From 0d72a5f3204618bc7093ea6b68c5ed20921ec9ec Mon Sep 17 00:00:00 2001 From: Stephane Glondu Date: Wed, 10 Jul 2019 14:50:44 +0200 Subject: [PATCH] New upstream version 4.08.0 --- .depend | 7577 ++- .depend.menhir | 11 + .gitattributes | 144 +- .gitignore | 193 +- .mailmap | 34 +- .merlin | 56 - .travis.yml | 6 +- BOOTSTRAP.adoc | 58 + CONTRIBUTING.md | 3 + Changes | 4967 +- HACKING.adoc | 24 +- INSTALL.adoc | 252 +- Makefile | 527 +- Makefile.common | 30 - Makefile.common.in | 53 + Makefile.config.in | 290 + Makefile.menhir | 163 + Makefile.nt | 16 - Makefile.tools | 13 +- News | 180 + README.adoc | 24 +- README.win32.adoc | 37 +- VERSION | 2 +- aclocal.m4 | 267 + appveyor.yml | 6 + asmcomp/CSEgen.ml | 2 +- asmcomp/CSEgen.mli | 2 +- asmcomp/afl_instrument.ml | 32 +- asmcomp/amd64/CSE.ml | 2 +- asmcomp/amd64/arch.ml | 4 + asmcomp/amd64/emit.mlp | 90 +- asmcomp/amd64/proc.ml | 20 +- asmcomp/amd64/selection.ml | 7 + asmcomp/arm/emit.mlp | 56 +- asmcomp/arm/proc.ml | 43 +- asmcomp/arm/reload.ml | 6 +- asmcomp/arm64/arch.ml | 6 +- asmcomp/arm64/emit.mlp | 70 +- asmcomp/arm64/proc.ml | 32 +- asmcomp/asmgen.ml | 139 +- asmcomp/asmgen.mli | 6 +- asmcomp/asmlibrarian.ml | 42 +- asmcomp/asmlink.ml | 67 +- asmcomp/asmlink.mli | 4 +- asmcomp/asmpackager.ml | 31 +- asmcomp/asmpackager.mli | 2 +- asmcomp/backend_var.ml | 87 + asmcomp/backend_var.mli | 54 + asmcomp/branch_relaxation.ml | 4 +- asmcomp/branch_relaxation_intf.ml | 2 +- asmcomp/build_export_info.ml | 12 +- asmcomp/clambda.ml | 50 +- asmcomp/clambda.mli | 55 +- asmcomp/closure.ml | 188 +- asmcomp/cmm.ml | 27 +- asmcomp/cmm.mli | 50 +- asmcomp/cmmgen.ml | 412 +- asmcomp/cmmgen.mli | 7 +- asmcomp/comballoc.ml | 53 +- asmcomp/compilenv.ml | 24 +- asmcomp/compilenv.mli | 2 +- asmcomp/debug/available_regs.ml | 4 +- asmcomp/debug/reg_availability_set.ml | 15 +- asmcomp/debug/reg_with_debug_info.ml | 14 +- asmcomp/debug/reg_with_debug_info.mli | 4 +- asmcomp/dune | 44 + asmcomp/emitaux.ml | 2 +- asmcomp/export_info.ml | 4 +- asmcomp/flambda_to_clambda.ml | 55 +- asmcomp/i386/emit.mlp | 88 +- asmcomp/i386/proc.ml | 18 + asmcomp/linearize.ml | 16 +- asmcomp/linearize.mli | 3 +- asmcomp/linscan.ml | 3 +- asmcomp/liveness.ml | 6 +- asmcomp/liveness.mli | 4 +- asmcomp/mach.ml | 4 +- asmcomp/mach.mli | 4 +- asmcomp/power/arch.ml | 6 +- asmcomp/power/emit.mlp | 105 +- asmcomp/power/proc.ml | 44 +- asmcomp/printclambda.ml | 92 +- asmcomp/printclambda.mli | 5 + asmcomp/printcmm.ml | 62 +- asmcomp/printlinear.ml | 2 + asmcomp/printmach.ml | 8 +- asmcomp/proc.mli | 10 + asmcomp/reg.ml | 12 +- asmcomp/reg.mli | 2 +- asmcomp/s390x/emit.mlp | 13 +- asmcomp/s390x/proc.ml | 28 +- asmcomp/selectgen.ml | 101 +- asmcomp/selectgen.mli | 10 +- asmcomp/spacetime_profiling.ml | 112 +- asmcomp/split.ml | 3 +- asmcomp/strmatch.ml | 13 +- asmcomp/un_anf.ml | 416 +- asmcomp/un_anf.mli | 3 +- asmcomp/x86_gas.ml | 4 +- asmcomp/x86_proc.ml | 6 +- asmrun/.depend | 1460 - asmrun/Makefile | 203 - asmrun/Makefile.nt | 16 - asmrun/amd64.S | 741 - asmrun/amd64nt.asm | 536 - asmrun/arm64.S | 571 - asmrun/backtrace_prim.c | 249 - asmrun/clambda_checks.c | 88 - asmrun/fail.c | 198 - asmrun/roots.c | 521 - asmrun/signals_asm.c | 288 - asmrun/spacetime.c | 1161 - asmrun/startup.c | 187 - autogen | 2 + boot/menhir/menhirLib.ml | 3517 ++ boot/menhir/menhirLib.mli | 1705 + boot/menhir/parser.ml | 45873 ++++++++++++++++ boot/menhir/parser.mli | 174 + boot/ocamlc | Bin 2291338 -> 2623328 bytes boot/ocamllex | Bin 305599 -> 323034 bytes build-aux/ax_func_which_gethostbyname_r.m4 | 308 + build-aux/ax_pthread.m4 | 485 + build-aux/compile | 347 + build-aux/config.guess | 1480 + build-aux/config.sub | 1801 + build-aux/install-sh | 508 + build-aux/libtool.m4 | 8387 +++ build-aux/ltmain.sh | 11346 ++++ build-aux/ltoptions.m4 | 437 + build-aux/ltsugar.m4 | 124 + build-aux/ltversion.m4 | 23 + build-aux/lt~obsolete.m4 | 99 + build-aux/missing | 215 + bytecomp/bytegen.ml | 27 +- bytecomp/bytegen.mli | 3 +- bytecomp/bytelibrarian.ml | 55 +- bytecomp/bytelibrarian.mli | 2 +- bytecomp/bytelink.ml | 449 +- bytecomp/bytelink.mli | 5 +- bytecomp/bytepackager.ml | 49 +- bytecomp/bytepackager.mli | 3 +- bytecomp/cmo_format.mli | 6 - bytecomp/dll.ml | 29 +- bytecomp/dune | 28 + bytecomp/emitcode.ml | 33 +- bytecomp/emitcode.mli | 9 +- bytecomp/generate_runtimedef.sh | 25 + bytecomp/instruct.ml | 2 +- bytecomp/instruct.mli | 2 +- bytecomp/lambda.ml | 443 +- bytecomp/lambda.mli | 88 +- bytecomp/matching.ml | 252 +- bytecomp/meta.ml | 18 +- bytecomp/meta.mli | 18 +- bytecomp/printlambda.ml | 58 +- bytecomp/printlambda.mli | 3 +- bytecomp/simplif.ml | 205 +- bytecomp/simplif.mli | 10 +- bytecomp/switch.ml | 1206 +- bytecomp/symtable.ml | 202 +- bytecomp/symtable.mli | 8 +- bytecomp/translattribute.ml | 182 +- bytecomp/translattribute.mli | 20 +- bytecomp/translclass.ml | 202 +- bytecomp/translcore.ml | 438 +- bytecomp/translcore.mli | 2 + bytecomp/translmod.ml | 660 +- bytecomp/translmod.mli | 12 +- bytecomp/translobj.ml | 61 +- bytecomp/translprim.ml | 564 +- bytecomp/translprim.mli | 2 + byterun/.depend | 803 - byterun/Makefile | 234 - byterun/Makefile.nt | 16 - byterun/alloc.c | 247 - byterun/array.c | 586 - byterun/backtrace.c | 349 - byterun/backtrace_prim.c | 457 - byterun/bigarray.c | 1223 - byterun/caml/backtrace.h | 136 - byterun/caml/backtrace_prim.h | 91 - byterun/caml/compatibility.h | 375 - byterun/caml/config.h | 208 - byterun/caml/custom.h | 73 - byterun/caml/exec.h | 65 - byterun/caml/finalise.h | 36 - byterun/caml/gc.h | 79 - byterun/caml/gc_ctrl.h | 58 - byterun/caml/instrtrace.h | 35 - byterun/caml/intext.h | 207 - byterun/caml/memory.h | 595 - byterun/caml/minor_gc.h | 120 - byterun/caml/misc.h | 525 - byterun/caml/osdeps.h | 152 - byterun/caml/signals.h | 59 - byterun/caml/stack.h | 124 - byterun/caml/startup.h | 52 - byterun/caml/startup_aux.h | 44 - byterun/caml/sys.h | 45 - byterun/caml/weak.h | 93 - byterun/compact.c | 562 - byterun/compare.c | 363 - byterun/custom.c | 124 - byterun/debugger.c | 454 - byterun/dynlink.c | 300 - byterun/extern.c | 925 - byterun/fail.c | 204 - byterun/fix_code.c | 195 - byterun/floats.c | 720 - byterun/freelist.c | 621 - byterun/gc_ctrl.c | 691 - byterun/instrtrace.c | 269 - byterun/intern.c | 1048 - byterun/interp.c | 1172 - byterun/ints.c | 830 - byterun/io.c | 828 - byterun/major_gc.c | 936 - byterun/memory.c | 1016 - byterun/meta.c | 234 - byterun/minor_gc.c | 558 - byterun/misc.c | 276 - byterun/printexc.c | 155 - byterun/roots.c | 120 - byterun/signals.c | 398 - byterun/startup.c | 531 - byterun/startup_aux.c | 168 - byterun/str.c | 474 - byterun/sys.c | 718 - byterun/unix.c | 447 - byterun/weak.c | 427 - byterun/win32.c | 1019 - config/Makefile-templ | 202 - config/Makefile.mingw | 32 +- config/Makefile.mingw64 | 32 +- config/Makefile.msvc | 32 +- config/Makefile.msvc64 | 34 +- config/auto-aux/simple.S | 3 + config/m-nt.h | 7 - config/m-templ.h | 83 - config/s-nt.h | 5 +- config/s-templ.h | 214 - configure | 21055 ++++++- configure.ac | 1813 + debugger/.depend | 790 +- debugger/Makefile | 128 +- debugger/Makefile.nt | 16 - debugger/breakpoints.ml | 2 +- debugger/command_line.ml | 13 +- debugger/dune | 25 + debugger/eval.ml | 26 +- debugger/input_handling.ml | 2 +- debugger/loadprinter.ml | 39 +- debugger/main.ml | 6 +- debugger/parameters.ml | 4 +- debugger/printval.ml | 13 +- debugger/program_management.ml | 6 +- debugger/source.ml | 2 +- debugger/symbols.ml | 9 +- debugger/time_travel.ml | 10 +- debugger/unix_tools.ml | 3 +- driver/compdynlink.mlno | 57 - driver/compenv.ml | 99 +- driver/compenv.mli | 11 +- driver/compify_dynlink.sh | 3 + driver/compile.ml | 138 +- driver/compile.mli | 22 +- driver/compile_common.ml | 129 + driver/compile_common.mli | 92 + driver/compmisc.ml | 38 +- driver/compmisc.mli | 6 +- driver/compplugin.ml | 5 +- driver/dune | 55 + driver/main.ml | 84 +- driver/main_args.ml | 95 +- driver/main_args.mli | 11 +- driver/makedepend.ml | 103 +- driver/optcompile.ml | 182 +- driver/optcompile.mli | 28 +- driver/optmain.ml | 63 +- driver/pparse.ml | 106 +- driver/pparse.mli | 13 +- dune | 177 + dune-project | 2 + emacs/COPYING | 340 - emacs/Makefile | 85 - emacs/README | 209 - emacs/README.itz | 177 - emacs/caml-compat.el | 41 - emacs/caml-emacs.el | 45 - emacs/caml-font-old.el | 141 - emacs/caml-font.el | 440 - emacs/caml-help.el | 857 - emacs/caml-hilit.el | 67 - emacs/caml-types.el | 762 - emacs/caml-xemacs.el | 57 - emacs/caml.el | 1986 - emacs/camldebug.el | 795 - emacs/inf-caml.el | 364 - emacs/ocamltags.in | 141 - lex/.depend | 148 +- lex/Makefile | 40 +- lex/Makefile.nt | 16 - lex/common.ml | 2 +- lex/lexer.mll | 103 +- lex/lexgen.ml | 10 +- lex/main.ml | 3 +- lex/output.ml | 14 +- lex/outputbis.ml | 18 +- man/Makefile | 3 +- man/ocaml.m | 43 + man/ocamlc.m | 58 +- man/ocamldep.m | 8 +- man/ocamldoc.m | 7 +- man/ocamlopt.m | 39 +- man/ocamlrun.m | 37 + manual/Makefile | 48 +- manual/README.md | 27 +- manual/manual/Makefile | 237 +- manual/manual/allfiles.etex | 4 +- manual/manual/biblio.etex | 34 +- manual/manual/cmds/Makefile | 74 +- manual/manual/cmds/afl-fuzz.etex | 1 - manual/manual/cmds/browser.etex | 1 - manual/manual/cmds/comp.etex | 10 +- manual/manual/cmds/debugger.etex | 1 - manual/manual/cmds/depend.etex | 1 - manual/manual/cmds/flambda.etex | 7 +- manual/manual/cmds/intf-c.etex | 67 +- manual/manual/cmds/lexyacc.etex | 7 +- manual/manual/cmds/native.etex | 1 - manual/manual/cmds/ocamlbuild.etex | 1 - manual/manual/cmds/ocamldoc.etex | 7 +- manual/manual/cmds/plugins.etex | 1 - manual/manual/cmds/profil.etex | 1 - manual/manual/cmds/runtime.etex | 28 +- manual/manual/cmds/spacetime.etex | 1 - manual/manual/cmds/top.etex | 8 +- manual/manual/cmds/unified-options.etex | 70 +- manual/manual/htmlman/.gitignore | 2 + manual/manual/library/.cvsignore | 5 - manual/manual/library/.gitignore | 2 + manual/manual/library/Makefile | 119 +- manual/manual/library/builtin.etex | 18 +- manual/manual/library/compiler_libs.mld | 9 + manual/manual/library/compilerlibs.etex | 30 +- manual/manual/library/core.etex | 8 +- manual/manual/library/libbigarray.etex | 1 - manual/manual/library/libdynlink.etex | 1 - manual/manual/library/libgraph.etex | 1 - manual/manual/library/libnum.etex | 1 - manual/manual/library/libstr.etex | 1 - manual/manual/library/libthreads.etex | 6 +- manual/manual/library/libunix.etex | 2 - manual/manual/library/stdlib.etex | 26 +- manual/manual/macros.hva | 15 +- manual/manual/macros.tex | 48 +- manual/manual/manual.tex | 12 +- manual/manual/pdfmanual.tex | 31 - manual/manual/plaintext.tex | 17 - manual/manual/refman/.cvsignore | 2 - manual/manual/refman/Makefile | 58 +- manual/manual/refman/classes.etex | 3 +- manual/manual/refman/compunit.etex | 1 - manual/manual/refman/const.etex | 15 +- manual/manual/refman/expr.etex | 53 +- manual/manual/refman/exten.etex | 1484 +- manual/manual/refman/lex.etex | 33 +- manual/manual/refman/modtypes.etex | 1 - manual/manual/refman/modules.etex | 26 +- manual/manual/refman/names.etex | 1 - manual/manual/refman/patterns.etex | 59 +- manual/manual/refman/refman.etex | 1 - manual/manual/refman/typedecl.etex | 1 - manual/manual/refman/types.etex | 1 - manual/manual/refman/values.etex | 1 - manual/manual/style.css | 12 +- manual/manual/texstuff/.cvsignore | 13 - manual/manual/texstuff/.gitignore | 2 +- manual/manual/textman/.cvsignore | 5 - manual/manual/tutorials/.cvsignore | 2 - manual/manual/tutorials/Makefile | 45 +- manual/manual/tutorials/advexamples.etex | 6 +- manual/manual/tutorials/coreexamples.etex | 243 +- manual/manual/tutorials/lablexamples.etex | 8 +- manual/manual/tutorials/moduleexamples.etex | 6 - manual/manual/tutorials/objectexamples.etex | 33 +- manual/manual/tutorials/polymorphism.etex | 3 +- manual/styles/ocamldoc.hva | 2 - manual/styles/plaintext.sty | 268 - manual/tests/.gitignore | 1 + manual/tests/Makefile | 26 +- manual/tests/cross_reference_checker.ml | 26 +- manual/tools/.gitignore | 1 - manual/tools/.ignore | 11 - manual/tools/Makefile | 52 +- manual/tools/caml-tex | 131 - manual/tools/caml_tex2.ml | 605 - manual/tools/dvi_to_txt/Makefile | 8 - manual/tools/dvi_to_txt/dvi.h | 8 - manual/tools/dvi_to_txt/interp.c | 305 - manual/tools/dvi_to_txt/io.c | 43 - manual/tools/dvi_to_txt/io.h | 10 - manual/tools/dvi_to_txt/main.c | 47 - manual/tools/dvi_to_txt/output.c | 209 - manual/tools/dvi_to_txt/output.h | 24 - manual/tools/dvi_to_txt/print.c | 41 - manual/tools/dvi_to_txt/print_rtf.c | 80 - manual/tools/dvi_to_txt/print_styl.c | 90 - manual/tools/fix_index.sh | 13 +- manual/tools/format-intf | 153 - manual/tools/htmlcut | 111 - manual/tools/htmlquote.c | 87 - manual/tools/htmltbl | 134 - manual/tools/htmlthread | 58 - manual/tools/latexmacros.ml | 149 - manual/tools/latexmacros.mli | 8 - manual/tools/latexmain.ml | 4 - manual/tools/latexscan.mll | 166 - manual/tools/texexpand | 40 - manual/tools/texquote2.c | 167 - manual/tools/texquote2.ml | 137 + middle_end/alias_analysis.ml | 3 +- middle_end/allocated_const.ml | 13 +- middle_end/augment_specialised_args.ml | 6 +- middle_end/base_types/closure_element.ml | 3 +- middle_end/base_types/closure_id.ml | 3 +- middle_end/base_types/closure_origin.ml | 3 +- middle_end/base_types/compilation_unit.ml | 3 +- middle_end/base_types/export_id.ml | 3 +- middle_end/base_types/id_types.ml | 5 +- middle_end/base_types/linkage_name.ml | 3 +- middle_end/base_types/mutable_variable.ml | 3 +- middle_end/base_types/set_of_closures_id.ml | 3 +- .../base_types/set_of_closures_origin.ml | 3 +- middle_end/base_types/static_exception.ml | 3 +- middle_end/base_types/symbol.ml | 3 +- middle_end/base_types/tag.ml | 5 +- middle_end/base_types/tag.mli | 2 + middle_end/base_types/var_within_closure.ml | 3 +- middle_end/base_types/variable.ml | 7 +- middle_end/closure_conversion.ml | 24 +- middle_end/closure_conversion_aux.ml | 9 +- middle_end/debuginfo.ml | 34 +- middle_end/debuginfo.mli | 5 +- middle_end/effect_analysis.ml | 3 +- middle_end/extract_projections.ml | 3 +- middle_end/find_recursive_functions.ml | 7 +- middle_end/flambda.ml | 19 +- middle_end/flambda.mli | 10 + middle_end/flambda_invariants.ml | 5 +- middle_end/flambda_iterators.ml | 3 +- middle_end/flambda_utils.ml | 53 +- middle_end/flambda_utils.mli | 6 +- middle_end/freshening.ml | 7 +- middle_end/freshening.mli | 2 + middle_end/inconstant_idents.ml | 3 +- middle_end/initialize_symbol_to_let_symbol.ml | 3 +- middle_end/inline_and_simplify.ml | 18 +- middle_end/inline_and_simplify.mli | 1 + middle_end/inline_and_simplify_aux.ml | 8 +- middle_end/inline_and_simplify_aux.mli | 4 + middle_end/inlining_cost.ml | 32 +- middle_end/inlining_cost.mli | 1 + middle_end/inlining_decision.ml | 37 +- middle_end/inlining_stats.ml | 3 +- middle_end/inlining_stats_types.ml | 3 +- middle_end/inlining_transforms.ml | 20 +- middle_end/int_replace_polymorphic_compare.ml | 8 + .../int_replace_polymorphic_compare.mli | 8 + middle_end/internal_variable_names.ml | 19 +- middle_end/invariant_params.ml | 3 +- middle_end/lift_code.ml | 3 +- middle_end/lift_constants.ml | 5 +- middle_end/lift_let_to_initialize_symbol.ml | 3 +- middle_end/middle_end.ml | 39 +- middle_end/middle_end.mli | 2 +- middle_end/parameter.ml | 3 +- middle_end/pass_wrapper.ml | 11 +- middle_end/pass_wrapper.mli | 3 +- middle_end/projection.ml | 3 +- middle_end/ref_to_variables.ml | 6 +- middle_end/remove_free_vars_equal_to_args.ml | 7 +- middle_end/remove_free_vars_equal_to_args.mli | 5 +- middle_end/remove_unused_arguments.ml | 3 +- middle_end/remove_unused_closure_vars.ml | 3 +- .../remove_unused_program_constructs.ml | 11 +- middle_end/share_constants.ml | 3 +- middle_end/simple_value_approx.ml | 10 +- middle_end/simple_value_approx.mli | 4 +- middle_end/simplify_boxed_integer_ops.ml | 42 +- middle_end/simplify_common.ml | 9 +- middle_end/simplify_common.mli | 4 +- middle_end/simplify_primitives.ml | 46 +- middle_end/unbox_closures.ml | 3 +- middle_end/unbox_free_vars_of_closures.ml | 6 +- middle_end/unbox_specialised_args.ml | 3 +- ocaml-variants.opam | 29 + ocamldoc/.depend | 1087 +- ocamldoc/Changes.txt | 6 +- ocamldoc/Makefile | 160 +- ocamldoc/Makefile.docfiles | 72 + ocamldoc/Makefile.nt | 16 - ocamldoc/Makefile.unprefix | 102 - ocamldoc/dune | 25 + ocamldoc/odoc_analyse.ml | 45 +- ocamldoc/odoc_args.ml | 8 +- ocamldoc/odoc_ast.ml | 22 +- ocamldoc/odoc_comments.ml | 4 +- ocamldoc/odoc_cross.ml | 18 +- ocamldoc/odoc_dep.ml | 54 +- ocamldoc/odoc_env.ml | 14 +- ocamldoc/odoc_global.ml | 2 + ocamldoc/odoc_global.mli | 3 + ocamldoc/odoc_html.ml | 53 +- ocamldoc/odoc_info.mli | 4 + ocamldoc/odoc_latex.ml | 8 +- ocamldoc/odoc_man.ml | 7 +- ocamldoc/odoc_merge.ml | 2 +- ocamldoc/odoc_messages.ml | 17 +- ocamldoc/odoc_misc.ml | 12 +- ocamldoc/odoc_module.ml | 17 +- ocamldoc/odoc_name.ml | 26 +- ocamldoc/odoc_name.mli | 9 + ocamldoc/odoc_print.ml | 7 +- ocamldoc/odoc_sig.ml | 180 +- ocamldoc/odoc_str.ml | 1 + ocamldoc/odoc_text_parser.mly | 6 +- ocamldoc/stdlib_non_prefixed/.depend | 185 - ocamldoc/stdlib_non_prefixed/Makefile | 25 - .../extract_pervasives.awk | 23 - ocamltest/.depend | 545 +- ocamltest/Makefile | 101 +- ocamltest/README | 8 +- ocamltest/actions.ml | 2 +- ocamltest/actions_helpers.ml | 59 +- ocamltest/actions_helpers.mli | 2 + ocamltest/builtin_actions.ml | 45 +- ocamltest/builtin_actions.mli | 1 + ocamltest/builtin_variables.ml | 62 +- ocamltest/builtin_variables.mli | 4 + ocamltest/dune | 52 + ocamltest/environments.ml | 41 +- ocamltest/filecompare.ml | 10 +- ocamltest/filecompare.mli | 2 +- ocamltest/main.ml | 22 +- ocamltest/ocaml_actions.ml | 519 +- ocamltest/ocaml_actions.mli | 5 + ocamltest/ocaml_commands.ml | 6 + ocamltest/ocaml_commands.mli | 3 + ocamltest/ocaml_directories.ml | 8 +- ocamltest/ocaml_directories.mli | 2 - ocamltest/ocaml_files.ml | 14 +- ocamltest/ocaml_files.mli | 4 + ocamltest/ocaml_filetypes.ml | 7 +- ocamltest/ocaml_filetypes.mli | 1 + ocamltest/ocaml_flags.ml | 11 +- ocamltest/ocaml_flags.mli | 3 +- ocamltest/ocaml_modifiers.ml | 4 + ocamltest/ocaml_tests.ml | 30 + ocamltest/ocaml_tests.mli | 2 + ocamltest/ocaml_variables.ml | 76 +- ocamltest/ocaml_variables.mli | 34 +- ocamltest/ocamltest_config.ml.in | 35 +- ocamltest/ocamltest_config.mli | 50 +- ocamltest/ocamltest_stdlib.ml | 9 +- ocamltest/ocamltest_stdlib.mli | 9 +- ocamltest/ocamltest_stdlib_stubs.c | 7 +- ocamltest/options.ml | 10 + ocamltest/run_unix.c | 16 +- ocamltest/run_win32.c | 58 +- ocamltest/tsl_ast.ml | 2 +- ocamltest/tsl_ast.mli | 2 +- ocamltest/tsl_lexer.mli | 2 + ocamltest/tsl_lexer.mll | 44 +- ocamltest/variables.ml | 4 + ocamltest/variables.mli | 2 + otherlibs/Makefile | 129 +- otherlibs/Makefile.otherlibs.common | 141 + otherlibs/bigarray/.depend | 6 +- otherlibs/bigarray/Makefile | 16 +- otherlibs/bigarray/Makefile.nt | 16 - otherlibs/bigarray/bigarray.ml | 38 +- otherlibs/bigarray/bigarray.mli | 45 - .../bigarray/empty.c | 0 otherlibs/dynlink/Makefile | 176 +- otherlibs/dynlink/Makefile.nt | 18 - otherlibs/dynlink/dune | 27 + otherlibs/dynlink/dynlink.ml | 462 +- otherlibs/dynlink/dynlink.mli | 159 +- otherlibs/dynlink/dynlink_common.ml | 360 + otherlibs/dynlink/dynlink_common.mli | 34 + otherlibs/dynlink/dynlink_platform_intf.ml | 67 + otherlibs/dynlink/dynlink_types.ml | 116 + otherlibs/dynlink/dynlink_types.mli | 49 + otherlibs/dynlink/extract_crc.ml | 39 +- otherlibs/dynlink/natdynlink.ml | 306 +- otherlibs/dynlink/nodynlink.ml | 79 + otherlibs/graph/.depend | 14 +- otherlibs/graph/Makefile | 6 +- otherlibs/graph/events.c | 2 +- otherlibs/graph/graphics.mli | 7 +- otherlibs/graph/image.c | 3 +- otherlibs/graph/open.c | 4 +- otherlibs/raw_spacetime_lib/.depend | 28 +- otherlibs/raw_spacetime_lib/Makefile | 6 +- otherlibs/raw_spacetime_lib/Makefile.nt | 16 - .../raw_spacetime_lib/spacetime_offline.c | 1 - otherlibs/str/.depend | 16 +- otherlibs/str/Makefile | 6 +- otherlibs/str/Makefile.nt | 16 - otherlibs/str/dune | 20 + otherlibs/str/str.mli | 2 +- otherlibs/systhreads/.depend | 89 +- otherlibs/systhreads/Makefile | 42 +- otherlibs/systhreads/Makefile.nt | 16 - otherlibs/systhreads/st_posix.h | 10 +- otherlibs/systhreads/st_stubs.c | 34 +- otherlibs/systhreads/st_win32.h | 7 +- otherlibs/threads/.depend | 103 +- otherlibs/threads/Makefile | 88 +- otherlibs/threads/scheduler.c | 2 +- otherlibs/threads/stdlib.ml | 30 +- otherlibs/threads/unix.ml | 123 +- otherlibs/unix/.depend | 892 +- otherlibs/unix/Makefile | 12 +- otherlibs/unix/access.c | 2 +- otherlibs/unix/channels.c | 89 + otherlibs/unix/cstringv.c | 3 +- otherlibs/unix/dune | 33 + otherlibs/unix/execvp.c | 1 - otherlibs/unix/fsync.c | 40 + otherlibs/unix/getaddrinfo.c | 2 +- otherlibs/unix/getgr.c | 3 +- otherlibs/unix/gethost.c | 3 +- otherlibs/unix/getnameinfo.c | 3 +- otherlibs/unix/link.c | 26 +- otherlibs/unix/mmap_ba.c | 5 +- otherlibs/unix/signals.c | 8 +- otherlibs/unix/socketaddr.c | 3 +- otherlibs/unix/times.c | 16 +- otherlibs/unix/unix.ml | 109 +- otherlibs/unix/unix.mli | 117 +- otherlibs/unix/unixLabels.mli | 80 +- otherlibs/win32graph/Makefile | 2 +- otherlibs/win32graph/Makefile.nt | 16 - otherlibs/win32graph/draw.c | 3 +- otherlibs/win32graph/open.c | 4 +- otherlibs/win32unix/.depend | 39 +- otherlibs/win32unix/Makefile | 8 +- otherlibs/win32unix/Makefile.nt | 16 - otherlibs/win32unix/channels.c | 42 + otherlibs/win32unix/createprocess.c | 17 +- otherlibs/win32unix/errmsg.c | 3 +- otherlibs/win32unix/link.c | 7 +- otherlibs/win32unix/lockf.c | 2 +- otherlibs/win32unix/mmap.c | 3 +- otherlibs/win32unix/readlink.c | 8 +- otherlibs/win32unix/select.c | 2 +- otherlibs/win32unix/unix.ml | 96 +- otherlibs/win32unix/unixsupport.c | 9 +- otherlibs/win32unix/utimes.c | 9 +- otherlibs/win32unix/winworker.c | 4 +- parsing/CONFLICTS.md | 54 + parsing/HACKING.adoc | 67 + parsing/VIPs.md | 20 + parsing/ast_helper.ml | 127 +- parsing/ast_helper.mli | 68 +- parsing/ast_invariants.ml | 32 +- parsing/ast_invariants.mli | 7 +- parsing/ast_iterator.ml | 115 +- parsing/ast_iterator.mli | 13 +- parsing/ast_mapper.ml | 232 +- parsing/ast_mapper.mli | 9 +- parsing/asttypes.mli | 7 +- parsing/attr_helper.ml | 10 +- parsing/attr_helper.mli | 7 +- parsing/builtin_attributes.ml | 241 +- parsing/builtin_attributes.mli | 41 +- parsing/depend.ml | 174 +- parsing/depend.mli | 20 +- parsing/docstrings.ml | 75 +- parsing/docstrings.mli | 65 +- parsing/dune | 48 + parsing/lexer.mli | 15 +- parsing/lexer.mll | 319 +- parsing/location.ml | 1052 +- parsing/location.mli | 233 +- parsing/longident.mli | 10 +- parsing/parse.ml | 144 +- parsing/parse.mli | 7 +- parsing/parser.mly | 4124 +- parsing/parsetree.mli | 129 +- parsing/pprintast.ml | 173 +- parsing/pprintast.mli | 24 +- parsing/printast.ml | 127 +- parsing/printast.mli | 7 + parsing/syntaxerr.ml | 44 - parsing/syntaxerr.mli | 10 +- runtime/.depend | 2178 + runtime/Makefile | 418 + {byterun => runtime}/afl.c | 0 runtime/alloc.c | 247 + runtime/amd64.S | 741 + runtime/amd64nt.asm | 536 + {asmrun => runtime}/arm.S | 0 runtime/arm64.S | 579 + runtime/array.c | 591 + runtime/backtrace.c | 349 + runtime/backtrace_byt.c | 454 + runtime/backtrace_nat.c | 235 + runtime/bigarray.c | 1229 + {byterun => runtime}/callback.c | 0 {byterun => runtime}/caml/address_class.h | 0 {byterun => runtime}/caml/alloc.h | 0 runtime/caml/backtrace.h | 137 + runtime/caml/backtrace_prim.h | 100 + {byterun => runtime}/caml/bigarray.h | 0 {byterun => runtime}/caml/callback.h | 0 {byterun => runtime}/caml/compact.h | 0 {byterun => runtime}/caml/compare.h | 0 runtime/caml/compatibility.h | 375 + runtime/caml/config.h | 258 + runtime/caml/custom.h | 84 + {byterun => runtime}/caml/debugger.h | 0 runtime/caml/dune | 29 + {byterun => runtime}/caml/dynlink.h | 0 runtime/caml/exec.h | 67 + {byterun => runtime}/caml/fail.h | 0 runtime/caml/finalise.h | 36 + {byterun => runtime}/caml/fix_code.h | 0 {byterun => runtime}/caml/freelist.h | 0 runtime/caml/gc.h | 79 + runtime/caml/gc_ctrl.h | 62 + {byterun => runtime}/caml/globroots.h | 0 {byterun => runtime}/caml/hash.h | 0 {byterun => runtime}/caml/hooks.h | 0 runtime/caml/instrtrace.h | 35 + {byterun => runtime}/caml/instruct.h | 0 {byterun => runtime}/caml/int64_emul.h | 0 {byterun => runtime}/caml/int64_format.h | 0 {byterun => runtime}/caml/int64_native.h | 0 {byterun => runtime}/caml/interp.h | 0 runtime/caml/intext.h | 213 + {byterun => runtime}/caml/io.h | 0 runtime/caml/m.h.in | 104 + {byterun => runtime}/caml/major_gc.h | 0 {byterun => runtime}/caml/md5.h | 0 runtime/caml/memory.h | 596 + runtime/caml/minor_gc.h | 120 + runtime/caml/misc.h | 437 + {byterun => runtime}/caml/mlvalues.h | 0 runtime/caml/osdeps.h | 160 + {byterun => runtime}/caml/prims.h | 0 {byterun => runtime}/caml/printexc.h | 0 {byterun => runtime}/caml/reverse.h | 0 {byterun => runtime}/caml/roots.h | 0 runtime/caml/s.h.in | 279 + runtime/caml/signals.h | 66 + {byterun => runtime}/caml/signals_machdep.h | 0 {byterun => runtime}/caml/spacetime.h | 0 runtime/caml/stack.h | 124 + {byterun => runtime}/caml/stacks.h | 0 runtime/caml/startup.h | 52 + runtime/caml/startup_aux.h | 50 + runtime/caml/sys.h | 55 + {byterun => runtime}/caml/ui.h | 0 runtime/caml/weak.h | 216 + runtime/clambda_checks.c | 88 + runtime/compact.c | 564 + runtime/compare.c | 373 + runtime/custom.c | 162 + runtime/debugger.c | 462 + runtime/dune | 58 + runtime/dynlink.c | 304 + asmrun/natdynlink.c => runtime/dynlink_nat.c | 0 runtime/extern.c | 947 + runtime/fail_byt.c | 204 + runtime/fail_nat.c | 192 + {byterun => runtime}/finalise.c | 0 runtime/fix_code.c | 195 + runtime/floats.c | 1094 + runtime/freelist.c | 623 + runtime/gc_ctrl.c | 739 + runtime/gen_primitives.sh | 30 + {byterun => runtime}/globroots.c | 0 {byterun => runtime}/hash.c | 0 {asmrun => runtime}/i386.S | 0 {asmrun => runtime}/i386nt.asm | 0 runtime/instrtrace.c | 269 + runtime/intern.c | 1086 + runtime/interp.c | 1172 + runtime/ints.c | 847 + runtime/io.c | 835 + {byterun => runtime}/lexing.c | 0 {byterun => runtime}/main.c | 0 runtime/major_gc.c | 948 + {byterun => runtime}/md5.c | 0 runtime/memory.c | 1010 + runtime/meta.c | 297 + runtime/minor_gc.c | 558 + runtime/misc.c | 283 + {byterun => runtime}/obj.c | 0 {byterun => runtime}/parsing.c | 0 {asmrun => runtime}/power.S | 0 runtime/printexc.c | 154 + runtime/roots_byt.c | 120 + runtime/roots_nat.c | 506 + {asmrun => runtime}/s390x.S | 0 runtime/signals.c | 450 + {byterun => runtime}/signals_byt.c | 0 runtime/signals_nat.c | 288 + {asmrun => runtime}/signals_osdep.h | 0 .../spacetime.c => runtime/spacetime_byt.c | 0 runtime/spacetime_nat.c | 1161 + {asmrun => runtime}/spacetime_snapshot.c | 0 {byterun => runtime}/stacks.c | 0 runtime/startup_aux.c | 176 + runtime/startup_byt.c | 563 + runtime/startup_nat.c | 190 + runtime/str.c | 474 + runtime/sys.c | 644 + runtime/unix.c | 442 + runtime/weak.c | 574 + runtime/win32.c | 1037 + stdlib/.depend | 1488 +- stdlib/Compflags | 7 +- stdlib/HACKING.adoc | 37 + stdlib/Makefile | 80 +- stdlib/Makefile.nt | 16 - stdlib/StdlibModules | 8 +- stdlib/arg.ml | 24 +- stdlib/arg.mli | 8 +- stdlib/array.ml | 5 +- stdlib/array.mli | 45 +- stdlib/arrayLabels.mli | 11 +- stdlib/bigarray.mli | 248 +- stdlib/bool.ml | 33 + stdlib/bool.mli | 68 + stdlib/buffer.ml | 59 +- stdlib/buffer.mli | 105 +- stdlib/bytes.ml | 90 +- stdlib/bytes.mli | 206 +- stdlib/bytesLabels.mli | 203 +- stdlib/camlinternalFormat.ml | 303 +- stdlib/camlinternalFormat.mli | 4 +- stdlib/camlinternalFormatBasics.ml | 1 + stdlib/camlinternalFormatBasics.mli | 1 + stdlib/camlinternalLazy.ml | 2 + stdlib/camlinternalLazy.mli | 2 + stdlib/char.mli | 2 +- stdlib/digest.mli | 2 +- stdlib/dune | 36 + stdlib/ephemeron.ml | 12 + stdlib/ephemeron.mli | 2 +- stdlib/expand_module_aliases.awk | 10 +- stdlib/filename.ml | 32 +- stdlib/filename.mli | 25 +- stdlib/float.ml | 434 +- stdlib/float.mli | 405 +- stdlib/format.ml | 707 +- stdlib/format.mli | 329 +- stdlib/fun.ml | 34 + stdlib/fun.mli | 63 + stdlib/gc.ml | 3 + stdlib/gc.mli | 53 +- stdlib/hashtbl.ml | 20 +- stdlib/hashtbl.mli | 15 +- stdlib/headernt.c | 15 +- stdlib/int.ml | 50 + stdlib/int.mli | 144 + stdlib/int32.ml | 35 +- stdlib/int32.mli | 44 +- stdlib/int64.ml | 27 +- stdlib/int64.mli | 38 +- stdlib/lazy.ml | 2 +- stdlib/lazy.mli | 19 +- stdlib/lexing.ml | 36 +- stdlib/lexing.mli | 56 +- stdlib/list.ml | 18 +- stdlib/list.mli | 16 +- stdlib/listLabels.mli | 14 +- stdlib/map.ml | 6 +- stdlib/map.mli | 34 +- stdlib/marshal.ml | 2 +- stdlib/moreLabels.mli | 1 + stdlib/nativeint.ml | 27 +- stdlib/nativeint.mli | 38 +- stdlib/obj.ml | 87 +- stdlib/obj.mli | 19 +- stdlib/ocaml_operators.mld | 100 + stdlib/option.ml | 43 + stdlib/option.mli | 83 + stdlib/pervasives.ml | 244 + stdlib/printexc.ml | 8 +- stdlib/printexc.mli | 5 +- stdlib/printf.ml | 8 +- stdlib/printf.mli | 6 +- stdlib/queue.ml | 19 +- stdlib/queue.mli | 15 +- stdlib/random.ml | 12 +- stdlib/result.ml | 46 + stdlib/result.mli | 101 + stdlib/scanf.ml | 59 +- stdlib/scanf.mli | 26 +- stdlib/seq.mli | 15 +- stdlib/set.ml | 33 + stdlib/set.mli | 15 +- stdlib/sort.ml | 99 - stdlib/sort.mli | 44 - stdlib/stack.ml | 15 +- stdlib/stack.mli | 13 +- stdlib/stdlib.ml | 31 +- stdlib/stdlib.mli | 361 +- stdlib/string.ml | 16 +- stdlib/string.mli | 32 +- stdlib/stringLabels.mli | 4 +- stdlib/sys.mli | 13 +- stdlib/sys.mlp | 1 + stdlib/uchar.ml | 2 +- stdlib/uchar.mli | 2 +- stdlib/unit.ml | 20 + stdlib/unit.mli | 36 + stdlib/weak.ml | 38 +- stdlib/weak.mli | 13 +- testsuite/HACKING.adoc | 27 +- testsuite/Makefile | 64 +- testsuite/lib/lib.ml | 15 + testsuite/lib/testing.ml | 2 +- testsuite/lib/testing.mli | 2 +- testsuite/makefiles/Makefile.common | 12 +- testsuite/makefiles/Makefile.dlambda | 38 - testsuite/makefiles/Makefile.dparsetree | 33 - testsuite/makefiles/Makefile.expect | 41 - testsuite/makefiles/Makefile.okbad | 54 - testsuite/makefiles/Makefile.one | 2 +- testsuite/makefiles/Makefile.several | 154 - testsuite/makefiles/Makefile.toplevel | 37 - testsuite/makefiles/summarize.awk | 53 +- .../tests/afl-instrumentation/afltest.ml | 13 +- .../tests/afl-instrumentation/afltest.run | 4 +- .../tests/afl-instrumentation/harness.ml | 9 +- testsuite/tests/afl-instrumentation/test.ml | 9 +- testsuite/tests/asmcomp/is_static_flambda.ml | 4 +- testsuite/tests/asmcomp/register_typing.ml | 2 +- .../tests/asmcomp/register_typing_switch.ml | 2 +- testsuite/tests/asmcomp/staticalloc.ml | 5 +- testsuite/tests/asmgen/Makefile | 122 - testsuite/tests/asmgen/arith.cmm | 6 + testsuite/tests/asmgen/catch-float.cmm | 11 + testsuite/tests/asmgen/catch-rec.cmm | 8 +- testsuite/tests/asmgen/catch-try-float.cmm | 12 + testsuite/tests/asmgen/catch-try.cmm | 7 +- testsuite/tests/asmgen/checkbound.cmm | 6 + .../tests/asmgen/even-odd-spill-float.cmm | 27 + testsuite/tests/asmgen/even-odd-spill.cmm | 10 +- testsuite/tests/asmgen/even-odd.cmm | 12 +- testsuite/tests/asmgen/fib.cmm | 6 + testsuite/tests/asmgen/i386.S | 59 - testsuite/tests/asmgen/i386nt.asm | 65 - testsuite/tests/asmgen/integr.cmm | 8 + testsuite/tests/asmgen/lexcmm.mli | 10 - testsuite/tests/asmgen/lexcmm.mll | 245 - testsuite/tests/asmgen/main.c | 18 + testsuite/tests/asmgen/main.ml | 66 - testsuite/tests/asmgen/mainarith.c | 2 +- testsuite/tests/asmgen/ocamltests | 20 + testsuite/tests/asmgen/parsecmm.mly | 373 - testsuite/tests/asmgen/parsecmmaux.ml | 43 - testsuite/tests/asmgen/parsecmmaux.mli | 16 - testsuite/tests/asmgen/pgcd.cmm | 10 +- testsuite/tests/asmgen/quicksort.cmm | 6 + testsuite/tests/asmgen/quicksort2.cmm | 6 + testsuite/tests/asmgen/soli.cmm | 6 + testsuite/tests/asmgen/tagged-fib.cmm | 6 + testsuite/tests/asmgen/tagged-integr.cmm | 6 + testsuite/tests/asmgen/tagged-quicksort.cmm | 6 + testsuite/tests/asmgen/tagged-tak.cmm | 6 + testsuite/tests/asmgen/tak.cmm | 6 + testsuite/tests/ast-invariants/test.ml | 3 +- .../tests/backtrace/backtrace2.byte.reference | 10 +- .../tests/backtrace/backtrace2.opt.reference | 10 +- .../backtrace_or_exception.byte.reference | 14 + .../tests/backtrace/backtrace_or_exception.ml | 54 + .../backtrace_or_exception.opt.reference | 14 + testsuite/tests/backtrace/backtrace_slots.ml | 2 +- testsuite/tests/backtrace/callstack.ml | 19 + testsuite/tests/backtrace/callstack.reference | 12 + .../tests/backtrace/inline_traversal_test.ml | 2 +- testsuite/tests/backtrace/ocamltests | 2 + .../backtrace/pr6920_why_at.byte.reference | 2 +- .../pr6920_why_at.native.reference} | 0 .../backtrace/pr6920_why_at.opt.reference | 2 +- .../pr6920_why_swallow.byte.reference | 2 +- .../pr6920_why_swallow.native.reference} | 0 .../pr6920_why_swallow.opt.reference | 2 +- .../basic-float/zero_sized_float_arrays.ml | 8 +- .../recursive_module_evaluation_errors.ml | 105 +- .../basic-more/morematch.compilers.reference | 38 +- testsuite/tests/basic-more/morematch.ml | 2 +- .../robustmatch.compilers.reference | 89 + .../tests/basic-more/structural_constants.ml | 175 +- testsuite/tests/basic/boxedints.ml | 104 +- testsuite/tests/basic/boxedints.reference | 12 + testsuite/tests/basic/camlCase.ml | 1 + testsuite/tests/basic/constprop.ml | 124 - testsuite/tests/basic/constprop.ml.c | 130 + ...tprop.reference => constprop.ml.reference} | 0 testsuite/tests/basic/eval_order_4.ml | 6 +- testsuite/tests/basic/eval_order_6.ml | 5 +- testsuite/tests/basic/localfunction.ml | 32 + testsuite/tests/basic/localfunction.reference | 1 + testsuite/tests/basic/maps.ml | 12 +- testsuite/tests/basic/min_int.ml | 2 +- testsuite/tests/basic/ocamltests | 5 +- testsuite/tests/basic/opt_variants.ml | 18 + testsuite/tests/basic/patmatch_incoherence.ml | 138 + testsuite/tests/basic/pr7253.ml | 1 - testsuite/tests/basic/switch_opts.ml | 4 +- .../basic/unit_naming.compilers.reference | 4 + testsuite/tests/basic/unit_naming.ml | 9 + testsuite/tests/compiler-libs/ocamltests | 1 + .../tests/compiler-libs/test_longident.ml | 112 + testsuite/tests/embedded/cmcaml.ml | 2 +- testsuite/tests/ephe-c-api/ocamltests | 1 + testsuite/tests/ephe-c-api/stubs.c | 325 + testsuite/tests/ephe-c-api/test.ml | 24 + testsuite/tests/ephe-c-api/test.reference | 65 + testsuite/tests/extension-constructor/test.ml | 8 +- testsuite/tests/flambda/gpr2239.ml | 16 + testsuite/tests/flambda/gpr2239.reference | 1 + testsuite/tests/flambda/ocamltests | 1 + testsuite/tests/flambda/specialise.ml | 11 +- .../float_subst_boxed_number.ml | 10 +- testsuite/tests/float-unboxing/ocamltests | 1 + .../float-unboxing/unbox_under_assign.ml | 75 + testsuite/tests/fma/fma.ml | 496 + testsuite/tests/fma/fma.reference | 317 + testsuite/tests/fma/ocamltests | 1 + testsuite/tests/formatting/errors_batch.ml | 43 + .../tests/formatting/errors_batch.reference | 10 + testsuite/tests/formatting/margins.ml | 1 + .../tests/formatting/margins.ocaml.reference | 12 +- testsuite/tests/formatting/ocamltests | 1 + .../functors/functors.compilers.reference | 25 +- testsuite/tests/gc-roots/globroots.ml | 8 +- .../tests/generalized-open/accepted_batch.ml | 34 + .../generalized-open/accepted_batch.reference | 3 + .../tests/generalized-open/accepted_expect.ml | 63 + .../tests/generalized-open/expansiveness.ml | 93 + .../funct_body.compilers.reference | 5 + .../tests/generalized-open/funct_body.ml | 47 + testsuite/tests/generalized-open/gpr1506.ml | 389 + testsuite/tests/generalized-open/ocamltests | 6 + testsuite/tests/generalized-open/shadowing.ml | 59 + testsuite/tests/let-syntax/let_syntax.ml | 723 + testsuite/tests/let-syntax/ocamltests | 1 + testsuite/tests/letrec-check/basic.ml | 363 + .../letrec-check/extension_constructor.ml | 25 + .../tests/letrec-check/flat_float_array.ml | 52 + .../tests/letrec-check/float_unboxing.ml | 37 + testsuite/tests/letrec-check/labels.ml | 33 + testsuite/tests/letrec-check/lazy_.ml | 23 + testsuite/tests/letrec-check/modules.ml | 97 + .../tests/letrec-check/no_flat_float_array.ml | 32 + testsuite/tests/letrec-check/objects.ml | 60 + testsuite/tests/letrec-check/ocamltests | 14 + .../pr7215.ml | 0 .../tests/letrec-check/pr7215.ocaml.reference | 7 + testsuite/tests/letrec-check/pr7231.ml | 5 + .../tests/letrec-check/pr7231.ocaml.reference | 9 + .../pr7706.ml | 0 .../tests/letrec-check/pr7706.ocaml.reference | 9 + testsuite/tests/letrec-check/records.ml | 31 + testsuite/tests/letrec-check/unboxed.ml | 109 + .../backreferences.ml | 0 .../backreferences.reference} | 0 .../{letrec => letrec-compilation}/class_1.ml | 0 .../class_1.reference} | 0 .../{letrec => letrec-compilation}/class_2.ml | 0 .../class_2.reference | 0 .../evaluation_order_1.ml | 0 .../evaluation_order_1.reference | 0 .../evaluation_order_2.ml | 0 .../evaluation_order_2.reference | 0 .../evaluation_order_3.ml | 0 .../evaluation_order_3.reference | 0 .../float_block_1.ml | 0 .../float_block_1.reference | 0 .../generic_array.ml | 0 .../generic_array.reference} | 0 .../{letrec => letrec-compilation}/labels.ml | 0 .../labels.reference} | 0 .../{letrec => letrec-compilation}/lazy_.ml | 0 .../lazy_.reference | 0 .../{letrec => letrec-compilation}/lists.ml | 0 .../lists.reference} | 0 .../mixing_value_closures_1.ml | 0 .../mixing_value_closures_1.reference} | 0 .../mixing_value_closures_2.ml | 0 .../mixing_value_closures_2.reference} | 0 .../mutual_functions.ml | 0 .../mutual_functions.reference} | 0 .../{letrec => letrec-compilation}/nested.ml | 0 .../nested.reference} | 0 testsuite/tests/letrec-compilation/ocamltests | 18 + .../{letrec => letrec-compilation}/pr4989.ml | 0 .../pr4989.reference} | 0 .../record_with.ml | 0 .../record_with.reference | 0 testsuite/tests/letrec-compilation/ref.ml | 15 + .../tests/letrec-compilation/ref.reference | 0 .../tests/letrec-disallowed/disallowed.ml | 116 - .../disallowed.ocaml.reference | 125 - .../extension_constructor.ml | 16 - .../extension_constructor.ocaml.reference | 6 - .../letrec-disallowed/float_block_allowed.ml | 14 - .../float_block_allowed.ocaml.reference | 2 - .../float_block_disallowed.ml | 18 - .../float_block_disallowed.ocaml.reference | 5 - .../tests/letrec-disallowed/generic_arrays.ml | 7 - .../generic_arrays.ocaml.reference | 5 - testsuite/tests/letrec-disallowed/labels.ml | 6 - .../letrec-disallowed/labels.ocaml.reference | 6 - testsuite/tests/letrec-disallowed/lazy_.ml | 7 - .../letrec-disallowed/lazy_.ocaml.reference | 7 - .../letrec-disallowed/module_constraints.ml | 10 - .../module_constraints.ocaml.reference | 8 - testsuite/tests/letrec-disallowed/ocamltests | 12 - .../letrec-disallowed/pr7215.ocaml.reference | 7 - testsuite/tests/letrec-disallowed/pr7231.ml | 5 - .../letrec-disallowed/pr7231.ocaml.reference | 9 - .../letrec-disallowed/pr7706.ocaml.reference | 9 - testsuite/tests/letrec-disallowed/unboxed.ml | 29 - .../letrec-disallowed/unboxed.ocaml.reference | 27 - testsuite/tests/letrec/allowed.ml | 108 - testsuite/tests/letrec/ocamltests | 19 - testsuite/tests/letrec/ref.ml | 14 - testsuite/tests/lexing/escape.ml | 11 + testsuite/tests/lexing/escape.ocaml.reference | 24 + testsuite/tests/lexing/ocamltests | 1 + .../tests/lexing/uchar_esc.ocaml.reference | 60 +- testsuite/tests/lib-arg/testarg.ml | 3 +- testsuite/tests/lib-arg/testerror.ml | 9 +- testsuite/tests/lib-arg/testerror.reference | 34 +- testsuite/tests/lib-bigarray-2/Makefile | 24 - testsuite/tests/lib-bigarray-2/bigarrfml.ml | 30 + testsuite/tests/lib-bigarray-2/bigarrfstub.c | 2 +- .../tests/lib-bigarray-2/has-gfortran.sh | 12 + testsuite/tests/lib-bigarray-2/ocamltests | 1 + testsuite/tests/lib-bigarray-file/mapfile.ml | 1 + testsuite/tests/lib-bigarray/change_layout.ml | 3 +- testsuite/tests/lib-bool/ocamltests | 1 + testsuite/tests/lib-bool/test.ml | 86 + testsuite/tests/lib-bool/test.reference | 1 + testsuite/tests/lib-buffer/test.ml | 61 + testsuite/tests/lib-bytes/binary.ml | 172 + testsuite/tests/lib-bytes/ocamltests | 1 + testsuite/tests/lib-bytes/test_bytes.ml | 4 +- testsuite/tests/lib-digest/md5.ml | 12 +- testsuite/tests/lib-dynlink-bytecode/Makefile | 73 - testsuite/tests/lib-dynlink-bytecode/main.ml | 58 +- .../tests/lib-dynlink-bytecode/ocamltests | 1 + testsuite/tests/lib-dynlink-csharp/Makefile | 122 - .../lib-dynlink-csharp/bytecode.reference | 7 - testsuite/tests/lib-dynlink-csharp/entry.c | 0 .../main.bytecode.reference | 5 + testsuite/tests/lib-dynlink-csharp/main.cs | 0 testsuite/tests/lib-dynlink-csharp/main.ml | 93 +- .../lib-dynlink-csharp/main.native.reference | 5 + .../tests/lib-dynlink-csharp/native.reference | 7 - testsuite/tests/lib-dynlink-csharp/ocamltests | 1 + testsuite/tests/lib-dynlink-csharp/plugin.ml | 0 .../tests/lib-dynlink-initializers/ocamltests | 9 + .../test1_inited_second.ml | 1 + .../lib-dynlink-initializers/test1_main.ml | 57 + .../lib-dynlink-initializers/test1_plugin.ml | 2 + .../test2_inited_first.ml | 1 + .../lib-dynlink-initializers/test2_main.ml | 50 + .../lib-dynlink-initializers/test2_plugin.ml | 2 + .../lib-dynlink-initializers/test3_main.ml | 55 + .../test3_plugin_a.ml | 1 + .../test3_plugin_b.ml | 2 + .../lib-dynlink-initializers/test4_main.ml | 60 + .../test4_plugin_a.ml | 2 + .../test4_plugin_b.ml | 1 + .../lib-dynlink-initializers/test5_main.ml | 60 + .../test5_plugin_a.ml | 4 + .../test5_plugin_b.ml | 6 + .../test5_second_plugin.ml | 2 + .../lib-dynlink-initializers/test6_main.ml | 50 + .../lib-dynlink-initializers/test6_plugin.ml | 17 + .../test6_second_plugin.ml | 2 + .../test7_interface_only.mli | 2 + .../lib-dynlink-initializers/test7_main.ml | 49 + .../lib-dynlink-initializers/test7_plugin.ml | 2 + .../lib-dynlink-initializers/test8_main.ml | 58 + .../test8_plugin_a.ml | 4 + .../test8_plugin_b.ml | 4 + .../test8_plugin_b.mli | 2 + .../lib-dynlink-initializers/test9_main.ml | 57 + .../lib-dynlink-initializers/test9_plugin.ml | 2 + .../test9_second_plugin.ml | 4 + .../test9_second_plugin.mli | 2 + testsuite/tests/lib-dynlink-native/Makefile | 126 - testsuite/tests/lib-dynlink-native/a.ml | 0 testsuite/tests/lib-dynlink-native/b.ml | 0 testsuite/tests/lib-dynlink-native/c.ml | 0 testsuite/tests/lib-dynlink-native/main.ml | 215 +- .../{reference => main.reference} | 0 testsuite/tests/lib-dynlink-native/ocamltests | 1 + .../tests/lib-dynlink-pr4229/abstract.ml | 3 + .../tests/lib-dynlink-pr4229/abstract.mli | 3 + testsuite/tests/lib-dynlink-pr4229/client.ml | 1 + testsuite/tests/lib-dynlink-pr4229/main.ml | 94 + .../tests/lib-dynlink-pr4229/main.reference | 1 + .../tests/lib-dynlink-pr4229/main_native.ml | 10 + testsuite/tests/lib-dynlink-pr4229/ocamltests | 1 + testsuite/tests/lib-dynlink-pr4229/static.ml | 1 + .../tests/lib-dynlink-pr4229/sub/abstract.ml | 3 + .../tests/lib-dynlink-pr4229/sub/abstract.mli | 3 + .../lib-dynlink-pr4839/byte.plugin1.reference | 3 + .../lib-dynlink-pr4839/byte.plugin2.reference | 2 + .../lib-dynlink-pr4839/byte.plugin3.reference | 2 + .../lib-dynlink-pr4839/byte.plugin4.reference | 2 + .../tests/lib-dynlink-pr4839/host/api.ml | 3 + .../tests/lib-dynlink-pr4839/host/api.mli | 2 + .../tests/lib-dynlink-pr4839/host/host.ml | 8 + .../native.plugin1.reference | 3 + .../native.plugin2.reference | 2 + .../native.plugin3.reference | 2 + .../native.plugin4.reference | 2 + testsuite/tests/lib-dynlink-pr4839/ocamltests | 1 + .../tests/lib-dynlink-pr4839/plugin1/api.ml | 3 + .../tests/lib-dynlink-pr4839/plugin1/api.mli | 2 + .../lib-dynlink-pr4839/plugin1/plugin.ml | 7 + .../tests/lib-dynlink-pr4839/plugin2/api.ml | 3 + .../tests/lib-dynlink-pr4839/plugin2/api.mli | 2 + .../lib-dynlink-pr4839/plugin2/plugin.ml | 7 + .../tests/lib-dynlink-pr4839/plugin3/api.ml | 3 + .../tests/lib-dynlink-pr4839/plugin3/api.mli | 2 + .../lib-dynlink-pr4839/plugin3/plugin.ml | 7 + .../tests/lib-dynlink-pr4839/plugin4/api.ml | 3 + .../tests/lib-dynlink-pr4839/plugin4/api.mli | 2 + .../lib-dynlink-pr4839/plugin4/plugin.ml | 7 + testsuite/tests/lib-dynlink-pr4839/test.ml | 261 + testsuite/tests/lib-dynlink-pr6950/b.ml | 1 + .../tests/lib-dynlink-pr6950/byte.reference | 0 testsuite/tests/lib-dynlink-pr6950/config.ml | 2 + testsuite/tests/lib-dynlink-pr6950/loader.ml | 48 + .../tests/lib-dynlink-pr6950/native.reference | 0 testsuite/tests/lib-dynlink-pr6950/ocamltests | 1 + .../tests/lib-dynlink-private/ocamltests | 1 + testsuite/tests/lib-dynlink-private/pig.mli | 4 + .../lib-dynlink-private/plugin1/sheep.ml | 4 + .../lib-dynlink-private/plugin1/sheep.mli | 4 + .../tests/lib-dynlink-private/plugin2/cow.ml | 4 + .../tests/lib-dynlink-private/plugin2/cow.mli | 4 + .../tests/lib-dynlink-private/plugin2b/cow.ml | 4 + .../lib-dynlink-private/plugin2b/cow.mli | 4 + .../tests/lib-dynlink-private/plugin2c/cow.ml | 4 + .../lib-dynlink-private/plugin2c/cow.mli | 4 + .../tests/lib-dynlink-private/plugin3/pig.ml | 4 + .../tests/lib-dynlink-private/plugin3/pig.mli | 4 + .../lib-dynlink-private/plugin4/chicken.ml | 11 + .../lib-dynlink-private/plugin4/chicken.mli | 0 .../lib-dynlink-private/plugin5/chicken.ml | 2 + .../lib-dynlink-private/plugin5/chicken.mli | 2 + .../lib-dynlink-private/plugin6/partridge.ml | 1 + .../lib-dynlink-private/plugin6/partridge.mli | 1 + .../lib-dynlink-private/plugin6/pheasant.ml | 10 + .../lib-dynlink-private/plugin6/pheasant.mli | 0 testsuite/tests/lib-dynlink-private/sheep.ml | 4 + testsuite/tests/lib-dynlink-private/sheep.mli | 4 + testsuite/tests/lib-dynlink-private/test.ml | 272 + testsuite/tests/lib-filename/ocamltests | 1 + testsuite/tests/lib-filename/suffix.ml | 27 + testsuite/tests/lib-filename/suffix.reference | 0 testsuite/tests/lib-float/ocamltests | 1 + testsuite/tests/lib-float/test.ml | 119 + testsuite/tests/lib-float/test.reference | 1 + testsuite/tests/lib-floatarray/floatarray.ml | 528 + testsuite/tests/lib-floatarray/ocamltests | 1 + testsuite/tests/lib-format/ocamltests | 2 + .../tests/lib-format/pp_print_custom_break.ml | 64 + .../pp_print_custom_break.reference | 159 + .../tests/lib-format/print_if_newline.ml | 26 + .../lib-format/print_if_newline.reference | 6 + testsuite/tests/lib-format/tformat.ml | 8 + testsuite/tests/lib-format/tformat.reference | 2 + testsuite/tests/lib-fun/ocamltests | 1 + testsuite/tests/lib-fun/test.ml | 52 + testsuite/tests/lib-fun/test.reference | 1 + testsuite/tests/lib-hashtbl/htbl.ml | 19 +- testsuite/tests/lib-int/ocamltests | 1 + testsuite/tests/lib-int/test.ml | 71 + testsuite/tests/lib-int/test.reference | 1 + testsuite/tests/lib-int64/ocamltests | 1 + testsuite/tests/lib-int64/test.ml | 71 + testsuite/tests/lib-int64/test.reference | 1 + testsuite/tests/lib-list/test.ml | 10 +- testsuite/tests/lib-marshal/intext.ml | 14 + testsuite/tests/lib-marshal/intextaux.c | 34 + testsuite/tests/lib-option/ocamltests | 1 + testsuite/tests/lib-option/test.ml | 117 + testsuite/tests/lib-option/test.reference | 1 + testsuite/tests/lib-printf/tprintf.ml | 29 +- testsuite/tests/lib-printf/tprintf.reference | 92 +- testsuite/tests/lib-result/ocamltests | 1 + testsuite/tests/lib-result/test.ml | 131 + testsuite/tests/lib-result/test.reference | 1 + .../{reference => tscanf2.reference} | 0 testsuite/tests/lib-scanf-2/tscanf2_master.ml | 55 +- testsuite/tests/lib-scanf-2/tscanf2_slave.ml | 28 - testsuite/tests/lib-scanf-2/tscanf2_worker.ml | 28 + testsuite/tests/lib-scanf/tscanf.ml | 26 +- testsuite/tests/lib-scanf/tscanf.reference | 2 +- testsuite/tests/lib-seq/test.ml | 4 +- testsuite/tests/lib-set/testset.ml | 3 + testsuite/tests/lib-stdlib/ocamltests | 1 + .../tests/lib-stdlib/pervasives_deprecated.ml | 41 + testsuite/tests/lib-str/t01.ml | 1 + testsuite/tests/lib-systhreads/ocamltests | 1 + testsuite/tests/lib-systhreads/testfork.ml | 9 +- testsuite/tests/lib-systhreads/testpreempt.ml | 7 +- .../tests/lib-systhreads/threadsigmask.ml | 80 + .../lib-systhreads/threadsigmask.reference | 1 + .../tests/lib-threads/backtrace_threads.ml | 1 + testsuite/tests/lib-threads/bank.ml | 1 + testsuite/tests/lib-threads/beat.ml | 1 + testsuite/tests/lib-threads/bufchan.ml | 1 + testsuite/tests/lib-threads/close.ml | 1 + testsuite/tests/lib-threads/fileio.ml | 1 + testsuite/tests/lib-threads/pr4466.ml | 22 +- testsuite/tests/lib-threads/pr5325.ml | 26 +- testsuite/tests/lib-threads/pr7638.ml | 1 + testsuite/tests/lib-threads/prodcons.ml | 1 + testsuite/tests/lib-threads/prodcons2.ml | 1 + testsuite/tests/lib-threads/sieve.ml | 1 + testsuite/tests/lib-threads/signal.ml | 27 +- testsuite/tests/lib-threads/sockets.ml | 7 +- testsuite/tests/lib-threads/swapchan.ml | 1 + testsuite/tests/lib-threads/tls.ml | 1 + testsuite/tests/lib-threads/torture.ml | 4 +- testsuite/tests/lib-unix/common/channel_of.ml | 66 + .../lib-unix/common/channel_of.reference | 12 + testsuite/tests/lib-unix/common/cloexec.ml | 35 +- testsuite/tests/lib-unix/common/dup.ml | 3 + testsuite/tests/lib-unix/common/dup2.ml | 7 +- .../tests/lib-unix/common/getaddrinfo.ml | 16 + testsuite/tests/lib-unix/common/ocamltests | 3 + testsuite/tests/lib-unix/common/pipe_eof.ml | 3 + .../tests/lib-unix/common/process_pid.ml | 24 + .../lib-unix/common/process_pid.reference | 1 + .../tests/lib-unix/common/redirections.ml | 42 +- testsuite/tests/lib-unix/common/reflector.ml | 9 +- testsuite/tests/lib-unix/common/rename.ml | 3 + .../lib-unix/common/test_unix_cmdline.ml | 29 +- testsuite/tests/lib-unix/common/utimes.ml | 3 + .../tests/lib-unix/common/wait_nohang.ml | 1 + testsuite/tests/lib-unix/isatty/isatty_std.ml | 3 + testsuite/tests/lib-unix/unix-execvpe/exec.ml | 7 +- .../lib-unix/unix-execvpe/has-execvpe.sh | 2 +- testsuite/tests/lib-unix/unix-execvpe/script3 | 1 - .../lib-unix/unix-execvpe/subdir/nonexec | 1 - testsuite/tests/lib-unix/win-env/test_env.ml | 3 +- testsuite/tests/lib-unix/win-stat/test.ml | 4 +- .../tests/lib-unix/win-symlink/ocamltests | 1 + testsuite/tests/lib-unix/win-symlink/test.ml | 2 +- testsuite/tests/link-test/test.ml | 3 +- testsuite/tests/local-functions/ocamltests | 2 + testsuite/tests/local-functions/tupled.ml | 11 + testsuite/tests/local-functions/tupled2.ml | 16 + testsuite/tests/locale/ocamltests | 1 + testsuite/tests/locale/stubs.c | 8 + testsuite/tests/locale/test.ml | 31 + testsuite/tests/locale/test.reference | 12 + testsuite/tests/manual-intf-c/curses_stubs.c | 3 +- testsuite/tests/manual-intf-c/prog.ml | 2 +- .../exhaustiveness_warnings.ml | 79 +- .../exhaustiveness_warnings.ml.reference | 11 - .../exhaustiveness_warnings.ocaml.reference | 10 - .../no_mixing_under_guard.ml | 21 + .../no_value_clauses.ml | 15 + .../match-exception-warnings/placement.ml | 172 + .../tests/match-exception-warnings/pr7083.ml | 13 + .../match-exception-warnings/reachability.ml | 61 + .../match-exception/identifier_sharing.ml | 9 + .../identifier_sharing.reference | 1 + testsuite/tests/match-exception/ocamltests | 1 + testsuite/tests/messages/precise_locations.ml | 64 +- testsuite/tests/misc/ephetest2.ml | 7 +- testsuite/tests/no-alias-deps/a2235.ml | 1 + .../no-alias-deps/aliases.compilers.reference | 8 +- testsuite/tests/no-alias-deps/aliases.ml | 3 +- testsuite/tests/no-alias-deps/gpr2235.ml | 21 + testsuite/tests/no-alias-deps/lib2235.ml | 1 + testsuite/tests/no-alias-deps/lib__2235.ml | 1 + testsuite/tests/no-alias-deps/ocamltests | 1 + .../tests/no-alias-deps/user_of_lib2235.ml | 3 + testsuite/tests/opaque/test.ml | 9 +- .../tests/output-complete-obj/ocamltests | 1 + testsuite/tests/output-complete-obj/test.ml | 33 + .../test.ml_stub.c | 0 testsuite/tests/output_obj/Makefile.disabled | 58 - testsuite/tests/output_obj/test.ml | 1 - .../escape_error.compilers.reference | 13 + testsuite/tests/parse-errors/escape_error.ml | 12 + .../expecting.compilers.reference | 33 + testsuite/tests/parse-errors/expecting.ml | 35 + testsuite/tests/parse-errors/ocamltests | 18 + .../parse-errors/pr7847.compilers.reference | 4 + testsuite/tests/parse-errors/pr7847.ml | 10 + ...closed_class_signature.compilers.reference | 6 + .../parse-errors/unclosed_class_signature.mli | 10 + ...osed_class_simpl_expr1.compilers.reference | 6 + .../unclosed_class_simpl_expr1.ml | 9 + ...osed_class_simpl_expr2.compilers.reference | 6 + .../unclosed_class_simpl_expr2.ml | 8 + ...osed_class_simpl_expr3.compilers.reference | 6 + .../unclosed_class_simpl_expr3.ml | 8 + .../unclosed_object.compilers.reference | 6 + .../tests/parse-errors/unclosed_object.ml | 10 + ...sed_paren_module_expr1.compilers.reference | 6 + .../unclosed_paren_module_expr1.ml | 8 + ...sed_paren_module_expr2.compilers.reference | 6 + .../unclosed_paren_module_expr2.ml | 8 + ...sed_paren_module_expr3.compilers.reference | 6 + .../unclosed_paren_module_expr3.ml | 8 + ...sed_paren_module_expr4.compilers.reference | 6 + .../unclosed_paren_module_expr4.ml | 8 + ...sed_paren_module_expr5.compilers.reference | 6 + .../unclosed_paren_module_expr5.ml | 8 + ...osed_paren_module_type.compilers.reference | 6 + .../unclosed_paren_module_type.mli | 8 + .../unclosed_sig.compilers.reference | 6 + testsuite/tests/parse-errors/unclosed_sig.mli | 9 + .../unclosed_simple_expr.compilers.reference | 186 + .../parse-errors/unclosed_simple_expr.ml | 49 + ...nclosed_simple_pattern.compilers.reference | 53 + .../parse-errors/unclosed_simple_pattern.ml | 37 + .../unclosed_struct.compilers.reference | 6 + .../tests/parse-errors/unclosed_struct.ml | 9 + testsuite/tests/parsetree/source.ml | 36 +- testsuite/tests/parsetree/test.ml | 5 +- ...nymous_class_parameter.compilers.reference | 1 + .../parsing/anonymous_class_parameter.ml | 15 + .../arrow_ambiguity.compilers.reference | 2 + testsuite/tests/parsing/arrow_ambiguity.ml | 28 + .../parsing/attributes.compilers.reference | 132 +- testsuite/tests/parsing/attributes.ml | 6 + .../broken_invariants.compilers.reference | 25 + testsuite/tests/parsing/broken_invariants.ml | 17 + ...nstructor_declarations.compilers.reference | 4 + .../tests/parsing/constructor_declarations.ml | 25 + testsuite/tests/parsing/docstrings.ml | 40 +- .../parsing/extensions.compilers.reference | 12 +- .../hash_ambiguity.compilers.reference | 113 + testsuite/tests/parsing/hash_ambiguity.ml | 17 + testsuite/tests/parsing/illegal_ppx.ml | 38 + ...nd_float_with_modifier.compilers.reference | 2 + testsuite/tests/parsing/ocamltests | 6 + .../tests/parsing/pr6604.compilers.reference | 2 + .../parsing/pr6604_2.compilers.reference | 2 + .../tests/parsing/pr6865.compilers.reference | 2 + .../tests/parsing/pr7165.compilers.reference | 2 + testsuite/tests/parsing/reloc.ml | 25 + .../shortcut_ext_attr.compilers.reference | 52 +- testsuite/tests/ppx-attributes/warning.ml | 15 +- testsuite/tests/ppx-contexts/myppx.ml | 41 +- .../ppx-contexts/test.compilers.reference | 35 +- testsuite/tests/ppx-contexts/test.ml | 17 +- testsuite/tests/regression/gpr1623/gpr1623.ml | 8 +- .../missing_set_of_closures.ml | 2 +- .../tests/regression/pr3612/custom_finalize.c | 3 +- testsuite/tests/regression/pr7920/ocamltests | 1 + testsuite/tests/regression/pr7920/pr7920.ml | 11 + .../tests/regression/pr7920/pr7920.reference | 0 testsuite/tests/runtime-errors/Makefile | 80 - .../has-stackoverflow-detection.sh | 8 + testsuite/tests/runtime-errors/ocamltests | 2 + .../stackoverflow.bytecode.checker | 16 - .../tests/runtime-errors/stackoverflow.ml | 25 + .../stackoverflow.native.checker | 16 - ...code.reference => stackoverflow.reference} | 0 .../tests/runtime-errors/stackoverflow.run | 16 + .../runtime-errors/syserror.bytecode.checker | 16 - testsuite/tests/runtime-errors/syserror.ml | 30 + .../runtime-errors/syserror.native.checker | 16 - .../runtime-errors/syserror.native.reference | 1 - ...code.reference => syserror.unix.reference} | 0 .../runtime-errors/syserror.win32.reference | 1 + .../tests/self-contained-toplevel/main.ml | 6 + testsuite/tests/shadow_include/artificial.ml | 70 + .../cannot_shadow_error.compilers.reference | 8 + .../shadow_include/cannot_shadow_error.ml | 25 + testsuite/tests/shadow_include/ocamltests | 3 + testsuite/tests/shadow_include/shadow_all.ml | 477 + testsuite/tests/tool-caml-tex/ellipses.ml | 60 + .../tests/tool-caml-tex/ellipses.reference | 58 + testsuite/tests/tool-caml-tex/ocamltests | 2 + testsuite/tests/tool-caml-tex/redirections.ml | 27 + .../tool-caml-tex/redirections.reference | 38 + .../test.compilers.reference | 1 + testsuite/tests/tool-command-line/test.ml | 21 +- .../test.ocamlc.byte.reference | 130 - .../test.ocamlopt.byte.flambda.reference | 178 - .../test.ocamlopt.byte.reference | 178 - .../tests/tool-debugger/basic/debuggee.ml | 13 +- .../tool-debugger/find-artifacts/debuggee.ml | 19 +- .../tool-debugger/no_debug_event/noev.ml | 19 +- .../tests/tool-expect-test/clean_typer.ml | 82 + testsuite/tests/tool-expect-test/ocamltests | 1 + testsuite/tests/tool-lexyacc/chars.mll | 16 + testsuite/tests/tool-lexyacc/main.ml | 3 +- testsuite/tests/tool-lexyacc/mpr7760.mll | 13 + .../tests/tool-lexyacc/mpr7760.reference | 1 + testsuite/tests/tool-lexyacc/ocamltests | 2 + testsuite/tests/tool-lexyacc/output.ml | 14 +- .../tests/tool-ocaml-annot/check-annot.sh | 7 + testsuite/tests/tool-ocaml-annot/failure.ml | 19 + testsuite/tests/tool-ocaml-annot/ocamltests | 3 + testsuite/tests/tool-ocaml-annot/success.ml | 18 + testsuite/tests/tool-ocaml-annot/typeonly.ml | 18 + testsuite/tests/tool-ocaml/t240-c_call1.ml | 4 +- .../check-error-cleanup.sh | 6 + .../tool-ocamlc-error-cleanup/ocamltests | 1 + .../tests/tool-ocamlc-error-cleanup/test.ml | 16 + .../tests/tool-ocamlc-stop-after/ocamltests | 3 + ...top_after_parsing_impl.compilers.reference | 36 + .../stop_after_parsing_impl.ml | 12 + ...top_after_parsing_intf.compilers.reference | 10 + .../stop_after_parsing_intf.mli | 12 + ...stop_after_typing_impl.compilers.reference | 18 + .../stop_after_typing_impl.ml | 13 + .../tests/tool-ocamldep-modalias/Makefile | 73 - .../tool-ocamldep-modalias/Makefile.build | 52 +- .../tool-ocamldep-modalias/Makefile.build2 | 53 +- .../depend.mk.reference | 36 +- .../depend.mk2.reference | 30 +- .../tests/tool-ocamldep-modalias/main.ml | 83 + .../tests/tool-ocamldep-modalias/ocamltests | 1 + .../tool-ocamldep-modalias/setup-links.sh | 2 + .../tool-ocamldoc/Documentation_tags.mli | 4 +- .../Include_module_type_of.html.reference | 29 + .../Include_module_type_of.latex.reference | 96 + .../tool-ocamldoc/Include_module_type_of.mli | 21 + .../tool-ocamldoc/Level_0.latex.reference | 10 +- testsuite/tests/tool-ocamldoc/Level_0.mli | 14 +- .../tool-ocamldoc/Paragraph.html.reference | 2 +- testsuite/tests/tool-ocamldoc/Paragraph.mli | 2 +- .../tool-ocamldoc/latex_ref.latex.reference | 27 + testsuite/tests/tool-ocamldoc/latex_ref.mli | 11 + testsuite/tests/tool-ocamldoc/ocamltests | 2 + .../tests/tool-ocamlobjinfo/has-lib-bfd.sh | 2 +- .../tests/tool-toplevel-invocation/test.ml | 6 +- .../error_highlighting.compilers.reference | 68 + .../tests/tool-toplevel/error_highlighting.ml | 32 + .../tool-toplevel/error_highlighting_use1.ml | 1 + .../tool-toplevel/error_highlighting_use2.ml | 1 + .../tool-toplevel/error_highlighting_use3.ml | 4 + .../tool-toplevel/error_highlighting_use4.ml | 4 + testsuite/tests/tool-toplevel/exotic_lists.ml | 2 - testsuite/tests/tool-toplevel/ocamltests | 2 + .../tool-toplevel/pr6468.compilers.reference | 12 + testsuite/tests/tool-toplevel/pr6468.ml | 10 + .../tool-toplevel/pr7060.compilers.reference | 10 +- .../tool-toplevel/pr7751.compilers.reference | 2 +- testsuite/tests/tool-toplevel/strings.ml | 3 +- .../array_spec.compilers.flat.reference | 65 + .../array_spec.compilers.no-flat.reference | 65 + .../array_spec.compilers.reference.flat | 65 - .../array_spec.compilers.reference.no-flat | 65 - testsuite/tests/translprim/array_spec.ml | 6 +- .../comparison_table.compilers.reference | 80 +- testsuite/tests/translprim/locs.ml | 2 +- .../module_coercion.compilers.flat.reference | 87 + ...odule_coercion.compilers.no-flat.reference | 87 + .../module_coercion.compilers.reference.flat | 87 - ...odule_coercion.compilers.reference.no-flat | 87 - testsuite/tests/translprim/module_coercion.ml | 6 +- .../typing-core-bugs/missing_rec_hint.ml | 67 + testsuite/tests/typing-core-bugs/ocamltests | 2 + .../typing-core-bugs/repeated_did_you_mean.ml | 22 + .../type_expected_explanation.ml | 106 +- .../tests/typing-core-bugs/unit_fun_hints.ml | 30 +- testsuite/tests/typing-deprecated/alerts.ml | 273 + .../tests/typing-deprecated/deprecated.ml | 328 +- testsuite/tests/typing-deprecated/ocamltests | 1 + .../test.ocaml.reference | 6 +- testsuite/tests/typing-extensions/cast.ml | 2 +- .../tests/typing-extensions/extensions.ml | 10 +- .../extensions.ocaml.reference | 78 +- testsuite/tests/typing-extensions/msg.ml | 2 +- .../open_types.ocaml.reference | 76 +- .../tests/typing-fstclassmod/fstclassmod.ml | 6 +- testsuite/tests/typing-gadts/ambiguity.ml | 78 +- testsuite/tests/typing-gadts/didier.ml | 30 +- .../tests/typing-gadts/dynamic_frisch.ml | 6 +- testsuite/tests/typing-gadts/gpr1997.ml | 53 - .../tests/typing-gadts/nested_equations.ml | 12 +- testsuite/tests/typing-gadts/ocamltests | 3 +- testsuite/tests/typing-gadts/or_patterns.ml | 763 + testsuite/tests/typing-gadts/pr5332.ml | 6 +- testsuite/tests/typing-gadts/pr5689.ml | 6 +- testsuite/tests/typing-gadts/pr5785.ml | 8 +- testsuite/tests/typing-gadts/pr5906.ml | 12 +- testsuite/tests/typing-gadts/pr5948.ml | 12 +- testsuite/tests/typing-gadts/pr5981.ml | 12 +- testsuite/tests/typing-gadts/pr5985.ml | 68 +- testsuite/tests/typing-gadts/pr5989.ml | 12 +- testsuite/tests/typing-gadts/pr5997.ml | 12 +- testsuite/tests/typing-gadts/pr6158.ml | 6 +- testsuite/tests/typing-gadts/pr6163.ml | 6 +- testsuite/tests/typing-gadts/pr6174.ml | 6 +- testsuite/tests/typing-gadts/pr6241.ml | 6 +- testsuite/tests/typing-gadts/pr6690.ml | 34 +- testsuite/tests/typing-gadts/pr6934.ml | 7 +- testsuite/tests/typing-gadts/pr6980.ml | 6 +- testsuite/tests/typing-gadts/pr6993_bad.ml | 6 +- testsuite/tests/typing-gadts/pr7016.ml | 12 +- testsuite/tests/typing-gadts/pr7160.ml | 6 +- testsuite/tests/typing-gadts/pr7214.ml | 12 +- testsuite/tests/typing-gadts/pr7222.ml | 13 +- testsuite/tests/typing-gadts/pr7234.ml | 12 +- testsuite/tests/typing-gadts/pr7260.ml | 14 +- testsuite/tests/typing-gadts/pr7269.ml | 18 +- testsuite/tests/typing-gadts/pr7374.ml | 12 +- testsuite/tests/typing-gadts/pr7378.ml | 6 +- testsuite/tests/typing-gadts/pr7390.ml | 6 +- testsuite/tests/typing-gadts/pr7421.ml | 12 +- testsuite/tests/typing-gadts/pr7432.ml | 6 +- testsuite/tests/typing-gadts/pr7618.ml | 20 +- testsuite/tests/typing-gadts/pr7747.ml | 6 +- testsuite/tests/typing-gadts/term-conv.ml | 4 +- testsuite/tests/typing-gadts/test.ml | 273 +- .../typing-gadts/unexpected_existentials.ml | 158 + testsuite/tests/typing-gadts/yallop_bugs.ml | 28 +- testsuite/tests/typing-immediate/immediate.ml | 32 +- .../typing-implicit_unpack/implicit_unpack.ml | 2 +- .../implicit_unpack.ocaml.reference | 44 +- testsuite/tests/typing-labels/mixin.ml | 2 +- testsuite/tests/typing-labels/mixin2.ml | 2 +- testsuite/tests/typing-labels/mixin3.ml | 2 +- .../pr6303_bad.compilers.reference | 2 + .../pr6946_bad.compilers.reference | 2 + testsuite/tests/typing-misc/constraints.ml | 60 +- .../typing-misc/disambiguate_principality.ml | 337 +- testsuite/tests/typing-misc/empty_ppx.ml | 14 + testsuite/tests/typing-misc/empty_variant.ml | 2 +- .../tests/typing-misc/exotic_unifications.ml | 29 + testsuite/tests/typing-misc/external_arity.ml | 33 + testsuite/tests/typing-misc/labels.ml | 12 +- testsuite/tests/typing-misc/mapping.ml | 4 + testsuite/tests/typing-misc/ocamltests | 14 + testsuite/tests/typing-misc/occur_check.ml | 12 +- .../tests/typing-misc/pat_type_sharing.ml | 17 + testsuite/tests/typing-misc/pattern_open.ml | 249 + testsuite/tests/typing-misc/polyvars.ml | 78 +- testsuite/tests/typing-misc/pr6416.ml | 406 + testsuite/tests/typing-misc/pr6634.ml | 30 + .../typing-misc/pr6939-flat-float-array.ml | 18 +- .../typing-misc/pr6939-no-flat-float-array.ml | 12 +- testsuite/tests/typing-misc/pr7103.ml | 18 +- testsuite/tests/typing-misc/pr7228.ml | 6 +- testsuite/tests/typing-misc/pr7668_bad.ml | 69 +- testsuite/tests/typing-misc/pr8548.ml | 146 + testsuite/tests/typing-misc/pr8548_split.ml | 20 + testsuite/tests/typing-misc/printing.ml | 14 +- testsuite/tests/typing-misc/range.ml | 16 + testsuite/tests/typing-misc/range_intf.ml | 16 + testsuite/tests/typing-misc/ranged.ml | 14 + testsuite/tests/typing-misc/ranged_intf.ml | 4 + testsuite/tests/typing-misc/records.ml | 85 +- testsuite/tests/typing-misc/scope_escape.ml | 15 + ...mpty_polyvariant_error.compilers.reference | 6 + .../typecore_empty_polyvariant_error.ml | 13 + .../tests/typing-misc/typecore_errors.ml | 475 + .../typing-misc/typecore_nolabel_errors.ml | 50 + .../tests/typing-misc/typetexp_errors.ml | 25 + .../unique_names_in_unification.ml | 87 + testsuite/tests/typing-misc/variant.ml | 10 +- testsuite/tests/typing-misc/wellfounded.ml | 6 +- testsuite/tests/typing-missing-cmi-2/bar.mli | 1 + testsuite/tests/typing-missing-cmi-2/baz.ml | 1 + testsuite/tests/typing-missing-cmi-2/foo.mli | 1 + .../tests/typing-missing-cmi-2/ocamltests | 1 + .../test.compilers.reference | 1 + testsuite/tests/typing-missing-cmi-2/test.ml | 15 + .../test.compilers.reference | 6 +- .../pr6293_bad.compilers.reference | 6 +- .../pr6427_bad.compilers.reference | 2 + .../tests/typing-modules-bugs/pr6485_ok.ml | 1 - .../tests/typing-modules-bugs/pr6572_ok.ml | 2 +- .../pr6752_bad.compilers.reference | 2 + .../pr6899_first_bad.compilers.reference | 2 + .../pr6899_second_bad.compilers.reference | 2 + .../pr6992_bad.compilers.reference | 2 + .../pr7112_bad.compilers.reference | 2 + .../pr7414_2_bad.compilers.reference | 2 + .../tests/typing-modules-bugs/pr7414_2_bad.ml | 2 +- .../pr7414_bad.compilers.reference | 2 + .../tests/typing-modules-bugs/pr7414_bad.ml | 2 +- .../tests/typing-modules-bugs/pr7601_ok.ml | 5 +- .../tests/typing-modules-bugs/pr7601a_ok.ml | 1 - testsuite/tests/typing-modules/.gitattributes | 0 testsuite/tests/typing-modules/Test.ml | 98 +- testsuite/tests/typing-modules/aliases.ml | 74 +- .../applicative_functor_type.ml | 24 +- testsuite/tests/typing-modules/firstclass.ml | 12 +- testsuite/tests/typing-modules/generative.ml | 24 +- testsuite/tests/typing-modules/nondep.ml | 21 + .../typing-modules/nondep_private_abbrev.ml | 137 + .../tests/typing-modules/normalize_path.ml | 17 + testsuite/tests/typing-modules/ocamltests | 6 + testsuite/tests/typing-modules/pr6394.ml | 10 +- testsuite/tests/typing-modules/pr7207.ml | 6 +- testsuite/tests/typing-modules/pr7348.ml | 2 +- testsuite/tests/typing-modules/pr7726.ml | 150 + testsuite/tests/typing-modules/pr7818.ml | 28 +- testsuite/tests/typing-modules/pr7851.ml | 79 + testsuite/tests/typing-modules/recursive.ml | 6 +- .../typing-modules/unroll_private_abbrev.ml | 80 + testsuite/tests/typing-multifile/pr7325.ml | 2 +- .../pr3968_bad.compilers.reference | 10 + .../pr4018_bad.compilers.reference | 29 +- .../pr4435_bad.compilers.reference | 4 +- .../pr4824a_bad.compilers.reference | 4 +- .../pr7284_bad.compilers.reference | 2 + testsuite/tests/typing-objects/Exemples.ml | 63 +- testsuite/tests/typing-objects/Tests.ml | 172 +- .../tests/typing-objects/abstract_rows.ml | 26 + testsuite/tests/typing-objects/dummy.ml | 32 +- testsuite/tests/typing-objects/errors.ml | 15 + testsuite/tests/typing-objects/ocamltests | 3 + testsuite/tests/typing-objects/pr5619_bad.ml | 16 +- testsuite/tests/typing-objects/pr5858.ml | 6 +- testsuite/tests/typing-objects/pr6123_bad.ml | 6 +- testsuite/tests/typing-objects/pr6383.ml | 6 +- testsuite/tests/typing-objects/pr6907_bad.ml | 6 +- .../typing-objects/self_cannot_be_closed.ml | 17 + testsuite/tests/typing-ocamlc-i/ocamltests | 4 + .../pervasives_leitmotiv.compilers.reference | 13 + .../typing-ocamlc-i/pervasives_leitmotiv.ml | 14 + .../pr4791.compilers.reference | 12 + testsuite/tests/typing-ocamlc-i/pr4791.ml | 13 + .../pr6323.compilers.reference | 14 + testsuite/tests/typing-ocamlc-i/pr6323.ml | 17 + .../pr7402.compilers.reference | 12 + testsuite/tests/typing-ocamlc-i/pr7402.ml | 19 + .../pr7620_bad.compilers.reference | 2 + testsuite/tests/typing-ocamlc-i/pr7620_bad.ml | 2 +- .../tests/typing-pattern_open/ocamltests | 1 - .../tests/typing-pattern_open/pattern_open.ml | 151 - .../pattern_open.ocaml.reference | 80 - .../pr5673_bad.compilers.reference | 13 +- testsuite/tests/typing-poly/error_messages.ml | 85 + testsuite/tests/typing-poly/ocamltests | 1 + testsuite/tests/typing-poly/poly.ml | 336 +- .../pr3918c.compilers.reference | 4 +- .../pr5057a_bad.compilers.reference | 2 + .../tests/typing-polyvariants-bugs/pr7824.ml | 6 +- .../pr5026_bad.compilers.reference | 2 + .../private.compilers.principal.reference | 66 +- .../private.compilers.reference | 66 +- testsuite/tests/typing-private/private.ml | 1 - testsuite/tests/typing-recmod/gpr1626.ml | 16 + testsuite/tests/typing-recmod/ocamltests | 2 +- .../typing-recmod/t01bad.compilers.reference | 2 + .../typing-recmod/t02bad.compilers.reference | 2 + .../typing-recmod/t04bad.compilers.reference | 2 + .../typing-recmod/t05bad.compilers.reference | 2 + .../typing-recmod/t07bad.compilers.reference | 2 + .../typing-recmod/t08bad.compilers.reference | 2 + .../typing-recmod/t09bad.compilers.reference | 2 + .../typing-recmod/t11bad.compilers.reference | 2 + .../typing-recmod/t12bad.compilers.reference | 5 + .../typing-recmod/t14bad.compilers.reference | 4 +- testsuite/tests/typing-recmod/t14bad.ml | 2 +- .../typing-recmod/t15bad.compilers.reference | 2 + testsuite/tests/typing-recmod/t19ok.ml | 22 - testsuite/tests/typing-recmod/t22ok.ml | 2 +- .../recordarg.ocaml.reference | 48 +- .../pr5343_bad.compilers.reference | 2 + .../pr6174_bad.compilers.reference | 2 + .../pr6870_bad.compilers.reference | 2 + .../b_bad.compilers.reference | 6 +- testsuite/tests/typing-safe-linking/b_bad.ml | 3 +- .../ocamltests | 1 + ...redefine_largefile_top.compilers.reference | 2 + .../redefine_largefile_top.ml | 16 + testsuite/tests/typing-short-paths/gpr1223.ml | 2 +- .../pr5918.compilers.reference | 6 +- .../pr7543.compilers.reference | 6 +- .../short-paths.compilers.reference | 12 +- .../typing-signatures/pr6672.ocaml.reference | 6 +- testsuite/tests/typing-sigsubst/mpr7852.mli | 12 + testsuite/tests/typing-sigsubst/ocamltests | 3 + .../typing-sigsubst/sig_local_aliases.ml | 120 + ..._aliases_syntax_errors.compilers.reference | 38 + .../sig_local_aliases_syntax_errors.ml | 36 + testsuite/tests/typing-sigsubst/sigsubst.ml | 135 +- .../tests/typing-sigsubst/test_functor.ml | 13 + .../test_loc_modtype_type_eq.ml | 3 + .../test_loc_modtype_type_subst.ml | 3 + .../tests/typing-sigsubst/test_loc_type_eq.ml | 1 + .../typing-sigsubst/test_loc_type_subst.ml | 1 + .../test_locations.compilers.reference | 74 + .../tests/typing-sigsubst/test_locations.ml | 26 + .../typing-typeparam/newtype.ocaml.reference | 12 +- .../tests/typing-unboxed-types/ocamltests | 2 + testsuite/tests/typing-unboxed-types/test.ml | 275 +- .../test.ml.reference-flat | 212 - .../test.ml.reference-noflat | 178 - .../tests/typing-unboxed-types/test_flat.ml | 202 + .../typing-unboxed-types/test_no_flat.ml | 154 + testsuite/tests/typing-unboxed/test.ml | 334 +- .../tests/typing-unboxed/test.ocaml.reference | 60 +- ...us_guarded_disjunction.compilers.reference | 163 - .../ambiguous_guarded_disjunction.ml | 254 +- .../application.compilers.reference | 13 - .../tests/typing-warnings/application.ml | 80 +- .../coercions.compilers.principal.reference | 25 - .../coercions.compilers.reference | 17 - testsuite/tests/typing-warnings/coercions.ml | 54 +- .../exhaustiveness.compilers.reference | 152 - .../tests/typing-warnings/exhaustiveness.ml | 248 +- testsuite/tests/typing-warnings/ocamltests | 2 + .../tests/typing-warnings/open_warnings.ml | 179 + .../pr5892.compilers.reference | 11 - testsuite/tests/typing-warnings/pr5892.ml | 18 +- .../pr6587.compilers.reference | 16 - testsuite/tests/typing-warnings/pr6587.ml | 23 +- .../pr6872.compilers.principal.reference | 38 - .../pr6872.compilers.reference | 34 - testsuite/tests/typing-warnings/pr6872.ml | 92 +- .../pr7085.compilers.reference | 19 - testsuite/tests/typing-warnings/pr7085.ml | 24 +- .../pr7115.compilers.reference | 21 - testsuite/tests/typing-warnings/pr7115.ml | 30 +- .../pr7261.compilers.reference | 12 +- .../pr7297.compilers.reference | 2 +- testsuite/tests/typing-warnings/pr7297.ml | 12 +- .../pr7553.compilers.reference | 19 - testsuite/tests/typing-warnings/pr7553.ml | 29 +- .../records.compilers.principal.reference | 320 - .../records.compilers.reference | 312 - testsuite/tests/typing-warnings/records.ml | 466 +- testsuite/tests/typing-warnings/unused_rec.ml | 49 + .../unused_types.compilers.reference | 57 - .../tests/typing-warnings/unused_types.ml | 109 +- .../tests/unboxed-primitive-args/Makefile | 40 - .../tests/unboxed-primitive-args/common.ml | 2 +- .../tests/unboxed-primitive-args/ocamltests | 1 + .../tests/unboxed-primitive-args/test.ml | 22 + .../unboxed-primitive-args/test.reference | 0 testsuite/tests/unwind/Makefile | 41 - .../tests/unwind/check-linker-version.sh | 16 + testsuite/tests/unwind/driver.ml | 20 + testsuite/tests/unwind/ocamltests | 1 + testsuite/tests/utils/edit_distance.ml | 4 +- testsuite/tests/utils/overflow_detection.ml | 4 +- .../test_strongly_connected_components.ml | 6 +- .../deprecated_module.compilers.reference | 8 +- ...cated_module_assigment.compilers.reference | 132 +- .../deprecated_module_use.compilers.reference | 20 +- testsuite/tests/warnings/ocamltests | 1 + .../tests/warnings/w01.compilers.reference | 16 +- .../tests/warnings/w03.compilers.reference | 8 + testsuite/tests/warnings/w03.ml | 24 + .../tests/warnings/w04.compilers.reference | 3 + testsuite/tests/warnings/w04.ml | 2 +- .../warnings/w04_failure.compilers.reference | 12 + .../tests/warnings/w06.compilers.reference | 4 + .../tests/warnings/w32.compilers.reference | 37 + .../tests/warnings/w32b.compilers.reference | 2 + .../tests/warnings/w33.compilers.reference | 8 + testsuite/tests/warnings/w33.ml | 2 +- .../tests/warnings/w45.compilers.reference | 6 + .../warnings/w47_inline.compilers.reference | 37 +- testsuite/tests/warnings/w47_inline.ml | 16 + .../tests/warnings/w50.compilers.reference | 4 + .../tests/warnings/w51.compilers.reference | 2 + .../warnings/w51_bis.compilers.reference | 2 + .../tests/warnings/w52.compilers.reference | 12 - testsuite/tests/warnings/w52.ml | 99 +- .../tests/warnings/w53.compilers.reference | 26 + .../tests/warnings/w54.compilers.reference | 8 + .../tests/warnings/w55.flambda.reference | 6 + testsuite/tests/warnings/w55.native.reference | 12 + .../tests/warnings/w59.flambda.reference | 10 + testsuite/tests/win-unicode/Makefile | 34 - testsuite/tests/win-unicode/exec_tests.ml | 63 - .../tests/win-unicode/exec_tests.precheck | 3 - .../tests/win-unicode/exec_tests.reference | 6 - testsuite/tests/win-unicode/mkfiles.c | 38 - .../win-unicode/mltest.compilers.reference | 83 + testsuite/tests/win-unicode/mltest.ml | 511 +- testsuite/tests/win-unicode/mltest.reference | 360 - testsuite/tests/win-unicode/ocamltests | 1 + testsuite/tests/win-unicode/printargv.c | 25 - testsuite/tests/win-unicode/printenv.c | 36 - testsuite/tests/win-unicode/symlink_tests.ml | 27 - .../tests/win-unicode/symlink_tests.reference | 1 - testsuite/tools/Makefile | 76 +- .../asmgen/amd64.S => tools/asmgen_amd64.S} | 0 .../asmgen/arm.S => tools/asmgen_arm.S} | 0 .../asmgen/arm64.S => tools/asmgen_arm64.S} | 0 testsuite/tools/asmgen_i386.S | 72 + testsuite/tools/asmgen_i386nt.asm | 71 + .../asmgen/power.S => tools/asmgen_power.S} | 0 .../asmgen/s390x.S => tools/asmgen_s390x.S} | 0 testsuite/tools/codegen_main.ml | 81 + testsuite/tools/expect_test.ml | 43 +- testsuite/tools/lexcmm.mli | 25 + testsuite/tools/lexcmm.mll | 259 + testsuite/tools/parsecmm.mly | 385 + testsuite/tools/parsecmmaux.ml | 58 + testsuite/tools/parsecmmaux.mli | 31 + tools/.depend | 296 +- tools/Makefile | 202 +- tools/Makefile.nt | 16 - tools/caml_tex.ml | 761 + tools/check-parser-uptodate-or-warn.sh | 56 + tools/check-symbol-names | 2 +- tools/check-typo | 220 +- tools/check-typo-since | 37 + tools/ci/appveyor/appveyor_build.cmd | 47 +- tools/ci/appveyor/appveyor_build.sh | 114 +- tools/ci/inria/bootstrap | 245 + tools/ci/inria/extra-checks | 233 + tools/ci/inria/lsan-suppr.txt | 2 + tools/ci/inria/main | 72 +- tools/ci/inria/other-configs | 8 +- tools/ci/inria/remove-sinh-primitive.patch | 103 + tools/ci/inria/tsan-suppr.txt | 6 + tools/ci/travis/travis-ci.sh | 143 +- tools/cmt2annot.ml | 9 +- tools/dumpobj.ml | 5 +- tools/dune | 25 + tools/eqparsetree.ml | 16 +- tools/lintapidiff.ml | 7 +- tools/markdown-add-pr-links.sh | 34 + tools/msvs-promote-path | 2 +- tools/objinfo.ml | 40 +- tools/ocaml-instr-graph | 2 +- tools/ocaml-objcopy-macosx | 2 +- tools/ocamlcp.ml | 10 + tools/ocamlmklib.ml | 75 +- tools/ocamloptp.ml | 10 +- tools/ocamlprof.ml | 18 +- tools/pre-commit-githook | 85 + tools/primreq.ml | 13 +- tools/release-checklist | 386 + tools/scrapelabels.ml | 6 +- toplevel/dune | 98 + toplevel/expunge.ml | 15 +- toplevel/genprintval.ml | 53 +- toplevel/genprintval.mli | 2 +- toplevel/opttopdirs.ml | 28 +- toplevel/opttoploop.ml | 126 +- toplevel/opttoploop.mli | 26 +- toplevel/opttopmain.ml | 34 +- toplevel/topdirs.ml | 94 +- toplevel/toploop.ml | 144 +- toplevel/toploop.mli | 27 +- toplevel/topmain.ml | 29 +- typing/TODO.md | 79 + typing/btype.ml | 177 +- typing/btype.mli | 25 +- typing/cmi_format.ml | 2 +- typing/cmi_format.mli | 2 +- typing/cmt_format.ml | 50 +- typing/ctype.ml | 879 +- typing/ctype.mli | 112 +- typing/datarepr.ml | 9 +- typing/env.ml | 1534 +- typing/env.mli | 123 +- typing/envaux.ml | 27 +- typing/ident.ml | 248 +- typing/ident.mli | 43 +- typing/includeclass.ml | 10 +- typing/includecore.ml | 135 +- typing/includecore.mli | 6 +- typing/includemod.ml | 277 +- typing/includemod.mli | 9 +- typing/mtype.ml | 382 +- typing/mtype.mli | 13 +- typing/oprint.ml | 64 +- typing/oprint.mli | 1 + typing/outcometree.mli | 8 +- typing/parmatch.ml | 63 +- typing/parmatch.mli | 9 +- typing/path.ml | 62 +- typing/path.mli | 14 +- typing/predef.ml | 41 +- typing/primitive.ml | 13 +- typing/printpat.ml | 2 + typing/printtyp.ml | 924 +- typing/printtyp.mli | 65 +- typing/printtyped.ml | 125 +- typing/rec_check.ml | 1244 + typing/rec_check.mli | 19 + typing/stypes.ml | 2 +- typing/subst.ml | 446 +- typing/subst.mli | 27 +- typing/tast_mapper.ml | 105 +- typing/tast_mapper.mli | 9 +- typing/typeclass.ml | 158 +- typing/typeclass.mli | 19 +- typing/typecore.ml | 2397 +- typing/typecore.mli | 53 +- typing/typedecl.ml | 717 +- typing/typedecl.mli | 33 +- typing/typedecl_immediacy.ml | 62 + typing/typedecl_immediacy.mli | 27 + typing/typedecl_properties.ml | 73 + typing/typedecl_properties.mli | 55 + typing/typedecl_unboxed.ml | 49 + typing/typedecl_unboxed.mli | 4 + typing/typedecl_variance.ml | 372 + typing/typedecl_variance.mli | 56 + typing/typedtree.ml | 146 +- typing/typedtree.mli | 116 +- typing/typedtreeIter.ml | 55 +- typing/typedtreeIter.mli | 2 + typing/typedtreeMap.ml | 732 - typing/typedtreeMap.mli | 94 - typing/typemod.ml | 1507 +- typing/typemod.mli | 60 +- typing/typeopt.ml | 10 +- typing/typeopt.mli | 6 + typing/types.ml | 71 +- typing/types.mli | 50 +- typing/typetexp.ml | 185 +- typing/typetexp.mli | 8 +- typing/untypeast.ml | 146 +- typing/untypeast.mli | 6 + utils/HACKING.adoc | 60 + utils/Makefile | 93 + utils/arg_helper.mli | 5 + utils/build_path_prefix_map.ml | 15 + utils/build_path_prefix_map.mli | 23 + utils/ccomp.ml | 24 +- utils/ccomp.mli | 10 +- utils/clflags.ml | 88 +- utils/clflags.mli | 30 +- utils/config.mli | 238 +- utils/config.mlp | 75 +- utils/consistbl.mli | 7 +- utils/dune | 21 + utils/identifiable.ml | 4 +- utils/identifiable.mli | 11 +- utils/load_path.ml | 89 + utils/load_path.mli | 67 + utils/misc.ml | 216 +- utils/misc.mli | 133 +- utils/numbers.ml | 2 +- utils/numbers.mli | 7 +- utils/profile.ml | 15 +- utils/profile.mli | 7 +- utils/strongly_connected_components.mli | 7 +- utils/targetint.ml | 6 + utils/targetint.mli | 23 +- utils/tbl.ml | 123 - utils/tbl.mli | 34 - utils/terminfo.ml | 2 +- utils/terminfo.mli | 7 +- utils/warnings.ml | 219 +- utils/warnings.mli | 29 +- yacc/Makefile | 28 +- yacc/Makefile.nt | 16 - yacc/reader.c | 2 +- 2072 files changed, 203675 insertions(+), 76117 deletions(-) create mode 100644 .depend.menhir delete mode 100644 .merlin create mode 100644 BOOTSTRAP.adoc delete mode 100644 Makefile.common create mode 100644 Makefile.common.in create mode 100644 Makefile.config.in create mode 100644 Makefile.menhir delete mode 100644 Makefile.nt create mode 100644 News create mode 100644 aclocal.m4 create mode 100644 asmcomp/backend_var.ml create mode 100644 asmcomp/backend_var.mli create mode 100644 asmcomp/dune delete mode 100644 asmrun/.depend delete mode 100644 asmrun/Makefile delete mode 100644 asmrun/Makefile.nt delete mode 100644 asmrun/amd64.S delete mode 100644 asmrun/amd64nt.asm delete mode 100644 asmrun/arm64.S delete mode 100644 asmrun/backtrace_prim.c delete mode 100644 asmrun/clambda_checks.c delete mode 100644 asmrun/fail.c delete mode 100644 asmrun/roots.c delete mode 100644 asmrun/signals_asm.c delete mode 100644 asmrun/spacetime.c delete mode 100644 asmrun/startup.c create mode 100755 autogen create mode 100644 boot/menhir/menhirLib.ml create mode 100644 boot/menhir/menhirLib.mli create mode 100644 boot/menhir/parser.ml create mode 100644 boot/menhir/parser.mli create mode 100644 build-aux/ax_func_which_gethostbyname_r.m4 create mode 100644 build-aux/ax_pthread.m4 create mode 100755 build-aux/compile create mode 100755 build-aux/config.guess create mode 100755 build-aux/config.sub create mode 100755 build-aux/install-sh create mode 100644 build-aux/libtool.m4 create mode 100644 build-aux/ltmain.sh create mode 100644 build-aux/ltoptions.m4 create mode 100644 build-aux/ltsugar.m4 create mode 100644 build-aux/ltversion.m4 create mode 100644 build-aux/lt~obsolete.m4 create mode 100755 build-aux/missing create mode 100644 bytecomp/dune create mode 100755 bytecomp/generate_runtimedef.sh delete mode 100644 byterun/.depend delete mode 100644 byterun/Makefile delete mode 100644 byterun/Makefile.nt delete mode 100644 byterun/alloc.c delete mode 100644 byterun/array.c delete mode 100644 byterun/backtrace.c delete mode 100644 byterun/backtrace_prim.c delete mode 100644 byterun/bigarray.c delete mode 100644 byterun/caml/backtrace.h delete mode 100644 byterun/caml/backtrace_prim.h delete mode 100644 byterun/caml/compatibility.h delete mode 100644 byterun/caml/config.h delete mode 100644 byterun/caml/custom.h delete mode 100644 byterun/caml/exec.h delete mode 100644 byterun/caml/finalise.h delete mode 100644 byterun/caml/gc.h delete mode 100644 byterun/caml/gc_ctrl.h delete mode 100644 byterun/caml/instrtrace.h delete mode 100644 byterun/caml/intext.h delete mode 100644 byterun/caml/memory.h delete mode 100644 byterun/caml/minor_gc.h delete mode 100644 byterun/caml/misc.h delete mode 100644 byterun/caml/osdeps.h delete mode 100644 byterun/caml/signals.h delete mode 100644 byterun/caml/stack.h delete mode 100644 byterun/caml/startup.h delete mode 100644 byterun/caml/startup_aux.h delete mode 100644 byterun/caml/sys.h delete mode 100644 byterun/caml/weak.h delete mode 100644 byterun/compact.c delete mode 100644 byterun/compare.c delete mode 100644 byterun/custom.c delete mode 100644 byterun/debugger.c delete mode 100644 byterun/dynlink.c delete mode 100644 byterun/extern.c delete mode 100644 byterun/fail.c delete mode 100644 byterun/fix_code.c delete mode 100644 byterun/floats.c delete mode 100644 byterun/freelist.c delete mode 100644 byterun/gc_ctrl.c delete mode 100644 byterun/instrtrace.c delete mode 100644 byterun/intern.c delete mode 100644 byterun/interp.c delete mode 100644 byterun/ints.c delete mode 100644 byterun/io.c delete mode 100644 byterun/major_gc.c delete mode 100644 byterun/memory.c delete mode 100644 byterun/meta.c delete mode 100644 byterun/minor_gc.c delete mode 100644 byterun/misc.c delete mode 100644 byterun/printexc.c delete mode 100644 byterun/roots.c delete mode 100644 byterun/signals.c delete mode 100644 byterun/startup.c delete mode 100644 byterun/startup_aux.c delete mode 100644 byterun/str.c delete mode 100644 byterun/sys.c delete mode 100644 byterun/unix.c delete mode 100644 byterun/weak.c delete mode 100644 byterun/win32.c delete mode 100644 config/Makefile-templ create mode 100644 config/auto-aux/simple.S delete mode 100644 config/m-templ.h delete mode 100644 config/s-templ.h create mode 100644 configure.ac delete mode 100644 debugger/Makefile.nt create mode 100644 debugger/dune delete mode 100644 driver/compdynlink.mlno create mode 100755 driver/compify_dynlink.sh create mode 100644 driver/compile_common.ml create mode 100644 driver/compile_common.mli create mode 100644 driver/dune create mode 100644 dune create mode 100644 dune-project delete mode 100644 emacs/COPYING delete mode 100644 emacs/Makefile delete mode 100644 emacs/README delete mode 100644 emacs/README.itz delete mode 100644 emacs/caml-compat.el delete mode 100644 emacs/caml-emacs.el delete mode 100644 emacs/caml-font-old.el delete mode 100644 emacs/caml-font.el delete mode 100644 emacs/caml-help.el delete mode 100644 emacs/caml-hilit.el delete mode 100644 emacs/caml-types.el delete mode 100644 emacs/caml-xemacs.el delete mode 100644 emacs/caml.el delete mode 100644 emacs/camldebug.el delete mode 100644 emacs/inf-caml.el delete mode 100644 emacs/ocamltags.in delete mode 100644 lex/Makefile.nt delete mode 100644 manual/manual/library/.cvsignore create mode 100644 manual/manual/library/compiler_libs.mld delete mode 100644 manual/manual/pdfmanual.tex delete mode 100644 manual/manual/plaintext.tex delete mode 100644 manual/manual/refman/.cvsignore delete mode 100644 manual/manual/texstuff/.cvsignore delete mode 100644 manual/manual/textman/.cvsignore delete mode 100644 manual/manual/tutorials/.cvsignore delete mode 100644 manual/styles/plaintext.sty create mode 100644 manual/tests/.gitignore delete mode 100644 manual/tools/.ignore delete mode 100755 manual/tools/caml-tex delete mode 100644 manual/tools/caml_tex2.ml delete mode 100644 manual/tools/dvi_to_txt/Makefile delete mode 100644 manual/tools/dvi_to_txt/dvi.h delete mode 100644 manual/tools/dvi_to_txt/interp.c delete mode 100644 manual/tools/dvi_to_txt/io.c delete mode 100644 manual/tools/dvi_to_txt/io.h delete mode 100644 manual/tools/dvi_to_txt/main.c delete mode 100644 manual/tools/dvi_to_txt/output.c delete mode 100644 manual/tools/dvi_to_txt/output.h delete mode 100644 manual/tools/dvi_to_txt/print.c delete mode 100644 manual/tools/dvi_to_txt/print_rtf.c delete mode 100644 manual/tools/dvi_to_txt/print_styl.c delete mode 100755 manual/tools/format-intf delete mode 100755 manual/tools/htmlcut delete mode 100644 manual/tools/htmlquote.c delete mode 100755 manual/tools/htmltbl delete mode 100755 manual/tools/htmlthread delete mode 100644 manual/tools/latexmacros.ml delete mode 100644 manual/tools/latexmacros.mli delete mode 100644 manual/tools/latexmain.ml delete mode 100644 manual/tools/latexscan.mll delete mode 100755 manual/tools/texexpand delete mode 100644 manual/tools/texquote2.c create mode 100644 manual/tools/texquote2.ml create mode 100644 middle_end/int_replace_polymorphic_compare.ml create mode 100644 middle_end/int_replace_polymorphic_compare.mli create mode 100644 ocaml-variants.opam create mode 100644 ocamldoc/Makefile.docfiles delete mode 100644 ocamldoc/Makefile.nt delete mode 100644 ocamldoc/Makefile.unprefix create mode 100644 ocamldoc/dune delete mode 100644 ocamldoc/stdlib_non_prefixed/.depend delete mode 100644 ocamldoc/stdlib_non_prefixed/Makefile delete mode 100644 ocamldoc/stdlib_non_prefixed/extract_pervasives.awk create mode 100644 ocamltest/dune create mode 100644 otherlibs/Makefile.otherlibs.common delete mode 100644 otherlibs/bigarray/Makefile.nt rename testsuite/tests/letrec/allowed.reference => otherlibs/bigarray/empty.c (100%) delete mode 100644 otherlibs/dynlink/Makefile.nt create mode 100644 otherlibs/dynlink/dune create mode 100644 otherlibs/dynlink/dynlink_common.ml create mode 100644 otherlibs/dynlink/dynlink_common.mli create mode 100644 otherlibs/dynlink/dynlink_platform_intf.ml create mode 100644 otherlibs/dynlink/dynlink_types.ml create mode 100644 otherlibs/dynlink/dynlink_types.mli create mode 100644 otherlibs/dynlink/nodynlink.ml delete mode 100644 otherlibs/raw_spacetime_lib/Makefile.nt delete mode 100644 otherlibs/str/Makefile.nt create mode 100644 otherlibs/str/dune delete mode 100644 otherlibs/systhreads/Makefile.nt create mode 100644 otherlibs/unix/channels.c create mode 100644 otherlibs/unix/dune create mode 100644 otherlibs/unix/fsync.c delete mode 100644 otherlibs/win32graph/Makefile.nt delete mode 100644 otherlibs/win32unix/Makefile.nt create mode 100644 parsing/CONFLICTS.md create mode 100644 parsing/VIPs.md create mode 100644 parsing/dune create mode 100644 runtime/.depend create mode 100644 runtime/Makefile rename {byterun => runtime}/afl.c (100%) create mode 100644 runtime/alloc.c create mode 100644 runtime/amd64.S create mode 100644 runtime/amd64nt.asm rename {asmrun => runtime}/arm.S (100%) create mode 100644 runtime/arm64.S create mode 100644 runtime/array.c create mode 100644 runtime/backtrace.c create mode 100644 runtime/backtrace_byt.c create mode 100644 runtime/backtrace_nat.c create mode 100644 runtime/bigarray.c rename {byterun => runtime}/callback.c (100%) rename {byterun => runtime}/caml/address_class.h (100%) rename {byterun => runtime}/caml/alloc.h (100%) create mode 100644 runtime/caml/backtrace.h create mode 100644 runtime/caml/backtrace_prim.h rename {byterun => runtime}/caml/bigarray.h (100%) rename {byterun => runtime}/caml/callback.h (100%) rename {byterun => runtime}/caml/compact.h (100%) rename {byterun => runtime}/caml/compare.h (100%) create mode 100644 runtime/caml/compatibility.h create mode 100644 runtime/caml/config.h create mode 100644 runtime/caml/custom.h rename {byterun => runtime}/caml/debugger.h (100%) create mode 100644 runtime/caml/dune rename {byterun => runtime}/caml/dynlink.h (100%) create mode 100644 runtime/caml/exec.h rename {byterun => runtime}/caml/fail.h (100%) create mode 100644 runtime/caml/finalise.h rename {byterun => runtime}/caml/fix_code.h (100%) rename {byterun => runtime}/caml/freelist.h (100%) create mode 100644 runtime/caml/gc.h create mode 100644 runtime/caml/gc_ctrl.h rename {byterun => runtime}/caml/globroots.h (100%) rename {byterun => runtime}/caml/hash.h (100%) rename {byterun => runtime}/caml/hooks.h (100%) create mode 100644 runtime/caml/instrtrace.h rename {byterun => runtime}/caml/instruct.h (100%) rename {byterun => runtime}/caml/int64_emul.h (100%) rename {byterun => runtime}/caml/int64_format.h (100%) rename {byterun => runtime}/caml/int64_native.h (100%) rename {byterun => runtime}/caml/interp.h (100%) create mode 100644 runtime/caml/intext.h rename {byterun => runtime}/caml/io.h (100%) create mode 100644 runtime/caml/m.h.in rename {byterun => runtime}/caml/major_gc.h (100%) rename {byterun => runtime}/caml/md5.h (100%) create mode 100644 runtime/caml/memory.h create mode 100644 runtime/caml/minor_gc.h create mode 100644 runtime/caml/misc.h rename {byterun => runtime}/caml/mlvalues.h (100%) create mode 100644 runtime/caml/osdeps.h rename {byterun => runtime}/caml/prims.h (100%) rename {byterun => runtime}/caml/printexc.h (100%) rename {byterun => runtime}/caml/reverse.h (100%) rename {byterun => runtime}/caml/roots.h (100%) create mode 100644 runtime/caml/s.h.in create mode 100644 runtime/caml/signals.h rename {byterun => runtime}/caml/signals_machdep.h (100%) rename {byterun => runtime}/caml/spacetime.h (100%) create mode 100644 runtime/caml/stack.h rename {byterun => runtime}/caml/stacks.h (100%) create mode 100644 runtime/caml/startup.h create mode 100644 runtime/caml/startup_aux.h create mode 100644 runtime/caml/sys.h rename {byterun => runtime}/caml/ui.h (100%) create mode 100644 runtime/caml/weak.h create mode 100644 runtime/clambda_checks.c create mode 100644 runtime/compact.c create mode 100644 runtime/compare.c create mode 100644 runtime/custom.c create mode 100644 runtime/debugger.c create mode 100644 runtime/dune create mode 100644 runtime/dynlink.c rename asmrun/natdynlink.c => runtime/dynlink_nat.c (100%) create mode 100644 runtime/extern.c create mode 100644 runtime/fail_byt.c create mode 100644 runtime/fail_nat.c rename {byterun => runtime}/finalise.c (100%) create mode 100644 runtime/fix_code.c create mode 100644 runtime/floats.c create mode 100644 runtime/freelist.c create mode 100644 runtime/gc_ctrl.c create mode 100755 runtime/gen_primitives.sh rename {byterun => runtime}/globroots.c (100%) rename {byterun => runtime}/hash.c (100%) rename {asmrun => runtime}/i386.S (100%) rename {asmrun => runtime}/i386nt.asm (100%) create mode 100644 runtime/instrtrace.c create mode 100644 runtime/intern.c create mode 100644 runtime/interp.c create mode 100644 runtime/ints.c create mode 100644 runtime/io.c rename {byterun => runtime}/lexing.c (100%) rename {byterun => runtime}/main.c (100%) create mode 100644 runtime/major_gc.c rename {byterun => runtime}/md5.c (100%) create mode 100644 runtime/memory.c create mode 100644 runtime/meta.c create mode 100644 runtime/minor_gc.c create mode 100644 runtime/misc.c rename {byterun => runtime}/obj.c (100%) rename {byterun => runtime}/parsing.c (100%) rename {asmrun => runtime}/power.S (100%) create mode 100644 runtime/printexc.c create mode 100644 runtime/roots_byt.c create mode 100644 runtime/roots_nat.c rename {asmrun => runtime}/s390x.S (100%) create mode 100644 runtime/signals.c rename {byterun => runtime}/signals_byt.c (100%) create mode 100644 runtime/signals_nat.c rename {asmrun => runtime}/signals_osdep.h (100%) rename byterun/spacetime.c => runtime/spacetime_byt.c (100%) create mode 100644 runtime/spacetime_nat.c rename {asmrun => runtime}/spacetime_snapshot.c (100%) rename {byterun => runtime}/stacks.c (100%) create mode 100644 runtime/startup_aux.c create mode 100644 runtime/startup_byt.c create mode 100644 runtime/startup_nat.c create mode 100644 runtime/str.c create mode 100644 runtime/sys.c create mode 100644 runtime/unix.c create mode 100644 runtime/weak.c create mode 100644 runtime/win32.c create mode 100644 stdlib/HACKING.adoc delete mode 100644 stdlib/Makefile.nt create mode 100644 stdlib/bool.ml create mode 100644 stdlib/bool.mli create mode 100644 stdlib/dune create mode 100644 stdlib/fun.ml create mode 100644 stdlib/fun.mli create mode 100644 stdlib/int.ml create mode 100644 stdlib/int.mli create mode 100644 stdlib/ocaml_operators.mld create mode 100644 stdlib/option.ml create mode 100644 stdlib/option.mli create mode 100644 stdlib/pervasives.ml create mode 100644 stdlib/result.ml create mode 100644 stdlib/result.mli delete mode 100644 stdlib/sort.ml delete mode 100644 stdlib/sort.mli create mode 100644 stdlib/unit.ml create mode 100644 stdlib/unit.mli delete mode 100644 testsuite/makefiles/Makefile.dlambda delete mode 100644 testsuite/makefiles/Makefile.dparsetree delete mode 100644 testsuite/makefiles/Makefile.expect delete mode 100644 testsuite/makefiles/Makefile.okbad delete mode 100644 testsuite/makefiles/Makefile.several delete mode 100644 testsuite/makefiles/Makefile.toplevel delete mode 100644 testsuite/tests/asmgen/Makefile create mode 100644 testsuite/tests/asmgen/catch-float.cmm create mode 100644 testsuite/tests/asmgen/catch-try-float.cmm create mode 100644 testsuite/tests/asmgen/even-odd-spill-float.cmm delete mode 100644 testsuite/tests/asmgen/i386.S delete mode 100644 testsuite/tests/asmgen/i386nt.asm delete mode 100644 testsuite/tests/asmgen/lexcmm.mli delete mode 100644 testsuite/tests/asmgen/lexcmm.mll delete mode 100644 testsuite/tests/asmgen/main.ml create mode 100644 testsuite/tests/asmgen/ocamltests delete mode 100644 testsuite/tests/asmgen/parsecmm.mly delete mode 100644 testsuite/tests/asmgen/parsecmmaux.ml delete mode 100644 testsuite/tests/asmgen/parsecmmaux.mli create mode 100644 testsuite/tests/backtrace/backtrace_or_exception.byte.reference create mode 100644 testsuite/tests/backtrace/backtrace_or_exception.ml create mode 100644 testsuite/tests/backtrace/backtrace_or_exception.opt.reference create mode 100644 testsuite/tests/backtrace/callstack.ml create mode 100644 testsuite/tests/backtrace/callstack.reference rename testsuite/tests/{letrec/backreferences.reference => backtrace/pr6920_why_at.native.reference} (100%) rename testsuite/tests/{letrec/class_1.reference => backtrace/pr6920_why_swallow.native.reference} (100%) create mode 100644 testsuite/tests/basic/camlCase.ml delete mode 100644 testsuite/tests/basic/constprop.ml create mode 100644 testsuite/tests/basic/constprop.ml.c rename testsuite/tests/basic/{constprop.reference => constprop.ml.reference} (100%) create mode 100755 testsuite/tests/basic/localfunction.ml create mode 100755 testsuite/tests/basic/localfunction.reference create mode 100644 testsuite/tests/basic/patmatch_incoherence.ml create mode 100644 testsuite/tests/basic/unit_naming.compilers.reference create mode 100644 testsuite/tests/basic/unit_naming.ml create mode 100644 testsuite/tests/compiler-libs/ocamltests create mode 100644 testsuite/tests/compiler-libs/test_longident.ml create mode 100644 testsuite/tests/ephe-c-api/ocamltests create mode 100644 testsuite/tests/ephe-c-api/stubs.c create mode 100644 testsuite/tests/ephe-c-api/test.ml create mode 100644 testsuite/tests/ephe-c-api/test.reference create mode 100644 testsuite/tests/flambda/gpr2239.ml create mode 100644 testsuite/tests/flambda/gpr2239.reference create mode 100644 testsuite/tests/float-unboxing/unbox_under_assign.ml create mode 100644 testsuite/tests/fma/fma.ml create mode 100644 testsuite/tests/fma/fma.reference create mode 100644 testsuite/tests/fma/ocamltests create mode 100644 testsuite/tests/formatting/errors_batch.ml create mode 100644 testsuite/tests/formatting/errors_batch.reference create mode 100644 testsuite/tests/generalized-open/accepted_batch.ml create mode 100644 testsuite/tests/generalized-open/accepted_batch.reference create mode 100644 testsuite/tests/generalized-open/accepted_expect.ml create mode 100644 testsuite/tests/generalized-open/expansiveness.ml create mode 100644 testsuite/tests/generalized-open/funct_body.compilers.reference create mode 100644 testsuite/tests/generalized-open/funct_body.ml create mode 100644 testsuite/tests/generalized-open/gpr1506.ml create mode 100644 testsuite/tests/generalized-open/ocamltests create mode 100644 testsuite/tests/generalized-open/shadowing.ml create mode 100644 testsuite/tests/let-syntax/let_syntax.ml create mode 100644 testsuite/tests/let-syntax/ocamltests create mode 100644 testsuite/tests/letrec-check/basic.ml create mode 100644 testsuite/tests/letrec-check/extension_constructor.ml create mode 100644 testsuite/tests/letrec-check/flat_float_array.ml create mode 100644 testsuite/tests/letrec-check/float_unboxing.ml create mode 100644 testsuite/tests/letrec-check/labels.ml create mode 100644 testsuite/tests/letrec-check/lazy_.ml create mode 100644 testsuite/tests/letrec-check/modules.ml create mode 100644 testsuite/tests/letrec-check/no_flat_float_array.ml create mode 100644 testsuite/tests/letrec-check/objects.ml create mode 100644 testsuite/tests/letrec-check/ocamltests rename testsuite/tests/{letrec-disallowed => letrec-check}/pr7215.ml (100%) create mode 100644 testsuite/tests/letrec-check/pr7215.ocaml.reference create mode 100644 testsuite/tests/letrec-check/pr7231.ml create mode 100644 testsuite/tests/letrec-check/pr7231.ocaml.reference rename testsuite/tests/{letrec-disallowed => letrec-check}/pr7706.ml (100%) create mode 100644 testsuite/tests/letrec-check/pr7706.ocaml.reference create mode 100644 testsuite/tests/letrec-check/records.ml create mode 100644 testsuite/tests/letrec-check/unboxed.ml rename testsuite/tests/{letrec => letrec-compilation}/backreferences.ml (100%) rename testsuite/tests/{letrec/generic_array.reference => letrec-compilation/backreferences.reference} (100%) rename testsuite/tests/{letrec => letrec-compilation}/class_1.ml (100%) rename testsuite/tests/{letrec/labels.reference => letrec-compilation/class_1.reference} (100%) rename testsuite/tests/{letrec => letrec-compilation}/class_2.ml (100%) rename testsuite/tests/{letrec => letrec-compilation}/class_2.reference (100%) rename testsuite/tests/{letrec => letrec-compilation}/evaluation_order_1.ml (100%) rename testsuite/tests/{letrec => letrec-compilation}/evaluation_order_1.reference (100%) rename testsuite/tests/{letrec => letrec-compilation}/evaluation_order_2.ml (100%) rename testsuite/tests/{letrec => letrec-compilation}/evaluation_order_2.reference (100%) rename testsuite/tests/{letrec => letrec-compilation}/evaluation_order_3.ml (100%) rename testsuite/tests/{letrec => letrec-compilation}/evaluation_order_3.reference (100%) rename testsuite/tests/{letrec => letrec-compilation}/float_block_1.ml (100%) rename testsuite/tests/{letrec => letrec-compilation}/float_block_1.reference (100%) rename testsuite/tests/{letrec => letrec-compilation}/generic_array.ml (100%) rename testsuite/tests/{letrec/lists.reference => letrec-compilation/generic_array.reference} (100%) rename testsuite/tests/{letrec => letrec-compilation}/labels.ml (100%) rename testsuite/tests/{letrec/mixing_value_closures_1.reference => letrec-compilation/labels.reference} (100%) rename testsuite/tests/{letrec => letrec-compilation}/lazy_.ml (100%) rename testsuite/tests/{letrec => letrec-compilation}/lazy_.reference (100%) rename testsuite/tests/{letrec => letrec-compilation}/lists.ml (100%) rename testsuite/tests/{letrec/mixing_value_closures_2.reference => letrec-compilation/lists.reference} (100%) rename testsuite/tests/{letrec => letrec-compilation}/mixing_value_closures_1.ml (100%) rename testsuite/tests/{letrec/mutual_functions.reference => letrec-compilation/mixing_value_closures_1.reference} (100%) rename testsuite/tests/{letrec => letrec-compilation}/mixing_value_closures_2.ml (100%) rename testsuite/tests/{letrec/nested.reference => letrec-compilation/mixing_value_closures_2.reference} (100%) rename testsuite/tests/{letrec => letrec-compilation}/mutual_functions.ml (100%) rename testsuite/tests/{letrec/pr4989.reference => letrec-compilation/mutual_functions.reference} (100%) rename testsuite/tests/{letrec => letrec-compilation}/nested.ml (100%) rename testsuite/tests/{letrec/ref.reference => letrec-compilation/nested.reference} (100%) create mode 100644 testsuite/tests/letrec-compilation/ocamltests rename testsuite/tests/{letrec => letrec-compilation}/pr4989.ml (100%) rename testsuite/tests/{unboxed-primitive-args/main.reference => letrec-compilation/pr4989.reference} (100%) rename testsuite/tests/{letrec => letrec-compilation}/record_with.ml (100%) rename testsuite/tests/{letrec => letrec-compilation}/record_with.reference (100%) create mode 100644 testsuite/tests/letrec-compilation/ref.ml create mode 100644 testsuite/tests/letrec-compilation/ref.reference delete mode 100644 testsuite/tests/letrec-disallowed/disallowed.ml delete mode 100644 testsuite/tests/letrec-disallowed/disallowed.ocaml.reference delete mode 100644 testsuite/tests/letrec-disallowed/extension_constructor.ml delete mode 100644 testsuite/tests/letrec-disallowed/extension_constructor.ocaml.reference delete mode 100644 testsuite/tests/letrec-disallowed/float_block_allowed.ml delete mode 100644 testsuite/tests/letrec-disallowed/float_block_allowed.ocaml.reference delete mode 100644 testsuite/tests/letrec-disallowed/float_block_disallowed.ml delete mode 100644 testsuite/tests/letrec-disallowed/float_block_disallowed.ocaml.reference delete mode 100644 testsuite/tests/letrec-disallowed/generic_arrays.ml delete mode 100644 testsuite/tests/letrec-disallowed/generic_arrays.ocaml.reference delete mode 100644 testsuite/tests/letrec-disallowed/labels.ml delete mode 100644 testsuite/tests/letrec-disallowed/labels.ocaml.reference delete mode 100644 testsuite/tests/letrec-disallowed/lazy_.ml delete mode 100644 testsuite/tests/letrec-disallowed/lazy_.ocaml.reference delete mode 100644 testsuite/tests/letrec-disallowed/module_constraints.ml delete mode 100644 testsuite/tests/letrec-disallowed/module_constraints.ocaml.reference delete mode 100644 testsuite/tests/letrec-disallowed/ocamltests delete mode 100644 testsuite/tests/letrec-disallowed/pr7215.ocaml.reference delete mode 100644 testsuite/tests/letrec-disallowed/pr7231.ml delete mode 100644 testsuite/tests/letrec-disallowed/pr7231.ocaml.reference delete mode 100644 testsuite/tests/letrec-disallowed/pr7706.ocaml.reference delete mode 100644 testsuite/tests/letrec-disallowed/unboxed.ml delete mode 100644 testsuite/tests/letrec-disallowed/unboxed.ocaml.reference delete mode 100644 testsuite/tests/letrec/allowed.ml delete mode 100644 testsuite/tests/letrec/ocamltests delete mode 100644 testsuite/tests/letrec/ref.ml create mode 100644 testsuite/tests/lexing/escape.ml create mode 100644 testsuite/tests/lexing/escape.ocaml.reference delete mode 100644 testsuite/tests/lib-bigarray-2/Makefile create mode 100644 testsuite/tests/lib-bigarray-2/has-gfortran.sh create mode 100644 testsuite/tests/lib-bigarray-2/ocamltests create mode 100644 testsuite/tests/lib-bool/ocamltests create mode 100644 testsuite/tests/lib-bool/test.ml create mode 100644 testsuite/tests/lib-bool/test.reference create mode 100755 testsuite/tests/lib-bytes/binary.ml delete mode 100644 testsuite/tests/lib-dynlink-bytecode/Makefile create mode 100644 testsuite/tests/lib-dynlink-bytecode/ocamltests delete mode 100644 testsuite/tests/lib-dynlink-csharp/Makefile delete mode 100644 testsuite/tests/lib-dynlink-csharp/bytecode.reference mode change 100755 => 100644 testsuite/tests/lib-dynlink-csharp/entry.c create mode 100644 testsuite/tests/lib-dynlink-csharp/main.bytecode.reference mode change 100755 => 100644 testsuite/tests/lib-dynlink-csharp/main.cs mode change 100755 => 100644 testsuite/tests/lib-dynlink-csharp/main.ml create mode 100644 testsuite/tests/lib-dynlink-csharp/main.native.reference delete mode 100644 testsuite/tests/lib-dynlink-csharp/native.reference create mode 100644 testsuite/tests/lib-dynlink-csharp/ocamltests mode change 100755 => 100644 testsuite/tests/lib-dynlink-csharp/plugin.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/ocamltests create mode 100644 testsuite/tests/lib-dynlink-initializers/test1_inited_second.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test1_main.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test1_plugin.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test2_inited_first.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test2_main.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test2_plugin.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test3_main.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test3_plugin_a.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test3_plugin_b.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test4_main.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test4_plugin_a.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test4_plugin_b.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test5_main.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test5_plugin_a.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test5_plugin_b.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test5_second_plugin.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test6_main.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test6_plugin.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test6_second_plugin.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test7_interface_only.mli create mode 100644 testsuite/tests/lib-dynlink-initializers/test7_main.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test7_plugin.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test8_main.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test8_plugin_a.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test8_plugin_b.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test8_plugin_b.mli create mode 100644 testsuite/tests/lib-dynlink-initializers/test9_main.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test9_plugin.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test9_second_plugin.ml create mode 100644 testsuite/tests/lib-dynlink-initializers/test9_second_plugin.mli delete mode 100644 testsuite/tests/lib-dynlink-native/Makefile mode change 100755 => 100644 testsuite/tests/lib-dynlink-native/a.ml mode change 100755 => 100644 testsuite/tests/lib-dynlink-native/b.ml mode change 100755 => 100644 testsuite/tests/lib-dynlink-native/c.ml rename testsuite/tests/lib-dynlink-native/{reference => main.reference} (100%) create mode 100644 testsuite/tests/lib-dynlink-native/ocamltests create mode 100644 testsuite/tests/lib-dynlink-pr4229/abstract.ml create mode 100644 testsuite/tests/lib-dynlink-pr4229/abstract.mli create mode 100644 testsuite/tests/lib-dynlink-pr4229/client.ml create mode 100644 testsuite/tests/lib-dynlink-pr4229/main.ml create mode 100644 testsuite/tests/lib-dynlink-pr4229/main.reference create mode 100644 testsuite/tests/lib-dynlink-pr4229/main_native.ml create mode 100644 testsuite/tests/lib-dynlink-pr4229/ocamltests create mode 100644 testsuite/tests/lib-dynlink-pr4229/static.ml create mode 100644 testsuite/tests/lib-dynlink-pr4229/sub/abstract.ml create mode 100644 testsuite/tests/lib-dynlink-pr4229/sub/abstract.mli create mode 100644 testsuite/tests/lib-dynlink-pr4839/byte.plugin1.reference create mode 100644 testsuite/tests/lib-dynlink-pr4839/byte.plugin2.reference create mode 100644 testsuite/tests/lib-dynlink-pr4839/byte.plugin3.reference create mode 100644 testsuite/tests/lib-dynlink-pr4839/byte.plugin4.reference create mode 100644 testsuite/tests/lib-dynlink-pr4839/host/api.ml create mode 100644 testsuite/tests/lib-dynlink-pr4839/host/api.mli create mode 100644 testsuite/tests/lib-dynlink-pr4839/host/host.ml create mode 100644 testsuite/tests/lib-dynlink-pr4839/native.plugin1.reference create mode 100644 testsuite/tests/lib-dynlink-pr4839/native.plugin2.reference create mode 100644 testsuite/tests/lib-dynlink-pr4839/native.plugin3.reference create mode 100644 testsuite/tests/lib-dynlink-pr4839/native.plugin4.reference create mode 100644 testsuite/tests/lib-dynlink-pr4839/ocamltests create mode 100644 testsuite/tests/lib-dynlink-pr4839/plugin1/api.ml create mode 100644 testsuite/tests/lib-dynlink-pr4839/plugin1/api.mli create mode 100644 testsuite/tests/lib-dynlink-pr4839/plugin1/plugin.ml create mode 100644 testsuite/tests/lib-dynlink-pr4839/plugin2/api.ml create mode 100644 testsuite/tests/lib-dynlink-pr4839/plugin2/api.mli create mode 100644 testsuite/tests/lib-dynlink-pr4839/plugin2/plugin.ml create mode 100644 testsuite/tests/lib-dynlink-pr4839/plugin3/api.ml create mode 100644 testsuite/tests/lib-dynlink-pr4839/plugin3/api.mli create mode 100644 testsuite/tests/lib-dynlink-pr4839/plugin3/plugin.ml create mode 100644 testsuite/tests/lib-dynlink-pr4839/plugin4/api.ml create mode 100644 testsuite/tests/lib-dynlink-pr4839/plugin4/api.mli create mode 100644 testsuite/tests/lib-dynlink-pr4839/plugin4/plugin.ml create mode 100644 testsuite/tests/lib-dynlink-pr4839/test.ml create mode 100644 testsuite/tests/lib-dynlink-pr6950/b.ml create mode 100644 testsuite/tests/lib-dynlink-pr6950/byte.reference create mode 100644 testsuite/tests/lib-dynlink-pr6950/config.ml create mode 100644 testsuite/tests/lib-dynlink-pr6950/loader.ml create mode 100644 testsuite/tests/lib-dynlink-pr6950/native.reference create mode 100644 testsuite/tests/lib-dynlink-pr6950/ocamltests create mode 100644 testsuite/tests/lib-dynlink-private/ocamltests create mode 100644 testsuite/tests/lib-dynlink-private/pig.mli create mode 100644 testsuite/tests/lib-dynlink-private/plugin1/sheep.ml create mode 100644 testsuite/tests/lib-dynlink-private/plugin1/sheep.mli create mode 100644 testsuite/tests/lib-dynlink-private/plugin2/cow.ml create mode 100644 testsuite/tests/lib-dynlink-private/plugin2/cow.mli create mode 100644 testsuite/tests/lib-dynlink-private/plugin2b/cow.ml create mode 100644 testsuite/tests/lib-dynlink-private/plugin2b/cow.mli create mode 100644 testsuite/tests/lib-dynlink-private/plugin2c/cow.ml create mode 100644 testsuite/tests/lib-dynlink-private/plugin2c/cow.mli create mode 100644 testsuite/tests/lib-dynlink-private/plugin3/pig.ml create mode 100644 testsuite/tests/lib-dynlink-private/plugin3/pig.mli create mode 100644 testsuite/tests/lib-dynlink-private/plugin4/chicken.ml create mode 100644 testsuite/tests/lib-dynlink-private/plugin4/chicken.mli create mode 100644 testsuite/tests/lib-dynlink-private/plugin5/chicken.ml create mode 100644 testsuite/tests/lib-dynlink-private/plugin5/chicken.mli create mode 100644 testsuite/tests/lib-dynlink-private/plugin6/partridge.ml create mode 100644 testsuite/tests/lib-dynlink-private/plugin6/partridge.mli create mode 100644 testsuite/tests/lib-dynlink-private/plugin6/pheasant.ml create mode 100644 testsuite/tests/lib-dynlink-private/plugin6/pheasant.mli create mode 100644 testsuite/tests/lib-dynlink-private/sheep.ml create mode 100644 testsuite/tests/lib-dynlink-private/sheep.mli create mode 100644 testsuite/tests/lib-dynlink-private/test.ml create mode 100755 testsuite/tests/lib-filename/suffix.ml create mode 100644 testsuite/tests/lib-filename/suffix.reference create mode 100644 testsuite/tests/lib-float/ocamltests create mode 100644 testsuite/tests/lib-float/test.ml create mode 100644 testsuite/tests/lib-float/test.reference create mode 100644 testsuite/tests/lib-floatarray/floatarray.ml create mode 100644 testsuite/tests/lib-floatarray/ocamltests create mode 100644 testsuite/tests/lib-format/pp_print_custom_break.ml create mode 100644 testsuite/tests/lib-format/pp_print_custom_break.reference create mode 100644 testsuite/tests/lib-format/print_if_newline.ml create mode 100644 testsuite/tests/lib-format/print_if_newline.reference create mode 100644 testsuite/tests/lib-fun/ocamltests create mode 100644 testsuite/tests/lib-fun/test.ml create mode 100644 testsuite/tests/lib-fun/test.reference create mode 100644 testsuite/tests/lib-int/ocamltests create mode 100644 testsuite/tests/lib-int/test.ml create mode 100644 testsuite/tests/lib-int/test.reference create mode 100644 testsuite/tests/lib-int64/ocamltests create mode 100644 testsuite/tests/lib-int64/test.ml create mode 100644 testsuite/tests/lib-int64/test.reference create mode 100644 testsuite/tests/lib-option/ocamltests create mode 100644 testsuite/tests/lib-option/test.ml create mode 100644 testsuite/tests/lib-option/test.reference create mode 100644 testsuite/tests/lib-result/ocamltests create mode 100644 testsuite/tests/lib-result/test.ml create mode 100644 testsuite/tests/lib-result/test.reference rename testsuite/tests/lib-scanf-2/{reference => tscanf2.reference} (100%) delete mode 100644 testsuite/tests/lib-scanf-2/tscanf2_slave.ml create mode 100644 testsuite/tests/lib-scanf-2/tscanf2_worker.ml create mode 100644 testsuite/tests/lib-stdlib/ocamltests create mode 100644 testsuite/tests/lib-stdlib/pervasives_deprecated.ml create mode 100644 testsuite/tests/lib-systhreads/threadsigmask.ml create mode 100644 testsuite/tests/lib-systhreads/threadsigmask.reference create mode 100644 testsuite/tests/lib-unix/common/channel_of.ml create mode 100644 testsuite/tests/lib-unix/common/channel_of.reference create mode 100644 testsuite/tests/lib-unix/common/getaddrinfo.ml create mode 100644 testsuite/tests/lib-unix/common/process_pid.ml create mode 100644 testsuite/tests/lib-unix/common/process_pid.reference create mode 100644 testsuite/tests/lib-unix/win-symlink/ocamltests create mode 100644 testsuite/tests/local-functions/ocamltests create mode 100644 testsuite/tests/local-functions/tupled.ml create mode 100644 testsuite/tests/local-functions/tupled2.ml create mode 100644 testsuite/tests/locale/ocamltests create mode 100644 testsuite/tests/locale/stubs.c create mode 100644 testsuite/tests/locale/test.ml create mode 100644 testsuite/tests/locale/test.reference delete mode 100644 testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml.reference delete mode 100644 testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ocaml.reference create mode 100644 testsuite/tests/match-exception-warnings/no_mixing_under_guard.ml create mode 100644 testsuite/tests/match-exception-warnings/no_value_clauses.ml create mode 100644 testsuite/tests/match-exception-warnings/placement.ml create mode 100644 testsuite/tests/match-exception-warnings/pr7083.ml create mode 100644 testsuite/tests/match-exception-warnings/reachability.ml create mode 100644 testsuite/tests/match-exception/identifier_sharing.ml create mode 100644 testsuite/tests/match-exception/identifier_sharing.reference create mode 100644 testsuite/tests/no-alias-deps/a2235.ml create mode 100644 testsuite/tests/no-alias-deps/gpr2235.ml create mode 100644 testsuite/tests/no-alias-deps/lib2235.ml create mode 100644 testsuite/tests/no-alias-deps/lib__2235.ml create mode 100644 testsuite/tests/no-alias-deps/user_of_lib2235.ml create mode 100644 testsuite/tests/output-complete-obj/ocamltests create mode 100644 testsuite/tests/output-complete-obj/test.ml rename testsuite/tests/{output_obj => output-complete-obj}/test.ml_stub.c (100%) delete mode 100644 testsuite/tests/output_obj/Makefile.disabled delete mode 100644 testsuite/tests/output_obj/test.ml create mode 100644 testsuite/tests/parse-errors/escape_error.compilers.reference create mode 100644 testsuite/tests/parse-errors/escape_error.ml create mode 100644 testsuite/tests/parse-errors/expecting.compilers.reference create mode 100644 testsuite/tests/parse-errors/expecting.ml create mode 100644 testsuite/tests/parse-errors/ocamltests create mode 100644 testsuite/tests/parse-errors/pr7847.compilers.reference create mode 100644 testsuite/tests/parse-errors/pr7847.ml create mode 100644 testsuite/tests/parse-errors/unclosed_class_signature.compilers.reference create mode 100644 testsuite/tests/parse-errors/unclosed_class_signature.mli create mode 100644 testsuite/tests/parse-errors/unclosed_class_simpl_expr1.compilers.reference create mode 100644 testsuite/tests/parse-errors/unclosed_class_simpl_expr1.ml create mode 100644 testsuite/tests/parse-errors/unclosed_class_simpl_expr2.compilers.reference create mode 100644 testsuite/tests/parse-errors/unclosed_class_simpl_expr2.ml create mode 100644 testsuite/tests/parse-errors/unclosed_class_simpl_expr3.compilers.reference create mode 100644 testsuite/tests/parse-errors/unclosed_class_simpl_expr3.ml create mode 100644 testsuite/tests/parse-errors/unclosed_object.compilers.reference create mode 100644 testsuite/tests/parse-errors/unclosed_object.ml create mode 100644 testsuite/tests/parse-errors/unclosed_paren_module_expr1.compilers.reference create mode 100644 testsuite/tests/parse-errors/unclosed_paren_module_expr1.ml create mode 100644 testsuite/tests/parse-errors/unclosed_paren_module_expr2.compilers.reference create mode 100644 testsuite/tests/parse-errors/unclosed_paren_module_expr2.ml create mode 100644 testsuite/tests/parse-errors/unclosed_paren_module_expr3.compilers.reference create mode 100644 testsuite/tests/parse-errors/unclosed_paren_module_expr3.ml create mode 100644 testsuite/tests/parse-errors/unclosed_paren_module_expr4.compilers.reference create mode 100644 testsuite/tests/parse-errors/unclosed_paren_module_expr4.ml create mode 100644 testsuite/tests/parse-errors/unclosed_paren_module_expr5.compilers.reference create mode 100644 testsuite/tests/parse-errors/unclosed_paren_module_expr5.ml create mode 100644 testsuite/tests/parse-errors/unclosed_paren_module_type.compilers.reference create mode 100644 testsuite/tests/parse-errors/unclosed_paren_module_type.mli create mode 100644 testsuite/tests/parse-errors/unclosed_sig.compilers.reference create mode 100644 testsuite/tests/parse-errors/unclosed_sig.mli create mode 100644 testsuite/tests/parse-errors/unclosed_simple_expr.compilers.reference create mode 100644 testsuite/tests/parse-errors/unclosed_simple_expr.ml create mode 100644 testsuite/tests/parse-errors/unclosed_simple_pattern.compilers.reference create mode 100644 testsuite/tests/parse-errors/unclosed_simple_pattern.ml create mode 100644 testsuite/tests/parse-errors/unclosed_struct.compilers.reference create mode 100644 testsuite/tests/parse-errors/unclosed_struct.ml create mode 100644 testsuite/tests/parsing/anonymous_class_parameter.compilers.reference create mode 100644 testsuite/tests/parsing/anonymous_class_parameter.ml create mode 100644 testsuite/tests/parsing/arrow_ambiguity.compilers.reference create mode 100644 testsuite/tests/parsing/arrow_ambiguity.ml create mode 100644 testsuite/tests/parsing/broken_invariants.compilers.reference create mode 100644 testsuite/tests/parsing/broken_invariants.ml create mode 100644 testsuite/tests/parsing/constructor_declarations.compilers.reference create mode 100644 testsuite/tests/parsing/constructor_declarations.ml create mode 100644 testsuite/tests/parsing/hash_ambiguity.compilers.reference create mode 100644 testsuite/tests/parsing/hash_ambiguity.ml create mode 100644 testsuite/tests/parsing/illegal_ppx.ml create mode 100644 testsuite/tests/parsing/reloc.ml create mode 100644 testsuite/tests/regression/pr7920/ocamltests create mode 100644 testsuite/tests/regression/pr7920/pr7920.ml create mode 100644 testsuite/tests/regression/pr7920/pr7920.reference delete mode 100644 testsuite/tests/runtime-errors/Makefile create mode 100644 testsuite/tests/runtime-errors/has-stackoverflow-detection.sh create mode 100644 testsuite/tests/runtime-errors/ocamltests delete mode 100644 testsuite/tests/runtime-errors/stackoverflow.bytecode.checker delete mode 100644 testsuite/tests/runtime-errors/stackoverflow.native.checker rename testsuite/tests/runtime-errors/{stackoverflow.bytecode.reference => stackoverflow.reference} (100%) create mode 100644 testsuite/tests/runtime-errors/stackoverflow.run delete mode 100644 testsuite/tests/runtime-errors/syserror.bytecode.checker delete mode 100644 testsuite/tests/runtime-errors/syserror.native.checker delete mode 100644 testsuite/tests/runtime-errors/syserror.native.reference rename testsuite/tests/runtime-errors/{syserror.bytecode.reference => syserror.unix.reference} (100%) create mode 100644 testsuite/tests/runtime-errors/syserror.win32.reference create mode 100644 testsuite/tests/shadow_include/artificial.ml create mode 100644 testsuite/tests/shadow_include/cannot_shadow_error.compilers.reference create mode 100644 testsuite/tests/shadow_include/cannot_shadow_error.ml create mode 100644 testsuite/tests/shadow_include/ocamltests create mode 100644 testsuite/tests/shadow_include/shadow_all.ml create mode 100644 testsuite/tests/tool-caml-tex/ellipses.ml create mode 100644 testsuite/tests/tool-caml-tex/ellipses.reference create mode 100644 testsuite/tests/tool-caml-tex/ocamltests create mode 100644 testsuite/tests/tool-caml-tex/redirections.ml create mode 100644 testsuite/tests/tool-caml-tex/redirections.reference create mode 100644 testsuite/tests/tool-command-line/test.compilers.reference delete mode 100644 testsuite/tests/tool-command-line/test.ocamlc.byte.reference delete mode 100644 testsuite/tests/tool-command-line/test.ocamlopt.byte.flambda.reference delete mode 100644 testsuite/tests/tool-command-line/test.ocamlopt.byte.reference create mode 100644 testsuite/tests/tool-expect-test/clean_typer.ml create mode 100644 testsuite/tests/tool-expect-test/ocamltests create mode 100644 testsuite/tests/tool-lexyacc/chars.mll create mode 100644 testsuite/tests/tool-lexyacc/mpr7760.mll create mode 100644 testsuite/tests/tool-lexyacc/mpr7760.reference create mode 100755 testsuite/tests/tool-ocaml-annot/check-annot.sh create mode 100644 testsuite/tests/tool-ocaml-annot/failure.ml create mode 100644 testsuite/tests/tool-ocaml-annot/ocamltests create mode 100644 testsuite/tests/tool-ocaml-annot/success.ml create mode 100644 testsuite/tests/tool-ocaml-annot/typeonly.ml create mode 100644 testsuite/tests/tool-ocamlc-error-cleanup/check-error-cleanup.sh create mode 100644 testsuite/tests/tool-ocamlc-error-cleanup/ocamltests create mode 100644 testsuite/tests/tool-ocamlc-error-cleanup/test.ml create mode 100644 testsuite/tests/tool-ocamlc-stop-after/ocamltests create mode 100644 testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_impl.compilers.reference create mode 100644 testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_impl.ml create mode 100644 testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_intf.compilers.reference create mode 100644 testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_intf.mli create mode 100644 testsuite/tests/tool-ocamlc-stop-after/stop_after_typing_impl.compilers.reference create mode 100644 testsuite/tests/tool-ocamlc-stop-after/stop_after_typing_impl.ml delete mode 100644 testsuite/tests/tool-ocamldep-modalias/Makefile create mode 100644 testsuite/tests/tool-ocamldep-modalias/ocamltests create mode 100644 testsuite/tests/tool-ocamldep-modalias/setup-links.sh create mode 100644 testsuite/tests/tool-ocamldoc/Include_module_type_of.html.reference create mode 100644 testsuite/tests/tool-ocamldoc/Include_module_type_of.latex.reference create mode 100644 testsuite/tests/tool-ocamldoc/Include_module_type_of.mli create mode 100644 testsuite/tests/tool-ocamldoc/latex_ref.latex.reference create mode 100644 testsuite/tests/tool-ocamldoc/latex_ref.mli create mode 100644 testsuite/tests/tool-toplevel/error_highlighting.compilers.reference create mode 100644 testsuite/tests/tool-toplevel/error_highlighting.ml create mode 100644 testsuite/tests/tool-toplevel/error_highlighting_use1.ml create mode 100644 testsuite/tests/tool-toplevel/error_highlighting_use2.ml create mode 100644 testsuite/tests/tool-toplevel/error_highlighting_use3.ml create mode 100644 testsuite/tests/tool-toplevel/error_highlighting_use4.ml create mode 100644 testsuite/tests/tool-toplevel/pr6468.compilers.reference create mode 100644 testsuite/tests/tool-toplevel/pr6468.ml create mode 100644 testsuite/tests/translprim/array_spec.compilers.flat.reference create mode 100644 testsuite/tests/translprim/array_spec.compilers.no-flat.reference delete mode 100644 testsuite/tests/translprim/array_spec.compilers.reference.flat delete mode 100644 testsuite/tests/translprim/array_spec.compilers.reference.no-flat create mode 100644 testsuite/tests/translprim/module_coercion.compilers.flat.reference create mode 100644 testsuite/tests/translprim/module_coercion.compilers.no-flat.reference delete mode 100644 testsuite/tests/translprim/module_coercion.compilers.reference.flat delete mode 100644 testsuite/tests/translprim/module_coercion.compilers.reference.no-flat create mode 100644 testsuite/tests/typing-core-bugs/missing_rec_hint.ml create mode 100755 testsuite/tests/typing-core-bugs/repeated_did_you_mean.ml create mode 100755 testsuite/tests/typing-deprecated/alerts.ml delete mode 100644 testsuite/tests/typing-gadts/gpr1997.ml create mode 100644 testsuite/tests/typing-gadts/or_patterns.ml create mode 100644 testsuite/tests/typing-gadts/unexpected_existentials.ml create mode 100644 testsuite/tests/typing-misc/empty_ppx.ml create mode 100644 testsuite/tests/typing-misc/exotic_unifications.ml create mode 100644 testsuite/tests/typing-misc/external_arity.ml create mode 100644 testsuite/tests/typing-misc/mapping.ml create mode 100644 testsuite/tests/typing-misc/pat_type_sharing.ml create mode 100644 testsuite/tests/typing-misc/pattern_open.ml create mode 100644 testsuite/tests/typing-misc/pr6416.ml create mode 100644 testsuite/tests/typing-misc/pr6634.ml create mode 100644 testsuite/tests/typing-misc/pr8548.ml create mode 100644 testsuite/tests/typing-misc/pr8548_split.ml create mode 100644 testsuite/tests/typing-misc/range.ml create mode 100644 testsuite/tests/typing-misc/range_intf.ml create mode 100644 testsuite/tests/typing-misc/ranged.ml create mode 100644 testsuite/tests/typing-misc/ranged_intf.ml create mode 100644 testsuite/tests/typing-misc/scope_escape.ml create mode 100644 testsuite/tests/typing-misc/typecore_empty_polyvariant_error.compilers.reference create mode 100644 testsuite/tests/typing-misc/typecore_empty_polyvariant_error.ml create mode 100644 testsuite/tests/typing-misc/typecore_errors.ml create mode 100644 testsuite/tests/typing-misc/typecore_nolabel_errors.ml create mode 100644 testsuite/tests/typing-misc/typetexp_errors.ml create mode 100644 testsuite/tests/typing-misc/unique_names_in_unification.ml create mode 100644 testsuite/tests/typing-missing-cmi-2/bar.mli create mode 100644 testsuite/tests/typing-missing-cmi-2/baz.ml create mode 100644 testsuite/tests/typing-missing-cmi-2/foo.mli create mode 100644 testsuite/tests/typing-missing-cmi-2/ocamltests create mode 100644 testsuite/tests/typing-missing-cmi-2/test.compilers.reference create mode 100644 testsuite/tests/typing-missing-cmi-2/test.ml create mode 100644 testsuite/tests/typing-modules/.gitattributes create mode 100644 testsuite/tests/typing-modules/nondep.ml create mode 100644 testsuite/tests/typing-modules/nondep_private_abbrev.ml create mode 100755 testsuite/tests/typing-modules/normalize_path.ml create mode 100644 testsuite/tests/typing-modules/pr7726.ml create mode 100644 testsuite/tests/typing-modules/pr7851.ml create mode 100644 testsuite/tests/typing-modules/unroll_private_abbrev.ml create mode 100644 testsuite/tests/typing-objects/abstract_rows.ml create mode 100644 testsuite/tests/typing-objects/errors.ml create mode 100644 testsuite/tests/typing-objects/self_cannot_be_closed.ml create mode 100644 testsuite/tests/typing-ocamlc-i/pervasives_leitmotiv.compilers.reference create mode 100644 testsuite/tests/typing-ocamlc-i/pervasives_leitmotiv.ml create mode 100644 testsuite/tests/typing-ocamlc-i/pr4791.compilers.reference create mode 100644 testsuite/tests/typing-ocamlc-i/pr4791.ml create mode 100644 testsuite/tests/typing-ocamlc-i/pr6323.compilers.reference create mode 100644 testsuite/tests/typing-ocamlc-i/pr6323.ml create mode 100644 testsuite/tests/typing-ocamlc-i/pr7402.compilers.reference create mode 100644 testsuite/tests/typing-ocamlc-i/pr7402.ml delete mode 100644 testsuite/tests/typing-pattern_open/ocamltests delete mode 100644 testsuite/tests/typing-pattern_open/pattern_open.ml delete mode 100644 testsuite/tests/typing-pattern_open/pattern_open.ocaml.reference create mode 100644 testsuite/tests/typing-poly/error_messages.ml create mode 100644 testsuite/tests/typing-recmod/gpr1626.ml delete mode 100644 testsuite/tests/typing-recmod/t19ok.ml create mode 100644 testsuite/tests/typing-shadowing-of-pervasives-submodules/redefine_largefile_top.compilers.reference create mode 100644 testsuite/tests/typing-shadowing-of-pervasives-submodules/redefine_largefile_top.ml create mode 100644 testsuite/tests/typing-sigsubst/mpr7852.mli create mode 100644 testsuite/tests/typing-sigsubst/sig_local_aliases.ml create mode 100644 testsuite/tests/typing-sigsubst/sig_local_aliases_syntax_errors.compilers.reference create mode 100644 testsuite/tests/typing-sigsubst/sig_local_aliases_syntax_errors.ml create mode 100644 testsuite/tests/typing-sigsubst/test_functor.ml create mode 100644 testsuite/tests/typing-sigsubst/test_loc_modtype_type_eq.ml create mode 100644 testsuite/tests/typing-sigsubst/test_loc_modtype_type_subst.ml create mode 100644 testsuite/tests/typing-sigsubst/test_loc_type_eq.ml create mode 100644 testsuite/tests/typing-sigsubst/test_loc_type_subst.ml create mode 100644 testsuite/tests/typing-sigsubst/test_locations.compilers.reference create mode 100644 testsuite/tests/typing-sigsubst/test_locations.ml delete mode 100644 testsuite/tests/typing-unboxed-types/test.ml.reference-flat delete mode 100644 testsuite/tests/typing-unboxed-types/test.ml.reference-noflat create mode 100644 testsuite/tests/typing-unboxed-types/test_flat.ml create mode 100644 testsuite/tests/typing-unboxed-types/test_no_flat.ml delete mode 100644 testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.compilers.reference delete mode 100644 testsuite/tests/typing-warnings/application.compilers.reference delete mode 100644 testsuite/tests/typing-warnings/coercions.compilers.principal.reference delete mode 100644 testsuite/tests/typing-warnings/coercions.compilers.reference delete mode 100644 testsuite/tests/typing-warnings/exhaustiveness.compilers.reference create mode 100755 testsuite/tests/typing-warnings/open_warnings.ml delete mode 100644 testsuite/tests/typing-warnings/pr5892.compilers.reference delete mode 100644 testsuite/tests/typing-warnings/pr6587.compilers.reference delete mode 100644 testsuite/tests/typing-warnings/pr6872.compilers.principal.reference delete mode 100644 testsuite/tests/typing-warnings/pr6872.compilers.reference delete mode 100644 testsuite/tests/typing-warnings/pr7085.compilers.reference delete mode 100644 testsuite/tests/typing-warnings/pr7115.compilers.reference delete mode 100644 testsuite/tests/typing-warnings/pr7553.compilers.reference delete mode 100644 testsuite/tests/typing-warnings/records.compilers.principal.reference delete mode 100644 testsuite/tests/typing-warnings/records.compilers.reference create mode 100644 testsuite/tests/typing-warnings/unused_rec.ml delete mode 100644 testsuite/tests/typing-warnings/unused_types.compilers.reference delete mode 100644 testsuite/tests/unboxed-primitive-args/Makefile create mode 100644 testsuite/tests/unboxed-primitive-args/ocamltests create mode 100644 testsuite/tests/unboxed-primitive-args/test.ml create mode 100644 testsuite/tests/unboxed-primitive-args/test.reference delete mode 100644 testsuite/tests/unwind/Makefile create mode 100644 testsuite/tests/unwind/check-linker-version.sh create mode 100644 testsuite/tests/unwind/ocamltests create mode 100644 testsuite/tests/warnings/w03.compilers.reference create mode 100644 testsuite/tests/warnings/w03.ml delete mode 100644 testsuite/tests/warnings/w52.compilers.reference delete mode 100644 testsuite/tests/win-unicode/Makefile delete mode 100755 testsuite/tests/win-unicode/exec_tests.ml delete mode 100644 testsuite/tests/win-unicode/exec_tests.precheck delete mode 100644 testsuite/tests/win-unicode/exec_tests.reference delete mode 100644 testsuite/tests/win-unicode/mkfiles.c create mode 100755 testsuite/tests/win-unicode/mltest.compilers.reference delete mode 100644 testsuite/tests/win-unicode/mltest.reference create mode 100644 testsuite/tests/win-unicode/ocamltests delete mode 100755 testsuite/tests/win-unicode/printargv.c delete mode 100755 testsuite/tests/win-unicode/printenv.c delete mode 100755 testsuite/tests/win-unicode/symlink_tests.ml delete mode 100644 testsuite/tests/win-unicode/symlink_tests.reference rename testsuite/{tests/asmgen/amd64.S => tools/asmgen_amd64.S} (100%) rename testsuite/{tests/asmgen/arm.S => tools/asmgen_arm.S} (100%) rename testsuite/{tests/asmgen/arm64.S => tools/asmgen_arm64.S} (100%) create mode 100644 testsuite/tools/asmgen_i386.S create mode 100644 testsuite/tools/asmgen_i386nt.asm rename testsuite/{tests/asmgen/power.S => tools/asmgen_power.S} (100%) rename testsuite/{tests/asmgen/s390x.S => tools/asmgen_s390x.S} (100%) create mode 100644 testsuite/tools/codegen_main.ml create mode 100644 testsuite/tools/lexcmm.mli create mode 100644 testsuite/tools/lexcmm.mll create mode 100644 testsuite/tools/parsecmm.mly create mode 100644 testsuite/tools/parsecmmaux.ml create mode 100644 testsuite/tools/parsecmmaux.mli delete mode 100644 tools/Makefile.nt create mode 100644 tools/caml_tex.ml create mode 100755 tools/check-parser-uptodate-or-warn.sh create mode 100755 tools/check-typo-since create mode 100755 tools/ci/inria/bootstrap create mode 100755 tools/ci/inria/extra-checks create mode 100644 tools/ci/inria/lsan-suppr.txt create mode 100644 tools/ci/inria/remove-sinh-primitive.patch create mode 100644 tools/ci/inria/tsan-suppr.txt create mode 100644 tools/dune create mode 100644 tools/markdown-add-pr-links.sh create mode 100755 tools/pre-commit-githook create mode 100644 tools/release-checklist create mode 100644 toplevel/dune create mode 100755 typing/TODO.md create mode 100644 typing/rec_check.ml create mode 100644 typing/rec_check.mli create mode 100644 typing/typedecl_immediacy.ml create mode 100644 typing/typedecl_immediacy.mli create mode 100644 typing/typedecl_properties.ml create mode 100644 typing/typedecl_properties.mli create mode 100644 typing/typedecl_unboxed.ml create mode 100644 typing/typedecl_unboxed.mli create mode 100644 typing/typedecl_variance.ml create mode 100644 typing/typedecl_variance.mli delete mode 100644 typing/typedtreeMap.ml delete mode 100644 typing/typedtreeMap.mli create mode 100644 utils/HACKING.adoc create mode 100644 utils/Makefile create mode 100644 utils/dune create mode 100644 utils/load_path.ml create mode 100644 utils/load_path.mli delete mode 100644 utils/tbl.ml delete mode 100644 utils/tbl.mli delete mode 100644 yacc/Makefile.nt diff --git a/.depend b/.depend index 891a9c9b..19f8c5d7 100644 --- a/.depend +++ b/.depend @@ -1,2433 +1,6128 @@ -utils/arg_helper.cmo : utils/arg_helper.cmi -utils/arg_helper.cmx : utils/arg_helper.cmi +utils/arg_helper.cmo : \ + utils/arg_helper.cmi +utils/arg_helper.cmx : \ + utils/arg_helper.cmi utils/arg_helper.cmi : -utils/build_path_prefix_map.cmo : utils/build_path_prefix_map.cmi -utils/build_path_prefix_map.cmx : utils/build_path_prefix_map.cmi +utils/build_path_prefix_map.cmo : \ + utils/build_path_prefix_map.cmi +utils/build_path_prefix_map.cmx : \ + utils/build_path_prefix_map.cmi utils/build_path_prefix_map.cmi : -utils/ccomp.cmo : utils/misc.cmi utils/config.cmi utils/clflags.cmi \ +utils/ccomp.cmo : \ + utils/misc.cmi \ + utils/load_path.cmi \ + utils/config.cmi \ + utils/clflags.cmi \ utils/ccomp.cmi -utils/ccomp.cmx : utils/misc.cmx utils/config.cmx utils/clflags.cmx \ +utils/ccomp.cmx : \ + utils/misc.cmx \ + utils/load_path.cmx \ + utils/config.cmx \ + utils/clflags.cmx \ utils/ccomp.cmi utils/ccomp.cmi : -utils/clflags.cmo : utils/profile.cmi utils/numbers.cmi utils/misc.cmi \ - utils/config.cmi utils/arg_helper.cmi utils/clflags.cmi -utils/clflags.cmx : utils/profile.cmx utils/numbers.cmx utils/misc.cmx \ - utils/config.cmx utils/arg_helper.cmx utils/clflags.cmi -utils/clflags.cmi : utils/profile.cmi utils/misc.cmi -utils/config.cmo : utils/config.cmi -utils/config.cmx : utils/config.cmi +utils/clflags.cmo : \ + utils/profile.cmi \ + utils/numbers.cmi \ + utils/misc.cmi \ + utils/config.cmi \ + utils/arg_helper.cmi \ + utils/clflags.cmi +utils/clflags.cmx : \ + utils/profile.cmx \ + utils/numbers.cmx \ + utils/misc.cmx \ + utils/config.cmx \ + utils/arg_helper.cmx \ + utils/clflags.cmi +utils/clflags.cmi : \ + utils/profile.cmi \ + utils/misc.cmi +utils/config.cmo : \ + utils/config.cmi +utils/config.cmx : \ + utils/config.cmi utils/config.cmi : -utils/consistbl.cmo : utils/consistbl.cmi -utils/consistbl.cmx : utils/consistbl.cmi +utils/consistbl.cmo : \ + utils/consistbl.cmi +utils/consistbl.cmx : \ + utils/consistbl.cmi utils/consistbl.cmi : -utils/identifiable.cmo : utils/misc.cmi utils/identifiable.cmi -utils/identifiable.cmx : utils/misc.cmx utils/identifiable.cmi +utils/identifiable.cmo : \ + utils/misc.cmi \ + utils/identifiable.cmi +utils/identifiable.cmx : \ + utils/misc.cmx \ + utils/identifiable.cmi utils/identifiable.cmi : -utils/misc.cmo : utils/misc.cmi -utils/misc.cmx : utils/misc.cmi -utils/misc.cmi : -utils/numbers.cmo : utils/misc.cmi utils/identifiable.cmi utils/numbers.cmi -utils/numbers.cmx : utils/misc.cmx utils/identifiable.cmx utils/numbers.cmi -utils/numbers.cmi : utils/identifiable.cmi -utils/profile.cmo : utils/misc.cmi utils/profile.cmi -utils/profile.cmx : utils/misc.cmx utils/profile.cmi +utils/load_path.cmo : \ + utils/misc.cmi \ + utils/load_path.cmi +utils/load_path.cmx : \ + utils/misc.cmx \ + utils/load_path.cmi +utils/load_path.cmi : +utils/misc.cmo : \ + utils/config.cmi \ + utils/build_path_prefix_map.cmi \ + utils/misc.cmi +utils/misc.cmx : \ + utils/config.cmx \ + utils/build_path_prefix_map.cmx \ + utils/misc.cmi +utils/misc.cmi : \ + utils/build_path_prefix_map.cmi +utils/numbers.cmo : \ + utils/misc.cmi \ + utils/identifiable.cmi \ + utils/numbers.cmi +utils/numbers.cmx : \ + utils/misc.cmx \ + utils/identifiable.cmx \ + utils/numbers.cmi +utils/numbers.cmi : \ + utils/identifiable.cmi +utils/profile.cmo : \ + utils/misc.cmi \ + utils/profile.cmi +utils/profile.cmx : \ + utils/misc.cmx \ + utils/profile.cmi utils/profile.cmi : -utils/strongly_connected_components.cmo : utils/numbers.cmi utils/misc.cmi \ - utils/identifiable.cmi utils/strongly_connected_components.cmi -utils/strongly_connected_components.cmx : utils/numbers.cmx utils/misc.cmx \ - utils/identifiable.cmx utils/strongly_connected_components.cmi -utils/strongly_connected_components.cmi : utils/identifiable.cmi -utils/targetint.cmo : utils/misc.cmi utils/targetint.cmi -utils/targetint.cmx : utils/misc.cmx utils/targetint.cmi +utils/strongly_connected_components.cmo : \ + utils/numbers.cmi \ + utils/misc.cmi \ + utils/identifiable.cmi \ + utils/strongly_connected_components.cmi +utils/strongly_connected_components.cmx : \ + utils/numbers.cmx \ + utils/misc.cmx \ + utils/identifiable.cmx \ + utils/strongly_connected_components.cmi +utils/strongly_connected_components.cmi : \ + utils/identifiable.cmi +utils/targetint.cmo : \ + utils/misc.cmi \ + utils/targetint.cmi +utils/targetint.cmx : \ + utils/misc.cmx \ + utils/targetint.cmi utils/targetint.cmi : -utils/tbl.cmo : utils/tbl.cmi -utils/tbl.cmx : utils/tbl.cmi -utils/tbl.cmi : -utils/terminfo.cmo : utils/terminfo.cmi -utils/terminfo.cmx : utils/terminfo.cmi +utils/terminfo.cmo : \ + utils/terminfo.cmi +utils/terminfo.cmx : \ + utils/terminfo.cmi utils/terminfo.cmi : -utils/warnings.cmo : utils/misc.cmi utils/warnings.cmi -utils/warnings.cmx : utils/misc.cmx utils/warnings.cmi +utils/warnings.cmo : \ + utils/misc.cmi \ + utils/warnings.cmi +utils/warnings.cmx : \ + utils/misc.cmx \ + utils/warnings.cmi utils/warnings.cmi : -parsing/ast_helper.cmo : parsing/syntaxerr.cmi parsing/parsetree.cmi \ - parsing/longident.cmi parsing/location.cmi parsing/docstrings.cmi \ - parsing/asttypes.cmi parsing/ast_helper.cmi -parsing/ast_helper.cmx : parsing/syntaxerr.cmx parsing/parsetree.cmi \ - parsing/longident.cmx parsing/location.cmx parsing/docstrings.cmx \ - parsing/asttypes.cmi parsing/ast_helper.cmi -parsing/ast_helper.cmi : parsing/parsetree.cmi parsing/longident.cmi \ - parsing/location.cmi parsing/docstrings.cmi parsing/asttypes.cmi -parsing/ast_invariants.cmo : parsing/syntaxerr.cmi parsing/parsetree.cmi \ - parsing/longident.cmi parsing/builtin_attributes.cmi parsing/asttypes.cmi \ - parsing/ast_iterator.cmi parsing/ast_invariants.cmi -parsing/ast_invariants.cmx : parsing/syntaxerr.cmx parsing/parsetree.cmi \ - parsing/longident.cmx parsing/builtin_attributes.cmx parsing/asttypes.cmi \ - parsing/ast_iterator.cmx parsing/ast_invariants.cmi -parsing/ast_invariants.cmi : parsing/parsetree.cmi -parsing/ast_iterator.cmo : parsing/parsetree.cmi parsing/location.cmi \ +parsing/ast_helper.cmo : \ + parsing/syntaxerr.cmi \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + parsing/docstrings.cmi \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmi +parsing/ast_helper.cmx : \ + parsing/syntaxerr.cmx \ + parsing/parsetree.cmi \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + parsing/docstrings.cmx \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmi +parsing/ast_helper.cmi : \ + parsing/parsetree.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + parsing/docstrings.cmi \ + parsing/asttypes.cmi +parsing/ast_invariants.cmo : \ + parsing/syntaxerr.cmi \ + parsing/parsetree.cmi \ + parsing/longident.cmi \ + parsing/builtin_attributes.cmi \ + parsing/asttypes.cmi \ + parsing/ast_iterator.cmi \ + parsing/ast_invariants.cmi +parsing/ast_invariants.cmx : \ + parsing/syntaxerr.cmx \ + parsing/parsetree.cmi \ + parsing/longident.cmx \ + parsing/builtin_attributes.cmx \ + parsing/asttypes.cmi \ + parsing/ast_iterator.cmx \ + parsing/ast_invariants.cmi +parsing/ast_invariants.cmi : \ + parsing/parsetree.cmi +parsing/ast_iterator.cmo : \ + parsing/parsetree.cmi \ + parsing/location.cmi \ parsing/ast_iterator.cmi -parsing/ast_iterator.cmx : parsing/parsetree.cmi parsing/location.cmx \ +parsing/ast_iterator.cmx : \ + parsing/parsetree.cmi \ + parsing/location.cmx \ parsing/ast_iterator.cmi -parsing/ast_iterator.cmi : parsing/parsetree.cmi parsing/location.cmi -parsing/ast_mapper.cmo : parsing/parsetree.cmi utils/misc.cmi \ - parsing/longident.cmi parsing/location.cmi utils/config.cmi \ - utils/clflags.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \ +parsing/ast_iterator.cmi : \ + parsing/parsetree.cmi \ + parsing/location.cmi +parsing/ast_mapper.cmo : \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + utils/config.cmi \ + utils/clflags.cmi \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmi \ parsing/ast_mapper.cmi -parsing/ast_mapper.cmx : parsing/parsetree.cmi utils/misc.cmx \ - parsing/longident.cmx parsing/location.cmx utils/config.cmx \ - utils/clflags.cmx parsing/asttypes.cmi parsing/ast_helper.cmx \ +parsing/ast_mapper.cmx : \ + parsing/parsetree.cmi \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + utils/load_path.cmx \ + utils/config.cmx \ + utils/clflags.cmx \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmx \ parsing/ast_mapper.cmi -parsing/ast_mapper.cmi : parsing/parsetree.cmi parsing/location.cmi -parsing/asttypes.cmi : parsing/location.cmi -parsing/attr_helper.cmo : parsing/parsetree.cmi parsing/location.cmi \ - parsing/asttypes.cmi parsing/attr_helper.cmi -parsing/attr_helper.cmx : parsing/parsetree.cmi parsing/location.cmx \ - parsing/asttypes.cmi parsing/attr_helper.cmi -parsing/attr_helper.cmi : parsing/parsetree.cmi parsing/location.cmi \ +parsing/ast_mapper.cmi : \ + parsing/parsetree.cmi \ + parsing/location.cmi +parsing/asttypes.cmi : \ + parsing/location.cmi +parsing/attr_helper.cmo : \ + parsing/parsetree.cmi \ + parsing/location.cmi \ + parsing/asttypes.cmi \ + parsing/attr_helper.cmi +parsing/attr_helper.cmx : \ + parsing/parsetree.cmi \ + parsing/location.cmx \ + parsing/asttypes.cmi \ + parsing/attr_helper.cmi +parsing/attr_helper.cmi : \ + parsing/parsetree.cmi \ + parsing/location.cmi \ parsing/asttypes.cmi -parsing/builtin_attributes.cmo : utils/warnings.cmi parsing/parsetree.cmi \ - parsing/location.cmi parsing/asttypes.cmi parsing/builtin_attributes.cmi -parsing/builtin_attributes.cmx : utils/warnings.cmx parsing/parsetree.cmi \ - parsing/location.cmx parsing/asttypes.cmi parsing/builtin_attributes.cmi -parsing/builtin_attributes.cmi : parsing/parsetree.cmi parsing/location.cmi -parsing/depend.cmo : parsing/parsetree.cmi utils/misc.cmi \ - parsing/longident.cmi parsing/location.cmi utils/clflags.cmi \ - parsing/builtin_attributes.cmi parsing/asttypes.cmi parsing/depend.cmi -parsing/depend.cmx : parsing/parsetree.cmi utils/misc.cmx \ - parsing/longident.cmx parsing/location.cmx utils/clflags.cmx \ - parsing/builtin_attributes.cmx parsing/asttypes.cmi parsing/depend.cmi -parsing/depend.cmi : parsing/parsetree.cmi parsing/longident.cmi -parsing/docstrings.cmo : utils/warnings.cmi parsing/parsetree.cmi \ - parsing/location.cmi parsing/docstrings.cmi -parsing/docstrings.cmx : utils/warnings.cmx parsing/parsetree.cmi \ - parsing/location.cmx parsing/docstrings.cmi -parsing/docstrings.cmi : parsing/parsetree.cmi parsing/location.cmi -parsing/lexer.cmo : utils/warnings.cmi parsing/parser.cmi utils/misc.cmi \ - parsing/location.cmi parsing/docstrings.cmi parsing/lexer.cmi -parsing/lexer.cmx : utils/warnings.cmx parsing/parser.cmx utils/misc.cmx \ - parsing/location.cmx parsing/docstrings.cmx parsing/lexer.cmi -parsing/lexer.cmi : parsing/parser.cmi parsing/location.cmi -parsing/location.cmo : utils/warnings.cmi utils/terminfo.cmi utils/misc.cmi \ - utils/clflags.cmi utils/build_path_prefix_map.cmi parsing/location.cmi -parsing/location.cmx : utils/warnings.cmx utils/terminfo.cmx utils/misc.cmx \ - utils/clflags.cmx utils/build_path_prefix_map.cmx parsing/location.cmi -parsing/location.cmi : utils/warnings.cmi -parsing/longident.cmo : utils/misc.cmi parsing/longident.cmi -parsing/longident.cmx : utils/misc.cmx parsing/longident.cmi +parsing/builtin_attributes.cmo : \ + utils/warnings.cmi \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + parsing/asttypes.cmi \ + parsing/builtin_attributes.cmi +parsing/builtin_attributes.cmx : \ + utils/warnings.cmx \ + parsing/parsetree.cmi \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + parsing/asttypes.cmi \ + parsing/builtin_attributes.cmi +parsing/builtin_attributes.cmi : \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/location.cmi +parsing/camlinternalMenhirLib.cmo : \ + parsing/camlinternalMenhirLib.cmi +parsing/camlinternalMenhirLib.cmx : \ + parsing/camlinternalMenhirLib.cmi +parsing/camlinternalMenhirLib.cmi : +parsing/depend.cmo : \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + utils/clflags.cmi \ + parsing/builtin_attributes.cmi \ + parsing/asttypes.cmi \ + parsing/depend.cmi +parsing/depend.cmx : \ + parsing/parsetree.cmi \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + utils/clflags.cmx \ + parsing/builtin_attributes.cmx \ + parsing/asttypes.cmi \ + parsing/depend.cmi +parsing/depend.cmi : \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/longident.cmi +parsing/docstrings.cmo : \ + utils/warnings.cmi \ + parsing/parsetree.cmi \ + parsing/location.cmi \ + parsing/docstrings.cmi +parsing/docstrings.cmx : \ + utils/warnings.cmx \ + parsing/parsetree.cmi \ + parsing/location.cmx \ + parsing/docstrings.cmi +parsing/docstrings.cmi : \ + parsing/parsetree.cmi \ + parsing/location.cmi +parsing/lexer.cmo : \ + utils/warnings.cmi \ + parsing/parser.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + parsing/docstrings.cmi \ + parsing/lexer.cmi +parsing/lexer.cmx : \ + utils/warnings.cmx \ + parsing/parser.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + parsing/docstrings.cmx \ + parsing/lexer.cmi +parsing/lexer.cmi : \ + parsing/parser.cmi \ + parsing/location.cmi +parsing/location.cmo : \ + utils/warnings.cmi \ + utils/terminfo.cmi \ + utils/misc.cmi \ + utils/clflags.cmi \ + utils/build_path_prefix_map.cmi \ + parsing/location.cmi +parsing/location.cmx : \ + utils/warnings.cmx \ + utils/terminfo.cmx \ + utils/misc.cmx \ + utils/clflags.cmx \ + utils/build_path_prefix_map.cmx \ + parsing/location.cmi +parsing/location.cmi : \ + utils/warnings.cmi +parsing/longident.cmo : \ + utils/misc.cmi \ + parsing/longident.cmi +parsing/longident.cmx : \ + utils/misc.cmx \ + parsing/longident.cmi parsing/longident.cmi : -parsing/parse.cmo : parsing/syntaxerr.cmi parsing/parser.cmi \ - parsing/location.cmi parsing/lexer.cmi parsing/docstrings.cmi \ +parsing/parse.cmo : \ + parsing/syntaxerr.cmi \ + parsing/pprintast.cmi \ + parsing/parser.cmi \ + parsing/location.cmi \ + parsing/lexer.cmi \ + parsing/docstrings.cmi \ parsing/parse.cmi -parsing/parse.cmx : parsing/syntaxerr.cmx parsing/parser.cmx \ - parsing/location.cmx parsing/lexer.cmx parsing/docstrings.cmx \ +parsing/parse.cmx : \ + parsing/syntaxerr.cmx \ + parsing/pprintast.cmx \ + parsing/parser.cmx \ + parsing/location.cmx \ + parsing/lexer.cmx \ + parsing/docstrings.cmx \ parsing/parse.cmi -parsing/parse.cmi : parsing/parsetree.cmi -parsing/parser.cmo : parsing/syntaxerr.cmi parsing/parsetree.cmi \ - parsing/longident.cmi parsing/location.cmi parsing/docstrings.cmi \ - utils/clflags.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \ +parsing/parse.cmi : \ + parsing/parsetree.cmi +parsing/parser.cmo : \ + parsing/syntaxerr.cmi \ + parsing/parsetree.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + parsing/docstrings.cmi \ + utils/clflags.cmi \ + parsing/camlinternalMenhirLib.cmi \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmi \ parsing/parser.cmi -parsing/parser.cmx : parsing/syntaxerr.cmx parsing/parsetree.cmi \ - parsing/longident.cmx parsing/location.cmx parsing/docstrings.cmx \ - utils/clflags.cmx parsing/asttypes.cmi parsing/ast_helper.cmx \ +parsing/parser.cmx : \ + parsing/syntaxerr.cmx \ + parsing/parsetree.cmi \ + parsing/longident.cmx \ + parsing/location.cmx \ + parsing/docstrings.cmx \ + utils/clflags.cmx \ + parsing/camlinternalMenhirLib.cmx \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmx \ parsing/parser.cmi -parsing/parser.cmi : parsing/parsetree.cmi parsing/location.cmi \ - parsing/docstrings.cmi -parsing/parsetree.cmi : parsing/longident.cmi parsing/location.cmi \ +parsing/parser.cmi : \ + parsing/parsetree.cmi \ + parsing/location.cmi \ + parsing/docstrings.cmi \ + parsing/camlinternalMenhirLib.cmi +parsing/parsetree.cmi : \ + parsing/longident.cmi \ + parsing/location.cmi \ parsing/asttypes.cmi -parsing/pprintast.cmo : parsing/parsetree.cmi utils/misc.cmi \ - parsing/longident.cmi parsing/location.cmi parsing/asttypes.cmi \ - parsing/ast_helper.cmi parsing/pprintast.cmi -parsing/pprintast.cmx : parsing/parsetree.cmi utils/misc.cmx \ - parsing/longident.cmx parsing/location.cmx parsing/asttypes.cmi \ - parsing/ast_helper.cmx parsing/pprintast.cmi -parsing/pprintast.cmi : parsing/parsetree.cmi -parsing/printast.cmo : parsing/parsetree.cmi utils/misc.cmi \ - parsing/longident.cmi parsing/location.cmi parsing/asttypes.cmi \ +parsing/pprintast.cmo : \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmi \ + parsing/pprintast.cmi +parsing/pprintast.cmx : \ + parsing/parsetree.cmi \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmx \ + parsing/pprintast.cmi +parsing/pprintast.cmi : \ + parsing/parsetree.cmi \ + parsing/longident.cmi +parsing/printast.cmo : \ + parsing/pprintast.cmi \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + parsing/asttypes.cmi \ parsing/printast.cmi -parsing/printast.cmx : parsing/parsetree.cmi utils/misc.cmx \ - parsing/longident.cmx parsing/location.cmx parsing/asttypes.cmi \ +parsing/printast.cmx : \ + parsing/pprintast.cmx \ + parsing/parsetree.cmi \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + parsing/asttypes.cmi \ parsing/printast.cmi -parsing/printast.cmi : parsing/parsetree.cmi -parsing/syntaxerr.cmo : parsing/location.cmi parsing/syntaxerr.cmi -parsing/syntaxerr.cmx : parsing/location.cmx parsing/syntaxerr.cmi -parsing/syntaxerr.cmi : parsing/location.cmi -typing/annot.cmi : parsing/location.cmi -typing/btype.cmo : typing/types.cmi typing/path.cmi utils/misc.cmi \ - typing/ident.cmi parsing/asttypes.cmi typing/btype.cmi -typing/btype.cmx : typing/types.cmx typing/path.cmx utils/misc.cmx \ - typing/ident.cmx parsing/asttypes.cmi typing/btype.cmi -typing/btype.cmi : typing/types.cmi typing/path.cmi parsing/asttypes.cmi -typing/cmi_format.cmo : typing/types.cmi parsing/location.cmi \ - utils/config.cmi typing/cmi_format.cmi -typing/cmi_format.cmx : typing/types.cmx parsing/location.cmx \ - utils/config.cmx typing/cmi_format.cmi -typing/cmi_format.cmi : typing/types.cmi -typing/cmt_format.cmo : typing/types.cmi typing/typedtree.cmi \ - typing/tast_mapper.cmi utils/misc.cmi parsing/location.cmi \ - parsing/lexer.cmi typing/env.cmi utils/config.cmi typing/cmi_format.cmi \ - utils/clflags.cmi typing/cmt_format.cmi -typing/cmt_format.cmx : typing/types.cmx typing/typedtree.cmx \ - typing/tast_mapper.cmx utils/misc.cmx parsing/location.cmx \ - parsing/lexer.cmx typing/env.cmx utils/config.cmx typing/cmi_format.cmx \ - utils/clflags.cmx typing/cmt_format.cmi -typing/cmt_format.cmi : typing/types.cmi typing/typedtree.cmi \ - parsing/location.cmi typing/env.cmi typing/cmi_format.cmi -typing/ctype.cmo : typing/types.cmi typing/subst.cmi typing/predef.cmi \ - typing/path.cmi utils/misc.cmi parsing/longident.cmi parsing/location.cmi \ - typing/ident.cmi typing/env.cmi utils/clflags.cmi typing/btype.cmi \ - parsing/asttypes.cmi typing/ctype.cmi -typing/ctype.cmx : typing/types.cmx typing/subst.cmx typing/predef.cmx \ - typing/path.cmx utils/misc.cmx parsing/longident.cmx parsing/location.cmx \ - typing/ident.cmx typing/env.cmx utils/clflags.cmx typing/btype.cmx \ - parsing/asttypes.cmi typing/ctype.cmi -typing/ctype.cmi : typing/types.cmi typing/path.cmi parsing/longident.cmi \ - typing/ident.cmi typing/env.cmi parsing/asttypes.cmi -typing/datarepr.cmo : typing/types.cmi typing/path.cmi parsing/location.cmi \ - typing/ident.cmi typing/btype.cmi parsing/asttypes.cmi \ +parsing/printast.cmi : \ + parsing/parsetree.cmi +parsing/syntaxerr.cmo : \ + parsing/location.cmi \ + parsing/syntaxerr.cmi +parsing/syntaxerr.cmx : \ + parsing/location.cmx \ + parsing/syntaxerr.cmi +parsing/syntaxerr.cmi : \ + parsing/location.cmi +typing/annot.cmi : \ + parsing/location.cmi +typing/btype.cmo : \ + typing/types.cmi \ + typing/path.cmi \ + utils/misc.cmi \ + typing/ident.cmi \ + parsing/asttypes.cmi \ + typing/btype.cmi +typing/btype.cmx : \ + typing/types.cmx \ + typing/path.cmx \ + utils/misc.cmx \ + typing/ident.cmx \ + parsing/asttypes.cmi \ + typing/btype.cmi +typing/btype.cmi : \ + typing/types.cmi \ + typing/path.cmi \ + parsing/asttypes.cmi +typing/cmi_format.cmo : \ + typing/types.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + utils/config.cmi \ + typing/cmi_format.cmi +typing/cmi_format.cmx : \ + typing/types.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + utils/config.cmx \ + typing/cmi_format.cmi +typing/cmi_format.cmi : \ + typing/types.cmi \ + utils/misc.cmi +typing/cmt_format.cmo : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/tast_mapper.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + parsing/lexer.cmi \ + typing/env.cmi \ + utils/config.cmi \ + typing/cmi_format.cmi \ + utils/clflags.cmi \ + typing/cmt_format.cmi +typing/cmt_format.cmx : \ + typing/types.cmx \ + typing/typedtree.cmx \ + typing/tast_mapper.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + utils/load_path.cmx \ + parsing/lexer.cmx \ + typing/env.cmx \ + utils/config.cmx \ + typing/cmi_format.cmx \ + utils/clflags.cmx \ + typing/cmt_format.cmi +typing/cmt_format.cmi : \ + typing/types.cmi \ + typing/typedtree.cmi \ + parsing/location.cmi \ + typing/env.cmi \ + typing/cmi_format.cmi +typing/ctype.cmo : \ + typing/types.cmi \ + typing/subst.cmi \ + typing/predef.cmi \ + typing/path.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + utils/clflags.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ + typing/ctype.cmi +typing/ctype.cmx : \ + typing/types.cmx \ + typing/subst.cmx \ + typing/predef.cmx \ + typing/path.cmx \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + utils/clflags.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ + typing/ctype.cmi +typing/ctype.cmi : \ + typing/types.cmi \ + typing/path.cmi \ + parsing/longident.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + parsing/asttypes.cmi +typing/datarepr.cmo : \ + typing/types.cmi \ + typing/path.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ typing/datarepr.cmi -typing/datarepr.cmx : typing/types.cmx typing/path.cmx parsing/location.cmx \ - typing/ident.cmx typing/btype.cmx parsing/asttypes.cmi \ +typing/datarepr.cmx : \ + typing/types.cmx \ + typing/path.cmx \ + parsing/location.cmx \ + typing/ident.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ typing/datarepr.cmi -typing/datarepr.cmi : typing/types.cmi typing/path.cmi typing/ident.cmi -typing/env.cmo : utils/warnings.cmi typing/types.cmi utils/tbl.cmi \ - typing/subst.cmi typing/predef.cmi typing/path.cmi utils/misc.cmi \ - parsing/longident.cmi parsing/location.cmi typing/ident.cmi \ - typing/datarepr.cmi utils/consistbl.cmi utils/config.cmi \ - typing/cmi_format.cmi utils/clflags.cmi parsing/builtin_attributes.cmi \ - typing/btype.cmi parsing/asttypes.cmi typing/env.cmi -typing/env.cmx : utils/warnings.cmx typing/types.cmx utils/tbl.cmx \ - typing/subst.cmx typing/predef.cmx typing/path.cmx utils/misc.cmx \ - parsing/longident.cmx parsing/location.cmx typing/ident.cmx \ - typing/datarepr.cmx utils/consistbl.cmx utils/config.cmx \ - typing/cmi_format.cmx utils/clflags.cmx parsing/builtin_attributes.cmx \ - typing/btype.cmx parsing/asttypes.cmi typing/env.cmi -typing/env.cmi : utils/warnings.cmi typing/types.cmi typing/subst.cmi \ - typing/path.cmi utils/misc.cmi parsing/longident.cmi parsing/location.cmi \ - typing/ident.cmi utils/consistbl.cmi typing/cmi_format.cmi \ +typing/datarepr.cmi : \ + typing/types.cmi \ + typing/path.cmi \ + typing/ident.cmi +typing/env.cmo : \ + utils/warnings.cmi \ + typing/types.cmi \ + typing/subst.cmi \ + typing/predef.cmi \ + typing/path.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + typing/ident.cmi \ + typing/datarepr.cmi \ + utils/consistbl.cmi \ + utils/config.cmi \ + typing/cmi_format.cmi \ + utils/clflags.cmi \ + parsing/builtin_attributes.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ + typing/env.cmi +typing/env.cmx : \ + utils/warnings.cmx \ + typing/types.cmx \ + typing/subst.cmx \ + typing/predef.cmx \ + typing/path.cmx \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + utils/load_path.cmx \ + typing/ident.cmx \ + typing/datarepr.cmx \ + utils/consistbl.cmx \ + utils/config.cmx \ + typing/cmi_format.cmx \ + utils/clflags.cmx \ + parsing/builtin_attributes.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ + typing/env.cmi +typing/env.cmi : \ + utils/warnings.cmi \ + typing/types.cmi \ + typing/subst.cmi \ + typing/path.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + typing/ident.cmi \ + utils/consistbl.cmi \ + typing/cmi_format.cmi \ parsing/asttypes.cmi -typing/envaux.cmo : typing/subst.cmi typing/printtyp.cmi typing/path.cmi \ - typing/ident.cmi typing/env.cmi typing/envaux.cmi -typing/envaux.cmx : typing/subst.cmx typing/printtyp.cmx typing/path.cmx \ - typing/ident.cmx typing/env.cmx typing/envaux.cmi -typing/envaux.cmi : typing/subst.cmi typing/path.cmi typing/env.cmi -typing/ident.cmo : utils/identifiable.cmi utils/clflags.cmi typing/ident.cmi -typing/ident.cmx : utils/identifiable.cmx utils/clflags.cmx typing/ident.cmi -typing/ident.cmi : utils/identifiable.cmi -typing/includeclass.cmo : typing/types.cmi typing/printtyp.cmi \ - typing/path.cmi typing/ctype.cmi parsing/builtin_attributes.cmi \ +typing/envaux.cmo : \ + typing/subst.cmi \ + typing/printtyp.cmi \ + typing/path.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + parsing/asttypes.cmi \ + typing/envaux.cmi +typing/envaux.cmx : \ + typing/subst.cmx \ + typing/printtyp.cmx \ + typing/path.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + parsing/asttypes.cmi \ + typing/envaux.cmi +typing/envaux.cmi : \ + typing/subst.cmi \ + typing/path.cmi \ + typing/env.cmi +typing/ident.cmo : \ + utils/misc.cmi \ + utils/identifiable.cmi \ + utils/clflags.cmi \ + typing/ident.cmi +typing/ident.cmx : \ + utils/misc.cmx \ + utils/identifiable.cmx \ + utils/clflags.cmx \ + typing/ident.cmi +typing/ident.cmi : \ + utils/identifiable.cmi +typing/includeclass.cmo : \ + typing/types.cmi \ + typing/printtyp.cmi \ + typing/path.cmi \ + typing/ctype.cmi \ + parsing/builtin_attributes.cmi \ typing/includeclass.cmi -typing/includeclass.cmx : typing/types.cmx typing/printtyp.cmx \ - typing/path.cmx typing/ctype.cmx parsing/builtin_attributes.cmx \ +typing/includeclass.cmx : \ + typing/types.cmx \ + typing/printtyp.cmx \ + typing/path.cmx \ + typing/ctype.cmx \ + parsing/builtin_attributes.cmx \ typing/includeclass.cmi -typing/includeclass.cmi : typing/types.cmi parsing/location.cmi \ - typing/env.cmi typing/ctype.cmi -typing/includecore.cmo : typing/types.cmi typing/typedtree.cmi \ - typing/path.cmi typing/ident.cmi typing/env.cmi typing/ctype.cmi \ - parsing/builtin_attributes.cmi typing/btype.cmi parsing/asttypes.cmi \ +typing/includeclass.cmi : \ + typing/types.cmi \ + parsing/location.cmi \ + typing/env.cmi \ + typing/ctype.cmi +typing/includecore.cmo : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/path.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + parsing/builtin_attributes.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ typing/includecore.cmi -typing/includecore.cmx : typing/types.cmx typing/typedtree.cmx \ - typing/path.cmx typing/ident.cmx typing/env.cmx typing/ctype.cmx \ - parsing/builtin_attributes.cmx typing/btype.cmx parsing/asttypes.cmi \ +typing/includecore.cmx : \ + typing/types.cmx \ + typing/typedtree.cmx \ + typing/path.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + typing/ctype.cmx \ + parsing/builtin_attributes.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ typing/includecore.cmi -typing/includecore.cmi : typing/types.cmi typing/typedtree.cmi \ - parsing/location.cmi typing/ident.cmi typing/env.cmi -typing/includemod.cmo : typing/types.cmi typing/typedtree.cmi utils/tbl.cmi \ - typing/subst.cmi typing/printtyp.cmi typing/primitive.cmi typing/path.cmi \ - typing/mtype.cmi utils/misc.cmi parsing/location.cmi \ - typing/includecore.cmi typing/includeclass.cmi typing/ident.cmi \ - typing/env.cmi typing/ctype.cmi typing/cmt_format.cmi utils/clflags.cmi \ - parsing/builtin_attributes.cmi typing/btype.cmi typing/includemod.cmi -typing/includemod.cmx : typing/types.cmx typing/typedtree.cmx utils/tbl.cmx \ - typing/subst.cmx typing/printtyp.cmx typing/primitive.cmx typing/path.cmx \ - typing/mtype.cmx utils/misc.cmx parsing/location.cmx \ - typing/includecore.cmx typing/includeclass.cmx typing/ident.cmx \ - typing/env.cmx typing/ctype.cmx typing/cmt_format.cmx utils/clflags.cmx \ - parsing/builtin_attributes.cmx typing/btype.cmx typing/includemod.cmi -typing/includemod.cmi : typing/types.cmi typing/typedtree.cmi \ - typing/path.cmi parsing/location.cmi typing/includecore.cmi \ - typing/ident.cmi typing/env.cmi typing/ctype.cmi -typing/mtype.cmo : typing/types.cmi typing/subst.cmi typing/path.cmi \ - utils/misc.cmi parsing/location.cmi typing/ident.cmi typing/env.cmi \ - typing/ctype.cmi utils/clflags.cmi typing/btype.cmi parsing/asttypes.cmi \ +typing/includecore.cmi : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/path.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi +typing/includemod.cmo : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/subst.cmi \ + typing/printtyp.cmi \ + typing/primitive.cmi \ + typing/path.cmi \ + typing/oprint.cmi \ + typing/mtype.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + typing/includecore.cmi \ + typing/includeclass.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + typing/cmt_format.cmi \ + utils/clflags.cmi \ + parsing/builtin_attributes.cmi \ + typing/btype.cmi \ + typing/includemod.cmi +typing/includemod.cmx : \ + typing/types.cmx \ + typing/typedtree.cmx \ + typing/subst.cmx \ + typing/printtyp.cmx \ + typing/primitive.cmx \ + typing/path.cmx \ + typing/oprint.cmx \ + typing/mtype.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + typing/includecore.cmx \ + typing/includeclass.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + typing/ctype.cmx \ + typing/cmt_format.cmx \ + utils/clflags.cmx \ + parsing/builtin_attributes.cmx \ + typing/btype.cmx \ + typing/includemod.cmi +typing/includemod.cmi : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/path.cmi \ + parsing/location.cmi \ + typing/includecore.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi +typing/mtype.cmo : \ + typing/types.cmi \ + typing/subst.cmi \ + typing/path.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + utils/clflags.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ typing/mtype.cmi -typing/mtype.cmx : typing/types.cmx typing/subst.cmx typing/path.cmx \ - utils/misc.cmx parsing/location.cmx typing/ident.cmx typing/env.cmx \ - typing/ctype.cmx utils/clflags.cmx typing/btype.cmx parsing/asttypes.cmi \ +typing/mtype.cmx : \ + typing/types.cmx \ + typing/subst.cmx \ + typing/path.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + typing/ctype.cmx \ + utils/clflags.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ typing/mtype.cmi -typing/mtype.cmi : typing/types.cmi typing/path.cmi typing/ident.cmi \ +typing/mtype.cmi : \ + typing/types.cmi \ + typing/path.cmi \ + typing/ident.cmi \ typing/env.cmi -typing/oprint.cmo : typing/outcometree.cmi parsing/asttypes.cmi \ +typing/oprint.cmo : \ + parsing/pprintast.cmi \ + typing/outcometree.cmi \ + parsing/asttypes.cmi \ typing/oprint.cmi -typing/oprint.cmx : typing/outcometree.cmi parsing/asttypes.cmi \ +typing/oprint.cmx : \ + parsing/pprintast.cmx \ + typing/outcometree.cmi \ + parsing/asttypes.cmi \ typing/oprint.cmi -typing/oprint.cmi : typing/outcometree.cmi -typing/outcometree.cmi : parsing/asttypes.cmi -typing/parmatch.cmo : utils/warnings.cmi typing/untypeast.cmi \ - typing/types.cmi typing/typedtreeIter.cmi typing/typedtree.cmi \ - typing/subst.cmi typing/printpat.cmi typing/predef.cmi typing/path.cmi \ - parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \ - parsing/location.cmi typing/ident.cmi typing/env.cmi typing/ctype.cmi \ - utils/config.cmi typing/btype.cmi parsing/asttypes.cmi \ - parsing/ast_helper.cmi typing/parmatch.cmi -typing/parmatch.cmx : utils/warnings.cmx typing/untypeast.cmx \ - typing/types.cmx typing/typedtreeIter.cmx typing/typedtree.cmx \ - typing/subst.cmx typing/printpat.cmx typing/predef.cmx typing/path.cmx \ - parsing/parsetree.cmi utils/misc.cmx parsing/longident.cmx \ - parsing/location.cmx typing/ident.cmx typing/env.cmx typing/ctype.cmx \ - utils/config.cmx typing/btype.cmx parsing/asttypes.cmi \ - parsing/ast_helper.cmx typing/parmatch.cmi -typing/parmatch.cmi : typing/types.cmi typing/typedtree.cmi \ - parsing/parsetree.cmi parsing/location.cmi typing/env.cmi \ +typing/oprint.cmi : \ + typing/outcometree.cmi +typing/outcometree.cmi : \ + parsing/asttypes.cmi +typing/parmatch.cmo : \ + utils/warnings.cmi \ + typing/untypeast.cmi \ + typing/types.cmi \ + typing/typedtreeIter.cmi \ + typing/typedtree.cmi \ + typing/subst.cmi \ + typing/printpat.cmi \ + typing/predef.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + utils/config.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmi \ + typing/parmatch.cmi +typing/parmatch.cmx : \ + utils/warnings.cmx \ + typing/untypeast.cmx \ + typing/types.cmx \ + typing/typedtreeIter.cmx \ + typing/typedtree.cmx \ + typing/subst.cmx \ + typing/printpat.cmx \ + typing/predef.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + typing/ctype.cmx \ + utils/config.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmx \ + typing/parmatch.cmi +typing/parmatch.cmi : \ + typing/types.cmi \ + typing/typedtree.cmi \ + parsing/parsetree.cmi \ + parsing/location.cmi \ + typing/env.cmi \ parsing/asttypes.cmi -typing/path.cmo : typing/ident.cmi typing/path.cmi -typing/path.cmx : typing/ident.cmx typing/path.cmi -typing/path.cmi : typing/ident.cmi -typing/predef.cmo : typing/types.cmi typing/path.cmi parsing/parsetree.cmi \ - parsing/location.cmi typing/ident.cmi typing/btype.cmi \ - parsing/asttypes.cmi typing/predef.cmi -typing/predef.cmx : typing/types.cmx typing/path.cmx parsing/parsetree.cmi \ - parsing/location.cmx typing/ident.cmx typing/btype.cmx \ - parsing/asttypes.cmi typing/predef.cmi -typing/predef.cmi : typing/types.cmi typing/path.cmi typing/ident.cmi -typing/primitive.cmo : parsing/parsetree.cmi typing/outcometree.cmi \ - utils/misc.cmi parsing/location.cmi parsing/attr_helper.cmi \ +typing/path.cmo : \ + typing/ident.cmi \ + typing/path.cmi +typing/path.cmx : \ + typing/ident.cmx \ + typing/path.cmi +typing/path.cmi : \ + typing/ident.cmi +typing/predef.cmo : \ + typing/types.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmi \ + typing/predef.cmi +typing/predef.cmx : \ + typing/types.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + parsing/location.cmx \ + typing/ident.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmx \ + typing/predef.cmi +typing/predef.cmi : \ + typing/types.cmi \ + typing/path.cmi \ + typing/ident.cmi +typing/primitive.cmo : \ + parsing/parsetree.cmi \ + typing/outcometree.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + parsing/attr_helper.cmi \ typing/primitive.cmi -typing/primitive.cmx : parsing/parsetree.cmi typing/outcometree.cmi \ - utils/misc.cmx parsing/location.cmx parsing/attr_helper.cmx \ +typing/primitive.cmx : \ + parsing/parsetree.cmi \ + typing/outcometree.cmi \ + utils/misc.cmx \ + parsing/location.cmx \ + parsing/attr_helper.cmx \ typing/primitive.cmi -typing/primitive.cmi : parsing/parsetree.cmi typing/outcometree.cmi \ +typing/primitive.cmi : \ + parsing/parsetree.cmi \ + typing/outcometree.cmi \ parsing/location.cmi -typing/printpat.cmo : typing/types.cmi typing/typedtree.cmi typing/ident.cmi \ - parsing/asttypes.cmi typing/printpat.cmi -typing/printpat.cmx : typing/types.cmx typing/typedtree.cmx typing/ident.cmx \ - parsing/asttypes.cmi typing/printpat.cmi -typing/printpat.cmi : typing/typedtree.cmi parsing/asttypes.cmi -typing/printtyp.cmo : typing/types.cmi typing/primitive.cmi \ - typing/predef.cmi typing/path.cmi parsing/parsetree.cmi \ - typing/outcometree.cmi typing/oprint.cmi utils/misc.cmi \ - parsing/longident.cmi parsing/location.cmi typing/ident.cmi \ - typing/env.cmi typing/ctype.cmi utils/clflags.cmi \ - parsing/builtin_attributes.cmi typing/btype.cmi parsing/asttypes.cmi \ +typing/printpat.cmo : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/ident.cmi \ + parsing/asttypes.cmi \ + typing/printpat.cmi +typing/printpat.cmx : \ + typing/types.cmx \ + typing/typedtree.cmx \ + typing/ident.cmx \ + parsing/asttypes.cmi \ + typing/printpat.cmi +typing/printpat.cmi : \ + typing/typedtree.cmi \ + parsing/asttypes.cmi +typing/printtyp.cmo : \ + utils/warnings.cmi \ + typing/types.cmi \ + typing/primitive.cmi \ + typing/predef.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + typing/outcometree.cmi \ + typing/oprint.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + utils/clflags.cmi \ + parsing/builtin_attributes.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ typing/printtyp.cmi -typing/printtyp.cmx : typing/types.cmx typing/primitive.cmx \ - typing/predef.cmx typing/path.cmx parsing/parsetree.cmi \ - typing/outcometree.cmi typing/oprint.cmx utils/misc.cmx \ - parsing/longident.cmx parsing/location.cmx typing/ident.cmx \ - typing/env.cmx typing/ctype.cmx utils/clflags.cmx \ - parsing/builtin_attributes.cmx typing/btype.cmx parsing/asttypes.cmi \ +typing/printtyp.cmx : \ + utils/warnings.cmx \ + typing/types.cmx \ + typing/primitive.cmx \ + typing/predef.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + typing/outcometree.cmi \ + typing/oprint.cmx \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + typing/ctype.cmx \ + utils/clflags.cmx \ + parsing/builtin_attributes.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ typing/printtyp.cmi -typing/printtyp.cmi : typing/types.cmi typing/path.cmi \ - typing/outcometree.cmi parsing/longident.cmi typing/ident.cmi \ - typing/env.cmi parsing/asttypes.cmi -typing/printtyped.cmo : typing/types.cmi typing/typedtree.cmi \ - parsing/printast.cmi typing/path.cmi utils/misc.cmi parsing/longident.cmi \ - parsing/location.cmi typing/ident.cmi parsing/asttypes.cmi \ +typing/printtyp.cmi : \ + typing/types.cmi \ + typing/path.cmi \ + typing/outcometree.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + parsing/asttypes.cmi +typing/printtyped.cmo : \ + typing/types.cmi \ + typing/typedtree.cmi \ + parsing/printast.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + parsing/asttypes.cmi \ typing/printtyped.cmi -typing/printtyped.cmx : typing/types.cmx typing/typedtree.cmx \ - parsing/printast.cmx typing/path.cmx utils/misc.cmx parsing/longident.cmx \ - parsing/location.cmx typing/ident.cmx parsing/asttypes.cmi \ +typing/printtyped.cmx : \ + typing/types.cmx \ + typing/typedtree.cmx \ + parsing/printast.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + typing/ident.cmx \ + parsing/asttypes.cmi \ typing/printtyped.cmi -typing/printtyped.cmi : typing/typedtree.cmi -typing/stypes.cmo : typing/typedtree.cmi typing/printtyp.cmi utils/misc.cmi \ - parsing/location.cmi utils/clflags.cmi typing/annot.cmi typing/stypes.cmi -typing/stypes.cmx : typing/typedtree.cmx typing/printtyp.cmx utils/misc.cmx \ - parsing/location.cmx utils/clflags.cmx typing/annot.cmi typing/stypes.cmi -typing/stypes.cmi : typing/typedtree.cmi parsing/location.cmi \ +typing/printtyped.cmi : \ + typing/typedtree.cmi +typing/rec_check.cmo : \ + typing/types.cmi \ + typing/typeopt.cmi \ + typing/typedtree.cmi \ + typing/primitive.cmi \ + typing/path.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + parsing/asttypes.cmi \ + typing/rec_check.cmi +typing/rec_check.cmx : \ + typing/types.cmx \ + typing/typeopt.cmx \ + typing/typedtree.cmx \ + typing/primitive.cmx \ + typing/path.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + parsing/asttypes.cmi \ + typing/rec_check.cmi +typing/rec_check.cmi : \ + typing/typedtree.cmi \ + typing/ident.cmi +typing/stypes.cmo : \ + typing/typedtree.cmi \ + typing/printtyp.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + utils/clflags.cmi \ + typing/annot.cmi \ + typing/stypes.cmi +typing/stypes.cmx : \ + typing/typedtree.cmx \ + typing/printtyp.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + utils/clflags.cmx \ + typing/annot.cmi \ + typing/stypes.cmi +typing/stypes.cmi : \ + typing/typedtree.cmi \ + parsing/location.cmi \ typing/annot.cmi -typing/subst.cmo : typing/types.cmi utils/tbl.cmi typing/path.cmi \ - utils/misc.cmi parsing/location.cmi typing/ident.cmi utils/clflags.cmi \ - typing/btype.cmi parsing/ast_mapper.cmi typing/subst.cmi -typing/subst.cmx : typing/types.cmx utils/tbl.cmx typing/path.cmx \ - utils/misc.cmx parsing/location.cmx typing/ident.cmx utils/clflags.cmx \ - typing/btype.cmx parsing/ast_mapper.cmx typing/subst.cmi -typing/subst.cmi : typing/types.cmi typing/path.cmi typing/ident.cmi -typing/tast_mapper.cmo : typing/typedtree.cmi typing/env.cmi \ - parsing/asttypes.cmi typing/tast_mapper.cmi -typing/tast_mapper.cmx : typing/typedtree.cmx typing/env.cmx \ - parsing/asttypes.cmi typing/tast_mapper.cmi -typing/tast_mapper.cmi : typing/typedtree.cmi typing/env.cmi \ +typing/subst.cmo : \ + typing/types.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + utils/clflags.cmi \ + typing/btype.cmi \ + parsing/ast_mapper.cmi \ + typing/subst.cmi +typing/subst.cmx : \ + typing/types.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + utils/misc.cmx \ + parsing/location.cmx \ + typing/ident.cmx \ + utils/clflags.cmx \ + typing/btype.cmx \ + parsing/ast_mapper.cmx \ + typing/subst.cmi +typing/subst.cmi : \ + typing/types.cmi \ + typing/path.cmi \ + typing/ident.cmi +typing/tast_mapper.cmo : \ + typing/typedtree.cmi \ + typing/env.cmi \ + parsing/asttypes.cmi \ + typing/tast_mapper.cmi +typing/tast_mapper.cmx : \ + typing/typedtree.cmx \ + typing/env.cmx \ + parsing/asttypes.cmi \ + typing/tast_mapper.cmi +typing/tast_mapper.cmi : \ + typing/typedtree.cmi \ + typing/env.cmi \ + parsing/asttypes.cmi +typing/typeclass.cmo : \ + utils/warnings.cmi \ + typing/typetexp.cmi \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/typedecl_variance.cmi \ + typing/typedecl.cmi \ + typing/typecore.cmi \ + typing/subst.cmi \ + typing/stypes.cmi \ + typing/printtyp.cmi \ + typing/predef.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + typing/oprint.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/includeclass.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + typing/cmt_format.cmi \ + utils/clflags.cmi \ + parsing/builtin_attributes.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmi \ + typing/typeclass.cmi +typing/typeclass.cmx : \ + utils/warnings.cmx \ + typing/typetexp.cmx \ + typing/types.cmx \ + typing/typedtree.cmx \ + typing/typedecl_variance.cmx \ + typing/typedecl.cmx \ + typing/typecore.cmx \ + typing/subst.cmx \ + typing/stypes.cmx \ + typing/printtyp.cmx \ + typing/predef.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + typing/oprint.cmx \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + typing/includeclass.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + typing/ctype.cmx \ + typing/cmt_format.cmx \ + utils/clflags.cmx \ + parsing/builtin_attributes.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmx \ + typing/typeclass.cmi +typing/typeclass.cmi : \ + typing/types.cmi \ + typing/typedtree.cmi \ + parsing/parsetree.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ parsing/asttypes.cmi -typing/typeclass.cmo : utils/warnings.cmi typing/typetexp.cmi \ - typing/types.cmi typing/typedtree.cmi typing/typedecl.cmi \ - typing/typecore.cmi typing/subst.cmi typing/stypes.cmi \ - typing/printtyp.cmi typing/predef.cmi typing/path.cmi \ - parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \ - parsing/location.cmi typing/includeclass.cmi typing/ident.cmi \ - typing/env.cmi typing/ctype.cmi typing/cmt_format.cmi utils/clflags.cmi \ - parsing/builtin_attributes.cmi typing/btype.cmi parsing/asttypes.cmi \ - parsing/ast_helper.cmi typing/typeclass.cmi -typing/typeclass.cmx : utils/warnings.cmx typing/typetexp.cmx \ - typing/types.cmx typing/typedtree.cmx typing/typedecl.cmx \ - typing/typecore.cmx typing/subst.cmx typing/stypes.cmx \ - typing/printtyp.cmx typing/predef.cmx typing/path.cmx \ - parsing/parsetree.cmi utils/misc.cmx parsing/longident.cmx \ - parsing/location.cmx typing/includeclass.cmx typing/ident.cmx \ - typing/env.cmx typing/ctype.cmx typing/cmt_format.cmx utils/clflags.cmx \ - parsing/builtin_attributes.cmx typing/btype.cmx parsing/asttypes.cmi \ - parsing/ast_helper.cmx typing/typeclass.cmi -typing/typeclass.cmi : typing/types.cmi typing/typedtree.cmi \ - parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \ - typing/ident.cmi typing/env.cmi typing/ctype.cmi parsing/asttypes.cmi -typing/typecore.cmo : utils/warnings.cmi typing/typetexp.cmi \ - typing/types.cmi typing/typeopt.cmi typing/typedtree.cmi \ - typing/typedecl.cmi typing/subst.cmi typing/stypes.cmi \ - typing/printtyp.cmi typing/printpat.cmi typing/primitive.cmi \ - typing/predef.cmi typing/path.cmi parsing/parsetree.cmi \ - typing/parmatch.cmi typing/oprint.cmi typing/mtype.cmi utils/misc.cmi \ - parsing/longident.cmi parsing/location.cmi typing/ident.cmi \ - typing/env.cmi typing/ctype.cmi utils/config.cmi typing/cmt_format.cmi \ - utils/clflags.cmi parsing/builtin_attributes.cmi typing/btype.cmi \ - parsing/asttypes.cmi parsing/ast_helper.cmi typing/annot.cmi \ +typing/typecore.cmo : \ + utils/warnings.cmi \ + typing/typetexp.cmi \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/typedecl.cmi \ + typing/subst.cmi \ + typing/stypes.cmi \ + typing/rec_check.cmi \ + typing/printtyp.cmi \ + typing/printpat.cmi \ + typing/primitive.cmi \ + typing/predef.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + typing/parmatch.cmi \ + typing/oprint.cmi \ + typing/mtype.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + typing/cmt_format.cmi \ + utils/clflags.cmi \ + parsing/builtin_attributes.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmi \ + typing/annot.cmi \ typing/typecore.cmi -typing/typecore.cmx : utils/warnings.cmx typing/typetexp.cmx \ - typing/types.cmx typing/typeopt.cmx typing/typedtree.cmx \ - typing/typedecl.cmx typing/subst.cmx typing/stypes.cmx \ - typing/printtyp.cmx typing/printpat.cmx typing/primitive.cmx \ - typing/predef.cmx typing/path.cmx parsing/parsetree.cmi \ - typing/parmatch.cmx typing/oprint.cmx typing/mtype.cmx utils/misc.cmx \ - parsing/longident.cmx parsing/location.cmx typing/ident.cmx \ - typing/env.cmx typing/ctype.cmx utils/config.cmx typing/cmt_format.cmx \ - utils/clflags.cmx parsing/builtin_attributes.cmx typing/btype.cmx \ - parsing/asttypes.cmi parsing/ast_helper.cmx typing/annot.cmi \ +typing/typecore.cmx : \ + utils/warnings.cmx \ + typing/typetexp.cmx \ + typing/types.cmx \ + typing/typedtree.cmx \ + typing/typedecl.cmx \ + typing/subst.cmx \ + typing/stypes.cmx \ + typing/rec_check.cmx \ + typing/printtyp.cmx \ + typing/printpat.cmx \ + typing/primitive.cmx \ + typing/predef.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + typing/parmatch.cmx \ + typing/oprint.cmx \ + typing/mtype.cmx \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + typing/ctype.cmx \ + typing/cmt_format.cmx \ + utils/clflags.cmx \ + parsing/builtin_attributes.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmx \ + typing/annot.cmi \ typing/typecore.cmi -typing/typecore.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \ - parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \ - typing/ident.cmi typing/env.cmi parsing/asttypes.cmi typing/annot.cmi -typing/typedecl.cmo : utils/warnings.cmi typing/typetexp.cmi \ - typing/types.cmi typing/typedtree.cmi typing/subst.cmi \ - typing/printtyp.cmi typing/primitive.cmi typing/predef.cmi \ - typing/path.cmi parsing/parsetree.cmi utils/misc.cmi \ - parsing/longident.cmi parsing/location.cmi typing/includecore.cmi \ - typing/ident.cmi typing/env.cmi typing/datarepr.cmi typing/ctype.cmi \ - utils/config.cmi utils/clflags.cmi parsing/builtin_attributes.cmi \ - typing/btype.cmi parsing/attr_helper.cmi parsing/asttypes.cmi \ - parsing/ast_iterator.cmi parsing/ast_helper.cmi typing/typedecl.cmi -typing/typedecl.cmx : utils/warnings.cmx typing/typetexp.cmx \ - typing/types.cmx typing/typedtree.cmx typing/subst.cmx \ - typing/printtyp.cmx typing/primitive.cmx typing/predef.cmx \ - typing/path.cmx parsing/parsetree.cmi utils/misc.cmx \ - parsing/longident.cmx parsing/location.cmx typing/includecore.cmx \ - typing/ident.cmx typing/env.cmx typing/datarepr.cmx typing/ctype.cmx \ - utils/config.cmx utils/clflags.cmx parsing/builtin_attributes.cmx \ - typing/btype.cmx parsing/attr_helper.cmx parsing/asttypes.cmi \ - parsing/ast_iterator.cmx parsing/ast_helper.cmx typing/typedecl.cmi -typing/typedecl.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \ - parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \ - typing/includecore.cmi typing/ident.cmi typing/env.cmi \ +typing/typecore.cmi : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + parsing/asttypes.cmi \ + typing/annot.cmi +typing/typedecl.cmo : \ + utils/warnings.cmi \ + typing/typetexp.cmi \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/typedecl_variance.cmi \ + typing/typedecl_unboxed.cmi \ + typing/typedecl_immediacy.cmi \ + typing/subst.cmi \ + typing/printtyp.cmi \ + typing/primitive.cmi \ + typing/predef.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + typing/oprint.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/includecore.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/datarepr.cmi \ + typing/ctype.cmi \ + utils/config.cmi \ + utils/clflags.cmi \ + parsing/builtin_attributes.cmi \ + typing/btype.cmi \ + parsing/attr_helper.cmi \ + parsing/asttypes.cmi \ + parsing/ast_iterator.cmi \ + parsing/ast_helper.cmi \ + typing/typedecl.cmi +typing/typedecl.cmx : \ + utils/warnings.cmx \ + typing/typetexp.cmx \ + typing/types.cmx \ + typing/typedtree.cmx \ + typing/typedecl_variance.cmx \ + typing/typedecl_unboxed.cmx \ + typing/typedecl_immediacy.cmx \ + typing/subst.cmx \ + typing/printtyp.cmx \ + typing/primitive.cmx \ + typing/predef.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + typing/oprint.cmx \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + typing/includecore.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + typing/datarepr.cmx \ + typing/ctype.cmx \ + utils/config.cmx \ + utils/clflags.cmx \ + parsing/builtin_attributes.cmx \ + typing/btype.cmx \ + parsing/attr_helper.cmx \ + parsing/asttypes.cmi \ + parsing/ast_iterator.cmx \ + parsing/ast_helper.cmx \ + typing/typedecl.cmi +typing/typedecl.cmi : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/typedecl_variance.cmi \ + typing/typedecl_immediacy.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/includecore.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + parsing/asttypes.cmi +typing/typedecl_immediacy.cmo : \ + typing/types.cmi \ + typing/typedecl_unboxed.cmi \ + typing/typedecl_properties.cmi \ + parsing/location.cmi \ + typing/ctype.cmi \ + parsing/builtin_attributes.cmi \ + typing/typedecl_immediacy.cmi +typing/typedecl_immediacy.cmx : \ + typing/types.cmx \ + typing/typedecl_unboxed.cmx \ + typing/typedecl_properties.cmx \ + parsing/location.cmx \ + typing/ctype.cmx \ + parsing/builtin_attributes.cmx \ + typing/typedecl_immediacy.cmi +typing/typedecl_immediacy.cmi : \ + typing/types.cmi \ + typing/typedecl_properties.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi +typing/typedecl_properties.cmo : \ + typing/types.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + parsing/builtin_attributes.cmi \ + typing/typedecl_properties.cmi +typing/typedecl_properties.cmx : \ + typing/types.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + parsing/builtin_attributes.cmx \ + typing/typedecl_properties.cmi +typing/typedecl_properties.cmi : \ + typing/types.cmi \ + typing/ident.cmi \ + typing/env.cmi +typing/typedecl_unboxed.cmo : \ + typing/types.cmi \ + typing/predef.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + typing/typedecl_unboxed.cmi +typing/typedecl_unboxed.cmx : \ + typing/types.cmx \ + typing/predef.cmx \ + typing/env.cmx \ + typing/ctype.cmx \ + typing/typedecl_unboxed.cmi +typing/typedecl_unboxed.cmi : \ + typing/types.cmi \ + typing/env.cmi +typing/typedecl_variance.cmo : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/typedecl_properties.cmi \ + parsing/parsetree.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ + typing/typedecl_variance.cmi +typing/typedecl_variance.cmx : \ + typing/types.cmx \ + typing/typedtree.cmx \ + typing/typedecl_properties.cmx \ + parsing/parsetree.cmi \ + parsing/location.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + typing/ctype.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ + typing/typedecl_variance.cmi +typing/typedecl_variance.cmi : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/typedecl_properties.cmi \ + parsing/parsetree.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi \ parsing/asttypes.cmi -typing/typedtree.cmo : typing/types.cmi typing/primitive.cmi typing/path.cmi \ - parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \ - parsing/location.cmi typing/ident.cmi typing/env.cmi parsing/asttypes.cmi \ +typing/typedtree.cmo : \ + typing/types.cmi \ + typing/primitive.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + parsing/asttypes.cmi \ typing/typedtree.cmi -typing/typedtree.cmx : typing/types.cmx typing/primitive.cmx typing/path.cmx \ - parsing/parsetree.cmi utils/misc.cmx parsing/longident.cmx \ - parsing/location.cmx typing/ident.cmx typing/env.cmx parsing/asttypes.cmi \ +typing/typedtree.cmx : \ + typing/types.cmx \ + typing/primitive.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + parsing/asttypes.cmi \ typing/typedtree.cmi -typing/typedtree.cmi : typing/types.cmi typing/primitive.cmi typing/path.cmi \ - parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \ - typing/ident.cmi typing/env.cmi parsing/asttypes.cmi -typing/typedtreeIter.cmo : typing/typedtree.cmi utils/misc.cmi \ - parsing/asttypes.cmi typing/typedtreeIter.cmi -typing/typedtreeIter.cmx : typing/typedtree.cmx utils/misc.cmx \ - parsing/asttypes.cmi typing/typedtreeIter.cmi -typing/typedtreeIter.cmi : typing/typedtree.cmi parsing/asttypes.cmi -typing/typedtreeMap.cmo : typing/typedtree.cmi utils/misc.cmi \ - typing/typedtreeMap.cmi -typing/typedtreeMap.cmx : typing/typedtree.cmx utils/misc.cmx \ - typing/typedtreeMap.cmi -typing/typedtreeMap.cmi : typing/typedtree.cmi -typing/typemod.cmo : utils/warnings.cmi typing/typetexp.cmi typing/types.cmi \ - typing/typedtree.cmi typing/typedecl.cmi typing/typecore.cmi \ - typing/typeclass.cmi typing/subst.cmi typing/stypes.cmi \ - typing/printtyp.cmi typing/path.cmi parsing/parsetree.cmi \ - typing/mtype.cmi utils/misc.cmi parsing/longident.cmi \ - parsing/location.cmi typing/includemod.cmi typing/ident.cmi \ - typing/env.cmi typing/ctype.cmi utils/config.cmi typing/cmt_format.cmi \ - typing/cmi_format.cmi utils/clflags.cmi parsing/builtin_attributes.cmi \ - typing/btype.cmi parsing/attr_helper.cmi parsing/asttypes.cmi \ - typing/annot.cmi typing/typemod.cmi -typing/typemod.cmx : utils/warnings.cmx typing/typetexp.cmx typing/types.cmx \ - typing/typedtree.cmx typing/typedecl.cmx typing/typecore.cmx \ - typing/typeclass.cmx typing/subst.cmx typing/stypes.cmx \ - typing/printtyp.cmx typing/path.cmx parsing/parsetree.cmi \ - typing/mtype.cmx utils/misc.cmx parsing/longident.cmx \ - parsing/location.cmx typing/includemod.cmx typing/ident.cmx \ - typing/env.cmx typing/ctype.cmx utils/config.cmx typing/cmt_format.cmx \ - typing/cmi_format.cmx utils/clflags.cmx parsing/builtin_attributes.cmx \ - typing/btype.cmx parsing/attr_helper.cmx parsing/asttypes.cmi \ - typing/annot.cmi typing/typemod.cmi -typing/typemod.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \ - parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \ - parsing/location.cmi typing/includemod.cmi typing/ident.cmi \ - typing/env.cmi typing/cmi_format.cmi parsing/asttypes.cmi -typing/typeopt.cmo : typing/types.cmi typing/typedtree.cmi \ - typing/typedecl.cmi typing/predef.cmi typing/path.cmi bytecomp/lambda.cmi \ - typing/ident.cmi typing/env.cmi typing/ctype.cmi utils/config.cmi \ - parsing/asttypes.cmi typing/typeopt.cmi -typing/typeopt.cmx : typing/types.cmx typing/typedtree.cmx \ - typing/typedecl.cmx typing/predef.cmx typing/path.cmx bytecomp/lambda.cmx \ - typing/ident.cmx typing/env.cmx typing/ctype.cmx utils/config.cmx \ - parsing/asttypes.cmi typing/typeopt.cmi -typing/typeopt.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \ - bytecomp/lambda.cmi typing/env.cmi -typing/types.cmo : typing/primitive.cmi typing/path.cmi \ - parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \ - typing/ident.cmi parsing/asttypes.cmi typing/types.cmi -typing/types.cmx : typing/primitive.cmx typing/path.cmx \ - parsing/parsetree.cmi parsing/longident.cmx parsing/location.cmx \ - typing/ident.cmx parsing/asttypes.cmi typing/types.cmi -typing/types.cmi : typing/primitive.cmi typing/path.cmi \ - parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \ - typing/ident.cmi parsing/asttypes.cmi -typing/typetexp.cmo : typing/types.cmi typing/typedtree.cmi utils/tbl.cmi \ - typing/printtyp.cmi typing/predef.cmi typing/path.cmi \ - parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \ - parsing/location.cmi typing/includemod.cmi typing/env.cmi \ - typing/ctype.cmi utils/clflags.cmi parsing/builtin_attributes.cmi \ - typing/btype.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \ +typing/typedtree.cmi : \ + typing/types.cmi \ + typing/primitive.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + parsing/asttypes.cmi +typing/typedtreeIter.cmo : \ + typing/typedtree.cmi \ + utils/misc.cmi \ + parsing/asttypes.cmi \ + typing/typedtreeIter.cmi +typing/typedtreeIter.cmx : \ + typing/typedtree.cmx \ + utils/misc.cmx \ + parsing/asttypes.cmi \ + typing/typedtreeIter.cmi +typing/typedtreeIter.cmi : \ + typing/typedtree.cmi \ + parsing/asttypes.cmi +typing/typemod.cmo : \ + utils/warnings.cmi \ + typing/typetexp.cmi \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/typedecl.cmi \ + typing/typecore.cmi \ + typing/typeclass.cmi \ + typing/subst.cmi \ + typing/stypes.cmi \ + typing/printtyp.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + typing/mtype.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + typing/includemod.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + utils/config.cmi \ + typing/cmt_format.cmi \ + typing/cmi_format.cmi \ + utils/clflags.cmi \ + parsing/builtin_attributes.cmi \ + typing/btype.cmi \ + parsing/attr_helper.cmi \ + parsing/asttypes.cmi \ + typing/annot.cmi \ + typing/typemod.cmi +typing/typemod.cmx : \ + utils/warnings.cmx \ + typing/typetexp.cmx \ + typing/types.cmx \ + typing/typedtree.cmx \ + typing/typedecl.cmx \ + typing/typecore.cmx \ + typing/typeclass.cmx \ + typing/subst.cmx \ + typing/stypes.cmx \ + typing/printtyp.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + typing/mtype.cmx \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + utils/load_path.cmx \ + typing/includemod.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + typing/ctype.cmx \ + utils/config.cmx \ + typing/cmt_format.cmx \ + typing/cmi_format.cmx \ + utils/clflags.cmx \ + parsing/builtin_attributes.cmx \ + typing/btype.cmx \ + parsing/attr_helper.cmx \ + parsing/asttypes.cmi \ + typing/annot.cmi \ + typing/typemod.cmi +typing/typemod.cmi : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/typedecl.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/includemod.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/cmi_format.cmi +typing/typeopt.cmo : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/typedecl.cmi \ + typing/predef.cmi \ + typing/path.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + utils/config.cmi \ + parsing/asttypes.cmi \ + typing/typeopt.cmi +typing/typeopt.cmx : \ + typing/types.cmx \ + typing/typedtree.cmx \ + typing/typedecl.cmx \ + typing/predef.cmx \ + typing/path.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + typing/ctype.cmx \ + utils/config.cmx \ + parsing/asttypes.cmi \ + typing/typeopt.cmi +typing/typeopt.cmi : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/path.cmi \ + bytecomp/lambda.cmi \ + typing/env.cmi +typing/types.cmo : \ + typing/primitive.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + parsing/asttypes.cmi \ + typing/types.cmi +typing/types.cmx : \ + typing/primitive.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + typing/ident.cmx \ + parsing/asttypes.cmi \ + typing/types.cmi +typing/types.cmi : \ + typing/primitive.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + parsing/asttypes.cmi +typing/typetexp.cmo : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/printtyp.cmi \ + typing/predef.cmi \ + parsing/pprintast.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + typing/oprint.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/includemod.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + utils/clflags.cmi \ + parsing/builtin_attributes.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmi \ typing/typetexp.cmi -typing/typetexp.cmx : typing/types.cmx typing/typedtree.cmx utils/tbl.cmx \ - typing/printtyp.cmx typing/predef.cmx typing/path.cmx \ - parsing/parsetree.cmi utils/misc.cmx parsing/longident.cmx \ - parsing/location.cmx typing/includemod.cmx typing/env.cmx \ - typing/ctype.cmx utils/clflags.cmx parsing/builtin_attributes.cmx \ - typing/btype.cmx parsing/asttypes.cmi parsing/ast_helper.cmx \ +typing/typetexp.cmx : \ + typing/types.cmx \ + typing/typedtree.cmx \ + typing/printtyp.cmx \ + typing/predef.cmx \ + parsing/pprintast.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + typing/oprint.cmx \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + typing/includemod.cmx \ + typing/env.cmx \ + typing/ctype.cmx \ + utils/clflags.cmx \ + parsing/builtin_attributes.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmx \ typing/typetexp.cmi -typing/typetexp.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \ - parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \ - typing/includemod.cmi typing/env.cmi parsing/asttypes.cmi -typing/untypeast.cmo : typing/typedtree.cmi typing/path.cmi \ - parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \ - parsing/location.cmi typing/ident.cmi typing/env.cmi parsing/asttypes.cmi \ - parsing/ast_helper.cmi typing/untypeast.cmi -typing/untypeast.cmx : typing/typedtree.cmx typing/path.cmx \ - parsing/parsetree.cmi utils/misc.cmx parsing/longident.cmx \ - parsing/location.cmx typing/ident.cmx typing/env.cmx parsing/asttypes.cmi \ - parsing/ast_helper.cmx typing/untypeast.cmi -typing/untypeast.cmi : typing/typedtree.cmi typing/path.cmi \ - parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \ +typing/typetexp.cmi : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/includemod.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ parsing/asttypes.cmi -bytecomp/bytegen.cmo : typing/types.cmi bytecomp/switch.cmi typing/subst.cmi \ - typing/primitive.cmi utils/misc.cmi bytecomp/matching.cmi \ - bytecomp/lambda.cmi bytecomp/instruct.cmi typing/ident.cmi \ - utils/config.cmi parsing/asttypes.cmi bytecomp/bytegen.cmi -bytecomp/bytegen.cmx : typing/types.cmx bytecomp/switch.cmx typing/subst.cmx \ - typing/primitive.cmx utils/misc.cmx bytecomp/matching.cmx \ - bytecomp/lambda.cmx bytecomp/instruct.cmx typing/ident.cmx \ - utils/config.cmx parsing/asttypes.cmi bytecomp/bytegen.cmi -bytecomp/bytegen.cmi : bytecomp/lambda.cmi bytecomp/instruct.cmi -bytecomp/bytelibrarian.cmo : utils/misc.cmi parsing/location.cmi \ - bytecomp/emitcode.cmi utils/config.cmi bytecomp/cmo_format.cmi \ - utils/clflags.cmi bytecomp/bytelink.cmi bytecomp/bytelibrarian.cmi -bytecomp/bytelibrarian.cmx : utils/misc.cmx parsing/location.cmx \ - bytecomp/emitcode.cmx utils/config.cmx bytecomp/cmo_format.cmi \ - utils/clflags.cmx bytecomp/bytelink.cmx bytecomp/bytelibrarian.cmi +typing/untypeast.cmo : \ + typing/typedtree.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmi \ + typing/untypeast.cmi +typing/untypeast.cmx : \ + typing/typedtree.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmx \ + typing/untypeast.cmi +typing/untypeast.cmi : \ + typing/typedtree.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + parsing/asttypes.cmi +bytecomp/bytegen.cmo : \ + typing/types.cmi \ + bytecomp/switch.cmi \ + typing/subst.cmi \ + typing/primitive.cmi \ + utils/misc.cmi \ + bytecomp/matching.cmi \ + bytecomp/lambda.cmi \ + bytecomp/instruct.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + utils/config.cmi \ + parsing/asttypes.cmi \ + bytecomp/bytegen.cmi +bytecomp/bytegen.cmx : \ + typing/types.cmx \ + bytecomp/switch.cmx \ + typing/subst.cmx \ + typing/primitive.cmx \ + utils/misc.cmx \ + bytecomp/matching.cmx \ + bytecomp/lambda.cmx \ + bytecomp/instruct.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + utils/config.cmx \ + parsing/asttypes.cmi \ + bytecomp/bytegen.cmi +bytecomp/bytegen.cmi : \ + bytecomp/lambda.cmi \ + bytecomp/instruct.cmi +bytecomp/bytelibrarian.cmo : \ + utils/misc.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + bytecomp/emitcode.cmi \ + utils/config.cmi \ + bytecomp/cmo_format.cmi \ + utils/clflags.cmi \ + bytecomp/bytelink.cmi \ + bytecomp/bytelibrarian.cmi +bytecomp/bytelibrarian.cmx : \ + utils/misc.cmx \ + parsing/location.cmx \ + utils/load_path.cmx \ + bytecomp/emitcode.cmx \ + utils/config.cmx \ + bytecomp/cmo_format.cmi \ + utils/clflags.cmx \ + bytecomp/bytelink.cmx \ + bytecomp/bytelibrarian.cmi bytecomp/bytelibrarian.cmi : -bytecomp/bytelink.cmo : utils/warnings.cmi bytecomp/symtable.cmi \ - bytecomp/opcodes.cmo utils/misc.cmi parsing/location.cmi \ - bytecomp/instruct.cmi typing/ident.cmi bytecomp/emitcode.cmi \ - bytecomp/dll.cmi utils/consistbl.cmi utils/config.cmi \ - bytecomp/cmo_format.cmi utils/clflags.cmi utils/ccomp.cmi \ - bytecomp/bytesections.cmi bytecomp/bytelink.cmi -bytecomp/bytelink.cmx : utils/warnings.cmx bytecomp/symtable.cmx \ - bytecomp/opcodes.cmx utils/misc.cmx parsing/location.cmx \ - bytecomp/instruct.cmx typing/ident.cmx bytecomp/emitcode.cmx \ - bytecomp/dll.cmx utils/consistbl.cmx utils/config.cmx \ - bytecomp/cmo_format.cmi utils/clflags.cmx utils/ccomp.cmx \ - bytecomp/bytesections.cmx bytecomp/bytelink.cmi -bytecomp/bytelink.cmi : bytecomp/symtable.cmi bytecomp/cmo_format.cmi -bytecomp/bytepackager.cmo : typing/typemod.cmi bytecomp/translmod.cmi \ - typing/subst.cmi bytecomp/printlambda.cmi typing/path.cmi utils/misc.cmi \ - parsing/location.cmi bytecomp/instruct.cmi typing/ident.cmi \ - typing/env.cmi bytecomp/emitcode.cmi utils/config.cmi \ - bytecomp/cmo_format.cmi utils/clflags.cmi bytecomp/bytelink.cmi \ - bytecomp/bytegen.cmi bytecomp/bytepackager.cmi -bytecomp/bytepackager.cmx : typing/typemod.cmx bytecomp/translmod.cmx \ - typing/subst.cmx bytecomp/printlambda.cmx typing/path.cmx utils/misc.cmx \ - parsing/location.cmx bytecomp/instruct.cmx typing/ident.cmx \ - typing/env.cmx bytecomp/emitcode.cmx utils/config.cmx \ - bytecomp/cmo_format.cmi utils/clflags.cmx bytecomp/bytelink.cmx \ - bytecomp/bytegen.cmx bytecomp/bytepackager.cmi -bytecomp/bytepackager.cmi : typing/ident.cmi typing/env.cmi -bytecomp/bytesections.cmo : utils/config.cmi bytecomp/bytesections.cmi -bytecomp/bytesections.cmx : utils/config.cmx bytecomp/bytesections.cmi +bytecomp/bytelink.cmo : \ + utils/warnings.cmi \ + bytecomp/symtable.cmi \ + bytecomp/opcodes.cmo \ + utils/misc.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + bytecomp/instruct.cmi \ + typing/ident.cmi \ + bytecomp/emitcode.cmi \ + bytecomp/dll.cmi \ + utils/consistbl.cmi \ + utils/config.cmi \ + bytecomp/cmo_format.cmi \ + utils/clflags.cmi \ + utils/ccomp.cmi \ + bytecomp/bytesections.cmi \ + bytecomp/bytelink.cmi +bytecomp/bytelink.cmx : \ + utils/warnings.cmx \ + bytecomp/symtable.cmx \ + bytecomp/opcodes.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + utils/load_path.cmx \ + bytecomp/instruct.cmx \ + typing/ident.cmx \ + bytecomp/emitcode.cmx \ + bytecomp/dll.cmx \ + utils/consistbl.cmx \ + utils/config.cmx \ + bytecomp/cmo_format.cmi \ + utils/clflags.cmx \ + utils/ccomp.cmx \ + bytecomp/bytesections.cmx \ + bytecomp/bytelink.cmi +bytecomp/bytelink.cmi : \ + bytecomp/symtable.cmi \ + bytecomp/cmo_format.cmi +bytecomp/bytepackager.cmo : \ + typing/typemod.cmi \ + bytecomp/translmod.cmi \ + typing/subst.cmi \ + bytecomp/printlambda.cmi \ + typing/path.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + bytecomp/instruct.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + bytecomp/emitcode.cmi \ + utils/config.cmi \ + bytecomp/cmo_format.cmi \ + utils/clflags.cmi \ + bytecomp/bytelink.cmi \ + bytecomp/bytegen.cmi \ + bytecomp/bytepackager.cmi +bytecomp/bytepackager.cmx : \ + typing/typemod.cmx \ + bytecomp/translmod.cmx \ + typing/subst.cmx \ + bytecomp/printlambda.cmx \ + typing/path.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + utils/load_path.cmx \ + bytecomp/instruct.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + bytecomp/emitcode.cmx \ + utils/config.cmx \ + bytecomp/cmo_format.cmi \ + utils/clflags.cmx \ + bytecomp/bytelink.cmx \ + bytecomp/bytegen.cmx \ + bytecomp/bytepackager.cmi +bytecomp/bytepackager.cmi : \ + typing/ident.cmi \ + typing/env.cmi +bytecomp/bytesections.cmo : \ + utils/config.cmi \ + bytecomp/bytesections.cmi +bytecomp/bytesections.cmx : \ + utils/config.cmx \ + bytecomp/bytesections.cmi bytecomp/bytesections.cmi : -bytecomp/cmo_format.cmi : utils/tbl.cmi bytecomp/lambda.cmi typing/ident.cmi -bytecomp/dll.cmo : utils/misc.cmi utils/config.cmi bytecomp/dll.cmi -bytecomp/dll.cmx : utils/misc.cmx utils/config.cmx bytecomp/dll.cmi +bytecomp/cmo_format.cmi : \ + bytecomp/lambda.cmi \ + typing/ident.cmi +bytecomp/dll.cmo : \ + utils/misc.cmi \ + utils/config.cmi \ + bytecomp/dll.cmi +bytecomp/dll.cmx : \ + utils/misc.cmx \ + utils/config.cmx \ + bytecomp/dll.cmi bytecomp/dll.cmi : -bytecomp/emitcode.cmo : bytecomp/translmod.cmi typing/primitive.cmi \ - bytecomp/opcodes.cmo utils/misc.cmi bytecomp/meta.cmi \ - parsing/location.cmi bytecomp/lambda.cmi bytecomp/instruct.cmi \ - typing/ident.cmi typing/env.cmi utils/config.cmi bytecomp/cmo_format.cmi \ - utils/clflags.cmi bytecomp/bytegen.cmi typing/btype.cmi \ - parsing/asttypes.cmi bytecomp/emitcode.cmi -bytecomp/emitcode.cmx : bytecomp/translmod.cmx typing/primitive.cmx \ - bytecomp/opcodes.cmx utils/misc.cmx bytecomp/meta.cmx \ - parsing/location.cmx bytecomp/lambda.cmx bytecomp/instruct.cmx \ - typing/ident.cmx typing/env.cmx utils/config.cmx bytecomp/cmo_format.cmi \ - utils/clflags.cmx bytecomp/bytegen.cmx typing/btype.cmx \ - parsing/asttypes.cmi bytecomp/emitcode.cmi -bytecomp/emitcode.cmi : bytecomp/instruct.cmi typing/ident.cmi \ +bytecomp/emitcode.cmo : \ + bytecomp/translmod.cmi \ + typing/primitive.cmi \ + bytecomp/opcodes.cmo \ + utils/misc.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + bytecomp/instruct.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + utils/config.cmi \ + bytecomp/cmo_format.cmi \ + utils/clflags.cmi \ + bytecomp/bytegen.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ + bytecomp/emitcode.cmi +bytecomp/emitcode.cmx : \ + bytecomp/translmod.cmx \ + typing/primitive.cmx \ + bytecomp/opcodes.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + bytecomp/instruct.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + utils/config.cmx \ + bytecomp/cmo_format.cmi \ + utils/clflags.cmx \ + bytecomp/bytegen.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ + bytecomp/emitcode.cmi +bytecomp/emitcode.cmi : \ + utils/misc.cmi \ + bytecomp/instruct.cmi \ + typing/ident.cmi \ bytecomp/cmo_format.cmi -bytecomp/instruct.cmo : typing/types.cmi typing/subst.cmi \ - parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi \ +bytecomp/instruct.cmo : \ + typing/types.cmi \ + typing/subst.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + typing/env.cmi \ bytecomp/instruct.cmi -bytecomp/instruct.cmx : typing/types.cmx typing/subst.cmx \ - parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx \ +bytecomp/instruct.cmx : \ + typing/types.cmx \ + typing/subst.cmx \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + typing/env.cmx \ bytecomp/instruct.cmi -bytecomp/instruct.cmi : typing/types.cmi typing/subst.cmi \ - parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi -bytecomp/lambda.cmo : typing/types.cmi typing/primitive.cmi typing/path.cmi \ - utils/misc.cmi parsing/location.cmi typing/ident.cmi typing/env.cmi \ - parsing/asttypes.cmi bytecomp/lambda.cmi -bytecomp/lambda.cmx : typing/types.cmx typing/primitive.cmx typing/path.cmx \ - utils/misc.cmx parsing/location.cmx typing/ident.cmx typing/env.cmx \ - parsing/asttypes.cmi bytecomp/lambda.cmi -bytecomp/lambda.cmi : typing/types.cmi typing/primitive.cmi typing/path.cmi \ - parsing/location.cmi typing/ident.cmi typing/env.cmi parsing/asttypes.cmi -bytecomp/matching.cmo : typing/types.cmi typing/typeopt.cmi \ - typing/typedtree.cmi bytecomp/switch.cmi typing/printpat.cmi \ - bytecomp/printlambda.cmi typing/primitive.cmi typing/predef.cmi \ - typing/path.cmi typing/parmatch.cmi utils/misc.cmi parsing/longident.cmi \ - parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi \ - utils/clflags.cmi typing/btype.cmi parsing/asttypes.cmi \ +bytecomp/instruct.cmi : \ + typing/types.cmi \ + typing/subst.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + typing/env.cmi +bytecomp/lambda.cmo : \ + typing/types.cmi \ + typing/primitive.cmi \ + typing/path.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + parsing/asttypes.cmi \ + bytecomp/lambda.cmi +bytecomp/lambda.cmx : \ + typing/types.cmx \ + typing/primitive.cmx \ + typing/path.cmx \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + parsing/asttypes.cmi \ + bytecomp/lambda.cmi +bytecomp/lambda.cmi : \ + typing/types.cmi \ + typing/primitive.cmi \ + typing/path.cmi \ + parsing/location.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + parsing/asttypes.cmi +bytecomp/matching.cmo : \ + typing/types.cmi \ + typing/typeopt.cmi \ + typing/typedtree.cmi \ + bytecomp/switch.cmi \ + typing/printpat.cmi \ + bytecomp/printlambda.cmi \ + typing/primitive.cmi \ + typing/predef.cmi \ + typing/parmatch.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + utils/clflags.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ bytecomp/matching.cmi -bytecomp/matching.cmx : typing/types.cmx typing/typeopt.cmx \ - typing/typedtree.cmx bytecomp/switch.cmx typing/printpat.cmx \ - bytecomp/printlambda.cmx typing/primitive.cmx typing/predef.cmx \ - typing/path.cmx typing/parmatch.cmx utils/misc.cmx parsing/longident.cmx \ - parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx \ - utils/clflags.cmx typing/btype.cmx parsing/asttypes.cmi \ +bytecomp/matching.cmx : \ + typing/types.cmx \ + typing/typeopt.cmx \ + typing/typedtree.cmx \ + bytecomp/switch.cmx \ + typing/printpat.cmx \ + bytecomp/printlambda.cmx \ + typing/primitive.cmx \ + typing/predef.cmx \ + typing/parmatch.cmx \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + utils/clflags.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ bytecomp/matching.cmi -bytecomp/matching.cmi : typing/typedtree.cmi parsing/location.cmi \ - bytecomp/lambda.cmi typing/ident.cmi -bytecomp/meta.cmo : bytecomp/instruct.cmi bytecomp/meta.cmi -bytecomp/meta.cmx : bytecomp/instruct.cmx bytecomp/meta.cmi -bytecomp/meta.cmi : bytecomp/instruct.cmi +bytecomp/matching.cmi : \ + typing/typedtree.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi +bytecomp/meta.cmo : \ + bytecomp/instruct.cmi \ + bytecomp/meta.cmi +bytecomp/meta.cmx : \ + bytecomp/instruct.cmx \ + bytecomp/meta.cmi +bytecomp/meta.cmi : \ + bytecomp/instruct.cmi bytecomp/opcodes.cmo : bytecomp/opcodes.cmx : -bytecomp/printinstr.cmo : bytecomp/printlambda.cmi parsing/location.cmi \ - bytecomp/lambda.cmi bytecomp/instruct.cmi typing/ident.cmi \ +bytecomp/printinstr.cmo : \ + bytecomp/printlambda.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + bytecomp/instruct.cmi \ + typing/ident.cmi \ bytecomp/printinstr.cmi -bytecomp/printinstr.cmx : bytecomp/printlambda.cmx parsing/location.cmx \ - bytecomp/lambda.cmx bytecomp/instruct.cmx typing/ident.cmx \ +bytecomp/printinstr.cmx : \ + bytecomp/printlambda.cmx \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + bytecomp/instruct.cmx \ + typing/ident.cmx \ bytecomp/printinstr.cmi -bytecomp/printinstr.cmi : bytecomp/instruct.cmi -bytecomp/printlambda.cmo : typing/types.cmi typing/primitive.cmi \ - parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi \ - parsing/asttypes.cmi bytecomp/printlambda.cmi -bytecomp/printlambda.cmx : typing/types.cmx typing/primitive.cmx \ - parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx \ - parsing/asttypes.cmi bytecomp/printlambda.cmi -bytecomp/printlambda.cmi : bytecomp/lambda.cmi -bytecomp/runtimedef.cmo : bytecomp/runtimedef.cmi -bytecomp/runtimedef.cmx : bytecomp/runtimedef.cmi +bytecomp/printinstr.cmi : \ + bytecomp/instruct.cmi +bytecomp/printlambda.cmo : \ + typing/types.cmi \ + typing/printtyp.cmi \ + typing/primitive.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + parsing/asttypes.cmi \ + bytecomp/printlambda.cmi +bytecomp/printlambda.cmx : \ + typing/types.cmx \ + typing/printtyp.cmx \ + typing/primitive.cmx \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + parsing/asttypes.cmi \ + bytecomp/printlambda.cmi +bytecomp/printlambda.cmi : \ + bytecomp/lambda.cmi +bytecomp/runtimedef.cmo : \ + bytecomp/runtimedef.cmi +bytecomp/runtimedef.cmx : \ + bytecomp/runtimedef.cmi bytecomp/runtimedef.cmi : -bytecomp/semantics_of_primitives.cmo : bytecomp/lambda.cmi \ +bytecomp/semantics_of_primitives.cmo : \ + bytecomp/lambda.cmi \ bytecomp/semantics_of_primitives.cmi -bytecomp/semantics_of_primitives.cmx : bytecomp/lambda.cmx \ +bytecomp/semantics_of_primitives.cmx : \ + bytecomp/lambda.cmx \ bytecomp/semantics_of_primitives.cmi -bytecomp/semantics_of_primitives.cmi : bytecomp/lambda.cmi -bytecomp/simplif.cmo : utils/warnings.cmi utils/tbl.cmi typing/stypes.cmi \ - utils/misc.cmi parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi \ - utils/clflags.cmi parsing/asttypes.cmi typing/annot.cmi \ +bytecomp/semantics_of_primitives.cmi : \ + bytecomp/lambda.cmi +bytecomp/simplif.cmo : \ + utils/warnings.cmi \ + typing/stypes.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + utils/clflags.cmi \ + parsing/asttypes.cmi \ + typing/annot.cmi \ bytecomp/simplif.cmi -bytecomp/simplif.cmx : utils/warnings.cmx utils/tbl.cmx typing/stypes.cmx \ - utils/misc.cmx parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx \ - utils/clflags.cmx parsing/asttypes.cmi typing/annot.cmi \ +bytecomp/simplif.cmx : \ + utils/warnings.cmx \ + typing/stypes.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + utils/clflags.cmx \ + parsing/asttypes.cmi \ + typing/annot.cmi \ bytecomp/simplif.cmi -bytecomp/simplif.cmi : utils/misc.cmi parsing/location.cmi \ - bytecomp/lambda.cmi typing/ident.cmi -bytecomp/switch.cmo : parsing/location.cmi bytecomp/switch.cmi -bytecomp/switch.cmx : parsing/location.cmx bytecomp/switch.cmi -bytecomp/switch.cmi : parsing/location.cmi -bytecomp/symtable.cmo : utils/tbl.cmi bytecomp/runtimedef.cmi \ - typing/predef.cmi utils/misc.cmi bytecomp/meta.cmi parsing/location.cmi \ - bytecomp/lambda.cmi typing/ident.cmi bytecomp/dll.cmi utils/config.cmi \ - bytecomp/cmo_format.cmi utils/clflags.cmi bytecomp/bytesections.cmi \ - parsing/asttypes.cmi bytecomp/symtable.cmi -bytecomp/symtable.cmx : utils/tbl.cmx bytecomp/runtimedef.cmx \ - typing/predef.cmx utils/misc.cmx bytecomp/meta.cmx parsing/location.cmx \ - bytecomp/lambda.cmx typing/ident.cmx bytecomp/dll.cmx utils/config.cmx \ - bytecomp/cmo_format.cmi utils/clflags.cmx bytecomp/bytesections.cmx \ - parsing/asttypes.cmi bytecomp/symtable.cmi -bytecomp/symtable.cmi : utils/misc.cmi bytecomp/lambda.cmi typing/ident.cmi \ +bytecomp/simplif.cmi : \ + utils/misc.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi +bytecomp/switch.cmo : \ + parsing/location.cmi \ + bytecomp/switch.cmi +bytecomp/switch.cmx : \ + parsing/location.cmx \ + bytecomp/switch.cmi +bytecomp/switch.cmi : \ + parsing/location.cmi +bytecomp/symtable.cmo : \ + bytecomp/runtimedef.cmi \ + typing/predef.cmi \ + utils/misc.cmi \ + bytecomp/meta.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + bytecomp/dll.cmi \ + utils/config.cmi \ + bytecomp/cmo_format.cmi \ + utils/clflags.cmi \ + bytecomp/bytesections.cmi \ + parsing/asttypes.cmi \ + bytecomp/symtable.cmi +bytecomp/symtable.cmx : \ + bytecomp/runtimedef.cmx \ + typing/predef.cmx \ + utils/misc.cmx \ + bytecomp/meta.cmx \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + bytecomp/dll.cmx \ + utils/config.cmx \ + bytecomp/cmo_format.cmi \ + utils/clflags.cmx \ + bytecomp/bytesections.cmx \ + parsing/asttypes.cmi \ + bytecomp/symtable.cmi +bytecomp/symtable.cmi : \ + utils/misc.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ bytecomp/cmo_format.cmi -bytecomp/translattribute.cmo : utils/warnings.cmi typing/typedtree.cmi \ - parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \ - parsing/location.cmi bytecomp/lambda.cmi utils/config.cmi \ +bytecomp/translattribute.cmo : \ + utils/warnings.cmi \ + typing/typedtree.cmi \ + parsing/parsetree.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + utils/config.cmi \ bytecomp/translattribute.cmi -bytecomp/translattribute.cmx : utils/warnings.cmx typing/typedtree.cmx \ - parsing/parsetree.cmi utils/misc.cmx parsing/longident.cmx \ - parsing/location.cmx bytecomp/lambda.cmx utils/config.cmx \ +bytecomp/translattribute.cmx : \ + utils/warnings.cmx \ + typing/typedtree.cmx \ + parsing/parsetree.cmi \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + utils/config.cmx \ bytecomp/translattribute.cmi -bytecomp/translattribute.cmi : typing/typedtree.cmi parsing/parsetree.cmi \ - parsing/location.cmi bytecomp/lambda.cmi -bytecomp/translclass.cmo : typing/types.cmi typing/typeopt.cmi \ - typing/typedtree.cmi bytecomp/translobj.cmi bytecomp/translcore.cmi \ - typing/path.cmi bytecomp/matching.cmi parsing/location.cmi \ - bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi utils/clflags.cmi \ - typing/btype.cmi parsing/asttypes.cmi bytecomp/translclass.cmi -bytecomp/translclass.cmx : typing/types.cmx typing/typeopt.cmx \ - typing/typedtree.cmx bytecomp/translobj.cmx bytecomp/translcore.cmx \ - typing/path.cmx bytecomp/matching.cmx parsing/location.cmx \ - bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx utils/clflags.cmx \ - typing/btype.cmx parsing/asttypes.cmi bytecomp/translclass.cmi -bytecomp/translclass.cmi : typing/typedtree.cmi parsing/location.cmi \ - bytecomp/lambda.cmi typing/ident.cmi parsing/asttypes.cmi -bytecomp/translcore.cmo : typing/types.cmi typing/typeopt.cmi \ - typing/typedtree.cmi typing/typecore.cmi bytecomp/translprim.cmi \ - bytecomp/translobj.cmi bytecomp/translattribute.cmi typing/printtyp.cmi \ - typing/primitive.cmi typing/predef.cmi typing/path.cmi \ - typing/parmatch.cmi utils/misc.cmi bytecomp/matching.cmi \ - parsing/longident.cmi parsing/location.cmi bytecomp/lambda.cmi \ - typing/ident.cmi typing/env.cmi utils/config.cmi utils/clflags.cmi \ - typing/btype.cmi parsing/asttypes.cmi bytecomp/translcore.cmi -bytecomp/translcore.cmx : typing/types.cmx typing/typeopt.cmx \ - typing/typedtree.cmx typing/typecore.cmx bytecomp/translprim.cmx \ - bytecomp/translobj.cmx bytecomp/translattribute.cmx typing/printtyp.cmx \ - typing/primitive.cmx typing/predef.cmx typing/path.cmx \ - typing/parmatch.cmx utils/misc.cmx bytecomp/matching.cmx \ - parsing/longident.cmx parsing/location.cmx bytecomp/lambda.cmx \ - typing/ident.cmx typing/env.cmx utils/config.cmx utils/clflags.cmx \ - typing/btype.cmx parsing/asttypes.cmi bytecomp/translcore.cmi -bytecomp/translcore.cmi : typing/typedtree.cmi typing/path.cmi \ - parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi \ +bytecomp/translattribute.cmi : \ + typing/typedtree.cmi \ + parsing/parsetree.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi +bytecomp/translclass.cmo : \ + typing/types.cmi \ + typing/typeopt.cmi \ + typing/typedtree.cmi \ + bytecomp/translobj.cmi \ + bytecomp/translcore.cmi \ + typing/path.cmi \ + bytecomp/matching.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + utils/clflags.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ + bytecomp/translclass.cmi +bytecomp/translclass.cmx : \ + typing/types.cmx \ + typing/typeopt.cmx \ + typing/typedtree.cmx \ + bytecomp/translobj.cmx \ + bytecomp/translcore.cmx \ + typing/path.cmx \ + bytecomp/matching.cmx \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + utils/clflags.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ + bytecomp/translclass.cmi +bytecomp/translclass.cmi : \ + typing/typedtree.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ parsing/asttypes.cmi -bytecomp/translmod.cmo : typing/types.cmi typing/typedtree.cmi \ - bytecomp/translprim.cmi bytecomp/translobj.cmi bytecomp/translcore.cmi \ - bytecomp/translclass.cmi bytecomp/translattribute.cmi typing/printtyp.cmi \ - typing/primitive.cmi typing/predef.cmi typing/path.cmi typing/mtype.cmi \ - utils/misc.cmi parsing/longident.cmi parsing/location.cmi \ - bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi typing/ctype.cmi \ - utils/clflags.cmi parsing/asttypes.cmi bytecomp/translmod.cmi -bytecomp/translmod.cmx : typing/types.cmx typing/typedtree.cmx \ - bytecomp/translprim.cmx bytecomp/translobj.cmx bytecomp/translcore.cmx \ - bytecomp/translclass.cmx bytecomp/translattribute.cmx typing/printtyp.cmx \ - typing/primitive.cmx typing/predef.cmx typing/path.cmx typing/mtype.cmx \ - utils/misc.cmx parsing/longident.cmx parsing/location.cmx \ - bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx typing/ctype.cmx \ - utils/clflags.cmx parsing/asttypes.cmi bytecomp/translmod.cmi -bytecomp/translmod.cmi : typing/typedtree.cmi typing/primitive.cmi \ - parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi -bytecomp/translobj.cmo : typing/primitive.cmi utils/misc.cmi \ - parsing/longident.cmi parsing/location.cmi bytecomp/lambda.cmi \ - typing/ident.cmi typing/env.cmi utils/config.cmi utils/clflags.cmi \ - typing/btype.cmi parsing/asttypes.cmi bytecomp/translobj.cmi -bytecomp/translobj.cmx : typing/primitive.cmx utils/misc.cmx \ - parsing/longident.cmx parsing/location.cmx bytecomp/lambda.cmx \ - typing/ident.cmx typing/env.cmx utils/config.cmx utils/clflags.cmx \ - typing/btype.cmx parsing/asttypes.cmi bytecomp/translobj.cmi -bytecomp/translobj.cmi : bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi -bytecomp/translprim.cmo : typing/types.cmi typing/typeopt.cmi \ - typing/typedtree.cmi typing/primitive.cmi typing/predef.cmi \ - typing/path.cmi utils/misc.cmi bytecomp/matching.cmi parsing/location.cmi \ - bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi utils/config.cmi \ - utils/clflags.cmi parsing/asttypes.cmi bytecomp/translprim.cmi -bytecomp/translprim.cmx : typing/types.cmx typing/typeopt.cmx \ - typing/typedtree.cmx typing/primitive.cmx typing/predef.cmx \ - typing/path.cmx utils/misc.cmx bytecomp/matching.cmx parsing/location.cmx \ - bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx utils/config.cmx \ - utils/clflags.cmx parsing/asttypes.cmi bytecomp/translprim.cmi -bytecomp/translprim.cmi : typing/types.cmi typing/typedtree.cmi \ - typing/primitive.cmi typing/path.cmi parsing/location.cmi \ - bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi -asmcomp/CSE.cmo : asmcomp/mach.cmi asmcomp/CSEgen.cmi asmcomp/arch.cmo -asmcomp/CSE.cmx : asmcomp/mach.cmx asmcomp/CSEgen.cmx asmcomp/arch.cmx -asmcomp/CSEgen.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \ - asmcomp/cmm.cmi asmcomp/CSEgen.cmi -asmcomp/CSEgen.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \ - asmcomp/cmm.cmx asmcomp/CSEgen.cmi -asmcomp/CSEgen.cmi : asmcomp/mach.cmi -asmcomp/afl_instrument.cmo : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi asmcomp/cmm.cmi utils/clflags.cmi \ - parsing/asttypes.cmi asmcomp/afl_instrument.cmi -asmcomp/afl_instrument.cmx : bytecomp/lambda.cmx typing/ident.cmx \ - middle_end/debuginfo.cmx asmcomp/cmm.cmx utils/clflags.cmx \ - parsing/asttypes.cmi asmcomp/afl_instrument.cmi -asmcomp/afl_instrument.cmi : asmcomp/cmm.cmi -asmcomp/arch.cmo : utils/config.cmi utils/clflags.cmi -asmcomp/arch.cmx : utils/config.cmx utils/clflags.cmx -asmcomp/asmgen.cmo : asmcomp/un_anf.cmi bytecomp/translmod.cmi \ - middle_end/base_types/symbol.cmi asmcomp/split.cmi asmcomp/spill.cmi \ - asmcomp/selection.cmi asmcomp/scheduling.cmi asmcomp/reload.cmi \ - asmcomp/reg.cmi utils/profile.cmi asmcomp/proc.cmi asmcomp/printmach.cmi \ - asmcomp/printlinear.cmi asmcomp/printcmm.cmi asmcomp/printclambda.cmi \ - typing/primitive.cmi utils/misc.cmi asmcomp/mach.cmi parsing/location.cmi \ - asmcomp/liveness.cmi asmcomp/linscan.cmi \ - middle_end/base_types/linkage_name.cmi asmcomp/linearize.cmi \ - bytecomp/lambda.cmi asmcomp/interval.cmi asmcomp/interf.cmi \ - typing/ident.cmi asmcomp/flambda_to_clambda.cmi middle_end/flambda.cmi \ - asmcomp/emitaux.cmi asmcomp/emit.cmi asmcomp/deadcode.cmi \ - utils/config.cmi asmcomp/compilenv.cmi asmcomp/comballoc.cmi \ - asmcomp/coloring.cmi asmcomp/cmmgen.cmi asmcomp/cmm.cmi \ - asmcomp/closure.cmi utils/clflags.cmi asmcomp/clambda.cmi asmcomp/CSE.cmo \ - asmcomp/build_export_info.cmi asmcomp/debug/available_regs.cmi \ +bytecomp/translcore.cmo : \ + typing/types.cmi \ + typing/typeopt.cmi \ + typing/typedtree.cmi \ + typing/typecore.cmi \ + bytecomp/translprim.cmi \ + bytecomp/translobj.cmi \ + bytecomp/translattribute.cmi \ + typing/printtyp.cmi \ + typing/primitive.cmi \ + typing/predef.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + typing/parmatch.cmi \ + utils/misc.cmi \ + bytecomp/matching.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + utils/config.cmi \ + utils/clflags.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ + bytecomp/translcore.cmi +bytecomp/translcore.cmx : \ + typing/types.cmx \ + typing/typeopt.cmx \ + typing/typedtree.cmx \ + typing/typecore.cmx \ + bytecomp/translprim.cmx \ + bytecomp/translobj.cmx \ + bytecomp/translattribute.cmx \ + typing/printtyp.cmx \ + typing/primitive.cmx \ + typing/predef.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + typing/parmatch.cmx \ + utils/misc.cmx \ + bytecomp/matching.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + utils/config.cmx \ + utils/clflags.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ + bytecomp/translcore.cmi +bytecomp/translcore.cmi : \ + typing/typedtree.cmi \ + typing/path.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + parsing/asttypes.cmi +bytecomp/translmod.cmo : \ + typing/types.cmi \ + typing/typedtree.cmi \ + bytecomp/translprim.cmi \ + bytecomp/translobj.cmi \ + bytecomp/translcore.cmi \ + bytecomp/translclass.cmi \ + bytecomp/translattribute.cmi \ + typing/primitive.cmi \ + typing/predef.cmi \ + typing/path.cmi \ + typing/mtype.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + utils/clflags.cmi \ + parsing/asttypes.cmi \ + bytecomp/translmod.cmi +bytecomp/translmod.cmx : \ + typing/types.cmx \ + typing/typedtree.cmx \ + bytecomp/translprim.cmx \ + bytecomp/translobj.cmx \ + bytecomp/translcore.cmx \ + bytecomp/translclass.cmx \ + bytecomp/translattribute.cmx \ + typing/primitive.cmx \ + typing/predef.cmx \ + typing/path.cmx \ + typing/mtype.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + typing/ctype.cmx \ + utils/clflags.cmx \ + parsing/asttypes.cmi \ + bytecomp/translmod.cmi +bytecomp/translmod.cmi : \ + typing/typedtree.cmi \ + typing/primitive.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi +bytecomp/translobj.cmo : \ + typing/primitive.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + utils/config.cmi \ + utils/clflags.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ + bytecomp/translobj.cmi +bytecomp/translobj.cmx : \ + typing/primitive.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + utils/config.cmx \ + utils/clflags.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ + bytecomp/translobj.cmi +bytecomp/translobj.cmi : \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + typing/env.cmi +bytecomp/translprim.cmo : \ + typing/types.cmi \ + typing/typeopt.cmi \ + typing/typedtree.cmi \ + typing/primitive.cmi \ + typing/predef.cmi \ + typing/path.cmi \ + utils/misc.cmi \ + bytecomp/matching.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + utils/config.cmi \ + utils/clflags.cmi \ + parsing/asttypes.cmi \ + bytecomp/translprim.cmi +bytecomp/translprim.cmx : \ + typing/types.cmx \ + typing/typeopt.cmx \ + typing/typedtree.cmx \ + typing/primitive.cmx \ + typing/predef.cmx \ + typing/path.cmx \ + utils/misc.cmx \ + bytecomp/matching.cmx \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + utils/config.cmx \ + utils/clflags.cmx \ + parsing/asttypes.cmi \ + bytecomp/translprim.cmi +bytecomp/translprim.cmi : \ + typing/types.cmi \ + typing/typedtree.cmi \ + typing/primitive.cmi \ + typing/path.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + typing/env.cmi +asmcomp/CSE.cmo : \ + asmcomp/mach.cmi \ + asmcomp/CSEgen.cmi \ + asmcomp/arch.cmo +asmcomp/CSE.cmx : \ + asmcomp/mach.cmx \ + asmcomp/CSEgen.cmx \ + asmcomp/arch.cmx +asmcomp/CSEgen.cmo : \ + asmcomp/reg.cmi \ + asmcomp/proc.cmi \ + asmcomp/mach.cmi \ + asmcomp/cmm.cmi \ + asmcomp/CSEgen.cmi +asmcomp/CSEgen.cmx : \ + asmcomp/reg.cmx \ + asmcomp/proc.cmx \ + asmcomp/mach.cmx \ + asmcomp/cmm.cmx \ + asmcomp/CSEgen.cmi +asmcomp/CSEgen.cmi : \ + asmcomp/mach.cmi +asmcomp/afl_instrument.cmo : \ + bytecomp/lambda.cmi \ + middle_end/debuginfo.cmi \ + asmcomp/cmm.cmi \ + utils/clflags.cmi \ + asmcomp/backend_var.cmi \ + parsing/asttypes.cmi \ + asmcomp/afl_instrument.cmi +asmcomp/afl_instrument.cmx : \ + bytecomp/lambda.cmx \ + middle_end/debuginfo.cmx \ + asmcomp/cmm.cmx \ + utils/clflags.cmx \ + asmcomp/backend_var.cmx \ + parsing/asttypes.cmi \ + asmcomp/afl_instrument.cmi +asmcomp/afl_instrument.cmi : \ + asmcomp/cmm.cmi +asmcomp/arch.cmo : \ + utils/config.cmi \ + utils/clflags.cmi +asmcomp/arch.cmx : \ + utils/config.cmx \ + utils/clflags.cmx +asmcomp/asmgen.cmo : \ + asmcomp/un_anf.cmi \ + bytecomp/translmod.cmi \ + middle_end/base_types/symbol.cmi \ + asmcomp/split.cmi \ + asmcomp/spill.cmi \ + asmcomp/selection.cmi \ + asmcomp/scheduling.cmi \ + asmcomp/reload.cmi \ + asmcomp/reg.cmi \ + utils/profile.cmi \ + asmcomp/proc.cmi \ + asmcomp/printmach.cmi \ + asmcomp/printlinear.cmi \ + asmcomp/printcmm.cmi \ + asmcomp/printclambda.cmi \ + typing/primitive.cmi \ + typing/path.cmi \ + utils/misc.cmi \ + asmcomp/mach.cmi \ + parsing/location.cmi \ + asmcomp/liveness.cmi \ + asmcomp/linscan.cmi \ + middle_end/base_types/linkage_name.cmi \ + asmcomp/linearize.cmi \ + bytecomp/lambda.cmi \ + asmcomp/interval.cmi \ + asmcomp/interf.cmi \ + typing/ident.cmi \ + asmcomp/flambda_to_clambda.cmi \ + middle_end/flambda.cmi \ + asmcomp/emitaux.cmi \ + asmcomp/emit.cmi \ + asmcomp/deadcode.cmi \ + utils/config.cmi \ + asmcomp/compilenv.cmi \ + asmcomp/comballoc.cmi \ + asmcomp/coloring.cmi \ + asmcomp/cmmgen.cmi \ + asmcomp/cmm.cmi \ + asmcomp/closure.cmi \ + utils/clflags.cmi \ + asmcomp/clambda.cmi \ + asmcomp/CSE.cmo \ + asmcomp/build_export_info.cmi \ + asmcomp/debug/available_regs.cmi \ asmcomp/asmgen.cmi -asmcomp/asmgen.cmx : asmcomp/un_anf.cmx bytecomp/translmod.cmx \ - middle_end/base_types/symbol.cmx asmcomp/split.cmx asmcomp/spill.cmx \ - asmcomp/selection.cmx asmcomp/scheduling.cmx asmcomp/reload.cmx \ - asmcomp/reg.cmx utils/profile.cmx asmcomp/proc.cmx asmcomp/printmach.cmx \ - asmcomp/printlinear.cmx asmcomp/printcmm.cmx asmcomp/printclambda.cmx \ - typing/primitive.cmx utils/misc.cmx asmcomp/mach.cmx parsing/location.cmx \ - asmcomp/liveness.cmx asmcomp/linscan.cmx \ - middle_end/base_types/linkage_name.cmx asmcomp/linearize.cmx \ - bytecomp/lambda.cmx asmcomp/interval.cmx asmcomp/interf.cmx \ - typing/ident.cmx asmcomp/flambda_to_clambda.cmx middle_end/flambda.cmx \ - asmcomp/emitaux.cmx asmcomp/emit.cmx asmcomp/deadcode.cmx \ - utils/config.cmx asmcomp/compilenv.cmx asmcomp/comballoc.cmx \ - asmcomp/coloring.cmx asmcomp/cmmgen.cmx asmcomp/cmm.cmx \ - asmcomp/closure.cmx utils/clflags.cmx asmcomp/clambda.cmx asmcomp/CSE.cmx \ - asmcomp/build_export_info.cmx asmcomp/debug/available_regs.cmx \ +asmcomp/asmgen.cmx : \ + asmcomp/un_anf.cmx \ + bytecomp/translmod.cmx \ + middle_end/base_types/symbol.cmx \ + asmcomp/split.cmx \ + asmcomp/spill.cmx \ + asmcomp/selection.cmx \ + asmcomp/scheduling.cmx \ + asmcomp/reload.cmx \ + asmcomp/reg.cmx \ + utils/profile.cmx \ + asmcomp/proc.cmx \ + asmcomp/printmach.cmx \ + asmcomp/printlinear.cmx \ + asmcomp/printcmm.cmx \ + asmcomp/printclambda.cmx \ + typing/primitive.cmx \ + typing/path.cmx \ + utils/misc.cmx \ + asmcomp/mach.cmx \ + parsing/location.cmx \ + asmcomp/liveness.cmx \ + asmcomp/linscan.cmx \ + middle_end/base_types/linkage_name.cmx \ + asmcomp/linearize.cmx \ + bytecomp/lambda.cmx \ + asmcomp/interval.cmx \ + asmcomp/interf.cmx \ + typing/ident.cmx \ + asmcomp/flambda_to_clambda.cmx \ + middle_end/flambda.cmx \ + asmcomp/emitaux.cmx \ + asmcomp/emit.cmx \ + asmcomp/deadcode.cmx \ + utils/config.cmx \ + asmcomp/compilenv.cmx \ + asmcomp/comballoc.cmx \ + asmcomp/coloring.cmx \ + asmcomp/cmmgen.cmx \ + asmcomp/cmm.cmx \ + asmcomp/closure.cmx \ + utils/clflags.cmx \ + asmcomp/clambda.cmx \ + asmcomp/CSE.cmx \ + asmcomp/build_export_info.cmx \ + asmcomp/debug/available_regs.cmx \ asmcomp/asmgen.cmi -asmcomp/asmgen.cmi : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/flambda.cmi asmcomp/cmm.cmi middle_end/backend_intf.cmi -asmcomp/asmlibrarian.cmo : utils/misc.cmi parsing/location.cmi \ - asmcomp/export_info.cmi utils/config.cmi asmcomp/compilenv.cmi \ - asmcomp/cmx_format.cmi utils/clflags.cmi asmcomp/clambda.cmi \ - utils/ccomp.cmi asmcomp/asmlink.cmi asmcomp/asmlibrarian.cmi -asmcomp/asmlibrarian.cmx : utils/misc.cmx parsing/location.cmx \ - asmcomp/export_info.cmx utils/config.cmx asmcomp/compilenv.cmx \ - asmcomp/cmx_format.cmi utils/clflags.cmx asmcomp/clambda.cmx \ - utils/ccomp.cmx asmcomp/asmlink.cmx asmcomp/asmlibrarian.cmi +asmcomp/asmgen.cmi : \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + middle_end/flambda.cmi \ + asmcomp/cmm.cmi \ + middle_end/backend_intf.cmi +asmcomp/asmlibrarian.cmo : \ + utils/misc.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + asmcomp/export_info.cmi \ + utils/config.cmi \ + asmcomp/compilenv.cmi \ + asmcomp/cmx_format.cmi \ + utils/clflags.cmi \ + asmcomp/clambda.cmi \ + utils/ccomp.cmi \ + asmcomp/asmlink.cmi \ + asmcomp/asmlibrarian.cmi +asmcomp/asmlibrarian.cmx : \ + utils/misc.cmx \ + parsing/location.cmx \ + utils/load_path.cmx \ + asmcomp/export_info.cmx \ + utils/config.cmx \ + asmcomp/compilenv.cmx \ + asmcomp/cmx_format.cmi \ + utils/clflags.cmx \ + asmcomp/clambda.cmx \ + utils/ccomp.cmx \ + asmcomp/asmlink.cmx \ + asmcomp/asmlibrarian.cmi asmcomp/asmlibrarian.cmi : -asmcomp/asmlink.cmo : bytecomp/runtimedef.cmi utils/profile.cmi \ - utils/misc.cmi parsing/location.cmi asmcomp/emitaux.cmi asmcomp/emit.cmi \ - utils/consistbl.cmi utils/config.cmi asmcomp/compilenv.cmi \ - asmcomp/cmx_format.cmi asmcomp/cmmgen.cmi asmcomp/cmm.cmi \ - utils/clflags.cmi utils/ccomp.cmi asmcomp/asmgen.cmi asmcomp/asmlink.cmi -asmcomp/asmlink.cmx : bytecomp/runtimedef.cmx utils/profile.cmx \ - utils/misc.cmx parsing/location.cmx asmcomp/emitaux.cmx asmcomp/emit.cmx \ - utils/consistbl.cmx utils/config.cmx asmcomp/compilenv.cmx \ - asmcomp/cmx_format.cmi asmcomp/cmmgen.cmx asmcomp/cmm.cmx \ - utils/clflags.cmx utils/ccomp.cmx asmcomp/asmgen.cmx asmcomp/asmlink.cmi -asmcomp/asmlink.cmi : asmcomp/cmx_format.cmi -asmcomp/asmpackager.cmo : typing/typemod.cmi bytecomp/translmod.cmi \ - utils/profile.cmi utils/misc.cmi middle_end/middle_end.cmi \ - parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi \ - asmcomp/export_info_for_pack.cmi asmcomp/export_info.cmi typing/env.cmi \ - utils/config.cmi asmcomp/compilenv.cmi \ - middle_end/base_types/compilation_unit.cmi asmcomp/cmx_format.cmi \ - utils/clflags.cmi utils/ccomp.cmi asmcomp/asmlink.cmi asmcomp/asmgen.cmi \ +asmcomp/asmlink.cmo : \ + bytecomp/runtimedef.cmi \ + utils/profile.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + asmcomp/emitaux.cmi \ + asmcomp/emit.cmi \ + utils/consistbl.cmi \ + utils/config.cmi \ + asmcomp/compilenv.cmi \ + asmcomp/cmx_format.cmi \ + asmcomp/cmmgen.cmi \ + asmcomp/cmm.cmi \ + utils/clflags.cmi \ + utils/ccomp.cmi \ + asmcomp/asmgen.cmi \ + asmcomp/asmlink.cmi +asmcomp/asmlink.cmx : \ + bytecomp/runtimedef.cmx \ + utils/profile.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + utils/load_path.cmx \ + asmcomp/emitaux.cmx \ + asmcomp/emit.cmx \ + utils/consistbl.cmx \ + utils/config.cmx \ + asmcomp/compilenv.cmx \ + asmcomp/cmx_format.cmi \ + asmcomp/cmmgen.cmx \ + asmcomp/cmm.cmx \ + utils/clflags.cmx \ + utils/ccomp.cmx \ + asmcomp/asmgen.cmx \ + asmcomp/asmlink.cmi +asmcomp/asmlink.cmi : \ + asmcomp/cmx_format.cmi +asmcomp/asmpackager.cmo : \ + typing/typemod.cmi \ + bytecomp/translmod.cmi \ + utils/profile.cmi \ + utils/misc.cmi \ + middle_end/middle_end.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + asmcomp/export_info_for_pack.cmi \ + asmcomp/export_info.cmi \ + typing/env.cmi \ + utils/config.cmi \ + asmcomp/compilenv.cmi \ + middle_end/base_types/compilation_unit.cmi \ + asmcomp/cmx_format.cmi \ + utils/clflags.cmi \ + utils/ccomp.cmi \ + asmcomp/asmlink.cmi \ + asmcomp/asmgen.cmi \ asmcomp/asmpackager.cmi -asmcomp/asmpackager.cmx : typing/typemod.cmx bytecomp/translmod.cmx \ - utils/profile.cmx utils/misc.cmx middle_end/middle_end.cmx \ - parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx \ - asmcomp/export_info_for_pack.cmx asmcomp/export_info.cmx typing/env.cmx \ - utils/config.cmx asmcomp/compilenv.cmx \ - middle_end/base_types/compilation_unit.cmx asmcomp/cmx_format.cmi \ - utils/clflags.cmx utils/ccomp.cmx asmcomp/asmlink.cmx asmcomp/asmgen.cmx \ +asmcomp/asmpackager.cmx : \ + typing/typemod.cmx \ + bytecomp/translmod.cmx \ + utils/profile.cmx \ + utils/misc.cmx \ + middle_end/middle_end.cmx \ + parsing/location.cmx \ + utils/load_path.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + asmcomp/export_info_for_pack.cmx \ + asmcomp/export_info.cmx \ + typing/env.cmx \ + utils/config.cmx \ + asmcomp/compilenv.cmx \ + middle_end/base_types/compilation_unit.cmx \ + asmcomp/cmx_format.cmi \ + utils/clflags.cmx \ + utils/ccomp.cmx \ + asmcomp/asmlink.cmx \ + asmcomp/asmgen.cmx \ asmcomp/asmpackager.cmi -asmcomp/asmpackager.cmi : typing/env.cmi middle_end/backend_intf.cmi -asmcomp/branch_relaxation.cmo : utils/misc.cmi asmcomp/mach.cmi \ - asmcomp/linearize.cmi asmcomp/cmm.cmi asmcomp/branch_relaxation_intf.cmo \ +asmcomp/asmpackager.cmi : \ + typing/env.cmi \ + middle_end/backend_intf.cmi +asmcomp/backend_var.cmo : \ + typing/path.cmi \ + typing/ident.cmi \ + middle_end/debuginfo.cmi \ + asmcomp/backend_var.cmi +asmcomp/backend_var.cmx : \ + typing/path.cmx \ + typing/ident.cmx \ + middle_end/debuginfo.cmx \ + asmcomp/backend_var.cmi +asmcomp/backend_var.cmi : \ + typing/path.cmi \ + typing/ident.cmi \ + middle_end/debuginfo.cmi +asmcomp/branch_relaxation.cmo : \ + utils/misc.cmi \ + asmcomp/mach.cmi \ + asmcomp/linearize.cmi \ + asmcomp/cmm.cmi \ + asmcomp/branch_relaxation_intf.cmo \ asmcomp/branch_relaxation.cmi -asmcomp/branch_relaxation.cmx : utils/misc.cmx asmcomp/mach.cmx \ - asmcomp/linearize.cmx asmcomp/cmm.cmx asmcomp/branch_relaxation_intf.cmx \ +asmcomp/branch_relaxation.cmx : \ + utils/misc.cmx \ + asmcomp/mach.cmx \ + asmcomp/linearize.cmx \ + asmcomp/cmm.cmx \ + asmcomp/branch_relaxation_intf.cmx \ asmcomp/branch_relaxation.cmi -asmcomp/branch_relaxation.cmi : asmcomp/linearize.cmi \ +asmcomp/branch_relaxation.cmi : \ + asmcomp/linearize.cmi \ asmcomp/branch_relaxation_intf.cmo -asmcomp/branch_relaxation_intf.cmo : asmcomp/linearize.cmi asmcomp/cmm.cmi \ +asmcomp/branch_relaxation_intf.cmo : \ + asmcomp/linearize.cmi \ + asmcomp/cmm.cmi \ asmcomp/arch.cmo -asmcomp/branch_relaxation_intf.cmx : asmcomp/linearize.cmx asmcomp/cmm.cmx \ +asmcomp/branch_relaxation_intf.cmx : \ + asmcomp/linearize.cmx \ + asmcomp/cmm.cmx \ asmcomp/arch.cmx -asmcomp/build_export_info.cmo : middle_end/base_types/variable.cmi \ +asmcomp/build_export_info.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - asmcomp/traverse_for_exported_symbols.cmi middle_end/base_types/tag.cmi \ - middle_end/base_types/symbol.cmi middle_end/simple_value_approx.cmi \ - middle_end/base_types/set_of_closures_id.cmi utils/misc.cmi \ - middle_end/invariant_params.cmi middle_end/inline_and_simplify_aux.cmi \ - middle_end/flambda_utils.cmi middle_end/flambda.cmi \ - middle_end/find_recursive_functions.cmi asmcomp/export_info.cmi \ - middle_end/base_types/export_id.cmi asmcomp/compilenv.cmi \ + asmcomp/traverse_for_exported_symbols.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ + middle_end/simple_value_approx.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + utils/misc.cmi \ + middle_end/invariant_params.cmi \ + middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi \ + middle_end/find_recursive_functions.cmi \ + asmcomp/export_info.cmi \ + middle_end/base_types/export_id.cmi \ + asmcomp/compilenv.cmi \ middle_end/base_types/compilation_unit.cmi \ - middle_end/base_types/closure_id.cmi utils/clflags.cmi \ - middle_end/backend_intf.cmi middle_end/allocated_const.cmi \ + middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi \ + middle_end/backend_intf.cmi \ + middle_end/allocated_const.cmi \ asmcomp/build_export_info.cmi -asmcomp/build_export_info.cmx : middle_end/base_types/variable.cmx \ +asmcomp/build_export_info.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ - asmcomp/traverse_for_exported_symbols.cmx middle_end/base_types/tag.cmx \ - middle_end/base_types/symbol.cmx middle_end/simple_value_approx.cmx \ - middle_end/base_types/set_of_closures_id.cmx utils/misc.cmx \ - middle_end/invariant_params.cmx middle_end/inline_and_simplify_aux.cmx \ - middle_end/flambda_utils.cmx middle_end/flambda.cmx \ - middle_end/find_recursive_functions.cmx asmcomp/export_info.cmx \ - middle_end/base_types/export_id.cmx asmcomp/compilenv.cmx \ + asmcomp/traverse_for_exported_symbols.cmx \ + middle_end/base_types/tag.cmx \ + middle_end/base_types/symbol.cmx \ + middle_end/simple_value_approx.cmx \ + middle_end/base_types/set_of_closures_id.cmx \ + utils/misc.cmx \ + middle_end/invariant_params.cmx \ + middle_end/inline_and_simplify_aux.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx \ + middle_end/find_recursive_functions.cmx \ + asmcomp/export_info.cmx \ + middle_end/base_types/export_id.cmx \ + asmcomp/compilenv.cmx \ middle_end/base_types/compilation_unit.cmx \ - middle_end/base_types/closure_id.cmx utils/clflags.cmx \ - middle_end/backend_intf.cmi middle_end/allocated_const.cmx \ + middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx \ + middle_end/backend_intf.cmi \ + middle_end/allocated_const.cmx \ asmcomp/build_export_info.cmi -asmcomp/build_export_info.cmi : middle_end/flambda.cmi \ - asmcomp/export_info.cmi middle_end/backend_intf.cmi -asmcomp/clambda.cmo : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi parsing/asttypes.cmi asmcomp/clambda.cmi -asmcomp/clambda.cmx : bytecomp/lambda.cmx typing/ident.cmx \ - middle_end/debuginfo.cmx parsing/asttypes.cmi asmcomp/clambda.cmi -asmcomp/clambda.cmi : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi parsing/asttypes.cmi -asmcomp/closure.cmo : utils/warnings.cmi utils/tbl.cmi bytecomp/switch.cmi \ - bytecomp/simplif.cmi bytecomp/semantics_of_primitives.cmi \ - typing/primitive.cmi utils/misc.cmi parsing/location.cmi \ - bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi \ - middle_end/debuginfo.cmi utils/config.cmi asmcomp/compilenv.cmi \ - utils/clflags.cmi asmcomp/clambda.cmi parsing/asttypes.cmi \ - asmcomp/arch.cmo asmcomp/closure.cmi -asmcomp/closure.cmx : utils/warnings.cmx utils/tbl.cmx bytecomp/switch.cmx \ - bytecomp/simplif.cmx bytecomp/semantics_of_primitives.cmx \ - typing/primitive.cmx utils/misc.cmx parsing/location.cmx \ - bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx \ - middle_end/debuginfo.cmx utils/config.cmx asmcomp/compilenv.cmx \ - utils/clflags.cmx asmcomp/clambda.cmx parsing/asttypes.cmi \ - asmcomp/arch.cmx asmcomp/closure.cmi -asmcomp/closure.cmi : bytecomp/lambda.cmi asmcomp/clambda.cmi -asmcomp/closure_offsets.cmo : middle_end/base_types/variable.cmi \ - middle_end/base_types/var_within_closure.cmi utils/misc.cmi \ - middle_end/flambda_utils.cmi middle_end/flambda.cmi \ - middle_end/base_types/closure_id.cmi asmcomp/closure_offsets.cmi -asmcomp/closure_offsets.cmx : middle_end/base_types/variable.cmx \ - middle_end/base_types/var_within_closure.cmx utils/misc.cmx \ - middle_end/flambda_utils.cmx middle_end/flambda.cmx \ - middle_end/base_types/closure_id.cmx asmcomp/closure_offsets.cmi -asmcomp/closure_offsets.cmi : middle_end/base_types/var_within_closure.cmi \ - middle_end/flambda.cmi middle_end/base_types/closure_id.cmi -asmcomp/cmm.cmo : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi parsing/asttypes.cmi asmcomp/arch.cmo \ +asmcomp/build_export_info.cmi : \ + middle_end/flambda.cmi \ + asmcomp/export_info.cmi \ + middle_end/backend_intf.cmi +asmcomp/clambda.cmo : \ + typing/path.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + middle_end/debuginfo.cmi \ + asmcomp/backend_var.cmi \ + parsing/asttypes.cmi \ + asmcomp/clambda.cmi +asmcomp/clambda.cmx : \ + typing/path.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + middle_end/debuginfo.cmx \ + asmcomp/backend_var.cmx \ + parsing/asttypes.cmi \ + asmcomp/clambda.cmi +asmcomp/clambda.cmi : \ + typing/path.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + middle_end/debuginfo.cmi \ + asmcomp/backend_var.cmi \ + parsing/asttypes.cmi +asmcomp/closure.cmo : \ + utils/warnings.cmi \ + bytecomp/switch.cmi \ + bytecomp/simplif.cmi \ + bytecomp/semantics_of_primitives.cmi \ + typing/primitive.cmi \ + utils/numbers.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + middle_end/debuginfo.cmi \ + utils/config.cmi \ + asmcomp/compilenv.cmi \ + utils/clflags.cmi \ + asmcomp/clambda.cmi \ + asmcomp/backend_var.cmi \ + parsing/asttypes.cmi \ + asmcomp/arch.cmo \ + asmcomp/closure.cmi +asmcomp/closure.cmx : \ + utils/warnings.cmx \ + bytecomp/switch.cmx \ + bytecomp/simplif.cmx \ + bytecomp/semantics_of_primitives.cmx \ + typing/primitive.cmx \ + utils/numbers.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + middle_end/debuginfo.cmx \ + utils/config.cmx \ + asmcomp/compilenv.cmx \ + utils/clflags.cmx \ + asmcomp/clambda.cmx \ + asmcomp/backend_var.cmx \ + parsing/asttypes.cmi \ + asmcomp/arch.cmx \ + asmcomp/closure.cmi +asmcomp/closure.cmi : \ + bytecomp/lambda.cmi \ + asmcomp/clambda.cmi +asmcomp/closure_offsets.cmo : \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/var_within_closure.cmi \ + utils/misc.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi \ + middle_end/base_types/closure_id.cmi \ + asmcomp/closure_offsets.cmi +asmcomp/closure_offsets.cmx : \ + middle_end/base_types/variable.cmx \ + middle_end/base_types/var_within_closure.cmx \ + utils/misc.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx \ + middle_end/base_types/closure_id.cmx \ + asmcomp/closure_offsets.cmi +asmcomp/closure_offsets.cmi : \ + middle_end/base_types/var_within_closure.cmi \ + middle_end/flambda.cmi \ + middle_end/base_types/closure_id.cmi +asmcomp/cmm.cmo : \ + utils/targetint.cmi \ + bytecomp/lambda.cmi \ + middle_end/debuginfo.cmi \ + asmcomp/backend_var.cmi \ + parsing/asttypes.cmi \ + asmcomp/arch.cmo \ asmcomp/cmm.cmi -asmcomp/cmm.cmx : bytecomp/lambda.cmx typing/ident.cmx \ - middle_end/debuginfo.cmx parsing/asttypes.cmi asmcomp/arch.cmx \ +asmcomp/cmm.cmx : \ + utils/targetint.cmx \ + bytecomp/lambda.cmx \ + middle_end/debuginfo.cmx \ + asmcomp/backend_var.cmx \ + parsing/asttypes.cmi \ + asmcomp/arch.cmx \ asmcomp/cmm.cmi -asmcomp/cmm.cmi : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi parsing/asttypes.cmi -asmcomp/cmmgen.cmo : asmcomp/un_anf.cmi typing/types.cmi bytecomp/switch.cmi \ - asmcomp/strmatch.cmi asmcomp/proc.cmi bytecomp/printlambda.cmi \ - typing/primitive.cmi utils/misc.cmi bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi utils/config.cmi asmcomp/compilenv.cmi \ - asmcomp/cmx_format.cmi asmcomp/cmm.cmi utils/clflags.cmi \ - asmcomp/clambda.cmi parsing/asttypes.cmi asmcomp/arch.cmo \ - asmcomp/afl_instrument.cmi asmcomp/cmmgen.cmi -asmcomp/cmmgen.cmx : asmcomp/un_anf.cmx typing/types.cmx bytecomp/switch.cmx \ - asmcomp/strmatch.cmx asmcomp/proc.cmx bytecomp/printlambda.cmx \ - typing/primitive.cmx utils/misc.cmx bytecomp/lambda.cmx typing/ident.cmx \ - middle_end/debuginfo.cmx utils/config.cmx asmcomp/compilenv.cmx \ - asmcomp/cmx_format.cmi asmcomp/cmm.cmx utils/clflags.cmx \ - asmcomp/clambda.cmx parsing/asttypes.cmi asmcomp/arch.cmx \ - asmcomp/afl_instrument.cmx asmcomp/cmmgen.cmi -asmcomp/cmmgen.cmi : asmcomp/cmx_format.cmi asmcomp/cmm.cmi \ +asmcomp/cmm.cmi : \ + utils/targetint.cmi \ + bytecomp/lambda.cmi \ + middle_end/debuginfo.cmi \ + asmcomp/backend_var.cmi \ + parsing/asttypes.cmi +asmcomp/cmmgen.cmo : \ + asmcomp/un_anf.cmi \ + typing/types.cmi \ + utils/targetint.cmi \ + bytecomp/switch.cmi \ + asmcomp/strmatch.cmi \ + asmcomp/proc.cmi \ + bytecomp/printlambda.cmi \ + typing/primitive.cmi \ + utils/numbers.cmi \ + utils/misc.cmi \ + bytecomp/lambda.cmi \ + middle_end/debuginfo.cmi \ + utils/config.cmi \ + asmcomp/compilenv.cmi \ + asmcomp/cmx_format.cmi \ + asmcomp/cmm.cmi \ + utils/clflags.cmi \ + asmcomp/clambda.cmi \ + asmcomp/backend_var.cmi \ + parsing/asttypes.cmi \ + asmcomp/arch.cmo \ + asmcomp/afl_instrument.cmi \ + asmcomp/cmmgen.cmi +asmcomp/cmmgen.cmx : \ + asmcomp/un_anf.cmx \ + typing/types.cmx \ + utils/targetint.cmx \ + bytecomp/switch.cmx \ + asmcomp/strmatch.cmx \ + asmcomp/proc.cmx \ + bytecomp/printlambda.cmx \ + typing/primitive.cmx \ + utils/numbers.cmx \ + utils/misc.cmx \ + bytecomp/lambda.cmx \ + middle_end/debuginfo.cmx \ + utils/config.cmx \ + asmcomp/compilenv.cmx \ + asmcomp/cmx_format.cmi \ + asmcomp/cmm.cmx \ + utils/clflags.cmx \ + asmcomp/clambda.cmx \ + asmcomp/backend_var.cmx \ + parsing/asttypes.cmi \ + asmcomp/arch.cmx \ + asmcomp/afl_instrument.cmx \ + asmcomp/cmmgen.cmi +asmcomp/cmmgen.cmi : \ + asmcomp/cmx_format.cmi \ + asmcomp/cmm.cmi \ + asmcomp/clambda.cmi +asmcomp/cmx_format.cmi : \ + asmcomp/export_info.cmi \ asmcomp/clambda.cmi -asmcomp/cmx_format.cmi : asmcomp/export_info.cmi asmcomp/clambda.cmi -asmcomp/coloring.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/coloring.cmi -asmcomp/coloring.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/coloring.cmi +asmcomp/coloring.cmo : \ + asmcomp/reg.cmi \ + asmcomp/proc.cmi \ + asmcomp/coloring.cmi +asmcomp/coloring.cmx : \ + asmcomp/reg.cmx \ + asmcomp/proc.cmx \ + asmcomp/coloring.cmi asmcomp/coloring.cmi : -asmcomp/comballoc.cmo : asmcomp/reg.cmi asmcomp/mach.cmi utils/config.cmi \ - asmcomp/arch.cmo asmcomp/comballoc.cmi -asmcomp/comballoc.cmx : asmcomp/reg.cmx asmcomp/mach.cmx utils/config.cmx \ - asmcomp/arch.cmx asmcomp/comballoc.cmi -asmcomp/comballoc.cmi : asmcomp/mach.cmi -asmcomp/compilenv.cmo : utils/warnings.cmi middle_end/base_types/symbol.cmi \ +asmcomp/comballoc.cmo : \ + asmcomp/reg.cmi \ + asmcomp/mach.cmi \ + utils/config.cmi \ + asmcomp/arch.cmo \ + asmcomp/comballoc.cmi +asmcomp/comballoc.cmx : \ + asmcomp/reg.cmx \ + asmcomp/mach.cmx \ + utils/config.cmx \ + asmcomp/arch.cmx \ + asmcomp/comballoc.cmi +asmcomp/comballoc.cmi : \ + asmcomp/mach.cmi +asmcomp/compilenv.cmo : \ + utils/warnings.cmi \ + middle_end/base_types/symbol.cmi \ middle_end/simple_value_approx.cmi \ - middle_end/base_types/set_of_closures_id.cmi utils/misc.cmi \ - parsing/location.cmi middle_end/base_types/linkage_name.cmi \ - typing/ident.cmi asmcomp/export_info.cmi typing/env.cmi utils/config.cmi \ - middle_end/base_types/compilation_unit.cmi asmcomp/cmx_format.cmi \ - middle_end/base_types/closure_id.cmi utils/clflags.cmi \ - asmcomp/clambda.cmi asmcomp/compilenv.cmi -asmcomp/compilenv.cmx : utils/warnings.cmx middle_end/base_types/symbol.cmx \ + middle_end/base_types/set_of_closures_id.cmi \ + typing/path.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + middle_end/base_types/linkage_name.cmi \ + typing/ident.cmi \ + asmcomp/export_info.cmi \ + typing/env.cmi \ + utils/config.cmi \ + middle_end/base_types/compilation_unit.cmi \ + asmcomp/cmx_format.cmi \ + middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi \ + asmcomp/clambda.cmi \ + asmcomp/compilenv.cmi +asmcomp/compilenv.cmx : \ + utils/warnings.cmx \ + middle_end/base_types/symbol.cmx \ middle_end/simple_value_approx.cmx \ - middle_end/base_types/set_of_closures_id.cmx utils/misc.cmx \ - parsing/location.cmx middle_end/base_types/linkage_name.cmx \ - typing/ident.cmx asmcomp/export_info.cmx typing/env.cmx utils/config.cmx \ - middle_end/base_types/compilation_unit.cmx asmcomp/cmx_format.cmi \ - middle_end/base_types/closure_id.cmx utils/clflags.cmx \ - asmcomp/clambda.cmx asmcomp/compilenv.cmi -asmcomp/compilenv.cmi : middle_end/base_types/symbol.cmi \ + middle_end/base_types/set_of_closures_id.cmx \ + typing/path.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + utils/load_path.cmx \ + middle_end/base_types/linkage_name.cmx \ + typing/ident.cmx \ + asmcomp/export_info.cmx \ + typing/env.cmx \ + utils/config.cmx \ + middle_end/base_types/compilation_unit.cmx \ + asmcomp/cmx_format.cmi \ + middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx \ + asmcomp/clambda.cmx \ + asmcomp/compilenv.cmi +asmcomp/compilenv.cmi : \ + middle_end/base_types/symbol.cmi \ middle_end/simple_value_approx.cmi \ middle_end/base_types/set_of_closures_id.cmi \ - middle_end/base_types/linkage_name.cmi typing/ident.cmi \ - asmcomp/export_info.cmi middle_end/base_types/compilation_unit.cmi \ - asmcomp/cmx_format.cmi middle_end/base_types/closure_id.cmi \ + middle_end/base_types/linkage_name.cmi \ + typing/ident.cmi \ + asmcomp/export_info.cmi \ + middle_end/base_types/compilation_unit.cmi \ + asmcomp/cmx_format.cmi \ + middle_end/base_types/closure_id.cmi \ asmcomp/clambda.cmi -asmcomp/deadcode.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \ - utils/config.cmi asmcomp/deadcode.cmi -asmcomp/deadcode.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \ - utils/config.cmx asmcomp/deadcode.cmi -asmcomp/deadcode.cmi : asmcomp/mach.cmi -asmcomp/emit.cmo : asmcomp/x86_proc.cmi asmcomp/x86_masm.cmi \ - asmcomp/x86_gas.cmi asmcomp/x86_dsl.cmi asmcomp/x86_ast.cmi \ - asmcomp/reg.cmi asmcomp/proc.cmi utils/misc.cmi asmcomp/mach.cmi \ - asmcomp/linearize.cmi asmcomp/emitaux.cmi middle_end/debuginfo.cmi \ - utils/config.cmi asmcomp/compilenv.cmi asmcomp/cmm.cmi utils/clflags.cmi \ - asmcomp/branch_relaxation.cmi asmcomp/arch.cmo asmcomp/emit.cmi -asmcomp/emit.cmx : asmcomp/x86_proc.cmx asmcomp/x86_masm.cmx \ - asmcomp/x86_gas.cmx asmcomp/x86_dsl.cmx asmcomp/x86_ast.cmi \ - asmcomp/reg.cmx asmcomp/proc.cmx utils/misc.cmx asmcomp/mach.cmx \ - asmcomp/linearize.cmx asmcomp/emitaux.cmx middle_end/debuginfo.cmx \ - utils/config.cmx asmcomp/compilenv.cmx asmcomp/cmm.cmx utils/clflags.cmx \ - asmcomp/branch_relaxation.cmx asmcomp/arch.cmx asmcomp/emit.cmi -asmcomp/emit.cmi : asmcomp/linearize.cmi asmcomp/cmm.cmi -asmcomp/emitaux.cmo : middle_end/debuginfo.cmi utils/config.cmi \ - asmcomp/cmm.cmi utils/clflags.cmi asmcomp/arch.cmo asmcomp/emitaux.cmi -asmcomp/emitaux.cmx : middle_end/debuginfo.cmx utils/config.cmx \ - asmcomp/cmm.cmx utils/clflags.cmx asmcomp/arch.cmx asmcomp/emitaux.cmi -asmcomp/emitaux.cmi : middle_end/debuginfo.cmi -asmcomp/export_info.cmo : middle_end/base_types/variable.cmi \ +asmcomp/deadcode.cmo : \ + asmcomp/reg.cmi \ + asmcomp/proc.cmi \ + asmcomp/mach.cmi \ + utils/config.cmi \ + asmcomp/deadcode.cmi +asmcomp/deadcode.cmx : \ + asmcomp/reg.cmx \ + asmcomp/proc.cmx \ + asmcomp/mach.cmx \ + utils/config.cmx \ + asmcomp/deadcode.cmi +asmcomp/deadcode.cmi : \ + asmcomp/mach.cmi +asmcomp/emit.cmo : \ + asmcomp/x86_proc.cmi \ + asmcomp/x86_masm.cmi \ + asmcomp/x86_gas.cmi \ + asmcomp/x86_dsl.cmi \ + asmcomp/x86_ast.cmi \ + asmcomp/reg.cmi \ + asmcomp/proc.cmi \ + utils/misc.cmi \ + asmcomp/mach.cmi \ + asmcomp/linearize.cmi \ + asmcomp/emitaux.cmi \ + middle_end/debuginfo.cmi \ + utils/config.cmi \ + asmcomp/compilenv.cmi \ + asmcomp/cmm.cmi \ + utils/clflags.cmi \ + asmcomp/branch_relaxation.cmi \ + asmcomp/arch.cmo \ + asmcomp/emit.cmi +asmcomp/emit.cmx : \ + asmcomp/x86_proc.cmx \ + asmcomp/x86_masm.cmx \ + asmcomp/x86_gas.cmx \ + asmcomp/x86_dsl.cmx \ + asmcomp/x86_ast.cmi \ + asmcomp/reg.cmx \ + asmcomp/proc.cmx \ + utils/misc.cmx \ + asmcomp/mach.cmx \ + asmcomp/linearize.cmx \ + asmcomp/emitaux.cmx \ + middle_end/debuginfo.cmx \ + utils/config.cmx \ + asmcomp/compilenv.cmx \ + asmcomp/cmm.cmx \ + utils/clflags.cmx \ + asmcomp/branch_relaxation.cmx \ + asmcomp/arch.cmx \ + asmcomp/emit.cmi +asmcomp/emit.cmi : \ + asmcomp/linearize.cmi \ + asmcomp/cmm.cmi +asmcomp/emitaux.cmo : \ + middle_end/debuginfo.cmi \ + utils/config.cmi \ + asmcomp/cmm.cmi \ + utils/clflags.cmi \ + asmcomp/arch.cmo \ + asmcomp/emitaux.cmi +asmcomp/emitaux.cmx : \ + middle_end/debuginfo.cmx \ + utils/config.cmx \ + asmcomp/cmm.cmx \ + utils/clflags.cmx \ + asmcomp/arch.cmx \ + asmcomp/emitaux.cmi +asmcomp/emitaux.cmi : \ + middle_end/debuginfo.cmi +asmcomp/export_info.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ middle_end/simple_value_approx.cmi \ - middle_end/base_types/set_of_closures_id.cmi middle_end/flambda.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + middle_end/flambda.cmi \ middle_end/base_types/export_id.cmi \ middle_end/base_types/compilation_unit.cmi \ - middle_end/base_types/closure_id.cmi asmcomp/export_info.cmi -asmcomp/export_info.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/closure_id.cmi \ + asmcomp/export_info.cmi +asmcomp/export_info.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ - middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \ + middle_end/base_types/tag.cmx \ + middle_end/base_types/symbol.cmx \ middle_end/simple_value_approx.cmx \ - middle_end/base_types/set_of_closures_id.cmx middle_end/flambda.cmx \ + middle_end/base_types/set_of_closures_id.cmx \ + middle_end/flambda.cmx \ middle_end/base_types/export_id.cmx \ middle_end/base_types/compilation_unit.cmx \ - middle_end/base_types/closure_id.cmx asmcomp/export_info.cmi -asmcomp/export_info.cmi : middle_end/base_types/variable.cmi \ + middle_end/base_types/closure_id.cmx \ + asmcomp/export_info.cmi +asmcomp/export_info.cmi : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ middle_end/simple_value_approx.cmi \ - middle_end/base_types/set_of_closures_id.cmi middle_end/flambda.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + middle_end/flambda.cmi \ middle_end/base_types/export_id.cmi \ middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/closure_id.cmi -asmcomp/export_info_for_pack.cmo : middle_end/base_types/variable.cmi \ +asmcomp/export_info_for_pack.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/base_types/symbol.cmi middle_end/simple_value_approx.cmi \ + middle_end/base_types/symbol.cmi \ + middle_end/simple_value_approx.cmi \ middle_end/base_types/set_of_closures_origin.cmi \ - middle_end/base_types/set_of_closures_id.cmi utils/misc.cmi \ - middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ - asmcomp/export_info.cmi middle_end/base_types/export_id.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + utils/misc.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + asmcomp/export_info.cmi \ + middle_end/base_types/export_id.cmi \ middle_end/base_types/compilation_unit.cmi \ - middle_end/base_types/closure_id.cmi asmcomp/export_info_for_pack.cmi -asmcomp/export_info_for_pack.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/closure_id.cmi \ + asmcomp/export_info_for_pack.cmi +asmcomp/export_info_for_pack.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ - middle_end/base_types/symbol.cmx middle_end/simple_value_approx.cmx \ + middle_end/base_types/symbol.cmx \ + middle_end/simple_value_approx.cmx \ middle_end/base_types/set_of_closures_origin.cmx \ - middle_end/base_types/set_of_closures_id.cmx utils/misc.cmx \ - middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ - asmcomp/export_info.cmx middle_end/base_types/export_id.cmx \ + middle_end/base_types/set_of_closures_id.cmx \ + utils/misc.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + asmcomp/export_info.cmx \ + middle_end/base_types/export_id.cmx \ middle_end/base_types/compilation_unit.cmx \ - middle_end/base_types/closure_id.cmx asmcomp/export_info_for_pack.cmi -asmcomp/export_info_for_pack.cmi : asmcomp/export_info.cmi \ + middle_end/base_types/closure_id.cmx \ + asmcomp/export_info_for_pack.cmi +asmcomp/export_info_for_pack.cmi : \ + asmcomp/export_info.cmi \ middle_end/base_types/compilation_unit.cmi -asmcomp/flambda_to_clambda.cmo : middle_end/base_types/variable.cmi \ +asmcomp/flambda_to_clambda.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ middle_end/base_types/static_exception.cmi \ middle_end/simple_value_approx.cmi \ - middle_end/base_types/set_of_closures_id.cmi typing/primitive.cmi \ - middle_end/parameter.cmi utils/numbers.cmi \ - middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + typing/primitive.cmi \ + middle_end/parameter.cmi \ + utils/numbers.cmi \ + middle_end/base_types/mutable_variable.cmi \ + utils/misc.cmi \ middle_end/base_types/linkage_name.cmi \ - middle_end/initialize_symbol_to_let_symbol.cmi typing/ident.cmi \ - middle_end/flambda_utils.cmi middle_end/flambda.cmi \ - asmcomp/export_info.cmi middle_end/debuginfo.cmi asmcomp/compilenv.cmi \ - asmcomp/closure_offsets.cmi middle_end/base_types/closure_id.cmi \ - utils/clflags.cmi asmcomp/clambda.cmi middle_end/allocated_const.cmi \ + bytecomp/lambda.cmi \ + middle_end/initialize_symbol_to_let_symbol.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi \ + asmcomp/export_info.cmi \ + middle_end/debuginfo.cmi \ + asmcomp/compilenv.cmi \ + asmcomp/closure_offsets.cmi \ + middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi \ + asmcomp/clambda.cmi \ + asmcomp/backend_var.cmi \ + middle_end/allocated_const.cmi \ asmcomp/flambda_to_clambda.cmi -asmcomp/flambda_to_clambda.cmx : middle_end/base_types/variable.cmx \ +asmcomp/flambda_to_clambda.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ - middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \ + middle_end/base_types/tag.cmx \ + middle_end/base_types/symbol.cmx \ middle_end/base_types/static_exception.cmx \ middle_end/simple_value_approx.cmx \ - middle_end/base_types/set_of_closures_id.cmx typing/primitive.cmx \ - middle_end/parameter.cmx utils/numbers.cmx \ - middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ + middle_end/base_types/set_of_closures_id.cmx \ + typing/primitive.cmx \ + middle_end/parameter.cmx \ + utils/numbers.cmx \ + middle_end/base_types/mutable_variable.cmx \ + utils/misc.cmx \ middle_end/base_types/linkage_name.cmx \ - middle_end/initialize_symbol_to_let_symbol.cmx typing/ident.cmx \ - middle_end/flambda_utils.cmx middle_end/flambda.cmx \ - asmcomp/export_info.cmx middle_end/debuginfo.cmx asmcomp/compilenv.cmx \ - asmcomp/closure_offsets.cmx middle_end/base_types/closure_id.cmx \ - utils/clflags.cmx asmcomp/clambda.cmx middle_end/allocated_const.cmx \ + bytecomp/lambda.cmx \ + middle_end/initialize_symbol_to_let_symbol.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx \ + asmcomp/export_info.cmx \ + middle_end/debuginfo.cmx \ + asmcomp/compilenv.cmx \ + asmcomp/closure_offsets.cmx \ + middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx \ + asmcomp/clambda.cmx \ + asmcomp/backend_var.cmx \ + middle_end/allocated_const.cmx \ asmcomp/flambda_to_clambda.cmi -asmcomp/flambda_to_clambda.cmi : middle_end/base_types/symbol.cmi \ - middle_end/flambda.cmi asmcomp/export_info.cmi asmcomp/clambda.cmi -asmcomp/import_approx.cmo : middle_end/base_types/variable.cmi \ +asmcomp/flambda_to_clambda.cmi : \ + middle_end/base_types/symbol.cmi \ + middle_end/flambda.cmi \ + asmcomp/export_info.cmi \ + asmcomp/clambda.cmi +asmcomp/import_approx.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/base_types/symbol.cmi middle_end/simple_value_approx.cmi \ - middle_end/base_types/set_of_closures_id.cmi utils/misc.cmi \ - middle_end/freshening.cmi middle_end/flambda_iterators.cmi \ - middle_end/flambda.cmi asmcomp/export_info.cmi \ - middle_end/base_types/export_id.cmi asmcomp/compilenv.cmi \ + middle_end/base_types/symbol.cmi \ + middle_end/simple_value_approx.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + utils/misc.cmi \ + middle_end/freshening.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + asmcomp/export_info.cmi \ + middle_end/base_types/export_id.cmi \ + asmcomp/compilenv.cmi \ middle_end/base_types/compilation_unit.cmi \ - middle_end/base_types/closure_id.cmi asmcomp/import_approx.cmi -asmcomp/import_approx.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/closure_id.cmi \ + asmcomp/import_approx.cmi +asmcomp/import_approx.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ - middle_end/base_types/symbol.cmx middle_end/simple_value_approx.cmx \ - middle_end/base_types/set_of_closures_id.cmx utils/misc.cmx \ - middle_end/freshening.cmx middle_end/flambda_iterators.cmx \ - middle_end/flambda.cmx asmcomp/export_info.cmx \ - middle_end/base_types/export_id.cmx asmcomp/compilenv.cmx \ + middle_end/base_types/symbol.cmx \ + middle_end/simple_value_approx.cmx \ + middle_end/base_types/set_of_closures_id.cmx \ + utils/misc.cmx \ + middle_end/freshening.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + asmcomp/export_info.cmx \ + middle_end/base_types/export_id.cmx \ + asmcomp/compilenv.cmx \ middle_end/base_types/compilation_unit.cmx \ - middle_end/base_types/closure_id.cmx asmcomp/import_approx.cmi -asmcomp/import_approx.cmi : middle_end/base_types/symbol.cmi \ + middle_end/base_types/closure_id.cmx \ + asmcomp/import_approx.cmi +asmcomp/import_approx.cmi : \ + middle_end/base_types/symbol.cmi \ middle_end/simple_value_approx.cmi -asmcomp/interf.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \ - asmcomp/cmm.cmi asmcomp/interf.cmi -asmcomp/interf.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \ - asmcomp/cmm.cmx asmcomp/interf.cmi -asmcomp/interf.cmi : asmcomp/mach.cmi -asmcomp/interval.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \ +asmcomp/interf.cmo : \ + asmcomp/reg.cmi \ + asmcomp/proc.cmi \ + asmcomp/mach.cmi \ + asmcomp/cmm.cmi \ + asmcomp/interf.cmi +asmcomp/interf.cmx : \ + asmcomp/reg.cmx \ + asmcomp/proc.cmx \ + asmcomp/mach.cmx \ + asmcomp/cmm.cmx \ + asmcomp/interf.cmi +asmcomp/interf.cmi : \ + asmcomp/mach.cmi +asmcomp/interval.cmo : \ + asmcomp/reg.cmi \ + asmcomp/proc.cmi \ + asmcomp/mach.cmi \ asmcomp/interval.cmi -asmcomp/interval.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \ +asmcomp/interval.cmx : \ + asmcomp/reg.cmx \ + asmcomp/proc.cmx \ + asmcomp/mach.cmx \ asmcomp/interval.cmi -asmcomp/interval.cmi : asmcomp/reg.cmi asmcomp/mach.cmi -asmcomp/linearize.cmo : asmcomp/reg.cmi asmcomp/proc.cmi utils/misc.cmi \ - asmcomp/mach.cmi middle_end/debuginfo.cmi utils/config.cmi \ - asmcomp/cmm.cmi asmcomp/linearize.cmi -asmcomp/linearize.cmx : asmcomp/reg.cmx asmcomp/proc.cmx utils/misc.cmx \ - asmcomp/mach.cmx middle_end/debuginfo.cmx utils/config.cmx \ - asmcomp/cmm.cmx asmcomp/linearize.cmi -asmcomp/linearize.cmi : asmcomp/reg.cmi asmcomp/mach.cmi \ - middle_end/debuginfo.cmi asmcomp/cmm.cmi -asmcomp/linscan.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/interval.cmi \ +asmcomp/interval.cmi : \ + asmcomp/reg.cmi \ + asmcomp/mach.cmi +asmcomp/linearize.cmo : \ + asmcomp/reg.cmi \ + asmcomp/proc.cmi \ + utils/misc.cmi \ + asmcomp/mach.cmi \ + middle_end/debuginfo.cmi \ + utils/config.cmi \ + asmcomp/cmm.cmi \ + asmcomp/linearize.cmi +asmcomp/linearize.cmx : \ + asmcomp/reg.cmx \ + asmcomp/proc.cmx \ + utils/misc.cmx \ + asmcomp/mach.cmx \ + middle_end/debuginfo.cmx \ + utils/config.cmx \ + asmcomp/cmm.cmx \ + asmcomp/linearize.cmi +asmcomp/linearize.cmi : \ + asmcomp/reg.cmi \ + asmcomp/mach.cmi \ + middle_end/debuginfo.cmi \ + asmcomp/cmm.cmi +asmcomp/linscan.cmo : \ + asmcomp/reg.cmi \ + asmcomp/proc.cmi \ + asmcomp/interval.cmi \ asmcomp/linscan.cmi -asmcomp/linscan.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/interval.cmx \ +asmcomp/linscan.cmx : \ + asmcomp/reg.cmx \ + asmcomp/proc.cmx \ + asmcomp/interval.cmx \ asmcomp/linscan.cmi asmcomp/linscan.cmi : -asmcomp/liveness.cmo : asmcomp/reg.cmi asmcomp/proc.cmi \ - asmcomp/printmach.cmi utils/misc.cmi asmcomp/mach.cmi utils/config.cmi \ - asmcomp/cmm.cmi asmcomp/liveness.cmi -asmcomp/liveness.cmx : asmcomp/reg.cmx asmcomp/proc.cmx \ - asmcomp/printmach.cmx utils/misc.cmx asmcomp/mach.cmx utils/config.cmx \ - asmcomp/cmm.cmx asmcomp/liveness.cmi -asmcomp/liveness.cmi : asmcomp/mach.cmi -asmcomp/mach.cmo : asmcomp/debug/reg_with_debug_info.cmi \ - asmcomp/debug/reg_availability_set.cmi asmcomp/reg.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo \ +asmcomp/liveness.cmo : \ + asmcomp/reg.cmi \ + asmcomp/proc.cmi \ + asmcomp/printmach.cmi \ + utils/misc.cmi \ + asmcomp/mach.cmi \ + utils/config.cmi \ + asmcomp/cmm.cmi \ + asmcomp/liveness.cmi +asmcomp/liveness.cmx : \ + asmcomp/reg.cmx \ + asmcomp/proc.cmx \ + asmcomp/printmach.cmx \ + utils/misc.cmx \ + asmcomp/mach.cmx \ + utils/config.cmx \ + asmcomp/cmm.cmx \ + asmcomp/liveness.cmi +asmcomp/liveness.cmi : \ + asmcomp/mach.cmi +asmcomp/mach.cmo : \ + asmcomp/debug/reg_with_debug_info.cmi \ + asmcomp/debug/reg_availability_set.cmi \ + asmcomp/reg.cmi \ + middle_end/debuginfo.cmi \ + asmcomp/cmm.cmi \ + asmcomp/backend_var.cmi \ + asmcomp/arch.cmo \ asmcomp/mach.cmi -asmcomp/mach.cmx : asmcomp/debug/reg_with_debug_info.cmx \ - asmcomp/debug/reg_availability_set.cmx asmcomp/reg.cmx typing/ident.cmx \ - middle_end/debuginfo.cmx asmcomp/cmm.cmx asmcomp/arch.cmx \ +asmcomp/mach.cmx : \ + asmcomp/debug/reg_with_debug_info.cmx \ + asmcomp/debug/reg_availability_set.cmx \ + asmcomp/reg.cmx \ + middle_end/debuginfo.cmx \ + asmcomp/cmm.cmx \ + asmcomp/backend_var.cmx \ + asmcomp/arch.cmx \ asmcomp/mach.cmi -asmcomp/mach.cmi : asmcomp/debug/reg_availability_set.cmi asmcomp/reg.cmi \ - typing/ident.cmi middle_end/debuginfo.cmi asmcomp/cmm.cmi \ +asmcomp/mach.cmi : \ + asmcomp/debug/reg_availability_set.cmi \ + asmcomp/reg.cmi \ + middle_end/debuginfo.cmi \ + asmcomp/cmm.cmi \ + asmcomp/backend_var.cmi \ asmcomp/arch.cmo -asmcomp/printclambda.cmo : bytecomp/printlambda.cmi bytecomp/lambda.cmi \ - typing/ident.cmi asmcomp/clambda.cmi parsing/asttypes.cmi \ +asmcomp/printclambda.cmo : \ + bytecomp/printlambda.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + asmcomp/clambda.cmi \ + asmcomp/backend_var.cmi \ + parsing/asttypes.cmi \ asmcomp/printclambda.cmi -asmcomp/printclambda.cmx : bytecomp/printlambda.cmx bytecomp/lambda.cmx \ - typing/ident.cmx asmcomp/clambda.cmx parsing/asttypes.cmi \ +asmcomp/printclambda.cmx : \ + bytecomp/printlambda.cmx \ + bytecomp/lambda.cmx \ + typing/ident.cmx \ + asmcomp/clambda.cmx \ + asmcomp/backend_var.cmx \ + parsing/asttypes.cmi \ asmcomp/printclambda.cmi -asmcomp/printclambda.cmi : asmcomp/clambda.cmi -asmcomp/printcmm.cmo : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi asmcomp/cmm.cmi parsing/asttypes.cmi \ +asmcomp/printclambda.cmi : \ + asmcomp/clambda.cmi +asmcomp/printcmm.cmo : \ + utils/targetint.cmi \ + bytecomp/lambda.cmi \ + middle_end/debuginfo.cmi \ + asmcomp/cmm.cmi \ + asmcomp/backend_var.cmi \ + parsing/asttypes.cmi \ asmcomp/printcmm.cmi -asmcomp/printcmm.cmx : bytecomp/lambda.cmx typing/ident.cmx \ - middle_end/debuginfo.cmx asmcomp/cmm.cmx parsing/asttypes.cmi \ +asmcomp/printcmm.cmx : \ + utils/targetint.cmx \ + bytecomp/lambda.cmx \ + middle_end/debuginfo.cmx \ + asmcomp/cmm.cmx \ + asmcomp/backend_var.cmx \ + parsing/asttypes.cmi \ asmcomp/printcmm.cmi -asmcomp/printcmm.cmi : middle_end/debuginfo.cmi asmcomp/cmm.cmi -asmcomp/printlinear.cmo : asmcomp/printmach.cmi asmcomp/printcmm.cmi \ - asmcomp/mach.cmi asmcomp/linearize.cmi middle_end/debuginfo.cmi \ +asmcomp/printcmm.cmi : \ + middle_end/debuginfo.cmi \ + asmcomp/cmm.cmi +asmcomp/printlinear.cmo : \ + asmcomp/printmach.cmi \ + asmcomp/printcmm.cmi \ + asmcomp/mach.cmi \ + asmcomp/linearize.cmi \ + middle_end/debuginfo.cmi \ asmcomp/printlinear.cmi -asmcomp/printlinear.cmx : asmcomp/printmach.cmx asmcomp/printcmm.cmx \ - asmcomp/mach.cmx asmcomp/linearize.cmx middle_end/debuginfo.cmx \ +asmcomp/printlinear.cmx : \ + asmcomp/printmach.cmx \ + asmcomp/printcmm.cmx \ + asmcomp/mach.cmx \ + asmcomp/linearize.cmx \ + middle_end/debuginfo.cmx \ asmcomp/printlinear.cmi -asmcomp/printlinear.cmi : asmcomp/linearize.cmi -asmcomp/printmach.cmo : asmcomp/debug/reg_availability_set.cmi \ - asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/printcmm.cmi asmcomp/mach.cmi \ - asmcomp/interval.cmi typing/ident.cmi middle_end/debuginfo.cmi \ - utils/config.cmi asmcomp/cmm.cmi utils/clflags.cmi asmcomp/arch.cmo \ +asmcomp/printlinear.cmi : \ + asmcomp/linearize.cmi +asmcomp/printmach.cmo : \ + asmcomp/debug/reg_availability_set.cmi \ + asmcomp/reg.cmi \ + asmcomp/proc.cmi \ + asmcomp/printcmm.cmi \ + asmcomp/mach.cmi \ + asmcomp/interval.cmi \ + middle_end/debuginfo.cmi \ + utils/config.cmi \ + asmcomp/cmm.cmi \ + utils/clflags.cmi \ + asmcomp/backend_var.cmi \ + asmcomp/arch.cmo \ asmcomp/printmach.cmi -asmcomp/printmach.cmx : asmcomp/debug/reg_availability_set.cmx \ - asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/printcmm.cmx asmcomp/mach.cmx \ - asmcomp/interval.cmx typing/ident.cmx middle_end/debuginfo.cmx \ - utils/config.cmx asmcomp/cmm.cmx utils/clflags.cmx asmcomp/arch.cmx \ +asmcomp/printmach.cmx : \ + asmcomp/debug/reg_availability_set.cmx \ + asmcomp/reg.cmx \ + asmcomp/proc.cmx \ + asmcomp/printcmm.cmx \ + asmcomp/mach.cmx \ + asmcomp/interval.cmx \ + middle_end/debuginfo.cmx \ + utils/config.cmx \ + asmcomp/cmm.cmx \ + utils/clflags.cmx \ + asmcomp/backend_var.cmx \ + asmcomp/arch.cmx \ asmcomp/printmach.cmi -asmcomp/printmach.cmi : asmcomp/reg.cmi asmcomp/mach.cmi -asmcomp/proc.cmo : asmcomp/x86_proc.cmi asmcomp/reg.cmi utils/misc.cmi \ - asmcomp/mach.cmi utils/config.cmi asmcomp/cmm.cmi asmcomp/arch.cmo \ +asmcomp/printmach.cmi : \ + asmcomp/reg.cmi \ + asmcomp/mach.cmi +asmcomp/proc.cmo : \ + asmcomp/x86_proc.cmi \ + asmcomp/reg.cmi \ + utils/misc.cmi \ + asmcomp/mach.cmi \ + utils/config.cmi \ + asmcomp/cmm.cmi \ + asmcomp/arch.cmo \ asmcomp/proc.cmi -asmcomp/proc.cmx : asmcomp/x86_proc.cmx asmcomp/reg.cmx utils/misc.cmx \ - asmcomp/mach.cmx utils/config.cmx asmcomp/cmm.cmx asmcomp/arch.cmx \ +asmcomp/proc.cmx : \ + asmcomp/x86_proc.cmx \ + asmcomp/reg.cmx \ + utils/misc.cmx \ + asmcomp/mach.cmx \ + utils/config.cmx \ + asmcomp/cmm.cmx \ + asmcomp/arch.cmx \ asmcomp/proc.cmi -asmcomp/proc.cmi : asmcomp/reg.cmi asmcomp/mach.cmi -asmcomp/reg.cmo : typing/ident.cmi asmcomp/cmm.cmi asmcomp/reg.cmi -asmcomp/reg.cmx : typing/ident.cmx asmcomp/cmm.cmx asmcomp/reg.cmi -asmcomp/reg.cmi : typing/ident.cmi asmcomp/cmm.cmi -asmcomp/reload.cmo : asmcomp/reloadgen.cmi asmcomp/reg.cmi asmcomp/mach.cmi \ - asmcomp/cmm.cmi utils/clflags.cmi asmcomp/arch.cmo asmcomp/reload.cmi -asmcomp/reload.cmx : asmcomp/reloadgen.cmx asmcomp/reg.cmx asmcomp/mach.cmx \ - asmcomp/cmm.cmx utils/clflags.cmx asmcomp/arch.cmx asmcomp/reload.cmi -asmcomp/reload.cmi : asmcomp/mach.cmi -asmcomp/reloadgen.cmo : asmcomp/reg.cmi utils/misc.cmi asmcomp/mach.cmi \ +asmcomp/proc.cmi : \ + asmcomp/reg.cmi \ + asmcomp/mach.cmi +asmcomp/reg.cmo : \ + asmcomp/cmm.cmi \ + asmcomp/backend_var.cmi \ + asmcomp/reg.cmi +asmcomp/reg.cmx : \ + asmcomp/cmm.cmx \ + asmcomp/backend_var.cmx \ + asmcomp/reg.cmi +asmcomp/reg.cmi : \ + asmcomp/cmm.cmi \ + asmcomp/backend_var.cmi +asmcomp/reload.cmo : \ + asmcomp/reloadgen.cmi \ + asmcomp/reg.cmi \ + asmcomp/mach.cmi \ + asmcomp/cmm.cmi \ + utils/clflags.cmi \ + asmcomp/arch.cmo \ + asmcomp/reload.cmi +asmcomp/reload.cmx : \ + asmcomp/reloadgen.cmx \ + asmcomp/reg.cmx \ + asmcomp/mach.cmx \ + asmcomp/cmm.cmx \ + utils/clflags.cmx \ + asmcomp/arch.cmx \ + asmcomp/reload.cmi +asmcomp/reload.cmi : \ + asmcomp/mach.cmi +asmcomp/reloadgen.cmo : \ + asmcomp/reg.cmi \ + utils/misc.cmi \ + asmcomp/mach.cmi \ asmcomp/reloadgen.cmi -asmcomp/reloadgen.cmx : asmcomp/reg.cmx utils/misc.cmx asmcomp/mach.cmx \ +asmcomp/reloadgen.cmx : \ + asmcomp/reg.cmx \ + utils/misc.cmx \ + asmcomp/mach.cmx \ asmcomp/reloadgen.cmi -asmcomp/reloadgen.cmi : asmcomp/reg.cmi asmcomp/mach.cmi -asmcomp/schedgen.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \ - asmcomp/linearize.cmi asmcomp/cmm.cmi asmcomp/arch.cmo \ +asmcomp/reloadgen.cmi : \ + asmcomp/reg.cmi \ + asmcomp/mach.cmi +asmcomp/schedgen.cmo : \ + asmcomp/reg.cmi \ + asmcomp/proc.cmi \ + asmcomp/mach.cmi \ + asmcomp/linearize.cmi \ + asmcomp/cmm.cmi \ + asmcomp/arch.cmo \ asmcomp/schedgen.cmi -asmcomp/schedgen.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \ - asmcomp/linearize.cmx asmcomp/cmm.cmx asmcomp/arch.cmx \ +asmcomp/schedgen.cmx : \ + asmcomp/reg.cmx \ + asmcomp/proc.cmx \ + asmcomp/mach.cmx \ + asmcomp/linearize.cmx \ + asmcomp/cmm.cmx \ + asmcomp/arch.cmx \ asmcomp/schedgen.cmi -asmcomp/schedgen.cmi : asmcomp/mach.cmi asmcomp/linearize.cmi -asmcomp/scheduling.cmo : asmcomp/schedgen.cmi asmcomp/scheduling.cmi -asmcomp/scheduling.cmx : asmcomp/schedgen.cmx asmcomp/scheduling.cmi -asmcomp/scheduling.cmi : asmcomp/linearize.cmi -asmcomp/selectgen.cmo : utils/tbl.cmi bytecomp/simplif.cmi asmcomp/reg.cmi \ - asmcomp/proc.cmi utils/misc.cmi asmcomp/mach.cmi bytecomp/lambda.cmi \ - typing/ident.cmi middle_end/debuginfo.cmi utils/config.cmi \ - asmcomp/cmm.cmi parsing/asttypes.cmi asmcomp/arch.cmo \ +asmcomp/schedgen.cmi : \ + asmcomp/mach.cmi \ + asmcomp/linearize.cmi +asmcomp/scheduling.cmo : \ + asmcomp/schedgen.cmi \ + asmcomp/scheduling.cmi +asmcomp/scheduling.cmx : \ + asmcomp/schedgen.cmx \ + asmcomp/scheduling.cmi +asmcomp/scheduling.cmi : \ + asmcomp/linearize.cmi +asmcomp/selectgen.cmo : \ + bytecomp/simplif.cmi \ + asmcomp/reg.cmi \ + asmcomp/proc.cmi \ + utils/numbers.cmi \ + utils/misc.cmi \ + asmcomp/mach.cmi \ + bytecomp/lambda.cmi \ + middle_end/debuginfo.cmi \ + utils/config.cmi \ + asmcomp/cmm.cmi \ + asmcomp/backend_var.cmi \ + parsing/asttypes.cmi \ + asmcomp/arch.cmo \ asmcomp/selectgen.cmi -asmcomp/selectgen.cmx : utils/tbl.cmx bytecomp/simplif.cmx asmcomp/reg.cmx \ - asmcomp/proc.cmx utils/misc.cmx asmcomp/mach.cmx bytecomp/lambda.cmx \ - typing/ident.cmx middle_end/debuginfo.cmx utils/config.cmx \ - asmcomp/cmm.cmx parsing/asttypes.cmi asmcomp/arch.cmx \ +asmcomp/selectgen.cmx : \ + bytecomp/simplif.cmx \ + asmcomp/reg.cmx \ + asmcomp/proc.cmx \ + utils/numbers.cmx \ + utils/misc.cmx \ + asmcomp/mach.cmx \ + bytecomp/lambda.cmx \ + middle_end/debuginfo.cmx \ + utils/config.cmx \ + asmcomp/cmm.cmx \ + asmcomp/backend_var.cmx \ + parsing/asttypes.cmi \ + asmcomp/arch.cmx \ + asmcomp/selectgen.cmi +asmcomp/selectgen.cmi : \ + asmcomp/reg.cmi \ + asmcomp/mach.cmi \ + middle_end/debuginfo.cmi \ + asmcomp/cmm.cmi \ + asmcomp/backend_var.cmi \ + asmcomp/arch.cmo +asmcomp/selection.cmo : \ + asmcomp/spacetime_profiling.cmi \ + asmcomp/selectgen.cmi \ + asmcomp/proc.cmi \ + asmcomp/mach.cmi \ + utils/config.cmi \ + asmcomp/cmm.cmi \ + utils/clflags.cmi \ + asmcomp/arch.cmo \ + asmcomp/selection.cmi +asmcomp/selection.cmx : \ + asmcomp/spacetime_profiling.cmx \ + asmcomp/selectgen.cmx \ + asmcomp/proc.cmx \ + asmcomp/mach.cmx \ + utils/config.cmx \ + asmcomp/cmm.cmx \ + utils/clflags.cmx \ + asmcomp/arch.cmx \ + asmcomp/selection.cmi +asmcomp/selection.cmi : \ + asmcomp/mach.cmi \ + asmcomp/cmm.cmi +asmcomp/spacetime_profiling.cmo : \ + asmcomp/selectgen.cmi \ + asmcomp/proc.cmi \ + utils/misc.cmi \ + asmcomp/mach.cmi \ + bytecomp/lambda.cmi \ + middle_end/debuginfo.cmi \ + utils/config.cmi \ + asmcomp/cmm.cmi \ + asmcomp/backend_var.cmi \ + parsing/asttypes.cmi \ + asmcomp/arch.cmo \ + asmcomp/spacetime_profiling.cmi +asmcomp/spacetime_profiling.cmx : \ + asmcomp/selectgen.cmx \ + asmcomp/proc.cmx \ + utils/misc.cmx \ + asmcomp/mach.cmx \ + bytecomp/lambda.cmx \ + middle_end/debuginfo.cmx \ + utils/config.cmx \ + asmcomp/cmm.cmx \ + asmcomp/backend_var.cmx \ + parsing/asttypes.cmi \ + asmcomp/arch.cmx \ + asmcomp/spacetime_profiling.cmi +asmcomp/spacetime_profiling.cmi : \ asmcomp/selectgen.cmi -asmcomp/selectgen.cmi : asmcomp/reg.cmi asmcomp/mach.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo -asmcomp/selection.cmo : asmcomp/spacetime_profiling.cmi \ - asmcomp/selectgen.cmi asmcomp/proc.cmi asmcomp/mach.cmi utils/config.cmi \ - asmcomp/cmm.cmi utils/clflags.cmi asmcomp/arch.cmo asmcomp/selection.cmi -asmcomp/selection.cmx : asmcomp/spacetime_profiling.cmx \ - asmcomp/selectgen.cmx asmcomp/proc.cmx asmcomp/mach.cmx utils/config.cmx \ - asmcomp/cmm.cmx utils/clflags.cmx asmcomp/arch.cmx asmcomp/selection.cmi -asmcomp/selection.cmi : asmcomp/mach.cmi asmcomp/cmm.cmi -asmcomp/spacetime_profiling.cmo : asmcomp/selectgen.cmi asmcomp/proc.cmi \ - utils/misc.cmi asmcomp/mach.cmi bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/debuginfo.cmi utils/config.cmi asmcomp/cmm.cmi \ - parsing/asttypes.cmi asmcomp/arch.cmo asmcomp/spacetime_profiling.cmi -asmcomp/spacetime_profiling.cmx : asmcomp/selectgen.cmx asmcomp/proc.cmx \ - utils/misc.cmx asmcomp/mach.cmx bytecomp/lambda.cmx typing/ident.cmx \ - middle_end/debuginfo.cmx utils/config.cmx asmcomp/cmm.cmx \ - parsing/asttypes.cmi asmcomp/arch.cmx asmcomp/spacetime_profiling.cmi -asmcomp/spacetime_profiling.cmi : asmcomp/selectgen.cmi -asmcomp/spill.cmo : asmcomp/reg.cmi asmcomp/proc.cmi utils/misc.cmi \ - asmcomp/mach.cmi asmcomp/cmm.cmi utils/clflags.cmi asmcomp/spill.cmi -asmcomp/spill.cmx : asmcomp/reg.cmx asmcomp/proc.cmx utils/misc.cmx \ - asmcomp/mach.cmx asmcomp/cmm.cmx utils/clflags.cmx asmcomp/spill.cmi -asmcomp/spill.cmi : asmcomp/mach.cmi -asmcomp/split.cmo : asmcomp/reg.cmi utils/misc.cmi asmcomp/mach.cmi \ +asmcomp/spill.cmo : \ + asmcomp/reg.cmi \ + asmcomp/proc.cmi \ + utils/misc.cmi \ + asmcomp/mach.cmi \ + asmcomp/cmm.cmi \ + utils/clflags.cmi \ + asmcomp/spill.cmi +asmcomp/spill.cmx : \ + asmcomp/reg.cmx \ + asmcomp/proc.cmx \ + utils/misc.cmx \ + asmcomp/mach.cmx \ + asmcomp/cmm.cmx \ + utils/clflags.cmx \ + asmcomp/spill.cmi +asmcomp/spill.cmi : \ + asmcomp/mach.cmi +asmcomp/split.cmo : \ + asmcomp/reg.cmi \ + utils/misc.cmi \ + asmcomp/mach.cmi \ asmcomp/split.cmi -asmcomp/split.cmx : asmcomp/reg.cmx utils/misc.cmx asmcomp/mach.cmx \ +asmcomp/split.cmx : \ + asmcomp/reg.cmx \ + utils/misc.cmx \ + asmcomp/mach.cmx \ asmcomp/split.cmi -asmcomp/split.cmi : asmcomp/mach.cmi -asmcomp/strmatch.cmo : parsing/location.cmi bytecomp/lambda.cmi \ - typing/ident.cmi middle_end/debuginfo.cmi asmcomp/cmm.cmi \ - parsing/asttypes.cmi asmcomp/arch.cmo asmcomp/strmatch.cmi -asmcomp/strmatch.cmx : parsing/location.cmx bytecomp/lambda.cmx \ - typing/ident.cmx middle_end/debuginfo.cmx asmcomp/cmm.cmx \ - parsing/asttypes.cmi asmcomp/arch.cmx asmcomp/strmatch.cmi -asmcomp/strmatch.cmi : parsing/location.cmi middle_end/debuginfo.cmi \ +asmcomp/split.cmi : \ + asmcomp/mach.cmi +asmcomp/strmatch.cmo : \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + middle_end/debuginfo.cmi \ + asmcomp/cmm.cmi \ + asmcomp/backend_var.cmi \ + parsing/asttypes.cmi \ + asmcomp/arch.cmo \ + asmcomp/strmatch.cmi +asmcomp/strmatch.cmx : \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + middle_end/debuginfo.cmx \ + asmcomp/cmm.cmx \ + asmcomp/backend_var.cmx \ + parsing/asttypes.cmi \ + asmcomp/arch.cmx \ + asmcomp/strmatch.cmi +asmcomp/strmatch.cmi : \ + parsing/location.cmi \ + middle_end/debuginfo.cmi \ asmcomp/cmm.cmi asmcomp/traverse_for_exported_symbols.cmo : \ middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/base_types/symbol.cmi middle_end/simple_value_approx.cmi \ - middle_end/base_types/set_of_closures_id.cmi utils/misc.cmi \ - middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ - asmcomp/export_info.cmi middle_end/base_types/export_id.cmi \ + middle_end/base_types/symbol.cmi \ + middle_end/simple_value_approx.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + utils/misc.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + asmcomp/export_info.cmi \ + middle_end/base_types/export_id.cmi \ middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/closure_id.cmi \ asmcomp/traverse_for_exported_symbols.cmi asmcomp/traverse_for_exported_symbols.cmx : \ middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ - middle_end/base_types/symbol.cmx middle_end/simple_value_approx.cmx \ - middle_end/base_types/set_of_closures_id.cmx utils/misc.cmx \ - middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ - asmcomp/export_info.cmx middle_end/base_types/export_id.cmx \ + middle_end/base_types/symbol.cmx \ + middle_end/simple_value_approx.cmx \ + middle_end/base_types/set_of_closures_id.cmx \ + utils/misc.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + asmcomp/export_info.cmx \ + middle_end/base_types/export_id.cmx \ middle_end/base_types/compilation_unit.cmx \ middle_end/base_types/closure_id.cmx \ asmcomp/traverse_for_exported_symbols.cmi asmcomp/traverse_for_exported_symbols.cmi : \ middle_end/base_types/var_within_closure.cmi \ - middle_end/base_types/symbol.cmi middle_end/simple_value_approx.cmi \ - middle_end/base_types/set_of_closures_id.cmi middle_end/flambda.cmi \ - asmcomp/export_info.cmi middle_end/base_types/export_id.cmi \ + middle_end/base_types/symbol.cmi \ + middle_end/simple_value_approx.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + middle_end/flambda.cmi \ + asmcomp/export_info.cmi \ + middle_end/base_types/export_id.cmi \ middle_end/base_types/closure_id.cmi -asmcomp/un_anf.cmo : bytecomp/semantics_of_primitives.cmi \ - asmcomp/printclambda.cmi utils/misc.cmi bytecomp/lambda.cmi \ - typing/ident.cmi middle_end/debuginfo.cmi utils/clflags.cmi \ - asmcomp/clambda.cmi parsing/asttypes.cmi asmcomp/un_anf.cmi -asmcomp/un_anf.cmx : bytecomp/semantics_of_primitives.cmx \ - asmcomp/printclambda.cmx utils/misc.cmx bytecomp/lambda.cmx \ - typing/ident.cmx middle_end/debuginfo.cmx utils/clflags.cmx \ - asmcomp/clambda.cmx parsing/asttypes.cmi asmcomp/un_anf.cmi -asmcomp/un_anf.cmi : asmcomp/clambda.cmi +asmcomp/un_anf.cmo : \ + bytecomp/semantics_of_primitives.cmi \ + asmcomp/printclambda.cmi \ + utils/misc.cmi \ + bytecomp/lambda.cmi \ + middle_end/debuginfo.cmi \ + utils/clflags.cmi \ + asmcomp/clambda.cmi \ + asmcomp/backend_var.cmi \ + parsing/asttypes.cmi \ + asmcomp/un_anf.cmi +asmcomp/un_anf.cmx : \ + bytecomp/semantics_of_primitives.cmx \ + asmcomp/printclambda.cmx \ + utils/misc.cmx \ + bytecomp/lambda.cmx \ + middle_end/debuginfo.cmx \ + utils/clflags.cmx \ + asmcomp/clambda.cmx \ + asmcomp/backend_var.cmx \ + parsing/asttypes.cmi \ + asmcomp/un_anf.cmi +asmcomp/un_anf.cmi : \ + asmcomp/clambda.cmi asmcomp/x86_ast.cmi : -asmcomp/x86_dsl.cmo : asmcomp/x86_proc.cmi asmcomp/x86_ast.cmi \ +asmcomp/x86_dsl.cmo : \ + asmcomp/x86_proc.cmi \ + asmcomp/x86_ast.cmi \ asmcomp/x86_dsl.cmi -asmcomp/x86_dsl.cmx : asmcomp/x86_proc.cmx asmcomp/x86_ast.cmi \ +asmcomp/x86_dsl.cmx : \ + asmcomp/x86_proc.cmx \ + asmcomp/x86_ast.cmi \ asmcomp/x86_dsl.cmi -asmcomp/x86_dsl.cmi : asmcomp/x86_ast.cmi -asmcomp/x86_gas.cmo : asmcomp/x86_proc.cmi asmcomp/x86_ast.cmi \ - utils/misc.cmi asmcomp/x86_gas.cmi -asmcomp/x86_gas.cmx : asmcomp/x86_proc.cmx asmcomp/x86_ast.cmi \ - utils/misc.cmx asmcomp/x86_gas.cmi -asmcomp/x86_gas.cmi : asmcomp/x86_ast.cmi -asmcomp/x86_masm.cmo : asmcomp/x86_proc.cmi asmcomp/x86_ast.cmi \ +asmcomp/x86_dsl.cmi : \ + asmcomp/x86_ast.cmi +asmcomp/x86_gas.cmo : \ + asmcomp/x86_proc.cmi \ + asmcomp/x86_ast.cmi \ + utils/misc.cmi \ + asmcomp/x86_gas.cmi +asmcomp/x86_gas.cmx : \ + asmcomp/x86_proc.cmx \ + asmcomp/x86_ast.cmi \ + utils/misc.cmx \ + asmcomp/x86_gas.cmi +asmcomp/x86_gas.cmi : \ + asmcomp/x86_ast.cmi +asmcomp/x86_masm.cmo : \ + asmcomp/x86_proc.cmi \ + asmcomp/x86_ast.cmi \ asmcomp/x86_masm.cmi -asmcomp/x86_masm.cmx : asmcomp/x86_proc.cmx asmcomp/x86_ast.cmi \ +asmcomp/x86_masm.cmx : \ + asmcomp/x86_proc.cmx \ + asmcomp/x86_ast.cmi \ asmcomp/x86_masm.cmi -asmcomp/x86_masm.cmi : asmcomp/x86_ast.cmi -asmcomp/x86_proc.cmo : asmcomp/x86_ast.cmi utils/config.cmi \ - utils/clflags.cmi utils/ccomp.cmi asmcomp/x86_proc.cmi -asmcomp/x86_proc.cmx : asmcomp/x86_ast.cmi utils/config.cmx \ - utils/clflags.cmx utils/ccomp.cmx asmcomp/x86_proc.cmi -asmcomp/x86_proc.cmi : asmcomp/x86_ast.cmi -middle_end/alias_analysis.cmo : middle_end/base_types/variable.cmi \ +asmcomp/x86_masm.cmi : \ + asmcomp/x86_ast.cmi +asmcomp/x86_proc.cmo : \ + asmcomp/x86_ast.cmi \ + utils/misc.cmi \ + utils/config.cmi \ + utils/clflags.cmi \ + utils/ccomp.cmi \ + asmcomp/x86_proc.cmi +asmcomp/x86_proc.cmx : \ + asmcomp/x86_ast.cmi \ + utils/misc.cmx \ + utils/config.cmx \ + utils/clflags.cmx \ + utils/ccomp.cmx \ + asmcomp/x86_proc.cmi +asmcomp/x86_proc.cmi : \ + asmcomp/x86_ast.cmi +middle_end/alias_analysis.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ - utils/misc.cmi bytecomp/lambda.cmi middle_end/flambda.cmi \ - parsing/asttypes.cmi middle_end/allocated_const.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ + utils/misc.cmi \ + bytecomp/lambda.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda.cmi \ + parsing/asttypes.cmi \ + middle_end/allocated_const.cmi \ middle_end/alias_analysis.cmi -middle_end/alias_analysis.cmx : middle_end/base_types/variable.cmx \ +middle_end/alias_analysis.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ - middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \ - utils/misc.cmx bytecomp/lambda.cmx middle_end/flambda.cmx \ - parsing/asttypes.cmi middle_end/allocated_const.cmx \ + middle_end/base_types/tag.cmx \ + middle_end/base_types/symbol.cmx \ + utils/misc.cmx \ + bytecomp/lambda.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda.cmx \ + parsing/asttypes.cmi \ + middle_end/allocated_const.cmx \ middle_end/alias_analysis.cmi -middle_end/alias_analysis.cmi : middle_end/base_types/variable.cmi \ - middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ - bytecomp/lambda.cmi middle_end/flambda.cmi parsing/asttypes.cmi \ +middle_end/alias_analysis.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ + bytecomp/lambda.cmi \ + middle_end/flambda.cmi \ + parsing/asttypes.cmi \ + middle_end/allocated_const.cmi +middle_end/allocated_const.cmo : \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/allocated_const.cmi +middle_end/allocated_const.cmx : \ + middle_end/int_replace_polymorphic_compare.cmx \ middle_end/allocated_const.cmi -middle_end/allocated_const.cmo : middle_end/allocated_const.cmi -middle_end/allocated_const.cmx : middle_end/allocated_const.cmi middle_end/allocated_const.cmi : -middle_end/augment_specialised_args.cmo : middle_end/base_types/variable.cmi \ - middle_end/projection.cmi middle_end/pass_wrapper.cmi \ - middle_end/parameter.cmi utils/misc.cmi \ - middle_end/internal_variable_names.cmi middle_end/inlining_cost.cmi \ - middle_end/inline_and_simplify_aux.cmi utils/identifiable.cmi \ - middle_end/flambda_utils.cmi middle_end/flambda.cmi \ - middle_end/debuginfo.cmi middle_end/base_types/closure_origin.cmi \ - middle_end/base_types/closure_id.cmi utils/clflags.cmi \ - middle_end/backend_intf.cmi middle_end/augment_specialised_args.cmi -middle_end/augment_specialised_args.cmx : middle_end/base_types/variable.cmx \ - middle_end/projection.cmx middle_end/pass_wrapper.cmx \ - middle_end/parameter.cmx utils/misc.cmx \ - middle_end/internal_variable_names.cmx middle_end/inlining_cost.cmx \ - middle_end/inline_and_simplify_aux.cmx utils/identifiable.cmx \ - middle_end/flambda_utils.cmx middle_end/flambda.cmx \ - middle_end/debuginfo.cmx middle_end/base_types/closure_origin.cmx \ - middle_end/base_types/closure_id.cmx utils/clflags.cmx \ - middle_end/backend_intf.cmi middle_end/augment_specialised_args.cmi -middle_end/augment_specialised_args.cmi : middle_end/base_types/variable.cmi \ - middle_end/projection.cmi middle_end/inlining_cost.cmi \ - middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi -middle_end/backend_intf.cmi : middle_end/base_types/symbol.cmi \ - middle_end/simple_value_approx.cmi typing/ident.cmi \ +middle_end/augment_specialised_args.cmo : \ + middle_end/base_types/variable.cmi \ + middle_end/projection.cmi \ + middle_end/pass_wrapper.cmi \ + middle_end/parameter.cmi \ + utils/misc.cmi \ + middle_end/internal_variable_names.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/inline_and_simplify_aux.cmi \ + utils/identifiable.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi \ + middle_end/debuginfo.cmi \ + middle_end/base_types/closure_origin.cmi \ + middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi \ + middle_end/backend_intf.cmi \ + middle_end/augment_specialised_args.cmi +middle_end/augment_specialised_args.cmx : \ + middle_end/base_types/variable.cmx \ + middle_end/projection.cmx \ + middle_end/pass_wrapper.cmx \ + middle_end/parameter.cmx \ + utils/misc.cmx \ + middle_end/internal_variable_names.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inlining_cost.cmx \ + middle_end/inline_and_simplify_aux.cmx \ + utils/identifiable.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx \ + middle_end/debuginfo.cmx \ + middle_end/base_types/closure_origin.cmx \ + middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx \ + middle_end/backend_intf.cmi \ + middle_end/augment_specialised_args.cmi +middle_end/augment_specialised_args.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/projection.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda.cmi +middle_end/backend_intf.cmi : \ + middle_end/base_types/symbol.cmi \ + middle_end/simple_value_approx.cmi \ + typing/ident.cmi \ middle_end/base_types/closure_id.cmi -middle_end/closure_conversion.cmo : middle_end/base_types/variable.cmi \ - middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ - middle_end/base_types/static_exception.cmi bytecomp/simplif.cmi \ - typing/predef.cmi middle_end/parameter.cmi utils/numbers.cmi \ - middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ - middle_end/lift_code.cmi bytecomp/lambda.cmi \ - middle_end/internal_variable_names.cmi typing/ident.cmi \ - middle_end/flambda_utils.cmi middle_end/flambda.cmi \ - middle_end/debuginfo.cmi utils/config.cmi \ +middle_end/closure_conversion.cmo : \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ + middle_end/base_types/static_exception.cmi \ + bytecomp/simplif.cmi \ + typing/predef.cmi \ + middle_end/parameter.cmi \ + utils/numbers.cmi \ + middle_end/base_types/mutable_variable.cmi \ + utils/misc.cmi \ + middle_end/lift_code.cmi \ + bytecomp/lambda.cmi \ + middle_end/internal_variable_names.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + typing/ident.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi \ + middle_end/debuginfo.cmi \ + utils/config.cmi \ middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/closure_origin.cmi \ middle_end/base_types/closure_id.cmi \ - middle_end/closure_conversion_aux.cmi utils/clflags.cmi \ - middle_end/backend_intf.cmi middle_end/closure_conversion.cmi -middle_end/closure_conversion.cmx : middle_end/base_types/variable.cmx \ - middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \ - middle_end/base_types/static_exception.cmx bytecomp/simplif.cmx \ - typing/predef.cmx middle_end/parameter.cmx utils/numbers.cmx \ - middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ - middle_end/lift_code.cmx bytecomp/lambda.cmx \ - middle_end/internal_variable_names.cmx typing/ident.cmx \ - middle_end/flambda_utils.cmx middle_end/flambda.cmx \ - middle_end/debuginfo.cmx utils/config.cmx \ + middle_end/closure_conversion_aux.cmi \ + utils/clflags.cmi \ + middle_end/backend_intf.cmi \ + middle_end/closure_conversion.cmi +middle_end/closure_conversion.cmx : \ + middle_end/base_types/variable.cmx \ + middle_end/base_types/tag.cmx \ + middle_end/base_types/symbol.cmx \ + middle_end/base_types/static_exception.cmx \ + bytecomp/simplif.cmx \ + typing/predef.cmx \ + middle_end/parameter.cmx \ + utils/numbers.cmx \ + middle_end/base_types/mutable_variable.cmx \ + utils/misc.cmx \ + middle_end/lift_code.cmx \ + bytecomp/lambda.cmx \ + middle_end/internal_variable_names.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + typing/ident.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx \ + middle_end/debuginfo.cmx \ + utils/config.cmx \ middle_end/base_types/compilation_unit.cmx \ middle_end/base_types/closure_origin.cmx \ middle_end/base_types/closure_id.cmx \ - middle_end/closure_conversion_aux.cmx utils/clflags.cmx \ - middle_end/backend_intf.cmi middle_end/closure_conversion.cmi -middle_end/closure_conversion.cmi : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/flambda.cmi middle_end/backend_intf.cmi -middle_end/closure_conversion_aux.cmo : middle_end/base_types/variable.cmi \ + middle_end/closure_conversion_aux.cmx \ + utils/clflags.cmx \ + middle_end/backend_intf.cmi \ + middle_end/closure_conversion.cmi +middle_end/closure_conversion.cmi : \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + middle_end/flambda.cmi \ + middle_end/backend_intf.cmi +middle_end/closure_conversion_aux.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/symbol.cmi \ - middle_end/base_types/static_exception.cmi utils/numbers.cmi \ - middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ - parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi \ + middle_end/base_types/static_exception.cmi \ + utils/numbers.cmi \ + middle_end/base_types/mutable_variable.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + typing/ident.cmi \ middle_end/closure_conversion_aux.cmi -middle_end/closure_conversion_aux.cmx : middle_end/base_types/variable.cmx \ +middle_end/closure_conversion_aux.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/symbol.cmx \ - middle_end/base_types/static_exception.cmx utils/numbers.cmx \ - middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ - parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx \ + middle_end/base_types/static_exception.cmx \ + utils/numbers.cmx \ + middle_end/base_types/mutable_variable.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + typing/ident.cmx \ middle_end/closure_conversion_aux.cmi -middle_end/closure_conversion_aux.cmi : middle_end/base_types/variable.cmi \ +middle_end/closure_conversion_aux.cmi : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/symbol.cmi \ middle_end/base_types/static_exception.cmi \ - middle_end/base_types/mutable_variable.cmi parsing/location.cmi \ - bytecomp/lambda.cmi typing/ident.cmi -middle_end/debuginfo.cmo : parsing/location.cmi middle_end/debuginfo.cmi -middle_end/debuginfo.cmx : parsing/location.cmx middle_end/debuginfo.cmi -middle_end/debuginfo.cmi : parsing/location.cmi -middle_end/effect_analysis.cmo : bytecomp/semantics_of_primitives.cmi \ - utils/misc.cmi bytecomp/lambda.cmi middle_end/flambda.cmi \ + middle_end/base_types/mutable_variable.cmi \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + typing/ident.cmi +middle_end/debuginfo.cmo : \ + parsing/location.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/debuginfo.cmi +middle_end/debuginfo.cmx : \ + parsing/location.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/debuginfo.cmi +middle_end/debuginfo.cmi : \ + parsing/location.cmi +middle_end/effect_analysis.cmo : \ + bytecomp/semantics_of_primitives.cmi \ + utils/misc.cmi \ + bytecomp/lambda.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda.cmi \ middle_end/effect_analysis.cmi -middle_end/effect_analysis.cmx : bytecomp/semantics_of_primitives.cmx \ - utils/misc.cmx bytecomp/lambda.cmx middle_end/flambda.cmx \ +middle_end/effect_analysis.cmx : \ + bytecomp/semantics_of_primitives.cmx \ + utils/misc.cmx \ + bytecomp/lambda.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda.cmx \ middle_end/effect_analysis.cmi -middle_end/effect_analysis.cmi : middle_end/flambda.cmi -middle_end/extract_projections.cmo : middle_end/base_types/variable.cmi \ +middle_end/effect_analysis.cmi : \ + middle_end/flambda.cmi +middle_end/extract_projections.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/simple_value_approx.cmi middle_end/projection.cmi \ - middle_end/inline_and_simplify_aux.cmi middle_end/freshening.cmi \ - middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ - middle_end/base_types/closure_id.cmi middle_end/extract_projections.cmi -middle_end/extract_projections.cmx : middle_end/base_types/variable.cmx \ + middle_end/simple_value_approx.cmi \ + middle_end/projection.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inline_and_simplify_aux.cmi \ + middle_end/freshening.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + middle_end/base_types/closure_id.cmi \ + middle_end/extract_projections.cmi +middle_end/extract_projections.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ - middle_end/simple_value_approx.cmx middle_end/projection.cmx \ - middle_end/inline_and_simplify_aux.cmx middle_end/freshening.cmx \ - middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ - middle_end/base_types/closure_id.cmx middle_end/extract_projections.cmi -middle_end/extract_projections.cmi : middle_end/base_types/variable.cmi \ - middle_end/projection.cmi middle_end/inline_and_simplify_aux.cmi \ + middle_end/simple_value_approx.cmx \ + middle_end/projection.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inline_and_simplify_aux.cmx \ + middle_end/freshening.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + middle_end/base_types/closure_id.cmx \ + middle_end/extract_projections.cmi +middle_end/extract_projections.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/projection.cmi \ + middle_end/inline_and_simplify_aux.cmi \ middle_end/flambda.cmi -middle_end/find_recursive_functions.cmo : middle_end/base_types/variable.cmi \ - utils/strongly_connected_components.cmi middle_end/flambda_utils.cmi \ - middle_end/flambda.cmi middle_end/find_recursive_functions.cmi -middle_end/find_recursive_functions.cmx : middle_end/base_types/variable.cmx \ - utils/strongly_connected_components.cmx middle_end/flambda_utils.cmx \ - middle_end/flambda.cmx middle_end/find_recursive_functions.cmi -middle_end/find_recursive_functions.cmi : middle_end/base_types/variable.cmi \ - middle_end/flambda.cmi middle_end/backend_intf.cmi -middle_end/flambda.cmo : middle_end/base_types/variable.cmi \ - middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ +middle_end/find_recursive_functions.cmo : \ + middle_end/base_types/variable.cmi \ + utils/strongly_connected_components.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi \ + middle_end/backend_intf.cmi \ + middle_end/find_recursive_functions.cmi +middle_end/find_recursive_functions.cmx : \ + middle_end/base_types/variable.cmx \ + utils/strongly_connected_components.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx \ + middle_end/backend_intf.cmi \ + middle_end/find_recursive_functions.cmi +middle_end/find_recursive_functions.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/flambda.cmi \ + middle_end/backend_intf.cmi +middle_end/flambda.cmo : \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ middle_end/base_types/static_exception.cmi \ middle_end/base_types/set_of_closures_origin.cmi \ - middle_end/base_types/set_of_closures_id.cmi middle_end/projection.cmi \ - bytecomp/printlambda.cmi middle_end/parameter.cmi utils/numbers.cmi \ - middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ - bytecomp/lambda.cmi utils/identifiable.cmi middle_end/debuginfo.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + middle_end/projection.cmi \ + bytecomp/printlambda.cmi \ + middle_end/parameter.cmi \ + utils/numbers.cmi \ + middle_end/base_types/mutable_variable.cmi \ + utils/misc.cmi \ + bytecomp/lambda.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + utils/identifiable.cmi \ + middle_end/debuginfo.cmi \ middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/closure_origin.cmi \ - middle_end/base_types/closure_id.cmi utils/clflags.cmi \ - parsing/asttypes.cmi middle_end/allocated_const.cmi \ + middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi \ + parsing/asttypes.cmi \ + middle_end/allocated_const.cmi \ middle_end/flambda.cmi -middle_end/flambda.cmx : middle_end/base_types/variable.cmx \ - middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \ +middle_end/flambda.cmx : \ + middle_end/base_types/variable.cmx \ + middle_end/base_types/tag.cmx \ + middle_end/base_types/symbol.cmx \ middle_end/base_types/static_exception.cmx \ middle_end/base_types/set_of_closures_origin.cmx \ - middle_end/base_types/set_of_closures_id.cmx middle_end/projection.cmx \ - bytecomp/printlambda.cmx middle_end/parameter.cmx utils/numbers.cmx \ - middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ - bytecomp/lambda.cmx utils/identifiable.cmx middle_end/debuginfo.cmx \ + middle_end/base_types/set_of_closures_id.cmx \ + middle_end/projection.cmx \ + bytecomp/printlambda.cmx \ + middle_end/parameter.cmx \ + utils/numbers.cmx \ + middle_end/base_types/mutable_variable.cmx \ + utils/misc.cmx \ + bytecomp/lambda.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + utils/identifiable.cmx \ + middle_end/debuginfo.cmx \ middle_end/base_types/compilation_unit.cmx \ middle_end/base_types/closure_origin.cmx \ - middle_end/base_types/closure_id.cmx utils/clflags.cmx \ - parsing/asttypes.cmi middle_end/allocated_const.cmx \ + middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx \ + parsing/asttypes.cmi \ + middle_end/allocated_const.cmx \ middle_end/flambda.cmi -middle_end/flambda.cmi : middle_end/base_types/variable.cmi \ - middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ +middle_end/flambda.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ middle_end/base_types/static_exception.cmi \ middle_end/base_types/set_of_closures_origin.cmi \ - middle_end/base_types/set_of_closures_id.cmi middle_end/projection.cmi \ - middle_end/parameter.cmi utils/numbers.cmi \ - middle_end/base_types/mutable_variable.cmi bytecomp/lambda.cmi \ - utils/identifiable.cmi middle_end/debuginfo.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + middle_end/projection.cmi \ + middle_end/parameter.cmi \ + utils/numbers.cmi \ + middle_end/base_types/mutable_variable.cmi \ + bytecomp/lambda.cmi \ + utils/identifiable.cmi \ + middle_end/debuginfo.cmi \ middle_end/base_types/closure_origin.cmi \ - middle_end/base_types/closure_id.cmi parsing/asttypes.cmi \ + middle_end/base_types/closure_id.cmi \ + parsing/asttypes.cmi \ middle_end/allocated_const.cmi -middle_end/flambda_invariants.cmo : middle_end/base_types/variable.cmi \ +middle_end/flambda_invariants.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ middle_end/base_types/static_exception.cmi \ middle_end/base_types/set_of_closures_origin.cmi \ - middle_end/base_types/set_of_closures_id.cmi middle_end/projection.cmi \ - bytecomp/printlambda.cmi middle_end/parameter.cmi utils/numbers.cmi \ - middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ - bytecomp/lambda.cmi typing/ident.cmi middle_end/flambda_iterators.cmi \ - middle_end/flambda.cmi middle_end/debuginfo.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + middle_end/projection.cmi \ + bytecomp/printlambda.cmi \ + middle_end/parameter.cmi \ + utils/numbers.cmi \ + middle_end/base_types/mutable_variable.cmi \ + utils/misc.cmi \ + bytecomp/lambda.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + typing/ident.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + middle_end/debuginfo.cmi \ middle_end/base_types/compilation_unit.cmi \ - middle_end/base_types/closure_id.cmi parsing/asttypes.cmi \ - middle_end/allocated_const.cmi middle_end/flambda_invariants.cmi -middle_end/flambda_invariants.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/closure_id.cmi \ + parsing/asttypes.cmi \ + middle_end/allocated_const.cmi \ + middle_end/flambda_invariants.cmi +middle_end/flambda_invariants.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ - middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \ + middle_end/base_types/tag.cmx \ + middle_end/base_types/symbol.cmx \ middle_end/base_types/static_exception.cmx \ middle_end/base_types/set_of_closures_origin.cmx \ - middle_end/base_types/set_of_closures_id.cmx middle_end/projection.cmx \ - bytecomp/printlambda.cmx middle_end/parameter.cmx utils/numbers.cmx \ - middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ - bytecomp/lambda.cmx typing/ident.cmx middle_end/flambda_iterators.cmx \ - middle_end/flambda.cmx middle_end/debuginfo.cmx \ + middle_end/base_types/set_of_closures_id.cmx \ + middle_end/projection.cmx \ + bytecomp/printlambda.cmx \ + middle_end/parameter.cmx \ + utils/numbers.cmx \ + middle_end/base_types/mutable_variable.cmx \ + utils/misc.cmx \ + bytecomp/lambda.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + typing/ident.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + middle_end/debuginfo.cmx \ middle_end/base_types/compilation_unit.cmx \ - middle_end/base_types/closure_id.cmx parsing/asttypes.cmi \ - middle_end/allocated_const.cmx middle_end/flambda_invariants.cmi -middle_end/flambda_invariants.cmi : middle_end/flambda.cmi -middle_end/flambda_iterators.cmo : middle_end/base_types/variable.cmi \ - utils/misc.cmi middle_end/flambda.cmi middle_end/flambda_iterators.cmi -middle_end/flambda_iterators.cmx : middle_end/base_types/variable.cmx \ - utils/misc.cmx middle_end/flambda.cmx middle_end/flambda_iterators.cmi -middle_end/flambda_iterators.cmi : middle_end/base_types/variable.cmi \ - middle_end/base_types/symbol.cmi middle_end/flambda.cmi -middle_end/flambda_utils.cmo : middle_end/base_types/variable.cmi \ + middle_end/base_types/closure_id.cmx \ + parsing/asttypes.cmi \ + middle_end/allocated_const.cmx \ + middle_end/flambda_invariants.cmi +middle_end/flambda_invariants.cmi : \ + middle_end/flambda.cmi +middle_end/flambda_iterators.cmo : \ + middle_end/base_types/variable.cmi \ + utils/misc.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda.cmi \ + middle_end/flambda_iterators.cmi +middle_end/flambda_iterators.cmx : \ + middle_end/base_types/variable.cmx \ + utils/misc.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda.cmx \ + middle_end/flambda_iterators.cmi +middle_end/flambda_iterators.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/symbol.cmi \ + middle_end/flambda.cmi +middle_end/flambda_utils.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/base_types/symbol.cmi bytecomp/switch.cmi \ + middle_end/base_types/symbol.cmi \ + bytecomp/switch.cmi \ middle_end/base_types/static_exception.cmi \ - middle_end/base_types/set_of_closures_id.cmi middle_end/projection.cmi \ - middle_end/parameter.cmi middle_end/base_types/mutable_variable.cmi \ - utils/misc.cmi bytecomp/lambda.cmi middle_end/internal_variable_names.cmi \ - middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ - middle_end/debuginfo.cmi middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + middle_end/projection.cmi \ + middle_end/parameter.cmi \ + utils/numbers.cmi \ + middle_end/base_types/mutable_variable.cmi \ + utils/misc.cmi \ + bytecomp/lambda.cmi \ + middle_end/internal_variable_names.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + middle_end/debuginfo.cmi \ + middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/closure_origin.cmi \ - middle_end/base_types/closure_id.cmi middle_end/backend_intf.cmi \ - middle_end/allocated_const.cmi middle_end/flambda_utils.cmi -middle_end/flambda_utils.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/closure_id.cmi \ + parsing/asttypes.cmi \ + middle_end/allocated_const.cmi \ + middle_end/flambda_utils.cmi +middle_end/flambda_utils.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ - middle_end/base_types/symbol.cmx bytecomp/switch.cmx \ + middle_end/base_types/symbol.cmx \ + bytecomp/switch.cmx \ middle_end/base_types/static_exception.cmx \ - middle_end/base_types/set_of_closures_id.cmx middle_end/projection.cmx \ - middle_end/parameter.cmx middle_end/base_types/mutable_variable.cmx \ - utils/misc.cmx bytecomp/lambda.cmx middle_end/internal_variable_names.cmx \ - middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ - middle_end/debuginfo.cmx middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/set_of_closures_id.cmx \ + middle_end/projection.cmx \ + middle_end/parameter.cmx \ + utils/numbers.cmx \ + middle_end/base_types/mutable_variable.cmx \ + utils/misc.cmx \ + bytecomp/lambda.cmx \ + middle_end/internal_variable_names.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + middle_end/debuginfo.cmx \ + middle_end/base_types/compilation_unit.cmx \ middle_end/base_types/closure_origin.cmx \ - middle_end/base_types/closure_id.cmx middle_end/backend_intf.cmi \ - middle_end/allocated_const.cmx middle_end/flambda_utils.cmi -middle_end/flambda_utils.cmi : middle_end/base_types/variable.cmi \ + middle_end/base_types/closure_id.cmx \ + parsing/asttypes.cmi \ + middle_end/allocated_const.cmx \ + middle_end/flambda_utils.cmi +middle_end/flambda_utils.cmi : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ - bytecomp/switch.cmi middle_end/base_types/static_exception.cmi \ - middle_end/base_types/set_of_closures_id.cmi middle_end/projection.cmi \ - middle_end/parameter.cmi middle_end/internal_variable_names.cmi \ - middle_end/flambda.cmi middle_end/base_types/closure_id.cmi \ - middle_end/backend_intf.cmi -middle_end/freshening.cmo : middle_end/base_types/variable.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ + bytecomp/switch.cmi \ + middle_end/base_types/static_exception.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + middle_end/projection.cmi \ + middle_end/parameter.cmi \ + middle_end/internal_variable_names.cmi \ + middle_end/flambda.cmi \ + middle_end/base_types/closure_id.cmi +middle_end/freshening.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ middle_end/base_types/symbol.cmi \ - middle_end/base_types/static_exception.cmi middle_end/projection.cmi \ - middle_end/parameter.cmi middle_end/base_types/mutable_variable.cmi \ - utils/misc.cmi utils/identifiable.cmi middle_end/flambda_utils.cmi \ - middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ - middle_end/base_types/closure_id.cmi middle_end/freshening.cmi -middle_end/freshening.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/static_exception.cmi \ + middle_end/projection.cmi \ + middle_end/parameter.cmi \ + middle_end/base_types/mutable_variable.cmi \ + utils/misc.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + utils/identifiable.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + middle_end/base_types/closure_id.cmi \ + middle_end/freshening.cmi +middle_end/freshening.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ middle_end/base_types/symbol.cmx \ - middle_end/base_types/static_exception.cmx middle_end/projection.cmx \ - middle_end/parameter.cmx middle_end/base_types/mutable_variable.cmx \ - utils/misc.cmx utils/identifiable.cmx middle_end/flambda_utils.cmx \ - middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ - middle_end/base_types/closure_id.cmx middle_end/freshening.cmi -middle_end/freshening.cmi : middle_end/base_types/variable.cmi \ + middle_end/base_types/static_exception.cmx \ + middle_end/projection.cmx \ + middle_end/parameter.cmx \ + middle_end/base_types/mutable_variable.cmx \ + utils/misc.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + utils/identifiable.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + middle_end/base_types/closure_id.cmx \ + middle_end/freshening.cmi +middle_end/freshening.cmi : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ middle_end/base_types/symbol.cmi \ middle_end/base_types/static_exception.cmi \ - middle_end/base_types/mutable_variable.cmi middle_end/flambda.cmi \ + middle_end/base_types/mutable_variable.cmi \ + middle_end/flambda.cmi \ middle_end/base_types/closure_id.cmi -middle_end/inconstant_idents.cmo : middle_end/base_types/variable.cmi \ +middle_end/inconstant_idents.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/symbol.cmi \ - middle_end/base_types/set_of_closures_id.cmi middle_end/parameter.cmi \ - utils/numbers.cmi utils/misc.cmi bytecomp/lambda.cmi \ - utils/identifiable.cmi middle_end/flambda_utils.cmi \ - middle_end/flambda.cmi middle_end/base_types/compilation_unit.cmi \ - middle_end/base_types/closure_id.cmi middle_end/backend_intf.cmi \ - parsing/asttypes.cmi middle_end/inconstant_idents.cmi -middle_end/inconstant_idents.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/set_of_closures_id.cmi \ + middle_end/parameter.cmi \ + utils/numbers.cmi \ + utils/misc.cmi \ + bytecomp/lambda.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + utils/identifiable.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/closure_id.cmi \ + middle_end/backend_intf.cmi \ + parsing/asttypes.cmi \ + middle_end/inconstant_idents.cmi +middle_end/inconstant_idents.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/symbol.cmx \ - middle_end/base_types/set_of_closures_id.cmx middle_end/parameter.cmx \ - utils/numbers.cmx utils/misc.cmx bytecomp/lambda.cmx \ - utils/identifiable.cmx middle_end/flambda_utils.cmx \ - middle_end/flambda.cmx middle_end/base_types/compilation_unit.cmx \ - middle_end/base_types/closure_id.cmx middle_end/backend_intf.cmi \ - parsing/asttypes.cmi middle_end/inconstant_idents.cmi -middle_end/inconstant_idents.cmi : middle_end/base_types/variable.cmi \ - middle_end/base_types/set_of_closures_id.cmi middle_end/flambda.cmi \ - middle_end/base_types/compilation_unit.cmi middle_end/backend_intf.cmi + middle_end/base_types/set_of_closures_id.cmx \ + middle_end/parameter.cmx \ + utils/numbers.cmx \ + utils/misc.cmx \ + bytecomp/lambda.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + utils/identifiable.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx \ + middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/closure_id.cmx \ + middle_end/backend_intf.cmi \ + parsing/asttypes.cmi \ + middle_end/inconstant_idents.cmi +middle_end/inconstant_idents.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + middle_end/flambda.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/backend_intf.cmi middle_end/initialize_symbol_to_let_symbol.cmo : \ - middle_end/base_types/variable.cmi utils/misc.cmi middle_end/flambda.cmi \ + middle_end/base_types/variable.cmi \ + utils/misc.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda.cmi \ middle_end/initialize_symbol_to_let_symbol.cmi middle_end/initialize_symbol_to_let_symbol.cmx : \ - middle_end/base_types/variable.cmx utils/misc.cmx middle_end/flambda.cmx \ + middle_end/base_types/variable.cmx \ + utils/misc.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda.cmx \ middle_end/initialize_symbol_to_let_symbol.cmi -middle_end/initialize_symbol_to_let_symbol.cmi : middle_end/flambda.cmi -middle_end/inline_and_simplify.cmo : utils/warnings.cmi \ +middle_end/initialize_symbol_to_let_symbol.cmi : \ + middle_end/flambda.cmi +middle_end/inline_and_simplify.cmo : \ + utils/warnings.cmi \ middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ middle_end/unbox_specialised_args.cmi \ - middle_end/unbox_free_vars_of_closures.cmi middle_end/unbox_closures.cmi \ - middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ + middle_end/unbox_free_vars_of_closures.cmi \ + middle_end/unbox_closures.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ middle_end/base_types/static_exception.cmi \ - middle_end/simplify_primitives.cmi middle_end/simple_value_approx.cmi \ + middle_end/simplify_primitives.cmi \ + middle_end/simple_value_approx.cmi \ middle_end/remove_unused_arguments.cmi \ - middle_end/remove_free_vars_equal_to_args.cmi middle_end/projection.cmi \ - typing/predef.cmi middle_end/parameter.cmi utils/misc.cmi \ - parsing/location.cmi middle_end/lift_code.cmi bytecomp/lambda.cmi \ - middle_end/invariant_params.cmi middle_end/internal_variable_names.cmi \ - middle_end/inlining_stats.cmi middle_end/inlining_decision.cmi \ - middle_end/inlining_cost.cmi middle_end/inline_and_simplify_aux.cmi \ - typing/ident.cmi middle_end/freshening.cmi middle_end/flambda_utils.cmi \ - middle_end/flambda.cmi middle_end/find_recursive_functions.cmi \ - middle_end/effect_analysis.cmi middle_end/debuginfo.cmi utils/config.cmi \ + middle_end/remove_free_vars_equal_to_args.cmi \ + middle_end/projection.cmi \ + typing/predef.cmi \ + middle_end/parameter.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + middle_end/lift_code.cmi \ + bytecomp/lambda.cmi \ + middle_end/invariant_params.cmi \ + middle_end/internal_variable_names.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inlining_stats.cmi \ + middle_end/inlining_decision.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/inline_and_simplify_aux.cmi \ + typing/ident.cmi \ + middle_end/freshening.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi \ + middle_end/find_recursive_functions.cmi \ + middle_end/effect_analysis.cmi \ + middle_end/debuginfo.cmi \ + utils/config.cmi \ middle_end/base_types/closure_origin.cmi \ - middle_end/base_types/closure_id.cmi utils/clflags.cmi \ - middle_end/backend_intf.cmi middle_end/allocated_const.cmi \ + middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi \ + middle_end/backend_intf.cmi \ + middle_end/allocated_const.cmi \ middle_end/inline_and_simplify.cmi -middle_end/inline_and_simplify.cmx : utils/warnings.cmx \ +middle_end/inline_and_simplify.cmx : \ + utils/warnings.cmx \ middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ middle_end/unbox_specialised_args.cmx \ - middle_end/unbox_free_vars_of_closures.cmx middle_end/unbox_closures.cmx \ - middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \ + middle_end/unbox_free_vars_of_closures.cmx \ + middle_end/unbox_closures.cmx \ + middle_end/base_types/tag.cmx \ + middle_end/base_types/symbol.cmx \ middle_end/base_types/static_exception.cmx \ - middle_end/simplify_primitives.cmx middle_end/simple_value_approx.cmx \ + middle_end/simplify_primitives.cmx \ + middle_end/simple_value_approx.cmx \ middle_end/remove_unused_arguments.cmx \ - middle_end/remove_free_vars_equal_to_args.cmx middle_end/projection.cmx \ - typing/predef.cmx middle_end/parameter.cmx utils/misc.cmx \ - parsing/location.cmx middle_end/lift_code.cmx bytecomp/lambda.cmx \ - middle_end/invariant_params.cmx middle_end/internal_variable_names.cmx \ - middle_end/inlining_stats.cmx middle_end/inlining_decision.cmx \ - middle_end/inlining_cost.cmx middle_end/inline_and_simplify_aux.cmx \ - typing/ident.cmx middle_end/freshening.cmx middle_end/flambda_utils.cmx \ - middle_end/flambda.cmx middle_end/find_recursive_functions.cmx \ - middle_end/effect_analysis.cmx middle_end/debuginfo.cmx utils/config.cmx \ + middle_end/remove_free_vars_equal_to_args.cmx \ + middle_end/projection.cmx \ + typing/predef.cmx \ + middle_end/parameter.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + middle_end/lift_code.cmx \ + bytecomp/lambda.cmx \ + middle_end/invariant_params.cmx \ + middle_end/internal_variable_names.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inlining_stats.cmx \ + middle_end/inlining_decision.cmx \ + middle_end/inlining_cost.cmx \ + middle_end/inline_and_simplify_aux.cmx \ + typing/ident.cmx \ + middle_end/freshening.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx \ + middle_end/find_recursive_functions.cmx \ + middle_end/effect_analysis.cmx \ + middle_end/debuginfo.cmx \ + utils/config.cmx \ middle_end/base_types/closure_origin.cmx \ - middle_end/base_types/closure_id.cmx utils/clflags.cmx \ - middle_end/backend_intf.cmi middle_end/allocated_const.cmx \ + middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx \ + middle_end/backend_intf.cmi \ + middle_end/allocated_const.cmx \ middle_end/inline_and_simplify.cmi -middle_end/inline_and_simplify.cmi : middle_end/base_types/variable.cmi \ - middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi \ +middle_end/inline_and_simplify.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda.cmi \ middle_end/backend_intf.cmi -middle_end/inline_and_simplify_aux.cmo : middle_end/base_types/variable.cmi \ +middle_end/inline_and_simplify_aux.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ middle_end/base_types/symbol.cmi \ middle_end/base_types/static_exception.cmi \ middle_end/simple_value_approx.cmi \ middle_end/base_types/set_of_closures_origin.cmi \ - middle_end/projection.cmi middle_end/parameter.cmi \ - middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ - middle_end/inlining_stats.cmi middle_end/inlining_cost.cmi \ - middle_end/freshening.cmi middle_end/flambda_utils.cmi \ - middle_end/flambda.cmi middle_end/debuginfo.cmi \ + middle_end/projection.cmi \ + middle_end/parameter.cmi \ + middle_end/base_types/mutable_variable.cmi \ + utils/misc.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inlining_stats.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/freshening.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi \ + middle_end/debuginfo.cmi \ middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/closure_origin.cmi \ - middle_end/base_types/closure_id.cmi utils/clflags.cmi \ - middle_end/backend_intf.cmi middle_end/inline_and_simplify_aux.cmi -middle_end/inline_and_simplify_aux.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi \ + middle_end/backend_intf.cmi \ + middle_end/inline_and_simplify_aux.cmi +middle_end/inline_and_simplify_aux.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ middle_end/base_types/symbol.cmx \ middle_end/base_types/static_exception.cmx \ middle_end/simple_value_approx.cmx \ middle_end/base_types/set_of_closures_origin.cmx \ - middle_end/projection.cmx middle_end/parameter.cmx \ - middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ - middle_end/inlining_stats.cmx middle_end/inlining_cost.cmx \ - middle_end/freshening.cmx middle_end/flambda_utils.cmx \ - middle_end/flambda.cmx middle_end/debuginfo.cmx \ + middle_end/projection.cmx \ + middle_end/parameter.cmx \ + middle_end/base_types/mutable_variable.cmx \ + utils/misc.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inlining_stats.cmx \ + middle_end/inlining_cost.cmx \ + middle_end/freshening.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx \ + middle_end/debuginfo.cmx \ middle_end/base_types/compilation_unit.cmx \ middle_end/base_types/closure_origin.cmx \ - middle_end/base_types/closure_id.cmx utils/clflags.cmx \ - middle_end/backend_intf.cmi middle_end/inline_and_simplify_aux.cmi -middle_end/inline_and_simplify_aux.cmi : middle_end/base_types/variable.cmi \ + middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx \ + middle_end/backend_intf.cmi \ + middle_end/inline_and_simplify_aux.cmi +middle_end/inline_and_simplify_aux.cmi : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/symbol.cmi \ middle_end/base_types/static_exception.cmi \ middle_end/simple_value_approx.cmi \ middle_end/base_types/set_of_closures_origin.cmi \ - middle_end/projection.cmi middle_end/base_types/mutable_variable.cmi \ - middle_end/inlining_stats_types.cmi middle_end/inlining_cost.cmi \ - middle_end/freshening.cmi middle_end/flambda.cmi middle_end/debuginfo.cmi \ + middle_end/projection.cmi \ + middle_end/base_types/mutable_variable.cmi \ + middle_end/inlining_stats_types.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/freshening.cmi \ + middle_end/flambda.cmi \ + middle_end/debuginfo.cmi \ middle_end/base_types/closure_origin.cmi \ - middle_end/base_types/closure_id.cmi middle_end/backend_intf.cmi -middle_end/inlining_cost.cmo : middle_end/base_types/variable.cmi \ - middle_end/projection.cmi typing/primitive.cmi utils/misc.cmi \ - bytecomp/lambda.cmi middle_end/flambda_iterators.cmi \ - middle_end/flambda.cmi utils/clflags.cmi middle_end/inlining_cost.cmi -middle_end/inlining_cost.cmx : middle_end/base_types/variable.cmx \ - middle_end/projection.cmx typing/primitive.cmx utils/misc.cmx \ - bytecomp/lambda.cmx middle_end/flambda_iterators.cmx \ - middle_end/flambda.cmx utils/clflags.cmx middle_end/inlining_cost.cmi -middle_end/inlining_cost.cmi : middle_end/projection.cmi \ + middle_end/base_types/closure_id.cmi \ + middle_end/backend_intf.cmi +middle_end/inlining_cost.cmo : \ + middle_end/base_types/variable.cmi \ + middle_end/projection.cmi \ + typing/primitive.cmi \ + utils/misc.cmi \ + bytecomp/lambda.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + utils/clflags.cmi \ + middle_end/inlining_cost.cmi +middle_end/inlining_cost.cmx : \ + middle_end/base_types/variable.cmx \ + middle_end/projection.cmx \ + typing/primitive.cmx \ + utils/misc.cmx \ + bytecomp/lambda.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + utils/clflags.cmx \ + middle_end/inlining_cost.cmi +middle_end/inlining_cost.cmi : \ + middle_end/projection.cmi \ middle_end/flambda.cmi -middle_end/inlining_decision.cmo : middle_end/base_types/variable.cmi \ +middle_end/inlining_decision.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/simple_value_approx.cmi middle_end/parameter.cmi \ - utils/misc.cmi bytecomp/lambda.cmi middle_end/inlining_transforms.cmi \ - middle_end/inlining_stats_types.cmi middle_end/inlining_cost.cmi \ - middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi \ - middle_end/base_types/closure_id.cmi utils/clflags.cmi \ + middle_end/simple_value_approx.cmi \ + middle_end/parameter.cmi \ + utils/misc.cmi \ + bytecomp/lambda.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inlining_transforms.cmi \ + middle_end/inlining_stats_types.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda.cmi \ + middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi \ middle_end/inlining_decision.cmi -middle_end/inlining_decision.cmx : middle_end/base_types/variable.cmx \ +middle_end/inlining_decision.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ - middle_end/simple_value_approx.cmx middle_end/parameter.cmx \ - utils/misc.cmx bytecomp/lambda.cmx middle_end/inlining_transforms.cmx \ - middle_end/inlining_stats_types.cmx middle_end/inlining_cost.cmx \ - middle_end/inline_and_simplify_aux.cmx middle_end/flambda.cmx \ - middle_end/base_types/closure_id.cmx utils/clflags.cmx \ + middle_end/simple_value_approx.cmx \ + middle_end/parameter.cmx \ + utils/misc.cmx \ + bytecomp/lambda.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inlining_transforms.cmx \ + middle_end/inlining_stats_types.cmx \ + middle_end/inlining_cost.cmx \ + middle_end/inline_and_simplify_aux.cmx \ + middle_end/flambda.cmx \ + middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx \ middle_end/inlining_decision.cmi -middle_end/inlining_decision.cmi : middle_end/base_types/variable.cmi \ - middle_end/simple_value_approx.cmi bytecomp/lambda.cmi \ +middle_end/inlining_decision.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/simple_value_approx.cmi \ + bytecomp/lambda.cmi \ middle_end/inlining_decision_intf.cmi \ - middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi \ - middle_end/debuginfo.cmi middle_end/base_types/closure_id.cmi -middle_end/inlining_decision_intf.cmi : middle_end/base_types/variable.cmi \ - middle_end/simple_value_approx.cmi middle_end/inline_and_simplify_aux.cmi \ - middle_end/flambda.cmi middle_end/debuginfo.cmi \ + middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda.cmi \ + middle_end/debuginfo.cmi \ + middle_end/base_types/closure_id.cmi +middle_end/inlining_decision_intf.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/simple_value_approx.cmi \ + middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda.cmi \ + middle_end/debuginfo.cmi \ middle_end/base_types/closure_id.cmi -middle_end/inlining_stats.cmo : utils/misc.cmi \ - middle_end/inlining_stats_types.cmi middle_end/debuginfo.cmi \ - middle_end/base_types/closure_id.cmi utils/clflags.cmi \ +middle_end/inlining_stats.cmo : \ + utils/misc.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inlining_stats_types.cmi \ + middle_end/debuginfo.cmi \ + middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi \ middle_end/inlining_stats.cmi -middle_end/inlining_stats.cmx : utils/misc.cmx \ - middle_end/inlining_stats_types.cmx middle_end/debuginfo.cmx \ - middle_end/base_types/closure_id.cmx utils/clflags.cmx \ +middle_end/inlining_stats.cmx : \ + utils/misc.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inlining_stats_types.cmx \ + middle_end/debuginfo.cmx \ + middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx \ middle_end/inlining_stats.cmi -middle_end/inlining_stats.cmi : middle_end/inlining_stats_types.cmi \ - middle_end/debuginfo.cmi middle_end/base_types/closure_id.cmi -middle_end/inlining_stats_types.cmo : middle_end/inlining_cost.cmi \ +middle_end/inlining_stats.cmi : \ + middle_end/inlining_stats_types.cmi \ + middle_end/debuginfo.cmi \ + middle_end/base_types/closure_id.cmi +middle_end/inlining_stats_types.cmo : \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inlining_cost.cmi \ middle_end/inlining_stats_types.cmi -middle_end/inlining_stats_types.cmx : middle_end/inlining_cost.cmx \ +middle_end/inlining_stats_types.cmx : \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inlining_cost.cmx \ middle_end/inlining_stats_types.cmi -middle_end/inlining_stats_types.cmi : middle_end/inlining_cost.cmi -middle_end/inlining_transforms.cmo : middle_end/base_types/variable.cmi \ +middle_end/inlining_stats_types.cmi : \ + middle_end/inlining_cost.cmi +middle_end/inlining_transforms.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/simple_value_approx.cmi middle_end/projection.cmi \ - middle_end/parameter.cmi bytecomp/lambda.cmi \ + middle_end/simple_value_approx.cmi \ + middle_end/projection.cmi \ + middle_end/parameter.cmi \ + bytecomp/lambda.cmi \ middle_end/internal_variable_names.cmi \ - middle_end/inlining_decision_intf.cmi middle_end/inlining_cost.cmi \ - middle_end/inline_and_simplify_aux.cmi middle_end/flambda_utils.cmi \ - middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ - middle_end/debuginfo.cmi middle_end/base_types/compilation_unit.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inlining_decision_intf.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + middle_end/debuginfo.cmi \ + middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/closure_origin.cmi \ - middle_end/base_types/closure_id.cmi middle_end/inlining_transforms.cmi -middle_end/inlining_transforms.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/closure_id.cmi \ + middle_end/inlining_transforms.cmi +middle_end/inlining_transforms.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ - middle_end/simple_value_approx.cmx middle_end/projection.cmx \ - middle_end/parameter.cmx bytecomp/lambda.cmx \ + middle_end/simple_value_approx.cmx \ + middle_end/projection.cmx \ + middle_end/parameter.cmx \ + bytecomp/lambda.cmx \ middle_end/internal_variable_names.cmx \ - middle_end/inlining_decision_intf.cmi middle_end/inlining_cost.cmx \ - middle_end/inline_and_simplify_aux.cmx middle_end/flambda_utils.cmx \ - middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ - middle_end/debuginfo.cmx middle_end/base_types/compilation_unit.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inlining_decision_intf.cmi \ + middle_end/inlining_cost.cmx \ + middle_end/inline_and_simplify_aux.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + middle_end/debuginfo.cmx \ + middle_end/base_types/compilation_unit.cmx \ middle_end/base_types/closure_origin.cmx \ - middle_end/base_types/closure_id.cmx middle_end/inlining_transforms.cmi -middle_end/inlining_transforms.cmi : middle_end/base_types/variable.cmi \ - middle_end/simple_value_approx.cmi bytecomp/lambda.cmi \ + middle_end/base_types/closure_id.cmx \ + middle_end/inlining_transforms.cmi +middle_end/inlining_transforms.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/simple_value_approx.cmi \ + bytecomp/lambda.cmi \ middle_end/inlining_decision_intf.cmi \ - middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi \ - middle_end/debuginfo.cmi middle_end/base_types/closure_id.cmi -middle_end/internal_variable_names.cmo : parsing/location.cmi \ - bytecomp/lambda.cmi middle_end/internal_variable_names.cmi -middle_end/internal_variable_names.cmx : parsing/location.cmx \ - bytecomp/lambda.cmx middle_end/internal_variable_names.cmi -middle_end/internal_variable_names.cmi : parsing/location.cmi \ + middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda.cmi \ + middle_end/debuginfo.cmi \ + middle_end/base_types/closure_id.cmi +middle_end/int_replace_polymorphic_compare.cmo : \ + middle_end/int_replace_polymorphic_compare.cmi +middle_end/int_replace_polymorphic_compare.cmx : \ + middle_end/int_replace_polymorphic_compare.cmi +middle_end/int_replace_polymorphic_compare.cmi : +middle_end/internal_variable_names.cmo : \ + parsing/location.cmi \ + bytecomp/lambda.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/internal_variable_names.cmi +middle_end/internal_variable_names.cmx : \ + parsing/location.cmx \ + bytecomp/lambda.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/internal_variable_names.cmi +middle_end/internal_variable_names.cmi : \ + parsing/location.cmi \ bytecomp/lambda.cmi -middle_end/invariant_params.cmo : middle_end/base_types/variable.cmi \ - middle_end/base_types/symbol.cmi middle_end/parameter.cmi \ - middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \ - middle_end/flambda.cmi middle_end/base_types/closure_id.cmi \ - utils/clflags.cmi middle_end/backend_intf.cmi \ +middle_end/invariant_params.cmo : \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/symbol.cmi \ + middle_end/parameter.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi \ + middle_end/backend_intf.cmi \ middle_end/invariant_params.cmi -middle_end/invariant_params.cmx : middle_end/base_types/variable.cmx \ - middle_end/base_types/symbol.cmx middle_end/parameter.cmx \ - middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \ - middle_end/flambda.cmx middle_end/base_types/closure_id.cmx \ - utils/clflags.cmx middle_end/backend_intf.cmi \ +middle_end/invariant_params.cmx : \ + middle_end/base_types/variable.cmx \ + middle_end/base_types/symbol.cmx \ + middle_end/parameter.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx \ + middle_end/backend_intf.cmi \ middle_end/invariant_params.cmi -middle_end/invariant_params.cmi : middle_end/base_types/variable.cmi \ - middle_end/flambda.cmi middle_end/backend_intf.cmi -middle_end/lift_code.cmo : middle_end/base_types/variable.cmi \ - utils/strongly_connected_components.cmi middle_end/flambda_iterators.cmi \ - middle_end/flambda.cmi middle_end/base_types/compilation_unit.cmi \ +middle_end/invariant_params.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/flambda.cmi \ + middle_end/backend_intf.cmi +middle_end/lift_code.cmo : \ + middle_end/base_types/variable.cmi \ + utils/strongly_connected_components.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + middle_end/base_types/compilation_unit.cmi \ middle_end/lift_code.cmi -middle_end/lift_code.cmx : middle_end/base_types/variable.cmx \ - utils/strongly_connected_components.cmx middle_end/flambda_iterators.cmx \ - middle_end/flambda.cmx middle_end/base_types/compilation_unit.cmx \ +middle_end/lift_code.cmx : \ + middle_end/base_types/variable.cmx \ + utils/strongly_connected_components.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + middle_end/base_types/compilation_unit.cmx \ middle_end/lift_code.cmi -middle_end/lift_code.cmi : middle_end/base_types/variable.cmi \ - middle_end/internal_variable_names.cmi middle_end/flambda.cmi -middle_end/lift_constants.cmo : middle_end/base_types/variable.cmi \ +middle_end/lift_code.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/internal_variable_names.cmi \ + middle_end/flambda.cmi +middle_end/lift_constants.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ utils/strongly_connected_components.cmi \ - middle_end/simple_value_approx.cmi utils/misc.cmi \ - middle_end/internal_variable_names.cmi middle_end/inconstant_idents.cmi \ - middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \ - middle_end/flambda.cmi middle_end/base_types/compilation_unit.cmi \ - middle_end/base_types/closure_id.cmi middle_end/backend_intf.cmi \ - parsing/asttypes.cmi middle_end/allocated_const.cmi \ - middle_end/alias_analysis.cmi middle_end/lift_constants.cmi -middle_end/lift_constants.cmx : middle_end/base_types/variable.cmx \ + middle_end/simple_value_approx.cmi \ + utils/misc.cmi \ + middle_end/internal_variable_names.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inconstant_idents.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/closure_id.cmi \ + middle_end/backend_intf.cmi \ + parsing/asttypes.cmi \ + middle_end/allocated_const.cmi \ + middle_end/alias_analysis.cmi \ + middle_end/lift_constants.cmi +middle_end/lift_constants.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ - middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \ + middle_end/base_types/tag.cmx \ + middle_end/base_types/symbol.cmx \ utils/strongly_connected_components.cmx \ - middle_end/simple_value_approx.cmx utils/misc.cmx \ - middle_end/internal_variable_names.cmx middle_end/inconstant_idents.cmx \ - middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \ - middle_end/flambda.cmx middle_end/base_types/compilation_unit.cmx \ - middle_end/base_types/closure_id.cmx middle_end/backend_intf.cmi \ - parsing/asttypes.cmi middle_end/allocated_const.cmx \ - middle_end/alias_analysis.cmx middle_end/lift_constants.cmi -middle_end/lift_constants.cmi : middle_end/flambda.cmi \ + middle_end/simple_value_approx.cmx \ + utils/misc.cmx \ + middle_end/internal_variable_names.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inconstant_idents.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/closure_id.cmx \ + middle_end/backend_intf.cmi \ + parsing/asttypes.cmi \ + middle_end/allocated_const.cmx \ + middle_end/alias_analysis.cmx \ + middle_end/lift_constants.cmi +middle_end/lift_constants.cmi : \ + middle_end/flambda.cmi \ middle_end/backend_intf.cmi middle_end/lift_let_to_initialize_symbol.cmo : \ - middle_end/base_types/variable.cmi middle_end/base_types/tag.cmi \ - middle_end/base_types/symbol.cmi middle_end/internal_variable_names.cmi \ - middle_end/flambda_utils.cmi middle_end/flambda.cmi \ - middle_end/debuginfo.cmi parsing/asttypes.cmi \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ + middle_end/internal_variable_names.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi \ + middle_end/debuginfo.cmi \ + parsing/asttypes.cmi \ middle_end/lift_let_to_initialize_symbol.cmi middle_end/lift_let_to_initialize_symbol.cmx : \ - middle_end/base_types/variable.cmx middle_end/base_types/tag.cmx \ - middle_end/base_types/symbol.cmx middle_end/internal_variable_names.cmx \ - middle_end/flambda_utils.cmx middle_end/flambda.cmx \ - middle_end/debuginfo.cmx parsing/asttypes.cmi \ + middle_end/base_types/variable.cmx \ + middle_end/base_types/tag.cmx \ + middle_end/base_types/symbol.cmx \ + middle_end/internal_variable_names.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx \ + middle_end/debuginfo.cmx \ + parsing/asttypes.cmi \ middle_end/lift_let_to_initialize_symbol.cmi -middle_end/lift_let_to_initialize_symbol.cmi : middle_end/flambda.cmi \ +middle_end/lift_let_to_initialize_symbol.cmi : \ + middle_end/flambda.cmi \ middle_end/backend_intf.cmi -middle_end/middle_end.cmo : utils/warnings.cmi \ - middle_end/base_types/variable.cmi middle_end/base_types/symbol.cmi \ +middle_end/middle_end.cmo : \ + utils/warnings.cmi \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/symbol.cmi \ middle_end/share_constants.cmi \ middle_end/remove_unused_program_constructs.cmi \ - middle_end/remove_unused_closure_vars.cmi middle_end/ref_to_variables.cmi \ - utils/profile.cmi utils/misc.cmi parsing/location.cmi \ + middle_end/remove_unused_closure_vars.cmi \ + middle_end/ref_to_variables.cmi \ + utils/profile.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ middle_end/lift_let_to_initialize_symbol.cmi \ - middle_end/lift_constants.cmi middle_end/lift_code.cmi \ - middle_end/inlining_cost.cmi middle_end/inline_and_simplify.cmi \ + middle_end/lift_constants.cmi \ + middle_end/lift_code.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/inline_and_simplify.cmi \ middle_end/initialize_symbol_to_let_symbol.cmi \ - middle_end/flambda_iterators.cmi middle_end/flambda_invariants.cmi \ - middle_end/flambda.cmi middle_end/debuginfo.cmi \ - middle_end/base_types/closure_id.cmi middle_end/closure_conversion.cmi \ - utils/clflags.cmi middle_end/backend_intf.cmi middle_end/middle_end.cmi -middle_end/middle_end.cmx : utils/warnings.cmx \ - middle_end/base_types/variable.cmx middle_end/base_types/symbol.cmx \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda_invariants.cmi \ + middle_end/flambda.cmi \ + middle_end/debuginfo.cmi \ + middle_end/base_types/closure_id.cmi \ + middle_end/closure_conversion.cmi \ + utils/clflags.cmi \ + middle_end/backend_intf.cmi \ + middle_end/middle_end.cmi +middle_end/middle_end.cmx : \ + utils/warnings.cmx \ + middle_end/base_types/variable.cmx \ + middle_end/base_types/symbol.cmx \ middle_end/share_constants.cmx \ middle_end/remove_unused_program_constructs.cmx \ - middle_end/remove_unused_closure_vars.cmx middle_end/ref_to_variables.cmx \ - utils/profile.cmx utils/misc.cmx parsing/location.cmx \ + middle_end/remove_unused_closure_vars.cmx \ + middle_end/ref_to_variables.cmx \ + utils/profile.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ middle_end/lift_let_to_initialize_symbol.cmx \ - middle_end/lift_constants.cmx middle_end/lift_code.cmx \ - middle_end/inlining_cost.cmx middle_end/inline_and_simplify.cmx \ + middle_end/lift_constants.cmx \ + middle_end/lift_code.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inlining_cost.cmx \ + middle_end/inline_and_simplify.cmx \ middle_end/initialize_symbol_to_let_symbol.cmx \ - middle_end/flambda_iterators.cmx middle_end/flambda_invariants.cmx \ - middle_end/flambda.cmx middle_end/debuginfo.cmx \ - middle_end/base_types/closure_id.cmx middle_end/closure_conversion.cmx \ - utils/clflags.cmx middle_end/backend_intf.cmi middle_end/middle_end.cmi -middle_end/middle_end.cmi : bytecomp/lambda.cmi typing/ident.cmi \ - middle_end/flambda.cmi middle_end/backend_intf.cmi -middle_end/parameter.cmo : middle_end/base_types/variable.cmi \ - utils/identifiable.cmi middle_end/parameter.cmi -middle_end/parameter.cmx : middle_end/base_types/variable.cmx \ - utils/identifiable.cmx middle_end/parameter.cmi -middle_end/parameter.cmi : middle_end/base_types/variable.cmi \ - utils/identifiable.cmi middle_end/base_types/compilation_unit.cmi -middle_end/pass_wrapper.cmo : utils/clflags.cmi middle_end/pass_wrapper.cmi -middle_end/pass_wrapper.cmx : utils/clflags.cmx middle_end/pass_wrapper.cmi + middle_end/flambda_iterators.cmx \ + middle_end/flambda_invariants.cmx \ + middle_end/flambda.cmx \ + middle_end/debuginfo.cmx \ + middle_end/base_types/closure_id.cmx \ + middle_end/closure_conversion.cmx \ + utils/clflags.cmx \ + middle_end/backend_intf.cmi \ + middle_end/middle_end.cmi +middle_end/middle_end.cmi : \ + bytecomp/lambda.cmi \ + typing/ident.cmi \ + middle_end/flambda.cmi \ + middle_end/backend_intf.cmi +middle_end/parameter.cmo : \ + middle_end/base_types/variable.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + utils/identifiable.cmi \ + middle_end/parameter.cmi +middle_end/parameter.cmx : \ + middle_end/base_types/variable.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + utils/identifiable.cmx \ + middle_end/parameter.cmi +middle_end/parameter.cmi : \ + middle_end/base_types/variable.cmi \ + utils/identifiable.cmi \ + middle_end/base_types/compilation_unit.cmi +middle_end/pass_wrapper.cmo : \ + middle_end/int_replace_polymorphic_compare.cmi \ + utils/clflags.cmi \ + middle_end/pass_wrapper.cmi +middle_end/pass_wrapper.cmx : \ + middle_end/int_replace_polymorphic_compare.cmx \ + utils/clflags.cmx \ + middle_end/pass_wrapper.cmi middle_end/pass_wrapper.cmi : -middle_end/projection.cmo : middle_end/base_types/variable.cmi \ - middle_end/base_types/var_within_closure.cmi utils/identifiable.cmi \ - middle_end/base_types/closure_id.cmi middle_end/projection.cmi -middle_end/projection.cmx : middle_end/base_types/variable.cmx \ - middle_end/base_types/var_within_closure.cmx utils/identifiable.cmx \ - middle_end/base_types/closure_id.cmx middle_end/projection.cmi -middle_end/projection.cmi : middle_end/base_types/variable.cmi \ - middle_end/base_types/var_within_closure.cmi utils/identifiable.cmi \ +middle_end/projection.cmo : \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/var_within_closure.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + utils/identifiable.cmi \ + middle_end/base_types/closure_id.cmi \ + middle_end/projection.cmi +middle_end/projection.cmx : \ + middle_end/base_types/variable.cmx \ + middle_end/base_types/var_within_closure.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + utils/identifiable.cmx \ + middle_end/base_types/closure_id.cmx \ + middle_end/projection.cmi +middle_end/projection.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/var_within_closure.cmi \ + utils/identifiable.cmi \ middle_end/base_types/closure_id.cmi -middle_end/ref_to_variables.cmo : middle_end/base_types/variable.cmi \ - middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ - bytecomp/lambda.cmi middle_end/internal_variable_names.cmi \ - middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ - parsing/asttypes.cmi middle_end/ref_to_variables.cmi -middle_end/ref_to_variables.cmx : middle_end/base_types/variable.cmx \ - middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ - bytecomp/lambda.cmx middle_end/internal_variable_names.cmx \ - middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ - parsing/asttypes.cmi middle_end/ref_to_variables.cmi -middle_end/ref_to_variables.cmi : middle_end/flambda.cmi +middle_end/ref_to_variables.cmo : \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/mutable_variable.cmi \ + utils/misc.cmi \ + bytecomp/lambda.cmi \ + middle_end/internal_variable_names.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + parsing/asttypes.cmi \ + middle_end/ref_to_variables.cmi +middle_end/ref_to_variables.cmx : \ + middle_end/base_types/variable.cmx \ + middle_end/base_types/mutable_variable.cmx \ + utils/misc.cmx \ + bytecomp/lambda.cmx \ + middle_end/internal_variable_names.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + parsing/asttypes.cmi \ + middle_end/ref_to_variables.cmi +middle_end/ref_to_variables.cmi : \ + middle_end/flambda.cmi middle_end/remove_free_vars_equal_to_args.cmo : \ - middle_end/base_types/variable.cmi middle_end/pass_wrapper.cmi \ - middle_end/parameter.cmi middle_end/flambda_utils.cmi \ - middle_end/flambda.cmi middle_end/remove_free_vars_equal_to_args.cmi + middle_end/base_types/variable.cmi \ + middle_end/pass_wrapper.cmi \ + middle_end/parameter.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi \ + middle_end/remove_free_vars_equal_to_args.cmi middle_end/remove_free_vars_equal_to_args.cmx : \ - middle_end/base_types/variable.cmx middle_end/pass_wrapper.cmx \ - middle_end/parameter.cmx middle_end/flambda_utils.cmx \ - middle_end/flambda.cmx middle_end/remove_free_vars_equal_to_args.cmi -middle_end/remove_free_vars_equal_to_args.cmi : middle_end/flambda.cmi -middle_end/remove_unused_arguments.cmo : middle_end/base_types/variable.cmi \ - middle_end/projection.cmi middle_end/parameter.cmi \ - middle_end/invariant_params.cmi middle_end/flambda_utils.cmi \ - middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ + middle_end/base_types/variable.cmx \ + middle_end/pass_wrapper.cmx \ + middle_end/parameter.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx \ + middle_end/remove_free_vars_equal_to_args.cmi +middle_end/remove_free_vars_equal_to_args.cmi : \ + middle_end/flambda.cmi +middle_end/remove_unused_arguments.cmo : \ + middle_end/base_types/variable.cmi \ + middle_end/projection.cmi \ + middle_end/parameter.cmi \ + middle_end/invariant_params.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ middle_end/find_recursive_functions.cmi \ middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/closure_origin.cmi \ - middle_end/base_types/closure_id.cmi utils/clflags.cmi \ + middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi \ middle_end/remove_unused_arguments.cmi -middle_end/remove_unused_arguments.cmx : middle_end/base_types/variable.cmx \ - middle_end/projection.cmx middle_end/parameter.cmx \ - middle_end/invariant_params.cmx middle_end/flambda_utils.cmx \ - middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ +middle_end/remove_unused_arguments.cmx : \ + middle_end/base_types/variable.cmx \ + middle_end/projection.cmx \ + middle_end/parameter.cmx \ + middle_end/invariant_params.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ middle_end/find_recursive_functions.cmx \ middle_end/base_types/compilation_unit.cmx \ middle_end/base_types/closure_origin.cmx \ - middle_end/base_types/closure_id.cmx utils/clflags.cmx \ + middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx \ middle_end/remove_unused_arguments.cmi -middle_end/remove_unused_arguments.cmi : middle_end/flambda.cmi \ +middle_end/remove_unused_arguments.cmi : \ + middle_end/flambda.cmi \ middle_end/backend_intf.cmi middle_end/remove_unused_closure_vars.cmo : \ middle_end/base_types/variable.cmi \ - middle_end/base_types/var_within_closure.cmi middle_end/parameter.cmi \ - middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \ - middle_end/flambda.cmi middle_end/base_types/closure_id.cmi \ + middle_end/base_types/var_within_closure.cmi \ + middle_end/parameter.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + middle_end/base_types/closure_id.cmi \ middle_end/remove_unused_closure_vars.cmi middle_end/remove_unused_closure_vars.cmx : \ middle_end/base_types/variable.cmx \ - middle_end/base_types/var_within_closure.cmx middle_end/parameter.cmx \ - middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \ - middle_end/flambda.cmx middle_end/base_types/closure_id.cmx \ + middle_end/base_types/var_within_closure.cmx \ + middle_end/parameter.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + middle_end/base_types/closure_id.cmx \ middle_end/remove_unused_closure_vars.cmi -middle_end/remove_unused_closure_vars.cmi : middle_end/flambda.cmi +middle_end/remove_unused_closure_vars.cmi : \ + middle_end/flambda.cmi middle_end/remove_unused_program_constructs.cmo : \ - middle_end/base_types/symbol.cmi utils/misc.cmi middle_end/flambda.cmi \ + middle_end/base_types/symbol.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda.cmi \ middle_end/effect_analysis.cmi \ middle_end/remove_unused_program_constructs.cmi middle_end/remove_unused_program_constructs.cmx : \ - middle_end/base_types/symbol.cmx utils/misc.cmx middle_end/flambda.cmx \ + middle_end/base_types/symbol.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda.cmx \ middle_end/effect_analysis.cmx \ middle_end/remove_unused_program_constructs.cmi -middle_end/remove_unused_program_constructs.cmi : middle_end/flambda.cmi -middle_end/share_constants.cmo : middle_end/base_types/symbol.cmi \ - middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ +middle_end/remove_unused_program_constructs.cmi : \ + middle_end/flambda.cmi +middle_end/share_constants.cmo : \ + middle_end/base_types/symbol.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ middle_end/share_constants.cmi -middle_end/share_constants.cmx : middle_end/base_types/symbol.cmx \ - middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ +middle_end/share_constants.cmx : \ + middle_end/base_types/symbol.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ middle_end/share_constants.cmi -middle_end/share_constants.cmi : middle_end/flambda.cmi -middle_end/simple_value_approx.cmo : middle_end/base_types/variable.cmi \ +middle_end/share_constants.cmi : \ + middle_end/flambda.cmi +middle_end/simple_value_approx.cmo : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ middle_end/base_types/set_of_closures_origin.cmi \ - middle_end/base_types/set_of_closures_id.cmi middle_end/parameter.cmi \ - utils/misc.cmi bytecomp/lambda.cmi middle_end/internal_variable_names.cmi \ - middle_end/inlining_cost.cmi middle_end/freshening.cmi \ - middle_end/flambda_utils.cmi middle_end/flambda.cmi \ - middle_end/base_types/export_id.cmi middle_end/effect_analysis.cmi \ - middle_end/debuginfo.cmi middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + middle_end/parameter.cmi \ + utils/misc.cmi \ + bytecomp/lambda.cmi \ + middle_end/internal_variable_names.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/freshening.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi \ + middle_end/base_types/export_id.cmi \ + middle_end/effect_analysis.cmi \ + middle_end/debuginfo.cmi \ + middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/closure_origin.cmi \ - middle_end/base_types/closure_id.cmi middle_end/allocated_const.cmi \ + middle_end/base_types/closure_id.cmi \ + middle_end/allocated_const.cmi \ middle_end/simple_value_approx.cmi -middle_end/simple_value_approx.cmx : middle_end/base_types/variable.cmx \ +middle_end/simple_value_approx.cmx : \ + middle_end/base_types/variable.cmx \ middle_end/base_types/var_within_closure.cmx \ - middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \ + middle_end/base_types/tag.cmx \ + middle_end/base_types/symbol.cmx \ middle_end/base_types/set_of_closures_origin.cmx \ - middle_end/base_types/set_of_closures_id.cmx middle_end/parameter.cmx \ - utils/misc.cmx bytecomp/lambda.cmx middle_end/internal_variable_names.cmx \ - middle_end/inlining_cost.cmx middle_end/freshening.cmx \ - middle_end/flambda_utils.cmx middle_end/flambda.cmx \ - middle_end/base_types/export_id.cmx middle_end/effect_analysis.cmx \ - middle_end/debuginfo.cmx middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/set_of_closures_id.cmx \ + middle_end/parameter.cmx \ + utils/misc.cmx \ + bytecomp/lambda.cmx \ + middle_end/internal_variable_names.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inlining_cost.cmx \ + middle_end/freshening.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx \ + middle_end/base_types/export_id.cmx \ + middle_end/effect_analysis.cmx \ + middle_end/debuginfo.cmx \ + middle_end/base_types/compilation_unit.cmx \ middle_end/base_types/closure_origin.cmx \ - middle_end/base_types/closure_id.cmx middle_end/allocated_const.cmx \ + middle_end/base_types/closure_id.cmx \ + middle_end/allocated_const.cmx \ middle_end/simple_value_approx.cmi -middle_end/simple_value_approx.cmi : middle_end/base_types/variable.cmi \ +middle_end/simple_value_approx.cmi : \ + middle_end/base_types/variable.cmi \ middle_end/base_types/var_within_closure.cmi \ - middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ middle_end/base_types/set_of_closures_origin.cmi \ - middle_end/base_types/set_of_closures_id.cmi middle_end/parameter.cmi \ - bytecomp/lambda.cmi middle_end/freshening.cmi middle_end/flambda.cmi \ - middle_end/base_types/export_id.cmi middle_end/debuginfo.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + middle_end/parameter.cmi \ + bytecomp/lambda.cmi \ + middle_end/freshening.cmi \ + middle_end/flambda.cmi \ + middle_end/base_types/export_id.cmi \ + middle_end/debuginfo.cmi \ middle_end/base_types/closure_origin.cmi \ middle_end/base_types/closure_id.cmi -middle_end/simplify_boxed_integer_ops.cmo : middle_end/simplify_common.cmi \ +middle_end/simplify_boxed_integer_ops.cmo : \ + middle_end/simplify_common.cmi \ middle_end/simplify_boxed_integer_ops_intf.cmi \ - middle_end/simple_value_approx.cmi bytecomp/lambda.cmi \ - middle_end/inlining_cost.cmi middle_end/simplify_boxed_integer_ops.cmi -middle_end/simplify_boxed_integer_ops.cmx : middle_end/simplify_common.cmx \ + middle_end/simple_value_approx.cmi \ + bytecomp/lambda.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/simplify_boxed_integer_ops.cmi +middle_end/simplify_boxed_integer_ops.cmx : \ + middle_end/simplify_common.cmx \ middle_end/simplify_boxed_integer_ops_intf.cmi \ - middle_end/simple_value_approx.cmx bytecomp/lambda.cmx \ - middle_end/inlining_cost.cmx middle_end/simplify_boxed_integer_ops.cmi + middle_end/simple_value_approx.cmx \ + bytecomp/lambda.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inlining_cost.cmx \ + middle_end/simplify_boxed_integer_ops.cmi middle_end/simplify_boxed_integer_ops.cmi : \ middle_end/simplify_boxed_integer_ops_intf.cmi middle_end/simplify_boxed_integer_ops_intf.cmi : \ - middle_end/simple_value_approx.cmi bytecomp/lambda.cmi \ - middle_end/inlining_cost.cmi middle_end/flambda.cmi -middle_end/simplify_common.cmo : middle_end/simple_value_approx.cmi \ - bytecomp/lambda.cmi middle_end/inlining_cost.cmi \ - middle_end/effect_analysis.cmi middle_end/simplify_common.cmi -middle_end/simplify_common.cmx : middle_end/simple_value_approx.cmx \ - bytecomp/lambda.cmx middle_end/inlining_cost.cmx \ - middle_end/effect_analysis.cmx middle_end/simplify_common.cmi -middle_end/simplify_common.cmi : middle_end/simple_value_approx.cmi \ - bytecomp/lambda.cmi middle_end/inlining_cost.cmi middle_end/flambda.cmi -middle_end/simplify_primitives.cmo : middle_end/base_types/tag.cmi \ - middle_end/base_types/symbol.cmi middle_end/simplify_common.cmi \ + middle_end/simple_value_approx.cmi \ + bytecomp/lambda.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/flambda.cmi +middle_end/simplify_common.cmo : \ + middle_end/simple_value_approx.cmi \ + bytecomp/lambda.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/effect_analysis.cmi \ + middle_end/simplify_common.cmi +middle_end/simplify_common.cmx : \ + middle_end/simple_value_approx.cmx \ + bytecomp/lambda.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inlining_cost.cmx \ + middle_end/effect_analysis.cmx \ + middle_end/simplify_common.cmi +middle_end/simplify_common.cmi : \ + middle_end/simple_value_approx.cmi \ + bytecomp/lambda.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/flambda.cmi +middle_end/simplify_primitives.cmo : \ + middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi \ + middle_end/simplify_common.cmi \ middle_end/simplify_boxed_integer_ops.cmi \ - middle_end/simple_value_approx.cmi bytecomp/semantics_of_primitives.cmi \ - utils/misc.cmi bytecomp/lambda.cmi middle_end/inlining_cost.cmi \ - middle_end/flambda.cmi utils/clflags.cmi parsing/asttypes.cmi \ + middle_end/simple_value_approx.cmi \ + bytecomp/semantics_of_primitives.cmi \ + utils/misc.cmi \ + bytecomp/lambda.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/flambda.cmi \ + utils/clflags.cmi \ + parsing/asttypes.cmi \ middle_end/simplify_primitives.cmi -middle_end/simplify_primitives.cmx : middle_end/base_types/tag.cmx \ - middle_end/base_types/symbol.cmx middle_end/simplify_common.cmx \ +middle_end/simplify_primitives.cmx : \ + middle_end/base_types/tag.cmx \ + middle_end/base_types/symbol.cmx \ + middle_end/simplify_common.cmx \ middle_end/simplify_boxed_integer_ops.cmx \ - middle_end/simple_value_approx.cmx bytecomp/semantics_of_primitives.cmx \ - utils/misc.cmx bytecomp/lambda.cmx middle_end/inlining_cost.cmx \ - middle_end/flambda.cmx utils/clflags.cmx parsing/asttypes.cmi \ + middle_end/simple_value_approx.cmx \ + bytecomp/semantics_of_primitives.cmx \ + utils/misc.cmx \ + bytecomp/lambda.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inlining_cost.cmx \ + middle_end/flambda.cmx \ + utils/clflags.cmx \ + parsing/asttypes.cmi \ middle_end/simplify_primitives.cmi -middle_end/simplify_primitives.cmi : middle_end/base_types/variable.cmi \ - middle_end/simple_value_approx.cmi bytecomp/lambda.cmi \ - middle_end/inlining_cost.cmi middle_end/flambda.cmi \ +middle_end/simplify_primitives.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/simple_value_approx.cmi \ + bytecomp/lambda.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/flambda.cmi \ middle_end/debuginfo.cmi -middle_end/unbox_closures.cmo : middle_end/base_types/variable.cmi \ - middle_end/inlining_cost.cmi middle_end/inline_and_simplify_aux.cmi \ - middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \ - middle_end/flambda.cmi middle_end/base_types/closure_id.cmi \ - utils/clflags.cmi middle_end/augment_specialised_args.cmi \ +middle_end/unbox_closures.cmo : \ + middle_end/base_types/variable.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi \ + middle_end/augment_specialised_args.cmi \ middle_end/unbox_closures.cmi -middle_end/unbox_closures.cmx : middle_end/base_types/variable.cmx \ - middle_end/inlining_cost.cmx middle_end/inline_and_simplify_aux.cmx \ - middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \ - middle_end/flambda.cmx middle_end/base_types/closure_id.cmx \ - utils/clflags.cmx middle_end/augment_specialised_args.cmx \ +middle_end/unbox_closures.cmx : \ + middle_end/base_types/variable.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inlining_cost.cmx \ + middle_end/inline_and_simplify_aux.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx \ + middle_end/augment_specialised_args.cmx \ middle_end/unbox_closures.cmi -middle_end/unbox_closures.cmi : middle_end/base_types/variable.cmi \ - middle_end/inlining_cost.cmi middle_end/inline_and_simplify_aux.cmi \ +middle_end/unbox_closures.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/inline_and_simplify_aux.cmi \ middle_end/flambda.cmi middle_end/unbox_free_vars_of_closures.cmo : \ - middle_end/base_types/variable.cmi middle_end/projection.cmi \ - middle_end/pass_wrapper.cmi utils/misc.cmi \ - middle_end/internal_variable_names.cmi middle_end/inlining_cost.cmi \ - middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \ - middle_end/flambda.cmi middle_end/extract_projections.cmi \ - utils/clflags.cmi middle_end/unbox_free_vars_of_closures.cmi + middle_end/base_types/variable.cmi \ + middle_end/projection.cmi \ + middle_end/pass_wrapper.cmi \ + utils/misc.cmi \ + middle_end/internal_variable_names.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda_utils.cmi \ + middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi \ + middle_end/extract_projections.cmi \ + utils/clflags.cmi \ + middle_end/unbox_free_vars_of_closures.cmi middle_end/unbox_free_vars_of_closures.cmx : \ - middle_end/base_types/variable.cmx middle_end/projection.cmx \ - middle_end/pass_wrapper.cmx utils/misc.cmx \ - middle_end/internal_variable_names.cmx middle_end/inlining_cost.cmx \ - middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \ - middle_end/flambda.cmx middle_end/extract_projections.cmx \ - utils/clflags.cmx middle_end/unbox_free_vars_of_closures.cmi -middle_end/unbox_free_vars_of_closures.cmi : middle_end/inlining_cost.cmi \ - middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi -middle_end/unbox_specialised_args.cmo : middle_end/base_types/variable.cmi \ - middle_end/projection.cmi middle_end/invariant_params.cmi \ - middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi \ - middle_end/extract_projections.cmi utils/clflags.cmi \ + middle_end/base_types/variable.cmx \ + middle_end/projection.cmx \ + middle_end/pass_wrapper.cmx \ + utils/misc.cmx \ + middle_end/internal_variable_names.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inlining_cost.cmx \ + middle_end/inline_and_simplify_aux.cmx \ + middle_end/flambda_utils.cmx \ + middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx \ + middle_end/extract_projections.cmx \ + utils/clflags.cmx \ + middle_end/unbox_free_vars_of_closures.cmi +middle_end/unbox_free_vars_of_closures.cmi : \ + middle_end/inlining_cost.cmi \ + middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda.cmi +middle_end/unbox_specialised_args.cmo : \ + middle_end/base_types/variable.cmi \ + middle_end/projection.cmi \ + middle_end/invariant_params.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda.cmi \ + middle_end/extract_projections.cmi \ + utils/clflags.cmi \ middle_end/augment_specialised_args.cmi \ middle_end/unbox_specialised_args.cmi -middle_end/unbox_specialised_args.cmx : middle_end/base_types/variable.cmx \ - middle_end/projection.cmx middle_end/invariant_params.cmx \ - middle_end/inline_and_simplify_aux.cmx middle_end/flambda.cmx \ - middle_end/extract_projections.cmx utils/clflags.cmx \ +middle_end/unbox_specialised_args.cmx : \ + middle_end/base_types/variable.cmx \ + middle_end/projection.cmx \ + middle_end/invariant_params.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/inline_and_simplify_aux.cmx \ + middle_end/flambda.cmx \ + middle_end/extract_projections.cmx \ + utils/clflags.cmx \ middle_end/augment_specialised_args.cmx \ middle_end/unbox_specialised_args.cmi -middle_end/unbox_specialised_args.cmi : middle_end/base_types/variable.cmi \ - middle_end/inlining_cost.cmi middle_end/inline_and_simplify_aux.cmi \ +middle_end/unbox_specialised_args.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/inlining_cost.cmi \ + middle_end/inline_and_simplify_aux.cmi \ middle_end/flambda.cmi middle_end/base_types/closure_element.cmo : \ middle_end/base_types/variable.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ middle_end/base_types/closure_element.cmi middle_end/base_types/closure_element.cmx : \ middle_end/base_types/variable.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ middle_end/base_types/closure_element.cmi middle_end/base_types/closure_element.cmi : \ - middle_end/base_types/variable.cmi utils/identifiable.cmi \ + middle_end/base_types/variable.cmi \ + utils/identifiable.cmi \ middle_end/base_types/compilation_unit.cmi middle_end/base_types/closure_id.cmo : \ + middle_end/int_replace_polymorphic_compare.cmi \ middle_end/base_types/closure_element.cmi \ middle_end/base_types/closure_id.cmi middle_end/base_types/closure_id.cmx : \ + middle_end/int_replace_polymorphic_compare.cmx \ middle_end/base_types/closure_element.cmx \ middle_end/base_types/closure_id.cmi middle_end/base_types/closure_id.cmi : \ middle_end/base_types/closure_element.cmi middle_end/base_types/closure_origin.cmo : \ + middle_end/int_replace_polymorphic_compare.cmi \ middle_end/base_types/closure_id.cmi \ middle_end/base_types/closure_origin.cmi middle_end/base_types/closure_origin.cmx : \ + middle_end/int_replace_polymorphic_compare.cmx \ middle_end/base_types/closure_id.cmx \ middle_end/base_types/closure_origin.cmi -middle_end/base_types/closure_origin.cmi : utils/identifiable.cmi \ +middle_end/base_types/closure_origin.cmi : \ + utils/identifiable.cmi \ middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/closure_id.cmi -middle_end/base_types/compilation_unit.cmo : utils/misc.cmi \ - middle_end/base_types/linkage_name.cmi utils/identifiable.cmi \ - typing/ident.cmi middle_end/base_types/compilation_unit.cmi -middle_end/base_types/compilation_unit.cmx : utils/misc.cmx \ - middle_end/base_types/linkage_name.cmx utils/identifiable.cmx \ - typing/ident.cmx middle_end/base_types/compilation_unit.cmi +middle_end/base_types/compilation_unit.cmo : \ + utils/misc.cmi \ + middle_end/base_types/linkage_name.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + utils/identifiable.cmi \ + typing/ident.cmi \ + middle_end/base_types/compilation_unit.cmi +middle_end/base_types/compilation_unit.cmx : \ + utils/misc.cmx \ + middle_end/base_types/linkage_name.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + utils/identifiable.cmx \ + typing/ident.cmx \ + middle_end/base_types/compilation_unit.cmi middle_end/base_types/compilation_unit.cmi : \ - middle_end/base_types/linkage_name.cmi utils/identifiable.cmi \ + middle_end/base_types/linkage_name.cmi \ + utils/identifiable.cmi \ typing/ident.cmi -middle_end/base_types/export_id.cmo : utils/identifiable.cmi \ +middle_end/base_types/export_id.cmo : \ + middle_end/int_replace_polymorphic_compare.cmi \ + utils/identifiable.cmi \ middle_end/base_types/id_types.cmi \ middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/export_id.cmi -middle_end/base_types/export_id.cmx : utils/identifiable.cmx \ +middle_end/base_types/export_id.cmx : \ + middle_end/int_replace_polymorphic_compare.cmx \ + utils/identifiable.cmx \ middle_end/base_types/id_types.cmx \ middle_end/base_types/compilation_unit.cmx \ middle_end/base_types/export_id.cmi -middle_end/base_types/export_id.cmi : utils/identifiable.cmi \ +middle_end/base_types/export_id.cmi : \ + utils/identifiable.cmi \ middle_end/base_types/compilation_unit.cmi -middle_end/base_types/id_types.cmo : utils/identifiable.cmi \ +middle_end/base_types/id_types.cmo : \ + middle_end/int_replace_polymorphic_compare.cmi \ + utils/identifiable.cmi \ middle_end/base_types/id_types.cmi -middle_end/base_types/id_types.cmx : utils/identifiable.cmx \ +middle_end/base_types/id_types.cmx : \ + middle_end/int_replace_polymorphic_compare.cmx \ + utils/identifiable.cmx \ middle_end/base_types/id_types.cmi -middle_end/base_types/id_types.cmi : utils/identifiable.cmi -middle_end/base_types/linkage_name.cmo : utils/identifiable.cmi \ +middle_end/base_types/id_types.cmi : \ + utils/identifiable.cmi +middle_end/base_types/linkage_name.cmo : \ + middle_end/int_replace_polymorphic_compare.cmi \ + utils/identifiable.cmi \ middle_end/base_types/linkage_name.cmi -middle_end/base_types/linkage_name.cmx : utils/identifiable.cmx \ +middle_end/base_types/linkage_name.cmx : \ + middle_end/int_replace_polymorphic_compare.cmx \ + utils/identifiable.cmx \ middle_end/base_types/linkage_name.cmi -middle_end/base_types/linkage_name.cmi : utils/identifiable.cmi +middle_end/base_types/linkage_name.cmi : \ + utils/identifiable.cmi middle_end/base_types/mutable_variable.cmo : \ middle_end/base_types/variable.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ middle_end/base_types/mutable_variable.cmi middle_end/base_types/mutable_variable.cmx : \ middle_end/base_types/variable.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ middle_end/base_types/mutable_variable.cmi middle_end/base_types/mutable_variable.cmi : \ - middle_end/base_types/variable.cmi middle_end/internal_variable_names.cmi \ - utils/identifiable.cmi typing/ident.cmi \ + middle_end/base_types/variable.cmi \ + middle_end/internal_variable_names.cmi \ + utils/identifiable.cmi \ + typing/ident.cmi \ middle_end/base_types/compilation_unit.cmi -middle_end/base_types/set_of_closures_id.cmo : utils/identifiable.cmi \ +middle_end/base_types/set_of_closures_id.cmo : \ + middle_end/int_replace_polymorphic_compare.cmi \ + utils/identifiable.cmi \ middle_end/base_types/id_types.cmi \ middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/set_of_closures_id.cmi -middle_end/base_types/set_of_closures_id.cmx : utils/identifiable.cmx \ +middle_end/base_types/set_of_closures_id.cmx : \ + middle_end/int_replace_polymorphic_compare.cmx \ + utils/identifiable.cmx \ middle_end/base_types/id_types.cmx \ middle_end/base_types/compilation_unit.cmx \ middle_end/base_types/set_of_closures_id.cmi -middle_end/base_types/set_of_closures_id.cmi : utils/identifiable.cmi \ +middle_end/base_types/set_of_closures_id.cmi : \ + utils/identifiable.cmi \ middle_end/base_types/compilation_unit.cmi middle_end/base_types/set_of_closures_origin.cmo : \ middle_end/base_types/set_of_closures_id.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ middle_end/base_types/set_of_closures_origin.cmi middle_end/base_types/set_of_closures_origin.cmx : \ middle_end/base_types/set_of_closures_id.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ middle_end/base_types/set_of_closures_origin.cmi middle_end/base_types/set_of_closures_origin.cmi : \ - middle_end/base_types/set_of_closures_id.cmi utils/identifiable.cmi \ + middle_end/base_types/set_of_closures_id.cmi \ + utils/identifiable.cmi \ middle_end/base_types/compilation_unit.cmi -middle_end/base_types/static_exception.cmo : utils/numbers.cmi \ - bytecomp/lambda.cmi middle_end/base_types/static_exception.cmi -middle_end/base_types/static_exception.cmx : utils/numbers.cmx \ - bytecomp/lambda.cmx middle_end/base_types/static_exception.cmi -middle_end/base_types/static_exception.cmi : utils/identifiable.cmi -middle_end/base_types/symbol.cmo : middle_end/base_types/variable.cmi \ - utils/misc.cmi middle_end/base_types/linkage_name.cmi \ - utils/identifiable.cmi middle_end/base_types/compilation_unit.cmi \ +middle_end/base_types/static_exception.cmo : \ + utils/numbers.cmi \ + bytecomp/lambda.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + middle_end/base_types/static_exception.cmi +middle_end/base_types/static_exception.cmx : \ + utils/numbers.cmx \ + bytecomp/lambda.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + middle_end/base_types/static_exception.cmi +middle_end/base_types/static_exception.cmi : \ + utils/identifiable.cmi +middle_end/base_types/symbol.cmo : \ + middle_end/base_types/variable.cmi \ + utils/misc.cmi \ + middle_end/base_types/linkage_name.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + utils/identifiable.cmi \ + middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/symbol.cmi -middle_end/base_types/symbol.cmx : middle_end/base_types/variable.cmx \ - utils/misc.cmx middle_end/base_types/linkage_name.cmx \ - utils/identifiable.cmx middle_end/base_types/compilation_unit.cmx \ +middle_end/base_types/symbol.cmx : \ + middle_end/base_types/variable.cmx \ + utils/misc.cmx \ + middle_end/base_types/linkage_name.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + utils/identifiable.cmx \ + middle_end/base_types/compilation_unit.cmx \ middle_end/base_types/symbol.cmi -middle_end/base_types/symbol.cmi : middle_end/base_types/variable.cmi \ - middle_end/base_types/linkage_name.cmi utils/identifiable.cmi \ +middle_end/base_types/symbol.cmi : \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/linkage_name.cmi \ + utils/identifiable.cmi \ middle_end/base_types/compilation_unit.cmi -middle_end/base_types/tag.cmo : utils/numbers.cmi utils/misc.cmi \ - utils/identifiable.cmi middle_end/base_types/tag.cmi -middle_end/base_types/tag.cmx : utils/numbers.cmx utils/misc.cmx \ - utils/identifiable.cmx middle_end/base_types/tag.cmi -middle_end/base_types/tag.cmi : utils/identifiable.cmi +middle_end/base_types/tag.cmo : \ + utils/numbers.cmi \ + utils/misc.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + utils/identifiable.cmi \ + middle_end/base_types/tag.cmi +middle_end/base_types/tag.cmx : \ + utils/numbers.cmx \ + utils/misc.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + utils/identifiable.cmx \ + middle_end/base_types/tag.cmi +middle_end/base_types/tag.cmi : \ + utils/identifiable.cmi middle_end/base_types/var_within_closure.cmo : \ + middle_end/int_replace_polymorphic_compare.cmi \ middle_end/base_types/closure_element.cmi \ middle_end/base_types/var_within_closure.cmi middle_end/base_types/var_within_closure.cmx : \ + middle_end/int_replace_polymorphic_compare.cmx \ middle_end/base_types/closure_element.cmx \ middle_end/base_types/var_within_closure.cmi middle_end/base_types/var_within_closure.cmi : \ middle_end/base_types/closure_element.cmi -middle_end/base_types/variable.cmo : utils/misc.cmi \ - middle_end/internal_variable_names.cmi utils/identifiable.cmi \ - typing/ident.cmi middle_end/base_types/compilation_unit.cmi \ +middle_end/base_types/variable.cmo : \ + utils/misc.cmi \ + middle_end/internal_variable_names.cmi \ + middle_end/int_replace_polymorphic_compare.cmi \ + utils/identifiable.cmi \ + typing/ident.cmi \ + middle_end/base_types/compilation_unit.cmi \ middle_end/base_types/variable.cmi -middle_end/base_types/variable.cmx : utils/misc.cmx \ - middle_end/internal_variable_names.cmx utils/identifiable.cmx \ - typing/ident.cmx middle_end/base_types/compilation_unit.cmx \ +middle_end/base_types/variable.cmx : \ + utils/misc.cmx \ + middle_end/internal_variable_names.cmx \ + middle_end/int_replace_polymorphic_compare.cmx \ + utils/identifiable.cmx \ + typing/ident.cmx \ + middle_end/base_types/compilation_unit.cmx \ middle_end/base_types/variable.cmi -middle_end/base_types/variable.cmi : middle_end/internal_variable_names.cmi \ - utils/identifiable.cmi typing/ident.cmi \ +middle_end/base_types/variable.cmi : \ + middle_end/internal_variable_names.cmi \ + utils/identifiable.cmi \ + typing/ident.cmi \ middle_end/base_types/compilation_unit.cmi -asmcomp/debug/available_regs.cmo : asmcomp/debug/reg_with_debug_info.cmi \ - asmcomp/debug/reg_availability_set.cmi asmcomp/reg.cmi asmcomp/proc.cmi \ - asmcomp/printmach.cmi utils/misc.cmi asmcomp/mach.cmi typing/ident.cmi \ - utils/clflags.cmi asmcomp/debug/available_regs.cmi -asmcomp/debug/available_regs.cmx : asmcomp/debug/reg_with_debug_info.cmx \ - asmcomp/debug/reg_availability_set.cmx asmcomp/reg.cmx asmcomp/proc.cmx \ - asmcomp/printmach.cmx utils/misc.cmx asmcomp/mach.cmx typing/ident.cmx \ - utils/clflags.cmx asmcomp/debug/available_regs.cmi -asmcomp/debug/available_regs.cmi : asmcomp/mach.cmi +asmcomp/debug/available_regs.cmo : \ + asmcomp/debug/reg_with_debug_info.cmi \ + asmcomp/debug/reg_availability_set.cmi \ + asmcomp/reg.cmi \ + asmcomp/proc.cmi \ + asmcomp/printmach.cmi \ + utils/misc.cmi \ + asmcomp/mach.cmi \ + utils/clflags.cmi \ + asmcomp/backend_var.cmi \ + asmcomp/debug/available_regs.cmi +asmcomp/debug/available_regs.cmx : \ + asmcomp/debug/reg_with_debug_info.cmx \ + asmcomp/debug/reg_availability_set.cmx \ + asmcomp/reg.cmx \ + asmcomp/proc.cmx \ + asmcomp/printmach.cmx \ + utils/misc.cmx \ + asmcomp/mach.cmx \ + utils/clflags.cmx \ + asmcomp/backend_var.cmx \ + asmcomp/debug/available_regs.cmi +asmcomp/debug/available_regs.cmi : \ + asmcomp/mach.cmi asmcomp/debug/reg_availability_set.cmo : \ - asmcomp/debug/reg_with_debug_info.cmi typing/ident.cmi \ + asmcomp/debug/reg_with_debug_info.cmi \ + asmcomp/backend_var.cmi \ asmcomp/debug/reg_availability_set.cmi asmcomp/debug/reg_availability_set.cmx : \ - asmcomp/debug/reg_with_debug_info.cmx typing/ident.cmx \ + asmcomp/debug/reg_with_debug_info.cmx \ + asmcomp/backend_var.cmx \ asmcomp/debug/reg_availability_set.cmi asmcomp/debug/reg_availability_set.cmi : \ - asmcomp/debug/reg_with_debug_info.cmi asmcomp/reg.cmi -asmcomp/debug/reg_with_debug_info.cmo : asmcomp/reg.cmi typing/ident.cmi \ + asmcomp/debug/reg_with_debug_info.cmi \ + asmcomp/reg.cmi +asmcomp/debug/reg_with_debug_info.cmo : \ + asmcomp/reg.cmi \ + asmcomp/backend_var.cmi \ asmcomp/debug/reg_with_debug_info.cmi -asmcomp/debug/reg_with_debug_info.cmx : asmcomp/reg.cmx typing/ident.cmx \ +asmcomp/debug/reg_with_debug_info.cmx : \ + asmcomp/reg.cmx \ + asmcomp/backend_var.cmx \ asmcomp/debug/reg_with_debug_info.cmi -asmcomp/debug/reg_with_debug_info.cmi : asmcomp/reg.cmi typing/ident.cmi +asmcomp/debug/reg_with_debug_info.cmi : \ + asmcomp/reg.cmi \ + asmcomp/backend_var.cmi driver/compdynlink.cmi : -driver/compenv.cmo : utils/warnings.cmi utils/profile.cmi utils/misc.cmi \ - parsing/location.cmi utils/config.cmi utils/clflags.cmi utils/ccomp.cmi \ +driver/compdynlink_common.cmo : \ + driver/compdynlink_types.cmi \ + driver/compdynlink_platform_intf.cmi \ + driver/compdynlink_common.cmi +driver/compdynlink_common.cmx : \ + driver/compdynlink_types.cmx \ + driver/compdynlink_platform_intf.cmx \ + driver/compdynlink_common.cmi +driver/compdynlink_common.cmi : \ + driver/compdynlink_platform_intf.cmi +driver/compdynlink_platform_intf.cmo : \ + driver/compdynlink_types.cmi \ + driver/compdynlink_platform_intf.cmi +driver/compdynlink_platform_intf.cmx : \ + driver/compdynlink_types.cmx \ + driver/compdynlink_platform_intf.cmi +driver/compdynlink_platform_intf.cmi : \ + driver/compdynlink_types.cmi +driver/compdynlink_types.cmo : \ + driver/compdynlink_types.cmi +driver/compdynlink_types.cmx : \ + driver/compdynlink_types.cmi +driver/compdynlink_types.cmi : +driver/compenv.cmo : \ + utils/warnings.cmi \ + utils/profile.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + utils/config.cmi \ + utils/clflags.cmi \ + utils/ccomp.cmi \ driver/compenv.cmi -driver/compenv.cmx : utils/warnings.cmx utils/profile.cmx utils/misc.cmx \ - parsing/location.cmx utils/config.cmx utils/clflags.cmx utils/ccomp.cmx \ +driver/compenv.cmx : \ + utils/warnings.cmx \ + utils/profile.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + utils/config.cmx \ + utils/clflags.cmx \ + utils/ccomp.cmx \ driver/compenv.cmi driver/compenv.cmi : -driver/compile.cmo : utils/warnings.cmi typing/typemod.cmi \ - typing/typedtree.cmi typing/typecore.cmi bytecomp/translmod.cmi \ - typing/stypes.cmi bytecomp/simplif.cmi utils/profile.cmi \ - typing/printtyped.cmi typing/printtyp.cmi bytecomp/printlambda.cmi \ - bytecomp/printinstr.cmi parsing/printast.cmi parsing/pprintast.cmi \ - driver/pparse.cmi utils/misc.cmi bytecomp/lambda.cmi \ - typing/includemod.cmi typing/env.cmi bytecomp/emitcode.cmi \ - driver/compmisc.cmi driver/compenv.cmi utils/clflags.cmi \ - bytecomp/bytegen.cmi parsing/builtin_attributes.cmi driver/compile.cmi -driver/compile.cmx : utils/warnings.cmx typing/typemod.cmx \ - typing/typedtree.cmx typing/typecore.cmx bytecomp/translmod.cmx \ - typing/stypes.cmx bytecomp/simplif.cmx utils/profile.cmx \ - typing/printtyped.cmx typing/printtyp.cmx bytecomp/printlambda.cmx \ - bytecomp/printinstr.cmx parsing/printast.cmx parsing/pprintast.cmx \ - driver/pparse.cmx utils/misc.cmx bytecomp/lambda.cmx \ - typing/includemod.cmx typing/env.cmx bytecomp/emitcode.cmx \ - driver/compmisc.cmx driver/compenv.cmx utils/clflags.cmx \ - bytecomp/bytegen.cmx parsing/builtin_attributes.cmx driver/compile.cmi -driver/compile.cmi : -driver/compmisc.cmo : utils/warnings.cmi typing/typemod.cmi utils/misc.cmi \ - parsing/location.cmi typing/ident.cmi typing/env.cmi utils/config.cmi \ - driver/compenv.cmi utils/clflags.cmi driver/compmisc.cmi -driver/compmisc.cmx : utils/warnings.cmx typing/typemod.cmx utils/misc.cmx \ - parsing/location.cmx typing/ident.cmx typing/env.cmx utils/config.cmx \ - driver/compenv.cmx utils/clflags.cmx driver/compmisc.cmi -driver/compmisc.cmi : typing/env.cmi -driver/compplugin.cmo : utils/misc.cmi parsing/location.cmi utils/config.cmi \ - driver/compmisc.cmi driver/compenv.cmi driver/compdynlink.cmi \ - utils/clflags.cmi driver/compplugin.cmi -driver/compplugin.cmx : utils/misc.cmx parsing/location.cmx utils/config.cmx \ - driver/compmisc.cmx driver/compenv.cmx driver/compdynlink.cmi \ - utils/clflags.cmx driver/compplugin.cmi +driver/compile.cmo : \ + bytecomp/translmod.cmi \ + bytecomp/simplif.cmi \ + utils/profile.cmi \ + bytecomp/printlambda.cmi \ + bytecomp/printinstr.cmi \ + utils/misc.cmi \ + bytecomp/lambda.cmi \ + bytecomp/emitcode.cmi \ + driver/compile_common.cmi \ + utils/clflags.cmi \ + bytecomp/bytegen.cmi \ + driver/compile.cmi +driver/compile.cmx : \ + bytecomp/translmod.cmx \ + bytecomp/simplif.cmx \ + utils/profile.cmx \ + bytecomp/printlambda.cmx \ + bytecomp/printinstr.cmx \ + utils/misc.cmx \ + bytecomp/lambda.cmx \ + bytecomp/emitcode.cmx \ + driver/compile_common.cmx \ + utils/clflags.cmx \ + bytecomp/bytegen.cmx \ + driver/compile.cmi +driver/compile.cmi : \ + typing/typedtree.cmi \ + bytecomp/instruct.cmi \ + typing/ident.cmi \ + driver/compile_common.cmi +driver/compile_common.cmo : \ + utils/warnings.cmi \ + typing/typemod.cmi \ + typing/typedtree.cmi \ + typing/typecore.cmi \ + typing/stypes.cmi \ + utils/profile.cmi \ + typing/printtyped.cmi \ + typing/printtyp.cmi \ + parsing/printast.cmi \ + parsing/pprintast.cmi \ + driver/pparse.cmi \ + utils/misc.cmi \ + typing/includemod.cmi \ + typing/env.cmi \ + utils/config.cmi \ + driver/compmisc.cmi \ + driver/compenv.cmi \ + utils/clflags.cmi \ + parsing/builtin_attributes.cmi \ + driver/compile_common.cmi +driver/compile_common.cmx : \ + utils/warnings.cmx \ + typing/typemod.cmx \ + typing/typedtree.cmx \ + typing/typecore.cmx \ + typing/stypes.cmx \ + utils/profile.cmx \ + typing/printtyped.cmx \ + typing/printtyp.cmx \ + parsing/printast.cmx \ + parsing/pprintast.cmx \ + driver/pparse.cmx \ + utils/misc.cmx \ + typing/includemod.cmx \ + typing/env.cmx \ + utils/config.cmx \ + driver/compmisc.cmx \ + driver/compenv.cmx \ + utils/clflags.cmx \ + parsing/builtin_attributes.cmx \ + driver/compile_common.cmi +driver/compile_common.cmi : \ + typing/typedtree.cmi \ + parsing/parsetree.cmi \ + typing/env.cmi +driver/compmisc.cmo : \ + utils/warnings.cmi \ + typing/typemod.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + utils/config.cmi \ + driver/compenv.cmi \ + utils/clflags.cmi \ + driver/compmisc.cmi +driver/compmisc.cmx : \ + utils/warnings.cmx \ + typing/typemod.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + utils/load_path.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + utils/config.cmx \ + driver/compenv.cmx \ + utils/clflags.cmx \ + driver/compmisc.cmi +driver/compmisc.cmi : \ + typing/env.cmi \ + utils/clflags.cmi +driver/compplugin.cmo : \ + parsing/location.cmi \ + utils/load_path.cmi \ + driver/compmisc.cmi \ + driver/compenv.cmi \ + driver/compdynlink.cmi \ + utils/clflags.cmi \ + driver/compplugin.cmi +driver/compplugin.cmx : \ + parsing/location.cmx \ + utils/load_path.cmx \ + driver/compmisc.cmx \ + driver/compenv.cmx \ + driver/compdynlink.cmi \ + utils/clflags.cmx \ + driver/compplugin.cmi driver/compplugin.cmi : -driver/errors.cmo : parsing/location.cmi driver/errors.cmi -driver/errors.cmx : parsing/location.cmx driver/errors.cmi +driver/errors.cmo : \ + parsing/location.cmi \ + driver/errors.cmi +driver/errors.cmx : \ + parsing/location.cmx \ + driver/errors.cmi driver/errors.cmi : -driver/main.cmo : utils/warnings.cmi utils/profile.cmi utils/misc.cmi \ - driver/makedepend.cmi driver/main_args.cmi parsing/location.cmi \ - utils/config.cmi driver/compplugin.cmi driver/compmisc.cmi \ - driver/compile.cmi driver/compenv.cmi utils/clflags.cmi \ - bytecomp/bytepackager.cmi bytecomp/bytelink.cmi \ - bytecomp/bytelibrarian.cmi driver/main.cmi -driver/main.cmx : utils/warnings.cmx utils/profile.cmx utils/misc.cmx \ - driver/makedepend.cmx driver/main_args.cmx parsing/location.cmx \ - utils/config.cmx driver/compplugin.cmx driver/compmisc.cmx \ - driver/compile.cmx driver/compenv.cmx utils/clflags.cmx \ - bytecomp/bytepackager.cmx bytecomp/bytelink.cmx \ - bytecomp/bytelibrarian.cmx driver/main.cmi +driver/main.cmo : \ + utils/warnings.cmi \ + utils/profile.cmi \ + utils/misc.cmi \ + driver/makedepend.cmi \ + driver/main_args.cmi \ + parsing/location.cmi \ + utils/config.cmi \ + driver/compplugin.cmi \ + driver/compmisc.cmi \ + driver/compile.cmi \ + driver/compenv.cmi \ + utils/clflags.cmi \ + bytecomp/bytepackager.cmi \ + bytecomp/bytelink.cmi \ + bytecomp/bytelibrarian.cmi \ + driver/main.cmi +driver/main.cmx : \ + utils/warnings.cmx \ + utils/profile.cmx \ + utils/misc.cmx \ + driver/makedepend.cmx \ + driver/main_args.cmx \ + parsing/location.cmx \ + utils/config.cmx \ + driver/compplugin.cmx \ + driver/compmisc.cmx \ + driver/compile.cmx \ + driver/compenv.cmx \ + utils/clflags.cmx \ + bytecomp/bytepackager.cmx \ + bytecomp/bytelink.cmx \ + bytecomp/bytelibrarian.cmx \ + driver/main.cmi driver/main.cmi : -driver/main_args.cmo : utils/warnings.cmi utils/profile.cmi utils/config.cmi \ - utils/clflags.cmi driver/main_args.cmi -driver/main_args.cmx : utils/warnings.cmx utils/profile.cmx utils/config.cmx \ - utils/clflags.cmx driver/main_args.cmi +driver/main_args.cmo : \ + utils/warnings.cmi \ + utils/profile.cmi \ + utils/config.cmi \ + utils/clflags.cmi \ + driver/main_args.cmi +driver/main_args.cmx : \ + utils/warnings.cmx \ + utils/profile.cmx \ + utils/config.cmx \ + utils/clflags.cmx \ + driver/main_args.cmi driver/main_args.cmi : -driver/makedepend.cmo : driver/pparse.cmi parsing/parsetree.cmi \ - parsing/parser.cmi parsing/parse.cmi utils/misc.cmi parsing/longident.cmi \ - parsing/location.cmi parsing/lexer.cmi parsing/depend.cmi \ - utils/config.cmi driver/compplugin.cmi driver/compenv.cmi \ - utils/clflags.cmi driver/makedepend.cmi -driver/makedepend.cmx : driver/pparse.cmx parsing/parsetree.cmi \ - parsing/parser.cmx parsing/parse.cmx utils/misc.cmx parsing/longident.cmx \ - parsing/location.cmx parsing/lexer.cmx parsing/depend.cmx \ - utils/config.cmx driver/compplugin.cmx driver/compenv.cmx \ - utils/clflags.cmx driver/makedepend.cmi +driver/makedepend.cmo : \ + driver/pparse.cmi \ + parsing/parsetree.cmi \ + parsing/parser.cmi \ + parsing/parse.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + parsing/lexer.cmi \ + parsing/depend.cmi \ + utils/config.cmi \ + driver/compplugin.cmi \ + driver/compenv.cmi \ + utils/clflags.cmi \ + driver/makedepend.cmi +driver/makedepend.cmx : \ + driver/pparse.cmx \ + parsing/parsetree.cmi \ + parsing/parser.cmx \ + parsing/parse.cmx \ + utils/misc.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + parsing/lexer.cmx \ + parsing/depend.cmx \ + utils/config.cmx \ + driver/compplugin.cmx \ + driver/compenv.cmx \ + utils/clflags.cmx \ + driver/makedepend.cmi driver/makedepend.cmi : -driver/optcompile.cmo : utils/warnings.cmi typing/typemod.cmi \ - typing/typedtree.cmi typing/typecore.cmi bytecomp/translmod.cmi \ - typing/stypes.cmi bytecomp/simplif.cmi utils/profile.cmi \ - typing/printtyped.cmi typing/printtyp.cmi bytecomp/printlambda.cmi \ - parsing/printast.cmi parsing/pprintast.cmi driver/pparse.cmi \ - utils/misc.cmi middle_end/middle_end.cmi bytecomp/lambda.cmi \ - typing/includemod.cmi typing/env.cmi utils/config.cmi driver/compmisc.cmi \ - asmcomp/compilenv.cmi driver/compenv.cmi utils/clflags.cmi \ - parsing/builtin_attributes.cmi asmcomp/asmgen.cmi driver/optcompile.cmi -driver/optcompile.cmx : utils/warnings.cmx typing/typemod.cmx \ - typing/typedtree.cmx typing/typecore.cmx bytecomp/translmod.cmx \ - typing/stypes.cmx bytecomp/simplif.cmx utils/profile.cmx \ - typing/printtyped.cmx typing/printtyp.cmx bytecomp/printlambda.cmx \ - parsing/printast.cmx parsing/pprintast.cmx driver/pparse.cmx \ - utils/misc.cmx middle_end/middle_end.cmx bytecomp/lambda.cmx \ - typing/includemod.cmx typing/env.cmx utils/config.cmx driver/compmisc.cmx \ - asmcomp/compilenv.cmx driver/compenv.cmx utils/clflags.cmx \ - parsing/builtin_attributes.cmx asmcomp/asmgen.cmx driver/optcompile.cmi -driver/optcompile.cmi : middle_end/backend_intf.cmi -driver/opterrors.cmo : parsing/location.cmi driver/opterrors.cmi -driver/opterrors.cmx : parsing/location.cmx driver/opterrors.cmi +driver/optcompile.cmo : \ + bytecomp/translmod.cmi \ + bytecomp/simplif.cmi \ + utils/profile.cmi \ + bytecomp/printlambda.cmi \ + utils/misc.cmi \ + middle_end/middle_end.cmi \ + bytecomp/lambda.cmi \ + utils/config.cmi \ + asmcomp/compilenv.cmi \ + driver/compile_common.cmi \ + utils/clflags.cmi \ + asmcomp/asmgen.cmi \ + driver/optcompile.cmi +driver/optcompile.cmx : \ + bytecomp/translmod.cmx \ + bytecomp/simplif.cmx \ + utils/profile.cmx \ + bytecomp/printlambda.cmx \ + utils/misc.cmx \ + middle_end/middle_end.cmx \ + bytecomp/lambda.cmx \ + utils/config.cmx \ + asmcomp/compilenv.cmx \ + driver/compile_common.cmx \ + utils/clflags.cmx \ + asmcomp/asmgen.cmx \ + driver/optcompile.cmi +driver/optcompile.cmi : \ + typing/typedtree.cmi \ + driver/compile_common.cmi \ + middle_end/backend_intf.cmi +driver/opterrors.cmo : \ + parsing/location.cmi \ + driver/opterrors.cmi +driver/opterrors.cmx : \ + parsing/location.cmx \ + driver/opterrors.cmi driver/opterrors.cmi : -driver/optmain.cmo : utils/warnings.cmi utils/profile.cmi asmcomp/proc.cmi \ - asmcomp/printmach.cmi driver/optcompile.cmi utils/misc.cmi \ - driver/makedepend.cmi driver/main_args.cmi parsing/location.cmi \ - asmcomp/import_approx.cmi utils/config.cmi driver/compplugin.cmi \ - driver/compmisc.cmi asmcomp/compilenv.cmi driver/compenv.cmi \ - utils/clflags.cmi middle_end/backend_intf.cmi asmcomp/asmpackager.cmi \ - asmcomp/asmlink.cmi asmcomp/asmlibrarian.cmi asmcomp/arch.cmo \ +driver/optmain.cmo : \ + utils/warnings.cmi \ + utils/profile.cmi \ + asmcomp/proc.cmi \ + asmcomp/printmach.cmi \ + driver/optcompile.cmi \ + utils/misc.cmi \ + driver/makedepend.cmi \ + driver/main_args.cmi \ + parsing/location.cmi \ + asmcomp/import_approx.cmi \ + utils/config.cmi \ + driver/compplugin.cmi \ + driver/compmisc.cmi \ + asmcomp/compilenv.cmi \ + driver/compenv.cmi \ + utils/clflags.cmi \ + middle_end/backend_intf.cmi \ + asmcomp/asmpackager.cmi \ + asmcomp/asmlink.cmi \ + asmcomp/asmlibrarian.cmi \ + asmcomp/arch.cmo \ driver/optmain.cmi -driver/optmain.cmx : utils/warnings.cmx utils/profile.cmx asmcomp/proc.cmx \ - asmcomp/printmach.cmx driver/optcompile.cmx utils/misc.cmx \ - driver/makedepend.cmx driver/main_args.cmx parsing/location.cmx \ - asmcomp/import_approx.cmx utils/config.cmx driver/compplugin.cmx \ - driver/compmisc.cmx asmcomp/compilenv.cmx driver/compenv.cmx \ - utils/clflags.cmx middle_end/backend_intf.cmi asmcomp/asmpackager.cmx \ - asmcomp/asmlink.cmx asmcomp/asmlibrarian.cmx asmcomp/arch.cmx \ +driver/optmain.cmx : \ + utils/warnings.cmx \ + utils/profile.cmx \ + asmcomp/proc.cmx \ + asmcomp/printmach.cmx \ + driver/optcompile.cmx \ + utils/misc.cmx \ + driver/makedepend.cmx \ + driver/main_args.cmx \ + parsing/location.cmx \ + asmcomp/import_approx.cmx \ + utils/config.cmx \ + driver/compplugin.cmx \ + driver/compmisc.cmx \ + asmcomp/compilenv.cmx \ + driver/compenv.cmx \ + utils/clflags.cmx \ + middle_end/backend_intf.cmi \ + asmcomp/asmpackager.cmx \ + asmcomp/asmlink.cmx \ + asmcomp/asmlibrarian.cmx \ + asmcomp/arch.cmx \ driver/optmain.cmi driver/optmain.cmi : -driver/pparse.cmo : utils/profile.cmi parsing/parsetree.cmi \ - parsing/parse.cmi utils/misc.cmi parsing/location.cmi utils/config.cmi \ - utils/clflags.cmi utils/ccomp.cmi parsing/ast_mapper.cmi \ - parsing/ast_invariants.cmi driver/pparse.cmi -driver/pparse.cmx : utils/profile.cmx parsing/parsetree.cmi \ - parsing/parse.cmx utils/misc.cmx parsing/location.cmx utils/config.cmx \ - utils/clflags.cmx utils/ccomp.cmx parsing/ast_mapper.cmx \ - parsing/ast_invariants.cmx driver/pparse.cmi -driver/pparse.cmi : parsing/parsetree.cmi utils/misc.cmi -toplevel/expunge.cmo : bytecomp/symtable.cmi bytecomp/runtimedef.cmi \ - utils/misc.cmi typing/ident.cmi bytecomp/bytesections.cmi -toplevel/expunge.cmx : bytecomp/symtable.cmx bytecomp/runtimedef.cmx \ - utils/misc.cmx typing/ident.cmx bytecomp/bytesections.cmx -toplevel/genprintval.cmo : typing/types.cmi typing/printtyp.cmi \ - typing/predef.cmi typing/path.cmi typing/outcometree.cmi \ - typing/oprint.cmi utils/misc.cmi parsing/longident.cmi typing/ident.cmi \ - typing/env.cmi typing/datarepr.cmi typing/ctype.cmi typing/btype.cmi \ +driver/pparse.cmo : \ + utils/warnings.cmi \ + utils/profile.cmi \ + parsing/parsetree.cmi \ + parsing/parse.cmi \ + utils/misc.cmi \ + parsing/location.cmi \ + utils/config.cmi \ + utils/clflags.cmi \ + utils/ccomp.cmi \ + parsing/ast_mapper.cmi \ + parsing/ast_invariants.cmi \ + driver/pparse.cmi +driver/pparse.cmx : \ + utils/warnings.cmx \ + utils/profile.cmx \ + parsing/parsetree.cmi \ + parsing/parse.cmx \ + utils/misc.cmx \ + parsing/location.cmx \ + utils/config.cmx \ + utils/clflags.cmx \ + utils/ccomp.cmx \ + parsing/ast_mapper.cmx \ + parsing/ast_invariants.cmx \ + driver/pparse.cmi +driver/pparse.cmi : \ + parsing/parsetree.cmi \ + utils/misc.cmi +toplevel/expunge.cmo : \ + bytecomp/symtable.cmi \ + bytecomp/runtimedef.cmi \ + utils/misc.cmi \ + typing/ident.cmi \ + bytecomp/bytesections.cmi +toplevel/expunge.cmx : \ + bytecomp/symtable.cmx \ + bytecomp/runtimedef.cmx \ + utils/misc.cmx \ + typing/ident.cmx \ + bytecomp/bytesections.cmx +toplevel/genprintval.cmo : \ + typing/types.cmi \ + typing/printtyp.cmi \ + typing/predef.cmi \ + typing/path.cmi \ + typing/outcometree.cmi \ + typing/oprint.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/datarepr.cmi \ + typing/ctype.cmi \ + typing/btype.cmi \ toplevel/genprintval.cmi -toplevel/genprintval.cmx : typing/types.cmx typing/printtyp.cmx \ - typing/predef.cmx typing/path.cmx typing/outcometree.cmi \ - typing/oprint.cmx utils/misc.cmx parsing/longident.cmx typing/ident.cmx \ - typing/env.cmx typing/datarepr.cmx typing/ctype.cmx typing/btype.cmx \ +toplevel/genprintval.cmx : \ + typing/types.cmx \ + typing/printtyp.cmx \ + typing/predef.cmx \ + typing/path.cmx \ + typing/outcometree.cmi \ + typing/oprint.cmx \ + utils/misc.cmx \ + parsing/longident.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + typing/datarepr.cmx \ + typing/ctype.cmx \ + typing/btype.cmx \ toplevel/genprintval.cmi -toplevel/genprintval.cmi : typing/types.cmi typing/path.cmi \ - typing/outcometree.cmi typing/env.cmi -toplevel/opttopdirs.cmo : utils/warnings.cmi typing/types.cmi \ - typing/printtyp.cmi toplevel/opttoploop.cmi utils/misc.cmi \ - parsing/longident.cmi typing/ident.cmi typing/env.cmi typing/ctype.cmi \ - utils/config.cmi driver/compdynlink.cmi utils/clflags.cmi \ - asmcomp/asmlink.cmi toplevel/opttopdirs.cmi -toplevel/opttopdirs.cmx : utils/warnings.cmx typing/types.cmx \ - typing/printtyp.cmx toplevel/opttoploop.cmx utils/misc.cmx \ - parsing/longident.cmx typing/ident.cmx typing/env.cmx typing/ctype.cmx \ - utils/config.cmx driver/compdynlink.cmi utils/clflags.cmx \ - asmcomp/asmlink.cmx toplevel/opttopdirs.cmi -toplevel/opttopdirs.cmi : parsing/longident.cmi -toplevel/opttoploop.cmo : utils/warnings.cmi typing/types.cmi \ - typing/typemod.cmi typing/typedtree.cmi typing/typecore.cmi \ - bytecomp/translmod.cmi bytecomp/simplif.cmi asmcomp/proc.cmi \ - typing/printtyped.cmi typing/printtyp.cmi bytecomp/printlambda.cmi \ - parsing/printast.cmi typing/predef.cmi parsing/pprintast.cmi \ - driver/pparse.cmi typing/path.cmi parsing/parsetree.cmi parsing/parse.cmi \ - typing/outcometree.cmi typing/oprint.cmi utils/misc.cmi \ - middle_end/middle_end.cmi parsing/longident.cmi parsing/location.cmi \ - parsing/lexer.cmi bytecomp/lambda.cmi typing/includemod.cmi \ - asmcomp/import_approx.cmi typing/ident.cmi toplevel/genprintval.cmi \ - typing/env.cmi utils/config.cmi driver/compmisc.cmi asmcomp/compilenv.cmi \ - driver/compdynlink.cmi utils/clflags.cmi typing/btype.cmi \ - middle_end/backend_intf.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \ - asmcomp/asmlink.cmi asmcomp/asmgen.cmi asmcomp/arch.cmo \ +toplevel/genprintval.cmi : \ + typing/types.cmi \ + typing/path.cmi \ + typing/outcometree.cmi \ + typing/env.cmi +toplevel/opttopdirs.cmo : \ + utils/warnings.cmi \ + typing/types.cmi \ + typing/printtyp.cmi \ + toplevel/opttoploop.cmi \ + utils/misc.cmi \ + parsing/longident.cmi \ + utils/load_path.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + typing/ctype.cmi \ + utils/config.cmi \ + driver/compdynlink.cmi \ + utils/clflags.cmi \ + asmcomp/asmlink.cmi \ + toplevel/opttopdirs.cmi +toplevel/opttopdirs.cmx : \ + utils/warnings.cmx \ + typing/types.cmx \ + typing/printtyp.cmx \ + toplevel/opttoploop.cmx \ + utils/misc.cmx \ + parsing/longident.cmx \ + utils/load_path.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + typing/ctype.cmx \ + utils/config.cmx \ + driver/compdynlink.cmi \ + utils/clflags.cmx \ + asmcomp/asmlink.cmx \ + toplevel/opttopdirs.cmi +toplevel/opttopdirs.cmi : \ + parsing/longident.cmi +toplevel/opttoploop.cmo : \ + utils/warnings.cmi \ + typing/types.cmi \ + typing/typemod.cmi \ + typing/typedtree.cmi \ + typing/typecore.cmi \ + bytecomp/translmod.cmi \ + bytecomp/simplif.cmi \ + asmcomp/proc.cmi \ + typing/printtyped.cmi \ + typing/printtyp.cmi \ + bytecomp/printlambda.cmi \ + parsing/printast.cmi \ + typing/predef.cmi \ + parsing/pprintast.cmi \ + driver/pparse.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + parsing/parse.cmi \ + typing/outcometree.cmi \ + typing/oprint.cmi \ + utils/misc.cmi \ + middle_end/middle_end.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + parsing/lexer.cmi \ + bytecomp/lambda.cmi \ + typing/includemod.cmi \ + asmcomp/import_approx.cmi \ + typing/ident.cmi \ + toplevel/genprintval.cmi \ + typing/env.cmi \ + utils/config.cmi \ + driver/compmisc.cmi \ + asmcomp/compilenv.cmi \ + driver/compenv.cmi \ + utils/clflags.cmi \ + typing/btype.cmi \ + middle_end/backend_intf.cmi \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmi \ + asmcomp/asmlink.cmi \ + asmcomp/asmgen.cmi \ + asmcomp/arch.cmo \ toplevel/opttoploop.cmi -toplevel/opttoploop.cmx : utils/warnings.cmx typing/types.cmx \ - typing/typemod.cmx typing/typedtree.cmx typing/typecore.cmx \ - bytecomp/translmod.cmx bytecomp/simplif.cmx asmcomp/proc.cmx \ - typing/printtyped.cmx typing/printtyp.cmx bytecomp/printlambda.cmx \ - parsing/printast.cmx typing/predef.cmx parsing/pprintast.cmx \ - driver/pparse.cmx typing/path.cmx parsing/parsetree.cmi parsing/parse.cmx \ - typing/outcometree.cmi typing/oprint.cmx utils/misc.cmx \ - middle_end/middle_end.cmx parsing/longident.cmx parsing/location.cmx \ - parsing/lexer.cmx bytecomp/lambda.cmx typing/includemod.cmx \ - asmcomp/import_approx.cmx typing/ident.cmx toplevel/genprintval.cmx \ - typing/env.cmx utils/config.cmx driver/compmisc.cmx asmcomp/compilenv.cmx \ - driver/compdynlink.cmi utils/clflags.cmx typing/btype.cmx \ - middle_end/backend_intf.cmi parsing/asttypes.cmi parsing/ast_helper.cmx \ - asmcomp/asmlink.cmx asmcomp/asmgen.cmx asmcomp/arch.cmx \ +toplevel/opttoploop.cmx : \ + utils/warnings.cmx \ + typing/types.cmx \ + typing/typemod.cmx \ + typing/typedtree.cmx \ + typing/typecore.cmx \ + bytecomp/translmod.cmx \ + bytecomp/simplif.cmx \ + asmcomp/proc.cmx \ + typing/printtyped.cmx \ + typing/printtyp.cmx \ + bytecomp/printlambda.cmx \ + parsing/printast.cmx \ + typing/predef.cmx \ + parsing/pprintast.cmx \ + driver/pparse.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + parsing/parse.cmx \ + typing/outcometree.cmi \ + typing/oprint.cmx \ + utils/misc.cmx \ + middle_end/middle_end.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + utils/load_path.cmx \ + parsing/lexer.cmx \ + bytecomp/lambda.cmx \ + typing/includemod.cmx \ + asmcomp/import_approx.cmx \ + typing/ident.cmx \ + toplevel/genprintval.cmx \ + typing/env.cmx \ + utils/config.cmx \ + driver/compmisc.cmx \ + asmcomp/compilenv.cmx \ + driver/compenv.cmx \ + utils/clflags.cmx \ + typing/btype.cmx \ + middle_end/backend_intf.cmi \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmx \ + asmcomp/asmlink.cmx \ + asmcomp/asmgen.cmx \ + asmcomp/arch.cmx \ toplevel/opttoploop.cmi -toplevel/opttoploop.cmi : utils/warnings.cmi typing/types.cmi \ - typing/path.cmi parsing/parsetree.cmi typing/outcometree.cmi \ - parsing/longident.cmi parsing/location.cmi typing/env.cmi -toplevel/opttopmain.cmo : utils/warnings.cmi asmcomp/printmach.cmi \ - toplevel/opttoploop.cmi toplevel/opttopdirs.cmi utils/misc.cmi \ - driver/main_args.cmi parsing/location.cmi utils/config.cmi \ - driver/compmisc.cmi driver/compenv.cmi utils/clflags.cmi \ +toplevel/opttoploop.cmi : \ + utils/warnings.cmi \ + typing/types.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + typing/outcometree.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/env.cmi +toplevel/opttopmain.cmo : \ + utils/warnings.cmi \ + asmcomp/printmach.cmi \ + toplevel/opttoploop.cmi \ + toplevel/opttopdirs.cmi \ + utils/misc.cmi \ + driver/main_args.cmi \ + parsing/location.cmi \ + driver/compmisc.cmi \ + driver/compenv.cmi \ + utils/clflags.cmi \ toplevel/opttopmain.cmi -toplevel/opttopmain.cmx : utils/warnings.cmx asmcomp/printmach.cmx \ - toplevel/opttoploop.cmx toplevel/opttopdirs.cmx utils/misc.cmx \ - driver/main_args.cmx parsing/location.cmx utils/config.cmx \ - driver/compmisc.cmx driver/compenv.cmx utils/clflags.cmx \ +toplevel/opttopmain.cmx : \ + utils/warnings.cmx \ + asmcomp/printmach.cmx \ + toplevel/opttoploop.cmx \ + toplevel/opttopdirs.cmx \ + utils/misc.cmx \ + driver/main_args.cmx \ + parsing/location.cmx \ + driver/compmisc.cmx \ + driver/compenv.cmx \ + utils/clflags.cmx \ toplevel/opttopmain.cmi toplevel/opttopmain.cmi : -toplevel/opttopstart.cmo : toplevel/opttopmain.cmi -toplevel/opttopstart.cmx : toplevel/opttopmain.cmx -toplevel/topdirs.cmo : utils/warnings.cmi typing/typetexp.cmi \ - typing/types.cmi toplevel/trace.cmi toplevel/toploop.cmi \ - bytecomp/symtable.cmi typing/printtyp.cmi typing/predef.cmi \ - typing/path.cmi parsing/parsetree.cmi bytecomp/opcodes.cmo utils/misc.cmi \ - bytecomp/meta.cmi parsing/longident.cmi parsing/location.cmi \ - typing/ident.cmi typing/env.cmi bytecomp/dll.cmi typing/ctype.cmi \ - utils/consistbl.cmi utils/config.cmi bytecomp/cmo_format.cmi \ - utils/clflags.cmi typing/btype.cmi parsing/asttypes.cmi \ +toplevel/opttopstart.cmo : \ + toplevel/opttopmain.cmi +toplevel/opttopstart.cmx : \ + toplevel/opttopmain.cmx +toplevel/topdirs.cmo : \ + utils/warnings.cmi \ + typing/typetexp.cmi \ + typing/types.cmi \ + toplevel/trace.cmi \ + toplevel/toploop.cmi \ + bytecomp/symtable.cmi \ + typing/printtyp.cmi \ + typing/predef.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + bytecomp/opcodes.cmo \ + utils/misc.cmi \ + bytecomp/meta.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + typing/ident.cmi \ + typing/env.cmi \ + bytecomp/dll.cmi \ + typing/ctype.cmi \ + utils/consistbl.cmi \ + utils/config.cmi \ + bytecomp/cmo_format.cmi \ + utils/clflags.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmi \ toplevel/topdirs.cmi -toplevel/topdirs.cmx : utils/warnings.cmx typing/typetexp.cmx \ - typing/types.cmx toplevel/trace.cmx toplevel/toploop.cmx \ - bytecomp/symtable.cmx typing/printtyp.cmx typing/predef.cmx \ - typing/path.cmx parsing/parsetree.cmi bytecomp/opcodes.cmx utils/misc.cmx \ - bytecomp/meta.cmx parsing/longident.cmx parsing/location.cmx \ - typing/ident.cmx typing/env.cmx bytecomp/dll.cmx typing/ctype.cmx \ - utils/consistbl.cmx utils/config.cmx bytecomp/cmo_format.cmi \ - utils/clflags.cmx typing/btype.cmx parsing/asttypes.cmi \ +toplevel/topdirs.cmx : \ + utils/warnings.cmx \ + typing/typetexp.cmx \ + typing/types.cmx \ + toplevel/trace.cmx \ + toplevel/toploop.cmx \ + bytecomp/symtable.cmx \ + typing/printtyp.cmx \ + typing/predef.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + bytecomp/opcodes.cmx \ + utils/misc.cmx \ + bytecomp/meta.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + utils/load_path.cmx \ + typing/ident.cmx \ + typing/env.cmx \ + bytecomp/dll.cmx \ + typing/ctype.cmx \ + utils/consistbl.cmx \ + utils/config.cmx \ + bytecomp/cmo_format.cmi \ + utils/clflags.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmx \ toplevel/topdirs.cmi -toplevel/topdirs.cmi : parsing/longident.cmi -toplevel/toploop.cmo : utils/warnings.cmi typing/typetexp.cmi \ - typing/types.cmi typing/typemod.cmi typing/typedtree.cmi \ - typing/typecore.cmi bytecomp/translmod.cmi bytecomp/symtable.cmi \ - bytecomp/simplif.cmi typing/printtyped.cmi typing/printtyp.cmi \ - bytecomp/printlambda.cmi bytecomp/printinstr.cmi parsing/printast.cmi \ - typing/predef.cmi parsing/pprintast.cmi driver/pparse.cmi typing/path.cmi \ - parsing/parsetree.cmi parsing/parse.cmi typing/outcometree.cmi \ - typing/oprint.cmi utils/misc.cmi bytecomp/meta.cmi parsing/longident.cmi \ - parsing/location.cmi parsing/lexer.cmi typing/includemod.cmi \ - typing/ident.cmi toplevel/genprintval.cmi typing/env.cmi \ - bytecomp/emitcode.cmi bytecomp/dll.cmi utils/consistbl.cmi \ - utils/config.cmi driver/compmisc.cmi driver/compenv.cmi utils/clflags.cmi \ - bytecomp/bytegen.cmi typing/btype.cmi parsing/asttypes.cmi \ - parsing/ast_helper.cmi toplevel/toploop.cmi -toplevel/toploop.cmx : utils/warnings.cmx typing/typetexp.cmx \ - typing/types.cmx typing/typemod.cmx typing/typedtree.cmx \ - typing/typecore.cmx bytecomp/translmod.cmx bytecomp/symtable.cmx \ - bytecomp/simplif.cmx typing/printtyped.cmx typing/printtyp.cmx \ - bytecomp/printlambda.cmx bytecomp/printinstr.cmx parsing/printast.cmx \ - typing/predef.cmx parsing/pprintast.cmx driver/pparse.cmx typing/path.cmx \ - parsing/parsetree.cmi parsing/parse.cmx typing/outcometree.cmi \ - typing/oprint.cmx utils/misc.cmx bytecomp/meta.cmx parsing/longident.cmx \ - parsing/location.cmx parsing/lexer.cmx typing/includemod.cmx \ - typing/ident.cmx toplevel/genprintval.cmx typing/env.cmx \ - bytecomp/emitcode.cmx bytecomp/dll.cmx utils/consistbl.cmx \ - utils/config.cmx driver/compmisc.cmx driver/compenv.cmx utils/clflags.cmx \ - bytecomp/bytegen.cmx typing/btype.cmx parsing/asttypes.cmi \ - parsing/ast_helper.cmx toplevel/toploop.cmi -toplevel/toploop.cmi : utils/warnings.cmi typing/types.cmi typing/path.cmi \ - parsing/parsetree.cmi typing/outcometree.cmi parsing/longident.cmi \ - parsing/location.cmi typing/env.cmi -toplevel/topmain.cmo : utils/warnings.cmi toplevel/toploop.cmi \ - toplevel/topdirs.cmi utils/profile.cmi utils/misc.cmi \ - driver/main_args.cmi parsing/location.cmi utils/config.cmi \ - driver/compmisc.cmi driver/compenv.cmi utils/clflags.cmi \ +toplevel/topdirs.cmi : \ + parsing/longident.cmi +toplevel/toploop.cmo : \ + utils/warnings.cmi \ + typing/typetexp.cmi \ + typing/types.cmi \ + typing/typemod.cmi \ + typing/typedtree.cmi \ + typing/typecore.cmi \ + bytecomp/translmod.cmi \ + bytecomp/symtable.cmi \ + bytecomp/simplif.cmi \ + typing/printtyped.cmi \ + typing/printtyp.cmi \ + bytecomp/printlambda.cmi \ + bytecomp/printinstr.cmi \ + parsing/printast.cmi \ + typing/predef.cmi \ + parsing/pprintast.cmi \ + driver/pparse.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + parsing/parse.cmi \ + typing/outcometree.cmi \ + typing/oprint.cmi \ + utils/misc.cmi \ + bytecomp/meta.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + utils/load_path.cmi \ + parsing/lexer.cmi \ + typing/includemod.cmi \ + typing/ident.cmi \ + toplevel/genprintval.cmi \ + typing/env.cmi \ + bytecomp/emitcode.cmi \ + bytecomp/dll.cmi \ + utils/consistbl.cmi \ + utils/config.cmi \ + driver/compmisc.cmi \ + driver/compenv.cmi \ + utils/clflags.cmi \ + bytecomp/bytegen.cmi \ + typing/btype.cmi \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmi \ + toplevel/toploop.cmi +toplevel/toploop.cmx : \ + utils/warnings.cmx \ + typing/typetexp.cmx \ + typing/types.cmx \ + typing/typemod.cmx \ + typing/typedtree.cmx \ + typing/typecore.cmx \ + bytecomp/translmod.cmx \ + bytecomp/symtable.cmx \ + bytecomp/simplif.cmx \ + typing/printtyped.cmx \ + typing/printtyp.cmx \ + bytecomp/printlambda.cmx \ + bytecomp/printinstr.cmx \ + parsing/printast.cmx \ + typing/predef.cmx \ + parsing/pprintast.cmx \ + driver/pparse.cmx \ + typing/path.cmx \ + parsing/parsetree.cmi \ + parsing/parse.cmx \ + typing/outcometree.cmi \ + typing/oprint.cmx \ + utils/misc.cmx \ + bytecomp/meta.cmx \ + parsing/longident.cmx \ + parsing/location.cmx \ + utils/load_path.cmx \ + parsing/lexer.cmx \ + typing/includemod.cmx \ + typing/ident.cmx \ + toplevel/genprintval.cmx \ + typing/env.cmx \ + bytecomp/emitcode.cmx \ + bytecomp/dll.cmx \ + utils/consistbl.cmx \ + utils/config.cmx \ + driver/compmisc.cmx \ + driver/compenv.cmx \ + utils/clflags.cmx \ + bytecomp/bytegen.cmx \ + typing/btype.cmx \ + parsing/asttypes.cmi \ + parsing/ast_helper.cmx \ + toplevel/toploop.cmi +toplevel/toploop.cmi : \ + utils/warnings.cmi \ + typing/types.cmi \ + typing/path.cmi \ + parsing/parsetree.cmi \ + typing/outcometree.cmi \ + parsing/longident.cmi \ + parsing/location.cmi \ + typing/env.cmi +toplevel/topmain.cmo : \ + utils/warnings.cmi \ + toplevel/toploop.cmi \ + toplevel/topdirs.cmi \ + utils/profile.cmi \ + utils/misc.cmi \ + driver/main_args.cmi \ + parsing/location.cmi \ + driver/compmisc.cmi \ + driver/compenv.cmi \ + utils/clflags.cmi \ toplevel/topmain.cmi -toplevel/topmain.cmx : utils/warnings.cmx toplevel/toploop.cmx \ - toplevel/topdirs.cmx utils/profile.cmx utils/misc.cmx \ - driver/main_args.cmx parsing/location.cmx utils/config.cmx \ - driver/compmisc.cmx driver/compenv.cmx utils/clflags.cmx \ +toplevel/topmain.cmx : \ + utils/warnings.cmx \ + toplevel/toploop.cmx \ + toplevel/topdirs.cmx \ + utils/profile.cmx \ + utils/misc.cmx \ + driver/main_args.cmx \ + parsing/location.cmx \ + driver/compmisc.cmx \ + driver/compenv.cmx \ + utils/clflags.cmx \ toplevel/topmain.cmi toplevel/topmain.cmi : -toplevel/topstart.cmo : toplevel/topmain.cmi -toplevel/topstart.cmx : toplevel/topmain.cmx -toplevel/trace.cmo : typing/types.cmi toplevel/toploop.cmi \ - typing/printtyp.cmi typing/predef.cmi typing/path.cmi utils/misc.cmi \ - bytecomp/meta.cmi parsing/longident.cmi typing/ctype.cmi \ - parsing/asttypes.cmi toplevel/trace.cmi -toplevel/trace.cmx : typing/types.cmx toplevel/toploop.cmx \ - typing/printtyp.cmx typing/predef.cmx typing/path.cmx utils/misc.cmx \ - bytecomp/meta.cmx parsing/longident.cmx typing/ctype.cmx \ - parsing/asttypes.cmi toplevel/trace.cmi -toplevel/trace.cmi : typing/types.cmi typing/path.cmi parsing/longident.cmi \ +toplevel/topstart.cmo : \ + toplevel/topmain.cmi +toplevel/topstart.cmx : \ + toplevel/topmain.cmx +toplevel/trace.cmo : \ + typing/types.cmi \ + toplevel/toploop.cmi \ + typing/printtyp.cmi \ + typing/predef.cmi \ + typing/path.cmi \ + utils/misc.cmi \ + bytecomp/meta.cmi \ + parsing/longident.cmi \ + typing/ctype.cmi \ + parsing/asttypes.cmi \ + toplevel/trace.cmi +toplevel/trace.cmx : \ + typing/types.cmx \ + toplevel/toploop.cmx \ + typing/printtyp.cmx \ + typing/predef.cmx \ + typing/path.cmx \ + utils/misc.cmx \ + bytecomp/meta.cmx \ + parsing/longident.cmx \ + typing/ctype.cmx \ + parsing/asttypes.cmi \ + toplevel/trace.cmi +toplevel/trace.cmi : \ + typing/types.cmi \ + typing/path.cmi \ + parsing/longident.cmi \ typing/env.cmi -driver/compdynlink.cmx : asmcomp/cmx_format.cmi driver/compdynlink.cmi -driver/compdynlink.cmo : bytecomp/symtable.cmi bytecomp/opcodes.cmo \ - utils/misc.cmi bytecomp/meta.cmi bytecomp/dll.cmi utils/consistbl.cmi \ - utils/config.cmi bytecomp/cmo_format.cmi typing/cmi_format.cmi \ +driver/compdynlink.cmx : \ + driver/compdynlink_types.cmx \ + driver/compdynlink_common.cmx \ + asmcomp/cmx_format.cmi \ + driver/compdynlink.cmi +driver/compdynlink.cmo : \ + bytecomp/symtable.cmi \ + bytecomp/opcodes.cmo \ + utils/misc.cmi \ + bytecomp/meta.cmi \ + typing/ident.cmi \ + bytecomp/dll.cmi \ + utils/config.cmi \ + driver/compdynlink_types.cmi \ + driver/compdynlink_common.cmi \ + bytecomp/cmo_format.cmi \ driver/compdynlink.cmi diff --git a/.depend.menhir b/.depend.menhir new file mode 100644 index 00000000..3b9e6e09 --- /dev/null +++ b/.depend.menhir @@ -0,0 +1,11 @@ +parsing/parser.cmo : parsing/syntaxerr.cmi parsing/parsetree.cmi \ + parsing/longident.cmi parsing/location.cmi parsing/docstrings.cmi \ + utils/clflags.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \ + parsing/parser.cmi +parsing/parser.cmx : parsing/syntaxerr.cmx parsing/parsetree.cmi \ + parsing/longident.cmx parsing/location.cmx parsing/docstrings.cmx \ + utils/clflags.cmx parsing/asttypes.cmi parsing/ast_helper.cmx \ + parsing/parser.cmi +parsing/parser.cmi : parsing/parsetree.cmi parsing/location.cmi \ + parsing/docstrings.cmi +parsing/parser.ml parsing/parser.mli: parsing/ast_helper.cmi parsing/asttypes.cmi utils/clflags.cmi parsing/docstrings.cmi parsing/location.cmi parsing/longident.cmi parsing/parsetree.cmi parsing/syntaxerr.cmi diff --git a/.gitattributes b/.gitattributes index 60c928da..ceac151d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -16,8 +16,8 @@ # Default behaviour, for if core.autocrlf isn't set * text=auto -# Don't believe there's a way to wrap lines in .gitattributes -.gitattributes ocaml-typo=long-line +# It is not possible to wrap lines lines in .gitattributes files +.gitattributes typo.long-line=may # Binary files /boot/ocamlc binary @@ -31,81 +31,122 @@ # http://krlmlr.github.io/using-gitattributes-to-avoid-merge-conflicts/ /.mailmap merge=union - # We tried using 'union' for Changes and it did not work: # instead of creating Changes conflict it would silently duplicate # the lines involved in the conflict, which is arguably worse #/Changes merge=union # No header for text files (would be too obtrusive). -*.md ocaml-typo=missing-header -README* ocaml-typo=missing-header -*.adoc ocaml-typo=missing-header,long-line,unused-prop - -/.mailmap ocaml-typo=long-line,missing-header,non-ascii -/.merlin ocaml-typo=missing-header -/Changes ocaml-typo=non-ascii,missing-header -/INSTALL ocaml-typo=missing-header -/LICENSE ocaml-typo=long-line,very-long-line,missing-header +*.md typo.missing-header +README* typo.missing-header +*.adoc typo.missing-header +stdlib/*.mld typo.missing-header + +*.adoc typo.long-line=may + +/.mailmap typo.long-line typo.missing-header typo.non-ascii +/.merlin typo.missing-header +/Changes typo.utf8 typo.missing-header +/News typo.utf8 typo.missing-header +/INSTALL typo.missing-header +/LICENSE typo.very-long-line typo.missing-header # tools/ci/appveyor/appveyor_build.cmd only has missing-header because # dra27 too lazy to update check-typo to interpret Cmd-style comments! -/tools/ci/appveyor/appveyor_build.cmd ocaml-typo=long-line,very-long-line,missing-header text eol=crlf -/tools/ci/appveyor/appveyor_build.sh ocaml-typo=non-ascii +/tools/ci/appveyor/appveyor_build.cmd typo.very-long-line typo.missing-header typo.non-ascii +/tools/ci/appveyor/appveyor_build.sh typo.non-ascii +/tools/ci/inria/remove-sinh-primitive.patch typo.white-at-eol typo.missing-header typo.long-line +/tools/release-checklist typo.missing-header + +# ignore auto-generated .depend files +.depend typo.prune +/.depend.menhir typo.prune + +# Makefiles may contain tabs +Makefile* typo.tab=may +asmcomp/*/emit.mlp typo.tab=may typo.long-line=may -asmcomp/*/emit.mlp ocaml-typo=tab,long-line,unused-prop -asmcomp/power/NOTES.md ocaml-typo=missing-header +# The build-aux directory contains bundled files so do not check it +build-aux typo.prune -asmrun/i386.S ocaml-typo=long-line +/config/gnu typo.prune +/config/gnu/** typo.prune -config/gnu ocaml-typo=prune +/manual typo.prune +/manual/** typo.prune -emacs/*.el ocaml-typo=long-line,unused-prop -emacs/caml.el ocaml-typo=long-line,unused-prop,missing-header -emacs/COPYING ocaml-typo=tab,non-printing,missing-header -emacs/ocamltags.in ocaml-typo=non-printing +# configure is generated so do not check it +configure typo.prune -experimental ocaml-typo=prune +ocaml-variants.opam typo.prune -manual ocaml-typo=prune +emacs/*.el typo.long-line=may +emacs/caml.el typo.long-line=may typo.missing-header +emacs/COPYING typo.prune +emacs/ocamltags.in typo.non-printing -ocamlbuild/* ocaml-typo=long-line -ocamlbuild/AUTHORS ocaml-typo=missing-header -ocamlbuild/ChangeLog ocaml-typo=tab,missing-header -ocamlbuild/TODO ocaml-typo=missing-header +ocamldoc/** typo.long-line=may +ocamldoc/Changes.txt typo.missing-header +ocamldoc/ocamldoc.sty typo.missing-header +ocamldoc/odoc_index.html typo.missing-header -ocamldoc/Changes.txt ocaml-typo=missing-header -ocamldoc/ocamldoc.sty ocaml-typo=missing-header +otherlibs/win32unix/readlink.c typo.long-line +otherlibs/win32unix/stat.c typo.long-line +otherlibs/win32unix/symlink.c typo.long-line -otherlibs/win32unix/readlink.c ocaml-typo=long-line -otherlibs/win32unix/stat.c ocaml-typo=long-line -otherlibs/win32unix/symlink.c ocaml-typo=long-line +runtime/i386.S typo.long-line -stdlib/hashbang ocaml-typo=white-at-eol,missing-lf +stdlib/hashbang typo.white-at-eol typo.missing-lf -testsuite/tests/** ocaml-typo=missing-header -testsuite/tests/lib-unix/win-stat/fakeclock.c ocaml-typo= -testsuite/tests/lib-bigarray-2/bigarrf.f ocaml-typo=missing-header,tab -testsuite/tests/misc-unsafe/almabench.ml ocaml-typo=missing-header,long-line -testsuite/typing ocaml-typo=missing-header +testsuite/tests/** typo.missing-header typo.long-line=may +testsuite/tests/lib-bigarray-2/bigarrf.f typo.tab +testsuite/tests/lib-unix/win-stat/fakeclock.c typo.missing-header=false +testsuite/tests/misc-unsafe/almabench.ml typo.long-line +testsuite/tests/tool-toplevel/strings.ml typo.utf8 +testsuite/tests/win-unicode/*.ml typo.utf8 +testsuite/tools/*.S typo.missing-header +testsuite/tools/*.asm typo.missing-header +testsuite/typing typo.missing-header -tools/magic ocaml-typo=missing-header +# prune testsuite reference files +testsuite/tests/**/*.reference typo.prune -yacc/*.[ch] ocaml-typo=long-line,very-long-line,unused-prop +# Expect tests with overly long lines of expected output +testsuite/tests/parsing/docstrings.ml typo.very-long-line + +tools/magic typo.missing-header + +# TODO we should fix the long-line errors in yacc/*.c +/yacc/*.[ch] typo.very-long-line=may + +menhir-bench.bash typo.missing-header typo.utf8 + +# bootstrap files produced by Menhir +/boot/menhir/** typo.long-line=may typo.very-long-line=may +/boot/menhir/** typo.missing-header=may +/boot/menhir/** typo.white-at-eol=may +/boot/menhir/** typo.utf8=may # Line-ending specifications, for Windows interoperability *.sh text eol=lf *.sh.in text eol=lf *.awk text eol=lf +*.m4 text eol=lf -# Test suite command fragments -*.checker text eol=lf -*.precheck text eol=lf # ocamltest hooks which are used in the testsuite *.check-program-output text eol=lf *.run text eol=lf +/tools/ci/appveyor/appveyor_build.cmd text eol=crlf + configure text eol=lf +configure.ac text eol=lf +autogen text eol=lf +build-aux/compile text eol=lf +build-aux/config.guess text eol=lf +build-aux/config.sub text eol=lf +build-aux/install text eol=lf +build-aux/missing text eol=lf config/auto-aux/hasgot text eol=lf config/auto-aux/hasgot2 text eol=lf config/auto-aux/runtest text eol=lf @@ -119,6 +160,7 @@ ocamldoc/remove_DEBUG text eol=lf ocamltest/getocamloptdefaultflags text eol=lf stdlib/Compflags text eol=lf stdlib/sharpbang text eol=lf +tools/ci/inria/remove-sinh-primitive.patch text eol=lf tools/check-typo text eol=lf tools/ci-build text eol=lf tools/msvs-promote-path text eol=lf @@ -129,6 +171,10 @@ tools/make-package-macosx text eol=lf tools/ocaml-objcopy-macosx text eol=lf tools/ocamlmktop.tpl text eol=lf tools/ocamlsize text eol=lf +tools/pre-commit-githook text eol=lf +tools/markdown-add-pr-links.sh text eol=lf +runtime/caml/m.h.in text eol=lf +runtime/caml/s.h.in text eol=lf # These two are cat scripts, so may not actually require this config/auto-aux/sharpbang text eol=lf @@ -149,8 +195,15 @@ testsuite/tests/basic-more/robustmatch.ml text eol=lf testsuite/tests/parsing/*.ml text eol=lf testsuite/tests/docstrings/empty.ml text eol=lf testsuite/tests/functors/functors.ml text eol=lf +testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_impl.ml text eol=lf +testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_intf.mli text eol=lf +testsuite/tests/tool-ocamlc-stop-after/stop_after_typing_impl.ml text eol=lf +testsuite/tests/tool-toplevel/error_highlighting.ml text eol=lf +testsuite/tests/tool-toplevel/error_highlighting_use4.ml text eol=lf testsuite/tests/translprim/module_coercion.ml text eol=lf testsuite/tests/typing-objects-bugs/pr3968_bad.ml text eol=lf +testsuite/tests/typing-ocamlc-i/pr7402.ml text eol=lf +testsuite/tests/typing-ocamlc-i/pervasives_leitmotiv.ml text eol=lf testsuite/tests/typing-recmod/t12bad.ml text eol=lf testsuite/tests/typing-safe-linking/b_bad.ml text eol=lf testsuite/tests/warnings/w04.ml text eol=lf @@ -160,6 +213,7 @@ testsuite/tests/warnings/w32.ml text eol=lf # These are forced to \n to allow the Cygwin testsuite to pass on a # Windows-checkout testsuite/tests/formatting/margins.ml text eol=lf +testsuite/tests/letrec-check/pr7706.ml text eol=lf testsuite/tests/letrec-disallowed/disallowed.ml text eol=lf testsuite/tests/letrec-disallowed/extension_constructor.ml text eol=lf testsuite/tests/letrec-disallowed/float_block_allowed.ml text eol=lf @@ -190,6 +244,8 @@ testsuite/tests/typing-sigsubst/sigsubst.ml text eol=lf testsuite/tests/typing-typeparam/newtype.ml text eol=lf testsuite/tests/typing-unboxed/test.ml text eol=lf testsuite/tests/typing-unboxed-types/test.ml text eol=lf +testsuite/tests/typing-unboxed-types/test_flat.ml text eol=lf +testsuite/tests/typing-unboxed-types/test_no_flat.ml text eol=lf testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml text eol=lf testsuite/tests/typing-warnings/application.ml text eol=lf testsuite/tests/typing-warnings/coercions.ml text eol=lf diff --git a/.gitignore b/.gitignore index 4b78128f..1f324126 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ *.obj *.lib *.dll +*.la *.cm[ioxat] *.cmx[as] *.cmti @@ -34,16 +35,24 @@ _ocamltest _ocamltestd *.odoc +.merlin +_build # local to root directory +/Makefile.common +/Makefile.config +/autom4te.cache /ocamlc +/config.cache +/config.log +/config.status +/libtool /ocamlc.opt /expunge /ocaml /ocamlopt /ocamlopt.opt -/package-macosx /ocamlnat # specific files and patterns in sub-directories @@ -56,77 +65,12 @@ _ocamltestd /asmcomp/scheduling.ml /asmcomp/CSE.ml -/asmrun/*.p.c -/asmrun/*.d.c -/asmrun/alloc.c -/asmrun/afl.c -/asmrun/array.c -/asmrun/backtrace.c -/asmrun/bigarray.c -/asmrun/callback.c -/asmrun/compact.c -/asmrun/compare.c -/asmrun/custom.c -/asmrun/debugger.c -/asmrun/dynlink.c -/asmrun/extern.c -/asmrun/finalise.c -/asmrun/floats.c -/asmrun/freelist.c -/asmrun/gc_ctrl.c -/asmrun/globroots.c -/asmrun/hash.c -/asmrun/intern.c -/asmrun/ints.c -/asmrun/io.c -/asmrun/lexing.c -/asmrun/main.c -/asmrun/major_gc.c -/asmrun/md5.c -/asmrun/memory.c -/asmrun/meta.c -/asmrun/minor_gc.c -/asmrun/misc.c -/asmrun/obj.c -/asmrun/parsing.c -/asmrun/printexc.c -/asmrun/signals.c -/asmrun/startup_aux.c -/asmrun/str.c -/asmrun/sys.c -/asmrun/terminfo.c -/asmrun/unix.c -/asmrun/weak.c -/asmrun/win32.c - -/boot/Saved /boot/ocamlrun -/boot/ocamlyacc /boot/camlheader /bytecomp/runtimedef.ml /bytecomp/opcodes.ml -/byterun/caml/jumptbl.h -/byterun/caml/m.h -/byterun/caml/s.h -/byterun/primitives -/byterun/prims.c -/byterun/caml/opnames.h -/byterun/caml/version.h -/byterun/ocamlrun -/byterun/ocamlrund -/byterun/ocamlruni -/byterun/ld.conf -/byterun/interp.a.lst -/byterun/*.[sd]obj -/byterun/.gdb_history -/byterun/*.d.c -/byterun/*.pic.c - -/config/Makefile -/config/auto-aux/hashbang4 - /debugger/lexer.ml /debugger/parser.ml /debugger/parser.mli @@ -134,13 +78,16 @@ _ocamltestd /driver/compdynlink.mlopt /driver/compdynlink.mlbyte /driver/compdynlink.mli +/driver/compdynlink_common.ml +/driver/compdynlink_common.mli +/driver/compdynlink_platform_intf.ml +/driver/compdynlink_platform_intf.mli +/driver/compdynlink_types.ml +/driver/compdynlink_types.mli /emacs/ocamltags /emacs/*.elc -/experimental/garrigue/*.out -/experimental/garrigue/*.out2 - /lex/parser.ml /lex/parser.mli /lex/lexer.ml @@ -151,12 +98,6 @@ _ocamltestd /manual/manual/cmds/warnings-help.etex /manual/manual/warnings-help.etex -/ocamlbuild/ocamlbuild_config.ml -/ocamlbuild/lexers.ml -/ocamlbuild/glob_lexer.ml -/ocamlbuild/ocamlbuild.native -/ocamlbuild/ocamlbuild.byte - /ocamldoc/ocamldoc /ocamldoc/ocamldoc.opt /ocamldoc/odoc @@ -170,8 +111,9 @@ _ocamltestd /ocamldoc/odoc_text_parser.ml /ocamldoc/odoc_text_parser.mli /ocamldoc/stdlib_man -/ocamldoc/stdlib_non_prefixed/*.mli /ocamldoc/stdlib_html +/ocamldoc/stdlib_latex +/ocamldoc/stdlib_texi /ocamldoc/*.output /ocamldoc/test_stdlib /ocamldoc/test_latex @@ -185,6 +127,7 @@ _ocamltestd /ocamltest/tsl_parser.mli /otherlibs/dynlink/extract_crc +/otherlibs/dynlink/dynlink_platform_intf.mli /otherlibs/threads/marshal.mli /otherlibs/threads/stdlib.mli /otherlibs/threads/unix.mli @@ -217,6 +160,7 @@ _ocamltestd /otherlibs/win32unix/strofaddr.c /otherlibs/win32unix/time.c /otherlibs/win32unix/unlink.c +/otherlibs/win32unix/fsync.c /parsing/parser.ml /parsing/parser.mli @@ -227,6 +171,25 @@ _ocamltestd /parsing/parser.output /parsing/parser.automaton /parsing/parser.conflicts +/parsing/camlinternalMenhirLib.ml +/parsing/camlinternalMenhirLib.mli + +/runtime/caml/jumptbl.h +/runtime/caml/m.h +/runtime/caml/s.h +/runtime/primitives +/runtime/prims.c +/runtime/caml/opnames.h +/runtime/caml/version.h +/runtime/ocamlrun +/runtime/ocamlrund +/runtime/ocamlruni +/runtime/ld.conf +/runtime/interp.a.lst +/runtime/*.[sd]obj +/runtime/.gdb_history +/runtime/*.d.c +/runtime/*.pic.c /stdlib/camlheader /stdlib/target_camlheader @@ -248,81 +211,12 @@ _ocamltestd /testsuite/_retries -/testsuite/tests/asmgen/codegen -/testsuite/tests/asmgen/parsecmm.ml -/testsuite/tests/asmgen/parsecmm.mli -/testsuite/tests/asmgen/lexcmm.ml -/testsuite/tests/asmgen/*.s -/testsuite/tests/asmgen/*.out.manifest - - -/testsuite/tests/embedded/caml - -/testsuite/tests/lib-dynlink-bytecode/main -/testsuite/tests/lib-dynlink-bytecode/static -/testsuite/tests/lib-dynlink-bytecode/custom -/testsuite/tests/lib-dynlink-bytecode/marshal.data -/testsuite/tests/lib-dynlink-bytecode/caml - -/testsuite/tests/lib-dynlink-native/mypack.pack.s -/testsuite/tests/lib-dynlink-native/mypack.pack.asm -/testsuite/tests/lib-dynlink-native/result -/testsuite/tests/lib-dynlink-native/main -/testsuite/tests/lib-dynlink-native/marshal.data -/testsuite/tests/lib-dynlink-native/caml - -/testsuite/tests/lib-scanf/tscanf_data - -/testsuite/tests/lib-threads/*.byt - -/testsuite/tests/output_obj/*.bc.c -/testsuite/tests/output_obj/*_stub -/testsuite/tests/output_obj/*_stub - -/testsuite/tests/runtime-errors/*.bytecode - -/testsuite/tests/self-contained-toplevel/cached_cmi.ml - -/testsuite/tests/tool-ocamldep-modalias/*.byt* -/testsuite/tests/tool-ocamldep-modalias/*.opt* -/testsuite/tests/tool-ocamldep-modalias/depend.mk -/testsuite/tests/tool-ocamldep-modalias/depend.mk2 -/testsuite/tests/tool-ocamldep-modalias/depend.mod -/testsuite/tests/tool-ocamldep-modalias/depend.mod2 -/testsuite/tests/tool-ocamldep-modalias/depend.mod3 - -/testsuite/tests/tool-ocamldoc/*.html -/testsuite/tests/tool-ocamldoc/*.sty -/testsuite/tests/tool-ocamldoc/*.css - -/testsuite/tests/tool-ocamldoc-2/ocamldoc.sty - -/testsuite/tests/tool-ocamldoc-html/*.html -/testsuite/tests/tool-ocamldoc-html/style.css - -/testsuite/tests/tool-ocamldoc-man/*.3o - -/testsuite/tests/tool-ocamldoc-open/alias.odoc -/testsuite/tests/tool-ocamldoc-open/inner.odoc -/testsuite/tests/tool-ocamldoc-open/main.odoc -/testsuite/tests/tool-ocamldoc-open/ocamldoc.sty - -/testsuite/tests/tool-lexyacc/scanner.ml -/testsuite/tests/tool-lexyacc/grammar.mli -/testsuite/tests/tool-lexyacc/grammar.ml - -/testsuite/tests/typing-unboxed-types/false.flat-float -/testsuite/tests/typing-unboxed-types/true.flat-float -/testsuite/tests/typing-unboxed-types/test.ml.reference - -/testsuite/tests/unboxed-primitive-args/main.ml -/testsuite/tests/unboxed-primitive-args/stubs.c - -/testsuite/tests/unwind/unwind_test - -/testsuite/tests/win-unicode/symlink_tests.precheck +/testsuite/tools/codegen /testsuite/tools/expect_test +/testsuite/tools/lexcmm.ml +/testsuite/tools/parsecmm.ml +/testsuite/tools/parsecmm.mli /tools/ocamldep /tools/ocamldep.opt @@ -366,6 +260,7 @@ _ocamltestd /tools/stripdebug.opt /tools/make_opcodes /tools/make_opcodes.ml +/tools/caml-tex /utils/config.ml diff --git a/.mailmap b/.mailmap index 9635a00a..6959fe22 100644 --- a/.mailmap +++ b/.mailmap @@ -8,9 +8,12 @@ # See the MAPPING AUTHORS section of 'man git-shortlog' for more details. # Such a remapping may be useful in particular for tracking authorship -# of commits erroneously made under an obscure alias or email adress. +# of commits erroneously made under an obscure alias or email address. # (Some Name , pour ne pas le citer) + +### Normalizing information for frequent git commit authors + Alain Frisch alainfrisch @@ -29,6 +32,25 @@ Jérémie Dimino Jeremy Yallop yallop Nicolás Ojeda Bär + +### Approved Approvers + +# The current policy to handle pull requests for the compiler +# distribution is to merge a PR only it has been "approved" by someone +# who is not an author of the PR and has the "approver" status, by +# either +# (1) having been given commit rights, or +# (2) being part of the list of "approvers" below. +# +# Format: +# +# Preferred Name + +Gabriel Radanne + + +### Remembering naming preferences for contributors + # The aliases below correspond to preference expressed by # contributors on the name under which they credited, for example # if they use an opaque nickname from github or mantis: @@ -93,9 +115,13 @@ Hendrik Tews Hugo Heuzard Miod Vallat Christoph Spiel +Joris Giovannangeli +Wilfred Hughes +John Skaller # These contributors prefer to be referred to pseudonymously whitequark - -tkob tkob -ygrek ygrek +william +tkob +ygrek +linse diff --git a/.merlin b/.merlin deleted file mode 100644 index 5649a110..00000000 --- a/.merlin +++ /dev/null @@ -1,56 +0,0 @@ -S ./asmcomp -B ./asmcomp - -S ./middle_end -B ./middle_end - -S ./middle_end/base_types -B ./middle_end/base_types - -S ./bytecomp -B ./bytecomp - -S ./driver -B ./driver - -S ./lex -B ./lex - -S ./otherlibs/bigarray -B ./otherlibs/bigarray - -S ./otherlibs/dynlink -B ./otherlibs/dynlink - -S ./otherlibs/graph -B ./otherlibs/graph - -S ./otherlibs/str -B ./otherlibs/str - -S ./otherlibs/systhreads -B ./otherlibs/systhreads - -S ./otherlibs/threads -B ./otherlibs/threads - -S ./otherlibs/unix -B ./otherlibs/unix - -S ./parsing -B ./parsing - -STDLIB ./stdlib -FLG -open Stdlib -nopervasives - -S ./toplevel -B ./toplevel - -S ./typing -B ./typing - -S ./utils -B ./utils - -S ./ocamltest -B ./ocamltest diff --git a/.travis.yml b/.travis.yml index eb065cd3..60b2d7ab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ sudo: false language: c git: submodules: false -script: bash -ex tools/ci/travis/travis-ci.sh +script: bash -e tools/ci/travis/travis-ci.sh matrix: include: - env: CI_KIND=build XARCH=i386 @@ -31,8 +31,10 @@ matrix: - libx11-dev:i386 - libc6-dev:i386 - env: CI_KIND=build XARCH=x64 - - env: CI_KIND=build XARCH=x64 CONFIG_ARG=-flambda OCAMLRUNPARAM=b,v=0 + - env: CI_KIND=build XARCH=x64 CONFIG_ARG=--enable-flambda OCAMLRUNPARAM=b,v=0 - env: CI_KIND=changes + - env: CI_KIND=manual + - env: CI_KIND=check-typo - env: CI_KIND=tests allow_failures: - env: CI_KIND=tests diff --git a/BOOTSTRAP.adoc b/BOOTSTRAP.adoc new file mode 100644 index 00000000..dbd99675 --- /dev/null +++ b/BOOTSTRAP.adoc @@ -0,0 +1,58 @@ += Bootstrapping the compiler + +This file explains how to bootstrap the OCaml compiler, i.e. how to +update the binaries in the link:boot/[] directory. + +A bootstrap is required for example when something changes in the +runtime system (the magic number of bytecode executables, the format of +bytecode instructions, the set of available primitives) or when the +format of .cmi files is modified. In particular, given that the .cmi +files contain information related to types, modifying the way a type is +represented will modify the format of .cmi files and thus require a +bootstrap. + +Here is how to perform a change that requires a bootstrap: + +1. Make sure you start with a clean source tree (e.g. check with + `git status`) + +2. Configure your source tree by running: + + ./configure + +3. Bring your system to a stable state. Concretely, this means that the + boot/ directory should contain a version of ocamlrun and all the + \*.cm* files of the standard library. This stable state can be reached + by running + + make world ++ +(Actually, running `make coldstart` should be enough but `make world` is +safer. Similarly, `make world.opt` will also bring you to such a stable +state but builds more things than actually required.) + +4. Now, and only now, edit the sources. Changes here may include adding, + removing or renaming a primitive in the runtime, changing the magic + number of bytecode executable files, changing the way types are + represented or anything else in the format of .cmi files, etc. + +5. Run: + + make coreall ++ +This will rebuild runtime/ocamlrun, ocamlc, etc. + +6. (optional) The new system can now be tested: + + echo 'let _ = print_string "Hello world!\n"' > foo.ml + ./boot/ocamlrun ./ocamlc -I ./stdlib foo.ml + ./runtime/ocamlrun a.out + +7. We now know the system works and can thus build the new boot/ + binaries: + + make bootstrap + +If you notice that this procedure fails for a given change you are +trying to implement, please report it so that the procedure can be +updated to also cope with your change. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index aae6f0ad..7cfbf6b2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,6 +68,9 @@ columns, not use tab characters (spaces only), and not use non-ASCII characters. These typographical rules can be checked with the script `tools/check-typo`. +If you are working from a Git clone, you can automate this process by +copying the file `tools/pre-commit-githook` to `.git/hooks/pre-commit`. + Otherwise, there are no strongly enforced guidelines specific to the compiler -- and, as a result, the style may differ in the different parts of the compiler. The general [OCaml Programming diff --git a/Changes b/Changes index 584fa9a9..30478453 100644 --- a/Changes +++ b/Changes @@ -1,34 +1,951 @@ +OCaml 4.08.0 (13 June 2019) +--------------------------- + +(Changes that can break existing programs are marked with a "*") + +### Language features: + +- #1947: Introduce binding operators (let*, let+, and* etc.) + (Leo White, review by Thomas Refis) + +- #1892: Allow shadowing of items coming from an include + (Thomas Refis, review by Gabriel Radanne) + +- #2122: Introduce local substitutions in signatures: "type t := type_expr" + and "module M := Extended(Module).Path" + (Thomas Refis, with help and review from Leo White, and Alain Frisch) + +- #1804: New notion of "alerts" that generalizes the deprecated warning + [@@ocaml.alert deprecated "Please use bar instead!"] + [@@ocaml.alert unsafe "Please use safe_foo instead!"] + (Alain Frisch, review by Leo White and Damien Doligez) + +- #6422, #7083, #305, #1568: Allow `exception` under or-patterns + (Thomas Refis, with help and review from Alain Frisch, Gabriel Scherer, Jeremy + Yallop, Leo White and Luc Maranget) + + +- #1705: Allow @@attributes on exception declarations. + (Hugo Heuzard, review by Gabriel Radanne and Thomas Refis) + +- #1506, #2147, #2166, #2167: Extended `open` to arbitrary module + expression in structures and to applicative paths in signatures + (Runhang Li, review by Alain Frisch, Florian Angeletti, Jeremy Yallop, + Leo White and Thomas Refis) + +* #2106: .~ is now a reserved keyword, and is no longer available + for use in extended indexing operators + (Jeremy Yallop, review by Gabriel Scherer, Florian Angeletti, and + Damien Doligez) + +* #7841, #2041, #2235: allow modules from include directories + to shadow other ones, even in the toplevel; for a example, including + a directory that defines its own Result module will shadow the stdlib's. + (Jérémie Dimino, review by Alain Frisch and David Allsopp) + +### Type system: + +- #2110: Partial support for GADTs inside or-patterns; + The type equalities introduced by the GADT constructor are only + available inside the or-pattern; they cannot be used in the + right-hand-side of the clause, when both sides of the or-pattern + agree on it. + (Thomas Refis and Leo White, review by Jacques Garrigue) + +- #1826: allow expanding a type to a private abbreviation instead of + abstracting when removing references to an identifier. + (Thomas Refis and Leo White, review by Jacques Garrigue) + +- #1942, #2244: simplification of the static check + for recursive definitions + (Alban Reynaud and Gabriel Scherer, + review by Jeremy Yallop, Armaël Guéneau and Damien Doligez) + +### Standard library: + +- #2128: Add Fun module: `id, const, flip, negate, protect` + (protect is a "try_finally" combinator) + https://caml.inria.fr/pub/docs/manual-ocaml/libref/Fun.html + (Many fine eyes) + +- #2010: Add Bool module + https://caml.inria.fr/pub/docs/manual-ocaml/libref/Bool.html + (Many fine eyes) + +- #2011: Add Int module + https://caml.inria.fr/pub/docs/manual-ocaml/libref/Int.html + (Many fine eyes) + +- #1940: Add Option module and Format.pp_print_option + `none, some, value, get, bind, join, map, fold, iter`, etc. + https://caml.inria.fr/pub/docs/manual-ocaml/libref/Option.html + (Many fine eyes) + +- #1956: Add Result module and Format.pp_print_result + `ok, error, value, get_ok, bind, join, map, map_error`, etc. + https://caml.inria.fr/pub/docs/manual-ocaml/libref/Result.html + (Many fine eyes) + +- #1855, #2118: Add `Fun.protect ~finally` for enforcing local + invariants whether a function raises or not, similar to + `unwind-protect` in Lisp and `FINALLY` in Modula-2. It is careful + about preserving backtraces and treating exceptions in finally as + errors. + (Marcello Seri and Guillaume Munch-Maccagnoni, review by Daniel + Bünzli, Gabriel Scherer, François Bobot, Nicolás Ojeda Bär, Xavier + Clerc, Boris Yakobowski, Damien Doligez, and Xavier Leroy) + +* #1605: Deprecate Stdlib.Pervasives. Following #1010, Pervasives + is no longer needed and Stdlib should be used instead. + (Jérémie Dimino, review by Nicolás Ojeda Bär) + +- #2185: Add `List.filter_map` + (Thomas Refis, review by Alain Frisch and Gabriel Scherer) + +- #1957: Add Stack.{top_opt,pop_opt} and Queue.{peek_opt,take_opt}. + (Vladimir Keleshev, review by Nicolás Ojeda Bär and Gabriel Scherer) + +- #1182: Add new Printf formats %#d %#Ld %#ld %#nd (idem for %i and %u) for + alternative integer formatting -- inserts '_' between blocks of digits. + (ygrek, review by Gabriel Scherer) + +- #1959: Add Format.dprintf, a printing function which outputs a closure + usable with %t. + (Gabriel Radanne, request by Armaël Guéneau, + review by Florian Angeletti and Gabriel Scherer) + +- #1986, #6450: Add Set.disjoint + (Nicolás Ojeda Bär, review by Gabriel Scherer) + +- #7812, #2125: Add Filename.chop_suffix_opt + (Alain Frisch, review by Nicolás Ojeda Bär, suggestion by whitequark) + +- #1864: Extend Bytes and Buffer with functions to read/write + binary representations of numbers + (Alain Frisch and Daniel Bünzli) + +- #1458: Add unsigned operations unsigned_div, unsigned_rem, unsigned_compare + and unsigned_to_int to modules Int32, Int64, Nativeint. + (Nicolás Ojeda Bär, review by Daniel Bünzli, Alain Frisch and Max Mouratov) + +- #2002: Add Format.pp_print_custom_break, a new more general kind of break + hint that can emit non-whitespace characters. + (Vladimir Keleshev and Pierre Weis, review by Josh Berdine, Gabriel Radanne) + +- #1966: Add Format semantic tags using extensible sum types. + (Gabriel Radanne, review by Nicolás Ojeda Bär) + +- #1794: Add constants zero, one, minus_one and functions succ, + pred, is_finite, is_infinite, is_nan, is_integer, trunc, round, + next_after, sign_bit, min, max, min_max, min_num, max_num, + min_max_num to module Float. + (Christophe Troestler, review by Alain Frish, Xavier Clerc and Daniel Bünzli) + +- #1354, #2177: Add fma support to Float module. + (Laurent Thévenoux, review by Alain Frisch, Jacques-Henri Jourdan, + Xavier Leroy) + + + +- #5072, #6655, #1876: add aliases in Stdlib for built-in types + and exceptions. + (Jeremy Yallop, reports by Pierre Letouzey and David Sheets, + review by Valentin Gatien-Baron, Gabriel Scherer and Alain Frisch) + +- #1731: Format, use raise_notrace to preserve backtraces. + (Frédéric Bour, report by Jules Villard, review by Gabriel Scherer) + +- #6701, #1185, #1803: make float_of_string and string_of_float + locale-independent. + (ygrek, review by Xavier Leroy and Damien Doligez) + +- #7795, #1782: Fix off-by-one error in Weak.create. + (KC Sivaramakrishnan, review by Gabriel Scherer and François Bobot) + +- #7235: Format, flush err_formatter at exit. + (Pierre Weis, request by Jun Furuse) + +- #1857, #7812: Remove Sort module, deprecated since 2000 and emitting + a deprecation warning since 4.02. + (whitequark) + +- #1923: Arg module sometimes misbehaved instead of rejecting invalid + -keyword=arg inputs + (Valentin Gatien-Baron, review by Gabriel Scherer) + +- #1959: Small simplification and optimization to Format.ifprintf + (Gabriel Radanne, review by Gabriel Scherer) + +- #2119: clarify the documentation of Set.diff + (Gabriel Scherer, suggestion by John Skaller) + +- #2145: Deprecate the mutability of Gc.control record fields + (Damien Doligez, review by Alain Frisch) + +- #2159, #7874: annotate {String,Bytes}.equal as being [@@noalloc]. + (Pierre-Marie Pédrot, review by Nicolás Ojeda Bär) + +- #1936: Add module Float.Array + (Damien Doligez, review by Xavier Clerc and Alain Frisch) + +- #2183: Fix segfault in Array.create_float with -no-flat-float-array + (Damien Doligez, review by Gabriel Scherer and Jeremy Yallop) + +- #1525: Make function set_max_indent respect documentation + (Pierre Weis, Richard Bonichon, review by Florian Angeletti) + +- #2202: Correct Hashtbl.MakeSeeded.{add_seq,replace_seq,of_seq} to use + functor hash function instead of default hash function. Hashtbl.Make.of_seq + shouldn't create randomized hash tables. + (David Allsopp, review by Alain Frisch) + +### Other libraries: + +- #2533, #1839, #1949: added Unix.fsync + (Francois Berenger, Nicolás Ojeda Bär, review by Daniel Bünzli, David Allsopp + and ygrek) + +- #1792, #7794: Add Unix.open_process_args{,_in,_out,_full} similar to + Unix.open_process{,_in,_out,_full}, but passing an explicit argv array. + (Nicolás Ojeda Bär, review by Jérémie Dimino, request by Volker Diels-Grabsch) + +- #1999: Add Unix.process{,_in,_out,_full}_pid to retrieve opened process's + pid. + (Romain Beauxis, review by Nicolás Ojeda Bär) + +- #2222: Set default status in waitpid when pid is zero. Otherwise, + status value is undefined. + (Romain Beauxis and Xavier Leroy, review by Stephen Dolan) + +* #2104, #2211, #4127, #7709: Fix Thread.sigmask. When + system threads are loaded, Unix.sigprocmask is now an alias for + Thread.sigmask. This changes the behavior at least on MacOS, where + Unix.sigprocmask used to change the masks of all threads. + (Jacques-Henri Jourdan, review by Jérémie Dimino) + +- #1061: Add ?follow parameter to Unix.link. This allows hardlinking + symlinks. + (Christopher Zimmermann, review by Xavier Leroy, Damien Doligez, David + Allsopp, David Sheets) + +- #2038: Deprecate vm threads. + OCaml supported both "native threads", based on pthreads, + and its own green-threads implementation, "vm threads". We are not + aware of any recent usage of "vm threads", and removing them simplifies + further maintenance. + (Jérémie Dimino) + +* #4208, #4229, #4839, #6462, #6957, #6950, #1063, #2176, + #2297: Make (nat)dynlink sound by correctly failing when + dynlinked module names clash with other modules or interfaces. + (Mark Shinwell, Leo White, Nicolás Ojeda Bär, Pierre Chambart) + +- #2263: Delete the deprecated Bigarray.*.map_file functions in + favour of `*_of_genarray (Unix.map_file ...)` functions instead. The + `Unix.map_file` function was introduced in OCaml 4.06.0 onwards. + (Jérémie Dimino, reviewed by David Allsopp and Anil Madhavapeddy) + +### Compiler user-interface and warnings: + +- #2096: Add source highlighting for errors & warnings in batch mode + (Armaël Guéneau, review by Gabriel Scherer and Jérémie Dimino) + +- #2133: [@ocaml.warn_on_literal_pattern]: now warn on literal patterns + found anywhere in a constructor's arguments. + (Jeremy Yallop, review by Gabriel Scherer) + +- #1720: Improve error reporting for missing 'rec' in let-bindings. + (Arthur Charguéraud and Armaël Guéneau, with help and advice + from Gabriel Scherer, Frédéric Bour, Xavier Clerc and Leo White) + +- #7116, #1430: new -config-var option + to get the value of a single configuration variable in scripts. + (Gabriel Scherer, review by Sébastien Hinderer and David Allsopp, + request by Adrien Nader) + +- #1733,1993,1998,2058,2094,2140: Typing error message improvements + - #1733, change the perspective of the unexpected existential error + message. + - #1993, expanded error messages for universal quantification failure + - #1998, more context for unbound type parameter error + - #2058, full explanation for unsafe cycles in recursive module + definitions (suggestion by Ivan Gotovchits) + - #2094, rewording for "constructor has no type" error + - #7565, #2140, more context for universal variable escape + in method type + (Florian Angeletti, reviews by Jacques Garrique, Armaël Guéneau, + Gabriel Radanne, Gabriel Scherer and Jeremy Yallop) + +- #1913: new flag -dump-into-file to print debug output like -dlambda into + a file named after the file being built, instead of on stderr. + (Valentin Gatien-Baron, review by Thomas Refis) + +- #1921: in the compilation context passed to ppx extensions, + add more configuration options related to type-checking: + -rectypes, -principal, -alias-deps, -unboxed-types, -unsafe-string + (Gabriel Scherer, review by Gabriel Radanne, Xavier Clerc and Frédéric Bour) + +- #1976: Better error messages for extension constructor type mismatches + (Thomas Refis, review by Gabriel Scherer) + +- #1841, #7808: the environment variable OCAMLTOP_INCLUDE_PATH can now + specify a list of additional include directories for the ocaml toplevel. + (Nicolás Ojeda Bär, request by Daniel Bünzli, review by Daniel Bünzli and + Damien Doligez) + +- #6638, #1110: introduced a dedicated warning to report + unused "open!" statements + (Alain Frisch, report by dwang, review by and design from Leo White) + +- #1974: Trigger warning 5 in "let _ = e" and "ignore e" if e is of function + type and syntactically an application. (For the case of "ignore e" the warning + already existed, but used to be triggered even when e was not an application.) + (Nicolás Ojeda Bär, review by Alain Frisch and Jacques Garrigue) + +- #7408, #7846, #2015: Check arity of primitives. + (Hugo Heuzard, review by Nicolás Ojeda Bär) + + + +- #2091: Add a warning triggered by type declarations "type t = ()" + (Armaël Guéneau, report by linse, review by Florian Angeletti and Gabriel + Scherer) + +- #2004: Use common standard library path `lib/ocaml` for Windows, + for consistency with OSX & Linux. Previously was located at `lib`. + (Bryan Phelps, Jordan Walke, review by David Allsopp) + +- #6416, #1120: unique printed names for identifiers + (Florian Angeletti, review by Jacques Garrigue) + +- #1691: add shared_libraries to ocamlc -config exporting + SUPPORTS_SHARED_LIBRARIES from Makefile.config. + (David Allsopp, review by Gabriel Scherer and Mark Shinwell) + +- #6913, #1786: new -match-context-rows option + to control the degree of optimization in the pattern matching compiler. + (Dwight Guth, review by Gabriel Scherer and Luc Maranget) + +- #1822: keep attributes attached to pattern variables from being discarded. + (Nicolás Ojeda Bär, review by Thomas Refis) + +- #1845: new `-dcamlprimc` option to keep the generated C file containing + the information about primitives; pass `-fdebug-prefix-map` to the C compiler + when supported, for reproducible builds + (Xavier Clerc, review by Jérémie Dimino) + +- #1856, #1869: use `BUILD_PATH_PREFIX_MAP` when compiling primitives + in order to make builds reproducible if code contains uses of + `__FILE__` or `__LOC__` + (Xavier Clerc, review by Gabriel Scherer and Sébastien Hinderer) + +- #1906: the -unsafe option does not apply to marshalled ASTs passed + to the compiler directly or by a -pp preprocessor; add a proper + warning (64) instead of a simple stderr message + (Valentin Gatien-Baron) + +- #1925: Print error locations more consistently between batch mode, toplevel + and expect tests + (Armaël Guéneau, review by Thomas Refis, Gabriel Scherer and François Bobot) + +- #1930: pass the elements from `BUILD_PATH_PREFIX_MAP` to the assembler + (Xavier Clerc, review by Gabriel Scherer, Sébastien Hinderer, and + Xavier Leroy) + +- #1945, #2032: new "-stop-after [parsing|typing]" option + to stop compilation after the parsing or typing pass + (Gabriel Scherer, review by Jérémie Dimino) + +- #1953: Add locations to attributes in the parsetree. + (Hugo Heuzard, review by Gabriel Radanne) + +- #1954: Add locations to toplevel directives. + (Hugo Heuzard, review by Gabriel Radanne) + +* #1979: Remove support for TERM=norepeat when displaying errors + (Armaël Guéneau, review by Gabriel Scherer and Florian Angeletti) + +- #1960: The parser keeps previous location when relocating ast node. + (Hugo Heuzard, review by Jérémie Dimino) + +- #7864, #2109: remove duplicates from spelling suggestions. + (Nicolás Ojeda Bär, review by Armaël Guéneau) + +### Manual and documentation: + +- #7548: printf example in the tutorial part of the manual + (Kostikova Oxana, rewiew by Gabriel Scherer, Florian Angeletti, + Marcello Seri and Armaël Guéneau) + +- #7546, #2020: preambles and introduction for compiler-libs. + (Florian Angeletti, review by Daniel Bünzli, Perry E. Metzger + and Gabriel Scherer) + +- #7547, #2273: Tutorial on Lazy expressions and patterns in OCaml Manual + (Ulugbek Abdullaev, review by Florian Angeletti and Gabriel Scherer) + +- #7720, #1596, precise the documentation + of the maximum indentation limit in Format. + (Florian Angeletti, review by Richard Bonichon and Pierre Weis) + +- #7825: html manual split compilerlibs from stdlib in the html + index of modules + (Florian Angeletti, review by Perry E. Metzger and Gabriel Scherer) + +- #1209, #2008: in the Extension section, use the caml_example environment + (uses the compiler to check the example code). + This change was made possible by a lot of tooling work from Florian Angeletti: + #1702, #1765, #1863, and Gabriel Scherer's #1903. + (Gabriel Scherer, review by Florian Angeletti) + +- #1788, 1831, 2007, 2198, 2232, move language extensions to the core + chapters: + - #1788: quoted string description + - #1831: local exceptions and exception cases + - #2007: 32-bit, 64-bit and native integer literals + - #2198: lazy patterns + - #2232: short object copy notation + (Florian Angeletti, review by Xavier Clerc, Perry E. Metzger, Gabriel Scherer + and Jeremy Yallop) + +- #1863: caml-tex2, move to compiler-libs + (Florian Angeletti, review by Sébastien Hinderer and Gabriel Scherer) + +- #2105: Change verbatim to caml_example in documentation + (Maxime Flin, review by Florian Angeletti) + +- #2114: ocamldoc, improved manpages for documentation inside modules + (Florian Angeletti, review by Gabriel Scherer) + +- #2117: stdlib documentation, duplicate the operator precedence table + from the manual inside a separate "OCaml_operators" module. + (Florian Angeletti, review by Daniel Bünzli, Perry E. Metzger + and Gabriel Scherer) + +- #2187: document "exception A | pat" patterns + (Florian Angeletti, review by Perry E. Metzger and Jeremy Yallop) + +- #8508: refresh \moduleref macro + (Florian Angeletti, review by Gabriel Scherer) + +### Code generation and optimizations: + +- #7725, #1754: improve AFL instrumentation for objects and lazy values. + (Stephen Dolan) + +- #1631: AMD64 code generator: emit shorter instruction sequences for the + sign-extension operations. + (LemonBoy, review by Alain Frisch and Xavier Leroy) + +- #7246, #2146: make a few int64 primitives use [@@unboxed] + stubs on 32bits + (Jérémie Dimino) + +- #1917: comballoc: ensure object allocation order is preserved + (Stephen Dolan) + +- #6242, #2143, #8558, #8559: Optimize some local functions. + Local functions that do not escape and whose calls all have + the same continuation are lowered into a static-catch handler. + (Alain Frisch, review by Gabriel Scherer) + +- #2082: New options [-insn-sched] and [-no-insn-sched] to control + instruction scheduling. + (Mark Shinwell, review by Damien Doligez) + +- #2239: Fix match miscompilation with flambda + (Leo White, review by Alain Frisch) + +### Runtime system: + +- #7198, #7750, #1738: add a function (caml_alloc_custom_mem) + and three GC parameters to give the user better control of the + out-of-heap memory retained by custom values; use the function to + allocate bigarrays and I/O channels. + (Damien Doligez, review by Alain Frisch) + +- #1793: add the -m and -M command-line options to ocamlrun. + Option -m prints the magic number of the bytecode executable passed + as argument, -M prints the magic number expected by ocamlrun. + (Sébastien Hinderer, review by Xavier Clerc and Damien Doligez) + +- #1867: Remove the C plugins mechanism. + (Xavier Leroy, review by David Allsopp, Damien Doligez, Sébastien Hinderer) + +- #8627: Require SSE2 for 32-bit mingw port to generate correct code + for caml_round with GCC 7.4. + (David Allsopp, review by Xavier Leroy) + +- #7676, #2144: Remove old GC heuristic + (Damien Doligez, report and review by Alain Frisch) + +- #1723: Remove internal Meta.static_{alloc,free} primitives. + (Stephen Dolan, review by Gabriel Scherer) + +- #1895: Printexc.get_callstack would return only one frame in native + code in threads other then the initial one + (Valentin Gatien-Baron, review by Xavier Leroy) + +- #1900, #7814: avoid exporting non-prefixed identifiers in the debug + and instrumented runtimes. + (Damien Doligez, report by Gabriel Scherer) + +- #2079: Avoid page table lookup in Pervasives.compare with + no-naked-pointers + (Sam Goldman, review by Gabriel Scherer, David Allsopp, Stephen Dolan) + +- #7829, #8585: Fix pointer comparisons in freelist.c (for 32-bit platforms) + (David Allsopp and Damien Doligez) + +- #8567, #8569: on ARM64, use 32-bit loads to access caml_backtrace_active + (Xavier Leroy, review by Mark Shinwell and Greta Yorsh) + +- #8568: Fix a memory leak in mmapped bigarrays + (Damien Doligez, review by Xavier Leroy and Jérémie Dimino) + +### Tools + +- #2182: Split Emacs caml-mode as an independent project. + (Christophe Troestler, review by Gabriel Scherer) + +- #1865: support dark themes in Emacs, and clean up usage of + deprecated Emacs APIs + (Wilfred Hughes, review by Clément Pit-Claudel) + +- #1590: ocamllex-generated lexers can be instructed not to update + their lex_curr_p/lex_start_p fields, resulting in a significant + performance gain when those fields are not required. + (Alain Frisch, review by Jérémie Dimino) + +- #7843, #2013: ocamldoc, better handling of {{!label}text} in the latex + backend. + (Florian Angeletti, review by Nicolás Ojeda Bär and Gabriel Scherer) + +- #7844, #2040: Emacs, use built-in detection of comments, + fixes an imenu crash. + (Wilfred Hughes, review by Christophe Troestler) + +- #7850: Emacs, use symbol boundaries in regular expressions, + fixes an imenu crash. + (Wilfred Hughes, review by Christophe Troestler) + +- #1711: the new 'open' flag in OCAMLRUNPARAM takes a comma-separated list of + modules to open as if they had been passed via the command line -open flag. + (Nicolás Ojeda Bär, review by Mark Shinwell) + +- #2000: ocamdoc, extended support for "include module type of ..." + (Florian Angeletti, review by Jérémie Dimino) + +- #2045: ocamlmklib now supports options -args and -args0 to provide extra + command-line arguments in a file. + (Nicolás Ojeda Bär, review by Gabriel Scherer and Daniel Bünzli) + +- #2189: change ocamldep Makefile-output to print each dependency + on a new line, for more readable diffs of versioned dependencies. + (Gabriel Scherer, review by Nicolás Ojeda Bär) + +- #2223: ocamltest: fix the "bsd" and "not-bsd" built-in actions to + recognize all BSD variants + (Damien Doligez, review by Sébastien Hinderer and David Allsopp) + +### Compiler distribution build system: + +- #1776: add -no-install-bytecode-programs and related configure options to + control (non-)installation of ".byte" executables. + (Mark Shinwell, review by Sébastien Hinderer and Gabriel Scherer) + +- #1777: add -no-install-source-artifacts and related configure options to + control installation of .cmt, .cmti, .mli and .ml files. + (Mark Shinwell, review by Nicolás Ojeda Bär and Sébastien Hinderer) + +- #1781: cleanup of the manual's build process. + (steinuil, review by Marcello Seri, Gabriel Scherer and Florian Angeletti) + +- #1797: remove the deprecated Makefile.nt files. + (Sébastien Hinderer, review by Nicolas Ojeda Bar) + +- #1805: fix the bootstrap procedure and its documentation. + (Sébastien Hinderer, Xavier Leroy and Damien Doligez; review by + Gabriel Scherer) + +- #1840: build system enhancements. + (Sébastien Hinderer, review by David Allsopp, Xavier Leroy and + Damien Doligez) + +- #1852: merge runtime directories + (Sébastien Hinderer, review by Xavier Leroy and Damien Doligez) + +- #1854: remove the no longer defined BYTECCCOMPOPTS build variable. + (Sébastien Hinderer, review by Damien Doligez) + +- #2024: stop supporting obsolete platforms: Rhapsody (old beta + version of MacOS X, BeOS, alpha*-*-linux*, mips-*-irix6*, + alpha*-*-unicos, powerpc-*-aix, *-*-solaris2*, mips*-*-irix[56]*, + i[3456]86-*-darwin[89].*, i[3456]86-*-solaris*, *-*-sunos* *-*-unicos. + (Sébastien Hinderer, review by Xavier Leroy, Damien Doligez, Gabriel + Scherer and Armaël Guéneau) + +- #2053: allow unix, vmthreads and str not to be built. + (David Allsopp, review by Sébastien Hinderer) + +* #2059: stop defining OCAML_STDLIB_DIR in s.h. + (Sébastien Hinderer, review by David Allsopp and Damien Doligez) + +* #2066: remove the standard_runtime configuration variable. + (Sébastien Hinderer, review by Xavier Leroy, Stephen Dolan and + Damien Doligez) + +* #2139: use autoconf to generate the compiler's configuration script + (Sébastien Hinderer, review by Damien Doligez and David Allsopp) + +- #2148: fix a parallel build bug involving CamlinternalLazy. + (Stephen Dolan, review by Gabriel Scherer and Nicolas Ojeda Bar) + +- #2264, #7904: the configure script now sets the Unicode handling mode + under Windows according to the value of the variable WINDOWS_UNICODE_MODE. If + WINDOWS_UNICODE_MODE is "ansi" then it is assumed to be the current code page + encoding. If WINDOWS_UNICODE_MODE is "compatible" or empty or not set at all, + then encoding is UTF-8 with code page fallback. + (Nicolás Ojeda Bär, review by Sébastien Hinderer and David Allsopp) + +- #2266: ensure Cygwin ports configure with `EXE=.exe`, or the compiler is + unable to find the camlheader files (subtle regression of #2139/2041) + (David Allsopp, report and review by Sébastien Hinderer) + +- #7919, #2311: Fix assembler detection in configure + (Sébastien Hinderer, review by David Allsopp) + +- #2295: Restore support for bytecode target XLC/AIX/Power + (Konstantin Romanov, review by Sébastien Hinderer and David Allsopp) + +- #8528: get rid of the direct call to the C preprocessor in the testsuite + (Sébastien Hinderer, review by David Allsopp) + +- #7938, #8532: Fix alignment detection for ints on 32-bits platforms + (Sébastien Hinderer, review by Xavier Leroy) + +* #8533: Remove some unused configure tests + (Stephen Dolan, review by David Allsopp and Sébastien Hinderer) + +- #2207, #8604: Add opam files to allow pinning + (Leo White, Greta Yorsh, review by Gabriel Radanne) + +- #8616: configure: use variables rather than arguments for a few options + (Sébastien Hinderer, review by David Allsopp, Gabriel Scherer and + Damien Doligez) + +- #8632: Correctly propagate flags for --with-pic in configure. + (David Allsopp, review by Sébastien Hinderer and Damien Doligez) + +- #8673: restore SpaceTime and libunwind support in configure script + (Sébastien Hinderer, review by Damien Doligez) + +### Internal/compiler-libs changes: + +- #7918, #1703, #1944, #2213, #2257: Add the module + Compile_common, which factorizes the common part in Compile and + Optcompile. This also makes the pipeline more modular. + (Gabriel Radanne, help from Gabriel Scherer and Valentin + Gatien-Baron, review by Mark Shinwell and Gabriel Radanne, + regression spotted by Clément Franchini) + +- #292: use Menhir as the parser generator for the OCaml parser. + Satellite GPRs: #1844, #1846, #1853, #1850, #1934, #2151, + #2174 + (Gabriel Scherer, Nicolás Ojeda Bär, Frédéric Bour, Thomas Refis + and François Pottier, + review by Nicolás Ojeda Bär, Leo White and David Allsopp) + +- #374: use Misc.try_finally for resource cleanup in the compiler + codebase. This should fix the problem of catch-and-reraise `try .. with` + blocks destroying backtrace information -- in the compiler. + (François Bobot, help from Gabriel Scherer and Nicolás Ojeda Bär, + review by Gabriel Scherer) + +- #1148, #1287, #1288, #1874: significant improvements + of the tools/check-typo script used over the files of the whole repository; + contributors are now expected to check that check-typo passes on their + pull requests; see CONTRIBUTING.md for more details. + (David Allsopp, review by Damien Doligez and Sébastien Hinderer) + +- #1610, #2252: Remove positions from paths + (Leo White, review by Frédéric Bour and Thomas Refis) + +- #1745: do not generalize the type of every sub-pattern, + only of variables. (preliminary work for GADTs in or-patterns) + (Thomas Refis, review by Leo White) + +- #1909: unsharing pattern types (preliminary work for GADTs in or-patterns) + (Thomas Refis, with help from Leo White, review by Jacques Garrigue) + +- #1748: do not error when instantiating polymorphic fields in patterns. + (Thomas Refis, review by Gabriel Scherer) + +- #2317: type_let: be more careful generalizing parts of the pattern + (Thomas Refis and Leo White, review by Jacques Garrigue) + +- #1746: remove unreachable error variant: Make_seltype_nongen. + (Florian Angeletti, review by Gabriel Radanne) + +- #1747: type_cases: always propagate (preliminary work + for GADTs in or-patterns) + (Thomas Refis, review by Jacques Garrigue) + +- #1811: shadow the polymorphic comparison in the middle-end + (Xavier Clerc, review by Pierre Chambart) + +- #1833: allow non-val payloads in CMM Ccatch handlers + (Simon Fowler, review by Xavier Clerc) + +- #1866: document the release process + (Damien Doligez and Gabriel Scherer, review by Sébastien Hinderer, + Perry E. Metzger, Xavier Leroy and David Allsopp) + +- #1886: move the Location.absname reference to Clflags.absname + (Armaël Guéneau, review by Jérémie Dimino) + +- #1894: generalize highlight_dumb in location.ml to handle highlighting + several locations + (Armaël Guéneau, review by Gabriel Scherer) + +- #1903: parsetree, add locations to all nodes with attributes + (Gabriel Scherer, review by Thomas Refis) + +- #1905: add check-typo-since to check the files changed + since a given git reference + (Gabriel Scherer, review by David Allsopp) + +- #1910: improve the check-typo use of .gitattributes + (Gabriel Scherer, review by David Allsopp and Damien Doligez) + +- #1938: always check ast invariants after preprocessing + (Florian Angeletti, review by Alain Frisch and Gabriel Scherer) + +- #1941: refactor the command line parsing of ocamlcp and ocamloptp + (Valentin Gatien-Baron, review by Florian Angeletti) + +- #1948: Refactor Stdlib.Format. Notably, use Stdlib.Stack and Stdlib.Queue, + and avoid exceptions for control flow. + (Vladimir Keleshev, review by Nicolás Ojeda Bär and Gabriel Scherer) + +* #1952: refactor the code responsible for displaying errors and warnings + `Location.report_error` is removed, use `Location.print_report` instead + (Armaël Guéneau, review by Thomas Refis) + +- #7835, #1980, #8548, #8586: separate scope from stamp in idents and explicitly + rescope idents when substituting signatures. + (Thomas Refis, review by Jacques Garrigue and Leo White) + +- #1996: expose Pprintast.longident to help compiler-libs users print + Longident.t values. + (Gabriel Scherer, review by Florian Angeletti and Thomas Refis) + +- #2030: makefile targets to build AST files of sources + for parser testing. See parsing/HACKING.adoc. + (Gabriel Scherer, review by Nicolás Ojeda Bär) + +* #2041: add a cache for looking up files in the load path + (Jérémie Dimino, review by Alain Frisch and David Allsopp) + +- #2047, #2269: a new type for unification traces + (Florian Angeletti, report by Leo White (#2269), + review by Thomas Refis and Gabriel Scherer) + +- #2055: Add [Linearize.Lprologue]. + (Mark Shinwell, review by Pierre Chambart) + +- #2056: Use [Backend_var] rather than [Ident] from [Clambda] onwards; + use [Backend_var.With_provenance] for variables in binding position. + (Mark Shinwell, review by Pierre Chambart) + +- #2060: "Phantom let" support for the Clambda language. + (Mark Shinwell, review by Vincent Laviron) + +- #2065: Add [Proc.destroyed_at_reloadretaddr]. + (Mark Shinwell, review by Damien Doligez) + +- #2070: "Phantom let" support for the Cmm language. + (Mark Shinwell, review by Vincent Laviron) + +- #2072: Always associate a scope to a type + (Thomas Refis, review by Jacques Garrigue and Leo White) + +- #2074: Correct naming of record field inside [Ialloc] terms. + (Mark Shinwell, review by Jérémie Dimino) + +- #2076: Add [Targetint.print]. + (Mark Shinwell) + +- #2080: Add [Proc.dwarf_register_numbers] and + [Proc.stack_ptr_dwarf_register_number]. + (Mark Shinwell, review by Bernhard Schommer) + +- #2088: Add [Clambda.usymbol_provenance]. + (Mark Shinwell, review by Damien Doligez) + +- #2152, #2517: refactorize the fixpoint to compute type-system + properties of mutually-recursive type declarations. + (Gabriel Scherer and Rodolphe Lepigre, review by Armaël Guéneau) + +- #2156: propagate more type information through Lambda and Clambda + intermediate language, as a preparation step for more future optimizations + (Pierre Chambart and Alain Frisch, cross-reviewed by themselves) + +- #2160: restore --disable-shared support and ensure testsuite runs correctly + when compiled without shared library support. + (David Allsopp, review by Damien Doligez and Sébastien Hinderer) + +* #2173: removed TypedtreeMap + (Thomas Refis, review by Gabriel Scherer) + +- #7867: Fix #mod_use raising an exception for filenames with no + extension. + (Geoff Gole) + +- #2100: Fix Unix.getaddrinfo when called on strings containing + null bytes; it would crash the GC later on. + (Armaël Guéneau, report and fix by Joe, review by Sébastien Hinderer) + +- #7847, #2019: Fix an infinite loop that could occur when the + (Menhir-generated) parser encountered a syntax error in a certain + specific state. + (François Pottier, report by Stefan Muenzel, + review by Frédéric Bour, Thomas Refis, Gabriel Scherer) + +- #1626: Do not allow recursive modules in `with module` + (Leo White, review by Gabriel Radanne) + +- #7726, #1676: Recursive modules, equi-recursive types and stack overflow + (Jacques Garrigue, report by Jeremy Yallop, review by Leo White) + +- #7723, #1698: Ensure `with module` and `with type` do not weaken + module aliases. + (Leo White, review by Gabriel Radanne and Jacques Garrigue) + +- #1719: fix Pervasives.LargeFile functions under Windows. + (Alain Frisch) + +- #1739: ensure ocamltest waits for child processes to terminate on Windows. + (David Allsopp, review by Sébastien Hinderer) + +- #7554, #1751: Lambda.subst: also update debug event environments + (Thomas Refis, review by Gabriel Scherer) + +- #7238, #1825: in Unix.in_channel_of_descr and Unix.out_channel_of_descr, + raise an error if the given file description is not suitable for + character-oriented I/O, for example if it is a block device or a + datagram socket. + (Xavier Leroy, review by Jérémie Dimino and Perry E. Metzger) + +- #7799, #1820: fix bug where Scanf.format_from_string could fail when + the argument string contained characters that require escaping. + (Gabriel Scherer and Nicolás Ojeda Bär, report by Guillaume Melquiond, review + by Gabriel Scherer) + +- #1843: ocamloptp was doing the wrong thing with option -inline-max-unroll. + (Github user @poechsel, review by Nicolás Ojeda Bär). + +- #1890: remove last use of Ctype.unroll_abbrev + (Thomas Refis, report by Leo White, review by Jacques Garrigue) + +- #1893: dev-branch only, warning 40(name not in scope) triggered spurious + warnings 49(missing cmi) with -no-alias-deps. + (Florian Angeletti, report by Valentin Gatien-Baron, + review by Gabriel Scherer) + +- #1912: Allow quoted strings, octal/unicode escape sequences and identifiers + containing apostrophes in ocamllex actions and comments. + (Pieter Goetschalckx, review by Damien Doligez) + +- #7828, #1935: correct the conditions that generate warning 61, + Unboxable_type_in_prim_decl + (Stefan Muenzel) + +- #1958: allow [module M(_:S) = struct end] syntax + (Hugo Heuzard, review by Gabriel Scherer) + +- #1970: fix order of floatting documentation comments in classes + (Hugo Heuzard, review by Nicolás Ojeda Bär) + +- #1977: [@@ocaml.warning "..."] attributes attached to type declarations are + no longer ignored. + (Nicolás Ojeda Bär, review by Gabriel Scherer) + +- #7830, #1987: fix ocamldebug crash when printing a value in the scope of + an `open` statement for which the `.cmi` is not available. + (Nicolás Ojeda Bär, report by Jocelyn Sérot, review by Gabriel Scherer) + +- #7854, #2062: fix an issue where the wrong locale may be used when using + the legacy ANSI encoding under Windows. + (Nicolás Ojeda Bär, report by Tiphaine Turpin) + +- #2083: Fix excessively aggressive float unboxing and introduce similar fix + as a preventative measure for boxed int unboxing. + (Thomas Refis, Mark Shinwell, Leo White) + +- #2130: fix printing of type variables with a quote in their name + (Alain Frisch, review by Armaël Guéneau and Gabriel Scherer, + report by Hugo Heuzard) + +- #2131: fix wrong calls to Env.normalize_path on non-module paths + (Alain Frisch, review by Jacques Garrigue) + +- #2175: Apply substitution to all modules when packing + (Leo White, review by Gabriel Scherer) + +- #2220: Remove duplicate process management code in + otherlibs/threads/unix.ml + (Romain Beauxis, review by Gabriel Scherer and Alain Frisch) + +- #2231: Env: always freshen persistent signatures before using them + (Thomas Refis and Leo White, review by Gabriel Radanne) + +- #7851, #8570: Module type of allows to transform a malformed + module type into a vicious signature, breaking soundness + (Jacques Garrigue, review by Leo White) + +- #7923, #2259: fix regression in FlexDLL bootstrapped build caused by + refactoring the root Makefile for Dune in #2093) + (David Allsopp, report by Marc Lasson) + +- #7929, #2261: Subst.signature: call cleanup_types exactly once + (Thomas Refis, review by Gabriel Scherer and Jacques Garrigue, + report by Daniel Bünzli and Jon Ludlam) + +- #8550, #8552: Soundness issue with class generalization + (Jacques Garrigue, review by Leo White and Thomas Refis, + report by Jeremy Yallop) + OCaml 4.07.1 (4 October 2018) ----------------------------- ### Bug fixes: -- MPR#7815, GPR#1896: major GC crash with first-fit policy +- #7815, #1896: major GC crash with first-fit policy (Stephen Dolan and Damien Doligez, report by Joris Giovannangeli) -* MPR#7818, GPR#2051: Remove local aliases in functor argument types, +* #7818, #2051: Remove local aliases in functor argument types, to prevent the aliasing of their target. (Jacques Garrigue, report by mandrykin, review by Leo White) -- MPR#7820, GPR#1897: Fix Array.of_seq. This function used to apply a circular +- #7820, #1897: Fix Array.of_seq. This function used to apply a circular permutation of one cell to the right on the sequence. (Thierry Martinez, review by Nicolás Ojeda Bär) -- MPR#7821, GPR#1908: make sure that the compilation of extension +- #7821, #1908: make sure that the compilation of extension constructors doesn't cause the compiler to load more cmi files - (Jérémie Dimino) + (Jérémie Dimino, review by Gabriel Scherer) -- MPR#7824, GPR#1914: subtype_row: filter out absent fields when row is closed +- #7824, #1914: subtype_row: filter out absent fields when row is closed (Leo White and Thomas Refis, report by talex, review by Jacques Garrigue) -- GPR#1915: rec_check.ml is too permissive for certain class declarations. +- #1915: rec_check.ml is too permissive for certain class declarations. (Alban Reynaud with Gabriel Scherer, review by Jeremy Yallop) -- MPR#7833, MPR#7835, MPR#7822, GPR#1997: Track newtype level again - (Leo White, reports by Jerome Simeon, Thomas Refis and Florian - Angeletti, review by Jacques Garrigue) +- #7833, #1946: typecore: only 1k existential per match, not 100k + (Thomas Refis, report by Jerome Simeon, review by Jacques Garrigue) -- MPR#7838: -principal causes assertion failure in type checker +- #7838: -principal causes assertion failure in type checker (Jacques Garrigue, report by Markus Mottl, review by Thomas Refis) OCaml 4.07.0 (10 July 2018) @@ -38,30 +955,35 @@ OCaml 4.07.0 (10 July 2018) ### Language features: -- MPR#6023, GPR#1648: Allow type-based selection of GADT constructors +- #6023, #1648: Allow type-based selection of GADT constructors. (Thomas Refis and Leo White, review by Jacques Garrigue and Gabriel Scherer) -- GPR#1546: Allow empty variants +- #1546: Allow empty variants. (Runhang Li, review by Gabriel Radanne and Jacques Garrigue) ### Standard library: -- MPR#4170, GPR#1674: add the constant `Float.pi`. +- #4170, #1674: add the constant `Float.pi`. (Christophe Troestler, review by Damien Doligez) -- MPR#6139, GPR#1685: Move the Bigarray module to the standard library. Keep the - bigarray library as on overlay adding the deprecated map_file functions +- #6139, #1685: Move the Bigarray module to the standard library. Keep the + bigarray library as on overlay adding the deprecated map_file functions. (Jérémie Dimino, review by Mark Shinwell) -- MPR#7690, GPR#1528: fix the float_of_string function for hexadecimal floats +- #7528, #1500: add a Format.pp_set_geometry function to avoid memory + effects in set_margin and set_max_indent. + (Florian Angeletti, review by Richard Bonichon, Gabriel Radanne, + Gabiel Scherer and Pierre Weis) + +- #7690, #1528: fix the float_of_string function for hexadecimal floats with very large values of the exponent. (Olivier Andrieu) -- GPR#1002: add a new `Seq` module defining a list-of-thunks style iterator. +- #1002: add a new `Seq` module defining a list-of-thunks style iterator. Also add `{to,of}_seq` to several standard modules. (Simon Cruanes, review by Alain Frisch and François Bobot) -* GPR#1010: pack all standard library modules into a single module Stdlib +* #1010: pack all standard library modules into a single module Stdlib which is the default opened module (Stdlib itself includes Pervasives) to free up the global namespace for other standard libraries, while still allowing any OCaml standard library module to be referred to as Stdlib.Module). This is @@ -70,570 +992,589 @@ OCaml 4.07.0 (10 July 2018) (Jérémie Dimino, David Allsopp and Florian Angeletti, review by David Allsopp and Gabriel Radanne) -- GPR#1637: String.escaped is faster and does not allocate when called with a +- #1637: String.escaped is faster and does not allocate when called with a string that does not contain any characters needing to be escaped. (Alain Frisch, review by Xavier Leroy and Gabriel Scherer) -- GPR#1638: add a Float module. +- #1638: add a Float module. (Nicolás Ojeda Bär, review by Alain Frisch and Jeremy Yallop) -- GPR#1697: Tune [List.init] tailrec threshold so that it does not stack overflow - when compiled with the Js_of_ocaml backend. +- #1697: Tune [List.init] tailrec threshold so that it does not stack + overflow when compiled with the Js_of_ocaml backend. (Hugo Heuzard, reviewed by Gabriel Scherer) ### Other libraries: -- MPR#7745, GPR#1629: Graphics.open_graph displays the correct window title on +- #7745, #1629: Graphics.open_graph displays the correct window title on Windows again (fault introduced by 4.06 Unicode changes). (David Allsopp) -* GPR#1406: Unix.isatty now returns true in the native Windows ports when +* #1406: Unix.isatty now returns true in the native Windows ports when passed a file descriptor connected to a Cygwin PTY. In particular, compiler colors for the native Windows ports now work under Cygwin/MSYS2. (Nicolás Ojeda Bär, review by Gabriel Scherer, David Allsopp, Xavier Leroy) -- GPR#1451: [getpwuid], [getgrgid], [getpwnam], [getgrnam] now raise Unix error +- #1451: [getpwuid], [getgrgid], [getpwnam], [getgrnam] now raise Unix error instead of returning [Not_found] when interrupted by a signal. (Arseniy Alekseyev, review by Mark Shinwell and Xavier Leroy) -- GPR#1477: raw_spacetime_lib can now be used in bytecode. +- #1477: raw_spacetime_lib can now be used in bytecode. (Nicolás Ojeda Bär, review by Mark Shinwell) -- GPR#1533: (a) The implementation of Thread.yield for system thread +- #1533: (a) The implementation of Thread.yield for system thread now uses nanosleep(1) for enabling better preemption. (b) Thread.delay is now an alias for Unix.sleepf. (Jacques-Henri Jourdan, review by Xavier Leroy and David Allsopp) ### Compiler user-interface and warnings: -- MPR#7663, GPR#1694: print the whole cycle and add a reference to the manual in +- #7663, #1694: print the whole cycle and add a reference to the manual in the unsafe recursive module evaluation error message. (Florian Angeletti, report by Matej Košík, review by Gabriel Scherer) -- GPR#1166: In OCAMLPARAM, an alternative separator can be specified as +- #1166: In OCAMLPARAM, an alternative separator can be specified as first character (instead of comma) in the set ":|; ," (Fabrice Le Fessant) -- GPR#1358: Fix usage warnings with no mli file +- #1358: Fix usage warnings with no mli file. (Leo White, review by Alain Frisch) -- GPR#1428: give a non dummy location for warning 49 (no cmi found) +- #1428: give a non dummy location for warning 49 (no cmi found). (Valentin Gatien-Baron) -- GPR#1491: Improve error reporting for ill-typed applicative functor +- #1491: Improve error reporting for ill-typed applicative functor types, F(M).t. (Valentin Gatien-Baron, review by Florian Angeletti and Gabriel Radanne) -- GPR#1496: Refactor the code printing explanation for unification type errors, - in order to avoid duplicating pattern matches +- #1496: Refactor the code printing explanation for unification type errors, + in order to avoid duplicating pattern matches. (Armaël Guéneau, review by Florian Angeletti and Gabriel Scherer) -- GPR#1505: Add specific error messages for unification errors involving - functions of type "unit -> _" +- #1505: Add specific error messages for unification errors involving + functions of type "unit -> _". (Arthur Charguéraud and Armaël Guéneau, with help from Leo White, review by Florian Angeletti and Gabriel Radanne) -- GPR#1510: Add specific explanation for unification errors caused by type - constraints propagated by keywords (such as if, while, for...) +- #1510: Add specific explanation for unification errors caused by type + constraints propagated by keywords (such as if, while, for...). (Armaël Guéneau and Gabriel Scherer, original design by Arthur Charguéraud, review by Frédéric Bour, Gabriel Radanne and Alain Frisch) -- GPR#1515: honor the BUILD_PATH_PREFIX_MAP environment variable - to enable reproducible builds +- #1515: honor the BUILD_PATH_PREFIX_MAP environment variable + to enable reproducible builds. (Gabriel Scherer, with help from Ximin Luo, review by Damien Doligez) -- GPR#1534: Extend the warning printed when (*) is used, adding a hint to - suggest using ( * ) instead +- #1534: Extend the warning printed when (*) is used, adding a hint to + suggest using ( * ) instead. (Armaël Guéneau, with help and review from Florian Angeletti and Gabriel Scherer) -- GPR#1552, GPR#1577: do not warn about ambiguous variables in guards +- #1552, #1577: do not warn about ambiguous variables in guards (warning 57) when the ambiguous values have been filtered by - a previous clause + a previous clause. (Gabriel Scherer and Thomas Refis, review by Luc Maranget) -- GPR#1554: warnings 52 and 57: fix reference to manual detailed explanation +- #1554: warnings 52 and 57: fix reference to manual detailed explanation. (Florian Angeletti, review by Thomas Refis and Gabriel Scherer) -- GPR#1618: add the -dno-unique-ids and -dunique-ids compiler flags +- #1618: add the -dno-unique-ids and -dunique-ids compiler flags. (Sébastien Hinderer, review by Leo White and Damien Doligez) -- GPR#1649 change compilation order of toplevel definitions, so that some warnings - emitted by the bytecode compiler appear more in-order than before. +- #1649: change compilation order of toplevel definitions, so that some + warnings emitted by the bytecode compiler appear more in-order than before. (Luc Maranget, advice and review by Damien Doligez) -- GPR#1806: add linscan to OCAMLPARAM options +- #1806: add linscan to OCAMLPARAM options. (Raja Boujbel) ### Code generation and optimizations: -- MPR#7630, GPR#1401: Faster compilation of large modules with Flambda. +- #7630, #1401: Faster compilation of large modules with Flambda. (Pierre Chambart, report by Emilio Jesús Gallego Arias, Pierre-Marie Pédrot and Paul Steckler, review by Gabriel Scherer and Leo White) -- MPR#7630, GPR#1455: Disable CSE for the initialization function +- #7630, #1455: Disable CSE for the initialization function. (Pierre Chambart, report by Emilio Jesús Gallego Arias, review by Gabriel Scherer and Xavier Leroy) -- GPR#1370: Fix code duplication in Cmmgen +- #1370: Fix code duplication in Cmmgen. (Vincent Laviron, with help from Pierre Chambart, reviews by Gabriel Scherer and Luc Maranget) -- GPR#1486: ARM 32-bit port: add support for ARMv8 in 32-bit mode, +- #1486: ARM 32-bit port: add support for ARMv8 in 32-bit mode, a.k.a. AArch32. For this platform, avoid ITE conditional instruction blocks and use - simpler IT blocks instead + simpler IT blocks instead. (Xavier Leroy, review by Mark Shinwell) -- GPR#1487: Treat negated float comparisons more directly +- #1487: Treat negated float comparisons more directly. (Leo White, review by Xavier Leroy) -- GPR#1573: emitcode: merge events after instructions reordering +- #1573: emitcode: merge events after instructions reordering. (Thomas Refis and Leo White, with help from David Allsopp, review by Frédéric Bour) -- GPR#1606: Simplify the semantics of Lambda.free_variables and Lambda.subst, - including some API changes in bytecomp/lambda.mli +- #1606: Simplify the semantics of Lambda.free_variables and Lambda.subst, + including some API changes in bytecomp/lambda.mli. (Pierre Chambart, review by Gabriel Scherer) -- GPR#1613: ensure that set-of-closures are processed first so that other - entries in the let-rec symbol do not get dummy approximations +- #1613: ensure that set-of-closures are processed first so that other + entries in the let-rec symbol do not get dummy approximations. (Leo White and Xavier Clerc, review by Pierre Chambart) -* GPR#1617: Make string/bytes distinguishable in the bytecode. +* #1617: Make string/bytes distinguishable in the bytecode. (Hugo Heuzard, reviewed by Nicolás Ojeda Bär) -- GPR#1627: Reduce cmx sizes by sharing variable names (Flambda only) +- #1627: Reduce cmx sizes by sharing variable names (Flambda only). (Fuyong Quah, Leo White, review by Xavier Clerc) -- GPR#1665: reduce the size of cmx files in classic mode by droping the - bodies of functions that will not be inlined +- #1665: reduce the size of cmx files in classic mode by dropping the + bodies of functions that will not be inlined. (Fuyong Quah, review by Leo White and Pierre Chambart) -- GPR#1666: reduce the size of cmx files in classic mode by droping the - bodies of functions that cannot be reached from the module block +- #1666: reduce the size of cmx files in classic mode by dropping the + bodies of functions that cannot be reached from the module block. (Fuyong Quah, review by Leo White and Pierre Chambart) -- GPR#1686: Turn off by default flambda invariants checks. +- #1686: Turn off by default flambda invariants checks. (Pierre Chambart) -- GPR#1707: Add [Closure_origin.t] to trace inlined functions to prevent +- #1707: Add [Closure_origin.t] to trace inlined functions to prevent infinite loops from repeatedly inlining copies of the same function. (Fu Yong Quah) -- GPR#1740: make sure startup.o is always linked in when using +- #1740: make sure startup.o is always linked in when using "-output-complete-obj". Previously, it was always linked in only on some - platforms, making this option unusable on platforms where it wasn't + platforms, making this option unusable on platforms where it wasn't. (Jérémie Dimino, review by Sébastien Hinderer and Xavier Leroy) ### Runtime system: -- MPR#6411, GPR#1535: don't compile everything with -static-libgcc on mingw32, +- #515 #676 #7173: Add a public C API for weak arrays and + ephemerons. Update the documentation for a 4.03 change: finalisation + functions are now run before the erasure of the corresponding + values. + (François Bobot and Jacques-Henri Jourdan, review by Mark Shinwell, + Damien Doligez and Frédéric Bour) + +- #6411, #1535: don't compile everything with -static-libgcc on mingw32, only dllbigarray.dll and libbigarray.a. Allows the use of C++ libraries which raise exceptions. (David Allsopp) -- MPR#7100, GPR#1476: trigger a minor GC when custom blocks accumulate - in minor heap +- #7100, #1476: trigger a minor GC when custom blocks accumulate + in minor heap. (Alain Frisch, report by talex, review by Damien Doligez, Leo White, Gabriel Scherer) -- GPR#1431: remove ocamlrun dependencies on curses/terminfo/termcap C library +- #1431: remove ocamlrun dependencies on curses/terminfo/termcap C library. (Xavier Leroy, review by Daniel Bünzli) -- GPR#1478: The Spacetime profiler now works under Windows (but it is not yet +- #1478: The Spacetime profiler now works under Windows (but it is not yet able to collect profiling information from C stubs). (Nicolás Ojeda Bär, review by Xavier Leroy, Mark Shinwell) -- GPR#1483: fix GC freelist accounting for chunks larger than the maximum block +- #1483: fix GC freelist accounting for chunks larger than the maximum block size. (David Allsopp and Damien Doligez) -- GPR#1526: install the debug and instrumented runtimes - (lib{caml,asm}run{d,i}.a) +- #1526: install the debug and instrumented runtimes + (lib{caml,asm}run{d,i}.a). (Gabriel Scherer, reminded by Julia Lawall) -- GPR#1563: simplify implementation of LSRINT and ASRINT +- #1563: simplify implementation of LSRINT and ASRINT. (Max Mouratov, review by Frédéric Bour) -- GPR#1644: remove caml_alloc_float_array from the bytecode primitives list - (it's a native code primitive) +- #1644: remove caml_alloc_float_array from the bytecode primitives list + (it's a native code primitive). (David Allsopp) -- GPR#1701: fix missing root bug in GPR#1476 +- #1701: fix missing root bug in #1476. (Mark Shinwell) -- GPR#1752: do not alias function arguments to sigprocmask (Anil Madhavapeddy) +- #1752: do not alias function arguments to sigprocmask. + (Anil Madhavapeddy) -- GPR#1753: avoid potential off-by-one overflow in debugger socket path - length (Anil Madhavapeddy) +- #1753: avoid potential off-by-one overflow in debugger socket path length. + (Anil Madhavapeddy) + +* #1683: Change Marshal format to make Custom_tag objects store their + length. Old versions of OCaml will no longer be able to parse new marshalled + files containing custom blocks, but old files will still parse. + (Stephen Dolan) ### Tools: -- MPR#7643, GPR#1377: ocamldep, fix an exponential blowup in presence of nested - structures and signatures (e.g. "include struct … include(struct … end) … end") +- #7643, #1377: ocamldep, fix an exponential blowup in presence of nested + structures and signatures, e.g. "include struct … include(struct … end) … end" (Florian Angeletti, review by Gabriel Scherer, report by Christophe Raffalli) -- MPR#7687, GPR#1653: deprecate -thread option, +- #7687, #1653: deprecate -thread option, which is equivalent to -I +threads. (Nicolás Ojeda Bär, report by Daniel Bünzli) -- MPR#7710: `ocamldep -sort` should exit with nonzero code in case of - cyclic dependencies +- #7710: `ocamldep -sort` should exit with nonzero code in case of + cyclic dependencies. (Xavier Leroy, report by Mantis user baileyparker) -- GPR#1537: boot/ocamldep is no longer included in the source distribution; +- #1537: boot/ocamldep is no longer included in the source distribution; boot/ocamlc -depend can be used in its place. (Nicolás Ojeda Bär, review by Xavier Leroy and Damien Doligez) -- GPR#1585: optimize output of "ocamllex -ml" +- #1585: optimize output of "ocamllex -ml". (Alain Frisch, review by Frédéric Bour and Gabriel Scherer) -- GPR#1667: add command-line options -no-propt, -no-version, -no-time, - -no-breakpoint and -topdirs-path to ocamldebug +- #1667: add command-line options -no-prompt, -no-version, -no-time, + -no-breakpoint-message and -topdirs-path to ocamldebug. (Sébastien Hinderer, review by Damien Doligez) -- GPR#1695: add the -null-crc command-line option to ocamlobjinfo. +- #1695: add the -null-crc command-line option to ocamlobjinfo. (Sébastien Hinderer, review by David Allsopp and Gabriel Scherer) -- GPR#1710: ocamldoc, improve the 'man' rendering of subscripts and +- #1710: ocamldoc, improve the 'man' rendering of subscripts and superscripts. (Gabriel Scherer) -- GPR#1771: ocamdebug, avoid out of bound access +- #1771: ocamldebug, avoid out of bound access. (Thomas Refis) ### Manual and documentation: -- MPR#7613: minor reword of the "refutation cases" paragraph +- #7613: minor rewording of the "refutation cases" paragraph. (Florian Angeletti, review by Jacques Garrigue) -- PR#7647, GPR#1384: emphasize ocaml.org website and forum in README +- #7647, #1384: emphasize ocaml.org website and forum in README. (Yawar Amin, review by Gabriel Scherer) -- PR#7698, GPR#1545: improve wording in OCaml manual in several places, +- #7698, #1545: improve wording in OCaml manual in several places, mostly in Chapter 1. This addresses the easier changes suggested in the PR. (Jim Fehrle, review by Florian Angeletti and David Allsopp) -- GPR#1540: manual, decouple verbatim and toplevel style in code examples +- #1540: manual, decouple verbatim and toplevel style in code examples. (Florian Angeletti, review by Gabriel Scherer) -- GPR#1556: manual, add a consistency test for manual references inside +- #1556: manual, add a consistency test for manual references inside the compiler source code. (Florian Angeletti, review by Gabriel Scherer) -- GPR#1647: manual, subsection on record and variant disambiguation +- #1647: manual, subsection on record and variant disambiguation. (Florian Angeletti, review by Alain Frisch and Gabriel Scherer) -- GPR#1702: manual, add a signature mode for code examples +- #1702: manual, add a signature mode for code examples. (Florian Angeletti, review by Gabriel Scherer) -- GPR#1741: manual, improve typesetting and legibility in HTML output +- #1741: manual, improve typesetting and legibility in HTML output. (steinuil, review by Gabriel Scherer) -- GPR#1757: style the html manual, changing type and layout +- #1757: style the html manual, changing type and layout. (Charles Chamberlain, review by Florian Angeletti, Xavier Leroy, Gabriel Radanne, Perry E. Metzger, and Gabriel Scherer) -- GPR#1765: manual, ellipsis in code examples +- #1765: manual, ellipsis in code examples. (Florian Angeletti, review and suggestion by Gabriel Scherer) -- GPR#1767: change html manual to use relative font sizes +- #1767: change html manual to use relative font sizes. (Charles Chamberlain, review by Daniel Bünzli, Perry E. Metzger, Josh Berdine, and Gabriel Scherer) -- GPR#1779: integrate the Bigarray documentation into the main manual. +- #1779: integrate the Bigarray documentation into the main manual. (Perry E. Metzger, review by Florian Angeletti and Xavier Clerc) ### Type system: -- MPR#7611, GPR#1491: reject the use of generative functors as applicative +- #7611, #1491: reject the use of generative functors as applicative. (Valentin Gatien-Baron) -- MPR#7706, GPR#1565: in recursive value declarations, track - static size of locally-defined variables +- #7706, #1565: in recursive value declarations, track + static size of locally-defined variables. (Gabriel Scherer, review by Jeremy Yallop and Leo White, report by Leo White) -- MPR#7717, GPR#1593: in recursive value declarations, don't treat - unboxed constructor size as statically known +- #7717, #1593: in recursive value declarations, don't treat + unboxed constructor size as statically known. (Jeremy Yallop, report by Pierre Chambart, review by Gabriel Scherer) -- MPR#7767, GPR#1712: restore legacy treatment of partially-applied +- #7767, #1712: restore legacy treatment of partially-applied labeled functions in 'let rec' bindings. (Jeremy Yallop, report by Ivan Gotovchits, review by Gabriel Scherer) -* MPR#7787, GPR#1652, GPR#1743: Don't remove module aliases in `module type of` +* #7787, #1652, #1743: Don't remove module aliases in `module type of` and `with module`. The old behaviour can be obtained using the `[@remove_aliases]` attribute. (Leo White and Thomas Refis, review by Jacques Garrigue) -- GPR#1468: Do not enrich type_decls with incoherent manifests +- #1468: Do not enrich type_decls with incoherent manifests. (Thomas Refis and Leo White, review by Jacques Garrigue) -- GPR#1469: Use the information from [@@immediate] annotations when - computing whether a type can be [@@unboxed] +- #1469: Use the information from [@@immediate] annotations when + computing whether a type can be [@@unboxed]. (Damien Doligez, report by Stephan Muenzel, review by Alain Frisch) -- GPR#1513: Allow compilation units to shadow sub-modules of Pervasives. +- #1513: Allow compilation units to shadow sub-modules of Pervasives. For instance users can now use a largeFile.ml file in their project. - (Jérémie Dimino, review by Nicolas Ojeda Bar, Alain Frisch and Gabriel Radanne) + (Jérémie Dimino, review by Nicolás Ojeda Bär, Alain Frisch and Gabriel + Radanne) -- GPR#1516: Allow float array construction in recursive bindings - when configured with -no-flat-float-array +- #1516: Allow float array construction in recursive bindings + when configured with -no-flat-float-array. (Jeremy Yallop, report by Gabriel Scherer) -- GPR#1583: propagate refined ty_arg to Parmatch checks +- #1583: propagate refined ty_arg to Parmatch checks. (Thomas Refis, review by Jacques Garrigue) -- GPR#1609: Changes to ambivalence scope tracking +- #1609: Changes to ambivalence scope tracking. (Thomas Refis and Leo White, review by Jacques Garrigue) -- GPR#1628: Treat reraise and raise_notrace as nonexpansive. +- #1628: Treat reraise and raise_notrace as nonexpansive. (Leo White, review by Alain Frisch) -* GPR#1778: Fix Soundness bug with non-generalized type variable and - local modules. This is the same bug as MPR#7414, but using local +* #1778: Fix Soundness bug with non-generalized type variable and + local modules. This is the same bug as #7414, but using local modules instead of non-local ones. (Leo White, review by Jacques Garrigue) -### Compiler distribution build system +### Compiler distribution build system: -- MPR#5219, GPR#1680, GPR#1877: use 'install' instead of 'cp' +- #5219, #1680, #1877: use 'install' instead of 'cp' in install scripts. (Gabriel Scherer, review by Sébastien Hinderer and Valentin Gatien-Baron) -- MPR#7679: make sure .a files are erased before calling ar rc, otherwise - leftover .a files from an earlier compilation may contain unwanted modules +- #7679: make sure .a files are erased before calling ar rc, otherwise + leftover .a files from an earlier compilation may contain unwanted modules. (Xavier Leroy) -- GPR#1571: do not perform architecture tests on 32-bit platforms, allowing - 64-bit back-ends to use 64-bit specific constructs +- #1571: do not perform architecture tests on 32-bit platforms, allowing + 64-bit back-ends to use 64-bit specific constructs. (Xavier Clerc, review by Damien Doligez) ### Internal/compiler-libs changes: -- MPR#7738, GPR#1624: Asmlink.reset also resets lib_ccobjs/ccopts +- #7738, #1624: Asmlink.reset also resets lib_ccobjs/ccopts. (Cedric Cellier, review by Gabriel Scherer) -- GPR#1488, GPR#1560: Refreshing parmatch +- #1488, #1560: Refreshing parmatch. (Gabriel Scherer and Thomas Refis, review by Luc Maranget) -- GPR#1502: more command line options for expect tests +- #1502: more command line options for expect tests. (Florian Angeletti, review by Gabriel Scherer) -- GPR#1511: show code at error location in expect-style tests, - using new Location.show_code_at_location function +- #1511: show code at error location in expect-style tests, + using new Location.show_code_at_location function. (Gabriel Scherer and Armaël Guéneau, review by Valentin Gatien-Baron and Damien Doligez) -- GPR#1519, GPR#1532, GRP#1570: migrate tests to ocamltest +- #1519, #1532, #1570: migrate tests to ocamltest. (Sébastien Hinderer, review by Gabriel Scherer, Valentin Gatien-Baron and Nicolás Ojeda Bär) -- GPR#1520: more robust implementation of Misc.no_overflow_mul +- #1520: more robust implementation of Misc.no_overflow_mul. (Max Mouratov, review by Xavier Leroy) -- GPR#1557: Organise and simplify translation of primitives +- #1557: Organise and simplify translation of primitives. (Leo White, review by François Bobot and Nicolás Ojeda Bär) -- GPR#1567: register all idents relevant for reraise +- #1567: register all idents relevant for reraise. (Thomas Refis, review by Alain Frisch and Frédéric Bour) -- GPR#1586: testsuite: 'make promote' for ocamltest tests +- #1586: testsuite: 'make promote' for ocamltest tests. (The new "-promote" option for ocamltest is experimental and subject to change/removal). (Gabriel Scherer) -- GPR#1619: expect_test: print all the exceptions, even the unexpected ones +- #1619: expect_test: print all the exceptions, even the unexpected ones. (Thomas Refis, review by Jérémie Dimino) -- GPR#1621: expect_test: make sure to not use the installed stdlib +- #1621: expect_test: make sure to not use the installed stdlib. (Jérémie Dimino, review by Thomas Refis) -- GPR#1646 : add ocamldoc test to ocamltest and - migrate ocamldoc tests to ocamltest +- #1646: add ocamldoc test to ocamltest and + migrate ocamldoc tests to ocamltest. (Florian Angeletti, review by Sébastien Hinderer) -- GPR#1663: refactor flambda specialise/inlining handling +- #1663: refactor flambda specialise/inlining handling. (Leo White and Xavier Clerc, review by Pierre Chambart) -- GPR#1679 : remove Pbittest from primitives in lambda +- #1679: remove Pbittest from primitives in lambda. (Hugo Heuzard, review by Mark Shinwell) -* GPR#1704: Make Ident.t abstract and immutable. +* #1704: Make Ident.t abstract and immutable. (Gabriel Radanne, review by Mark Shinwell) -### Bug fixes +- #1699: Clean up Maps and Sets throughout the compiler. + Remove the Tbl module in favor of dedicated Maps. + (Gabriel Radanne, review by Mark Shinwell) -- MPR#4499, GPR#1479: Use native Windows API to implement Sys.getenv, +### Bug fixes: + +- #4499, #1479: Use native Windows API to implement Sys.getenv, Unix.getenv and Unix.environment under Windows. (Nicolás Ojeda Bär, report by Alain Frisch, review by David Allsopp, Xavier Leroy) -- MPR#5250, GPR#1435: on Cygwin, when ocamlrun searches the path +- #5250, #1435: on Cygwin, when ocamlrun searches the path for a bytecode executable file, skip directories and other non-regular files, like other Unix variants do. (Xavier Leroy) -- MPR#6394, GPR#1425: fix fatal_error from Parmatch.get_type_path +- #6394, #1425: fix fatal_error from Parmatch.get_type_path. (Virgile Prevosto, review by David Allsopp, Thomas Refis and Jacques Garrigue) -* MPR#6604, GPR#931: Only allow directives with filename and at the beginning of - the line +* #6604, #931: Only allow directives with filename and at the beginning of + the line. (Tadeu Zagallo, report by Roberto Di Cosmo, review by Hongbo Zhang, David Allsopp, Gabriel Scherer, Xavier Leroy) -- MPR#7138, MPR#7701, GPR#1693: Keep documentation comments - even in empty structures and signatures +- #7138, #7701, #1693: Keep documentation comments + even in empty structures and signatures. (Leo White, Florian Angeletti, report by Anton Bachin) -- MPR#7178, MPR#7253, MPR#7796, GPR#1790: Make sure a function - registered with "at_exit" is executed only once when the program exits +- #7178, #7253, #7796, #1790: Make sure a function + registered with "at_exit" is executed only once when the program exits. (Nicolás Ojeda Bär and Xavier Leroy, review by Max Mouratov) -- MPR#7391, GPR#1620: Do not put a dummy method in object types +- #7391, #1620: Do not put a dummy method in object types. (Thomas Refis, review by Jacques Garrigue) -- PR#7660, GPR#1445: Use native Windows API to implement Unix.utimes in order to +- #7660, #1445: Use native Windows API to implement Unix.utimes in order to avoid unintended shifts of the argument timestamp depending on DST setting. (Nicolás Ojeda Bär, review by David Allsopp, Xavier Leroy) -- MPR#7668: -principal is broken with polymorphic variants +- #7668: -principal is broken with polymorphic variants. (Jacques Garrigue, report by Jun Furuse) -- MPR#7680, GPR#1497: Incorrect interaction between Matching.for_let and - Simplif.simplify_exits +- #7680, #1497: Incorrect interaction between Matching.for_let and + Simplif.simplify_exits. (Alain Frisch, report and review by Vincent Laviron) -- MPR#7682, GPR#1495: fix [@@unboxed] for records with 1 polymorphic field +- #7682, #1495: fix [@@unboxed] for records with 1 polymorphic field. (Alain Frisch, report by Stéphane Graham-Lengrand, review by Gabriel Scherer) -- MPR#7695, GPR#1541: Fatal error: exception Ctype.Unify(_) with field override +- #7695, #1541: Fatal error: exception Ctype.Unify(_) with field override (Jacques Garrigue, report by Nicolás Ojeda Bär) -- MPR#7704, GPR#1564: use proper variant tag in non-exhaustiveness warning +- #7704, #1564: use proper variant tag in non-exhaustiveness warning. (Jacques Garrigue, report by Thomas Refis) -- MPR#7711, GPR#1581: Internal typechecker error triggered by a constraint on - self type in a class type +- #7711, #1581: Internal typechecker error triggered by a constraint on + self type in a class type. (Jacques Garrigue, report and review by Florian Angeletti) -- MPR#7712, GPR#1576: assertion failure with type abbreviations +- #7712, #1576: assertion failure with type abbreviations. (Thomas Refis, report by Michael O'Connor, review by Jacques Garrigue) -- MPR#7747: Type checker can loop infinitly and consumes all computer memory +- #7747: Type checker can loop infinitely and consume all computer memory. (Jacques Garrigue, report by kantian) -- MPR#7751, GPR#1657: The toplevel prints some concrete types as abstract +- #7751, #1657: The toplevel prints some concrete types as abstract. (Jacques Garrigue, report by Matej Kosik) -- MPR#7765, GPR#1718: When unmarshaling bigarrays, protect against integer - overflows in size computations +- #7765, #1718: When unmarshaling bigarrays, protect against integer + overflows in size computations. (Xavier Leroy, report by Maximilian Tschirschnitz, review by Gabriel Scherer) -- MPR#7760, GPR#1713: Exact selection of lexing engine, that is - correct "Segfault in ocamllex-generated code using 'shortest'" +- #7760, #1713: Exact selection of lexing engine, that is + correct "Segfault in ocamllex-generated code using 'shortest'". (Luc Maranget, Frédéric Bour, report by Stephen Dolan, review by Gabriel Scherer) -- MPR#7769, GPR#1714: calls to Stream.junk could, under some conditions, be +- #7769, #1714: calls to Stream.junk could, under some conditions, be ignored when used on streams based on input channels. (Nicolás Ojeda Bär, report by Michael Perin, review by Gabriel Scherer) -- MPR#7793, GPR#1766: the toplevel #use directive now accepts sequences of ';;' +- #7793, #1766: the toplevel #use directive now accepts sequences of ';;' tokens. This fixes a bug in which certain files accepted by the compiler were rejected by ocamldep. (Nicolás Ojeda Bär, report by Hugo Heuzard, review by Hugo Heuzard) -- GPR#1517: More robust handling of type variables in mcomp +- #1517: More robust handling of type variables in mcomp. (Leo White and Thomas Refis, review by Jacques Garrigue) -- GPR#1530, GPR#1574: testsuite, fix 'make parallel' and 'make one DIR=...' +- #1530, #1574: testsuite, fix 'make parallel' and 'make one DIR=...' to work on ocamltest-based tests. (Runhang Li and Sébastien Hinderer, review by Gabriel Scherer) -- GPR#1550, GPR#1555: Make pattern matching warnings more robust - to ill-typed columns +- #1550, #1555: Make pattern matching warnings more robust + to ill-typed columns. (Thomas Refis, with help from Gabriel Scherer and Luc Maranget) -- GPR#1614: consider all bound variables when inlining, fixing a compiler +- #1614: consider all bound variables when inlining, fixing a compiler fatal error. (Xavier Clerc, review by Pierre Chambart, Leo White) -- GPR#1622: fix bug in the expansion of command-line arguments under Windows +- #1622: fix bug in the expansion of command-line arguments under Windows which could result in some elements of Sys.argv being truncated in some cases. (Nicolás Ojeda Bär, review by Sébastien Hinderer) -- GPR#1623: Segfault on Windows 64 bits when expanding wildcards in arguments. +- #1623: Segfault on Windows 64 bits when expanding wildcards in arguments. (Marc Lasson, review by David Allsopp, Alain Frisch, Sébastien Hinderer, Xavier Leroy, Nicolas Ojeda Bar) -- GPR#1661: more precise principality warning regarding record fields - disambiguation +- #1661: more precise principality warning regarding record fields + disambiguation. (Thomas Refis, review by Leo White) -- GPR#1687: fix bug in the printing of short functor types "(S1 -> S2) -> S3" +- #1687: fix bug in the printing of short functor types "(S1 -> S2) -> S3". (Pieter Goetschalckx, review by Gabriel Scherer) -- GPR#1722: Scrape types in Typeopt.maybe_pointer +- #1722: Scrape types in Typeopt.maybe_pointer. (Leo White, review by Thomas Refis) -- GPR#1755: ensure that a bigarray is never collected while reading complex - values (Xavier Clerc, Mark Shinwell and Leo White, report by Chris Hardin, +- #1755: ensure that a bigarray is never collected while reading complex + values. + (Xavier Clerc, Mark Shinwell and Leo White, report by Chris Hardin, reviews by Stephen Dolan and Xavier Leroy) -- GPR#1764: in byterun/memory.c, struct pool_block, use C99 flexible arrays - if available +- #1764: in byterun/memory.c, struct pool_block, use C99 flexible arrays + if available. (Xavier Leroy, review by Max Mouratov) -- GPR#1774: ocamlopt for ARM could generate VFP loads and stores with bad +- #1774: ocamlopt for ARM could generate VFP loads and stores with bad offsets, rejected by the assembler. (Xavier Leroy, review by Mark Shinwell) -- GPR#1808: handle `[@inlined]` attributes under a module constraint +- #1808: handle `[@inlined]` attributes under a module constraint. (Xavier Clerc, review by Leo White) -- GPR#1810: use bit-pattern comparison when meeting float approximations +- #1810: use bit-pattern comparison when meeting float approximations. (Xavier Clerc, report by Christophe Troestler, review by Nicolás Ojeda Bär and Gabriel Scherer) -- GPR#1835: Fix off-by-one errors in Weak.get_copy and Weak.blit +- #1835: Fix off-by-one errors in Weak.get_copy and Weak.blit. (KC Sivaramakrishnan) -- GPR#1849: bug in runtime function generic_final_minor_update() - that could lead to crashes when Gc.finalise_last is used +- #1849: bug in runtime function generic_final_minor_update() + that could lead to crashes when Gc.finalise_last is used. (report and fix by Yuriy Vostrikov, review by François Bobot) OCaml 4.06.1 (16 Feb 2018): --------------------------- -### Bug fixes +### Bug fixes: -- MPR#7661, GPR#1459: fix faulty compilation of patterns +- #7661, #1459: fix faulty compilation of patterns using extensible variants constructors (Luc Maranget, review by Thomas Refis and Gabriel Scherer, report by Abdelraouf Ouadjaout and Thibault Suzanne) -- MPR#7702, GPR#1553: refresh raise counts when inlining a function +- #7702, #1553: refresh raise counts when inlining a function (Vincent Laviron, Xavier Clerc, report by Cheng Sun) -- MPR#7704, GPR#1559: Soundness issue with private rows and pattern-matching +- #7704, #1559: Soundness issue with private rows and pattern-matching (Jacques Garrigue, report by Jeremy Yallop, review by Thomas Refis) -- MPR#7705, GPR#1558: add missing bounds check in Bigarray.Genarray.nth_dim. +- #7705, #1558: add missing bounds check in Bigarray.Genarray.nth_dim. (Nicolás Ojeda Bär, report by Jeremy Yallop, review by Gabriel Scherer) -- MPR#7713, GPR#1587: Make pattern matching warnings more robust - to ill-typed columns; this is a backport of GPR#1550 from 4.07+dev +- #7713, #1587: Make pattern matching warnings more robust + to ill-typed columns; this is a backport of #1550 from 4.07+dev (Thomas Refis, review by Gabriel Scherer, report by Andreas Hauptmann) -- GPR#1470: Don't commute negation with float comparison +- #1470: Don't commute negation with float comparison (Leo White, review by Xavier Leroy) -- GPR#1538: Make pattern matching compilation more robust to ill-typed columns +- #1538: Make pattern matching compilation more robust to ill-typed columns (Gabriel Scherer and Thomas Refis, review by Luc Maranget) OCaml 4.06.0 (3 Nov 2017): @@ -643,16 +1584,16 @@ OCaml 4.06.0 (3 Nov 2017): ### Language features: -- MPR#6271, MPR#7529, GPR#1249: Support "let open M in ..." +- #6271, #7529, #1249: Support "let open M in ..." in class expressions and class type expressions. (Alain Frisch, reviews by Thomas Refis and Jacques Garrigue) -- GPR#792: fix limitations of destructive substitutions, by +- #792: fix limitations of destructive substitutions, by allowing "S with type t := type-expr", "S with type M.t := type-expr", "S with module M.N := path" (Valentin Gatien-Baron, review by Jacques Garrigue and Leo White) -* GPR#1064, GPR#1392: extended indexing operators, add a new class of +* #1064, #1392: extended indexing operators, add a new class of user-defined indexing operators, obtained by adding at least one operator character after the dot symbol to the standard indexing operators: e,g ".%()", ".?[]", ".@{}<-": @@ -663,30 +1604,30 @@ OCaml 4.06.0 (3 Nov 2017): e.g. "unit>" must now be written "unit>". (Florian Angeletti, review by Damien Doligez and Gabriel Radanne) -- GPR#1118: Support inherited field in object type expression +- #1118: Support inherited field in object type expression type t = < m : int > type u = < n : int; t; k : int > (Runhang Li, review by Jeremy Yallop, Leo White, Jacques Garrigue, and Florian Angeletti) -* GPR#1232: Support Unicode character escape sequences in string +* #1232: Support Unicode character escape sequences in string literals via the \u{X+} syntax. These escapes are substituted by the UTF-8 encoding of the Unicode character. (Daniel Bünzli, review by Damien Doligez, Alain Frisch, Xavier Leroy and Leo White) -- GPR#1247: M.(::) construction for expressions +- #1247: M.(::) construction for expressions and patterns (plus fix printing of (::) in the toplevel) (Florian Angeletti, review by Alain Frisch, Gabriel Scherer) -* GPR#1252: The default mode is now safe-string, can be overridden +* #1252: The default mode is now safe-string, can be overridden at configure time or at compile time. - (See GPR#1386 below for the configure-time options) + (See #1386 below for the configure-time options) This breaks the code that uses the 'string' type as mutable strings (instead of Bytes.t, introduced by 4.02 in 2014). (Damien Doligez) -* GPR#1253: Private extensible variants +* #1253: Private extensible variants This change breaks code relying on the undocumented ability to export extension constructors for abstract type in signature. Briefly, module type S = sig @@ -700,56 +1641,57 @@ OCaml 4.06.0 (3 Nov 2017): end (Leo White, review by Alain Frisch) -- GPR#1333: turn off warning 40 by default +- #1333: turn off warning 40 by default (Constructor or label name used out of scope) (Leo White) -- GPR#1348: accept anonymous type parameters in `with` constraints: +- #1348: accept anonymous type parameters in `with` constraints: S with type _ t = int (Valentin Gatien-Baron, report by Jeremy Yallop) ### Type system -- MPR#248, GPR#1225: unique names for weak type variables +- #2642, #1225: unique names for weak type variables # ref [];; - : '_weak1 list ref = {contents = []} (Florian Angeletti, review by Frédéric Bour, Jacques Garrigue, Gabriel Radanne and Gabriel Scherer) -* MPR#6738, MPR#7215, MPR#7231, GPR#556: Add a new check that 'let rec' +* #6738, #7215, #7231, #556: Add a new check that 'let rec' bindings are well formed. (Jeremy Yallop, reviews by Stephen Dolan, Gabriel Scherer, Leo White, and Damien Doligez) -- GPR#1142: Mark assertions nonexpansive, so that 'assert false' +- #1142: Mark assertions nonexpansive, so that 'assert false' can be used as a placeholder for a polymorphic function. (Stephen Dolan) ### Standard library: -- MPR#1771, MPR#7309, GPR#1026: Add update to maps. Allows to update a +- #8223, #7309, #1026: Add update to maps. Allows to update a binding in a map or create a new binding if the key had no binding val update: key -> ('a option -> 'a option) -> 'a t -> 'a t (Sébastien Briais, review by Daniel Bünzli, Alain Frisch and Gabriel Scherer) -- MPR#7515, GPR#1147: Arg.align now optionally uses the tab character '\t' to +- #7515, #1147: Arg.align now optionally uses the tab character '\t' to separate the "unaligned" and "aligned" parts of the documentation string. If tab is not present, then space is used as a fallback. Allows to have spaces in the unaligned part, which is useful for Tuple options. (Nicolás Ojeda Bär, review by Alain Frisch and Gabriel Scherer) -* GPR#615: Format, add symbolic formatters that output symbolic +* #615: Format, add symbolic formatters that output symbolic pretty-printing items. New fields have been added to the formatter_out_functions record, thus this change will break any code building such record from scratch. - When building Format.formatter_out_functions values redefining the out_spaces field, - "{ fmt_out_funs with out_spaces = f; }" should be replaced by - "{ fmt_out_funs with out_spaces = f; out_indent = f; }" to maintain the old behavior. + When building Format.formatter_out_functions values redefining the out_spaces + field, "{ fmt_out_funs with out_spaces = f; }" should be replaced by + "{ fmt_out_funs with out_spaces = f; out_indent = f; }" to maintain the old + behavior. (Richard Bonichon and Pierre Weis, review by Alain Frisch, original request by - Spiros Eliopoulos in GPR#506) + Spiros Eliopoulos in #506) -* GPR#943: Fixed the divergence of the Pervasives module between the stdlib +* #943: Fixed the divergence of the Pervasives module between the stdlib and threads implementations. In rare circumstances this can change the behavior of existing applications: the implementation of Pervasives.close_out used when compiling with thread support was inconsistent with the manual. @@ -762,27 +1704,27 @@ OCaml 4.06.0 (3 Nov 2017): (Markus Mottl, review by Hezekiah M. Carty, Jeremie Dimino, Damien Doligez, Alain Frisch, Xavier Leroy, Gabriel Scherer and Mark Shinwell) -- GPR#1034: List.init : int -> (int -> 'a) -> 'a list +- #1034: List.init : int -> (int -> 'a) -> 'a list (Richard Degenne, review by David Allsopp, Thomas Braibant, Florian Angeletti, Gabriel Scherer, Nathan Moreau, Alain Frisch) -- GRP#1091 Add the Uchar.{bom,rep} constants. +- #1091 Add the Uchar.{bom,rep} constants. (Daniel Bünzli, Alain Frisch) -- GPR#1091: Add Buffer.add_utf_{8,16le,16be}_uchar to encode Uchar.t +- #1091: Add Buffer.add_utf_{8,16le,16be}_uchar to encode Uchar.t values to the corresponding UTF-X transformation formats in Buffer.t values. (Daniel Bünzli, review by Damien Doligez, Max Mouratov) -- GPR#1175: Bigarray, add a change_layout function to each Array[N] +- #1175: Bigarray, add a change_layout function to each Array[N] submodules. (Florian Angeletti) -* GPR#1306: In the MSVC and Mingw ports, "Sys.rename src dst" no longer fails if +* #1306: In the MSVC and Mingw ports, "Sys.rename src dst" no longer fails if file "dst" exists, but replaces it with file "src", like in the other ports. (Xavier Leroy) -- GPR#1314: Format, use the optional width information +- #1314: Format, use the optional width information when formatting a boolean: "%8B", "%-8B" for example (Xavier Clerc, review by Gabriel Scherer) @@ -792,76 +1734,76 @@ OCaml 4.06.0 (3 Nov 2017): ### Other libraries: -- MPR#7564, GPR#1211: Allow forward slashes in the target of symbolic links +- #7564, #1211: Allow forward slashes in the target of symbolic links created by Unix.symlink under Windows. (Nicolás Ojeda Bär, review by David Allsopp) -* MPR#7640, GPR#1414: reimplementation of Unix.execvpe to fix issues +* #7640, #1414: reimplementation of Unix.execvpe to fix issues with the 4.05 implementation. The main issue is that the current directory was always searched (last), even if the current directory is not listed in the PATH. (Xavier Leroy, report by Louis Gesbert and Arseniy Alekseyev, review by Ivan Gotovchits) -- GPR#997, GPR#1077: Deprecate Bigarray.*.map_file and add Unix.map_file as a +- #997, #1077: Deprecate Bigarray.*.map_file and add Unix.map_file as a first step towards moving Bigarray to the stdlib (Jérémie Dimino and Xavier Leroy) -* GPR#1178: remove the Num library for arbitrary-precision arithmetic. +* #1178: remove the Num library for arbitrary-precision arithmetic. It now lives as a separate project https://github.com/ocaml/num with an OPAM package called "num". (Xavier Leroy) -- GPR#1217: Restrict Unix.environment in privileged contexts; add +- #1217: Restrict Unix.environment in privileged contexts; add Unix.unsafe_environment. (Jeremy Yallop, review by Mark Shinwell, Nicolás Ojeda Bär, Damien Doligez and Hannes Mehnert) -- GPR#1321: Reimplement Unix.isatty on Windows. It no longer returns true for +- #1321: Reimplement Unix.isatty on Windows. It no longer returns true for the null device. (David Allsopp) ### Compiler user-interface and warnings: -- MPR#7361, GPR#1248: support "ocaml.warning" in all attribute contexts, and +- #7361, #1248: support "ocaml.warning" in all attribute contexts, and arrange so that "ocaml.ppwarning" is correctly scoped by surrounding "ocaml.warning" attributes (Alain Frisch, review by Florian Angeletti and Thomas Refis) -- MPR#7444, GPR#1138: trigger deprecation warning when a "deprecated" +- #7444, #1138: trigger deprecation warning when a "deprecated" attribute is hidden by signature coercion (Alain Frisch, report by bmillwood, review by Leo White) -- MPR#7472: ensure .cmi files are created atomically, +- #7472: ensure .cmi files are created atomically, to avoid corruption of .cmi files produced simultaneously by a run of ocamlc and a run of ocamlopt. (Xavier Leroy, from a suggestion by Gerd Stolpmann) -* MPR#7514, GPR#1152: add -dprofile option, similar to -dtimings but +* #7514, #1152: add -dprofile option, similar to -dtimings but also displays memory allocation and consumption. The corresponding addition of a new compiler-internal Profile module may affect some users of compilers-libs/ocamlcommon (by creating module conflicts). (Valentin Gatien-Baron, report by Gabriel Scherer) -- MPR#7620, GPR#1317: Typecore.force_delayed_checks does not run with -i option +- #7620, #1317: Typecore.force_delayed_checks does not run with -i option (Jacques Garrigue, report by Jun Furuse) -- MPR#7624: handle warning attributes placed on let bindings +- #7624: handle warning attributes placed on let bindings (Xavier Clerc, report by dinosaure, review by Alain Frisch) -- GPR#896: "-compat-32" is now taken into account when building .cmo/.cma +- #896: "-compat-32" is now taken into account when building .cmo/.cma (Hugo Heuzard) -- GPR#948: the compiler now reports warnings-as-errors by prefixing +- #948: the compiler now reports warnings-as-errors by prefixing them with "Error (warning ..):", instead of "Warning ..:" and a trailing "Error: Some fatal warnings were triggered" message. (Valentin Gatien-Baron, review by Alain Frisch) -- GPR#1032: display the output of -dtimings as a hierarchy +- #1032: display the output of -dtimings as a hierarchy (Valentin Gatien-Baron, review by Gabriel Scherer) -- GPR#1114, GPR#1393, GPR#1429: refine the (ocamlc -config) information +- #1114, #1393, #1429: refine the (ocamlc -config) information on C compilers: the variables `{bytecode,native}_c_compiler` are deprecated (the distinction is now mostly meaningless) in favor of a single `c_compiler` variable combined with `ocaml{c,opt}_cflags` @@ -869,19 +1811,19 @@ OCaml 4.06.0 (3 Nov 2017): (Sébastien Hinderer, Jeremy Yallop, Gabriel Scherer, review by Adrien Nader and David Allsopp) -* GPR#1189: allow MSVC ports to use -l option in ocamlmklib +* #1189: allow MSVC ports to use -l option in ocamlmklib (David Allsopp) -- GPR#1332: fix ocamlc handling of "-output-complete-obj" +- #1332: fix ocamlc handling of "-output-complete-obj" (François Bobot) -- GPR#1336: -thread and -vmthread option information is propagated to +- #1336: -thread and -vmthread option information is propagated to PPX rewriters. (Jun Furuse, review by Alain Frisch) ### Code generation and optimizations: -- MPR#5324, GPR#375: An alternative Linear Scan register allocator for +- #5324, #375: An alternative Linear Scan register allocator for ocamlopt, activated with the -linscan command-line flag. This allocator represents a trade-off between worse generated code performance for higher compilation speed (especially interesting in @@ -889,344 +1831,344 @@ OCaml 4.06.0 (3 Nov 2017): (Marcell Fischbach and Benedikt Meurer, adapted by Nicolás Ojeda Bär, review by Nicolás Ojeda Bär and Alain Frisch) -- MPR#6927, GPR#988: On macOS, when compiling bytecode stubs, plugins, +- #6927, #988: On macOS, when compiling bytecode stubs, plugins, and shared libraries through -output-obj, generate dylibs instead of bundles. (whitequark) -- MPR#7447, GPR#995: incorrect code generation for nested recursive bindings +- #7447, #995: incorrect code generation for nested recursive bindings (Leo White and Jeremy Yallop, report by Stephen Dolan) -- MPR#7501, GPR#1089: Consider arrays of length zero as constants +- #7501, #1089: Consider arrays of length zero as constants when using Flambda. (Pierre Chambart, review by Mark Shinwell and Leo White) -- MPR#7531, GPR#1162: Erroneous code transformation at partial applications +- #7531, #1162: Erroneous code transformation at partial applications (Mark Shinwell) -- MPR#7614, GPR#1313: Ensure that inlining does not depend on the order +- #7614, #1313: Ensure that inlining does not depend on the order of symbols (flambda) (Leo White, Xavier Clerc, report by Alex, review by Gabriel Scherer and Pierre Chambart) -- MPR#7616, GPR#1339: don't warn on mutation of zero size blocks. +- #7616, #1339: don't warn on mutation of zero size blocks. (Leo White) -- MPR#7631, GPR#1355: "-linscan" option crashes ocamlopt +- #7631, #1355: "-linscan" option crashes ocamlopt (Xavier Clerc, report by Paul Steckler) -- MPR#7642, GPR#1411: ARM port: wrong register allocation for integer +- #7642, #1411: ARM port: wrong register allocation for integer multiply on ARMv4 and ARMv5; possible wrong register allocation for floating-point multiply and add on VFP and for floating-point negation and absolute value on soft FP emulation. (Xavier Leroy, report by Stéphane Glondu and Ximin Luo, review and additional sightings by Mark Shinwell) -* GPR#659: Remove support for SPARC native code generation +* #659: Remove support for SPARC native code generation (Mark Shinwell) -- GPR#850: Optimize away some physical equality +- #850: Optimize away some physical equality (Pierre Chambart, review by Mark Shinwell and Leo White) -- GPR#856: Register availability analysis +- #856: Register availability analysis (Mark Shinwell, Thomas Refis, review by Pierre Chambart) -- GPR#1143: tweaked several allocation functions in the runtime by +- #1143: tweaked several allocation functions in the runtime by checking for likely conditions before unlikely ones and eliminating some redundant checks. (Markus Mottl, review by Alain Frisch, Xavier Leroy, Gabriel Scherer, Mark Shinwell and Leo White) -- GPR#1183: compile curried functors to multi-argument functions +- #1183: compile curried functors to multi-argument functions earlier in the compiler pipeline; correctly propagate [@@inline] attributes on such functors; mark functor coercion veneers as stubs. (Mark Shinwell, review by Pierre Chambart and Leo White) -- GPR#1195: Merge functions based on partiality rather than +- #1195: Merge functions based on partiality rather than Parmatch.irrefutable. (Leo White, review by Thomas Refis, Alain Frisch and Gabriel Scherer) -- GPR#1215: Improve compilation of short-circuit operators +- #1215: Improve compilation of short-circuit operators (Leo White, review by Frédéric Bour and Mark Shinwell) -- GPR#1250: illegal ARM64 assembly code generated for large combined allocations +- #1250: illegal ARM64 assembly code generated for large combined allocations (report and initial fix by Steve Walk, review and final fix by Xavier Leroy) -- GPR#1271: Don't generate Ialloc instructions for closures that exceed +- #1271: Don't generate Ialloc instructions for closures that exceed Max_young_wosize; instead allocate them on the major heap. (Related - to GPR#1250.) + to #1250.) (Mark Shinwell) -- GPR#1294: Add a configure-time option to remove the dynamic float array +- #1294: Add a configure-time option to remove the dynamic float array optimization and add a floatarray type to let the user choose when to flatten float arrays. Note that float-only records are unchanged: they are still optimized by unboxing their fields. (Damien Doligez, review by Alain Frisch and Mark Shinwell) -- GPR#1304: Mark registers clobbered by PLT stubs as destroyed across +- #1304: Mark registers clobbered by PLT stubs as destroyed across allocations. (Mark Shinwell, Xavier Clerc, report and initial debugging by Valentin Gatien-Baron) -- GPR#1323: make sure that frame tables are generated in the data +- #1323: make sure that frame tables are generated in the data section and not in the read-only data section, as was the case before in the PPC and System-Z ports. This avoids relocations in the text segment of shared libraries and position-independent executables generated by ocamlopt. (Xavier Leroy, review by Mark Shinwell) -- GPR#1330: when generating dynamically-linkable code on AArch64, always +- #1330: when generating dynamically-linkable code on AArch64, always reference symbols (even locally-defined ones) through the GOT. (Mark Shinwell, review by Xavier Leroy) ### Tools: -- MPR#1956, GPR#973: tools/check-symbol-names checks for globally +- #8395, #973: tools/check-symbol-names checks for globally linked names not namespaced with caml_ (Stephen Dolan) -- MPR#6928, GPR#1103: ocamldoc, do not introduce an empty

in index.html +- #6928, #1103: ocamldoc, do not introduce an empty

in index.html when no -title has been provided (Pierre Boutillier) -- MPR#7048: ocamldoc, in -latex mode, don't escape Latin-1 accented letters +- #7048: ocamldoc, in -latex mode, don't escape Latin-1 accented letters (Xavier Leroy, report by Hugo Herbelin) -* MPR#7351: ocamldoc, use semantic tags rather than
tags in the html +* #7351: ocamldoc, use semantic tags rather than
tags in the html backend (Florian Angeletti, request and review by Daniel Bünzli ) -* MPR#7352, MPR#7353: ocamldoc, better paragraphs in html output +* #7352, #7353: ocamldoc, better paragraphs in html output (Florian Angeletti, request by Daniel Bünzli) -* MPR#7363, GPR#830: ocamldoc, start heading levels at {1 not {2 or {6. +* #7363, #830: ocamldoc, start heading levels at {1 not {2 or {6. This change modifies the mapping between ocamldoc heading level and html heading level, breaking custom css style for ocamldoc. (Florian Angeletti, request and review by Daniel Bünzli) -* MPR#7478, GPR#1037: ocamldoc, do not use as a module preamble documentation +* #7478, #1037: ocamldoc, do not use as a module preamble documentation comments that occur after the first module element. This change may break - existing documenation. In particular, module preambles must now come before + existing documentation. In particular, module preambles must now come before any `open` statement. (Florian Angeletti, review by David Allsopp and report by Daniel Bünzli) -- MPR#7521, GPR#1159: ocamldoc, end generated latex file with a new line +- #7521, #1159: ocamldoc, end generated latex file with a new line (Florian Angeletti) -- MPR#7575, GPR#1219: Switch compilers from -no-keep-locs +- #7575, #1219: Switch compilers from -no-keep-locs to -keep-locs by default: produced .cmi files will contain locations. This provides better error messages. Note that, as a consequence, .cmi digests now depend on the file path as given to the compiler. (Daniel Bünzli) -- MPR#7610, GPR#1346: caml.el (the Emacs editing mode) was cleaned up +- #7610, #1346: caml.el (the Emacs editing mode) was cleaned up and made compatible with Emacs 25. (Stefan Monnier, Christophe Troestler) -- MPR#7635, GPR#1383: ocamldoc, add an identifier to module +- #7635, #1383: ocamldoc, add an identifier to module and module type elements (Florian Angeletti, review by Yawar Amin and Gabriel Scherer) -- GPR#681, GPR#1426: Introduce ocamltest, a new test driver for the +- #681, #1426: Introduce ocamltest, a new test driver for the OCaml compiler testsuite (Sébastien Hinderer, review by Damien Doligez) -- GPR#1012: ocamlyacc, fix parsing of raw strings and nested comments, as well +- #1012: ocamlyacc, fix parsing of raw strings and nested comments, as well as the handling of ' characters in identifiers. (Demi Obenour) -- GPR#1045: ocamldep, add a "-shared" option to generate dependencies +- #1045: ocamldep, add a "-shared" option to generate dependencies for native plugin files (i.e. .cmxs files) (Florian Angeletti, suggestion by Sébastien Hinderer) -- GPR#1078: add a subcommand "-depend" to "ocamlc" and "ocamlopt", +- #1078: add a subcommand "-depend" to "ocamlc" and "ocamlopt", to behave as ocamldep. Should be used mostly to replace "ocamldep" in the "boot" directory to reduce its size in the future. (Fabrice Le Fessant) -- GPR#1036: ocamlcmt (tools/read_cmt) is installed, converts .cmt to .annot +- #1036: ocamlcmt (tools/read_cmt) is installed, converts .cmt to .annot (Fabrice Le Fessant) -- GPR#1180: Add support for recording numbers of direct and indirect +- #1180: Add support for recording numbers of direct and indirect calls over the lifetime of a program when using Spacetime profiling (Mark Shinwell) -- GPR#1457, ocamldoc: restore label for exception in the latex backend +- #1457, ocamldoc: restore label for exception in the latex backend (omitted since 4.04.0) (Florian Angeletti, review by Gabriel Scherer) ### Toplevel: -- MPR#7570: remove unusable -plugin option from the toplevel +- #7570: remove unusable -plugin option from the toplevel (Florian Angeletti) -- GPR#1041: -nostdlib no longer ignored by toplevel. +- #1041: -nostdlib no longer ignored by toplevel. (David Allsopp, review by Xavier Leroy) -- GPR#1231: improved printing of unicode texts in the toplevel, +- #1231: improved printing of unicode texts in the toplevel, unless OCAMLTOP_UTF_8 is set to false. (Florian Angeletti, review by Daniel Bünzli, Xavier Leroy and Gabriel Scherer) -- GPR#1688: Fix printing of -0. +- #1688: Fix printing of -0. (Nicolás Ojeda Bär, review by Jérémie Dimino) ### Runtime system: -* MPR#3771, GPR#153, GPR#1200, GPR#1357, GPR#1362, GPR#1363, GPR#1369, GPR#1398, - GPR#1446, GPR#1448: Unicode support for the Windows runtime. +* #3771, #153, #1200, #1357, #1362, #1363, #1369, #1398, + #1446, #1448: Unicode support for the Windows runtime. (ygrek, Nicolás Ojeda Bär, review by Alain Frisch, David Allsopp, Damien Doligez) -* MPR#7594, GPR#1274, GPR#1368: String_val now returns 'const char*', not +* #7594, #1274, #1368: String_val now returns 'const char*', not 'char*' when -safe-string is enabled at configure time. New macro Bytes_val for accessing bytes values. (Jeremy Yallop, reviews by Mark Shinwell and Xavier Leroy) -- GPR#71: The runtime can now be shut down gracefully by means of the new +- #71: The runtime can now be shut down gracefully by means of the new caml_shutdown and caml_startup_pooled functions. The new 'c' flag in OCAMLRUNPARAM enables shutting the runtime properly on process exit. (Max Mouratov, review and discussion by Damien Doligez, Gabriel Scherer, Mark Shinwell, Thomas Braibant, Stephen Dolan, Pierre Chambart, François Bobot, Jacques Garrigue, David Allsopp, and Alain Frisch) -- GPR#938, GPR#1170, GPR#1289: Stack overflow detection on 64-bit Windows +- #938, #1170, #1289: Stack overflow detection on 64-bit Windows (Olivier Andrieu, tweaked by David Allsopp) -- GPR#1070, GPR#1295: enable gcc typechecking for caml_alloc_sprintf, +- #1070, #1295: enable gcc typechecking for caml_alloc_sprintf, caml_gc_message. Make caml_gc_message a variadic function. Fix many caml_gc_message format strings. (Olivier Andrieu, review and 32bit fix by David Allsopp) -- GPR#1073: Remove statically allocated compare stack. +- #1073: Remove statically allocated compare stack. (Stephen Dolan) -- GPR#1086: in Sys.getcwd, just fail instead of calling getwd() +- #1086: in Sys.getcwd, just fail instead of calling getwd() if HAS_GETCWD is not set. (Report and first fix by Sebastian Markbåge, final fix by Xavier Leroy, review by Mark Shinwell) -- GPR#1269: Remove 50ms delay at exit for programs using threads +- #1269: Remove 50ms delay at exit for programs using threads (Valentin Gatien-Baron, review by Stephen Dolan) -* GPR#1309: open files with O_CLOEXEC (or equivalent) in caml_sys_open, thus +* #1309: open files with O_CLOEXEC (or equivalent) in caml_sys_open, thus unifying the semantics between Unix and Windows and also eliminating race condition on Unix. (David Allsopp, report by Andreas Hauptmann) -- GPR#1326: Enable use of CFI directives in AArch64 and ARM runtime +- #1326: Enable use of CFI directives in AArch64 and ARM runtime systems' assembly code (asmrun/arm64.S). Add CFI directives to enable unwinding through [caml_c_call] and [caml_call_gc] with correct termination of unwinding at [main]. (Mark Shinwell, review by Xavier Leroy and Gabriel Scherer, with thanks to Daniel Bünzli and Fu Yong Quah for testing) -- GPR#1338: Add "-g" for bytecode runtime system compilation +- #1338: Add "-g" for bytecode runtime system compilation (Mark Shinwell) -* GPR#1416, GPR#1444: switch the Windows 10 Console to UTF-8 encoding. +* #1416, #1444: switch the Windows 10 Console to UTF-8 encoding. (David Allsopp, reviews by Nicolás Ojeda Bär and Xavier Leroy) ### Manual and documentation: -- MPR#6548: remove obsolete limitation in the description of private +- #6548: remove obsolete limitation in the description of private type abbreviations (Florian Angeletti, suggestion by Leo White) -- MPR#6676, GPR#1110: move record notation to tutorial +- #6676, #1110: move record notation to tutorial (Florian Angeletti, review by Gabriel Scherer) -- MPR#6676, GPR#1112: move local opens to tutorial +- #6676, #1112: move local opens to tutorial (Florian Angeletti) -- MPR#6676, GPR#1153: move overriding class definitions to reference +- #6676, #1153: move overriding class definitions to reference manual and tutorial (Florian Angeletti) -- MPR#6709: document the associativity and precedence level of +- #6709: document the associativity and precedence level of pervasive operators (Florian Angeletti, review by David Allsopp) -- MPR#7254, GPR#1096: Rudimentary documentation of ocamlnat +- #7254, #1096: Rudimentary documentation of ocamlnat (Mark Shinwell) -- MPR#7281, GPR#1259: fix .TH macros in generated manpages +- #7281, #1259: fix .TH macros in generated manpages (Olaf Hering) -- MPR#7507: Align the description of the printf conversion +- #7507: Align the description of the printf conversion specification "%g" with the ISO C90 description. (Florian Angeletti, suggestion by Armaël Guéneau) -- MPR#7551, GPR#1194 : make the final ";;" potentially optional in +- #7551, #1194 : make the final ";;" potentially optional in caml_example (Florian Angeletti, review and suggestion by Gabriel Scherer) -- MPR#7588, GPR#1291: make format documentation predictable +- #7588, #1291: make format documentation predictable (Florian Angeletti, review by Gabriel Radanne) -- MPR#7604: Minor Ephemeron documentation fixes +- #7604: Minor Ephemeron documentation fixes (Miod Vallat, review by Florian Angeletti) -- GPR#594: New chapter on polymorphism troubles: +- #594: New chapter on polymorphism troubles: weakly polymorphic types, polymorphic recursion,and higher-ranked polymorphism. (Florian Angeletti, review by Damien Doligez, Gabriel Scherer, and Gerd Stolpmann) -- GPR#1187: Minimal documentation for compiler plugins +- #1187: Minimal documentation for compiler plugins (Florian Angeletti) -- GPR#1202: Fix Typos in comments as well as basic grammar errors. +- #1202: Fix Typos in comments as well as basic grammar errors. (JP Rodi, review and suggestions by David Allsopp, Max Mouratov, Florian Angeletti, Xavier Leroy, Mark Shinwell and Damien Doligez) -- GPR#1220: Fix "-keep-docs" option in ocamlopt manpage +- #1220: Fix "-keep-docs" option in ocamlopt manpage (Etienne Millon) ### Compiler distribution build system: -- MPR#6373, GPR#1093: Suppress trigraph warnings from macOS assembler +- #6373, #1093: Suppress trigraph warnings from macOS assembler (Mark Shinwell) -- MPR#7639, GPR#1371: fix configure script for correct detection of +- #7639, #1371: fix configure script for correct detection of int64 alignment on Mac OS X 10.13 (High Sierra) and above; fix bug in configure script relating to such detection. (Mark Shinwell, report by John Whitington, review by Xavier Leroy) -- GPR#558: enable shared library and natdynlink support on more Linux +- #558: enable shared library and natdynlink support on more Linux platforms (Felix Janda, Mark Shinwell) -* GPR#1104: remove support for the NeXTStep platform +* #1104: remove support for the NeXTStep platform (Sébastien Hinderer) -- GPR#1130: enable detection of IBM XL C compiler (one need to run configure +- #1130: enable detection of IBM XL C compiler (one need to run configure with "-cc "). Enable shared library support for bytecode executables on AIX/xlc (tested on AIX 7.1, XL C 12). To enable 64-bit, run both "configure" and "make world" with OBJECT_MODE=64. (Konstantin Romanov, Enrique Naudon) -- GPR#1203: speed up the manual build by using ocamldoc.opt +- #1203: speed up the manual build by using ocamldoc.opt (Gabriel Scherer, review by Florian Angeletti) -- GPR#1214: harden config/Makefile against '#' characters in PREFIX +- #1214: harden config/Makefile against '#' characters in PREFIX (Gabriel Scherer, review by David Allsopp and Damien Doligez) -- GPR#1216: move Compplugin and friends from BYTECOMP to COMP +- #1216: move Compplugin and friends from BYTECOMP to COMP (Leo White, review by Mark Shinwell) -* GPR#1242: disable C plugins loading by default +* #1242: disable C plugins loading by default (Alexey Egorov) -- GPR#1275: correct configure test for Spacetime availability +- #1275: correct configure test for Spacetime availability (Mark Shinwell) -- GPR#1278: discover presence of during configure for afl runtime +- #1278: discover presence of during configure for afl runtime (Hannes Mehnert) -- GPR#1386: provide configure-time options to fine-tune the safe-string - options and default settings changed by GPR#1525. +- #1386: provide configure-time options to fine-tune the safe-string + options and default settings changed by #1252. The previous configure option -safe-string is now renamed -force-safe-string. @@ -1235,32 +2177,32 @@ OCaml 4.06.0 (3 Nov 2017): immutable strings (this disables the per-file, compile-time -unsafe-string option). The new default-(un)safe-string options let you set the default choice for the per-file compile-time - option. (The new GPR#1252 behavior corresponds to having + option. (The new #1252 behavior corresponds to having -default-safe-string, while 4.05 and older had -default-unsafe-string). - (Gabriel Scherer, review by Jacques-Pascal Deplaix and Damien Doligez) + (Gabriel Scherer, review by Kate Deplaix and Damien Doligez) -- GPR#1409: Fix to enable NetBSD/powerpc to work. +- #1409: Fix to enable NetBSD/powerpc to work. (Håvard Eidnes) ### Internal/compiler-libs changes: -- MPR#6826, GPR#828, GPR#834: improve compilation time for open +- #6826, #828, #834: improve compilation time for open (Alain Frisch, review by Frédéric Bour and Jacques Garrigue) -- MPR#7127, GPR#454, GPR#1058: in toplevel, print bytes and strip +- #7127, #454, #1058: in toplevel, print bytes and strip strings longer than the size specified by the "print_length" directive (Fabrice Le Fessant, initial PR by Junsong Li) -- GPR#406: remove polymorphic comparison for Types.constructor_tag in compiler +- #406: remove polymorphic comparison for Types.constructor_tag in compiler (Dwight Guth, review by Gabriel Radanne, Damien Doligez, Gabriel Scherer, Pierre Chambart, Mark Shinwell) -- GRP#1119: Change Set (private) type to inline records. +- #1119: Change Set (private) type to inline records. (Albin Coquereau) -* GPR#1127: move config/{m,s}.h to byterun/caml and install them. +* #1127: move config/{m,s}.h to byterun/caml and install them. User code should not have to include them directly since they are included by other header files. Previously {m,s}.h were not installed but they were substituted into @@ -1270,140 +2212,140 @@ OCaml 4.06.0 (3 Nov 2017): to try to grep those files if they exist. (Sébastien Hinderer) -- GPR#1281: avoid formatter flushes inside exported printers in Location +- #1281: avoid formatter flushes inside exported printers in Location (Florian Angeletti, review by Gabriel Scherer) -### Bug fixes +### Bug fixes: -- MPR#5927: Type equality broken for conjunctive polymorphic variant tags +- #5927: Type equality broken for conjunctive polymorphic variant tags (Jacques Garrigue, report by Leo White) -- MPR#6329, GPR#1437: Introduce padding word before "data_end" symbols +- #6329, #1437: Introduce padding word before "data_end" symbols to ensure page table tests work correctly on an immediately preceding block of zero size. (Mark Shinwell, review by Xavier Leroy) -- MPR#6587: only elide Pervasives from printed type paths in unambiguous context +- #6587: only elide Pervasives from printed type paths in unambiguous context (Florian Angeletti and Jacques Garrigue) -- MPR#6934: nonrec misbehaves with GADTs +- #6934: nonrec misbehaves with GADTs (Jacques Garrigue, report by Markus Mottl) -- MPR#7070, GPR#1139: Unexported values can cause non-generalisable variables +- #7070, #1139: Unexported values can cause non-generalisable variables error (Leo White) -- MPR#7261: Warn on type constraints in GADT declarations +- #7261: Warn on type constraints in GADT declarations (Jacques Garrigue, report by Fabrice Le Botlan) -- MPR#7321: Private type in signature clashes with type definition via +- #7321: Private type in signature clashes with type definition via functor instantiation (Jacques Garrigue, report by Markus Mottl) -- MPR#7372, GPR#834: fix type-checker bug with GADT and inline records +- #7372, #834: fix type-checker bug with GADT and inline records (Alain Frisch, review by Frédéric Bour and Jacques Garrigue) -- MPR#7344: Inconsistent behavior with type annotations on let +- #7344: Inconsistent behavior with type annotations on let (Jacques Garrigue, report by Leo White) -- MPR#7468: possible GC problem in caml_alloc_sprintf +- #7468: possible GC problem in caml_alloc_sprintf (Xavier Leroy, discovery by Olivier Andrieu) -- MPR#7496: Fixed conjunctive polymorphic variant tags do not unify +- #7496: Fixed conjunctive polymorphic variant tags do not unify with themselves (Jacques Garrigue, report by Leo White) -- MPR#7506: pprintast ignores attributes in tails of a list +- #7506: pprintast ignores attributes in tails of a list (Alain Frisch, report by Kenichi Asai and Gabriel Scherer) -- MPR#7513: List.compare_length_with mishandles negative numbers / overflow +- #7513: List.compare_length_with mishandles negative numbers / overflow (Fabrice Le Fessant, report by Jeremy Yallop) -- MPR#7519: Incorrect rejection of program due to faux scope escape +- #7519: Incorrect rejection of program due to faux scope escape (Jacques Garrigue, report by Markus Mottl) -- MPR#7540, GPR#1179: Fixed setting of breakpoints within packed modules +- #7540, #1179: Fixed setting of breakpoints within packed modules for ocamldebug (Hugo Herbelin, review by Gabriel Scherer, Damien Doligez) -- MPR#7543: short-paths printtyp can fail on packed type error messages +- #7543: short-paths printtyp can fail on packed type error messages (Florian Angeletti) -- MPR#7553, GPR#1191: Prevent repeated warnings with recursive modules. +- #7553, #1191: Prevent repeated warnings with recursive modules. (Leo White, review by Josh Berdine and Alain Frisch) -- MPR#7563, GPR#1210: code generation bug when a module alias and +- #7563, #1210: code generation bug when a module alias and an extension constructor have the same name in the same module (Gabriel Scherer, report by Manuel Fähndrich, review by Jacques Garrigue and Leo White) -- MPR#7591, GPR#1257: on x86-64, frame table is not 8-aligned +- #7591, #1257: on x86-64, frame table is not 8-aligned (Xavier Leroy, report by Mantis user "voglerr", review by Gabriel Scherer) -- MPR#7601, GPR#1320: It seems like a hidden non-generalized type variable +- #7601, #1320: It seems like a hidden non-generalized type variable remains in some inferred signatures, which leads to strange errors (Jacques Garrigue, report by Mandrikin) -- MPR#7609: use-after-free memory corruption if a program debugged +- #7609: use-after-free memory corruption if a program debugged under ocamldebug calls Pervasives.flush_all (Xavier Leroy, report by Paul Steckler, review by Gabriel Scherer) -- MPR#7612, GPR#1345: afl-instrumentation bugfix for classes. +- #7612, #1345: afl-instrumentation bugfix for classes. (Stephen Dolan, review by Gabriel Scherer and David Allsopp) -- MPR#7617, MPR#7618, GPR#1318: Ambiguous (mistakenly) type escaping the +- #7617, #7618, #1318: Ambiguous (mistakenly) type escaping the scope of its equation (Jacques Garrigue, report by Thomas Refis) -- MPR#7619, GPR#1387: position of the optional last semi-column not included +- #7619, #1387: position of the optional last semi-column not included in the position of the expression (same behavior as for lists) (Christophe Raffalli, review by Gabriel Scherer) -- MPR#7638: in the Windows Mingw64 port, multithreaded programs compiled +- #7638: in the Windows Mingw64 port, multithreaded programs compiled to bytecode could crash when raising an exception from C code. This looks like a Mingw64 issue, which we work around with GCC builtins. (Xavier Leroy) -- MPR#7656, GPR#1423: false 'unused type/constructor/value' alarms +- #7656, #1423: false 'unused type/constructor/value' alarms in the 4.06 development version - (Alain Frisch, review by Jacques Garrigue, report by Jacques-Pascal Deplaix) + (Alain Frisch, review by Jacques Garrigue, report by Kate Deplaix) -- MPR#7657, GPR#1424: ensures correct call-by-value semantics when +- #7657, #1424: ensures correct call-by-value semantics when eta-expanding functions to eliminate optional arguments (Alain Frisch, report by sliquister, review by Leo White and Jacques Garrigue) -- MPR#7658, GPR#1439: Fix Spacetime runtime system compilation with +- #7658, #1439: Fix Spacetime runtime system compilation with -force-safe-string (Mark Shinwell, report by Christoph Spiel, review by Gabriel Scherer) -- GPR#1155: Fix a race condition with WAIT_NOHANG on Windows +- #1155: Fix a race condition with WAIT_NOHANG on Windows (Jérémie Dimino and David Allsopp) -- GPR#1199: Pretty-printing formatting cleanup in pprintast +- #1199: Pretty-printing formatting cleanup in pprintast (Ethan Aubin, suggestion by Gabriel Scherer, review by David Allsopp, Florian Angeletti, and Gabriel Scherer) -- GPR#1223: Fix corruption of the environment when using -short-paths +- #1223: Fix corruption of the environment when using -short-paths with the toplevel. (Leo White, review by Alain Frisch) -- GPR#1243: Fix pprintast for #... infix operators +- #1243: Fix pprintast for #... infix operators (Alain Frisch, report by Omar Chebib) -- GPR#1324: ensure that flambda warning are printed only once +- #1324: ensure that flambda warning are printed only once (Xavier Clerc) -- GPR#1329: Prevent recursive polymorphic variant names +- #1329: Prevent recursive polymorphic variant names (Jacques Garrigue, fix suggested by Leo White) -- GPR#1308: Only treat pure patterns as inactive +- #1308: Only treat pure patterns as inactive (Leo White, review by Alain Frisch and Gabriel Scherer) -- GPR#1390: fix the [@@unboxed] type check to accept parametrized types +- #1390: fix the [@@unboxed] type check to accept parametrized types (Leo White, review by Damien Doligez) -- GPR#1407: Fix raw_spacetime_lib +- #1407: Fix raw_spacetime_lib (Leo White, review by Gabriel Scherer and Damien Doligez) OCaml 4.05.0 (13 Jul 2017): @@ -1415,37 +2357,37 @@ OCaml 4.05.0 (13 Jul 2017): ### Code generation and optimizations: -- MPR#7201, GPR#954: Correct wrong optimisation of "0 / " +- #7201, #954: Correct wrong optimisation of "0 / " and "0 mod " in the case when was a non-constant evaluating to zero (Mark Shinwell, review by Gabriel Scherer, Leo White and Xavier Leroy) -- MPR#7357, GPR#832: Improve compilation time for toplevel +- #7357, #832: Improve compilation time for toplevel include(struct ... end : sig ... end) (Alain Frisch, report by Hongbo Zhang, review by Jacques Garrigue) -- MPR#7533, GPR#1173: Correctly perform side effects for certain +- #7533, #1173: Correctly perform side effects for certain cases of "/" and "mod" (Mark Shinwell, report by Jan Mitgaard) -- GPR#504: Instrumentation support for fuzzing with afl-fuzz. +- #504: Instrumentation support for fuzzing with afl-fuzz. (Stephen Dolan, review by Alain Frisch, Pierre Chambart, Mark Shinwell, Gabriel Scherer and Damien Doligez) -- GPR#863, GPR#1068, GPR#1069: Optimise matches with constant +- #863, #1068, #1069: Optimise matches with constant results to lookup tables. (Stephen Dolan, review by Gabriel Scherer, Pierre Chambart, Mark Shinwell, and bug report by Gabriel Scherer) -- GPR#1150: Fix typo in arm64 assembler directives +- #1150: Fix typo in arm64 assembler directives (KC Sivaramakrishnan) ### Runtime system: -- MPR#385, GPR#953: Add caml_startup_exn +- #2784, #953: Add caml_startup_exn (Mark Shinwell) -- MPR#7423, GPR#946: expose new exception-raising functions +- #7423, #946: expose new exception-raising functions `void caml_{failwith,invalid_argument}_value(value msg)` in addition to `void caml_{failwith,invalid_argument}(char const *msg)`. @@ -1454,23 +2396,23 @@ OCaml 4.05.0 (13 Jul 2017): passed to the new functions are handled by the garbage collector. (Gabriel Scherer, review by Mark Shinwell, request by Immanuel Litzroth) -- MPR#7557, GPR#1213: More security for getenv +- #7557, #1213: More security for getenv (Damien Doligez, reports by Seth Arnold and Eric Milliken, review by Xavier Leroy, David Allsopp, Stephen Dolan, Hannes Mehnert) -- GPR#795: remove 256-character limitation on Sys.executable_name +- #795: remove 256-character limitation on Sys.executable_name (Xavier Leroy) -- GPR#891: Use -fno-builtin-memcmp when building runtime with gcc. +- #891: Use -fno-builtin-memcmp when building runtime with gcc. (Leo White) ### Type system: -- MPR#6608, GPR#901: unify record types when overriding all fields +- #6608, #901: unify record types when overriding all fields (Tadeu Zagallo and Gabriel Scherer, report by Jeremy Yallop, review by David Allsopp, Jacques Garrigue) -* MPR#7414, GPR#929: Soundness bug with non-generalized type variables and +* #7414, #929: Soundness bug with non-generalized type variables and functors. (compatibility: some code using module-global mutable state will fail at compile-time and is fixed by adding extra annotations; @@ -1479,7 +2421,7 @@ OCaml 4.05.0 (13 Jul 2017): ### Compiler user-interface and warnings: -- MPR#7050, GPR#748 GPR#843 GPR#864: new `-args/-args0 ` parameters to +- #7050, #748 #843 #864: new `-args/-args0 ` parameters to provide extra command-line arguments in a file -- see documentation. User programs may implement similar options using the new `Expand` constructor of the `Arg` module. @@ -1487,60 +2429,60 @@ OCaml 4.05.0 (13 Jul 2017): and Damien Doligez, discussion with Alain Frisch and Xavier Leroy, feature request from the Coq team) -- MPR#7137, GPR#960: "-open" command line flag now accepts +- #7137, #960: "-open" command line flag now accepts a module path (not a module name) (Arseniy Alekseyev and Leo White) -- MPR#7172, GPR#970: add extra (ocamlc -config) options +- #7172, #970: add extra (ocamlc -config) options int_size, word_size, ext_exe (Gabriel Scherer, request by Daniel Bünzli) -- MPR#7315, GPR#736: refine some error locations +- #7315, #736: refine some error locations (Gabriel Scherer and Alain Frisch, report by Matej Košík) -- MPR#7473, GPR#1025: perform proper globbing for command-line arguments on +- #7473, #1025: perform proper globbing for command-line arguments on Windows (Jonathan Protzenko) -- MPR#7479: make sure "ocamlc -pack" is only given .cmo and .cmi files, +- #7479: make sure "ocamlc -pack" is only given .cmo and .cmi files, and that "ocamlopt -pack" is only given .cmx and .cmi files. (Xavier Leroy) -- GPR#796: allow compiler plugins to declare their own arguments. +- #796: allow compiler plugins to declare their own arguments. (Fabrice Le Fessant) -- GPR#829: better error when opening a module aliased to a functor +- #829: better error when opening a module aliased to a functor (Alain Frisch) -- GPR#911: ocamlc/ocamlopt do not pass warnings-related options to C +- #911: ocamlc/ocamlopt do not pass warnings-related options to C compiler when called to compile third-party C source files (Sébastien Hinderer, review by Adrien Nader and David Allsopp) -- GPR#915: fix -dsource (pprintast.ml) bugs +- #915: fix -dsource (pprintast.ml) bugs (Runhang Li, review by Alain Frisch) -* GPR#933: ocamlopt -p now reports an error on platforms that do not +* #933: ocamlopt -p now reports an error on platforms that do not support profiling with gprof; dummy profiling libraries are no longer installed on such platforms. This can be tested with ocamlopt -config (Sébastien Hinderer) -- GPR#1009: "ocamlc -c -linkall" and "ocamlopt -c -linkall" can now be used +- #1009: "ocamlc -c -linkall" and "ocamlopt -c -linkall" can now be used to set the "always link" flag on individual compilation units. This controls linking with finer granularity than "-a -linkall", which sets the "always link" flag on all units of the given library. (Xavier Leroy) -- GPR#1015: add option "-plugin PLUGIN" to ocamldep too. Use compilerlibs +- #1015: add option "-plugin PLUGIN" to ocamldep too. Use compilerlibs to build ocamldep. Add option "-depend" to ocamlc/ocamlopt to behave as ocamldep. Remove any use of ocamldep to build the distribution. (Fabrice Le Fessant) -- GPR#1027: various improvements to -dtimings, mostly including time +- #1027: various improvements to -dtimings, mostly including time spent in subprocesses like preprocessors (Valentin Gatien-Baron, review by Gabriel Scherer) -- GPR#1098: the compiler now takes the boolean "OCAML_COLOR" environment +- #1098: the compiler now takes the boolean "OCAML_COLOR" environment variable into account if "-color" is not provided. This allows users to override the default behaviour without modifying invocations of ocaml manually. @@ -1549,122 +2491,122 @@ OCaml 4.05.0 (13 Jul 2017): ### Standard library: -- MPR#6975, GPR#902: Truncate function added to stdlib Buffer module +- #6975, #902: Truncate function added to stdlib Buffer module (Dhruv Makwana, review by Alain Frisch and Gabriel Scherer) -- MPR#7279, GPR#710: `Weak.get_copy` `Ephemeron.*_copy` doesn't copy +- #7279, #710: `Weak.get_copy` `Ephemeron.*_copy` doesn't copy custom blocks anymore (François Bobot, Alain Frisch, bug reported by Martin R. Neuhäußer, review by Thomas Braibant and Damien Doligez) -* MPR#7500, GPR#1081: Remove Uchar.dump +* #7500, #1081: Remove Uchar.dump (Daniel Bünzli) -- GPR#760: Add a functions List.compare_lengths and +- #760: Add a functions List.compare_lengths and List.compare_length_with to avoid full list length computations (Fabrice Le Fessant, review by Leo White, Josh Berdine and Gabriel Scherer) -- GPR#778: Arg: added option Expand that allows to expand a string +- #778: Arg: added option Expand that allows to expand a string argument to a string array of new arguments (Bernhard Schommer, review by Gabriel Scherer and Jérémie Dimino) -- GPR#849: Expose a Spacetime.enabled value +- #849: Expose a Spacetime.enabled value (Leo White) -- GPR#885: Option-returning variants of stdlib functions +- #885: Option-returning variants of stdlib functions (Alain Frisch, review by David Allsopp and Bart Jacobs) -- GPR#869: Add find_first, find_first_opt, find_last, find_last_opt to +- #869: Add find_first, find_first_opt, find_last, find_last_opt to maps and sets. Find the first or last binding or element satisfying a monotonic predicate. (Gabriel de Perthuis, with contributions from Alain Frisch, review by Hezekiah M. Carty and Simon Cruanes, initial report by Gerd Stolpmann) -- GPR#875: Add missing functions to ArrayLabels, BytesLabels, +- #875: Add missing functions to ArrayLabels, BytesLabels, ListLabels, MoreLabels, StringLabels so they are compatible with non-labeled counterparts. Also add missing @@ocaml.deprecated attributes in StringLabels and BytesLabels. (Roma Sokolov, review by Gabriel Scherer, Jacques Garrigue, Gabriel Radanne, Alain Frisch) -- GPR#999: Arg, do not repeat the usage message thrice when reporting an error +- #999: Arg, do not repeat the usage message thrice when reporting an error (this was a regression in 4.03) (Florian Angeletti, review by Gabriel Scherer) -- GPR#1042: Fix escaping of command-line arguments in +- #1042: Fix escaping of command-line arguments in Unix.create_process{,_env} under Windows. Arguments with tabs should now be received verbatim by the child process. (Nicolás Ojeda Bär, Andreas Hauptmann review by Xavier Leroy) ### Debugging and profiling: -- MPR#7258: ocamldebug's "install_printer" command had problems with +- #7258: ocamldebug's "install_printer" command had problems with module aliases (Xavier Leroy) -- GPR#378: Add [Printexc.raise_with_backtrace] to raise an exception using +- #378: Add [Printexc.raise_with_backtrace] to raise an exception using an explicit backtrace (François Bobot, review by Gabriel Scherer, Xavier Leroy, Damien Doligez, Frédéric Bour) ### Manual and documentation: -- MPR#6597, GPR#1030: add forward references to language extensions +- #6597, #1030: add forward references to language extensions that extend non-terminal symbols in the language reference section. (Florian Angeletti, review by Gabriel Scherer) -- MPR#7497, GPR#1095: manual, enable numbering for table of contents +- #7497, #1095: manual, enable numbering for table of contents (Florian Angeletti, request by Daniel Bünzli) -- MPR#7539, GPR#1181: manual, update dead links in ocamldoc chapter +- #7539, #1181: manual, update dead links in ocamldoc chapter (Florian Angeletti) -- GPR#633: manpage and manual documentation for the `-opaque` option +- #633: manpage and manual documentation for the `-opaque` option (Konstantin Romanov, Gabriel Scherer, review by Mark Shinwell) -- GPR#751, GPR#925: add a HACKING.adoc file to contain various +- #751, #925: add a HACKING.adoc file to contain various tips and tricks for people hacking on the repository. See also CONTRIBUTING.md for advice on sending contributions upstream. (Gabriel Scherer and Gabriel Radanne, review by David Allsopp, inspired by John Whitington) -- GPR#916: new tool lintapidiff, use it to update the manual with +- #916: new tool lintapidiff, use it to update the manual with @since annotations for API changes introduced between 4.00-4.05. (Edwin Török, review by Gabriel Scherer, discussion with Alain Frisch, David Allsopp, Sébastien Hinderer, Damien Doligez and Xavier Leroy) -- GPR#939: activate the caml_example environment in the language +- #939: activate the caml_example environment in the language extensions section of the manual. Convert some existing code examples to this format. (Florian Angeletti) -- GPR#1082: clarify that the use of quoted string for preprocessed +- #1082: clarify that the use of quoted string for preprocessed foreign quotations still requires the use of an extension node [%foo ...] to mark non-standard interpretation. - (Gabriel Scherer, request by Matthew Wahab in GPR#1066, + (Gabriel Scherer, request by Matthew Wahab in #1066, review by Florian Angeletti) ### Other libraries: -- MPR#7158: Event.sync, Mutex.create, Condition.create cause too many GCs. +- #7158: Event.sync, Mutex.create, Condition.create cause too many GCs. The fix is to no longer consider mutexes and condition variables as rare kernel resources. (Xavier Leroy) -- MPR#7264: document the different behaviors of Unix.lockf under POSIX +- #7264: document the different behaviors of Unix.lockf under POSIX and under Win32. (Xavier Leroy, report by David Allsopp) -- MPR#7339, GPR#787: Support the '0 dimension' case for bigarrays +- #7339, #787: Support the '0 dimension' case for bigarrays (see Bigarray documentation) (Laurent Mazare, review by Gabriel Scherer, Alain Frisch and Hezekiah M. Carty) -* MPR#7342, GPR#797: fix Unix.read on pipes with no data left on Windows +* #7342, #797: fix Unix.read on pipes with no data left on Windows it previously raised an EPIPE error, it now returns 0 like other OSes (Jonathan Protzenko, review by Andreas Hauptmann and Damien Doligez) -- GPR#650: in the Unix library, add `?cloexec:bool` optional arguments to +- #650: in the Unix library, add `?cloexec:bool` optional arguments to functions that create file descriptors (`dup`, `dup2`, `pipe`, `socket`, `socketpair`, `accept`). Implement these optional arguments in the most atomic manner provided by the operating system to set (or clear) @@ -1675,36 +2617,36 @@ OCaml 4.05.0 (13 Jul 2017): (Xavier Leroy, review by Mark Shinwell, David Allsopp and Alain Frisch, request by Romain Beauxis) -- GPR#996: correctly update caml_top_of_stack in systhreads +- #996: correctly update caml_top_of_stack in systhreads (Fabrice Le Fessant) -- GPR#997, GPR#1077: Deprecate Bigarray.*.map_file and add Unix.map_file as a +- #997, #1077: Deprecate Bigarray.*.map_file and add Unix.map_file as a first step towards moving Bigarray to the stdlib (Jérémie Dimino and Xavier Leroy) ### Toplevel: -- MPR#7060, GPR#1035: Print exceptions in installed custom printers +- #7060, #1035: Print exceptions in installed custom printers (Tadeu Zagallo, review by David Allsopp) ### Tools: -- MPR#5163: ocamlobjinfo, dump globals defined by bytecode executables +- #5163: ocamlobjinfo, dump globals defined by bytecode executables (Stéphane Glondu) -- MPR#7333: ocamldoc, use the first sentence of text file as +- #7333: ocamldoc, use the first sentence of text file as a short description in overviews. (Florian Angeletti) -- GPR#848: ocamldoc, escape link targets in HTML output +- #848: ocamldoc, escape link targets in HTML output (Etienne Millon, review by Gabriel Scherer, Florian Angeletti and Daniel Bünzli) -- GPR#986: ocamldoc, use relative paths in error message +- #986: ocamldoc, use relative paths in error message to solve ocamlbuild+doc usability issue (ocaml/ocamlbuild#79) (Gabriel Scherer, review by Florian Angeletti, discussion with Daniel Bünzli) -- GPR#1017: ocamldoc, add an option to detect code fragments that could be +- #1017: ocamldoc, add an option to detect code fragments that could be transformed into a cross-reference to a known element. (Florian Angeletti, review and suggestion by David Allsopp) @@ -1713,66 +2655,66 @@ OCaml 4.05.0 (13 Jul 2017): ### Compiler distribution build system: -- MPR#7377: remove -std=gnu99 for newer gcc versions +- #7377: remove -std=gnu99 for newer gcc versions (Damien Doligez, report by ygrek) -- MPR#7452, GPR#1228: tweak GCC options to try to avoid the +- #7452, #1228: tweak GCC options to try to avoid the Skylake/Kaby lake bug (Damien Doligez, review by David Allsopp, Xavier Leroy and Mark Shinwell) -- GPR#693: fail on unexpected errors or warnings within caml_example +- #693: fail on unexpected errors or warnings within caml_example environment. (Florian Angeletti) -- GPR#803: new ocamllex-based tool to extract bytecode compiler +- #803: new ocamllex-based tool to extract bytecode compiler opcode information from C headers. (Nicolás Ojeda Bär) -- GPR#827: install missing mli and cmti files, new make target +- #827: install missing mli and cmti files, new make target install-compiler-sources for installation of compiler-libs ml files (Hendrik Tews) -- GPR#887: allow -with-frame-pointers if clang is used as compiler on Linux +- #887: allow -with-frame-pointers if clang is used as compiler on Linux (Bernhard Schommer) -- GPR#898: fix locale-dependence of primitive list order, +- #898: fix locale-dependence of primitive list order, detected through reproducible-builds.org. (Hannes Mehnert, review by Gabriel Scherer and Ximin Luo) -- GPR#907: Remove unused variable from the build system +- #907: Remove unused variable from the build system (Sébastien Hinderer, review by whitequark, Gabriel Scherer, Adrien Nader) -- GPR#911: Clarify the use of C compiler related variables in the build system. +- #911: Clarify the use of C compiler related variables in the build system. (Sébastien Hinderer, review by Adrien Nader, Alain Frisch, David Allsopp) -- GPR#919: use clang as preprocessor assembler if clang is used as compiler +- #919: use clang as preprocessor assembler if clang is used as compiler (Bernhard Schommer) -- GPR#927: improve the detection of hashbang support in the configure script +- #927: improve the detection of hashbang support in the configure script (Armaël Guéneau) -- GPR#932: install ocaml{c,lex}->ocaml{c,lex}.byte symlink correctly +- #932: install ocaml{c,lex}->ocaml{c,lex}.byte symlink correctly when the opt target is built but opt.opt target is not. (whitequark, review by Gabriel Scherer) -- GPR#935: allow build in Android's termux +- #935: allow build in Android's termux (ygrek, review by Gabriel Scherer) -- GPR#984: Fix compilation of compiler distribution when Spacetime +- #984: Fix compilation of compiler distribution when Spacetime enabled (Mark Shinwell) -- GPR#991: On Windows, fix installation when native compiler is not +- #991: On Windows, fix installation when native compiler is not built (Sébastien Hinderer, review by David Allsopp) -- GPR#1033: merge Unix and Windows build systems in the root directory +- #1033: merge Unix and Windows build systems in the root directory (Sébastien Hinderer, review by Damien Doligez and Adrien Nader) -- GPR#1047: Make .depend files generated for C sources more portable +- #1047: Make .depend files generated for C sources more portable (Sébastien Hinderer, review by Xavier Leroy and David Allsopp) -- GPR#1076: Simplify ocamlyacc's build system +- #1076: Simplify ocamlyacc's build system (Sébastien Hinderer, review by David Allsopp) ### Compiler distribution build system: Makefile factorization @@ -1801,188 +2743,188 @@ systems. on it is a bit fragile. We plan to make `ocamlc -config` easier to use for scripting purposes, and have a stable interface there. If you rely on Makefile.config, you may want to get in touch with Sébastien Hinderer - or participate to MPR#7116 (Allow easy retrieval of Makefile.config's values) - or MPR#7172 (More information in ocamlc -config). + or participate to #7116 (Allow easy retrieval of Makefile.config's values) + or #7172 (More information in ocamlc -config). The complete list of changes is listed below. -- GPR#705: update Makefile.nt so that ocamlnat compiles +- #705: update Makefile.nt so that ocamlnat compiles for non-Cygwin Windows ports. (Sébastien Hinderer, review by Alain Frisch) -- GPR#729: Make sure ocamlnat is built with a $(EXE) extension, merge +- #729: Make sure ocamlnat is built with a $(EXE) extension, merge rules between Unix and Windows Makefiles (Sébastien Hinderer, review by Alain Frisch) -- GPR#762: Merge build systems in the yacc/ directory. +- #762: Merge build systems in the yacc/ directory. (Sébastien Hinderer, review by David Allsopp, Alain Frisch) -- GPR#764: Merge build systems in the debugger/ directory. +- #764: Merge build systems in the debugger/ directory. (Sébastien Hinderer, review by Alain Frisch) -- GPR#785: Merge build systems in otherlibs/systhreads/ +- #785: Merge build systems in otherlibs/systhreads/ (Sébastien Hinderer, review by Alain Frisch, David Allsopp, testing and regression fix by Jérémie Dimino) -- GPR#788: Merge build systems in subdirectories of otherlibs/. +- #788: Merge build systems in subdirectories of otherlibs/. (Sébastien Hinderer, review by Alain Frisch) -- GPR#808, GPR#906: Merge Unix and Windows build systems +- #808, #906: Merge Unix and Windows build systems in the ocamldoc/ directory (Sébastien Hinderer, review by Alain Frisch) -- GPR#812: Merge build systems in the tools/ subdirectory +- #812: Merge build systems in the tools/ subdirectory (Sébastien Hinderer, review by Alain Frisch) -- GPR#866: Merge build systems in the stdlib/ directory +- #866: Merge build systems in the stdlib/ directory (Sébastien Hinderer, review by David Allsopp and Adrien Nader) -- GPR#941: Merge Unix and Windows build systems in the asmrun/ directory +- #941: Merge Unix and Windows build systems in the asmrun/ directory (Sébastien Hinderer, review by Mark Shinwell, Adrien Nader, Xavier Leroy, David Allsopp, Damien Doligez) -- GPR#981: Merge build systems in the byterun/ directory +- #981: Merge build systems in the byterun/ directory (Sébastien Hinderer, review by Adrien Nader) -- GPR#1033, GPR#1048: Merge build systems in the root directory +- #1033, #1048: Merge build systems in the root directory (Sébastien Hinderer, review by Adrien Nader and Damien Doligez, testing and regression fix by Andreas Hauptmann) ### Internal/compiler-libs changes: -- GPR#673: distinguish initialization of block fields from mutation in lambda. +- #673: distinguish initialization of block fields from mutation in lambda. (Frédéric Bour, review by Xavier Leroy, Stephen Dolan and Mark Shinwell) -- GPR#744, GPR#781: fix duplicate self-reference in imported cmi_crcs +- #744, #781: fix duplicate self-reference in imported cmi_crcs list in .cmti files + avoid rebuilding cmi_info record when creating .cmti files (Alain Frisch, report by Daniel Bünzli, review by Jérémie Dimino) -- GPR#881: change `Outcometree.out_variant` to be more general. +- #881: change `Outcometree.out_variant` to be more general. `Ovar_name of out_ident * out_type list` becomes `Ovar_type of out_type`. (Valentin Gatien-Baron, review by Leo White) -- GPR#908: refactor PIC-handling in the s390x backend +- #908: refactor PIC-handling in the s390x backend (Gabriel Scherer, review by Xavier Leroy and Mark Shinwell) -### Bug fixes +### Bug fixes: -- MPR#5115: protect all byterun/fail.c functions against +- #5115: protect all byterun/fail.c functions against uninitialized caml_global_data (only changes the bytecode behavior) (Gabriel Scherer, review by Xavier Leroy) -- MPR#6136, GPR#967: Fix Closure so that overapplication evaluation order +- #6136, #967: Fix Closure so that overapplication evaluation order matches the bytecode compiler and Flambda. (Mark Shinwell, report by Jeremy Yallop, review by Frédéric Bour) -- MPR#6550, GPR#1094: Allow creation of empty .cmxa files on macOS +- #6550, #1094: Allow creation of empty .cmxa files on macOS (Mark Shinwell) -- MPR#6594, GPR#955: Remove "Istore_symbol" specific operation on x86-64. +- #6594, #955: Remove "Istore_symbol" specific operation on x86-64. This is more robust and in particular avoids assembly failures on Win64. (Mark Shinwell, review by Xavier Leroy, testing by David Allsopp and Olivier Andrieu) -- MPR#6903: Unix.execvpe doesn't change environment on Cygwin +- #6903: Unix.execvpe doesn't change environment on Cygwin (Xavier Leroy, report by Adrien Nader) -- MPR#6987: Strange error message probably caused by +- #6987: Strange error message probably caused by universal variable escape (with polymorphic variants) (Jacques Garrigue, report by Mikhail Mandrykin and Leo White) -- MPR#7216, GPR#949: don't require double parens in Functor((val x)) +- #7216, #949: don't require double parens in Functor((val x)) (Jacques Garrigue, review by Valentin Gatien-Baron) -- MPR#7331: ocamldoc, avoid infinite loop in presence of self alias, +- #7331: ocamldoc, avoid infinite loop in presence of self alias, i.e. module rec M:sig end = M (Florian Angeletti, review Gabriel Scherer) -- MPR#7346, GPR#966: Fix evaluation order problem whereby expressions could +- #7346, #966: Fix evaluation order problem whereby expressions could be incorrectly re-ordered when compiling with Flambda. This also fixes one example of evaluation order in the native code compiler not matching the bytecode compiler (even when not using Flambda) (Mark Shinwell, Leo White, code review by Pierre Chambart) -- MPR#7348: Private row variables can escape their scope +- #7348: Private row variables can escape their scope (Jacques Garrigue, report by Leo White) -- MPR#7407: Two not-quite-standard C idioms rejected by SUNWSPro compilers +- #7407: Two not-quite-standard C idioms rejected by SUNWSPro compilers (Xavier Leroy) -- MPR#7421: Soundness bug with GADTs and lazy +- #7421: Soundness bug with GADTs and lazy (Jacques Garrigue, report by Leo White) -- MPR#7424: Typechecker diverges on unboxed type declaration +- #7424: Typechecker diverges on unboxed type declaration (Jacques Garrigue, report by Stephen Dolan) -- MPR#7426, GPR#965: Fix fatal error during object compilation (also +- #7426, #965: Fix fatal error during object compilation (also introduces new [Pfield_computed] and [Psetfield_computed] primitives) (Mark Shinwell, report by Ulrich Singer) -- MPR#7427, GPR#959: Don't delete let bodies in Cmmgen +- #7427, #959: Don't delete let bodies in Cmmgen (Mark Shinwell, report by Valentin Gatien-Baron) -- MPR#7432: Linking modules compiled with -labels and -nolabels is not safe +- #7432: Linking modules compiled with -labels and -nolabels is not safe (Jacques Garrigue, report by Jeremy Yallop) -- MPR#7437: typing assert failure with nonrec priv +- #7437: typing assert failure with nonrec priv (Jacques Garrigue, report by Anil Madhavapeddy) -- MPR#7438: warning +34 exposes #row with private types +- #7438: warning +34 exposes #row with private types (Alain Frisch, report by Anil Madhavapeddy) -- MPR#7443, GPR#990: spurious unused open warning with local open in patterns +- #7443, #990: spurious unused open warning with local open in patterns (Florian Angeletti, report by Gabriel Scherer) -- MPR#7456, GPR#1092: fix slow compilation on source files containing a lot +- #7456, #1092: fix slow compilation on source files containing a lot of similar debugging information location entries (Mark Shinwell) -- MPR#7504: fix warning 8 with unconstrained records +- #7504: fix warning 8 with unconstrained records (Florian Angeletti, report by John Whitington) -- MPR#7511, GPR#1133: Unboxed type with unboxed argument should not be accepted +- #7511, #1133: Unboxed type with unboxed argument should not be accepted (Damien Doligez, review by Jeremy Yallop and Leo White) -- GPR#805, GPR#815, GPR#833: check for integer overflow in String.concat +- #805, #815, #833: check for integer overflow in String.concat (Jeremy Yallop, review by Damien Doligez, Alain Frisch, Daniel Bünzli, Fabrice Le Fessant) -- GPR#881: short-paths did not apply to some polymorphic variants +- #881: short-paths did not apply to some polymorphic variants (Valentin Gatien-Baron, review by Leo White) -- GPR#886: Fix Ctype.moregeneral's handling of row_name +- #886: Fix Ctype.moregeneral's handling of row_name (Leo White, review by Jacques Garrigue) -- GPR#934: check for integer overflow in Bytes.extend +- #934: check for integer overflow in Bytes.extend (Jeremy Yallop, review by Gabriel Scherer) -- GPR#956: Keep possibly-effectful expressions when optimizing multiplication +- #956: Keep possibly-effectful expressions when optimizing multiplication by zero. (Jeremy Yallop, review by Nicolás Ojeda Bär, Xavier Leroy and Mark Shinwell) -- GPR#977: Catch Out_of_range in ocamldebug's "list" command +- #977: Catch Out_of_range in ocamldebug's "list" command (Yunxing Dai) -- GPR#983: Avoid removing effectful expressions in Closure, and +- #983: Avoid removing effectful expressions in Closure, and eliminate more non-effectful ones (Alain Frisch, review by Mark Shinwell and Gabriel Scherer) -- GPR#987: alloc_sockaddr: don't assume a null terminator. It is not inserted +- #987: alloc_sockaddr: don't assume a null terminator. It is not inserted on macOS by system calls that fill in a struct sockaddr (e.g. getsockname). (Anton Bachin) -- GPR#998: Do not delete unused closures in un_anf.ml. +- #998: Do not delete unused closures in un_anf.ml. (Leo White, review by Mark Shinwell and Pierre Chambart) -- GPR#1019: Fix fatal error in Flambda mode "[functions] does not map set of +- #1019: Fix fatal error in Flambda mode "[functions] does not map set of closures ID" (Pierre Chambart, code review by Mark Shinwell and Leo White) -- GPR#1075: Ensure that zero-sized float arrays have zero tags. +- #1075: Ensure that zero-sized float arrays have zero tags. (Mark Shinwell, Leo White, review by Xavier Leroy) -* GPR#1088: Gc.minor_words now returns accurate numbers. +* #1088: Gc.minor_words now returns accurate numbers. (compatibility: the .mli declaration of `Gc.minor_words` and `Gc.get_minor_free` changed, which may break libraries re-exporting these values.) @@ -1993,7 +2935,7 @@ OCaml 4.04.2 (23 Jun 2017): ### Security fix: -- PR#7557: Local privilege escalation issue with ocaml binaries. +- #7557: Local privilege escalation issue with ocaml binaries. (Damien Doligez, report by Eric Milliken, review by Xavier Leroy) OCaml 4.04.1 (14 Apr 2017): @@ -2001,81 +2943,83 @@ OCaml 4.04.1 (14 Apr 2017): ### Standard library: -- PR#7403, GPR#894: fix a bug in Set.map as introduced in 4.04.0 +- #7403, #894: fix a bug in Set.map as introduced in 4.04.0 (Gabriel Scherer, report by Thomas Leonard) ### Tools: -- PR#7411: ocamldoc, avoid nested
 tags in module description.
+- #7411: ocamldoc, avoid nested 
 tags in module description.
   (Florian Angeletti, report by user 'kosik')
 
-- PR#7488: ocamldoc, wrong Latex output for variant types
+- #7488: ocamldoc, wrong Latex output for variant types
   with constructors without arguments.
   (Florian Angeletti, report by Xavier Leroy)
 
 ### Build system:
 
-- PR#7373, GPR#1023: New flexlink target in Makefile.nt to bootstrap the
+- #7373, #1023: New flexlink target in Makefile.nt to bootstrap the
   flexlink binary only, rather than the flexlink binary and the FlexDLL C
   objects.
   (David Allsopp)
 
-### Bug fixes
+### Bug fixes:
 
-- PR#7369: Str.regexp raises "Invalid_argument: index out of bounds"
+- #7369: Str.regexp raises "Invalid_argument: index out of bounds"
   (Damien Doligez, report by John Whitington)
 
-- PR#7373, GPR#1023: Fix ocamlmklib with bootstrapped FlexDLL. Bootstrapped
+- #7373, #1023: Fix ocamlmklib with bootstrapped FlexDLL. Bootstrapped
   FlexDLL objects are now installed to a subdirectory flexdll of the Standard
   Library which allows the compilers to pick them up explicitly and also
   ocamlmklib to include them without unnecessarily adding the entire Standard
   Library.
   (David Allsopp)
 
-- PR#7385, GPR#1057: fix incorrect timestamps returned by Unix.stat on Windows
+- #7385, #1057: fix incorrect timestamps returned by Unix.stat on Windows
   when either TZ is set or system date is in DST.
   (David Allsopp, report and initial fix by Nicolás Ojeda Bär, review and
    superior implementation suggestion by Xavier Leroy)
 
-- PR#7405, GPR#903: s390x: Fix address of caml_raise_exn in native dynlink modules
+- #7405, #903: s390x: Fix address of caml_raise_exn in native dynlink
+  modules.
   (Richard Jones, review by Xavier Leroy)
 
-- PR#7417, GPR#930: ensure 16 byte stack alignment inside caml_allocN on x86-64
+- #7417, #930: ensure 16 byte stack alignment inside caml_allocN on x86-64
   for ocaml build with WITH_FRAME_POINTERS defined
   (Christoph Cullmann)
 
-- PR#7456, GPR#1092: fix slow compilation on source files containing a lot
+- #7456, #1092: fix slow compilation on source files containing a lot
   of similar debugging information location entries
   (Mark Shinwell)
 
-- PR#7457: a case of double free in the systhreads library (POSIX implementation)
+- #7457: a case of double free in the systhreads library (POSIX
+  implementation).
   (Xavier Leroy, report by Chet Murthy)
 
-- PR#7460, GPR#1011: catch uncaught exception when unknown files are passed
+- #7460, #1011: catch uncaught exception when unknown files are passed
   as argument (regression in 4.04.0)
   (Bernhard Schommer, review by Florian Angeletti and Gabriel Scherer,
    report by Stephen Dolan)
 
-- PR#7505: Memory cannot be released after calling
+- #7505: Memory cannot be released after calling
     Bigarray.Genarray.change_layout.
   (Damien Doligez and Xavier Leroy, report by Liang Wang)
 
-- GPR#912: Fix segfault in Unix.create_process on Windows caused by wrong header
+- #912: Fix segfault in Unix.create_process on Windows caused by wrong header
   configuration.
   (David Allsopp)
 
-- GPR#980: add dynlink options to ocamlbytecomp.cmxa to allow ocamlopt.opt
+- #980: add dynlink options to ocamlbytecomp.cmxa to allow ocamlopt.opt
   to load plugins. See http://github.com/OCamlPro/ocamlc-plugins for examples.
   (Fabrice Le Fessant, review by David Allsopp)
 
-- GPR#992: caml-types.el: Fix missing format argument, so that it can show kind
+- #992: caml-types.el: Fix missing format argument, so that it can show kind
   of call at point correctly.
   (Chunhui He)
 
-- GPR#1043: Allow Windows CRLF line-endings in ocamlyacc on Unix and Cygwin.
+- #1043: Allow Windows CRLF line-endings in ocamlyacc on Unix and Cygwin.
   (David Allsopp, review by Damien Doligez and Xavier Leroy)
 
-- GPR#1072: Fix segfault in Sys.runtime_parameters when exception backtraces
+- #1072: Fix segfault in Sys.runtime_parameters when exception backtraces
   are enabled.
   (Olivier Andrieu)
 
@@ -2086,160 +3030,160 @@ OCaml 4.04.0 (4 Nov 2016):
 
 ### Language features:
 
-- PR#7233: Support GADT equations on non-local abstract types
+- #7233: Support GADT equations on non-local abstract types
   (Jacques Garrigue)
 
-- GPR#187, GPR#578: Local opening of modules in a pattern.
+- #187, #578: Local opening of modules in a pattern.
   Syntax: "M.(p)", "M.[p]","M.[| p |]", "M.{p}"
   (Florian Angeletti, Jacques Garrigue, review by Alain Frisch)
 
-- GPR#301: local exception declarations "let exception ... in"
+- #301: local exception declarations "let exception ... in"
   (Alain Frisch)
 
-- GPR#508: Allow shortcut for extension on semicolons: ;%foo
+- #508: Allow shortcut for extension on semicolons: ;%foo
   (Jérémie Dimino)
 
-- GPR#606: optimized representation for immutable records with a single
+- #606: optimized representation for immutable records with a single
   field, and concrete types with a single constructor with a single argument.
   This is triggered with a [@@unboxed] attribute on the type definition.
   Currently mutually recursive datatypes are not well supported, this
-  limitation should be lifted in the future (see MPR#7364).
+  limitation should be lifted in the future (see #7364).
   (Damien Doligez)
 
 ### Compiler user-interface and warnings:
 
-* PR#6475, GPR#464: interpret all command-line options before compiling any
+* #6475, #464: interpret all command-line options before compiling any
   files, changes (improves) the semantics of repeated -o options or -o
   combined with -c see the super-detailed commit message at
   https://github.com/ocaml/ocaml/commit/da56cf6dfdc13c09905c2e07f1d4849c8346eec8
   (whitequark)
 
-- PR#7139: clarify the wording of Warning 38
+- #7139: clarify the wording of Warning 38
   (Unused exception or extension constructor)
   (Gabriel Scherer)
 
-* PR#7147, GPR#475: add colors when reporting errors generated by ppx rewriters.
+* #7147, #475: add colors when reporting errors generated by ppx rewriters.
   Remove the `Location.errorf_prefixed` function which is no longer relevant
   (Simon Cruanes, Jérémie Dimino)
 
-- PR#7169, GPR#501: clarify the wording of Warning 8
+- #7169, #501: clarify the wording of Warning 8
   (Non-exhaustivity warning for pattern matching)
   (Florian Angeletti, review and report by Gabriel Scherer)
 
-* GPR#591: Improve support for OCAMLPARAM: (i) do not use objects
+* #591: Improve support for OCAMLPARAM: (i) do not use objects
   files with -a, -pack, -shared; (ii) use "before" objects in the toplevel
   (but not "after" objects); (iii) use -I dirs in the toplevel,
   (iv) fix bug where -I dirs were ignored when using threads
   (Marc Lasson, review by Damien Doligez and Alain Frisch)
 
-- GPR#648: New -plugin option for ocamlc and ocamlopt, to dynamically extend
+- #648: New -plugin option for ocamlc and ocamlopt, to dynamically extend
   the compilers at runtime.
   (Fabrice Le Fessant)
 
-- GPR#684: Detect unused module declarations
+- #684: Detect unused module declarations
   (Alain Frisch)
 
-- GPR#706: Add a settable Env.Persistent_signature.load function so
+- #706: Add a settable Env.Persistent_signature.load function so
   that cmi files can be loaded from other sources. This can be used to
   create self-contained toplevels.
   (Jérémie Dimino)
 
 ### Standard library:
 
-- PR#6279, GPR#553: implement Set.map
+- #6279, #553: implement Set.map
   (Gabriel Scherer)
 
-- PR#6820, GPR#560: Add Obj.reachable_words to compute the
+- #6820, #560: Add Obj.reachable_words to compute the
   "transitive" heap size of a value
   (Alain Frisch, review by Mark Shinwell and Damien Doligez)
 
-- GPR#473: Provide `Sys.backend_type` so that user can write backend-specific
+- #473: Provide `Sys.backend_type` so that user can write backend-specific
   code in some cases (for example,  code generator).
   (Hongbo Zhang)
 
-- GPR#589: Add a non-allocating function to recover the number of
+- #589: Add a non-allocating function to recover the number of
   allocated minor words.
   (Pierre Chambart, review by Damien Doligez and Gabriel Scherer)
 
-- GPR#626: String.split_on_char
+- #626: String.split_on_char
   (Alain Frisch)
 
-- GPR#669: Filename.extension and Filename.remove_extension
+- #669: Filename.extension and Filename.remove_extension
   (Alain Frisch, request by Edgar Aroutiounian, review by Daniel Bünzli
   and Damien Doligez)
 
-- GPR#674: support unknown Sys.os_type in Filename, defaulting to Unix
+- #674: support unknown Sys.os_type in Filename, defaulting to Unix
   (Filename would previously fail at initialization time for
    Sys.os_type values other than "Unix", "Win32" and "Cygwin";
    mirage-os uses "xen")
   (Anil Madhavapeddy)
 
-- GPR#772 %string_safe_set and %string_unsafe_set are deprecated aliases
+- #772 %string_safe_set and %string_unsafe_set are deprecated aliases
   for %bytes_safe_set and %bytes_unsafe_set.
   (Hongbo Zhang and Damien Doligez)
 
 ### Other libraries
 
-- MPR#4834, GPR#592: Add a Biggarray.Genarray.change_layout function
+- #4834, #592: Add a Biggarray.Genarray.change_layout function
   to switch bigarrays between C and fortran layouts.
   (Guillaume Hennequin, review by Florian Angeletti)
 
 ### Code generation and optimizations:
 
-- PR#4747, GPR#328: Optimize Hashtbl by using in-place updates of its
+- #4747, #328: Optimize Hashtbl by using in-place updates of its
   internal bucket lists.  All operations run in constant stack size
   and are usually faster, except Hashtbl.copy which can be much
   slower
   (Alain Frisch)
 
-- PR#6217, GPR#538: Optimize performance of record update:
+- #6217, #538: Optimize performance of record update:
   no more performance cliff when { foo with t1 = ..; t2 = ...; ... }
   hits 6 updated fields
   (Olivier Nicole, review by Thomas Braibant and Pierre Chambart)
 
-- PR#7023, GPR#336: Better unboxing strategy
+- #7023, #336: Better unboxing strategy
   (Alain Frisch, Pierre Chambart)
 
-- PR#7244, GPR#840: Ocamlopt + flambda requires a lot of memory
+- #7244, #840: Ocamlopt + flambda requires a lot of memory
   to compile large array literal expressions
   (Pierre Chambart, review by Mark Shinwell)
 
-- PR#7291, GPR#780: Handle specialisation of recursive function that does
+- #7291, #780: Handle specialisation of recursive function that does
   not always preserve the arguments
   (Pierre Chambart, Mark Shinwell, report by Simon Cruanes)
 
-- PR#7328, GPR#702: Do not eliminate boxed int divisions by zero and
+- #7328, #702: Do not eliminate boxed int divisions by zero and
   avoid checking twice if divisor is zero with flambda.
   (Pierre Chambart, report by Jeremy Yallop)
 
-- GPR#427: Obj.is_block is now an inlined OCaml function instead of a
+- #427: Obj.is_block is now an inlined OCaml function instead of a
   C external.  This should be faster.
   (Demi Obenour)
 
-- GPR#580: Optimize immutable float records
+- #580: Optimize immutable float records
   (Pierre Chambart, review by Mark Shinwell)
 
-- GPR#602: Do not generate dummy code to force module linking
+- #602: Do not generate dummy code to force module linking
   (Pierre Chambart, reviewed by Jacques Garrigue)
 
-- GPR#703: Optimize some constant string operations when the "-safe-string"
+- #703: Optimize some constant string operations when the "-safe-string"
   configure time option is enabled.
   (Pierre Chambart)
 
-- GPR#707: Load cross module information during a meet
+- #707: Load cross module information during a meet
   (Pierre Chambart, report by Leo White, review by Mark Shinwell)
 
-- GPR#709: Share a few more equal switch branches
+- #709: Share a few more equal switch branches
   (Pierre Chambart, review by Gabriel Scherer)
 
-- GPR#712: Small improvements to type-based optimizations for array
+- #712: Small improvements to type-based optimizations for array
   and lazy
   (Alain Frisch, review by Pierre Chambart)
 
-- GPR#714: Prevent warning 59 from triggering on Lazy of constants
+- #714: Prevent warning 59 from triggering on Lazy of constants
   (Pierre Chambart, review by Leo White)
 
-- GPR#723 Sort emitted functions according to source location
+- #723 Sort emitted functions according to source location
   (Pierre Chambart, review by Mark Shinwell)
 
 - Lack of type normalization lead to missing simple compilation for "lazy x"
@@ -2247,18 +3191,18 @@ OCaml 4.04.0 (4 Nov 2016):
 
 ### Runtime system:
 
-- PR#7203, GPR#534: Add a new primitive caml_alloc_float_array to allocate an
+- #7203, #534: Add a new primitive caml_alloc_float_array to allocate an
   array of floats
   (Thomas Braibant)
 
-- PR#7210, GPR#562: Allows to register finalisation function that are
+- #7210, #562: Allows to register finalisation function that are
   called only when a value will never be reachable anymore. The
   drawbacks compared to the existing one is that the finalisation
   function is not called with the value as argument. These finalisers
   are registered with `GC.finalise_last`
   (François Bobot reviewed by Damien Doligez and Leo White)
 
-- GPR#247: In previous OCaml versions, inlining caused stack frames to
+- #247: In previous OCaml versions, inlining caused stack frames to
   disappear from stacktraces. This made debugging harder in presence of
   optimizations, and flambda was going to make this worse. The debugging
   information produced by the compiler now enables the reconstruction of the
@@ -2266,245 +3210,245 @@ OCaml 4.04.0 (4 Nov 2016):
   the list of inlined stack frames.
   (Frédéric Bour, review by Mark Shinwell and Xavier Leroy)
 
-- GPR#590: Do not perform compaction if the real overhead is less than expected
+- #590: Do not perform compaction if the real overhead is less than expected
   (Thomas Braibant)
 
 ### Tools:
 
-- PR#7189: toplevel #show, follow chains of module aliases
+- #7189: toplevel #show, follow chains of module aliases
   (Gabriel Scherer, report by Daniel Bünzli, review by Thomas Refis)
 
-- PR#7248: have ocamldep interpret -open arguments in left-to-right order
+- #7248: have ocamldep interpret -open arguments in left-to-right order
   (Gabriel Scherer, report by Anton Bachin)
 
-- PR#7272, GPR#798: ocamldoc, missing line breaks in type_*.html files
+- #7272, #798: ocamldoc, missing line breaks in type_*.html files
   (Florian Angeletti)
 
-- PR#7290: ocamldoc, improved support for inline records
+- #7290: ocamldoc, improved support for inline records
   (Florian Angeletti)
 
-- PR#7323, GPR#750: ensure "ocamllex -ml" works with -safe-string
+- #7323, #750: ensure "ocamllex -ml" works with -safe-string
   (Hongbo Zhang)
 
-- PR#7350, GPR#806: ocamldoc, add viewport metadata to generated html pages
+- #7350, #806: ocamldoc, add viewport metadata to generated html pages
   (Florian Angeletti, request by Daniel Bünzli)
 
-- GPR#452: Make the output of ocamldep more stable
+- #452: Make the output of ocamldep more stable
   (Alain Frisch)
 
-- GPR#548: empty documentation comments
+- #548: empty documentation comments
   (Florian Angeletti)
 
-- GPR#575: Add the -no-version option to the toplevel
+- #575: Add the -no-version option to the toplevel
   (Sébastien Hinderer)
 
-- GPR#598: Add a --strict option to ocamlyacc treat conflicts as errors
+- #598: Add a --strict option to ocamlyacc treat conflicts as errors
   (this option is now used for the compiler's parser)
   (Jeremy Yallop)
 
-- GPR#613: make ocamldoc use -open arguments
+- #613: make ocamldoc use -open arguments
   (Florian Angeletti)
 
-- GPR#718: ocamldoc, fix order of extensible variant constructors
+- #718: ocamldoc, fix order of extensible variant constructors
   (Florian Angeletti)
 
 ### Debugging and profiling:
 
-- GPR#585: Spacetime, a new memory profiler (Mark Shinwell, Leo White)
+- #585: Spacetime, a new memory profiler (Mark Shinwell, Leo White)
 
 ### Manual and documentation:
 
-- PR#7007, PR#7311: document the existence of OCAMLPARAM and
+- #7007, #7311: document the existence of OCAMLPARAM and
   ocaml_compiler_internal_params
   (Damien Doligez, reports by Wim Lewis and Gabriel Scherer)
 
-- PR#7243: warn users against using WinZip to unpack the source archive
+- #7243: warn users against using WinZip to unpack the source archive
   (Damien Doligez, report by Shayne Fletcher)
 
-- PR#7245, GPR#565: clarification to the wording and documentation
+- #7245, #565: clarification to the wording and documentation
   of Warning 52 (fragile constant pattern)
   (Gabriel Scherer, William, Adrien Nader, Jacques Garrigue)
 
-- #PR7265, GPR#769: Restore 4.02.3 behaviour of Unix.fstat, if the
+- #PR7265, #769: Restore 4.02.3 behaviour of Unix.fstat, if the
   file descriptor doesn't wrap a regular file (win32unix only)
   (Andreas Hauptmann, review by David Allsopp)
 
-- PR#7288: flatten : Avoid confusion
+- #7288: flatten : Avoid confusion
   (Damien Doligez, report by user 'tormen')
 
-- PR#7355: Gc.finalise and lazy values
+- #7355: Gc.finalise and lazy values
   (Jeremy Yallop)
 
-- GPR#842: Document that [Store_field] must not be used to populate
+- #842: Document that [Store_field] must not be used to populate
   arrays of values declared using [CAMLlocalN] (Mark Shinwell)
 
 ### Compiler distribution build system:
 
-- GPR#324: Compiler developers: Adding new primitives to the
+- #324: Compiler developers: Adding new C primitives to the
   standard runtime doesn't require anymore to run `make bootstrap`
   (François Bobot)
 
-- GPR#384: Fix compilation using old Microsoft C Compilers not
+- #384: Fix compilation using old Microsoft C Compilers not
   supporting secure CRT functions (SDK Visual Studio 2005 compiler and
   earlier) and standard 64-bit integer literals (Visual Studio .NET
   2002 and earlier)
   (David Allsopp)
 
-- GPR#507: More sharing between Unix and Windows makefiles
+- #507: More sharing between Unix and Windows makefiles
   (whitequark, review by Alain Frisch)
 
-* GPR#512, GPR#587: Installed `ocamlc`, `ocamlopt`, and `ocamllex` are
+* #512, #587: Installed `ocamlc`, `ocamlopt`, and `ocamllex` are
   now the native-code versions of the tools, if those versions were
   built.
   (Demi Obenour)
 
-- GPR#525: fix build on OpenIndiana
+- #525: fix build on OpenIndiana
   (Sergey Avseyev, review by Damien Doligez)
 
-- GPR#687: "./configure -safe-string" to get a system where
+- #687: "./configure -safe-string" to get a system where
   "-unsafe-string" is not allowed, thus giving stronger non-local
   guarantees about immutability of strings
   (Alain Frisch, review by Hezekiah M. Carty)
 
 ### Bug fixes:
 
-* PR#6505: Missed Type-error leads to a segfault upon record access.
+* #6505: Missed Type-error leads to a segfault upon record access.
   (Jacques Garrigue, extra report by Stephen Dolan)
   Proper fix required a more restrictive approach to recursive types:
   mutually recursive types are seen as abstract types (i.e. non-contractive)
   when checking the well-foundedness of the recursion.
 
-* PR#6752: Nominal types and scope escaping.
+* #6752: Nominal types and scope escaping.
   Revert to strict scope for non-generalizable type variables, cf. Mantis.
   Note that this is actually stricter than the behavior before 4.03,
-  cf. PR#7313, meaning that you may sometimes need to add type annotations
+  cf. #7313, meaning that you may sometimes need to add type annotations
   to explicitly instantiate non-generalizable type variables.
   (Jacques Garrigue, following discussion with Jeremy Yallop,
    Nicolás Ojeda Bär and Alain Frisch)
 
-- PR#7112: Aliased arguments ignored for equality of module types
+- #7112: Aliased arguments ignored for equality of module types
   (Jacques Garrigue, report by Leo White)
 
-- PR#7134: compiler forcing aliases it shouldn't while reporting type errors
+- #7134: compiler forcing aliases it shouldn't while reporting type errors
   (Jacques Garrigue, report and suggestion by sliquister)
 
-- PR#7153: document that Unix.SOCK_SEQPACKET is not really usable.
+- #7153: document that Unix.SOCK_SEQPACKET is not really usable.
 
-- PR#7165, GPR#494: uncaught exception on invalid lexer directive
+- #7165, #494: uncaught exception on invalid lexer directive
   (Gabriel Scherer, report by KC Sivaramakrishnan using afl-fuzz)
 
-- PR#7257, GPR#583: revert a 4.03 change of behavior on (Unix.sleep 0.),
+- #7257, #583: revert a 4.03 change of behavior on (Unix.sleep 0.),
   it now calls (nano)sleep for 0 seconds as in (< 4.03) versions.
   (Hannes Mehnert, review by Damien Doligez)
 
-- PR#7259 and GPR#603: flambda does not collapse pattern matching
+- #7259 and #603: flambda does not collapse pattern matching
   in some cases
   (Pierre Chambart, report by Reed Wilson, review by Mark Shinwell)
 
-- PR#7260: GADT + subtyping compile time crash
+- #7260: GADT + subtyping compile time crash
   (Jacques Garrigue, report by Nicolás Ojeda Bär)
 
-- PR#7269: Segfault from conjunctive constraints in GADT
+- #7269: Segfault from conjunctive constraints in GADT
   (Jacques Garrigue, report by Stephen Dolan)
 
-- PR#7276: Support more than FD_SETSIZE sockets in Windows' emulation
+- #7276: Support more than FD_SETSIZE sockets in Windows' emulation
   of select
   (David Scott, review by Alain Frisch)
 
-* PR#7278: Prevent private inline records from being mutated
+* #7278: Prevent private inline records from being mutated
   (Alain Frisch, report by Pierre Chambart)
 
-- PR#7284: Bug in mcomp_fields leads to segfault
+- #7284: Bug in mcomp_fields leads to segfault
   (Jacques Garrigue, report by Leo White)
 
-- PR#7285: Relaxed value restriction broken with principal
+- #7285: Relaxed value restriction broken with principal
   (Jacques Garrigue, report by Leo White)
 
-- PR#7297: -strict-sequence turns off Warning 21
+- #7297: -strict-sequence turns off Warning 21
   (Jacques Garrigue, report by Valentin Gatien-Baron)
 
-- PR#7299: remove access to OCaml heap inside blocking section in win32unix
+- #7299: remove access to OCaml heap inside blocking section in win32unix
   (David Allsopp, report by Andreas Hauptmann)
 
-- PR#7300: remove access to OCaml heap inside blocking in Unix.sleep on Windows
+- #7300: remove access to OCaml heap inside blocking in Unix.sleep on Windows
   (David Allsopp)
 
-- PR#7305: -principal causes loop in type checker when compiling
+- #7305: -principal causes loop in type checker when compiling
   (Jacques Garrigue, report by Anil Madhavapeddy, analysis by Leo White)
 
-- PR#7330: Missing exhaustivity check for extensible variant
+- #7330: Missing exhaustivity check for extensible variant
   (Jacques Garrigue, report by Elarnon *)
 
-- PR#7374: Contractiveness check unsound with constraints
+- #7374: Contractiveness check unsound with constraints
   (Jacques Garrigue, report by Leo White)
 
-- PR#7378: GADT constructors can be re-exposed with an incompatible type
+- #7378: GADT constructors can be re-exposed with an incompatible type
   (Jacques Garrigue, report by Alain Frisch)
 
-- PR#7389: Unsoundness in GADT exhaustiveness with existential variables
+- #7389: Unsoundness in GADT exhaustiveness with existential variables
   (Jacques Garrigue, report by Stephen Dolan)
 
-* GPR#533: Thread library: fixed [Thread.wait_signal] so that it
+* #533: Thread library: fixed [Thread.wait_signal] so that it
   converts back the signal number returned by [sigwait] to an
   OS-independent number
   (Jérémie Dimino)
 
-- GPR#600: (similar to GPR#555) ensure that register typing constraints are
+- #600: (similar to #555) ensure that register typing constraints are
   respected at N-way join points in the control flow graph
   (Mark Shinwell)
 
-- GPR#672: Fix float_of_hex parser to correctly reject some invalid forms
+- #672: Fix float_of_hex parser to correctly reject some invalid forms
   (Bogdan Tătăroiu, review by Thomas Braibant and Alain Frisch)
 
-- GPR#700: Fix maximum weak bucket size
+- #700: Fix maximum weak bucket size
   (Nicolás Ojeda Bär, review by François Bobot)
 
-- GPR#708 Allow more module aliases in strengthening (Leo White)
+- #708 Allow more module aliases in strengthening (Leo White)
 
-- GPR#713, PR#7301: Fix wrong code generation involving lazy values in Flambda
+- #713, #7301: Fix wrong code generation involving lazy values in Flambda
   mode
   (Mark Shinwell, review by Pierre Chambart and Alain Frisch)
 
-- GPR#721: Fix infinite loop in flambda due to [@@specialise] annotations
+- #721: Fix infinite loop in flambda due to [@@specialise] annotations
 
-- GPR#779: Building native runtime on Windows could fail when bootstrapping
+- #779: Building native runtime on Windows could fail when bootstrapping
   FlexDLL if there was also a system-installed flexlink
   (David Allsopp, report Michael Soegtrop)
 
-- GPR#805, GPR#815, GPR#833: check for integer overflow in String.concat
+- #805, #815, #833: check for integer overflow in String.concat
   (Jeremy Yallop,
    review by Damien Doligez, Alain Frisch, Daniel Bünzli, Fabrice Le Fessant)
 
-- GPR#810: check for integer overflow in Array.concat
+- #810: check for integer overflow in Array.concat
   (Jeremy Yallop)
 
-- GPR#814: fix the Buffer.add_substring bounds check to handle overflow
+- #814: fix the Buffer.add_substring bounds check to handle overflow
   (Jeremy Yallop)
 
-- GPR#880: Fix [@@inline] with default parameters in flambda (Leo White)
+- #880: Fix [@@inline] with default parameters in flambda (Leo White)
 
-* GPR#1353: add labels to BytesLabels.sub_string (Jacques Garrigue)
+* #1353: add labels to BytesLabels.sub_string (Jacques Garrigue)
 
 ### Internal/compiler-libs changes:
 
-- PR#7200, GPR#539: Improve, fix, and add test for parsing/pprintast.ml
+- #7200, #539: Improve, fix, and add test for parsing/pprintast.ml
   (Runhang Li, David Sheets, Alain Frisch)
 
-- GPR#351: make driver/pparse.ml functions type-safe
+- #351: make driver/pparse.ml functions type-safe
   (Gabriel Scherer, Dmitrii Kosarev, review by Jérémie Dimino)
 
-- GPR#516: Improve Texp_record constructor representation, and
+- #516: Improve Texp_record constructor representation, and
   propagate updated record type information
   (Pierre Chambart, review by Alain Frisch)
 
-- GPR#678: Graphics.close_graph crashes 64-bit Windows ports (re-implementation
-  of PR#3963)
+- #678: Graphics.close_graph crashes 64-bit Windows ports (re-implementation
+  of #3963)
   (David Allsopp)
 
-- GPR#679: delay registration of docstring after the mapper is applied
+- #679: delay registration of docstring after the mapper is applied
   (Hugo Heuzard, review by Leo White)
 
-- GPR#872: don't attach (**/**) comments to any particular node
+- #872: don't attach (**/**) comments to any particular node
   (Thomas Refis, review by Leo White)
 
 OCaml 4.03.0 (25 Apr 2016):
@@ -2514,10 +3458,10 @@ OCaml 4.03.0 (25 Apr 2016):
 
 ### Language features:
 
-- PR#5528: inline records for constructor arguments
+- #5528: inline records for constructor arguments
   (Alain Frisch)
 
-- PR#6220, PR#6403, PR#6437, PR#6801:
+- #6220, #6403, #6437, #6801:
   Improved redundancy and exhaustiveness checks for GADTs.
   Namely, the redundancy checker now checks whether the uncovered pattern
   of the pattern is actually inhabited, exploding at most one wild card.
@@ -2526,86 +3470,86 @@ OCaml 4.03.0 (25 Apr 2016):
   "pat -> .", which are treated by the redundancy check.
   (Jacques Garrigue)
 
-- PR#6374: allow "_ t" as a short-hand for "(_, _, ..) t" for n-ary type
+- #6374: allow "_ t" as a short-hand for "(_, _, ..) t" for n-ary type
   constructors
   (Alain Frisch)
 
-- PR#6714: allow [@@ocaml.warning] on most structure and signature items:
+- #6714: allow [@@ocaml.warning] on most structure and signature items:
   values, modules, module types
   (whitequark)
 
-- PR#6806: Syntax shortcut for putting a type annotation on a record field:
+- #6806: Syntax shortcut for putting a type annotation on a record field:
   { f1 : typ = e } is sugar for { f1 = (e : typ) }
   { f1 : typ } is sugar for { f1 = (f1 : typ) }
   (Valentin Gatien-Baron, review by Jérémie Dimino)
 
-- PR#6806: Allow type annotations before the "->" in "fun  -> "
+- #6806: Allow type annotations before the "->" in "fun  -> "
   fun x y : (int * int) -> (x, y)
   (Valentin Gatien-Baron, review by Jérémie Dimino)
 
-- GPR#26: support for "(type a b)" as syntactic sugar for "(type a) (type b)"
+- #26: support for "(type a b)" as syntactic sugar for "(type a) (type b)"
   (Gabriel Scherer)
 
-- GPR#42: short functor type syntax: "S -> T" for "functor (_ : S) -> T"
+- #42: short functor type syntax: "S -> T" for "functor (_ : S) -> T"
   (Leo White)
 
-- GPR#88: allow field punning in object copying expressions:
+- #88: allow field punning in object copying expressions:
   {< x; y; >} is sugar for {< x = x; y = y; >}
   (Jeremy Yallop)
 
-- GPR#112: octal escape sequences for char and string literals
+- #112: octal escape sequences for char and string literals
   "Make it \o033[1mBOLD\o033[0m"
   (Rafaël Bocquet, request by John Whitington)
 
-- GPR#167: allow to annotate externals' arguments and result types so
+- #167: allow to annotate externals' arguments and result types so
   they can be unboxed or untagged: [@unboxed], [@untagged]. Supports
   untagging int and unboxing int32, int64, nativeint and float.
   (Jérémie Dimino, Mark Shinwell)
 
-- GPR#173: [@inline] and [@inlined] attributes (for function declarations
+- #173: [@inline] and [@inlined] attributes (for function declarations
   and call sites respectively) to control inlining
   (Pierre Chambart, Mark Shinwell)
 
-- GPR#188: accept [@@immediate] attribute on type declarations to mark types
+- #188: accept [@@immediate] attribute on type declarations to mark types
   that are represented at runtime by an integer
   (Will Crichton, reviewed by Leo White)
 
-* GPR#234: allow "[]" as a user-defined constructor. Demand parenthesis
+* #234: allow "[]" as a user-defined constructor. Demand parenthesis
   around "::" when using "::" as user-defined constructor:
   code using "| :: of ..." must change to "| (::) of ...".
   (Runhang Li, review by Damien Doligez)
 
-- GPR#240: replace special annotations on externals by attributes:
+- #240: replace special annotations on externals by attributes:
   * "float" is generalized to [@@unboxed]
   * "noalloc" becomes [@@noalloc]
   Deprecate "float" and "noalloc".
   (Jérémie Dimino)
 
-- GPR#254: @ocaml.warn_on_literal_pattern attribute on constructors to
+- #254: @ocaml.warn_on_literal_pattern attribute on constructors to
   warn when the argument is matches against a constant pattern.  This
   attribute is applied on predefined exception constructors which
   carry purely informational (with no stability guarantee) messages.
   (Alain Frisch)
 
-- GPR#268: hexadecimal notation for floating-point literals: -0x1.ffffp+987
+- #268: hexadecimal notation for floating-point literals: -0x1.ffffp+987
   In OCaml source code, FP literals can be written using the hexadecimal
   notation 0xp from ISO C99.
   (Xavier Leroy)
 
-- GPR#273: allow to get the extension slot of an extension constructor
+- #273: allow to get the extension slot of an extension constructor
   by writing [%extension_constructor ]
   (Jérémie Dimino)
 
-- GPR#282: change short-paths penalty heuristic to assign the same cost to
+- #282: change short-paths penalty heuristic to assign the same cost to
   idents containing double underscores as to idents starting with an underscore
   (Thomas Refis, Leo White)
 
-- PR#6681 GPR#326: signature items are now accepted as payloads for
+- #6681 #326: signature items are now accepted as payloads for
   extension and attributes, using the syntax [%foo: SIG ] or [@foo: SIG ].
   Examples: "[%%client: val foo : int]" or "val%client foo : int".
   (Alain Frisch and Gabriel Radanne)
 
-* GPR#342: Allow shortcuts for extension and attributes on all keywords:
+* #342: Allow shortcuts for extension and attributes on all keywords:
   module%foo, class[@foo], etc.
   The attribute in "let[@foo] .. in .." is now attached to the value binding,
   not to the expression.
@@ -2613,198 +3557,198 @@ OCaml 4.03.0 (25 Apr 2016):
 
 ### Compilers:
 
-* PR#4231, PR#5461: warning 31 is now fatal by default
+* #4231, #5461: warning 31 is now fatal by default
   (Warning 31: A module is linked twice in the same executable.)
   This is an interim solution; double-linking of modules has dangerous
   semantics, eg. exception constructors end up with two distinct declarations.
   (Alain Frisch)
 
-- PR#4800: better compilation of tuple assignment
+- #4800: better compilation of tuple assignment
   (Gabriel Scherer and Alain Frisch)
 
-- PR#5995: keep -for-pack into account to name exceptions;
+- #5995: keep -for-pack into account to name exceptions;
   -for-pack should now be used during bytecode compilation as well
   (Alain Frisch, report by Christophe Troestler)
 
-- PR#6400: better error message for '_' used as an expression
+- #6400: better error message for '_' used as an expression
   (Alain Frisch, report by whitequark)
 
-- PR#6501: harden the native-code generator against certain uses of "%identity"
+- #6501: harden the native-code generator against certain uses of "%identity"
   (Xavier Leroy, report by Antoine Miné)
 
-- PR#6636: add --version option
+- #6636: add --version option
   (whitequark)
 
-- PR#6679: fix pprintast printing of constraints in type declarations
+- #6679: fix pprintast printing of constraints in type declarations
   (Alain Frisch, report by Jun Furuse)
 
-- PR#6737: fix Typedtree attributes on (fun x -> body) expressions
+- #6737: fix Typedtree attributes on (fun x -> body) expressions
   (Alain Frisch, report by Oleg Kiselyov)
 
-* PR#6865: remove special case for parsing "let _ = expr" in structures
+* #6865: remove special case for parsing "let _ = expr" in structures
   (Jérémie Dimino, Alain Frisch)
 
-* PR#6438, PR#7059, GPR#315: Pattern guard disables exhaustiveness check
+* #6438, #7059, #315: Pattern guard disables exhaustiveness check
   (function Some x when x = 0 -> ()) will now raise warning 8 (non-exhaustive)
   instead of warning 25 (all clauses are guarded). 25 isn't raised anymore.
   Projects that set warning 8 as an error may fail to compile (presumably
   this is the semantics they wanted).
   (Alain Frisch, request by Martin Jambon and John Whitington)
 
-- PR#6920: fix debug informations around uses of %apply or %revapply
+- #6920: fix debug information around uses of %apply or %revapply
   (Jérémie Dimino, report by Daniel Bünzli)
 
-- PR#6939: Segfault with improper use of let-rec
+- #6939: Segfault with improper use of let-rec
   (Alain Frisch)
 
-- PR#6943: native-code generator for POWER/PowerPC 64 bits, both in
+- #6943: native-code generator for POWER/PowerPC 64 bits, both in
   big-endian (ppc64) and little-endian (ppc64le) configuration.
   (Xavier Leroy, with inspiration from RedHat's unofficial ppc64 and ppc64le
   ports)
 
-- PR#6979: better code generation in x86-32 backend for copying floats to
+- #6979: better code generation in x86-32 backend for copying floats to
   the stack
   (Marc Lasson, review by Xavier Leroy)
 
-- PR#7018: fix missing identifier renaming during inlining
+- #7018: fix missing identifier renaming during inlining
   (Alain Frisch, review by Xavier Leroy)
 
-- PR#7022, GPR#259: unbox float and boxed ints earlier, avoid second pass
+- #7022, #259: unbox float and boxed ints earlier, avoid second pass
   (Alain Frisch)
 
-- PR#7026, GPR#288: remove write barrier for polymorphic variants without
+- #7026, #288: remove write barrier for polymorphic variants without
   arguments
   (Simon Cruanes)
 
-- PR#7031: new warning 57, ambiguous guarded or-patterns
+- #7031: new warning 57, ambiguous guarded or-patterns
   (Luc Maranget, Gabriel Scherer, report by Martin Clochard and Claude Marché)
 
-- PR#7064, GPR#316: allowing to mark compilation units and sub-modules as
+- #7064, #316: allowing to mark compilation units and sub-modules as
   deprecated
   (Alain Frisch)
 
-- PR#7067: fix performance regression (wrt. 4.01) in the native compiler
+- #7067: fix performance regression (wrt. 4.01) in the native compiler
   for long nested structures
   (Alain Frisch, report by Daniel Bünzli, review by Jacques Garrigue)
 
-- PR#7097: fix strange syntax error message around illegal packaged module
+- #7097: fix strange syntax error message around illegal packaged module
   signature constraints
   (Alain Frisch, report by Jun Furuse)
 
-- PR#7118, PR#7120, GPR#408, GPR#476: Bug fixed in stack unwinding
+- #7118, #7120, #408, #476: Bug fixed in stack unwinding
   metadata generation. Was a cause of crashes in GUI programs on OS X.
   (Bart Jacobs, review by Mark Shinwell)
 
-- PR#7168: Exceeding stack limit in bytecode can lead to a crash.
+- #7168: Exceeding stack limit in bytecode can lead to a crash.
   (Jacques-Henri Jourdan)
 
-- PR#7232: Strange Pprintast output with ppx_deriving
+- #7232: Strange Pprintast output with ppx_deriving
   (Damien Doligez, report by Anton Bachin)
 
-- GPR#17: some cmm optimizations of integer operations with constants
+- #17: some cmm optimizations of integer operations with constants
   (Stephen Dolan, review by Pierre Chambart)
 
-- GPR#89: improve type-specialization of unapplied primitives:
+- #89: improve type-specialization of unapplied primitives:
   unapplied annotations (compare : int -> _),
   type propagation (List.sort compare [1;2;3])
   and propagation from module signatures now lead to specialization
   (Frédéric Bour, review by Gabriel Scherer)
 
-- GPR#107: Prevent more unnecessary float boxing, especially in `if` and `match`
+- #107: Prevent more unnecessary float boxing, especially in `if` and `match`
   (Vladimir Brankov, review by Alain Frisch)
 
-- GPR#109: new (lazy) unboxing strategy for float and int references
+- #109: new (lazy) unboxing strategy for float and int references
   (Vladimir Brankov, review by Alain Frisch)
 
-- GPR#115: More precise typing of values at the C-- and Mach level.
+- #115: More precise typing of values at the C-- and Mach level.
   (Xavier Leroy, review by Pierre Chambart)
 
-- GPR#132: Flambda: new intermediate language and "middle-end" optimizers
+- #132: Flambda: new intermediate language and "middle-end" optimizers
   (Pierre Chambart, Mark Shinwell, Leo White)
 
-- GPR#212, PR#7226, GPR#542: emit column position in gas assembly `.loc`
+- #212, #7226, #542: emit column position in gas assembly `.loc`
   (Frédéric Bour, Anton Bachin)
 
-- GPR#207: Colors in compiler messages (warnings, errors)
+- #207: Colors in compiler messages (warnings, errors)
   configure with -color {auto|always|never} or TERM=dumb
   (Simon Cruanes, review by Gabriel Scherer)
 
-- GPR#258: more precise information on PowerPC instruction sizes
+- #258: more precise information on PowerPC instruction sizes
   (Pierre Chambart, Xavier Leroy)
 
-- GPR#263: improve code generation for if-equivalents of (&&) and (||)
+- #263: improve code generation for if-equivalents of (&&) and (||)
   (Pierre Chambart)
 
-- GPR#270: Make [transl_exception_constructor] generate [Immutable] blocks
+- #270: Make [transl_exception_constructor] generate [Immutable] blocks
   (Mark Shinwell)
 
-- GPR#271: Fix incorrect mutability flag when records are built using "with"
+- #271: Fix incorrect mutability flag when records are built using "with"
   (Mark Shinwell)
 
-- GPR#275: native-code generator for IBM z System running Linux.
+- #275: native-code generator for IBM z System running Linux.
   In memoriam Gene Amdahl, 1922-2015.
   (Bill O'Farrell, Tristan Amini, Xavier Leroy)
 
-- GPR#282: relax short-paths safety check in presence of module aliases, take
+- #282: relax short-paths safety check in presence of module aliases, take
   penalty into account while building the printing map.
   (Thomas Refis, Leo White)
 
-- GPR#306: Instrument the compiler to debug performance regressions
+- #306: Instrument the compiler to debug performance regressions
   (Pierre Chambart)
 
-- GPR#319: add warning 58 for missing cmx files, and
+- #319: add warning 58 for missing cmx files, and
   extend -opaque option to mli files: a missing .cmx does not warn
   if the corresponding .cmi is compiled -opaque.
   (Leo White)
 
-- GPR#388: OCAML_FLEXLINK environment variable allows overriding flexlink
+- #388: OCAML_FLEXLINK environment variable allows overriding flexlink
   command (David Allsopp)
 
-- GPR#392: put all parsetree invariants in a new module Ast_invariants
+- #392: put all parsetree invariants in a new module Ast_invariants
   (Jérémie Dimino)
 
-- GPR#407: don't display the name of compiled .c files when calling the
+- #407: don't display the name of compiled .c files when calling the
   Microsoft C Compiler (same as the assembler).
   (David Allsopp)
 
-- GPR#431: permit constant float arrays to be eligible for pattern match
+- #431: permit constant float arrays to be eligible for pattern match
   branch merging
   (Pierre Chambart)
 
-- GPR#455: provide more debugging information to Js_of_ocaml
+- #455: provide more debugging information to Js_of_ocaml
   (Jérôme Vouillon)
 
-- GPR#514, GPR#554: Added several command-line flags to explicitly enable
+- #514, #554: Added several command-line flags to explicitly enable
   settings that are currently the default:
   `-alias-deps`, `-app-funct`, `-no-keep-docs`, `-no-keep-locs`,
   `-no-principal`, `-no-rectypes`, `-no-strict-formats`
   (Demi Obenour)
 
-- GPR#545: use reraise to preserve backtrace on
+- #545: use reraise to preserve backtrace on
   `match .. with exception e -> raise e`
   (Nicolás Ojeda Bär, review by Gabriel Scherer)
 
 ### Runtime system:
 
-* GPR#596: make string/bytes distinguishable in the underlying
+* #596: make string/bytes distinguishable in the underlying
   compiler implementation; caml_fill_string and caml_create_string are
   deprecated and will be removed in the future, please use
   caml_fill_bytes and caml_create_bytes for migration
   (Hongbo Zhang, review by Damien Doligez, Alain Frisch, and Hugo Heuzard)
 
-- PR#3612, PR#92: allow allocating custom block with finalizers
+- #3612, #2429: allow allocating custom block with finalizers
   in the minor heap.
   (Pierre Chambart)
 
-* PR#6517: use ISO C99 types {,u}int{32,64}_t in preference to our homegrown
+* #6517: use ISO C99 types {,u}int{32,64}_t in preference to our homegrown
   types {,u}int{32,64}.
   C stubs may have to be updated as {,u}int{32,64}_t are not defined anymore.
   (Xavier Leroy)
 
-- PR#6760: closures evaluated in the toplevel can now be marshalled
+- #6760: closures evaluated in the toplevel can now be marshalled
   (whitequark, review by Jacques-Henri Jourdan)
 
-- PR#6902, GPR#210: emit a runtime warning on stderr
+- #6902, #210: emit a runtime warning on stderr
   when finalizing an I/O channel which is still open:
     "channel opened on file '...' dies without being closed"
   this is controlled by OCAMLRUNPARAM=W=1 or with Sys.enable_runtime_warnings.
@@ -2816,198 +3760,201 @@ OCaml 4.03.0 (25 Apr 2016):
   if available.
   (Xavier Leroy)
 
-- PR#6910, GPR#224: marshaling (output_value, input_value, et al)
+- #6910, #224: marshaling (output_value, input_value, et al)
   now support marshaled data bigger than 4 Gb.
   (Xavier Leroy)
 
-* GPR#226: select higher levels of optimization for GCC >= 3.4 and Clang
+* #22: The undocumented layout of weak arrays has been changed. Finalisation
+  functions are now run before the erasure of the corresponding values.
+
+* #226: select higher levels of optimization for GCC >= 3.4 and Clang
   when compiling the run-time system and C stub code.
   "-std=gnu99 -O2 -fno-strict-aliasing -fwrapv" is used by default.
   This also affects default flags for user stubs compiled with "ocamlc -c foo.c"
   and may uncover bugs in them.
   (Xavier Leroy)
 
-- GPR#262: Multiple GC roots per compilation unit
+- #262: Multiple GC roots per compilation unit
   (Pierre Chambart, Mark Shinwell, review by Damien Doligez)
 
-* GPR#297: Several changes to improve the worst-case GC pause time.
+* #297: Several changes to improve the worst-case GC pause time.
   Changes Gc.control and Gc.major_slice and adds functions to the Gc module.
   (Damien Doligez, with help from François Bobot, Thomas Braibant, Leo White)
 
-- GPR#325: Add v=0x400 flag to OCAMLRUNPARAM to display GC stats on exit
+- #325: Add v=0x400 flag to OCAMLRUNPARAM to display GC stats on exit
   (Louis Gesbert, review by Alain Frisch)
 
 ### Standard library:
 
-- PR#1460, GPR#230: Array.map2, Array.iter2
+- #7848, #230: Array.map2, Array.iter2
   (John Christopher McAlpine)
 
-- PR#5197, GPR#63: Arg: allow flags such as --flag=arg as well as --flag arg
+- #5197, #63: Arg: allow flags such as --flag=arg as well as --flag arg
   (Richard Jones)
 
-- PR#6017, PR#7034, GPR#267: More efficient ifprintf implementation
+- #6017, #7034, #267: More efficient ifprintf implementation
   (Jeremy Yallop, review by Gabriel Scherer)
 
-- PR#6296: Some documentation on the floating-point representations
+- #6296: Some documentation on the floating-point representations
     recognized by Pervasives.float_of_string
   (Xavier Leroy)
 
-- PR#6316: Scanf.scanf failure on %u formats when reading big integers
+- #6316: Scanf.scanf failure on %u formats when reading big integers
   (Xavier Leroy, Benoît Vaugon)
 
-- PR#6321: guarantee that "hypot infinity nan = infinity"
+- #6321: guarantee that "hypot infinity nan = infinity"
   (for conformance with ISO C99)
   (Xavier Leroy)
 
-- PR#6390, GPR#36: expose Sys.{int_size,max_wosize} for js_of_ocaml portability
+- #6390, #36: expose Sys.{int_size,max_wosize} for js_of_ocaml portability
   (Hugo Heuzard)
 
-- PR#6449: Add Map.union
+- #6449: Add Map.union
   (Alain Frisch)
 
-* PR#6494: Add 'equal' functions in modules
+* #6494: Add 'equal' functions in modules
   Bytes, Char, Digest, Int32, Int64, Nativeint, and String
   Users defining their own modules with signature 'module type of Int32'
   have to extend their implementation.
   (Romain Calascibetta)
 
-* PR#6524, GPR#79: Filename: Optional ?perms argument to open_temp_file
+* #6524, #79: Filename: Optional ?perms argument to open_temp_file
   May break partial applications of the function (fix by passing ?perms:None)
-  (Daniel Bünzli, review by Jacques-Pascal Deplaix)
+  (Daniel Bünzli, review by Kate Deplaix)
 
-* PR#6525, GPR#80: Add Uchar module to the standard library
+* #6525, #80: Add Uchar module to the standard library
   May introduce module name conflicts with existing projects.
   (Daniel Bünzli, review by Yoriyuki Yamagata and Damien Doligez)
 
-- PR#6577: improve performance of %L, %l, %n, %S, %C format specifiers
+- #6577: improve performance of %L, %l, %n, %S, %C format specifiers
   (Alain Frisch)
 
-- PR#6585: fix memory leak in win32unix/createprocess.c
+- #6585: fix memory leak in win32unix/createprocess.c
   (Alain Frisch, report by user 'aha')
 
-- PR#6645, GPR#174: Guarantee that Set.add, Set.remove, Set.filter
+- #6645, #174: Guarantee that Set.add, Set.remove, Set.filter
   return the original set if no change is required
   (Alain Frisch, Mohamed Iguernlala)
 
-- PR#6649, GPR#222: accept (int_of_string "+3")
+- #6649, #222: accept (int_of_string "+3")
   (John Christopher McAlpine)
 
-- PR#6694, PR#6695, GPR#124: deprecate functions using ISO-8859-1 character set
+- #6694, #6695, #124: deprecate functions using ISO-8859-1 character set
   in Char, Bytes, String and provide alternatives *_acii using US-ASCII.
   Affected functions:
     {Char,String,Bytes}.{uppercase,lowercase},
     {String,Bytes}.{capitalize,uncaptialize}
   (whitequark, review by Damien Doligez)
 
-- GPR#22: Add the Ephemeron module that implements ephemerons and weak
+- #22: Add the Ephemeron module that implements ephemerons and weak
   hash table
   (François Bobot, review by Damien Doligez, Daniel Bünzli,
   Alain Frisch, Pierre Chambart)
 
-- GPR#164: more efficient (branchless) implementation of Pervasives.compare
+- #164: more efficient (branchless) implementation of Pervasives.compare
   specialized at type 'float'.
   (Vladimir Brankov)
 
-- GPR#175: Guarantee that Map.add, Map.remove, Map.filter
+- #175: Guarantee that Map.add, Map.remove, Map.filter
   return the original map if no change is required.
   (Mohamed Iguernlala)
 
-- GPR#201: generalize types of Printf.{ifprintf,ikfprintf}
+- #201: generalize types of Printf.{ifprintf,ikfprintf}
   (Maxence Guesdon)
 
-- GPR#216: add the missing POSIX.1-2001 signals in Sys
+- #216: add the missing POSIX.1-2001 signals in Sys
   (Guillaume Bury)
 
-- GPR#239: remove type-unsafe code from Stream
+- #239: remove type-unsafe code from Stream
   (Pierre Chambart, review by Gabriel Scherer and Jeremy Yallop)
 
-- GPR#250: Check for negative start element in Array.sub
+- #250: Check for negative start element in Array.sub
   (Jeremy Yallop)
 
-- GPR#265: new implementation of Queue avoiding Obj.magic
+- #265: new implementation of Queue avoiding Obj.magic
   (Jérémie Dimino)
 
-- GPR#268, GPR#303: '%h' and '%H' modifiers for printf and scanf to
+- #268, #303: '%h' and '%H' modifiers for printf and scanf to
   support floating-point numbers in hexadecimal notation
   (Xavier Leroy, Benoît Vaugon)
 
-- GPR#272: Switch classify_float to [@@unboxed]
+- #272: Switch classify_float to [@@unboxed]
   (Alain Frisch)
 
 - Improve speed of classify_float by not going through fpclassify()
   (Alain Frisch, Xavier Leroy)
 
-- GPR#277: Switch the following externals to [@@unboxed]:
+- #277: Switch the following externals to [@@unboxed]:
   * {Nativeint,Int32,Int64}.{of,to}_float
   * Int{32,64}.float_of_bits
   * Int{32,64}.bits_of_float
   (Jérémie Dimino)
 
-- GPR#281: Switch the following externals to [@@unboxed]:
+- #281: Switch the following externals to [@@unboxed]:
   * Sys.time (and [@@noalloc])
   * Pervasives.ldexp (and [@@noalloc])
   * Pervasives.compare for float, nativeint, int32, int64.
   (François Bobot)
 
-- PR#3622, GPR#195: add function Stack.fold
+- #3622, #195: add function Stack.fold
   (Simon Cruanes)
 
-- GPR#329: Add exists, for_all,  mem and memq functions in Array
+- #329: Add exists, for_all,  mem and memq functions in Array
   (Bernhard Schommer)
 
-- GPR#337: Add [Hashtbl.filter_map_inplace]
+- #337: Add [Hashtbl.filter_map_inplace]
   (Alain Frisch)
 
-- GPR#356: Add [Format.kasprintf]
+- #356: Add [Format.kasprintf]
   (Jérémie Dimino, Mark Shinwell)
 
 ### Type system:
 
-- PR#5545: Type annotations on methods cannot control the choice of abbreviation
+- #5545: Type annotations on methods cannot control the choice of abbreviation
   (Jacques Garrigue)
 
-* PR#6465: allow incremental weakening of module aliases.
+* #6465: allow incremental weakening of module aliases.
   This is done by adding equations to submodules when expanding aliases.
   In theory this may be incompatible is some corner cases defining a module
   type through inference, but no breakage known on published code.
   (Jacques Garrigue)
 
-- PR#6593: Functor application in tests/basic-modules fails after commit 15405
+- #6593: Functor application in tests/basic-modules fails after commit 15405
   (Jacques Garrigue)
 
 ### Toplevel and debugger:
 
-- PR#6113: Add descriptions to directives, and display them via #help
+- #6113: Add descriptions to directives, and display them via #help
   (Nick Giannarakis, Berke Durak, Francis Southern and Gabriel Scherer)
 
-- PR#6396: Warnings-as-errors not properly flushed in the toplevel
+- #6396: Warnings-as-errors not properly flushed in the toplevel
   (Alain Frisch)
 
-- PR#6401: use proper error reporting for toplevel environment initialization:
+- #6401: use proper error reporting for toplevel environment initialization:
   no more Env.Error(_) at start time
   (Gabriel Scherer, Alain Frisch)
 
-- PR#6468: toplevel now supports backtraces if invoked with OCAMLRUNPARAM=b
+- #6468: toplevel now supports backtraces if invoked with OCAMLRUNPARAM=b
   (whitequark and Jake Donham,
    review by Gabriel Scherer and Jacques-Henri Jourdan)
 
-- PR#6906: wrong error location for unmatched paren with #use in toplevel
+- #6906: wrong error location for unmatched paren with #use in toplevel
   (Damien Doligez, report by Kenichi Asai)
 
-- PR#6935, GPR#298: crash in debugger when load_printer is given a directory
+- #6935, #298: crash in debugger when load_printer is given a directory
   (Junsong Li, review by Gabriel Scherer)
 
-- PR#7081: report preprocessor warnings in the toplevel
+- #7081: report preprocessor warnings in the toplevel
   (Valentin Gatien-Baron, review by Jérémie Dimino)
 
-- PR#7098: Loss of ppx context in toplevel after an exception
+- #7098: Loss of ppx context in toplevel after an exception
   (Alain Frisch, report by whitequark)
 
-- PR#7101: The toplevel does not close in_channel for libraries specified on
+- #7101: The toplevel does not close in_channel for libraries specified on
   its command line
   (Alain Frisch)
 
-- PR#7119: the toplevel does not respect [@@@warning]
+- #7119: the toplevel does not respect [@@@warning]
   (Alain Frisch, report by Gabriel Radanne)
 
 ### Other libraries:
@@ -3018,7 +3965,7 @@ OCaml 4.03.0 (25 Apr 2016):
   now causes an error.
   (Xavier Leroy)
 
-- PR#4023 and GPR#68: add Unix.sleepf (sleep with sub-second resolution)
+- #4023 and #68: add Unix.sleepf (sleep with sub-second resolution)
   (Evgenii Lepikhin and Xavier Leroy)
 
 * Protect Unix.sleep against interruptions by handled signals.
@@ -3026,546 +3973,546 @@ OCaml 4.03.0 (25 Apr 2016):
   Now, the sleep is restarted until the given time is elapsed.
   (Xavier Leroy)
 
-* PR#6120, GPR#462: implement Unix.symlink and Unix.readlink on
+* #6120, #462: implement Unix.symlink and Unix.readlink on
   Windows. Unix.symlink has a new optional argument to_dir (ignored on
   non-native Windows platforms). stat functions reimplemented to avoid
   buggy Microsoft CRT implementations (native Windows only)
   (David Allsopp, review by Daniel Bünzli)
 
-- PR#6263: add kind_size_in_bytes and size_in_bytes functions
+- #6263: add kind_size_in_bytes and size_in_bytes functions
   to Bigarray module.
   (Runhang Li, review by Mark Shinwell)
 
-- PR#6289: Unix.utimes uses the current time only if both arguments
+- #6289: Unix.utimes uses the current time only if both arguments
     are exactly 0.0.  Also, use sub-second resolution if available.
   (Xavier Leroy, report by Christophe Troestler)
 
-- PR#6896: serious reimplementation of Big_int.float_of_big_int and
+- #6896: serious reimplementation of Big_int.float_of_big_int and
   Ratio.float_of_ratio, ensuring that the result is correctly rounded.
   (Xavier Leroy)
 
-- PR#6989: in Str library, make sure that all \(...\) groups are binding
+- #6989: in Str library, make sure that all \(...\) groups are binding
     and can be consulted with Str.matched_group.  There used to be
     a limitation to 32 binding groups.
   (Xavier Leroy)
 
-- PR#7013: spurious wake-up in the Event module
+- #7013: spurious wake-up in the Event module
   (Xavier Leroy)
 
-- PR#7024: in documentation of Str regular expressions, clarify what
+- #7024: in documentation of Str regular expressions, clarify what
     "end of line" means for "^" and "$" regexps.
   (Xavier Leroy, question by Fredrik Lindgren)
 
-- PR#7209: do not run at_exit handlers in [Unix.create_process] and
+- #7209: do not run at_exit handlers in [Unix.create_process] and
   similar functions when the [exec] call fails in the child process
   (Jérémie Dimino)
 
 ### OCamldep:
 
-- GPR#286: add support for module aliases
+- #286: add support for module aliases
   (Jacques Garrigue)
 
 ### Manual:
 
-- GPR#302: The OCaml reference manual is now included in the manual/
+- #302: The OCaml reference manual is now included in the manual/
   subdirectory of the main OCaml source repository. Contributions to
   the manual are warmly welcome.
   (François Bobot, review by Florian Angeletti)
 
-- PR#6601: replace strcpy with caml_strdup in sample code
+- #6601: replace strcpy with caml_strdup in sample code
   (Christopher Zimmermann)
 
-- PR#6676: ongoing simplification of the "Language Extensions" section
+- #6676: ongoing simplification of the "Language Extensions" section
   (Alain Frisch, John Whitington)
 
-- PR#6898: Update win32 support documentation of the Unix library
+- #6898: Update win32 support documentation of the Unix library
   (Damien Doligez, report by Daniel Bünzli)
 
-- PR#7092, GPR#379: Add missing documentation for new 4.03 features
+- #7092, #379: Add missing documentation for new 4.03 features
   (Florian Angeletti)
 
-- PR#7094, GPR#468, GPR#551: add new section 8.5 to document warnings
+- #7094, #468, #551: add new section 8.5 to document warnings
   The general idea is to document warnings that may require explanations.
   Currently documented warnings are:
   - 52: Fragile constant pattern.
   - 57: Ambiguous or-pattern variables under guard
   (Florian Angeletti and Gabriel Scherer)
 
-- PR#7109, GPR#380: Fix bigarray documentation layout
+- #7109, #380: Fix bigarray documentation layout
   (Florian Angeletti, Leo White)
 
 ### Bug fixes:
 
-- PR#3612: memory leak in bigarray read from file
+- #3612: memory leak in bigarray read from file
   (Pierre Chambart, report by Gary Huber)
 
-* PR#4166, PR#6956: force linking when calling external C primitives
+* #4166, #6956: force linking when calling external C primitives
   (Jacques Garrigue, reports by Markus Mottl and Christophe Troestler)
 
-* PR#4466, PR#5325: under Windows, concurrent read and write operations
+* #4466, #5325: under Windows, concurrent read and write operations
     on the same socket could block unexpectedly.  Fixed by keeping sockets
     in asynchronous mode rather than creating them in synchronous mode.
   (Xavier Leroy)
 
-* PR#4539: change exception string raised when comparing functional values
+* #4539: change exception string raised when comparing functional values
   May break programs matching on the string argument of Invalid_argument.
   Matching on the string argument of Invalid_argument or Failure is a
   programming mistake: these strings may change in future versions.
   (Nicolas Braud-Santoni, report by Eric Cooper)
 
-- PR#4832: Filling bigarrays may block out runtime
+- #4832: Filling bigarrays may block out runtime
   (Markus Mottl)
 
-- PR#5663: program rejected due to nongeneralizable type variable that
+- #5663: program rejected due to nongeneralizable type variable that
     appears nowhere
   (Jacques Garrigue, report by Stephen Weeks)
 
-- PR#5780: report more informative type names in GADTs error messages
+- #5780: report more informative type names in GADTs error messages
   (Jacques Garrigue, report by Sebastien Furic)
 
-- PR#5887: move the byterun/*.h headers to byterun/caml/*.h to avoid header
+- #5887: move the byterun/*.h headers to byterun/caml/*.h to avoid header
     name clashes
   (Jérôme Vouillon and Adrien Nader and whitequark)
 
-* PR#6081: ocaml now adds script's directory to search path, not current
+* #6081: ocaml now adds script's directory to search path, not current
     directory
   (Thomas Leonard and Damien Doligez)
 
-- PR#6108, PR#6802: fail cleanly if dynlink.cma or ocamltoplevel.cma
+- #6108, #6802: fail cleanly if dynlink.cma or ocamltoplevel.cma
     are loaded inside the toplevel loop.
   (Xavier Leroy)
 
-- PR#6171: Confusing error message when a type escapes its scope.
+- #6171: Confusing error message when a type escapes its scope.
   (Jacques Garrigue and Leo White, report by John Whitington)
 
-- PR#6340: Incorrect handling of \r when processing "Windows" source files
+- #6340: Incorrect handling of \r when processing "Windows" source files
   (Damien Doligez, report by David Allsopp)
 
-- PR#6342: Incorrect error message when type constraints differ
+- #6342: Incorrect error message when type constraints differ
   (Alain Frisch, report by Philippe Wang)
 
-* PR#6521: {Bytes,Char,String}.escaped were locale-dependent
+* #6521: {Bytes,Char,String}.escaped were locale-dependent
   we now escape all non-ASCII-printable instead of a locale-dependent subset.
   (Damien Doligez, report by Jun Furuse)
 
-- PR#6526: ocamllex should not warn on unescaped newline inside comments
+- #6526: ocamllex should not warn on unescaped newline inside comments
   (Damien Doligez, report by user 'dhekir')
 
-- PR#6341: ocamldoc -colorize-code adds spurious 
tags to
 blocks
+- #6341: ocamldoc -colorize-code adds spurious 
tags to
 blocks
   (Maxence Guesdon, report by Damien Doligez)
 
-- PR#6560: Wrong failure message for {Int32,Int64,NativeInt}.of_string
+- #6560: Wrong failure message for {Int32,Int64,NativeInt}.of_string
   It reported (Failure "int_of_string"), now "Int32.of_string" etc.
   (Maxime Dénès and Gabriel Scherer)
 
-- PR#6648: show_module should indicate its elision
+- #6648: show_module should indicate its elision
   (Jacques Garrigue, report by Leo White)
 
-- PR#6650: Cty_constr not handled correctly by Subst
+- #6650: Cty_constr not handled correctly by Subst
   (Jacques Garrigue, report by Leo White)
 
-- PR#6651: Failing component lookup
+- #6651: Failing component lookup
   (Jacques Garrigue, report by Leo White)
 
-* PR#6664: Crash when finalising lazy values of the wrong type.
+* #6664: Crash when finalising lazy values of the wrong type.
   (Damien Doligez)
 
-- PR#6672: Unused variance specification allowed in with constraint
+- #6672: Unused variance specification allowed in with constraint
   (Jacques Garrigue, report by Leo White)
 
-- PR#6677: Allow to disable warning 39 (useless "rec") with [@ocaml.warning]
+- #6677: Allow to disable warning 39 (useless "rec") with [@ocaml.warning]
   applied to the first value binding of the would-be "rec" declaration
   (Alain Frisch, report by Jun Furuse)
 
-- PR#6744: Univars can escape through polymorphic variants (partial fix)
+- #6744: Univars can escape through polymorphic variants (partial fix)
   (Jacques Garrigue, report by Leo White)
 
-- PR#6752: Extensible variant types and scope escaping
+- #6752: Extensible variant types and scope escaping
   A side-effect of the fix is that (ocamlc -i) sometimes reports
   (type-sound) invalid signature, with a type used before its declaration.
   (Jacques Garrigue, report by Maxence Guesdon)
 
-- PR#6762: improve warning 45 in presence of re-exported type definitions
+- #6762: improve warning 45 in presence of re-exported type definitions
   (Warning 45: open statement shadows the constructor)
   (Alain Frisch, report by Olivier Andrieu)
 
-- PR#6776: Failure to kill the "tick" thread, segfault when exiting the runtime
+- #6776: Failure to kill the "tick" thread, segfault when exiting the runtime
   (Damien Doligez, report by Thomas Braibant)
 
-- PR#6780: Poor error message for wrong -farch and -ffpu options (ocamlopt, ARM)
+- #6780: Poor error message for wrong -farch and -ffpu options (ocamlopt, ARM)
   (Xavier Leroy, report by whitequark)
 
-- PR#6805: Duplicated expression in case of hole in a non-failing switch.
+- #6805: Duplicated expression in case of hole in a non-failing switch.
   (Luc Maranget)
 
-* PR#6808: the parsing of OCAMLRUNPARAM is too lax
+* #6808: the parsing of OCAMLRUNPARAM is too lax
   (Damien Doligez)
 
-- PR#6874: Inefficient code generated for module function arguments
+- #6874: Inefficient code generated for module function arguments
   (Jacques Garrigue, report by Markus Mottl)
 
-- PR#6888: The list command of ocamldebug uses the wrong file
+- #6888: The list command of ocamldebug uses the wrong file
   (Damien Doligez, report by Pierre-Marie Pédrot)
 
-- PR#6897: Bad error message for some pattern matching on extensible variants
+- #6897: Bad error message for some pattern matching on extensible variants
   (Alain Frisch, report by Gabriel Radanne)
 
-- PR#6899: Optional parameters and non generalizable type variables
+- #6899: Optional parameters and non generalizable type variables
   (Thomas Refis and Leo White)
 
-- PR#6907: Stack overflow printing error in class declaration
+- #6907: Stack overflow printing error in class declaration
   (Jacques Garrigue, report by Ivan Gotovchits)
 
-- PR#6931: Incorrect error message on type error inside record construction
+- #6931: Incorrect error message on type error inside record construction
   (Damien Doligez, report by Leo White)
 
-- PR#6938: fix regression on "%047.27{l,L,n}{d,i,x,X,o,u}"
+- #6938: fix regression on "%047.27{l,L,n}{d,i,x,X,o,u}"
   (Benoît Vaugon, report by Arduino Cascella)
 
-- PR#6944: let module X = Path in … is not typed as a module alias
+- #6944: let module X = Path in … is not typed as a module alias
   (Jacques Garrigue, report by Frédéric Bour)
 
-- PR#6945 and GPR#227: protect Sys and Unix functions against string
+- #6945 and #227: protect Sys and Unix functions against string
     arguments containing the null character '\000'
   (Simon Cruanes and Xavier Leroy, report by Daniel Bünzli)
 
-- PR#6946: Uncaught exception with wrong type for "%ignore"
+- #6946: Uncaught exception with wrong type for "%ignore"
   (Jacques Garrigue, report by Leo White)
 
-- PR#6954: Infinite loop in type checker with module aliases
+- #6954: Infinite loop in type checker with module aliases
   (Jacques Garrigue, report by Markus Mottl)
 
-- PR#6972, GPR#276: 4.02.3 regression on documentation comments in .cmt files
+- #6972, #276: 4.02.3 regression on documentation comments in .cmt files
   (Leo White, report by Olivier Andrieu)
 
-- PR#6977: String literals in comments interpret escape sequences
+- #6977: String literals in comments interpret escape sequences
   (Damien Doligez, report by Daniel Bünzli and David Sheets)
 
-- PR#6980: Assert failure from polymorphic variants and existentials
+- #6980: Assert failure from polymorphic variants and existentials
   (Jacques Garrigue, report by Leo White)
 
-- PR#6981: Ctype.Unify(_) with associated functor arg refering to previous one
+- #6981: Ctype.Unify(_) with associated functor arg referring to previous one
   (Jacques Garrigue, report by Nicholas Labich)
 
-- PR#6982: unexpected type error when packing a module alias
+- #6982: unexpected type error when packing a module alias
   (Jacques Garrigue, report by Valentin Gatien-Baron)
 
-- PR#6985: `module type of struct include Bar end exposes
+- #6985: `module type of struct include Bar end exposes
            %s#row when Bar contains private row types
   (Jacques Garrigue, report by Nicholas Labich)
 
-- PR#6992: Segfault from bug in GADT/module typing
+- #6992: Segfault from bug in GADT/module typing
   (Jacques Garrigue, report by Stephen Dolan)
 
-- PR#6993: Segfault from recursive modules violating exhaustiveness assumptions
+- #6993: Segfault from recursive modules violating exhaustiveness assumptions
   (Jacques Garrigue, report by Stephen Dolan)
 
-- PR#6998: Typer fails reading unnecessary cmis with -no-alias-deps and -w -49
+- #6998: Typer fails reading unnecessary cmis with -no-alias-deps and -w -49
   (Leo White, report by Valentin Gatien-Baron)
 
-- PR#7003: String.sub may cause segmentation fault on sizes above 2^31
+- #7003: String.sub may cause segmentation fault on sizes above 2^31
   (Damien Doligez, report by Radek Micek)
 
-- PR#7008: Fatal error in ocamlc with empty compilation unit name
+- #7008: Fatal error in ocamlc with empty compilation unit name
   (Damien Doligez, report by Cesar Kunz)
 
-- PR#7012: Variable name forgotten when it starts with a capital letter
+- #7012: Variable name forgotten when it starts with a capital letter
   (Jacques Garrigue, Gabriel Scherer,
    report by Thomas Leonard and Florian Angeletti)
 
-- PR#7016: fix Stack overflow in GADT typing
+- #7016: fix Stack overflow in GADT typing
   Note: Equi-recursive types are considered when checking GADT pattern
   exhaustiveness, even when -rectypes is not used.
   (Jacques Garrigue, report by Mikhail Mandrykin)
 
-- PR#7030: libasmrun_shared.so fails to build on SPARC Solaris
+- #7030: libasmrun_shared.so fails to build on SPARC Solaris
   (report and fix by Patrick Star)
 
-- PR#7036: Module alias is not taken into account when checking module
+- #7036: Module alias is not taken into account when checking module
   type compatibility (in a class type)
   (Jacques Garrigue)
 
-- PR#7037: more reproducible builds, don't put temp file names into objects
+- #7037: more reproducible builds, don't put temp file names into objects
   (Xavier Leroy)
 
-- PR#7038: out of memory condition in caml_io_mutex_lock
+- #7038: out of memory condition in caml_io_mutex_lock
   (Xavier Leroy, report by Marc Lasson)
 
-- PR#7039: Unix.getsockname returns garbage for unnamed PF_UNIX sockets
+- #7039: Unix.getsockname returns garbage for unnamed PF_UNIX sockets
   (Xavier Leroy)
 
-- PR#7042 and GPR#295: CSE optimization confuses the FP literals +0.0 and -0.0
+- #7042 and #295: CSE optimization confuses the FP literals +0.0 and -0.0
   (Xavier Leroy)
 
-- PR#7075: Fix repetitions in ocamldoc generated documentation
+- #7075: Fix repetitions in ocamldoc generated documentation
   (Florian Angeletti)
 
-- PR#7082: Object type in recursive module's `with` annotation
+- #7082: Object type in recursive module's `with` annotation
   (Jacques Garrigue and Alain Frisch, report by Nicholas Labich)
 
-- PR#7096: ocamldoc uses an incorrect subscript/superscript style
+- #7096: ocamldoc uses an incorrect subscript/superscript style
   (Gabriel Scherer, report by user 'pierpa')
 
-- PR#7108: ocamldoc, have -html preserve custom/extended html generators
+- #7108: ocamldoc, have -html preserve custom/extended html generators
   (Armaël Guéneau)
 
-- PR#7111: reject empty let bindings instead of printing incorrect syntax
+- #7111: reject empty let bindings instead of printing incorrect syntax
   (Jérémie Dimino)
 
-* PR#7113: -safe-string can break GADT compatibility check
+* #7113: -safe-string can break GADT compatibility check
   bytes and string are now considered compatible even with -safe-string,
   which may break exhaustivity for code assuming they were disjoint
   (Jacques Garrigue, report by Jeremy Yallop)
 
-- PR#7115: shadowing in a branch of a GADT match breaks unused variable warning
+- #7115: shadowing in a branch of a GADT match breaks unused variable warning
   (Alain Frisch, report by Valentin Gatien-Baron)
 
-- PR#7133, GPR#450: generate local jump labels on OS X
+- #7133, #450: generate local jump labels on OS X
   (Bart Jacobs)
 
-- PR#7135: only warn about ground coercions in -principal mode
+- #7135: only warn about ground coercions in -principal mode
   (Jacques Garrigue, report by Jeremy Yallop)
 
-* PR#7152: Typing equality involving non-generalizable type variable
+* #7152: Typing equality involving non-generalizable type variable
   A side-effect of the fix is that, for deeply nested non generalizable
   type variables, having an interface file may no longer be sufficient,
-  and you may have to add a local type annotation (cf PR#7313)
+  and you may have to add a local type annotation (cf #7313)
   (Jacques Garrigue, report by François Bobot)
 
-- PR#7160: Type synonym definitions can weaken gadt constructor types
+- #7160: Type synonym definitions can weaken gadt constructor types
   (Jacques Garrigue, report by Mikhail Mandrykin)
 
-- PR#7181: Misleading error message with GADTs and polymorphic variants
+- #7181: Misleading error message with GADTs and polymorphic variants
   (Jacques Garrigue, report by Pierre Chambart)
 
-- PR#7182: Assertion failure with recursive modules and externals
+- #7182: Assertion failure with recursive modules and externals
   (Jacques Garrigue, report by Jeremy Yallop)
 
-- PR#7196: "let open" is not correctly pretty-printed to the left of a ';'
+- #7196: "let open" is not correctly pretty-printed to the left of a ';'
   (Gabriel Scherer, report by Christophe Raffalli)
 
-- PR#7214: Assertion failure in Env.add_gadt_instances
+- #7214: Assertion failure in Env.add_gadt_instances
   (Jacques Garrigue, report by Stephen Dolan)
 
-- PR#7220: fix a memory leak when using both threads and exception backtraces
+- #7220: fix a memory leak when using both threads and exception backtraces
   (Gabriel Scherer, review by François Bobot, report by Rob Hoes)
 
-- PR#7222: Escaped existential type
+- #7222: Escaped existential type
   (Jacques Garrigue, report by Florian Angeletti)
 
-- PR#7230: Scrutinee discarded in match with only refutation cases
+- #7230: Scrutinee discarded in match with only refutation cases
   (Jacques Garrigue, report by Jeremy Yallop)
 
-- PR#7234: Compatibility check wrong for abstract type constructors
+- #7234: Compatibility check wrong for abstract type constructors
   (Jacques Garrigue, report by Stephen Dolan)
 
-- PR#7324: OCaml 4.03.0 type checker dies with an assert failure when
-  given some cyclic recusive module expression
+- #7324: OCaml 4.03.0 type checker dies with an assert failure when
+  given some cyclic recursive module expression
   (Jacques Garrigue, report by jmcarthur)
 
-- PR#7368: Manual major GC fails to compact the heap
+- #7368: Manual major GC fails to compact the heap
   (Krzysztof Pszeniczny)
 
-- GPR#205: Clear caml_backtrace_last_exn before registering as root
+- #205: Clear caml_backtrace_last_exn before registering as root
   (report and fix by Frédéric Bour)
 
-- GPR#220: minor -dsource error on recursive modules
+- #220: minor -dsource error on recursive modules
   (Hongbo Zhang)
 
-- GPR#228: fix a dangling internal pointer in (bytecode )debug_info
+- #228: fix a dangling internal pointer in (bytecode )debug_info
   (Gabriel Scherer and Mark Shinwell and Xavier Leroy)
 
-- GPR#233: Make CamlinternalMod.init_mod robust to optimization
+- #233: Make CamlinternalMod.init_mod robust to optimization
   (Pierre Chambart, Mark Shinwell)
 
-- GPR#249: fix a few hardcoded ar commands
+- #249: fix a few hardcoded ar commands
   (Daniel Bünzli)
 
-- GPR#251: fix cross-compilation with ocamldoc enabled
+- #251: fix cross-compilation with ocamldoc enabled
   (whitequark)
 
-- GPR#280: Fix stdlib dependencies for .p.cmx
+- #280: Fix stdlib dependencies for .p.cmx
   (Pierre Chambart, Mark Shinwell)
 
-- GPR#283: Fix memory leaks in intern.c when OOM is raised
+- #283: Fix memory leaks in intern.c when OOM is raised
   (Marc Lasson, review by Alain Frisch)
 
-- GPR#22: Fix the cleaning of weak pointers. In very rare cases
+- #22: Fix the cleaning of weak pointers. In very rare cases
   accessing a value during the cleaning of the weak pointers could
   result in the value being removed from one weak arrays and kept in
   another one. That breaks the property that a value is removed from a
   weak pointer only when it is dead and garbage collected.
   (François Bobot, review by Damien Doligez)
 
-- GPR#313: Prevent quadratic cases in CSE
+- #313: Prevent quadratic cases in CSE
   (Pierre Chambart, review by Xavier Leroy)
 
-- PR#6795, PR#6996: Make ocamldep report errors passed in
+- #6795, #6996: Make ocamldep report errors passed in
   [%ocaml.error] extension points
   (Jérémie Dimino)
 
-- GPR#355: make ocamlnat build again
+- #355: make ocamlnat build again
   (Jérémie Dimino, Thomas Refis)
 
-- GPR#405: fix compilation under Visual Studio 2015
+- #405: fix compilation under Visual Studio 2015
   (David Allsopp)
 
-- GPR#441: better type error location in presence of type constraints
+- #441: better type error location in presence of type constraints
   (Thomas Refis, report by Arseniy Alekseyev)
 
-- GPR#477: reallow docstrings inside object types, and inside polymorphic
+- #477: reallow docstrings inside object types, and inside polymorphic
   variant and arrow types
   (Thomas Refis)
 
 ### Features wishes:
 
-- PR#4518, GPR#29: change location format for reporting errors in ocamldoc
+- #4518, #29: change location format for reporting errors in ocamldoc
   (Sergei Lebedev)
 
-- PR#4714: List.cons
+- #4714: List.cons
 
-- PR#5418 (comments) : generate dependencies with $(CC) instead of gcc
+- #5418 (comments) : generate dependencies with $(CC) instead of gcc
   (Damien Doligez, report by Michael Grünewald)
 
-- PR#6167: OCAMLPARAM support for disabling PIC generation ("pic=0")
+- #6167: OCAMLPARAM support for disabling PIC generation ("pic=0")
   (Gabor Pali)
 
-- PR#6367, GPR#25: introduce Asttypes.arg_label to encode labelled arguments
+- #6367, #25: introduce Asttypes.arg_label to encode labelled arguments
   (Frédéric Bour and Jacques Garrigue)
 
-- PR#6452, GPR#140: add internal suport for custom printing formats
+- #6452, #140: add internal support for custom printing formats
   (Jérémie Dimino)
 
-- PR#6611: remove the option wrapper on optional arguments in the syntax tree
+- #6611: remove the option wrapper on optional arguments in the syntax tree
   (Alain Frisch, review by Damien Doligez, request by whitequark)
 
-- PR#6635: support M.[], M.(), M.{< >} and M.[| |]
+- #6635: support M.[], M.(), M.{< >} and M.[| |]
   (Jeremy Yallop, review by Gabriel Radanne)
 
-- PR#6691: install .cmt[i] files for stdlib and compiler-libs
+- #6691: install .cmt[i] files for stdlib and compiler-libs
   (David Sheets, request by Gabriel Radanne)
 
-- PR#6722: compatibility with x32 architecture (x86-64 in ILP32 mode).
+- #6722: compatibility with x32 architecture (x86-64 in ILP32 mode).
   ocamlopt is not supported, but bytecode compiles cleanly.
   (Adam Borowski and Xavier Leroy)
 
-- PR#6742: remove duplicate virtual_flag information from Tstr_class
+- #6742: remove duplicate virtual_flag information from Tstr_class
   (Gabriel Radanne and Jacques Garrigue)
 
-- PR#6719: improve Buffer.add_channel when not enough input is available
+- #6719: improve Buffer.add_channel when not enough input is available
   (Simon Cruanes)
 
-* PR#6816: reject integer and float literals directly followed by an identifier.
-  This was prevously read as two separate tokens.
+* #6816: reject integer and float literals directly followed by an identifier.
+  This was previously read as two separate tokens.
   [let abc = 1 in (+) 123abc] was accepted and is now rejected.
   (Hugo Heuzard)
 
-- PR#6876: improve warning 6 by listing the omitted labels.
+- #6876: improve warning 6 by listing the omitted labels.
   (Warning 6: Label omitted in function application)
   (Eyyüb Sari)
 
-- PR#6924: tiny optim to avoid some spilling of floats in x87
+- #6924: tiny optim to avoid some spilling of floats in x87
   (Alain Frisch)
 
-- GPR#111: `(f [@taillcall]) x y` warns if `f x y` is not a tail-call
+- #111: `(f [@taillcall]) x y` warns if `f x y` is not a tail-call
   (Simon Cruanes)
 
-- GPR#118: ocamldep -allow-approx: fallback to a lexer-based approximation
+- #118: ocamldep -allow-approx: fallback to a lexer-based approximation
   (Frédéric Bour)
 
-- GPR#137: add untypeast.ml (in open recursion style) to compiler-libs
+- #137: add untypeast.ml (in open recursion style) to compiler-libs
   (Gabriel Radanne)
 
-- GPR#142: add a CAMLdrop macro for undoing CAMLparam*/CAMLlocal*
+- #142: add a CAMLdrop macro for undoing CAMLparam*/CAMLlocal*
   (Thomas Braibant and Damien Doligez)
 
-- GPR#145: speeedup bigarray access by optimizing Cmmgen.bigarray_indexing
+- #145: speeedup bigarray access by optimizing Cmmgen.bigarray_indexing
   (Vladimir Brankov, review by Gabriel Scherer)
 
-- GPR#147: [type 'a result = Ok of 'a | Error of 'b] in Pervasives
+- #147: [type 'a result = Ok of 'a | Error of 'b] in Pervasives
   (Yaron Minsky)
 
-- GPR#156, GPR#279: optimize caml_frame_descriptors realloc (dynlink speedup)
+- #156, #279: optimize caml_frame_descriptors realloc (dynlink speedup)
   (Pierre Chambart, Alain Frisch,
    review by François Bobot, Xavier Leroy and Damien Doligez)
 
-- GPR#165, GPR#221: fix windows compilation warnings
+- #165, #221: fix windows compilation warnings
   (Bernhard Schommer, Gabriel Scherer, report by Alain Frisch)
 
-* GPR#170: Parse arbitrary precision integers.
+* #170: Parse arbitrary precision integers.
   Accept a single [A-Za-z] as modifier for integers (generalizing 'l','L','n')
   and floats.
   May cause breakage (ie. ppx preprocessor) because of changes in the parsetree.
-  This changes PR#6816 a little bit by reading the literal [123a] as a single
+  This changes #6816 a little bit by reading the literal [123a] as a single
   token that can later be rewritten by a ppx preprocessor.
   (Hugo Heuzard)
 
-- GPR#189: Added .dylib and .so as extensions for ocamlmklib
+- #189: Added .dylib and .so as extensions for ocamlmklib
   (Edgar Aroutiounian, whitequark)
 
-- GPR#191: Making gc.h and some part of memory.h public
+- #191: Making gc.h and some part of memory.h public
   (Thomas Refis)
 
-- GPR#196: Make [Thread.id] and [Thread.self] [noalloc]
+- #196: Make [Thread.id] and [Thread.self] [noalloc]
   (Clark Gaebel)
 
-- GPR#237: a CONTRIBUTING document
+- #237: a CONTRIBUTING document
   (François Bobot, Gabriel Scherer, review by Xavier Leroy)
 
-- GPR#245: remove a few remaining French comments
+- #245: remove a few remaining French comments
   (Florian Angeletti)
 
-- GPR#252: improve build instructions in MSVC Windows README
+- #252: improve build instructions in MSVC Windows README
   (Philip Daian)
 
-- GPR#308: add experimental support for NetBSD/arm (verified on RaspberryPi)
+- #308: add experimental support for NetBSD/arm (verified on RaspberryPi)
   (Rich Neswold)
 
-- GPR#335: Type error messages specifies if a type is abstract
+- #335: Type error messages specifies if a type is abstract
   because no corresponding cmi could be found.
   (Hugo Heuzard)
 
-- GPR#365: prevent printing just a single type variable on one side
+- #365: prevent printing just a single type variable on one side
   of a type error clash.
   (Hugo Heuzard)
 
-- GPR#383: configure: define _ALL_SOURCE for build on AIX7.1
+- #383: configure: define _ALL_SOURCE for build on AIX7.1
   (tkob)
 
-- GPR#401: automatically retry failed test directories in the testsuite
+- #401: automatically retry failed test directories in the testsuite
   (David Allsopp)
 
-- GPR#451: an optional 'parallel' target in testsuite/Makefile using the
+- #451: an optional 'parallel' target in testsuite/Makefile using the
   GNU parallel tool to run tests in parallel.
   (Gabriel Scherer)
 
-- GPR#555: ensure that register typing constraints are respected at
+- #555: ensure that register typing constraints are respected at
   join points in the control flow graph
   (Mark Shinwell, debugging & test case by Arseniy Alekseyev and Leo White,
     code review by Xavier Leroy)
 
 ### Build system:
 
-- GPR#388: FlexDLL added as a Git submodule and bootstrappable with the compiler
+- #388: FlexDLL added as a Git submodule and bootstrappable with the compiler
   (David Allsopp)
 
 OCaml 4.02.3 (27 Jul 2015):
 ---------------------------
 
 Bug fixes:
-- PR#6908: Top-level custom printing for GADTs: interface change in 4.02.2
+- #6908: Top-level custom printing for GADTs: interface change in 4.02.2
   (Grégoire Henry, report by Jeremy Yallop)
-- PR#6919: corrupted final_table
+- #6919: corrupted final_table
   (ygrek)
-- PR#6926: Regression: ocamldoc lost unattached comment
+- #6926: Regression: ocamldoc lost unattached comment
   (Damien Doligez, report by François Bobot)
-- PR#6930: Aliased result type of GADT constructor results in assertion failure
+- #6930: Aliased result type of GADT constructor results in assertion failure
   (Jacques Garrigue)
 
 Feature wishes:
-- PR#6691: install .cmt[i] files for stdlib and compiler-libs
+- #6691: install .cmt[i] files for stdlib and compiler-libs
   (David Sheets, request by Gabriel Radanne)
-- GPR#37: New primitive: caml_alloc_dummy_function
+- #37: New primitive: caml_alloc_dummy_function
   (Hugo Heuzard)
 
 OCaml 4.02.2 (17 Jun 2015):
@@ -3574,75 +4521,75 @@ OCaml 4.02.2 (17 Jun 2015):
 (Changes that can break existing programs are marked with a "*")
 
 Language features:
-- PR#6583: add a new class of binary operators with the same syntactic
+- #6583: add a new class of binary operators with the same syntactic
   precedence as method calls; these operators start with # followed
   by a non-empty sequence of operator symbols (for instance #+, #!?).
   It is also possible to use '#' as part of these extra symbols
   (for instance ##, or #+#); this is rejected by the type-checker,
   but can be used e.g. by ppx rewriters.
   (Alain Frisch, request by Gabriel Radanne)
-* PR#6016: add a "nonrec" keyword for type declarations
+* #6016: add a "nonrec" keyword for type declarations
   (Jérémie Dimino)
-* PR#6612, GPR#152: change the precedence of attributes in type declarations
+* #6612, #152: change the precedence of attributes in type declarations
   (Jérémie Dimino)
 
 Compilers:
-- PR#6600: make -short-paths faster by building the printing map
+- #6600: make -short-paths faster by building the printing map
   incrementally
   (Jacques Garrigue)
-- PR#6642: replace $CAMLORIGIN in -ccopt with the path to cma or cmxa
+- #6642: replace $CAMLORIGIN in -ccopt with the path to cma or cmxa
   (whitequark, Gabriel Scherer, review by Damien Doligez)
-- PR#6797: new option -output-complete-obj
+- #6797: new option -output-complete-obj
   to output an object file with included runtime and autolink libraries
   (whitequark)
-- PR#6845: -no-check-prims to tell ocamlc not to check primitives in runtime
+- #6845: -no-check-prims to tell ocamlc not to check primitives in runtime
   (Alain Frisch)
-- GPR#149: Attach documentation comments to parse tree
+- #149: Attach documentation comments to parse tree
   (Leo White)
-- GPR#159: Better locations for structure/signature items
+- #159: Better locations for structure/signature items
   (Leo White)
 
 Toplevel and debugger:
-- PR#5958: generalized polymorphic #install_printer
+- #5958: generalized polymorphic #install_printer
   (Pierre Chambart and Grégoire Henry)
 
 OCamlbuild:
-- PR#6237: explicit "infer" tag to control or disable menhir --infer
+- #6237: explicit "infer" tag to control or disable menhir --infer
   (Hugo Heuzard)
-- PR#6625: pass -linkpkg to files built with -output-obj.
+- #6625: pass -linkpkg to files built with -output-obj.
   (whitequark)
-- PR#6702: explicit "linkpkg" and "dontlink(foo)" flags
+- #6702: explicit "linkpkg" and "dontlink(foo)" flags
   (whitequark, Gabriel Scherer)
-- PR#6712: Ignore common VCS directories
+- #6712: Ignore common VCS directories
   (whitequark)
-- PR#6720: pass -g to C compilers when tag 'debug' is set
+- #6720: pass -g to C compilers when tag 'debug' is set
   (whitequark, Gabriel Scherer)
-- PR#6733: add .byte.so and .native.so targets to pass
+- #6733: add .byte.so and .native.so targets to pass
   -output-obj -cclib -shared.
   (whitequark)
-- PR#6733: "runtime_variant(X)" to pass -runtime-variant X option.
+- #6733: "runtime_variant(X)" to pass -runtime-variant X option.
   (whitequark)
-- PR#6774: new menhir-specific flags "only_tokens" and "external_tokens(Foo)"
+- #6774: new menhir-specific flags "only_tokens" and "external_tokens(Foo)"
   (François Pottier)
 
 Libraries:
-- PR#6285: Add support for nanosecond precision in Unix.stat()
+- #6285: Add support for nanosecond precision in Unix.stat()
   (Jérémie Dimino, report by user 'gfxmonk')
-- PR#6781: Add higher baud rates to Unix termios
+- #6781: Add higher baud rates to Unix termios
   (Damien Doligez, report by Berke Durak)
-- PR#6834: Add Obj.{first,last}_non_constant_constructor_tag
+- #6834: Add Obj.{first,last}_non_constant_constructor_tag
   (Mark Shinwell, request by Gabriel Scherer)
 
 Runtime:
-- PR#6078: Release the runtime system when calling caml_dlopen
+- #6078: Release the runtime system when calling caml_dlopen
   (Jérémie Dimino)
-- PR#6675: GC hooks
+- #6675: GC hooks
   (Damien Doligez and Roshan James)
 
 Build system:
-- PR#5418 (comments) : generate dependencies with $(CC) instead of gcc
+- #5418 (comments) : generate dependencies with $(CC) instead of gcc
   (Damien Doligez and Michael Grünewald)
-- PR#6266: Cross compilation for iOs, Android etc
+- #6266: Cross compilation for iOs, Android etc
   (whitequark, review by Damien Doligez and Mark Shinwell)
 
 Installation procedure:
@@ -3650,164 +4597,164 @@ Installation procedure:
   (Mark Shinwell)
 
 Bug fixes:
-- PR#5271: Location.prerr_warning is hard-coded to use Format.err_formatter
+- #5271: Location.prerr_warning is hard-coded to use Format.err_formatter
   (Damien Doligez, report by Rolf Rolles)
-- PR#5395: OCamlbuild mishandles relative symlinks and include paths
+- #5395: OCamlbuild mishandles relative symlinks and include paths
   (Damien Doligez, report by Didier Le Botlan)
-- PR#5822: wrong value of Options.ext_dll on windows
+- #5822: wrong value of Options.ext_dll on windows
   (Damien Doligez and Daniel Weil)
-- PR#5836, PR#6684: printing lazy values in ocamldebug may segfault
+- #5836, #6684: printing lazy values in ocamldebug may segfault
   (Gabriel Scherer, request by the Coq team)
-- PR#5887: move the byterun/*.h headers to byterun/caml/*.h to avoid
+- #5887: move the byterun/*.h headers to byterun/caml/*.h to avoid
   header name clashes
   (Jérôme Vouillon and Adrien Nader and whitequark)
-- PR#6281: Graphics window does not acknowledge second click (double click)
+- #6281: Graphics window does not acknowledge second click (double click)
   (Kyle Headley)
-- PR#6490: incorrect backtraces in gdb on AArch64.  Also fixes incorrect
+- #6490: incorrect backtraces in gdb on AArch64.  Also fixes incorrect
   backtraces on 32-bit ARM.
   (Mark Shinwell)
-- PR#6573: extern "C" for systhreads/threads.h
+- #6573: extern "C" for systhreads/threads.h
   (Mickaël Delahaye)
-- PR#6575: Array.init evaluates callback although it should not do so
+- #6575: Array.init evaluates callback although it should not do so
   (Alain Frisch, report by Gerd Stolpmann)
-- PR#6607: The manual doesn't mention 0x200 flag for OCAMLRUNPARAM=v
+- #6607: The manual doesn't mention 0x200 flag for OCAMLRUNPARAM=v
   (Alain Frisch)
-- PR#6616: allow meaningful use of -use-runtime without -custom.
+- #6616: allow meaningful use of -use-runtime without -custom.
   (whitequark)
-- PR#6617: allow android build with pthreads support (since SDK r10c)
+- #6617: allow android build with pthreads support (since SDK r10c)
   (whitequark)
-- PR#6626: ocamlbuild on cygwin cannot find ocamlfind
+- #6626: ocamlbuild on cygwin cannot find ocamlfind
   (Gergely Szilvasy)
-- PR#6628: Configure script rejects legitimate arguments
+- #6628: Configure script rejects legitimate arguments
   (Michael Grünewald, Damien Doligez)
-- PR#6630: Failure of tests/prim-bigstring/{big,}string.ml on big-endian
+- #6630: Failure of tests/prim-bigstring/{big,}string.ml on big-endian
   architectures
   (Pierre Chambart, testing by Mark Shinwell)
-- PR#6640: ocamlbuild: wrong "unused tag" warning on "precious"
+- #6640: ocamlbuild: wrong "unused tag" warning on "precious"
   (report by user 'william')
-- PR#6652: ocamlbuild -clean does not print a newline after output
+- #6652: ocamlbuild -clean does not print a newline after output
   (Damien Doligez, report by Andi McClure)
-- PR#6658: cross-compiler: version check not working on OS X
+- #6658: cross-compiler: version check not working on OS X
   (Gerd Stolpmann)
-- PR#6665: Failure of tests/asmcomp on sparc
+- #6665: Failure of tests/asmcomp on sparc
   (Stéphane Glondu)
-- PR#6667: wrong implementation of %bswap16 on ARM64
+- #6667: wrong implementation of %bswap16 on ARM64
   (Xavier Leroy)
-- PR#6669: fix 4.02 regression in toplevel printing of lazy values
+- #6669: fix 4.02 regression in toplevel printing of lazy values
   (Leo White, review by Gabriel Scherer)
-- PR#6671: Windows: environment variable 'TZ' affects Unix.gettimeofday
+- #6671: Windows: environment variable 'TZ' affects Unix.gettimeofday
   (Mickaël Delahaye and Damien Doligez)
-- PR#6680: Missing parentheses in warning about polymorphic variant value
+- #6680: Missing parentheses in warning about polymorphic variant value
   (Jacques Garrigue and Gabriel Scherer, report by Philippe Veber)
-- PR#6686: Bug in [subst_boxed_number]
+- #6686: Bug in [subst_boxed_number]
   (Jérémie Dimino, Mark Shinwell)
-- PR#6690: Uncaught exception (Not_found) with (wrong) wildcard or unification
+- #6690: Uncaught exception (Not_found) with (wrong) wildcard or unification
   type variable in place of a local abstract type
   (Jacques Garrigue, report by Mikhail Mandrykin)
-- PR#6693 (part two): Incorrect relocation types in x86-64 runtime system
+- #6693 (part two): Incorrect relocation types in x86-64 runtime system
   (whitequark, review by Jacques-Henri Jourdan, Xavier Leroy and Mark Shinwell)
-- PR#6717: Pprintast does not print let-pattern attributes
+- #6717: Pprintast does not print let-pattern attributes
   (Gabriel Scherer, report by whitequark)
-- PR#6727: Printf.sprintf "%F" misbehavior
+- #6727: Printf.sprintf "%F" misbehavior
   (Benoît Vaugon, report by Vassili Karpov)
-- PR#6747: ocamlobjinfo: missing symbol caml_plugin_header due to underscore
+- #6747: ocamlobjinfo: missing symbol caml_plugin_header due to underscore
   (Damien Doligez, Maverick Woo)
-- PR#6749: ocamlopt returns n for (n mod 1) instead of 0
+- #6749: ocamlopt returns n for (n mod 1) instead of 0
   (Mark Shinwell and Jérémie Dimino)
-- PR#6753: Num.quo_num and Num.mod_num incorrect for some negative arguments
+- #6753: Num.quo_num and Num.mod_num incorrect for some negative arguments
   (Xavier Leroy)
-- PR#6758: Ocamldoc "analyse_module: parsetree and typedtree don't match"
+- #6758: Ocamldoc "analyse_module: parsetree and typedtree don't match"
   (Damien Doligez, report by user 'maro')
-- PR#6759: big_int_of_string incorrectly parses some hexa literals
+- #6759: big_int_of_string incorrectly parses some hexa literals
   (Damien Doligez, report by Pierre-yves Strub)
-- PR#6763: #show with -short-paths doesn't select shortest type paths
+- #6763: #show with -short-paths doesn't select shortest type paths
   (Jacques Garrigue, report by David Sheets)
-- PR#6768: Typechecker overflow the stack on cyclic type
+- #6768: Typechecker overflow the stack on cyclic type
   (Jacques Garrigue, report by user 'darktenaibre')
-- PR#6770: (duplicate of PR#6686)
-- PR#6772: asmrun/signals_asm.c doesn't compile on NetBSD/i386
+- #6770: (duplicate of #6686)
+- #6772: asmrun/signals_asm.c doesn't compile on NetBSD/i386
   (Kenji Tokudome)
-- PR#6775: Digest.file leaks file descriptor on error
+- #6775: Digest.file leaks file descriptor on error
   (Valentin Gatien-Baron)
-- PR#6779: Cross-compilers cannot link bytecode using custom primitives
+- #6779: Cross-compilers cannot link bytecode using custom primitives
   (Damien Doligez, request by whitequark)
-- PR#6787: Soundness bug with polymorphic variants
+- #6787: Soundness bug with polymorphic variants
   (Jacques Garrigue, with help from Leo White and Grégoire Henry,
    report by Michael O'Connor)
-- PR#6790: otherlibs should be built with -g
+- #6790: otherlibs should be built with -g
   (Damien Doligez, report by whitequark)
-- PR#6791: "%s@[", "%s@{" regression in Scanf
+- #6791: "%s@[", "%s@{" regression in Scanf
   (Benoît Vaugon)
-- PR#6793: ocamlbuild passes nonsensical "-ocamlc ..." commands to menhir
+- #6793: ocamlbuild passes nonsensical "-ocamlc ..." commands to menhir
   (Gabriel Scherer, report by Damien Doligez)
-- PR#6799: include guards missing for unixsupport.h and other files
+- #6799: include guards missing for unixsupport.h and other files
   (Andreas Hauptmann)
-- PR#6810: Improve documentation of Bigarray.Genarray.map_file
+- #6810: Improve documentation of Bigarray.Genarray.map_file
   (Mark Shinwell and Daniel Bünzli)
-- PR#6812: -short-paths and -no-alias-deps can create inconsistent assumptions
+- #6812: -short-paths and -no-alias-deps can create inconsistent assumptions
   (Jacques Garrigue, report by Valentin Gatien-Baron)
-- PR#6817: GADT exhaustiveness breakage with modules
+- #6817: GADT exhaustiveness breakage with modules
   (Leo White, report by Pierre Chambart)
-- PR#6824: fix buffer sharing on partial application of Format.asprintf
+- #6824: fix buffer sharing on partial application of Format.asprintf
   (Gabriel Scherer, report by Alain Frisch)
-- PR#6831: Build breaks for -aspp gcc on solaris-like OSs
+- #6831: Build breaks for -aspp gcc on solaris-like OSs
   (John Tibble)
-- PR#6836: Assertion failure using -short-paths
+- #6836: Assertion failure using -short-paths
   (Jacques Garrigue, report by David Sheets)
-- PR#6837: Build profiling libraries on FreeBSD and NetBSD x86-64
+- #6837: Build profiling libraries on FreeBSD and NetBSD x86-64
   (Mark Shinwell, report by Michael Grünewald)
-- PR#6841: Changing compilation unit name with -o breaks ocamldebug
+- #6841: Changing compilation unit name with -o breaks ocamldebug
   (Jacques Garrigue, report by Jordan Walke)
-- PR#6842: export Typemod.modtype_of_package
-- PR#6843: record weak dependencies even when the .cmi is missing
+- #6842: export Typemod.modtype_of_package
+- #6843: record weak dependencies even when the .cmi is missing
   (Leo White, Gabriel Scherer)
-- PR#6849: Inverted pattern unification error
+- #6849: Inverted pattern unification error
   (Jacques Garrigue, report by Leo White)
-- PR#6857: __MODULE__ doesn't give the current module with -o
+- #6857: __MODULE__ doesn't give the current module with -o
   (Jacques Garrigue, report by Valentin Gatien-Baron)
-- PR#6862: Exhaustiveness check wrong for class constructor arguments
+- #6862: Exhaustiveness check wrong for class constructor arguments
   (Jacques Garrigue)
-- PR#6869: Improve comment on [Hashtbl.hash_param]
+- #6869: Improve comment on [Hashtbl.hash_param]
   (Mark Shinwell, report by Jun Furuse)
-- PR#6870: Unsoundness when -rectypes fails to detect non-contractive type
+- #6870: Unsoundness when -rectypes fails to detect non-contractive type
   (Jacques Garrigue, report by Stephen Dolan)
-- PR#6872: Type-directed propagation fails to disambiguate variants
+- #6872: Type-directed propagation fails to disambiguate variants
   that are also exception constructors
   (Jacques Garrigue, report by Romain Beauxis)
-- PR#6878: AArch64 backend generates invalid asm: conditional branch
+- #6878: AArch64 backend generates invalid asm: conditional branch
   out of range (Mark Shinwell, report by Richard Jones, testing by Richard
   Jones and Xavier Leroy, code review by Xavier Leroy and Thomas Refis)
-- PR#6879: Wrong optimization of 1 mod n
+- #6879: Wrong optimization of 1 mod n
   (Mark Shinwell, report by Jean-Christophe Filliâtre)
-- PR#6884: The __CYGWIN32__ #define should be replaced with __CYGWIN__
+- #6884: The __CYGWIN32__ #define should be replaced with __CYGWIN__
   (Adrien Nader)
-- PR#6886: -no-alias-deps allows to build self-referential compilation units
+- #6886: -no-alias-deps allows to build self-referential compilation units
   (Jacques Garrigue, report by Valentin Gatien-Baron)
-- PR#6889: ast_mapper fails to rewrite class attributes
+- #6889: ast_mapper fails to rewrite class attributes
   (Sébastien Briais)
-- PR#6893: ocamlbuild:  "tag not used" warning when using (p)dep
+- #6893: ocamlbuild:  "tag not used" warning when using (p)dep
   (Gabriel Scherer, report by Christiano Haesbaert)
-- GPR#143: fix getsockopt behaviour for boolean socket options
+- #143: fix getsockopt behaviour for boolean socket options
   (Anil Madhavapeddy and Andrew Ray)
-- GPR#190: typo in pervasives
+- #190: typo in pervasives
   (Guillaume Bury)
 - Misplaced assertion in major_gc.c for no-naked-pointers mode
   (Stephen Dolan, Mark Shinwell)
 
 Feature wishes:
-- PR#6452, GPR#140: add internal suport for custom printing formats
+- #6452, #140: add internal support for custom printing formats
   (Jérémie Dimino)
-- PR#6641: add -g, -ocamlcflags, -ocamloptflags options to ocamlmklib
+- #6641: add -g, -ocamlcflags, -ocamloptflags options to ocamlmklib
   (whitequark)
-- PR#6693: also build libasmrun_shared.so and lib{asm,caml}run_pic.a
+- #6693: also build libasmrun_shared.so and lib{asm,caml}run_pic.a
   (whitequark, review by Mark Shinwell)
-- PR#6842: export Typemod.modtype_of_package
+- #6842: export Typemod.modtype_of_package
   (Jacques Garrigue, request by Jun Furuse)
-- GPR#139: more versatile specification of locations of .annot
+- #139: more versatile specification of locations of .annot
   (Christophe Troestler, review by Damien Doligez)
-- GPR#171: allow custom warning printers / catchers
+- #171: allow custom warning printers / catchers
   (Benjamin Canou, review by Damien Doligez)
-- GPR#191: Making gc.h and some part of memory.h public
+- #191: Making gc.h and some part of memory.h public
   (Thomas Refis)
 
 OCaml 4.02.1 (14 Oct 2014):
@@ -3819,65 +4766,65 @@ Standard library:
 * Add optional argument ?limit to Arg.align.
 
 Bug Fixes:
-- PR#4099: Bug in Makefile.nt: won't stop on error
+- #4099: Bug in Makefile.nt: won't stop on error
   (George Necula)
-- PR#6181: Improve MSVC build
+- #6181: Improve MSVC build
   (Chen Gang)
-- PR#6207: Configure doesn't detect features correctly on Haiku
+- #6207: Configure doesn't detect features correctly on Haiku
   (Jessica Hamilton)
-- PR#6466: Non-exhaustive matching warning message for open types is confusing
+- #6466: Non-exhaustive matching warning message for open types is confusing
   (whitequark)
-- PR#6529: fix quadratic-time algorithm in Consistbl.extract.
-  (Xavier Leroy, Alain Frisch, relase-worthy report by Jacques-Pascal Deplaix)
-- PR#6530: Add stack overflow handling for native code (OpenBSD i386 and amd64)
+- #6529: fix quadratic-time algorithm in Consistbl.extract.
+  (Xavier Leroy, Alain Frisch, relase-worthy report by Kate Deplaix)
+- #6530: Add stack overflow handling for native code (OpenBSD i386 and amd64)
   (Cristopher Zimmermann)
-- PR#6533: broken semantics of %(%) when substituted by a box
+- #6533: broken semantics of %(%) when substituted by a box
   (Benoît Vaugon, report by Boris Yakobowski)
-- PR#6534: legacy support for %.10s
+- #6534: legacy support for %.10s
   (Benoît Vaugon, Gabriel Scherer, report by Nick Chapman)
-- PR#6536: better documentation of flag # in format strings
+- #6536: better documentation of flag # in format strings
   (Damien Doligez, report by Nick Chapman)
-- PR#6544: Bytes and CamlinternalFormat missing from threads stdlib.cma
+- #6544: Bytes and CamlinternalFormat missing from threads stdlib.cma
   (Christopher Zimmermann)
-- PR#6546: -dsource omits parens for `List ((`String "A")::[]) in patterns
+- #6546: -dsource omits parens for `List ((`String "A")::[]) in patterns
   (Gabriel Scherer, report by whitequark)
-- PR#6547: __MODULE__ aborts the compiler if the module name cannot be inferred
+- #6547: __MODULE__ aborts the compiler if the module name cannot be inferred
   (Jacques Garrigue, report by Kaustuv Chaudhuri)
-- PR#6549: Debug section is sometimes not readable when using -pack
+- #6549: Debug section is sometimes not readable when using -pack
   (Hugo Heuzard, review by Gabriel Scherer)
-- PR#6553: Missing command line options for ocamldoc
+- #6553: Missing command line options for ocamldoc
   (Maxence Guesdon)
-- PR#6554: fix race condition when retrieving backtraces
+- #6554: fix race condition when retrieving backtraces
   (Jérémie Dimino, Mark Shinwell).
-- PR#6557: String.sub throws Invalid_argument("Bytes.sub")
+- #6557: String.sub throws Invalid_argument("Bytes.sub")
   (Damien Doligez, report by Oliver Bandel)
-- PR#6562: Fix ocamldebug module source lookup
+- #6562: Fix ocamldebug module source lookup
   (Leo White)
-- PR#6563: Inclusion of packs failing to run module initializers
+- #6563: Inclusion of packs failing to run module initializers
   (Jacques Garrigue, report by Mark Shinwell)
-- PR#6564: infinite loop in Mtype.remove_aliases
+- #6564: infinite loop in Mtype.remove_aliases
   (Jacques Garrigue, report by Mark Shinwell)
-- PR#6565: compilation fails with Env.Error(_)
+- #6565: compilation fails with Env.Error(_)
   (Jacques Garrigue and Mark Shinwell)
-- PR#6566: -short-paths and signature inclusion errors
+- #6566: -short-paths and signature inclusion errors
   (Jacques Garrigue, report by Mark Shinwell)
-- PR#6572: Fatal error with recursive modules
+- #6572: Fatal error with recursive modules
   (Jacques Garrigue, report by Quentin Stievenart)
-- PR#6575: Array.init evaluates callback although it should not do so
+- #6575: Array.init evaluates callback although it should not do so
   (Alain Frisch, report by Gerd Stolpmann)
-- PR#6578: Recursive module containing alias causes Segmentation fault
+- #6578: Recursive module containing alias causes Segmentation fault
   (Jacques Garrigue)
-- PR#6581: Some bugs in generative functors
+- #6581: Some bugs in generative functors
   (Jacques Garrigue, report by Mark Shinwell)
-- PR#6584: ocamldep support for "-open M"
+- #6584: ocamldep support for "-open M"
   (Gabriel Scherer, review by Damien Doligez, report by Hezekiah M. Carty)
-- PR#6588: Code generation errors for ARM
+- #6588: Code generation errors for ARM
   (Mark Shinwell, Xavier Leroy)
-- PR#6590: Improve Windows (MSVC and mingw) build
+- #6590: Improve Windows (MSVC and mingw) build
   (Chen Gang)
-- PR#6599: ocamlbuild: add -bin-annot when using -pack
+- #6599: ocamlbuild: add -bin-annot when using -pack
   (Christopher Zimmermann)
-- PR#6602: Fatal error when tracing a function with abstract type
+- #6602: Fatal error when tracing a function with abstract type
   (Jacques Garrigue, report by Hugo Herbelin)
 - ocamlbuild: add an -ocamlmklib option to change the ocamlmklib command
   (Jérôme Vouillon)
@@ -3890,7 +4837,7 @@ OCaml 4.02.0 (29 Aug 2014):
 Language features:
 - Attributes and extension nodes
   (Alain Frisch)
-- Generative functors (PR#5905)
+- Generative functors (#5905)
   (Jacques Garrigue)
 * Module aliases
   (Jacques Garrigue)
@@ -3899,9 +4846,9 @@ Language features:
 - Separation between read-only strings (type string) and read-write byte
   sequences (type bytes). Activated by command-line option -safe-string.
   (Damien Doligez)
-- PR#6318: Exception cases in pattern matching
+- #6318: Exception cases in pattern matching
   (Jeremy Yallop, backend by Alain Frisch)
-- PR#5584: Extensible open datatypes
+- #5584: Extensible open datatypes
   (Leo White)
 
 Build system for the OCaml distribution:
@@ -3914,9 +4861,9 @@ Shedding weight:
 * Removed Labltk from the distribution, now available as a third-party library.
 
 Type system:
-* PR#6235: Keep typing of pattern cases independent in principal mode
+* #6235: Keep typing of pattern cases independent in principal mode
   (i.e. information from previous cases is no longer used when typing
-  patterns; cf. 'PR#6235' in testsuite/test/typing-warnings/records.ml)
+  patterns; cf. '#6235' in testsuite/test/typing-warnings/records.ml)
   (Jacques Garrigue)
 - Allow opening a first-class module or applying a generative functor
   in the body of a generative functor. Allow it also in the body of
@@ -3927,11 +4874,11 @@ Type system:
   original modules. This also changes the signature inferred by
   "module type of".
   (Jacques Garrigue, feedback from Leo White, Mark Shinwell and Nick Chapman)
-- PR#6331: Slight change in the criterion to distinguish private
+- #6331: Slight change in the criterion to distinguish private
   abbreviations and private row types: create a private abbreviation for
   closed objects and fixed polymorphic variants.
   (Jacques Garrigue)
-* PR#6333: Compare first class module types structurally rather than
+* #6333: Compare first class module types structurally rather than
   nominally. Value subtyping allows module subtyping as long as the internal
   representation is unchanged.
   (Jacques Garrigue)
@@ -3948,11 +4895,11 @@ Compilers:
 - New back-end optimization pass: dead code elimination.
   (Removes arithmetic and load instructions whose results are unused.)
   (Xavier Leroy)
-- PR#6269: Optimization of sequences of string patterns
+- #6269: Optimization of sequences of string patterns
   (Benoît Vaugon and Luc Maranget)
 - Experimental native code generator for AArch64 (ARM 64 bits)
   (Xavier Leroy)
-- PR#6042: Optimization of integer division and modulus by constant divisors
+- #6042: Optimization of integer division and modulus by constant divisors
   (Xavier Leroy and Phil Denys)
 - Add "-open" command line flag for opening a single module before typing
   (Leo White, Mark Shinwell and Nick Chapman)
@@ -3960,26 +4907,26 @@ Compilers:
   (it also applies when "-o" is not given, i.e. the module name is then
    the input file name up to the first ".")
   (Leo White, Mark Shinwell and Nick Chapman)
-* PR#5779: better sharing of structured constants
+* #5779: better sharing of structured constants
   (Alain Frisch)
-- PR#5817: new flag to keep locations in cmi files
+- #5817: new flag to keep locations in cmi files
   (Alain Frisch)
-- PR#5854: issue warning 3 when referring to a value marked with
+- #5854: issue warning 3 when referring to a value marked with
   the [@@ocaml.deprecated] attribute
   (Alain Frisch, suggestion by Pierre-Marie Pédrot)
-- PR#6017: a new format implementation based on GADTs
+- #6017: a new format implementation based on GADTs
   (Benoît Vaugon and Gabriel Scherer)
-* PR#6203: Constant exception constructors no longer allocate
+* #6203: Constant exception constructors no longer allocate
   (Alain Frisch)
-- PR#6260: avoid unnecessary boxing in let
+- #6260: avoid unnecessary boxing in let
   (Vladimir Brankov)
-- PR#6345: Better compilation of optional arguments with default values
+- #6345: Better compilation of optional arguments with default values
   (Alain Frisch, review by Jacques Garrigue)
-- PR#6389: ocamlopt -opaque option for incremental native compilation
+- #6389: ocamlopt -opaque option for incremental native compilation
   (Pierre Chambart, Gabriel Scherer)
 
 Toplevel interactive system:
-- PR#5377: New "#show_*" directives
+- #5377: New "#show_*" directives
   (ygrek, Jacques Garrigue and Alain Frisch)
 
 Runtime system:
@@ -3998,11 +4945,11 @@ Runtime system:
 - Fixed a major performance problem on large heaps (~1GB) by making heap
   increments proportional to heap size by default
   (Damien Doligez)
-- PR#4765: Structural equality treats exception specifically
+- #4765: Structural equality treats exception specifically
   (Alain Frisch)
-- PR#5009: efficient comparison/indexing of exceptions
+- #5009: efficient comparison/indexing of exceptions
   (Alain Frisch, request by Markus Mottl)
-- PR#6075: avoid using unsafe C library functions (strcpy, strcat, sprintf)
+- #6075: avoid using unsafe C library functions (strcpy, strcat, sprintf)
   (Xavier Leroy, reports from user 'jfc' and Anil Madhavapeddy)
 - An ISO C99-compliant C compiler and standard library is now assumed.
   (Plus special exceptions for MSVC.)  In particular, emulation code for
@@ -4013,152 +4960,152 @@ Runtime system:
 Standard library:
 * Add new modules Bytes and BytesLabels for mutable byte sequences.
   (Damien Doligez)
-- PR#4986: add List.sort_uniq and Set.of_list
+- #4986: add List.sort_uniq and Set.of_list
   (Alain Frisch)
-- PR#5935: a faster version of "raise" which does not maintain the backtrace
+- #5935: a faster version of "raise" which does not maintain the backtrace
   (Alain Frisch)
-- PR#6146: support "Unix.kill pid Sys.sigkill" under Windows
+- #6146: support "Unix.kill pid Sys.sigkill" under Windows
   (Romain Bardou and Alain Frisch)
-- PR#6148: speed improvement for Buffer
+- #6148: speed improvement for Buffer
   (John Whitington)
-- PR#6180: efficient creation of uninitialized float arrays
+- #6180: efficient creation of uninitialized float arrays
   (Alain Frisch, request by Markus Mottl)
-- PR#6355: Improve documentation regarding finalisers and multithreading
+- #6355: Improve documentation regarding finalisers and multithreading
   (Daniel Bünzli, Mark Shinwell)
 - Trigger warning 3 for all values marked as deprecated in the documentation.
   (Damien Doligez)
 
 OCamldoc:
-- PR#6257: handle full doc comments for variant constructors and
+- #6257: handle full doc comments for variant constructors and
   record fields
   (Maxence Guesdon, request by ygrek)
-- PR#6274: allow doc comments on object types
+- #6274: allow doc comments on object types
   (Thomas Refis)
-- PR#6310: fix ocamldoc's subscript/superscript CSS font size
+- #6310: fix ocamldoc's subscript/superscript CSS font size
   (Anil Madhavapeddy)
-- PR#6425: fix generation of man pages
+- #6425: fix generation of man pages
   (Maxence Guesdon, report by Anil Madhavapeddy)
 
 Bug fixes:
-- PR#2719: wrong scheduling of bound checks within a
+- #2719: wrong scheduling of bound checks within a
   try...with Invalid_argument -> _ ...  (Xavier Leroy)
-- PR#4719: Sys.executable_name wrong if executable name contains dots (Windows)
+- #4719: Sys.executable_name wrong if executable name contains dots (Windows)
   (Alain Frisch, report by Bart Jacobs)
-- PR#5406 ocamlbuild: "tag 'package' does not expect a parameter"
+- #5406 ocamlbuild: "tag 'package' does not expect a parameter"
   (Gabriel Scherer)
-- PR#5598, PR#6165: Alterations to handling of \013 in source files
+- #5598, #6165: Alterations to handling of \013 in source files
   breaking other tools
   (David Allsopp and Damien Doligez)
-- PR#5820: Fix camlp4 lexer roll back problem
+- #5820: Fix camlp4 lexer roll back problem
   (Hongbo Zhang)
-- PR#5946: CAMLprim taking (void) as argument
+- #5946: CAMLprim taking (void) as argument
   (Benoît Vaugon)
-- PR#6038: on x86-32, enforce 16-byte stack alignment for compatibility
+- #6038: on x86-32, enforce 16-byte stack alignment for compatibility
   with recent GCC and Clang.  Win32/MSVC keeps 4-byte stack alignment.
   (Xavier Leroy)
-- PR#6062: Fix a 4.01 camlp4 DELETE_RULE regression caused by commit 13047
+- #6062: Fix a 4.01 camlp4 DELETE_RULE regression caused by commit 13047
   (Hongbo Zhang, report by Christophe Troestler)
-- PR#6173: Typing error message is worse than before
+- #6173: Typing error message is worse than before
   (Jacques Garrigue and John Whitington)
-- PR#6174: OCaml compiler loops on an example using GADTs (-rectypes case)
+- #6174: OCaml compiler loops on an example using GADTs (-rectypes case)
   (Jacques Garrigue and Grégoire Henry, report by Chantal Keller)
-- PR#6175: open! was not suppored by camlp4
+- #6175: open! was not supported by camlp4
   (Hongbo Zhang)
-- PR#6184: ocamlbuild: `ocamlfind ocamldep` does not support -predicate
-  (Jacques-Pascal Deplaix)
-- PR#6194: Incorrect unused warning with first-class modules in patterns
+- #6184: ocamlbuild: `ocamlfind ocamldep` does not support -predicate
+  (Kate Deplaix)
+- #6194: Incorrect unused warning with first-class modules in patterns
   (Jacques Garrigue, report by Markus Mottl and Leo White)
-- PR#6211: in toplevel interactive use, bad interaction between uncaught
+- #6211: in toplevel interactive use, bad interaction between uncaught
   exceptions and multiple bindings of the form "let x = a let y = b;;".
   (Xavier Leroy)
-- PR#6216: inlining of GADT matches generates invalid assembly
+- #6216: inlining of GADT matches generates invalid assembly
   (Xavier Leroy and Alain Frisch, report by Mark Shinwell)
-- PR#6232: Don't use [mktemp] on platforms where [mkstemp] is available
+- #6232: Don't use [mktemp] on platforms where [mkstemp] is available
   (Stéphane Glondu, Mark Shinwell)
-- PR#6233: out-of-bounds exceptions lose their locations on ARM, PowerPC
+- #6233: out-of-bounds exceptions lose their locations on ARM, PowerPC
   (Jacques-Henri Jourdan and Xavier Leroy,
    report and testing by Stéphane Glondu)
-- PR#6235: Issue with type information flowing through a variant pattern
+- #6235: Issue with type information flowing through a variant pattern
   (Jacques Garrigue, report by Hongbo Zhang)
-- PR#6239: sometimes wrong stack alignment when raising exceptions
+- #6239: sometimes wrong stack alignment when raising exceptions
            in -g mode with backtraces active
   (Xavier Leroy, report by Yaron Minsky)
-- PR#6240: Fail to expand module type abbreviation during substyping
+- #6240: Fail to expand module type abbreviation during substyping
   (Jacques Garrigue, report by Leo White)
-- PR#6241: Assumed inequality between paths involving functor arguments
+- #6241: Assumed inequality between paths involving functor arguments
   (Jacques Garrigue, report by Jeremy Yallop)
-- PR#6243: Make "ocamlopt -g" more resistant to ill-formed locations
+- #6243: Make "ocamlopt -g" more resistant to ill-formed locations
   (Xavier Leroy, report by Pierre-Marie Pédrot)
-- PR#6262: equality of first-class modules take module aliases into account
+- #6262: equality of first-class modules take module aliases into account
   (Alain Frisch and Leo White)
-- PR#6268: -DMODEL_$(MODEL) not passed when building asmrun/arm.p.o
+- #6268: -DMODEL_$(MODEL) not passed when building asmrun/arm.p.o
   (Peter Michael Green)
-- PR#6273: fix Sys.file_exists on large files (Win32)
+- #6273: fix Sys.file_exists on large files (Win32)
   (Christoph Bauer)
-- PR#6275: Soundness bug related to type constraints
+- #6275: Soundness bug related to type constraints
   (Jacques Garrigue, report by Leo White)
-- PR#6293: Assert_failure with invalid package type
+- #6293: Assert_failure with invalid package type
   (Jacques Garrigue, report by Elnatan Reisner)
-- PR#6300: ocamlbuild -use-ocamlfind conflicts with -ocamlc
+- #6300: ocamlbuild -use-ocamlfind conflicts with -ocamlc
   (Gabriel Scherer)
-- PR#6302: bytecode debug information re-read from filesystem every time
+- #6302: bytecode debug information re-read from filesystem every time
   (Jacques-Henri Jourdan)
-- PR#6307: Behavior of 'module type of' w.r.t. module aliases
+- #6307: Behavior of 'module type of' w.r.t. module aliases
   (Jacques Garrigue, report by Alain Frisch)
-- PR#6332: Unix.open_process fails to pass empty arguments under Windows
+- #6332: Unix.open_process fails to pass empty arguments under Windows
   (Damien Doligez, report Virgile Prevosto)
-- PR#6346: Build failure with latest version of xcode on OSX
+- #6346: Build failure with latest version of xcode on OSX
   (Jérémie Dimino)
-- PR#6348: Unification failure for GADT when original definition is hidden
+- #6348: Unification failure for GADT when original definition is hidden
   (Leo White and Jacques Garrigue, report by Jeremy Yallop)
-- PR#6352: Automatic removal of optional arguments and sequencing
+- #6352: Automatic removal of optional arguments and sequencing
   (Jacques Garrigue and Alain Frisch)
-- PR#6361: Hashtbl.hash not terminating on some lazy values w/ recursive types
+- #6361: Hashtbl.hash not terminating on some lazy values w/ recursive types
   (Xavier Leroy, report by Leo White)
-- PR#6383: Exception Not_found when using object type in absent module
+- #6383: Exception Not_found when using object type in absent module
   (Jacques Garrigue, report by Sébastien Briais)
-- PR#6384: Uncaught Not_found exception with a hidden .cmi file
+- #6384: Uncaught Not_found exception with a hidden .cmi file
   (Leo White)
-- PR#6385: wrong allocation of large closures by the bytecode interpreter
+- #6385: wrong allocation of large closures by the bytecode interpreter
   (Xavier Leroy, report by Stephen Dolan)
-- PR#6394: Assertion failed in Typecore.expand_path
+- #6394: Assertion failed in Typecore.expand_path
   (Alain Frisch and Jacques Garrigue)
-- PR#6405: unsound interaction of -rectypes and GADTs
+- #6405: unsound interaction of -rectypes and GADTs
   (Jacques Garrigue, report by Gabriel Scherer and Benoît Vaugon)
-- PR#6408: Optional arguments given as ~?arg instead of ?arg in message
+- #6408: Optional arguments given as ~?arg instead of ?arg in message
   (Michael O'Connor)
-- PR#6411: missing libgcc_s_sjlj-1.dll in mingw (add -static-libgcc)
+- #6411: missing libgcc_s_sjlj-1.dll in mingw (add -static-libgcc)
   (Jun Furuse and Alain Frisch, Jonathan Protzenko and Adrien Nader)
-- PR#6436: Typos in @deprecated text in stdlib/arrayLabels.mli
+- #6436: Typos in @deprecated text in stdlib/arrayLabels.mli
   (John Whitington)
-- PR#6439: Don't use the deprecated [getpagesize] function
+- #6439: Don't use the deprecated [getpagesize] function
   (John Whitington, Mark Shinwell)
-- PR#6441: undetected tail-call in some mutually-recursive functions
+- #6441: undetected tail-call in some mutually-recursive functions
   (many arguments, and mutual block mixes functions and non-functions)
   (Stefan Holdermans, review by Xavier Leroy)
-- PR#6443: ocaml segfault when List.fold_left is traced then executed
+- #6443: ocaml segfault when List.fold_left is traced then executed
   (Jacques Garrigue, report by user 'Reventlov')
-- PR#6451: some bugs in untypeast.ml
+- #6451: some bugs in untypeast.ml
   (Jun Furuse, review by Alain Frisch)
-- PR#6460: runtime assertion failure with large [| e1;...eN |]
+- #6460: runtime assertion failure with large [| e1;...eN |]
   float array expressions
   (Leo White)
-- PR#6463: -dtypedtree fails on class fields
+- #6463: -dtypedtree fails on class fields
   (Leo White)
-- PR#6469: invalid -dsource printing of "external _pipe = ...", "Pervasives.(!)"
+- #6469: invalid -dsource printing of "external _pipe = ...", "Pervasives.(!)"
   (Gabriel Scherer and Damien Doligez, user 'ngunn')
-- PR#6482: ocamlbuild fails when _tags file in unhygienic directory
+- #6482: ocamlbuild fails when _tags file in unhygienic directory
   (Gabriel Scherer)
-- PR#6502: ocamlbuild spurious warning on "use_menhir" tag
+- #6502: ocamlbuild spurious warning on "use_menhir" tag
   (Xavier Leroy)
-- PR#6505: Missed Type-error leads to a segfault upon record access
+- #6505: Missed Type-error leads to a segfault upon record access
   (Jacques Garrigue, Jeremy Yallop, report by Christoph Höger)
-- PR#6507: crash on AArch64 resulting from incorrect setting of
+- #6507: crash on AArch64 resulting from incorrect setting of
   [caml_bottom_of_stack].  (Richard Jones, Mark Shinwell)
-- PR#6509: add -linkall flag to ocamlcommon.cma
+- #6509: add -linkall flag to ocamlcommon.cma
   (Frédéric Bour)
-- PR#6513: Fatal error Ctype.Unify(_) in functor type
-- PR#6523: failure upon character bigarray access, and unnecessary change
+- #6513: Fatal error Ctype.Unify(_) in functor type
+- #6523: failure upon character bigarray access, and unnecessary change
   in comparison ordering (Jeremy Yallop, Mark Shinwell)
 - bound-checking bug in caml_string_{get,set}{16,32,64}
   (Pierre Chambart and Gabriel Scherer, report by Nicolas Trangez)
@@ -4166,68 +5113,68 @@ Bug fixes:
   (Gabriel Scherer and Xavier Leroy, report by Pierre Chambart)
 
 Features wishes:
-- PR#4243: make the Makefiles parallelizable
+- #4243: make the Makefiles parallelizable
   (Grégoire Henry and Damien Doligez)
-- PR#4323: have "of_string" in Num and Big_int work with binary and
+- #4323: have "of_string" in Num and Big_int work with binary and
            hex representations
   (Zoe Paraskevopoulou, review by Gabriel Scherer)
-- PR#4771: Clarify documentation of Dynlink.allow_only
+- #4771: Clarify documentation of Dynlink.allow_only
   (Damien Doligez, report by David Allsopp)
-- PR#4855: 'camlp4 -I +dir' accepted, dir is relative to 'camlp4 -where'
+- #4855: 'camlp4 -I +dir' accepted, dir is relative to 'camlp4 -where'
   (Jun Furuse and Hongbo Zhang, report by Dmitry Grebeniuk)
-- PR#5201: ocamlbuild: add --norc to the bash invocation to help performances
+- #5201: ocamlbuild: add --norc to the bash invocation to help performances
   (Daniel Weil)
-- PR#5650: Camlp4FoldGenerator doesn't handle well "abstract" types
+- #5650: Camlp4FoldGenerator doesn't handle well "abstract" types
   (Hongbo Zhang)
-- PR#5808: allow simple patterns, not just identifiers, in "let p : t = ..."
+- #5808: allow simple patterns, not just identifiers, in "let p : t = ..."
   (Alain Frisch)
-- PR#5851: warn when -r is disabled because no _tags file is present
+- #5851: warn when -r is disabled because no _tags file is present
   (Gabriel Scherer)
-- PR#5899: a programmer-friendly access to backtrace information
+- #5899: a programmer-friendly access to backtrace information
   (Jacques-Henri Jourdan and Gabriel Scherer)
-- PR#6000 comment 9644: add a warning for non-principal coercions to format
+- #6000 comment 9644: add a warning for non-principal coercions to format
   (Jacques Garrigue, report by Damien Doligez)
-- PR#6054: add support for M.[ foo ], M.[| foo |] etc.
+- #6054: add support for M.[ foo ], M.[| foo |] etc.
   (Kaustuv Chaudhuri)
-- PR#6064: GADT representation for Bigarray.kind + CAML_BA_CHAR runtime kind
+- #6064: GADT representation for Bigarray.kind + CAML_BA_CHAR runtime kind
   (Jeremy Yallop, review by Gabriel Scherer)
-- PR#6071: Add a -noinit option to the toplevel
+- #6071: Add a -noinit option to the toplevel
   (David Sheets)
-- PR#6087: ocamlbuild, improve _tags parsing of escaped newlines
+- #6087: ocamlbuild, improve _tags parsing of escaped newlines
   (Gabriel Scherer, request by Daniel Bünzli)
-- PR#6109: Typos in ocamlbuild error messages
+- #6109: Typos in ocamlbuild error messages
   (Gabriel Kerneis)
-- PR#6116: more efficient implementation of Digest.to_hex
+- #6116: more efficient implementation of Digest.to_hex
   (ygrek)
-- PR#6142: add cmt file support to ocamlobjinfo
+- #6142: add cmt file support to ocamlobjinfo
   (Anil Madhavapeddy)
-- PR#6166: document -ocamldoc option of ocamlbuild
+- #6166: document -ocamldoc option of ocamlbuild
   (Xavier Clerc)
-- PR#6182: better message for virtual objects and class types
+- #6182: better message for virtual objects and class types
   (Leo White, Stephen Dolan)
-- PR#6183: enhanced documentation for 'Unix.shutdown_connection'
+- #6183: enhanced documentation for 'Unix.shutdown_connection'
   (Anil Madhavapeddy, report by Jun Furuse)
-- PR#6187: ocamlbuild: warn when using -plugin-tag(s) without myocamlbuild.ml
-  (Jacques-Pascal Deplaix)
-- PR#6246: allow wildcard _ as for-loop index
+- #6187: ocamlbuild: warn when using -plugin-tag(s) without myocamlbuild.ml
+  (Kate Deplaix)
+- #6246: allow wildcard _ as for-loop index
   (Alain Frisch, request by ygrek)
-- PR#6267: more information printed by "bt" command of ocamldebug
+- #6267: more information printed by "bt" command of ocamldebug
   (Josh Watzman)
-- PR#6270: remove need for -I directives to ocamldebug in common case
+- #6270: remove need for -I directives to ocamldebug in common case
   (Josh Watzman, review by Xavier Clerc and Alain Frisch)
-- PR#6311: Improve signature mismatch error messages
+- #6311: Improve signature mismatch error messages
   (Alain Frisch, suggestion by Daniel Bünzli)
-- PR#6358: obey DESTDIR in install targets
+- #6358: obey DESTDIR in install targets
   (Gabriel Scherer, request by François Berenger)
-- PR#6388, PR#6424: more parsetree correctness checks for -ppx users
+- #6388, #6424: more parsetree correctness checks for -ppx users
   (Alain Frisch, request by whitequark and Jun Furuse)
-- PR#6406: Expose OCaml version in C headers
+- #6406: Expose OCaml version in C headers
   (whitequark and Romain Calascibetta)
-- PR#6446: improve "unused declaration" warnings wrt. name shadowing
+- #6446: improve "unused declaration" warnings wrt. name shadowing
   (Alain Frisch)
-- PR#6495: ocamlbuild tags 'safe_string', 'unsafe_string'
+- #6495: ocamlbuild tags 'safe_string', 'unsafe_string'
   (Anil Madhavapeddy)
-- PR#6497: pass context information to -ppx preprocessors
+- #6497: pass context information to -ppx preprocessors
   (whitequark, Alain Frisch)
 - ocamllex: user-definable refill action
   (Frédéric Bour, review by Gabriel Scherer and Luc Maranget)
@@ -4245,7 +5192,7 @@ Other libraries:
 - Labltk: updated to Tcl/Tk 8.6.
 
 Type system:
-- PR#5759: use well-disciplined type information propagation to
+- #5759: use well-disciplined type information propagation to
   disambiguate label and constructor names
   (Jacques Garrigue, Alain Frisch and Leo White)
 * Propagate type information towards pattern-matching, even in the presence of
@@ -4253,19 +5200,19 @@ Type system:
   constructors). As a result, matching against absent constructors is no longer
   allowed for exact and fixed polymorphic variant types.
   (Jacques Garrigue)
-* PR#6035: Reject multiple declarations of the same method or instance variable
+* #6035: Reject multiple declarations of the same method or instance variable
   in an object
   (Alain Frisch)
 
 Compilers:
-- PR#5861: raise an error when multiple private keywords are used in type
+- #5861: raise an error when multiple private keywords are used in type
   declarations
   (Hongbo Zhang)
-- PR#5634: parsetree rewriter (-ppx flag)
+- #5634: parsetree rewriter (-ppx flag)
   (Alain Frisch)
 - ocamldep now supports -absname
   (Alain Frisch)
-- PR#5768: On "unbound identifier" errors, use spell-checking to suggest names
+- #5768: On "unbound identifier" errors, use spell-checking to suggest names
   present in the environment
   (Gabriel Scherer)
 - ocamlc has a new option -dsource to visualize the parsetree
@@ -4280,10 +5227,10 @@ Compilers:
   into account. This can make types much more readable if your code
   uses lots of functors.
   (Jacques Garrigue)
-- PR#5986: added flag -compat-32 to ocamlc, ensuring that the generated
+- #5986: added flag -compat-32 to ocamlc, ensuring that the generated
   bytecode executable can be loaded on 32-bit hosts.
   (Xavier Leroy)
-- PR#5980: warning on open statements which shadow an existing
+- #5980: warning on open statements which shadow an existing
   identifier (if it is actually used in the scope of the open); new
   open! syntax to silence it locally
   (Alain Frisch, thanks to a report of Daniel Bünzli)
@@ -4293,31 +5240,31 @@ Compilers:
   (Damien Doligez)
 - Experimental OCAMLPARAM for ocamlc and ocamlopt
   (Fabrice Le Fessant)
-- PR#5571: incorrect ordinal number in error message
+- #5571: incorrect ordinal number in error message
   (Alain Frisch, report by John Carr)
-- PR#6073: add signature to Tstr_include
+- #6073: add signature to Tstr_include
   (patch by Leo White)
 
 Standard library:
-- PR#5899: expose a way to inspect the current call stack,
+- #5899: expose a way to inspect the current call stack,
   Printexc.get_callstack
   (Gabriel Scherer, Jacques-Henri Jourdan, Alain Frisch)
-- PR#5986: new flag Marshal.Compat_32 for the serialization functions
+- #5986: new flag Marshal.Compat_32 for the serialization functions
   (Marshal.to_*), forcing the output to be readable on 32-bit hosts.
   (Xavier Leroy)
 - infix application operators |> and @@ in Pervasives
   (Fabrice Le Fessant)
-- PR#6176: new Format.asprintf function with a %a formatter
+- #6176: new Format.asprintf function with a %a formatter
   compatible with Format.fprintf (unlike Format.sprintf)
   (Pierre Weis)
 
 Other libraries:
-- PR#5568: add O_CLOEXEC flag to Unix.openfile, so that the returned
+- #5568: add O_CLOEXEC flag to Unix.openfile, so that the returned
   file descriptor is created in close-on-exec mode
   (Xavier Leroy)
 
 Runtime system:
-* PR#6019: more efficient implementation of caml_modify() and caml_initialize().
+* #6019: more efficient implementation of caml_modify() and caml_initialize().
   The new implementations are less lenient than the old ones: now,
   the destination pointer of caml_modify() must point within the minor or
   major heaps, and the destination pointer of caml_initialize() must
@@ -4333,327 +5280,327 @@ Internals:
   (Damien Doligez)
 
 Bug fixes:
-- PR#3236: Document the fact that queues are not thread-safe
+- #3236: Document the fact that queues are not thread-safe
   (Damien Doligez)
-- PR#3468: (part 1) Sys_error documentation
+- #3468: (part 1) Sys_error documentation
   (Damien Doligez)
-- PR#3679: Warning display problems
+- #3679: Warning display problems
   (Fabrice Le Fessant)
-- PR#3963: Graphics.wait_next_event in Win32 hangs if window closed
+- #3963: Graphics.wait_next_event in Win32 hangs if window closed
   (Damien Doligez)
-- PR#4079: Queue.copy is now tail-recursive
+- #4079: Queue.copy is now tail-recursive
   (patch by Christophe Papazian)
-- PR#4138: Documentation for Unix.mkdir
+- #4138: Documentation for Unix.mkdir
   (Damien Doligez)
-- PR#4469: emacs mode: caml-set-compile-command is annoying with ocamlbuild
+- #4469: emacs mode: caml-set-compile-command is annoying with ocamlbuild
   (Daniel Bünzli)
-- PR#4485: Graphics: Keyboard events incorrectly delivered in native code
+- #4485: Graphics: Keyboard events incorrectly delivered in native code
   (Damien Doligez, report by Sharvil Nanavati)
-- PR#4502: ocamlbuild now reliably excludes the build-dir from hygiene check
+- #4502: ocamlbuild now reliably excludes the build-dir from hygiene check
   (Gabriel Scherer, report by Romain Bardou)
-- PR#4762: ?? is not used at all, but registered as a lexer token
+- #4762: ?? is not used at all, but registered as a lexer token
   (Alain Frisch)
-- PR#4788: wrong error message when executable file is not found for backtrace
+- #4788: wrong error message when executable file is not found for backtrace
   (Damien Doligez, report by Claudio Sacerdoti Coen)
-- PR#4812: otherlibs/unix: add extern int code_of_unix_error (value error);
+- #4812: otherlibs/unix: add extern int code_of_unix_error (value error);
   (Goswin von Berdelow)
-- PR#4887: input_char after close_in crashes ocaml (msvc runtime)
+- #4887: input_char after close_in crashes ocaml (msvc runtime)
   (Alain Frisch and Christoph Bauer, report by ygrek)
-- PR#4994: ocaml-mode doesn't work with xemacs21
+- #4994: ocaml-mode doesn't work with xemacs21
   (Damien Doligez, report by Stéphane Glondu)
-- PR#5098: creating module values may lead to memory leaks
+- #5098: creating module values may lead to memory leaks
   (Alain Frisch, report by Milan Stanojević)
-- PR#5102: ocamlbuild fails when using an unbound variable in rule dependency
+- #5102: ocamlbuild fails when using an unbound variable in rule dependency
   (Xavier Clerc, report by Daniel Bünzli)
-* PR#5119: camlp4 now raises a specific exception when 'DELETE_RULE' fails,
+* #5119: camlp4 now raises a specific exception when 'DELETE_RULE' fails,
   rather than raising 'Not_found'
   (ygrek)
-- PR#5121: %( %) in Format module seems to be broken
+- #5121: %( %) in Format module seems to be broken
   (Pierre Weis, first patch by Valentin Gatien-Baron, report by Khoo Yit Phang)
-- PR#5178: document in INSTALL how to build a 32-bit version under Linux x86-64
+- #5178: document in INSTALL how to build a 32-bit version under Linux x86-64
   (Benjamin Monate)
-- PR#5212: Improve ocamlbuild error messages of _tags parser
+- #5212: Improve ocamlbuild error messages of _tags parser
   (ygrek)
-- PR#5240: register exception printers for Unix.Unix_error and Dynlink.Error
+- #5240: register exception printers for Unix.Unix_error and Dynlink.Error
   (Jérémie Dimino)
-- PR#5300: ocamlbuild: verbose parameter should implicitly set classic display
+- #5300: ocamlbuild: verbose parameter should implicitly set classic display
   (Xavier Clerc, report by Robert Jakob)
-- PR#5327: (Windows) Unix.select blocks if same socket listed in first and
+- #5327: (Windows) Unix.select blocks if same socket listed in first and
   third arguments
   (David Allsopp, displaying impressive MSDN skills)
-- PR#5343: ocaml -rectypes is unsound wrt module subtyping (was still unsound)
+- #5343: ocaml -rectypes is unsound wrt module subtyping (was still unsound)
   (Jacques Garrigue)
-- PR#5350: missing return code checks in the runtime system
+- #5350: missing return code checks in the runtime system
   (Xavier Leroy)
-- PR#5468: ocamlbuild should preserve order of parametric tags
+- #5468: ocamlbuild should preserve order of parametric tags
   (Wojciech Meyer, report by Dario Texeira)
-- PR#5551: Avoid repeated lookups for missing cmi files
+- #5551: Avoid repeated lookups for missing cmi files
   (Alain Frisch)
-- PR#5552: unrecognized gcc option -no-cpp-precomp
+- #5552: unrecognized gcc option -no-cpp-precomp
   (Damien Doligez, report by Markus Mottl)
-* PR#5580: missed opportunities for constant propagation
+* #5580: missed opportunities for constant propagation
   (Xavier Leroy and John Carr)
-- PR#5611: avoid clashes betwen .cmo files and output files during linking
+- #5611: avoid clashes between .cmo files and output files during linking
   (Wojciech Meyer)
-- PR#5662: typo in md5.c
+- #5662: typo in md5.c
   (Olivier Andrieu)
-- PR#5673: type equality in a polymorphic field
+- #5673: type equality in a polymorphic field
   (Jacques Garrigue, report by Jean-Louis Giavitto)
-- PR#5674: Methods call are 2 times slower with 4.00 than with 3.12
+- #5674: Methods call are 2 times slower with 4.00 than with 3.12
   (Jacques Garrigue, Gabriel Scherer, report by Jean-Louis Giavitto)
-- PR#5694: Exception raised by type checker
+- #5694: Exception raised by type checker
   (Jacques Garrigue, report by Markus Mottl)
-- PR#5695: remove warnings on sparc code emitter
+- #5695: remove warnings on sparc code emitter
   (Fabrice Le Fessant)
-- PR#5697: better location for warnings on statement expressions
+- #5697: better location for warnings on statement expressions
   (Dan Bensen)
-- PR#5698: remove harcoded limit of 200000 labels in emitaux.ml
+- #5698: remove hardcoded limit of 200000 labels in emitaux.ml
   (Fabrice Le Fessant, report by Marcin Sawicki)
-- PR#5702: bytecomp/bytelibrarian lib_sharedobjs was defined but never used
+- #5702: bytecomp/bytelibrarian lib_sharedobjs was defined but never used
   (Hongbo Zhang, Fabrice Le Fessant)
-- PR#5708: catch Failure"int_of_string" in ocamldebug
+- #5708: catch Failure"int_of_string" in ocamldebug
   (Fabrice Le Fessant, report by user 'schommer')
-- PR#5712: (9) new option -bin-annot is not documented
+- #5712: (9) new option -bin-annot is not documented
   (Damien Doligez, report by Hendrik Tews)
-- PR#5731: instruction scheduling forgot to account for destroyed registers
+- #5731: instruction scheduling forgot to account for destroyed registers
   (Xavier Leroy, Benedikt Meurer, reported by Jeffrey Scofield)
-- PR#5734: improved Win32 implementation of Unix.gettimeofday
+- #5734: improved Win32 implementation of Unix.gettimeofday
   (David Allsopp)
-- PR#5735: %apply and %revapply not first class citizens
+- #5735: %apply and %revapply not first class citizens
   (Fabrice Le Fessant, reported by Jun Furuse)
-- PR#5738: first class module patterns not handled by ocamldep
+- #5738: first class module patterns not handled by ocamldep
   (Fabrice Le Fessant, Jacques Garrigue, reported by Hongbo Zhang)
-- PR#5739: Printf.printf "%F" (-.nan) returns -nan
+- #5739: Printf.printf "%F" (-.nan) returns -nan
   (Xavier Leroy, David Allsopp, reported by Samuel Mimram)
-- PR#5741: make pprintast.ml in compiler_libs
+- #5741: make pprintast.ml in compiler_libs
   (Alain Frisch, Hongbo Zhang)
-- PR#5747: 'unused open' warning not given when compiling with -annot
+- #5747: 'unused open' warning not given when compiling with -annot
   (Alain Frisch, reported by Valentin Gatien-Baron)
-- PR#5752: missing dependencies at byte-code link with mlpack
+- #5752: missing dependencies at byte-code link with mlpack
   (Wojciech Meyer, Nicholas Lucaroni)
-- PR#5763: ocamlbuild does not give correct flags when running menhir
+- #5763: ocamlbuild does not give correct flags when running menhir
   (Gabriel Scherer, reported by Philippe Veber)
-- PR#5765: ocamllex doesn't preserve line directives
+- #5765: ocamllex doesn't preserve line directives
   (Damien Doligez, reported by Martin Jambon)
-- PR#5770: Syntax error messages involving unclosed parens are sometimes
+- #5770: Syntax error messages involving unclosed parens are sometimes
   incorrect
   (Michel Mauny)
-- PR#5772: problem with marshaling of mutually-recursive functions
+- #5772: problem with marshaling of mutually-recursive functions
   (Jacques-Henri Jourdan, reported by Cédric Pasteur)
-- PR#5775: several bug fixes for tools/pprintast.ml
+- #5775: several bug fixes for tools/pprintast.ml
   (Hongbo Zhang)
-- PR#5784: -dclambda option is ignored
+- #5784: -dclambda option is ignored
   (Pierre Chambart)
-- PR#5785: misbehaviour with abstracted structural type used as GADT index
+- #5785: misbehaviour with abstracted structural type used as GADT index
   (Jacques Garrigue, report by Jeremy Yallop)
-- PR#5787: Bad behavior of 'Unused ...' warnings in the toplevel
+- #5787: Bad behavior of 'Unused ...' warnings in the toplevel
   (Alain Frisch)
-- PR#5793: integer marshalling is inconsistent between architectures
+- #5793: integer marshalling is inconsistent between architectures
   (Xavier Clerc, report by Pierre-Marie Pédrot)
-- PR#5798: add ARM VFPv2 support for Raspbian (ocamlopt)
+- #5798: add ARM VFPv2 support for Raspbian (ocamlopt)
   (Jeffrey Scofield and Anil Madhavapeddy, patch review by Benedikt Meurer)
-- PR#5802: Avoiding "let" as a value name
+- #5802: Avoiding "let" as a value name
   (Jacques Garrigue, report by Tiphaine Turpin)
-- PR#5805: Assert failure with warning 34 on pre-processed file
+- #5805: Assert failure with warning 34 on pre-processed file
   (Alain Frisch, report by Tiphaine Turpin)
-- PR#5806: ensure that backtrace tests are always run (testsuite)
+- #5806: ensure that backtrace tests are always run (testsuite)
   (Xavier Clerc, report by user 'michi')
-- PR#5809: Generating .cmt files takes a long time, in case of type error
+- #5809: Generating .cmt files takes a long time, in case of type error
   (Alain Frisch)
-- PR#5810: error in switch printing when using -dclambda
+- #5810: error in switch printing when using -dclambda
   (Pierre Chambart)
-- PR#5811: Untypeast produces singleton tuples for constructor patterns
+- #5811: Untypeast produces singleton tuples for constructor patterns
   with only one argument
   (Tiphaine Turpin)
-- PR#5813: GC not called when unmarshaling repeatedly in a tight loop (ocamlopt)
+- #5813: GC not called when unmarshaling repeatedly in a tight loop (ocamlopt)
   (Xavier Leroy, report by David Waern)
-- PR#5814: read_cmt -annot does not report internal references
+- #5814: read_cmt -annot does not report internal references
   (Alain Frisch)
-- PR#5815: Multiple exceptions in signatures gives an error
+- #5815: Multiple exceptions in signatures gives an error
   (Leo White)
-- PR#5816: read_cmt -annot does not work for partial .cmt files
+- #5816: read_cmt -annot does not work for partial .cmt files
   (Alain Frisch)
-- PR#5819: segfault when using [with] on large recursive record (ocamlopt)
+- #5819: segfault when using [with] on large recursive record (ocamlopt)
   (Xavier Leroy, Damien Doligez)
-- PR#5821: Wrong record field is reported as duplicate
+- #5821: Wrong record field is reported as duplicate
   (Alain Frisch, report by Martin Jambon)
-- PR#5824: Generate more efficient code for immediate right shifts.
+- #5824: Generate more efficient code for immediate right shifts.
   (Pierre Chambart, review by Xavier Leroy)
-- PR#5825: Add a toplevel primitive to use source file wrapped with the
-  coresponding module
+- #5825: Add a toplevel primitive to use source file wrapped with the
+  corresponding module
   (Grégoire Henry, Wojciech Meyer, caml-list discussion)
-- PR#5833: README.win32 can leave the wrong flexlink in the path
+- #5833: README.win32 can leave the wrong flexlink in the path
   (Damien Doligez, report by William Smith)
-- PR#5835: nonoptional labeled arguments can be passed with '?'
+- #5835: nonoptional labeled arguments can be passed with '?'
   (Jacques Garrigue, report by Elnatan Reisner)
-- PR#5840: improved documentation for 'Unix.lseek'
+- #5840: improved documentation for 'Unix.lseek'
   (Xavier Clerc, report by Matej Košík)
-- PR#5848: Assertion failure in type checker
+- #5848: Assertion failure in type checker
   (Jacques Garrigue, Alain Frisch, report by David Waern)
-- PR#5858: Assert failure during typing of class
+- #5858: Assert failure during typing of class
   (Jacques Garrigue, report by Julien Signoles)
-- PR#5865: assert failure when reporting undefined field label
+- #5865: assert failure when reporting undefined field label
   (Jacques Garrigue, report by Anil Madhavapeddy)
-- PR#5872: Performance: Buffer.add_char is not inlined
+- #5872: Performance: Buffer.add_char is not inlined
   (Gerd Stolpmann, Damien Doligez)
-- PR#5876: Uncaught exception with a typing error
+- #5876: Uncaught exception with a typing error
   (Alain Frisch, Gabriel Scherer, report by Julien Moutinho)
-- PR#5877: multiple "open" can become expensive in memory
+- #5877: multiple "open" can become expensive in memory
   (Fabrice Le Fessant and Alain Frisch)
-- PR#5880: 'Genlex.make_lexer' documention mentions the wrong exception
+- #5880: 'Genlex.make_lexer' documentation mentions the wrong exception
   (Xavier Clerc, report by Virgile Prevosto)
-- PR#5885: Incorrect rule for compiling C stubs when shared libraries are not
+- #5885: Incorrect rule for compiling C stubs when shared libraries are not
   supported.
   (Jérôme Vouillon)
-- PR#5891: ocamlbuild: support rectypes tag for mlpack
+- #5891: ocamlbuild: support rectypes tag for mlpack
   (Khoo Yit Phang)
-- PR#5892: GADT exhaustiveness check is broken
+- #5892: GADT exhaustiveness check is broken
   (Jacques Garrigue and Leo White)
-- PR#5906: GADT exhaustiveness check is still broken
+- #5906: GADT exhaustiveness check is still broken
   (Jacques Garrigue, report by Sébastien Briais)
-- PR#5907: Undetected cycle during typecheck causes exceptions
+- #5907: Undetected cycle during typecheck causes exceptions
   (Jacques Garrigue, report by Pascal Zimmer)
-- PR#5910: Fix code generation bug for "mod 1" on ARM.
+- #5910: Fix code generation bug for "mod 1" on ARM.
   (Benedikt Meurer, report by user 'jteg68')
-- PR#5911: Signature substitutions fail in submodules
+- #5911: Signature substitutions fail in submodules
   (Jacques Garrigue, report by Markus Mottl)
-- PR#5912: add configure option -no-cfi (for OSX 10.6.x with XCode 4.0.2)
+- #5912: add configure option -no-cfi (for OSX 10.6.x with XCode 4.0.2)
   (Damien Doligez against XCode versions, report by Thomas Gazagnaire)
-- PR#5914: Functor breaks with an equivalent argument signature
+- #5914: Functor breaks with an equivalent argument signature
   (Jacques Garrigue, report by Markus Mottl and Grégoire Henry)
-- PR#5920, PR#5957: linking failure for big bytecodes on 32bit architectures
+- #5920, #5957: linking failure for big bytecodes on 32bit architectures
   (Benoît Vaugon and Chet Murthy, report by Jun Furuse and Sebastien Mondet)
-- PR#5928: Missing space between words in manual page for ocamlmktop
+- #5928: Missing space between words in manual page for ocamlmktop
   (Damien Doligez, report by Matej Košík)
-- PR#5930: ocamldep leaks temporary preprocessing files
+- #5930: ocamldep leaks temporary preprocessing files
   (Gabriel Scherer, report by Valentin Gatien-Baron)
-- PR#5933: Linking is slow when there are functions with large arities
+- #5933: Linking is slow when there are functions with large arities
   (Valentin Gatien-Baron, review by Gabriel Scherer)
-- PR#5934: integer shift by negative amount (in otherlibs/num)
+- #5934: integer shift by negative amount (in otherlibs/num)
   (Xavier Leroy, report by John Regehr)
-- PR#5944: Bad typing performances of big variant type declaration
+- #5944: Bad typing performances of big variant type declaration
   (Benoît Vaugon)
-- PR#5945: Mix-up of Minor_heap_min and Minor_heap_max units
+- #5945: Mix-up of Minor_heap_min and Minor_heap_max units
   (Benoît Vaugon)
-- PR#5948: GADT with polymorphic variants bug
+- #5948: GADT with polymorphic variants bug
   (Jacques Garrigue, report by Leo White)
-- PR#5953: Unix.system does not handle EINTR
+- #5953: Unix.system does not handle EINTR
   (Jérémie Dimino)
-- PR#5965: disallow auto-reference to a recursive module in its definition
+- #5965: disallow auto-reference to a recursive module in its definition
   (Alain Frisch, report by Arthur Windler via Gabriel Scherer)
-- PR#5973: Format module incorrectly parses format string
+- #5973: Format module incorrectly parses format string
   (Pierre Weis, report by Frédéric Bour)
-- PR#5974: better documentation for Str.regexp
+- #5974: better documentation for Str.regexp
   (Damien Doligez, report by william)
-- PR#5976: crash after recovering from two stack overflows (ocamlopt on MacOS X)
+- #5976: crash after recovering from two stack overflows (ocamlopt on MacOS X)
   (Xavier Leroy, report by Pierre Boutillier)
-- PR#5977: Build failure on raspberry pi: "input_value: integer too large"
+- #5977: Build failure on raspberry pi: "input_value: integer too large"
   (Alain Frisch, report by Sylvain Le Gall)
-- PR#5981: Incompatibility check assumes abstracted types are injective
+- #5981: Incompatibility check assumes abstracted types are injective
   (Jacques Garrigue, report by Jeremy Yallop)
-- PR#5982: caml_leave_blocking section and errno corruption
+- #5982: caml_leave_blocking section and errno corruption
   (Jérémie Dimino)
-- PR#5985: Unexpected interaction between variance and GADTs
+- #5985: Unexpected interaction between variance and GADTs
   (Jacques Garrigue, Jeremy Yallop and Leo White and Gabriel Scherer)
-- PR#5988: missing from the documentation: -impl is a valid flag for ocamlopt
+- #5988: missing from the documentation: -impl is a valid flag for ocamlopt
   (Damien Doligez, report by Vincent Bernardoff)
-- PR#5989: Assumed inequalities involving private rows
+- #5989: Assumed inequalities involving private rows
   (Jacques Garrigue, report by Jeremy Yallop)
-- PR#5992: Crash when pattern-matching lazy values modifies the scrutinee
+- #5992: Crash when pattern-matching lazy values modifies the scrutinee
   (Luc Maranget, Leo White)
-- PR#5993: Variance of private type abbreviations not checked for modules
+- #5993: Variance of private type abbreviations not checked for modules
   (Jacques Garrigue)
-- PR#5997: Non-compatibility assumed for concrete types with same constructor
+- #5997: Non-compatibility assumed for concrete types with same constructor
   (Jacques Garrigue, report by Gabriel Scherer)
-- PR#6004: Type information does not flow to "inherit" parameters
+- #6004: Type information does not flow to "inherit" parameters
   (Jacques Garrigue, report by Alain Frisch)
-- PR#6005: Type unsoundness with recursive modules
+- #6005: Type unsoundness with recursive modules
   (Jacques Garrigue, report by Jérémie Dimino and Josh Berdine)
-- PR#6010: Big_int.extract_big_int gives wrong results on negative arguments
+- #6010: Big_int.extract_big_int gives wrong results on negative arguments
   (Xavier Leroy, report by Drake Wilson via Stéphane Glondu)
-- PR#6024: Format syntax for printing @ is incompatible with 3.12.1
+- #6024: Format syntax for printing @ is incompatible with 3.12.1
   (Damien Doligez, report by Boris Yakobowski)
-- PR#6001: Reduce the memory used by compiling Camlp4
+- #6001: Reduce the memory used by compiling Camlp4
   (Hongbo Zhang and Gabriel Scherer, report by Henri Gouraud)
-- PR#6031: Camomile problem with -with-frame-pointers
+- #6031: Camomile problem with -with-frame-pointers
   (Fabrice Le Fessant, report by Anil Madhavapeddy)
-- PR#6032: better Random.self_init under Windows
+- #6032: better Random.self_init under Windows
   (Alain Frisch, Xavier Leroy)
-- PR#6033: Matching.inline_lazy_force needs eta-expansion (command-line flags)
+- #6033: Matching.inline_lazy_force needs eta-expansion (command-line flags)
   (Pierre Chambart, Xavier Leroy and Luc Maranget,
    regression report by Gabriel Scherer)
-- PR#6046: testsuite picks up the wrong ocamlrun dlls
+- #6046: testsuite picks up the wrong ocamlrun dlls
   (Anil Madhavapeddy)
-- PR#6056: Using 'match' prevents generalization of values
+- #6056: Using 'match' prevents generalization of values
   (Jacques Garrigue, report by Elnatan Reisner)
-- PR#6058: 'ocamlbuild -use-ocamlfind -tag thread -package threads t.cma' fails
+- #6058: 'ocamlbuild -use-ocamlfind -tag thread -package threads t.cma' fails
   (Gabriel Scherer, report by Hezekiah M. Carty)
-- PR#6069: ocamldoc: lexing: empty token
+- #6069: ocamldoc: lexing: empty token
   (Maxence Guesdon, Grégoire Henry, report by ygrek)
-- PR#6072: configure does not handle FreeBSD current (i.e. 10) correctly
+- #6072: configure does not handle FreeBSD current (i.e. 10) correctly
   (Damien Doligez, report by Prashanth Mundkur)
-- PR#6074: Wrong error message for failing Condition.broadcast
+- #6074: Wrong error message for failing Condition.broadcast
   (Markus Mottl)
-- PR#6084: Define caml_modify and caml_initialize as weak symbols to help
+- #6084: Define caml_modify and caml_initialize as weak symbols to help
   with Netmulticore
   (Xavier Leroy, Gerd Stolpmann)
-- PR#6090: Module constraint + private type seems broken in ocaml 4.01.0
-  (Jacques Garrigue, report by Jacques-Pascal Deplaix)
-- PR#6109: Typos in ocamlbuild error messages
+- #6090: Module constraint + private type seems broken in ocaml 4.01.0
+  (Jacques Garrigue, report by Kate Deplaix)
+- #6109: Typos in ocamlbuild error messages
   (Gabriel Kerneis)
-- PR#6123: Assert failure when self escapes its class
+- #6123: Assert failure when self escapes its class
   (Jacques Garrigue, report by whitequark)
-- PR#6158: Fatal error using GADTs
+- #6158: Fatal error using GADTs
   (Jacques Garrigue, report by Jeremy Yallop)
-- PR#6163: Assert_failure using polymorphic variants in GADTs
+- #6163: Assert_failure using polymorphic variants in GADTs
   (Jacques Garrigue, report by Leo White)
-- PR#6164: segmentation fault on Num.power_num of 0/1
+- #6164: segmentation fault on Num.power_num of 0/1
   (Fabrice Le Fessant, report by Johannes Kanig)
-- PR#6210: Camlp4 location error
+- #6210: Camlp4 location error
   (Hongbo Zhang, report by Jun Furuse)
 
 Feature wishes:
-- PR#5181: Merge common floating point constants in ocamlopt
+- #5181: Merge common floating point constants in ocamlopt
   (Benedikt Meurer)
-- PR#5243: improve the ocamlbuild API documentation in signatures.mli
+- #5243: improve the ocamlbuild API documentation in signatures.mli
   (Christophe Troestler)
-- PR#5546: moving a function into an internal module slows down its use
+- #5546: moving a function into an internal module slows down its use
   (Alain Frisch, report by Fabrice Le Fessant)
-- PR#5597: add instruction trace option 't' to OCAMLRUNPARAM
+- #5597: add instruction trace option 't' to OCAMLRUNPARAM
   (Anil Madhavapeddy, Wojciech Meyer)
-- PR#5676: IPv6 support under Windows
+- #5676: IPv6 support under Windows
   (Jérôme Vouillon, review by Jonathan Protzenko)
-- PR#5721: configure -with-frame-pointers for Linux perf profiling
+- #5721: configure -with-frame-pointers for Linux perf profiling
   (Fabrice Le Fessant, test by Jérémie Dimino)
-- PR#5722: toplevel: print full module path only for first record field
+- #5722: toplevel: print full module path only for first record field
   (Jacques Garrigue, report by ygrek)
-- PR#5762: Add primitives for fast access to bigarray dimensions
+- #5762: Add primitives for fast access to bigarray dimensions
   (Pierre Chambart)
-- PR#5769: Allow propagation of Sys.big_endian in native code
+- #5769: Allow propagation of Sys.big_endian in native code
   (Pierre Chambart, stealth commit by Fabrice Le Fessant)
-- PR#5771: Add primitives for reading 2, 4, 8 bytes in strings and bigarrays
+- #5771: Add primitives for reading 2, 4, 8 bytes in strings and bigarrays
   (Pierre Chambart)
-- PR#5774: Add bswap primitives for amd64 and arm
+- #5774: Add bswap primitives for amd64 and arm
   (Pierre Chambart, test by Alain Frisch)
-- PR#5795: Generate sqrtsd opcode instead of external call to sqrt on amd64
+- #5795: Generate sqrtsd opcode instead of external call to sqrt on amd64
   (Pierre Chambart)
-- PR#5827: provide a dynamic command line parsing mechanism
+- #5827: provide a dynamic command line parsing mechanism
   (Hongbo Zhang)
-- PR#5832: patch to improve "wrong file naming" error messages
+- #5832: patch to improve "wrong file naming" error messages
   (William Smith)
-- PR#5864: Add a find operation to Set
+- #5864: Add a find operation to Set
   (François Berenger)
-- PR#5886: Small changes to compile for Android
+- #5886: Small changes to compile for Android
   (Jérôme Vouillon, review by Benedikt Meurer)
-- PR#5902: -ppx based pre-processor executables accept arguments
+- #5902: -ppx based pre-processor executables accept arguments
   (Alain Frisch, report by Wojciech Meyer)
-- PR#5986: Protect against marshaling 64-bit integers in bytecode
+- #5986: Protect against marshaling 64-bit integers in bytecode
   (Xavier Leroy, report by Alain Frisch)
-- PR#6049: support for OpenBSD/macppc platform
+- #6049: support for OpenBSD/macppc platform
   (Anil Madhavapeddy, review by Benedikt Meurer)
-- PR#6059: add -output-obj rules for ocamlbuild
+- #6059: add -output-obj rules for ocamlbuild
   (Anil Madhavapeddy)
-- PR#6060: ocamlbuild tags 'principal', 'strict_sequence' and 'short_paths'
+- #6060: ocamlbuild tags 'principal', 'strict_sequence' and 'short_paths'
   (Anil Madhavapeddy)
 - ocamlbuild tag 'no_alias_deps'
   (Daniel Bünzli)
@@ -4666,9 +5613,9 @@ Tools:
   (Jonathan Protzenko)
 - OCamlbuild now picks the non-core tools like ocamlfind and menhir from PATH
   (Wojciech Meyer)
-- PR#5884: Misc minor fixes and cleanup for emacs mode
+- #5884: Misc minor fixes and cleanup for emacs mode
   (Stefan Monnier)
-- PR#6030: Improve performance of -annot
+- #6030: Improve performance of -annot
   (Guillaume Melquiond, Alain Frisch)
 
 
@@ -4676,30 +5623,30 @@ OCaml 4.00.1 (5 Oct 2012):
 --------------------------
 
 Bug fixes:
-- PR#4019: better documentation of Str.matched_string
-- PR#5111: ocamldoc, heading tags inside spans tags is illegal in html
-- PR#5278: better error message when typing "make"
-- PR#5468: ocamlbuild should preserve order of parametric tags
-- PR#5563: harden Unix.select against file descriptors above FD_SETSIZE
-- PR#5690: "ocamldoc ... -text README" raises exception
-- PR#5700: crash with native-code stack backtraces under MacOS 10.8 x86-64
-- PR#5707: AMD64 code generator: do not use r10 and r11 for parameter passing,
+- #4019: better documentation of Str.matched_string
+- #5111: ocamldoc, heading tags inside spans tags is illegal in html
+- #5278: better error message when typing "make"
+- #5468: ocamlbuild should preserve order of parametric tags
+- #5563: harden Unix.select against file descriptors above FD_SETSIZE
+- #5690: "ocamldoc ... -text README" raises exception
+- #5700: crash with native-code stack backtraces under MacOS 10.8 x86-64
+- #5707: AMD64 code generator: do not use r10 and r11 for parameter passing,
   as these registers can be destroyed by the dynamic loader
-- PR#5712: some documentation problems
-- PR#5715: configuring with -no-shared-libs breaks under cygwin
-- PR#5718: false positive on 'unused constructor' warning
-- PR#5719: ocamlyacc generates code that is not warning 33-compliant
-- PR#5725: ocamldoc output of preformatted code
-- PR#5727: emacs caml-mode indents shebang line in toplevel scripts
-- PR#5729: tools/untypeast.ml creates unary Pexp_tuple
-- PR#5731: instruction scheduling forgot to account for destroyed registers
-- PR#5735: %apply and %revapply not first class citizens
-- PR#5738: first class module patterns not handled by ocamldep
-- PR#5742: missing bound checks in Array.sub
-- PR#5744: ocamldoc error on "val virtual"
-- PR#5757: GC compaction bug (crash)
-- PR#5758: Compiler bug when matching on floats
-- PR#5761: Incorrect bigarray custom block size
+- #5712: some documentation problems
+- #5715: configuring with -no-shared-libs breaks under cygwin
+- #5718: false positive on 'unused constructor' warning
+- #5719: ocamlyacc generates code that is not warning 33-compliant
+- #5725: ocamldoc output of preformatted code
+- #5727: emacs caml-mode indents shebang line in toplevel scripts
+- #5729: tools/untypeast.ml creates unary Pexp_tuple
+- #5731: instruction scheduling forgot to account for destroyed registers
+- #5735: %apply and %revapply not first class citizens
+- #5738: first class module patterns not handled by ocamldep
+- #5742: missing bound checks in Array.sub
+- #5744: ocamldoc error on "val virtual"
+- #5757: GC compaction bug (crash)
+- #5758: Compiler bug when matching on floats
+- #5761: Incorrect bigarray custom block size
 
 
 OCaml 4.00.0 (26 Jul 2012):
@@ -4719,7 +5666,7 @@ Language features:
   unpacking of a first-class module.
 
 Compilers:
-- Revised simplification of let-alias (PR#5205, PR#5288)
+- Revised simplification of let-alias (#5205, #5288)
 - Better reporting of compiler version mismatch in .cmi files
 * Warning 28 is now enabled by default.
 - New option -absname to use absolute paths in error messages
@@ -4731,10 +5678,10 @@ Compilers:
   with the "method" keyword.  Use "method!" to avoid the warning.
 
 Native-code compiler:
-- Optimized handling of partially-applied functions (PR#5287)
-- Small improvements in code generated for array bounds checks (PR#5345,
-  PR#5360).
-* New ARM backend (PR#5433):
+- Optimized handling of partially-applied functions (#5287)
+- Small improvements in code generated for array bounds checks (#5345,
+  #5360).
+* New ARM backend (#5433):
     . Supports both Linux/EABI (armel) and Linux/EABI+VFPv3 (armhf).
     . Added support for the Thumb-2 instruction set with average code size
       savings of 28%.
@@ -4743,51 +5690,51 @@ Native-code compiler:
 - Generation of CFI information, and filename/line number debugging (with -g)
   annotations, enabling in particular precise stack backtraces with
   the gdb debugger. Currently supported for x86 32-bits and 64-bits only.
-  (PR#5487)
+  (#5487)
 - New tool: ocamloptp, the equivalent of ocamlcp for the native-code compiler.
 
 OCamldoc:
-- PR#5645: ocamldoc doesn't handle module/type substitution in signatures
-- PR#5544: improve HTML output (less formatting in html code)
-- PR#5522: allow refering to record fields and variant constructors
-- fix PR#5419 (error message in french)
-- fix PR#5535 (no cross ref to class after dump+load)
+- #5645: ocamldoc doesn't handle module/type substitution in signatures
+- #5544: improve HTML output (less formatting in html code)
+- #5522: allow referring to record fields and variant constructors
+- fix #5419 (error message in french)
+- fix #5535 (no cross ref to class after dump+load)
 * Use first class modules for custom generators, to be able to
   load various plugins incrementally adding features to the current
   generator
-* PR#5507: Use Location.t structures for locations.
+* #5507: Use Location.t structures for locations.
 - fix: do not keep code when not told to keep code.
 
 Standard library:
-- Added float functions "hypot" and "copysign" (PR#3806, PR#4752, PR#5246)
+- Added float functions "hypot" and "copysign" (#3806, #4752, #5246)
 * Arg: options with empty doc strings are no longer included in the usage string
-  (PR#5437)
+  (#5437)
 - Array: faster implementations of "blit", "copy", "sub", "append" and "concat"
-  (PR#2395, PR#2787, PR#4591)
+  (#2395, #2787, #4591)
 * Hashtbl:
-    . Statistically-better generic hash function based on Murmur 3 (PR#5225)
-    . Fixed behavior of generic hash function w.r.t. -0.0 and NaN (PR#5222)
+    . Statistically-better generic hash function based on Murmur 3 (#5225)
+    . Fixed behavior of generic hash function w.r.t. -0.0 and NaN (#5222)
     . Added optional "random" parameter to Hashtbl.create to randomize
-      collision patterns and improve security (PR#5572, CVE-2012-0839)
+      collision patterns and improve security (#5572, CVE-2012-0839)
     . Added "randomize" function and "R" parameter to OCAMLRUNPARAM
-      to turn randomization on by default (PR#5572, CVE-2012-0839)
+      to turn randomization on by default (#5572, CVE-2012-0839)
     . Added new functorial interface "MakeSeeded" to support randomization
       with user-provided seeded hash functions.
     . Install new header  for C code.
 - Filename: on-demand (lazy) initialization of the PRNG used by "temp_file".
 - Marshal: marshalling of function values (flag Marshal.Closures) now
-  also works for functions that come from dynamically-loaded modules (PR#5215)
+  also works for functions that come from dynamically-loaded modules (#5215)
 - Random:
      . More random initialization (Random.self_init()), using /dev/urandom
        when available (e.g. Linux, FreeBSD, MacOS X, Solaris)
      * Faster implementation of Random.float (changes the generated sequences)
-- Format strings for formatted input/output revised to correct PR#5380
+- Format strings for formatted input/output revised to correct #5380
     . Consistently treat %@ as a plain @ character
     . Consistently treat %% as a plain % character
 - Scanf: width and precision for floating point numbers are now handled
-- Scanf: new function "unescaped" (PR#3888)
+- Scanf: new function "unescaped" (#3888)
 - Set and Map: more efficient implementation of "filter" and "partition"
-- String: new function "map" (PR#3888)
+- String: new function "map" (#3888)
 
 Installation procedure:
 - Compiler internals are now installed in `ocamlc -where`/compiler-libs.
@@ -4797,7 +5744,7 @@ Installation procedure:
       ocamlbytecomp.cma/.cmxa   modules for ocamlc and ocaml
       ocamloptcomp.cma/.cmxa    modules specific to ocamlopt
       ocamltoplevel.cma         modules specific to ocaml
-   (PR#1804, PR#4653, frequently-asked feature).
+   (#8255, #4653, frequently-asked feature).
 * Some .cmi for toplevel internals that used to be installed in
   `ocamlc -where` are now to be found in  `ocamlc -where`/compiler-libs.
   Add "-I +compiler-libs" where needed.
@@ -4809,208 +5756,208 @@ Installation procedure:
 
 Bug Fixes:
 
-- PR#1643: functions of the Lazy module whose named started with 'lazy_' have
+- #8109: functions of the Lazy module whose named started with 'lazy_' have
   been deprecated, and new ones without the prefix added
-- PR#3571: in Bigarrays, call msync() before unmapping to commit changes
-- PR#4292: various documentation problems
-- PR#4511, PR#4838: local modules remove polymorphism
-* PR#4549: Filename.dirname is not handling multiple / on Unix
-- PR#4688: (Windows) special floating-point values aren't converted to strings
+- #3571: in Bigarrays, call msync() before unmapping to commit changes
+- #4292: various documentation problems
+- #4511, #4838: local modules remove polymorphism
+* #4549: Filename.dirname is not handling multiple / on Unix
+- #4688: (Windows) special floating-point values aren't converted to strings
   correctly
-- PR#4697: Unix.putenv leaks memory on failure
-- PR#4705: camlp4 does not allow to define types with `True or `False
-- PR#4746: wrong detection of stack overflows in native code under Linux
-- PR#4869: rare collisions between assembly labels for code and data
-- PR#4880: "assert" constructs now show up in the exception stack backtrace
-- PR#4892: Array.set could raise "out of bounds" before evaluating 3rd arg
-- PR#4937: camlp4 incorrectly handles optional arguments if 'option' is
+- #4697: Unix.putenv leaks memory on failure
+- #4705: camlp4 does not allow to define types with `True or `False
+- #4746: wrong detection of stack overflows in native code under Linux
+- #4869: rare collisions between assembly labels for code and data
+- #4880: "assert" constructs now show up in the exception stack backtrace
+- #4892: Array.set could raise "out of bounds" before evaluating 3rd arg
+- #4937: camlp4 incorrectly handles optional arguments if 'option' is
   redefined
-- PR#5024: camlp4r now handles underscores in irrefutable pattern matching of
+- #5024: camlp4r now handles underscores in irrefutable pattern matching of
   records
-- PR#5064, PR#5485: try to ensure that 4K words of stack are available
+- #5064, #5485: try to ensure that 4K words of stack are available
   before calling into C functions, raising a Stack_overflow exception
   otherwise.  This reduces (but does not eliminate) the risk of
   segmentation faults due to stack overflow in C code
-- PR#5073: wrong location for 'Unbound record field label' error
-- PR#5084: sub-sub-module building fails for native code compilation
-- PR#5120: fix the output function of Camlp4.Debug.formatter
-- PR#5131: compilation of custom runtime with g++ generates lots of warnings
-- PR#5137: caml-types-explore does not work
-- PR#5159: better documentation of type Lexing.position
-- PR#5171: Map.join does more comparisons than needed
-- PR#5176: emacs mode: stack overflow in regexp matcher
-- PR#5179: port OCaml to mingw-w64
-- PR#5211: updated Genlex documentation to state that camlp4 is mandatory for
+- #5073: wrong location for 'Unbound record field label' error
+- #5084: sub-sub-module building fails for native code compilation
+- #5120: fix the output function of Camlp4.Debug.formatter
+- #5131: compilation of custom runtime with g++ generates lots of warnings
+- #5137: caml-types-explore does not work
+- #5159: better documentation of type Lexing.position
+- #5171: Map.join does more comparisons than needed
+- #5176: emacs mode: stack overflow in regexp matcher
+- #5179: port OCaml to mingw-w64
+- #5211: updated Genlex documentation to state that camlp4 is mandatory for
   'parser' keyword and associated notation
-- PR#5214: ocamlfind plugin invokes 'cut' utility
-- PR#5218: use $(MAKE) instead of "make" in Makefiles
-- PR#5224: confusing error message in non-regular type definition
-- PR#5231: camlp4: fix parsing of <:str_item< type t = $x$ >>
-- PR#5233: finaliser on weak array gives dangling pointers (crash)
-- PR#5238, PR#5277: Sys_error when getting error location
-- PR#5261, PR#5497: Ocaml source-code examples are not "copy-paste-able"
-* PR#5279: executable name is not initialized properly in caml_startup_code
-- PR#5290: added hash functions for channels, nats, mutexes, conditions
-- PR#5291: undetected loop in class initialization
-- PR#5295: OS threads: problem with caml_c_thread_unregister()
-- PR#5301: camlp4r and exception equal to another one with parameters
-- PR#5305: prevent ocamlbuild from complaining about links to _build/
-- PR#5306: comparing to Thread.self() raises exception at runtime
-- PR#5309: Queue.add is not thread/signal safe
-- PR#5310: Ratio.create_ratio/create_normalized_ratio have misleading names
-- PR#5311: better message for warning 23
-* PR#5312: command-line arguments @reponsefile auto-expansion feature
+- #5214: ocamlfind plugin invokes 'cut' utility
+- #5218: use $(MAKE) instead of "make" in Makefiles
+- #5224: confusing error message in non-regular type definition
+- #5231: camlp4: fix parsing of <:str_item< type t = $x$ >>
+- #5233: finaliser on weak array gives dangling pointers (crash)
+- #5238, #5277: Sys_error when getting error location
+- #5261, #5497: Ocaml source-code examples are not "copy-paste-able"
+* #5279: executable name is not initialized properly in caml_startup_code
+- #5290: added hash functions for channels, nats, mutexes, conditions
+- #5291: undetected loop in class initialization
+- #5295: OS threads: problem with caml_c_thread_unregister()
+- #5301: camlp4r and exception equal to another one with parameters
+- #5305: prevent ocamlbuild from complaining about links to _build/
+- #5306: comparing to Thread.self() raises exception at runtime
+- #5309: Queue.add is not thread/signal safe
+- #5310: Ratio.create_ratio/create_normalized_ratio have misleading names
+- #5311: better message for warning 23
+* #5312: command-line arguments @reponsefile auto-expansion feature
   removed from the Windows OCaml runtime, to avoid conflicts with "-w @..."
-- PR#5313: ocamlopt -g misses optimizations
-- PR#5214: ocamlfind plugin invokes 'cut' utility
-- PR#5316: objinfo now shows ccopts/ccobjs/force_link when applicable
-- PR#5318: segfault on stack overflow when reading marshaled data
-- PR#5319: %r11 clobbered by Lswitch in Windows AMD64 native-code compilation
-- PR#5322: type abbreviations expanding to a universal type variable
-- PR#5328: under Windows, Unix.select leaves sockets in non-blocking mode
-- PR#5330: thread tag with '.top' and '.inferred.mli' targets
-- PR#5331: ocamlmktop is not always a shell script
-- PR#5335: Unix.environment segfaults after a call to clearenv
-- PR#5338: sanitize.sh has windows style end-of-lines (mingw)
-- PR#5344: some predefined exceptions need special printing
-- PR#5349: Hashtbl.replace uses new key instead of reusing old key
-- PR#5356: ocamlbuild handling of 'predicates' for ocamlfind
-- PR#5364: wrong compilation of "((val m : SIG1) : SIG2)"
-- PR#5370: ocamldep omits filename in syntax error message
-- PR#5374: camlp4 creates wrong location for type definitions
-- PR#5380: strange sscanf input segfault
-- PR#5382: EOPNOTSUPP and ENOTSUPP different on exotic platforms
-- PR#5383: build failure in Win32/MSVC
-- PR#5387: camlp4: str_item and other syntactic elements with Nils are
+- #5313: ocamlopt -g misses optimizations
+- #5214: ocamlfind plugin invokes 'cut' utility
+- #5316: objinfo now shows ccopts/ccobjs/force_link when applicable
+- #5318: segfault on stack overflow when reading marshaled data
+- #5319: %r11 clobbered by Lswitch in Windows AMD64 native-code compilation
+- #5322: type abbreviations expanding to a universal type variable
+- #5328: under Windows, Unix.select leaves sockets in non-blocking mode
+- #5330: thread tag with '.top' and '.inferred.mli' targets
+- #5331: ocamlmktop is not always a shell script
+- #5335: Unix.environment segfaults after a call to clearenv
+- #5338: sanitize.sh has windows style end-of-lines (mingw)
+- #5344: some predefined exceptions need special printing
+- #5349: Hashtbl.replace uses new key instead of reusing old key
+- #5356: ocamlbuild handling of 'predicates' for ocamlfind
+- #5364: wrong compilation of "((val m : SIG1) : SIG2)"
+- #5370: ocamldep omits filename in syntax error message
+- #5374: camlp4 creates wrong location for type definitions
+- #5380: strange sscanf input segfault
+- #5382: EOPNOTSUPP and ENOTSUPP different on exotic platforms
+- #5383: build failure in Win32/MSVC
+- #5387: camlp4: str_item and other syntactic elements with Nils are
   not very usable
-- PR#5389: compaction sometimes leaves a very large heap
-- PR#5393: fails to build from source on GNU/kFreeBSD because of -R link option
-- PR#5394: documentation for -dtypes is missing in manpage
-- PR#5397: Filename.temp_dir_name should be mutable
-- PR#5410: fix printing of class application with Camlp4
-- PR#5416: (Windows) Unix.(set|clear)_close_on_exec now preserves blocking mode
-- PR#5435: ocamlbuild does not find .opt executables on Windows
-- PR#5436: update object ids on unmarshaling
-- PR#5442: camlp4: quotation issue with strings
-- PR#5453: configure doesn't find X11 under Ubuntu/MultiarchSpec
-- PR#5461: Double linking of bytecode modules
-- PR#5463: Bigarray.*.map_file fail if empty array is requested
-- PR#5465: increase stack size of ocamlopt.opt for windows
-- PR#5469: private record type generated by functor loses abbreviation
-- PR#5475: Wrapper script for interpreted LablTk wrongly handles command line
+- #5389: compaction sometimes leaves a very large heap
+- #5393: fails to build from source on GNU/kFreeBSD because of -R link option
+- #5394: documentation for -dtypes is missing in manpage
+- #5397: Filename.temp_dir_name should be mutable
+- #5410: fix printing of class application with Camlp4
+- #5416: (Windows) Unix.(set|clear)_close_on_exec now preserves blocking mode
+- #5435: ocamlbuild does not find .opt executables on Windows
+- #5436: update object ids on unmarshaling
+- #5442: camlp4: quotation issue with strings
+- #5453: configure doesn't find X11 under Ubuntu/MultiarchSpec
+- #5461: Double linking of bytecode modules
+- #5463: Bigarray.*.map_file fail if empty array is requested
+- #5465: increase stack size of ocamlopt.opt for windows
+- #5469: private record type generated by functor loses abbreviation
+- #5475: Wrapper script for interpreted LablTk wrongly handles command line
   parameters
-- PR#5476: bug in native code compilation of let rec on float arrays
-- PR#5477: use pkg-config to configure graphics on linux
-- PR#5481: update camlp4 magic numbers
-- PR#5482: remove bashism in test suite scripts
-- PR#5495: camlp4o dies on infix definition (or)
-- PR#5498: Unification with an empty object only checks the absence of
+- #5476: bug in native code compilation of let rec on float arrays
+- #5477: use pkg-config to configure graphics on linux
+- #5481: update camlp4 magic numbers
+- #5482: remove bashism in test suite scripts
+- #5495: camlp4o dies on infix definition (or)
+- #5498: Unification with an empty object only checks the absence of
   the first method
-- PR#5503: error when ocamlbuild is passed an absolute path as build directory
-- PR#5509: misclassification of statically-allocated empty array that
+- #5503: error when ocamlbuild is passed an absolute path as build directory
+- #5509: misclassification of statically-allocated empty array that
   falls exactly at beginning of an otherwise unused data page.
-- PR#5510: ocamldep has duplicate -ml{,i}-synonym options
-- PR#5511: in Bigarray.reshape, unwarranted limitation on new array dimensions.
-- PR#5513: Int64.div causes floating point exception (ocamlopt, x86)
-- PR#5516: in Bigarray C stubs, use C99 flexible array types if possible
-- PR#5518: segfault with lazy empty array
-- PR#5531: Allow ocamlbuild to add ocamldoc flags through -docflag
+- #5510: ocamldep has duplicate -ml{,i}-synonym options
+- #5511: in Bigarray.reshape, unwarranted limitation on new array dimensions.
+- #5513: Int64.div causes floating point exception (ocamlopt, x86)
+- #5516: in Bigarray C stubs, use C99 flexible array types if possible
+- #5518: segfault with lazy empty array
+- #5531: Allow ocamlbuild to add ocamldoc flags through -docflag
   and -docflags switches
-- PR#5538: combining -i and -annot in ocamlc
-- PR#5543: in Bigarray.map_file, try to avoid using lseek() when growing file
-- PR#5648: (probably fixed) test failures in tests/lib-threads
-- PR#5551: repeated calls to find_in_path degrade performance
-- PR#5552: Mac OS X: unrecognized gcc option "-no-cpp-precomp"
-- PR#5555: add Hashtbl.reset to resize the bucket table to its initial size
-- PR#5560: incompatible type for tuple pattern with -principal
-- PR#5575: Random states are not marshallable across architectures
-- PR#5579: camlp4: when a plugin is loaded in the toplevel,
+- #5538: combining -i and -annot in ocamlc
+- #5543: in Bigarray.map_file, try to avoid using lseek() when growing file
+- #5648: (probably fixed) test failures in tests/lib-threads
+- #5551: repeated calls to find_in_path degrade performance
+- #5552: Mac OS X: unrecognized gcc option "-no-cpp-precomp"
+- #5555: add Hashtbl.reset to resize the bucket table to its initial size
+- #5560: incompatible type for tuple pattern with -principal
+- #5575: Random states are not marshallable across architectures
+- #5579: camlp4: when a plugin is loaded in the toplevel,
   Token.Filter.define_filter has no effect before the first syntax error
-- PR#5585: typo: "explicitely"
-- PR#5587: documentation: "allows to" is not correct English
-- PR#5593: remove C file when -output-obj fails
-- PR#5597: register names for instrtrace primitives in embedded bytecode
-- PR#5598: add backslash-space support in strings in ocamllex
-- PR#5603: wrong .file debug info generated by ocamlopt -g
-- PR#5604: fix permissions of files created by ocamlbuild itself
-- PR#5610: new unmarshaler (from PR#5318) fails to freshen object identifiers
-- PR#5614: add missing -linkall flag when compiling ocamldoc.opt
-- PR#5616: move ocamlbuild documentation to the reference manual
-- PR#5619: Uncaught CType.Unify exception in the compiler
-- PR#5620: invalid printing of type manifest (camlp4 revised syntax)
-- PR#5637: invalid printing of anonymous type parameters (camlp4 revised syntax)
-- PR#5643: issues with .cfi and .loc directives generated by ocamlopt -g
-- PR#5644: Stream.count broken when used with Sapp or Slazy nodes
-- PR#5647: Cannot use install_printer in debugger
-- PR#5651: printer for abstract data type (camlp4 revised syntax)
-- PR#5654: self pattern variable location tweak
-- PR#5655: ocamlbuild doesn't pass cflags when building C stubs
-- PR#5657: wrong error location for abbreviated record fields
-- PR#5659: ocamlmklib -L option breaks with MSVC
-- PR#5661: fixes for the test suite
-- PR#5668: Camlp4 produces invalid syntax for "let _ = ..."
-- PR#5671: initialization of compare_ext field in caml_final_custom_operations()
-- PR#5677: do not use "value" as identifier (genprintval.ml)
-- PR#5687: dynlink broken when used from "output-obj" main program (bytecode)
+- #5585: typo: "explicitely"
+- #5587: documentation: "allows to" is not correct English
+- #5593: remove C file when -output-obj fails
+- #5597: register names for instrtrace primitives in embedded bytecode
+- #5598: add backslash-space support in strings in ocamllex
+- #5603: wrong .file debug info generated by ocamlopt -g
+- #5604: fix permissions of files created by ocamlbuild itself
+- #5610: new unmarshaler (from #5318) fails to freshen object identifiers
+- #5614: add missing -linkall flag when compiling ocamldoc.opt
+- #5616: move ocamlbuild documentation to the reference manual
+- #5619: Uncaught CType.Unify exception in the compiler
+- #5620: invalid printing of type manifest (camlp4 revised syntax)
+- #5637: invalid printing of anonymous type parameters (camlp4 revised syntax)
+- #5643: issues with .cfi and .loc directives generated by ocamlopt -g
+- #5644: Stream.count broken when used with Sapp or Slazy nodes
+- #5647: Cannot use install_printer in debugger
+- #5651: printer for abstract data type (camlp4 revised syntax)
+- #5654: self pattern variable location tweak
+- #5655: ocamlbuild doesn't pass cflags when building C stubs
+- #5657: wrong error location for abbreviated record fields
+- #5659: ocamlmklib -L option breaks with MSVC
+- #5661: fixes for the test suite
+- #5668: Camlp4 produces invalid syntax for "let _ = ..."
+- #5671: initialization of compare_ext field in caml_final_custom_operations()
+- #5677: do not use "value" as identifier (genprintval.ml)
+- #5687: dynlink broken when used from "output-obj" main program (bytecode)
 - problem with printing of string literals in camlp4 (reported on caml-list)
 - emacs mode: colorization of comments and strings now works correctly
 - problem with forall and method (reported on caml-list on 2011-07-26)
 - crash when using OCAMLRUNPARAM=a=X with invalid X (reported in private)
 
 Feature wishes:
-- PR#352: new option "-stdin" to make ocaml read stdin as a script
-- PR#1164: better error message when mixing -a and .cmxa
-- PR#1284: documentation: remove restriction on mixed streams
-- PR#1496: allow configuring LIBDIR, BINDIR, and MANDIR relative to $(PREFIX)
-- PR#1835: add Digest.from_hex
-- PR#1898: toplevel: add option to suppress continuation prompts
-- PR#4278: configure: option to disable "graph" library
-- PR#4444: new String.trim function, removing leading and trailing whistespace
-- PR#4549: make Filename.dirname/basename POSIX compliant
-- PR#4830: add option -v to expunge.ml
-- PR#4898: new Sys.big_endian boolean for machine endianness
-- PR#4963, PR#5467: no extern "C" into ocaml C-stub headers
-- PR#5199: tests are run only for bytecode if either native support is missing,
+- #2757: new option "-stdin" to make ocaml read stdin as a script
+- #3358: better error message when mixing -a and .cmxa
+- #3492: documentation: remove restriction on mixed streams
+- #7971: allow configuring LIBDIR, BINDIR, and MANDIR relative to $(PREFIX)
+- #8285: add Digest.from_hex
+- #8341: toplevel: add option to suppress continuation prompts
+- #4278: configure: option to disable "graph" library
+- #4444: new String.trim function, removing leading and trailing whistespace
+- #4549: make Filename.dirname/basename POSIX compliant
+- #4830: add option -v to expunge.ml
+- #4898: new Sys.big_endian boolean for machine endianness
+- #4963, #5467: no extern "C" into ocaml C-stub headers
+- #5199: tests are run only for bytecode if either native support is missing,
   or a non-empty value is set to "BYTECODE_ONLY" Makefile variable
-- PR#5215: marshalling of dynlinked closure
-- PR#5236: new '%revapply' primitive with the semantics 'revapply x f = f x',
+- #5215: marshalling of dynlinked closure
+- #5236: new '%revapply' primitive with the semantics 'revapply x f = f x',
     and '%apply' with semantics 'apply f x = f x'.
-- PR#5255: natdynlink detection on powerpc, hurd, sparc
-- PR#5295: OS threads: problem with caml_c_thread_unregister()
-- PR#5297: compiler now checks existence of builtin primitives
-- PR#5329: (Windows) more efficient Unix.select if all fd's are sockets
-- PR#5357: warning for useless open statements
-- PR#5358: first class modules don't allow "with type" declarations for types
+- #5255: natdynlink detection on powerpc, hurd, sparc
+- #5295: OS threads: problem with caml_c_thread_unregister()
+- #5297: compiler now checks existence of builtin primitives
+- #5329: (Windows) more efficient Unix.select if all fd's are sockets
+- #5357: warning for useless open statements
+- #5358: first class modules don't allow "with type" declarations for types
   in sub-modules
-- PR#5385: configure: emit a warning when MACOSX_DEPLOYMENT_TARGET is set
-- PR#5396: ocamldep: add options -sort, -all, and -one-line
-- PR#5397: Filename.temp_dir_name should be mutable
-- PR#5403: give better error message when emacs is not found in PATH
-- PR#5411: new directive for the toplevel: #load_rec
-- PR#5420: Unix.openfile share mode (Windows)
-- PR#5421: Unix: do not leak fds in various open_proc* functions
-- PR#5434: implement Unix.times in win32unix (partially)
-- PR#5438: new warnings for unused declarations
-- PR#5439: upgrade config.guess and config.sub
-- PR#5445 and others: better printing of types with user-provided names
-- PR#5454: Digest.compare is missing and md5 doc update
-- PR#5455: .emacs instructions, add lines to recognize ocaml scripts
-- PR#5456: pa_macro: replace __LOCATION__ after macro expansion; add LOCATION_OF
-- PR#5461: bytecode: emit warning when linking two modules with the same name
-- PR#5478: ocamlopt assumes ar command exists
-- PR#5479: Num.num_of_string may raise an exception, not reflected in the
+- #5385: configure: emit a warning when MACOSX_DEPLOYMENT_TARGET is set
+- #5396: ocamldep: add options -sort, -all, and -one-line
+- #5397: Filename.temp_dir_name should be mutable
+- #5403: give better error message when emacs is not found in PATH
+- #5411: new directive for the toplevel: #load_rec
+- #5420: Unix.openfile share mode (Windows)
+- #5421: Unix: do not leak fds in various open_proc* functions
+- #5434: implement Unix.times in win32unix (partially)
+- #5438: new warnings for unused declarations
+- #5439: upgrade config.guess and config.sub
+- #5445 and others: better printing of types with user-provided names
+- #5454: Digest.compare is missing and md5 doc update
+- #5455: .emacs instructions, add lines to recognize ocaml scripts
+- #5456: pa_macro: replace __LOCATION__ after macro expansion; add LOCATION_OF
+- #5461: bytecode: emit warning when linking two modules with the same name
+- #5478: ocamlopt assumes ar command exists
+- #5479: Num.num_of_string may raise an exception, not reflected in the
   documentation.
-- PR#5501: increase IO_BUFFER_SIZE to 64KiB
-- PR#5532: improve error message when bytecode file is wrong
-- PR#5555: add function Hashtbl.reset to resize the bucket table to
+- #5501: increase IO_BUFFER_SIZE to 64KiB
+- #5532: improve error message when bytecode file is wrong
+- #5555: add function Hashtbl.reset to resize the bucket table to
   its initial size.
-- PR#5586: increase UNIX_BUFFER_SIZE to 64KiB
-- PR#5597: register names for instrtrace primitives in embedded bytecode
-- PR#5599: Add warn() tag in ocamlbuild to control -w compiler switch
-- PR#5628: add #remove_directory and Topdirs.remove_directory to remove
+- #5586: increase UNIX_BUFFER_SIZE to 64KiB
+- #5597: register names for instrtrace primitives in embedded bytecode
+- #5599: Add warn() tag in ocamlbuild to control -w compiler switch
+- #5628: add #remove_directory and Topdirs.remove_directory to remove
   a directory from the load path
-- PR#5636: in system threads library, issue with linking of pthread_atfork
-- PR#5666: C includes don't provide a revision number
+- #5636: in system threads library, issue with linking of pthread_atfork
+- #5666: C includes don't provide a revision number
 - ocamldebug: ability to inspect values that contain code pointers
 - ocamldebug: new 'environment' directive to set environment variables
   for debuggee
@@ -5033,71 +5980,71 @@ OCaml 3.12.1 (4 Jul 2011):
 --------------------------
 
 Bug fixes:
-- PR#4345, PR#4767: problems with camlp4 printing of float values
-- PR#4380: ocamlbuild should not use tput on windows
-- PR#4487, PR#5164: multiple 'module type of' are incompatible
-- PR#4552: ocamlbuild does not create symlinks when using '.itarget' file
-- PR#4673, PR#5144: camlp4 fails on object copy syntax
-- PR#4702: system threads: cleanup tick thread at exit
-- PR#4732: camlp4 rejects polymorphic variants using keywords from macros
-- PR#4778: Win32/MSVC port: rare syntax error in generated MASM assembly file
-- PR#4794, PR#4959: call annotations not generated by ocamlopt
-- PR#4820: revised syntax pretty printer crashes with 'Stack_overflow'
-- PR#4928: wrong printing of classes and class types by camlp4
-- PR#4939: camlp4 rejects patterns of the '?x:_' form
-- PR#4967: ocamlbuild passes wrong switches to ocamldep through menhir
-- PR#4972: mkcamlp4 does not include 'dynlink.cma'
-- PR#5039: ocamlbuild should use '-linkpkg' only when linking programs
-- PR#5066: ocamldoc: add -charset option used in html generator
-- PR#5069: fcntl() in caml_sys_open may block, do it within blocking section
-- PR#5071, PR#5129, PR#5134: inconsistencies between camlp4 and camlp4* binaries
-- PR#5080, PR#5104: regression in type constructor handling by camlp4
-- PR#5090: bad interaction between toplevel and camlp4
-- PR#5095: ocamlbuild ignores some tags when building bytecode objects
-- PR#5100: ocamlbuild always rebuilds a 'cmxs' file
-- PR#5103: build and install objinfo when building with ocamlbuild
-- PR#5109: crash when a parser calls a lexer that calls another parser
-- PR#5110: invalid module name when using optional argument
-- PR#5115: bytecode executables produced by msvc64 port crash on 32-bit versions
-- PR#5117: bigarray: wrong function name without HAS_MMAP; missing include
-- PR#5118: Camlp4o and integer literals
-- PR#5122: camlp4 rejects lowercase identifiers for module types
-- PR#5123: shift_right_big_int returns a wrong zero
-- PR#5124: substitution inside a signature leads to odd printing
-- PR#5128: typo in 'Camlp4ListComprehension' syntax extension
-- PR#5136: obsolete function used in emacs mode
-- PR#5145: ocamldoc: missing html escapes
-- PR#5146: problem with spaces in multi-line string constants
-- PR#5149: (partial) various documentation problems
-- PR#5156: rare compiler crash with objects
-- PR#5165: ocamlbuild does not pass '-thread' option to ocamlfind
-- PR#5167: camlp4r loops when printing package type
-- PR#5172: camlp4 support for 'module type of' construct
-- PR#5175: in bigarray accesses, make sure bigarray expr is evaluated only once
-- PR#5177: Gc.compact implies Gc.full_major
-- PR#5182: use bytecode version of ocamldoc to generate man pages
-- PR#5184: under Windows, alignment issue with bigarrays mapped from files
-- PR#5188: double-free corruption in bytecode system threads
-- PR#5192: mismatch between words and bytes in interpreting max_young_wosize
-- PR#5202: error in documentation of atan2
-- PR#5209: natdynlink incorrectly detected on BSD systems
-- PR#5213: ocamlbuild should pass '-rectypes' to ocamldoc when needed
-- PR#5217: ocamlfind plugin should add '-linkpkg' for toplevel
-- PR#5228: document the exceptions raised by functions in 'Filename'
-- PR#5229: typo in build script ('TAG_LINE' vs 'TAGLINE')
-- PR#5230: error in documentation of Scanf.Scanning.open_in
-- PR#5234: option -shared reverses order of -cclib options
-- PR#5237: incorrect .size directives generated for x86-32 and x86-64
-- PR#5244: String.compare uses polymorphic compare_val (regression of PR#4194)
-- PR#5248: regression introduced while fixing PR#5118
-- PR#5252: typo in docs
-- PR#5258: win32unix: unix fd leak under windows
-- PR#5269: (tentative fix) Wrong ext_ref entries in .annot files
-- PR#5272: caml.el doesn't recognize downto as a keyword
-- PR#5276: issue with ocamlc -pack and recursively-packed modules
-- PR#5280: alignment constraints incorrectly autodetected on MIPS 32
-- PR#5281: typo in error message
-- PR#5308: unused variables not detected in "include (struct .. end)"
+- #4345, #4767: problems with camlp4 printing of float values
+- #4380: ocamlbuild should not use tput on windows
+- #4487, #5164: multiple 'module type of' are incompatible
+- #4552: ocamlbuild does not create symlinks when using '.itarget' file
+- #4673, #5144: camlp4 fails on object copy syntax
+- #4702: system threads: cleanup tick thread at exit
+- #4732: camlp4 rejects polymorphic variants using keywords from macros
+- #4778: Win32/MSVC port: rare syntax error in generated MASM assembly file
+- #4794, #4959: call annotations not generated by ocamlopt
+- #4820: revised syntax pretty printer crashes with 'Stack_overflow'
+- #4928: wrong printing of classes and class types by camlp4
+- #4939: camlp4 rejects patterns of the '?x:_' form
+- #4967: ocamlbuild passes wrong switches to ocamldep through menhir
+- #4972: mkcamlp4 does not include 'dynlink.cma'
+- #5039: ocamlbuild should use '-linkpkg' only when linking programs
+- #5066: ocamldoc: add -charset option used in html generator
+- #5069: fcntl() in caml_sys_open may block, do it within blocking section
+- #5071, #5129, #5134: inconsistencies between camlp4 and camlp4* binaries
+- #5080, #5104: regression in type constructor handling by camlp4
+- #5090: bad interaction between toplevel and camlp4
+- #5095: ocamlbuild ignores some tags when building bytecode objects
+- #5100: ocamlbuild always rebuilds a 'cmxs' file
+- #5103: build and install objinfo when building with ocamlbuild
+- #5109: crash when a parser calls a lexer that calls another parser
+- #5110: invalid module name when using optional argument
+- #5115: bytecode executables produced by msvc64 port crash on 32-bit versions
+- #5117: bigarray: wrong function name without HAS_MMAP; missing include
+- #5118: Camlp4o and integer literals
+- #5122: camlp4 rejects lowercase identifiers for module types
+- #5123: shift_right_big_int returns a wrong zero
+- #5124: substitution inside a signature leads to odd printing
+- #5128: typo in 'Camlp4ListComprehension' syntax extension
+- #5136: obsolete function used in emacs mode
+- #5145: ocamldoc: missing html escapes
+- #5146: problem with spaces in multi-line string constants
+- #5149: (partial) various documentation problems
+- #5156: rare compiler crash with objects
+- #5165: ocamlbuild does not pass '-thread' option to ocamlfind
+- #5167: camlp4r loops when printing package type
+- #5172: camlp4 support for 'module type of' construct
+- #5175: in bigarray accesses, make sure bigarray expr is evaluated only once
+- #5177: Gc.compact implies Gc.full_major
+- #5182: use bytecode version of ocamldoc to generate man pages
+- #5184: under Windows, alignment issue with bigarrays mapped from files
+- #5188: double-free corruption in bytecode system threads
+- #5192: mismatch between words and bytes in interpreting max_young_wosize
+- #5202: error in documentation of atan2
+- #5209: natdynlink incorrectly detected on BSD systems
+- #5213: ocamlbuild should pass '-rectypes' to ocamldoc when needed
+- #5217: ocamlfind plugin should add '-linkpkg' for toplevel
+- #5228: document the exceptions raised by functions in 'Filename'
+- #5229: typo in build script ('TAG_LINE' vs 'TAGLINE')
+- #5230: error in documentation of Scanf.Scanning.open_in
+- #5234: option -shared reverses order of -cclib options
+- #5237: incorrect .size directives generated for x86-32 and x86-64
+- #5244: String.compare uses polymorphic compare_val (regression of #4194)
+- #5248: regression introduced while fixing #5118
+- #5252: typo in docs
+- #5258: win32unix: unix fd leak under windows
+- #5269: (tentative fix) Wrong ext_ref entries in .annot files
+- #5272: caml.el doesn't recognize downto as a keyword
+- #5276: issue with ocamlc -pack and recursively-packed modules
+- #5280: alignment constraints incorrectly autodetected on MIPS 32
+- #5281: typo in error message
+- #5308: unused variables not detected in "include (struct .. end)"
 - camlp4 revised syntax printing bug in the toplevel (reported on caml-list)
 - configure: do not define _WIN32 under cygwin
 - Hardened generic comparison in the case where two custom blocks
@@ -5111,11 +6058,11 @@ Bug fixes:
 - mismatch between declaration and definition of caml_major_collection_slice
 
 Feature wishes:
-- PR#4992: added '-ml-synonym' and '-mli-synonym' options to ocamldep
-- PR#5065: added '-ocamldoc' option to ocamlbuild
-- PR#5139: added possibility to add options to ocamlbuild
-- PR#5158: added access to current camlp4 parsers and printers
-- PR#5180: improved instruction selection for float operations on amd64
+- #4992: added '-ml-synonym' and '-mli-synonym' options to ocamldep
+- #5065: added '-ocamldoc' option to ocamlbuild
+- #5139: added possibility to add options to ocamlbuild
+- #5158: added access to current camlp4 parsers and printers
+- #5180: improved instruction selection for float operations on amd64
 - stdlib: added a 'usage_string' function to Arg
 - allow with constraints to add a type equation to a datatype definition
 - ocamldoc: allow to merge '@before' tags like other ones
@@ -5173,7 +6120,7 @@ Language features:
   inside the signature, removing their respective fields. Among other
   uses, this allows to merge two signatures containing identically
   named fields.
-* While fixing PR#4824, also corrected a gaping hole in the type checker,
+* While fixing #4824, also corrected a gaping hole in the type checker,
   which allowed instantiating separately object parameters and instance
   variables in an interface. This hole was here since the beginning of
   ocaml, and as a result many programs using object inheritance in a non
@@ -5210,7 +6157,7 @@ Native-code compiler:
 Standard library:
 - Format: new function ikfprintf analoguous to ifprintf with a continuation
   argument.
-* PR#4210, #4245: stricter range checking in string->integer conversion
+* #4210, #4245: stricter range checking in string->integer conversion
   functions (int_of_string, Int32.of_string, Int64.of_string,
   Nativeint.of_string).  The decimal string corresponding to
   max_int + 1 is no longer accepted.
@@ -5223,7 +6170,7 @@ Standard library:
 Other libraries:
 * Str: letters that constitute a word now include digits 0-9 and
   underscore _.  This changes the interpretation of '\b' (word boundary)
-  in regexps, but is more consistent with other regexp libraries. (PR#4874).
+  in regexps, but is more consistent with other regexp libraries. (#4874).
 
 Ocamlbuild:
 - Add support for native dynlink.
@@ -5235,25 +6182,25 @@ New tool:
   that was installed by some OCaml packages.
 
 All tools:
-- PR#4857: add a -vnum option to display the version number and nothing else
+- #4857: add a -vnum option to display the version number and nothing else
 
 Bug Fixes:
-- PR#4012: Map.map and Map.mapi do not conform to specification
-- PR#4478: better error messages for type definition mismatches
-- PR#4683: labltk script uses fixed path on windows
-- PR#4742: finalisation function raising an exception blocks other finalisations
-- PR#4775: compiler crash on crazy types (temporary fix)
-- PR#4824: narrowing the type of class parameters with a module specification
-- PR#4862: relaxed value restriction and records
-- PR#4884: optional arguments do not work when Some is redefined
-- PR#4964: parenthesized names for infix functions in annot files
-- PR#4970: better error message for instance variables
-- PR#4975: spelling mistakes
-- PR#4988: contravariance lost with ocamlc -i
-- PR#5004: problem in Buffer.add_channel with very large lengths.
-- PR#5008: on AMD64/MSVC port, rare float corruption during GC.
-- PR#5018: wrong exception raised by Dynlink.loadfile.
-- PR#5057: fatal typing error with local module + functor + polymorphic variant
+- #4012: Map.map and Map.mapi do not conform to specification
+- #4478: better error messages for type definition mismatches
+- #4683: labltk script uses fixed path on windows
+- #4742: finalisation function raising an exception blocks other finalisations
+- #4775: compiler crash on crazy types (temporary fix)
+- #4824: narrowing the type of class parameters with a module specification
+- #4862: relaxed value restriction and records
+- #4884: optional arguments do not work when Some is redefined
+- #4964: parenthesized names for infix functions in annot files
+- #4970: better error message for instance variables
+- #4975: spelling mistakes
+- #4988: contravariance lost with ocamlc -i
+- #5004: problem in Buffer.add_channel with very large lengths.
+- #5008: on AMD64/MSVC port, rare float corruption during GC.
+- #5018: wrong exception raised by Dynlink.loadfile.
+- #5057: fatal typing error with local module + functor + polymorphic variant
 - Wrong type for Obj.add_offset.
 - Small problem with representation of Int32, Int64, and Nativeint constants.
 - Use RTLD_LOCAL for native dynlink in private mode.
@@ -5262,93 +6209,93 @@ Objective Caml 3.11.2 (20 Jan 2010):
 ------------------------------------
 
 Bug fixes:
-- PR#4151: better documentation for min and max w.r.t. NaN
-- PR#4421: ocamlbuild uses wrong compiler for C files
-- PR#4710, PR#4720: ocamlbuild does not use properly configuration information
-- PR#4750: under some Windows installations, high start-up times for Unix lib
-- PR#4777: problem with scanf and CRLF
-- PR#4783: ocamlmklib problem under Windows
-- PR#4810: BSD problem with socket addresses, e.g. in Unix.getnameinfo
-- PR#4813: issue with parsing of float literals by the GNU assembler
-- PR#4816: problem with modules and private types
-- PR#4818: missed opportunity for type-based optimization of bigarray accesses
-- PR#4821: check for duplicate method names in classes
-- PR#4823: build problem on Mac OS X
-- PR#4836: spurious errors raised by Unix.single_write under Windows
-- PR#4841, PR#4860, PR#4930: problem with ocamlopt -output-obj under Mac OS X
-- PR#4847: C compiler error with ocamlc -output-obj under Win64
-- PR#4856: ocamlbuild uses ocamlrun to execute a native plugin
-- PR#4867, PR#4760: ocamlopt -shared fails on Mac OS X 64bit
-- PR#4873: ocamlbuild ignores "thread" tag when building a custom toplevel
-- PR#4890: ocamlbuild tries to use native plugin on bytecode-only arch
-- PR#4896: ocamlbuild should always pass -I to tools for external libraries
-- PR#4900: small bug triggering automatic compaction even if max_overhead = 1M
-- PR#4902: bug in %.0F printf format
-- PR#4910: problem with format concatenation
-- PR#4922: ocamlbuild recompiles too many files
-- PR#4923: missing \xff for scanf %S
-- PR#4933: functors not handling private types correctly
-- PR#4940: problem with end-of-line in DOS text mode, tentative fix
-- PR#4953: problem compiling bytecode interpreter on ARM in Thumb mode.
-- PR#4955: compiler crash when typing recursive type expression with constraint
+- #4151: better documentation for min and max w.r.t. NaN
+- #4421: ocamlbuild uses wrong compiler for C files
+- #4710, #4720: ocamlbuild does not use properly configuration information
+- #4750: under some Windows installations, high start-up times for Unix lib
+- #4777: problem with scanf and CRLF
+- #4783: ocamlmklib problem under Windows
+- #4810: BSD problem with socket addresses, e.g. in Unix.getnameinfo
+- #4813: issue with parsing of float literals by the GNU assembler
+- #4816: problem with modules and private types
+- #4818: missed opportunity for type-based optimization of bigarray accesses
+- #4821: check for duplicate method names in classes
+- #4823: build problem on Mac OS X
+- #4836: spurious errors raised by Unix.single_write under Windows
+- #4841, #4860, #4930: problem with ocamlopt -output-obj under Mac OS X
+- #4847: C compiler error with ocamlc -output-obj under Win64
+- #4856: ocamlbuild uses ocamlrun to execute a native plugin
+- #4867, #4760: ocamlopt -shared fails on Mac OS X 64bit
+- #4873: ocamlbuild ignores "thread" tag when building a custom toplevel
+- #4890: ocamlbuild tries to use native plugin on bytecode-only arch
+- #4896: ocamlbuild should always pass -I to tools for external libraries
+- #4900: small bug triggering automatic compaction even if max_overhead = 1M
+- #4902: bug in %.0F printf format
+- #4910: problem with format concatenation
+- #4922: ocamlbuild recompiles too many files
+- #4923: missing \xff for scanf %S
+- #4933: functors not handling private types correctly
+- #4940: problem with end-of-line in DOS text mode, tentative fix
+- #4953: problem compiling bytecode interpreter on ARM in Thumb mode.
+- #4955: compiler crash when typing recursive type expression with constraint
 - Module Printf: the simple conversion %F (without width indication) was not
            treated properly.
 - Makefile: problem with cygwin, flexdll, and symbolic links
 - Various build problems with ocamlbuild under Windows with msvc
 
 Feature wishes:
-- PR#9: (tentative implementation) make ocamldebug use #linenum annotations
-- PR#123, PR#4477: custom exception printers
-- PR#3456: Obj.double_field and Obj.set_double_field functions
-- PR#4003: destination directory can be given to Filename.[open_]temp_file
-- PR#4647: Buffer.blit function
-- PR#4685: access to Filename.dir_sep
-- PR#4703: support for debugging embedded applications
-- PR#4723: "clear_rules" function to empty the set of ocamlbuild rules
-- PR#4921: configure option to help cross-compilers
+- #2337: (tentative implementation) make ocamldebug use #linenum annotations
+- #2464, #4477: custom exception printers
+- #3456: Obj.double_field and Obj.set_double_field functions
+- #4003: destination directory can be given to Filename.[open_]temp_file
+- #4647: Buffer.blit function
+- #4685: access to Filename.dir_sep
+- #4703: support for debugging embedded applications
+- #4723: "clear_rules" function to empty the set of ocamlbuild rules
+- #4921: configure option to help cross-compilers
 
 Objective Caml 3.11.1 (12 Jun 2009):
 ------------------------------------
 
 Bug fixes:
-- PR#4095: ocamldebug: strange behaviour of control-C
-- PR#4403: ocamldebug: improved handling of packed modules
-- PR#4650: Str.regexp_case_fold mis-handling complemented character sets [^a]
-- PR#4660: Scanf.format_from_string: handling of double quote
-- PR#4666: Unix.exec* failure in multithread programs under MacOS X and FreeBSD
-- PR#4667: debugger out of sync with dynlink changes
-- PR#4678: random "out of memory" error with systhreads
-- PR#4690: issue with dynamic loading under MacOS 10.5
-- PR#4692: wrong error message with options -i and -pack passed to ocamlc
-- PR#4699: in otherlibs/dbm, fixed construction of dlldbm.so.
-- PR#4704: error in caml_modify_generational_global_root()
-- PR#4708: (ocamldoc) improved printing of infix identifiers such as "lor".
-- PR#4722: typo in configure script
-- PR#4729: documented the fact that PF_INET6 is not available on all platforms
-- PR#4730: incorrect typing involving abbreviation "type 'a t = 'a"
-- PR#4731: incorrect quoting of arguments passed to the assembler on x86-64
-- PR#4735: Unix.LargeFile.fstat cannot report size over 32bits on Win32
-- PR#4740: guard against possible processor error in
+- #4095: ocamldebug: strange behaviour of control-C
+- #4403: ocamldebug: improved handling of packed modules
+- #4650: Str.regexp_case_fold mis-handling complemented character sets [^a]
+- #4660: Scanf.format_from_string: handling of double quote
+- #4666: Unix.exec* failure in multithread programs under MacOS X and FreeBSD
+- #4667: debugger out of sync with dynlink changes
+- #4678: random "out of memory" error with systhreads
+- #4690: issue with dynamic loading under MacOS 10.5
+- #4692: wrong error message with options -i and -pack passed to ocamlc
+- #4699: in otherlibs/dbm, fixed construction of dlldbm.so.
+- #4704: error in caml_modify_generational_global_root()
+- #4708: (ocamldoc) improved printing of infix identifiers such as "lor".
+- #4722: typo in configure script
+- #4729: documented the fact that PF_INET6 is not available on all platforms
+- #4730: incorrect typing involving abbreviation "type 'a t = 'a"
+- #4731: incorrect quoting of arguments passed to the assembler on x86-64
+- #4735: Unix.LargeFile.fstat cannot report size over 32bits on Win32
+- #4740: guard against possible processor error in
            {Int32,Int64,Nativeint}.{div,rem}
-- PR#4745: type inference wrongly produced non-generalizable type variables.
-- PR#4749: better pipe size for win32unix
-- PR#4756: printf: no error reported for wrong format '%_s'
-- PR#4758: scanf: handling of \ by format '%S'
-- PR#4766: incorrect simplification of some type abbreviations.
-- PR#4768: printf: %F does not respect width and precision specifications
-- PR#4769: Format.bprintf fails to flush
-- PR#4775: fatal error Ctype.Unify during module type-checking (temporary fix)
-- PR#4776: bad interaction between exceptions and classes
-- PR#4780: labltk build problem under Windows.
-- PR#4790: under Windows, map ERROR_NO_DATA Win32 error to EPIPE Unix error.
-- PR#4792: bug in Big_int.big_int_of_int64 on 32-bit platforms.
-- PR#4796: ocamlyacc: missing NUL termination of string
-- PR#4804: bug in Big_int.int64_of_big_int on 32-bit platforms.
-- PR#4805: improving compatibility with the clang C compiler
-- PR#4809: issue with Unix.create_process under Win32
-- PR#4814: ocamlbrowser: crash when editing comments
-- PR#4816: module abbreviations remove 'private' type restrictions
-- PR#4817: Object type gives error "Unbound type parameter .."
+- #4745: type inference wrongly produced non-generalizable type variables.
+- #4749: better pipe size for win32unix
+- #4756: printf: no error reported for wrong format '%_s'
+- #4758: scanf: handling of \ by format '%S'
+- #4766: incorrect simplification of some type abbreviations.
+- #4768: printf: %F does not respect width and precision specifications
+- #4769: Format.bprintf fails to flush
+- #4775: fatal error Ctype.Unify during module type-checking (temporary fix)
+- #4776: bad interaction between exceptions and classes
+- #4780: labltk build problem under Windows.
+- #4790: under Windows, map ERROR_NO_DATA Win32 error to EPIPE Unix error.
+- #4792: bug in Big_int.big_int_of_int64 on 32-bit platforms.
+- #4796: ocamlyacc: missing NUL termination of string
+- #4804: bug in Big_int.int64_of_big_int on 32-bit platforms.
+- #4805: improving compatibility with the clang C compiler
+- #4809: issue with Unix.create_process under Win32
+- #4814: ocamlbrowser: crash when editing comments
+- #4816: module abbreviations remove 'private' type restrictions
+- #4817: Object type gives error "Unbound type parameter .."
 - Module Parsing: improved computation of locations when an ocamlyacc rule
                   starts with an empty nonterminal
 - Type-checker: fixed wrong variance computation for private types
@@ -5360,7 +6307,7 @@ Bug fixes:
 Other changes:
 - Improved wording of various error messages
   (contributed by Jonathan Davies, Citrix).
-- Support for 64-bit mode in Solaris/x86 (PR#4670).
+- Support for 64-bit mode in Solaris/x86 (#4670).
 
 
 Objective Caml 3.11.0 (03 Dec 2008):
@@ -5412,7 +6359,7 @@ Native-code compiler:
 Run-time system:
 - New implementation of the page table describing the heap (two-level
   array in 32 bits, sparse hashtable in 64 bits), fixes issues with address
-  space randomization on 64-bit OS (PR#4448).
+  space randomization on 64-bit OS (#4448).
 - New "generational" API for registering global memory roots with the GC,
   enables faster scanning of global roots.
   (The functions are caml_*_generational_global_root in .)
@@ -5448,11 +6395,11 @@ Other libraries:
 - Num: added conversions between big_int and int32, nativeint, int64.
   More efficient implementation of Num.quo_num and Num.mod_num.
 - Threads: improved efficiency of mutex and condition variable operations;
-  improved interaction with Unix.fork (PR#4577).
+  improved interaction with Unix.fork (#4577).
 - Unix: added getsockopt_error returning type Unix.error.
   Added support for TCP_NODELAY and IPV6_ONLY socket options.
 - Win32 Unix: "select" now supports all kinds of file descriptors.
-  Improved emulation of "lockf" (PR#4609).
+  Improved emulation of "lockf" (#4609).
 
 Tools:
 - ocamldebug now supported under Windows (MSVC and Mingw ports),
@@ -5470,42 +6417,42 @@ Camlp4:
 Bug fixes:
 - Major GC and heap compaction: fixed bug involving lazy values and
   out-of-heap pointers.
-- PR#3915: updated most man pages.
-- PR#4261: type-checking of recursive modules
-- PR#4308: better stack backtraces for "spontaneous" exceptions such as
+- #3915: updated most man pages.
+- #4261: type-checking of recursive modules
+- #4308: better stack backtraces for "spontaneous" exceptions such as
   Stack_overflow, Out_of_memory, etc.
-- PR#4338: Str.global_substitute, Str.global_replace and the Str.*split*
+- #4338: Str.global_substitute, Str.global_replace and the Str.*split*
   functions are now tail-recursive.
-- PR#4503: fixed bug in classify_float on ARM.
-- PR#4512: type-checking of recursive modules
-- PR#4517: crash in ocamllex-generated lexers.
-- PR#4542: problem with return value of Unix.nice.
-- PR#4557: type-checking of recursive modules.
-- PR#4562: strange %n semantics in scanf.
-- PR#4564: add note "stack is not executable" to object files generated by
+- #4503: fixed bug in classify_float on ARM.
+- #4512: type-checking of recursive modules
+- #4517: crash in ocamllex-generated lexers.
+- #4542: problem with return value of Unix.nice.
+- #4557: type-checking of recursive modules.
+- #4562: strange %n semantics in scanf.
+- #4564: add note "stack is not executable" to object files generated by
   ocamlopt (Linux/x86, Linux/AMD64).
-- PR#4566: bug in Ratio.approx_ratio_fix and Num.approx_num_fix.
-- PR#4582: clarified the documentation of functions in the String module.
-- PR#4583: stack overflow in "ocamlopt -g" during closure conversion pass.
-- PR#4585: ocamldoc and "val virtual" declarations.
-- PR#4587: ocamldoc and escaped @ characters.
-- PR#4605: Buffer.add_substitute was sometime wrong when target string had
+- #4566: bug in Ratio.approx_ratio_fix and Num.approx_num_fix.
+- #4582: clarified the documentation of functions in the String module.
+- #4583: stack overflow in "ocamlopt -g" during closure conversion pass.
+- #4585: ocamldoc and "val virtual" declarations.
+- #4587: ocamldoc and escaped @ characters.
+- #4605: Buffer.add_substitute was sometime wrong when target string had
            backslashes.
-- PR#4614: Inconsistent declaration of CamlCBCmd in LablTk library.
+- #4614: Inconsistent declaration of CamlCBCmd in LablTk library.
 
 
 Objective Caml 3.10.2 (29 Feb 2008):
 ------------------------------------
 
 Bug fixes:
-- PR#1217 (partial) Typo in ocamldep man page
-- PR#3952 (partial) ocamlopt: allocation problems on ARM
-- PR#4339 (continued) ocamlopt: problems on HPPA
-- PR#4455 str.mli not installed under Windows
-- PR#4473 crash when accessing float array with polymorphic method
-- PR#4480 runtime would not compile without gcc extensions
-- PR#4481 wrong typing of exceptions with object arguments
-- PR#4490 typo in error message
+- #3410 (partial) Typo in ocamldep man page
+- #3952 (partial) ocamlopt: allocation problems on ARM
+- #4339 (continued) ocamlopt: problems on HPPA
+- #4455 str.mli not installed under Windows
+- #4473 crash when accessing float array with polymorphic method
+- #4480 runtime would not compile without gcc extensions
+- #4481 wrong typing of exceptions with object arguments
+- #4490 typo in error message
 - Random crash on 32-bit when major_heap_increment >= 2^22
 - Big performance bug in Weak hashtables
 - Small bugs in the make-package-macosx script
@@ -5516,78 +6463,78 @@ Objective Caml 3.10.1 (11 Jan 2008):
 ------------------------------------
 
 Bug fixes:
-- PR#3830 small bugs in docs
-- PR#4053 compilers: improved compilation time for large variant types
-- PR#4174 ocamlopt: fixed ocamlopt -nopervasives
-- PR#4199 otherlibs: documented a small problem in Unix.utimes
-- PR#4280 camlp4: parsing of identifier (^)
-- PR#4281 camlp4: parsing of type constraint
-- PR#4285 runtime: cannot compile under AIX
-- PR#4286 ocamlbuild: cannot compile under AIX and SunOS
-- PR#4288 compilers: including a functor application with side effects
-- PR#4295 camlp4 toplevel: synchronization after an error
-- PR#4300 ocamlopt: crash with backtrace and illegal array access
-- PR#4302 camlp4: list comprehension parsing problem
-- PR#4304 ocamlbuild: handle -I correctly
-- PR#4305 stdlib: alignment of Arg.Symbol
-- PR#4307 camlp4: assertion failure
-- PR#4312 camlp4: accept "let _ : int = 1"
-- PR#4313 ocamlbuild: -log and missing directories
-- PR#4315 camlp4: constraints in classes
-- PR#4316 compilers: crash with recursive modules and Lazy
-- PR#4318 ocamldoc: installation problem with Cygwin (tentative fix)
-- PR#4322 ocamlopt: stack overflow under Windows
-- PR#4325 compilers: wrong error message for unused var
-- PR#4326 otherlibs: marshal Big_int on win64
-- PR#4327 ocamlbuild: make emacs look for .annot in _build directory
-- PR#4328 camlp4: stack overflow with nil nodes
-- PR#4331 camlp4: guards on fun expressions
-- PR#4332 camlp4: parsing of negative 32/64 bit numbers
-- PR#4336 compilers: unsafe recursive modules
-- PR#4337 (note) camlp4: invalid character escapes
-- PR#4339 ocamlopt: problems on HP-UX (tentative fix)
-- PR#4340 camlp4: wrong pretty-printing of optional arguments
-- PR#4348 ocamlopt: crash on Mac Intel
-- PR#4349 camlp4: bug in private type definitions
-- PR#4350 compilers: type errors with records and polymorphic variants
-- PR#4352 compilers: terminal recursion under Windows (tentative fix)
-- PR#4354 ocamlcp: mismatch with ocaml on polymorphic let
-- PR#4358 ocamlopt: float constants wrong on ARM
-- PR#4360 ocamldoc: string inside comment
-- PR#4365 toplevel: wrong pretty-printing of polymorphic variants
-- PR#4373 otherlibs: leaks in win32unix
-- PR#4374 otherlibs: threads module not initialized
-- PR#4375 configure: fails to build on bytecode-only architectures
-- PR#4377 runtime: finalisation of infix pointers
-- PR#4378 ocamlbuild: typo in plugin.ml
-- PR#4379 ocamlbuild: problem with plugins under Windows
-- PR#4382 compilers: typing of polymorphic record fields
-- PR#4383 compilers: including module with private type
-- PR#4385 stdlib: Int32/Int64.format are unsafe
-- PR#4386 otherlibs: wrong signal numbers with Unix.sigprocmask etc.
-- PR#4387 ocamlbuild: build directory not used properly
-- PR#4392 ocamldep: optional argument of class
-- PR#4394 otherlibs: infinite loops in Str
-- PR#4397 otherlibs: wrong size for flag arrays in win32unix
-- PR#4402 ocamldebug: doesn't work with -rectypes
-- PR#4410 ocamlbuild: problem with plugin and -build
-- PR#4411 otherlibs: crash with Unix.access under Windows
-- PR#4412 stdlib: marshalling broken on 64 bit architectures
-- PR#4413 ocamlopt: crash on AMD64 with out-of-bound access and reraise
-- PR#4417 camlp4: pretty-printing of unary minus
-- PR#4419 camlp4: problem with constraint in type class
-- PR#4426 compilers: problem with optional labels
-- PR#4427 camlp4: wrong pretty-printing of lists of functions
-- PR#4433 ocamlopt: fails to build on MacOSX 10.5
-- PR#4435 compilers: crash with objects
-- PR#4439 fails to build on MacOSX 10.5
-- PR#4441 crash when build on sparc64 linux
-- PR#4442 stdlib: crash with weak pointers
-- PR#4446 configure: fails to detect X11 on MacOSX 10.5
-- PR#4448 runtime: huge page table on 64-bit architectures
-- PR#4450 compilers: stack overflow with recursive modules
-- PR#4470 compilers: type-checking of recursive modules too restrictive
-- PR#4472 configure: autodetection of libX11.so on Fedora x86_64
+- #3830 small bugs in docs
+- #4053 compilers: improved compilation time for large variant types
+- #4174 ocamlopt: fixed ocamlopt -nopervasives
+- #4199 otherlibs: documented a small problem in Unix.utimes
+- #4280 camlp4: parsing of identifier (^)
+- #4281 camlp4: parsing of type constraint
+- #4285 runtime: cannot compile under AIX
+- #4286 ocamlbuild: cannot compile under AIX and SunOS
+- #4288 compilers: including a functor application with side effects
+- #4295 camlp4 toplevel: synchronization after an error
+- #4300 ocamlopt: crash with backtrace and illegal array access
+- #4302 camlp4: list comprehension parsing problem
+- #4304 ocamlbuild: handle -I correctly
+- #4305 stdlib: alignment of Arg.Symbol
+- #4307 camlp4: assertion failure
+- #4312 camlp4: accept "let _ : int = 1"
+- #4313 ocamlbuild: -log and missing directories
+- #4315 camlp4: constraints in classes
+- #4316 compilers: crash with recursive modules and Lazy
+- #4318 ocamldoc: installation problem with Cygwin (tentative fix)
+- #4322 ocamlopt: stack overflow under Windows
+- #4325 compilers: wrong error message for unused var
+- #4326 otherlibs: marshal Big_int on win64
+- #4327 ocamlbuild: make emacs look for .annot in _build directory
+- #4328 camlp4: stack overflow with nil nodes
+- #4331 camlp4: guards on fun expressions
+- #4332 camlp4: parsing of negative 32/64 bit numbers
+- #4336 compilers: unsafe recursive modules
+- #4337 (note) camlp4: invalid character escapes
+- #4339 ocamlopt: problems on HP-UX (tentative fix)
+- #4340 camlp4: wrong pretty-printing of optional arguments
+- #4348 ocamlopt: crash on Mac Intel
+- #4349 camlp4: bug in private type definitions
+- #4350 compilers: type errors with records and polymorphic variants
+- #4352 compilers: terminal recursion under Windows (tentative fix)
+- #4354 ocamlcp: mismatch with ocaml on polymorphic let
+- #4358 ocamlopt: float constants wrong on ARM
+- #4360 ocamldoc: string inside comment
+- #4365 toplevel: wrong pretty-printing of polymorphic variants
+- #4373 otherlibs: leaks in win32unix
+- #4374 otherlibs: threads module not initialized
+- #4375 configure: fails to build on bytecode-only architectures
+- #4377 runtime: finalisation of infix pointers
+- #4378 ocamlbuild: typo in plugin.ml
+- #4379 ocamlbuild: problem with plugins under Windows
+- #4382 compilers: typing of polymorphic record fields
+- #4383 compilers: including module with private type
+- #4385 stdlib: Int32/Int64.format are unsafe
+- #4386 otherlibs: wrong signal numbers with Unix.sigprocmask etc.
+- #4387 ocamlbuild: build directory not used properly
+- #4392 ocamldep: optional argument of class
+- #4394 otherlibs: infinite loops in Str
+- #4397 otherlibs: wrong size for flag arrays in win32unix
+- #4402 ocamldebug: doesn't work with -rectypes
+- #4410 ocamlbuild: problem with plugin and -build
+- #4411 otherlibs: crash with Unix.access under Windows
+- #4412 stdlib: marshalling broken on 64 bit architectures
+- #4413 ocamlopt: crash on AMD64 with out-of-bound access and reraise
+- #4417 camlp4: pretty-printing of unary minus
+- #4419 camlp4: problem with constraint in type class
+- #4426 compilers: problem with optional labels
+- #4427 camlp4: wrong pretty-printing of lists of functions
+- #4433 ocamlopt: fails to build on MacOSX 10.5
+- #4435 compilers: crash with objects
+- #4439 fails to build on MacOSX 10.5
+- #4441 crash when build on sparc64 linux
+- #4442 stdlib: crash with weak pointers
+- #4446 configure: fails to detect X11 on MacOSX 10.5
+- #4448 runtime: huge page table on 64-bit architectures
+- #4450 compilers: stack overflow with recursive modules
+- #4470 compilers: type-checking of recursive modules too restrictive
+- #4472 configure: autodetection of libX11.so on Fedora x86_64
 - printf: removed (partially implemented) positional specifications
 - polymorphic < and <= comparisons: some C compiler optimizations
   were causing incorrect results when arguments are incomparable
@@ -5633,8 +6580,8 @@ Native-code compiler:
 - Stack overflow detection on MS Windows 32 bits (courtesy O. Andrieu).
 - Stack overflow detection on MacOS X PPC and Intel.
 - Intel/AMD 64 bits: generate position-independent code by default.
-- Fixed bug involving -for-pack and missing .cmx files (PR#4124).
-- Fixed bug causing duplication of literals  (PR#4152).
+- Fixed bug involving -for-pack and missing .cmx files (#4124).
+- Fixed bug causing duplication of literals  (#4152).
 
 Run-time system:
 - C/Caml interface functions take "char const *" arguments
@@ -5647,13 +6594,13 @@ Standard library:
     and prints nothing (useful to print conditionally).
 - Scanf:
     new function format_from_string to convert a string to a format string;
-    new %r conversion to accomodate user defined scanners.
+    new %r conversion to accommodate user defined scanners.
 - Filename: improved Win32 implementation of Filename.quote.
 - List: List.nth now tail-recursive.
 - Sys: added Sys.is_directory.  Some functions (e.g. Sys.command) that
     could incorrectly raise Sys_io_blocked now raise Sys_error as intended.
 - String and Char: the function ``escaped'' now escapes all the characters
-    especially handled by the compiler's lexer (PR#4220).
+    especially handled by the compiler's lexer (#4220).
 
 Other libraries:
 - Bigarray: mmap_file takes an optional argument specifying
@@ -5664,12 +6611,12 @@ Other libraries:
 - VM threads: improved performance of I/O operations (less polling).
 - Unix: new function Unix.isatty.
 - Unix emulation under Win32:
-    fixed incorrect error reporting in several functions (PR#4097);
-    better handling of channels opened on sockets (PR#4098);
-    fixed GC bug in Unix.system (PR#4112).
+    fixed incorrect error reporting in several functions (#4097);
+    better handling of channels opened on sockets (#4098);
+    fixed GC bug in Unix.system (#4112).
 
 Documentation generator (OCamldoc):
-- correctly handle '?' in value names (PR#4215)
+- correctly handle '?' in value names (#4215)
 - new option -hide-warnings not to print ocamldoc warnings
 
 Lexer generator (ocamllex): improved error reporting.
@@ -5682,33 +6629,33 @@ Objective Caml 3.09.3 (15 Sep 2006):
 
 Bug fixes:
 - ocamldoc: -using modtype constraint to filter module elements displayed
-    in doc PR#4016
-- ocamldoc: error in merging of top dependencies of modules PR#4007
-- ocamldoc: -dot-colors has no effect PR#3981
-- ocamdloc: missing crossref in text from intro files PR#4066
-- compilers: segfault with recursive modules PR#4008
-- compilers: infinite loop when compiling objects PR#4018
-- compilers: bad error message when signature mismatch PR#4001
-- compilers: infinite loop with -rectypes PR#3999
+    in doc #4016
+- ocamldoc: error in merging of top dependencies of modules #4007
+- ocamldoc: -dot-colors has no effect #3981
+- ocamdloc: missing crossref in text from intro files #4066
+- compilers: segfault with recursive modules #4008
+- compilers: infinite loop when compiling objects #4018
+- compilers: bad error message when signature mismatch #4001
+- compilers: infinite loop with -rectypes #3999
 - compilers: contravariance bug in private rows
-- compilers: unsafe cast with polymorphic exception PR#4002
-- native compiler: bad assembly code generated for AMD64 PR#4067
-- native compiler: stack alignment problems on MacOSX/i386 PR#4036
-- stdlib: crash in marshalling PR#4030
-- stdlib: crash when closing a channel twice PR#4039
-- stdlib: memory leak in Sys.readdir PR#4093
-- C interface: better definition of CAMLreturn PR#4068
-- otherlibs/unix: crash in gethostbyname PR#3043
-- tools: subtle problem with unset in makefile PR#4048
-- camlp4: install pa_o_fast.o PR#3812
-- camlp4: install more modules PR#3689
+- compilers: unsafe cast with polymorphic exception #4002
+- native compiler: bad assembly code generated for AMD64 #4067
+- native compiler: stack alignment problems on MacOSX/i386 #4036
+- stdlib: crash in marshalling #4030
+- stdlib: crash when closing a channel twice #4039
+- stdlib: memory leak in Sys.readdir #4093
+- C interface: better definition of CAMLreturn #4068
+- otherlibs/unix: crash in gethostbyname #3043
+- tools: subtle problem with unset in makefile #4048
+- camlp4: install pa_o_fast.o #3812
+- camlp4: install more modules #3689
 
 New features:
 - ocamldoc: name resolution in cross-referencing {!name}: if name is not
     found, then it is searched in the parent module/class, and in the parent
     of the parent, and so on until it is found.
 - ocamldoc: new option -short-functors to use a short form to display
-    functors in html generator PR#4017
+    functors in html generator #4017
 - ocamlprof: added "-version" option
 
 
@@ -5717,64 +6664,64 @@ Objective Caml 3.09.2 (14 Apr 2006):
 ------------------------------------
 
 Bug fixes:
-- Makefile: problem with "make world.opt" PR#3954
-- compilers: problem compiling several modules with one command line PR#3979
+- Makefile: problem with "make world.opt" #3954
+- compilers: problem compiling several modules with one command line #3979
 - compilers,ocamldoc: error message that Emacs cannot parse
-- compilers: crash when printing type error PR#3968
-- compilers: -dtypes wrong for monomorphic type variables PR#3894
-- compilers: wrong warning on optional arguments PR#3980
-- compilers: crash when wrong use of type constructor in let rec PR#3976
-- compilers: better wording of "statement never returns" warning PR#3889
-- runtime: inefficiency of signal handling PR#3990
-- runtime: crashes with I/O in multithread programs PR#3906
-- camlp4: empty file name in error messages PR#3886
-- camlp4: stack overflow PR#3948
-- otherlibs/labltk: ocamlbrowser ignores its command line options PR#3961
-- otherlibs/unix: Unix.times wrong under Mac OS X PR#3960
-- otherlibs/unix: wrong doc for execvp and execvpe PR#3973
-- otherlibs/win32unix: random crash in Unix.stat PR#3998
-- stdlib: update_mod not found under Windows PR#3847
-- stdlib: Filename.dirname/basename wrong on Win32 PR#3933
-- stdlib: incomplete documentation of Pervasives.abs PR#3967
-- stdlib: Printf bugs PR#3902, PR#3955
+- compilers: crash when printing type error #3968
+- compilers: -dtypes wrong for monomorphic type variables #3894
+- compilers: wrong warning on optional arguments #3980
+- compilers: crash when wrong use of type constructor in let rec #3976
+- compilers: better wording of "statement never returns" warning #3889
+- runtime: inefficiency of signal handling #3990
+- runtime: crashes with I/O in multithread programs #3906
+- camlp4: empty file name in error messages #3886
+- camlp4: stack overflow #3948
+- otherlibs/labltk: ocamlbrowser ignores its command line options #3961
+- otherlibs/unix: Unix.times wrong under Mac OS X #3960
+- otherlibs/unix: wrong doc for execvp and execvpe #3973
+- otherlibs/win32unix: random crash in Unix.stat #3998
+- stdlib: update_mod not found under Windows #3847
+- stdlib: Filename.dirname/basename wrong on Win32 #3933
+- stdlib: incomplete documentation of Pervasives.abs #3967
+- stdlib: Printf bugs #3902, #3955
 - tools/checkstack.c: missing include
-- yacc: crash when given argument "-" PR#3956
+- yacc: crash when given argument "-" #3956
 
 New features:
-- ported to MacOS X on Intel PR#3985
-- configure: added support for GNU Hurd PR#3991
+- ported to MacOS X on Intel #3985
+- configure: added support for GNU Hurd #3991
 
 Objective Caml 3.09.1 (4 Jan 2006):
 -----------------------------------
 
 Bug fixes:
-- compilers: raise not_found with -principal PR#3855
-- compilers: assert failure in typeclass.cml PR#3856
-- compilers: assert failure in typing/ctype.ml PR#3909
-- compilers: fatal error exception Ctype.Unify PR#3918
-- compilers: spurious warning Y in objects PR#3868
-- compilers: spurious warning Z on loop index PR#3907
+- compilers: raise not_found with -principal #3855
+- compilers: assert failure in typeclass.cml #3856
+- compilers: assert failure in typing/ctype.ml #3909
+- compilers: fatal error exception Ctype.Unify #3918
+- compilers: spurious warning Y in objects #3868
+- compilers: spurious warning Z on loop index #3907
 - compilers: error message that emacs cannot parse
-- ocamlopt: problems with -for-pack/-pack PR#3825, PR#3826, PR#3919
-- ocamlopt: can't produce shared libraries on x86_64 PR#3869, PR#3924
-- ocamlopt: float alignment problem on SPARC PR#3944
-- ocamlopt: can't compile on MIPS PR#3936
+- ocamlopt: problems with -for-pack/-pack #3825, #3826, #3919
+- ocamlopt: can't produce shared libraries on x86_64 #3869, #3924
+- ocamlopt: float alignment problem on SPARC #3944
+- ocamlopt: can't compile on MIPS #3936
 - runtime: missing dependence for ld.conf
-- runtime: missing dependence for .depend.nt PR#3880
-- runtime: memory leak in caml_register_named_value PR#3940
-- runtime: crash in Marshal.to_buffer PR#3879
-- stdlib: Sys.time giving wrong results on Mac OS X PR#3850
+- runtime: missing dependence for .depend.nt #3880
+- runtime: memory leak in caml_register_named_value #3940
+- runtime: crash in Marshal.to_buffer #3879
+- stdlib: Sys.time giving wrong results on Mac OS X #3850
 - stdlib: Weak.get_copy causing random crashes in rare cases
-- stdlib, debugger, labltk: use TMPDIR if set PR#3895
-- stdlib: scanf bug on int32 and nativeint PR#3932
-- camlp4: mkcamlp4 option parsing problem PR#3941
+- stdlib, debugger, labltk: use TMPDIR if set #3895
+- stdlib: scanf bug on int32 and nativeint #3932
+- camlp4: mkcamlp4 option parsing problem #3941
 - camlp4: bug in pretty-printing of lazy/assert/new
 - camlp4: update the unmaintained makefile for _loc name
 - ocamldoc: several fixes see ocamldoc/Changes.txt
-- otherlibs/str: bug in long sequences of alternatives PR#3783
-- otherlibs/systhreads: deadlock in Windows PR#3910
-- tools: update dumpobj to handle new event format PR#3873
-- toplevel: activate warning Y in toplevel PR#3832
+- otherlibs/str: bug in long sequences of alternatives #3783
+- otherlibs/systhreads: deadlock in Windows #3910
+- tools: update dumpobj to handle new event format #3873
+- toplevel: activate warning Y in toplevel #3832
 
 New features:
 - otherlibs/labltk: browser uses menu bars instead of menu buttons
@@ -5799,7 +6746,7 @@ Both compilers:
   never used.
 - Added warning for some uses non-returning functions (e.g. raise), when they
   are passed extra arguments, or followed by extra statements.
-- Pattern matching: more prudent compilation in case of guards; fixed PR#3780.
+- Pattern matching: more prudent compilation in case of guards; fixed #3780.
 - Compilation of classes: reduction in size of generated code.
 - Compilation of "module rec" definitions: fixed a bad interaction with
   structure coercion (to a more restrictive signature).
@@ -5859,44 +6806,44 @@ Objective Caml 3.08.4 (11 Aug 2005):
 
 New features:
 - configure: find X11 config in some 64-bit Linux distribs
-- ocamldoc: (**/**) can be canceled with another (**/**) PR#3665
+- ocamldoc: (**/**) can be canceled with another (**/**) #3665
 - graphics: added resize_window
-- graphics: check for invalid arguments to drawing primitives PR#3595
+- graphics: check for invalid arguments to drawing primitives #3595
 - ocamlbrowser: use windows subsystem on mingw
 
 Bug fixes:
-- ocamlopt: code generation problem on AMD64 PR#3640
-- wrong code generated for some classes PR#3576
-- fatal error when compiling some OO code PR#3745
-- problem with comparison on constant constructors PR#3608
-- camlp4: cryptic error message PR#3592
-- camlp4: line numbers in multi-line antiquotations PR#3549
+- ocamlopt: code generation problem on AMD64 #3640
+- wrong code generated for some classes #3576
+- fatal error when compiling some OO code #3745
+- problem with comparison on constant constructors #3608
+- camlp4: cryptic error message #3592
+- camlp4: line numbers in multi-line antiquotations #3549
 - camlp4: problem with make depend
-- camlp4: parse error with :> PR#3561
+- camlp4: parse error with :> #3561
 - camlp4: ident conversion problem with val/contents/contents__
-- camlp4: several small parsing problems PR#3688
-- ocamldebug: handling of spaces in executable file name PR#3736
-- emacs-mode: problem when caml-types-buffer is deleted by user PR#3704
-- ocamldoc: extra backslash in ocamldoc man page PR#3687
-- ocamldoc: improvements to HTML display PR#3698
+- camlp4: several small parsing problems #3688
+- ocamldebug: handling of spaces in executable file name #3736
+- emacs-mode: problem when caml-types-buffer is deleted by user #3704
+- ocamldoc: extra backslash in ocamldoc man page #3687
+- ocamldoc: improvements to HTML display #3698
 - ocamldoc: escaping of @ in info files
-- ocamldoc: escaping of . and \ in man pages PR#3686
+- ocamldoc: escaping of . and \ in man pages #3686
 - ocamldoc: better error reporting of misplaced comments
-- graphics: fixed .depend file PR#3558
-- graphics: segfault with threads and graphics PR#3651
-- nums: several bugs: PR#3718, PR#3719, others
-- nums: inline asm problems with gcc 4.0 PR#3604, PR#3637
+- graphics: fixed .depend file #3558
+- graphics: segfault with threads and graphics #3651
+- nums: several bugs: #3718, #3719, others
+- nums: inline asm problems with gcc 4.0 #3604, #3637
 - threads: problem with backtrace
-- unix: problem with getaddrinfo PR#3565
-- stdlib: documentation of Int32.rem and Int64.rem PR#3573
-- stdlib: documentation of List.rev_map2 PR#3685
-- stdlib: wrong order in Map.fold PR#3607
-- stdlib: documentation of maximum float array length PR#3714
+- unix: problem with getaddrinfo #3565
+- stdlib: documentation of Int32.rem and Int64.rem #3573
+- stdlib: documentation of List.rev_map2 #3685
+- stdlib: wrong order in Map.fold #3607
+- stdlib: documentation of maximum float array length #3714
 - better detection of cycles when using -rectypes
-- missing case of module equality PR#3738
+- missing case of module equality #3738
 - better error messages for unbound type variables
-- stack overflow while printing type error message PR#3705
-- assert failure when typing some classes PR#3638
+- stack overflow while printing type error message #3705
+- assert failure when typing some classes #3638
 - bug in type_approx
 - better error messages related to type variance checking
 - yacc: avoid name capture for idents of the Parsing module
@@ -5906,12 +6853,12 @@ Objective Caml 3.08.3 (24 Mar 2005):
 ------------------------------------
 
 New features:
-- support for ocamlopt -pack under Mac OS X (PR#2634, PR#3320)
+- support for ocamlopt -pack under Mac OS X (#2634, #3320)
 - ignore unknown warning options for forward and backward compatibility
-- runtime: export caml_compare_unordered (PR#3479)
-- camlp4: install argl.* files (PR#3439)
+- runtime: export caml_compare_unordered (#3479)
+- camlp4: install argl.* files (#3439)
 - ocamldoc: add -man-section option
-- labltk: add the "solid" relief option (PR#3343)
+- labltk: add the "solid" relief option (#3343)
 
 Bug fixes:
 - typing: fix unsoundness in type declaration variance inference.
@@ -5919,53 +6866,53 @@ Bug fixes:
     annotation, otherwise they are invariant. This is not backward
     compatible, so this might break code which either uses subtyping or
     uses the relaxed value restriction (i.e. was not typable before 3.07)
-- typing: erroneous partial match warning for polymorphic variants (PR#3424)
-- runtime: handle the case of an empty command line (PR#3409, PR#3444)
-- stdlib: make Sys.executable_name an absolute path in native code (PR#3303)
+- typing: erroneous partial match warning for polymorphic variants (#3424)
+- runtime: handle the case of an empty command line (#3409, #3444)
+- stdlib: make Sys.executable_name an absolute path in native code (#3303)
 - runtime: fix memory leak in finalise.c
-- runtime: auto-trigger compaction even if gc is called manually (PR#3392)
-- stdlib: fix segfault in Obj.dup on zero-sized values (PR#3406)
-- camlp4: correct parsing of the $ identifier (PR#3310, PR#3469)
-- windows (MS tools): use link /lib instead of lib (PR#3333)
+- runtime: auto-trigger compaction even if gc is called manually (#3392)
+- stdlib: fix segfault in Obj.dup on zero-sized values (#3406)
+- camlp4: correct parsing of the $ identifier (#3310, #3469)
+- windows (MS tools): use link /lib instead of lib (#3333)
 - windows (MS tools): change default install destination
-- autoconf: better checking of SSE2 instructions (PR#3329, PR#3330)
-- graphics: make close_graph close the X display as well as the window (PR#3312)
-- num: fix big_int_of_string (empty string) (PR#3483)
-- num: fix big bug on 64-bit architecture (PR#3299)
-- str: better documentation of string_match and string_partial_match (PR#3395)
-- unix: fix file descriptor leak in Unix.accept (PR#3423)
+- autoconf: better checking of SSE2 instructions (#3329, #3330)
+- graphics: make close_graph close the X display as well as the window (#3312)
+- num: fix big_int_of_string (empty string) (#3483)
+- num: fix big bug on 64-bit architecture (#3299)
+- str: better documentation of string_match and string_partial_match (#3395)
+- unix: fix file descriptor leak in Unix.accept (#3423)
 - unix: miscellaneous clean-ups
-- unix: fix documentation of Unix.tm (PR#3341)
-- graphics: fix problem when allocating lots of images under Windows (PR#3433)
-- compiler: fix error message with -pack when .cmi is missing (PR#3028)
-- cygwin: fix problem with compilation of camlheader (PR#3485)
-- stdlib: Filename.basename doesn't return an empty string any more (PR#3451)
-- stdlib: better documentation of Open_excl flag (PR#3450)
-- ocamlcp: accept -thread option (PR#3511)
-- ocamldep: handle spaces in file names (PR#3370)
-- compiler: remove spurious warning in pattern-matching on variants (PR#3424)
-- windows: better handling of InterpreterPath registry entry (PR#3334, PR#3432)
+- unix: fix documentation of Unix.tm (#3341)
+- graphics: fix problem when allocating lots of images under Windows (#3433)
+- compiler: fix error message with -pack when .cmi is missing (#3028)
+- cygwin: fix problem with compilation of camlheader (#3485)
+- stdlib: Filename.basename doesn't return an empty string any more (#3451)
+- stdlib: better documentation of Open_excl flag (#3450)
+- ocamlcp: accept -thread option (#3511)
+- ocamldep: handle spaces in file names (#3370)
+- compiler: remove spurious warning in pattern-matching on variants (#3424)
+- windows: better handling of InterpreterPath registry entry (#3334, #3432)
 
 
 Objective Caml 3.08.2 (22 Nov 2004):
 ------------------------------------
 
 Bug fixes:
-- runtime: memory leak when unmarshalling big data structures (PR#3247)
-- camlp4: incorrect line numbers in errors (PR#3188)
+- runtime: memory leak when unmarshalling big data structures (#3247)
+- camlp4: incorrect line numbers in errors (#3188)
 - emacs: xemacs-specific code, wrong call to "sit-for"
-- ocamldoc: "Lexing: empty token" (PR#3173)
-- unix: problem with close_process_* (PR#3191)
-- unix: possible coredumps (PR#3252)
-- stdlib: wrong order in Set.fold (PR#3161)
-- ocamlcp: array out of bounds in profiled programs (PR#3267)
-- yacc: problem with polymorphic variant types for grammar entries (PR#3033)
+- ocamldoc: "Lexing: empty token" (#3173)
+- unix: problem with close_process_* (#3191)
+- unix: possible coredumps (#3252)
+- stdlib: wrong order in Set.fold (#3161)
+- ocamlcp: array out of bounds in profiled programs (#3267)
+- yacc: problem with polymorphic variant types for grammar entries (#3033)
 
 Misc:
-- export  for caml_format_exception (PR#3080)
-- clean up caml_search_exe_in_path (maybe PR#3079)
+- export  for caml_format_exception (#3080)
+- clean up caml_search_exe_in_path (maybe #3079)
 - camlp4: new function "make_lexer" for new-style locations
-- unix: added missing #includes (PR#3088)
+- unix: added missing #includes (#3088)
 
 
 Objective Caml 3.08.1 (19 Aug 2004):
@@ -5977,21 +6924,21 @@ Licence:
 
 Bug fixes:
 - ld.conf now generated at compile-time instead of install-time
-- fixed -pack on Windows XP (PR#2935)
-- fixed Obj.tag (PR#2946)
+- fixed -pack on Windows XP (#2935)
+- fixed Obj.tag (#2946)
 - added support for multiple dlopen in Darwin
-- run ranlib when installing camlp4 libraries (PR#2944)
-- link camlp4opt with -linkall (PR#2949)
-- camlp4 parsing of patterns now conforms to normal parsing (PR#3015)
-- install camlp4 *.cmx files (PR#2955)
-- fixed handling of linefeed in string constants in camlp4 (PR#3074)
-- ocamldoc: fixed display of class parameters in HTML and LaTeX (PR#2994)
-- ocamldoc: fixed display of link to class page in html (PR#2994)
-- Windows toplevel GUI: assorted fixes (including PR#2932)
+- run ranlib when installing camlp4 libraries (#2944)
+- link camlp4opt with -linkall (#2949)
+- camlp4 parsing of patterns now conforms to normal parsing (#3015)
+- install camlp4 *.cmx files (#2955)
+- fixed handling of linefeed in string constants in camlp4 (#3074)
+- ocamldoc: fixed display of class parameters in HTML and LaTeX (#2994)
+- ocamldoc: fixed display of link to class page in html (#2994)
+- Windows toplevel GUI: assorted fixes (including #2932)
 
 Misc:
 - added -v option to ocamllex
-- ocamldoc: new -intf and -impl options supported (PR#3036)
+- ocamldoc: new -intf and -impl options supported (#3036)
 
 Objective Caml 3.08.0 (13 Jul 2004):
 ------------------------------------
@@ -6667,7 +7614,7 @@ Both compilers:
 - Option -warn-error to turn warnings into errors.
 - Option -where to print the location of the standard library directory.
 - Assertions are now type-checked even if the -noassert option is given,
-  thus -noassert can no longe change the types of modules.
+  thus -noassert can no longer change the types of modules.
 
 Bytecode compiler and bytecode interpreter:
 - Print stack backtrace when a program aborts due to an uncaught exception
@@ -6685,7 +7632,7 @@ Native-code compiler:
 - Removed spurious dependency on the -lcurses library.
 
 Toplevel environment:
-- Revised handling of top-level value definitions, allows reclaimation
+- Revised handling of top-level value definitions, allows reclamation
   of definitions that are shadowed by later definitions with the same names.
   (E.g. "let x = ;; let x = 1;;" allows  to be reclaimed.)
 - Revised the tracing facility so that for standard library functions,
@@ -7451,7 +8398,7 @@ Objective Caml 1.03 (29 Oct 1996):
     exp() or log() cause a domain error; fixed bug with
     String.length "literal";
   - Sparc, Mips, HPPA: removed marking of scanned stack frames
-    (benefits do not outweight cost).
+    (benefits do not outweigh cost).
 
 * Standard library:
   - Arg.parse now prints documentation for command-line options;
@@ -7611,7 +8558,7 @@ marshaling to/from strings.
 
 * Thread library: much better support for I/O and blocking system calls.
 
-* Graphics library: faster reclaimation of unused pixmaps.
+* Graphics library: faster reclamation of unused pixmaps.
 
 * Unix library: new functions {set,clear}_nonblock, {set,clear}_close_on_exec,
 {set,get}itimer, inet_addr_any, {get,set}sockopt.
diff --git a/HACKING.adoc b/HACKING.adoc
index 0770d4af..93c6e4fe 100644
--- a/HACKING.adoc
+++ b/HACKING.adoc
@@ -43,6 +43,14 @@ make tests
 ----
 opam compiler-conf install
 ----
++
+With opam 2, create a local opam switch with the compiler installed from
+the current source directory:
++
+----
+opam switch create . --empty
+opam install .
+----
 
 6. You did it, Well done! Consult link:CONTRIBUTING.md[] to send your contribution upstream.
 
@@ -157,37 +165,37 @@ has excellent documentation.
 
 === Complete file listing
 
+  BOOTSTRAP.adoc::        instructions for bootstrapping
   Changes::               what's new with each release
-  configure::             configure script
   CONTRIBUTING.md::       how to contribute to OCaml
   HACKING.adoc::          this file
   INSTALL.adoc::          instructions for installation
   LICENSE::               license and copyright notice
   Makefile::              main Makefile
-  Makefile.nt::           Windows Makefile (deprecated)
+  Makefile.common::       common Makefile definitions
   Makefile.tools::        used by manual/ and testsuite/ Makefiles
   README.adoc::           general information on the compiler distribution
   README.win32.adoc::     general information on the Windows ports of OCaml
   VERSION::               version string
   asmcomp/::              native-code compiler and linker
-  asmrun/::               native-code runtime library
   boot/::                 bootstrap compiler
   bytecomp/::             bytecode compiler and linker
-  byterun/::              bytecode interpreter and runtime system
   compilerlibs/::         the OCaml compiler as a library
   config/::               configuration files
+  configure::             configure script
   debugger/::             source-level replay debugger
   driver/::               driver code for the compilers
   emacs/::                editing mode and debugger interface for GNU Emacs
-  experimental/::         experiments not built by default
   flexdll/::              git submodule -- see link:README.win32.adoc[]
   lex/::                  lexer generator
   man/::                  man pages
   manual/::               system to generate the manual
   middle_end/::           the flambda optimisation phase
   ocamldoc/::             documentation generator
+  ocamltest/::            test driver
   otherlibs/::            several additional libraries
   parsing/::              syntax analysis -- see link:parsing/HACKING.adoc[]
+  runtime/::              bytecode interpreter and runtime systems
   stdlib/::               standard library
   testsuite/::            tests -- see link:testsuite/HACKING.adoc[]
   tools/::                various utilities
@@ -224,12 +232,12 @@ installation, the following targets may be of use:
 === Bootstrapping
 
 The OCaml compiler is bootstrapped. This means that
-previously-compiled bytecode versions of the compiler, dependency
-generator and lexer are included in the repository under the
+previously-compiled bytecode versions of the compiler and lexer are
+included in the repository under the
 link:boot/[] directory. These bytecode images are used once the
 bytecode runtime (which is written in C) has been built to compile the
 standard library and then to build a fresh compiler. Details can be
-found in link:INSTALL.adoc#bootstrap[INSTALL.adoc].
+found in link:BOOTSTRAP.adoc[].
 
 === Continuous integration
 
diff --git a/INSTALL.adoc b/INSTALL.adoc
index bf3990fd..c281eeb8 100644
--- a/INSTALL.adoc
+++ b/INSTALL.adoc
@@ -1,6 +1,6 @@
 = Installing OCaml from sources on a Unix(-like) machine =
 
-== PREREQUISITES
+== Prerequisites
 
 * The GNU C Compiler (gcc) is recommended, as the bytecode interpreter takes
   advantage of GCC-specific features to enhance performance. gcc is the standard
@@ -19,173 +19,46 @@
   to be able to process `.cmxs` files.  `diffutils` is necessary to run the test
   suite.
 
-== INSTALLATION INSTRUCTIONS
+== Configuration
 
-1. Configure the system. From the top directory, do:
+From the top directory, do:
 
         ./configure
 +
-This generates the three configuration files `config/Makefile`,
-`byterun/caml/m.h` and `byterun/caml/s.h`.
+This generates the three configuration files `Makefile.config`,
+`runtime/caml/m.h` and `runtime/caml/s.h`.
 +
-The `configure` script accepts the following options:
-+
-`-prefix `::                   (default: `/usr/local`)
-        Set the `PREFIX` variable used to define the defaults of the following
-        three options.  Must be an absolute path name.
-
-`-bindir `::                   (default: `$(PREFIX)/bin`)
-        Directory where the binaries will be installed.  Must be an absolute
-        path name, or start with `$(PREFIX)`.
-
-`-libdir `::                   (default: `$(PREFIX)/lib/ocaml`)
-        Directory where the OCaml library will be installed.  Must be an
-        absolute path name, or start with `$(PREFIX)`.
-
-`-mandir `::                   (default: `$(PREFIX)/man/man1`)
-        Directory where the manual pages will be installed.  Must be an absolute
-        path name, or start with `$(PREFIX)`.
-
-`-cc `::    (default: `gcc` if found, otherwise `cc`)
-        C compiler to use for building the system.
-
-`-libs `::         (default: none)
-        Extra libraries to link with the system.
-
-`-no-curses`::
-        Do not use the curses library.
-        The only use for this is to highlight errors in the toplevel using
-        'standout' mode, e.g. underline, rather than with '^' on a newline.
-
-`-host `::                (default: determined automatically)
-        The type of the host machine, in GNU's "configuration name" format
-        (CPU-COMPANY-SYSTEM or CPU-COMPANY-KERNEL-SYSTEM).  This info is
-        generally determined automatically by the `configure` script, and rarely
-        ever needs to be provided by hand.  The installation instructions for
-        GCC or GNU Emacs contain a complete list of configuration names.
-
-`-target `::            (default: same as `-host`)
-        The type of the target machine, in GNU's "configuration name" format
-        (CPU-COMPANY-SYSTEM or CPU-COMPANY-KERNEL-SYSTEM). Setting this will
-        setup OCaml as a cross-compiler which runs on `$host` and produces code
-        for `$target`. This requires a C toolchain which also produces code for
-        `$target` and a native OCaml compiler of the exact same version (if you
-        want a cross 4.00.1, you need a native 4.00.1).
-
-`-x11include `::       (default: determined automatically)
-`-x11lib `::               (default: determined automatically)
-        Location of the X11 include directory (e.g. `/usr/X11R6/include`) and
-        the X11 library directory (e.g. `/usr/X11R6/lib`).
-
-`-no-pthread`::
-        Do not attempt to use POSIX threads.
-
-`-with-pthread`::
-        Attempt to use POSIX threads (this is the default).
-
-`-no-shared-libs`::
-        Do not configure support for shared libraries.
-
-`-dldefs `::
-`-dllibs `::
-        These options specify where to find the libraries for dynamic linking
-        (i.e. use of shared libraries).  `-dldefs` specifies options for finding
-        the header files, and `-dllibs` for finding the C libraries.
-
-`-as `::     (default: determined automatically)
-        The assembler to use for assembling ocamlopt-generated code.
-
-`-aspp `::   (default: determined automatically)
-        The assembler to use for assembling the parts of the run-time system
-        manually written in assembly language. This assembler must pre-process
-        its input with the C preprocessor.
-
-`-with-debug-runtime`::
-        Compile and install the debug version of the runtimes, useful for
-        debugging C stubs and other low-level code.
-
-`-with-instrumented-runtime`::
-        Compile and install the instrumented version of the runtimes, useful
-        mainly for fine-tuning the GC.  Works only on Linux.
-
-`-verbose`::
-        Verbose output of the configuration tests.  Use it if the outcome of
-        `configure` is not what you were expecting.
-
-`-no-debugger`::
-        Do not build `ocamldebug`.
-
-`-no-native-compiler`::
-        Do not build the native compiler -- bytecode compilation only.
-
-`-no-ocamldoc`::
-        Do not build `ocamldoc`.
-
-`-no-ocamlbuild`::
-        Deprecated since 4.03.0, as `ocamlbuild` is now distributed separately
-        from the compiler distribution.
-
-`-no-graph`::
-        Do not compile the Graphics library.
-
-`-partialld `:: (default: determined automatically)
-        The linker and options to use for producing an object file (rather than
-        an executable) from several other object files.
+The `configure` script accepts options that can be discovered by running:
 
-`-no-cfi`::
-        Do not compile support for CFI directives.
+        ./configure --help
++
+Some options or variables like (LDFLAGS) may not be taken into account
+by the OCaml build system at the moment. Please report an issue if you
+discover such a variable or option and this causes troubles to you.
 +
 Examples:
 
 * Standard installation in `/usr/{bin,lib,man}` instead of `/usr/local`:
-    ./configure -prefix /usr
-
+    ./configure --prefix=/usr
 
-* Installation in `/usr`, man pages in section "l":
-
-    ./configure -bindir /usr/bin -libdir /usr/lib/ocaml -mandir /usr/man/manl
-+
-or:
-
-    ./configure -prefix /usr -mandir '$(PREFIX)/man/manl'
 
 * On a Linux x86-64 host, to build a 32-bit version of OCaml:
 
-    ./configure -cc "gcc -m32" -as "as --32" -aspp "gcc -m32 -c" \
-                -host i386-linux -partialld "ld -r -melf_i386"
-
-* On a Linux x86-64 host, to build the run-time system in PIC mode, no special
-  options should be required -- the libraries should be built automatically.
-  The old instructions were:
-
-    ./configure -cc "gcc -fPIC" -aspp "gcc -c -fPIC"
-+
-On a 64-bit POWER architecture host running Linux, OCaml only operates in a
-  32-bit environment.  If your system compiler is configured as 32-bit, e.g.
-  Red Hat 5.9, you don't need to do anything special.  If that is not the case
-  (e.g. Red Hat 6.4), then IBM's "Advance Toolchain" can be used.  For example:
-
-    export PATH=/opt/at7.0/bin:$PATH
-    ./configure -cc "gcc -m32" -as "as -a32" -aspp "gcc -m32 -c" \
-      -partialld "ld -r -m elf32ppc"
-
-* On a OS X 10.5/Intel Core 2 or OS X 10.5/PowerPC host, to build a 64-bit
-  version of OCaml:
-
-    ./configure -cc "gcc -m64"
-
-* On OS X Intel, to build a 32-bit version of OCaml:
-
-    ./configure -host "i386-apple-darwin13.2.0" -cc "gcc -arch i386 -m32" \
-      -as "as -arch i386" -aspp "gcc -arch i386 -m32 -c"
-
-* For Sun Solaris with the `acc` compiler:
-
-    ./configure -cc "acc -fast" -libs "-lucb"
+    ./configure --build=x86_64-pc-linux-gnu --host=i386-linux \
+                CC='gcc -m32' AS='as --32' ASPP='gcc -m32 -c' \
+                PARTIALLD='ld -r -melf_i386'
 
 * For AIX 4.3 with the IBM compiler `xlc`:
 
     ./configure -cc "xlc_r -D_AIX43 -Wl,-bexpall,-brtl -qmaxmem=8192"
+
+* For AIX 7.x with the IBM compiler `xlc`:
+
+    ./configure CC=xlc
++
+By default, build is 32-bit. For 64-bit build, please set environment variable `OBJECT_MODE=64`
+  for _both_ `configure` and `make world` phases. Note, if this variable is set for only one phase,
+  your build will break (`ocamlrun` segfaults).
 +
 If something goes wrong during the automatic configuration, or if the generated
 files cause errors later on, then look at the template files:
@@ -196,7 +69,9 @@ files cause errors later on, then look at the template files:
 +
 for guidance on how to edit the generated files by hand.
 
-2. From the top directory, do:
+== Building the compiler
+
+From the top directory, do:
 
         make world.opt
 +
@@ -213,27 +88,16 @@ fairly verbose; consider redirecting the output to a file:
         make world > log.world 2>&1     # in sh
         make world >& log.world         # in csh
 
-[[bootstrap]]
-3. (Optional) To be sure everything works well, you can try to bootstrap the
-   system -- that is, to recompile all OCaml sources with the newly created
-   compiler. From the top directory, do:
+== (Optional) Running the testsuite
 
-        make bootstrap
-+
-or, better:
+To be sure everything works well, you can run the test suite
+   that comes with the compiler. To do so, do:
 
-        make bootstrap > log.bootstrap 2>&1     # in sh
-        make bootstrap >& log.bootstrap         # in csh
-+
-The `make bootstrap` checks that the bytecode programs compiled with the new
-compiler are identical to the bytecode programs compiled with the old compiler.
-If this is the case, you can be pretty sure the system has been correctly
-compiled. Otherwise, this does not necessarily mean something went wrong.  The
-best thing to do is to try a second bootstrapping phase: just do
-`make bootstrap` again.  It will either crash almost immediately, or
-re-re-compile everything correctly and reach the fix-point.
-
-4. You can now install the OCaml system. This will create the following commands
+        make tests
+
+== Installing the compiler
+
+You can now install the OCaml system. This will create the following commands
    (in the binary directory selected during autoconfiguration):
 +
 [width="70%",frame="topbot",cols="25%,75%"]
@@ -255,38 +119,24 @@ re-re-compile everything correctly and reach the fix-point.
 +
 From the top directory, become superuser and do:
 
-        umask 022       # make sure to give read & execute permission to all
         make install
 
-5. Installation is complete. Time to clean up. From the toplevel directory,
+Installation is complete. Time to clean up. From the toplevel directory,
    do:
 
         make clean
 
-6. (Optional) The `emacs/` subdirectory contains Emacs-Lisp files for an OCaml
-   editing mode and an interface for the debugger.  To install these files,
-   change to the `emacs/` subdirectory and do:
-
-        make EMACSDIR= install
-+
-or
-
-        make install
-+
-In the latter case, the destination directory defaults to the
-`site-lisp` directory of your Emacs installation.
-
-7. After installation, do *not* strip the `ocamldebug` and `ocamlbrowser`
-   executables. These are mixed-mode executables (containing both compiled C
+After installation, do *not* strip the `ocamldebug` executables.
+   This is a mixed-mode executable (containing both compiled C
    code and OCaml bytecode) and stripping erases the bytecode!  Other
    executables such as `ocamlrun` can safely be stripped.
 
-== IF SOMETHING GOES WRONG
+== If something goes wwong
 
 Read the "common problems" and "machine-specific hints" section at the end of
 this file.
 
-Check the files `m.h` and `s.h` in `byterun/caml/`.
+Check the files `m.h` and `s.h` in `runtime/caml/`.
 Wrong endianness or alignment constraints in `machine.h` will
 immediately crash the bytecode interpreter.
 
@@ -295,24 +145,18 @@ and data segment size (type `limit` under csh or `ulimit -a` under bash). Make
 sure the limit on the stack size is at least 4M.
 
 Try recompiling the runtime system with optimizations turned off (change
-`CFLAGS` in `byterun/Makefile` and `asmrun/Makefile`). The runtime system
+`OC_CFLAGS` in `runtime/Makefile`). The runtime system
 contains some complex, atypical pieces of C code which can uncover bugs in
 optimizing compilers.  Alternatively, try another C compiler (e.g. `gcc` instead
 of the vendor-supplied `cc`).
 
-You can also build a debug version of the runtime system. Go to the `byterun/`
+You can also build a debug version of the runtime system. Go to the `runtime/`
 directory and do `make ocamlrund`.  Then, copy `ocamlrund` to
 `../boot/ocamlrun`, and try again.  This version of the runtime system contains
 lots of assertions and sanity checks that could help you pinpoint the problem.
 
 
-== COMMON PROBLEMS
-
-* The Makefiles use the `include` directive, which is not supported by all
-  versions of make. Use GNU Make if this is a problem.
-
-* Solaris make mishandles a space in our Makefiles, so you have to use GNU make
-  to build on Solaris.
+== Common problems
 
 * The Makefiles assume that make executes commands by calling `/bin/sh`. They
   won't work if `/bin/csh` is called instead.  You may have to unset the `SHELL`
@@ -322,18 +166,6 @@ lots of assertions and sanity checks that could help you pinpoint the problem.
   the C locale (`export LC_ALL=C`) before compiling if you have strange errors
   while compiling OCaml.
 
-* GCC 2.7.2.1 generates incorrect code for the runtime system in `-O` mode on
-  some Intel x86 platforms (e.g. Linux RedHat 4.1 and 4.2). If this causes a
-  problem, the solution is to upgrade to 2.7.2.3 or above.
-
-* Some versions of GCC 2.96 for the Intel x86 (as found in RedHat 7.2,
-  Mandrake 8.0 and Mandrake 8.1) generate incorrect code for the runtime system.
-  The `configure` script tries to work around this problem.
-
 * On HP 9000/700 machines under HP/UX 9, some versions of `cc` are unable to
   compile correctly the runtime system (wrong code is generated for `(x - y)`
   where `x` is a pointer and `y` an integer). Fix: use `gcc`.
-
-* Under OS X 10.6, with XCode 4.0.2, the `configure` script mistakenly detects
-  support for CFI directives in the assembler. Fix: give the `-no-cfi` option to
-  `configure`.
diff --git a/Makefile b/Makefile
index 1b4bec8e..2a9413a9 100644
--- a/Makefile
+++ b/Makefile
@@ -15,22 +15,9 @@
 
 # The main Makefile
 
-# Hard bootstrap how-to:
-# (only necessary if you remove or rename some primitive)
-#
-# make core     [old system -- you were in a stable state]
-# make coreboot [optional -- check state stability]
-# 
-# make clean && make core
-# if the above fails:
-#     
-#     make clean && make core
-# make coreboot [intermediate state with both old and new primitives]
-# 
-# make clean && make runtime && make coreall
-# make coreboot [new system -- now in a stable state]
-
-include config/Makefile
+ROOTDIR = .
+
+include Makefile.config
 include Makefile.common
 
 # For users who don't read the INSTALL file
@@ -55,17 +42,16 @@ LN = ln -sf
 endif
 
 CAMLRUN ?= boot/ocamlrun
-CAMLYACC ?= boot/ocamlyacc
 include stdlib/StdlibModules
 
-CAMLC=$(CAMLRUN) boot/ocamlc -g -nostdlib -I boot -use-prims byterun/primitives
+CAMLC=$(CAMLRUN) boot/ocamlc -g -nostdlib -I boot -use-prims runtime/primitives
 CAMLOPT=$(CAMLRUN) ./ocamlopt -g -nostdlib -I stdlib -I otherlibs/dynlink
 ARCHES=amd64 i386 arm arm64 power s390x
 INCLUDES=-I utils -I parsing -I typing -I bytecomp -I middle_end \
         -I middle_end/base_types -I asmcomp -I asmcomp/debug \
         -I driver -I toplevel
 
-COMPFLAGS=-strict-sequence -principal -absname -w +a-4-9-41-42-44-45-48 \
+COMPFLAGS=-strict-sequence -principal -absname -w +a-4-9-40-41-42-44-45-48-66 \
 	  -warn-error A \
           -bin-annot -safe-string -strict-formats $(INCLUDES)
 LINKFLAGS=
@@ -79,24 +65,26 @@ endif
 YACCFLAGS=-v --strict
 CAMLLEX=$(CAMLRUN) boot/ocamllex
 CAMLDEP=$(CAMLRUN) boot/ocamlc -depend
-DEPFLAGS=$(INCLUDES)
+DEPFLAGS=-slash
+DEPINCLUDES=$(INCLUDES)
 
 OCAMLDOC_OPT=$(WITH_OCAMLDOC:=.opt)
 
-UTILS=utils/config.cmo utils/misc.cmo \
+UTILS=utils/config.cmo utils/build_path_prefix_map.cmo utils/misc.cmo \
   utils/identifiable.cmo utils/numbers.cmo utils/arg_helper.cmo \
-  utils/clflags.cmo utils/tbl.cmo utils/profile.cmo \
+  utils/clflags.cmo utils/profile.cmo \
+  utils/load_path.cmo \
   utils/terminfo.cmo utils/ccomp.cmo utils/warnings.cmo \
   utils/consistbl.cmo \
   utils/strongly_connected_components.cmo \
-  utils/build_path_prefix_map.cmo \
   utils/targetint.cmo
 
 PARSING=parsing/location.cmo parsing/longident.cmo \
   parsing/docstrings.cmo parsing/syntaxerr.cmo \
-  parsing/ast_helper.cmo parsing/parser.cmo \
-  parsing/lexer.cmo parsing/parse.cmo parsing/printast.cmo \
+  parsing/ast_helper.cmo \
   parsing/pprintast.cmo \
+  parsing/camlinternalMenhirLib.cmo parsing/parser.cmo \
+  parsing/lexer.cmo parsing/parse.cmo parsing/printast.cmo \
   parsing/ast_mapper.cmo parsing/ast_iterator.cmo parsing/attr_helper.cmo \
   parsing/builtin_attributes.cmo parsing/ast_invariants.cmo parsing/depend.cmo
 
@@ -108,12 +96,15 @@ TYPING=typing/ident.cmo typing/path.cmo \
   typing/typedtree.cmo typing/printtyped.cmo typing/ctype.cmo \
   typing/printtyp.cmo typing/includeclass.cmo \
   typing/mtype.cmo typing/envaux.cmo typing/includecore.cmo \
-  typing/typedtreeIter.cmo typing/typedtreeMap.cmo \
-  typing/tast_mapper.cmo \
+  typing/typedtreeIter.cmo typing/tast_mapper.cmo \
   typing/cmt_format.cmo typing/untypeast.cmo \
   typing/includemod.cmo typing/typetexp.cmo typing/printpat.cmo \
-  typing/parmatch.cmo typing/stypes.cmo typing/typedecl.cmo typing/typeopt.cmo \
-  typing/typecore.cmo typing/typeclass.cmo typing/typemod.cmo
+  typing/parmatch.cmo typing/stypes.cmo \
+  typing/typedecl_properties.cmo typing/typedecl_variance.cmo \
+  typing/typedecl_unboxed.cmo typing/typedecl_immediacy.cmo \
+  typing/typedecl.cmo typing/typeopt.cmo \
+  typing/rec_check.cmo typing/typecore.cmo typing/typeclass.cmo \
+  typing/typemod.cmo
 
 COMP=bytecomp/lambda.cmo bytecomp/printlambda.cmo \
   bytecomp/semantics_of_primitives.cmo \
@@ -127,7 +118,10 @@ COMP=bytecomp/lambda.cmo bytecomp/printlambda.cmo \
   bytecomp/symtable.cmo \
   driver/pparse.cmo driver/main_args.cmo \
   driver/compenv.cmo driver/compmisc.cmo \
-  driver/compdynlink.cmo driver/compplugin.cmo driver/makedepend.cmo
+  driver/compdynlink_types.cmo driver/compdynlink_platform_intf.cmo \
+  driver/compdynlink_common.cmo driver/compdynlink.cmo \
+  driver/compplugin.cmo driver/makedepend.cmo \
+  driver/compile_common.cmo
 
 
 COMMON=$(UTILS) $(PARSING) $(TYPING) $(COMP)
@@ -158,6 +152,7 @@ endif
 ASMCOMP=\
   $(ARCH_SPECIFIC_ASMCOMP) \
   asmcomp/arch.cmo \
+  asmcomp/backend_var.cmo \
   asmcomp/cmm.cmo asmcomp/printcmm.cmo \
   asmcomp/reg.cmo asmcomp/debug/reg_with_debug_info.cmo \
   asmcomp/debug/reg_availability_set.cmo \
@@ -196,6 +191,7 @@ ASMCOMP=\
   driver/opterrors.cmo driver/optcompile.cmo
 
 MIDDLE_END=\
+  middle_end/int_replace_polymorphic_compare.cmo \
   middle_end/debuginfo.cmo \
   middle_end/base_types/tag.cmo \
   middle_end/base_types/linkage_name.cmo \
@@ -257,6 +253,8 @@ MIDDLE_END=\
   middle_end/flambda_invariants.cmo \
   middle_end/middle_end.cmo
 
+OPTCOMP=$(MIDDLE_END) $(ASMCOMP)
+
 TOPLEVEL=toplevel/genprintval.cmo toplevel/toploop.cmo \
   toplevel/trace.cmo toplevel/topdirs.cmo toplevel/topmain.cmo
 
@@ -274,12 +272,10 @@ PERVASIVES=$(STDLIB_MODULES) outcometree topdirs toploop
 
 LIBFILES=stdlib.cma std_exit.cmo *.cmi camlheader
 
-MAXSAVED=boot/Saved/Saved.prev/Saved.prev/Saved.prev/Saved.prev/Saved.prev
-
 COMPLIBDIR=$(LIBDIR)/compiler-libs
 
 TOPINCLUDES=$(addprefix -I otherlibs/,$(filter-out %threads,$(OTHERLIBRARIES)))
-RUNTOP=./byterun/ocamlrun ./ocaml \
+RUNTOP=./runtime/ocamlrun ./ocaml \
   -nostdlib -I stdlib \
   -noinit $(TOPFLAGS) $(TOPINCLUDES)
 NATRUNTOP=./ocamlnat$(EXE) \
@@ -296,79 +292,17 @@ BOOT_FLEXLINK_CMD=
 ifeq "$(UNIX_OR_WIN32)" "win32"
 FLEXDLL_SUBMODULE_PRESENT := $(wildcard flexdll/Makefile)
 ifeq "$(FLEXDLL_SUBMODULE_PRESENT)" ""
-  BOOT_FLEXLINK_CMD=
-  FLEXDLL_DIR=
+  BOOT_FLEXLINK_CMD =
 else
   BOOT_FLEXLINK_CMD = FLEXLINK_CMD="../boot/ocamlrun ../flexdll/flexlink.exe"
-  CAMLOPT := OCAML_FLEXLINK="boot/ocamlrun flexdll/flexlink.exe" $(CAMLOPT)
-  FLEXDLL_DIR=$(if $(wildcard flexdll/flexdll_*.$(O)),+flexdll)
 endif
 else
-  FLEXDLL_DIR=
 endif
 
 # The configuration file
 
-# SUBST generates the sed substitution for the variable *named* in $1
-# SUBST_QUOTE does the same, adding double-quotes around non-empty strings
-#   (see FLEXDLL_DIR which must empty if FLEXDLL_DIR is empty but an OCaml
-#    string otherwise)
-SUBST_ESCAPE=$(subst ",\\",$(subst \,\\,$(if $2,$2,$($1))))
-SUBST=-e 's|%%$1%%|$(call SUBST_ESCAPE,$1,$2)|'
-SUBST_QUOTE2=-e 's|%%$1%%|$(if $2,"$2")|'
-SUBST_QUOTE=$(call SUBST_QUOTE2,$1,$(call SUBST_ESCAPE,$1,$2))
-FLEXLINK_LDFLAGS=$(if $(LDFLAGS), -link "$(LDFLAGS)")
-utils/config.ml: utils/config.mlp config/Makefile Makefile
-	sed $(call SUBST,AFL_INSTRUMENT) \
-	    $(call SUBST,ARCH) \
-	    $(call SUBST,ARCMD) \
-	    $(call SUBST,ASM) \
-	    $(call SUBST,ASM_CFI_SUPPORTED) \
-	    $(call SUBST,BYTECCLIBS) \
-	    $(call SUBST,BYTERUN) \
-	    $(call SUBST,CC) \
-	    $(call SUBST,CCOMPTYPE) \
-	    $(call SUBST,CC_PROFILE) \
-	    $(call SUBST,OUTPUTOBJ) \
-	    $(call SUBST,EXT_ASM) \
-	    $(call SUBST,EXT_DLL) \
-	    $(call SUBST,EXE) \
-	    $(call SUBST,EXT_LIB) \
-	    $(call SUBST,EXT_OBJ) \
-	    $(call SUBST,FLAMBDA) \
-	    $(call SUBST,WITH_FLAMBDA_INVARIANTS) \
-	    $(call SUBST,FLEXLINK_FLAGS) \
-	    $(call SUBST_QUOTE,FLEXDLL_DIR) \
-	    $(call SUBST,HOST) \
-	    $(call SUBST,LIBDIR) \
-	    $(call SUBST,LIBUNWIND_AVAILABLE) \
-	    $(call SUBST,LIBUNWIND_LINK_FLAGS) \
-	    $(call SUBST,MKDLL) \
-	    $(call SUBST,MKEXE) \
-	    $(call SUBST,FLEXLINK_LDFLAGS) \
-	    $(call SUBST,MKMAINDLL) \
-	    $(call SUBST,MODEL) \
-	    $(call SUBST,NATIVECCLIBS) \
-	    $(call SUBST,OCAMLC_CFLAGS) \
-	    $(call SUBST,OCAMLC_CPPFLAGS) \
-	    $(call SUBST,OCAMLOPT_CFLAGS) \
-	    $(call SUBST,OCAMLOPT_CPPFLAGS) \
-	    $(call SUBST,PACKLD) \
-	    $(call SUBST,PROFILING) \
-	    $(call SUBST,PROFINFO_WIDTH) \
-	    $(call SUBST,RANLIBCMD) \
-	    $(call SUBST,FORCE_SAFE_STRING) \
-	    $(call SUBST,DEFAULT_SAFE_STRING) \
-	    $(call SUBST,WINDOWS_UNICODE) \
-	    $(call SUBST,SYSTEM) \
-	    $(call SUBST,SYSTHREAD_SUPPORT) \
-	    $(call SUBST,TARGET) \
-	    $(call SUBST,WITH_FRAME_POINTERS) \
-	    $(call SUBST,WITH_PROFINFO) \
-	    $(call SUBST,WITH_SPACETIME) \
-	    $(call SUBST,ENABLE_CALL_COUNTS) \
-	    $(call SUBST,FLAT_FLOAT_ARRAY) \
-	    $< > $@
+utils/config.ml: utils/config.mlp Makefile.config utils/Makefile Makefile
+	$(MAKE) -C utils config.ml
 
 ifeq "$(UNIX_OR_WIN32)" "unix"
 .PHONY: reconfigure
@@ -386,20 +320,18 @@ beforedepend:: utils/config.ml
 # Start up the system from the distribution compiler
 .PHONY: coldstart
 coldstart:
-	$(MAKE) -C byterun $(BOOT_FLEXLINK_CMD) all
-	cp byterun/ocamlrun$(EXE) boot/ocamlrun$(EXE)
-	$(MAKE) -C yacc $(BOOT_FLEXLINK_CMD) all
-	cp yacc/ocamlyacc$(EXE) boot/ocamlyacc$(EXE)
+	$(MAKE) -C runtime $(BOOT_FLEXLINK_CMD) all
+	cp runtime/ocamlrun$(EXE) boot/ocamlrun$(EXE)
 	$(MAKE) -C stdlib $(BOOT_FLEXLINK_CMD) \
-	  COMPILER="../boot/ocamlc -use-prims ../byterun/primitives" all
+	  COMPILER="../boot/ocamlc -use-prims ../runtime/primitives" all
 	cd stdlib; cp $(LIBFILES) ../boot
-	cd boot; $(LN) ../byterun/libcamlrun.$(A) .
+	cd boot; $(LN) ../runtime/libcamlrun.$(A) .
 
 # Recompile the core system using the bootstrap compiler
 .PHONY: coreall
-coreall:
+coreall: runtime
 	$(MAKE) ocamlc
-	$(MAKE) ocamllex ocamlyacc ocamltools library
+	$(MAKE) ocamllex ocamltools library
 
 # Build the core system: the minimum needed to make depend and bootstrap
 .PHONY: core
@@ -407,51 +339,38 @@ core:
 	$(MAKE) coldstart
 	$(MAKE) coreall
 
-# Save the current bootstrap compiler
-.PHONY: backup
-backup:
-	$(MKDIR) boot/Saved
-	if test -d $(MAXSAVED); then rm -r $(MAXSAVED); fi
-	mv boot/Saved boot/Saved.prev
-	mkdir boot/Saved
-	mv boot/Saved.prev boot/Saved/Saved.prev
-	cp boot/ocamlrun$(EXE) boot/Saved
-	cd boot; mv ocamlc ocamllex ocamlyacc$(EXE) Saved
-	cd boot; cp $(LIBFILES) Saved
-
-# Restore the saved bootstrap compiler if a problem arises
-.PHONY: restore
-restore:
-	cd boot; mv Saved/* .; rmdir Saved; mv Saved.prev Saved
-
 # Check if fixpoint reached
 .PHONY: compare
 compare:
 	@if $(CAMLRUN) tools/cmpbyt boot/ocamlc ocamlc \
          && $(CAMLRUN) tools/cmpbyt boot/ocamllex lex/ocamllex; \
 	then echo "Fixpoint reached, bootstrap succeeded."; \
-	else echo "Fixpoint not reached, try one more bootstrapping cycle."; \
+	else \
+	  echo "Fixpoint not reached, try one more bootstrapping cycle."; \
+	  exit 1; \
 	fi
 
+# Promote a compiler
+
+PROMOTE ?= cp
+
+.PHONY: promote-common
+promote-common:
+	$(PROMOTE) ocamlc boot/ocamlc
+	$(PROMOTE) lex/ocamllex boot/ocamllex
+	cd stdlib; cp $(LIBFILES) ../boot
+
 # Promote the newly compiled system to the rank of cross compiler
 # (Runs on the old runtime, produces code for the new runtime)
 .PHONY: promote-cross
-promote-cross:
-	$(CAMLRUN) tools/stripdebug ocamlc boot/ocamlc
-	$(CAMLRUN) tools/stripdebug lex/ocamllex boot/ocamllex
-	cp yacc/ocamlyacc$(EXE) boot/ocamlyacc$(EXE)
-	cd stdlib; cp $(LIBFILES) ../boot
+promote-cross: promote-common
 
 # Promote the newly compiled system to the rank of bootstrap compiler
 # (Runs on the new runtime, produces code for the new runtime)
 .PHONY: promote
-promote: promote-cross
-	cp byterun/ocamlrun$(EXE) boot/ocamlrun$(EXE)
-
-# Remove old bootstrap compilers
-.PHONY: cleanboot
-cleanboot:
-	rm -rf boot/Saved/Saved.prev/*
+promote: PROMOTE = $(CAMLRUN) tools/stripdebug
+promote: promote-common
+	cp runtime/ocamlrun$(EXE) boot/ocamlrun$(EXE)
 
 # Compile the native-code compiler
 .PHONY: opt-core
@@ -484,19 +403,17 @@ opt.opt:
 # Core bootstrapping cycle
 .PHONY: coreboot
 coreboot:
-# Save the original bootstrap compiler
-	$(MAKE) backup
 # Promote the new compiler but keep the old runtime
 # This compiler runs on boot/ocamlrun and produces bytecode for
-# byterun/ocamlrun
+# runtime/ocamlrun
 	$(MAKE) promote-cross
-# Rebuild ocamlc and ocamllex (run on byterun/ocamlrun)
+# Rebuild ocamlc and ocamllex (run on runtime/ocamlrun)
 	$(MAKE) partialclean
 	$(MAKE) ocamlc ocamllex ocamltools
-# Rebuild the library (using byterun/ocamlrun ./ocamlc)
+# Rebuild the library (using runtime/ocamlrun ./ocamlc)
 	$(MAKE) library-cross
 # Promote the new compiler and the new runtime
-	$(MAKE) CAMLRUN=byterun/ocamlrun promote
+	$(MAKE) CAMLRUN=runtime/ocamlrun promote
 # Rebuild the core system
 	$(MAKE) partialclean
 	$(MAKE) core
@@ -506,8 +423,7 @@ coreboot:
 # Recompile the system using the bootstrap compiler
 
 .PHONY: all
-all: runtime
-	$(MAKE) coreall
+all: coreall
 	$(MAKE) ocaml
 	$(MAKE) otherlibraries $(WITH_DEBUGGER) $(WITH_OCAMLDOC) ocamltest
 
@@ -517,7 +433,6 @@ all: runtime
 .PHONY: bootstrap
 bootstrap: coreboot
 	$(MAKE) all
-	$(MAKE) compare
 
 # Compile everything the first time
 
@@ -551,30 +466,31 @@ flexdll/Makefile:
 .PHONY: flexdll
 flexdll: flexdll/Makefile flexlink
 	$(MAKE) -C flexdll \
-	     OCAML_CONFIG_FILE=../config/Makefile \
+	     OCAML_CONFIG_FILE=../Makefile.config \
              MSVC_DETECT=0 CHAINS=$(FLEXDLL_CHAIN) NATDYNLINK=false support
 
 # Bootstrapping flexlink - leaves a bytecode image of flexlink.exe in flexdll/
 .PHONY: flexlink
 flexlink: flexdll/Makefile
-	$(MAKE) -C byterun BOOTSTRAPPING_FLEXLINK=yes ocamlrun$(EXE)
-	cp byterun/ocamlrun$(EXE) boot/ocamlrun$(EXE)
+	$(MAKE) -C runtime BOOTSTRAPPING_FLEXLINK=yes ocamlrun$(EXE)
+	cp runtime/ocamlrun$(EXE) boot/ocamlrun$(EXE)
 	$(MAKE) -C stdlib COMPILER=../boot/ocamlc stdlib.cma std_exit.cmo
 	cd stdlib && cp stdlib.cma std_exit.cmo *.cmi ../boot
-	$(MAKE) -C flexdll MSVC_DETECT=0 OCAML_CONFIG_FILE=../config/Makefile \
+	$(MAKE) -C flexdll MSVC_DETECT=0 OCAML_CONFIG_FILE=../Makefile.config \
 	  CHAINS=$(FLEXDLL_CHAIN) NATDYNLINK=false \
 	  OCAMLOPT="../boot/ocamlrun ../boot/ocamlc -I ../boot" \
 	  flexlink.exe
-	$(MAKE) -C byterun clean
+	$(MAKE) -C runtime clean
 	$(MAKE) partialclean
 
 .PHONY: flexlink.opt
 flexlink.opt:
 	cd flexdll && \
 	mv flexlink.exe flexlink && \
-	$(MAKE) OCAML_FLEXLINK="../boot/ocamlrun ./flexlink" MSVC_DETECT=0 \
-	           OCAML_CONFIG_FILE=../config/Makefile \
-	           OCAMLOPT="../ocamlopt.opt -I ../stdlib" flexlink.exe && \
+	($(MAKE) OCAML_FLEXLINK="../boot/ocamlrun ./flexlink" MSVC_DETECT=0 \
+	           OCAML_CONFIG_FILE=../Makefile.config \
+	           OCAMLOPT="../ocamlopt.opt -I ../stdlib" flexlink.exe || \
+	 (mv flexlink flexlink.exe && false)) && \
 	mv flexlink.exe flexlink.opt && \
 	mv flexlink flexlink.exe
 
@@ -604,20 +520,34 @@ install:
 	$(INSTALL_DATA) \
 	  VERSION \
 	  "$(INSTALL_LIBDIR)"
-	$(MAKE) -C byterun install
+	$(MAKE) -C runtime install
 	$(INSTALL_PROG) ocaml "$(INSTALL_BINDIR)/ocaml$(EXE)"
+ifeq "$(INSTALL_BYTECODE_PROGRAMS)" "true"
 	$(INSTALL_PROG) ocamlc "$(INSTALL_BINDIR)/ocamlc.byte$(EXE)"
+endif
 	$(MAKE) -C stdlib install
+ifeq "$(INSTALL_BYTECODE_PROGRAMS)" "true"
 	$(INSTALL_PROG) lex/ocamllex "$(INSTALL_BINDIR)/ocamllex.byte$(EXE)"
+endif
 	$(INSTALL_PROG) yacc/ocamlyacc$(EXE) "$(INSTALL_BINDIR)/ocamlyacc$(EXE)"
 	$(INSTALL_DATA) \
-	   utils/*.cmi utils/*.cmt utils/*.cmti utils/*.mli \
-	   parsing/*.cmi parsing/*.cmt parsing/*.cmti parsing/*.mli \
-	   typing/*.cmi typing/*.cmt typing/*.cmti typing/*.mli \
-	   bytecomp/*.cmi bytecomp/*.cmt bytecomp/*.cmti bytecomp/*.mli \
-	   driver/*.cmi driver/*.cmt driver/*.cmti driver/*.mli \
-	   toplevel/*.cmi toplevel/*.cmt toplevel/*.cmti toplevel/*.mli \
+	   utils/*.cmi \
+	   parsing/*.cmi \
+	   typing/*.cmi \
+	   bytecomp/*.cmi \
+	   driver/*.cmi \
+	   toplevel/*.cmi \
 	   "$(INSTALL_COMPLIBDIR)"
+ifeq "$(INSTALL_SOURCE_ARTIFACTS)" "true"
+	$(INSTALL_DATA) \
+	   utils/*.cmt utils/*.cmti utils/*.mli \
+	   parsing/*.cmt parsing/*.cmti parsing/*.mli \
+	   typing/*.cmt typing/*.cmti typing/*.mli \
+	   bytecomp/*.cmt bytecomp/*.cmti bytecomp/*.mli \
+	   driver/*.cmt driver/*.cmti driver/*.mli \
+	   toplevel/*.cmt toplevel/*.cmti toplevel/*.mli \
+	   "$(INSTALL_COMPLIBDIR)"
+endif
 	$(INSTALL_DATA) \
 	   compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma \
 	   compilerlibs/ocamltoplevel.cma $(BYTESTART) $(TOPLEVELSTART) \
@@ -625,9 +555,13 @@ install:
 	$(INSTALL_PROG) expunge "$(INSTALL_LIBDIR)/expunge$(EXE)"
 	$(INSTALL_DATA) \
 	   toplevel/topdirs.cmi \
+	   "$(INSTALL_LIBDIR)"
+ifeq "$(INSTALL_SOURCE_ARTIFACTS)" "true"
+	$(INSTALL_DATA) \
 	   toplevel/topdirs.cmt toplevel/topdirs.cmti \
            toplevel/topdirs.mli \
 	   "$(INSTALL_LIBDIR)"
+endif
 	$(MAKE) -C tools install
 ifeq "$(UNIX_OR_WIN32)" "unix" # Install manual pages only on Unix
 	$(MKDIR) "$(INSTALL_MANDIR)/man$(PROGRAMS_MAN_SECTION)"
@@ -651,34 +585,48 @@ ifeq "$(UNIX_OR_WIN32)" "win32"
 	  $(MAKE) install-flexdll; \
 	fi
 endif
-	$(INSTALL_DATA) config/Makefile "$(INSTALL_LIBDIR)/Makefile.config"
+	$(INSTALL_DATA) Makefile.config "$(INSTALL_LIBDIR)/Makefile.config"
+ifeq "$(INSTALL_BYTECODE_PROGRAMS)" "true"
 	if test -f ocamlopt; then $(MAKE) installopt; else \
 	   cd "$(INSTALL_BINDIR)"; \
 	   $(LN) ocamlc.byte$(EXE) ocamlc$(EXE); \
 	   $(LN) ocamllex.byte$(EXE) ocamllex$(EXE); \
 	fi
+else
+	if test -f ocamlopt; then $(MAKE) installopt; fi
+endif
 
 # Installation of the native-code compiler
 .PHONY: installopt
 installopt:
-	$(MAKE) -C asmrun install
+	$(MAKE) -C runtime installopt
+ifeq "$(INSTALL_BYTECODE_PROGRAMS)" "true"
 	$(INSTALL_PROG) ocamlopt "$(INSTALL_BINDIR)/ocamlopt.byte$(EXE)"
+endif
 	$(MAKE) -C stdlib installopt
 	$(INSTALL_DATA) \
 	    middle_end/*.cmi \
+	    "$(INSTALL_COMPLIBDIR)"
+	$(INSTALL_DATA) \
+	    middle_end/base_types/*.cmi \
+	    "$(INSTALL_COMPLIBDIR)"
+	$(INSTALL_DATA) \
+	    asmcomp/*.cmi \
+	    "$(INSTALL_COMPLIBDIR)"
+ifeq "$(INSTALL_SOURCE_ARTIFACTS)" "true"
+	$(INSTALL_DATA) \
 	    middle_end/*.cmt middle_end/*.cmti \
 	    middle_end/*.mli \
 	    "$(INSTALL_COMPLIBDIR)"
 	$(INSTALL_DATA) \
-	    middle_end/base_types/*.cmi \
 	    middle_end/base_types/*.cmt middle_end/base_types/*.cmti \
 	    middle_end/base_types/*.mli \
 	    "$(INSTALL_COMPLIBDIR)"
 	$(INSTALL_DATA) \
-	    asmcomp/*.cmi \
 	    asmcomp/*.cmt asmcomp/*.cmti \
 	    asmcomp/*.mli \
 	    "$(INSTALL_COMPLIBDIR)"
+endif
 	$(INSTALL_DATA) \
 	    compilerlibs/ocamloptcomp.cma $(OPTSTART) \
 	    "$(INSTALL_COMPLIBDIR)"
@@ -688,12 +636,16 @@ installopt:
 	for i in $(OTHERLIBRARIES); do \
 	  $(MAKE) -C otherlibs/$$i installopt || exit $$?; \
 	done
+ifeq "$(INSTALL_BYTECODE_PROGRAMS)" "true"
 	if test -f ocamlopt.opt ; then $(MAKE) installoptopt; else \
 	   cd "$(INSTALL_BINDIR)"; \
 	   $(LN) ocamlc.byte$(EXE) ocamlc$(EXE); \
 	   $(LN) ocamlopt.byte$(EXE) ocamlopt$(EXE); \
 	   $(LN) ocamllex.byte$(EXE) ocamllex$(EXE); \
 	fi
+else
+	if test -f ocamlopt.opt ; then $(MAKE) installoptopt; fi
+endif
 	$(MAKE) -C tools installopt
 	if test -f ocamlopt.opt -a -f flexdll/flexlink.opt ; then \
 	  $(INSTALL_PROG) \
@@ -712,8 +664,8 @@ installoptopt:
 	   $(LN) ocamllex.opt$(EXE) ocamllex$(EXE)
 	$(INSTALL_DATA) \
 	   utils/*.cmx parsing/*.cmx typing/*.cmx bytecomp/*.cmx \
-	   driver/*.cmx asmcomp/*.cmx \
-	  "$(INSTALL_COMPLIBDIR)"
+	   driver/*.cmx asmcomp/*.cmx middle_end/*.cmx \
+	   middle_end/base_types/*.cmx "$(INSTALL_COMPLIBDIR)"
 	$(INSTALL_DATA) \
            compilerlibs/ocamlcommon.cmxa compilerlibs/ocamlcommon.$(A) \
 	   compilerlibs/ocamlbytecomp.cmxa compilerlibs/ocamlbytecomp.$(A) \
@@ -739,17 +691,19 @@ installoptopt:
 # Installation of the *.ml sources of compiler-libs
 .PHONY: install-compiler-sources
 install-compiler-sources:
+ifeq "$(INSTALL_SOURCE_ARTIFACTS)" "true"
 	$(INSTALL_DATA) \
 	   utils/*.ml parsing/*.ml typing/*.ml bytecomp/*.ml driver/*.ml \
 	   toplevel/*.ml middle_end/*.ml middle_end/base_types/*.ml \
 	   asmcomp/*.ml \
 	   "$(INSTALL_COMPLIBDIR)"
+endif
 
 # Run all tests
 
 .PHONY: tests
-tests: opt.opt ocamltest
-	cd testsuite; $(MAKE) clean && $(MAKE) all
+tests:
+	$(MAKE) -C testsuite all
 
 # Make clean in the test suite
 
@@ -788,7 +742,7 @@ partialclean::
 
 # The native-code compiler
 
-compilerlibs/ocamloptcomp.cma: $(MIDDLE_END) $(ASMCOMP)
+compilerlibs/ocamloptcomp.cma: $(OPTCOMP)
 	$(CAMLC) -a -o $@ $^
 
 partialclean::
@@ -845,16 +799,6 @@ natruntop:
 otherlibs/dynlink/dynlink.cmxa: otherlibs/dynlink/natdynlink.ml
 	$(MAKE) -C otherlibs/dynlink allopt
 
-# The parser
-
-parsing/parser.mli parsing/parser.ml: parsing/parser.mly
-	$(CAMLYACC) $(YACCFLAGS) $<
-
-partialclean::
-	rm -f parsing/parser.mli parsing/parser.ml parsing/parser.output
-
-beforedepend:: parsing/parser.mli parsing/parser.ml
-
 # The lexer
 
 parsing/lexer.ml: parsing/lexer.mll
@@ -881,41 +825,35 @@ partialclean::
 
 ocamlc.opt: compilerlibs/ocamlcommon.cmxa compilerlibs/ocamlbytecomp.cmxa \
             $(BYTESTART:.cmo=.cmx)
-	$(CAMLOPT) $(LINKFLAGS) -o $@ $^ -cclib "$(BYTECCLIBS)"
+	$(CAMLOPT_CMD) $(LINKFLAGS) -o $@ $^ -cclib "$(BYTECCLIBS)"
 
 partialclean::
 	rm -f ocamlc.opt
 
 # The native-code compiler compiled with itself
 
-compilerlibs/ocamloptcomp.cmxa: $(MIDDLE_END:.cmo=.cmx) $(ASMCOMP:.cmo=.cmx)
+compilerlibs/ocamloptcomp.cmxa: $(OPTCOMP:.cmo=.cmx)
 	$(CAMLOPT) -a -o $@ $^
 partialclean::
 	rm -f compilerlibs/ocamloptcomp.cmxa compilerlibs/ocamloptcomp.$(A)
 
 ocamlopt.opt: compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
               $(OPTSTART:.cmo=.cmx)
-	$(CAMLOPT) $(LINKFLAGS) -o $@ $^
+	$(CAMLOPT_CMD) $(LINKFLAGS) -o $@ $^
 
 partialclean::
 	rm -f ocamlopt.opt
 
-$(COMMON:.cmo=.cmx) $(BYTECOMP:.cmo=.cmx) $(MIDDLE_END:.cmo=.cmx) \
-$(ASMCOMP:.cmo=.cmx): ocamlopt
+$(COMMON:.cmo=.cmx) $(BYTECOMP:.cmo=.cmx) $(OPTCOMP:.cmo=.cmx): ocamlopt
 
 # The predefined exceptions and primitives
 
-byterun/primitives:
-	$(MAKE) -C byterun primitives
+runtime/primitives:
+	$(MAKE) -C runtime primitives
 
-bytecomp/runtimedef.ml: byterun/primitives byterun/caml/fail.h
-	(echo 'let builtin_exceptions = [|'; \
-	 cat byterun/caml/fail.h | tr -d '\r' | \
-	 sed -n -e 's|.*/\* \("[A-Za-z_]*"\) \*/$$|  \1;|p'; \
-	 echo '|]'; \
-	 echo 'let builtin_primitives = [|'; \
-	 sed -e 's/.*/  "&";/' byterun/primitives; \
-	 echo '|]') > $@
+bytecomp/runtimedef.ml: bytecomp/generate_runtimedef.sh runtime/caml/fail.h \
+    runtime/primitives
+	$^ > $@
 
 partialclean::
 	rm -f bytecomp/runtimedef.ml
@@ -973,19 +911,18 @@ runtime: stdlib/libcamlrun.$(A)
 
 .PHONY: makeruntime
 makeruntime:
-	$(MAKE) -C byterun $(BOOT_FLEXLINK_CMD) all
-byterun/libcamlrun.$(A): makeruntime ;
-stdlib/libcamlrun.$(A): byterun/libcamlrun.$(A)
-	cd stdlib; $(LN) ../byterun/libcamlrun.$(A) .
+	$(MAKE) -C runtime $(BOOT_FLEXLINK_CMD) all
+runtime/libcamlrun.$(A): makeruntime ;
+stdlib/libcamlrun.$(A): runtime/libcamlrun.$(A)
+	cd stdlib; $(LN) ../runtime/libcamlrun.$(A) .
 clean::
-	$(MAKE) -C byterun clean
+	$(MAKE) -C runtime clean
 	rm -f stdlib/libcamlrun.$(A)
 
 otherlibs_all := bigarray dynlink graph raw_spacetime_lib \
   str systhreads threads unix win32graph win32unix
-subdirs := asmrun byterun debugger lex ocamldoc ocamltest stdlib tools \
+subdirs := debugger lex ocamldoc ocamltest runtime stdlib tools \
   $(addprefix otherlibs/, $(otherlibs_all)) \
-  ocamldoc/stdlib_non_prefixed
 
 .PHONY: alldepend
 ifeq "$(TOOLCHAIN)" "msvc"
@@ -1005,12 +942,11 @@ runtimeopt: stdlib/libasmrun.$(A)
 
 .PHONY: makeruntimeopt
 makeruntimeopt:
-	$(MAKE) -C asmrun $(BOOT_FLEXLINK_CMD) all
-asmrun/libasmrun.$(A): makeruntimeopt ;
-stdlib/libasmrun.$(A): asmrun/libasmrun.$(A)
+	$(MAKE) -C runtime $(BOOT_FLEXLINK_CMD) allopt
+runtime/libasmrun.$(A): makeruntimeopt ;
+stdlib/libasmrun.$(A): runtime/libasmrun.$(A)
 	cp $< $@
 clean::
-	$(MAKE) -C asmrun clean
 	rm -f stdlib/libasmrun.$(A)
 
 # The standard library
@@ -1021,7 +957,7 @@ library: ocamlc
 
 .PHONY: library-cross
 library-cross:
-	$(MAKE) -C stdlib $(BOOT_FLEXLINK_CMD) CAMLRUN=../byterun/ocamlrun all
+	$(MAKE) -C stdlib $(BOOT_FLEXLINK_CMD) CAMLRUN=../runtime/ocamlrun all
 
 .PHONY: libraryopt
 libraryopt:
@@ -1050,6 +986,46 @@ ocamlyacc:
 clean::
 	$(MAKE) -C yacc clean
 
+# The Menhir-generated parser
+
+# In order to avoid a build-time dependency on Menhir,
+# we store the result of the parser generator (which
+# are OCaml source files) and Menhir's runtime libraries
+# (that the parser files rely on) in boot/.
+
+# The rules below do not depend on Menhir being available,
+# they just build the parser from boot/.
+
+# See Makefile.menhir for the rules to rebuild the parser and update
+# boot/, which require Menhir. The targets in Makefile.menhir
+# (also included here for convenience) must be used after any
+# modification of parser.mly.
+include Makefile.menhir
+
+# To avoid module-name conflicts with compiler-lib users that link
+# with their code with their own MenhirLib module (possibly with
+# a different Menhir version), we rename MenhirLib into
+# CamlinternalMenhirlib -- and replace the module occurrences in the
+# generated parser.ml.
+
+parsing/camlinternalMenhirLib.ml: boot/menhir/menhirLib.ml
+	cp $< $@
+parsing/camlinternalMenhirLib.mli: boot/menhir/menhirLib.mli
+	cp $< $@
+
+# Copy parsing/parser.ml from boot/
+
+parsing/parser.ml: boot/menhir/parser.ml parsing/parser.mly \
+  tools/check-parser-uptodate-or-warn.sh
+	@tools/check-parser-uptodate-or-warn.sh
+	cat $< | sed "s/MenhirLib/CamlinternalMenhirLib/g" > $@
+parsing/parser.mli: boot/menhir/parser.mli
+	cat $< | sed "s/MenhirLib/CamlinternalMenhirLib/g" > $@
+
+
+partialclean:: partialclean-menhir
+
+
 # OCamldoc
 
 .PHONY: ocamldoc
@@ -1084,25 +1060,17 @@ partialclean::
 
 .PHONY: otherlibraries
 otherlibraries: ocamltools
-	for i in $(OTHERLIBRARIES); do \
-	  ($(MAKE) -C otherlibs/$$i all) || exit $$?; \
-	done
+	$(MAKE) -C otherlibs all
 
 .PHONY: otherlibrariesopt
 otherlibrariesopt:
-	for i in $(OTHERLIBRARIES); do \
-	  ($(MAKE) -C otherlibs/$$i allopt) || exit $$?; \
-	done
+	$(MAKE) -C otherlibs allopt
 
 partialclean::
-	for i in $(OTHERLIBRARIES); do \
-	  ($(MAKE) -C otherlibs/$$i partialclean); \
-	done
+	$(MAKE) -C otherlibs partialclean
 
 clean::
-	for i in $(OTHERLIBRARIES); do \
-	  ($(MAKE) -C otherlibs/$$i clean); \
-	done
+	$(MAKE) -C otherlibs clean
 
 # The replay debugger
 
@@ -1135,11 +1103,6 @@ lintapidiff:
 	    grep -Ev internal\|obj\|spacetime\|stdLabels\|moreLabels |\
 	    tools/lintapidiff.opt $(VERSIONS)
 
-# Make clean in the test suite
-
-clean::
-	cd testsuite; $(MAKE) clean
-
 # The middle end (whose .cma library is currently only used for linking
 # the "ocamlobjinfo" program, since we cannot depend on the whole native code
 # compiler for "make world" and the list of dependencies for
@@ -1157,7 +1120,7 @@ partialclean::
 # Tools
 
 .PHONY: ocamltools
-ocamltools: ocamlc ocamlyacc ocamllex asmcomp/cmx_format.cmi \
+ocamltools: ocamlc ocamllex asmcomp/cmx_format.cmi \
             asmcomp/printclambda.cmo compilerlibs/ocamlmiddleend.cma \
             asmcomp/export_info.cmo
 	$(MAKE) -C tools all
@@ -1167,7 +1130,7 @@ ocamltoolsopt: ocamlopt
 	$(MAKE) -C tools opt
 
 .PHONY: ocamltoolsopt.opt
-ocamltoolsopt.opt: ocamlc.opt ocamlyacc ocamllex.opt asmcomp/cmx_format.cmi \
+ocamltoolsopt.opt: ocamlc.opt ocamllex.opt asmcomp/cmx_format.cmi \
                    asmcomp/printclambda.cmx compilerlibs/ocamlmiddleend.cmxa \
                    asmcomp/export_info.cmx
 	$(MAKE) -C tools opt.opt
@@ -1195,7 +1158,7 @@ check_arch:
 
 .PHONY: check_all_arches
 check_all_arches:
-ifneq ($(shell grep -E '^\#define ARCH_SIXTYFOUR$$' byterun/caml/m.h 2> /dev/null),)
+ifeq ($(ARCH64),true)
 	@STATUS=0; \
 	 for i in $(ARCHES); do \
 	   $(MAKE) --no-print-directory check_arch ARCH=$$i || STATUS=1; \
@@ -1209,33 +1172,73 @@ endif
 
 DYNLINK_DIR=otherlibs/dynlink
 
-driver/compdynlink.mlbyte: $(DYNLINK_DIR)/dynlink.ml driver/compdynlink.mli
-	grep -v 'REMOVE_ME for ../../debugger/dynlink.ml' \
-	     $(DYNLINK_DIR)/dynlink.ml >driver/compdynlink.mlbyte
+driver/compdynlink.mlbyte: $(DYNLINK_DIR)/dynlink.ml driver/compdynlink.mli \
+    driver/compify_dynlink.sh
+	driver/compify_dynlink.sh $< $@
+
+driver/compdynlink_common.ml: $(DYNLINK_DIR)/dynlink_common.ml \
+    driver/compify_dynlink.sh
+	driver/compify_dynlink.sh $< $@
+
+driver/compdynlink_common.mli: $(DYNLINK_DIR)/dynlink_common.mli \
+    driver/compify_dynlink.sh
+	driver/compify_dynlink.sh $< $@
+
+driver/compdynlink_types.mli: $(DYNLINK_DIR)/dynlink_types.mli
+	cp $(DYNLINK_DIR)/dynlink_types.mli driver/compdynlink_types.mli
+
+driver/compdynlink_types.ml: $(DYNLINK_DIR)/dynlink_types.ml
+	cp $(DYNLINK_DIR)/dynlink_types.ml driver/compdynlink_types.ml
+
+driver/compdynlink_platform_intf.ml: $(DYNLINK_DIR)/dynlink_platform_intf.ml \
+    driver/compify_dynlink.sh
+	driver/compify_dynlink.sh $< $@
 
 ifeq ($(NATDYNLINK),true)
 driver/compdynlink.mlopt: $(DYNLINK_DIR)/natdynlink.ml driver/compdynlink.mli
-	cp $(DYNLINK_DIR)/natdynlink.ml driver/compdynlink.mlopt
+	cat $(DYNLINK_DIR)/natdynlink.ml | \
+	  sed 's/Dynlink_/Compdynlink_/g' \
+	  > driver/compdynlink.mlopt
 else
-driver/compdynlink.mlopt: driver/compdynlink.mlno driver/compdynlink.mli
-	cp driver/compdynlink.mlno driver/compdynlink.mlopt
+driver/compdynlink.mlopt: $(DYNLINK_DIR)/nodynlink.ml driver/compdynlink.mli
+	cat $(DYNLINK_DIR)/nodynlink.ml | \
+	  sed 's/Dynlink_/Compdynlink_/g' \
+	  > driver/compdynlink.mlopt
 endif
 
-driver/compdynlink.mli: $(DYNLINK_DIR)/dynlink.mli
-	cp $(DYNLINK_DIR)/dynlink.mli driver/compdynlink.mli
+driver/compdynlink.mli: $(DYNLINK_DIR)/dynlink.mli \
+    driver/compify_dynlink.sh
+	driver/compify_dynlink.sh $< $@
 
-driver/compdynlink.cmo: driver/compdynlink.mlbyte driver/compdynlink.cmi
+# See comment in otherlibs/dynlink/Makefile about these two rules.
+driver/compdynlink_platform_intf.mli: driver/compdynlink_platform_intf.ml
+	cp $< $@
+
+driver/compdynlink.cmo: driver/compdynlink.mlbyte
 	$(CAMLC) $(COMPFLAGS) -c -impl $<
 
-driver/compdynlink.cmx: driver/compdynlink.mlopt driver/compdynlink.cmi
+driver/compdynlink.cmx: driver/compdynlink.mlopt
 	$(CAMLOPT) $(COMPFLAGS) -c -impl $<
 
-beforedepend:: driver/compdynlink.mlbyte driver/compdynlink.mlopt \
-               driver/compdynlink.mli
+beforedepend:: driver/compdynlink.mlbyte \
+               driver/compdynlink.mlopt \
+               driver/compdynlink_platform_intf.ml \
+               driver/compdynlink_platform_intf.mli \
+               driver/compdynlink_types.ml \
+               driver/compdynlink_types.mli \
+               driver/compdynlink.mli \
+               driver/compdynlink_common.ml \
+               driver/compdynlink_common.mli
 partialclean::
 	rm -f driver/compdynlink.mlbyte
-	rm -f driver/compdynlink.mli
 	rm -f driver/compdynlink.mlopt
+	rm -f driver/compdynlink.mli
+	rm -f driver/compdynlink_platform_intf.ml
+	rm -f driver/compdynlink_platform_intf.mli
+	rm -f driver/compdynlink_common.ml
+	rm -f driver/compdynlink_common.mli
+	rm -f driver/compdynlink_types.mli
+	rm -f driver/compdynlink_types.ml
 
 # The native toplevel
 
@@ -1256,7 +1259,7 @@ ocamlnat$(EXE): compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
     compilerlibs/ocamlbytecomp.cmxa \
     compilerlibs/ocamlopttoplevel.cmxa \
     $(OPTTOPLEVELSTART:.cmo=.cmx)
-	$(CAMLOPT) $(LINKFLAGS) -linkall -o $@ $^
+	$(CAMLOPT_CMD) $(LINKFLAGS) -linkall -o $@ $^
 
 partialclean::
 	rm -f ocamlnat$(EXE)
@@ -1265,8 +1268,8 @@ toplevel/opttoploop.cmx: otherlibs/dynlink/dynlink.cmxa
 
 # The numeric opcodes
 
-bytecomp/opcodes.ml: byterun/caml/instruct.h tools/make_opcodes
-	$(CAMLRUN) tools/make_opcodes -opcodes < $< > $@
+bytecomp/opcodes.ml: runtime/caml/instruct.h tools/make_opcodes
+	runtime/ocamlrun tools/make_opcodes -opcodes < $< > $@
 
 tools/make_opcodes: tools/make_opcodes.mll
 	$(MAKE) -C tools make_opcodes
@@ -1276,6 +1279,35 @@ partialclean::
 
 beforedepend:: bytecomp/opcodes.ml
 
+# Testing the parser -- see parsing/HACKING.adoc
+
+SOURCE_FILES=$(shell git ls-files '*.ml' '*.mli' | grep -v boot/menhir/parser)
+
+AST_FILES=$(addsuffix .ast,$(SOURCE_FILES))
+
+build-all-asts: $(AST_FILES)
+
+CAMLC_DPARSETREE := \
+	$(CAMLRUN) ./ocamlc -nostdlib -nopervasives \
+	  -stop-after parsing -dparsetree
+
+%.ml.ast: %.ml ocamlc
+	$(CAMLC_DPARSETREE) $< 2> $@ || exit 0
+# `|| exit 0` : some source files will fail to parse
+# (for example, they are meant as toplevel scripts
+# rather than source files, or are parse-error tests),
+# we ignore the failure in that case
+
+%.mli.ast: %.mli ocamlc
+	$(CAMLC_DPARSETREE) $< 2> $@ || exit 0
+
+.PHONY: list-all-asts
+list-all-asts:
+	@for f in $(AST_FILES); do echo "'$$f'"; done
+
+partialclean::
+	rm -f $(AST_FILES)
+
 # Default rules
 
 .SUFFIXES: .ml .mli .cmo .cmi .cmx
@@ -1301,18 +1333,19 @@ partialclean::
 depend: beforedepend
 	(for d in utils parsing typing bytecomp asmcomp middle_end \
 	 middle_end/base_types asmcomp/debug driver toplevel; \
-	 do $(CAMLDEP) -slash $(DEPFLAGS) $$d/*.mli $$d/*.ml || exit; \
+	 do $(CAMLDEP) $(DEPFLAGS) $(DEPINCLUDES) $$d/*.mli $$d/*.ml || exit; \
 	 done) > .depend
-	$(CAMLDEP) -slash $(DEPFLAGS) -native \
+	$(CAMLDEP) $(DEPFLAGS) $(DEPINCLUDES) -native \
 		-impl driver/compdynlink.mlopt >> .depend
-	$(CAMLDEP) -slash $(DEPFLAGS) -bytecode \
+	$(CAMLDEP) $(DEPFLAGS) $(DEPINCLUDES) -bytecode \
 		-impl driver/compdynlink.mlbyte >> .depend
 
 .PHONY: distclean
 distclean: clean
 	rm -f boot/ocamlrun boot/ocamlrun$(EXE) boot/camlheader \
-	      boot/ocamlyacc boot/*.cm* boot/libcamlrun.$(A)
-	rm -f config/Makefile byterun/caml/m.h byterun/caml/s.h
+	      boot/*.cm* boot/libcamlrun.$(A)
+	rm -f Makefile.config runtime/caml/m.h runtime/caml/s.h
+	rm -f Makefile.common config.log config.status libtool
 	rm -f tools/*.bak
 	rm -f ocaml ocamlc
 	rm -f testsuite/_log*
diff --git a/Makefile.common b/Makefile.common
deleted file mode 100644
index cd9f676b..00000000
--- a/Makefile.common
+++ /dev/null
@@ -1,30 +0,0 @@
-#**************************************************************************
-#*                                                                        *
-#*                                 OCaml                                  *
-#*                                                                        *
-#*            Gabriel Scherer, projet Parsifal, INRIA Saclay              *
-#*                                                                        *
-#*   Copyright 2018 Institut National de Recherche en Informatique et     *
-#*     en Automatique.                                                    *
-#*                                                                        *
-#*   All rights reserved.  This file is distributed under the terms of    *
-#*   the GNU Lesser General Public License version 2.1, with the          *
-#*   special exception on linking described in the file LICENSE.          *
-#*                                                                        *
-#**************************************************************************
-
-# This makefile contains common definitions shared by other Makefiles
-# We assume that config/Makefile has already been included
-
-INSTALL ?= install
-INSTALL_DATA ?= $(INSTALL) -m u=rw,g=rw,o=r
-INSTALL_PROG ?= $(INSTALL) -m u=rwx,g=rwx,o=rx
-
-# note: these are defined by lazy expansions
-# as some parts of the makefiles change BINDIR, etc.
-# and expect INSTALL_BINDIR, etc. to stay in synch
-# (see `shellquote` in tools/Makefile)
-INSTALL_BINDIR = $(DESTDIR)$(BINDIR)
-INSTALL_LIBDIR = $(DESTDIR)$(LIBDIR)
-INSTALL_STUBLIBDIR = $(DESTDIR)$(STUBLIBDIR)
-INSTALL_MANDIR = $(DESTDIR)$(MANDIR)
diff --git a/Makefile.common.in b/Makefile.common.in
new file mode 100644
index 00000000..585aab9d
--- /dev/null
+++ b/Makefile.common.in
@@ -0,0 +1,53 @@
+#**************************************************************************
+#*                                                                        *
+#*                                 OCaml                                  *
+#*                                                                        *
+#*            Gabriel Scherer, projet Parsifal, INRIA Saclay              *
+#*                                                                        *
+#*   Copyright 2018 Institut National de Recherche en Informatique et     *
+#*     en Automatique.                                                    *
+#*                                                                        *
+#*   All rights reserved.  This file is distributed under the terms of    *
+#*   the GNU Lesser General Public License version 2.1, with the          *
+#*   special exception on linking described in the file LICENSE.          *
+#*                                                                        *
+#**************************************************************************
+
+# This makefile contains common definitions shared by other Makefiles
+# We assume that Makefile.config has already been included
+
+INSTALL ?= @INSTALL@
+INSTALL_DATA ?= $(INSTALL) -m u=rw,g=rw,o=r
+INSTALL_PROG ?= $(INSTALL) -m u=rwx,g=rwx,o=rx
+
+# note: these are defined by lazy expansions
+# as some parts of the makefiles change BINDIR, etc.
+# and expect INSTALL_BINDIR, etc. to stay in synch
+# (see `shellquote` in tools/Makefile)
+INSTALL_BINDIR = $(DESTDIR)$(BINDIR)
+INSTALL_LIBDIR = $(DESTDIR)$(LIBDIR)
+INSTALL_STUBLIBDIR = $(DESTDIR)$(STUBLIBDIR)
+INSTALL_MANDIR = $(DESTDIR)$(MANDIR)
+
+ifeq "$(UNIX_OR_WIN32)" "win32"
+FLEXDLL_SUBMODULE_PRESENT := $(wildcard $(ROOTDIR)/flexdll/Makefile)
+else
+FLEXDLL_SUBMODULE_PRESENT =
+endif
+
+ifeq "$(FLEXDLL_SUBMODULE_PRESENT)" ""
+  FLEXLINK_ENV =
+  CAMLOPT_CMD = $(CAMLOPT)
+  OCAMLOPT_CMD = $(OCAMLOPT)
+  MKLIB_CMD = $(MKLIB)
+  ocamlc_cmd = $(ocamlc)
+  ocamlopt_cmd = $(ocamlopt)
+else
+  FLEXLINK_ENV = \
+    OCAML_FLEXLINK="$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/flexdll/flexlink.exe"
+  CAMLOPT_CMD = $(FLEXLINK_ENV) $(CAMLOPT)
+  OCAMLOPT_CMD = $(FLEXLINK_ENV) $(OCAMLOPT)
+  MKLIB_CMD = $(FLEXLINK_ENV) $(MKLIB)
+  ocamlc_cmd = $(FLEXLINK_ENV) $(ocamlc)
+  ocamlopt_cmd = $(FLEXLINK_ENV) $(ocamlopt)
+endif
diff --git a/Makefile.config.in b/Makefile.config.in
new file mode 100644
index 00000000..391e469a
--- /dev/null
+++ b/Makefile.config.in
@@ -0,0 +1,290 @@
+# @configure_input@
+
+#**************************************************************************
+#*                                                                        *
+#*                                 OCaml                                  *
+#*                                                                        *
+#*            Xavier Leroy, projet Cristal, INRIA Rocquencourt            *
+#*                                                                        *
+#*   Copyright 1999 Institut National de Recherche en Informatique et     *
+#*     en Automatique.                                                    *
+#*                                                                        *
+#*   All rights reserved.  This file is distributed under the terms of    *
+#*   the GNU Lesser General Public License version 2.1, with the          *
+#*   special exception on linking described in the file LICENSE.          *
+#*                                                                        *
+#**************************************************************************
+
+# The configuration Makefile
+
+## The EMPTY variable, used in other definitions
+EMPTY=
+
+## Arguments passed to the configure script
+
+CONFIGURE_ARGS=@CONFIGURE_ARGS@
+
+## Top build directory
+
+TOP_BUILDDIR = @top_builddir@
+
+## Installation directories
+
+prefix=@prefix@
+
+exec_prefix=@exec_prefix@
+
+### Where to install the binaries
+BINDIR=@bindir@
+
+datarootdir=@datarootdir@
+
+### Where to install the standard library
+LIBDIR=@libdir@
+
+### Where to install the stub code for the standard library
+STUBLIBDIR=@libdir@/stublibs
+
+### Where to install the man pages
+# Man pages for commands go in $(MANDIR)/man$(PROGRAMS_MAN_SECTION)
+# Man pages for the library go in $(MANDIR)/man/man$(LIBRARIES_MAN_SECTION)
+MANDIR=@mandir@
+PROGRAMS_MAN_SECTION=@programs_man_section@
+LIBRARIES_MAN_SECTION=@libraries_man_section@
+
+### Do #! scripts work on your system?
+### Beware: on some systems (e.g. SunOS 4), this will work only if
+### the string "#!$(BINDIR)/ocamlrun" is less than 32 characters long.
+### In doubt, set HASHBANGSCRIPTS to false.
+HASHBANGSCRIPTS=@hashbangscripts@
+
+### Path to the libtool script
+LIBTOOL = $(TOP_BUILDDIR)/libtool
+
+### Which C compiler to use
+TOOLPREF=@ac_tool_prefix@
+CC=@CC@
+
+CC_HAS_DEBUG_PREFIX_MAP=@cc_has_debug_prefix_map@
+AS_HAS_DEBUG_PREFIX_MAP=@as_has_debug_prefix_map@
+
+### Additional link-time options
+# To support dynamic loading of shared libraries (they need to look at
+# our own symbols):
+OC_LDFLAGS=@oc_ldflags@
+
+### How to invoke the C preprocessor through the C compiler
+CPP=@CPP@
+
+### How to invoke ranlib
+RANLIB=@RANLIB@
+RANLIBCMD=@RANLIBCMD@
+
+### How to invoke ar
+ARCMD=@AR@
+
+### Extension of object files
+O=@OBJEXT@
+EXT_OBJ=.@OBJEXT@
+
+### How to tell the C compiler to output an object file
+OUTPUTOBJ=@outputobj@
+
+### Extension of static libraries
+A=@libext@
+EXT_LIB=.@libext@
+
+### Extension of assembler files
+S=@S@
+EXT_ASM=.@S@
+
+### Extension for shared libraries
+SO=@SO@
+EXT_DLL=.@SO@
+
+SHAREDLIB_CFLAGS=@sharedlib_cflags@
+
+# Compile-time option to $(CC) to add a directory to be searched
+# at run-time for shared libraries
+RPATH=@rpath@
+
+############# Configuration for the native-code compiler
+
+### Name of architecture for the native-code compiler
+### Currently supported:
+###
+### i386        Intel Pentium PCs under Linux, *BSD*, NextStep
+### power       Macintosh under Mac OS X and Linux
+### arm         ARM under Linux
+###
+### Set ARCH=none if your machine is not supported
+ARCH=@arch@
+
+# Whether the architecture has 64 bits
+ARCH64=@arch64@
+
+### Name of architecture model for the native-code compiler.
+### Some architectures come in several slightly different flavors
+### that share a common code generator. This variable tailors the
+### behavior of the code generator to the particular flavor used.
+### Currently needed only if ARCH=power; leave MODEL=default for
+### other architectures.
+### If ARCH=power: set MODEL=ppc
+### For other architectures: leave MODEL=default
+###
+MODEL=@model@
+
+### Name of operating system family for the native-code compiler.
+SYSTEM=@system@
+
+### Command and flags to use for assembling ocamlopt-generated code
+ASM=@AS@
+
+### Command and flags to use for assembling .S files (often with preprocessing)
+ASPP=@ASPP@
+
+### Set to "true" to install ".byte" executables (ocamlc.byte, etc.)
+INSTALL_BYTECODE_PROGRAMS=@install_bytecode_programs@
+
+### Extra flags to use for assembling .S files in profiling mode
+ASPPPROFFLAGS=@asppprofflags@
+
+### true if profiling with gprof is supported, false otherwise
+PROFILING=@profiling@
+
+### Option to give to the C compiler for profiling
+CC_PROFILE=@cc_profile@
+
+############# Configuration for the contributed libraries
+
+### Which libraries to compile and install
+# Currently available:
+#       unix            Unix system calls
+#       str             Regular expressions and high-level string processing
+#       threads         Lightweight concurrent processes
+#       systhreads      Same as threads, requires POSIX threads
+#       graph           Portable drawing primitives for X11
+#       dynlink         Dynamic linking of bytecode
+#       bigarray        Large, multidimensional numerical arrays
+OTHERLIBRARIES=@otherlibraries@
+
+### Link-time options to ocamlc or ocamlopt for linking with POSIX threads
+# Needed for the "systhreads" package
+PTHREAD_LINK=@pthread_link@
+PTHREAD_CAML_LINK=$(addprefix -cclib ,$(PTHREAD_LINK))
+
+### -I options for finding the X11/*.h includes
+# Needed for the "graph" package
+X11_INCDDIR=@x_includes@
+X11_INCLUDES=$(addprefix -I,$(X11_INCDDIR))
+
+### Link-time options to ocamlc or ocamlopt for linking with X11 libraries
+# Needed for the "graph" package
+X11_LINK=@x_libraries@
+
+UNIX_OR_WIN32=@unix_or_win32@
+UNIXLIB=@unixlib@
+GRAPHLIB=@graphlib@
+LIBBFD_LINK=@libbfd_link@
+LIBBFD_INCLUDE=@libbfd_include@
+INSTALL_SOURCE_ARTIFACTS=@install_source_artifacts@
+
+OC_CFLAGS=@oc_cflags@
+OC_CPPFLAGS=@oc_cppflags@
+OCAMLC_CFLAGS=@ocamlc_cflags@
+
+OCAMLC_CPPFLAGS=@ocamlc_cppflags@
+BYTECCLIBS=@bytecclibs@
+EXE=@exeext@
+OUTPUTEXE=@outputexe@
+SUPPORTS_SHARED_LIBRARIES=@supports_shared_libraries@
+MKSHAREDLIBRPATH=@mksharedlibrpath@
+DYNLINKOPTS=@DLLIBS@
+NATDYNLINK=@natdynlink@
+NATDYNLINKOPTS=@natdynlinkopts@
+SYSLIB=@syslib@
+MKLIB=@mklib@
+OCAMLOPT_CFLAGS=@ocamlopt_cflags@
+OCAMLOPT_CPPFLAGS=@ocamlopt_cppflags@
+NATIVECCLIBS=@nativecclibs@
+SYSTHREAD_SUPPORT=@systhread_support@
+PACKLD=@PACKLD@
+IFLEXDIR=@iflexdir@
+EXTRALIBS=@extralibs@
+CCOMPTYPE=@ccomptype@
+TOOLCHAIN=@toolchain@
+CMXS=@cmxs@
+
+# On Windows, MKDLL, MKEXE and MKMAINDLL must ultimately be equivalent to
+#   $(FLEXLINK_CMD) $(FLEXLINK_FLAGS) [-exe|-maindll]
+# or OCAML_FLEXLINK overriding will not work (see utils/config.mlp)
+
+MKEXE=@mkexe@
+MKDLL=@mksharedlib@
+MKMAINDLL=@mkmaindll@
+
+MKEXEDEBUGFLAG=@mkexedebugflag@
+RUNTIMED=@debug_runtime@
+RUNTIMEI=@instrumented_runtime@
+WITH_DEBUGGER=@with_debugger@
+WITH_CAMLTEX=@with_camltex@
+WITH_OCAMLDOC=@ocamldoc@
+ASM_CFI_SUPPORTED=@asm_cfi_supported@
+WITH_FRAME_POINTERS=@frame_pointers@
+WITH_SPACETIME=@spacetime@
+ENABLE_CALL_COUNTS=@call_counts@
+WITH_PROFINFO=@profinfo@
+PROFINFO_WIDTH=@profinfo_width@
+LIBUNWIND_AVAILABLE=@libunwind_available@
+LIBUNWIND_INCLUDE_FLAGS=@libunwind_include_flags@
+LIBUNWIND_LINK_FLAGS=@libunwind_link_flags@
+WITH_FPIC=@fpic@
+TARGET=@target@
+HOST=@host@
+FLAMBDA=@flambda@
+WITH_FLAMBDA_INVARIANTS=@flambda_invariants@
+FORCE_SAFE_STRING=@force_safe_string@
+DEFAULT_SAFE_STRING=@default_safe_string@
+WINDOWS_UNICODE=@windows_unicode@
+AFL_INSTRUMENT=@afl@
+MAX_TESTSUITE_DIR_RETRIES=@max_testsuite_dir_retries@
+FLAT_FLOAT_ARRAY=@flat_float_array@
+AWK=@AWK@
+
+# The following variables were defined only in the config/Makefile.* files.
+# They were not defined by the configure script used on Unix systems,
+# so we also make sure to provide them only under Windows
+# User code should absolutely not rely on their presence because
+# in the future their definition may be moved to a more private part of
+# the compiler's build system
+ifeq "$(UNIX_OR_WIN32)" "win32"
+  DISTRIB=$(prefix)
+  OTOPDIR=$(WINTOPDIR)
+  CTOPDIR=$(WINTOPDIR)
+  CYGPATH=cygpath -m
+  DIFF=/usr/bin/diff -q --strip-trailing-cr
+  FIND=/usr/bin/find
+  SORT=/usr/bin/sort
+  SET_LD_PATH=PATH="$(PATH):$(LD_PATH)"
+  FLEXLINK_CMD=flexlink
+  MKEXE_ANSI=$(FLEXLINK) -exe
+  FLEXDLL_CHAIN=@flexdll_chain@
+  # FLEXLINK_FLAGS must be safe to insert in an OCaml string
+  #   (see ocamlmklibconfig.ml in tools/Makefile)
+  FLEXLINK_FLAGS=@flexlink_flags@
+  FLEXLINK=$(FLEXLINK_CMD) $(FLEXLINK_FLAGS)
+
+  ### Native command to build ocamlrun.exe
+
+  ifeq "$(TOOLCHAIN)" "mingw"
+    MKEXE_BOOT=$(CC) $(OC_CFLAGS) $(OC_LDFLAGS) $(OUTPUTEXE)$(1) $(2)
+  endif # ifeq "$(TOOLCHAIN)" "mingw"
+
+  ifeq "$(TOOLCHAIN)" "msvc"
+    MERGEMANIFESTEXE=test ! -f $(1).manifest \
+	           || mt -nologo -outputresource:$(1) -manifest $(1).manifest \
+	           && rm -f $(1).manifest
+    MKEXE_BOOT=$(CC) $(OC_CFLAGS) $(OUTPUTEXE)$(1) $(2) \
+      /link /subsystem:console $(OC_LDFLAGS) && ($(MERGEMANIFESTEXE))
+  endif # ifeq "$(TOOLCHAIN)" "msvc"
+endif # ifeq "$(UNIX_OR_WIN32)" "win32"
diff --git a/Makefile.menhir b/Makefile.menhir
new file mode 100644
index 00000000..c2068d23
--- /dev/null
+++ b/Makefile.menhir
@@ -0,0 +1,163 @@
+#**************************************************************************
+#*                                                                        *
+#*                                 OCaml                                  *
+#*                                                                        *
+#*            Gabriel Scherer, projet Parsifal, INRIA Saclay              *
+#*                                                                        *
+#*   Copyright 2018 Institut National de Recherche en Informatique et     *
+#*     en Automatique.                                                    *
+#*                                                                        *
+#*   All rights reserved.  This file is distributed under the terms of    *
+#*   the GNU Lesser General Public License version 2.1, with the          *
+#*   special exception on linking described in the file LICENSE.          *
+#*                                                                        *
+#**************************************************************************
+
+# The rules in this Makefile use Menhir to rebuild the OCaml compiler
+# parser. They are included in the main Makefile, so should be invoked
+# directly, for example 'make promote-menhir'. They must be called
+# after any modification to parsing/parser.mly, for the modification
+# to affect the parser linked in the produced compiler:
+#
+# - promote-menhir builds the parser from parser.mly and stores it in
+#   the boot/ directory, so that future builds of the compiler use the
+#   updated result. Use it to make permanent changes to the compiler
+#   parser.
+#
+# - demote-menhir undoes the effect of promote-menhir. The files in
+#   the boot/ directory that are affected by promote-menhir and are
+#   under version control are restored to their normal state (HEAD).
+#
+# - test-menhir builds the parser from parser.mly without storing it
+#   in the boot/ directory, and only checks that the generated parser
+#   builds correctly. Use it to quickly check if a parser.mly change
+#   breaks the build. If you want to test a compiler produced with
+#   the new parser, you must use promote-menhir instead.
+#   (Using this rule requires a partial compiler build as obtained
+#    by 'make core' or 'make world'.)
+#
+# - clean-menhir removes the files generated by Menhir from parsing/,
+#   keeping only the reference sources for the grammar.
+#
+# - depend-menhir updates the dependency information for the
+#   Menhir-generated parser, which is versioned in the OCaml repository
+#   like all other .depend files. It should be used when the dependencies
+#   (of the OCaml code in the grammar semantic actions) change.
+
+MENHIR ?= menhir
+
+## Unused tokens
+
+# tokens COMMENT, DOCSTRING and EOL are produced by special lexer
+# modes used by other consumers than the parser.
+
+# GREATERBRACKET ">]" was added by the parser by symmetry with "[<"
+# (which is used in polymorphic variant), but is not currently used by
+# the grammar.
+
+unused_tokens := COMMENT DOCSTRING EOL GREATERRBRACKET
+
+## Menhir compilation flags
+
+MENHIRFLAGS := --explain --dump --ocamlc "$(CAMLC) $(COMPFLAGS)" --infer \
+	--lalr --strict --table -lg 1 -la 1 \
+        $(addprefix --unused-token ,$(unused_tokens)) --fixed-exception
+
+## promote-menhir
+
+.PHONY: promote-menhir
+promote-menhir: parsing/parser.mly
+	@ $(MAKE) import-menhirLib
+	$(MENHIR) $(MENHIRFLAGS) parsing/parser.mly
+# The generated parser.ml may contain lexer directives containing
+# the absolute path to Menhir's standard library on the promoter's machine.
+# This is benign but will generate pointless churn if another developer
+# rebuilds the same grammar (from the same Menhir version).
+	@ for f in $(addprefix parser.,ml mli) ; do \
+	  sed \
+	    's,^#\(.*\)"[^"]*/menhir/standard.mly",#\1"menhir/standard.mly",g' \
+	    parsing/$$f \
+	    > boot/menhir/$$f; \
+	  rm parsing/$$f; \
+	done
+
+# The import-menhirLib invocation in promote-menhir ensures that each
+# update of the boot/ parser is paired with an update of the imported
+# menhirLib; otherwise it would be easy to generate a parser and keep
+# an incompatible version of menhirLib, which would fail at
+# compile-time.
+
+.PHONY: import-menhirLib
+import-menhirLib:
+	@ mkdir -p boot/menhir
+	@ cp \
+           $(addprefix `$(MENHIR) --suggest-menhirLib`/menhirLib.,ml mli) \
+           boot/menhir
+
+
+## demote-menhir
+
+DEMOTE:=menhirLib.ml menhirLib.mli parser.ml parser.mli
+
+.PHONY: demote-menhir
+demote-menhir:
+	git checkout HEAD -- $(addprefix boot/menhir/,$(DEMOTE))
+
+## test-menhir
+
+# This rule assumes that the `parsing/` sources and its dependencies
+# have already been compiled; 'make core' suffices to be in that
+# state. We don't make 'core' an explicit dependency, as building
+# 'test-menhir' repeatedly would rebuild the compiler each time
+# (parser.ml has changed), without actually taking the changes from
+# parser.mly into account ('core' uses the parser from boot/).
+
+# The test-menhir target does not read or write the boot directory,
+# it directly builds the parser in parsing/. In particular, it must
+# duplicate the MenhirLib->CamlinternalMenhirlib renaming usually
+# performed by the parsing/parser.ml import rule in the main
+# Makefile.
+.PHONY: test-menhir
+test-menhir: parsing/parser.mly
+	$(MENHIR) $(MENHIRFLAGS) parsing/parser.mly
+	for f in $(addprefix parsing/parser.,ml mli) ; do \
+	  cat $$f | sed "s/MenhirLib/CamlinternalMenhirLib/g" > $$f.tmp && \
+	  mv $$f.tmp $$f ; \
+	done
+	$(MAKE) parsing/parser.cmo
+
+
+## clean-menhir
+
+partialclean-menhir::
+	rm -f \
+	  $(addprefix parsing/parser.,ml mli) \
+	  $(addprefix parsing/camlinternalMenhirLib.,ml mli)
+
+clean-menhir: partialclean-menhir
+
+
+## depend-menhir
+
+.PHONY: depend-menhir
+depend-menhir:
+	$(MENHIR) --depend --ocamldep "$(CAMLDEP) $(DEPFLAGS) $(DEPINCLUDES)" \
+          parsing/parser.mly > .depend.menhir
+# this rule depends on the variables CAMLDEP, DEPFLAGS, DEPINCLUDES
+# defined in Makefile, so it can only be invoked from the main Makefile
+
+include .depend.menhir
+
+## interpret-menhir
+
+# This rule runs Menhir in interactive mode.
+# The user can enter sentences, such as:
+#   implementation: TYPE LIDENT EQUAL LIDENT EOF
+# and see how Menhir interprets them.
+
+interpret-menhir:
+	@ echo "Please wait, I am building the LALR automaton..."
+	@ $(MENHIR) $(MENHIRFLAGS) parsing/parser.mly \
+	    --interpret \
+	    --interpret-show-cst \
+	    --trace \
diff --git a/Makefile.nt b/Makefile.nt
deleted file mode 100644
index ed9900bb..00000000
--- a/Makefile.nt
+++ /dev/null
@@ -1,16 +0,0 @@
-#**************************************************************************
-#*                                                                        *
-#*                                 OCaml                                  *
-#*                                                                        *
-#*            Xavier Leroy, projet Cristal, INRIA Rocquencourt            *
-#*                                                                        *
-#*   Copyright 1999 Institut National de Recherche en Informatique et     *
-#*     en Automatique.                                                    *
-#*                                                                        *
-#*   All rights reserved.  This file is distributed under the terms of    *
-#*   the GNU Lesser General Public License version 2.1, with the          *
-#*   special exception on linking described in the file LICENSE.          *
-#*                                                                        *
-#**************************************************************************
-
-include Makefile
diff --git a/Makefile.tools b/Makefile.tools
index 9ec9a98d..0026b2e0 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -33,7 +33,7 @@ DIFF=diff -q
 SORT=sort
 SET_LD_PATH=CAML_LD_LIBRARY_PATH="$(LD_PATH)"
 
-# The variables above may be overridden by .../config/Makefile
+# The variables above may be overridden by .../Makefile.config
 # OTOPDIR is either TOPDIR or WINTOPDIR, whichever is appropriate for
 #   arguments given to the OCaml compiler.
 # CTOPDIR is either TOPDIR or WINTOPDIR, whichever is appropriate for
@@ -48,7 +48,7 @@ SET_LD_PATH=CAML_LD_LIBRARY_PATH="$(LD_PATH)"
 #   variable. Note that for Windows we add Unix-syntax directory names in
 #   PATH, and Cygwin will translate it to Windows syntax.
 
-include $(TOPDIR)/config/Makefile
+include $(TOPDIR)/Makefile.config
 
 ifneq ($(USE_RUNTIME),)
 #Check USE_RUNTIME value
@@ -57,12 +57,12 @@ $(error If set, USE_RUNTIME must be equal to "d" (debug runtime) \
         or "i" (instrumented runtime))
 endif
 
-RUNTIME_VARIANT=-I $(OTOPDIR)/asmrun -I $(OTOPDIR)/byterun \
+RUNTIME_VARIANT=-I $(OTOPDIR)/runtime \
                 -runtime-variant $(USE_RUNTIME)
 export OCAMLRUNPARAM?=v=0
 endif
 
-OCAMLRUN=$(TOPDIR)/byterun/ocamlrun$(USE_RUNTIME)$(EXE)
+OCAMLRUN=$(TOPDIR)/runtime/ocamlrun$(USE_RUNTIME)$(EXE)
 
 OCFLAGS=-nostdlib -I $(OTOPDIR)/stdlib $(COMPFLAGS)
 OCOPTFLAGS=
@@ -74,7 +74,6 @@ else
 endif
 
 OCAML=$(OCAMLRUN) $(OTOPDIR)/ocaml $(OCFLAGS) -noinit
-EXPECT_TEST=$(OCAMLRUN) $(OTOPDIR)/testsuite/tools/expect_test$(EXE)
 ifeq "$(FLEXLINK)" ""
   FLEXLINK_PREFIX=
 else
@@ -93,9 +92,9 @@ OCAMLOPT=$(FLEXLINK_PREFIX)$(OCAMLRUN) $(OTOPDIR)/ocamlopt $(OCFLAGS) \
 OCAMLDOC=$(OCAMLRUN) $(OTOPDIR)/ocamldoc/ocamldoc
 OCAMLLEX=$(OCAMLRUN) $(OTOPDIR)/lex/ocamllex
 OCAMLMKLIB=$(FLEXLINK_PREFIX)$(OCAMLRUN) $(OTOPDIR)/tools/ocamlmklib \
-           -ocamlc "$(OTOPDIR)/byterun/ocamlrun$(USE_RUNTIME)$(EXE) \
+           -ocamlc "$(OTOPDIR)/runtime/ocamlrun$(USE_RUNTIME)$(EXE) \
                     $(OTOPDIR)/ocamlc $(OCFLAGS) $(RUNTIME_VARIANT)" \
-           -ocamlopt "$(OTOPDIR)/byterun/ocamlrun$(USE_RUNTIME)$(EXE) \
+           -ocamlopt "$(OTOPDIR)/runtime/ocamlrun$(USE_RUNTIME)$(EXE) \
                       $(OTOPDIR)/ocamlopt $(OCFLAGS) $(RUNTIME_VARIANT)"
 OCAMLYACC=$(TOPDIR)/yacc/ocamlyacc$(EXE)
 DUMPOBJ=$(OCAMLRUN) $(OTOPDIR)/tools/dumpobj
diff --git a/News b/News
new file mode 100644
index 00000000..94371099
--- /dev/null
+++ b/News
@@ -0,0 +1,180 @@
+OCaml 4.07.1 (4 October 2018)
+-----------------------------
+
+This release consists mostly of bug fixes. The most salient bugs were
+
+- MPR#7820, GPR#1897: a bug in Array.of_seq (new in 4.07)
+  (Thierry Martinez, review by Nicolás Ojeda Bär)
+
+- MPR#7815, GPR#1896: crash in the major GC with the first-fit policy
+  (Stephen Dolan and Damien Doligez, report by Joris Giovannangeli)
+
+- MPR#7821, GPR#1908: the compiler loads more cmi, which breaks some builds
+  (Jérémie Dimino, review by Gabriel Scherer)
+
+- MPR#7833, GPR#1946: typechecking failure (regression) on large GADT matchings
+  (Thomas Refis, report by Jerome Simeon, review by Jacques Garrigue)
+
+See the detailed list of fixes at (Changes#4.07.1).
+
+
+OCaml 4.07.0 (10 July 2018):
+----------------------------
+
+Some highlights of this release are:
+
+-   The way the standard library modules are organized internally has
+    changed (GPR#1010, by Jérémie Dimino):
+
+    1. the `List` module (for example) is now named `Stdlib__list`
+    2. a new Stdlib module contains a series of aliases
+    such as `module List = Stdlib__list`
+    3. the `Stdlib` module is implicitly opened when type-checking OCaml
+    programs (as `Pervasives` previously was), so that `Stdlib.List` can be
+    accessed as just `List`, as before.
+
+    This should be invisible to most users, although it is possible that
+    some tools show the `Stdlib.` or `Stdlib__` prefixes in
+    messages. (You might want to report these situations as usability
+    bugs.) The change prevents standard library modules from conflicting
+    with end-user filenames (please avoid `stdlib.ml` and the
+    `Stdlib__` prefix); we may introduce new standard library modules in
+    the future with less fear of breaking user code. In particular,
+    `Float` (GPR#1638, by Nicolás Ojeda Bär) and `Seq` (GPR#1002, by
+    Simon Cruanes) modules have now been added to the standard library.
+
+-   The error messages caused by various typing errors have been improved
+    to be easier to understand, in particular for beginners.
+    (GPR#1505, GPR#1510, by Arthur Charguéreau and Armaël Guéneau)
+
+    For example,
+
+        # while 1 do () done;;
+                ^
+        Error: This expression has type int but
+               an expression was expected of type bool
+
+    now adds the extra explanation
+
+        because it is in the condition of a while-loop
+
+-   Effort has been made to reduce the compilation time of flambda
+    programs, and the size of the produced `.cmx` files when using
+    the -Oclassic optimisation level.
+    (GPR#1401, GPR#1455, GPR#1627, GPR#1665, by Pierre Chambart, Xavier
+    Clerc, Fuyong Quah, and Leo White)
+
+-   The HTML manual has benefited from various style improvements
+    and should look visually nicer than previous editions.
+    (GPR#1741, GPR#1757, GPR#1767 by Charles Chamberlain and steinuil)
+
+    The new version of the manual can be consulted at
+    ; see the
+    previous version for comparison at
+    .
+
+-   Since 4.01, it is possible to select a variant constructor or
+    record field from a sub-module that is not opened in the current
+    scope, if type information is available at the point of use. This
+    now also works for GADT constructors.
+    (GPR#1648, by Thomas Refis and Leo White)
+
+-   The GC should handle the accumulation of custom blocks in the minor
+    heap better; this solves some memory-usage issues observed by code
+    which allocates a lot of small custom blocks, typically small bigarrays
+    (GPR#1476, by Alain Frsich)
+
+See also the detailed list of changes: (Changes#4.07.0).
+
+
+OCaml 4.06.1 (16 Feb 2018):
+---------------------------
+
+This release consists mostly of bug fixes. The most salient bugs were
+
+-   An incorrect compilation of pattern-matching in presence of
+    extensible variant constructors (such as exceptions), that had been
+    present for a long time.
+    (GPR#1459, GPR#1538, by Luc Maranget, Thomas Refis and Gabriel Scherer)
+
+-   An optimization of `not (x = y)` into `x <> y`, introduced in
+    4.06.0, is incorrect on floating-point numbers in the `nan`
+    case. (GPR#1470, by Leo White)
+
+See the detailed list of fixes at (Changes#4.06.1).
+
+
+OCaml 4.06.0 (3 Nov 2017):
+--------------------------
+
+-   Strings (type `string`) are now immutable by default. In-place
+    modification must use the type `bytes` of byte sequences, which is
+    distinct from `string`.  This corresponds to the `-safe-string`
+    compile-time option, which was introduced in OCaml 4.02 in 2014, and
+    which is now the default.
+    (GPR#1252, by Damien Doligez)
+
+-   Object types can now extend a previously-defined object type,
+    as in ``.
+    (GPR#1118, by Runhang Li)
+
+-   Destructive substitution over module signatures can now express more
+    substitutions, such as `S with type M.t := type-expr` and `S with
+    module M.N := path`.
+    (GPR#792, by Valentin Gatien-Baron)
+
+-   Users can now define operators that look like array indexing,
+    e.g. `let ( .%() ) = List.nth in [0; 1; 2].%(1)`
+    (GPR#1064, GPR#1392, by Florian Angeletti)
+
+-   New escape `\u{XXXX}` in string literals, denoting the UTF-8
+    encoding of the Unicode code point `XXXX`.
+    (GPR#1232, by Daniel Bünzli)
+
+-   Full Unicode support was added to the Windows runtime system.  In
+    particular, file names can now contain Unicode characters.
+    (GPR#153, GPR#1200, GPR#1357, GPR#1362, GPR#1363, GPR#1369, GPR#1398,
+    GPR#1446, GPR#1448, by ygrek and Nicolás Ojeda Bär)
+
+-   An alternate register allocator based on linear scan can be selected
+    with `ocamlopt -linscan`.  It reduces compilation time compared with
+    the default register allocator.
+    (GPR#375, Marcell Fischbach and Benedikt Meurer)
+
+-   The Num library for arbitrary-precision integer and rational
+    arithmetic is no longer part of the core distribution and can be
+    found as a separate OPAM package.
+
+See the detailed list of changes: (Changes#4.06.0).
+
+
+OCaml 4.05.0 (13 Jul 2017):
+---------------------------
+
+Some highlights include:
+
+-   Instrumentation support for fuzzing with afl-fuzz.
+    (GPR#504, by Stephen Dolan)
+
+-   The compilers now accept new `-args/-args0 ` comand-line
+    parameters to provide extra command-line arguments in a file.  User
+    programs may implement similar options using the new `Expand`
+    constructor of the `Arg` module.
+    (GPR#748, GPR#843, GPR#864, by Bernhard Schommer)
+
+-   Many functions of the standard library that raise an exception now
+    have an option-returning variable suffixed by `_opt` Typical
+    examples of the new functions include:
+
+        int_of_string_opt: string -> int option
+        List.nth_opt: 'a list -> int -> 'a option
+        Hashtbl.find_opt : ('a, 'b) t -> 'a -> 'b option
+
+    (GPR#885, by Alain Frisch)
+
+-   The security of the runtime system is now hardened by using `secure_getenv`
+    to access environment variables whenever its possible, to avoid unplanned
+    privilege-escalation when running setuid binaries.
+    (GPR#1213, by Damien Doligez)
+
+See the detailed list of changes: (Changes#4.05.0).
diff --git a/README.adoc b/README.adoc
index 74d1ec25..53cd4512 100644
--- a/README.adoc
+++ b/README.adoc
@@ -1,14 +1,22 @@
 |=====
 | Branch `trunk` | Branch `4.06` | Branch `4.05` | Branch `4.04`
 
-| image:https://travis-ci.org/ocaml/ocaml.svg?branch=trunk["TravisCI Build Status (trunk branch)",link="https://travis-ci.org/ocaml/ocaml"]
-  image:https://ci.appveyor.com/api/projects/status/github/ocaml/ocaml?branch=trunk&svg=true["AppVeyor Build Status (trunk branch)",link="https://ci.appveyor.com/project/avsm/ocaml"]
-| image:https://travis-ci.org/ocaml/ocaml.svg?branch=4.06["TravisCI Build Status (4.06 branch)",link="https://travis-ci.org/ocaml/ocaml"]
-  image:https://ci.appveyor.com/api/projects/status/github/ocaml/ocaml?branch=4.06&svg=true["AppVeyor Build Status (4.06 branch)",link="https://ci.appveyor.com/project/avsm/ocaml"]
-| image:https://travis-ci.org/ocaml/ocaml.svg?branch=4.05["TravisCI Build Status (4.05 branch)",link="https://travis-ci.org/ocaml/ocaml"]
-  image:https://ci.appveyor.com/api/projects/status/github/ocaml/ocaml?branch=4.05&svg=true["AppVeyor Build Status (4.05 branch)",link="https://ci.appveyor.com/project/avsm/ocaml"]
-| image:https://travis-ci.org/ocaml/ocaml.svg?branch=4.04["TravisCI Build Status (4.04 branch)",link="https://travis-ci.org/ocaml/ocaml"]
-  image:https://ci.appveyor.com/api/projects/status/github/ocaml/ocaml?branch=4.04&svg=true["AppVeyor Build Status (4.04 branch)",link="https://ci.appveyor.com/project/avsm/ocaml"]
+| image:https://travis-ci.org/ocaml/ocaml.svg?branch=trunk["TravisCI Build Status (trunk branch)",
+     link="https://travis-ci.org/ocaml/ocaml"]
+  image:https://ci.appveyor.com/api/projects/status/github/ocaml/ocaml?branch=trunk&svg=true["AppVeyor Build Status (trunk branch)",
+     link="https://ci.appveyor.com/project/avsm/ocaml"]
+| image:https://travis-ci.org/ocaml/ocaml.svg?branch=4.06["TravisCI Build Status (4.06 branch)",
+     link="https://travis-ci.org/ocaml/ocaml"]
+  image:https://ci.appveyor.com/api/projects/status/github/ocaml/ocaml?branch=4.06&svg=true["AppVeyor Build Status (4.06 branch)",
+     link="https://ci.appveyor.com/project/avsm/ocaml"]
+| image:https://travis-ci.org/ocaml/ocaml.svg?branch=4.05["TravisCI Build Status (4.05 branch)",
+     link="https://travis-ci.org/ocaml/ocaml"]
+  image:https://ci.appveyor.com/api/projects/status/github/ocaml/ocaml?branch=4.05&svg=true["AppVeyor Build Status (4.05 branch)",
+     link="https://ci.appveyor.com/project/avsm/ocaml"]
+| image:https://travis-ci.org/ocaml/ocaml.svg?branch=4.04["TravisCI Build Status (4.04 branch)",
+     link="https://travis-ci.org/ocaml/ocaml"]
+  image:https://ci.appveyor.com/api/projects/status/github/ocaml/ocaml?branch=4.04&svg=true["AppVeyor Build Status (4.04 branch)",
+     link="https://ci.appveyor.com/project/avsm/ocaml"]
 
 |=====
 
diff --git a/README.win32.adoc b/README.win32.adoc
index 8d9d110b..8ad56c88 100644
--- a/README.win32.adoc
+++ b/README.win32.adoc
@@ -92,17 +92,17 @@ C code (`ocamlc -custom`) require a Microsoft Visual C/C++ Compiler and the
 Any edition (including Express/Community editions) of Microsoft Visual Studio
 2005 or later may be used to provide the required Windows headers and the C
 compiler. Additionally, some older Microsoft Windows SDKs include the
-Visual C/C++ Compiler.
+Visual C/C++ Compiler as well as the Build Tools for Visual Studio.
 
 |=====
-|                    | `cl` Version | Express                 | SDK
+|                    | `cl` Version | Express                 | SDK/Build Tools
 | Visual Studio 2005 | 14.00.x.x    | 32-bit only <> |
 | Visual Studio 2008 | 15.00.x.x    | 32-bit only             | Windows SDK 7.0 also provides 32/64-bit compilers
 | Visual Studio 2010 | 16.00.x.x    | 32-bit only             | Windows SDK 7.1 also provides 32/64-bit compilers
 | Visual Studio 2012 | 17.00.x.x    | 32/64-bit               |
 | Visual Studio 2013 | 18.00.x.x    | 32/64-bit               |
-| Visual Studio 2015 | 19.00.x.x    | 32/64-bit               |
-| Visual Studio 2017 | 19.10.x.x    | 32/64-bit               |
+| Visual Studio 2015 | 19.00.x.x    | 32/64-bit               | Build Tools for Visual Studio 2015 also provides 32/64-bit compilers
+| Visual Studio 2017 | 19.10.x.x    | 32/64-bit               | Build Tools for Visual Studio 2017 also provides 32/64-bit compilers
 |=====
 
 [[vs1]]
@@ -159,6 +159,9 @@ indicate if they are the "Native Tools" or "Cross Tools" versions. Visual Studio
 2015 and 2017 make the shortcuts even clearer by including the full name of the
 architecture.
 
+The Build Tools for Visual Studio 2015 and 2017 provide shortcuts similar to
+the ones of their respective Visual Studio version.
+
 You cannot at present use a cross-compiler to compile 64-bit OCaml on 32-bit
 Windows.
 
@@ -193,18 +196,13 @@ quickly as it will be unable to link `ocamlrun`.
 
 Now run:
 
-        cp config/m-nt.h byterun/caml/m.h
-        cp config/s-nt.h byterun/caml/s.h
-
-followed by:
-
-        cp config/Makefile.msvc config/Makefile
+        ./configure --build=i686-pc-cygwin --host=i686-pc-windows
 
 for 32-bit, or:
 
-        cp config/Makefile.msvc64 config/Makefile
+        ./configure --build=x86_64-unknown-cygwin --host=x86_64-pc-windows
 
-for 64-bit. Then, edit `config/Makefile` as needed, following the comments in
+for 64-bit. Then, edit `Makefile.config` as needed, following the comments in
 this file. Normally, the only variable that needs to be changed is `PREFIX`,
 which indicates where to install everything.
 
@@ -224,7 +222,7 @@ like to copy the `tools/msvs-promote-path` script and add the `eval` line to
 your `~/.bashrc` file.
 
 * The Microsoft Visual C/C++ compiler does not implement "computed gotos", and
-  therefore generates inefficient code for `byterun/interp.c`.  Consequently,
+  therefore generates inefficient code for `runtime/interp.c`.  Consequently,
   the performance of bytecode programs is about 2/3 of that obtained under
   Unix/GCC,  Cygwin or Mingw-w64 on similar hardware.
 
@@ -265,18 +263,13 @@ the WinZip Options Window.)
 
 Now run:
 
-        cp config/m-nt.h byterun/caml/m.h
-        cp config/s-nt.h byterun/caml/s.h
-
-followed by:
-
-        cp config/Makefile.mingw config/Makefile
+        ./configure --build=i686-pc-cygwin --host=i686-w64-mingw32
 
 for 32-bit, or:
 
-        cp config/Makefile.mingw64 config/Makefile
+        ./configure --build=x86_64-unknown-cygwin --host=x86_64-w64-mingw32
 
-for 64-bit. Then, edit `config/Makefile` as needed, following the comments in
+for 64-bit. Then, edit `Makefile.config` as needed, following the comments in
 this file. Normally, the only variable that needs to be changed is `PREFIX`,
 which indicates where to install everything.
 
@@ -350,7 +343,7 @@ are UTF-8 encoded strings.  In addition to filenames,
 this applies to environment variables and command-line arguments.
 
 The mode must be decided before building the system, by tweaking
-the `WINDOWS_UNICODE` variable in `config/Makefile`.  A value of 1
+the `WINDOWS_UNICODE` variable in `Makefile.config`.  A value of 1
 enables the the new "Unicode" mode, while a value of 0 maintains
 the legacy mode.
 
diff --git a/VERSION b/VERSION
index 0e48c0f1..5612695a 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
-4.07.1
+4.08.0
 
 # The version string is the first line of this file.
 # It must be in the format described in stdlib/sys.mli
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 00000000..543fff72
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,267 @@
+#**************************************************************************
+#*                                                                        *
+#*                                 OCaml                                  *
+#*                                                                        *
+#*            Sebastien Hinderer, projet Gallium, INRIA Paris             *
+#*                                                                        *
+#*   Copyright 2018 Institut National de Recherche en Informatique et     *
+#*     en Automatique.                                                    *
+#*                                                                        *
+#*   All rights reserved.  This file is distributed under the terms of    *
+#*   the GNU Lesser General Public License version 2.1, with the          *
+#*   special exception on linking described in the file LICENSE.          *
+#*                                                                        *
+#**************************************************************************
+
+# This file is processed by autoconf.
+# It contains macro definitions specific to the OCaml package.
+# Every macro defined here should have its name prefixed with OCAML_.
+
+# libtool macros
+
+# Since the project does not use automake, the libtool macro files
+# need to be manually included
+m4_include([build-aux/libtool.m4])
+m4_include([build-aux/ltoptions.m4])
+m4_include([build-aux/ltsugar.m4])
+m4_include([build-aux/ltversion.m4])
+m4_include([build-aux/lt~obsolete.m4])
+
+# Macros from the autoconf macro archive
+m4_include([build-aux/ax_func_which_gethostbyname_r.m4])
+m4_include([build-aux/ax_pthread.m4])
+
+# The following macro figures out which C compiler is used.
+# It does so by checking for compiler-specific predefined macros.
+# A list of such macros can be found at
+# https://sourceforge.net/p/predef/wiki/Compilers/
+AC_DEFUN([OCAML_CC_VENDOR], [
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_PROG_CPP])
+  AC_MSG_CHECKING([C compiler vendor])
+  AC_PREPROC_IFELSE(
+    [AC_LANG_SOURCE([
+#if defined(_MSC_VER)
+msvc _MSC_VER
+#elif defined(__INTEL_COMPILER)
+icc __INTEL_COMPILER
+#elif defined(__clang_major__) && defined(__clang_minor__)
+clang __clang_major__ __clang_minor__
+#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
+gcc __GNUC__ __GNUC_MINOR__
+#elif defined(__xlc__) && defined(__xlC__)
+xlc __xlC__ __xlC_ver__
+#else
+unknown
+#endif]
+    )],
+    [AC_CACHE_VAL([ocaml_cv_cc_vendor],
+      [ocaml_cv_cc_vendor=`grep ['^[a-z]'] conftest.i | tr -s ' ' '-'`])],
+    [AC_MSG_FAILURE([unexpected preprocessor failure])])
+  AC_MSG_RESULT([$ocaml_cv_cc_vendor])
+])
+
+AC_DEFUN([OCAML_SIGNAL_HANDLERS_SEMANTICS], [
+  AC_MSG_NOTICE([checking semantics of signal handlers])
+  AC_CHECK_FUNC([sigaction], [has_sigaction=true], [has_sigaction=false])
+  AC_CHECK_FUNC([sigprocmask], [has_sigprocmask=true], [has_sigprocmask=false])
+  AS_IF([$has_sigaction && $has_sigprocmask],
+    [AC_DEFINE([POSIX_SIGNALS])
+      AC_MSG_NOTICE([POSIX signal handling found.])],
+    [AC_MSG_NOTICE([assuming signals have the System V semantics.])
+    AC_CHECK_FUNCS([sigsetmask], [AC_DEFINE([HAS_SIGSETMASK])])
+    ]
+  )
+])
+
+AC_DEFUN([OCAML_CC_HAS_FNO_TREE_VRP], [
+  AC_MSG_CHECKING([whether the C compiler supports -fno-tree-vrp])
+  saved_CFLAGS="$CFLAGS"
+  CFLAGS="-Werror -fno-tree-vrp $CFLAGS"
+  AC_COMPILE_IFELSE(
+    [AC_LANG_SOURCE([int main() { return 0; }])],
+    [cc_has_fno_tree_vrp=true
+    AC_MSG_RESULT([yes])],
+    [cc_has_fno_tree_vrp=false
+    AC_MSG_RESULT([no])])
+  CFLAGS="$saved_CFLAGS"
+])
+
+AC_DEFUN([OCAML_CC_HAS_DEBUG_PREFIX_MAP], [
+  AC_MSG_CHECKING([whether the C compiler supports -fdebug-prefix-map])
+  saved_CFLAGS="$CFLAGS"
+  CFLAGS="-fdebug-prefix-map=old=new $CFLAGS"
+  AC_COMPILE_IFELSE(
+    [AC_LANG_SOURCE([int main() { return 0; }])],
+    [cc_has_debug_prefix_map=true
+    AC_MSG_RESULT([yes])],
+    [cc_has_debug_prefix_map=false
+    AC_MSG_RESULT([no])])
+  CFLAGS="$saved_CFLAGS"
+])
+
+# Save C compiler related variables
+AC_DEFUN([OCAML_CC_SAVE_VARIABLES], [
+  saved_CC="$CC"
+  saved_CFLAGS="$CFLAGS"
+  saved_CPPFLAGS="$CPPFLAGS"
+  saved_ac_ext="$ac_ext"
+  saved_ac_compile="$ac_compile"
+  # Move the content of confdefs.h to another file so it does not
+  # get included
+  mv confdefs.h confdefs.h.bak
+  touch confdefs.h
+])
+
+# Restore the C compiler related variables
+AC_DEFUN([OCAML_CC_RESTORE_VARIABLES], [
+  # Restore the content of confdefs.h
+  mv confdefs.h.bak confdefs.h
+  ac_compile="$saved_ac_compile"
+  ac_ext="$saved_ac_ext"
+  CPPFLAGS="$saved_CPPFLAGS"
+  CFLAGS="$saved_CFLAGS"
+  CC="$saved_CC"
+])
+
+AC_DEFUN([OCAML_AS_HAS_DEBUG_PREFIX_MAP], [
+  AC_MSG_CHECKING([whether the assembler supports --debug-prefix-map])
+
+  OCAML_CC_SAVE_VARIABLES
+
+  # Modify C-compiler variables to use the assembler
+  CC="$AS"
+  CFLAGS="--debug-prefix-map old=new -o conftest.$ac_objext"
+  CPPFLAGS=""
+  ac_ext="S"
+  ac_compile='$CC $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+
+  AC_COMPILE_IFELSE(
+    [AC_LANG_SOURCE([
+camlPervasives__loop_1128:
+        .file   1       "pervasives.ml"
+        .loc    1       193
+    ])],
+    [as_has_debug_prefix_map=true
+    AC_MSG_RESULT([yes])],
+    [ashas_debug_prefix_map=false
+    AC_MSG_RESULT([no])])
+
+  OCAML_CC_RESTORE_VARIABLES
+])
+
+AC_DEFUN([OCAML_AS_HAS_CFI_DIRECTIVES], [
+  AC_MSG_CHECKING([whether the assembler supports CFI directives])
+
+  AS_IF([test x"$enable_cfi" = "xno"],
+    [AC_MSG_RESULT([disabled])],
+    [OCAML_CC_SAVE_VARIABLES
+
+    # Modify C-compiler variables to use the assembler
+    CC="$ASPP"
+    CFLAGS="-o conftest.$ac_objext"
+    CPPFLAGS=""
+    ac_ext="S"
+    ac_compile='$CC $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+
+    AC_COMPILE_IFELSE(
+      [AC_LANG_SOURCE([
+camlPervasives__loop_1128:
+        .file   1       "pervasives.ml"
+        .loc    1       193
+        .cfi_startproc
+        .cfi_adjust_cfa_offset 8
+        .cfi_endproc
+      ])],
+      [aspp_ok=true],
+      [aspp_ok=false])
+
+    AS_IF([test "$AS" = "$ASPP"],
+      [as_ok="$aspp_ok"],
+      [CC="$AS"
+      ac_compile='$CC $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+      AC_COMPILE_IFELSE(
+        [AC_LANG_SOURCE([
+camlPervasives__loop_1128:
+        .file   1       "pervasives.ml"
+        .loc    1       193
+        .cfi_startproc
+        .cfi_adjust_cfa_offset 8
+        .cfi_endproc
+        ])],
+        [as_ok=true],
+        [as_ok=false])])
+
+    OCAML_CC_RESTORE_VARIABLES
+
+    AS_IF([$aspp_ok && $as_ok],
+      [asm_cfi_supported=true
+      AC_DEFINE([ASM_CFI_SUPPORTED])
+      AC_MSG_RESULT([yes])],
+      [AS_IF([test x"$enable_cfi" = "xyes"],
+        [AC_MSG_RESULT([requested but not available
+        AC_MSG_ERROR([exiting])])],
+        [asm_cfi_supported=false
+        AC_MSG_RESULT([no])])])
+  ])])
+
+AC_DEFUN([OCAML_MMAP_SUPPORTS_HUGE_PAGES], [
+  AC_MSG_CHECKING([whether mmap supports huge pages])
+  AC_RUN_IFELSE(
+    [AC_LANG_SOURCE([[
+#include 
+#include 
+#include 
+
+#define huge_page_size (4 * 1024 * 1024)
+
+/* Test for the possible availability of huge pages. Answer yes
+   if the OS knows about huge pages, even if they are not available
+   on the build machine at configure time, because (on Linux) huge
+   pages can be activated and deactivated easily while the system
+   is running.
+*/
+
+int main (int argc, char *argv[]){
+  void *block;
+  char *p;
+  int i, res;
+  block = mmap (NULL, huge_page_size, PROT_READ | PROT_WRITE,
+                MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
+                -1, 0);
+  if (block == MAP_FAILED){
+    block = mmap (NULL, huge_page_size, PROT_READ | PROT_WRITE,
+                  MAP_PRIVATE | MAP_ANONYMOUS,
+                  -1, 0);
+  }
+  if (block == MAP_FAILED){
+    perror ("mmap");
+    return 3;
+  }
+  /*printf ("block = %p\n", block);*/
+  p = (char *) block;
+  for (i = 0; i < huge_page_size; i += 4096){
+    p[i] = (char) i;
+  }
+  return 0;
+}
+    ]])],
+    [AC_DEFINE([HAS_HUGE_PAGES])
+    AC_DEFINE_UNQUOTED([HUGE_PAGE_SIZE], [(4 * 1024 * 1024)])
+    AC_MSG_RESULT([yes])],
+    [AC_MSG_RESULT([no])],
+    [AC_MSG_RESULT([no assumed])])
+])
+
+AC_DEFUN([OCAML_CHECK_LIBUNWIND], [
+  SAVED_CFLAGS="$CFLAGS"
+  SAVED_LDFLAGS="$LDFLAGS"
+  CFLAGS="$CFLAGS $libunwind_include_flags"
+  LDFLAGS="$LDFLAGS $libunwind_link_flags"
+  AC_CHECK_HEADER([libunwind.h],
+    [AC_DEFINE([HAS_LIBUNWIND])
+    libunwind_available=true],
+    [libunwind_available=false])
+  LDFLAGS="$SAVED_LDFLAGS"
+  CFLAGS="$SAVED_CFLAGS"
+])
diff --git a/appveyor.yml b/appveyor.yml
index c07c60f6..e055683f 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -28,6 +28,12 @@ environment:
     CYG_CACHE: C:/cygwin64/var/cache/setup
     FLEXDLL_VERSION: 0.37
     OCAMLRUNPARAM: v=0,b
+  matrix:
+    - PORT: mingw32
+    - PORT: msvc64
+
+matrix:
+  fast_finish: true
 
 cache:
   - C:\cygwin64\var\cache\setup
diff --git a/asmcomp/CSEgen.ml b/asmcomp/CSEgen.ml
index d0b6eb2a..09ecca70 100644
--- a/asmcomp/CSEgen.ml
+++ b/asmcomp/CSEgen.ml
@@ -37,7 +37,7 @@ type rhs = operation * valnum array
 
 module Equations = struct
   module Rhs_map =
-    Map.Make(struct type t = rhs let compare = Pervasives.compare end)
+    Map.Make(struct type t = rhs let compare = Stdlib.compare end)
 
   type 'a t =
     { load_equations : 'a Rhs_map.t;
diff --git a/asmcomp/CSEgen.mli b/asmcomp/CSEgen.mli
index 98b5f5b0..c80e7b4c 100644
--- a/asmcomp/CSEgen.mli
+++ b/asmcomp/CSEgen.mli
@@ -24,7 +24,7 @@ type op_class =
   | Op_other   (* anything else that does not allocate nor store in memory *)
 
 class cse_generic : object
-  (* The following methods can be overriden to handle processor-specific
+  (* The following methods can be overridden to handle processor-specific
      operations. *)
 
   method class_of_operation: Mach.operation -> op_class
diff --git a/asmcomp/afl_instrument.ml b/asmcomp/afl_instrument.ml
index d3d371cf..8397c30d 100644
--- a/asmcomp/afl_instrument.ml
+++ b/asmcomp/afl_instrument.ml
@@ -17,6 +17,9 @@
 open Lambda
 open Cmm
 
+module V = Backend_var
+module VP = Backend_var.With_provenance
+
 let afl_area_ptr = Cconst_symbol "caml_afl_area_ptr"
 let afl_prev_loc = Cconst_symbol "caml_afl_prev_loc"
 let afl_map_size = 1 lsl 16
@@ -35,20 +38,21 @@ let rec with_afl_logging b =
        docs/technical_details.txt in afl-fuzz source for for a full
        description of what's going on. *)
     let cur_location = Random.int afl_map_size in
-    let cur_pos = Ident.create "pos" in
-    let afl_area = Ident.create "shared_mem" in
+    let cur_pos = V.create_local "pos" in
+    let afl_area = V.create_local "shared_mem" in
     let op oper args = Cop (oper, args, Debuginfo.none) in
-    Clet(afl_area, op (Cload (Word_int, Asttypes.Mutable)) [afl_area_ptr],
-    Clet(cur_pos,  op Cxor [op (Cload (Word_int, Asttypes.Mutable))
-      [afl_prev_loc]; Cconst_int cur_location],
-    Csequence(
-      op (Cstore(Byte_unsigned, Assignment))
-         [op Cadda [Cvar afl_area; Cvar cur_pos];
-          op Cadda [op (Cload (Byte_unsigned, Asttypes.Mutable))
-                       [op Cadda [Cvar afl_area; Cvar cur_pos]];
-                    Cconst_int 1]],
-      op (Cstore(Word_int, Assignment))
-         [afl_prev_loc; Cconst_int (cur_location lsr 1)]))) in
+    Clet(VP.create afl_area,
+      op (Cload (Word_int, Asttypes.Mutable)) [afl_area_ptr],
+      Clet(VP.create cur_pos, op Cxor [op (Cload (Word_int, Asttypes.Mutable))
+        [afl_prev_loc]; Cconst_int cur_location],
+      Csequence(
+        op (Cstore(Byte_unsigned, Assignment))
+          [op Cadda [Cvar afl_area; Cvar cur_pos];
+            op Cadda [op (Cload (Byte_unsigned, Asttypes.Mutable))
+                        [op Cadda [Cvar afl_area; Cvar cur_pos]];
+                      Cconst_int 1]],
+        op (Cstore(Word_int, Assignment))
+          [afl_prev_loc; Cconst_int (cur_location lsr 1)]))) in
   Csequence(instrumentation, instrument b)
 
 and instrument = function
@@ -64,6 +68,8 @@ and instrument = function
 
   (* these cases add no logging, but instrument subexpressions *)
   | Clet (v, e, body) -> Clet (v, instrument e, instrument body)
+  | Cphantom_let (v, defining_expr, body) ->
+    Cphantom_let (v, defining_expr, instrument body)
   | Cassign (v, e) -> Cassign (v, instrument e)
   | Ctuple es -> Ctuple (List.map instrument es)
   | Cop (op, es, dbg) -> Cop (op, List.map instrument es, dbg)
diff --git a/asmcomp/amd64/CSE.ml b/asmcomp/amd64/CSE.ml
index 7e4193d7..1c2ec7ee 100644
--- a/asmcomp/amd64/CSE.ml
+++ b/asmcomp/amd64/CSE.ml
@@ -27,7 +27,7 @@ method! class_of_operation op =
   match op with
   | Ispecific spec ->
     begin match spec with
-    | Ilea _ -> Op_pure
+    | Ilea _ | Isextend32 -> Op_pure
     | Istore_int(_, _, is_asg) -> Op_store is_asg
     | Ioffset_loc(_, _) -> Op_store true
     | Ifloatarithmem _ | Ifloatsqrtf _ -> Op_load
diff --git a/asmcomp/amd64/arch.ml b/asmcomp/amd64/arch.ml
index 4b5789f1..62ba8808 100644
--- a/asmcomp/amd64/arch.ml
+++ b/asmcomp/amd64/arch.ml
@@ -42,6 +42,8 @@ type specific_operation =
   | Ibswap of int                      (* endianness conversion *)
   | Isqrtf                             (* Float square root *)
   | Ifloatsqrtf of addressing_mode     (* Float square root from memory *)
+  | Isextend32                         (* 32 to 64 bit conversion with sign
+                                          extension *)
 and float_operation =
     Ifloatadd | Ifloatsub | Ifloatmul | Ifloatdiv
 
@@ -126,6 +128,8 @@ let print_specific_operation printreg op ppf arg =
                    (Array.sub arg 1 (Array.length arg - 1))
   | Ibswap i ->
       fprintf ppf "bswap_%i %a" i printreg arg.(0)
+  | Isextend32 ->
+      fprintf ppf "sextend32 %a" printreg arg.(0)
 
 let win64 =
   match Config.system with
diff --git a/asmcomp/amd64/emit.mlp b/asmcomp/amd64/emit.mlp
index cf261a06..e984ed56 100644
--- a/asmcomp/amd64/emit.mlp
+++ b/asmcomp/amd64/emit.mlp
@@ -16,7 +16,6 @@
 
 (* Emission of Intel x86_64 assembly code *)
 
-open Misc
 open Cmm
 open Arch
 open Proc
@@ -28,6 +27,7 @@ open Emitaux
 open X86_ast
 open X86_proc
 open X86_dsl
+module String = Misc.Stdlib.String
 
 (* [Branch_relaxation] is not used in this file, but is required by
    emit.mlp files for certain other targets; the reference here ensures
@@ -103,11 +103,11 @@ let emit_symbol s = string_of_symbol symbol_prefix s
 (* Record symbols used and defined - at the end generate extern for those
    used but not defined *)
 
-let symbols_defined = ref StringSet.empty
-let symbols_used = ref StringSet.empty
+let symbols_defined = ref String.Set.empty
+let symbols_used = ref String.Set.empty
 
-let add_def_symbol s = symbols_defined := StringSet.add s !symbols_defined
-let add_used_symbol s = symbols_used := StringSet.add s !symbols_used
+let add_def_symbol s = symbols_defined := String.Set.add s !symbols_defined
+let add_used_symbol s = symbols_used := String.Set.add s !symbols_used
 
 let imp_table = Hashtbl.create 16
 
@@ -160,8 +160,8 @@ let load_symbol_addr s arg =
 
 let emit_label lbl =
   match system with
-  | S_macosx | S_win64 -> "L" ^ string_of_int lbl
-  | _ -> ".L" ^ string_of_int lbl
+  | S_macosx | S_win64 -> "L" ^ Int.to_string lbl
+  | _ -> ".L" ^ Int.to_string lbl
 
 let label s = sym (emit_label s)
 
@@ -473,6 +473,22 @@ let emit_global_label s =
   D.global lbl;
   _label lbl
 
+(* Emission of the profiling prelude *)
+
+let emit_profile () =
+  if system = S_gnu || system = S_linux then begin
+    (* mcount preserves rax, rcx, rdx, rsi, rdi, r8, r9 explicitly
+       and rbx, rbp, r12-r15 like all C functions.  This includes
+       all the registers used for argument passing, so we don't
+       need to preserve other regs.  We do need to initialize rbp
+       like mcount expects it, though. *)
+    I.push r10;
+    if not fp then I.mov rsp rbp;
+    (* No Spacetime instrumentation needed: [mcount] cannot call anything
+       OCaml-related. *)
+    emit_call "mcount";
+    I.pop r10
+  end
 
 (* Output the assembly code for an instruction *)
 
@@ -486,6 +502,22 @@ let emit_instr fallthrough i =
   emit_debug_info i.dbg;
   match i.desc with
   | Lend -> ()
+  | Lprologue ->
+    if fp then begin
+      I.push rbp;
+      cfi_adjust_cfa_offset 8;
+      I.mov rsp rbp;
+    end;
+    if !Clflags.gprofile then emit_profile();
+    if frame_required() then begin
+      let n = frame_size() - 8 - (if fp then 8 else 0) in
+      if n <> 0
+      then begin
+        I.sub (int n) rsp;
+        cfi_adjust_cfa_offset n;
+      end;
+    end;
+    def_label !tailrec_entry_point
   | Lop(Imove | Ispill | Ireload) ->
       let src = i.arg.(0) and dst = i.res.(0) in
       if src.loc <> dst.loc then
@@ -610,7 +642,7 @@ let emit_instr fallthrough i =
       | Double | Double_u ->
           I.movsd (arg i 0) (addressing addr REAL8 i 1)
       end
-  | Lop(Ialloc { words = n; label_after_call_gc; spacetime_index; }) ->
+  | Lop(Ialloc { bytes = n; label_after_call_gc; spacetime_index; }) ->
       if !fastcode_flag then begin
         let lbl_redo = new_label() in
         def_label lbl_redo;
@@ -748,6 +780,8 @@ let emit_instr fallthrough i =
       I.sqrtsd (arg i 0) (res i 0)
   | Lop(Ispecific(Ifloatsqrtf addr)) ->
       I.sqrtsd (addressing addr REAL8 i 0) (res i 0)
+  | Lop(Ispecific(Isextend32)) ->
+      I.movsxd (arg32 i 0) (res i 0)
   | Lop (Iname_for_debugger _) -> ()
   | Lreloadretaddr ->
       ()
@@ -866,23 +900,6 @@ let rec emit_all fallthrough i =
       emit_instr fallthrough i;
       emit_all (Linearize.has_fallthrough i.desc) i.next
 
-(* Emission of the profiling prelude *)
-
-let emit_profile () =
-  if system = S_gnu || system = S_linux then begin
-    (* mcount preserves rax, rcx, rdx, rsi, rdi, r8, r9 explicitly
-       and rbx, rbp, r12-r15 like all C functions.  This includes
-       all the registers used for argument passing, so we don't
-       need to preserve other regs.  We do need to initialize rbp
-       like mcount expects it, though. *)
-    I.push r10;
-    if not fp then I.mov rsp rbp;
-    (* No Spacetime instrumentation needed: [mcount] cannot call anything
-       OCaml-related. *)
-    emit_call "mcount";
-    I.pop r10
-  end
-
 let all_functions = ref []
 
 (* Emission of a function declaration *)
@@ -909,21 +926,6 @@ let fundecl fundecl =
   D.label (emit_symbol fundecl.fun_name);
   emit_debug_info fundecl.fun_dbg;
   cfi_startproc ();
-  if fp then begin
-    I.push rbp;
-    cfi_adjust_cfa_offset 8;
-    I.mov rsp rbp;
-  end;
-  if !Clflags.gprofile then emit_profile();
-  if frame_required() then begin
-    let n = frame_size() - 8 - (if fp then 8 else 0) in
-    if n <> 0
-    then begin
-      I.sub (int n) rsp;
-      cfi_adjust_cfa_offset n;
-    end;
-  end;
-  def_label !tailrec_entry_point;
   emit_all true fundecl.fun_body;
   List.iter emit_call_gc !call_gc_sites;
   emit_call_bound_errors ();
@@ -1112,13 +1114,13 @@ let end_assembly() =
 
   if system = S_win64 then begin
     D.comment "External functions";
-    StringSet.iter
+    String.Set.iter
       (fun s ->
-         if not (StringSet.mem s !symbols_defined) then
+         if not (String.Set.mem s !symbols_defined) then
            D.extrn (emit_symbol s) NEAR)
       !symbols_used;
-    symbols_used := StringSet.empty;
-    symbols_defined := StringSet.empty;
+    symbols_used := String.Set.empty;
+    symbols_defined := String.Set.empty;
   end;
 
   let asm =
diff --git a/asmcomp/amd64/proc.ml b/asmcomp/amd64/proc.ml
index cd21e526..db94a476 100644
--- a/asmcomp/amd64/proc.ml
+++ b/asmcomp/amd64/proc.ml
@@ -266,6 +266,22 @@ let loc_external_arguments arg =
 
 let loc_exn_bucket = rax
 
+(** See "System V Application Binary Interface, AMD64 Architecture Processor
+    Supplement" (www.x86-64.org/documentation/abi.pdf) page 57, fig. 3.36. *)
+let int_dwarf_reg_numbers =
+  [| 0; 3; 5; 4; 1; 2; 8; 9; 12; 13; 10; 11; 6 |]
+
+let float_dwarf_reg_numbers =
+  [| 17; 18; 19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32 |]
+
+let dwarf_register_numbers ~reg_class =
+  match reg_class with
+  | 0 -> int_dwarf_reg_numbers
+  | 1 -> float_dwarf_reg_numbers
+  | _ -> Misc.fatal_errorf "Bad register class %d" reg_class
+
+let stack_ptr_dwarf_register_number = 7
+
 (* Volatile registers: none *)
 
 let regs_are_volatile _rs = false
@@ -319,6 +335,8 @@ let destroyed_at_oper = function
 
 let destroyed_at_raise = all_phys_regs
 
+let destroyed_at_reloadretaddr = [| |]
+
 (* Maximal register pressure *)
 
 
@@ -350,7 +368,7 @@ let op_is_pure = function
   | Icall_ind _ | Icall_imm _ | Itailcall_ind _ | Itailcall_imm _
   | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _
   | Iintop(Icheckbound _) | Iintop_imm(Icheckbound _, _) -> false
-  | Ispecific(Ilea _) -> true
+  | Ispecific(Ilea _|Isextend32) -> true
   | Ispecific _ -> false
   | _ -> true
 
diff --git a/asmcomp/amd64/selection.ml b/asmcomp/amd64/selection.ml
index 336120f4..db7ee0a6 100644
--- a/asmcomp/amd64/selection.ml
+++ b/asmcomp/amd64/selection.ml
@@ -231,6 +231,13 @@ method! select_operation op args dbg =
   (* AMD64 does not support immediate operands for multiply high signed *)
   | Cmulhi ->
       (Iintop Imulh, args)
+  | Casr ->
+      begin match args with
+        (* Recognize sign extension *)
+        [Cop(Clsl, [k; Cconst_int 32], _); Cconst_int 32] ->
+          (Ispecific Isextend32, [k])
+        | _ -> super#select_operation op args dbg
+      end
   | _ -> super#select_operation op args dbg
 
 (* Recognize float arithmetic with mem *)
diff --git a/asmcomp/arm/emit.mlp b/asmcomp/arm/emit.mlp
index 182ccbdf..a523fbb9 100644
--- a/asmcomp/arm/emit.mlp
+++ b/asmcomp/arm/emit.mlp
@@ -396,12 +396,44 @@ let emit_set_condition cmp rd =
     end
   end
 
+(* Emission of the profiling prelude *)
+
+let emit_profile() =
+  match Config.system with
+    "linux_eabi" | "linux_eabihf" | "netbsd" ->
+      `	push	\{lr}\n`;
+      `	{emit_call "__gnu_mcount_nc"}\n`;
+      2
+  | _ -> 0
+
 (* Output the assembly code for an instruction *)
 
 let emit_instr i =
     emit_debug_info i.dbg;
     match i.desc with
-      Lend -> 0
+    | Lend -> 0
+    | Lprologue ->
+      let num_instrs0 =
+        if !Clflags.gprofile then emit_profile()
+        else 0
+      in
+      let n = frame_size() in
+      let num_instrs1 =
+        if n > 0 then begin
+          let num_instrs = emit_stack_adjustment (-n) in
+          if !contains_calls then begin
+            cfi_offset ~reg:14 (* lr *) ~offset:(-4);
+            `	str	lr, [sp, #{emit_int(n - 4)}]\n`;
+            num_instrs + 1
+          end else begin
+            num_instrs
+          end
+        end else begin
+          0
+        end
+      in
+      `{emit_label !tailrec_entry_point}:\n`;
+      num_instrs0 + num_instrs1
     | Lop(Imove | Ispill | Ireload) ->
         let src = i.arg.(0) and dst = i.res.(0) in
         if src.loc = dst.loc then 0 else begin
@@ -568,7 +600,7 @@ let emit_instr i =
           | Double_u -> "fstd"
           | _ (* 32-bit quantities *) -> "str" in
         `	{emit_string instr}	{emit_reg r}, {emit_addressing addr i.arg 1}\n`; 1
-    | Lop(Ialloc { words = n; label_after_call_gc; }) ->
+    | Lop(Ialloc { bytes = n; label_after_call_gc; }) ->
         let lbl_frame =
           record_frame_label i.live false i.dbg ?label:label_after_call_gc
         in
@@ -868,16 +900,6 @@ let rec emit_all ninstr fallthrough i =
     emit_all (ninstr' + n) (has_fallthrough i.desc) i.next
   end
 
-
-(* Emission of the profiling prelude *)
-
-let emit_profile() =
-  match Config.system with
-    "linux_eabi" | "linux_eabihf" | "netbsd" ->
-      `	push	\{lr}\n`;
-      `	{emit_call "__gnu_mcount_nc"}\n`
-  | _ -> ()
-
 (* Emission of a function declaration *)
 
 let fundecl fundecl =
@@ -901,16 +923,6 @@ let fundecl fundecl =
   `{emit_symbol fundecl.fun_name}:\n`;
   emit_debug_info fundecl.fun_dbg;
   cfi_startproc();
-  if !Clflags.gprofile then emit_profile();
-  let n = frame_size() in
-  if n > 0 then begin
-    ignore(emit_stack_adjustment (-n));
-    if !contains_calls then begin
-      cfi_offset ~reg:14 (* lr *) ~offset:(-4);
-      `	str	lr, [sp, #{emit_int(n - 4)}]\n`
-    end
-  end;
-  `{emit_label !tailrec_entry_point}:\n`;
   emit_all 0 true fundecl.fun_body;
   emit_literals();
   List.iter emit_call_gc !call_gc_sites;
diff --git a/asmcomp/arm/proc.ml b/asmcomp/arm/proc.ml
index 9e1bb648..1622fa49 100644
--- a/asmcomp/arm/proc.ml
+++ b/asmcomp/arm/proc.ml
@@ -224,6 +224,40 @@ let loc_external_results res =
 
 let loc_exn_bucket = phys_reg 0
 
+(* See "DWARF for the ARM architecture" available from developer.arm.com. *)
+
+let int_dwarf_reg_numbers =
+  [| 0; 1; 2; 3; 4; 5; 6; 7; 12 |]
+
+let float_dwarf_reg_numbers_legacy =
+  [| 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;
+  |]
+
+let float_dwarf_reg_numbers =
+  [| 256; 257; 258; 259; 260; 261; 262; 263;
+     264; 265; 266; 267; 268; 269; 270; 271;
+     272; 273; 274; 275; 276; 277; 278; 279;
+     280; 281; 282; 283; 284; 285; 286; 287;
+  |]
+
+let dwarf_register_numbers ~reg_class =
+  match reg_class with
+  | 0 -> int_dwarf_reg_numbers
+  | 1 ->
+    (* Section 3.1 note 4 says that the "new" VFPv3 register numberings
+       (as per [float_dwarf_reg_numbers]) should be used for VFPv2 as well.
+       However we believe that for <= ARMv6 we should use the legacy VFPv2
+       numberings. *)
+    if !arch <= ARMv6 then float_dwarf_reg_numbers_legacy
+    else float_dwarf_reg_numbers
+  | 2 -> float_dwarf_reg_numbers
+  | _ -> Misc.fatal_errorf "Bad register class %d" reg_class
+
+let stack_ptr_dwarf_register_number = 13
+
 (* Volatile registers: none *)
 
 let regs_are_volatile _rs = false
@@ -274,6 +308,10 @@ let destroyed_at_oper = function
 
 let destroyed_at_raise = all_phys_regs
 
+(* lr is destroyed at [Lreloadretaddr], but lr is not used for register
+   allocation, and thus does not need to (and indeed cannot) occur here. *)
+let destroyed_at_reloadretaddr = [| |]
+
 (* Maximal register pressure *)
 
 let safe_register_pressure = function
@@ -310,8 +348,9 @@ let contains_calls = ref false
 (* Calling the assembler *)
 
 let assemble_file infile outfile =
-  Ccomp.command (Config.asm ^ " -o " ^
-                 Filename.quote outfile ^ " " ^ Filename.quote infile)
+  Ccomp.command (Config.asm ^ " " ^
+                 (String.concat " " (Misc.debug_prefix_map_flags ())) ^
+                 " -o " ^ Filename.quote outfile ^ " " ^ Filename.quote infile)
 
 
 let init () = ()
diff --git a/asmcomp/arm/reload.ml b/asmcomp/arm/reload.ml
index f7b61498..9d4f3973 100644
--- a/asmcomp/arm/reload.ml
+++ b/asmcomp/arm/reload.ml
@@ -44,9 +44,9 @@ method! reload_operation op arg res =
   | Iabsf | Inegf when !fpu = Soft ->
       (* Soft FP neg and abs also have a "two-address" constraint of sorts.
          64-bit floats are represented by pairs of 32-bit integers,
-	 hence there are two arguments and two results.
-	 The code emitter assumes [arg.(0) = res.(0)] but supports
-	 [arg.(1)] and [res.(1)] being in different registers. *)
+         hence there are two arguments and two results.
+         The code emitter assumes [arg.(0) = res.(0)] but supports
+         [arg.(1)] and [res.(1)] being in different registers. *)
       res'.(0) <- arg'.(0);
       argres'
   | _ ->
diff --git a/asmcomp/arm64/arch.ml b/asmcomp/arm64/arch.ml
index 01362a5e..ce5902aa 100644
--- a/asmcomp/arm64/arch.ml
+++ b/asmcomp/arm64/arch.ml
@@ -38,7 +38,7 @@ type cmm_label = int
   (* Do not introduce a dependency to Cmm *)
 
 type specific_operation =
-  | Ifar_alloc of { words : int; label_after_call_gc : cmm_label option; }
+  | Ifar_alloc of { bytes : int; label_after_call_gc : cmm_label option; }
   | Ifar_intop_checkbound of { label_after_error : cmm_label option; }
   | Ifar_intop_imm_checkbound of
       { bound : int; label_after_error : cmm_label option; }
@@ -107,8 +107,8 @@ let print_addressing printreg addr ppf arg =
 
 let print_specific_operation printreg op ppf arg =
   match op with
-  | Ifar_alloc { words; label_after_call_gc = _; } ->
-    fprintf ppf "(far) alloc %i" words
+  | Ifar_alloc { bytes; label_after_call_gc = _; } ->
+    fprintf ppf "(far) alloc %i" bytes
   | Ifar_intop_checkbound _ ->
     fprintf ppf "%a (far) check > %a" printreg arg.(0) printreg arg.(1)
   | Ifar_intop_imm_checkbound { bound; _ } ->
diff --git a/asmcomp/arm64/emit.mlp b/asmcomp/arm64/emit.mlp
index de15b744..8c855b8d 100644
--- a/asmcomp/arm64/emit.mlp
+++ b/asmcomp/arm64/emit.mlp
@@ -419,11 +419,16 @@ module BR = Branch_relaxation.Make (struct
 
   let offset_pc_at_branch = 0
 
+  let prologue_size () =
+    (if frame_size () > 0 then 2 else 0)
+      + (if !contains_calls then 1 else 0)
+
   let epilogue_size () =
     if !contains_calls then 3 else 2
 
   let instr_size = function
     | Lend -> 0
+    | Lprologue -> prologue_size ()
     | Lop (Imove | Ispill | Ireload) -> 1
     | Lop (Iconst_int n) ->
       num_instructions_for_intconst n
@@ -440,15 +445,15 @@ module BR = Branch_relaxation.Make (struct
     | Lop (Iload (size, addr)) | Lop (Istore (size, addr, _)) ->
       let based = match addr with Iindexed _ -> 0 | Ibased _ -> 1 in
       based + begin match size with Single -> 2 | _ -> 1 end
-    | Lop (Ialloc {words = num_words}) when !fastcode_flag ->
-      if num_words <= 0xFFF then 4 else 5
-    | Lop (Ispecific (Ifar_alloc {words = num_words})) when !fastcode_flag ->
-      if num_words <= 0xFFF then 5 else 6
-    | Lop (Ialloc { words = num_words; _ })
-    | Lop (Ispecific (Ifar_alloc { words = num_words; _ })) ->
-      begin match num_words with
+    | Lop (Ialloc {bytes = num_bytes}) when !fastcode_flag ->
+      if num_bytes <= 0xFFF then 4 else 5
+    | Lop (Ispecific (Ifar_alloc {bytes = num_bytes})) when !fastcode_flag ->
+      if num_bytes <= 0xFFF then 5 else 6
+    | Lop (Ialloc { bytes = num_bytes; _ })
+    | Lop (Ispecific (Ifar_alloc { bytes = num_bytes; _ })) ->
+      begin match num_bytes with
       | 16 | 24 | 32 -> 1
-      | _ -> 1 + num_instructions_for_intconst (Nativeint.of_int num_words)
+      | _ -> 1 + num_instructions_for_intconst (Nativeint.of_int num_bytes)
       end
     | Lop (Iintop (Icomp _)) -> 2
     | Lop (Iintop_imm (Icomp _, _)) -> 2
@@ -498,8 +503,8 @@ module BR = Branch_relaxation.Make (struct
       | Cmm.Raise_notrace -> 4
       end
 
-  let relax_allocation ~num_words ~label_after_call_gc =
-    Lop (Ispecific (Ifar_alloc { words = num_words; label_after_call_gc; }))
+  let relax_allocation ~num_bytes ~label_after_call_gc =
+    Lop (Ispecific (Ifar_alloc { bytes = num_bytes; label_after_call_gc; }))
 
   let relax_intop_checkbound ~label_after_error =
     Lop (Ispecific (Ifar_intop_checkbound { label_after_error; }))
@@ -554,12 +559,33 @@ let assembly_code_for_allocation ?label_after_call_gc i ~n ~far =
     `{emit_label lbl_frame}:	add	{emit_reg i.res.(0)}, {emit_reg reg_alloc_ptr}, #8\n`
   end
 
+(* Emission of the profiling prelude *)
+
+let emit_profile() = ()   (* TODO *)
+(*
+  match Config.system with
+    "linux_eabi" | "linux_eabihf" | "netbsd" ->
+      `	push	\{lr}\n`;
+      `	{emit_call "__gnu_mcount_nc"}\n`
+  | _ -> ()
+*)
+
 (* Output the assembly code for an instruction *)
 
 let emit_instr i =
     emit_debug_info i.dbg;
     match i.desc with
     | Lend -> ()
+    | Lprologue ->
+      if !Clflags.gprofile then emit_profile();
+      let n = frame_size() in
+      if n > 0 then
+        emit_stack_adjustment (-n);
+      if !contains_calls then begin
+        cfi_offset ~reg:30 (* return address *) ~offset:(-8);
+        `	str	x30, [sp, #{emit_int (n-8)}]\n`
+      end;
+      `{emit_label !tailrec_entry_point}:\n`;
     | Lop(Imove | Ispill | Ireload) ->
         let src = i.arg.(0) and dst = i.res.(0) in
         if src.loc <> dst.loc then begin
@@ -662,9 +688,9 @@ let emit_instr i =
         | Word_int | Word_val | Double | Double_u ->
             `	str	{emit_reg src}, {emit_addressing addr base}\n`
         end
-    | Lop(Ialloc { words = n; label_after_call_gc; }) ->
+    | Lop(Ialloc { bytes = n; label_after_call_gc; }) ->
         assembly_code_for_allocation i ~n ~far:false ?label_after_call_gc
-    | Lop(Ispecific (Ifar_alloc { words = n; label_after_call_gc; })) ->
+    | Lop(Ispecific (Ifar_alloc { bytes = n; label_after_call_gc; })) ->
         assembly_code_for_allocation i ~n ~far:true ?label_after_call_gc
     | Lop(Iintop(Icomp cmp)) ->
         `	cmp	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
@@ -879,17 +905,6 @@ let emit_instr i =
 let rec emit_all i =
   if i.desc = Lend then () else (emit_instr i; emit_all i.next)
 
-(* Emission of the profiling prelude *)
-
-let emit_profile() = ()   (* TODO *)
-(*
-  match Config.system with
-    "linux_eabi" | "linux_eabihf" | "netbsd" ->
-      `	push	\{lr}\n`;
-      `	{emit_call "__gnu_mcount_nc"}\n`
-  | _ -> ()
-*)
-
 (* Emission of a function declaration *)
 
 let fundecl fundecl =
@@ -907,15 +922,6 @@ let fundecl fundecl =
   `{emit_symbol fundecl.fun_name}:\n`;
   emit_debug_info fundecl.fun_dbg;
   cfi_startproc();
-  if !Clflags.gprofile then emit_profile();
-  let n = frame_size() in
-  if n > 0 then
-    emit_stack_adjustment (-n);
-  if !contains_calls then begin
-    cfi_offset ~reg:30 (* return address *) ~offset:(-8);
-    `	str	x30, [sp, #{emit_int (n-8)}]\n`
-  end;
-  `{emit_label !tailrec_entry_point}:\n`;
   let num_call_gc, num_check_bound =
     num_call_gc_and_check_bound_points fundecl.fun_body
   in
diff --git a/asmcomp/arm64/proc.ml b/asmcomp/arm64/proc.ml
index 30c69cb9..14ba08d5 100644
--- a/asmcomp/arm64/proc.ml
+++ b/asmcomp/arm64/proc.ml
@@ -171,6 +171,31 @@ let loc_external_results res =
 
 let loc_exn_bucket = phys_reg 0
 
+(* See "DWARF for the ARM 64-bit architecture (AArch64)" available from
+   developer.arm.com. *)
+
+let int_dwarf_reg_numbers =
+  [| 0; 1; 2; 3; 4; 5; 6; 7;
+     8; 9; 10; 11; 12; 13; 14; 15;
+     19; 20; 21; 22; 23; 24; 25;
+     26; 27; 28; 16; 17;
+  |]
+
+let float_dwarf_reg_numbers =
+  [| 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;
+  |]
+
+let dwarf_register_numbers ~reg_class =
+  match reg_class with
+  | 0 -> int_dwarf_reg_numbers
+  | 1 -> float_dwarf_reg_numbers
+  | _ -> Misc.fatal_errorf "Bad register class %d" reg_class
+
+let stack_ptr_dwarf_register_number = 31
+
 (* Volatile registers: none *)
 
 let regs_are_volatile _rs = false
@@ -198,6 +223,8 @@ let destroyed_at_oper = function
 
 let destroyed_at_raise = all_phys_regs
 
+let destroyed_at_reloadretaddr = [| |]
+
 (* Maximal register pressure *)
 
 let safe_register_pressure = function
@@ -230,8 +257,9 @@ let contains_calls = ref false
 (* Calling the assembler *)
 
 let assemble_file infile outfile =
-  Ccomp.command (Config.asm ^ " -o " ^
-                 Filename.quote outfile ^ " " ^ Filename.quote infile)
+  Ccomp.command (Config.asm ^ " " ^
+                 (String.concat " " (Misc.debug_prefix_map_flags ())) ^
+                 " -o " ^ Filename.quote outfile ^ " " ^ Filename.quote infile)
 
 
 let init () = ()
diff --git a/asmcomp/asmgen.ml b/asmcomp/asmgen.ml
index c3bd1cb5..ddbbae8d 100644
--- a/asmcomp/asmgen.ml
+++ b/asmcomp/asmgen.ml
@@ -27,8 +27,7 @@ type error = Assembler_error of string
 
 exception Error of error
 
-let liveness ppf phrase =
-  Liveness.fundecl ppf phrase; phrase
+let liveness phrase = Liveness.fundecl phrase; phrase
 
 let dump_if ppf flag message phrase =
   if !flag then Printmach.phase message ppf phrase
@@ -75,73 +74,73 @@ let raw_clambda_dump_if ppf
     end;
   if !dump_cmm then Format.fprintf ppf "@.cmm:@."
 
-let rec regalloc ppf round fd =
+let rec regalloc ~ppf_dump round fd =
   if round > 50 then
     fatal_error(fd.Mach.fun_name ^
                 ": function too complex, cannot complete register allocation");
-  dump_if ppf dump_live "Liveness analysis" fd;
+  dump_if ppf_dump dump_live "Liveness analysis" fd;
   if !use_linscan then begin
     (* Linear Scan *)
     Interval.build_intervals fd;
-    if !dump_interval then Printmach.intervals ppf ();
+    if !dump_interval then Printmach.intervals ppf_dump ();
     Linscan.allocate_registers()
   end else begin
     (* Graph Coloring *)
     Interf.build_graph fd;
-    if !dump_interf then Printmach.interferences ppf ();
-    if !dump_prefer then Printmach.preferences ppf ();
+    if !dump_interf then Printmach.interferences ppf_dump ();
+    if !dump_prefer then Printmach.preferences ppf_dump ();
     Coloring.allocate_registers()
   end;
-  dump_if ppf dump_regalloc "After register allocation" fd;
+  dump_if ppf_dump dump_regalloc "After register allocation" fd;
   let (newfd, redo_regalloc) = Reload.fundecl fd in
-  dump_if ppf dump_reload "After insertion of reloading code" newfd;
+  dump_if ppf_dump dump_reload "After insertion of reloading code" newfd;
   if redo_regalloc then begin
-    Reg.reinit(); Liveness.fundecl ppf newfd; regalloc ppf (round + 1) newfd
+    Reg.reinit(); Liveness.fundecl newfd; regalloc ~ppf_dump (round + 1) newfd
   end else newfd
 
 let (++) x f = f x
 
-let compile_fundecl (ppf : formatter) fd_cmm =
+let compile_fundecl ~ppf_dump fd_cmm =
   Proc.init ();
   Reg.reset();
   fd_cmm
   ++ Profile.record ~accumulate:true "selection" Selection.fundecl
-  ++ pass_dump_if ppf dump_selection "After instruction selection"
+  ++ pass_dump_if ppf_dump dump_selection "After instruction selection"
   ++ Profile.record ~accumulate:true "comballoc" Comballoc.fundecl
-  ++ pass_dump_if ppf dump_combine "After allocation combining"
+  ++ pass_dump_if ppf_dump dump_combine "After allocation combining"
   ++ Profile.record ~accumulate:true "cse" CSE.fundecl
-  ++ pass_dump_if ppf dump_cse "After CSE"
-  ++ Profile.record ~accumulate:true "liveness" (liveness ppf)
+  ++ pass_dump_if ppf_dump dump_cse "After CSE"
+  ++ Profile.record ~accumulate:true "liveness" liveness
   ++ Profile.record ~accumulate:true "deadcode" Deadcode.fundecl
-  ++ pass_dump_if ppf dump_live "Liveness analysis"
+  ++ pass_dump_if ppf_dump dump_live "Liveness analysis"
   ++ Profile.record ~accumulate:true "spill" Spill.fundecl
-  ++ Profile.record ~accumulate:true "liveness" (liveness ppf)
-  ++ pass_dump_if ppf dump_spill "After spilling"
+  ++ Profile.record ~accumulate:true "liveness" liveness
+  ++ pass_dump_if ppf_dump dump_spill "After spilling"
   ++ Profile.record ~accumulate:true "split" Split.fundecl
-  ++ pass_dump_if ppf dump_split "After live range splitting"
-  ++ Profile.record ~accumulate:true "liveness" (liveness ppf)
-  ++ Profile.record ~accumulate:true "regalloc" (regalloc ppf 1)
+  ++ pass_dump_if ppf_dump dump_split "After live range splitting"
+  ++ Profile.record ~accumulate:true "liveness" liveness
+  ++ Profile.record ~accumulate:true "regalloc" (regalloc ~ppf_dump 1)
   ++ Profile.record ~accumulate:true "available_regs" Available_regs.fundecl
   ++ Profile.record ~accumulate:true "linearize" Linearize.fundecl
-  ++ pass_dump_linear_if ppf dump_linear "Linearized code"
+  ++ pass_dump_linear_if ppf_dump dump_linear "Linearized code"
   ++ Profile.record ~accumulate:true "scheduling" Scheduling.fundecl
-  ++ pass_dump_linear_if ppf dump_scheduling "After instruction scheduling"
+  ++ pass_dump_linear_if ppf_dump dump_scheduling "After instruction scheduling"
   ++ Profile.record ~accumulate:true "emit" Emit.fundecl
 
-let compile_phrase ppf p =
-  if !dump_cmm then fprintf ppf "%a@." Printcmm.phrase p;
+let compile_phrase ~ppf_dump p =
+  if !dump_cmm then fprintf ppf_dump "%a@." Printcmm.phrase p;
   match p with
-  | Cfunction fd -> compile_fundecl ppf fd
+  | Cfunction fd -> compile_fundecl ~ppf_dump fd
   | Cdata dl -> Emit.data dl
 
 
 (* For the native toplevel: generates generic functions unless
    they are already available in the process *)
-let compile_genfuns ppf f =
+let compile_genfuns ~ppf_dump f =
   List.iter
     (function
        | (Cfunction {fun_name = name}) as ph when f name ->
-           compile_phrase ppf ph
+           compile_phrase ~ppf_dump ph
        | _ -> ())
     (Cmmgen.generic_functions true [Compilenv.current_unit_infos ()])
 
@@ -149,39 +148,36 @@ let compile_unit _output_prefix asm_filename keep_asm
       obj_filename gen =
   let create_asm = keep_asm || not !Emitaux.binary_backend_available in
   Emitaux.create_asm_file := create_asm;
-  try
-    if create_asm then Emitaux.output_channel := open_out asm_filename;
-    begin try
-      gen ();
-      if create_asm then close_out !Emitaux.output_channel;
-    with exn when create_asm ->
-      close_out !Emitaux.output_channel;
-      if not keep_asm then remove_file asm_filename;
-      raise exn
-    end;
-    let assemble_result =
-      Profile.record "assemble"
-        (Proc.assemble_file asm_filename) obj_filename
-    in
-    if assemble_result <> 0
-    then raise(Error(Assembler_error asm_filename));
-    if create_asm && not keep_asm then remove_file asm_filename
-  with exn ->
-    remove_file obj_filename;
-    raise exn
+  Misc.try_finally
+    ~exceptionally:(fun () -> remove_file obj_filename)
+    (fun () ->
+       if create_asm then Emitaux.output_channel := open_out asm_filename;
+       Misc.try_finally gen
+         ~always:(fun () ->
+             if create_asm then close_out !Emitaux.output_channel)
+         ~exceptionally:(fun () ->
+             if create_asm && not keep_asm then remove_file asm_filename);
+       let assemble_result =
+         Profile.record "assemble"
+           (Proc.assemble_file asm_filename) obj_filename
+       in
+       if assemble_result <> 0
+       then raise(Error(Assembler_error asm_filename));
+       if create_asm && not keep_asm then remove_file asm_filename
+    )
 
 let set_export_info (ulambda, prealloc, structured_constants, export) =
   Compilenv.set_export_info export;
   (ulambda, prealloc, structured_constants)
 
-let end_gen_implementation ?toplevel ppf
+let end_gen_implementation ?toplevel ~ppf_dump
     (clambda:clambda_and_constants) =
   Emit.begin_assembly ();
   clambda
-  ++ Profile.record "cmm" Cmmgen.compunit
-  ++ Profile.record "compile_phrases" (List.iter (compile_phrase ppf))
+  ++ Profile.record "cmm" (Cmmgen.compunit ~ppf_dump)
+  ++ Profile.record "compile_phrases" (List.iter (compile_phrase ~ppf_dump))
   ++ (fun () -> ());
-  (match toplevel with None -> () | Some f -> compile_genfuns ppf f);
+  (match toplevel with None -> () | Some f -> compile_genfuns ~ppf_dump f);
 
   (* We add explicit references to external primitive symbols.  This
      is to ensure that the object files that define these symbols,
@@ -189,26 +185,26 @@ let end_gen_implementation ?toplevel ppf
      This is important if a module that uses such a symbol is later
      dynlinked. *)
 
-  compile_phrase ppf
+  compile_phrase ~ppf_dump
     (Cmmgen.reference_symbols
        (List.filter (fun s -> s <> "" && s.[0] <> '%')
           (List.map Primitive.native_name !Translmod.primitive_declarations))
     );
   Emit.end_assembly ()
 
-let flambda_gen_implementation ?toplevel ~backend ppf
+let flambda_gen_implementation ?toplevel ~backend ~ppf_dump
     (program:Flambda.program) =
   let export = Build_export_info.build_transient ~backend program in
   let (clambda, preallocated, constants) =
     Profile.record_call "backend" (fun () ->
       (program, export)
       ++ Flambda_to_clambda.convert
-      ++ flambda_raw_clambda_dump_if ppf
+      ++ flambda_raw_clambda_dump_if ppf_dump
       ++ (fun { Flambda_to_clambda. expr; preallocated_blocks;
                 structured_constants; exported; } ->
              (* "init_code" following the name used in
                 [Cmmgen.compunit_and_constants]. *)
-           Un_anf.apply expr ~what:"init_code", preallocated_blocks,
+           Un_anf.apply ~ppf_dump expr ~what:"init_code", preallocated_blocks,
            structured_constants, exported)
       ++ set_export_info)
   in
@@ -216,31 +212,40 @@ let flambda_gen_implementation ?toplevel ~backend ppf
     List.map (fun (symbol, definition) ->
         { Clambda.symbol = Linkage_name.to_string (Symbol.label symbol);
           exported = true;
-          definition })
+          definition;
+          provenance = None;
+        })
       (Symbol.Map.bindings constants)
   in
-  end_gen_implementation ?toplevel ppf
+  end_gen_implementation ?toplevel ~ppf_dump
     (clambda, preallocated, constants)
 
-let lambda_gen_implementation ?toplevel ppf
+let lambda_gen_implementation ?toplevel ~ppf_dump
     (lambda:Lambda.program) =
   let clambda = Closure.intro lambda.main_module_block_size lambda.code in
+  let provenance : Clambda.usymbol_provenance =
+    { original_idents = [];
+      module_path =
+        Path.Pident (Ident.create_persistent (Compilenv.current_unit_name ()));
+    }
+  in
   let preallocated_block =
     Clambda.{
       symbol = Compilenv.make_symbol None;
       exported = true;
       tag = 0;
       fields = List.init lambda.main_module_block_size (fun _ -> None);
+      provenance = Some provenance;
     }
   in
   let clambda_and_constants =
     clambda, [preallocated_block], []
   in
-  raw_clambda_dump_if ppf clambda_and_constants;
-  end_gen_implementation ?toplevel ppf clambda_and_constants
+  raw_clambda_dump_if ppf_dump clambda_and_constants;
+  end_gen_implementation ?toplevel ~ppf_dump clambda_and_constants
 
 let compile_implementation_gen ?toplevel prefixname
-    ~required_globals ppf gen_implementation program =
+    ~required_globals ~ppf_dump gen_implementation program =
   let asmfile =
     if !keep_asm_file || !Emitaux.binary_backend_available
     then prefixname ^ ext_asm
@@ -249,18 +254,18 @@ let compile_implementation_gen ?toplevel prefixname
   compile_unit prefixname asmfile !keep_asm_file
       (prefixname ^ ext_obj) (fun () ->
         Ident.Set.iter Compilenv.require_global required_globals;
-        gen_implementation ?toplevel ppf program)
+        gen_implementation ?toplevel ~ppf_dump program)
 
 let compile_implementation_clambda ?toplevel prefixname
-    ppf (program:Lambda.program) =
+    ~ppf_dump (program:Lambda.program) =
   compile_implementation_gen ?toplevel prefixname
     ~required_globals:program.Lambda.required_globals
-    ppf lambda_gen_implementation program
+    ~ppf_dump lambda_gen_implementation program
 
 let compile_implementation_flambda ?toplevel prefixname
-    ~required_globals ~backend ppf (program:Flambda.program) =
+    ~required_globals ~backend ~ppf_dump (program:Flambda.program) =
   compile_implementation_gen ?toplevel prefixname
-    ~required_globals ppf (flambda_gen_implementation ~backend) program
+    ~required_globals ~ppf_dump (flambda_gen_implementation ~backend) program
 
 (* Error report *)
 
diff --git a/asmcomp/asmgen.mli b/asmcomp/asmgen.mli
index e70ee511..f2f4ccae 100644
--- a/asmcomp/asmgen.mli
+++ b/asmcomp/asmgen.mli
@@ -20,15 +20,15 @@ val compile_implementation_flambda :
     string ->
     required_globals:Ident.Set.t ->
     backend:(module Backend_intf.S) ->
-    Format.formatter -> Flambda.program -> unit
+    ppf_dump:Format.formatter -> Flambda.program -> unit
 
 val compile_implementation_clambda :
     ?toplevel:(string -> bool) ->
     string ->
-    Format.formatter -> Lambda.program -> unit
+    ppf_dump:Format.formatter -> Lambda.program -> unit
 
 val compile_phrase :
-    Format.formatter -> Cmm.phrase -> unit
+    ppf_dump:Format.formatter -> Cmm.phrase -> unit
 
 type error = Assembler_error of string
 exception Error of error
diff --git a/asmcomp/asmlibrarian.ml b/asmcomp/asmlibrarian.ml
index 6545a9f5..ba1d06b2 100644
--- a/asmcomp/asmlibrarian.ml
+++ b/asmcomp/asmlibrarian.ml
@@ -34,7 +34,7 @@ let default_ui_export_info =
 let read_info name =
   let filename =
     try
-      find_in_path !load_path name
+      Load_path.find name
     with Not_found ->
       raise(Error(File_not_found name)) in
   let (info, crc) = Compilenv.read_unit_info filename in
@@ -49,27 +49,25 @@ let read_info name =
 let create_archive file_list lib_name =
   let archive_name = Filename.remove_extension lib_name ^ ext_lib in
   let outchan = open_out_bin lib_name in
-  try
-    output_string outchan cmxa_magic_number;
-    let (objfile_list, descr_list) =
-      List.split (List.map read_info file_list) in
-    List.iter2
-      (fun file_name (unit, crc) ->
-        Asmlink.check_consistency file_name unit crc)
-      file_list descr_list;
-    let infos =
-      { lib_units = descr_list;
-        lib_ccobjs = !Clflags.ccobjs;
-        lib_ccopts = !Clflags.all_ccopts } in
-    output_value outchan infos;
-    if Ccomp.create_archive archive_name objfile_list <> 0
-    then raise(Error(Archiver_error archive_name));
-    close_out outchan
-  with x ->
-    close_out outchan;
-    remove_file lib_name;
-    remove_file archive_name;
-    raise x
+  Misc.try_finally
+    ~always:(fun () -> close_out outchan)
+    ~exceptionally:(fun () -> remove_file lib_name; remove_file archive_name)
+    (fun () ->
+       output_string outchan cmxa_magic_number;
+       let (objfile_list, descr_list) =
+         List.split (List.map read_info file_list) in
+       List.iter2
+         (fun file_name (unit, crc) ->
+            Asmlink.check_consistency file_name unit crc)
+         file_list descr_list;
+       let infos =
+         { lib_units = descr_list;
+           lib_ccobjs = !Clflags.ccobjs;
+           lib_ccopts = !Clflags.all_ccopts } in
+       output_value outchan infos;
+       if Ccomp.create_archive archive_name objfile_list <> 0
+       then raise(Error(Archiver_error archive_name));
+    )
 
 open Format
 
diff --git a/asmcomp/asmlink.ml b/asmcomp/asmlink.ml
index 90617dc8..f77b6cc3 100644
--- a/asmcomp/asmlink.ml
+++ b/asmcomp/asmlink.ml
@@ -20,6 +20,8 @@ open Config
 open Cmx_format
 open Compilenv
 
+module String = Misc.Stdlib.String
+
 type error =
     File_not_found of string
   | Not_an_object_file of string
@@ -110,14 +112,14 @@ let runtime_lib () =
     else "libasmrun" ^ !Clflags.runtime_variant ^ ext_lib in
   try
     if !Clflags.nopervasives then []
-    else [ find_in_path !load_path libname ]
+    else [ Load_path.find libname ]
   with Not_found ->
     raise(Error(File_not_found libname))
 
 let object_file_name name =
   let file_name =
     try
-      find_in_path !load_path name
+      Load_path.find name
     with Not_found ->
       fatal_errorf "Asmlink.object_file_name: %s not found" name in
   if Filename.check_suffix file_name ".cmx" then
@@ -157,7 +159,7 @@ type file =
 let read_file obj_name =
   let file_name =
     try
-      find_in_path !load_path obj_name
+      Load_path.find obj_name
     with Not_found ->
       raise(Error(File_not_found obj_name)) in
   if Filename.check_suffix file_name ".cmx" then begin
@@ -203,11 +205,25 @@ let scan_file obj_name tolink = match read_file obj_name with
 
 (* Second pass: generate the startup file and link it with everything else *)
 
-let force_linking_of_startup ppf =
-  Asmgen.compile_phrase ppf (Cmm.Cdata ([Cmm.Csymbol_address "caml_startup"]))
+let force_linking_of_startup ~ppf_dump =
+  Asmgen.compile_phrase ~ppf_dump
+    (Cmm.Cdata ([Cmm.Csymbol_address "caml_startup"]))
+
+let make_globals_map units_list ~crc_interfaces =
+  let crc_interfaces = String.Tbl.of_seq (List.to_seq crc_interfaces) in
+  let defined =
+    List.map (fun (unit, _, impl_crc) ->
+        let intf_crc = String.Tbl.find crc_interfaces unit.ui_name in
+        String.Tbl.remove crc_interfaces unit.ui_name;
+        (unit.ui_name, intf_crc, Some impl_crc, unit.ui_defines))
+      units_list
+  in
+  String.Tbl.fold (fun name intf acc ->
+      (name, intf, None, []) :: acc)
+    crc_interfaces defined
 
-let make_startup_file ppf units_list =
-  let compile_phrase p = Asmgen.compile_phrase ppf p in
+let make_startup_file ~ppf_dump units_list ~crc_interfaces =
+  let compile_phrase p = Asmgen.compile_phrase ~ppf_dump p in
   Location.input_name := "caml_startup"; (* set name of "current" input *)
   Compilenv.reset "_startup";
   (* set the name of the "current" compunit *)
@@ -221,19 +237,8 @@ let make_startup_file ppf units_list =
     (fun i name -> compile_phrase (Cmmgen.predef_exception i name))
     Runtimedef.builtin_exceptions;
   compile_phrase (Cmmgen.global_table name_list);
-  compile_phrase
-    (Cmmgen.globals_map
-       (List.map
-          (fun (unit,_,crc) ->
-               let intf_crc =
-                 try
-                   match List.assoc unit.ui_name unit.ui_imports_cmi with
-                     None -> assert false
-                   | Some crc -> crc
-                 with Not_found -> assert false
-               in
-                 (unit.ui_name, intf_crc, crc, unit.ui_defines))
-          units_list));
+  let globals_map = make_globals_map units_list ~crc_interfaces in
+  compile_phrase (Cmmgen.globals_map globals_map);
   compile_phrase(Cmmgen.data_segment_table ("_startup" :: name_list));
   compile_phrase(Cmmgen.code_segment_table ("_startup" :: name_list));
   let all_names = "_startup" :: "_system" :: name_list in
@@ -242,11 +247,11 @@ let make_startup_file ppf units_list =
     compile_phrase (Cmmgen.spacetime_shapes all_names);
   end;
   if !Clflags.output_complete_object then
-    force_linking_of_startup ppf;
+    force_linking_of_startup ~ppf_dump;
   Emit.end_assembly ()
 
-let make_shared_startup_file ppf units =
-  let compile_phrase p = Asmgen.compile_phrase ppf p in
+let make_shared_startup_file ~ppf_dump units =
+  let compile_phrase p = Asmgen.compile_phrase ~ppf_dump p in
   Location.input_name := "caml_startup";
   Compilenv.reset "_shared_startup";
   Emit.begin_assembly ();
@@ -257,7 +262,7 @@ let make_shared_startup_file ppf units =
     (Cmmgen.global_table
        (List.map (fun (ui,_) -> ui.ui_symbol) units));
   if !Clflags.output_complete_object then
-    force_linking_of_startup ppf;
+    force_linking_of_startup ~ppf_dump;
   (* this is to force a reference to all units, otherwise the linker
      might drop some of them (in case of libraries) *)
   Emit.end_assembly ()
@@ -266,7 +271,7 @@ let call_linker_shared file_list output_name =
   if not (Ccomp.call_linker Ccomp.Dll output_name file_list "")
   then raise(Error Linking_error)
 
-let link_shared ppf objfiles output_name =
+let link_shared ~ppf_dump objfiles output_name =
   Profile.record_call output_name (fun () ->
     let units_tolink = List.fold_right scan_file objfiles [] in
     List.iter
@@ -285,7 +290,7 @@ let link_shared ppf objfiles output_name =
     Asmgen.compile_unit output_name
       startup !Clflags.keep_startup_file startup_obj
       (fun () ->
-         make_shared_startup_file ppf
+         make_shared_startup_file ~ppf_dump
            (List.map (fun (ui,_,crc) -> (ui,crc)) units_tolink)
       );
     call_linker_shared (startup_obj :: objfiles) output_name;
@@ -321,7 +326,7 @@ let call_linker file_list startup_file output_name =
 
 (* Main entry point *)
 
-let link ppf objfiles output_name =
+let link ~ppf_dump objfiles output_name =
   Profile.record_call output_name (fun () ->
     let stdlib =
       if !Clflags.gprofile then "stdlib.p.cmxa" else "stdlib.cmxa" in
@@ -340,6 +345,7 @@ let link ppf objfiles output_name =
     List.iter
       (fun (info, file_name, crc) -> check_consistency file_name info crc)
       units_tolink;
+    let crc_interfaces = extract_crc_interfaces () in
     Clflags.ccobjs := !Clflags.ccobjs @ !lib_ccobjs;
     Clflags.all_ccopts := !lib_ccopts @ !Clflags.all_ccopts;
                                                  (* put user's opts first *)
@@ -350,11 +356,12 @@ let link ppf objfiles output_name =
     let startup_obj = Filename.temp_file "camlstartup" ext_obj in
     Asmgen.compile_unit output_name
       startup !Clflags.keep_startup_file startup_obj
-      (fun () -> make_startup_file ppf units_tolink);
+      (fun () -> make_startup_file ~ppf_dump units_tolink ~crc_interfaces);
     Misc.try_finally
       (fun () ->
-        call_linker (List.map object_file_name objfiles) startup_obj output_name)
-      (fun () -> remove_file startup_obj)
+         call_linker (List.map object_file_name objfiles)
+           startup_obj output_name)
+      ~always:(fun () -> remove_file startup_obj)
   )
 
 (* Error report *)
diff --git a/asmcomp/asmlink.mli b/asmcomp/asmlink.mli
index 55310bd9..80d66099 100644
--- a/asmcomp/asmlink.mli
+++ b/asmcomp/asmlink.mli
@@ -17,9 +17,9 @@
 
 open Format
 
-val link: formatter -> string list -> string -> unit
+val link: ppf_dump:formatter -> string list -> string -> unit
 
-val link_shared: formatter -> string list -> string -> unit
+val link_shared: ppf_dump:formatter -> string list -> string -> unit
 
 val call_linker_shared: string list -> string -> unit
 
diff --git a/asmcomp/asmpackager.ml b/asmcomp/asmpackager.ml
index 5a8c2794..cddb3463 100644
--- a/asmcomp/asmpackager.ml
+++ b/asmcomp/asmpackager.ml
@@ -79,7 +79,7 @@ let check_units members =
 
 (* Make the .o file for the package *)
 
-let make_package_object ppf members targetobj targetname coercion
+let make_package_object ~ppf_dump members targetobj targetname coercion
       ~backend =
   Profile.record_call (Printf.sprintf "pack(%s)" targetname) (fun () ->
     let objtemp =
@@ -102,7 +102,7 @@ let make_package_object ppf members targetobj targetname coercion
     if Config.flambda then begin
       let size, lam = Translmod.transl_package_flambda components coercion in
       let flam =
-        Middle_end.middle_end ppf
+        Middle_end.middle_end ~ppf_dump
           ~prefixname
           ~backend
           ~size
@@ -111,13 +111,13 @@ let make_package_object ppf members targetobj targetname coercion
           ~module_initializer:lam
       in
       Asmgen.compile_implementation_flambda
-        prefixname ~backend ~required_globals:Ident.Set.empty ppf flam;
+        prefixname ~backend ~required_globals:Ident.Set.empty ~ppf_dump flam;
     end else begin
       let main_module_block_size, code =
         Translmod.transl_store_package
           components (Ident.create_persistent targetname) coercion in
       Asmgen.compile_implementation_clambda
-        prefixname ppf { Lambda.code; main_module_block_size;
+        prefixname ~ppf_dump { Lambda.code; main_module_block_size;
                          module_ident; required_globals = Ident.Set.empty }
     end;
     let objfiles =
@@ -220,7 +220,7 @@ let build_package_cmx members cmxfile =
 
 (* Make the .cmx and the .o for the package *)
 
-let package_object_files ppf files targetcmx
+let package_object_files ~ppf_dump files targetcmx
                          targetobj targetname coercion ~backend =
   let pack_path =
     match !Clflags.for_package with
@@ -228,16 +228,16 @@ let package_object_files ppf files targetcmx
     | Some p -> p ^ "." ^ targetname in
   let members = map_left_right (read_member_info pack_path) files in
   check_units members;
-  make_package_object ppf members targetobj targetname coercion ~backend;
+  make_package_object ~ppf_dump members targetobj targetname coercion ~backend;
   build_package_cmx members targetcmx
 
 (* The entry point *)
 
-let package_files ppf initial_env files targetcmx ~backend =
+let package_files ~ppf_dump initial_env files targetcmx ~backend =
   let files =
     List.map
       (fun f ->
-        try find_in_path !Config.load_path f
+        try Load_path.find f
         with Not_found -> raise(Error(File_not_found f)))
       files in
   let prefix = chop_extensions targetcmx in
@@ -248,14 +248,13 @@ let package_files ppf initial_env files targetcmx ~backend =
   Location.input_name := targetcmx;
   (* Set the name of the current compunit *)
   Compilenv.reset ?packname:!Clflags.for_package targetname;
-  try
-    let coercion =
-      Typemod.package_units initial_env files targetcmi targetname in
-    package_object_files ppf files targetcmx targetobj targetname coercion
-      ~backend
-  with x ->
-    remove_file targetcmx; remove_file targetobj;
-    raise x
+  Misc.try_finally (fun () ->
+      let coercion =
+        Typemod.package_units initial_env files targetcmi targetname in
+      package_object_files ~ppf_dump files targetcmx targetobj targetname
+        coercion ~backend
+    )
+    ~exceptionally:(fun () -> remove_file targetcmx; remove_file targetobj)
 
 (* Error report *)
 
diff --git a/asmcomp/asmpackager.mli b/asmcomp/asmpackager.mli
index 203fc301..3ea21425 100644
--- a/asmcomp/asmpackager.mli
+++ b/asmcomp/asmpackager.mli
@@ -17,7 +17,7 @@
    original compilation units as sub-modules. *)
 
 val package_files
-   : Format.formatter
+   : ppf_dump:Format.formatter
   -> Env.t
   -> string list
   -> string
diff --git a/asmcomp/backend_var.ml b/asmcomp/backend_var.ml
new file mode 100644
index 00000000..39af7f60
--- /dev/null
+++ b/asmcomp/backend_var.ml
@@ -0,0 +1,87 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                  Mark Shinwell, Jane Street Europe                     *)
+(*                                                                        *)
+(*   Copyright 2018 Jane Street Group LLC                                 *)
+(*                                                                        *)
+(*   All rights reserved.  This file is distributed under the terms of    *)
+(*   the GNU Lesser General Public License version 2.1, with the          *)
+(*   special exception on linking described in the file LICENSE.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-30-40-41-42"]
+
+include Ident
+
+type backend_var = t
+
+module Provenance = struct
+  type t = {
+    module_path : Path.t;
+    location : Debuginfo.t;
+    original_ident : Ident.t;
+  }
+
+  let print ppf { module_path; location; original_ident; } =
+    Format.fprintf ppf "@[(\
+        @[(module_path@ %a)@]@ \
+        @[(location@ %a)@]@ \
+        @[(original_ident@ %a)@]\
+        )@]"
+      Path.print module_path
+      Debuginfo.print_compact location
+      Ident.print original_ident
+
+  let create ~module_path ~location ~original_ident =
+    { module_path;
+      location;
+      original_ident;
+    }
+
+  let module_path t = t.module_path
+  let location t = t.location
+  let original_ident t = t.original_ident
+end
+
+module With_provenance = struct
+  type t =
+    | Without_provenance of backend_var
+    | With_provenance of {
+        var : backend_var;
+        provenance : Provenance.t;
+      }
+
+  let create ?provenance var =
+    match provenance with
+    | None -> Without_provenance var
+    | Some provenance -> With_provenance { var; provenance; }
+
+  let var t =
+    match t with
+    | Without_provenance var
+    | With_provenance { var; provenance = _; } -> var
+
+  let provenance t =
+    match t with
+    | Without_provenance _ -> None
+    | With_provenance { var = _; provenance; } -> Some provenance
+
+  let name t = name (var t)
+
+  let rename t =
+    let var = rename (var t) in
+    match provenance t with
+    | None -> Without_provenance var
+    | Some provenance -> With_provenance { var; provenance; }
+
+  let print ppf t =
+    match provenance t with
+    | None -> print ppf (var t)
+    | Some provenance ->
+      Format.fprintf ppf "%a[%a]"
+        print (var t)
+        Provenance.print provenance
+end
diff --git a/asmcomp/backend_var.mli b/asmcomp/backend_var.mli
new file mode 100644
index 00000000..f236be1e
--- /dev/null
+++ b/asmcomp/backend_var.mli
@@ -0,0 +1,54 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                  Mark Shinwell, Jane Street Europe                     *)
+(*                                                                        *)
+(*   Copyright 2018 Jane Street Group LLC                                 *)
+(*                                                                        *)
+(*   All rights reserved.  This file is distributed under the terms of    *)
+(*   the GNU Lesser General Public License version 2.1, with the          *)
+(*   special exception on linking described in the file LICENSE.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Variables used in the backend, optionally equipped with "provenance"
+    information, used for the emission of debugging information. *)
+
+[@@@ocaml.warning "+a-4-30-40-41-42"]
+
+include module type of struct include Ident end
+
+type backend_var = t
+
+module Provenance : sig
+  type t
+
+  val create
+     : module_path:Path.t
+    -> location:Debuginfo.t
+    -> original_ident:Ident.t
+    -> t
+
+  val module_path : t -> Path.t
+  val location : t -> Debuginfo.t
+  val original_ident : t -> Ident.t
+
+  val print : Format.formatter -> t -> unit
+end
+
+module With_provenance : sig
+  (** Values of type [t] should be used for variables in binding position. *)
+  type t
+
+  val print : Format.formatter -> t -> unit
+
+  val create : ?provenance:Provenance.t -> backend_var -> t
+
+  val var : t -> backend_var
+  val provenance : t -> Provenance.t option
+
+  val name : t -> string
+
+  val rename : t -> t
+end
diff --git a/asmcomp/branch_relaxation.ml b/asmcomp/branch_relaxation.ml
index 6486d19c..f8f90719 100644
--- a/asmcomp/branch_relaxation.ml
+++ b/asmcomp/branch_relaxation.ml
@@ -86,8 +86,8 @@ module Make (T : Branch_relaxation_intf.S) = struct
           fixup did_fix (pc + T.instr_size instr.desc) instr.next
         else
           match instr.desc with
-          | Lop (Ialloc { words = num_words; label_after_call_gc; }) ->
-            instr.desc <- T.relax_allocation ~num_words ~label_after_call_gc;
+          | Lop (Ialloc { bytes = num_bytes; label_after_call_gc; }) ->
+            instr.desc <- T.relax_allocation ~num_bytes ~label_after_call_gc;
             fixup true (pc + T.instr_size instr.desc) instr.next
           | Lop (Iintop (Icheckbound { label_after_error; })) ->
             instr.desc <- T.relax_intop_checkbound ~label_after_error;
diff --git a/asmcomp/branch_relaxation_intf.ml b/asmcomp/branch_relaxation_intf.ml
index 3b1fbac5..f95ab67d 100644
--- a/asmcomp/branch_relaxation_intf.ml
+++ b/asmcomp/branch_relaxation_intf.ml
@@ -61,7 +61,7 @@ module type S = sig
      relaxed generically.  It is assumed that these rewrites do not change
      the size of out-of-line code (cf. branch_relaxation.mli). *)
   val relax_allocation
-     : num_words:int
+     : num_bytes:int
     -> label_after_call_gc:Cmm.label option
     -> Linearize.instruction_desc
   val relax_intop_checkbound
diff --git a/asmcomp/build_export_info.ml b/asmcomp/build_export_info.ml
index bf37e609..88082cf6 100644
--- a/asmcomp/build_export_info.ml
+++ b/asmcomp/build_export_info.ml
@@ -652,13 +652,14 @@ let build_transient ~(backend : (module Backend_intf.S))
       let closure_id_to_set_of_closures_id =
         Set_of_closures_id.Map.fold
           (fun set_of_closure_id
-            (function_declarations : Simple_value_approx.function_declarations) acc ->
-             Variable.Map.fold
-               (fun fun_var _ acc ->
+            (function_declarations : Simple_value_approx.function_declarations)
+            acc ->
+              Variable.Map.fold
+                (fun fun_var _ acc ->
                   let closure_id = Closure_id.wrap fun_var in
                   Closure_id.Map.add closure_id set_of_closure_id acc)
-               function_declarations.funs
-               acc)
+                function_declarations.funs
+                acc)
           function_declarations_map
           Closure_id.Map.empty
       in
@@ -710,4 +711,3 @@ let build_transient ~(backend : (module Backend_intf.S))
       ~relevant_imported_closure_ids
       ~relevant_local_vars_within_closure
       ~relevant_imported_vars_within_closure
-
diff --git a/asmcomp/clambda.ml b/asmcomp/clambda.ml
index dc0d5fd3..0e858f11 100644
--- a/asmcomp/clambda.ml
+++ b/asmcomp/clambda.ml
@@ -36,36 +36,53 @@ and uconstant =
   | Uconst_int of int
   | Uconst_ptr of int
 
+and uphantom_defining_expr =
+  | Uphantom_const of uconstant
+  | Uphantom_var of Backend_var.t
+  | Uphantom_offset_var of { var : Backend_var.t; offset_in_words : int; }
+  | Uphantom_read_field of { var : Backend_var.t; field : int; }
+  | Uphantom_read_symbol_field of { sym : string; field : int; }
+  | Uphantom_block of { tag : int; fields : Backend_var.t list; }
+
 and ulambda =
-    Uvar of Ident.t
+    Uvar of Backend_var.t
   | Uconst of uconstant
   | Udirect_apply of function_label * ulambda list * Debuginfo.t
   | Ugeneric_apply of ulambda * ulambda list * Debuginfo.t
   | Uclosure of ufunction list * ulambda list
   | Uoffset of ulambda * int
-  | Ulet of mutable_flag * value_kind * Ident.t * ulambda * ulambda
-  | Uletrec of (Ident.t * ulambda) list * ulambda
+  | Ulet of mutable_flag * value_kind * Backend_var.With_provenance.t
+      * ulambda * ulambda
+  | Uphantom_let of Backend_var.With_provenance.t
+      * uphantom_defining_expr option * ulambda
+  | Uletrec of (Backend_var.With_provenance.t * ulambda) list * ulambda
   | Uprim of primitive * ulambda list * Debuginfo.t
   | Uswitch of ulambda * ulambda_switch * Debuginfo.t
   | Ustringswitch of ulambda * (string * ulambda) list * ulambda option
   | Ustaticfail of int * ulambda list
-  | Ucatch of int * Ident.t list * ulambda * ulambda
-  | Utrywith of ulambda * Ident.t * ulambda
+  | Ucatch of
+      int *
+      (Backend_var.With_provenance.t * value_kind) list *
+      ulambda *
+      ulambda
+  | Utrywith of ulambda * Backend_var.With_provenance.t * ulambda
   | Uifthenelse of ulambda * ulambda * ulambda
   | Usequence of ulambda * ulambda
   | Uwhile of ulambda * ulambda
-  | Ufor of Ident.t * ulambda * ulambda * direction_flag * ulambda
-  | Uassign of Ident.t * ulambda
+  | Ufor of Backend_var.With_provenance.t * ulambda * ulambda
+      * direction_flag * ulambda
+  | Uassign of Backend_var.t * ulambda
   | Usend of meth_kind * ulambda * ulambda * ulambda list * Debuginfo.t
   | Uunreachable
 
 and ufunction = {
   label  : function_label;
   arity  : int;
-  params : Ident.t list;
+  params : (Backend_var.With_provenance.t * value_kind) list;
+  return : value_kind;
   body   : ulambda;
   dbg    : Debuginfo.t;
-  env    : Ident.t option;
+  env    : Backend_var.t option;
 }
 
 and ulambda_switch =
@@ -80,7 +97,7 @@ type function_description =
   { fun_label: function_label;          (* Label of direct entry point *)
     fun_arity: int;                     (* Number of arguments *)
     mutable fun_closed: bool;           (* True if environment not used *)
-    mutable fun_inline: (Ident.t list * ulambda) option;
+    mutable fun_inline: (Backend_var.With_provenance.t list * ulambda) option;
     mutable fun_float_const_prop: bool  (* Can propagate FP consts *)
   }
 
@@ -95,6 +112,11 @@ type value_approximation =
 
 (* Preallocated globals *)
 
+type usymbol_provenance = {
+  original_idents : Ident.t list;
+  module_path : Path.t;
+}
+
 type uconstant_block_field =
   | Uconst_field_ref of string
   | Uconst_field_int of int
@@ -104,15 +126,17 @@ type preallocated_block = {
   exported : bool;
   tag : int;
   fields : uconstant_block_field option list;
+  provenance : usymbol_provenance option;
 }
 
 type preallocated_constant = {
   symbol : string;
   exported : bool;
   definition : ustructured_constant;
+  provenance : usymbol_provenance option;
 }
 
-(* Comparison functions for constants.  We must not use Pervasives.compare
+(* Comparison functions for constants.  We must not use Stdlib.compare
    because it compares "0.0" and "-0.0" equal.  (PR#6442) *)
 
 let compare_floats x1 x2 =
@@ -134,8 +158,8 @@ let compare_constants c1 c2 =
          Different labels -> different constants, even if the contents
            match, because of string constants that must not be
            reshared. *)
-  | Uconst_int n1, Uconst_int n2 -> Pervasives.compare n1 n2
-  | Uconst_ptr n1, Uconst_ptr n2 -> Pervasives.compare n1 n2
+  | Uconst_int n1, Uconst_int n2 -> Stdlib.compare n1 n2
+  | Uconst_ptr n1, Uconst_ptr n2 -> Stdlib.compare n1 n2
   | Uconst_ref _, _ -> -1
   | Uconst_int _, Uconst_ref _ -> 1
   | Uconst_int _, Uconst_ptr _ -> -1
diff --git a/asmcomp/clambda.mli b/asmcomp/clambda.mli
index e4db85a0..98f3184d 100644
--- a/asmcomp/clambda.mli
+++ b/asmcomp/clambda.mli
@@ -36,36 +36,64 @@ and uconstant =
   | Uconst_int of int
   | Uconst_ptr of int
 
+and uphantom_defining_expr =
+  | Uphantom_const of uconstant
+  (** The phantom-let-bound variable is a constant. *)
+  | Uphantom_var of Backend_var.t
+  (** The phantom-let-bound variable is an alias for another variable. *)
+  | Uphantom_offset_var of { var : Backend_var.t; offset_in_words : int; }
+  (** The phantom-let-bound-variable's value is defined by adding the given
+      number of words to the pointer contained in the given identifier. *)
+  | Uphantom_read_field of { var : Backend_var.t; field : int; }
+  (** The phantom-let-bound-variable's value is found by adding the given
+      number of words to the pointer contained in the given identifier, then
+      dereferencing. *)
+  | Uphantom_read_symbol_field of { sym : string; field : int; }
+  (** As for [Uphantom_read_var_field], but with the pointer specified by
+      a symbol. *)
+  | Uphantom_block of { tag : int; fields : Backend_var.t list; }
+  (** The phantom-let-bound variable points at a block with the given
+      structure. *)
+
 and ulambda =
-    Uvar of Ident.t
+    Uvar of Backend_var.t
   | Uconst of uconstant
   | Udirect_apply of function_label * ulambda list * Debuginfo.t
   | Ugeneric_apply of ulambda * ulambda list * Debuginfo.t
   | Uclosure of ufunction list * ulambda list
   | Uoffset of ulambda * int
-  | Ulet of mutable_flag * value_kind * Ident.t * ulambda * ulambda
-  | Uletrec of (Ident.t * ulambda) list * ulambda
+  | Ulet of mutable_flag * value_kind * Backend_var.With_provenance.t
+      * ulambda * ulambda
+  | Uphantom_let of Backend_var.With_provenance.t
+      * uphantom_defining_expr option * ulambda
+  | Uletrec of (Backend_var.With_provenance.t * ulambda) list * ulambda
   | Uprim of primitive * ulambda list * Debuginfo.t
   | Uswitch of ulambda * ulambda_switch * Debuginfo.t
   | Ustringswitch of ulambda * (string * ulambda) list * ulambda option
   | Ustaticfail of int * ulambda list
-  | Ucatch of int * Ident.t list * ulambda * ulambda
-  | Utrywith of ulambda * Ident.t * ulambda
+  | Ucatch of
+      int *
+      (Backend_var.With_provenance.t * value_kind) list *
+      ulambda *
+      ulambda
+  | Utrywith of ulambda * Backend_var.With_provenance.t * ulambda
   | Uifthenelse of ulambda * ulambda * ulambda
   | Usequence of ulambda * ulambda
   | Uwhile of ulambda * ulambda
-  | Ufor of Ident.t * ulambda * ulambda * direction_flag * ulambda
-  | Uassign of Ident.t * ulambda
+  | Ufor of Backend_var.With_provenance.t * ulambda * ulambda
+      * direction_flag * ulambda
+  | Uassign of Backend_var.t * ulambda
   | Usend of meth_kind * ulambda * ulambda * ulambda list * Debuginfo.t
   | Uunreachable
 
 and ufunction = {
   label  : function_label;
   arity  : int;
-  params : Ident.t list;
+  params : (Backend_var.With_provenance.t * value_kind) list;
+  return : value_kind;
   body   : ulambda;
   dbg    : Debuginfo.t;
-  env    : Ident.t option;
+  env    : Backend_var.t option;
 }
 
 and ulambda_switch =
@@ -80,7 +108,7 @@ type function_description =
   { fun_label: function_label;          (* Label of direct entry point *)
     fun_arity: int;                     (* Number of arguments *)
     mutable fun_closed: bool;           (* True if environment not used *)
-    mutable fun_inline: (Ident.t list * ulambda) option;
+    mutable fun_inline: (Backend_var.With_provenance.t list * ulambda) option;
     mutable fun_float_const_prop: bool  (* Can propagate FP consts *)
   }
 
@@ -100,6 +128,11 @@ val compare_structured_constants:
 val compare_constants:
         uconstant -> uconstant -> int
 
+type usymbol_provenance = {
+  original_idents : Ident.t list;
+  module_path : Path.t;
+}
+
 type uconstant_block_field =
   | Uconst_field_ref of string
   | Uconst_field_int of int
@@ -109,10 +142,12 @@ type preallocated_block = {
   exported : bool;
   tag : int;
   fields : uconstant_block_field option list;
+  provenance : usymbol_provenance option;
 }
 
 type preallocated_constant = {
   symbol : string;
   exported : bool;
   definition : ustructured_constant;
+  provenance : usymbol_provenance option;
 }
diff --git a/asmcomp/closure.ml b/asmcomp/closure.ml
index a8a22253..35239faf 100644
--- a/asmcomp/closure.ml
+++ b/asmcomp/closure.ml
@@ -22,15 +22,22 @@ open Lambda
 open Switch
 open Clambda
 
+module Int = Numbers.Int
 module Storer =
   Switch.Store
     (struct
       type t = lambda
       type key = lambda
       let make_key =  Lambda.make_key
-      let compare_key = Pervasives.compare
+      let compare_key = Stdlib.compare
     end)
 
+module V = Backend_var
+module VP = Backend_var.With_provenance
+
+let no_phantom_lets () =
+  Misc.fatal_error "Closure does not support phantom let generation"
+
 (* Auxiliaries for compiling functions *)
 
 let rec split_list n l =
@@ -41,10 +48,11 @@ let rec split_list n l =
   end
 
 let rec build_closure_env env_param pos = function
-    [] -> Tbl.empty
+    [] -> V.Map.empty
   | id :: rem ->
-      Tbl.add id (Uprim(Pfield pos, [Uvar env_param], Debuginfo.none))
-              (build_closure_env env_param (pos+1) rem)
+      V.Map.add id
+        (Uprim(Pfield pos, [Uvar env_param], Debuginfo.none))
+          (build_closure_env env_param (pos+1) rem)
 
 (* Auxiliary for accessing globals.  We change the name of the global
    to the name of the corresponding asm symbol.  This is done here
@@ -52,7 +60,7 @@ let rec build_closure_env env_param pos = function
    contain the right names if the -for-pack option is active. *)
 
 let getglobal dbg id =
-  Uprim(Pgetglobal (Ident.create_persistent (Compilenv.symbol_for_global id)),
+  Uprim(Pgetglobal (V.create_persistent (Compilenv.symbol_for_global id)),
         [], dbg)
 
 (* Check if a variable occurs in a [clambda] term. *)
@@ -66,6 +74,7 @@ let occurs_var var u =
     | Uclosure(_fundecls, clos) -> List.exists occurs clos
     | Uoffset(u, _ofs) -> occurs u
     | Ulet(_str, _kind, _id, def, body) -> occurs def || occurs body
+    | Uphantom_let _ -> no_phantom_lets ()
     | Uletrec(decls, body) ->
         List.exists (fun (_id, u) -> occurs u) decls || occurs body
     | Uprim(_p, args, _) -> List.exists occurs args
@@ -154,6 +163,7 @@ let lambda_smaller lam threshold =
         incr size; lambda_size lam
     | Ulet(_str, _kind, _id, lam, body) ->
         lambda_size lam; lambda_size body
+    | Uphantom_let _ -> no_phantom_lets ()
     | Uletrec _ ->
         raise Exit (* usually too large *)
     | Uprim(prim, args, _) ->
@@ -546,7 +556,7 @@ let subst_debuginfo loc dbg =
 let rec substitute loc fpc sb rn ulam =
   match ulam with
     Uvar v ->
-      begin try Tbl.find v sb with Not_found -> ulam end
+      begin try V.Map.find v sb with Not_found -> ulam end
   | Uconst _ -> ulam
   | Udirect_apply(lbl, args, dbg) ->
       let dbg = subst_debuginfo loc dbg in
@@ -567,16 +577,21 @@ let rec substitute loc fpc sb rn ulam =
       Uclosure(defs, List.map (substitute loc fpc sb rn) env)
   | Uoffset(u, ofs) -> Uoffset(substitute loc fpc sb rn u, ofs)
   | Ulet(str, kind, id, u1, u2) ->
-      let id' = Ident.rename id in
+      let id' = VP.rename id in
       Ulet(str, kind, id', substitute loc fpc sb rn u1,
-           substitute loc fpc (Tbl.add id (Uvar id') sb) rn u2)
+           substitute loc fpc
+             (V.Map.add (VP.var id) (Uvar (VP.var id')) sb) rn u2)
+  | Uphantom_let _ -> no_phantom_lets ()
   | Uletrec(bindings, body) ->
       let bindings1 =
-        List.map (fun (id, rhs) -> (id, Ident.rename id, rhs)) bindings in
+        List.map (fun (id, rhs) ->
+          (VP.var id, VP.rename id, rhs)) bindings
+      in
       let sb' =
-        List.fold_right
-          (fun (id, id', _) s -> Tbl.add id (Uvar id') s)
-          bindings1 sb in
+        List.fold_right (fun (id, id', _) s ->
+            V.Map.add id (Uvar (VP.var id')) s)
+          bindings1 sb
+      in
       Uletrec(
         List.map
            (fun (_id, id', rhs) -> (id', substitute loc fpc sb' rn rhs))
@@ -626,7 +641,7 @@ let rec substitute loc fpc sb rn ulam =
         match rn with
         | Some rn ->
           begin try
-            Tbl.find nfail rn
+            Int.Map.find nfail rn
           with Not_found ->
             fatal_errorf "Closure.split_list: invalid nfail (%d)" nfail
           end
@@ -637,40 +652,49 @@ let rec substitute loc fpc sb rn ulam =
         match rn with
         | Some rn ->
           let new_nfail = next_raise_count () in
-          new_nfail, Some (Tbl.add nfail new_nfail rn)
+          new_nfail, Some (Int.Map.add nfail new_nfail rn)
         | None -> nfail, rn in
-      let ids' = List.map Ident.rename ids in
+      let ids' = List.map (fun (id, k) -> VP.rename id, k) ids in
       let sb' =
         List.fold_right2
-          (fun id id' s -> Tbl.add id (Uvar id') s)
+          (fun (id, _) (id', _) s ->
+             V.Map.add (VP.var id) (Uvar (VP.var id')) s
+          )
           ids ids' sb
       in
-      Ucatch(nfail, ids', substitute loc fpc sb rn u1, substitute loc fpc sb' rn u2)
+      Ucatch(nfail, ids', substitute loc fpc sb rn u1,
+                          substitute loc fpc sb' rn u2)
   | Utrywith(u1, id, u2) ->
-      let id' = Ident.rename id in
+      let id' = VP.rename id in
       Utrywith(substitute loc fpc sb rn u1, id',
-               substitute loc fpc (Tbl.add id (Uvar id') sb) rn u2)
+               substitute loc fpc
+                 (V.Map.add (VP.var id) (Uvar (VP.var id')) sb) rn u2)
   | Uifthenelse(u1, u2, u3) ->
       begin match substitute loc fpc sb rn u1 with
         Uconst (Uconst_ptr n) ->
-          if n <> 0 then substitute loc fpc sb rn u2 else substitute loc fpc sb rn u3
+          if n <> 0 then
+            substitute loc fpc sb rn u2
+          else
+            substitute loc fpc sb rn u3
       | Uprim(Pmakeblock _, _, _) ->
           substitute loc fpc sb rn u2
       | su1 ->
-          Uifthenelse(su1, substitute loc fpc sb rn u2, substitute loc fpc sb rn u3)
+          Uifthenelse(su1, substitute loc fpc sb rn u2,
+                           substitute loc fpc sb rn u3)
       end
   | Usequence(u1, u2) ->
       Usequence(substitute loc fpc sb rn u1, substitute loc fpc sb rn u2)
   | Uwhile(u1, u2) ->
       Uwhile(substitute loc fpc sb rn u1, substitute loc fpc sb rn u2)
   | Ufor(id, u1, u2, dir, u3) ->
-      let id' = Ident.rename id in
+      let id' = VP.rename id in
       Ufor(id', substitute loc fpc sb rn u1, substitute loc fpc sb rn u2, dir,
-           substitute loc fpc (Tbl.add id (Uvar id') sb) rn u3)
+           substitute loc fpc
+           (V.Map.add (VP.var id) (Uvar (VP.var id')) sb) rn u3)
   | Uassign(id, u) ->
       let id' =
         try
-          match Tbl.find id sb with Uvar i -> i | _ -> assert false
+          match V.Map.find id sb with Uvar i -> i | _ -> assert false
         with Not_found ->
           id in
       Uassign(id', substitute loc fpc sb rn u)
@@ -693,22 +717,25 @@ let no_effects = function
 
 let rec bind_params_rec loc fpc subst params args body =
   match (params, args) with
-    ([], []) -> substitute loc fpc subst (Some Tbl.empty) body
+    ([], []) -> substitute loc fpc subst (Some Int.Map.empty) body
   | (p1 :: pl, a1 :: al) ->
       if is_simple_argument a1 then
-        bind_params_rec loc fpc (Tbl.add p1 a1 subst) pl al body
+        bind_params_rec loc fpc (V.Map.add (VP.var p1) a1 subst)
+          pl al body
       else begin
-        let p1' = Ident.rename p1 in
+        let p1' = VP.rename p1 in
         let u1, u2 =
-          match Ident.name p1, a1 with
+          match VP.name p1, a1 with
           | "*opt*", Uprim(Pmakeblock(0, Immutable, kind), [a], dbg) ->
-              a, Uprim(Pmakeblock(0, Immutable, kind), [Uvar p1'], dbg)
+              a, Uprim(Pmakeblock(0, Immutable, kind), [Uvar (VP.var p1')], dbg)
           | _ ->
-              a1, Uvar p1'
+              a1, Uvar (VP.var p1')
         in
         let body' =
-          bind_params_rec loc fpc (Tbl.add p1 u2 subst) pl al body in
-        if occurs_var p1 body then Ulet(Immutable, Pgenval, p1', u1, body')
+          bind_params_rec loc fpc (V.Map.add (VP.var p1) u2 subst)
+            pl al body in
+        if occurs_var (VP.var p1) body then
+          Ulet(Immutable, Pgenval, p1', u1, body')
         else if no_effects a1 then body'
         else Usequence(a1, body')
       end
@@ -717,7 +744,7 @@ let rec bind_params_rec loc fpc subst params args body =
 let bind_params loc fpc params args body =
   (* Reverse parameters and arguments to preserve right-to-left
      evaluation order (PR#2910). *)
-  bind_params_rec loc fpc Tbl.empty (List.rev params) (List.rev args) body
+  bind_params_rec loc fpc V.Map.empty (List.rev params) (List.rev args) body
 
 (* Check if a lambda term is ``pure'',
    that is without side-effects *and* not containing function definitions *)
@@ -778,7 +805,7 @@ let check_constant_result lam ulam approx =
       | Uprim(Pfield _, [Uprim(Pgetglobal _, _, _)], _) -> (ulam, approx)
       | _ ->
           let glb =
-            Uprim(Pgetglobal (Ident.create_persistent id), [], Debuginfo.none)
+            Uprim(Pgetglobal (V.create_persistent id), [], Debuginfo.none)
           in
           Uprim(Pfield i, [glb], Debuginfo.none), approx
       end
@@ -809,11 +836,11 @@ let excessive_function_nesting_depth = 5
 exception NotClosed
 
 let close_approx_var fenv cenv id =
-  let approx = try Tbl.find id fenv with Not_found -> Value_unknown in
+  let approx = try V.Map.find id fenv with Not_found -> Value_unknown in
   match approx with
     Value_const c -> make_const c
   | approx ->
-      let subst = try Tbl.find id cenv with Not_found -> Uvar id in
+      let subst = try V.Map.find id cenv with Not_found -> Uvar id in
       (subst, approx)
 
 let close_var fenv cenv id =
@@ -855,7 +882,7 @@ let rec close fenv cenv = function
       in
       make_const (transl cst)
   | Lfunction _ as funct ->
-      close_one_function fenv cenv (Ident.create "fun") funct
+      close_one_function fenv cenv (Ident.create_local "fun") funct
 
     (* We convert [f a] to [let a' = a in let f' = f in fun b c -> f' a' b c]
        when fun_arity > nargs *)
@@ -878,27 +905,28 @@ let rec close fenv cenv = function
       | ((ufunct, (Value_closure(fundesc, _) as fapprox)), uargs)
           when nargs < fundesc.fun_arity ->
         let first_args = List.map (fun arg ->
-          (Ident.create "arg", arg) ) uargs in
+          (V.create_local "arg", arg) ) uargs in
         let final_args =
           Array.to_list (Array.init (fundesc.fun_arity - nargs)
-                                    (fun _ -> Ident.create "arg")) in
+                                    (fun _ -> V.create_local "arg")) in
         let rec iter args body =
           match args with
               [] -> body
             | (arg1, arg2) :: args ->
               iter args
-                (Ulet (Immutable, Pgenval, arg1, arg2, body))
+                (Ulet (Immutable, Pgenval, VP.create arg1, arg2, body))
         in
         let internal_args =
           (List.map (fun (arg1, _arg2) -> Lvar arg1) first_args)
           @ (List.map (fun arg -> Lvar arg ) final_args)
         in
-        let funct_var = Ident.create "funct" in
-        let fenv = Tbl.add funct_var fapprox fenv in
+        let funct_var = V.create_local "funct" in
+        let fenv = V.Map.add funct_var fapprox fenv in
         let (new_fun, approx) = close fenv cenv
           (Lfunction{
                kind = Curried;
-               params = final_args;
+               return = Pgenval;
+               params = List.map (fun v -> v, Pgenval) final_args;
                body = Lapply{ap_should_be_tailcall=false;
                              ap_loc=loc;
                              ap_func=(Lvar funct_var);
@@ -910,14 +938,14 @@ let rec close fenv cenv = function
         in
         let new_fun =
           iter first_args
-            (Ulet (Immutable, Pgenval, funct_var, ufunct, new_fun))
+            (Ulet (Immutable, Pgenval, VP.create funct_var, ufunct, new_fun))
         in
         warning_if_forced_inline ~loc ~attribute "Partial application";
         (new_fun, approx)
 
       | ((ufunct, Value_closure(fundesc, _approx_res)), uargs)
         when fundesc.fun_arity > 0 && nargs > fundesc.fun_arity ->
-          let args = List.map (fun arg -> Ident.create "arg", arg) uargs in
+          let args = List.map (fun arg -> V.create_local "arg", arg) uargs in
           let (first_args, rem_args) = split_list fundesc.fun_arity args in
           let first_args = List.map (fun (id, _) -> Uvar id) first_args in
           let rem_args = List.map (fun (id, _) -> Uvar id) rem_args in
@@ -930,7 +958,7 @@ let rec close fenv cenv = function
           in
           let result =
             List.fold_left (fun body (id, defining_expr) ->
-                Ulet (Immutable, Pgenval, id, defining_expr, body))
+                Ulet (Immutable, Pgenval, VP.create id, defining_expr, body))
               body
               args
           in
@@ -951,13 +979,13 @@ let rec close fenv cenv = function
       begin match (str, alam) with
         (Variable, _) ->
           let (ubody, abody) = close fenv cenv body in
-          (Ulet(Mutable, kind, id, ulam, ubody), abody)
+          (Ulet(Mutable, kind, VP.create id, ulam, ubody), abody)
       | (_, Value_const _)
         when str = Alias || is_pure lam ->
-          close (Tbl.add id alam fenv) cenv body
+          close (V.Map.add id alam fenv) cenv body
       | (_, _) ->
-          let (ubody, abody) = close (Tbl.add id alam fenv) cenv body in
-          (Ulet(Immutable, kind, id, ulam, ubody), abody)
+          let (ubody, abody) = close (V.Map.add id alam fenv) cenv body in
+          (Ulet(Immutable, kind, VP.create id, ulam, ubody), abody)
       end
   | Lletrec(defs, body) ->
       if List.for_all
@@ -966,18 +994,18 @@ let rec close fenv cenv = function
       then begin
         (* Simple case: only function definitions *)
         let (clos, infos) = close_functions fenv cenv defs in
-        let clos_ident = Ident.create "clos" in
+        let clos_ident = V.create_local "clos" in
         let fenv_body =
           List.fold_right
-            (fun (id, _pos, approx) fenv -> Tbl.add id approx fenv)
+            (fun (id, _pos, approx) fenv -> V.Map.add id approx fenv)
             infos fenv in
         let (ubody, approx) = close fenv_body cenv body in
         let sb =
           List.fold_right
             (fun (id, pos, _approx) sb ->
-              Tbl.add id (Uoffset(Uvar clos_ident, pos)) sb)
-            infos Tbl.empty in
-        (Ulet(Immutable, Pgenval, clos_ident, clos,
+              V.Map.add id (Uoffset(Uvar clos_ident, pos)) sb)
+            infos V.Map.empty in
+        (Ulet(Immutable, Pgenval, VP.create clos_ident, clos,
               substitute Location.none !Clflags.float_const_prop sb None ubody),
          approx)
       end else begin
@@ -987,7 +1015,7 @@ let rec close fenv cenv = function
         | (id, lam) :: rem ->
             let (udefs, fenv_body) = clos_defs rem in
             let (ulam, approx) = close_named fenv cenv id lam in
-            ((id, ulam) :: udefs, Tbl.add id approx fenv_body) in
+            ((VP.create id, ulam) :: udefs, V.Map.add id approx fenv_body) in
         let (udefs, fenv_body) = clos_defs defs in
         let (ubody, approx) = close fenv_body cenv body in
         (Uletrec(udefs, ubody), approx)
@@ -1077,11 +1105,12 @@ let rec close fenv cenv = function
   | Lstaticcatch(body, (i, vars), handler) ->
       let (ubody, _) = close fenv cenv body in
       let (uhandler, _) = close fenv cenv handler in
+      let vars = List.map (fun (var, k) -> VP.create var, k) vars in
       (Ucatch(i, vars, ubody, uhandler), Value_unknown)
   | Ltrywith(body, id, handler) ->
       let (ubody, _) = close fenv cenv body in
       let (uhandler, _) = close fenv cenv handler in
-      (Utrywith(ubody, id, uhandler), Value_unknown)
+      (Utrywith(ubody, VP.create id, uhandler), Value_unknown)
   | Lifthenelse(arg, ifso, ifnot) ->
       begin match close fenv cenv arg with
         (uarg, Value_const (Uconst_ptr n)) ->
@@ -1104,7 +1133,7 @@ let rec close fenv cenv = function
       let (ulo, _) = close fenv cenv lo in
       let (uhi, _) = close fenv cenv hi in
       let (ubody, _) = close fenv cenv body in
-      (Ufor(id, ulo, uhi, dir, ubody), Value_unknown)
+      (Ufor(VP.create id, ulo, uhi, dir, ubody), Value_unknown)
   | Lassign(id, lam) ->
       let (ulam, _) = close fenv cenv lam in
       (Uassign(id, ulam), Value_unknown)
@@ -1139,9 +1168,9 @@ and close_functions fenv cenv fun_defs =
     List.flatten
       (List.map
          (function
-           | (id, Lfunction{kind; params; body; attr; loc}) ->
+           | (id, Lfunction{kind; params; return; body; attr; loc}) ->
                Simplif.split_default_wrapper ~id ~kind ~params
-                 ~body ~attr ~loc
+                 ~body ~attr ~loc ~return
            | _ -> assert false
          )
          fun_defs)
@@ -1156,15 +1185,15 @@ and close_functions fenv cenv fun_defs =
     !function_nesting_depth < excessive_function_nesting_depth in
   (* Determine the free variables of the functions *)
   let fv =
-    Ident.Set.elements (free_variables (Lletrec(fun_defs, lambda_unit))) in
+    V.Set.elements (free_variables (Lletrec(fun_defs, lambda_unit))) in
   (* Build the function descriptors for the functions.
      Initially all functions are assumed not to need their environment
      parameter. *)
   let uncurried_defs =
     List.map
       (function
-          (id, Lfunction{kind; params; body; loc}) ->
-            let label = Compilenv.make_symbol (Some (Ident.unique_name id)) in
+          (id, Lfunction{kind; params; return; body; loc}) ->
+            let label = Compilenv.make_symbol (Some (V.unique_name id)) in
             let arity = List.length params in
             let fundesc =
               {fun_label = label;
@@ -1173,20 +1202,20 @@ and close_functions fenv cenv fun_defs =
                fun_inline = None;
                fun_float_const_prop = !Clflags.float_const_prop } in
             let dbg = Debuginfo.from_location loc in
-            (id, params, body, fundesc, dbg)
+            (id, params, return, body, fundesc, dbg)
         | (_, _) -> fatal_error "Closure.close_functions")
       fun_defs in
   (* Build an approximate fenv for compiling the functions *)
   let fenv_rec =
     List.fold_right
-      (fun (id, _params, _body, fundesc, _dbg) fenv ->
-        Tbl.add id (Value_closure(fundesc, Value_unknown)) fenv)
+      (fun (id, _params, _return, _body, fundesc, _dbg) fenv ->
+        V.Map.add id (Value_closure(fundesc, Value_unknown)) fenv)
       uncurried_defs fenv in
   (* Determine the offsets of each function's closure in the shared block *)
   let env_pos = ref (-1) in
   let clos_offsets =
     List.map
-      (fun (_id, _params, _body, fundesc, _dbg) ->
+      (fun (_id, _params, _return, _body, fundesc, _dbg) ->
         let pos = !env_pos + 1 in
         env_pos := !env_pos + 1 + (if fundesc.fun_arity <> 1 then 3 else 2);
         pos)
@@ -1196,23 +1225,28 @@ and close_functions fenv cenv fun_defs =
      does not use its environment parameter is invalidated. *)
   let useless_env = ref initially_closed in
   (* Translate each function definition *)
-  let clos_fundef (id, params, body, fundesc, dbg) env_pos =
-    let env_param = Ident.create "env" in
+  let clos_fundef (id, params, return, body, fundesc, dbg) env_pos =
+    let env_param = V.create_local "env" in
     let cenv_fv =
       build_closure_env env_param (fv_pos - env_pos) fv in
     let cenv_body =
       List.fold_right2
-        (fun (id, _params, _body, _fundesc, _dbg) pos env ->
-          Tbl.add id (Uoffset(Uvar env_param, pos - env_pos)) env)
+        (fun (id, _params, _return, _body, _fundesc, _dbg) pos env ->
+          V.Map.add id (Uoffset(Uvar env_param, pos - env_pos)) env)
         uncurried_defs clos_offsets cenv_fv in
     let (ubody, approx) = close fenv_rec cenv_body body in
     if !useless_env && occurs_var env_param ubody then raise NotClosed;
-    let fun_params = if !useless_env then params else params @ [env_param] in
+    let fun_params =
+      if !useless_env
+      then params
+      else params @ [env_param, Pgenval]
+    in
     let f =
       {
         label  = fundesc.fun_label;
         arity  = fundesc.fun_arity;
-        params = fun_params;
+        params = List.map (fun (var, kind) -> VP.create var, kind) fun_params;
+        return;
         body   = ubody;
         dbg;
         env = Some env_param;
@@ -1222,7 +1256,7 @@ and close_functions fenv cenv fun_defs =
        their wrapper functions) to be inlined *)
     let n =
       List.fold_left
-        (fun n id -> n + if Ident.name id = "*opt*" then 8 else 1)
+        (fun n (id, _) -> n + if V.name id = "*opt*" then 8 else 1)
         0
         fun_params
     in
@@ -1238,6 +1272,7 @@ and close_functions fenv cenv fun_defs =
       | Never_inline -> min_int
       | Unroll _ -> assert false
     in
+    let fun_params = List.map (fun (var, _) -> VP.create var) fun_params in
     if lambda_smaller ubody threshold
     then fundesc.fun_inline <- Some(fun_params, ubody);
 
@@ -1253,7 +1288,7 @@ and close_functions fenv cenv fun_defs =
          recompile *)
         Compilenv.backtrack snap; (* PR#6337 *)
         List.iter
-          (fun (_id, _params, _body, fundesc, _dbg) ->
+          (fun (_id, _params, _return, _body, fundesc, _dbg) ->
              fundesc.fun_closed <- false;
              fundesc.fun_inline <- None;
           )
@@ -1365,6 +1400,7 @@ let collect_exported_structured_constants a =
         List.iter ulam ul
     | Uoffset(u, _) -> ulam u
     | Ulet (_str, _kind, _, u1, u2) -> ulam u1; ulam u2
+    | Uphantom_let _ -> no_phantom_lets ()
     | Uletrec (l, u) -> List.iter (fun (_, u) -> ulam u) l; ulam u
     | Uprim (_, ul, _) -> List.iter ulam ul
     | Uswitch (u, sl, _dbg) ->
@@ -1399,7 +1435,7 @@ let intro size lam =
   let id = Compilenv.make_symbol None in
   global_approx := Array.init size (fun i -> Value_global_field (id, i));
   Compilenv.set_global_approx(Value_tuple !global_approx);
-  let (ulam, _approx) = close Tbl.empty Tbl.empty lam in
+  let (ulam, _approx) = close V.Map.empty V.Map.empty lam in
   let opaque =
     !Clflags.opaque
     || Env.is_imported_opaque (Compilenv.current_unit_name ())
diff --git a/asmcomp/cmm.ml b/asmcomp/cmm.ml
index 939298dd..3c0b2d78 100644
--- a/asmcomp/cmm.ml
+++ b/asmcomp/cmm.ml
@@ -116,6 +116,15 @@ type raise_kind =
 
 type rec_flag = Nonrecursive | Recursive
 
+type phantom_defining_expr =
+  | Cphantom_const_int of Targetint.t
+  | Cphantom_const_symbol of string
+  | Cphantom_var of Backend_var.t
+  | Cphantom_offset_var of { var : Backend_var.t; offset_in_words : int; }
+  | Cphantom_read_field of { var : Backend_var.t; field : int; }
+  | Cphantom_read_symbol_field of { sym : string; field : int; }
+  | Cphantom_block of { tag : int; fields : Backend_var.t list; }
+
 type memory_chunk =
     Byte_unsigned
   | Byte_signed
@@ -157,18 +166,24 @@ type expression =
   | Cconst_pointer of int
   | Cconst_natpointer of nativeint
   | Cblockheader of nativeint * Debuginfo.t
-  | Cvar of Ident.t
-  | Clet of Ident.t * expression * expression
-  | Cassign of Ident.t * expression
+  | Cvar of Backend_var.t
+  | Clet of Backend_var.With_provenance.t * expression * expression
+  | Cphantom_let of Backend_var.With_provenance.t
+      * phantom_defining_expr option * expression
+  | Cassign of Backend_var.t * expression
   | Ctuple of expression list
   | Cop of operation * expression list * Debuginfo.t
   | Csequence of expression * expression
   | Cifthenelse of expression * expression * expression
   | Cswitch of expression * int array * expression array * Debuginfo.t
   | Cloop of expression
-  | Ccatch of rec_flag * (int * Ident.t list * expression) list * expression
+  | Ccatch of
+      rec_flag
+        * (int * (Backend_var.With_provenance.t * machtype) list
+          * expression) list
+        * expression
   | Cexit of int * expression list
-  | Ctrywith of expression * Ident.t * expression
+  | Ctrywith of expression * Backend_var.With_provenance.t * expression
 
 type codegen_option =
   | Reduce_code_size
@@ -176,7 +191,7 @@ type codegen_option =
 
 type fundecl =
   { fun_name: string;
-    fun_args: (Ident.t * machtype) list;
+    fun_args: (Backend_var.With_provenance.t * machtype) list;
     fun_body: expression;
     fun_codegen_options : codegen_option list;
     fun_dbg : Debuginfo.t;
diff --git a/asmcomp/cmm.mli b/asmcomp/cmm.mli
index 01fe0c93..219083a1 100644
--- a/asmcomp/cmm.mli
+++ b/asmcomp/cmm.mli
@@ -93,6 +93,33 @@ type raise_kind =
 
 type rec_flag = Nonrecursive | Recursive
 
+type phantom_defining_expr =
+  (* CR-soon mshinwell: Convert this to [Targetint.OCaml.t] (or whatever the
+     representation of "target-width OCaml integers of type [int]"
+     becomes when merged). *)
+  | Cphantom_const_int of Targetint.t
+  (** The phantom-let-bound variable is a constant integer.
+      The argument must be the tagged representation of an integer within
+      the range of type [int] on the target.  (Analogously to [Cconst_int].) *)
+  | Cphantom_const_symbol of string
+  (** The phantom-let-bound variable is an alias for a symbol. *)
+  | Cphantom_var of Backend_var.t
+  (** The phantom-let-bound variable is an alias for another variable.  The
+      aliased variable must not be a bound by a phantom let. *)
+  | Cphantom_offset_var of { var : Backend_var.t; offset_in_words : int; }
+  (** The phantom-let-bound-variable's value is defined by adding the given
+      number of words to the pointer contained in the given identifier. *)
+  | Cphantom_read_field of { var : Backend_var.t; field : int; }
+  (** The phantom-let-bound-variable's value is found by adding the given
+      number of words to the pointer contained in the given identifier, then
+      dereferencing. *)
+  | Cphantom_read_symbol_field of { sym : string; field : int; }
+  (** As for [Uphantom_read_var_field], but with the pointer specified by
+      a symbol. *)
+  | Cphantom_block of { tag : int; fields : Backend_var.t list; }
+  (** The phantom-let-bound variable points at a block with the given
+      structure. *)
+
 type memory_chunk =
     Byte_unsigned
   | Byte_signed
@@ -137,18 +164,24 @@ and expression =
   | Cconst_pointer of int
   | Cconst_natpointer of nativeint
   | Cblockheader of nativeint * Debuginfo.t
-  | Cvar of Ident.t
-  | Clet of Ident.t * expression * expression
-  | Cassign of Ident.t * expression
+  | Cvar of Backend_var.t
+  | Clet of Backend_var.With_provenance.t * expression * expression
+  | Cphantom_let of Backend_var.With_provenance.t
+      * phantom_defining_expr option * expression
+  | Cassign of Backend_var.t * expression
   | Ctuple of expression list
   | Cop of operation * expression list * Debuginfo.t
   | Csequence of expression * expression
   | Cifthenelse of expression * expression * expression
   | Cswitch of expression * int array * expression array * Debuginfo.t
   | Cloop of expression
-  | Ccatch of rec_flag * (int * Ident.t list * expression) list * expression
+  | Ccatch of
+      rec_flag
+        * (int * (Backend_var.With_provenance.t * machtype) list
+          * expression) list
+        * expression
   | Cexit of int * expression list
-  | Ctrywith of expression * Ident.t * expression
+  | Ctrywith of expression * Backend_var.With_provenance.t * expression
 
 type codegen_option =
   | Reduce_code_size
@@ -156,7 +189,7 @@ type codegen_option =
 
 type fundecl =
   { fun_name: string;
-    fun_args: (Ident.t * machtype) list;
+    fun_args: (Backend_var.With_provenance.t * machtype) list;
     fun_body: expression;
     fun_codegen_options : codegen_option list;
     fun_dbg : Debuginfo.t;
@@ -180,6 +213,9 @@ type phrase =
     Cfunction of fundecl
   | Cdata of data_item list
 
-val ccatch : int * Ident.t list * expression * expression -> expression
+val ccatch :
+     int * (Backend_var.With_provenance.t * machtype) list
+       * expression * expression
+  -> expression
 
 val reset : unit -> unit
diff --git a/asmcomp/cmmgen.ml b/asmcomp/cmmgen.ml
index 4509f58b..d0490998 100644
--- a/asmcomp/cmmgen.ml
+++ b/asmcomp/cmmgen.ml
@@ -25,6 +25,10 @@ open Clambda
 open Cmm
 open Cmx_format
 
+module String = Misc.Stdlib.String
+module V = Backend_var
+module VP = Backend_var.With_provenance
+
 (* Environments used for translation to Cmm. *)
 
 type boxed_number =
@@ -32,28 +36,28 @@ type boxed_number =
   | Boxed_integer of boxed_integer * Debuginfo.t
 
 type env = {
-  unboxed_ids : (Ident.t * boxed_number) Ident.tbl;
-  environment_param : Ident.t option;
+  unboxed_ids : (V.t * boxed_number) V.tbl;
+  environment_param : V.t option;
 }
 
 let empty_env =
   {
-    unboxed_ids =Ident.empty;
+    unboxed_ids =V.empty;
     environment_param = None;
   }
 
 let create_env ~environment_param =
-  { unboxed_ids = Ident.empty;
+  { unboxed_ids = V.empty;
     environment_param;
   }
 
 let is_unboxed_id id env =
-  try Some (Ident.find_same id env.unboxed_ids)
+  try Some (V.find_same id env.unboxed_ids)
   with Not_found -> None
 
 let add_unboxed_id id unboxed_id bn env =
   { env with
-    unboxed_ids = Ident.add id (unboxed_id, bn) env.unboxed_ids;
+    unboxed_ids = V.add id (unboxed_id, bn) env.unboxed_ids;
   }
 
 (* Local binding of complex expressions *)
@@ -63,7 +67,7 @@ let bind name arg fn =
     Cvar _ | Cconst_int _ | Cconst_natint _ | Cconst_symbol _
   | Cconst_pointer _ | Cconst_natpointer _
   | Cblockheader _ -> fn arg
-  | _ -> let id = Ident.create name in Clet(id, arg, fn (Cvar id))
+  | _ -> let id = V.create_local name in Clet(VP.create id, arg, fn (Cvar id))
 
 let bind_load name arg fn =
   match arg with
@@ -75,10 +79,10 @@ let bind_nonvar name arg fn =
     Cconst_int _ | Cconst_natint _ | Cconst_symbol _
   | Cconst_pointer _ | Cconst_natpointer _
   | Cblockheader _ -> fn arg
-  | _ -> let id = Ident.create name in Clet(id, arg, fn (Cvar id))
+  | _ -> let id = V.create_local name in Clet(VP.create id, arg, fn (Cvar id))
 
 let caml_black = Nativeint.shift_left (Nativeint.of_int 3) 8
-    (* cf. byterun/gc.h *)
+    (* cf. runtime/caml/gc.h *)
 
 (* Block headers. Meaning of the tag field: see stdlib/obj.ml *)
 
@@ -129,6 +133,10 @@ let int_const n =
 let cint_const n =
   Cint(Nativeint.add (Nativeint.shift_left (Nativeint.of_int n) 1) 1n)
 
+let targetint_const n =
+  Targetint.add (Targetint.shift_left (Targetint.of_int n) 1)
+    Targetint.one
+
 let add_no_overflow n x c dbg =
   let d = n + x in
   if d = 0 then c else Cop(Caddi, [c; Cconst_int d], dbg)
@@ -444,7 +452,7 @@ let rec div_int c1 c2 is_safe dbg =
           let t = if p > 0 then Cop(Casr, [t; Cconst_int p], dbg) else t in
           add_int t (lsr_int c1 (Cconst_int (Nativeint.size - 1)) dbg) dbg)
       end
-  | (c1, c2) when !Clflags.fast || is_safe = Lambda.Unsafe ->
+  | (c1, c2) when !Clflags.unsafe || is_safe = Lambda.Unsafe ->
       Cop(Cdivi, [c1; c2], dbg)
   | (c1, c2) ->
       bind "divisor" c2 (fun c2 ->
@@ -480,7 +488,7 @@ let mod_int c1 c2 is_safe dbg =
       else
         bind "dividend" c1 (fun c1 ->
           sub_int c1 (mul_int (div_int c1 c2 is_safe dbg) c2 dbg) dbg)
-  | (c1, c2) when !Clflags.fast || is_safe = Lambda.Unsafe ->
+  | (c1, c2) when !Clflags.unsafe || is_safe = Lambda.Unsafe ->
       (* Flambda already generates that test *)
       Cop(Cmodi, [c1; c2], dbg)
   | (c1, c2) ->
@@ -539,7 +547,8 @@ let map_ccatch f rec_flag handlers body =
 
 let rec unbox_float dbg cmm =
   match cmm with
-  | Cop(Calloc, [_header; c], _) -> c
+  | Cop(Calloc, [Cblockheader (header, _); c], _) when header = float_header ->
+      c
   | Clet(id, exp, body) -> Clet(id, exp, unbox_float dbg body)
   | Cifthenelse(cond, e1, e2) ->
       Cifthenelse(cond, unbox_float dbg e1, unbox_float dbg e2)
@@ -602,7 +611,7 @@ let get_field env ptr n dbg =
       match ptr with
       | Cvar ptr ->
         (* Loads from the current function's closure are immutable. *)
-        if Ident.same environment_param ptr then Immutable
+        if V.same environment_param ptr then Immutable
         else Mutable
       | _ -> Mutable
   in
@@ -612,7 +621,7 @@ let set_field ptr n newval init dbg =
   Cop(Cstore (Word_val, init), [field_address ptr n dbg; newval], dbg)
 
 let non_profinfo_mask =
-  if Config.profinfo 
+  if Config.profinfo
   then (1 lsl (64 - Config.profinfo_width)) - 1
   else 0 (* [non_profinfo_mask] is unused in this case *)
 
@@ -727,8 +736,8 @@ let float_array_set arr ofs newval dbg =
 
 let string_length exp dbg =
   bind "str" exp (fun str ->
-    let tmp_var = Ident.create "tmp" in
-    Clet(tmp_var,
+    let tmp_var = V.create_local "tmp" in
+    Clet(VP.create tmp_var,
          Cop(Csubi,
              [Cop(Clsl,
                    [get_size str dbg;
@@ -759,7 +768,7 @@ let call_cached_method obj tag cache pos args dbg =
   let cache = array_indexing log2_size_addr cache pos dbg in
   Compilenv.need_send_fun arity;
   Cop(Capply typ_val,
-      Cconst_symbol("caml_send" ^ string_of_int arity) ::
+      Cconst_symbol("caml_send" ^ Int.to_string arity) ::
         obj :: tag :: cache :: args,
       dbg)
 
@@ -769,12 +778,12 @@ let make_alloc_generic set_fn dbg tag wordsize args =
   if wordsize <= Config.max_young_wosize then
     Cop(Calloc, Cblockheader(block_header tag wordsize, dbg) :: args, dbg)
   else begin
-    let id = Ident.create "alloc" in
+    let id = V.create_local "alloc" in
     let rec fill_fields idx = function
       [] -> Cvar id
     | e1::el -> Csequence(set_fn (Cvar id) (Cconst_int idx) e1 dbg,
                           fill_fields (idx + 2) el) in
-    Clet(id,
+    Clet(VP.create id,
          Cop(Cextcall("caml_alloc", typ_val, true, None),
                  [Cconst_int wordsize; Cconst_int tag], dbg),
          fill_fields 1 args)
@@ -826,15 +835,15 @@ type rhs_kind =
 ;;
 let rec expr_size env = function
   | Uvar id ->
-      begin try Ident.find_same id env with Not_found -> RHS_nonrec end
+      begin try V.find_same id env with Not_found -> RHS_nonrec end
   | Uclosure(fundecls, clos_vars) ->
       RHS_block (fundecls_size fundecls + List.length clos_vars)
   | Ulet(_str, _kind, id, exp, body) ->
-      expr_size (Ident.add id (expr_size env exp) env) body
+      expr_size (V.add (VP.var id) (expr_size env exp) env) body
   | Uletrec(bindings, body) ->
       let env =
         List.fold_right
-          (fun (id, exp) env -> Ident.add id (expr_size env exp) env)
+          (fun (id, exp) env -> V.add (VP.var id) (expr_size env exp) env)
           bindings env
       in
       expr_size env body
@@ -852,7 +861,7 @@ let rec expr_size env = function
       RHS_block sz
   | Uprim (Pduprecord (Record_unboxed _, _), _, _) ->
       assert false
-  | Uprim (Pduprecord (Record_extension, sz), _, _) ->
+  | Uprim (Pduprecord (Record_extension _, sz), _, _) ->
       RHS_block (sz + 1)
   | Uprim (Pduprecord (Record_float, sz), _, _) ->
       RHS_floatblock sz
@@ -867,12 +876,12 @@ let rec expr_size env = function
 (* Record application and currying functions *)
 
 let apply_function n =
-  Compilenv.need_apply_fun n; "caml_apply" ^ string_of_int n
+  Compilenv.need_apply_fun n; "caml_apply" ^ Int.to_string n
 let curry_function n =
   Compilenv.need_curry_fun n;
   if n >= 0
-  then "caml_curry" ^ string_of_int n
-  else "caml_tuplify" ^ string_of_int (-n)
+  then "caml_curry" ^ Int.to_string n
+  else "caml_tuplify" ^ Int.to_string (-n)
 
 (* Comparisons *)
 
@@ -921,11 +930,15 @@ let box_int_constant bi n =
   | Pint32 -> Uconst_int32 (Nativeint.to_int32 n)
   | Pint64 -> Uconst_int64 (Int64.of_nativeint n)
 
+let caml_nativeint_ops = "caml_nativeint_ops"
+let caml_int32_ops = "caml_int32_ops"
+let caml_int64_ops = "caml_int64_ops"
+
 let operations_boxed_int bi =
   match bi with
-    Pnativeint -> "caml_nativeint_ops"
-  | Pint32 -> "caml_int32_ops"
-  | Pint64 -> "caml_int64_ops"
+    Pnativeint -> caml_nativeint_ops
+  | Pint32 -> caml_int32_ops
+  | Pint64 -> caml_int64_ops
 
 let alloc_header_boxed_int bi =
   match bi with
@@ -955,18 +968,34 @@ let split_int64_for_32bit_target arg dbg =
     Ctuple [Cop (Cload (Thirtytwo_unsigned, Mutable), [first], dbg);
             Cop (Cload (Thirtytwo_unsigned, Mutable), [second], dbg)])
 
+let alloc_matches_boxed_int bi ~hdr ~ops =
+  match bi, hdr, ops with
+  | Pnativeint, Cblockheader (hdr, _dbg), Cconst_symbol sym ->
+      Nativeint.equal hdr boxedintnat_header
+        && String.equal sym caml_nativeint_ops
+  | Pint32, Cblockheader (hdr, _dbg), Cconst_symbol sym ->
+      Nativeint.equal hdr boxedint32_header
+        && String.equal sym caml_int32_ops
+  | Pint64, Cblockheader (hdr, _dbg), Cconst_symbol sym ->
+      Nativeint.equal hdr boxedint64_header
+        && String.equal sym caml_int64_ops
+  | (Pnativeint | Pint32 | Pint64), _, _ -> false
+
 let rec unbox_int bi arg dbg =
   match arg with
-    Cop(Calloc, [_hdr; _ops; Cop(Clsl, [contents; Cconst_int 32], dbg')], _dbg)
-    when bi = Pint32 && size_int = 8 && big_endian ->
+    Cop(Calloc, [hdr; ops; Cop(Clsl, [contents; Cconst_int 32], dbg')], _dbg)
+    when bi = Pint32 && size_int = 8 && big_endian
+      && alloc_matches_boxed_int bi ~hdr ~ops ->
       (* Force sign-extension of low 32 bits *)
       Cop(Casr, [Cop(Clsl, [contents; Cconst_int 32], dbg'); Cconst_int 32],
         dbg)
-  | Cop(Calloc, [_hdr; _ops; contents], _dbg)
-    when bi = Pint32 && size_int = 8 && not big_endian ->
+  | Cop(Calloc, [hdr; ops; contents], _dbg)
+    when bi = Pint32 && size_int = 8 && not big_endian
+      && alloc_matches_boxed_int bi ~hdr ~ops ->
       (* Force sign-extension of low 32 bits *)
       Cop(Casr, [Cop(Clsl, [contents; Cconst_int 32], dbg); Cconst_int 32], dbg)
-  | Cop(Calloc, [_hdr; _ops; contents], _dbg) ->
+  | Cop(Calloc, [hdr; ops; contents], _dbg)
+    when alloc_matches_boxed_int bi ~hdr ~ops ->
       contents
   | Clet(id, exp, body) -> Clet(id, exp, unbox_int bi body dbg)
   | Cifthenelse(cond, e1, e2) ->
@@ -1106,13 +1135,14 @@ let bigarray_get unsafe elt_kind layout b args dbg =
       Pbigarray_complex32 | Pbigarray_complex64 ->
         let kind = bigarray_word_kind elt_kind in
         let sz = bigarray_elt_size elt_kind / 2 in
-        bind "addr" (bigarray_indexing unsafe elt_kind layout b args dbg) (fun addr ->
-          bind "reval"
-            (Cop(Cload (kind, Mutable), [addr], dbg)) (fun reval ->
-              bind "imval"
-                (Cop(Cload (kind, Mutable),
-                     [Cop(Cadda, [addr; Cconst_int sz], dbg)], dbg)) (fun imval ->
-          box_complex dbg reval imval)))
+        bind "addr"
+          (bigarray_indexing unsafe elt_kind layout b args dbg) (fun addr ->
+            bind "reval"
+              (Cop(Cload (kind, Mutable), [addr], dbg)) (fun reval ->
+                bind "imval"
+                  (Cop(Cload (kind, Mutable),
+                       [Cop(Cadda, [addr; Cconst_int sz], dbg)], dbg))
+                  (fun imval -> box_complex dbg reval imval)))
     | _ ->
         Cop(Cload (bigarray_word_kind elt_kind, Mutable),
             [bigarray_indexing unsafe elt_kind layout b args dbg],
@@ -1346,6 +1376,14 @@ let check_bound unsafe dbg a1 a2 k =
 let default_prim name =
   Primitive.simple ~name ~arity:0(*ignored*) ~alloc:true
 
+let int64_native_prim name arity ~alloc =
+  let u64 = Unboxed_integer Pint64 in
+  let rec make_args = function 0 -> [] | n -> u64 :: make_args (n - 1) in
+  Primitive.make ~name ~native_name:(name ^ "_native")
+    ~alloc
+    ~native_repr_args:(make_args arity)
+    ~native_repr_res:u64
+
 let simplif_primitive_32bits = function
     Pbintofint Pint64 -> Pccall (default_prim "caml_int64_of_int")
   | Pintofbint Pint64 -> Pccall (default_prim "caml_int64_to_int")
@@ -1355,15 +1393,24 @@ let simplif_primitive_32bits = function
       Pccall (default_prim "caml_int64_of_nativeint")
   | Pcvtbint(Pint64, Pnativeint) ->
       Pccall (default_prim "caml_int64_to_nativeint")
-  | Pnegbint Pint64 -> Pccall (default_prim "caml_int64_neg")
-  | Paddbint Pint64 -> Pccall (default_prim "caml_int64_add")
-  | Psubbint Pint64 -> Pccall (default_prim "caml_int64_sub")
-  | Pmulbint Pint64 -> Pccall (default_prim "caml_int64_mul")
-  | Pdivbint {size=Pint64} -> Pccall (default_prim "caml_int64_div")
-  | Pmodbint {size=Pint64} -> Pccall (default_prim "caml_int64_mod")
-  | Pandbint Pint64 -> Pccall (default_prim "caml_int64_and")
-  | Porbint Pint64 ->  Pccall (default_prim "caml_int64_or")
-  | Pxorbint Pint64 -> Pccall (default_prim "caml_int64_xor")
+  | Pnegbint Pint64 -> Pccall (int64_native_prim "caml_int64_neg" 1
+                                 ~alloc:false)
+  | Paddbint Pint64 -> Pccall (int64_native_prim "caml_int64_add" 2
+                                 ~alloc:false)
+  | Psubbint Pint64 -> Pccall (int64_native_prim "caml_int64_sub" 2
+                                 ~alloc:false)
+  | Pmulbint Pint64 -> Pccall (int64_native_prim "caml_int64_mul" 2
+                                 ~alloc:false)
+  | Pdivbint {size=Pint64} -> Pccall (int64_native_prim "caml_int64_div" 2
+                                        ~alloc:true)
+  | Pmodbint {size=Pint64} -> Pccall (int64_native_prim "caml_int64_mod" 2
+                                        ~alloc:true)
+  | Pandbint Pint64 -> Pccall (int64_native_prim "caml_int64_and" 2
+                                 ~alloc:false)
+  | Porbint Pint64 ->  Pccall (int64_native_prim "caml_int64_or" 2
+                                 ~alloc:false)
+  | Pxorbint Pint64 -> Pccall (int64_native_prim "caml_int64_xor" 2
+                                 ~alloc:false)
   | Plslbint Pint64 -> Pccall (default_prim "caml_int64_shift_left")
   | Plsrbint Pint64 -> Pccall (default_prim "caml_int64_shift_right_unsigned")
   | Pasrbint Pint64 -> Pccall (default_prim "caml_int64_shift_right")
@@ -1374,9 +1421,9 @@ let simplif_primitive_32bits = function
   | Pbintcomp(Pint64, Lambda.Cle) -> Pccall (default_prim "caml_lessequal")
   | Pbintcomp(Pint64, Lambda.Cge) -> Pccall (default_prim "caml_greaterequal")
   | Pbigarrayref(_unsafe, n, Pbigarray_int64, _layout) ->
-      Pccall (default_prim ("caml_ba_get_" ^ string_of_int n))
+      Pccall (default_prim ("caml_ba_get_" ^ Int.to_string n))
   | Pbigarrayset(_unsafe, n, Pbigarray_int64, _layout) ->
-      Pccall (default_prim ("caml_ba_set_" ^ string_of_int n))
+      Pccall (default_prim ("caml_ba_set_" ^ Int.to_string n))
   | Pstring_load_64(_) -> Pccall (default_prim "caml_string_get64")
   | Pbytes_load_64(_) -> Pccall (default_prim "caml_bytes_get64")
   | Pbytes_set_64(_) -> Pccall (default_prim "caml_bytes_set64")
@@ -1390,13 +1437,13 @@ let simplif_primitive p =
   | Pduprecord _ ->
       Pccall (default_prim "caml_obj_dup")
   | Pbigarrayref(_unsafe, n, Pbigarray_unknown, _layout) ->
-      Pccall (default_prim ("caml_ba_get_" ^ string_of_int n))
+      Pccall (default_prim ("caml_ba_get_" ^ Int.to_string n))
   | Pbigarrayset(_unsafe, n, Pbigarray_unknown, _layout) ->
-      Pccall (default_prim ("caml_ba_set_" ^ string_of_int n))
+      Pccall (default_prim ("caml_ba_set_" ^ Int.to_string n))
   | Pbigarrayref(_unsafe, n, _kind, Pbigarray_unknown_layout) ->
-      Pccall (default_prim ("caml_ba_get_" ^ string_of_int n))
+      Pccall (default_prim ("caml_ba_get_" ^ Int.to_string n))
   | Pbigarrayset(_unsafe, n, _kind, Pbigarray_unknown_layout) ->
-      Pccall (default_prim ("caml_ba_set_" ^ string_of_int n))
+      Pccall (default_prim ("caml_ba_set_" ^ Int.to_string n))
   | p ->
       if size_int = 8 then p else simplif_primitive_32bits p
 
@@ -1499,7 +1546,7 @@ module StoreExpForSwitch =
       let compare_key (cont, index) (cont', index') =
         match cont, cont' with
         | Some i, Some i' when i = i' -> 0
-        | _, _ -> Pervasives.compare index index'
+        | _, _ -> Stdlib.compare index index'
     end)
 
 (* For string switches, we can use a generic store *)
@@ -1511,7 +1558,7 @@ module StoreExp =
       let make_key = function
         | Cexit (i,[]) -> Some i
         | _ -> None
-      let compare_key = Pervasives.compare
+      let compare_key = Stdlib.compare
     end)
 
 module SwitcherBlocks = Switch.Make(SArgBlocks)
@@ -1784,6 +1831,30 @@ let rec transl env e =
               (call_met obj args))
   | Ulet(str, kind, id, exp, body) ->
       transl_let env str kind id exp body
+  | Uphantom_let (var, defining_expr, body) ->
+      let defining_expr =
+        match defining_expr with
+        | None -> None
+        | Some defining_expr ->
+          let defining_expr =
+            match defining_expr with
+            | Uphantom_const (Uconst_ref (sym, _defining_expr)) ->
+              Cphantom_const_symbol sym
+            | Uphantom_read_symbol_field { sym; field; } ->
+              Cphantom_read_symbol_field { sym; field; }
+            | Uphantom_const (Uconst_int i) | Uphantom_const (Uconst_ptr i) ->
+              Cphantom_const_int (targetint_const i)
+            | Uphantom_var var -> Cphantom_var var
+            | Uphantom_read_field { var; field; } ->
+              Cphantom_read_field { var; field; }
+            | Uphantom_offset_var { var; offset_in_words; } ->
+              Cphantom_offset_var { var; offset_in_words; }
+            | Uphantom_block { tag; fields; } ->
+              Cphantom_block { tag; fields; }
+          in
+          Some defining_expr
+      in
+      Cphantom_let (var, defining_expr, transl env body)
   | Uletrec(bindings, body) ->
       transl_letrec env bindings (transl env body)
 
@@ -1791,7 +1862,7 @@ let rec transl env e =
   | Uprim(prim, args, dbg) ->
       begin match (simplif_primitive prim, args) with
         (Pgetglobal id, []) ->
-          Cconst_symbol (Ident.name id)
+          Cconst_symbol (V.name id)
       | (Pmakeblock _, []) ->
           assert false
       | (Pmakeblock(tag, _mut, _kind), args) ->
@@ -1874,8 +1945,9 @@ let rec transl env e =
           (Array.map (transl env) s.us_actions_consts)
           dbg
       else if Array.length s.us_index_consts = 0 then
-        transl_switch loc env (get_tag (transl env arg) dbg)
-          s.us_index_blocks s.us_actions_blocks
+        bind "switch" (transl env arg) (fun arg ->
+          transl_switch loc env (get_tag arg dbg)
+            s.us_index_blocks s.us_actions_blocks)
       else
         bind "switch" (transl env arg) (fun arg ->
           Cifthenelse(
@@ -1895,7 +1967,11 @@ let rec transl env e =
   | Ucatch(nfail, [], body, handler) ->
       make_catch nfail (transl env body) (transl env handler)
   | Ucatch(nfail, ids, body, handler) ->
-      ccatch(nfail, ids, transl env body, transl env handler)
+      (* CR-someday mshinwell: consider how we can do better than
+         [typ_val] when appropriate. *)
+      let ids_with_types =
+        List.map (fun (i, _) -> (i, Cmm.typ_val)) ids in
+      ccatch(nfail, ids_with_types, transl env body, transl env handler)
   | Utrywith(body, exn, handler) ->
       Ctrywith(transl env body, exn, transl env handler)
   | Uifthenelse(cond, ifso, ifnot) ->
@@ -1919,7 +1995,7 @@ let rec transl env e =
       let tst = match dir with Upto -> Cgt   | Downto -> Clt in
       let inc = match dir with Upto -> Caddi | Downto -> Csubi in
       let raise_num = next_raise_count () in
-      let id_prev = Ident.rename id in
+      let id_prev = VP.rename id in
       return_unit
         (Clet
            (id, transl env low,
@@ -1927,18 +2003,18 @@ let rec transl env e =
               ccatch
                 (raise_num, [],
                  Cifthenelse
-                   (Cop(Ccmpi tst, [Cvar id; high], dbg),
+                   (Cop(Ccmpi tst, [Cvar (VP.var id); high], dbg),
                     Cexit (raise_num, []),
                     Cloop
                       (Csequence
                          (remove_unit(transl env body),
-                         Clet(id_prev, Cvar id,
+                         Clet(id_prev, Cvar (VP.var id),
                           Csequence
-                            (Cassign(id,
-                               Cop(inc, [Cvar id; Cconst_int 2],
+                            (Cassign(VP.var id,
+                               Cop(inc, [Cvar (VP.var id); Cconst_int 2],
                                  dbg)),
                              Cifthenelse
-                               (Cop(Ccmpi Ceq, [Cvar id_prev; high],
+                               (Cop(Ccmpi Ceq, [Cvar (VP.var id_prev); high],
                                   dbg),
                                 Cexit (raise_num,[]), Ctuple [])))))),
                  Ctuple []))))
@@ -2081,7 +2157,8 @@ and transl_prim_1 env p arg dbg =
               bind "header" hdr (fun hdr ->
                 Cifthenelse(is_addr_array_hdr hdr dbg,
                             Cop(Clsr, [hdr; Cconst_int wordsize_shift], dbg),
-                            Cop(Clsr, [hdr; Cconst_int numfloat_shift], dbg))) in
+                            Cop(Clsr, [hdr; Cconst_int numfloat_shift], dbg)))
+          in
           Cop(Cor, [len; Cconst_int 1], dbg)
       | Paddrarray | Pintarray ->
           Cop(Cor, [addr_array_length hdr dbg; Cconst_int 1], dbg)
@@ -2155,7 +2232,7 @@ and transl_prim_2 env p arg1 arg2 dbg =
       let dbg' = Debuginfo.none in
       transl_sequand env arg1 dbg arg2 dbg' Then_true_else_false
         (Cconst_pointer 3) (Cconst_pointer 1)
-      (* let id = Ident.create "res1" in
+      (* let id = V.create_local "res1" in
       Clet(id, transl env arg1,
            Cifthenelse(test_bool dbg (Cvar id), transl env arg2, Cvar id)) *)
   | Psequor ->
@@ -2213,23 +2290,28 @@ and transl_prim_2 env p arg1 arg2 dbg =
   (* Float operations *)
   | Paddfloat ->
       box_float dbg (Cop(Caddf,
-                    [transl_unbox_float dbg env arg1; transl_unbox_float dbg env arg2],
+                    [transl_unbox_float dbg env arg1;
+                     transl_unbox_float dbg env arg2],
                     dbg))
   | Psubfloat ->
       box_float dbg (Cop(Csubf,
-                    [transl_unbox_float dbg env arg1; transl_unbox_float dbg env arg2],
+                    [transl_unbox_float dbg env arg1;
+                     transl_unbox_float dbg env arg2],
                     dbg))
   | Pmulfloat ->
       box_float dbg (Cop(Cmulf,
-                    [transl_unbox_float dbg env arg1; transl_unbox_float dbg env arg2],
+                    [transl_unbox_float dbg env arg1;
+                     transl_unbox_float dbg env arg2],
                     dbg))
   | Pdivfloat ->
       box_float dbg (Cop(Cdivf,
-                    [transl_unbox_float dbg env arg1; transl_unbox_float dbg env arg2],
+                    [transl_unbox_float dbg env arg1;
+                     transl_unbox_float dbg env arg2],
                     dbg))
   | Pfloatcomp cmp ->
       tag_int(Cop(Ccmpf(transl_float_comparison cmp),
-                  [transl_unbox_float dbg env arg1; transl_unbox_float dbg env arg2],
+                  [transl_unbox_float dbg env arg1;
+                   transl_unbox_float dbg env arg2],
                   dbg)) dbg
 
   (* String operations *)
@@ -2404,7 +2486,8 @@ and transl_prim_2 env p arg1 arg2 dbg =
                       untag_int(transl env arg2) dbg], dbg))
   | Plsrbint bi ->
       box_int dbg bi (Cop(Clsr,
-                     [make_unsigned_int bi (transl_unbox_int dbg env bi arg1) dbg;
+                     [make_unsigned_int bi (transl_unbox_int dbg env bi arg1)
+                                        dbg;
                       untag_int(transl env arg2) dbg], dbg))
   | Pasrbint bi ->
       box_int dbg bi (Cop(Casr,
@@ -2651,9 +2734,9 @@ and transl_let env str kind id exp body =
          there may be constant closures inside that need lifting out. *)
       Clet(id, transl env exp, transl env body)
   | Boxed (boxed_number, _false) ->
-      let unboxed_id = Ident.create (Ident.name id) in
-      Clet(unboxed_id, transl_unbox_number dbg env boxed_number exp,
-           transl (add_unboxed_id id unboxed_id boxed_number env) body)
+      let unboxed_id = V.create_local (VP.name id) in
+      Clet(VP.create unboxed_id, transl_unbox_number dbg env boxed_number exp,
+           transl (add_unboxed_id (VP.var id) unboxed_id boxed_number env) body)
 
 and make_catch ncatch body handler = match body with
 | Cexit (nexit,[]) when nexit=ncatch -> handler
@@ -2733,6 +2816,7 @@ and transl_sequor env arg1 dbg1 arg2 dbg2 approx then_ else_ =
          (transl_if env arg2 dbg2 approx shareable_then else_))
     then_
 
+(* This assumes that [arg] can be safely discarded if it is not used. *)
 and transl_switch loc env arg index cases = match Array.length cases with
 | 0 -> fatal_error "Cmmgen.transl_switch"
 | 1 -> transl env cases.(0)
@@ -2774,7 +2858,7 @@ and transl_switch loc env arg index cases = match Array.length cases with
 and transl_letrec env bindings cont =
   let dbg = Debuginfo.none in
   let bsz =
-    List.map (fun (id, exp) -> (id, exp, expr_size Ident.empty exp))
+    List.map (fun (id, exp) -> (id, exp, expr_size V.empty exp))
       bindings
   in
   let op_alloc prim sz =
@@ -2800,7 +2884,7 @@ and transl_letrec env bindings cont =
     | (id, exp, (RHS_block _ | RHS_floatblock _)) :: rem ->
         let op =
           Cop(Cextcall("caml_update_dummy", typ_void, false, None),
-              [Cvar id; transl env exp], dbg) in
+              [Cvar (VP.var id); transl env exp], dbg) in
         Csequence(op, fill_blocks rem)
     | (_id, _exp, RHS_nonrec) :: rem ->
         fill_blocks rem
@@ -2808,10 +2892,10 @@ and transl_letrec env bindings cont =
 
 (* Translate a function definition *)
 
-let transl_function f =
+let transl_function ~ppf_dump f =
   let body =
     if Config.flambda then
-      Un_anf.apply f.body ~what:f.label
+      Un_anf.apply ~ppf_dump f.body ~what:f.label
     else
       f.body
   in
@@ -2828,28 +2912,22 @@ let transl_function f =
       [ Reduce_code_size ]
   in
   Cfunction {fun_name = f.label;
-             fun_args = List.map (fun id -> (id, typ_val)) f.params;
+             fun_args = List.map (fun (id, _) -> (id, typ_val)) f.params;
              fun_body = cmm_body;
              fun_codegen_options;
              fun_dbg  = f.dbg}
 
 (* Translate all function definitions *)
 
-module StringSet =
-  Set.Make(struct
-    type t = string
-    let compare (x:t) y = compare x y
-  end)
-
-let rec transl_all_functions already_translated cont =
+let rec transl_all_functions ~ppf_dump already_translated cont =
   try
     let f = Queue.take functions in
-    if StringSet.mem f.label already_translated then
-      transl_all_functions already_translated cont
+    if String.Set.mem f.label already_translated then
+      transl_all_functions ~ppf_dump already_translated cont
     else begin
-      transl_all_functions
-        (StringSet.add f.label already_translated)
-        ((f.dbg, transl_function f) :: cont)
+      transl_all_functions ~ppf_dump
+        (String.Set.add f.label already_translated)
+        ((f.dbg, transl_function ~ppf_dump f) :: cont)
     end
   with Queue.Empty ->
     cont, already_translated
@@ -2989,7 +3067,7 @@ let emit_constant_table symb elems =
 let emit_constants cont (constants:Clambda.preallocated_constant list) =
   let c = ref cont in
   List.iter
-    (fun { symbol = lbl; exported; definition = cst } ->
+    (fun { symbol = lbl; exported; definition = cst; provenance = _; } ->
        let global = if exported then Global else Not_global in
        let cst = emit_structured_constant (lbl, global) cst [] in
          c:= Cdata(cst):: !c)
@@ -3009,20 +3087,20 @@ let emit_all_constants cont =
   Compilenv.clear_structured_constants ();
   emit_constants cont constants
 
-let transl_all_functions_and_emit_all_constants cont =
+let transl_all_functions_and_emit_all_constants ~ppf_dump cont =
   let rec aux already_translated cont translated_functions =
     if Compilenv.structured_constants () = [] &&
        Queue.is_empty functions
     then cont, translated_functions
     else
       let translated_functions, already_translated =
-        transl_all_functions already_translated translated_functions
+        transl_all_functions ~ppf_dump already_translated translated_functions
       in
       let cont = emit_all_constants cont in
       aux already_translated cont translated_functions
   in
   let cont, translated_functions =
-    aux StringSet.empty cont []
+    aux String.Set.empty cont []
   in
   let translated_functions =
     (* Sort functions according to source position *)
@@ -3081,7 +3159,7 @@ let emit_preallocated_blocks preallocated_blocks cont =
 
 (* Translate a compilation unit *)
 
-let compunit (ulam, preallocated_blocks, constants) =
+let compunit ~ppf_dump (ulam, preallocated_blocks, constants) =
   let init_code =
     if !Clflags.afl_instrument then
       Afl_instrument.instrument_initialiser (transl empty_env ulam)
@@ -3101,7 +3179,7 @@ let compunit (ulam, preallocated_blocks, constants) =
                          else [ Reduce_code_size ];
                        fun_dbg  = Debuginfo.none }] in
   let c2 = emit_constants c1 constants in
-  let c3 = transl_all_functions_and_emit_all_constants c2 in
+  let c3 = transl_all_functions_and_emit_all_constants ~ppf_dump c2 in
   emit_preallocated_blocks preallocated_blocks c3
 
 (*
@@ -3120,18 +3198,18 @@ CAMLprim value caml_cache_public_method (value meths, value tag, value *cache)
 
 let cache_public_method meths tag cache dbg =
   let raise_num = next_raise_count () in
-  let li = Ident.create "li" and hi = Ident.create "hi"
-  and mi = Ident.create "mi" and tagged = Ident.create "tagged" in
+  let li = V.create_local "li" and hi = V.create_local "hi"
+  and mi = V.create_local "mi" and tagged = V.create_local "tagged" in
   Clet (
-  li, Cconst_int 3,
+  VP.create li, Cconst_int 3,
   Clet (
-  hi, Cop(Cload (Word_int, Mutable), [meths], dbg),
+  VP.create hi, Cop(Cload (Word_int, Mutable), [meths], dbg),
   Csequence(
   ccatch
     (raise_num, [],
      Cloop
        (Clet(
-        mi,
+        VP.create mi,
         Cop(Cor,
             [Cop(Clsr, [Cop(Caddi, [Cvar li; Cvar hi], dbg); Cconst_int 1],
                dbg);
@@ -3153,7 +3231,7 @@ let cache_public_method meths tag cache dbg =
            Ctuple [])))),
      Ctuple []),
   Clet (
-    tagged,
+    VP.create tagged,
       Cop(Cadda, [lsl_const (Cvar li) log2_size_addr dbg;
         Cconst_int(1 - 3 * size_addr)], dbg),
     Csequence(Cop (Cstore (Word_int, Assignment), [cache; Cvar tagged], dbg),
@@ -3172,17 +3250,17 @@ let cache_public_method meths tag cache dbg =
 
 let apply_function_body arity =
   let dbg = Debuginfo.none in
-  let arg = Array.make arity (Ident.create "arg") in
-  for i = 1 to arity - 1 do arg.(i) <- Ident.create "arg" done;
-  let clos = Ident.create "clos" in
+  let arg = Array.make arity (V.create_local "arg") in
+  for i = 1 to arity - 1 do arg.(i) <- V.create_local "arg" done;
+  let clos = V.create_local "clos" in
   let env = empty_env in
   let rec app_fun clos n =
     if n = arity-1 then
       Cop(Capply typ_val,
           [get_field env (Cvar clos) 0 dbg; Cvar arg.(n); Cvar clos], dbg)
     else begin
-      let newclos = Ident.create "clos" in
-      Clet(newclos,
+      let newclos = V.create_local "clos" in
+      Clet(VP.create newclos,
            Cop(Capply typ_val,
                [get_field env (Cvar clos) 0 dbg; Cvar arg.(n); Cvar clos], dbg),
            app_fun newclos (n+1))
@@ -3201,26 +3279,26 @@ let apply_function_body arity =
 let send_function arity =
   let dbg = Debuginfo.none in
   let (args, clos', body) = apply_function_body (1+arity) in
-  let cache = Ident.create "cache"
+  let cache = V.create_local "cache"
   and obj = List.hd args
-  and tag = Ident.create "tag" in
+  and tag = V.create_local "tag" in
   let env = empty_env in
   let clos =
     let cache = Cvar cache and obj = Cvar obj and tag = Cvar tag in
-    let meths = Ident.create "meths" and cached = Ident.create "cached" in
-    let real = Ident.create "real" in
+    let meths = V.create_local "meths" and cached = V.create_local "cached" in
+    let real = V.create_local "real" in
     let mask = get_field env (Cvar meths) 1 dbg in
     let cached_pos = Cvar cached in
     let tag_pos = Cop(Cadda, [Cop (Cadda, [cached_pos; Cvar meths], dbg);
                               Cconst_int(3*size_addr-1)], dbg) in
     let tag' = Cop(Cload (Word_int, Mutable), [tag_pos], dbg) in
     Clet (
-    meths, Cop(Cload (Word_val, Mutable), [obj], dbg),
+    VP.create meths, Cop(Cload (Word_val, Mutable), [obj], dbg),
     Clet (
-    cached,
+    VP.create cached,
       Cop(Cand, [Cop(Cload (Word_int, Mutable), [cache], dbg); mask], dbg),
     Clet (
-    real,
+    VP.create real,
     Cifthenelse(Cop(Ccmpa Cne, [tag'; tag], dbg),
                 cache_public_method (Cvar meths) tag cache dbg,
                 cached_pos),
@@ -3229,15 +3307,15 @@ let send_function arity =
        Cconst_int(2*size_addr-1)], dbg)], dbg))))
 
   in
-  let body = Clet(clos', clos, body) in
+  let body = Clet(VP.create clos', clos, body) in
   let cache = cache in
   let fun_args =
     [obj, typ_val; tag, typ_int; cache, typ_val]
     @ List.map (fun id -> (id, typ_val)) (List.tl args) in
-  let fun_name = "caml_send" ^ string_of_int arity in
+  let fun_name = "caml_send" ^ Int.to_string arity in
   Cfunction
    {fun_name;
-    fun_args = fun_args;
+    fun_args = List.map (fun (arg, ty) -> VP.create arg, ty) fun_args;
     fun_body = body;
     fun_codegen_options = [];
     fun_dbg  = Debuginfo.none }
@@ -3245,10 +3323,10 @@ let send_function arity =
 let apply_function arity =
   let (args, clos, body) = apply_function_body arity in
   let all_args = args @ [clos] in
-  let fun_name = "caml_apply" ^ string_of_int arity in
+  let fun_name = "caml_apply" ^ Int.to_string arity in
   Cfunction
    {fun_name;
-    fun_args = List.map (fun id -> (id, typ_val)) all_args;
+    fun_args = List.map (fun arg -> (VP.create arg, typ_val)) all_args;
     fun_body = body;
     fun_codegen_options = [];
     fun_dbg  = Debuginfo.none;
@@ -3260,17 +3338,17 @@ let apply_function arity =
 
 let tuplify_function arity =
   let dbg = Debuginfo.none in
-  let arg = Ident.create "arg" in
-  let clos = Ident.create "clos" in
+  let arg = V.create_local "arg" in
+  let clos = V.create_local "clos" in
   let env = empty_env in
   let rec access_components i =
     if i >= arity
     then []
     else get_field env (Cvar arg) i dbg :: access_components(i+1) in
-  let fun_name = "caml_tuplify" ^ string_of_int arity in
+  let fun_name = "caml_tuplify" ^ Int.to_string arity in
   Cfunction
    {fun_name;
-    fun_args = [arg, typ_val; clos, typ_val];
+    fun_args = [VP.create arg, typ_val; VP.create clos, typ_val];
     fun_body =
       Cop(Capply typ_val,
           get_field env (Cvar clos) 2 dbg :: access_components 0 @ [Cvar clos],
@@ -3310,8 +3388,8 @@ let tuplify_function arity =
 let max_arity_optimized = 15
 let final_curry_function arity =
   let dbg = Debuginfo.none in
-  let last_arg = Ident.create "arg" in
-  let last_clos = Ident.create "clos" in
+  let last_arg = V.create_local "arg" in
+  let last_clos = V.create_local "clos" in
   let env = empty_env in
   let rec curry_fun args clos n =
     if n = 0 then
@@ -3322,21 +3400,22 @@ let final_curry_function arity =
     else
       if n = arity - 1 || arity > max_arity_optimized then
         begin
-      let newclos = Ident.create "clos" in
-      Clet(newclos,
+      let newclos = V.create_local "clos" in
+      Clet(VP.create newclos,
            get_field env (Cvar clos) 3 dbg,
            curry_fun (get_field env (Cvar clos) 2 dbg :: args) newclos (n-1))
         end else
         begin
-          let newclos = Ident.create "clos" in
-          Clet(newclos,
+          let newclos = V.create_local "clos" in
+          Clet(VP.create newclos,
                get_field env (Cvar clos) 4 dbg,
-               curry_fun (get_field env (Cvar clos) 3 dbg :: args) newclos (n-1))
+               curry_fun (get_field env (Cvar clos) 3 dbg :: args)
+                         newclos (n-1))
     end in
   Cfunction
-   {fun_name = "caml_curry" ^ string_of_int arity ^
-               "_" ^ string_of_int (arity-1);
-    fun_args = [last_arg, typ_val; last_clos, typ_val];
+   {fun_name = "caml_curry" ^ Int.to_string arity ^
+               "_" ^ Int.to_string (arity-1);
+    fun_args = [VP.create last_arg, typ_val; VP.create last_clos, typ_val];
     fun_body = curry_fun [] last_clos (arity-1);
     fun_codegen_options = [];
     fun_dbg  = Debuginfo.none }
@@ -3347,25 +3426,25 @@ let rec intermediate_curry_functions arity num =
   if num = arity - 1 then
     [final_curry_function arity]
   else begin
-    let name1 = "caml_curry" ^ string_of_int arity in
-    let name2 = if num = 0 then name1 else name1 ^ "_" ^ string_of_int num in
-    let arg = Ident.create "arg" and clos = Ident.create "clos" in
+    let name1 = "caml_curry" ^ Int.to_string arity in
+    let name2 = if num = 0 then name1 else name1 ^ "_" ^ Int.to_string num in
+    let arg = V.create_local "arg" and clos = V.create_local "clos" in
     Cfunction
      {fun_name = name2;
-      fun_args = [arg, typ_val; clos, typ_val];
+      fun_args = [VP.create arg, typ_val; VP.create clos, typ_val];
       fun_body =
          if arity - num > 2 && arity <= max_arity_optimized then
            Cop(Calloc,
                [alloc_closure_header 5 Debuginfo.none;
-                Cconst_symbol(name1 ^ "_" ^ string_of_int (num+1));
+                Cconst_symbol(name1 ^ "_" ^ Int.to_string (num+1));
                 int_const (arity - num - 1);
-                Cconst_symbol(name1 ^ "_" ^ string_of_int (num+1) ^ "_app");
+                Cconst_symbol(name1 ^ "_" ^ Int.to_string (num+1) ^ "_app");
                 Cvar arg; Cvar clos],
                dbg)
          else
            Cop(Calloc,
                 [alloc_closure_header 4 Debuginfo.none;
-                 Cconst_symbol(name1 ^ "_" ^ string_of_int (num+1));
+                 Cconst_symbol(name1 ^ "_" ^ Int.to_string (num+1));
                  int_const 1; Cvar arg; Cvar clos],
                 dbg);
       fun_codegen_options = [];
@@ -3374,7 +3453,7 @@ let rec intermediate_curry_functions arity num =
       (if arity <= max_arity_optimized && arity - num > 2 then
           let rec iter i =
             if i <= arity then
-              let arg = Ident.create (Printf.sprintf "arg%d" i) in
+              let arg = V.create_local (Printf.sprintf "arg%d" i) in
               (arg, typ_val) :: iter (i+1)
             else []
           in
@@ -3385,15 +3464,19 @@ let rec intermediate_curry_functions arity num =
                   (get_field env (Cvar clos) 2 dbg) :: args @ [Cvar clos],
                   dbg)
             else
-              let newclos = Ident.create "clos" in
-              Clet(newclos,
+              let newclos = V.create_local "clos" in
+              Clet(VP.create newclos,
                    get_field env (Cvar clos) 4 dbg,
                    iter (i-1) (get_field env (Cvar clos) 3 dbg :: args) newclos)
           in
+          let fun_args =
+            List.map (fun (arg, ty) -> VP.create arg, ty)
+              (direct_args @ [clos, typ_val])
+          in
           let cf =
             Cfunction
-              {fun_name = name1 ^ "_" ^ string_of_int (num+1) ^ "_app";
-               fun_args = direct_args @ [clos, typ_val];
+              {fun_name = name1 ^ "_" ^ Int.to_string (num+1) ^ "_app";
+               fun_args;
                fun_body = iter (num+1)
                   (List.map (fun (arg,_) -> Cvar arg) direct_args) clos;
                fun_codegen_options = [];
@@ -3411,30 +3494,25 @@ let curry_function arity =
   then intermediate_curry_functions arity 0
   else [tuplify_function (-arity)]
 
+module Int = Numbers.Int
 
-module IntSet = Set.Make(
-  struct
-    type t = int
-    let compare (x:t) y = compare x y
-  end)
-
-let default_apply = IntSet.add 2 (IntSet.add 3 IntSet.empty)
+let default_apply = Int.Set.add 2 (Int.Set.add 3 Int.Set.empty)
   (* These apply funs are always present in the main program because
-     the run-time system needs them (cf. asmrun/.S) . *)
+     the run-time system needs them (cf. runtime/.S) . *)
 
 let generic_functions shared units =
   let (apply,send,curry) =
     List.fold_left
       (fun (apply,send,curry) ui ->
-         List.fold_right IntSet.add ui.ui_apply_fun apply,
-         List.fold_right IntSet.add ui.ui_send_fun send,
-         List.fold_right IntSet.add ui.ui_curry_fun curry)
-      (IntSet.empty,IntSet.empty,IntSet.empty)
+         List.fold_right Int.Set.add ui.ui_apply_fun apply,
+         List.fold_right Int.Set.add ui.ui_send_fun send,
+         List.fold_right Int.Set.add ui.ui_curry_fun curry)
+      (Int.Set.empty,Int.Set.empty,Int.Set.empty)
       units in
-  let apply = if shared then apply else IntSet.union apply default_apply in
-  let accu = IntSet.fold (fun n accu -> apply_function n :: accu) apply [] in
-  let accu = IntSet.fold (fun n accu -> send_function n :: accu) send accu in
-  IntSet.fold (fun n accu -> curry_function n @ accu) curry accu
+  let apply = if shared then apply else Int.Set.union apply default_apply in
+  let accu = Int.Set.fold (fun n accu -> apply_function n :: accu) apply [] in
+  let accu = Int.Set.fold (fun n accu -> send_function n :: accu) send accu in
+  Int.Set.fold (fun n accu -> curry_function n @ accu) curry accu
 
 (* Generate the entry point *)
 
diff --git a/asmcomp/cmmgen.mli b/asmcomp/cmmgen.mli
index 8104afab..6c33da95 100644
--- a/asmcomp/cmmgen.mli
+++ b/asmcomp/cmmgen.mli
@@ -16,7 +16,8 @@
 (* Translation from closed lambda to C-- *)
 
 val compunit:
-    Clambda.ulambda
+  ppf_dump:Format.formatter
+  -> Clambda.ulambda
     * Clambda.preallocated_block list
     * Clambda.preallocated_constant list
   -> Cmm.phrase list
@@ -28,8 +29,8 @@ val generic_functions: bool -> Cmx_format.unit_infos list -> Cmm.phrase list
 val entry_point: string list -> Cmm.phrase
 val global_table: string list -> Cmm.phrase
 val reference_symbols: string list -> Cmm.phrase
-val globals_map: (string * Digest.t * Digest.t * string list) list ->
-  Cmm.phrase
+val globals_map:
+  (string * Digest.t option * Digest.t option * string list) list -> Cmm.phrase
 val frame_table: string list -> Cmm.phrase
 val spacetime_shapes: string list -> Cmm.phrase
 val data_segment_table: string list -> Cmm.phrase
diff --git a/asmcomp/comballoc.ml b/asmcomp/comballoc.ml
index b4e1b1ef..b10edd2a 100644
--- a/asmcomp/comballoc.ml
+++ b/asmcomp/comballoc.ml
@@ -18,41 +18,42 @@
 open Mach
 
 type allocation_state =
-    No_alloc                            (* no allocation is pending *)
-  | Pending_alloc of Reg.t * int        (* an allocation is pending *)
-(* The arguments of Pending_alloc(reg, ofs) are:
-     reg  the register holding the result of the last allocation
-     ofs  the alloc position in the allocated block *)
+    No_alloc
+  | Pending_alloc of
+    { reg: Reg.t;    (* register holding the result of the last allocation *)
+      totalsz: int } (* amount to be allocated in this block *)
 
 let allocated_size = function
     No_alloc -> 0
-  | Pending_alloc(_, ofs) -> ofs
+  | Pending_alloc {totalsz; _} -> totalsz
 
 let rec combine i allocstate =
   match i.desc with
     Iend | Ireturn | Iexit _ | Iraise _ ->
       (i, allocated_size allocstate)
-  | Iop(Ialloc { words = sz; _ }) ->
+  | Iop(Ialloc { bytes = sz; _ }) ->
       begin match allocstate with
-        No_alloc ->
-          let (newnext, newsz) =
-            combine i.next (Pending_alloc(i.res.(0), sz)) in
-          (instr_cons_debug (Iop(Ialloc {words = newsz; spacetime_index = 0;
-              label_after_call_gc = None; }))
-            i.arg i.res i.dbg newnext, 0)
-      | Pending_alloc(reg, ofs) ->
-          if ofs + sz < Config.max_young_wosize * Arch.size_addr then begin
-            let (newnext, newsz) =
-              combine i.next (Pending_alloc(reg, ofs + sz)) in
-            (instr_cons (Iop(Iintop_imm(Iadd, ofs))) [| reg |] i.res newnext,
-             newsz)
-          end else begin
-            let (newnext, newsz) =
-              combine i.next (Pending_alloc(i.res.(0), sz)) in
-            (instr_cons_debug (Iop(Ialloc { words = newsz; spacetime_index = 0;
-                label_after_call_gc = None; }))
-              i.arg i.res i.dbg newnext, ofs)
-          end
+      | Pending_alloc {reg; totalsz}
+          when totalsz + sz < Config.max_young_wosize * Arch.size_addr ->
+         let (next, totalsz) =
+           combine i.next
+             (Pending_alloc { reg = i.res.(0); totalsz = totalsz + sz }) in
+         (instr_cons_debug (Iop(Iintop_imm(Iadd, -sz)))
+            [| reg |] i.res i.dbg next,
+          totalsz)
+      | No_alloc | Pending_alloc _ ->
+         let (next, totalsz) =
+           combine i.next
+             (Pending_alloc { reg = i.res.(0); totalsz = sz }) in
+         let next =
+           let offset = totalsz - sz in
+           if offset = 0 then next
+           else instr_cons_debug (Iop(Iintop_imm(Iadd, offset))) i.res
+                i.res i.dbg next
+         in
+         (instr_cons_debug (Iop(Ialloc {bytes = totalsz; spacetime_index = 0;
+                                        label_after_call_gc = None; }))
+          i.arg i.res i.dbg next, allocated_size allocstate)
       end
   | Iop(Icall_ind _ | Icall_imm _ | Iextcall _ |
         Itailcall_ind _ | Itailcall_imm _) ->
diff --git a/asmcomp/compilenv.ml b/asmcomp/compilenv.ml
index 0eb7eab2..add4e90e 100644
--- a/asmcomp/compilenv.ml
+++ b/asmcomp/compilenv.ml
@@ -22,7 +22,6 @@
 [@@@ocaml.warning "+a-4-9-40-41-42"]
 
 open Config
-open Misc
 open Cmx_format
 
 type error =
@@ -46,7 +45,7 @@ module CstMap =
   Map.Make(struct
     type t = Clambda.ustructured_constant
     let compare = Clambda.compare_structured_constants
-    (* PR#6442: it is incorrect to use Pervasives.compare on values of type t
+    (* PR#6442: it is incorrect to use Stdlib.compare on values of type t
        because it compares "0.0" and "-0.0" equal. *)
   end)
 
@@ -196,7 +195,7 @@ let get_global_info global_ident = (
         else begin
           try
             let filename =
-              find_in_path_uncap !load_path (modname ^ ".cmx") in
+              Load_path.find_uncap (modname ^ ".cmx") in
             let (ui, crc) = read_unit_info filename in
             if ui.ui_name <> modname then
               raise(Error(Illegal_renaming(modname, ui.ui_name, filename)));
@@ -233,7 +232,7 @@ let record_global_approx_toplevel () =
     (get_clambda_approx current_unit)
 
 let global_approx id =
-  if Ident.is_predef_exn id then Clambda.Value_unknown
+  if Ident.is_predef id then Clambda.Value_unknown
   else try Hashtbl.find toplevel_approx (Ident.name id)
   with Not_found ->
     match get_global_info id with
@@ -243,7 +242,7 @@ let global_approx id =
 (* Return the symbol used to refer to a global identifier *)
 
 let symbol_for_global id =
-  if Ident.is_predef_exn id then
+  if Ident.is_predef id then
     "caml_exn_" ^ Ident.name id
   else begin
     let unitname = Ident.name id in
@@ -272,7 +271,7 @@ let is_predefined_exception sym =
 
 let symbol_for_global' id =
   let sym_label = Linkage_name.create (symbol_for_global id) in
-  if Ident.is_predef_exn id then
+  if Ident.is_predef id then
     Symbol.of_global_linkage predefined_exception_compilation_unit sym_label
   else
     Symbol.of_global_linkage (unit_for_global id) sym_label
@@ -298,7 +297,7 @@ let approx_for_global comp_unit =
   if (Compilation_unit.equal
       predefined_exception_compilation_unit
       comp_unit)
-     || Ident.is_predef_exn id
+     || Ident.is_predef id
      || not (Ident.global id)
   then invalid_arg (Format.asprintf "approx_for_global %a" Ident.print id);
   let modname = Ident.name id in
@@ -357,7 +356,7 @@ let const_label = ref 0
 
 let new_const_symbol () =
   incr const_label;
-  make_symbol (Some (string_of_int !const_label))
+  make_symbol (Some (Int.to_string !const_label))
 
 let snapshot () = !structured_constants
 let backtrack s = structured_constants := s
@@ -391,12 +390,19 @@ let clear_structured_constants () =
   structured_constants := structured_constants_empty
 
 let structured_constants () =
+  let provenance : Clambda.usymbol_provenance =
+    { original_idents = [];
+      module_path =
+        Path.Pident (Ident.create_persistent (current_unit_name ()));
+    }
+  in
   List.map
     (fun (symbol, definition) ->
        {
          Clambda.symbol;
          exported = Hashtbl.mem exported_constants symbol;
          definition;
+         provenance = Some provenance;
        })
     (!structured_constants).strcst_all
 
@@ -419,7 +425,7 @@ let function_label fv =
   (concat_symbol unitname (Closure_id.unique_name fv))
 
 let require_global global_ident =
-  if not (Ident.is_predef_exn global_ident) then
+  if not (Ident.is_predef global_ident) then
     ignore (get_global_info global_ident : Cmx_format.unit_infos option)
 
 (* Error report *)
diff --git a/asmcomp/compilenv.mli b/asmcomp/compilenv.mli
index 4fcd55e2..569d51ea 100644
--- a/asmcomp/compilenv.mli
+++ b/asmcomp/compilenv.mli
@@ -86,7 +86,7 @@ val record_global_approx_toplevel: unit -> unit
            clambda-only *)
 
 val set_export_info: Export_info.t -> unit
-        (* Record the informations of the unit being compiled
+        (* Record the information of the unit being compiled
            flambda-only *)
 val approx_env: unit -> Export_info.t
         (* Returns all the information loaded from external compilation units
diff --git a/asmcomp/debug/available_regs.ml b/asmcomp/debug/available_regs.ml
index b95c6415..9886f772 100644
--- a/asmcomp/debug/available_regs.ml
+++ b/asmcomp/debug/available_regs.ml
@@ -18,6 +18,7 @@ module M = Mach
 module R = Reg
 module RAS = Reg_availability_set
 module RD = Reg_with_debug_info
+module V = Backend_var
 
 (* This pass treats [avail_at_exit] like a "result" structure whereas the
    equivalent in [Liveness] is like an "environment".  (Which means we need
@@ -108,7 +109,8 @@ let rec available_regs (instr : M.instruction)
                 match RD.debug_info reg with
                 | None -> reg
                 | Some debug_info ->
-                  if Ident.same (RD.Debug_info.holds_value_of debug_info) ident
+                  if V.same
+                    (RD.Debug_info.holds_value_of debug_info) ident
                   then RD.clear_debug_info reg
                   else reg)
               avail_before
diff --git a/asmcomp/debug/reg_availability_set.ml b/asmcomp/debug/reg_availability_set.ml
index 832ff141..fbff598d 100644
--- a/asmcomp/debug/reg_availability_set.ml
+++ b/asmcomp/debug/reg_availability_set.ml
@@ -15,6 +15,7 @@
 [@@@ocaml.warning "+a-4-9-30-40-41-42"]
 
 module RD = Reg_with_debug_info
+module V = Backend_var
 
 type t =
   | Ok of RD.Set.t
@@ -69,15 +70,15 @@ let canonicalise availability =
   match availability with
   | Unreachable -> Unreachable
   | Ok availability ->
-    let regs_by_ident = Ident.Tbl.create 42 in
+    let regs_by_ident = V.Tbl.create 42 in
     RD.Set.iter (fun reg ->
         match RD.debug_info reg with
         | None -> ()
         | Some debug_info ->
           let name = RD.Debug_info.holds_value_of debug_info in
-          if not (Ident.persistent name) then begin
-            match Ident.Tbl.find regs_by_ident name with
-            | exception Not_found -> Ident.Tbl.add regs_by_ident name reg
+          if not (V.persistent name) then begin
+            match V.Tbl.find regs_by_ident name with
+            | exception Not_found -> V.Tbl.add regs_by_ident name reg
             | (reg' : RD.t) ->
               (* We prefer registers that are assigned to the stack since
                  they probably give longer available ranges (less likely to
@@ -89,12 +90,12 @@ let canonicalise availability =
               | _, Unknown
               | Unknown, _ -> ()
               | Stack _, Reg _ ->
-                Ident.Tbl.remove regs_by_ident name;
-                Ident.Tbl.add regs_by_ident name reg
+                V.Tbl.remove regs_by_ident name;
+                V.Tbl.add regs_by_ident name reg
           end)
       availability;
     let result =
-      Ident.Tbl.fold (fun _ident reg availability ->
+      V.Tbl.fold (fun _ident reg availability ->
           RD.Set.add reg availability)
         regs_by_ident
         RD.Set.empty
diff --git a/asmcomp/debug/reg_with_debug_info.ml b/asmcomp/debug/reg_with_debug_info.ml
index e6ff8361..3dd0ce0c 100644
--- a/asmcomp/debug/reg_with_debug_info.ml
+++ b/asmcomp/debug/reg_with_debug_info.ml
@@ -14,9 +14,11 @@
 
 [@@@ocaml.warning "+a-4-9-30-40-41-42"]
 
+module V = Backend_var
+
 module Debug_info = struct
   type t = {
-    holds_value_of : Ident.t;
+    holds_value_of : V.t;
     part_of_value : int;
     num_parts_of_value : int;
     which_parameter : int option;
@@ -24,10 +26,10 @@ module Debug_info = struct
   }
 
   let compare t1 t2 =
-    let c = Ident.compare t1.holds_value_of t2.holds_value_of in
+    let c = V.compare t1.holds_value_of t2.holds_value_of in
     if c <> 0 then c
     else
-      Pervasives.compare
+      Stdlib.compare
         (t1.part_of_value, t1.num_parts_of_value, t1.which_parameter)
         (t2.part_of_value, t2.num_parts_of_value, t2.which_parameter)
 
@@ -38,7 +40,7 @@ module Debug_info = struct
   let provenance t = t.provenance
 
   let print ppf t =
-    Format.fprintf ppf "%a" Ident.print t.holds_value_of;
+    Format.fprintf ppf "%a" V.print t.holds_value_of;
     if not (t.part_of_value = 0 && t.num_parts_of_value = 1) then begin
       Format.fprintf ppf "(%d/%d)" t.part_of_value t.num_parts_of_value
     end;
@@ -140,9 +142,9 @@ module Order_distinguishing_names_and_locations = struct
     | None, Some _ -> -1
     | Some _, None -> 1
     | Some di1, Some di2 ->
-      let c = Ident.compare di1.holds_value_of di2.holds_value_of in
+      let c = V.compare di1.holds_value_of di2.holds_value_of in
       if c <> 0 then c
-      else Pervasives.compare t1.reg.loc t2.reg.loc
+      else Stdlib.compare t1.reg.loc t2.reg.loc
 end
 
 module Set_distinguishing_names_and_locations =
diff --git a/asmcomp/debug/reg_with_debug_info.mli b/asmcomp/debug/reg_with_debug_info.mli
index 2f0599d3..b989bdeb 100644
--- a/asmcomp/debug/reg_with_debug_info.mli
+++ b/asmcomp/debug/reg_with_debug_info.mli
@@ -20,7 +20,7 @@ module Debug_info : sig
 
   val compare : t -> t -> int
 
-  val holds_value_of : t -> Ident.t
+  val holds_value_of : t -> Backend_var.t
   (** The identifier that the register holds (part of) the value of. *)
 
   val part_of_value : t -> int
@@ -39,7 +39,7 @@ type reg_with_debug_info = t
 
 val create
    : reg:Reg.t
-  -> holds_value_of:Ident.t
+  -> holds_value_of:Backend_var.t
   -> part_of_value:int
   -> num_parts_of_value:int
   -> which_parameter:int option
diff --git a/asmcomp/dune b/asmcomp/dune
new file mode 100644
index 00000000..a208b56e
--- /dev/null
+++ b/asmcomp/dune
@@ -0,0 +1,44 @@
+;**************************************************************************
+;*                                                                        *
+;*                                 OCaml                                  *
+;*                                                                        *
+;*                     Thomas Refis, Jane Street Europe                   *
+;*                                                                        *
+;*   Copyright 2018 Jane Street Group LLC                                 *
+;*                                                                        *
+;*   All rights reserved.  This file is distributed under the terms of    *
+;*   the GNU Lesser General Public License version 2.1, with the          *
+;*   special exception on linking described in the file LICENSE.          *
+;*                                                                        *
+;**************************************************************************
+
+(rule
+ (targets arch.ml CSE.ml proc.ml reload.ml scheduling.ml selection.ml)
+ (mode    fallback)
+ (deps    (:conf ../Makefile.config)
+          (glob_files amd64/*.ml)
+          (glob_files arm/*.ml)
+          (glob_files arm64/*.ml)
+          (glob_files i386/*.ml)
+          (glob_files power/*.ml)
+          (glob_files s390x/*.ml))
+ (action  (bash "cp `grep '^ARCH=' %{conf} | cut -d'=' -f2`/*.ml .")))
+
+(rule
+ (targets emit.ml)
+ (mode    fallback)
+ (deps    (:conf ../Makefile.config)
+          amd64/emit.mlp
+          arm/emit.mlp
+          arm64/emit.mlp
+          i386/emit.mlp
+          power/emit.mlp
+          s390x/emit.mlp)
+ (action
+   (progn
+     (with-stdout-to contains-input-name
+       (bash "echo `grep '^ARCH=' %{conf} | cut -d'=' -f2`/emit.mlp"))
+     (with-stdout-to %{targets}
+       (progn
+         (bash "echo \\# 1 \\\"`cat contains-input-name`\\\"")
+         (bash "%{dep:../tools/cvt_emit.exe} < `cat contains-input-name`"))))))
diff --git a/asmcomp/emitaux.ml b/asmcomp/emitaux.ml
index 9fd925d3..e0476d17 100644
--- a/asmcomp/emitaux.ml
+++ b/asmcomp/emitaux.ml
@@ -19,7 +19,7 @@ let output_channel = ref stdout
 
 let emit_string s = output_string !output_channel s
 
-let emit_int n = output_string !output_channel (string_of_int n)
+let emit_int n = output_string !output_channel (Int.to_string n)
 
 let emit_char c = output_char !output_channel c
 
diff --git a/asmcomp/export_info.ml b/asmcomp/export_info.ml
index 9edc7c1b..22dbb6c5 100644
--- a/asmcomp/export_info.ml
+++ b/asmcomp/export_info.ml
@@ -277,7 +277,9 @@ let merge (t1 : t) (t2 : t) : t =
     sets_of_closures =
       Set_of_closures_id.Map.disjoint_union t1.sets_of_closures
         t2.sets_of_closures;
-    symbol_id = Symbol.Map.disjoint_union ~print:Export_id.print t1.symbol_id t2.symbol_id;
+    symbol_id =
+      Symbol.Map.disjoint_union ~print:Export_id.print t1.symbol_id
+        t2.symbol_id;
     offset_fun = Closure_id.Map.disjoint_union
         ~eq:int_eq t1.offset_fun t2.offset_fun;
     offset_fv = Var_within_closure.Map.disjoint_union
diff --git a/asmcomp/flambda_to_clambda.ml b/asmcomp/flambda_to_clambda.ml
index 713e87bf..e1b0f446 100644
--- a/asmcomp/flambda_to_clambda.ml
+++ b/asmcomp/flambda_to_clambda.ml
@@ -16,6 +16,9 @@
 
 [@@@ocaml.warning "+a-4-9-30-40-41-42"]
 
+module V = Backend_var
+module VP = Backend_var.With_provenance
+
 type 'a for_one_or_more_units = {
   fun_offset_table : int Closure_id.Map.t;
   fv_offset_table : int Var_within_closure.Map.t;
@@ -24,8 +27,10 @@ type 'a for_one_or_more_units = {
 }
 
 type t = {
-  current_unit : Set_of_closures_id.t for_one_or_more_units;
-  imported_units : Simple_value_approx.function_declarations for_one_or_more_units;
+  current_unit :
+    Set_of_closures_id.t for_one_or_more_units;
+  imported_units :
+    Simple_value_approx.function_declarations for_one_or_more_units;
 }
 
 let get_fun_offset t closure_id =
@@ -107,11 +112,11 @@ module Env : sig
   val add_subst : t -> Variable.t -> Clambda.ulambda -> t
   val find_subst_exn : t -> Variable.t -> Clambda.ulambda
 
-  val add_fresh_ident : t -> Variable.t -> Ident.t * t
-  val ident_for_var_exn : t -> Variable.t -> Ident.t
+  val add_fresh_ident : t -> Variable.t -> V.t * t
+  val ident_for_var_exn : t -> Variable.t -> V.t
 
-  val add_fresh_mutable_ident : t -> Mutable_variable.t -> Ident.t * t
-  val ident_for_mutable_var_exn : t -> Mutable_variable.t -> Ident.t
+  val add_fresh_mutable_ident : t -> Mutable_variable.t -> V.t * t
+  val ident_for_mutable_var_exn : t -> Mutable_variable.t -> V.t
 
   val add_allocated_const : t -> Symbol.t -> Allocated_const.t -> t
   val allocated_const_for_symbol : t -> Symbol.t -> Allocated_const.t option
@@ -120,8 +125,8 @@ module Env : sig
 end = struct
   type t =
     { subst : Clambda.ulambda Variable.Map.t;
-      var : Ident.t Variable.Map.t;
-      mutable_var : Ident.t Mutable_variable.Map.t;
+      var : V.t Variable.Map.t;
+      mutable_var : V.t Mutable_variable.Map.t;
       toplevel : bool;
       allocated_constant_for_symbol : Allocated_const.t Symbol.Map.t;
     }
@@ -142,14 +147,14 @@ end = struct
   let ident_for_var_exn t id = Variable.Map.find id t.var
 
   let add_fresh_ident t var =
-    let id = Ident.create (Variable.name var) in
+    let id = V.create_local (Variable.name var) in
     id, { t with var = Variable.Map.add var id t.var }
 
   let ident_for_mutable_var_exn t mut_var =
     Mutable_variable.Map.find mut_var t.mutable_var
 
   let add_fresh_mutable_ident t mut_var =
-    let id = Ident.create (Mutable_variable.name mut_var) in
+    let id = V.create_local (Mutable_variable.name mut_var) in
     let mutable_var = Mutable_variable.Map.add mut_var id t.mutable_var in
     id, { t with mutable_var; }
 
@@ -222,12 +227,13 @@ let rec to_clambda t env (flam : Flambda.t) : Clambda.ulambda =
   | Let { var; defining_expr; body; _ } ->
     (* TODO: synthesize proper value_kind *)
     let id, env_body = Env.add_fresh_ident env var in
-    Ulet (Immutable, Pgenval, id, to_clambda_named t env var defining_expr,
+    Ulet (Immutable, Pgenval, VP.create id,
+      to_clambda_named t env var defining_expr,
       to_clambda t env_body body)
   | Let_mutable { var = mut_var; initial_value = var; body; contents_kind } ->
     let id, env_body = Env.add_fresh_mutable_ident env mut_var in
     let def = subst_var env var in
-    Ulet (Mutable, contents_kind, id, def, to_clambda t env_body body)
+    Ulet (Mutable, contents_kind, VP.create id, def, to_clambda t env_body body)
   | Let_rec (defs, body) ->
     let env, defs =
       List.fold_right (fun (var, def) (env, defs) ->
@@ -236,7 +242,9 @@ let rec to_clambda t env (flam : Flambda.t) : Clambda.ulambda =
         defs (env, [])
     in
     let defs =
-      List.map (fun (id, var, def) -> id, to_clambda_named t env var def) defs
+      List.map (fun (id, var, def) ->
+          VP.create id, to_clambda_named t env var def)
+        defs
     in
     Uletrec (defs, to_clambda t env body)
   | Apply { func; args; kind = Direct direct_func; dbg = dbg } ->
@@ -301,14 +309,15 @@ let rec to_clambda t env (flam : Flambda.t) : Clambda.ulambda =
     let env_handler, ids =
       List.fold_right (fun var (env, ids) ->
           let id, env = Env.add_fresh_ident env var in
-          env, id :: ids)
+          env, (VP.create id, Lambda.Pgenval) :: ids)
         vars (env, [])
     in
     Ucatch (Static_exception.to_int static_exn, ids,
       to_clambda t env body, to_clambda t env_handler handler)
   | Try_with (body, var, handler) ->
     let id, env_handler = Env.add_fresh_ident env var in
-    Utrywith (to_clambda t env body, id, to_clambda t env_handler handler)
+    Utrywith (to_clambda t env body, VP.create id,
+      to_clambda t env_handler handler)
   | If_then_else (arg, ifso, ifnot) ->
     Uifthenelse (subst_var env arg, to_clambda t env ifso,
       to_clambda t env ifnot)
@@ -316,7 +325,7 @@ let rec to_clambda t env (flam : Flambda.t) : Clambda.ulambda =
     Uwhile (to_clambda t env cond, to_clambda t env body)
   | For { bound_var; from_value; to_value; direction; body } ->
     let id, env_body = Env.add_fresh_ident env bound_var in
-    Ufor (id, subst_var env from_value, subst_var env to_value,
+    Ufor (VP.create id, subst_var env from_value, subst_var env to_value,
       direction, to_clambda t env_body body)
   | Assign { being_assigned; new_value } ->
     let id =
@@ -464,7 +473,7 @@ and to_clambda_set_of_closures t env
       (({ function_decls; free_vars } : Flambda.set_of_closures)
         as set_of_closures) : Clambda.ulambda =
   let all_functions = Variable.Map.bindings function_decls.funs in
-  let env_var = Ident.create "env" in
+  let env_var = V.create_local "env" in
   let to_clambda_function
         (closure_id, (function_decl : Flambda.function_declaration))
         : Clambda.ufunction =
@@ -518,7 +527,11 @@ and to_clambda_set_of_closures t env
     in
     { label = Compilenv.function_label closure_id;
       arity = Flambda_utils.function_arity function_decl;
-      params = params @ [env_var];
+      params =
+        List.map
+          (fun var -> VP.create var, Lambda.Pgenval)
+          (params @ [env_var]);
+      return = Lambda.Pgenval;
       body = to_clambda t env_body function_decl.body;
       dbg = function_decl.dbg;
       env = Some env_var;
@@ -558,7 +571,8 @@ and to_clambda_closed_set_of_closures t env symbol
     in
     { label = Compilenv.function_label (Closure_id.wrap id);
       arity = Flambda_utils.function_arity function_decl;
-      params;
+      params = List.map (fun var -> VP.create var, Lambda.Pgenval) params;
+      return = Lambda.Pgenval;
       body = to_clambda t env_body function_decl.body;
       dbg = function_decl.dbg;
       env = None;
@@ -635,7 +649,7 @@ let to_clambda_program t env constants (program : Flambda.program) =
           fields
       in
       let init_fields =
-        Misc.Stdlib.List.filter_map (function
+        List.filter_map (function
             | (i, field, None) -> Some (i, field)
             | (_, _, Some _) -> None)
           fields
@@ -663,6 +677,7 @@ let to_clambda_program t env constants (program : Flambda.program) =
           exported = true;
           tag = Tag.to_int tag;
           fields = constant_fields;
+          provenance = None;
         }
       in
       let e2, constants, preallocated_blocks = loop env constants program in
diff --git a/asmcomp/i386/emit.mlp b/asmcomp/i386/emit.mlp
index 2d633f55..654b5629 100644
--- a/asmcomp/i386/emit.mlp
+++ b/asmcomp/i386/emit.mlp
@@ -24,6 +24,7 @@ open Reg
 open Mach
 open Linearize
 open Emitaux
+module String = Misc.Stdlib.String
 
 open X86_ast
 open X86_proc
@@ -77,11 +78,11 @@ let slot_offset loc cl =
 (* Record symbols used and defined - at the end generate extern for those
    used but not defined *)
 
-let symbols_defined = ref StringSet.empty
-let symbols_used = ref StringSet.empty
+let symbols_defined = ref String.Set.empty
+let symbols_used = ref String.Set.empty
 
-let add_def_symbol s = symbols_defined := StringSet.add s !symbols_defined
-let add_used_symbol s = symbols_used := StringSet.add s !symbols_used
+let add_def_symbol s = symbols_defined := String.Set.add s !symbols_defined
+let add_used_symbol s = symbols_used := String.Set.add s !symbols_used
 
 let trap_frame_size = Misc.align 8 stack_alignment
 
@@ -467,13 +468,40 @@ let function_name = ref ""
 (* Entry point for tail recursive calls *)
 let tailrec_entry_point = ref 0
 (* Record references to external C functions (for MacOSX) *)
-let external_symbols_direct = ref StringSet.empty
-let external_symbols_indirect = ref StringSet.empty
+let external_symbols_direct = ref String.Set.empty
+let external_symbols_indirect = ref String.Set.empty
+
+(* Emission of the profiling prelude *)
+
+let call_mcount mcount =
+  I.push eax;
+  I.mov esp ebp;
+  I.push ecx;
+  I.push edx;
+  I.call (sym mcount);
+  I.pop edx;
+  I.pop ecx;
+  I.pop eax
+
+let emit_profile () =
+  match system with
+  | S_linux_elf | S_gnu -> call_mcount "mcount"
+  | S_bsd_elf -> call_mcount ".mcount"
+  | S_macosx -> call_mcount "Lmcount$stub"
+  | _ -> () (*unsupported yet*)
 
 let emit_instr fallthrough i =
   emit_debug_info i.dbg;
   match i.desc with
   | Lend -> ()
+  | Lprologue ->
+    if !Clflags.gprofile then emit_profile();
+    let n = frame_size() - 4 in
+    if n > 0 then  begin
+      I.sub (int n) esp;
+      cfi_adjust_cfa_offset n;
+    end;
+    def_label !tailrec_entry_point
   | Lop(Imove | Ispill | Ireload) ->
       let src = i.arg.(0) and dst = i.res.(0) in
       if src.loc <> dst.loc then begin
@@ -540,7 +568,7 @@ let emit_instr fallthrough i =
           I.mov (immsym func) eax
         else begin
           external_symbols_indirect :=
-            StringSet.add func !external_symbols_indirect;
+            String.Set.add func !external_symbols_indirect;
           I.mov (mem_sym DWORD (Printf.sprintf "L%s$non_lazy_ptr"
                               (emit_symbol func))) eax
         end;
@@ -551,7 +579,7 @@ let emit_instr fallthrough i =
           emit_call func
         else begin
           external_symbols_direct :=
-            StringSet.add func !external_symbols_direct;
+            String.Set.add func !external_symbols_direct;
           I.call (sym (Printf.sprintf "L%s$stub" (emit_symbol func)))
         end
       end
@@ -602,7 +630,7 @@ let emit_instr fallthrough i =
             I.fstp (addressing addr REAL8 i 1)
           end
       end
-  | Lop(Ialloc { words = n; label_after_call_gc; }) ->
+  | Lop(Ialloc { bytes = n; label_after_call_gc; }) ->
       if !fastcode_flag then begin
         let lbl_redo = new_label() in
         def_label lbl_redo;
@@ -902,37 +930,18 @@ let emit_external_symbol_indirect s =
 
 let emit_external_symbols () =
   D.section [ "__IMPORT"; "__pointers"] None ["non_lazy_symbol_pointers" ];
-  StringSet.iter emit_external_symbol_indirect !external_symbols_indirect;
-  external_symbols_indirect := StringSet.empty;
+  String.Set.iter emit_external_symbol_indirect !external_symbols_indirect;
+  external_symbols_indirect := String.Set.empty;
   D.section [ "__IMPORT"; "__jump_table"] None
     [ "symbol_stubs"; "self_modifying_code+pure_instructions"; "5" ];
-  StringSet.iter emit_external_symbol_direct !external_symbols_direct;
-  external_symbols_direct := StringSet.empty;
+  String.Set.iter emit_external_symbol_direct !external_symbols_direct;
+  external_symbols_direct := String.Set.empty;
   if !Clflags.gprofile then begin
     _label "Lmcount$stub";
     D.indirect_symbol "mcount";
     I.hlt (); I.hlt (); I.hlt () ; I.hlt () ; I.hlt ()
   end
 
-(* Emission of the profiling prelude *)
-
-let call_mcount mcount =
-  I.push eax;
-  I.mov esp ebp;
-  I.push ecx;
-  I.push edx;
-  I.call (sym mcount);
-  I.pop edx;
-  I.pop ecx;
-  I.pop eax
-
-let emit_profile () =
-  match system with
-  | S_linux_elf | S_gnu -> call_mcount "mcount"
-  | S_bsd_elf -> call_mcount ".mcount"
-  | S_macosx -> call_mcount "Lmcount$stub"
-  | _ -> () (*unsupported yet*)
-
 (* Emission of a function declaration *)
 
 let fundecl fundecl =
@@ -956,13 +965,6 @@ let fundecl fundecl =
   D.label (emit_symbol fundecl.fun_name);
   emit_debug_info fundecl.fun_dbg;
   cfi_startproc ();
-  if !Clflags.gprofile then emit_profile();
-  let n = frame_size() - 4 in
-  if n > 0 then  begin
-    I.sub (int n) esp;
-    cfi_adjust_cfa_offset n;
-  end;
-  def_label !tailrec_entry_point;
   emit_all true fundecl.fun_body;
   List.iter emit_call_gc !call_gc_sites;
   emit_call_bound_errors ();
@@ -1071,13 +1073,13 @@ let end_assembly() =
 
   if system = S_win32 then begin
     D.comment "External functions";
-    StringSet.iter
+    String.Set.iter
       (fun s ->
-         if not (StringSet.mem s !symbols_defined) then
+         if not (String.Set.mem s !symbols_defined) then
            D.extrn (emit_symbol s) PROC)
       !symbols_used;
-    symbols_used := StringSet.empty;
-    symbols_defined := StringSet.empty;
+    symbols_used := String.Set.empty;
+    symbols_defined := String.Set.empty;
   end;
 
   let asm =
diff --git a/asmcomp/i386/proc.ml b/asmcomp/i386/proc.ml
index 7e883fc7..29290d0d 100644
--- a/asmcomp/i386/proc.ml
+++ b/asmcomp/i386/proc.ml
@@ -163,6 +163,22 @@ let loc_external_results res =
 
 let loc_exn_bucket = eax
 
+(* See "System V Application Binary Interface Intel386 Architecture
+   Processor Supplement Version 1.0"
+   (https://www.uclibc.org/docs/psABI-i386.pdf) *)
+
+let int_dwarf_reg_numbers = [| 0; 3; 1; 2; 6; 7; 5 |]
+
+let float_dwarf_reg_numbers = [| |]
+
+let dwarf_register_numbers ~reg_class =
+  match reg_class with
+  | 0 -> int_dwarf_reg_numbers
+  | 1 -> float_dwarf_reg_numbers
+  | _ -> Misc.fatal_errorf "Bad register class %d" reg_class
+
+let stack_ptr_dwarf_register_number = 4
+
 (* Volatile registers: the x87 top of FP stack is *)
 
 let reg_is_volatile = function
@@ -196,6 +212,8 @@ let destroyed_at_oper = function
 
 let destroyed_at_raise = all_phys_regs
 
+let destroyed_at_reloadretaddr = [| |]
+
 (* Maximal register pressure *)
 
 let safe_register_pressure _op = 4
diff --git a/asmcomp/linearize.ml b/asmcomp/linearize.ml
index e915bb5e..a5a39aa5 100644
--- a/asmcomp/linearize.ml
+++ b/asmcomp/linearize.ml
@@ -29,7 +29,8 @@ type instruction =
     live: Reg.Set.t }
 
 and instruction_desc =
-    Lend
+  | Lprologue
+  | Lend
   | Lop of operation
   | Lreloadretaddr
   | Lreturn
@@ -308,9 +309,20 @@ let rec linear i n =
   | Iraise k ->
       copy_instr (Lraise k) i (discard_dead_code n)
 
+let add_prologue first_insn =
+  let insn = first_insn in
+  { desc = Lprologue;
+    next = insn;
+    arg = [| |];
+    res = [| |];
+    dbg = insn.dbg;
+    live = insn.live;
+  }
+
 let fundecl f =
+  let fun_body = add_prologue (linear f.Mach.fun_body end_instr) in
   { fun_name = f.Mach.fun_name;
-    fun_body = linear f.Mach.fun_body end_instr;
+    fun_body;
     fun_fast = not (List.mem Cmm.Reduce_code_size f.Mach.fun_codegen_options);
     fun_dbg  = f.Mach.fun_dbg;
     fun_spacetime_shape = f.Mach.fun_spacetime_shape;
diff --git a/asmcomp/linearize.mli b/asmcomp/linearize.mli
index 850fbd89..e30996fe 100644
--- a/asmcomp/linearize.mli
+++ b/asmcomp/linearize.mli
@@ -26,7 +26,8 @@ type instruction =
     live: Reg.Set.t }
 
 and instruction_desc =
-    Lend
+  | Lprologue
+  | Lend
   | Lop of Mach.operation
   | Lreloadretaddr
   | Lreturn
diff --git a/asmcomp/linscan.ml b/asmcomp/linscan.ml
index 26b8b72c..d1bfbe54 100644
--- a/asmcomp/linscan.ml
+++ b/asmcomp/linscan.ml
@@ -113,7 +113,8 @@ let allocate_free_register i =
           (* Remove all overlapping registers from the register mask *)
           let remove_bound_overlapping = function
               {reg = {loc = Reg r}} as j ->
-                if (r - r0 < rn) && regmask.(r - r0) && Interval.overlap j i then
+                if (r - r0 < rn) && regmask.(r - r0)
+                   && Interval.overlap j i then
                 regmask.(r - r0) <- false
             | _ -> () in
           List.iter remove_bound_overlapping ci.ci_inactive;
diff --git a/asmcomp/liveness.ml b/asmcomp/liveness.ml
index 9791e8c5..28c5868c 100644
--- a/asmcomp/liveness.ml
+++ b/asmcomp/liveness.ml
@@ -160,7 +160,7 @@ let reset () =
   live_at_raise := Reg.Set.empty;
   live_at_exit := []
 
-let fundecl ppf f =
+let fundecl f =
   let initially_live = live f.fun_body Reg.Set.empty in
   (* Sanity check: only function parameters (and the Spacetime node hole
      register, if profiling) can be live at entrypoint *)
@@ -170,6 +170,6 @@ let fundecl ppf f =
     else Reg.Set.remove Proc.loc_spacetime_node_hole wrong_live
   in
   if not (Reg.Set.is_empty wrong_live) then begin
-    Format.fprintf ppf "%a@." Printmach.regset wrong_live;
-    Misc.fatal_error "Liveness.fundecl"
+    Misc.fatal_errorf "@[Liveness.fundecl:@\n%a@]"
+      Printmach.regset wrong_live
   end
diff --git a/asmcomp/liveness.mli b/asmcomp/liveness.mli
index 7a8fae62..37f5c170 100644
--- a/asmcomp/liveness.mli
+++ b/asmcomp/liveness.mli
@@ -16,7 +16,5 @@
 (* Liveness analysis.
    Annotate mach code with the set of regs live at each point. *)
 
-open Format
-
 val reset : unit -> unit
-val fundecl: formatter -> Mach.fundecl -> unit
+val fundecl: Mach.fundecl -> unit
diff --git a/asmcomp/mach.ml b/asmcomp/mach.ml
index 756ec61a..17a5ba7e 100644
--- a/asmcomp/mach.ml
+++ b/asmcomp/mach.ml
@@ -54,14 +54,14 @@ type operation =
   | Istackoffset of int
   | Iload of Cmm.memory_chunk * Arch.addressing_mode
   | Istore of Cmm.memory_chunk * Arch.addressing_mode * bool
-  | Ialloc of { words : int; label_after_call_gc : label option;
+  | Ialloc of { bytes : int; label_after_call_gc : label option;
         spacetime_index : int; }
   | Iintop of integer_operation
   | Iintop_imm of integer_operation * int
   | Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf
   | Ifloatofint | Iintoffloat
   | Ispecific of Arch.specific_operation
-  | Iname_for_debugger of { ident : Ident.t; which_parameter : int option;
+  | Iname_for_debugger of { ident : Backend_var.t; which_parameter : int option;
       provenance : unit option; is_assignment : bool; }
 
 type instruction =
diff --git a/asmcomp/mach.mli b/asmcomp/mach.mli
index be17ba2b..f32d8604 100644
--- a/asmcomp/mach.mli
+++ b/asmcomp/mach.mli
@@ -62,7 +62,7 @@ type operation =
   | Iload of Cmm.memory_chunk * Arch.addressing_mode
   | Istore of Cmm.memory_chunk * Arch.addressing_mode * bool
                                  (* false = initialization, true = assignment *)
-  | Ialloc of { words : int; label_after_call_gc : label option;
+  | Ialloc of { bytes : int; label_after_call_gc : label option;
       spacetime_index : int; }
     (** For Spacetime only, Ialloc instructions take one argument, being the
         pointer to the trie node for the current function. *)
@@ -71,7 +71,7 @@ type operation =
   | Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf
   | Ifloatofint | Iintoffloat
   | Ispecific of Arch.specific_operation
-  | Iname_for_debugger of { ident : Ident.t; which_parameter : int option;
+  | Iname_for_debugger of { ident : Backend_var.t; which_parameter : int option;
       provenance : unit option; is_assignment : bool; }
     (** [Iname_for_debugger] has the following semantics:
         (a) The argument register(s) is/are deemed to contain the value of the
diff --git a/asmcomp/power/arch.ml b/asmcomp/power/arch.ml
index 289f33ca..70cd75dd 100644
--- a/asmcomp/power/arch.ml
+++ b/asmcomp/power/arch.ml
@@ -47,7 +47,7 @@ type specific_operation =
     Imultaddf                           (* multiply and add *)
   | Imultsubf                           (* multiply and subtract *)
   | Ialloc_far of                       (* allocation in large functions *)
-      { words : int; label_after_call_gc : int (*Cmm.label*) option; }
+      { bytes : int; label_after_call_gc : int (*Cmm.label*) option; }
 
 (* note: we avoid introducing a dependency to Cmm since this dep
    is not detected when "make depend" is run under amd64 *)
@@ -118,5 +118,5 @@ let print_specific_operation printreg op ppf arg =
   | Imultsubf ->
       fprintf ppf "%a *f %a -f %a"
         printreg arg.(0) printreg arg.(1) printreg arg.(2)
-  | Ialloc_far { words; _ } ->
-      fprintf ppf "alloc_far %d" words
+  | Ialloc_far { bytes; _ } ->
+      fprintf ppf "alloc_far %d" bytes
diff --git a/asmcomp/power/emit.mlp b/asmcomp/power/emit.mlp
index bd0c7134..f4147c49 100644
--- a/asmcomp/power/emit.mlp
+++ b/asmcomp/power/emit.mlp
@@ -424,6 +424,21 @@ module BR = Branch_relaxation.Make (struct
     | ELF64v1 -> (fun _ b _ -> b)
     | ELF64v2 -> (fun _ _ c -> c)
 
+  let profiling_prologue_size () =
+    match abi with
+    | ELF32 -> 5
+    | ELF64v1 | ELF64v2 -> 6
+
+  let prologue_size () =
+    profiling_prologue_size ()
+      + (if frame_size () > 0 then 1 else 0)
+      + (if !contains_calls then
+           2 +
+             match abi with
+             | ELF32 -> 0
+             | ELF64v1 | ELF64v2 -> 1
+         else 0)
+
   let tocload_size() =
     if !big_toc || !Clflags.for_package <> None then 2 else 1
 
@@ -438,6 +453,7 @@ module BR = Branch_relaxation.Make (struct
 
   let instr_size = function
     | Lend -> 0
+    | Lprologue -> prologue_size ()
     | Lop(Imove | Ispill | Ireload) -> 1
     | Lop(Iconst_int n) ->
       if is_native_immediate n then 1
@@ -491,8 +507,8 @@ module BR = Branch_relaxation.Make (struct
     | Lpoptrap -> 2
     | Lraise _ -> 6
 
-  let relax_allocation ~num_words:words ~label_after_call_gc =
-    Lop (Ispecific (Ialloc_far { words; label_after_call_gc; }))
+  let relax_allocation ~num_bytes:bytes ~label_after_call_gc =
+    Lop (Ispecific (Ialloc_far { bytes; label_after_call_gc; }))
 
   (* [classify_addr], above, never identifies these instructions as needing
      relaxing.  As such, these functions should never be called. *)
@@ -501,12 +517,52 @@ module BR = Branch_relaxation.Make (struct
   let relax_intop_imm_checkbound ~bound:_ ~label_after_error:_ = assert false
 end)
 
+(* Emission of the profiling prelude *)
+
+let emit_profile () =
+  match abi with
+  | ELF32 ->
+      `	mflr    0\n`;
+      `	addi	1, 1, -16\n`;
+      `	stw	0, 4(1)\n`;
+      (* _mcount preserves the registers used for parameter passing *)
+      (* when it returns, lr contains the original return address *)
+      `	bl	{emit_symbol "_mcount"}\n`;
+      `	addi	1, 1, 16\n`
+  | ELF64v1 | ELF64v2 ->
+      `	mflr	0\n`;
+      (* save the registers used for parameter passing *)
+      `	bl	{emit_symbol "caml_before_mcount"}\n`;
+      `	bl	{emit_symbol "_mcount"}\n`;
+      `	nop\n`;
+      (* restore the registers used for parameter passing *)
+      `	bl	{emit_symbol "caml_after_mcount"}\n`;
+      `	mtlr	0\n`
+
 (* Output the assembly code for an instruction *)
 
 let emit_instr i =
     emit_debug_info i.dbg;
     match i.desc with
     | Lend -> ()
+    | Lprologue ->
+      if !Clflags.gprofile then emit_profile();
+      let n = frame_size() in
+      if n > 0 then begin
+        `	addi	1, 1, {emit_int(-n)}\n`;
+        cfi_adjust_cfa_offset n
+      end;
+      if !contains_calls then begin
+        let ra = retaddr_offset() in
+        `	mflr	0\n`;
+        `	{emit_string stg}	0, {emit_int ra}(1)\n`;
+        cfi_offset ~reg: 65 (* LR *) ~offset: (ra - n);
+        match abi with
+        | ELF32 -> ()
+        | ELF64v1 | ELF64v2 ->
+          `	std	2, {emit_int(toc_save_offset())}(1)\n`
+      end;
+      `{emit_label !tailrec_entry_point}:\n`
     | Lop(Imove | Ispill | Ireload) ->
         let src = i.arg.(0) and dst = i.res.(0) in
         if src.loc <> dst.loc then begin
@@ -714,7 +770,7 @@ let emit_instr i =
           | Single -> "stfs"
           | Double | Double_u -> "stfd" in
         emit_load_store storeinstr addr i.arg 1 i.arg.(0)
-    | Lop(Ialloc { words = n; label_after_call_gc; }) ->
+    | Lop(Ialloc { bytes = n; label_after_call_gc; }) ->
         if !call_gc_label = 0 then begin
           match label_after_call_gc with
           | None -> call_gc_label := new_label ()
@@ -726,7 +782,7 @@ let emit_instr i =
         `	bltl	{emit_label !call_gc_label}\n`;
         (* Exactly 4 instructions after the beginning of the alloc sequence *)
         record_frame i.live false Debuginfo.none
-    | Lop(Ispecific(Ialloc_far { words = n; label_after_call_gc; })) ->
+    | Lop(Ispecific(Ialloc_far { bytes = n; label_after_call_gc; })) ->
         if !call_gc_label = 0 then begin
           match label_after_call_gc with
           | None -> call_gc_label := new_label ()
@@ -967,28 +1023,6 @@ let rec emit_all i =
   | Lend -> ()
   |  _   -> emit_instr i; emit_all i.next
 
-(* Emission of the profiling prelude *)
-
-let emit_profile () =
-  match abi with
-  | ELF32 ->
-      `	mflr    0\n`;
-      `	addi	1, 1, -16\n`;
-      `	stw	0, 4(1)\n`;
-      (* _mcount preserves the registers used for parameter passing *)
-      (* when it returns, lr contains the original return address *)
-      `	bl	{emit_symbol "_mcount"}\n`;
-      `	addi	1, 1, 16\n`
-  | ELF64v1 | ELF64v2 ->
-      `	mflr	0\n`;
-      (* save the registers used for parameter passing *)
-      `	bl	{emit_symbol "caml_before_mcount"}\n`;
-      `	bl	{emit_symbol "_mcount"}\n`;
-      `	nop\n`;
-      (* restore the registers used for parameter passing *)
-      `	bl	{emit_symbol "caml_after_mcount"}\n`;
-      `	mtlr	0\n`
-
 (* Emission of a function declaration *)
 
 let fundecl fundecl =
@@ -1027,23 +1061,6 @@ let fundecl fundecl =
   end;
   emit_debug_info fundecl.fun_dbg;
   cfi_startproc();
-  if !Clflags.gprofile then emit_profile();
-  let n = frame_size() in
-  if n > 0 then begin
-    `	addi	1, 1, {emit_int(-n)}\n`;
-    cfi_adjust_cfa_offset n
-  end;
-  if !contains_calls then begin
-    let ra = retaddr_offset() in
-    `	mflr	0\n`;
-    `	{emit_string stg}	0, {emit_int ra}(1)\n`;
-    cfi_offset ~reg: 65 (* LR *) ~offset: (ra - n);
-    match abi with
-    | ELF32 -> ()
-    | ELF64v1 | ELF64v2 ->
-      `	std	2, {emit_int(toc_save_offset())}(1)\n`
-  end;
-  `{emit_label !tailrec_entry_point}:\n`;
   (* On this target, there is at most one "out of line" code block per
      function: a single "call GC" point.  It comes immediately after the
      function's body. *)
@@ -1169,7 +1186,7 @@ let end_assembly() =
   (* In profiling mode, for ELF64, emit the helper functions
      for register saving and restoring.  We put one copy of these
      functions in every generated file, instead of defining
-     them once in asmrun/power.S, so that we can call them
+     them once in runtime/power.S, so that we can call them
      without risking to save r2 in the wrong place. *)
   if ppc64 && !Clflags.gprofile then begin
     let save_area = reserved_stack_space + (if abi = ELF64v1 then 8*8 else 0) in
diff --git a/asmcomp/power/proc.ml b/asmcomp/power/proc.ml
index 670e8495..8560d0f9 100644
--- a/asmcomp/power/proc.ml
+++ b/asmcomp/power/proc.ml
@@ -257,6 +257,43 @@ let loc_external_results res =
 
 let loc_exn_bucket = phys_reg 0
 
+(* For ELF32 see:
+   "System V Application Binary Interface PowerPC Processor Supplement"
+   http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf
+
+   For ELF64v1 see:
+   "64-bit PowerPC ELF Application Binary Interface Supplement 1.9"
+   http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html
+
+   For ELF64v2 see:
+   "64-Bit ELF V2 ABI Specification -- Power Architecture"
+   http://openpowerfoundation.org/wp-content/uploads/resources/leabi/
+     content/dbdoclet.50655239___RefHeading___Toc377640569.html
+
+   All of these specifications seem to agree on the numberings we need.
+*)
+
+let int_dwarf_reg_numbers =
+  [| 3; 4; 5; 6; 7; 8; 9; 10;
+     14; 15; 16; 17; 18; 19; 20; 21;
+     22; 23; 24; 25; 26; 27; 28;
+  |]
+
+let float_dwarf_reg_numbers =
+  [| 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;
+  |]
+
+let dwarf_register_numbers ~reg_class =
+  match reg_class with
+  | 0 -> int_dwarf_reg_numbers
+  | 1 -> float_dwarf_reg_numbers
+  | _ -> Misc.fatal_errorf "Bad register class %d" reg_class
+
+let stack_ptr_dwarf_register_number = 1
+
 (* Volatile registers: none *)
 
 let regs_are_volatile _rs = false
@@ -276,6 +313,8 @@ let destroyed_at_oper = function
 
 let destroyed_at_raise = all_phys_regs
 
+let destroyed_at_reloadretaddr = [| phys_reg 11 |]
+
 (* Maximal register pressure *)
 
 let safe_register_pressure = function
@@ -305,7 +344,8 @@ let contains_calls = ref false
 (* Calling the assembler *)
 
 let assemble_file infile outfile =
-  Ccomp.command (Config.asm ^ " -o " ^
-                 Filename.quote outfile ^ " " ^ Filename.quote infile)
+  Ccomp.command (Config.asm ^ " " ^
+                 (String.concat " " (Misc.debug_prefix_map_flags ())) ^
+                 " -o " ^ Filename.quote outfile ^ " " ^ Filename.quote infile)
 
 let init () = ()
diff --git a/asmcomp/printclambda.ml b/asmcomp/printclambda.ml
index c353b3df..954fecf8 100644
--- a/asmcomp/printclambda.ml
+++ b/asmcomp/printclambda.ml
@@ -18,6 +18,9 @@ open Format
 open Asttypes
 open Clambda
 
+module V = Backend_var
+module VP = Backend_var.With_provenance
+
 let mutable_flag = function
   | Mutable-> "[mut]"
   | Immutable -> ""
@@ -49,17 +52,43 @@ let rec structured_constant ppf = function
       fprintf ppf ")"
   | Uconst_string s -> fprintf ppf "%S" s
   | Uconst_closure(clos, sym, fv) ->
-      let idents ppf =
-        List.iter (fprintf ppf "@ %a" Ident.print)in
-      let one_fun ppf f =
-        fprintf ppf "(fun@ %s@ %d@ @[<2>%a@]@ @[<2>%a@])"
-          f.label f.arity idents f.params lam f.body in
       let funs ppf =
         List.iter (fprintf ppf "@ %a" one_fun) in
       let sconsts ppf scl =
         List.iter (fun sc -> fprintf ppf "@ %a" uconstant sc) scl in
       fprintf ppf "@[<2>(const_closure%a %s@ %a)@]" funs clos sym sconsts fv
 
+and one_fun ppf f =
+  let idents ppf =
+    List.iter
+      (fun (x, k) ->
+         fprintf ppf "@ %a%a"
+           VP.print x
+           Printlambda.value_kind k
+      )
+  in
+  fprintf ppf "(fun@ %s%s@ %d@ @[<2>%a@]@ @[<2>%a@])"
+    f.label (value_kind f.return) f.arity idents f.params lam f.body
+
+and phantom_defining_expr ppf = function
+  | Uphantom_const const -> uconstant ppf const
+  | Uphantom_var var -> Ident.print ppf var
+  | Uphantom_offset_var { var; offset_in_words; } ->
+    Format.fprintf ppf "%a+(%d)" Backend_var.print var offset_in_words
+  | Uphantom_read_field { var; field; } ->
+    Format.fprintf ppf "%a[%d]" Backend_var.print var field
+  | Uphantom_read_symbol_field { sym; field; } ->
+    Format.fprintf ppf "%s[%d]" sym field
+  | Uphantom_block { tag; fields; } ->
+    Format.fprintf ppf "[%d: " tag;
+    List.iter (fun field ->
+        Format.fprintf ppf "%a; " Backend_var.print field)
+      fields;
+    Format.fprintf ppf "]"
+
+and phantom_defining_expr_opt ppf = function
+  | None -> Format.fprintf ppf "DEAD"
+  | Some expr -> phantom_defining_expr ppf expr
 
 and uconstant ppf = function
   | Uconst_ref (s, Some c) ->
@@ -70,7 +99,7 @@ and uconstant ppf = function
 
 and lam ppf = function
   | Uvar id ->
-      Ident.print ppf id
+      V.print ppf id
   | Uconst c -> uconstant ppf c
   | Udirect_apply(f, largs, _) ->
       let lams ppf largs =
@@ -81,13 +110,8 @@ and lam ppf = function
         List.iter (fun l -> fprintf ppf "@ %a" lam l) largs in
       fprintf ppf "@[<2>(apply@ %a%a)@]" lam lfun lams largs
   | Uclosure(clos, fv) ->
-      let idents ppf =
-        List.iter (fprintf ppf "@ %a" Ident.print)in
-      let one_fun ppf f =
-        fprintf ppf "@[<2>(fun@ %s@ %d @[<2>%a@]@ @[<2>%a@]@])"
-          f.label f.arity idents f.params lam f.body in
       let funs ppf =
-        List.iter (fprintf ppf "@ %a" one_fun) in
+        List.iter (fprintf ppf "@ @[<2>%a@]" one_fun) in
       let lams ppf =
         List.iter (fprintf ppf "@ %a" lam) in
       fprintf ppf "@[<2>(closure@ %a %a)@]" funs clos lams fv
@@ -96,11 +120,26 @@ and lam ppf = function
       let rec letbody ul = match ul with
         | Ulet(mut, kind, id, arg, body) ->
             fprintf ppf "@ @[<2>%a%s%s@ %a@]"
-              Ident.print id (mutable_flag mut) (value_kind kind) lam arg;
+              VP.print id
+              (mutable_flag mut) (value_kind kind) lam arg;
             letbody body
         | _ -> ul in
       fprintf ppf "@[<2>(let@ @[(@[<2>%a%s%s@ %a@]"
-        Ident.print id (mutable_flag mut) (value_kind kind) lam arg;
+        VP.print id (mutable_flag mut)
+          (value_kind kind) lam arg;
+      let expr = letbody body in
+      fprintf ppf ")@]@ %a)@]" lam expr
+  | Uphantom_let (id, defining_expr, body) ->
+      let rec letbody ul = match ul with
+        | Uphantom_let (id, defining_expr, body) ->
+            fprintf ppf "@ @[<2>%a@ %a@]"
+              Backend_var.With_provenance.print id
+              phantom_defining_expr_opt defining_expr;
+            letbody body
+        | _ -> ul in
+      fprintf ppf "@[<2>(phantom_let@ @[(@[<2>%a@ %a@]"
+        Backend_var.With_provenance.print id
+        phantom_defining_expr_opt defining_expr;
       let expr = letbody body in
       fprintf ppf ")@]@ %a)@]" lam expr
   | Uletrec(id_arg_list, body) ->
@@ -109,7 +148,9 @@ and lam ppf = function
         List.iter
           (fun (id, l) ->
             if !spc then fprintf ppf "@ " else spc := true;
-            fprintf ppf "@[<2>%a@ %a@]" Ident.print id lam l)
+            fprintf ppf "@[<2>%a@ %a@]"
+              VP.print id
+              lam l)
           id_arg_list in
       fprintf ppf
         "@[<2>(letrec@ (@[%a@])@ %a)@]" bindings id_arg_list lam body
@@ -157,17 +198,20 @@ and lam ppf = function
   | Ucatch(i, vars, lbody, lhandler) ->
       fprintf ppf "@[<2>(catch@ %a@;<1 -1>with (%d%a)@ %a)@]"
         lam lbody i
-        (fun ppf vars -> match vars with
-          | [] -> ()
-          | _ ->
-              List.iter
-                (fun x -> fprintf ppf " %a" Ident.print x)
-                vars)
+        (fun ppf vars ->
+           List.iter
+             (fun (x, k) ->
+                fprintf ppf " %a%a"
+                 VP.print x
+                 Printlambda.value_kind k
+             )
+             vars
+        )
         vars
         lam lhandler
   | Utrywith(lbody, param, lhandler) ->
       fprintf ppf "@[<2>(try@ %a@;<1 -1>with %a@ %a)@]"
-        lam lbody Ident.print param lam lhandler
+        lam lbody VP.print param lam lhandler
   | Uifthenelse(lcond, lif, lelse) ->
       fprintf ppf "@[<2>(if@ %a@ %a@ %a)@]" lam lcond lam lif lam lelse
   | Usequence(l1, l2) ->
@@ -176,11 +220,11 @@ and lam ppf = function
       fprintf ppf "@[<2>(while@ %a@ %a)@]" lam lcond lam lbody
   | Ufor(param, lo, hi, dir, body) ->
       fprintf ppf "@[<2>(for %a@ %a@ %s@ %a@ %a)@]"
-       Ident.print param lam lo
+       VP.print param lam lo
        (match dir with Upto -> "to" | Downto -> "downto")
        lam hi lam body
   | Uassign(id, expr) ->
-      fprintf ppf "@[<2>(assign@ %a@ %a)@]" Ident.print id lam expr
+      fprintf ppf "@[<2>(assign@ %a@ %a)@]" V.print id lam expr
   | Usend (k, met, obj, largs, _) ->
       let args ppf largs =
         List.iter (fun l -> fprintf ppf "@ %a" lam l) largs in
diff --git a/asmcomp/printclambda.mli b/asmcomp/printclambda.mli
index 3b1ff58f..121667e2 100644
--- a/asmcomp/printclambda.mli
+++ b/asmcomp/printclambda.mli
@@ -19,3 +19,8 @@ open Format
 val clambda: formatter -> ulambda -> unit
 val approx: formatter -> value_approximation -> unit
 val structured_constant: formatter -> ustructured_constant -> unit
+
+val phantom_defining_expr_opt
+   : formatter
+  -> uphantom_defining_expr option
+  -> unit
diff --git a/asmcomp/printcmm.ml b/asmcomp/printcmm.ml
index 51682690..c485eec1 100644
--- a/asmcomp/printcmm.ml
+++ b/asmcomp/printcmm.ml
@@ -18,6 +18,9 @@
 open Format
 open Cmm
 
+module V = Backend_var
+module VP = Backend_var.With_provenance
+
 let rec_flag ppf = function
   | Nonrecursive -> ()
   | Recursive -> fprintf ppf " rec"
@@ -73,6 +76,29 @@ let raise_kind fmt = function
   | Raise_withtrace -> Format.fprintf fmt "raise_withtrace"
   | Raise_notrace -> Format.fprintf fmt "raise_notrace"
 
+let phantom_defining_expr ppf defining_expr =
+  match defining_expr with
+  | Cphantom_const_int i -> Targetint.print ppf i
+  | Cphantom_const_symbol sym -> Format.pp_print_string ppf sym
+  | Cphantom_var var -> V.print ppf var
+  | Cphantom_offset_var { var; offset_in_words; } ->
+    Format.fprintf ppf "%a+(%d)" V.print var offset_in_words
+  | Cphantom_read_field { var; field; } ->
+    Format.fprintf ppf "%a[%d]" V.print var field
+  | Cphantom_read_symbol_field { sym; field; } ->
+    Format.fprintf ppf "%s[%d]" sym field
+  | Cphantom_block { tag; fields; } ->
+    Format.fprintf ppf "[%d: " tag;
+    List.iter (fun field ->
+        Format.fprintf ppf "%a; " V.print field)
+      fields;
+    Format.fprintf ppf "]"
+
+let phantom_defining_expr_opt ppf defining_expr =
+  match defining_expr with
+  | None -> Format.pp_print_string ppf "()"
+  | Some defining_expr -> phantom_defining_expr ppf defining_expr
+
 let operation d = function
   | Capply _ty -> "app" ^ Debuginfo.to_string d
   | Cextcall(lbl, _ty, _alloc, _) ->
@@ -127,10 +153,11 @@ let rec expr ppf = function
   | Cconst_symbol s -> fprintf ppf "\"%s\"" s
   | Cconst_pointer n -> fprintf ppf "%ia" n
   | Cconst_natpointer n -> fprintf ppf "%sa" (Nativeint.to_string n)
-  | Cvar id -> Ident.print ppf id
+  | Cvar id -> V.print ppf id
   | Clet(id, def, (Clet(_, _, _) as body)) ->
       let print_binding id ppf def =
-        fprintf ppf "@[<2>%a@ %a@]" Ident.print id expr def in
+        fprintf ppf "@[<2>%a@ %a@]"
+          VP.print id expr def in
       let rec in_part ppf = function
         | Clet(id, def, body) ->
             fprintf ppf "@ %a" (print_binding id) def;
@@ -142,9 +169,28 @@ let rec expr ppf = function
   | Clet(id, def, body) ->
      fprintf ppf
       "@[<2>(let@ @[<2>%a@ %a@]@ %a)@]"
-      Ident.print id expr def sequence body
+      VP.print id expr def sequence body
+  | Cphantom_let(var, def, (Cphantom_let(_, _, _) as body)) ->
+      let print_binding var ppf def =
+        fprintf ppf "@[<2>%a@ %a@]" VP.print var
+          phantom_defining_expr_opt def
+      in
+      let rec in_part ppf = function
+        | Cphantom_let(var, def, body) ->
+            fprintf ppf "@ %a" (print_binding var) def;
+            in_part ppf body
+        | exp -> exp in
+      fprintf ppf "@[<2>(let?@ @[<1>(%a" (print_binding var) def;
+      let exp = in_part ppf body in
+      fprintf ppf ")@]@ %a)@]" sequence exp
+  | Cphantom_let(var, def, body) ->
+    fprintf ppf
+      "@[<2>(let?@ @[<2>%a@ %a@]@ %a)@]"
+      VP.print var
+      phantom_defining_expr_opt def
+      sequence body
   | Cassign(id, exp) ->
-      fprintf ppf "@[<2>(assign @[<2>%a@ %a@])@]" Ident.print id expr exp
+      fprintf ppf "@[<2>(assign @[<2>%a@ %a@])@]" V.print id expr exp
   | Ctuple el ->
       let tuple ppf el =
        let first = ref true in
@@ -185,7 +231,9 @@ let rec expr ppf = function
           i
           (fun ppf ids ->
              List.iter
-               (fun id -> fprintf ppf " %a" Ident.print id)
+               (fun (id, ty) ->
+                 fprintf ppf "@ %a: %a"
+                   VP.print id machtype ty)
                ids) ids
           sequence e2
       in
@@ -203,7 +251,7 @@ let rec expr ppf = function
       fprintf ppf ")@]"
   | Ctrywith(e1, id, e2) ->
       fprintf ppf "@[<2>(try@ %a@;<1 -2>with@ %a@ %a)@]"
-             sequence e1 Ident.print id sequence e2
+             sequence e1 VP.print id sequence e2
 
 and sequence ppf = function
   | Csequence(e1, e2) -> fprintf ppf "%a@ %a" sequence e1 sequence e2
@@ -217,7 +265,7 @@ let fundecl ppf f =
     List.iter
      (fun (id, ty) ->
        if !first then first := false else fprintf ppf "@ ";
-       fprintf ppf "%a: %a" Ident.print id machtype ty)
+       fprintf ppf "%a: %a" VP.print id machtype ty)
      cases in
   fprintf ppf "@[<1>(function%s %s@;<1 4>@[<1>(%a)@]@ @[%a@])@]@."
          (Debuginfo.to_string f.fun_dbg) f.fun_name
diff --git a/asmcomp/printlinear.ml b/asmcomp/printlinear.ml
index faf26d2d..69557687 100644
--- a/asmcomp/printlinear.ml
+++ b/asmcomp/printlinear.ml
@@ -26,6 +26,8 @@ let label ppf l =
 let instr ppf i =
   begin match i.desc with
   | Lend -> ()
+  | Lprologue ->
+      fprintf ppf "prologue"
   | Lop op ->
       begin match op with
       | Ialloc _ | Icall_ind _ | Icall_imm _ | Iextcall _ ->
diff --git a/asmcomp/printmach.ml b/asmcomp/printmach.ml
index 57b111ce..6ef11ce3 100644
--- a/asmcomp/printmach.ml
+++ b/asmcomp/printmach.ml
@@ -21,6 +21,8 @@ open Reg
 open Mach
 open Interval
 
+module V = Backend_var
+
 let reg ppf r =
   if not (Reg.anonymous r) then
     fprintf ppf "%s" (Reg.name r)
@@ -95,7 +97,7 @@ let intop = function
         begin
           match label_after_error with
           | None -> ""
-          | Some lbl -> string_of_int lbl
+          | Some lbl -> Int.to_string lbl
         end
         spacetime_index
 
@@ -141,7 +143,7 @@ let operation op arg ppf res =
        (Array.sub arg 1 (Array.length arg - 1))
        reg arg.(0)
        (if is_assign then "(assign)" else "(init)")
-  | Ialloc { words = n; _ } ->
+  | Ialloc { bytes = n; _ } ->
     fprintf ppf "alloc %i" n;
     if Config.spacetime then begin
       fprintf ppf "(spacetime node = %a)" reg arg.(0)
@@ -158,7 +160,7 @@ let operation op arg ppf res =
   | Iintoffloat -> fprintf ppf "intoffloat %a" reg arg.(0)
   | Iname_for_debugger { ident; which_parameter; } ->
     fprintf ppf "name_for_debugger %a%s=%a"
-      Ident.print ident
+      V.print ident
       (match which_parameter with
         | None -> ""
         | Some index -> sprintf "[P%d]" index)
diff --git a/asmcomp/proc.mli b/asmcomp/proc.mli
index 23f503fa..2074d619 100644
--- a/asmcomp/proc.mli
+++ b/asmcomp/proc.mli
@@ -56,6 +56,7 @@ val max_register_pressure: Mach.operation -> int array
 (* Registers destroyed by operations *)
 val destroyed_at_oper: Mach.instruction_desc -> Reg.t array
 val destroyed_at_raise: Reg.t array
+val destroyed_at_reloadretaddr : Reg.t array
 
 (* Volatile registers: those that change value when read *)
 val regs_are_volatile: Reg.t array -> bool
@@ -67,6 +68,15 @@ val op_is_pure: Mach.operation -> bool
 val num_stack_slots: int array
 val contains_calls: bool ref
 
+(** For a given register class, the DWARF register numbering for that class.
+    Given an allocated register with location [Reg n] and class [reg_class], the
+    returned array contains the corresponding DWARF register number at index
+    [n - first_available_register.(reg_class)]. *)
+val dwarf_register_numbers : reg_class:int -> int array
+
+(** The DWARF register number corresponding to the stack pointer. *)
+val stack_ptr_dwarf_register_number : int
+
 (* Calling the assembler *)
 val assemble_file: string -> string -> int
 
diff --git a/asmcomp/reg.ml b/asmcomp/reg.ml
index 441a6d38..72b68dab 100644
--- a/asmcomp/reg.ml
+++ b/asmcomp/reg.ml
@@ -15,20 +15,22 @@
 
 open Cmm
 
+module V = Backend_var
+
 module Raw_name = struct
   type t =
     | Anon
     | R
-    | Ident of Ident.t
+    | Var of V.t
 
-  let create_from_ident ident = Ident ident
+  let create_from_var var = Var var
 
   let to_string t =
     match t with
     | Anon -> None
     | R -> Some "R"
-    | Ident ident ->
-      let name = Ident.name ident in
+    | Var var ->
+      let name = V.name var in
       if String.length name <= 0 then None else Some name
 end
 
@@ -115,7 +117,7 @@ let name t =
     in
     match t.part with
     | None -> with_spilled
-    | Some part -> with_spilled ^ "#" ^ string_of_int part
+    | Some part -> with_spilled ^ "#" ^ Int.to_string part
 
 let first_virtual_reg_stamp = ref (-1)
 
diff --git a/asmcomp/reg.mli b/asmcomp/reg.mli
index d918f07e..cd376394 100644
--- a/asmcomp/reg.mli
+++ b/asmcomp/reg.mli
@@ -17,7 +17,7 @@
 
 module Raw_name : sig
   type t
-  val create_from_ident : Ident.t -> t
+  val create_from_var : Backend_var.t -> t
 end
 
 type t =
diff --git a/asmcomp/s390x/emit.mlp b/asmcomp/s390x/emit.mlp
index cef1022a..f422ad29 100644
--- a/asmcomp/s390x/emit.mlp
+++ b/asmcomp/s390x/emit.mlp
@@ -307,6 +307,12 @@ let emit_instr i =
     emit_debug_info i.dbg;
     match i.desc with
       Lend -> ()
+    | Lprologue ->
+      let n = frame_size() in
+      emit_stack_adjust n;
+      if !contains_calls then
+        `	stg	%r14, {emit_int(n - size_addr)}(%r15)\n`;
+      `{emit_label !tailrec_entry_point}:\n`;
     | Lop(Imove | Ispill | Ireload) ->
         let src = i.arg.(0) and dst = i.res.(0) in
         if src.loc <> dst.loc then begin
@@ -412,7 +418,7 @@ let emit_instr i =
           | Double | Double_u -> "stdy" in
         emit_load_store storeinstr addr i.arg 1 i.arg.(0)
 
-    | Lop(Ialloc { words = n; label_after_call_gc; }) ->
+    | Lop(Ialloc { bytes = n; label_after_call_gc; }) ->
         let lbl_redo = new_label() in
         let lbl_call_gc = new_label() in
         let lbl_frame =
@@ -654,11 +660,6 @@ let fundecl fundecl =
   emit_string code_space;
   `	.align	8\n`;
   `{emit_symbol fundecl.fun_name}:\n`;
-  let n = frame_size() in
-  emit_stack_adjust n;
-  if !contains_calls then
-    `	stg	%r14, {emit_int(n - size_addr)}(%r15)\n`;
-  `{emit_label !tailrec_entry_point}:\n`;
   emit_all fundecl.fun_body;
   (* Emit the glue code to call the GC *)
   List.iter emit_call_gc !call_gc_sites;
diff --git a/asmcomp/s390x/proc.ml b/asmcomp/s390x/proc.ml
index 78f13bff..9b359b19 100644
--- a/asmcomp/s390x/proc.ml
+++ b/asmcomp/s390x/proc.ml
@@ -161,6 +161,25 @@ let loc_external_results res =
 
 let loc_exn_bucket = phys_reg 0
 
+(* See "S/390 ELF Application Binary Interface Supplement"
+   (http://refspecs.linuxfoundation.org/ELF/zSeries/lzsabi0_s390/x1542.html)
+*)
+
+let int_dwarf_reg_numbers = [| 2; 3; 4; 5; 6; 7; 8; 9; 12; |]
+
+let float_dwarf_reg_numbers =
+  [| 16; 17; 18; 19; 20; 21; 22; 23;
+     24; 28; 25; 29; 26; 30; 27; 31;
+  |]
+
+let dwarf_register_numbers ~reg_class =
+  match reg_class with
+  | 0 -> int_dwarf_reg_numbers
+  | 1 -> float_dwarf_reg_numbers
+  | _ -> Misc.fatal_errorf "Bad register class %d" reg_class
+
+let stack_ptr_dwarf_register_number = 15
+
 (* Volatile registers: none *)
 
 let regs_are_volatile _rs = false
@@ -180,6 +199,10 @@ let destroyed_at_oper = function
 
 let destroyed_at_raise = all_phys_regs
 
+(* %r14 is destroyed at [Lreloadretaddr], but %r14 is not used for register
+   allocation, and thus does not need to (and indeed cannot) occur here. *)
+let destroyed_at_reloadretaddr = [| |]
+
 (* Maximal register pressure *)
 
 let safe_register_pressure = function
@@ -208,7 +231,8 @@ let contains_calls = ref false
 (* Calling the assembler *)
 
 let assemble_file infile outfile =
-  Ccomp.command (Config.asm ^ " -o " ^
-                 Filename.quote outfile ^ " " ^ Filename.quote infile)
+  Ccomp.command (Config.asm ^ " " ^
+                 (String.concat " " (Misc.debug_prefix_map_flags ())) ^
+                 " -o " ^ Filename.quote outfile ^ " " ^ Filename.quote infile)
 
 let init () = ()
diff --git a/asmcomp/selectgen.ml b/asmcomp/selectgen.ml
index d0520ba9..302115c7 100644
--- a/asmcomp/selectgen.ml
+++ b/asmcomp/selectgen.ml
@@ -16,33 +16,39 @@
 (* Selection of pseudo-instructions, assignment of pseudo-registers,
    sequentialization. *)
 
-open Misc
 open Cmm
 open Reg
 open Mach
 
+module Int = Numbers.Int
+module V = Backend_var
+module VP = Backend_var.With_provenance
+
 type environment =
-  { vars : (Ident.t, Reg.t array) Tbl.t;
-    static_exceptions : (int, Reg.t array list) Tbl.t;
+  { vars : (Reg.t array * Backend_var.Provenance.t option) V.Map.t;
+    static_exceptions : Reg.t array list Int.Map.t;
     (** Which registers must be populated when jumping to the given
         handler. *)
   }
 
-let env_add id v env =
-  { env with vars = Tbl.add id v env.vars }
+let env_add var regs env =
+  let provenance = VP.provenance var in
+  let var = VP.var var in
+  { env with vars = V.Map.add var (regs, provenance) env.vars }
 
 let env_add_static_exception id v env =
-  { env with static_exceptions = Tbl.add id v env.static_exceptions }
+  { env with static_exceptions = Int.Map.add id v env.static_exceptions }
 
 let env_find id env =
-  Tbl.find id env.vars
+  let regs, _provenance = V.Map.find id env.vars in
+  regs
 
 let env_find_static_exception id env =
-  Tbl.find id env.static_exceptions
+  Int.Map.find id env.static_exceptions
 
 let env_empty = {
-  vars = Tbl.empty;
-  static_exceptions = Tbl.empty;
+  vars = V.Map.empty;
+  static_exceptions = Int.Map.empty;
 }
 
 (* Infer the type of the result of an operation *)
@@ -81,26 +87,26 @@ let size_expr (env:environment) exp =
     | Cblockheader _ -> Arch.size_int
     | Cvar id ->
         begin try
-          Tbl.find id localenv
+          V.Map.find id localenv
         with Not_found ->
         try
           let regs = env_find id env in
           size_machtype (Array.map (fun r -> r.typ) regs)
         with Not_found ->
-          fatal_error("Selection.size_expr: unbound var " ^
-                      Ident.unique_name id)
+          Misc.fatal_error("Selection.size_expr: unbound var " ^
+                           V.unique_name id)
         end
     | Ctuple el ->
         List.fold_right (fun e sz -> size localenv e + sz) el 0
     | Cop(op, _, _) ->
         size_machtype(oper_result_type op)
     | Clet(id, arg, body) ->
-        size (Tbl.add id (size localenv arg) localenv) body
+        size (V.Map.add (VP.var id) (size localenv arg) localenv) body
     | Csequence(_e1, e2) ->
         size localenv e2
     | _ ->
-        fatal_error "Selection.size_expr"
-  in size Tbl.empty exp
+        Misc.fatal_error "Selection.size_expr"
+  in size V.Map.empty exp
 
 (* Swap the two arguments of an integer comparison *)
 
@@ -120,11 +126,12 @@ let all_regs_anonymous rv =
     false
 
 let name_regs id rv =
+  let id = VP.var id in
   if Array.length rv = 1 then
-    rv.(0).raw_name <- Raw_name.create_from_ident id
+    rv.(0).raw_name <- Raw_name.create_from_var id
   else
     for i = 0 to Array.length rv - 1 do
-      rv.(i).raw_name <- Raw_name.create_from_ident id;
+      rv.(i).raw_name <- Raw_name.create_from_var id;
       rv.(i).part <- Some i
     done
 
@@ -290,6 +297,7 @@ method is_simple_expr = function
   | Cvar _ -> true
   | Ctuple el -> List.for_all self#is_simple_expr el
   | Clet(_id, arg, body) -> self#is_simple_expr arg && self#is_simple_expr body
+  | Cphantom_let(_var, _defining_expr, body) -> self#is_simple_expr body
   | Csequence(e1, e2) -> self#is_simple_expr e1 && self#is_simple_expr e2
   | Cop(op, args, _) ->
       begin match op with
@@ -325,6 +333,7 @@ method effects_of exp =
   | Ctuple el -> EC.join_list_map el self#effects_of
   | Clet (_id, arg, body) ->
     EC.join (self#effects_of arg) (self#effects_of body)
+  | Cphantom_let (_var, _defining_expr, body) -> self#effects_of body
   | Csequence (e1, e2) ->
     EC.join (self#effects_of e1) (self#effects_of e2)
   | Cifthenelse (cond, ifso, ifnot) ->
@@ -395,8 +404,8 @@ method mark_instr = function
 
 (* Default instruction selection for operators *)
 
-method select_allocation words =
-  Ialloc { words; spacetime_index = 0; label_after_call_gc = None; }
+method select_allocation bytes =
+  Ialloc { bytes; spacetime_index = 0; label_after_call_gc = None; }
 method select_allocation_args _env = [| |]
 
 method select_checkbound () =
@@ -465,7 +474,7 @@ method select_operation op args _dbg =
     let extra_args = self#select_checkbound_extra_args () in
     let op = self#select_checkbound () in
     self#select_arith op (args @ extra_args)
-  | _ -> fatal_error "Selection.select_oper"
+  | _ -> Misc.fatal_error "Selection.select_oper"
 
 method private select_arith_comm op = function
     [arg; Cconst_int n] when self#is_immediate n ->
@@ -583,8 +592,8 @@ method adjust_type src dst =
     match ts, td with
     | Val, Int -> dst.typ <- Val
     | Int, Val -> ()
-    | _, _ -> fatal_error("Selection.adjust_type: bad assignment to "
-                                                           ^ Reg.name dst)
+    | _, _ -> Misc.fatal_error("Selection.adjust_type: bad assignment to "
+                               ^ Reg.name dst)
 
 method adjust_types src dst =
   for i = 0 to min (Array.length src) (Array.length dst) - 1 do
@@ -655,19 +664,21 @@ method emit_expr (env:environment) exp =
       begin try
         Some(env_find v env)
       with Not_found ->
-        fatal_error("Selection.emit_expr: unbound var " ^ Ident.unique_name v)
+        Misc.fatal_error("Selection.emit_expr: unbound var " ^ V.unique_name v)
       end
   | Clet(v, e1, e2) ->
       begin match self#emit_expr env e1 with
         None -> None
       | Some r1 -> self#emit_expr (self#bind_let env v r1) e2
       end
+  | Cphantom_let (_var, _defining_expr, body) ->
+      self#emit_expr env body
   | Cassign(v, e1) ->
       let rv =
         try
           env_find v env
         with Not_found ->
-          fatal_error ("Selection.emit_expr: unbound var " ^ Ident.name v) in
+          Misc.fatal_error ("Selection.emit_expr: unbound var " ^ V.name v) in
       begin match self#emit_expr env e1 with
         None -> None
       | Some r1 -> self#adjust_types r1 rv; self#insert_moves r1 rv; Some [||]
@@ -738,12 +749,11 @@ method emit_expr (env:environment) exp =
                   loc_arg (Proc.loc_external_results rd) in
               self#insert_move_results loc_res rd stack_ofs;
               Some rd
-          | Ialloc { words; spacetime_index; label_after_call_gc; } ->
-              assert (words <= Config.max_young_wosize);
+          | Ialloc { bytes = _; spacetime_index; label_after_call_gc; } ->
               let rd = self#regs_for typ_val in
-              let size = size_expr env (Ctuple new_args) in
+              let bytes = size_expr env (Ctuple new_args) in
               let op =
-                Ialloc { words = size; spacetime_index; label_after_call_gc; }
+                Ialloc { bytes; spacetime_index; label_after_call_gc; }
               in
               let args = self#select_allocation_args env in
               self#insert_debug (Iop op) dbg args rd;
@@ -793,9 +803,8 @@ method emit_expr (env:environment) exp =
         List.map (fun (nfail, ids, e2) ->
             let rs =
               List.map
-                (* CR-someday mshinwell: consider how we can do better than
-                   [typ_val] when appropriate. *)
-                (fun id -> let r = self#regs_for typ_val in name_regs id r; r)
+                (fun (id, typ) ->
+                  let r = self#regs_for typ in name_regs id r; r)
                 ids in
             (nfail, ids, rs, e2))
           handlers
@@ -812,7 +821,7 @@ method emit_expr (env:environment) exp =
       let translate_one_handler (nfail, ids, rs, e2) =
         assert(List.length ids = List.length rs);
         let new_env =
-          List.fold_left (fun env (id, r) -> env_add id r env)
+          List.fold_left (fun env ((id, _typ), r) -> env_add id r env)
             env (List.combine ids rs)
         in
         let (r, s) = self#emit_sequence new_env e2 in
@@ -832,14 +841,13 @@ method emit_expr (env:environment) exp =
           let dest_args =
             try env_find_static_exception nfail env
             with Not_found ->
-              fatal_error ("Selection.emit_expr: unboun label "^
-                           string_of_int nfail)
+              Misc.fatal_error ("Selection.emit_expr: unbound label "^
+                                Stdlib.Int.to_string nfail)
           in
           (* Intermediate registers to handle cases where some
              registers from src are present in dest *)
           let tmp_regs = Reg.createv_like src in
-          (* Ccatch registers are created with type Val. They must not
-             contain out of heap pointers *)
+          (* Ccatch registers must not contain out of heap pointers *)
           Array.iter (fun reg -> assert(reg.typ <> Addr)) src;
           self#insert_moves src tmp_regs ;
           self#insert_moves tmp_regs (Array.concat dest_args) ;
@@ -928,15 +936,15 @@ method private emit_parts (env:environment) ~effects_after exp =
           Some (Ctuple [], env)
         else begin
           (* The normal case *)
-          let id = Ident.create "bind" in
+          let id = V.create_local "bind" in
           if all_regs_anonymous r then
             (* r is an anonymous, unshared register; use it directly *)
-            Some (Cvar id, env_add id r env)
+            Some (Cvar id, env_add (VP.create id) r env)
           else begin
             (* Introduce a fresh temp to hold the result *)
             let tmp = Reg.createv_like r in
             self#insert_moves r tmp;
-            Some (Cvar id, env_add id tmp env)
+            Some (Cvar id, env_add (VP.create id) tmp env)
           end
         end
   end
@@ -1032,6 +1040,8 @@ method emit_tail (env:environment) exp =
         None -> ()
       | Some r1 -> self#emit_tail (self#bind_let env v r1) e2
       end
+  | Cphantom_let (_var, _defining_expr, body) ->
+      self#emit_tail env body
   | Cop((Capply ty) as op, args, dbg) ->
       begin match self#emit_parts_list env args with
         None -> ()
@@ -1096,7 +1106,7 @@ method emit_tail (env:environment) exp =
                 self#insert(Iop(Istackoffset(-stack_ofs))) [||] [||];
                 self#insert Ireturn loc_res [||]
               end
-          | _ -> fatal_error "Selection.emit_tail"
+          | _ -> Misc.fatal_error "Selection.emit_tail"
       end
   | Csequence(e1, e2) ->
       begin match self#emit_expr env e1 with
@@ -1127,7 +1137,8 @@ method emit_tail (env:environment) exp =
         List.map (fun (nfail, ids, e2) ->
             let rs =
               List.map
-                (fun id -> let r = self#regs_for typ_val in name_regs id r; r)
+                (fun (id, typ) ->
+                  let r = self#regs_for typ in name_regs id r; r)
                 ids in
             (nfail, ids, rs, e2))
           handlers in
@@ -1140,7 +1151,7 @@ method emit_tail (env:environment) exp =
         assert(List.length ids = List.length rs);
         let new_env =
           List.fold_left
-            (fun env (id,r) -> env_add id r env)
+            (fun env ((id, _typ),r) -> env_add id r env)
             env (List.combine ids rs) in
         nfail, self#emit_tail_sequence new_env e2
       in
@@ -1200,8 +1211,8 @@ method emit_fundecl f =
     if not Config.spacetime then None, env
     else begin
       let reg = self#regs_for typ_int in
-      let node_hole = Ident.create "spacetime_node_hole" in
-      Some (node_hole, reg), env_add node_hole reg env
+      let node_hole = V.create_local "spacetime_node_hole" in
+      Some (node_hole, reg), env_add (VP.create node_hole) reg env
     end
   in
   self#emit_tail env f.Cmm.fun_body;
diff --git a/asmcomp/selectgen.mli b/asmcomp/selectgen.mli
index 3cd24787..003d7067 100644
--- a/asmcomp/selectgen.mli
+++ b/asmcomp/selectgen.mli
@@ -18,9 +18,13 @@
 
 type environment
 
-val env_add : Ident.t -> Reg.t array -> environment -> environment
+val env_add
+   : Backend_var.With_provenance.t
+  -> Reg.t array
+  -> environment
+  -> environment
 
-val env_find : Ident.t -> environment -> Reg.t array
+val env_find : Backend_var.t -> environment -> Reg.t array
 
 val size_expr : environment -> Cmm.expression -> int
 
@@ -165,7 +169,7 @@ class virtual selector_generic : object
      : Cmm.fundecl
     -> loc_arg:Reg.t array
     -> rarg:Reg.t array
-    -> spacetime_node_hole:(Ident.t * Reg.t array) option
+    -> spacetime_node_hole:(Backend_var.t * Reg.t array) option
     -> env:environment
     -> Mach.spacetime_shape option
 
diff --git a/asmcomp/spacetime_profiling.ml b/asmcomp/spacetime_profiling.ml
index b118e6a4..acabf7c0 100644
--- a/asmcomp/spacetime_profiling.ml
+++ b/asmcomp/spacetime_profiling.ml
@@ -12,14 +12,17 @@
 (*                                                                        *)
 (**************************************************************************)
 
+module V = Backend_var
+module VP = Backend_var.With_provenance
+
 let node_num_header_words = 2 (* [Node_num_header_words] in the runtime. *)
 let index_within_node = ref node_num_header_words
-(* The [lazy]s are to ensure that we don't create [Ident.t]s at toplevel
+(* The [lazy]s are to ensure that we don't create [V.t]s at toplevel
    when not using Spacetime profiling.  (This could cause stamps to differ
    between bytecode and native .cmis when no .mli is present, e.g.
    arch.ml.) *)
-let spacetime_node = ref (lazy (Cmm.Cvar (Ident.create "dummy")))
-let spacetime_node_ident = ref (lazy (Ident.create "dummy"))
+let spacetime_node = ref (lazy (Cmm.Cvar (V.create_local "dummy")))
+let spacetime_node_ident = ref (lazy (V.create_local "dummy"))
 let current_function_label = ref ""
 let direct_tail_call_point_indexes = ref []
 
@@ -55,15 +58,15 @@ let reset ~spacetime_node_ident:ident ~function_label =
   reverse_shape := []
 
 let code_for_function_prologue ~function_name ~node_hole =
-  let node = Ident.create "node" in
-  let new_node = Ident.create "new_node" in
-  let must_allocate_node = Ident.create "must_allocate_node" in
-  let is_new_node = Ident.create "is_new_node" in
+  let node = V.create_local "node" in
+  let new_node = V.create_local "new_node" in
+  let must_allocate_node = V.create_local "must_allocate_node" in
+  let is_new_node = V.create_local "is_new_node" in
   let no_tail_calls = List.length !direct_tail_call_point_indexes < 1 in
   let dbg = Debuginfo.none in
   let open Cmm in
   let initialize_direct_tail_call_points_and_return_node =
-    let new_node_encoded = Ident.create "new_node_encoded" in
+    let new_node_encoded = V.create_local "new_node_encoded" in
     (* The callee node pointers within direct tail call points must initially
        point back at the start of the current node and be marked as per
        [Encode_tail_caller_node] in the runtime. *)
@@ -83,42 +86,43 @@ let code_for_function_prologue ~function_name ~node_hole =
     match indexes with
     | [] -> body
     | _ ->
-      Clet (new_node_encoded,
+      Clet (VP.create new_node_encoded,
         (* Cf. [Encode_tail_caller_node] in the runtime. *)
         Cop (Cor, [Cvar new_node; Cconst_int 1], dbg),
         body)
   in
-  let pc = Ident.create "pc" in
-  Clet (node, Cop (Cload (Word_int, Asttypes.Mutable), [Cvar node_hole], dbg),
-    Clet (must_allocate_node,
-      Cop (Cand, [Cvar node; Cconst_int 1], dbg),
-      Cifthenelse (
-        Cop (Ccmpi Cne, [Cvar must_allocate_node; Cconst_int 1], dbg),
-        Cvar node,
-        Clet (is_new_node,
-          Clet (pc, Cconst_symbol function_name,
-            Cop (Cextcall ("caml_spacetime_allocate_node",
-                [| Int |], false, None),
-              [Cconst_int (1 (* header *) + !index_within_node);
-               Cvar pc;
-               Cvar node_hole;
-              ],
-              dbg)),
-            Clet (new_node,
-              Cop (Cload (Word_int, Asttypes.Mutable), [Cvar node_hole], dbg),
-              if no_tail_calls then Cvar new_node
-              else
-                Cifthenelse (
-                  Cop (Ccmpi Ceq, [Cvar is_new_node; Cconst_int 0], dbg),
-                  Cvar new_node,
-                  initialize_direct_tail_call_points_and_return_node))))))
+  let pc = V.create_local "pc" in
+  Clet (VP.create node,
+    Cop (Cload (Word_int, Asttypes.Mutable), [Cvar node_hole], dbg),
+      Clet (VP.create must_allocate_node,
+        Cop (Cand, [Cvar node; Cconst_int 1], dbg),
+        Cifthenelse (
+          Cop (Ccmpi Cne, [Cvar must_allocate_node; Cconst_int 1], dbg),
+          Cvar node,
+          Clet (VP.create is_new_node,
+            Clet (VP.create pc, Cconst_symbol function_name,
+              Cop (Cextcall ("caml_spacetime_allocate_node",
+                  [| Int |], false, None),
+                [Cconst_int (1 (* header *) + !index_within_node);
+                Cvar pc;
+                Cvar node_hole;
+                ],
+                dbg)),
+              Clet (VP.create new_node,
+                Cop (Cload (Word_int, Asttypes.Mutable), [Cvar node_hole], dbg),
+                if no_tail_calls then Cvar new_node
+                else
+                  Cifthenelse (
+                    Cop (Ccmpi Ceq, [Cvar is_new_node; Cconst_int 0], dbg),
+                    Cvar new_node,
+                    initialize_direct_tail_call_points_and_return_node))))))
 
 let code_for_blockheader ~value's_header ~node ~dbg =
   let num_words = Nativeint.shift_right_logical value's_header 10 in
-  let existing_profinfo = Ident.create "existing_profinfo" in
-  let existing_count = Ident.create "existing_count" in
-  let profinfo = Ident.create "profinfo" in
-  let address_of_profinfo = Ident.create "address_of_profinfo" in
+  let existing_profinfo = V.create_local "existing_profinfo" in
+  let existing_count = V.create_local "existing_count" in
+  let profinfo = V.create_local "profinfo" in
+  let address_of_profinfo = V.create_local "address_of_profinfo" in
   let label = Cmm.new_label () in
   let index_within_node =
     next_index_within_node ~part_of_shape:Mach.Allocation_point ~label
@@ -143,20 +147,20 @@ let code_for_blockheader ~value's_header ~node ~dbg =
   (* Check if we have already allocated a profinfo value for this allocation
      point with the current backtrace.  If so, use that value; if not,
      allocate a new one. *)
-  Clet (address_of_profinfo,
+  Clet (VP.create address_of_profinfo,
     Cop (Caddi, [
       Cvar node;
       Cconst_int offset_into_node;
     ], dbg),
-    Clet (existing_profinfo,
+    Clet (VP.create existing_profinfo,
         Cop (Cload (Word_int, Asttypes.Mutable), [Cvar address_of_profinfo],
           dbg),
-      Clet (profinfo,
+      Clet (VP.create profinfo,
         Cifthenelse (
           Cop (Ccmpi Cne, [Cvar existing_profinfo; Cconst_int 1 (* () *)], dbg),
           Cvar existing_profinfo,
           generate_new_profinfo),
-        Clet (existing_count,
+        Clet (VP.create existing_count,
           Cop (Cload (Word_int, Asttypes.Mutable), [
             Cop (Caddi,
               [Cvar address_of_profinfo; Cconst_int Arch.size_addr], dbg)
@@ -216,10 +220,10 @@ let code_for_call ~node ~callee ~is_tail ~label =
         index_within_node::!direct_tail_call_point_indexes
     | Direct _ | Indirect _ -> ()
   end;
-  let place_within_node = Ident.create "place_within_node" in
+  let place_within_node = V.create_local "place_within_node" in
   let dbg = Debuginfo.none in
   let open Cmm in
-  Clet (place_within_node,
+  Clet (VP.create place_within_node,
     Cop (Caddi, [node; Cconst_int (index_within_node * Arch.size_addr)], dbg),
     (* The following code returns the address that is to be moved into the
        (hard) node hole pointer register immediately before the call.
@@ -227,11 +231,11 @@ let code_for_call ~node ~callee ~is_tail ~label =
     match callee with
     | Direct _callee ->
       if Config.enable_call_counts then begin
-        let count_addr = Ident.create "call_count_addr" in
-        let count = Ident.create "call_count" in
-        Clet (count_addr,
+        let count_addr = V.create_local "call_count_addr" in
+        let count = V.create_local "call_count" in
+        Clet (VP.create count_addr,
           Cop (Caddi, [Cvar place_within_node; Cconst_int Arch.size_addr], dbg),
-          Clet (count,
+          Clet (VP.create count,
             Cop (Cload (Word_int, Asttypes.Mutable), [Cvar count_addr], dbg),
             Csequence (
               Cop (Cstore (Word_int, Lambda.Assignment),
@@ -276,8 +280,8 @@ class virtual instruction_selection = object (self)
       ~label_after =
     (* [callee] is a pseudoregister, so we have to bind it in the environment
        and reference the variable to which it is bound. *)
-    let callee_ident = Ident.create "callee" in
-    let env = Selectgen.env_add callee_ident [| callee |] env in
+    let callee_ident = V.create_local "callee" in
+    let env = Selectgen.env_add (VP.create callee_ident) [| callee |] env in
     let instrumentation =
       code_for_call
         ~node:(Lazy.force !spacetime_node)
@@ -357,7 +361,7 @@ class virtual instruction_selection = object (self)
       super#emit_blockheader env n dbg
     end
 
-  method! select_allocation words =
+  method! select_allocation bytes =
     if self#can_instrument () then begin
       (* Leave space for a direct call point.  We cannot easily insert any
          instrumentation code, so the fields are filled in instead by
@@ -369,12 +373,12 @@ class virtual instruction_selection = object (self)
           ~label
       in
       Mach.Ialloc {
-        words;
+        bytes;
         label_after_call_gc = Some label;
         spacetime_index = index;
       }
     end else begin
-      super#select_allocation words
+      super#select_allocation bytes
     end
 
   method! select_allocation_args env =
@@ -416,7 +420,7 @@ class virtual instruction_selection = object (self)
   method! initial_env () =
     let env = super#initial_env () in
     if Config.spacetime then
-      Selectgen.env_add (Lazy.force !spacetime_node_ident)
+      Selectgen.env_add (VP.create (Lazy.force !spacetime_node_ident))
         (self#regs_for Cmm.typ_int) env
     else
       env
@@ -424,7 +428,7 @@ class virtual instruction_selection = object (self)
   method! emit_fundecl f =
     if Config.spacetime then begin
       disable_instrumentation <- false;
-      let node = Ident.create "spacetime_node" in
+      let node = V.create_local "spacetime_node" in
       reset ~spacetime_node_ident:node ~function_label:f.Cmm.fun_name
     end;
     super#emit_fundecl f
diff --git a/asmcomp/split.ml b/asmcomp/split.ml
index 59826284..650c404e 100644
--- a/asmcomp/split.ml
+++ b/asmcomp/split.ml
@@ -171,7 +171,8 @@ let rec rename i sub =
       let previous_exit_subst = !exit_subst in
       exit_subst := new_subst @ !exit_subst;
       let (new_body, sub_body) = rename body sub in
-      let res = List.map2 (fun (_, handler) (_, new_subst) -> rename handler !new_subst)
+      let res =
+        List.map2 (fun (_, handler) (_, new_subst) -> rename handler !new_subst)
           handlers new_subst in
       exit_subst := previous_exit_subst;
       let merged_subst =
diff --git a/asmcomp/strmatch.ml b/asmcomp/strmatch.ml
index 3a60f241..b1efbf8f 100644
--- a/asmcomp/strmatch.ml
+++ b/asmcomp/strmatch.ml
@@ -18,6 +18,9 @@
 open Lambda
 open Cmm
 
+module V = Backend_var
+module VP = Backend_var.With_provenance
+
 module type I = sig
   val string_block_length : Cmm.expression -> Cmm.expression
   val transl_switch :
@@ -62,13 +65,13 @@ module Make(I:I) = struct
   let pp_match chan tag idxs cases =
     Printf.eprintf
       "%s: idx=[%s]\n" tag
-      (String.concat "; " (List.map string_of_int idxs)) ;
+      (String.concat "; " (List.map Int.to_string idxs)) ;
     do_pp_cases chan cases
 
 (* Utilities *)
 
-  let gen_cell_id () = Ident.create "cell"
-  let gen_size_id () = Ident.create "size"
+  let gen_cell_id () = V.create_local "cell"
+  let gen_size_id () = V.create_local "size"
 
   let mk_let_cell id str ind body =
     let dbg = Debuginfo.none in
@@ -293,7 +296,7 @@ module Make(I:I) = struct
         else
           let lt,midkey,ge = split_env len env in
           mk_lt id midkey (comp_rec lt) (comp_rec ge) in
-      mk_let_cell id str idx (comp_rec env)
+      mk_let_cell (VP.create id) str idx (comp_rec env)
 
 (*
   Recursive 'list of cells' compile function:
@@ -352,7 +355,7 @@ module Make(I:I) = struct
       let id = gen_size_id () in
       let loc = Debuginfo.to_location dbg in
       let switch = I.transl_switch loc (Cvar id) 1 max_int size_cases default in
-      mk_let_size id str switch
+      mk_let_size (VP.create id) str switch
 
 (*
   Compilation entry point: we choose to switch
diff --git a/asmcomp/un_anf.ml b/asmcomp/un_anf.ml
index bc8f9eb8..450a9dd5 100644
--- a/asmcomp/un_anf.ml
+++ b/asmcomp/un_anf.ml
@@ -16,58 +16,74 @@
 
 [@@@ocaml.warning "+a-4-30-40-41-42"]
 
-(* We say that an [Ident.t] is "linear" iff:
+(* CR-someday vlaviron for mshinwell: I believe that the phantom lets introduced
+   in un_anf (when the new debug_full flag is enabled) bind mostly variables
+   that were created in the middle-end. Is it relevant to generate debugging
+   information for such variables ? I expect later pull requests to refine the
+   generation of these phantom constructions anyway, but maybe it would already
+   make sense to restrict the phantom let generation to variables with an actual
+   provenance.
+*)
+
+module V = Backend_var
+module VP = Backend_var.With_provenance
+
+(* We say that an [V.t] is "linear" iff:
    (a) it is used exactly once;
    (b) it is never assigned to (using [Uassign]).
 *)
-type ident_info =
-  { used : Ident.Set.t;
-    linear : Ident.Set.t;
-    assigned : Ident.Set.t;
-    closure_environment : Ident.Set.t;
-    let_bound_vars_that_can_be_moved : Ident.Set.t;
+type var_info =
+  { used : V.Set.t;
+    linear : V.Set.t;
+    assigned : V.Set.t;
+    closure_environment : V.Set.t;
+    let_bound_vars_that_can_be_moved : V.Set.t;
   }
 
 let ignore_uconstant (_ : Clambda.uconstant) = ()
 let ignore_ulambda (_ : Clambda.ulambda) = ()
 let ignore_ulambda_list (_ : Clambda.ulambda list) = ()
+let ignore_uphantom_defining_expr_option
+      (_ : Clambda.uphantom_defining_expr option) = ()
 let ignore_function_label (_ : Clambda.function_label) = ()
 let ignore_debuginfo (_ : Debuginfo.t) = ()
 let ignore_int (_ : int) = ()
-let ignore_ident (_ : Ident.t) = ()
-let ignore_ident_option (_ : Ident.t option) = ()
+let ignore_var (_ : V.t) = ()
+let ignore_var_option (_ : V.t option) = ()
 let ignore_primitive (_ : Lambda.primitive) = ()
 let ignore_string (_ : string) = ()
 let ignore_int_array (_ : int array) = ()
-let ignore_ident_list (_ : Ident.t list) = ()
+let ignore_var_with_provenance (_ : VP.t) = ()
+let ignore_params_with_value_kind (_ : (VP.t * Lambda.value_kind) list) = ()
 let ignore_direction_flag (_ : Asttypes.direction_flag) = ()
 let ignore_meth_kind (_ : Lambda.meth_kind) = ()
+let ignore_value_kind (_ : Lambda.value_kind) = ()
 
 (* CR-soon mshinwell: check we aren't traversing function bodies more than
    once (need to analyse exactly what the calls are from Cmmgen into this
    module). *)
 
-let closure_environment_ident (ufunction:Clambda.ufunction) =
+let closure_environment_var (ufunction:Clambda.ufunction) =
   (* The argument after the arity is the environment *)
   if List.length ufunction.params = ufunction.arity + 1 then
-    let env_var = List.nth ufunction.params ufunction.arity in
-    assert(Ident.name env_var = "env");
+    let (env_var, _) = List.nth ufunction.params ufunction.arity in
+    assert (VP.name env_var = "env");
     Some env_var
   else
     (* closed function, no environment *)
     None
 
-let make_ident_info (clam : Clambda.ulambda) : ident_info =
-  let t : int Ident.Tbl.t = Ident.Tbl.create 42 in
-  let assigned_idents = ref Ident.Set.empty in
-  let environment_idents = ref Ident.Set.empty in
+let make_var_info (clam : Clambda.ulambda) : var_info =
+  let t : int V.Tbl.t = V.Tbl.create 42 in
+  let assigned_vars = ref V.Set.empty in
+  let environment_vars = ref V.Set.empty in
   let rec loop : Clambda.ulambda -> unit = function
     (* No underscores in the pattern match, to reduce the chance of failing
        to traverse some subexpression. *)
-    | Uvar id ->
-      begin match Ident.Tbl.find t id with
-      | n -> Ident.Tbl.replace t id (n + 1)
-      | exception Not_found -> Ident.Tbl.add t id 1
+    | Uvar var ->
+      begin match V.Tbl.find t var with
+      | n -> V.Tbl.replace t var (n + 1)
+      | exception Not_found -> V.Tbl.add t var 1
       end
     | Uconst const ->
       (* The only variables that might occur in [const] are those in constant
@@ -88,28 +104,33 @@ let make_ident_info (clam : Clambda.ulambda) : ident_info =
     | Uclosure (functions, captured_variables) ->
       List.iter loop captured_variables;
       List.iter (fun (
-        { Clambda. label; arity; params; body; dbg; env; } as clos) ->
-          (match closure_environment_ident clos with
+        { Clambda. label; arity; params; return; body; dbg; env; } as clos) ->
+          (match closure_environment_var clos with
            | None -> ()
            | Some env_var ->
-             environment_idents :=
-               Ident.Set.add env_var !environment_idents);
+             environment_vars :=
+               V.Set.add (VP.var env_var) !environment_vars);
           ignore_function_label label;
           ignore_int arity;
-          ignore_ident_list params;
+          ignore_params_with_value_kind params;
+          ignore_value_kind return;
           loop body;
           ignore_debuginfo dbg;
-          ignore_ident_option env)
+          ignore_var_option env)
         functions
     | Uoffset (expr, offset) ->
       loop expr;
       ignore_int offset
-    | Ulet (_let_kind, _value_kind, _ident, def, body) ->
+    | Ulet (_let_kind, _value_kind, _var, def, body) ->
       loop def;
       loop body
+    | Uphantom_let (var, defining_expr_opt, body) ->
+      ignore_var_with_provenance var;
+      ignore_uphantom_defining_expr_option defining_expr_opt;
+      loop body
     | Uletrec (defs, body) ->
-      List.iter (fun (ident, def) ->
-          ignore_ident ident;
+      List.iter (fun (var, def) ->
+          ignore_var_with_provenance var;
           loop def)
         defs;
       loop body
@@ -135,14 +156,14 @@ let make_ident_info (clam : Clambda.ulambda) : ident_info =
     | Ustaticfail (static_exn, args) ->
       ignore_int static_exn;
       List.iter loop args
-    | Ucatch (static_exn, idents, body, handler) ->
+    | Ucatch (static_exn, vars, body, handler) ->
       ignore_int static_exn;
-      ignore_ident_list idents;
+      ignore_params_with_value_kind vars;
       loop body;
       loop handler
-    | Utrywith (body, ident, handler) ->
+    | Utrywith (body, var, handler) ->
       loop body;
-      ignore_ident ident;
+      ignore_var_with_provenance var;
       loop handler
     | Uifthenelse (cond, ifso, ifnot) ->
       loop cond;
@@ -154,14 +175,14 @@ let make_ident_info (clam : Clambda.ulambda) : ident_info =
     | Uwhile (cond, body) ->
       loop cond;
       loop body
-    | Ufor (ident, low, high, direction_flag, body) ->
-      ignore_ident ident;
+    | Ufor (var, low, high, direction_flag, body) ->
+      ignore_var_with_provenance var;
       loop low;
       loop high;
       ignore_direction_flag direction_flag;
       loop body
-    | Uassign (ident, expr) ->
-      assigned_idents := Ident.Set.add ident !assigned_idents;
+    | Uassign (var, expr) ->
+      assigned_vars := V.Set.add var !assigned_vars;
       loop expr
     | Usend (meth_kind, e1, e2, args, dbg) ->
       ignore_meth_kind meth_kind;
@@ -174,24 +195,24 @@ let make_ident_info (clam : Clambda.ulambda) : ident_info =
   in
   loop clam;
   let linear =
-    Ident.Tbl.fold (fun id n acc ->
+    V.Tbl.fold (fun var n acc ->
         assert (n >= 1);
-        if n = 1 && not (Ident.Set.mem id !assigned_idents)
-        then Ident.Set.add id acc
+        if n = 1 && not (V.Set.mem var !assigned_vars)
+        then V.Set.add var acc
         else acc)
-      t Ident.Set.empty
+      t V.Set.empty
   in
-  let assigned = !assigned_idents in
+  let assigned = !assigned_vars in
   let used =
     (* This doesn't work transitively and thus is somewhat restricted.  In
        particular, it does not allow us to get rid of useless chains of [let]s.
        However it should be sufficient to remove the majority of unnecessary
        [let] bindings that might hinder [Cmmgen]. *)
-    Ident.Tbl.fold (fun id _n acc -> Ident.Set.add id acc)
+    V.Tbl.fold (fun var _n acc -> V.Set.add var acc)
       t assigned
   in
-  { used; linear; assigned; closure_environment = !environment_idents;
-    let_bound_vars_that_can_be_moved = Ident.Set.empty;
+  { used; linear; assigned; closure_environment = !environment_vars;
+    let_bound_vars_that_can_be_moved = V.Set.empty;
   }
 
 (* When sequences of [let]-bindings match the evaluation order in a subsequent
@@ -200,9 +221,9 @@ let make_ident_info (clam : Clambda.ulambda) : ident_info =
    variables that are known to be constant), and it is known that there were no
    intervening side-effects during the evaluation of the [let]-bindings,
    permit substitution of the variables for their defining expressions. *)
-let let_bound_vars_that_can_be_moved ident_info (clam : Clambda.ulambda) =
-  let obviously_constant = ref Ident.Set.empty in
-  let can_move = ref Ident.Set.empty in
+let let_bound_vars_that_can_be_moved var_info (clam : Clambda.ulambda) =
+  let obviously_constant = ref V.Set.empty in
+  let can_move = ref V.Set.empty in
   let let_stack = ref [] in
   let examine_argument_list args =
     let rec loop let_bound_vars (args : Clambda.ulambda list) =
@@ -217,14 +238,14 @@ let let_bound_vars_that_can_be_moved ident_info (clam : Clambda.ulambda) =
            is left empty. *)
         []
       | let_bound_vars, (Uvar arg)::args
-          when Ident.Set.mem arg !obviously_constant ->
+          when V.Set.mem arg !obviously_constant ->
         loop let_bound_vars args
       | let_bound_var::let_bound_vars, (Uvar arg)::args
-          when Ident.same let_bound_var arg
-            && not (Ident.Set.mem arg ident_info.assigned) ->
-        assert (Ident.Set.mem arg ident_info.used);
-        assert (Ident.Set.mem arg ident_info.linear);
-        can_move := Ident.Set.add arg !can_move;
+          when V.same let_bound_var arg
+            && not (V.Set.mem arg var_info.assigned) ->
+        assert (V.Set.mem arg var_info.used);
+        assert (V.Set.mem arg var_info.linear);
+        can_move := V.Set.add arg !can_move;
         loop let_bound_vars args
       | _::_, _::_ ->
         (* The [let] sequence has ceased to match the evaluation order
@@ -238,8 +259,8 @@ let let_bound_vars_that_can_be_moved ident_info (clam : Clambda.ulambda) =
     let_stack := loop !let_stack args
   in
   let rec loop : Clambda.ulambda -> unit = function
-    | Uvar ident ->
-      if Ident.Set.mem ident ident_info.assigned then begin
+    | Uvar var ->
+      if V.Set.mem var var_info.assigned then begin
         let_stack := []
       end
     | Uconst const ->
@@ -257,32 +278,34 @@ let let_bound_vars_that_can_be_moved ident_info (clam : Clambda.ulambda) =
     | Uclosure (functions, captured_variables) ->
       ignore_ulambda_list captured_variables;
       (* Start a new let stack for speed. *)
-      List.iter (fun { Clambda. label; arity; params; body; dbg; env; } ->
+      List.iter (fun {Clambda. label; arity; params; return; body; dbg; env} ->
           ignore_function_label label;
           ignore_int arity;
-          ignore_ident_list params;
+          ignore_params_with_value_kind params;
+          ignore_value_kind return;
           let_stack := [];
           loop body;
           let_stack := [];
           ignore_debuginfo dbg;
-          ignore_ident_option env)
+          ignore_var_option env)
         functions
     | Uoffset (expr, offset) ->
       (* [expr] should usually be a variable. *)
       examine_argument_list [expr];
       ignore_int offset
-    | Ulet (_let_kind, _value_kind, ident, def, body) ->
+    | Ulet (_let_kind, _value_kind, var, def, body) ->
+      let var = VP.var var in
       begin match def with
       | Uconst _ ->
         (* The defining expression is obviously constant, so we don't
            have to put this [let] on the stack, and we don't have to
            traverse the defining expression either. *)
-        obviously_constant := Ident.Set.add ident !obviously_constant;
+        obviously_constant := V.Set.add var !obviously_constant;
         loop body
       | _ ->
         loop def;
-        if Ident.Set.mem ident ident_info.linear then begin
-          let_stack := ident::!let_stack
+        if V.Set.mem var var_info.linear then begin
+          let_stack := var::!let_stack
         end else begin
           (* If we encounter a non-linear [let]-binding then we must clear
              the let stack, since we cannot now move any previous binding
@@ -291,12 +314,15 @@ let let_bound_vars_that_can_be_moved ident_info (clam : Clambda.ulambda) =
         end;
         loop body
       end
+    | Uphantom_let (var, _defining_expr, body) ->
+      ignore_var_with_provenance var;
+      loop body
     | Uletrec (defs, body) ->
       (* Evaluation order for [defs] is not defined, and this case
          probably isn't important for [Cmmgen] anyway. *)
       let_stack := [];
-      List.iter (fun (ident, def) ->
-          ignore_ident ident;
+      List.iter (fun (var, def) ->
+          ignore_var_with_provenance var;
           loop def;
           let_stack := [])
         defs;
@@ -333,19 +359,19 @@ let let_bound_vars_that_can_be_moved ident_info (clam : Clambda.ulambda) =
     | Ustaticfail (static_exn, args) ->
       ignore_int static_exn;
       examine_argument_list args
-    | Ucatch (static_exn, idents, body, handler) ->
+    | Ucatch (static_exn, vars, body, handler) ->
       ignore_int static_exn;
-      ignore_ident_list idents;
+      ignore_params_with_value_kind vars;
       let_stack := [];
       loop body;
       let_stack := [];
       loop handler;
       let_stack := []
-    | Utrywith (body, ident, handler) ->
+    | Utrywith (body, var, handler) ->
       let_stack := [];
       loop body;
       let_stack := [];
-      ignore_ident ident;
+      ignore_var_with_provenance var;
       loop handler;
       let_stack := []
     | Uifthenelse (cond, ifso, ifnot) ->
@@ -366,8 +392,8 @@ let let_bound_vars_that_can_be_moved ident_info (clam : Clambda.ulambda) =
       let_stack := [];
       loop body;
       let_stack := []
-    | Ufor (ident, low, high, direction_flag, body) ->
-      ignore_ident ident;
+    | Ufor (var, low, high, direction_flag, body) ->
+      ignore_var_with_provenance var;
       (* Cmmgen generates code that evaluates low before high,
          but we don't do anything here at the moment anyway. *)
       ignore_ulambda low;
@@ -376,8 +402,8 @@ let let_bound_vars_that_can_be_moved ident_info (clam : Clambda.ulambda) =
       let_stack := [];
       loop body;
       let_stack := []
-    | Uassign (ident, expr) ->
-      ignore_ident ident;
+    | Uassign (var, expr) ->
+      ignore_var var;
       ignore_ulambda expr;
       let_stack := []
     | Usend (meth_kind, e1, e2, args, dbg) ->
@@ -399,15 +425,15 @@ let let_bound_vars_that_can_be_moved ident_info (clam : Clambda.ulambda) =
 let rec substitute_let_moveable is_let_moveable env (clam : Clambda.ulambda)
       : Clambda.ulambda =
   match clam with
-  | Uvar id ->
-    if not (Ident.Set.mem id is_let_moveable) then
+  | Uvar var ->
+    if not (V.Set.mem var is_let_moveable) then
       clam
     else
-      begin match Ident.Map.find id env with
+      begin match V.Map.find var env with
       | clam -> clam
       | exception Not_found ->
-        Misc.fatal_errorf "substitute_let_moveable: Unbound identifier %a"
-          Ident.print id
+        Misc.fatal_errorf "substitute_let_moveable: Unbound variable %a"
+          V.print var
       end
   | Uconst _ -> clam
   | Udirect_apply (label, args, dbg) ->
@@ -433,18 +459,35 @@ let rec substitute_let_moveable is_let_moveable env (clam : Clambda.ulambda)
   | Uoffset (clam, n) ->
     let clam = substitute_let_moveable is_let_moveable env clam in
     Uoffset (clam, n)
-  | Ulet (let_kind, value_kind, id, def, body) ->
+  | Ulet (let_kind, value_kind, var, def, body) ->
     let def = substitute_let_moveable is_let_moveable env def in
-    if Ident.Set.mem id is_let_moveable then
-      let env = Ident.Map.add id def env in
-      substitute_let_moveable is_let_moveable env body
+    if V.Set.mem (VP.var var) is_let_moveable then
+      let env = V.Map.add (VP.var var) def env in
+      let body = substitute_let_moveable is_let_moveable env body in
+      (* If we are about to delete a [let] in debug mode, keep it for the
+         debugger. *)
+      (* CR-someday mshinwell: find out why some closure constructions were
+         not leaving phantom lets behind after substitution. *)
+      if not !Clflags.debug_full then
+        body
+      else
+        match def with
+        | Uconst const ->
+          Uphantom_let (var, Some (Clambda.Uphantom_const const), body)
+        | Uvar alias_of ->
+          Uphantom_let (var, Some (Clambda.Uphantom_var alias_of), body)
+        | _ ->
+          Uphantom_let (var, None, body)
     else
       Ulet (let_kind, value_kind,
-            id, def, substitute_let_moveable is_let_moveable env body)
+            var, def, substitute_let_moveable is_let_moveable env body)
+  | Uphantom_let (var, defining_expr, body) ->
+    let body = substitute_let_moveable is_let_moveable env body in
+    Uphantom_let (var, defining_expr, body)
   | Uletrec (defs, body) ->
     let defs =
-      List.map (fun (id, def) ->
-          id, substitute_let_moveable is_let_moveable env def)
+      List.map (fun (var, def) ->
+          var, substitute_let_moveable is_let_moveable env def)
         defs
     in
     let body = substitute_let_moveable is_let_moveable env body in
@@ -479,14 +522,14 @@ let rec substitute_let_moveable is_let_moveable env (clam : Clambda.ulambda)
   | Ustaticfail (n, args) ->
     let args = substitute_let_moveable_list is_let_moveable env args in
     Ustaticfail (n, args)
-  | Ucatch (n, ids, body, handler) ->
+  | Ucatch (n, vars, body, handler) ->
     let body = substitute_let_moveable is_let_moveable env body in
     let handler = substitute_let_moveable is_let_moveable env handler in
-    Ucatch (n, ids, body, handler)
-  | Utrywith (body, id, handler) ->
+    Ucatch (n, vars, body, handler)
+  | Utrywith (body, var, handler) ->
     let body = substitute_let_moveable is_let_moveable env body in
     let handler = substitute_let_moveable is_let_moveable env handler in
-    Utrywith (body, id, handler)
+    Utrywith (body, var, handler)
   | Uifthenelse (cond, ifso, ifnot) ->
     let cond = substitute_let_moveable is_let_moveable env cond in
     let ifso = substitute_let_moveable is_let_moveable env ifso in
@@ -500,14 +543,14 @@ let rec substitute_let_moveable is_let_moveable env (clam : Clambda.ulambda)
     let cond = substitute_let_moveable is_let_moveable env cond in
     let body = substitute_let_moveable is_let_moveable env body in
     Uwhile (cond, body)
-  | Ufor (id, low, high, direction, body) ->
+  | Ufor (var, low, high, direction, body) ->
     let low = substitute_let_moveable is_let_moveable env low in
     let high = substitute_let_moveable is_let_moveable env high in
     let body = substitute_let_moveable is_let_moveable env body in
-    Ufor (id, low, high, direction, body)
-  | Uassign (id, expr) ->
+    Ufor (var, low, high, direction, body)
+  | Uassign (var, expr) ->
     let expr = substitute_let_moveable is_let_moveable env expr in
-    Uassign (id, expr)
+    Uassign (var, expr)
   | Usend (kind, e1, e2, args, dbg) ->
     let e1 = substitute_let_moveable is_let_moveable env e1 in
     let e2 = substitute_let_moveable is_let_moveable env e2 in
@@ -541,7 +584,7 @@ let both_moveable a b =
 
 let primitive_moveable (prim : Lambda.primitive)
     (args : Clambda.ulambda list)
-    (ident_info : ident_info) =
+    (var_info : var_info) =
   match prim, args with
   | Pfield _, [Uconst (Uconst_ref (_, _))] ->
     (* CR-someday mshinwell: Actually, maybe this shouldn't be needed; these
@@ -551,7 +594,7 @@ let primitive_moveable (prim : Lambda.primitive)
     (* Allow field access of symbols to be moveable.  (The comment in
        flambda.mli on [Read_symbol_field] may be helpful to the reader.) *)
     Moveable
-  | Pfield _, [Uvar id] when Ident.Set.mem id ident_info.closure_environment ->
+  | Pfield _, [Uvar var] when V.Set.mem var var_info.closure_environment ->
     (* accesses to the function environment is coeffect free: this block
        is never mutated *)
     Moveable
@@ -568,16 +611,16 @@ type moveable_for_env = Constant | Moveable
 
 (** Eliminate, through substitution, [let]-bindings of linear variables with
     moveable defining expressions. *)
-let rec un_anf_and_moveable ident_info env (clam : Clambda.ulambda)
+let rec un_anf_and_moveable var_info env (clam : Clambda.ulambda)
       : Clambda.ulambda * moveable =
   match clam with
-  | Uvar id ->
-    begin match Ident.Map.find id env with
+  | Uvar var ->
+    begin match V.Map.find var env with
     | Constant, def -> def, Constant
     | Moveable, def -> def, Moveable
     | exception Not_found ->
       let moveable : moveable =
-        if Ident.Set.mem id ident_info.assigned then
+        if V.Set.mem var var_info.assigned then
           Fixed
         else
           Moveable
@@ -588,164 +631,187 @@ let rec un_anf_and_moveable ident_info env (clam : Clambda.ulambda)
     (* Constant closures are rewritten separately. *)
     clam, Constant
   | Udirect_apply (label, args, dbg) ->
-    let args = un_anf_list ident_info env args in
+    let args = un_anf_list var_info env args in
     Udirect_apply (label, args, dbg), Fixed
   | Ugeneric_apply (func, args, dbg) ->
-    let func = un_anf ident_info env func in
-    let args = un_anf_list ident_info env args in
+    let func = un_anf var_info env func in
+    let args = un_anf_list var_info env args in
     Ugeneric_apply (func, args, dbg), Fixed
   | Uclosure (functions, variables_bound_by_the_closure) ->
     let functions =
       List.map (fun (ufunction : Clambda.ufunction) ->
           { ufunction with
-            body = un_anf ident_info env ufunction.body;
+            body = un_anf var_info env ufunction.body;
           })
         functions
     in
     let variables_bound_by_the_closure =
-      un_anf_list ident_info env variables_bound_by_the_closure
+      un_anf_list var_info env variables_bound_by_the_closure
     in
     Uclosure (functions, variables_bound_by_the_closure), Fixed
   | Uoffset (clam, n) ->
-    let clam, moveable = un_anf_and_moveable ident_info env clam in
+    let clam, moveable = un_anf_and_moveable var_info env clam in
     Uoffset (clam, n), both_moveable Moveable moveable
-  | Ulet (_let_kind, _value_kind, id, def, Uvar id') when Ident.same id id' ->
-    un_anf_and_moveable ident_info env def
-  | Ulet (let_kind, value_kind, id, def, body) ->
-    let def, def_moveable = un_anf_and_moveable ident_info env def in
-    let is_linear = Ident.Set.mem id ident_info.linear in
-    let is_used = Ident.Set.mem id ident_info.used in
-    let is_assigned = Ident.Set.mem id ident_info.assigned in
+  | Ulet (_let_kind, _value_kind, var, def, Uvar var')
+      when V.same (VP.var var) var' ->
+    un_anf_and_moveable var_info env def
+  | Ulet (let_kind, value_kind, var, def, body) ->
+    let def, def_moveable = un_anf_and_moveable var_info env def in
+    let is_linear = V.Set.mem (VP.var var) var_info.linear in
+    let is_used = V.Set.mem (VP.var var) var_info.used in
+    let is_assigned = V.Set.mem (VP.var var) var_info.assigned in
+    let maybe_for_debugger (body, moveable) : Clambda.ulambda * moveable =
+      if not !Clflags.debug_full then
+        body, moveable
+      else
+        match def with
+        | Uconst const ->
+          Uphantom_let (var, Some (Clambda.Uphantom_const const),
+            body), moveable
+        | Uvar alias_of ->
+          Uphantom_let (var, Some (Clambda.Uphantom_var alias_of), body),
+            moveable
+        | _ ->
+          Uphantom_let (var, None, body), moveable
+    in
     begin match def_moveable, is_linear, is_used, is_assigned with
     | (Constant | Moveable), _, false, _ ->
-      (* A moveable expression that is never used may be eliminated. *)
-      un_anf_and_moveable ident_info env body
+      (* A moveable expression that is never used may be eliminated.
+         However, if in debug mode and the defining expression is
+         appropriate, keep the let (as a phantom let) for the debugger. *)
+      maybe_for_debugger (un_anf_and_moveable var_info env body)
     | Constant, _, true, false
-    (* A constant expression bound to an unassigned identifier can replace any
-         occurrences of the identifier. *)
+    (* A constant expression bound to an unassigned variable can replace any
+       occurrences of the variable.  The same comment as above concerning
+       phantom lets applies. *)
     | Moveable, true, true, false  ->
-      (* A moveable expression bound to a linear unassigned [Ident.t]
-         may replace the single occurrence of the identifier. *)
+      (* A moveable expression bound to a linear unassigned [V.t]
+         may replace the single occurrence of the variable.  The same comment
+         as above concerning phantom lets applies. *)
       let def_moveable =
         match def_moveable with
         | Moveable -> Moveable
         | Constant -> Constant
         | Fixed -> assert false
       in
-      let env = Ident.Map.add id (def_moveable, def) env in
-      un_anf_and_moveable ident_info env body
+      let env = V.Map.add (VP.var var) (def_moveable, def) env in
+      maybe_for_debugger (un_anf_and_moveable var_info env body)
     | (Constant | Moveable), _, _, true
         (* Constant or Moveable but assigned. *)
     | Moveable, false, _, _
         (* Moveable but not used linearly. *)
     | Fixed, _, _, _ ->
-      let body, body_moveable = un_anf_and_moveable ident_info env body in
-      Ulet (let_kind, value_kind, id, def, body),
+      let body, body_moveable = un_anf_and_moveable var_info env body in
+      Ulet (let_kind, value_kind, var, def, body),
       both_moveable def_moveable body_moveable
     end
+  | Uphantom_let (var, defining_expr, body) ->
+    let body, body_moveable = un_anf_and_moveable var_info env body in
+    Uphantom_let (var, defining_expr, body), body_moveable
   | Uletrec (defs, body) ->
     let defs =
-      List.map (fun (id, def) -> id, un_anf ident_info env def) defs
+      List.map (fun (var, def) -> var, un_anf var_info env def) defs
     in
-    let body = un_anf ident_info env body in
+    let body = un_anf var_info env body in
     Uletrec (defs, body), Fixed
   | Uprim (prim, args, dbg) ->
-    let args, args_moveable = un_anf_list_and_moveable ident_info env args in
+    let args, args_moveable = un_anf_list_and_moveable var_info env args in
     let moveable =
-      both_moveable args_moveable (primitive_moveable prim args ident_info)
+      both_moveable args_moveable (primitive_moveable prim args var_info)
     in
     Uprim (prim, args, dbg), moveable
   | Uswitch (cond, sw, dbg) ->
-    let cond = un_anf ident_info env cond in
+    let cond = un_anf var_info env cond in
     let sw =
       { sw with
-        us_actions_consts = un_anf_array ident_info env sw.us_actions_consts;
-        us_actions_blocks = un_anf_array ident_info env sw.us_actions_blocks;
+        us_actions_consts = un_anf_array var_info env sw.us_actions_consts;
+        us_actions_blocks = un_anf_array var_info env sw.us_actions_blocks;
       }
     in
     Uswitch (cond, sw, dbg), Fixed
   | Ustringswitch (cond, branches, default) ->
-    let cond = un_anf ident_info env cond in
+    let cond = un_anf var_info env cond in
     let branches =
-      List.map (fun (s, branch) -> s, un_anf ident_info env branch)
+      List.map (fun (s, branch) -> s, un_anf var_info env branch)
         branches
     in
-    let default = Misc.may_map (un_anf ident_info env) default in
+    let default = Misc.may_map (un_anf var_info env) default in
     Ustringswitch (cond, branches, default), Fixed
   | Ustaticfail (n, args) ->
-    let args = un_anf_list ident_info env args in
+    let args = un_anf_list var_info env args in
     Ustaticfail (n, args), Fixed
-  | Ucatch (n, ids, body, handler) ->
-    let body = un_anf ident_info env body in
-    let handler = un_anf ident_info env handler in
-    Ucatch (n, ids, body, handler), Fixed
-  | Utrywith (body, id, handler) ->
-    let body = un_anf ident_info env body in
-    let handler = un_anf ident_info env handler in
-    Utrywith (body, id, handler), Fixed
+  | Ucatch (n, vars, body, handler) ->
+    let body = un_anf var_info env body in
+    let handler = un_anf var_info env handler in
+    Ucatch (n, vars, body, handler), Fixed
+  | Utrywith (body, var, handler) ->
+    let body = un_anf var_info env body in
+    let handler = un_anf var_info env handler in
+    Utrywith (body, var, handler), Fixed
   | Uifthenelse (cond, ifso, ifnot) ->
-    let cond, cond_moveable = un_anf_and_moveable ident_info env cond in
-    let ifso, ifso_moveable = un_anf_and_moveable ident_info env ifso in
-    let ifnot, ifnot_moveable = un_anf_and_moveable ident_info env ifnot in
+    let cond, cond_moveable = un_anf_and_moveable var_info env cond in
+    let ifso, ifso_moveable = un_anf_and_moveable var_info env ifso in
+    let ifnot, ifnot_moveable = un_anf_and_moveable var_info env ifnot in
     let moveable =
       both_moveable cond_moveable
         (both_moveable ifso_moveable ifnot_moveable)
     in
     Uifthenelse (cond, ifso, ifnot), moveable
   | Usequence (e1, e2) ->
-    let e1 = un_anf ident_info env e1 in
-    let e2 = un_anf ident_info env e2 in
+    let e1 = un_anf var_info env e1 in
+    let e2 = un_anf var_info env e2 in
     Usequence (e1, e2), Fixed
   | Uwhile (cond, body) ->
-    let cond = un_anf ident_info env cond in
-    let body = un_anf ident_info env body in
+    let cond = un_anf var_info env cond in
+    let body = un_anf var_info env body in
     Uwhile (cond, body), Fixed
-  | Ufor (id, low, high, direction, body) ->
-    let low = un_anf ident_info env low in
-    let high = un_anf ident_info env high in
-    let body = un_anf ident_info env body in
-    Ufor (id, low, high, direction, body), Fixed
-  | Uassign (id, expr) ->
-    let expr = un_anf ident_info env expr in
-    Uassign (id, expr), Fixed
+  | Ufor (var, low, high, direction, body) ->
+    let low = un_anf var_info env low in
+    let high = un_anf var_info env high in
+    let body = un_anf var_info env body in
+    Ufor (var, low, high, direction, body), Fixed
+  | Uassign (var, expr) ->
+    let expr = un_anf var_info env expr in
+    Uassign (var, expr), Fixed
   | Usend (kind, e1, e2, args, dbg) ->
-    let e1 = un_anf ident_info env e1 in
-    let e2 = un_anf ident_info env e2 in
-    let args = un_anf_list ident_info env args in
+    let e1 = un_anf var_info env e1 in
+    let e2 = un_anf var_info env e2 in
+    let args = un_anf_list var_info env args in
     Usend (kind, e1, e2, args, dbg), Fixed
   | Uunreachable ->
     Uunreachable, Fixed
 
-and un_anf ident_info env clam : Clambda.ulambda =
-  let clam, _moveable = un_anf_and_moveable ident_info env clam in
+and un_anf var_info env clam : Clambda.ulambda =
+  let clam, _moveable = un_anf_and_moveable var_info env clam in
   clam
 
-and un_anf_list_and_moveable ident_info env clams
+and un_anf_list_and_moveable var_info env clams
       : Clambda.ulambda list * moveable =
   List.fold_right (fun clam (l, acc_moveable) ->
-      let clam, moveable = un_anf_and_moveable ident_info env clam in
+      let clam, moveable = un_anf_and_moveable var_info env clam in
       clam :: l, both_moveable moveable acc_moveable)
     clams ([], (Moveable : moveable))
 
-and un_anf_list ident_info env clams : Clambda.ulambda list =
-  let clams, _moveable = un_anf_list_and_moveable ident_info env clams in
+and un_anf_list var_info env clams : Clambda.ulambda list =
+  let clams, _moveable = un_anf_list_and_moveable var_info env clams in
   clams
 
-and un_anf_array ident_info env clams : Clambda.ulambda array =
-  Array.map (un_anf ident_info env) clams
+and un_anf_array var_info env clams : Clambda.ulambda array =
+  Array.map (un_anf var_info env) clams
 
-let apply clam ~what =
-  let ident_info = make_ident_info clam in
+let apply ~ppf_dump clam ~what =
+  let var_info = make_var_info clam in
   let let_bound_vars_that_can_be_moved =
-    let_bound_vars_that_can_be_moved ident_info clam
+    let_bound_vars_that_can_be_moved var_info clam
   in
   let clam =
     substitute_let_moveable let_bound_vars_that_can_be_moved
-      Ident.Map.empty clam
+      V.Map.empty clam
   in
-  let ident_info = make_ident_info clam in
-  let clam = un_anf ident_info Ident.Map.empty clam in
+  let var_info = make_var_info clam in
+  let clam = un_anf var_info V.Map.empty clam in
   if !Clflags.dump_clambda then begin
-    Format.eprintf "@.un-anf (%s):@ %a@." what Printclambda.clambda clam
+    Format.fprintf ppf_dump
+      "@.un-anf (%s):@ %a@." what Printclambda.clambda clam
   end;
   clam
diff --git a/asmcomp/un_anf.mli b/asmcomp/un_anf.mli
index 004704da..92ea06cd 100644
--- a/asmcomp/un_anf.mli
+++ b/asmcomp/un_anf.mli
@@ -17,6 +17,7 @@
 (** Expand ANF-like constructs so that pattern matches in [Cmmgen] will
     work correctly. *)
 val apply
-   : Clambda.ulambda
+  : ppf_dump:Format.formatter
+  -> Clambda.ulambda
   -> what:string
   -> Clambda.ulambda
diff --git a/asmcomp/x86_gas.ml b/asmcomp/x86_gas.ml
index f905dc33..6d2363a7 100644
--- a/asmcomp/x86_gas.ml
+++ b/asmcomp/x86_gas.ml
@@ -36,7 +36,7 @@ let arg_mem b {arch; typ=_; idx; scale; base; sym; displ} =
   begin match sym with
   | None ->
       if displ <> 0 || scale = 0 then
-        Buffer.add_string b (string_of_int displ)
+        Buffer.add_string b (Int.to_string displ)
   | Some s ->
       Buffer.add_string b s;
       opt_displ b displ
@@ -49,7 +49,7 @@ let arg_mem b {arch; typ=_; idx; scale; base; sym; displ} =
     end;
     if base != None || scale <> 1 then Buffer.add_char b ',';
     print_reg b string_of_register idx;
-    if scale <> 1 then bprintf b ",%s" (string_of_int scale);
+    if scale <> 1 then bprintf b ",%s" (Int.to_string scale);
     Buffer.add_char b ')'
   end
 
diff --git a/asmcomp/x86_proc.ml b/asmcomp/x86_proc.ml
index 897794b4..31e16a4f 100644
--- a/asmcomp/x86_proc.ml
+++ b/asmcomp/x86_proc.ml
@@ -249,8 +249,10 @@ let compile infile outfile =
                    Filename.quote outfile ^ " " ^ Filename.quote infile ^
                    (if !Clflags.verbose then "" else ">NUL"))
   else
-    Ccomp.command (Config.asm ^ " -o " ^
-                   Filename.quote outfile ^ " " ^ Filename.quote infile)
+    Ccomp.command (Config.asm ^ " " ^
+                   (String.concat " " (Misc.debug_prefix_map_flags ())) ^
+                   " -o " ^ Filename.quote outfile ^ " " ^
+                   Filename.quote infile)
 
 let assemble_file infile outfile =
   match !binary_content with
diff --git a/asmrun/.depend b/asmrun/.depend
deleted file mode 100644
index f80abd3f..00000000
--- a/asmrun/.depend
+++ /dev/null
@@ -1,1460 +0,0 @@
-startup_aux.$(O): startup_aux.c ../byterun/caml/backtrace.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/exec.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/callback.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/startup_aux.h
-startup.$(O): startup.c ../byterun/caml/callback.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
-  ../byterun/caml/custom.h ../byterun/caml/debugger.h \
-  ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
-  ../byterun/caml/io.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/printexc.h ../byterun/caml/stack.h \
-  ../byterun/caml/startup_aux.h ../byterun/caml/sys.h
-main.$(O): main.c ../byterun/caml/misc.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/sys.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-fail.$(O): fail.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h \
-  ../byterun/caml/gc.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/printexc.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/roots.h \
-  ../byterun/caml/callback.h
-roots.$(O): roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/globroots.h \
-  ../byterun/caml/stack.h
-signals.$(O): signals.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/roots.h ../byterun/caml/signals.h \
-  ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
-signals_asm.$(O): signals_asm.c ../byterun/caml/fail.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/signals.h \
-  ../byterun/caml/signals_machdep.h signals_osdep.h \
-  ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
-  ../byterun/caml/io.h
-misc.$(O): misc.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/version.h
-freelist.$(O): freelist.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/freelist.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h
-major_gc.$(O): major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/finalise.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
-  ../byterun/caml/weak.h
-minor_gc.$(O): minor_gc.c ../byterun/caml/custom.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/fail.h ../byterun/caml/finalise.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
-  ../byterun/caml/weak.h
-memory.$(O): memory.c ../byterun/caml/address_class.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/signals.h
-alloc.$(O): alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/stacks.h
-compare.$(O): compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/fail.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h
-ints.$(O): ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/intext.h ../byterun/caml/io.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-floats.$(O): floats.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/reverse.h ../byterun/caml/stacks.h
-str.$(O): str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-array.$(O): array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
-  ../byterun/caml/io.h ../byterun/caml/stack.h
-io.$(O): io.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/io.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/signals.h ../byterun/caml/sys.h
-extern.$(O): extern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
-  ../byterun/caml/io.h ../byterun/caml/md5.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/reverse.h
-intern.$(O): intern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
-  ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/md5.h \
-  ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/reverse.h
-hash.$(O): hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/custom.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/hash.h
-sys.$(O): sys.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
-  ../byterun/caml/fail.h ../byterun/caml/gc_ctrl.h ../byterun/caml/io.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h ../byterun/caml/stacks.h \
-  ../byterun/caml/sys.h ../byterun/caml/version.h \
-  ../byterun/caml/callback.h ../byterun/caml/startup_aux.h
-parsing.$(O): parsing.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/alloc.h
-gc_ctrl.$(O): gc_ctrl.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/backtrace.h \
-  ../byterun/caml/exec.h ../byterun/caml/compact.h \
-  ../byterun/caml/custom.h ../byterun/caml/fail.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/startup_aux.h
-md5.$(O): md5.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/md5.h ../byterun/caml/io.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/reverse.h
-obj.$(O): obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
-  ../byterun/caml/interp.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/prims.h ../byterun/caml/spacetime.h \
-  ../byterun/caml/io.h ../byterun/caml/stack.h
-lexing.$(O): lexing.c ../byterun/caml/fail.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-unix.$(O): unix.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/fail.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/signals.h ../byterun/caml/sys.h ../byterun/caml/io.h \
-  ../byterun/caml/alloc.h
-printexc.$(O): printexc.c ../byterun/caml/backtrace.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/exec.h ../byterun/caml/callback.h \
-  ../byterun/caml/debugger.h ../byterun/caml/fail.h \
-  ../byterun/caml/printexc.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h
-callback.$(O): callback.c ../byterun/caml/callback.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-weak.$(O): weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/weak.h
-compact.$(O): compact.c ../byterun/caml/address_class.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
-  ../byterun/caml/weak.h ../byterun/caml/compact.h
-finalise.$(O): finalise.c ../byterun/caml/callback.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/compact.h ../byterun/caml/fail.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h
-custom.$(O): custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h
-globroots.$(O): globroots.c ../byterun/caml/memory.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/gc.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/roots.h ../byterun/caml/globroots.h
-backtrace_prim.$(O): backtrace_prim.c ../byterun/caml/alloc.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
-  ../byterun/caml/backtrace_prim.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/stack.h
-backtrace.$(O): backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/backtrace.h \
-  ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.h \
-  ../byterun/caml/fail.h
-natdynlink.$(O): natdynlink.c ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/stack.h \
-  ../byterun/caml/callback.h ../byterun/caml/alloc.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/fail.h ../byterun/caml/signals.h \
-  ../byterun/caml/hooks.h
-debugger.$(O): debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-meta.$(O): meta.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/fix_code.h ../byterun/caml/interp.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/prims.h ../byterun/caml/stacks.h
-dynlink.$(O): dynlink.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
-  ../byterun/caml/signals.h
-clambda_checks.$(O): clambda_checks.c ../byterun/caml/mlvalues.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h
-spacetime.$(O): spacetime.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/backtrace_prim.h \
-  ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
-  ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
-  ../byterun/caml/io.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/roots.h \
-  ../byterun/caml/signals.h ../byterun/caml/stack.h \
-  ../byterun/caml/sys.h ../byterun/caml/spacetime.h
-spacetime_snapshot.$(O): spacetime_snapshot.c ../byterun/caml/alloc.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/backtrace_prim.h ../byterun/caml/backtrace.h \
-  ../byterun/caml/exec.h ../byterun/caml/custom.h ../byterun/caml/fail.h \
-  ../byterun/caml/gc.h ../byterun/caml/gc_ctrl.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/roots.h \
-  ../byterun/caml/signals.h ../byterun/caml/stack.h \
-  ../byterun/caml/sys.h ../byterun/caml/spacetime.h
-afl.$(O): afl.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-bigarray.$(O): bigarray.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/bigarray.h \
-  ../byterun/caml/custom.h ../byterun/caml/fail.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/hash.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h
-startup_aux.p.$(O): startup_aux.c ../byterun/caml/backtrace.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/exec.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/callback.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/startup_aux.h
-startup.p.$(O): startup.c ../byterun/caml/callback.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
-  ../byterun/caml/custom.h ../byterun/caml/debugger.h \
-  ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
-  ../byterun/caml/io.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/printexc.h ../byterun/caml/stack.h \
-  ../byterun/caml/startup_aux.h ../byterun/caml/sys.h
-main.p.$(O): main.c ../byterun/caml/misc.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/sys.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-fail.p.$(O): fail.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h \
-  ../byterun/caml/gc.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/printexc.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/roots.h \
-  ../byterun/caml/callback.h
-roots.p.$(O): roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/globroots.h \
-  ../byterun/caml/stack.h
-signals.p.$(O): signals.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/roots.h ../byterun/caml/signals.h \
-  ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
-signals_asm.p.$(O): signals_asm.c ../byterun/caml/fail.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/signals.h \
-  ../byterun/caml/signals_machdep.h signals_osdep.h \
-  ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
-  ../byterun/caml/io.h
-misc.p.$(O): misc.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/version.h
-freelist.p.$(O): freelist.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/freelist.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h
-major_gc.p.$(O): major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/finalise.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
-  ../byterun/caml/weak.h
-minor_gc.p.$(O): minor_gc.c ../byterun/caml/custom.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/fail.h ../byterun/caml/finalise.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
-  ../byterun/caml/weak.h
-memory.p.$(O): memory.c ../byterun/caml/address_class.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/signals.h
-alloc.p.$(O): alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/stacks.h
-compare.p.$(O): compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/fail.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h
-ints.p.$(O): ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/intext.h ../byterun/caml/io.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-floats.p.$(O): floats.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/reverse.h ../byterun/caml/stacks.h
-str.p.$(O): str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-array.p.$(O): array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
-  ../byterun/caml/io.h ../byterun/caml/stack.h
-io.p.$(O): io.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/io.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/signals.h ../byterun/caml/sys.h
-extern.p.$(O): extern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
-  ../byterun/caml/io.h ../byterun/caml/md5.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/reverse.h
-intern.p.$(O): intern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
-  ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/md5.h \
-  ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/reverse.h
-hash.p.$(O): hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/custom.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/hash.h
-sys.p.$(O): sys.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
-  ../byterun/caml/fail.h ../byterun/caml/gc_ctrl.h ../byterun/caml/io.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h ../byterun/caml/stacks.h \
-  ../byterun/caml/sys.h ../byterun/caml/version.h \
-  ../byterun/caml/callback.h ../byterun/caml/startup_aux.h
-parsing.p.$(O): parsing.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/alloc.h
-gc_ctrl.p.$(O): gc_ctrl.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/backtrace.h \
-  ../byterun/caml/exec.h ../byterun/caml/compact.h \
-  ../byterun/caml/custom.h ../byterun/caml/fail.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/startup_aux.h
-md5.p.$(O): md5.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/md5.h ../byterun/caml/io.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/reverse.h
-obj.p.$(O): obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
-  ../byterun/caml/interp.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/prims.h ../byterun/caml/spacetime.h \
-  ../byterun/caml/io.h ../byterun/caml/stack.h
-lexing.p.$(O): lexing.c ../byterun/caml/fail.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-unix.p.$(O): unix.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/fail.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/signals.h ../byterun/caml/sys.h ../byterun/caml/io.h \
-  ../byterun/caml/alloc.h
-printexc.p.$(O): printexc.c ../byterun/caml/backtrace.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/exec.h ../byterun/caml/callback.h \
-  ../byterun/caml/debugger.h ../byterun/caml/fail.h \
-  ../byterun/caml/printexc.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h
-callback.p.$(O): callback.c ../byterun/caml/callback.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-weak.p.$(O): weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/weak.h
-compact.p.$(O): compact.c ../byterun/caml/address_class.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
-  ../byterun/caml/weak.h ../byterun/caml/compact.h
-finalise.p.$(O): finalise.c ../byterun/caml/callback.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/compact.h ../byterun/caml/fail.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h
-custom.p.$(O): custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h
-globroots.p.$(O): globroots.c ../byterun/caml/memory.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/gc.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/roots.h ../byterun/caml/globroots.h
-backtrace_prim.p.$(O): backtrace_prim.c ../byterun/caml/alloc.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
-  ../byterun/caml/backtrace_prim.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/stack.h
-backtrace.p.$(O): backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/backtrace.h \
-  ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.h \
-  ../byterun/caml/fail.h
-natdynlink.p.$(O): natdynlink.c ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/stack.h \
-  ../byterun/caml/callback.h ../byterun/caml/alloc.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/fail.h ../byterun/caml/signals.h \
-  ../byterun/caml/hooks.h
-debugger.p.$(O): debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-meta.p.$(O): meta.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/fix_code.h ../byterun/caml/interp.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/prims.h ../byterun/caml/stacks.h
-dynlink.p.$(O): dynlink.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
-  ../byterun/caml/signals.h
-clambda_checks.p.$(O): clambda_checks.c ../byterun/caml/mlvalues.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h
-spacetime.p.$(O): spacetime.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/backtrace_prim.h \
-  ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
-  ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
-  ../byterun/caml/io.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/roots.h \
-  ../byterun/caml/signals.h ../byterun/caml/stack.h \
-  ../byterun/caml/sys.h ../byterun/caml/spacetime.h
-spacetime_snapshot.p.$(O): spacetime_snapshot.c ../byterun/caml/alloc.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/backtrace_prim.h ../byterun/caml/backtrace.h \
-  ../byterun/caml/exec.h ../byterun/caml/custom.h ../byterun/caml/fail.h \
-  ../byterun/caml/gc.h ../byterun/caml/gc_ctrl.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/roots.h \
-  ../byterun/caml/signals.h ../byterun/caml/stack.h \
-  ../byterun/caml/sys.h ../byterun/caml/spacetime.h
-afl.p.$(O): afl.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-bigarray.p.$(O): bigarray.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/bigarray.h \
-  ../byterun/caml/custom.h ../byterun/caml/fail.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/hash.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h
-startup_aux.d.$(O): startup_aux.c ../byterun/caml/backtrace.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/exec.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/callback.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/startup_aux.h
-startup.d.$(O): startup.c ../byterun/caml/callback.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
-  ../byterun/caml/custom.h ../byterun/caml/debugger.h \
-  ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
-  ../byterun/caml/io.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/printexc.h ../byterun/caml/stack.h \
-  ../byterun/caml/startup_aux.h ../byterun/caml/sys.h
-main.d.$(O): main.c ../byterun/caml/misc.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/sys.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-fail.d.$(O): fail.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h \
-  ../byterun/caml/gc.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/printexc.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/roots.h \
-  ../byterun/caml/callback.h
-roots.d.$(O): roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/globroots.h \
-  ../byterun/caml/stack.h
-signals.d.$(O): signals.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/roots.h ../byterun/caml/signals.h \
-  ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
-signals_asm.d.$(O): signals_asm.c ../byterun/caml/fail.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/signals.h \
-  ../byterun/caml/signals_machdep.h signals_osdep.h \
-  ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
-  ../byterun/caml/io.h
-misc.d.$(O): misc.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/version.h
-freelist.d.$(O): freelist.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/freelist.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h
-major_gc.d.$(O): major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/finalise.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
-  ../byterun/caml/weak.h
-minor_gc.d.$(O): minor_gc.c ../byterun/caml/custom.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/fail.h ../byterun/caml/finalise.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
-  ../byterun/caml/weak.h
-memory.d.$(O): memory.c ../byterun/caml/address_class.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/signals.h
-alloc.d.$(O): alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/stacks.h
-compare.d.$(O): compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/fail.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h
-ints.d.$(O): ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/intext.h ../byterun/caml/io.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-floats.d.$(O): floats.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/reverse.h ../byterun/caml/stacks.h
-str.d.$(O): str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-array.d.$(O): array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
-  ../byterun/caml/io.h ../byterun/caml/stack.h
-io.d.$(O): io.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/io.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/signals.h ../byterun/caml/sys.h
-extern.d.$(O): extern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
-  ../byterun/caml/io.h ../byterun/caml/md5.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/reverse.h
-intern.d.$(O): intern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
-  ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/md5.h \
-  ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/reverse.h
-hash.d.$(O): hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/custom.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/hash.h
-sys.d.$(O): sys.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
-  ../byterun/caml/fail.h ../byterun/caml/gc_ctrl.h ../byterun/caml/io.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h ../byterun/caml/stacks.h \
-  ../byterun/caml/sys.h ../byterun/caml/version.h \
-  ../byterun/caml/callback.h ../byterun/caml/startup_aux.h
-parsing.d.$(O): parsing.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/alloc.h
-gc_ctrl.d.$(O): gc_ctrl.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/backtrace.h \
-  ../byterun/caml/exec.h ../byterun/caml/compact.h \
-  ../byterun/caml/custom.h ../byterun/caml/fail.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/startup_aux.h
-md5.d.$(O): md5.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/md5.h ../byterun/caml/io.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/reverse.h
-obj.d.$(O): obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
-  ../byterun/caml/interp.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/prims.h ../byterun/caml/spacetime.h \
-  ../byterun/caml/io.h ../byterun/caml/stack.h
-lexing.d.$(O): lexing.c ../byterun/caml/fail.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-unix.d.$(O): unix.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/fail.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/signals.h ../byterun/caml/sys.h ../byterun/caml/io.h \
-  ../byterun/caml/alloc.h
-printexc.d.$(O): printexc.c ../byterun/caml/backtrace.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/exec.h ../byterun/caml/callback.h \
-  ../byterun/caml/debugger.h ../byterun/caml/fail.h \
-  ../byterun/caml/printexc.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h
-callback.d.$(O): callback.c ../byterun/caml/callback.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-weak.d.$(O): weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/weak.h
-compact.d.$(O): compact.c ../byterun/caml/address_class.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
-  ../byterun/caml/weak.h ../byterun/caml/compact.h
-finalise.d.$(O): finalise.c ../byterun/caml/callback.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/compact.h ../byterun/caml/fail.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h
-custom.d.$(O): custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h
-globroots.d.$(O): globroots.c ../byterun/caml/memory.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/gc.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/roots.h ../byterun/caml/globroots.h
-backtrace_prim.d.$(O): backtrace_prim.c ../byterun/caml/alloc.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
-  ../byterun/caml/backtrace_prim.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/stack.h
-backtrace.d.$(O): backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/backtrace.h \
-  ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.h \
-  ../byterun/caml/fail.h
-natdynlink.d.$(O): natdynlink.c ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/stack.h \
-  ../byterun/caml/callback.h ../byterun/caml/alloc.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/fail.h ../byterun/caml/signals.h \
-  ../byterun/caml/hooks.h
-debugger.d.$(O): debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-meta.d.$(O): meta.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/fix_code.h ../byterun/caml/interp.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/prims.h ../byterun/caml/stacks.h
-dynlink.d.$(O): dynlink.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
-  ../byterun/caml/signals.h
-clambda_checks.d.$(O): clambda_checks.c ../byterun/caml/mlvalues.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h
-spacetime.d.$(O): spacetime.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/backtrace_prim.h \
-  ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
-  ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
-  ../byterun/caml/io.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/roots.h \
-  ../byterun/caml/signals.h ../byterun/caml/stack.h \
-  ../byterun/caml/sys.h ../byterun/caml/spacetime.h
-spacetime_snapshot.d.$(O): spacetime_snapshot.c ../byterun/caml/alloc.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/backtrace_prim.h ../byterun/caml/backtrace.h \
-  ../byterun/caml/exec.h ../byterun/caml/custom.h ../byterun/caml/fail.h \
-  ../byterun/caml/gc.h ../byterun/caml/gc_ctrl.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/roots.h \
-  ../byterun/caml/signals.h ../byterun/caml/stack.h \
-  ../byterun/caml/sys.h ../byterun/caml/spacetime.h
-afl.d.$(O): afl.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-bigarray.d.$(O): bigarray.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/bigarray.h \
-  ../byterun/caml/custom.h ../byterun/caml/fail.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/hash.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h
-startup_aux.i.$(O): startup_aux.c ../byterun/caml/backtrace.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/exec.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/callback.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/startup_aux.h
-startup.i.$(O): startup.c ../byterun/caml/callback.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
-  ../byterun/caml/custom.h ../byterun/caml/debugger.h \
-  ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
-  ../byterun/caml/io.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/printexc.h ../byterun/caml/stack.h \
-  ../byterun/caml/startup_aux.h ../byterun/caml/sys.h
-main.i.$(O): main.c ../byterun/caml/misc.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/sys.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-fail.i.$(O): fail.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h \
-  ../byterun/caml/gc.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/printexc.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/roots.h \
-  ../byterun/caml/callback.h
-roots.i.$(O): roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/globroots.h \
-  ../byterun/caml/stack.h
-signals.i.$(O): signals.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/roots.h ../byterun/caml/signals.h \
-  ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
-signals_asm.i.$(O): signals_asm.c ../byterun/caml/fail.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/signals.h \
-  ../byterun/caml/signals_machdep.h signals_osdep.h \
-  ../byterun/caml/stack.h ../byterun/caml/spacetime.h \
-  ../byterun/caml/io.h
-misc.i.$(O): misc.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/version.h
-freelist.i.$(O): freelist.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/freelist.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h
-major_gc.i.$(O): major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/finalise.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
-  ../byterun/caml/weak.h
-minor_gc.i.$(O): minor_gc.c ../byterun/caml/custom.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/fail.h ../byterun/caml/finalise.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
-  ../byterun/caml/weak.h
-memory.i.$(O): memory.c ../byterun/caml/address_class.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/signals.h
-alloc.i.$(O): alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/stacks.h
-compare.i.$(O): compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/fail.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h
-ints.i.$(O): ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/intext.h ../byterun/caml/io.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-floats.i.$(O): floats.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/reverse.h ../byterun/caml/stacks.h
-str.i.$(O): str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-array.i.$(O): array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h ../byterun/caml/spacetime.h \
-  ../byterun/caml/io.h ../byterun/caml/stack.h
-io.i.$(O): io.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/io.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/signals.h ../byterun/caml/sys.h
-extern.i.$(O): extern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
-  ../byterun/caml/io.h ../byterun/caml/md5.h ../byterun/caml/memory.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/reverse.h
-intern.i.$(O): intern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/callback.h \
-  ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/md5.h \
-  ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/reverse.h
-hash.i.$(O): hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/custom.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/hash.h
-sys.i.$(O): sys.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
-  ../byterun/caml/fail.h ../byterun/caml/gc_ctrl.h ../byterun/caml/io.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h ../byterun/caml/stacks.h \
-  ../byterun/caml/sys.h ../byterun/caml/version.h \
-  ../byterun/caml/callback.h ../byterun/caml/startup_aux.h
-parsing.i.$(O): parsing.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/alloc.h
-gc_ctrl.i.$(O): gc_ctrl.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/backtrace.h \
-  ../byterun/caml/exec.h ../byterun/caml/compact.h \
-  ../byterun/caml/custom.h ../byterun/caml/fail.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
-  ../byterun/caml/stack.h ../byterun/caml/startup_aux.h
-md5.i.$(O): md5.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/md5.h ../byterun/caml/io.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/reverse.h
-obj.i.$(O): obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
-  ../byterun/caml/interp.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/prims.h ../byterun/caml/spacetime.h \
-  ../byterun/caml/io.h ../byterun/caml/stack.h
-lexing.i.$(O): lexing.c ../byterun/caml/fail.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-unix.i.$(O): unix.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/fail.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/signals.h ../byterun/caml/sys.h ../byterun/caml/io.h \
-  ../byterun/caml/alloc.h
-printexc.i.$(O): printexc.c ../byterun/caml/backtrace.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/exec.h ../byterun/caml/callback.h \
-  ../byterun/caml/debugger.h ../byterun/caml/fail.h \
-  ../byterun/caml/printexc.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h
-callback.i.$(O): callback.c ../byterun/caml/callback.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-weak.i.$(O): weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/weak.h
-compact.i.$(O): compact.c ../byterun/caml/address_class.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
-  ../byterun/caml/weak.h ../byterun/caml/compact.h
-finalise.i.$(O): finalise.c ../byterun/caml/callback.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/m.h ../byterun/caml/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/compact.h ../byterun/caml/fail.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h
-custom.i.$(O): custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h
-globroots.i.$(O): globroots.c ../byterun/caml/memory.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/gc.h ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/roots.h ../byterun/caml/globroots.h
-backtrace_prim.i.$(O): backtrace_prim.c ../byterun/caml/alloc.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
-  ../byterun/caml/backtrace_prim.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/stack.h
-backtrace.i.$(O): backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/backtrace.h \
-  ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.h \
-  ../byterun/caml/fail.h
-natdynlink.i.$(O): natdynlink.c ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/stack.h \
-  ../byterun/caml/callback.h ../byterun/caml/alloc.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/osdeps.h \
-  ../byterun/caml/fail.h ../byterun/caml/signals.h \
-  ../byterun/caml/hooks.h
-debugger.i.$(O): debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-meta.i.$(O): meta.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
-  ../byterun/caml/fix_code.h ../byterun/caml/interp.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/prims.h ../byterun/caml/stacks.h
-dynlink.i.$(O): dynlink.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
-  ../byterun/caml/signals.h
-clambda_checks.i.$(O): clambda_checks.c ../byterun/caml/mlvalues.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/misc.h
-spacetime.i.$(O): spacetime.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/backtrace_prim.h \
-  ../byterun/caml/backtrace.h ../byterun/caml/exec.h \
-  ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
-  ../byterun/caml/io.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/roots.h \
-  ../byterun/caml/signals.h ../byterun/caml/stack.h \
-  ../byterun/caml/sys.h ../byterun/caml/spacetime.h
-spacetime_snapshot.i.$(O): spacetime_snapshot.c ../byterun/caml/alloc.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/backtrace_prim.h ../byterun/caml/backtrace.h \
-  ../byterun/caml/exec.h ../byterun/caml/custom.h ../byterun/caml/fail.h \
-  ../byterun/caml/gc.h ../byterun/caml/gc_ctrl.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/roots.h \
-  ../byterun/caml/signals.h ../byterun/caml/stack.h \
-  ../byterun/caml/sys.h ../byterun/caml/spacetime.h
-afl.i.$(O): afl.c ../byterun/caml/config.h ../byterun/caml/m.h \
-  ../byterun/caml/s.h ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
-bigarray.i.$(O): bigarray.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/bigarray.h \
-  ../byterun/caml/custom.h ../byterun/caml/fail.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/hash.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/signals.h
diff --git a/asmrun/Makefile b/asmrun/Makefile
deleted file mode 100644
index f275e2a0..00000000
--- a/asmrun/Makefile
+++ /dev/null
@@ -1,203 +0,0 @@
-#**************************************************************************
-#*                                                                        *
-#*                                 OCaml                                  *
-#*                                                                        *
-#*            Xavier Leroy, projet Cristal, INRIA Rocquencourt            *
-#*                                                                        *
-#*   Copyright 1999 Institut National de Recherche en Informatique et     *
-#*     en Automatique.                                                    *
-#*                                                                        *
-#*   All rights reserved.  This file is distributed under the terms of    *
-#*   the GNU Lesser General Public License version 2.1, with the          *
-#*   special exception on linking described in the file LICENSE.          *
-#*                                                                        *
-#**************************************************************************
-
-include ../config/Makefile
-include ../Makefile.common
-
-LINKEDFILES=misc.c freelist.c major_gc.c minor_gc.c memory.c alloc.c array.c \
-  compare.c ints.c floats.c str.c io.c extern.c intern.c hash.c sys.c \
-  parsing.c gc_ctrl.c md5.c obj.c lexing.c printexc.c callback.c \
-  weak.c compact.c finalise.c meta.c custom.c main.c globroots.c \
-  $(UNIX_OR_WIN32).c dynlink.c signals.c debugger.c startup_aux.c \
-  backtrace.c afl.c bigarray.c
-
-# The following variable stores the list of files for which dependencies
-# should be computed. It includes even the files that won't actually be
-# compiled on the platform where make depend is run
-sources := $(LINKEDFILES)
-
-ifeq "$(UNIX_OR_WIN32)" "win32"
-LN = cp
-sources += ../byterun/unix.c
-else
-LN = ln -s
-sources += ../byterun/win32.c
-endif
-
-CPPFLAGS += -I../byterun -DNATIVE_CODE -DTARGET_$(ARCH)
-
-ifeq "$(UNIX_OR_WIN32)" "unix"
-CPPFLAGS += -DMODEL_$(MODEL)
-endif
-
-CPPFLAGS += -DSYS_$(SYSTEM) $(IFLEXDIR) $(LIBUNWIND_INCLUDE_FLAGS)
-
-ifneq "$(CCOMPTYPE)" "msvc"
-CFLAGS += -g
-endif
-
-ifeq "$(TOOLCHAIN)" "msvc"
-DFLAGS = $(CFLAGS) -DDEBUG
-PFLAGS=$(CFLAGS) -DPROFILING $(NATIVECCPROFOPTS)
-ASMOBJS=$(ARCH)nt.$(O)
-ASMFLAGS=
-ifeq ($(WITH_SPACETIME),true)
-ASMFLAGS=/DWITH_SPACETIME
-endif
-else
-DFLAGS = $(CFLAGS) -g -DDEBUG
-PFLAGS=$(CFLAGS) -pg -DPROFILING $(NATIVECCPROFOPTS)
-ASMOBJS=$(ARCH).$(O)
-endif
-
-IFLAGS=$(CFLAGS) -DCAML_INSTR
-PICFLAGS=$(CFLAGS) $(SHAREDCCCOMPOPTS)
-
-ASPPFLAGS = -DSYS_$(SYSTEM) -I../byterun
-ifeq "$(UNIX_OR_WIN32)" "unix"
-ASPPFLAGS += -DMODEL_$(MODEL)
-endif
-
-COBJS=startup_aux.$(O) startup.$(O) main.$(O) fail.$(O)		\
-  roots.$(O) signals.$(O) signals_asm.$(O) misc.$(O) freelist.$(O)	\
-  major_gc.$(O) minor_gc.$(O) memory.$(O) alloc.$(O) compare.$(O)	\
-  ints.$(O) floats.$(O) str.$(O) array.$(O) io.$(O) extern.$(O)		\
-  intern.$(O) hash.$(O) sys.$(O) parsing.$(O) gc_ctrl.$(O)		\
-  md5.$(O) obj.$(O) lexing.$(O) $(UNIX_OR_WIN32).$(O)	\
-  printexc.$(O) callback.$(O) weak.$(O) compact.$(O) finalise.$(O)	\
-  custom.$(O) globroots.$(O) backtrace_prim.$(O) backtrace.$(O)		\
-  natdynlink.$(O) debugger.$(O) meta.$(O) dynlink.$(O)			\
-  clambda_checks.$(O) spacetime.$(O) spacetime_snapshot.$(O)		\
-  afl.$(O) bigarray.$(O)
-
-OBJS=$(COBJS) $(ASMOBJS)
-
-DOBJS=$(COBJS:.$(O)=.d.$(O)) $(ASMOBJS)
-IOBJS=$(COBJS:.$(O)=.i.$(O)) $(ASMOBJS)
-POBJS=$(COBJS:.$(O)=.p.$(O)) $(ASMOBJS:.$(O)=.p.$(O))
-PICOBJS=$(COBJS:.$(O)=.pic.$(O)) $(ASMOBJS:.$(O)=.pic.$(O))
-
-TARGETS_A = libasmrun.$(A)
-TARGETS_SO=
-
-ifeq "$(RUNTIMED)" "true"
-TARGETS_A += libasmrund.$(A)
-endif
-
-ifeq "$(RUNTIMEI)" "true"
-TARGETS_A += libasmruni.$(A)
-endif
-
-ifeq "$(PROFILING)" "true"
-TARGETS_A += libasmrunp.$(A)
-endif
-
-ifeq "$(UNIX_OR_WIN32)" "unix"
-ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true"
-TARGETS_A += libasmrun_pic.$(A)
-TARGETS_SO += libasmrun_shared.$(SO)
-endif
-endif
-
-.PHONY: all
-all: $(TARGETS_A) $(TARGETS_SO)
-
-libasmrun.$(A): $(OBJS)
-	$(call MKLIB,$@, $^)
-
-libasmrund.$(A): $(DOBJS)
-	$(call MKLIB,$@, $^)
-
-libasmruni.$(A): $(IOBJS)
-	$(call MKLIB,$@, $^)
-
-libasmrunp.$(A): $(POBJS)
-	$(call MKLIB,$@, $^)
-
-libasmrun_pic.$(A): $(PICOBJS)
-	$(call MKLIB,$@, $^)
-
-libasmrun_shared.$(SO): $(PICOBJS)
-	$(MKDLL) -o $@ $^ $(NATIVECCLIBS)
-
-.PHONY: install
-install:
-	$(INSTALL_DATA) $(TARGETS_A) "$(INSTALL_LIBDIR)"
-	if test -n "$(TARGETS_SO)"; then \
-	  $(INSTALL_PROG) $(TARGETS_SO) "$(INSTALL_LIBDIR)"; \
-	fi
-
-$(LINKEDFILES): %.c: ../byterun/%.c
-	$(LN) $< $@
-
-%.d.$(O): %.c
-	$(CC) -c $(DFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $<
-
-%.i.$(O): %.c
-	$(CC) -c $(IFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $<
-
-%.p.$(O): %.c
-	$(CC) -c $(PFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $<
-
-%.pic.$(O): %.c
-	$(CC) -c $(PICFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $<
-
-%.$(O): %.c
-	$(CC) -c $(CFLAGS) $(CPPFLAGS) $<
-
-%.o: %.S
-	$(ASPP) $(ASPPFLAGS) -o $@ $< || \
-	{ echo "If your assembler produced syntax errors, it is probably";\
-          echo "unhappy with the preprocessor. Check your assembler, or";\
-          echo "try producing $*.o by hand.";\
-          exit 2; }
-
-%.p.o: %.S
-	$(ASPP) $(ASPPFLAGS) $(ASPPPROFFLAGS) -o $@ $<
-
-%.pic.o: %.S
-	$(ASPP) $(ASPPFLAGS) $(SHAREDCCCOMPOPTS) -o $@ $<
-
-%.obj: %.asm
-	$(ASM)$@ $(ASMFLAGS) $<
-
-%.pic.obj: %.asm
-	$(ASM)$@ $(ASMFLAGS) $<
-
-.PHONY: clean
-clean:
-	rm -f $(LINKEDFILES)
-	rm -f *.$(O) *.$(A) *.$(SO)
-
-.PHONY: distclean
-distclean: clean
-	rm -r *~
-
-.PHONY: depend
-ifeq "$(TOOLCHAIN)" "msvc"
-depend:
-	$(error Dependencies cannot be regenerated using the MSVC ports)
-else
-depend: $(COBJS:.$(O)=.c) $(sources)
-	$(CC) -MM $(CFLAGS) $(CPPFLAGS) $^ | sed -e 's/\.o/.$$(O)/' > .depend
-	$(CC) -MM $(PFLAGS) $(CPPFLAGS) $^ | sed -e 's/\.o/.p.$$(O)/' \
-	  >> .depend
-	$(CC) -MM $(DFLAGS) $(CPPFLAGS) $^ | sed -e 's/\.o/.d.$$(O)/' \
-	  >> .depend
-	$(CC) -MM $(IFLAGS) $(CPPFLAGS) $^ | sed -e 's/\.o/.i.$$(O)/' \
-	  >> .depend
-endif
-
-include .depend
diff --git a/asmrun/Makefile.nt b/asmrun/Makefile.nt
deleted file mode 100644
index ed9900bb..00000000
--- a/asmrun/Makefile.nt
+++ /dev/null
@@ -1,16 +0,0 @@
-#**************************************************************************
-#*                                                                        *
-#*                                 OCaml                                  *
-#*                                                                        *
-#*            Xavier Leroy, projet Cristal, INRIA Rocquencourt            *
-#*                                                                        *
-#*   Copyright 1999 Institut National de Recherche en Informatique et     *
-#*     en Automatique.                                                    *
-#*                                                                        *
-#*   All rights reserved.  This file is distributed under the terms of    *
-#*   the GNU Lesser General Public License version 2.1, with the          *
-#*   special exception on linking described in the file LICENSE.          *
-#*                                                                        *
-#**************************************************************************
-
-include Makefile
diff --git a/asmrun/amd64.S b/asmrun/amd64.S
deleted file mode 100644
index 3e3bf83e..00000000
--- a/asmrun/amd64.S
+++ /dev/null
@@ -1,741 +0,0 @@
-/**************************************************************************/
-/*                                                                        */
-/*                                 OCaml                                  */
-/*                                                                        */
-/*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           */
-/*                                                                        */
-/*   Copyright 2003 Institut National de Recherche en Informatique et     */
-/*     en Automatique.                                                    */
-/*                                                                        */
-/*   All rights reserved.  This file is distributed under the terms of    */
-/*   the GNU Lesser General Public License version 2.1, with the          */
-/*   special exception on linking described in the file LICENSE.          */
-/*                                                                        */
-/**************************************************************************/
-
-/* Asm part of the runtime system, AMD64 processor */
-/* Must be preprocessed by cpp */
-
-/* PIC mode support based on contribution by Paul Stravers (see PR#4795) */
-
-#include "caml/m.h"
-
-#if defined(SYS_macosx)
-
-#define LBL(x) L##x
-#define G(r) _##r
-#define GREL(r) _##r@GOTPCREL
-#define GCALL(r) _##r
-#define FUNCTION_ALIGN 2
-#define EIGHT_ALIGN 3
-#define SIXTEEN_ALIGN 4
-#define FUNCTION(name) \
-        .globl name; \
-        .align FUNCTION_ALIGN; \
-        name:
-
-#elif defined(SYS_mingw64) || defined(SYS_cygwin)
-
-#define LBL(x) .L##x
-#define G(r) r
-#undef  GREL
-#define GCALL(r) r
-#define FUNCTION_ALIGN 4
-#define EIGHT_ALIGN 8
-#define SIXTEEN_ALIGN 16
-#define FUNCTION(name) \
-        .globl name; \
-        .align FUNCTION_ALIGN; \
-        name:
-
-#else
-
-#define LBL(x) .L##x
-#define G(r) r
-#define GREL(r) r@GOTPCREL
-#define GCALL(r) r@PLT
-#define FUNCTION_ALIGN 4
-#define EIGHT_ALIGN 8
-#define SIXTEEN_ALIGN 16
-#define FUNCTION(name) \
-        .globl name; \
-        .type name,@function; \
-        .align FUNCTION_ALIGN; \
-        name:
-
-#endif
-
-#ifdef ASM_CFI_SUPPORTED
-#define CFI_STARTPROC .cfi_startproc
-#define CFI_ENDPROC .cfi_endproc
-#define CFI_ADJUST(n) .cfi_adjust_cfa_offset n
-#define CFI_OFFSET(r, n) .cfi_offset r, n
-#define CFI_SAME_VALUE(r) .cfi_same_value r
-#else
-#define CFI_STARTPROC
-#define CFI_ENDPROC
-#define CFI_ADJUST(n)
-#define CFI_OFFSET(r, n)
-#define CFI_SAME_VALUE(r)
-#endif
-
-#ifdef WITH_FRAME_POINTERS
-
-#define ENTER_FUNCTION \
-        pushq   %rbp; CFI_ADJUST(8); \
-        movq    %rsp, %rbp
-#define LEAVE_FUNCTION \
-        popq    %rbp; CFI_ADJUST(-8);
-
-#else
-
-#define ENTER_FUNCTION \
-        subq    $8, %rsp; CFI_ADJUST (8);
-#define LEAVE_FUNCTION \
-        addq    $8, %rsp; CFI_ADJUST (-8);
-
-#endif
-
-#if defined(__PIC__) && !defined(SYS_mingw64) && !defined(SYS_cygwin)
-
-/* Position-independent operations on global variables. */
-
-/* Store [srcreg] in global [dstlabel].  Clobbers %r11. */
-#define STORE_VAR(srcreg,dstlabel) \
-        movq    GREL(dstlabel)(%rip), %r11 ; \
-        movq    srcreg, (%r11)
-
-#define STORE_VAR32(srcreg,dstlabel) \
-        movq    GREL(dstlabel)(%rip), %r11 ; \
-        movl    srcreg, (%r11)
-
-/* Load global [srclabel] in register [dstreg].  Clobbers %r11. */
-#define LOAD_VAR(srclabel,dstreg) \
-        movq    GREL(srclabel)(%rip), %r11 ; \
-        movq    (%r11), dstreg
-
-/* Compare global [label] with register [reg].  Clobbers %rax. */
-#define CMP_VAR(label,reg) \
-        movq    GREL(label)(%rip), %rax ; \
-        cmpq    (%rax), reg
-
-/* Test 32-bit global [label] against mask [imm].  Clobbers %r11. */
-#define TESTL_VAR(imm,label) \
-        movq    GREL(label)(%rip), %r11 ; \
-        testl   imm, (%r11)
-
-/* Push global [label] on stack.  Clobbers %r11. */
-#define PUSH_VAR(srclabel) \
-        movq    GREL(srclabel)(%rip), %r11 ; \
-        pushq   (%r11); CFI_ADJUST (8)
-
-/* Pop global [label] off stack.  Clobbers %r11. */
-#define POP_VAR(dstlabel) \
-        movq    GREL(dstlabel)(%rip), %r11 ; \
-        popq    (%r11);  CFI_ADJUST (-8)
-
-/* Record lowest stack address and return address.  Clobbers %rax. */
-#define RECORD_STACK_FRAME(OFFSET) \
-        pushq   %r11 ; CFI_ADJUST(8); \
-        movq    8+OFFSET(%rsp), %rax ; \
-        STORE_VAR(%rax,caml_last_return_address) ; \
-        leaq    16+OFFSET(%rsp), %rax ; \
-        STORE_VAR(%rax,caml_bottom_of_stack) ; \
-        popq    %r11; CFI_ADJUST(-8)
-
-/* Load address of global [label] in register [dst]. */
-#define LEA_VAR(label,dst) \
-        movq    GREL(label)(%rip), dst
-
-#else
-
-/* Non-PIC operations on global variables.  Slightly faster. */
-
-#define STORE_VAR(srcreg,dstlabel) \
-        movq    srcreg, G(dstlabel)(%rip)
-
-#define STORE_VAR32(srcreg,dstlabel) \
-        movl    srcreg, G(dstlabel)(%rip)
-
-#define LOAD_VAR(srclabel,dstreg) \
-        movq    G(srclabel)(%rip), dstreg
-
-#define CMP_VAR(label,reg) \
-        cmpq    G(label)(%rip), %r15
-
-#define TESTL_VAR(imm,label) \
-        testl   imm, G(label)(%rip)
-
-#define PUSH_VAR(srclabel) \
-        pushq   G(srclabel)(%rip) ; CFI_ADJUST(8)
-
-#define POP_VAR(dstlabel) \
-        popq    G(dstlabel)(%rip); CFI_ADJUST(-8)
-
-#define RECORD_STACK_FRAME(OFFSET) \
-        movq    OFFSET(%rsp), %rax ; \
-        STORE_VAR(%rax,caml_last_return_address) ; \
-        leaq    8+OFFSET(%rsp), %rax ; \
-        STORE_VAR(%rax,caml_bottom_of_stack)
-
-#define LEA_VAR(label,dst) \
-        leaq    G(label)(%rip), dst
-#endif
-
-/* Save and restore all callee-save registers on stack.
-   Keep the stack 16-aligned. */
-
-#if defined(SYS_mingw64) || defined(SYS_cygwin)
-
-/* Win64 API: callee-save regs are rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15 */
-
-#define PUSH_CALLEE_SAVE_REGS \
-        pushq   %rbx; CFI_ADJUST (8); CFI_OFFSET(rbx, -16); \
-        pushq   %rbp; CFI_ADJUST (8); CFI_OFFSET(rbp, -24); \
-                      /* Allows debugger to walk the stack */ \
-        pushq   %rsi; CFI_ADJUST (8); CFI_OFFSET(rsi, -32); \
-        pushq   %rdi; CFI_ADJUST (8); CFI_OFFSET(rdi, -40); \
-        pushq   %r12; CFI_ADJUST (8); CFI_OFFSET(r12, -48); \
-        pushq   %r13; CFI_ADJUST (8); CFI_OFFSET(r13, -56); \
-        pushq   %r14; CFI_ADJUST (8); CFI_OFFSET(r14, -64); \
-        pushq   %r15; CFI_ADJUST (8); CFI_OFFSET(r15, -72); \
-        subq    $(8+10*16), %rsp; CFI_ADJUST (8+10*16); \
-        movupd  %xmm6, 0*16(%rsp); \
-        movupd  %xmm7, 1*16(%rsp); \
-        movupd  %xmm8, 2*16(%rsp); \
-        movupd  %xmm9, 3*16(%rsp); \
-        movupd  %xmm10, 4*16(%rsp); \
-        movupd  %xmm11, 5*16(%rsp); \
-        movupd  %xmm12, 6*16(%rsp); \
-        movupd  %xmm13, 7*16(%rsp); \
-        movupd  %xmm14, 8*16(%rsp); \
-        movupd  %xmm15, 9*16(%rsp)
-
-#define POP_CALLEE_SAVE_REGS \
-        movupd  0*16(%rsp), %xmm6; \
-        movupd  1*16(%rsp), %xmm7; \
-        movupd  2*16(%rsp), %xmm8; \
-        movupd  3*16(%rsp), %xmm9; \
-        movupd  4*16(%rsp), %xmm10; \
-        movupd  5*16(%rsp), %xmm11; \
-        movupd  6*16(%rsp), %xmm12; \
-        movupd  7*16(%rsp), %xmm13; \
-        movupd  8*16(%rsp), %xmm14; \
-        movupd  9*16(%rsp), %xmm15; \
-        addq    $(8+10*16), %rsp; CFI_ADJUST (-8-10*16); \
-        popq    %r15; CFI_ADJUST(-8); CFI_SAME_VALUE(r15); \
-        popq    %r14; CFI_ADJUST(-8); CFI_SAME_VALUE(r14); \
-        popq    %r13; CFI_ADJUST(-8); CFI_SAME_VALUE(r13); \
-        popq    %r12; CFI_ADJUST(-8); CFI_SAME_VALUE(r12); \
-        popq    %rdi; CFI_ADJUST(-8); CFI_SAME_VALUE(rdi); \
-        popq    %rsi; CFI_ADJUST(-8); CFI_SAME_VALUE(rsi); \
-        popq    %rbp; CFI_ADJUST(-8); CFI_SAME_VALUE(rbp); \
-        popq    %rbx; CFI_ADJUST(-8); CFI_SAME_VALUE(rbx)
-
-#else
-
-/* Unix API: callee-save regs are rbx, rbp, r12-r15 */
-
-#define PUSH_CALLEE_SAVE_REGS \
-        pushq   %rbx; CFI_ADJUST(8); CFI_OFFSET(rbx, -16); \
-        pushq   %rbp; CFI_ADJUST(8); CFI_OFFSET(rbp, -24); \
-        pushq   %r12; CFI_ADJUST(8); CFI_OFFSET(r12, -32); \
-        pushq   %r13; CFI_ADJUST(8); CFI_OFFSET(r13, -40); \
-        pushq   %r14; CFI_ADJUST(8); CFI_OFFSET(r14, -48); \
-        pushq   %r15; CFI_ADJUST(8); CFI_OFFSET(r15, -56); \
-        subq    $8, %rsp; CFI_ADJUST(8)
-
-#define POP_CALLEE_SAVE_REGS \
-        addq    $8, %rsp; CFI_ADJUST(-8); \
-        popq    %r15; CFI_ADJUST(-8); CFI_SAME_VALUE(r15); \
-        popq    %r14; CFI_ADJUST(-8); CFI_SAME_VALUE(r14); \
-        popq    %r13; CFI_ADJUST(-8); CFI_SAME_VALUE(r13); \
-        popq    %r12; CFI_ADJUST(-8); CFI_SAME_VALUE(r12); \
-        popq    %rbp; CFI_ADJUST(-8); CFI_SAME_VALUE(rbp); \
-        popq    %rbx; CFI_ADJUST(-8); CFI_SAME_VALUE(rbx)
-
-#endif
-
-#if defined(SYS_mingw64) || defined (SYS_cygwin)
-   /* Calls from OCaml to C must reserve 32 bytes of extra stack space */
-#  define PREPARE_FOR_C_CALL subq $32, %rsp; CFI_ADJUST(32)
-#  define CLEANUP_AFTER_C_CALL addq $32, %rsp; CFI_ADJUST(-32)
-   /* Stack probing mustn't be larger than the page size */
-#  define STACK_PROBE_SIZE $4096
-#else
-#  define PREPARE_FOR_C_CALL
-#  define CLEANUP_AFTER_C_CALL
-#  define STACK_PROBE_SIZE $32768
-#endif
-
-/* Registers holding arguments of C functions. */
-
-#if defined(SYS_mingw64) || defined(SYS_cygwin)
-#define C_ARG_1 %rcx
-#define C_ARG_2 %rdx
-#define C_ARG_3 %r8
-#define C_ARG_4 %r9
-#else
-#define C_ARG_1 %rdi
-#define C_ARG_2 %rsi
-#define C_ARG_3 %rdx
-#define C_ARG_4 %rcx
-#endif
-
-        .text
-
-        .globl  G(caml_system__code_begin)
-G(caml_system__code_begin):
-        ret  /* just one instruction, so that debuggers don't display
-        caml_system__code_begin instead of caml_call_gc */
-
-/* Allocation */
-
-FUNCTION(G(caml_call_gc))
-        CFI_STARTPROC
-        RECORD_STACK_FRAME(0)
-LBL(caml_call_gc):
-    /* Touch the stack to trigger a recoverable segfault
-       if insufficient space remains */
-        subq    STACK_PROBE_SIZE, %rsp
-        movq    %rax, 0(%rsp)
-        addq    STACK_PROBE_SIZE, %rsp
-    /* Build array of registers, save it into caml_gc_regs */
-#ifdef WITH_FRAME_POINTERS
-        ENTER_FUNCTION          ;
-#else
-        pushq   %rbp; CFI_ADJUST(8);
-#endif
-        pushq   %r11; CFI_ADJUST (8);
-        pushq   %r10; CFI_ADJUST (8);
-        pushq   %r13; CFI_ADJUST (8);
-        pushq   %r12; CFI_ADJUST (8);
-        pushq   %r9; CFI_ADJUST (8);
-        pushq   %r8; CFI_ADJUST (8);
-        pushq   %rcx; CFI_ADJUST (8);
-        pushq   %rdx; CFI_ADJUST (8);
-        pushq   %rsi; CFI_ADJUST (8);
-        pushq   %rdi; CFI_ADJUST (8);
-        pushq   %rbx; CFI_ADJUST (8);
-        pushq   %rax; CFI_ADJUST (8);
-        STORE_VAR(%rsp, caml_gc_regs)
-    /* Save caml_young_ptr, caml_exception_pointer */
-        STORE_VAR(%r15, caml_young_ptr)
-        STORE_VAR(%r14, caml_exception_pointer)
-#ifdef WITH_SPACETIME
-        STORE_VAR(%r13, caml_spacetime_trie_node_ptr)
-#endif
-    /* Save floating-point registers */
-        subq    $(16*8), %rsp; CFI_ADJUST (16*8);
-        movsd   %xmm0, 0*8(%rsp)
-        movsd   %xmm1, 1*8(%rsp)
-        movsd   %xmm2, 2*8(%rsp)
-        movsd   %xmm3, 3*8(%rsp)
-        movsd   %xmm4, 4*8(%rsp)
-        movsd   %xmm5, 5*8(%rsp)
-        movsd   %xmm6, 6*8(%rsp)
-        movsd   %xmm7, 7*8(%rsp)
-        movsd   %xmm8, 8*8(%rsp)
-        movsd   %xmm9, 9*8(%rsp)
-        movsd   %xmm10, 10*8(%rsp)
-        movsd   %xmm11, 11*8(%rsp)
-        movsd   %xmm12, 12*8(%rsp)
-        movsd   %xmm13, 13*8(%rsp)
-        movsd   %xmm14, 14*8(%rsp)
-        movsd   %xmm15, 15*8(%rsp)
-    /* Call the garbage collector */
-        PREPARE_FOR_C_CALL
-        call    GCALL(caml_garbage_collection)
-        CLEANUP_AFTER_C_CALL
-    /* Restore caml_young_ptr, caml_exception_pointer */
-        LOAD_VAR(caml_young_ptr, %r15)
-        LOAD_VAR(caml_exception_pointer, %r14)
-    /* Restore all regs used by the code generator */
-        movsd   0*8(%rsp), %xmm0
-        movsd   1*8(%rsp), %xmm1
-        movsd   2*8(%rsp), %xmm2
-        movsd   3*8(%rsp), %xmm3
-        movsd   4*8(%rsp), %xmm4
-        movsd   5*8(%rsp), %xmm5
-        movsd   6*8(%rsp), %xmm6
-        movsd   7*8(%rsp), %xmm7
-        movsd   8*8(%rsp), %xmm8
-        movsd   9*8(%rsp), %xmm9
-        movsd   10*8(%rsp), %xmm10
-        movsd   11*8(%rsp), %xmm11
-        movsd   12*8(%rsp), %xmm12
-        movsd   13*8(%rsp), %xmm13
-        movsd   14*8(%rsp), %xmm14
-        movsd   15*8(%rsp), %xmm15
-        addq    $(16*8), %rsp; CFI_ADJUST(-16*8)
-        popq    %rax; CFI_ADJUST(-8)
-        popq    %rbx; CFI_ADJUST(-8)
-        popq    %rdi; CFI_ADJUST(-8)
-        popq    %rsi; CFI_ADJUST(-8)
-        popq    %rdx; CFI_ADJUST(-8)
-        popq    %rcx; CFI_ADJUST(-8)
-        popq    %r8; CFI_ADJUST(-8)
-        popq    %r9; CFI_ADJUST(-8)
-        popq    %r12; CFI_ADJUST(-8)
-        popq    %r13; CFI_ADJUST(-8)
-        popq    %r10; CFI_ADJUST(-8)
-        popq    %r11; CFI_ADJUST(-8)
-#ifdef WITH_FRAME_POINTERS
-        LEAVE_FUNCTION
-#else
-        popq    %rbp; CFI_ADJUST(-8);
-#endif
-    /* Return to caller */
-        ret
-CFI_ENDPROC
-
-FUNCTION(G(caml_alloc1))
-CFI_STARTPROC
-LBL(caml_alloc1):
-        subq    $16, %r15
-        CMP_VAR(caml_young_limit, %r15)
-        jb      LBL(100)
-        ret
-LBL(100):
-        RECORD_STACK_FRAME(0)
-        ENTER_FUNCTION
-/*        subq    $8, %rsp; CFI_ADJUST (8); */
-        call    LBL(caml_call_gc)
-/*        addq    $8, %rsp; CFI_ADJUST (-8); */
-        LEAVE_FUNCTION
-        jmp     LBL(caml_alloc1)
-CFI_ENDPROC
-
-FUNCTION(G(caml_alloc2))
-CFI_STARTPROC
-LBL(caml_alloc2):
-        subq    $24, %r15
-        CMP_VAR(caml_young_limit, %r15)
-        jb      LBL(101)
-        ret
-LBL(101):
-        RECORD_STACK_FRAME(0)
-        ENTER_FUNCTION
-/*        subq    $8, %rsp; CFI_ADJUST (8); */
-        call    LBL(caml_call_gc)
-/*        addq    $8, %rsp; CFI_ADJUST (-8); */
-        LEAVE_FUNCTION
-        jmp     LBL(caml_alloc2)
-CFI_ENDPROC
-
-FUNCTION(G(caml_alloc3))
-CFI_STARTPROC
-LBL(caml_alloc3):
-        subq    $32, %r15
-        CMP_VAR(caml_young_limit, %r15)
-        jb      LBL(102)
-        ret
-LBL(102):
-        RECORD_STACK_FRAME(0)
-        ENTER_FUNCTION
-/*        subq    $8, %rsp; CFI_ADJUST (8) */
-        call    LBL(caml_call_gc)
-/*        addq    $8, %rsp; CFI_ADJUST (-8) */
-        LEAVE_FUNCTION
-        jmp     LBL(caml_alloc3)
-CFI_ENDPROC
-
-FUNCTION(G(caml_allocN))
-CFI_STARTPROC
-LBL(caml_allocN):
-        pushq   %rax; CFI_ADJUST(8)        /* save desired size */
-        subq    %rax, %r15
-        CMP_VAR(caml_young_limit, %r15)
-        jb      LBL(103)
-        addq    $8, %rsp; CFI_ADJUST (-8)  /* drop desired size */
-        ret
-LBL(103):
-        CFI_ADJUST(8)
-        RECORD_STACK_FRAME(8)
-#ifdef WITH_FRAME_POINTERS
-        /* ensure 16 byte alignment by subq + enter using 16-bytes, PR#7417 */
-        subq    $8, %rsp; CFI_ADJUST (8)
-        ENTER_FUNCTION
-#endif
-        call    LBL(caml_call_gc)
-#ifdef WITH_FRAME_POINTERS
-        /* ensure 16 byte alignment by leave + addq using 16-bytes PR#7417 */
-        LEAVE_FUNCTION
-        addq    $8, %rsp; CFI_ADJUST (-8)
-#endif
-        popq    %rax; CFI_ADJUST(-8)       /* recover desired size */
-        jmp     LBL(caml_allocN)
-CFI_ENDPROC
-
-/* Call a C function from OCaml */
-
-FUNCTION(G(caml_c_call))
-CFI_STARTPROC
-LBL(caml_c_call):
-    /* Record lowest stack address and return address */
-        popq    %r12; CFI_ADJUST(-8)
-        STORE_VAR(%r12, caml_last_return_address)
-        STORE_VAR(%rsp, caml_bottom_of_stack)
-#ifdef WITH_SPACETIME
-    /* Record the trie node hole pointer that corresponds to
-       [caml_last_return_address] */
-        STORE_VAR(%r13, caml_spacetime_trie_node_ptr)
-#endif
-        subq    $8, %rsp; CFI_ADJUST(8) /* equivalent to pushq %r12 */
-    /* Touch the stack to trigger a recoverable segfault
-       if insufficient space remains */
-        subq    STACK_PROBE_SIZE, %rsp
-        movq    %rax, 0(%rsp)
-        addq    STACK_PROBE_SIZE, %rsp
-    /* Make the exception handler and alloc ptr available to the C code */
-        STORE_VAR(%r15, caml_young_ptr)
-        STORE_VAR(%r14, caml_exception_pointer)
-    /* Call the function (address in %rax) */
-    /* No need to PREPARE_FOR_C_CALL since the caller already
-       reserved the stack space if needed (cf. amd64/proc.ml) */
-        jmp    *%rax
-CFI_ENDPROC
-
-/* Start the OCaml program */
-
-FUNCTION(G(caml_start_program))
-       CFI_STARTPROC
-    /* Save callee-save registers */
-        PUSH_CALLEE_SAVE_REGS
-    /* Initial entry point is G(caml_program) */
-        LEA_VAR(caml_program, %r12)
-    /* Common code for caml_start_program and caml_callback* */
-LBL(caml_start_program):
-    /* Build a callback link */
-#ifdef WITH_SPACETIME
-        PUSH_VAR(caml_spacetime_trie_node_ptr)
-#else
-        subq    $8, %rsp; CFI_ADJUST (8)        /* stack 16-aligned */
-#endif
-        PUSH_VAR(caml_gc_regs)
-        PUSH_VAR(caml_last_return_address)
-        PUSH_VAR(caml_bottom_of_stack)
-#ifdef WITH_SPACETIME
-        /* Save arguments to caml_callback* */
-        pushq   %rax; CFI_ADJUST (8)
-        pushq   %rbx; CFI_ADJUST (8)
-        pushq   %rdi; CFI_ADJUST (8)
-        pushq   %rsi; CFI_ADJUST (8)
-        /* No need to push %r12: it's callee-save. */
-        movq    %r12, C_ARG_1
-        LEA_VAR(caml_start_program, C_ARG_2)
-        call    GCALL(caml_spacetime_c_to_ocaml)
-        popq    %rsi; CFI_ADJUST (-8)
-        popq    %rdi; CFI_ADJUST (-8)
-        popq    %rbx; CFI_ADJUST (-8)
-        popq    %rax; CFI_ADJUST (-8)
-#endif
-    /* Setup alloc ptr and exception ptr */
-        LOAD_VAR(caml_young_ptr, %r15)
-        LOAD_VAR(caml_exception_pointer, %r14)
-    /* Build an exception handler */
-        lea     LBL(108)(%rip), %r13
-        pushq   %r13; CFI_ADJUST(8)
-        pushq   %r14; CFI_ADJUST(8)
-        movq    %rsp, %r14
-#ifdef WITH_SPACETIME
-        LOAD_VAR(caml_spacetime_trie_node_ptr, %r13)
-#endif
-    /* Call the OCaml code */
-        call    *%r12
-LBL(107):
-    /* Pop the exception handler */
-        popq    %r14; CFI_ADJUST(-8)
-        popq    %r12; CFI_ADJUST(-8)   /* dummy register */
-LBL(109):
-    /* Update alloc ptr and exception ptr */
-        STORE_VAR(%r15,caml_young_ptr)
-        STORE_VAR(%r14,caml_exception_pointer)
-    /* Pop the callback link, restoring the global variables */
-        POP_VAR(caml_bottom_of_stack)
-        POP_VAR(caml_last_return_address)
-        POP_VAR(caml_gc_regs)
-#ifdef WITH_SPACETIME
-        POP_VAR(caml_spacetime_trie_node_ptr)
-#else
-        addq    $8, %rsp; CFI_ADJUST (-8);
-#endif
-    /* Restore callee-save registers. */
-        POP_CALLEE_SAVE_REGS
-    /* Return to caller. */
-        ret
-LBL(108):
-    /* Exception handler*/
-    /* Mark the bucket as an exception result and return it */
-        orq     $2, %rax
-        jmp     LBL(109)
-CFI_ENDPROC
-
-/* Raise an exception from OCaml */
-
-FUNCTION(G(caml_raise_exn))
-CFI_STARTPROC
-        TESTL_VAR($1, caml_backtrace_active)
-        jne     LBL(110)
-        movq    %r14, %rsp
-        popq    %r14
-        ret
-LBL(110):
-        movq    %rax, %r12            /* Save exception bucket */
-        movq    %rax, C_ARG_1         /* arg 1: exception bucket */
-#ifdef WITH_FRAME_POINTERS
-        ENTER_FUNCTION
-        movq    8(%rsp), C_ARG_2      /* arg 2: pc of raise */
-        leaq    16(%rsp), C_ARG_3     /* arg 3: sp at raise */
-#else
-        popq    C_ARG_2               /* arg 2: pc of raise */
-        movq    %rsp, C_ARG_3         /* arg 3: sp at raise */
-#endif
-        movq    %r14, C_ARG_4         /* arg 4: sp of handler */
-        /* PR#5700: thanks to popq above, stack is now 16-aligned */
-        /* Thanks to ENTER_FUNCTION, stack is now 16-aligned */
-        PREPARE_FOR_C_CALL            /* no need to cleanup after */
-        call    GCALL(caml_stash_backtrace)
-        movq    %r12, %rax            /* Recover exception bucket */
-        movq    %r14, %rsp
-        popq    %r14
-        ret
-CFI_ENDPROC
-
-/* Raise an exception from C */
-
-FUNCTION(G(caml_raise_exception))
-CFI_STARTPROC
-        TESTL_VAR($1, caml_backtrace_active)
-        jne     LBL(112)
-        movq    C_ARG_1, %rax
-        LOAD_VAR(caml_exception_pointer, %rsp)  /* Cut stack */
-        popq    %r14                   /* Recover previous exception handler */
-        LOAD_VAR(caml_young_ptr, %r15) /* Reload alloc ptr */
-        ret
-LBL(112):
-#ifdef WITH_FRAME_POINTERS
-        ENTER_FUNCTION          ;
-#endif
-        movq    C_ARG_1, %r12            /* Save exception bucket */
-                                      /* arg 1: exception bucket */
-        LOAD_VAR(caml_last_return_address,C_ARG_2)   /* arg 2: pc of raise */
-        LOAD_VAR(caml_bottom_of_stack,C_ARG_3)       /* arg 3: sp of raise */
-        LOAD_VAR(caml_exception_pointer,C_ARG_4)     /* arg 4: sp of handler */
-#ifndef WITH_FRAME_POINTERS
-        subq    $8, %rsp              /* PR#5700: maintain stack alignment */
-#endif
-        PREPARE_FOR_C_CALL            /* no need to cleanup after */
-        call    GCALL(caml_stash_backtrace)
-        movq    %r12, %rax            /* Recover exception bucket */
-        LOAD_VAR(caml_exception_pointer,%rsp)
-        popq    %r14                  /* Recover previous exception handler */
-        LOAD_VAR(caml_young_ptr,%r15) /* Reload alloc ptr */
-        ret
-CFI_ENDPROC
-
-/* Raise a Stack_overflow exception on return from segv_handler()
-   (in asmrun/signals_asm.c).  On entry, the stack is full, so we
-   cannot record a backtrace.
-   No CFI information here since this function disrupts the stack
-   backtrace anyway. */
-
-FUNCTION(G(caml_stack_overflow))
-        LEA_VAR(caml_exn_Stack_overflow, %rax)
-        movq    %r14, %rsp            /* cut the stack */
-        popq    %r14                  /* recover previous exn handler */
-        ret                           /* jump to handler's code */
-
-/* Callback from C to OCaml */
-
-FUNCTION(G(caml_callback_exn))
-CFI_STARTPROC
-    /* Save callee-save registers */
-        PUSH_CALLEE_SAVE_REGS
-    /* Initial loading of arguments */
-        movq    C_ARG_1, %rbx      /* closure */
-        movq    C_ARG_2, %rax      /* argument */
-        movq    0(%rbx), %r12      /* code pointer */
-        jmp     LBL(caml_start_program)
-CFI_ENDPROC
-
-FUNCTION(G(caml_callback2_exn))
-CFI_STARTPROC
-    /* Save callee-save registers */
-        PUSH_CALLEE_SAVE_REGS
-    /* Initial loading of arguments */
-        movq    C_ARG_1, %rdi      /* closure -- no op with Unix conventions */
-        movq    C_ARG_2, %rax      /* first argument */
-        movq    C_ARG_3, %rbx      /* second argument */
-        LEA_VAR(caml_apply2, %r12) /* code pointer */
-        jmp     LBL(caml_start_program)
-CFI_ENDPROC
-
-FUNCTION(G(caml_callback3_exn))
-CFI_STARTPROC
-    /* Save callee-save registers */
-        PUSH_CALLEE_SAVE_REGS
-    /* Initial loading of arguments */
-        movq    C_ARG_2, %rax      /* first argument */
-        movq    C_ARG_3, %rbx      /* second argument */
-        movq    C_ARG_1, %rsi      /* closure */
-        movq    C_ARG_4, %rdi      /* third argument */
-        LEA_VAR(caml_apply3, %r12) /* code pointer */
-        jmp     LBL(caml_start_program)
-CFI_ENDPROC
-
-FUNCTION(G(caml_ml_array_bound_error))
-CFI_STARTPROC
-        LEA_VAR(caml_array_bound_error, %rax)
-        jmp     LBL(caml_c_call)
-CFI_ENDPROC
-
-        .globl  G(caml_system__code_end)
-G(caml_system__code_end):
-
-        .data
-        .globl  G(caml_system__frametable)
-        .align  EIGHT_ALIGN
-G(caml_system__frametable):
-        .quad   1           /* one descriptor */
-        .quad   LBL(107)    /* return address into callback */
-        .value  -1          /* negative frame size => use callback link */
-        .value  0           /* no roots here */
-        .align  EIGHT_ALIGN
-        .quad   16
-        .quad   0
-        .string "amd64.S"
-
-#ifdef WITH_SPACETIME
-        .data
-        .globl  G(caml_system__spacetime_shapes)
-        .align  EIGHT_ALIGN
-G(caml_system__spacetime_shapes):
-        .quad   G(caml_start_program)
-        .quad   2           /* indirect call point to OCaml code */
-        .quad   LBL(107)    /* in caml_start_program / caml_callback* */
-        .quad   0           /* end of shapes for caml_start_program */
-        .quad   0           /* end of shape table */
-        .align  EIGHT_ALIGN
-#endif
-
-#if defined(SYS_macosx)
-        .literal16
-#elif defined(SYS_mingw64) || defined(SYS_cygwin)
-        .section .rdata,"dr"
-#else
-        .section    .rodata.cst8,"a",@progbits
-#endif
-        .globl  G(caml_negf_mask)
-        .align  SIXTEEN_ALIGN
-G(caml_negf_mask):
-        .quad   0x8000000000000000, 0
-        .globl  G(caml_absf_mask)
-        .align  SIXTEEN_ALIGN
-G(caml_absf_mask):
-        .quad   0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF
-
-#if defined(SYS_linux)
-    /* Mark stack as non-executable, PR#4564 */
-        .section .note.GNU-stack,"",%progbits
-#endif
diff --git a/asmrun/amd64nt.asm b/asmrun/amd64nt.asm
deleted file mode 100644
index 7915c1e3..00000000
--- a/asmrun/amd64nt.asm
+++ /dev/null
@@ -1,536 +0,0 @@
-;**************************************************************************
-;*                                                                        *
-;*                                 OCaml                                  *
-;*                                                                        *
-;*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *
-;*                                                                        *
-;*   Copyright 2006 Institut National de Recherche en Informatique et     *
-;*     en Automatique.                                                    *
-;*                                                                        *
-;*   All rights reserved.  This file is distributed under the terms of    *
-;*   the GNU Lesser General Public License version 2.1, with the          *
-;*   special exception on linking described in the file LICENSE.          *
-;*                                                                        *
-;**************************************************************************
-
-; Asm part of the runtime system, AMD64 processor, Intel syntax
-
-; Notes on Win64 calling conventions:
-;     function arguments in RCX, RDX, R8, R9 / XMM0 - XMM3
-;     caller must reserve 32 bytes of stack space
-;     callee must preserve RBX, RBP, RSI, RDI, R12-R15, XMM6-XMM15
-
-        EXTRN  caml_garbage_collection: NEAR
-        EXTRN  caml_apply2: NEAR
-        EXTRN  caml_apply3: NEAR
-        EXTRN  caml_program: NEAR
-        EXTRN  caml_array_bound_error: NEAR
-        EXTRN  caml_young_limit: QWORD
-        EXTRN  caml_young_ptr: QWORD
-        EXTRN  caml_bottom_of_stack: QWORD
-        EXTRN  caml_last_return_address: QWORD
-        EXTRN  caml_gc_regs: QWORD
-        EXTRN  caml_exception_pointer: QWORD
-        EXTRN  caml_backtrace_pos: DWORD
-        EXTRN  caml_backtrace_active: DWORD
-        EXTRN  caml_stash_backtrace: NEAR
-IFDEF WITH_SPACETIME
-        EXTRN  caml_spacetime_trie_node_ptr: QWORD
-        EXTRN  caml_spacetime_c_to_ocaml: NEAR
-ENDIF
-
-        .CODE
-
-        PUBLIC  caml_system__code_begin
-caml_system__code_begin:
-        ret  ; just one instruction, so that debuggers don't display
-             ; caml_system__code_begin instead of caml_call_gc
-
-; Allocation
-
-        PUBLIC  caml_call_gc
-        ALIGN   16
-caml_call_gc:
-    ; Record lowest stack address and return address
-        mov     rax, [rsp]
-        mov     caml_last_return_address, rax
-        lea     rax, [rsp+8]
-        mov     caml_bottom_of_stack, rax
-L105:
-    ; Touch the stack to trigger a recoverable segfault
-    ; if insufficient space remains
-        sub     rsp, 01000h
-        mov     [rsp], rax
-        add     rsp, 01000h
-    ; Save caml_young_ptr, caml_exception_pointer
-        mov     caml_young_ptr, r15
-        mov     caml_exception_pointer, r14
-IFDEF WITH_SPACETIME
-        mov     caml_spacetime_trie_node_ptr, r13
-ENDIF
-    ; Build array of registers, save it into caml_gc_regs
-        push    rbp
-        push    r11
-        push    r10
-        push    r13
-        push    r12
-        push    r9
-        push    r8
-        push    rcx
-        push    rdx
-        push    rsi
-        push    rdi
-        push    rbx
-        push    rax
-        mov     caml_gc_regs, rsp
-    ; Save floating-point registers
-        sub     rsp, 16*8
-        movsd   QWORD PTR [rsp + 0*8], xmm0
-        movsd   QWORD PTR [rsp + 1*8], xmm1
-        movsd   QWORD PTR [rsp + 2*8], xmm2
-        movsd   QWORD PTR [rsp + 3*8], xmm3
-        movsd   QWORD PTR [rsp + 4*8], xmm4
-        movsd   QWORD PTR [rsp + 5*8], xmm5
-        movsd   QWORD PTR [rsp + 6*8], xmm6
-        movsd   QWORD PTR [rsp + 7*8], xmm7
-        movsd   QWORD PTR [rsp + 8*8], xmm8
-        movsd   QWORD PTR [rsp + 9*8], xmm9
-        movsd   QWORD PTR [rsp + 10*8], xmm10
-        movsd   QWORD PTR [rsp + 11*8], xmm11
-        movsd   QWORD PTR [rsp + 12*8], xmm12
-        movsd   QWORD PTR [rsp + 13*8], xmm13
-        movsd   QWORD PTR [rsp + 14*8], xmm14
-        movsd   QWORD PTR [rsp + 15*8], xmm15
-    ; Call the garbage collector
-        sub rsp, 32      ; PR#5008: bottom 32 bytes are reserved for callee
-        call caml_garbage_collection
-        add rsp, 32      ; PR#5008
-    ; Restore all regs used by the code generator
-        movsd   xmm0, QWORD PTR [rsp + 0*8]
-        movsd   xmm1, QWORD PTR [rsp + 1*8]
-        movsd   xmm2, QWORD PTR [rsp + 2*8]
-        movsd   xmm3, QWORD PTR [rsp + 3*8]
-        movsd   xmm4, QWORD PTR [rsp + 4*8]
-        movsd   xmm5, QWORD PTR [rsp + 5*8]
-        movsd   xmm6, QWORD PTR [rsp + 6*8]
-        movsd   xmm7, QWORD PTR [rsp + 7*8]
-        movsd   xmm8, QWORD PTR [rsp + 8*8]
-        movsd   xmm9, QWORD PTR [rsp + 9*8]
-        movsd   xmm10, QWORD PTR [rsp + 10*8]
-        movsd   xmm11, QWORD PTR [rsp + 11*8]
-        movsd   xmm12, QWORD PTR [rsp + 12*8]
-        movsd   xmm13, QWORD PTR [rsp + 13*8]
-        movsd   xmm14, QWORD PTR [rsp + 14*8]
-        movsd   xmm15, QWORD PTR [rsp + 15*8]
-        add     rsp, 16*8
-        pop     rax
-        pop     rbx
-        pop     rdi
-        pop     rsi
-        pop     rdx
-        pop     rcx
-        pop     r8
-        pop     r9
-        pop     r12
-        pop     r13
-        pop     r10
-        pop     r11
-        pop     rbp
-    ; Restore caml_young_ptr, caml_exception_pointer
-        mov     r15, caml_young_ptr
-        mov     r14, caml_exception_pointer
-    ; Return to caller
-        ret
-
-        PUBLIC  caml_alloc1
-        ALIGN   16
-caml_alloc1:
-        sub     r15, 16
-        cmp     r15, caml_young_limit
-        jb      L100
-        ret
-L100:
-        mov     rax, [rsp + 0]
-        mov     caml_last_return_address, rax
-        lea     rax, [rsp + 8]
-        mov     caml_bottom_of_stack, rax
-        sub     rsp, 8
-        call    L105
-        add     rsp, 8
-        jmp     caml_alloc1
-
-        PUBLIC  caml_alloc2
-        ALIGN   16
-caml_alloc2:
-        sub     r15, 24
-        cmp     r15, caml_young_limit
-        jb      L101
-        ret
-L101:
-        mov     rax, [rsp + 0]
-        mov     caml_last_return_address, rax
-        lea     rax, [rsp + 8]
-        mov     caml_bottom_of_stack, rax
-        sub     rsp, 8
-        call    L105
-        add     rsp, 8
-        jmp     caml_alloc2
-
-        PUBLIC  caml_alloc3
-        ALIGN   16
-caml_alloc3:
-        sub     r15, 32
-        cmp     r15, caml_young_limit
-        jb      L102
-        ret
-L102:
-        mov     rax, [rsp + 0]
-        mov     caml_last_return_address, rax
-        lea     rax, [rsp + 8]
-        mov     caml_bottom_of_stack, rax
-        sub     rsp, 8
-        call    L105
-        add     rsp, 8
-        jmp     caml_alloc3
-
-        PUBLIC  caml_allocN
-        ALIGN   16
-caml_allocN:
-        sub     r15, rax
-        cmp     r15, caml_young_limit
-        jb      L103
-        ret
-L103:
-        push    rax                       ; save desired size
-        mov     rax, [rsp + 8]
-        mov     caml_last_return_address, rax
-        lea     rax, [rsp + 16]
-        mov     caml_bottom_of_stack, rax
-        call    L105
-        pop     rax                      ; recover desired size
-        jmp     caml_allocN
-
-; Call a C function from OCaml
-
-        PUBLIC  caml_c_call
-        ALIGN   16
-caml_c_call:
-    ; Record lowest stack address and return address
-        pop     r12
-        mov     caml_last_return_address, r12
-        mov     caml_bottom_of_stack, rsp
-IFDEF WITH_SPACETIME
-    ; Record the trie node hole pointer that corresponds to
-    ; [caml_last_return_address]
-        mov     caml_spacetime_trie_node_ptr, r13
-ENDIF
-    ; Touch the stack to trigger a recoverable segfault
-    ; if insufficient space remains
-        sub     rsp, 01000h
-        mov     [rsp], rax
-        add     rsp, 01000h
-    ; Make the exception handler and alloc ptr available to the C code
-        mov     caml_young_ptr, r15
-        mov     caml_exception_pointer, r14
-    ; Call the function (address in rax)
-        call    rax
-    ; Reload alloc ptr
-        mov     r15, caml_young_ptr
-    ; Return to caller
-        push    r12
-        ret
-
-; Start the OCaml program
-
-        PUBLIC  caml_start_program
-        ALIGN   16
-caml_start_program:
-    ; Save callee-save registers
-        push    rbx
-        push    rbp
-        push    rsi
-        push    rdi
-        push    r12
-        push    r13
-        push    r14
-        push    r15
-        sub     rsp, 8+10*16       ; stack 16-aligned + 10 saved xmm regs
-        movapd  OWORD PTR [rsp + 0*16], xmm6
-        movapd  OWORD PTR [rsp + 1*16], xmm7
-        movapd  OWORD PTR [rsp + 2*16], xmm8
-        movapd  OWORD PTR [rsp + 3*16], xmm9
-        movapd  OWORD PTR [rsp + 4*16], xmm10
-        movapd  OWORD PTR [rsp + 5*16], xmm11
-        movapd  OWORD PTR [rsp + 6*16], xmm12
-        movapd  OWORD PTR [rsp + 7*16], xmm13
-        movapd  OWORD PTR [rsp + 8*16], xmm14
-        movapd  OWORD PTR [rsp + 9*16], xmm15
-    ; Initial entry point is caml_program
-        lea     r12, caml_program
-    ; Common code for caml_start_program and caml_callback*
-L106:
-    ; Build a callback link
-IFDEF WITH_SPACETIME
-        push    caml_spacetime_trie_node_ptr
-ELSE
-        sub     rsp, 8  ; stack 16-aligned
-ENDIF
-        push    caml_gc_regs
-        push    caml_last_return_address
-        push    caml_bottom_of_stack
-IFDEF WITH_SPACETIME
-    ; Save arguments to caml_callback
-        push    rax
-        push    rbx
-        push    rdi
-        push    rsi
-    ; No need to push r12: it is callee-save.
-        mov     rcx, r12
-        lea     rdx, caml_start_program
-        call    caml_spacetime_c_to_ocaml
-        pop     rsi
-        pop     rdi
-        pop     rbx
-        pop     rax
-ENDIF
-    ; Setup alloc ptr and exception ptr
-        mov     r15, caml_young_ptr
-        mov     r14, caml_exception_pointer
-    ; Build an exception handler
-        lea     r13, L108
-        push    r13
-        push    r14
-        mov     r14, rsp
-IFDEF WITH_SPACETIME
-        mov     r13, caml_spacetime_trie_node_ptr
-ENDIF
-    ; Call the OCaml code
-        call    r12
-L107:
-    ; Pop the exception handler
-        pop     r14
-        pop     r12    ; dummy register
-L109:
-    ; Update alloc ptr and exception ptr
-        mov     caml_young_ptr, r15
-        mov     caml_exception_pointer, r14
-    ; Pop the callback restoring, link the global variables
-        pop     caml_bottom_of_stack
-        pop     caml_last_return_address
-        pop     caml_gc_regs
-IFDEF WITH_SPACETIME
-        pop     caml_spacetime_trie_node_ptr
-ELSE
-        add     rsp, 8
-ENDIF
-    ; Restore callee-save registers.
-        movapd  xmm6, OWORD PTR [rsp + 0*16]
-        movapd  xmm7, OWORD PTR [rsp + 1*16]
-        movapd  xmm8, OWORD PTR [rsp + 2*16]
-        movapd  xmm9, OWORD PTR [rsp + 3*16]
-        movapd  xmm10, OWORD PTR [rsp + 4*16]
-        movapd  xmm11, OWORD PTR [rsp + 5*16]
-        movapd  xmm12, OWORD PTR [rsp + 6*16]
-        movapd  xmm13, OWORD PTR [rsp + 7*16]
-        movapd  xmm14, OWORD PTR [rsp + 8*16]
-        movapd  xmm15, OWORD PTR [rsp + 9*16]
-        add     rsp, 8+10*16
-        pop     r15
-        pop     r14
-        pop     r13
-        pop     r12
-        pop     rdi
-        pop     rsi
-        pop     rbp
-        pop     rbx
-    ; Return to caller
-        ret
-L108:
-    ; Exception handler
-    ; Mark the bucket as an exception result and return it
-        or      rax, 2
-        jmp     L109
-
-; Raise an exception from OCaml
-
-        PUBLIC  caml_raise_exn
-        ALIGN   16
-caml_raise_exn:
-        test    caml_backtrace_active, 1
-        jne     L110
-        mov     rsp, r14             ; Cut stack
-        pop     r14                  ; Recover previous exception handler
-        ret                          ; Branch to handler
-L110:
-        mov     r12, rax             ; Save exception bucket in r12
-        mov     rcx, rax             ; Arg 1: exception bucket
-        mov     rdx, [rsp]           ; Arg 2: PC of raise
-        lea     r8, [rsp+8]          ; Arg 3: SP of raise
-        mov     r9, r14              ; Arg 4: SP of handler
-        sub     rsp, 32              ; Reserve 32 bytes on stack
-        call    caml_stash_backtrace
-        mov     rax, r12             ; Recover exception bucket
-        mov     rsp, r14             ; Cut stack
-        pop     r14                  ; Recover previous exception handler
-        ret                          ; Branch to handler
-
-; Raise an exception from C
-
-        PUBLIC  caml_raise_exception
-        ALIGN   16
-caml_raise_exception:
-        test    caml_backtrace_active, 1
-        jne     L112
-        mov     rax, rcx             ; First argument is exn bucket
-        mov     rsp, caml_exception_pointer
-        pop     r14                  ; Recover previous exception handler
-        mov     r15, caml_young_ptr ; Reload alloc ptr
-        ret
-L112:
-        mov     r12, rcx             ; Save exception bucket in r12
-                                     ; Arg 1: exception bucket
-        mov     rdx, caml_last_return_address ; Arg 2: PC of raise
-        mov     r8, caml_bottom_of_stack      ; Arg 3: SP of raise
-        mov     r9, caml_exception_pointer    ; Arg 4: SP of handler
-        sub     rsp, 32              ; Reserve 32 bytes on stack
-        call    caml_stash_backtrace
-        mov     rax, r12             ; Recover exception bucket
-        mov     rsp, caml_exception_pointer
-        pop     r14                  ; Recover previous exception handler
-        mov     r15, caml_young_ptr ; Reload alloc ptr
-        ret
-
-; Callback from C to OCaml
-
-        PUBLIC  caml_callback_exn
-        ALIGN   16
-caml_callback_exn:
-    ; Save callee-save registers
-        push    rbx
-        push    rbp
-        push    rsi
-        push    rdi
-        push    r12
-        push    r13
-        push    r14
-        push    r15
-        sub     rsp, 8+10*16       ; stack 16-aligned + 10 saved xmm regs
-        movapd  OWORD PTR [rsp + 0*16], xmm6
-        movapd  OWORD PTR [rsp + 1*16], xmm7
-        movapd  OWORD PTR [rsp + 2*16], xmm8
-        movapd  OWORD PTR [rsp + 3*16], xmm9
-        movapd  OWORD PTR [rsp + 4*16], xmm10
-        movapd  OWORD PTR [rsp + 5*16], xmm11
-        movapd  OWORD PTR [rsp + 6*16], xmm12
-        movapd  OWORD PTR [rsp + 7*16], xmm13
-        movapd  OWORD PTR [rsp + 8*16], xmm14
-        movapd  OWORD PTR [rsp + 9*16], xmm15
-    ; Initial loading of arguments
-        mov     rbx, rcx      ; closure
-        mov     rax, rdx      ; argument
-        mov     r12, [rbx]    ; code pointer
-        jmp     L106
-
-        PUBLIC  caml_callback2_exn
-        ALIGN   16
-caml_callback2_exn:
-    ; Save callee-save registers
-        push    rbx
-        push    rbp
-        push    rsi
-        push    rdi
-        push    r12
-        push    r13
-        push    r14
-        push    r15
-        sub     rsp, 8+10*16       ; stack 16-aligned + 10 saved xmm regs
-        movapd  OWORD PTR [rsp + 0*16], xmm6
-        movapd  OWORD PTR [rsp + 1*16], xmm7
-        movapd  OWORD PTR [rsp + 2*16], xmm8
-        movapd  OWORD PTR [rsp + 3*16], xmm9
-        movapd  OWORD PTR [rsp + 4*16], xmm10
-        movapd  OWORD PTR [rsp + 5*16], xmm11
-        movapd  OWORD PTR [rsp + 6*16], xmm12
-        movapd  OWORD PTR [rsp + 7*16], xmm13
-        movapd  OWORD PTR [rsp + 8*16], xmm14
-        movapd  OWORD PTR [rsp + 9*16], xmm15
-    ; Initial loading of arguments
-        mov     rdi, rcx        ; closure
-        mov     rax, rdx        ; first argument
-        mov     rbx, r8         ; second argument
-        lea     r12, caml_apply2  ; code pointer
-        jmp     L106
-
-        PUBLIC  caml_callback3_exn
-        ALIGN   16
-caml_callback3_exn:
-    ; Save callee-save registers
-        push    rbx
-        push    rbp
-        push    rsi
-        push    rdi
-        push    r12
-        push    r13
-        push    r14
-        push    r15
-        sub     rsp, 8+10*16       ; stack 16-aligned + 10 saved xmm regs
-        movapd  OWORD PTR [rsp + 0*16], xmm6
-        movapd  OWORD PTR [rsp + 1*16], xmm7
-        movapd  OWORD PTR [rsp + 2*16], xmm8
-        movapd  OWORD PTR [rsp + 3*16], xmm9
-        movapd  OWORD PTR [rsp + 4*16], xmm10
-        movapd  OWORD PTR [rsp + 5*16], xmm11
-        movapd  OWORD PTR [rsp + 6*16], xmm12
-        movapd  OWORD PTR [rsp + 7*16], xmm13
-        movapd  OWORD PTR [rsp + 8*16], xmm14
-        movapd  OWORD PTR [rsp + 9*16], xmm15
-    ; Initial loading of arguments
-        mov     rsi, rcx        ; closure
-        mov     rax, rdx        ; first argument
-        mov     rbx, r8         ; second argument
-        mov     rdi, r9         ; third argument
-        lea     r12, caml_apply3      ; code pointer
-        jmp     L106
-
-        PUBLIC  caml_ml_array_bound_error
-        ALIGN   16
-caml_ml_array_bound_error:
-        lea     rax, caml_array_bound_error
-        jmp     caml_c_call
-
-	PUBLIC caml_system__code_end
-caml_system__code_end:
-
-        .DATA
-        PUBLIC  caml_system__frametable
-caml_system__frametable LABEL QWORD
-        QWORD   1           ; one descriptor
-        QWORD   L107        ; return address into callback
-        WORD    -1          ; negative frame size => use callback link
-        WORD    0           ; no roots here
-        ALIGN   8
-
-IFDEF WITH_SPACETIME
-        .DATA
-        PUBLIC  caml_system__spacetime_shapes
-        ALIGN   8
-caml_system__spacetime_shapes LABEL QWORD
-        QWORD   caml_start_program
-        QWORD   2         ; indirect call point to OCaml code
-        QWORD   L107      ; in caml_start_program / caml_callback*
-        QWORD   0         ; end of shapes in caml_start_program
-        QWORD   0         ; end of shape table
-        ALIGN   8
-ENDIF
-
-        PUBLIC  caml_negf_mask
-        ALIGN   16
-caml_negf_mask LABEL QWORD
-        QWORD   8000000000000000H, 0
-
-        PUBLIC  caml_absf_mask
-        ALIGN   16
-caml_absf_mask LABEL QWORD
-        QWORD   7FFFFFFFFFFFFFFFH, 0FFFFFFFFFFFFFFFFH
-
-        END
diff --git a/asmrun/arm64.S b/asmrun/arm64.S
deleted file mode 100644
index dea5ab73..00000000
--- a/asmrun/arm64.S
+++ /dev/null
@@ -1,571 +0,0 @@
-/**************************************************************************/
-/*                                                                        */
-/*                                 OCaml                                  */
-/*                                                                        */
-/*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           */
-/*                                                                        */
-/*   Copyright 2013 Institut National de Recherche en Informatique et     */
-/*     en Automatique.                                                    */
-/*                                                                        */
-/*   All rights reserved.  This file is distributed under the terms of    */
-/*   the GNU Lesser General Public License version 2.1, with the          */
-/*   special exception on linking described in the file LICENSE.          */
-/*                                                                        */
-/**************************************************************************/
-
-/* Asm part of the runtime system, ARM processor, 64-bit mode */
-/* Must be preprocessed by cpp */
-
-#include "caml/m.h"
-
-/* Special registers */
-
-#define TRAP_PTR x26
-#define ALLOC_PTR x27
-#define ALLOC_LIMIT x28
-#define ARG x15
-#define TMP x16
-#define TMP2 x17
-
-/* Support for CFI directives */
-
-#if defined(ASM_CFI_SUPPORTED)
-#define CFI_STARTPROC .cfi_startproc
-#define CFI_ENDPROC .cfi_endproc
-#define CFI_ADJUST(n) .cfi_adjust_cfa_offset n
-#define CFI_REGISTER(r1,r2) .cfi_register r1,r2
-#define CFI_OFFSET(r,n) .cfi_offset r,n
-#else
-#define CFI_STARTPROC
-#define CFI_ENDPROC
-#define CFI_ADJUST(n)
-#define CFI_REGISTER(r1,r2)
-#define CFI_OFFSET(r,n)
-#endif
-
-/* Support for profiling with gprof */
-
-#define PROFILE
-
-/* Macros to load and store global variables.  Destroy TMP2 */
-
-#if defined(__PIC__)
-
-#define ADDRGLOBAL(reg,symb) \
-        adrp    TMP2, :got:symb; \
-        ldr     reg, [TMP2, #:got_lo12:symb]
-
-#define LOADGLOBAL(reg,symb) \
-        ADDRGLOBAL(TMP2,symb); \
-        ldr     reg, [TMP2]
-
-#define STOREGLOBAL(reg,symb) \
-        ADDRGLOBAL(TMP2,symb); \
-        str     reg, [TMP2]
-
-#else
-
-#define ADDRGLOBAL(reg,symb) \
-        adrp    reg, symb; \
-        add     reg, reg, #:lo12:symb
-
-#define LOADGLOBAL(reg,symb) \
-        adrp    TMP2, symb; \
-        ldr     reg, [TMP2, #:lo12:symb]
-
-#define STOREGLOBAL(reg,symb) \
-        adrp    TMP2, symb; \
-        str     reg, [TMP2, #:lo12:symb]
-
-#endif
-
-/* Allocation functions and GC interface */
-
-        .globl  caml_system__code_begin
-caml_system__code_begin:
-
-        .align  2
-        .globl  caml_call_gc
-caml_call_gc:
-        CFI_STARTPROC
-        PROFILE
-    /* Record return address */
-        STOREGLOBAL(x30, caml_last_return_address)
-    /* Record lowest stack address */
-        mov     TMP, sp
-        STOREGLOBAL(TMP, caml_bottom_of_stack)
-.Lcaml_call_gc:
-    /* Set up stack space, saving return address and frame pointer */
-    /* (2 regs RA/GP, 24 allocatable int regs, 24 caller-save float regs) * 8 */
-        CFI_OFFSET(29, -400)
-        CFI_OFFSET(30, -392)
-        stp     x29, x30, [sp, -400]!
-        CFI_ADJUST(400)
-        add     x29, sp, #0
-    /* Save allocatable integer registers on the stack, in the order
-       given in proc.ml */
-        stp     x0, x1, [sp, 16]
-        stp     x2, x3, [sp, 32]
-        stp     x4, x5, [sp, 48]
-        stp     x6, x7, [sp, 64]
-        stp     x8, x9, [sp, 80]
-        stp     x10, x11, [sp, 96]
-        stp     x12, x13, [sp, 112]
-        stp     x14, x15, [sp, 128]
-        stp     x19, x20, [sp, 144]
-        stp     x21, x22, [sp, 160]
-        stp     x23, x24, [sp, 176]
-        str     x25, [sp, 192]
-     /* Save caller-save floating-point registers on the stack
-        (callee-saves are preserved by caml_garbage_collection) */
-        stp     d0, d1, [sp, 208]
-        stp     d2, d3, [sp, 224]
-        stp     d4, d5, [sp, 240]
-        stp     d6, d7, [sp, 256]
-        stp     d16, d17, [sp, 272]
-        stp     d18, d19, [sp, 288]
-        stp     d20, d21, [sp, 304]
-        stp     d22, d23, [sp, 320]
-        stp     d24, d25, [sp, 336]
-        stp     d26, d27, [sp, 352]
-        stp     d28, d29, [sp, 368]
-        stp     d30, d31, [sp, 384]
-    /* Store pointer to saved integer registers in caml_gc_regs */
-        add     TMP, sp, #16
-        STOREGLOBAL(TMP, caml_gc_regs)
-    /* Save current allocation pointer for debugging purposes */
-        STOREGLOBAL(ALLOC_PTR, caml_young_ptr)
-    /* Save trap pointer in case an exception is raised during GC */
-        STOREGLOBAL(TRAP_PTR, caml_exception_pointer)
-    /* Call the garbage collector */
-        bl      caml_garbage_collection
-    /* Restore registers */
-        ldp     x0, x1, [sp, 16]
-        ldp     x2, x3, [sp, 32]
-        ldp     x4, x5, [sp, 48]
-        ldp     x6, x7, [sp, 64]
-        ldp     x8, x9, [sp, 80]
-        ldp     x10, x11, [sp, 96]
-        ldp     x12, x13, [sp, 112]
-        ldp     x14, x15, [sp, 128]
-        ldp     x19, x20, [sp, 144]
-        ldp     x21, x22, [sp, 160]
-        ldp     x23, x24, [sp, 176]
-        ldr     x25, [sp, 192]
-        ldp     d0, d1, [sp, 208]
-        ldp     d2, d3, [sp, 224]
-        ldp     d4, d5, [sp, 240]
-        ldp     d6, d7, [sp, 256]
-        ldp     d16, d17, [sp, 272]
-        ldp     d18, d19, [sp, 288]
-        ldp     d20, d21, [sp, 304]
-        ldp     d22, d23, [sp, 320]
-        ldp     d24, d25, [sp, 336]
-        ldp     d26, d27, [sp, 352]
-        ldp     d28, d29, [sp, 368]
-        ldp     d30, d31, [sp, 384]
-    /* Reload new allocation pointer and allocation limit */
-        LOADGLOBAL(ALLOC_PTR, caml_young_ptr)
-        LOADGLOBAL(ALLOC_LIMIT, caml_young_limit)
-    /* Free stack space and return to caller */
-        ldp     x29, x30, [sp], 400
-        ret
-        CFI_ENDPROC
-        .type   caml_call_gc, %function
-        .size   caml_call_gc, .-caml_call_gc
-
-        .align  2
-        .globl  caml_alloc1
-caml_alloc1:
-        CFI_STARTPROC
-        PROFILE
-1:      sub     ALLOC_PTR, ALLOC_PTR, #16
-        cmp     ALLOC_PTR, ALLOC_LIMIT
-        b.lo    2f
-        ret
-2:      stp     x29, x30, [sp, -16]!
-        CFI_ADJUST(16)
-    /* Record the lowest address of the caller's stack frame.  This is the
-       address immediately above the pair of words (x29 and x30) we just
-       pushed.  Those must not be included since otherwise the distance from
-       [caml_bottom_of_stack] to the highest address in the caller's stack
-       frame won't match the frame size contained in the relevant frame
-       descriptor. */
-        add     x29, sp, #16
-        STOREGLOBAL(x29, caml_bottom_of_stack)
-        add     x29, sp, #0
-    /* Record return address */
-        STOREGLOBAL(x30, caml_last_return_address)
-    /* Call GC */
-        bl      .Lcaml_call_gc
-    /* Restore return address */
-        ldp     x29, x30, [sp], 16
-        CFI_ADJUST(-16)
-    /* Try again */
-        b       1b
-        CFI_ENDPROC
-        .type   caml_alloc1, %function
-        .size   caml_alloc1, .-caml_alloc1
-
-        .align  2
-        .globl  caml_alloc2
-caml_alloc2:
-        CFI_STARTPROC
-        PROFILE
-1:      sub     ALLOC_PTR, ALLOC_PTR, #24
-        cmp     ALLOC_PTR, ALLOC_LIMIT
-        b.lo    2f
-        ret
-2:      stp     x29, x30, [sp, -16]!
-        CFI_ADJUST(16)
-    /* Record the lowest address of the caller's stack frame.
-       See comment above. */
-        add     x29, sp, #16
-        STOREGLOBAL(x29, caml_bottom_of_stack)
-        add     x29, sp, #0
-    /* Record return address */
-        STOREGLOBAL(x30, caml_last_return_address)
-    /* Call GC */
-        bl      .Lcaml_call_gc
-    /* Restore return address */
-        ldp     x29, x30, [sp], 16
-        CFI_ADJUST(-16)
-    /* Try again */
-        b       1b
-        CFI_ENDPROC
-        .type   caml_alloc2, %function
-        .size   caml_alloc2, .-caml_alloc2
-
-        .align  2
-        .globl  caml_alloc3
-caml_alloc3:
-        CFI_STARTPROC
-        PROFILE
-1:      sub     ALLOC_PTR, ALLOC_PTR, #32
-        cmp     ALLOC_PTR, ALLOC_LIMIT
-        b.lo    2f
-        ret
-2:      stp     x29, x30, [sp, -16]!
-        CFI_ADJUST(16)
-    /* Record the lowest address of the caller's stack frame.
-       See comment above. */
-        add     x29, sp, #16
-        STOREGLOBAL(x29, caml_bottom_of_stack)
-        add     x29, sp, #0
-    /* Record return address */
-        STOREGLOBAL(x30, caml_last_return_address)
-    /* Call GC */
-        bl      .Lcaml_call_gc
-    /* Restore return address */
-        ldp     x29, x30, [sp], 16
-        CFI_ADJUST(-16)
-    /* Try again */
-        b       1b
-        CFI_ENDPROC
-        .type   caml_alloc3, %function
-        .size   caml_alloc3, .-caml_alloc3
-
-        .align  2
-        .globl  caml_allocN
-caml_allocN:
-        CFI_STARTPROC
-        PROFILE
-1:      sub     ALLOC_PTR, ALLOC_PTR, ARG
-        cmp     ALLOC_PTR, ALLOC_LIMIT
-        b.lo    2f
-        ret
-2:      stp     x29, x30, [sp, -16]!
-        CFI_ADJUST(16)
-    /* Record the lowest address of the caller's stack frame.
-       See comment above. */
-        add     x29, sp, #16
-        STOREGLOBAL(x29, caml_bottom_of_stack)
-        add     x29, sp, #0
-    /* Record return address */
-        STOREGLOBAL(x30, caml_last_return_address)
-    /* Call GC.  This preserves ARG */
-        bl      .Lcaml_call_gc
-    /* Restore return address */
-        ldp     x29, x30, [sp], 16
-        CFI_ADJUST(-16)
-    /* Try again */
-        b       1b
-        CFI_ENDPROC
-        .type   caml_allocN, %function
-        .size   caml_allocN, .-caml_allocN
-
-/* Call a C function from OCaml */
-/* Function to call is in ARG */
-
-        .align  2
-        .globl  caml_c_call
-caml_c_call:
-        CFI_STARTPROC
-        PROFILE
-    /* Preserve return address in callee-save register x19 */
-        mov     x19, x30
-        CFI_REGISTER(30, 19)
-    /* Record lowest stack address and return address */
-        STOREGLOBAL(x30, caml_last_return_address)
-        add     TMP, sp, #0
-        STOREGLOBAL(TMP, caml_bottom_of_stack)
-    /* Make the exception handler alloc ptr available to the C code */
-        STOREGLOBAL(ALLOC_PTR, caml_young_ptr)
-        STOREGLOBAL(TRAP_PTR, caml_exception_pointer)
-    /* Call the function */
-        blr     ARG
-    /* Reload alloc ptr and alloc limit */
-        LOADGLOBAL(ALLOC_PTR, caml_young_ptr)
-        LOADGLOBAL(ALLOC_LIMIT, caml_young_limit)
-    /* Return */
-        ret     x19
-        CFI_ENDPROC
-        .type   caml_c_call, %function
-        .size   caml_c_call, .-caml_c_call
-
-/* Start the OCaml program */
-
-        .align  2
-        .globl  caml_start_program
-caml_start_program:
-        CFI_STARTPROC
-        PROFILE
-        ADDRGLOBAL(ARG, caml_program)
-
-/* Code shared with caml_callback* */
-/* Address of OCaml code to call is in ARG */
-/* Arguments to the OCaml code are in x0...x7 */
-
-.Ljump_to_caml:
-    /* Set up stack frame and save callee-save registers */
-        CFI_OFFSET(29, -160)
-        CFI_OFFSET(30, -152)
-        stp     x29, x30, [sp, -160]!
-        CFI_ADJUST(160)
-        add     x29, sp, #0
-        stp     x19, x20, [sp, 16]
-        stp     x21, x22, [sp, 32]
-        stp     x23, x24, [sp, 48]
-        stp     x25, x26, [sp, 64]
-        stp     x27, x28, [sp, 80]
-        stp     d8, d9, [sp, 96]
-        stp     d10, d11, [sp, 112]
-        stp     d12, d13, [sp, 128]
-        stp     d14, d15, [sp, 144]
-    /* Setup a callback link on the stack */
-        LOADGLOBAL(x8, caml_bottom_of_stack)
-        LOADGLOBAL(x9, caml_last_return_address)
-        LOADGLOBAL(x10, caml_gc_regs)
-        stp     x8, x9, [sp, -32]!     /* 16-byte alignment */
-        CFI_ADJUST(32)
-        str     x10, [sp, 16]
-    /* Setup a trap frame to catch exceptions escaping the OCaml code */
-        LOADGLOBAL(x8, caml_exception_pointer)
-        adr     x9, .Ltrap_handler
-        stp     x8, x9, [sp, -16]!
-        CFI_ADJUST(16)
-        add     TRAP_PTR, sp, #0
-    /* Reload allocation pointers */
-        LOADGLOBAL(ALLOC_PTR, caml_young_ptr)
-        LOADGLOBAL(ALLOC_LIMIT, caml_young_limit)
-    /* Call the OCaml code */
-        blr     ARG
-.Lcaml_retaddr:
-    /* Pop the trap frame, restoring caml_exception_pointer */
-        ldr     x8, [sp], 16
-        CFI_ADJUST(-16)
-        STOREGLOBAL(x8, caml_exception_pointer)
-    /* Pop the callback link, restoring the global variables */
-.Lreturn_result:
-        ldr     x10, [sp, 16]
-        ldp     x8, x9, [sp], 32
-        CFI_ADJUST(-32)
-        STOREGLOBAL(x8, caml_bottom_of_stack)
-        STOREGLOBAL(x9, caml_last_return_address)
-        STOREGLOBAL(x10, caml_gc_regs)
-    /* Update allocation pointer */
-        STOREGLOBAL(ALLOC_PTR, caml_young_ptr)
-    /* Reload callee-save registers and return address */
-        ldp     x19, x20, [sp, 16]
-        ldp     x21, x22, [sp, 32]
-        ldp     x23, x24, [sp, 48]
-        ldp     x25, x26, [sp, 64]
-        ldp     x27, x28, [sp, 80]
-        ldp     d8, d9, [sp, 96]
-        ldp     d10, d11, [sp, 112]
-        ldp     d12, d13, [sp, 128]
-        ldp     d14, d15, [sp, 144]
-        ldp     x29, x30, [sp], 160
-        CFI_ADJUST(-160)
-    /* Return to C caller */
-        ret
-        CFI_ENDPROC
-        .type   .Lcaml_retaddr, %function
-        .size   .Lcaml_retaddr, .-.Lcaml_retaddr
-        .type   caml_start_program, %function
-        .size   caml_start_program, .-caml_start_program
-
-/* The trap handler */
-
-        .align  2
-.Ltrap_handler:
-        CFI_STARTPROC
-    /* Save exception pointer */
-        STOREGLOBAL(TRAP_PTR, caml_exception_pointer)
-    /* Encode exception bucket as an exception result */
-        orr     x0, x0, #2
-    /* Return it */
-        b       .Lreturn_result
-        CFI_ENDPROC
-        .type   .Ltrap_handler, %function
-        .size   .Ltrap_handler, .-.Ltrap_handler
-
-/* Raise an exception from OCaml */
-
-        .align  2
-        .globl  caml_raise_exn
-caml_raise_exn:
-        CFI_STARTPROC
-        PROFILE
-    /* Test if backtrace is active */
-        LOADGLOBAL(TMP, caml_backtrace_active)
-        cbnz     TMP, 2f
-1:  /* Cut stack at current trap handler */
-        mov     sp, TRAP_PTR
-    /* Pop previous handler and jump to it */
-        ldr     TMP, [sp, 8]
-        ldr     TRAP_PTR, [sp], 16
-        br      TMP
-2:  /* Preserve exception bucket in callee-save register x19 */
-        mov     x19, x0
-    /* Stash the backtrace */
-                               /* arg1: exn bucket, already in x0 */
-        mov     x1, x30        /* arg2: pc of raise */
-        add     x2, sp, #0     /* arg3: sp of raise */
-        mov     x3, TRAP_PTR   /* arg4: sp of handler */
-        bl      caml_stash_backtrace
-    /* Restore exception bucket and raise */
-        mov     x0, x19
-        b       1b
-        CFI_ENDPROC
-        .type   caml_raise_exn, %function
-        .size   caml_raise_exn, .-caml_raise_exn
-
-/* Raise an exception from C */
-
-        .align  2
-        .globl  caml_raise_exception
-caml_raise_exception:
-        CFI_STARTPROC
-        PROFILE
-    /* Reload trap ptr, alloc ptr and alloc limit */
-        LOADGLOBAL(TRAP_PTR, caml_exception_pointer)
-        LOADGLOBAL(ALLOC_PTR, caml_young_ptr)
-        LOADGLOBAL(ALLOC_LIMIT, caml_young_limit)
-    /* Test if backtrace is active */
-        LOADGLOBAL(TMP, caml_backtrace_active)
-        cbnz    TMP, 2f
-1:  /* Cut stack at current trap handler */
-        mov     sp, TRAP_PTR
-    /* Pop previous handler and jump to it */
-        ldr     TMP, [sp, 8]
-        ldr     TRAP_PTR, [sp], 16
-        br      TMP
-2:  /* Preserve exception bucket in callee-save register x19 */
-        mov     x19, x0
-    /* Stash the backtrace */
-                               /* arg1: exn bucket, already in x0 */
-        LOADGLOBAL(x1, caml_last_return_address)   /* arg2: pc of raise */
-        LOADGLOBAL(x2, caml_bottom_of_stack)       /* arg3: sp of raise */
-        mov     x3, TRAP_PTR   /* arg4: sp of handler */
-        bl      caml_stash_backtrace
-    /* Restore exception bucket and raise */
-        mov     x0, x19
-        b       1b
-        CFI_ENDPROC
-        .type   caml_raise_exception, %function
-        .size   caml_raise_exception, .-caml_raise_exception
-
-/* Callback from C to OCaml */
-
-        .align  2
-        .globl  caml_callback_exn
-caml_callback_exn:
-        CFI_STARTPROC
-        PROFILE
-    /* Initial shuffling of arguments (x0 = closure, x1 = first arg) */
-        mov     TMP, x0
-        mov     x0, x1          /* x0 = first arg */
-        mov     x1, TMP         /* x1 = closure environment */
-        ldr     ARG, [TMP]      /* code pointer */
-        b       .Ljump_to_caml
-        CFI_ENDPROC
-        .type   caml_callback_exn, %function
-        .size   caml_callback_exn, .-caml_callback_exn
-
-        .align  2
-        .globl  caml_callback2_exn
-caml_callback2_exn:
-        CFI_STARTPROC
-        PROFILE
-    /* Initial shuffling of arguments (x0 = closure, x1 = arg1, x2 = arg2) */
-        mov     TMP, x0
-        mov     x0, x1          /* x0 = first arg */
-        mov     x1, x2          /* x1 = second arg */
-        mov     x2, TMP         /* x2 = closure environment */
-        ADDRGLOBAL(ARG, caml_apply2)
-        b       .Ljump_to_caml
-        CFI_ENDPROC
-        .type   caml_callback2_exn, %function
-        .size   caml_callback2_exn, .-caml_callback2_exn
-
-        .align  2
-        .globl  caml_callback3_exn
-caml_callback3_exn:
-        CFI_STARTPROC
-        PROFILE
-    /* Initial shuffling of arguments */
-    /* (x0 = closure, x1 = arg1, x2 = arg2, x3 = arg3) */
-        mov     TMP, x0
-        mov     x0, x1          /* x0 = first arg */
-        mov     x1, x2          /* x1 = second arg */
-        mov     x2, x3          /* x2 = third arg */
-        mov     x3, TMP         /* x3 = closure environment */
-        ADDRGLOBAL(ARG, caml_apply3)
-        b       .Ljump_to_caml
-        CFI_ENDPROC
-        .type   caml_callback3_exn, %function
-        .size   caml_callback3_exn, .-caml_callback3_exn
-
-        .align  2
-        .globl  caml_ml_array_bound_error
-caml_ml_array_bound_error:
-        CFI_STARTPROC
-        PROFILE
-    /* Load address of [caml_array_bound_error] in ARG */
-        ADDRGLOBAL(ARG, caml_array_bound_error)
-    /* Call that function */
-        b       caml_c_call
-        CFI_ENDPROC
-        .type   caml_ml_array_bound_error, %function
-        .size   caml_ml_array_bound_error, .-caml_ml_array_bound_error
-
-        .globl  caml_system__code_end
-caml_system__code_end:
-
-/* GC roots for callback */
-
-        .data
-        .align  3
-        .globl  caml_system__frametable
-caml_system__frametable:
-        .quad   1               /* one descriptor */
-        .quad   .Lcaml_retaddr  /* return address into callback */
-        .short  -1              /* negative frame size => use callback link */
-        .short  0               /* no roots */
-        .align  3
-        .type   caml_system__frametable, %object
-        .size   caml_system__frametable, .-caml_system__frametable
-
-/* Mark stack as non-executable */
-        .section .note.GNU-stack,"",%progbits
diff --git a/asmrun/backtrace_prim.c b/asmrun/backtrace_prim.c
deleted file mode 100644
index 7691a7b4..00000000
--- a/asmrun/backtrace_prim.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/**************************************************************************/
-/*                                                                        */
-/*                                 OCaml                                  */
-/*                                                                        */
-/*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           */
-/*                                                                        */
-/*   Copyright 2006 Institut National de Recherche en Informatique et     */
-/*     en Automatique.                                                    */
-/*                                                                        */
-/*   All rights reserved.  This file is distributed under the terms of    */
-/*   the GNU Lesser General Public License version 2.1, with the          */
-/*   special exception on linking described in the file LICENSE.          */
-/*                                                                        */
-/**************************************************************************/
-
-#define CAML_INTERNALS
-
-/* Stack backtrace for uncaught exceptions */
-
-#include 
-#include 
-#include 
-
-#include "caml/alloc.h"
-#include "caml/backtrace.h"
-#include "caml/backtrace_prim.h"
-#include "caml/memory.h"
-#include "caml/misc.h"
-#include "caml/mlvalues.h"
-#include "caml/stack.h"
-
-/* Returns the next frame descriptor (or NULL if none is available),
-   and updates *pc and *sp to point to the following one.  */
-frame_descr * caml_next_frame_descriptor(uintnat * pc, char ** sp)
-{
-  frame_descr * d;
-  uintnat h;
-
-  while (1) {
-    h = Hash_retaddr(*pc);
-    while (1) {
-      d = caml_frame_descriptors[h];
-      if (d == NULL) return NULL; /* happens if some code compiled without -g */
-      if (d->retaddr == *pc) break;
-      h = (h+1) & caml_frame_descriptors_mask;
-    }
-    /* Skip to next frame */
-    if (d->frame_size != 0xFFFF) {
-      /* Regular frame, update sp/pc and return the frame descriptor */
-#ifndef Stack_grows_upwards
-      *sp += (d->frame_size & 0xFFFC);
-#else
-      *sp -= (d->frame_size & 0xFFFC);
-#endif
-      *pc = Saved_return_address(*sp);
-#ifdef Mask_already_scanned
-      *pc = Mask_already_scanned(*pc);
-#endif
-      return d;
-    } else {
-      /* Special frame marking the top of a stack chunk for an ML callback.
-         Skip C portion of stack and continue with next ML stack chunk. */
-      struct caml_context * next_context = Callback_link(*sp);
-      *sp = next_context->bottom_of_stack;
-      *pc = next_context->last_retaddr;
-      /* A null sp means no more ML stack chunks; stop here. */
-      if (*sp == NULL) return NULL;
-    }
-  }
-}
-
-int caml_alloc_backtrace_buffer(void){
-  CAMLassert(caml_backtrace_pos == 0);
-  caml_backtrace_buffer =
-    caml_stat_alloc_noexc(BACKTRACE_BUFFER_SIZE * sizeof(backtrace_slot));
-  if (caml_backtrace_buffer == NULL) return -1;
-  return 0;
-}
-
-/* Stores the return addresses contained in the given stack fragment
-   into the backtrace array ; this version is performance-sensitive as
-   it is called at each [raise] in a program compiled with [-g], so we
-   preserved the global, statically bounded buffer of the old
-   implementation -- before the more flexible
-   [caml_get_current_callstack] was implemented. */
-void caml_stash_backtrace(value exn, uintnat pc, char * sp, char * trapsp)
-{
-  if (exn != caml_backtrace_last_exn) {
-    caml_backtrace_pos = 0;
-    caml_backtrace_last_exn = exn;
-  }
-
-  if (caml_backtrace_buffer == NULL && caml_alloc_backtrace_buffer() == -1)
-    return;
-
-  /* iterate on each frame  */
-  while (1) {
-    frame_descr * descr = caml_next_frame_descriptor(&pc, &sp);
-    if (descr == NULL) return;
-    /* store its descriptor in the backtrace buffer */
-    if (caml_backtrace_pos >= BACKTRACE_BUFFER_SIZE) return;
-    caml_backtrace_buffer[caml_backtrace_pos++] = (backtrace_slot) descr;
-
-    /* Stop when we reach the current exception handler */
-#ifndef Stack_grows_upwards
-    if (sp > trapsp) return;
-#else
-    if (sp < trapsp) return;
-#endif
-  }
-}
-
-/* Stores upto [max_frames_value] frames of the current call stack to
-   return to the user. This is used not in an exception-raising
-   context, but only when the user requests to save the trace
-   (hopefully less often). Instead of using a bounded buffer as
-   [caml_stash_backtrace], we first traverse the stack to compute the
-   right size, then allocate space for the trace. */
-CAMLprim value caml_get_current_callstack(value max_frames_value)
-{
-  CAMLparam1(max_frames_value);
-  CAMLlocal1(trace);
-
-  /* we use `intnat` here because, were it only `int`, passing `max_int`
-     from the OCaml side would overflow on 64bits machines. */
-  intnat max_frames = Long_val(max_frames_value);
-  intnat trace_size;
-
-  /* first compute the size of the trace */
-  {
-    uintnat pc = caml_last_return_address;
-    /* note that [caml_bottom_of_stack] always points to the most recent
-     * frame, independently of the [Stack_grows_upwards] setting */
-    char * sp = caml_bottom_of_stack;
-    char * limitsp = caml_top_of_stack;
-
-    trace_size = 0;
-    while (1) {
-      frame_descr * descr = caml_next_frame_descriptor(&pc, &sp);
-      if (descr == NULL) break;
-      if (trace_size >= max_frames) break;
-      ++trace_size;
-
-#ifndef Stack_grows_upwards
-      if (sp > limitsp) break;
-#else
-      if (sp < limitsp) break;
-#endif
-    }
-  }
-
-  trace = caml_alloc((mlsize_t) trace_size, 0);
-
-  /* then collect the trace */
-  {
-    uintnat pc = caml_last_return_address;
-    char * sp = caml_bottom_of_stack;
-    intnat trace_pos;
-
-    for (trace_pos = 0; trace_pos < trace_size; trace_pos++) {
-      frame_descr * descr = caml_next_frame_descriptor(&pc, &sp);
-      CAMLassert(descr != NULL);
-      Field(trace, trace_pos) = Val_backtrace_slot((backtrace_slot) descr);
-    }
-  }
-
-  CAMLreturn(trace);
-}
-
-
-debuginfo caml_debuginfo_extract(backtrace_slot slot)
-{
-  uintnat infoptr;
-  frame_descr * d = (frame_descr *)slot;
-
-  if ((d->frame_size & 1) == 0) {
-    return NULL;
-  }
-  /* Recover debugging info */
-  infoptr = ((uintnat) d +
-             sizeof(char *) + sizeof(short) + sizeof(short) +
-             sizeof(short) * d->num_live + sizeof(frame_descr *) - 1)
-            & -sizeof(frame_descr *);
-  return *((debuginfo*)infoptr);
-}
-
-debuginfo caml_debuginfo_next(debuginfo dbg)
-{
-  uint32_t * infoptr;
-
-  if (dbg == NULL)
-    return NULL;
-
-  infoptr = dbg;
-  infoptr += 2; /* Two packed info fields */
-  return *((debuginfo*)infoptr);
-}
-
-/* Extract location information for the given frame descriptor */
-void caml_debuginfo_location(debuginfo dbg, /*out*/ struct caml_loc_info * li)
-{
-  uint32_t info1, info2;
-
-  /* If no debugging information available, print nothing.
-     When everything is compiled with -g, this corresponds to
-     compiler-inserted re-raise operations. */
-  if (dbg == NULL) {
-    li->loc_valid = 0;
-    li->loc_is_raise = 1;
-    li->loc_is_inlined = 0;
-    return;
-  }
-  /* Recover debugging info */
-  info1 = ((uint32_t *)dbg)[0];
-  info2 = ((uint32_t *)dbg)[1];
-  /* Format of the two info words:
-       llllllllllllllllllll aaaaaaaa bbbbbbbbbb nnnnnnnnnnnnnnnnnnnnnnnn kk
-                          44       36         26                       2  0
-                       (32+12)    (32+4)
-     k ( 2 bits): 0 if it's a call
-                  1 if it's a raise
-     n (24 bits): offset (in 4-byte words) of file name relative to dbg
-     l (20 bits): line number
-     a ( 8 bits): beginning of character range
-     b (10 bits): end of character range */
-  li->loc_valid = 1;
-  li->loc_is_raise = (info1 & 3) == 1;
-  li->loc_is_inlined = caml_debuginfo_next(dbg) != NULL;
-  li->loc_filename = (char *) dbg + (info1 & 0x3FFFFFC);
-  li->loc_lnum = info2 >> 12;
-  li->loc_startchr = (info2 >> 4) & 0xFF;
-  li->loc_endchr = ((info2 & 0xF) << 6) | (info1 >> 26);
-}
-
-CAMLprim value caml_add_debug_info(backtrace_slot start, value size,
-                                   value events)
-{
-  return Val_unit;
-}
-
-CAMLprim value caml_remove_debug_info(backtrace_slot start)
-{
-  return Val_unit;
-}
-
-int caml_debug_info_available(void)
-{
-  return 1;
-}
diff --git a/asmrun/clambda_checks.c b/asmrun/clambda_checks.c
deleted file mode 100644
index bf1cb85e..00000000
--- a/asmrun/clambda_checks.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/**************************************************************************/
-/*                                                                        */
-/*                                 OCaml                                  */
-/*                                                                        */
-/*                       Pierre Chambart, OCamlPro                        */
-/*                   Mark Shinwell, Jane Street Europe                    */
-/*                                                                        */
-/*   Copyright 2013--2016 OCamlPro SAS                                    */
-/*   Copyright 2014--2016 Jane Street Group LLC                           */
-/*                                                                        */
-/*   All rights reserved.  This file is distributed under the terms of    */
-/*   the GNU Lesser General Public License version 2.1, with the          */
-/*   special exception on linking described in the file LICENSE.          */
-/*                                                                        */
-/**************************************************************************/
-
-/* Runtime checks to try to catch errors in code generation.
-   See flambda_to_clambda.ml for more information. */
-
-#include 
-
-#include 
-
-value caml_check_value_is_closure(value v, value v_descr)
-{
-  const char* descr = String_val(v_descr);
-  value orig_v = v;
-
-  if (v == (value) 0) {
-    fprintf(stderr, "NULL is not a closure: %s\n",
-      descr);
-    abort();
-  }
-  if (!Is_block(v)) {
-    fprintf(stderr,
-      "Expecting a closure, got a non-boxed value %p: %s\n",
-      (void*) v, descr);
-    abort();
-  }
-  if (!(Tag_val(v) == Closure_tag || Tag_val(v) == Infix_tag)) {
-    fprintf(stderr,
-      "Expecting a closure, got a boxed value with tag %i: %s\n",
-      Tag_val(v), descr);
-    abort();
-  }
-  if (Tag_val(v) == Infix_tag) {
-    v -= Infix_offset_val(v);
-    CAMLassert(Tag_val(v) == Closure_tag);
-  }
-  CAMLassert(Wosize_val(v) >= 2);
-
-  return orig_v;
-}
-
-value caml_check_field_access(value v, value pos, value v_descr)
-{
-  const char* descr = String_val(v_descr);
-  value orig_v = v;
-  if (v == (value) 0) {
-    fprintf(stderr,
-      "Access to field %" ARCH_INT64_PRINTF_FORMAT
-      "u of NULL: %s\n", (ARCH_UINT64_TYPE) Long_val(pos), descr);
-    abort();
-  }
-  if (!Is_block(v)) {
-    fprintf(stderr,
-      "Access to field %" ARCH_INT64_PRINTF_FORMAT
-      "u of non-boxed value %p is illegal: %s\n",
-      (ARCH_UINT64_TYPE) Long_val(pos), (void*) v, descr);
-    abort();
-  }
-  if (Tag_val(v) == Infix_tag) {
-    uintnat offset = Infix_offset_val(v);
-    v -= offset;
-    pos += offset / sizeof(value);
-  }
-  CAMLassert(Long_val(pos) >= 0);
-  if (Long_val(pos) >= Wosize_val(v)) {
-    fprintf(stderr,
-      "Access to field %" ARCH_INT64_PRINTF_FORMAT
-      "u of value %p of size %" ARCH_INT64_PRINTF_FORMAT "u is illegal: %s\n",
-      (ARCH_UINT64_TYPE) Long_val(pos), (void*) v,
-      (ARCH_UINT64_TYPE) Wosize_val(v),
-      descr);
-    abort();
-  }
-  return orig_v;
-}
diff --git a/asmrun/fail.c b/asmrun/fail.c
deleted file mode 100644
index e2df8cb8..00000000
--- a/asmrun/fail.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/**************************************************************************/
-/*                                                                        */
-/*                                 OCaml                                  */
-/*                                                                        */
-/*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           */
-/*                                                                        */
-/*   Copyright 1996 Institut National de Recherche en Informatique et     */
-/*     en Automatique.                                                    */
-/*                                                                        */
-/*   All rights reserved.  This file is distributed under the terms of    */
-/*   the GNU Lesser General Public License version 2.1, with the          */
-/*   special exception on linking described in the file LICENSE.          */
-/*                                                                        */
-/**************************************************************************/
-
-#define CAML_INTERNALS
-
-/* Raising exceptions from C. */
-
-#include 
-#include 
-#include "caml/alloc.h"
-#include "caml/fail.h"
-#include "caml/io.h"
-#include "caml/gc.h"
-#include "caml/memory.h"
-#include "caml/mlvalues.h"
-#include "caml/printexc.h"
-#include "caml/signals.h"
-#include "caml/stack.h"
-#include "caml/roots.h"
-#include "caml/callback.h"
-
-/* The globals holding predefined exceptions */
-
-typedef value caml_generated_constant[1];
-
-extern caml_generated_constant
-  caml_exn_Out_of_memory,
-  caml_exn_Sys_error,
-  caml_exn_Failure,
-  caml_exn_Invalid_argument,
-  caml_exn_End_of_file,
-  caml_exn_Division_by_zero,
-  caml_exn_Not_found,
-  caml_exn_Match_failure,
-  caml_exn_Sys_blocked_io,
-  caml_exn_Stack_overflow,
-  caml_exn_Assert_failure,
-  caml_exn_Undefined_recursive_module;
-
-/* Exception raising */
-
-CAMLnoreturn_start
-  extern void caml_raise_exception (value bucket)
-CAMLnoreturn_end;
-
-char * caml_exception_pointer = NULL;
-
-void caml_raise(value v)
-{
-  Unlock_exn();
-  if (caml_exception_pointer == NULL) caml_fatal_uncaught_exception(v);
-
-#ifndef Stack_grows_upwards
-#define PUSHED_AFTER <
-#else
-#define PUSHED_AFTER >
-#endif
-  while (caml_local_roots != NULL &&
-         (char *) caml_local_roots PUSHED_AFTER caml_exception_pointer) {
-    caml_local_roots = caml_local_roots->next;
-  }
-#undef PUSHED_AFTER
-
-  caml_raise_exception(v);
-}
-
-void caml_raise_constant(value tag)
-{
-  caml_raise(tag);
-}
-
-void caml_raise_with_arg(value tag, value arg)
-{
-  CAMLparam2 (tag, arg);
-  CAMLlocal1 (bucket);
-
-  bucket = caml_alloc_small (2, 0);
-  Field(bucket, 0) = tag;
-  Field(bucket, 1) = arg;
-  caml_raise(bucket);
-  CAMLnoreturn;
-}
-
-void caml_raise_with_args(value tag, int nargs, value args[])
-{
-  CAMLparam1 (tag);
-  CAMLxparamN (args, nargs);
-  value bucket;
-  int i;
-
-  CAMLassert(1 + nargs <= Max_young_wosize);
-  bucket = caml_alloc_small (1 + nargs, 0);
-  Field(bucket, 0) = tag;
-  for (i = 0; i < nargs; i++) Field(bucket, 1 + i) = args[i];
-  caml_raise(bucket);
-  CAMLnoreturn;
-}
-
-void caml_raise_with_string(value tag, char const *msg)
-{
-  CAMLparam1(tag);
-  value v_msg = caml_copy_string(msg);
-  caml_raise_with_arg(tag, v_msg);
-  CAMLnoreturn;
-}
-
-void caml_failwith (char const *msg)
-{
-  caml_raise_with_string((value) caml_exn_Failure, msg);
-}
-
-void caml_failwith_value (value msg)
-{
-  caml_raise_with_arg((value) caml_exn_Failure, msg);
-}
-
-void caml_invalid_argument (char const *msg)
-{
-  caml_raise_with_string((value) caml_exn_Invalid_argument, msg);
-}
-
-void caml_invalid_argument_value (value msg)
-{
-  caml_raise_with_arg((value) caml_exn_Invalid_argument, msg);
-}
-
-void caml_raise_out_of_memory(void)
-{
-  caml_raise_constant((value) caml_exn_Out_of_memory);
-}
-
-void caml_raise_stack_overflow(void)
-{
-  caml_raise_constant((value) caml_exn_Stack_overflow);
-}
-
-void caml_raise_sys_error(value msg)
-{
-  caml_raise_with_arg((value) caml_exn_Sys_error, msg);
-}
-
-void caml_raise_end_of_file(void)
-{
-  caml_raise_constant((value) caml_exn_End_of_file);
-}
-
-void caml_raise_zero_divide(void)
-{
-  caml_raise_constant((value) caml_exn_Division_by_zero);
-}
-
-void caml_raise_not_found(void)
-{
-  caml_raise_constant((value) caml_exn_Not_found);
-}
-
-void caml_raise_sys_blocked_io(void)
-{
-  caml_raise_constant((value) caml_exn_Sys_blocked_io);
-}
-
-/* We use a pre-allocated exception because we can't
-   do a GC before the exception is raised (lack of stack descriptors
-   for the ccall to [caml_array_bound_error]).  */
-
-static value * caml_array_bound_error_exn = NULL;
-
-void caml_array_bound_error(void)
-{
-  if (caml_array_bound_error_exn == NULL) {
-    caml_array_bound_error_exn =
-      caml_named_value("Pervasives.array_bound_error");
-    if (caml_array_bound_error_exn == NULL) {
-      fprintf(stderr, "Fatal error: exception "
-                      "Invalid_argument(\"index out of bounds\")\n");
-      exit(2);
-    }
-  }
-  caml_raise(*caml_array_bound_error_exn);
-}
-
-int caml_is_special_exception(value exn) {
-  return exn == (value) caml_exn_Match_failure
-    || exn == (value) caml_exn_Assert_failure
-    || exn == (value) caml_exn_Undefined_recursive_module;
-}
diff --git a/asmrun/roots.c b/asmrun/roots.c
deleted file mode 100644
index c9526b2a..00000000
--- a/asmrun/roots.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/**************************************************************************/
-/*                                                                        */
-/*                                 OCaml                                  */
-/*                                                                        */
-/*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           */
-/*                                                                        */
-/*   Copyright 1996 Institut National de Recherche en Informatique et     */
-/*     en Automatique.                                                    */
-/*                                                                        */
-/*   All rights reserved.  This file is distributed under the terms of    */
-/*   the GNU Lesser General Public License version 2.1, with the          */
-/*   special exception on linking described in the file LICENSE.          */
-/*                                                                        */
-/**************************************************************************/
-
-#define CAML_INTERNALS
-
-/* To walk the memory roots for garbage collection */
-
-#include "caml/finalise.h"
-#include "caml/globroots.h"
-#include "caml/memory.h"
-#include "caml/major_gc.h"
-#include "caml/minor_gc.h"
-#include "caml/misc.h"
-#include "caml/mlvalues.h"
-#include "caml/stack.h"
-#include "caml/roots.h"
-#include 
-#include 
-
-/* Roots registered from C functions */
-
-struct caml__roots_block *caml_local_roots = NULL;
-
-void (*caml_scan_roots_hook) (scanning_action) = NULL;
-
-/* The hashtable of frame descriptors */
-frame_descr ** caml_frame_descriptors = NULL;
-int caml_frame_descriptors_mask = 0;
-
-/* Linked-list */
-
-typedef struct link {
-  void *data;
-  struct link *next;
-} link;
-
-static link *cons(void *data, link *tl) {
-  link *lnk = caml_stat_alloc(sizeof(link));
-  lnk->data = data;
-  lnk->next = tl;
-  return lnk;
-}
-
-#define iter_list(list,lnk) \
-  for (lnk = list; lnk != NULL; lnk = lnk->next)
-
-/* Linked-list of frametables */
-
-static link *frametables = NULL;
-static intnat num_descr = 0;
-
-static int count_descriptors(link *list) {
-  intnat num_descr = 0;
-  link *lnk;
-  iter_list(list,lnk) {
-    num_descr += *((intnat*) lnk->data);
-  }
-  return num_descr;
-}
-
-static link* frametables_list_tail(link *list) {
-  link *lnk, *tail = NULL;
-  iter_list(list,lnk) {
-    tail = lnk;
-  }
-  return tail;
-}
-
-static frame_descr * next_frame_descr(frame_descr * d) {
-  uintnat nextd;
-  nextd =
-    ((uintnat)d +
-     sizeof(char *) + sizeof(short) + sizeof(short) +
-     sizeof(short) * d->num_live + sizeof(frame_descr *) - 1)
-    & -sizeof(frame_descr *);
-  if (d->frame_size & 1) nextd += sizeof(void *); /* pointer to debuginfo */
-  return((frame_descr *) nextd);
-}
-
-static void fill_hashtable(link *frametables) {
-  intnat len, j;
-  intnat * tbl;
-  frame_descr * d;
-  uintnat h;
-  link *lnk = NULL;
-
-  iter_list(frametables,lnk) {
-    tbl = (intnat*) lnk->data;
-    len = *tbl;
-    d = (frame_descr *)(tbl + 1);
-    for (j = 0; j < len; j++) {
-      h = Hash_retaddr(d->retaddr);
-      while (caml_frame_descriptors[h] != NULL) {
-        h = (h+1) & caml_frame_descriptors_mask;
-      }
-      caml_frame_descriptors[h] = d;
-      d = next_frame_descr(d);
-    }
-  }
-}
-
-static void init_frame_descriptors(link *new_frametables)
-{
-  intnat tblsize, increase, i;
-  link *tail = NULL;
-
-  CAMLassert(new_frametables);
-
-  tail = frametables_list_tail(new_frametables);
-  increase = count_descriptors(new_frametables);
-  tblsize = caml_frame_descriptors_mask + 1;
-
-  /* Reallocate the caml_frame_descriptor table if it is too small */
-  if(tblsize < (num_descr + increase) * 2) {
-
-    /* Merge both lists */
-    tail->next = frametables;
-    frametables = NULL;
-
-    /* [num_descr] can be less than [num_descr + increase] if frame
-       tables where unregistered */
-    num_descr = count_descriptors(new_frametables);
-
-    tblsize = 4;
-    while (tblsize < 2 * num_descr) tblsize *= 2;
-
-    caml_frame_descriptors_mask = tblsize - 1;
-    if(caml_frame_descriptors) caml_stat_free(caml_frame_descriptors);
-    caml_frame_descriptors =
-      (frame_descr **) caml_stat_alloc(tblsize * sizeof(frame_descr *));
-    for (i = 0; i < tblsize; i++) caml_frame_descriptors[i] = NULL;
-
-    fill_hashtable(new_frametables);
-  } else {
-    num_descr += increase;
-    fill_hashtable(new_frametables);
-    tail->next = frametables;
-  }
-
-  frametables = new_frametables;
-}
-
-void caml_init_frame_descriptors(void) {
-  intnat i;
-  link *new_frametables = NULL;
-  for (i = 0; caml_frametable[i] != 0; i++)
-    new_frametables = cons(caml_frametable[i],new_frametables);
-  init_frame_descriptors(new_frametables);
-}
-
-void caml_register_frametable(intnat *table) {
-  link *new_frametables = cons(table,NULL);
-  init_frame_descriptors(new_frametables);
-}
-
-static void remove_entry(frame_descr * d) {
-  uintnat i;
-  uintnat r;
-  uintnat j;
-
-  i = Hash_retaddr(d->retaddr);
-  while (caml_frame_descriptors[i] != d) {
-    i = (i+1) & caml_frame_descriptors_mask;
-  }
-
- r1:
-  j = i;
-  caml_frame_descriptors[i] = NULL;
- r2:
-  i = (i+1) & caml_frame_descriptors_mask;
-  // r3
-  if(caml_frame_descriptors[i] == NULL) return;
-  r = Hash_retaddr(caml_frame_descriptors[i]->retaddr);
-  /* If r is between i and j (cyclically), i.e. if
-     caml_frame_descriptors[i]->retaddr don't need to be moved */
-  if(( ( j < r )  && ( r <= i ) ) ||
-     ( ( i < j )  && ( j < r )  ) ||      /* i cycled, r not */
-     ( ( r <= i ) && ( i < j ) )     ) {  /* i and r cycled */
-    goto r2;
-  }
-  // r4
-  caml_frame_descriptors[j] = caml_frame_descriptors[i];
-  goto r1;
-}
-
-void caml_unregister_frametable(intnat *table) {
-  intnat len, j;
-  link *lnk;
-  link *previous = frametables;
-  frame_descr * d;
-
-  len = *table;
-  d = (frame_descr *)(table + 1);
-  for (j = 0; j < len; j++) {
-    remove_entry(d);
-    d = next_frame_descr(d);
-  }
-
-  iter_list(frametables,lnk) {
-    if(lnk->data == table) {
-      previous->next = lnk->next;
-      caml_stat_free(lnk);
-      break;
-    }
-    previous = lnk;
-  }
-}
-
-/* Communication with [caml_start_program] and [caml_call_gc]. */
-
-char * caml_top_of_stack;
-char * caml_bottom_of_stack = NULL; /* no stack initially */
-uintnat caml_last_return_address = 1; /* not in OCaml code initially */
-value * caml_gc_regs;
-intnat caml_globals_inited = 0;
-static intnat caml_globals_scanned = 0;
-static link * caml_dyn_globals = NULL;
-
-void caml_register_dyn_global(void *v) {
-  caml_dyn_globals = cons((void*) v,caml_dyn_globals);
-}
-
-/* Call [caml_oldify_one] on (at least) all the roots that point to the minor
-   heap. */
-void caml_oldify_local_roots (void)
-{
-  char * sp;
-  uintnat retaddr;
-  value * regs;
-  frame_descr * d;
-  uintnat h;
-  int i, j, n, ofs;
-#ifdef Stack_grows_upwards
-  short * p;  /* PR#4339: stack offsets are negative in this case */
-#else
-  unsigned short * p;
-#endif
-  value * glob;
-  value * root;
-  struct caml__roots_block *lr;
-  link *lnk;
-
-  /* The global roots */
-  for (i = caml_globals_scanned;
-       i <= caml_globals_inited && caml_globals[i] != 0;
-       i++) {
-    for(glob = caml_globals[i]; *glob != 0; glob++) {
-      for (j = 0; j < Wosize_val(*glob); j++){
-        Oldify (&Field (*glob, j));
-      }
-    }
-  }
-  caml_globals_scanned = caml_globals_inited;
-
-  /* Dynamic global roots */
-  iter_list(caml_dyn_globals, lnk) {
-    for(glob = (value *) lnk->data; *glob != 0; glob++) {
-      for (j = 0; j < Wosize_val(*glob); j++){
-        Oldify (&Field (*glob, j));
-      }
-    }
-  }
-
-  /* The stack and local roots */
-  sp = caml_bottom_of_stack;
-  retaddr = caml_last_return_address;
-  regs = caml_gc_regs;
-  if (sp != NULL) {
-    while (1) {
-      /* Find the descriptor corresponding to the return address */
-      h = Hash_retaddr(retaddr);
-      while(1) {
-        d = caml_frame_descriptors[h];
-        if (d->retaddr == retaddr) break;
-        h = (h+1) & caml_frame_descriptors_mask;
-      }
-      if (d->frame_size != 0xFFFF) {
-        /* Scan the roots in this frame */
-        for (p = d->live_ofs, n = d->num_live; n > 0; n--, p++) {
-          ofs = *p;
-          if (ofs & 1) {
-            root = regs + (ofs >> 1);
-          } else {
-            root = (value *)(sp + ofs);
-          }
-          Oldify (root);
-        }
-        /* Move to next frame */
-#ifndef Stack_grows_upwards
-        sp += (d->frame_size & 0xFFFC);
-#else
-        sp -= (d->frame_size & 0xFFFC);
-#endif
-        retaddr = Saved_return_address(sp);
-#ifdef Already_scanned
-        /* Stop here if the frame has been scanned during earlier GCs  */
-        if (Already_scanned(sp, retaddr)) break;
-        /* Mark frame as already scanned */
-        Mark_scanned(sp, retaddr);
-#endif
-      } else {
-        /* This marks the top of a stack chunk for an ML callback.
-           Skip C portion of stack and continue with next ML stack chunk. */
-        struct caml_context * next_context = Callback_link(sp);
-        sp = next_context->bottom_of_stack;
-        retaddr = next_context->last_retaddr;
-        regs = next_context->gc_regs;
-        /* A null sp means no more ML stack chunks; stop here. */
-        if (sp == NULL) break;
-      }
-    }
-  }
-  /* Local C roots */
-  for (lr = caml_local_roots; lr != NULL; lr = lr->next) {
-    for (i = 0; i < lr->ntables; i++){
-      for (j = 0; j < lr->nitems; j++){
-        root = &(lr->tables[i][j]);
-        Oldify (root);
-      }
-    }
-  }
-  /* Global C roots */
-  caml_scan_global_young_roots(&caml_oldify_one);
-  /* Finalised values */
-  caml_final_oldify_young_roots ();
-  /* Hook */
-  if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(&caml_oldify_one);
-}
-
-uintnat caml_incremental_roots_count = 0;
-
-/* Call [caml_darken] on all roots, incrementally:
-   [caml_darken_all_roots_start] does the non-incremental part and
-   sets things up for [caml_darken_all_roots_slice].
-*/
-void caml_darken_all_roots_start (void)
-{
-  caml_do_roots (caml_darken, 0);
-}
-
-/* Call [caml_darken] on at most [work] global roots. Return the
-   amount of work not done, if any. If this is strictly positive,
-   the darkening is done.
- */
-intnat caml_darken_all_roots_slice (intnat work)
-{
-  static int i, j;
-  static value *glob;
-  static int do_resume = 0;
-  static mlsize_t roots_count = 0;
-  intnat remaining_work = work;
-  CAML_INSTR_SETUP (tmr, "");
-
-  /* If the loop was started in a previous call, resume it. */
-  if (do_resume) goto resume;
-
-  /* This is the same loop as in [caml_do_roots], but we make it
-     suspend itself when [work] reaches 0. */
-  for (i = 0; caml_globals[i] != 0; i++) {
-    for(glob = caml_globals[i]; *glob != 0; glob++) {
-      for (j = 0; j < Wosize_val(*glob); j++){
-        caml_darken (Field (*glob, j), &Field (*glob, j));
-        -- remaining_work;
-        if (remaining_work == 0){
-          roots_count += work;
-          do_resume = 1;
-          goto suspend;
-        }
-      resume: ;
-      }
-    }
-  }
-
-  /* The loop finished normally, so all roots are now darkened. */
-  caml_incremental_roots_count = roots_count + work - remaining_work;
-  /* Prepare for the next run. */
-  do_resume = 0;
-  roots_count = 0;
-
- suspend:
-  /* Do this in both cases. */
-  CAML_INSTR_TIME (tmr, "major/mark/global_roots_slice");
-  return remaining_work;
-}
-
-void caml_do_roots (scanning_action f, int do_globals)
-{
-  int i, j;
-  value * glob;
-  link *lnk;
-  CAML_INSTR_SETUP (tmr, "major_roots");
-
-  if (do_globals){
-    /* The global roots */
-    for (i = 0; caml_globals[i] != 0; i++) {
-      for(glob = caml_globals[i]; *glob != 0; glob++) {
-        for (j = 0; j < Wosize_val(*glob); j++)
-          f (Field (*glob, j), &Field (*glob, j));
-      }
-    }
-  }
-  /* Dynamic global roots */
-  iter_list(caml_dyn_globals, lnk) {
-    for(glob = (value *) lnk->data; *glob != 0; glob++) {
-      for (j = 0; j < Wosize_val(*glob); j++){
-        f (Field (*glob, j), &Field (*glob, j));
-      }
-    }
-  }
-  CAML_INSTR_TIME (tmr, "major_roots/dynamic_global");
-  /* The stack and local roots */
-  caml_do_local_roots(f, caml_bottom_of_stack, caml_last_return_address,
-                      caml_gc_regs, caml_local_roots);
-  CAML_INSTR_TIME (tmr, "major_roots/local");
-  /* Global C roots */
-  caml_scan_global_roots(f);
-  CAML_INSTR_TIME (tmr, "major_roots/C");
-  /* Finalised values */
-  caml_final_do_roots (f);
-  CAML_INSTR_TIME (tmr, "major_roots/finalised");
-  /* Hook */
-  if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(f);
-  CAML_INSTR_TIME (tmr, "major_roots/hook");
-}
-
-void caml_do_local_roots(scanning_action f, char * bottom_of_stack,
-                         uintnat last_retaddr, value * gc_regs,
-                         struct caml__roots_block * local_roots)
-{
-  char * sp;
-  uintnat retaddr;
-  value * regs;
-  frame_descr * d;
-  uintnat h;
-  int i, j, n, ofs;
-#ifdef Stack_grows_upwards
-  short * p;  /* PR#4339: stack offsets are negative in this case */
-#else
-  unsigned short * p;
-#endif
-  value * root;
-  struct caml__roots_block *lr;
-
-  sp = bottom_of_stack;
-  retaddr = last_retaddr;
-  regs = gc_regs;
-  if (sp != NULL) {
-    while (1) {
-      /* Find the descriptor corresponding to the return address */
-      h = Hash_retaddr(retaddr);
-      while(1) {
-        d = caml_frame_descriptors[h];
-        if (d->retaddr == retaddr) break;
-        h = (h+1) & caml_frame_descriptors_mask;
-      }
-      if (d->frame_size != 0xFFFF) {
-        /* Scan the roots in this frame */
-        for (p = d->live_ofs, n = d->num_live; n > 0; n--, p++) {
-          ofs = *p;
-          if (ofs & 1) {
-            root = regs + (ofs >> 1);
-          } else {
-            root = (value *)(sp + ofs);
-          }
-          f (*root, root);
-        }
-        /* Move to next frame */
-#ifndef Stack_grows_upwards
-        sp += (d->frame_size & 0xFFFC);
-#else
-        sp -= (d->frame_size & 0xFFFC);
-#endif
-        retaddr = Saved_return_address(sp);
-#ifdef Mask_already_scanned
-        retaddr = Mask_already_scanned(retaddr);
-#endif
-      } else {
-        /* This marks the top of a stack chunk for an ML callback.
-           Skip C portion of stack and continue with next ML stack chunk. */
-        struct caml_context * next_context = Callback_link(sp);
-        sp = next_context->bottom_of_stack;
-        retaddr = next_context->last_retaddr;
-        regs = next_context->gc_regs;
-        /* A null sp means no more ML stack chunks; stop here. */
-        if (sp == NULL) break;
-      }
-    }
-  }
-  /* Local C roots */
-  for (lr = local_roots; lr != NULL; lr = lr->next) {
-    for (i = 0; i < lr->ntables; i++){
-      for (j = 0; j < lr->nitems; j++){
-        root = &(lr->tables[i][j]);
-        f (*root, root);
-      }
-    }
-  }
-}
-
-uintnat (*caml_stack_usage_hook)(void) = NULL;
-
-uintnat caml_stack_usage (void)
-{
-  uintnat sz;
-  sz = (value *) caml_top_of_stack - (value *) caml_bottom_of_stack;
-  if (caml_stack_usage_hook != NULL)
-    sz += (*caml_stack_usage_hook)();
-  return sz;
-}
diff --git a/asmrun/signals_asm.c b/asmrun/signals_asm.c
deleted file mode 100644
index 3895d752..00000000
--- a/asmrun/signals_asm.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/**************************************************************************/
-/*                                                                        */
-/*                                 OCaml                                  */
-/*                                                                        */
-/*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           */
-/*                                                                        */
-/*   Copyright 2007 Institut National de Recherche en Informatique et     */
-/*     en Automatique.                                                    */
-/*                                                                        */
-/*   All rights reserved.  This file is distributed under the terms of    */
-/*   the GNU Lesser General Public License version 2.1, with the          */
-/*   special exception on linking described in the file LICENSE.          */
-/*                                                                        */
-/**************************************************************************/
-
-#define CAML_INTERNALS
-
-/* Signal handling, code specific to the native-code compiler */
-
-#if defined(TARGET_amd64) && defined (SYS_linux)
-#define _GNU_SOURCE
-#endif
-#include 
-#include 
-#include 
-#include "caml/fail.h"
-#include "caml/memory.h"
-#include "caml/osdeps.h"
-#include "caml/signals.h"
-#include "caml/signals_machdep.h"
-#include "signals_osdep.h"
-#include "caml/stack.h"
-#include "caml/spacetime.h"
-
-#ifdef HAS_STACK_OVERFLOW_DETECTION
-#include 
-#include 
-#endif
-
-#ifndef NSIG
-#define NSIG 64
-#endif
-
-typedef void (*signal_handler)(int signo);
-
-#ifdef _WIN32
-extern signal_handler caml_win32_signal(int sig, signal_handler action);
-#define signal(sig,act) caml_win32_signal(sig,act)
-extern void caml_win32_overflow_detection();
-#endif
-
-extern char * caml_code_area_start, * caml_code_area_end;
-extern char caml_system__code_begin, caml_system__code_end;
-
-/* Do not use the macro from address_class.h here. */
-#undef Is_in_code_area
-#define Is_in_code_area(pc) \
- ( ((char *)(pc) >= caml_code_area_start && \
-    (char *)(pc) <= caml_code_area_end)     \
-|| ((char *)(pc) >= &caml_system__code_begin && \
-    (char *)(pc) <= &caml_system__code_end)     \
-|| (Classify_addr(pc) & In_code_area) )
-
-/* This routine is the common entry point for garbage collection
-   and signal handling.  It can trigger a callback to OCaml code.
-   With system threads, this callback can cause a context switch.
-   Hence [caml_garbage_collection] must not be called from regular C code
-   (e.g. the [caml_alloc] function) because the context of the call
-   (e.g. [intern_val]) may not allow context switching.
-   Only generated assembly code can call [caml_garbage_collection],
-   via the caml_call_gc assembly stubs.  */
-
-void caml_garbage_collection(void)
-{
-  caml_young_limit = caml_young_trigger;
-  if (caml_requested_major_slice || caml_requested_minor_gc ||
-      caml_young_ptr - caml_young_trigger < Max_young_whsize){
-    caml_gc_dispatch ();
-  }
-
-#ifdef WITH_SPACETIME
-  if (caml_young_ptr == caml_young_alloc_end) {
-    caml_spacetime_automatic_snapshot();
-  }
-#endif
-
-  caml_process_pending_signals();
-}
-
-DECLARE_SIGNAL_HANDLER(handle_signal)
-{
-  int saved_errno;
-  /* Save the value of errno (PR#5982). */
-  saved_errno = errno;
-#if !defined(POSIX_SIGNALS) && !defined(BSD_SIGNALS)
-  signal(sig, handle_signal);
-#endif
-  if (sig < 0 || sig >= NSIG) return;
-  if (caml_try_leave_blocking_section_hook ()) {
-    caml_execute_signal(sig, 1);
-    caml_enter_blocking_section_hook();
-  } else {
-    caml_record_signal(sig);
-  /* Some ports cache [caml_young_limit] in a register.
-     Use the signal context to modify that register too, but only if
-     we are inside OCaml code (not inside C code). */
-#if defined(CONTEXT_PC) && defined(CONTEXT_YOUNG_LIMIT)
-    if (Is_in_code_area(CONTEXT_PC))
-      CONTEXT_YOUNG_LIMIT = (context_reg) caml_young_limit;
-#endif
-  }
-  errno = saved_errno;
-}
-
-int caml_set_signal_action(int signo, int action)
-{
-  signal_handler oldact;
-#ifdef POSIX_SIGNALS
-  struct sigaction sigact, oldsigact;
-#else
-  signal_handler act;
-#endif
-
-#ifdef POSIX_SIGNALS
-  switch(action) {
-  case 0:
-    sigact.sa_handler = SIG_DFL;
-    sigact.sa_flags = 0;
-    break;
-  case 1:
-    sigact.sa_handler = SIG_IGN;
-    sigact.sa_flags = 0;
-    break;
-  default:
-    SET_SIGACT(sigact, handle_signal);
-    break;
-  }
-  sigemptyset(&sigact.sa_mask);
-  if (sigaction(signo, &sigact, &oldsigact) == -1) return -1;
-  oldact = oldsigact.sa_handler;
-#else
-  switch(action) {
-  case 0:  act = SIG_DFL; break;
-  case 1:  act = SIG_IGN; break;
-  default: act = handle_signal; break;
-  }
-  oldact = signal(signo, act);
-  if (oldact == SIG_ERR) return -1;
-#endif
-  if (oldact == (signal_handler) handle_signal)
-    return 2;
-  else if (oldact == SIG_IGN)
-    return 1;
-  else
-    return 0;
-}
-
-/* Machine- and OS-dependent handling of bound check trap */
-
-#if defined(TARGET_power) \
-  || defined(TARGET_s390x)
-DECLARE_SIGNAL_HANDLER(trap_handler)
-{
-#if defined(SYS_rhapsody)
-  /* Unblock SIGTRAP */
-  { sigset_t mask;
-    sigemptyset(&mask);
-    sigaddset(&mask, SIGTRAP);
-    sigprocmask(SIG_UNBLOCK, &mask, NULL);
-  }
-#endif
-  caml_exception_pointer = (char *) CONTEXT_EXCEPTION_POINTER;
-  caml_young_ptr = (value *) CONTEXT_YOUNG_PTR;
-  caml_bottom_of_stack = (char *) CONTEXT_SP;
-  caml_last_return_address = (uintnat) CONTEXT_PC;
-  caml_array_bound_error();
-}
-#endif
-
-/* Machine- and OS-dependent handling of stack overflow */
-
-#ifdef HAS_STACK_OVERFLOW_DETECTION
-
-static char * system_stack_top;
-static char sig_alt_stack[SIGSTKSZ];
-
-#if defined(SYS_linux)
-/* PR#4746: recent Linux kernels with support for stack randomization
-   silently add 2 Mb of stack space on top of RLIMIT_STACK.
-   2 Mb = 0x200000, to which we add 8 kB (=0x2000) for overshoot. */
-#define EXTRA_STACK 0x202000
-#else
-#define EXTRA_STACK 0x2000
-#endif
-
-#ifdef RETURN_AFTER_STACK_OVERFLOW
-extern void caml_stack_overflow(void);
-#endif
-
-DECLARE_SIGNAL_HANDLER(segv_handler)
-{
-  struct rlimit limit;
-  struct sigaction act;
-  char * fault_addr;
-
-  /* Sanity checks:
-     - faulting address is word-aligned
-     - faulting address is within the stack
-     - we are in OCaml code */
-  fault_addr = CONTEXT_FAULTING_ADDRESS;
-  if (((uintnat) fault_addr & (sizeof(intnat) - 1)) == 0
-      && getrlimit(RLIMIT_STACK, &limit) == 0
-      && fault_addr < system_stack_top
-      && fault_addr >= system_stack_top - limit.rlim_cur - EXTRA_STACK
-#ifdef CONTEXT_PC
-      && Is_in_code_area(CONTEXT_PC)
-#endif
-      ) {
-#ifdef RETURN_AFTER_STACK_OVERFLOW
-    /* Tweak the PC part of the context so that on return from this
-       handler, we jump to the asm function [caml_stack_overflow]
-       (from $ARCH.S). */
-#ifdef CONTEXT_PC
-    CONTEXT_PC = (context_reg) &caml_stack_overflow;
-#else
-#error "CONTEXT_PC must be defined if RETURN_AFTER_STACK_OVERFLOW is"
-#endif
-#else
-    /* Raise a Stack_overflow exception straight from this signal handler */
-#if defined(CONTEXT_YOUNG_PTR) && defined(CONTEXT_EXCEPTION_POINTER)
-    caml_exception_pointer = (char *) CONTEXT_EXCEPTION_POINTER;
-    caml_young_ptr = (value *) CONTEXT_YOUNG_PTR;
-#endif
-    caml_raise_stack_overflow();
-#endif
-  } else {
-    /* Otherwise, deactivate our exception handler and return,
-       causing fatal signal to be generated at point of error. */
-    act.sa_handler = SIG_DFL;
-    act.sa_flags = 0;
-    sigemptyset(&act.sa_mask);
-    sigaction(SIGSEGV, &act, NULL);
-  }
-}
-
-#endif
-
-/* Initialization of signal stuff */
-
-void caml_init_signals(void)
-{
-  /* Bound-check trap handling */
-
-#if defined(TARGET_power)
-  { struct sigaction act;
-    sigemptyset(&act.sa_mask);
-    SET_SIGACT(act, trap_handler);
-#if !defined(SYS_rhapsody)
-    act.sa_flags |= SA_NODEFER;
-#endif
-    sigaction(SIGTRAP, &act, NULL);
-  }
-#endif
-
-#if defined(TARGET_s390x)
-  { struct sigaction act;
-    sigemptyset(&act.sa_mask);
-    SET_SIGACT(act, trap_handler);
-    sigaction(SIGFPE, &act, NULL);
-  }
-#endif
-
-  /* Stack overflow handling */
-#ifdef HAS_STACK_OVERFLOW_DETECTION
-  {
-    stack_t stk;
-    struct sigaction act;
-    stk.ss_sp = sig_alt_stack;
-    stk.ss_size = SIGSTKSZ;
-    stk.ss_flags = 0;
-    SET_SIGACT(act, segv_handler);
-    act.sa_flags |= SA_ONSTACK | SA_NODEFER;
-    sigemptyset(&act.sa_mask);
-    system_stack_top = (char *) &act;
-    if (sigaltstack(&stk, NULL) == 0) { sigaction(SIGSEGV, &act, NULL); }
-  }
-#endif
-}
diff --git a/asmrun/spacetime.c b/asmrun/spacetime.c
deleted file mode 100644
index f6fc5c30..00000000
--- a/asmrun/spacetime.c
+++ /dev/null
@@ -1,1161 +0,0 @@
-/**************************************************************************/
-/*                                                                        */
-/*                                 OCaml                                  */
-/*                                                                        */
-/*            Mark Shinwell and Leo White, Jane Street Europe             */
-/*                                                                        */
-/*   Copyright 2013--2016, Jane Street Group, LLC                         */
-/*                                                                        */
-/*   All rights reserved.  This file is distributed under the terms of    */
-/*   the GNU Lesser General Public License version 2.1, with the          */
-/*   special exception on linking described in the file LICENSE.          */
-/*                                                                        */
-/**************************************************************************/
-
-#define CAML_INTERNALS
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include "caml/config.h"
-#ifdef HAS_UNISTD
-#include 
-#endif
-#ifdef _WIN32
-#include  /* for _getpid */
-#include  /* for _wgetcwd */
-#endif
-
-#include "caml/alloc.h"
-#include "caml/backtrace_prim.h"
-#include "caml/fail.h"
-#include "caml/gc.h"
-#include "caml/intext.h"
-#include "caml/major_gc.h"
-#include "caml/memory.h"
-#include "caml/minor_gc.h"
-#include "caml/misc.h"
-#include "caml/mlvalues.h"
-#include "caml/osdeps.h"
-#include "caml/roots.h"
-#include "caml/signals.h"
-#include "caml/stack.h"
-#include "caml/sys.h"
-#include "caml/spacetime.h"
-
-#ifdef WITH_SPACETIME
-
-/* We force "noinline" in certain places to be sure we know how many
-   frames there will be on the stack. */
-#ifdef _MSC_VER
-#define NOINLINE __declspec(noinline)
-#else
-#define NOINLINE __attribute__((noinline))
-#endif
-
-#ifdef HAS_LIBUNWIND
-#define UNW_LOCAL_ONLY
-#include "libunwind.h"
-#endif
-
-static int automatic_snapshots = 0;
-static double snapshot_interval = 0.0;
-static double next_snapshot_time = 0.0;
-static struct channel *snapshot_channel;
-static int pid_when_snapshot_channel_opened;
-
-extern value caml_spacetime_debug(value);
-
-static char* start_of_free_node_block;
-static char* end_of_free_node_block;
-
-typedef struct per_thread {
-  value* trie_node_root;
-  value* finaliser_trie_node_root;
-  struct per_thread* next;
-} per_thread;
-
-/* List of tries corresponding to threads that have been created. */
-/* CR-soon mshinwell: just include the main trie in this list. */
-static per_thread* per_threads = NULL;
-static int num_per_threads = 0;
-
-/* [caml_spacetime_shapes] is defined in the startup file. */
-extern uint64_t* caml_spacetime_shapes;
-
-uint64_t** caml_spacetime_static_shape_tables = NULL;
-shape_table* caml_spacetime_dynamic_shape_tables = NULL;
-
-static uintnat caml_spacetime_profinfo = (uintnat) 0;
-
-value caml_spacetime_trie_root = Val_unit;
-value* caml_spacetime_trie_node_ptr = &caml_spacetime_trie_root;
-
-static value caml_spacetime_finaliser_trie_root_main_thread = Val_unit;
-value* caml_spacetime_finaliser_trie_root
-  = &caml_spacetime_finaliser_trie_root_main_thread;
-
-/* CR-someday mshinwell: think about thread safety of the manipulation of
-   this list for multicore */
-allocation_point* caml_all_allocation_points = NULL;
-
-static const uintnat chunk_size = 1024 * 1024;
-
-#ifdef _WIN32
-#define strdup_os wcsdup
-#define snprintf_os _snwprintf
-#else
-#define strdup_os strdup
-#define snprintf_os snprintf
-#endif
-
-static void reinitialise_free_node_block(void)
-{
-  size_t index;
-
-  start_of_free_node_block = (char*) caml_stat_alloc_noexc(chunk_size);
-  end_of_free_node_block = start_of_free_node_block + chunk_size;
-
-  for (index = 0; index < chunk_size / sizeof(value); index++) {
-    ((value*) start_of_free_node_block)[index] = Val_unit;
-  }
-}
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-enum {
-  FEATURE_CALL_COUNTS = 1,
-} features;
-
-static uint16_t version_number = 0;
-static uint32_t magic_number_base = 0xace00ace;
-
-static void caml_spacetime_write_magic_number_internal(struct channel* chan)
-{
-  value magic_number;
-  uint16_t features = 0;
-
-#ifdef ENABLE_CALL_COUNTS
-  features |= FEATURE_CALL_COUNTS;
-#endif
-
-  magic_number =
-    Val_long(((uint64_t) magic_number_base)
-             | (((uint64_t) version_number) << 32)
-             | (((uint64_t) features) << 48));
-
-  Lock(chan);
-  caml_output_val(chan, magic_number, Val_long(0));
-  Unlock(chan);
-}
-
-CAMLprim value caml_spacetime_write_magic_number(value v_channel)
-{
-  caml_spacetime_write_magic_number_internal(Channel(v_channel));
-  return Val_unit;
-}
-
-static char_os* automatic_snapshot_dir;
-
-static void open_snapshot_channel(void)
-{
-  int fd;
-  char_os filename[8192];
-  int pid;
-  int filename_len = sizeof(filename)/sizeof(char_os);
-#ifdef _WIN32
-  pid = _getpid();
-#else
-  pid = getpid();
-#endif
-  snprintf_os(filename, filename_len, _T("%s/spacetime-%d"),
-              automatic_snapshot_dir, pid);
-  filename[filename_len-1] = _T('\0');
-  fd = open_os(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
-  if (fd == -1) {
-    automatic_snapshots = 0;
-  }
-  else {
-    snapshot_channel = caml_open_descriptor_out(fd);
-    snapshot_channel->flags |= CHANNEL_FLAG_BLOCKING_WRITE;
-    pid_when_snapshot_channel_opened = pid;
-    caml_spacetime_write_magic_number_internal(snapshot_channel);
-  }
-}
-
-static void maybe_reopen_snapshot_channel(void)
-{
-  /* This function should be used before writing to the automatic snapshot
-     channel.  It detects whether we have forked since the channel was opened.
-     If so, we close the old channel (ignoring any errors just in case the
-     old fd has been closed, e.g. in a double-fork situation where the middle
-     process has a loop to manually close all fds and no Spacetime snapshot
-     was written during that time) and then open a new one. */
-
-  int pid;
-#ifdef _WIN32
-  pid = _getpid();
-#else
-  pid = getpid();
-#endif
-
-  if (pid != pid_when_snapshot_channel_opened) {
-    caml_close_channel(snapshot_channel);
-    open_snapshot_channel();
-  }
-}
-
-extern void caml_spacetime_automatic_save(void);
-
-void caml_spacetime_initialize(void)
-{
-  /* Note that this is called very early (even prior to GC initialisation). */
-
-  char_os *ap_interval;
-
-  reinitialise_free_node_block();
-
-  caml_spacetime_static_shape_tables = &caml_spacetime_shapes;
-
-  ap_interval = caml_secure_getenv (_T("OCAML_SPACETIME_INTERVAL"));
-  if (ap_interval != NULL) {
-    unsigned int interval = 0;
-    sscanf_os(ap_interval, _T("%u"), &interval);
-    if (interval != 0) {
-      double time;
-      char_os cwd[4096];
-      char_os* user_specified_automatic_snapshot_dir;
-      int dir_ok = 1;
-
-      user_specified_automatic_snapshot_dir =
-        caml_secure_getenv(_T("OCAML_SPACETIME_SNAPSHOT_DIR"));
-
-      if (user_specified_automatic_snapshot_dir == NULL) {
-#if defined(HAS_GETCWD)
-        if (getcwd_os(cwd, sizeof(cwd)/sizeof(char_os)) == NULL) {
-          dir_ok = 0;
-        }
-#else
-        dir_ok = 0;
-#endif
-        if (dir_ok) {
-          automatic_snapshot_dir = strdup_os(cwd);
-        }
-      }
-      else {
-        automatic_snapshot_dir =
-          strdup_os(user_specified_automatic_snapshot_dir);
-      }
-
-      if (dir_ok) {
-        automatic_snapshots = 1;
-        open_snapshot_channel();
-        if (automatic_snapshots) {
-#ifdef SIGINT
-          /* Catch interrupt so that the profile can be completed.
-             We do this by marking the signal as handled without
-             specifying an actual handler. This causes the signal
-             to be handled by a call to exit. */
-          caml_set_signal_action(SIGINT, 2);
-#endif
-          snapshot_interval = interval / 1e3;
-          time = caml_sys_time_unboxed(Val_unit);
-          next_snapshot_time = time + snapshot_interval;
-          atexit(&caml_spacetime_automatic_save);
-        }
-      }
-    }
-  }
-}
-
-void caml_spacetime_register_shapes(void* dynlinked_table)
-{
-  shape_table* table;
-  table = (shape_table*) caml_stat_alloc_noexc(sizeof(shape_table));
-  if (table == NULL) {
-    fprintf(stderr, "Out of memory whilst registering shape table");
-    abort();
-  }
-  table->table = (uint64_t*) dynlinked_table;
-  table->next = caml_spacetime_dynamic_shape_tables;
-  caml_spacetime_dynamic_shape_tables = table;
-}
-
-CAMLprim value caml_spacetime_trie_is_initialized (value v_unit)
-{
-  return (caml_spacetime_trie_root == Val_unit) ? Val_false : Val_true;
-}
-
-CAMLprim value caml_spacetime_get_trie_root (value v_unit)
-{
-  return caml_spacetime_trie_root;
-}
-
-void caml_spacetime_register_thread(
-  value* trie_node_root, value* finaliser_trie_node_root)
-{
-  per_thread* thr;
-
-  thr = (per_thread*) caml_stat_alloc_noexc(sizeof(per_thread));
-  if (thr == NULL) {
-    fprintf(stderr, "Out of memory while registering thread for profiling\n");
-    abort();
-  }
-  thr->next = per_threads;
-  per_threads = thr;
-
-  thr->trie_node_root = trie_node_root;
-  thr->finaliser_trie_node_root = finaliser_trie_node_root;
-
-  /* CR-soon mshinwell: record thread ID (and for the main thread too) */
-
-  num_per_threads++;
-}
-
-static void caml_spacetime_save_event_internal (value v_time_opt,
-                                                struct channel* chan,
-                                                value v_event_name)
-{
-  value v_time;
-  double time_override = 0.0;
-  int use_time_override = 0;
-
-  if (Is_block(v_time_opt)) {
-    time_override = Double_field(Field(v_time_opt, 0), 0);
-    use_time_override = 1;
-  }
-  v_time = caml_spacetime_timestamp(time_override, use_time_override);
-
-  Lock(chan);
-  caml_output_val(chan, Val_long(2), Val_long(0));
-  caml_output_val(chan, v_event_name, Val_long(0));
-  caml_extern_allow_out_of_heap = 1;
-  caml_output_val(chan, v_time, Val_long(0));
-  caml_extern_allow_out_of_heap = 0;
-  Unlock(chan);
-
-  caml_stat_free(Hp_val(v_time));
-}
-
-CAMLprim value caml_spacetime_save_event (value v_time_opt,
-                                          value v_channel,
-                                          value v_event_name)
-{
-  struct channel* chan = Channel(v_channel);
-
-  caml_spacetime_save_event_internal(v_time_opt, chan, v_event_name);
-
-  return Val_unit;
-}
-
-
-void save_trie (struct channel *chan, double time_override,
-                int use_time_override)
-{
-  value v_time, v_frames, v_shapes;
-  /* CR-someday mshinwell: The commented-out changes here are for multicore,
-     where we think we should have one trie per domain. */
-  /* int num_marshalled = 0;
-  per_thread* thr = per_threads; */
-
-  Lock(chan);
-
-  caml_output_val(chan, Val_long(1), Val_long(0));
-
-  v_time = caml_spacetime_timestamp(time_override, use_time_override);
-  v_frames = caml_spacetime_frame_table();
-  v_shapes = caml_spacetime_shape_table();
-
-  caml_extern_allow_out_of_heap = 1;
-  caml_output_val(chan, v_time, Val_long(0));
-  caml_output_val(chan, v_frames, Val_long(0));
-  caml_output_val(chan, v_shapes, Val_long(0));
-  caml_extern_allow_out_of_heap = 0;
-
-  caml_output_val(chan, Val_long(1) /* Val_long(num_per_threads + 1) */,
-    Val_long(0));
-
-  /* Marshal both the main and finaliser tries, for all threads that have
-     been created, to an [out_channel].  This can be done by using the
-     extern.c code as usual, since the trie looks like standard OCaml values;
-     but we must allow it to traverse outside the heap. */
-
-  caml_extern_allow_out_of_heap = 1;
-  caml_output_val(chan, caml_spacetime_trie_root, Val_long(0));
-  caml_output_val(chan,
-    caml_spacetime_finaliser_trie_root_main_thread, Val_long(0));
-  /* while (thr != NULL) {
-    caml_output_val(chan, *(thr->trie_node_root), Val_long(0));
-    caml_output_val(chan, *(thr->finaliser_trie_node_root),
-      Val_long(0));
-    thr = thr->next;
-    num_marshalled++;
-  }
-  CAMLassert(num_marshalled == num_per_threads); */
-  caml_extern_allow_out_of_heap = 0;
-
-  Unlock(chan);
-}
-
-CAMLprim value caml_spacetime_save_trie (value v_time_opt, value v_channel)
-{
-  struct channel* channel = Channel(v_channel);
-  double time_override = 0.0;
-  int use_time_override = 0;
-
-  if (Is_block(v_time_opt)) {
-    time_override = Double_field(Field(v_time_opt, 0), 0);
-    use_time_override = 1;
-  }
-
-  save_trie(channel, time_override, use_time_override);
-
-  return Val_unit;
-}
-
-c_node_type caml_spacetime_classify_c_node(c_node* node)
-{
-  return (node->pc & 2) ? CALL : ALLOCATION;
-}
-
-c_node* caml_spacetime_c_node_of_stored_pointer(value node_stored)
-{
-  CAMLassert(node_stored == Val_unit || Is_c_node(node_stored));
-  return (node_stored == Val_unit) ? NULL : (c_node*) Hp_val(node_stored);
-}
-
-c_node* caml_spacetime_c_node_of_stored_pointer_not_null(
-      value node_stored)
-{
-  CAMLassert(Is_c_node(node_stored));
-  return (c_node*) Hp_val(node_stored);
-}
-
-value caml_spacetime_stored_pointer_of_c_node(c_node* c_node)
-{
-  value node;
-  CAMLassert(c_node != NULL);
-  node = Val_hp(c_node);
-  CAMLassert(Is_c_node(node));
-  return node;
-}
-
-#ifdef HAS_LIBUNWIND
-static int pc_inside_c_node_matches(c_node* node, void* pc)
-{
-  return Decode_c_node_pc(node->pc) == pc;
-}
-#endif
-
-static value allocate_uninitialized_ocaml_node(int size_including_header)
-{
-  void* node;
-  uintnat size;
-
-  CAMLassert(size_including_header >= 3);
-  node = caml_stat_alloc(sizeof(uintnat) * size_including_header);
-
-  size = size_including_header * sizeof(value);
-
-  node = (void*) start_of_free_node_block;
-  if (end_of_free_node_block - start_of_free_node_block < size) {
-    reinitialise_free_node_block();
-    node = (void*) start_of_free_node_block;
-    CAMLassert(end_of_free_node_block - start_of_free_node_block >= size);
-  }
-
-  start_of_free_node_block += size;
-
-  /* We don't currently rely on [uintnat] alignment, but we do need some
-     alignment, so just be sure. */
-  CAMLassert (((uintnat) node) % sizeof(uintnat) == 0);
-  return Val_hp(node);
-}
-
-static value find_tail_node(value node, void* callee)
-{
-  /* Search the tail chain within [node] (which corresponds to an invocation
-     of a caller of [callee]) to determine whether it contains a tail node
-     corresponding to [callee].  Returns any such node, or [Val_unit] if no
-     such node exists. */
-
-  value starting_node;
-  value pc;
-  value found = Val_unit;
-
-  starting_node = node;
-  pc = Encode_node_pc(callee);
-
-  do {
-    CAMLassert(Is_ocaml_node(node));
-    if (Node_pc(node) == pc) {
-      found = node;
-    }
-    else {
-      node = Tail_link(node);
-    }
-  } while (found == Val_unit && starting_node != node);
-
-  return found;
-}
-
-CAMLprim value caml_spacetime_allocate_node(
-      int size_including_header, void* pc, value* node_hole)
-{
-  value node;
-  value caller_node = Val_unit;
-
-  node = *node_hole;
-  /* The node hole should either contain [Val_unit], indicating that this
-     function was not tail called and we have not been to this point in the
-     trie before; or it should contain a value encoded using
-     [Encoded_tail_caller_node] that points at the node of a caller
-     that tail called the current function.  (Such a value is necessary to
-     be able to find the start of the caller's node, and hence its tail
-     chain, so we as a tail-called callee can link ourselves in.) */
-  CAMLassert(Is_tail_caller_node_encoded(node));
-
-  if (node != Val_unit) {
-    value tail_node;
-    /* The callee was tail called.  Find whether there already exists a node
-       for it in the tail call chain within the caller's node.  The caller's
-       node must always be an OCaml node. */
-    caller_node = Decode_tail_caller_node(node);
-    tail_node = find_tail_node(caller_node, pc);
-    if (tail_node != Val_unit) {
-      /* This tail calling sequence has happened before; just fill the hole
-         with the existing node and return. */
-      *node_hole = tail_node;
-      return 0;  /* indicates an existing node was returned */
-    }
-  }
-
-  node = allocate_uninitialized_ocaml_node(size_including_header);
-  Hd_val(node) =
-    Make_header(size_including_header - 1, OCaml_node_tag, Caml_black);
-  CAMLassert((((uintnat) pc) % 1) == 0);
-  Node_pc(node) = Encode_node_pc(pc);
-  /* If the callee was tail called, then the tail link field will link this
-     new node into an existing tail chain.  Otherwise, it is initialized with
-     the empty tail chain, i.e. the one pointing directly at [node]. */
-  if (caller_node == Val_unit) {
-    Tail_link(node) = node;
-  }
-  else {
-    Tail_link(node) = Tail_link(caller_node);
-    Tail_link(caller_node) = node;
-  }
-
-  /* The callee node pointers for direct tail call points are
-     initialized from code emitted by the OCaml compiler.  This is done to
-     avoid having to pass this function a description of which nodes are
-     direct tail call points.  (We cannot just count them and put them at the
-     beginning of the node because we need the indexes of elements within the
-     node during instruction selection before we have found all call points.)
-
-     All other fields have already been initialised by
-     [reinitialise_free_node_block].
-  */
-
-  *node_hole = node;
-
-  return 1;  /* indicates a new node was created */
-}
-
-static c_node* allocate_c_node(void)
-{
-  c_node* node;
-  size_t index;
-
-  node = (c_node*) start_of_free_node_block;
-  if (end_of_free_node_block - start_of_free_node_block < sizeof(c_node)) {
-    reinitialise_free_node_block();
-    node = (c_node*) start_of_free_node_block;
-    CAMLassert(end_of_free_node_block - start_of_free_node_block
-      >= sizeof(c_node));
-  }
-  start_of_free_node_block += sizeof(c_node);
-
-  CAMLassert((sizeof(c_node) % sizeof(uintnat)) == 0);
-
-  /* CR-soon mshinwell: remove this and pad the structure properly */
-  for (index = 0; index < sizeof(c_node) / sizeof(value); index++) {
-    ((value*) node)[index] = Val_unit;
-  }
-
-  node->gc_header =
-    Make_header(sizeof(c_node)/sizeof(uintnat) - 1, C_node_tag, Caml_black);
-  node->data.call.callee_node = Val_unit;
-  node->data.call.call_count = Val_long(0);
-  node->next = Val_unit;
-
-  return node;
-}
-
-/* Since a given indirect call site either always yields tail calls or
-   always yields non-tail calls, the output of
-   [caml_spacetime_indirect_node_hole_ptr] is uniquely determined by its
-   first two arguments (the callee and the node hole).  We cache these
-   to increase performance of recursive functions containing an indirect
-   call (e.g. [List.map] when not inlined). */
-static void* last_indirect_node_hole_ptr_callee;
-static value* last_indirect_node_hole_ptr_node_hole;
-static call_point* last_indirect_node_hole_ptr_result;
-
-CAMLprim value* caml_spacetime_indirect_node_hole_ptr
-      (void* callee, value* node_hole, value caller_node)
-{
-  /* Find the address of the node hole for an indirect call to [callee].
-     If [caller_node] is not [Val_unit], it is a pointer to the caller's
-     node, and indicates that this is a tail call site. */
-
-  c_node* c_node;
-  value encoded_callee;
-
-  if (callee == last_indirect_node_hole_ptr_callee
-      && node_hole == last_indirect_node_hole_ptr_node_hole) {
-#ifdef ENABLE_CALL_COUNTS
-    last_indirect_node_hole_ptr_result->call_count =
-      Val_long (Long_val (last_indirect_node_hole_ptr_result->call_count) + 1);
-#endif
-    return &(last_indirect_node_hole_ptr_result->callee_node);
-  }
-
-  last_indirect_node_hole_ptr_callee = callee;
-  last_indirect_node_hole_ptr_node_hole = node_hole;
-
-  encoded_callee = Encode_c_node_pc_for_call(callee);
-
-  while (*node_hole != Val_unit) {
-    CAMLassert(((uintnat) *node_hole) % sizeof(value) == 0);
-
-    c_node = caml_spacetime_c_node_of_stored_pointer_not_null(*node_hole);
-
-    CAMLassert(c_node != NULL);
-    CAMLassert(caml_spacetime_classify_c_node(c_node) == CALL);
-
-    if (c_node->pc == encoded_callee) {
-#ifdef ENABLE_CALL_COUNTS
-      c_node->data.call.call_count =
-        Val_long (Long_val(c_node->data.call.call_count) + 1);
-#endif
-      last_indirect_node_hole_ptr_result = &(c_node->data.call);
-      return &(last_indirect_node_hole_ptr_result->callee_node);
-    }
-    else {
-      node_hole = &c_node->next;
-    }
-  }
-
-  c_node = allocate_c_node();
-  c_node->pc = encoded_callee;
-
-  if (caller_node != Val_unit) {
-    /* This is a tail call site.
-       Perform the initialization equivalent to that emitted by
-       [Spacetime.code_for_function_prologue] for direct tail call
-       sites. */
-    c_node->data.call.callee_node = Encode_tail_caller_node(caller_node);
-  }
-
-  *node_hole = caml_spacetime_stored_pointer_of_c_node(c_node);
-
-  CAMLassert(((uintnat) *node_hole) % sizeof(value) == 0);
-  CAMLassert(*node_hole != Val_unit);
-
-#ifdef ENABLE_CALL_COUNTS
-  c_node->data.call.call_count =
-    Val_long (Long_val(c_node->data.call.call_count) + 1);
-#endif
-  last_indirect_node_hole_ptr_result = &(c_node->data.call);
-
-  return &(last_indirect_node_hole_ptr_result->callee_node);
-}
-
-/* Some notes on why caml_call_gc doesn't need a distinguished node.
-   (Remember that thread switches are irrelevant here because each thread
-   has its own trie.)
-
-   caml_call_gc only invokes OCaml functions in the following circumstances:
-   1. running an OCaml finaliser;
-   2. executing an OCaml signal handler.
-   Both of these are done on the finaliser trie.  Furthermore, both of
-   these invocations start via caml_callback; the code in this file for
-   handling that (caml_spacetime_c_to_ocaml) correctly copes with that by
-   attaching a single "caml_start_program" node that can cope with any
-   number of indirect OCaml calls from that point.
-
-   caml_call_gc may also invoke C functions that cause allocation.  All of
-   these (assuming libunwind support is present) will cause a chain of
-   c_node structures to be attached to the trie, starting at the node hole
-   passed to caml_call_gc from OCaml code.  These structures are extensible
-   and can thus accommodate any number of C backtraces leading from
-   caml_call_gc.
-*/
-/* CR-soon mshinwell: it might in fact be the case now that nothing called
-   from caml_call_gc will do any allocation that ends up on the trie.  We
-   can revisit this after the first release. */
-
-static NOINLINE void* find_trie_node_from_libunwind(int for_allocation,
-    uintnat wosize, struct ext_table** cached_frames)
-{
-#ifdef HAS_LIBUNWIND
-  /* Given that [caml_last_return_address] is the most recent call site in
-     OCaml code, and that we are now in C (or other) code called from that
-     site, obtain a backtrace using libunwind and graft the most recent
-     portion (everything back to but not including [caml_last_return_address])
-     onto the trie.  See the important comment below regarding the fact that
-     call site, and not callee, addresses are recorded during this process.
-
-     If [for_allocation] is non-zero, the final node recorded will be for
-     an allocation, and the returned pointer is to the allocation node.
-     Otherwise, no node is recorded for the innermost frame, and the
-     returned pointer is a pointer to the *node hole* where a node for that
-     frame should be attached.
-
-     If [for_allocation] is non-zero then [wosize] must give the size in
-     words, excluding the header, of the value being allocated.
-
-     If [cached_frames != NULL] then:
-     1. If [*cached_frames] is NULL then save the captured backtrace in a
-        newly-allocated table and store the pointer to that table in
-        [*cached_frames];
-     2. Otherwise use [*cached_frames] as the unwinding information.
-     The intention is that when the context is known (e.g. a function such
-     as [caml_make_vect] known to have been directly invoked from OCaml),
-     we can avoid expensive calls to libunwind.
-  */
-
-  unw_cursor_t cur;
-  unw_context_t ctx;
-  int ret;
-  int innermost_frame;
-  int frame;
-  static struct ext_table frames_local;
-  struct ext_table* frames;
-  static int ext_table_initialised = 0;
-  int have_frames_already = 0;
-  value* node_hole;
-  c_node* node = NULL;
-  int initial_table_size = 1000;
-  int must_initialise_node_for_allocation = 0;
-
-  if (!cached_frames) {
-    if (!ext_table_initialised) {
-      caml_ext_table_init(&frames_local, initial_table_size);
-      ext_table_initialised = 1;
-    }
-    else {
-      caml_ext_table_clear(&frames_local, 0);
-    }
-    frames = &frames_local;
-  } else {
-    if (*cached_frames) {
-      frames = *cached_frames;
-      have_frames_already = 1;
-    }
-    else {
-      frames =
-        (struct ext_table*) caml_stat_alloc_noexc(sizeof(struct ext_table));
-      if (!frames) {
-        caml_fatal_error("Not enough memory for ext_table allocation");
-      }
-      caml_ext_table_init(frames, initial_table_size);
-      *cached_frames = frames;
-    }
-  }
-
-  if (!have_frames_already) {
-    /* Get the stack backtrace as far as [caml_last_return_address]. */
-
-    ret = unw_getcontext(&ctx);
-    if (ret != UNW_ESUCCESS) {
-      return NULL;
-    }
-
-    ret = unw_init_local(&cur, &ctx);
-    if (ret != UNW_ESUCCESS) {
-      return NULL;
-    }
-
-    while ((ret = unw_step(&cur)) > 0) {
-      unw_word_t ip;
-      unw_get_reg(&cur, UNW_REG_IP, &ip);
-      if (caml_last_return_address == (uintnat) ip) {
-        break;
-      }
-      else {
-        /* Inlined some of [caml_ext_table_add] for speed. */
-        if (frames->size < frames->capacity) {
-          frames->contents[frames->size++] = (void*) ip;
-        } else {
-          caml_ext_table_add(frames, (void*) ip);
-        }
-      }
-    }
-  }
-
-  /* We always need to ignore the frames for:
-      #0  find_trie_node_from_libunwind
-      #1  caml_spacetime_c_to_ocaml
-     Further, if this is not an allocation point, we should not create the
-     node for the current C function that triggered us (i.e. frame #2). */
-  innermost_frame = for_allocation ? 1 : 2;
-
-  if (frames->size - 1 < innermost_frame) {
-    /* Insufficiently many frames (maybe no frames) returned from
-       libunwind; just don't do anything. */
-    return NULL;
-  }
-
-  node_hole = caml_spacetime_trie_node_ptr;
-  /* Note that if [node_hole] is filled, then it must point to a C node,
-     since it is not possible for there to be a call point in an OCaml
-     function that sometimes calls C and sometimes calls OCaml. */
-
-  for (frame = frames->size - 1; frame >= innermost_frame; frame--) {
-    c_node_type expected_type;
-    void* pc = frames->contents[frame];
-    CAMLassert (pc != (void*) caml_last_return_address);
-
-    if (!for_allocation) {
-      expected_type = CALL;
-    }
-    else {
-      expected_type = (frame > innermost_frame ? CALL : ALLOCATION);
-    }
-
-    if (*node_hole == Val_unit) {
-      node = allocate_c_node();
-      /* Note: for CALL nodes, the PC is the program counter at each call
-         site.  We do not store program counter addresses of the start of
-         callees, unlike for OCaml nodes.  This means that some trie nodes
-         will become conflated.  These can be split during post-processing by
-         working out which function each call site was in. */
-      node->pc = (expected_type == CALL ? Encode_c_node_pc_for_call(pc)
-        : Encode_c_node_pc_for_alloc_point(pc));
-      *node_hole = caml_spacetime_stored_pointer_of_c_node(node);
-      if (expected_type == ALLOCATION) {
-        must_initialise_node_for_allocation = 1;
-      }
-    }
-    else {
-      c_node* prev;
-      int found = 0;
-
-      node = caml_spacetime_c_node_of_stored_pointer_not_null(*node_hole);
-      CAMLassert(node != NULL);
-      CAMLassert(node->next == Val_unit
-        || (((uintnat) (node->next)) % sizeof(value) == 0));
-
-      prev = NULL;
-
-      while (!found && node != NULL) {
-        if (caml_spacetime_classify_c_node(node) == expected_type
-            && pc_inside_c_node_matches(node, pc)) {
-          found = 1;
-        }
-        else {
-          prev = node;
-          node = caml_spacetime_c_node_of_stored_pointer(node->next);
-        }
-      }
-      if (!found) {
-        CAMLassert(prev != NULL);
-        node = allocate_c_node();
-        node->pc = (expected_type == CALL ? Encode_c_node_pc_for_call(pc)
-          : Encode_c_node_pc_for_alloc_point(pc));
-        if (expected_type == ALLOCATION) {
-          must_initialise_node_for_allocation = 1;
-        }
-        prev->next = caml_spacetime_stored_pointer_of_c_node(node);
-      }
-    }
-
-    CAMLassert(node != NULL);
-
-    CAMLassert(caml_spacetime_classify_c_node(node) == expected_type);
-    CAMLassert(pc_inside_c_node_matches(node, pc));
-    node_hole = &node->data.call.callee_node;
-  }
-
-  if (must_initialise_node_for_allocation) {
-    caml_spacetime_profinfo++;
-    if (caml_spacetime_profinfo > PROFINFO_MASK) {
-      /* Profiling counter overflow. */
-      caml_spacetime_profinfo = PROFINFO_MASK;
-    }
-    node->data.allocation.profinfo =
-      Make_header_with_profinfo(
-        /* "-1" because [c_node] has the GC header as its first
-           element. */
-        offsetof(c_node, data.allocation.count)/sizeof(value) - 1,
-        Infix_tag,
-        Caml_black,
-        caml_spacetime_profinfo);
-    node->data.allocation.count = Val_long(0);
-
-    /* Add the new allocation point into the linked list of all allocation
-       points. */
-    if (caml_all_allocation_points != NULL) {
-      node->data.allocation.next =
-        (value) &caml_all_allocation_points->count;
-    } else {
-      node->data.allocation.next = Val_unit;
-    }
-    caml_all_allocation_points = &node->data.allocation;
-  }
-
-  if (for_allocation) {
-    CAMLassert(caml_spacetime_classify_c_node(node) == ALLOCATION);
-    CAMLassert(caml_spacetime_c_node_of_stored_pointer(node->next) != node);
-    CAMLassert(Profinfo_hd(node->data.allocation.profinfo) > 0);
-    node->data.allocation.count =
-      Val_long(Long_val(node->data.allocation.count) + (1 + wosize));
-  }
-
-  CAMLassert(node->next != (value) NULL);
-
-  return for_allocation ? (void*) node : (void*) node_hole;
-#else
-  return NULL;
-#endif
-}
-
-void caml_spacetime_c_to_ocaml(void* ocaml_entry_point,
-      void* identifying_pc_for_caml_start_program)
-{
-  /* Called in [caml_start_program] and [caml_callback*] when we are about
-     to cross from C into OCaml.  [ocaml_entry_point] is the branch target.
-     This situation is handled by ensuring the presence of a new OCaml node
-     for the callback veneer; the node contains a single indirect call point
-     which accumulates the [ocaml_entry_point]s.
-
-     The layout of the node is described in the "system shape table"; see
-     asmrun/amd64.S.
-  */
-
-  value node;
-
-  /* Update the trie with the current backtrace, as far back as
-     [caml_last_return_address], and leave the node hole pointer at
-     the correct place for attachment of a [caml_start_program] node. */
-
-#ifdef HAS_LIBUNWIND
-  value* node_temp;
-  node_temp = (value*) find_trie_node_from_libunwind(0, 0, NULL);
-  if (node_temp != NULL) {
-    caml_spacetime_trie_node_ptr = node_temp;
-  }
-#endif
-
-  if (*caml_spacetime_trie_node_ptr == Val_unit) {
-    uintnat size_including_header;
-
-    size_including_header =
-      1 /* GC header */ + Node_num_header_words + Indirect_num_fields;
-
-    node = allocate_uninitialized_ocaml_node(size_including_header);
-    Hd_val(node) =
-      Make_header(size_including_header - 1, OCaml_node_tag, Caml_black);
-    CAMLassert((((uintnat) identifying_pc_for_caml_start_program) % 1) == 0);
-    Node_pc(node) = Encode_node_pc(identifying_pc_for_caml_start_program);
-    Tail_link(node) = node;
-    Indirect_pc_linked_list(node, Node_num_header_words) = Val_unit;
-    *caml_spacetime_trie_node_ptr = node;
-  }
-  else {
-    node = *caml_spacetime_trie_node_ptr;
-    /* If there is a node here already, it should never be an initialized
-       (but as yet unused) tail call point, since calls from OCaml into C
-       are never tail calls (and no C -> C call is marked as tail). */
-    CAMLassert(!Is_tail_caller_node_encoded(node));
-  }
-
-  CAMLassert(Is_ocaml_node(node));
-  CAMLassert(Decode_node_pc(Node_pc(node))
-    == identifying_pc_for_caml_start_program);
-  CAMLassert(Tail_link(node) == node);
-  CAMLassert(Wosize_val(node) == Node_num_header_words + Indirect_num_fields);
-
-  /* Search the node to find the node hole corresponding to the indirect
-     call to the OCaml function. */
-  caml_spacetime_trie_node_ptr =
-    caml_spacetime_indirect_node_hole_ptr(
-      ocaml_entry_point,
-      &Indirect_pc_linked_list(node, Node_num_header_words),
-      Val_unit);
-  CAMLassert(*caml_spacetime_trie_node_ptr == Val_unit
-    || Is_ocaml_node(*caml_spacetime_trie_node_ptr));
-}
-
-extern void caml_garbage_collection(void);  /* signals_asm.c */
-extern void caml_array_bound_error(void);  /* fail.c */
-
-CAMLprim uintnat caml_spacetime_generate_profinfo (void* profinfo_words,
-                                                   uintnat index_within_node)
-{
-  /* Called from code that creates a value's header inside an OCaml
-     function. */
-
-  value node;
-  uintnat profinfo;
-
-  caml_spacetime_profinfo++;
-  if (caml_spacetime_profinfo > PROFINFO_MASK) {
-    /* Profiling counter overflow. */
-    caml_spacetime_profinfo = PROFINFO_MASK;
-  }
-  profinfo = caml_spacetime_profinfo;
-
-  /* CR-someday mshinwell: we could always use the [struct allocation_point]
-     overlay instead of the macros now. */
-
-  /* [node] isn't really a node; it points into the middle of
-     one---specifically to the "profinfo" word of an allocation point.
-     It's done like this to avoid re-calculating the place in the node
-     (which already has to be done in the OCaml-generated code run before
-     this function). */
-  node = (value) profinfo_words;
-  CAMLassert(Alloc_point_profinfo(node, 0) == Val_unit);
-
-  /* The profinfo value is stored shifted to reduce the number of
-     instructions required on the OCaml side.  It also enables us to use
-     [Infix_tag] to obtain valid value pointers into the middle of nodes,
-     which is used for the linked list of all allocation points. */
-  profinfo = Make_header_with_profinfo(
-    index_within_node, Infix_tag, Caml_black, profinfo);
-
-  CAMLassert(!Is_block(profinfo));
-  Alloc_point_profinfo(node, 0) = profinfo;
-  /* The count is set to zero by the initialisation when the node was
-     created (see above). */
-  CAMLassert(Alloc_point_count(node, 0) == Val_long(0));
-
-  /* Add the new allocation point into the linked list of all allocation
-     points. */
-  if (caml_all_allocation_points != NULL) {
-    Alloc_point_next_ptr(node, 0) = (value) &caml_all_allocation_points->count;
-  }
-  else {
-    CAMLassert(Alloc_point_next_ptr(node, 0) == Val_unit);
-  }
-  caml_all_allocation_points = (allocation_point*) node;
-
-  return profinfo;
-}
-
-uintnat caml_spacetime_my_profinfo (struct ext_table** cached_frames,
-                                    uintnat wosize)
-{
-  /* Return the profinfo value that should be written into a value's header
-     during an allocation from C.  This may necessitate extending the trie
-     with information obtained from libunwind. */
-
-  c_node* node;
-  uintnat profinfo = 0;
-
-  node = find_trie_node_from_libunwind(1, wosize, cached_frames);
-  if (node != NULL) {
-    profinfo = ((uintnat) (node->data.allocation.profinfo)) >> PROFINFO_SHIFT;
-  }
-
-  return profinfo;  /* N.B. not shifted by PROFINFO_SHIFT */
-}
-
-void caml_spacetime_automatic_snapshot (void)
-{
-  if (automatic_snapshots) {
-    double start_time, end_time;
-    start_time = caml_sys_time_unboxed(Val_unit);
-    if (start_time >= next_snapshot_time) {
-      maybe_reopen_snapshot_channel();
-      caml_spacetime_save_snapshot(snapshot_channel, 0.0, 0);
-      end_time = caml_sys_time_unboxed(Val_unit);
-      next_snapshot_time = end_time + snapshot_interval;
-    }
-  }
-}
-
-CAMLprim value caml_spacetime_save_event_for_automatic_snapshots
-  (value v_event_name)
-{
-  if (automatic_snapshots) {
-    maybe_reopen_snapshot_channel();
-    caml_spacetime_save_event_internal (Val_unit, snapshot_channel,
-                                        v_event_name);
-  }
-  return Val_unit;
-}
-
-void caml_spacetime_automatic_save (void)
-{
-  /* Called from [atexit]. */
-
-  if (automatic_snapshots) {
-    automatic_snapshots = 0;
-    maybe_reopen_snapshot_channel();
-    save_trie(snapshot_channel, 0.0, 0);
-    caml_flush(snapshot_channel);
-    caml_close_channel(snapshot_channel);
-  }
-}
-
-CAMLprim value caml_spacetime_enabled (value v_unit)
-{
-  return Val_true;
-}
-
-CAMLprim value caml_register_channel_for_spacetime (value v_channel)
-{
-  struct channel* channel = Channel(v_channel);
-  channel->flags |= CHANNEL_FLAG_BLOCKING_WRITE;
-  return Val_unit;
-}
-
-#else
-
-/* Functions for when the compiler was not configured with "-spacetime". */
-
-CAMLprim value caml_spacetime_write_magic_number(value v_channel)
-{
-  return Val_unit;
-}
-
-CAMLprim value caml_spacetime_enabled (value v_unit)
-{
-  return Val_false;
-}
-
-CAMLprim value caml_spacetime_save_event (value v_time_opt,
-                                          value v_channel,
-                                          value v_event_name)
-{
-  return Val_unit;
-}
-
-CAMLprim value caml_spacetime_save_event_for_automatic_snapshots
-  (value v_event_name)
-{
-  return Val_unit;
-}
-
-CAMLprim value caml_spacetime_save_trie (value ignored)
-{
-  return Val_unit;
-}
-
-CAMLprim value caml_register_channel_for_spacetime (value v_channel)
-{
-  return Val_unit;
-}
-
-#endif
diff --git a/asmrun/startup.c b/asmrun/startup.c
deleted file mode 100644
index 070f0c64..00000000
--- a/asmrun/startup.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/**************************************************************************/
-/*                                                                        */
-/*                                 OCaml                                  */
-/*                                                                        */
-/*          Xavier Leroy and Damien Doligez, INRIA Rocquencourt           */
-/*                                                                        */
-/*   Copyright 1996 Institut National de Recherche en Informatique et     */
-/*     en Automatique.                                                    */
-/*                                                                        */
-/*   All rights reserved.  This file is distributed under the terms of    */
-/*   the GNU Lesser General Public License version 2.1, with the          */
-/*   special exception on linking described in the file LICENSE.          */
-/*                                                                        */
-/**************************************************************************/
-
-#define CAML_INTERNALS
-
-/* Start-up code */
-
-#include 
-#include 
-#include "caml/callback.h"
-#include "caml/backtrace.h"
-#include "caml/custom.h"
-#include "caml/debugger.h"
-#include "caml/fail.h"
-#include "caml/freelist.h"
-#include "caml/gc.h"
-#include "caml/gc_ctrl.h"
-#include "caml/intext.h"
-#include "caml/memory.h"
-#include "caml/misc.h"
-#include "caml/mlvalues.h"
-#include "caml/osdeps.h"
-#include "caml/printexc.h"
-#include "caml/stack.h"
-#include "caml/startup_aux.h"
-#include "caml/sys.h"
-#ifdef WITH_SPACETIME
-#include "caml/spacetime.h"
-#endif
-#ifdef HAS_UI
-#include "caml/ui.h"
-#endif
-
-extern int caml_parser_trace;
-CAMLexport header_t caml_atom_table[256];
-char * caml_code_area_start, * caml_code_area_end;
-struct ext_table caml_code_fragments_table;
-
-/* Initialize the atom table and the static data and code area limits. */
-
-struct segment { char * begin; char * end; };
-
-static void init_static(void)
-{
-  extern struct segment caml_data_segments[], caml_code_segments[];
-  int i;
-  struct code_fragment * cf;
-
-  caml_init_atom_table ();
-
-  for (i = 0; caml_data_segments[i].begin != 0; i++) {
-    /* PR#5509: we must include the zero word at end of data segment,
-       because pointers equal to caml_data_segments[i].end are static data. */
-    if (caml_page_table_add(In_static_data,
-                            caml_data_segments[i].begin,
-                            caml_data_segments[i].end + sizeof(value)) != 0)
-      caml_fatal_error("Fatal error: not enough memory for initial page table");
-  }
-
-  caml_code_area_start = caml_code_segments[0].begin;
-  caml_code_area_end = caml_code_segments[0].end;
-  for (i = 1; caml_code_segments[i].begin != 0; i++) {
-    if (caml_code_segments[i].begin < caml_code_area_start)
-      caml_code_area_start = caml_code_segments[i].begin;
-    if (caml_code_segments[i].end > caml_code_area_end)
-      caml_code_area_end = caml_code_segments[i].end;
-  }
-  /* Register the code in the table of code fragments */
-  cf = caml_stat_alloc(sizeof(struct code_fragment));
-  cf->code_start = caml_code_area_start;
-  cf->code_end = caml_code_area_end;
-  cf->digest_computed = 0;
-  caml_ext_table_init(&caml_code_fragments_table, 8);
-  caml_ext_table_add(&caml_code_fragments_table, cf);
-}
-
-/* These are termination hooks used by the systhreads library */
-struct longjmp_buffer caml_termination_jmpbuf;
-void (*caml_termination_hook)(void *) = NULL;
-
-extern value caml_start_program (void);
-extern void caml_init_ieee_floats (void);
-extern void caml_init_signals (void);
-#ifdef _WIN32
-extern void caml_win32_overflow_detection (void);
-#endif
-
-#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L
-
-/* PR 4887: avoid crash box of windows runtime on some system calls */
-extern void caml_install_invalid_parameter_handler();
-
-#endif
-
-value caml_startup_common(char_os **argv, int pooling)
-{
-  char_os * exe_name, * proc_self_exe;
-  char tos;
-
-  /* Determine options */
-#ifdef DEBUG
-  caml_verb_gc = 0x3F;
-#endif
-  caml_parse_ocamlrunparam();
-#ifdef DEBUG
-  caml_gc_message (-1, "### OCaml runtime: debug mode ###\n");
-#endif
-  if (caml_cleanup_on_exit)
-    pooling = 1;
-  if (!caml_startup_aux(pooling))
-    return Val_unit;
-
-#ifdef WITH_SPACETIME
-  caml_spacetime_initialize();
-#endif
-  caml_init_frame_descriptors();
-  caml_init_ieee_floats();
-#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L
-  caml_install_invalid_parameter_handler();
-#endif
-  caml_init_custom_operations();
-  caml_top_of_stack = &tos;
-  caml_init_gc (caml_init_minor_heap_wsz, caml_init_heap_wsz,
-                caml_init_heap_chunk_sz, caml_init_percent_free,
-                caml_init_max_percent_free, caml_init_major_window);
-  init_static();
-  caml_init_signals();
-#ifdef _WIN32
-  caml_win32_overflow_detection();
-#endif
-  caml_init_backtrace();
-  caml_debugger_init (); /* force debugger.o stub to be linked */
-  exe_name = argv[0];
-  if (exe_name == NULL) exe_name = _T("");
-  proc_self_exe = caml_executable_name();
-  if (proc_self_exe != NULL)
-    exe_name = proc_self_exe;
-  else
-    exe_name = caml_search_exe_in_path(exe_name);
-  caml_sys_init(exe_name, argv);
-  if (sigsetjmp(caml_termination_jmpbuf.buf, 0)) {
-    if (caml_termination_hook != NULL) caml_termination_hook(NULL);
-    return Val_unit;
-  }
-  return caml_start_program();
-}
-
-value caml_startup_exn(char_os **argv)
-{
-  return caml_startup_common(argv, /* pooling */ 0);
-}
-
-void caml_startup(char_os **argv)
-{
-  value res = caml_startup_exn(argv);
-  if (Is_exception_result(res))
-    caml_fatal_uncaught_exception(Extract_exception(res));
-}
-
-void caml_main(char_os **argv)
-{
-  caml_startup(argv);
-}
-
-value caml_startup_pooled_exn(char_os **argv)
-{
-  return caml_startup_common(argv, /* pooling */ 1);
-}
-
-void caml_startup_pooled(char_os **argv)
-{
-  value res = caml_startup_pooled_exn(argv);
-  if (Is_exception_result(res))
-    caml_fatal_uncaught_exception(Extract_exception(res));
-}
diff --git a/autogen b/autogen
new file mode 100755
index 00000000..a4e15f94
--- /dev/null
+++ b/autogen
@@ -0,0 +1,2 @@
+#!/bin/sh
+autoconf -W all,error
diff --git a/boot/menhir/menhirLib.ml b/boot/menhir/menhirLib.ml
new file mode 100644
index 00000000..19e30f24
--- /dev/null
+++ b/boot/menhir/menhirLib.ml
@@ -0,0 +1,3517 @@
+module General = struct
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* --------------------------------------------------------------------------- *)
+
+(* Lists. *)
+
+let rec take n xs =
+  match n, xs with
+  | 0, _
+  | _, [] ->
+      []
+  | _, (x :: xs as input) ->
+     let xs' = take (n - 1) xs in
+     if xs == xs' then
+       input
+     else
+       x :: xs'
+
+let rec drop n xs =
+  match n, xs with
+  | 0, _ ->
+      xs
+  | _, [] ->
+      []
+  | _, _ :: xs ->
+      drop (n - 1) xs
+
+let rec uniq1 cmp x ys =
+  match ys with
+  | [] ->
+      []
+  | y :: ys ->
+      if cmp x y = 0 then
+        uniq1 compare x ys
+      else
+        y :: uniq1 cmp y ys
+
+let uniq cmp xs =
+  match xs with
+  | [] ->
+      []
+  | x :: xs ->
+      x :: uniq1 cmp x xs
+
+let weed cmp xs =
+  uniq cmp (List.sort cmp xs)
+
+(* --------------------------------------------------------------------------- *)
+
+(* Streams. *)
+
+type 'a stream =
+    'a head Lazy.t
+
+and 'a head =
+  | Nil
+  | Cons of 'a * 'a stream
+
+(* The length of a stream. *)
+
+let rec length xs =
+  match Lazy.force xs with
+  | Nil ->
+      0
+  | Cons (_, xs) ->
+      1 + length xs
+
+(* Folding over a stream. *)
+
+let rec foldr f xs accu =
+  match Lazy.force xs with
+  | Nil ->
+      accu
+  | Cons (x, xs) ->
+      f x (foldr f xs accu)
+
+end
+module Convert = struct
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* An ocamlyacc-style, or Menhir-style, parser requires access to
+   the lexer, which must be parameterized with a lexing buffer, and
+   to the lexing buffer itself, where it reads position information. *)
+
+(* This traditional API is convenient when used with ocamllex, but
+   inelegant when used with other lexer generators. *)
+
+type ('token, 'semantic_value) traditional =
+    (Lexing.lexbuf -> 'token) -> Lexing.lexbuf -> 'semantic_value
+
+(* This revised API is independent of any lexer generator. Here, the
+   parser only requires access to the lexer, and the lexer takes no
+   parameters. The tokens returned by the lexer may contain position
+   information. *)
+
+type ('token, 'semantic_value) revised =
+    (unit -> 'token) -> 'semantic_value
+
+(* --------------------------------------------------------------------------- *)
+
+(* Converting a traditional parser, produced by ocamlyacc or Menhir,
+   into a revised parser. *)
+
+(* A token of the revised lexer is essentially a triple of a token
+   of the traditional lexer (or raw token), a start position, and
+   and end position. The three [get] functions are accessors. *)
+
+(* We do not require the type ['token] to actually be a triple type.
+   This enables complex applications where it is a record type with
+   more than three fields. It also enables simple applications where
+   positions are of no interest, so ['token] is just ['raw_token]
+   and [get_startp] and [get_endp] return dummy positions. *)
+
+let traditional2revised
+  (get_raw_token : 'token -> 'raw_token)
+  (get_startp    : 'token -> Lexing.position)
+  (get_endp      : 'token -> Lexing.position)
+  (parser : ('raw_token, 'semantic_value) traditional)
+: ('token, 'semantic_value) revised =
+
+  (* Accept a revised lexer. *)
+
+  fun (lexer : unit -> 'token) ->
+
+    (* Create a dummy lexing buffer. *)
+
+    let lexbuf : Lexing.lexbuf =
+      Lexing.from_string ""
+    in
+
+    (* Wrap the revised lexer as a traditional lexer. A traditional
+       lexer returns a raw token and updates the fields of the lexing
+       buffer with new positions, which will be read by the parser. *)
+
+    let lexer (lexbuf : Lexing.lexbuf) : 'raw_token =
+      let token : 'token = lexer() in
+      lexbuf.Lexing.lex_start_p <- get_startp token;
+      lexbuf.Lexing.lex_curr_p <- get_endp token;
+      get_raw_token token
+    in
+
+    (* Invoke the traditional parser. *)
+
+    parser lexer lexbuf
+
+(* --------------------------------------------------------------------------- *)
+
+(* Converting a revised parser back to a traditional parser. *)
+
+let revised2traditional
+  (make_token : 'raw_token -> Lexing.position -> Lexing.position -> 'token)
+  (parser : ('token, 'semantic_value) revised)
+: ('raw_token, 'semantic_value) traditional =
+
+  (* Accept a traditional lexer and a lexing buffer. *)
+
+  fun (lexer : Lexing.lexbuf -> 'raw_token) (lexbuf : Lexing.lexbuf) ->
+
+    (* Wrap the traditional lexer as a revised lexer. *)
+
+    let lexer () : 'token =
+      let token : 'raw_token = lexer lexbuf in
+      make_token token lexbuf.Lexing.lex_start_p lexbuf.Lexing.lex_curr_p
+    in
+
+    (* Invoke the revised parser. *)
+
+    parser lexer
+
+(* --------------------------------------------------------------------------- *)
+
+(* Simplified versions of the above, where concrete triples are used. *)
+
+module Simplified = struct
+
+  let traditional2revised parser =
+    traditional2revised
+      (fun (token, _, _)  -> token)
+      (fun (_, startp, _) -> startp)
+      (fun (_, _, endp)   -> endp)
+      parser
+
+  let revised2traditional parser =
+    revised2traditional
+      (fun token startp endp -> (token, startp, endp))
+      parser
+
+end
+end
+module IncrementalEngine = struct
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+type position = Lexing.position
+
+open General
+
+(* This signature describes the incremental LR engine. *)
+
+(* In this mode, the user controls the lexer, and the parser suspends
+   itself when it needs to read a new token. *)
+
+module type INCREMENTAL_ENGINE = sig
+
+  type token
+
+  (* A value of type [production] is (an index for) a production. The start
+     productions (which do not exist in an \mly file, but are constructed by
+     Menhir internally) are not part of this type. *)
+
+  type production
+
+  (* The type ['a checkpoint] represents an intermediate or final state of the
+     parser. An intermediate checkpoint is a suspension: it records the parser's
+     current state, and allows parsing to be resumed. The parameter ['a] is
+     the type of the semantic value that will eventually be produced if the
+     parser succeeds. *)
+
+  (* [Accepted] and [Rejected] are final checkpoints. [Accepted] carries a
+     semantic value. *)
+
+  (* [InputNeeded] is an intermediate checkpoint. It means that the parser wishes
+     to read one token before continuing. *)
+
+  (* [Shifting] is an intermediate checkpoint. It means that the parser is taking
+     a shift transition. It exposes the state of the parser before and after
+     the transition. The Boolean parameter tells whether the parser intends to
+     request a new token after this transition. (It always does, except when
+     it is about to accept.) *)
+
+  (* [AboutToReduce] is an intermediate checkpoint. It means that the parser is
+     about to perform a reduction step. It exposes the parser's current
+     state as well as the production that is about to be reduced. *)
+
+  (* [HandlingError] is an intermediate checkpoint. It means that the parser has
+     detected an error and is currently handling it, in several steps. *)
+
+  (* A value of type ['a env] represents a configuration of the automaton:
+     current state, stack, lookahead token, etc. The parameter ['a] is the
+     type of the semantic value that will eventually be produced if the parser
+     succeeds. *)
+
+  (* In normal operation, the parser works with checkpoints: see the functions
+     [offer] and [resume]. However, it is also possible to work directly with
+     environments (see the functions [pop], [force_reduction], and [feed]) and
+     to reconstruct a checkpoint out of an environment (see [input_needed]).
+     This is considered advanced functionality; its purpose is to allow error
+     recovery strategies to be programmed by the user. *)
+
+  type 'a env
+
+  type 'a checkpoint = private
+    | InputNeeded of 'a env
+    | Shifting of 'a env * 'a env * bool
+    | AboutToReduce of 'a env * production
+    | HandlingError of 'a env
+    | Accepted of 'a
+    | Rejected
+
+  (* [offer] allows the user to resume the parser after it has suspended
+     itself with a checkpoint of the form [InputNeeded env]. [offer] expects the
+     old checkpoint as well as a new token and produces a new checkpoint. It does not
+     raise any exception. *)
+
+  val offer:
+    'a checkpoint ->
+    token * position * position ->
+    'a checkpoint
+
+  (* [resume] allows the user to resume the parser after it has suspended
+     itself with a checkpoint of the form [AboutToReduce (env, prod)] or
+     [HandlingError env]. [resume] expects the old checkpoint and produces a new
+     checkpoint. It does not raise any exception. *)
+
+  val resume:
+    'a checkpoint ->
+    'a checkpoint
+
+  (* A token supplier is a function of no arguments which delivers a new token
+     (together with its start and end positions) every time it is called. *)
+
+  type supplier =
+    unit -> token * position * position
+
+  (* A pair of a lexer and a lexing buffer can be easily turned into a supplier. *)
+
+  val lexer_lexbuf_to_supplier:
+    (Lexing.lexbuf -> token) ->
+    Lexing.lexbuf ->
+    supplier
+
+  (* The functions [offer] and [resume] are sufficient to write a parser loop.
+     One can imagine many variations (which is why we expose these functions
+     in the first place!). Here, we expose a few variations of the main loop,
+     ready for use. *)
+
+  (* [loop supplier checkpoint] begins parsing from [checkpoint], reading
+     tokens from [supplier]. It continues parsing until it reaches a
+     checkpoint of the form [Accepted v] or [Rejected]. In the former case, it
+     returns [v]. In the latter case, it raises the exception [Error]. *)
+
+  val loop: supplier -> 'a checkpoint -> 'a
+
+  (* [loop_handle succeed fail supplier checkpoint] begins parsing from
+     [checkpoint], reading tokens from [supplier]. It continues parsing until
+     it reaches a checkpoint of the form [Accepted v] or [HandlingError env]
+     (or [Rejected], but that should not happen, as [HandlingError _] will be
+     observed first). In the former case, it calls [succeed v]. In the latter
+     case, it calls [fail] with this checkpoint. It cannot raise [Error].
+
+     This means that Menhir's traditional error-handling procedure (which pops
+     the stack until a state that can act on the [error] token is found) does
+     not get a chance to run. Instead, the user can implement her own error
+     handling code, in the [fail] continuation. *)
+
+  val loop_handle:
+    ('a -> 'answer) ->
+    ('a checkpoint -> 'answer) ->
+    supplier -> 'a checkpoint -> 'answer
+
+  (* [loop_handle_undo] is analogous to [loop_handle], except it passes a pair
+     of checkpoints to the failure continuation.
+
+     The first (and oldest) checkpoint is the last [InputNeeded] checkpoint that
+     was encountered before the error was detected. The second (and newest)
+     checkpoint is where the error was detected, as in [loop_handle]. Going back
+     to the first checkpoint can be thought of as undoing any reductions that
+     were performed after seeing the problematic token. (These reductions must
+     be default reductions or spurious reductions.)
+
+     [loop_handle_undo] must initially be applied to an [InputNeeded] checkpoint.
+     The parser's initial checkpoints satisfy this constraint. *)
+
+  val loop_handle_undo:
+    ('a -> 'answer) ->
+    ('a checkpoint -> 'a checkpoint -> 'answer) ->
+    supplier -> 'a checkpoint -> 'answer
+
+  (* [shifts checkpoint] assumes that [checkpoint] has been obtained by
+     submitting a token to the parser. It runs the parser from [checkpoint],
+     through an arbitrary number of reductions, until the parser either
+     accepts this token (i.e., shifts) or rejects it (i.e., signals an error).
+     If the parser decides to shift, then [Some env] is returned, where [env]
+     is the parser's state just before shifting. Otherwise, [None] is
+     returned. *)
+
+  (* It is desirable that the semantic actions be side-effect free, or that
+     their side-effects be harmless (replayable). *)
+
+  val shifts: 'a checkpoint -> 'a env option
+
+  (* The function [acceptable] allows testing, after an error has been
+     detected, which tokens would have been accepted at this point. It is
+     implemented using [shifts]. Its argument should be an [InputNeeded]
+     checkpoint. *)
+
+  (* For completeness, one must undo any spurious reductions before carrying out
+     this test -- that is, one must apply [acceptable] to the FIRST checkpoint
+     that is passed by [loop_handle_undo] to its failure continuation. *)
+
+  (* This test causes some semantic actions to be run! The semantic actions
+     should be side-effect free, or their side-effects should be harmless. *)
+
+  (* The position [pos] is used as the start and end positions of the
+     hypothetical token, and may be picked up by the semantic actions. We
+     suggest using the position where the error was detected. *)
+
+  val acceptable: 'a checkpoint -> token -> position -> bool
+
+  (* The abstract type ['a lr1state] describes the non-initial states of the
+     LR(1) automaton. The index ['a] represents the type of the semantic value
+     associated with this state's incoming symbol. *)
+
+  type 'a lr1state
+
+  (* The states of the LR(1) automaton are numbered (from 0 and up). *)
+
+  val number: _ lr1state -> int
+
+  (* Productions are numbered. *)
+
+  (* [find_production i] requires the index [i] to be valid. Use with care. *)
+
+  val production_index: production -> int
+  val find_production: int -> production
+
+  (* An element is a pair of a non-initial state [s] and a semantic value [v]
+     associated with the incoming symbol of this state. The idea is, the value
+     [v] was pushed onto the stack just before the state [s] was entered. Thus,
+     for some type ['a], the state [s] has type ['a lr1state] and the value [v]
+     has type ['a]. In other words, the type [element] is an existential type. *)
+
+  type element =
+    | Element: 'a lr1state * 'a * position * position -> element
+
+  (* The parser's stack is (or, more precisely, can be viewed as) a stream of
+     elements. The type [stream] is defined by the module [General]. *)
+
+  (* As of 2017/03/31, the types [stream] and [stack] and the function [stack]
+     are DEPRECATED. They might be removed in the future. An alternative way
+     of inspecting the stack is via the functions [top] and [pop]. *)
+
+  type stack = (* DEPRECATED *)
+    element stream
+
+  (* This is the parser's stack, a stream of elements. This stream is empty if
+     the parser is in an initial state; otherwise, it is non-empty.  The LR(1)
+     automaton's current state is the one found in the top element of the
+     stack. *)
+
+  val stack: 'a env -> stack (* DEPRECATED *)
+
+  (* [top env] returns the parser's top stack element. The state contained in
+     this stack element is the current state of the automaton. If the stack is
+     empty, [None] is returned. In that case, the current state of the
+     automaton must be an initial state. *)
+
+  val top: 'a env -> element option
+
+  (* [pop_many i env] pops [i] cells off the automaton's stack. This is done
+     via [i] successive invocations of [pop]. Thus, [pop_many 1] is [pop]. The
+     index [i] must be nonnegative. The time complexity is O(i). *)
+
+  val pop_many: int -> 'a env -> 'a env option
+
+  (* [get i env] returns the parser's [i]-th stack element. The index [i] is
+     0-based: thus, [get 0] is [top]. If [i] is greater than or equal to the
+     number of elements in the stack, [None] is returned. The time complexity
+     is O(i). *)
+
+  val get: int -> 'a env -> element option
+
+  (* [current_state_number env] is (the integer number of) the automaton's
+     current state. This works even if the automaton's stack is empty, in
+     which case the current state is an initial state. This number can be
+     passed as an argument to a [message] function generated by [menhir
+     --compile-errors]. *)
+
+  val current_state_number: 'a env -> int
+
+  (* [equal env1 env2] tells whether the parser configurations [env1] and
+     [env2] are equal in the sense that the automaton's current state is the
+     same in [env1] and [env2] and the stack is *physically* the same in
+     [env1] and [env2]. If [equal env1 env2] is [true], then the sequence of
+     the stack elements, as observed via [pop] and [top], must be the same in
+     [env1] and [env2]. Also, if [equal env1 env2] holds, then the checkpoints
+     [input_needed env1] and [input_needed env2] must be equivalent. The
+     function [equal] has time complexity O(1). *)
+
+  val equal: 'a env -> 'a env -> bool
+
+  (* These are the start and end positions of the current lookahead token. If
+     invoked in an initial state, this function returns a pair of twice the
+     initial position. *)
+
+  val positions: 'a env -> position * position
+
+  (* When applied to an environment taken from a checkpoint of the form
+     [AboutToReduce (env, prod)], the function [env_has_default_reduction]
+     tells whether the reduction that is about to take place is a default
+     reduction. *)
+
+  val env_has_default_reduction: 'a env -> bool
+
+  (* [state_has_default_reduction s] tells whether the state [s] has a default
+     reduction. This includes the case where [s] is an accepting state. *)
+
+  val state_has_default_reduction: _ lr1state -> bool
+
+  (* [pop env] returns a new environment, where the parser's top stack cell
+     has been popped off. (If the stack is empty, [None] is returned.) This
+     amounts to pretending that the (terminal or nonterminal) symbol that
+     corresponds to this stack cell has not been read. *)
+
+  val pop: 'a env -> 'a env option
+
+  (* [force_reduction prod env] should be called only if in the state [env]
+     the parser is capable of reducing the production [prod]. If this
+     condition is satisfied, then this production is reduced, which means that
+     its semantic action is executed (this can have side effects!) and the
+     automaton makes a goto (nonterminal) transition. If this condition is not
+     satisfied, [Invalid_argument _] is raised. *)
+
+  val force_reduction: production -> 'a env -> 'a env
+
+  (* [input_needed env] returns [InputNeeded env]. That is, out of an [env]
+     that might have been obtained via a series of calls to the functions
+     [pop], [force_reduction], [feed], etc., it produces a checkpoint, which
+     can be used to resume normal parsing, by supplying this checkpoint as an
+     argument to [offer]. *)
+
+  (* This function should be used with some care. It could "mess up the
+     lookahead" in the sense that it allows parsing to resume in an arbitrary
+     state [s] with an arbitrary lookahead symbol [t], even though Menhir's
+     reachability analysis (menhir --list-errors) might well think that it is
+     impossible to reach this particular configuration. If one is using
+     Menhir's new error reporting facility, this could cause the parser to
+     reach an error state for which no error message has been prepared. *)
+
+  val input_needed: 'a env -> 'a checkpoint
+
+end
+
+(* This signature is a fragment of the inspection API that is made available
+   to the user when [--inspection] is used. This fragment contains type
+   definitions for symbols. *)
+
+module type SYMBOLS = sig
+
+  (* The type ['a terminal] represents a terminal symbol. The type ['a
+     nonterminal] represents a nonterminal symbol. In both cases, the index
+     ['a] represents the type of the semantic values associated with this
+     symbol. The concrete definitions of these types are generated. *)
+
+  type 'a terminal
+  type 'a nonterminal
+
+  (* The type ['a symbol] represents a terminal or nonterminal symbol. It is
+     the disjoint union of the types ['a terminal] and ['a nonterminal]. *)
+
+  type 'a symbol =
+    | T : 'a terminal -> 'a symbol
+    | N : 'a nonterminal -> 'a symbol
+
+  (* The type [xsymbol] is an existentially quantified version of the type
+     ['a symbol]. This type is useful in situations where the index ['a]
+     is not statically known. *)
+
+  type xsymbol =
+    | X : 'a symbol -> xsymbol
+
+end
+
+(* This signature describes the inspection API that is made available to the
+   user when [--inspection] is used. *)
+
+module type INSPECTION = sig
+
+  (* The types of symbols are described above. *)
+
+  include SYMBOLS
+
+  (* The type ['a lr1state] is meant to be the same as in [INCREMENTAL_ENGINE]. *)
+
+  type 'a lr1state
+
+  (* The type [production] is meant to be the same as in [INCREMENTAL_ENGINE].
+     It represents a production of the grammar. A production can be examined
+     via the functions [lhs] and [rhs] below. *)
+
+  type production
+
+  (* An LR(0) item is a pair of a production [prod] and a valid index [i] into
+     this production. That is, if the length of [rhs prod] is [n], then [i] is
+     comprised between 0 and [n], inclusive. *)
+
+  type item =
+      production * int
+
+  (* Ordering functions. *)
+
+  val compare_terminals: _ terminal -> _ terminal -> int
+  val compare_nonterminals: _ nonterminal -> _ nonterminal -> int
+  val compare_symbols: xsymbol -> xsymbol -> int
+  val compare_productions: production -> production -> int
+  val compare_items: item -> item -> int
+
+  (* [incoming_symbol s] is the incoming symbol of the state [s], that is,
+     the symbol that the parser must recognize before (has recognized when)
+     it enters the state [s]. This function gives access to the semantic
+     value [v] stored in a stack element [Element (s, v, _, _)]. Indeed,
+     by case analysis on the symbol [incoming_symbol s], one discovers the
+     type ['a] of the value [v]. *)
+
+  val incoming_symbol: 'a lr1state -> 'a symbol
+
+  (* [items s] is the set of the LR(0) items in the LR(0) core of the LR(1)
+     state [s]. This set is not epsilon-closed. This set is presented as a
+     list, in an arbitrary order. *)
+
+  val items: _ lr1state -> item list
+
+  (* [lhs prod] is the left-hand side of the production [prod]. This is
+     always a non-terminal symbol. *)
+
+  val lhs: production -> xsymbol
+
+  (* [rhs prod] is the right-hand side of the production [prod]. This is
+     a (possibly empty) sequence of (terminal or nonterminal) symbols. *)
+
+  val rhs: production -> xsymbol list
+
+  (* [nullable nt] tells whether the non-terminal symbol [nt] is nullable.
+     That is, it is true if and only if this symbol produces the empty
+     word [epsilon]. *)
+
+  val nullable: _ nonterminal -> bool
+
+  (* [first nt t] tells whether the FIRST set of the nonterminal symbol [nt]
+     contains the terminal symbol [t]. That is, it is true if and only if
+     [nt] produces a word that begins with [t]. *)
+
+  val first: _ nonterminal -> _ terminal -> bool
+
+  (* [xfirst] is analogous to [first], but expects a first argument of type
+     [xsymbol] instead of [_ terminal]. *)
+
+  val xfirst: xsymbol -> _ terminal -> bool
+
+  (* [foreach_terminal] enumerates the terminal symbols, including [error].
+     [foreach_terminal_but_error] enumerates the terminal symbols, excluding
+     [error]. *)
+
+  val foreach_terminal:           (xsymbol -> 'a -> 'a) -> 'a -> 'a
+  val foreach_terminal_but_error: (xsymbol -> 'a -> 'a) -> 'a -> 'a
+
+  (* The type [env] is meant to be the same as in [INCREMENTAL_ENGINE]. *)
+
+  type 'a env
+
+  (* [feed symbol startp semv endp env] causes the parser to consume the
+     (terminal or nonterminal) symbol [symbol], accompanied with the semantic
+     value [semv] and with the start and end positions [startp] and [endp].
+     Thus, the automaton makes a transition, and reaches a new state. The
+     stack grows by one cell. This operation is permitted only if the current
+     state (as determined by [env]) has an outgoing transition labeled with
+     [symbol]. Otherwise, [Invalid_argument _] is raised. *)
+
+  val feed: 'a symbol -> position -> 'a -> position -> 'b env -> 'b env
+
+end
+
+(* This signature combines the incremental API and the inspection API. *)
+
+module type EVERYTHING = sig
+
+  include INCREMENTAL_ENGINE
+
+  include INSPECTION
+    with type 'a lr1state := 'a lr1state
+    with type production := production
+    with type 'a env := 'a env
+
+end
+end
+module EngineTypes = struct
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* This file defines several types and module types that are used in the
+   specification of module [Engine]. *)
+
+(* --------------------------------------------------------------------------- *)
+
+(* It would be nice if we could keep the structure of stacks and environments
+   hidden. However, stacks and environments must be accessible to semantic
+   actions, so the following data structure definitions must be public. *)
+
+(* --------------------------------------------------------------------------- *)
+
+(* A stack is a linked list of cells. A sentinel cell -- which is its own
+   successor -- is used to mark the bottom of the stack. The sentinel cell
+   itself is not significant -- it contains dummy values. *)
+
+type ('state, 'semantic_value) stack = {
+
+  (* The state that we should go back to if we pop this stack cell. *)
+
+  (* This convention means that the state contained in the top stack cell is
+     not the current state [env.current]. It also means that the state found
+     within the sentinel is a dummy -- it is never consulted. This convention
+     is the same as that adopted by the code-based back-end. *)
+
+  state: 'state;
+
+  (* The semantic value associated with the chunk of input that this cell
+     represents. *)
+
+  semv: 'semantic_value;
+
+  (* The start and end positions of the chunk of input that this cell
+     represents. *)
+
+  startp: Lexing.position;
+  endp: Lexing.position;
+
+  (* The next cell down in the stack. If this is a self-pointer, then this
+     cell is the sentinel, and the stack is conceptually empty. *)
+
+  next: ('state, 'semantic_value) stack;
+
+}
+
+(* --------------------------------------------------------------------------- *)
+
+(* A parsing environment contains all of the parser's state (except for the
+   current program point). *)
+
+type ('state, 'semantic_value, 'token) env = {
+
+  (* If this flag is true, then the first component of [env.triple] should
+     be ignored, as it has been logically overwritten with the [error]
+     pseudo-token. *)
+
+  error: bool;
+
+  (* The last token that was obtained from the lexer, together with its start
+     and end positions. Warning: before the first call to the lexer has taken
+     place, a dummy (and possibly invalid) token is stored here. *)
+
+  triple: 'token * Lexing.position * Lexing.position;
+
+  (* The stack. In [CodeBackend], it is passed around on its own,
+     whereas, here, it is accessed via the environment. *)
+
+  stack: ('state, 'semantic_value) stack;
+
+  (* The current state. In [CodeBackend], it is passed around on its
+     own, whereas, here, it is accessed via the environment. *)
+
+  current: 'state;
+
+}
+
+(* --------------------------------------------------------------------------- *)
+
+(* This signature describes the parameters that must be supplied to the LR
+   engine. *)
+
+module type TABLE = sig
+
+  (* The type of automaton states. *)
+
+  type state
+
+  (* States are numbered. *)
+
+  val number: state -> int
+
+  (* The type of tokens. These can be thought of as real tokens, that is,
+     tokens returned by the lexer. They carry a semantic value. This type
+     does not include the [error] pseudo-token. *)
+
+  type token
+
+  (* The type of terminal symbols. These can be thought of as integer codes.
+     They do not carry a semantic value. This type does include the [error]
+     pseudo-token. *)
+
+  type terminal
+
+  (* The type of nonterminal symbols. *)
+
+  type nonterminal
+
+  (* The type of semantic values. *)
+
+  type semantic_value
+
+  (* A token is conceptually a pair of a (non-[error]) terminal symbol and
+     a semantic value. The following two functions are the pair projections. *)
+
+  val token2terminal: token -> terminal
+  val token2value: token -> semantic_value
+
+  (* Even though the [error] pseudo-token is not a real token, it is a
+     terminal symbol. Furthermore, for regularity, it must have a semantic
+     value. *)
+
+  val error_terminal: terminal
+  val error_value: semantic_value
+
+  (* [foreach_terminal] allows iterating over all terminal symbols. *)
+
+  val foreach_terminal: (terminal -> 'a -> 'a) -> 'a -> 'a
+
+  (* The type of productions. *)
+
+  type production
+
+  val production_index: production -> int
+  val find_production: int -> production
+
+  (* If a state [s] has a default reduction on production [prod], then, upon
+     entering [s], the automaton should reduce [prod] without consulting the
+     lookahead token. The following function allows determining which states
+     have default reductions. *)
+
+  (* Instead of returning a value of a sum type -- either [DefRed prod], or
+     [NoDefRed] -- it accepts two continuations, and invokes just one of
+     them. This mechanism allows avoiding a memory allocation. *)
+
+  val default_reduction:
+    state ->
+    ('env -> production -> 'answer) ->
+    ('env -> 'answer) ->
+    'env -> 'answer
+
+  (* An LR automaton can normally take three kinds of actions: shift, reduce,
+     or fail. (Acceptance is a particular case of reduction: it consists in
+     reducing a start production.) *)
+
+  (* There are two variants of the shift action. [shift/discard s] instructs
+     the automaton to discard the current token, request a new one from the
+     lexer, and move to state [s]. [shift/nodiscard s] instructs it to move to
+     state [s] without requesting a new token. This instruction should be used
+     when [s] has a default reduction on [#]. See [CodeBackend.gettoken] for
+     details. *)
+
+  (* This is the automaton's action table. It maps a pair of a state and a
+     terminal symbol to an action. *)
+
+  (* Instead of returning a value of a sum type -- one of shift/discard,
+     shift/nodiscard, reduce, or fail -- this function accepts three
+     continuations, and invokes just one them. This mechanism allows avoiding
+     a memory allocation. *)
+
+  (* In summary, the parameters to [action] are as follows:
+
+     - the first two parameters, a state and a terminal symbol, are used to
+       look up the action table;
+
+     - the next parameter is the semantic value associated with the above
+       terminal symbol; it is not used, only passed along to the shift
+       continuation, as explained below;
+
+     - the shift continuation expects an environment; a flag that tells
+       whether to discard the current token; the terminal symbol that
+       is being shifted; its semantic value; and the target state of
+       the transition;
+
+     - the reduce continuation expects an environment and a production;
+
+     - the fail continuation expects an environment;
+
+     - the last parameter is the environment; it is not used, only passed
+       along to the selected continuation. *)
+
+  val action:
+    state ->
+    terminal ->
+    semantic_value ->
+    ('env -> bool -> terminal -> semantic_value -> state -> 'answer) ->
+    ('env -> production -> 'answer) ->
+    ('env -> 'answer) ->
+    'env -> 'answer
+
+  (* This is the automaton's goto table. This table maps a pair of a state
+     and a nonterminal symbol to a new state. By extension, it also maps a
+     pair of a state and a production to a new state. *)
+
+  (* The function [goto_nt] can be applied to [s] and [nt] ONLY if the state
+     [s] has an outgoing transition labeled [nt]. Otherwise, its result is
+     undefined. Similarly, the call [goto_prod prod s] is permitted ONLY if
+     the state [s] has an outgoing transition labeled with the nonterminal
+     symbol [lhs prod]. The function [maybe_goto_nt] involves an additional
+     dynamic check and CAN be called even if there is no outgoing transition. *)
+
+  val       goto_nt  : state -> nonterminal -> state
+  val       goto_prod: state -> production  -> state
+  val maybe_goto_nt:   state -> nonterminal -> state option
+
+  (* [is_start prod] tells whether the production [prod] is a start production. *)
+
+  val is_start: production -> bool
+
+  (* By convention, a semantic action is responsible for:
+
+     1. fetching whatever semantic values and positions it needs off the stack;
+
+     2. popping an appropriate number of cells off the stack, as dictated
+        by the length of the right-hand side of the production;
+
+     3. computing a new semantic value, as well as new start and end positions;
+
+     4. pushing a new stack cell, which contains the three values
+        computed in step 3;
+
+     5. returning the new stack computed in steps 2 and 4.
+
+     Point 1 is essentially forced upon us: if semantic values were fetched
+     off the stack by this interpreter, then the calling convention for
+     semantic actions would be variadic: not all semantic actions would have
+     the same number of arguments. The rest follows rather naturally. *)
+
+  (* Semantic actions are allowed to raise [Error]. *)
+
+  exception Error
+
+  type semantic_action =
+      (state, semantic_value, token) env -> (state, semantic_value) stack
+
+  val semantic_action: production -> semantic_action
+
+  (* [may_reduce state prod] tests whether the state [state] is capable of
+     reducing the production [prod]. This function is currently costly and
+     is not used by the core LR engine. It is used in the implementation
+     of certain functions, such as [force_reduction], which allow the engine
+     to be driven programmatically. *)
+
+  val may_reduce: state -> production -> bool
+
+  (* The LR engine requires a number of hooks, which are used for logging. *)
+
+  (* The comments below indicate the conventional messages that correspond
+     to these hooks in the code-based back-end; see [CodeBackend]. *)
+
+  (* If the flag [log] is false, then the logging functions are not called.
+     If it is [true], then they are called. *)
+
+  val log : bool
+
+  module Log : sig
+
+    (* State %d: *)
+
+    val state: state -> unit
+
+    (* Shifting () to state  *)
+
+    val shift: terminal -> state -> unit
+
+    (* Reducing a production should be logged either as a reduction
+       event (for regular productions) or as an acceptance event (for
+       start productions). *)
+
+    (* Reducing production  / Accepting *)
+
+    val reduce_or_accept: production -> unit
+
+    (* Lookahead token is now  (-) *)
+
+    val lookahead_token: terminal -> Lexing.position -> Lexing.position -> unit
+
+    (* Initiating error handling *)
+
+    val initiating_error_handling: unit -> unit
+
+    (* Resuming error handling *)
+
+    val resuming_error_handling: unit -> unit
+
+    (* Handling error in state  *)
+
+    val handling_error: state -> unit
+
+  end
+
+end
+
+(* --------------------------------------------------------------------------- *)
+
+(* This signature describes the monolithic (traditional) LR engine. *)
+
+(* In this interface, the parser controls the lexer. *)
+
+module type MONOLITHIC_ENGINE = sig
+
+  type state
+
+  type token
+
+  type semantic_value
+
+  (* An entry point to the engine requires a start state, a lexer, and a lexing
+     buffer. It either succeeds and produces a semantic value, or fails and
+     raises [Error]. *)
+
+  exception Error
+
+  val entry:
+    state ->
+    (Lexing.lexbuf -> token) ->
+    Lexing.lexbuf ->
+    semantic_value
+
+end
+
+(* --------------------------------------------------------------------------- *)
+
+(* The following signatures describe the incremental LR engine. *)
+
+(* First, see [INCREMENTAL_ENGINE] in the file [IncrementalEngine.ml]. *)
+
+(* The [start] function is set apart because we do not wish to publish
+   it as part of the generated [parser.mli] file. Instead, the table
+   back-end will publish specialized versions of it, with a suitable
+   type cast. *)
+
+module type INCREMENTAL_ENGINE_START = sig
+
+  (* [start] is an entry point. It requires a start state and a start position
+     and begins the parsing process. If the lexer is based on an OCaml lexing
+     buffer, the start position should be [lexbuf.lex_curr_p]. [start] produces
+     a checkpoint, which usually will be an [InputNeeded] checkpoint. (It could
+     be [Accepted] if this starting state accepts only the empty word. It could
+     be [Rejected] if this starting state accepts no word at all.) It does not
+     raise any exception. *)
+
+  (* [start s pos] should really produce a checkpoint of type ['a checkpoint],
+     for a fixed ['a] that depends on the state [s]. We cannot express this, so
+     we use [semantic_value checkpoint], which is safe. The table back-end uses
+     [Obj.magic] to produce safe specialized versions of [start]. *)
+
+  type state
+  type semantic_value
+  type 'a checkpoint
+
+  val start:
+    state ->
+    Lexing.position ->
+    semantic_value checkpoint
+
+end
+
+(* --------------------------------------------------------------------------- *)
+
+(* This signature describes the LR engine, which combines the monolithic
+   and incremental interfaces. *)
+
+module type ENGINE = sig
+
+  include MONOLITHIC_ENGINE
+
+  include IncrementalEngine.INCREMENTAL_ENGINE
+    with type token := token
+     and type 'a lr1state = state (* useful for us; hidden from the end user *)
+
+  include INCREMENTAL_ENGINE_START
+    with type state := state
+     and type semantic_value := semantic_value
+     and type 'a checkpoint := 'a checkpoint
+
+end
+end
+module Engine = struct
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+type position = Lexing.position
+open EngineTypes
+
+(* The LR parsing engine. *)
+
+(* This module is used:
+
+   - at compile time, if so requested by the user, via the --interpret options;
+   - at run time, in the table-based back-end. *)
+
+module Make (T : TABLE) = struct
+
+  (* This propagates type and exception definitions. The functions [number],
+     [production_index], [find_production], too, are defined by this [include]
+     declaration. *)
+
+  include T
+
+  type 'a env =
+      (state, semantic_value, token) EngineTypes.env
+
+  (* ------------------------------------------------------------------------ *)
+
+  (* The type [checkpoint] represents an intermediate or final result of the
+     parser. See [EngineTypes]. *)
+
+  (* The type [checkpoint] is presented to the user as a private type (see
+     [IncrementalEngine]). This prevents the user from manufacturing
+     checkpoints (i.e., continuations) that do not make sense. (Such
+     continuations could potentially violate the LR invariant and lead to
+     crashes.) *)
+
+  (* 2017/03/29 Although [checkpoint] is a private type, we now expose a
+     constructor function, [input_needed]. This function allows manufacturing
+     a checkpoint out of an environment. For this reason, the type [env] must
+     also be parameterized with ['a]. *)
+
+  type 'a checkpoint =
+    | InputNeeded of 'a env
+    | Shifting of 'a env * 'a env * bool
+    | AboutToReduce of 'a env * production
+    | HandlingError of 'a env
+    | Accepted of 'a
+    | Rejected
+
+  (* ------------------------------------------------------------------------ *)
+
+  (* In the code-based back-end, the [run] function is sometimes responsible
+     for pushing a new cell on the stack. This is motivated by code sharing
+     concerns. In this interpreter, there is no such concern; [run]'s caller
+     is always responsible for updating the stack. *)
+
+  (* In the code-based back-end, there is a [run] function for each state
+     [s]. This function can behave in two slightly different ways, depending
+     on when it is invoked, or (equivalently) depending on [s].
+
+     If [run] is invoked after shifting a terminal symbol (or, equivalently,
+     if [s] has a terminal incoming symbol), then [run] discards a token,
+     unless [s] has a default reduction on [#]. (Indeed, in that case,
+     requesting the next token might drive the lexer off the end of the input
+     stream.)
+
+     If, on the other hand, [run] is invoked after performing a goto
+     transition, or invoked directly by an entry point, then there is nothing
+     to discard.
+
+     These two cases are reflected in [CodeBackend.gettoken].
+
+     Here, the code is structured in a slightly different way. It is up to the
+     caller of [run] to indicate whether to discard a token, via the parameter
+     [please_discard]. This flag is set when [s] is being entered by shifting
+     a terminal symbol and [s] does not have a default reduction on [#]. *)
+
+  (* The following recursive group of functions are tail recursive, produce a
+     checkpoint of type [semantic_value checkpoint], and cannot raise an
+     exception. A semantic action can raise [Error], but this exception is
+     immediately caught within [reduce]. *)
+
+  let rec run env please_discard : semantic_value checkpoint =
+
+    (* Log the fact that we just entered this state. *)
+
+    if log then
+      Log.state env.current;
+
+    (* If [please_discard] is set, we discard the current lookahead token and
+       fetch the next one. In order to request a token from the user, we
+       return an [InputNeeded] continuation, which, when invoked by the user,
+       will take us to [discard]. If [please_discard] is not set, we skip this
+       step and jump directly to [check_for_default_reduction]. *)
+
+    if please_discard then
+      InputNeeded env
+    else
+      check_for_default_reduction env
+
+  (* [discard env triple] stores [triple] into [env], overwriting the previous
+     token. It is invoked by [offer], which itself is invoked by the user in
+     response to an [InputNeeded] checkpoint. *)
+
+  and discard env triple =
+    if log then begin
+      let (token, startp, endp) = triple in
+      Log.lookahead_token (T.token2terminal token) startp endp
+    end;
+    let env = { env with error = false; triple } in
+    check_for_default_reduction env
+
+  and check_for_default_reduction env =
+
+    (* Examine what situation we are in. This case analysis is analogous to
+       that performed in [CodeBackend.gettoken], in the sub-case where we do
+       not have a terminal incoming symbol. *)
+
+    T.default_reduction
+      env.current
+      announce_reduce       (* there is a default reduction; perform it *)
+      check_for_error_token (* there is none; continue below *)
+      env
+
+  and check_for_error_token env =
+
+    (* There is no default reduction. Consult the current lookahead token
+       so as to determine which action should be taken. *)
+
+    (* Peeking at the first input token, without taking it off the input
+       stream, is done by reading [env.triple]. We are careful to first
+       check [env.error]. *)
+
+    (* Note that, if [please_discard] was true, then we have just called
+       [discard], so the lookahead token cannot be [error]. *)
+
+    (* Returning [HandlingError env] is equivalent to calling [error env]
+       directly, except it allows the user to regain control. *)
+
+    if env.error then begin
+      if log then
+        Log.resuming_error_handling();
+      HandlingError env
+    end
+    else
+      let (token, _, _) = env.triple in
+
+      (* We consult the two-dimensional action table, indexed by the
+         current state and the current lookahead token, in order to
+         determine which action should be taken. *)
+
+      T.action
+        env.current                    (* determines a row *)
+        (T.token2terminal token)       (* determines a column *)
+        (T.token2value token)
+        shift                          (* shift continuation *)
+        announce_reduce                (* reduce continuation *)
+        initiate                       (* failure continuation *)
+        env
+
+  (* ------------------------------------------------------------------------ *)
+
+  (* This function takes care of shift transitions along a terminal symbol.
+     (Goto transitions are taken care of within [reduce] below.) The symbol
+     can be either an actual token or the [error] pseudo-token. *)
+
+  (* Here, the lookahead token CAN be [error]. *)
+
+  and shift env
+      (please_discard : bool)
+      (terminal : terminal)
+      (value : semantic_value)
+      (s' : state) =
+
+    (* Log the transition. *)
+
+    if log then
+      Log.shift terminal s';
+
+    (* Push a new cell onto the stack, containing the identity of the
+       state that we are leaving. *)
+
+    let (_, startp, endp) = env.triple in
+    let stack = {
+      state = env.current;
+      semv = value;
+      startp;
+      endp;
+      next = env.stack;
+    } in
+
+    (* Switch to state [s']. *)
+
+    let new_env = { env with stack; current = s' } in
+
+    (* Expose the transition to the user. (In principle, we have a choice
+       between exposing the transition before we take it, after we take
+       it, or at some point in between. This affects the number and type
+       of the parameters carried by [Shifting]. Here, we choose to expose
+       the transition after we take it; this allows [Shifting] to carry
+       only three parameters, whose meaning is simple.) *)
+
+    Shifting (env, new_env, please_discard)
+
+  (* ------------------------------------------------------------------------ *)
+
+  (* The function [announce_reduce] stops the parser and returns a checkpoint
+     which allows the parser to be resumed by calling [reduce]. *)
+
+  (* Only ordinary productions are exposed to the user. Start productions
+     are not exposed to the user. Reducing a start production simply leads
+     to the successful termination of the parser. *)
+
+  and announce_reduce env (prod : production) =
+    if T.is_start prod then
+      accept env prod
+    else
+      AboutToReduce (env, prod)
+
+  (* The function [reduce] takes care of reductions. It is invoked by
+     [resume] after an [AboutToReduce] event has been produced. *)
+
+  (* Here, the lookahead token CAN be [error]. *)
+
+  (* The production [prod] CANNOT be a start production. *)
+
+  and reduce env (prod : production) =
+
+    (* Log a reduction event. *)
+
+    if log then
+      Log.reduce_or_accept prod;
+
+    (* Invoke the semantic action. The semantic action is responsible for
+       truncating the stack and pushing a new cell onto the stack, which
+       contains a new semantic value. It can raise [Error]. *)
+
+    (* If the semantic action terminates normally, it returns a new stack,
+       which becomes the current stack. *)
+
+    (* If the semantic action raises [Error], we catch it and initiate error
+       handling. *)
+
+    (* This [match/with/exception] construct requires OCaml 4.02. *)
+
+    match T.semantic_action prod env with
+    | stack ->
+
+        (* By our convention, the semantic action has produced an updated
+           stack. The state now found in the top stack cell is the return
+           state. *)
+
+        (* Perform a goto transition. The target state is determined
+           by consulting the goto table at the return state and at
+           production [prod]. *)
+
+        let current = T.goto_prod stack.state prod in
+        let env = { env with stack; current } in
+        run env false
+
+    | exception Error ->
+        initiate env
+
+  and accept env prod =
+    (* Log an accept event. *)
+    if log then
+      Log.reduce_or_accept prod;
+    (* Extract the semantic value out of the stack. *)
+    let v = env.stack.semv in
+    (* Finish. *)
+    Accepted v
+
+  (* ------------------------------------------------------------------------ *)
+
+  (* The following functions deal with errors. *)
+
+  (* [initiate] initiates or resumes error handling. *)
+
+  (* Here, the lookahead token CAN be [error]. *)
+
+  and initiate env =
+    if log then
+      Log.initiating_error_handling();
+    let env = { env with error = true } in
+    HandlingError env
+
+  (* [error] handles errors. *)
+
+  and error env =
+    assert env.error;
+
+    (* Consult the column associated with the [error] pseudo-token in the
+       action table. *)
+
+    T.action
+      env.current                    (* determines a row *)
+      T.error_terminal               (* determines a column *)
+      T.error_value
+      error_shift                    (* shift continuation *)
+      error_reduce                   (* reduce continuation *)
+      error_fail                     (* failure continuation *)
+      env
+
+  and error_shift env please_discard terminal value s' =
+
+    (* Here, [terminal] is [T.error_terminal],
+       and [value] is [T.error_value]. *)
+
+    assert (terminal = T.error_terminal && value = T.error_value);
+
+    (* This state is capable of shifting the [error] token. *)
+
+    if log then
+      Log.handling_error env.current;
+    shift env please_discard terminal value s'
+
+  and error_reduce env prod =
+
+    (* This state is capable of performing a reduction on [error]. *)
+
+    if log then
+      Log.handling_error env.current;
+    reduce env prod
+      (* Intentionally calling [reduce] instead of [announce_reduce].
+         It does not seem very useful, and it could be confusing, to
+         expose the reduction steps taken during error handling. *)
+
+  and error_fail env =
+
+    (* This state is unable to handle errors. Attempt to pop a stack
+       cell. *)
+
+    let cell = env.stack in
+    let next = cell.next in
+    if next == cell then
+
+      (* The stack is empty. Die. *)
+
+      Rejected
+
+    else begin
+
+      (* The stack is nonempty. Pop a cell, updating the current state
+         with that found in the popped cell, and try again. *)
+
+      let env = { env with
+        stack = next;
+        current = cell.state
+      } in
+      HandlingError env
+
+    end
+
+  (* End of the nest of tail recursive functions. *)
+
+  (* ------------------------------------------------------------------------ *)
+  (* ------------------------------------------------------------------------ *)
+
+  (* The incremental interface. See [EngineTypes]. *)
+
+  (* [start s] begins the parsing process. *)
+
+  let start (s : state) (initial : position) : semantic_value checkpoint =
+
+    (* Build an empty stack. This is a dummy cell, which is its own successor.
+       Its [next] field WILL be accessed by [error_fail] if an error occurs and
+       is propagated all the way until the stack is empty. Its [endp] field WILL
+       be accessed (by a semantic action) if an epsilon production is reduced
+       when the stack is empty. *)
+
+    let rec empty = {
+      state = s;                          (* dummy *)
+      semv = T.error_value;               (* dummy *)
+      startp = initial;                   (* dummy *)
+      endp = initial;
+      next = empty;
+    } in
+
+    (* Build an initial environment. *)
+
+    (* Unfortunately, there is no type-safe way of constructing a
+       dummy token. Tokens carry semantic values, which in general
+       we cannot manufacture. This instance of [Obj.magic] could
+       be avoided by adopting a different representation (e.g., no
+       [env.error] field, and an option in the first component of
+       [env.triple]), but I like this representation better. *)
+
+    let dummy_token = Obj.magic () in
+    let env = {
+      error = false;
+      triple = (dummy_token, initial, initial); (* dummy *)
+      stack = empty;
+      current = s;
+    } in
+
+    (* Begin parsing. *)
+
+    (* The parameter [please_discard] here is [true], which means we know
+       that we must read at least one token. This claim relies on the fact
+       that we have ruled out the two special cases where a start symbol
+       recognizes the empty language or the singleton language {epsilon}. *)
+
+    run env true
+
+  (* [offer checkpoint triple] is invoked by the user in response to a
+     checkpoint of the form [InputNeeded env]. It checks that [checkpoint] is
+     indeed of this form, and invokes [discard]. *)
+
+  (* [resume checkpoint] is invoked by the user in response to a checkpoint of
+     the form [AboutToReduce (env, prod)] or [HandlingError env]. It checks
+     that [checkpoint] is indeed of this form, and invokes [reduce] or
+     [error], as appropriate. *)
+
+  (* In reality, [offer] and [resume] accept an argument of type
+     [semantic_value checkpoint] and produce a checkpoint of the same type.
+     The choice of [semantic_value] is forced by the fact that this is the
+     parameter of the checkpoint [Accepted]. *)
+
+  (* We change this as follows. *)
+
+  (* We change the argument and result type of [offer] and [resume] from
+     [semantic_value checkpoint] to ['a checkpoint]. This is safe, in this
+     case, because we give the user access to values of type [t checkpoint]
+     only if [t] is indeed the type of the eventual semantic value for this
+     run. (More precisely, by examining the signatures [INCREMENTAL_ENGINE]
+     and [INCREMENTAL_ENGINE_START], one finds that the user can build a value
+     of type ['a checkpoint] only if ['a] is [semantic_value]. The table
+     back-end goes further than this and produces versions of [start] composed
+     with a suitable cast, which give the user access to a value of type
+     [t checkpoint] where [t] is the type of the start symbol.) *)
+
+  let offer : 'a . 'a checkpoint ->
+                   token * position * position ->
+                   'a checkpoint
+  = function
+    | InputNeeded env ->
+        Obj.magic discard env
+    | _ ->
+        invalid_arg "offer expects InputNeeded"
+
+  let resume : 'a . 'a checkpoint -> 'a checkpoint = function
+    | HandlingError env ->
+        Obj.magic error env
+    | Shifting (_, env, please_discard) ->
+        Obj.magic run env please_discard
+    | AboutToReduce (env, prod) ->
+        Obj.magic reduce env prod
+    | _ ->
+        invalid_arg "resume expects HandlingError | Shifting | AboutToReduce"
+
+  (* ------------------------------------------------------------------------ *)
+  (* ------------------------------------------------------------------------ *)
+
+  (* The traditional interface. See [EngineTypes]. *)
+
+  (* ------------------------------------------------------------------------ *)
+
+  (* Wrapping a lexer and lexbuf as a token supplier. *)
+
+  type supplier =
+    unit -> token * position * position
+
+  let lexer_lexbuf_to_supplier
+      (lexer : Lexing.lexbuf -> token)
+      (lexbuf : Lexing.lexbuf)
+  : supplier =
+    fun () ->
+      let token = lexer lexbuf in
+      let startp = lexbuf.Lexing.lex_start_p
+      and endp = lexbuf.Lexing.lex_curr_p in
+      token, startp, endp
+
+  (* ------------------------------------------------------------------------ *)
+
+  (* The main loop repeatedly handles intermediate checkpoints, until a final
+     checkpoint is obtained. This allows implementing the monolithic interface
+     ([entry]) in terms of the incremental interface ([start], [offer],
+     [handle], [reduce]). *)
+
+  (* By convention, acceptance is reported by returning a semantic value,
+     whereas rejection is reported by raising [Error]. *)
+
+  (* [loop] is polymorphic in ['a]. No cheating is involved in achieving this.
+     All of the cheating resides in the types assigned to [offer] and [handle]
+     above. *)
+
+  let rec loop : 'a . supplier -> 'a checkpoint -> 'a =
+    fun read checkpoint ->
+    match checkpoint with
+    | InputNeeded _ ->
+        (* The parser needs a token. Request one from the lexer,
+           and offer it to the parser, which will produce a new
+           checkpoint. Then, repeat. *)
+        let triple = read() in
+        let checkpoint = offer checkpoint triple in
+        loop read checkpoint
+    | Shifting _
+    | AboutToReduce _
+    | HandlingError _ ->
+        (* The parser has suspended itself, but does not need
+           new input. Just resume the parser. Then, repeat. *)
+        let checkpoint = resume checkpoint in
+        loop read checkpoint
+    | Accepted v ->
+        (* The parser has succeeded and produced a semantic value.
+           Return this semantic value to the user. *)
+        v
+    | Rejected ->
+        (* The parser rejects this input. Raise an exception. *)
+        raise Error
+
+  let entry (s : state) lexer lexbuf : semantic_value =
+    let initial = lexbuf.Lexing.lex_curr_p in
+    loop (lexer_lexbuf_to_supplier lexer lexbuf) (start s initial)
+
+  (* ------------------------------------------------------------------------ *)
+
+  (* [loop_handle] stops if it encounters an error, and at this point, invokes
+     its failure continuation, without letting Menhir do its own traditional
+     error-handling (which involves popping the stack, etc.). *)
+
+  let rec loop_handle succeed fail read checkpoint =
+    match checkpoint with
+    | InputNeeded _ ->
+        let triple = read() in
+        let checkpoint = offer checkpoint triple in
+        loop_handle succeed fail read checkpoint
+    | Shifting _
+    | AboutToReduce _ ->
+        let checkpoint = resume checkpoint in
+        loop_handle succeed fail read checkpoint
+    | HandlingError _
+    | Rejected ->
+        (* The parser has detected an error. Invoke the failure continuation. *)
+        fail checkpoint
+    | Accepted v ->
+        (* The parser has succeeded and produced a semantic value. Invoke the
+           success continuation. *)
+        succeed v
+
+  (* ------------------------------------------------------------------------ *)
+
+  (* [loop_handle_undo] is analogous to [loop_handle], except it passes a pair
+     of checkpoints to the failure continuation.
+
+     The first (and oldest) checkpoint is the last [InputNeeded] checkpoint
+     that was encountered before the error was detected. The second (and
+     newest) checkpoint is where the error was detected, as in [loop_handle].
+     Going back to the first checkpoint can be thought of as undoing any
+     reductions that were performed after seeing the problematic token. (These
+     reductions must be default reductions or spurious reductions.) *)
+
+  let rec loop_handle_undo succeed fail read (inputneeded, checkpoint) =
+    match checkpoint with
+    | InputNeeded _ ->
+        (* Update the last recorded [InputNeeded] checkpoint. *)
+        let inputneeded = checkpoint in
+        let triple = read() in
+        let checkpoint = offer checkpoint triple in
+        loop_handle_undo succeed fail read (inputneeded, checkpoint)
+    | Shifting _
+    | AboutToReduce _ ->
+        let checkpoint = resume checkpoint in
+        loop_handle_undo succeed fail read (inputneeded, checkpoint)
+    | HandlingError _
+    | Rejected ->
+        fail inputneeded checkpoint
+    | Accepted v ->
+        succeed v
+
+  (* For simplicity, we publish a version of [loop_handle_undo] that takes a
+     single checkpoint as an argument, instead of a pair of checkpoints. We
+     check that the argument is [InputNeeded _], and duplicate it. *)
+
+  (* The parser cannot accept or reject before it asks for the very first
+     character of input. (Indeed, we statically reject a symbol that
+     generates the empty language or the singleton language {epsilon}.)
+     So, the [start] checkpoint must match [InputNeeded _]. Hence, it is
+     permitted to call [loop_handle_undo] with a [start] checkpoint. *)
+
+  let loop_handle_undo succeed fail read checkpoint =
+    assert (match checkpoint with InputNeeded _ -> true | _ -> false);
+    loop_handle_undo succeed fail read (checkpoint, checkpoint)
+
+  (* ------------------------------------------------------------------------ *)
+
+  let rec shifts checkpoint =
+    match checkpoint with
+    | Shifting (env, _, _) ->
+        (* The parser is about to shift, which means it is willing to
+           consume the terminal symbol that we have fed it. Return the
+           state just before this transition. *)
+        Some env
+    | AboutToReduce _ ->
+        (* The parser wishes to reduce. Just follow. *)
+        shifts (resume checkpoint)
+    | HandlingError _ ->
+        (* The parser fails, which means it rejects the terminal symbol
+           that we have fed it. *)
+        None
+    | InputNeeded _
+    | Accepted _
+    | Rejected ->
+        (* None of these cases can arise. Indeed, after a token is submitted
+           to it, the parser must shift, reduce, or signal an error, before
+           it can request another token or terminate. *)
+        assert false
+
+  let acceptable checkpoint token pos =
+    let triple = (token, pos, pos) in
+    let checkpoint = offer checkpoint triple in
+    match shifts checkpoint with
+    | None      -> false
+    | Some _env -> true
+
+  (* ------------------------------------------------------------------------ *)
+
+  (* The type ['a lr1state] describes the (non-initial) states of the LR(1)
+     automaton. The index ['a] represents the type of the semantic value
+     associated with the state's incoming symbol. *)
+
+  (* The type ['a lr1state] is defined as an alias for [state], which itself
+     is usually defined as [int] (see [TableInterpreter]). So, ['a lr1state]
+     is technically a phantom type, but should really be thought of as a GADT
+     whose data constructors happen to be represented as integers. It is
+     presented to the user as an abstract type (see [IncrementalEngine]). *)
+
+  type 'a lr1state =
+      state
+
+  (* ------------------------------------------------------------------------ *)
+
+  (* Stack inspection. *)
+
+  (* We offer a read-only view of the parser's state as a stream of elements.
+     Each element contains a pair of a (non-initial) state and a semantic
+     value associated with (the incoming symbol of) this state. Note that the
+     type [element] is an existential type. *)
+
+  (* As of 2017/03/31, the type [stack] and the function [stack] are DEPRECATED.
+     If desired, they could now be implemented outside Menhir, by relying on
+     the functions [top] and [pop]. *)
+
+  type element =
+    | Element: 'a lr1state * 'a * position * position -> element
+
+  open General
+
+  type stack =
+    element stream
+
+  (* If [current] is the current state and [cell] is the top stack cell,
+     then [stack cell current] is a view of the parser's state as a stream
+     of elements. *)
+
+  let rec stack cell current : element stream =
+    lazy (
+      (* The stack is empty iff the top stack cell is its own successor. In
+         that case, the current state [current] should be an initial state
+         (which has no incoming symbol).
+         We do not allow the user to inspect this state. *)
+      let next = cell.next in
+      if next == cell then
+        Nil
+      else
+        (* Construct an element containing the current state [current] as well
+           as the semantic value contained in the top stack cell. This semantic
+           value is associated with the incoming symbol of this state, so it
+           makes sense to pair them together. The state has type ['a state] and
+           the semantic value has type ['a], for some type ['a]. Here, the OCaml
+           type-checker thinks ['a] is [semantic_value] and considers this code
+           well-typed. Outside, we will use magic to provide the user with a way
+           of inspecting states and recovering the value of ['a]. *)
+        let element = Element (
+          current,
+          cell.semv,
+          cell.startp,
+          cell.endp
+        ) in
+        Cons (element, stack next cell.state)
+    )
+
+  let stack env : element stream =
+    stack env.stack env.current
+
+  (* As explained above, the function [top] allows access to the top stack
+     element only if the stack is nonempty, i.e., only if the current state
+     is not an initial state. *)
+
+  let top env : element option =
+    let cell = env.stack in
+    let next = cell.next in
+    if next == cell then
+      None
+    else
+      Some (Element (env.current, cell.semv, cell.startp, cell.endp))
+
+  (* [equal] compares the stacks for physical equality, and compares the
+     current states via their numbers (this seems cleaner than using OCaml's
+     polymorphic equality). *)
+
+  (* The two fields that are not compared by [equal], namely [error] and
+     [triple], are overwritten by the function [discard], which handles
+     [InputNeeded] checkpoints. Thus, if [equal env1 env2] holds, then the
+     checkpoints [input_needed env1] and [input_needed env2] are
+     equivalent: they lead the parser to behave in the same way. *)
+
+  let equal env1 env2 =
+    env1.stack == env2.stack &&
+    number env1.current = number env2.current
+
+  let current_state_number env =
+    number env.current
+
+  (* ------------------------------------------------------------------------ *)
+
+  (* Access to the position of the lookahead token. *)
+
+  let positions { triple = (_, startp, endp); _ } =
+    startp, endp
+
+  (* ------------------------------------------------------------------------ *)
+
+  (* Access to information about default reductions. *)
+
+  (* This can be a function of states, or a function of environments.
+     We offer both. *)
+
+  (* Instead of a Boolean result, we could return a [production option].
+     However, we would have to explicitly test whether [prod] is a start
+     production, and in that case, return [None], I suppose. Indeed, we
+     have decided not to expose the start productions. *)
+
+  let state_has_default_reduction (state : _ lr1state) : bool =
+    T.default_reduction state
+      (fun _env _prod -> true)
+      (fun _env -> false)
+      ()
+
+  let env_has_default_reduction env =
+    state_has_default_reduction env.current
+
+  (* ------------------------------------------------------------------------ *)
+
+  (* The following functions work at the level of environments (as opposed to
+     checkpoints). The function [pop] causes the automaton to go back into the
+     past, pretending that the last input symbol has never been read. The
+     function [force_reduction] causes the automaton to re-interpret the past,
+     by recognizing the right-hand side of a production and reducing this
+     production. The function [feed] causes the automaton to progress into the
+     future by pretending that a (terminal or nonterminal) symbol has been
+     read. *)
+
+  (* The function [feed] would ideally be defined here. However, for this
+     function to be type-safe, the GADT ['a symbol] is needed. For this
+     reason, we move its definition to [InspectionTableInterpreter], where
+     the inspection API is available. *)
+
+  (* [pop] pops one stack cell. It cannot go wrong. *)
+
+  let pop (env : 'a env) : 'a env option =
+    let cell = env.stack in
+    let next = cell.next in
+    if next == cell then
+      (* The stack is empty. *)
+      None
+    else
+      (* The stack is nonempty. Pop off one cell. *)
+      Some { env with stack = next; current = cell.state }
+
+  (* [force_reduction] is analogous to [reduce], except that it does not
+     continue by calling [run env] or [initiate env]. Instead, it returns
+     [env] to the user. *)
+
+  (* [force_reduction] is dangerous insofar as it executes a semantic action.
+     This semantic action could have side effects: nontermination, state,
+     exceptions, input/output, etc. *)
+
+  let force_reduction prod (env : 'a env) : 'a env =
+    (* Check if this reduction is permitted. This check is REALLY important.
+       The stack must have the correct shape: that is, it must be sufficiently
+       high, and must contain semantic values of appropriate types, otherwise
+       the semantic action will crash and burn. *)
+    (* We currently check whether the current state is WILLING to reduce this
+       production (i.e., there is a reduction action in the action table row
+       associated with this state), whereas it would be more liberal to check
+       whether this state is CAPABLE of reducing this production (i.e., the
+       stack has an appropriate shape). We currently have no means of
+       performing such a check. *)
+    if not (T.may_reduce env.current prod) then
+      invalid_arg "force_reduction: this reduction is not permitted in this state"
+    else begin
+      (* We do not expose the start productions to the user, so this cannot be
+         a start production. Hence, it has a semantic action. *)
+      assert (not (T.is_start prod));
+      (* Invoke the semantic action. *)
+      let stack = T.semantic_action prod env in
+      (* Perform a goto transition. *)
+      let current = T.goto_prod stack.state prod in
+      { env with stack; current }
+    end
+
+  (* The environment manipulation functions -- [pop] and [force_reduction]
+     above, plus [feed] -- manipulate the automaton's stack and current state,
+     but do not affect the automaton's lookahead symbol. When the function
+     [input_needed] is used to go back from an environment to a checkpoint
+     (and therefore, resume normal parsing), the lookahead symbol is clobbered
+     anyway, since the only action that the user can take is to call [offer].
+     So far, so good. One problem, though, is that this call to [offer] may
+     well place the automaton in a configuration of a state [s] and a
+     lookahead symbol [t] that is normally unreachable. Also, perhaps the
+     state [s] is a state where an input symbol normally is never demanded, so
+     this [InputNeeded] checkpoint is fishy. There does not seem to be a deep
+     problem here, but, when programming an error recovery strategy, one
+     should pay some attention to this issue. Ideally, perhaps, one should use
+     [input_needed] only in a state [s] where an input symbol is normally
+     demanded, that is, a state [s] whose incoming symbol is a terminal symbol
+     and which does not have a default reduction on [#]. *)
+
+  let input_needed (env : 'a env) : 'a checkpoint =
+    InputNeeded env
+
+  (* The following functions are compositions of [top] and [pop]. *)
+
+  let rec pop_many i env =
+    if i = 0 then
+      Some env
+    else match pop env with
+    | None ->
+        None
+    | Some env ->
+        pop_many (i - 1) env
+
+  let get i env =
+    match pop_many i env with
+    | None ->
+        None
+    | Some env ->
+        top env
+
+end
+end
+module ErrorReports = struct
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* -------------------------------------------------------------------------- *)
+
+(* A two-place buffer stores zero, one, or two elements. *)
+
+type 'a content =
+| Zero
+| One of 'a
+| Two of 'a * (* most recent: *) 'a
+
+type 'a buffer =
+  'a content ref
+
+(* [update buffer x] pushes [x] into [buffer], causing the buffer to slide. *)
+
+let update buffer x =
+  buffer :=
+    match !buffer, x with
+    | Zero, _ ->
+        One x
+    | One x1, x2
+    | Two (_, x1), x2 ->
+        Two (x1, x2)
+
+(* [show f buffer] prints the contents of the buffer. The function [f] is
+   used to print an element. *)
+
+let show f buffer : string =
+  match !buffer with
+  | Zero ->
+      (* The buffer cannot be empty. If we have read no tokens,
+         we cannot have detected a syntax error. *)
+      assert false
+  | One invalid ->
+      (* It is unlikely, but possible, that we have read just one token. *)
+      Printf.sprintf "before '%s'" (f invalid)
+  | Two (valid, invalid) ->
+      (* In the most likely case, we have read two tokens. *)
+      Printf.sprintf "after '%s' and before '%s'" (f valid) (f invalid)
+
+(* [last buffer] returns the last element of the buffer (that is, the invalid
+   token). *)
+
+let last buffer =
+  match !buffer with
+  | Zero ->
+      (* The buffer cannot be empty. If we have read no tokens,
+         we cannot have detected a syntax error. *)
+      assert false
+  | One invalid
+  | Two (_, invalid) ->
+      invalid
+
+(* [wrap buffer lexer] *)
+
+open Lexing
+
+let wrap lexer =
+  let buffer = ref Zero in
+  buffer,
+  fun lexbuf ->
+    let token = lexer lexbuf in
+    update buffer (lexbuf.lex_start_p, lexbuf.lex_curr_p);
+    token
+
+(* -------------------------------------------------------------------------- *)
+end
+module Printers = struct
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+module Make
+  (I : IncrementalEngine.EVERYTHING)
+  (User : sig
+    val print: string -> unit
+    val print_symbol: I.xsymbol -> unit
+    val print_element: (I.element -> unit) option
+  end)
+= struct
+
+  let arrow = " -> "
+  let dot = "."
+  let space = " "
+  let newline = "\n"
+
+  open User
+  open I
+
+  (* Printing a list of symbols. An optional dot is printed at offset
+     [i] into the list [symbols], if this offset lies between [0] and
+     the length of the list (included). *)
+
+  let rec print_symbols i symbols =
+    if i = 0 then begin
+      print dot;
+      print space;
+      print_symbols (-1) symbols
+    end
+    else begin
+      match symbols with
+      | [] ->
+          ()
+      | symbol :: symbols ->
+          print_symbol symbol;
+          print space;
+          print_symbols (i - 1) symbols
+    end
+
+  (* Printing an element as a symbol. *)
+
+  let print_element_as_symbol element =
+    match element with
+    | Element (s, _, _, _) ->
+        print_symbol (X (incoming_symbol s))
+
+  (* Some of the functions that follow need an element printer. They use
+     [print_element] if provided by the user; otherwise they use
+     [print_element_as_symbol]. *)
+
+  let print_element =
+    match print_element with
+    | Some print_element ->
+        print_element
+    | None ->
+        print_element_as_symbol
+
+  (* Printing a stack as a list of symbols. Stack bottom on the left,
+     stack top on the right. *)
+
+  let rec print_stack env =
+    match top env, pop env with
+    | Some element, Some env ->
+        print_stack env;
+        print space;
+        print_element element
+    | _, _ ->
+        ()
+
+  let print_stack env =
+    print_stack env;
+    print newline
+
+  (* Printing an item. *)
+
+  let print_item (prod, i) =
+    print_symbol (lhs prod);
+    print arrow;
+    print_symbols i (rhs prod);
+    print newline
+
+  (* Printing a list of symbols (public version). *)
+
+  let print_symbols symbols =
+    print_symbols (-1) symbols
+
+  (* Printing a production (without a dot). *)
+
+  let print_production prod =
+    print_item (prod, -1)
+
+  (* Printing the current LR(1) state. *)
+
+  let print_current_state env =
+    print "Current LR(1) state: ";
+    match top env with
+    | None ->
+        print ""; (* TEMPORARY unsatisfactory *)
+        print newline
+    | Some (Element (current, _, _, _)) ->
+        print (string_of_int (number current));
+        print newline;
+        List.iter print_item (items current)
+
+  let print_env env =
+    print_stack env;
+    print_current_state env;
+    print newline
+
+end
+end
+module InfiniteArray = struct
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(** This module implements infinite arrays, that is, arrays that grow
+    transparently upon demand. *)
+
+type 'a t = {
+    default: 'a;
+    mutable table: 'a array;
+    mutable extent: int; (* the index of the greatest [set] ever, plus one *)
+  }
+
+let default_size =
+  16384 (* must be non-zero *)
+
+let make x = {
+  default = x;
+  table = Array.make default_size x;
+  extent = 0;
+}
+
+let rec new_length length i =
+  if i < length then
+    length
+  else
+    new_length (2 * length) i
+
+let ensure a i =
+  assert (0 <= i);
+  let table = a.table in
+  let length = Array.length table in
+  if i >= length then begin
+    let table' = Array.make (new_length (2 * length) i) a.default in
+    Array.blit table 0 table' 0 length;
+    a.table <- table'
+  end
+
+let get a i =
+  ensure a i;
+  Array.unsafe_get a.table (i)
+
+let set a i x =
+  ensure a i;
+  Array.unsafe_set a.table (i) x;
+  if a.extent <= i then
+    a.extent <- i + 1
+
+let extent a =
+  a.extent
+
+let domain a =
+  Array.sub a.table 0 a.extent
+
+end
+module PackedIntArray = struct
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* A packed integer array is represented as a pair of an integer [k] and
+   a string [s]. The integer [k] is the number of bits per integer that we
+   use. The string [s] is just an array of bits, which is read in 8-bit
+   chunks. *)
+
+(* The ocaml programming language treats string literals and array literals
+   in slightly different ways: the former are statically allocated, while
+   the latter are dynamically allocated. (This is rather arbitrary.) In the
+   context of Menhir's table-based back-end, where compact, immutable
+   integer arrays are needed, ocaml strings are preferable to ocaml arrays. *)
+
+type t =
+  int * string
+
+(* The magnitude [k] of an integer [v] is the number of bits required
+   to represent [v]. It is rounded up to the nearest power of two, so
+   that [k] divides [Sys.word_size]. *)
+
+let magnitude (v : int) =
+  if v < 0 then
+    Sys.word_size
+  else
+    let rec check k max = (* [max] equals [2^k] *)
+      if (max <= 0) || (v < max) then
+        k
+          (* if [max] just overflew, then [v] requires a full ocaml
+             integer, and [k] is the number of bits in an ocaml integer
+             plus one, that is, [Sys.word_size]. *)
+      else
+        check (2 * k) (max * max)
+    in
+    check 1 2
+
+(* [pack a] turns an array of integers into a packed integer array. *)
+
+(* Because the sign bit is the most significant bit, the magnitude of
+   any negative number is the word size. In other words, [pack] does
+   not achieve any space savings as soon as [a] contains any negative
+   numbers, even if they are ``small''. *)
+
+let pack (a : int array) : t =
+
+  let m = Array.length a in
+
+  (* Compute the maximum magnitude of the array elements. This tells
+     us how many bits per element we are going to use. *)
+
+  let k =
+    Array.fold_left (fun k v ->
+      max k (magnitude v)
+    ) 1 a
+  in
+
+  (* Because access to ocaml strings is performed on an 8-bit basis,
+     two cases arise. If [k] is less than 8, then we can pack multiple
+     array entries into a single character. If [k] is greater than 8,
+     then we must use multiple characters to represent a single array
+     entry. *)
+
+  if k <= 8 then begin
+
+    (* [w] is the number of array entries that we pack in a character. *)
+
+    assert (8 mod k = 0);
+    let w = 8 / k in
+
+    (* [n] is the length of the string that we allocate. *)
+
+    let n =
+      if m mod w = 0 then
+        m / w
+      else
+        m / w + 1
+    in
+
+    let s =
+      Bytes.create n
+    in
+
+    (* Define a reader for the source array. The reader might run off
+       the end if [w] does not divide [m]. *)
+
+    let i = ref 0 in
+    let next () =
+      let ii = !i in
+      if ii = m then
+        0 (* ran off the end, pad with zeroes *)
+      else
+        let v = a.(ii) in
+        i := ii + 1;
+        v
+    in
+
+    (* Fill up the string. *)
+
+    for j = 0 to n - 1 do
+      let c = ref 0 in
+      for _x = 1 to w do
+        c := (!c lsl k) lor next()
+      done;
+      Bytes.set s j (Char.chr !c)
+    done;
+
+    (* Done. *)
+
+    k, Bytes.unsafe_to_string s
+
+  end
+  else begin (* k > 8 *)
+
+    (* [w] is the number of characters that we use to encode an array entry. *)
+
+    assert (k mod 8 = 0);
+    let w = k / 8 in
+
+    (* [n] is the length of the string that we allocate. *)
+
+    let n =
+      m * w
+    in
+
+    let s =
+      Bytes.create n
+    in
+
+    (* Fill up the string. *)
+
+    for i = 0 to m - 1 do
+      let v = ref a.(i) in
+      for x = 1 to w do
+        Bytes.set s ((i + 1) * w - x) (Char.chr (!v land 255));
+        v := !v lsr 8
+      done
+    done;
+
+    (* Done. *)
+
+    k, Bytes.unsafe_to_string s
+
+  end
+
+(* Access to a string. *)
+
+let read (s : string) (i : int) : int =
+  Char.code (String.unsafe_get s i)
+
+(* [get1 t i] returns the integer stored in the packed array [t] at index [i].
+   It assumes (and does not check) that the array's bit width is [1]. The
+   parameter [t] is just a string. *)
+
+let get1 (s : string) (i : int) : int =
+  let c = read s (i lsr 3) in
+  let c = c lsr ((lnot i) land 0b111) in
+  let c = c land 0b1 in
+  c
+
+(* [get t i] returns the integer stored in the packed array [t] at index [i]. *)
+
+(* Together, [pack] and [get] satisfy the following property: if the index [i]
+   is within bounds, then [get (pack a) i] equals [a.(i)]. *)
+
+let get ((k, s) : t) (i : int) : int =
+  match k with
+  | 1 ->
+      get1 s i
+  | 2 ->
+      let c = read s (i lsr 2) in
+      let c = c lsr (2 * ((lnot i) land 0b11)) in
+      let c = c land 0b11 in
+      c
+  | 4 ->
+      let c = read s (i lsr 1) in
+      let c = c lsr (4 * ((lnot i) land 0b1)) in
+      let c = c land 0b1111 in
+      c
+  | 8 ->
+      read s i
+  | 16 ->
+      let j = 2 * i in
+      (read s j) lsl 8 + read s (j + 1)
+  | _ ->
+      assert (k = 32); (* 64 bits unlikely, not supported *)
+      let j = 4 * i in
+      (((read s j lsl 8) + read s (j + 1)) lsl 8 + read s (j + 2)) lsl 8 + read s (j + 3)
+
+(* [unflatten1 (n, data) i j] accesses the two-dimensional bitmap
+   represented by [(n, data)] at indices [i] and [j]. The integer
+   [n] is the width of the bitmap; the string [data] is the second
+   component of the packed array obtained by encoding the table as
+   a one-dimensional array. *)
+
+let unflatten1 (n, data) i j =
+   get1 data (n * i + j)
+
+end
+module RowDisplacement = struct
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* This module compresses a two-dimensional table, where some values
+   are considered insignificant, via row displacement. *)
+
+(* This idea reportedly appears in Aho and Ullman's ``Principles
+   of Compiler Design'' (1977). It is evaluated in Tarjan and Yao's
+   ``Storing a Sparse Table'' (1979) and in Dencker, Dürre, and Heuft's
+   ``Optimization of Parser Tables for Portable Compilers'' (1984). *)
+
+(* A compressed table is represented as a pair of arrays. The
+   displacement array is an array of offsets into the data array. *)
+
+type 'a table =
+    int array * (* displacement *)
+     'a array   (* data *)
+
+(* In a natural version of this algorithm, displacements would be greater
+   than (or equal to) [-n]. However, in the particular setting of Menhir,
+   both arrays are intended to be compressed with [PackedIntArray], which
+   does not efficiently support negative numbers. For this reason, we are
+   careful not to produce negative displacements. *)
+
+(* In order to avoid producing negative displacements, we simply use the
+   least significant bit as the sign bit. This is implemented by [encode]
+   and [decode] below. *)
+
+(* One could also think, say, of adding [n] to every displacement, so as
+   to ensure that all displacements are nonnegative. This would work, but
+   would require [n] to be published, for use by the decoder. *)
+
+let encode (displacement : int) : int =
+  if displacement >= 0 then
+    displacement lsl 1
+  else
+    (-displacement) lsl 1 + 1
+
+let decode (displacement : int) : int =
+  if displacement land 1 = 0 then
+    displacement lsr 1
+  else
+    -(displacement lsr 1)
+
+(* It is reasonable to assume that, as matrices grow large, their
+   density becomes low, i.e., they have many insignificant entries.
+   As a result, it is important to work with a sparse data structure
+   for rows. We internally represent a row as a list of its
+   significant entries, where each entry is a pair of a [j] index and
+   an element. *)
+
+type 'a row =
+    (int * 'a) list
+
+(* [compress equal insignificant dummy m n t] turns the two-dimensional table
+   [t] into a compressed table. The parameter [equal] is equality of data
+   values. The parameter [wildcard] tells which data values are insignificant,
+   and can thus be overwritten with other values. The parameter [dummy] is
+   used to fill holes in the data array. [m] and [n] are the integer
+   dimensions of the table [t]. *)
+
+let compress
+    (equal : 'a -> 'a -> bool)
+    (insignificant : 'a -> bool)
+    (dummy : 'a)
+    (m : int) (n : int)
+    (t : 'a array array)
+    : 'a table =
+
+  (* Be defensive. *)
+
+  assert (Array.length t = m);
+  assert begin
+    for i = 0 to m - 1 do
+      assert (Array.length t.(i) = n)
+    done;
+    true
+  end;
+
+  (* This turns a row-as-array into a row-as-sparse-list. The row is
+     accompanied by its index [i] and by its rank (the number of its
+     significant entries, that is, the length of the row-as-a-list. *)
+
+  let sparse (i : int) (line : 'a array) : int * int * 'a row (* index, rank, row *) =
+
+    let rec loop (j : int) (rank : int) (row : 'a row) =
+      if j < 0 then
+        i, rank, row
+      else
+        let x = line.(j) in
+        if insignificant x then
+          loop (j - 1) rank row
+        else
+          loop (j - 1) (1 + rank) ((j, x) :: row)
+    in
+
+    loop (n - 1) 0 []
+
+  in
+
+  (* Construct an array of all rows, together with their index and rank. *)
+
+  let rows : (int * int * 'a row) array = (* index, rank, row *)
+    Array.mapi sparse t
+  in
+
+  (* Sort this array by decreasing rank. This does not have any impact
+     on correctness, but reportedly improves compression. The
+     intuitive idea is that rows with few significant elements are
+     easy to fit, so they should be inserted last, after the problem
+     has become quite constrained by fitting the heavier rows. This
+     heuristic is attributed to Ziegler. *)
+
+  Array.fast_sort (fun (_, rank1, _) (_, rank2, _) ->
+    compare rank2 rank1
+  ) rows;
+
+  (* Allocate a one-dimensional array of displacements. *)
+
+  let displacement : int array =
+    Array.make m 0
+  in
+
+  (* Allocate a one-dimensional, infinite array of values. Indices
+     into this array are written [k]. *)
+
+  let data : 'a InfiniteArray.t =
+    InfiniteArray.make dummy
+  in
+
+  (* Determine whether [row] fits at offset [k] within the current [data]
+     array, up to extension of this array. *)
+
+  (* Note that this check always succeeds when [k] equals the length of
+     the [data] array. Indeed, the loop is then skipped. This property
+     guarantees the termination of the recursive function [fit] below. *)
+
+  let fits k (row : 'a row) : bool =
+
+    let d = InfiniteArray.extent data in
+
+    let rec loop = function
+      | [] ->
+          true
+      | (j, x) :: row ->
+
+          (* [x] is a significant element. *)
+
+          (* By hypothesis, [k + j] is nonnegative. If it is greater than or
+             equal to the current length of the data array, stop -- the row
+             fits. *)
+
+          assert (k + j >= 0);
+
+          if k + j >= d then
+            true
+
+          (* We now know that [k + j] is within bounds of the data
+             array. Check whether it is compatible with the element [y] found
+             there. If it is, continue. If it isn't, stop -- the row does not
+             fit. *)
+
+          else
+            let y = InfiniteArray.get data (k + j) in
+            if insignificant y || equal x y then
+              loop row
+            else
+              false
+
+    in
+    loop row
+
+  in
+
+  (* Find the leftmost position where a row fits. *)
+
+  (* If the leftmost significant element in this row is at offset [j],
+     then we can hope to fit as far left as [-j] -- so this element
+     lands at offset [0] in the data array. *)
+
+  (* Note that displacements may be negative. This means that, for
+     insignificant elements, accesses to the data array could fail: they could
+     be out of bounds, either towards the left or towards the right. This is
+     not a problem, as long as [get] is invoked only at significant
+     elements. *)
+
+  let rec fit k row : int =
+    if fits k row then
+      k
+    else
+      fit (k + 1) row
+  in
+
+  let fit row =
+    match row with
+    | [] ->
+        0 (* irrelevant *)
+    | (j, _) :: _ ->
+        fit (-j) row
+  in
+
+  (* Write [row] at (compatible) offset [k]. *)
+
+  let rec write k = function
+    | [] ->
+        ()
+    | (j, x) :: row ->
+        InfiniteArray.set data (k + j) x;
+        write k row
+  in
+
+  (* Iterate over the sorted array of rows. Fit and write each row at
+     the leftmost compatible offset. Update the displacement table. *)
+
+  Array.iter (fun (i, _, row) ->
+    let k = fit row in (* if [row] has leading insignificant elements, then [k] can be negative *)
+    write k row;
+    displacement.(i) <- encode k
+  ) rows;
+
+  (* Return the compressed tables. *)
+
+  displacement, InfiniteArray.domain data
+
+(* [get ct i j] returns the value found at indices [i] and [j] in the
+   compressed table [ct]. This function call is permitted only if the
+   value found at indices [i] and [j] in the original table is
+   significant -- otherwise, it could fail abruptly. *)
+
+(* Together, [compress] and [get] have the property that, if the value
+   found at indices [i] and [j] in an uncompressed table [t] is
+   significant, then [get (compress t) i j] is equal to that value. *)
+
+let get (displacement, data) i j =
+  assert (0 <= i && i < Array.length displacement);
+  let k = decode displacement.(i) in
+  assert (0 <= k + j && k + j < Array.length data);
+    (* failure of this assertion indicates an attempt to access an
+       insignificant element that happens to be mapped out of the bounds
+       of the [data] array. *)
+  data.(k + j)
+
+(* [getget] is a variant of [get] which only requires read access,
+   via accessors, to the two components of the table. *)
+
+let getget get_displacement get_data (displacement, data) i j =
+  let k = decode (get_displacement displacement i) in
+  get_data data (k + j)
+end
+module LinearizedArray = struct
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* The [entry] array contains offsets into the [data] array. It has [n+1]
+   elements if the original (unencoded) array has [n] elements. The value
+   of [entry.(n)] is the length of the [data] array. This convention is
+   natural and allows avoiding a special case. *)
+
+type 'a t =
+  (* data: *)   'a array *
+  (* entry: *) int array
+
+let make (a : 'a array array) : 'a t =
+  let n = Array.length a in
+  (* Build the entry array. *)
+  let size = ref 0 in
+  let entry = Array.init (n + 1) (fun i ->
+    let s = !size in
+    if i < n then
+      size := s + Array.length a.(i);
+    s
+  ) in
+  assert (entry.(n) = !size);
+  (* Build the data array. *)
+  let i = ref 0
+  and j = ref 0 in
+  let data = Array.init !size (fun _ ->
+    while !j = Array.length a.(!i) do
+      i := !i + 1;
+      j := 0;
+    done;
+    let x = a.(!i).(!j) in
+    j := !j + 1;
+    x
+  ) in
+  data, entry
+
+let length ((_, entry) : 'a t) : int =
+  Array.length entry
+
+let row_length ((_, entry) : 'a t) i : int =
+  entry.(i + 1) - entry.(i)
+
+let row_length_via get_entry i =
+  get_entry (i + 1) - get_entry i
+
+let read ((data, entry) as la : 'a t) i j : 'a =
+  assert (0 <= j && j < row_length la i);
+  data.(entry.(i) + j)
+
+let read_via get_data get_entry i j =
+  assert (0 <= j && j < row_length_via get_entry i);
+  get_data (get_entry i + j)
+
+let write ((data, entry) as la : 'a t) i j (v : 'a) : unit =
+  assert (0 <= j && j < row_length la i);
+  data.(entry.(i) + j) <- v
+
+let rec read_interval_via get_data i j =
+  if i = j then
+    []
+  else
+    get_data i :: read_interval_via get_data (i + 1) j
+
+let read_row_via get_data get_entry i =
+  read_interval_via get_data (get_entry i) (get_entry (i + 1))
+
+let read_row ((data, entry) : 'a t) i : 'a list =
+  read_row_via (Array.get data) (Array.get entry) i
+
+end
+module TableFormat = struct
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* This signature defines the format of the parse tables. It is used as
+   an argument to [TableInterpreter.Make]. *)
+
+module type TABLES = sig
+
+  (* This is the parser's type of tokens. *)
+
+  type token
+
+  (* This maps a token to its internal (generation-time) integer code. *)
+
+  val token2terminal: token -> int
+
+  (* This is the integer code for the error pseudo-token. *)
+
+  val error_terminal: int
+
+  (* This maps a token to its semantic value. *)
+
+  val token2value: token -> Obj.t
+
+  (* Traditionally, an LR automaton is described by two tables, namely, an
+     action table and a goto table. See, for instance, the Dragon book.
+
+     The action table is a two-dimensional matrix that maps a state and a
+     lookahead token to an action. An action is one of: shift to a certain
+     state, reduce a certain production, accept, or fail.
+
+     The goto table is a two-dimensional matrix that maps a state and a
+     non-terminal symbol to either a state or undefined. By construction, this
+     table is sparse: its undefined entries are never looked up. A compression
+     technique is free to overlap them with other entries.
+
+     In Menhir, things are slightly different. If a state has a default
+     reduction on token [#], then that reduction must be performed without
+     consulting the lookahead token. As a result, we must first determine
+     whether that is the case, before we can obtain a lookahead token and use it
+     as an index in the action table.
+
+     Thus, Menhir's tables are as follows.
+
+     A one-dimensional default reduction table maps a state to either ``no
+     default reduction'' (encoded as: 0) or ``by default, reduce prod''
+     (encoded as: 1 + prod). The action table is looked up only when there
+     is no default reduction. *)
+
+  val default_reduction: PackedIntArray.t
+
+  (* Menhir follows Dencker, Dürre and Heuft, who point out that, although the
+     action table is not sparse by nature (i.e., the error entries are
+     significant), it can be made sparse by first factoring out a binary error
+     matrix, then replacing the error entries in the action table with undefined
+     entries. Thus:
+
+     A two-dimensional error bitmap maps a state and a terminal to either
+     ``fail'' (encoded as: 0) or ``do not fail'' (encoded as: 1). The action
+     table, which is now sparse, is looked up only in the latter case. *)
+
+  (* The error bitmap is flattened into a one-dimensional table; its width is
+     recorded so as to allow indexing. The table is then compressed via
+     [PackedIntArray]. The bit width of the resulting packed array must be
+     [1], so it is not explicitly recorded. *)
+
+  (* The error bitmap does not contain a column for the [#] pseudo-terminal.
+     Thus, its width is [Terminal.n - 1]. We exploit the fact that the integer
+     code assigned to [#] is greatest: the fact that the right-most column
+     in the bitmap is missing does not affect the code for accessing it. *)
+
+  val error: int (* width of the bitmap *) * string (* second component of [PackedIntArray.t] *)
+
+  (* A two-dimensional action table maps a state and a terminal to one of
+     ``shift to state s and discard the current token'' (encoded as: s | 10),
+     ``shift to state s without discarding the current token'' (encoded as: s |
+     11), or ``reduce prod'' (encoded as: prod | 01). *)
+
+  (* The action table is first compressed via [RowDisplacement], then packed
+     via [PackedIntArray]. *)
+
+  (* Like the error bitmap, the action table does not contain a column for the
+     [#] pseudo-terminal. *)
+
+  val action: PackedIntArray.t * PackedIntArray.t
+
+  (* A one-dimensional lhs table maps a production to its left-hand side (a
+     non-terminal symbol). *)
+
+  val lhs: PackedIntArray.t
+
+  (* A two-dimensional goto table maps a state and a non-terminal symbol to
+     either undefined (encoded as: 0) or a new state s (encoded as: 1 + s). *)
+
+  (* The goto table is first compressed via [RowDisplacement], then packed
+     via [PackedIntArray]. *)
+
+  val goto: PackedIntArray.t * PackedIntArray.t
+
+  (* The number of start productions. A production [prod] is a start
+     production if and only if [prod < start] holds. This is also the
+     number of start symbols. A nonterminal symbol [nt] is a start
+     symbol if and only if [nt < start] holds. *)
+
+  val start: int
+
+  (* A one-dimensional semantic action table maps productions to semantic
+     actions. The calling convention for semantic actions is described in
+     [EngineTypes]. This table contains ONLY NON-START PRODUCTIONS, so the
+     indexing is off by [start]. Be careful. *)
+
+  val semantic_action: ((int, Obj.t, token) EngineTypes.env ->
+                        (int, Obj.t)        EngineTypes.stack) array
+
+  (* The parser defines its own [Error] exception. This exception can be
+     raised by semantic actions and caught by the engine, and raised by the
+     engine towards the final user. *)
+
+  exception Error
+
+  (* The parser indicates whether to generate a trace. Generating a
+     trace requires two extra tables, which respectively map a
+     terminal symbol and a production to a string. *)
+
+  val trace: (string array * string array) option
+
+end
+end
+module InspectionTableFormat = struct
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* This signature defines the format of the tables that are produced (in
+   addition to the tables described in [TableFormat]) when the command line
+   switch [--inspection] is enabled. It is used as an argument to
+   [InspectionTableInterpreter.Make]. *)
+
+module type TABLES = sig
+
+  (* The types of symbols. *)
+
+  include IncrementalEngine.SYMBOLS
+
+  (* The type ['a lr1state] describes an LR(1) state. The generated parser defines
+     it internally as [int]. *)
+
+  type 'a lr1state
+
+  (* Some of the tables that follow use encodings of (terminal and
+     nonterminal) symbols as integers. So, we need functions that
+     map the integer encoding of a symbol to its algebraic encoding. *)
+
+  val    terminal: int -> xsymbol
+  val nonterminal: int -> xsymbol
+
+  (* The left-hand side of every production already appears in the
+     signature [TableFormat.TABLES], so we need not repeat it here. *)
+
+  (* The right-hand side of every production. This a linearized array
+     of arrays of integers, whose [data] and [entry] components have
+     been packed. The encoding of symbols as integers in described in
+     [TableBackend]. *)
+
+  val rhs: PackedIntArray.t * PackedIntArray.t
+
+  (* A mapping of every (non-initial) state to its LR(0) core. *)
+
+  val lr0_core: PackedIntArray.t
+
+  (* A mapping of every LR(0) state to its set of LR(0) items. Each item is
+     represented in its packed form (see [Item]) as an integer. Thus the
+     mapping is an array of arrays of integers, which is linearized and
+     packed, like [rhs]. *)
+
+  val lr0_items: PackedIntArray.t * PackedIntArray.t
+
+  (* A mapping of every LR(0) state to its incoming symbol, if it has one. *)
+
+  val lr0_incoming: PackedIntArray.t
+
+  (* A table that tells which non-terminal symbols are nullable. *)
+
+  val nullable: string
+    (* This is a packed int array of bit width 1. It can be read
+       using [PackedIntArray.get1]. *)
+
+  (* A two-table dimensional table, indexed by a nonterminal symbol and
+     by a terminal symbol (other than [#]), encodes the FIRST sets. *)
+
+  val first: int (* width of the bitmap *) * string (* second component of [PackedIntArray.t] *)
+
+end
+
+end
+module InspectionTableInterpreter = struct
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* -------------------------------------------------------------------------- *)
+
+(* The type functor. *)
+
+module Symbols (T : sig
+
+  type 'a terminal
+  type 'a nonterminal
+
+end) = struct
+
+  open T
+
+  (* This should be the only place in the whole library (and generator!)
+     where these types are defined. *)
+
+  type 'a symbol =
+    | T : 'a terminal -> 'a symbol
+    | N : 'a nonterminal -> 'a symbol
+
+  type xsymbol =
+    | X : 'a symbol -> xsymbol
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* The code functor. *)
+
+module Make
+  (TT : TableFormat.TABLES)
+  (IT : InspectionTableFormat.TABLES
+        with type 'a lr1state = int)
+  (ET : EngineTypes.TABLE
+        with type terminal = int
+         and type nonterminal = int
+         and type semantic_value = Obj.t)
+  (E : sig
+     type 'a env = (ET.state, ET.semantic_value, ET.token) EngineTypes.env
+   end)
+= struct
+
+  (* Including [IT] is an easy way of inheriting the definitions of the types
+     [symbol] and [xsymbol]. *)
+
+  include IT
+
+  (* This auxiliary function decodes a packed linearized array, as created by
+     [TableBackend.linearize_and_marshal1]. Here, we read a row all at once. *)
+
+  let read_packed_linearized
+    (data, entry : PackedIntArray.t * PackedIntArray.t) (i : int) : int list
+  =
+    LinearizedArray.read_row_via
+      (PackedIntArray.get data)
+      (PackedIntArray.get entry)
+      i
+
+  (* This auxiliary function decodes a symbol. The encoding was done by
+     [encode_symbol] or [encode_symbol_option] in the table back-end. *)
+
+  let decode_symbol (symbol : int) : IT.xsymbol =
+    (* If [symbol] is 0, then we have no symbol. This could mean e.g.
+       that the function [incoming_symbol] has been applied to an
+       initial state. In principle, this cannot happen. *)
+    assert (symbol > 0);
+    (* The low-order bit distinguishes terminal and nonterminal symbols. *)
+    let kind = symbol land 1 in
+    let symbol = symbol lsr 1 in
+    if kind = 0 then
+      IT.terminal (symbol - 1)
+    else
+      IT.nonterminal symbol
+
+  (* These auxiliary functions convert a symbol to its integer code. For speed
+     and for convenience, we use an unsafe type cast. This relies on the fact
+     that the data constructors of the [terminal] and [nonterminal] GADTs are
+     declared in an order that reflects their internal code. In the case of
+     nonterminal symbols, we add [start] to account for the presence of the
+     start symbols. *)
+
+  let n2i (nt : 'a IT.nonterminal) : int =
+    let answer = TT.start + Obj.magic nt in
+    (* For safety, check that the above cast produced a correct result. *)
+    assert (IT.nonterminal answer = X (N nt));
+    answer
+
+  let t2i (t : 'a IT.terminal) : int =
+    let answer = Obj.magic t in
+    (* For safety, check that the above cast produced a correct result. *)
+    assert (IT.terminal answer = X (T t));
+    answer
+
+  (* Ordering functions. *)
+
+  let compare_terminals t1 t2 =
+    (* Subtraction is safe because overflow is impossible. *)
+    t2i t1 - t2i t2
+
+  let compare_nonterminals nt1 nt2 =
+    (* Subtraction is safe because overflow is impossible. *)
+    n2i nt1 - n2i nt2
+
+  let compare_symbols symbol1 symbol2 =
+    match symbol1, symbol2 with
+    | X (T _), X (N _) ->
+        -1
+    | X (N _), X (T _) ->
+        1
+    | X (T t1), X (T t2) ->
+        compare_terminals t1 t2
+    | X (N nt1), X (N nt2) ->
+        compare_nonterminals nt1 nt2
+
+  let compare_productions prod1 prod2 =
+    (* Subtraction is safe because overflow is impossible. *)
+    prod1 - prod2
+
+  let compare_items (prod1, index1) (prod2, index2) =
+    let c = compare_productions prod1 prod2 in
+    (* Subtraction is safe because overflow is impossible. *)
+    if c <> 0 then c else index1 - index2
+
+  (* The function [incoming_symbol] goes through the tables [IT.lr0_core] and
+     [IT.lr0_incoming]. This yields a representation of type [xsymbol], out of
+     which we strip the [X] quantifier, so as to get a naked symbol. This last
+     step is ill-typed and potentially dangerous. It is safe only because this
+     function is used at type ['a lr1state -> 'a symbol], which forces an
+     appropriate choice of ['a]. *)
+
+  let incoming_symbol (s : 'a IT.lr1state) : 'a IT.symbol =
+    let core = PackedIntArray.get IT.lr0_core s in
+    let symbol = decode_symbol (PackedIntArray.get IT.lr0_incoming core) in
+    match symbol with
+    | IT.X symbol ->
+        Obj.magic symbol
+
+  (* The function [lhs] reads the table [TT.lhs] and uses [IT.nonterminal]
+     to decode the symbol. *)
+
+  let lhs prod =
+    IT.nonterminal (PackedIntArray.get TT.lhs prod)
+
+  (* The function [rhs] reads the table [IT.rhs] and uses [decode_symbol]
+     to decode the symbol. *)
+
+  let rhs prod =
+    List.map decode_symbol (read_packed_linearized IT.rhs prod)
+
+  (* The function [items] maps the LR(1) state [s] to its LR(0) core,
+     then uses [core] as an index into the table [IT.lr0_items]. The
+     items are then decoded by the function [export] below, which is
+     essentially a copy of [Item.export]. *)
+
+  type item =
+      int * int
+
+  let export t : item =
+    (t lsr 7, t mod 128)
+
+  let items s =
+    (* Map [s] to its LR(0) core. *)
+    let core = PackedIntArray.get IT.lr0_core s in
+    (* Now use [core] to look up the table [IT.lr0_items]. *)
+    List.map export (read_packed_linearized IT.lr0_items core)
+
+  (* The function [nullable] maps the nonterminal symbol [nt] to its
+     integer code, which it uses to look up the array [IT.nullable].
+     This yields 0 or 1, which we map back to a Boolean result. *)
+
+  let decode_bool i =
+    assert (i = 0 || i = 1);
+    i = 1
+
+  let nullable nt =
+    decode_bool (PackedIntArray.get1 IT.nullable (n2i nt))
+
+  (* The function [first] maps the symbols [nt] and [t] to their integer
+     codes, which it uses to look up the matrix [IT.first]. *)
+
+  let first nt t =
+    decode_bool (PackedIntArray.unflatten1 IT.first (n2i nt) (t2i t))
+
+  let xfirst symbol t =
+    match symbol with
+    | X (T t') ->
+        compare_terminals t t' = 0
+    | X (N nt) ->
+        first nt t
+
+  (* The function [foreach_terminal] exploits the fact that the
+     first component of [TT.error] is [Terminal.n - 1], i.e., the
+     number of terminal symbols, including [error] but not [#]. *)
+
+  let rec foldij i j f accu =
+    if i = j then
+      accu
+    else
+      foldij (i + 1) j f (f i accu)
+
+  let foreach_terminal f accu =
+    let n, _ = TT.error in
+    foldij 0 n (fun i accu ->
+      f (IT.terminal i) accu
+    ) accu
+
+  let foreach_terminal_but_error f accu =
+    let n, _ = TT.error in
+    foldij 0 n (fun i accu ->
+      if i = TT.error_terminal then
+        accu
+      else
+        f (IT.terminal i) accu
+    ) accu
+
+  (* ------------------------------------------------------------------------ *)
+
+  (* The following is the implementation of the function [feed]. This function
+     is logically part of the LR engine, so it would be nice if it were placed
+     in the module [Engine], but it must be placed here because, to ensure
+     type safety, its arguments must be a symbol of type ['a symbol] and a
+     semantic value of type ['a]. The type ['a symbol] is not available in
+     [Engine]. It is available here. *)
+
+  open EngineTypes
+  open ET
+  open E
+
+  (* [feed] fails if the current state does not have an outgoing transition
+     labeled with the desired symbol. This check is carried out at runtime. *)
+
+  let feed_failure () =
+    invalid_arg "feed: outgoing transition does not exist"
+
+  (* Feeding a nonterminal symbol [nt]. Here, [nt] has type [nonterminal],
+     which is a synonym for [int], and [semv] has type [semantic_value],
+     which is a synonym for [Obj.t]. This type is unsafe, because pushing
+     a semantic value of arbitrary type into the stack can later cause a
+     semantic action to crash and burn. The function [feed] is given a safe
+     type below. *)
+
+  let feed_nonterminal
+        (nt : nonterminal) startp (semv : semantic_value) endp (env : 'b env)
+      : 'b env
+  =
+    (* Check if the source state has an outgoing transition labeled [nt].
+       This is done by consulting the [goto] table. *)
+    let source = env.current in
+    match ET.maybe_goto_nt source nt with
+    | None ->
+        feed_failure()
+    | Some target ->
+        (* Push a new cell onto the stack, containing the identity of the state
+           that we are leaving. The semantic value [semv] and positions [startp]
+           and [endp] contained in the new cell are provided by the caller. *)
+        let stack = { state = source; semv; startp; endp; next = env.stack } in
+        (* Move to the target state. *)
+        { env with stack; current = target }
+
+  let reduce   _env _prod = feed_failure()
+  let initiate _env       = feed_failure()
+
+  let feed_terminal
+        (terminal : terminal) startp (semv : semantic_value) endp (env : 'b env)
+      : 'b env
+  =
+    (* Check if the source state has an outgoing transition labeled [terminal].
+       This is done by consulting the [action] table. *)
+    let source = env.current in
+    ET.action source terminal semv
+      (fun env _please_discard _terminal semv target ->
+        (* There is indeed a transition toward the state [target].
+           Push a new cell onto the stack and move to the target state. *)
+        let stack = { state = source; semv; startp; endp; next = env.stack } in
+        { env with stack; current = target }
+      ) reduce initiate env
+
+  (* The type assigned to [feed] ensures that the type of the semantic value
+     [semv] is appropriate: it must be the semantic-value type of the symbol
+     [symbol]. *)
+
+  let feed (symbol : 'a symbol) startp (semv : 'a) endp env =
+    let semv : semantic_value = Obj.repr semv in
+    match symbol with
+    | N nt ->
+        feed_nonterminal (n2i nt) startp semv endp env
+    | T terminal ->
+        feed_terminal (t2i terminal) startp semv endp env
+
+end
+end
+module TableInterpreter = struct
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+module MakeEngineTable (T : TableFormat.TABLES) = struct
+
+  type state =
+      int
+
+  let number s = s
+
+  type token =
+      T.token
+
+  type terminal =
+      int
+
+  type nonterminal =
+      int
+
+  type semantic_value =
+      Obj.t
+
+  let token2terminal =
+    T.token2terminal
+
+  let token2value =
+    T.token2value
+
+  let error_terminal =
+    T.error_terminal
+
+  let error_value =
+    Obj.repr ()
+
+  (* The function [foreach_terminal] exploits the fact that the
+     first component of [T.error] is [Terminal.n - 1], i.e., the
+     number of terminal symbols, including [error] but not [#]. *)
+
+  (* There is similar code in [InspectionTableInterpreter]. The
+     code there contains an additional conversion of the type
+     [terminal] to the type [xsymbol]. *)
+
+  let rec foldij i j f accu =
+    if i = j then
+      accu
+    else
+      foldij (i + 1) j f (f i accu)
+
+  let foreach_terminal f accu =
+    let n, _ = T.error in
+    foldij 0 n (fun i accu ->
+      f i accu
+    ) accu
+
+  type production =
+      int
+
+  (* In principle, only non-start productions are exposed to the user,
+     at type [production] or at type [int]. This is checked dynamically. *)
+  let non_start_production i =
+    assert (T.start <= i && i - T.start < Array.length T.semantic_action)
+
+  let production_index i =
+    non_start_production i;
+    i
+
+  let find_production i =
+    non_start_production i;
+    i
+
+  let default_reduction state defred nodefred env =
+    let code = PackedIntArray.get T.default_reduction state in
+    if code = 0 then
+      nodefred env
+    else
+      defred env (code - 1)
+
+  let is_start prod =
+    prod < T.start
+
+  (* This auxiliary function helps access a compressed, two-dimensional
+     matrix, like the action and goto tables. *)
+
+  let unmarshal2 table i j =
+    RowDisplacement.getget
+      PackedIntArray.get
+      PackedIntArray.get
+      table
+      i j
+
+  let action state terminal value shift reduce fail env =
+    match PackedIntArray.unflatten1 T.error state terminal with
+    | 1 ->
+        let action = unmarshal2 T.action state terminal in
+        let opcode = action land 0b11
+        and param = action lsr 2 in
+        if opcode >= 0b10 then
+          (* 0b10 : shift/discard *)
+          (* 0b11 : shift/nodiscard *)
+          let please_discard = (opcode = 0b10) in
+          shift env please_discard terminal value param
+        else
+          (* 0b01 : reduce *)
+          (* 0b00 : cannot happen *)
+          reduce env param
+    | c ->
+        assert (c = 0);
+        fail env
+
+  let goto_nt state nt =
+    let code = unmarshal2 T.goto state nt in
+    (* code = 1 + state *)
+    code - 1
+
+  let goto_prod state prod =
+    goto_nt state (PackedIntArray.get T.lhs prod)
+
+  let maybe_goto_nt state nt =
+    let code = unmarshal2 T.goto state nt in
+    (* If [code] is 0, there is no outgoing transition.
+       If [code] is [1 + state], there is a transition towards [state]. *)
+    assert (0 <= code);
+    if code = 0 then None else Some (code - 1)
+
+  exception Error =
+        T.Error
+
+  type semantic_action =
+      (state, semantic_value, token) EngineTypes.env ->
+      (state, semantic_value)        EngineTypes.stack
+
+  let semantic_action prod =
+    (* Indexing into the array [T.semantic_action] is off by [T.start],
+       because the start productions do not have entries in this array. *)
+    T.semantic_action.(prod - T.start)
+
+  (* [may_reduce state prod] tests whether the state [state] is capable of
+     reducing the production [prod]. This information could be determined
+     in constant time if we were willing to create a bitmap for it, but
+     that would take up a lot of space. Instead, we obtain this information
+     by iterating over a line in the action table. This is costly, but this
+     function is not normally used by the LR engine anyway; it is supposed
+     to be used only by programmers who wish to develop error recovery
+     strategies. *)
+
+  (* In the future, if desired, we could memoize this function, so as
+     to pay the cost in (memory) space only if and where this function
+     is actually used. We could also replace [foreach_terminal] with a
+     function [exists_terminal] which stops as soon as the accumulator
+     is [true]. *)
+
+  let may_reduce state prod =
+    (* Test if there is a default reduction of [prod]. *)
+    default_reduction state
+      (fun () prod' -> prod = prod')
+      (fun () ->
+        (* If not, then for each terminal [t], ... *)
+        foreach_terminal (fun t accu ->
+          accu ||
+          (* ... test if there is a reduction of [prod] on [t]. *)
+          action state t ()
+            (* shift:  *) (fun () _ _ () _ -> false)
+            (* reduce: *) (fun () prod' -> prod = prod')
+            (* fail:   *) (fun () -> false)
+            ()
+        ) false
+      )
+      ()
+
+  (* If [T.trace] is [None], then the logging functions do nothing. *)
+
+  let log =
+    match T.trace with Some _ -> true | None -> false
+
+  module Log = struct
+
+    open Printf
+
+    let state state =
+      match T.trace with
+      | Some _ ->
+          fprintf stderr "State %d:\n%!" state
+      | None ->
+          ()
+
+    let shift terminal state =
+      match T.trace with
+      | Some (terminals, _) ->
+          fprintf stderr "Shifting (%s) to state %d\n%!" terminals.(terminal) state
+      | None ->
+          ()
+
+    let reduce_or_accept prod =
+      match T.trace with
+      | Some (_, productions) ->
+          fprintf stderr "%s\n%!" productions.(prod)
+      | None ->
+          ()
+
+    let lookahead_token token startp endp =
+      match T.trace with
+      | Some (terminals, _) ->
+          fprintf stderr "Lookahead token is now %s (%d-%d)\n%!"
+            terminals.(token)
+            startp.Lexing.pos_cnum
+            endp.Lexing.pos_cnum
+      | None ->
+          ()
+
+    let initiating_error_handling () =
+      match T.trace with
+      | Some _ ->
+          fprintf stderr "Initiating error handling\n%!"
+      | None ->
+          ()
+
+    let resuming_error_handling () =
+      match T.trace with
+      | Some _ ->
+          fprintf stderr "Resuming error handling\n%!"
+      | None ->
+          ()
+
+    let handling_error state =
+      match T.trace with
+      | Some _ ->
+          fprintf stderr "Handling error in state %d\n%!" state
+      | None ->
+          ()
+
+  end
+
+end
+end
+module StaticVersion = struct
+let require_20181113 = ()
+end
diff --git a/boot/menhir/menhirLib.mli b/boot/menhir/menhirLib.mli
new file mode 100644
index 00000000..343c9d6c
--- /dev/null
+++ b/boot/menhir/menhirLib.mli
@@ -0,0 +1,1705 @@
+module General : sig
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* This module offers general-purpose functions on lists and streams. *)
+
+(* As of 2017/03/31, this module is DEPRECATED. It might be removed in
+   the future. *)
+
+(* --------------------------------------------------------------------------- *)
+
+(* Lists. *)
+
+(* [take n xs] returns the [n] first elements of the list [xs]. It is
+   acceptable  for the list [xs] to have length less than [n], in
+   which case [xs] itself is returned. *)
+
+val take: int -> 'a list -> 'a list
+
+(* [drop n xs] returns the list [xs], deprived of its [n] first elements.
+   It is acceptable for the list [xs] to have length less than [n], in
+   which case an empty list is returned. *)
+
+val drop: int -> 'a list -> 'a list
+
+(* [uniq cmp xs] assumes that the list [xs] is sorted according to the
+   ordering [cmp] and returns the list [xs] deprived of any duplicate
+   elements. *)
+
+val uniq: ('a -> 'a -> int) -> 'a list -> 'a list
+
+(* [weed cmp xs] returns the list [xs] deprived of any duplicate elements. *)
+
+val weed: ('a -> 'a -> int) -> 'a list -> 'a list
+
+(* --------------------------------------------------------------------------- *)
+
+(* A stream is a list whose elements are produced on demand. *)
+
+type 'a stream =
+    'a head Lazy.t
+
+and 'a head =
+  | Nil
+  | Cons of 'a * 'a stream
+
+(* The length of a stream. *)
+
+val length: 'a stream -> int
+
+(* Folding over a stream. *)
+
+val foldr: ('a -> 'b -> 'b) -> 'a stream -> 'b -> 'b
+end
+module Convert : sig
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* An ocamlyacc-style, or Menhir-style, parser requires access to
+   the lexer, which must be parameterized with a lexing buffer, and
+   to the lexing buffer itself, where it reads position information. *)
+
+(* This traditional API is convenient when used with ocamllex, but
+   inelegant when used with other lexer generators. *)
+
+type ('token, 'semantic_value) traditional =
+    (Lexing.lexbuf -> 'token) -> Lexing.lexbuf -> 'semantic_value
+
+(* This revised API is independent of any lexer generator. Here, the
+   parser only requires access to the lexer, and the lexer takes no
+   parameters. The tokens returned by the lexer may contain position
+   information. *)
+
+type ('token, 'semantic_value) revised =
+    (unit -> 'token) -> 'semantic_value
+
+(* --------------------------------------------------------------------------- *)
+
+(* Converting a traditional parser, produced by ocamlyacc or Menhir,
+   into a revised parser. *)
+
+(* A token of the revised lexer is essentially a triple of a token
+   of the traditional lexer (or raw token), a start position, and
+   and end position. The three [get] functions are accessors. *)
+
+(* We do not require the type ['token] to actually be a triple type.
+   This enables complex applications where it is a record type with
+   more than three fields. It also enables simple applications where
+   positions are of no interest, so ['token] is just ['raw_token]
+   and [get_startp] and [get_endp] return dummy positions. *)
+
+val traditional2revised:
+  ('token -> 'raw_token) ->
+  ('token -> Lexing.position) ->
+  ('token -> Lexing.position) ->
+  ('raw_token, 'semantic_value) traditional ->
+  ('token, 'semantic_value) revised
+
+(* --------------------------------------------------------------------------- *)
+
+(* Converting a revised parser back to a traditional parser. *)
+
+val revised2traditional:
+  ('raw_token -> Lexing.position -> Lexing.position -> 'token) ->
+  ('token, 'semantic_value) revised ->
+  ('raw_token, 'semantic_value) traditional
+
+(* --------------------------------------------------------------------------- *)
+
+(* Simplified versions of the above, where concrete triples are used. *)
+
+module Simplified : sig
+
+  val traditional2revised:
+    ('token, 'semantic_value) traditional ->
+    ('token * Lexing.position * Lexing.position, 'semantic_value) revised
+
+  val revised2traditional:
+    ('token * Lexing.position * Lexing.position, 'semantic_value) revised ->
+    ('token, 'semantic_value) traditional
+
+end
+end
+module IncrementalEngine : sig
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+type position = Lexing.position
+
+open General
+
+(* This signature describes the incremental LR engine. *)
+
+(* In this mode, the user controls the lexer, and the parser suspends
+   itself when it needs to read a new token. *)
+
+module type INCREMENTAL_ENGINE = sig
+
+  type token
+
+  (* A value of type [production] is (an index for) a production. The start
+     productions (which do not exist in an \mly file, but are constructed by
+     Menhir internally) are not part of this type. *)
+
+  type production
+
+  (* The type ['a checkpoint] represents an intermediate or final state of the
+     parser. An intermediate checkpoint is a suspension: it records the parser's
+     current state, and allows parsing to be resumed. The parameter ['a] is
+     the type of the semantic value that will eventually be produced if the
+     parser succeeds. *)
+
+  (* [Accepted] and [Rejected] are final checkpoints. [Accepted] carries a
+     semantic value. *)
+
+  (* [InputNeeded] is an intermediate checkpoint. It means that the parser wishes
+     to read one token before continuing. *)
+
+  (* [Shifting] is an intermediate checkpoint. It means that the parser is taking
+     a shift transition. It exposes the state of the parser before and after
+     the transition. The Boolean parameter tells whether the parser intends to
+     request a new token after this transition. (It always does, except when
+     it is about to accept.) *)
+
+  (* [AboutToReduce] is an intermediate checkpoint. It means that the parser is
+     about to perform a reduction step. It exposes the parser's current
+     state as well as the production that is about to be reduced. *)
+
+  (* [HandlingError] is an intermediate checkpoint. It means that the parser has
+     detected an error and is currently handling it, in several steps. *)
+
+  (* A value of type ['a env] represents a configuration of the automaton:
+     current state, stack, lookahead token, etc. The parameter ['a] is the
+     type of the semantic value that will eventually be produced if the parser
+     succeeds. *)
+
+  (* In normal operation, the parser works with checkpoints: see the functions
+     [offer] and [resume]. However, it is also possible to work directly with
+     environments (see the functions [pop], [force_reduction], and [feed]) and
+     to reconstruct a checkpoint out of an environment (see [input_needed]).
+     This is considered advanced functionality; its purpose is to allow error
+     recovery strategies to be programmed by the user. *)
+
+  type 'a env
+
+  type 'a checkpoint = private
+    | InputNeeded of 'a env
+    | Shifting of 'a env * 'a env * bool
+    | AboutToReduce of 'a env * production
+    | HandlingError of 'a env
+    | Accepted of 'a
+    | Rejected
+
+  (* [offer] allows the user to resume the parser after it has suspended
+     itself with a checkpoint of the form [InputNeeded env]. [offer] expects the
+     old checkpoint as well as a new token and produces a new checkpoint. It does not
+     raise any exception. *)
+
+  val offer:
+    'a checkpoint ->
+    token * position * position ->
+    'a checkpoint
+
+  (* [resume] allows the user to resume the parser after it has suspended
+     itself with a checkpoint of the form [AboutToReduce (env, prod)] or
+     [HandlingError env]. [resume] expects the old checkpoint and produces a new
+     checkpoint. It does not raise any exception. *)
+
+  val resume:
+    'a checkpoint ->
+    'a checkpoint
+
+  (* A token supplier is a function of no arguments which delivers a new token
+     (together with its start and end positions) every time it is called. *)
+
+  type supplier =
+    unit -> token * position * position
+
+  (* A pair of a lexer and a lexing buffer can be easily turned into a supplier. *)
+
+  val lexer_lexbuf_to_supplier:
+    (Lexing.lexbuf -> token) ->
+    Lexing.lexbuf ->
+    supplier
+
+  (* The functions [offer] and [resume] are sufficient to write a parser loop.
+     One can imagine many variations (which is why we expose these functions
+     in the first place!). Here, we expose a few variations of the main loop,
+     ready for use. *)
+
+  (* [loop supplier checkpoint] begins parsing from [checkpoint], reading
+     tokens from [supplier]. It continues parsing until it reaches a
+     checkpoint of the form [Accepted v] or [Rejected]. In the former case, it
+     returns [v]. In the latter case, it raises the exception [Error]. *)
+
+  val loop: supplier -> 'a checkpoint -> 'a
+
+  (* [loop_handle succeed fail supplier checkpoint] begins parsing from
+     [checkpoint], reading tokens from [supplier]. It continues parsing until
+     it reaches a checkpoint of the form [Accepted v] or [HandlingError env]
+     (or [Rejected], but that should not happen, as [HandlingError _] will be
+     observed first). In the former case, it calls [succeed v]. In the latter
+     case, it calls [fail] with this checkpoint. It cannot raise [Error].
+
+     This means that Menhir's traditional error-handling procedure (which pops
+     the stack until a state that can act on the [error] token is found) does
+     not get a chance to run. Instead, the user can implement her own error
+     handling code, in the [fail] continuation. *)
+
+  val loop_handle:
+    ('a -> 'answer) ->
+    ('a checkpoint -> 'answer) ->
+    supplier -> 'a checkpoint -> 'answer
+
+  (* [loop_handle_undo] is analogous to [loop_handle], except it passes a pair
+     of checkpoints to the failure continuation.
+
+     The first (and oldest) checkpoint is the last [InputNeeded] checkpoint that
+     was encountered before the error was detected. The second (and newest)
+     checkpoint is where the error was detected, as in [loop_handle]. Going back
+     to the first checkpoint can be thought of as undoing any reductions that
+     were performed after seeing the problematic token. (These reductions must
+     be default reductions or spurious reductions.)
+
+     [loop_handle_undo] must initially be applied to an [InputNeeded] checkpoint.
+     The parser's initial checkpoints satisfy this constraint. *)
+
+  val loop_handle_undo:
+    ('a -> 'answer) ->
+    ('a checkpoint -> 'a checkpoint -> 'answer) ->
+    supplier -> 'a checkpoint -> 'answer
+
+  (* [shifts checkpoint] assumes that [checkpoint] has been obtained by
+     submitting a token to the parser. It runs the parser from [checkpoint],
+     through an arbitrary number of reductions, until the parser either
+     accepts this token (i.e., shifts) or rejects it (i.e., signals an error).
+     If the parser decides to shift, then [Some env] is returned, where [env]
+     is the parser's state just before shifting. Otherwise, [None] is
+     returned. *)
+
+  (* It is desirable that the semantic actions be side-effect free, or that
+     their side-effects be harmless (replayable). *)
+
+  val shifts: 'a checkpoint -> 'a env option
+
+  (* The function [acceptable] allows testing, after an error has been
+     detected, which tokens would have been accepted at this point. It is
+     implemented using [shifts]. Its argument should be an [InputNeeded]
+     checkpoint. *)
+
+  (* For completeness, one must undo any spurious reductions before carrying out
+     this test -- that is, one must apply [acceptable] to the FIRST checkpoint
+     that is passed by [loop_handle_undo] to its failure continuation. *)
+
+  (* This test causes some semantic actions to be run! The semantic actions
+     should be side-effect free, or their side-effects should be harmless. *)
+
+  (* The position [pos] is used as the start and end positions of the
+     hypothetical token, and may be picked up by the semantic actions. We
+     suggest using the position where the error was detected. *)
+
+  val acceptable: 'a checkpoint -> token -> position -> bool
+
+  (* The abstract type ['a lr1state] describes the non-initial states of the
+     LR(1) automaton. The index ['a] represents the type of the semantic value
+     associated with this state's incoming symbol. *)
+
+  type 'a lr1state
+
+  (* The states of the LR(1) automaton are numbered (from 0 and up). *)
+
+  val number: _ lr1state -> int
+
+  (* Productions are numbered. *)
+
+  (* [find_production i] requires the index [i] to be valid. Use with care. *)
+
+  val production_index: production -> int
+  val find_production: int -> production
+
+  (* An element is a pair of a non-initial state [s] and a semantic value [v]
+     associated with the incoming symbol of this state. The idea is, the value
+     [v] was pushed onto the stack just before the state [s] was entered. Thus,
+     for some type ['a], the state [s] has type ['a lr1state] and the value [v]
+     has type ['a]. In other words, the type [element] is an existential type. *)
+
+  type element =
+    | Element: 'a lr1state * 'a * position * position -> element
+
+  (* The parser's stack is (or, more precisely, can be viewed as) a stream of
+     elements. The type [stream] is defined by the module [General]. *)
+
+  (* As of 2017/03/31, the types [stream] and [stack] and the function [stack]
+     are DEPRECATED. They might be removed in the future. An alternative way
+     of inspecting the stack is via the functions [top] and [pop]. *)
+
+  type stack = (* DEPRECATED *)
+    element stream
+
+  (* This is the parser's stack, a stream of elements. This stream is empty if
+     the parser is in an initial state; otherwise, it is non-empty.  The LR(1)
+     automaton's current state is the one found in the top element of the
+     stack. *)
+
+  val stack: 'a env -> stack (* DEPRECATED *)
+
+  (* [top env] returns the parser's top stack element. The state contained in
+     this stack element is the current state of the automaton. If the stack is
+     empty, [None] is returned. In that case, the current state of the
+     automaton must be an initial state. *)
+
+  val top: 'a env -> element option
+
+  (* [pop_many i env] pops [i] cells off the automaton's stack. This is done
+     via [i] successive invocations of [pop]. Thus, [pop_many 1] is [pop]. The
+     index [i] must be nonnegative. The time complexity is O(i). *)
+
+  val pop_many: int -> 'a env -> 'a env option
+
+  (* [get i env] returns the parser's [i]-th stack element. The index [i] is
+     0-based: thus, [get 0] is [top]. If [i] is greater than or equal to the
+     number of elements in the stack, [None] is returned. The time complexity
+     is O(i). *)
+
+  val get: int -> 'a env -> element option
+
+  (* [current_state_number env] is (the integer number of) the automaton's
+     current state. This works even if the automaton's stack is empty, in
+     which case the current state is an initial state. This number can be
+     passed as an argument to a [message] function generated by [menhir
+     --compile-errors]. *)
+
+  val current_state_number: 'a env -> int
+
+  (* [equal env1 env2] tells whether the parser configurations [env1] and
+     [env2] are equal in the sense that the automaton's current state is the
+     same in [env1] and [env2] and the stack is *physically* the same in
+     [env1] and [env2]. If [equal env1 env2] is [true], then the sequence of
+     the stack elements, as observed via [pop] and [top], must be the same in
+     [env1] and [env2]. Also, if [equal env1 env2] holds, then the checkpoints
+     [input_needed env1] and [input_needed env2] must be equivalent. The
+     function [equal] has time complexity O(1). *)
+
+  val equal: 'a env -> 'a env -> bool
+
+  (* These are the start and end positions of the current lookahead token. If
+     invoked in an initial state, this function returns a pair of twice the
+     initial position. *)
+
+  val positions: 'a env -> position * position
+
+  (* When applied to an environment taken from a checkpoint of the form
+     [AboutToReduce (env, prod)], the function [env_has_default_reduction]
+     tells whether the reduction that is about to take place is a default
+     reduction. *)
+
+  val env_has_default_reduction: 'a env -> bool
+
+  (* [state_has_default_reduction s] tells whether the state [s] has a default
+     reduction. This includes the case where [s] is an accepting state. *)
+
+  val state_has_default_reduction: _ lr1state -> bool
+
+  (* [pop env] returns a new environment, where the parser's top stack cell
+     has been popped off. (If the stack is empty, [None] is returned.) This
+     amounts to pretending that the (terminal or nonterminal) symbol that
+     corresponds to this stack cell has not been read. *)
+
+  val pop: 'a env -> 'a env option
+
+  (* [force_reduction prod env] should be called only if in the state [env]
+     the parser is capable of reducing the production [prod]. If this
+     condition is satisfied, then this production is reduced, which means that
+     its semantic action is executed (this can have side effects!) and the
+     automaton makes a goto (nonterminal) transition. If this condition is not
+     satisfied, [Invalid_argument _] is raised. *)
+
+  val force_reduction: production -> 'a env -> 'a env
+
+  (* [input_needed env] returns [InputNeeded env]. That is, out of an [env]
+     that might have been obtained via a series of calls to the functions
+     [pop], [force_reduction], [feed], etc., it produces a checkpoint, which
+     can be used to resume normal parsing, by supplying this checkpoint as an
+     argument to [offer]. *)
+
+  (* This function should be used with some care. It could "mess up the
+     lookahead" in the sense that it allows parsing to resume in an arbitrary
+     state [s] with an arbitrary lookahead symbol [t], even though Menhir's
+     reachability analysis (menhir --list-errors) might well think that it is
+     impossible to reach this particular configuration. If one is using
+     Menhir's new error reporting facility, this could cause the parser to
+     reach an error state for which no error message has been prepared. *)
+
+  val input_needed: 'a env -> 'a checkpoint
+
+end
+
+(* This signature is a fragment of the inspection API that is made available
+   to the user when [--inspection] is used. This fragment contains type
+   definitions for symbols. *)
+
+module type SYMBOLS = sig
+
+  (* The type ['a terminal] represents a terminal symbol. The type ['a
+     nonterminal] represents a nonterminal symbol. In both cases, the index
+     ['a] represents the type of the semantic values associated with this
+     symbol. The concrete definitions of these types are generated. *)
+
+  type 'a terminal
+  type 'a nonterminal
+
+  (* The type ['a symbol] represents a terminal or nonterminal symbol. It is
+     the disjoint union of the types ['a terminal] and ['a nonterminal]. *)
+
+  type 'a symbol =
+    | T : 'a terminal -> 'a symbol
+    | N : 'a nonterminal -> 'a symbol
+
+  (* The type [xsymbol] is an existentially quantified version of the type
+     ['a symbol]. This type is useful in situations where the index ['a]
+     is not statically known. *)
+
+  type xsymbol =
+    | X : 'a symbol -> xsymbol
+
+end
+
+(* This signature describes the inspection API that is made available to the
+   user when [--inspection] is used. *)
+
+module type INSPECTION = sig
+
+  (* The types of symbols are described above. *)
+
+  include SYMBOLS
+
+  (* The type ['a lr1state] is meant to be the same as in [INCREMENTAL_ENGINE]. *)
+
+  type 'a lr1state
+
+  (* The type [production] is meant to be the same as in [INCREMENTAL_ENGINE].
+     It represents a production of the grammar. A production can be examined
+     via the functions [lhs] and [rhs] below. *)
+
+  type production
+
+  (* An LR(0) item is a pair of a production [prod] and a valid index [i] into
+     this production. That is, if the length of [rhs prod] is [n], then [i] is
+     comprised between 0 and [n], inclusive. *)
+
+  type item =
+      production * int
+
+  (* Ordering functions. *)
+
+  val compare_terminals: _ terminal -> _ terminal -> int
+  val compare_nonterminals: _ nonterminal -> _ nonterminal -> int
+  val compare_symbols: xsymbol -> xsymbol -> int
+  val compare_productions: production -> production -> int
+  val compare_items: item -> item -> int
+
+  (* [incoming_symbol s] is the incoming symbol of the state [s], that is,
+     the symbol that the parser must recognize before (has recognized when)
+     it enters the state [s]. This function gives access to the semantic
+     value [v] stored in a stack element [Element (s, v, _, _)]. Indeed,
+     by case analysis on the symbol [incoming_symbol s], one discovers the
+     type ['a] of the value [v]. *)
+
+  val incoming_symbol: 'a lr1state -> 'a symbol
+
+  (* [items s] is the set of the LR(0) items in the LR(0) core of the LR(1)
+     state [s]. This set is not epsilon-closed. This set is presented as a
+     list, in an arbitrary order. *)
+
+  val items: _ lr1state -> item list
+
+  (* [lhs prod] is the left-hand side of the production [prod]. This is
+     always a non-terminal symbol. *)
+
+  val lhs: production -> xsymbol
+
+  (* [rhs prod] is the right-hand side of the production [prod]. This is
+     a (possibly empty) sequence of (terminal or nonterminal) symbols. *)
+
+  val rhs: production -> xsymbol list
+
+  (* [nullable nt] tells whether the non-terminal symbol [nt] is nullable.
+     That is, it is true if and only if this symbol produces the empty
+     word [epsilon]. *)
+
+  val nullable: _ nonterminal -> bool
+
+  (* [first nt t] tells whether the FIRST set of the nonterminal symbol [nt]
+     contains the terminal symbol [t]. That is, it is true if and only if
+     [nt] produces a word that begins with [t]. *)
+
+  val first: _ nonterminal -> _ terminal -> bool
+
+  (* [xfirst] is analogous to [first], but expects a first argument of type
+     [xsymbol] instead of [_ terminal]. *)
+
+  val xfirst: xsymbol -> _ terminal -> bool
+
+  (* [foreach_terminal] enumerates the terminal symbols, including [error].
+     [foreach_terminal_but_error] enumerates the terminal symbols, excluding
+     [error]. *)
+
+  val foreach_terminal:           (xsymbol -> 'a -> 'a) -> 'a -> 'a
+  val foreach_terminal_but_error: (xsymbol -> 'a -> 'a) -> 'a -> 'a
+
+  (* The type [env] is meant to be the same as in [INCREMENTAL_ENGINE]. *)
+
+  type 'a env
+
+  (* [feed symbol startp semv endp env] causes the parser to consume the
+     (terminal or nonterminal) symbol [symbol], accompanied with the semantic
+     value [semv] and with the start and end positions [startp] and [endp].
+     Thus, the automaton makes a transition, and reaches a new state. The
+     stack grows by one cell. This operation is permitted only if the current
+     state (as determined by [env]) has an outgoing transition labeled with
+     [symbol]. Otherwise, [Invalid_argument _] is raised. *)
+
+  val feed: 'a symbol -> position -> 'a -> position -> 'b env -> 'b env
+
+end
+
+(* This signature combines the incremental API and the inspection API. *)
+
+module type EVERYTHING = sig
+
+  include INCREMENTAL_ENGINE
+
+  include INSPECTION
+    with type 'a lr1state := 'a lr1state
+    with type production := production
+    with type 'a env := 'a env
+
+end
+end
+module EngineTypes : sig
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* This file defines several types and module types that are used in the
+   specification of module [Engine]. *)
+
+(* --------------------------------------------------------------------------- *)
+
+(* It would be nice if we could keep the structure of stacks and environments
+   hidden. However, stacks and environments must be accessible to semantic
+   actions, so the following data structure definitions must be public. *)
+
+(* --------------------------------------------------------------------------- *)
+
+(* A stack is a linked list of cells. A sentinel cell -- which is its own
+   successor -- is used to mark the bottom of the stack. The sentinel cell
+   itself is not significant -- it contains dummy values. *)
+
+type ('state, 'semantic_value) stack = {
+
+  (* The state that we should go back to if we pop this stack cell. *)
+
+  (* This convention means that the state contained in the top stack cell is
+     not the current state [env.current]. It also means that the state found
+     within the sentinel is a dummy -- it is never consulted. This convention
+     is the same as that adopted by the code-based back-end. *)
+
+  state: 'state;
+
+  (* The semantic value associated with the chunk of input that this cell
+     represents. *)
+
+  semv: 'semantic_value;
+
+  (* The start and end positions of the chunk of input that this cell
+     represents. *)
+
+  startp: Lexing.position;
+  endp: Lexing.position;
+
+  (* The next cell down in the stack. If this is a self-pointer, then this
+     cell is the sentinel, and the stack is conceptually empty. *)
+
+  next: ('state, 'semantic_value) stack;
+
+}
+
+(* --------------------------------------------------------------------------- *)
+
+(* A parsing environment contains all of the parser's state (except for the
+   current program point). *)
+
+type ('state, 'semantic_value, 'token) env = {
+
+  (* If this flag is true, then the first component of [env.triple] should
+     be ignored, as it has been logically overwritten with the [error]
+     pseudo-token. *)
+
+  error: bool;
+
+  (* The last token that was obtained from the lexer, together with its start
+     and end positions. Warning: before the first call to the lexer has taken
+     place, a dummy (and possibly invalid) token is stored here. *)
+
+  triple: 'token * Lexing.position * Lexing.position;
+
+  (* The stack. In [CodeBackend], it is passed around on its own,
+     whereas, here, it is accessed via the environment. *)
+
+  stack: ('state, 'semantic_value) stack;
+
+  (* The current state. In [CodeBackend], it is passed around on its
+     own, whereas, here, it is accessed via the environment. *)
+
+  current: 'state;
+
+}
+
+(* --------------------------------------------------------------------------- *)
+
+(* This signature describes the parameters that must be supplied to the LR
+   engine. *)
+
+module type TABLE = sig
+
+  (* The type of automaton states. *)
+
+  type state
+
+  (* States are numbered. *)
+
+  val number: state -> int
+
+  (* The type of tokens. These can be thought of as real tokens, that is,
+     tokens returned by the lexer. They carry a semantic value. This type
+     does not include the [error] pseudo-token. *)
+
+  type token
+
+  (* The type of terminal symbols. These can be thought of as integer codes.
+     They do not carry a semantic value. This type does include the [error]
+     pseudo-token. *)
+
+  type terminal
+
+  (* The type of nonterminal symbols. *)
+
+  type nonterminal
+
+  (* The type of semantic values. *)
+
+  type semantic_value
+
+  (* A token is conceptually a pair of a (non-[error]) terminal symbol and
+     a semantic value. The following two functions are the pair projections. *)
+
+  val token2terminal: token -> terminal
+  val token2value: token -> semantic_value
+
+  (* Even though the [error] pseudo-token is not a real token, it is a
+     terminal symbol. Furthermore, for regularity, it must have a semantic
+     value. *)
+
+  val error_terminal: terminal
+  val error_value: semantic_value
+
+  (* [foreach_terminal] allows iterating over all terminal symbols. *)
+
+  val foreach_terminal: (terminal -> 'a -> 'a) -> 'a -> 'a
+
+  (* The type of productions. *)
+
+  type production
+
+  val production_index: production -> int
+  val find_production: int -> production
+
+  (* If a state [s] has a default reduction on production [prod], then, upon
+     entering [s], the automaton should reduce [prod] without consulting the
+     lookahead token. The following function allows determining which states
+     have default reductions. *)
+
+  (* Instead of returning a value of a sum type -- either [DefRed prod], or
+     [NoDefRed] -- it accepts two continuations, and invokes just one of
+     them. This mechanism allows avoiding a memory allocation. *)
+
+  val default_reduction:
+    state ->
+    ('env -> production -> 'answer) ->
+    ('env -> 'answer) ->
+    'env -> 'answer
+
+  (* An LR automaton can normally take three kinds of actions: shift, reduce,
+     or fail. (Acceptance is a particular case of reduction: it consists in
+     reducing a start production.) *)
+
+  (* There are two variants of the shift action. [shift/discard s] instructs
+     the automaton to discard the current token, request a new one from the
+     lexer, and move to state [s]. [shift/nodiscard s] instructs it to move to
+     state [s] without requesting a new token. This instruction should be used
+     when [s] has a default reduction on [#]. See [CodeBackend.gettoken] for
+     details. *)
+
+  (* This is the automaton's action table. It maps a pair of a state and a
+     terminal symbol to an action. *)
+
+  (* Instead of returning a value of a sum type -- one of shift/discard,
+     shift/nodiscard, reduce, or fail -- this function accepts three
+     continuations, and invokes just one them. This mechanism allows avoiding
+     a memory allocation. *)
+
+  (* In summary, the parameters to [action] are as follows:
+
+     - the first two parameters, a state and a terminal symbol, are used to
+       look up the action table;
+
+     - the next parameter is the semantic value associated with the above
+       terminal symbol; it is not used, only passed along to the shift
+       continuation, as explained below;
+
+     - the shift continuation expects an environment; a flag that tells
+       whether to discard the current token; the terminal symbol that
+       is being shifted; its semantic value; and the target state of
+       the transition;
+
+     - the reduce continuation expects an environment and a production;
+
+     - the fail continuation expects an environment;
+
+     - the last parameter is the environment; it is not used, only passed
+       along to the selected continuation. *)
+
+  val action:
+    state ->
+    terminal ->
+    semantic_value ->
+    ('env -> bool -> terminal -> semantic_value -> state -> 'answer) ->
+    ('env -> production -> 'answer) ->
+    ('env -> 'answer) ->
+    'env -> 'answer
+
+  (* This is the automaton's goto table. This table maps a pair of a state
+     and a nonterminal symbol to a new state. By extension, it also maps a
+     pair of a state and a production to a new state. *)
+
+  (* The function [goto_nt] can be applied to [s] and [nt] ONLY if the state
+     [s] has an outgoing transition labeled [nt]. Otherwise, its result is
+     undefined. Similarly, the call [goto_prod prod s] is permitted ONLY if
+     the state [s] has an outgoing transition labeled with the nonterminal
+     symbol [lhs prod]. The function [maybe_goto_nt] involves an additional
+     dynamic check and CAN be called even if there is no outgoing transition. *)
+
+  val       goto_nt  : state -> nonterminal -> state
+  val       goto_prod: state -> production  -> state
+  val maybe_goto_nt:   state -> nonterminal -> state option
+
+  (* [is_start prod] tells whether the production [prod] is a start production. *)
+
+  val is_start: production -> bool
+
+  (* By convention, a semantic action is responsible for:
+
+     1. fetching whatever semantic values and positions it needs off the stack;
+
+     2. popping an appropriate number of cells off the stack, as dictated
+        by the length of the right-hand side of the production;
+
+     3. computing a new semantic value, as well as new start and end positions;
+
+     4. pushing a new stack cell, which contains the three values
+        computed in step 3;
+
+     5. returning the new stack computed in steps 2 and 4.
+
+     Point 1 is essentially forced upon us: if semantic values were fetched
+     off the stack by this interpreter, then the calling convention for
+     semantic actions would be variadic: not all semantic actions would have
+     the same number of arguments. The rest follows rather naturally. *)
+
+  (* Semantic actions are allowed to raise [Error]. *)
+
+  exception Error
+
+  type semantic_action =
+      (state, semantic_value, token) env -> (state, semantic_value) stack
+
+  val semantic_action: production -> semantic_action
+
+  (* [may_reduce state prod] tests whether the state [state] is capable of
+     reducing the production [prod]. This function is currently costly and
+     is not used by the core LR engine. It is used in the implementation
+     of certain functions, such as [force_reduction], which allow the engine
+     to be driven programmatically. *)
+
+  val may_reduce: state -> production -> bool
+
+  (* The LR engine requires a number of hooks, which are used for logging. *)
+
+  (* The comments below indicate the conventional messages that correspond
+     to these hooks in the code-based back-end; see [CodeBackend]. *)
+
+  (* If the flag [log] is false, then the logging functions are not called.
+     If it is [true], then they are called. *)
+
+  val log : bool
+
+  module Log : sig
+
+    (* State %d: *)
+
+    val state: state -> unit
+
+    (* Shifting () to state  *)
+
+    val shift: terminal -> state -> unit
+
+    (* Reducing a production should be logged either as a reduction
+       event (for regular productions) or as an acceptance event (for
+       start productions). *)
+
+    (* Reducing production  / Accepting *)
+
+    val reduce_or_accept: production -> unit
+
+    (* Lookahead token is now  (-) *)
+
+    val lookahead_token: terminal -> Lexing.position -> Lexing.position -> unit
+
+    (* Initiating error handling *)
+
+    val initiating_error_handling: unit -> unit
+
+    (* Resuming error handling *)
+
+    val resuming_error_handling: unit -> unit
+
+    (* Handling error in state  *)
+
+    val handling_error: state -> unit
+
+  end
+
+end
+
+(* --------------------------------------------------------------------------- *)
+
+(* This signature describes the monolithic (traditional) LR engine. *)
+
+(* In this interface, the parser controls the lexer. *)
+
+module type MONOLITHIC_ENGINE = sig
+
+  type state
+
+  type token
+
+  type semantic_value
+
+  (* An entry point to the engine requires a start state, a lexer, and a lexing
+     buffer. It either succeeds and produces a semantic value, or fails and
+     raises [Error]. *)
+
+  exception Error
+
+  val entry:
+    state ->
+    (Lexing.lexbuf -> token) ->
+    Lexing.lexbuf ->
+    semantic_value
+
+end
+
+(* --------------------------------------------------------------------------- *)
+
+(* The following signatures describe the incremental LR engine. *)
+
+(* First, see [INCREMENTAL_ENGINE] in the file [IncrementalEngine.ml]. *)
+
+(* The [start] function is set apart because we do not wish to publish
+   it as part of the generated [parser.mli] file. Instead, the table
+   back-end will publish specialized versions of it, with a suitable
+   type cast. *)
+
+module type INCREMENTAL_ENGINE_START = sig
+
+  (* [start] is an entry point. It requires a start state and a start position
+     and begins the parsing process. If the lexer is based on an OCaml lexing
+     buffer, the start position should be [lexbuf.lex_curr_p]. [start] produces
+     a checkpoint, which usually will be an [InputNeeded] checkpoint. (It could
+     be [Accepted] if this starting state accepts only the empty word. It could
+     be [Rejected] if this starting state accepts no word at all.) It does not
+     raise any exception. *)
+
+  (* [start s pos] should really produce a checkpoint of type ['a checkpoint],
+     for a fixed ['a] that depends on the state [s]. We cannot express this, so
+     we use [semantic_value checkpoint], which is safe. The table back-end uses
+     [Obj.magic] to produce safe specialized versions of [start]. *)
+
+  type state
+  type semantic_value
+  type 'a checkpoint
+
+  val start:
+    state ->
+    Lexing.position ->
+    semantic_value checkpoint
+
+end
+
+(* --------------------------------------------------------------------------- *)
+
+(* This signature describes the LR engine, which combines the monolithic
+   and incremental interfaces. *)
+
+module type ENGINE = sig
+
+  include MONOLITHIC_ENGINE
+
+  include IncrementalEngine.INCREMENTAL_ENGINE
+    with type token := token
+     and type 'a lr1state = state (* useful for us; hidden from the end user *)
+
+  include INCREMENTAL_ENGINE_START
+    with type state := state
+     and type semantic_value := semantic_value
+     and type 'a checkpoint := 'a checkpoint
+
+end
+end
+module Engine : sig
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+open EngineTypes
+
+(* The LR parsing engine. *)
+
+module Make (T : TABLE)
+: ENGINE
+  with type state = T.state
+   and type token = T.token
+   and type semantic_value = T.semantic_value
+   and type production = T.production
+   and type 'a env = (T.state, T.semantic_value, T.token) EngineTypes.env
+
+(* We would prefer not to expose the definition of the type [env].
+   However, it must be exposed because some of the code in the
+   inspection API needs access to the engine's internals; see
+   [InspectionTableInterpreter]. Everything would be simpler if
+   --inspection was always ON, but that would lead to bigger parse
+   tables for everybody. *)
+end
+module ErrorReports : sig
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* -------------------------------------------------------------------------- *)
+
+(* The following functions help keep track of the start and end positions of
+   the last two tokens in a two-place buffer. This is used to nicely display
+   where a syntax error took place. *)
+
+type 'a buffer
+
+(* [wrap lexer] returns a pair of a new (initially empty) buffer and a lexer
+   which internally relies on [lexer] and updates [buffer] on the fly whenever
+   a token is demanded. *)
+
+open Lexing
+
+val wrap:
+  (lexbuf -> 'token) ->
+  (position * position) buffer * (lexbuf -> 'token)
+
+(* [show f buffer] prints the contents of the buffer, producing a string that
+   is typically of the form "after '%s' and before '%s'". The function [f] is
+   used to print an element. The buffer MUST be nonempty. *)
+
+val show: ('a -> string) -> 'a buffer -> string
+
+(* [last buffer] returns the last element of the buffer. The buffer MUST be
+   nonempty. *)
+
+val last: 'a buffer -> 'a
+
+(* -------------------------------------------------------------------------- *)
+end
+module Printers : sig
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* This module is part of MenhirLib. *)
+
+module Make
+
+  (I : IncrementalEngine.EVERYTHING)
+
+  (User : sig
+
+    (* [print s] is supposed to send the string [s] to some output channel. *)
+
+    val print: string -> unit
+
+    (* [print_symbol s] is supposed to print a representation of the symbol [s]. *)
+
+    val print_symbol: I.xsymbol -> unit
+
+    (* [print_element e] is supposed to print a representation of the element [e].
+       This function is optional; if it is not provided, [print_element_as_symbol]
+       (defined below) is used instead. *)
+
+    val print_element: (I.element -> unit) option
+
+  end)
+
+: sig
+
+  open I
+
+  (* Printing a list of symbols. *)
+
+  val print_symbols: xsymbol list -> unit
+
+  (* Printing an element as a symbol. This prints just the symbol
+     that this element represents; nothing more. *)
+
+  val print_element_as_symbol: element -> unit
+
+  (* Printing a stack as a list of elements. This function needs an element
+     printer. It uses [print_element] if provided by the user; otherwise
+     it uses [print_element_as_symbol]. (Ending with a newline.) *)
+
+  val print_stack: 'a env -> unit
+
+  (* Printing an item. (Ending with a newline.) *)
+
+  val print_item: item -> unit
+
+  (* Printing a production. (Ending with a newline.) *)
+
+  val print_production: production -> unit
+
+  (* Printing the current LR(1) state. The current state is first displayed
+     as a number; then the list of its LR(0) items is printed. (Ending with
+     a newline.) *)
+
+  val print_current_state: 'a env -> unit
+
+  (* Printing a summary of the stack and current state. This function just
+     calls [print_stack] and [print_current_state] in succession. *)
+
+  val print_env: 'a env -> unit
+
+end
+end
+module InfiniteArray : sig
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(** This module implements infinite arrays. **)
+type 'a t
+
+(** [make x] creates an infinite array, where every slot contains [x]. **)
+val make: 'a -> 'a t
+
+(** [get a i] returns the element contained at offset [i] in the array [a].
+   Slots are numbered 0 and up. **)
+val get: 'a t -> int -> 'a
+
+(** [set a i x] sets the element contained at offset [i] in the array
+    [a] to [x]. Slots are numbered 0 and up. **)
+val set: 'a t -> int -> 'a -> unit
+
+(** [extent a] is the length of an initial segment of the array [a]
+    that is sufficiently large to contain all [set] operations ever
+    performed. In other words, all elements beyond that segment have
+    the default value. *)
+val extent: 'a t -> int
+
+(** [domain a] is a fresh copy of an initial segment of the array [a]
+    whose length is [extent a]. *)
+val domain: 'a t -> 'a array
+end
+module PackedIntArray : sig
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* A packed integer array is represented as a pair of an integer [k] and
+   a string [s]. The integer [k] is the number of bits per integer that we
+   use. The string [s] is just an array of bits, which is read in 8-bit
+   chunks. *)
+
+(* The ocaml programming language treats string literals and array literals
+   in slightly different ways: the former are statically allocated, while
+   the latter are dynamically allocated. (This is rather arbitrary.) In the
+   context of Menhir's table-based back-end, where compact, immutable
+   integer arrays are needed, ocaml strings are preferable to ocaml arrays. *)
+
+type t =
+  int * string
+
+(* [pack a] turns an array of integers into a packed integer array. *)
+
+(* Because the sign bit is the most significant bit, the magnitude of
+   any negative number is the word size. In other words, [pack] does
+   not achieve any space savings as soon as [a] contains any negative
+   numbers, even if they are ``small''. *)
+
+val pack: int array -> t
+
+(* [get t i] returns the integer stored in the packed array [t] at index [i]. *)
+
+(* Together, [pack] and [get] satisfy the following property: if the index [i]
+   is within bounds, then [get (pack a) i] equals [a.(i)]. *)
+
+val get: t -> int -> int
+
+(* [get1 t i] returns the integer stored in the packed array [t] at index [i].
+   It assumes (and does not check) that the array's bit width is [1]. The
+   parameter [t] is just a string. *)
+
+val get1: string -> int -> int
+
+(* [unflatten1 (n, data) i j] accesses the two-dimensional bitmap
+   represented by [(n, data)] at indices [i] and [j]. The integer
+   [n] is the width of the bitmap; the string [data] is the second
+   component of the packed array obtained by encoding the table as
+   a one-dimensional array. *)
+
+val unflatten1: int * string -> int -> int -> int
+
+end
+module RowDisplacement : sig
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* This module compresses a two-dimensional table, where some values
+   are considered insignificant, via row displacement. *)
+
+(* A compressed table is represented as a pair of arrays. The
+   displacement array is an array of offsets into the data array. *)
+
+type 'a table =
+    int array * (* displacement *)
+     'a array   (* data *)
+
+(* [compress equal insignificant dummy m n t] turns the two-dimensional table
+   [t] into a compressed table. The parameter [equal] is equality of data
+   values. The parameter [wildcard] tells which data values are insignificant,
+   and can thus be overwritten with other values. The parameter [dummy] is
+   used to fill holes in the data array. [m] and [n] are the integer
+   dimensions of the table [t]. *)
+
+val compress:
+  ('a -> 'a -> bool) ->
+  ('a -> bool) ->
+  'a ->
+  int -> int ->
+  'a array array ->
+  'a table
+
+(* [get ct i j] returns the value found at indices [i] and [j] in the
+   compressed table [ct]. This function call is permitted only if the
+   value found at indices [i] and [j] in the original table is
+   significant -- otherwise, it could fail abruptly. *)
+
+(* Together, [compress] and [get] have the property that, if the value
+   found at indices [i] and [j] in an uncompressed table [t] is
+   significant, then [get (compress t) i j] is equal to that value. *)
+
+val get:
+  'a table ->
+  int -> int ->
+  'a
+
+(* [getget] is a variant of [get] which only requires read access,
+   via accessors, to the two components of the table. *)
+
+val getget:
+  ('displacement -> int -> int) ->
+  ('data -> int -> 'a) ->
+  'displacement * 'data ->
+  int -> int ->
+  'a
+
+end
+module LinearizedArray : sig
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* An array of arrays (of possibly different lengths!) can be ``linearized'',
+   i.e., encoded as a data array (by concatenating all of the little arrays)
+   and an entry array (which contains offsets into the data array). *)
+
+type 'a t =
+  (* data: *)   'a array *
+  (* entry: *) int array
+
+(* [make a] turns the array of arrays [a] into a linearized array. *)
+
+val make: 'a array array -> 'a t
+
+(* [read la i j] reads the linearized array [la] at indices [i] and [j].
+   Thus, [read (make a) i j] is equivalent to [a.(i).(j)]. *)
+
+val read: 'a t -> int -> int -> 'a
+
+(* [write la i j v] writes the value [v] into the linearized array [la]
+   at indices [i] and [j]. *)
+
+val write: 'a t -> int -> int -> 'a -> unit
+
+(* [length la] is the number of rows of the array [la]. Thus, [length (make
+   a)] is equivalent to [Array.length a]. *)
+
+val length: 'a t -> int
+
+(* [row_length la i] is the length of the row at index [i] in the linearized
+   array [la]. Thus, [row_length (make a) i] is equivalent to [Array.length
+   a.(i)]. *)
+
+val row_length: 'a t -> int -> int
+
+(* [read_row la i] reads the row at index [i], producing a list. Thus,
+   [read_row (make a) i] is equivalent to [Array.to_list a.(i)]. *)
+
+val read_row: 'a t -> int -> 'a list
+
+(* The following variants read the linearized array via accessors
+   [get_data : int -> 'a] and [get_entry : int -> int]. *)
+
+val row_length_via:
+  (* get_entry: *) (int -> int) ->
+  (* i: *)         int ->
+                   int
+
+val read_via:
+  (* get_data: *)  (int -> 'a) ->
+  (* get_entry: *) (int -> int) ->
+  (* i: *)         int ->
+  (* j: *)         int ->
+                   'a
+
+val read_row_via:
+  (* get_data: *)  (int -> 'a) ->
+  (* get_entry: *) (int -> int) ->
+  (* i: *)         int ->
+                   'a list
+
+end
+module TableFormat : sig
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* This signature defines the format of the parse tables. It is used as
+   an argument to [TableInterpreter.Make]. *)
+
+module type TABLES = sig
+
+  (* This is the parser's type of tokens. *)
+
+  type token
+
+  (* This maps a token to its internal (generation-time) integer code. *)
+
+  val token2terminal: token -> int
+
+  (* This is the integer code for the error pseudo-token. *)
+
+  val error_terminal: int
+
+  (* This maps a token to its semantic value. *)
+
+  val token2value: token -> Obj.t
+
+  (* Traditionally, an LR automaton is described by two tables, namely, an
+     action table and a goto table. See, for instance, the Dragon book.
+
+     The action table is a two-dimensional matrix that maps a state and a
+     lookahead token to an action. An action is one of: shift to a certain
+     state, reduce a certain production, accept, or fail.
+
+     The goto table is a two-dimensional matrix that maps a state and a
+     non-terminal symbol to either a state or undefined. By construction, this
+     table is sparse: its undefined entries are never looked up. A compression
+     technique is free to overlap them with other entries.
+
+     In Menhir, things are slightly different. If a state has a default
+     reduction on token [#], then that reduction must be performed without
+     consulting the lookahead token. As a result, we must first determine
+     whether that is the case, before we can obtain a lookahead token and use it
+     as an index in the action table.
+
+     Thus, Menhir's tables are as follows.
+
+     A one-dimensional default reduction table maps a state to either ``no
+     default reduction'' (encoded as: 0) or ``by default, reduce prod''
+     (encoded as: 1 + prod). The action table is looked up only when there
+     is no default reduction. *)
+
+  val default_reduction: PackedIntArray.t
+
+  (* Menhir follows Dencker, Dürre and Heuft, who point out that, although the
+     action table is not sparse by nature (i.e., the error entries are
+     significant), it can be made sparse by first factoring out a binary error
+     matrix, then replacing the error entries in the action table with undefined
+     entries. Thus:
+
+     A two-dimensional error bitmap maps a state and a terminal to either
+     ``fail'' (encoded as: 0) or ``do not fail'' (encoded as: 1). The action
+     table, which is now sparse, is looked up only in the latter case. *)
+
+  (* The error bitmap is flattened into a one-dimensional table; its width is
+     recorded so as to allow indexing. The table is then compressed via
+     [PackedIntArray]. The bit width of the resulting packed array must be
+     [1], so it is not explicitly recorded. *)
+
+  (* The error bitmap does not contain a column for the [#] pseudo-terminal.
+     Thus, its width is [Terminal.n - 1]. We exploit the fact that the integer
+     code assigned to [#] is greatest: the fact that the right-most column
+     in the bitmap is missing does not affect the code for accessing it. *)
+
+  val error: int (* width of the bitmap *) * string (* second component of [PackedIntArray.t] *)
+
+  (* A two-dimensional action table maps a state and a terminal to one of
+     ``shift to state s and discard the current token'' (encoded as: s | 10),
+     ``shift to state s without discarding the current token'' (encoded as: s |
+     11), or ``reduce prod'' (encoded as: prod | 01). *)
+
+  (* The action table is first compressed via [RowDisplacement], then packed
+     via [PackedIntArray]. *)
+
+  (* Like the error bitmap, the action table does not contain a column for the
+     [#] pseudo-terminal. *)
+
+  val action: PackedIntArray.t * PackedIntArray.t
+
+  (* A one-dimensional lhs table maps a production to its left-hand side (a
+     non-terminal symbol). *)
+
+  val lhs: PackedIntArray.t
+
+  (* A two-dimensional goto table maps a state and a non-terminal symbol to
+     either undefined (encoded as: 0) or a new state s (encoded as: 1 + s). *)
+
+  (* The goto table is first compressed via [RowDisplacement], then packed
+     via [PackedIntArray]. *)
+
+  val goto: PackedIntArray.t * PackedIntArray.t
+
+  (* The number of start productions. A production [prod] is a start
+     production if and only if [prod < start] holds. This is also the
+     number of start symbols. A nonterminal symbol [nt] is a start
+     symbol if and only if [nt < start] holds. *)
+
+  val start: int
+
+  (* A one-dimensional semantic action table maps productions to semantic
+     actions. The calling convention for semantic actions is described in
+     [EngineTypes]. This table contains ONLY NON-START PRODUCTIONS, so the
+     indexing is off by [start]. Be careful. *)
+
+  val semantic_action: ((int, Obj.t, token) EngineTypes.env ->
+                        (int, Obj.t)        EngineTypes.stack) array
+
+  (* The parser defines its own [Error] exception. This exception can be
+     raised by semantic actions and caught by the engine, and raised by the
+     engine towards the final user. *)
+
+  exception Error
+
+  (* The parser indicates whether to generate a trace. Generating a
+     trace requires two extra tables, which respectively map a
+     terminal symbol and a production to a string. *)
+
+  val trace: (string array * string array) option
+
+end
+end
+module InspectionTableFormat : sig
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* This signature defines the format of the tables that are produced (in
+   addition to the tables described in [TableFormat]) when the command line
+   switch [--inspection] is enabled. It is used as an argument to
+   [InspectionTableInterpreter.Make]. *)
+
+module type TABLES = sig
+
+  (* The types of symbols. *)
+
+  include IncrementalEngine.SYMBOLS
+
+  (* The type ['a lr1state] describes an LR(1) state. The generated parser defines
+     it internally as [int]. *)
+
+  type 'a lr1state
+
+  (* Some of the tables that follow use encodings of (terminal and
+     nonterminal) symbols as integers. So, we need functions that
+     map the integer encoding of a symbol to its algebraic encoding. *)
+
+  val    terminal: int -> xsymbol
+  val nonterminal: int -> xsymbol
+
+  (* The left-hand side of every production already appears in the
+     signature [TableFormat.TABLES], so we need not repeat it here. *)
+
+  (* The right-hand side of every production. This a linearized array
+     of arrays of integers, whose [data] and [entry] components have
+     been packed. The encoding of symbols as integers in described in
+     [TableBackend]. *)
+
+  val rhs: PackedIntArray.t * PackedIntArray.t
+
+  (* A mapping of every (non-initial) state to its LR(0) core. *)
+
+  val lr0_core: PackedIntArray.t
+
+  (* A mapping of every LR(0) state to its set of LR(0) items. Each item is
+     represented in its packed form (see [Item]) as an integer. Thus the
+     mapping is an array of arrays of integers, which is linearized and
+     packed, like [rhs]. *)
+
+  val lr0_items: PackedIntArray.t * PackedIntArray.t
+
+  (* A mapping of every LR(0) state to its incoming symbol, if it has one. *)
+
+  val lr0_incoming: PackedIntArray.t
+
+  (* A table that tells which non-terminal symbols are nullable. *)
+
+  val nullable: string
+    (* This is a packed int array of bit width 1. It can be read
+       using [PackedIntArray.get1]. *)
+
+  (* A two-table dimensional table, indexed by a nonterminal symbol and
+     by a terminal symbol (other than [#]), encodes the FIRST sets. *)
+
+  val first: int (* width of the bitmap *) * string (* second component of [PackedIntArray.t] *)
+
+end
+
+end
+module InspectionTableInterpreter : sig
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* This functor is invoked inside the generated parser, in [--table] mode. It
+   produces no code! It simply constructs the types [symbol] and [xsymbol] on
+   top of the generated types [terminal] and [nonterminal]. *)
+
+module Symbols (T : sig
+
+  type 'a terminal
+  type 'a nonterminal
+
+end)
+
+: IncrementalEngine.SYMBOLS
+  with type 'a terminal := 'a T.terminal
+   and type 'a nonterminal := 'a T.nonterminal
+
+(* This functor is invoked inside the generated parser, in [--table] mode. It
+   constructs the inspection API on top of the inspection tables described in
+   [InspectionTableFormat]. *)
+
+module Make
+  (TT : TableFormat.TABLES)
+  (IT : InspectionTableFormat.TABLES
+        with type 'a lr1state = int)
+  (ET : EngineTypes.TABLE
+        with type terminal = int
+         and type nonterminal = int
+         and type semantic_value = Obj.t)
+  (E : sig
+     type 'a env = (ET.state, ET.semantic_value, ET.token) EngineTypes.env
+   end)
+
+: IncrementalEngine.INSPECTION
+  with type 'a terminal := 'a IT.terminal
+   and type 'a nonterminal := 'a IT.nonterminal
+   and type 'a lr1state := 'a IT.lr1state
+   and type production := int
+   and type 'a env := 'a E.env
+end
+module TableInterpreter : sig
+(******************************************************************************)
+(*                                                                            *)
+(*                                   Menhir                                   *)
+(*                                                                            *)
+(*                       François Pottier, Inria Paris                        *)
+(*              Yann Régis-Gianas, PPS, Université Paris Diderot              *)
+(*                                                                            *)
+(*  Copyright Inria. All rights reserved. This file is distributed under the  *)
+(*  terms of the GNU Library General Public License version 2, with a         *)
+(*  special exception on linking, as described in the file LICENSE.           *)
+(*                                                                            *)
+(******************************************************************************)
+
+(* This module provides a thin decoding layer for the generated tables, thus
+   providing an API that is suitable for use by [Engine.Make]. It is part of
+   [MenhirLib]. *)
+
+(* The exception [Error] is declared within the generated parser. This is
+   preferable to pre-declaring it here, as it ensures that each parser gets
+   its own, distinct [Error] exception. This is consistent with the code-based
+   back-end. *)
+
+(* This functor is invoked by the generated parser. *)
+
+module MakeEngineTable
+  (T : TableFormat.TABLES)
+: EngineTypes.TABLE
+    with type state = int
+     and type token = T.token
+     and type semantic_value = Obj.t
+     and type production = int
+     and type terminal = int
+     and type nonterminal = int
+end
+module StaticVersion : sig
+val require_20181113 : unit
+end
diff --git a/boot/menhir/parser.ml b/boot/menhir/parser.ml
new file mode 100644
index 00000000..9f3d4f6d
--- /dev/null
+++ b/boot/menhir/parser.ml
@@ -0,0 +1,45873 @@
+
+(* This generated code requires the following version of MenhirLib: *)
+
+let () =
+  MenhirLib.StaticVersion.require_20181113
+
+module MenhirBasics = struct
+  
+  exception Error = Parsing.Parse_error
+  
+  type token = 
+    | WITH
+    | WHILE
+    | WHEN
+    | VIRTUAL
+    | VAL
+    | UNDERSCORE
+    | UIDENT of (
+# 666 "parsing/parser.mly"
+       (string)
+# 22 "parsing/parser.ml"
+  )
+    | TYPE
+    | TRY
+    | TRUE
+    | TO
+    | TILDE
+    | THEN
+    | STRUCT
+    | STRING of (
+# 658 "parsing/parser.mly"
+       (string * string option)
+# 34 "parsing/parser.ml"
+  )
+    | STAR
+    | SIG
+    | SEMISEMI
+    | SEMI
+    | RPAREN
+    | REC
+    | RBRACKET
+    | RBRACE
+    | QUOTE
+    | QUESTION
+    | PRIVATE
+    | PREFIXOP of (
+# 644 "parsing/parser.mly"
+       (string)
+# 50 "parsing/parser.ml"
+  )
+    | PLUSEQ
+    | PLUSDOT
+    | PLUS
+    | PERCENT
+    | OR
+    | OPTLABEL of (
+# 637 "parsing/parser.mly"
+       (string)
+# 60 "parsing/parser.ml"
+  )
+    | OPEN
+    | OF
+    | OBJECT
+    | NONREC
+    | NEW
+    | MUTABLE
+    | MODULE
+    | MINUSGREATER
+    | MINUSDOT
+    | MINUS
+    | METHOD
+    | MATCH
+    | LPAREN
+    | LIDENT of (
+# 620 "parsing/parser.mly"
+       (string)
+# 78 "parsing/parser.ml"
+  )
+    | LETOP of (
+# 602 "parsing/parser.mly"
+       (string)
+# 83 "parsing/parser.ml"
+  )
+    | LET
+    | LESSMINUS
+    | LESS
+    | LBRACKETPERCENTPERCENT
+    | LBRACKETPERCENT
+    | LBRACKETLESS
+    | LBRACKETGREATER
+    | LBRACKETBAR
+    | LBRACKETATATAT
+    | LBRACKETATAT
+    | LBRACKETAT
+    | LBRACKET
+    | LBRACELESS
+    | LBRACE
+    | LAZY
+    | LABEL of (
+# 607 "parsing/parser.mly"
+       (string)
+# 103 "parsing/parser.ml"
+  )
+    | INT of (
+# 606 "parsing/parser.mly"
+       (string * char option)
+# 108 "parsing/parser.ml"
+  )
+    | INITIALIZER
+    | INHERIT
+    | INFIXOP4 of (
+# 600 "parsing/parser.mly"
+       (string)
+# 115 "parsing/parser.ml"
+  )
+    | INFIXOP3 of (
+# 599 "parsing/parser.mly"
+       (string)
+# 120 "parsing/parser.ml"
+  )
+    | INFIXOP2 of (
+# 598 "parsing/parser.mly"
+       (string)
+# 125 "parsing/parser.ml"
+  )
+    | INFIXOP1 of (
+# 597 "parsing/parser.mly"
+       (string)
+# 130 "parsing/parser.ml"
+  )
+    | INFIXOP0 of (
+# 596 "parsing/parser.mly"
+       (string)
+# 135 "parsing/parser.ml"
+  )
+    | INCLUDE
+    | IN
+    | IF
+    | HASHOP of (
+# 655 "parsing/parser.mly"
+       (string)
+# 143 "parsing/parser.ml"
+  )
+    | HASH
+    | GREATERRBRACKET
+    | GREATERRBRACE
+    | GREATER
+    | FUNCTOR
+    | FUNCTION
+    | FUN
+    | FOR
+    | FLOAT of (
+# 585 "parsing/parser.mly"
+       (string * char option)
+# 156 "parsing/parser.ml"
+  )
+    | FALSE
+    | EXTERNAL
+    | EXCEPTION
+    | EQUAL
+    | EOL
+    | EOF
+    | END
+    | ELSE
+    | DOWNTO
+    | DOTOP of (
+# 601 "parsing/parser.mly"
+       (string)
+# 170 "parsing/parser.ml"
+  )
+    | DOTDOT
+    | DOT
+    | DONE
+    | DOCSTRING of (
+# 674 "parsing/parser.mly"
+       (Docstrings.docstring)
+# 178 "parsing/parser.ml"
+  )
+    | DO
+    | CONSTRAINT
+    | COMMENT of (
+# 673 "parsing/parser.mly"
+       (string * Location.t)
+# 185 "parsing/parser.ml"
+  )
+    | COMMA
+    | COLONGREATER
+    | COLONEQUAL
+    | COLONCOLON
+    | COLON
+    | CLASS
+    | CHAR of (
+# 565 "parsing/parser.mly"
+       (char)
+# 196 "parsing/parser.ml"
+  )
+    | BEGIN
+    | BARRBRACKET
+    | BARBAR
+    | BAR
+    | BANG
+    | BACKQUOTE
+    | ASSERT
+    | AS
+    | ANDOP of (
+# 603 "parsing/parser.mly"
+       (string)
+# 209 "parsing/parser.ml"
+  )
+    | AND
+    | AMPERSAND
+    | AMPERAMPER
+  
+end
+
+include MenhirBasics
+
+let _eRR =
+  MenhirBasics.Error
+
+# 18 "parsing/parser.mly"
+  
+
+open Asttypes
+open Longident
+open Parsetree
+open Ast_helper
+open Docstrings
+open Docstrings.WithMenhir
+
+let mkloc = Location.mkloc
+let mknoloc = Location.mknoloc
+
+let make_loc (startpos, endpos) = {
+  Location.loc_start = startpos;
+  Location.loc_end = endpos;
+  Location.loc_ghost = false;
+}
+
+let ghost_loc (startpos, endpos) = {
+  Location.loc_start = startpos;
+  Location.loc_end = endpos;
+  Location.loc_ghost = true;
+}
+
+let mktyp ~loc d = Typ.mk ~loc:(make_loc loc) d
+let mkpat ~loc d = Pat.mk ~loc:(make_loc loc) d
+let mkexp ~loc d = Exp.mk ~loc:(make_loc loc) d
+let mkmty ~loc ?attrs d = Mty.mk ~loc:(make_loc loc) ?attrs d
+let mksig ~loc d = Sig.mk ~loc:(make_loc loc) d
+let mkmod ~loc ?attrs d = Mod.mk ~loc:(make_loc loc) ?attrs d
+let mkstr ~loc d = Str.mk ~loc:(make_loc loc) d
+let mkclass ~loc ?attrs d = Cl.mk ~loc:(make_loc loc) ?attrs d
+let mkcty ~loc ?attrs d = Cty.mk ~loc:(make_loc loc) ?attrs d
+
+let pstr_typext (te, ext) =
+  (Pstr_typext te, ext)
+let pstr_primitive (vd, ext) =
+  (Pstr_primitive vd, ext)
+let pstr_type ((nr, ext), tys) =
+  (Pstr_type (nr, tys), ext)
+let pstr_exception (te, ext) =
+  (Pstr_exception te, ext)
+let pstr_include (body, ext) =
+  (Pstr_include body, ext)
+let pstr_recmodule (ext, bindings) =
+  (Pstr_recmodule bindings, ext)
+
+let psig_typext (te, ext) =
+  (Psig_typext te, ext)
+let psig_value (vd, ext) =
+  (Psig_value vd, ext)
+let psig_type ((nr, ext), tys) =
+  (Psig_type (nr, tys), ext)
+let psig_typesubst ((nr, ext), tys) =
+  assert (nr = Recursive); (* see [no_nonrec_flag] *)
+  (Psig_typesubst tys, ext)
+let psig_exception (te, ext) =
+  (Psig_exception te, ext)
+let psig_include (body, ext) =
+  (Psig_include body, ext)
+
+let mkctf ~loc ?attrs ?docs d =
+  Ctf.mk ~loc:(make_loc loc) ?attrs ?docs d
+let mkcf ~loc ?attrs ?docs d =
+  Cf.mk ~loc:(make_loc loc) ?attrs ?docs d
+
+let mkrhs rhs loc = mkloc rhs (make_loc loc)
+let ghrhs rhs loc = mkloc rhs (ghost_loc loc)
+
+let push_loc x acc =
+  if x.Location.loc_ghost
+  then acc
+  else x :: acc
+
+let reloc_pat ~loc x =
+  { x with ppat_loc = make_loc loc;
+           ppat_loc_stack = push_loc x.ppat_loc x.ppat_loc_stack };;
+let reloc_exp ~loc x =
+  { x with pexp_loc = make_loc loc;
+           pexp_loc_stack = push_loc x.pexp_loc x.pexp_loc_stack };;
+let reloc_typ ~loc x =
+  { x with ptyp_loc = make_loc loc;
+           ptyp_loc_stack = push_loc x.ptyp_loc x.ptyp_loc_stack };;
+
+let mkexpvar ~loc (name : string) =
+  mkexp ~loc (Pexp_ident(mkrhs (Lident name) loc))
+
+let mkoperator =
+  mkexpvar
+
+let mkpatvar ~loc name =
+  mkpat ~loc (Ppat_var (mkrhs name loc))
+
+(*
+  Ghost expressions and patterns:
+  expressions and patterns that do not appear explicitly in the
+  source file they have the loc_ghost flag set to true.
+  Then the profiler will not try to instrument them and the
+  -annot option will not try to display their type.
+
+  Every grammar rule that generates an element with a location must
+  make at most one non-ghost element, the topmost one.
+
+  How to tell whether your location must be ghost:
+  A location corresponds to a range of characters in the source file.
+  If the location contains a piece of code that is syntactically
+  valid (according to the documentation), and corresponds to the
+  AST node, then the location must be real; in all other cases,
+  it must be ghost.
+*)
+let ghexp ~loc d = Exp.mk ~loc:(ghost_loc loc) d
+let ghpat ~loc d = Pat.mk ~loc:(ghost_loc loc) d
+let ghtyp ~loc d = Typ.mk ~loc:(ghost_loc loc) d
+let ghloc ~loc d = { txt = d; loc = ghost_loc loc }
+let ghstr ~loc d = Str.mk ~loc:(ghost_loc loc) d
+let ghsig ~loc d = Sig.mk ~loc:(ghost_loc loc) d
+
+let mkinfix arg1 op arg2 =
+  Pexp_apply(op, [Nolabel, arg1; Nolabel, arg2])
+
+let neg_string f =
+  if String.length f > 0 && f.[0] = '-'
+  then String.sub f 1 (String.length f - 1)
+  else "-" ^ f
+
+let mkuminus ~oploc name arg =
+  match name, arg.pexp_desc with
+  | "-", Pexp_constant(Pconst_integer (n,m)) ->
+      Pexp_constant(Pconst_integer(neg_string n,m))
+  | ("-" | "-."), Pexp_constant(Pconst_float (f, m)) ->
+      Pexp_constant(Pconst_float(neg_string f, m))
+  | _ ->
+      Pexp_apply(mkoperator ~loc:oploc ("~" ^ name), [Nolabel, arg])
+
+let mkuplus ~oploc name arg =
+  let desc = arg.pexp_desc in
+  match name, desc with
+  | "+", Pexp_constant(Pconst_integer _)
+  | ("+" | "+."), Pexp_constant(Pconst_float _) -> desc
+  | _ ->
+      Pexp_apply(mkoperator ~loc:oploc ("~" ^ name), [Nolabel, arg])
+
+(* TODO define an abstraction boundary between locations-as-pairs
+   and locations-as-Location.t; it should be clear when we move from
+   one world to the other *)
+
+let mkexp_cons_desc consloc args =
+  Pexp_construct(mkrhs (Lident "::") consloc, Some args)
+let mkexp_cons ~loc consloc args =
+  mkexp ~loc (mkexp_cons_desc consloc args)
+
+let mkpat_cons_desc consloc args =
+  Ppat_construct(mkrhs (Lident "::") consloc, Some args)
+let mkpat_cons ~loc consloc args =
+  mkpat ~loc (mkpat_cons_desc consloc args)
+
+let ghexp_cons_desc consloc args =
+  Pexp_construct(ghrhs (Lident "::") consloc, Some args)
+let ghpat_cons_desc consloc args =
+  Ppat_construct(ghrhs (Lident "::") consloc, Some args)
+
+let rec mktailexp nilloc = let open Location in function
+    [] ->
+      let nil = ghloc ~loc:nilloc (Lident "[]") in
+      Pexp_construct (nil, None), nilloc
+  | e1 :: el ->
+      let exp_el, el_loc = mktailexp nilloc el in
+      let loc = (e1.pexp_loc.loc_start, snd el_loc) in
+      let arg = ghexp ~loc (Pexp_tuple [e1; ghexp ~loc:el_loc exp_el]) in
+      ghexp_cons_desc loc arg, loc
+
+let rec mktailpat nilloc = let open Location in function
+    [] ->
+      let nil = ghloc ~loc:nilloc (Lident "[]") in
+      Ppat_construct (nil, None), nilloc
+  | p1 :: pl ->
+      let pat_pl, el_loc = mktailpat nilloc pl in
+      let loc = (p1.ppat_loc.loc_start, snd el_loc) in
+      let arg = ghpat ~loc (Ppat_tuple [p1; ghpat ~loc:el_loc pat_pl]) in
+      ghpat_cons_desc loc arg, loc
+
+let mkstrexp e attrs =
+  { pstr_desc = Pstr_eval (e, attrs); pstr_loc = e.pexp_loc }
+
+let mkexp_constraint ~loc e (t1, t2) =
+  match t1, t2 with
+  | Some t, None -> ghexp ~loc (Pexp_constraint(e, t))
+  | _, Some t -> ghexp ~loc (Pexp_coerce(e, t1, t))
+  | None, None -> assert false
+
+let mkexp_opt_constraint ~loc e = function
+  | None -> e
+  | Some constraint_ -> mkexp_constraint ~loc e constraint_
+
+let mkpat_opt_constraint ~loc p = function
+  | None -> p
+  | Some typ -> mkpat ~loc (Ppat_constraint(p, typ))
+
+let syntax_error () =
+  raise Syntaxerr.Escape_error
+
+let unclosed opening_name opening_loc closing_name closing_loc =
+  raise(Syntaxerr.Error(Syntaxerr.Unclosed(make_loc opening_loc, opening_name,
+                                           make_loc closing_loc, closing_name)))
+
+let expecting loc nonterm =
+    raise Syntaxerr.(Error(Expecting(make_loc loc, nonterm)))
+
+let not_expecting loc nonterm =
+    raise Syntaxerr.(Error(Not_expecting(make_loc loc, nonterm)))
+
+let dotop_fun ~loc dotop =
+  (* We could use ghexp here, but sticking to mkexp for parser.mly
+     compatibility. TODO improve parser.mly *)
+  mkexp ~loc (Pexp_ident (ghloc ~loc dotop))
+
+let array_function ~loc str name =
+  ghloc ~loc (Ldot(Lident str,
+                   (if !Clflags.unsafe then "unsafe_" ^ name else name)))
+
+let array_get_fun ~loc =
+  ghexp ~loc (Pexp_ident(array_function ~loc "Array" "get"))
+let string_get_fun ~loc =
+  ghexp ~loc (Pexp_ident(array_function ~loc "String" "get"))
+
+let array_set_fun ~loc =
+  ghexp ~loc (Pexp_ident(array_function ~loc "Array" "set"))
+let string_set_fun ~loc =
+  ghexp ~loc (Pexp_ident(array_function ~loc "String" "set"))
+
+let index_get ~loc get_fun array index =
+  let args = [Nolabel, array; Nolabel, index] in
+   mkexp ~loc (Pexp_apply(get_fun, args))
+
+let index_set ~loc set_fun array index value =
+  let args = [Nolabel, array; Nolabel, index; Nolabel, value] in
+   mkexp ~loc (Pexp_apply(set_fun, args))
+
+let array_get ~loc = index_get ~loc (array_get_fun ~loc)
+let string_get ~loc = index_get ~loc (string_get_fun ~loc)
+let dotop_get ~loc dotop = index_get ~loc (dotop_fun ~loc dotop)
+
+let array_set ~loc = index_set ~loc (array_set_fun ~loc)
+let string_set ~loc = index_set ~loc (string_set_fun ~loc)
+let dotop_set ~loc dotop = index_set ~loc (dotop_fun ~loc dotop)
+
+let bigarray_function ~loc str name =
+  ghloc ~loc (Ldot(Ldot(Lident "Bigarray", str), name))
+
+let bigarray_untuplify = function
+    { pexp_desc = Pexp_tuple explist; pexp_loc = _ } -> explist
+  | exp -> [exp]
+
+let bigarray_get ~loc arr arg =
+  let mkexp, ghexp = mkexp ~loc, ghexp ~loc in
+  let bigarray_function = bigarray_function ~loc in
+  let get = if !Clflags.unsafe then "unsafe_get" else "get" in
+  match bigarray_untuplify arg with
+    [c1] ->
+      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array1" get)),
+                       [Nolabel, arr; Nolabel, c1]))
+  | [c1;c2] ->
+      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array2" get)),
+                       [Nolabel, arr; Nolabel, c1; Nolabel, c2]))
+  | [c1;c2;c3] ->
+      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array3" get)),
+                       [Nolabel, arr; Nolabel, c1; Nolabel, c2; Nolabel, c3]))
+  | coords ->
+      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Genarray" "get")),
+                       [Nolabel, arr; Nolabel, ghexp(Pexp_array coords)]))
+
+let bigarray_set ~loc arr arg newval =
+  let mkexp, ghexp = mkexp ~loc, ghexp ~loc in
+  let bigarray_function = bigarray_function ~loc in
+  let set = if !Clflags.unsafe then "unsafe_set" else "set" in
+  match bigarray_untuplify arg with
+    [c1] ->
+      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array1" set)),
+                       [Nolabel, arr; Nolabel, c1; Nolabel, newval]))
+  | [c1;c2] ->
+      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array2" set)),
+                       [Nolabel, arr; Nolabel, c1;
+                        Nolabel, c2; Nolabel, newval]))
+  | [c1;c2;c3] ->
+      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array3" set)),
+                       [Nolabel, arr; Nolabel, c1;
+                        Nolabel, c2; Nolabel, c3; Nolabel, newval]))
+  | coords ->
+      mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Genarray" "set")),
+                       [Nolabel, arr;
+                        Nolabel, ghexp(Pexp_array coords);
+                        Nolabel, newval]))
+
+let lapply ~loc p1 p2 =
+  if !Clflags.applicative_functors
+  then Lapply(p1, p2)
+  else raise (Syntaxerr.Error(
+                  Syntaxerr.Applicative_path (make_loc loc)))
+
+let exp_of_longident ~loc lid =
+  mkexp ~loc (Pexp_ident {lid with txt = Lident(Longident.last lid.txt)})
+
+(* [loc_map] could be [Location.map]. *)
+let loc_map (f : 'a -> 'b) (x : 'a Location.loc) : 'b Location.loc =
+  { x with txt = f x.txt }
+
+let loc_last (id : Longident.t Location.loc) : string Location.loc =
+  loc_map Longident.last id
+
+let loc_lident (id : string Location.loc) : Longident.t Location.loc =
+  loc_map (fun x -> Lident x) id
+
+let exp_of_label ~loc lbl =
+  mkexp ~loc (Pexp_ident (loc_lident lbl))
+
+let pat_of_label ~loc lbl =
+  mkpat ~loc (Ppat_var (loc_last lbl))
+
+let mk_newtypes ~loc newtypes exp =
+  let mkexp = mkexp ~loc in
+  List.fold_right (fun newtype exp -> mkexp (Pexp_newtype (newtype, exp)))
+    newtypes exp
+
+let wrap_type_annotation ~loc newtypes core_type body =
+  let mkexp, ghtyp = mkexp ~loc, ghtyp ~loc in
+  let mk_newtypes = mk_newtypes ~loc in
+  let exp = mkexp(Pexp_constraint(body,core_type)) in
+  let exp = mk_newtypes newtypes exp in
+  (exp, ghtyp(Ptyp_poly(newtypes, Typ.varify_constructors newtypes core_type)))
+
+let wrap_exp_attrs ~loc body (ext, attrs) =
+  let ghexp = ghexp ~loc in
+  (* todo: keep exact location for the entire attribute *)
+  let body = {body with pexp_attributes = attrs @ body.pexp_attributes} in
+  match ext with
+  | None -> body
+  | Some id -> ghexp(Pexp_extension (id, PStr [mkstrexp body []]))
+
+let mkexp_attrs ~loc d attrs =
+  wrap_exp_attrs ~loc (mkexp ~loc d) attrs
+
+let wrap_typ_attrs ~loc typ (ext, attrs) =
+  (* todo: keep exact location for the entire attribute *)
+  let typ = {typ with ptyp_attributes = attrs @ typ.ptyp_attributes} in
+  match ext with
+  | None -> typ
+  | Some id -> ghtyp ~loc (Ptyp_extension (id, PTyp typ))
+
+let wrap_pat_attrs ~loc pat (ext, attrs) =
+  (* todo: keep exact location for the entire attribute *)
+  let pat = {pat with ppat_attributes = attrs @ pat.ppat_attributes} in
+  match ext with
+  | None -> pat
+  | Some id -> ghpat ~loc (Ppat_extension (id, PPat (pat, None)))
+
+let mkpat_attrs ~loc d attrs =
+  wrap_pat_attrs ~loc (mkpat ~loc d) attrs
+
+let wrap_class_attrs ~loc:_ body attrs =
+  {body with pcl_attributes = attrs @ body.pcl_attributes}
+let wrap_mod_attrs ~loc:_ attrs body =
+  {body with pmod_attributes = attrs @ body.pmod_attributes}
+let wrap_mty_attrs ~loc:_ attrs body =
+  {body with pmty_attributes = attrs @ body.pmty_attributes}
+
+let wrap_str_ext ~loc body ext =
+  match ext with
+  | None -> body
+  | Some id -> ghstr ~loc (Pstr_extension ((id, PStr [body]), []))
+
+let wrap_mkstr_ext ~loc (item, ext) =
+  wrap_str_ext ~loc (mkstr ~loc item) ext
+
+let wrap_sig_ext ~loc body ext =
+  match ext with
+  | None -> body
+  | Some id -> ghsig ~loc (Psig_extension ((id, PSig [body]), []))
+
+let wrap_mksig_ext ~loc (item, ext) =
+  wrap_sig_ext ~loc (mksig ~loc item) ext
+
+let text_str pos = Str.text (rhs_text pos)
+let text_sig pos = Sig.text (rhs_text pos)
+let text_cstr pos = Cf.text (rhs_text pos)
+let text_csig pos = Ctf.text (rhs_text pos)
+let text_def pos = [Ptop_def (Str.text (rhs_text pos))]
+
+let extra_text startpos endpos text items =
+  match items with
+  | [] ->
+      let post = rhs_post_text endpos in
+      let post_extras = rhs_post_extra_text endpos in
+      text post @ text post_extras
+  | _ :: _ ->
+      let pre_extras = rhs_pre_extra_text startpos in
+      let post_extras = rhs_post_extra_text endpos in
+        text pre_extras @ items @ text post_extras
+
+let extra_str p1 p2 items = extra_text p1 p2 Str.text items
+let extra_sig p1 p2 items = extra_text p1 p2 Sig.text items
+let extra_cstr p1 p2 items = extra_text p1 p2 Cf.text items
+let extra_csig p1 p2 items = extra_text p1 p2 Ctf.text  items
+let extra_def p1 p2 items =
+  extra_text p1 p2 (fun txt -> [Ptop_def (Str.text txt)]) items
+
+let extra_rhs_core_type ct ~pos =
+  let docs = rhs_info pos in
+  { ct with ptyp_attributes = add_info_attrs docs ct.ptyp_attributes }
+
+type let_binding =
+  { lb_pattern: pattern;
+    lb_expression: expression;
+    lb_attributes: attributes;
+    lb_docs: docs Lazy.t;
+    lb_text: text Lazy.t;
+    lb_loc: Location.t; }
+
+type let_bindings =
+  { lbs_bindings: let_binding list;
+    lbs_rec: rec_flag;
+    lbs_extension: string Asttypes.loc option;
+    lbs_loc: Location.t }
+
+let mklb first ~loc (p, e) attrs =
+  {
+    lb_pattern = p;
+    lb_expression = e;
+    lb_attributes = attrs;
+    lb_docs = symbol_docs_lazy loc;
+    lb_text = (if first then empty_text_lazy
+               else symbol_text_lazy (fst loc));
+    lb_loc = make_loc loc;
+  }
+
+let mklbs ~loc ext rf lb =
+  {
+    lbs_bindings = [lb];
+    lbs_rec = rf;
+    lbs_extension = ext ;
+    lbs_loc = make_loc loc;
+  }
+
+let addlb lbs lb =
+  { lbs with lbs_bindings = lb :: lbs.lbs_bindings }
+
+let val_of_let_bindings ~loc lbs =
+  let bindings =
+    List.map
+      (fun lb ->
+         Vb.mk ~loc:lb.lb_loc ~attrs:lb.lb_attributes
+           ~docs:(Lazy.force lb.lb_docs)
+           ~text:(Lazy.force lb.lb_text)
+           lb.lb_pattern lb.lb_expression)
+      lbs.lbs_bindings
+  in
+  let str = mkstr ~loc (Pstr_value(lbs.lbs_rec, List.rev bindings)) in
+  match lbs.lbs_extension with
+  | None -> str
+  | Some id -> ghstr ~loc (Pstr_extension((id, PStr [str]), []))
+
+let expr_of_let_bindings ~loc lbs body =
+  let bindings =
+    List.map
+      (fun lb ->
+         Vb.mk ~loc:lb.lb_loc ~attrs:lb.lb_attributes
+           lb.lb_pattern lb.lb_expression)
+      lbs.lbs_bindings
+  in
+    mkexp_attrs ~loc (Pexp_let(lbs.lbs_rec, List.rev bindings, body))
+      (lbs.lbs_extension, [])
+
+let class_of_let_bindings ~loc lbs body =
+  let bindings =
+    List.map
+      (fun lb ->
+         Vb.mk ~loc:lb.lb_loc ~attrs:lb.lb_attributes
+           lb.lb_pattern lb.lb_expression)
+      lbs.lbs_bindings
+  in
+    (* Our use of let_bindings(no_ext) guarantees the following: *)
+    assert (lbs.lbs_extension = None);
+    mkclass ~loc (Pcl_let (lbs.lbs_rec, List.rev bindings, body))
+
+(* Alternatively, we could keep the generic module type in the Parsetree
+   and extract the package type during type-checking. In that case,
+   the assertions below should be turned into explicit checks. *)
+let package_type_of_module_type pmty =
+  let err loc s =
+    raise (Syntaxerr.Error (Syntaxerr.Invalid_package_type (loc, s)))
+  in
+  let map_cstr = function
+    | Pwith_type (lid, ptyp) ->
+        let loc = ptyp.ptype_loc in
+        if ptyp.ptype_params <> [] then
+          err loc "parametrized types are not supported";
+        if ptyp.ptype_cstrs <> [] then
+          err loc "constrained types are not supported";
+        if ptyp.ptype_private <> Public then
+          err loc "private types are not supported";
+
+        (* restrictions below are checked by the 'with_constraint' rule *)
+        assert (ptyp.ptype_kind = Ptype_abstract);
+        assert (ptyp.ptype_attributes = []);
+        let ty =
+          match ptyp.ptype_manifest with
+          | Some ty -> ty
+          | None -> assert false
+        in
+        (lid, ty)
+    | _ ->
+        err pmty.pmty_loc "only 'with type t =' constraints are supported"
+  in
+  match pmty with
+  | {pmty_desc = Pmty_ident lid} -> (lid, [])
+  | {pmty_desc = Pmty_with({pmty_desc = Pmty_ident lid}, cstrs)} ->
+      (lid, List.map map_cstr cstrs)
+  | _ ->
+      err pmty.pmty_loc
+        "only module type identifier and 'with type' constraints are supported"
+
+let mk_directive_arg ~loc k =
+  { pdira_desc = k;
+    pdira_loc = make_loc loc;
+  }
+
+let mk_directive ~loc name arg =
+  Ptop_dir {
+      pdir_name = name;
+      pdir_arg = arg;
+      pdir_loc = make_loc loc;
+    }
+
+
+# 756 "parsing/parser.ml"
+
+module Tables = struct
+  
+  include MenhirBasics
+  
+  let token2terminal : token -> int =
+    fun _tok ->
+      match _tok with
+      | AMPERAMPER ->
+          121
+      | AMPERSAND ->
+          120
+      | AND ->
+          119
+      | ANDOP _ ->
+          118
+      | AS ->
+          117
+      | ASSERT ->
+          116
+      | BACKQUOTE ->
+          115
+      | BANG ->
+          114
+      | BAR ->
+          113
+      | BARBAR ->
+          112
+      | BARRBRACKET ->
+          111
+      | BEGIN ->
+          110
+      | CHAR _ ->
+          109
+      | CLASS ->
+          108
+      | COLON ->
+          107
+      | COLONCOLON ->
+          106
+      | COLONEQUAL ->
+          105
+      | COLONGREATER ->
+          104
+      | COMMA ->
+          103
+      | COMMENT _ ->
+          102
+      | CONSTRAINT ->
+          101
+      | DO ->
+          100
+      | DOCSTRING _ ->
+          99
+      | DONE ->
+          98
+      | DOT ->
+          97
+      | DOTDOT ->
+          96
+      | DOTOP _ ->
+          95
+      | DOWNTO ->
+          94
+      | ELSE ->
+          93
+      | END ->
+          92
+      | EOF ->
+          91
+      | EOL ->
+          90
+      | EQUAL ->
+          89
+      | EXCEPTION ->
+          88
+      | EXTERNAL ->
+          87
+      | FALSE ->
+          86
+      | FLOAT _ ->
+          85
+      | FOR ->
+          84
+      | FUN ->
+          83
+      | FUNCTION ->
+          82
+      | FUNCTOR ->
+          81
+      | GREATER ->
+          80
+      | GREATERRBRACE ->
+          79
+      | GREATERRBRACKET ->
+          78
+      | HASH ->
+          77
+      | HASHOP _ ->
+          76
+      | IF ->
+          75
+      | IN ->
+          74
+      | INCLUDE ->
+          73
+      | INFIXOP0 _ ->
+          72
+      | INFIXOP1 _ ->
+          71
+      | INFIXOP2 _ ->
+          70
+      | INFIXOP3 _ ->
+          69
+      | INFIXOP4 _ ->
+          68
+      | INHERIT ->
+          67
+      | INITIALIZER ->
+          66
+      | INT _ ->
+          65
+      | LABEL _ ->
+          64
+      | LAZY ->
+          63
+      | LBRACE ->
+          62
+      | LBRACELESS ->
+          61
+      | LBRACKET ->
+          60
+      | LBRACKETAT ->
+          59
+      | LBRACKETATAT ->
+          58
+      | LBRACKETATATAT ->
+          57
+      | LBRACKETBAR ->
+          56
+      | LBRACKETGREATER ->
+          55
+      | LBRACKETLESS ->
+          54
+      | LBRACKETPERCENT ->
+          53
+      | LBRACKETPERCENTPERCENT ->
+          52
+      | LESS ->
+          51
+      | LESSMINUS ->
+          50
+      | LET ->
+          49
+      | LETOP _ ->
+          48
+      | LIDENT _ ->
+          47
+      | LPAREN ->
+          46
+      | MATCH ->
+          45
+      | METHOD ->
+          44
+      | MINUS ->
+          43
+      | MINUSDOT ->
+          42
+      | MINUSGREATER ->
+          41
+      | MODULE ->
+          40
+      | MUTABLE ->
+          39
+      | NEW ->
+          38
+      | NONREC ->
+          37
+      | OBJECT ->
+          36
+      | OF ->
+          35
+      | OPEN ->
+          34
+      | OPTLABEL _ ->
+          33
+      | OR ->
+          32
+      | PERCENT ->
+          31
+      | PLUS ->
+          30
+      | PLUSDOT ->
+          29
+      | PLUSEQ ->
+          28
+      | PREFIXOP _ ->
+          27
+      | PRIVATE ->
+          26
+      | QUESTION ->
+          25
+      | QUOTE ->
+          24
+      | RBRACE ->
+          23
+      | RBRACKET ->
+          22
+      | REC ->
+          21
+      | RPAREN ->
+          20
+      | SEMI ->
+          19
+      | SEMISEMI ->
+          18
+      | SIG ->
+          17
+      | STAR ->
+          16
+      | STRING _ ->
+          15
+      | STRUCT ->
+          14
+      | THEN ->
+          13
+      | TILDE ->
+          12
+      | TO ->
+          11
+      | TRUE ->
+          10
+      | TRY ->
+          9
+      | TYPE ->
+          8
+      | UIDENT _ ->
+          7
+      | UNDERSCORE ->
+          6
+      | VAL ->
+          5
+      | VIRTUAL ->
+          4
+      | WHEN ->
+          3
+      | WHILE ->
+          2
+      | WITH ->
+          1
+  
+  and error_terminal =
+    0
+  
+  and token2value : token -> Obj.t =
+    fun _tok ->
+      match _tok with
+      | AMPERAMPER ->
+          Obj.repr ()
+      | AMPERSAND ->
+          Obj.repr ()
+      | AND ->
+          Obj.repr ()
+      | ANDOP _v ->
+          Obj.repr _v
+      | AS ->
+          Obj.repr ()
+      | ASSERT ->
+          Obj.repr ()
+      | BACKQUOTE ->
+          Obj.repr ()
+      | BANG ->
+          Obj.repr ()
+      | BAR ->
+          Obj.repr ()
+      | BARBAR ->
+          Obj.repr ()
+      | BARRBRACKET ->
+          Obj.repr ()
+      | BEGIN ->
+          Obj.repr ()
+      | CHAR _v ->
+          Obj.repr _v
+      | CLASS ->
+          Obj.repr ()
+      | COLON ->
+          Obj.repr ()
+      | COLONCOLON ->
+          Obj.repr ()
+      | COLONEQUAL ->
+          Obj.repr ()
+      | COLONGREATER ->
+          Obj.repr ()
+      | COMMA ->
+          Obj.repr ()
+      | COMMENT _v ->
+          Obj.repr _v
+      | CONSTRAINT ->
+          Obj.repr ()
+      | DO ->
+          Obj.repr ()
+      | DOCSTRING _v ->
+          Obj.repr _v
+      | DONE ->
+          Obj.repr ()
+      | DOT ->
+          Obj.repr ()
+      | DOTDOT ->
+          Obj.repr ()
+      | DOTOP _v ->
+          Obj.repr _v
+      | DOWNTO ->
+          Obj.repr ()
+      | ELSE ->
+          Obj.repr ()
+      | END ->
+          Obj.repr ()
+      | EOF ->
+          Obj.repr ()
+      | EOL ->
+          Obj.repr ()
+      | EQUAL ->
+          Obj.repr ()
+      | EXCEPTION ->
+          Obj.repr ()
+      | EXTERNAL ->
+          Obj.repr ()
+      | FALSE ->
+          Obj.repr ()
+      | FLOAT _v ->
+          Obj.repr _v
+      | FOR ->
+          Obj.repr ()
+      | FUN ->
+          Obj.repr ()
+      | FUNCTION ->
+          Obj.repr ()
+      | FUNCTOR ->
+          Obj.repr ()
+      | GREATER ->
+          Obj.repr ()
+      | GREATERRBRACE ->
+          Obj.repr ()
+      | GREATERRBRACKET ->
+          Obj.repr ()
+      | HASH ->
+          Obj.repr ()
+      | HASHOP _v ->
+          Obj.repr _v
+      | IF ->
+          Obj.repr ()
+      | IN ->
+          Obj.repr ()
+      | INCLUDE ->
+          Obj.repr ()
+      | INFIXOP0 _v ->
+          Obj.repr _v
+      | INFIXOP1 _v ->
+          Obj.repr _v
+      | INFIXOP2 _v ->
+          Obj.repr _v
+      | INFIXOP3 _v ->
+          Obj.repr _v
+      | INFIXOP4 _v ->
+          Obj.repr _v
+      | INHERIT ->
+          Obj.repr ()
+      | INITIALIZER ->
+          Obj.repr ()
+      | INT _v ->
+          Obj.repr _v
+      | LABEL _v ->
+          Obj.repr _v
+      | LAZY ->
+          Obj.repr ()
+      | LBRACE ->
+          Obj.repr ()
+      | LBRACELESS ->
+          Obj.repr ()
+      | LBRACKET ->
+          Obj.repr ()
+      | LBRACKETAT ->
+          Obj.repr ()
+      | LBRACKETATAT ->
+          Obj.repr ()
+      | LBRACKETATATAT ->
+          Obj.repr ()
+      | LBRACKETBAR ->
+          Obj.repr ()
+      | LBRACKETGREATER ->
+          Obj.repr ()
+      | LBRACKETLESS ->
+          Obj.repr ()
+      | LBRACKETPERCENT ->
+          Obj.repr ()
+      | LBRACKETPERCENTPERCENT ->
+          Obj.repr ()
+      | LESS ->
+          Obj.repr ()
+      | LESSMINUS ->
+          Obj.repr ()
+      | LET ->
+          Obj.repr ()
+      | LETOP _v ->
+          Obj.repr _v
+      | LIDENT _v ->
+          Obj.repr _v
+      | LPAREN ->
+          Obj.repr ()
+      | MATCH ->
+          Obj.repr ()
+      | METHOD ->
+          Obj.repr ()
+      | MINUS ->
+          Obj.repr ()
+      | MINUSDOT ->
+          Obj.repr ()
+      | MINUSGREATER ->
+          Obj.repr ()
+      | MODULE ->
+          Obj.repr ()
+      | MUTABLE ->
+          Obj.repr ()
+      | NEW ->
+          Obj.repr ()
+      | NONREC ->
+          Obj.repr ()
+      | OBJECT ->
+          Obj.repr ()
+      | OF ->
+          Obj.repr ()
+      | OPEN ->
+          Obj.repr ()
+      | OPTLABEL _v ->
+          Obj.repr _v
+      | OR ->
+          Obj.repr ()
+      | PERCENT ->
+          Obj.repr ()
+      | PLUS ->
+          Obj.repr ()
+      | PLUSDOT ->
+          Obj.repr ()
+      | PLUSEQ ->
+          Obj.repr ()
+      | PREFIXOP _v ->
+          Obj.repr _v
+      | PRIVATE ->
+          Obj.repr ()
+      | QUESTION ->
+          Obj.repr ()
+      | QUOTE ->
+          Obj.repr ()
+      | RBRACE ->
+          Obj.repr ()
+      | RBRACKET ->
+          Obj.repr ()
+      | REC ->
+          Obj.repr ()
+      | RPAREN ->
+          Obj.repr ()
+      | SEMI ->
+          Obj.repr ()
+      | SEMISEMI ->
+          Obj.repr ()
+      | SIG ->
+          Obj.repr ()
+      | STAR ->
+          Obj.repr ()
+      | STRING _v ->
+          Obj.repr _v
+      | STRUCT ->
+          Obj.repr ()
+      | THEN ->
+          Obj.repr ()
+      | TILDE ->
+          Obj.repr ()
+      | TO ->
+          Obj.repr ()
+      | TRUE ->
+          Obj.repr ()
+      | TRY ->
+          Obj.repr ()
+      | TYPE ->
+          Obj.repr ()
+      | UIDENT _v ->
+          Obj.repr _v
+      | UNDERSCORE ->
+          Obj.repr ()
+      | VAL ->
+          Obj.repr ()
+      | VIRTUAL ->
+          Obj.repr ()
+      | WHEN ->
+          Obj.repr ()
+      | WHILE ->
+          Obj.repr ()
+      | WITH ->
+          Obj.repr ()
+  
+  and default_reduction =
+    (16, "\000\000\000\000\000\000\002\219\002\218\002\217\002\216\002\215\002\170\002\214\002\213\002\212\002\211\002\210\002\209\002\208\002\207\002\206\002\205\002\204\002\203\002\202\002\201\002\200\002\199\002\198\002\197\002\196\002\169\002\195\002\194\002\193\002\192\002\191\002\190\002\189\002\188\002\187\002\186\002\185\002\184\002\183\002\182\002\181\002\180\002\179\002\178\002\177\002\176\002\175\002\174\002\173\002\172\002\171\000\000\000\000\000\"\000\182\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\027\001\146\001}\001\143\001\142\001\141\001\147\001\151\000\000\003\028\001\145\001\144\001~\001\149\001\140\001\139\001\138\001\137\001\136\001\134\001\150\001\148\000\000\000\000\000\000\001\129\000\000\000\000\001\131\000\000\000\000\001\133\001\155\001\152\001\135\001\127\001\153\001\154\000\000\003\026\003\025\003\024\000\000\000\000\000\016\001;\000\000\000\213\000\214\000\015\000\000\000\000\001\177\001\176\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\020\000\000\003\021\000\000\000\000\003\018\000\000\003\017\003\r\002\022\000\000\003\016\000\000\002\023\000\000\000\000\000\000\000\000\000f\000\000\000\000\000c\000\000\000\000\003\011\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\180\001?\000\000\000\000\000\000\000\000\000\000\000\000\002\001\000\000\000\000\000\000\000\000\000\000\000\000\000m\000_\000\000\000\000\000\000\000\000\0009\000\000\000\000\001@\000:\002j\000\000\001\r\000\000\000j\000\000\000\000\000\t\000\b\000\000\000\000\000\000\000\000\002\151\000\000\002I\002J\000\000\002G\002H\000\000\000\000\000\000\000\000\000\000\000\000\002\149\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\244\002\243\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000i\000\000\000\225\000\000\000\000\000\226\000\000\002L\002K\000\000\000\000\000\000\001\159\000\000\000\000\000\029\000\000\000\000\000\000\000\022\000\000\000\000\001f\000\017\000\000\000\000\000\000\000\000\000\000\000\000\001>\000\000\001=\000\000\001<\000\000\003\012\000 \000\000\000\000\000\023\000\018\000\000\000\000\000\000\000\196\000\000\000\000\000\000\000\198\002 \002\018\000\000\000\026\000\000\002\019\000\000\000\000\001\156\000\000\000\000\000\000\000\n\000\000\000\000\000\000\000\011\002\245\000\000\002\246\000\000\000u\000\000\000\000\000\025\000\000\000\000\000\000\000\027\000\000\000\028\000\000\000\030\000\000\000\000\000\031\002\b\002\007\000\000\000\000\000\000\000\000\000\000\000\000\000]\000\000\002\156\000`\000l\000^\002\145\002\146\001\211\002\148\000\000\000\000\002\153\002F\002\155\000\000\000\000\000\000\002\162\002\159\000\000\000\000\000\000\001\208\001\194\000\000\000\000\000\000\000\000\001\198\000\000\001\193\000\000\001\210\002\168\000\000\001\209\001\201\000\000\000h\000\000\002\161\002\160\000\000\001\204\000\000\000\000\001\200\000\000\000\000\001\196\001\195\000\000\002\158\000\000\002N\002M\000\000\000\000\002*\002\157\002\154\000\000\000\000\000\000\000\000\001\161\001(\001)\002P\000\000\002Q\002O\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\236\000\237\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\202\000\201\000\199\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001X\000\000\000\000\000\000\000\000\000\000\000\000\0032\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\016\000\000\000\000\002\017\000\000\000\000\001W\000\000\000\000\000\000\001^\001]\001[\002\004\002\003\000\000\001V\001U\000\000\000\200\000\000\000\000\001I\000\000\000\000\001M\000\000\001\181\001\180\000\000\000\000\001\179\001\178\001L\001J\000\000\001N\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002n\003\029\002s\002q\000\000\000\000\000\000\002~\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\144\000\000\002\143\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\222\000\000\000\000\000\000\000\000\000\000\000\000\000\234\001\221\000\235\000\000\000\000\000\000\001h\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\229\000\000\000\230\000\000\000\000\000\000\002{\000\000\000\000\000\000\002V\002U\000\000\000\000\000\000\000\000\002}\002p\002o\000\000\000\000\000\165\000\000\000\000\000\000\000\000\000\000\000\179\000\000\000\000\000\000\000\164\000\000\000\000\000\000\0021\0020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\238\000\000\002\222\000\000\003\b\000\000\000\000\003\007\000\000\000\000\000\000\000\000\000\000\000\190\000\189\000\239\000\000\002\223\002\224\000\000\000\000\000k\000\000\002\163\002\147\000\000\002\166\000\000\002\165\002\164\000\000\000\000\000\000\000\000\000\000\000\000\000\243\000\000\000\000\002\n\000\000\000\000\000\000\000\242\000\000\000\000\000\241\000\240\000\000\000\000\000\000\000\000\000\245\000\000\000\000\000\244\000\000\001\207\000\000\000\000\001\218\000\000\000\000\001\220\000\000\000\000\001\216\001\215\001\213\001\214\000\000\000\000\000\000\000\000\000\000\001\019\000\012\000\247\000\000\000\000\000\000\002X\002W\000\000\000\000\002f\002e\000\000\000\000\000\000\000\000\002b\002a\000\000\000\000\002`\002_\000\000\000\000\002d\002c\002w\000\000\000\000\000\000\000\000\000\000\002\\\000\000\000\000\000\000\000\000\000\000\002Z\000\000\000\000\000\000\000\000\000\000\002^\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\006\002\005\000\163\000\000\002[\000\000\000\000\002Y\000\000\000\000\002]\000\000\000v\000w\000\000\000\000\000\000\000\000\000\134\000\191\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\192\000\000\000\193\000\194\000\127\000\000\000~\000\000\000\000\001+\000\000\001,\001*\002\012\000\000\000\000\002\r\002\011\000\000\000\000\000\000\000\000\000\000\000\254\000\000\000\000\000\255\000\000\000\000\000\166\000\000\001\001\001\000\000\000\000\000\002\127\002x\000\000\002\136\000\000\002\137\002\135\000\000\000\000\002$\000\000\002\141\000\000\002\142\002\140\000\000\000\000\002z\002y\000\000\000\000\000\000\001\244\000\000\001\175\000\000\000\000\000\000\002-\001\243\000\000\002\131\002\130\000\000\000\000\000\000\003\030\000\000\002h\000\000\002i\002g\000\000\002\129\002\128\000\000\000\000\000\000\002'\002v\000\000\002u\002t\000\000\002\139\002\138\000|\000\000\000\000\000\000\000\000\000{\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000y\000\000\001C\000\000\000\000\000\000\000a\000\000\000\000\000d\000\000\000b\000e\000\000\000\000\000\000\001`\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\219\000\000\000\000\000q\000\000\000\222\000\220\000\000\000\000\000\000\000\204\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000z\000\000\000\000\001\242\000\000\000\000\000\246\001\173\000\000\000\232\000\233\000\253\000\000\000\000\000\000\000\000\000\000\001\188\001\182\000\000\001\187\000\000\001\185\000\000\001\186\000\000\001\183\000\000\000\000\001\184\000\000\001z\000\000\000\000\000\000\001y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\\\000\000\000\000\000\000\000\000\002\236\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\t\002\237\000\000\000\000\000\000\000\000\000\000\001\227\000\000\000\000\000\000\000\000\000\000\000\000\002\242\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001j\000\000\001\233\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\221\000\000\000\000\0022\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001|\000\000\000\000\000\000\001{\000\000\000\000\000\000\000\000\000\000\000\000\002>\000\000\001P\000\000\001O\000\000\000\000\000\000\002=\000\000\001E\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\011\002@\000\000\000\000\000\000\000\000\002C\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003&\000\000\000\000\000\000\000\188\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000>\000\000\000\000\000\000\000\000\001e\000\000\001d\000\000\000\000\000\000\000\000\000A\000\000\000\000\000\000\001\240\000\000\001\239\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000B\000\000\000\000\000\000\000[\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\\\000G\000\000\000\000\000\000\000H\000F\000\000\000K\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000C\000\000\000J\000I\000\000\000D\000E\000\000\001\028\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\007\000Z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000W\000\000\000Y\000X\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\005\002D\0026\000\000\002<\0027\002B\002A\002?\001\022\000\000\0024\000\000\000\000\000\000\000\000\000\000\002\001\000\000\000\000\001\015\0028\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001u\001q\000\000\000\000\000\000\000\207\000\000\000\000\001\247\002\001\000\000\000\000\001\017\001\245\001\246\000\000\000\000\000\000\000\000\000\000\001x\001t\001p\000\000\000\000\000\208\000\000\000\000\001w\001s\001o\001m\0029\0025\002E\001\021\001\224\0023\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003!\000\000\000\000\003#\000\000\000.\000\000\000\000\003)\000\000\003(\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003 \000\000\000\000\003\"\000\000\000\000\000\000\001\235\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001:\000\000\000\000\0018\0016\000\000\000/\000\000\000\000\003,\000\000\003+\000\000\000\000\000\000\0014\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0019\000\000\000\000\0017\0015\000\000\000\000\000\000\0001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\249\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000Q\000\000\000\000\000\000\000\000\000\000\000\000\000+\000\000\000\000\000P\000\000\000)\000\250\000\000\0008\000%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\248\000\000\000O\000N\000\000\000\000\000T\000S\000\000\000\000\001\163\000\000\000-\000\000\000\000\000\000\000,\000\000\000\000\000\000\0000\000\000\000R\000U\000\000\0002\0003\000\000\001\030\000\000\000\000\000\000\000\000\000\000\000\000\0006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\003\002\240\002\231\000\000\000\000\002\235\002\220\002\230\002\239\002\238\001\026\000\000\000\000\002\228\000\000\002\232\002\229\002\241\001\223\000\000\000\000\002\226\000\000\000\186\002\225\000\000\000\000\000\217\000\000\000\000\001\025\001\024\000\000\001G\001F\000\000\000\000\002\167\002\150\000\000\000;\000\000\000\000\000<\000\000\000\000\000\138\000\137\002\134\000\000\002\133\002\132\002r\000\000\000\000\000\000\000\000\002k\000\000\002m\000\000\002l\000\000\002S\002R\000\000\002T\000\000\000\000\000\130\000\000\000\000\001\232\000\212\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\184\000\000\002\234\001\252\001\253\001\248\001\250\001\249\001\251\000\000\000\000\000\000\000\185\000\000\000\000\002\001\000\000\000\211\000\000\000\000\000\000\000\000\002\233\000\000\000\183\000\000\000\000\000\000\000\000\0013\001-\000\000\000\000\001.\000\021\000\000\000\020\000\000\000\000\000\197\000\000\000\000\000\000\000\024\000\019\000\000\000\000\000\000\000\r\000\000\000\000\000\000\000\000\001v\001r\000\000\001n\003\n\000\000\002\001\000\000\000\210\000\000\000\000\000\000\000\000\002;\002\000\001\254\001\255\000\000\000\000\000\000\002\001\000\000\000\209\000\000\000\000\000\000\000\000\002:\000\000\001R\001Q\000\000\000\014\000\000\003$\000\000\000#\000\000\000\000\000\000\000\000\000\133\000\000\000\215\000\001\000\000\000\000\000\216\000\002\000\000\000\003\000\000\001\189\000\000\000\000\001\190\000\004\000\000\000\000\001\191\000\005\000\000\000\000\000\000\002\253\002\248\002\249\002\252\002\250\000\000\000\000\003\001\000\006\000\000\003\000\000\000\001 \000\000\000\000\002\254\000\000\002\255\000\000\000\000\000\000\000\000\001$\001%\000\000\000\000\001#\001\"\000\007\000\000\000\000\000\000\003\023\000\000\003\022")
+  
+  and error =
+    (122, "'\225 \022*\183\204\207@P?\144\000\0148\b\216@\005\194\141\241'\208\004\015\128\000\001\142\007\223dB\011\248\212\000\019\007\007\184\226\192\160\208\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\254\182mf\235\252\205\255\005G\248\132A\231\129\247\217\016\130\2545\000\004\193\193\2388\176(4\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0026\016\001`\163|I\244\001\003\224\000\000c\129\247\217\016\130\2545\000\004\193\193\2388\176(4'\225\"V*\183\204\207@P?\128\000\0308\000\000\000\000@\000\192\004\000\000\000\000\000\000\000\000\000\000\000\000\0000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\128\000\128\031\128\176\144\000\015\136\128A\000@\162\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000(\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000 \000\002\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\002\000\000 \000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\003\000\000\192@\003\023\b\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\000\003\001\002\012\\ \000\016\000\000\000\000\000\001\000@\001\000\131\004\016\000\000@\000\000\000\000\000@\016\000\000 \193\004\000\000\016\000\000\000\000\000\016\004\000\000\b0@\000\000\004\000\000\000\000\003\018\000\168\000\131\t!\192\001\016\007a\002 \004\132\128 \000 \128\bP\000@\001\136\000\b\000! \b\000\b \002\016\000\016\000b\000\002\000\0000\000\b0A0\001\000\000\000\000\000\000\000\000\012\000\002\b\016L\000@\000\000\000\000\000\000\000\003\000\000\130\004\019\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\b \0010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\130\000\016\000\000\000\000\000\000\000\000\000\000\128\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000 \128\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\004\000\000\000\000\000\000\000\000\000\132\128\"\b \128\b`\000@\001\216\004H\001\000\200\0008\016\000\197\194\128\001\000\128 \000\016\bH\002 \003\b$\135\000\004@\025\132A\132\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003 \000\192@\003\023\n\000\004\002\000\128\000@\000\192\0020\016 \197\194\000\001\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\022\002\236\000\131%!\192\193\018\007`\022a\022\003\000\000\128\000\003\023\b\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\b\000\0001p\128\000H\000\b\000\000\000\004\000@\000\000\004\000\000\000\018\000\000\000@\000\003\000\000\192@\003\023\b\000\004\000\000\000\000\000\000@\000\000\000\000@\000\000\000\000\000\000\000\000\bP\t\024\000\004\144\135\003\000H\004\132H\000A\247\217\016\130\2545\000\004\193\193\2388\176(4'\225\"V*\183\204\207@P?\128\000\0308\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\000\002\012\016L\000@\000\000\000\000\000\000\000\003\000\000\130\004\019\000\016\000\000\000\000\000\000\000\000\192\000 \129\004\192\000\000\000\000\000\000\000\000\0000\000\b \0010\000\000\000\000\000\000\000\000\000\004\000\000\000\000\004\000\000\000\000\000\000\000\000\000\132\128\"\b \128H`\000D\001\216\004\b\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002 \002\b\004\134\000\004@\025\128@\128\017\247\217\016\130\2545\000\004\193\193\2388\176(4'\225\"V*\183\204\207@P?\128\000\0308\b\216@\005\194\141\241'\208\004\015\128\000\001\142\0026\016\001`\163|I\244\001\003\224\000\000c\128\141\132\000X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\016\001\000 0H\228\000\000`\000\000c\000\004\000\000\004\000\004\000@\000\000\000\000\000\000\000\001\000\000\000\000\001\000\016\000\000\000\000\000\000\000\000@\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\001\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\175\235w\246o\191\223\255\240t\255\152\132\014y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n6\024\129\248\171}H\244\249\139\228\016\006k\172\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\129!\b\016\002\003\004\142@\000\006\000\000\0060\b\216@\005\130\141\241#\208\004\015\128\000\001\206\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\001\000\n\bP0\000\000\b\004\000\000!\000\000\000\000\002\130\020\012\000\000\002\001\000\000\b@\000\000\000\000\160\132\003\000\000\000\128@\000\000\012\132\000\b\000L\018-\000\016\026\000\000\016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\012\134 ~\002\206R->2\027\004\001\146\203\128\000\b\000\000\000\000\000@\000\004\000\000\000\000 @\000\000@\000\000\004\000\000\000\000\000\000\000\000\016\000\000\000\000\000\001\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\004\000\000\b0@\000\000\004\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000@\128\000\000\000\129\004\000\000\016\000\000\000\000\000\016 \000\000\000 @\000\000\004\000\000\000\000\002\159\132\128X\170\2233}\001@\254 \0008\224\167\225 \022*\183\204\207@P?\136\000\0148)\248H\133\138\173\2433\208\020\015\230\000\003\142\000\016 \000\016\000 A\000\000\004\000\000\000\002\000\004\b\000\004\000\b\016@\000\001\000\000\000\000\000\001\002\000\000\000\002\004\016\000\000@\000\000\000\000\000@\128\000\000\000\129\000\000\000\016\000\000\000\000\000P \000\000\000 @\000\000\004\000\000\000\000\000\141\132\000X(\223\018}\000@\248\000\000\024\224#a\000\022\n7\196\143@\016>\000\000\0068\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\141\132\000\\(\223\018}\000@\248\000\000\024\224#a\000\022\n7\196\159@\016>\000\000\0068\b\216@\005\130\141\241#\208\004\015\128\000\001\142\012[\219\181\254/\183\207\239\254\216}\246\223\255<\141\132\000X(\223\018=\000@\248\000\000\024\224\003!\000\002\000\019\004\139@\004\006\000\000\004\016\000\200@\000\128\004\193\"\208\001\001\160\000\001D\0002\016  \0010H\180\000@h\000\000A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\004\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\017\000\000\000\000\000\000\000\000@\000\016\000\000\192\0000\016\000\197\194\000\001\000\000\000\000\000\0000\000\012\004\0001p\128\000@\000\000\000\005\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000\192@\003\023\b\000\004\000\000\000\000\016\000\192\000\176\016\000\197\194\000\001\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\000\003\001\000\012\\ \000\016\000\000\000\000@\003\000\000\192@\003\023\b\000\004\000\000\000\000P\000@\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\000\003\001\000\012\\ \000\016\000\000\000\000@\001\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\018\000\236\000\131!!\192\193\018\007`\022!\022\003\000\000\192@\003\023\b\000\004\000\000\000\000\0001 .\192\b2\018\028\012\017 v\001b\017`0\000\b\000\0001p\128\000@\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\001\000\000\000\129\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000 \000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0001`.\192\b2R\028\012\017 v\001b\017`\016\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\192\000 \000\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\012\000\003\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0001`.\192\b2R\028\012\017 v\001b\017`0\000\b\000\0001p\128\000@\000\000\000\000\003\022\002\236\000\131%!\192\193\018\007`\022!\022\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\192\0000\016\000\197\194\000\001\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000@\000\000@\000\002\000\000\000\001\000\003\000\000\192@\003\023\b\000\004\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\012\004\0001p\128\000@\000\000\000\000\000\000\000\b\000\000\000\000@\000\002\000\000\000\001\002\003\000\000\192@\003\023\b\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\001\000\000\b\000\000\000\004H\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000@\000\002\000\000\000\001\018\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\004\000\000 \000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\018\000\236\000\131!!\192\193\018\007`\022!\020\000\000\002\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\012\000\003\001\000\012\\ \000\016\000\000\000\000@\000\000\002\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\128\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000D\000\000\000\000@\000\000\001\000\000\000\000\128\000\017\000\000\000\000\000\000\000\000@\000\000\000\000\200@\000\128\004\193\"\208\001\001\160\000\001\004\0002\016\0000\0010I\164\000@`\000\000A\000\012\132\000\b\000L\018i\000\016\024\000\000\016@\003!\000\002\000\019\004\138@\004\006\000\000\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002L\164m\t\001L\018k\000\016\025B\006\213P\000\001\000\002\000\016\000\000@\000\004\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\147)\027B@S\004\155\192\004\006\208A\181T\000@\000\000\000\000\128\"\128\000\000\000\000\000\000\b2\016\128 \0010H\180\000@h\000\002A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200@\000\192\004\193&\208\001\001\160\000\001\004\0002\016\000 \0010I\180\000@h\000\000A\000\012\132\000\b\000L\018-\000\016\026\000\000\016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\000\001\176\000\004\000\001\000\000\000\005\000\019\020@\012\132\000\b\000L\018-\000\016\026\000\000\016@\144\000\027\000\000@\000\016\000\000\000P\0011D \200@\000\128\004\193\"\208\001\001\160\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002@\000l\000\001\000\000@\000\000\001@\004\197\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\200F\192\128\020\193&\208\001\001\180\000MU\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\147!\027\002\000S\004\155@\004\006\208\0015T\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\002\000\000\000\000\004\000\000\000\000\000H\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\131!\000\002\000\019\004\139@\004\006\128\000\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\000\001\176\000\004\000\001\000\000\000\005\000\019\020B\012\132\000\b\000L\018-\000\016\026\000\000\016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\000\006\192\000\016\000\004\000\000\000\020\000LQ\b\000\000\000\000\0000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200@\128\128\004\193\"\208\001\001\160\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\001 \000\000\000\001\000\000\000\000\000\018\020B\012\132\b\b\000L\018-\000\016\026\000\000\020@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000D\000\000\000\000@\000\000\000\000\004\129\016\128\000\017\000\000\000\000\000\000\000\000\000\000\000\000 \192\000@\000\000@\000\000\000\000\000\000\000\000\b\000\001\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\144\004$\0010I\172\000@d\000\019E@\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\016\000\004\000\0000\000\012\004\0001p\128\000@\000\000\000\000\000\000\000 \000\000\000\000@\000\000\001\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\016\000\000\000\0026\016\001`\163|H\244\001\003\224\000\000c\128\012\132\016\012\130L\018m\000\016\026\000\000\016@\001\002\000\001\000\002\004\016\000\000@\000\000\000 \000@\128\000@\000\129\004\000\000\016\000\000\000\000\000\016 \000\000\000 A\000\000\004\000\000\000\000\000\004\b\000\000\000\b\016\000\000\001\000\000\000\000\000\000\000\000\000\000\002\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\0000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\004\001\000\000\002\012\016\000\000\001\000\000\000\000\000\001\000@\000\000\131\004\000\000\000@\000\000\000\000\000\000\000\000\000\000\128\004\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\001\b\000\000\000\000\000\000\000\000\000\001\000@\000\000\131\004\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012H\002\160\002\012\004\135\000\004@\029\128\b\128\016\002\000\000\000\002\000\000\000\000\000\000\000\000\000\000\003\000\000\130\000\019\000\000\000\000\000\000\000\000\000\000@\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\004\000\000\012\000\003\129\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\192\0000\016\000\197\194\000\001\000\000\000\000\000\012H\002\160\002\012\004\135\000\004@\029\128\b\128P\012\000\003\001\000\012\\ \000\016\000\000\000\000\000\196\128*\000 \192Hp\000D\001\216\004\136\0051 \n\128\b0\018\028\000\017\000v\001\"\000@0\000\012\004\0001p\128\000@\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\001\000\000\000\000\003\000\000\192@\003\023\b\000\004\000\000\000\000\0001 \n\128\b0\018\028\000\017\000v\001\"\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@@@\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\012H\002\160\002\012$\135\000\004@\029\132\b\128\016\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\0001 \n\128\b0\146\028\000\017\000v\016\"\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\018\000\168\000\131\001!\192\001\016\007`\002 \004\000\128\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\004\000\000\b0@\000\000\004\000\000\000\000\003\018\000\168\000\131\001!\192\001\016\007`\002 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\016\000\000\000\016\000\000\000\000\016\000\000\000\000\000\000\000\000\003\018\000\168\000\131\t!\192\001\016\007a\002 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\002\000\000\016\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\b\000\000@\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004 \000\000\000\000\000\000\000\000\000\004\b\000\000\000\b\016\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0001 \n\128\b0\146\028\000\025\000v\000&\000@P \128\000\000 @\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\002\000\016\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\001\000\000\002\012\016\000\000\001\000\000\000\000\000\192\000\b\000\000@\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0001 \n\128\b0\146\028\000\025\000v\016&\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000@\000\128\000\000\000\000\000#a\000\022\n7\196\143@\016>\000\000\0068\b\216@\133\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\016\000\000\000\016\000\000\000\000\002\000\000@\000\000\000\000\000\000\004\001\000\000\000\000#a\000\022\n7\196\143@\016>\000\000\0068\000H@\004\000\128\193#\144\000\001\128\000\001\140\012\000\001\016\000\000\000\000\000\000\192\004\020\t\000\000\141\132\000\\(\223\018}\000@\248 \000\024\224#a\000\022\n7\196\159@\016>\b\000\0068\b\216@\005\130\141\241#\208\004\015\130\000\001\142\000\018\016\001\016 0I\228\000\000`\000\000c\000\004\132\000@\b\012\018y\000\000\024\000\000\024\192\001!\000\016\002\003\004\142@\000\006\000\000\0060\000H@\004\000\128\193#\144\000\001\128\000\001\140\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012[\219\181\254/\181\207\239\254\216}\246\223\255|\004\000\000\000\000\012\0028\000\000\000\000\000\000\000\163a\136\031\138\183\212\143O\152\190A\000f\186\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n6\016\129`\163|H\244\001\003\224\000\000c\130\141\132 X(\223\018=\000@\248\000\000\024\224\129\002\000\001\000\002\004\016\000\000@\000\000\000\000\000@\128\000\000\000\129\004\000\000\016\000\000\000\000\000\016 \000\000\000 @\000\000\004\000\000\000\000\000\000\000\000\000\000\b\000@\000\000\000\000\000@\000\129\000@\000\000\131\004\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\128\000\004\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\163a\b\022\n7\196\143@\016>\000\000\0068(\216B\005\130\141\241#\208\004\015\128\000\001\142\b2\016\128 \0010H\180\000@`\000\000A\000\000\000\000\000\000\000\000@\000\000\001\000\004\193\016\003\000\000\192@\003\023\b\000\004\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000\000\000\0026\016\001`\163|H\244\001\003\224\000\000c\128\141\132\000\\(\223\018}\000@\248\000\000\024\224#a\000\022\n7\196\159@\016>\000\000\0068\b\216@\005\130\141\241#\208\004\015\128\000\001\142\0002\016\0000\0010I\180\000@h\000\000E\000\012\132\000\b\000L\018m\000\016\026\000\000\017@\003!\000\002\000\019\004\139@\004\006\128\000\004P\000\200@\000\128\004\193\"\208\001\001\160\000\001\004\001\000\000\000\000\004\000\001\000\000\000\000\000\018\004@\141\132\000X(\223\018=\000@\248\000\000\024\224\003)\000C@\019\004\154\192\004\006\000\000\004\016\000\202@\016\144\004\193&\176\001\001\128\000\001\004\0002\144\004$\0010H\172\000@`\000\000A\000\b\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200@\000\128\004\193\"\208\001\001\160\000\001\004\000\000\000\128\000\000\000\001\000\000\000\004\000\019\004@\012\000\003\001\000\012\\ \000\016\000\000\000\000\000\000\000\b\000\000\000\000\016\000\000\000@\000\000\000\000\000\002\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b:\024\129\248\0119H\180\248\200l\016\006K,\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\b\000\000\001\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\012\164\001\t\001L\018+\000\016\024\000\000P@#a\000\022\n7\196\143@\016>\000\000\0068\000\200@\000\192\004\193&\208\001\001\160\000\001\004\0002\016\000 \0010I\180\000@h\000\000A\000\012\132\000\b\000L\018-\000\016\026\000\000\016@\000\000\000\000\000\000\000\016\000\000\000@\001 D\b\216@\005\130\141\241#\208\004\015\128\000\001\142\000\018\016\001\016 0I\228\000\000`\000\000c\000\004\132\000@\b\012\018y\000\000\024\000\000\024\192\001!\000\016\002\003\004\142@\000\006\000\000\00601%.\195\232>\022\028\015\251`w\219~p\240\018\016\001\000 0H\228\000\000`\000\000c\003\022\246\237\127\139\237s\251\255\182\031}\183\255\223\000\000\000\000\000\002\000\n\000\000\000\000\000\000\000\b\216@\005\130\141\241#\208\004\015\128\000\001\142\0026\016\001`\163|H\244\001\003\224\000\000c\131\022\246\237\127\139\237s\251\255\182\031}\183\255\207\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001!\000\016\002\003\004\142@\000\006\000\000\00601on\215\248\190\215?\191\251a\247\219\127\253\240\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\003\000\n\000\000\000\000\000\000\000\b\216@\005\130\141\241#\208\004\015\128\000\001\142\b\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0001%.\195\232>\022\028\015\249`w\139~p\2426\016\001`\163|H\244\001\003\224\000\000c\131\022\246\237\127\139\237s\251\255\182\031}\183\255\207\196\148\187\015\160\248Xp?\237\129\223m\249\195\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\001\b\216@\005\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\018R\236>\131\225a\192\255\150\007x\183\231\015#a\000\022\n7\196\143@\016>\000\000\00681%.\195\232>\022\028\015\249`w\139~p\2426\016\001`\163|H\244\001\003\224\000\000c\131\018R\236>\131\225a\192\255\150\007x\183\231\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0001on\215\248\190\215?\191\251a\247\219\127\252\252IK\176\250\015\133\135\003\254\216\029\246\223\156<\141\132\000X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0009\253n\199\234\191\247?\223\253o\247\139\127\254\247\223dB\011\248\212\000\019\007\007\184\226\192\160\208\141\132\000X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0026\016\001`\163|H\244\001\003\224\000\000c\131\018R\236>\131\225a\192\255\150\007x\183\231\015#a\000\022\n7\196\143@\016>\000\000\00681%.\195\232>\022\028\015\249`w\139~p\2426\016\001`\163|H\244\001\003\224\000\000c\131\018R\236>\131\225a\192\255\150\007x\183\231\015#a\000\022\n7\196\143@\016>\000\000\00681%.\195\232>\022\028\015\249`w\139~p\2426\016\001`\163|H\244\001\003\224\000\000c\131\018R\236>\131\225a\192\255\150\007x\183\231\015#a\000\022\n7\196\143@\016>\000\000\00681%.\195\232>\022\028\015\249`w\139~p\2426\016\001`\163|H\244\001\003\224\000\000c\131\018R\236>\131\225a\192\255\150\007x\183\231\015#a\000\022\n7\196\143@\016>\000\000\00681%.\195\232>\022\028\015\249`w\139~p\2426\016\001`\163|H\244\001\003\224\000\000c\131\018R\236>\131\225a\192\255\150\007x\183\231\015#a\000\022\n7\196\143@\016>\000\000\00681%.\195\232>\022\028\015\249`w\139~p\2426\016\001`\163|H\244\001\003\224\000\000c\131\018R\236>\131\225a\192\255\150\007x\183\231\015#a\000\022\n7\196\143@\016>\000\000\00681%.\195\232>\022\028\015\249`w\139~p\2426\016\001`\163|H\244\001\003\224\000\000c\131\018R\236>\131\225a\192\255\150\007x\183\231\015#a\000\022\n7\196\143@\016>\000\000\00681%.\195\232>\022\028\015\249`w\139~p\2426\016\001`\163|H\244\001\003\224\000\000c\131\018R\236>\131\225a\192\255\150\007x\183\231\015#a\000\022\n7\196\143@\016>\000\000\00681%.\195\232>\022\028\015\249`w\139~p\2426\016\001`\163|H\244\001\003\224\000\000c\131\018R\236>\131\225a\192\255\150\007x\183\231\015#a\000\022\n7\196\143@\016>\000\000\00681%.\195\232>\022\028\015\249`w\139~p\2426\016\001`\163|H\244\001\003\224\000\000c\131\018R\236>\131\225a\192\255\150\007x\183\231\015#a\000\022\n7\196\143@\016>\000\000\00681%.\195\232>\022\028\015\249`w\139~p\2402\016\000 \0010I\180\000@`\000\000A\000\012\132\000\b\000L\018-\000\016\024\000\000\016@\003)\000B@\019\004\154\192\004\006@\001\180T \232b\007\224,\229\"\211\227!\176@\025,\176\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\003)\000B@\019\004\138\192\004\006@\000\148\016\000\200@\000\128\004\193\"\144\001\001\128\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\141\132\000X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \192\0000\016\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000d\000\000\000\000@\000\000\001\000\000\000\000\131\000\000\192@\003\023\b\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\001\144\000\000\000\001\000\000\000\004\000\b\000\000\012\000\003\001\000\012\\ \000\016\000\000\000\000\000\128\000\025\000\000\000\000\016\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\0026\016\001`\163|H\244\001\003\224\000\000c\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\144\004$\0010H\172\000@d\000\tA\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\002\000\000\000\000\000\016\000\001\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\000\000\016\000\000\000\000\0010D\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\012\000\003\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\002\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\131\128\000\192@\003\023\b\000\004\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\012\000\003\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000@\000\000\000\b\216@\005\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\001\000\000\000\001\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\012\004\0001p\128\000@\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\001\000\000\000\000#a\000\022\n7\196\143@\016>\000\000\0068\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\141\132\000X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\004\000\019\004@\012\000\003\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000@\000\000\000\b\216@\005\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\001\000\004\129\016#a\000\022\n7\196\143@\016>\000\000\0068\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b2\016\000 \0010H\180\000@h\000\000A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000@\001 D \200@\000\128\004\193\"\208\001\001\160\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\001\000\004\129\016\131!\000\002\000\019\004\139@\004\006\128\000\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\004\000\018\004B\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000@\001 D\000\200@\000\128\004\193\"\208\001\001\160\000\001\004\000\000\000\000\000\000\000\001\000\000\000\004\000\018\004B\018\000\136\000\130\001!\128\001\144\006`\000 \004\132\128\"\000 \136H`0d\001\152\004\b\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\148\187\015\160\248Xp?\229\129\222-\249\195\200\216@\005\130\141\241#\208\004\015\128\000\001\142\b\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\216@\005\130\141\241#\208\004\015\128\000\001\142\b\000\b\016\248\003\001\001\000\248\b\004\000\022\b\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000P\000\000\000\000\000\000\000\000 \000\160\000\000\000\000\000\000\000\141\132\000X(\223\018=\000@\248\000\000\024\224\128\000\136\015\1280\016\016\015\128\128@\001`\128\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\141\132\000X(\223\018=\000@\248\000\000\024\224\128\000\130\015\1280\016\016\015\128\128@\001`\128\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\141\132\000X(\223\018=\000@\248\000\000\024\224\128\000\129\015\1280\016\016\015\128\128@\001`\128\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001!\000\016\002\003\004\142@\000\006\000\000\00601on\215\248\190\215?\191\251a\247\219\127\253\240\000\000\000\000\000 \000\160\000\000\000\000\000\000\000\141\132\000X(\223\018=\000@\248\000\000\024\224\128\000\136\015\1280\016\016\015\128\128@\001`\128\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012[\219\181\254/\183\207\239\254\216}\246\223\255<\141\132\000X(\223\018=\000@\248\000\000\024\224\196\148\187\015\160\248Xp?\229\129\222-\249\195\200\216@\005\130\141\241#\208\004\015\128\000\001\142\b\000\b \248\003\001\001\000\248\b\004\000\022\b\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\197\189\187_\226\251|\254\255\237\135\223m\255\243\200\216@\005\130\141\241#\208\004\015\128\000\001\142\012IK\176\250\015\133\135\003\254X\029\226\223\156<\141\132\000X(\223\018=\000@\248\000\000\024\224\128\000\129\015\1280\016\016\015\128\128@\001`\128\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012[\219\181\254/\183\207\239\254\216}\246\223\255<\141\132\000X(\223\018=\000@\248\000\000\024\224\196\148\187\015\160\248Xp?\229\129\222-\249\195\192@\000\000\000\000\192\002\128\000\000\000\000\000\000\0026\016\001`\163|H\244\001\003\224\000\000c\130\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\197\189\187_\226\251|\254\255\237\135\223m\255\243\200\216@\005\130\141\241#\208\004\015\128\000\001\142\012IK\176\250\015\133\135\003\254X\029\226\223\156<\141\132\000X(\223\018=\000@\248\000\000\024\224\128\000\002\000\000\000\000\000\000\000\000\000\000\000\0001on\215\248\190\223?\191\251a\247\219\127\252\2426\016\001`\163|H\244\001\003\224\000\000c\131\018R\236>\131\225a\192\255\150\007x\183\231\015#a\000\022\n7\196\143@\016>\000\000\0068 \000 C\224\012\004\004\003\224 \016\000X <[\219\181\254/\183\207\239\254\216}\246\223\255<\141\132\000X(\223\018=\000@\248\000\000\024\224\196\148\187\015\160\248Xp?\229\129\222-\249\195\192\000\000\000\000\000\000\000\000\000\000\000P\000\000\000\000\000\000\000\000 \000\160\000\000\000\000\000\000\000\141\132\000X(\223\018=\000@\248\000\000\024\224\128\000\136\015\1280\016\016\015\128\128@\001`\128\241on\215\248\190\223?\191\251a\247\219\127\252\2426\016\001`\163|H\244\001\003\224\000\000c\131\018R\236>\131\225a\192\255\150\007x\183\231\015#a\000\022\n7\196\143@\016>\000\000\0068 \000 \131\224\012\004\004\003\224 \016\000X <[\219\181\254/\183\207\239\254\216}\246\223\255<\141\132\000X(\223\018=\000@\248\000\000\024\224\196\148\187\015\160\248Xp?\229\129\222-\249\195\200\216@\005\130\141\241#\208\004\015\128\000\001\142\b\000\b\016\248\003\001\001\000\248\b\004\000\022\b\015\022\246\237\127\139\237\243\251\255\182\031}\183\255\207#a\000\022\n7\196\143@\016>\000\000\00681%.\195\232>\022\028\015\249`w\139~p\252[\219\181\254/\183\207\239\254\216}\246\223\255<\141\132\000X(\223\018=\000@\248\000\000\024\224\196\148\187\015\160\248Xp?\229\129\222-\249\195\241on\215\248\190\215?\191\251a\247\219\127\253\252[\219\181\254/\181\207\239\254X}\226\223\255<\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\b\128\248\003\001\001\000\248\b\004\000\022\b\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000#a\000\022\n7\196\143@\016>\000\000\0068 \000 \131\224\012\004\004\003\224 \016\000X 0\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\141\132\000X(\223\018=\000@\248\000\000\024\224\128\000\129\015\1280\016\016\015\128\128@\001`\128\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\216@\005\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\141\132\000X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\014\134 ~\002\206R->2\027\004\001\146\203\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\0002\144\004$\0050H\172\000@`\000\001A\000\012\000\002\000\000\012\\ \000\016\000\000\000\000\000\001\000\000\000\000A\000\000\000\004\000\000\000\000\000\b\216@\005\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\164\001\t\001L\018+\000\016\024\000\000P@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\164\001\t\001L\018+\000\016\024\000\000P@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\0026\016\001`\163|H\244\001\003\224\000\000c\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000#a\000\022\n7\196\143@\016>\000@\0068\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\148\187\015\160\248Xp?\229\129\222-\249\195\192\200@\000\128\004\193\"\208\001\001\160\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\b\216@\005\130\141\241#\208\004\015\128\000\001\142\012IK\176\250\015\133\135\003\254X\029\226\223\156<\141\132\000X(\223\018=\000@\248\000\000\024\224\196\148\187\015\160\248Xp?\229\129\222-\249\195\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\004\000\018\004@\141\132\000X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\1306\016\001`\163|H\244\001\003\224\000\000c\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003!\000\002\000\019\004\139@\004\006\000\000\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\004\132 @\b\012\0189\000\000\024\000\000\024\192\128\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\141\132\000X(\223\018=\000@\248\000\000\028\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\146\015\1280\016\016\015\128\128@\001a\128\232\216@\133\130\141\241#\208\004\015\128\000\001\206\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\141\132\bX(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001!\000\016\002\003\004\142@\000\006\000\000\0060\016\000\000\000\000\000\000\000\000\003\000\000P\000\000\000\016\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\017\000\000\000\000\000\000\000\000@\000\144\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\001\016\000\000\000\000\000\000\000\004\000\000\000\002\000\000D\000\000\000\000\000\000\000\000\000\000\000\000\129\000\001\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\192\000\020\000\000\000\004\000\000\000\000\012\0028\000\000\000\000\000\000\000\192\000\017\000\000\000\000\000\000\012\000A@\144\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012IK\176\250\015\133\135\003\254\216\029\246\223\156<\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\t\016\248\003\001\001\000\248\024\004\000\022\b\014\000\000@\000\000\000\000\000\000\004\000\000\000\000\000\128\000\000\000\000\001\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016 \000\000\000 A\000\000\004\000\000\000\000\000\004\b\000\000\000\b\016\000\000\001\000\000\000\000\000\000\000\000\000\000\002\000\016\000 \000\000\000\000\000\b\216@\005\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\004\000\000\000@\000\000\000\000\000\000\000\001\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\004\000\001\000\000\004\b\000\000\000\b\016\000\000\001\000\000\000\000\000\132\128\"\000 \130Hp\000d\001\152\000\b\001\000@\016\000\000 \193\000\000\000\016\000\000\000\000\004\000\000\000\000\004\000\001\000\000\000\004\000\000\000\000\004\b\000\000\000\b\016\000\000\001\000\000\000\000\000\132\128\"\000 \130Hp\000d\001\152\000\b\001\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\0026\016\001`\163|H\244\001\003\224\000\000c\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000@\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\000\000\016\000 \001\128\000\000 \000\000\000\000\004\128\000\000\000\b\000`\000\000\b\000\000\000\000\001 \000\000\000\002\000\b\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\002\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\016\000 \000\000\000\016\000\000\192\000 \000\000\197\194\128\001\000\000\000\000\000\000\000\000\000\000\016\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\0000\000\012\004\0001p\128\000@\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\001\000\000\000\003\000\000\192@\003\023\b\000\004\000\000\000\000\000\000\000\004@\000\000\000\004\000\000 \000\000\000\001\000\000\001\016\000\000\000\001\000\000\000\000\000\000\000\000\000\000D\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\001\001\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\016\000\000\000\001\000\000\b\000\000\000\000@\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000@@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\192\000 \000\000\197\194\000\001\000\000\000\000\000\bX\n \002\012\020\135\000\006@\025\128@\132\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\133\128\162\000 \129Hp\000d\001\152\004\bA\000\192\000 \000\000\197\194\128\001\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\012\000\002\000\000\012\\ \000\016\000\000\000\000\000\133\128\"\000 \129Hp\000d\001\152\004\bA!`(\128\b0R\028\000\025\000f\001\002\016@\000\000\000\000\000\000\001\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000#a\000\022\n7\196\143@\016>\000\000\0068\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\016@ \0010I\180\000@`\000\000A\000\012\132\016\b\000L\018-\000\016\024\000\000\016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200@\000\128\004\193\"\208\001\001\128\000\001\004\bH\002 \002\b\004\134\000\006@\025\128\000\128\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0001%.\195\232>\022\028\015\249`w\139~p\244\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\132\000\b\000L\018-\000\016\026\000\000\017@\196\148\187\015\160\248Xp?\229\129\222-\249\195\224\000\"\003\224\012\004\004\003\224 \016\000| 0\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\129\000@\000\000\131\004\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\128\000\004\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\129\000@\000\000\131\004\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\128\000\004\000\001\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000@\000\000\131\004\000\000\000@\000\000\000\000\016\000\002\000\000\016\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\018\000\136\000\130\t!\192\001\016\006`\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\128\000\000\000\129\004\000\000\016\000\000\000\000\000\016 \000\000\000 @\000\000\004\000\000\000\000\002\018\000\136\000\130\t!\192\001\016\006`\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000`\001\000@\000\000\004\000\000\000\000\000\000\000\000\016\000\000\016\000\016\001\000\000\000\000\000\000\000\000\004\000\000\000\000\004\000@\000\000\000\000\000\000\000\001\000\000\000\000\001\000\000\000\000\000\000\000\000\000! \b\128\b \018\024\000\017\000v\000\002\000\000\016\004\000\000\b0@\000\000\004\000\000\000\000\003\018\000\136\000\131\001!\192\001\016\006`\000 \000\132\128\"\000 \128H`\000D\001\152\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000@\000\000\000\001\000\000\000\000\000\000\000\000\004\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000@\000\016\000! \b\128\b \018\024\000\017\000f\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000@\000\016\000! \b\128\b \018\024\000\017\000f\000\002\000HH\002 \002\b\004\132\000\004@\025\128\000\128\016\004\000\000\000\000\000\000@\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\016\000\004\000\bH\002 \002\b\004\134\000\004@\025\128\000\128\018\018\000\136\000\130\001!\000\001\016\006`\000 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\223dB\011\248\212\000\019\007\007\184\226\192\160\208\159\132\137X\170\2233=\001@\254\000\000x\224\003!\000\002\000\019\004\139@\004\006\128\000\004\016\004\000\000\128\000\000\000\004\000\000\000\000\000H\017\0026\016\001`\163|H\244\001\003\224\000\000c\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000}\246D \191\141@\0010p{\142,\n\r\t\248H\149\138\173\2433\208\020\015\224\000\007\142\000\016 \000\016\000 A\000\000\004\000\000\000\000\000\004\b\000\000\000\b\016@\000\001\000\000\000\000\000\001\002\000\000\000\002\004\000\000\000@\000\000\000\000! \b\128\b \146\028\000\017\000f\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\012\000@\000\000\000\000\000\000\000\000\000\000\000\000\003\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\012\000\003\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000@\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\bH\018 \002\b\004\134\000\004@\025\128\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\000 \128H`\000D\001\152\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\000\000\016\000 \001\128\000\000 \000\000\000\000\004\128\000\000\000\b\000`\000\000\b\000\000\000\000\001 \000\000\000\002\000\b\000\000\002\000\000\000\000! \b\128\012 \018\028\000\017\000v\000\006\000\000\018\000\000\000\000 \000\128\000\000 \000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\128\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000! \b\128\b \018\028\000\017\000f\016\002\016\000\016\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\132\128\"\000 \128Hp\000D\001\152\000\b\000! \b\128\b \018\024\000\017\000f\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\018\000\136\000\130\001!\192\001\016\006`\000 \000\132\128\"\000 \128H`\000D\001\152\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000x\002,\006\b1\244\128\004@\024\000\000\128\002\018\000\136\000\130\000!\000\001\000\006`\000 \000\001\000\000\001\000\000\000\016\000\000\000\000\000\000 \000@\000\000@\000\000\004\000\000\000\000\000\000\000\000\016\000\000\000\000\000\001\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\000 \130\b`\000@\001\152@\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\001\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\000 \130\b`\000@\001\152@\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\024\000@\016\000\000\001\000\000\000\000\000\000\000\000\004\000\016\000\000\000\000@\000\000\000\000\000\000\000\001\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\016\000\020\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\002\018\000\136\000\130\000!\128\001\000\006a\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 @\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\018\000\136\000\130\b!\128\001\000\006a\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\016\000\000 \193\000\000\000\016\000\000\000\000\012H\002 \002\012\000\135\000\004\000\025\128\000\128\002\018\000\136\000\130\000!\128\001\000\006`\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000@\016\000\000 \193\000\000\000\016\000\000\000\000\012H\002 \002\012\000\135\000\004\000\025\128\000\128\018\018\000\136\000\130\000!\000\001\000\006`\000 \004\001\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\004\001\000\000\002\012\016\000\000\001\000\000\000\000\000\196\128\"\000 \192\bp\000@\001\152\000\b\001! \b\128\b \002\016\000\016\000f\000\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000@\001\000\131\004\016\000\000@\000\000\000\000\000@\016\000\000 \193\004\000\000\016\000\000\000\000\000\016\004\000\000\b0@\000\000\004\000\000\000\000\003\018\000\136\000\131\000!\192\001\000\006`\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000H\000\000@\000\128\006\000\000\000\128\000\000\000\000\018\000\000\000\000 \001\128\000\000 \000\000\000\000\004\128\000\000\000\b\000 \000\000\b\000\000\000\000\132\128\"\0000\128\bp\000@\001\152\000\024\000\002 \000\000@\000@\006\000\000\000\000\000\000\000\000\128\000\000\016\000\016\001\128\000\000\000\000\000\000\000 \000\000\000\000\004\000`\000\000\000\000\000\000\000\b\000\000\000\000\001\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\128\000\000\000\000\000\000\000\b\000\002\b\000@\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\001\000\000\000\b\001D\b\000\000\000\000\000\000\000!\000\000\000\000\002\130\020\004\000\000\002\001\000\000\b@\000\000\000\000\160\132\001\000\000\000\128@\000\000\012\000\003\001\000\012\\ \000\016\000\000\000\000\000\000\000\b\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b@\000\000\000\000\128\132\001\000\000\000\128@\000\000 \000\000\000\004\004\000@\000\000\000\000\000\000\000\b\000\000\000\001\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000@@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\012\000\003\001\000\012\\ \000\016\000\000\000\000\000\132\000\000\000\000\b\bp\016\000\000\b\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\002\000\000\016\001\000\000\000\000\000\000\000\000 \000\000\128\000\004\000\000\000\000\000\000\000\000\000\000\000\000 \000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\0000\000\012\004\0001p\128\000@\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\001\000\000\000\003\000\000\192@\003\023\b\000\004\000\000\000\000\000!\000\000\000\000\002\002\028\012\000\000\018\001\000\000\b@\000\000\000\000\128\134\001\000\000\000\128@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\000\000\b\bp0\000\000H\004\000\000\000@\000\000\002\000Q\006\000\000\000\000\000\000\000\000\016\000\000\000\128\020@\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\004\000\000\000\000\000\000\b\000\016\000\000\000\000\000\001\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000@\000\000\000@\000\000\002\000Q\002\000\000\000\000\000\000\000\0000\000\012\004\0001p\128\000@\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\004\000\000\001\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\016\000\000\000\016\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\192\0000\016\000\197\194\000\001\000\000\000\000\000\000\000\000 \000\000\000\001\000\000\000\000\000\016\000\000\000\000\b\000\000\000\000@\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002\160\002\b\132\135\001\004@\029\128@\128\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\016\000\000\000\016\000\000\000\128\020@\128\000\000\000\000\000\000\002\018\000\168\000\130!!\192A\016\007`\016 \004\132\000\000\000\000\b\bp\016\000\000\b\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\012\004\0001q\128\000@\000\000\000\000\000\012\000\003\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000@\000\000\000\000\192\0000\016\000\197\194\000\001\000\000\000\000\000\b@\000\000\000\000\128\135\003\000\000\000\128@\000\002\016\000\000\000\000 !\128@\000\000 \016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\000\000\b\b`\016\000\000\b\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\016\000\000\000\000 !\000@\000\000 \016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000! \b\128\b \018\028\000\017\000f\000\002\000HH\002 \002\b\004\132\000\004@\025\128\000\128\016 \000\000\000\000\004\000`\000\000\000\000\000\000\000\b\000\000\000\000\001\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\001\000\000\000\b\001D\b\000\000\000\000\000\000\000! \b\128\b \018\028\000\017\000f\000\002\000HH\002 \002\b\004\132\000\004@\025\128\000\128\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000@\006\000\000\000\000\000\000\000\000\128\000\000\000\000\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\0000\000\012\004\1285p\128\000@\000\000\000\000\002\022\002\168\000\131\004!\192\001\016\007`\000`\004\003\000\000\128\000\003\023\b\000\004\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\0000\000\012\004\1285p\128\000@\000\000\000\000\000\012\000\003\001\000\012\\ \000\016\000\000\000\001@\000\000\002\000\000\000\000\016\000\000\000\000\001\000@\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\0000\000\012\004\1285p\128\000@\000\000\000\000\000\012\000\002\000\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\192\0000\018\000\213\194\000\001\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\004\000\000\000\004\000\000\000\000\004\000\000\000\000\000\000\000\000\000\133\128\170\000 \193\bp\000D\001\216\000\b\001!`*\128\b0B\028\000\017\000v\000\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\018\000\168\000\130\000!\192\001\000\007`\000 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002 \002\b\000\134\000\004\000\025\128\000\128\018\018\000\136\000\130\000!\000\001\000\006`\000 \004\b\000\000\000\000\001\000\024\000\000\000\000\000\000\000\002\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\192\0000\018\000\213\194\000\001\000\000\000\000\000\bH\002 \002\b\000\134\000\004\000\025\128\000\128\018\018\000\136\000\130\000!\000\001\000\006`\000 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\018\000\136\000\130\000!\000\001\000\006`\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002 \002\b\000\134\000\004\000\025\128\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\000 \128\b@\000@\001\152\000\b\001\000\128\000 \128\004\192\004\000\000\000\000\000\000\000\000 \000\b \0010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\132\128\"\000 \128H`\000D\001\216\004\b\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002 \002\b\004\134\000\004@\025\128@\128\018\018\000\136\000\130\001!\000\001\016\006`\000 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002 \002\b\000\132\000\004\000\025\128\000\128\016\b\000\002\b\000L\000@\000\000\000\000\000\000\000\002\000\000\130\000\019\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\012\128\003\129\000\012\\(\000\016\b\002\000\001\000\003\000\002\192@\003\023\b\000\004\000\000\000\000P\000\000\000\000\000@@\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000!h\b\128\b \146\026\000\017\000\230\001\002\000HH\002 \003\b\004\135\000\004@\025\128A\132\018\018\000\136\000\130\001!\192\001\016\006`\016!\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000! \b\128\b \018\024\000\017\000f\001\002\016@\018\000\000\000\000 \000\128\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000! \b\128\b \002\024\000\016\000f\001\002\000HH\002 \002\b\000\132\000\004\000\025\128\000\128\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002 \002\b\004\135\000\004@\029\128@\128\016\004\128\000\128\000\b\000(\000\000\b\002\000\001\000\001 \000\000\000\002\000\n\000\000\002\000\128\000@\000\000\000\000\000@@\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002 \003\b\004\135\000\004@\025\128A\132\018\018\000\136\000\130\001!\192\001\016\006`\016!\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@@\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\004\000\000\000\000\000\000\000\000\136\000\000\016\000\016\001\128\000\000\000\000\000\000\000 \000\000\000\000\004\000`\000\000\000\000\000\000\000\b\000\000\000\000\001\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\012\164\001\t\000L\018+\000\016\025\000\000P@\001\000\000\000\b\003D\b\000\000\016\000\000\000\000!\000\000\000\000\002\130\020\012\000\000\002\001\000\000\b@\000\000\000\000\160\132\003\000\000\000\128@\000\002\016\000\000\000\000 !\000\192\000\000 \016\000\000\b\000\000\000\001\001\000\016\000\000\000\000\000\000 \000\000\000\000\000@@\004\000\000\000\000\000\000\000\000\000\000\000\000\016\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\144\000\b\216@\005\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000#a\000\022\n7\196\143@\016>\000\000\0068\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b@\000\000\000\000\128\134\003\000\000\000\128@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\001\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000@@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\012\000\003\001\000\012\\ \000\016\000\000\000\000\000\132\000\000\000\000\b\bp0\000\000\b\004\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\t\000\000\141\132\000X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\0026\016\001`\163|H\244\001\003\224\000\000c\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000 \000\001\000\016\000\000\000\000\000\000 \000\000\000\b\000\000@\004\000\000\000\000\000\000\000\000\000\000\002\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\202@\016\144\004\193\"\176\001\001\144\000\005\004\0008\000\012\004\0001p\128\000@\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\192\0000\016\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\004\000\000\000\000\141\132\000X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\0026\016\001`\163|H\244\001\003\224\000\000c\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000!\000\000\000\000\002\002\024\012\000\000\002\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\128\000\004\000\000\000\000\000\000\000\000\000\000\000\000 \000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\0000\000\012\004\0001p\128\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\202@\016\144\004\193\"\176\001\001\144\000\005\004\0008\000\012\004\0001p\128\000@\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\192\0000\016\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\004\000\000\000\000\141\132\000X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\0026\016\001`\163|H\244\001\003\224\000\000c\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\216@\005\130\141\241'\208\004\015\128\000\001\142\0026\016\001`\163|H\244\001\003\224\000\000c\130\016\000\000\000\000 !\128\192\000\000 \016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\002\000\209\006\000\000\004\000\000\000\b\000\016\000\000\000\1284A\128\000\001\000\000\000\000\000\004\000\000\000 \r\016 \000\000@\000\000\000\000\001\000\000\000\b\003D\b\000\000\016\000\000\000\000\000\200A\000\200\004\193&\208\001\001\128\000\001\004\007\223dB\011\248\212\000\019\007\007\184\226\192\160\208\012\132\016\b\000L\018m\000\016\024\000\000\016@\003!\004\002\000\019\004\139@\004\006\000\000\004\016\000\200@\000\128\004\193\"\208\001\001\128\000\001\004\000\000\000\000\000\000\000\002\000\002\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\016\000\000\000\000\000\000 \000@\000\000\000\000\000\004\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\001\000\000\000\001\000\000\000\b\003D\b\000\000\016\000\000\000\000\000\192\0000\016\000\197\194\000\001\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\016\000\000\004\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\202@\016\144\004\193&\176\001\001\128\000\001\004\0002\144\004$\0010H\172\000@`\000\000A\000\012\164\001\t\001L\018+\000\016\024\000\000\016@\001\000\000\000\b\003D\b\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000@\016\000\000\000\1284@\128\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\133\169*Pb\139L\254\240D\007\152\004\0305!jJ\148\024\162\211?\188\017\001\230\001\007\141@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\018\000\168\000\130!!\192\193\016\006`\016`\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002\160\002\b\132\135\003\004@\025\128A\128P\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000! \n\128\b\"\018\028\012\017\000f\001\006\001@\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\001\000\000\000\001\000\000\000\b\003D\b\000\000\016\000\000\000\000! \n\128\b\"\018\028\012\017\000f\001\006\001@2\016@ \0010H\180\000@`\000\000A\000\012\132\000\b\000L\018-\000\016\024\000\000\016@\000\000\000\000\000\000\000 \000 \000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\128\000\000\000\001\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\192\0000\018\000\213\194\000\001\000\000\000\000\000\b\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000!\000\000\000\000\002\002\028\012\000\000\002\001\000\001\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\000\000\b\b`0\000\000\b\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\1284@\128\000\001\000\000\000\000\002\016\000\000\000\000 !\192\192\000\000 \016\000\016\132\000\000\000\000\b\b`0\000\000\b\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\012\004\0001q\128\000@\000\000\000\000\000\012\000\003\001\000\012\\ \000\016\000\000\000\000\000\132\000\000\000\000\b\b`0\000\000\b\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000!\000\000\000\000\002\002\024\012\000\000\002\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\000\000\b\b@0\000\000\b\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002 \002\b\004\135\000\004@\025\128\000\128\016\012\000\003\001 \r\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000@\000\000\002\000\209\002\000\000\004\000\000\000\000\bH\002 \002\b\004\135\000\004@\025\128\000\128\016\012\164\001\t\000L\018+\000\016\025\000\000P@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000! \b\128\b \018\024\000\017\000f\000\002\000HH\002 \002\b\004\132\000\004@\025\128\000\128\016 \000\000\000\000\004\000`\000\000\000\000\000\000\000\b\000\000\000\000\001\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\012\164\001\t\000L\018+\000\016\025\000\000P@\132\128\"\000 \128H`\000D\001\152\000\b\001! \b\128\b \018\016\000\017\000f\000\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000! \b\128\b \018\016\000\016\000f\000\002\000\0002\016@0\0010I\180\000@`\000\000A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000! \b\128\b \018\016\000\017\000f\000\002\000HH\002 \002\b\004\134\000\004@\025\128\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\000 \128H@\000D\001\152\000\b\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000! \b\128\b \018\024\000\016\000f\000\002\000\bH\002 \002\b\004\132\000\004\000\025\128\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\018\000\136\000\130\001!\000\001\144\006`\000 \004\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002 \002\b\004\134\000\004\000\025\128\000\128\002\018\000\136\000\130\001!\000\001\000\006`\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0001 \n\128\b0\146\028\000\017\000v\000\"\000L\000\000\128\000\004\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\004\000\000\000\000\000L\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\000\003\001\000\012\\ \000\016\000\000\000\000\000\000\000\b\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b@\000\000\000\000\128\132\003\000\000\000\128@\000\002\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\004\b\000\004\000\b\016@\000\001\000\000\000\000\000\001\002\000\000\000\002\004\016\000\000@\000\000\000\000\000@\128\000\000\000\129\000\000\000\016\000\000\000\000\000\000\000\128\000\000 \001\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\129\000@\000\000\131\004\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\128\000\004\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\000\000\000\000\000\000\000\000\144\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b2\016\000 \0010H\180\000@h\000\000E\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\148\187\015\160\248Xp?\229\129\222-\249\195\192\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000H\000\b\000\000\128\002\000\000\000\128\000\000\016\000\018\000\000\000\000 \000\128\000\000 \000\000\004\000\004\128\000\000\000\b\000 \000\000\b\000\000\000\000\132\128\"\0000\128Hp\000D\001\216\000\024@\000H\000\000\000\000\128\002\000\000\000\128\000\000\000\bH\002 \002\b\004\135\000\004@\025\128\000\132\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\000 \128H`\000D\001\152\000\b@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\0000\128Hp\000D\001\216\000\024@\000H\000\000\000\000\128\002\000\000\000\128\000\000\000\bH\002 \002\b\004\135\000\004@\025\128\000\132\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\001\000\000\000\000\000\000\000\000\000! \b\130\b \018\024\000\017\000v\001\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\018\000\136\000\130\001!\128\001\016\006`\016 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\018\000\002\000\000 \000\128\000\000 \000\000\004\000\004\128\000\000\000\b\000 \000\000\b\000\000\001\000\132\128\"\000 \128H`\000D\001\152\000\b@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\016\000\000\128\000\000\000\000\000\000\004\000\000\000\000\000\000\000 \000\000\000\000\0000\000\b\000\0001q\128\000H\000\b\000\000\000\012\000\002\000\000\012\\ \000\018\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\001\000\000\000\016\000\000\000H\000\000\000\000\000\012\000\002\000\000\012\\ \000\018\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\192\0000\016\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\004\000\000\001\000\000\000\000\001\000\000\000\004\000\000\000\000\000\000@\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000\192@\003\023\b\000\004\000\000\000\000\000\000\000\002\000\000\000\000\004\000\000\000\000\000@\000\000\000\000\128\000\000\000\001\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000\192@\003\023\b\000\004\000\000\000\000\000\000\000\002\000\000\000\000\004\000\000\000\000\000@\000\000\000\000\000\000\016\016\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002 \002\b\004\135\000\004@\025\128@\128\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\0008\016\000\197\194\128\001\000\128 \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\018\000\136\000\130\000!\128\001\000\006`\016 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\018\000\002\000\000 \000\128\000\000 \000\000\004\000\004\128\000\000\000\b\000 \000\000\b\000\000\001\000\132\128\"\000 \128\b`\000@\001\152\000\b@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000@\000\000\000\000\000\000\000\000\bH\002 \130\b\000\134\000\004\000\029\128D\128\016\012\128\003\129\000\012\\(\000\016\b\002\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000! \b\128\b \002\024\000\016\000f\001\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\001 \000 \000\002\000\b\000\000\002\000\000\000@\000H\000\000\000\000\128\002\000\000\000\128\000\000\016\bH\002 \002\b\000\134\000\004\000\025\128\000\132\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000 \000\001\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000! \b\128\b \018\028\000\017\000f\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\216@\005\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\141\132\000X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001 \b\000\b \002\016\000\016\000d\000\002\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\192\0000\016\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\216@\005\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200@\000\128\004\193\"\208\001\001\160\000\001\004\000\000\000\000\000\000\000\001\000\000\000\001\000\018\004@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\248H\005\138\173\2433\208\021\015\228\000\003\142\000\016\000\000\000\000\016\000\000\000\000\000\000\000\000\000\022\132\128\000\130\r!\001\001\016\014@\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001 \b\000\b \018\016\000\017\000d\016\002\000\000\016\000\000\000\0000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\000\128\000\130\001!\000\001\000\006\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\b\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002~\018\001b\171|\204\244\005C\249\000\000\227\128\159\132\128X\170\2233=\001P\254@\0008\224\004\128 \000 \128H@\000D\001\144\000\b\000\001 \b\000\b \018\016\000\017\000d\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\128 \000 \128H`\000D\001\144\000\b\000\001 \b\000\b \018\016\000\017\000d\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001 \b\000\b \018\024\000\017\000d\000\002\000\000H\002\000\002\b\004\132\000\004@\025\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")
+  
+  and start =
+    7
+  
+  and action =
+    ((16, "C\134O\006B\154\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\240B\154\000\000\000\000\020\004B\154C\134\028Z\005\162\002\134X\194\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001<\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\170\001r\000\b\000\000\001|\000\252\000\000\002\208\005\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\244\000\000\000\000\000\000\003\012o\180\000\000\000\000\0032\000\000\000\000\000\000\003\186\003\160\000\000\000\000rTN\200\020\004A\028Y\252\020\004R\154O\006\020\004Lj\000\000\021P\000\000\021P\000\007\000\000\0032\000\000\000\000\000\000\001h\000\000\021P\000\000\003\148^\204\132:b\132\000\000\134`|8\000\000J\136D8\000\000I*\027:M \0032r\174B\154C\134\000\000\000\000O\006\020\004R\188\021P\004&y\018\000\000\129\150B\154C\134O\006\020\004\000\000\000\000\000\000\0164\020\184\000V\005|\000\000\004\182\tF\000\000\000\000\000\000\020\004\000\000@\190\000\000{\210C\134\000\000\000\000NF\020\004BjT\208\000\000\001\022\000\000\000\000\002\n\000\000\000\000F\b\001\022\b\138\000V\005\182\000\017\000\000A\028\006n\006>\019\168\020\180\020\004C\134C\134EjEj\019\168\020\180\020\180\020\004\000\000\000\000\000\000O\006\020\004\000\000\000\244\000\000T\208v>v>\000\000\tL\000\000\000}\n@\000\000\003\168\000\000\000\000 \140o\180b@\000\000rTb@\000\000rTrT\005|\000\000rT\0032\000\000\000\000T:o\180R\172D8\003|\001\016\000\000\001\146\000\000\007R\000\000\0114\000\000\000\000LZ\005|\000\000\000\000D8\007jo\180\000\000MLD8N>\000\000\000\000\000\000\001j\000\000rT\000\000\000\252u\156\000\000o\180\005\192o\180\000\000\023|\b\018\0032\000\000\000\000\024p\000\000\t\144\000\000V\\\005\214\000\000\007rrT\007\190\000\000\t\202\000\000\004F\000\000\000\000\005@\000\000\000\000\000\000\025\000\027\220T\208N\198\020\004T\208\000\000\002\234\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000KnEH\000\000\000\000\000\000\001\236 \224v>\000\000\000\000wJ\020\004T\208\000\000\000\000P(T\208Q\148|d\000\000p\014\000\000T\208\000\000\000\000U\184\000\000\000\000\b\186\000\000\023<\000\000\000\000|\202\000\000\136\n}D\000\000\136H\003$\000\000\000\000{R\000\000\b\176\000\000\000\000\023\002v\210\000\000\000\000\000\000@\000\019\168\025\248\021\142\000\000\000\000\000\000\000\000\000\028\000\000\000\000W\146\005\012\b\216\002\198o\180\000\216\n\002\000\000\000\000\006\000\b\216\003\180\000\000O\006G\176Ej\019\168\020\180\005\162\004\\\000&\000\000\000\000\000\000\tfA\028A\028\005\162\004\\\007\234A\028\000\000f|\001\224\021P\tL\006Hz\150\000\000o\180c@o\180Z\182c\214o\180\004\174o\180dl\000\000\000\000\021J\001\016[L\tF\001\016\\\006\000\000g\018\001\224\000\000A\028g\168\000\000\005P\011X\\\192\000\000\000\000\000\000\000\000\000\000\0240\000\000\000\000\027\134\000\000\t>\020\180\000\000YfBb\000\000\021\196\000\000\000\000A\028\024\170\000\000\000\000\000\000\000\000X\030\000\000\003\168\000\000I\168\006B\0224\000\000\021\218M\024O\006\020\004H\194N\198\020\004\0164\0164\000\000\000\000\000\000\000\000\001\232\020ZA\168\000\000O\188PrEj\019\168\020\180\006\150A\"\000\000\028\244\000\000Q(Q\222}\170\022do\180\005\162\000\000O\006\020\004\000\000wJ\020\004v>T\208@\160\000\000O\006\020\004y|\000b\000\000T\208@\000o\180\004\168\003\180\nZ\000\000\000\000\000\000F\b\005\b\005\b\000\000\011\180s2\000\000wJ\020\004T\208\023\002\000\000N\198\020\004\0164\021\218\0164\002\220\003\158\000\000\000\000\0164\011\198\000\000\011\216\000\000\0164\003\208\0120\000\000!\212\000\000\007P\000\000\000\000\025\170\000\000\017(\022\206\000\000\000\000\000\000\007\000\000\000\000\000\026\158\000\000\027\146\000\000\028\134\000\000\018\028\023\194\000\000\000\000\000\000B\154\000\000\000\000\000\000\000\000\029z\000\000\030n\000\000\031b\000\000 V\000\000!J\000\000\">\000\000#2\000\000$&\000\000%\026\000\000&\014\000\000'\002\000\000'\246\000\000(\234\000\000)\222\000\000*\210\000\000+\198\000\000,\186\000\000-\174\000\000.\162\000\000/\150\020\004T\208V\230F\240\005\b\012\134h T\208\000\000\000\000\000\000o\180\000\000\026\132\138\004\000\000\024\236o\180\027x\012\018\000\000\000\000\000\000\000\000h \000\000\000\000\002f\012\186\000\000B\146\000\000\000\000\138H\000\000\006\180\000\000\000\000M \005\b\012Vo\180\006\162\000\000\000\000\nP\0032\000\000o\180\tr\000\000\000\000\012\172\000\000\000\000\000\000\025@o\180\n\018\000\000\000\000\027\198\000\000\000\000~$\000\000\028\028~\138\000\000\028\186\127\004\000\000\029\016\004l\000\000\000\000\000\000\000\000\029\174T\208\030\004s\172s\172\000\000\000\000\000\0000\138\000\000\011H\000\000\000\000\000\000h\134\000\000\000\000\000}\bb\000\000h\224\000\000\000\000\000\000ib\000\000\000\000\000\000i\228\000\000\000\000\000\000\0164\004\196\tV\000\000j>\000\000\005\184\000\0001~\000\000j\192\000\000\006\172\000\0002r\000\000kB\000\000\007\160\000\0003f\"\200\000\000\b\014\b\148\000\0004Z\000\000\011\140\t\136\000\0005N\000\000k\196\n|\000\0006B\0046\nJ\000\000l\030\011p\000\00076\000\000l\160\012d\000\0008*\000\000m\"\rX\000\0009\030\014L\000\000:\018\015@\019\016\000\000\000\000\000\000m|\000\000\000\000m\254\000\000\000\000n\128\000\000\t\020\000\000\000\000\000\000\012\172\000\000\r\002\000\000\000\000G\216\005\b\r\210s2D8\002\234\000\000\000\000s2\000\000\000\000\000\000s2\000\000\r\172\000\000\000\000\000\000\000\000\000\000\000\000;\006T\208\000\000\000\000\r\242\000\000;\250\000\000<\238\000\000\030\162\000\000\000\000\006\222\000\000\000\000T\208\000\000\000\000\127\026\t\018\000\000\000\000I\168\000\000\005\212\000\000\000\000]fH\194\000\000St\000\000\012<\000\000\000\000\0022\b\154\000\000\000\000\021\218\025.\tL\000\000\031\152\000\000\031\172\021\184\022\234\000\000\000\000\005\144\000\000\000\000\001\230\021FU0\000\000\024\182\000\000\006\244\000\000\000\000\t`\000\000\000\000]\232\005\188\0022\000\000\000\000\n,\000\000\000\000\012Z\000\000\000\000\000\000\019\168\020\180\004\174\000\000\000\000\007\150\000V\014h\004\\\020\180y\222A\028\020\144\020\180z\\\r\236\000\000\000\000\004\\\000\000E$\020\004\000\142\000\000\b \014l\000\000\014n\000\000\000\000\003\186D8\006\168\000\000\014N\r\228M \n^o\180\0190\005\216\012\132\002\252\000\000\027$\014\156\000\000\006\168\000\000\000\000\014\194D8^\128\000\000d\234D8\014\150D8o\024^\254\005\216\014Z\000\000\000\000\020\004\130\014\000\000T\208s\172\000\000\000\000\014\200\000\000\000\000\000\000=\226\014\240v>>\214_\170\000\000\000\000Cj\000\000\029\028\000\000C\182\000\000\025\182\000\000A\028\029\232\000\000\130p\000\000\019\168\020\180\130p\000\000\025\204\020\184\000V\0032\132\188A\028\127\168s\172\000\000\000V\nF\004\\s\172\000\000\014\230\004\\s\172\134\132\000V\014\242\004\\s\172\134\132\000\000\000\000B\154C\134T\208F4\000\000\000\000B\154C\134Ej\019\168\020\180\130p\000\000\028Z\005\162\002\134\014\024`p\166D|\000\000\020\004o\180\011Zo\180S\252D|\000\000\011\190\000\000\000\000D|\000\000\000\000VP\000\000s\172\134\222\019\174\007J\011\184\015*\014\216\024`s\172\134\222\000\000\000\000\019\174\007J\011\184\0150\014\196N\018ehD8\015NN\018rT\003\254\015RN\018D8\015ZN\018\011\252\r\028q$q\162\000\000\130\240\000\000\000\000s\172\136\252\019\174\007J\011\184\015P\014\232N\018s\172\136\252\000\000\000\000\000\000\137v\000\000\000\000\000\000\000\000\000\000\000\000h \000\000\135V\020\004\021P\015xy\018\000\000\129\150\135V\000\000\000\000\137\000\020\004\021P\015~\015\016\132:rT\006\168\015\182\000\000\000\000r\026t*\020\004\000\000\128z\000\142\000\000\000\000tv\137\000\000\000\000\000\000\000z\218EZO\200\006\168\015\184\000\000\000\000\000\000t*\020\004\000\000\006\168\015\186\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\r`\020\184\019\174\007J\011\184\015\150t\154B\178\020\004BjG\130\026\158\002\252\006\168\015\162\003\198\000\000\000\000\015T\000\000\000\000F\224\000\000\bX\012\172\000\000\rD\000\000\015\174\015Ro\180Yn\015\218\004<\000\000\000\000\015\136\000\000\000\000\028n\007r\011\186\000\000\015\222u<\131\030\005\b\015~o\180\012\238\000\000\000\000\015\148\000\000\000\000\000\000F\224\000\000\t\132\012\210\000\000\r\150\000\000\015\242\015\128M \000\000\016\000u\222\136J\005\b\015\162o\180\012\244\000\000\000\000\015\182\000\000\000\000\000\000\020\004\000\000F\224\000\000\020&\019\206B\178B\178w\196B\154\020\004\130\014T\208\011&\000\000\011.\000V\000\000\r\144B\178o\180\012\128\005|\000\000\020\004U\184t\154B\178\nBB\178\000\000DfEH\000\000`>\000\000\000\000`\214\000\000\000\000an\000\000\r\172B\178b\006\130\014T\208\011&\000\000\000\"\000\000\000\000N\018\012l\000\000\000\000L\028\016\028\000\000F\224\000\000B\178L\028F\224\000\000\020\004o\180F\224\000\000\r`\000\000\000\000F\224\000\000\000\000G\130\000\000\131JN\018\015\202B\178\131\202t\154\000\000s\172\135\176\019\174\007J\011\184\016 t\154s\172\135\176\000\000\000\000\000\000\137zO\006\000\000\000\000\000\000\000\000\000\000\000\000\133\232s\172\000\000\135V\000\000\000\000\000\000\000\000h \137z\000\000\016V\000\000\000\000\133\232\016b\000\000h \137z\000\000\000\000\r\196\000\000\000\000e\230\026\024\000\000\000\000@\160\000\000o\180\r`\000\000G\130\r\238\000\000\000\000\000\000\r\184\000\000\000\000\000\000Ej\019\168\020\180\004\174\000\000Fz\000\000\030\016\000\000\001\180\000\000\000\000\016l\000\000\016\150{R\000\000?\202\016t\000\000\000\000\016j\0268\022h\000\142x>\007:\020\004\000\000s\172\000\000\000\000\000\000\000\000\000\000\000\000\000\000xP\007:\020\004\000\000\r\242y\018\000\000\129\150\000\000\016z\0268\022hs\172\000\000\016\158\000\000\006\162\r\\\020\004K\150\000\000\000\000\028F\\\234\000\000\000\000\0160\000\000\016\132o\180\000\000\r\138\n\138\005|\000\000\000\000o\180\007\246\b\198\000\000o\180\t\b\006\168\016\170\000\000\000\000\128~\000\000\000\000\132:\000\000tv\000\000\016\162\0268\023\\h \000\000\000\000\000\000\000\000\0144y\018\132:\000\000tv\000\000\016\164\0268\023\\h \000\000\014T\000\000\000\000\030\220\000\000s\172\000\000\016\188\000\000\000\000\016,\000\000\0166\000\000\016J\000\000\000\000K \016f\000\000\000\000o\180\000\000\r\168\000\000\000\000\016h\000\000\000\000T\208\031\150\000\000\000\000H\194\0032\129<\000\000\000\000\000\000\000\000\000\000w<\023l\000\000\000\000\017\b\000\000JV\000\000\014D\017\n\000\000\017\012\000\000I\168I\168\138\\\138\\\000\000\000\000sN\138\\\000\000\000\000\000\000sN\138\\\016~\000\000\016\132\000\000"), (16, "\b\185\b\185\000\006\002\026\005\253\b\185\002\134\002\138\b\185\002\182\002\194\b\185\003V\b\185\006R\002\198\b\185\023n\b\185\b\185\b\185\002\030\b\185\b\185\005\253\006\174\006\178\002\202\b\185\003\n\003\014\t\170\b\185\011\218\b\185\003\206\003\018\023r\002\206\006\182\b\185\b\185\003\150\003\154\b\185\003\158\002\250\003\170\003\178\006\142\004-\b\185\b\185\002~\001j\b\162\003\006\b\185\b\185\b\185\007\214\007\218\007\230\007\250\004-\0056\b\185\b\185\b\185\b\185\b\185\b\185\b\185\b\185\b\185\bn\000\238\b\185\0156\b\185\b\185\002N\bz\b\146\b\230\005B\005F\b\185\b\185\b\185\004-\b\185\b\185\b\185\b\185\b\166\b\194\r\150\b\185\003Z\b\185\b\185\000\238\b\185\b\185\b\185\b\185\b\185\b\185\005J\007\238\b\185\b\185\b\185\b\006\004\018\b\250\015:\b\185\b\185\b\185\b\185\012]\012]\023v\006V\006\005\012]\003}\012]\012]\015F\012]\012]\012]\012]\0046\012]\012]\0061\012]\012]\012]\001\186\012]\012]\006\005\012]\004-\012]\012]\012]\012]\012]\012]\012]\012]\015N\001*\0061\012]\004\162\012]\012]\012]\012]\012]\000\238\012]\012]\017\186\012]\003\174\012]\012]\012]\001v\001\186\012]\012]\012]\012]\012]\012]\012]\000\238\012]\012]\012]\012]\012]\012]\012]\012]\012]\012]\012]\003}\012]\012]\0022\012]\012]\004\146\003*\001f\004-\012]\012]\012]\012]\012]\001r\012]\012]\012]\012]\012]\025\022\012]\012]\004>\012]\012]\003.\012]\012]\012]\012]\012]\012]\012]\012]\012]\012]\012]\012]\012]\025\026\004-\012]\012]\012]\012]\001\153\001\153\001\153\0042\006\226\001\153\001\162\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\166\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\007\030\b\149\001\153\0026\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\004\150\001\153\001\153\001\153\004B\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\006=\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\n\134\001\153\001\153\n\146\0036\006=\007\222\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\014~\b\030\001\153\005v\001\153\001\153\003:\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\001\153\b\149\001\153\001\153\001\153\001\153\001\153\t\237\t\237\018\178\001\002\001\170\t\237\0036\t\237\t\237\003y\t\237\t\237\t\237\t\237\001\186\t\237\t\237\001~\t\237\t\237\t\237\001b\t\237\t\237\018\186\t\237\003:\t\237\t\237\t\237\t\237\t\237\t\237\t\237\t\237\001n\005\254\001z\t\237\004-\t\237\t\237\t\237\t\237\t\237\007\173\t\237\t\237\rf\t\237\001\194\t\237\t\237\t\237\002f\004-\t\237\t\237\t\237\t\237\t\237\t\237\t\237\004-\t\237\t\237\t\237\t\237\t\237\t\237\t\237\t\237\t\237\t\237\t\237\000\238\t\237\t\237\003y\t\237\t\237\004-\001\002\001\170\004Z\t\237\t\237\t\237\t\237\t\237\001\198\t\237\t\237\t\237\t\237\t\018\006j\tB\t\237\001\186\t\237\t\237\003\218\t\237\t\237\t\237\t\237\t\237\t\237\t\237\t\237\t\237\t\237\t\237\t\237\t\237\004-\t\237\t\237\t\237\t\237\t\237\003\153\003\153\004-\003\222\0042\003\153\006\173\003\153\003\153\001\178\003\153\003\153\003\153\003\153\000\238\003\153\003\153\002B\003\153\003\153\003\153\t\022\003\153\003\153\015V\003\153\007\154\003\153\003\153\003\153\003\153\003\153\003\153\003\153\003\153\r\018\001\210\r\030\003\153\000\238\003\153\003\153\003\153\003\153\003\153\bM\003\153\003\153\003)\003\153\001\186\003\153\003\153\003\153\007\210\004J\003\153\003\153\003\153\003\153\003\153\003\153\003\153\003)\003\153\003\153\003\153\003\153\003\153\003\153\003\153\003\153\003\153\003\153\003\153\006\138\t\n\t:\011\130\003\153\003\153\005\006\000\238\001\214\021\166\003\153\003\153\003\153\003\153\003\153\002\162\003\153\003\153\003\153\003\153\t\018\015\182\tB\003\153\n\134\003\153\003\153\n\146\003\153\003\153\003\153\003\153\003\153\003\153\003\153\003\153\003\153\003\153\003\153\003\153\003\153\006\170\003\153\003\153\003\153\003\153\003\153\003\141\003\141\001\002\001\170\bM\003\141\003\237\003\141\003\141\024\254\003\141\003\141\003\141\003\141\b\129\003\141\003\141\005\n\003\141\003\141\003\141\021\238\003\141\003\141\012\170\003\141\003\206\003\141\003\141\003\141\003\141\003\141\003\141\003\141\003\141\007\154\n\134\014\254\003\141\n\146\003\141\003\141\003\141\003\141\003\141\000\238\003\141\003\141\000\238\003\141\004\150\003\141\003\141\003\141\005\153\015\006\003\141\003\141\003\141\003\141\003\141\003\141\003\141\014\230\003\141\003\141\003\141\003\141\003\141\003\141\003\141\003\141\003\141\003\141\003\141\003\237\t\n\t:\007\018\003\141\003\141\b\210\006b\006z\005\018\003\141\003\141\003\141\003\141\003\141\002\226\003\141\003\141\003\141\003\141\t\018\025\002\tB\003\141\002\138\003\141\003\141\014r\003\141\003\141\003\141\003\141\003\141\003\141\003\141\003\141\003\141\003\141\003\141\003\141\003\141\0042\003\141\003\141\003\141\003\141\003\141\ti\ti\b\145\014v\006\r\ti\003R\ti\ti\005\153\ti\ti\ti\ti\014\n\ti\ti\002\218\ti\ti\ti\014\178\ti\ti\006\r\ti\004-\ti\ti\ti\ti\ti\ti\ti\ti\004-\004-\004\230\ti\004-\ti\ti\ti\ti\ti\007Z\ti\ti\000\238\ti\012.\ti\ti\ti\001\130\004\018\ti\ti\ti\ti\ti\ti\ti\000\238\ti\ti\ti\ti\ti\ti\ti\ti\ti\ti\ti\000\238\ti\ti\bj\ti\ti\b\145\006\130\015\254\004-\ti\ti\ti\ti\ti\004-\ti\ti\ti\ti\ti\018\134\ti\ti\003b\ti\ti\003f\ti\ti\ti\ti\ti\ti\ti\ti\ti\ti\ti\ti\ti\007\222\004-\ti\ti\ti\ti\ta\ta\004\178\014\014\n\234\ta\b}\ta\ta\018\142\ta\ta\ta\ta\004-\ta\ta\005\129\ta\ta\ta\003q\ta\ta\n\238\ta\014\186\ta\ta\ta\ta\ta\ta\ta\ta\007\154\014\150\015^\ta\006\238\ta\ta\ta\ta\ta\005y\ta\ta\000\238\ta\012F\ta\ta\ta\000\238\006\246\ta\ta\ta\ta\ta\ta\ta\000\238\ta\ta\ta\ta\ta\ta\ta\ta\ta\ta\ta\004-\ta\ta\002\138\ta\ta\002\194\tN\018F\011\006\ta\ta\ta\ta\ta\004F\ta\ta\ta\ta\ta\bB\ta\ta\r\218\ta\ta\tR\ta\ta\ta\ta\ta\ta\ta\ta\ta\ta\ta\ta\ta\tv\017>\ta\ta\ta\ta\tq\tq\002\209\004-\012\145\tq\014\154\tq\tq\017B\tq\tq\tq\tq\004n\tq\tq\012\145\tq\tq\tq\r\226\tq\tq\004-\tq\000\n\tq\tq\tq\tq\tq\tq\tq\tq\005F\000\238\004\246\tq\nZ\tq\tq\tq\tq\tq\bQ\tq\tq\0042\tq\012^\tq\tq\tq\002\209\tN\tq\tq\tq\tq\tq\tq\tq\be\tq\tq\tq\tq\tq\tq\tq\tq\tq\tq\tq\012r\tq\tq\006\210\tq\tq\004\194\000\238\006\170\002Z\tq\tq\tq\tq\tq\004\238\tq\tq\tq\tq\tq\021\198\tq\tq\019\026\tq\tq\000\238\tq\tq\tq\tq\tq\tq\tq\tq\tq\tq\tq\tq\tq\006\170\001*\tq\tq\tq\tq\tQ\tQ\002\209\014:\bQ\tQ\004\150\tQ\tQ\021\206\tQ\tQ\tQ\tQ\006\018\tQ\tQ\005y\tQ\tQ\tQ\011\222\tQ\tQ\be\tQ\000\n\tQ\tQ\tQ\tQ\tQ\tQ\tQ\tQ\011\238\006\022\011\254\tQ\005\210\tQ\tQ\tQ\tQ\tQ\026\030\tQ\tQ\015>\tQ\012v\tQ\tQ\tQ\002\209\017\198\tQ\tQ\tQ\tQ\tQ\tQ\tQ\r\246\tQ\tQ\tQ\tQ\tQ\tQ\tQ\tQ\tQ\tQ\tQ\r.\tQ\tQ\bi\tQ\tQ\006f\014>\r\250\000\238\tQ\tQ\tQ\tQ\tQ\002\254\tQ\tQ\tQ\tQ\tQ\002\230\tQ\tQ\002\138\tQ\tQ\014\162\tQ\tQ\tQ\tQ\tQ\tQ\tQ\tQ\tQ\tQ\tQ\tQ\tQ\018V\000\238\tQ\tQ\tQ\tQ\tY\tY\022R\014\166\007\142\tY\026\"\tY\tY\006\170\tY\tY\tY\tY\002\234\tY\tY\003\198\tY\tY\tY\012\030\tY\tY\022Z\tY\b\129\tY\tY\tY\tY\tY\tY\tY\tY\0126\r2\012N\tY\bi\tY\tY\tY\tY\tY\007\165\tY\tY\000\238\tY\012\138\tY\tY\tY\n\202\004\254\tY\tY\tY\tY\tY\tY\tY\000\238\tY\tY\tY\tY\tY\tY\tY\tY\tY\tY\tY\0026\tY\tY\011\"\tY\tY\006v\014\194\018\146\b\129\tY\tY\tY\tY\tY\006\190\tY\tY\tY\tY\tY\004-\tY\tY\002\230\tY\tY\016\146\tY\tY\tY\tY\tY\tY\tY\tY\tY\tY\tY\tY\tY\016\158\b\129\tY\tY\tY\tY\t\145\t\145\011\018\b\190\005\133\t\145\000\238\t\145\t\145\011\018\t\145\t\145\t\145\t\145\001\186\t\145\t\145\003\210\t\145\t\145\t\145\012\174\t\145\t\145\004\150\t\145\000\238\t\145\t\145\t\145\t\145\t\145\t\145\t\145\t\145\012\194\011F\012\214\t\145\014\198\t\145\t\145\t\145\t\145\t\145\023\026\t\145\t\145\000\238\t\145\012\158\t\145\t\145\t\145\002f\018\138\t\145\t\145\t\145\t\145\t\145\t\145\t\145\005\137\t\145\t\145\t\145\t\145\t\145\t\145\t\145\t\145\t\145\t\145\t\145\011\026\t\145\t\145\017\022\t\145\t\145\018\250\015r\018\190\026\006\t\145\t\145\t\145\t\145\t\145\nZ\t\145\t\145\t\145\t\145\t\145\004-\t\145\t\145\004F\t\145\t\145\011\190\t\145\t\145\t\145\t\145\t\145\t\145\t\145\t\145\t\145\t\145\t\145\t\145\t\145\019\018\007^\t\145\t\145\t\145\t\145\t\129\t\129\011\194\018\182\007\177\t\129\002\230\t\129\t\129\018v\t\129\t\129\t\129\t\129\011\190\t\129\t\129\004N\t\129\t\129\t\129\002\174\t\129\t\129\007\181\t\129\000\238\t\129\t\129\t\129\t\129\t\129\t\129\t\129\t\129\001\198\012\134\004E\t\129\019z\t\129\t\129\t\129\t\129\t\129\017N\t\129\t\129\000\238\t\129\012\186\t\129\t\129\t\129\b\222\011\018\t\129\t\129\t\129\t\129\t\129\t\129\t\129\022\014\t\129\t\129\t\129\t\129\t\129\t\129\t\129\t\129\t\129\t\129\t\129\019&\t\129\t\129\019f\t\129\t\129\022\230\004E\002\233\007\165\t\129\t\129\t\129\t\129\t\129\t&\t\129\t\129\t\129\t\129\t\129\018N\t\129\t\129\t.\t\129\t\129\014*\t\129\t\129\t\129\t\129\t\129\t\129\t\129\t\129\t\129\t\129\t\129\t\129\t\129\0042\014\206\t\129\t\129\t\129\t\129\ty\ty\014.\019\006\023~\ty\018\210\ty\ty\019~\ty\ty\ty\ty\001\186\ty\ty\014\210\ty\ty\ty\t>\ty\ty\023\130\ty\007.\ty\ty\ty\ty\ty\ty\ty\ty\015\130\022\254\nr\ty\003e\ty\ty\ty\ty\ty\020\014\ty\ty\n\170\ty\012\206\ty\ty\ty\018\238\019J\ty\ty\ty\ty\ty\ty\ty\n\206\ty\ty\ty\ty\ty\ty\ty\ty\ty\ty\ty\021\202\ty\ty\007.\ty\ty\022V\017\166\012\153\004F\ty\ty\ty\ty\ty\n\254\ty\ty\ty\ty\ty\017\222\ty\ty\004F\ty\ty\012\165\ty\ty\ty\ty\ty\ty\ty\ty\ty\ty\ty\ty\ty\021\210\019&\ty\ty\ty\ty\t\137\t\137\019\030\011.\023\190\t\137\000\238\t\137\t\137\000\238\t\137\t\137\t\137\t\137\r>\t\137\t\137\020\018\t\137\t\137\t\137\025\202\t\137\t\137\024\198\t\137\007\129\t\137\t\137\t\137\t\137\t\137\t\137\t\137\t\137\022^\022.\005}\t\137\022\142\t\137\t\137\t\137\t\137\t\137\026\002\t\137\t\137\024\226\t\137\012\226\t\137\t\137\t\137\024\158\rF\t\137\t\137\t\137\t\137\t\137\t\137\t\137\000\238\t\137\t\137\t\137\t\137\t\137\t\137\t\137\t\137\t\137\t\137\t\137\024\210\t\137\t\137\007\169\t\137\t\137\rZ\004\193\r\138\001\186\t\137\t\137\t\137\t\137\t\137\r\182\t\137\t\137\t\137\t\137\t\137\023\194\t\137\t\137\000\238\t\137\t\137\022\242\t\137\t\137\t\137\t\137\t\137\t\137\t\137\t\137\t\137\t\137\t\137\t\137\t\137\023R\001\186\t\137\t\137\t\137\t\137\t\217\t\217\025\150\007.\026\166\t\217\026\018\t\217\t\217\027\003\t\217\t\217\t\217\t\217\004E\t\217\t\217\007.\t\217\t\217\t\217\014\250\t\217\t\217\024\162\t\217\015\026\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\026z\015B\024\230\t\217\015J\t\217\t\217\t\217\t\217\t\217\024\214\t\217\t\217\015f\t\217\012\238\t\217\t\217\t\217\002\174\015j\t\217\t\217\t\217\t\217\t\217\t\217\t\217\015\146\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\015\166\t\217\t\217\015\190\t\217\t\217\015\210\015\250\016\014\016\162\t\217\t\217\t\217\t\217\t\217\016\182\t\217\t\217\t\217\t\217\t\217\026\170\t\217\t\217\017\014\t\217\t\217\017\026\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\003\190\005\206\t\217\t\217\t\217\t\217\003\137\003\137\017\226\017\230\017\250\003\137\017\254\003\137\003\137\018^\003\137\003\137\003\137\003\137\018b\003\137\003\137\018\154\003\137\003\137\003\137\018\158\003\137\003\137\018\198\003\137\018\202\003\137\003\137\003\137\003\137\003\137\003\137\003\137\003\137\018\246\019\174\019\178\003\137\019\214\003\137\003\137\003\137\003\137\003\137\019\218\003\137\003\137\019\234\003\137\019\250\003\137\003\137\003\137\020\006\020B\003\137\003\137\003\137\003\137\003\137\003\137\003\137\020F\003\137\003\137\003\137\003\137\003\137\003\137\003\137\003\137\003\137\003\137\003\137\020\146\t\n\t:\020\186\003\137\003\137\020\190\020\206\021\030\021>\003\137\003\137\003\137\003\137\003\137\021~\003\137\003\137\003\137\003\137\t\018\021\162\tB\003\137\021\178\003\137\003\137\021\218\003\137\003\137\003\137\003\137\003\137\003\137\003\137\003\137\003\137\003\137\003\137\003\137\003\137\021\222\003\137\003\137\003\137\003\137\003\137\001\221\001\221\021\234\021\250\022\022\001\221\022&\002\138\001\221\022:\002\194\001\221\t\"\001\221\022f\002\198\001\221\022j\001\221\001\221\001\221\022v\001\221\001\221\022\134\t*\022\154\002\202\001\221\001\221\001\221\001\221\001\221\t2\001\221\023\142\023\230\024\014\002\206\024v\001\221\001\221\001\221\001\221\001\221\024\134\002\250\001\170\025\"\001\221\025*\001\221\001\221\002~\025:\025F\003\006\001\221\001\221\001\221\007\214\007\218\007\230\025\170\012\018\0056\001\221\001\221\001\221\001\221\001\221\001\221\001\221\001\221\001\221\025\190\t\n\t:\025\238\001\221\001\221\025\246\0262\026Z\026\146\005B\005F\001\221\001\221\001\221\026\194\001\221\001\221\001\221\001\221\012\026\026\206\012f\001\221\026\214\001\221\001\221\026\223\001\221\001\221\001\221\001\221\001\221\001\221\005J\007\238\001\221\001\221\001\221\b\006\004\018\026\239\027\015\001\221\001\221\001\221\001\221\t\193\t\193\027[\027o\027w\t\193\027\179\002\138\t\193\027\187\002\194\t\193\t\193\t\193\000\000\002\198\t\193\000\000\t\193\t\193\t\193\000\000\t\193\t\193\000\000\t\193\000\000\002\202\t\193\t\193\t\193\t\193\t\193\t\193\t\193\000\000\000\000\000\000\002\206\000\000\t\193\t\193\t\193\t\193\t\193\000\000\002\250\001\170\000\000\t\193\000\000\t\193\t\193\002~\000\000\000\000\003\006\t\193\t\193\t\193\007\214\007\218\007\230\000\000\t\193\0056\t\193\t\193\t\193\t\193\t\193\t\193\t\193\t\193\t\193\000\000\t\193\t\193\000\000\t\193\t\193\000\000\000\000\000\000\000\000\005B\005F\t\193\t\193\t\193\000\000\t\193\t\193\t\193\t\193\t\193\000\000\t\193\t\193\000\000\t\193\t\193\000\000\t\193\t\193\t\193\t\193\t\193\t\193\005J\007\238\t\193\t\193\t\193\b\006\004\018\000\000\000\000\t\193\t\193\t\193\t\193\t\189\t\189\000\000\000\000\000\000\t\189\000\000\002\138\t\189\000\000\002\194\t\189\t\189\t\189\000\000\002\198\t\189\000\000\t\189\t\189\t\189\000\000\t\189\t\189\000\000\t\189\000\000\002\202\t\189\t\189\t\189\t\189\t\189\t\189\t\189\000\000\000\000\000\000\002\206\000\000\t\189\t\189\t\189\t\189\t\189\000\000\002\250\001\170\000\000\t\189\000\000\t\189\t\189\002~\000\000\000\000\003\006\t\189\t\189\t\189\007\214\007\218\007\230\000\000\t\189\0056\t\189\t\189\t\189\t\189\t\189\t\189\t\189\t\189\t\189\000\000\t\189\t\189\000\000\t\189\t\189\000\000\000\000\000\000\000\000\005B\005F\t\189\t\189\t\189\000\000\t\189\t\189\t\189\t\189\t\189\000\000\t\189\t\189\000\000\t\189\t\189\000\000\t\189\t\189\t\189\t\189\t\189\t\189\005J\007\238\t\189\t\189\t\189\b\006\004\018\000\000\000\000\t\189\t\189\t\189\t\189\002)\002)\000\000\000\000\000\000\002)\000\000\002\138\002)\000\000\002\194\002)\t\"\002)\000\000\002\198\002)\000\000\002)\002)\002)\000\000\002)\002)\000\000\t*\000\000\002\202\002)\002)\002)\002)\002)\t2\002)\007\153\000\000\000\000\002\206\007\153\002)\002)\002)\002)\002)\000\000\002\250\001\170\000\000\002)\000\000\002)\002)\002~\000\000\000\000\003\006\002)\002)\002)\007\214\007\218\007\230\000\000\012\018\0056\002)\002)\002)\002)\002)\002)\002)\002)\002)\007\153\004\149\002)\000\000\002)\002)\000\000\000\000\004-\000\000\005B\005F\002)\002)\002)\004-\002)\002)\002)\002)\0066\007\153\000\000\002)\004\149\002)\002)\004-\002)\002)\002)\002)\002)\002)\005J\007\238\002)\002)\002)\b\006\004\018\000\000\000\000\002)\002)\002)\002)\004-\000\000\004-\000\000\004-\004-\004-\004-\004-\004-\004-\004\190\004-\000\238\004-\004-\000\238\004-\004-\004-\004-\004-\004-\004-\004-\004-\004-\004-\000\000\004-\004-\000\000\000\238\004-\004-\004-\004-\004-\004-\004-\004-\000\000\004-\004-\004-\004-\004-\004-\004-\004-\002\230\004-\004-\004-\004-\004-\004-\004-\004-\000\238\004-\004-\004-\004-\004-\004-\004-\004-\000\000\000\000\004-\006\222\000\000\004-\004-\004-\000\238\004-\000\000\000\000\004-\004-\004-\004-\004-\004-\004-\004-\004-\b\"\001\170\004-\004-\003\142\002\209\002\138\004-\002\209\018:\r\254\004-\004-\003n\014\030\0142\014B\000\000\000\000\004-\004-\004-\007J\000\000\004-\004-\004-\004-\000\000\000\129\004-\000\129\000\n\000\129\000\129\000\129\000\129\000\129\000\129\000\129\000\238\000\129\022\186\000\129\000\129\003\138\000\129\000\129\002\209\000\000\000\129\000\129\002~\000\129\000\129\000\000\000\129\000\000\000\129\000\129\002\209\002\209\000\129\000\129\000\000\000\129\000\129\000\129\000\000\000\129\015\014\000\129\000\129\000\129\000\129\000\129\000\129\000\129\000\129\002\230\006\162\000\129\000\129\012I\0125\000\129\000\129\000\000\000\129\000\129\000\129\000\129\000\129\000\129\000\129\000\129\000\129\000\000\000\000\000\000\000\000\012I\000\129\000\000\000\129\000\000\000\129\002\006\006}\000\000\000\129\000\129\000\129\000\129\000\129\000\129\000\129\000\129\b\"\014\130\002\014\000\129\000\000\002\018\0125\000\000\000\222\006>\r\254\b\169\000\129\006}\014\030\0142\014B\007\166\000\129\000\129\000\129\000\129\000\000\000\000\000\129\000\129\000\129\000\129\002\025\002\025\014b\000\000\000\000\002\025\b\169\002\138\002\025\007\170\002\194\002\025\000\000\002\025\000\000\002\198\002\025\007&\002\025\002\025\002\025\000\000\002\025\002\025\000\000\007.\000\000\002\202\002\025\002\025\002\025\002\025\002\025\0072\002\025\007\154\000\000\000\000\002\206\000\000\002\025\002\025\002\025\002\025\002\025\006\149\002\250\007\234\000\238\002\025\000\000\002\025\002\025\002~\000\000\000\000\003\006\002\025\002\025\002\025\007\214\007\218\007\230\000\000\006\149\0056\002\025\002\025\002\025\002\025\002\025\002\025\002\025\002\025\002\025\000\000\t\n\t:\0156\002\025\002\025\002N\000\000\000\000\000\000\005B\005F\002\025\002\025\002\025\000\000\002\025\002\025\002\025\002\025\t\018\007\174\tB\002\025\000\000\002\025\002\025\000\000\002\025\002\025\002\025\002\025\002\025\002\025\005J\007\238\002\025\002\025\002\025\b\006\004\018\000\000\015:\002\025\002\025\002\025\002\025\0025\0025\006\149\000\000\006\170\0025\007=\000\000\0025\015F\000\000\0025\007\226\0025\b\173\000\000\0025\000\000\0025\0025\0025\002\138\0025\0025\000\000\000\000\b\157\000\000\0025\0025\0025\0025\0025\000\000\0025\015N\007=\b\173\000\000\000\000\0025\0025\0025\0025\0025\006\030\000\000\017\170\b\157\0025\007=\0025\0025\007=\bb\005\218\000\000\0025\0025\0025\007=\003\198\025N\017\182\007=\017\198\0025\0025\0025\0025\0025\0025\0025\0025\0025\005\222\t\n\t:\0156\0025\0025\002N\000\000\000\000\000\000\000\238\002\230\0025\0025\0025\000\000\0025\0025\0025\0025\t\018\000\000\tB\0025\000\000\0025\0025\000\000\0025\0025\0025\0025\0025\0025\b9\000\000\0025\0025\0025\000\238\b\246\000\000\015:\0025\0025\0025\0025\0021\0021\000\000\001\002\001\170\0021\000\000\005\226\0021\015F\005\166\0021\000\000\0021\000\000\b\157\0021\005\238\0021\0021\0021\005\250\0021\0021\b9\000\000\000\000\000\000\0021\0021\0021\0021\0021\000\000\0021\015N\005\226\000\000\000\000\005\166\0021\0021\0021\0021\0021\b9\005\238\000\000\000\000\0021\005\250\0021\0021\000\000\000\000\007z\006\222\0021\0021\0021\000\000\000\000\020\234\000\000\000\000\000\000\0021\0021\0021\0021\0021\0021\0021\0021\0021\007~\t\n\t:\b9\0021\0021\000\000\004\190\000\000\000\000\b9\001\186\0021\0021\0021\000\000\0021\0021\0021\0021\t\018\007J\tB\0021\000\000\0021\0021\000\000\0021\0021\0021\0021\0021\0021\b5\000\000\0021\0021\0021\000\238\018f\007\182\006\222\0021\0021\0021\0021\002\029\002\029\002\209\000\000\018\238\002\029\018\242\000\000\002\029\000\000\002~\002\029\000\000\002\029\007\186\000\000\002\029\019\n\002\029\002\029\002\029\000\000\002\029\002\029\b5\000\000\000\n\012\r\002\029\002\029\002\029\002\029\002\029\000\000\002\029\007J\000\000\006\145\000\000\000\000\002\029\002\029\002\029\002\029\002\029\b5\012\r\012\r\000\000\002\029\012\r\002\029\002\029\000\238\002\209\000\000\006\145\002\029\002\029\002\029\006\145\014J\000\000\000\000\000\000\000\000\002\029\002\029\002\029\002\029\002\029\002\029\002\029\002\029\002\029\000\000\t\n\t:\b5\002\029\002\029\000\000\004\190\000\000\000\000\b5\000\238\002\029\002\029\002\029\000\000\002\029\002\029\002\029\002\029\t\018\000\238\tB\002\029\000\000\002\029\002\029\000\000\002\029\002\029\002\029\002\029\002\029\002\029\017v\000\000\002\029\002\029\002\029\000\000\000\000\012\r\000\000\002\029\002\029\002\029\002\029\002-\002-\000\000\000\000\006\145\002-\nE\006\222\002-\n\158\000\000\002-\000\000\002-\t\n\t:\002-\000\000\002-\002-\002-\000\000\002-\002-\002\209\016j\016>\000\000\002-\002-\002-\002-\002-\t\018\002-\tB\nE\000\000\002\209\004\153\002-\002-\002-\002-\002-\006:\002\138\007J\000\n\002-\nE\002-\002-\nE\011>\024\174\006\222\002-\002-\002-\nE\000\000\004\153\000\000\nE\000\238\002-\002-\002-\002-\002-\002-\002-\002-\002-\024\178\002\209\002-\007\165\002-\002-\007\165\000\000\000\000\000\000\000\000\003\198\002-\002-\002-\000\000\002-\002-\002-\002-\000\000\007J\022\014\002-\000\000\002-\002-\000\000\tZ\002-\002-\002-\002-\002-\012\021\016B\002-\002-\002-\000\238\000\000\000\000\007\165\002-\002-\002-\002-\b\181\b\181\000\000\000\000\004-\b\181\012\021\012\021\b\181\007\165\012\021\b\181\000\000\b\181\000\000\000\000\t\130\000\000\b\181\t\166\b\181\000\000\b\181\b\181\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\b\181\007\165\000\000\000\000\000\000\004-\b\181\b\181\t\234\t\242\b\181\000\000\000\238\004-\000\000\b\181\000\000\t\250\b\181\000\000\000\000\000\000\000\000\b\181\b\181\000\238\000\000\000\000\007\165\000\000\000\000\000\000\b\181\b\181\t\138\t\202\n\002\n\n\n\026\b\181\b\181\000\000\012\021\b\181\000\000\b\181\n\"\000\000\000\000\000\000\000\000\012)\007\149\b\181\b\181\n*\007\149\b\181\b\181\b\181\b\181\000\000\000\000\012)\b\181\000\000\b\181\b\181\000\000\nJ\b\181\nR\n\018\b\181\b\181\012\017\000\000\b\181\n2\b\181\021\150\000\000\000\000\006\222\b\181\b\181\n:\nB\002a\002a\000\000\012)\007\149\002a\012\017\012\017\002a\000\000\012\017\002a\000\000\002a\007\134\000\000\002a\000\000\002a\002a\002a\000\000\002a\002a\000\000\007\149\000\000\000\000\002a\002a\002a\002a\002a\012)\002a\007J\012)\006\165\000\000\000\000\002a\002a\002a\002a\002a\000\000\000\238\000\000\000\000\002a\000\000\002a\002a\000\238\000\000\000\000\006\165\002a\002a\002a\006\165\000\000\004\190\002r\000\000\000\000\002a\002a\t\138\002a\002a\002a\002a\002a\002a\000\000\012\017\002a\000\000\002a\002a\000\000\000\000\000\000\000\000\000\238\000\000\002a\002a\002a\000\000\002a\002a\002a\002a\000\000\000\000\001\186\002a\000\000\002a\002a\000\000\002a\002a\002a\002a\002a\002a\025\222\000\000\002a\002a\002a\004-\011R\000\000\000\000\002a\002a\002a\002a\002I\002I\000\000\000\000\005&\002I\000\238\011Z\002I\000\n\011f\002I\000\000\002I\004-\002f\002I\011r\002I\002I\002I\011~\002I\002I\002\209\002\209\000\000\000\000\002I\002I\002I\002I\002I\000\000\002I\004-\0075\002\209\000\000\000\000\002I\002I\002I\002I\002I\004Z\000\000\000\238\004\197\002I\0075\002I\002I\005\166\000\000\000\000\006\222\002I\002I\002I\0075\000\000\000\000\000\000\0075\000\000\002I\002I\t\138\002I\002I\002I\002I\002I\002I\bN\006\222\002I\000\000\002I\002I\000\000\000\000\000\000\000\000\007M\000\000\002I\002I\002I\000\000\002I\002I\002I\002I\016.\007J\000\000\002I\000\000\002I\002I\022\006\002I\002I\002I\002I\002I\002I\000\000\000\000\002I\002I\002I\000\238\007M\007J\000\000\002I\002I\002I\002I\002U\002U\000\000\000\000\000\000\002U\000\238\007M\002U\000\000\005\166\002U\000\238\002U\000\000\000\000\t\130\007M\002U\002U\002U\007M\002U\002U\000\000\000\000\000\000\000\000\002U\002U\002U\t\194\002U\000\000\002U\000\000\007i\000\000\000\000\000\000\002U\002U\002U\002U\002U\000\000\000\000\000\000\000\000\002U\005\226\002U\002U\005\166\000\000\000\000\006\222\002U\002U\002U\007i\000\000\000\000\000\000\007i\000\000\002U\002U\t\138\t\202\002U\002U\002U\002U\002U\016J\006\222\002U\000\000\002U\002U\000\000\000\000\000\000\000\000\007a\000\000\002U\002U\002U\000\000\002U\002U\002U\002U\025\014\007J\000\000\002U\000\000\002U\002U\000\000\002U\002U\002U\002U\002U\002U\000\000\000\000\002U\002U\002U\000\238\007a\007J\000\000\002U\002U\002U\002U\002e\002e\000\000\000\000\000\000\002e\000\238\011\150\002e\000\000\007a\002e\000\238\002e\000\000\000\000\002e\007a\002e\002e\002e\007a\002e\002e\000\000\000\000\000\000\000\000\002e\002e\002e\002e\002e\000\000\002e\000\000\0071\000\000\000\000\000\000\002e\002e\002e\002e\002e\000\000\000\000\000\000\000\000\002e\0071\002e\002e\005\166\000\000\000\000\006\222\002e\002e\002e\0071\000\000\000\000\000\000\0071\000\000\002e\002e\t\138\002e\002e\002e\002e\002e\002e\026\178\000\000\002e\000\000\002e\002e\000\000\000\000\000\000\000\000\000\238\000\000\002e\002e\002e\000\000\002e\002e\002e\002e\000\000\007J\000\000\002e\000\000\002e\002e\000\000\002e\002e\002e\002e\002e\002e\000\000\000\000\002e\002e\002e\000\238\r\206\000\000\000\000\002e\002e\002e\002e\002E\002E\000\000\000\000\000\000\002E\000\000\011Z\002E\000\000\011f\002E\000\000\002E\000\000\000\000\002E\011r\002E\002E\002E\011~\002E\002E\000\000\000\000\000\000\006\181\002E\002E\002E\002E\002E\000\000\002E\000\000\000\000\006\149\000\000\000\000\002E\002E\002E\002E\002E\000\000\006\181\000\000\000\000\002E\006\181\002E\002E\000\000\000\000\000\000\006\149\002E\002E\002E\006\149\000\000\000\000\000\000\000\000\000\000\002E\002E\t\138\002E\002E\002E\002E\002E\002E\000\000\000\000\002E\000\000\002E\002E\000\000\000\000\000\000\000\000\000\238\000\000\002E\002E\002E\000\000\002E\002E\002E\002E\000\000\000\000\000\000\002E\000\000\002E\002E\000\000\002E\002E\002E\002E\002E\002E\000\000\000\000\002E\002E\002E\000\000\000\000\006\181\027\031\002E\002E\002E\002E\002Q\002Q\000\000\000\000\007\226\002Q\000\000\005\226\002Q\n\134\005\166\002Q\n\146\002Q\000\000\000\000\t\130\005\238\002Q\002Q\002Q\005\250\002Q\002Q\000\000\000\000\000\000\006\141\002Q\002Q\002Q\t\194\002Q\000\000\002Q\000\000\000\000\000\000\000\000\000\000\002Q\002Q\002Q\002Q\002Q\000\000\006\141\000\000\000\000\002Q\006\141\002Q\002Q\000\000\000\000\000\000\000\000\002Q\002Q\002Q\000\000\000\000\000\000\000\000\000\000\000\000\002Q\002Q\t\138\t\202\002Q\002Q\002Q\002Q\002Q\000\000\002\230\002Q\000\000\002Q\002Q\000\000\000\000\000\000\000\000\000\000\000\000\002Q\002Q\002Q\000\000\002Q\002Q\002Q\002Q\000\000\000\000\000\000\002Q\000\000\002Q\002Q\000\000\002Q\002Q\002Q\002Q\002Q\002Q\000\000\000\000\002Q\002Q\002Q\000\000\005z\006\141\000\000\002Q\002Q\002Q\002Q\002M\002M\000\000\003\182\000\000\002M\000\000\006\006\002M\003\194\000\000\002M\003\230\002M\000\000\000\000\t\130\000\000\002M\002M\002M\000\000\002M\002M\000\000\000\000\000\000\000\000\002M\002M\002M\t\194\002M\000\000\002M\000\000\000\000\000\000\000\000\000\000\002M\002M\002M\002M\002M\000\000\000\000\000\000\000\000\002M\000\000\002M\002M\000\000\000\000\000\000\000\000\002M\002M\002M\000\000\000\000\000\000\000\000\000\000\000\000\002M\002M\t\138\t\202\002M\002M\002M\002M\002M\000\000\002\138\002M\000\000\002M\002M\000\000\000\000\000\000\000\000\000\000\000\000\002M\002M\002M\000\000\002M\002M\002M\002M\000\000\000\000\000\000\002M\000\000\002M\002M\000\000\002M\002M\002M\002M\002M\002M\000\000\000\000\002M\002M\002M\000\000\tF\003\198\000\000\002M\002M\002M\002M\002u\002u\000\000\000\000\000\000\002u\000\000\011\182\002u\011\198\000\000\002u\000\000\002u\000\000\000\000\t\130\000\000\002u\002u\002u\000\000\002u\002u\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002u\000\000\000\000\000\000\000\000\000\000\002u\002u\t\234\t\242\002u\000\000\000\000\000\000\000\000\002u\000\000\t\250\002u\000\000\000\000\000\000\000\000\002u\002u\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002u\002u\t\138\t\202\n\002\n\n\n\026\002u\002u\000\000\002\138\002u\000\000\002u\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002u\002u\n*\000\000\002u\002u\002u\002u\000\000\000\000\000\000\002u\000\000\002u\002u\000\000\002u\002u\002u\n\018\002u\002u\000\000\000\000\002u\n2\002u\000\000\012j\003\198\000\000\002u\002u\n:\nB\002]\002]\000\000\000\000\000\000\002]\000\000\012~\002]\012\146\000\000\002]\000\000\002]\000\000\000\000\t\130\000\000\002]\002]\002]\000\000\002]\002]\000\000\000\000\000\000\000\000\002]\002]\002]\t\194\002]\000\000\002]\000\000\000\000\000\000\000\000\000\000\002]\002]\002]\002]\002]\000\000\000\000\000\000\000\000\002]\000\000\002]\002]\000\000\000\000\000\000\000\000\002]\002]\002]\000\000\000\000\000\000\000\000\000\000\000\000\002]\002]\t\138\t\202\002]\002]\002]\002]\002]\000\000\000\000\002]\000\000\002]\002]\000\000\000\000\000\000\000\000\000\000\000\000\002]\002]\002]\000\000\002]\002]\002]\002]\000\000\000\000\000\000\002]\000\000\002]\002]\000\000\002]\002]\002]\002]\002]\002]\000\000\000\000\002]\002]\002]\000\000\000\000\000\000\000\000\002]\002]\002]\002]\002Y\002Y\000\000\000\000\000\000\002Y\000\000\000\000\002Y\000\000\000\000\002Y\000\000\002Y\000\000\000\000\t\130\000\000\002Y\002Y\002Y\000\000\002Y\002Y\000\000\000\000\000\000\000\000\002Y\002Y\002Y\t\194\002Y\000\000\002Y\000\000\000\000\000\000\000\000\000\000\002Y\002Y\002Y\002Y\002Y\000\000\000\000\000\000\000\000\002Y\000\000\002Y\002Y\000\000\000\000\000\000\000\000\002Y\002Y\002Y\000\000\000\000\000\000\000\000\000\000\000\000\002Y\002Y\t\138\t\202\002Y\002Y\002Y\002Y\002Y\000\000\000\000\002Y\000\000\002Y\002Y\000\000\000\000\000\000\000\000\000\000\000\000\002Y\002Y\002Y\000\000\002Y\002Y\002Y\002Y\000\000\000\000\000\000\002Y\000\000\002Y\002Y\000\000\002Y\002Y\002Y\002Y\002Y\002Y\000\000\000\000\002Y\002Y\002Y\000\000\000\000\000\000\000\000\002Y\002Y\002Y\002Y\002m\002m\000\000\000\000\000\000\002m\000\000\000\000\002m\000\000\000\000\002m\000\000\002m\000\000\000\000\t\130\000\000\002m\002m\002m\000\000\002m\002m\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\002m\000\000\002m\000\000\000\000\000\000\000\000\000\000\002m\002m\t\234\t\242\002m\000\000\000\000\000\000\000\000\002m\000\000\002m\002m\000\000\000\000\000\000\000\000\002m\002m\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002m\002m\t\138\t\202\n\002\n\n\002m\002m\002m\000\000\000\000\002m\000\000\002m\002m\000\000\000\000\000\000\000\000\000\000\000\000\002m\002m\002m\000\000\002m\002m\002m\002m\000\000\000\000\000\000\002m\000\000\002m\002m\000\000\002m\002m\002m\n\018\002m\002m\000\000\000\000\002m\002m\002m\000\000\000\000\000\000\000\000\002m\002m\002m\002m\002A\002A\000\000\000\000\000\000\002A\000\000\000\000\002A\000\000\000\000\002A\000\000\002A\000\000\000\000\t\130\000\000\002A\002A\002A\000\000\002A\002A\000\000\000\000\000\000\000\000\002A\002A\002A\t\194\002A\000\000\002A\000\000\000\000\000\000\000\000\000\000\002A\002A\002A\002A\002A\000\000\000\000\000\000\000\000\002A\000\000\002A\002A\000\000\000\000\000\000\000\000\002A\002A\002A\000\000\000\000\000\000\000\000\000\000\000\000\002A\002A\t\138\t\202\002A\002A\002A\002A\002A\000\000\000\000\002A\000\000\002A\002A\000\000\000\000\000\000\000\000\000\000\000\000\002A\002A\002A\000\000\002A\002A\002A\002A\000\000\000\000\000\000\002A\000\000\002A\002A\000\000\002A\002A\002A\002A\002A\002A\000\000\000\000\002A\002A\002A\000\000\000\000\000\000\000\000\002A\002A\002A\002A\002=\002=\000\000\000\000\000\000\002=\000\000\000\000\002=\000\000\000\000\002=\000\000\002=\000\000\000\000\t\130\000\000\002=\002=\002=\000\000\002=\002=\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\002=\000\000\002=\000\000\000\000\000\000\000\000\000\000\002=\002=\t\234\t\242\002=\000\000\000\000\000\000\000\000\002=\000\000\002=\002=\000\000\000\000\000\000\000\000\002=\002=\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002=\002=\t\138\t\202\n\002\n\n\002=\002=\002=\000\000\000\000\002=\000\000\002=\002=\000\000\000\000\000\000\000\000\000\000\000\000\002=\002=\002=\000\000\002=\002=\002=\002=\000\000\000\000\000\000\002=\000\000\002=\002=\000\000\002=\002=\002=\n\018\002=\002=\000\000\000\000\002=\002=\002=\000\000\000\000\000\000\000\000\002=\002=\002=\002=\002\153\002\153\000\000\000\000\000\000\002\153\000\000\000\000\002\153\000\000\000\000\002\153\000\000\002\153\000\000\000\000\t\130\000\000\002\153\002\153\002\153\000\000\002\153\002\153\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\002\153\000\000\002\153\000\000\000\000\000\000\000\000\000\000\002\153\002\153\t\234\t\242\002\153\000\000\000\000\000\000\000\000\002\153\000\000\002\153\002\153\000\000\000\000\000\000\000\000\002\153\002\153\002\153\000\000\000\000\000\000\000\000\000\000\000\000\002\153\002\153\t\138\t\202\n\002\002\153\002\153\002\153\002\153\000\000\000\000\002\153\000\000\002\153\002\153\000\000\000\000\000\000\000\000\000\000\000\000\002\153\002\153\002\153\000\000\002\153\002\153\002\153\002\153\000\000\000\000\000\000\002\153\000\000\002\153\002\153\000\000\002\153\002\153\002\153\n\018\002\153\002\153\000\000\000\000\002\153\002\153\002\153\000\000\000\000\000\000\000\000\002\153\002\153\002\153\002\153\0029\0029\000\000\000\000\000\000\0029\000\000\000\000\0029\000\000\000\000\0029\000\000\0029\000\000\000\000\t\130\000\000\0029\0029\0029\000\000\0029\0029\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\0029\000\000\0029\000\000\000\000\000\000\000\000\000\000\0029\0029\t\234\t\242\0029\000\000\000\000\000\000\000\000\0029\000\000\0029\0029\000\000\000\000\000\000\000\000\0029\0029\000\238\000\000\000\000\000\000\000\000\000\000\000\000\0029\0029\t\138\t\202\n\002\n\n\0029\0029\0029\000\000\000\000\0029\000\000\0029\0029\000\000\000\000\000\000\000\000\000\000\000\000\0029\0029\0029\000\000\0029\0029\0029\0029\000\000\000\000\000\000\0029\000\000\0029\0029\000\000\0029\0029\0029\n\018\0029\0029\000\000\000\000\0029\0029\0029\000\000\000\000\000\000\000\000\0029\0029\0029\0029\002q\002q\000\000\000\000\000\000\002q\000\000\000\000\002q\000\000\000\000\002q\000\000\002q\000\000\000\000\t\130\000\000\002q\002q\002q\000\000\002q\002q\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\002q\000\000\002q\000\000\000\000\000\000\000\000\000\000\002q\002q\t\234\t\242\002q\000\000\000\000\000\000\000\000\002q\000\000\002q\002q\000\000\000\000\000\000\000\000\002q\002q\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002q\002q\t\138\t\202\n\002\n\n\002q\002q\002q\000\000\000\000\002q\000\000\002q\002q\000\000\000\000\000\000\000\000\000\000\000\000\002q\002q\002q\000\000\002q\002q\002q\002q\000\000\000\000\000\000\002q\000\000\002q\002q\000\000\002q\002q\002q\n\018\002q\002q\000\000\000\000\002q\002q\002q\000\000\000\000\000\000\000\000\002q\002q\002q\002q\002i\002i\000\000\000\000\000\000\002i\000\000\000\000\002i\000\000\000\000\002i\000\000\002i\000\000\000\000\t\130\000\000\002i\002i\002i\000\000\002i\002i\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\002i\000\000\002i\000\000\000\000\000\000\000\000\000\000\002i\002i\t\234\t\242\002i\000\000\000\000\000\000\000\000\002i\000\000\002i\002i\000\000\000\000\000\000\000\000\002i\002i\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002i\002i\t\138\t\202\n\002\n\n\002i\002i\002i\000\000\000\000\002i\000\000\002i\002i\000\000\000\000\000\000\000\000\000\000\000\000\002i\002i\002i\000\000\002i\002i\002i\002i\000\000\000\000\000\000\002i\000\000\002i\002i\000\000\002i\002i\002i\n\018\002i\002i\000\000\000\000\002i\002i\002i\000\000\000\000\000\000\000\000\002i\002i\002i\002i\002y\002y\000\000\000\000\000\000\002y\000\000\000\000\002y\000\000\000\000\002y\000\000\002y\000\000\000\000\t\130\000\000\002y\002y\002y\000\000\002y\002y\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002y\000\000\000\000\000\000\000\000\000\000\002y\002y\t\234\t\242\002y\000\000\000\000\000\000\000\000\002y\000\000\t\250\002y\000\000\000\000\000\000\000\000\002y\002y\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002y\002y\t\138\t\202\n\002\n\n\n\026\002y\002y\000\000\000\000\002y\000\000\002y\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002y\002y\n*\000\000\002y\002y\002y\002y\000\000\000\000\000\000\002y\000\000\002y\002y\000\000\002y\002y\002y\n\018\002y\002y\000\000\000\000\002y\n2\002y\000\000\000\000\000\000\000\000\002y\002y\n:\nB\002}\002}\000\000\000\000\000\000\002}\000\000\000\000\002}\000\000\000\000\002}\000\000\002}\000\000\000\000\t\130\000\000\002}\002}\002}\000\000\002}\002}\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\002}\000\000\002}\000\000\000\000\000\000\000\000\000\000\002}\002}\t\234\t\242\002}\000\000\000\000\000\000\000\000\002}\000\000\t\250\002}\000\000\000\000\000\000\000\000\002}\002}\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002}\002}\t\138\t\202\n\002\n\n\n\026\002}\002}\000\000\000\000\002}\000\000\002}\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002}\002}\n*\000\000\002}\002}\002}\002}\000\000\000\000\000\000\002}\000\000\002}\002}\000\000\002}\002}\002}\n\018\002}\002}\000\000\000\000\002}\002}\002}\000\000\000\000\000\000\000\000\002}\002}\n:\nB\002\129\002\129\000\000\000\000\000\000\002\129\000\000\000\000\002\129\000\000\000\000\002\129\000\000\002\129\000\000\000\000\t\130\000\000\002\129\002\129\002\129\000\000\002\129\002\129\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\002\129\000\000\002\129\000\000\000\000\000\000\000\000\000\000\002\129\002\129\t\234\t\242\002\129\000\000\000\000\000\000\000\000\002\129\000\000\t\250\002\129\000\000\000\000\000\000\000\000\002\129\002\129\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\129\002\129\t\138\t\202\n\002\n\n\n\026\002\129\002\129\000\000\000\000\002\129\000\000\002\129\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002\129\002\129\n*\000\000\002\129\002\129\002\129\002\129\000\000\000\000\000\000\002\129\000\000\002\129\002\129\000\000\002\129\002\129\002\129\n\018\002\129\002\129\000\000\000\000\002\129\002\129\002\129\000\000\000\000\000\000\000\000\002\129\002\129\n:\nB\bq\bq\000\000\000\000\000\000\bq\000\000\000\000\bq\000\000\000\000\bq\000\000\bq\000\000\000\000\t\130\000\000\bq\bq\bq\000\000\bq\bq\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\bq\000\000\000\000\000\000\000\000\000\000\bq\bq\t\234\t\242\bq\000\000\000\000\000\000\000\000\bq\000\000\t\250\bq\000\000\000\000\000\000\000\000\bq\bq\000\238\000\000\000\000\000\000\000\000\000\000\000\000\bq\bq\t\138\t\202\n\002\n\n\n\026\bq\bq\000\000\000\000\bq\000\000\bq\n\"\000\000\000\000\000\000\000\000\000\000\000\000\bq\bq\n*\000\000\bq\bq\bq\bq\000\000\000\000\000\000\bq\000\000\bq\bq\000\000\bq\bq\bq\n\018\bq\bq\000\000\000\000\bq\n2\bq\000\000\000\000\000\000\000\000\bq\bq\n:\nB\002\133\002\133\000\000\000\000\000\000\002\133\000\000\000\000\002\133\000\000\000\000\002\133\000\000\002\133\000\000\000\000\t\130\000\000\002\133\002\133\002\133\000\000\002\133\002\133\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002\133\000\000\000\000\000\000\000\000\000\000\002\133\002\133\t\234\t\242\002\133\000\000\000\000\000\000\000\000\002\133\000\000\t\250\002\133\000\000\000\000\000\000\000\000\002\133\002\133\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\133\002\133\t\138\t\202\n\002\n\n\n\026\002\133\002\133\000\000\000\000\002\133\000\000\002\133\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002\133\002\133\n*\000\000\002\133\002\133\002\133\002\133\000\000\000\000\000\000\002\133\000\000\002\133\002\133\000\000\nJ\002\133\nR\n\018\002\133\002\133\000\000\000\000\002\133\n2\002\133\000\000\000\000\000\000\000\000\002\133\002\133\n:\nB\bm\bm\000\000\000\000\000\000\bm\000\000\000\000\bm\000\000\000\000\bm\000\000\bm\000\000\000\000\t\130\000\000\bm\bm\bm\000\000\bm\bm\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\bm\000\000\000\000\000\000\000\000\000\000\bm\bm\t\234\t\242\bm\000\000\000\000\000\000\000\000\bm\000\000\t\250\bm\000\000\000\000\000\000\000\000\bm\bm\000\238\000\000\000\000\000\000\000\000\000\000\000\000\bm\bm\t\138\t\202\n\002\n\n\n\026\bm\bm\000\000\000\000\bm\000\000\bm\n\"\000\000\000\000\000\000\000\000\000\000\000\000\bm\bm\n*\000\000\bm\bm\bm\bm\000\000\000\000\000\000\bm\000\000\bm\bm\000\000\bm\bm\bm\n\018\bm\bm\000\000\000\000\bm\n2\bm\000\000\000\000\000\000\000\000\bm\bm\n:\nB\002\181\002\181\000\000\000\000\000\000\002\181\000\000\000\000\002\181\000\000\000\000\002\181\000\000\002\181\000\000\000\000\t\130\000\000\002\181\002\181\002\181\000\000\002\181\002\181\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002\181\000\000\000\000\000\000\000\000\000\000\002\181\002\181\t\234\t\242\002\181\000\000\000\000\000\000\000\000\002\181\000\000\t\250\002\181\000\000\000\000\000\000\000\000\002\181\002\181\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\181\002\181\t\138\t\202\n\002\n\n\n\026\002\181\002\181\000\000\000\000\002\181\000\000\002\181\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002\181\002\181\n*\000\000\002\181\002\181\002\181\002\181\000\000\000\000\000\000\002\181\000\000\002\181\002\181\000\000\nJ\002\181\nR\n\018\002\181\002\181\000\000\000\000\002\181\n2\002\181\000\000\000\000\000\000\000\000\002\181\002\181\n:\nB\002\177\002\177\000\000\000\000\000\000\002\177\000\000\000\000\002\177\000\000\000\000\002\177\000\000\002\177\000\000\000\000\t\130\000\000\002\177\002\177\002\177\000\000\002\177\002\177\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002\177\000\000\000\000\000\000\000\000\000\000\002\177\002\177\t\234\t\242\002\177\000\000\000\000\000\000\000\000\002\177\000\000\t\250\002\177\000\000\000\000\000\000\000\000\002\177\002\177\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\177\002\177\t\138\t\202\n\002\n\n\n\026\002\177\002\177\000\000\000\000\002\177\000\000\002\177\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002\177\002\177\n*\000\000\002\177\002\177\002\177\002\177\000\000\000\000\000\000\002\177\000\000\002\177\002\177\000\000\nJ\002\177\nR\n\018\002\177\002\177\000\000\000\000\002\177\n2\002\177\000\000\000\000\000\000\000\000\002\177\002\177\n:\nB\002\185\002\185\000\000\000\000\000\000\002\185\000\000\000\000\002\185\000\000\000\000\002\185\000\000\002\185\000\000\000\000\t\130\000\000\002\185\002\185\002\185\000\000\002\185\002\185\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002\185\000\000\000\000\000\000\000\000\000\000\002\185\002\185\t\234\t\242\002\185\000\000\000\000\000\000\000\000\002\185\000\000\t\250\002\185\000\000\000\000\000\000\000\000\002\185\002\185\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\185\002\185\t\138\t\202\n\002\n\n\n\026\002\185\002\185\000\000\000\000\002\185\000\000\002\185\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002\185\002\185\n*\000\000\002\185\002\185\002\185\002\185\000\000\000\000\000\000\002\185\000\000\002\185\002\185\000\000\nJ\002\185\nR\n\018\002\185\002\185\000\000\000\000\002\185\n2\002\185\000\000\000\000\000\000\000\000\002\185\002\185\n:\nB\002\165\002\165\000\000\000\000\000\000\002\165\000\000\000\000\002\165\000\000\000\000\002\165\000\000\002\165\000\000\000\000\t\130\000\000\002\165\002\165\002\165\000\000\002\165\002\165\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002\165\000\000\000\000\000\000\000\000\000\000\002\165\002\165\t\234\t\242\002\165\000\000\000\000\000\000\000\000\002\165\000\000\t\250\002\165\000\000\000\000\000\000\000\000\002\165\002\165\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\165\002\165\t\138\t\202\n\002\n\n\n\026\002\165\002\165\000\000\000\000\002\165\000\000\002\165\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002\165\002\165\n*\000\000\002\165\002\165\002\165\002\165\000\000\000\000\000\000\002\165\000\000\002\165\002\165\000\000\nJ\002\165\nR\n\018\002\165\002\165\000\000\000\000\002\165\n2\002\165\000\000\000\000\000\000\000\000\002\165\002\165\n:\nB\002\169\002\169\000\000\000\000\000\000\002\169\000\000\000\000\002\169\000\000\000\000\002\169\000\000\002\169\000\000\000\000\t\130\000\000\002\169\002\169\002\169\000\000\002\169\002\169\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002\169\000\000\000\000\000\000\000\000\000\000\002\169\002\169\t\234\t\242\002\169\000\000\000\000\000\000\000\000\002\169\000\000\t\250\002\169\000\000\000\000\000\000\000\000\002\169\002\169\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\169\002\169\t\138\t\202\n\002\n\n\n\026\002\169\002\169\000\000\000\000\002\169\000\000\002\169\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002\169\002\169\n*\000\000\002\169\002\169\002\169\002\169\000\000\000\000\000\000\002\169\000\000\002\169\002\169\000\000\nJ\002\169\nR\n\018\002\169\002\169\000\000\000\000\002\169\n2\002\169\000\000\000\000\000\000\000\000\002\169\002\169\n:\nB\002\173\002\173\000\000\000\000\000\000\002\173\000\000\000\000\002\173\000\000\000\000\002\173\000\000\002\173\000\000\000\000\t\130\000\000\002\173\002\173\002\173\000\000\002\173\002\173\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002\173\000\000\000\000\000\000\000\000\000\000\002\173\002\173\t\234\t\242\002\173\000\000\000\000\000\000\000\000\002\173\000\000\t\250\002\173\000\000\000\000\000\000\000\000\002\173\002\173\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\173\002\173\t\138\t\202\n\002\n\n\n\026\002\173\002\173\000\000\000\000\002\173\000\000\002\173\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002\173\002\173\n*\000\000\002\173\002\173\002\173\002\173\000\000\000\000\000\000\002\173\000\000\002\173\002\173\000\000\nJ\002\173\nR\n\018\002\173\002\173\000\000\000\000\002\173\n2\002\173\000\000\000\000\000\000\000\000\002\173\002\173\n:\nB\002\193\002\193\000\000\000\000\000\000\002\193\000\000\000\000\002\193\000\000\000\000\002\193\000\000\002\193\000\000\000\000\t\130\000\000\002\193\002\193\002\193\000\000\002\193\002\193\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002\193\000\000\000\000\000\000\000\000\000\000\002\193\002\193\t\234\t\242\002\193\000\000\000\000\000\000\000\000\002\193\000\000\t\250\002\193\000\000\000\000\000\000\000\000\002\193\002\193\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\193\002\193\t\138\t\202\n\002\n\n\n\026\002\193\002\193\000\000\000\000\002\193\000\000\002\193\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002\193\002\193\n*\000\000\002\193\002\193\002\193\002\193\000\000\000\000\000\000\002\193\000\000\002\193\002\193\000\000\nJ\002\193\nR\n\018\002\193\002\193\000\000\000\000\002\193\n2\002\193\000\000\000\000\000\000\000\000\002\193\002\193\n:\nB\002\189\002\189\000\000\000\000\000\000\002\189\000\000\000\000\002\189\000\000\000\000\002\189\000\000\002\189\000\000\000\000\t\130\000\000\002\189\002\189\002\189\000\000\002\189\002\189\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002\189\000\000\000\000\000\000\000\000\000\000\002\189\002\189\t\234\t\242\002\189\000\000\000\000\000\000\000\000\002\189\000\000\t\250\002\189\000\000\000\000\000\000\000\000\002\189\002\189\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\189\002\189\t\138\t\202\n\002\n\n\n\026\002\189\002\189\000\000\000\000\002\189\000\000\002\189\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002\189\002\189\n*\000\000\002\189\002\189\002\189\002\189\000\000\000\000\000\000\002\189\000\000\002\189\002\189\000\000\nJ\002\189\nR\n\018\002\189\002\189\000\000\000\000\002\189\n2\002\189\000\000\000\000\000\000\000\000\002\189\002\189\n:\nB\002\197\002\197\000\000\000\000\000\000\002\197\000\000\000\000\002\197\000\000\000\000\002\197\000\000\002\197\000\000\000\000\t\130\000\000\002\197\002\197\002\197\000\000\002\197\002\197\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002\197\000\000\000\000\000\000\000\000\000\000\002\197\002\197\t\234\t\242\002\197\000\000\000\000\000\000\000\000\002\197\000\000\t\250\002\197\000\000\000\000\000\000\000\000\002\197\002\197\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\197\002\197\t\138\t\202\n\002\n\n\n\026\002\197\002\197\000\000\000\000\002\197\000\000\002\197\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002\197\002\197\n*\000\000\002\197\002\197\002\197\002\197\000\000\000\000\000\000\002\197\000\000\002\197\002\197\000\000\nJ\002\197\nR\n\018\002\197\002\197\000\000\000\000\002\197\n2\002\197\000\000\000\000\000\000\000\000\002\197\002\197\n:\nB\002\161\002\161\000\000\000\000\000\000\002\161\000\000\000\000\002\161\000\000\000\000\002\161\000\000\002\161\000\000\000\000\t\130\000\000\002\161\002\161\002\161\000\000\002\161\002\161\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002\161\000\000\000\000\000\000\000\000\000\000\002\161\002\161\t\234\t\242\002\161\000\000\000\000\000\000\000\000\002\161\000\000\t\250\002\161\000\000\000\000\000\000\000\000\002\161\002\161\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\161\002\161\t\138\t\202\n\002\n\n\n\026\002\161\002\161\000\000\000\000\002\161\000\000\002\161\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002\161\002\161\n*\000\000\002\161\002\161\002\161\002\161\000\000\000\000\000\000\002\161\000\000\002\161\002\161\000\000\nJ\002\161\nR\n\018\002\161\002\161\000\000\000\000\002\161\n2\002\161\000\000\000\000\000\000\000\000\002\161\002\161\n:\nB\001\241\001\241\000\000\000\000\000\000\001\241\000\000\000\000\001\241\000\000\000\000\001\241\000\000\001\241\000\000\000\000\001\241\000\000\001\241\001\241\001\241\000\000\001\241\001\241\000\000\000\000\000\000\000\000\001\241\001\241\001\241\001\241\001\241\000\000\001\241\000\000\000\000\000\000\000\000\000\000\001\241\001\241\001\241\001\241\001\241\000\000\000\000\000\000\000\000\001\241\000\000\001\241\001\241\000\000\000\000\000\000\000\000\001\241\001\241\001\241\000\000\000\000\000\000\000\000\000\000\000\000\001\241\001\241\001\241\001\241\001\241\001\241\001\241\001\241\001\241\000\000\000\000\001\241\000\000\001\241\001\241\000\000\000\000\000\000\000\000\000\000\000\000\001\241\001\241\001\241\000\000\001\241\001\241\001\241\001\241\000\000\000\000\000\000\001\241\000\000\001\241\001\241\000\000\001\241\001\241\001\241\001\241\001\241\001\241\000\000\000\000\001\241\001\241\r\166\000\000\000\000\000\000\000\000\001\241\001\241\001\241\001\241\002\r\002\r\000\000\000\000\000\000\002\r\000\000\000\000\002\r\000\000\000\000\002\r\000\000\002\r\000\000\000\000\t\130\000\000\002\r\002\r\002\r\000\000\002\r\002\r\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002\r\000\000\000\000\000\000\000\000\000\000\002\r\002\r\t\234\t\242\002\r\000\000\000\000\000\000\000\000\002\r\000\000\t\250\002\r\000\000\000\000\000\000\000\000\002\r\002\r\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\r\002\r\t\138\t\202\n\002\n\n\n\026\002\r\002\r\000\000\000\000\002\r\000\000\002\r\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002\r\002\r\n*\000\000\002\r\002\r\r\190\002\r\000\000\000\000\000\000\002\r\000\000\002\r\002\r\000\000\nJ\002\r\nR\n\018\002\r\002\r\000\000\000\000\002\r\n2\002\r\000\000\000\000\000\000\000\000\002\r\002\r\n:\nB\002\t\002\t\000\000\000\000\000\000\002\t\000\000\000\000\002\t\000\000\000\000\002\t\000\000\002\t\000\000\000\000\t\130\000\000\002\t\002\t\002\t\000\000\002\t\002\t\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002\t\000\000\000\000\000\000\000\000\000\000\002\t\002\t\t\234\t\242\002\t\000\000\000\000\000\000\000\000\002\t\000\000\t\250\002\t\000\000\000\000\000\000\000\000\002\t\002\t\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\t\002\t\t\138\t\202\n\002\n\n\n\026\002\t\002\t\000\000\000\000\002\t\000\000\002\t\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002\t\002\t\n*\000\000\002\t\002\t\002\t\002\t\000\000\000\000\000\000\002\t\000\000\002\t\002\t\000\000\nJ\002\t\nR\n\018\002\t\002\t\000\000\000\000\002\t\n2\002\t\000\000\000\000\000\000\000\000\002\t\002\t\n:\nB\002\157\002\157\000\000\000\000\000\000\002\157\000\000\000\000\002\157\000\000\000\000\002\157\000\000\002\157\000\000\000\000\t\130\000\000\002\157\002\157\002\157\000\000\002\157\002\157\000\000\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\002\157\000\000\000\000\000\000\000\000\000\000\002\157\002\157\t\234\t\242\002\157\000\000\000\000\000\000\000\000\002\157\000\000\t\250\002\157\000\000\000\000\000\000\000\000\002\157\002\157\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\157\002\157\t\138\t\202\n\002\n\n\n\026\002\157\002\157\000\000\000\000\002\157\000\000\002\157\n\"\000\000\000\000\000\000\000\000\000\000\000\000\002\157\002\157\n*\000\000\002\157\002\157\002\157\002\157\000\000\000\000\000\000\002\157\000\000\002\157\002\157\000\000\nJ\002\157\nR\n\018\002\157\002\157\000\000\000\000\002\157\n2\002\157\000\000\000\000\000\000\000\000\002\157\002\157\n:\nB\001\253\001\253\000\000\000\000\000\000\001\253\000\000\000\000\001\253\000\000\000\000\001\253\000\000\001\253\000\000\000\000\001\253\000\000\001\253\001\253\001\253\000\000\001\253\001\253\000\000\000\000\000\000\000\000\001\253\001\253\001\253\001\253\001\253\000\000\001\253\000\000\000\000\000\000\000\000\000\000\001\253\001\253\001\253\001\253\001\253\000\000\000\000\000\000\000\000\001\253\000\000\001\253\001\253\000\000\000\000\000\000\000\000\001\253\001\253\001\253\000\000\000\000\000\000\000\000\000\000\000\000\001\253\001\253\001\253\001\253\001\253\001\253\001\253\001\253\001\253\000\000\000\000\001\253\000\000\001\253\001\253\000\000\000\000\000\000\000\000\000\000\000\000\001\253\001\253\001\253\000\000\001\253\001\253\001\253\001\253\000\000\000\000\000\000\001\253\000\000\001\253\001\253\000\000\001\253\001\253\001\253\001\253\001\253\001\253\000\000\000\000\001\253\001\253\r\166\000\000\000\000\000\000\000\000\001\253\001\253\001\253\001\253\002\001\002\001\000\000\000\000\000\000\002\001\000\000\000\000\002\001\000\000\000\000\002\001\000\000\002\001\000\000\000\000\002\001\000\000\002\001\002\001\002\001\000\000\002\001\002\001\000\000\000\000\000\000\006\169\002\001\002\001\002\001\002\001\002\001\000\000\002\001\000\000\000\000\000\000\000\000\000\000\002\001\002\001\002\001\002\001\002\001\000\000\006\169\003\233\000\000\002\001\006\169\002\001\002\001\000\000\000\000\000\000\000\000\002\001\002\001\002\001\000\000\000\000\000\000\000\000\000\000\000\000\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\000\000\000\000\002\001\000\000\002\001\002\001\000\000\000\000\000\000\000\000\000\000\000\238\002\001\002\001\002\001\000\000\002\001\002\001\002\001\002\001\000\000\000\000\000\000\002\001\000\000\002\001\002\001\000\000\002\001\002\001\002\001\002\001\002\001\002\001\000\000\b\142\002\001\002\001\r\166\000\000\000\000\003\233\000\000\002\001\002\001\002\001\002\001\001\006\000\000\000\006\000\000\000\000\024\186\002\134\002\138\005\226\002\182\002\194\005\166\b\174\000\000\000\000\002\198\001\n\000\000\005\238\000\000\002\254\000\000\005\250\000\000\000\000\000\000\r\146\003\002\001\018\b*\b.\001\030\001\"\000\000\000\000\000\000\003\018\000\000\002\206\000\000\024\238\000\000\bR\bV\000\238\003\158\002\250\003\170\bZ\006\142\bF\001:\000\000\002~\001\238\000\000\003\006\001\238\000\000\000\000\007\214\007\218\007\230\007\250\001\242\0056\000\000\001\242\001>\001B\001F\001J\001N\000\000\000\000\bn\001R\000\000\000\000\000\000\001V\000\000\bz\b\146\b\230\005B\005F\003^\005\226\001Z\003^\005\166\024\190\006\194\001\198\001^\006\194\001\198\005\238\000\000\002~\000\000\005\250\002~\000\000\001\134\n\202\000\000\000\000\005J\007\238\000\000\001\138\000\000\r\238\004\018\b\250\001\006\001\146\000\006\001\150\001\154\000\000\002\134\002\138\000\000\002\182\002\194\006\198\000\000\000\000\006\198\002\198\001\n\000\000\000\000\000\000\b&\000\000\000\000\000\000\000\000\000\000\000\000\003\002\001\018\b*\b.\001\030\001\"\000\000\000\000\000\000\003\018\000\000\002\206\000\000\b2\000\000\bR\bV\000\000\003\158\002\250\003\170\bZ\006\142\000\000\001:\000\000\002~\000\000\000\000\003\006\000\000\000\000\000\000\007\214\007\218\007\230\007\250\000\000\0056\000\000\000\000\001>\001B\001F\001J\001N\000\000\000\000\bn\001R\000\000\000\000\000\000\001V\000\000\bz\b\146\b\230\005B\005F\000\000\000\000\001Z\000\000\000\000\000\000\000\000\000\000\001^\000\000\000\241\003\142\000\000\002\138\000\000\000\241\000\000\000\000\001\134\005\206\003n\000\000\005J\007\238\000\000\001\138\007\158\r\238\004\018\b\250\n\214\001\146\000\000\001\150\001\154\000\014\000\018\000\022\000\026\000\030\000\000\000\"\000&\000*\000.\0002\000\000\0006\000:\000\000\n\218\000>\003\138\002\138\000\241\000B\003\030\000\000\000\000\002~\000F\000\000\000\241\000\000\000\000\000\000\000J\000\241\000N\000R\000V\000Z\000^\000b\000f\000\000\000\241\000\241\000j\000n\000\000\000r\021\134\000v\000\000\000\000\000\000\006\162\000\000\000\238\000\000\000\000\022\194\002\218\000\000\022\198\000\000\000z\000\000\002~\000~\000\130\000\241\000\000\000\000\000\000\022\246\000\134\000\138\000\142\000\000\000\241\000\000\000\000\000\000\000\146\000\150\000\154\000\158\000\000\000\162\000\166\000\170\000\000\000\000\000\000\000\174\000\178\000\182\023\006\000\000\000\000\000\186\005\226\000\190\000\194\005\166\n\222\016&\000\000\000\000\000\000\000\198\005\238\000\202\001\238\000\000\005\250\000\000\000\000\000\206\000\210\004Y\000\214\000\006\001\242\000\000\000\246\002\134\002\138\002\142\002\182\002\194\000\000\000\000\000\000\000\000\002\198\000\000\000\000\003v\000\000\000\000\000\000\004Y\000\000\0166\016\210\003^\002\202\000\000\003\n\003\014\001\238\006\194\001\198\003z\000\000\003\018\000\000\002\206\002~\016f\001\242\003\150\003\154\000\000\003\158\002\250\003\170\003\178\006\142\000\000\000\000\016\202\002~\000\000\000\000\003\006\016\226\000\000\000\000\007\214\007\218\007\230\007\250\003^\0056\000\000\006\198\000\000\000\000\006\194\001\198\000\000\016\234\000\000\bn\000\000\002~\000\000\000\000\000\000\000\000\bz\b\146\b\230\005B\005F\016\254\017*\000\000\000\000\004Y\004Y\000\000\000\000\001\182\001\186\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\198\000\000\017j\021j\005J\007\238\024\218\000\141\001\190\b\006\004\018\b\250\000\141\000\000\002\138\000\141\000\000\002\194\004E\t\"\000\000\000\000\002\198\004E\000\000\000\141\000\000\000\141\000\000\000\141\001\222\002f\t*\000\000\002\202\002j\000\000\002~\003\234\003\246\t2\000\141\000\000\000\000\004\002\002\206\015Z\000\141\000\000\000\000\000\000\000\141\000\000\002\250\001\170\000\000\000\141\000\000\000\000\000\141\002~\004\006\004E\003\006\000\141\000\141\000\141\007\214\007\218\007\230\004E\012\018\0056\000\141\000\141\004E\002\174\000\238\000\000\000\000\000\141\000\000\000\000\000\000\000\141\004E\000\000\000\000\000\000\000\000\000\000\000\000\005B\005F\000\141\000\141\000\000\000\000\000\141\000\141\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\141\002\209\004E\000\000\002\209\000\000\000\141\000\141\005J\007\238\000\000\004E\000\165\b\006\004\018\000\000\000\141\000\165\000\141\002\138\000\165\000\000\002\194\000\000\t\"\000\n\000\000\002\198\0156\001*\000\165\002N\000\165\000\000\000\165\000\000\002\209\t*\000\000\002\202\002\209\000\000\003&\002\209\000\000\t2\000\165\021\018\000\000\000\000\002\206\000\000\000\165\002\209\002\209\0032\000\165\000\000\002\250\001\170\000\n\000\165\000\000\000\000\000\165\002~\000\000\015:\003\006\000\165\000\165\000\165\007\214\007\218\007\230\002\209\012\018\0056\000\165\000\165\002\209\015F\002\209\0216\000\000\000\165\000\000\000\000\002\209\000\165\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005B\005F\000\165\000\165\000\000\000\000\000\165\000\165\000\000\000\000\015N\001\006\000\000\002\209\000\000\000\000\000\165\003\"\002\138\b\206\021B\002\194\000\165\000\165\005J\007\238\002\198\001\n\000\000\b\006\004\018\002\254\000\165\000\000\000\165\000\000\016\218\020\214\001\014\001\018\001\022\003B\001\030\001\"\000\000\000\000\003~\000\000\000\000\000\000\000\000\003F\000\000\001.\n\198\007\133\000\000\003>\001\170\0016\000\000\000\249\001:\000\000\002~\000\000\000\249\003\182\025\006\000\000\000\000\003\186\000\000\003\194\005*\001\238\0056\000\000\000\000\001>\001B\001F\001J\001N\000\000\001\242\000\000\001R\005:\000\000\000\000\001V\000\238\000\000\000\000\000\000\005B\005F\000\000\005\134\001Z\000\000\000\000\000\000\000\000\000\249\001^\018n\003^\000\000\000\000\000\000\000\000\000\249\006\194\001\198\001\134\n\202\000\249\004E\005J\002~\000\000\001\138\004E\001\142\004\018\001\006\000\249\001\146\000\000\001\150\001\154\003\"\002\138\nj\005\226\002\194\000\000\005\166\000\000\000\000\002\198\001\n\000\000\000\000\005\238\002\254\000\000\006\198\005\250\000\000\000\000\000\249\001\014\001\018\001\022\003B\001\030\001\"\000\000\000\000\000\249\004E\000\000\000\000\000\000\003F\000\000\001.\n\198\004E\000\000\003>\001\170\0016\004E\002\174\001:\000\000\002~\000\000\000\000\003\182\000\000\004E\004E\003\186\000\000\003\194\005*\000\000\0056\000\000\000\000\001>\001B\001F\001J\001N\004q\000\000\000\000\001R\005:\021\146\000\000\001V\000\000\000\000\000\000\004E\005B\005F\000\000\005\134\001Z\000\000\000\000\000\000\004E\000\000\001^\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\209\000\000\001\134\n\202\000\000\000\000\005J\002\209\000\000\001\138\000\000\001\142\004\018\001\006\022\002\001\146\000\000\001\150\001\154\003\"\002\138\rR\016\202\002\194\000\n\000\000\000\000\016\226\002\198\001\n\000\000\000\000\000\000\002\254\000\000\000\000\022\166\022\182\000\000\002\209\001\014\001\018\001\022\003B\001\030\001\"\002\209\000\000\000\000\000\000\000\000\000\000\002\209\003F\000\000\001.\n\198\000\000\000\000\003>\001\170\0016\004q\000\000\001:\000\000\002~\000\000\000\000\003\182\000\000\023\170\000\000\003\186\002\209\003\194\005*\000\000\0056\000\000\000\000\001>\001B\001F\001J\001N\000\000\000\000\000\000\001R\005:\000\000\000\000\001V\000\000\000\000\000\000\000\000\005B\005F\000\000\005\134\001Z\000\000\000\000\000\000\000\000\006\150\001^\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\134\n\202\000\000\000\000\005J\000\000\000\000\001\138\000\000\001\142\004\018\000\000\b\137\001\146\000\006\001\150\001\154\000\246\002\134\002\138\002\142\002\182\002\194\000\000\000\000\000\000\000\000\002\198\000\000\000\000\004y\000\000\000\000\000\000\b\137\000\000\000\000\000\000\000\000\002\202\000\000\003\n\003\014\000\000\000\000\000\000\003z\000\000\003\018\000\000\002\206\000\000\016f\000\000\003\150\003\154\000\000\003\158\002\250\003\170\003\178\006\142\000\000\000\000\016\202\002~\000\000\000\000\003\006\016\226\001\182\001\186\007\214\007\218\007\230\007\250\000\000\0056\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\234\000\000\bn\001\190\027*\000\000\000\000\000\000\000\000\bz\b\146\b\230\005B\005F\016\254\017*\000\000\000\000\027O\014\142\000\000\000\000\000\000\000\000\000\000\001\222\002n\000\000\000\000\000\000\002j\000\000\002~\003\234\003\246\021j\005J\007\238\b\137\004\002\000\000\b\006\004\018\b\250\000\006\000\000\000\000\000\246\002\134\002\138\002\142\002\182\002\194\000\000\000\000\000\000\004\006\002\198\000\000\025\230\027~\000\000\000\000\000\000\003\190\000\000\000\000\000\000\000\000\002\202\000\000\003\n\003\014\000\000\000\000\025\210\003z\000\000\003\018\000\000\002\206\000\000\016f\000\000\003\150\003\154\000\000\003\158\002\250\003\170\003\178\006\142\000\000\000\000\016\202\002~\000\000\000\000\003\006\016\226\000\000\000\000\007\214\007\218\007\230\007\250\000\000\0056\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\234\000\000\bn\000\000\027*\000\000\000\000\000\000\000\000\bz\b\146\b\230\005B\005F\016\254\017*\000\000\000\000\004\129\000\246\000\000\000\000\002\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004y\000\000\000\000\021j\005J\007\238\014\002\012)\012)\b\006\004\018\b\250\012)\000\000\012)\012)\003z\000\000\000\000\000\000\000\000\000\000\016f\012)\000\000\012)\012)\012)\000\000\012)\012)\024*\000\000\000\000\016\202\000\000\000\000\000\000\000\000\016\226\000\000\012)\000\000\000\000\000\000\000\000\000\000\012)\012)\000\000\000\000\012)\000\000\000\000\012)\016\234\012)\000\000\000\000\012)\000\000\000\000\000\000\000\000\012)\012)\012)\000\000\000\000\016\254\017*\000\000\000\000\012)\012)\000\000\000\000\000\000\000\000\000\000\012)\000\000\000\000\000\000\012)\000\000\000\000\012)\000\246\000\000\021j\001\250\000\000\000\000\012)\012)\012)\000\000\012)\012)\000\000\017n\000\000\000\000\000\000\000\000\000\000\000\000\012)\000\000\012)\012)\000\000\000\000\002b\012)\000\000\017r\000\000\000\000\012)\000\000\n]\017\154\012)\n]\012)\012)\n]\n]\000\000\000\000\n]\000\000\n]\016\202\000\000\n]\000\000\000\000\016\226\n]\n]\000\000\n]\n]\000\000\n]\001\182\001\186\000\000\000\000\n]\000\000\000\000\n]\018\018\000\000\000\000\000\000\000\000\000\000\000\000\n]\000\000\n]\001\190\000\000\n]\n]\016\254\018&\000\000\000\000\004M\n]\000\000\000\000\n]\000\000\000\000\n]\n]\000\000\n]\000\000\n]\n]\001\222\002n\000\000\0186\000\000\002j\000\000\002~\003\234\003\246\000\000\n]\000\000\000\000\004\002\000\000\000\000\000\000\000\000\n]\n]\006\133\000\000\n]\000\000\n]\006\133\000\000\000\000\000\000\005b\004\006\000\000\000\000\004\185\000\000\000\000\n]\n]\000\000\n]\n]\000\000\n]\000\000\n]\000\000\n]\000\000\n]\025\210\n]\bu\bu\000\000\000\000\000\000\bu\000\000\001\186\bu\000\000\000\000\000\000\000\000\006\133\012I\0125\bu\000\000\bu\bu\bu\006\133\bu\bu\000\000\000\000\006\133\006\133\000\238\000\000\000\000\000\000\012I\000\000\bu\006\133\006\133\000\000\002\006\000\000\bu\bu\000\000\000\000\bu\002\n\000\000\002f\000\000\bu\000\000\002\014\bu\000\000\002\018\0125\000\000\bu\bu\bu\000\000\006\133\000\000\000\000\000\000\000\000\bu\bu\000\000\000\000\006\133\000\000\000\000\bu\000\000\000\000\000\000\004Z\000\000\000\000\bu\000\000\000\000\000\000\000\000\000\000\023\138\bu\bu\bu\000\000\bu\bu\000\000\000\000\003\129\012]\000\000\000\000\n\150\000\000\bu\000\000\bu\bu\001\182\001\186\n\246\bu\000\000\000\000\000\000\000\000\bu\003\129\000\000\000\000\bu\003\129\bu\bu\012\005\012\005\002v\001\206\000\000\012\005\000\000\001\186\012\005\000\000\000\000\001\218\000\000\000\000\000\000\000\000\004z\000\000\012\005\012\005\012\005\000\000\012\005\012\005\001\222\002^\000\000\000\000\000\000\002j\000\000\002~\003\234\003\246\012\005\000\000\000\000\000\000\004\002\000\000\012\005\012\005\000\000\000\000\012\005\000\000\000\000\002f\000\000\012\005\012]\012]\012\005\000\000\000\000\004\006\000\000\012\005\012\005\012\005\000\000\000\000\000\000\003\129\000\000\000\000\012\005\012\005\000\000\012]\000\000\012]\000\000\012\005\000\000\000\000\000\000\004Z\003\129\000\000\012\005\003\129\000\000\000\000\000\000\000\000\000\000\012\005\012\005\012\005\000\000\012\005\012\005\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\005\000\000\012\005\012\005\001\182\001\186\000\000\012\005\000\000\000\000\000\000\000\000\012\005\000\000\000\000\000\000\012\005\000\000\012\005\012\005\by\by\001\190\001\206\002\209\by\000\000\001\186\by\002\209\000\000\001\218\000\000\000\000\018f\000\000\by\000\000\by\by\by\000\000\by\by\001\222\019\222\000\000\018\242\000\000\002j\000\000\002~\003\234\003\246\by\000\n\000\000\000\000\019\238\000\000\by\by\000\000\000\000\by\000\000\000\000\002f\002\209\by\002\209\000\000\by\000\000\000\000\004\006\002\209\by\by\by\000\000\002\209\000\000\002\209\000\000\000\000\by\by\000\000\000\000\002\209\002\209\000\000\by\002\209\002\209\002\209\004Z\002\209\000\000\by\000\000\000\000\002\209\000\000\000\000\002\209\by\by\by\000\000\by\by\000\000\000\000\002\209\002\209\000\000\002\209\000\n\000\n\by\002\209\by\by\002\209\002\209\002\209\by\002\209\002\209\002\209\002\209\by\002\209\002\209\002\209\by\000\000\by\by\002\209\002\209\000\000\002\209\002\209\000\000\002\209\002\209\002\209\002\209\000\n\000\000\002\209\006\146\000\000\002\209\002\209\002\209\000\000\014\238\000\000\002\209\002\209\000\000\002\209\002\209\002\209\002\209\002\209\002\209\000\000\000\000\002\209\002\209\000\000\002\209\000\000\000\000\002\209\002\209\002\209\002\209\002\209\002\209\002\209\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\209\000\000\002\209\002\209\000\000\000\000\000\000\002\209\002\209\002\209\002\209\002\209\000\000\015*\000\000\000\000\0065\002\209\000!\000\000\000\000\000\000\000!\000!\000\000\000!\000!\000\000\000\000\0156\000\000\000!\002N\000\000\002\209\002\209\0065\000\000\000\000\002\209\002\209\002\209\000\000\000!\000\000\000!\000!\000\000\000\000\000\000\000\000\000\000\000!\000\000\000!\000\000\000\000\000\000\000!\000!\000\000\000!\000!\000!\000!\000!\000\000\000\000\015:\000!\007\017\000\000\000!\007\017\000\000\000\000\000!\000!\000!\000!\000\000\000!\015F\000\000\021\022\000\000\000\000\000\000\000\000\007\017\007\017\000!\007\017\007\017\000\000\000\000\000\000\000\000\000!\000!\000!\000!\000!\000\000\000\000\000\000\000\000\0061\015N\000\029\000\000\007\017\000\000\000\029\000\029\000\000\000\029\000\029\021\"\000\000\000\000\000\000\000\029\000\000\000\000\000!\000!\0061\000\000\007\017\000!\000!\000!\000\000\000\029\020\214\000\029\000\029\000\000\000\000\000\000\000\000\000\000\000\029\000\000\000\029\000\000\000\000\000\000\000\029\000\029\000\000\000\029\000\029\000\029\000\029\000\029\000\000\000\000\007\017\000\029\007\017\000\000\000\029\000\000\000\000\000\000\000\029\000\029\000\029\000\029\000\000\000\029\005\158\000\000\000\000\007\017\007\017\000\000\000\000\000\000\007\017\000\029\007\017\000\000\000\000\000\000\007\017\000\000\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\000\000\000\006A\000\000\011\205\000\000\000\000\000\000\011\205\011\205\000\000\011\205\011\205\000\000\000\000\000\000\000\000\011\205\000\000\000\000\000\029\000\029\006A\000\000\000\000\000\029\000\029\000\029\000\000\011\205\000\000\011\205\011\205\000\000\000\000\000\000\000\000\000\000\011\205\000\000\011\205\000\000\000\000\000\000\011\205\011\205\000\000\011\205\011\205\011\205\011\205\011\205\000\000\000\000\000\000\011\205\007%\000\000\011\205\007%\000\000\000\000\011\205\011\205\011\205\011\205\000\000\011\205\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007%\007%\011\205\007%\007%\000\000\000\000\000\000\000\000\011\205\011\205\011\205\011\205\011\205\000\000\000\000\000\000\000\000\006=\000\000\011\201\000\000\007%\000\000\011\201\011\201\000\000\011\201\011\201\000\000\000\000\000\000\000\000\011\201\000\000\000\000\011\205\011\205\006=\000\000\000\238\011\205\011\205\011\205\000\000\011\201\000\000\011\201\011\201\000\000\000\000\000\000\000\000\000\000\011\201\000\000\011\201\000\000\000\000\000\000\011\201\011\201\000\000\011\201\011\201\011\201\011\201\011\201\000\000\000\000\007%\011\201\007%\000\000\011\201\000\000\000\000\000\000\011\201\011\201\011\201\011\201\000\000\011\201\007%\000\000\000\000\005\166\007%\000\000\000\000\000\000\007%\011\201\007%\000\000\000\000\000\000\007%\000\000\011\201\011\201\011\201\011\201\011\201\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004M\000\000\000\000\000\000\000\000\000\246\000\000\000\000\001\250\012\t\012\t\000\000\000\000\000\000\012\t\011\201\011\201\012\t\017n\000\000\011\201\011\201\011\201\012I\0125\004*\000\000\012\t\012\t\012\t\000\000\012\t\012\t\000\000\017r\000\000\000\000\000\000\000\000\000\000\017\154\012I\000\000\012\t\000\000\000\000\000\000\002\006\000\000\012\t\012\t\000\000\016\202\012\t\002\154\000\000\000\000\016\226\012\t\000\000\002\014\012\t\000\000\002\018\0125\000\000\012\t\012\t\012\t\000\000\000\000\000\000\000\000\018\018\000\000\012\t\012\t\000\000\000\000\000\000\000\000\000\000\012\t\000\000\000\000\000\000\012\t\016\254\018&\012\t\000\000\000\000\004M\000\000\000\000\000\000\012\t\012\t\012\t\000\000\012\t\012\t\000\000\000\000\000\000\000\000\000\000\000\000\0186\007\145\012\t\000\006\012\t\012\t\007\145\002\134\002\138\012\t\002\182\002\194\000\000\000\000\012\t\000\000\002\198\000\000\012\t\000\000\012\t\012\t\000\000\014\"\000\000\000\000\000\000\000\000\002\202\000\000\003\n\003\014\000\000\000\000\000\000\000\000\000\000\003\018\000\000\002\206\000\000\000\000\000\000\003\150\003\154\007\145\003\158\002\250\003\170\003\178\006\142\000\000\000\000\007\145\002~\000\000\000\000\003\006\007\145\007\145\000\238\007\214\007\218\007\230\007\250\000\000\0056\007\145\007\145\001\181\000\000\000\000\000\000\000\000\001\181\000\000\bn\000\000\000\000\000\000\000\000\000\000\000\000\bz\b\146\b\230\005B\005F\000\000\000\000\007\145\000\000\000\000\007\145\000\000\000\000\000\000\000\000\000\000\000\000\003\t\003\t\007\145\000\000\000\000\003\t\000\000\000\000\003\t\000\000\005J\007\238\000\000\001\181\000\000\b\006\004\018\b\250\003\t\003\t\003\t\001\181\003\t\003\t\000\000\000\000\001\181\001\181\000\238\000\000\000\000\000\000\000\000\000\000\003\t\001\181\001\181\000\000\000\000\000\000\003\t\004\"\000\000\000\000\003\t\000\000\000\000\000\000\000\000\003\t\000\000\000\000\003\t\000\000\000\000\000\000\000\000\003\t\003\t\003\t\000\000\001\181\000\000\000\000\000\000\000\000\003\t\003\t\000\000\000\000\001\181\000\000\000\000\003\t\000\000\ni\000\000\003\t\ni\000\000\003\t\003\"\002\138\000\000\000\000\002\194\000\000\003\t\003\t\003\t\002\198\003\t\003\t\000\000\ni\ni\000\000\ni\ni\000\000\000\000\003\t\000\000\003\t\003\t\003&\000\000\000\000\003\t\000\000\000\000\000\000\000\000\003\t\000\000\000\000\ni\003\t\0032\003\t\003\t\003>\001\170\003\133\012]\000\000\000\000\000\000\002~\000\000\000\000\003\182\000\000\000\000\ni\003\186\000\000\003\194\005*\000\000\0056\000\000\003\133\000\000\000\000\000\000\003\133\000\000\000\000\000\000\000\000\000\000\005:\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005B\005F\000\000\005\134\ni\000\000\ni\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ni\000\000\000\000\ni\ni\000\000\005J\000\000\ni\000\000\ni\000\000\004\018\ne\ni\000\000\ne\000\000\000\000\003\"\002\138\012]\012]\002\194\000\000\006^\000\000\000\000\002\198\000\000\000\000\000\000\ne\ne\003\133\ne\ne\000\000\006~\000\000\012]\000\000\012]\003&\000\000\000\000\b\158\000\000\000\000\003\133\000\000\000\000\003\133\000\000\ne\000\000\0032\000\000\000\000\003>\001\170\000\000\000\000\000\000\000\000\000\000\002~\000\000\000\000\003\182\000\000\000\000\ne\003\186\000\000\003\194\005*\nv\0056\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004i\005:\000\000\000\000\000\000\018~\001\205\001\205\000\000\005B\005F\001\205\005\134\ne\001\205\ne\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\205\001\205\001\205\ne\001\205\001\205\ne\ne\000\000\005J\000\000\ne\000\000\ne\000\000\004\018\001\205\ne\000\000\000\000\018\170\000\000\001\205\001\205\000\000\000\000\001\205\000\000\016\202\000\000\000\000\001\205\000\000\016\226\001\205\000\000\000\000\000\000\000\000\001\205\001\205\001\205\000\000\018\230\000\000\000\000\000\000\000\000\001\205\001\205\000\000\000\000\000\000\000\000\000\000\001\205\000\000\003\"\002\138\001\205\000\000\002\194\001\205\006^\000\000\000\000\002\198\000\000\004i\001\205\001\205\001\205\000\000\001\205\001\205\000\000\006~\019Z\000\000\000\000\000\000\003&\000\000\001\205\b\158\001\205\001\205\000\000\000\000\000\000\001\205\000\000\000\000\000\000\0032\001\205\000\000\nf\001\170\004\190\000\000\001\205\000\000\000\000\002~\000\000\000\000\003\182\000\000\000\000\nA\003\186\000\000\003\194\000\000\nv\0056\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005:\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005B\005F\000\000\000\000\n~\000\000\000\000\003\"\002\138\000\000\000\000\002\194\000\000\006^\000\000\000\000\002\198\000\000\nA\n\134\000\000\nA\n\242\000\000\005J\000\000\006~\000\000\nA\000\000\004\018\003&\nA\000\000\b\158\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0032\000\000\000\000\nf\001\170\000\000\000\000\000\000\000\000\000\000\002~\000\000\000\000\003\182\000\000\000\000\nA\003\186\000\000\003\194\000\000\nv\0056\000\000\000\000\000\000\000\000\005)\005)\000\000\000\000\007\141\005)\000\000\005:\005)\007\141\000\000\000\000\000\000\000\000\000\000\005B\005F\000\000\005)\n~\005)\000\000\005)\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\nA\005)\000\000\nA\nA\000\000\005J\005)\005)\000\000\nA\000\000\004\018\005)\nA\007\141\005)\000\000\000\000\005)\000\000\000\000\000\000\007\141\005)\005)\005)\000\000\007\141\007\141\000\238\000\000\000\000\000\000\000\000\000\000\000\000\007\141\007\141\000\000\005)\005)\000\000\000\000\005)\000\000\000\000\000\000\000\000\001\006\000\000\000\000\000\000\000\000\005)\005)\005)\000\000\005)\005)\007\141\000\000\000\000\007\141\007.\001\n\000\000\000\000\000\000\000\000\000\000\005)\007\141\000\000\005)\005)\001\014\001\018\001\022\001\026\001\030\001\"\000\000\000\000\000\000\000\000\005)\000\000\000\000\001&\000\000\001.\0012\000\000\000\000\000\000\000\000\0016\000\000\000\000\001:\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001>\001B\001F\001J\001N\000\000\000\000\000\000\001R\000\000\000\000\000\000\001V\000\000\005\029\005\029\000\000\000\000\012y\005\029\000\000\001Z\005\029\012y\000\000\000\000\000\000\001^\000\000\000\000\000\000\000\000\005\029\000\000\005\029\000\000\005\029\001\134\000\000\000\000\000\000\000\000\000\000\000\000\001\138\000\000\001\142\000\000\005\029\000\000\001\146\000\000\001\150\001\154\005\029\005\029\000\000\000\000\000\000\000\000\007\154\000\000\012y\005\029\000\000\000\000\005\029\000\000\000\000\000\000\012y\005\029\005\029\000\238\000\000\012y\012y\000\238\000\000\000\000\000\000\000\000\000\000\000\000\012y\012y\000\000\005\029\005\029\003Q\003Q\005\029\000\000\000\000\003Q\000\000\000\000\003Q\000\000\000\000\000\000\005\029\005\029\005\029\000\000\005\029\005\029\003Q\000\000\003Q\012y\003Q\000\000\000\000\000\000\000\000\000\000\000\000\005\029\012y\000\000\005\029\005\029\003Q\000\000\000\000\000\000\000\000\000\000\003Q\003Q\000\000\000\000\005\029\000\000\004\233\000\000\000\000\003Q\000\000\000\000\003Q\000\000\000\000\000\000\000\000\003Q\003Q\003Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003Q\000\000\000\000\000\000\003Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003Q\003Q\003Q\000\000\003Q\003Q\b\001\b\001\000\000\000\000\004\233\b\001\000\000\000\000\b\001\000\000\000\000\003Q\000\000\000\000\000\000\003Q\000\000\000\000\b\001\000\000\b\001\000\000\b\001\000\000\000\000\000\000\003Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\001\000\000\000\000\000\000\000\000\000\000\b\001\b\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\001\000\000\000\000\b\001\000\000\000\000\000\000\000\000\b\001\b\001\b\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\001\000\000\012\185\012\185\b\001\000\000\000\000\012\185\000\000\000\000\012\185\000\000\000\000\000\000\b\001\b\001\b\001\000\000\b\001\b\001\012\185\000\000\012\185\000\000\012\185\000\000\000\000\000\000\b\001\000\000\000\000\b\001\000\000\000\000\000\000\b\001\012\185\000\000\000\000\000\000\000\000\000\000\012\185\012\185\004\190\000\000\b\001\000\000\0042\000\000\000\000\012\185\000\000\000\000\012\185\000\000\000\000\000\000\000\000\012\185\012\185\012\185\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\185\000\000\000\000\000\000\012\185\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\185\012\185\012\185\000\000\012\185\012\185\012\189\012\189\000\000\000\000\004B\012\189\000\000\000\000\012\189\000\000\000\000\012\185\000\000\000\000\000\000\012\185\000\000\000\000\012\189\000\000\012\189\000\000\012\189\000\000\000\000\000\000\012\185\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\189\000\000\000\000\000\000\000\000\000\000\012\189\012\189\000\000\000\000\000\000\000\000\0042\000\000\000\000\012\189\000\000\000\000\012\189\000\000\000\000\000\000\000\000\012\189\012\189\012\189\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\189\000\000\000\000\000\000\012\189\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\189\012\189\012\189\000\000\012\189\012\189\003Q\003Q\000\000\000\000\004B\003Q\000\000\000\000\003Q\000\000\000\000\012\189\000\000\000\000\000\000\012\189\000\000\000\000\003Q\000\000\003Q\000\000\003Q\000\000\000\000\000\000\012\189\001\182\001\186\000\000\000\000\000\000\000\000\000\000\003Q\000\000\000\000\000\000\000\000\000\000\003Q\003Q\000\000\000\000\000\000\001\190\004\237\000\000\000\000\003Q\000\000\000\000\003Q\000\000\000\000\000\000\000\000\003Q\003Q\003Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\222\002n\000\000\000\000\000\000\002j\003Q\002~\003\234\003\246\003Q\000\000\000\000\000\000\004\002\000\000\b\133\000\000\000\000\000\000\003Q\003Q\003Q\000\000\003Q\003Q\000\000\000\000\000\000\000\000\004\237\004\006\t\130\000\000\004\189\014\022\000\000\003Q\b\133\000\000\000\000\003Q\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\025\210\000\000\003Q\000\000\000\000\000\000\000\000\000\000\t\234\t\242\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\006\153\000\000\000\000\t\138\t\202\n\002\n\n\n\026\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\"\t\130\000\000\000\000\006\153\000\000\000\000\000\000\006\153\n*\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\000\000\000\000\000\000\000\000\nJ\000\000\nR\n\018\t\234\t\242\000\000\000\000\b\133\n2\000\000\000\000\000\000\t\250\000\000\000\000\000\000\n:\nB\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\138\t\202\n\002\n\n\n\026\000\000\000\000\000\000\001\189\000\000\000\000\006\153\n\"\001\189\000\000\001\186\001\189\000\000\000\000\000\000\000\000\n*\000\000\000\000\ba\000\000\001\189\000\000\000\000\000\000\001\189\000\000\000\000\000\000\000\000\nJ\000\000\nR\n\018\000\000\000\000\000\000\001\189\000\000\n2\000\000\012!\000\000\001\189\001\189\000\000\012!\n:\nB\012!\002f\000\000\001\189\000\000\000\000\001\189\000\000\000\000\000\000\012!\001\189\001\189\001\189\012!\000\000\000\000\0035\000\000\000\000\012)\000\000\0035\000\000\001\186\0035\012!\001\189\001\189\000\000\000\000\004Z\012!\b]\000\000\0035\000\000\000\000\000\000\0035\000\000\001\189\001\189\000\000\012!\001\189\001\189\000\000\000\000\012!\012!\0035\000\000\000\000\000\000\001\189\000\000\0035\001\185\000\000\000\000\000\000\001\189\000\000\002f\012!\0035\001\189\000\000\0035\000\000\000\000\000\000\001\189\0035\0035\0035\000\000\000\000\012!\012!\002F\000\000\012!\012!\000\000\000\000\000\000\000\000\000\000\0035\0035\000\000\012!\004Z\000\000\000\000\026F\000\000\000\000\012!\000\000\000\000\016\026\0035\0035\000\000\000\000\0035\0035\000\000\012!\000\000\000\000\000\000\000\000\000\000\000\000\0035\t\130\000\000\000\000\000\000\016\030\000\000\0035\000\000\000\000\000\000\000\000\0035\t\186\t\210\t\218\t\194\t\226\0035\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\234\t\242\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\138\t\202\n\002\n\n\n\026\000\000\000\149\000\000\000\000\000\000\000\000\000\149\n\"\000\000\000\149\000\000\000\000\000\000\000\000\000\000\000\000\n*\000\000\000\000\000\149\000\000\000\149\000\000\000\149\000\000\000\000\000\000\000\000\000\000\000\000\nJ\016\"\nR\n\018\0162\000\149\000\000\000\000\000\000\n2\000\000\000\149\000\000\000\000\000\000\000\149\000\000\n:\nB\000\000\000\149\000\000\000\000\000\149\000\000\000\000\000\000\000\000\000\149\000\149\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\149\000\149\000\000\000\000\000\000\000\000\000\000\000\149\000\000\000\000\000\217\000\149\000\000\000\000\000\000\000\217\000\000\000\000\000\217\000\000\000\000\000\149\000\149\000\000\000\000\000\149\000\149\000\000\000\217\000\000\000\217\000\000\000\217\000\000\000\000\000\149\000\000\000\000\000\000\000\000\000\000\000\149\000\149\000\000\000\217\000\000\000\000\000\000\000\000\000\000\000\217\000\149\000\000\000\149\000\217\000\000\000\000\000\000\000\000\000\217\000\000\000\000\000\217\000\000\000\000\000\000\000\000\000\217\000\217\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\217\000\217\000\000\000\000\000\000\000\000\000\000\000\217\000\000\000\000\000\157\000\217\000\000\000\000\000\000\000\157\000\000\000\000\000\157\000\000\000\000\000\217\000\217\000\000\000\000\000\217\000\217\000\000\000\157\000\000\000\157\000\000\000\157\000\000\000\000\000\217\000\000\000\000\000\000\000\000\000\000\000\217\000\217\000\000\000\157\000\000\000\000\000\000\000\000\000\000\000\157\000\217\000\000\000\217\000\157\000\000\000\000\000\000\000\000\000\157\000\000\000\000\000\157\000\000\000\000\000\000\000\000\000\157\000\157\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\157\000\157\000\000\000\000\000\000\000\000\000\000\000\157\000\000\000\000\000\153\000\157\000\000\000\000\000\000\000\153\000\000\000\000\000\153\000\000\000\000\000\157\000\157\000\000\000\000\000\157\000\157\000\000\000\153\000\000\000\153\000\000\000\153\000\000\000\000\000\157\000\000\000\000\000\000\000\000\000\000\000\157\000\157\000\000\000\153\006u\006u\000\000\000\000\000\000\000\153\000\157\000\000\000\157\000\153\000\000\000\000\000\000\000\000\000\153\000\000\003\250\000\153\006u\006u\000\000\000\000\000\153\000\153\000\238\000\000\000\000\006u\001\129\000\000\000\000\000\153\000\153\001\129\000\000\000\000\001\129\000\000\000\153\000\000\006u\006u\000\153\000\000\000\000\006u\001\129\006u\006u\006u\001\129\000\000\000\153\000\153\006u\000\000\000\153\000\153\000\000\000\000\000\000\000\000\001\129\001\129\000\000\000\000\000\153\000\000\001\129\000\000\000\000\006u\000\153\000\153\004\233\000\000\000\000\001\129\000\000\000\000\001\129\000\000\000\153\000\000\000\153\001\129\001\129\001\129\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\129\000\000\000\000\000\000\001\129\000\000\003\238\000\000\006u\000\000\000\000\000\000\000\000\000\000\001\129\001\129\000\000\000\000\001\129\001\129\000\000\012\181\012\181\000\000\004\233\000\000\012\181\000\000\001\129\012\181\000\000\000\000\000\000\000\000\001\129\001\129\000\000\000\000\000\000\012\181\001\129\012\181\000\000\012\181\000\000\000\000\001\129\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\181\000\000\000\000\000\000\000\000\000\000\012\181\012\181\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\181\000\000\000\000\012\181\000\000\000\000\000\000\000\000\012\181\012\181\012\181\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\181\000\000\012\177\012\177\012\181\000\000\000\000\012\177\000\000\000\000\012\177\000\000\000\000\000\000\012\181\012\181\012\181\000\000\012\181\012\181\012\177\000\000\012\177\000\000\012\177\000\000\000\000\000\000\000\000\000\000\000\000\012\181\000\000\000\000\000\000\012\181\012\177\000\000\000\000\000\000\000\000\000\000\012\177\012\177\004\190\000\000\012\181\000\000\000\000\000\000\000\000\012\177\000\000\000\000\012\177\000\000\000\000\000\000\000\000\012\177\012\177\012\177\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\177\000\000\b\005\b\005\012\177\000\000\000\000\b\005\000\000\000\000\b\005\000\000\000\000\000\000\012\177\012\177\012\177\000\000\012\177\012\177\b\005\000\000\b\005\000\000\b\005\000\000\000\000\000\000\007\n\000\000\000\000\012\177\000\000\000\000\000\000\012\177\b\005\000\000\000\000\000\000\000\000\000\000\b\005\b\005\000\000\000\000\012\177\000\000\000\000\000\000\000\000\b\005\000\000\000\000\b\005\000\000\000\000\000\000\000\000\b\005\b\005\000\238\000\000\000\000\000\000\001\185\000\000\000\000\000\000\000\000\001\185\000\000\001\186\001\185\000\000\b\005\000\000\000\000\000\000\b\005\000\000\b]\000\000\001\185\000\000\000\000\000\000\001\185\000\000\b\005\b\005\b\005\000\000\b\005\b\005\000\000\000\000\000\000\000\000\001\185\000\000\000\000\000\000\b\005\000\000\001\185\b\005\000\000\000\000\000\000\b\005\000\000\002f\000\000\001\185\000\000\000\000\001\185\000\000\000\000\000\000\b\005\001\185\001\185\001\185\000\000\000\000\000\000\001i\000\000\000\000\000\000\000\000\001i\000\000\012)\001i\000\000\001\185\001\185\000\000\000\000\004Z\000\000\012)\000\000\001i\000\000\001i\000\000\001i\000\000\001\185\001\185\000\000\000\000\001\185\001\185\000\000\000\000\000\000\000\000\001i\000\000\000\000\000\000\001\185\000\000\001i\012)\000\000\000\000\000\000\001\185\000\000\012)\000\000\000\000\001\185\000\000\001i\000\000\000\000\000\000\001\185\001i\001i\001i\000\000\000\000\000\000\005M\005M\000\000\000\000\000\000\005M\000\000\000\000\005M\000\000\001i\000\000\000\000\000\000\012)\000\000\000\000\000\000\005M\000\000\005M\000\000\005M\000\000\001i\001i\001i\000\000\001i\001i\000\000\000\000\000\000\000\000\005M\000\000\000\000\000\000\000\000\000\000\005M\005M\000\000\000\000\019\226\001i\007\154\000\000\000\000\005M\000\000\000\000\005M\000\000\000\000\000\000\001i\005M\005M\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005M\000\000\005I\006\222\005M\000\000\000\000\005I\000\000\000\000\005I\000\000\000\000\000\000\005M\005M\005M\000\000\005M\005M\005I\000\000\005I\000\000\005I\000\000\000\000\000\000\000\000\000\000\000\000\005M\000\000\000\000\000\000\005M\005I\000\000\000\000\000\000\000\000\000\000\005I\007J\000\000\000\000\005M\000\000\000\000\000\000\000\000\005I\000\000\000\000\005I\000\000\000\000\000\000\000\000\005I\005I\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005I\000\000\005e\005e\005I\000\000\000\000\005e\000\000\000\000\005e\000\000\000\000\000\000\005I\005I\005I\000\000\005I\005I\005e\000\000\005e\000\000\005e\000\000\000\000\000\000\000\000\000\000\000\000\005I\000\000\000\000\000\000\005I\005e\000\000\000\000\000\000\000\000\000\000\005e\005e\000\000\000\000\005I\000\000\000\000\000\000\000\000\005e\000\000\000\000\005e\000\000\000\000\000\000\000\000\005e\005e\005e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005e\000\000\005a\006\222\005e\000\000\000\000\005a\000\000\000\000\005a\000\000\000\000\000\000\005e\005e\005e\000\000\005e\005e\005a\000\000\005a\000\000\005a\000\000\000\000\000\000\000\000\000\000\000\000\005e\000\000\000\000\000\000\005e\005a\000\000\000\000\000\000\000\000\000\000\005a\007J\000\000\000\000\007B\000\000\000\000\000\000\000\000\005a\000\000\000\000\005a\000\000\000\000\000\000\000\000\005a\005a\000\238\004E\000\000\000\000\000\000\000\000\004E\003\"\002\138\004E\000\000\002\194\000\000\006^\005a\000\000\002\198\000\000\005a\004E\000\000\000\000\000\000\004E\000\000\000\000\006~\000\000\005a\005a\005a\003&\005a\005a\b\158\004E\000\000\000\000\000\000\000\000\000\000\004E\000\000\000\000\0032\005a\000\000\nf\001\170\005a\004E\000\000\011\206\004E\002~\000\000\000\000\003\182\004E\002\174\005a\003\186\000\000\003\194\000\000\nv\0056\000\000\t\130\000\000\000\000\000\000\000\000\000\000\004E\011\210\000\000\000\000\005:\000\000\t\186\t\210\t\218\t\194\t\226\000\000\005B\005F\004E\004E\n~\000\000\004E\004E\t\234\t\242\000\000\011\230\007.\000\000\000\000\000\000\000\000\t\250\000\000\n\134\000\000\000\000\n\146\004E\005J\000\238\000\000\t\130\020\234\000\000\004\018\011\234\000\000\000\000\t\138\t\202\n\002\n\n\n\026\t\186\t\210\t\218\t\194\t\226\000\000\000\000\n\"\000\000\000\000\000\000\000\000\000\000\000\000\t\234\t\242\n*\000\000\000\000\000\000\000\000\000\000\000\000\t\250\000\000\000\000\000\000\000\000\000\000\000\000\nJ\000\238\nR\n\018\000\000\000\000\000\000\011\246\000\000\n2\t\138\t\202\n\002\n\n\n\026\000\000\000\000\n:\nB\000\000\000\000\000\000\n\"\t\130\000\000\000\000\000\000\000\000\000\000\011\250\000\000\n*\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\000\000\000\000\000\000\000\000\nJ\000\000\nR\n\018\t\234\t\242\000\000\000\000\000\000\n2\000\000\000\000\000\000\t\250\000\000\000\000\000\000\n:\nB\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\012\006\000\000\000\000\t\138\t\202\n\002\n\n\n\026\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\"\t\130\000\000\000\000\000\000\000\000\000\000\000\000\012\n\n*\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\000\000\000\000\000\000\000\000\nJ\000\000\nR\n\018\t\234\t\242\000\000\012&\000\000\n2\000\000\000\000\000\000\t\250\000\000\000\000\000\000\n:\nB\000\000\000\000\000\238\000\000\t\130\000\000\000\000\000\000\012*\000\000\000\000\t\138\t\202\n\002\n\n\n\026\t\186\t\210\t\218\t\194\t\226\000\000\000\000\n\"\000\000\000\000\000\000\000\000\000\000\000\000\t\234\t\242\n*\000\000\000\000\000\000\000\000\000\000\000\000\t\250\000\000\000\000\000\000\000\000\000\000\000\000\nJ\000\238\nR\n\018\000\000\000\000\000\000\012>\000\000\n2\t\138\t\202\n\002\n\n\n\026\000\000\000\000\n:\nB\000\000\000\000\000\000\n\"\t\130\000\000\000\000\000\000\000\000\000\000\012B\000\000\n*\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\000\000\000\000\000\000\000\000\nJ\000\000\nR\n\018\t\234\t\242\000\000\000\000\000\000\n2\000\000\000\000\000\000\t\250\000\000\000\000\000\000\n:\nB\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\012V\000\000\000\000\t\138\t\202\n\002\n\n\n\026\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\"\t\130\000\000\000\000\000\000\000\000\000\000\000\000\012Z\n*\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\000\000\000\000\000\000\000\000\nJ\000\000\nR\n\018\t\234\t\242\000\000\000\000\000\000\n2\000\000\000\000\000\000\t\250\000\000\000\000\000\000\n:\nB\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\011\206\000\000\000\000\t\138\t\202\n\002\n\n\n\026\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\"\t\130\000\000\000\000\000\000\000\000\000\000\000\000\012\154\n*\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\000\000\000\000\000\000\000\000\nJ\000\000\nR\n\018\t\234\t\242\000\000\011\230\000\000\n2\000\000\000\000\000\000\t\250\000\000\000\000\000\000\n:\nB\000\000\000\000\000\238\000\000\t\130\000\000\000\000\000\000\012\182\000\000\000\000\t\138\t\202\n\002\n\n\n\026\t\186\t\210\t\218\t\194\t\226\000\000\000\000\n\"\000\000\000\000\000\000\000\000\000\000\000\000\t\234\t\242\n*\000\000\000\000\000\000\000\000\000\000\000\000\t\250\000\000\000\000\000\000\000\000\000\000\000\000\nJ\000\238\nR\n\018\000\000\000\000\000\000\011\246\000\000\n2\t\138\t\202\n\002\n\n\n\026\000\000\000\000\n:\nB\000\000\000\000\000\000\n\"\t\130\000\000\000\000\000\000\000\000\000\000\012\202\000\000\n*\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\000\000\000\000\000\000\000\000\nJ\000\000\nR\n\018\t\234\t\242\000\000\000\000\000\000\n2\000\000\000\000\000\000\t\250\000\000\000\000\000\000\n:\nB\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\012\006\000\000\000\000\t\138\t\202\n\002\n\n\n\026\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\"\t\130\000\000\000\000\000\000\000\000\000\000\000\000\012\222\n*\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\000\000\000\000\000\000\000\000\nJ\000\000\nR\n\018\t\234\t\242\000\000\012&\000\000\n2\000\000\000\000\000\000\t\250\000\000\000\000\000\000\n:\nB\000\000\000\000\000\238\000\000\t\130\000\000\000\000\000\000\r\014\000\000\000\000\t\138\t\202\n\002\n\n\n\026\t\186\t\210\t\218\t\194\t\226\000\000\000\000\n\"\000\000\000\000\000\000\000\000\000\000\000\000\t\234\t\242\n*\000\000\000\000\000\000\000\000\000\000\000\000\t\250\000\000\000\000\000\000\000\000\000\000\000\000\nJ\000\238\nR\n\018\000\000\000\000\000\000\012>\000\000\n2\t\138\t\202\n\002\n\n\n\026\000\000\000\000\n:\nB\000\000\000\000\000\000\n\"\t\130\000\000\000\000\000\000\000\000\000\000\r\026\000\000\n*\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\000\000\000\000\000\000\000\000\nJ\000\000\nR\n\018\t\234\t\242\000\000\000\000\000\000\n2\000\000\000\000\000\000\t\250\000\000\000\000\000\000\n:\nB\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\012V\000\000\000\000\t\138\t\202\n\002\n\n\n\026\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\"\t\130\000\000\000\000\000\000\000\000\000\000\000\000\r&\n*\000\000\000\000\000\000\t\186\t\210\t\218\t\194\t\226\000\000\000\000\000\000\000\000\000\000\nJ\000\000\nR\n\018\t\234\t\242\000\000\000\000\000\000\n2\000\000\000\000\000\000\t\250\000\000\000\000\000\000\n:\nB\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\138\t\202\n\002\n\n\n\026\000\000\000\000\000\000\0031\000\000\000\000\000\000\n\"\0031\000\000\001\186\0031\000\000\000\000\000\000\000\000\n*\000\000\000\000\000\000\000\000\0031\000\000\000\000\000\000\0031\000\000\000\000\000\000\000\000\nJ\000\000\nR\n\018\000\000\000\000\000\000\0031\000\000\n2\000\000\000\000\000\000\0031\000\000\000\000\000\000\n:\nB\000\000\002f\000\000\0031\000\000\000\000\0031\000\000\000\000\000\000\000\000\0031\0031\0031\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0031\0031\000\000\000\000\004Z\n\138\000\000\000\000\000\000\000\000\000\246\001\182\001\186\001\250\0031\0031\000\000\000\000\0031\0031\000\000\000\000\000\000\017n\000\000\000\000\000\000\004M\0031\001\190\001\206\000\000\000\000\000\000\000\000\0031\000\000\000\000\001\218\017r\0031\000\000\000\000\000\000\000\000\017\154\0031\000\000\000\000\000\000\006\253\001\222\002^\006\253\000\000\000\000\002j\016\202\002~\003\234\003\246\000\000\016\226\0011\000\000\004\002\000\000\000\000\0011\006\253\006\253\0011\006\253\006\253\000\000\000\000\000\000\000\000\018\018\000\000\000\000\0011\004\006\0011\000\000\0011\000\000\000\000\000\000\000\000\000\000\006\253\016\254\018&\000\000\000\000\000\000\0011\000\000\000\000\000\000\000\000\000\000\0011\000\000\000\000\000\000\0011\000\000\006\253\000\000\000\000\0011\0186\000\000\0011\000\000\000\000\000\000\000\000\0011\0011\000\238\000\000\000\000\000\000\001-\000\000\000\000\000\000\0011\001-\000\000\000\000\001-\000\000\0011\000\000\000\000\006\253\0011\006\253\000\000\000\000\001-\000\000\001-\000\000\001-\000\000\0011\0011\0011\006\253\0011\0011\005\166\006\253\000\000\000\000\001-\006\253\000\000\006\253\0011\000\000\001-\006\253\000\000\000\000\001-\0011\000\000\000\000\000\000\001-\000\000\000\000\001-\000\000\000\000\000\000\0011\001-\001-\000\238\000\000\000\000\000\000\001m\000\000\000\000\000\000\001-\001m\000\000\012-\001m\000\000\001-\000\000\000\000\000\000\001-\000\000\012-\000\000\001m\000\000\001m\000\000\001m\000\000\001-\001-\001-\000\000\001-\001-\000\000\000\000\000\000\000\000\001m\000\000\000\000\000\000\001-\000\000\001m\012-\000\000\000\000\000\000\001-\000\000\012-\000\000\000\000\000\000\000\000\001m\000\000\000\000\000\000\001-\001m\001m\001m\000\000\000\000\000\000\001\029\000\000\000\000\000\000\000\000\001\029\000\000\000}\001\029\000\000\001m\000\000\000\000\000\000\012-\000\000\000}\000\000\001\029\000\000\001\029\000\000\001\029\000\000\001m\001m\001m\000\000\001m\001m\000\000\000\000\000\000\000\000\001\029\000\000\000\000\000\000\000\000\000\000\001\029\000}\000\000\000\000\000\000\001m\000\000\000}\000\000\000\000\000\000\000\000\001\029\000\000\000\000\000\000\001m\001\029\001\029\001\029\001\197\000\000\000\000\000\000\000\000\001\197\000\000\0156\001\197\000\000\002N\000\000\000\000\001\029\000\000\000\000\000\000\000}\001\197\000\000\000\000\000\000\001\197\000\000\000\000\000\000\000\000\001\029\001\029\001\029\000\000\001\029\001\029\000\000\001\197\001\182\001\186\000\000\000\000\000\000\001\197\000\000\000\000\000\000\000\000\000\000\015:\000\000\001\029\001\197\000\000\015J\001\197\001\190\001\206\000\000\000\000\001\197\001\197\001\029\015F\000\000\001\218\000\000\000\000\000\000\000\000\000\000\000\000\001\226\000\000\000\000\000\000\001\197\0009\001\222\002^\001\197\000\000\0009\002j\0009\002~\003\234\003\246\000\000\015N\001\197\001\197\004\002\0009\001\197\001\197\0009\000\000\000\000\000\000\0009\b!\000\000\000\000\001\197\000\000\000\000\000\000\000\000\004\006\000\000\001\197\000\000\000\000\000\000\000\000\000\000\000\000\0009\000\000\000\000\0009\001\197\000\000\0009\000\000\000\000\000\000\000\000\0009\000\000\000\000\000\000\000\000\0009\0009\0009\000\000\000\000\000\000\000\000\000\000\000\000\0009\0009\004\014\000\000\004\018\000\000\003\"\002\138\000\000\000\000\002\194\0009\006^\000\000\0009\002\198\000\000\000\000\000\000\004E\000\000\000\000\004E\0009\000\000\006~\0009\000\000\000\000\000\000\003&\b!\004E\b\158\000\000\0009\000\000\000\000\0009\000\000\000\000\b\226\000\000\0032\000\000\000\000\rN\001\170\004E\000\000\000\000\0009\000\000\002~\004E\000\000\003\182\000\000\000\000\000\000\003\186\004E\003\194\004E\nv\0056\004E\000\000\000\000\004E\000\000\004E\002\174\000\000\000\000\000\000\000\000\005:\000\000\004E\000\000\000\000\000\000\004E\000\000\005B\005F\004E\000\000\000\000\000\000\004E\000\000\000\000\000\000\004E\000\000\000\000\000\000\000\000\000\000\004E\004E\000\000\000\000\004E\000\000\r^\000\000\005J\004E\000\000\000\000\004E\000\000\004\018\000\000\000\000\004E\002\174\000\238\000\000\004E\000\000\003)\000\000\000\000\004E\004E\003)\000\000\000\000\003)\000\000\004E\004E\000\000\000\000\004E\000\000\000\000\000\000\003)\000\000\000\000\000\000\003)\000\000\004E\004E\000\000\000\000\004E\004E\000\000\000\000\000\000\000\000\003)\015V\000\000\000\000\004E\000\000\003)\000\000\000\000\004E\000\000\004E\004E\000\000\000\000\003)\025N\000\000\003)\000\000\000\000\000\000\004E\003)\003)\003)\004E\000\000\003\"\002\138\000\000\000\000\002\194\000\000\006^\000\000\000\000\002\198\004E\003)\000\000\000\000\000\000\003)\004E\000\000\000\000\006~\000\000\000\000\0042\000\000\003&\003)\003)\b\158\004E\003)\003)\000\000\000\000\004E\002\174\023\018\000\000\0032\000\000\003)\003>\001\170\000\000\000\000\000\000\015\182\003)\002~\000\000\004E\003\182\003)\000\000\000\000\003\186\000\000\003\194\003)\nv\0056\000\000\000\000\000\000\004E\004E\000\000\000\000\004E\004E\000\000\000\000\005:\000\000\004B\000\000\000\000\000\000\007\n\000\000\005B\005F\003\"\002\138\021\130\004E\002\194\000\000\006^\000\000\000\000\002\198\000\000\000\000\000\000\000\000\004E\000\000\000\000\000\000\000\000\006~\023\222\000\000\005J\000\000\003&\000\000\000\000\b\158\004\018\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0032\000\000\000\000\nf\001\170\000\000\000\000\000\000\000\000\000\000\002~\006q\006q\003\182\000\000\000\000\000\000\003\186\000\000\003\194\000\000\nv\0056\000\000\000\000\000\000\000\000\000\000\000\000\006q\006q\000\000\000\000\000\000\005:\000\000\000\000\000\000\006q\000\000\000\000\000\000\005B\005F\003\"\002\138\n~\000\000\002\194\000\000\006^\006q\006q\002\198\000\000\000\000\006q\000\000\006q\006q\006q\000\000\000\000\006~\022\026\006q\005J\000\000\003&\000\000\000\000\b\158\004\018\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0032\006q\000\000\nf\001\170\005~\000\000\000\000\000\000\000\000\002~\003\"\002\138\003\182\000\000\002\194\000\000\003\186\000\000\003\194\002\198\nv\0056\000\000\000\000\005\130\000\000\003\190\000\000\000\000\000\000\000\000\000\000\000\000\005:\003&\000\000\000\000\000\000\000\000\000\000\000\000\005B\005F\004\166\000\000\n~\000\000\0032\000\000\000\000\003>\001\170\000\000\000\000\000\000\000\000\000\000\002~\000\000\000\000\003\182\000\000\000\000\022z\003\186\005J\003\194\005*\000\000\0056\000\000\004\018\000\000\000\000\000\000\000\000\000\000\000\000\b\161\000\000\000\000\005:\000\000\000\000\003\"\002\138\000\000\000\000\002\194\005B\005F\000\000\005\134\002\198\000\000\000\000\000\000\000\000\000\000\000\000\b\161\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003&\000\000\005\206\000\000\000\000\005J\000\000\006J\000\000\b\134\000\000\004\018\000\000\0032\000\000\000\000\003>\001\170\000\000\000\000\000\000\000\000\000\000\002~\000\000\000\000\003\182\000\000\011\233\000\000\003\186\011\233\003\194\005*\000\000\0056\002\209\002\209\000\000\000\000\002\209\011\233\000\000\000\000\000\000\002\209\000\000\005:\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005B\005F\011\233\005\134\000\000\002\209\000\n\000\000\011\233\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\233\002\209\000\000\011\233\002\209\002\209\000\000\005J\011\233\b\161\000\000\002\209\000\000\004\018\002\209\000\000\000\000\002\209\002\209\000\000\002\209\002\209\000\000\002\209\011\233\004-\004-\000\000\011\233\004-\000\000\000\000\000\000\000\000\004-\002\209\000\000\000\000\011\233\011\233\004-\000\000\011\233\002\209\002\209\000\000\002\209\000\000\027J\004-\022\202\000\000\000\000\022\226\000\000\000\000\000\000\000\000\000\000\011\233\000\000\000\000\004-\000\000\000\000\004-\004-\002\209\000\000\000\000\000\000\002\209\004-\002\209\000\000\004-\000\000\000\000\000\238\004-\003)\004-\004-\000\000\004-\003)\000\000\000\000\003)\003)\000\000\000\000\000\000\000\000\003)\000\000\004-\003)\003)\000\000\000\000\000\000\003)\000\000\004-\004-\000\000\003)\000\000\000\000\000\000\003)\000\000\000\000\003)\015V\000\000\000\000\000\000\000\000\003)\000\000\000\000\003)\015V\000\000\000\000\000\000\004-\003)\000\000\000\000\003)\000\000\004-\000\000\000\000\003)\003)\003)\003)\003)\000\000\000\000\000\000\003)\003)\003)\003)\000\000\000\000\000\000\000\000\003)\000\000\000\000\000\000\003)\003)\000\000\000\000\000\000\003)\000\000\000\000\000\000\003)\003)\003)\025V\000\000\003)\003)\000\000\003)\015V\003)\003)\025\134\000\000\003)\003)\000\000\000\000\000\000\000\000\012!\015\182\003)\003)\000\000\012!\003)\003)\012!\000\000\015\182\003)\003)\003)\000\000\000\000\003)\000\000\012!\000\000\000\000\000\000\012!\000\000\000\000\000\000\000\000\003)\012)\000\000\000\000\003)\000\000\000\000\012!\000\000\000\000\000\000\000\000\000\000\012!\003)\003)\017:\000\000\003)\003)\000\000\000\000\012!\000\000\000\000\012!\000\000\000\000\000\000\000\000\012!\012!\003\"\002\138\015\182\003)\002\194\000\000\006^\000\000\000\000\002\198\000\000\000\000\000\000\000\000\012!\000\000\000\000\000\000\012!\006~\000\000\000\000\000\000\000\000\003&\000\000\000\000\b\158\012!\012!\002F\000\000\012!\012!\000\000\000\000\000\000\0032\000\000\000\000\b\202\001\170\012!\005\001\000\000\000\000\026~\002~\005\001\012!\003\182\005\001\000\000\000\000\003\186\000\000\003\194\000\000\nv\0056\012!\005\001\000\000\000\000\000\000\005\001\000\000\000\000\000\000\000\000\000\000\005:\000\000\000\000\000\000\000\000\000\000\005\001\000\000\005B\005F\000\000\000\000\005\001\000\000\000\000\000\000\000\000\000\000\007\154\000\000\000\000\005\001\000\000\000\000\005\001\000\000\000\000\000\000\000\000\005\001\005\001\000\238\005J\000\000\000\000\005\005\000\000\000\000\004\018\000\000\005\005\000\000\000\000\005\005\000\000\005\001\005\001\000\000\000\000\005\001\000\000\000\000\000\000\005\005\000\000\000\000\000\000\005\005\000\000\005\001\005\001\000\000\000\000\005\001\005\001\000\000\000\000\000\000\000\000\005\005\012\193\012\193\000\000\000\000\000\000\005\005\000\000\000\000\000\000\000\000\005\001\007\154\000\000\000\000\005\005\000\000\000\000\005\005\012\193\012\193\006\242\005\001\005\005\005\005\000\238\000\000\000\000\012\193\005\169\000\000\000\000\000\000\000\000\005\169\000\000\000\000\005\169\000\000\005\005\005\005\012\193\012\193\005\005\000\000\000\000\012\193\005\169\012\193\012\193\012\193\005\169\000\000\005\005\005\005\012\193\000\000\005\005\005\005\000\000\000\000\000\000\000\000\005\169\000\000\000\000\000\000\000\000\000\000\005\169\000\000\000\000\012\193\000\000\005\005\000\000\000\000\000\000\005\169\000\000\000\000\005\169\000\000\000\000\000\000\005\005\005\169\005\169\000\238\025.\000\000\000\000\000\000\000\000\000\000\003\"\002\138\000\000\000\000\002\194\000\000\000\000\005\169\000\000\002\198\000\000\005\169\000\000\000\000\000\000\000\000\006\n\000\000\000\000\000\000\000\000\005\169\005\169\021\014\003&\005\169\005\169\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\169\000\000\0032\000\000\000\000\003>\001\170\005\169\000\000\000\000\000\000\000\000\002~\000\000\000\000\003\182\000\000\000\000\005\169\003\186\000\000\003\194\005*\005\241\0056\000\000\000\000\000\000\000\000\000\000\002\138\000\000\000\000\002\194\000\000\000\000\005:\000\000\002\198\000\000\000\000\000\000\000\000\005\241\005B\005F\000\000\005\134\000\000\000\000\002\202\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\206\000\000\000\000\000\000\000\000\000\000\000\000\005J\002\250\001\170\000\000\b\134\000\000\004\018\000\000\002~\000\000\000\000\003\006\001\182\001\186\000\000\007\214\007\218\007\230\000\000\000\000\0056\000\000\000\000\000\000\000\000\000\000\002Z\000\000\005\170\000\000\001\190\001\206\000\000\000\000\003\"\002\138\000\000\000\000\002\194\001\218\005B\005F\000\000\002\198\000\000\000\000\001\226\000\000\000\000\000\000\000\000\000\000\001\222\002^\000\000\000\000\000\000\002j\003&\002~\003\234\003\246\000\000\000\000\005J\007\238\004\002\000\000\000\000\b\006\004\018\0032\000\000\000\000\003>\001\170\000\000\000\000\000\000\005\230\000\000\002~\000\000\004\006\003\182\003\"\002\138\000\000\003\186\002\194\003\194\005*\000\000\0056\002\198\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005:\000\000\000\000\000\000\003&\000\000\000\000\015>\005B\005F\000\000\005\134\000\000\000\000\000\000\000\000\000\000\0032\000\000\000\000\003>\001\170\000\000\000\000\000\000\000\000\000\000\002~\000\000\000\000\003\182\000\000\005J\000\000\003\186\005\242\003\194\005*\004\018\0056\000\000\003\"\002\138\000\000\000\000\002\194\000\000\000\000\000\000\000\000\002\198\005:\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005B\005F\000\000\005\134\000\000\000\000\003&\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0032\000\000\000\000\003>\001\170\005J\000\000\000\000\005\245\000\000\002~\004\018\000\000\003\182\003\"\002\138\000\000\003\186\002\194\003\194\005*\000\000\0056\002\198\000\000\000\000\000\000\000\000\005\245\000\000\000\000\000\000\000\000\000\000\005:\000\000\000\000\000\000\003&\000\000\000\000\000\000\005B\005F\000\000\005\134\000\000\000\000\000\000\000\000\000\000\0032\000\000\000\000\003>\001\170\000\000\000\000\000\000\000\000\000\000\002~\000\000\000\000\003\182\000\000\005J\000\000\003\186\011^\003\194\005*\004\018\0056\000\000\003\"\002\138\000\000\000\000\002\194\000\000\000\000\000\000\000\000\002\198\005:\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005B\005F\000\000\000\000\000\000\000\000\003&\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0032\000\000\000\000\003>\001\170\005J\000\000\000\000\011j\000\000\002~\004\018\000\000\003\182\003\"\002\138\000\000\003\186\002\194\003\194\005*\000\000\0056\002\198\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005:\000\000\000\000\000\000\003&\000\000\000\000\000\000\005B\005F\000\000\005\134\000\000\000\000\000\000\000\000\000\000\0032\000\000\000\000\003>\001\170\000\000\000\000\000\000\000\000\000\000\002~\000\000\000\000\003\182\000\000\005J\000\000\003\186\011v\003\194\005*\004\018\0056\000\000\003\"\002\138\000\000\000\000\002\194\006\025\000\000\000\000\000\000\002\198\005:\000\000\002\138\000\000\000\000\002\194\000\000\000\000\005B\005F\002\198\005\134\000\000\000\000\003&\006\025\000\000\000\000\000\000\000\000\000\000\000\000\002\202\000\000\000\000\000\000\000\000\0032\000\000\000\000\003>\001\170\005J\002\206\000\000\000\000\000\000\002~\004\018\000\000\003\182\002\250\001\170\000\000\003\186\000\000\003\194\005*\002~\0056\000\000\003\006\000\000\000\000\000\000\007\214\007\218\007\230\000\000\000\000\0056\005:\000\000\000\000\000\000\000\000\006\161\006\222\000\000\005B\005F\006\161\005\134\000\000\006\161\000\000\000\000\000\000\000\000\000\000\005B\005F\000\000\000\000\006\161\000\000\000\000\000\000\006\161\000\000\000\000\000\000\000\000\005J\000\000\000\000\000\000\000\000\000\000\004\018\006\161\000\000\000\000\000\000\005J\007\238\006\161\007J\000\000\b\006\004\018\001\153\000\000\000\000\000\000\006\161\001\153\000\000\006\161\001\153\000\000\000\000\000\000\006\161\006\161\000\238\000\000\000\000\000\000\001\153\000\000\000\000\000\000\001\153\000\000\000\000\000\000\000\000\000\000\006\161\000\000\000\000\000\000\006\161\000\000\001\153\000\000\000\000\000\000\000\000\000\000\001\153\000\000\006\161\006\161\000\000\000\000\006\161\006\161\000\000\001\153\000\000\000\000\001\153\000\000\000\000\000\000\000\000\001\153\001\153\001\153\001\201\000\000\005\173\006\161\000\000\001\201\000\000\005\173\001\201\000\000\005\173\000\000\000\000\001\153\000\000\000\000\000\000\001\153\001\201\000\000\005\173\000\000\001\201\000\000\005\173\000\000\000\000\001\153\001\153\000\000\000\000\001\153\001\153\000\000\001\201\000\000\005\173\017J\000\000\000\000\001\201\000\000\005\173\000\000\000\000\000\000\000\000\000\000\001\153\001\201\000\000\005\173\001\201\001\153\005\173\000\000\000\000\001\201\001\201\005\173\005\173\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\201\000\000\005\173\000\000\001\201\000\000\005\173\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\201\001\201\005\173\005\173\001\201\001\201\005\173\005\173\000\000\000\000\000\000\000\000\000\000\000\000\001\201\011\217\005\173\002\138\011\217\000\000\0272\001\201\000\000\005\173\000\000\0276\020\234\000\000\011\217\000\000\000\000\000\000\001\201\000\000\005\173\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\217\000\000\000\000\000\000\000\000\000\000\011\217\000\000\000\000\000\000\000\000\004E\001\002\001\170\000\000\011\217\004E\000\000\011\217\004E\000\000\000\000\000\000\011\217\000\000\000\000\000\000\000\000\000\000\004E\000\000\027:\000\000\004E\000\000\000\000\000\000\000\000\000\000\011\217\000\000\000\000\000\000\011\217\000\000\004E\000\000\000\000\000\000\000\000\000\000\004E\027>\011\217\011\217\000\000\000\000\011\217\000\000\000\000\004E\000\000\000\000\004E\000\000\000\000\000\000\000\000\004E\002\174\000\000\000\000\000\000\000\000\011\217\000\000\000\000\007\193\007\193\000\000\000\000\007\193\000\000\000\000\004E\000\000\007\193\000\000\004E\000\000\000\000\000\000\015\226\000\000\000\000\000\000\000\000\000\000\004E\004E\000\000\007\193\004E\004E\006\222\000\000\000\000\000\000\004E\000\000\000\000\004E\007\n\000\000\007\193\000\000\000\000\007\193\007\193\004E\004E\004E\000\000\000\000\007\193\004E\000\000\007\193\004E\000\000\004E\007\193\000\000\007\193\007\193\000\000\007\193\004E\004E\000\000\000\000\000\000\004E\004E\007J\000\000\000\000\000\000\007\193\000\000\000\000\000\000\000\000\000\000\004E\004E\007\193\007\193\000\000\000\000\004E\002\174\000\238\000\000\000\000\000\000\007\154\000\000\000\000\004E\000\000\000\000\004E\000\000\000\000\000\000\004E\004E\002\174\000\238\007\193\000\000\000\000\000\000\001U\000\000\007\193\000\000\000\000\001U\004E\004E\001U\004E\004E\004E\000\000\004E\000\000\000\000\000\000\000\000\001U\000\000\001U\000\000\001U\004E\004E\000\000\000\000\004E\004E\001\182\001\186\022\030\000\000\000\000\001U\000\000\000\000\000\000\004E\000\000\001U\000\000\000\000\000\000\004E\000\205\000\000\002v\001\206\000\000\000\205\000\000\001U\000\205\000\000\000\000\001\218\001U\001U\000\238\000\000\000\000\000\000\000\205\000\000\000\000\000\000\000\205\000\000\001\222\002^\000\000\000\000\001U\002j\000\000\002~\003\234\003\246\000\205\000\000\000\000\000\000\004\002\000\000\000\205\000\000\001U\001U\001U\000\000\001U\001U\000\000\000\205\000\000\000\000\000\205\000\000\000\000\004\006\000\000\000\205\000\205\000\238\000\000\000\000\000\000\001U\000\209\000\000\000\000\000\000\000\000\000\209\000\000\000\000\000\209\000\205\001U\000\000\000\000\000\205\000\000\000\000\000\000\000\000\000\209\000\000\000\000\000\000\000\209\000\205\000\205\000\000\000\000\000\205\000\205\000\000\000\000\000\000\000\000\000\000\000\209\000\000\000\000\000\000\000\000\000\000\000\209\000\000\000\000\000\000\000\205\000\000\000\000\000\000\000\000\000\209\000\000\000\000\000\209\000\000\000\000\000\205\000\000\000\209\000\209\000\238\000\000\000\000\001\182\002J\000\000\000\000\002N\000\000\000\000\000\000\000\000\000\000\000\000\000\209\000\000\000\000\000\000\000\209\000\000\000\000\001\190\001\206\002R\000\000\000\000\000\000\000\000\000\209\000\209\001\218\000\000\000\209\000\209\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002V\002^\000\000\000\000\000\000\002j\000\209\002~\003\234\003\246\000\000\000\000\000\000\000\000\020\194\000\000\020\198\000\209\000\000\006\157\000\000\000\000\000\000\000\000\006\157\000\000\000\000\006\157\000\000\000\000\000\000\004\006\000\000\000\000\000\000\000\000\000\000\006\157\000\000\000\000\015N\006\157\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\210\000\000\000\000\006\157\000\000\000\000\000\000\000\000\000\000\006\157\000\000\000\000\000\000\000\000\005\161\000\000\000\000\020\214\006\157\005\161\000\000\006\157\005\161\000\000\000\000\000\000\006\157\006\157\000\000\017\026\000\000\000\000\005\161\000\000\000\000\000\000\005\161\000\000\000\000\000\000\000\000\000\000\006\157\000\000\000\000\000\000\006\157\000\000\005\161\000\000\000\000\000\000\000\000\000\000\005\161\000\000\006\157\006\157\016z\000\000\006\157\006\157\000\000\005\161\000\000\000\000\005\161\000\000\000\000\000\000\000\000\005\161\005\161\000\000\005\r\006\222\000\000\006\157\000\000\005\r\000\000\000\000\005\r\000\000\000\000\000\000\000\000\005\161\000\000\000\000\000\000\005\161\005\r\000\000\000\000\000\000\005\r\000\000\000\000\000\000\000\000\005\161\005\161\000\000\000\000\005\161\005\161\000\000\005\r\000\000\000\000\000\000\000\000\000\000\005\r\007J\000\000\000\000\000\000\011\137\000\000\000\000\005\161\000\000\011\137\000\000\005\r\011\137\000\000\000\000\000\000\005\r\005\r\000\238\000\000\000\000\000\000\011\137\000\000\000\000\000\000\011\137\000\000\000\000\000\000\000\000\000\000\005\r\000\000\000\000\000\000\000\000\000\000\011\137\000\000\000\000\000\000\000\000\000\000\011\137\000\000\005\r\005\r\000\000\000\000\005\r\005\r\000\000\011\137\000\000\000\000\011\137\000\000\000\000\000\000\000\000\011\137\000\000\000\000\000\000\000\000\000\000\005\r\000\000\000\000\001\182\002J\000\000\000\000\002N\000\000\000\000\011\137\tv\000\000\000\000\011\137\004\029\000\000\000\000\000\000\000\000\004\029\001\190\001\206\004\029\011\137\011\137\000\000\000\000\011\137\011\137\001\218\000\000\000\000\004\029\000\000\000\000\000\000\004\029\000\000\000\000\000\000\000\000\000\000\002V\002^\011\137\000\000\000\000\002j\004\029\002~\003\234\003\246\000\000\000\000\004\029\nZ\020\194\000\000\026*\004\021\000\000\000\000\000\000\004\029\004\021\000\000\004\029\004\021\000\000\000\000\000\000\004\029\000\000\004\006\000\000\000\000\000\000\004\021\000\000\000\000\000\000\004\021\015N\000\000\000\000\000\000\000\000\004\029\000\000\000\000\000\000\004\029\0266\004\021\000\000\000\000\000\000\000\000\000\000\004\021\000\000\004\029\004\029\000\000\000\000\004\029\004\029\000\000\004\021\020\214\000\000\004\021\000\000\000\000\000\000\000\000\004\021\000\000\000\000\0045\000\000\000\000\004\029\000\000\0045\000\000\000\000\0045\000\000\000\000\000\000\000\000\004\021\016\174\000\000\000\000\004\021\0045\000\000\000\000\000\000\0045\000\000\000\000\000\000\000\000\004\021\004\021\000\000\000\000\004\021\004\021\000\000\0045\000\000\000\000\000\000\000\000\000\000\0045\000\000\000\000\000\000\000\000\004\005\000\000\000\000\004\021\0045\004\005\000\000\0045\004\005\000\000\000\000\000\000\0045\000\000\019\158\000\000\000\000\000\000\004\005\000\000\000\000\000\000\004\005\000\000\000\000\000\000\000\000\000\000\0045\000\000\000\000\000\000\0045\000\000\004\005\000\000\000\000\000\000\000\000\000\000\004\005\000\000\0045\0045\000\000\007)\0045\0045\007)\004\005\000\000\000\000\004\005\000\000\000\000\000\000\000\000\004\005\000\000\000\000\000\000\000\000\000\000\0045\007)\007)\000\000\007)\007)\000\000\000\000\000\000\000\000\004\005\020\134\000\000\007\025\004\005\000\000\007\025\000\000\000\000\000\000\001\182\001\186\022~\007)\004\005\004\005\000\000\000\000\004\005\004\005\000\000\000\000\007\025\007\025\000\000\007\025\007\025\000\000\002v\001\206\000\000\000\238\000\000\000\000\004%\004\005\000\000\001\218\000\000\004%\000\000\000\000\004%\000\000\007\025\000\000\023\254\000\000\000\000\000\000\001\222\002^\004%\000\000\000\000\002j\004%\002~\003\234\003\246\000\000\007)\000\238\007)\004\002\000\000\000\000\000\000\004%\000\000\000\000\000\000\000\000\000\000\004%\007)\000\000\000\000\005\166\007)\000\000\004\006\000\000\007)\000\000\007)\004%\000\000\000\000\007)\000\000\004%\007\025\004\r\007\025\004=\000\000\000\000\004\r\000\000\004=\004\r\000\000\004=\000\000\000\000\005\226\004%\000\000\005\166\007\025\004\r\000\000\004=\007\025\004\r\007\025\004=\000\000\000\000\007\025\004%\004%\000\000\000\000\004%\004%\004\r\000\000\004=\000\000\000\000\000\000\004\r\000\000\004=\000\000\000\000\000\000\000\000\000\000\000\000\004%\000\000\000\000\004\r\000\000\004=\000\000\000\000\004\r\000\000\004=\017\242\004M\000\000\004Y\000\000\000\000\000\246\000\000\000\246\001\250\000\000\002\142\000\000\004\r\000\000\004=\000\000\000\000\000\000\017n\000\000\003v\000\000\004M\000\000\004Y\000\000\004\r\004\r\004=\004=\004\r\004\r\004=\004=\017r\000\000\003z\000\000\000\000\000\000\017\154\000\000\016f\000\000\000\000\000\000\000\000\004\r\000\000\004=\000\000\024*\016\202\000\000\016\202\000\000\000\000\016\226\0202\016\226\020\174\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\150\000\000\018\018\000\000\016\234\000\000\001\182\001\186\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\254\018&\016\254\017*\004M\004M\004Y\004Y\001\190\001\206\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\218\n\226\000\000\000\000\0186\000\000\021j\001\182\001\186\000\000\000\000\000\000\000\000\001\222\002^\000\000\000\246\000\000\002j\002\142\002~\003\234\003\246\000\000\000\000\001\190\001\206\004\002\000\000\027~\000\000\000\000\000\000\000\000\001\218\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\006\003z\000\000\001\222\002^\000\000\000\000\016f\002j\000\000\002~\003\234\003\246\000\000\000\000\000\000\024*\004\002\000\000\016\202\000\000\000\000\000\000\000\000\016\226\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\006\000\000\000\000\000\000\000\000\000\000\016\234\000\000\000\000\000\000\027*\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\254\017*\000\000\000\000\004\129\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\021j"))
+  
+  and lhs =
+    (8, "\006\005\004\003\002\001\000\193\193\192\192\191\190\190\190\190\190\190\190\190\190\190\190\190\190\190\190\190\190\190\190\190\189\189\188\187\187\187\187\187\187\187\187\186\186\186\186\186\186\186\186\185\185\185\184\184\183\183\182\182\182\181\181\180\180\180\180\180\180\179\179\179\179\179\179\179\179\178\178\178\178\178\178\178\178\177\177\177\177\176\175\175\174\174\174\174\173\173\173\173\173\173\172\172\172\172\172\172\172\171\170\170\170\169\169\168\168\167\167\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\166\165\165\164\163\162\161\160\160\159\159\158\158\158\158\157\157\157\157\156\156\155\155\154\154\154\154\153\152\151\151\150\150\149\149\148\147\146\145\144\143\143\143\142\142\141\141\140\140\140\140\140\139\139\139\139\139\139\139\139\138\138\138\138\138\138\137\137\136\136\136\135\135\134\134\134\133\133\132\132\131\131\130\130\129\129\128\128\127\127~~}}||{{{zzzzyyxxwwvvvvvuuuutttsssssssrrrrrrrqqqqppooonnmmmmmmmmmllkkkkkkkkkkkjiihhgggggfeeddccccccccccccccbbaa```````````````````````````````__^^]]\\\\[[ZZYYXXWWVVUUTTTTTTTTTTTSRQPPPPPPPPPPOOONNNMMMMLLLLLLLLLKKJJJJJIIHHGFEEDDDDDCCBBAAA@@@@@@???>>==<<;;::999887766554433221100//...---,,,+++****)(''''''''''''''''''&&&&&%%%%%%%$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$##\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  \031\031\031\030\030\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\028\028\027\027\026\026\026\026\026\026\026\025\025\025\025\024\024\023\023\023\023\023\022\022\021\021\020\019\019\019\018\018\017\017\017\016\016\015\015\015\015\015\014\014\r\r\r\r\r\012\011\011\n\n\n\t\t\t\b\b\b\b\007\007")
+  
+  and goto =
+    ((16, "\000\025\001A\000\024\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000p\000\000\000\000\000T\000\176\000\022\001-\000\142\000\024\000u\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000*\250\000\000\000\000\000\021\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\000\254\000\240\000\199\000\000\001\190\t\006\001\014\001\244\000T\000\000\000^\000\000\000>\002N\000\000\002,\000\000\000\000\000\000\000\000\000\000\000\017\000\000\000\023\003N\002\n\000\000\000\000\001`\000\164\000\000\000\000\000~\000\000\001z\000\000\bx\002d\000\000\001\164\000\228\000\000\000\000\002V\002P\001.\003\b\001\130\003N\003\212\003 \002\188\001\130\003.\003\018\b8\000\000\000\000\000\168\003\132\003\172\000\132\000\000\000\000\000\000\000\000\000\000\000\000\003\214\000\000\004~\000\000\000\168\t\022\000\000\000\000\003\160\003\240\003\142\025d\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000N\000\000\003\186\004.\000\000\000\000\000\000\000\189\000\000\000\000\0048\000\127\006\000\005\000\0068\004\180\004\244\006,\000Q\000\011\006d\025\152\000\000\000\000\005b\006\202\t4\000\000\025\216\007x\t\244\n\016\000\000\000\169\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\016+\012\006\026\000\000\n@\006\028\000\000\nr\026*\001\202\000\000\n\142\005\192\000\000\000\000\000\000\000#\000\000\000\002\000\000\006\164\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0048\003\162\000\000\000\000\000\134\000\000\002r\000\000\0048\005\140\0048\000\000\000\000\000\000\000\000\000\000\026f\000\000\0076\006\232\000\000\019*\007J/`\000\000\000\000\000\000\006\166\000\000\000\000\000\000\000\000\006|\000\000\000\000\000\000\000\000\000\000\n\200\000\000\000\000\000\000\000\000\000\000\000\000\0007\007P\000\000\000\000\000\000\006|\b\"\0268\007\238\007x#\140\000\000\004\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\166\000\000\000\000\000\000\000\000\t\026\026\248\000\000\000\000\bB\007\234\027\"\000\000\000\000\000\000\027@\b,\027X\000\000\b,\000\000\027\206\b,\000\000\027\230\b,\b,\000\000\000\000\b,\000\000\000\000\027\240\000\000\b,\028t\000\000\b,\t\146\000\000\000\000\n\016\000\000\000\000\000\000\000\000\b,\011V\000\000\000\000\000\000\b,\000\000\000\242\b\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\"J\000\000\b\182\000\000+F\006|\000\000\000\000\000\000\000\000\b\196\t6\n\216\b\156\b\176\b\190\b\216\000\180\t\018\000\004\b\214\000\000\000\000\000\000\000\000\000\143\001\172\t\156\002\240\b\224\002\002\000\000\001\198\0006\003L\000\250\n(\000\000\000\000/~\000\000/\154\t\220\000\000+Z\006|+\150\006|\000\000\t\198\000\000\t\210\000\000\000\000\t\230\000\000\000\000\000\000\n\236\000\000\002\222\001\198\000\000\000\000\t\218\000\000\000\000\000\000\000\000\000\000\000\000\001\198\000\000\000\000\001\198\000\000\b\224\000\212\000\000\000*\000\011\000\000\000*\000\000\000\000\0034\001\198\000\000\000\000\000\000\000\000\000\000\000\000\000*\n\250\011n\n\172\nT\025\238\023X\000\000\t\218\t\166\011\246\t\230\t\200\005<\012H\000\000\000\000\000\000\000\000\000\000\011\024\004\190\000\000\000\000\000\000\t\254\t\204\0018\000*\003^\000\000\001\198\000\000\000\000\000\000\007x\000\000+\176\006|\012B\n\012\n\012\012p\n\022\nT\007\212\012N\b,\012\188\n2\n`*v\011\000\000\000\012\224\b,+\188\006|\n\234\000\000\000\000\000\000\000\000\000N\011\n\011\022\000\000\000\000(\160\r\020\n\154\np\028\176\b,\rv\n\162\n\136\rD\000\000\021h\000\000\000\000\028\140\028\212\005\156\000\000\000\000\000\000\000\000\021\216\000\000\000\000\000\000\004b\r\184\000\000\000\000\000\000\000\000\029F\024 \000\000\000\000\000\000\000\000\n\128\r\190\000\000\n\142\029\\\n\142\029z\n\142\000\000\030T\000\000\029\154\n\142\014\016\004D\014\022\000\000\000\000\029\168\n\142\030L\n\142\030b\n\142\030\160\n\142\030\178\n\142\030\240\n\142\031\006\n\142\031\020\n\142\031D\n\142\031R\n\142\031\170\n\142\031\184\n\142\031\232\n\142\031\246\n\142 \012\n\142 J\n\142 \\\n\142 \154\n\142 \176\n\142 \238\n\142\n\144\014b!\204\000N\011L\000\000\014\154%\130\000\000\014\214\000\000,8\000\000\006|\024\168\000\000\006|,:\006|\000\000\015(\000\000\000\000\000\000\015h\000\000\000\000\000\000\000\000\000\000\b,\000\000\000\000,D\000\000\006|\000\000\000\000\024\168\011R\000\000,T\006|\015p\000\000\000\000\n\252\000\000,`\006|\015\194\000\000\000\000\015\200\000\000\000\000\000\000,\244\006|\016\n\000\000\n\178\016\152\000\000\028\188\000\000\b,!\140\000\000\b,\"\n\000\000\b,\012\026\000\000\000\000\000\000\000\000\000\000\".\b,\005\022\006\028\000\000\000\000\000\000\n\142\016\218\000\000\000\000\000\000!\230\n\142\000\000\000\000\000\000\000\000\"\"\n\142\000\000\000\000\"n\n\142\000\000\000\000\"\188\n\142\000\000\000\000\000\000\"\164\000\000\000\000\"\212\n\142\000\000\000\000\"\244\n\142#V\n\142\000\000\000\000#z\n\142#\240\n\142\000\000\000\000$,\n\142\005@\016\224\000\000\000\000$B\n\142\017\"\000\000\000\000$\162\n\142$\208\n\142\000\000$\254\n\142\000\000\000\000%\b\n\142\000\000%^\n\142%\158\n\142\000\000%\188\n\142&\004\n\142\000\000&V\n\142\000\000&\\\n\142\000\000\006X\000\000\000\000\n\142\n\142\000\000&z\n\142\000\000&\170\n\142\000\000\n\238\000\000\000\000\017v\000\000\017\128\000\000\000\000\000\000\000N\011\134\000\000(\208\007\174\0048\017\190\000\000)\012\000\000\000\000\000\000)\030\000\000\000\000\017\220\000\000\018d\000\000\000\000\000\000\000\000\018\156\000\000\000\000\000\000&\184\n\142'\000\n\142\000\000\n\178\018\246\000\000\000\000\019\014\000\000\015\206\000\000\000\000\012H\000\000\000\000\000\000\0192\000\000\000\000\000\000\000\000\n\142\019j\000\000\019\128\000\000\000\000\000\000\000\000\012\020\000\000\000\000\000\000 \148\000\000\002\194\000\000\001\244\000\000\011\252\000\000\003,\000\000\000\000\000\000\000\000\000\000\000\000\011\024\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\142\000\000\012Z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\212\002\164\000*\019\206\000\000\011r\n\228\000\000\004\136\004\238\000*\003\222\001\198\006 \000*\000\000\019\228\000\000\0052\000\000\011~\n\250\011z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\178\001P\000b\000\000\000\000\000\000\026~\000\0000\006\000\000\n\252\000\000\011\006\000\000\000\000\000\000\000\000\004\216\000\000\000\000\000\000\b\232\0048\000\000\0048\002P\000\000\t@\0048\0048\011*\000\000\020\130\000\000\011.\012\128\000\000\020\192\006\182\000\000\000\000\000\000\000\000\000\000\000\000\n\142\000\000\007\222\000\000\n\142\000\000\000\000\004,\000\000\001\198\000\000\005\006\000\000\001\198\000\000\005\026\001\198\000\000\000*\000\000\0114\b\206\003B\000\000\011\206\011\210\011V\011\246\012\130\006@\001\198\006\186\000\000\011d\000\000\007t\007\204\000\000\000\000\007\130\b\006\012B\011j\000\000\b\004\b\146\012\\\000\000\000\000\006P\0024&\224\b,\020\224\000\000\bb\002\210\012\028\011l\b\222\006\"\000\000\012X\011r\r\152\000\000-\004\006|\r\n\rB\000\000\b\180\000\000\012\196\011\132\012\234\r:\002\168\000\000\000\000\000\000\000\000\000\000\011\136\t\222\000\000\011\138\n\214\000\000\006~'\130\r0\r2\011\158\r\164\011\004\000\000\011\192\r\178\011&\000\000\rP\011\194\000\000\001R\r\196\011\140\000\000\r\248\000\000\011\178\000\000\007\004\001\198\012P\000\000\001\234\000\000\000\000\000\000\007h\001\198\r\238\011\206\000\000\000\000\b\004\004\160\014\002\000\000\000\000\r\200\011\210\b\212\006\022\000\000\r\242\011\226\r\228\r:\014\000\014 \011\244\015^\000\000\0148\001\214\000\000\000\000\000\000\000\000\000j\011\248\014\020-\028\006|\000\000\000\246\011\250\014\186\000\000\000\000\000\000\000\000\000\000\000\000-@\007\014\000\000\011\252\015\b\000\000\000\000\000\000\000\000\000\000\000\000\004b\000\000-h\006|\012\132\000\000\006|\012\012\003\204\000\000\000\000\012\014\012B\014\196\000\000\004\166\026\206\000\000\006\170\000\000\000\000\000\000\000\000-\168\006|\006|\000\000\000\000\b\n\000\000\014\234\000\000\006n\b\n\b\n\000\000\012X'@\006|-\180\006|\012\202\000\000\000\000\000\000\000\000\r\n\000\000\000\000\0016\000\000\t\n\014\200\012f\015\186\014\150\000\000\000\000\006\138\t\012\014\214\000\000\000\000\012l\015\198\014\176\000\000\000\000#4\000\000\001<\000\000-\196\020\196\006|\000\000-\240\b\228\000\000.\b\000\000\000\000\000\000\000\000\000\000\b\n\000\000\000\000\r$\014\242\012p\015\230\014\194\000\000\000\000.\024\r&\015\000\000\000\000\000\000\000'\158\000\000\000\000\000\000\000\000\000\000\000\000\r8\000\000\015\016\012\170\004|\000\000\015\226\015\164\rT\0150\000\000\000\000\0156\012\178\007\014\000\000\000\000\003\024\026*\007\170\000\000\000\000\000\000\014\220\015\004\012\238\000\000\015\012\014\220\000\000\015\196\rX\015J\000\000\000\000\000\000\006|\003\140\004\248\b\174\000\000\000\000\000\000\000\000\015\018\012\252\000\000\b\204\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006|\015\000\012\254\0166\015\014\000\000#\158\000q\r\024\014\232\000c\003\006\r8\015\134\000\000\016,\021\028\000\000\000\000\021Z\000\000\r\\\000\000\000\019\000\000\000\000\000\000\000\000\000\000\000\000-\200\006|\000\000\016.\021~\000\000\000\000\021\206\000\000\002\254\r<\015\214\000\000\000\000)Z\005@\015\152\000\000.d\006|\0222\000\000\000\000\022`\000\000\000\000\rj\000\000\b\020\000\000\000\000\000\000\000\000\000\000\000\000\t\146\000\000\000\000)v\022Z\015\154\000\000.\160\006|\022\160\000\000\000\000\023\000\000\000\000\000\rB\023\006\rp\000\000\rH\rL\002`\002\130\rT\b\216\r\\\015\232\022\196\r\240\000\000\r\144\r\148\015\146\000\000\0032*\154\000\000\005\132\000\000\r\164)\196)\208\005\216\014\248\005\222\000\000\006\022\006X\000\000\003\244\000\000\000\000\003\244\000\000\000\000\003\244\015\152\000\000\007\134\003\244\015\244\023\170\r\244\000\000\003\244\000\000\000\000.\170\000\000\000\000\000\000\003\244\000\000\000\000\014(\000\000\tj\005J\014.\000\000\r\172*\190\0148\000\000\000\000\000\000\000\000\014\\\000\000\000\000\006\022\000\000\003\244.\236\000\000\n:\003\244*\000\000\000\014\138\015t\r\180\016p\015H\000\000*:\014\164\015\130\000\000\000\000\000\000\026\136\b\156\000\000\000\000\000\000\000\000\000\000\000\000\n\128\014\166\000\000\015\144\000\000\000\000\000\000\000\000\014\168'\224\000\000\000\000\000\000\000\000\n\128\000\000\000\000\014\196'\244\000\000\000\000\000\000\000\000\000\000\000*\001\198\000\000\000\000\b,\000\000/\018\006|\000\000\n>\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015F\r\216\n\158\000*\000\000\n\148\000\000\001\198\000\000\016d\000\000\000\000\000\000\000\000\000\000\b\024\000\000\000\000\000\000\000\000\000\000\000\000\016\012\001\182\015>\015\004\007\174\014J\000\000\004<\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\018\bH\014N\000\000\006<\016p\016\"\014\200\000\000\000\000\016\022\003*\007V\000\000\000\000\000\000\014P\000\000\014\\\002 \000\000\000\000\0048\005V\000\000\000\000\000\000\000\000\000\000\t>\000\000\000\000\006\198\t\016\000\000\000\000/2\006|\006|\000\000/V\006|\t\198\000\000\000\000\000\000\006|\000\000\000\000\006\176\016(\014\214\000\000\000\000\016\"\t\208\002\030\000\000\000\000\000\000\000\000\b\226\016p\006\188\0166\014\242\000\000\000\000\0160\011F\003\192\000\000\000\000\000\000\000\000\001\198\000\000\tJ\000\000\000\000\000\000\023\178\000\000\024\024\000\000\000\000\000\000\000\000\000\000\b\026\000\000\000\000\000\000*h\000\000\006|\000\000\b\194\000\000\000\000\000\000\024v\b,\000\000\000\000\003\160\015\148\007`\000\000\000\000\000\000\000\000\000\000\000\000\011\024\000\000\000\000\000\000\000\000(J\000\000\014\246\000\000\000\000\000\000\000\000\004\004\005Z\024\\\025\006\000\000\000\000\015\006\025\016\000\000\000\000\000\000\015\012\025\026\000\000\000\000\000\000\000\000"), (16, "\006\t\005v\002\003\002\004\001\007\000;\001\182\001\b\006\172\000\134\006\150\001\182\000\143\006+\001\214\000?\002G\006\n\006\183\001\214\006\012\001\229\001\007\006\t\002H\002\003\002\004\000l\000\243\006\r\006\026\001\n\001D\000\246\001\182\001\207\001\225\002V\000h\002G\006\n\006\025\001\214\006\012\001\229\0007\006*\002H\000\134\001\242\001\218\000\139\006\r\006\026\001T\001\218\000\184\000\249\006\014\000\134\002V\006\158\001\199\001\227\000\134\001\219\000\144\001\199\001\026\004\020\001\219\005\239\001\242\001U\001e\001G\001W\001X\001\218\001\229\005\198\006\014\001\208\000\140\001\007\006\176\006\015\006}\001\007\0007\002X\001\027\002\233\001\219\006\016\005z\001\012\005\242\002\003\002\004\002\007\001\243\001\012\001\007\001\233\001\240\001\b\001\242\005\200\006\015\006\031\001\n\005\244\002X\001\012\001\n\001f\006\016\001g\002\181\006;\0007\005\201\002\007\001\243\006 \006\t\005\203\002\003\002\004\001\n\005\247\006\128\006\031\006\019\000h\006\185\005\245\006\021\000s\001!\001n\002G\006\n\006\025\004\021\006\012\001\021\006 \006\023\002H\001]\002Z\003\217\002`\006\r\006\026\006\019\001\221\001\243\002f\006\021\002\\\002V\006\024\001\021\004\198\001\026\000\134\006\178\006e\001\199\006\023\001\030\001\229\002Z\001\012\002`\000\184\001\007\001\012\002h\004\250\002f\006\014\002\\\002\006\006\024\006o\001\007\001\229\001\022\003\228\003\230\003\232\001\012\002\007\001\007\000@\001\244\001\b\000:\001\242\001p\002h\006\t\001\n\002\003\002\004\001\241\001\007\001q\006\015\001[\006Q\001\230\002X\004\205\001\242\003\233\006\016\002G\006\n\006\025\001\n\006\012\002\007\001\021\004\206\002H\000\189\001\021\004\230\000\243\006\r\006\026\006\031\000\243\001\146\001.\001\229\005:\002V\0007\004\222\0009\001\021\000{\002Z\000\188\006\135\006 \000\134\001\030\001\243\000\139\002[\001\030\002\\\000\189\006\019\001\026\000\249\006\014\006\021\002\016\001\187\006N\001\242\004\225\001\243\001\012\001\030\003\150\0018\006\023\004\229\000=\002Z\004t\002`\001\012\001\007\006Y\004\227\001\b\002f\004\149\002\\\001\012\006\024\006\015\000z\001\007\006\t\002X\002\003\002\004\002\233\006\016\000\128\004\225\001\012\004\228\006{\002\007\001\012\002h\000\189\001\n\002G\006\n\006\025\000\138\006\012\006\031\004\227\001\007\002H\001\182\001\243\001\222\001\021\006\r\006\026\004v\005:\001\214\005A\005B\006 \002V\001\021\001.\001\007\004\228\003\151\001\b\003\236\006\019\001\021\000\184\002\233\006\021\006\143\006\144\001\026\003\233\001\030\005K\000~\004|\006\014\001\021\006\023\004w\006!\002Z\003\237\002`\006\145\001\n\001\182\001\218\001\183\002f\001\030\002\\\0018\006\024\001\214\006]\006^\006\t\001\012\002\003\002\004\000\129\001\219\006w\006\015\006_\006`\0007\002X\001\012\002h\006v\006\016\002G\006\n\006\025\006a\006\012\002\007\006\154\003\148\002H\001\026\000\161\005o\004v\006\r\006\026\006\031\000\134\001\218\000\168\001\199\001\012\002V\000\189\001\003\005A\005B\001\213\000\184\001\007\001.\006 \001\b\001\219\001\229\000\166\006\155\001\021\001\012\000\137\006\019\005C\005S\006\014\006\021\000\184\005K\006\029\001\021\001\180\000\189\000\134\005\198\001\186\001\199\006\023\001\n\000\170\002Z\003\185\002`\003\154\001\242\001\030\004R\0018\002f\000\159\002\\\005\198\006\024\006\015\001\021\005:\006w\002X\000\165\000\243\003\239\006\016\005\200\006m\001\029\002\233\001\182\002\007\001\212\002h\006\t\001\021\002\003\002\004\001\214\001\026\005\201\006\031\000\189\005\200\003\242\005\203\002\233\006\213\006\214\005\226\002G\006\216\003\149\005=\006\012\005\146\006 \005\201\002H\001\240\001\243\001\030\005\203\006\r\006\218\006\019\005\219\001\012\005\148\006\021\004U\002V\005q\001\182\001\218\001\237\000\243\005:\000\176\000\184\006\023\001\214\006P\002Z\006\t\002`\002\003\002\004\006\233\001\219\001\221\002f\006\014\002\\\001\182\006\024\002\019\000\173\006\225\004\025\002G\006\226\001\214\005\198\006\012\003\149\005A\005B\002H\002\233\000\171\001.\002h\006\r\006\234\006]\006^\001\218\001\021\001\025\006\015\002V\005C\005S\002X\006_\006`\005K\006\016\000\189\000\175\005\200\001\219\000\189\002\007\000\184\006a\0007\001\218\000\189\001\007\006\221\006\014\001\b\001\030\005\201\0018\002\003\002\004\000\134\005\203\005$\001\199\001\219\005\210\000\182\005\229\004\198\001\182\006 \003\195\002G\006\168\001\241\005A\005B\001\214\001\n\006\019\002H\006\015\002\233\006\021\000\181\002X\006E\000\190\004\180\006\016\002\003\002\004\005R\002V\006\023\002\007\005K\002Z\000\198\002`\000\199\006\238\006\155\004\183\002G\002f\0063\002\\\001\182\006\024\004\011\000\211\002H\001\218\001P\001\026\001\214\001\024\003}\004\205\006 \006\t\001\012\002\003\002\004\002V\002h\000\189\001\219\006\019\004\206\000\212\002\233\006\021\004\213\006Z\000\219\002G\006\n\006'\000h\006\012\002\246\001\012\006\023\002H\002X\002Z\000\189\002`\006\r\006\026\001\218\002\003\002\004\002f\002\007\002\\\002V\006\024\003\198\000\189\001\007\005\205\006[\001\b\006\t\001\219\002\003\002\004\005:\003\004\000h\001\007\006\\\003\163\002h\004\198\002X\006\014\006\225\002]\002G\006\226\001\229\004\130\006\012\001.\002\007\001\n\002H\002\233\000\189\003\217\001\021\006\r\006\229\000\189\004\185\004\180\001\007\002\003\002\004\002V\002l\003\201\001\012\006\015\002Z\003\193\002`\002X\001\242\002]\005\142\006\016\002f\001\182\002\\\004\015\001\030\002\007\0018\003>\006\014\001\214\001\026\001\182\004\205\004\018\001Z\006\031\003\231\003\230\003\232\001\214\004\022\002h\005\233\004\206\002Z\002\006\002`\004\207\002\235\003\202\006 \003?\002f\001\213\002\\\002\007\006\015\003*\001\012\006\019\002X\005A\005B\006\021\006\016\001\218\002\003\002\004\001\243\001\012\002\007\006y\000\225\002h\006\023\001\218\006\232\002Z\005J\002`\001\219\006\t\005K\002\003\002\004\002f\003;\002\\\003>\006\024\001\219\000\184\006j\002\006\003\201\006 \001\012\002G\006\n\002\003\002\004\006\012\001.\002\007\006\019\002H\002h\002Z\006\021\001\021\006\r\006#\005\202\004\185\0007\002[\005\023\002\\\002V\006\023\001\021\003>\002Z\002\233\002`\001\007\002\233\000\233\001\b\002\233\002f\003A\002\\\000\184\006\024\001\030\000\184\0018\005\205\006\014\001I\001\229\001\240\005\024\005X\005\025\006w\001\021\000\253\001\000\001\007\002h\001\n\001\b\002\006\002Z\001\007\005\198\001\006\001\b\005\198\006\132\005\193\002[\002\007\002\\\003\197\006\015\000\221\001\242\001[\002X\005\246\001 \005\026\006\016\004\137\001\n\001\182\002\234\004 \002\007\004?\001\n\001\012\005\200\001\214\002\006\005\200\001\026\000\226\006&\003A\000\134\005:\005.\001\199\002\007\005\242\005\201\005:\005\027\005\201\002\233\005\203\002\233\006 \005\203\005\207\004\198\005\028\005\204\005\029\005\244\001\026\006\019\002Z\001\012\000\229\006\021\001\026\001\243\001\218\004\198\002[\003@\002\\\005Y\006\147\000\189\006\023\006\209\002\004\002Z\006\161\002`\001\015\001\219\005\245\004\198\001\213\002f\001\012\002\\\001\151\006\024\001\241\002\233\001\012\002Z\005\031\000\189\001+\001\012\005!\005+\003\252\002[\004\"\002\\\004\205\001.\002h\001U\002\024\005U\001W\001X\001\021\000\234\0044\004\206\005Z\0012\004\205\004\212\001\182\001\007\004s\000\189\005V\005A\005B\002\233\001\214\004\206\001.\005A\005B\004\238\001T\0017\001.\001\021\001\030\001T\0018\005C\005S\001\021\004\170\004\201\005K\005C\005S\003s\002\228\002\229\005K\001U\001e\001F\001W\001X\001U\001e\005\153\001W\001X\001\030\001\218\0018\005\023\0015\001T\001\030\001\182\0018\004{\006\210\000\189\001n\003i\0013\001\214\001\219\006n\004\005\004&\002\003\002\004\001]\002\233\001U\001e\004*\001W\001X\000\184\005\024\006\187\005\025\001f\002G\001g\002#\001M\001f\003\217\001g\002#\002H\003v\003{\0017\006[\006M\006J\004R\001\012\001\218\002\233\005\198\002\233\002V\006\\\005\157\001n\001\007\0007\005\026\001\b\001n\003\201\000\189\001\219\001f\001]\001g\002#\003\201\003l\001]\001p\000\189\004'\003l\0053\003\230\003\232\005\200\001q\001\141\001[\001\182\001\n\004\129\005\027\002\003\002\004\004/\001n\001\214\001d\005\201\003\220\005\028\000\189\005\029\005\203\001\021\001]\002G\005\214\004+\003l\004\214\002X\006W\006q\002H\006\164\001\007\005Y\001\007\005\001\006\195\002\007\0007\001p\005\023\002\233\001\026\002V\001p\004R\003Y\001q\001\218\001[\002\003\002\004\001q\001L\001[\003\201\005\031\006\189\002\233\001\n\005!\005+\002]\001\219\002G\002\003\002\004\005\024\006\169\005\025\001\012\005U\002H\001p\000\189\001\138\006\197\001\007\001\007\002G\001\b\001q\0068\001[\001\229\002V\005V\002H\003\217\002Z\004\208\002`\001\229\004\003\0040\001c\002X\002f\005\026\002\\\002V\002\233\002\233\003\217\001\n\006c\002\007\001m\001\182\004\024\004\136\004J\001\242\001\129\001.\001\145\001\214\004>\002h\001\007\001\242\001\021\001\b\001\012\001\012\005\027\001\012\005G\003\230\003\232\001\157\002]\001\168\002\233\005\028\004:\005\029\001\162\002X\003\254\003\247\001\026\005O\003\230\003\232\000\184\001\n\001\030\002\007\003\227\003\183\005Y\001\218\002X\004\231\004\239\004\180\001\167\002Z\001\175\002`\001\170\001T\002\007\001\243\001\220\002f\001\219\002\\\001\012\001\012\005\156\001\243\002]\005\031\001\021\001T\001\021\005!\005+\001\192\001U\001e\001\026\001W\001X\006\175\002h\002]\005U\000\184\001\148\006\153\000\189\005\180\001U\001e\001\194\001W\001X\002Z\001\030\003\133\003\235\005V\001\132\001\007\002\233\002f\001\b\002\\\001\012\001\"\006\127\005\198\002Z\006\131\002`\004\208\004\208\001\021\001\021\000\189\002f\001f\002\\\001g\001\135\003\217\002h\001\179\001\007\001#\001\n\001\b\001\254\001\201\001\"\001f\001A\001g\001\135\005\200\001\203\002h\001\007\001\030\003\241\001\b\001n\0017\001\"\002\001\001\206\002\015\001.\005\201\001#\001\n\001]\004W\005\203\001\021\001n\001?\005\232\004\185\006\140\003\230\003\232\001\026\001#\001\n\001]\001\007\002\003\002\004\001\b\001$\001\210\001\"\006\156\006\157\001\217\003\176\003\172\002\030\001(\001\030\002G\0018\000\189\002\003\002\004\000\184\001\026\000\189\002H\001\012\001\253\001#\001\n\005K\003\253\0064\002\000\002G\001=\003\162\001\026\002V\001p\001(\000\189\002H\000\189\001\229\002\014\005\198\001q\003\182\001[\002!\001\012\002\029\001p\001(\002V\002'\002 \005\242\002\233\001\182\001q\006C\001[\002<\001\012\001\026\001T\001\214\006?\001.\002&\001\242\005\244\005\200\000\189\002A\001\021\002\003\002\004\002\152\0016\002\233\001(\0022\002/\001U\001e\005\201\001W\001X\002X\002G\005\203\001\012\001.\001\137\005\251\005\245\002\233\002H\002\007\001\021\001\030\001\218\0018\0016\006\167\002X\001.\003\179\000\189\004Z\002V\003\184\0027\001\021\000\189\002\007\001\219\0016\0026\003\190\002;\001\243\000\189\002]\002@\001\030\001f\0018\001g\001\135\003\205\003\224\004b\002\236\000\189\001.\003\226\002e\000\189\001\030\002]\0018\001\021\002\003\002\004\002\156\0016\002\233\002\191\004f\002Z\001n\002`\002\198\003\244\002\227\003\248\002G\002f\004\023\002\\\001]\002\226\002X\003N\002H\002\233\002Z\001\030\002`\0018\003\165\000\189\002\007\003V\002f\004\029\002\\\002V\002h\000\189\002\003\002\004\004$\002\003\002\004\004-\004=\001T\003\142\004B\000\189\000\189\006\156\006\157\002G\002h\000\189\002]\004M\004m\004V\004Y\002H\002\003\002\004\002\005\001U\001e\003r\001W\001X\004`\001p\005K\000\189\002V\000\189\002G\004q\000\189\001q\003\152\001[\003\174\002Z\002H\003\133\003\189\004d\004i\002X\003m\002f\003\204\002\\\004~\000\189\004\135\002V\003\213\002\007\002\003\002\004\000\189\002\233\004\140\000\189\000\189\003\243\001f\000\189\001g\002#\002h\004\145\002G\004\155\004\161\004\172\000\189\001T\000\189\000\189\002H\003\250\002]\004\187\004\209\002X\003b\002\233\002\006\000\189\004#\001n\004\028\002V\004\030\002\007\001U\001e\002\007\001W\001X\001]\002\003\002\004\004!\003h\000\189\000\189\002X\002Z\004\192\002`\0042\000\189\004u\000\189\002G\002f\002\007\002\\\002]\004\216\002\233\000\189\002H\0041\002\003\002\004\004\233\004<\003S\004\243\000\189\005\014\000\189\000\189\000\189\002V\002h\001f\004\184\001g\002+\002]\000\189\000\189\002X\002Z\002B\002`\002Z\002\003\002\004\001p\002\233\002f\002\007\002\\\002[\004A\002\\\001q\005#\001[\001n\002G\005-\002\233\002\233\004C\002Z\000\189\002`\002H\001]\004\221\002h\002\233\002f\003K\002\\\002]\000\189\004I\002\003\002\004\002V\002\003\002\004\000\189\002X\002\233\000\189\002\233\000\189\002\233\0059\002.\002G\002h\002\007\002G\002\233\005M\005]\002\233\002H\004\226\002Z\002H\002`\004H\002S\004L\002\006\002_\002f\005c\002\\\002V\005\012\005\020\002V\000\189\002\007\002]\001p\000\189\002\003\002\004\005 \002\003\002\004\005g\001q\005\131\001[\002h\005\171\002X\004N\005\231\002G\005\176\005(\002G\005?\005\215\005p\002\007\002H\005\181\002Z\002H\002`\005\147\002n\000\189\005\173\002m\002f\004X\002\\\002V\000\189\000\189\002V\004c\004_\002\233\002\153\002\233\002X\004a\002]\002X\002Z\005\211\000\189\005\187\004e\002h\002\007\004h\002[\002\007\002\\\005\195\004l\002\207\001e\005\236\001W\001X\000\189\006\001\000\189\002\233\001T\000\189\002\233\002Z\000\189\002`\000\189\002\233\002\170\002]\000\189\002f\002]\002\\\000\189\006>\002\173\004p\002X\001U\002\174\002X\001W\001X\005\184\002\233\005\218\004\132\002\007\002\003\002\004\002\007\002h\002\212\002\228\002\229\002Z\004\131\002`\002Z\000\189\002`\000\189\002G\002f\004\134\002\\\002f\002\233\002\\\000\189\002H\005\230\002]\000\189\005\234\002]\002\161\000\189\001n\005\238\002\233\002\233\002\233\002V\002h\004\139\004\141\002h\001]\002\003\002\004\006X\004\242\006d\006r\000\189\002\233\005\243\002\233\002Z\006t\002`\002Z\002G\002`\002\233\001\\\002f\004\144\002\\\002f\002H\002\\\004\147\002\232\004\151\001]\002\172\004\159\002\233\005\255\002\233\001T\004\166\002V\002\003\002\004\004\177\002h\002\233\002\170\002h\002\233\006\006\006\020\006\027\002X\004\193\002\173\002G\001p\001U\002\174\002\175\001W\001X\002\007\002H\001q\006$\001[\006i\000\189\002\195\000\189\000\189\004\210\004\241\006\149\004\234\002V\000\189\004\235\002\177\004\240\004\244\002\003\002\004\001p\002\003\002\004\002]\006\163\002\153\006\219\004\245\001\139\002X\001[\005\022\002G\005\015\006\230\002G\005\016\006\235\005\021\002\007\002H\005*\005&\002H\002\207\001e\002\202\001W\001X\002\205\002Z\005'\002`\002V\002\003\002\004\002V\005)\002f\005T\002\\\001\\\0057\0058\002]\002X\005<\005>\002G\005@\005L\001]\005\\\005^\005_\002\007\002H\005d\005h\002h\005l\005~\002\211\005\133\005\137\005\161\002\212\002\228\002\229\002V\005\182\002Z\005\188\002`\005\206\005\212\005\216\006\b\002\175\002f\002]\002\\\006\002\006\003\006\007\006\022\002X\006=\006H\002X\006S\006U\001n\006g\006h\006l\002\007\006\148\002\176\002\007\002h\006\152\001]\001p\006\162\002\003\002\004\002Z\006\166\002`\006\204\001\139\000\000\001[\000\000\002f\000\000\002\\\000\000\002G\000\000\002]\002X\000\000\002]\000\000\000\000\002H\003z\000\000\000\000\000\000\002\007\002\214\000\000\000\000\002h\000\000\002\003\002\004\002V\002\003\002\004\000\000\000\000\000\000\000\000\000\000\002Z\000\000\002`\002Z\002G\002`\001p\002G\002f\002]\002\\\002f\002H\002\\\001q\002H\001[\000\000\002\239\000\000\000\000\003\028\000\000\000\000\000\000\002V\002\003\002\004\002V\002h\000\000\000\000\002h\000\000\000\000\000\000\002Z\000\000\002`\000\000\002G\000\000\000\000\000\000\002f\002X\002\\\000\000\002H\000\000\000\000\000\000\000\000\000\000\003!\002\007\000\000\000\000\000\000\000\000\000\000\002V\000\000\000\000\000\000\002h\000\000\000\000\002\003\002\004\000\000\000\000\000\000\002\003\002\004\000\000\000\000\000\000\002X\000\000\002]\002X\002G\000\000\000\000\000\000\000\000\002G\002\007\000\000\002H\002\007\000\000\000\000\000\000\002H\003O\000\000\000\000\000\000\000\000\003Q\000\000\002V\002\003\002\004\000\000\002Z\002V\002`\000\000\000\000\000\000\002]\002X\002f\002]\002\\\002G\002\003\002\004\000\000\000\000\000\000\002\007\000\000\002H\000\000\000\000\000\000\000\000\000\000\003[\002G\000\000\000\000\002h\000\000\000\000\002V\002Z\002H\002`\002Z\000\000\002`\000\000\003d\002f\002]\002\\\002f\000\000\002\\\002V\000\000\002X\000\000\000\000\000\000\000\000\002X\000\000\000\000\000\000\000\000\002\007\000\000\000\000\002h\000\000\002\007\002h\000\000\000\000\000\000\002Z\000\000\002`\000\000\000\000\000\000\000\000\000\000\002f\000\000\002\\\002\003\002\004\000\000\000\000\002]\002X\000\000\000\000\000\000\002]\000\000\000\000\000\000\000\000\002G\002\007\000\000\000\000\002h\000\000\002X\000\000\002H\000\000\000\000\000\000\000\000\000\000\003g\001T\002\007\002Z\000\000\002`\000\000\002V\002Z\000\000\002`\002f\002]\002\\\000\000\000\000\002f\000\000\002\\\000\000\001U\001e\000\000\001W\001X\000\000\000\000\002]\000\000\000\000\000\000\000\000\002h\000\000\000\000\000\000\000\000\002h\000\000\002Z\000\000\002`\000\000\000\000\000\000\002\003\002\004\002f\000\000\002\\\000\000\000\000\000\000\000\000\002Z\000\000\002`\002\003\002\004\002G\002X\000\000\002f\001f\002\\\001g\002#\002H\002h\000\000\002\007\002G\000\000\003u\000\000\002\003\002\004\000\000\001\007\002H\002V\001\b\000\000\002h\000\000\003x\000\000\000\000\001n\002G\000\000\000\000\002V\000\000\000\000\002]\000\000\002H\001]\000\000\000\000\000\000\003k\002\003\002\004\001\n\000\000\003\130\000\000\000\000\002V\000\000\000\000\001,\002\003\002\004\000\000\002G\000\000\000\000\000\000\000\000\002Z\000\000\002`\002H\000\000\000\000\002G\000\000\002f\000\000\002\\\002X\000\000\003\135\002H\000\000\002V\000\000\000\000\000\000\001\026\002\007\000\000\002X\003\138\000\000\000\000\002V\001p\002h\000\000\002\003\002\004\002\007\000\000\000\000\001q\000\000\001[\000\000\000\000\002X\002\003\002\004\000\000\002G\002]\000\000\001\012\000\000\000\000\002\007\000\000\002H\000\000\000\000\002G\000\000\002]\003\187\000\000\000\000\000\000\000\000\002H\000\000\002V\000\000\000\000\002X\003\200\000\000\000\000\002Z\000\000\002`\002]\002V\000\000\002\007\002X\002f\000\000\002\\\000\000\002Z\000\000\002`\000\000\000\000\002\007\000\000\001.\002f\000\000\002\\\000\000\000\000\000\000\001\021\000\000\000\000\002h\002Z\002]\003\133\000\000\000\000\000\000\000\000\000\000\002f\000\000\002\\\002h\002]\000\000\000\000\000\000\002X\000\000\002\003\002\004\000\000\000\000\001\030\000\000\0014\000\000\002\007\002X\002Z\002h\003\133\000\000\002G\000\000\000\000\000\000\002f\002\007\002\\\002Z\002H\003\133\000\000\000\000\000\000\000\000\003\246\002f\000\000\002\\\002\153\002]\000\000\002V\000\000\000\000\000\000\002h\001\007\000\000\000\000\001\b\002]\000\000\0019\002\003\002\004\000\000\002h\002\207\001e\000\000\001W\001X\000\000\000\000\000\000\000\000\002Z\002G\002`\000\000\000\000\000\000\001;\001\n\002f\002H\002\\\002Z\004\196\002`\000\000\0048\000\000\002\003\002\004\002f\000\000\002\\\002V\000\000\000\000\000\000\000\000\000\000\002X\002h\000\000\002G\000\000\002\212\002\228\002\229\000\000\000\000\002\007\002H\002h\000\000\000\000\000\000\001\026\005k\000\000\000\000\002\003\002\004\000\000\000\000\002V\000\000\000\000\002\003\002\004\000\000\000\000\001n\000\000\001(\002G\002]\000\000\000\000\002\003\002\004\000\000\001]\002H\000\000\001\012\000\000\000\000\002X\005n\002D\000\000\000\000\002G\000\000\000\000\002V\000\000\002\007\000\000\000\000\002H\000\000\002Z\000\000\002`\000\000\005}\003\251\000\000\000\000\002f\000\000\002\\\002V\000\000\000\000\000\000\002X\002\003\002\004\000\000\000\000\002]\002\003\002\004\000\000\000\000\002\007\001.\000\000\000\000\002h\002G\001p\000\000\001\021\000\000\000\000\000\000\004\253\002H\001q\000\000\001[\000\000\002N\005\128\000\000\002X\002Z\000\000\002`\002]\002V\000\000\002\006\000\000\002f\002\007\002\\\000\000\001\030\000\000\0018\000\000\002\007\002X\000\000\002\003\002\004\000\000\000\000\000\000\000\000\000\000\000\000\002\007\000\000\002h\002Z\000\000\002`\002G\002]\000\000\000\000\000\000\002f\000\000\002\\\002H\002\003\002\004\000\000\000\000\001\007\005\141\000\000\001\b\000\000\000\000\002]\000\000\002V\000\000\002G\002X\000\000\002h\000\000\002Z\002\006\002`\002H\000\000\000\000\002\007\002Z\002f\005\144\002\\\002\007\001\n\002\003\002\004\002[\002V\002\\\002Z\000\000\002`\000\000\004\180\000\000\000\000\000\000\002f\002G\002\\\002h\000\000\002]\002\153\000\000\000\000\002H\000\000\005\166\000\000\000\000\000\000\005\165\000\000\000\000\000\000\000\000\002X\002h\002V\001\026\000\000\002\207\001e\000\000\001W\001X\002\007\000\000\002Z\000\000\002`\002\003\002\004\002Z\002\003\002\004\002f\000\000\002\\\002X\000\000\002[\000\000\002\\\000\000\002G\000\000\001\012\002G\002\007\000\000\002]\000\000\002H\000\000\000\000\002H\002h\000\000\005\168\000\000\000\000\005\172\002\212\002\228\002\229\002V\000\000\000\000\002V\000\000\002X\000\000\000\000\002]\002\003\002\004\000\000\002Z\000\000\002`\002\007\000\000\000\000\000\000\000\000\002f\000\000\002\\\001n\000\000\001.\000\000\000\000\000\000\000\000\000\000\003\146\001\021\001]\000\000\002Z\004\185\002`\003\155\000\000\002]\002h\000\000\002f\000\000\002\\\000\000\000\000\000\000\000\000\000\000\002\153\000\000\002X\002\003\002\004\002X\000\000\001\030\005\183\0018\003\168\000\000\002\007\002h\000\000\002\007\002Z\002G\002`\002\207\001e\000\000\001W\001X\002f\002H\002\\\000\000\000\000\000\000\000\000\006\179\000\000\000\000\001p\000\000\000\000\002]\002V\000\000\002]\000\000\001q\000\000\001[\002h\002\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\003\002\004\003\159\000\000\002\003\002\004\000\000\002\212\002\228\002\229\002Z\000\000\002`\002Z\002G\002`\000\000\000\000\002f\000\000\002\\\002f\002H\002\\\000\000\000\000\002Y\000\000\006\181\000\000\000\000\003\149\006\t\001n\000\000\002V\000\000\002X\000\000\002h\000\000\000\000\002h\001]\000\000\000\000\006\225\002\007\001T\006\226\000\000\000\000\006\012\000\000\002Z\000\000\000\000\000\000\000\000\000\000\000\000\006\r\002[\000\000\002\\\000\000\000\000\001U\001e\005\217\001W\001X\002]\000\000\000\000\000\000\000\000\000\000\000\000\001\007\000\000\000\000\001\b\000\000\000\000\000\000\000\000\000\000\002X\000\000\006\014\000\000\002\006\000\000\000\000\001p\000\000\000\000\002\007\002Z\000\000\002`\002\007\001q\000\000\001[\001\n\002f\000\000\002\\\001f\000\000\001g\006\199\006\201\000\000\002\196\006\t\006\015\000\000\000\000\000\000\006\t\002]\000\000\000\000\006\016\006\t\002h\000\000\000\000\006\225\000\000\000\000\006\226\001n\006\225\006\012\006\228\006\226\000\000\006\225\006\012\001\026\006\226\001]\006\r\006\012\000\000\000\000\002Z\006\r\002`\000\000\002Z\000\000\006\r\006\018\002f\000\000\002\\\000\000\002[\000\000\002\\\000\000\006\019\001T\000\000\000\000\006\021\001\012\000\000\000\000\000\000\006\014\000\000\000\000\000\000\002h\006\014\006\023\000\000\000\000\000\000\006\014\001U\001e\000\000\001W\001X\000\000\002\003\002\004\000\000\000\000\006\024\001p\000\000\000\000\000\000\000\000\000\000\006\015\000\000\001q\002G\001[\006\015\000\000\000\000\006\016\000\000\006\015\002H\001.\006\016\000\000\000\000\000\000\000\000\006\016\001\021\006\227\002\003\002\004\002\167\002V\006\231\001f\000\000\001g\006.\006\236\000\000\002\003\002\004\000\000\002G\000\000\000\000\000\000\006\018\000\000\000\000\000\000\002H\006\018\001\030\002G\0018\006\019\006\018\000\000\001n\006\021\006\019\002H\000\000\002V\006\021\006\019\000\000\000\000\001]\006\021\006\023\000\000\000\000\000\000\002V\006\023\001\007\001T\000\000\001\b\006\023\000\000\0019\000\000\002X\006\024\000\000\000\000\000\000\000\000\006\024\000\000\000\000\000\000\002\007\006\024\001U\001e\000\000\001W\001X\000\000\001;\001\n\000\000\000\000\001\007\000\000\000\000\001\b\000\000\000\000\001\"\000\000\006\t\000\000\002X\000\000\001\007\002]\001p\001\b\000\000\000\000\000\000\000\000\002\007\002X\001q\000\000\001[\006\n\001'\001\n\006\012\000\000\000\000\002\007\000\000\001f\001\026\001g\001\140\006\r\000\000\001\n\002Z\000\000\004\006\000\000\000\000\002]\000\000\000\000\002f\003\220\002\\\001(\001\007\000\000\000\000\001\b\002]\000\000\001n\000\000\000\000\000\000\001\012\003\223\001\026\000\000\006\014\001T\001]\002h\000\000\000\000\002Z\000\000\004\002\000\000\001\026\000\000\000\000\001\n\002f\001(\002\\\002Z\004\196\003\171\001U\001e\001T\001W\001X\002f\001\012\002\\\006\015\000\000\000\000\000\000\000\000\000\000\000\000\002h\006\016\001T\001\012\000\000\001.\001U\001e\000\000\001W\001X\002h\001\021\000\000\001T\001\026\0016\006\017\000\000\001p\000\000\001U\001e\000\000\001W\001X\000\000\001q\001f\001[\001g\001v\006\018\001U\001e\001.\001W\001X\001\030\000\000\0018\006\019\001\021\001\012\000\000\006\021\0016\001.\000\000\001f\000\000\001g\001s\001n\001\021\000\000\006\023\000\000\000\000\000\000\000\000\000\000\000\000\001]\001f\000\000\001g\001i\001\030\000\000\0018\006\024\000\000\001T\001n\000\000\001f\000\000\001g\001l\001\030\000\000\003\227\000\000\001]\001T\000\000\001.\000\000\001n\001T\000\000\001U\001e\001\021\001W\001X\000\000\004\204\001]\000\000\001n\000\000\000\000\001U\001e\000\000\001W\001X\001U\001e\001]\001W\001X\000\000\001p\000\000\000\000\000\000\000\000\001\030\000\000\0018\001q\000\000\001[\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001f\001p\001g\001o\000\000\000\000\000\000\000\000\000\000\001q\000\000\001[\001f\000\000\001g\001r\001p\001f\000\000\001g\001{\001T\000\000\000\000\001q\001n\001[\000\000\001p\000\000\000\000\000\000\002\003\002\004\000\000\001]\001q\001n\001[\000\000\001U\001e\001n\001W\001X\000\000\002G\001]\000\000\000\000\000\000\001T\001]\000\000\002H\000\000\000\000\001T\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002V\002\003\002\004\001U\001e\000\000\001W\001X\000\000\001U\001e\000\000\001W\001X\000\000\002G\001f\000\000\001g\001~\001p\000\000\000\000\002H\000\000\000\000\000\000\000\000\001q\000\000\001[\000\000\001p\000\000\000\000\000\000\002V\001p\000\000\000\000\001q\001n\001[\000\000\000\000\001q\001f\001[\001g\002=\000\000\001]\001f\002X\001g\002\217\000\000\000\000\002\003\002\004\000\000\000\000\000\000\002\007\000\000\000\000\000\000\000\000\000\000\002\003\002\004\001n\002G\000\000\000\000\000\000\000\000\001n\000\000\000\000\002H\001]\000\000\002G\002\003\002\004\000\000\001]\002]\002X\000\000\002H\000\000\002V\000\000\000\000\000\000\000\000\002G\002\007\002\003\002\004\000\000\001p\002V\000\000\002H\002\003\002\004\000\000\000\000\001q\000\000\001[\002G\002Z\000\000\003C\000\000\002V\000\000\002G\002H\002f\002]\002\\\000\000\000\000\000\000\002H\000\000\000\000\000\000\001p\000\000\002V\000\000\000\000\000\000\001p\000\000\001q\002V\001[\002h\000\000\002X\001q\000\000\001[\000\000\002Z\000\000\003B\000\000\000\000\002\007\002X\000\000\002f\000\000\002\\\000\000\000\000\000\000\000\000\000\000\002\007\000\000\000\000\000\000\000\000\002X\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002h\002]\002\007\000\000\000\000\000\000\000\000\000\000\002X\002\003\002\004\000\000\002]\002\003\002\004\002X\000\000\000\000\002\007\000\000\002\003\002\004\000\000\002G\000\000\002\007\000\000\002]\002Z\000\000\002\237\002H\000\000\000\000\002G\002g\002f\000\000\002\\\002Z\000\000\002b\002H\002]\002V\000\000\000\000\002f\000\000\002\\\002]\002\003\002\004\000\000\002Z\002V\002d\002h\000\000\000\000\002\003\002\004\002f\000\000\002\\\002G\000\000\000\000\002h\000\000\002Z\000\000\002i\002H\002G\000\000\000\000\002Z\002f\002p\002\\\000\000\002H\002h\000\000\002f\002V\002\\\000\000\000\000\000\000\002\003\002\004\000\000\000\000\002V\000\000\002X\000\000\002h\000\000\002\006\002\003\002\004\000\000\002G\002h\002\007\002X\002\003\002\004\002\007\000\000\002H\000\000\000\000\002G\000\000\002\007\000\000\000\000\000\000\000\000\002G\002H\000\000\002V\000\000\000\000\000\000\000\000\002H\002]\002\003\002\004\000\000\000\000\002V\000\000\002X\002\003\002\004\000\000\002]\002V\000\000\000\000\002G\002X\002\007\000\000\000\000\000\000\000\000\002G\002H\000\000\000\000\002\007\002Z\000\000\002r\002H\002Z\000\000\000\000\000\000\002f\002V\002\\\002Z\002[\002t\002\\\002]\002V\000\000\000\000\002f\002X\002\\\000\000\000\000\002]\002\003\002\004\000\000\000\000\002h\002\007\002X\002\003\002\004\000\000\000\000\000\000\000\000\002X\002G\002h\002\007\002Z\000\000\002v\000\000\002G\002H\002\007\000\000\002f\002Z\002\\\002x\002H\002]\002\003\002\004\000\000\002f\002V\002\\\002X\002\003\002\004\000\000\002]\002V\000\000\002X\002G\002h\002\007\002]\002\003\002\004\000\000\002G\002H\002\007\002h\000\000\002Z\000\000\002z\002H\000\000\000\000\002G\000\000\002f\002V\002\\\002Z\000\000\002|\002H\002]\002V\000\000\002Z\002f\002~\002\\\002]\002\003\002\004\000\000\002f\002V\002\\\002h\000\000\002X\002\003\002\004\000\000\000\000\000\000\002G\002X\000\000\002h\002\007\002Z\000\000\002\128\002H\002G\002h\002\007\002Z\002f\002\130\002\\\000\000\002H\000\000\000\000\002f\002V\002\\\002\003\002\004\002X\002\003\002\004\000\000\002]\002V\000\000\002X\000\000\002h\002\007\002]\002\003\002\004\000\000\002G\002h\002\007\002X\000\000\003\146\000\000\000\000\002H\000\000\000\000\002G\003\155\002\007\000\000\000\000\002Z\000\000\002\132\002H\002]\002V\000\000\002Z\002f\002\134\002\\\002]\002\003\002\004\000\000\002f\002V\002\\\002X\003\156\000\000\000\000\002]\000\000\000\000\000\000\002G\002X\002\007\002h\000\000\002Z\000\000\002\136\002H\000\000\002h\002\007\002Z\002f\002\138\002\\\000\000\000\000\000\000\000\000\002f\002V\002\\\002Z\000\000\002\140\000\000\002]\000\000\002\006\000\000\002f\002X\002\\\002h\000\000\002]\000\000\000\000\003\159\000\000\002h\002\007\002X\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002h\002\007\002Z\000\000\002\142\000\000\000\000\000\000\000\000\000\000\002f\002Z\002\\\002\144\001T\002]\003\149\000\000\000\000\002f\000\000\002\\\002X\000\000\000\000\000\000\002]\000\000\000\000\000\000\000\000\002h\002\007\001U\001e\000\000\001W\001X\000\000\002Z\002h\000\000\002Z\000\000\002\146\000\000\001T\002[\000\000\002\\\002f\000\000\002\\\002Z\002\203\002\148\000\000\002]\002\003\002\004\000\000\002f\002\206\002\\\000\000\001U\002\174\000\000\001W\001X\000\000\002h\002G\000\000\000\000\000\000\001f\001T\001g\002\220\002H\000\000\002h\000\000\002Z\000\000\002\150\000\000\002\003\002\004\000\000\000\000\002f\002V\002\\\001T\001U\001e\000\000\001W\001X\001n\002G\000\000\000\000\000\000\000\000\000\000\000\000\001T\002H\001]\000\000\002h\001U\001e\000\000\001W\001X\000\000\000\000\000\000\000\000\002V\000\000\004\001\002\003\002\004\001U\002\174\000\000\001W\001X\001\\\000\000\000\000\000\000\000\000\000\000\001f\002G\001g\002\223\001]\000\000\000\000\002X\000\000\002H\000\000\000\000\000\000\000\000\002\003\002\004\000\000\002\007\001f\000\000\001g\002\231\002V\000\000\001p\001n\002\003\002\004\000\000\000\000\000\000\002\175\001q\000\000\001[\001]\003\006\002X\002\003\002\004\002G\000\000\002]\001n\000\000\000\000\000\000\002\007\002H\000\000\000\000\000\000\002G\001]\002\003\002\004\001p\001\\\000\000\000\000\002H\002V\000\000\000\000\001\139\000\000\001[\001]\002G\002Z\000\000\002\243\002]\002V\000\000\002X\002H\002f\000\000\002\\\000\000\000\000\000\000\000\000\000\000\002\007\000\000\001p\000\000\002V\000\000\000\000\000\000\001\007\002\175\001q\004\254\001[\002h\002Z\000\000\002\249\002\006\002\003\002\004\001p\000\000\002f\000\000\002\\\002]\000\000\002\007\001q\002X\001[\000\000\002G\000\000\001p\001\n\002\003\002\004\000\000\002\007\002H\002X\001\139\002h\001[\000\000\001T\000\000\000\000\000\000\002G\002\007\002Z\002V\002\253\001T\000\000\002X\002H\000\000\002f\000\000\002\\\000\000\002]\001U\001V\002\007\001W\001X\000\000\002V\005\000\000\000\001U\002\174\002]\001W\001X\002Z\000\000\002h\000\000\000\000\000\000\000\000\000\000\002[\000\000\002\\\000\000\002Z\002]\003\001\000\000\002\003\002\004\000\000\000\000\002f\005\003\002\\\000\000\002Z\000\000\003\t\002X\000\000\000\000\002G\000\000\002f\000\000\002\\\000\000\000\000\002\007\002H\000\000\002Z\002h\003\r\000\000\000\000\002X\002\003\002\004\002f\000\000\002\\\002V\000\000\002h\001\\\002\007\000\000\002\003\002\004\000\000\002G\000\000\002]\001\\\001]\000\000\000\000\000\000\002H\002h\000\000\002G\005\006\001]\000\000\000\000\000\000\000\000\000\000\002H\002]\002V\000\000\004\206\000\000\005\011\000\000\005\b\000\000\002Z\000\000\003\015\002V\000\000\000\000\000\000\000\000\002f\001\030\002\\\005\252\000\000\000\000\000\000\002X\002\003\002\004\002Z\000\000\003\019\000\000\000\000\000\000\000\000\002\007\002f\001p\002\\\002h\002G\000\000\000\000\000\000\000\000\001\139\001p\001[\002H\002\003\002\004\000\000\000\000\000\000\001\139\002X\001[\002h\000\000\000\000\002]\002V\000\000\002G\000\000\002\007\002X\005\254\000\000\000\000\000\000\002H\002\003\002\004\000\000\000\000\002\007\002\003\002\004\000\000\000\000\000\000\000\000\000\000\002V\000\000\002G\002Z\000\000\003\021\002]\002G\000\000\000\000\002H\002f\000\000\002\\\000\000\002H\000\000\002]\000\000\000\000\000\000\000\000\000\000\002V\000\000\000\000\000\000\000\000\002V\000\000\002X\000\000\002h\002Z\000\000\003\025\002\003\002\004\000\000\000\000\002\007\002f\000\000\002\\\002Z\000\000\003\031\000\000\000\000\000\000\002G\000\000\002f\002X\002\\\001T\000\000\000\000\002H\000\000\000\000\000\000\002h\002\007\000\000\002]\000\000\000\000\002\003\002\004\000\000\002V\000\000\002h\001U\002\159\002X\001W\001X\000\000\000\000\002X\002G\002\003\002\004\000\000\002\007\000\000\002]\000\000\002H\002\007\002Z\000\000\003$\000\000\000\000\002G\000\000\000\000\002f\000\000\002\\\002V\000\000\002H\000\000\000\000\000\000\000\000\000\000\002]\000\000\000\000\000\000\002Z\002]\003&\002V\002\003\002\004\002h\000\000\002f\002X\002\\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002G\002\007\000\000\000\000\000\000\002Z\000\000\003)\002H\001\\\002Z\002h\003-\002f\000\000\002\\\000\000\000\000\002f\001]\002\\\002V\000\000\002X\000\000\000\000\002]\002\003\002\004\000\000\002\003\002\004\000\000\002\007\002h\000\000\000\000\000\000\002X\002h\000\000\002G\000\000\000\000\002G\002\003\002\004\000\000\002\007\002H\000\000\000\000\002H\002Z\000\000\0030\000\000\000\000\002]\002G\000\000\002f\002V\002\\\000\000\002V\000\000\002H\000\000\002\003\002\004\001p\000\000\002]\002X\000\000\002\003\002\004\000\000\001\139\002V\001[\002h\002G\002\007\002Z\000\000\0032\000\000\000\000\002G\002H\000\000\002f\000\000\002\\\000\000\001T\002H\000\000\002Z\000\000\0035\000\000\002V\000\000\000\000\000\000\002f\002]\002\\\002V\002\003\002\004\002h\002X\001U\001e\002X\001W\001X\000\000\000\000\000\000\000\000\002\007\002G\000\000\002\007\002h\000\000\000\000\000\000\002X\002H\000\000\002Z\000\000\0037\000\000\000\000\000\000\000\000\002\007\002f\000\000\002\\\002V\000\000\000\000\002]\001\007\000\000\002]\001\b\000\000\000\000\002X\000\000\001f\000\000\001g\0046\000\000\002X\002h\000\000\002\007\002]\000\000\000\000\000\000\000\000\000\000\002\007\005\023\000\000\002Z\001\n\003:\002Z\000\000\003=\000\000\001n\002f\000\000\002\\\002f\005\023\002\\\000\000\002]\000\000\001]\002Z\000\000\003F\000\000\002]\002X\000\000\005\024\002f\005\025\002\\\002h\000\000\000\000\002h\002\007\000\000\000\000\000\000\000\000\001\026\005\024\000\000\005\025\002Z\000\000\003I\006\t\000\000\002h\000\000\002Z\002f\003o\002\\\000\000\000\000\006\t\005\026\002f\002]\002\\\000\000\000\000\006\n\000\000\000\000\006\012\001\012\000\000\000\000\001p\005\026\002h\006\n\000\000\006\r\006\012\000\000\001q\002h\001[\000\000\000\000\000\000\005\027\006\r\002Z\000\000\003q\000\000\000\000\000\000\000\000\005\028\002f\005\029\002\\\000\000\005\027\006\t\000\000\000\000\000\000\000\000\006\014\000\000\000\000\005\028\000\000\005\029\005W\001.\000\000\000\000\006\014\002h\006\216\000\000\001\021\006\012\000\000\000\000\004\217\000\000\005\030\004\220\000\000\000\000\006\r\000\000\000\000\000\000\006\015\005\031\000\000\000\000\000\000\005!\005+\000\000\006\016\000\000\006\015\000\000\001\030\001T\0018\005\031\005U\000\000\006\016\005!\005+\000\000\000\000\000\000\006\028\006\014\000\000\000\000\000\000\000\000\005U\005V\001U\002\174\006%\001W\001X\001T\000\000\006\018\000\000\000\000\000\000\000\000\000\000\005V\000\000\000\000\006\019\006\018\000\000\000\000\006\021\006\015\000\000\000\000\001U\002\174\006\019\001W\001X\006\016\006\021\006\023\000\000\000\000\000\000\001T\000\000\000\000\000\000\000\000\000\000\006\023\006\217\000\000\001T\000\000\006\024\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001U\002\174\006\024\001W\001X\000\000\006\018\000\000\000\000\001U\002\174\000\000\001W\001X\001\\\006\019\000\000\000\000\000\000\006\021\001T\000\000\000\000\000\000\001]\000\000\000\000\000\000\000\000\000\000\006\023\000\000\000\000\000\000\001T\000\000\005\145\000\000\001\\\001U\002\174\000\000\001W\001X\000\000\006\024\000\000\000\000\001]\000\000\005\169\003\\\000\000\001U\002\174\000\000\001W\001X\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\\\000\000\003_\000\000\000\000\001T\000\000\003\\\001p\001\\\001]\001T\000\000\000\000\000\000\000\000\001\139\000\000\001[\001]\000\000\000\000\000\000\000\000\001U\002\174\003^\001W\001X\000\000\001U\002\174\001p\001W\001X\001T\000\000\003\\\000\000\001\\\001\139\000\000\001[\000\000\000\000\000\000\003\\\000\000\000\000\001]\000\000\000\000\000\000\001\\\001U\002\174\003]\001W\001X\000\000\000\000\000\000\001p\001]\001T\003a\000\000\000\000\000\000\000\000\001\139\001p\001[\000\000\000\000\000\000\002\175\000\000\000\000\001\139\000\000\001[\000\000\001U\002\174\000\000\001W\001X\000\000\000\000\002\175\000\000\001\\\001\007\001T\000\000\001\b\000\000\001\\\000\000\000\000\001p\001]\000\000\000\000\000\000\000\000\000\000\001]\001\139\000\000\001[\000\000\001U\002\174\001p\001W\001X\001\007\000\000\001\n\001\b\001\\\001\139\000\000\001[\000\000\000\000\000\000\005\196\000\000\000\000\001]\000\000\000\000\005\196\001\007\000\000\000\000\001\b\000\000\000\000\000\000\000\000\000\000\001\n\000\000\000\000\000\000\000\000\005\191\001\\\000\000\000\000\001p\006\191\000\000\001\026\000\000\005\252\001p\001]\001\139\001\n\001[\000\000\001\007\000\000\001\139\001\b\001[\000\000\000\000\000\000\005\209\001\007\000\000\000\000\001\b\000\000\005\208\001\\\001\026\000\000\001p\001\012\000\000\000\000\005\252\000\000\000\000\001]\001\139\001\n\001[\000\000\000\000\000\000\000\000\000\000\001\026\000\000\001\n\000\000\001\007\005\253\000\000\001\b\000\000\000\000\001\012\000\000\000\000\001p\001\007\000\000\000\000\001\b\003`\000\000\000\000\001\139\000\000\001[\000\000\000\000\000\000\000\000\001\012\001.\001\026\001\n\000\000\000\000\006\005\000\000\001\021\000\000\000\000\001\026\006\192\001\n\000\000\001p\001\007\000\000\000\000\001\b\000\000\000\000\000\000\001\139\000\000\001[\001.\000\000\000\000\001\007\001\012\000\000\001\b\001\021\001\030\001\007\0018\004\204\001\b\001\012\001\026\000\000\000\000\001\n\001.\000\000\000\000\000\000\000\000\000\000\001\026\001\021\000\000\000\000\000\000\004\217\001\n\000\000\005\237\001\030\000\000\0018\001\n\000\000\000\000\000\000\000\000\000\000\001\012\000\000\000\000\000\000\000\000\000\000\001.\000\000\000\000\001\030\001\012\0018\001\026\001\021\000\000\001.\000\000\006\174\000\000\000\000\000\000\000\000\001\021\000\000\000\000\001\026\001H\000\000\000\000\001\007\001\007\001\026\001\b\001\b\000\000\001\007\000\000\000\000\001\b\001\030\001\012\0018\000\000\001\007\001.\000\000\001\b\000\000\001\030\001\007\0018\001\021\001\b\001\012\001.\001\156\001\n\001\n\000\000\001\012\000\000\001\021\001\n\000\000\000\000\001\196\000\000\000\000\000\000\000\000\001\n\000\000\000\000\000\000\000\000\000\000\001\n\001\030\000\000\0018\000\000\000\000\000\000\000\000\001.\000\000\000\000\001\030\000\000\0018\000\000\001\021\000\000\001\026\001\026\001\198\000\000\001.\000\000\001\026\000\000\000\000\000\000\001.\001\021\000\000\000\000\001\026\002\026\000\000\001\021\000\000\000\000\001\026\002-\000\000\000\000\001\030\000\000\0018\000\000\001\012\001\012\001\007\000\000\000\000\001\b\001\012\000\000\000\000\001\030\001\007\0018\000\000\001\b\001\012\001\030\000\000\0018\000\000\000\000\001\012\000\000\001\007\000\000\000\000\001\b\000\000\000\000\000\000\001\n\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\n\000\000\000\000\001\007\000\000\000\000\001\b\001.\001.\000\000\000\000\000\000\001\n\001.\001\021\001\021\000\000\000\000\002\164\002\169\001\021\001.\000\000\001\007\002\186\000\000\001\b\001.\001\021\001\026\001\n\000\000\002\193\000\000\001\021\000\000\000\000\001\026\002\200\000\000\001\030\001\030\0018\0018\000\000\000\000\001\030\000\000\0018\001\026\001\n\000\000\000\000\000\000\001\030\001\007\0018\001\012\001\b\000\000\001\030\001\007\0018\000\000\001\b\001\012\000\000\001\026\000\000\001\007\000\000\001\007\004\254\000\000\001\b\000\000\000\000\001\012\000\000\000\000\000\000\000\000\001\n\000\000\000\000\000\000\000\000\001\026\001\n\000\000\000\000\001\007\000\000\000\000\004\254\001\012\001\n\000\000\001\n\000\000\000\000\001.\000\000\001\007\000\000\000\000\004\254\000\000\001\021\001.\000\000\001\007\002\209\000\000\004\254\001\012\001\021\000\000\001\n\001\026\004E\001.\000\000\000\000\000\000\001\026\000\000\000\000\001\021\000\000\001\n\000\000\004\157\005\000\001\030\001\026\0018\000\000\001\n\001.\000\000\000\000\001\030\000\000\0018\000\000\001\021\001\012\000\000\001\007\004\169\000\000\001\b\001\012\001\030\005\000\0018\000\000\000\000\001.\000\000\005\003\000\000\001\012\000\000\000\000\001\021\005\000\000\000\000\000\004\182\000\000\001\030\000\000\0018\005\000\001\n\000\000\000\000\001\007\000\000\000\000\001\b\005\003\001\007\000\000\000\000\004\254\000\000\000\000\000\000\001.\001\030\000\000\0018\005\003\000\000\001.\001\021\000\000\000\000\000\000\004\203\005\003\001\021\000\000\001\n\001.\004\219\000\000\000\000\001\n\005\006\001\026\001\021\000\000\000\000\001\007\005y\000\000\004\254\000\000\000\000\004\206\001\030\005\n\0018\005\b\000\000\000\000\001\030\000\000\0018\000\000\005\006\000\000\001\007\000\000\001\030\001\b\001\030\001\012\0018\001\026\001\n\004\206\005\006\005\t\005\000\005\b\000\000\000\000\001\007\000\000\005\006\001\b\000\000\004\206\000\000\005\007\001\030\005\b\000\000\001\n\000\000\004\206\000\000\005\019\000\000\005\b\001\007\001\012\001\030\001\b\000\000\001\007\005\003\000\000\001\b\001\n\001\030\005\000\000\000\000\000\000\000\001.\000\000\000\000\000\000\000\000\001\007\000\000\001\021\001\b\000\000\000\000\005\139\001\n\000\000\000\000\001\026\000\000\001\n\000\000\001\007\000\000\000\000\001\b\000\000\005\003\000\000\000\000\000\000\000\000\000\000\001.\001\026\001\n\001\030\000\000\0018\000\000\001\021\000\000\000\000\000\000\005\163\005\006\001\012\000\000\000\000\001\n\000\000\000\000\001\026\000\000\000\000\000\000\004\206\001\026\005\223\000\000\005\b\000\000\001\012\000\000\000\000\000\000\001\030\000\000\0018\000\000\000\000\001\030\001\026\000\000\000\000\000\000\001\007\000\000\005\006\001\b\001\012\000\000\000\000\000\000\000\000\001\012\001\026\000\000\000\000\004\206\001.\005\249\000\000\005\b\000\000\000\000\000\000\001\021\000\000\000\000\001\012\0061\000\000\001\n\001\030\000\000\001.\000\000\000\000\000\000\000\000\000\000\000\000\001\021\001\012\000\000\000\000\006\134\000\000\000\000\000\000\000\000\000\000\001\030\001.\0018\000\000\000\000\000\000\001.\000\000\001\021\000\000\000\000\000\000\006\138\001\021\000\000\000\000\001\030\001\026\0018\000\000\000\000\001.\000\000\000\000\000\000\000\000\000\000\000\000\001\021\000\000\000\000\000\000\000\000\000\000\001\030\001.\0018\000\000\000\000\001\030\000\000\001/\001\021\000\000\000\000\001\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\030\000\000\001\191\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\030\000\000\001\193\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001.\000\000\000\000\000\000\000\000\000\000\000\000\001\021\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\030\000\000\003\222"))
+  
+  and semantic_action =
+    [|
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3552 "parsing/parser.mly"
+                                                ( "+" )
+# 1293 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3553 "parsing/parser.mly"
+                                                ( "+." )
+# 1318 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.core_type) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.core_type) = 
+# 3125 "parsing/parser.mly"
+      ( _1 )
+# 1343 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = tyvar;
+          MenhirLib.EngineTypes.startp = _startpos_tyvar_;
+          MenhirLib.EngineTypes.endp = _endpos_tyvar_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = ty;
+                MenhirLib.EngineTypes.startp = _startpos_ty_;
+                MenhirLib.EngineTypes.endp = _endpos_ty_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let tyvar : (Asttypes.label) = Obj.magic tyvar in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let ty : (Parsetree.core_type) = Obj.magic ty in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_ty_ in
+        let _endpos = _endpos_tyvar_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 = 
+# 3128 "parsing/parser.mly"
+        ( Ptyp_alias(ty, tyvar) )
+# 1390 "parsing/parser.ml"
+           in
+          let (_endpos__1_, _startpos__1_) = (_endpos_tyvar_, _startpos_ty_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 1399 "parsing/parser.ml"
+          
+        in
+        
+# 3130 "parsing/parser.mly"
+    ( _1 )
+# 1405 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = body;
+            MenhirLib.EngineTypes.startp = _startpos_body_;
+            MenhirLib.EngineTypes.endp = _endpos_body_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let body : (Parsetree.pattern * Parsetree.expression) = Obj.magic body in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (let_binding) = let attrs2 =
+          let _1 = _1_inlined2 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 1453 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs2_ = _endpos__1_inlined2_ in
+        let attrs1 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 1462 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_attrs2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2405 "parsing/parser.mly"
+    (
+      let attrs = attrs1 @ attrs2 in
+      mklb ~loc:_sloc false body attrs
+    )
+# 1474 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.core_type) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.core_type) = 
+# 3186 "parsing/parser.mly"
+      ( _2 )
+# 1513 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _2;
+                  MenhirLib.EngineTypes.startp = _startpos__2_;
+                  MenhirLib.EngineTypes.endp = _endpos__2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined3 : (Parsetree.module_type) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.core_type) = let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+          let _1 =
+            let _1 = 
+# 3247 "parsing/parser.mly"
+      ( Ptyp_package (package_type_of_module_type _1) )
+# 1576 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 1584 "parsing/parser.ml"
+            
+          in
+          
+# 3248 "parsing/parser.mly"
+      ( _1 )
+# 1590 "parsing/parser.ml"
+          
+        in
+        let _3 =
+          let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+          let _2 =
+            let _1 = _1_inlined1 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 1600 "parsing/parser.ml"
+            
+          in
+          
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 1606 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3188 "parsing/parser.mly"
+      ( wrap_typ_attrs ~loc:_sloc (reloc_typ ~loc:_sloc _4) _3 )
+# 1615 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Asttypes.label) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 = 
+# 3191 "parsing/parser.mly"
+        ( Ptyp_var _2 )
+# 1648 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 1657 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 1663 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 = 
+# 3193 "parsing/parser.mly"
+        ( Ptyp_any )
+# 1689 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 1697 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 1703 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let tid =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 1734 "parsing/parser.ml"
+              
+            in
+            let tys = 
+# 3238 "parsing/parser.mly"
+      ( [] )
+# 1740 "parsing/parser.ml"
+             in
+            
+# 3196 "parsing/parser.mly"
+        ( Ptyp_constr(tid, tys) )
+# 1745 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 1754 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 1760 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = ty;
+            MenhirLib.EngineTypes.startp = _startpos_ty_;
+            MenhirLib.EngineTypes.endp = _endpos_ty_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let ty : (Parsetree.core_type) = Obj.magic ty in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_ty_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let tid =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 1798 "parsing/parser.ml"
+              
+            in
+            let tys = 
+# 3240 "parsing/parser.mly"
+      ( [ty] )
+# 1804 "parsing/parser.ml"
+             in
+            
+# 3196 "parsing/parser.mly"
+        ( Ptyp_constr(tid, tys) )
+# 1809 "parsing/parser.ml"
+            
+          in
+          let _startpos__1_ = _startpos_ty_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 1819 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 1825 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Longident.t) = Obj.magic _1_inlined1 in
+        let _3 : unit = Obj.magic _3 in
+        let xs : (Parsetree.core_type list) = Obj.magic xs in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let tid =
+              let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 1878 "parsing/parser.ml"
+              
+            in
+            let tys =
+              let tys =
+                let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 1886 "parsing/parser.ml"
+                 in
+                
+# 932 "parsing/parser.mly"
+    ( xs )
+# 1891 "parsing/parser.ml"
+                
+              in
+              
+# 3242 "parsing/parser.mly"
+      ( tys )
+# 1897 "parsing/parser.ml"
+              
+            in
+            
+# 3196 "parsing/parser.mly"
+        ( Ptyp_constr(tid, tys) )
+# 1903 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined1_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 1913 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 1919 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.object_field list * Asttypes.closed_flag) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 = 
+# 3198 "parsing/parser.mly"
+        ( let (f, c) = _2 in Ptyp_object (f, c) )
+# 1959 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 1968 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 1974 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 = 
+# 3200 "parsing/parser.mly"
+        ( Ptyp_object ([], Closed) )
+# 2007 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 2016 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 2022 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _2 : unit = Obj.magic _2 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__2_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let cid =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 2060 "parsing/parser.ml"
+              
+            in
+            let tys = 
+# 3238 "parsing/parser.mly"
+      ( [] )
+# 2066 "parsing/parser.ml"
+             in
+            
+# 3204 "parsing/parser.mly"
+        ( Ptyp_class(cid, tys) )
+# 2071 "parsing/parser.ml"
+            
+          in
+          let _startpos__1_ = _startpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 2081 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 2087 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = ty;
+              MenhirLib.EngineTypes.startp = _startpos_ty_;
+              MenhirLib.EngineTypes.endp = _endpos_ty_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _2 : unit = Obj.magic _2 in
+        let ty : (Parsetree.core_type) = Obj.magic ty in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_ty_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let cid =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 2132 "parsing/parser.ml"
+              
+            in
+            let tys = 
+# 3240 "parsing/parser.mly"
+      ( [ty] )
+# 2138 "parsing/parser.ml"
+             in
+            
+# 3204 "parsing/parser.mly"
+        ( Ptyp_class(cid, tys) )
+# 2143 "parsing/parser.ml"
+            
+          in
+          let _startpos__1_ = _startpos_ty_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 2153 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 2159 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = xs;
+                MenhirLib.EngineTypes.startp = _startpos_xs_;
+                MenhirLib.EngineTypes.endp = _endpos_xs_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Longident.t) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _3 : unit = Obj.magic _3 in
+        let xs : (Parsetree.core_type list) = Obj.magic xs in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let cid =
+              let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 2219 "parsing/parser.ml"
+              
+            in
+            let tys =
+              let tys =
+                let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 2227 "parsing/parser.ml"
+                 in
+                
+# 932 "parsing/parser.mly"
+    ( xs )
+# 2232 "parsing/parser.ml"
+                
+              in
+              
+# 3242 "parsing/parser.mly"
+      ( tys )
+# 2238 "parsing/parser.ml"
+              
+            in
+            
+# 3204 "parsing/parser.mly"
+        ( Ptyp_class(cid, tys) )
+# 2244 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined1_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 2254 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 2260 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.row_field) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 = 
+# 3207 "parsing/parser.mly"
+        ( Ptyp_variant([_2], Closed, None) )
+# 2300 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 2309 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 2315 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let xs : (Parsetree.row_field list) = Obj.magic xs in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let _3 =
+              let _1 =
+                let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 2365 "parsing/parser.ml"
+                 in
+                
+# 904 "parsing/parser.mly"
+    ( xs )
+# 2370 "parsing/parser.ml"
+                
+              in
+              
+# 3252 "parsing/parser.mly"
+    ( _1 )
+# 2376 "parsing/parser.ml"
+              
+            in
+            
+# 3209 "parsing/parser.mly"
+        ( Ptyp_variant(_3, Closed, None) )
+# 2382 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__4_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 2392 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 2398 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let xs : (Parsetree.row_field list) = Obj.magic xs in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.row_field) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let _4 =
+              let _1 =
+                let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 2455 "parsing/parser.ml"
+                 in
+                
+# 904 "parsing/parser.mly"
+    ( xs )
+# 2460 "parsing/parser.ml"
+                
+              in
+              
+# 3252 "parsing/parser.mly"
+    ( _1 )
+# 2466 "parsing/parser.ml"
+              
+            in
+            
+# 3211 "parsing/parser.mly"
+        ( Ptyp_variant(_2 :: _4, Closed, None) )
+# 2472 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 2482 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 2488 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let xs : (Parsetree.row_field list) = Obj.magic xs in
+        let _2 : (unit option) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let _3 =
+              let _1 =
+                let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 2538 "parsing/parser.ml"
+                 in
+                
+# 904 "parsing/parser.mly"
+    ( xs )
+# 2543 "parsing/parser.ml"
+                
+              in
+              
+# 3252 "parsing/parser.mly"
+    ( _1 )
+# 2549 "parsing/parser.ml"
+              
+            in
+            
+# 3213 "parsing/parser.mly"
+        ( Ptyp_variant(_3, Open, None) )
+# 2555 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__4_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 2565 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 2571 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 = 
+# 3215 "parsing/parser.mly"
+        ( Ptyp_variant([], Open, None) )
+# 2604 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 2613 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 2619 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let xs : (Parsetree.row_field list) = Obj.magic xs in
+        let _2 : (unit option) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let _3 =
+              let _1 =
+                let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 2669 "parsing/parser.ml"
+                 in
+                
+# 904 "parsing/parser.mly"
+    ( xs )
+# 2674 "parsing/parser.ml"
+                
+              in
+              
+# 3252 "parsing/parser.mly"
+    ( _1 )
+# 2680 "parsing/parser.ml"
+              
+            in
+            
+# 3217 "parsing/parser.mly"
+        ( Ptyp_variant(_3, Closed, Some []) )
+# 2686 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__4_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 2696 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 2702 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _6;
+          MenhirLib.EngineTypes.startp = _startpos__6_;
+          MenhirLib.EngineTypes.endp = _endpos__6_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos_xs_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _4;
+              MenhirLib.EngineTypes.startp = _startpos__4_;
+              MenhirLib.EngineTypes.endp = _endpos__4_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = xs;
+                MenhirLib.EngineTypes.startp = _startpos_xs_;
+                MenhirLib.EngineTypes.endp = _endpos_xs_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _2;
+                  MenhirLib.EngineTypes.startp = _startpos__2_;
+                  MenhirLib.EngineTypes.endp = _endpos__2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _6 : unit = Obj.magic _6 in
+        let xs_inlined1 : (Asttypes.label list) = Obj.magic xs_inlined1 in
+        let _4 : unit = Obj.magic _4 in
+        let xs : (Parsetree.row_field list) = Obj.magic xs in
+        let _2 : (unit option) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__6_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let _5 =
+              let xs = xs_inlined1 in
+              let _1 =
+                let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 2767 "parsing/parser.ml"
+                 in
+                
+# 872 "parsing/parser.mly"
+    ( xs )
+# 2772 "parsing/parser.ml"
+                
+              in
+              
+# 3280 "parsing/parser.mly"
+    ( _1 )
+# 2778 "parsing/parser.ml"
+              
+            in
+            let _3 =
+              let _1 =
+                let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 2786 "parsing/parser.ml"
+                 in
+                
+# 904 "parsing/parser.mly"
+    ( xs )
+# 2791 "parsing/parser.ml"
+                
+              in
+              
+# 3252 "parsing/parser.mly"
+    ( _1 )
+# 2797 "parsing/parser.ml"
+              
+            in
+            
+# 3219 "parsing/parser.mly"
+        ( Ptyp_variant(_3, Closed, Some _5) )
+# 2803 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__6_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 2813 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 2819 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.extension) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 = 
+# 3221 "parsing/parser.mly"
+        ( Ptyp_extension _1 )
+# 2845 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 2853 "parsing/parser.ml"
+          
+        in
+        
+# 3223 "parsing/parser.mly"
+  ( _1 )
+# 2859 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (string) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string Asttypes.loc) = let _1 =
+          let _1 = 
+# 3619 "parsing/parser.mly"
+                     ( _1 )
+# 2885 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 800 "parsing/parser.mly"
+    ( mkloc _1 (make_loc _sloc) )
+# 2893 "parsing/parser.ml"
+          
+        in
+        
+# 3621 "parsing/parser.mly"
+    ( _1 )
+# 2899 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (string Asttypes.loc) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (string) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (string Asttypes.loc) = let _1 =
+          let _1 = 
+# 3620 "parsing/parser.mly"
+                                 ( _1 ^ "." ^ _3.txt )
+# 2939 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 800 "parsing/parser.mly"
+    ( mkloc _1 (make_loc _sloc) )
+# 2948 "parsing/parser.ml"
+          
+        in
+        
+# 3621 "parsing/parser.mly"
+    ( _1 )
+# 2954 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.payload) = Obj.magic _3 in
+        let _2 : (string Asttypes.loc) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.attribute) = let _endpos = _endpos__4_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3625 "parsing/parser.mly"
+    ( Attr.mk ~loc:(make_loc _sloc) _2 _3 )
+# 3003 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.class_expr) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.class_expr) = 
+# 1692 "parsing/parser.mly"
+      ( _1 )
+# 3028 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.class_expr) = Obj.magic _3 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.class_expr) = let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 3069 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__3_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1694 "parsing/parser.mly"
+      ( wrap_class_attrs ~loc:_sloc _3 _2 )
+# 3078 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.class_expr) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (let_bindings) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.class_expr) = let _endpos = _endpos__3_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1696 "parsing/parser.mly"
+      ( class_of_let_bindings ~loc:_sloc _1 _3 )
+# 3120 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _2;
+                  MenhirLib.EngineTypes.startp = _startpos__2_;
+                  MenhirLib.EngineTypes.endp = _endpos__2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.class_expr) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _1_inlined2 : (Longident.t) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.class_expr) = let _5 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 3185 "parsing/parser.ml"
+          
+        in
+        let _4 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 3193 "parsing/parser.ml"
+          
+        in
+        let _endpos__4_ = _endpos__1_inlined1_ in
+        let _3 = 
+# 3544 "parsing/parser.mly"
+                                                ( Fresh )
+# 3200 "parsing/parser.ml"
+         in
+        let _endpos = _endpos__7_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1698 "parsing/parser.mly"
+      ( let loc = (_startpos__2_, _endpos__4_) in
+        let od = Opn.mk ~override:_3 ~loc:(make_loc loc) _5 in
+        mkclass ~loc:_sloc ~attrs:_4 (Pcl_open(od, _7)) )
+# 3210 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined3;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.class_expr) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _1_inlined3 : (Longident.t) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : unit = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.class_expr) = let _5 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 3282 "parsing/parser.ml"
+          
+        in
+        let _4 =
+          let _1 = _1_inlined2 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 3290 "parsing/parser.ml"
+          
+        in
+        let _endpos__4_ = _endpos__1_inlined2_ in
+        let _3 =
+          let _1 = _1_inlined1 in
+          
+# 3545 "parsing/parser.mly"
+                                                ( Override )
+# 3299 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__7_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1698 "parsing/parser.mly"
+      ( let loc = (_startpos__2_, _endpos__4_) in
+        let od = Opn.mk ~override:_3 ~loc:(make_loc loc) _5 in
+        mkclass ~loc:_sloc ~attrs:_4 (Pcl_open(od, _7)) )
+# 3310 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.attribute) = Obj.magic _2 in
+        let _1 : (Parsetree.class_expr) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.class_expr) = 
+# 1702 "parsing/parser.mly"
+      ( Cl.attr _1 _2 )
+# 3342 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : ((Asttypes.arg_label * Parsetree.expression) list) = Obj.magic xs in
+        let _1 : (Parsetree.class_expr) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.class_expr) = let _1 =
+          let _1 =
+            let _2 =
+              let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 3377 "parsing/parser.ml"
+               in
+              
+# 872 "parsing/parser.mly"
+    ( xs )
+# 3382 "parsing/parser.ml"
+              
+            in
+            
+# 1705 "parsing/parser.mly"
+        ( Pcl_apply(_1, _2) )
+# 3388 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos_xs_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 823 "parsing/parser.mly"
+    ( mkclass ~loc:_sloc _1 )
+# 3398 "parsing/parser.ml"
+          
+        in
+        
+# 1708 "parsing/parser.mly"
+      ( _1 )
+# 3404 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.extension) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.class_expr) = let _1 =
+          let _1 = 
+# 1707 "parsing/parser.mly"
+        ( Pcl_extension _1 )
+# 3430 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 823 "parsing/parser.mly"
+    ( mkclass ~loc:_sloc _1 )
+# 3438 "parsing/parser.ml"
+          
+        in
+        
+# 1708 "parsing/parser.mly"
+      ( _1 )
+# 3444 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = self;
+            MenhirLib.EngineTypes.startp = _startpos_self_;
+            MenhirLib.EngineTypes.endp = _endpos_self_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _4;
+              MenhirLib.EngineTypes.startp = _startpos__4_;
+              MenhirLib.EngineTypes.endp = _endpos__4_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let self : (string Asttypes.loc option) = Obj.magic self in
+        let _4 : (Parsetree.class_expr) = Obj.magic _4 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.class_field) = let _6 =
+          let _1 = _1_inlined2 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 3499 "parsing/parser.ml"
+          
+        in
+        let _endpos__6_ = _endpos__1_inlined2_ in
+        let _3 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 3508 "parsing/parser.ml"
+          
+        in
+        let _2 = 
+# 3544 "parsing/parser.mly"
+                                                ( Fresh )
+# 3514 "parsing/parser.ml"
+         in
+        let _endpos = _endpos__6_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1757 "parsing/parser.mly"
+      ( let docs = symbol_docs _sloc in
+        mkcf ~loc:_sloc (Pcf_inherit (_2, _4, self)) ~attrs:(_3@_6) ~docs )
+# 3523 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = self;
+            MenhirLib.EngineTypes.startp = _startpos_self_;
+            MenhirLib.EngineTypes.endp = _endpos_self_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _4;
+              MenhirLib.EngineTypes.startp = _startpos__4_;
+              MenhirLib.EngineTypes.endp = _endpos__4_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let self : (string Asttypes.loc option) = Obj.magic self in
+        let _4 : (Parsetree.class_expr) = Obj.magic _4 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : unit = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (Parsetree.class_field) = let _6 =
+          let _1 = _1_inlined3 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 3585 "parsing/parser.ml"
+          
+        in
+        let _endpos__6_ = _endpos__1_inlined3_ in
+        let _3 =
+          let _1 = _1_inlined2 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 3594 "parsing/parser.ml"
+          
+        in
+        let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3545 "parsing/parser.mly"
+                                                ( Override )
+# 3602 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__6_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1757 "parsing/parser.mly"
+      ( let docs = symbol_docs _sloc in
+        mkcf ~loc:_sloc (Pcf_inherit (_2, _4, self)) ~attrs:(_3@_6) ~docs )
+# 3612 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _2 : ((Asttypes.label Asttypes.loc * Asttypes.mutable_flag *
+   Parsetree.class_field_kind) *
+  Parsetree.attributes) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.class_field) = let _3 =
+          let _1 = _1_inlined1 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 3655 "parsing/parser.ml"
+          
+        in
+        let _endpos__3_ = _endpos__1_inlined1_ in
+        let _endpos = _endpos__3_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1760 "parsing/parser.mly"
+      ( let v, attrs = _2 in
+        let docs = symbol_docs _sloc in
+        mkcf ~loc:_sloc (Pcf_val v) ~attrs:(attrs@_3) ~docs )
+# 3667 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _2 : ((Asttypes.label Asttypes.loc * Asttypes.private_flag *
+   Parsetree.class_field_kind) *
+  Parsetree.attributes) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.class_field) = let _3 =
+          let _1 = _1_inlined1 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 3710 "parsing/parser.ml"
+          
+        in
+        let _endpos__3_ = _endpos__1_inlined1_ in
+        let _endpos = _endpos__3_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1764 "parsing/parser.mly"
+      ( let meth, attrs = _2 in
+        let docs = symbol_docs _sloc in
+        mkcf ~loc:_sloc (Pcf_method meth) ~attrs:(attrs@_3) ~docs )
+# 3722 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _3 : (Parsetree.core_type * Parsetree.core_type) = Obj.magic _3 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.class_field) = let _4 =
+          let _1 = _1_inlined2 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 3770 "parsing/parser.ml"
+          
+        in
+        let _endpos__4_ = _endpos__1_inlined2_ in
+        let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 3779 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__4_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1768 "parsing/parser.mly"
+      ( let docs = symbol_docs _sloc in
+        mkcf ~loc:_sloc (Pcf_constraint _3) ~attrs:(_2@_4) ~docs )
+# 3789 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.class_field) = let _4 =
+          let _1 = _1_inlined2 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 3837 "parsing/parser.ml"
+          
+        in
+        let _endpos__4_ = _endpos__1_inlined2_ in
+        let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 3846 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__4_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1771 "parsing/parser.mly"
+      ( let docs = symbol_docs _sloc in
+        mkcf ~loc:_sloc (Pcf_initializer _3) ~attrs:(_2@_4) ~docs )
+# 3856 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : (Parsetree.extension) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.class_field) = let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 3890 "parsing/parser.ml"
+          
+        in
+        let _endpos__2_ = _endpos__1_inlined1_ in
+        let _endpos = _endpos__2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1774 "parsing/parser.mly"
+      ( let docs = symbol_docs _sloc in
+        mkcf ~loc:_sloc (Pcf_extension _1) ~attrs:_2 ~docs )
+# 3901 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.attribute) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.class_field) = let _1 =
+          let _1 = 
+# 1777 "parsing/parser.mly"
+      ( Pcf_attribute _1 )
+# 3927 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 821 "parsing/parser.mly"
+    ( mkcf ~loc:_sloc _1 )
+# 3935 "parsing/parser.ml"
+          
+        in
+        
+# 1778 "parsing/parser.mly"
+      ( _1 )
+# 3941 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.class_expr) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.class_expr) = 
+# 1672 "parsing/parser.mly"
+      ( _2 )
+# 3973 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : (Parsetree.class_expr) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.class_type) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.class_expr) = let _1 =
+          let _1 = 
+# 1675 "parsing/parser.mly"
+        ( Pcl_constraint(_4, _2) )
+# 4020 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__4_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 823 "parsing/parser.mly"
+    ( mkclass ~loc:_sloc _1 )
+# 4029 "parsing/parser.ml"
+          
+        in
+        
+# 1678 "parsing/parser.mly"
+      ( _1 )
+# 4035 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.class_expr) = Obj.magic _2 in
+        let _1 : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.class_expr) = let _1 =
+          let _1 = 
+# 1677 "parsing/parser.mly"
+      ( let (l,o,p) = _1 in Pcl_fun(l, o, p, _2) )
+# 4068 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 823 "parsing/parser.mly"
+    ( mkclass ~loc:_sloc _1 )
+# 4077 "parsing/parser.ml"
+          
+        in
+        
+# 1678 "parsing/parser.mly"
+      ( _1 )
+# 4083 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e;
+          MenhirLib.EngineTypes.startp = _startpos_e_;
+          MenhirLib.EngineTypes.endp = _endpos_e_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e : (Parsetree.class_expr) = Obj.magic e in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_e_ in
+        let _v : (Parsetree.class_expr) = let _1 =
+          let _1 = 
+# 1733 "parsing/parser.mly"
+      ( let (l,o,p) = _1 in Pcl_fun(l, o, p, e) )
+# 4123 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos_e_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 823 "parsing/parser.mly"
+    ( mkclass ~loc:_sloc _1 )
+# 4132 "parsing/parser.ml"
+          
+        in
+        
+# 1734 "parsing/parser.mly"
+    ( _1 )
+# 4138 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e;
+          MenhirLib.EngineTypes.startp = _startpos_e_;
+          MenhirLib.EngineTypes.endp = _endpos_e_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let e : (Parsetree.class_expr) = Obj.magic e in
+        let _1 : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_e_ in
+        let _v : (Parsetree.class_expr) = let _1 =
+          let _1 = 
+# 1733 "parsing/parser.mly"
+      ( let (l,o,p) = _1 in Pcl_fun(l, o, p, e) )
+# 4171 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos_e_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 823 "parsing/parser.mly"
+    ( mkclass ~loc:_sloc _1 )
+# 4180 "parsing/parser.ml"
+          
+        in
+        
+# 1734 "parsing/parser.mly"
+    ( _1 )
+# 4186 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 4207 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Longident.t) = 
+# 3439 "parsing/parser.mly"
+                                                ( Lident _1 )
+# 4215 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 4248 "parsing/parser.ml"
+        ) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Longident.t) = 
+# 3440 "parsing/parser.mly"
+                                                ( Ldot(_1, _3) )
+# 4258 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.pattern) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _endpos = _endpos__3_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1742 "parsing/parser.mly"
+      ( reloc_pat ~loc:_sloc _2 )
+# 4300 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.core_type) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.pattern) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 = 
+# 1744 "parsing/parser.mly"
+      ( Ppat_constraint(_2, _4) )
+# 4354 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 4363 "parsing/parser.ml"
+          
+        in
+        
+# 1745 "parsing/parser.mly"
+      ( _1 )
+# 4369 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.pattern) = let _endpos = _endpos__0_ in
+        let _symbolstartpos = _endpos in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1747 "parsing/parser.mly"
+      ( ghpat ~loc:_sloc Ppat_any )
+# 4390 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.core_type) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.core_type) = 
+# 1872 "parsing/parser.mly"
+      ( _2 )
+# 4429 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 = 
+# 1873 "parsing/parser.mly"
+                      ( Ptyp_any )
+# 4448 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__0_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _endpos in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 4457 "parsing/parser.ml"
+          
+        in
+        
+# 1874 "parsing/parser.mly"
+      ( _1 )
+# 4463 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _3 : (Parsetree.class_type) = Obj.magic _3 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.class_type_field) = let _4 =
+          let _1 = _1_inlined2 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 4511 "parsing/parser.ml"
+          
+        in
+        let _endpos__4_ = _endpos__1_inlined2_ in
+        let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 4520 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__4_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1882 "parsing/parser.mly"
+      ( let docs = symbol_docs _sloc in
+        mkctf ~loc:_sloc (Pctf_inherit _3) ~attrs:(_2@_4) ~docs )
+# 4530 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = ty;
+            MenhirLib.EngineTypes.startp = _startpos_ty_;
+            MenhirLib.EngineTypes.endp = _endpos_ty_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = flags;
+                  MenhirLib.EngineTypes.startp = _startpos_flags_;
+                  MenhirLib.EngineTypes.endp = _endpos_flags_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let ty : (Parsetree.core_type) = Obj.magic ty in
+        let _3 : unit = Obj.magic _3 in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 4590 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let flags : (Asttypes.mutable_flag * Asttypes.virtual_flag) = Obj.magic flags in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (Parsetree.class_type_field) = let _4 =
+          let _1 = _1_inlined3 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 4603 "parsing/parser.ml"
+          
+        in
+        let _endpos__4_ = _endpos__1_inlined3_ in
+        let _3 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let label =
+            let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 4613 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 4621 "parsing/parser.ml"
+            
+          in
+          
+# 1907 "parsing/parser.mly"
+  (
+    let mut, virt = flags in
+    label, mut, virt, ty
+  )
+# 4630 "parsing/parser.ml"
+          
+        in
+        let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 4638 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__4_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1885 "parsing/parser.mly"
+      ( let docs = symbol_docs _sloc in
+        mkctf ~loc:_sloc (Pctf_val _3) ~attrs:(_2@_4) ~docs )
+# 4648 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined4;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined4_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined4 : (Parsetree.attributes) = Obj.magic _1_inlined4 in
+        let _1_inlined3 : (Parsetree.core_type) = Obj.magic _1_inlined3 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 4708 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _3 : (Asttypes.private_flag * Asttypes.virtual_flag) = Obj.magic _3 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined4_ in
+        let _v : (Parsetree.class_type_field) = let _7 =
+          let _1 = _1_inlined4 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 4721 "parsing/parser.ml"
+          
+        in
+        let _endpos__7_ = _endpos__1_inlined4_ in
+        let _6 =
+          let _1 = _1_inlined3 in
+          
+# 3091 "parsing/parser.mly"
+    ( _1 )
+# 4730 "parsing/parser.ml"
+          
+        in
+        let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 4738 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 4746 "parsing/parser.ml"
+          
+        in
+        let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 4754 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__7_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1889 "parsing/parser.mly"
+      ( let (p, v) = _3 in
+        let docs = symbol_docs _sloc in
+        mkctf ~loc:_sloc (Pctf_method (_4, p, v, _6)) ~attrs:(_2@_7) ~docs )
+# 4765 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _3 : (Parsetree.core_type * Parsetree.core_type) = Obj.magic _3 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.class_type_field) = let _4 =
+          let _1 = _1_inlined2 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 4813 "parsing/parser.ml"
+          
+        in
+        let _endpos__4_ = _endpos__1_inlined2_ in
+        let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 4822 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__4_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1893 "parsing/parser.mly"
+      ( let docs = symbol_docs _sloc in
+        mkctf ~loc:_sloc (Pctf_constraint _3) ~attrs:(_2@_4) ~docs )
+# 4832 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : (Parsetree.extension) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.class_type_field) = let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 4866 "parsing/parser.ml"
+          
+        in
+        let _endpos__2_ = _endpos__1_inlined1_ in
+        let _endpos = _endpos__2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1896 "parsing/parser.mly"
+      ( let docs = symbol_docs _sloc in
+        mkctf ~loc:_sloc (Pctf_extension _1) ~attrs:_2 ~docs )
+# 4877 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.attribute) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.class_type_field) = let _1 =
+          let _1 = 
+# 1899 "parsing/parser.mly"
+      ( Pctf_attribute _1 )
+# 4903 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 819 "parsing/parser.mly"
+    ( mkctf ~loc:_sloc _1 )
+# 4911 "parsing/parser.ml"
+          
+        in
+        
+# 1900 "parsing/parser.mly"
+      ( _1 )
+# 4917 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.class_type) = let _1 =
+          let _1 =
+            let cid =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 4948 "parsing/parser.ml"
+              
+            in
+            let tys =
+              let tys = 
+# 1858 "parsing/parser.mly"
+      ( [] )
+# 4955 "parsing/parser.ml"
+               in
+              
+# 1864 "parsing/parser.mly"
+    ( tys )
+# 4960 "parsing/parser.ml"
+              
+            in
+            
+# 1841 "parsing/parser.mly"
+        ( Pcty_constr (cid, tys) )
+# 4966 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 817 "parsing/parser.mly"
+    ( mkcty ~loc:_sloc _1 )
+# 4975 "parsing/parser.ml"
+          
+        in
+        
+# 1844 "parsing/parser.mly"
+      ( _1 )
+# 4981 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Longident.t) = Obj.magic _1_inlined1 in
+        let _3 : unit = Obj.magic _3 in
+        let xs : (Parsetree.core_type list) = Obj.magic xs in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.class_type) = let _1 =
+          let _1 =
+            let cid =
+              let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 5034 "parsing/parser.ml"
+              
+            in
+            let tys =
+              let tys =
+                let params =
+                  let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 5043 "parsing/parser.ml"
+                   in
+                  
+# 904 "parsing/parser.mly"
+    ( xs )
+# 5048 "parsing/parser.ml"
+                  
+                in
+                
+# 1860 "parsing/parser.mly"
+      ( params )
+# 5054 "parsing/parser.ml"
+                
+              in
+              
+# 1864 "parsing/parser.mly"
+    ( tys )
+# 5060 "parsing/parser.ml"
+              
+            in
+            
+# 1841 "parsing/parser.mly"
+        ( Pcty_constr (cid, tys) )
+# 5066 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined1_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 817 "parsing/parser.mly"
+    ( mkcty ~loc:_sloc _1 )
+# 5076 "parsing/parser.ml"
+          
+        in
+        
+# 1844 "parsing/parser.mly"
+      ( _1 )
+# 5082 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.extension) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.class_type) = let _1 =
+          let _1 = 
+# 1843 "parsing/parser.mly"
+        ( Pcty_extension _1 )
+# 5108 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 817 "parsing/parser.mly"
+    ( mkcty ~loc:_sloc _1 )
+# 5116 "parsing/parser.ml"
+          
+        in
+        
+# 1844 "parsing/parser.mly"
+      ( _1 )
+# 5122 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xss;
+            MenhirLib.EngineTypes.startp = _startpos_xss_;
+            MenhirLib.EngineTypes.endp = _endpos_xss_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let xss : (Parsetree.class_type_field list list) = Obj.magic xss in
+        let _1_inlined2 : (Parsetree.core_type) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.class_type) = let _3 =
+          let _1 = _1_inlined2 in
+          let _2 =
+            let _1 =
+              let _1 = 
+# 260 "menhir/standard.mly"
+    ( List.flatten xss )
+# 5179 "parsing/parser.ml"
+               in
+              
+# 1878 "parsing/parser.mly"
+    ( _1 )
+# 5184 "parsing/parser.ml"
+              
+            in
+            let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in
+            let _endpos = _endpos__1_ in
+            let _startpos = _startpos__1_ in
+            
+# 765 "parsing/parser.mly"
+                               ( extra_csig _startpos _endpos _1 )
+# 5193 "parsing/parser.ml"
+            
+          in
+          
+# 1868 "parsing/parser.mly"
+      ( Csig.mk _1 _2 )
+# 5199 "parsing/parser.ml"
+          
+        in
+        let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 5207 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__4_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1846 "parsing/parser.mly"
+      ( mkcty ~loc:_sloc ~attrs:_2 (Pcty_signature _3) )
+# 5216 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xss;
+            MenhirLib.EngineTypes.startp = _startpos_xss_;
+            MenhirLib.EngineTypes.endp = _endpos_xss_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let xss : (Parsetree.class_type_field list list) = Obj.magic xss in
+        let _1_inlined2 : (Parsetree.core_type) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.class_type) = let _3 =
+          let _1 = _1_inlined2 in
+          let _2 =
+            let _1 =
+              let _1 = 
+# 260 "menhir/standard.mly"
+    ( List.flatten xss )
+# 5273 "parsing/parser.ml"
+               in
+              
+# 1878 "parsing/parser.mly"
+    ( _1 )
+# 5278 "parsing/parser.ml"
+              
+            in
+            let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in
+            let _endpos = _endpos__1_ in
+            let _startpos = _startpos__1_ in
+            
+# 765 "parsing/parser.mly"
+                               ( extra_csig _startpos _endpos _1 )
+# 5287 "parsing/parser.ml"
+            
+          in
+          
+# 1868 "parsing/parser.mly"
+      ( Csig.mk _1 _2 )
+# 5293 "parsing/parser.ml"
+          
+        in
+        let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 5301 "parsing/parser.ml"
+          
+        in
+        let _loc__4_ = (_startpos__4_, _endpos__4_) in
+        let _loc__1_ = (_startpos__1_, _endpos__1_) in
+        
+# 1848 "parsing/parser.mly"
+      ( unclosed "object" _loc__1_ "end" _loc__4_ )
+# 5309 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.attribute) = Obj.magic _2 in
+        let _1 : (Parsetree.class_type) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.class_type) = 
+# 1850 "parsing/parser.mly"
+      ( Cty.attr _1 _2 )
+# 5341 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _2;
+                  MenhirLib.EngineTypes.startp = _startpos__2_;
+                  MenhirLib.EngineTypes.endp = _endpos__2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.class_type) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _1_inlined2 : (Longident.t) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.class_type) = let _5 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 5406 "parsing/parser.ml"
+          
+        in
+        let _4 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 5414 "parsing/parser.ml"
+          
+        in
+        let _endpos__4_ = _endpos__1_inlined1_ in
+        let _3 = 
+# 3544 "parsing/parser.mly"
+                                                ( Fresh )
+# 5421 "parsing/parser.ml"
+         in
+        let _endpos = _endpos__7_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1852 "parsing/parser.mly"
+      ( let loc = (_startpos__2_, _endpos__4_) in
+        let od = Opn.mk ~override:_3 ~loc:(make_loc loc) _5 in
+        mkcty ~loc:_sloc ~attrs:_4 (Pcty_open(od, _7)) )
+# 5431 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined3;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.class_type) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _1_inlined3 : (Longident.t) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : unit = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.class_type) = let _5 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 5503 "parsing/parser.ml"
+          
+        in
+        let _4 =
+          let _1 = _1_inlined2 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 5511 "parsing/parser.ml"
+          
+        in
+        let _endpos__4_ = _endpos__1_inlined2_ in
+        let _3 =
+          let _1 = _1_inlined1 in
+          
+# 3545 "parsing/parser.mly"
+                                                ( Override )
+# 5520 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__7_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1852 "parsing/parser.mly"
+      ( let loc = (_startpos__2_, _endpos__4_) in
+        let od = Opn.mk ~override:_3 ~loc:(make_loc loc) _5 in
+        mkcty ~loc:_sloc ~attrs:_4 (Pcty_open(od, _7)) )
+# 5531 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.class_expr) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.class_expr) = 
+# 1712 "parsing/parser.mly"
+      ( _2 )
+# 5570 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.class_expr) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.class_expr) = let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        let _loc__1_ = (_startpos__1_, _endpos__1_) in
+        
+# 1714 "parsing/parser.mly"
+      ( unclosed "(" _loc__1_ ")" _loc__3_ )
+# 5611 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.class_expr) = let _1 =
+          let _1 =
+            let cid =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 5642 "parsing/parser.ml"
+              
+            in
+            let tys =
+              let tys = 
+# 1858 "parsing/parser.mly"
+      ( [] )
+# 5649 "parsing/parser.ml"
+               in
+              
+# 1864 "parsing/parser.mly"
+    ( tys )
+# 5654 "parsing/parser.ml"
+              
+            in
+            
+# 1717 "parsing/parser.mly"
+        ( Pcl_constr(cid, tys) )
+# 5660 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 823 "parsing/parser.mly"
+    ( mkclass ~loc:_sloc _1 )
+# 5669 "parsing/parser.ml"
+          
+        in
+        
+# 1724 "parsing/parser.mly"
+      ( _1 )
+# 5675 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Longident.t) = Obj.magic _1_inlined1 in
+        let _3 : unit = Obj.magic _3 in
+        let xs : (Parsetree.core_type list) = Obj.magic xs in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.class_expr) = let _1 =
+          let _1 =
+            let cid =
+              let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 5728 "parsing/parser.ml"
+              
+            in
+            let tys =
+              let tys =
+                let params =
+                  let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 5737 "parsing/parser.ml"
+                   in
+                  
+# 904 "parsing/parser.mly"
+    ( xs )
+# 5742 "parsing/parser.ml"
+                  
+                in
+                
+# 1860 "parsing/parser.mly"
+      ( params )
+# 5748 "parsing/parser.ml"
+                
+              in
+              
+# 1864 "parsing/parser.mly"
+    ( tys )
+# 5754 "parsing/parser.ml"
+              
+            in
+            
+# 1717 "parsing/parser.mly"
+        ( Pcl_constr(cid, tys) )
+# 5760 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined1_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 823 "parsing/parser.mly"
+    ( mkclass ~loc:_sloc _1 )
+# 5770 "parsing/parser.ml"
+          
+        in
+        
+# 1724 "parsing/parser.mly"
+      ( _1 )
+# 5776 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xss;
+            MenhirLib.EngineTypes.startp = _startpos_xss_;
+            MenhirLib.EngineTypes.endp = _endpos_xss_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let xss : (Parsetree.class_field list list) = Obj.magic xss in
+        let _1_inlined2 : (Parsetree.pattern) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.class_expr) = let _1 =
+          let _1 =
+            let _3 =
+              let _1 = _1_inlined2 in
+              let _2 =
+                let _1 =
+                  let _1 = 
+# 260 "menhir/standard.mly"
+    ( List.flatten xss )
+# 5835 "parsing/parser.ml"
+                   in
+                  
+# 1751 "parsing/parser.mly"
+    ( _1 )
+# 5840 "parsing/parser.ml"
+                  
+                in
+                let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in
+                let _endpos = _endpos__1_ in
+                let _startpos = _startpos__1_ in
+                
+# 764 "parsing/parser.mly"
+                               ( extra_cstr _startpos _endpos _1 )
+# 5849 "parsing/parser.ml"
+                
+              in
+              
+# 1738 "parsing/parser.mly"
+       ( Cstr.mk _1 _2 )
+# 5855 "parsing/parser.ml"
+              
+            in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 5863 "parsing/parser.ml"
+              
+            in
+            let _loc__4_ = (_startpos__4_, _endpos__4_) in
+            let _loc__1_ = (_startpos__1_, _endpos__1_) in
+            
+# 1719 "parsing/parser.mly"
+        ( unclosed "object" _loc__1_ "end" _loc__4_ )
+# 5871 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__4_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 823 "parsing/parser.mly"
+    ( mkclass ~loc:_sloc _1 )
+# 5881 "parsing/parser.ml"
+          
+        in
+        
+# 1724 "parsing/parser.mly"
+      ( _1 )
+# 5887 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.class_type) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.class_expr) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.class_expr) = let _1 =
+          let _1 = 
+# 1721 "parsing/parser.mly"
+        ( Pcl_constraint(_2, _4) )
+# 5941 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 823 "parsing/parser.mly"
+    ( mkclass ~loc:_sloc _1 )
+# 5950 "parsing/parser.ml"
+          
+        in
+        
+# 1724 "parsing/parser.mly"
+      ( _1 )
+# 5956 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.class_type) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.class_expr) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.class_expr) = let _1 =
+          let _1 =
+            let _loc__5_ = (_startpos__5_, _endpos__5_) in
+            let _loc__1_ = (_startpos__1_, _endpos__1_) in
+            
+# 1723 "parsing/parser.mly"
+        ( unclosed "(" _loc__1_ ")" _loc__5_ )
+# 6013 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 823 "parsing/parser.mly"
+    ( mkclass ~loc:_sloc _1 )
+# 6023 "parsing/parser.ml"
+          
+        in
+        
+# 1724 "parsing/parser.mly"
+      ( _1 )
+# 6029 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xss;
+            MenhirLib.EngineTypes.startp = _startpos_xss_;
+            MenhirLib.EngineTypes.endp = _endpos_xss_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let xss : (Parsetree.class_field list list) = Obj.magic xss in
+        let _1_inlined2 : (Parsetree.pattern) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.class_expr) = let _3 =
+          let _1 = _1_inlined2 in
+          let _2 =
+            let _1 =
+              let _1 = 
+# 260 "menhir/standard.mly"
+    ( List.flatten xss )
+# 6086 "parsing/parser.ml"
+               in
+              
+# 1751 "parsing/parser.mly"
+    ( _1 )
+# 6091 "parsing/parser.ml"
+              
+            in
+            let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in
+            let _endpos = _endpos__1_ in
+            let _startpos = _startpos__1_ in
+            
+# 764 "parsing/parser.mly"
+                               ( extra_cstr _startpos _endpos _1 )
+# 6100 "parsing/parser.ml"
+            
+          in
+          
+# 1738 "parsing/parser.mly"
+       ( Cstr.mk _1 _2 )
+# 6106 "parsing/parser.ml"
+          
+        in
+        let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 6114 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__4_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1726 "parsing/parser.mly"
+    ( mkclass ~loc:_sloc ~attrs:_2 (Pcl_structure _3) )
+# 6123 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.class_type) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.class_type) = 
+# 1829 "parsing/parser.mly"
+      ( _1 )
+# 6148 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = codomain;
+          MenhirLib.EngineTypes.startp = _startpos_codomain_;
+          MenhirLib.EngineTypes.endp = _endpos_codomain_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = domain;
+              MenhirLib.EngineTypes.startp = _startpos_domain_;
+              MenhirLib.EngineTypes.endp = _endpos_domain_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = label;
+                MenhirLib.EngineTypes.startp = _startpos_label_;
+                MenhirLib.EngineTypes.endp = _endpos_label_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let codomain : (Parsetree.class_type) = Obj.magic codomain in
+        let _3 : unit = Obj.magic _3 in
+        let domain : (Parsetree.core_type) = Obj.magic domain in
+        let label : (string) = Obj.magic label in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_label_ in
+        let _endpos = _endpos_codomain_ in
+        let _v : (Parsetree.class_type) = let _1 =
+          let _1 =
+            let label = 
+# 3154 "parsing/parser.mly"
+      ( Optional label )
+# 6196 "parsing/parser.ml"
+             in
+            
+# 1835 "parsing/parser.mly"
+        ( Pcty_arrow(label, domain, codomain) )
+# 6201 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_codomain_, _startpos_label_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 817 "parsing/parser.mly"
+    ( mkcty ~loc:_sloc _1 )
+# 6211 "parsing/parser.ml"
+          
+        in
+        
+# 1836 "parsing/parser.mly"
+      ( _1 )
+# 6217 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = codomain;
+          MenhirLib.EngineTypes.startp = _startpos_codomain_;
+          MenhirLib.EngineTypes.endp = _endpos_codomain_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = domain;
+              MenhirLib.EngineTypes.startp = _startpos_domain_;
+              MenhirLib.EngineTypes.endp = _endpos_domain_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = label;
+                  MenhirLib.EngineTypes.startp = _startpos_label_;
+                  MenhirLib.EngineTypes.endp = _endpos_label_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let codomain : (Parsetree.class_type) = Obj.magic codomain in
+        let _3 : unit = Obj.magic _3 in
+        let domain : (Parsetree.core_type) = Obj.magic domain in
+        let _2 : unit = Obj.magic _2 in
+        let label : (
+# 620 "parsing/parser.mly"
+       (string)
+# 6266 "parsing/parser.ml"
+        ) = Obj.magic label in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_label_ in
+        let _endpos = _endpos_codomain_ in
+        let _v : (Parsetree.class_type) = let _1 =
+          let _1 =
+            let label = 
+# 3156 "parsing/parser.mly"
+      ( Labelled label )
+# 6276 "parsing/parser.ml"
+             in
+            
+# 1835 "parsing/parser.mly"
+        ( Pcty_arrow(label, domain, codomain) )
+# 6281 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_codomain_, _startpos_label_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 817 "parsing/parser.mly"
+    ( mkcty ~loc:_sloc _1 )
+# 6291 "parsing/parser.ml"
+          
+        in
+        
+# 1836 "parsing/parser.mly"
+      ( _1 )
+# 6297 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = codomain;
+          MenhirLib.EngineTypes.startp = _startpos_codomain_;
+          MenhirLib.EngineTypes.endp = _endpos_codomain_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = domain;
+              MenhirLib.EngineTypes.startp = _startpos_domain_;
+              MenhirLib.EngineTypes.endp = _endpos_domain_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let codomain : (Parsetree.class_type) = Obj.magic codomain in
+        let _3 : unit = Obj.magic _3 in
+        let domain : (Parsetree.core_type) = Obj.magic domain in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_domain_ in
+        let _endpos = _endpos_codomain_ in
+        let _v : (Parsetree.class_type) = let _1 =
+          let _1 =
+            let label = 
+# 3158 "parsing/parser.mly"
+      ( Nolabel )
+# 6338 "parsing/parser.ml"
+             in
+            
+# 1835 "parsing/parser.mly"
+        ( Pcty_arrow(label, domain, codomain) )
+# 6343 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_codomain_, _startpos_domain_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 817 "parsing/parser.mly"
+    ( mkcty ~loc:_sloc _1 )
+# 6353 "parsing/parser.ml"
+          
+        in
+        
+# 1836 "parsing/parser.mly"
+      ( _1 )
+# 6359 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = bs;
+          MenhirLib.EngineTypes.startp = _startpos_bs_;
+          MenhirLib.EngineTypes.endp = _endpos_bs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = csig;
+              MenhirLib.EngineTypes.startp = _startpos_csig_;
+              MenhirLib.EngineTypes.endp = _endpos_csig_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _8;
+                MenhirLib.EngineTypes.startp = _startpos__8_;
+                MenhirLib.EngineTypes.endp = _endpos__8_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = params;
+                    MenhirLib.EngineTypes.startp = _startpos_params_;
+                    MenhirLib.EngineTypes.endp = _endpos_params_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = virt;
+                      MenhirLib.EngineTypes.startp = _startpos_virt_;
+                      MenhirLib.EngineTypes.endp = _endpos_virt_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _1_inlined1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _;
+                          MenhirLib.EngineTypes.semv = ext;
+                          MenhirLib.EngineTypes.startp = _startpos_ext_;
+                          MenhirLib.EngineTypes.endp = _endpos_ext_;
+                          MenhirLib.EngineTypes.next = {
+                            MenhirLib.EngineTypes.state = _;
+                            MenhirLib.EngineTypes.semv = _2;
+                            MenhirLib.EngineTypes.startp = _startpos__2_;
+                            MenhirLib.EngineTypes.endp = _endpos__2_;
+                            MenhirLib.EngineTypes.next = {
+                              MenhirLib.EngineTypes.state = _menhir_s;
+                              MenhirLib.EngineTypes.semv = _1;
+                              MenhirLib.EngineTypes.startp = _startpos__1_;
+                              MenhirLib.EngineTypes.endp = _endpos__1_;
+                              MenhirLib.EngineTypes.next = _menhir_stack;
+                            };
+                          };
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let bs : (Parsetree.class_type_declaration list) = Obj.magic bs in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let csig : (Parsetree.class_type) = Obj.magic csig in
+        let _8 : unit = Obj.magic _8 in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 6444 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let virt : (Asttypes.virtual_flag) = Obj.magic virt in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_bs_ in
+        let _v : (string Asttypes.loc option * Parsetree.class_type_declaration list) = let _1 =
+          let a =
+            let attrs2 =
+              let _1 = _1_inlined3 in
+              
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 6462 "parsing/parser.ml"
+              
+            in
+            let _endpos_attrs2_ = _endpos__1_inlined3_ in
+            let id =
+              let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 6474 "parsing/parser.ml"
+              
+            in
+            let attrs1 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 6482 "parsing/parser.ml"
+              
+            in
+            let _endpos = _endpos_attrs2_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 1974 "parsing/parser.mly"
+    (
+      let attrs = attrs1 @ attrs2 in
+      let loc = make_loc _sloc in
+      let docs = symbol_docs _sloc in
+      ext,
+      Ci.mk id csig ~virt ~params ~attrs ~loc ~docs
+    )
+# 6497 "parsing/parser.ml"
+            
+          in
+          
+# 1001 "parsing/parser.mly"
+    ( let (x, b) = a in x, b :: bs )
+# 6503 "parsing/parser.ml"
+          
+        in
+        
+# 1962 "parsing/parser.mly"
+    ( _1 )
+# 6509 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 6530 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Longident.t) = 
+# 3435 "parsing/parser.mly"
+                                                ( Lident _1 )
+# 6538 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 6571 "parsing/parser.ml"
+        ) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Longident.t) = 
+# 3436 "parsing/parser.mly"
+                                                ( Ldot(_1, _3) )
+# 6581 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 606 "parsing/parser.mly"
+       (string * char option)
+# 6602 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.constant) = 
+# 3326 "parsing/parser.mly"
+                 ( let (n, m) = _1 in Pconst_integer (n, m) )
+# 6610 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 565 "parsing/parser.mly"
+       (char)
+# 6631 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.constant) = 
+# 3327 "parsing/parser.mly"
+                 ( Pconst_char _1 )
+# 6639 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 658 "parsing/parser.mly"
+       (string * string option)
+# 6660 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.constant) = 
+# 3328 "parsing/parser.mly"
+                 ( let (s, d) = _1 in Pconst_string (s, d) )
+# 6668 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 585 "parsing/parser.mly"
+       (string * char option)
+# 6689 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.constant) = 
+# 3329 "parsing/parser.mly"
+                 ( let (f, m) = _1 in Pconst_float (f, m) )
+# 6697 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 6718 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3389 "parsing/parser.mly"
+                                                ( _1 )
+# 6726 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (string) = 
+# 3390 "parsing/parser.mly"
+                                                ( "[]" )
+# 6758 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (string) = 
+# 3391 "parsing/parser.mly"
+                                                ( "()" )
+# 6790 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (string) = 
+# 3392 "parsing/parser.mly"
+                                                ( "::" )
+# 6829 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3393 "parsing/parser.mly"
+                                                ( "false" )
+# 6854 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3394 "parsing/parser.mly"
+                                                ( "true" )
+# 6879 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Longident.t) = 
+# 3402 "parsing/parser.mly"
+                                                ( _1 )
+# 6904 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Longident.t) = 
+# 3403 "parsing/parser.mly"
+                                                ( Ldot(_1,"::") )
+# 6957 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Longident.t) = 
+# 3404 "parsing/parser.mly"
+                                                ( Lident "[]" )
+# 6989 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Longident.t) = 
+# 3405 "parsing/parser.mly"
+                                                ( Lident "()" )
+# 7021 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Longident.t) = 
+# 3406 "parsing/parser.mly"
+                                                ( Lident "::" )
+# 7060 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Longident.t) = 
+# 3407 "parsing/parser.mly"
+                                                ( Lident "false" )
+# 7085 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Longident.t) = 
+# 3408 "parsing/parser.mly"
+                                                ( Lident "true" )
+# 7110 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.core_type) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.core_type) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.core_type * Parsetree.core_type) = 
+# 1918 "parsing/parser.mly"
+    ( _1, _3 )
+# 7149 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : (Parsetree.core_type) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.constructor_arguments) = let tys =
+          let xs =
+            let xs = 
+# 888 "parsing/parser.mly"
+    ( [ x ] )
+# 7176 "parsing/parser.ml"
+             in
+            
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 7181 "parsing/parser.ml"
+            
+          in
+          
+# 908 "parsing/parser.mly"
+    ( xs )
+# 7187 "parsing/parser.ml"
+          
+        in
+        
+# 2961 "parsing/parser.mly"
+      ( Pcstr_tuple tys )
+# 7193 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.core_type) = Obj.magic x in
+        let _2 : unit = Obj.magic _2 in
+        let xs : (Parsetree.core_type list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.constructor_arguments) = let tys =
+          let xs =
+            let xs = 
+# 892 "parsing/parser.mly"
+    ( x :: xs )
+# 7234 "parsing/parser.ml"
+             in
+            
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 7239 "parsing/parser.ml"
+            
+          in
+          
+# 908 "parsing/parser.mly"
+    ( xs )
+# 7245 "parsing/parser.ml"
+          
+        in
+        
+# 2961 "parsing/parser.mly"
+      ( Pcstr_tuple tys )
+# 7251 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.label_declaration list) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.constructor_arguments) = 
+# 2963 "parsing/parser.mly"
+      ( Pcstr_record _2 )
+# 7290 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.constructor_declaration list) = 
+# 2882 "parsing/parser.mly"
+      ( [] )
+# 7315 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let xs : (Parsetree.constructor_declaration list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.constructor_declaration list) = let cs = 
+# 993 "parsing/parser.mly"
+    ( List.rev xs )
+# 7340 "parsing/parser.ml"
+         in
+        
+# 2884 "parsing/parser.mly"
+      ( cs )
+# 7345 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.core_type) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.core_type) = let _1 = 
+# 3116 "parsing/parser.mly"
+    ( _1 )
+# 7370 "parsing/parser.ml"
+         in
+        
+# 3106 "parsing/parser.mly"
+      ( _1 )
+# 7375 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.attribute) = Obj.magic _2 in
+        let _1 : (Parsetree.core_type) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.core_type) = 
+# 3108 "parsing/parser.mly"
+      ( Typ.attr _1 _2 )
+# 7407 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.direction_flag) = 
+# 3489 "parsing/parser.mly"
+                                                ( Upto )
+# 7432 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.direction_flag) = 
+# 3490 "parsing/parser.mly"
+                                                ( Downto )
+# 7457 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.expression) = 
+# 2065 "parsing/parser.mly"
+      ( _1 )
+# 7482 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined3;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _2;
+                      MenhirLib.EngineTypes.startp = _startpos__2_;
+                      MenhirLib.EngineTypes.endp = _endpos__2_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _menhir_s;
+                        MenhirLib.EngineTypes.semv = _1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_;
+                        MenhirLib.EngineTypes.next = _menhir_stack;
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.expression) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : (Parsetree.module_expr) = Obj.magic _5 in
+        let _1_inlined3 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 7548 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _4 =
+            let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 7566 "parsing/parser.ml"
+            
+          in
+          let _3 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 7576 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 7582 "parsing/parser.ml"
+            
+          in
+          
+# 2110 "parsing/parser.mly"
+      ( Pexp_letmodule(_4, _5, _7), _3 )
+# 7588 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__7_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 7599 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _6;
+          MenhirLib.EngineTypes.startp = _startpos__6_;
+          MenhirLib.EngineTypes.endp = _endpos__6_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _5;
+            MenhirLib.EngineTypes.startp = _startpos__5_;
+            MenhirLib.EngineTypes.endp = _endpos__5_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined4;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined4_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined4_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__2_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__2_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined3;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined2;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _2;
+                        MenhirLib.EngineTypes.startp = _startpos__2_;
+                        MenhirLib.EngineTypes.endp = _endpos__2_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _6 : (Parsetree.expression) = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined4 : (Parsetree.attributes) = Obj.magic _1_inlined4 in
+        let _2_inlined1 : (Parsetree.constructor_arguments * Parsetree.core_type option) = Obj.magic _2_inlined1 in
+        let _1_inlined3 : (string) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__6_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _4 =
+            let (_endpos__1_inlined1_, _endpos__1_, _startpos__1_, _1_inlined1, _2, _1) = (_endpos__1_inlined4_, _endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined4, _2_inlined1, _1_inlined3) in
+            let _3 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 7685 "parsing/parser.ml"
+              
+            in
+            let _endpos__3_ = _endpos__1_inlined1_ in
+            let _1 =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 7696 "parsing/parser.ml"
+              
+            in
+            let _endpos = _endpos__3_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 2946 "parsing/parser.mly"
+      ( let args, res = _2 in
+        Te.decl _1 ~args ?res ~attrs:_3 ~loc:(make_loc _sloc) )
+# 7706 "parsing/parser.ml"
+            
+          in
+          let _3 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 7716 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 7722 "parsing/parser.ml"
+            
+          in
+          
+# 2112 "parsing/parser.mly"
+      ( Pexp_letexception(_4, _6), _3 )
+# 7728 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__6_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 7739 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.expression) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : (Parsetree.module_expr) = Obj.magic _5 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _4 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 7811 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 7817 "parsing/parser.ml"
+            
+          in
+          let _3 = 
+# 3544 "parsing/parser.mly"
+                                                ( Fresh )
+# 7823 "parsing/parser.ml"
+           in
+          
+# 2114 "parsing/parser.mly"
+      ( let open_loc = make_loc (_startpos__2_, _endpos__5_) in
+        let od = Opn.mk _5 ~override:_3 ~loc:open_loc in
+        Pexp_open(od, _7), _4 )
+# 7830 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__7_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 7841 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined3;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _2;
+                      MenhirLib.EngineTypes.startp = _startpos__2_;
+                      MenhirLib.EngineTypes.endp = _endpos__2_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _menhir_s;
+                        MenhirLib.EngineTypes.semv = _1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_;
+                        MenhirLib.EngineTypes.next = _menhir_stack;
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.expression) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : (Parsetree.module_expr) = Obj.magic _5 in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (string Asttypes.loc option) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : unit = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _4 =
+            let (_1_inlined1, _1) = (_1_inlined3, _1_inlined2) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 7920 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 7926 "parsing/parser.ml"
+            
+          in
+          let _3 =
+            let _1 = _1_inlined1 in
+            
+# 3545 "parsing/parser.mly"
+                                                ( Override )
+# 7934 "parsing/parser.ml"
+            
+          in
+          
+# 2114 "parsing/parser.mly"
+      ( let open_loc = make_loc (_startpos__2_, _endpos__5_) in
+        let od = Opn.mk _5 ~override:_3 ~loc:open_loc in
+        Pexp_open(od, _7), _4 )
+# 7942 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__7_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 7953 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined2;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.case list) = Obj.magic xs in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _3 =
+            let xs =
+              let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 8002 "parsing/parser.ml"
+               in
+              
+# 965 "parsing/parser.mly"
+    ( xs )
+# 8007 "parsing/parser.ml"
+              
+            in
+            
+# 2446 "parsing/parser.mly"
+    ( xs )
+# 8013 "parsing/parser.ml"
+            
+          in
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 8023 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 8029 "parsing/parser.ml"
+            
+          in
+          
+# 2118 "parsing/parser.mly"
+      ( Pexp_function _3, _2 )
+# 8035 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos_xs_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 8046 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = Obj.magic _3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 8104 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 8110 "parsing/parser.ml"
+            
+          in
+          
+# 2120 "parsing/parser.mly"
+      ( let (l,o,p) = _3 in
+        Pexp_fun(l, o, p, _4), _2 )
+# 8117 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__4_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 8128 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined2;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _menhir_s;
+                        MenhirLib.EngineTypes.semv = _1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_;
+                        MenhirLib.EngineTypes.next = _menhir_stack;
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.expression) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let xs : (string Asttypes.loc list) = Obj.magic xs in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _5 = 
+# 2341 "parsing/parser.mly"
+    ( xs )
+# 8203 "parsing/parser.ml"
+           in
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 8212 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 8218 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__7_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2123 "parsing/parser.mly"
+      ( (mk_newtypes ~loc:_sloc _5 _7).pexp_desc, _2 )
+# 8227 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__7_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 8238 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.case list) = Obj.magic xs in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _5 =
+            let xs =
+              let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 8301 "parsing/parser.ml"
+               in
+              
+# 965 "parsing/parser.mly"
+    ( xs )
+# 8306 "parsing/parser.ml"
+              
+            in
+            
+# 2446 "parsing/parser.mly"
+    ( xs )
+# 8312 "parsing/parser.ml"
+            
+          in
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 8322 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 8328 "parsing/parser.ml"
+            
+          in
+          
+# 2125 "parsing/parser.mly"
+      ( Pexp_match(_3, _5), _2 )
+# 8334 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos_xs_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 8345 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.case list) = Obj.magic xs in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _5 =
+            let xs =
+              let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 8408 "parsing/parser.ml"
+               in
+              
+# 965 "parsing/parser.mly"
+    ( xs )
+# 8413 "parsing/parser.ml"
+              
+            in
+            
+# 2446 "parsing/parser.mly"
+    ( xs )
+# 8419 "parsing/parser.ml"
+            
+          in
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 8429 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 8435 "parsing/parser.ml"
+            
+          in
+          
+# 2127 "parsing/parser.mly"
+      ( Pexp_try(_3, _5), _2 )
+# 8441 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos_xs_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 8452 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 8517 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 8523 "parsing/parser.ml"
+            
+          in
+          
+# 2129 "parsing/parser.mly"
+      ( syntax_error() )
+# 8529 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__5_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 8540 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined2;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _menhir_s;
+                        MenhirLib.EngineTypes.semv = _1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_;
+                        MenhirLib.EngineTypes.next = _menhir_stack;
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.expression) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : (Parsetree.expression) = Obj.magic _5 in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 8619 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 8625 "parsing/parser.ml"
+            
+          in
+          
+# 2131 "parsing/parser.mly"
+      ( Pexp_ifthenelse(_3, _5, Some _7), _2 )
+# 8631 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__7_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 8642 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : (Parsetree.expression) = Obj.magic _5 in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 8707 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 8713 "parsing/parser.ml"
+            
+          in
+          
+# 2133 "parsing/parser.mly"
+      ( Pexp_ifthenelse(_3, _5, None), _2 )
+# 8719 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__5_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 8730 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _6;
+          MenhirLib.EngineTypes.startp = _startpos__6_;
+          MenhirLib.EngineTypes.endp = _endpos__6_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _5;
+            MenhirLib.EngineTypes.startp = _startpos__5_;
+            MenhirLib.EngineTypes.endp = _endpos__5_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _4;
+              MenhirLib.EngineTypes.startp = _startpos__4_;
+              MenhirLib.EngineTypes.endp = _endpos__4_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _3;
+                MenhirLib.EngineTypes.startp = _startpos__3_;
+                MenhirLib.EngineTypes.endp = _endpos__3_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : (Parsetree.expression) = Obj.magic _5 in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__6_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 8802 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 8808 "parsing/parser.ml"
+            
+          in
+          
+# 2135 "parsing/parser.mly"
+      ( Pexp_while(_3, _5), _2 )
+# 8814 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__6_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 8825 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _10;
+          MenhirLib.EngineTypes.startp = _startpos__10_;
+          MenhirLib.EngineTypes.endp = _endpos__10_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _9;
+            MenhirLib.EngineTypes.startp = _startpos__9_;
+            MenhirLib.EngineTypes.endp = _endpos__9_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _8;
+              MenhirLib.EngineTypes.startp = _startpos__8_;
+              MenhirLib.EngineTypes.endp = _endpos__8_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _7;
+                MenhirLib.EngineTypes.startp = _startpos__7_;
+                MenhirLib.EngineTypes.endp = _endpos__7_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _6;
+                  MenhirLib.EngineTypes.startp = _startpos__6_;
+                  MenhirLib.EngineTypes.endp = _endpos__6_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _5;
+                    MenhirLib.EngineTypes.startp = _startpos__5_;
+                    MenhirLib.EngineTypes.endp = _endpos__5_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _4;
+                      MenhirLib.EngineTypes.startp = _startpos__4_;
+                      MenhirLib.EngineTypes.endp = _endpos__4_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _3;
+                        MenhirLib.EngineTypes.startp = _startpos__3_;
+                        MenhirLib.EngineTypes.endp = _endpos__3_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _;
+                          MenhirLib.EngineTypes.semv = _1_inlined2;
+                          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                          MenhirLib.EngineTypes.next = {
+                            MenhirLib.EngineTypes.state = _;
+                            MenhirLib.EngineTypes.semv = _1_inlined1;
+                            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                            MenhirLib.EngineTypes.next = {
+                              MenhirLib.EngineTypes.state = _menhir_s;
+                              MenhirLib.EngineTypes.semv = _1;
+                              MenhirLib.EngineTypes.startp = _startpos__1_;
+                              MenhirLib.EngineTypes.endp = _endpos__1_;
+                              MenhirLib.EngineTypes.next = _menhir_stack;
+                            };
+                          };
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _10 : unit = Obj.magic _10 in
+        let _9 : (Parsetree.expression) = Obj.magic _9 in
+        let _8 : unit = Obj.magic _8 in
+        let _7 : (Parsetree.expression) = Obj.magic _7 in
+        let _6 : (Asttypes.direction_flag) = Obj.magic _6 in
+        let _5 : (Parsetree.expression) = Obj.magic _5 in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.pattern) = Obj.magic _3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__10_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 8925 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 8931 "parsing/parser.ml"
+            
+          in
+          
+# 2138 "parsing/parser.mly"
+      ( Pexp_for(_3, _5, _7, _6, _9), _2 )
+# 8937 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__10_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 8948 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined2;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 8999 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 9005 "parsing/parser.ml"
+            
+          in
+          
+# 2140 "parsing/parser.mly"
+      ( Pexp_assert _3, _2 )
+# 9011 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__3_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 9022 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined2;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 9073 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 9079 "parsing/parser.ml"
+            
+          in
+          
+# 2142 "parsing/parser.mly"
+      ( Pexp_lazy _3, _2 )
+# 9085 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__3_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 9096 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xss;
+            MenhirLib.EngineTypes.startp = _startpos_xss_;
+            MenhirLib.EngineTypes.endp = _endpos_xss_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined3;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let xss : (Parsetree.class_field list list) = Obj.magic xss in
+        let _1_inlined3 : (Parsetree.pattern) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _3 =
+            let _1 = _1_inlined3 in
+            let _2 =
+              let _1 =
+                let _1 = 
+# 260 "menhir/standard.mly"
+    ( List.flatten xss )
+# 9161 "parsing/parser.ml"
+                 in
+                
+# 1751 "parsing/parser.mly"
+    ( _1 )
+# 9166 "parsing/parser.ml"
+                
+              in
+              let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in
+              let _endpos = _endpos__1_ in
+              let _startpos = _startpos__1_ in
+              
+# 764 "parsing/parser.mly"
+                               ( extra_cstr _startpos _endpos _1 )
+# 9175 "parsing/parser.ml"
+              
+            in
+            
+# 1738 "parsing/parser.mly"
+       ( Cstr.mk _1 _2 )
+# 9181 "parsing/parser.ml"
+            
+          in
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 9191 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 9197 "parsing/parser.ml"
+            
+          in
+          
+# 2144 "parsing/parser.mly"
+      ( Pexp_object _3, _2 )
+# 9203 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__4_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 9214 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xss;
+            MenhirLib.EngineTypes.startp = _startpos_xss_;
+            MenhirLib.EngineTypes.endp = _endpos_xss_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined3;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let xss : (Parsetree.class_field list list) = Obj.magic xss in
+        let _1_inlined3 : (Parsetree.pattern) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _3 =
+            let _1 = _1_inlined3 in
+            let _2 =
+              let _1 =
+                let _1 = 
+# 260 "menhir/standard.mly"
+    ( List.flatten xss )
+# 9279 "parsing/parser.ml"
+                 in
+                
+# 1751 "parsing/parser.mly"
+    ( _1 )
+# 9284 "parsing/parser.ml"
+                
+              in
+              let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in
+              let _endpos = _endpos__1_ in
+              let _startpos = _startpos__1_ in
+              
+# 764 "parsing/parser.mly"
+                               ( extra_cstr _startpos _endpos _1 )
+# 9293 "parsing/parser.ml"
+              
+            in
+            
+# 1738 "parsing/parser.mly"
+       ( Cstr.mk _1 _2 )
+# 9299 "parsing/parser.ml"
+            
+          in
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 9309 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 9315 "parsing/parser.ml"
+            
+          in
+          let _loc__4_ = (_startpos__4_, _endpos__4_) in
+          let _loc__1_ = (_startpos__1_, _endpos__1_) in
+          
+# 2146 "parsing/parser.mly"
+      ( unclosed "object" _loc__1_ "end" _loc__4_ )
+# 9323 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__4_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2067 "parsing/parser.mly"
+      ( let desc, attrs = _1 in
+        mkexp_attrs ~loc:_sloc desc attrs )
+# 9334 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : ((Asttypes.arg_label * Parsetree.expression) list) = Obj.magic xs in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _2 =
+              let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 9369 "parsing/parser.ml"
+               in
+              
+# 872 "parsing/parser.mly"
+    ( xs )
+# 9374 "parsing/parser.ml"
+              
+            in
+            
+# 2150 "parsing/parser.mly"
+      ( Pexp_apply(_1, _2) )
+# 9380 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos_xs_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 9390 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 9396 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let xs : (Parsetree.expression list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _1 =
+              let es =
+                let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 9425 "parsing/parser.ml"
+                 in
+                
+# 932 "parsing/parser.mly"
+    ( xs )
+# 9430 "parsing/parser.ml"
+                
+              in
+              
+# 2473 "parsing/parser.mly"
+    ( es )
+# 9436 "parsing/parser.ml"
+              
+            in
+            
+# 2152 "parsing/parser.mly"
+      ( Pexp_tuple(_1) )
+# 9442 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_xs_, _startpos_xs_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 9452 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 9458 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _1 =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 9496 "parsing/parser.ml"
+              
+            in
+            
+# 2154 "parsing/parser.mly"
+      ( Pexp_construct(_1, Some _2) )
+# 9502 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 9512 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 9518 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : (Asttypes.label) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 = 
+# 2156 "parsing/parser.mly"
+      ( Pexp_variant(_1, Some _2) )
+# 9551 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 9560 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 9566 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = op;
+            MenhirLib.EngineTypes.startp = _startpos_op_;
+            MenhirLib.EngineTypes.endp = _endpos_op_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let op : (
+# 596 "parsing/parser.mly"
+       (string)
+# 9600 "parsing/parser.ml"
+        ) = Obj.magic op in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3367 "parsing/parser.mly"
+                  ( op )
+# 9612 "parsing/parser.ml"
+               in
+              let (_endpos__1_, _startpos__1_) = (_endpos_op_, _startpos_op_) in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 9621 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 9627 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 9637 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 9643 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = op;
+            MenhirLib.EngineTypes.startp = _startpos_op_;
+            MenhirLib.EngineTypes.endp = _endpos_op_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let op : (
+# 597 "parsing/parser.mly"
+       (string)
+# 9677 "parsing/parser.ml"
+        ) = Obj.magic op in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3368 "parsing/parser.mly"
+                  ( op )
+# 9689 "parsing/parser.ml"
+               in
+              let (_endpos__1_, _startpos__1_) = (_endpos_op_, _startpos_op_) in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 9698 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 9704 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 9714 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 9720 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = op;
+            MenhirLib.EngineTypes.startp = _startpos_op_;
+            MenhirLib.EngineTypes.endp = _endpos_op_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let op : (
+# 598 "parsing/parser.mly"
+       (string)
+# 9754 "parsing/parser.ml"
+        ) = Obj.magic op in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3369 "parsing/parser.mly"
+                  ( op )
+# 9766 "parsing/parser.ml"
+               in
+              let (_endpos__1_, _startpos__1_) = (_endpos_op_, _startpos_op_) in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 9775 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 9781 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 9791 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 9797 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = op;
+            MenhirLib.EngineTypes.startp = _startpos_op_;
+            MenhirLib.EngineTypes.endp = _endpos_op_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let op : (
+# 599 "parsing/parser.mly"
+       (string)
+# 9831 "parsing/parser.ml"
+        ) = Obj.magic op in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3370 "parsing/parser.mly"
+                  ( op )
+# 9843 "parsing/parser.ml"
+               in
+              let (_endpos__1_, _startpos__1_) = (_endpos_op_, _startpos_op_) in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 9852 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 9858 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 9868 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 9874 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = op;
+            MenhirLib.EngineTypes.startp = _startpos_op_;
+            MenhirLib.EngineTypes.endp = _endpos_op_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let op : (
+# 600 "parsing/parser.mly"
+       (string)
+# 9908 "parsing/parser.ml"
+        ) = Obj.magic op in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3371 "parsing/parser.mly"
+                  ( op )
+# 9920 "parsing/parser.ml"
+               in
+              let (_endpos__1_, _startpos__1_) = (_endpos_op_, _startpos_op_) in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 9929 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 9935 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 9945 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 9951 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let _1 : unit = Obj.magic _1 in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3372 "parsing/parser.mly"
+                   ("+")
+# 9993 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 10001 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 10007 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 10017 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 10023 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let _1 : unit = Obj.magic _1 in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3373 "parsing/parser.mly"
+                  ("+.")
+# 10065 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 10073 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 10079 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 10089 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 10095 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let _1 : unit = Obj.magic _1 in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3374 "parsing/parser.mly"
+                  ("+=")
+# 10137 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 10145 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 10151 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 10161 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 10167 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let _1 : unit = Obj.magic _1 in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3375 "parsing/parser.mly"
+                   ("-")
+# 10209 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 10217 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 10223 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 10233 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 10239 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let _1 : unit = Obj.magic _1 in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3376 "parsing/parser.mly"
+                  ("-.")
+# 10281 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 10289 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 10295 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 10305 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 10311 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let _1 : unit = Obj.magic _1 in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3377 "parsing/parser.mly"
+                   ("*")
+# 10353 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 10361 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 10367 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 10377 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 10383 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let _1 : unit = Obj.magic _1 in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3378 "parsing/parser.mly"
+                   ("%")
+# 10425 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 10433 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 10439 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 10449 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 10455 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let _1 : unit = Obj.magic _1 in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3379 "parsing/parser.mly"
+                   ("=")
+# 10497 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 10505 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 10511 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 10521 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 10527 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let _1 : unit = Obj.magic _1 in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3380 "parsing/parser.mly"
+                   ("<")
+# 10569 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 10577 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 10583 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 10593 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 10599 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let _1 : unit = Obj.magic _1 in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3381 "parsing/parser.mly"
+                   (">")
+# 10641 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 10649 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 10655 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 10665 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 10671 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let _1 : unit = Obj.magic _1 in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3382 "parsing/parser.mly"
+                  ("or")
+# 10713 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 10721 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 10727 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 10737 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 10743 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let _1 : unit = Obj.magic _1 in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3383 "parsing/parser.mly"
+                  ("||")
+# 10785 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 10793 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 10799 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 10809 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 10815 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let _1 : unit = Obj.magic _1 in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3384 "parsing/parser.mly"
+                   ("&")
+# 10857 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 10865 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 10871 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 10881 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 10887 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let _1 : unit = Obj.magic _1 in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3385 "parsing/parser.mly"
+                  ("&&")
+# 10929 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 10937 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 10943 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 10953 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 10959 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = e2;
+          MenhirLib.EngineTypes.startp = _startpos_e2_;
+          MenhirLib.EngineTypes.endp = _endpos_e2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e1;
+              MenhirLib.EngineTypes.startp = _startpos_e1_;
+              MenhirLib.EngineTypes.endp = _endpos_e1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let e2 : (Parsetree.expression) = Obj.magic e2 in
+        let _1 : unit = Obj.magic _1 in
+        let e1 : (Parsetree.expression) = Obj.magic e1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e1_ in
+        let _endpos = _endpos_e2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let op =
+              let _1 = 
+# 3386 "parsing/parser.mly"
+                  (":=")
+# 11001 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 11009 "parsing/parser.ml"
+              
+            in
+            
+# 2158 "parsing/parser.mly"
+      ( mkinfix e1 op e2 )
+# 11015 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 11025 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 11031 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : (string) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _loc__1_ = (_startpos__1_, _endpos__1_) in
+            
+# 2160 "parsing/parser.mly"
+      ( mkuminus ~oploc:_loc__1_ _1 _2 )
+# 11066 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 11076 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 11082 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : (string) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _loc__1_ = (_startpos__1_, _endpos__1_) in
+            
+# 2162 "parsing/parser.mly"
+      ( mkuplus ~oploc:_loc__1_ _1 _2 )
+# 11117 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 11127 "parsing/parser.ml"
+          
+        in
+        
+# 2070 "parsing/parser.mly"
+      ( _1 )
+# 11133 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (let_bindings) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__3_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2072 "parsing/parser.mly"
+      ( expr_of_let_bindings ~loc:_sloc _1 _3 )
+# 11175 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = body;
+          MenhirLib.EngineTypes.startp = _startpos_body_;
+          MenhirLib.EngineTypes.endp = _endpos_body_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = bindings;
+              MenhirLib.EngineTypes.startp = _startpos_bindings_;
+              MenhirLib.EngineTypes.endp = _endpos_bindings_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let body : (Parsetree.expression) = Obj.magic body in
+        let _3 : unit = Obj.magic _3 in
+        let bindings : (Parsetree.pattern * Parsetree.expression * Parsetree.binding_op list) = Obj.magic bindings in
+        let _1 : (
+# 602 "parsing/parser.mly"
+       (string)
+# 11217 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_body_ in
+        let _v : (Parsetree.expression) = let pbop_op =
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 11229 "parsing/parser.ml"
+          
+        in
+        let _startpos_pbop_op_ = _startpos__1_ in
+        let _endpos = _endpos_body_ in
+        let _symbolstartpos = _startpos_pbop_op_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2074 "parsing/parser.mly"
+      ( let (pbop_pat, pbop_exp, rev_ands) = bindings in
+        let ands = List.rev rev_ands in
+        let pbop_loc = make_loc _sloc in
+        let let_ = {pbop_op; pbop_pat; pbop_exp; pbop_loc} in
+        mkexp ~loc:_sloc (Pexp_letop{ let_; ands; body}) )
+# 11243 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__3_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _loc__2_ = (_startpos__2_, _endpos__2_) in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2080 "parsing/parser.mly"
+      ( mkexp_cons ~loc:_sloc _loc__2_ (ghexp ~loc:_sloc (Pexp_tuple[_1;_3])) )
+# 11286 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 11321 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 11330 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 11338 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__3_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2082 "parsing/parser.mly"
+      ( mkexp ~loc:_sloc (Pexp_setinstvar(_1, _3)) )
+# 11347 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : (Parsetree.expression) = Obj.magic _5 in
+        let _4 : unit = Obj.magic _4 in
+        let _1_inlined1 : (Longident.t) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _3 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 11405 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2084 "parsing/parser.mly"
+      ( mkexp ~loc:_sloc (Pexp_setfield(_1, _3, _5)) )
+# 11414 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.expression) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__7_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2086 "parsing/parser.mly"
+      ( array_set ~loc:_sloc _1 _4 _7 )
+# 11484 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.expression) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__7_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2088 "parsing/parser.mly"
+      ( string_set ~loc:_sloc _1 _4 _7 )
+# 11554 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.expression) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__7_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2090 "parsing/parser.mly"
+      ( bigarray_set ~loc:_sloc _1 _4 _7 )
+# 11624 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.expression) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 11686 "parsing/parser.ml"
+        ) = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__7_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2092 "parsing/parser.mly"
+      ( dotop_set ~loc:_sloc (Lident ("." ^ _2 ^ "[]<-")) _1 _4 _7 )
+# 11698 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.expression) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 11760 "parsing/parser.ml"
+        ) = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__7_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2094 "parsing/parser.mly"
+      ( dotop_set ~loc:_sloc (Lident ("." ^ _2 ^ "()<-")) _1 _4 _7 )
+# 11772 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.expression) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 11834 "parsing/parser.ml"
+        ) = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__7_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2096 "parsing/parser.mly"
+      ( dotop_set ~loc:_sloc (Lident ("." ^ _2 ^ "{}<-")) _1 _4 _7 )
+# 11846 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _9;
+          MenhirLib.EngineTypes.startp = _startpos__9_;
+          MenhirLib.EngineTypes.endp = _endpos__9_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _8;
+            MenhirLib.EngineTypes.startp = _startpos__8_;
+            MenhirLib.EngineTypes.endp = _endpos__8_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _7;
+              MenhirLib.EngineTypes.startp = _startpos__7_;
+              MenhirLib.EngineTypes.endp = _endpos__7_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _6;
+                MenhirLib.EngineTypes.startp = _startpos__6_;
+                MenhirLib.EngineTypes.endp = _endpos__6_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _5;
+                  MenhirLib.EngineTypes.startp = _startpos__5_;
+                  MenhirLib.EngineTypes.endp = _endpos__5_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _4;
+                    MenhirLib.EngineTypes.startp = _startpos__4_;
+                    MenhirLib.EngineTypes.endp = _endpos__4_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _3;
+                      MenhirLib.EngineTypes.startp = _startpos__3_;
+                      MenhirLib.EngineTypes.endp = _endpos__3_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _2;
+                        MenhirLib.EngineTypes.startp = _startpos__2_;
+                        MenhirLib.EngineTypes.endp = _endpos__2_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _9 : (Parsetree.expression) = Obj.magic _9 in
+        let _8 : unit = Obj.magic _8 in
+        let _7 : unit = Obj.magic _7 in
+        let _6 : (Parsetree.expression) = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 11920 "parsing/parser.ml"
+        ) = Obj.magic _4 in
+        let _3 : (Longident.t) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__9_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__9_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2098 "parsing/parser.mly"
+      ( dotop_set ~loc:_sloc (Ldot(_3,"." ^ _4 ^ "[]<-")) _1 _6 _9 )
+# 11934 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _9;
+          MenhirLib.EngineTypes.startp = _startpos__9_;
+          MenhirLib.EngineTypes.endp = _endpos__9_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _8;
+            MenhirLib.EngineTypes.startp = _startpos__8_;
+            MenhirLib.EngineTypes.endp = _endpos__8_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _7;
+              MenhirLib.EngineTypes.startp = _startpos__7_;
+              MenhirLib.EngineTypes.endp = _endpos__7_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _6;
+                MenhirLib.EngineTypes.startp = _startpos__6_;
+                MenhirLib.EngineTypes.endp = _endpos__6_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _5;
+                  MenhirLib.EngineTypes.startp = _startpos__5_;
+                  MenhirLib.EngineTypes.endp = _endpos__5_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _4;
+                    MenhirLib.EngineTypes.startp = _startpos__4_;
+                    MenhirLib.EngineTypes.endp = _endpos__4_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _3;
+                      MenhirLib.EngineTypes.startp = _startpos__3_;
+                      MenhirLib.EngineTypes.endp = _endpos__3_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _2;
+                        MenhirLib.EngineTypes.startp = _startpos__2_;
+                        MenhirLib.EngineTypes.endp = _endpos__2_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _9 : (Parsetree.expression) = Obj.magic _9 in
+        let _8 : unit = Obj.magic _8 in
+        let _7 : unit = Obj.magic _7 in
+        let _6 : (Parsetree.expression) = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 12008 "parsing/parser.ml"
+        ) = Obj.magic _4 in
+        let _3 : (Longident.t) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__9_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__9_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2100 "parsing/parser.mly"
+      ( dotop_set ~loc:_sloc (Ldot(_3, "." ^ _4 ^ "()<-")) _1 _6 _9 )
+# 12022 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _9;
+          MenhirLib.EngineTypes.startp = _startpos__9_;
+          MenhirLib.EngineTypes.endp = _endpos__9_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _8;
+            MenhirLib.EngineTypes.startp = _startpos__8_;
+            MenhirLib.EngineTypes.endp = _endpos__8_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _7;
+              MenhirLib.EngineTypes.startp = _startpos__7_;
+              MenhirLib.EngineTypes.endp = _endpos__7_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _6;
+                MenhirLib.EngineTypes.startp = _startpos__6_;
+                MenhirLib.EngineTypes.endp = _endpos__6_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _5;
+                  MenhirLib.EngineTypes.startp = _startpos__5_;
+                  MenhirLib.EngineTypes.endp = _endpos__5_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _4;
+                    MenhirLib.EngineTypes.startp = _startpos__4_;
+                    MenhirLib.EngineTypes.endp = _endpos__4_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _3;
+                      MenhirLib.EngineTypes.startp = _startpos__3_;
+                      MenhirLib.EngineTypes.endp = _endpos__3_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _2;
+                        MenhirLib.EngineTypes.startp = _startpos__2_;
+                        MenhirLib.EngineTypes.endp = _endpos__2_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _9 : (Parsetree.expression) = Obj.magic _9 in
+        let _8 : unit = Obj.magic _8 in
+        let _7 : unit = Obj.magic _7 in
+        let _6 : (Parsetree.expression) = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 12096 "parsing/parser.ml"
+        ) = Obj.magic _4 in
+        let _3 : (Longident.t) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__9_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__9_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2102 "parsing/parser.mly"
+      ( dotop_set ~loc:_sloc (Ldot(_3, "." ^ _4 ^ "{}<-")) _1 _6 _9 )
+# 12110 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.attribute) = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.expression) = 
+# 2104 "parsing/parser.mly"
+      ( Exp.attr _1 _2 )
+# 12142 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.expression) = let _loc__1_ = (_startpos__1_, _endpos__1_) in
+        
+# 2106 "parsing/parser.mly"
+     ( not_expecting _loc__1_ "wildcard \"_\"" )
+# 12168 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (string Asttypes.loc option) = 
+# 3645 "parsing/parser.mly"
+                    ( None )
+# 12186 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (string Asttypes.loc) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (string Asttypes.loc option) = 
+# 3646 "parsing/parser.mly"
+                    ( Some _2 )
+# 12218 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.payload) = Obj.magic _3 in
+        let _2 : (string Asttypes.loc) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.extension) = 
+# 3656 "parsing/parser.mly"
+                                           ( (_2, _3) )
+# 12264 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined2;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (Longident.t) = Obj.magic _1_inlined2 in
+        let _3 : unit = Obj.magic _3 in
+        let _1_inlined1 : (string) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (Parsetree.extension_constructor) = let attrs =
+          let _1 = _1_inlined3 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 12319 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs_ = _endpos__1_inlined3_ in
+        let lid =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 12331 "parsing/parser.ml"
+          
+        in
+        let cid =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 12342 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_attrs_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3030 "parsing/parser.mly"
+      ( let info = symbol_info _endpos in
+        Te.rebind cid lid ~attrs ~loc:(make_loc _sloc) ~info )
+# 12352 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Longident.t) = Obj.magic _1_inlined1 in
+        let _3 : unit = Obj.magic _3 in
+        let _1 : (string) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.extension_constructor) = let attrs =
+          let _1 = _1_inlined2 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 12400 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs_ = _endpos__1_inlined2_ in
+        let lid =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 12412 "parsing/parser.ml"
+          
+        in
+        let cid =
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 12422 "parsing/parser.ml"
+          
+        in
+        let _startpos_cid_ = _startpos__1_ in
+        let _1 = 
+# 3465 "parsing/parser.mly"
+    ( () )
+# 12429 "parsing/parser.ml"
+         in
+        let _endpos = _endpos_attrs_ in
+        let _symbolstartpos = _startpos_cid_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3030 "parsing/parser.mly"
+      ( let info = symbol_info _endpos in
+        Te.rebind cid lid ~attrs ~loc:(make_loc _sloc) ~info )
+# 12438 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.payload) = Obj.magic _3 in
+        let _2 : (string Asttypes.loc) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.attribute) = let _endpos = _endpos__4_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3633 "parsing/parser.mly"
+    ( mark_symbol_docs _sloc;
+      Attr.mk ~loc:(make_loc _sloc) _2 _3 )
+# 12488 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : ((Parsetree.core_type * Asttypes.variance) list) = let params = 
+# 1858 "parsing/parser.mly"
+      ( [] )
+# 12506 "parsing/parser.ml"
+         in
+        
+# 1683 "parsing/parser.mly"
+    ( params )
+# 12511 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let xs : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic xs in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : ((Parsetree.core_type * Asttypes.variance) list) = let params =
+          let params =
+            let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 12552 "parsing/parser.ml"
+             in
+            
+# 904 "parsing/parser.mly"
+    ( xs )
+# 12557 "parsing/parser.ml"
+            
+          in
+          
+# 1860 "parsing/parser.mly"
+      ( params )
+# 12563 "parsing/parser.ml"
+          
+        in
+        
+# 1683 "parsing/parser.mly"
+    ( params )
+# 12569 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.expression) = 
+# 2432 "parsing/parser.mly"
+      ( _1 )
+# 12594 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.core_type option * Parsetree.core_type option) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__3_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2434 "parsing/parser.mly"
+      ( mkexp_constraint ~loc:_sloc _3 _1 )
+# 12636 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.expression) = 
+# 2458 "parsing/parser.mly"
+      ( _2 )
+# 12668 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.core_type) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 = 
+# 2460 "parsing/parser.mly"
+      ( Pexp_constraint (_4, _2) )
+# 12715 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__4_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 12724 "parsing/parser.ml"
+          
+        in
+        
+# 2461 "parsing/parser.mly"
+      ( _1 )
+# 12730 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2464 "parsing/parser.mly"
+      (
+       let (l,o,p) = _1 in
+       ghexp ~loc:_sloc (Pexp_fun(l, o, p, _2))
+      )
+# 12768 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : (Parsetree.expression) = Obj.magic _5 in
+        let _4 : unit = Obj.magic _4 in
+        let xs : (string Asttypes.loc list) = Obj.magic xs in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _3 = 
+# 2341 "parsing/parser.mly"
+    ( xs )
+# 12821 "parsing/parser.ml"
+         in
+        let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2469 "parsing/parser.mly"
+      ( mk_newtypes ~loc:_sloc _3 _5 )
+# 12829 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = ty;
+          MenhirLib.EngineTypes.startp = _startpos_ty_;
+          MenhirLib.EngineTypes.endp = _endpos_ty_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let ty : (Parsetree.core_type) = Obj.magic ty in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_ty_ in
+        let _endpos = _endpos_ty_ in
+        let _v : (Parsetree.core_type) = 
+# 3142 "parsing/parser.mly"
+      ( ty )
+# 12854 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = codomain;
+          MenhirLib.EngineTypes.startp = _startpos_codomain_;
+          MenhirLib.EngineTypes.endp = _endpos_codomain_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = label;
+                MenhirLib.EngineTypes.startp = _startpos_label_;
+                MenhirLib.EngineTypes.endp = _endpos_label_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let codomain : (Parsetree.core_type) = Obj.magic codomain in
+        let _3 : unit = Obj.magic _3 in
+        let _1 : (Parsetree.core_type) = Obj.magic _1 in
+        let label : (string) = Obj.magic label in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_label_ in
+        let _endpos = _endpos_codomain_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let domain = 
+# 768 "parsing/parser.mly"
+                              ( extra_rhs_core_type _1 ~pos:_endpos__1_ )
+# 12902 "parsing/parser.ml"
+             in
+            let label = 
+# 3154 "parsing/parser.mly"
+      ( Optional label )
+# 12907 "parsing/parser.ml"
+             in
+            
+# 3148 "parsing/parser.mly"
+        ( Ptyp_arrow(label, domain, codomain) )
+# 12912 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_codomain_, _startpos_label_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 12922 "parsing/parser.ml"
+          
+        in
+        
+# 3150 "parsing/parser.mly"
+    ( _1 )
+# 12928 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = codomain;
+          MenhirLib.EngineTypes.startp = _startpos_codomain_;
+          MenhirLib.EngineTypes.endp = _endpos_codomain_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = label;
+                  MenhirLib.EngineTypes.startp = _startpos_label_;
+                  MenhirLib.EngineTypes.endp = _endpos_label_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let codomain : (Parsetree.core_type) = Obj.magic codomain in
+        let _3 : unit = Obj.magic _3 in
+        let _1 : (Parsetree.core_type) = Obj.magic _1 in
+        let _2 : unit = Obj.magic _2 in
+        let label : (
+# 620 "parsing/parser.mly"
+       (string)
+# 12977 "parsing/parser.ml"
+        ) = Obj.magic label in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_label_ in
+        let _endpos = _endpos_codomain_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let domain = 
+# 768 "parsing/parser.mly"
+                              ( extra_rhs_core_type _1 ~pos:_endpos__1_ )
+# 12987 "parsing/parser.ml"
+             in
+            let label = 
+# 3156 "parsing/parser.mly"
+      ( Labelled label )
+# 12992 "parsing/parser.ml"
+             in
+            
+# 3148 "parsing/parser.mly"
+        ( Ptyp_arrow(label, domain, codomain) )
+# 12997 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_codomain_, _startpos_label_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 13007 "parsing/parser.ml"
+          
+        in
+        
+# 3150 "parsing/parser.mly"
+    ( _1 )
+# 13013 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = codomain;
+          MenhirLib.EngineTypes.startp = _startpos_codomain_;
+          MenhirLib.EngineTypes.endp = _endpos_codomain_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let codomain : (Parsetree.core_type) = Obj.magic codomain in
+        let _3 : unit = Obj.magic _3 in
+        let _1 : (Parsetree.core_type) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_codomain_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let domain = 
+# 768 "parsing/parser.mly"
+                              ( extra_rhs_core_type _1 ~pos:_endpos__1_ )
+# 13054 "parsing/parser.ml"
+             in
+            let label = 
+# 3158 "parsing/parser.mly"
+      ( Nolabel )
+# 13059 "parsing/parser.ml"
+             in
+            
+# 3148 "parsing/parser.mly"
+        ( Ptyp_arrow(label, domain, codomain) )
+# 13064 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos_codomain_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 13074 "parsing/parser.ml"
+          
+        in
+        
+# 3150 "parsing/parser.mly"
+    ( _1 )
+# 13080 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (string Asttypes.loc * Parsetree.module_type option) = let x =
+          let _1 = 
+# 1113 "parsing/parser.mly"
+                            ("*")
+# 13113 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 13122 "parsing/parser.ml"
+          
+        in
+        
+# 1114 "parsing/parser.mly"
+      ( x, None )
+# 13128 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = mty;
+            MenhirLib.EngineTypes.startp = _startpos_mty_;
+            MenhirLib.EngineTypes.endp = _endpos_mty_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let mty : (Parsetree.module_type) = Obj.magic mty in
+        let _3 : unit = Obj.magic _3 in
+        let _1_inlined1 : (string) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (string Asttypes.loc * Parsetree.module_type option) = let x =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 13186 "parsing/parser.ml"
+          
+        in
+        
+# 1117 "parsing/parser.mly"
+      ( x, Some mty )
+# 13192 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : (
+# 666 "parsing/parser.mly"
+       (string)
+# 13213 "parsing/parser.ml"
+        ) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : (string) = 
+# 1123 "parsing/parser.mly"
+      ( x )
+# 13221 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 1126 "parsing/parser.mly"
+      ( "_" )
+# 13246 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.constructor_arguments * Parsetree.core_type option) = 
+# 2950 "parsing/parser.mly"
+                                  ( (Pcstr_tuple [],None) )
+# 13264 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.constructor_arguments) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.constructor_arguments * Parsetree.core_type option) = 
+# 2951 "parsing/parser.mly"
+                                  ( (_2,None) )
+# 13296 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : (Parsetree.core_type) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.constructor_arguments) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.constructor_arguments * Parsetree.core_type option) = 
+# 2953 "parsing/parser.mly"
+                                  ( (_2,Some _4) )
+# 13342 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.core_type) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.constructor_arguments * Parsetree.core_type option) = 
+# 2955 "parsing/parser.mly"
+                                  ( (Pcstr_tuple [],Some _2) )
+# 13374 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = args_res;
+            MenhirLib.EngineTypes.startp = _startpos_args_res_;
+            MenhirLib.EngineTypes.endp = _endpos_args_res_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let args_res : (Parsetree.constructor_arguments * Parsetree.core_type option) = Obj.magic args_res in
+        let _1_inlined1 : (string) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Ast_helper.str * Parsetree.constructor_arguments *
+  Parsetree.core_type option * Parsetree.attributes * Location.t *
+  Docstrings.info) = let attrs =
+          let _1 = _1_inlined2 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 13424 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs_ = _endpos__1_inlined2_ in
+        let cid =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 13436 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_attrs_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2898 "parsing/parser.mly"
+    (
+      let args, res = args_res in
+      let info = symbol_info _endpos in
+      let loc = make_loc _sloc in
+      cid, args, res, attrs, loc, info
+    )
+# 13450 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = args_res;
+            MenhirLib.EngineTypes.startp = _startpos_args_res_;
+            MenhirLib.EngineTypes.endp = _endpos_args_res_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let args_res : (Parsetree.constructor_arguments * Parsetree.core_type option) = Obj.magic args_res in
+        let _1 : (string) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Ast_helper.str * Parsetree.constructor_arguments *
+  Parsetree.core_type option * Parsetree.attributes * Location.t *
+  Docstrings.info) = let attrs =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 13493 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs_ = _endpos__1_inlined1_ in
+        let cid =
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 13504 "parsing/parser.ml"
+          
+        in
+        let _startpos_cid_ = _startpos__1_ in
+        let _1 = 
+# 3465 "parsing/parser.mly"
+    ( () )
+# 13511 "parsing/parser.ml"
+         in
+        let _endpos = _endpos_attrs_ in
+        let _symbolstartpos = _startpos_cid_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2898 "parsing/parser.mly"
+    (
+      let args, res = args_res in
+      let info = symbol_info _endpos in
+      let loc = make_loc _sloc in
+      cid, args, res, attrs, loc, info
+    )
+# 13524 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined4;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined4_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined3;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = params;
+                    MenhirLib.EngineTypes.startp = _startpos_params_;
+                    MenhirLib.EngineTypes.endp = _endpos_params_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = ext;
+                        MenhirLib.EngineTypes.startp = _startpos_ext_;
+                        MenhirLib.EngineTypes.endp = _endpos_ext_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined4 : (Parsetree.attributes) = Obj.magic _1_inlined4 in
+        let xs : ((Parsetree.core_type * Parsetree.core_type * Ast_helper.loc) list) = Obj.magic xs in
+        let _2 : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = Obj.magic _2 in
+        let _1_inlined3 : unit = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 13597 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined4_ in
+        let _v : ((Asttypes.rec_flag * string Asttypes.loc option) *
+  Parsetree.type_declaration) = let attrs2 =
+          let _1 = _1_inlined4 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 13612 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs2_ = _endpos__1_inlined4_ in
+        let cstrs =
+          let _1 =
+            let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 13621 "parsing/parser.ml"
+             in
+            
+# 854 "parsing/parser.mly"
+    ( xs )
+# 13626 "parsing/parser.ml"
+            
+          in
+          
+# 2814 "parsing/parser.mly"
+    ( _1 )
+# 13632 "parsing/parser.ml"
+          
+        in
+        let kind_priv_manifest =
+          let _1 = _1_inlined3 in
+          
+# 2849 "parsing/parser.mly"
+      ( _2 )
+# 13640 "parsing/parser.ml"
+          
+        in
+        let id =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 13651 "parsing/parser.ml"
+          
+        in
+        let flag = 
+# 3485 "parsing/parser.mly"
+                ( Recursive )
+# 13657 "parsing/parser.ml"
+         in
+        let attrs1 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 13664 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_attrs2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2786 "parsing/parser.mly"
+    (
+      let (kind, priv, manifest) = kind_priv_manifest in
+      let docs = symbol_docs _sloc in
+      let attrs = attrs1 @ attrs2 in
+      let loc = make_loc _sloc in
+      (flag, ext),
+      Type.mk id ~params ~cstrs ~kind ~priv ?manifest ~attrs ~loc ~docs
+    )
+# 13680 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined5;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined5_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined4;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined4_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined3;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = params;
+                    MenhirLib.EngineTypes.startp = _startpos_params_;
+                    MenhirLib.EngineTypes.endp = _endpos_params_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined2;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _1_inlined1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _;
+                          MenhirLib.EngineTypes.semv = ext;
+                          MenhirLib.EngineTypes.startp = _startpos_ext_;
+                          MenhirLib.EngineTypes.endp = _endpos_ext_;
+                          MenhirLib.EngineTypes.next = {
+                            MenhirLib.EngineTypes.state = _menhir_s;
+                            MenhirLib.EngineTypes.semv = _1;
+                            MenhirLib.EngineTypes.startp = _startpos__1_;
+                            MenhirLib.EngineTypes.endp = _endpos__1_;
+                            MenhirLib.EngineTypes.next = _menhir_stack;
+                          };
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined5 : (Parsetree.attributes) = Obj.magic _1_inlined5 in
+        let xs : ((Parsetree.core_type * Parsetree.core_type * Ast_helper.loc) list) = Obj.magic xs in
+        let _2 : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = Obj.magic _2 in
+        let _1_inlined4 : unit = Obj.magic _1_inlined4 in
+        let _1_inlined3 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 13759 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined3 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let _1_inlined2 : unit = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined5_ in
+        let _v : ((Asttypes.rec_flag * string Asttypes.loc option) *
+  Parsetree.type_declaration) = let attrs2 =
+          let _1 = _1_inlined5 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 13775 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs2_ = _endpos__1_inlined5_ in
+        let cstrs =
+          let _1 =
+            let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 13784 "parsing/parser.ml"
+             in
+            
+# 854 "parsing/parser.mly"
+    ( xs )
+# 13789 "parsing/parser.ml"
+            
+          in
+          
+# 2814 "parsing/parser.mly"
+    ( _1 )
+# 13795 "parsing/parser.ml"
+          
+        in
+        let kind_priv_manifest =
+          let _1 = _1_inlined4 in
+          
+# 2849 "parsing/parser.mly"
+      ( _2 )
+# 13803 "parsing/parser.ml"
+          
+        in
+        let id =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 13814 "parsing/parser.ml"
+          
+        in
+        let flag =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _startpos = _startpos__1_ in
+          let _loc = (_startpos, _endpos) in
+          
+# 3486 "parsing/parser.mly"
+                ( not_expecting _loc "nonrec flag" )
+# 13825 "parsing/parser.ml"
+          
+        in
+        let attrs1 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 13833 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_attrs2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2786 "parsing/parser.mly"
+    (
+      let (kind, priv, manifest) = kind_priv_manifest in
+      let docs = symbol_docs _sloc in
+      let attrs = attrs1 @ attrs2 in
+      let loc = make_loc _sloc in
+      (flag, ext),
+      Type.mk id ~params ~cstrs ~kind ~priv ?manifest ~attrs ~loc ~docs
+    )
+# 13849 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = kind_priv_manifest;
+              MenhirLib.EngineTypes.startp = _startpos_kind_priv_manifest_;
+              MenhirLib.EngineTypes.endp = _endpos_kind_priv_manifest_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = params;
+                  MenhirLib.EngineTypes.startp = _startpos_params_;
+                  MenhirLib.EngineTypes.endp = _endpos_params_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = ext;
+                      MenhirLib.EngineTypes.startp = _startpos_ext_;
+                      MenhirLib.EngineTypes.endp = _endpos_ext_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _menhir_s;
+                        MenhirLib.EngineTypes.semv = _1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_;
+                        MenhirLib.EngineTypes.next = _menhir_stack;
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let xs : ((Parsetree.core_type * Parsetree.core_type * Ast_helper.loc) list) = Obj.magic xs in
+        let kind_priv_manifest : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = Obj.magic kind_priv_manifest in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 13915 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : ((Asttypes.rec_flag * string Asttypes.loc option) *
+  Parsetree.type_declaration) = let attrs2 =
+          let _1 = _1_inlined3 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 13930 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs2_ = _endpos__1_inlined3_ in
+        let cstrs =
+          let _1 =
+            let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 13939 "parsing/parser.ml"
+             in
+            
+# 854 "parsing/parser.mly"
+    ( xs )
+# 13944 "parsing/parser.ml"
+            
+          in
+          
+# 2814 "parsing/parser.mly"
+    ( _1 )
+# 13950 "parsing/parser.ml"
+          
+        in
+        let id =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 13961 "parsing/parser.ml"
+          
+        in
+        let flag = 
+# 3481 "parsing/parser.mly"
+                                                ( Recursive )
+# 13967 "parsing/parser.ml"
+         in
+        let attrs1 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 13974 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_attrs2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2786 "parsing/parser.mly"
+    (
+      let (kind, priv, manifest) = kind_priv_manifest in
+      let docs = symbol_docs _sloc in
+      let attrs = attrs1 @ attrs2 in
+      let loc = make_loc _sloc in
+      (flag, ext),
+      Type.mk id ~params ~cstrs ~kind ~priv ?manifest ~attrs ~loc ~docs
+    )
+# 13990 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined4;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined4_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = kind_priv_manifest;
+              MenhirLib.EngineTypes.startp = _startpos_kind_priv_manifest_;
+              MenhirLib.EngineTypes.endp = _endpos_kind_priv_manifest_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined3;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = params;
+                  MenhirLib.EngineTypes.startp = _startpos_params_;
+                  MenhirLib.EngineTypes.endp = _endpos_params_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined2;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = ext;
+                        MenhirLib.EngineTypes.startp = _startpos_ext_;
+                        MenhirLib.EngineTypes.endp = _endpos_ext_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined4 : (Parsetree.attributes) = Obj.magic _1_inlined4 in
+        let xs : ((Parsetree.core_type * Parsetree.core_type * Ast_helper.loc) list) = Obj.magic xs in
+        let kind_priv_manifest : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = Obj.magic kind_priv_manifest in
+        let _1_inlined3 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 14062 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined3 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let _1_inlined2 : unit = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined4_ in
+        let _v : ((Asttypes.rec_flag * string Asttypes.loc option) *
+  Parsetree.type_declaration) = let attrs2 =
+          let _1 = _1_inlined4 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 14078 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs2_ = _endpos__1_inlined4_ in
+        let cstrs =
+          let _1 =
+            let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 14087 "parsing/parser.ml"
+             in
+            
+# 854 "parsing/parser.mly"
+    ( xs )
+# 14092 "parsing/parser.ml"
+            
+          in
+          
+# 2814 "parsing/parser.mly"
+    ( _1 )
+# 14098 "parsing/parser.ml"
+          
+        in
+        let id =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 14109 "parsing/parser.ml"
+          
+        in
+        let flag =
+          let _1 = _1_inlined2 in
+          
+# 3482 "parsing/parser.mly"
+                                                ( Nonrecursive )
+# 14117 "parsing/parser.ml"
+          
+        in
+        let attrs1 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 14125 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_attrs2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2786 "parsing/parser.mly"
+    (
+      let (kind, priv, manifest) = kind_priv_manifest in
+      let docs = symbol_docs _sloc in
+      let attrs = attrs1 @ attrs2 in
+      let loc = make_loc _sloc in
+      (flag, ext),
+      Type.mk id ~params ~cstrs ~kind ~priv ?manifest ~attrs ~loc ~docs
+    )
+# 14141 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 14162 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.label) = 
+# 3342 "parsing/parser.mly"
+                              ( _1 )
+# 14170 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 14191 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.label) = 
+# 3343 "parsing/parser.mly"
+                              ( _1 )
+# 14199 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.structure) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (
+# 746 "parsing/parser.mly"
+      (Parsetree.structure)
+# 14231 "parsing/parser.ml"
+        ) = 
+# 1025 "parsing/parser.mly"
+    ( _1 )
+# 14235 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.signature) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (
+# 748 "parsing/parser.mly"
+      (Parsetree.signature)
+# 14267 "parsing/parser.ml"
+        ) = 
+# 1031 "parsing/parser.mly"
+    ( _1 )
+# 14271 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.payload) = Obj.magic _3 in
+        let _2 : (string Asttypes.loc) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.extension) = 
+# 3659 "parsing/parser.mly"
+                                                  ( (_2, _3) )
+# 14317 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined2;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (Parsetree.core_type) = Obj.magic _1_inlined2 in
+        let _3 : unit = Obj.magic _3 in
+        let _1_inlined1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 14365 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined1 in
+        let _1 : (Asttypes.mutable_flag) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (Parsetree.label_declaration) = let _5 =
+          let _1 = _1_inlined3 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 14376 "parsing/parser.ml"
+          
+        in
+        let _endpos__5_ = _endpos__1_inlined3_ in
+        let _4 =
+          let _1 = _1_inlined2 in
+          
+# 3095 "parsing/parser.mly"
+    ( _1 )
+# 14385 "parsing/parser.ml"
+          
+        in
+        let _2 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 14393 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 14401 "parsing/parser.ml"
+          
+        in
+        let _startpos__2_ = _startpos__1_inlined1_ in
+        let _endpos = _endpos__5_ in
+        let _symbolstartpos = if _startpos__1_ != _endpos__1_ then
+          _startpos__1_
+        else
+          _startpos__2_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2972 "parsing/parser.mly"
+      ( let info = symbol_info _endpos in
+        Type.field _2 _4 ~mut:_1 ~attrs:_5 ~loc:(make_loc _sloc) ~info )
+# 14415 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined4;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined4_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined3;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined4 : (Parsetree.attributes) = Obj.magic _1_inlined4 in
+        let _6 : unit = Obj.magic _6 in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (Parsetree.core_type) = Obj.magic _1_inlined2 in
+        let _3 : unit = Obj.magic _3 in
+        let _1_inlined1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 14477 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined1 in
+        let _1 : (Asttypes.mutable_flag) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined4_ in
+        let _v : (Parsetree.label_declaration) = let _7 =
+          let _1 = _1_inlined4 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 14488 "parsing/parser.ml"
+          
+        in
+        let _endpos__7_ = _endpos__1_inlined4_ in
+        let _5 =
+          let _1 = _1_inlined3 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 14497 "parsing/parser.ml"
+          
+        in
+        let _endpos__5_ = _endpos__1_inlined3_ in
+        let _4 =
+          let _1 = _1_inlined2 in
+          
+# 3095 "parsing/parser.mly"
+    ( _1 )
+# 14506 "parsing/parser.ml"
+          
+        in
+        let _2 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 14514 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 14522 "parsing/parser.ml"
+          
+        in
+        let _startpos__2_ = _startpos__1_inlined1_ in
+        let _endpos = _endpos__7_ in
+        let _symbolstartpos = if _startpos__1_ != _endpos__1_ then
+          _startpos__1_
+        else
+          _startpos__2_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2977 "parsing/parser.mly"
+      ( let info =
+          match rhs_info _endpos__5_ with
+          | Some _ as info_before_semi -> info_before_semi
+          | None -> symbol_info _endpos
+       in
+       Type.field _2 _4 ~mut:_1 ~attrs:(_5 @ _7) ~loc:(make_loc _sloc) ~info )
+# 14540 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.label_declaration) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.label_declaration list) = 
+# 2966 "parsing/parser.mly"
+                                                ( [_1] )
+# 14565 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.label_declaration) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.label_declaration list) = 
+# 2967 "parsing/parser.mly"
+                                                ( [_1] )
+# 14590 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.label_declaration list) = Obj.magic _2 in
+        let _1 : (Parsetree.label_declaration) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.label_declaration list) = 
+# 2968 "parsing/parser.mly"
+                                                ( _1 :: _2 )
+# 14622 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 14643 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string * Parsetree.pattern) = let x =
+          let _1 =
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 14656 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2053 "parsing/parser.mly"
+      ( (_1.Location.txt, mkpat ~loc:_sloc (Ppat_var _1)) )
+# 14665 "parsing/parser.ml"
+          
+        in
+        
+# 2045 "parsing/parser.mly"
+      ( x )
+# 14671 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = cty;
+          MenhirLib.EngineTypes.startp = _startpos_cty_;
+          MenhirLib.EngineTypes.endp = _endpos_cty_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let cty : (Parsetree.core_type) = Obj.magic cty in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 14706 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_cty_ in
+        let _v : (string * Parsetree.pattern) = let x =
+          let _1 =
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 14719 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2053 "parsing/parser.mly"
+      ( (_1.Location.txt, mkpat ~loc:_sloc (Ppat_var _1)) )
+# 14728 "parsing/parser.ml"
+          
+        in
+        let _startpos_x_ = _startpos__1_ in
+        let _endpos = _endpos_cty_ in
+        let _symbolstartpos = _startpos_x_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2047 "parsing/parser.mly"
+      ( let lab, pat = x in
+        lab,
+        mkpat ~loc:_sloc (Ppat_constraint (pat, cty)) )
+# 14740 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 14761 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Longident.t) = 
+# 3411 "parsing/parser.mly"
+                                                ( Lident _1 )
+# 14769 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 14802 "parsing/parser.ml"
+        ) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Longident.t) = 
+# 3412 "parsing/parser.mly"
+                                                ( Ldot(_1, _3) )
+# 14812 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.arg_label * Parsetree.expression) = 
+# 2327 "parsing/parser.mly"
+      ( (Nolabel, _1) )
+# 14837 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : (
+# 607 "parsing/parser.mly"
+       (string)
+# 14865 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Asttypes.arg_label * Parsetree.expression) = 
+# 2329 "parsing/parser.mly"
+      ( (Labelled _1, _2) )
+# 14873 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = label;
+          MenhirLib.EngineTypes.startp = _startpos_label_;
+          MenhirLib.EngineTypes.endp = _endpos_label_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let label : (
+# 620 "parsing/parser.mly"
+       (string)
+# 14900 "parsing/parser.ml"
+        ) = Obj.magic label in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_label_ in
+        let _v : (Asttypes.arg_label * Parsetree.expression) = let _loc_label_ = (_startpos_label_, _endpos_label_) in
+        
+# 2331 "parsing/parser.mly"
+      ( let loc = _loc_label_ in
+        (Labelled label, mkexpvar ~loc label) )
+# 14911 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = label;
+          MenhirLib.EngineTypes.startp = _startpos_label_;
+          MenhirLib.EngineTypes.endp = _endpos_label_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let label : (
+# 620 "parsing/parser.mly"
+       (string)
+# 14938 "parsing/parser.ml"
+        ) = Obj.magic label in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_label_ in
+        let _v : (Asttypes.arg_label * Parsetree.expression) = let _loc_label_ = (_startpos_label_, _endpos_label_) in
+        
+# 2334 "parsing/parser.mly"
+      ( let loc = _loc_label_ in
+        (Optional label, mkexpvar ~loc label) )
+# 14949 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : (
+# 637 "parsing/parser.mly"
+       (string)
+# 14977 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Asttypes.arg_label * Parsetree.expression) = 
+# 2337 "parsing/parser.mly"
+      ( (Optional _1, _2) )
+# 14985 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined1 : (Parsetree.expression option) = Obj.magic _1_inlined1 in
+        let _3 : (string * Parsetree.pattern) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = let _4 =
+          let _1 = _1_inlined1 in
+          
+# 2041 "parsing/parser.mly"
+    ( _1 )
+# 15040 "parsing/parser.ml"
+          
+        in
+        
+# 2015 "parsing/parser.mly"
+      ( (Optional (fst _3), _4, snd _3) )
+# 15046 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 15073 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = let _2 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _1 =
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 15088 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2053 "parsing/parser.mly"
+      ( (_1.Location.txt, mkpat ~loc:_sloc (Ppat_var _1)) )
+# 15097 "parsing/parser.ml"
+          
+        in
+        
+# 2017 "parsing/parser.mly"
+      ( (Optional (fst _2), None, snd _2) )
+# 15103 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined1 : (Parsetree.expression option) = Obj.magic _1_inlined1 in
+        let _3 : (Parsetree.pattern) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (
+# 637 "parsing/parser.mly"
+       (string)
+# 15152 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = let _4 =
+          let _1 = _1_inlined1 in
+          
+# 2041 "parsing/parser.mly"
+    ( _1 )
+# 15162 "parsing/parser.ml"
+          
+        in
+        
+# 2019 "parsing/parser.mly"
+      ( (Optional _1, _4, _3) )
+# 15168 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.pattern) = Obj.magic _2 in
+        let _1 : (
+# 637 "parsing/parser.mly"
+       (string)
+# 15196 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = 
+# 2021 "parsing/parser.mly"
+      ( (Optional _1, None, _2) )
+# 15204 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (string * Parsetree.pattern) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = 
+# 2023 "parsing/parser.mly"
+      ( (Labelled (fst _3), None, snd _3) )
+# 15250 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 15277 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = let _2 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _1 =
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 15292 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2053 "parsing/parser.mly"
+      ( (_1.Location.txt, mkpat ~loc:_sloc (Ppat_var _1)) )
+# 15301 "parsing/parser.ml"
+          
+        in
+        
+# 2025 "parsing/parser.mly"
+      ( (Labelled (fst _2), None, snd _2) )
+# 15307 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.pattern) = Obj.magic _2 in
+        let _1 : (
+# 607 "parsing/parser.mly"
+       (string)
+# 15335 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = 
+# 2027 "parsing/parser.mly"
+      ( (Labelled _1, None, _2) )
+# 15343 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = 
+# 2029 "parsing/parser.mly"
+      ( (Nolabel, None, _1) )
+# 15368 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : (string) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.pattern * Parsetree.expression) = let _1 =
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2344 "parsing/parser.mly"
+              ( mkpatvar ~loc:_sloc _1 )
+# 15404 "parsing/parser.ml"
+          
+        in
+        
+# 2348 "parsing/parser.mly"
+      ( (_1, _2) )
+# 15410 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.core_type option * Parsetree.core_type option) = Obj.magic _2 in
+        let _1 : (string) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.pattern * Parsetree.expression) = let _1 =
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2344 "parsing/parser.mly"
+              ( mkpatvar ~loc:_sloc _1 )
+# 15460 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__4_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2350 "parsing/parser.mly"
+      ( let v = _1 in (* PR#7344 *)
+        let t =
+          match _2 with
+            Some t, None -> t
+          | _, Some t -> t
+          | _ -> assert false
+        in
+        let loc = Location.(t.ptyp_loc.loc_start, t.ptyp_loc.loc_end) in
+        let typ = ghtyp ~loc (Ptyp_poly([],t)) in
+        let patloc = (_startpos__1_, _endpos__2_) in
+        (ghpat ~loc:patloc (Ppat_constraint(v, typ)),
+         mkexp_constraint ~loc:_sloc _4 _2) )
+# 15480 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = xs;
+                  MenhirLib.EngineTypes.startp = _startpos_xs_;
+                  MenhirLib.EngineTypes.endp = _endpos_xs_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.expression) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : (Parsetree.core_type) = Obj.magic _5 in
+        let _4 : unit = Obj.magic _4 in
+        let xs : (Asttypes.label Asttypes.loc list) = Obj.magic xs in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (string) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.pattern * Parsetree.expression) = let _3 =
+          let _1 =
+            let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 15549 "parsing/parser.ml"
+             in
+            
+# 872 "parsing/parser.mly"
+    ( xs )
+# 15554 "parsing/parser.ml"
+            
+          in
+          
+# 3077 "parsing/parser.mly"
+    ( _1 )
+# 15560 "parsing/parser.ml"
+          
+        in
+        let _startpos__3_ = _startpos_xs_ in
+        let _1 =
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2344 "parsing/parser.mly"
+              ( mkpatvar ~loc:_sloc _1 )
+# 15571 "parsing/parser.ml"
+          
+        in
+        
+# 2366 "parsing/parser.mly"
+      ( let typloc = (_startpos__3_, _endpos__5_) in
+        let patloc = (_startpos__1_, _endpos__5_) in
+        (ghpat ~loc:patloc
+           (Ppat_constraint(_1, ghtyp ~loc:typloc (Ptyp_poly(_3,_5)))),
+         _7) )
+# 15581 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _8;
+          MenhirLib.EngineTypes.startp = _startpos__8_;
+          MenhirLib.EngineTypes.endp = _endpos__8_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _7;
+            MenhirLib.EngineTypes.startp = _startpos__7_;
+            MenhirLib.EngineTypes.endp = _endpos__7_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _6;
+              MenhirLib.EngineTypes.startp = _startpos__6_;
+              MenhirLib.EngineTypes.endp = _endpos__6_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _5;
+                MenhirLib.EngineTypes.startp = _startpos__5_;
+                MenhirLib.EngineTypes.endp = _endpos__5_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = xs;
+                  MenhirLib.EngineTypes.startp = _startpos_xs_;
+                  MenhirLib.EngineTypes.endp = _endpos_xs_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _3;
+                    MenhirLib.EngineTypes.startp = _startpos__3_;
+                    MenhirLib.EngineTypes.endp = _endpos__3_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _2;
+                      MenhirLib.EngineTypes.startp = _startpos__2_;
+                      MenhirLib.EngineTypes.endp = _endpos__2_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _menhir_s;
+                        MenhirLib.EngineTypes.semv = _1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_;
+                        MenhirLib.EngineTypes.next = _menhir_stack;
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _8 : (Parsetree.expression) = Obj.magic _8 in
+        let _7 : unit = Obj.magic _7 in
+        let _6 : (Parsetree.core_type) = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let xs : (string Asttypes.loc list) = Obj.magic xs in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (string) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__8_ in
+        let _v : (Parsetree.pattern * Parsetree.expression) = let _4 = 
+# 2341 "parsing/parser.mly"
+    ( xs )
+# 15655 "parsing/parser.ml"
+         in
+        let _1 =
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2344 "parsing/parser.mly"
+              ( mkpatvar ~loc:_sloc _1 )
+# 15664 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__8_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2372 "parsing/parser.mly"
+      ( let exp, poly =
+          wrap_type_annotation ~loc:_sloc _4 _6 _8 in
+        let loc = (_startpos__1_, _endpos__6_) in
+        (ghpat ~loc (Ppat_constraint(_1, poly)), exp) )
+# 15676 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern * Parsetree.expression) = 
+# 2377 "parsing/parser.mly"
+      ( (_1, _3) )
+# 15715 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : (Parsetree.expression) = Obj.magic _5 in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.core_type) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.pattern * Parsetree.expression) = 
+# 2379 "parsing/parser.mly"
+      ( let loc = (_startpos__1_, _endpos__3_) in
+        (ghpat ~loc (Ppat_constraint(_1, _3)), _5) )
+# 15769 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = body;
+            MenhirLib.EngineTypes.startp = _startpos_body_;
+            MenhirLib.EngineTypes.endp = _endpos_body_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = rec_flag;
+              MenhirLib.EngineTypes.startp = _startpos_rec_flag_;
+              MenhirLib.EngineTypes.endp = _endpos_rec_flag_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = ext;
+                  MenhirLib.EngineTypes.startp = _startpos_ext_;
+                  MenhirLib.EngineTypes.endp = _endpos_ext_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let body : (Parsetree.pattern * Parsetree.expression) = Obj.magic body in
+        let rec_flag : (Asttypes.rec_flag) = Obj.magic rec_flag in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (let_bindings) = let _1 =
+          let attrs2 =
+            let _1 = _1_inlined2 in
+            
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 15832 "parsing/parser.ml"
+            
+          in
+          let _endpos_attrs2_ = _endpos__1_inlined2_ in
+          let attrs1 =
+            let _1 = _1_inlined1 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 15841 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos_attrs2_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2395 "parsing/parser.mly"
+    (
+      let attrs = attrs1 @ attrs2 in
+      mklbs ~loc:_sloc ext rec_flag (mklb ~loc:_sloc true body attrs)
+    )
+# 15853 "parsing/parser.ml"
+          
+        in
+        
+# 2385 "parsing/parser.mly"
+                                                ( _1 )
+# 15859 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (let_binding) = Obj.magic _2 in
+        let _1 : (let_bindings) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (let_bindings) = 
+# 2386 "parsing/parser.mly"
+                                                ( addlb _1 _2 )
+# 15891 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = body;
+            MenhirLib.EngineTypes.startp = _startpos_body_;
+            MenhirLib.EngineTypes.endp = _endpos_body_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = rec_flag;
+              MenhirLib.EngineTypes.startp = _startpos_rec_flag_;
+              MenhirLib.EngineTypes.endp = _endpos_rec_flag_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let body : (Parsetree.pattern * Parsetree.expression) = Obj.magic body in
+        let rec_flag : (Asttypes.rec_flag) = Obj.magic rec_flag in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (let_bindings) = let _1 =
+          let attrs2 =
+            let _1 = _1_inlined2 in
+            
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 15947 "parsing/parser.ml"
+            
+          in
+          let _endpos_attrs2_ = _endpos__1_inlined2_ in
+          let attrs1 =
+            let _1 = _1_inlined1 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 15956 "parsing/parser.ml"
+            
+          in
+          let ext = 
+# 3649 "parsing/parser.mly"
+                    ( None )
+# 15962 "parsing/parser.ml"
+           in
+          let _endpos = _endpos_attrs2_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2395 "parsing/parser.mly"
+    (
+      let attrs = attrs1 @ attrs2 in
+      mklbs ~loc:_sloc ext rec_flag (mklb ~loc:_sloc true body attrs)
+    )
+# 15973 "parsing/parser.ml"
+          
+        in
+        
+# 2385 "parsing/parser.mly"
+                                                ( _1 )
+# 15979 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = body;
+            MenhirLib.EngineTypes.startp = _startpos_body_;
+            MenhirLib.EngineTypes.endp = _endpos_body_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = rec_flag;
+              MenhirLib.EngineTypes.startp = _startpos_rec_flag_;
+              MenhirLib.EngineTypes.endp = _endpos_rec_flag_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _2;
+                  MenhirLib.EngineTypes.startp = _startpos__2_;
+                  MenhirLib.EngineTypes.endp = _endpos__2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let body : (Parsetree.pattern * Parsetree.expression) = Obj.magic body in
+        let rec_flag : (Asttypes.rec_flag) = Obj.magic rec_flag in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _2 : (string Asttypes.loc) = Obj.magic _2 in
+        let _1_inlined1 : unit = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (let_bindings) = let _1 =
+          let attrs2 =
+            let _1 = _1_inlined3 in
+            
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 16049 "parsing/parser.ml"
+            
+          in
+          let _endpos_attrs2_ = _endpos__1_inlined3_ in
+          let attrs1 =
+            let _1 = _1_inlined2 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 16058 "parsing/parser.ml"
+            
+          in
+          let ext =
+            let (_startpos__1_, _1) = (_startpos__1_inlined1_, _1_inlined1) in
+            let _endpos = _endpos__2_ in
+            let _startpos = _startpos__1_ in
+            let _loc = (_startpos, _endpos) in
+            
+# 3650 "parsing/parser.mly"
+                    ( not_expecting _loc "extension" )
+# 16069 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos_attrs2_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2395 "parsing/parser.mly"
+    (
+      let attrs = attrs1 @ attrs2 in
+      mklbs ~loc:_sloc ext rec_flag (mklb ~loc:_sloc true body attrs)
+    )
+# 16081 "parsing/parser.ml"
+          
+        in
+        
+# 2385 "parsing/parser.mly"
+                                                ( _1 )
+# 16087 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (let_binding) = Obj.magic _2 in
+        let _1 : (let_bindings) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (let_bindings) = 
+# 2386 "parsing/parser.mly"
+                                                ( addlb _1 _2 )
+# 16119 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = 
+# 2057 "parsing/parser.mly"
+      ( _1 )
+# 16144 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.core_type) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 = 
+# 2059 "parsing/parser.mly"
+      ( Ppat_constraint(_1, _3) )
+# 16184 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 16193 "parsing/parser.ml"
+          
+        in
+        
+# 2060 "parsing/parser.mly"
+      ( _1 )
+# 16199 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = exp;
+          MenhirLib.EngineTypes.startp = _startpos_exp_;
+          MenhirLib.EngineTypes.endp = _endpos_exp_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let exp : (Parsetree.expression) = Obj.magic exp in
+        let _1 : (string) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_exp_ in
+        let _v : (Parsetree.pattern * Parsetree.expression) = let pat =
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2344 "parsing/parser.mly"
+              ( mkpatvar ~loc:_sloc _1 )
+# 16235 "parsing/parser.ml"
+          
+        in
+        
+# 2412 "parsing/parser.mly"
+      ( (pat, exp) )
+# 16241 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = exp;
+          MenhirLib.EngineTypes.startp = _startpos_exp_;
+          MenhirLib.EngineTypes.endp = _endpos_exp_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = typ;
+              MenhirLib.EngineTypes.startp = _startpos_typ_;
+              MenhirLib.EngineTypes.endp = _endpos_typ_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = pat;
+                  MenhirLib.EngineTypes.startp = _startpos_pat_;
+                  MenhirLib.EngineTypes.endp = _endpos_pat_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let exp : (Parsetree.expression) = Obj.magic exp in
+        let _4 : unit = Obj.magic _4 in
+        let typ : (Parsetree.core_type) = Obj.magic typ in
+        let _2 : unit = Obj.magic _2 in
+        let pat : (Parsetree.pattern) = Obj.magic pat in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_pat_ in
+        let _endpos = _endpos_exp_ in
+        let _v : (Parsetree.pattern * Parsetree.expression) = 
+# 2414 "parsing/parser.mly"
+      ( let loc = (_startpos_pat_, _endpos_typ_) in
+        (ghpat ~loc (Ppat_constraint(pat, typ)), exp) )
+# 16295 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = exp;
+          MenhirLib.EngineTypes.startp = _startpos_exp_;
+          MenhirLib.EngineTypes.endp = _endpos_exp_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = pat;
+              MenhirLib.EngineTypes.startp = _startpos_pat_;
+              MenhirLib.EngineTypes.endp = _endpos_pat_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let exp : (Parsetree.expression) = Obj.magic exp in
+        let _2 : unit = Obj.magic _2 in
+        let pat : (Parsetree.pattern) = Obj.magic pat in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_pat_ in
+        let _endpos = _endpos_exp_ in
+        let _v : (Parsetree.pattern * Parsetree.expression) = 
+# 2417 "parsing/parser.mly"
+      ( (pat, exp) )
+# 16334 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = body;
+          MenhirLib.EngineTypes.startp = _startpos_body_;
+          MenhirLib.EngineTypes.endp = _endpos_body_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let body : (Parsetree.pattern * Parsetree.expression) = Obj.magic body in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_body_ in
+        let _endpos = _endpos_body_ in
+        let _v : (Parsetree.pattern * Parsetree.expression * Parsetree.binding_op list) = 
+# 2421 "parsing/parser.mly"
+      ( let let_pat, let_exp = body in
+        let_pat, let_exp, [] )
+# 16360 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = body;
+          MenhirLib.EngineTypes.startp = _startpos_body_;
+          MenhirLib.EngineTypes.endp = _endpos_body_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = bindings;
+              MenhirLib.EngineTypes.startp = _startpos_bindings_;
+              MenhirLib.EngineTypes.endp = _endpos_bindings_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let body : (Parsetree.pattern * Parsetree.expression) = Obj.magic body in
+        let _1 : (
+# 603 "parsing/parser.mly"
+       (string)
+# 16394 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let bindings : (Parsetree.pattern * Parsetree.expression * Parsetree.binding_op list) = Obj.magic bindings in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_bindings_ in
+        let _endpos = _endpos_body_ in
+        let _v : (Parsetree.pattern * Parsetree.expression * Parsetree.binding_op list) = let pbop_op =
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 16407 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_body_ in
+        let _symbolstartpos = _startpos_bindings_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2424 "parsing/parser.mly"
+      ( let let_pat, let_exp, rev_ands = bindings in
+        let pbop_pat, pbop_exp = body in
+        let pbop_loc = make_loc _sloc in
+        let and_ = {pbop_op; pbop_pat; pbop_exp; pbop_loc} in
+        let_pat, let_exp, and_ :: rev_ands )
+# 16420 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.class_declaration list) = 
+# 211 "menhir/standard.mly"
+    ( [] )
+# 16438 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = body;
+              MenhirLib.EngineTypes.startp = _startpos_body_;
+              MenhirLib.EngineTypes.endp = _endpos_body_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = params;
+                  MenhirLib.EngineTypes.startp = _startpos_params_;
+                  MenhirLib.EngineTypes.endp = _endpos_params_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = virt;
+                    MenhirLib.EngineTypes.startp = _startpos_virt_;
+                    MenhirLib.EngineTypes.endp = _endpos_virt_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _menhir_s;
+                        MenhirLib.EngineTypes.semv = _1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_;
+                        MenhirLib.EngineTypes.next = _menhir_stack;
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.class_declaration list) = Obj.magic xs in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let body : (Parsetree.class_expr) = Obj.magic body in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 16504 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let virt : (Asttypes.virtual_flag) = Obj.magic virt in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.class_declaration list) = let x =
+          let attrs2 =
+            let _1 = _1_inlined3 in
+            
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 16519 "parsing/parser.ml"
+            
+          in
+          let _endpos_attrs2_ = _endpos__1_inlined3_ in
+          let id =
+            let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 16531 "parsing/parser.ml"
+            
+          in
+          let attrs1 =
+            let _1 = _1_inlined1 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 16539 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos_attrs2_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 1661 "parsing/parser.mly"
+  (
+    let attrs = attrs1 @ attrs2 in
+    let loc = make_loc _sloc in
+    let docs = symbol_docs _sloc in
+    let text = symbol_text _symbolstartpos in
+    Ci.mk id body ~virt ~params ~attrs ~loc ~text ~docs
+  )
+# 16554 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 16560 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.class_description list) = 
+# 211 "menhir/standard.mly"
+    ( [] )
+# 16578 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = cty;
+              MenhirLib.EngineTypes.startp = _startpos_cty_;
+              MenhirLib.EngineTypes.endp = _endpos_cty_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _6;
+                MenhirLib.EngineTypes.startp = _startpos__6_;
+                MenhirLib.EngineTypes.endp = _endpos__6_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = params;
+                    MenhirLib.EngineTypes.startp = _startpos_params_;
+                    MenhirLib.EngineTypes.endp = _endpos_params_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = virt;
+                      MenhirLib.EngineTypes.startp = _startpos_virt_;
+                      MenhirLib.EngineTypes.endp = _endpos_virt_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _1_inlined1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.class_description list) = Obj.magic xs in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let cty : (Parsetree.class_type) = Obj.magic cty in
+        let _6 : unit = Obj.magic _6 in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 16651 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let virt : (Asttypes.virtual_flag) = Obj.magic virt in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.class_description list) = let x =
+          let attrs2 =
+            let _1 = _1_inlined3 in
+            
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 16666 "parsing/parser.ml"
+            
+          in
+          let _endpos_attrs2_ = _endpos__1_inlined3_ in
+          let id =
+            let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 16678 "parsing/parser.ml"
+            
+          in
+          let attrs1 =
+            let _1 = _1_inlined1 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 16686 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos_attrs2_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 1952 "parsing/parser.mly"
+    (
+      let attrs = attrs1 @ attrs2 in
+      let loc = make_loc _sloc in
+      let docs = symbol_docs _sloc in
+      let text = symbol_text _symbolstartpos in
+      Ci.mk id cty ~virt ~params ~attrs ~loc ~text ~docs
+    )
+# 16701 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 16707 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.class_type_declaration list) = 
+# 211 "menhir/standard.mly"
+    ( [] )
+# 16725 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = csig;
+              MenhirLib.EngineTypes.startp = _startpos_csig_;
+              MenhirLib.EngineTypes.endp = _endpos_csig_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _6;
+                MenhirLib.EngineTypes.startp = _startpos__6_;
+                MenhirLib.EngineTypes.endp = _endpos__6_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = params;
+                    MenhirLib.EngineTypes.startp = _startpos_params_;
+                    MenhirLib.EngineTypes.endp = _endpos_params_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = virt;
+                      MenhirLib.EngineTypes.startp = _startpos_virt_;
+                      MenhirLib.EngineTypes.endp = _endpos_virt_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _1_inlined1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.class_type_declaration list) = Obj.magic xs in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let csig : (Parsetree.class_type) = Obj.magic csig in
+        let _6 : unit = Obj.magic _6 in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 16798 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let virt : (Asttypes.virtual_flag) = Obj.magic virt in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.class_type_declaration list) = let x =
+          let attrs2 =
+            let _1 = _1_inlined3 in
+            
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 16813 "parsing/parser.ml"
+            
+          in
+          let _endpos_attrs2_ = _endpos__1_inlined3_ in
+          let id =
+            let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 16825 "parsing/parser.ml"
+            
+          in
+          let attrs1 =
+            let _1 = _1_inlined1 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 16833 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos_attrs2_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 1991 "parsing/parser.mly"
+    (
+      let attrs = attrs1 @ attrs2 in
+      let loc = make_loc _sloc in
+      let docs = symbol_docs _sloc in
+      let text = symbol_text _symbolstartpos in
+      Ci.mk id csig ~virt ~params ~attrs ~loc ~text ~docs
+    )
+# 16848 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 16854 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.module_binding list) = 
+# 211 "menhir/standard.mly"
+    ( [] )
+# 16872 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = body;
+              MenhirLib.EngineTypes.startp = _startpos_body_;
+              MenhirLib.EngineTypes.endp = _endpos_body_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.module_binding list) = Obj.magic xs in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let body : (Parsetree.module_expr) = Obj.magic body in
+        let _1_inlined2 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 16926 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.module_binding list) = let x =
+          let attrs2 =
+            let _1 = _1_inlined3 in
+            
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 16939 "parsing/parser.ml"
+            
+          in
+          let _endpos_attrs2_ = _endpos__1_inlined3_ in
+          let uid =
+            let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 16951 "parsing/parser.ml"
+            
+          in
+          let attrs1 =
+            let _1 = _1_inlined1 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 16959 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos_attrs2_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 1342 "parsing/parser.mly"
+  (
+    let loc = make_loc _sloc in
+    let attrs = attrs1 @ attrs2 in
+    let docs = symbol_docs _sloc in
+    let text = symbol_text _symbolstartpos in
+    Mb.mk uid body ~attrs ~loc ~text ~docs
+  )
+# 16974 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 16980 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.module_declaration list) = 
+# 211 "menhir/standard.mly"
+    ( [] )
+# 16998 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = mty;
+              MenhirLib.EngineTypes.startp = _startpos_mty_;
+              MenhirLib.EngineTypes.endp = _endpos_mty_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.module_declaration list) = Obj.magic xs in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let mty : (Parsetree.module_type) = Obj.magic mty in
+        let _4 : unit = Obj.magic _4 in
+        let _1_inlined2 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 17059 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.module_declaration list) = let x =
+          let attrs2 =
+            let _1 = _1_inlined3 in
+            
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 17072 "parsing/parser.ml"
+            
+          in
+          let _endpos_attrs2_ = _endpos__1_inlined3_ in
+          let uid =
+            let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 17084 "parsing/parser.ml"
+            
+          in
+          let attrs1 =
+            let _1 = _1_inlined1 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 17092 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos_attrs2_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 1619 "parsing/parser.mly"
+  (
+    let attrs = attrs1 @ attrs2 in
+    let docs = symbol_docs _sloc in
+    let loc = make_loc _sloc in
+    let text = symbol_text _symbolstartpos in
+    Md.mk uid mty ~attrs ~loc ~text ~docs
+  )
+# 17107 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 17113 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.attributes) = 
+# 211 "menhir/standard.mly"
+    ( [] )
+# 17131 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = x;
+            MenhirLib.EngineTypes.startp = _startpos_x_;
+            MenhirLib.EngineTypes.endp = _endpos_x_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.attributes) = Obj.magic xs in
+        let x : (Parsetree.attribute) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.attributes) = 
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 17163 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.type_declaration list) = 
+# 211 "menhir/standard.mly"
+    ( [] )
+# 17181 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = xs_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos_xs_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = kind_priv_manifest;
+                MenhirLib.EngineTypes.startp = _startpos_kind_priv_manifest_;
+                MenhirLib.EngineTypes.endp = _endpos_kind_priv_manifest_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = params;
+                    MenhirLib.EngineTypes.startp = _startpos_params_;
+                    MenhirLib.EngineTypes.endp = _endpos_params_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _menhir_s;
+                        MenhirLib.EngineTypes.semv = _1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_;
+                        MenhirLib.EngineTypes.next = _menhir_stack;
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.type_declaration list) = Obj.magic xs in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let xs_inlined1 : ((Parsetree.core_type * Parsetree.core_type * Ast_helper.loc) list) = Obj.magic xs_inlined1 in
+        let kind_priv_manifest : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = Obj.magic kind_priv_manifest in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 17248 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.type_declaration list) = let x =
+          let xs = xs_inlined1 in
+          let attrs2 =
+            let _1 = _1_inlined3 in
+            
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 17263 "parsing/parser.ml"
+            
+          in
+          let _endpos_attrs2_ = _endpos__1_inlined3_ in
+          let cstrs =
+            let _1 =
+              let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 17272 "parsing/parser.ml"
+               in
+              
+# 854 "parsing/parser.mly"
+    ( xs )
+# 17277 "parsing/parser.ml"
+              
+            in
+            
+# 2814 "parsing/parser.mly"
+    ( _1 )
+# 17283 "parsing/parser.ml"
+            
+          in
+          let id =
+            let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 17294 "parsing/parser.ml"
+            
+          in
+          let attrs1 =
+            let _1 = _1_inlined1 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 17302 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos_attrs2_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2803 "parsing/parser.mly"
+    (
+      let (kind, priv, manifest) = kind_priv_manifest in
+      let docs = symbol_docs _sloc in
+      let attrs = attrs1 @ attrs2 in
+      let loc = make_loc _sloc in
+      let text = symbol_text _symbolstartpos in
+      Type.mk id ~params ~cstrs ~kind ~priv ?manifest ~attrs ~loc ~docs ~text
+    )
+# 17318 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 17324 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.type_declaration list) = 
+# 211 "menhir/standard.mly"
+    ( [] )
+# 17342 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined4;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined4_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = xs_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos_xs_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined3;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined2;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = params;
+                      MenhirLib.EngineTypes.startp = _startpos_params_;
+                      MenhirLib.EngineTypes.endp = _endpos_params_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _1_inlined1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.type_declaration list) = Obj.magic xs in
+        let _1_inlined4 : (Parsetree.attributes) = Obj.magic _1_inlined4 in
+        let xs_inlined1 : ((Parsetree.core_type * Parsetree.core_type * Ast_helper.loc) list) = Obj.magic xs_inlined1 in
+        let _2 : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = Obj.magic _2 in
+        let _1_inlined3 : unit = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 17416 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.type_declaration list) = let x =
+          let xs = xs_inlined1 in
+          let attrs2 =
+            let _1 = _1_inlined4 in
+            
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 17431 "parsing/parser.ml"
+            
+          in
+          let _endpos_attrs2_ = _endpos__1_inlined4_ in
+          let cstrs =
+            let _1 =
+              let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 17440 "parsing/parser.ml"
+               in
+              
+# 854 "parsing/parser.mly"
+    ( xs )
+# 17445 "parsing/parser.ml"
+              
+            in
+            
+# 2814 "parsing/parser.mly"
+    ( _1 )
+# 17451 "parsing/parser.ml"
+            
+          in
+          let kind_priv_manifest =
+            let _1 = _1_inlined3 in
+            
+# 2849 "parsing/parser.mly"
+      ( _2 )
+# 17459 "parsing/parser.ml"
+            
+          in
+          let id =
+            let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 17470 "parsing/parser.ml"
+            
+          in
+          let attrs1 =
+            let _1 = _1_inlined1 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 17478 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos_attrs2_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2803 "parsing/parser.mly"
+    (
+      let (kind, priv, manifest) = kind_priv_manifest in
+      let docs = symbol_docs _sloc in
+      let attrs = attrs1 @ attrs2 in
+      let loc = make_loc _sloc in
+      let text = symbol_text _symbolstartpos in
+      Type.mk id ~params ~cstrs ~kind ~priv ?manifest ~attrs ~loc ~docs ~text
+    )
+# 17494 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 17500 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.attributes) = 
+# 211 "menhir/standard.mly"
+    ( [] )
+# 17518 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = x;
+            MenhirLib.EngineTypes.startp = _startpos_x_;
+            MenhirLib.EngineTypes.endp = _endpos_x_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.attributes) = Obj.magic xs in
+        let x : (Parsetree.attribute) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.attributes) = 
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 17550 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.signature_item list list) = 
+# 211 "menhir/standard.mly"
+    ( [] )
+# 17568 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.signature_item list list) = Obj.magic xs in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.signature_item list list) = let x =
+          let _1 =
+            let _startpos = _startpos__1_ in
+            
+# 780 "parsing/parser.mly"
+  ( text_sig _startpos )
+# 17603 "parsing/parser.ml"
+            
+          in
+          
+# 1480 "parsing/parser.mly"
+      ( _1 )
+# 17609 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 17615 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.signature_item list list) = Obj.magic xs in
+        let _1 : (Parsetree.signature_item) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.signature_item list list) = let x =
+          let _1 =
+            let _startpos = _startpos__1_ in
+            
+# 778 "parsing/parser.mly"
+  ( text_sig _startpos @ [_1] )
+# 17650 "parsing/parser.ml"
+            
+          in
+          
+# 1480 "parsing/parser.mly"
+      ( _1 )
+# 17656 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 17662 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.structure_item list list) = 
+# 211 "menhir/standard.mly"
+    ( [] )
+# 17680 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.structure_item list list) = Obj.magic xs in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.structure_item list list) = let x =
+          let _1 =
+            let ys =
+              let items = 
+# 840 "parsing/parser.mly"
+    ( [] )
+# 17715 "parsing/parser.ml"
+               in
+              
+# 1225 "parsing/parser.mly"
+    ( items )
+# 17720 "parsing/parser.ml"
+              
+            in
+            let xs =
+              let _startpos = _startpos__1_ in
+              
+# 776 "parsing/parser.mly"
+  ( text_str _startpos )
+# 17728 "parsing/parser.ml"
+              
+            in
+            
+# 267 "menhir/standard.mly"
+    ( xs @ ys )
+# 17734 "parsing/parser.ml"
+            
+          in
+          
+# 1241 "parsing/parser.mly"
+      ( _1 )
+# 17740 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 17746 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = e;
+              MenhirLib.EngineTypes.startp = _startpos_e_;
+              MenhirLib.EngineTypes.endp = _endpos_e_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.structure_item list list) = Obj.magic xs in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let e : (Parsetree.expression) = Obj.magic e in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.structure_item list list) = let x =
+          let _1 =
+            let ys =
+              let (_endpos__1_, _1) = (_endpos__1_inlined1_, _1_inlined1) in
+              let items =
+                let x =
+                  let _1 =
+                    let _1 =
+                      let attrs = 
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 17800 "parsing/parser.ml"
+                       in
+                      
+# 1232 "parsing/parser.mly"
+    ( mkstrexp e attrs )
+# 17805 "parsing/parser.ml"
+                      
+                    in
+                    let _startpos__1_ = _startpos_e_ in
+                    let _startpos = _startpos__1_ in
+                    
+# 774 "parsing/parser.mly"
+  ( text_str _startpos @ [_1] )
+# 17813 "parsing/parser.ml"
+                    
+                  in
+                  let _startpos__1_ = _startpos_e_ in
+                  let _endpos = _endpos__1_ in
+                  let _startpos = _startpos__1_ in
+                  
+# 793 "parsing/parser.mly"
+  ( mark_rhs_docs _startpos _endpos;
+    _1 )
+# 17823 "parsing/parser.ml"
+                  
+                in
+                
+# 842 "parsing/parser.mly"
+    ( x )
+# 17829 "parsing/parser.ml"
+                
+              in
+              
+# 1225 "parsing/parser.mly"
+    ( items )
+# 17835 "parsing/parser.ml"
+              
+            in
+            let xs =
+              let _startpos = _startpos__1_ in
+              
+# 776 "parsing/parser.mly"
+  ( text_str _startpos )
+# 17843 "parsing/parser.ml"
+              
+            in
+            
+# 267 "menhir/standard.mly"
+    ( xs @ ys )
+# 17849 "parsing/parser.ml"
+            
+          in
+          
+# 1241 "parsing/parser.mly"
+      ( _1 )
+# 17855 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 17861 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.structure_item list list) = Obj.magic xs in
+        let _1 : (Parsetree.structure_item) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.structure_item list list) = let x =
+          let _1 =
+            let _startpos = _startpos__1_ in
+            
+# 774 "parsing/parser.mly"
+  ( text_str _startpos @ [_1] )
+# 17896 "parsing/parser.ml"
+            
+          in
+          
+# 1241 "parsing/parser.mly"
+      ( _1 )
+# 17902 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 17908 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.class_type_field list list) = 
+# 211 "menhir/standard.mly"
+    ( [] )
+# 17926 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.class_type_field list list) = Obj.magic xs in
+        let _1 : (Parsetree.class_type_field) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.class_type_field list list) = let x =
+          let _startpos = _startpos__1_ in
+          
+# 788 "parsing/parser.mly"
+  ( text_csig _startpos @ [_1] )
+# 17960 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 17966 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.class_field list list) = 
+# 211 "menhir/standard.mly"
+    ( [] )
+# 17984 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.class_field list list) = Obj.magic xs in
+        let _1 : (Parsetree.class_field) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.class_field list list) = let x =
+          let _startpos = _startpos__1_ in
+          
+# 786 "parsing/parser.mly"
+  ( text_cstr _startpos @ [_1] )
+# 18018 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 18024 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.structure_item list list) = 
+# 211 "menhir/standard.mly"
+    ( [] )
+# 18042 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.structure_item list list) = Obj.magic xs in
+        let _1 : (Parsetree.structure_item) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.structure_item list list) = let x =
+          let _startpos = _startpos__1_ in
+          
+# 774 "parsing/parser.mly"
+  ( text_str _startpos @ [_1] )
+# 18076 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 18082 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.toplevel_phrase list list) = 
+# 211 "menhir/standard.mly"
+    ( [] )
+# 18100 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.toplevel_phrase list list) = Obj.magic xs in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.toplevel_phrase list list) = let x =
+          let _1 =
+            let x =
+              let _1 = 
+# 840 "parsing/parser.mly"
+    ( [] )
+# 18135 "parsing/parser.ml"
+               in
+              
+# 1070 "parsing/parser.mly"
+    ( _1 )
+# 18140 "parsing/parser.ml"
+              
+            in
+            
+# 183 "menhir/standard.mly"
+    ( x )
+# 18146 "parsing/parser.ml"
+            
+          in
+          
+# 1082 "parsing/parser.mly"
+      ( _1 )
+# 18152 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 18158 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = e;
+              MenhirLib.EngineTypes.startp = _startpos_e_;
+              MenhirLib.EngineTypes.endp = _endpos_e_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.toplevel_phrase list list) = Obj.magic xs in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let e : (Parsetree.expression) = Obj.magic e in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.toplevel_phrase list list) = let x =
+          let _1 =
+            let x =
+              let _1 = _1_inlined1 in
+              let _1 =
+                let x =
+                  let _1 =
+                    let _1 =
+                      let attrs = 
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 18212 "parsing/parser.ml"
+                       in
+                      
+# 1232 "parsing/parser.mly"
+    ( mkstrexp e attrs )
+# 18217 "parsing/parser.ml"
+                      
+                    in
+                    
+# 784 "parsing/parser.mly"
+  ( Ptop_def [_1] )
+# 18223 "parsing/parser.ml"
+                    
+                  in
+                  let _startpos__1_ = _startpos_e_ in
+                  let _startpos = _startpos__1_ in
+                  
+# 782 "parsing/parser.mly"
+  ( text_def _startpos @ [_1] )
+# 18231 "parsing/parser.ml"
+                  
+                in
+                
+# 842 "parsing/parser.mly"
+    ( x )
+# 18237 "parsing/parser.ml"
+                
+              in
+              
+# 1070 "parsing/parser.mly"
+    ( _1 )
+# 18243 "parsing/parser.ml"
+              
+            in
+            
+# 183 "menhir/standard.mly"
+    ( x )
+# 18249 "parsing/parser.ml"
+            
+          in
+          
+# 1082 "parsing/parser.mly"
+      ( _1 )
+# 18255 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 18261 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.toplevel_phrase list list) = Obj.magic xs in
+        let _1 : (Parsetree.structure_item) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.toplevel_phrase list list) = let x =
+          let _1 =
+            let _1 = 
+# 784 "parsing/parser.mly"
+  ( Ptop_def [_1] )
+# 18295 "parsing/parser.ml"
+             in
+            let _startpos = _startpos__1_ in
+            
+# 782 "parsing/parser.mly"
+  ( text_def _startpos @ [_1] )
+# 18301 "parsing/parser.ml"
+            
+          in
+          
+# 1082 "parsing/parser.mly"
+      ( _1 )
+# 18307 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 18313 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.toplevel_phrase list list) = Obj.magic xs in
+        let _1 : (Parsetree.toplevel_phrase) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.toplevel_phrase list list) = let x =
+          let _1 =
+            let _1 =
+              let _endpos = _endpos__1_ in
+              let _startpos = _startpos__1_ in
+              
+# 793 "parsing/parser.mly"
+  ( mark_rhs_docs _startpos _endpos;
+    _1 )
+# 18351 "parsing/parser.ml"
+              
+            in
+            let _startpos = _startpos__1_ in
+            
+# 782 "parsing/parser.mly"
+  ( text_def _startpos @ [_1] )
+# 18358 "parsing/parser.ml"
+            
+          in
+          
+# 1082 "parsing/parser.mly"
+      ( _1 )
+# 18364 "parsing/parser.ml"
+          
+        in
+        
+# 213 "menhir/standard.mly"
+    ( x :: xs )
+# 18370 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = opat;
+          MenhirLib.EngineTypes.startp = _startpos_opat_;
+          MenhirLib.EngineTypes.endp = _endpos_opat_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = octy;
+            MenhirLib.EngineTypes.startp = _startpos_octy_;
+            MenhirLib.EngineTypes.endp = _endpos_octy_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let opat : (Parsetree.pattern option) = Obj.magic opat in
+        let octy : (Parsetree.core_type option) = Obj.magic octy in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_opat_ in
+        let _v : ((Longident.t Asttypes.loc * Parsetree.pattern) list * unit option) = let _2 = 
+# 124 "menhir/standard.mly"
+    ( None )
+# 18409 "parsing/parser.ml"
+         in
+        let x =
+          let label =
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 18419 "parsing/parser.ml"
+            
+          in
+          let _startpos_label_ = _startpos__1_ in
+          let _endpos = _endpos_opat_ in
+          let _symbolstartpos = _startpos_label_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2692 "parsing/parser.mly"
+    ( let pat =
+        match opat with
+        | None ->
+            (* No pattern; this is a pun. Desugar it. *)
+            pat_of_label ~loc:_sloc label
+        | Some pat ->
+            pat
+      in
+      label, mkpat_opt_constraint ~loc:_sloc pat octy
+    )
+# 18438 "parsing/parser.ml"
+          
+        in
+        
+# 1009 "parsing/parser.mly"
+    ( [x], None )
+# 18444 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = opat;
+            MenhirLib.EngineTypes.startp = _startpos_opat_;
+            MenhirLib.EngineTypes.endp = _endpos_opat_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = octy;
+              MenhirLib.EngineTypes.startp = _startpos_octy_;
+              MenhirLib.EngineTypes.endp = _endpos_octy_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let x : unit = Obj.magic x in
+        let opat : (Parsetree.pattern option) = Obj.magic opat in
+        let octy : (Parsetree.core_type option) = Obj.magic octy in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_x_ in
+        let _v : ((Longident.t Asttypes.loc * Parsetree.pattern) list * unit option) = let _2 = 
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 18490 "parsing/parser.ml"
+         in
+        let x =
+          let label =
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 18500 "parsing/parser.ml"
+            
+          in
+          let _startpos_label_ = _startpos__1_ in
+          let _endpos = _endpos_opat_ in
+          let _symbolstartpos = _startpos_label_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2692 "parsing/parser.mly"
+    ( let pat =
+        match opat with
+        | None ->
+            (* No pattern; this is a pun. Desugar it. *)
+            pat_of_label ~loc:_sloc label
+        | Some pat ->
+            pat
+      in
+      label, mkpat_opt_constraint ~loc:_sloc pat octy
+    )
+# 18519 "parsing/parser.ml"
+          
+        in
+        
+# 1009 "parsing/parser.mly"
+    ( [x], None )
+# 18525 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = y;
+            MenhirLib.EngineTypes.startp = _startpos_y_;
+            MenhirLib.EngineTypes.endp = _endpos_y_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = opat;
+                MenhirLib.EngineTypes.startp = _startpos_opat_;
+                MenhirLib.EngineTypes.endp = _endpos_opat_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = octy;
+                  MenhirLib.EngineTypes.startp = _startpos_octy_;
+                  MenhirLib.EngineTypes.endp = _endpos_octy_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : (unit option) = Obj.magic _4 in
+        let y : unit = Obj.magic y in
+        let _2 : unit = Obj.magic _2 in
+        let opat : (Parsetree.pattern option) = Obj.magic opat in
+        let octy : (Parsetree.core_type option) = Obj.magic octy in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : ((Longident.t Asttypes.loc * Parsetree.pattern) list * unit option) = let x =
+          let label =
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 18590 "parsing/parser.ml"
+            
+          in
+          let _startpos_label_ = _startpos__1_ in
+          let _endpos = _endpos_opat_ in
+          let _symbolstartpos = _startpos_label_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2692 "parsing/parser.mly"
+    ( let pat =
+        match opat with
+        | None ->
+            (* No pattern; this is a pun. Desugar it. *)
+            pat_of_label ~loc:_sloc label
+        | Some pat ->
+            pat
+      in
+      label, mkpat_opt_constraint ~loc:_sloc pat octy
+    )
+# 18609 "parsing/parser.ml"
+          
+        in
+        
+# 1011 "parsing/parser.mly"
+    ( [x], Some y )
+# 18615 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = tail;
+          MenhirLib.EngineTypes.startp = _startpos_tail_;
+          MenhirLib.EngineTypes.endp = _endpos_tail_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = opat;
+              MenhirLib.EngineTypes.startp = _startpos_opat_;
+              MenhirLib.EngineTypes.endp = _endpos_opat_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = octy;
+                MenhirLib.EngineTypes.startp = _startpos_octy_;
+                MenhirLib.EngineTypes.endp = _endpos_octy_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let tail : ((Longident.t Asttypes.loc * Parsetree.pattern) list * unit option) = Obj.magic tail in
+        let _2 : unit = Obj.magic _2 in
+        let opat : (Parsetree.pattern option) = Obj.magic opat in
+        let octy : (Parsetree.core_type option) = Obj.magic octy in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_tail_ in
+        let _v : ((Longident.t Asttypes.loc * Parsetree.pattern) list * unit option) = let x =
+          let label =
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 18673 "parsing/parser.ml"
+            
+          in
+          let _startpos_label_ = _startpos__1_ in
+          let _endpos = _endpos_opat_ in
+          let _symbolstartpos = _startpos_label_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2692 "parsing/parser.mly"
+    ( let pat =
+        match opat with
+        | None ->
+            (* No pattern; this is a pun. Desugar it. *)
+            pat_of_label ~loc:_sloc label
+        | Some pat ->
+            pat
+      in
+      label, mkpat_opt_constraint ~loc:_sloc pat octy
+    )
+# 18692 "parsing/parser.ml"
+          
+        in
+        
+# 1015 "parsing/parser.mly"
+    ( let xs, y = tail in
+      x :: xs, y )
+# 18699 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.case) = 
+# 2450 "parsing/parser.mly"
+      ( Exp.case _1 _3 )
+# 18738 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : (Parsetree.expression) = Obj.magic _5 in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.case) = 
+# 2452 "parsing/parser.mly"
+      ( Exp.case _1 ~guard:_3 _5 )
+# 18791 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.case) = let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        
+# 2454 "parsing/parser.mly"
+      ( Exp.case _1 (Exp.unreachable ~loc:(make_loc _loc__3_) ()) )
+# 18831 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = tail;
+          MenhirLib.EngineTypes.startp = _startpos_tail_;
+          MenhirLib.EngineTypes.endp = _endpos_tail_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let tail : (Parsetree.object_field list * Asttypes.closed_flag) = Obj.magic tail in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.core_type) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 18894 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_tail_ in
+        let _v : (Parsetree.object_field list * Asttypes.closed_flag) = let head =
+          let _6 =
+            let _1 = _1_inlined3 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 18905 "parsing/parser.ml"
+            
+          in
+          let _endpos__6_ = _endpos__1_inlined3_ in
+          let _4 =
+            let _1 = _1_inlined2 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 18914 "parsing/parser.ml"
+            
+          in
+          let _endpos__4_ = _endpos__1_inlined2_ in
+          let _3 =
+            let _1 = _1_inlined1 in
+            
+# 3095 "parsing/parser.mly"
+    ( _1 )
+# 18923 "parsing/parser.ml"
+            
+          in
+          let _1 =
+            let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 18930 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 18938 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__6_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 3305 "parsing/parser.mly"
+    ( let info =
+        match rhs_info _endpos__4_ with
+        | Some _ as info_before_semi -> info_before_semi
+        | None -> symbol_info _endpos
+      in
+      let attrs = add_info_attrs info (_4 @ _6) in
+      Of.tag ~loc:(make_loc _sloc) ~attrs _1 _3 )
+# 18953 "parsing/parser.ml"
+          
+        in
+        
+# 3286 "parsing/parser.mly"
+      ( let (f, c) = tail in (head :: f, c) )
+# 18959 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = tail;
+          MenhirLib.EngineTypes.startp = _startpos_tail_;
+          MenhirLib.EngineTypes.endp = _endpos_tail_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = ty;
+              MenhirLib.EngineTypes.startp = _startpos_ty_;
+              MenhirLib.EngineTypes.endp = _endpos_ty_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let tail : (Parsetree.object_field list * Asttypes.closed_flag) = Obj.magic tail in
+        let _2 : unit = Obj.magic _2 in
+        let ty : (Parsetree.core_type) = Obj.magic ty in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_ty_ in
+        let _endpos = _endpos_tail_ in
+        let _v : (Parsetree.object_field list * Asttypes.closed_flag) = let head =
+          let _endpos = _endpos_ty_ in
+          let _symbolstartpos = _startpos_ty_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 3316 "parsing/parser.mly"
+    ( Of.inherit_ ~loc:(make_loc _sloc) ty )
+# 19002 "parsing/parser.ml"
+          
+        in
+        
+# 3286 "parsing/parser.mly"
+      ( let (f, c) = tail in (head :: f, c) )
+# 19008 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _5;
+            MenhirLib.EngineTypes.startp = _startpos__5_;
+            MenhirLib.EngineTypes.endp = _endpos__5_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _2;
+                  MenhirLib.EngineTypes.startp = _startpos__2_;
+                  MenhirLib.EngineTypes.endp = _endpos__2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.core_type) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 19064 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (Parsetree.object_field list * Asttypes.closed_flag) = let head =
+          let _6 =
+            let _1 = _1_inlined3 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 19075 "parsing/parser.ml"
+            
+          in
+          let _endpos__6_ = _endpos__1_inlined3_ in
+          let _4 =
+            let _1 = _1_inlined2 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 19084 "parsing/parser.ml"
+            
+          in
+          let _endpos__4_ = _endpos__1_inlined2_ in
+          let _3 =
+            let _1 = _1_inlined1 in
+            
+# 3095 "parsing/parser.mly"
+    ( _1 )
+# 19093 "parsing/parser.ml"
+            
+          in
+          let _1 =
+            let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 19100 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 19108 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__6_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 3305 "parsing/parser.mly"
+    ( let info =
+        match rhs_info _endpos__4_ with
+        | Some _ as info_before_semi -> info_before_semi
+        | None -> symbol_info _endpos
+      in
+      let attrs = add_info_attrs info (_4 @ _6) in
+      Of.tag ~loc:(make_loc _sloc) ~attrs _1 _3 )
+# 19123 "parsing/parser.ml"
+          
+        in
+        
+# 3289 "parsing/parser.mly"
+      ( [head], Closed )
+# 19129 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = ty;
+            MenhirLib.EngineTypes.startp = _startpos_ty_;
+            MenhirLib.EngineTypes.endp = _endpos_ty_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let ty : (Parsetree.core_type) = Obj.magic ty in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_ty_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.object_field list * Asttypes.closed_flag) = let head =
+          let _endpos = _endpos_ty_ in
+          let _symbolstartpos = _startpos_ty_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 3316 "parsing/parser.mly"
+    ( Of.inherit_ ~loc:(make_loc _sloc) ty )
+# 19165 "parsing/parser.ml"
+          
+        in
+        
+# 3289 "parsing/parser.mly"
+      ( [head], Closed )
+# 19171 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.core_type) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 19213 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.object_field list * Asttypes.closed_flag) = let head =
+          let _4 =
+            let _1 = _1_inlined2 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 19224 "parsing/parser.ml"
+            
+          in
+          let _endpos__4_ = _endpos__1_inlined2_ in
+          let _3 =
+            let _1 = _1_inlined1 in
+            
+# 3095 "parsing/parser.mly"
+    ( _1 )
+# 19233 "parsing/parser.ml"
+            
+          in
+          let _1 =
+            let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 19240 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 19248 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__4_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 3298 "parsing/parser.mly"
+    ( let info = symbol_info _endpos in
+      let attrs = add_info_attrs info _4 in
+      Of.tag ~loc:(make_loc _sloc) ~attrs _1 _3 )
+# 19259 "parsing/parser.ml"
+          
+        in
+        
+# 3292 "parsing/parser.mly"
+      ( [head], Closed )
+# 19265 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = ty;
+          MenhirLib.EngineTypes.startp = _startpos_ty_;
+          MenhirLib.EngineTypes.endp = _endpos_ty_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let ty : (Parsetree.core_type) = Obj.magic ty in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_ty_ in
+        let _endpos = _endpos_ty_ in
+        let _v : (Parsetree.object_field list * Asttypes.closed_flag) = let head =
+          let _endpos = _endpos_ty_ in
+          let _symbolstartpos = _startpos_ty_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 3316 "parsing/parser.mly"
+    ( Of.inherit_ ~loc:(make_loc _sloc) ty )
+# 19294 "parsing/parser.ml"
+          
+        in
+        
+# 3292 "parsing/parser.mly"
+      ( [head], Closed )
+# 19300 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.object_field list * Asttypes.closed_flag) = 
+# 3294 "parsing/parser.mly"
+      ( [], Open )
+# 19325 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _5;
+            MenhirLib.EngineTypes.startp = _startpos__5_;
+            MenhirLib.EngineTypes.endp = _endpos__5_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = private_;
+                MenhirLib.EngineTypes.startp = _startpos_private__;
+                MenhirLib.EngineTypes.endp = _endpos_private__;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.core_type) = Obj.magic _1_inlined2 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 19372 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined1 in
+        let private_ : (Asttypes.private_flag) = Obj.magic private_ in
+        let _1 : (Parsetree.attributes) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : ((Asttypes.label Asttypes.loc * Asttypes.private_flag *
+   Parsetree.class_field_kind) *
+  Parsetree.attributes) = let ty =
+          let _1 = _1_inlined2 in
+          
+# 3091 "parsing/parser.mly"
+    ( _1 )
+# 19386 "parsing/parser.ml"
+          
+        in
+        let label =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 19394 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 19402 "parsing/parser.ml"
+          
+        in
+        let attrs = 
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 19408 "parsing/parser.ml"
+         in
+        let _1 = 
+# 3541 "parsing/parser.mly"
+                                                ( Fresh )
+# 19413 "parsing/parser.ml"
+         in
+        
+# 1799 "parsing/parser.mly"
+      ( (label, private_, Cfk_virtual ty), attrs )
+# 19418 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : (Parsetree.expression) = Obj.magic _5 in
+        let _1_inlined1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 19458 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined1 in
+        let _3 : (Asttypes.private_flag) = Obj.magic _3 in
+        let _1 : (Parsetree.attributes) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : ((Asttypes.label Asttypes.loc * Asttypes.private_flag *
+   Parsetree.class_field_kind) *
+  Parsetree.attributes) = let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 19472 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 19480 "parsing/parser.ml"
+          
+        in
+        let _2 = 
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 19486 "parsing/parser.ml"
+         in
+        let _1 = 
+# 3544 "parsing/parser.mly"
+                                                ( Fresh )
+# 19491 "parsing/parser.ml"
+         in
+        
+# 1801 "parsing/parser.mly"
+      ( let e = _5 in
+        let loc = Location.(e.pexp_loc.loc_start, e.pexp_loc.loc_end) in
+        (_4, _3,
+        Cfk_concrete (_1, ghexp ~loc (Pexp_poly (e, None)))), _2 )
+# 19499 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined2;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : (Parsetree.expression) = Obj.magic _5 in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 19545 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _3 : (Asttypes.private_flag) = Obj.magic _3 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : ((Asttypes.label Asttypes.loc * Asttypes.private_flag *
+   Parsetree.class_field_kind) *
+  Parsetree.attributes) = let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 19560 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 19568 "parsing/parser.ml"
+          
+        in
+        let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 19576 "parsing/parser.ml"
+          
+        in
+        let _1 = 
+# 3545 "parsing/parser.mly"
+                                                ( Override )
+# 19582 "parsing/parser.ml"
+         in
+        
+# 1801 "parsing/parser.mly"
+      ( let e = _5 in
+        let loc = Location.(e.pexp_loc.loc_start, e.pexp_loc.loc_end) in
+        (_4, _3,
+        Cfk_concrete (_1, ghexp ~loc (Pexp_poly (e, None)))), _2 )
+# 19590 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _8;
+          MenhirLib.EngineTypes.startp = _startpos__8_;
+          MenhirLib.EngineTypes.endp = _endpos__8_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _7;
+            MenhirLib.EngineTypes.startp = _startpos__7_;
+            MenhirLib.EngineTypes.endp = _endpos__7_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _5;
+                MenhirLib.EngineTypes.startp = _startpos__5_;
+                MenhirLib.EngineTypes.endp = _endpos__5_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _3;
+                    MenhirLib.EngineTypes.startp = _startpos__3_;
+                    MenhirLib.EngineTypes.endp = _endpos__3_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _8 : (Parsetree.expression) = Obj.magic _8 in
+        let _7 : unit = Obj.magic _7 in
+        let _1_inlined2 : (Parsetree.core_type) = Obj.magic _1_inlined2 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 19651 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined1 in
+        let _3 : (Asttypes.private_flag) = Obj.magic _3 in
+        let _1 : (Parsetree.attributes) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__8_ in
+        let _v : ((Asttypes.label Asttypes.loc * Asttypes.private_flag *
+   Parsetree.class_field_kind) *
+  Parsetree.attributes) = let _6 =
+          let _1 = _1_inlined2 in
+          
+# 3091 "parsing/parser.mly"
+    ( _1 )
+# 19665 "parsing/parser.ml"
+          
+        in
+        let _startpos__6_ = _startpos__1_inlined2_ in
+        let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 19674 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 19682 "parsing/parser.ml"
+          
+        in
+        let _2 = 
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 19688 "parsing/parser.ml"
+         in
+        let _1 = 
+# 3544 "parsing/parser.mly"
+                                                ( Fresh )
+# 19693 "parsing/parser.ml"
+         in
+        
+# 1807 "parsing/parser.mly"
+      ( let poly_exp =
+          let loc = (_startpos__6_, _endpos__8_) in
+          ghexp ~loc (Pexp_poly(_8, Some _6)) in
+        (_4, _3, Cfk_concrete (_1, poly_exp)), _2 )
+# 19701 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _8;
+          MenhirLib.EngineTypes.startp = _startpos__8_;
+          MenhirLib.EngineTypes.endp = _endpos__8_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _7;
+            MenhirLib.EngineTypes.startp = _startpos__7_;
+            MenhirLib.EngineTypes.endp = _endpos__7_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined3;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _5;
+                MenhirLib.EngineTypes.startp = _startpos__5_;
+                MenhirLib.EngineTypes.endp = _endpos__5_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _3;
+                    MenhirLib.EngineTypes.startp = _startpos__3_;
+                    MenhirLib.EngineTypes.endp = _endpos__3_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _menhir_s;
+                        MenhirLib.EngineTypes.semv = _1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_;
+                        MenhirLib.EngineTypes.next = _menhir_stack;
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _8 : (Parsetree.expression) = Obj.magic _8 in
+        let _7 : unit = Obj.magic _7 in
+        let _1_inlined3 : (Parsetree.core_type) = Obj.magic _1_inlined3 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 19768 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _3 : (Asttypes.private_flag) = Obj.magic _3 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__8_ in
+        let _v : ((Asttypes.label Asttypes.loc * Asttypes.private_flag *
+   Parsetree.class_field_kind) *
+  Parsetree.attributes) = let _6 =
+          let _1 = _1_inlined3 in
+          
+# 3091 "parsing/parser.mly"
+    ( _1 )
+# 19783 "parsing/parser.ml"
+          
+        in
+        let _startpos__6_ = _startpos__1_inlined3_ in
+        let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 19792 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 19800 "parsing/parser.ml"
+          
+        in
+        let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 19808 "parsing/parser.ml"
+          
+        in
+        let _1 = 
+# 3545 "parsing/parser.mly"
+                                                ( Override )
+# 19814 "parsing/parser.ml"
+         in
+        
+# 1807 "parsing/parser.mly"
+      ( let poly_exp =
+          let loc = (_startpos__6_, _endpos__8_) in
+          ghexp ~loc (Pexp_poly(_8, Some _6)) in
+        (_4, _3, Cfk_concrete (_1, poly_exp)), _2 )
+# 19822 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _11;
+          MenhirLib.EngineTypes.startp = _startpos__11_;
+          MenhirLib.EngineTypes.endp = _endpos__11_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _10;
+            MenhirLib.EngineTypes.startp = _startpos__10_;
+            MenhirLib.EngineTypes.endp = _endpos__10_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _9;
+              MenhirLib.EngineTypes.startp = _startpos__9_;
+              MenhirLib.EngineTypes.endp = _endpos__9_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _8;
+                MenhirLib.EngineTypes.startp = _startpos__8_;
+                MenhirLib.EngineTypes.endp = _endpos__8_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = xs;
+                  MenhirLib.EngineTypes.startp = _startpos_xs_;
+                  MenhirLib.EngineTypes.endp = _endpos_xs_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _6;
+                    MenhirLib.EngineTypes.startp = _startpos__6_;
+                    MenhirLib.EngineTypes.endp = _endpos__6_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _5;
+                      MenhirLib.EngineTypes.startp = _startpos__5_;
+                      MenhirLib.EngineTypes.endp = _endpos__5_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _1_inlined1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _;
+                          MenhirLib.EngineTypes.semv = _3;
+                          MenhirLib.EngineTypes.startp = _startpos__3_;
+                          MenhirLib.EngineTypes.endp = _endpos__3_;
+                          MenhirLib.EngineTypes.next = {
+                            MenhirLib.EngineTypes.state = _menhir_s;
+                            MenhirLib.EngineTypes.semv = _1;
+                            MenhirLib.EngineTypes.startp = _startpos__1_;
+                            MenhirLib.EngineTypes.endp = _endpos__1_;
+                            MenhirLib.EngineTypes.next = _menhir_stack;
+                          };
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _11 : (Parsetree.expression) = Obj.magic _11 in
+        let _10 : unit = Obj.magic _10 in
+        let _9 : (Parsetree.core_type) = Obj.magic _9 in
+        let _8 : unit = Obj.magic _8 in
+        let xs : (string Asttypes.loc list) = Obj.magic xs in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 19904 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined1 in
+        let _3 : (Asttypes.private_flag) = Obj.magic _3 in
+        let _1 : (Parsetree.attributes) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__11_ in
+        let _v : ((Asttypes.label Asttypes.loc * Asttypes.private_flag *
+   Parsetree.class_field_kind) *
+  Parsetree.attributes) = let _7 = 
+# 2341 "parsing/parser.mly"
+    ( xs )
+# 19916 "parsing/parser.ml"
+         in
+        let _startpos__7_ = _startpos_xs_ in
+        let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 19924 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 19932 "parsing/parser.ml"
+          
+        in
+        let _startpos__4_ = _startpos__1_inlined1_ in
+        let _2 = 
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 19939 "parsing/parser.ml"
+         in
+        let (_endpos__2_, _startpos__2_) = (_endpos__1_, _startpos__1_) in
+        let _1 = 
+# 3544 "parsing/parser.mly"
+                                                ( Fresh )
+# 19945 "parsing/parser.ml"
+         in
+        let (_endpos__1_, _startpos__1_) = (_endpos__0_, _endpos__0_) in
+        let _endpos = _endpos__11_ in
+        let _symbolstartpos = if _startpos__1_ != _endpos__1_ then
+          _startpos__1_
+        else
+          if _startpos__2_ != _endpos__2_ then
+            _startpos__2_
+          else
+            if _startpos__3_ != _endpos__3_ then
+              _startpos__3_
+            else
+              _startpos__4_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1813 "parsing/parser.mly"
+      ( let poly_exp_loc = (_startpos__7_, _endpos__11_) in
+        let poly_exp =
+          let exp, poly =
+            (* it seems odd to use the global ~loc here while poly_exp_loc
+               is tighter, but this is what ocamlyacc does;
+               TODO improve parser.mly *)
+            wrap_type_annotation ~loc:_sloc _7 _9 _11 in
+          ghexp ~loc:poly_exp_loc (Pexp_poly(exp, Some poly)) in
+        (_4, _3,
+        Cfk_concrete (_1, poly_exp)), _2 )
+# 19972 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _11;
+          MenhirLib.EngineTypes.startp = _startpos__11_;
+          MenhirLib.EngineTypes.endp = _endpos__11_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _10;
+            MenhirLib.EngineTypes.startp = _startpos__10_;
+            MenhirLib.EngineTypes.endp = _endpos__10_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _9;
+              MenhirLib.EngineTypes.startp = _startpos__9_;
+              MenhirLib.EngineTypes.endp = _endpos__9_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _8;
+                MenhirLib.EngineTypes.startp = _startpos__8_;
+                MenhirLib.EngineTypes.endp = _endpos__8_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = xs;
+                  MenhirLib.EngineTypes.startp = _startpos_xs_;
+                  MenhirLib.EngineTypes.endp = _endpos_xs_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _6;
+                    MenhirLib.EngineTypes.startp = _startpos__6_;
+                    MenhirLib.EngineTypes.endp = _endpos__6_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _5;
+                      MenhirLib.EngineTypes.startp = _startpos__5_;
+                      MenhirLib.EngineTypes.endp = _endpos__5_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _1_inlined2;
+                        MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _;
+                          MenhirLib.EngineTypes.semv = _3;
+                          MenhirLib.EngineTypes.startp = _startpos__3_;
+                          MenhirLib.EngineTypes.endp = _endpos__3_;
+                          MenhirLib.EngineTypes.next = {
+                            MenhirLib.EngineTypes.state = _;
+                            MenhirLib.EngineTypes.semv = _1_inlined1;
+                            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                            MenhirLib.EngineTypes.next = {
+                              MenhirLib.EngineTypes.state = _menhir_s;
+                              MenhirLib.EngineTypes.semv = _1;
+                              MenhirLib.EngineTypes.startp = _startpos__1_;
+                              MenhirLib.EngineTypes.endp = _endpos__1_;
+                              MenhirLib.EngineTypes.next = _menhir_stack;
+                            };
+                          };
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _11 : (Parsetree.expression) = Obj.magic _11 in
+        let _10 : unit = Obj.magic _10 in
+        let _9 : (Parsetree.core_type) = Obj.magic _9 in
+        let _8 : unit = Obj.magic _8 in
+        let xs : (string Asttypes.loc list) = Obj.magic xs in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 20060 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _3 : (Asttypes.private_flag) = Obj.magic _3 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__11_ in
+        let _v : ((Asttypes.label Asttypes.loc * Asttypes.private_flag *
+   Parsetree.class_field_kind) *
+  Parsetree.attributes) = let _7 = 
+# 2341 "parsing/parser.mly"
+    ( xs )
+# 20073 "parsing/parser.ml"
+         in
+        let _startpos__7_ = _startpos_xs_ in
+        let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 20081 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 20089 "parsing/parser.ml"
+          
+        in
+        let _startpos__4_ = _startpos__1_inlined2_ in
+        let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 20098 "parsing/parser.ml"
+          
+        in
+        let (_endpos__2_, _startpos__2_) = (_endpos__1_inlined1_, _startpos__1_inlined1_) in
+        let _1 = 
+# 3545 "parsing/parser.mly"
+                                                ( Override )
+# 20105 "parsing/parser.ml"
+         in
+        let _endpos = _endpos__11_ in
+        let _symbolstartpos = if _startpos__1_ != _endpos__1_ then
+          _startpos__1_
+        else
+          if _startpos__2_ != _endpos__2_ then
+            _startpos__2_
+          else
+            if _startpos__3_ != _endpos__3_ then
+              _startpos__3_
+            else
+              _startpos__4_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1813 "parsing/parser.mly"
+      ( let poly_exp_loc = (_startpos__7_, _endpos__11_) in
+        let poly_exp =
+          let exp, poly =
+            (* it seems odd to use the global ~loc here while poly_exp_loc
+               is tighter, but this is what ocamlyacc does;
+               TODO improve parser.mly *)
+            wrap_type_annotation ~loc:_sloc _7 _9 _11 in
+          ghexp ~loc:poly_exp_loc (Pexp_poly(exp, Some poly)) in
+        (_4, _3,
+        Cfk_concrete (_1, poly_exp)), _2 )
+# 20131 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 20152 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Longident.t) = 
+# 3423 "parsing/parser.mly"
+                                                ( Lident _1 )
+# 20160 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 20193 "parsing/parser.ml"
+        ) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Longident.t) = 
+# 3424 "parsing/parser.mly"
+                                                ( Ldot(_1, _3) )
+# 20203 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Longident.t) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Longident.t) = let _endpos = _endpos__4_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3426 "parsing/parser.mly"
+      ( lapply ~loc:_sloc _1 _3 )
+# 20252 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Longident.t) = let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        
+# 3428 "parsing/parser.mly"
+      ( expecting _loc__3_ "module path" )
+# 20292 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 20313 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Longident.t) = 
+# 3419 "parsing/parser.mly"
+                                                ( Lident _1 )
+# 20321 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 20354 "parsing/parser.ml"
+        ) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Longident.t) = 
+# 3420 "parsing/parser.mly"
+                                                ( Ldot(_1, _3) )
+# 20364 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = me;
+          MenhirLib.EngineTypes.startp = _startpos_me_;
+          MenhirLib.EngineTypes.endp = _endpos_me_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let me : (Parsetree.module_expr) = Obj.magic me in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_me_ in
+        let _v : (Parsetree.module_expr) = 
+# 1301 "parsing/parser.mly"
+      ( me )
+# 20396 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = me;
+          MenhirLib.EngineTypes.startp = _startpos_me_;
+          MenhirLib.EngineTypes.endp = _endpos_me_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = mty;
+              MenhirLib.EngineTypes.startp = _startpos_mty_;
+              MenhirLib.EngineTypes.endp = _endpos_mty_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let me : (Parsetree.module_expr) = Obj.magic me in
+        let _3 : unit = Obj.magic _3 in
+        let mty : (Parsetree.module_type) = Obj.magic mty in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_me_ in
+        let _v : (Parsetree.module_expr) = let _1 =
+          let _1 = 
+# 1304 "parsing/parser.mly"
+        ( Pmod_constraint(me, mty) )
+# 20443 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos_me_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 813 "parsing/parser.mly"
+    ( mkmod ~loc:_sloc _1 )
+# 20452 "parsing/parser.ml"
+          
+        in
+        
+# 1308 "parsing/parser.mly"
+    ( _1 )
+# 20458 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = body;
+          MenhirLib.EngineTypes.startp = _startpos_body_;
+          MenhirLib.EngineTypes.endp = _endpos_body_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = arg;
+            MenhirLib.EngineTypes.startp = _startpos_arg_;
+            MenhirLib.EngineTypes.endp = _endpos_arg_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let body : (Parsetree.module_expr) = Obj.magic body in
+        let arg : (string Asttypes.loc * Parsetree.module_type option) = Obj.magic arg in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_arg_ in
+        let _endpos = _endpos_body_ in
+        let _v : (Parsetree.module_expr) = let _1 =
+          let _1 = 
+# 1306 "parsing/parser.mly"
+        ( let (x, mty) = arg in
+          Pmod_functor(x, mty, body) )
+# 20492 "parsing/parser.ml"
+           in
+          let (_endpos__1_, _startpos__1_) = (_endpos_body_, _startpos_arg_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 813 "parsing/parser.mly"
+    ( mkmod ~loc:_sloc _1 )
+# 20501 "parsing/parser.ml"
+          
+        in
+        
+# 1308 "parsing/parser.mly"
+    ( _1 )
+# 20507 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = mty;
+          MenhirLib.EngineTypes.startp = _startpos_mty_;
+          MenhirLib.EngineTypes.endp = _endpos_mty_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let mty : (Parsetree.module_type) = Obj.magic mty in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_mty_ in
+        let _v : (Parsetree.module_type) = 
+# 1545 "parsing/parser.mly"
+      ( mty )
+# 20539 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = body;
+          MenhirLib.EngineTypes.startp = _startpos_body_;
+          MenhirLib.EngineTypes.endp = _endpos_body_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = arg;
+            MenhirLib.EngineTypes.startp = _startpos_arg_;
+            MenhirLib.EngineTypes.endp = _endpos_arg_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let body : (Parsetree.module_type) = Obj.magic body in
+        let arg : (string Asttypes.loc * Parsetree.module_type option) = Obj.magic arg in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_arg_ in
+        let _endpos = _endpos_body_ in
+        let _v : (Parsetree.module_type) = let _1 =
+          let _1 = 
+# 1548 "parsing/parser.mly"
+        ( let (x, mty) = arg in
+          Pmty_functor(x, mty, body) )
+# 20573 "parsing/parser.ml"
+           in
+          let (_endpos__1_, _startpos__1_) = (_endpos_body_, _startpos_arg_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 815 "parsing/parser.mly"
+    ( mkmty ~loc:_sloc _1 )
+# 20582 "parsing/parser.ml"
+          
+        in
+        
+# 1551 "parsing/parser.mly"
+    ( _1 )
+# 20588 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = s;
+            MenhirLib.EngineTypes.startp = _startpos_s_;
+            MenhirLib.EngineTypes.endp = _endpos_s_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let s : (Parsetree.structure) = Obj.magic s in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.module_expr) = let attrs =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 20636 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__4_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1140 "parsing/parser.mly"
+      ( mkmod ~loc:_sloc ~attrs (Pmod_structure s) )
+# 20645 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.structure) = Obj.magic _3 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.module_expr) = let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 20693 "parsing/parser.ml"
+          
+        in
+        let _loc__4_ = (_startpos__4_, _endpos__4_) in
+        let _loc__1_ = (_startpos__1_, _endpos__1_) in
+        
+# 1142 "parsing/parser.mly"
+      ( unclosed "struct" _loc__1_ "end" _loc__4_ )
+# 20701 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = me;
+          MenhirLib.EngineTypes.startp = _startpos_me_;
+          MenhirLib.EngineTypes.endp = _endpos_me_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let me : (Parsetree.module_expr) = Obj.magic me in
+        let _4 : unit = Obj.magic _4 in
+        let _1_inlined2 : ((string Asttypes.loc * Parsetree.module_type option) list) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_me_ in
+        let _v : (Parsetree.module_expr) = let args =
+          let _1 = _1_inlined2 in
+          
+# 1106 "parsing/parser.mly"
+    ( _1 )
+# 20756 "parsing/parser.ml"
+          
+        in
+        let attrs =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 20764 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_me_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1144 "parsing/parser.mly"
+      ( wrap_mod_attrs ~loc:_sloc attrs (
+          List.fold_left (fun acc (x, mty) ->
+            mkmod ~loc:_sloc (Pmod_functor (x, mty, acc))
+          ) me args
+        ) )
+# 20777 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = me;
+          MenhirLib.EngineTypes.startp = _startpos_me_;
+          MenhirLib.EngineTypes.endp = _endpos_me_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let me : (Parsetree.module_expr) = Obj.magic me in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_me_ in
+        let _endpos = _endpos_me_ in
+        let _v : (Parsetree.module_expr) = 
+# 1150 "parsing/parser.mly"
+      ( me )
+# 20802 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = attr;
+          MenhirLib.EngineTypes.startp = _startpos_attr_;
+          MenhirLib.EngineTypes.endp = _endpos_attr_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = me;
+            MenhirLib.EngineTypes.startp = _startpos_me_;
+            MenhirLib.EngineTypes.endp = _endpos_me_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let attr : (Parsetree.attribute) = Obj.magic attr in
+        let me : (Parsetree.module_expr) = Obj.magic me in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_me_ in
+        let _endpos = _endpos_attr_ in
+        let _v : (Parsetree.module_expr) = 
+# 1152 "parsing/parser.mly"
+      ( Mod.attr me attr )
+# 20834 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.module_expr) = let _1 =
+          let _1 =
+            let x =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 20865 "parsing/parser.ml"
+              
+            in
+            
+# 1156 "parsing/parser.mly"
+        ( Pmod_ident x )
+# 20871 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 813 "parsing/parser.mly"
+    ( mkmod ~loc:_sloc _1 )
+# 20880 "parsing/parser.ml"
+          
+        in
+        
+# 1168 "parsing/parser.mly"
+    ( _1 )
+# 20886 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = me2;
+          MenhirLib.EngineTypes.startp = _startpos_me2_;
+          MenhirLib.EngineTypes.endp = _endpos_me2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = me1;
+            MenhirLib.EngineTypes.startp = _startpos_me1_;
+            MenhirLib.EngineTypes.endp = _endpos_me1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let me2 : (Parsetree.module_expr) = Obj.magic me2 in
+        let me1 : (Parsetree.module_expr) = Obj.magic me1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_me1_ in
+        let _endpos = _endpos_me2_ in
+        let _v : (Parsetree.module_expr) = let _1 =
+          let _1 = 
+# 1159 "parsing/parser.mly"
+        ( Pmod_apply(me1, me2) )
+# 20919 "parsing/parser.ml"
+           in
+          let (_endpos__1_, _startpos__1_) = (_endpos_me2_, _startpos_me1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 813 "parsing/parser.mly"
+    ( mkmod ~loc:_sloc _1 )
+# 20928 "parsing/parser.ml"
+          
+        in
+        
+# 1168 "parsing/parser.mly"
+    ( _1 )
+# 20934 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = me1;
+              MenhirLib.EngineTypes.startp = _startpos_me1_;
+              MenhirLib.EngineTypes.endp = _endpos_me1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let me1 : (Parsetree.module_expr) = Obj.magic me1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_me1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.module_expr) = let _1 =
+          let _1 =
+            let _endpos = _endpos__3_ in
+            let _symbolstartpos = _startpos_me1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 1162 "parsing/parser.mly"
+        ( (* TODO review mkmod location *)
+          Pmod_apply(me1, mkmod ~loc:_sloc (Pmod_structure [])) )
+# 20979 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos__3_, _startpos_me1_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 813 "parsing/parser.mly"
+    ( mkmod ~loc:_sloc _1 )
+# 20989 "parsing/parser.ml"
+          
+        in
+        
+# 1168 "parsing/parser.mly"
+    ( _1 )
+# 20995 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = ex;
+          MenhirLib.EngineTypes.startp = _startpos_ex_;
+          MenhirLib.EngineTypes.endp = _endpos_ex_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let ex : (Parsetree.extension) = Obj.magic ex in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_ex_ in
+        let _endpos = _endpos_ex_ in
+        let _v : (Parsetree.module_expr) = let _1 =
+          let _1 = 
+# 1166 "parsing/parser.mly"
+        ( Pmod_extension ex )
+# 21021 "parsing/parser.ml"
+           in
+          let (_endpos__1_, _startpos__1_) = (_endpos_ex_, _startpos_ex_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 813 "parsing/parser.mly"
+    ( mkmod ~loc:_sloc _1 )
+# 21030 "parsing/parser.ml"
+          
+        in
+        
+# 1168 "parsing/parser.mly"
+    ( _1 )
+# 21036 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined4;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined4_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = ext;
+                    MenhirLib.EngineTypes.startp = _startpos_ext_;
+                    MenhirLib.EngineTypes.endp = _endpos_ext_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined4 : (Parsetree.attributes) = Obj.magic _1_inlined4 in
+        let _1_inlined3 : (Longident.t) = Obj.magic _1_inlined3 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined2 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 21096 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined4_ in
+        let _v : (Parsetree.module_substitution * string Asttypes.loc option) = let attrs2 =
+          let _1 = _1_inlined4 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 21109 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs2_ = _endpos__1_inlined4_ in
+        let body =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 21121 "parsing/parser.ml"
+          
+        in
+        let uid =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 21132 "parsing/parser.ml"
+          
+        in
+        let attrs1 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 21140 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_attrs2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1581 "parsing/parser.mly"
+  (
+    let attrs = attrs1 @ attrs2 in
+    let loc = make_loc _sloc in
+    let docs = symbol_docs _sloc in
+    Ms.mk uid body ~attrs ~loc ~docs, ext
+  )
+# 21154 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _6;
+          MenhirLib.EngineTypes.startp = _startpos__6_;
+          MenhirLib.EngineTypes.endp = _endpos__6_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _5;
+            MenhirLib.EngineTypes.startp = _startpos__5_;
+            MenhirLib.EngineTypes.endp = _endpos__5_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _2;
+                  MenhirLib.EngineTypes.startp = _startpos__2_;
+                  MenhirLib.EngineTypes.endp = _endpos__2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined2 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 21207 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _2 : (string Asttypes.loc option) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__6_ in
+        let _v : (Parsetree.module_substitution * string Asttypes.loc option) = let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 21223 "parsing/parser.ml"
+          
+        in
+        let _3 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 21231 "parsing/parser.ml"
+          
+        in
+        let _loc__6_ = (_startpos__6_, _endpos__6_) in
+        
+# 1588 "parsing/parser.mly"
+    ( expecting _loc__6_ "module path" )
+# 21238 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = s;
+            MenhirLib.EngineTypes.startp = _startpos_s_;
+            MenhirLib.EngineTypes.endp = _endpos_s_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let s : (Parsetree.signature) = Obj.magic s in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.module_type) = let attrs =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 21286 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__4_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1433 "parsing/parser.mly"
+      ( mkmty ~loc:_sloc ~attrs (Pmty_signature s) )
+# 21295 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.signature) = Obj.magic _3 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.module_type) = let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 21343 "parsing/parser.ml"
+          
+        in
+        let _loc__4_ = (_startpos__4_, _endpos__4_) in
+        let _loc__1_ = (_startpos__1_, _endpos__1_) in
+        
+# 1435 "parsing/parser.mly"
+      ( unclosed "sig" _loc__1_ "end" _loc__4_ )
+# 21351 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = mty;
+          MenhirLib.EngineTypes.startp = _startpos_mty_;
+          MenhirLib.EngineTypes.endp = _endpos_mty_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let mty : (Parsetree.module_type) = Obj.magic mty in
+        let _4 : unit = Obj.magic _4 in
+        let _1_inlined2 : ((string Asttypes.loc * Parsetree.module_type option) list) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_mty_ in
+        let _v : (Parsetree.module_type) = let args =
+          let _1 = _1_inlined2 in
+          
+# 1106 "parsing/parser.mly"
+    ( _1 )
+# 21406 "parsing/parser.ml"
+          
+        in
+        let attrs =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 21414 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_mty_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1439 "parsing/parser.mly"
+      ( wrap_mty_attrs ~loc:_sloc attrs (
+          List.fold_left (fun acc (x, mty) ->
+            mkmty ~loc:_sloc (Pmty_functor (x, mty, acc))
+          ) mty args
+        ) )
+# 21427 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : (Parsetree.module_expr) = Obj.magic _5 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.module_type) = let _4 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 21482 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1445 "parsing/parser.mly"
+      ( mkmty ~loc:_sloc ~attrs:_4 (Pmty_typeof _5) )
+# 21491 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.module_type) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.module_type) = 
+# 1447 "parsing/parser.mly"
+      ( _2 )
+# 21530 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.module_type) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.module_type) = let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        let _loc__1_ = (_startpos__1_, _endpos__1_) in
+        
+# 1449 "parsing/parser.mly"
+      ( unclosed "(" _loc__1_ ")" _loc__3_ )
+# 21571 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.attribute) = Obj.magic _2 in
+        let _1 : (Parsetree.module_type) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.module_type) = 
+# 1451 "parsing/parser.mly"
+      ( Mty.attr _1 _2 )
+# 21603 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.module_type) = let _1 =
+          let _1 =
+            let _1 =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 21634 "parsing/parser.ml"
+              
+            in
+            
+# 1454 "parsing/parser.mly"
+        ( Pmty_ident _1 )
+# 21640 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 815 "parsing/parser.mly"
+    ( mkmty ~loc:_sloc _1 )
+# 21649 "parsing/parser.ml"
+          
+        in
+        
+# 1465 "parsing/parser.mly"
+    ( _1 )
+# 21655 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.module_type) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.module_type) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.module_type) = let _1 =
+          let _1 = 
+# 1457 "parsing/parser.mly"
+        ( Pmty_functor(mknoloc "_", Some _1, _3) )
+# 21695 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 815 "parsing/parser.mly"
+    ( mkmty ~loc:_sloc _1 )
+# 21704 "parsing/parser.ml"
+          
+        in
+        
+# 1465 "parsing/parser.mly"
+    ( _1 )
+# 21710 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.with_constraint list) = Obj.magic xs in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.module_type) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.module_type) = let _1 =
+          let _1 =
+            let _3 =
+              let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 21752 "parsing/parser.ml"
+               in
+              
+# 904 "parsing/parser.mly"
+    ( xs )
+# 21757 "parsing/parser.ml"
+              
+            in
+            
+# 1459 "parsing/parser.mly"
+        ( Pmty_with(_1, _3) )
+# 21763 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos_xs_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 815 "parsing/parser.mly"
+    ( mkmty ~loc:_sloc _1 )
+# 21773 "parsing/parser.ml"
+          
+        in
+        
+# 1465 "parsing/parser.mly"
+    ( _1 )
+# 21779 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.extension) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.module_type) = let _1 =
+          let _1 = 
+# 1463 "parsing/parser.mly"
+        ( Pmty_extension _1 )
+# 21805 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 815 "parsing/parser.mly"
+    ( mkmty ~loc:_sloc _1 )
+# 21813 "parsing/parser.ml"
+          
+        in
+        
+# 1465 "parsing/parser.mly"
+    ( _1 )
+# 21819 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = typ;
+            MenhirLib.EngineTypes.startp = _startpos_typ_;
+            MenhirLib.EngineTypes.endp = _endpos_typ_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = ext;
+                  MenhirLib.EngineTypes.startp = _startpos_ext_;
+                  MenhirLib.EngineTypes.endp = _endpos_ext_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let typ : (Parsetree.module_type option) = Obj.magic typ in
+        let _1_inlined2 : (Asttypes.label) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (Parsetree.module_type_declaration * string Asttypes.loc option) = let attrs2 =
+          let _1 = _1_inlined3 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 21888 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs2_ = _endpos__1_inlined3_ in
+        let id =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 21900 "parsing/parser.ml"
+          
+        in
+        let attrs1 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 21908 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_attrs2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1379 "parsing/parser.mly"
+  (
+    let attrs = attrs1 @ attrs2 in
+    let loc = make_loc _sloc in
+    let docs = symbol_docs _sloc in
+    Mtd.mk id ?typ ~attrs ~loc ~docs, ext
+  )
+# 21922 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Asttypes.label) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Longident.t) = 
+# 3431 "parsing/parser.mly"
+                                                ( Lident _1 )
+# 21947 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Asttypes.label) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Longident.t) = 
+# 3432 "parsing/parser.mly"
+                                                ( Ldot(_1, _3) )
+# 21986 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Asttypes.mutable_flag) = 
+# 3501 "parsing/parser.mly"
+                                                ( Immutable )
+# 22004 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.mutable_flag) = 
+# 3502 "parsing/parser.mly"
+                                                ( Mutable )
+# 22029 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Asttypes.mutable_flag * Asttypes.virtual_flag) = 
+# 3510 "parsing/parser.mly"
+      ( Immutable, Concrete )
+# 22047 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.mutable_flag * Asttypes.virtual_flag) = 
+# 3512 "parsing/parser.mly"
+      ( Mutable, Concrete )
+# 22072 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.mutable_flag * Asttypes.virtual_flag) = 
+# 3514 "parsing/parser.mly"
+      ( Immutable, Virtual )
+# 22097 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Asttypes.mutable_flag * Asttypes.virtual_flag) = 
+# 3517 "parsing/parser.mly"
+      ( Mutable, Virtual )
+# 22129 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Asttypes.mutable_flag * Asttypes.virtual_flag) = 
+# 3517 "parsing/parser.mly"
+      ( Mutable, Virtual )
+# 22161 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Asttypes.label) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Asttypes.label) = 
+# 3474 "parsing/parser.mly"
+                                                ( _2 )
+# 22193 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 22214 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string Asttypes.loc list) = let x =
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 22226 "parsing/parser.ml"
+          
+        in
+        
+# 221 "menhir/standard.mly"
+    ( [ x ] )
+# 22232 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : (string Asttypes.loc list) = Obj.magic xs in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 22260 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (string Asttypes.loc list) = let x =
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 22272 "parsing/parser.ml"
+          
+        in
+        
+# 223 "menhir/standard.mly"
+    ( x :: xs )
+# 22278 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = s;
+          MenhirLib.EngineTypes.startp = _startpos_s_;
+          MenhirLib.EngineTypes.endp = _endpos_s_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let s : (
+# 658 "parsing/parser.mly"
+       (string * string option)
+# 22299 "parsing/parser.ml"
+        ) = Obj.magic s in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_s_ in
+        let _endpos = _endpos_s_ in
+        let _v : (string list) = let x = 
+# 3470 "parsing/parser.mly"
+    ( fst s )
+# 22307 "parsing/parser.ml"
+         in
+        
+# 221 "menhir/standard.mly"
+    ( [ x ] )
+# 22312 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = s;
+            MenhirLib.EngineTypes.startp = _startpos_s_;
+            MenhirLib.EngineTypes.endp = _endpos_s_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let xs : (string list) = Obj.magic xs in
+        let s : (
+# 658 "parsing/parser.mly"
+       (string * string option)
+# 22340 "parsing/parser.ml"
+        ) = Obj.magic s in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_s_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (string list) = let x = 
+# 3470 "parsing/parser.mly"
+    ( fst s )
+# 22348 "parsing/parser.ml"
+         in
+        
+# 223 "menhir/standard.mly"
+    ( x :: xs )
+# 22353 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = ty;
+          MenhirLib.EngineTypes.startp = _startpos_ty_;
+          MenhirLib.EngineTypes.endp = _endpos_ty_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let ty : (Parsetree.core_type) = Obj.magic ty in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_ty_ in
+        let _endpos = _endpos_ty_ in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = 
+# 3497 "parsing/parser.mly"
+                                                ( Public )
+# 22378 "parsing/parser.ml"
+         in
+        
+# 2823 "parsing/parser.mly"
+      ( (Ptype_abstract, priv, Some ty) )
+# 22383 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = ty;
+          MenhirLib.EngineTypes.startp = _startpos_ty_;
+          MenhirLib.EngineTypes.endp = _endpos_ty_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let ty : (Parsetree.core_type) = Obj.magic ty in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_ty_ in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = 
+# 3498 "parsing/parser.mly"
+                                                ( Private )
+# 22415 "parsing/parser.ml"
+         in
+        
+# 2823 "parsing/parser.mly"
+      ( (Ptype_abstract, priv, Some ty) )
+# 22420 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = cs;
+          MenhirLib.EngineTypes.startp = _startpos_cs_;
+          MenhirLib.EngineTypes.endp = _endpos_cs_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let cs : (Parsetree.constructor_declaration list) = Obj.magic cs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_cs_ in
+        let _endpos = _endpos_cs_ in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = 
+# 3497 "parsing/parser.mly"
+                                                ( Public )
+# 22445 "parsing/parser.ml"
+         in
+        let oty =
+          let _1 = 
+# 124 "menhir/standard.mly"
+    ( None )
+# 22451 "parsing/parser.ml"
+           in
+          
+# 2839 "parsing/parser.mly"
+    ( _1 )
+# 22456 "parsing/parser.ml"
+          
+        in
+        
+# 2827 "parsing/parser.mly"
+      ( (Ptype_variant cs, priv, oty) )
+# 22462 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = cs;
+          MenhirLib.EngineTypes.startp = _startpos_cs_;
+          MenhirLib.EngineTypes.endp = _endpos_cs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let cs : (Parsetree.constructor_declaration list) = Obj.magic cs in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_cs_ in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = 
+# 3498 "parsing/parser.mly"
+                                                ( Private )
+# 22494 "parsing/parser.ml"
+         in
+        let oty =
+          let _1 = 
+# 124 "menhir/standard.mly"
+    ( None )
+# 22500 "parsing/parser.ml"
+           in
+          
+# 2839 "parsing/parser.mly"
+    ( _1 )
+# 22505 "parsing/parser.ml"
+          
+        in
+        
+# 2827 "parsing/parser.mly"
+      ( (Ptype_variant cs, priv, oty) )
+# 22511 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = cs;
+          MenhirLib.EngineTypes.startp = _startpos_cs_;
+          MenhirLib.EngineTypes.endp = _endpos_cs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = x;
+              MenhirLib.EngineTypes.startp = _startpos_x_;
+              MenhirLib.EngineTypes.endp = _endpos_x_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let cs : (Parsetree.constructor_declaration list) = Obj.magic cs in
+        let _2 : unit = Obj.magic _2 in
+        let x : (Parsetree.core_type) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_cs_ in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = 
+# 3497 "parsing/parser.mly"
+                                                ( Public )
+# 22550 "parsing/parser.ml"
+         in
+        let oty =
+          let _1 =
+            let x = 
+# 191 "menhir/standard.mly"
+    ( x )
+# 22557 "parsing/parser.ml"
+             in
+            
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 22562 "parsing/parser.ml"
+            
+          in
+          
+# 2839 "parsing/parser.mly"
+    ( _1 )
+# 22568 "parsing/parser.ml"
+          
+        in
+        
+# 2827 "parsing/parser.mly"
+      ( (Ptype_variant cs, priv, oty) )
+# 22574 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = cs;
+          MenhirLib.EngineTypes.startp = _startpos_cs_;
+          MenhirLib.EngineTypes.endp = _endpos_cs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = x;
+                MenhirLib.EngineTypes.startp = _startpos_x_;
+                MenhirLib.EngineTypes.endp = _endpos_x_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let cs : (Parsetree.constructor_declaration list) = Obj.magic cs in
+        let _1 : unit = Obj.magic _1 in
+        let _2 : unit = Obj.magic _2 in
+        let x : (Parsetree.core_type) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_cs_ in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = 
+# 3498 "parsing/parser.mly"
+                                                ( Private )
+# 22620 "parsing/parser.ml"
+         in
+        let oty =
+          let _1 =
+            let x = 
+# 191 "menhir/standard.mly"
+    ( x )
+# 22627 "parsing/parser.ml"
+             in
+            
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 22632 "parsing/parser.ml"
+            
+          in
+          
+# 2839 "parsing/parser.mly"
+    ( _1 )
+# 22638 "parsing/parser.ml"
+          
+        in
+        
+# 2827 "parsing/parser.mly"
+      ( (Ptype_variant cs, priv, oty) )
+# 22644 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__3_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = 
+# 3497 "parsing/parser.mly"
+                                                ( Public )
+# 22669 "parsing/parser.ml"
+         in
+        let oty =
+          let _1 = 
+# 124 "menhir/standard.mly"
+    ( None )
+# 22675 "parsing/parser.ml"
+           in
+          
+# 2839 "parsing/parser.mly"
+    ( _1 )
+# 22680 "parsing/parser.ml"
+          
+        in
+        
+# 2831 "parsing/parser.mly"
+      ( (Ptype_open, priv, oty) )
+# 22686 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = 
+# 3498 "parsing/parser.mly"
+                                                ( Private )
+# 22718 "parsing/parser.ml"
+         in
+        let oty =
+          let _1 = 
+# 124 "menhir/standard.mly"
+    ( None )
+# 22724 "parsing/parser.ml"
+           in
+          
+# 2839 "parsing/parser.mly"
+    ( _1 )
+# 22729 "parsing/parser.ml"
+          
+        in
+        
+# 2831 "parsing/parser.mly"
+      ( (Ptype_open, priv, oty) )
+# 22735 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = x;
+              MenhirLib.EngineTypes.startp = _startpos_x_;
+              MenhirLib.EngineTypes.endp = _endpos_x_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let x : (Parsetree.core_type) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = 
+# 3497 "parsing/parser.mly"
+                                                ( Public )
+# 22774 "parsing/parser.ml"
+         in
+        let oty =
+          let _1 =
+            let x = 
+# 191 "menhir/standard.mly"
+    ( x )
+# 22781 "parsing/parser.ml"
+             in
+            
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 22786 "parsing/parser.ml"
+            
+          in
+          
+# 2839 "parsing/parser.mly"
+    ( _1 )
+# 22792 "parsing/parser.ml"
+          
+        in
+        
+# 2831 "parsing/parser.mly"
+      ( (Ptype_open, priv, oty) )
+# 22798 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = x;
+                MenhirLib.EngineTypes.startp = _startpos_x_;
+                MenhirLib.EngineTypes.endp = _endpos_x_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _1 : unit = Obj.magic _1 in
+        let _2 : unit = Obj.magic _2 in
+        let x : (Parsetree.core_type) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = 
+# 3498 "parsing/parser.mly"
+                                                ( Private )
+# 22844 "parsing/parser.ml"
+         in
+        let oty =
+          let _1 =
+            let x = 
+# 191 "menhir/standard.mly"
+    ( x )
+# 22851 "parsing/parser.ml"
+             in
+            
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 22856 "parsing/parser.ml"
+            
+          in
+          
+# 2839 "parsing/parser.mly"
+    ( _1 )
+# 22862 "parsing/parser.ml"
+          
+        in
+        
+# 2831 "parsing/parser.mly"
+      ( (Ptype_open, priv, oty) )
+# 22868 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = ls;
+            MenhirLib.EngineTypes.startp = _startpos_ls_;
+            MenhirLib.EngineTypes.endp = _endpos_ls_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let ls : (Parsetree.label_declaration list) = Obj.magic ls in
+        let _3 : unit = Obj.magic _3 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__3_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = 
+# 3497 "parsing/parser.mly"
+                                                ( Public )
+# 22907 "parsing/parser.ml"
+         in
+        let oty =
+          let _1 = 
+# 124 "menhir/standard.mly"
+    ( None )
+# 22913 "parsing/parser.ml"
+           in
+          
+# 2839 "parsing/parser.mly"
+    ( _1 )
+# 22918 "parsing/parser.ml"
+          
+        in
+        
+# 2835 "parsing/parser.mly"
+      ( (Ptype_record ls, priv, oty) )
+# 22924 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = ls;
+            MenhirLib.EngineTypes.startp = _startpos_ls_;
+            MenhirLib.EngineTypes.endp = _endpos_ls_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let ls : (Parsetree.label_declaration list) = Obj.magic ls in
+        let _3 : unit = Obj.magic _3 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = 
+# 3498 "parsing/parser.mly"
+                                                ( Private )
+# 22970 "parsing/parser.ml"
+         in
+        let oty =
+          let _1 = 
+# 124 "menhir/standard.mly"
+    ( None )
+# 22976 "parsing/parser.ml"
+           in
+          
+# 2839 "parsing/parser.mly"
+    ( _1 )
+# 22981 "parsing/parser.ml"
+          
+        in
+        
+# 2835 "parsing/parser.mly"
+      ( (Ptype_record ls, priv, oty) )
+# 22987 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = ls;
+            MenhirLib.EngineTypes.startp = _startpos_ls_;
+            MenhirLib.EngineTypes.endp = _endpos_ls_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = x;
+                  MenhirLib.EngineTypes.startp = _startpos_x_;
+                  MenhirLib.EngineTypes.endp = _endpos_x_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let ls : (Parsetree.label_declaration list) = Obj.magic ls in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let x : (Parsetree.core_type) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = 
+# 3497 "parsing/parser.mly"
+                                                ( Public )
+# 23040 "parsing/parser.ml"
+         in
+        let oty =
+          let _1 =
+            let x = 
+# 191 "menhir/standard.mly"
+    ( x )
+# 23047 "parsing/parser.ml"
+             in
+            
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 23052 "parsing/parser.ml"
+            
+          in
+          
+# 2839 "parsing/parser.mly"
+    ( _1 )
+# 23058 "parsing/parser.ml"
+          
+        in
+        
+# 2835 "parsing/parser.mly"
+      ( (Ptype_record ls, priv, oty) )
+# 23064 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = ls;
+            MenhirLib.EngineTypes.startp = _startpos_ls_;
+            MenhirLib.EngineTypes.endp = _endpos_ls_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _2;
+                  MenhirLib.EngineTypes.startp = _startpos__2_;
+                  MenhirLib.EngineTypes.endp = _endpos__2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = x;
+                    MenhirLib.EngineTypes.startp = _startpos_x_;
+                    MenhirLib.EngineTypes.endp = _endpos_x_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let ls : (Parsetree.label_declaration list) = Obj.magic ls in
+        let _3 : unit = Obj.magic _3 in
+        let _1 : unit = Obj.magic _1 in
+        let _2 : unit = Obj.magic _2 in
+        let x : (Parsetree.core_type) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = 
+# 3498 "parsing/parser.mly"
+                                                ( Private )
+# 23124 "parsing/parser.ml"
+         in
+        let oty =
+          let _1 =
+            let x = 
+# 191 "menhir/standard.mly"
+    ( x )
+# 23131 "parsing/parser.ml"
+             in
+            
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 23136 "parsing/parser.ml"
+            
+          in
+          
+# 2839 "parsing/parser.mly"
+    ( _1 )
+# 23142 "parsing/parser.ml"
+          
+        in
+        
+# 2835 "parsing/parser.mly"
+      ( (Ptype_record ls, priv, oty) )
+# 23148 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = me;
+            MenhirLib.EngineTypes.startp = _startpos_me_;
+            MenhirLib.EngineTypes.endp = _endpos_me_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = ext;
+                MenhirLib.EngineTypes.startp = _startpos_ext_;
+                MenhirLib.EngineTypes.endp = _endpos_ext_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let me : (Parsetree.module_expr) = Obj.magic me in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.open_declaration * string Asttypes.loc option) = let attrs2 =
+          let _1 = _1_inlined2 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 23203 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs2_ = _endpos__1_inlined2_ in
+        let attrs1 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 23212 "parsing/parser.ml"
+          
+        in
+        let override = 
+# 3544 "parsing/parser.mly"
+                                                ( Fresh )
+# 23218 "parsing/parser.ml"
+         in
+        let _endpos = _endpos_attrs2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1398 "parsing/parser.mly"
+  (
+    let attrs = attrs1 @ attrs2 in
+    let loc = make_loc _sloc in
+    let docs = symbol_docs _sloc in
+    Opn.mk me ~override ~attrs ~loc ~docs, ext
+  )
+# 23231 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = me;
+            MenhirLib.EngineTypes.startp = _startpos_me_;
+            MenhirLib.EngineTypes.endp = _endpos_me_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = ext;
+                MenhirLib.EngineTypes.startp = _startpos_ext_;
+                MenhirLib.EngineTypes.endp = _endpos_ext_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let me : (Parsetree.module_expr) = Obj.magic me in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1_inlined1 : unit = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (Parsetree.open_declaration * string Asttypes.loc option) = let attrs2 =
+          let _1 = _1_inlined3 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 23293 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs2_ = _endpos__1_inlined3_ in
+        let attrs1 =
+          let _1 = _1_inlined2 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 23302 "parsing/parser.ml"
+          
+        in
+        let override =
+          let _1 = _1_inlined1 in
+          
+# 3545 "parsing/parser.mly"
+                                                ( Override )
+# 23310 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_attrs2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1398 "parsing/parser.mly"
+  (
+    let attrs = attrs1 @ attrs2 in
+    let loc = make_loc _sloc in
+    let docs = symbol_docs _sloc in
+    Opn.mk me ~override ~attrs ~loc ~docs, ext
+  )
+# 23324 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined2;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = ext;
+                MenhirLib.EngineTypes.startp = _startpos_ext_;
+                MenhirLib.EngineTypes.endp = _endpos_ext_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (Longident.t) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (Parsetree.open_description * string Asttypes.loc option) = let attrs2 =
+          let _1 = _1_inlined3 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 23379 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs2_ = _endpos__1_inlined3_ in
+        let id =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 23391 "parsing/parser.ml"
+          
+        in
+        let attrs1 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 23399 "parsing/parser.ml"
+          
+        in
+        let override = 
+# 3544 "parsing/parser.mly"
+                                                ( Fresh )
+# 23405 "parsing/parser.ml"
+         in
+        let _endpos = _endpos_attrs2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1413 "parsing/parser.mly"
+  (
+    let attrs = attrs1 @ attrs2 in
+    let loc = make_loc _sloc in
+    let docs = symbol_docs _sloc in
+    Opn.mk id ~override ~attrs ~loc ~docs, ext
+  )
+# 23418 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined4;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined4_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = ext;
+                MenhirLib.EngineTypes.startp = _startpos_ext_;
+                MenhirLib.EngineTypes.endp = _endpos_ext_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined4 : (Parsetree.attributes) = Obj.magic _1_inlined4 in
+        let _1_inlined3 : (Longident.t) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1_inlined1 : unit = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined4_ in
+        let _v : (Parsetree.open_description * string Asttypes.loc option) = let attrs2 =
+          let _1 = _1_inlined4 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 23480 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs2_ = _endpos__1_inlined4_ in
+        let id =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 23492 "parsing/parser.ml"
+          
+        in
+        let attrs1 =
+          let _1 = _1_inlined2 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 23500 "parsing/parser.ml"
+          
+        in
+        let override =
+          let _1 = _1_inlined1 in
+          
+# 3545 "parsing/parser.mly"
+                                                ( Override )
+# 23508 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_attrs2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1413 "parsing/parser.mly"
+  (
+    let attrs = attrs1 @ attrs2 in
+    let loc = make_loc _sloc in
+    let docs = symbol_docs _sloc in
+    Opn.mk id ~override ~attrs ~loc ~docs, ext
+  )
+# 23522 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 644 "parsing/parser.mly"
+       (string)
+# 23543 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3353 "parsing/parser.mly"
+                                                ( _1 )
+# 23551 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 602 "parsing/parser.mly"
+       (string)
+# 23572 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3354 "parsing/parser.mly"
+                                                ( _1 )
+# 23580 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 603 "parsing/parser.mly"
+       (string)
+# 23601 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3355 "parsing/parser.mly"
+                                                ( _1 )
+# 23609 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 23644 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (string) = 
+# 3356 "parsing/parser.mly"
+                                                ( "."^ _1 ^"()" )
+# 23652 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 23694 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (string) = 
+# 3357 "parsing/parser.mly"
+                                                ( "."^ _1 ^ "()<-" )
+# 23702 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 23737 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (string) = 
+# 3358 "parsing/parser.mly"
+                                                ( "."^ _1 ^"[]" )
+# 23745 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 23787 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (string) = 
+# 3359 "parsing/parser.mly"
+                                                ( "."^ _1 ^ "[]<-" )
+# 23795 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 23830 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (string) = 
+# 3360 "parsing/parser.mly"
+                                                ( "."^ _1 ^"{}" )
+# 23838 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 23880 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (string) = 
+# 3361 "parsing/parser.mly"
+                                                ( "."^ _1 ^ "{}<-" )
+# 23888 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 655 "parsing/parser.mly"
+       (string)
+# 23909 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3362 "parsing/parser.mly"
+                                                ( _1 )
+# 23917 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3363 "parsing/parser.mly"
+                                                ( "!" )
+# 23942 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = op;
+          MenhirLib.EngineTypes.startp = _startpos_op_;
+          MenhirLib.EngineTypes.endp = _endpos_op_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let op : (
+# 596 "parsing/parser.mly"
+       (string)
+# 23963 "parsing/parser.ml"
+        ) = Obj.magic op in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_op_ in
+        let _endpos = _endpos_op_ in
+        let _v : (string) = let _1 = 
+# 3367 "parsing/parser.mly"
+                  ( op )
+# 23971 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 23976 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = op;
+          MenhirLib.EngineTypes.startp = _startpos_op_;
+          MenhirLib.EngineTypes.endp = _endpos_op_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let op : (
+# 597 "parsing/parser.mly"
+       (string)
+# 23997 "parsing/parser.ml"
+        ) = Obj.magic op in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_op_ in
+        let _endpos = _endpos_op_ in
+        let _v : (string) = let _1 = 
+# 3368 "parsing/parser.mly"
+                  ( op )
+# 24005 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24010 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = op;
+          MenhirLib.EngineTypes.startp = _startpos_op_;
+          MenhirLib.EngineTypes.endp = _endpos_op_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let op : (
+# 598 "parsing/parser.mly"
+       (string)
+# 24031 "parsing/parser.ml"
+        ) = Obj.magic op in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_op_ in
+        let _endpos = _endpos_op_ in
+        let _v : (string) = let _1 = 
+# 3369 "parsing/parser.mly"
+                  ( op )
+# 24039 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24044 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = op;
+          MenhirLib.EngineTypes.startp = _startpos_op_;
+          MenhirLib.EngineTypes.endp = _endpos_op_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let op : (
+# 599 "parsing/parser.mly"
+       (string)
+# 24065 "parsing/parser.ml"
+        ) = Obj.magic op in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_op_ in
+        let _endpos = _endpos_op_ in
+        let _v : (string) = let _1 = 
+# 3370 "parsing/parser.mly"
+                  ( op )
+# 24073 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24078 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = op;
+          MenhirLib.EngineTypes.startp = _startpos_op_;
+          MenhirLib.EngineTypes.endp = _endpos_op_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let op : (
+# 600 "parsing/parser.mly"
+       (string)
+# 24099 "parsing/parser.ml"
+        ) = Obj.magic op in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_op_ in
+        let _endpos = _endpos_op_ in
+        let _v : (string) = let _1 = 
+# 3371 "parsing/parser.mly"
+                  ( op )
+# 24107 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24112 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = let _1 = 
+# 3372 "parsing/parser.mly"
+                   ("+")
+# 24137 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24142 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = let _1 = 
+# 3373 "parsing/parser.mly"
+                  ("+.")
+# 24167 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24172 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = let _1 = 
+# 3374 "parsing/parser.mly"
+                  ("+=")
+# 24197 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24202 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = let _1 = 
+# 3375 "parsing/parser.mly"
+                   ("-")
+# 24227 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24232 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = let _1 = 
+# 3376 "parsing/parser.mly"
+                  ("-.")
+# 24257 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24262 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = let _1 = 
+# 3377 "parsing/parser.mly"
+                   ("*")
+# 24287 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24292 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = let _1 = 
+# 3378 "parsing/parser.mly"
+                   ("%")
+# 24317 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24322 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = let _1 = 
+# 3379 "parsing/parser.mly"
+                   ("=")
+# 24347 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24352 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = let _1 = 
+# 3380 "parsing/parser.mly"
+                   ("<")
+# 24377 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24382 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = let _1 = 
+# 3381 "parsing/parser.mly"
+                   (">")
+# 24407 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24412 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = let _1 = 
+# 3382 "parsing/parser.mly"
+                  ("or")
+# 24437 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24442 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = let _1 = 
+# 3383 "parsing/parser.mly"
+                  ("||")
+# 24467 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24472 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = let _1 = 
+# 3384 "parsing/parser.mly"
+                   ("&")
+# 24497 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24502 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = let _1 = 
+# 3385 "parsing/parser.mly"
+                  ("&&")
+# 24527 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24532 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = let _1 = 
+# 3386 "parsing/parser.mly"
+                  (":=")
+# 24557 "parsing/parser.ml"
+         in
+        
+# 3364 "parsing/parser.mly"
+                                                ( _1 )
+# 24562 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (bool) = 
+# 3271 "parsing/parser.mly"
+                                                ( true )
+# 24587 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (bool) = 
+# 3272 "parsing/parser.mly"
+                                                ( false )
+# 24605 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (unit option) = 
+# 114 "menhir/standard.mly"
+    ( None )
+# 24623 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : unit = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : (unit option) = 
+# 116 "menhir/standard.mly"
+    ( Some x )
+# 24648 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (unit option) = 
+# 114 "menhir/standard.mly"
+    ( None )
+# 24666 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : unit = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : (unit option) = 
+# 116 "menhir/standard.mly"
+    ( Some x )
+# 24691 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (string Asttypes.loc option) = 
+# 114 "menhir/standard.mly"
+    ( None )
+# 24709 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 24736 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (string Asttypes.loc option) = let x =
+          let x =
+            let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 24751 "parsing/parser.ml"
+            
+          in
+          
+# 183 "menhir/standard.mly"
+    ( x )
+# 24757 "parsing/parser.ml"
+          
+        in
+        
+# 116 "menhir/standard.mly"
+    ( Some x )
+# 24763 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.core_type option) = 
+# 114 "menhir/standard.mly"
+    ( None )
+# 24781 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.core_type) = Obj.magic x in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.core_type option) = let x = 
+# 183 "menhir/standard.mly"
+    ( x )
+# 24813 "parsing/parser.ml"
+         in
+        
+# 116 "menhir/standard.mly"
+    ( Some x )
+# 24818 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.expression option) = 
+# 114 "menhir/standard.mly"
+    ( None )
+# 24836 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.expression) = Obj.magic x in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.expression option) = let x = 
+# 183 "menhir/standard.mly"
+    ( x )
+# 24868 "parsing/parser.ml"
+         in
+        
+# 116 "menhir/standard.mly"
+    ( Some x )
+# 24873 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.module_type option) = 
+# 114 "menhir/standard.mly"
+    ( None )
+# 24891 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.module_type) = Obj.magic x in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.module_type option) = let x = 
+# 183 "menhir/standard.mly"
+    ( x )
+# 24923 "parsing/parser.ml"
+         in
+        
+# 116 "menhir/standard.mly"
+    ( Some x )
+# 24928 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.pattern option) = 
+# 114 "menhir/standard.mly"
+    ( None )
+# 24946 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.pattern) = Obj.magic x in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.pattern option) = let x = 
+# 183 "menhir/standard.mly"
+    ( x )
+# 24978 "parsing/parser.ml"
+         in
+        
+# 116 "menhir/standard.mly"
+    ( Some x )
+# 24983 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.expression option) = 
+# 114 "menhir/standard.mly"
+    ( None )
+# 25001 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.expression) = Obj.magic x in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.expression option) = let x = 
+# 183 "menhir/standard.mly"
+    ( x )
+# 25033 "parsing/parser.ml"
+         in
+        
+# 116 "menhir/standard.mly"
+    ( Some x )
+# 25038 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : ((Parsetree.core_type option * Parsetree.core_type option) option) = 
+# 114 "menhir/standard.mly"
+    ( None )
+# 25056 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : (Parsetree.core_type option * Parsetree.core_type option) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : ((Parsetree.core_type option * Parsetree.core_type option) option) = 
+# 116 "menhir/standard.mly"
+    ( Some x )
+# 25081 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 637 "parsing/parser.mly"
+       (string)
+# 25102 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3556 "parsing/parser.mly"
+                                                ( _1 )
+# 25110 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 25144 "parsing/parser.ml"
+        ) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (string) = 
+# 3557 "parsing/parser.mly"
+                                                ( _2 )
+# 25153 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = mty;
+            MenhirLib.EngineTypes.startp = _startpos_mty_;
+            MenhirLib.EngineTypes.endp = _endpos_mty_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = me;
+                MenhirLib.EngineTypes.startp = _startpos_me_;
+                MenhirLib.EngineTypes.endp = _endpos_me_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let mty : (Parsetree.module_type) = Obj.magic mty in
+        let _3 : unit = Obj.magic _3 in
+        let me : (Parsetree.module_expr) = Obj.magic me in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.module_expr) = let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1177 "parsing/parser.mly"
+      ( mkmod ~loc:_sloc (Pmod_constraint(me, mty)) )
+# 25209 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.module_type) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.module_expr) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.module_expr) = let _loc__5_ = (_startpos__5_, _endpos__5_) in
+        let _loc__1_ = (_startpos__1_, _endpos__1_) in
+        
+# 1179 "parsing/parser.mly"
+      ( unclosed "(" _loc__1_ ")" _loc__5_ )
+# 25264 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = me;
+            MenhirLib.EngineTypes.startp = _startpos_me_;
+            MenhirLib.EngineTypes.endp = _endpos_me_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let me : (Parsetree.module_expr) = Obj.magic me in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.module_expr) = 
+# 1182 "parsing/parser.mly"
+      ( me (* TODO consider reloc *) )
+# 25303 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.module_expr) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.module_expr) = let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        let _loc__1_ = (_startpos__1_, _endpos__1_) in
+        
+# 1184 "parsing/parser.mly"
+      ( unclosed "(" _loc__1_ ")" _loc__3_ )
+# 25344 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = e;
+            MenhirLib.EngineTypes.startp = _startpos_e_;
+            MenhirLib.EngineTypes.endp = _endpos_e_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let e : (Parsetree.expression) = Obj.magic e in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.module_expr) = let e = 
+# 1201 "parsing/parser.mly"
+      ( e )
+# 25397 "parsing/parser.ml"
+         in
+        let attrs =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 25404 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1188 "parsing/parser.mly"
+      ( mkmod ~loc:_sloc ~attrs (Pmod_unpack e) )
+# 25413 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined2;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__2_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__2_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = e;
+                MenhirLib.EngineTypes.startp = _startpos_e_;
+                MenhirLib.EngineTypes.endp = _endpos_e_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined2 : (Parsetree.module_type) = Obj.magic _1_inlined2 in
+        let _2_inlined1 : unit = Obj.magic _2_inlined1 in
+        let e : (Parsetree.expression) = Obj.magic e in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.module_expr) = let e =
+          let (_endpos__1_, _startpos__1_, _1, _2) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2, _2_inlined1) in
+          let ty =
+            let _1 =
+              let _1 = 
+# 3247 "parsing/parser.mly"
+      ( Ptyp_package (package_type_of_module_type _1) )
+# 25484 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 25492 "parsing/parser.ml"
+              
+            in
+            
+# 3248 "parsing/parser.mly"
+      ( _1 )
+# 25498 "parsing/parser.ml"
+            
+          in
+          let _endpos_ty_ = _endpos__1_ in
+          let _endpos = _endpos_ty_ in
+          let _startpos = _startpos_e_ in
+          let _loc = (_startpos, _endpos) in
+          
+# 1203 "parsing/parser.mly"
+      ( ghexp ~loc:_loc (Pexp_constraint (e, ty)) )
+# 25508 "parsing/parser.ml"
+          
+        in
+        let attrs =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 25516 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1188 "parsing/parser.mly"
+      ( mkmod ~loc:_sloc ~attrs (Pmod_unpack e) )
+# 25525 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _4;
+              MenhirLib.EngineTypes.startp = _startpos__4_;
+              MenhirLib.EngineTypes.endp = _endpos__4_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _2_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__2_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__2_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = e;
+                    MenhirLib.EngineTypes.startp = _startpos_e_;
+                    MenhirLib.EngineTypes.endp = _endpos_e_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _2;
+                        MenhirLib.EngineTypes.startp = _startpos__2_;
+                        MenhirLib.EngineTypes.endp = _endpos__2_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined3 : (Parsetree.module_type) = Obj.magic _1_inlined3 in
+        let _4 : unit = Obj.magic _4 in
+        let _1_inlined2 : (Parsetree.module_type) = Obj.magic _1_inlined2 in
+        let _2_inlined1 : unit = Obj.magic _2_inlined1 in
+        let e : (Parsetree.expression) = Obj.magic e in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.module_expr) = let e =
+          let (_endpos__1_inlined1_, _startpos__1_inlined1_, _endpos__1_, _startpos__1_, _1_inlined1, _1, _2) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined3, _1_inlined2, _2_inlined1) in
+          let ty2 =
+            let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+            let _1 =
+              let _1 = 
+# 3247 "parsing/parser.mly"
+      ( Ptyp_package (package_type_of_module_type _1) )
+# 25611 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 25619 "parsing/parser.ml"
+              
+            in
+            
+# 3248 "parsing/parser.mly"
+      ( _1 )
+# 25625 "parsing/parser.ml"
+            
+          in
+          let _endpos_ty2_ = _endpos__1_inlined1_ in
+          let ty1 =
+            let _1 =
+              let _1 = 
+# 3247 "parsing/parser.mly"
+      ( Ptyp_package (package_type_of_module_type _1) )
+# 25634 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 25642 "parsing/parser.ml"
+              
+            in
+            
+# 3248 "parsing/parser.mly"
+      ( _1 )
+# 25648 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos_ty2_ in
+          let _startpos = _startpos_e_ in
+          let _loc = (_startpos, _endpos) in
+          
+# 1205 "parsing/parser.mly"
+      ( ghexp ~loc:_loc (Pexp_coerce (e, Some ty1, ty2)) )
+# 25657 "parsing/parser.ml"
+          
+        in
+        let attrs =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 25665 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1188 "parsing/parser.mly"
+      ( mkmod ~loc:_sloc ~attrs (Pmod_unpack e) )
+# 25674 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined2;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__2_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__2_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = e;
+                MenhirLib.EngineTypes.startp = _startpos_e_;
+                MenhirLib.EngineTypes.endp = _endpos_e_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined2 : (Parsetree.module_type) = Obj.magic _1_inlined2 in
+        let _2_inlined1 : unit = Obj.magic _2_inlined1 in
+        let e : (Parsetree.expression) = Obj.magic e in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.module_expr) = let e =
+          let (_endpos__1_, _startpos__1_, _1, _2) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2, _2_inlined1) in
+          let ty2 =
+            let _1 =
+              let _1 = 
+# 3247 "parsing/parser.mly"
+      ( Ptyp_package (package_type_of_module_type _1) )
+# 25745 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 25753 "parsing/parser.ml"
+              
+            in
+            
+# 3248 "parsing/parser.mly"
+      ( _1 )
+# 25759 "parsing/parser.ml"
+            
+          in
+          let _endpos_ty2_ = _endpos__1_ in
+          let _endpos = _endpos_ty2_ in
+          let _startpos = _startpos_e_ in
+          let _loc = (_startpos, _endpos) in
+          
+# 1207 "parsing/parser.mly"
+      ( ghexp ~loc:_loc (Pexp_coerce (e, None, ty2)) )
+# 25769 "parsing/parser.ml"
+          
+        in
+        let attrs =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 25777 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1188 "parsing/parser.mly"
+      ( mkmod ~loc:_sloc ~attrs (Pmod_unpack e) )
+# 25786 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _6;
+          MenhirLib.EngineTypes.startp = _startpos__6_;
+          MenhirLib.EngineTypes.endp = _endpos__6_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _5;
+            MenhirLib.EngineTypes.startp = _startpos__5_;
+            MenhirLib.EngineTypes.endp = _endpos__5_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _4;
+              MenhirLib.EngineTypes.startp = _startpos__4_;
+              MenhirLib.EngineTypes.endp = _endpos__4_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _2;
+                  MenhirLib.EngineTypes.startp = _startpos__2_;
+                  MenhirLib.EngineTypes.endp = _endpos__2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__6_ in
+        let _v : (Parsetree.module_expr) = let _3 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 25848 "parsing/parser.ml"
+          
+        in
+        let _loc__6_ = (_startpos__6_, _endpos__6_) in
+        let _loc__1_ = (_startpos__1_, _endpos__1_) in
+        
+# 1190 "parsing/parser.mly"
+      ( unclosed "(" _loc__1_ ")" _loc__6_ )
+# 25856 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _6;
+          MenhirLib.EngineTypes.startp = _startpos__6_;
+          MenhirLib.EngineTypes.endp = _endpos__6_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _5;
+            MenhirLib.EngineTypes.startp = _startpos__5_;
+            MenhirLib.EngineTypes.endp = _endpos__5_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _4;
+              MenhirLib.EngineTypes.startp = _startpos__4_;
+              MenhirLib.EngineTypes.endp = _endpos__4_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _2;
+                  MenhirLib.EngineTypes.startp = _startpos__2_;
+                  MenhirLib.EngineTypes.endp = _endpos__2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__6_ in
+        let _v : (Parsetree.module_expr) = let _3 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 25918 "parsing/parser.ml"
+          
+        in
+        let _loc__6_ = (_startpos__6_, _endpos__6_) in
+        let _loc__1_ = (_startpos__1_, _endpos__1_) in
+        
+# 1192 "parsing/parser.mly"
+      ( unclosed "(" _loc__1_ ")" _loc__6_ )
+# 25926 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.module_expr) = let _3 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 25981 "parsing/parser.ml"
+          
+        in
+        let _loc__5_ = (_startpos__5_, _endpos__5_) in
+        let _loc__1_ = (_startpos__1_, _endpos__1_) in
+        
+# 1194 "parsing/parser.mly"
+      ( unclosed "(" _loc__1_ ")" _loc__5_ )
+# 25989 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.core_type) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (
+# 754 "parsing/parser.mly"
+      (Parsetree.core_type)
+# 26021 "parsing/parser.ml"
+        ) = 
+# 1087 "parsing/parser.mly"
+    ( _1 )
+# 26025 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (
+# 756 "parsing/parser.mly"
+      (Parsetree.expression)
+# 26057 "parsing/parser.ml"
+        ) = 
+# 1092 "parsing/parser.mly"
+    ( _1 )
+# 26061 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (
+# 758 "parsing/parser.mly"
+      (Parsetree.pattern)
+# 26093 "parsing/parser.ml"
+        ) = 
+# 1097 "parsing/parser.mly"
+    ( _1 )
+# 26097 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.pattern) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _endpos = _endpos__3_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _loc__2_ = (_startpos__2_, _endpos__2_) in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2558 "parsing/parser.mly"
+      ( mkpat_cons ~loc:_sloc _loc__2_ (ghpat ~loc:_sloc (Ppat_tuple[_1;_3])) )
+# 26141 "parsing/parser.ml"
+          
+        in
+        
+# 2546 "parsing/parser.mly"
+      ( _1 )
+# 26147 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.attribute) = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.pattern) = let _1 = 
+# 2560 "parsing/parser.mly"
+      ( Pat.attr _1 _2 )
+# 26179 "parsing/parser.ml"
+         in
+        
+# 2546 "parsing/parser.mly"
+      ( _1 )
+# 26184 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = let _1 = 
+# 2562 "parsing/parser.mly"
+      ( _1 )
+# 26209 "parsing/parser.ml"
+         in
+        
+# 2546 "parsing/parser.mly"
+      ( _1 )
+# 26214 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (string) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 =
+              let _3 =
+                let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 26261 "parsing/parser.ml"
+                
+              in
+              
+# 2565 "parsing/parser.mly"
+        ( Ppat_alias(_1, _3) )
+# 26267 "parsing/parser.ml"
+              
+            in
+            let _endpos__1_ = _endpos__1_inlined1_ in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 26277 "parsing/parser.ml"
+            
+          in
+          
+# 2576 "parsing/parser.mly"
+    ( _1 )
+# 26283 "parsing/parser.ml"
+          
+        in
+        
+# 2546 "parsing/parser.mly"
+      ( _1 )
+# 26289 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 =
+              let _loc__3_ = (_startpos__3_, _endpos__3_) in
+              
+# 2567 "parsing/parser.mly"
+        ( expecting _loc__3_ "identifier" )
+# 26332 "parsing/parser.ml"
+              
+            in
+            let _endpos__1_ = _endpos__3_ in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 26342 "parsing/parser.ml"
+            
+          in
+          
+# 2576 "parsing/parser.mly"
+    ( _1 )
+# 26348 "parsing/parser.ml"
+          
+        in
+        
+# 2546 "parsing/parser.mly"
+      ( _1 )
+# 26354 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.pattern list) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 = 
+# 2569 "parsing/parser.mly"
+        ( Ppat_tuple(List.rev _1) )
+# 26381 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 26389 "parsing/parser.ml"
+            
+          in
+          
+# 2576 "parsing/parser.mly"
+    ( _1 )
+# 26395 "parsing/parser.ml"
+          
+        in
+        
+# 2546 "parsing/parser.mly"
+      ( _1 )
+# 26401 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 =
+              let _loc__3_ = (_startpos__3_, _endpos__3_) in
+              
+# 2571 "parsing/parser.mly"
+        ( expecting _loc__3_ "pattern" )
+# 26444 "parsing/parser.ml"
+              
+            in
+            let _endpos__1_ = _endpos__3_ in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 26454 "parsing/parser.ml"
+            
+          in
+          
+# 2576 "parsing/parser.mly"
+    ( _1 )
+# 26460 "parsing/parser.ml"
+          
+        in
+        
+# 2546 "parsing/parser.mly"
+      ( _1 )
+# 26466 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.pattern) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 = 
+# 2573 "parsing/parser.mly"
+        ( Ppat_or(_1, _3) )
+# 26507 "parsing/parser.ml"
+             in
+            let _endpos__1_ = _endpos__3_ in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 26516 "parsing/parser.ml"
+            
+          in
+          
+# 2576 "parsing/parser.mly"
+    ( _1 )
+# 26522 "parsing/parser.ml"
+          
+        in
+        
+# 2546 "parsing/parser.mly"
+      ( _1 )
+# 26528 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 =
+              let _loc__3_ = (_startpos__3_, _endpos__3_) in
+              
+# 2575 "parsing/parser.mly"
+        ( expecting _loc__3_ "pattern" )
+# 26571 "parsing/parser.ml"
+              
+            in
+            let _endpos__1_ = _endpos__3_ in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 26581 "parsing/parser.ml"
+            
+          in
+          
+# 2576 "parsing/parser.mly"
+    ( _1 )
+# 26587 "parsing/parser.ml"
+          
+        in
+        
+# 2546 "parsing/parser.mly"
+      ( _1 )
+# 26593 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined2;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.pattern) = Obj.magic _3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _2 =
+          let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+          let _2 =
+            let _1 = _1_inlined1 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 26643 "parsing/parser.ml"
+            
+          in
+          
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 26649 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__3_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2548 "parsing/parser.mly"
+      ( mkpat_attrs ~loc:_sloc (Ppat_exception _3) _2)
+# 26658 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.pattern) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern list) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern list) = 
+# 2672 "parsing/parser.mly"
+                                                ( _3 :: _1 )
+# 26697 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.pattern) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern list) = 
+# 2673 "parsing/parser.mly"
+                                                ( [_3; _1] )
+# 26736 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern list) = let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        
+# 2674 "parsing/parser.mly"
+                                                ( expecting _loc__3_ "pattern" )
+# 26776 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.pattern) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern list) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern list) = 
+# 2672 "parsing/parser.mly"
+                                                ( _3 :: _1 )
+# 26815 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.pattern) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern list) = 
+# 2673 "parsing/parser.mly"
+                                                ( [_3; _1] )
+# 26854 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern list) = let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        
+# 2674 "parsing/parser.mly"
+                                                ( expecting _loc__3_ "pattern" )
+# 26894 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = 
+# 2581 "parsing/parser.mly"
+      ( _1 )
+# 26919 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.pattern) = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 26957 "parsing/parser.ml"
+              
+            in
+            
+# 2584 "parsing/parser.mly"
+        ( Ppat_construct(_1, Some _2) )
+# 26963 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 26973 "parsing/parser.ml"
+          
+        in
+        
+# 2587 "parsing/parser.mly"
+      ( _1 )
+# 26979 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.pattern) = Obj.magic _2 in
+        let _1 : (Asttypes.label) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 = 
+# 2586 "parsing/parser.mly"
+        ( Ppat_variant(_1, Some _2) )
+# 27012 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 27021 "parsing/parser.ml"
+          
+        in
+        
+# 2587 "parsing/parser.mly"
+      ( _1 )
+# 27027 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined2;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.pattern) = Obj.magic _3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _2 =
+          let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+          let _2 =
+            let _1 = _1_inlined1 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 27077 "parsing/parser.ml"
+            
+          in
+          
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 27083 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__3_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2589 "parsing/parser.mly"
+      ( mkpat_attrs ~loc:_sloc (Ppat_lazy _3) _2)
+# 27092 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.pattern) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _endpos = _endpos__3_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _loc__2_ = (_startpos__2_, _endpos__2_) in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2558 "parsing/parser.mly"
+      ( mkpat_cons ~loc:_sloc _loc__2_ (ghpat ~loc:_sloc (Ppat_tuple[_1;_3])) )
+# 27136 "parsing/parser.ml"
+          
+        in
+        
+# 2553 "parsing/parser.mly"
+      ( _1 )
+# 27142 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.attribute) = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.pattern) = let _1 = 
+# 2560 "parsing/parser.mly"
+      ( Pat.attr _1 _2 )
+# 27174 "parsing/parser.ml"
+         in
+        
+# 2553 "parsing/parser.mly"
+      ( _1 )
+# 27179 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = let _1 = 
+# 2562 "parsing/parser.mly"
+      ( _1 )
+# 27204 "parsing/parser.ml"
+         in
+        
+# 2553 "parsing/parser.mly"
+      ( _1 )
+# 27209 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (string) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 =
+              let _3 =
+                let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 27256 "parsing/parser.ml"
+                
+              in
+              
+# 2565 "parsing/parser.mly"
+        ( Ppat_alias(_1, _3) )
+# 27262 "parsing/parser.ml"
+              
+            in
+            let _endpos__1_ = _endpos__1_inlined1_ in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 27272 "parsing/parser.ml"
+            
+          in
+          
+# 2576 "parsing/parser.mly"
+    ( _1 )
+# 27278 "parsing/parser.ml"
+          
+        in
+        
+# 2553 "parsing/parser.mly"
+      ( _1 )
+# 27284 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 =
+              let _loc__3_ = (_startpos__3_, _endpos__3_) in
+              
+# 2567 "parsing/parser.mly"
+        ( expecting _loc__3_ "identifier" )
+# 27327 "parsing/parser.ml"
+              
+            in
+            let _endpos__1_ = _endpos__3_ in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 27337 "parsing/parser.ml"
+            
+          in
+          
+# 2576 "parsing/parser.mly"
+    ( _1 )
+# 27343 "parsing/parser.ml"
+          
+        in
+        
+# 2553 "parsing/parser.mly"
+      ( _1 )
+# 27349 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.pattern list) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 = 
+# 2569 "parsing/parser.mly"
+        ( Ppat_tuple(List.rev _1) )
+# 27376 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 27384 "parsing/parser.ml"
+            
+          in
+          
+# 2576 "parsing/parser.mly"
+    ( _1 )
+# 27390 "parsing/parser.ml"
+          
+        in
+        
+# 2553 "parsing/parser.mly"
+      ( _1 )
+# 27396 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 =
+              let _loc__3_ = (_startpos__3_, _endpos__3_) in
+              
+# 2571 "parsing/parser.mly"
+        ( expecting _loc__3_ "pattern" )
+# 27439 "parsing/parser.ml"
+              
+            in
+            let _endpos__1_ = _endpos__3_ in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 27449 "parsing/parser.ml"
+            
+          in
+          
+# 2576 "parsing/parser.mly"
+    ( _1 )
+# 27455 "parsing/parser.ml"
+          
+        in
+        
+# 2553 "parsing/parser.mly"
+      ( _1 )
+# 27461 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.pattern) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 = 
+# 2573 "parsing/parser.mly"
+        ( Ppat_or(_1, _3) )
+# 27502 "parsing/parser.ml"
+             in
+            let _endpos__1_ = _endpos__3_ in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 27511 "parsing/parser.ml"
+            
+          in
+          
+# 2576 "parsing/parser.mly"
+    ( _1 )
+# 27517 "parsing/parser.ml"
+          
+        in
+        
+# 2553 "parsing/parser.mly"
+      ( _1 )
+# 27523 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 =
+              let _loc__3_ = (_startpos__3_, _endpos__3_) in
+              
+# 2575 "parsing/parser.mly"
+        ( expecting _loc__3_ "pattern" )
+# 27566 "parsing/parser.ml"
+              
+            in
+            let _endpos__1_ = _endpos__3_ in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 27576 "parsing/parser.ml"
+            
+          in
+          
+# 2576 "parsing/parser.mly"
+    ( _1 )
+# 27582 "parsing/parser.ml"
+          
+        in
+        
+# 2553 "parsing/parser.mly"
+      ( _1 )
+# 27588 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 27609 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 27623 "parsing/parser.ml"
+              
+            in
+            
+# 2034 "parsing/parser.mly"
+                        ( Ppat_var _1 )
+# 27629 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 27638 "parsing/parser.ml"
+          
+        in
+        
+# 2036 "parsing/parser.mly"
+    ( _1 )
+# 27644 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 = 
+# 2035 "parsing/parser.mly"
+                        ( Ppat_any )
+# 27670 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 27678 "parsing/parser.ml"
+          
+        in
+        
+# 2036 "parsing/parser.mly"
+    ( _1 )
+# 27684 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.structure) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.payload) = 
+# 3662 "parsing/parser.mly"
+              ( PStr _1 )
+# 27709 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.signature) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.payload) = 
+# 3663 "parsing/parser.mly"
+                    ( PSig _2 )
+# 27741 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.core_type) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.payload) = 
+# 3664 "parsing/parser.mly"
+                    ( PTyp _2 )
+# 27773 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.pattern) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.payload) = 
+# 3665 "parsing/parser.mly"
+                     ( PPat (_2, None) )
+# 27805 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.pattern) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.payload) = 
+# 3666 "parsing/parser.mly"
+                                   ( PPat (_2, Some _4) )
+# 27851 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.core_type) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.core_type) = 
+# 3085 "parsing/parser.mly"
+    ( _1 )
+# 27876 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.core_type) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let xs : (Asttypes.label Asttypes.loc list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let _1 =
+              let _1 =
+                let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 27919 "parsing/parser.ml"
+                 in
+                
+# 872 "parsing/parser.mly"
+    ( xs )
+# 27924 "parsing/parser.ml"
+                
+              in
+              
+# 3077 "parsing/parser.mly"
+    ( _1 )
+# 27930 "parsing/parser.ml"
+              
+            in
+            
+# 3081 "parsing/parser.mly"
+    ( Ptyp_poly(_1, _3) )
+# 27936 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos__3_, _startpos_xs_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 27946 "parsing/parser.ml"
+          
+        in
+        
+# 3087 "parsing/parser.mly"
+    ( _1 )
+# 27952 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.core_type) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.core_type) = let _1 = 
+# 3116 "parsing/parser.mly"
+    ( _1 )
+# 27977 "parsing/parser.ml"
+         in
+        
+# 3085 "parsing/parser.mly"
+    ( _1 )
+# 27982 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1 : (Parsetree.core_type) = Obj.magic _1 in
+        let _2 : unit = Obj.magic _2 in
+        let xs : (Asttypes.label Asttypes.loc list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let _3 = 
+# 3116 "parsing/parser.mly"
+    ( _1 )
+# 28023 "parsing/parser.ml"
+             in
+            let _1 =
+              let _1 =
+                let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 28030 "parsing/parser.ml"
+                 in
+                
+# 872 "parsing/parser.mly"
+    ( xs )
+# 28035 "parsing/parser.ml"
+                
+              in
+              
+# 3077 "parsing/parser.mly"
+    ( _1 )
+# 28041 "parsing/parser.ml"
+              
+            in
+            
+# 3081 "parsing/parser.mly"
+    ( Ptyp_poly(_1, _3) )
+# 28047 "parsing/parser.ml"
+            
+          in
+          let _startpos__1_ = _startpos_xs_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 28057 "parsing/parser.ml"
+          
+        in
+        
+# 3087 "parsing/parser.mly"
+    ( _1 )
+# 28063 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.payload) = Obj.magic _3 in
+        let _2 : (string Asttypes.loc) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.attribute) = let _endpos = _endpos__4_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3629 "parsing/parser.mly"
+    ( Attr.mk ~loc:(make_loc _sloc) _2 _3 )
+# 28112 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = prim;
+            MenhirLib.EngineTypes.startp = _startpos_prim_;
+            MenhirLib.EngineTypes.endp = _endpos_prim_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _7;
+              MenhirLib.EngineTypes.startp = _startpos__7_;
+              MenhirLib.EngineTypes.endp = _endpos__7_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = ty;
+                MenhirLib.EngineTypes.startp = _startpos_ty_;
+                MenhirLib.EngineTypes.endp = _endpos_ty_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _5;
+                  MenhirLib.EngineTypes.startp = _startpos__5_;
+                  MenhirLib.EngineTypes.endp = _endpos__5_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined2;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = ext;
+                        MenhirLib.EngineTypes.startp = _startpos_ext_;
+                        MenhirLib.EngineTypes.endp = _endpos_ext_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let prim : (string list) = Obj.magic prim in
+        let _7 : unit = Obj.magic _7 in
+        let ty : (Parsetree.core_type) = Obj.magic ty in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined2 : (string) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (Parsetree.value_description * string Asttypes.loc option) = let attrs2 =
+          let _1 = _1_inlined3 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 28195 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs2_ = _endpos__1_inlined3_ in
+        let id =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 28207 "parsing/parser.ml"
+          
+        in
+        let attrs1 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 28215 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_attrs2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2733 "parsing/parser.mly"
+    ( let attrs = attrs1 @ attrs2 in
+      let loc = make_loc _sloc in
+      let docs = symbol_docs _sloc in
+      Val.mk id ty ~prim ~attrs ~loc ~docs,
+      ext )
+# 28228 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Asttypes.private_flag) = let _1 = 
+# 3497 "parsing/parser.mly"
+                                                ( Public )
+# 28246 "parsing/parser.ml"
+         in
+        
+# 3494 "parsing/parser.mly"
+    ( _1 )
+# 28251 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.private_flag) = let _1 = 
+# 3498 "parsing/parser.mly"
+                                                ( Private )
+# 28276 "parsing/parser.ml"
+         in
+        
+# 3494 "parsing/parser.mly"
+    ( _1 )
+# 28281 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Asttypes.private_flag * Asttypes.virtual_flag) = 
+# 3520 "parsing/parser.mly"
+                 ( Public, Concrete )
+# 28299 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.private_flag * Asttypes.virtual_flag) = 
+# 3521 "parsing/parser.mly"
+            ( Private, Concrete )
+# 28324 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.private_flag * Asttypes.virtual_flag) = 
+# 3522 "parsing/parser.mly"
+            ( Public, Virtual )
+# 28349 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Asttypes.private_flag * Asttypes.virtual_flag) = 
+# 3523 "parsing/parser.mly"
+                    ( Private, Virtual )
+# 28381 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Asttypes.private_flag * Asttypes.virtual_flag) = 
+# 3524 "parsing/parser.mly"
+                    ( Private, Virtual )
+# 28413 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Asttypes.rec_flag) = 
+# 3477 "parsing/parser.mly"
+                                                ( Nonrecursive )
+# 28431 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.rec_flag) = 
+# 3478 "parsing/parser.mly"
+                                                ( Recursive )
+# 28456 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = fields;
+          MenhirLib.EngineTypes.startp = _startpos_fields_;
+          MenhirLib.EngineTypes.endp = _endpos_fields_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let fields : ((Longident.t Asttypes.loc * Parsetree.expression) list) = Obj.magic fields in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_fields_ in
+        let _endpos = _endpos_fields_ in
+        let _v : (Parsetree.expression option *
+  (Longident.t Asttypes.loc * Parsetree.expression) list) = let eo = 
+# 124 "menhir/standard.mly"
+    ( None )
+# 28482 "parsing/parser.ml"
+         in
+        
+# 2478 "parsing/parser.mly"
+    ( eo, fields )
+# 28487 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = fields;
+          MenhirLib.EngineTypes.startp = _startpos_fields_;
+          MenhirLib.EngineTypes.endp = _endpos_fields_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = x;
+              MenhirLib.EngineTypes.startp = _startpos_x_;
+              MenhirLib.EngineTypes.endp = _endpos_x_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let fields : ((Longident.t Asttypes.loc * Parsetree.expression) list) = Obj.magic fields in
+        let _2 : unit = Obj.magic _2 in
+        let x : (Parsetree.expression) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_fields_ in
+        let _v : (Parsetree.expression option *
+  (Longident.t Asttypes.loc * Parsetree.expression) list) = let eo =
+          let x = 
+# 191 "menhir/standard.mly"
+    ( x )
+# 28528 "parsing/parser.ml"
+           in
+          
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 28533 "parsing/parser.ml"
+          
+        in
+        
+# 2478 "parsing/parser.mly"
+    ( eo, fields )
+# 28539 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = d;
+          MenhirLib.EngineTypes.startp = _startpos_d_;
+          MenhirLib.EngineTypes.endp = _endpos_d_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let d : (Ast_helper.str * Parsetree.constructor_arguments *
+  Parsetree.core_type option * Parsetree.attributes * Location.t *
+  Docstrings.info) = Obj.magic d in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_d_ in
+        let _endpos = _endpos_d_ in
+        let _v : (Parsetree.constructor_declaration list) = let x = 
+# 2907 "parsing/parser.mly"
+    (
+      let cid, args, res, attrs, loc, info = d in
+      Type.constructor cid ~args ?res ~attrs ~loc ~info
+    )
+# 28569 "parsing/parser.ml"
+         in
+        
+# 982 "parsing/parser.mly"
+      ( [x] )
+# 28574 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = d;
+          MenhirLib.EngineTypes.startp = _startpos_d_;
+          MenhirLib.EngineTypes.endp = _endpos_d_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let d : (Ast_helper.str * Parsetree.constructor_arguments *
+  Parsetree.core_type option * Parsetree.attributes * Location.t *
+  Docstrings.info) = Obj.magic d in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_d_ in
+        let _endpos = _endpos_d_ in
+        let _v : (Parsetree.constructor_declaration list) = let x = 
+# 2907 "parsing/parser.mly"
+    (
+      let cid, args, res, attrs, loc, info = d in
+      Type.constructor cid ~args ?res ~attrs ~loc ~info
+    )
+# 28604 "parsing/parser.ml"
+         in
+        
+# 985 "parsing/parser.mly"
+      ( [x] )
+# 28609 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = d;
+          MenhirLib.EngineTypes.startp = _startpos_d_;
+          MenhirLib.EngineTypes.endp = _endpos_d_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let d : (Ast_helper.str * Parsetree.constructor_arguments *
+  Parsetree.core_type option * Parsetree.attributes * Location.t *
+  Docstrings.info) = Obj.magic d in
+        let xs : (Parsetree.constructor_declaration list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_d_ in
+        let _v : (Parsetree.constructor_declaration list) = let x = 
+# 2907 "parsing/parser.mly"
+    (
+      let cid, args, res, attrs, loc, info = d in
+      Type.constructor cid ~args ?res ~attrs ~loc ~info
+    )
+# 28646 "parsing/parser.ml"
+         in
+        
+# 989 "parsing/parser.mly"
+      ( x :: xs )
+# 28651 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = d;
+          MenhirLib.EngineTypes.startp = _startpos_d_;
+          MenhirLib.EngineTypes.endp = _endpos_d_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let d : (Ast_helper.str * Parsetree.constructor_arguments *
+  Parsetree.core_type option * Parsetree.attributes * Location.t *
+  Docstrings.info) = Obj.magic d in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_d_ in
+        let _endpos = _endpos_d_ in
+        let _v : (Parsetree.extension_constructor list) = let x =
+          let _1 = 
+# 3019 "parsing/parser.mly"
+    (
+      let cid, args, res, attrs, loc, info = d in
+      Te.decl cid ~args ?res ~attrs ~loc ~info
+    )
+# 28682 "parsing/parser.ml"
+           in
+          
+# 3013 "parsing/parser.mly"
+      ( _1 )
+# 28687 "parsing/parser.ml"
+          
+        in
+        
+# 982 "parsing/parser.mly"
+      ( [x] )
+# 28693 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.extension_constructor) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.extension_constructor list) = let x = 
+# 3015 "parsing/parser.mly"
+      ( _1 )
+# 28718 "parsing/parser.ml"
+         in
+        
+# 982 "parsing/parser.mly"
+      ( [x] )
+# 28723 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = d;
+          MenhirLib.EngineTypes.startp = _startpos_d_;
+          MenhirLib.EngineTypes.endp = _endpos_d_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let d : (Ast_helper.str * Parsetree.constructor_arguments *
+  Parsetree.core_type option * Parsetree.attributes * Location.t *
+  Docstrings.info) = Obj.magic d in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_d_ in
+        let _endpos = _endpos_d_ in
+        let _v : (Parsetree.extension_constructor list) = let x =
+          let _1 = 
+# 3019 "parsing/parser.mly"
+    (
+      let cid, args, res, attrs, loc, info = d in
+      Te.decl cid ~args ?res ~attrs ~loc ~info
+    )
+# 28754 "parsing/parser.ml"
+           in
+          
+# 3013 "parsing/parser.mly"
+      ( _1 )
+# 28759 "parsing/parser.ml"
+          
+        in
+        
+# 985 "parsing/parser.mly"
+      ( [x] )
+# 28765 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.extension_constructor) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.extension_constructor list) = let x = 
+# 3015 "parsing/parser.mly"
+      ( _1 )
+# 28790 "parsing/parser.ml"
+         in
+        
+# 985 "parsing/parser.mly"
+      ( [x] )
+# 28795 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = d;
+          MenhirLib.EngineTypes.startp = _startpos_d_;
+          MenhirLib.EngineTypes.endp = _endpos_d_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let d : (Ast_helper.str * Parsetree.constructor_arguments *
+  Parsetree.core_type option * Parsetree.attributes * Location.t *
+  Docstrings.info) = Obj.magic d in
+        let xs : (Parsetree.extension_constructor list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_d_ in
+        let _v : (Parsetree.extension_constructor list) = let x =
+          let _1 = 
+# 3019 "parsing/parser.mly"
+    (
+      let cid, args, res, attrs, loc, info = d in
+      Te.decl cid ~args ?res ~attrs ~loc ~info
+    )
+# 28833 "parsing/parser.ml"
+           in
+          
+# 3013 "parsing/parser.mly"
+      ( _1 )
+# 28838 "parsing/parser.ml"
+          
+        in
+        
+# 989 "parsing/parser.mly"
+      ( x :: xs )
+# 28844 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _1 : (Parsetree.extension_constructor) = Obj.magic _1 in
+        let xs : (Parsetree.extension_constructor list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.extension_constructor list) = let x = 
+# 3015 "parsing/parser.mly"
+      ( _1 )
+# 28876 "parsing/parser.ml"
+         in
+        
+# 989 "parsing/parser.mly"
+      ( x :: xs )
+# 28881 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = d;
+          MenhirLib.EngineTypes.startp = _startpos_d_;
+          MenhirLib.EngineTypes.endp = _endpos_d_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let d : (Ast_helper.str * Parsetree.constructor_arguments *
+  Parsetree.core_type option * Parsetree.attributes * Location.t *
+  Docstrings.info) = Obj.magic d in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_d_ in
+        let _endpos = _endpos_d_ in
+        let _v : (Parsetree.extension_constructor list) = let x = 
+# 3019 "parsing/parser.mly"
+    (
+      let cid, args, res, attrs, loc, info = d in
+      Te.decl cid ~args ?res ~attrs ~loc ~info
+    )
+# 28911 "parsing/parser.ml"
+         in
+        
+# 982 "parsing/parser.mly"
+      ( [x] )
+# 28916 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = d;
+          MenhirLib.EngineTypes.startp = _startpos_d_;
+          MenhirLib.EngineTypes.endp = _endpos_d_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let d : (Ast_helper.str * Parsetree.constructor_arguments *
+  Parsetree.core_type option * Parsetree.attributes * Location.t *
+  Docstrings.info) = Obj.magic d in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_d_ in
+        let _endpos = _endpos_d_ in
+        let _v : (Parsetree.extension_constructor list) = let x = 
+# 3019 "parsing/parser.mly"
+    (
+      let cid, args, res, attrs, loc, info = d in
+      Te.decl cid ~args ?res ~attrs ~loc ~info
+    )
+# 28946 "parsing/parser.ml"
+         in
+        
+# 985 "parsing/parser.mly"
+      ( [x] )
+# 28951 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = d;
+          MenhirLib.EngineTypes.startp = _startpos_d_;
+          MenhirLib.EngineTypes.endp = _endpos_d_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let d : (Ast_helper.str * Parsetree.constructor_arguments *
+  Parsetree.core_type option * Parsetree.attributes * Location.t *
+  Docstrings.info) = Obj.magic d in
+        let xs : (Parsetree.extension_constructor list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_d_ in
+        let _v : (Parsetree.extension_constructor list) = let x = 
+# 3019 "parsing/parser.mly"
+    (
+      let cid, args, res, attrs, loc, info = d in
+      Te.decl cid ~args ?res ~attrs ~loc ~info
+    )
+# 28988 "parsing/parser.ml"
+         in
+        
+# 989 "parsing/parser.mly"
+      ( x :: xs )
+# 28993 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : ((Parsetree.core_type * Parsetree.core_type * Ast_helper.loc) list) = 
+# 848 "parsing/parser.mly"
+    ( [] )
+# 29011 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = xs;
+                  MenhirLib.EngineTypes.startp = _startpos_xs_;
+                  MenhirLib.EngineTypes.endp = _endpos_xs_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.core_type) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1_inlined1 : (Parsetree.core_type) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let xs : ((Parsetree.core_type * Parsetree.core_type * Ast_helper.loc) list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos__3_ in
+        let _v : ((Parsetree.core_type * Parsetree.core_type * Ast_helper.loc) list) = let x =
+          let x =
+            let (_startpos__1_, _1) = (_startpos__1_inlined1_, _1_inlined1) in
+            let _endpos = _endpos__3_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 1914 "parsing/parser.mly"
+    ( _1, _3, make_loc _sloc )
+# 29070 "parsing/parser.ml"
+            
+          in
+          
+# 183 "menhir/standard.mly"
+    ( x )
+# 29076 "parsing/parser.ml"
+          
+        in
+        
+# 850 "parsing/parser.mly"
+    ( x :: xs )
+# 29082 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : (string Asttypes.loc * Parsetree.module_type option) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : ((string Asttypes.loc * Parsetree.module_type option) list) = 
+# 862 "parsing/parser.mly"
+    ( [ x ] )
+# 29107 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let x : (string Asttypes.loc * Parsetree.module_type option) = Obj.magic x in
+        let xs : ((string Asttypes.loc * Parsetree.module_type option) list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_x_ in
+        let _v : ((string Asttypes.loc * Parsetree.module_type option) list) = 
+# 864 "parsing/parser.mly"
+    ( x :: xs )
+# 29139 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : (Asttypes.arg_label * Parsetree.expression) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : ((Asttypes.arg_label * Parsetree.expression) list) = 
+# 862 "parsing/parser.mly"
+    ( [ x ] )
+# 29164 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let x : (Asttypes.arg_label * Parsetree.expression) = Obj.magic x in
+        let xs : ((Asttypes.arg_label * Parsetree.expression) list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_x_ in
+        let _v : ((Asttypes.arg_label * Parsetree.expression) list) = 
+# 864 "parsing/parser.mly"
+    ( x :: xs )
+# 29196 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : (Asttypes.label) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Asttypes.label list) = 
+# 862 "parsing/parser.mly"
+    ( [ x ] )
+# 29221 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let x : (Asttypes.label) = Obj.magic x in
+        let xs : (Asttypes.label list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Asttypes.label list) = 
+# 864 "parsing/parser.mly"
+    ( x :: xs )
+# 29253 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Asttypes.label) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Asttypes.label Asttypes.loc list) = let x =
+          let _2 =
+            let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 29291 "parsing/parser.ml"
+            
+          in
+          
+# 3073 "parsing/parser.mly"
+    ( _2 )
+# 29297 "parsing/parser.ml"
+          
+        in
+        
+# 862 "parsing/parser.mly"
+    ( [ x ] )
+# 29303 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Asttypes.label) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let xs : (Asttypes.label Asttypes.loc list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Asttypes.label Asttypes.loc list) = let x =
+          let _2 =
+            let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 29348 "parsing/parser.ml"
+            
+          in
+          
+# 3073 "parsing/parser.mly"
+    ( _2 )
+# 29354 "parsing/parser.ml"
+          
+        in
+        
+# 864 "parsing/parser.mly"
+    ( x :: xs )
+# 29360 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : (Parsetree.case) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.case list) = let _1 = 
+# 124 "menhir/standard.mly"
+    ( None )
+# 29385 "parsing/parser.ml"
+         in
+        
+# 953 "parsing/parser.mly"
+    ( [x] )
+# 29390 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = x_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos_x_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos_x_inlined1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.case) = Obj.magic x in
+        let x_inlined1 : unit = Obj.magic x_inlined1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_inlined1_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.case list) = let _1 =
+          let x = x_inlined1 in
+          
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 29424 "parsing/parser.ml"
+          
+        in
+        
+# 953 "parsing/parser.mly"
+    ( [x] )
+# 29430 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.case) = Obj.magic x in
+        let _2 : unit = Obj.magic _2 in
+        let xs : (Parsetree.case list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.case list) = 
+# 957 "parsing/parser.mly"
+    ( x :: xs )
+# 29469 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.core_type) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.core_type list) = let xs =
+          let x = 
+# 3116 "parsing/parser.mly"
+    ( _1 )
+# 29495 "parsing/parser.ml"
+           in
+          
+# 888 "parsing/parser.mly"
+    ( [ x ] )
+# 29500 "parsing/parser.ml"
+          
+        in
+        
+# 896 "parsing/parser.mly"
+    ( xs )
+# 29506 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1 : (Parsetree.core_type) = Obj.magic _1 in
+        let _2 : unit = Obj.magic _2 in
+        let xs : (Parsetree.core_type list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.core_type list) = let xs =
+          let x = 
+# 3116 "parsing/parser.mly"
+    ( _1 )
+# 29546 "parsing/parser.ml"
+           in
+          
+# 892 "parsing/parser.mly"
+    ( x :: xs )
+# 29551 "parsing/parser.ml"
+          
+        in
+        
+# 896 "parsing/parser.mly"
+    ( xs )
+# 29557 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : (Parsetree.with_constraint) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.with_constraint list) = let xs = 
+# 888 "parsing/parser.mly"
+    ( [ x ] )
+# 29582 "parsing/parser.ml"
+         in
+        
+# 896 "parsing/parser.mly"
+    ( xs )
+# 29587 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.with_constraint) = Obj.magic x in
+        let _2 : unit = Obj.magic _2 in
+        let xs : (Parsetree.with_constraint list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.with_constraint list) = let xs = 
+# 892 "parsing/parser.mly"
+    ( x :: xs )
+# 29626 "parsing/parser.ml"
+         in
+        
+# 896 "parsing/parser.mly"
+    ( xs )
+# 29631 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : (Parsetree.row_field) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.row_field list) = let xs = 
+# 888 "parsing/parser.mly"
+    ( [ x ] )
+# 29656 "parsing/parser.ml"
+         in
+        
+# 896 "parsing/parser.mly"
+    ( xs )
+# 29661 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.row_field) = Obj.magic x in
+        let _2 : unit = Obj.magic _2 in
+        let xs : (Parsetree.row_field list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.row_field list) = let xs = 
+# 892 "parsing/parser.mly"
+    ( x :: xs )
+# 29700 "parsing/parser.ml"
+         in
+        
+# 896 "parsing/parser.mly"
+    ( xs )
+# 29705 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : (Parsetree.core_type) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.core_type list) = let xs = 
+# 888 "parsing/parser.mly"
+    ( [ x ] )
+# 29730 "parsing/parser.ml"
+         in
+        
+# 896 "parsing/parser.mly"
+    ( xs )
+# 29735 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.core_type) = Obj.magic x in
+        let _2 : unit = Obj.magic _2 in
+        let xs : (Parsetree.core_type list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.core_type list) = let xs = 
+# 892 "parsing/parser.mly"
+    ( x :: xs )
+# 29774 "parsing/parser.ml"
+         in
+        
+# 896 "parsing/parser.mly"
+    ( xs )
+# 29779 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : (Parsetree.core_type * Asttypes.variance) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : ((Parsetree.core_type * Asttypes.variance) list) = let xs = 
+# 888 "parsing/parser.mly"
+    ( [ x ] )
+# 29804 "parsing/parser.ml"
+         in
+        
+# 896 "parsing/parser.mly"
+    ( xs )
+# 29809 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.core_type * Asttypes.variance) = Obj.magic x in
+        let _2 : unit = Obj.magic _2 in
+        let xs : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_x_ in
+        let _v : ((Parsetree.core_type * Asttypes.variance) list) = let xs = 
+# 892 "parsing/parser.mly"
+    ( x :: xs )
+# 29848 "parsing/parser.ml"
+         in
+        
+# 896 "parsing/parser.mly"
+    ( xs )
+# 29853 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : (Parsetree.core_type) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.core_type list) = let xs = 
+# 888 "parsing/parser.mly"
+    ( [ x ] )
+# 29878 "parsing/parser.ml"
+         in
+        
+# 896 "parsing/parser.mly"
+    ( xs )
+# 29883 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.core_type) = Obj.magic x in
+        let _2 : unit = Obj.magic _2 in
+        let xs : (Parsetree.core_type list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.core_type list) = let xs = 
+# 892 "parsing/parser.mly"
+    ( x :: xs )
+# 29922 "parsing/parser.ml"
+         in
+        
+# 896 "parsing/parser.mly"
+    ( xs )
+# 29927 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.core_type) = Obj.magic x in
+        let _2 : unit = Obj.magic _2 in
+        let xs : (Parsetree.core_type list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.core_type list) = 
+# 919 "parsing/parser.mly"
+    ( x :: xs )
+# 29966 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x2;
+          MenhirLib.EngineTypes.startp = _startpos_x2_;
+          MenhirLib.EngineTypes.endp = _endpos_x2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = x1;
+              MenhirLib.EngineTypes.startp = _startpos_x1_;
+              MenhirLib.EngineTypes.endp = _endpos_x1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let x2 : (Parsetree.core_type) = Obj.magic x2 in
+        let _2 : unit = Obj.magic _2 in
+        let x1 : (Parsetree.core_type) = Obj.magic x1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x1_ in
+        let _endpos = _endpos_x2_ in
+        let _v : (Parsetree.core_type list) = 
+# 923 "parsing/parser.mly"
+    ( [ x2; x1 ] )
+# 30005 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.expression) = Obj.magic x in
+        let _2 : unit = Obj.magic _2 in
+        let xs : (Parsetree.expression list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.expression list) = 
+# 919 "parsing/parser.mly"
+    ( x :: xs )
+# 30044 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x2;
+          MenhirLib.EngineTypes.startp = _startpos_x2_;
+          MenhirLib.EngineTypes.endp = _endpos_x2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = x1;
+              MenhirLib.EngineTypes.startp = _startpos_x1_;
+              MenhirLib.EngineTypes.endp = _endpos_x1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let x2 : (Parsetree.expression) = Obj.magic x2 in
+        let _2 : unit = Obj.magic _2 in
+        let x1 : (Parsetree.expression) = Obj.magic x1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x1_ in
+        let _endpos = _endpos_x2_ in
+        let _v : (Parsetree.expression list) = 
+# 923 "parsing/parser.mly"
+    ( [ x2; x1 ] )
+# 30083 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let x : (Parsetree.core_type) = Obj.magic x in
+        let _2 : unit = Obj.magic _2 in
+        let xs : (Parsetree.core_type list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.core_type list) = 
+# 919 "parsing/parser.mly"
+    ( x :: xs )
+# 30122 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x2;
+          MenhirLib.EngineTypes.startp = _startpos_x2_;
+          MenhirLib.EngineTypes.endp = _endpos_x2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = x1;
+              MenhirLib.EngineTypes.startp = _startpos_x1_;
+              MenhirLib.EngineTypes.endp = _endpos_x1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let x2 : (Parsetree.core_type) = Obj.magic x2 in
+        let _2 : unit = Obj.magic _2 in
+        let x1 : (Parsetree.core_type) = Obj.magic x1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x1_ in
+        let _endpos = _endpos_x2_ in
+        let _v : (Parsetree.core_type list) = 
+# 923 "parsing/parser.mly"
+    ( [ x2; x1 ] )
+# 30161 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.row_field) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.row_field) = 
+# 3256 "parsing/parser.mly"
+      ( _1 )
+# 30186 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.core_type) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.row_field) = let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3258 "parsing/parser.mly"
+      ( Rf.inherit_ ~loc:(make_loc _sloc) _1 )
+# 30214 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : (Parsetree.expression) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.expression list) = let _2 = 
+# 124 "menhir/standard.mly"
+    ( None )
+# 30239 "parsing/parser.ml"
+         in
+        
+# 940 "parsing/parser.mly"
+    ( [x] )
+# 30244 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos_x_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos_x_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = x;
+            MenhirLib.EngineTypes.startp = _startpos_x_;
+            MenhirLib.EngineTypes.endp = _endpos_x_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let x_inlined1 : unit = Obj.magic x_inlined1 in
+        let x : (Parsetree.expression) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_inlined1_ in
+        let _v : (Parsetree.expression list) = let _2 =
+          let x = x_inlined1 in
+          
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 30278 "parsing/parser.ml"
+          
+        in
+        
+# 940 "parsing/parser.mly"
+    ( [x] )
+# 30284 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = x;
+              MenhirLib.EngineTypes.startp = _startpos_x_;
+              MenhirLib.EngineTypes.endp = _endpos_x_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.expression list) = Obj.magic xs in
+        let _2 : unit = Obj.magic _2 in
+        let x : (Parsetree.expression) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.expression list) = 
+# 944 "parsing/parser.mly"
+    ( x :: xs )
+# 30323 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = oe;
+          MenhirLib.EngineTypes.startp = _startpos_oe_;
+          MenhirLib.EngineTypes.endp = _endpos_oe_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let oe : (Parsetree.expression option) = Obj.magic oe in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 30351 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_oe_ in
+        let _v : ((Asttypes.label Asttypes.loc * Parsetree.expression) list) = let _2 = 
+# 124 "menhir/standard.mly"
+    ( None )
+# 30359 "parsing/parser.ml"
+         in
+        let x =
+          let label =
+            let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 30366 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 30374 "parsing/parser.ml"
+            
+          in
+          let _startpos_label_ = _startpos__1_ in
+          let _endpos = _endpos_oe_ in
+          let _symbolstartpos = _startpos_label_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2501 "parsing/parser.mly"
+      ( let e =
+          match oe with
+          | None ->
+              (* No expression; this is a pun. Desugar it. *)
+              exp_of_label ~loc:_sloc label
+          | Some e ->
+              e
+        in
+        label, e )
+# 30392 "parsing/parser.ml"
+          
+        in
+        
+# 940 "parsing/parser.mly"
+    ( [x] )
+# 30398 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = oe;
+            MenhirLib.EngineTypes.startp = _startpos_oe_;
+            MenhirLib.EngineTypes.endp = _endpos_oe_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let x : unit = Obj.magic x in
+        let oe : (Parsetree.expression option) = Obj.magic oe in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 30433 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_x_ in
+        let _v : ((Asttypes.label Asttypes.loc * Parsetree.expression) list) = let _2 = 
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 30441 "parsing/parser.ml"
+         in
+        let x =
+          let label =
+            let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 30448 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 30456 "parsing/parser.ml"
+            
+          in
+          let _startpos_label_ = _startpos__1_ in
+          let _endpos = _endpos_oe_ in
+          let _symbolstartpos = _startpos_label_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2501 "parsing/parser.mly"
+      ( let e =
+          match oe with
+          | None ->
+              (* No expression; this is a pun. Desugar it. *)
+              exp_of_label ~loc:_sloc label
+          | Some e ->
+              e
+        in
+        label, e )
+# 30474 "parsing/parser.ml"
+          
+        in
+        
+# 940 "parsing/parser.mly"
+    ( [x] )
+# 30480 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = oe;
+              MenhirLib.EngineTypes.startp = _startpos_oe_;
+              MenhirLib.EngineTypes.endp = _endpos_oe_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let xs : ((Asttypes.label Asttypes.loc * Parsetree.expression) list) = Obj.magic xs in
+        let _2 : unit = Obj.magic _2 in
+        let oe : (Parsetree.expression option) = Obj.magic oe in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 30522 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : ((Asttypes.label Asttypes.loc * Parsetree.expression) list) = let x =
+          let label =
+            let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 30532 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 30540 "parsing/parser.ml"
+            
+          in
+          let _startpos_label_ = _startpos__1_ in
+          let _endpos = _endpos_oe_ in
+          let _symbolstartpos = _startpos_label_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2501 "parsing/parser.mly"
+      ( let e =
+          match oe with
+          | None ->
+              (* No expression; this is a pun. Desugar it. *)
+              exp_of_label ~loc:_sloc label
+          | Some e ->
+              e
+        in
+        label, e )
+# 30558 "parsing/parser.ml"
+          
+        in
+        
+# 944 "parsing/parser.mly"
+    ( x :: xs )
+# 30564 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let x : (Parsetree.pattern) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_ in
+        let _v : (Parsetree.pattern list) = let _2 = 
+# 124 "menhir/standard.mly"
+    ( None )
+# 30589 "parsing/parser.ml"
+         in
+        
+# 940 "parsing/parser.mly"
+    ( [x] )
+# 30594 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos_x_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos_x_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = x;
+            MenhirLib.EngineTypes.startp = _startpos_x_;
+            MenhirLib.EngineTypes.endp = _endpos_x_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let x_inlined1 : unit = Obj.magic x_inlined1 in
+        let x : (Parsetree.pattern) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_x_inlined1_ in
+        let _v : (Parsetree.pattern list) = let _2 =
+          let x = x_inlined1 in
+          
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 30628 "parsing/parser.ml"
+          
+        in
+        
+# 940 "parsing/parser.mly"
+    ( [x] )
+# 30634 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = x;
+              MenhirLib.EngineTypes.startp = _startpos_x_;
+              MenhirLib.EngineTypes.endp = _endpos_x_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let xs : (Parsetree.pattern list) = Obj.magic xs in
+        let _2 : unit = Obj.magic _2 in
+        let x : (Parsetree.pattern) = Obj.magic x in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_x_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.pattern list) = 
+# 944 "parsing/parser.mly"
+    ( x :: xs )
+# 30673 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = eo;
+          MenhirLib.EngineTypes.startp = _startpos_eo_;
+          MenhirLib.EngineTypes.endp = _endpos_eo_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = c;
+            MenhirLib.EngineTypes.startp = _startpos_c_;
+            MenhirLib.EngineTypes.endp = _endpos_c_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let eo : (Parsetree.expression option) = Obj.magic eo in
+        let c : ((Parsetree.core_type option * Parsetree.core_type option) option) = Obj.magic c in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_eo_ in
+        let _v : ((Longident.t Asttypes.loc * Parsetree.expression) list) = let _2 = 
+# 124 "menhir/standard.mly"
+    ( None )
+# 30712 "parsing/parser.ml"
+         in
+        let x =
+          let label =
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 30722 "parsing/parser.ml"
+            
+          in
+          let _startpos_label_ = _startpos__1_ in
+          let _endpos = _endpos_eo_ in
+          let _symbolstartpos = _startpos_label_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2484 "parsing/parser.mly"
+      ( let e =
+          match eo with
+          | None ->
+              (* No pattern; this is a pun. Desugar it. *)
+              exp_of_longident ~loc:_sloc label
+          | Some e ->
+              e
+        in
+        label, mkexp_opt_constraint ~loc:_sloc e c )
+# 30740 "parsing/parser.ml"
+          
+        in
+        
+# 940 "parsing/parser.mly"
+    ( [x] )
+# 30746 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = x;
+          MenhirLib.EngineTypes.startp = _startpos_x_;
+          MenhirLib.EngineTypes.endp = _endpos_x_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = eo;
+            MenhirLib.EngineTypes.startp = _startpos_eo_;
+            MenhirLib.EngineTypes.endp = _endpos_eo_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = c;
+              MenhirLib.EngineTypes.startp = _startpos_c_;
+              MenhirLib.EngineTypes.endp = _endpos_c_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let x : unit = Obj.magic x in
+        let eo : (Parsetree.expression option) = Obj.magic eo in
+        let c : ((Parsetree.core_type option * Parsetree.core_type option) option) = Obj.magic c in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_x_ in
+        let _v : ((Longident.t Asttypes.loc * Parsetree.expression) list) = let _2 = 
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 30792 "parsing/parser.ml"
+         in
+        let x =
+          let label =
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 30802 "parsing/parser.ml"
+            
+          in
+          let _startpos_label_ = _startpos__1_ in
+          let _endpos = _endpos_eo_ in
+          let _symbolstartpos = _startpos_label_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2484 "parsing/parser.mly"
+      ( let e =
+          match eo with
+          | None ->
+              (* No pattern; this is a pun. Desugar it. *)
+              exp_of_longident ~loc:_sloc label
+          | Some e ->
+              e
+        in
+        label, mkexp_opt_constraint ~loc:_sloc e c )
+# 30820 "parsing/parser.ml"
+          
+        in
+        
+# 940 "parsing/parser.mly"
+    ( [x] )
+# 30826 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = eo;
+              MenhirLib.EngineTypes.startp = _startpos_eo_;
+              MenhirLib.EngineTypes.endp = _endpos_eo_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = c;
+                MenhirLib.EngineTypes.startp = _startpos_c_;
+                MenhirLib.EngineTypes.endp = _endpos_c_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let xs : ((Longident.t Asttypes.loc * Parsetree.expression) list) = Obj.magic xs in
+        let _2 : unit = Obj.magic _2 in
+        let eo : (Parsetree.expression option) = Obj.magic eo in
+        let c : ((Parsetree.core_type option * Parsetree.core_type option) option) = Obj.magic c in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : ((Longident.t Asttypes.loc * Parsetree.expression) list) = let x =
+          let label =
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 30884 "parsing/parser.ml"
+            
+          in
+          let _startpos_label_ = _startpos__1_ in
+          let _endpos = _endpos_eo_ in
+          let _symbolstartpos = _startpos_label_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2484 "parsing/parser.mly"
+      ( let e =
+          match eo with
+          | None ->
+              (* No pattern; this is a pun. Desugar it. *)
+              exp_of_longident ~loc:_sloc label
+          | Some e ->
+              e
+        in
+        label, mkexp_opt_constraint ~loc:_sloc e c )
+# 30902 "parsing/parser.ml"
+          
+        in
+        
+# 944 "parsing/parser.mly"
+    ( x :: xs )
+# 30908 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.expression) = 
+# 2003 "parsing/parser.mly"
+                                  ( _1 )
+# 30933 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.expression) = 
+# 2004 "parsing/parser.mly"
+                                  ( _1 )
+# 30965 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 = 
+# 2006 "parsing/parser.mly"
+    ( Pexp_sequence(_1, _3) )
+# 31005 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 31014 "parsing/parser.ml"
+          
+        in
+        
+# 2007 "parsing/parser.mly"
+    ( _1 )
+# 31020 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : (Parsetree.expression) = Obj.magic _5 in
+        let _4 : (string Asttypes.loc) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2009 "parsing/parser.mly"
+    ( let seq = mkexp ~loc:_sloc (Pexp_sequence (_1, _5)) in
+      let payload = PStr [mkstrexp seq []] in
+      mkexp ~loc:_sloc (Pexp_extension (_4, payload)) )
+# 31078 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined4;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined4_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = args_res;
+              MenhirLib.EngineTypes.startp = _startpos_args_res_;
+              MenhirLib.EngineTypes.endp = _endpos_args_res_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = ext;
+                    MenhirLib.EngineTypes.startp = _startpos_ext_;
+                    MenhirLib.EngineTypes.endp = _endpos_ext_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined4 : (Parsetree.attributes) = Obj.magic _1_inlined4 in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let args_res : (Parsetree.constructor_arguments * Parsetree.core_type option) = Obj.magic args_res in
+        let _1_inlined2 : (string) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined4_ in
+        let _v : (Parsetree.type_exception * string Asttypes.loc option) = let attrs =
+          let _1 = _1_inlined4 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 31147 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs_ = _endpos__1_inlined4_ in
+        let attrs2 =
+          let _1 = _1_inlined3 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 31156 "parsing/parser.ml"
+          
+        in
+        let id =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 31167 "parsing/parser.ml"
+          
+        in
+        let attrs1 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 31175 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_attrs_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2937 "parsing/parser.mly"
+    ( let args, res = args_res in
+      let loc = make_loc _sloc in
+      let docs = symbol_docs _sloc in
+      Te.mk_exception ~attrs
+        (Te.decl id ~args ?res ~attrs:(attrs1 @ attrs2) ~loc ~docs)
+      , ext )
+# 31189 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = xss;
+          MenhirLib.EngineTypes.startp = _startpos_xss_;
+          MenhirLib.EngineTypes.endp = _endpos_xss_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let xss : (Parsetree.signature_item list list) = Obj.magic xss in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xss_ in
+        let _endpos = _endpos_xss_ in
+        let _v : (Parsetree.signature) = let _1 =
+          let _1 = 
+# 260 "menhir/standard.mly"
+    ( List.flatten xss )
+# 31215 "parsing/parser.ml"
+           in
+          let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in
+          let _endpos = _endpos__1_ in
+          let _startpos = _startpos__1_ in
+          
+# 763 "parsing/parser.mly"
+                              ( extra_sig _startpos _endpos _1 )
+# 31223 "parsing/parser.ml"
+          
+        in
+        
+# 1471 "parsing/parser.mly"
+    ( _1 )
+# 31229 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : (Parsetree.extension) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.signature_item) = let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 31263 "parsing/parser.ml"
+          
+        in
+        let _endpos__2_ = _endpos__1_inlined1_ in
+        let _endpos = _endpos__2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1486 "parsing/parser.mly"
+      ( let docs = symbol_docs _sloc in
+        mksig ~loc:_sloc (Psig_extension (_1, (add_docs_attrs docs _2))) )
+# 31274 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.attribute) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 = 
+# 1490 "parsing/parser.mly"
+        ( Psig_attribute _1 )
+# 31300 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 811 "parsing/parser.mly"
+    ( mksig ~loc:_sloc _1 )
+# 31308 "parsing/parser.ml"
+          
+        in
+        
+# 1492 "parsing/parser.mly"
+    ( _1 )
+# 31314 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.value_description * string Asttypes.loc option) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 = 
+# 1495 "parsing/parser.mly"
+        ( psig_value _1 )
+# 31340 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 31348 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 31354 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.value_description * string Asttypes.loc option) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 = 
+# 1497 "parsing/parser.mly"
+        ( psig_value _1 )
+# 31380 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 31388 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 31394 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = bs;
+          MenhirLib.EngineTypes.startp = _startpos_bs_;
+          MenhirLib.EngineTypes.endp = _endpos_bs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = a;
+            MenhirLib.EngineTypes.startp = _startpos_a_;
+            MenhirLib.EngineTypes.endp = _endpos_a_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let bs : (Parsetree.type_declaration list) = Obj.magic bs in
+        let a : ((Asttypes.rec_flag * string Asttypes.loc option) *
+  Parsetree.type_declaration) = Obj.magic a in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_a_ in
+        let _endpos = _endpos_bs_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 =
+            let _1 =
+              let _1 =
+                let _1 = 
+# 1001 "parsing/parser.mly"
+    ( let (x, b) = a in x, b :: bs )
+# 31431 "parsing/parser.ml"
+                 in
+                
+# 2769 "parsing/parser.mly"
+  ( _1 )
+# 31436 "parsing/parser.ml"
+                
+              in
+              
+# 2752 "parsing/parser.mly"
+    ( _1 )
+# 31442 "parsing/parser.ml"
+              
+            in
+            
+# 1499 "parsing/parser.mly"
+        ( psig_type _1 )
+# 31448 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_bs_, _startpos_a_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 31458 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 31464 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = bs;
+          MenhirLib.EngineTypes.startp = _startpos_bs_;
+          MenhirLib.EngineTypes.endp = _endpos_bs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = a;
+            MenhirLib.EngineTypes.startp = _startpos_a_;
+            MenhirLib.EngineTypes.endp = _endpos_a_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let bs : (Parsetree.type_declaration list) = Obj.magic bs in
+        let a : ((Asttypes.rec_flag * string Asttypes.loc option) *
+  Parsetree.type_declaration) = Obj.magic a in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_a_ in
+        let _endpos = _endpos_bs_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 =
+            let _1 =
+              let _1 =
+                let _1 = 
+# 1001 "parsing/parser.mly"
+    ( let (x, b) = a in x, b :: bs )
+# 31501 "parsing/parser.ml"
+                 in
+                
+# 2769 "parsing/parser.mly"
+  ( _1 )
+# 31506 "parsing/parser.ml"
+                
+              in
+              
+# 2757 "parsing/parser.mly"
+    ( _1 )
+# 31512 "parsing/parser.ml"
+              
+            in
+            
+# 1501 "parsing/parser.mly"
+        ( psig_typesubst _1 )
+# 31518 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_bs_, _startpos_a_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 31528 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 31534 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = priv;
+              MenhirLib.EngineTypes.startp = _startpos_priv_;
+              MenhirLib.EngineTypes.endp = _endpos_priv_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _7;
+                MenhirLib.EngineTypes.startp = _startpos__7_;
+                MenhirLib.EngineTypes.endp = _endpos__7_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = params;
+                    MenhirLib.EngineTypes.startp = _startpos_params_;
+                    MenhirLib.EngineTypes.endp = _endpos_params_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = ext;
+                        MenhirLib.EngineTypes.startp = _startpos_ext_;
+                        MenhirLib.EngineTypes.endp = _endpos_ext_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let xs : (Parsetree.extension_constructor list) = Obj.magic xs in
+        let priv : (Asttypes.private_flag) = Obj.magic priv in
+        let _7 : unit = Obj.magic _7 in
+        let _1_inlined2 : (Longident.t) = Obj.magic _1_inlined2 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 =
+            let _1 =
+              let _1 =
+                let attrs2 =
+                  let _1 = _1_inlined3 in
+                  
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 31621 "parsing/parser.ml"
+                  
+                in
+                let _endpos_attrs2_ = _endpos__1_inlined3_ in
+                let cs = 
+# 993 "parsing/parser.mly"
+    ( List.rev xs )
+# 31628 "parsing/parser.ml"
+                 in
+                let tid =
+                  let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+                  let _endpos = _endpos__1_ in
+                  let _symbolstartpos = _startpos__1_ in
+                  let _sloc = (_symbolstartpos, _endpos) in
+                  
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 31638 "parsing/parser.ml"
+                  
+                in
+                let _4 = 
+# 3485 "parsing/parser.mly"
+                ( Recursive )
+# 31644 "parsing/parser.ml"
+                 in
+                let attrs1 =
+                  let _1 = _1_inlined1 in
+                  
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 31651 "parsing/parser.ml"
+                  
+                in
+                let _endpos = _endpos_attrs2_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 3006 "parsing/parser.mly"
+    ( let docs = symbol_docs _sloc in
+      let attrs = attrs1 @ attrs2 in
+      Te.mk tid cs ~params ~priv ~attrs ~docs,
+      ext )
+# 31663 "parsing/parser.ml"
+                
+              in
+              
+# 2993 "parsing/parser.mly"
+    ( _1 )
+# 31669 "parsing/parser.ml"
+              
+            in
+            
+# 1503 "parsing/parser.mly"
+        ( psig_typext _1 )
+# 31675 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 31685 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 31691 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined4;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined4_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = priv;
+              MenhirLib.EngineTypes.startp = _startpos_priv_;
+              MenhirLib.EngineTypes.endp = _endpos_priv_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _7;
+                MenhirLib.EngineTypes.startp = _startpos__7_;
+                MenhirLib.EngineTypes.endp = _endpos__7_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined3;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = params;
+                    MenhirLib.EngineTypes.startp = _startpos_params_;
+                    MenhirLib.EngineTypes.endp = _endpos_params_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined2;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _1_inlined1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _;
+                          MenhirLib.EngineTypes.semv = ext;
+                          MenhirLib.EngineTypes.startp = _startpos_ext_;
+                          MenhirLib.EngineTypes.endp = _endpos_ext_;
+                          MenhirLib.EngineTypes.next = {
+                            MenhirLib.EngineTypes.state = _menhir_s;
+                            MenhirLib.EngineTypes.semv = _1;
+                            MenhirLib.EngineTypes.startp = _startpos__1_;
+                            MenhirLib.EngineTypes.endp = _endpos__1_;
+                            MenhirLib.EngineTypes.next = _menhir_stack;
+                          };
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined4 : (Parsetree.attributes) = Obj.magic _1_inlined4 in
+        let xs : (Parsetree.extension_constructor list) = Obj.magic xs in
+        let priv : (Asttypes.private_flag) = Obj.magic priv in
+        let _7 : unit = Obj.magic _7 in
+        let _1_inlined3 : (Longident.t) = Obj.magic _1_inlined3 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let _1_inlined2 : unit = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined4_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 =
+            let _1 =
+              let _1 =
+                let attrs2 =
+                  let _1 = _1_inlined4 in
+                  
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 31785 "parsing/parser.ml"
+                  
+                in
+                let _endpos_attrs2_ = _endpos__1_inlined4_ in
+                let cs = 
+# 993 "parsing/parser.mly"
+    ( List.rev xs )
+# 31792 "parsing/parser.ml"
+                 in
+                let tid =
+                  let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+                  let _endpos = _endpos__1_ in
+                  let _symbolstartpos = _startpos__1_ in
+                  let _sloc = (_symbolstartpos, _endpos) in
+                  
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 31802 "parsing/parser.ml"
+                  
+                in
+                let _4 =
+                  let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+                  let _endpos = _endpos__1_ in
+                  let _startpos = _startpos__1_ in
+                  let _loc = (_startpos, _endpos) in
+                  
+# 3486 "parsing/parser.mly"
+                ( not_expecting _loc "nonrec flag" )
+# 31813 "parsing/parser.ml"
+                  
+                in
+                let attrs1 =
+                  let _1 = _1_inlined1 in
+                  
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 31821 "parsing/parser.ml"
+                  
+                in
+                let _endpos = _endpos_attrs2_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 3006 "parsing/parser.mly"
+    ( let docs = symbol_docs _sloc in
+      let attrs = attrs1 @ attrs2 in
+      Te.mk tid cs ~params ~priv ~attrs ~docs,
+      ext )
+# 31833 "parsing/parser.ml"
+                
+              in
+              
+# 2993 "parsing/parser.mly"
+    ( _1 )
+# 31839 "parsing/parser.ml"
+              
+            in
+            
+# 1503 "parsing/parser.mly"
+        ( psig_typext _1 )
+# 31845 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined4_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 31855 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 31861 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.type_exception * string Asttypes.loc option) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 = 
+# 1505 "parsing/parser.mly"
+        ( psig_exception _1 )
+# 31887 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 31895 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 31901 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = body;
+            MenhirLib.EngineTypes.startp = _startpos_body_;
+            MenhirLib.EngineTypes.endp = _endpos_body_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = ext;
+                  MenhirLib.EngineTypes.startp = _startpos_ext_;
+                  MenhirLib.EngineTypes.endp = _endpos_ext_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let body : (Parsetree.module_type) = Obj.magic body in
+        let _1_inlined2 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 31954 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 =
+            let _1 =
+              let attrs2 =
+                let _1 = _1_inlined3 in
+                
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 31970 "parsing/parser.ml"
+                
+              in
+              let _endpos_attrs2_ = _endpos__1_inlined3_ in
+              let uid =
+                let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 31982 "parsing/parser.ml"
+                
+              in
+              let attrs1 =
+                let _1 = _1_inlined1 in
+                
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 31990 "parsing/parser.ml"
+                
+              in
+              let _endpos = _endpos_attrs2_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 1534 "parsing/parser.mly"
+  (
+    let attrs = attrs1 @ attrs2 in
+    let loc = make_loc _sloc in
+    let docs = symbol_docs _sloc in
+    Md.mk uid body ~attrs ~loc ~docs, ext
+  )
+# 32004 "parsing/parser.ml"
+              
+            in
+            
+# 1507 "parsing/parser.mly"
+        ( let (body, ext) = _1 in (Psig_module body, ext) )
+# 32010 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 32020 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 32026 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined4;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined4_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = ext;
+                    MenhirLib.EngineTypes.startp = _startpos_ext_;
+                    MenhirLib.EngineTypes.endp = _endpos_ext_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined4 : (Parsetree.attributes) = Obj.magic _1_inlined4 in
+        let _1_inlined3 : (Longident.t) = Obj.magic _1_inlined3 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined2 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 32086 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined4_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 =
+            let _1 =
+              let attrs2 =
+                let _1 = _1_inlined4 in
+                
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 32102 "parsing/parser.ml"
+                
+              in
+              let _endpos_attrs2_ = _endpos__1_inlined4_ in
+              let body =
+                let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+                let id =
+                  let _endpos = _endpos__1_ in
+                  let _symbolstartpos = _startpos__1_ in
+                  let _sloc = (_symbolstartpos, _endpos) in
+                  
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 32115 "parsing/parser.ml"
+                  
+                in
+                let (_endpos_id_, _startpos_id_) = (_endpos__1_, _startpos__1_) in
+                let _endpos = _endpos_id_ in
+                let _symbolstartpos = _startpos_id_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 1571 "parsing/parser.mly"
+    ( Mty.alias ~loc:(make_loc _sloc) id )
+# 32125 "parsing/parser.ml"
+                
+              in
+              let uid =
+                let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 32136 "parsing/parser.ml"
+                
+              in
+              let attrs1 =
+                let _1 = _1_inlined1 in
+                
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 32144 "parsing/parser.ml"
+                
+              in
+              let _endpos = _endpos_attrs2_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 1562 "parsing/parser.mly"
+  (
+    let attrs = attrs1 @ attrs2 in
+    let loc = make_loc _sloc in
+    let docs = symbol_docs _sloc in
+    Md.mk uid body ~attrs ~loc ~docs, ext
+  )
+# 32158 "parsing/parser.ml"
+              
+            in
+            
+# 1509 "parsing/parser.mly"
+        ( let (body, ext) = _1 in (Psig_module body, ext) )
+# 32164 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined4_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 32174 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 32180 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.module_substitution * string Asttypes.loc option) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 = 
+# 1511 "parsing/parser.mly"
+        ( let (body, ext) = _1 in (Psig_modsubst body, ext) )
+# 32206 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 32214 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 32220 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = bs;
+          MenhirLib.EngineTypes.startp = _startpos_bs_;
+          MenhirLib.EngineTypes.endp = _endpos_bs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = mty;
+              MenhirLib.EngineTypes.startp = _startpos_mty_;
+              MenhirLib.EngineTypes.endp = _endpos_mty_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _6;
+                MenhirLib.EngineTypes.startp = _startpos__6_;
+                MenhirLib.EngineTypes.endp = _endpos__6_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _4;
+                    MenhirLib.EngineTypes.startp = _startpos__4_;
+                    MenhirLib.EngineTypes.endp = _endpos__4_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = ext;
+                        MenhirLib.EngineTypes.startp = _startpos_ext_;
+                        MenhirLib.EngineTypes.endp = _endpos_ext_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let bs : (Parsetree.module_declaration list) = Obj.magic bs in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let mty : (Parsetree.module_type) = Obj.magic mty in
+        let _6 : unit = Obj.magic _6 in
+        let _1_inlined2 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 32293 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _4 : unit = Obj.magic _4 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_bs_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 =
+            let _1 =
+              let _1 =
+                let a =
+                  let attrs2 =
+                    let _1 = _1_inlined3 in
+                    
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 32312 "parsing/parser.ml"
+                    
+                  in
+                  let _endpos_attrs2_ = _endpos__1_inlined3_ in
+                  let uid =
+                    let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+                    let _endpos = _endpos__1_ in
+                    let _symbolstartpos = _startpos__1_ in
+                    let _sloc = (_symbolstartpos, _endpos) in
+                    
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 32324 "parsing/parser.ml"
+                    
+                  in
+                  let attrs1 =
+                    let _1 = _1_inlined1 in
+                    
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 32332 "parsing/parser.ml"
+                    
+                  in
+                  let _endpos = _endpos_attrs2_ in
+                  let _symbolstartpos = _startpos__1_ in
+                  let _sloc = (_symbolstartpos, _endpos) in
+                  
+# 1605 "parsing/parser.mly"
+  (
+    let attrs = attrs1 @ attrs2 in
+    let loc = make_loc _sloc in
+    let docs = symbol_docs _sloc in
+    ext, Md.mk uid mty ~attrs ~loc ~docs
+  )
+# 32346 "parsing/parser.ml"
+                  
+                in
+                
+# 1001 "parsing/parser.mly"
+    ( let (x, b) = a in x, b :: bs )
+# 32352 "parsing/parser.ml"
+                
+              in
+              
+# 1594 "parsing/parser.mly"
+    ( _1 )
+# 32358 "parsing/parser.ml"
+              
+            in
+            
+# 1513 "parsing/parser.mly"
+        ( let (ext, l) = _1 in (Psig_recmodule l, ext) )
+# 32364 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos_bs_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 32374 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 32380 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.module_type_declaration * string Asttypes.loc option) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 = 
+# 1515 "parsing/parser.mly"
+        ( let (body, ext) = _1 in (Psig_modtype body, ext) )
+# 32406 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 32414 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 32420 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.open_description * string Asttypes.loc option) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 = 
+# 1517 "parsing/parser.mly"
+        ( let (body, ext) = _1 in (Psig_open body, ext) )
+# 32446 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 32454 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 32460 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = thing;
+            MenhirLib.EngineTypes.startp = _startpos_thing_;
+            MenhirLib.EngineTypes.endp = _endpos_thing_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = ext;
+                MenhirLib.EngineTypes.startp = _startpos_ext_;
+                MenhirLib.EngineTypes.endp = _endpos_ext_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let thing : (Parsetree.module_type) = Obj.magic thing in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 =
+            let _1 =
+              let attrs2 =
+                let _1 = _1_inlined2 in
+                
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 32518 "parsing/parser.ml"
+                
+              in
+              let _endpos_attrs2_ = _endpos__1_inlined2_ in
+              let attrs1 =
+                let _1 = _1_inlined1 in
+                
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 32527 "parsing/parser.ml"
+                
+              in
+              let _endpos = _endpos_attrs2_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 1363 "parsing/parser.mly"
+  (
+    let attrs = attrs1 @ attrs2 in
+    let loc = make_loc _sloc in
+    let docs = symbol_docs _sloc in
+    Incl.mk thing ~attrs ~loc ~docs, ext
+  )
+# 32541 "parsing/parser.ml"
+              
+            in
+            
+# 1519 "parsing/parser.mly"
+        ( psig_include _1 )
+# 32547 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 32557 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 32563 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = bs;
+          MenhirLib.EngineTypes.startp = _startpos_bs_;
+          MenhirLib.EngineTypes.endp = _endpos_bs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = cty;
+              MenhirLib.EngineTypes.startp = _startpos_cty_;
+              MenhirLib.EngineTypes.endp = _endpos_cty_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _7;
+                MenhirLib.EngineTypes.startp = _startpos__7_;
+                MenhirLib.EngineTypes.endp = _endpos__7_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = params;
+                    MenhirLib.EngineTypes.startp = _startpos_params_;
+                    MenhirLib.EngineTypes.endp = _endpos_params_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = virt;
+                      MenhirLib.EngineTypes.startp = _startpos_virt_;
+                      MenhirLib.EngineTypes.endp = _endpos_virt_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _1_inlined1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _;
+                          MenhirLib.EngineTypes.semv = ext;
+                          MenhirLib.EngineTypes.startp = _startpos_ext_;
+                          MenhirLib.EngineTypes.endp = _endpos_ext_;
+                          MenhirLib.EngineTypes.next = {
+                            MenhirLib.EngineTypes.state = _menhir_s;
+                            MenhirLib.EngineTypes.semv = _1;
+                            MenhirLib.EngineTypes.startp = _startpos__1_;
+                            MenhirLib.EngineTypes.endp = _endpos__1_;
+                            MenhirLib.EngineTypes.next = _menhir_stack;
+                          };
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let bs : (Parsetree.class_description list) = Obj.magic bs in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let cty : (Parsetree.class_type) = Obj.magic cty in
+        let _7 : unit = Obj.magic _7 in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 32642 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let virt : (Asttypes.virtual_flag) = Obj.magic virt in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_bs_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 =
+            let _1 =
+              let _1 =
+                let a =
+                  let attrs2 =
+                    let _1 = _1_inlined3 in
+                    
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 32662 "parsing/parser.ml"
+                    
+                  in
+                  let _endpos_attrs2_ = _endpos__1_inlined3_ in
+                  let id =
+                    let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+                    let _endpos = _endpos__1_ in
+                    let _symbolstartpos = _startpos__1_ in
+                    let _sloc = (_symbolstartpos, _endpos) in
+                    
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 32674 "parsing/parser.ml"
+                    
+                  in
+                  let attrs1 =
+                    let _1 = _1_inlined1 in
+                    
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 32682 "parsing/parser.ml"
+                    
+                  in
+                  let _endpos = _endpos_attrs2_ in
+                  let _symbolstartpos = _startpos__1_ in
+                  let _sloc = (_symbolstartpos, _endpos) in
+                  
+# 1935 "parsing/parser.mly"
+    (
+      let attrs = attrs1 @ attrs2 in
+      let loc = make_loc _sloc in
+      let docs = symbol_docs _sloc in
+      ext,
+      Ci.mk id cty ~virt ~params ~attrs ~loc ~docs
+    )
+# 32697 "parsing/parser.ml"
+                  
+                in
+                
+# 1001 "parsing/parser.mly"
+    ( let (x, b) = a in x, b :: bs )
+# 32703 "parsing/parser.ml"
+                
+              in
+              
+# 1923 "parsing/parser.mly"
+    ( _1 )
+# 32709 "parsing/parser.ml"
+              
+            in
+            
+# 1521 "parsing/parser.mly"
+        ( let (ext, l) = _1 in (Psig_class l, ext) )
+# 32715 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos_bs_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 32725 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 32731 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (string Asttypes.loc option * Parsetree.class_type_declaration list) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.signature_item) = let _1 =
+          let _1 = 
+# 1523 "parsing/parser.mly"
+        ( let (ext, l) = _1 in (Psig_class_type l, ext) )
+# 32757 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 828 "parsing/parser.mly"
+    ( wrap_mksig_ext ~loc:_sloc _1 )
+# 32765 "parsing/parser.ml"
+          
+        in
+        
+# 1525 "parsing/parser.mly"
+    ( _1 )
+# 32771 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.constant) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.constant) = 
+# 3332 "parsing/parser.mly"
+                 ( _1 )
+# 32796 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (
+# 606 "parsing/parser.mly"
+       (string * char option)
+# 32823 "parsing/parser.ml"
+        ) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.constant) = 
+# 3333 "parsing/parser.mly"
+                 ( let (n, m) = _2 in Pconst_integer("-" ^ n, m) )
+# 32832 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (
+# 585 "parsing/parser.mly"
+       (string * char option)
+# 32859 "parsing/parser.ml"
+        ) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.constant) = 
+# 3334 "parsing/parser.mly"
+                 ( let (f, m) = _2 in Pconst_float("-" ^ f, m) )
+# 32868 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (
+# 606 "parsing/parser.mly"
+       (string * char option)
+# 32895 "parsing/parser.ml"
+        ) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.constant) = 
+# 3335 "parsing/parser.mly"
+                 ( let (n, m) = _2 in Pconst_integer (n, m) )
+# 32904 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (
+# 585 "parsing/parser.mly"
+       (string * char option)
+# 32931 "parsing/parser.ml"
+        ) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.constant) = 
+# 3336 "parsing/parser.mly"
+                 ( let (f, m) = _2 in Pconst_float(f, m) )
+# 32940 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _1_inlined1 : ((Longident.t Asttypes.loc * Parsetree.pattern) list * unit option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 2684 "parsing/parser.mly"
+    ( let fields, closed = _1 in
+      let closed = match closed with Some () -> Open | None -> Closed in
+      fields, closed )
+# 32985 "parsing/parser.ml"
+              
+            in
+            
+# 2655 "parsing/parser.mly"
+      ( let (fields, closed) = _2 in
+        Ppat_record(fields, closed) )
+# 32992 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 33002 "parsing/parser.ml"
+          
+        in
+        
+# 2669 "parsing/parser.mly"
+    ( _1 )
+# 33008 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _1_inlined1 : ((Longident.t Asttypes.loc * Parsetree.pattern) list * unit option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 2684 "parsing/parser.mly"
+    ( let fields, closed = _1 in
+      let closed = match closed with Some () -> Open | None -> Closed in
+      fields, closed )
+# 33053 "parsing/parser.ml"
+              
+            in
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            let _loc__1_ = (_startpos__1_, _endpos__1_) in
+            
+# 2658 "parsing/parser.mly"
+      ( unclosed "{" _loc__1_ "}" _loc__3_ )
+# 33061 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 33071 "parsing/parser.ml"
+          
+        in
+        
+# 2669 "parsing/parser.mly"
+    ( _1 )
+# 33077 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = ps;
+            MenhirLib.EngineTypes.startp = _startpos_ps_;
+            MenhirLib.EngineTypes.endp = _endpos_ps_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let ps : (Parsetree.pattern list) = Obj.magic ps in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _2 = 
+# 2678 "parsing/parser.mly"
+    ( ps )
+# 33118 "parsing/parser.ml"
+             in
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            
+# 2660 "parsing/parser.mly"
+      ( fst (mktailpat _loc__3_ _2) )
+# 33124 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 33134 "parsing/parser.ml"
+          
+        in
+        
+# 2669 "parsing/parser.mly"
+    ( _1 )
+# 33140 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = ps;
+            MenhirLib.EngineTypes.startp = _startpos_ps_;
+            MenhirLib.EngineTypes.endp = _endpos_ps_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let ps : (Parsetree.pattern list) = Obj.magic ps in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _2 = 
+# 2678 "parsing/parser.mly"
+    ( ps )
+# 33181 "parsing/parser.ml"
+             in
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            let _loc__1_ = (_startpos__1_, _endpos__1_) in
+            
+# 2662 "parsing/parser.mly"
+      ( unclosed "[" _loc__1_ "]" _loc__3_ )
+# 33188 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 33198 "parsing/parser.ml"
+          
+        in
+        
+# 2669 "parsing/parser.mly"
+    ( _1 )
+# 33204 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = ps;
+            MenhirLib.EngineTypes.startp = _startpos_ps_;
+            MenhirLib.EngineTypes.endp = _endpos_ps_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let ps : (Parsetree.pattern list) = Obj.magic ps in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _2 = 
+# 2678 "parsing/parser.mly"
+    ( ps )
+# 33245 "parsing/parser.ml"
+             in
+            
+# 2664 "parsing/parser.mly"
+      ( Ppat_array _2 )
+# 33250 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 33260 "parsing/parser.ml"
+          
+        in
+        
+# 2669 "parsing/parser.mly"
+    ( _1 )
+# 33266 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 = 
+# 2666 "parsing/parser.mly"
+      ( Ppat_array [] )
+# 33299 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 33308 "parsing/parser.ml"
+          
+        in
+        
+# 2669 "parsing/parser.mly"
+    ( _1 )
+# 33314 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = ps;
+            MenhirLib.EngineTypes.startp = _startpos_ps_;
+            MenhirLib.EngineTypes.endp = _endpos_ps_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let ps : (Parsetree.pattern list) = Obj.magic ps in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _2 = 
+# 2678 "parsing/parser.mly"
+    ( ps )
+# 33355 "parsing/parser.ml"
+             in
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            let _loc__1_ = (_startpos__1_, _endpos__1_) in
+            
+# 2668 "parsing/parser.mly"
+      ( unclosed "[|" _loc__1_ "|]" _loc__3_ )
+# 33362 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 33372 "parsing/parser.ml"
+          
+        in
+        
+# 2669 "parsing/parser.mly"
+    ( _1 )
+# 33378 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__3_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2167 "parsing/parser.mly"
+      ( reloc_exp ~loc:_sloc _2 )
+# 33420 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        let _loc__1_ = (_startpos__1_, _endpos__1_) in
+        
+# 2169 "parsing/parser.mly"
+      ( unclosed "(" _loc__1_ ")" _loc__3_ )
+# 33461 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.core_type option * Parsetree.core_type option) = Obj.magic _3 in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__4_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2171 "parsing/parser.mly"
+      ( mkexp_constraint ~loc:_sloc _2 _3 )
+# 33510 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2173 "parsing/parser.mly"
+      ( array_get ~loc:_sloc _1 _4 )
+# 33566 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _loc__5_ = (_startpos__5_, _endpos__5_) in
+        let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        
+# 2175 "parsing/parser.mly"
+      ( unclosed "(" _loc__3_ ")" _loc__5_ )
+# 33621 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2177 "parsing/parser.mly"
+      ( string_get ~loc:_sloc _1 _4 )
+# 33677 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _loc__5_ = (_startpos__5_, _endpos__5_) in
+        let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        
+# 2179 "parsing/parser.mly"
+      ( unclosed "[" _loc__3_ "]" _loc__5_ )
+# 33732 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 33780 "parsing/parser.ml"
+        ) = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2181 "parsing/parser.mly"
+      ( dotop_get ~loc:_sloc (Lident ("." ^ _2 ^ "[]")) _1 _4 )
+# 33792 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 33840 "parsing/parser.ml"
+        ) = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _loc__5_ = (_startpos__5_, _endpos__5_) in
+        let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        
+# 2183 "parsing/parser.mly"
+      ( unclosed "[" _loc__3_ "]" _loc__5_ )
+# 33851 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 33899 "parsing/parser.ml"
+        ) = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2185 "parsing/parser.mly"
+      ( dotop_get ~loc:_sloc (Lident ("." ^ _2 ^ "()")) _1 _4  )
+# 33911 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 33959 "parsing/parser.ml"
+        ) = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _loc__5_ = (_startpos__5_, _endpos__5_) in
+        let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        
+# 2187 "parsing/parser.mly"
+      ( unclosed "(" _loc__3_ ")" _loc__5_ )
+# 33970 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 34018 "parsing/parser.ml"
+        ) = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2189 "parsing/parser.mly"
+      ( dotop_get ~loc:_sloc (Lident ("." ^ _2 ^ "{}")) _1 _4 )
+# 34030 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 34078 "parsing/parser.ml"
+        ) = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _loc__5_ = (_startpos__5_, _endpos__5_) in
+        let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        
+# 2191 "parsing/parser.mly"
+      ( unclosed "{" _loc__3_ "}" _loc__5_ )
+# 34089 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : unit = Obj.magic _7 in
+        let _6 : (Parsetree.expression) = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 34149 "parsing/parser.ml"
+        ) = Obj.magic _4 in
+        let _3 : (Longident.t) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__7_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2193 "parsing/parser.mly"
+      ( dotop_get ~loc:_sloc (Ldot(_3, "." ^ _4 ^ "[]")) _1 _6  )
+# 34163 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : unit = Obj.magic _7 in
+        let _6 : (Parsetree.expression) = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 34223 "parsing/parser.ml"
+        ) = Obj.magic _4 in
+        let _3 : (Longident.t) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _loc__7_ = (_startpos__7_, _endpos__7_) in
+        let _loc__5_ = (_startpos__5_, _endpos__5_) in
+        
+# 2196 "parsing/parser.mly"
+      ( unclosed "[" _loc__5_ "]" _loc__7_ )
+# 34236 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : unit = Obj.magic _7 in
+        let _6 : (Parsetree.expression) = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 34296 "parsing/parser.ml"
+        ) = Obj.magic _4 in
+        let _3 : (Longident.t) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__7_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2198 "parsing/parser.mly"
+      ( dotop_get ~loc:_sloc (Ldot(_3, "." ^ _4 ^ "()")) _1 _6 )
+# 34310 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : unit = Obj.magic _7 in
+        let _6 : (Parsetree.expression) = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 34370 "parsing/parser.ml"
+        ) = Obj.magic _4 in
+        let _3 : (Longident.t) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _loc__7_ = (_startpos__7_, _endpos__7_) in
+        let _loc__5_ = (_startpos__5_, _endpos__5_) in
+        
+# 2201 "parsing/parser.mly"
+      ( unclosed "(" _loc__5_ ")" _loc__7_ )
+# 34383 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : unit = Obj.magic _7 in
+        let _6 : (Parsetree.expression) = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 34443 "parsing/parser.ml"
+        ) = Obj.magic _4 in
+        let _3 : (Longident.t) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__7_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2203 "parsing/parser.mly"
+      ( dotop_get ~loc:_sloc (Ldot(_3, "." ^ _4 ^ "{}")) _1 _6  )
+# 34457 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : unit = Obj.magic _7 in
+        let _6 : (Parsetree.expression) = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (
+# 601 "parsing/parser.mly"
+       (string)
+# 34517 "parsing/parser.ml"
+        ) = Obj.magic _4 in
+        let _3 : (Longident.t) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _loc__7_ = (_startpos__7_, _endpos__7_) in
+        let _loc__5_ = (_startpos__5_, _endpos__5_) in
+        
+# 2206 "parsing/parser.mly"
+      ( unclosed "{" _loc__5_ "}" _loc__7_ )
+# 34530 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2208 "parsing/parser.mly"
+      ( bigarray_get ~loc:_sloc _1 _4 )
+# 34586 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _loc__5_ = (_startpos__5_, _endpos__5_) in
+        let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        
+# 2210 "parsing/parser.mly"
+      ( unclosed "{" _loc__3_ "}" _loc__5_ )
+# 34641 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = e;
+            MenhirLib.EngineTypes.startp = _startpos_e_;
+            MenhirLib.EngineTypes.endp = _endpos_e_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = ext;
+                MenhirLib.EngineTypes.startp = _startpos_ext_;
+                MenhirLib.EngineTypes.endp = _endpos_ext_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let e : (Parsetree.expression) = Obj.magic e in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let attrs =
+            let _1 = _1_inlined1 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 34697 "parsing/parser.ml"
+            
+          in
+          
+# 2219 "parsing/parser.mly"
+      ( e.pexp_desc, (ext, attrs @ e.pexp_attributes) )
+# 34703 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__5_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2212 "parsing/parser.mly"
+    ( let desc, attrs = _1 in
+      mkexp_attrs ~loc:_sloc desc attrs )
+# 34714 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined2;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 34765 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 34771 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__3_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2221 "parsing/parser.mly"
+      ( Pexp_construct (mkloc (Lident "()") (make_loc _sloc), None), _2 )
+# 34780 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__3_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2212 "parsing/parser.mly"
+    ( let desc, attrs = _1 in
+      mkexp_attrs ~loc:_sloc desc attrs )
+# 34791 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 34849 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 34855 "parsing/parser.ml"
+            
+          in
+          let _loc__4_ = (_startpos__4_, _endpos__4_) in
+          let _loc__1_ = (_startpos__1_, _endpos__1_) in
+          
+# 2223 "parsing/parser.mly"
+      ( unclosed "begin" _loc__1_ "end" _loc__4_ )
+# 34863 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__4_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2212 "parsing/parser.mly"
+    ( let desc, attrs = _1 in
+      mkexp_attrs ~loc:_sloc desc attrs )
+# 34874 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined2;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Longident.t) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _3 =
+            let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 34926 "parsing/parser.ml"
+            
+          in
+          let _2 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 34936 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 34942 "parsing/parser.ml"
+            
+          in
+          
+# 2225 "parsing/parser.mly"
+      ( Pexp_new(_3), _2 )
+# 34948 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__1_inlined3_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2212 "parsing/parser.mly"
+    ( let desc, attrs = _1 in
+      mkexp_attrs ~loc:_sloc desc attrs )
+# 34959 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _2;
+                  MenhirLib.EngineTypes.startp = _startpos__2_;
+                  MenhirLib.EngineTypes.endp = _endpos__2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.module_expr) = Obj.magic _4 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _3 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 35024 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 35030 "parsing/parser.ml"
+            
+          in
+          
+# 2227 "parsing/parser.mly"
+      ( Pexp_pack _4, _3 )
+# 35036 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__5_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2212 "parsing/parser.mly"
+    ( let desc, attrs = _1 in
+      mkexp_attrs ~loc:_sloc desc attrs )
+# 35047 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _2;
+                      MenhirLib.EngineTypes.startp = _startpos__2_;
+                      MenhirLib.EngineTypes.endp = _endpos__2_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _menhir_s;
+                        MenhirLib.EngineTypes.semv = _1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_;
+                        MenhirLib.EngineTypes.next = _menhir_stack;
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : unit = Obj.magic _7 in
+        let _1_inlined3 : (Parsetree.module_type) = Obj.magic _1_inlined3 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.module_expr) = Obj.magic _4 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _6 =
+            let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+            let _1 =
+              let _1 = 
+# 3247 "parsing/parser.mly"
+      ( Ptyp_package (package_type_of_module_type _1) )
+# 35125 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 35133 "parsing/parser.ml"
+              
+            in
+            
+# 3248 "parsing/parser.mly"
+      ( _1 )
+# 35139 "parsing/parser.ml"
+            
+          in
+          let _3 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 35149 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 35155 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__7_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 2229 "parsing/parser.mly"
+      ( Pexp_constraint (ghexp ~loc:_sloc (Pexp_pack _4), _6), _3 )
+# 35164 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__7_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2212 "parsing/parser.mly"
+    ( let desc, attrs = _1 in
+      mkexp_attrs ~loc:_sloc desc attrs )
+# 35175 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _6;
+          MenhirLib.EngineTypes.startp = _startpos__6_;
+          MenhirLib.EngineTypes.endp = _endpos__6_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _5;
+            MenhirLib.EngineTypes.startp = _startpos__5_;
+            MenhirLib.EngineTypes.endp = _endpos__5_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _4;
+              MenhirLib.EngineTypes.startp = _startpos__4_;
+              MenhirLib.EngineTypes.endp = _endpos__4_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _2;
+                    MenhirLib.EngineTypes.startp = _startpos__2_;
+                    MenhirLib.EngineTypes.endp = _endpos__2_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.module_expr) = Obj.magic _4 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__6_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _3 =
+            let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 35247 "parsing/parser.ml"
+              
+            in
+            
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 35253 "parsing/parser.ml"
+            
+          in
+          let _loc__6_ = (_startpos__6_, _endpos__6_) in
+          let _loc__1_ = (_startpos__1_, _endpos__1_) in
+          
+# 2231 "parsing/parser.mly"
+      ( unclosed "(" _loc__1_ ")" _loc__6_ )
+# 35261 "parsing/parser.ml"
+          
+        in
+        let _endpos__1_ = _endpos__6_ in
+        let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2212 "parsing/parser.mly"
+    ( let desc, attrs = _1 in
+      mkexp_attrs ~loc:_sloc desc attrs )
+# 35272 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _1 =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 35303 "parsing/parser.ml"
+              
+            in
+            
+# 2235 "parsing/parser.mly"
+      ( Pexp_ident (_1) )
+# 35309 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 35318 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 35324 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.constant) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 = 
+# 2237 "parsing/parser.mly"
+      ( Pexp_constant _1 )
+# 35350 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 35358 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 35364 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _1 =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 35395 "parsing/parser.ml"
+              
+            in
+            
+# 2239 "parsing/parser.mly"
+      ( Pexp_construct(_1, None) )
+# 35401 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 35410 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 35416 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Asttypes.label) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 = 
+# 2241 "parsing/parser.mly"
+      ( Pexp_variant(_1, None) )
+# 35442 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 35450 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 35456 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : (
+# 644 "parsing/parser.mly"
+       (string)
+# 35484 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _1 =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 35498 "parsing/parser.ml"
+              
+            in
+            
+# 2243 "parsing/parser.mly"
+      ( Pexp_apply(_1, [Nolabel,_2]) )
+# 35504 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 35514 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 35520 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _1 =
+              let _1 = 
+# 2244 "parsing/parser.mly"
+            ("!")
+# 35555 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 35563 "parsing/parser.ml"
+              
+            in
+            
+# 2245 "parsing/parser.mly"
+      ( Pexp_apply(_1, [Nolabel,_2]) )
+# 35569 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 35579 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 35585 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let xs : ((Asttypes.label Asttypes.loc * Parsetree.expression) list) = Obj.magic xs in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _2 = 
+# 2496 "parsing/parser.mly"
+    ( xs )
+# 35626 "parsing/parser.ml"
+             in
+            
+# 2247 "parsing/parser.mly"
+      ( Pexp_override _2 )
+# 35631 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 35641 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 35647 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let xs : ((Asttypes.label Asttypes.loc * Parsetree.expression) list) = Obj.magic xs in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _2 = 
+# 2496 "parsing/parser.mly"
+    ( xs )
+# 35688 "parsing/parser.ml"
+             in
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            let _loc__1_ = (_startpos__1_, _endpos__1_) in
+            
+# 2249 "parsing/parser.mly"
+      ( unclosed "{<" _loc__1_ ">}" _loc__3_ )
+# 35695 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 35705 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 35711 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 = 
+# 2251 "parsing/parser.mly"
+      ( Pexp_override [] )
+# 35744 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 35753 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 35759 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Longident.t) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _3 =
+              let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 35805 "parsing/parser.ml"
+              
+            in
+            
+# 2253 "parsing/parser.mly"
+      ( Pexp_field(_1, _3) )
+# 35811 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined1_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 35821 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 35827 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let od =
+              let _1 =
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 35887 "parsing/parser.ml"
+                
+              in
+              let _loc__1_ = (_startpos__1_, _endpos__1_) in
+              
+# 1422 "parsing/parser.mly"
+  ( let loc = make_loc _loc__1_ in
+    let me = Mod.ident ~loc _1 in
+    Opn.mk ~loc me )
+# 35896 "parsing/parser.ml"
+              
+            in
+            
+# 2255 "parsing/parser.mly"
+      ( Pexp_open(od, _4) )
+# 35902 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 35912 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 35918 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let xs : ((Asttypes.label Asttypes.loc * Parsetree.expression) list) = Obj.magic xs in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _4 = 
+# 2496 "parsing/parser.mly"
+    ( xs )
+# 35973 "parsing/parser.ml"
+             in
+            let od =
+              let _1 =
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 35983 "parsing/parser.ml"
+                
+              in
+              let _loc__1_ = (_startpos__1_, _endpos__1_) in
+              
+# 1422 "parsing/parser.mly"
+  ( let loc = make_loc _loc__1_ in
+    let me = Mod.ident ~loc _1 in
+    Opn.mk ~loc me )
+# 35992 "parsing/parser.ml"
+              
+            in
+            let _startpos_od_ = _startpos__1_ in
+            let _endpos = _endpos__5_ in
+            let _symbolstartpos = _startpos_od_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 2257 "parsing/parser.mly"
+      ( (* TODO: review the location of Pexp_override *)
+        Pexp_open(od, mkexp ~loc:_sloc (Pexp_override _4)) )
+# 36003 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 36013 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 36019 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let xs : ((Asttypes.label Asttypes.loc * Parsetree.expression) list) = Obj.magic xs in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _4 = 
+# 2496 "parsing/parser.mly"
+    ( xs )
+# 36074 "parsing/parser.ml"
+             in
+            let _loc__5_ = (_startpos__5_, _endpos__5_) in
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            
+# 2260 "parsing/parser.mly"
+      ( unclosed "{<" _loc__3_ ">}" _loc__5_ )
+# 36081 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 36091 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 36097 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 36130 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _3 =
+              let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+              let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 36144 "parsing/parser.ml"
+               in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 36152 "parsing/parser.ml"
+              
+            in
+            
+# 2262 "parsing/parser.mly"
+      ( Pexp_send(_1, _3) )
+# 36158 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined1_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 36168 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 36174 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.expression) = Obj.magic _3 in
+        let _1_inlined1 : (
+# 655 "parsing/parser.mly"
+       (string)
+# 36208 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined1 in
+        let _1 : (Parsetree.expression) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _2 =
+              let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 797 "parsing/parser.mly"
+   ( mkoperator ~loc:_sloc _1 )
+# 36224 "parsing/parser.ml"
+              
+            in
+            
+# 2264 "parsing/parser.mly"
+      ( mkinfix _1 _2 _3 )
+# 36230 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 36240 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 36246 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.extension) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 = 
+# 2266 "parsing/parser.mly"
+      ( Pexp_extension _1 )
+# 36272 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 36280 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 36286 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__2_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__2_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _2_inlined1 : unit = Obj.magic _2_inlined1 in
+        let _1_inlined1 : unit = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_inlined1_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _3 =
+              let (_endpos__2_, _startpos__1_, _2, _1) = (_endpos__2_inlined1_, _startpos__1_inlined1_, _2_inlined1, _1_inlined1) in
+              let _1 = 
+# 2267 "parsing/parser.mly"
+                                                    (Lident "()")
+# 36336 "parsing/parser.ml"
+               in
+              let _endpos__1_ = _endpos__2_ in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 36345 "parsing/parser.ml"
+              
+            in
+            let _endpos__3_ = _endpos__2_inlined1_ in
+            let od =
+              let _1 =
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 36357 "parsing/parser.ml"
+                
+              in
+              let _loc__1_ = (_startpos__1_, _endpos__1_) in
+              
+# 1422 "parsing/parser.mly"
+  ( let loc = make_loc _loc__1_ in
+    let me = Mod.ident ~loc _1 in
+    Opn.mk ~loc me )
+# 36366 "parsing/parser.ml"
+              
+            in
+            let _startpos_od_ = _startpos__1_ in
+            let _endpos = _endpos__3_ in
+            let _symbolstartpos = _startpos_od_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 2268 "parsing/parser.mly"
+      ( (* TODO: review the location of Pexp_construct *)
+        Pexp_open(od, mkexp ~loc:_sloc (Pexp_construct(_3, None))) )
+# 36377 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__2_inlined1_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 36387 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 36393 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _loc__5_ = (_startpos__5_, _endpos__5_) in
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            
+# 2271 "parsing/parser.mly"
+      ( unclosed "(" _loc__3_ ")" _loc__5_ )
+# 36450 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 36460 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 36466 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.expression option *
+  (Longident.t Asttypes.loc * Parsetree.expression) list) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 = 
+# 2273 "parsing/parser.mly"
+      ( let (exten, fields) = _2 in
+        Pexp_record(fields, exten) )
+# 36508 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 36517 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 36523 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.expression option *
+  (Longident.t Asttypes.loc * Parsetree.expression) list) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            let _loc__1_ = (_startpos__1_, _endpos__1_) in
+            
+# 2276 "parsing/parser.mly"
+      ( unclosed "{" _loc__1_ "}" _loc__3_ )
+# 36567 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 36577 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 36583 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression option *
+  (Longident.t Asttypes.loc * Parsetree.expression) list) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let od =
+              let _1 =
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 36644 "parsing/parser.ml"
+                
+              in
+              let _loc__1_ = (_startpos__1_, _endpos__1_) in
+              
+# 1422 "parsing/parser.mly"
+  ( let loc = make_loc _loc__1_ in
+    let me = Mod.ident ~loc _1 in
+    Opn.mk ~loc me )
+# 36653 "parsing/parser.ml"
+              
+            in
+            let _startpos_od_ = _startpos__1_ in
+            let _endpos = _endpos__5_ in
+            let _symbolstartpos = _startpos_od_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 2278 "parsing/parser.mly"
+      ( let (exten, fields) = _4 in
+        (* TODO: review the location of Pexp_construct *)
+        Pexp_open(od, mkexp ~loc:_sloc (Pexp_record(fields, exten))) )
+# 36665 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 36675 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 36681 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.expression option *
+  (Longident.t Asttypes.loc * Parsetree.expression) list) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _loc__5_ = (_startpos__5_, _endpos__5_) in
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            
+# 2282 "parsing/parser.mly"
+      ( unclosed "{" _loc__3_ "}" _loc__5_ )
+# 36739 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 36749 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 36755 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = es;
+            MenhirLib.EngineTypes.startp = _startpos_es_;
+            MenhirLib.EngineTypes.endp = _endpos_es_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let es : (Parsetree.expression list) = Obj.magic es in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _2 = 
+# 2513 "parsing/parser.mly"
+    ( es )
+# 36796 "parsing/parser.ml"
+             in
+            
+# 2284 "parsing/parser.mly"
+      ( Pexp_array(_2) )
+# 36801 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 36811 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 36817 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = es;
+            MenhirLib.EngineTypes.startp = _startpos_es_;
+            MenhirLib.EngineTypes.endp = _endpos_es_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let es : (Parsetree.expression list) = Obj.magic es in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _2 = 
+# 2513 "parsing/parser.mly"
+    ( es )
+# 36858 "parsing/parser.ml"
+             in
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            let _loc__1_ = (_startpos__1_, _endpos__1_) in
+            
+# 2286 "parsing/parser.mly"
+      ( unclosed "[|" _loc__1_ "|]" _loc__3_ )
+# 36865 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 36875 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 36881 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 = 
+# 2288 "parsing/parser.mly"
+      ( Pexp_array [] )
+# 36914 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 36923 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 36929 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = es;
+            MenhirLib.EngineTypes.startp = _startpos_es_;
+            MenhirLib.EngineTypes.endp = _endpos_es_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let es : (Parsetree.expression list) = Obj.magic es in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _4 = 
+# 2513 "parsing/parser.mly"
+    ( es )
+# 36984 "parsing/parser.ml"
+             in
+            let od =
+              let _1 =
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 36994 "parsing/parser.ml"
+                
+              in
+              let _loc__1_ = (_startpos__1_, _endpos__1_) in
+              
+# 1422 "parsing/parser.mly"
+  ( let loc = make_loc _loc__1_ in
+    let me = Mod.ident ~loc _1 in
+    Opn.mk ~loc me )
+# 37003 "parsing/parser.ml"
+              
+            in
+            let _startpos_od_ = _startpos__1_ in
+            let _endpos = _endpos__5_ in
+            let _symbolstartpos = _startpos_od_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 2290 "parsing/parser.mly"
+      ( (* TODO: review the location of Pexp_array *)
+        Pexp_open(od, mkexp ~loc:_sloc (Pexp_array(_4))) )
+# 37014 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 37024 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 37030 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let od =
+              let _1 =
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 37083 "parsing/parser.ml"
+                
+              in
+              let _loc__1_ = (_startpos__1_, _endpos__1_) in
+              
+# 1422 "parsing/parser.mly"
+  ( let loc = make_loc _loc__1_ in
+    let me = Mod.ident ~loc _1 in
+    Opn.mk ~loc me )
+# 37092 "parsing/parser.ml"
+              
+            in
+            let _startpos_od_ = _startpos__1_ in
+            let _endpos = _endpos__4_ in
+            let _symbolstartpos = _startpos_od_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 2293 "parsing/parser.mly"
+      ( (* TODO: review the location of Pexp_array *)
+        Pexp_open(od, mkexp ~loc:_sloc (Pexp_array [])) )
+# 37103 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__4_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 37113 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 37119 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = es;
+            MenhirLib.EngineTypes.startp = _startpos_es_;
+            MenhirLib.EngineTypes.endp = _endpos_es_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let es : (Parsetree.expression list) = Obj.magic es in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _4 = 
+# 2513 "parsing/parser.mly"
+    ( es )
+# 37174 "parsing/parser.ml"
+             in
+            let _loc__5_ = (_startpos__5_, _endpos__5_) in
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            
+# 2297 "parsing/parser.mly"
+      ( unclosed "[|" _loc__3_ "|]" _loc__5_ )
+# 37181 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 37191 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 37197 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = es;
+            MenhirLib.EngineTypes.startp = _startpos_es_;
+            MenhirLib.EngineTypes.endp = _endpos_es_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let es : (Parsetree.expression list) = Obj.magic es in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _2 = 
+# 2513 "parsing/parser.mly"
+    ( es )
+# 37238 "parsing/parser.ml"
+             in
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            
+# 2299 "parsing/parser.mly"
+      ( fst (mktailexp _loc__3_ _2) )
+# 37244 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 37254 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 37260 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = es;
+            MenhirLib.EngineTypes.startp = _startpos_es_;
+            MenhirLib.EngineTypes.endp = _endpos_es_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let es : (Parsetree.expression list) = Obj.magic es in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _2 = 
+# 2513 "parsing/parser.mly"
+    ( es )
+# 37301 "parsing/parser.ml"
+             in
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            let _loc__1_ = (_startpos__1_, _endpos__1_) in
+            
+# 2301 "parsing/parser.mly"
+      ( unclosed "[" _loc__1_ "]" _loc__3_ )
+# 37308 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 37318 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 37324 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = es;
+            MenhirLib.EngineTypes.startp = _startpos_es_;
+            MenhirLib.EngineTypes.endp = _endpos_es_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let es : (Parsetree.expression list) = Obj.magic es in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _4 = 
+# 2513 "parsing/parser.mly"
+    ( es )
+# 37379 "parsing/parser.ml"
+             in
+            let od =
+              let _1 =
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 37389 "parsing/parser.ml"
+                
+              in
+              let _loc__1_ = (_startpos__1_, _endpos__1_) in
+              
+# 1422 "parsing/parser.mly"
+  ( let loc = make_loc _loc__1_ in
+    let me = Mod.ident ~loc _1 in
+    Opn.mk ~loc me )
+# 37398 "parsing/parser.ml"
+              
+            in
+            let _startpos_od_ = _startpos__1_ in
+            let _endpos = _endpos__5_ in
+            let _symbolstartpos = _startpos_od_ in
+            let _loc__5_ = (_startpos__5_, _endpos__5_) in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 2303 "parsing/parser.mly"
+      ( let list_exp =
+          (* TODO: review the location of list_exp *)
+          let tail_exp, _tail_loc = mktailexp _loc__5_ _4 in
+          mkexp ~loc:_sloc tail_exp in
+        Pexp_open(od, list_exp) )
+# 37413 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 37423 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 37429 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__2_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__2_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _2_inlined1 : unit = Obj.magic _2_inlined1 in
+        let _1_inlined1 : unit = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_inlined1_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _3 =
+              let (_endpos__2_, _startpos__1_, _2, _1) = (_endpos__2_inlined1_, _startpos__1_inlined1_, _2_inlined1, _1_inlined1) in
+              let _1 = 
+# 2308 "parsing/parser.mly"
+                                                        (Lident "[]")
+# 37479 "parsing/parser.ml"
+               in
+              let _endpos__1_ = _endpos__2_ in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 37488 "parsing/parser.ml"
+              
+            in
+            let _endpos__3_ = _endpos__2_inlined1_ in
+            let od =
+              let _1 =
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 37500 "parsing/parser.ml"
+                
+              in
+              let _loc__1_ = (_startpos__1_, _endpos__1_) in
+              
+# 1422 "parsing/parser.mly"
+  ( let loc = make_loc _loc__1_ in
+    let me = Mod.ident ~loc _1 in
+    Opn.mk ~loc me )
+# 37509 "parsing/parser.ml"
+              
+            in
+            let _startpos_od_ = _startpos__1_ in
+            let _endpos = _endpos__3_ in
+            let _symbolstartpos = _startpos_od_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 2309 "parsing/parser.mly"
+      ( (* TODO: review the location of Pexp_construct *)
+        Pexp_open(od, mkexp ~loc:_sloc (Pexp_construct(_3, None))) )
+# 37520 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__2_inlined1_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 37530 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 37536 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = es;
+            MenhirLib.EngineTypes.startp = _startpos_es_;
+            MenhirLib.EngineTypes.endp = _endpos_es_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let es : (Parsetree.expression list) = Obj.magic es in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _4 = 
+# 2513 "parsing/parser.mly"
+    ( es )
+# 37591 "parsing/parser.ml"
+             in
+            let _loc__5_ = (_startpos__5_, _endpos__5_) in
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            
+# 2313 "parsing/parser.mly"
+      ( unclosed "[" _loc__3_ "]" _loc__5_ )
+# 37598 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 37608 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 37614 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _9;
+          MenhirLib.EngineTypes.startp = _startpos__9_;
+          MenhirLib.EngineTypes.endp = _endpos__9_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _7;
+              MenhirLib.EngineTypes.startp = _startpos__7_;
+              MenhirLib.EngineTypes.endp = _endpos__7_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _6;
+                MenhirLib.EngineTypes.startp = _startpos__6_;
+                MenhirLib.EngineTypes.endp = _endpos__6_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _4;
+                      MenhirLib.EngineTypes.startp = _startpos__4_;
+                      MenhirLib.EngineTypes.endp = _endpos__4_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _3;
+                        MenhirLib.EngineTypes.startp = _startpos__3_;
+                        MenhirLib.EngineTypes.endp = _endpos__3_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _;
+                          MenhirLib.EngineTypes.semv = _2;
+                          MenhirLib.EngineTypes.startp = _startpos__2_;
+                          MenhirLib.EngineTypes.endp = _endpos__2_;
+                          MenhirLib.EngineTypes.next = {
+                            MenhirLib.EngineTypes.state = _menhir_s;
+                            MenhirLib.EngineTypes.semv = _1;
+                            MenhirLib.EngineTypes.startp = _startpos__1_;
+                            MenhirLib.EngineTypes.endp = _endpos__1_;
+                            MenhirLib.EngineTypes.next = _menhir_stack;
+                          };
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _9 : unit = Obj.magic _9 in
+        let _1_inlined3 : (Parsetree.module_type) = Obj.magic _1_inlined3 in
+        let _7 : unit = Obj.magic _7 in
+        let _6 : (Parsetree.module_expr) = Obj.magic _6 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__9_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _8 =
+              let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+              let _1 =
+                let _1 = 
+# 3247 "parsing/parser.mly"
+      ( Ptyp_package (package_type_of_module_type _1) )
+# 37707 "parsing/parser.ml"
+                 in
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 37715 "parsing/parser.ml"
+                
+              in
+              
+# 3248 "parsing/parser.mly"
+      ( _1 )
+# 37721 "parsing/parser.ml"
+              
+            in
+            let _5 =
+              let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+              let _2 =
+                let _1 = _1_inlined1 in
+                
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 37731 "parsing/parser.ml"
+                
+              in
+              
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 37737 "parsing/parser.ml"
+              
+            in
+            let od =
+              let _1 =
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 37748 "parsing/parser.ml"
+                
+              in
+              let _loc__1_ = (_startpos__1_, _endpos__1_) in
+              
+# 1422 "parsing/parser.mly"
+  ( let loc = make_loc _loc__1_ in
+    let me = Mod.ident ~loc _1 in
+    Opn.mk ~loc me )
+# 37757 "parsing/parser.ml"
+              
+            in
+            let _startpos_od_ = _startpos__1_ in
+            let _endpos = _endpos__9_ in
+            let _symbolstartpos = _startpos_od_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 2316 "parsing/parser.mly"
+      ( (* TODO: review the location of Pexp_constraint *)
+        let modexp =
+          mkexp_attrs ~loc:_sloc
+            (Pexp_constraint (ghexp ~loc:_sloc (Pexp_pack _6), _8)) _5 in
+        Pexp_open(od, modexp) )
+# 37771 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__9_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 37781 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 37787 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _8;
+          MenhirLib.EngineTypes.startp = _startpos__8_;
+          MenhirLib.EngineTypes.endp = _endpos__8_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _7;
+            MenhirLib.EngineTypes.startp = _startpos__7_;
+            MenhirLib.EngineTypes.endp = _endpos__7_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _6;
+              MenhirLib.EngineTypes.startp = _startpos__6_;
+              MenhirLib.EngineTypes.endp = _endpos__6_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _4;
+                    MenhirLib.EngineTypes.startp = _startpos__4_;
+                    MenhirLib.EngineTypes.endp = _endpos__4_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _3;
+                      MenhirLib.EngineTypes.startp = _startpos__3_;
+                      MenhirLib.EngineTypes.endp = _endpos__3_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _2;
+                        MenhirLib.EngineTypes.startp = _startpos__2_;
+                        MenhirLib.EngineTypes.endp = _endpos__2_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _8 : unit = Obj.magic _8 in
+        let _7 : unit = Obj.magic _7 in
+        let _6 : (Parsetree.module_expr) = Obj.magic _6 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__8_ in
+        let _v : (Parsetree.expression) = let _1 =
+          let _1 =
+            let _5 =
+              let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+              let _2 =
+                let _1 = _1_inlined1 in
+                
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 37874 "parsing/parser.ml"
+                
+              in
+              
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 37880 "parsing/parser.ml"
+              
+            in
+            let _loc__8_ = (_startpos__8_, _endpos__8_) in
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            
+# 2323 "parsing/parser.mly"
+      ( unclosed "(" _loc__3_ ")" _loc__8_ )
+# 37888 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__8_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 803 "parsing/parser.mly"
+    ( mkexp ~loc:_sloc _1 )
+# 37898 "parsing/parser.ml"
+          
+        in
+        
+# 2215 "parsing/parser.mly"
+      ( _1 )
+# 37904 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (string) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 37935 "parsing/parser.ml"
+              
+            in
+            
+# 2593 "parsing/parser.mly"
+      ( Ppat_var (_1) )
+# 37941 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 37950 "parsing/parser.ml"
+          
+        in
+        
+# 2594 "parsing/parser.mly"
+      ( _1 )
+# 37956 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = 
+# 2595 "parsing/parser.mly"
+                             ( _1 )
+# 37981 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.pattern) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _endpos = _endpos__3_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2600 "parsing/parser.mly"
+      ( reloc_pat ~loc:_sloc _2 )
+# 38023 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = 
+# 2602 "parsing/parser.mly"
+      ( _1 )
+# 38048 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _2;
+                  MenhirLib.EngineTypes.startp = _startpos__2_;
+                  MenhirLib.EngineTypes.endp = _endpos__2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined3 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 38100 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.pattern) = let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 38117 "parsing/parser.ml"
+          
+        in
+        let _3 =
+          let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+          let _2 =
+            let _1 = _1_inlined1 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 38127 "parsing/parser.ml"
+            
+          in
+          
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 38133 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2604 "parsing/parser.mly"
+      ( mkpat_attrs ~loc:_sloc (Ppat_unpack _4) _3 )
+# 38142 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined4;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined4_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined3;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _2;
+                      MenhirLib.EngineTypes.startp = _startpos__2_;
+                      MenhirLib.EngineTypes.endp = _endpos__2_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _menhir_s;
+                        MenhirLib.EngineTypes.semv = _1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_;
+                        MenhirLib.EngineTypes.next = _menhir_stack;
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : unit = Obj.magic _7 in
+        let _1_inlined4 : (Parsetree.module_type) = Obj.magic _1_inlined4 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined3 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 38208 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined3 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.pattern) = let _6 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined4_, _startpos__1_inlined4_, _1_inlined4) in
+          let _1 =
+            let _1 = 
+# 3247 "parsing/parser.mly"
+      ( Ptyp_package (package_type_of_module_type _1) )
+# 38223 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 38231 "parsing/parser.ml"
+            
+          in
+          
+# 3248 "parsing/parser.mly"
+      ( _1 )
+# 38237 "parsing/parser.ml"
+          
+        in
+        let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 38248 "parsing/parser.ml"
+          
+        in
+        let _3 =
+          let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+          let _2 =
+            let _1 = _1_inlined1 in
+            
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 38258 "parsing/parser.ml"
+            
+          in
+          
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 38264 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__7_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2606 "parsing/parser.mly"
+      ( mkpat_attrs ~loc:_sloc
+          (Ppat_constraint(mkpat ~loc:_sloc (Ppat_unpack _4), _6))
+          _3 )
+# 38275 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 = 
+# 2614 "parsing/parser.mly"
+      ( Ppat_any )
+# 38301 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 38309 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 38315 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.constant) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 = 
+# 2616 "parsing/parser.mly"
+      ( Ppat_constant _1 )
+# 38341 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 38349 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 38355 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.constant) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.constant) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 = 
+# 2618 "parsing/parser.mly"
+      ( Ppat_interval (_1, _3) )
+# 38395 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 38404 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 38410 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 38441 "parsing/parser.ml"
+              
+            in
+            
+# 2620 "parsing/parser.mly"
+      ( Ppat_construct(_1, None) )
+# 38447 "parsing/parser.ml"
+            
+          in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 38456 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 38462 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Asttypes.label) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 = 
+# 2622 "parsing/parser.mly"
+      ( Ppat_variant(_1, None) )
+# 38488 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 38496 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 38502 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Longident.t) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _2 =
+              let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 38541 "parsing/parser.ml"
+              
+            in
+            
+# 2624 "parsing/parser.mly"
+      ( Ppat_type (_2) )
+# 38547 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined1_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 38557 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 38563 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (Parsetree.pattern) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 38608 "parsing/parser.ml"
+              
+            in
+            
+# 2626 "parsing/parser.mly"
+      ( Ppat_open(_1, _3) )
+# 38614 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 38624 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 38630 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__2_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__2_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _2_inlined1 : unit = Obj.magic _2_inlined1 in
+        let _1_inlined1 : unit = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_inlined1_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _3 =
+              let (_endpos__2_, _startpos__1_, _2, _1) = (_endpos__2_inlined1_, _startpos__1_inlined1_, _2_inlined1, _1_inlined1) in
+              let _1 = 
+# 2627 "parsing/parser.mly"
+                                                     (Lident "[]")
+# 38680 "parsing/parser.ml"
+               in
+              let _endpos__1_ = _endpos__2_ in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 38689 "parsing/parser.ml"
+              
+            in
+            let _endpos__3_ = _endpos__2_inlined1_ in
+            let _1 =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 38700 "parsing/parser.ml"
+              
+            in
+            let _endpos = _endpos__3_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 2628 "parsing/parser.mly"
+    ( Ppat_open(_1, mkpat ~loc:_sloc (Ppat_construct(_3, None))) )
+# 38709 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__2_inlined1_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 38719 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 38725 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__2_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__2_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _2_inlined1 : unit = Obj.magic _2_inlined1 in
+        let _1_inlined1 : unit = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_inlined1_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _3 =
+              let (_endpos__2_, _startpos__1_, _2, _1) = (_endpos__2_inlined1_, _startpos__1_inlined1_, _2_inlined1, _1_inlined1) in
+              let _1 = 
+# 2629 "parsing/parser.mly"
+                                                 (Lident "()")
+# 38775 "parsing/parser.ml"
+               in
+              let _endpos__1_ = _endpos__2_ in
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 38784 "parsing/parser.ml"
+              
+            in
+            let _endpos__3_ = _endpos__2_inlined1_ in
+            let _1 =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 38795 "parsing/parser.ml"
+              
+            in
+            let _endpos = _endpos__3_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 2630 "parsing/parser.mly"
+    ( Ppat_open(_1, mkpat ~loc:_sloc (Ppat_construct(_3, None))) )
+# 38804 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__2_inlined1_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 38814 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 38820 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.pattern) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _1 =
+              let _endpos = _endpos__1_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 38879 "parsing/parser.ml"
+              
+            in
+            
+# 2632 "parsing/parser.mly"
+      ( Ppat_open (_1, _4) )
+# 38885 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 38895 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 38901 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.pattern) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _loc__5_ = (_startpos__5_, _endpos__5_) in
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            
+# 2634 "parsing/parser.mly"
+      ( unclosed "(" _loc__3_ ")" _loc__5_  )
+# 38958 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 38968 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 38974 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _loc__4_ = (_startpos__4_, _endpos__4_) in
+            
+# 2636 "parsing/parser.mly"
+      ( expecting _loc__4_ "pattern" )
+# 39023 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__4_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 39033 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 39039 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.pattern) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _loc__3_ = (_startpos__3_, _endpos__3_) in
+            let _loc__1_ = (_startpos__1_, _endpos__1_) in
+            
+# 2638 "parsing/parser.mly"
+      ( unclosed "(" _loc__1_ ")" _loc__3_ )
+# 39082 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 39092 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 39098 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.core_type) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.pattern) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 = 
+# 2640 "parsing/parser.mly"
+      ( Ppat_constraint(_2, _4) )
+# 39152 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 39161 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 39167 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (Parsetree.core_type) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.pattern) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _loc__5_ = (_startpos__5_, _endpos__5_) in
+            let _loc__1_ = (_startpos__1_, _endpos__1_) in
+            
+# 2642 "parsing/parser.mly"
+      ( unclosed "(" _loc__1_ ")" _loc__5_ )
+# 39224 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__5_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 39234 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 39240 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : unit = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.pattern) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _loc__4_ = (_startpos__4_, _endpos__4_) in
+            
+# 2644 "parsing/parser.mly"
+      ( expecting _loc__4_ "type" )
+# 39289 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__4_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 39299 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 39305 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _4;
+                MenhirLib.EngineTypes.startp = _startpos__4_;
+                MenhirLib.EngineTypes.endp = _endpos__4_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _2;
+                      MenhirLib.EngineTypes.startp = _startpos__2_;
+                      MenhirLib.EngineTypes.endp = _endpos__2_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _menhir_s;
+                        MenhirLib.EngineTypes.semv = _1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_;
+                        MenhirLib.EngineTypes.next = _menhir_stack;
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : unit = Obj.magic _7 in
+        let _1_inlined3 : (Parsetree.module_type) = Obj.magic _1_inlined3 in
+        let _5 : unit = Obj.magic _5 in
+        let _4 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 39371 "parsing/parser.ml"
+        ) = Obj.magic _4 in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (string Asttypes.loc option) = Obj.magic _1_inlined1 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 =
+            let _6 =
+              let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+              let _1 =
+                let _1 = 
+# 3247 "parsing/parser.mly"
+      ( Ptyp_package (package_type_of_module_type _1) )
+# 39388 "parsing/parser.ml"
+                 in
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 39396 "parsing/parser.ml"
+                
+              in
+              
+# 3248 "parsing/parser.mly"
+      ( _1 )
+# 39402 "parsing/parser.ml"
+              
+            in
+            let _3 =
+              let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in
+              let _2 =
+                let _1 = _1_inlined1 in
+                
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 39412 "parsing/parser.ml"
+                
+              in
+              
+# 3653 "parsing/parser.mly"
+                    ( _1, _2 )
+# 39418 "parsing/parser.ml"
+              
+            in
+            let _loc__7_ = (_startpos__7_, _endpos__7_) in
+            let _loc__1_ = (_startpos__1_, _endpos__1_) in
+            
+# 2647 "parsing/parser.mly"
+      ( unclosed "(" _loc__1_ ")" _loc__7_ )
+# 39426 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__7_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 39436 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 39442 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.extension) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.pattern) = let _1 =
+          let _1 = 
+# 2649 "parsing/parser.mly"
+      ( Ppat_extension _1 )
+# 39468 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 805 "parsing/parser.mly"
+    ( mkpat ~loc:_sloc _1 )
+# 39476 "parsing/parser.ml"
+          
+        in
+        
+# 2610 "parsing/parser.mly"
+      ( _1 )
+# 39482 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 39503 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3563 "parsing/parser.mly"
+           ( _1 )
+# 39511 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 39532 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3564 "parsing/parser.mly"
+           ( _1 )
+# 39540 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3565 "parsing/parser.mly"
+        ( "and" )
+# 39565 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3566 "parsing/parser.mly"
+       ( "as" )
+# 39590 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3567 "parsing/parser.mly"
+           ( "assert" )
+# 39615 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3568 "parsing/parser.mly"
+          ( "begin" )
+# 39640 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3569 "parsing/parser.mly"
+          ( "class" )
+# 39665 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3570 "parsing/parser.mly"
+               ( "constraint" )
+# 39690 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3571 "parsing/parser.mly"
+       ( "do" )
+# 39715 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3572 "parsing/parser.mly"
+         ( "done" )
+# 39740 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3573 "parsing/parser.mly"
+           ( "downto" )
+# 39765 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3574 "parsing/parser.mly"
+         ( "else" )
+# 39790 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3575 "parsing/parser.mly"
+        ( "end" )
+# 39815 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3576 "parsing/parser.mly"
+              ( "exception" )
+# 39840 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3577 "parsing/parser.mly"
+             ( "external" )
+# 39865 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3578 "parsing/parser.mly"
+          ( "false" )
+# 39890 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3579 "parsing/parser.mly"
+        ( "for" )
+# 39915 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3580 "parsing/parser.mly"
+        ( "fun" )
+# 39940 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3581 "parsing/parser.mly"
+             ( "function" )
+# 39965 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3582 "parsing/parser.mly"
+            ( "functor" )
+# 39990 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3583 "parsing/parser.mly"
+       ( "if" )
+# 40015 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3584 "parsing/parser.mly"
+       ( "in" )
+# 40040 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3585 "parsing/parser.mly"
+            ( "include" )
+# 40065 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3586 "parsing/parser.mly"
+            ( "inherit" )
+# 40090 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3587 "parsing/parser.mly"
+                ( "initializer" )
+# 40115 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3588 "parsing/parser.mly"
+         ( "lazy" )
+# 40140 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3589 "parsing/parser.mly"
+        ( "let" )
+# 40165 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3590 "parsing/parser.mly"
+          ( "match" )
+# 40190 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3591 "parsing/parser.mly"
+           ( "method" )
+# 40215 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3592 "parsing/parser.mly"
+           ( "module" )
+# 40240 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3593 "parsing/parser.mly"
+            ( "mutable" )
+# 40265 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3594 "parsing/parser.mly"
+        ( "new" )
+# 40290 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3595 "parsing/parser.mly"
+           ( "nonrec" )
+# 40315 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3596 "parsing/parser.mly"
+           ( "object" )
+# 40340 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3597 "parsing/parser.mly"
+       ( "of" )
+# 40365 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3598 "parsing/parser.mly"
+         ( "open" )
+# 40390 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3599 "parsing/parser.mly"
+       ( "or" )
+# 40415 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3600 "parsing/parser.mly"
+            ( "private" )
+# 40440 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3601 "parsing/parser.mly"
+        ( "rec" )
+# 40465 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3602 "parsing/parser.mly"
+        ( "sig" )
+# 40490 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3603 "parsing/parser.mly"
+           ( "struct" )
+# 40515 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3604 "parsing/parser.mly"
+         ( "then" )
+# 40540 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3605 "parsing/parser.mly"
+       ( "to" )
+# 40565 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3606 "parsing/parser.mly"
+         ( "true" )
+# 40590 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3607 "parsing/parser.mly"
+        ( "try" )
+# 40615 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3608 "parsing/parser.mly"
+         ( "type" )
+# 40640 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3609 "parsing/parser.mly"
+        ( "val" )
+# 40665 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3610 "parsing/parser.mly"
+            ( "virtual" )
+# 40690 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3611 "parsing/parser.mly"
+         ( "when" )
+# 40715 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3612 "parsing/parser.mly"
+          ( "while" )
+# 40740 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3613 "parsing/parser.mly"
+         ( "with" )
+# 40765 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.type_exception * string Asttypes.loc option) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.type_exception * string Asttypes.loc option) = 
+# 2914 "parsing/parser.mly"
+    ( _1 )
+# 40790 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined5;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined5_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined4;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined4_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined3;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _5;
+                MenhirLib.EngineTypes.startp = _startpos__5_;
+                MenhirLib.EngineTypes.endp = _endpos__5_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = ext;
+                      MenhirLib.EngineTypes.startp = _startpos_ext_;
+                      MenhirLib.EngineTypes.endp = _endpos_ext_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _menhir_s;
+                        MenhirLib.EngineTypes.semv = _1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_;
+                        MenhirLib.EngineTypes.next = _menhir_stack;
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined5 : (Parsetree.attributes) = Obj.magic _1_inlined5 in
+        let _1_inlined4 : (Parsetree.attributes) = Obj.magic _1_inlined4 in
+        let _1_inlined3 : (Longident.t) = Obj.magic _1_inlined3 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined2 : (string) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined5_ in
+        let _v : (Parsetree.type_exception * string Asttypes.loc option) = let attrs =
+          let _1 = _1_inlined5 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 40866 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs_ = _endpos__1_inlined5_ in
+        let attrs2 =
+          let _1 = _1_inlined4 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 40875 "parsing/parser.ml"
+          
+        in
+        let lid =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 40886 "parsing/parser.ml"
+          
+        in
+        let id =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 40897 "parsing/parser.ml"
+          
+        in
+        let attrs1 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 40905 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_attrs_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2923 "parsing/parser.mly"
+  ( let loc = make_loc _sloc in
+    let docs = symbol_docs _sloc in
+    Te.mk_exception ~attrs
+      (Te.rebind id lid ~attrs:(attrs1 @ attrs2) ~loc ~docs)
+    , ext )
+# 40918 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.expression) = 
+# 2438 "parsing/parser.mly"
+      ( _2 )
+# 40950 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.expression) = Obj.magic _2 in
+        let _1 : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.expression) = let _endpos = _endpos__2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2440 "parsing/parser.mly"
+      ( let (l, o, p) = _1 in ghexp ~loc:_sloc (Pexp_fun(l, o, p, _2)) )
+# 40985 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _5;
+          MenhirLib.EngineTypes.startp = _startpos__5_;
+          MenhirLib.EngineTypes.endp = _endpos__5_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = xs;
+              MenhirLib.EngineTypes.startp = _startpos_xs_;
+              MenhirLib.EngineTypes.endp = _endpos_xs_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _5 : (Parsetree.expression) = Obj.magic _5 in
+        let _4 : unit = Obj.magic _4 in
+        let xs : (string Asttypes.loc list) = Obj.magic xs in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__5_ in
+        let _v : (Parsetree.expression) = let _3 = 
+# 2341 "parsing/parser.mly"
+    ( xs )
+# 41038 "parsing/parser.ml"
+         in
+        let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2442 "parsing/parser.mly"
+      ( mk_newtypes ~loc:_sloc _3 _5 )
+# 41046 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = xss;
+          MenhirLib.EngineTypes.startp = _startpos_xss_;
+          MenhirLib.EngineTypes.endp = _endpos_xss_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let xss : (Parsetree.structure_item list list) = Obj.magic xss in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xss_ in
+        let _endpos = _endpos_xss_ in
+        let _v : (Parsetree.structure) = let _1 =
+          let _1 =
+            let ys = 
+# 260 "menhir/standard.mly"
+    ( List.flatten xss )
+# 41073 "parsing/parser.ml"
+             in
+            let xs =
+              let items = 
+# 840 "parsing/parser.mly"
+    ( [] )
+# 41079 "parsing/parser.ml"
+               in
+              
+# 1225 "parsing/parser.mly"
+    ( items )
+# 41084 "parsing/parser.ml"
+              
+            in
+            
+# 267 "menhir/standard.mly"
+    ( xs @ ys )
+# 41090 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in
+          let _endpos = _endpos__1_ in
+          let _startpos = _startpos__1_ in
+          
+# 762 "parsing/parser.mly"
+                              ( extra_str _startpos _endpos _1 )
+# 41099 "parsing/parser.ml"
+          
+        in
+        
+# 1218 "parsing/parser.mly"
+  ( _1 )
+# 41105 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xss;
+          MenhirLib.EngineTypes.startp = _startpos_xss_;
+          MenhirLib.EngineTypes.endp = _endpos_xss_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e;
+              MenhirLib.EngineTypes.startp = _startpos_e_;
+              MenhirLib.EngineTypes.endp = _endpos_e_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let xss : (Parsetree.structure_item list list) = Obj.magic xss in
+        let _1 : (Parsetree.attributes) = Obj.magic _1 in
+        let e : (Parsetree.expression) = Obj.magic e in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e_ in
+        let _endpos = _endpos_xss_ in
+        let _v : (Parsetree.structure) = let _1 =
+          let _1 =
+            let ys = 
+# 260 "menhir/standard.mly"
+    ( List.flatten xss )
+# 41146 "parsing/parser.ml"
+             in
+            let xs =
+              let items =
+                let x =
+                  let _1 =
+                    let _1 =
+                      let attrs = 
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 41156 "parsing/parser.ml"
+                       in
+                      
+# 1232 "parsing/parser.mly"
+    ( mkstrexp e attrs )
+# 41161 "parsing/parser.ml"
+                      
+                    in
+                    let _startpos__1_ = _startpos_e_ in
+                    let _startpos = _startpos__1_ in
+                    
+# 774 "parsing/parser.mly"
+  ( text_str _startpos @ [_1] )
+# 41169 "parsing/parser.ml"
+                    
+                  in
+                  let _startpos__1_ = _startpos_e_ in
+                  let _endpos = _endpos__1_ in
+                  let _startpos = _startpos__1_ in
+                  
+# 793 "parsing/parser.mly"
+  ( mark_rhs_docs _startpos _endpos;
+    _1 )
+# 41179 "parsing/parser.ml"
+                  
+                in
+                
+# 842 "parsing/parser.mly"
+    ( x )
+# 41185 "parsing/parser.ml"
+                
+              in
+              
+# 1225 "parsing/parser.mly"
+    ( items )
+# 41191 "parsing/parser.ml"
+              
+            in
+            
+# 267 "menhir/standard.mly"
+    ( xs @ ys )
+# 41197 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_e_) in
+          let _endpos = _endpos__1_ in
+          let _startpos = _startpos__1_ in
+          
+# 762 "parsing/parser.mly"
+                              ( extra_str _startpos _endpos _1 )
+# 41206 "parsing/parser.ml"
+          
+        in
+        
+# 1218 "parsing/parser.mly"
+  ( _1 )
+# 41212 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (let_bindings) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.structure_item) = let _endpos = _endpos__1_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1247 "parsing/parser.mly"
+      ( val_of_let_bindings ~loc:_sloc _1 )
+# 41240 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : (Parsetree.extension) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.structure_item) = let _1 =
+          let _1 =
+            let _2 =
+              let _1 = _1_inlined1 in
+              
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 41276 "parsing/parser.ml"
+              
+            in
+            let _endpos__2_ = _endpos__1_inlined1_ in
+            let _endpos = _endpos__2_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 1250 "parsing/parser.mly"
+        ( let docs = symbol_docs _sloc in
+          Pstr_extension (_1, add_docs_attrs docs _2) )
+# 41287 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined1_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 809 "parsing/parser.mly"
+    ( mkstr ~loc:_sloc _1 )
+# 41297 "parsing/parser.ml"
+          
+        in
+        
+# 1281 "parsing/parser.mly"
+    ( _1 )
+# 41303 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.attribute) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.structure_item) = let _1 =
+          let _1 = 
+# 1253 "parsing/parser.mly"
+        ( Pstr_attribute _1 )
+# 41329 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 809 "parsing/parser.mly"
+    ( mkstr ~loc:_sloc _1 )
+# 41337 "parsing/parser.ml"
+          
+        in
+        
+# 1281 "parsing/parser.mly"
+    ( _1 )
+# 41343 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.value_description * string Asttypes.loc option) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.structure_item) = let _1 =
+          let _1 = 
+# 1257 "parsing/parser.mly"
+        ( pstr_primitive _1 )
+# 41369 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 826 "parsing/parser.mly"
+    ( wrap_mkstr_ext ~loc:_sloc _1 )
+# 41377 "parsing/parser.ml"
+          
+        in
+        
+# 1281 "parsing/parser.mly"
+    ( _1 )
+# 41383 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.value_description * string Asttypes.loc option) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.structure_item) = let _1 =
+          let _1 = 
+# 1259 "parsing/parser.mly"
+        ( pstr_primitive _1 )
+# 41409 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 826 "parsing/parser.mly"
+    ( wrap_mkstr_ext ~loc:_sloc _1 )
+# 41417 "parsing/parser.ml"
+          
+        in
+        
+# 1281 "parsing/parser.mly"
+    ( _1 )
+# 41423 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = bs;
+          MenhirLib.EngineTypes.startp = _startpos_bs_;
+          MenhirLib.EngineTypes.endp = _endpos_bs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = a;
+            MenhirLib.EngineTypes.startp = _startpos_a_;
+            MenhirLib.EngineTypes.endp = _endpos_a_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let bs : (Parsetree.type_declaration list) = Obj.magic bs in
+        let a : ((Asttypes.rec_flag * string Asttypes.loc option) *
+  Parsetree.type_declaration) = Obj.magic a in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_a_ in
+        let _endpos = _endpos_bs_ in
+        let _v : (Parsetree.structure_item) = let _1 =
+          let _1 =
+            let _1 =
+              let _1 =
+                let _1 = 
+# 1001 "parsing/parser.mly"
+    ( let (x, b) = a in x, b :: bs )
+# 41460 "parsing/parser.ml"
+                 in
+                
+# 2769 "parsing/parser.mly"
+  ( _1 )
+# 41465 "parsing/parser.ml"
+                
+              in
+              
+# 2752 "parsing/parser.mly"
+    ( _1 )
+# 41471 "parsing/parser.ml"
+              
+            in
+            
+# 1261 "parsing/parser.mly"
+        ( pstr_type _1 )
+# 41477 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_bs_, _startpos_a_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 826 "parsing/parser.mly"
+    ( wrap_mkstr_ext ~loc:_sloc _1 )
+# 41487 "parsing/parser.ml"
+          
+        in
+        
+# 1281 "parsing/parser.mly"
+    ( _1 )
+# 41493 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = priv;
+              MenhirLib.EngineTypes.startp = _startpos_priv_;
+              MenhirLib.EngineTypes.endp = _endpos_priv_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _7;
+                MenhirLib.EngineTypes.startp = _startpos__7_;
+                MenhirLib.EngineTypes.endp = _endpos__7_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined2;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = params;
+                    MenhirLib.EngineTypes.startp = _startpos_params_;
+                    MenhirLib.EngineTypes.endp = _endpos_params_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = ext;
+                        MenhirLib.EngineTypes.startp = _startpos_ext_;
+                        MenhirLib.EngineTypes.endp = _endpos_ext_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let xs : (Parsetree.extension_constructor list) = Obj.magic xs in
+        let priv : (Asttypes.private_flag) = Obj.magic priv in
+        let _7 : unit = Obj.magic _7 in
+        let _1_inlined2 : (Longident.t) = Obj.magic _1_inlined2 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (Parsetree.structure_item) = let _1 =
+          let _1 =
+            let _1 =
+              let _1 =
+                let attrs2 =
+                  let _1 = _1_inlined3 in
+                  
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 41580 "parsing/parser.ml"
+                  
+                in
+                let _endpos_attrs2_ = _endpos__1_inlined3_ in
+                let cs = 
+# 993 "parsing/parser.mly"
+    ( List.rev xs )
+# 41587 "parsing/parser.ml"
+                 in
+                let tid =
+                  let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+                  let _endpos = _endpos__1_ in
+                  let _symbolstartpos = _startpos__1_ in
+                  let _sloc = (_symbolstartpos, _endpos) in
+                  
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 41597 "parsing/parser.ml"
+                  
+                in
+                let _4 = 
+# 3485 "parsing/parser.mly"
+                ( Recursive )
+# 41603 "parsing/parser.ml"
+                 in
+                let attrs1 =
+                  let _1 = _1_inlined1 in
+                  
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 41610 "parsing/parser.ml"
+                  
+                in
+                let _endpos = _endpos_attrs2_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 3006 "parsing/parser.mly"
+    ( let docs = symbol_docs _sloc in
+      let attrs = attrs1 @ attrs2 in
+      Te.mk tid cs ~params ~priv ~attrs ~docs,
+      ext )
+# 41622 "parsing/parser.ml"
+                
+              in
+              
+# 2989 "parsing/parser.mly"
+    ( _1 )
+# 41628 "parsing/parser.ml"
+              
+            in
+            
+# 1263 "parsing/parser.mly"
+        ( pstr_typext _1 )
+# 41634 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 826 "parsing/parser.mly"
+    ( wrap_mkstr_ext ~loc:_sloc _1 )
+# 41644 "parsing/parser.ml"
+          
+        in
+        
+# 1281 "parsing/parser.mly"
+    ( _1 )
+# 41650 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined4;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined4_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = priv;
+              MenhirLib.EngineTypes.startp = _startpos_priv_;
+              MenhirLib.EngineTypes.endp = _endpos_priv_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _7;
+                MenhirLib.EngineTypes.startp = _startpos__7_;
+                MenhirLib.EngineTypes.endp = _endpos__7_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined3;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = params;
+                    MenhirLib.EngineTypes.startp = _startpos_params_;
+                    MenhirLib.EngineTypes.endp = _endpos_params_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined2;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = _1_inlined1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _;
+                          MenhirLib.EngineTypes.semv = ext;
+                          MenhirLib.EngineTypes.startp = _startpos_ext_;
+                          MenhirLib.EngineTypes.endp = _endpos_ext_;
+                          MenhirLib.EngineTypes.next = {
+                            MenhirLib.EngineTypes.state = _menhir_s;
+                            MenhirLib.EngineTypes.semv = _1;
+                            MenhirLib.EngineTypes.startp = _startpos__1_;
+                            MenhirLib.EngineTypes.endp = _endpos__1_;
+                            MenhirLib.EngineTypes.next = _menhir_stack;
+                          };
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined4 : (Parsetree.attributes) = Obj.magic _1_inlined4 in
+        let xs : (Parsetree.extension_constructor list) = Obj.magic xs in
+        let priv : (Asttypes.private_flag) = Obj.magic priv in
+        let _7 : unit = Obj.magic _7 in
+        let _1_inlined3 : (Longident.t) = Obj.magic _1_inlined3 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let _1_inlined2 : unit = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined4_ in
+        let _v : (Parsetree.structure_item) = let _1 =
+          let _1 =
+            let _1 =
+              let _1 =
+                let attrs2 =
+                  let _1 = _1_inlined4 in
+                  
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 41744 "parsing/parser.ml"
+                  
+                in
+                let _endpos_attrs2_ = _endpos__1_inlined4_ in
+                let cs = 
+# 993 "parsing/parser.mly"
+    ( List.rev xs )
+# 41751 "parsing/parser.ml"
+                 in
+                let tid =
+                  let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in
+                  let _endpos = _endpos__1_ in
+                  let _symbolstartpos = _startpos__1_ in
+                  let _sloc = (_symbolstartpos, _endpos) in
+                  
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 41761 "parsing/parser.ml"
+                  
+                in
+                let _4 =
+                  let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+                  let _endpos = _endpos__1_ in
+                  let _startpos = _startpos__1_ in
+                  let _loc = (_startpos, _endpos) in
+                  
+# 3486 "parsing/parser.mly"
+                ( not_expecting _loc "nonrec flag" )
+# 41772 "parsing/parser.ml"
+                  
+                in
+                let attrs1 =
+                  let _1 = _1_inlined1 in
+                  
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 41780 "parsing/parser.ml"
+                  
+                in
+                let _endpos = _endpos_attrs2_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 3006 "parsing/parser.mly"
+    ( let docs = symbol_docs _sloc in
+      let attrs = attrs1 @ attrs2 in
+      Te.mk tid cs ~params ~priv ~attrs ~docs,
+      ext )
+# 41792 "parsing/parser.ml"
+                
+              in
+              
+# 2989 "parsing/parser.mly"
+    ( _1 )
+# 41798 "parsing/parser.ml"
+              
+            in
+            
+# 1263 "parsing/parser.mly"
+        ( pstr_typext _1 )
+# 41804 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined4_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 826 "parsing/parser.mly"
+    ( wrap_mkstr_ext ~loc:_sloc _1 )
+# 41814 "parsing/parser.ml"
+          
+        in
+        
+# 1281 "parsing/parser.mly"
+    ( _1 )
+# 41820 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.type_exception * string Asttypes.loc option) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.structure_item) = let _1 =
+          let _1 = 
+# 1265 "parsing/parser.mly"
+        ( pstr_exception _1 )
+# 41846 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 826 "parsing/parser.mly"
+    ( wrap_mkstr_ext ~loc:_sloc _1 )
+# 41854 "parsing/parser.ml"
+          
+        in
+        
+# 1281 "parsing/parser.mly"
+    ( _1 )
+# 41860 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = body;
+            MenhirLib.EngineTypes.startp = _startpos_body_;
+            MenhirLib.EngineTypes.endp = _endpos_body_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = ext;
+                  MenhirLib.EngineTypes.startp = _startpos_ext_;
+                  MenhirLib.EngineTypes.endp = _endpos_ext_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let body : (Parsetree.module_expr) = Obj.magic body in
+        let _1_inlined2 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 41913 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (Parsetree.structure_item) = let _1 =
+          let _1 =
+            let _1 =
+              let attrs2 =
+                let _1 = _1_inlined3 in
+                
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 41929 "parsing/parser.ml"
+                
+              in
+              let _endpos_attrs2_ = _endpos__1_inlined3_ in
+              let uid =
+                let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+                let _endpos = _endpos__1_ in
+                let _symbolstartpos = _startpos__1_ in
+                let _sloc = (_symbolstartpos, _endpos) in
+                
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 41941 "parsing/parser.ml"
+                
+              in
+              let attrs1 =
+                let _1 = _1_inlined1 in
+                
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 41949 "parsing/parser.ml"
+                
+              in
+              let _endpos = _endpos_attrs2_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 1291 "parsing/parser.mly"
+    ( let docs = symbol_docs _sloc in
+      let loc = make_loc _sloc in
+      let attrs = attrs1 @ attrs2 in
+      let body = Mb.mk uid body ~attrs ~loc ~docs in
+      Pstr_module body, ext )
+# 41962 "parsing/parser.ml"
+              
+            in
+            
+# 1267 "parsing/parser.mly"
+        ( _1 )
+# 41968 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined3_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 826 "parsing/parser.mly"
+    ( wrap_mkstr_ext ~loc:_sloc _1 )
+# 41978 "parsing/parser.ml"
+          
+        in
+        
+# 1281 "parsing/parser.mly"
+    ( _1 )
+# 41984 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = bs;
+          MenhirLib.EngineTypes.startp = _startpos_bs_;
+          MenhirLib.EngineTypes.endp = _endpos_bs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = body;
+              MenhirLib.EngineTypes.startp = _startpos_body_;
+              MenhirLib.EngineTypes.endp = _endpos_body_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _4;
+                  MenhirLib.EngineTypes.startp = _startpos__4_;
+                  MenhirLib.EngineTypes.endp = _endpos__4_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = ext;
+                      MenhirLib.EngineTypes.startp = _startpos_ext_;
+                      MenhirLib.EngineTypes.endp = _endpos_ext_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _menhir_s;
+                        MenhirLib.EngineTypes.semv = _1;
+                        MenhirLib.EngineTypes.startp = _startpos__1_;
+                        MenhirLib.EngineTypes.endp = _endpos__1_;
+                        MenhirLib.EngineTypes.next = _menhir_stack;
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let bs : (Parsetree.module_binding list) = Obj.magic bs in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let body : (Parsetree.module_expr) = Obj.magic body in
+        let _1_inlined2 : (
+# 666 "parsing/parser.mly"
+       (string)
+# 42050 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _4 : unit = Obj.magic _4 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_bs_ in
+        let _v : (Parsetree.structure_item) = let _1 =
+          let _1 =
+            let _1 =
+              let _1 =
+                let a =
+                  let attrs2 =
+                    let _1 = _1_inlined3 in
+                    
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 42069 "parsing/parser.ml"
+                    
+                  in
+                  let _endpos_attrs2_ = _endpos__1_inlined3_ in
+                  let uid =
+                    let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+                    let _endpos = _endpos__1_ in
+                    let _symbolstartpos = _startpos__1_ in
+                    let _sloc = (_symbolstartpos, _endpos) in
+                    
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 42081 "parsing/parser.ml"
+                    
+                  in
+                  let attrs1 =
+                    let _1 = _1_inlined1 in
+                    
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 42089 "parsing/parser.ml"
+                    
+                  in
+                  let _endpos = _endpos_attrs2_ in
+                  let _symbolstartpos = _startpos__1_ in
+                  let _sloc = (_symbolstartpos, _endpos) in
+                  
+# 1326 "parsing/parser.mly"
+  (
+    let loc = make_loc _sloc in
+    let attrs = attrs1 @ attrs2 in
+    let docs = symbol_docs _sloc in
+    ext,
+    Mb.mk uid body ~attrs ~loc ~docs
+  )
+# 42104 "parsing/parser.ml"
+                  
+                in
+                
+# 1001 "parsing/parser.mly"
+    ( let (x, b) = a in x, b :: bs )
+# 42110 "parsing/parser.ml"
+                
+              in
+              
+# 1314 "parsing/parser.mly"
+    ( _1 )
+# 42116 "parsing/parser.ml"
+              
+            in
+            
+# 1269 "parsing/parser.mly"
+        ( pstr_recmodule _1 )
+# 42122 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos_bs_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 826 "parsing/parser.mly"
+    ( wrap_mkstr_ext ~loc:_sloc _1 )
+# 42132 "parsing/parser.ml"
+          
+        in
+        
+# 1281 "parsing/parser.mly"
+    ( _1 )
+# 42138 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.module_type_declaration * string Asttypes.loc option) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.structure_item) = let _1 =
+          let _1 = 
+# 1271 "parsing/parser.mly"
+        ( let (body, ext) = _1 in (Pstr_modtype body, ext) )
+# 42164 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 826 "parsing/parser.mly"
+    ( wrap_mkstr_ext ~loc:_sloc _1 )
+# 42172 "parsing/parser.ml"
+          
+        in
+        
+# 1281 "parsing/parser.mly"
+    ( _1 )
+# 42178 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (Parsetree.open_declaration * string Asttypes.loc option) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.structure_item) = let _1 =
+          let _1 = 
+# 1273 "parsing/parser.mly"
+        ( let (body, ext) = _1 in (Pstr_open body, ext) )
+# 42204 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 826 "parsing/parser.mly"
+    ( wrap_mkstr_ext ~loc:_sloc _1 )
+# 42212 "parsing/parser.ml"
+          
+        in
+        
+# 1281 "parsing/parser.mly"
+    ( _1 )
+# 42218 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = bs;
+          MenhirLib.EngineTypes.startp = _startpos_bs_;
+          MenhirLib.EngineTypes.endp = _endpos_bs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined3;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = body;
+              MenhirLib.EngineTypes.startp = _startpos_body_;
+              MenhirLib.EngineTypes.endp = _endpos_body_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = params;
+                  MenhirLib.EngineTypes.startp = _startpos_params_;
+                  MenhirLib.EngineTypes.endp = _endpos_params_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = virt;
+                    MenhirLib.EngineTypes.startp = _startpos_virt_;
+                    MenhirLib.EngineTypes.endp = _endpos_virt_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _;
+                      MenhirLib.EngineTypes.semv = _1_inlined1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                      MenhirLib.EngineTypes.next = {
+                        MenhirLib.EngineTypes.state = _;
+                        MenhirLib.EngineTypes.semv = ext;
+                        MenhirLib.EngineTypes.startp = _startpos_ext_;
+                        MenhirLib.EngineTypes.endp = _endpos_ext_;
+                        MenhirLib.EngineTypes.next = {
+                          MenhirLib.EngineTypes.state = _menhir_s;
+                          MenhirLib.EngineTypes.semv = _1;
+                          MenhirLib.EngineTypes.startp = _startpos__1_;
+                          MenhirLib.EngineTypes.endp = _endpos__1_;
+                          MenhirLib.EngineTypes.next = _menhir_stack;
+                        };
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let bs : (Parsetree.class_declaration list) = Obj.magic bs in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let body : (Parsetree.class_expr) = Obj.magic body in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 42290 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let params : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic params in
+        let virt : (Asttypes.virtual_flag) = Obj.magic virt in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_bs_ in
+        let _v : (Parsetree.structure_item) = let _1 =
+          let _1 =
+            let _1 =
+              let _1 =
+                let a =
+                  let attrs2 =
+                    let _1 = _1_inlined3 in
+                    
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 42310 "parsing/parser.ml"
+                    
+                  in
+                  let _endpos_attrs2_ = _endpos__1_inlined3_ in
+                  let id =
+                    let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+                    let _endpos = _endpos__1_ in
+                    let _symbolstartpos = _startpos__1_ in
+                    let _sloc = (_symbolstartpos, _endpos) in
+                    
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 42322 "parsing/parser.ml"
+                    
+                  in
+                  let attrs1 =
+                    let _1 = _1_inlined1 in
+                    
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 42330 "parsing/parser.ml"
+                    
+                  in
+                  let _endpos = _endpos_attrs2_ in
+                  let _symbolstartpos = _startpos__1_ in
+                  let _sloc = (_symbolstartpos, _endpos) in
+                  
+# 1645 "parsing/parser.mly"
+  (
+    let attrs = attrs1 @ attrs2 in
+    let loc = make_loc _sloc in
+    let docs = symbol_docs _sloc in
+    ext,
+    Ci.mk id body ~virt ~params ~attrs ~loc ~docs
+  )
+# 42345 "parsing/parser.ml"
+                  
+                in
+                
+# 1001 "parsing/parser.mly"
+    ( let (x, b) = a in x, b :: bs )
+# 42351 "parsing/parser.ml"
+                
+              in
+              
+# 1634 "parsing/parser.mly"
+    ( _1 )
+# 42357 "parsing/parser.ml"
+              
+            in
+            
+# 1275 "parsing/parser.mly"
+        ( let (ext, l) = _1 in (Pstr_class l, ext) )
+# 42363 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos_bs_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 826 "parsing/parser.mly"
+    ( wrap_mkstr_ext ~loc:_sloc _1 )
+# 42373 "parsing/parser.ml"
+          
+        in
+        
+# 1281 "parsing/parser.mly"
+    ( _1 )
+# 42379 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (string Asttypes.loc option * Parsetree.class_type_declaration list) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.structure_item) = let _1 =
+          let _1 = 
+# 1277 "parsing/parser.mly"
+        ( let (ext, l) = _1 in (Pstr_class_type l, ext) )
+# 42405 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 826 "parsing/parser.mly"
+    ( wrap_mkstr_ext ~loc:_sloc _1 )
+# 42413 "parsing/parser.ml"
+          
+        in
+        
+# 1281 "parsing/parser.mly"
+    ( _1 )
+# 42419 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = thing;
+            MenhirLib.EngineTypes.startp = _startpos_thing_;
+            MenhirLib.EngineTypes.endp = _endpos_thing_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = ext;
+                MenhirLib.EngineTypes.startp = _startpos_ext_;
+                MenhirLib.EngineTypes.endp = _endpos_ext_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in
+        let thing : (Parsetree.module_expr) = Obj.magic thing in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.structure_item) = let _1 =
+          let _1 =
+            let _1 =
+              let attrs2 =
+                let _1 = _1_inlined2 in
+                
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 42477 "parsing/parser.ml"
+                
+              in
+              let _endpos_attrs2_ = _endpos__1_inlined2_ in
+              let attrs1 =
+                let _1 = _1_inlined1 in
+                
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 42486 "parsing/parser.ml"
+                
+              in
+              let _endpos = _endpos_attrs2_ in
+              let _symbolstartpos = _startpos__1_ in
+              let _sloc = (_symbolstartpos, _endpos) in
+              
+# 1363 "parsing/parser.mly"
+  (
+    let attrs = attrs1 @ attrs2 in
+    let loc = make_loc _sloc in
+    let docs = symbol_docs _sloc in
+    Incl.mk thing ~attrs ~loc ~docs, ext
+  )
+# 42500 "parsing/parser.ml"
+              
+            in
+            
+# 1279 "parsing/parser.mly"
+        ( pstr_include _1 )
+# 42506 "parsing/parser.ml"
+            
+          in
+          let _endpos__1_ = _endpos__1_inlined2_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 826 "parsing/parser.mly"
+    ( wrap_mkstr_ext ~loc:_sloc _1 )
+# 42516 "parsing/parser.ml"
+          
+        in
+        
+# 1281 "parsing/parser.mly"
+    ( _1 )
+# 42522 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3548 "parsing/parser.mly"
+                                                ( "-" )
+# 42547 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3549 "parsing/parser.mly"
+                                                ( "-." )
+# 42572 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _3;
+              MenhirLib.EngineTypes.startp = _startpos__3_;
+              MenhirLib.EngineTypes.endp = _endpos__3_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let xs : (Parsetree.core_type list) = Obj.magic xs in
+        let _3 : (bool) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Asttypes.label) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.row_field) = let _5 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 42627 "parsing/parser.ml"
+          
+        in
+        let _endpos__5_ = _endpos__1_inlined1_ in
+        let _4 =
+          let _1 =
+            let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 42636 "parsing/parser.ml"
+             in
+            
+# 904 "parsing/parser.mly"
+    ( xs )
+# 42641 "parsing/parser.ml"
+            
+          in
+          
+# 3276 "parsing/parser.mly"
+    ( _1 )
+# 42647 "parsing/parser.ml"
+          
+        in
+        let _1 =
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 42657 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3262 "parsing/parser.mly"
+      ( let info = symbol_info _endpos in
+        let attrs = add_info_attrs info _5 in
+        Rf.tag ~loc:(make_loc _sloc) ~attrs _1 _3 _4 )
+# 42668 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : (Asttypes.label) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.row_field) = let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 42702 "parsing/parser.ml"
+          
+        in
+        let _endpos__2_ = _endpos__1_inlined1_ in
+        let _1 =
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 42713 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3266 "parsing/parser.mly"
+      ( let info = symbol_info _endpos in
+        let attrs = add_info_attrs info _2 in
+        Rf.tag ~loc:(make_loc _sloc) ~attrs _1 true [] )
+# 42724 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined1;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _1_inlined1 : (Asttypes.label) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined1_ in
+        let _v : (Parsetree.toplevel_phrase) = let arg = 
+# 124 "menhir/standard.mly"
+    ( None )
+# 42756 "parsing/parser.ml"
+         in
+        let _endpos_arg_ = _endpos__1_inlined1_ in
+        let dir =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 42767 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_arg_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3448 "parsing/parser.mly"
+    ( mk_directive ~loc:_sloc dir arg )
+# 42776 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (
+# 658 "parsing/parser.mly"
+       (string * string option)
+# 42809 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Asttypes.label) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.toplevel_phrase) = let arg =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let x =
+            let _1 = 
+# 3452 "parsing/parser.mly"
+                  ( let (s, _) = _1 in Pdir_string s )
+# 42822 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 831 "parsing/parser.mly"
+    ( mk_directive_arg ~loc:_sloc _1 )
+# 42830 "parsing/parser.ml"
+            
+          in
+          
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 42836 "parsing/parser.ml"
+          
+        in
+        let _endpos_arg_ = _endpos__1_inlined2_ in
+        let dir =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 42848 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_arg_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3448 "parsing/parser.mly"
+    ( mk_directive ~loc:_sloc dir arg )
+# 42857 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (
+# 606 "parsing/parser.mly"
+       (string * char option)
+# 42890 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Asttypes.label) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.toplevel_phrase) = let arg =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let x =
+            let _1 = 
+# 3453 "parsing/parser.mly"
+                  ( let (n, m) = _1 in Pdir_int (n ,m) )
+# 42903 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 831 "parsing/parser.mly"
+    ( mk_directive_arg ~loc:_sloc _1 )
+# 42911 "parsing/parser.ml"
+            
+          in
+          
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 42917 "parsing/parser.ml"
+          
+        in
+        let _endpos_arg_ = _endpos__1_inlined2_ in
+        let dir =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 42929 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_arg_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3448 "parsing/parser.mly"
+    ( mk_directive ~loc:_sloc dir arg )
+# 42938 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Longident.t) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Asttypes.label) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.toplevel_phrase) = let arg =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let x =
+            let _1 = 
+# 3454 "parsing/parser.mly"
+                  ( Pdir_ident _1 )
+# 42980 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 831 "parsing/parser.mly"
+    ( mk_directive_arg ~loc:_sloc _1 )
+# 42988 "parsing/parser.ml"
+            
+          in
+          
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 42994 "parsing/parser.ml"
+          
+        in
+        let _endpos_arg_ = _endpos__1_inlined2_ in
+        let dir =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 43006 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_arg_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3448 "parsing/parser.mly"
+    ( mk_directive ~loc:_sloc dir arg )
+# 43015 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Longident.t) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Asttypes.label) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.toplevel_phrase) = let arg =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let x =
+            let _1 = 
+# 3455 "parsing/parser.mly"
+                  ( Pdir_ident _1 )
+# 43057 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 831 "parsing/parser.mly"
+    ( mk_directive_arg ~loc:_sloc _1 )
+# 43065 "parsing/parser.ml"
+            
+          in
+          
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 43071 "parsing/parser.ml"
+          
+        in
+        let _endpos_arg_ = _endpos__1_inlined2_ in
+        let dir =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 43083 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_arg_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3448 "parsing/parser.mly"
+    ( mk_directive ~loc:_sloc dir arg )
+# 43092 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : unit = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Asttypes.label) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.toplevel_phrase) = let arg =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let x =
+            let _1 = 
+# 3456 "parsing/parser.mly"
+                  ( Pdir_bool false )
+# 43134 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 831 "parsing/parser.mly"
+    ( mk_directive_arg ~loc:_sloc _1 )
+# 43142 "parsing/parser.ml"
+            
+          in
+          
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 43148 "parsing/parser.ml"
+          
+        in
+        let _endpos_arg_ = _endpos__1_inlined2_ in
+        let dir =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 43160 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_arg_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3448 "parsing/parser.mly"
+    ( mk_directive ~loc:_sloc dir arg )
+# 43169 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined1;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : unit = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Asttypes.label) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.toplevel_phrase) = let arg =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let x =
+            let _1 = 
+# 3457 "parsing/parser.mly"
+                  ( Pdir_bool true )
+# 43211 "parsing/parser.ml"
+             in
+            let _endpos = _endpos__1_ in
+            let _symbolstartpos = _startpos__1_ in
+            let _sloc = (_symbolstartpos, _endpos) in
+            
+# 831 "parsing/parser.mly"
+    ( mk_directive_arg ~loc:_sloc _1 )
+# 43219 "parsing/parser.ml"
+            
+          in
+          
+# 126 "menhir/standard.mly"
+    ( Some x )
+# 43225 "parsing/parser.ml"
+          
+        in
+        let _endpos_arg_ = _endpos__1_inlined2_ in
+        let dir =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 43237 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_arg_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3448 "parsing/parser.mly"
+    ( mk_directive ~loc:_sloc dir arg )
+# 43246 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = e;
+              MenhirLib.EngineTypes.startp = _startpos_e_;
+              MenhirLib.EngineTypes.endp = _endpos_e_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.attributes) = Obj.magic _1 in
+        let e : (Parsetree.expression) = Obj.magic e in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e_ in
+        let _endpos = _endpos__2_ in
+        let _v : (
+# 750 "parsing/parser.mly"
+      (Parsetree.toplevel_phrase)
+# 43285 "parsing/parser.ml"
+        ) = let _1 =
+          let _1 =
+            let _1 =
+              let attrs = 
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 43292 "parsing/parser.ml"
+               in
+              
+# 1232 "parsing/parser.mly"
+    ( mkstrexp e attrs )
+# 43297 "parsing/parser.ml"
+              
+            in
+            let _startpos__1_ = _startpos_e_ in
+            let _startpos = _startpos__1_ in
+            
+# 774 "parsing/parser.mly"
+  ( text_str _startpos @ [_1] )
+# 43305 "parsing/parser.ml"
+            
+          in
+          let _startpos__1_ = _startpos_e_ in
+          let _endpos = _endpos__1_ in
+          let _startpos = _startpos__1_ in
+          
+# 762 "parsing/parser.mly"
+                              ( extra_str _startpos _endpos _1 )
+# 43314 "parsing/parser.ml"
+          
+        in
+        
+# 1039 "parsing/parser.mly"
+    ( Ptop_def _1 )
+# 43320 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = xss;
+            MenhirLib.EngineTypes.startp = _startpos_xss_;
+            MenhirLib.EngineTypes.endp = _endpos_xss_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let xss : (Parsetree.structure_item list list) = Obj.magic xss in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xss_ in
+        let _endpos = _endpos__2_ in
+        let _v : (
+# 750 "parsing/parser.mly"
+      (Parsetree.toplevel_phrase)
+# 43352 "parsing/parser.ml"
+        ) = let _1 =
+          let _1 = 
+# 260 "menhir/standard.mly"
+    ( List.flatten xss )
+# 43357 "parsing/parser.ml"
+           in
+          let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in
+          let _endpos = _endpos__1_ in
+          let _startpos = _startpos__1_ in
+          
+# 762 "parsing/parser.mly"
+                              ( extra_str _startpos _endpos _1 )
+# 43365 "parsing/parser.ml"
+          
+        in
+        
+# 1043 "parsing/parser.mly"
+    ( Ptop_def _1 )
+# 43371 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Parsetree.toplevel_phrase) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (
+# 750 "parsing/parser.mly"
+      (Parsetree.toplevel_phrase)
+# 43403 "parsing/parser.ml"
+        ) = 
+# 1047 "parsing/parser.mly"
+    ( _1 )
+# 43407 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (
+# 750 "parsing/parser.mly"
+      (Parsetree.toplevel_phrase)
+# 43432 "parsing/parser.ml"
+        ) = 
+# 1050 "parsing/parser.mly"
+    ( raise End_of_file )
+# 43436 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = ty;
+          MenhirLib.EngineTypes.startp = _startpos_ty_;
+          MenhirLib.EngineTypes.endp = _endpos_ty_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let ty : (Parsetree.core_type) = Obj.magic ty in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_ty_ in
+        let _endpos = _endpos_ty_ in
+        let _v : (Parsetree.core_type) = 
+# 3168 "parsing/parser.mly"
+      ( ty )
+# 43461 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let xs : (Parsetree.core_type list) = Obj.magic xs in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xs_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 =
+            let tys =
+              let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 43489 "parsing/parser.ml"
+               in
+              
+# 932 "parsing/parser.mly"
+    ( xs )
+# 43494 "parsing/parser.ml"
+              
+            in
+            
+# 3171 "parsing/parser.mly"
+        ( Ptyp_tuple tys )
+# 43500 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_xs_, _startpos_xs_) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 43510 "parsing/parser.ml"
+          
+        in
+        
+# 3173 "parsing/parser.mly"
+    ( _1 )
+# 43516 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.core_type) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.core_type option * Parsetree.core_type option) = 
+# 2516 "parsing/parser.mly"
+                                                ( (Some _2, None) )
+# 43548 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _4;
+          MenhirLib.EngineTypes.startp = _startpos__4_;
+          MenhirLib.EngineTypes.endp = _endpos__4_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _2;
+              MenhirLib.EngineTypes.startp = _startpos__2_;
+              MenhirLib.EngineTypes.endp = _endpos__2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _4 : (Parsetree.core_type) = Obj.magic _4 in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (Parsetree.core_type) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__4_ in
+        let _v : (Parsetree.core_type option * Parsetree.core_type option) = 
+# 2517 "parsing/parser.mly"
+                                                ( (Some _2, Some _4) )
+# 43594 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.core_type) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.core_type option * Parsetree.core_type option) = 
+# 2518 "parsing/parser.mly"
+                                                ( (None, Some _2) )
+# 43626 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.core_type option * Parsetree.core_type option) = 
+# 2519 "parsing/parser.mly"
+                                                ( syntax_error() )
+# 43658 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.core_type option * Parsetree.core_type option) = 
+# 2520 "parsing/parser.mly"
+                                                ( syntax_error() )
+# 43690 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = 
+# 2843 "parsing/parser.mly"
+      ( (Ptype_abstract, Public, None) )
+# 43708 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = 
+# 2845 "parsing/parser.mly"
+      ( _2 )
+# 43740 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 43761 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Longident.t) = 
+# 3415 "parsing/parser.mly"
+                                                ( Lident _1 )
+# 43769 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 43802 "parsing/parser.ml"
+        ) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Longident.t) = 
+# 3416 "parsing/parser.mly"
+                                                ( Ldot(_1, _3) )
+# 43812 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : (Parsetree.core_type) = Obj.magic _2 in
+        let _1 : (Asttypes.variance) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Parsetree.core_type * Asttypes.variance) = 
+# 2860 "parsing/parser.mly"
+                                       ( _2, _1 )
+# 43844 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : ((Parsetree.core_type * Asttypes.variance) list) = 
+# 2853 "parsing/parser.mly"
+      ( [] )
+# 43862 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = p;
+          MenhirLib.EngineTypes.startp = _startpos_p_;
+          MenhirLib.EngineTypes.endp = _endpos_p_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let p : (Parsetree.core_type * Asttypes.variance) = Obj.magic p in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_p_ in
+        let _endpos = _endpos_p_ in
+        let _v : ((Parsetree.core_type * Asttypes.variance) list) = 
+# 2855 "parsing/parser.mly"
+      ( [p] )
+# 43887 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xs;
+            MenhirLib.EngineTypes.startp = _startpos_xs_;
+            MenhirLib.EngineTypes.endp = _endpos_xs_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let xs : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic xs in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : ((Parsetree.core_type * Asttypes.variance) list) = let ps =
+          let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 43927 "parsing/parser.ml"
+           in
+          
+# 904 "parsing/parser.mly"
+    ( xs )
+# 43932 "parsing/parser.ml"
+          
+        in
+        
+# 2857 "parsing/parser.mly"
+      ( ps )
+# 43938 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = tyvar;
+          MenhirLib.EngineTypes.startp = _startpos_tyvar_;
+          MenhirLib.EngineTypes.endp = _endpos_tyvar_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let tyvar : (Asttypes.label) = Obj.magic tyvar in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_tyvar_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 = 
+# 2865 "parsing/parser.mly"
+      ( Ptyp_var tyvar )
+# 43971 "parsing/parser.ml"
+           in
+          let _endpos__1_ = _endpos_tyvar_ in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 43980 "parsing/parser.ml"
+          
+        in
+        
+# 2868 "parsing/parser.mly"
+    ( _1 )
+# 43986 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Parsetree.core_type) = let _1 =
+          let _1 = 
+# 2867 "parsing/parser.mly"
+      ( Ptyp_any )
+# 44012 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 807 "parsing/parser.mly"
+    ( mktyp ~loc:_sloc _1 )
+# 44020 "parsing/parser.ml"
+          
+        in
+        
+# 2868 "parsing/parser.mly"
+    ( _1 )
+# 44026 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Asttypes.variance) = 
+# 2872 "parsing/parser.mly"
+                                                ( Invariant )
+# 44044 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.variance) = 
+# 2873 "parsing/parser.mly"
+                                                ( Covariant )
+# 44069 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.variance) = 
+# 2874 "parsing/parser.mly"
+                                                ( Contravariant )
+# 44094 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = xss;
+            MenhirLib.EngineTypes.startp = _startpos_xss_;
+            MenhirLib.EngineTypes.endp = _endpos_xss_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let xss : (Parsetree.toplevel_phrase list list) = Obj.magic xss in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_xss_ in
+        let _endpos = _endpos__2_ in
+        let _v : (
+# 752 "parsing/parser.mly"
+      (Parsetree.toplevel_phrase list)
+# 44126 "parsing/parser.ml"
+        ) = let _1 =
+          let _1 =
+            let ys = 
+# 260 "menhir/standard.mly"
+    ( List.flatten xss )
+# 44132 "parsing/parser.ml"
+             in
+            let xs =
+              let _1 = 
+# 840 "parsing/parser.mly"
+    ( [] )
+# 44138 "parsing/parser.ml"
+               in
+              
+# 1070 "parsing/parser.mly"
+    ( _1 )
+# 44143 "parsing/parser.ml"
+              
+            in
+            
+# 267 "menhir/standard.mly"
+    ( xs @ ys )
+# 44149 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in
+          let _endpos = _endpos__1_ in
+          let _startpos = _startpos__1_ in
+          
+# 766 "parsing/parser.mly"
+                              ( extra_def _startpos _endpos _1 )
+# 44158 "parsing/parser.ml"
+          
+        in
+        
+# 1063 "parsing/parser.mly"
+    ( _1 )
+# 44164 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = xss;
+            MenhirLib.EngineTypes.startp = _startpos_xss_;
+            MenhirLib.EngineTypes.endp = _endpos_xss_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = e;
+                MenhirLib.EngineTypes.startp = _startpos_e_;
+                MenhirLib.EngineTypes.endp = _endpos_e_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let xss : (Parsetree.toplevel_phrase list list) = Obj.magic xss in
+        let _1 : (Parsetree.attributes) = Obj.magic _1 in
+        let e : (Parsetree.expression) = Obj.magic e in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos_e_ in
+        let _endpos = _endpos__2_ in
+        let _v : (
+# 752 "parsing/parser.mly"
+      (Parsetree.toplevel_phrase list)
+# 44210 "parsing/parser.ml"
+        ) = let _1 =
+          let _1 =
+            let ys = 
+# 260 "menhir/standard.mly"
+    ( List.flatten xss )
+# 44216 "parsing/parser.ml"
+             in
+            let xs =
+              let _1 =
+                let x =
+                  let _1 =
+                    let _1 =
+                      let attrs = 
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 44226 "parsing/parser.ml"
+                       in
+                      
+# 1232 "parsing/parser.mly"
+    ( mkstrexp e attrs )
+# 44231 "parsing/parser.ml"
+                      
+                    in
+                    
+# 784 "parsing/parser.mly"
+  ( Ptop_def [_1] )
+# 44237 "parsing/parser.ml"
+                    
+                  in
+                  let _startpos__1_ = _startpos_e_ in
+                  let _startpos = _startpos__1_ in
+                  
+# 782 "parsing/parser.mly"
+  ( text_def _startpos @ [_1] )
+# 44245 "parsing/parser.ml"
+                  
+                in
+                
+# 842 "parsing/parser.mly"
+    ( x )
+# 44251 "parsing/parser.ml"
+                
+              in
+              
+# 1070 "parsing/parser.mly"
+    ( _1 )
+# 44257 "parsing/parser.ml"
+              
+            in
+            
+# 267 "menhir/standard.mly"
+    ( xs @ ys )
+# 44263 "parsing/parser.ml"
+            
+          in
+          let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_e_) in
+          let _endpos = _endpos__1_ in
+          let _startpos = _startpos__1_ in
+          
+# 766 "parsing/parser.mly"
+                              ( extra_def _startpos _endpos _1 )
+# 44272 "parsing/parser.ml"
+          
+        in
+        
+# 1063 "parsing/parser.mly"
+    ( _1 )
+# 44278 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 44299 "parsing/parser.ml"
+        ) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (string) = 
+# 3346 "parsing/parser.mly"
+                              ( _1 )
+# 44307 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (string) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (string) = 
+# 3347 "parsing/parser.mly"
+                              ( _2 )
+# 44346 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : (string) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (string) = let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        let _loc__1_ = (_startpos__1_, _endpos__1_) in
+        
+# 3348 "parsing/parser.mly"
+                              ( unclosed "(" _loc__1_ ")" _loc__3_ )
+# 44387 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (string) = let _loc__2_ = (_startpos__2_, _endpos__2_) in
+        
+# 3349 "parsing/parser.mly"
+                              ( expecting _loc__2_ "operator" )
+# 44420 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : unit = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (string) = let _loc__3_ = (_startpos__3_, _endpos__3_) in
+        
+# 3350 "parsing/parser.mly"
+                              ( expecting _loc__3_ "module-expr" )
+# 44460 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : (string) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Longident.t) = 
+# 3398 "parsing/parser.mly"
+                                                ( Lident _1 )
+# 44485 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _3;
+          MenhirLib.EngineTypes.startp = _startpos__3_;
+          MenhirLib.EngineTypes.endp = _endpos__3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _2;
+            MenhirLib.EngineTypes.startp = _startpos__2_;
+            MenhirLib.EngineTypes.endp = _endpos__2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _menhir_s;
+              MenhirLib.EngineTypes.semv = _1;
+              MenhirLib.EngineTypes.startp = _startpos__1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_;
+              MenhirLib.EngineTypes.next = _menhir_stack;
+            };
+          };
+        } = _menhir_stack in
+        let _3 : (string) = Obj.magic _3 in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : (Longident.t) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__3_ in
+        let _v : (Longident.t) = 
+# 3399 "parsing/parser.mly"
+                                                ( Ldot(_1, _3) )
+# 44524 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = ty;
+          MenhirLib.EngineTypes.startp = _startpos_ty_;
+          MenhirLib.EngineTypes.endp = _endpos_ty_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _5;
+            MenhirLib.EngineTypes.startp = _startpos__5_;
+            MenhirLib.EngineTypes.endp = _endpos__5_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = mutable_;
+                MenhirLib.EngineTypes.startp = _startpos_mutable__;
+                MenhirLib.EngineTypes.endp = _endpos_mutable__;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let ty : (Parsetree.core_type) = Obj.magic ty in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 44571 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined1 in
+        let mutable_ : (Asttypes.mutable_flag) = Obj.magic mutable_ in
+        let _1 : (Parsetree.attributes) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_ty_ in
+        let _v : ((Asttypes.label Asttypes.loc * Asttypes.mutable_flag *
+   Parsetree.class_field_kind) *
+  Parsetree.attributes) = let label =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 44585 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 44593 "parsing/parser.ml"
+          
+        in
+        let attrs = 
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 44599 "parsing/parser.ml"
+         in
+        let _1 = 
+# 3541 "parsing/parser.mly"
+                                                ( Fresh )
+# 44604 "parsing/parser.ml"
+         in
+        
+# 1785 "parsing/parser.mly"
+      ( (label, mutable_, Cfk_virtual ty), attrs )
+# 44609 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _6;
+          MenhirLib.EngineTypes.startp = _startpos__6_;
+          MenhirLib.EngineTypes.endp = _endpos__6_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _5;
+            MenhirLib.EngineTypes.startp = _startpos__5_;
+            MenhirLib.EngineTypes.endp = _endpos__5_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _3;
+                MenhirLib.EngineTypes.startp = _startpos__3_;
+                MenhirLib.EngineTypes.endp = _endpos__3_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _6 : (Parsetree.expression) = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 44656 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined1 in
+        let _3 : (Asttypes.mutable_flag) = Obj.magic _3 in
+        let _1 : (Parsetree.attributes) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__6_ in
+        let _v : ((Asttypes.label Asttypes.loc * Asttypes.mutable_flag *
+   Parsetree.class_field_kind) *
+  Parsetree.attributes) = let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 44670 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 44678 "parsing/parser.ml"
+          
+        in
+        let _2 = 
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 44684 "parsing/parser.ml"
+         in
+        let _1 = 
+# 3544 "parsing/parser.mly"
+                                                ( Fresh )
+# 44689 "parsing/parser.ml"
+         in
+        
+# 1787 "parsing/parser.mly"
+      ( (_4, _3, Cfk_concrete (_1, _6)), _2 )
+# 44694 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _6;
+          MenhirLib.EngineTypes.startp = _startpos__6_;
+          MenhirLib.EngineTypes.endp = _endpos__6_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _5;
+            MenhirLib.EngineTypes.startp = _startpos__5_;
+            MenhirLib.EngineTypes.endp = _endpos__5_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined2;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _3;
+                MenhirLib.EngineTypes.startp = _startpos__3_;
+                MenhirLib.EngineTypes.endp = _endpos__3_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _6 : (Parsetree.expression) = Obj.magic _6 in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 44747 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _3 : (Asttypes.mutable_flag) = Obj.magic _3 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__6_ in
+        let _v : ((Asttypes.label Asttypes.loc * Asttypes.mutable_flag *
+   Parsetree.class_field_kind) *
+  Parsetree.attributes) = let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 44762 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 44770 "parsing/parser.ml"
+          
+        in
+        let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 44778 "parsing/parser.ml"
+          
+        in
+        let _1 = 
+# 3545 "parsing/parser.mly"
+                                                ( Override )
+# 44784 "parsing/parser.ml"
+         in
+        
+# 1787 "parsing/parser.mly"
+      ( (_4, _3, Cfk_concrete (_1, _6)), _2 )
+# 44789 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.expression) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : (Parsetree.core_type option * Parsetree.core_type option) = Obj.magic _5 in
+        let _1_inlined1 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 44843 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined1 in
+        let _3 : (Asttypes.mutable_flag) = Obj.magic _3 in
+        let _1 : (Parsetree.attributes) = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : ((Asttypes.label Asttypes.loc * Asttypes.mutable_flag *
+   Parsetree.class_field_kind) *
+  Parsetree.attributes) = let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 44857 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 44865 "parsing/parser.ml"
+          
+        in
+        let _startpos__4_ = _startpos__1_inlined1_ in
+        let _2 = 
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 44872 "parsing/parser.ml"
+         in
+        let (_endpos__2_, _startpos__2_) = (_endpos__1_, _startpos__1_) in
+        let _1 = 
+# 3544 "parsing/parser.mly"
+                                                ( Fresh )
+# 44878 "parsing/parser.ml"
+         in
+        let (_endpos__1_, _startpos__1_) = (_endpos__0_, _endpos__0_) in
+        let _endpos = _endpos__7_ in
+        let _symbolstartpos = if _startpos__1_ != _endpos__1_ then
+          _startpos__1_
+        else
+          if _startpos__2_ != _endpos__2_ then
+            _startpos__2_
+          else
+            if _startpos__3_ != _endpos__3_ then
+              _startpos__3_
+            else
+              _startpos__4_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1790 "parsing/parser.mly"
+      ( let e = mkexp_constraint ~loc:_sloc _7 _5 in
+        (_4, _3, Cfk_concrete (_1, e)), _2
+      )
+# 44898 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _7;
+          MenhirLib.EngineTypes.startp = _startpos__7_;
+          MenhirLib.EngineTypes.endp = _endpos__7_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _6;
+            MenhirLib.EngineTypes.startp = _startpos__6_;
+            MenhirLib.EngineTypes.endp = _endpos__6_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _3;
+                  MenhirLib.EngineTypes.startp = _startpos__3_;
+                  MenhirLib.EngineTypes.endp = _endpos__3_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = _1_inlined1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _7 : (Parsetree.expression) = Obj.magic _7 in
+        let _6 : unit = Obj.magic _6 in
+        let _5 : (Parsetree.core_type option * Parsetree.core_type option) = Obj.magic _5 in
+        let _1_inlined2 : (
+# 620 "parsing/parser.mly"
+       (string)
+# 44958 "parsing/parser.ml"
+        ) = Obj.magic _1_inlined2 in
+        let _3 : (Asttypes.mutable_flag) = Obj.magic _3 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__7_ in
+        let _v : ((Asttypes.label Asttypes.loc * Asttypes.mutable_flag *
+   Parsetree.class_field_kind) *
+  Parsetree.attributes) = let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _1 = 
+# 3320 "parsing/parser.mly"
+                                                ( _1 )
+# 44973 "parsing/parser.ml"
+           in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 44981 "parsing/parser.ml"
+          
+        in
+        let _startpos__4_ = _startpos__1_inlined2_ in
+        let _2 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 44990 "parsing/parser.ml"
+          
+        in
+        let (_endpos__2_, _startpos__2_) = (_endpos__1_inlined1_, _startpos__1_inlined1_) in
+        let _1 = 
+# 3545 "parsing/parser.mly"
+                                                ( Override )
+# 44997 "parsing/parser.ml"
+         in
+        let _endpos = _endpos__7_ in
+        let _symbolstartpos = if _startpos__1_ != _endpos__1_ then
+          _startpos__1_
+        else
+          if _startpos__2_ != _endpos__2_ then
+            _startpos__2_
+          else
+            if _startpos__3_ != _endpos__3_ then
+              _startpos__3_
+            else
+              _startpos__4_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 1790 "parsing/parser.mly"
+      ( let e = mkexp_constraint ~loc:_sloc _7 _5 in
+        (_4, _3, Cfk_concrete (_1, e)), _2
+      )
+# 45016 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined3;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined3_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined3_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = ty;
+            MenhirLib.EngineTypes.startp = _startpos_ty_;
+            MenhirLib.EngineTypes.endp = _endpos_ty_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _5;
+              MenhirLib.EngineTypes.startp = _startpos__5_;
+              MenhirLib.EngineTypes.endp = _endpos__5_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined2;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _1_inlined1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _;
+                    MenhirLib.EngineTypes.semv = ext;
+                    MenhirLib.EngineTypes.startp = _startpos_ext_;
+                    MenhirLib.EngineTypes.endp = _endpos_ext_;
+                    MenhirLib.EngineTypes.next = {
+                      MenhirLib.EngineTypes.state = _menhir_s;
+                      MenhirLib.EngineTypes.semv = _1;
+                      MenhirLib.EngineTypes.startp = _startpos__1_;
+                      MenhirLib.EngineTypes.endp = _endpos__1_;
+                      MenhirLib.EngineTypes.next = _menhir_stack;
+                    };
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in
+        let ty : (Parsetree.core_type) = Obj.magic ty in
+        let _5 : unit = Obj.magic _5 in
+        let _1_inlined2 : (string) = Obj.magic _1_inlined2 in
+        let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in
+        let ext : (string Asttypes.loc option) = Obj.magic ext in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined3_ in
+        let _v : (Parsetree.value_description * string Asttypes.loc option) = let attrs2 =
+          let _1 = _1_inlined3 in
+          
+# 3638 "parsing/parser.mly"
+    ( _1 )
+# 45085 "parsing/parser.ml"
+          
+        in
+        let _endpos_attrs2_ = _endpos__1_inlined3_ in
+        let id =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 45097 "parsing/parser.ml"
+          
+        in
+        let attrs1 =
+          let _1 = _1_inlined1 in
+          
+# 3642 "parsing/parser.mly"
+    ( _1 )
+# 45105 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos_attrs2_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 2714 "parsing/parser.mly"
+    ( let attrs = attrs1 @ attrs2 in
+      let loc = make_loc _sloc in
+      let docs = symbol_docs _sloc in
+      Val.mk id ty ~attrs ~loc ~docs,
+      ext )
+# 45118 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let _menhir_s = _menhir_env.MenhirLib.EngineTypes.current in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _endpos = _startpos in
+        let _v : (Asttypes.virtual_flag) = 
+# 3505 "parsing/parser.mly"
+                                                ( Concrete )
+# 45136 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.virtual_flag) = 
+# 3506 "parsing/parser.mly"
+                                                ( Virtual )
+# 45161 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.mutable_flag) = 
+# 3529 "parsing/parser.mly"
+            ( Immutable )
+# 45186 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Asttypes.mutable_flag) = 
+# 3530 "parsing/parser.mly"
+                    ( Mutable )
+# 45218 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Asttypes.mutable_flag) = 
+# 3531 "parsing/parser.mly"
+                    ( Mutable )
+# 45250 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.private_flag) = 
+# 3536 "parsing/parser.mly"
+            ( Public )
+# 45275 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Asttypes.private_flag) = 
+# 3537 "parsing/parser.mly"
+                    ( Private )
+# 45307 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Asttypes.private_flag) = 
+# 3538 "parsing/parser.mly"
+                    ( Private )
+# 45339 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = xs;
+          MenhirLib.EngineTypes.startp = _startpos_xs_;
+          MenhirLib.EngineTypes.endp = _endpos_xs_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _1_inlined2;
+            MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+            MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _4;
+              MenhirLib.EngineTypes.startp = _startpos__4_;
+              MenhirLib.EngineTypes.endp = _endpos__4_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _1_inlined1;
+                MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _;
+                  MenhirLib.EngineTypes.semv = _2;
+                  MenhirLib.EngineTypes.startp = _startpos__2_;
+                  MenhirLib.EngineTypes.endp = _endpos__2_;
+                  MenhirLib.EngineTypes.next = {
+                    MenhirLib.EngineTypes.state = _menhir_s;
+                    MenhirLib.EngineTypes.semv = _1;
+                    MenhirLib.EngineTypes.startp = _startpos__1_;
+                    MenhirLib.EngineTypes.endp = _endpos__1_;
+                    MenhirLib.EngineTypes.next = _menhir_stack;
+                  };
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let xs : ((Parsetree.core_type * Parsetree.core_type * Ast_helper.loc) list) = Obj.magic xs in
+        let _1_inlined2 : (Parsetree.core_type) = Obj.magic _1_inlined2 in
+        let _4 : (Asttypes.private_flag) = Obj.magic _4 in
+        let _1_inlined1 : (Longident.t) = Obj.magic _1_inlined1 in
+        let _2 : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos_xs_ in
+        let _v : (Parsetree.with_constraint) = let _6 =
+          let _1 =
+            let xs = 
+# 253 "menhir/standard.mly"
+    ( List.rev xs )
+# 45401 "parsing/parser.ml"
+             in
+            
+# 854 "parsing/parser.mly"
+    ( xs )
+# 45406 "parsing/parser.ml"
+            
+          in
+          
+# 2814 "parsing/parser.mly"
+    ( _1 )
+# 45412 "parsing/parser.ml"
+          
+        in
+        let _endpos__6_ = _endpos_xs_ in
+        let _5 =
+          let _1 = _1_inlined2 in
+          
+# 3116 "parsing/parser.mly"
+    ( _1 )
+# 45421 "parsing/parser.ml"
+          
+        in
+        let _3 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 45432 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__6_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3039 "parsing/parser.mly"
+      ( let lident = loc_last _3 in
+        Pwith_type
+          (_3,
+           (Type.mk lident
+              ~params:_2
+              ~cstrs:_6
+              ~manifest:_5
+              ~priv:_4
+              ~loc:(make_loc _sloc))) )
+# 45449 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _4;
+            MenhirLib.EngineTypes.startp = _startpos__4_;
+            MenhirLib.EngineTypes.endp = _endpos__4_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _;
+                MenhirLib.EngineTypes.semv = _2;
+                MenhirLib.EngineTypes.startp = _startpos__2_;
+                MenhirLib.EngineTypes.endp = _endpos__2_;
+                MenhirLib.EngineTypes.next = {
+                  MenhirLib.EngineTypes.state = _menhir_s;
+                  MenhirLib.EngineTypes.semv = _1;
+                  MenhirLib.EngineTypes.startp = _startpos__1_;
+                  MenhirLib.EngineTypes.endp = _endpos__1_;
+                  MenhirLib.EngineTypes.next = _menhir_stack;
+                };
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Parsetree.core_type) = Obj.magic _1_inlined2 in
+        let _4 : unit = Obj.magic _4 in
+        let _1_inlined1 : (Longident.t) = Obj.magic _1_inlined1 in
+        let _2 : ((Parsetree.core_type * Asttypes.variance) list) = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.with_constraint) = let _5 =
+          let _1 = _1_inlined2 in
+          
+# 3116 "parsing/parser.mly"
+    ( _1 )
+# 45504 "parsing/parser.ml"
+          
+        in
+        let _endpos__5_ = _endpos__1_inlined2_ in
+        let _3 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 45516 "parsing/parser.ml"
+          
+        in
+        let _endpos = _endpos__5_ in
+        let _symbolstartpos = _startpos__1_ in
+        let _sloc = (_symbolstartpos, _endpos) in
+        
+# 3052 "parsing/parser.mly"
+      ( let lident = loc_last _3 in
+        Pwith_typesubst
+         (_3,
+           (Type.mk lident
+              ~params:_2
+              ~manifest:_5
+              ~loc:(make_loc _sloc))) )
+# 45531 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Longident.t) = Obj.magic _1_inlined2 in
+        let _3 : unit = Obj.magic _3 in
+        let _1_inlined1 : (Longident.t) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.with_constraint) = let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 45582 "parsing/parser.ml"
+          
+        in
+        let _2 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 45593 "parsing/parser.ml"
+          
+        in
+        
+# 3060 "parsing/parser.mly"
+      ( Pwith_module (_2, _4) )
+# 45599 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _1_inlined2;
+          MenhirLib.EngineTypes.startp = _startpos__1_inlined2_;
+          MenhirLib.EngineTypes.endp = _endpos__1_inlined2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _;
+            MenhirLib.EngineTypes.semv = _3;
+            MenhirLib.EngineTypes.startp = _startpos__3_;
+            MenhirLib.EngineTypes.endp = _endpos__3_;
+            MenhirLib.EngineTypes.next = {
+              MenhirLib.EngineTypes.state = _;
+              MenhirLib.EngineTypes.semv = _1_inlined1;
+              MenhirLib.EngineTypes.startp = _startpos__1_inlined1_;
+              MenhirLib.EngineTypes.endp = _endpos__1_inlined1_;
+              MenhirLib.EngineTypes.next = {
+                MenhirLib.EngineTypes.state = _menhir_s;
+                MenhirLib.EngineTypes.semv = _1;
+                MenhirLib.EngineTypes.startp = _startpos__1_;
+                MenhirLib.EngineTypes.endp = _endpos__1_;
+                MenhirLib.EngineTypes.next = _menhir_stack;
+              };
+            };
+          };
+        } = _menhir_stack in
+        let _1_inlined2 : (Longident.t) = Obj.magic _1_inlined2 in
+        let _3 : unit = Obj.magic _3 in
+        let _1_inlined1 : (Longident.t) = Obj.magic _1_inlined1 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_inlined2_ in
+        let _v : (Parsetree.with_constraint) = let _4 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 45650 "parsing/parser.ml"
+          
+        in
+        let _2 =
+          let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in
+          let _endpos = _endpos__1_ in
+          let _symbolstartpos = _startpos__1_ in
+          let _sloc = (_symbolstartpos, _endpos) in
+          
+# 770 "parsing/parser.mly"
+    ( mkrhs _1 _sloc )
+# 45661 "parsing/parser.ml"
+          
+        in
+        
+# 3062 "parsing/parser.mly"
+      ( Pwith_modsubst (_2, _4) )
+# 45667 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = _1;
+          MenhirLib.EngineTypes.startp = _startpos__1_;
+          MenhirLib.EngineTypes.endp = _endpos__1_;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        } = _menhir_stack in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__1_ in
+        let _v : (Asttypes.private_flag) = 
+# 3065 "parsing/parser.mly"
+                   ( Public )
+# 45692 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+      (fun _menhir_env ->
+        let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in
+        let {
+          MenhirLib.EngineTypes.state = _;
+          MenhirLib.EngineTypes.semv = _2;
+          MenhirLib.EngineTypes.startp = _startpos__2_;
+          MenhirLib.EngineTypes.endp = _endpos__2_;
+          MenhirLib.EngineTypes.next = {
+            MenhirLib.EngineTypes.state = _menhir_s;
+            MenhirLib.EngineTypes.semv = _1;
+            MenhirLib.EngineTypes.startp = _startpos__1_;
+            MenhirLib.EngineTypes.endp = _endpos__1_;
+            MenhirLib.EngineTypes.next = _menhir_stack;
+          };
+        } = _menhir_stack in
+        let _2 : unit = Obj.magic _2 in
+        let _1 : unit = Obj.magic _1 in
+        let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in
+        let _startpos = _startpos__1_ in
+        let _endpos = _endpos__2_ in
+        let _v : (Asttypes.private_flag) = 
+# 3066 "parsing/parser.mly"
+                   ( Private )
+# 45724 "parsing/parser.ml"
+         in
+        {
+          MenhirLib.EngineTypes.state = _menhir_s;
+          MenhirLib.EngineTypes.semv = Obj.repr _v;
+          MenhirLib.EngineTypes.startp = _startpos;
+          MenhirLib.EngineTypes.endp = _endpos;
+          MenhirLib.EngineTypes.next = _menhir_stack;
+        });
+    |]
+  
+  and trace =
+    None
+  
+end
+
+module MenhirInterpreter = struct
+  
+  module ET = MenhirLib.TableInterpreter.MakeEngineTable (Tables)
+  
+  module TI = MenhirLib.Engine.Make (ET)
+  
+  include TI
+  
+end
+
+let use_file =
+  fun lexer lexbuf ->
+    (Obj.magic (MenhirInterpreter.entry 1758 lexer lexbuf) : (
+# 752 "parsing/parser.mly"
+      (Parsetree.toplevel_phrase list)
+# 45755 "parsing/parser.ml"
+    ))
+
+and toplevel_phrase =
+  fun lexer lexbuf ->
+    (Obj.magic (MenhirInterpreter.entry 1737 lexer lexbuf) : (
+# 750 "parsing/parser.mly"
+      (Parsetree.toplevel_phrase)
+# 45763 "parsing/parser.ml"
+    ))
+
+and parse_pattern =
+  fun lexer lexbuf ->
+    (Obj.magic (MenhirInterpreter.entry 1733 lexer lexbuf) : (
+# 758 "parsing/parser.mly"
+      (Parsetree.pattern)
+# 45771 "parsing/parser.ml"
+    ))
+
+and parse_expression =
+  fun lexer lexbuf ->
+    (Obj.magic (MenhirInterpreter.entry 1729 lexer lexbuf) : (
+# 756 "parsing/parser.mly"
+      (Parsetree.expression)
+# 45779 "parsing/parser.ml"
+    ))
+
+and parse_core_type =
+  fun lexer lexbuf ->
+    (Obj.magic (MenhirInterpreter.entry 1725 lexer lexbuf) : (
+# 754 "parsing/parser.mly"
+      (Parsetree.core_type)
+# 45787 "parsing/parser.ml"
+    ))
+
+and interface =
+  fun lexer lexbuf ->
+    (Obj.magic (MenhirInterpreter.entry 1721 lexer lexbuf) : (
+# 748 "parsing/parser.mly"
+      (Parsetree.signature)
+# 45795 "parsing/parser.ml"
+    ))
+
+and implementation =
+  fun lexer lexbuf ->
+    (Obj.magic (MenhirInterpreter.entry 0 lexer lexbuf) : (
+# 746 "parsing/parser.mly"
+      (Parsetree.structure)
+# 45803 "parsing/parser.ml"
+    ))
+
+module Incremental = struct
+  
+  let use_file =
+    fun initial_position ->
+      (Obj.magic (MenhirInterpreter.start 1758 initial_position) : (
+# 752 "parsing/parser.mly"
+      (Parsetree.toplevel_phrase list)
+# 45813 "parsing/parser.ml"
+      ) MenhirInterpreter.checkpoint)
+  
+  and toplevel_phrase =
+    fun initial_position ->
+      (Obj.magic (MenhirInterpreter.start 1737 initial_position) : (
+# 750 "parsing/parser.mly"
+      (Parsetree.toplevel_phrase)
+# 45821 "parsing/parser.ml"
+      ) MenhirInterpreter.checkpoint)
+  
+  and parse_pattern =
+    fun initial_position ->
+      (Obj.magic (MenhirInterpreter.start 1733 initial_position) : (
+# 758 "parsing/parser.mly"
+      (Parsetree.pattern)
+# 45829 "parsing/parser.ml"
+      ) MenhirInterpreter.checkpoint)
+  
+  and parse_expression =
+    fun initial_position ->
+      (Obj.magic (MenhirInterpreter.start 1729 initial_position) : (
+# 756 "parsing/parser.mly"
+      (Parsetree.expression)
+# 45837 "parsing/parser.ml"
+      ) MenhirInterpreter.checkpoint)
+  
+  and parse_core_type =
+    fun initial_position ->
+      (Obj.magic (MenhirInterpreter.start 1725 initial_position) : (
+# 754 "parsing/parser.mly"
+      (Parsetree.core_type)
+# 45845 "parsing/parser.ml"
+      ) MenhirInterpreter.checkpoint)
+  
+  and interface =
+    fun initial_position ->
+      (Obj.magic (MenhirInterpreter.start 1721 initial_position) : (
+# 748 "parsing/parser.mly"
+      (Parsetree.signature)
+# 45853 "parsing/parser.ml"
+      ) MenhirInterpreter.checkpoint)
+  
+  and implementation =
+    fun initial_position ->
+      (Obj.magic (MenhirInterpreter.start 0 initial_position) : (
+# 746 "parsing/parser.mly"
+      (Parsetree.structure)
+# 45861 "parsing/parser.ml"
+      ) MenhirInterpreter.checkpoint)
+  
+end
+
+# 3668 "parsing/parser.mly"
+  
+
+# 45869 "parsing/parser.ml"
+
+# 269 "menhir/standard.mly"
+  
+
+# 45874 "parsing/parser.ml"
diff --git a/boot/menhir/parser.mli b/boot/menhir/parser.mli
new file mode 100644
index 00000000..ae740328
--- /dev/null
+++ b/boot/menhir/parser.mli
@@ -0,0 +1,174 @@
+
+(* The type of tokens. *)
+
+type token = 
+  | WITH
+  | WHILE
+  | WHEN
+  | VIRTUAL
+  | VAL
+  | UNDERSCORE
+  | UIDENT of (string)
+  | TYPE
+  | TRY
+  | TRUE
+  | TO
+  | TILDE
+  | THEN
+  | STRUCT
+  | STRING of (string * string option)
+  | STAR
+  | SIG
+  | SEMISEMI
+  | SEMI
+  | RPAREN
+  | REC
+  | RBRACKET
+  | RBRACE
+  | QUOTE
+  | QUESTION
+  | PRIVATE
+  | PREFIXOP of (string)
+  | PLUSEQ
+  | PLUSDOT
+  | PLUS
+  | PERCENT
+  | OR
+  | OPTLABEL of (string)
+  | OPEN
+  | OF
+  | OBJECT
+  | NONREC
+  | NEW
+  | MUTABLE
+  | MODULE
+  | MINUSGREATER
+  | MINUSDOT
+  | MINUS
+  | METHOD
+  | MATCH
+  | LPAREN
+  | LIDENT of (string)
+  | LETOP of (string)
+  | LET
+  | LESSMINUS
+  | LESS
+  | LBRACKETPERCENTPERCENT
+  | LBRACKETPERCENT
+  | LBRACKETLESS
+  | LBRACKETGREATER
+  | LBRACKETBAR
+  | LBRACKETATATAT
+  | LBRACKETATAT
+  | LBRACKETAT
+  | LBRACKET
+  | LBRACELESS
+  | LBRACE
+  | LAZY
+  | LABEL of (string)
+  | INT of (string * char option)
+  | INITIALIZER
+  | INHERIT
+  | INFIXOP4 of (string)
+  | INFIXOP3 of (string)
+  | INFIXOP2 of (string)
+  | INFIXOP1 of (string)
+  | INFIXOP0 of (string)
+  | INCLUDE
+  | IN
+  | IF
+  | HASHOP of (string)
+  | HASH
+  | GREATERRBRACKET
+  | GREATERRBRACE
+  | GREATER
+  | FUNCTOR
+  | FUNCTION
+  | FUN
+  | FOR
+  | FLOAT of (string * char option)
+  | FALSE
+  | EXTERNAL
+  | EXCEPTION
+  | EQUAL
+  | EOL
+  | EOF
+  | END
+  | ELSE
+  | DOWNTO
+  | DOTOP of (string)
+  | DOTDOT
+  | DOT
+  | DONE
+  | DOCSTRING of (Docstrings.docstring)
+  | DO
+  | CONSTRAINT
+  | COMMENT of (string * Location.t)
+  | COMMA
+  | COLONGREATER
+  | COLONEQUAL
+  | COLONCOLON
+  | COLON
+  | CLASS
+  | CHAR of (char)
+  | BEGIN
+  | BARRBRACKET
+  | BARBAR
+  | BAR
+  | BANG
+  | BACKQUOTE
+  | ASSERT
+  | AS
+  | ANDOP of (string)
+  | AND
+  | AMPERSAND
+  | AMPERAMPER
+
+(* This exception is raised by the monolithic API functions. *)
+
+exception Error
+
+(* The monolithic API. *)
+
+val use_file: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.toplevel_phrase list)
+
+val toplevel_phrase: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.toplevel_phrase)
+
+val parse_pattern: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.pattern)
+
+val parse_expression: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.expression)
+
+val parse_core_type: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.core_type)
+
+val interface: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.signature)
+
+val implementation: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.structure)
+
+module MenhirInterpreter : sig
+  
+  (* The incremental API. *)
+  
+  include MenhirLib.IncrementalEngine.INCREMENTAL_ENGINE
+    with type token = token
+  
+end
+
+(* The entry point(s) to the incremental API. *)
+
+module Incremental : sig
+  
+  val use_file: Lexing.position -> (Parsetree.toplevel_phrase list) MenhirInterpreter.checkpoint
+  
+  val toplevel_phrase: Lexing.position -> (Parsetree.toplevel_phrase) MenhirInterpreter.checkpoint
+  
+  val parse_pattern: Lexing.position -> (Parsetree.pattern) MenhirInterpreter.checkpoint
+  
+  val parse_expression: Lexing.position -> (Parsetree.expression) MenhirInterpreter.checkpoint
+  
+  val parse_core_type: Lexing.position -> (Parsetree.core_type) MenhirInterpreter.checkpoint
+  
+  val interface: Lexing.position -> (Parsetree.signature) MenhirInterpreter.checkpoint
+  
+  val implementation: Lexing.position -> (Parsetree.structure) MenhirInterpreter.checkpoint
+  
+end
diff --git a/boot/ocamlc b/boot/ocamlc
index 4529ffc3bf81e7784ab0cb4fc00ee54038b7f600..2bc0cd94412a16fa46e5b47bef3c609aed3a2ceb 100755
GIT binary patch
literal 2623328
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
497pW^eg?SHVp?Otsd)G!PIl?XkJfxyZ#=yt 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 oe(JMn3Y43IuT3CNrWUs; zP^Q)A_8xOeYkZRFj`;`K%ZBleA*Vj?PJ35S|HkwEoQy9ar#gnCwl~tQuW4Sek1aS= z_{c8&Iv)zX@=Yzq;^I!bGe%h_X6&_Q3KTMp|A~O!vqPUR`o{MKcLj8*>oa?Rd@>Dda{ZQNRMJQ*mh*}OLpldro%O!xrhLY~+!R`p?A(_FtM^Tz_^ zH1ip>uo(+}3cEH2O&uu)2!>OS8K5}C0*1*{Pfntmtb{d}oWmt9)#xEvMv3La~x% z-BQ-;GZq>z{M{?uT}h^#6dN`zbEI}T`^}|}@s)kJ*$R56u>E{+GEiE}hid})^!01< ziJT+B(SSWlV>+I3yo_M?*e9d?-D%S+*20rrkx%nHJV;@eM-U*WNY-sbtc;|a2@bC>u@|))QDYfFc+BHYgJ{sUisjTt7 zIg#-Z-s8vqvxYt&+yUjRXNdf*K>x0Ypnp8E}?Sf}W-RUFmsK*!2fDyB%KoBp zHs|+v-MnUnf<14#4r9`6C4Yae;?g_FOq); z1AdJ*@E34szqWXY8Ib>vBENFjMz6JG>hoI;u|Z#3F0K382v>YN87Qs!>0FBWKaM{8 z$FFN}x#VCcZcb&bGuyk#v!&ou+dI`+av`tj5R+X2F1~rTt$&k;K0o{(-F zjCV%57x-aAdF$O_;+Uhbns@%_JRdlJQ=p8pH|G90KUtJQ&)!vQ`@O!t;~UsF+DspN z&DqQUaSyJn!J{~f4<6()S?cDX?;G5StsKy{hwPsB_NR;~e5Pac**G6-f6ugf3KY*moZ)5)lxg+3 zEfWuwNheqf#{zr(+kxiUlheN;V2grVyzy17bgcQkKVz>9_<%2bd|UXqDYZRQpxhPI z7J7l)Z=2hd+uGbW1Z3iY&0~#+t}V~@e0iYsUJ!3Kn)|%K`-i;ev;XJ)-qc&c1A+3< z+trTq&aP7VYO$`4m!-{SaWjWYbGTr?+Bm(Vj6LZe2-tZ%Fh8#0hnVdSzGR3Q->aKE z{?RSJ-3`|SQ=pjFU+SMSrcA5Pi?#jiZGMnT*Ays+1M}7SNab5^{}d>dCpT)NGv?fs z8}{S3?*&uZ%8B6m;IXzx46dZ_O7p#gN1oXENcozwN5RwXpyx^M0Io)mFaOkXRBatT z<&B(@Yxox1rzWq=pAVcjeDc3~tm|4i;oWh}eQOna$9Zzdt=(x}IJ@#)UMr^pytMAS zA$eDVeD9j_?Y_=cbm0zhXPgeyIOyHr?yv3T$Qm5E59J)&ae2?&9{JaX>Myta;`jJ> ziOt~yZ{^iq1!sO%eIWH#@X7!`Y{NU7$}3wchi!7O^2RvTN3yJ|t|iCIcb;{9{&jrh z;oKEui$}Tf&iul_vx^P427fv*|I)ek4Egr?nL2)b!AECEj_l-%+ui+c4Zh?B{q*AA zGp>B?8`|bOe%;WfPpmqpkNdGt-`IDS^l@$d-bKIp)Oo&->)Ac_o$2<|eAxMDOs-Tn zevc$}S1YsY9;xi+#j+-EIX33msAnfm#{KK$jq_I{`!l1+dE66>`p3OH*;0PSn*Ooh z_B$(kC%NQ564~Cn3o_f@sm_v1aKJXnoybp}; zJXv<(YefEdSMomP`MEXs{a&Z%`K`hD4wdfe?y{$APNhwb=k>8b@%M(Tac6m#xFI0V z`$Kh_b3g45JTE-Yy=!Rio!ex4M;Y%KypVZUpwyP7{r2&Pz9~>}|Syd_Oeeo9ne?1y-W4o(mHuUHeFMou*tnn23yEAroGfP%0HiZx~k*Y zyyvF}yYX}&zyFwfCYF`UrauUj>S%55Hv{@`&*rhl zW7oERMaKMl=p4n>*H6w+eQo`T^Vl~Gb2#_)xtw*@r$FKF-r!2}*0O<)TLQMxZ6DvS z4JqW{1wYk=L+8+Yk9mDx_gRx`VKp|TR_+bRa$k67-wepNw*01f!S+cfWmjkcPf0%a##$)RTolxg*OvBt}x0FO%JDi>}HoX^_sY>O9p zY+<|e!>{@=#^X%Jt+k&WjkEl`IZ!LT@5(=$=xM(--ljmAR-YGZc|$jQx?hapYGZ{@ z{<>r6=VSS3p5x$3U`N;RvG&LtxLiE=L9cyRvz~1669do0@618GDK!~Wpm=ti3&`f* zk>KduPPMwH=u+x$>)yA=GiUEc@EiI0wsSxy-E5`%?K|ks)CIZa@y9X-;)AadA3gV9 zKaA7O{@sBhx9FE!_Oe&}?g+Mmy)*FeNb*#!k+-ZH!;_g~%ewr%GvjQOgY>dV9?uQgvUXBQi$K#>ddKd6(!4synLv+>cKaW=7Kr*n>*p80k0!$o-> zV>zB7I;?v%yzz-`WVlOk#@=Nthzt-&JFD}TDGuDVF8O9zAlrf+9((j$RNA?G|2hD-;`>n6c zIC&ev@_rg+iW|P5chj-7_XNK%yc3zbKA>xq$9H#~^|<7_e%t&a`|jZ0pzo<8Kb|L^ zjkw}t&o-Iog8Gr>1zwze@lZy8=+jr%2E0_ieK@A;L~v;CR}Y=!zBo|m77xWoKy2yWAXg-8#8yH@xuOH-{Q0M|KmC1)gBdgLIpy8* zyB70X8B_4d4`uv53_tb<_WrZQ-rAU{6^CrW13SKZvG#_Hja-Q9sB`>#r=!mAS;(PN zE-2&v|G0+xt~;HzazYH$jf3_SD0sGhj5S}ZITmP-zc=I_ALA>AF9?)TA3w*w*pewf z-xAoz54t^L#6v8nKw;P8gMC5w{Yu*Qk&RQ&x$%yh(pS2dZ0E~5IdfxhFc4Q<81wxO z@{L_i*161IP9L7i;qJ8c*-F1Q9dsU_`)upq(={i){Iz$dnACT+kPB0wOsmiBy<}KJ zj<#Yi&N|Mfdje~;mD2%RP6ar=Dfr$w4{;}#apulY4g{L~Vn6u`UF0a{js@1OyC*g> zKH8M-Dh~F^GxG}DnnRVzxBoWezxXsa8;kmet8w42UFE)!6F%{+oS7r{R3MkV8+vZ; zo%_y8-+P*C*6k0bK*=k}YW<{>GOa!@zE3|P{q7}~4dZj#JbT=8iuWIP)<2))HvX(z zevQ1~y?N9a{nLRLzKHp9UxqHp6*h?te)+aM`{m}k%<;iIUifZK+{#0JwT3MH@!U@7 zE7R)pB2WD9-gP{g$CEh)Pa_xdgb(;&Pjf~7eb-fTV*gffJ}9rA>7%U6{cfDx`jSAA zQ{_=@?k@+sgXZLzf7WzQzei#ZJAA)VdmT;;<9rnt&!KXe<^`_BnT{z?`VKU$dKbUG zD96^4aM?Y4y3yFI{&A&0TuP8}9(QYrb4Pn6^9MU#z(U_GJ8AV7-0g8Ax|! zJHOaY*YUu*-N7qz4%kD#`+nWMz$bf~gW}(_aJl*^^E!9VT>*X0;S?x1oitL|&JKk> z9I|N&l;v7JFa2EF$+l-*2J9Q>Yv1yITIwF{^feq?*lOR|K*4w8$qswE=Ek%S2K$4h zY_fU=%iGe=Gg(9C$WQruXV$Lc@0RFU2XS1Eb<@>F3`=zPNb-&kuS21vxSUcMD_pibp=bo&MKupzFic9V6IT0fqEa9$L zj_KoXnGf_Te0K)%!vEUBHg}NoT>ZH9PCowIe0jB$T{-mblxvka`t;naUt-^yF>A)0 zn9^64cC7R9y6vSapYT{amcHSHAJ$BPvXt+A>amFBvm<8&8^`|G9{s-B`{YdIJt=6c z`D*X--$U|MJk?i{{b*x6-iyn7a-7rVYi+&U-PSmZW$y|8@ zvhAH}elBxs^hqw32VaAV(f;6pKyjy7zm#EJ&vVaVhE}|gV-H@)U;1!=#tQl199|zh zC-{)y-oU*3QLUT`$nuQ!KH%=z2>S0_*`svbGCuaw<$b67?fKZ;tM2m02g;eC`K*TJ zo&$?Lr{{HaTkpQ3YrNm|-Rq<7AI;An>2}r?HjcXZ_eF~}^^XqxD;;A88RIiXzwf?c zSpEEc<}AC<4fe`u>y*m9S}x!52bXf${mYpBwRs)>pBH@JwcB|!evN2O;paPtG4Gv zAn(a5-}}=R2YR0xD5JgR$Py>}ra+lipWFKOrrkB{`j)DPwjH(uVg?g;4H6S!M(+1eesKbQjL&Y&FQ5odj$v%fJQ zW8Y%_x#`o*R7}q5?UzR#eiDTEftNCu7ayno~hpcfMSi+}@bRy9 z;Pgo5jt2ZM2khGlmNw#Ixt>jQ)?Rkl&ld3;ZI&ms`Np&l2J39@8GEEWk*|z8%hR-) z*_odo+<_n4@Zj$`zi(=OzCK7wT=<&Q zD~4h*#;bN^_!9ovuZ(iW@8$1w5AgTafPeDjBLh0?>+{p@Gs{}O{OIh9f18U(XZd8H z*jHQR(q^FGzUNgV{^p{;YwjP9Uj8cI@y(b1KknrW&gI5WJ2M=J`?Hcg^y;=5rT&Ubm3>%EkN#FXmsE{`u&{`)34l@y8RdDfRCL%ekKz=Gf|7 zvPBG^w$OE7-sQb-c;A+9UH9q#bK6g^Z5{iZ-`oECqSlWxfB1h~%F*l6x5m42Ie5Q$ zY~L{U#ChMy-P^+5*#D{Y<=Gg6pa0!U^?hIZ^m#s1-`CA!o(q*H-oFxgsV*6N-nTq_ z>_aj}mhzH?zGpA`zn5QvU-JB;^Vq2S?paT5{I;wa{d#Nq&Psou$ei*=f=MGqoWyZ; zrV?juXKIx5S+nlyxoy@{TeAFduUpvijD;;f^E;Q?_C4v3dH=cTKPhsmKwl5s07Gi{n2}ANTG5`Si*Bu%O&p z_h+NO{9T(hqmK7T|4CWn{keP9Vqg!ue(XP8Iha)9YREV1D_^TDHpt>+GvtPs+S8&;OB+j}0FgTCMj!);0ER z1mFLw+xz@n#@t5*=GgZ+nWNJkTSQPywgmwT+0PipU+wfTE9=kC5YkbgfNfu4gOKzYi6V3hT>S#RCX zWS#n7r)G<@qyMw>_|K*0r|~BR<(>~;l>b4QJ#3JJ&q$v-V_k>qpUf})m4n`gAD8iR z_P2-mu6su2`Pg;%cyrc`KHQnUH8@j$QcymgHpnceZ2q-;F+oRThZlQ4F|e1Oug#iK z&x7-x`uU;hKPl_%`-^k^DXGo#_kaGoi~fG{JWlsJ=JD!2oUzKN?%T3v)O~Q#|AT+K z?epvAy`MJ7|BlR!zP)y_hHrmiSkv?5{8j(6GJjwC;v}D56Uc|3PaZ7u>BSjm>$vXU zTxQ+q*U$dqMO*2{&zEM*n&W|dQr@1s)qBn_L@wW~HFt8@&yPMM?8m7btQ`0Dp7}m_ zuX+CCQr`YG?MAzy7?jSF@8(1y6Ss`t(H_`YP` z*EniF-@G}nUvXzwR&_crjr%wM+_ud<-{aiVGRH38uaJArvo;$++n70RYw6N{QXp5g z>m&X8@|3N((SPFHw@%-4&0{z;_jl%cwi4gZ=dUbHrGEm z*FQejKQ-4sKi9vK8n@!i#=jc>Kl-0N^w5_DPxzjTUnhM@c)*=lDUY9daej^M4u1a! zE?x5@>C5@X*qU!$toh>fap?X$8+Zn71>~+9+n;gr>;e7Ju8)j7y!^v}U1E58wu4N2 z%{#;DZ<*`&O>Moq+ZM)k4>bZ||V`BM+HDe!;G5YbTz9H!PfBVlb`f9FcW_cH1H}5?-*N5l&&2!zH z_WeF`8f)?R7Fj_>cuIF8&^_XgyC=v?zz|Lf*j?zjt#^}N?+=l$k@ zEXDk<2QLWzLmWMu`kMtf#n1aaiGC!Xz^@T_8T(h;&bA9bFQVhf<6gA-I`~y-zdHl( zwa>d`+mE*Xyje!;M=R%DwNGw1gL2|S=Jx5-^7G}v;{$7)HEYf+`qtV%?vb0yI955* zj-2NN_MHmoIuRTS+YyKj|IzI#X+$EtHr#_9AfSDnt&sCz5@`fE+?aTcBZ zCkE`Q{p#9zE^TY7`IQaHGH#o?DzTetI^HxdjtEYK$%vb+kE;Nx97<90iP<9-1?`+ z7a3$*_l>h`d+{;_%C!32)`^q$TZ`dR=TkDqFWgOmQm*TB`JGm?7tesa_Pa12nVO8A zE6eODulgg;Lzh82jFdUQAia$v{k|KoL80G5x|E-*218%*$E10p<3Av=#HagZB*h6%$u|{AiQg z`{-=i&Xo0HJKDJH(F~H-9~Icyfo) zQ=7_Bb3#tDtMjAHjn4y_SJjv&f-80$S?OB-TV-za{l!L=gzuk(vje3 zASXeL_$*%bk|`HPxrfu2*SN5L9T#-tO#aZX;nP$cq60wr?eG%_@Xop zW6efu)bawiJ3Z6c+IzBl>bw2WbH(mcfjq*|@_xE~9x{Rizr5_E|0(mHQGd_U`OJ;?K;tjxr$Cuj zpWAs<`{-=$u&ex%`-Xsx=K}s!=2)Ab0;Tydt$LT*L(lGcoPYj*&vJ1q80A@_Pp&;` zAu1 zoudxx@*6TAw`Y z9{hug>#E~ZGB$FD+kOqRj!*OBJAc*!0v9hEbh4%2<8l6L*B{B6`dF^_W}d7k z&$adXPn~OLTHpOa4!%D-aZ@X}fXXXxt(}2UJ~{gG^5y{Vigk3pAo#5~b~g3VT&73V zfgA#I!MSl(s^1t}jfoi;b2l5K=WyUIu1t9drvmft1N`dCpZ^j&^zRPNWug0=4(IH@ zu9?G+x&O9ij-BRydog!=#x{bp0omsQcFH5;Y+>8>UG{{P{d^E(b-@ogvOl0p{&)x0 zzdjJ>%C<-8dOR)HkMA#6;^}t=pYF(F_I?%xDK856{ok{Oo{`IE&vU=KW{%DF{f{+s zjlu7&nUjb1{r;Lcoc7syHti2y^k1^*zi!c&ALIT{TJ-s`7X3f9=!?&|{{0tyXQDZ@E>?g^ZEZFh*0 zU*B0hYi>;&*Yr4}_8$tI>*bxL?~XbVDDt&qazSCcvDVg*-9D}k1WO+1lN)Sj!|vc* zz&1XU!B+G3$~EI>0(UVz?ksxT`(mRs-|kI&GLV7`^JJY5ra&=HpHf~t2b>r7t>eS} zF9+H1SlG$WDNvU7u=i^1;TJg1<$ig`;{ZG_%NIZRnd8687x}GCH!e2<@$np0ZVA{d z4&ovXc&JXff}bUKbQ=52Ku&qy?+uK7cCb63Q=yOE&U^PL#9X|sg^@q@+G9UImNw|u zxB4mm%|o1!PbNS4$4~z86Ss6XXPRrH4Tm%T#K3!xJQBa-0eyUWQ_i8bJ%{G8RPR># z*Y_DQ0X}R6Y=$vrxZsbm`mVp7d)Kbc^tto__iaDgn(R{neZ3!+?fWyQux-rYDgBM0 zaUK1TOKg%ma`Sn??p$)s+wpy7f94u{{EYhXBX{IX^Trut^Sa!zw>o<7u%$Bjz+R}_ zGihJV9q8`mueh)acb+pF@k=f*eag^<7(SLcaChVua-i);TfZ|o@WSYC4mi_S%7H!a zL=H61#OiW6VD4QR@5etz@&3%%*}FT<3-|Vw?toWkZ6W?`Kic}8iNBaP{>~)c>z8MT z^4WoNz3xtU!efvRy%+i{!=KVSg-!pf?}R5lf*ip=xQFC89{X%iKM*LM*-H7XpPlbL zyEnRVG2Tblr!OAo0{7Pw0%iF=)EIg%I~0hS@>s8v_xo0oFFt=xr_bNoF!sgRU3*P@ zJD>VB0Uv>F2LnFg?^OXGajHC8UGMP-bv-Y-o|HX&n1ZJVOFMoxW6C-o<>}}%U;3`V zhwloG1a3K{M_P~X1fRF9X5|Ne z=$5C}u*v(t8-tC2ugf*oTJvdvJEL~CX78><`<~QrXs+A;|FVuL7wm0Z_GWC)fZj=b zd`_U84wgLd-I}9;Jm$aieMcZK$aKE_jQkm?&2I(XQItCax#!Lx+r0HR2F{5beQh8< z;>}KH%sr_lOWWLdkL*wXRRP)c<-xS=2Yb}rPxnsyI^ex}Xsvp1d3dcQf`DeBl{%*!i8ULfv%|?G?nLX?lpRRX4`GGI% z#L_#WzWsk}-hW@(Z0-1aF60`=p?hEo+$nrq^7E98@ry0>%UR+BI|}w0^Z#^UPwy8x z6#=$+T7>lOFr5KNrXWT(@8D$yIue z=={_H<|>blPcV?uvDVxBAG`a_`BP2@3dCOmXfKq>YA2sH9;`h10*xulI!5>ea>5p^Hs6v)peD6griu&Vi_)4@O)=d3ZeFCe??TaRnW5z7OCGb$(h^9y>< z1>+gmlfKgUH}3f1m-XbZVG0zSjCTd@p1Ra?5_TUi#htQCf?4A;&*Vwul;|x=zr0o{}&hi zI~V<@E&4yc_<8q-&Of)N&-r?vxz8VC&cW~HXSGk7`_}we`p!l7eAC<)pT3)!< zIrFvk%jPxYoAX|&zBcHZ&t9zYezKJFtN-ItoB#Tv|Lu#v9rN+&SB`T{9viCjW%K$B zt$bRy)}D@wU2Pi2_btY8WF8kc2lgpAaliZi|Doiwv-43Fr<@ARJt^qB`BT!C7iR*? zP6v4Qo~G~a@w_@8u(9`T@8{zg+YGGhoI6qfT%aw^M}ngPUEn>$j5)R&V;}Br3a*ds z#_92QtX`Med!PGzx%P(3tgT+}kbELvySDPF;OAz*cHD}m`{8%zwtj6?TSMOIxwiI` z0%crh4S#n<`c~>I!L#;*u43JlYbv@gadyAG|j{KDcP}#)=QV;|1)u#(ueH ztow0b&Ki5H`8$jL-=6!s=6SXCa>4rkKIb}_bXl_*@L}B=@wMi219IDc)7-DVo%GlK za`Y*~K63wDpghu;esK0|y^ApN_Y%gXl$)!KX}Nt-_KIEa1G!LHV|<-Od^{_lzy0@{ z`;BM$ZhtfL$~u|l+*xFUyQ=G2k2W+9-S=#0-@RB))R&9(xyt|MOEz?@Iy`snbJz7wqC;P8&i$l~3$lHUPVZ*GU*pEKw*t1% zV=q1WV%a_!_JHTX{-Ac@fgGirX!GZAz%E7ZKR*A_XKsWwUd}LKH9yHcHfel$4XA+jxI0?gdWI^DGa%rIGD12^6x5ETFaKBx$6v99y2{%%F3Sc2AuI%Fp)G~Lw(0f%=Dnpy zuitMpik$@Z`TeeW&iCQE@8@~nZ!|Mn4y;qEeJE{w^9$I4E4K2d?iX#cpVh;i;{D)Y zVE@g5Jir-F9tgbKy1Q-c74j zZ}q$LYkiI1l`$ODI4;X3F{ts9{}CB`Q6MhbcosLD5l5o^dI-VvDg?2TD7}4;)&Kw~tJN7rg7A|n8&{sKGv9Fr_C5I1VeKsBo4#yuh zv$G2n@n~g0zTI*^2u-vfnAK3077<&rhZd|=F7Dt5DhXPEWIR|Drr%$+wn%ZB%)tysrL z=Sv%gXUKkMihb;TPgL!Dw$-5W+ZukBjYs-68!HcRXnxE$dU3d~Uqg?*>|j6n z;(||dTKlZ+0;RR}c=|`0=h<>UFK%oqd7cUUVFTaT=*}3v<78+uR(XLRduM|6fJ}R8 zo=kCO^P%8yKsNBrytSTHe4OvcPNgObPyA`uJ`y9zvsS)nE4UL2rDXEKI{dg_P6x#s z+4`RoyfSdtZoZ>!<~6;c?y6@7pBAtgH}n-p_{0JKjVWzyPp#2r7yHR(*G50)chx?n z9}}~iqL}~p2K9divj14{l+4*rmK>|Rx9{f64ae~!t_r@#d?0UM;4JZ_a;|FJkbg@r zzkY6FE@N_Onq1@S0bg2P(!HwlB}I&;&9P_N9GlIFM;9pg>;nFpYx!^UFH;i^*(K(l zS%BaBgKrGp5&U^@h>#TPW_!pdoP>@^zVA!D7|3;Fbju5|XCJvoGtu^MZTfpMKiuQ_ zH5?=7wq~FHu|fZM)6eu&yXB1>+#ld(Z!o6s_C_9kpV0KZCyM`YpK)h#IBx$_oBjGv z8}y&v^fP^l{qjLh;;Ww32hu(q&?$yvI-k+Vr1P0g-#&32?lUfi!*TmhH2d{GanSFY zex|R;hdN8c{8?>e()p~W&(=C)?LOmmPTFz%Pd5AY*9QGlO+V9DXI$P6$L)V^ zvtR#tgZ`&B{Y*c~hus!-NO+E9?8{-2xll* z?`H4b5V0CO5PV(mSpEH}$hbBa^P&dRx|5CO71*^P|=m zZ+-Wc{guPBY0vk4dgSmzV2%5EB~T7G-zTqUb=l!e$kTc@S#Jzh12%Pm;$BdkP4nwb zJI#r`c}8Hrvw5s<^Qm;ZAC-2jcwrNtUJ(Ha&4dH~SxYxA^;>TEP~6bF5VZD? zSvK1{6X4Z3$1{Je=>nzo*Lv}?hh3{t(8lkXgT9~TU^n0Ssm=ECz5L9wiM%6eX!EDd z0eyany_lAN>|6-kA@#X~Y-=A1=xzPwC;8U%i|t*Yw0>G=j=lVJCd!Y+ewmkKxu8XuC?(uV&I3%M$hRkP`0x1M?Z`uL@vAQ z7?`q^jed4sasJ!0Jv>kTK8K~Jr>vXFxcv6-Jlf97ErGUtcE`x?I*apbe84;1G^ss66C*8_K|oF`aT)@ za@Mcai{=Jc(jQ?9gY&!?}jn;%0v_L@w2Q&4)XBhy)#w$B})4CPsG zU)f+@TW+-NbSHdS59Y|McTZ>C=l1&o``OgC*PHPxZCCvGORm_p@0DWUbE-RL3~X)3 z#l`){e)r#Epp@U*<-2??{dB)LpdUXc19rHp+P_bDclvVXa6fk>HO}m-_uu)n@lM7| zf{%{yjnuCV>Rwt;n~m1^9{)XA^I+=zLCIlf$*H^Ax#HJqpxhH!V?H7#e$J#;9tp}< zW96&$z~(Mc@MFz-K>l^XN}&Ab{&O52*nBX+vpcx>p_}dG4)yT)SU-0%HJikhMmq7Q zuJeswG8Fot{HM>qmAJPS1G0=ANQ0dDX3Wp5xrdFhVK!hV|H^J-3&D$miVa(e=UT^K ze&YpKa%a77TVFnte|z9>RoCZ4a-E+Ve`(q$1J6-DD|ZBRYy@t77*LdrzHA?F%e?JiaT3^M%IeT4j zJa|D8vrGNwfp}FO|5Wn0?fW~L&YZkqN5wkL3(pLD>3UAqChaD&^jFgtr`gV9|FqtI{mz$^2ZCCU|1MC-yK`jy*^JkE zIo1V=^>>Y|-^!jdBkQ-a=Y=EdTlv?=hAvRp^P-XUt^7S%(*=t4FCJOHmA`k7tS9H5 zW?cW%2mO}}`u7g{FCFw>Ht2uGp#Snge|^xuZ_vMg(ErRq{}qG&#-M+8(0^di|Exj( z!9oAC2mMzL`kyoCf9|0Fd4v9|2K~<;^uJ)x|H484)r0;Q4fp|ILH`mk;`1G3bBgp#OIU{jVDI zzk1OBnnC}69`yh2p#Qal{v(6_*A4n#Kj?qMp#P17{x=Q!ZyEHzdC-6Bp#S#<{cjoc zzje_6wn6{f2mQZ4=zqtc|DA*WcMbagV9@{WLH~OO{qJr159a=QYTy~_b8lz*Yxz6H#yyWczl`n6SglF-s=plkZt3^-zgy~=QhPpO@VlE&PTxK3?slL4 z!`R23_U}V`&er_*U1t9KN9J4kKQJ=i%Ku+3Gyk@c`Bwfv8kuk9|KMfje`sXBmH&@N z=3Dtce3|(l8JTb8|C5pVR{oD(X8y-U=3DtcJ~H3R|B1`Y|I?BAR{lR5nQ!I) zpKqNfpI4nl_RjWoom=z9>-(~`&KNl7YJRHs_BH+bzGtMqp|9uqnr+6H`uad$FZcD~ zzP_=qZ|dut`}$~V_W(UVkUy?-UEfc2)wSujeEwYg9^L~FW*uLxGv~9V!Y;m(?LGSs z{`AuK?sug>jkB`t)_%XwXy29(uly|kthsQ1W$p>-w>ep)e6_>J+ z*}MC3->WB!40UmLENwD zAAEP;uCd2j|G_ro@t=+Oea?=2NhzPsZFVPISvM0{_pGe5bUS|Wfp6*$CD?m)z}`JE zR*Wl8#Xt;K1Eu_JYq=<<&fz)sw) zM~8Lq4Xo3b!}M(QZL+lGbJ^det<+lb>-$BWiIkcJwpHwZ zCi9_Sat7IVDyZ+-unC9G;=X{bWV46Ek5{_`{G)BuJvtkwceTdmpK!789Ni=#0Jl-YXkdBf1L?2wB{*6#cXVyoU#s| z*6Fh=>Mz92m>8;u@vF6J_D`!TM|NaQ7bvy&XxdA`uE0AEp7{Z6u6&d~IR1vfor=eE zf$~)W`vHIdDh}Z1d$VYF>V<$0^_)-hf=^;n_8G79g=goh@{<2zSaN)C9KUk`+pQ*Ud5z(@S@gS|M{c6Q4S@^=JXpezUYkhj|GI20TX ztW(Z!R+BSrjGnF^v&UZJ&cNQj-RfqGe0ey?x5y`dUtl3^daX0hMm4mYcIhkhxKoY= zztEqdBWcsSKbQ$xyN#1c$L3xAgvsY0eBl0uZ6Hf7$Y4J`a!nc9Etd0>nTv5fkUpE& z1NO5~sWZn{G29=26#FZt?^tVWxw1Ld;V2k;aeWy zX-9BtQ1Pk$*^Ke8&K;lqe^j_))2=|?xA9E(QJl*sGV$nsE_w3P*{S=ZOIxWsM;ulI zI_lnJlk>}N`ny08H~pb4r!q!w#fHApue}!V%inOIV=>_Kb-}(s9@g3R`Mhkkr+#Of zPjf-pBL~^TMum>zn=Ga5seE%@{`cgUXOFdApxm=rU66sZ*97*7DI59cvlrRU3%%B{ zm+sa+W2gJM;(;%IR-Vrb0eR%`M_v9~*Z#l0;#4|txfI9^_ABLM`wk{PPY>8-{Of{$ zo89$5a>m zubfeHvtn*d=_03|0qR=vZ?CIv){=a?$jSHMD-*N#i4rBzN;sG>+`>byE&;pxvzgD^{!woa37rx z_|I2yQWwwWapay?`2M=U{r>I2OyF#bwepAg+nBZ9xfN?`zdo>*9(u*|reInwv@(Cb zk?D-o9{I+P%H{KEE7t~cg6(xa*w6p>{0=2zmi+##+Ah*h{$~!!>zhbFh{MQWj()b& zXBZ+Q0UsYvZpB6!yNl&YflhG}m!&{%$OENf zQF(kkW51X)A~x-3Ub4t=ruZQ?l>^rLJ2m3#yqgo}@_Dr%TTbl^EA)v6nR0_n{nj2f z`u+%=Y-az#fWA9}x?eWZ?gDoPo7i!8Kp)xmm0b^|?T!;ybM*18y?@99c9W^Lmb_~N z<&n+m67KoEl|S`NQ=jYiyPK4yL@H`|B630;ptfLuM;=%v$qQr?=mw% z-6!TYpFf*_!_<4*{^0omxn+m;0lDH%uDasSN2TI#zql6<&ZIT?-WBMZw@%)AKXM)y z19^vU>l7SV%QiCXVTW~HpxDd4E>K#VjgQ$(rb1q8D|_1iKfLUDM#lMFKGiv{n7HHC z1Gd$foKL$86gHM!Rd*&*%69V2?FcGf&emAG_GH`~`|Wprx1bf-(y@XW}H4b zppBFDzF&TK>0cYTFBbxL(*HT-PO{hecNTp1ok>04kCnXgpWnLza>Z&pduvbK;qtZO zrd?;NOIzXBaEz`Y=hmJK%$4nUVLR?_3)re(=k~Q}d)_Ptblb-l#kwyE>OQg#cb*?F z4(O5BP-njOyF0CQj>)?z7(2(-$hq?Yo~oxj^~2fUR#1?2#i1o0o&3@0H)`9RXeJQ`p)CJA-y!d|IB% z{>qOl@sI4fN9Dm7|K!zK)yA1T=z^AK{_$PGlX5B;y94FR-hlp-f%sJZTF;Kd!9vjH zHa@4#i5vUM4t$b@bI;G&)aFYMxvi{ru9f9ZQ1DA0d(|b!zE(~<*JX|#Hi?_^fy&`~ zE5|(}F7(x%!{@%xwe!RFiOkbuAN|G0Rx{| zzcguG%n9@2=ljOyR-13Xx%K|iq+W`okdlJ-pS%lVmH`{i#$P2$kzlezjg2YmCl3l#eQZLi;1 zQ|5!Q++c(KP`S_l<)GqnDs3F#qT-@H7bvplQ(&|H|^oiPwmW@e3TdN6MP&A zD$cj3?caoO#NRW4wZ`k2y__~~vh2cse#(bh<7`$OR@26H?Mw3lm-cvHXFnP0Hw5%P zCs57>5B=`D|3sXXHwX88+VlRVW3eMJE{3hnE`6n9OON+vcLjU!pypfIRkF$t+_W-F zmKx9hE<9V?-Va^+N;mnsssBXU^eD~;-tbX&Yj=S{w)Z)5{XW}V>M?u8j=gn8^%XL4 zh@z0CAS2o{~v0VYXPY2?} zZuZbmk3Hn>3qB^ewy(7dY__)K>DP1iwzTJZ)L!7H?#_+s#`Kt&G)v z%-)j4e|#$ZC@xN=ZQWWx4*4Zhu9OX3+KRo!v%S`D1g{Cqu~8A{l}YQWtMaP~7htf~>0(&d(@FDiU-o(0%X{IK6Dn`RIu$K8@{^_#|P6Ss6Y$v09u#bOyP=jaL z|CJc?UwkVr=Gff@3OQn>*sovtOD_M6;bUm;=DoFhGH=c9#|aTLvA2DX;RpNN?KtTI zrJH=+^z+$$yK=F7K@XCq@}D}5^gTfetIYv$c~auCcb-`wPvv%e6q)pKVyu-0BO#e{Fo2z_OD_CegIuH!$f93qZGE7zl@7L+Ph~ru^7Yq}uiitf!K-$0a=MXI&lP+A z@9dG=ZLZ+jn(|3(isvqErJH=+wE1Y-ivc?-r@tZX0^X{9rL}yqN0BphRDI513Le{- zygGgH@@zIIM%wa+FP`1FJ{8n^oBj}T00+jqKc9k_xF3s?&1h9 zg}qI?#;&xco8NZ^#{#8vR()=B_=1fy>05s&csx17YZoZpx&U;(x`G7y}Y2)4jtR<@pl;uFY#OiRsex>s1jcEg0t9_;Qt=aqBet)V9wmNrp zp4e6AiOtTFcN*tQ4BQ=j<;Rg=Dd2~k;JfE=otxs*`Pmtik7-`eK_4A-oeG>`@|{ca z)OFttb+%`^p8wX;b8VoI!N1}We~%S=8yV%}of-4qsT6t zBu3=5u^7gn^6cuYQ#>O}W^vZ~CVuOIIMrHX)7IXfIq|8r@@K2H#RJad0Q*-0`<{{K zn;2T7zAL`cjt9G)+1rBmX03hZKW^l?xRLRaL(jp0oyCWJP`1iVHdRc;sQoO6 zj~cV?Kv0~Lu^f=691ngy7oGL(Gr3D&skK8}>U>PIf!?7FcpJ(opV*8qJSp#Kc)C7) zoLplfWh?*rIx|_dd3M?1?2=EHx=?qYpIIY&Ay^F*ez*3T2f6cYAy2z(Z)>vYlM~kB zz0KKwkUslP1=iGFcfpRU<|g;@eAGWPU^bZM7mloZWgzz}ALQ}r zplbQdXJ-gMmG5fzqg=T?lb*TafIFPfjVH3K70=R9`DKkgbhu|~Ts|3Bdw!b}H#J$t z)$(hjZ<?$On*`>keO zj{W3w1TNUiR&nz#`~M^nkEdo!7by1x`mMYlY~+>R;hOIpSwn`L#0Q;haSm<^^5=Rc z-&Zq-Gxp)qJ;lzsKwW(D^K3ATwSDsC?m*meQF4syKNR5lV89;dk3C{v^4V11>#MQK zRek49ZBNNhb7Chw{MzVI>$~)oZt`_{u9B%d67WaP06BP;8*1z7zL|DEv~fG!#02+? zLB*svz$-oCI^@7u%R$A;o-q!{!7Cn0u036#bd#^sd9X)(aNsT~|A%(rqP2@pb-&6V zWiF_Dq>YQUU7&Q6uhZ>egR&fmhvE*J58N;H{wF@g$Ii5u0=Y}SBKH<1tw*18@sy*d z0`Vma56-`FdgwET%gVp{-5@dL`_aI<$`fl>f|=l#bJqA^&Y1EG{aE=$PZzMc{5_QR z;h@%x*-B>F$TsI>%tq_j*#!z6#V=pYS6z4YT*k<l=MSkE*o)y>c7`gxD^zUZe8tcC&?I)ye`MWcH&(g(! zeYMu#1!b#P-5ii}V`_3>J$?3*w?Du`**lZAvJuD;cKlA(&!_GJg$V(%P2ur>3uz99$O{vuWe6Y^xaT&6pUFrR{9a z1Z-y)e%#x5|II19TVK4|r*9vAOO{$}iZ^!9dpVA>xg}dzb#l2J+*cfZgIrciH7$VLLmtE8nb@_u}%jK>U=ApbPLVC*(MLP6P`1 zxE{){d~5gIVnYhw-2Dn}aAb@P^_&5yR(P>*9ADhIaw8pFG!m%+_W6qZ#|Bm8(1TzxR+P#Roq`2!D_%Z zb)EZ{rrqwd_p^d7;A6X%jrJGk+Lz;eCTq6hoQ*jD?J1m>-(<)$G2sv1%Rjyv8~RuL zvU`8f$|8q6oK`LGd{3R4Fo1e3xI#0ecl~yx{lU;g^5yeT4(QSYPs2(kAEq`Ceh!!mg!Y zwggfG=mLd2wkmX0 zzx<#p+b1y>AEo^{5ImDd&+m@tVMFEieA<9tDDKmo+}Fm+PkY+mn>9xlp1ME|;*0<4 zmbX3W+duYmC)a1(I|4hrzj#g@2xbCByvW3b+Wa(r&3A!t}{b%El!XWcM=tXT=@{YT-g z&Of_xRd%=hzIB9O_Tsu^y?)9X`rTcnhusw;_Xs(-w$9vBf`z`%rmOqDwbsUmBTA9}CcY)GPzFyR|oc`W`kN9JU++>@)GFEogGs$~}+$>wfvFxkbzAjK|KV585 zaJ@6AE}EbjYnOZ|s^{jSvPmMd!d#GE}l zGsg$#UVg8jp&JUF??^cvslj-VrO!_dn}=57&JB$Qm;C1?~Xcer$jj`s%D0lkei? zxhDQ|fjqa)UU}eqGdQuIZZUN(tiLlbcWrP!Q0!k1%+W3P-a94t*eI{8+Y?m&vT>-} z{4{&(oYML7U`K%0rw2O&a^ZOJ2eF0E?cd9gC*EE7J?+_AoR+=r5Hjr*o4Wfp`tc#Z z8J_U#+*nf_cWEo#Tz`R1LajYYZ_ ze5+Vgj>sb%wR!#NgTJqMF!Q^EL&4!d{6GvnbG7Ni*~vg0|EP~+`wnmXKa7l5?C^^J zQ-PR~g)_1DtSf%$0`EI>fj#b%$_>xG`Jm)3rG0UA% z5qKw3tPy9NvYTAF>~orYoC|gZe8c(CU?HGmHZVTi!*+Z4rz{6_IKw#U0)@}+|5{6L z`*-Ec@ztJF!CHVn@~;i(ulVvuOr7!H=$|iayRjdiN&UKv?@P^g>&fJ^n3X@`R&6!T z=>_(XITx@??4e>uQcp{q;bb z9hGBr!MQ-8>sas~b3d?)T>qE%Yf>Kw$T9!NTg;biYhf+G`R2RD)sr~lm>&y4L`~YM zCY<23Y_EKjd;DdO_i$%rDY!bo3*XfETn&_a0=E81*4yV@TiGAj&o*+wy!(NUg8?3H z5Bxv0i>b}~{Z3qI*YB#f;zqqKn%NnJP|8UM; z^Iag`WAp7Czx0(l7u}?{`5gIA;SjIlR`a+Pzb;TbSN?OeZaIDHD<9~<>G1y~6ptEz zY1+8EE7%vT2W5NJcoehZ6km9^&z)a)koMW2ICUO(1&Unh0>0R*t(495TEn)PK#{*P zPR{YYg&F!Q&t;e#E6`DGbv^&@OdCf^?Pmj>$AbS7KIKuHyF1fYHtpH`zZCbRzx#1Q zR8G!Ls!MF5mmYqz>8BHfTT+Wd*(fgJaYumb0|8$u2gr~I_*e<_>-V?Bs^ngm_F~_c zFHcYVWME&xeYq5nS98YLuZUlbI}c?0|2gr!5Rh{`_|u-_Z;GI(y72DKHt`WJWlTmJ zN9)L@lP>REau7f5dtPzl+@B6E=FH~5ky_6u`tZrd{~8!$r|Fvnel`MNo=5jxtYT^UC+#!76Pko>JVA{BAV|pz8KZ}iQwXX{lckpoCpHEr0 zp0zItUKfz_zO3s~|9S9WAfM#LN}$M_^0yuLJ5V*w=d%HMe-U~7X#XED>+EGSxi~wM z{r0uC{AFWHyY_~xZFT?Ge9qLrv6q$Vs=u2LhweAeErku*bhUebJbUq4cD!sv)=&Q4 z#h(Gl(yQK+{%mSFQ2XYykB#zQ?8LC{Y_&PHd9^j_TBi-nRqyR<`KMo>0cw0-#`tTF zjNgk*Kk@tF@K4_V{)dCN1m73@Lh!EOs{B7ihl3XcKb>D}dquu6{ZI0Z)OQ6xlwa)p zvA@h*KKt-T`PH<`X6N0wy#2xc^O0xqP3g}E_{4`cdlmy{NL$|4nEDBQzx*%%d?xj* zAWLy}JqMl|{C^?Eo$#a^F6Om3?g`}Bf6F{M3&F<+Yk_z>JJ~Xki7(t-|SIN2l(Qbdei>RJDqGC z?F{6P9K!)!Vg=;N#j>+FF1^;Ydii}{z&2>-=)=Xdx%JGkkuJ}I`Mzym$uTE>Y-C%@ z7u(o{XPkazc$VjUliP~{UW$v7aWZ3Ml{|a#+sb42y(9AMDckUFue>Pr)d7R3d^`P!5T$~Qv9rUr2d}q$sV!#${dC~=nebyZb zmV$+VZ9{v-mW}k`fsT^JPNkcC-CR@cs>R111y5pv#{!v0gSt!P(QI&c;!bCsgI#IY z`$n1<-YexU|M?@wiUYpx3*?}DU~}0%tmzwaFe-#D}tzE#LS;xS@y78v*WW zEqRrjpZqK z-j@RV$UPJs?)&&F9qk?K8B+M{rhP2!_lGR@w|A>M*GtoI9G`eQZ$5<$;#=<${Mi-A z!Md|*kGt92dN8)GVrRV^;lH*R%M&@%1xk(ATD7=(PR#}EvVScQi{eDzS}{8xC~U$T zo9NQ6ytI~_E>OD3*Ng8O=IpVK{c5pV47Mx7{w`3K1N)WJLFIWXzx1>vzAP?xUvyPO6?_ge}GG6Z2VBh4+ms`d`OB-+H0xtV4s@b_XcN! zHgD*r!+!CmcOkIul|jwR$s+-q?+LumX?r)28)|nk8QNre){#^1I!kHK2G<3Lg4Xt- zz4o%(UiLg3u(4#!2`jGfDLq)-Ivo-cGE{z>ErvA>T*ZoS+4k7NPKmtvj0T^ zoA@xaNnY~RS~lRqJtTHjN8BZ!54!X}BY0o%3&9@;${hj!*->)Ilh5+A^>;CSvGD%j zci8MR-^Nv*ItT1ilWPs%$S-+#Bd^wUX)7B+tx?l47ue4ywvox#+G`IU;6z}LvK-(; zY5l|-`^ZpNe)Gc}#7Av&wXREB=_X$<-i_>HM_UhVV6Q@N*{8lMgaiaCBM_MQ*Ov2SO9hvUJHJ)3Kfq+NM!Z~I)rHQVdi zg7cD(ck+!{2e`O8FxLf2`|PD(!6DwO#ykJ;DsSW>JLz&(*e|AauFIY-V~TbBSPJ-A za;qN3h(3i5xnC&%TJHJPa<9$Dp$$0Q*>l?dUCu7!N_~dt(x!*bp9DxtK4dzJ9nl3ZNaYuzaQ)i(VvhYk$)zT!`f>BdrL;;w(;Uv&HlPaG}UaY~Q*T37XK#*PMLYOCcUKUM-`pO?>D zxWJcZju^1hxpJ1puGJ%^#!IKQCEs4>bYDL|le*$u_K~a2U;E_RTp(}g=>lar5I3c@ zrR2LO>>;acxsv*5_RR%2-~%4{#XoY`reEBM(LzxA&EZna9th3`Y^fNsZ7#58=ojA= zy6Co#+$*j5uoUpYUgiISeyI8RpT+dW&b)Zm`xKdS zem>X;$oB50-vtV}!!dG(WB3<`;XPBiB);T|cN=%I=xy)WZ%Tg*8J^sWU!#%I<}A7R zAj>$r>5;c;)>n z)cc}X91P@-!VWp3@Q)qsogfYcd0uTXQvPGU_bcY^#x79E+&O7od@kUy?gq6uPvcko zfDZQlVswZ{7bxV<2Db<90%wH&%lRU%e7~uw=hANF;Gnf%A9tlkpDpx>Rq^o7{@*^@ z&jI|TPu?mxz;F9mgG~x~!@1f=XFI2jKlxvA+>F`GgfH=S&nUIGa$wpWTt2t9iM4Vn zXm!q{k280NINuW-3JwQyDMw;*HlC0My$gXnU*1NaP1`h>i0`YorAU3$Qx1L>oPR;qkmGO5&q`gOr_FcT;z1AOuE&{fZv{C>s# zY5!Hm*~Y#vY}$X7ZGJ4aweLZT@i!r#+;8G0-d6|hz3w@6Ur=!#u6G8MwO}YiUU)V* zclK3&IA8k%_iyQ1Pn!A}zrHj16IXN|LH4ZECawP&o_nRS=ev-wGB*V)dac_PDo z0AuIhd)sWJ~BeO%qi|s>)A#g+tm8*Tz!7&*L^Y5_vPO0!I8ikpMjMd0&C|3 z_YryQQFnoIJou=A9r#e{4*%*5jA3`yjE#?tooZx|jo-S%|GK<)w0F(paX0;BIA~@5 zRcp&Nxghua+^cqbw|sK?N*l`$_8s@$=o{KmXS&YCZ}n@~RcG2~n0iio&u-7MJg#%$ zoRVL4m$u@2m}6)7Zw$^(ozXh8Z_hqFI-_{}XTi{Zxukq3d3;Os4eg*``B2y)X83q@ zFtnrMSsZ?LzlL2EPxrEW>;t)XKY9=|?`dLG&x9BB{mQ53_Wg?Cv(s0Kr*oU#3-96l z;alakzUqF`q)1Dh2GvHCY z@JQeAd2}dahXXb!bafgjbk7Gk65ql~+G6nBd~d`%bUlx5iG#2^V?P}HW>90>t#1ec zwU)iOpdS}%et&(S7{h@zp3!RdTk~KLQ!d$8d{_Qnodwp|!w>t(a|fyUPS%ZqG8{jU zG5d|Pt+;CK+Q>NGxu1y^05w7!{R|L)7!n15oLey^j}4H-C=Dh-*^c5$p=Yo-b^6 zU!Mxt%Xax{PkVRCp~^M)ynSum#`b9DmI8Vze%fU2jvZ~h_>MdH(csqtcCH02H#m9a z;|T8;d~S7oF!<*ezkfBrGgRE2o8y5}{u;wioAd8TUk-^^-J5m)i31;|#mzIJjoW;` zp1#TfwK#dsD&6Gk<~;lM?AiJba}ThWZ+!iGeV^VBHP60xJH~TyT6y@YtSe60kAtzi zH@+UU`Hhq7!%3G~Sq`jgV|I7?^03c|R(C#F5<<7xCRHR$b;5dfBu0GBJ`j zLwlZ*F{RDD1DivajFsKR-D1|T)%iaaR1TKy^<0pbH70l2+VWVof9z#!#|3U@0=%j9 z@yIrErg2p|KJGF)_@c1WnX#|_&9$Cwe09$FWWD=QA1|IM8-Y8t&XIib?{YV$o(rt2 zIXR=h9%%FBP;fYqm#`L)&n7Yc`1qg?`hPQh`sk^@4YQOsPS{uS$i6R-0|mD7v)0e1 zUF&zH4P@}qoIDlRg1vKrb!4$auCv9@8Cg$u$?^QFf1|XfeqI1?WYzar7SblKV6F?4 zZt`_=?nK)1S;48Cu*c_1vT$%Ppnq>ryjx@5UiECS7#L?ut?SZO@cg&JbNOX#KIk-3 z*jIhr(oYWAIN*Fm;1TKU~%WRu%{+u*kBp>vu&tu5Lg zjQrY;9c$6u+QMdW>H-Bna}7T@6=&sSAfMblWcaxrIW*t*-F^Fv2jW_JA|^l=`SX#F zZ~MAH8Os%G7qXVFt$sGJ{C*(ohWwZ9)>KZhEn+8kHN9;PTgSF8P}s1T#jC01DF68} zri+itb~s*YWVRgFc`;VdE>PNd*SzzBB#B>vvrb_2OECLV}raN+Q8T4%lJB< zHC^DY-AdLpp3A=Cfebhi@Sj~}pL#ZMN4V=-ev1=p>P(lc_Dpt}S4s!&6~2>M_T+lH zz_aHPKb;k|{3@GD$BB%Uy~}Bfzx*n@X4CEh#r`4JrI$SR4(G+<&=tf22kf0@pR+P{ z$JQNIam}(x&K%x`?ydCUqt#dE6hH2MFG6O0x<~j%=5UNof4_r_)?V$nKe;#LqkiepzAo4okm+8L2WNx&+#^@y8E)r- zHm55;@>+S}=clYE<799?P~1gilT*2YH+^|lI`Fa3_w5mXwwwqmKk-;{?dL-)(>gM( zYvoxxCJz^U!tI&BI%l(fpWeI}wC9x^e3afUZDlO?<-~B^@rebRcH-tI5ODjp0e2d2Z4&5D#qjSn*7%Xkk?Cyj3vj8=4(CnWE8p2rpV!M)JamB~ zmvJ%|SbKLMSDqNKxpa~HP=NcV2J1nsk<;}&P#3T4Jr%HpU*zu$aLPt)YwI%w`|xGm zFt>3#9D6WhVzAoRJ_C_)HfYbb&#K1B=mMpie7(q3_4$q;<&gll{9v;j&{rP|jwFZV zlKklcMNAF_hXeirnfBE9j#l2G&-rJk)pNl)yEizJpgL>TD{_c_d3RItuFZ`)dwAfZc$M7tek-oT z054){Y%QRduj&^C{1ZoZS~Iqm4Q1nc+II%xqR1Qe_?-ycu*X?>N^Gxqm0Y@t6Z%UR z`Se#UZ&w1GtcL52)O9DY)toY)IkNFfu5(}h$T|F2%hqS+-$+|IY`l5IM&q}PjMG!H z)%+%#&pRUf38~p{+&tdZ#?|fFMf#48=;P^|GiS6s=N3&-OD)gT_OqAW zpAuWhB-@*~piZLGfKNaDTPq_-7ODYOQBQYnL;C1U~T3cSxtSL_Gtnh=(dIrp;O)veoXP>+9c_@drFt{qVL{O%NzB9pp}WwzaJTN*LkfoXPrIxV&~PttFzXac$^OuJgx_H zi;cXno@_Gj3Th2KwFZCokw<6cd6%|goc&|t*Jqr4?o0BzK#@n!Odhe%dy~@6m+!_r z3)R*R|7H?Sogw32oBCvMCJ+OKk8D=#ulr;pZFY+XT{z?CYEZFxTH3{(JTDI1i(Q~h zlhaLRFUFAlY%*K}6E^Cz1G0m>AJ@Vp2@Y5qtRV_uz7(oDKDIS-TXfh*er#V9a{CHWM5Q4)<-(y4k=vcb*IEmihrC=;xj_GIvWqcXDLTnV@%VWX^k~xlN@6WpRfZaIahgj;9qc5-Y z`LAzW|JuGU_w?nZd3RfTcD_1&rT9>@?>Vt=T5dh9U-R4%ABwZ*jm%a4eCo(t<Yl8+OIukE$Y85=?R$)PECeqKth2xFR&A)~ z3)|hbHlFMMlVW?ieLKZ5VIGLj6aZZ*a+;Y&+q#33Aai& z`MUXBtFaRqyQUv!Cq3?C-0_FaYW}OqlWR8wIGPLOG8^T9HEV&pkAASe3zTm1b(4dI zwCmnFn>HC|0`l-AhTj$7@bgwK#NvvelZBEiRqKDc$7jMUJf*%LAN?t9Xm&(5JG4{?a2~#NFB& zGv5VDH~D%|clB#6eY3%szODQ$Imfg2rHR#QYI%$EvX4KleWk0_y%kU9YHcgWy~<~` z`}gi(IoKJ~3= zZ?C1U^J2Zyj+MRkI!EpwGEN5aP+hz^t6iWtkDW%!SUlMJ8L^e$W8Wunx5?eQ^W;|h zT#`3zDn7I~g7&PjkDixDPsO=QUt!=rX8KkzF4 zin!o*I3{o36tKscQO<8xll5}h*#PGje`Jv})O#>v^y0B(*r${Z`pB&OJDYZUcP^z* z2VdR&_w})D|BaIjdHc$s@){$R&)W-1YPQe5De4tC-i937mYV7bnwiw`x|KzZ_wR^2u zKh5s4qxkG1LmApbkFl-J|FpYwIs3%!P;fZl3$R-}>m8&^TcK-c4}M<}elKSO-pGaF z+1!<}vOyle$v`~3r|yWAQ8CdkH?=Q^EV&?qpL8f|0l76s7uzeJ_ov<3BM;^MM(<;- zo6i_I{Hpe;wDCy?uJ}N9J$H=V8=MW!1arZ9AP0uL^0NyRv9R7bWXsvu;%tbO{sX;j zTjc<|x0_UI4Wdqs%ePfz!@~PH#X)CS0$J76;ZPV}Yf|Wq|o#qaBa{7w_ z+sLPf{qDY{K-}fp&`vt+IT?`cGmAUldl4D#LY&IM_SsO+%OTg!`)~~3pS=yf>4DWi z=_X$S%mFU>syq^uzw%Tr%98>ga5)qFY$m!ZI9!kp>Ic&gD zy+eqBaopVyuxYDUm)+vqqHHt&t`Xa2GhVi}z76kN_6_49kIn>j7rZjDY43v1xlF9~ zXD_>2{oak+P7tM>oN=+am4GiK9p42SLsa&{+~#c4k10=CN&F%olg3K?uORxvxD zwo?9nZv1QKugjb~Q2b40`tafWEClT60z8{@N0N;PV@l~An=hX18S*3+L%)k3KD9p5 zHIy~&xqt(OpZ3u$7rKD_8c*|*oOXBA{lS-tsW^aK#<{|7vdJp`Pp0jj@yzu$7OE!j zEU5Nlsrk|BrC*^Jmvr9|h&6w;abfOs!1q&uduA;VV>Mro1WUm}V4Td>-}>Cs>gRVG zlXNeNW%USMH|9Q}!<8R41Zu>7D z^q)28uMGOT2mNaY{rBc)1Y7xUPalu+#$CeJZ_b!})W`Sv^yOXk?@k|&)%SCUxGlN% zd~SXot@`O+^-1ZINtd;FRpU_YjNTa7EADUn?fn1IDZ@GT{rh)s{taI8%!@f&%zb39 z$9U-|opcxn>*?{cUL`}_^6)eHnIArsU1?r*IxjD6|K9Y;Qr?#J<_gt!TVeo&0zo7rW!L6-*czkEZQ%z)&U2}N)o&3MuH8<4n zy?`BZym)#jKi@OtV)4D3GOVHRVAk-z^cef2d}AQhgjef2;?b28HYs`H{k7wX=zy^ifviCpauFw~EvhCHEJ9xzbo5V!l zJ@)yrv*hB?9{Zgwd)ZsIUYquzKrGmUBhQr`(Plkv?fK;3r9s`nY_WDN5U-QL6MD#l z+X8;w8t{cIKbyf${Ic7fjeGp6hw}LH1@Xn&_H(Ya`vUsdQ~Z*9HV{W^js|l9TiGZc zxaa~!AMEP_rJH=+l!3dFRW-lJTMGEcS9bH?`qKfsP6c$e{FHus*yGOO+s`Li#DPpa zl}s|MBg0tBam%6hVnDxjIOaRvcLly5#Qxc!bhg~H_fT*+;0v^Nm)!Y`^9jdv-V(5x z4tyt67vd`4tOI+-d^wSE{wmIy{3l0j<>>vv0|DOj>kL%R^M_4*V`Jq3xniRj` zl`Q9HE?~PcIX;wYd?-u4EeC8p6yS_psB?2HZ7|lhaVj?AD7U|Gi`>Q;UF8$LaoOf! z9+U5%%NQTzNzK{Y1xk(ag^Vsxy2;mz^R=$(qnTd{@W^Jq*bj6$2lUG^b8kr7IN-6( zFEK5y@CK&>cH+byoT&9H*Tt-SBhwu~m%R(YnSlPCLCxDc-}L2$K3(#h{k4{F&g)`e zo}F?}d$#Y(3;Xe6zZlegKbLmdhhKB@g^k9$K#?!x@tce;P>c`nUokKK$`|&uHseZ6 zxG2DN1#=v^_A|J)?`F-2|Ix{#Ezw-fG<^y@7?F_F3 z_W#o+5BRzekYSzuM}nomIN!~+``h1ZtNmTpD12i_YwNSp-;S^J;B4rtylUm$ls-RN z-`UPrc9uW*tbUg^8`w7+C@t6GU0{Q?{AgoEhnym})ve#^)`!(VE|yOB|Ev3Z{`q~9 z?#~#14+Vz!v>Q-WRMPqrKb6GT#LXe{oelv14ao4Yl*V{C#tP zFZjy3XJ*>niC4B4M-QY8 zHC~)$XyTi7Y*3qXhbdx)v*iE>zQ-j;>V2JU{1v~YzTM^!uAz7(18@6tkobbP;*tJ^ z!1}eo+LHm!oDWv9Yj1!H-$(kQ;EjP&Yw;*{%?p>;J3ZFV&{4w2J9(#H)XrEZ%Z7{rk2a>WvlPIwlK5WGSHzZ$iuH0|Uo3|2f-lP0 za)2kLjg38Z?|bhk$PI1hgM7SNYp*!5t34uVp$i6?Q&4# z@hH`BwGjGw7ox-*c5WuL{0A_@>~Of+s}LLxH^gq0~=| zJng6Vb*hPtv)icU`%)l>`Lr)EW{%I!%;jqG<^p@Bogp&u-rk>G`nXps_|#YM zgnM?Wq4v+Dy%4y!tvCK_Szvs=?;lCcN9$U@@T1QsHVtbsYiv7yi6xy~pzy(%!ghR| z4xDBDSj$d2%8spSHdL(0-P!MbEO9QI=v@hvPi@}&=xKS&E5PI)XEVOHs@WwT-cQAh zoLbM9xnNqJut)yMxm|&M#ZAS9{!@XoJQrBk1q$w+38lDKSG(lZolyF`=d!yvCBxcj zwS8Tn)ViZ-&jr(b!v!DMf?xZL@ul*bFN=Y78$H}b?v0_J?YR|Ca@6Mng^uFTIDK2y z>|YAlPydd9tzvOHU~Ac2{IT)2!1u)1EjIOhz@0YR$>5`R$(^aK9dci`6*tpr>$*T; zk9BOH3&yyox4rB6R(HMqE7^XQnwdvkUteuac0*{a42@U!{`$~ ze6Xhrl;vQUlYAWVV$WJY=UsubC)dvRHJ{}SyRE%k&9BN^Yj+0Z)9dH0$e0g~2Va~Q zU*qk+tF*r3m5kzISmT?%8v{1a2H%l?=cUs=y5t28aYQy-jN?KL)|xYBJrw8m)%mv$ z&)dl*^2CQt{2l79oCyV!HJ9_Xd?#<1f9x`UG?)v)c3SJ$&Dfs5#TZ6X+Y&ja( zgLkEJ&p3I-pZ9<3jp6f1uoN5!@IRC_>}ScuZu!;9#!Gu<{`tsz@|eD9@^Ay41t~Z# z--@?W8Ef<7oP{aYL2)wM^oxrwV+y(aR>&Rt)%tXPn?7xqGcm$R`~1BUj#}GZ_+heb z=<9m?Y0rcF|II+*Z^dh?{LfW1`F@1EVj+;5FAqL5aE`w+_?qC6;OBy&4Ucy}DlVK= zImh<%22*Ycb_DYO(LQZ{uiW@GJ={Us?mKq6cjf}6^4gsIHCK9SuIkM@T3dDPv8IisKH#%r*}ktmDdV`uEnhC@8~=y**3j4C{lvy;T#4m+(4NQg z>2yC%zG8g1uI)R=FB7zswV-^doZrY8@L`j$kGk-V$@l%ip`e~;Z%O+Hf*%ZiJNVP! zeZgvUjO8Pp-Z@$><;GUeGkG_ZHSF`B??c)6Y46we_crPsaG0CcPm@Onbb*4~I%~%9 z=x!-q)#n05PFP!Kw9WtCI`&OEt(twL+I1^4?^PqD{U$Hs;>>)j%oRsxBSY z(W!3Ho(1nS_-=io3r~tR8TJ^X_a_1zve{f4?=F1>ck*l+*KORMy^ZIh_1n!0JdAO{ z-j)Y##|77Gfn3?@IgcZS?Difk|Jz(!$Qs;kNA7lcdf$}qryPl%rQkrY6;EPSyi{Ge z;u+ZjH~LDgt-AJDbGiKTy-jh$L*)$`-;uQzcqBrPv1LK*h?lI+TFwXv&;Ma4< z={q}Q0Z#03xAN=Z_(i7J;?>yeN5%)dHgCl9)ftmt z$Ak0nRes^L^>-iR?+%H|A4EH+&wSTzwfy|u^$TKG%wTAt8 z*veLZl0P4Gfil$J+F!D}$;!?9WV`y=a$~Tg-}^}Ng#XT#-+Pc7?oFH*09TH zVj~^&vQ1q%T=u;x_L0ZF>w`1%#Tuz%WWv4l4bHu${`Jt90UlAL{VwfWt zdK4#e0f*#@yFEkR=rC`sy8MiqOL%i{Oylh<8{WiwD^Bp=1qu%2q;e*}lQPUv^7t{l z8|<(6y0^sL8h)5luLpeg^LTX4H)Hj#Voae|{#j2RZag#WBZvRPJEZhvYBFEBpI5e>HITlFJS< zx`1pxu+ceb@BhD!cCr~ycq=}t-pCl=y@%mK!EqbIvA%QTT*^>6`sCoQ;N?;DveaJ| zyft`xVC>gY?@6tFYhPz*qKmBd%zaYk6?)B`*GZ9grsRTg`LQohYVELoL*}gW{lS@_ z-Ru6S`@~u2N4v(H^J8u?iuL7$zIA1DYm*#ozjwk;&$Zd0JwprW%R4%a`?oqW{|9?_ z0`K=#)`{OXX`50+C}|r|=)FnWW-D#eHf1fpkfnrOXiI5J3#33=T2?_RJFSR-2z41p zP;tXinQ>PHbVN~*QAcJ(!9j6F)Dc$}9hLdKZ_X1=zn*WJ0?uFlGw0P$&+<-LIdj_U+L>c>J;%x>`KG&kXOng~d({g$djfT{ zF%Xlf&FlfP=wZ8NjSPO1QNEM0AyA|JUh$WAxzffY%6 zW)J$@nP4}WY_g9GYh{lZYh_O#^Ro^Ub8#BgLFtn>cAXd*zP3~kbZVtbUvaa}7k=yx z*y1sIfq_u#cF+^PS|P< z%Et{EyJM|+=UEe67_dhjYznMt<+HtLd}RZht5(V;KJw%C)bk?z^wMd+Rys#T*|i9?sjTUoFSU1P#%f^^X!Rb!)}qNv)r);}Z)*MFeE7F&w^%(ckQ>i( zdH1d)PI4;F>x0V!e&R?F-)w)@BZv^HyOA)9^lY3^9HsaF$vKIrkt@y5U!dLMUw?GCEOD$WP8 zCg;#AbDXuVP~kaxKrsy90K!r{s|d;${CL(E2-u&wRx9l0eM2 z2O9(W`KtAGd|~EvYMTOlWt%au&D~_oCNX3q+sZ~~#ph6BTfo0Q5FfCo@^7ygku~kv zS8I!mwZ+Q+KeJx+sh{dje5N}0WKCY#Kt8+8$zfCV;#shUr;pJhbFKKN{m33?NW<&Q zRqW*Jsz3}X9(wku8$T<^4>7d2=jrEUmK}?XH8ntnGg5U?dqy^*tq%IyFm?_%269P% z)yB~oZwu6z_VCodan*siIgj=g+*7a3JypJCx^hO{V`m4a27JeVprL$Vhc$MJ$x?vN z-sOPq%Bej!2kb=?U-p!}Y=3a9MwMBrp*7<47rw0bwV&(q_>)%?+ z@6h`io%UQCTo{Pi>VRE(ch}srVNGcE)%yXx_Ec>di)rt7rYnB(h5uVDq#56TW%QYI zRC(W>b@8h?o3{sjOxVJXJ|=x!mP4z!uum=3GjT)4hl>N*+9iSd7{x@q$>*1tR4m9g z7FRjj7>Em*&dt~7-0Vm%r;9+lBIsjQwL+G$cpPc1i2p?aozt4B_{i^70UN4j4i^uy z#DGubr@nGh4%kR{fv$}KpPcg}%~#3h+txt4rhR?kc}<@fRV?^G_gpN!kCmT#`#fX$ zte%zvHkQ1Kt=Qpbd-Zd%#j`zF3dj~9!`!&9lcH6vI2-mB-}a1`0y6CrM|$g?KR4sD#~${~`D!mcaADw1CwCE$y(zF? zqeBe%WzAfFQ=swRemcvqzGwHwfPDEqI#8<>SN*}e=h&6sd&=)mHQdm8d-+KZ+so%Z z_SVJyaKCTFy~EB`0YC89_p_|4Cq4i4(C2!4=1T#4te+H+Q~9l0WsAMu8)_`B*9Pu^ zKDT&!x%RCI)KcYik#Xf*4C$nQZLl2BzctXlYVb35-ZfsAi+yK$y2Z`@(cMWud87KU zZxK|D@KG)Olt_w_FyScn|Q^f z`e_}}K_+=(AfD#zP%E$RY6Z_{Q!Dl@0{x~yY>sMkx+-66sa%Pp*vM6#8@zo?)up*w z*br0>)suO}v3xH%_^nlsZxl=P?ZHw|ca}4EZXiC3fKPQtlzpSKL^pfk!a%)}DIU|a z!=5_BH|5{4PV-WJ(RW?QHBhnF<7G3y zcEx6E{5m5bLv!ZjRbS(}@7)Pk2mRe(tWNN}{d2K=)3bjm5JRvh&WaE z!#?`iZqD}d)0}^!vqR@15a)`iv%p6C$gEn?qp`VaV?)NpvpwUbpki#D4Rby%LMwmR zp~(xq)4tB$vqS6Q+?Z=~d+?B{@8Qmr1J98w+jwt!y!0K(^ZXIv6Fd9ld`}=o;?FlW z$(6q1D7Nx(Tkm{gvMR85THESY9<~QdftdHTX)k-M)w7x%p!fSO%v@cNy(wU)7}+bf`vNhbb0p8R z$n$b@uqCkfaRHs~PC4bHxx2nTPvn!h*4eK!Ev{?Y`UBHzY`Qk!7dkuiO98vB+anI_ zTm+hRdaRc}C39!i$&fuJ&^1(J|#+l$x<>RP~wcSD0yO>Pl zDAuP2?B5@V5&P^jMt7%F>~>|`%P_9rUAUC7xGe&$=R1&jouRp$9qv3VvY-8%f~r@! z;~V?Lh0S=_Sh4DDFjl|vydfyx$ygPX?`-Y&xj&Wydi!;J^eh5xO5-otx8<*MqDINr z%OgMgJFaTLI$JBx_G}HbPvkQ^btwi=`t{cJeAcgNJsswB>g7*QF2CIw+X8%KUY%#c z_vG^k|L*UY=({qwHu$c9O#VW}T3xLVD%N6;kI(hIV4IwYKf2GzwZ1}n% zpr23I2Iy=flh5{Pa&c9Fx9W*aY@6=s>xMn$C%)x?{+k1`&B-K--mSr^!0)%+)W+`h zt0KfbBVOz#qwdg)GPYNq$vXHxy7r6wobw24!!ugHt+i}BlrK6q=R1v0PXC1jIsQVj z_p`CpnNR9h&gZ+^cz1fW;o16=fmUa)>P20Qux@63#M`gcGx_4||K33Bb$+4L&;JcI z)7P22x%=epfa+-c=UMg6}YoTJf3TKP76Fk<=?ZX>cG9X2sASB=;^H9{@a?D zP4?sWygS@}{Cqnza9>{$6#wNJyL;($&lZpSx_{>{`t+Uu-{rls_PO)dH#z+~zj$f4 z1e=2`0eK*f;vzivZN<`H9f4)(Ut%*Ay*y3(uKX_KN zacjVa_vKlNzyEh(`1x!4D=y2~dv%M1PPYkQ9h*D=iIIBtxiTB*W``cm55A>6*XlWD zpZMZK|M#Jr+s~fe0UF!c0E}wIM}B%ad}T}B zS*K^rA9lNQ#Z9Yx%O!jE2lB`N^5cq(wLWg-$g%v>Bmd$?9$VbO=Bt8=pLKa6n_d1U zrnVH&jeikn?3vm~hjlU0$lJOyI{29gnRO2N$}Yeo9)73Ch-VR+*30G_o9yp>V`HIe zq2^UH>Qb!q)93l>to3=~OTVA3);>J2mA>V`d&lVk`!xBy-^%DS`RsGW2Rz#vkNlQ> zmH(cf-D;Gs>lzNE7rXvFP%amNCdUhdv>m~>CbyoiY$Qho}`oS1!Uf<>U2i)B4a78z^P+`S>WQ_FLCTZG1j+se}^jpwNJ zRrAImmUO5|F$e#4;p>B+2+ZlIoKN?wEj4mgKo-AV7N~*!fp*iu?pDuMa@C9d_ALkY zc;2$BVncW7xH@AwAlI6hz9fj5E5BFB`F&AvNw7Y+GEm2O)!J17`|$Oj?>SHPo-5Dx zvc(>@xZ}$nHHdDV-}D==4ftbxW59;ri(PE3XP@&z|E{3?QmgE$nr18emIHcwJ9lQT zEmr=2&@b}#1=j>6lU)@nwISB*Dj!CCr-n|}F##K@CyNd4yrn=q@s%w3z;C_$P)}v+ z6&Y*Rif+Gm4-peHb+3sF+U`I+%=NGcw9?BjHtr9M$T{ocKq)8DV{8LY8y z%2&4cd&O>RpnWp6Fn#8k-yHC7x%K^?{CV=*+@n_dJ^%d(_Q-#~=bcBehrjIgb(fr% z?Z)c^{Ud_|0e|HBV{KkJQ_td|7QZPv<-O)#nK>Q&Aq%bU&AKo3=z2W*;xksG^1m&h z1MmCueG@f;?UJe$4wkdFzX=I7F_)qz)Zx7B0@bQPw;`D7ZaSCZgPM??l{$Q8= z-+q|=MGOEU`e{a^^Ee8VigU&y8_43F>ld}&S zq^%FwanPUDhwjpovUblvV>{Vw5kK!W_E}p5Y|v}{+NR9qM0}~cHrN?x^1Lueb4M4C z{c}9!3tmt!ch10=ji2%3xRqz;bF=oE;ElmYf=>qi4UATIsGeW;vr(^Z#N(*k@YbA7 ze)N#<@0iIqK60H)_cs~thc$uNpO=OEr(YkixwrkOXy+%`rAN8go|>MY<~}df=odq^WB+%y{pNKp$eYf|aSqvcU9dCIh*jH*K$F+HFT_*~jt`ta zy2)7tnp&~HVrR^6yr&1|M+cQJJ(-m+a?3|?2DJ(Y0)G2U@a*(U0sBifUX4t8E(-Wu z@~s&^Eht~7eui|&Ha79?CW~o!HFq-|RTp^5ZfoqI3*WUt#f$yD56<6GAXepreS9Kc zUiJhd`Sg)b-jT|etFluZ=;5RN^olWkCGVV!mjZl?K-&~}pFLa-*~NCKe4Ur^hM@dh zlX1zQ8!s9gcLd*+8eXK==w!o)UrmYM{s14I&B2!7sNkevTVUP%hw>c%gWz!)F9m9i z-|S&W`7h>s1F;Y*`KWRAOIc&r0|TKLs^;0u7kc^V^L%^O2l9%}$3>ut1r-Zl zXS!?TyJBEZ<)v)epEYAS8_8yuR>g z#6tVa#G;@7)@1&U%+&#Ya=)+9w`DB;+GFxk^&7$Rhd=%49}Cd%YA5FlXttDny)2)% zv+a9gn|%1XL`;^0-lo&ScOYxMKi}K=BVNEpG5fvTG5!7*<=yGd|EWTIfXXfSC zoV`DopEbrO&$YfP-<}_~EB&X2haPgiJL_U6 zM)Je1idET}bg!)2hkknN)w}tY)}NW4+!KOhBDc@maVd6ssz)POmy*7|5>+Ygad=^bUnd)&lbM}fw)h%6r zkzc}1cExB-#%0Hkg=SC5_`b~fTl3eoy?w0J0N*#X{{4+7MCV#K~ zvs>%DA@e@&k8X52ym!^UJ7)ca%&ni-t$*lG587<~{BHd@S?}e3@T0e$zbbRSm%nV= z+1AMN+$h}}vo0T=-Tag%JeAvfw0Ze1?*E)Rr(Y94{5xAumibcaJy*<&k4@%P|HiPb z^`*aZz$W(M*W3|{;6B0krN%B!{|<$ewmT5VU9ER-)N|GPBG8-_erW$z_iT=BTY{q+ zytBAz-2-CdS^co!>fpxUb-|h>`hmeU!E=LG25$&{BzR}=zTmHee-73s0A~f{?+U~R z>TJr%`ry(aY%A{vSESF@L-Dg$omD(bmNmF2@P0zBvAb3N>wUyKma{7d>TP?l9I!!N z-A!!Jvyn~C9zN^p!u_PF3;NwBBOA%A&->_LNBPP|wvajXH%qtjZ_W?($q)Xp)tudB zt9kiIk9mO~Y!Dx@JTBl1dF-tGI71~*Ozk({8u0lkc|VxOZjp7e$t9m$^5jQN`5BNW zX7LLNPmbL`5*(?`U-AX!AHTH9(@h7bD|xIscRv0$SQV%f`Bc024Yb-@_r|)cxjQ~z zU6V#nrclBM` zT0IZMW_{p1tqtfo5LC>nHWyjb$g}1?-WjN2yz;ULD!$?`e&}psn>pL*V4J*(r+fk% zw+G9?^ltCHr>12mks>R+ncJZT+l{k>aZYUWQv#D?L-P`x9fqmrkzOaX_s{?su zlRSzyzuCkFF|?Qb(l6I+A_IL9s0A{}BV#US^^CW-a#;RZ+Zi~weT+UAS?v34WK}(t zol_gx-piefnf+|&{a$1)rhU9_?|$<7{dEr5rKZRiH+*FCM?TGaU(8`z8@1NovDT`- z$)jIAAFgJ~|3&!d{cLTfyXt&Yhh^`Y@TpaLYi-U4@($<2C~xA_`*2%%TZG@8SbH*D z$%h)RujfwBcr`*Ad3eQC8_n%K5cpcK_MV(^-R~D<-2W|a>wMAbzB3j_GSr1JK6dO6 z%7$yY@#c)T1ZCSjGd?ER8XO(uBf>*}L#@8HJ0}h`{l3o%i3I>J~dFcV({H@l$_-NzZxmJ zSUEfRe2$=&K%+|#(zVFgUOM+NGVQcLeB}a- zKfRy)y*6NrI^ZLoivs-a0P(1LDVr0@63 z*pM}?*P)iRey#M{PuAH%>8*ImGmLU^Vq33#*wg#r`zgJx>oT9(dL;3nyX-Qai$^b8 zuBxv48smTYHu4Ewortp<(tahM-=CXaT-l*Er#%08!c(=3PkfdGXT&=Yy}eC)GG|li z-j(slHpi=KTdlkyI?0qfdeocs;v4B)(|D>5rg1v9(aWZ?rTm~n3~D~|qxO)^-Xqy_ zq`psmq`&v+aJe1XOz+|Lln=e1m0SD7iQGP(z0bA3?5_FL?mpjW#|B3Sy{^5P(?zEo z-yWTH7T7VmA$^Cv>TTi!g{_`!hLx1bD&Ium2YHTNWs)wKbyT~P(^RZ&* z4&tlzV*=kJ)6*eNb$9riGh*nSNzXq$KkDmOceB{64@$3b$*1?JfqbA(-vQK$c5UF@ zhJO1s{)v<3xmE8s_leVZzbW|c!2GjCwjatnne1Wb$qBN1R4&=1@ky;$UpB4F+S<<} z`sdI;MQ+?%iLtns?y0Tp7B}{JR__e7;@8_RSCtF-)|LZj=f=QZGWa~zAs%$trw%pz z>O-T$9(<**m#M}MClj6Tbkm_u`)9E8s#Z&W)u1!^kjA?zy}e1_%KK{V7sGP{xkYy` z$gTR+*voJB>BXe>xC`v_*}piQ5wKO;8{n^6SetR-^HCRNKbyspO&0}XRP|7Ixp~>S zlrbOV=enTZ$49(He^SQ#1HP$`icy9uJPU&~e&U(tkS!Ymu@@_H>6`LRYxI8M(JJB2Zm+zP>71ASwU4|-pxK8XO;3Ks zpU<^N9mvCZ0eNamjmaMy#KwO9vESStHF;V<4qkgTd}!iOzO$>ZJ+|SYi@eRjmVm!? zr|-(Rd|>;&fIaN2=Szl%d_&(9Oy%K`AF@g&``!QiVHAS5 z`YT#r>$kVh_CvMAMtV!vx{T@hd_k_n@#26kG4JC;w|lW_On%n~YSh;a_$#+$xa-ix zx8Emc))#?#$7`)>#e74XAD!Nu?B2eOnQK+IbnFQZXXCM-yG=2Hz z&O9aa^#Pm6L{}&EzQnGIk9}JMeErwICuQE(e$`<4AEPCjV6n6N?p)aM~} z&P(=FLsK{8RGnqG66@>J-xf^_b_L4;|Lb|G&g4Mz?`Qh?cV=GsbHCA%6tCn@k4Emc zK#b(#b@^=EzdQLK!J5p;qmN#7R{Lw8xY_&h@Y`=)Jm|CM=0Fo4^5_&3F|4`qX@NT1 z9Bc{51vGKDNA1dywMC#=$5;FCXlw?tuAk3x2c8k|Lle*1U-OCy+bhPU`*B%ASKs}6 znOr+Fmj@+}-ZKL+DIe6XnqzOt%#NwtvV^@E+UYt4m#2jDQLig>#y4&FI?};adS1a2}=WWTjJ@(+G zb5(G0use`bHLsUD`kgg-^ZdZGBl!N@7ky3E8M!JnpY6);y@IeE;-h0rQ2AGDYO3V) z^h>hty@hRcPVuSLMW8KK{(tb!CsS_NS9a^6?g#e6f#AYGp82^5G_~j4iV3^4n-6xw zT2(u0yZ_mo(z!M3=nu%fg@?_${6506Z zthJ*$eey=ebq)L`&%LhEDIRqWT`t^d{8m45tj8;Mp8a(8vcJ8PUG`Uv^zmRP zze?vKW6hq0L0Z+&=8U%l_5&V1g1B!B)Cc>1Df->VV!S3`8~tSqox1}*ic9$^e)z<9 z5om0)kFWI9eA-WQ%{M%BECOw@^8bV9LHz2Oz(zKx)1w1>JlC9gHN8I|iyueYkL+Rp zBG48q|34UCaz9V>Z5cZY4Uz=X6lAqU46VQ(2BS0V#^5YX4Xf%{hB*m-Y*W` z6==QAFO=UO_2k$Ma$n>BKlk!>OdxOSMLqZRgN8@V<9T>cJnp@{LA|Hcy-$uh!sp(y zPg@S0r|DYVWoY)eOY7OOA!B!%`S!s5;!bCidx>o4&|K}CZ){_J*vCd^*!*A9M)!2t z$d`((`-E<5?pQqQ1Fhy_Q*p7zPxpg`Ums_2U>CpC3L0C*pkg6+*43L>h*j~{y~}s9)ChTa)L`jGr~kx2E=GFn zI}oTj@4RG_*Xu@qL7Kgr!cPiwI&bN=n*Gtdht*TVph6p&Q5nl)nSG!cSz+^9`^@w+Q;@t z^H9E*&lTgcqvoS{eKvcJG{*FcRmGfs^**f~ewK}gvzgwiH+x3+Q0*VldjIRpk|%!j zS5C{`lGV@oGbg+EtF zZ`Yoziy?dYSaGq&7jbol(8TV-Kpr%@=&8?E`#Y-6-I3_`+@!yrlj2qS+#z*eJT&9N z+HPEHx3`aoL-#}3dy~bqsyVeFuiFB?mOo-x@no+&^FuuO!JiX@HNnk+cDKOYR<%hU z-U2zs_UYx~%wS_67uMYKdZ4b*a-8Ry&G;||#sI49=r3}>Up?gMiBGj&boY;Z=F1F~xD zUhpovGjNvy8#i`y`uJpBO=~0D`OkK|#V?F{72 z81R)oailM9uC!b7f4;F<9OT9vkNFb<^VNa*l>r;74(xMp@lDR_*;@A_ImCEzq3^{W~^d+mtTeBuE zi~R7RJg5b=rN$S57>b|VX>7BXZTuov4`feeSl=1QGdbd*jpV4Mvd=y`%*)0T1~yjQ zdcKe6cU?{G5Z8)z+1dXa;yP3G;?=X!9bnGSs;LZD>RH_6iGS*ge{!M8r8tpMzOa=X zJ&f$A_44^A2fh@~a%8YcOzEZnm_QRd`sve`u0Frk7lHfE-c^Ct=SEI?SrrRCnQSP3 z78z^&Et=SnLB1N$dii+S*zYm!=VY*z48CedBBN}W$};a|(a*;E`e1FwpD!#$)=_~N zPV2kuTZATtm4o8vvwiF>8=Z4GUJhOvX!wo}N?z~pBI_mFzT!JA$U$RP0KVD>A z&dbIO51l7`>YZMBp^wZ_tyt@8XF9Gk=3LQrBsMO>=lp)Qwv`Q|JELMzJmPL#cDf%9 zXXiAACr<3_W3N6&`IR>{!4`R29b6FjnVvQ2%kRw@Zwb($ujkV<|9pXL_2@muvt8ab zaS=n`^W^9H0KM#~IC&S~k9B)`R9w;U^S%61yWSz4O>{Xged@&h&L(>0MeN!6^fum? zzI507*s83Nac1BSx2N9AmNKS~FXWSrxBu)_&gghaz&`s&de}Rs2W@{){$_aS=S6SH zxcnD0e7;uK=yuk6yU5xQ;AKmn6F%$>&IpY8hR2>>hM0>Xzba1T9f|#7ps`zxPXFB- zy|pfXbX*o(A3P>F5LApaT(N_nTLU)u`DZrQ{B4=5znVWUbNtr$t`2A-#(b% zo%k*J9g^}*SN}bF@#OncgE@Q1EPWe0ed=UQpl2h!zFrVp`q@wCUq?4ScH(oU*;{#L zC*Iv{U5wD(iF$sC(`}s(b?@d2AP|BjH~-UaR!Yz))@+cbLF#%{K)3bfDHdfiJe zjFaFzi}{vdM{rT_sNfmFw+BBQ_mv3TOq_wuLw^x-MF=;F`JpYGz%4!&C-$tYXq?C$l@cWzKV zmwja8>utDY#s&X z`Ql*Bxhc854!Kglb-!nLD4xe=yg%3!tPV6X*-oExs=qd%yPm-tGA>=c-F*zowqBm| zMjlzdpX$D*SG@R9^?xMqnBsCIe0a+Di!&Bmt?Uy!dBY>7c$|Iyv6anLFKiV9y%@8Z zoQjiJoEf;k>8Uu9QL#HCWB!wmj<@Qi^suAX!w&aaeGi+x8vfG)cbFWi0j=cO$F`RS z^l7Ezl#E{*r1U{u0O&N!QUx#Ytl(9jnKX?&j6zcZ!v@#=N-w$}Ro@XMc=YULvv)#v>!rjc3x zmR{@pRAcO)uDeHTU)7H_vF9g$YF+)v_Tse&GYkG|wj z$L27t`|_O}^2yPcoEmS<+EKytyLXU^=_2cL($^>Z>?N1Iz1+HcYCk?WFoD>p8+Y3| zQBKEA!Rp|90`r?&zd3a4cu#L*I@L_o=Cd*ewOQlOra!Okr+;@)_wTxlwSEncx>^-D z3!e^R-by^=uWV$~agAmy_x4${@9x>uzkB>e*0kDRKH3XxsqyF1*O|CD@|FYj())Kf zpXI~8pAY7I<|i5(y`Ru$&A#7h^NQUMXFiSjJ+r3uHceyxU7?r$>oNwlc4D9gjn&#B z(5$mzdM@iuz}x5IRhjcu?R`xf_x8LrYnoiqr&sTlvnw+OF{trp(|dl|$If1V#eZSrEh zm$9ys;T?G?;A6>A*Upo@?CbyC?unU;&s65$bl(^4Ws=3$%Y%wvoh|o?7(PD`KXY|R z{vu$HJ#5i#362h|i=#7nTX7UWHrQ7-@O91xG&Yp286Nr^Twci2SMJ#=&T{T+H1Q{6 zPk?uN&%00Ou7KfK)R%Z`WuI7zOZkn*9mB7x>jN1t0!^O#T4eu*K+N!;7OV;E z=eOMRkI!EkEC+n8vrzH5IcpkQ$Shg*k%g`o>yv`o|H6#$bwbwufM4wLHPU}N zdHnV6s?f^k6Ejvji$LSY$nUAGBN@{>yL9Y~OtIjTSZQKqygT4KKjrMD0spnyU+X?A z>h-EKd&wt@d~wxA^6{3;xiML2Wbs*JBl&F9myCYA$U1xMW21JY`_x*$ubvs?d(N{LsKvvV5z z6C3}L#C{Q8_dxHLvAWwFYzdrmP3^JY^GM9tua=#~wSguVa>FL$r?>IG^sC!goa=tA zIN*OsK)2kmot#CW(PQ4*K;9X_n!tUJ$6C)r7CSEw%CFKrdcN!r-+^EeX!abvGCFwA zKQ&|dz*Dh6ro)r8+e0=1;Cx1Wer}Fp9-W3%8 zUBge$eFM4ietDntV%Y0{RsOD9-_m-y#=ougXSV)ctv{>vXSe>G)^Bh9xvf91^>R<%j@EmZ zG*_2;In~Rr{(h~$f9oI6di90wZ0Q%R-`V;HwSHIYcej2|>-V<)qSimS_4``?kk&u6 z^$%z~#7 zXSe=2t^bPFKezSIYyDTY{;OL5{MO&t`WLkRg{^;4>tEdZm$d$+t$$hTU*7tgT7Prv zzq<9WX#Ll;{*|r&+Sb3S^{;OIYg+$xt$%InzrOXaYyIn6e@pAXq4nRG{`f$z!fyon5^%t9MrQ&ZvIT`Ukb%S+wp9>L1+thqV4-t$#%8AJzItxBlYR zJ45z6J9=kE@2u#Z5&aWd|D@JC3)YBv-Qtz{a3VJ4co7F^=ekH zR`qIB|I*gKy!AJ?UJatZvh}ZO{cBqP+Sb3W^|!SC8(aU)t^bzRe{1XC*!pj8{hM0< zU9JC~*1x&+|Dp9i(E7Ku{y(+;hg<)nt^e`X|77dm+WNP({vECV+1CGD>wmuW?`r)o zwf;S=e{bu5rS-qo`d@GTe{213wEj0+|AE&3cI!XX`rmE+@3sC9TK`9_|48dU+WJ3h z{r_zJ$6Ehat^b?W|6S`p(fUud{vTTZkFEdb)_bWsG2^3Kzq<9uwth|P@6h@?w*F47 zzjNzPZ2j8SpWOO&t@phjdcLgn_iX)A>({q_W9xnY3;(9{7pDKFK)Y*T>{ z?-Z2ovS)wR zXYph=-Oh%wGgj+2W=z-bCf97PI?C`?wJGj>?d{BbeL!BnzBlv3<#;)Cc5e;r&7Xk( z7eBKo-ux4b{_NXV@u7!)HQnc~=w%qm zb_73_JAIM(j7dY+rRH8gQ7 zeNPMR_{=ry&Jg|h*0i21bAI)G@mT})>^a6BP2Jn$Iri50tcKPnaDB{;`&@ik=5l2H zo`LgdE|>hPb$8ctKo>rDsd?qunO+}=J^Hc1h+Z{Gt{gerWZWF^+n$kq*JOQUUzS(y zD|VB~=Ngkk9-H`iID5+9u&vb0PbYrt@_CfFI@=kpd}g^O{rSP$!ovqYBYt^$y2Za@ zB1Yo%{NU1{?4nCOYqtdaX5&;}@z>cypDjqZV%u(JP_2xg~TlpT-AnD4cJ zUB+y67Tm-9LE9Brt9_5o*uF)esX4Z)k81+=r+1G1>C69qKi^0G)6GVW|KiJjt#q@C z?xK}^XOj(VEnf4(=^?xHBs?pv_OpfmqxYV=kL9lHkZ*p^`6jn~lb?4aKReR1ZxLu$ z1bEo7IoJ}g59qOGygP6|uu~n=cU5p%aG=eruH=q9cZvF21lsmM-Ks-2*>__=581Ux z9L0f-^#R%<(C!|{x5jSwfM?H{0lECq@NEm&PVReC7ZpEx$z+R~*2Iw=WZF}_eAyak z`R6qM;u*O=>t&O%*s!nUY|glkDWC8!2j!CsV$dw;_ z?g?`7$+tCUvF=U2vPCOeKhE}*z49P_TGia;8C&nq*63~#M|@;yRrA)}e{5v~{rLF7 z-pc~^S?AxnfPc=KnzL5>J%bj3W=-r*4odbSW3BSi`yfZ;iVuGJ#QNBPT~*I(GiLMd z0Pl|AXQHI|D<9%LU8}kM&h(nVSS(6^pXZ8)T(Ltu#Dd;AKCxFn6=${V9s6t2N6Z&3 z1SQ`g%v4w379bjPt7SY5S`d`@LfFpC>WtZQ?7xovZS3 zn)9AVKJaY~?E9PU?6Fl`>fDX?Ropku@b1rgJ;%gjH0EdN|I_Ffvzq@_=FXqF_VtbK zOw{|@s*Jxl>vC87{wYE1dF03M)UQ2!{q@XyoBI7P3a!`sWs~_o=I3sD`d?*!0y}~e zgL=1Q+xt5jo6y&^o;~L3Kre56P;1|jef92F`+9zS&ebcLEg7!VjPp@8=nL#Ko}<%! zVIU4#*>sQ(DEL z_^i>z->(SB1v2e@X(v-{inDe&-_#d9_59eM@jU}Iyf2V5bZhLgMjm|{nmS@fJu~=< zE@pD8uK3_@Z=9K)T@|0Qjb3B%p4RfgT3Wqg6Tj&5JfVYrI@IDjV=Uct`MUx)rdMa4 zB~#v?za6~4a65S4br{~>ub6b`y^_84GlhFH_UsVp0am+Xc`&#^@~8O znyA`DBUk^TfG@`d=Lf$Shxp)~Pg_3Nt=OVY?14p~Su5YfRGY4q-f5kyv%VJDAWyJA zsQS%tMW-{xZuU)|_k5^xF5c{ZSzui(waShA0bQ)Q$=*evT@h5g%<05i=MJx2*!OG6 z1=+n#WUC#vOzTbD4(Ibxq4&D+m;6P>8oKys2ZG}R_GtMLmqT~p+RV=g@E(aB_$vPY zr|b|n@f2UaxQAaKTpg%kz8)QDBRWn%A?`|~lMcf#_oiR0?+RaLGkII5y-cF>Zs0P z?W_Bwo+oV6UJ@J?*t;+AzF`hx>ixa+ydd*Sg7>FZ_NNykKJfcJ@ta-rF9(+geDi+B zmNNr2LRLMS)VaOCoV|Eg1==k^*&#>vd%s$fo@{!p+xy8E=>V|xuDUw&diP0&6`+4d&nwV%}Rra~VYyYJg(^D}h8&Q_mG ztE-xSIP;yEYvtQCmeY8N#i@Zqp+yxo4%D;Deock9Q3Iotc+hcdD~ zTUX*=_cxhx{8)rUOT3)_?kQb!d)5v1#GIjR^2o=!^VsbfRCk`ciXOicNuBHpb_BnYJHYzCOCZVK z5IB1;&fGb@F>o%$*uB&5e_-Z(5aUIlT@lbF_NBXQ636}?c8986cd)w?E#@3Li;vD& z9aSA(lkp{i&wTf%zdWe3%m?z>3H4l+U%dF(s?{A$z)$@cubr$)d{%#1=Yuq^GNBOhJx`x;Dei4Ynl+MN%1Z-Rcc*Jd2z-D?D zfwoxr|3Uh`jO9U`#Kg}mYjsw|n5;UdH)l-N`e0pvF0QYS?QBqsXQroD&3Zq3WqNH* zQ1x0oY*UkBRkS(_)BS7`?_Z0JJJSEx^x{IV&w=lhenTL}a$I#o_Gz&XZ(lce@8V5H zUpLNe#e;u!hv5?ga@0=MGF|dc2cJAcE2ruN|BC`=<&?m=B3CT03hd$2ug52OrpNi$ z_+&^9na1i;UW{)H$o=#9vp>CBLldj_MIPO~Jh?;rZ!}pQ^FzGnQa{A2d!|4ywKnS9{J-)t>WGwWkhC zp0OJ7T-AD-8bnifw^fgRR)*bGj~O1)VZU?l{A>>D-66x3dgbfY0UI|3ad)L=Kae=0 z?P_5E$AVhhov|2h4e0QW&o5`2AA5s~f-_o=mp@wRVY79zuZR%wX6uc?rGdLrqjNdH zZ!dkGFYX_Hi8VXj_w1tQ@}PJt&+csc>iNjNx(iRrn2bvT?+(`e+`#tq_8Xs*o~?cc z3?F&5KjB*0&u;5%WEY$E1XY9VmQTKs>+9KwUh$93o@eqnXY-oSXBrUwz)G&ec^;POdpU=JcAg!<=2_>@;V$ zIX}$#WnT5eZ*y@#7Z-DJG8Z>@Z_STLLexa?6_ivEr-RtGl)C;JSP3j<37@ye6-n z4IA2A{OQ}=`m{sNAygccZs>E)T;cw}yGx8s^#xCpRi4#A|=A$!4)2jZ8ruM}{v)5d%?fK?*9zUFf zm99FE8$vHzFVC30Yl70t)+>YZ>z2dN%4YXookQ`wq3Qp6$4{BuMgNM#>U0N-zmM9Z;$8X6~X>snjbbfTkNVjB-^v>_Y-5X-E|s& z*{KeCS!zp-ECOv)z^~1LdbQo2n*!~)z?wZEzj8NSXIHJ4EOInwQ*CLx0ydOyWuv&V zzdvvI>|GbI(Vd0om*O$qC zKRr+zQMtl*X8O8E)V959R4qHt^x>tSY_jTHl82v+O9Js=3-sqk{`LoDGvEIxLU*Jm zZxLwDmG{q*d0EEgPycM0^01SRs*R&EhLThF3teiCFI$7S`9;5+J5cPcyJxKP`K?*+ z@ACc~MNO72yjsPcPk-Ee`$+mxUe(vBf&8$6o$~I?@mK7pYjuB-|0j`)Uf-)-%9#KB zv;OylrjbRzyQuEa$}O69S#W8fKKNpP&m)c%2XR{jnq1*m3(pQy$yt+m?a`0+(4l53 zFXG|eXM_DvHCA@_HFkOEYRT82C9CSL?p=3|uCT70ef!l5nWO!3 zsg+DIubAw}_)n9^1L?{4jzreRK%7f=>8NzBK@ZVIoKND|M}co{rr0} z=O4QEy2<>-6aGsxS4Z+;k2wEQJ{xmCmX7ahpOsnj%(pIX`zD{Eot!yYweJtxXKE#j z?EjKAdF_4s*o<$_3UBYr<(ZSu2KQshWy`zrx!bMcF!>zr#f@$su#r7a%)0#cpUub} z9x>_p={dj2y>G_$xgYM6UT)bsT4yIYYXY+AChH^J=W+J-w0F19;@H^xOU~WeTG?0f zJzvlh&XxY8)_cBKzenqxZ*w;5H?-cn!i7PdP0y!w0ssCoLfxzD2~Cqjxo{sjm-h@d z2V^b+t?14*I{70yf6(0@Bl_8mPS1$WM*I13IQse-`dMwiy`%m2YV@TU`YDa>P8sbN zGWNlUE^lb^Goqi_=<+tA%ai@?juBms(a)Hns}FQ}8tqpP==ILC$XKiVZp#>59!LAt zJGwlL=R()TtRALeN6 zpVHhL>XBUbACAuc5#4=aKl?{?_X#@tr}RBp8=a@!Ss$H)U0I*jKcBUFo~sl0x^^I_ z`tT0Kj!}%n;Yp2tS^BA+=ud3)$Ij57(CC-W(64UvOJ?X-HM;wKq~Eie{g0WUU)ku7 zo}v5N!Tv9wpx)&M*Ei<{Q)y{&u#nfKSM`@`_0fjx6$uAL*Lry-lInLxrgk( z_ifPKBcuKM+x{IhboUnd=g-jHcj)KM(Chu|+!?y(y8ZGvvQJ&1%j1ZyuF$>bjp(N| zx_e?o_g-MXdtyZQUV!dBZbbK9fbKnTM7Iy!d)SEXy#amO4E@ALR|lj0*EG8KoDto* zC4ch_{Vt8}9E|qY``Z~a^m_kt4~+JE@1Wm3FrwG{lY3x9_ugT@dtgL&FQT6?LwE0? zkKRArnSeg`e(zpHr+cKIUi8HbonG{%8M?YacaMzZs|$1((Y+U-&AtDt3-r zx^q5~e_W$G=Og;DjqaR}=*Kj=b3UT4Zgl5#O0U>Eqf;8&JrnrmjE?9#8{HWl(HD*G z436lYDdanYBl?An?hK9So*DMfy}Ns6pwGR#duE_JLnHZ~8R*W?i0+wz?hK9S?tFAL zFrvHj(bd3+?#@S710%XS2VD(J>2)v3|CA=To)@E&bV?=*;qqAc~e@3ITV?=*?qqAc~ zzoF6DF`{4J=f9(wYE{*=m8Ty?Y z-E(dv-}?{wo|7Yby(@SQj_CB-?;MQi^`7|98T!|>{STR;?`m}CWF%i*(C?g#=+`v5 zIvmmO)adGPM1N4D%hQOyv(d$AL|-(zIE?6D-01X-=-w;%N6(1YbnghG{hqn#C(Y2+Ec)63eNUs^bwE=a>eXJ)=aFvp zithO`qN`VQ&+if4c|rI59?|6--Sc}ySMTVaFC)5|M|VGu=#Or6_uGj6&_;jK4Bhjb z{3p)Py$_<_V}^chqq{#x`khJp-Jc`6Gl}m08_}Ifbobkc?o6V)-$wNPjlOY)?#$Zn zejDwt{JGyo^jEe0UpGVl+D3oPfbLyj^uD?~>vQi({Fpvt#a8ofpo!V4mC>y~!>O|{ z_l&8tF!zk9dv5L-P`Q|U22`x)?(vGXni<8K?{cMPMs)Wh`rI?d{fIvIj3X0$^bB&B z)IHA6k^Z`;=AHvp%X9AlOOZ>zIE>`GU(v;3L`MU07}1?!^ttCm-8J@(_N!I z45Oc%5#2KiotzPUb)%CrrSEMtGNv@Scc+p~#+1G%Yojx_JL{ub_gtHvK|X7@^^AIS zc-XN&nA*Y4FK_g@_nAjE`Xw{_AKB>a7|DM`qhB~fzp~MRPG`Hg<@4E^Da{+JnhJ;Se=p+BVU zR|g~e)gArvIHK1xh8-h%J!2j=L$7DdLucsXLO(l4^6MG2?>6WUo}t@EzOyirZy&nz zKBCJjx-)$^y0bl^*E7-?AJOX>`JfqkJtKF{(CZnvn4$BV{STO-*E8~oGxT~!K4FGl z&&d1D(CZm_{~3DSv-h2$i#z-8GeZ}5^n1_H>lu8(3|(IA-!Vg%7xeRI=<m9~(Y()2NVE@(`y5}VNmKnObLEk(>uXm75Gjz{I`_Gu6AJ^!o&(M!;^wVbO$29uJ z8T#r*ch67bQ)kCBa!PaVJrmiEb~yUd4BeTs-!pQ$zjT-UMR+v%q}zEz^L(7{MR(rN zJs(GO=MCNSX+(G4&^@0g2XGC`%(cSM;dfi#>_9>0;&Z@oc z_7UA#MR&K3=*}v-yMIJ?R?*$_31AJgdWh7tW?jsB<^`a>K2ku!963H|Ptk$iUvy1QdUcbA|aH$y+8(cKNB z{iip&yJ1AH{J9&ZbkDQVnev>RJ4^1K={e%N=J}=ZX;t7{{#A-zZqV4^EdO=ZcBa?x z9u?sIn~s;ic>i{W_wPF1u&wZZe1`WE9j`ju5qxrn_frGjzn|g#hmN;w_+K-;|2W|N zry1UV9`Js8hS#N2@huyU%GxNtM-O;c&G4=s@E$Y6d+dPsxEbCx1K#6jc<(UaJz<9T zjsxB=p5eXIfcHygc<(&my~_;mi38rd&hV}s@SZfod-8zylo{T21KzvM@ZNpE`=v9y zUpC;q#|-a12fU}w@GcE_muGm_4|q4s@NOLNo;JgK`hfS08Qx7DZ{1OwXLz@CymdCW z&hTy<@SZutd#?fSSu?z64|va+;oUyqJ$HupyaDg|GrT(nycf*y-h04%pBdi!4tVc3 z!+ZY$?*nFdFC6ebaE5m=;N3aH`=9~ut{L9l1KvF|yn8#|dd6Nf;C*t6@cO{>+B2ia zj?5pNJ>KK%_XYSm!h0i`^^B>S-#3u&8UB#YmP}WkwGW-)eb|8a;WNCC$a-&^cNsRZ z`;nn7y7{AKWPJHyWITEz<1sTbF3x(zA}Uw(UozmmAhhpJ;3{61hNrjR*I^~6a`xE6 z$nk#1*UOGT&f^AhPpyRDPT|2{j-GKLLGrZSlT|K-zFTdXX7lC#~a6#broA|ut(!keN zTLbN{^E)rp!3~`*>(-t=(RFmzN|w)d$ntfRT6o4_|1&51>%IJ01KwxP@IGh2`xP_1 z&mHhSZ-)0P2fSZ3;JqNe`JFAVOfM$S56|4WtFw9IK#mx_AnVif^1=b{1>yC3Uiy17 zODpbiKU){E!s8c$NRvgfs#PxJcqSsQ)L^tu7>>t}dx>3Hj| z_=XwYZ|rzu)=I5>(+ux74|xCG4DYuLc>nzj@3#(k-!Q}b#sTlQ&G3GE$6Imujv3xJ z4S2tEhWEP$yx%>;`#l|R#rJz>c;7tW{k|FA|1jYF{u$mM81Vk!4DVY8y#H~A_dj*K z72hA4;r-zO?~lyz{%FTrG5fI@-X9UpiM{wh4TRabv~ z7&*^qa{lHB?PYvXkoXX$dA4bkKk+G}E`iH~Fs;>$D*FYBg|1s;OH`5i{ z{%MByp9j339`IfeIeh(w^lVfIeuul*)_7gU_5GDvQ#;};K7K&6)?b|IhM?@M_#73U zJ}33{-O*VuUZTibHN(3)>-P@5J|kMrxb~KwV+MQ6$0vlJ{9`9__%W4p+(3>TtjYS6 z_xKs!I}CVFnBl$SfcJ}Mc<*M@5uw+ zQ)YPAb-d-<-DY_2-gxgFMm7A#^m~IvAV+fjr89fKtnID41n)g&c<(vjJ#~h6spE~v z6&sdkc-MEl6~hfPyc;{-l6%?=@96{HGiG=<4R|-t@NOCKZk^%X*725aXU_26YruQf z4DZRk$EUwM*oryrFDJk6_Cu4ozvJt(`{MuE$^3^V^EXZA{swKo|K*eU zb0+g^Ci6=s^SzV#1(W%v$^34U`5h+n|CQgt+uQfi$^3(p`Fkhxw@>D8nasa!GJox4 z{*uZ3nUnbwC-a9+=J%e=H&5pNZddQ$Cnvun_@k5g`zG_ZPv&o#%wLze+I0_Km)?DP zVd_u+!1R9h!FxgRJS}6iMdR6--n(7TbA97^P~+K^-sjOh&kc=dcjMWU-p?cTJWp>t zdmGP1>HSO*o<1fIoA|V2GCyN7UpJW_KbikS`<=&iX8wFK|IlRqtCRW9PUb%}nZIc= zfBj_s^2z-A$^7w?`6DLt2TtZ^Pv*;$`H7SHs>%HCCVwaGk0dE}$`8#oa{e5II|E){OHO2Zzq34?vEz(_fO`(IGO+C zWd5ef{PmOh%O~^aOy)Z$^DUG4mrmw)oXr2J{jIsG*N;u+AD+yAeKLRNWd5U*`5Pzm zS4`&qj$U6+PnyghKAB%QnV&V8-*qxyJ(+*}legCQk;(kGCiC}9=081||G;GahROUj zllhA#^QTYdS5M}Tn#^}j=G!Op4U_rW$^4kf{1czJbv*uLGXKD2{>zj3+a~iLoXp=i znSb46{^H5}8I$=FCi5?!%pWwFpF5dvoXk&}%#WSSKbb$$*4N`lC-Vuk{aY{li=T$kso)^}g>&-leU-to7dM ztzX&tt6Kkr)<3EB*R=jX>%Ftt=bcOMok{=9)<389&ujhjTmQn=``icrOI!c)*5BOv zSG3;u#__$n^{;LH>so(H>%Z}Tvv()(dR|r8@M)4ZDMds~(=atBCuuXa1=3PNf%Yy* zQ^G9L(g6!{T6%(I5J7DjN^PZ8k)irh5EM`mMJ5p$R1^^r5fuj%73T?2(H9X>U*)_0 zPxeZ8Z=NUTqzn$9``4>$4{NV^@B4mE&d}&f8}-@VzE?N;1C9Prqd(l}>l%H1qi<~V z&5izeqd(E;I~x7TMt{1|pK0{njlQSR_cr>zM&IA)M;raaM*q0cKWp?a8~s?LA8+(; z8~sG1|Ip|s8~s$HpKkPD8~uNc{zs#}ky(6JG`gzMqZ(b)=xsyQw*23eZ|FEC)H}8J zVf&p|)I2)Z==MfWYV?#w@6qVaMo(+hyS@E&4$f@jq0t94x~I{-jXto^2RAyd|MS}X zqZ_@jQQx~l-?+Y?(B>B#{kle<+UV07eR`wg`o5;kKd;dn8vXW0pWkTJv9F`DN|)97s*wQe2{T73Gjw$XKs z<|EK#{?3iwwbA1noojTy(anvX*yz?qms=NA54+mFGa9{Lqla4`4{G}!(&)n)eMF;= zZ1ho$&Z-w*2N9pgHu|-VE;M>sqrPr}uj4gw(+wYy}Hq= zuWQ@*TN}N;(Qj*XTxTz8^EWp7-HpDa(YiOkr;T6H==U}Hsz$%R(I0H|hZ_BnMt`)? zH#GXDMt`i)@qPOCHvdzN{!F9qZuI9H{e?!~-{=P#{a~ZN+UT!0`r$@@r_uhL$ipAB z`9Es(Pa6I6M*p(Wk2U)7M*p_aPc-@ujefGxPc{0_js8oc|JLZgH~QH|k2vB$U94>M z$VOK;>i%W#?Hav(qyB!U`LAqrU8Cz8y<4Lj8l7)+bE79Vy0y{mjh@u#DUIHv(VdN+ z*68V>?wc0`|C~R7{AHo+89xth-{$Li@s(|SY@^3DdZ$M3(&*h9-O%X9MmIHjLZe$6 z-PS0Z*l}{B?nC2yH+r8&@7rkIBM)ff@$==uZT?}6&blwoZ|fH{dU2y))97Ox{n|#K z(CA{LPi*vxMxWg1QyX3Co_J2K=Gm8^65K?``yzjlR0kA87P7 zjlQnYH#Yj_M&HutTO0l9M(aHPVjKTbqrcqfuQd8=jn=vTtv3GcMnBT%?=||-M*pzU zKW_9-8y%nTzi#uNX|z9&YDpfS@RtYvcCv)lUaM$c*V+(u{B)wqr> zYW!74k89)08oj*H{f&NIqvQJdrZ)eqMxWd0^BVp3MxWnk)y0e2_{K)7K4#U!+Z*3I z8~sqDzY!{)&glpK{J`hDbSIyuZXbGwKz!E(&g7AS=DzSOac&>D{=oN7J`!`$r7Yz>YGG`ToE*cUm+gzgIbEke8}2CD*Xnp`}EvD`6#Z-YH!eszl+J6c5{Ii!2(`YI({1?mUS!)EY^iJH>N zHhz#T-oCGSZD`ps)-m31U+t&&;mg!3KD961i7iomaBf@rYL|S?z3Tk(dv73D=LFtM zJk#Zg&909Ayl%<(;lb5`cQ5Zz{KqR+6$A3*LL9Zq4<2i3&|1~x>hw#Wb#d}eQZk10 zHS=l)f93J$^lyy~eCusEBV#tmiMw@d+v%BmMDp>)vX5`|_jUQUArP;)JGn;|8^z~u zE6e#@Adl9r3aXwiOCO&YK0eqOls{|I=cnA)`5e;M>=9o)6<_^|uez9ZR^;Kx8SCt_ zw`{0F#q&w{!4S>!<4_*ZC^BeGYG}KC+x!=Vg|!=8Ny78GK`(`?wF;qm|F& zc$Ytq4Ub&8ixPr^I^}hmZDXBsQn?<|*Gi|gKF8Kh4;~psc>42aJniS1sxC@q?_ zoW0Ij&(rH2%jj*MC1Y%RP37l_nM>LyO&r$+#|Gk8 zwpZPb?Q%~QA9=mc^-QeiQsuUnHRjnC8GOn0I(c@xKgDbzaAvE2eEQB@KNe48d({XY zdEswAS25rx+sU2fgFB&YNN6W~rTb8O=EBRCtwF**Y3Jns?DCvJfo?IRL+n-s?9<41 z4=x5*1|@4-`V}L0#G_)Eyg0l3)R*fFC%%*6bAi7TFTW*UZPar{9@x1Md|7Z!fESN; zbg*O6yUlHWw|ht0lsWOW-#$8b2fcqAGiDQ>;;;8Kws|Ik7|=n+TRR=@Gd0TY-gmyz zMFv~R)XcG)&MShu1#Do`c+OtD-m5Q)KrvQFmj?Q5DV^eTVX!8+Q=tCXO!h?q{~jFB z;Ve`P z>9dKyX9pUaJa6TWKc@%h#Ynu~6Y9N&4$tTvp>qM5YNzJKK^{ zJ}1)2o*~d?`GfE3z`mWqmS9{9^1>HBu!+8h2OERR4g1R9b?J*c-oGI@4KM%Cj}!c_ z&zX4mjt$SDVp4U7zhW}>U(JyzzuLLMnt<%8$I2lYCk1r#?UI~}g;4f^*lY^y+Zw3d zZNc_{c=yAj<`t zyBpP?b?24ce3j3~1?;~tI^191n1%9N9`QKyd?s^aAP&7w{BLAleP5K? za~3ZNE{s$5J}=NVCJ^fL;_$dDr}2C`d+Cp{+k|#=2*V{a-s{U7oBze#W}osU!8Fmfw}a;R`z#gI$65sfUCP zfhNWaO&(r%hr4Imz87VF2sHaHJ;Xlimv!sMXY4&1}q7 z=eu=2((#1oC>diOHHYW&5zmR4a}Kr!>ZyFiyBOZ8fw9e5y3J)l=^NY3rbF3W_UvE6 z9_Rg?>1%vw z>t8oxeS2HKV#a#a@RMe&k8AjLGiq2Zutk%%CpUR=Ij-Sdne%&7a!e;*qZ7l*d7rNr zXMPAYGM}=9OlQfN$NSXIA9X{==0HuT`)T@|fg#Yy`1&dOtli*$X>SYU=4lGx< z=L+99bT;)ld}LdH`i%9Vtv_SNy7zhVzj4O8d)E3l%~&7j_`7m&`+Mshqw!la?$5-r zkzMzMxb`)^E8|BbFPlQe*Vr>uF4T%~vkP2flgz&F>3+j<&V+D`%`%4z8N9UO9N?jP-F2c8+3x(`Y=-(Gy4OPsms< z+!u?%u0Wi>BXkHfHU6w-58nQq8u$C;ZwNH|o}GPsvd7)6-Ee^1<}*3iV)>lLGwn>= zx$#`x>7T~;{Kz5exs8uMeO|t)tzR=^{cGF$x6D|7a9h82#(Le4*UeZT=k2|j5W8{Q zzcq71po!nNHhFmaxZAfYkgM+rRm;web8vo8u{LjRd?sF&xqZRb0B@a3vi1a?QSL%E zJg?b6&hY`=bkXl;qu5q=rn586FP}q(KqK?|L-@6r_44hw^oKyR?}laWduVuvK(p`L zvajmUdy;m;0dkvf2vs}Z-emKyuN}5q|Be~!cW>*@pRw-wZvS`ASRdEM{WDSdU>o~i z(Dus7u0Y;3`K`LBJzt+WdtP`Ld(?lumz4aZc2W!Tp;cG%p;cYs?Y|B{hI*p^MVc;1QgiGJ4cyn9- z?iuSZZ|nbO#`^Qx`b%c4%OCwW%~<#KA?q)lv3_n_f7y)noo)SlW~?9E)?Yqjz3Np7 z`n>Yuyex@3>{r~7<-=D z_WZzM?D?j)=Le_kabL)-vnbZ9gI$4~zBJU@#-Q#JJeqlP<7d=OnX4MIUNuBkJ)_it z8hK5#M=dRN*NpG~563>|>4zf29pkKz-_8Fu&f$4&c+}!Fp1;mKo*(XPnZ~E~@cl^R z;{(3>dPJS?*Uebp+xGwHjP-l8_1Di>uXmL<%vi7Uont*Y-!Dsi#Fd@>IXyAsA<*RD zjZGe2H6YH@_MMjbA<*o5Q})&Qp0&s4j3LnMdGj)Ltqt!GX!iZsGWT5*-XYNJd&`u4 z)^6~>w946!H@+ULges;#Xb7cM9GuDr5>pwSReVqF@tho8yjqlVAk+m<_8n{#C zoj=D1YQtT8Lf{>&?%V#EJ?s7c+2J1oP3+&(Z0+l6taCAZy8_P#dxk*M|M@BV%O19} z)4L`gt_V&F$kLy0F!p}J7jvb{{yqj79;}J4PG2tG+w_lfegC%p3p3X19KUbIdY$86 zoUuO6_vrb7vuk`^ps6)qhv9FZ%OPV;j;!^0!hcjSi{Dz$&wuFszc%9`(AfRUvAgb- zdLOxAvYHxf&-@QIo=Y-6elJ+rcz&hxe;S{6Ep_#)jc;66k8A6{He>yqw*H|R>-Eh4 z^%?6`cfT=XeO!01h+kqiuAi$jHw2pa{brMg_fXG#_6>n%-*07K#eLQ@|69U01e!e` zUdEpO>kPZH$KCRf&>_&s`Rzm4Tzj4qzP^_1t-7c?;&+;yaW3nQ_{fZPaZ(GvJ7Zm3 ztpDDO^>ME5nOyZ}_9tiLZgXS~fhG>W-{dcqJD(SaK(p_o%iMQrc!xlJ_2R_r}28etsYxnt5~MXWI8>POdHuN)EotpL1Q$4)XT~?D@mkgWog5-7z0{rg&ah z|D&weGsb-+&+M{i+Sk1@eXvGeo4y?Wag!m&?uB~Czp<_V$&7XHKlcCWjP=Xg`k&2M ze`H(#^BL<^qkl1D{p7a)FK4Wa1N;7J#`>{s{bMuMtA>;E$us)7p<)D!!LGo+{b(l! za-znI|0ScbcrLYnysqAy#Uaq-{I6qg-An3b+8#AA1e!e`U&fx7hi?cpd;Vs|9)7dy z`o{OS;iHcoYET@UW1*>g)7oNCd!Lv75NLG$-3(p*o-@NY1e!gc80}e|xst!oc>cce zuuH7UE`8^zm;c<1hd?9$AF|iGr1(3l{lCeWr^~yW_tp8}g5dmMT`=YyGN-Y_UgutX z==s0Vx9o!)p0`0B=drE%H z`5Yd$vA5@|`>Ni(%m2HDueXD)-VU)BANd;FLXY`g4_>}a<2B#&j%^Z$|4e(_Kc7rM z<@}Ps_aU-L4z2xT*3^*Lvfc0Hw^$b@6Ypcd4AXpR^l;J~wod zc}1YVJCNu97nyYS@u|-c|2|q18|R2`djfGJQ!K>uKf*6ZL!gNd|I`%T{lU(l>W8f* z3s3Q(v-sq)>iY8Zz2At>uE6&d+%r_1#aG;q3#?6xFPrEWhtJ0L;^RLVV_z~giEHK1 zx#d4Oo+;uu1R9&HqrES9@S3-82(($e)~Y7O*rh+V%h_Xl)$7Le$s5lNnbYdL>$?~H z47^-iXCloxs+t!YeYUERiyQCt>7N`p-dtUy3MzA(8FQ3}A z!CaueHGC%pRU=olF`xA12gnf96^)M9D+cONTq<`(#gd-5HNj~)v;18Q#1Lgu)hz$& zT-6>iIwE-)LOmzhL$B{~)~ZkcmVhl|8F>6m!tFxwRh^5|<-sX|bAgZlY~#Q9uu+_A zZDsnKg7WdA^u?+6%Nsw~S$7Rn`Ge1X%^gxQ=qdT`05+Pd`-m-?+M4E{INNhU;LO-Z zpXU)f`k0x=OP?5$ePX~y@)M@X9q{Z>XJSQS&o}kizZ=wDjo)1)uf~dxw7Ca{4kNk|!&)J#V9B5>`rn5r~{n|IKU;C;)(w)>Vs@{&$N!uOBb@8#+zhgUJ zr6b)#?oo3q6FfC72W-*Gw$swz7+luPJwE;7EuFnT?gM-HP;%Hbo|`5oYzOz;8aej6 z!&b#7x_!-qZSz6dn(nf6h|Q5rjy#n;C5PPduhtINXYc58zdMji`K{VDM?M~F#@3Gx z7J^!{e_x=fT{(oR)tX~(&5>unds<&UqvqiE>ifAbdUgcb>qg`69*v(f8b2jta_y(r z&$9IL9-8rD=FbYWFGj!D_uBmK;@+O;kH(M4m<{g1=LBl#sN{YK{Y=oyIxW0nUcUWF zerIn#zC*_D&RX|7d)5T+bWtTz3rCG-}P59#o#u zV;eoL(YQ33_g-lIZjEkebYm#}?07?dV58)Y^^||^=G%v_kIyGRdCOSem~p>;Oj{>| zAM~lc_vLrV(MLDi+^OhtY$t<_S44(Az5mvnhuvB0?Kr9FtC%?hWy>e>`_g*eH)TA| z1zxrN%B-=wa!l8EXYQEL;`#QBD`xgQH)DD9EM+fU=(fNfaa|Q2^V+Pum+kUq|E5Ou z!85I=71PSMXQTC>iLuI z_<268i7#?cw$Sfm%8`8!GO{XN=bv4DzZfaC> zCX>&6Bg6hDBrx)|IS^kmwguY*d>T9H)yR~OicxR(F`eDy;kB2oWfxuM*>t<`51|@4 z>x1HRu4}&$AF z`p%x(t9bL%vyP6%0FU!`RVbd)i%%aP|A#=s|IYB|zX|_BoBK$ZADF(lsnH#Q_JZ6A z&QXmo8jZgqV|H6-^S|VsrsscC8)s?iv&Y>o)|#5ozfW-c#F-BtA~bDx;C_jj2hYy$ zq;Gjoz=lUp#=jF?ru6Lxb(M6tpcgUKU)!#u8 z&%SnlG-Ivb^A$_%`Mv{NZn5W%OYC`Z+rw8epbzDN*?zXK8_5{w;6aq9mCy3ke_uWs z$1Ne_J_Mv4O2+ynWNbYk;-CzA@3h1o&v~u%+H>b6_BhX4zvnJX>=Eax>AOzht>+*g zRs{=zzPxDTvlS7OcPjVSD}o;i-Wt3o_+aqSz}dQ67|EeuV>2I*&%FATD>B64#DH$C z_iaP7cPYNPL+~By+-#1%y#X7`zKv7tQ+I5iAL*(2O;hHbq29;h-8|yu`%!^bXOONF z4q?ZMBN-)o%ar+9c5EH-vcvta^>%DKgdN*QGRlq}Q|4#cangvlx1+Cxlc(^FYi8Q{ zKjl{LyZbWs$yz!S)AtVKnXd0S=N(8NHP&~B;9JwiF<~-hxApaHTsE-D`v*I;{=VCv zv2}IGKW#DS=g717_<)<%=%Ig8VEuyN{D97N!S0~;h=F$$ylmeWutAKs1>0MHArznZ zSu1_Ue7i6ppFA-tJJ_VYE(+uV54h{`?h52g8z%oh@NWWm`unnU+&%N&6Xb`F{9req z#N9sBIveSj3!KmLPrvM2ojxDRZhPrMD@L`~o*e<7zCX3fc0Q>OKK63SAeZ0bX%Bg& zx7IUt@ay5^`5Go$?5&)oJIT8<^o%18#0=lcj861V$flgS^k zHTFA*#&?UdiSPZ``RvE;4y}B|zm)ui@Q@)6?7b$i-}{R3wSh+V%AjIa_rcKS zXW37_v*B#@@mS1Qjme!F-WWVHpqnmphpUSov8*%5UVf=XwMqxsY6<99H#-8c>hCgq zYL?w4kNu#|<#TtS_SL5`-sRLLd9!MBE^BNS2l>^fhdu12M_jaF^8W*C{dwT)mVj+y zV4rvofyVb~{A(twH`hG9>Xh!P>ka9Pfwh`j*UinUb+KW$y|ZeCe%Kn2)7Q3VrB-p# zXM-5cii@>repasNp|A2Q*6btCdEXd_75=IdJkK6I^TfKZ6Fk5N^{uwVN?%=*Cr4z{ z!%j7Ymd%^eS4({CpKEL;qqmu^#em$Z6Y|)9cA!?`j-T@!v1Yh0RWbFvp_>$CeFB^Z2#d+Ge^stc+ zY%E)*<(gl;Ondmx@0vHJ3oqN{tkBm#Kjfn7ZB6=BZ~VMha7N-sj(f(x*IyM%zIrTP zdFkULhS1x?&ecKr)~~4%_SZR4ukJ=N#kJ=p$MY0_*~G`A19{Lslsr_;7tc3lo^Ex@ zZ(j@Xx4QJN3;s0_dwz?ZdgFs;{nLT?SSRxXt6c1r$_zWH}NYQo|ExhKo7m< zPY&!mArK$+W?kcVPKVHXE>-Jd}Ke0JKSQRV;eB!SfxLF+N;-&zd2(w|BX6bxz^=;JH<_ci-#{P+1f zy><6)f45s#SFawemn`wyk~MqODxd9H5!|lrDII^8??ddLGsXAeHh)a^Sg(7_I{9a} zb-wrVFUt2LmaV9Fg_3#ytg+D^^X}fBmkwhwMBQg4TdZG`ziV&4w}nr4YV%|kzxlt; z-+{+3e*L_^XK%iq*=64kxA}SxsQH`Pygj{~XJx*>UoXp;fB3{5WfMv!y1r4*7xIq^ z{yl%+y>h3HKbr9|ZQb}cGq#uRa{_(O#l1magMCa(f7v7E_LV&qdvmb1(RGcMopf4f zFY5V@&NVvU=;lV9GwWL$-QMU)jh@ozJsREF=xL3*Pn|LPG;-+N7LX;cAUcttZHSra{d@JeXcZxg1&W*d}ihwRuz2Ot9+VAX&nRu%=dc@9MK!%#qr&lcXj|${j ze{~=Z@?c!~kS}A@I-SO-G24w%V>TG0#%wXJvr;xyUdyh!Gs?EgciC680Mk@c#lTl;OrFkqe7oyBF()>mi(U_JSK3buMFtf9vl&9#q;p= z-P2bDd8L@Vqg|5zKLm?`XLRvinErf#zPeG*WS`xAU$N(-&)W6(xO-d9%e=i81#I@L zExFzc;L70qz`oT%J#X+$`?sS^-{R+6>-}I&=EWO5JJ84|8~Mb?`Z?3%)2FZOd35?> z!VYreqt+@0WJAqgkiI>O0bhnd^G-A9q*dw^6pg zdtLsQrq3?#RPwYxsP!Y-T;)z&Kz_U{;+vHpH90E=;#6^5D%TY|Hf#;}(buM07k}-> zpz3|aWM=x;Qss*6zn2)S4Ygkl@y(fLw{>T!@}BPG{rT!pw&TU)``+>KmmId86OdPS z7LWML?WRBtye<0qL=I?V&`-vAzkAx=4T1W+JRnc*@U!iRfNnmX9z5Vqx3rTDayQo~ z|CECFee&&Pi`bB*CTgwb>0{?YP;+u>u4+Xb#YkL==g#T(=UoiwC|>7JhUHic*yY_= zBd2Q5SY6nwcFEOx9&0_1&j|OzlX!>=Swo;*e1P0yzxwI-lV^{(*WQ)s^KIH0z^@*w ze#v7WJM2+2J{O3u@sVM`voYYiJgKwm0!>WL2@R-2K9fB**pmhR%URto>|6-cj=lQoKyBNHpDeoAG%a5C;HS6Fus+b` zEbI=*BE!!cRn3`G1J>bDylGAj zHwWa)TW`B(9h>N|hIdCm_xtnAWh)(PgDpYXcus7z=HAdw2<*`+M$Qh|SWrIlfscFJ zel@05PAWF+HYaBLf`y>g*kX;X)=FQxlX{cG#o(%-U$b9M#ILt^Z^k8C+{ivU5C<(k zl6o)>>iEQfPizvmUaq}EpiR>)-gqt;t@k#leLQ44KVnXYSjppjAU?f~f7RKzX$H@4 zbv)$<*&02og0h)!)lYYlzZzFu^5wT%d_B(JlIv~qx83^j`$pqekH#-*WBSywJh4+e z)-=j*@2PUExx4figSrbUm)2^|J~G*^PA`ludwTo6YGlvejLU}Fw{yhvZ|$>M#pJf5 z@q_Yp+g`{0+c>HZ=_8-ni?RW&Sm=XufVvOG1i!{_eLlEv`u0Gkj1GbQ-$%W4XTHj~m5rI0#YacuJ1nfH}U>n(G7oBAn zTgomrmR)QwyV%LTvdx%{#uXcsU3K4ApKW+G_Ea5|?2>_6N0*Z)eCq=-;-4lK{JKwY zZer!W{fa1){ ze`T-`=ugf|sCdXh*@K53&rvqZ0XudFc-&X=#O|`$e)90!&;A<&F)&|#jK6>Ul&oDC zh@a<*pVNG7C|%`?pL5jsSa$mPOg8j(`r2mMr(Syd6UMj@i2|lWRiRctIeKbZXY+uVgP|%(i|nzqSNwzVdW=`f91-K!-*L-8%v@UpTtE z7Bi+(4Tvv)G;^zChdSC9$h-YjA99tjPU`hR;p6KgS~2s-b6MLHuwRbIxG)fJKJbY? zwNrl3t7gVIkv}f&3{D7)HFcvFYR|>#Zws~u>;*FSC*b<@iHCRi%W`|ZI`n_Byck?L zC05UxGPm4#{?LrQ*Nx_1F&Zyde(^a&RbNM>uRe{{(_)~eP7JE1)T){}GKHeXjn%L@ z@4Cu-Z*Xp4pT2X}?{Q}A?d2bpF`fH^UgtDB%$*vjb!SDJR>#+5ompAfLWV#+=!zaNtR)&P%o)&Vk+>3wEH#`^+1_LWW6*l$e?yc=n3@tjr{#|LVN zkM^;r*4+U$Z;rel2;CUqRVR;VIpC|>WgBYktFm@>s5VUge_;NR-5$B@_k8t?J&(#f zTaRn}#L;oy4F2;Q|GE+Xqi676(D;vT{6ad~HyXY6@Q)8P#9xpaKZ z4E{@+4!L4i=H0)1 zaBjvqddiG_PtCkDI&0t8&)E00%-iGZLVbR|VFv%xGrzy-@w^<{_lz0)zA^LeKDwsu z`=%NDzB%)CKAds;-7{moSI*dfRp#w+$M*Sp<_!L4b^6X6?RoZ$JfWmJc=Zha z=Qe)#W^dCqGx)zH^A&^gyL4PTW6yQno>xWBeBiDnXLq1o5;!O3-09*=zPsRC+y4G@ zd)@PQ%zD}L>h#IJG?;ehN6h5Tq4WIKH%FH_xmg>~>z$75e%*al_s)a!wJmz_-6Npa zexLhmUY^a9u{tQd?l{kMd*kZCSk&{~vvXzO`DV{4fjB%bg2?tR^vqDQ7XowrUNXmf zuRn~v&L4d@WRKXC&a2X=(|FqZzxN+?=lzHMNeapUCwpbeiO}n1HTIks0*wy#krDGIdwgy?qRqL-`9;3^65CC|p<=6k zOaC;R_cj@L=w}c8;_IBy{iHmfog==hsc#?E;aukAL7NpH^`y4SKmPNLpYwsZ@J&wG zJS_+6rR>G8zPwwi3r+kh_vm#d)7T~#-x0f=*OhJj{EYGO={q~0s*d~5E9_QxTCYdV z+5dt=?3W{P=zJkY#OU@X}T< z<9kxP-Cg$anNGELWgtK9N^$9JJyaZu7eCo@%@;A!4&{rp;EeU}S2gC-#0V-WfHr#bgLH_Vs?O%6L;ywch(%way3f#RNQ8&J5I!#!voU9(aDyUw1~jllb;F z(LtWr?+C>H?cKR1e?DM)@yPQtJDxiG;$FTwyY7YKg2x2psujBNtFMKCetk{f`L1W9 zn)%J{9kTS)*A%lnky&TBbX;d4?N4JP9W_t)RRR9f1J8mRa}SvZaq9nl%h)q&f43%I z^8vZ#E4#!{{KV$lo6YWN^Z2#hfw5C2jN*4R4t+Nl$_&I7$J=!P77Y5FUIQrhyr={4$&KT-*HaUEflZyiW#=MEW z<9FbSg}XxB@$C;51Nyx~%8mXvt~pTO;xHGGUojA~^35LcH5L={>Yg&M4U_-hT)$R&nKkuRbK+9@ta$VJgaGf3K>ORsIXYBK z>}B&}L&YTGC->Ch#)2I8n>+hZv8c7Z;bX%&fmrSd*eo6u^Qr-H!ONx-1F;jIYXgnV z{Is8}ss(3byjEw%{I+0wK)xmh{pY*WGyd+J2Xf__UE+>!{G4Rhxq({U6jc2fv)!JP zgU!KwAYSDEpUB5k>wL661X}sbUX2Z7-a0c|vnDP}`Bl1K65Zl8mN#Th6Gvx3PUK=; zun@5OrWTi3d-1$<2_AJTHYM|AOYoQ7-xEIf-z?o@yVVOF;yeUe-6f^_<&ilp4|GD+ zr1$%5g*epTJnS}#}L$Yrb8FGr?3b(T!`g1ec0a#3efj={c9toqzL-LpoX?a%VT zefkT5ef2!rm;SV`<=D%Y;$4|O-V1|=27CkSe;>!$BhUQ7W8SlZ-S{eoVk}4a#EwlR zgUxf@T>bk=*`YScqQ~84o*d^%duMl^oPkY&S^zrPBLAK>rPKK!PctVjd?kAbG`Tc) zQBXEijq$ygabx2@qVaDH<(Jw~&vey$;Cbnb2ibH_doJ{LkmWq#R~O<(Hkm`970*KY z?j1QhocxA;V#~>)4-d$$oNh~>T)AW~9=Vh(w-MQH&7R9iocrqvjeds#~Q!bSN_uTWx?gaTu`~-3m>(b zld}^7GOQmFnA_g^ArrstODW%CpE>;Uza!Az)6UqmT0J-G?2=2i@vZEjn;l|T_0Ny; z+j%ZK)1A~ojf>xTaX)Jn`??3N&Kz5x9DHl=(4b_isgjlM!F#9Xj>}xxDK`Ap)I;@4 zA3btI@4ld7Dt5br#o(%dZ*qOF;1wx~<;pLA_)$KMb@lmEBWDGgc;l5T`S!I)zKdDS zi@)EsiPyY4k)QVP%ilLtyYg7`_Iy|7o%?z|s>`}h`S`t4d|aRTvESw@mgI?9@2fd+ zb*wS{kcGVtW^%!QvIFjy9dY` z^Ym-8>>;bSM-I!Lbf?-QZqAguu=4rX^v`MYb8WtCl)J@t+`9Is>>eQ;3 zI*a@uLq64X)r6YUe`H`yEtd>&x^apOvP=K=^yx3V_*ZLUPbc}l9wE2(Ry~jpdjd9z z)zQI)!IOfzOYWHdnxL1vv5m#CKDV>~_~6LEy0Jau&!ex*xv5x-VcB_l`mf5GSoOO2 zz%TZ(b4S3B{&)4dU+~fIJm8ggve{1NwSgv93jtX}pz-5wlitmDCLa5SHeWR}ZLhp( zbe8<_UU3=k6igmUjna z%XRG$r_U#+uRcUhzkfzf$GNIHo0h9_EF*Ff%kjK-6ERi~{N%sb+$;EjY?8y3ZTy27 z%Ud4#57wY;u38x~r}4k93-?~} zj_bl$EPA`tl6mdM1LSkQ|JL-w19qz^F?QzoYyXPC`Q*bTjXJ+I_Ve&{m#!PllT~;1 zS?OzJvXk6;uF$ z2ImH98Lc|)eJtP9Rqxw8j$m6##wvaePXs$eALo7K0myS_^^|oX9V>bvF=;) z#H#WomV9S>-NEB?z<;sW6jbcfJ$N7Jlc`-Bcqf$?t!m-&^zYt{@0I?KG+*e)KkIz6 zSvxw|G3njrHh+<`HZ50poRO7*b6)3SG5xy7)Yy4QdpOb>B%e&@>v@@LOpx?d7Ry8=Eef*`rVpl#n zOZfQoiu~ZWyU2dLsP|yhU4d?HRDBz74eVbX+?3z1=xAEd1pYnLqQH1Mw+Y;)%yT^yJnj`|HC?zxi#A;sf!ye_OBk)ch%#mlOKM zrRMM4bgN}^a`1xuzNB$Z=8}^QS#!@V1cy3L)_fh241NDDs<9d70=`%;nU|)&9GQGC znQSGGO>+U6m79t)9eA7>l%MFfM)?d(Jma5kc~*}djaOtmOa3uUUge!l^i*w?zEj%# z&PGpb)LFpKH`KERyUo0yfsH;mlwZE~c3g7DZeuZfckTyq(bUAC zlg4KH?-RT!=h8Fo{1hk|?u(7VVt~ijA-=E8ogXUp>cSrNt9jRPCg+3w!BYE<3Xf)= z^FgM)>|%G--4A4eKPLn+W0G6(XCED&x6ZEhm_NDm&J87>t@e_|wjt2?H|V7C!5xB! zEkmH$S9Vn_|D-(|>``;_&2D!ceHDYcZ>@bad&qImp!iTad--_%{t3RF6=)TIKIXqk zJ=>?gwg=(__KanYZK40SoBZABm+ZGkFd5DY+48AgoK-$LOM3%8?P>I!M#+%_e;a+l$Y06f`w}m!d8ZI3HnWW#{vAvG%(wCN38)yCpJ%7< zUY_RXT;|L74@4P#wQoq@oilA;A0M_=d@BC4&hXaoiicM9Sm(I(@^5!=LEucS2{du4 zJ?d>sz+N)NMjO{5-#)TL9pb6nv8`hF&xs?s@}BM_4{Jlc55GBw&^vbzWC$wx3M1@Iv3De_mBMXZ*L&x{1*rE-8c4=Lx%dtzd7K)zH=l8_ThO?gzOAu z`{}`t#a{E?u@^(De^vT;#F9N#YbB38yP*drhYt3ZFZNWv<(lsr zopnxrDfu&IOWDppIbjEz6V^$t$ih?n?7AS6@;VpLztCXqwF#~~iGg`@^$aj~M6fl8 znFnjc9MD-dz9lx=JMA9AE571Z@g;9}z+UIen*Gi)x$|x8ENj-p>g>?vp5>Bh-;jM` zOP3gsH|?%-|El9UYpc_*Gl!}-XY98Hbb@m0=yxz>wMUtL?*+|By;3Eq~NUmlwF?kn=YxPBI&G(3Y& znmsE5d)}Ts-rY`5!EOtcTWgxTPW@``LO$#c_zGmY!#1_?)uCd=$DP5JfM4Wo4aB*0 z=mQ;3ZvEY%{C{+C*E~6f&@UzUSo$8;^=s}iQ|4;zi$UwTD?jcnXPS*-&=06 zYsFXjLe-Ca$)|W5_xtc@av-v-b3xjN9V(J(x%nS-pmhQBHUVCw|3uBemQ?tBl25yV_ptc1ahEnP7}`yC%x(M z9J2PM0^3X1gSvjrJz~mSt$i_Qe+HeIL&bMm+%L_ZX>qT6uySx+__S3)pDTU&c|x0? zR_{aB{xiVev0mqLJoovI{aeQ@8GU|yeRD;?E_aAnp-^|3GjU?zooOlFY4@Hx%sx3? z8OTrFSH?r2RnEtGzV^WK!Ov9odT!=f{aLon2aCZFXx`PHamNGpvWFi-pp}lkUV44z zJxl!ysLzD|aG3B8J!=oyeS9y;cz@8x#dJ%U2IC z%iMoAh-2B@_iOIIJC(N;!J`6qyjpT*)rz}L4z)g)s^-?#$+X%r#}4-`JJjvi4)=-H z+jeBe_8k@2=Uv8Kg2(#|n{!+z?@P{hoeO^9qr>{qf%EPz@?J(i|H-ChFqGNf4Zp`3D9Y!mu-_`7!qP-S`E2dvfUW$yG7v{Ot9a;ZHwLALd@(`E5KC=i z;N8}oJ5}FY*}$fA1356iKk)uL1PR5&F8X>s*JZ4|E5Nfiptq0Z+Kk6oKV@#rGi}T^ z`X3d%D$wM;bpCg}^Dc`IJ;c5r|99`poBEJ9=UyGDHB@cy37k{8^cn4(pgtefIad4X zQvTJ~ikuR4bYvj^`u5V}T>+o7b zoq_ki^Vyhn2A&?jmO2lwSO(8hGQL#n{hdaqx>5t`wDO$pr1tyzbau2p$IgUj$&rDY z&@cHVvp*a7oQ-$RI2%=uY?*dO?C*Jc`>bhY-?ayZlV`B*^}))3ooLxN&1X8CNivt> z4a-5^h1M6V-cCB}+?5ZzGsn;ITFH=?ZNc_{to6Y;fj#b~QvXJU*W%g3 z-|O0(`$VhwIor-Ko#a=}Dwjp^xnI~amPcppD|zNhUb+WsgFL$Mp?oeKYRFwBFMC}^ zY2|}E&%A#NuyjY3d;@}QP7lShcHfVB6pJv^djeVSr*--C4YtrX0o8;;#0r~Dd zam6nm?nZra!ACyxq3+`=()WBA0?nE`oXo3(d^^+R-?hk=BWL9&XPlKRO>~h_y7#cM<0IVKjG+_A+zwIvSX zsDH;mylT!ntUNnIn*wn~`8@=hXYNlWW`jW*pVv%!H|z3TWGfr#uwFW9jIycbtHzen z{nMRp^3Mvip7LWbnZ`aok~^-QrQ)$%o8EORY?>A`_NgPWQ{!UP=cmRf-z#?fSWe!4 z<}mGCjNBp6*we?@obfo;avC)g``Bcx9^lkqbFeCKA6BieOdr(x8Lck{_ExQn4WF+G z@R6hO-I_RU2we$B^Jg-`8OAchdbhDyISMF zn7Vg{K{Azrw_`Waw6#*Xit=b?<&4`s6u_oq2 zpouYi7h2zbO}%K91O1A%x#Bxi+`XfHzH#sEx-{~7-Lq^go2zc*$9bO%_@HK=9jGI5 z;)^`Y1^WUz7aQcIuc_-ZesQol0rm5euMT{V(N`wW>k`O&1>YJxHc9!#;P-=n3U(#v z9|`Ul<#&wG-wouQJ#utm;H<4_Fz;@!bE8(~138tyh@ABK@|0kFzUzJSqO6Grxn!Lj zs2%&S48-8!0sY?b@Ucf;)!Q`vblOj+*bRX;)=ADRo%hIEuTu?r)~Nq!I_05s_Vqi~ zNzN>tWUuVxi|@w3nf|#u-Mp{vIdXi@kaj{quXf`Batm6yq@(O4e`vgwgW_YS7~_>| zls@NNW0zdxQ=9xWCtq8F4M9vk`0T=iACFk+qfZXX4tXB}ZOkLr_Q>tdU@lK}QQ$wI_4aCa2 z+OcwJPRr3eG{jfifGqEcfMa6ALpnZS$H8l3m2WJN2sIdju z$AD*}A%VkeC2pN~VpKUAY1FS~jho;AgW;_YkH`4qQv8|9nWvD^Jq_27A3wuuA# z#fQx$SN@I&$gDY(%vv)h$9^_%3U&r_0XxKb2sFI(mxZ`JVLYsN9d^CeD3q z)^)L|yUjha5ZpUZ6XolWv07Vht;j{M>(lvuwX&ybLH_WuziI(BcTymRbY7pm6%%V> zP4cxBC#-QfZMD=&3zd1;FCUrs{8IKC?8+l_p)RETPL5J4Qm2D}NiL9-W<@~}q0UOxq z45H4P`c}`HK3=}*J9lie&bH5FL+|??BEPr&c3(i-|0T{G%64%s+r@4v+ka_f`=3O9 zZ~Gr)od0eS&ktv;^)de7fvH=}*+*8z{R5e(ns9H3wcLxpy1FUgTjhf=h?5Bul+k-Ku|gtTQHl{dzs$JfBtt?%=Zm&w(M($X=(BHqFa#RD0^6!@-{!zRdNj6{Epm;&-fN1M3}Z6pfu*>gc}k2`S)G<>1AcxMztvz#p z7llV;znK63{meZ+F&GX5eNLP??F&)6zz*C(aVe`7U+K05fH_$>SC z_%$2`ZV~tF6DN1>o<_yXc-nKOkG<#EQhWQl?f1G9dpo?#Rlcrh{UKD7JGo_#b6EYI z>2D5F0+Y{ty}TE${M>pXSL0{Z$--pjmNnuD;ThqqqF)HGEhbH#H;X!HyMwAr)_TUN z?;iH?&vWXcsryz>;v#<2U_W{GKPdZ&=>4zrlvm^l&)H$9=au~K4#eGadp_70cpiE$ zkS}N6bKU#MTrdQh9MxL&`+SKh+sI(srsy?Z(Z(Cvm@U@tk}+F*+n=1V*3VsbU}_ZG zFK#|R#ppD#I-Gp|<l>oK&+Cu0 zapmY))X7nq}JQ` z-~&^mI{4z&-gzw!y&V;+Rk4Si4+)Pt5hG_3Rj0n** z8H+1kHDvF6Fa%ohxEHE_YWkZ4Hmwc%n%ErsjOCNPa~Y3o!hUU^T8>>>A?en2Lt8imfA460 zU$-t^WDS8v-!F{#@1MC|-}^@E_v+TC$@|3-|F({wzW0yTH+JjOtP zYNytx$@}FIznZH&p*~N@nZCNMT2MpNa(!*)HM!NU4^{@fowv)_d6iF%&+5{1cnCB) z)d2ge-|J^r`L)>i#xjS@t65YlIfs(T|LZ2)2lST?x%yxitF0M}Nx%Lp-TD{OrasPl zqEq~wE%f~0&w>?!IW{?OZl<5e|EFQ?jQMH2{T!*ij{hk?XK`8lS_=D@!LyW%FV%W~ zC!ZF(-Ph_yZK#(c13W7OXYi{7b?nYQCvZOSqm^%G^UA<}@)iPn?Ymd-tEqiwgpMK5 zE)J|agU%l6+}52!pLui$=r}v@{$Bh$)88D>d2GODwvByJ|LmCy=(Nrkc>}inT5NPj z+}~o_rhuNZ2j%l((BDPo-B0eL-ahlaePSvWA8LBW--99Uz3o0vYW-a0ru-2zcal7? zmFY#D|LXU4xSOj6N+&*X5oC|4wY4yyD-RK3{tNXHDU!i;e6npY3~iP`=gp>dg7RNj|7Q_B=B< zFHqBu2{r_419tG2T(QAB1e)=>KpgbRqKlqd+nN4cAeP4ma?HMQK8>x((_;hv9ue3> zmOUuh`vS3E8Q`I}d}6bhn!hUG(+A_L_}F7jzhsSbPrkX5H!Viam>AK)_wt#|)vp}) zzARyVBMU%`C};xYjXklwRdOwo7)_H z*67mb3qCPBzV$bTl4x-~^`t-@(S1>VpJuN4$@j9A zezuTlKYRG=J`yXo8PiL)`6Gk=9-<4M^~w)9KyLMSroTC0M?FL6wqEfpe&f>u&s2Np zbPw1o7WVB4=tRY#{9#Mk!S)@2wl2QQ)uRGAuXxp5rVic#>PP(WRStSR)~^l3^&x@! z@cEE^Y_HhUQNGE=lLP*W8CvzqH|LBz^Ws1TzD>c-U@jovJpZTJ#om%jm$(>Loj5P# zvA5#Mz9G=?ifM0u&7tyEKGYc_XJ;@M^!}UYKOa{H;{G)Op7R6q`g?*|wPjxJcQ>A@ zyP{;uxA&J{pYbkN=U0Bn+8>Pllbb&NRhQ<=?|z+5GQ?nvzHH#T7*?%|gZinped%jk12XOJ&zZWi-f>86>Fc>)uk*Q7{K+{h(1ywX57<@xD>BEv8nfH|SiXwwculM}1az+q z#Kak5U*$^O*8I-&=h|8?e_Af+CSN0;?VbZepvjMzER~=$7RO}*(c`526V7NEREGz=@T#K zUQ#RQly)9Gmf&jB5kU`Mx~JE7WJ*kt>2r1M-W9{>y?|e?s~d?#uW#0=7J&6#9+`#BjdxP zJ?y(WSP_s>wP4Y2sCRI|MJ0@U2_56dahrT{?>pVx=#+gU)y(OaDG7Vy@KCK9P#vD zx4@^}7?A61@x$4ob5Fod{;ALF0yRSB%78rQ!a3U5`qr)Cuk~~%>y@9yj6p2O)Wpa> z`i4Mb!=RIK;dT_6p+Zd={?|J*wY}*~+HP3GP*u5dx5#YUdewn^!xjp=F4p!b~#pK+{**$}E zgVzQ2kw;d=A0?L#{hh&FK=%G%F_5GAz+Pa(`ryQXorf!zOtQbwa>-nd+^|hz%jfc^ zuXXVhBWuOO&+3cO=0J?x0rFjUoEm`R8m;l+P;o8(OVfW;Ajb5liK!ZhnlGvstNP>t;sJcmNnj)e#K7Atrb67 zd-Qu=I>mcWpk9GZXwPTvvfzni1VXPRRT?9{l7#o2L2iGeh}4 zEe`bY8J-fzHG79Z8~dC;({zit;N>$pWwXBb2;U3iIY%bD`FTmOKaj(@0I&NJ-5BtF zPax*o|e z+Y+&Cs-d>mc&7KVbTj~7W=-eMF25c$W zbLq2VvCZ{)Q+q?8(Xalu1=|C*_^cu)OWD)=8uo+rQ8pf(IsURiT-k4rSj+|ND|<^9 zzr^W=KwBG-!8h}AP&rNapdaL{35v(rTGy@flRizK&l*0BtrrINJStGLj|uGA9mqr3 zXfHi%nh(UD&zA=01^E+ZlYc9`D1EZ5*WPp|_Foz5P9dLv_{ydm)32ILccP!oD}rr- zJm~`&byoMJ&u;dLkvgUuo*e89HU)Up0Gs;XJ1c(f==!}f6{pg9MAkI&?Paqj7UFkO zP&~hr7_jf$KrKBnV2`m{ydubtQGfQSq3kKU_NKo-U~}=R9euHSN`MZVo zlg~D?&6n@i&JHwoIzQG{2V|=Oz7K(B&V6D|OpWD#E?@(DZwUChHqhuUd&r|_2sFCR z3CwH5`tYNO`o z(^oss4%C)Am!GExzn6<)2-W&CSbm{w9|EoHwZHmhyE!1|lHef$o)v+{9)JHtdse^} zeyLCMwbz<`#=YzeC!a5TFW8>=ds)W&1O392M&qYu{Pf_P19G1mTo>FBJU@6*@ZG^n zgI5Hv3Vty7;o$Ybn}fFo?+AW6cz5vL;Qhe|gAWD26?`Q4Xz<6up9k#uSm@sepAJ^U znWKX{1Z#u41oOd(0p5Fro)+v1&I0{szV$?Z!{YxYjODU!C;h+l|J~WWVk__G5M2kDc#+ z><;b6Ye(Z_N8@$fnC*Yi*>3!Yqwyb&#(z8-|H)|lr=#(ojmCdI8vjK%7B6>h`NN*S z?ADF{svF~Xwu;|)bvMTUv5w#Pue&jR?>hbd_1zf%$2)%Gzv;#qPVS-GhPp#4mnoA; z+nxW{TIF@TX3wtRQIj19o=HRccL>-u=BKA>VA@*MgEjuG3d+B9Z((oM$}~C0wtd$4 z{kJpx-jg*ozB?EK?=xjL{qEJ$Z(M#kJDPnJqYdfT-tpSpA=Wl_YwpX^m+nFN*BYcb zf757|GwMD_sT`d{fBPd{@sCCTx*avOYZ;e z_Ob7iqwzm>V{(=&_fy?Ia{p;G{&Y7kx#H;=`_Ea^_iWx0IF}mT#q*g%@bLT5!O8~b zaz~IWfATIfUSFMgbyx3@&d)c8nce@=>=bX~f9=Lg$;1C|9e*$XaZUdJ>(-Ye@83Iq z^8ce7_wpY|SXv)5-xRe}Tm^k8o+FmQvtk)ME0@8uY8gC7E`#T&W$>(C2G5#h@EpAi zp4-mgaR*j?s(UbY=ew&tbF+0)i^rr>cbrqg__M&tFP@tsEFJCDY98IA8c8sBX+K7KUbFdEN|#v4cD`EDF{58mPK$Tbbl zyyvOsxc8R326MsYK#Vp;hI`S^HyUql<6J3|@d<5wY#X20#@;#cZ)s!CA>*xWtd5Mg zwQ)T|x3{sns~oGf9hp~aH)X;7J|7H0)tY-+>+ijjvS)m!(Rp%{)&HA1ncITxfqKyT zXGuLP>_4U1SU%jnjmw97v@sv}&2BN&HU{R{b*Qt$pR$J>jXg4Tzx;nG$mdc#wN7f? zKj){<56={O**(|#V(U(-uSe;h6F7(V^9he}eGTEt^vSe#Y+#-LHDAwo@1&Z0O>Hhr z>C4N70r@4%yJ5xm#Prq0MFBbNuNYVUO0RbVxx8m`Rk`Tzx7t_tni||0-toNgxQ;S4 z`QD7mAG_BDe2<6;b+5zOfyRbGCvBMg|3IAgrO%g@LCND6h%4xmEgx#+f7G$!^aPoaOVt!2^4@U>|$fbJT6byk@ zIkb-VErEXJtz^6|bK12B$mg8JAI$v9fG>2D^|C-KS^rxD2jZg!#L68ePFlt2-1OzE z&!08?V(a;ZN8WoLccc5sUOBaPX;Al<`3-@yO;*jj57lAG+@HR=s=vAP>8kyn$;S4p zMZDH(zcJl=1AVosj^_gV=r?EoreFxP#bD4$n^mXm6g$3(-Rd@0ug3hU^JQ+99DLh? z?ExPa0{Zc@n~f+t3v~{*WX_&z0}by{0bj+R?`s2d`1H$8bL>1V&`KtMwCfI#$(cV~ znR2Vmk|}oVP(RDDk>AVZ=O_NV2J?Y9LOr7@u53^Xn*+5VUVR=ioYawevgh1DzjA=O zLypJ|C5P;jLyb>c19R-z9ZcglS2ZFRo|EHo?I)8R^=xKKt;v->KhzK1{2{CA@r3k? zf0`|x^}TNI4#hv#UG-GwcA7r+_43ped3|iWTb!CCjNcE$ZCkKCutyVr{#7pY`BAtg z{d&IGQ)i;;x!0TJgSE*{t>>R+=V?pWxiT_KvXwt|uZf*=iid5^K;fM9>+J4H ze=#^SV7n&H{MPvT&`Iy+`}#lgna19s!+6}U>DPME@%ra8?(1$c zhCr)a=!^Z6bka)pf7SRuA~p`U0{oe^&(F@yTI=J#IeeNJxr4-ivC+D-`)8l~Ny94# zL!gPhTvcv{^tC=GrK57^Yaj!rwA!z4oej|IuKQVTFAlW->bV_aQW$EBaPmY_!=l#?mCC z8C4_sku*(8(+5ymr!7#*BcgDCa~uvX7g~DHIfX)@J?8+ohc{d+EV)Ab9eIBTI;|5>%ac5_1J6gJ;ttSpE1U`Lf^y=)94fPMVIP~kHv@4 zr+IgX*5<`_N8JU{&P z^8$3~66_S*C`UHyC)Dlt{yyPpGJo^mHtK#hRen@u`eMyz4+bwTY!Q>uWor?1yL7XJ zoXCVO*oXT~+nwE$Z5+${L6KX~DVAJ*@Ad|2?uf`1V7|Md$mF!w@lzCz!>&(#g}qp} zIa9n_=~oisuW)~B=|*g@4q#(!L%L1C7$H7)$*%Z}F~+~+^_WuP9zS76Yfqkb_z9oU z_NEqXi3{lS0>%tH(mpdDyOn`wx_@E-K3w#*M|89a>H1WLF3lSqhXlmNpK0x&&C>#O z?iJ963%)n6gRjL@tai5vu>A?a!-6@%g5aFsDZ$$X7X0Z3@HWA_1>Yz5sNlZ|epB#= zg1-@5B`3UG@LEByV5@+4$8HteBY2%)PEZwmliP8ufRsQGeGO^+(sJzk7}PZ&;)Lo;B)^txm%v}KXn^HUW z9^qWpqcZEnCPCVU53kV={LMGHHE3JOG<^j!g>BIz-=wdM@La@)t%>8hw?S9-Q|$Gi zK}UGZhzGdP7R1tv1Zg`In)KH!?%>6}A@-z?(@py55uW;VKk2r!>ukG;&Au-Box6gz zp-saWDXQ&yV&oCgU+I{9bRD#%bUHwsm=f2t1@xUg$-gdy13u&5OBZ!jp~o}p_^dPb-!Rgo$0bz4ey7xsP3y7KDqH< zPCjgmFIn@k(^Kk;tC^i*;lGlATt9b(eg2W?ULj?W?`fZs|8l^y3M}HQT|iuYAZ4Sc zh2wfy01a}RJs(h>>#M<@vE*n4$lR*#UjiT6ll92rkog2#*;??V@;U~2fiqm@idewK zc}`YX`RGq=kWUS)eJxtx@>ua*Yo7Tc3d|=!-dLN`Nk3?PDaCj8_6*uCZisO-v{>8{!*VnU6@# z2OY{2GsM2dY#75~%n+|!#%HJU#s_@JhZwO~gExG_*f(F6R6*TW+LvE0o5zy@De=I{N;Q06Esv_d7)Y<>>o6#0OcBA6eex z^I`nZ7nj+Clrb6Zb7PhNEdYAw)~O5j+bF<(*almMF~oWu#t_eyEMB+o9RuNcc4O9ZO?|RwkBSVXV?~f!}3v;xlHdb zMMvy#B|3)vZ*jdht}&*+`3C!wHyO=W#EJE{S9!B3HVb9BC8$%j!QLi|rRlcBj`6j& z#1XzCw!^&!^(NyX<&oh{0%GV>08tle8 z!o1B|oDsZO5DU1N?_x5#nA>79x-9mgwebTUdiEve6Y4|W;d$8Q_%RP4>w*CO8-1C% z&ibPs9_bj!3CH#S$3Wt*ShfJd7+_vAyWw|ih3`mhU15Gr&wtFjT>{$TSNuY`U0^W* zjrl0-1A68+=(&s@9(h5(0Qy-0jFE%yC`Xhc7wwSeumF12Y4Upn>`e@Ba#1#(1IiBy z;7?nlfhRc1#2n=t1lWRcLcenY`X$f$8_IR7%FIWR06ktUur^^ILOWSHls1#a`i72n z@C;?MvdI+6K!4D73Xq+>l+htOSY zyoe!mdZnj>uf<&2w|Ujk2AcOtZuryoe!*>m*9ht~1w4G|pOjeN=gUeQPk6jYKp%Mla^0^6 zTRqNX#YbkxPUVS9W2f?O)}&*7G5F-1J#^8vx20Q&;O zEZ-lHM>q63F8J5lW5(+Hs{tk@hpk=20QM(V!Q&%rMG7#l;$z;O?NEvj_6xcNv4E>z zfWNRaZJO1?pDVOKzB?kgM{q*$kYGmeh+si*M(_r~HwxY^c&FgKg7*tn1V1QvPVi%b zpA>vl@NvO^7kow@1Ad{*!|!50KCl8{-!R>3WT!-BkkcOTy)cvkR1!7mH`N`PTr zEckB0ZwmN*yQ^i0uNMpob_xy%?h-sGI4xKde3#&d1RoRpf#CCk=LH)#YK#hYi8c4i zj1A`JY|>Q?Pb@dXA8mnWj5nkIh8B42*o+=uG{YZjfyZyn=pSr>Kh*+1-vVE5foE=R z)-Q3>4FCET_{A3ZY76{Q3;c2mJTcr%p0h3R=UU+3)B^uaE%4vi0?!y~CeOQ4col1N zCUZXHn;2CHyK6#!nNQy;*d!p1xo#2=*Ic3RXlF4GJu-9&xZtlL(Ukw&gl8DOOu+RP z0kq6BT-G1!JN-Q=;5nt~81~Cv;Y#{7p3IT!p}%gO^sI?#{;aL7?A%OmY`B)*QImes z_MQ|CHVyp>joIC7f^6yjkO3csex$AWyGQx7p47K$rz$6h_1WK|ecDb&KX?W7lcF(w zt=&-2F4PA(xzNx2gZy00_zVjl>I?sSA=U*ivr}4s%EU1~KsEr{s|C~+woz zK6|tBSMrP*z6Aj(^P=fLsyx0$cC)SdaLnV8gUfUK zNz;QnE?`EwN`DUtrUh^EprmGxgf2NFM}B;lhHxLm8pLH|fITt#-Y-BGuD2zL+i#M6 zi=ac0p8xW~g|5Y{Z}iyeiG@CPocJk8}Ihb!uj%nphPk4oPR&iB3aM%gGq2)})bW^s$hRj{Y zn>yp&ivFo}(tm3Udg352Xw{#|PK<=I5Rb$HK;0_^n+5Rc5tz;1th|moTwCJH@Wfp+ z{99V!-_`>E))x4;r|>Geea@B0d_L9IWPYp#{_z(0CtBb+gK4Jw8&i1v0v+=+>+#bn zl$0{|9}@hjfS92kTJ~4uk+<0y@r3aB=PH4FX|X4 z)UD@?+T^tHNLyqe7MXuvEyxQPqst<)z8S;Nr2B5B>mku)JT1D}zSQPJ#v=IZ1?WLJ z7I2wOu}6o)Bxi8sZHyvc=tIcZhY;gy(V+KQG$Lt9V=~h}vNQf-0axt)CT-I`HG2B) z6`;?6U{HWe*d2bXBk&|1@dxojy~PSXplp74NO|IbI5{rB3fKW2T=0BEfQ`Xb1m^_E zkrlw73p#i}XR^l1bH(m&Vq^M#slfW5^5wkJkf+%ReUQ)eA=bEPk1kxaqyJXAbgGUq z_!bF9JQ8zU$nUc?`OQwyv0p*fjKE@#IN?H1>(_J$V{TIQ$cETx&`bPHVNQ`-JyR{fF0Lr$6S+chi}(vx4B6>?9{4VpXy#DFdN}BvlF(*j_7bo zz-2aBP#*b+buRGehp+Dw=x03Kzaxe3-m1>cp7@#h6W%un@KMyaN`#F@n}zCq4racg{URXuc(ARWJUPC{%VV>2CWPQgCV zJSl+waTZulngBesztFJRvdA4}-Fy)%sd>GJ~m8xlbK3IDAQWv&mZOg-ZX9QwRRIAp^Iqe{C3%w-r0 zyv6W@^3<7Zb3q=S*xq=4jqk_gc!|o;hcbUl3z>h*|K6C%{0WtfKkEf}?DZqU<74aN zeVz^)<{+bc%=6nLoXH;Ah~EIfkKjl{J^nHEyJXax48+pU`R}5^y+S~}$wd9zeEYB+ zHh)a`wEdtlxuKZ}+M2xJ?-Tx7rO=b2C-_6cBRlv|hh4(sZ}6et`-Kl>FkeH%e8Zg8 zE5Pre-K>wz!kdl%r@o^_7VF1sX*OY;L(6#jVbLPX^&Ur@p7A)w9(3R)Jx^>4{U)Cp zZ6YxNHSGpAGLTG4N^(GPtXf71>B!jE~Ilrb9i z^Yy+Q`LsvrumGK|6?{QI#H7Uens)R{N*$>|#^-4du3vzB*x}pt8)wj)eJ|IRHq1G9 zsg2ppY}u?Y=<(AHqNm>az~7WZxu7M^|2g;_v#iRA}Schnk0ltjW0l}aE9>8&zZgO#ets=n|!5+a;!JOc% z;H?7IqHmQz$b+7?wh_zN0e;AgT+}nC<1^NXcd8w+9JcFGnReLXa&6zWj<)o5LG;)u z>u8It-zIv~$^37&P48*VW{ffPCQdp8Hdbu>V0Xqf z@%8QE&v-*l&WNxvbteS(3%*xCd&Ubkh6m#=7I0CfjnH>b;t-UdpzWs5Wx2lL0TW=iUnMu zKJ<@F$a=Xx;fuYo=XXfpN1+$6HlZJ}L|&paJSWAkrVrx++16@jI=xY}=(JPtKJ|%= zBLed+v5h}60&IaE_$C%`L62=VDTNPZ;)ZgUFT;;<2M^kt4`b!ItWTrC9~Oi77Q03Q zd~5fNCzQXOf9?LLUv$`w7^ffhrSL{Jv%ww8BfIgWzv~4deO6_BVEnKNcFzmU*QOUK zac41#Eh7Q)6EiknV3(T($b$X9Q}(xcjk<9GHseAT<~sO7PmH{O4SIN>8}#%`TV%tJ z;D`~*$b-%4%WQDDaf83wbFGk2j2>oGn-4*E2^4k$k;XcL%! zkd40ZH$1tBF?2GT&B_~%$%0M4OE!v?a?yr48QH%(WxF2X(4RKn6SSFA8K0mJHbHjy zAbYm}Jo?c$b{rCL{k*?FvVF&`!V!1$f!)mpw59Gkf%ybInFqMw8`6V^j@TkjC2CDS z=C!=Q#>n-`)1JQ4W0cr1ox}RW!kbOuO?$IHbj{j97q-I=w6hp68Je|)Hf)Psp}$Xn z-ZKK`o0kai1w7Fk**6MkZ}M(d-rB~>{aQO6DrL;!})+g-P?aSDPaY9>cPrtNX zQ5){9OmCYL@xRf0pXdL97W|h*3-U3q>3_FJh9|Z$UFnOMfsfe$of$u-bEG^vf4@3M&P@VqPuvr?_=K2(?gzZy z|K6uRsML6e_C*$A8<`o?|;JdHj4|34RF{VKVuX0 zM7JTIU-9?ev;&7u&j@Eckt>V?WIz{ujNXic9~MLOcu2sz-`Ep6?EfE9b@&@Qp&#w( zuU~*KX9c4IWTD@Z;8ggs%o^SJT3gK{T<3@1;kM(gT=-hg~xu#@?0Q`%?0qm=d?#}V$0gX zo3_{y8|MY+53e8bywd-+rK+60u`%?2(2L6L(?z9+mMc?TOV`z-9ccKJ=~Opr;+QwwI%Bqkw+!lkqWMpu6F1zlM(tk4^gp z_>l|!q`s4pGIPaW2yERd`}|?0*6v2-FR2mZjP=B17*`%$ssG?*>diOo$+)l=IApQB zjZ4P0^+Ss8Ljt*K!>6=Qz_*mq=aVW!!<-8qf1w95AtU}_exOX8@xJ-HloA6!mXep) z;_4Ql&;OCCXAF)D;DzkwCv-wK^ms_HTYN(KiFLElk6!^#kvLw+_!BC`O1Wb9x3OPh zf_|a>&>FP(&1gT|gccq@DZI&^_AxqR|yH#F=F!;d!7lw{Q~mD z&VQCJ@TU#yJ9a}xvnlcr6Ua#HGG39D@kT7YN?^2iC?AezlY{-S;jj1fKS@RxeHjir z!y6p3{TInb|L}pnO)0WKuc{i|f4vNywUuf$8I*NAZ4RP8u9Dydb+S|GN5#|hvh@kS z(JwZK-!IDMp$~pG@Ii?GaDX?PV7op6{tx3Nud?}@lu5U9F*Ta*!@m7K9h^)wio{TBz!CBvC1L}~^ z>X3)Hw|4Nbx(?-uQ>%lA)e)1lL(dxov|}uQGazO@COg?aFSK{0I_O^|cuIgx$ip9- zQy1ENR%K!hdCcaq@@8{&<78n^f^1x7gU6M});|&08XEdDUROF!>BrijdzYXhz<=n# z9EpF3m2VI{AlN3b`DRpkbhP+=yYgK4{zk#ir~`aUoLQSUDo-2i`Ln9G{+S2RAG?72 zNJqj4nT+PB@|3?`08fCrwf2p6&+?#Xk%#uilQ|eZ?7grnam|H{MuSX7gDubxp4bR} z@F4$gL5L?F^8pTfn#|$+Xtqh)llcLE(A=xQg~nw z#&#GR@S)wLfc$;|G&1pqSip5s0FA{9agw(40pXAhz05a5%0v4KjeT&N1oUk*=$8>7 z8}?-$qf8s@g&bxN^aD>H*wFT))|csbP<8O2-Iu$L*!#IPV$b3t60P}qxAOSFzXUxsIg>RYw@#AVur{vqZqcIfYumubg(!aQ$wr!6vIcavkM^8d~AAZD;V&r0!U zBp{`q|9+W%((=)UK4|wpF4GRVn0rHc%=fnnZ#Mmf%kVJ2FrFs__X~(UlL+hyvjWC5*KzkZdH0pMmWw{ofwAzAfH?vg7$0Kc#vpvu?S@#u#Tc}?8XNQr z)U38w>rkFH@I;m|U(P6HEk-~1*_iw-jY;UjaR(1@;XV``dji{s{*stL!(4KUpj$u; z&G?(=Zx%ekPp57IXG{Ex8eUHz?-bd*e77@ae?RF z!D8w@mC19N-N?@g*bCVE)r+Z2FHY4{cr$;t#6aD}dL4U{HWg z0J@qkpHKOKHYO)Lpq&(;|AYWLhy5HofJTe&0;}^09x`~Ck4>4Mw`u{p%2sHsPg#ObU;^=9a|$mb?Fp3 z`Wg}tI~SYy9zCs}Q_9ni>50zhk**hNUGi=gz1{C1H$0KmQj?wW0-hAvBLOn3CF5GY zU~a?4_yWH-(}y`Q7Buru=nJzE{N61vpCKb)^L56T(|rxdn@-TN3-^>Bn2pW9L zST-LJXY@;5v$YT(V=v<|r~Kmr;_+rdScjZu2a^fi4R=EME^DKGjC^HYE z4`pOFxtXW%KXM}rc0v#E$V496SiptvCj{WI0eTP@_!-{g0}Qq|2*} zZXE)PePpq@)ocl0Vgs;wbVzydoNpnA*%se0=TQDSK{%eVFY=*-&8_gH&qD%qJ}5xH zNnZvBj0@-wy<-8_NdavcyTl9nAv^xqEWnQNCp8(VLq_BRN8B@CbP1qMcBd;J;Zw|K@x0v4AUff9tVh@!BqY z=u^m;OX&MP0Xn3|5P0mug+DCDkPE+~7cq;yxQK6b=Yk#@bPQtw`H?#oa1n3F2Hx_a zocOO(fKA{Pp6Qq^v280`;wyOX7jUKH1zc!biv#>}RDeG8j~wq3U?a{F7*lp;75WmJ zVHe~vI`j?4?iQ69OD6Mi<>`mMv8CbZ6JA#bxD(1l8`9ajC3J1hfQAb{FppS&p)arv zeIg%mO+FTI#qMu?9MSG}f$6_l`Ltd)3upaczb~g=$cG=WO}G{jbJ!>^Kpw_|=}Su7 z5Qjqoxotxn%umeU-2!;i7O;G*e4Bujix{IlcEE1oT_Q5||8OtkQ=03R%+iy~3dv7xH|$bU!Fw z@TSiJ!Jq&+7y~>zM{fE%A;6b+2&`^YdFpJAm{Z<-P8=H@G0}={SatL_DS-dgf*Aq* z(m(dZALa*JFR6!bk0A7eitgU(f69^2urH+^U>qR_@rY001r0u6ZGa}tmp1fo@&0P% z;Xzw`g-_CL7>l&A_{%Ggjov8ODfnf{7At*TfX!^)Zk5N^^v6DKNFbFqe7hgx7Q@J7 ze4vL8yDs?{wDJj+;br9!l|%l_xx}c^5Eu9RceK!x{R~%^;7a6$7i$Oo(ewv&juPt9 zF5Ike_{8YIoe(bMkBp{2^}nL;V8Fp2fIs+m`0r!D;WNWO=;=)_XrKRw7hW))*y^`b zCT?lNbtzSTo64cBh#C5UCn>y0*#p9ZxoDT#r1hYV{yP4yvA>V$dmDIK{rgl7`-Atj z0#fsn>BzXrroPv?O5f{*`g~g7u7u?esvPo9>q8vV7rrKCtdTNbkoNm@P$@Da+hPCB z3uUfv`OCVWx>W{`?aRUwPwYiUm0BOj1Mlm6`Wl~_EE!+U`n1od14`k&Nw8hK(UX4Q zWwe`pnK|Bk1^qq&_T$2y(C-%fiU^q-dc=q^OuNGZ@-{D!563%x<(d#ck4babfMpl}B&<9OAKamtani zZo}MdZLSLHp+iR6!9P8(Q^p?D<1_S!j&+83u`+t0FMZgWVRZPk8C{4^zjGGyGd{MS zVQ1nGJ-E`knjMhu1_AP;qtW57UsvapiDCGspNUAl8a?&MbDIGDxQv(8Vc%W>{umI1 zF=sS;g~yJ>8ZrU!K{jlQ-LMH`5jOn_yXGi*=im!50HOeGyB@-zPx7P@V@= z#xB?n+Arq5sa@?%4&;pmTql#{itn4=E_#b|_6W8oTJL?+u-ckF_=z!Yb`I}{&>jDo z&!IgL&@z^>4R&E3Lr>_rsKakYgRi;;;rKhHGX3TS%we&Bi}?{=j3wg4bl$8ybPoya z{D!(Ohb|N1W3q<&ARlF9VH}x$#22f_K`?#OosOpzagi@!apy7$B=;QM>UrstIcn%@{A4oWem}lKFVqf zp81P;$MD~$djas+F08}9XH*yV|7+UALu+Ff9_ad$!eifX?`OP1TIBeEXyM64pVT8O zd)0jc`sHHGT`Slv_)Xb^IpHVd^Z})V0(=bMvqyZMxPl)(m=GWRuQz2JMFRMu7qVaz?&r{hScWJ0G~WDa`*r*V52K@OViFZ_v|{Q`LB1vdAPxA}#<%^&1# z4{}&}+M+wxgn;(gGd=fWd*p>DHX<%Zlx75GYj|}C=z~0ZT5Qn=a9qGl!(0Qet%6uU zEKyHC#4fVXpY?^En)z?1@V_OY@dLEBhwo9IK8T$(-!NV*4h)B0^abDFz5>3@P7^#p+AdF?0~++A3We63%E`uiCgb220Mf!CZQV=(DwH~9`Zd{{7{PY{Ho%^Yqiz8_Eq3h85gs9(`6krGiGXe{25+x9Q?|3niSn_n4+dj-TXeKUqXCt%-b&$)r_B8Wy5cwD4jth~8F?QQSUeh@cElI_u@^ER zukpWCdF;iW0zTl=b55^t&>`#Pc+dx6yv^>&29En}YXK9-0Y(*&qHkrqG8tKp*qPX62#b-}^f1>ui362Wwd@ z;ELVfWL~5XlRdOEVMRN}20D;OCsO9-eFEyZEQZh#y`Vv^oq|uxZj?>F^tlt`+;}6$ zh~PE>HpDjRIvXR%ij3Cg4&|{2@k3FTYtIQMJq@;iRwBFK+9n?hxZs6u z1A;*Teg~}WLFMTS|DqFhW`Ek^&%D6$#s^yJ7<1ThNWk@n!5l<lZq7!_VkEBd~iOqnQ-W{KPmzXZo~yVwf1SH3_>SPq%>eEj@?R zpS7ib@^ga61;{}k>H226|u)v31W|V6kZl< zA&*nSBa7*PeI69_3)1t7(Wpge2-$=j?_?&r7;y9bdO1Vx7ES{0!xB#886ES77SQe?CqHQ@wv?f*qAW{9kEK=Ljr6} ze8LCblLBJs|5Xf`KFk^Lf(BWd;j!~XKvPyeTg zK|U66p+ihY7cp)6KBzqHu&LP%-=Y6`0sRaK;7>h!HGI}3C<#UdX7luV#op9pCC^1a zzb|2|FY}%0$QU!6^#_0Y3-xSQnK(2((19}7y9I`~l=>W%x;f<2LrNc{W<#qtS>W|q|GtjV!51BN zq~7a!m-;4#p@WanEeenA!sisw7%g&H8&d0gqw@EvExK@-jL=|9=3HpF7zec5E%-zE zlGwUh24Sv1NBaNJYm&7DpLGZZ1cL&z9dv5y<{4x|E@BLN>>bjx=1^xk{;B*)8_Mwe ztjf$!pA$p;48WUt8kw0Fkqx;<1a}Cs0_KnC`D@PqfHFC!~_ zxzFH=1kix{uy``pBikRT-f;Ar5wx-mys-zdPD(rMNqlq(&>bAQ>=hUeT4KTC3VLjW zjK3foQExW;8I^4uh4>Ezc>2ID`oH$gp!ql!j;mjQ54a8qt`!^0tMJ^u>N2oiU~DCrk$7FA|vjp`-4DI7%1xq@3o5Ew6+hbhHoeBPoBQ8lxY1?3y zjm6^smI8*ecElp}T+|V7$c*gJgtEh%ORvqjarejKN1p(;=@HNtem4p}FC_jpdEw24 ztl&-7&xs##WBh+2RoPdnmeMJamb1=M}P*ZrvP$HpLaf2O)| zrChQ5o3#1!Cj1^yJ-@vN->((W-;2Z(z3GpTF&wg)Jm2T*X$KB{C8pDNmr`WL=M#ea z1=noC@ViV)PM|qQ{Px&vWJoL#pV%|dT&uHGFj7;dtxM?M)#T@d!USRUV6M0Vv zupzd$I`Y(Eo5uvyPYbMmv+|}Z>$Krp*%&!_rZlJ&8p`20(0wXjCx8!hjHOm|$W4s= zt^CuB23fHO7do?V2>FJx>{Q+J;sefpyRln&$`+?#?7@%m)Jk88UW+M+pT6x;M6{yIp;8SzqW$|D8%F1jI=! z;4<4&m+r^bRFji=C8U}0?Xk;dUl-yK1Nsp6DvvY!hIP$&r0FfzxQA$_3$job%Bf=Q zUe|QN1|dx-hxHlah=a5)jM0#Xiq4*l*>s)B%{KFT=+m)?uDgYw z5a27~zem70Hs4Vn@=?*%agWulJT}4>Hm-?%{E;3Hn}nmEv<%QwcO`vn6diJ<`w(iC z{=`7Yb3o-mL1+uB#~)!mz6oQNdi?N@-VZ#}E2`Wn7!q*t4PsdS1Ha$F#_Sh}H*95g zB_GbgtnbKX_4t5xVH@ntUOB`OW5g!7u>b#@l84{)25idsIdq z^2C$L#+ZekxHWqCT<`HFci7)zs{d1|@==wIKRUvn{X<%>ZK-yzOqJU_A7TV~;7J}G zLwWv8`xxu*Db>-R+}of}EBu>0J?mene=9uqYVc>x3h5aq;F;^ehw^NLG+kbF zVY_3g^1gr%@kxKI>1jSgsditJD!)A7v&Hk-=J}YMt?*ktJ$4TDPvb*9{zPZ2#`hb2 zd-i}~`!SDa?h5h9g`T^w5YJu=dd6(Xrxl(#ANpHT^uz;r;w+85AF4S*()r+D^-5l+mo>!u07=E1lXE6l?xe*f;7&`c0a=$_8p#%{QH!j@MY#e z?7>*09rfQCAu0!8DIQC`&Rg4 zDf-yc-Q^yvkkzT2l3 z_crgFJ_hxWi5N0_wAnasp&oK%cl3Y z`trMc`ixKCCj8_o|#R7OwwV+`Umaj;YH(#2{O;@K*mnyj>U(8n;%QG`mGll8p*{Ndrbj8yM z7d9!CD*36I<@x#ZzP^rVK{s`Jxtw1rR?5D?;$rUnRBmCRP@V}f)1{(`M2vnTP&CD!@Ou&WGx^~sZb}FuF2X1w{<>`?3a=Ds2U6@KqQOB-k;OkQT*RiX_ z2&zJ9s>N~x^QByQTN)9Tr*l(vYpRf+%avyfQ>EPb%Ca{h*u_F_sgP)>;!JTq%uj7? zC~a#fZLgJ17fYpD0qfVBQK~niRBuLUwoooC7W1{%j}|Q;Buz@z^71?aR%^tIh3Z^x zp)NfRtanYR-ZiCq*Oby-S4+iwz{~tDIhKp%rJL~i)}6J!Yq;(8K5Dp~J5qG&Z&h32 zR<#wb-ZuZ}(qb-On5r)2mX=Lx4Unnn^Gk)WTwPi$mS=sJ)w8*UT3--OE+OSw?eL|Dx)78jN(iwWy|DOar)PoHm~4b7_w z>r7#BX=*Wdc4|83J?PsutD35oDqie-W#N3aINLDFQ**P5a}8ZP+lKLwjOPaH%oNXr zZD!7wOU3e|OgmExi^cikQt^zB4XetRDpk!CML+Wyn(>-nUR*4cm#Fj+XtkwE<5306tEy<4ud^$ZtILZns`HOd<#P+Ud~wOIBZY;zf}6FbW^zlp#B6okqlJ(x zKUYxu6kUQ$5e8G7V}>57c81beSqM7;-^k5l(u9hoG*3{CZ8fv6CQFcY!qy$(5FU zXc%FskgFPsJw)T=;?}DvjZRINiT7%l21#g{OBVRRIgU0#%gRCf1Si|A!uhqb8F_sf zt+lEwHW+L^*I2AHY;sOl7U!j3umpQdT{qUBsY+$4==U(E7gJ7}%_sH=c0LZZT$Ts? z_z~jtvRpTxd&FiLp=uf_Kew!P`?Orcgd&D&ov5U`##XMRDW$fMK~XFRd|hekY-Mq# z-u>&Bi{i^FQ)64RwHO2y5~IFxWF**hK;Vcj|ET8>R29l+ii?%jFs%9I9swK!9lnk(cM5Wef+SOG zIh-lkq@e+@eH-hCk-DPo+mhPp;!-uGj;~;U5;knuog_3`u|f)G5}3iXp~4N(5HoMC zOBl^B`;{mumJ5E9loT7SUBf98vJ_RL<g&83gAF{E6q^t=_oK+C8~i9l+K)no zeoTr@dT8!lktfq_%@x9g-c5>4_=P@)Xt~scD2xOVsn~>QReXq2xX|=9jO{EF(~2sw z_iEZyEWyC9#lGoc6G@r`m>M<!w0E!QxZ*7FbvC!?$DXU0 zG_dM34^ml~G9)J;s|?Mta}ZmLk8EtdVVQL4;t9Sa9Dh=x6#5DoPWlfM(r?Szsc zkqGPdU}v;O1<0_ts5|6jrPNgZn3rUJ=0<9arkc-j7h>)Z-rbkfZ}HTo#y4G6J2Rn~7GbYhRSc_Udsm|sy3S;I zi3K~jT~AtrY!F!-!PQ1roh+^Wf)48fF_U6wcrc-`z8sRI&F|gfM}qpU77CAsz4&s- z!=b`{4ADp=<#pGwc%G@-f)D;R18NSK4=UVEePiHNW*Rm{%;&*^Set603WLnXtK)m3XSEff^VMRqk4a<}Rwrx{&KGs> zp#6D6Aq@4@69W|+4i9UlZJht>=t{YCo``-_&xdNeHD`I>SCKZJWqV330>KW!BjswZ%kp%CjnC^me{QDeXZ9*ZwpyN;Vnu=L#+II~ zO)Z_b=Od0ZsVmOP49< z-IK3Uqnbl%JefpOVieBR;#_1p+SDX=PCG9@<trkPrx3RKkIio zzN`bPx^$Y{WnAs2D~tXd7^-45w`6D3l-V8D+brr%T4yiX0R@Z|MS709n$==~c_(PB zJ+aMhuof&8=85?E+6_AR`W$E_%~1K$vZlfOT(LBxQ~5g6`mtzDIXx~6<4DDZ$w1SS zjs{OxrWPw_y-_v$m31~*Kk!>#(21L-%=&ZRvxVHF!Ba+8bVu-sC`s9krvOnKrmh;d z)eqerir9bp+kWt)8#aFOQ9XZu)rR)ApWo2-RPQFfMcJhPpC37@-Ll5byo@P7@eS^# z=Le3-Oohco-B16sL-ZZW6-#>5u;HIvaqMtei)(R)C~@=phJSSUp@SMH?8FpR8~!07 zoh+UyR^9RB`KiYWi$cgh(M)zG zs{`h0p+`t3+E#B6je?~)7YrG_wK^t znH<7bN0T#rhfka|bZluxPmx9sYG}V^>X8jk{+V7-&_(`*An);Qj^+z`AypT7_X3iq z-+Re5-Ed>j;Y?*p$M;MeaXeaahs{y38r@YX7vjvRQ<+nJnN!o5Q%jjs<;Qt!L$}5nAT*8X-N|u^lHe_YLi@k(8tR%0)I6k?t-_xy8tB-!j<~ zyYCws(-rB!SInXX9Y7cIdb(LzRL$10L%OW4x|~mH;xTU$1@hN-s&gT}k4Z2)W!fe~(vO3I|(Jt-u(zdaB*=^&ujd;W&OY*j1S4w8hZ7Xq{lr_)j z4y|yhujG0twY7cC9Z9>z!Wo^ZFKkQtE|!Z+{f|Iqk08iFLFkN*XqzI|n^=bK(YUr^XxW{iyyZ z1e1esIlRug5#QOnn!XurP2$GpHPS|OXOHJvM>nAyPL!4W+W7DHEqG0%MoYmT#|$RK zU~clHJk+a^Qt%A57uSlu(^F~S*NBvlYnn6~xkl57{rthNz5N_yHj^VIvyLX zKRRiG+G*Tk3l-Hbju zUuxU%`N_`VaUSQoDQZvTYO2xva&<|Q+?hhOG^Ytt+ngvlQtTW_sNFQSHu+#ejp=-r z$R9|svb#qzMQ!&pXi|5evb0p0*Lpbvyk@GnAz3_%ZndDSOAAXwss*TCHu|ST2>wYS zF7>nAZIk934jvjAJGXU;ncn?Ly3zXOFSkz7iLM~;*0Kak_gc&R733X0MSpNrh~>qhT{yEVLE^S}eF!h2F!YPE}JzouQw_{ssdIXM`|+m02MMw4wa z53i>RrKL;iLQB@AUd25T*WP_kA5?k@+$v>sFEn9usaJ~{JlfuQyIA%?1)CPBq)E0Z zZcjIQaDHLwd=2*v%Z25F$L*QWyOj!z!lIs+9?@fl(b^s^-g3YhY}D z!SjoUxA|(`$kASd7mqr-0$gos*#d=1Zb7}Yabw$tZ#{Nt<5g`Np1tkT#;Z4+Q{hEz z8@^eEO&ji2p>xCXZTsqsnmKXMS8GKd@>w^|d|sU?#`2kLHIprNXG?;z;7Bo(J)OxO z$YdYSWS_`n`!m^rOg5LvE@iU&Gug%N?9}3=8+qH*EON*_szu?BqsK38Y;Wrry6@7) zj<$|rB^%p1wkWx(tz%5d)omTyohBVSlx%A2*mb{DY3sO2$u(^qdmp;A@!GbITa>)G ztz-PbOB-L()^R||OWQi`ICW{`%i21QD0z8X$KA&>+2uB7?4LZKXee|#|;>Gn>UxO3~3w#puJZL-I{ zqFrq%Cbvzdk!0VgIeV$TEspeJ=5%2(`nX2v#jV4UPD}MBh2lIqUCPZy&%~X3Q#`WA znsdm`tZJQ|=o;%=P~dAOSs9Nn!~@z(=iSZOGx0Oy-F<_7-F+j1F~MM8*Vr@TU1I^w zcs;*zahUgksgxk$V^DW<>Jmv z%jqHRysL?TYw&cj)0Aa)W~6p=9`z0Mg{3F@E^Yjwwrd}lP9lz&0wSTGYrFP|Q%TWK zm)fp<_JO8KUv9F?3`ZY`FYdyuI*j8z;H9D-14X<*sSv+7)+c;mDL3DrXkvk8(Cj<@348zgWHkSK2HA;qi_$%ey$1W7={Q9CfL6w4 z!Q9GHeOSc5xGJ-CZYx*HBOKicIkPlZ)lEr3!CPHkSg0%#s*2qxn-BH^)ti>}Ov?wd z?xs1%N&yLFjDEUuF0%I$n1-}XsM#W2r(MBHJQ;OOcg=OrRnBDQ z&UBsWF6YW!qc8S%3>$`dcB<1|?vT#w?j^}2hkrfUq4G>mHsa4vxk!#p-npJ^cln$$ zC&-*orb4Eo%!~k%Wi=?#ls`iynzBDE(X^zdC7PDhv_#XAnwHemk zR?_r{njWF)5j8zR(<5qnL`@yZa(8w}`A9INCXsfcYS4X7XKqSPWU?aeuIP488&+-q zGTAORX=B>LW;5~YGVv3ccz-6oCKHcl;y4p$yW-5~U}qHW-VY^v)q8ocVOuw?J|EEL zqbFNc%yeC&g7(GLD@X=%It;DoaaVaz)3u+9gKS?;dknn}ZE4gMMg1&Z6>U~KC&w3O zbwawpUXh6)wFzlf~+SzD?5ND~E7!%2bhbSxsm>hs%?CBH!!E#Y`lL zo_knud)yx}_p8sYC%WFy^>|R}st0|w2zvKwrYr2zA*ee}CmIgqX0`;y+vM!9d~B(* z5JzIk>Lnd}S!Wc?7k3@f5mza>iQgmh`**aF>h^d~i%N;0`;i-iTGl+?Y*^NtuK^eT z4)H3+oi}|^ZC$@#ti%m{DqNDM7RlqJ%ZtC_j6pPX-rRrpVr5pZal6L_d{m=l#SO`k z*25rqmdv;ejNRKoUX81Hi~00Peb5Pmgsj6uCnH-N!~e?JLZTCC~m? z;1fjsv7a_#{;^+_Joa08ZjQ0~Truv|bd{|RM3F-Y(IdpbiZh~?y%p^hGTCEYQ!5vH z4|z9S?AK6V+Xu;%7@u7#&Vw@U%y28_! zcmQ1&uuh+@@btX#)0944Vf?i}(W_N@c2_81=$brwrrJ(3)<4+`4+*8WrD!4rcG!}nTHahAr(k|I)8K&_3|7k8Nw;^VT!v_MP+Zcx(F&C#N&*dq49N&$f^L)Va^J_x<8) z-`bvi*DXKWe$)Hk^xpRN-~afL_RSyP|3v%C%EykjfBh4G`9S+sue^dv0mJ_8p)4aC^@eUijMf{*Hh8 zkL{cO_!Fb;FS}=STl-bJ-}yW3U6U(E+OPS--v8R(_9M5xrv1i`?EUrj!TY{PeN=v9 zuD$oOPws5rT-p4y?OT58+aJ^Tzck2)T1(R<9awKD9UnP5F@EQfd+xjI?(uuZ?;H*b zQQX;gTunlvFBRfQw}ca2qh0$ld$&Yg`?~h(o}{za-?%L3D_lJZoGn!JG27z#Jz96p z>Gp3%uQEn^qivnTt?3r^xk9w}mav6J;{`z!U5er;(t~KX&Gami2dcc*8eiCO^1_D4 zclsM=cM9(IMecQ(J-mFs`t+S=1}&?WGB^5Gx(VY!k~^I!EMDq&Xr3ip^`m!oj zo|{uj)*kox#5Qn|=Bu3EYbnli*PsJ14(X#)7cOWIaV3P=d^V2(8flv`6vy7RsNkkU zW}SST>+?q(z3xa;cQ%8eCC0dqPTufI4t2Gk?2R00+}Ts7OitiKLhUde*{I3bl)pO< zOqw;&>E5(C^9HKS*mP#Bk{MghjGeo*@o-!F(Ba@^td)yf>xV?{SbYR=f8PSQ3apyz}q1MA?<>GEF6NOoZmDuSKVm)x4iEnOMr-x-DW6Ndt0(@j&zUf#q zLDYHZ{SG-{uT>;-x}2<+3F(O^&|M?D{ZxO9>1mX|_LgFA@=;H=lGky;P!JfsxoAR@ zLw_zx76#r%bT1noCHRsU~BK7L^~QQs(OB2 zJQrm~w`4|7b&rm25u8$qY!vDJ#nI8OExq^NdH3YudwRAk%`f!yo$BjL@TYq2J$UEc zS}Q%(gnLyvdz?3qk&2o1S?v(}+$m75cC=U9UH=Des1Do=+bz1+oG*|$==Ow`#u zGC6hV@R5U4M-Lr3cJSV*1BdTDcFWEkk&S5(QAFBS@rntyT+76w z!GBYCjo*22>e$`m69*+u3laVWwfh%j{cqZE!<^x7-MxGFiLq@r)(VHi!qKoW9v04r zg$KgIV`1UJuyAKsxGOA7hJ|}o=+SPqn9a@4?A+0(z|Sq0mh>Kye$MBdHXJ4WFjs2O z9oKZB*+Pel3wm@ll8-d^RWhU1%xJEAv|8Dn49*e#fLf_AGLu`>u-Lk5bl2!u>zdwV z;_J~1%jc3YoXw5u;Ip48O-B>6!!4x=g(CeFgNCO!>)Tx zy@nsqCD{1|e$b?`b*=%U4$h?!t0*dIiedv|s|4jIQ0o2c_Rsh99fg~C_|>6BeP>mu zZeixow+)&@+zZ>Ijo)~Uxe3Z`R`l#duQG1;Zklqx_m(V}LqUF^_MKFpn$Azp5|w=|^0uw%a*u<|{aTOYJ|LuWl9HRQ`0a-dndYy+~1*AK(bby~D~oj4qSq z%iPj1Q@&ou%(DX<%;)vXQ0P+dQ~$Q)drWDB!{?84@KL0*g9Q7Y#Lnp69U3>II#CFwst#*rU7M6Lxr?{xQ?~B`p zbq^8s-O?9T3)=GL^tx=^In;tadu%mz*DX5QH2V79Opn30x@Y_9l6|%7RkuG)DE&(S zAz>i0yCKuso5U_64@dp_RRkBJ?oF9Y-+<2Djd6-z&y@pez3Vcta#2x}+%f5enH?j^ z)>N<4)$RxN&dzMy*=1DOY%>~3oyiVmvij&tc00x34_QCor#= z)SYuK)@w1_M@HPwQI2SrpiQ8584Ho_c%INc@}?$L+3GFX>Wv5PJA7nv>hAG-Z=1UN zo`Z)DpP0IH{BGT99ysh3NPOwG?Yd76expeC)@PZ##L<)o&kpo9)R)eN=WW`)jyh$N z_nYFZ%JJ~Z2c8*sPXQnPK%CTWyjCaVL)k$d2)PJ6Lw~n+ zZF9LByLNW%N|+rGv;9#I!Kfz!32x%z_S-at?9sE(nMl7VsV5(L4$C77`Q}L{_JMd` zd`%M~9$#du`{VsxBf3548P&e}LR;I1qTP2A1GVRtyiV@FR_WK{R(%zrr%rPIHqA{0 z!ipThBY4->q(mI`(q0_fw=W7FDej5lZSnpzZp`)O$dZ?klQr?uO1yGmobRYE=$<8x zw>z@ibQ68>T=}?`V?6^K4sr3yvl1hh^qst|_H5h}M;?{9Xe%z-y6?FSk9)VpQ4-~P zJ9RvE8pO|Scp}NfTjj{D`yP)^Y5+v>>z;^TxAN?B59Gx(0l| z8+&xzKWEH0evNS-8jq7KPmV@4yCqD;_;pFsR`P8eHWs&Bk$@Ms^8)ouvHFN!bY!E> zQ>|w&_C&YrbID#Mni-l9Nh{IluSjIH=8WPSo3`Y!c>l9J$abc?wDAGyD@})@{%meo z=at!C7tl-Q6pzj?Q;P;6A2|s>umS@-Q~)jK=FN zIUDakHZYpJ^6x)&q)#`1eR6U4@tpfP7@gmgmN|#6vDQtxUeDB<9wqKs&+FAFy}?wN z*`v2T##%PgRN1V_idaR_q2i+6+Hic_i=O_G@J&st+%w_rs=BLic6FPbO)Atv?<~8o zA9}SB(Uy>JDt*>!2K9dIl6HFfCDyDvMRGK`(%IbkYEN!?sgf-hv@N-C;6i+1{L)zB zk9^7PcR2iRn?9hflbedjKM?APeI~MuFz^3Pu8-{37#ZFmhud{wd^Pa}kJ=rpU!Om$ z{x3{eNxy8J-1|=)J#zG(&YtAm9_=$S$gH85NmR(V^}?x;*_yOCc+WjY@0mJw?*m5; zcKWw_XjivG(#9DhqbXQlmSihBH(N~pc0~#qEiVuIb#WrrI|Ipzcuhv8@Zu&vVej63 z^Oy@}49mptGR&vUw9|Bmihifii*0ZQyZ7Ivuk`HbzSUs;jxno{` z#^yEkzV@Vh&br~i`{TaXp3Kf1$aV$TagQC(b|ssYWVaIc%vaCk2RLBU8?|$LG9yQ7 zp0}M*JmP(y?1{P}5$PG#s2?WW129N7{K82!)jFhetR!@dL72vS6h@+O!Ib*j!wFDk zq|_~GoLt&sa|;w9UbLlL(XVz@qAgk@_9Pv|ds|dH?w2;+pwD&=`Mdu_w#B@cO`E)G zq>`g_;V#Kt?Zv@p%S_?Sma={-G~QODs^P>4g)WXn+xDd>MI7SjvOAhlj}1KaN}iDV zQ)3x9ZF{RrGt$j#-W}~z!#Jx%q`I_r>ToZ;LBB=PutDG5tj_Jw<*vi}Uk8u4Ix{kx zjBSlWMszUJomO(6nJ9Fdde|34foRk=_&*V`D@wL@Qe4Npyt$?4f;#iiq2q$y{v3+p zm5)!Xj8E9BcYWFIMRB=iEQ-eY+(SqG$^GQ}dw_esyI>8_tcPW8ebj?(c~`S^zpTzL2Iy8w zud2HTb(~|24s_l_AYytwgDUaTD-X)fVdUbHzDnXHRCOmE9Dlt%rh}e6*U+GkL!!P& zr;L2-f+?!{^_^;UwDUnn>y4!QYJH(bB!~np3+Lw4f*%bXy=GjUCk*%)A?agPJ4BjY z)@cid*(+1bry&Y%N+V%6IKkxLrn|6MSVL*?-ob_b}J%7y2>J&joh5pTc{q{hKpDT`6qqNGt zb3zO(<}kxdfq$by-+npk>mh`;Yss06-o-vG3(H)A=zVqls-vvH`eICWai5NH+7PVR z*XV3YFIt>;PuymmcBhx!6HtE`B?j8EZG3s$dEu)|s_atd15WYu_|x`Whe0|#8NFsg z?$l2TFDkb6u5{i7)>86zY)&|7n#>Mv@b>Lhl}|5hEg1 z5KVXqiU|UuAm9Zf3Ra8O`d6o;cWlR>CDbyOQnl4aY8l7r&#G;$by~Gf%Q#MDY{#Fq zR`K^;Ywvwt_vV4^ubB2(sze5orTPTt@xp{Fgl8`h!xREt=$7jmfjY z!qJtm?2e{bgDdKAH4P)wHw1vWpsj42p}1@;w-+j;K(DbdCZaRAC{n43Gx31NBaQAl za`4b;QU2MDC4Nwszr=$OJc`eM>1i8X6!S5VD3ZmJnU zIQW)vn#gFSYagv<&HhV3B6T`0Wz-}wC=>goamWV?=%CCnzQ3xxrrfqdfMZkqW;)=k zX^lI@RoDw<%WLHAwP;y6HiJSZ={ChiA8csF_;@;%hz0 z$_$g#Pp%(MaMjGL&{5ln2|@!aH;LQ4mEsKADCOgS>|1YFWV=RFscNFY*BmKD3Jt8w zG0~RXibPs@Ivr6lU#zB7QmO{s=1+oP8qFZ~V%s?}T|VohbHVXx&R(VkvHQTKi3rM& zY20jji(k31yas%fM|i2mFRz)X+;lM;_Je3A^Q`iksVWo$a5Z*4tw(+7uB!5yGgSb! zJ6-JP(xGj&Fp5b5BbhZg;PPuA(-6Y1S%t$wRn0gDj^K%s-T4?NvBOo+{t#MK58PNY zZlXVibxvQ|&&3eK-~;FAY^ek# zOk|pLW%4A=JRthAps;hBt7uOS6YT=ZcjWo*;h^K?a4gADAr6vECGHndVygkF1MPPL9b?=CLJ9lwyVLf zv0M1AO>A7m4Lr-&LP7`M;_3s1_~&DIU~$ud2b`L}oVK+gH7Fb67ZroO?SGjPtcgH5 z#x9=1=n+g7ny1Wz(Itjiy2iQ)gs~0__$-10oN9TgB7_oOjWAK1n8YD?x3Nk812)9` z(>{-OhS=D(Rm&R{+cqG-4K;uU)u%}j@aeK>J?pC(PxK*$56lZ>CujD8VM0ybu*ZP5 z6fh-$X<~0L?Xjk9f*Xj5PPMD9U9%RFCyK%LC&fvyZdkhOsimTT0+=IKK+;J-hgEg!NQsW;GR8hm@-;|R~iGdbH(oS8we??j2uR)b@3ULi} zoQ@UV#l~PutSiDHzRU4doK-8wohA7MiE?>kDnSAp3aly|1=Ovhv?FrxlMESzPfQO? z9O$I}giQtgOyDbIvM-J7u_W+-Z}JToxJr-a*Rq3RJW+Zh+#ZlqV80XN!2c|%>yZZ= znTRKaydZ~69PbIP{=$gDJ(4yp#5;hCwN zRmS`(xaWr?K75e}O%2|*8Y)Gm zb{fkR_tmFiJJz>deGOJlFJW@+PYHDX^CYt`uc=WIg6dtUQsp9I@er8gSMDIZlKd^Z zJ{Z4}un6(DO~m|H@oMxG(({31<6vz2%H%cexO0KE8l=#{a6~kQc5ztGWft~QUf4dnYXU%6wQ^Y!a+3BM$8f>3#<70d zuZj{@|1YW~=#o_+OC85oJI8VBWo<|{t-_37O^kWe)GBmpSL{`T?!~84BZU!&(vt#6 zrBfJ9vKXW=l9 zzZU!`E+hw1yc4D2LvEN(C@E4En1m(>>UY#?CAOMD5Th9#Vy=UNmnaA_n!G{G6Ax(0 zWo_X0XQ9wfNR*i!$*i*Ga*+sDUB^lmyLn(lx@B#ww@)^tJfJVpJ zGr_{vZW?=*V{QNILjd~G<$E(i5@oQVy+-SRU9OCks;Ud1NyEx1sc_YI-Q+RQc3z}h z>(u9qQMt0Fa^<+`bJwlo`;O3x`pO5bj2aImF+_7>7=2o;@;n)}Vc#N_WmavXrI?L> znJA+`_6MWy7~)5B>2^gYJIl$=cCy&j)S7L}F3+yWuFS5=uFhW0_eSHKMzfQh>tyFS z+0SO@JK1xc?1Joh*_Q12*@f8)vWv18W*28am%S)^sgqseWS3&&;Dom7$<HM`|a#h=gD{HdZCTnb-*lK+s6nBuOTBB7MjSkDRq z)Vfu=OG67h;3~M63!~FUY%b?jBpr)$rHa=Z31BVJx%5$`MGztw*6C8}`4(>1 z(5V9plfF#+_&Imx+#GGBPg$MKF0g9AM)-hOzJ<)3RWbl^o;9W=ptVGU<OHC=5&S}CN z)2EEA=k6HRooZc^R<=rYf-f2Jy4b4l7*0J#^=m;K;OXe$nx3X1+7jzlkB4FGR7y;_ zX~L4vBPxU6CvXW?$w z20TlxFU*CkyW$!WhC-$H3=YdIykF;uNO1X0&nQ_iC$h+G{ZdSht&s!zp-lvi12^*^NqAxM$ySpVquJE#)qX2V9d>gkV&~70TaA=71&1i}KwpimmYVS*rl+A9XqYb=!0Y~gu zo0H96e^z5)BL(3!u#F;{-KKlH8rXbXBAeZAjlEE7K{Sl{^(xuy4y%d>dfC-zvjkP_ z9NHccWAE6EnsUI)>iO6HKc0iB`7}BjGALF z32#*W4k-+A+k7waJmDG>7)*SqXgXFg`Q%g4NegRUujz0mf7OaBrAWjFQF&59e4Vbi z2Obp&v^Il77}%qUGafi%VO{W-%NEB%kSm|opyL?Wy*Ynn_6O3oZe_M>+9K#i@qIvS zb(DuUz%F?uUyw=D|AIXqbqq%yIVNd|azn5y$V&UiZ7L+1gUW$I86 zUz$yaktU+GDWB4P*{-oOptb7Q(BNoGS0xV`Tu!4?>s+rQu&=Y-O*n3b8WI~E&)PNi zb8?)N$!V?0IRjbfs4CRiP75Uc0|A?Bt5k9uOEGJmnPHH;aJu+T=js9Fhp)1cruRPR zrud-au#81j(*YEKqen5!w!(yn9DF6th&r4 ztei82v^N_|dE3w)49mgjPIN)KuyGsO)tQL!I~ozewsCw2rxdX*oZ^Ap4r~LWb~vMF zRBmiQ1+J$zhYe`Ni9JbN0~%GP_af8L&UR4W*&y|Ur(;eNn{KWeO`B5Tf1s7mQB}gba;|@=u&-Qs>AKNAesJ2npXgT39TJA`D7LCI@ zvuYq=jh8lFggfm5-ckq-APbo4bMtgb9))yp;)t`x;l=}Nh^LRKY{QAVacIzWPWi;_ z0kIUsyv%kg!E=@oc^ugK0NB&UdT^QpH%RB0v)H{)))p)bH}|8_r>g_L_|ON=EViqb zvJf^Fq&dBYB7kjTe5$CbLfKS&RTY(vf6hyuS*)Wom30mJnBr#|(LU7;D!Wl0>CBPEu`UE2D)RxNL7WucyK@- z2F15g0EAP+;mFUP>3~gWlvX*@XH2rI>lzxxiLQ!mHpT$uu}xkIhlWvgxty}W***e3 ziym3t08@pHq_D~cne&0wPWc$sWYH~zkB-$U-gb(IGCNjtF60|*3f&fa5s}k4&S@Sl zB<>+6Ovfo_Hqpee;^(%=m>Iaj94)Kf)aSr5RrxJCTkLyjlofNFsVIQc@VP}`h_K{q z<4}$|uglyFh&9R#I3Y-Utt#&^;vVCi>F`?Plvfe)tB@m-uXv>VkMN-L>eJCRE_2E+ z(=8PJ5or7hmFgu#s&uBKk&q#gHEwPNNk4!gnpi*bzuqaI-V-hkY*X3X12pJre3=@k z!R8RhnWC#QgU~>TXaFjxMmQ<#s|9soN$MN~zm%-y=5gzyYyL z6<^J54UPbwK*cI}{|PXTf{sc#|0l38)*+=8_;L?Wbd9Z&vk;Z$=U&VI0=bPQwUY{Z z13{|Auq(vY7*OdYIZ$-6jq_C^RPS(!|LM=xr7>Twl-EgdsF?9NYAnrNV#ZQkDThyd zOCF`!i^d+ya0kRTXOuJ1JM_=M*Q#z(t9YP;Z=^6O*All|R#9J{C5fY+`h8nHICDkS zxQeCA_Hh7nSVcuKV<$kNSlq9@^X!4%eL%EoZW1$aPEwNz^`E+iR>@j?2zIGNNAxi~ z-Rz+_2V=&==r4-(#f&bmlv*x@Ae^cAuk2`92`wsGQ^QrLso|cadTPx0p6;q%nff$7 z^+Bd0T&{rZCpA!a1mYM?V4Wk#z&3KT?5eCT>66TsqEVhTq*KE9py7 zK~DQVaG)KRF>o%J`6;Rd&C!_S;wlZGXgI(n4PuAeYs@w9uG~RAMfyW%(%`H|P!)pE zO%d8vaaI*7sXKysork1@F>@Q@PCN_JBzFZ2P%LukoFKzEl@PtCa7bd{0Fa{GoIW4O zX&>UAMq(NoFOZoJG7L9Pl@#Tuq;|Bc>SDfO1ar{`9(3@pp#XF1s+dtNonu)nftb>y zdBJp=tm1DY{TzEnwTgk-(|E-~CZz=ja-u{1d84%hX_u9kyEIlw138KB^g7U{3sY>d zp`3Cbg&F-QthCdwl0OrvJ_lRAtfFRV`M8Rjs;Z{7m-8J^V>o=0eAUU<=~d_8#zMLw zs(gDz&GjMU;AA~R!KHT4NwyJ)ZZ7J5#H5zARR%r}= z;1TE~2lzrP3YOIARyj0`c@6MQA0ssndwJ1>Q;zDuJ4=&(!hI4Ec_6@O2`Xd(TmfVp zcBs!g<5?Cbox(U!gHv9Ut=KUEzv}F$9TRF`RM$8zcy8TXz#^be-7u>A^ej;yXw^}v z4QYfV@h%UalF<&vB6Ep5D2OAzKJLu|dKswtDlUXJ_$*oSO51>xoLS$Y$y` z_4T>}n89P#JiQ)l^uv z(_jOHFw!*&dyI6Ri@i(;`-~w3_nw2-cq@V+(FBHbmi*c!VGRLg9Vn zF}A9FeaE^j9b(b)j7hnRG1Z&;q8GggT>Z`x?xs~kKgSi-k;2|l#T7$H#Io(_=* z3m6hY{{&UH9tqRjlh?NE*=nFqkDjpxJe zQw+qS(}ESMqr8Zx<|qd+ifo36Enk!yNyB+Py@GM81MT}z&}tA&w2U`padcfQ5{S7B z_f^**GoX4oyowKfUy$Jeq){_!S2sK8|AfYBY$Kz||X40mcjgwQ2)<;aIoOx7e;0Lqde zD3|IWfHFD&iYG%7o6H5nqm(M3h;CYFhnUyu?=rFI_r2`pu&<+%`ml{M1-beMjWy7l zVxH)7Ft-%1wbdPQx<-*L7|XeZNUy7roUgZ9<)|PCOsbD*)Q9%Chn`DBnA2liV9=OK zkra!5)vcl?6HIM9XkB>-o8#P${HU8oL5>}WgnTNJKwP_8k*P!)C6yi$S?=5|R*XS4 zFn9BD9Gx{5Q;;*yqty&kLl>eXnhr=rvZ_lCOFUTi*gYONutJf)RFA1NxR|8pQAn4e zL|N7q^jv^KY7E1;+qYt$b@9iG4ysglK21`$PKO>rYIARP8>%#GuT-r`%;3D_9XmEKpKK&ccnhm)$C`XH&tpkfQG*}&`XfLC|!&BLrDLSmOZy(g0EVIr>h zt}fNrJpwaxgesUO$}K8nRwUA4vi1!BPA^%2>Qsb z(JQg^qY9J#h;w2VGks-;ez&jk727xZa%(r5F2BG)Y|qq?yz7JHzg!#xtUvf5W~M-` z@R5$Kec~bny>%w{S;iJM1Y8*0Q7U+*)ER+oqG703XdKx@RD0A61Pwk&_rT+ZKoGK& zl0dnwPPq-5qA-UHib+e|^>V3uBH~hPUZO@cPwt3g1p=B5(%Y*F$HxW~7x4*HO}$_d zi=T!HI%lvj!l?iubQx;R0?W1mg=j237106gM6LNieex`hpht1(XS?HVj8N@$GC3{6 z0Sp>ExufNdB5o$3tm4r?Ry47!Yd}^flUX>+!GSDEpRKYCX9}8#lSWD_HsYj_a-dh{ zDXm+H5aZGvnb$)V2P8spJ&7<-41f>rMj^M%AnE^7Xq+2iZ&_~zUwe7fAVy%|e;_beC<;+h- z&_ii1rn*LBFQU!BpiQq z>`0KTNXjO{an)m$ZM1x)S7c)GAyVERkNxlXYz47+U!fsMJ3h*lv{_rsG9^pV{^S9Q zF8Bgqav58}7vZAI4kaD)NXEs10~XAo7RL@$NJO-x2FTSe8{QD2#pqBcFSyXBBP+NF z*}E91=l#cwnlN*p(MmkdS@nMWC}@dny93@LxxC5 zdtz}DJa!V0loH?}ZVO4i>5B=ldaF1tq{mStY`?{)&=sF3IO@x9nrd-3lG`Yuu>*V; z5|9tMl7;n$lS$wY#uA?HMS+r-5n@?{c~>P;*C1II2vCV@z3{36=*wMRm3LuQud@f_ zv_w)P1Mn3Em{$UOlpb(SBaw^<6&n%hjWN})6;BLDBu^`j2w2e9wJWFm^z1s8sHFVH zQ&v(xLBgbtI?*>!CP)@Uo)a)=JF=VP8@qevm5IBM0q5+fm4lvC2q-0IX8^7V@}$-T zX>mzI;Ysd^WmJzz6p0W*|5E7c8mqPr2V#@r);Udu=(rHA`z#sCZ!Q^fw`KqdUZ}3~ z7hRuIwm&|me-AjdUg0`+o~=drVlJVK2I-Le!(UhPag8HC_z4+2)&u}G^j$7Sy{hB24LqNt?aUVy4r z>Fg?e%1P~`iY0#Jl|ZAezW^Cg@(XuxOuP&Tz1<$M#H%y`?_;}%i{RfNv8O3TkNkJ9 zcy|*9p;+(eKz)MS75c%IMqz)sLbZiSq-sL#6D9aPA&LY&A45V?Sz#qN^+Ylum8Uh3 zD(34}))08OJF8+AWD-qETq23{TCXXo9h z*(xLkS-1G8%%Xn6iP2r;z^cY7kdR!|cLiw39hQT%dgf)#LfYWWi=s4p3cWD-`^dvu z$dh6{MX-q5XgEN*n&Nn~5SFPW3Vef5IP0LM*;+-7iGxPEan}Y*gF4DB&D%Pp@s4yT z&ntAFLsChV-TLOW96};8#FhM~obQy+q zx4${=^%bF(fLu}v2(@knDyduRW%F=B5Bm%1^4H~&J_^chtzHWPYx8QJB;J+tluDkbxUKDeFh=GECi_uOQxuglzcfWV z$ntU=v@)sR&St?DlG{AC;I2WbYDuK|7a{zN*rLzdP{uMpmTTljH@%9; z!XY$e!NE0&H6`ERnr!lsa1ygsZ*Wci4H2C?^d%oapfe-yXzHrv#(RUNYV#zo!+N>w zr(Ej1Xs$|+bdD9{SUtl#Dgqjs5cPV3ViG*dWhcq?9{j%DpFXjX#*5KaU|SlxEt~>M zPWTbk^f73-6sPwzGxg&T3qFpe%p08Yvmi3z`T?B$bJQDKkI35{B$B@)G*rsjt0uhU z-;*b8I|LwE*B4C2^9|}ylaQ1!j%jfy2}uc?qouwStQuktGI9$o#7a+2p@n5YpdPyl zF$_O|gAABpFleqAQ+TS<+i0i?D?l7$a2U!HjSI&hvEINQD;y7(!g67?zYN;&f)5O! z44IrJGuY+s7V6f#a4K^>+s($mHd+Weh8!)k$xWO5Jq3qxSqP=0OD%=x`XFraLwEtD zt>vu!aCuZ$xWu0i$^UK}6t?+uT1h$85drG0fD*A@9k1|5rvcc9ejkrgx{KgkT5STA z3L2us0KZGxlHbwVt}myMLMAz}CvF!?=Z8SI>-~P<{|>-&0KO6h-lQ}~?t+>R1b30f=hGjP3HeNogA|XYTH@nA(Xj4oG2M$C=l?rPV7xlr)g!fX7H zUPoxwx^Xc4V@7P=wSSGev#==r7G(3_`#s=%}Yj-Izu_?VohlnF_y2 zl^>&~s0w}I8D3Y#^yzLRxLbp!v(~{UZMw3wZudM}nnT#^a^*#hR|pz1Ie^FH$m^cJ z)B%9k#i5oqd4%^=W{@k-HDcDqJvE{`75B+BuF#-o3}Io$w+`MDo`Ujq${-r?XPOPYIcg9@rBrDstyXA!%MC0!nP+{(}Q|eh=_Q6={pZ(qDc^!Zi z9omeeSgWT3maIX|fQa>NbMVU%%?He)qriZW0mK+lR7b_&V99iDIzDHr4x1wIOn^zJ zv#KgL;nXRPY*8{5hXf7y%B(`^uq1&)Vloj4V?rHUiWSW#!r3O*!n|_Mr})T@1P>Ro z#pF3U;I$O+jK!X6y80St=cX&G4=RRFLAEKEerdP5Y+clDBVdu|wYXVk`M@Lz8G~gK zkkSOl@eV1ubgj?p(N2H~Gi^6lXtP~HmqR&;i%jYik60LfkXu|iv*>QLfjS=+E4mj@ zsRLq)T8jRbnn9nyixrW~5juiLEy;5ZFV_A*EU&PG{=zUW>cZR#JVvFtbC;s;Qa+@x z*7F@V;*ns)qoIh{!aTaFzJ46|iQChPTvZ|feu)y`V^?nHBF>}h{Bs7MSpyM;FXRnh z$0)+$B2TrCjL@TMF7(VskjKX;iX@!vEjFG21_)vy33I{6K#v$@_g-iWE zY;?XtC!uj$uIu+A4ORGrAUro#u5i6sYr#?F!XMS@7lao|?e(W$QEC;9WE}@T&VxnC z!h3Y3=!iM#7&S(ig<%0%y>+y}IkRA7uvo?S++A)5W5p2@Zay*;(MP0@!moh9a$EOxYZKr(1Fn919D^JqScP$_q!(JTtHKKbuXILl>LA~-I4uvU#CEg=Q*3s#iEy>ZsLQ;Q%2a+JK8R-W z`!zcJ9tu}}2uBs@(g zN;<_V$8~Z#HYCtr8RF>+q>I}D1XR2o0O1faIx)8I(K#r#luszHwr!lY!JHQ`;x39B zfC(K&O_i?6Z-~sa<1O@6tYIM0Pu_G(f~u|jb}bc-WjrsBKXD#a zZU#JI;B&JZ$Juyrk>w3pvBSx3&u+`^$O17yz&E! zck+5Cd3ET#`<$6QMW|evq|Y5rTZlUuapkzqfbK4&{F3)M^*seqy85}icFUh<<4Zem z0gIb*M$dti_Kf+sZ=`JvK9`DHWUqu~23L&HrF6XNUB%a(UPUHUPyoXk-9vP&0#sG5 ztj7JPR1-8Es*4RvT&?jJtXaF7fkT^iO&G^__|vV)E@EbQG0@gtxWWq#Ug_AF+5(J; z(xVa|y{RleXweONeA@$ktq(hN_}-awSGBKMyJ7y?<#ev9Xx?mG%3>5v$K5Ouqo`=M zRkeB*zL`V!zFdwE5#zIV^l?hQjFYd(AdIifufZj!xFS#o zqZKcA>Qyk}1_I$e7_Bj4%K_DE(DHn)BKHJcWo#c_F-vyTrqFI`qXp<+VKR~_fuSf$#B^J%o2 zr}k8pk1MYVIb9Z4xw;L<>qbLcy$YRQW>z(hPD}5TLHjt&pPUM+m@u=vx}v(Ke0+Ij z`ONYev-E`Krs;wsW54I8=tiWf=CNLmg?SSR6($P^JvQ{m%Uw78FecMj%i;O>AV>nBeqq z^IVo3G)2bk0qQuK1VE|)e6vaH^yVGiO0MApr39~czQxr?NunNwZcW>k-IG>&`2?pm zuysW%5%A`HqWkXN$q}8Iu|YE(1E})vT0Nw#B7H3Cg>)5K1V7fB1W}V zM4zc@hwLT$8_pjw4ruXJi&iY#%RTSBT_D)_=#5`=zSwvW{htt51uYEj{O{PH=)aoo zOtxzHlZ^avOnEKcCVQs78C`zhkFNCGc+GnG=_PA4dK|9f#K$hSg4xi#PTuECccFT* zM!D1So+F*5=)cEC3fB-kaKKE2L<)hAAdxx+&lM8^|_RGmC zPiEtjPYe}*Gx_<2%!`>f6MwF+X9iThL$Y7IFk*@3rff@6h@#i{``^O+7xPu~=jJQs z&&>Vi%jQqbpO`;3Uou}bUod}UK5za{^M~d?o6nj5WIk*Dqj}W)f%%O2HS_!C5%X!Y z+x(vSl=-CjUGqEU6XxUQW9GNb!{)clL*_TlN6mjQ51QXFA2Gjf9x%JOtO{{hmZ{Ci zDaM_~cH;}i?Z$1!7mfc%h{y=z4r8CO!}yZ%dE-`Nud&Ct#n^4!ZQLc(7(3~0+{orl z#@`tC7&jX?821|YA?@(Uu*gu3mo}#3{ZsL>DB+m@U>s!skP#_EszKx#DaCI1}?=@5;5C@0tIVU~N)DgG0oubXdh@mIqB74wTQAHwhNO$8-~3Bmo= z)cxi6?E5?Mt_l?b{Rhu`XvrUu#dwv?U$FU#@iXJ6#>-@vk16_mM@ax^by6a8Ln79K>q z#rMeH_jJSlv^XMez?-Snm;kIyG{&1Lie(m=h4fa>34VXVCa`Z923yS=%@ zHNK4CJuy8ix_%JNP}0-xK(KoBbbyjZ@>TFyc$)(u?_9&sW^)f~TLY2cP5WXIqFGj$Rc*VscFiz=kBWBJvrvm#k%rnd; zv(Y@u7!22B9S%EpE2G4m=J{!xagCuy7a=*=A5`oC#{V+j*RfEG>x@mtdUn4+rg5#Y z(daO)GS4)pm}eVu3*^6i;MJ=u+E z2I?$MBYR{beiO(Be_y?o&zbChhA~CD#U%9(zWx|=!gYSYN9GT@730K*FsF&iKsY%* z!0$XE$Mi+w0`fAx0;8I2cmO9qwJ;Y78aL|%ux5Zy`5vlQ=rJPZyXL=;uER62GhPTZi8T=0cc@IBXZ0##`bi?DCAq5aVs*BjaP^1LH&EkH()= z(Bt%Gn)`@E%AyIJ969a#=a0O$q3{2g4b6z6@Ks&F|eTEu{XQ3-19h- z|2F;`1OI=%sPkTeb0!zA;gMs;<3M~Sgg8aMvUY!(-Gaw1>AgUC9}}(l(vYB$b2SqaGxl-CDSOJ z2fN*XzqZBxYZv&}D=#5Dks;wP)@I%v@bU*^mxSM$VW;i)3fj{?Ck6$Inelo3m8`1d zzeH&cjceUbWJp2|YJKI&G|xs~F?$N{A+aB`d6T9vu$rk$Y$0PB!ZE~+Q8*lq?!ab0 zjm%|m8n#3&g19&+3m+CYTIJnFx}eRpqn#OB*qKBN^0);}UT!Bu!iEMXjoBNJTZ^QP zUVlyrGm)OJ%HffHS5(U&Tz0@fV%w+NcKv$0dQfLpeR z*i2zbfp3jufW~gKHf{glh%gW((ETV$WH4r?H&&K+KV4eTI=F2x$TI^0sVDLTwuP9q zJ|mhrt0=V+!Cs1AE^Q-_yw#Ivv4)E1zMCVWIojDQ8bc#S9;UBT=6QoiQn^IpqM}>a zJEPrhx)71%#ddS6m-R!ReRh+ypN~jX&4e!(Q8~<_b`yJnV z{gZb$eR5A{@s?2hS3pDek>hSe=usE)B+ zb&OGMVsP?|XTIR1p-GCf1c>N8JxF{BdQ~X#11fQl!fsD3{g-c@IPKd%`p*-uY=8gt zPiBO=WTYG@92mXTiGn-<{j-k9M4zsB!7#GIm@Vqkwr$il9}>iVJz*tqT#;S4}tNfzWB)g_NQCB)5HNf6% zEFaM7j#Z8agzQOF>Q2uyzb(T}fUrC*#9-%7M!rnplFWOKq(dgP64(n}uum#6n#zW* z#%*WH)CX@6+qy*k4woE6SWq%3AFNaL_w8d^x#$Xzrw?GAd4ed&K~E%pA8O}}j-=iJ z+9p3PStX{mKtGX$(!y!u2LLHiv>6-=Z}(xqbD?*`!xn$ZBoc+54BV)!jaQgDLbQ!e z=Lf_=ik_cnxJ&k#*!D8ZgM3|b2C*D3W*!@%hU=`toIG)Q_Ch(cDb(Qx5F)_C;2&VU zQLtW7Yt+vDs&HC~^{T;rtw;|AIvvHg_iDb4^#14MdX+!rU)FBU|LRqiF~9Umksj6* z|7i}Sh%oZBMX#lQaoj0Q&IQrG>5j%y7&*`}wvl+Q9_acfN~tm|VH`wdh&p0oV3`w2ypOgwINSwVj7hWYP&)?!H63hn zKu!*b#EJeO+;2udJEuES#$X>3=aNFdx95xHr5Wj1fLMXnnDN*Mi!$*yc^h~lFP*W^JNFD4MpnF`K*)4xB^X>;!q`j zf9^388ITZ$4I8yHrhsJtJK@ROWe$7y*Fed$DXv3CbZ6Sf49LgsrV#wg2PKDbsDn=W zjgoy&7$d$QX|3BA9gU80KsYPKz_T6p^t6xcln9a0-Q2msa>go~VmTUzCxd)Sh$)VI zX|sotF(62dYqQe0W>TH$)UNrZSE;EHgmo|?Ev(zZ$pEPEG@(&bJ0yM32^zpx9CI-Z z2HqLhUhA{Fo}b2o(xUib;;&0K2z577li{tO47t6>_N=fO9(m_Y>_$#Cn^`jzB_+$L znM5XSB7}bGfmpH2T^WO)L;h@##rM#RoyO;#p2+MAmDYeXBtj*(goL_Z40{p}VLrkJdCA0{>XM`V zg^XHZQgI=~^pv?n%)pW0^$;g&y8-#Sq#NjAdl+^PjS)_ZodHXAbbt0DvMoa;>;CLw zCKSnahPq^T-(b5*`?9!10+KIM`6*sl=pkNI+ZRQ#kCx60(3AFKyS({k0IS ztj6mUP9jwbwHXB0q1{Hg@aw}uB}=eBr72Y%-_oj%ZA^J7cN5B2+HU#G-f#cp3+LVQ zRHIn^M0c>1Pp3l+P=yj=h%~~Zq_3SxUF&OS z(n|T-8ANiso}fsP`D{HwkwfeNM@>*jv4q;Sgl0EfSzYJSs1w#ojT5t+fzkUQ=>w%{ z@tl+12Vwo7LF5Txon?|{$Rw>)XCC81l7Xrzy>jI33_J;dC=_2#Xt=>Zj}XR=Ll!Uw z^(fAe(e9IeC+eXnE=7ofATul$P`Icvrx$)^1Lyan0Jq9gsBX2UaHY@{Dl!@Lz6n%fA+ysKRfGte`@=~ zzufTgyPTls#1tIq32ZcDhST@Ua1r*$)@yIwvHtf#!8KgxXYTq=N%n(_)}Qsx&eyN{ zSsf?pMWDW@m`FQj=0NRyV<8kNqd+!)fI0RNuf{8H*t|T8vjZioCs%3_@ zVjm*QAr{;)G{k1aFv^Rn<&edD$Sc$(GhS$aY@TGWQdo_Bq_EZC?yZRSRvJ$eB-p~J zo!xuhIDOz>H3~;oB}c>l`Q0~W^62!Pd~qqm{3UB__s;Z@98E1BYCaZ6*wDU#ckh$$ zP=5}j3^*7Ky_07kzUv^!@(XbsrQdbt*bY@Ux-;E7*pRoWKlijE$~h_8hA7p$u2)5t zy$U7Y*sIc1#g=t0jW)5nXQ@|bell-H7{JaInJE{y5@#wFkvIg8(GRKjQ`WhUeFlBC zbHeVWsebU}cP@MLPuos>^3Kh#U-ijo4o3apTN|E_>H9`3(JWc3baJ7X!>y1=28hOJ`i;L_Ty>AH#HC49{jFavd zzvFq;rw9ASPYrg6NJ7k@M9wAuOHD+7G%BbM3kj|tofN`ko!z;lOiWs-i?+Xs4LCk@ z_H6~&nO-_Z2yC>oA7Qnj{Bzh)ZyiGryH}5`Ej_+NtTzxZ)2r-h2jb>&n8m@(WgNu^ zoF}nx2uXmkTB#c{Aa7H!yL(4gsu2;T=+zt8h!j$?aQ^)^`jME%Tlw@M_4?b{>2rUW z&Q!g_{W(V;7K$Hq24&O`!unvn;gW+nD;G6oROIRa^G1dzWCA?9f_jn+dwNF16Qz*5 zhi5N_&t^tDZBkL6sZ`WT()Y#a%^K)cBi;x_wF7P^;L3Gm#GT&Y-j;bQpwrLUEP7jK z!mpwZWoMt18j2Hpy$Xrd<7i7SZzCvHxafxVxdqAC?Rtju@vVG2VqZAaxAIMth|WCQ zA7v-?Xb)_EP_7+`gVdZG#pmNi?dCIr?Dkd@y7dmkl)$A~zI1H$I)+qfg~BtQTavTq z&b6H!*a=}Nsdp$zy*PX5$Sh@jGUOnH^#^GvSv?*yv`_B)OqMjlgbs2ie$9BQj^lc#-QE z(n`(gZ50S7rb6hEjot^-=a{ky99bIsXagJWXeyckIOG-0z(|NzmAPTVX;ML6Bf`gf zGOm>)*se3LC6m{;M^E5JHWe)01Ro#faHFRgcdj#RQSBA>27+@G4sPWr4cJX^?_<<~ zFOu1KA%a20`ZAvlr|&UvA4DEJs~9>lH=QF1%$GQ9b%cXR{d_WkcnV<((!@nc+f0?+ zEaG$?qce=Tn=%jL?1v=JXreJ6wwW+x2_b3dCYrf>iOXB7u(x922T)$fQ>Q% z@Pv@yjtYv*p*UC_bnJlMGp+VYvEDNr+mlH$Sm1NdpirGfCS2!m;v4{TBJ}JLlJwsT z#q`v*I8rgd2?;cBh>D0iLD^>4h7yOIf7UASNhFrc#a}qMmVf;@O$h68V}{A<9o`Z` z>K%VRYG(hr9tR=5l2_*;Hn%!n_9|AM#Le=2Ri~iy zRiJH^*imU+hRj=mnuyhI2+YD9~{1H!e{#*=-fl6UuNR;ixAhn;S-rN z5Sft~6)W>>9?-{Fwf+6s_V;dcjN0|r-##%}WPQ;5C3SS>4N(v}I)hB9J#voDz|X-? zVVn0#<-;~&L@}-7s1%)^NT~U`**9zex4kRJ6#zP2qPf&N3dh*cA^h%x!cJ;@CJIa0 za$B2-%L9hOrZR0=rh1VhgP){La^X?rNt?@7r}>;IJZ%ceeKJCUO&jW{WAskjvOo8` zS6ydLj3*|&mx(&y@)?;Jr`B*~1;`UG`qxcmQxoDps)3Yjo?`Ih`b#H+y^GI?-s9x! z&lK%bCLYRCoi8zi;>d!LX$TbZ&ybO(iGc*0ob>2AXHe%hVY8plupOTx$0`#ipjpqG zI3#;w2O=Z`fi0VYIElaH*4&b1VHx?#tx&Fy2OVnY;O9xbp^_yVa@$$%F!LeC@v;ir zfOCrO+vEC71~N%^Vm-E^ki0F)lZl#`K`&WR))-w*>ex0$41ryjk~}E`|IbT|P|lMPz^5mZ*wp-i zXg0{Krzb-JJs?D-=^-(SIH}o9Ib~;>Be1MhiYyhjcT?`vRH3Jn+^BP{z-e??9i$cK zyW~j_XUd!mUOhav&);D?WrHW7s_Rxu`O8qBY0DOJxMZMMJ~?&Pq{z+9nYuZvBpH4a z$c$(H^fx`HK9F{c`oi`h_Ti(fpK?plRt>4Mg@9qpvpJ(H(I*wqDj&DGv`6k+f!&IH^7X1<0$nmyB2UTXkcJ@Xvp@qn4U5b+W!4Axbb=t~)=o7& zHI<(M_Fgg--18%g3^09aii|%+)Q?t8e*Oq-2LVz$XQr%I?Q9Ol{k1nnKIHMBof1+9*BqI^L$J@$TwUv5+k;^g2GW8HrW7$m5QGp5q_GtIRuqJD`|th zZp!S37=cj|S5MI3-Z~x%hbBH1fl?ff;~KJK@c3NN+UM*>PK^Zatzc;=ER%5OHfRev zKdPzZOP83_R5~E=2HJvk?xW;D;=UYOhyyxVWbP~epAjAcJDii8CV*o|ISk}xXQJKQ zo)p#2a}SLhC}iS(UNLfVvseW-=Fi;D&?-S1@~+Q8iv|uVakU&a!v?@jW%!^{6)u@E zf%1qjeG0@Dnbx1!*TurQh27`IxI$*VIwl{-!|dz zz#)Qq&yzqHC-w{~x&H{`bdKXCm)yC# zMJ36PFbAO+CB17^RBUckP7+u)@9k=+e$-iKuHNPJHqD`!8qq8^{MbTdg6&KQ>*>i* zK)(^@&jr=YnceuqrQKKZ|2wg*`m?@4HbkDg7xoQ`4Z_*5=~qTz7^T#F=z-l71U!zANaaBM3BcgTc<1A}_YXiR*Y>lJ;-6<~fg{ zvbBXxHbS5O0opQfOYd-?Kccjwoqbayl{hzAUY~OEmFgYvFjZDhWCr05Pa@G;3o{St z1lw5;?%myjx@5YK#JwvVdQU9rjDVAvleV5rRp*}gb|{%D*~wpLpWw>NY&1UGMVHvr z!-9`PP8eWA==+SloWwy%!^%ZnvpqomD&Q zsgXaXw1Xh}`^cHQfyJ(UG;;?X^_EzbthE(h;{HtgPp((Fw+hg*c?G7*K(Rh~-H*y~ zEx1>R`8l`#grr`<6NTI^CW}$RdZ!ZB{phj#0Z1T( z?YJ3glMIPY0c}N8MB#~g+KM`;Ki6ikV~KQtLmec>qZ8{L4pL7d$2AJqPmlpR+WW8Y z{-g+2~dA2F&djNZ&Oc*!s24v5Pc%dM)aN^ zCMp;i8AZclvr}H6h^2^TCSzAo%n->0J)6A3M%i=wds^mxC3dq7kfG~K7RPht$lG2J z+icg3`ngS|>grG+8)WI@0c-Oq5D}SMO6KHH+6;b@4no}({(UA!-}0wY03v0dj~Z@d zugYDo3a1a=za0vd`XeO>!m2Z2VD~CT32c6_=1$x_IVjLI-9$@HpIjD!g5oV4B4~OmyWF&&!cDZ)p0;9 zHc^bDJ%Vouw!2am3?x@?CG@6=%Y6DnJAk&Y$FOm*NnVM+GDt4{NSt4>6fV+%2mL}% z&vouk$lXICMB{b*&OQ@)j6MN!fyeDo@$*=i3X$trH^We^m*i}?+80lh1*cA2` zdnC4bny`{CcH=^8`<;DnB!saZU>lHn1#~!eZl0Xj%K@eL_Sn4ynmbC3fCgG}4a&?zON zm}5B5!)N@F9ls;To`|I$>S+wcCS-VFpi9KlUzUWA} zDEc&PPmj6Z*g%X3pXd7sqr(fa?qE#%q#`|$RL3EH*RfMXo`_`0wqenNXUn3EBQE}^ zEV}T%^WtUE`Bw-rsD*#{$W=teH`Yks$X%EIu(N(S81L@ZZPV~=yjy0&oIC!M`g83_ z-G)b~9+WTTwD7xwTB2jNKxEx{H~Etvg`t;BE_+NYj%|Zbb=aCC{V2?N3SVt}N#?L% z4zO~?q8Cs%zA)NMQoK0{V{l?G(jEp4h{h4|_ISg0Cl&X14bAhF^6&yI4*F?FBZM9;AmNtFk!weeLeHD z?PoVjm+@Qs4XU3I*Upo%u{2e+=!Ns|+O|@N^*F3VIS6s#V`L_t05mhmwhd+8lH5KU zW^-gT`CN}0CJvHqh`ISCdK0@J`0%g~2C2L6;4y-HKX+#=m3YNGin_g$Wd0M!8dL-| zJuiOFLD?3u2cwtZqCkGE)r}(>N03j!+l|O!^)};;K`qw&c=Oh~2}>)SjzdchuXwrR zQ1p?GLo3%&qCxYF^wRm(93y>6T!_m{jW?*>FGt(OS_&_^q?_W%XJ{?GPuUGTHk1K| zi&r--NBU>Tw{gVK{q&~iqLH%g=RO>78ax>>UOjgx(Mj_W!gG3Z8h-LI-YQ$th?36x zZp#K)oA}+06{!4s_@ZFd`LAu?KX@hD_CZPS67!oI7QNtPrO%da_$&?Z?x1ebha-oQ zOJu%t5;6RNjt*_C)9p3H6hf9i=+*RO^B0l(DQopN2OR6>ETL)&CCSErCm6QC4gFQ_+;_~<=0a#`GQD2|+k zNVZTv={RITF~o=5j*z6eBuU_cWOGyG(%yhKCh*gNv=vf2o;Mtx47S_DMcCi+Ade;70zSEPV&sf0F6~ImmeP+@Q*t-EO@~Z<> zS2m#?vO=7`y5d>%m*T`-LQGzQGCptJBE*yhi1AEvn-Ei*qEnN=^16|Q>xDRDDs0)* zN_=y2ybxDa6kR05nIntm3sGNM;tWj7vadoqgq|R?Jp+0!Bb&rSkx905UWp}&UfNhU zdz$14L`U?{yGYeo`b>|@b}9Njz7+W(z7u&I6!0L0#nG;sE8H;LDkaz4hf&*~kZsxO z<|9H}unDEkAh%hUxR2h0UL96LJoGd7;CEoqV}su&-`GAfjbnr6Tv&^CKaAYpBOj}k z%w=!IzH2gs$%*7n0Z;T0ua1J6fXTbX;^H;YOUe#yd986o*}k$vTQ4d4Ero!4h_gq7 zpWhBF+r{hf&Bu1~k32DZS{%?8FDUx;xpwl>jza@$W3Qw-&5zInMi+k>5FixcM`lmE zG=oc)-kv?J`0m-$I)+|)BKAr#Lr@moRZJL=G*bL5#TR1co5k;LZfJPc? z1m39AF#H-vocb0v!k{e)dU_B0A&q8{y3X%5j=14r&TDaUPV^G86(6Jb?oQP1_sWJm zX*68)!ko#JKiMU3p}eFFP&@;4zPk9sn+Bsrk&CSVb%zV;ExRO#^mzROIacei5 z9f$U89(sUqXrwo7MyBdL?1y4;>chcXWzRDf2|=NaBW}8#dSYUt5G7NK*Ef#XwcwWB zVsS}*@n&U57E&(QwLq7?X?)pZWsePfq+lLs{4sFt7S!&&;{8Kg%c67EbsQ=LMi;k4 zHpkZ|f%_zQNlCQ$u8u>qw-J=)D}_x+HypmD#rL0U7lOZEu!+Jh8Z+?up{?+5O4f_T zi1YH$R^&Dz%3uCR4v7CEhr^7`3td!uqa@u~zhP1Q z;gZATyJ0wR3a*veO0-RFvxi=Iw!V7ylJlNLJn$WQWIVW^knW&a)GFHr^}Ku2eNB&& z+;q;a;rE*#A;p6c=9DF9dq_`jpw%xTZdx=O7=NT>VaK71+e==J&Y;keTgV*IUa+AM z<&?a3&5RpI#u6nvIu50dbNF3k%3Q3@)Jw?aZp8b2N#UoP^C0|oM2_j? zUp#qBsT=lH9ag-E!bbi=LYn?AxzZEyn~EQJ3BJB`0M?6V4@kn5qS0&a!+S5;dkKYZTp-`lmImbMP8_&sLDXBP zCLT{bF5>3!*vE;-&E4i+n1{_HiN_<06OYFinnx3l4{4`3@E=KL?Bn<&@kh<)5F;5W zw)Q6;FMJjD=Od*$rH^NpEHK7X zyy%0TpEyqT0Z0{jMEc^p&YVX$j_1}k35i)p?&zJ7@y2R@nZ^bkFSTsgV2;y3W~9dR z58H+f_i`}qrN3xh{7t+cl&(I_hjL>Sj7)sVxYwMT8-m>LmcG%ZaAM`EOLZ)`L9MCv{Nu#KS8f7UzJJEe~rrm^38Co+{>ku7A>pYa5n zJCtiVy-VR2sh2*UX|%^q7+bA(qSc;X!Pm)Nv>N#wk-jEc%L^x4*sVjwak5EBqSXXl zbcqf_en(w1^AM?$p;j{sq>lf{XXB@BDWD90pV?tcksJy=m|3EFR_!% zSW>zM9jA9{Kg{Q)k7pL#m)u>9bSRZmk_n6{GkUl5jon)k_rl3md@Sg8UGGqx3rfkI zcqzU-zBR^n8E(F*<5{J{Ow{={b1(T6Z_xg^Z?q|5$UkeXwKj1_@#c7uwKlSlT(Nt} zq`%@MndYm?^(eh59_WO_Ju_O3zhl9Wf+Z9VDqWkZkui;3(NZss4h{N97o`GRSFm|U zd{@Z{f0=%J>28V>SQX0=5hEiO*JZM7w~TX2=$PA2^!7R=aA>55!U z@8of-t@sJ)Ase7?OU;pf;&}Xh9jbkTZtapKn|sM^9uU2w@bNpWtBdcm;2O|GCjCX*$)pha zD|(ats;#Rqe{ec!q|xy18JoKN;>9dfu-`kF6V3%qc$B~}I9+LhWsw)jhA zMvnkj`%PcY(c?Ovb@ia5WFI)3OyC!0{=fKsW4s%3zIDF&VsU)}@95nY%t6nSNq_ND zGSOb_DtwLJfbx9QnSDI7@OXT1;R(cj$@3dNlI$f7*7>Q;(${=(z)>%pY(?(}-P%=D zL$<_PGUKa@8;U+eePEY=CQ8zO<}tE?B48FjsC{$arHg$zTx?xDcwzBF1-Dxl53jJ` ziti_r{>-<@j2xA&)JS>{USeIG*eQKHGc~oSF0}w5Ydyb$zb89Nx;V90`X--?p76qT zXwXNx%&GJ)l<;gWK2mz8zs&ekUK;cQ#6-`399)XUZ##Ya8gA;ZZ|d8Y1{zUJ!EyoDsM^dR`lKhzmE^l+GkPif!W_rTJEOI_cc*3QBsrH2dt z!P*II!Bx7MO!`9}Fry2k%Y2011>drEq8=RXna0u7?&#Up&VgG!zX6<%;-;REzKPcg zOTBQi4K5D4wQJxQvJG6#agIgLHvb(|ST*D-9`B3e#b#TyuK0O3bc?m6 zxMpB{$PQ~u=}Q(|17VYYXlDv#U)UPRHDs5yrJzQJduGY5!6%X%tSymMo?lrp*^~RN zEve_FZ|U)Y^Sp2lRUtuNYs;YL$VZklc=3RTQum@I;UoW&C$!DlGT=3`%h1%{d;VeD zpqGG0ox>h$&%lv|HA9}V_MlDRk|x=T8ptdwCDYn7>^U-r9<}xq?36y9Ir!4SHL>m1 zp24?!e#1?U|E9Gkg&*7RFPh_plg%qD=s)x&au@uIhzxVvZwjm3BIsDxE`LMeSYKA{#{d{<-1=lGNGU*T03KQ67SMi7R9{Qm5^OE7x z$1{g-EomBh3?cJ8zo9Ray=1lZ^VD(aYd%tPg%{4DcLv?sRRU;`_9-@BD)}&7oJP6& zFMU|s0P}vb4=83c2QDvOi1!I{m0n6F+m^F=pK{&LuA_+Y zob>U`()R~GGVsyJo`ElWegj`6`@pyHL*DdP7B6e^!r5m|(5+o%cUq7=%bwskPnA7C zXyl*<9TwR$Xot32rGp-X?73$U%7)1$>agH@&}*LC_@(j7L2nQGaPVN`mxITcdtug_ zM~q)u6|k)~kHWly;^4iR&E3}c!S|WZNk1~JI^&l^ZXa@NXtDYHP>v(RhVC{$H1-ce zKEuY7kGW%5{jfQaxD1s#gJJtqrLn2f$8QdMit0S!q9Pr7% z)bQcYr&b%k9R4!7hrh1<=}kHV=}tgrF#JDHDbb1ztW4LvG5_NXdXqzlkn=*H26Yi8%U=^2Q^^bL1octU7aC!M&7+`Fz2>+Lz;VJL{CX&N7CsGtst}M%xPR zjebd|qnxAFSZG2!%kXHmju)RwC7a_YHcZ!_TvTTnPuE$eqTJ+<=YupSq`#-&cbsg} zRK7Zt{E>>x+;AD6qs2JsOZiGae=M>mDxfvNJ94}EqPZ9Ke6h5? z2y;#Nv=@&ot}AZx($O-FP7mLm$aAMi;^+T6E_M!nf_x%-$uwW2n0W8tSY(&(7ZF0~ z*d^a3#q2}A>d!oerCZojb5m2;Pses+z*jw~xoqbg&3Jsfo3k4?QBl0hq%v^)3Hb@} zTD+m?MB-~=XMDS?Yr#WY3Z73>EkV}B6;j>0{L;z%Dd z3u+Mdob)5JpbkGQ2f!B`%kz(a$^5Y3ZE;+ubSas0)07`n5el=?4mX6(3(DN~ZYU~Bv} z8BVUUx5=dR;lF|%ROiH*iB5qd8jkPpiLc?AWU%1;&|!mg2TFG z_??Qs7qPM9xOr;n?-A=%{C2Q;YQYoa9+>1f~24rO0!O;OC$1&=z930o^wak>qvRTJ^)&frqB{^RK3;U4$W3oj*aj#-&7kZ>9y&#)QKH`ZMG^~m0p{=gE{7s&`U01 zt>jLnD2@1%$4g!=*;4X!3Fb6qNK-99zg_a4Am!-7TFFPTq*#o+P$^PMR+l`VaWk1r zje2B#$n;YTMru&%I`T4uwNxDG)UB<|MDS0~bY%;#nSz=bmR?&Wf7%PTiuB0LShvA# zPjB&0KkH5a54hk?%3*Gcw$zbqp$Actf|!M_ zd3q9Y%26DUr&z1DbSG5SaVN3J?qN~~<+N>fq)t&>#GmX=R;?((V+*@4>Pj!UgfxD% zv>qs}Y!YN-%++HZh9gydq=AK3x&bv@z7M_+_g}HrN<{G7!T!M2FVBFJiW)Web;Yy`p zZbM3u)WW*`5Tz7F3pGH#npq3Zr!RT#DK7Q~ zZyhKo!_Ym&dzy9cEw+u}vC0L8EzL=_G{h`)rN#6@WJi**gmNWju@l)^U2HMdZmp|_ zY*`DGwVx!ukuS(Z{;%(W&l1EUnBiFKhN<~-7BAvV^kdJ5agmenOON0Mr#*rG*RdaT7# zXe<6C@kPEZa2G@rDYeC1YZ5asN>Li|c5cT=tHoU)b34+idQ?6}6wPgDXUshJBvP#u zTcot*YH7WRkxIwh&g-zXSQ?Zu?wH6IDYeC1YZ5asN>Q4~3k~C(M_Mh!##&WRVLREf zx@4RqNwrdJ(IPE9)?z8N6@QZWBHxa6kBul&YKytnBxYcgqBP?30&XHEt zqw+DLXq=%vKhBY@_HvY_9_vZ0(^4!S<18rKR=c(Z-VN>zkuOqei@DY$W?+<}G~)9y z=aE*6dxOLrX;nS36}FQtO0lgmD^INyTeL_^kF{8e)s2|NU)xsCYzw@j-J_MJWt?kG zVg`n-7@LS$=vJ#@B<4sfDTR`vrSMniv=qh+Nr>ylP)@do0 zkC+8z+v=HZf!FNXDlTZPe9D zu|?`9&(bX}X+imjIj_UkVrfuTxGN%WrPLO4tx3$lC`D<++n9NuB&M?Nu8^1`t;)rD zSfY)3Va$|?&%?x)%DF3w&cncy^DvZ!p2r>n(be)$A695t&ciNrFN|WAQd`WmCNTq} z6s09&j*(W2d!fV}X;nRlInhSFFlJ~^#2k5~nu}rvPhv)?KGCWoZ4N|N%S)n&1CQsP z7rPfn-b$%0=30}Ofl-Rmh_~Y$Bdr$qVu?A@s(KJ}qK$fC%+Q{QIr2y~7sU*o#Ei1g z^VmZmx>{ZmMNhy(%<0AHXt&Wa&b7vviD4_o#xcu1!2Eut7{;v9><89x4=|4rEd?=? z631+bv&h8jIr4}S?xlq>6Di}2k{?=BPqmeq2tMw6S{_=%EJ}To zabA#)&WyE;bFIlZ1H+c)Y9|@9B9%^zjC1~cn_P@@qK$e%%p#MI*;=7QdO=~#jIZ4N}&SO>MKZ@Y%l++G2gbR;vc&w5`%vVql-gphHHjG*r6`T~W%W9>knzqh1&@W%A>!wp7l2s3>M2C1#WsXOXmkm>-h44KBSzYgnOWiTN@2 zF>=9|GS0OoF$2Sv=87(eIntn7+{Yy5JdKiwInhSFFlJ~^#2k5~7K>sAPhv(Hd!tC^ zi1{&zIj;jT7g&~{GVwTzEn4HZC}!{^ zW|Xlvie!$MpOTpKIuLV#Wr=ycyFQ9pN^LRMn#2r@Qj|t~!8k`6BxWEb<~)ruh&jx5jgp8t(MG*6W@t~u9C@S`i(&>(Vn!Kzqe$k6`B{lMuLCg`SeBS? zb#K)uw2X7DNzA~orFjQ2M;at%ASLEJjgp8t(MG*6X3E6lEVgKk-=dholbBJ)-YAke zV!l;k&g($T1(q4J^RDx*MxkY#Cu@p|v3TkRa{6IiH88i-n8q5Z7GtGsJ1JwORa2py z(o|CtN0dccx}ua?CV%&irJZ-(GPg{vYZ>QSlW_)ytr%Oho+Ay^LyU}bo<>QGbE1uU z;W$$!9%r#dP5c&(Gk7x2D9fI(Iu*$r<6I`=oY#SIF0d?fyTmPtVwO@{%(W&l1EUnB z5nr&LBMqbzDKY11ltIjiHtK~jQznjCY^i;>q$pf-iKtC7r{hOe>dg%N{8*Fl-Zk?KtePcNtITqgNb*Bl=xt-VKkaToz5&(q zMc+#NqpwI`_nr8e*VP6wSc6hE%@n&2XOw6~Dsa z?BG1|;IYnQcV%Uh^B#YN1C;!)a8O6(^Y&ToO5E{}M;CJvqZ`d8=mPR>&SU8V0+Hf* zT={92!KCI_Ghg$wXaU=2gw(Jg(kiu5_N@v)bv8%#|_+m_Lno!esrq8~kyQ z1x>%sR<|j7t70BK@ZR=zmJAb~@m+UQMZMM)uWyn>lq=npe&~p~ z7eBpsY?;xDCZuB9(|bKUq1BK^@K(6 zFmt@8gTc;@_WKLhgL8T?k~r+7STRiEzX?`3_1Z@Mp);dvi#H=~%kIjZ^h1AKFp)jx ztoFw_Yy7T=^FzD8FwV?895XOZ!JU-0`zW4H`;_Y;TA?2n$4R|v&Bn>L#>qLBk5irp z^T%OEMsdOtdm^!q`irHFIIFIaI7Ko1=1fe)Nei-%3STqMoA`(!t<|7NoZa1IoMoqD z?LW=Ah>_c7<3z-W6Fc6W-PdvalW|g;O_+(%c#;yu3BL>D>~Rmr6IhIA`#4osVmu?| z#c`tFuP=_1&^S(MMR8(Zx*T!pk#U!Mr@umtr7zbKu|5x9v3F`a-aFAdP2lWd@8phW z&jD+q+e|tp8fCeg9fT+4CCcm| zKK-5@L~m`XY_e2aR*Tij=kthdl(H?=z?RaogDT&)HH)DQrPs(H>w zs#UR?cZtR>mb04NS(NUwL}hT!GQG=<*+H4<q&B)kgiQA(l~!^+4VU5NV6+vD(U7E8fLf9i8jd4(S|;%ucI?bnjwn zU`c*9$Oi6mXA@>!z=)Zn+`^p6$BZV1bmka|8On)ALS=L$6sg)YVo>m#Uy9*K5Md?M z7j4sb`HBb7R!?p=P>kBNvatrGGtYY{XLiZwiQFF9-*uZ&zFc~iF362 zSWa=VY@r0W8Iz$L=_+kYwNILjfOT57xzsoxUkY*bW{aG1#8QaSR!n6)inci^g~{4b zs>P97F_^TFZ@cu3Wco@?bNrYosD1gaA*I42iBWmdy&md{si^_PF;^?r9@}wB4M+_jN^zvCmRJ+KJ{HuCh?E*PvZlFeVOyn$!}~aq z7sWW$p=hgtdh|mb@MNRfU`sJ-N$EIp+-d!^SmLZ-u_jVA`KQ>Lo;$u}1LzL!vT0jxY9HEH3NK7uox-mnCC}wZan_Q{#2T;m;}oBqgnQ10fb6($(%j-M!#ND78 zGR;J2u6Be!km#g6wlmG(4HG`DW4%lDyZ~CYZ`Vbb$03=&?(r@q6_luCU9V$V(`2uE z)DufBEXlKe1`{_%Bw}`BG zNI!|;Pt7AooGdjJ#Mx-CV>8S3I@Y3W={MUryRLLzbg)k{PUpp7Ri@E-kv0kwF{Eow zzQl==bzHAUGF{=3>SKwu`aJbWZ5wkTV1>PnWu$Y4p774)M}#3S!C?=)J( zJUcDU)m!x>=uM7yT6TpZh+T2J+)}AzPG0u0>|=__K1QDAw4}1kNwZ&K6mK;v zpL8bb(=G@>G_&olpK)9be6@l$NB~FZE>C+j}aiRb_15wwx#YzmleH zOJ&>IR0-zE`*+@HdjHN!@SaNgQpH-?qz3=5e#pPU`|Hbb9fi3qSd~ux4Zi2g))&>q zzrkzG<|QB5T2v<1eRu)Pr;bsDg>h*n?OHJ;?SYhUjcxdXVkQyF@B& zb!7Vz;jAYX{V7+*SsZ;>!|z%jseJPM`fT6ybc=})k#@C0JK4UfL+yA+I?^Be3Oswq3IaE1Jctmp!S$UMv98!v<6LDSP@k}Ur zy^)63qSBbxgrzxUnY1L$eq+mpe72ZW-*u5TrNp_`UMuqJwFKJwadVz_Glh)i7O5p^ z_G{$?3|acCGD=Z>uO(>8jWIWaSGWpEiIdiE$kT2RmgW|zC296s>;<*l5H1UsMT%A5 z&4O1FB)yLkm>a+ozrtnC#R36EYmx&m`e+d~=VG=ZERbS}I-=xUoY!Ks1_bze9#W{6 zcJg?uprDL&i6#$T=Hmj&N@|&1n_Y{&0%tocor{@kvN&>-t~{&T;#AVMRG)3JRH;}m z5pgSt)H-?Dhwu?kvJZ(4$*D_ar38&!MOZynGZ2xC%4Z+qnTX|DsTd;`6B1UREs5m+ zdQ*vXK)UAC#gCSx*)K6EIeWKuvJY7qmDiT#T8%M=7VYeJ9-|BsYdF#%w@8-U>n%ok zA}wC4T+Aolc`PX{M;ftUb)*C5F@99mY0m3FEjx&9%jI6rW025DPw*^;(pCp`I?a?2 zDq31sx}`eJ{AepUB{;>_Sh8h#Ru5_RYh_~%%2OSztG;gAoMv8sSgum3TM&i&junWd0Jkh)k{sN@9@W2O?ZX@cTU*WyAee4K2y+OFjjgRL-I1@@P;cpoFT}zRpl|MU8Y6iX^xi(R=JwH~OJ@3^P&X0HS z+(uiaJ0U+T)=X;t{1}>(v6a%p!75kifzpc4ys0@tLy{@4IWfz#AvuK}kfN#31MDT4 z&U=s@xO)$5Y*~pZ_MkAff24P_qv%1bnK9-2ps07VnCqR7O*D0;cX5AbFM7BBpYK8G zroHmu#?E_C`c@~$cU_?e|Ge?to7Izj{=a2>_ipuU?R@WccJ-8%|9AE7-mIRon*WyG z-K*78Hn8)(%RcMO?nqqw_3It3^h`h2aAzQD$9;g~Q$({RcoXr>@BE}&4=hIaCY~)S z#nRd4N3C|0TdrT9S)J$aJ&cIWYFVLp4yzl=KYjCZoo7l((R04F)yO!`ccbGRQ8$FEJ{C-#}7Lb}DURC~_h zd?v}#Swnq?>T!lf<>6Xmu1NKST%nOJJW7-293I>m=^x6HG-52x+KcsyF4zIZT3--Z zAL^i%m0a;^ElZ2wp-^E!y51QSuVuJTHC7Vskwl*S zJe7?#M3Rvj;2^;yTB3T4fn0C-JgX>hP{Z@f$oWJ`jD#-{#+Kyqqa`KdJFPK>&o2vt zdM5%C%}>;xb$auOlK7b^vA0bvt-tpm(76u#JH{h2|~1E6_D-?QY^fX8uO$Ea+RZH%u}t(uaNyd zsV~;z4eE*cWp&UFKZ1?>IsX@K>jx#&0Pdzwd z8^kLQAW;(^9|z)TZ&3U<+u}%g<>BL8l8N^x*w35^RhOW@p2m2iFEM%>m@~!khbwz* zWk1tHa^N9+Doh>!r8Zm~E{})A+hQqF>EO|T-m)Q zT)Za_iIuB2=+lIih#rt%KZR#{_2zD{9tM|y_JqZ<3`S}XSene$JE0XCwFlxcBF0`F zvfllC@9|(_{Io@3AEs|5MtdM$pVSZPs(4h0QY>ql=u@zXb@o7rZ+aERFPb;-Y!^>P zlx}CtrQ5AfeAbRy+?UAFn)ONB%;{6<_5c=u#yqmv7*V>NdYH2eCYEle$E@Q`jK~5@ z<=k;kZvilUdk$h8k1U+Evqx>NonpT8@{#Oe1 z<9OVcdjh5K*Bg}l>x)vXzvNh~meip4(G+9(s*hT_V9&5tlpAB@uSi%uvKL|X6z?Av zneD4P9JSj0qy1lzboHd4ckapd4IE-?R=O(#2hpt4cJkhe#b9;`miWS%O1iF|LQHhu zPo!emz(IWnR}atubFLn(F&930ku~KgBIa2x>Di~UPf?FzqM8#~7Ym9B--A4op0#D4 z3hq`cZIG=vil_F-nQ!77)O5|51O4 z3bE=nQMRfacg(1xD3KEHi7`L9CkA)xs0M?Bcau+M<}!Ed&JqI_SGXNvH$QKPmQ|s@NQgm z4FWxQmk{T8NPN05?h(ZXZy^dCJ^T&r_2Tt_vg#XRjp91=5%-RaqteUo=VAaS92m+vl11F{aUY&QctnuEM>C#QyGg_99U2A3VY1cbOs2n@s~0Mv7~+&i zsvvQvt$QD~$YY{ZqW&WGFM0dRpawc}lv|w1sM{GQG?0mij&jcA_+2QKfo2}%M2kp6 zo7hol$$jn?FX9tv24BwdK{ZkBCG(<4i6)_24ok{1*-`QHWs32tRQ zDC7DOewoNgZZ&8bL^NAcm(`{^h|?65+4WO;IVt3`7L;k5HRy@vkfqsDB=R1pr0TU= z)CbWadXt#;S_)@L>E$KMsjc*KANLD2`Mo(y{NAOPt29f!7iclIB%ZTGaqc|7cRWk{ z-kEyNlA6JOmDS6d-#c!j6&-K$v?{!p7A0%N?_D$8^2v&{h`-Q=(yzjMX+l>~Mf*nz zntZKEt{N&I&{8=T5z*i!wTYd)OaUga(mrbbk<5hxbhlfgx}`;><=fKANL#f)IyDH| zjzlg}F($6jUTRQk5V6cP`N4iTA4&BjF4a?MydvnnlDe!mEmJ*-&^+2JW$yU{$mdA= z1E_&Hkv%?*^kJ`54n}%_9clQm12(u{qX<*1nVo@KUdRWFXz~$xD3s5wgJY5l8-t$iZ?<_&>M84Dc2(x)jp$7g1 zhrjt^v3?mo$I?qJ`EHwiN50FA_!~`A-fCp8dNALT(Klr(x9v9!UzvLrXUoj>`WGDj z=1Y9P-g2P<@3!$BdH)oA&hpQ)*K#q!*^=4D7XN~ScjV=*VdX|gIYjBs!>`)pujOQ& zW8~~_7U<~58nuRNIqaDBNLksGI8q9rdN4;{BP2n8)kbA)Zr8c+5g}9jn+4itZhr;9 zzc{9KT&tSbHa>&S9~K5aeqqTx_0*G3{_Kek()#s3{YjJ_kJ4k0J@)9MKmPH$b?ery zeMHiaqV#Z-9zuHXhd+D(>3&J~X}b5Gd+xdW?z`^#!4K~IN75a4-2VOBZf$G(-uG@n zx*6%Fo4)(q8Xx%#Sae)F4a)?9hz6-?iV(rQVUUw+wTmwo-~ zt5&VL^wO_=?W zv(K)tKkKZiQ@`+qDN`m-J~K{doPOG=`SkhEe}2-WNv9y4Y|}|6O=OxdVf^?LPZ&4u zc&6iy8#{K)m@%UzeeQFg8#U_KV~;uJv!5L~^5~vmqlOPZ^2j5O_{?X94Lkhs z!wx(2(7L+1p+kob88YOMLk<~?H0a=i+NFU^12i4@kEQY-?`t<2t zl=k1hSFajPJ&~%bdoXqHURAYUw{G3KcJ0!oOJ!vRQ+atAQ?|4e|2DIvq$G`$O0~6} zij`Bg)%0}6nCgy~*M9?bk?1_rJZQS(Pp)fVdD(x16{sAHjU1^;@;JNQd}`h?zra@Z zL`jHO&pt3`f;j`i;ex|uycq>uIR+v7|orBu#<_%JD0(7cV z=cS!Xyh+|GUak96)atyh=@BAxm-jXAKJzuHN13-72NdWsca?M}$!qi8@z(T&&Vn=v zoX7pTh_;@kKf-(^G=T|6_>cG>ghR|}rZk+>^E>1Pv%=>~j=)dQyqY?%Ro?~D%jN4}(Hu=701HNle+raww-<>BqIjMn@S-fdFDNe2HpsXrpP0>0!^ z4Gw#$;o+Zg`ZG8+@z9yd2=BCj@B&+dz31XOYDc9`)pmG6x?jzR)Q;47{jY$9-xr{y zp+67BYDrDa-&v-|rrz$=k2M@lMyH4LnhF}mvDYTa-%1Z*sWedEVQv3b<|WsVF1^GG zD5X=RBJ$=v{770s>NgRXb;cZWLL5u_nUdj|SJOA8A51@ye$_mJe<|#zF}6|qrgLA( zP3}AC-@E8jXM-8;ooqhJ98B(^82v+UEcq?;)rS`xay@mHY`|A8hf3a34Vk~7x3@wP zsbq`NG*=q)^zY3ppba*qk|XnuP_80L&3shalDRK)X3rfx&_DQ>ymyxFEP1Qsx!{=W z_&my#R{KwAtK`#?7n~7hus1{e7Gml=`1)XYL3V5=o5^MuWx8k1Oudqwlpd1(X=Yev z=HTUYAp86DkVAeNUXXb^uXj>urc`G6!EI&xWp2zY+W*1ykh0~O+cKAx9gjsim&pCE z*#DK_CM#3*s@D8jWsh1~?-QzPZ9Q{Q89dFb={*hK^D}FV>4TNr`^LfEWm zi~o3c$eG~<6|yI0K1ORMT2B*S@tjHx`5?TY68lf);mYrzhknXA+V=|P{Xj*(V!Vn1g?ndcYsi1>-&_tK>m_Sa$g>PI%`i1+|;B zHV`9v5VW)Ry6z;cTRD1m6Ki(PcN@kQQ)W%Kc|cqw4P@E

}-!AiaV1;3IhqYL}rWjX5lY&+w-dr6&JXEz^JIuI!I+v8R@d_DA?5N}+qdOMtD*UWD3{ z;krmf3VNH`${t|TM||8n0_c^pMs^ZtC_N&*$s3DuQ|Zg4Q%ZMcF9}D(^T$C!-=|tr zFHk;pNjl7q<)0AJe)^j1G}6LT-6IBKSJ?0Opw4n%&hB42KfN{VhhCamx}@wo#tikt z3(7KO(4Kw-)MrY+mVLWyq*xU9PT&t|q4mW`-bg^R}_Rr?cLh4oi94V7-OBqDx} zaaYz=trW~AtnE+Bj;WA-8dM*QuE1QZn-gBpUG|0UGl?pj2VeGM%_co>7__{5eZ`Hy zw*lWqUJn73jqMSZErQ(mvXkAJ?j>bsre7_aR`KWV&y>9b>Q!aeR$POg88#TQ0cJ$m z?Sq~f^sC_2^1la|;bC{~iXL{GIHy;sRo({`AN07V3>@XwMg6L+@`Eu0@FTC~b9Z$LYby^4lveQGCs1>6^5sdFG<> zJ256#Sz7sB2mRjGGZ(Q|{>(w*Z$ure=N>%b9om)sof#Ez@WNgn4)dVKjL#CJ^PqRM{d&yic%-5Z>mqPX%? z;omg3mMxsIMpU*+#H(;aNhMo{4%1b4=#=mRo`o^dcjOON9;_>=vR}!s+&-i+rMFcs z3V&KTy!<`3Di13?!F!T5CPq{OZ<%^v52{W?l&(?w;JIocEvpQe<$8|bwN+f3nyDDg zP`%$vc6u-y5TxdOHy3@gG5;pb8ARHv7_-FZE%49<75!F%+`O*!v7StsRe zcizEIIJ_4;2lN3>Cinp8Ec|Q=E1h%Pwc%&YQNc!{!&=1tONl)b{AYMkctF_A%nct4 z{uWl5rA}X`MWgYn5PKESJ>2ombhqAn&7H|;!fwv*ocGDD`0ccyt1er4Uc{zpKU109Cd;X=^f#P9OH;l1Vk8Qc^i8|{4Hq|He5 z!6J8VSmI>FyLW+H99B4Iho?Djxl{cY@w?I6!^)_yGa+TG{7vZV^(f!ckqHkl?>pDv zH&WgVMq*@+^0(r-+bZ*Ax8D3T{5no5R>8mb%{Sb$oj&d~vmVjZaAXiorSp?;lJlPb z2kFs1-u2Fiu!sMqIo7TBTiu!L{1qc}HO6`!X3me@CPoI|t1%y^ zhcnQhS$bzK#>_bvv*U~5OqomYE?jQ=Gi+dghBtcG!n+!CYp~E?E~9+_dTfii3o|u~ z{#@^P^wjx{jBQ<5i#hkY^QO5o{4PAtn#;p(!EwPE>`(J(a8lSC)JM#EvntqtcL6v% zGUgt5{Fpn_yAk8v$3NW}fj17m=T5_nM}In1!N~AjcdEI=yzl)7X8Lm>p83YCUx)sD zMP^5p%#O`YO|TK8y*_x(dk^z@d-$7hbFdA4{i=6eaBP?jt_f=~_9YrsrfZ} zXNz+xerag4Q|(>ozsS8oXA5rMaPGbycJnuxS7^ikO;~SUm$`fp_KU2$6Dt6FgF6*A z*6ZHjY@v1hHfBoq2K;Y&L>Igmp6#Te`E~Jar01Kth;1?4N3eFNe~LTb+X(9wm`P7ztfo5exzmF+h`kB(WSU=r z6_9d9c%#s(m?zFU|3y4YQXd}R{YiG6&3<=xZm=DDN4*=mGyQ*Y|J{2Y{rfq{{|26? z!U}IN^mlWo%DSw=9x9P>X8?DF`2)tfhqER8vs;fR&t{^ZO3>F5yZ2dl8Z1|1lphV} zxuLfat0c>QBVVKA$hmVd)2bx8{=xJ9V_1`C2R)?UdN@_yDEPJ=np2ot+p*_tcbmL1 z*s&gk<~~?`Bhahm&IIhG?*!Gs)Szd0F7}E~90Q5D*bCB#tR8*8!3mu-=IYmir`)qS zF5a`)wSI@ScQ&Hi>C^@_VWodLcMtb%zt&CppF=&1S-RN`k=K}Q;XrQ;X5`4A&iMuA z)O*23)O%rVZI^Xdi@EwQ{)S-x;065Z(gzNX5ZwRGn~1IkJ+=j7e6}|lEBvhRTi9`X zgfC$X>%&_ST?JgPzY~UVaN6ISmwts}bDX4dbVT@nFdQSOEu_sKCb-CTy>~C`FSoe20XF5k=Z>_@qek>zed;E>TNvwNI-8bAfgOlVae1ho4@i@3aYJIRuMg%>aBO%!bHb(eg4qt|MEnc(p z8O*TP!xsECaUjPRN6PKg;SZ)H_Q2}!CqYlA$vqKA;r`AkP7`J{YVLS%x%Xw~sPOFY zlyD+;!7OIj_Fx0Xc}h4fxY=pp5kIKGuF&FbTZ9#HkT*a03}-aP zX|Z#qb2fa-_!kGg=!t(QbZmC!1RK5I2K%E=dI!Hm^jK%XX8#axzP}kO?+bX+etdX4 z=E+(3I^oZ;FCFD9!aUsW)Zl2e$UogX3%a*pwlKQI&dJW%-p1g7a6J$ij*UAV>-t1; z5$oNEH5*LEz5@T8)#0-^hNlpF8b|UG@b69Rh*J>zYdEI<3giE#@A-#0v$2OX1vQ-e zh<`hJC=<@c3SNMfTkT)wPsD7!7-M%e#&Zdz>?2@qOpFn2E3R z=nlO%Iqzd%IRLiK#Bm9+I#0^{sNvX#Kg0^29!!SjYw_De>w`yx_cVFX*~h!o`}bgq z^EIwu=uC^we&JUz#`WP>vFrTG{}nV>Vef3h{FvsP<9r?cGS~SL;_J^9?0kwRy82<< z$B>6H{-wm;$9osN7R=^;u7lq^~M>A^lRLJov#8OgjfU zFFXCho5Gu&*SrV4``kXx!RVP2acgru5s0S-wejeIPbe9jzmyQ9Q`4#rY|Y+8Foaz&i%oYS4?D!_Q#_55#%u2f=gD zF~*Ujx%(YwIM4^X!`wsJi-?E4I2CjCmyoP;E)V`I_#66hJjRGC80*m)9{vD3f1URu ztb}@Ziub5{l=Nl_Yh}1Q+1d`55MUB-k;_E1-{pL+uTN!eK2oE zM1I^vKir@BO&Gxz99cGaAGm+?{?6m3kG&bIXB+0#B>1tNV~lw-!n*@DQr;9Gddm#P zag+V%A1L`y|5)ctZw=nbS&zLBy$)SOOvm4=7x+{Bv!DxTH(=b}62|S%#0oqK7@Tjp zC;E%w<6`eSSa%QLm@ppmYP~>c!V4tA#O(0*MsMf z!~FK2#0(w={4)9&9r368ui|J0z5d~X-|ipdo#A5)f^y1%gR=^!$$u0cVc)R2+_C8C zdP?B@A8Q3sOv8SUqn)!j=#O0kS0uquaJKu$>A41G=XC#fSbsb!o&+>>`4gxC7PJSZ ziYN4DdvLT{$6klt6VW;)z#a`Bx3M=7#d!A&|7093zlc3(Hb)RYTfU$4eF`%J`xrF_ zwUVC$kG_ieJU6%(JIJKqPw?!);9%sR3;s1&1PkMXwW>Gx7XEL-dOUlHQSzr!ul9gH z+y5f$-+=E_zX7uoy&3!($e;L)^wFQI$LZkb{(SdeuonKp5y0GW7z;-Zl5)l+wR;#l z`fR#f&5UyI_ZMMROm-hY4!HnV55X4yYw(P{gL4D-6&~p@g4l!ddN{vV!N(@(##Irb zc#C?2x1sk|%$Js62RQs-1pROLS7IDxPJ~na_rf{h68aLn4}N`!YbEr+iO9D*(CA+! zddFj)e#`x{|82c3&f1Ca5|GWE;|Bn9wW5rxz#M8s?yElZd`+sx3fgU+K=#H_f z2;V|p8UA}vB_lRC7>JpGzILA%D=%V14ubzOmoOg&VP>3(**GmYDj2~L3yuj!LBr_a zWM_IXEtnB}QS{6S=3-{d4_3Or4lWHY4{nY6dP=Yk8h`4}3^oO?1h0l^_lG)SAx;m& zRM;Iy;$uUcNrz{Ilbx3EoN#V9ALp6Zx({;1!td~SAKoVM)Q5NCT>Ay*8@Q!%Hg486 z;X4iA6Y+&-%y}~eYx{h?DFO|fg@T(aqCr=PGKs9mHySbY8P_uA5^{`~gR=v%@*jkI z`>T-c7wlt5np-_6;fc_jFth2|cx^NH`r`Z|pD<#QB0U(bs2$fN9_Wd5Qad%kw@44- z{Jd4j-z8MvP~wPy>mEt$mnbSZPl>3aN9)YJv(-xE%@ke5+B@LRvHb$wT+4=ittn9x zuc(3J7ICG2EfyRZF^&XjI%Zn47>yA;>R}Hgd+;2dr&zBLqmG`gf9i|o1NUys5bhkL z%AAl|*o8KT+}W3DkuFOVAbAR_a=&c3np2fbQpnq8?3`d644l0*Z4z-=EZmGo3_# z;@pI~aMkBd_bz2!Qxpx(C8IV+JenQ2(lgExXwyc$JC|~{UoaneoRl*HtIOLNX}dvs zI={YfErH~uCEBB-*ynP`12vi>L_iz%ZPq~lEUv+27r?RN8B+O2G|EOcBJIS&ySeI_ z?s!7uYyg!BXW?IBY2(rnvn{6u2pmJT2b7AV1jZs7nW;gGd%Vb>C^=W3L?j~<^?7ii z_g})5KDTqijx;3XcqNFGgFgv?g8Q~Oz8f7G#P*4410#bx8ZT;PlDUMDMs22z3w8BO?<50-E3PY%r$vG*gEn-fu{Y)3L^LC@;&BY( zk(75vI0k29?PK(Tn+eY!p$^n>oe3(Xr@J=@1-)n=5DD%O5OEkUtdAPh@^e6ZR*$J) z&c`B;86o>5I?nKJhM?&)^fRZ;;4apK`|MFqIE)GM$fN#`dPT-h=+Y}P2V_)8!^*w} z=lRrM@AF>acSRmH)FZ_(XOud|w1PWmKXyiV@B`yQH2aNbB5{;5qpf`SBi1+vfYmXE zO`QYiA&hr2vERM#0V$(x&!f9_-`yJ%zalo{pyMERgJ~61XeURj-P}ZlodFD&DmN zehOm9RLxcrhBpK ziS4nbXT@&sgxINNEn*Jpm5i)5qL_HhiTI0T4~>tb(xc#G&U(iIsmIarI2!V*Sf!zh ziT;ys>)1J_@OmE9XkDR3J!6UBYD10@vU-%toQd3I!ZBldLA3TfQ;vO#mLq3=&(Y&3 zExLczen%YVL`M-)XW`f?M<&$8542R8S2%N`)e1_)m3>U&p>#8(m4fpJcaa>y_1wLQ z=MU<;9jWAz3HL)H9}yFJfi3Y>`cclp^P>un3rC6`i!?ltf#({I3xR+EKNIfzw zfyeNi2_DNi4$gI2vG-W%=(-a8*h=0`shjN&@i=Kg=9ujl@rZMap3}#RART!O=}UB^61~9w zFY+;xj(wC~z}&q?vLR=!r?Bk%ZF>8KaHn?yF+SKtxvxzKa^c$ti|cnlv` z+xY`d+zVHr#l0vLD(`zyTJ*`eQ{Vdpg*tO&)lS!=8u++AqbAgF91$-TsddZ|XoEhv#{{12tS|CBqc^x22Hp9m(}#pnTcU)+s?T@2wxWPdnL}0)0AuQv!O=yM}VK77s8ZY_jK|&^Fz3pd~+=fhX$@ zqwJMLyEQzsR#1~ZxrBZd7!#~+wy#vJ)^*J7`@oH6gc8oYD z24a>$kBnCSXp_Lo)vrh~qCr^Uybm+i8=9CY_-id?M z_tbxw`X{qV_8Ul1FTAHtSyOtxB)T!iaz>-;1@glp-NZ}mmR-lZ9lU6)z!w2Uae>jkO*9ccQR+iEM zuAcC>wTw4X{5uxtmT0Cl@%adFfk*Gs>IrOdb_LbAKhl%)U+l?$7CV;gO4J?n!Zj|v!1<@9 zV1Ibgn_9uc6`Ur$vc=!v`Jb)6p!c5eJlx#yRm6d(?1=Jl&K&gdf6F?r;H0d;GZ2#a zw`b5R@#WR7KEZGR{`L%-@&v!Xy@rOa$@tqdcEE4|R|i*nCaJ%ML8;HPLqpC*&YR_jVsOQZlx>(lglnU<`!InOdN#>RdZ2Y4!MrcBPHo;a?10#RtyNH?W15wuHgAUd%{uT=e~GPW_U|mjlL8IV zY*jD4=z35%i)hJfV4X?#U#+`8R0^oPy36+sspLUhboYRD!9p8LP0%c!t8C;YR+c;` zP~c_o3?)=Hc*b7uM{3BC`weUdKeLv?pMhQj%E!uB+>{&>!o^$>@1y+@0COizloMOK!4 zE2}FD{RofXHJ=kmIU{f_&nHFTE2tU8u#Q$u{?0F+I6?G(jjrYMJp_zI7vbwfst>e{ zP+4jVG0P)9?na2#@lxW+7ogIN*?J3)Aj>u-g(E(~SNd4z+yoEVTa2JeqjzLHMPt%0 zJk0_ObZLrWk7#nQr3ThF07FX>J?pj~U5;JkuRBz2IY2b8|qSYGmZ28EE?vvC_wse>Z(&{{kzcN?m~ms*XVw&uO7+9Vjvez!mgw z;91WF$gx%&bwuM1`CkI3{?_@g6Nx8$LincroC;PjCer;)@Fj!i-n7R=7d#3f!QSix zZ|zFR;0e4iC<)};Rr$~fIXS0IK@Ud--bx$itU;Qqlsbr(DAVXc#IDKqqv}E*i4Otx zCGurNQPX(IqXwH0D@HQzU!@1%hez6zc^%{+%9`Nc=n?cqv%<=Pf>Bd>+G0!=L$vas zp)UAPH4q#1WHvk;b@c-y87Cca>>H~Rv_9}UTFbH)WHf+T9chbZ4>T6(>PUz9f2j2% zMrcjA*zY?^!o#ZDbK12ZdzMuMZFyTq_Z@s&zq*xImDDybtzFW%v~kJu#yPc33zyU` zTiRIL+){f=V{60bk84;k9|Pofo!ED9ZS76{`W`!CesfD>ZOgI+vl^GwE?m}HyRfNt zNkhvyjeYw+c=)1*B}K4qO@3=>u+97$|=^c`%bWC1)YQIAVx82)s zWbJLEM;|z{cEHlM`(~orpS1$=y~m!>x&$uN&TnpQT+%SVwq;>!EouvzTN+v$=ZxMx zyY1f3Oqf5v@f^s_p4+gbVKyXd558^mea)kXcfc61bWq#9C5KzitcKZNS~|aB>D=1J zrL!9rNiQx{Z_uqp3fZfbqf7E?J1q>O16teeJ@#}vX0hU>jf@)aflzU4) zGl(MCFqXo}+Sa*^x@&OzC|Yn!YY#qb=&&P?98@>DybM`^HO$`s*7rRFc zn6vj{9qnl5hT|Xf@pC}mnsCU;vMG*RvSi_swzmEaEpyDQwzhr^OHD&t+rWmU*nwNk z%(k`xGQCYbYO}GKEH!7fwGGA+!(zfBYc*#;XwE`&dRyCpa~8HVn$sXXXW_XmtqaX0 z&>H72Z8WFAKqCyC+}1Xz@x0lMi&~o(wwUp4Z3j1=hxOUgFyEXA{Y?!7p8zoSeKU^b zvKDhZU??#sA#+??+dsbyBOQYbI&$Kd z&i@WGsV-qvromEF8B-ELF5-P7&UZl~{e=YC%>AMH1(>b9z#RTI0mHB3KyC;a<7?x%WXAVbALB?bpKuMh3+49 z@7v?}9`ky&*YxXy>8a!9?7lGJ=o*1+)r}9?y<8+&+22U zpLCD%Pes2hb*@dlpZg$}HGj+fKKQl&N$w-_Ux@G1+{d}TsY%tI<2z;MzYyJrx!Uye zZs7bqHwG_!{%7vc(kf?Xu8aAL^S9j2+<)e}nr~O<&=(s`u5`Wk4m3@`s}?hyUj!fL zUJd>f{8#Sd>_@p5${wr!Ft^aT-uXE9?ewR)Ty8O5jQAwCyrdugv_H%Fk~74)6fezm zgAX!@Kp@qdv&Qz7*(KzB7= z(PEnt?bH57KkYfB^oCR)d=D^~c9@a_%ooh*n7bBzl$nSLs;%)+IY!De%qiwn^Z7i| zM71o+EaJ7f)ztYigOx*c3e%gP9Hu+-T_;btn&)!tTgt?E8ASYv0x2fua@s1UB~k2@ zLVi--@{$OZwmNKCD7E{R%1nUNHQSC`ti>&>Uu9#oYEmlkmZSKqpyL{It+2_x zEupgzE0DZ@l#XpbqD*jc8v-fzrLaa$EcGvfw0JA^n)xkI{1S^n{7fq$g=r90+h8-u z9AXZ|+8T;_9X^L*tzKuoZ|cp%_<61C%sTULsJ#eW8tb8l39$;hn;O&8>}RSmySiZ& z4aBW`Hh#{f(KKV@zSvx9E&}c=Skvu4O{VZO+qD0jV+ub9n7#R2QiSen z_U`l5c6b+K)M6GQ=Vy^wjB#eIUUJXO>EPqx2htR8Wo|+HW=t!k{=nR6?iIw<5pJ$2 z{5)VDN@$?e^X64^HAeI*^BQt~erL8~VzTz6~y-Udd~bUulc@lzAE7<@l+t*OBw1No&i^m3fLH1M_RKy&M{r zn=3@Z%B&XA)rKEUT1!%tPP_cBhWu*t4Uw=i8b=%vk&3r5st$Us-w^VOj}eSK#3_VI zQ=Z#EN1AANwRy~3F5F+W(*!nXn#cN!HHGG~2xZJF(P1qoWeT-C8sRRCN_uF_*YQ<* zNexy@E~mX6j}}@&I4bidHSb_F#l7Bg%RPtYLtl7FZI}uGP$L; zMjuOwX-d&tJtR8JOSIyr7Mb+Up{^&kmzpI)iz%cUpsg<+bSRhkT4kGWcJR5+wEwi? z=N0MY6v$55hmXN|9KGIG`LQA&Ic<(drTuZEw`E7=SfiigP>$>5$Eu*NeUX>v@2rwe z`+0)c>d4O%+xb0SDAt7fx%cu1m}iSV9UW(^6)ihL?1^SI9DvH6upRNQ##uenDEUY= zs*$cdr837~VR3{=N)#eGn(gDyQYoWr)Xn+we93PIuBAmZQc=LPqbLp z?8A9hEyTx&iZLj)Mha{C{kduXNlLKZCf_!cd-oY*z6VL0;=b!lZA`oV?Tl26>Dx}e zqcbh*o0c6R_C&K9`l7NYY)AZgrv2ypqV)Dib&~&#Y5%bvu)M=;DEgQJ{lCBu@+Ln? z*^a#1HSN}YiZ<5Qubq5+b|2T0{+Zog5yUcuHLIZ?DutZRwZ4SgKgA!bQ_Cc`kkgq~ zF4tN4xbHes+qc;mYyQ7AKA+p=*tMaP_ik5Gw87qVoea?Rof#&<+?Ypx$J~Vack^vl z;=b!lZEx|#Iy*N$Hxzi-xfx%GvI>&x=a^lNMxiWQKkVRRb!wSJ6mmM(>YV(y|A)t? z{rJlBmbfp4;P9( z3y({36{RvUr?WLtAll=z{Lab}N9*{pb5(`Ieb$jgF-;XvcHiV5#P1^(e-ciin&cL8I@ju~d~syEZ?~UeyT=!E zhqdeNj@I{Q3PS7%u_u~Uz-RUMgzbp`oN52DI<-vl3pt%@bymK(2Y288N5`kVeDav4 zk=di5mhGd}V9Yy`k$ZXUQhnCP5wPBog+0+Wn)aWBQ>Z5Sg`Cc{ zIxD{?PYe0&kKBd)J+=7v>%vb*XH6puLhJ~!Cz@4oG%9<-cEtasY5%c0wM_C0Ih|{D zR=%*e_SE`E$ERP>=#2P3b53(?fhV2oX4g+1_xtYg#oW%_Pbln>j{0v;G^-)L zRv6vEJlM4sEC0V=7Wd%p+yChJw3pZW_qwiTjz}`IUqxEn zu1foN2-WkyneTp_in;Cky%@3kc6<4;QSfJ=FA7s<{3^y+4gWkpCz$phYemZ>zu2E$wXFvFxi9jCeKoO2 zi`8hYXlbb|+dmm`QU|ngc?A=SEOb`B&`+wH*uf`nMk+}}`}O|$4tD^nfjzM=^48B& zAkVMq;F-UZg&t?S8r$8`tu*cJ4!3Kb)nLnxo=&tpEt9(1_h-ixtAR1^i@fbmtEW(l z)fjVGv(&vQt%iTJKmY$5_vGHmI(w}!CHt}cdhM8EHJpmdzQ`B*U~n|ro8wW(UbUxM zKTrFo`Pu%--QArpb-ZfYQ>~xWmF&;<$c`xuc*3s%vPtvf2v!_Q^#nqqqjVS;0gszkKF!M)cgH`jC85vQQRKBz;P;@JUJK z=<}+~`B4w;)0_6$Op8=K_9<7D(5E*GwJ5$=i+xhkYP0fMS}IG`nWPu%vOZY!ay&~L z>r-8{M~}5{Y`u^|OEv;>+CNX)87$GIk&kFARS}J{8FAZXUW_}{|pT_J& z&1z-2H|d4F0so)G#?O)eBkpDR;*EWKCoZWHKc^)55P9WB^LleVUb)fyVLZOS6))cK zA^!iLQzc&E>w=es1|jc){FDwpQ}HTF171IwiwEe+@S;u`aAmmV(f-31|B|2f2g;d6 zujVxEW#^UcCB7K`m0|+g9$q|JfSjL&_|!;EbFYI}hh~HSRl%stV!W*LUA%U66C{24 z+=dsl?vdKn5vA~DqjT^m^n>7d5tmXwG5;zr-dv3raP-BS*YWC2E|+}q<|(vuxu@{x zHNCqEU-JD3Ph>9lG&VxMc=MVZ?n05cO6vAi9KLe%YrJ@K4PKY=k^5*DzIek|a`>9! zD|k=MzN$#e`qE;OlFMxZGBBIOb_#Zst4PYE!Dr47Yg#X)D4o9Yn}!a>$1?ijBwwJ^ z8sA@KElE)=e4&!x40I?rmiZCrrABkUf||?K2!%C$ja7Bf2Y!Df8cGqJa#hA+%7Mw{ z%JBl7*0i3aB)y|7af**+Dntukbk*9AqMD`f?L~U0U)K4`o^q|sYk0|z9KJHEwJlN2 zQmzp`G3o=c6@sw{zK_^lP~A~#Etk`prEJP;p|AXQhYsb&GCe@=fmadvp+#+3no=~U zul)9a4lB_EuhNiP9p%+{jZxcLW3Cj{u||BQztzy8T;?2QrZv!4{Aqu>aW`apiN8}I zyDu-^e5bbx3*qux~%s(#QOQ0ujN?m@4xl0-KQaYbKAQ+==bs4+Uj(u zyB*w?FbGO)m#$Nsf9=VB+cNdnLiwAF=_d4A;$qZxIXYq39{ymhjmv6vhcE;e3C;hK z_%_FO6SgG`fp*=bZ%$J~zS;v^yHi^q1qamr6f-Z;!$&6sT;zTfoCrO};D z^51Yz>%Sz1t?@fUEIo!ntDRG~ruZ8@t^aJ9`s>FhW4a4!;CBQE62y>S`j?Q_ ze~h*9?NhYoNkW*PC9u9^Om`vX)&I1l?phnC^69S7QEAgCoW1DR)|P(x5UtDpWjc-3 zlwU;nL9R_P_ZOw!xU}xR=jN=uFy^;H^ZAT+dlkYt&PiU%|9c3rI+m#H-2wz`H&>eajd4)*jca7Eu`I5g}AH- zyEvoyAN=Bte`(Tw$2jrJLiwAF=`Pf5{&v*q4BOi39M?@ucNcHw5-o0bF=i*2r4dWo zDQ&y>zt_|H&z7mbeta^fyHL0J+hNxk_F%1z%WKWQPx?YH(P+!~y|v{-k}Zy7HKoQL zO!O&X?XN1tWj)x%8O_hU50>A*5M{q(ocLv-{7uGm7wR^Dd-`;OcA{se^v&?@F5VnU zw7A{Hn4MsjMl5NkwC&=51+LDT|JgG2*N;ucbQkJ2e>?0t!yc@)ad}5ut|=YuY5kXM zVQc)(5L?1g^v}+zTT|HlU;f`#+_r-}SZm`FTk{_S1&{Ucul=03ie zZ^E^<))d=Am`ls}a{t{P&*s<%Yi(T0iKd=7)^noGza&lCrPv8(OE>{4@07M(yv_gR z|80j|XV`%SzGTH|+y*b=m!ozpj`INj1;&6jQ%wzcSQyA(UYYzZuD zr?l^{W zT8;g-wdk*f-p{Wsp;HYzmGxu-PnPCii?QFf7X7u*`}wscu)h1rXVX4q@Z_(4Kh@Lv z&(@;9t?@fUYzbP=&gq*|oNu9LyNfrr7X59PVkej_f%WZ_wq5+i7ChTsEU>lcZ@Uyb z!E6bvZ>O~F;x8FI`K#ZT@XSH;KU<6bHpg}owk2pi-Q-B7dAfz3%@=PNwzcSQyA(UY zYzZuDr?lMPKK)}-R5A* z_u&VR|gS_*S$EdRzO^Xo+k>$M2Qkl*$qOERtIjbk+> z)7+9$ZuRh==FzVhqBz9m(J8ye#(6aMwv=!iZrSx~YfHa;h~mKXtnW4`q_J_HSEQ6z zdiYPv)h{2yycXZBtyfTn#>RO*DtSK&=kxltwWVJ^B*vQfeiUVBY@Fvir4+pcqpA75 zwdF%Bj>Lm8A4LlLPvbr&rF;y}0_fM)mVWsVO-Wq&A0H6V*f`I3Nh#ljCkpgyYfHa; zh{ch3F#cnb+E4M_Qp$JZ83g^>+S0EW@@b^tf5i1;J)cIp?~>Fu#is#l{-^b}`%7FE zUt6E1`f0$ow)C$;Sf~A;|IJk2-NXMBFXpj0GX19!*ZR+v)a|c-EyjNP*!^_k;!RvC zYi5Xl{qH!1{j#O<*TTB_y}#7ml=!7i&C?!J|Om$|8=GSNYoQ_j(&ic*3x=$ z_2a?+_mxiUl6GI+Wx5AR7CuNOFV9yx(IZBuPxJ0`r|2&`9G%$v_Es!7;CY*ae|P?$ ziifwhB*eqk@;|-Vw)5YX0=@$HGEzWTqjjSG9$X&$=^kDrRSrzaKk_deA3@K%8DU@NNC zr=PuphqG^o1wILUI2^@e)f1!cmFDP3Q#9YCwof?M>Lc<5H}mWr4Ofaw%lex2sywh; z$VW#to|#%>YxQiha8~UK&*D|>1ZJ5^9M>*uR$hy?xMic`E!p{+w2Q|B;>Bc&+}c{H zxQG|6@e1}@uDXneqHo9>(Ri15B|JO!-tjD6qh80m^C+jXv9?xT=R4MXn^%&R<$>dH zYPCFtqNey@F`sX)6smYb`b$?=t$zF*5n|Pgc%V2R@?GIcJe$2<=2rDd88AP(Z0sW?3S(cfOi{}&PQsrC|%&XJ(rtNl3>Yz&0Ny(2F)XVF6DNrjh01u&b9zM*N~Z7;Zv99EiIj@7qT34S5?O-{fQ# zvaw1Q@-Q_3!BlZC++Hlm?650p23X`g-ZEoiuaxe=l|0&9zC0feqU$htv`B?yavVFm zG0j1|3kwUUcws?n=4n8H`FbI@xXf7r1Zjd$R1j3m7Yr|Dy|C$2CUDH9{FVSovT?~* zDkytQx{y}}C(9}Z+%7OR3vgi$2?L-2w4W9^&e_5OjL?9Mk~IjqgHal=g;m!@nlgf) zHizSIi4X~i^^xRPMu|C`DPow{5XZ}=6XztmgIW$}er4!gkW*gB;&P){DCI5o8o;7Q zQetW}u}xu{*NqF7s{wKuL&Y0aELRGp3V6H)5?An{jl$|8lGqAN*j8|Bxu~-Ti`0N6 zE!Ps{18o#TLL9Bj8*Zj{55nQZ@)pa5b=I8-*_tbb)w~nR+BFJN!YYHT7H)YsFy!F? z>J?WjRrH9Y*<(p+fnHyhU&Nvq>~HDd!j>z*(ktcs2G>+*vUYV0lad_J69H{tw(*!G z3+oV1+ISP91R`au1ajXtf^!^26C>o?7N_&FEzX2&H-j*;>WGCg^E;?g)D#K<=PKa0 zt+`Aw#Kuoa#zec%4?R3HDEc>lWR`iv3?J(7|dag+9)jK3zfz7qAs!TV!4Gn z54Of&Nh;OPvSrAFWym^K^q9#_o&zlrHp}#yL}BfjTd9P{AXb|IpqoM#E7f&L(G;%L zr!>LMBDfSKB!g(VDRI5{Vy;>Uj|t`WGy}B(3SG&q7Ha9)KIn$S7ib#|U_ZA917Am(cxCu3 zT-YGtCfiP2AK4nYX2Rdt0E|S*Z5Lg4-ufC4%e)Msv}w9f_g@ zH#Wk+fj*E^{4~4SgC=tvkQ_G3&%}1#Fg;<{%1w~0Byj>oiF>01aT9PQ?wmG0Dblh3 zXay_ttSuH7UM#Ld3JUGAURbF{KrFbY5 z=1bVKWLDu=jR0&{x4dvN zrIhb2nJEDiLsdp1Q7Bf6&=Y*PfNe0wa}olnaAUz6yi!P8^0pbeW6xt8Zsbbncl(8< z|Ecoo;(7tA4dOrPLP7#J*g-$H7V`#s43^|F{Ju=%W>Q!4@iaB<0~EcdS1^tEd*V1O z38p21HzhO!xC~+*+2We{dnN&qawY^sg%T%RW{_`AxD0SHQNFN(F|9uwy0U?F zC#Ur!fK9fL+p;(ELX-{+dfTgJfX(l1)ij9#2o_l>1rR|3I^}^EfDFv8rh)KRL0gov@6Bl55 z3DRayGte-V)ZL~(54gg$jJS9^`rWi?N54OBqQvCrcVSa66U6ffm^lfM(T^lequ+x_ zIT)A#Iqg;)utVIR1$5AR5D^l{uZl0u;B}+hfU_PCuH8HBn&Zm=J9#QhkOn7L z*B1&90u)*9Ti6p3A{;~nfZ<%&kd1(~_2LR9t`}u#p9F{$K@vBRFam5)N`QzkVIv~q zkcbEblOiGk5D@_g+7E3G3C7Y)$mWknHboTTV}J~G&EYV_Ao3s{fy_{+&V(t z!|^C~0U5Qi>;sII??v?RbDVcyQ%`siQG_9hW|wNkG^vEirO5U$}up<`>jH%I#)xbqUlXIyilsOMqkt1jajR zb#{t$)(a<4u8$netuILx@{6PGXR5g+yUmiryeWl%AbQ9){*2qF#h=uJLg$5@GA8Hv zll&{-;=0>;LOsHSgcu?}jR1uQ8s<{XCV-l7TwplIz~SE}WMI~XGnLFDILS}I6`2<= ze8zhGHB1~fd`iIea=E0Zi&K(c!g9PgcClQ_T`zDEXur_F^8}S}-fWc&*%+dDPh1lH zo!h=bMHE9MiDR96*9}8vlsGP;o_V&sf+4CuwR+}ad6hx=snrLs?27OoKCa^9Dn5p; z;ER8tEt7NH`pDB8*KyJxnP0Hn)2h3P>_@FWe7byVHIlz5>$$ZE|DmjB3X2i{fIme6nVv+ns>?t{~jLa|4Jd5*~%YAeX@7EH_H! zoY#WACcOdMHV8|Eo6)EsltCvAvz$o&)(l65ccW3V6c%v+@c>OBISaXWJsO6P8m!%0 zHYcOSXbgw^JPbuEM#81#a-|xX-w<4Nujk5VqX<7&VGmHblF487fF+5#X%kFJg2_yN zHo(q&T>3FTHe5k559K&V3eLT8KCUl zDRpLG78V^VrR>_;?d)P1=e@V9t&sG-d2q-I)*1!a|6DqS3?Z0P&JI_K6*)Nzu}@ja zm1qcq@m*Y9+h|izYtft0Zbd+hiv|xL9=vjObg^8%SuDV0aF>X;GZ-*z9dl^vX~|zCpN^ia1?(ow#{ryg^v4 zavn0tm84m;R>rZIUR^A%Dqa&E`wun8d$b3u8(&Q#jcszqM^> zo*-^a^F&uTO1Fwa+nd6K%8nE;Dr=^#WV)4GU&Z3jmzp(*!PKKzxKz_ww=7>MLp7%c zo7kKd7HNkl2RF|YXqBjOekmghtC$HFBFs1wm&;`c^VK`yH3-qk(a`M*D$&6>jy9Wd z43^UK?nsgOj*N!+a-kx&khw*kX@xo1-rXT(qV$-Tm<4rAI?IF$%Y_mqpX?d7D4NR` zV7mf4OfaQc(;QU#v_{lS8-;~y8TpB7Q<~gxc5T#rMB~L3OkYKmYzXecpe$`ai?GOA zFIMmD)dG^hV+v#!EtFRmO3;U`=Sm!T9Qp@3z%#iL4)hJ0^4;9oCd~ZOr3QP$3gc^Q z_RFOhHISiPsgw>cFBd{7IFuueQ2ERX$mu0Zo*2B zw1=t0Qm86$ES_hZKrn;sE*aKZq{2kpfj&WIntRtv7Y^(SVW~T1+n}N&q+JQrH&ZLH zaiXy&40YYu5EJIXQP|wh-d8U0DU4MQJ%<5^4h0KxP_>qNtYZQ#;7f*UM!3ZvwI1nPsgfStJ{f5fM(L+uP;6{PsVAvSQpCUljckT5HCd>H)iTzYVk(O+ zKtD@bvL`LC!QbUug?u)B9)(%Ms@Gpy<}6Lnz*khdi5WPIM!fn$;8Vz^2QO2P?VSWx z!o}Pw(_Jrwg%zCWXZM}Q*%sB0$Q~L!MJ1aakqT&v;@4o)VadO-f_XWc9=%M$C+|9zm&BC39CD@YTOb1jO8^@A7I=)?erqZBM z1p0bfbPw5;Qqc2LPc>4#LC-&Us&=pZ*;7~n4^3x^+*F~oVQ4cdHSVqu!QIvHl}zz! z*qRb)vGJ1B*p20Iu2vanO@)XI(+mtu4=&6MEI^H<=wdxY>j;!God95O5DkXoL)o!# zAUiNVFb2g{M-%Wy*0hbLDQH^Hg{Q+ts;{STGHUFxQC7hzO@Hk)B-_|2>3 z4$=Z1yR{D*lSpNyEBAV$`h=Ouu1?z^bW}@){8b3MsM~@vQCteYZ4p3b!Y^aB%#pU( z869FYZc-701KsD&M48CtWDlFY-sO6FFQzjXc<>U&VmV)MTTyct!|8}A4zP;Jll$&S z_Qqfo&SP6B7cx9)BDBi7hH@_}pnaAOa;by%vgB~ zE^n0b6kXuI{4Ux+VzJNZ)bL_@x^r^yX`I{?IT(i1F_N;N+qCPi%`w{tn-hDhTofm;J=+79)dYgBlXsx=hrVaQjZ2bfBW3WQOw&Gp3Y9> zH&#~egnIZs5n+5MZgr3s-uCfY6yEh2YzX%j6c9yI(UnXt3IV~-Rj$>U0XppE@{8fz zahTTW2Ly)}k$P-CvYF?iD<&G+rASH$hr+4jgW-fLY3S(8@rZwHrg3DNInLUKId=?U z2;lY!R^%i0=8hg+Ml;lHkSzS=nWdEZSYs?Ya&$JFnmaz<^XK)!m&0hn0$vW=COID3 zW@U)(@koCxLi=p?zoM z&k4t%kjAuOns!CMP#n7MMQJIU5rtP1ZJA|TW{=m$#`FvcD#mH#m_2U8R6Z6>@k8V7 z@{0B`G^#Lk@8H#Olb&pYl0XoQ%}nL0&Hh*;^<(o;aYvXTdtTD^BzpT^&nwa7OTgDK zz$>60nB_1IP+l_a{wZ*01RW)SncNZbq)QWx8gR{}{zX(bgjCuQyhg$~JBwxX5M+oc z@(UoP{r>03Fovio908Vos(*=?jKpBL4TdAai5yBJpfg93`MuWzUPsBPM=d+eN>?Ds zHB9bR_Qt^EnAtdnjtT3I!ML;le;qdH{iz#|_g;!f+PULgB!q``Kpqi99&1487}{#S z{-A%}vR>35yh#LyL`4`-7zw-^xom0gLg^4DNQ1!vW&(K_#o^N* z4Bxel9h0$xHiiR-{S?zb67l?eN=FT_opsG3=b=S8L~4_4!Of&K^~IE`kLX%GF*N#v z$8FIG=Bf|DG~W;)4Kz)+k)B$Lj+2=CkUYWncKq+g+6Nm`8iR=-IA%$7)z%wDhozsq zglOI|ZQU4chhU%-hGSSOh@G_~l-IQQnqHD0`h#k7HO4fHToLnySIsuORv*URDP#>k z&-Di%i|aTbO<}TR1zevF#{Kz8}g z2ICy(;~eJoQDc%|$^AcL+&1OdXOcu=GV2gl|97Jd{`kk2jJcd1L`4zc@jf{j;9`(dH z&bW5RGJL#d%Iyy*MtB>PxgE5($A=npdLcOMidWA#&hQB7D#Zo_x`=ck0EABOTaXqf zp*WL*z~r%&i}@N-RSdcjITm4tm+1OX7E+jh#zH$1xJJl`SwSmd$(a_hDPS9iAVKbZ z*hcNOB*cAM?E;Jiwv~U4s7zKkAr;C3WcymrCTe{WwZ39&y|7)aX1uo+UY~H59--x% zJ%V%$7Y<@IoMIf8)r|>|T}cTZQM6Aoo0;6KsM?CIrtFwytnli6F>cC{HpN-#)uuJ0 zrecvGuDp-NfEZ=(t~sc8dH17wv{0=D7^w`}k;V0A83hocZn z)O$TIM*}aL;ZG8qF*qvA8Z2v1LN12KPyz=rg#`pDQbBrRWQ;Nf9}1)4h(c^Ct#kXb zxO?R07yB8}IA4vj;T3LaZJ34IL=#TQd=*P_NftwJ<{z3_3hN^CRU@^42bMUp=HjA8 z&^7ev!%76QM*F#TuVldwV+k=d=`S4m9=*5BSXo8%eKijMC2eGLK!%v{j>CQ|S-7~s zq6Oo+67zS|-)DwVqrdMPyc`ou?xlsi>dUxAkvFP3&FFn|F{2&jnhB!4?VR4qP^MLF zmN0H%h$N{;6Mr6gEQ)mSp(Ut4>@h`fHbJgLo!-vO{`!BODNeq#`Zv^J`Va&Tu z!l;n2!-O%8hZ8a;S%i(hdv}%}`9COEOvE~^&BXUJL3`2GIF*_4^W0Ad%K0IN& zPi1ixiNUaTw8w&@@28W3!;O?*Xr;$L^6ByU7JB>>uXWqe<9~Pb_!nM|zXtt--pMjGoU?FNqKDe)RaADs*AF=YDgXI&G{#p2RaA9I4qF1J}C#!>lNm?#}y+Ne?$wgM&i`kgSpA$EB*Z{3h9r8Z}JaHoV)-2P{A(s47SK_ZlU zw_3{!$4ccg)#LEYB9;K<)f3~cl7kPHJtht4{8WA7jP*odr{dI8ps&$RMTWwVWpO(4 zM3!_rbO{p_G^DUb5^I6jN_4LmgB7&i&)bs(ik_kJ*6}YIEHLBfK-Erh!1xHdfD8=EN z0PHkNcEU!8Gp5IWW|Qx7{(xg&v%hC9GNPBqOfgos@d#$p)Q`sbvLf1nvSxJt>deO< zoIt}VWNUJOGMFj8bD=0s$!edIgOd`7QYx0-x$r^fs;u_Q5_29g=Zojxxv;9_DBeGja9Kq2q(s)bf#_EOg@>8mdeW;IH1;=k4MR1JC^g=Oxs~tOt>TF zTxs;MPc^R zsrd`%FJF3k;knCa7Y>TKrJ7P=(+Y|YW}Y2d&8^n{(Ya{zJPzWrvvW%lxFmsn8hAzm z2bUa=Pp%f0V7_{TSK983*^dFP-^W5(ON~b(W89vM*9Ob$wIPU=+Hi?l@u3pJ!=>AV zmMSIw!B?)b9@&K+wtjZEJZ&V?nNq2^Rw-5@oHW?eO1UVarS5}MZjo# z6OXIAsfN^94d)5RByv_f6DerEwU8OvFj0T=893g>Z^h3hz>ya_|0 zVmUi6t}`qWho4)834U=Eab`B3u-IlrjX88652tiV|xt!FTF=KQl& z%@Cy*cff0#+OULbtp@|M1ufVSoGP#D@~aJPl!mFdLjXnTaJ!V8565yaDJkU(>!Z04 zzDo-0GpAOH;Hz~QE*pz7J3V6F$~s$uQLJicPB1nE{s3bPHKt6z7gk^7V1J0Gg}uSU zKl+Vf7y_p^eND*2$_Ss2z8#-1rQ7qudRYvlU`quP0x*qR#3~D@A zBoYVhmoU5VSTU}VjbcUo-M0KlR?}Xo)LWzlcO|vDez{S?O`a)qGbM9{qi((Mp^f5t zA>X0(8Q6I7ZcRNK7GZC*Uaf>T*2^n|9Ge6gi;K%VFlRZ&WLGqX6&-Mm6z0yjee~{{*4pEeG~AkRiUXJ?XEJ-H2RL#ZCEXMwqD5ysq2XhZ z!R#YWM;E2Crn4HUZ}afQZU;KZRY|Y8s04>z5K04XLgYX039r`fEn!fk2gTx)DCJ<1 zM{7auk|7vqE>?sA={oF#GB`lqIo)RMY*af5dl1UnM(W3d^pBivq<$hu|LDcx?BYt% zC==nBqP(7wTWCb{T_U0%`AZ>;KK^cyK6ieW^49G|xs7k6elmFY_=0pD)84ZcVS%S3+2w;yg@ghe40s)ov5u8C@gwxghm7fz&SrsZZkPmxI(t z-!I7i`>z)osecmm{SM-OE$I7A{QP>*_pk8t zg`n>XXN9rD5UU3)l3^Ec%?j9G1>4-$4D##jw{2#SlOj@I*L=}P{a-=f`xk4dXJ1Tpyc&g%*}{6Gz!!xjgPX@RE|u zIq`*SVUb4aPlDcWDK%36CFuRgY9sYugWi`G8mT`GdT+m{k@{~zZ{?*;Il0*M4yiVk znKo@tbFSF*nQc>#&^9x|+MDKh1xM{~3VOp8{JuHp{rWt%4gJAe-@iIeEXDpQoZ{y* z)=vP|4Q98#jWMBNh3!&6CkMaF(Qt@SMP@Bjm&^GO!}iIf*V&0nm)$j0?;H03U_H8> z-`UHcfN@ajK5@}dzUe(rs+x2`^*gI6jsGPtfcpayvMv_A0Mv03;u4~&PWh&NfZRyc zB*t`@cR@9Y0Z0<9Ku;Z+BCCaXerE-s&MoW})fpeAmsIx($Ql;=erMZ7NYzRd=XX}p z#eQcss8@GjY6DMF35edfl?jkMCn=`lphR!uNOtlvrjGcgzaN6?LxM_K)R?kYn`GkZBXBW*Sp-PUOea=d*gwNS#29LO@Y2^N91x_!BAhfW2BTK~dGtDXs4;I`>fC;ZX~O*CLR%kyO`u`X=$x)H=?XuvXj!k4Y&_8@Tu z&X=vJAogV|0Cit$kkf!257d*0;1W)pmE;10?7~V4B0!szbV_Tg!T#0A2|tmFxM@F) zNH}F3j5Dc9*_9!wWlEA;2emqbkQ^2wi4;B0yR8wq`%GQ9%B5a!dAA*?E6;ORZd}|- zIv2J?#+WfnUsK**N#}vJI28#1dy=XR%#ut!+Zw8Cz>Xivy~qq-eA*m3)tej|usL`w z*5u%)?LHt=UW-(;$#<=OM38TLJtn*x9or_BCKy_j%zNwv?G_124?K{g+TF1u6LkGG zmOJZ#V5_3N%jwxS_qU1vzva)iF3Y;Yg7qiG*-l#S0AvS&knWTzaezE6AtMke*Arpv z?q;JF$p23r(5eJ%@;@sQDdBN8 zN`!RmIsda5r?LN82{`|=eyGOYF+LV$Ul1>HTm8>orhC}L9>fDkpH52>r&AzrGD!>| zZxVuOO8n1y0XBe9MtI0LpNS!Mm|H)T_6!}XVMW}pt%7QD)*E%i4PFc0Gp=K#ofP!=^&AvBtUlP$l6}Y+ryL= z>=L6v$3p_&0gg^aIZ92%K|=-`Ew&My3X=e~!9v6#qaVUT zOM>23p&7uX8uKUj9ay^onS(G55rnf`uCtsZlaI@F{HZ4i z@$x5j%bN7idYQ~;3f=7mNPdYj^k+#k35Zb9fJh+22Q3ixwJk}zfo07#!K5@hK4pSs zsy6;tF9V_E_;g{@uS@_vvUOaJ@tFX~_ynYNeELA`SBx|Oofaq#uumBBr=k{!3}Ym6 zPFN+234tsQNq>}D#Jy39p-7LMSc_3gxNl(@MCd^q$pt2GVawzIz-ZHXRh1MmK*l+e z_~YCLwM!%eqs<^Tu?Wc^Mld;u695qcfPhr$RaHteA)7xQaugy+9Rp+xYW}7%=mXst z1kj8@?#)@08GxdwVK^RME+E6phT`FsgxH3d;R;1R{oa0n|@w z>|*s$GB)91b;^&^jI?VUkM<=ZV*jdqssZT9V8DTHWUAIM&y`IAv}ey;_&FH8MFwAm zWJ+jMoM!*t@RyTm0Lh$3ni;Lg8JmW`#B_U_p&6L%!YOO)g4O@-#vLop)^WGiI$OO@ zZ>-MX7n&M)6M+q2>YY#1<49kSde3_|(R6|5i#Kk-{ad9o+~wNWCL?>o>2%nl5z)V|=M3h><@JoM(2Q$x{F8$V$Tcv`OBw7A8i{A}jnt_i_}p33PUBrlmHFbKvXMFy1b+(!o(+Oe z!}8L+TZnIW0CL6luReB=}fF;We1ONX@jT>R4YCwyEWqG73xzZx~l) zICg|tah8xf6B>Itw^W(Z&u7(#+8zy^5|>j{WTE=G1WXpYuSPQpgz&(ci4X4@)<1R1 z7;o>^1eX?J|7hwkF|*BCXAU_C{QoU1n#$MV_Z=orogHeyPW(DOGL4-zN0Z}c(VHRf zNI{Uw_e+#+uiz@Ka9GxZMVb8Asg2c}tMKAIbgF!F;uL1-n9@j!mF5C){9B`~6H&U1r zHARrP_Kv2otJ;0R*ovcNUk(4K{+K)^bTzK|r*WCKi z%cA?Vm|$@bb8G6y5}}{)u%w5LnQ#i|^=x@G;iV*{iIxgvz~SZ(_||0VaG4JL#^Gyv z^XE~W=}o6vI`H@Tb+b-enwI=)>8hBz)V%;_U zyQc8};|jt>Si>Sxp5qU9M=mY5s5w|)602U2?}#(;wE@i8C+P)Be}r}L4bG8^bz_$| zR^efXf?&daZX*juF4MrsFjRl=wQQadW&OclV#p35y7y6TksR!t9fuB0(8N2otANr? z3EUrK{o=*j3tR58NcW=_J0R%qXS20n7+UuK;yREo%CF1Xf) z5}gGPZ>vh@*?KZ3owVkcG$Ox%Si{vjT>j!!LFq#>2d?AcI@0@_1bWrfzunUfruQb&XgHX{@x2Ft*h-$hP?`*`4nJ0|0scV{?(N z4mz@+S0cI+)H+yKgbM>72_F9RlWbV0ZUQ%Lb)su@uoFF%RPZVFb~l`({@zFL*31-FXrft7S4-d*$OK^I2`6vOCc^_$dxd;KPFdCcu@P@I# z>n+brC}CY!M(Gi#W}B08m$j~U)NG$SQcO5f zBySbf=Pu*=2${m|sl&VVY*^-g2Uoao*)4B|dVlYDd{a6-EAkEEPp-2i3jkdb`ON~K z%)*8qLqpU1o-LGaXvMlwLU)9iWg({W%Bi_f*CM_jZTQ}eCLbuLqr@pk2{6Sm$TGD5 zZvBW~i`+W{SGX<^%+c%PY&0{lh1Wlbdv@9a-cyUyLz?MYn~i;sU)@u-y7a!5{J7oe zI1>x8$q*OwV#+8fEFSaQ;L%Mv20yOX`g@<>W&nx<2!EW#4J-N$Tg0&*$l?fA9~T;u zEo`qBz&viI?Je@gPl$Kh<+>$`yI(f%ipO}5+qRpu;ChmuS;%MDP3}}` z%#K#>^!I)biPpQ@BI#+RNqqH>xP`CCefzG zGn}1RdcPf%+J8&D7kjl-aEVJv3${E)oRl$za$d3Vyc)JILs=mv#1DfI2Z$h7ytsD+ z!zfWLaRRwpKhUX^^j_l7Asu897Q$)TDPiQs^@~Q;2hgp^#T% z7sN@AV;ClouL3KfKCjx5F>u3HY{|7T;?PXQ+|Rk@G>P0kK4-wETZ_Er)pdH7E0i5|w&SrSP4D5T|Hkm2q1HeCZlq zND@zng~VZ5kv?jB6|EOGh3-*?K>QAiS2(YA3h}tK^Jw!QK%42yLI}>hJkPthwM2A=%ecPtSHL8G7j# zv04bPjg8|)9WF-H4~D}Fb9ZOFI_3r{ZrZ#e4DI`B z&)-WQ9dj8 zOV~`6LjmWVSMi*rbv7#~k3L(?mx|Z3_IGl68utuDKRi8cdAQH|o09VBm5NRryJ@CP zlQ}AGul47y^TgW6nJ9aju1)Y%E*=wsoP=Tyz0Hgq{8T?OYbJL%noK6dprrJJBNP0S z8?fdUtAFWLueo|RV|j#w$2oY214ro7nf!=SU=zn)QmHL0~`j}g|$c*b2G(05H6%8DSa5V$L?v_Z926}|T1<$szu)Al?Zjx~GxFKO9 zMSm4B5_s~ZZE{fZjY4SeJho9dyTa`m_3l7n9kqqNuBN9+GTzdc8*A86T)!jYQxQ|^P|Hdzb==Lxo+85bI30l}i}4m0AYiQCz)MB*I!CpkMCYj2MUGlM zJvVQf=xWRcEg~)Ki*C_!mjg}3*lw`Mz@aOV>0Cw&BDMq{lf(72@Vl%>Jg%1!E-S#MBX$T~i@{#S zp!=+D1u8^1RZkDG1)cI6`4`uRIkAiM$x6Te~6;>8`yTLSa+_-`{9YI~& zCKc!NY?PgZp9@wXUN1ytj-}dZ{5yqz-ydy$|NQ33&9j?lgcOgNMZ>*S_|1lb0uKF- zfcSTG7N>~~o?D|gDZIys*Mg(%A|YHu%%JAA2a%n+H-+wOz3^fIj}PXfos-mrx$y2R zU($q#793!zyj*C4)#?Woh#sQS6uT3bykiVzD$S%Dvc-a%1aeC_$cVO$#R{x`$WGo+ zWjPPxGE+oHz;tG2Z;7nMiWSwM%83WW7dF?_i*h-@y?QB1i_(we^An=zL^5r>P6N8Ne_tI9BX>2MtI3v_~7&r` zDoKeuE+V0b%ygHTN)rA5kpxP~y6zhpI89eX9uS%R=T;X>8+dyW2k_a`aIB}E7a;BE zG-|&%AYC|l?&AE#i zEYk9?_a~pD_rKnsx=HiD-tWD*-Sdf?J*CZ_^P4@Zk$W3S40_bzYJISnkMN(J0^(gX z6e42qFLQ1qei{r`gYiyU9m{J%(a}O$#*?mBSn>fEaiZ#reCr~Qv%1zLQ=MCkGYm)GM-G3mqsZjSUR0#EVE^Aqb~7oIxId!%E0 zxdMJA>!QxW(-qn1po>EeeZdFs4e)&0%LeicQvqiB;`>l>v?tD3VI28M44*LBiqRH- z+fX5XO@~j6X#+aG{zQ|7x#PH@B;3j^9v++1mvq2JpoJAq{|kz$kB*}SY}5=6TlMV& z1F7-(p?gIht1`7=9zwwXbRWKLeBwn-kuT zeeHxh@TEIzRZ&1S?p8)gFT>o*f7Xo8 zYlmy)is*C<*8km7+KfYef{a`vS-lKGXt?KVq-sI$&%kZzr-R;~I|unZdahI|EMb;_ zuQblWR%4{n1dbzhR>B6e+mti}#AL>?7hbztKW?6yR(G0m#>54M(OP2FHOADKO|E5f z+b7+7#-4V0kLx;CY$n&<=jmV2Eulo8VUGubueXFtvgn*yBAL-opP5SO{$RxBz+@d+ z0=KKeXX)1Bv>$eR4Vb8+`Kt9E=cjD)+8}cLGNzv7v%*G2AWd_0aEwUIsgd()0(Xwo%hK*~aY>IbH2ODu-kJ47xB5Tvf66Ani;KoxvkPI6jBw(j!x{BVT`O zm)`i+I;5Ieao+_wj7v7b@gg1EfJ)&i*uBl^R zxQ4uH(Mk>~c+SKybUH=b2)qVkr@8dSWFvN}&~H_;a2;N@MX;`UUboWls9P%V@obfE zcHPn+V6LhkOO_$}PFXzD4L9W2y$?re%vcmtP33T%vu)-~<*-Gj`5~fuI&(@q4{}M_ znbRG0f6~&cE9(BdO&wW!|3g5c^m{C&yQ+I9LNmT|`$DZ_XU2h3(sm=D1LNS?9K$%a zY5#{b?R>InovZDtRrS5k;pr~8p0|^;bkp5ve>*T&9@9+`cca-R2vd!kA$1qN)txQ} z57rlP*C8JrF|k&PB%1#53n6z%f>-k#2xbFycuIOdT}Ssu5rHu2i*z$hPn4%SbnN8$TDtlYuazb#q= z8VtigdksFi6Gz_zLjyy5Imt>{P};0kN@6+MNWCcteg;l`@mBPI!2PVZ1iiogoUpxB zQJH6vyv18aj?2wE$n~)c>U$OLSnIn-MPsb&x9p8Ja~2YH zlZeh=Sdr8jf7a^9Vxm($)?D`X(RgusRJ2p3Wa@cfmkcvN7y?B&N^A#btL)O-CAP8# zw$IdU;t_~$5~)^FCr$6D5)%wD*)U=Z%BHHr#FH2Hy4rh0h#uoCC%oxOLQi&6jLZe~ zLssTV86HE0ccUX6<0u)oG44vacYPbFYn-rw57!fSVB-NjIHvY$0cth#ng>iBT_ZdM zgb&%0&N(g9L)E>nT@j(>eVEnN@s=fR?<%3F5T~GZRHF^p;!Ntql)?#r{eWRznA1Zu zxwclKnI_m?a!vZVBokJ25T1*oTXQYRbR34q=1c2^T>g$7fLwgI zV?=b)iEZQAQLc+&Y^kDzCT?J_A+L*D;+T_~Z>Rk9x`um2>R=%rD1$yowFZWc4%0NO zzS`#kW46y@`!U{>n@KN9O~Wq-ifgJo9g;CtiWRX8l7}3sNVTzsO|cTn^ypthk4}zV zFH~>wafQ*NqXzzIG6dDWqsK>$DHfmSsvn_r;;3sg>6olPj%2fjNn*vYiTs}sd6c$t zF!Zvhgk!lIv;tsN#;jUXgTNvpXH2zn>_c^k7xcK#hb^kMjKR1WXBvui!9ettd^Qfwid$56czoRn+9oxrr z!;3lFPz%Ou&XCF{3-N0u3hMSq5$SP1Dd!Ww*~5v(agh^@5ujFBV0BwhPq}RZhAO=MH^EfJ@i)7g2LI2{W^WOr-86ru3 zIgCNZv500>+Fx}39k&ty%1}NfOXUhc%97#Qp(I%-Ksv>e+f6@sHAj?5N3875(J&E0 z6g_4xbVE56&mPH)%6Sy|ZL(QfBrPT76wb5aP0ofi<&D?oONG_KI@UBFF67NdErn+? zrQ>83L}rNXfs-XA7WsZbSVq?O!g^M%mcg3fXfd3P+Cr(sLuv?_TvD`y!_aV!eM=K4 z@w!ZjgECEN*J&yV`h#6uCd?({Wa_t%f#4Pt=b7UdHcHhZre-5+^$1j~L^+sa5ctM zjEL1pm!w>V8)I^NQ$Up>hno9Cc3?TayQSXdd0%lPnC2V>W8r;QuM*--1_DrP(%kX8yHRT1pRX`o>2!oALE|c(!lCtH zvjUWDn4L_~RGjL<%pP@IjSG#nua+-T%kJV%l)CQKXo$g!z);3wF>MiuN!O;dmtu{a zzQ61gaY^dLS>-;6Arl0yZ2&kE^wU#7UA0fL-Ac`e4l9n{lFqxy~aYO2( zyk7#SGC?v~+^$bB6&@Uw#?HJsodjqqRX-Zw=9&gui& z|Hlk1gg7T73<~mhbfPAAKn62;^UU{WI24}+UNR!-9qwL_yfvOL)#wNAUXQ#loc<3GQkG3m#=mQ9S zRq#mgJkJ)=U;iS{7Sg8>_m&_Xou9i1iwrKA77BPK_09s6X^qsQc;*m~1U?p|f9%2p z->}980`wTclXn}7g-uv?yghj2+u#H39l;}KHt0U?kt;Vo5vKR;8hZl!Wn4*}3@bF% zU)q4c$I=|T2VUY|$=%V*9;&F4X)-&W{xvPb@CF=j3$G=-$v(51*xf58mVlM8oNW6cc~%# z%mk@J&zX0}|KLO;H5a7zzy@$nkm?7s?F~|2f2($_=bLJ4cWOQJJ@2daDc(vnN1Ex;c@z zE>CPu+punZf#}(wZvkz6Jm`B0&i9@O`i|om>s-+HZajAQWYG83r|B!NFMY0&Iv@1@ z-ph^Dg`oFegGLvF-oO8mM(Pq?M|@(|u{B;0(s7r1PtZGk;fRaC6PY$H9HV$0Z={|L zg5Um7JZN*`vIV_O&mF;a)cAbR^CKT>q+aOx$k~D21G`_{jIyr4Gi3j{qr$e%cssX5 zgSAwKHl2?{Z@37}&e*On9NIO$Yg`<&Gc-89YlN%Av0Z}_fV#d4Z!tH*F&yp7$1u(d z!eN|!l`^=wv3PSt9kLEiO$`o)xcvqnFHr-_pGE`=c}STCLw3hntJrfU*Pbq)^%ipF;fyT~1@my?DnM z&O3o;F%bmDpN0(R3xcQ6o2ekU2%*xC{&_#eQvVY-!@){*a5X=;o*%3(PZU?_gn>%- zaJ&eke36Oci)HgQ1=hg{s2$&ve3A{DnBro!kcSr)ZWw&Mip~aVukYQ9qrrM29T!^m z+!87xYQ6oJrp@@L#ur43c8JF;J4|^b^CLgtR`@VfXSAip%A7?cDp$oTBFvd%m+5Nt z!~W@`oUqVcx#GA@9PQxP4Ec-mPqRhgffa;%!mmuUT_ju7a`DZ$38_%7!+5V+Tq!^c z+FiOsyxk?;N8PX2kMWv0IO;@icQjTP?2xVfPTx1_+% z7Fyw*i;Kc!AvnCkvIl#(^axGD)@jQwTV)AK@-sUE6~4xav(V zD3(MYW@%K#vJ%de-e4qfY|*)DA@1z+@({CkB#Z{3xpD)+)0)Fv7cGEADCm6ud3YPb zGSn4m@|pUCk$6|9Eo3h&>~l*?h5XgfIr&C)lX2E4iZk)MHM#BFC^akh=A10h%S&Jw zQv%i+;>XDJ6AqbiM<1H)mEzK}j0@UD;P?+?U2j_O7=wdBL%Jf;6R<`qhup`$(NiR> zLV1A;W>6<73tfQ|QvAO@RbI@kl(Hh~ubT6-DE*yO{p^S-^c?q#UKDPNR0eme5(t4M zNDtY1ovEjB!&n8WBc32GCpwmlIrT*&r$ZD(u2Bc0D-V+0N8ticczpi!Wh@x6Ry9^U z@%f7wgrJjh;V3#rbT-#Z<;9ym3J;Q<1LMeLc>D0Bql^k3NAWrjo&xL~&C5Ug7%wX_ z9ZoLefwmFMBDcSvg>wuB2GBW1MtZzGMCqj z*ox*#N1DzPAXux!hi&3p^=PYIdB_Q@oYTYwwl>aiZ1Nn>?V+)Vv)|2T&v6sQCxX~D zi}4a#ku+zHu6~KJ#?$T{u@;FHMfA_9w%F}(j;^NFnY_7vXz%D%z*QB@pmKuBz7e{s z<3bts4O?#thLx7Io)x*SYXpZz>US-hG*bT-BJf}*Ln@Q}|F+4cU^=6K(i@}}2Qy$X zE|{p3vHDml$rA=y%3d;Y!I;gA10AJ$#AusISW(`7S7C74T*j4wvqOf+Q6sTJfFYtN zhhtVWqiAGOXsB)M5Bh8)p_+XNL>YHPu_<_pD&HUgq$KD4wq^5v5)p2qi4p+|qdi8x z%5V`goShB6a0d1Ox!`~Y_ZWvMhGDp@vw>{&v5ohy)yA~3!!%0$fn})v;9YUUp&?|) zQ*ks4CZw+4=nl{j@hap=o4Bw)iwnbrHM8^R4<_7j!5amxWLZFZvM4M3ZmKD-ipD~u zPNqd9HOo3Cg989y>ats;Vkyf$#TaTYi24KEcC*;WlE^?}hS)|FVL42C9iTMz7Hm#< z;)Dji*b`C7hD~ap>6jNsVLB8<4`$l~1>bIqCrs!)D$D&$%f#=GThkvb_<`$w0RHQ2 z6C(&%)937&=KrovfVzg8w!!UejN6Ai++c0z>S^MD^nSx&Pym$FVIKUN(5^!EQDSOI zEtJRxsF>8xN+p{!2igV8GK(vjO$Jxrf>x{2Z#85Y2+v?jUN_&In`e@`}IzIDMu9 zGn?7CzeGJ+$RDR4TO^vMBbL+M`P?ri-@*=?{L*5h<3iI)<@W7Q?N$ zJS&hwC!cX^113eBouF01&KEKsZb3=DHo3R}NTwB~6F@iUa9xRwH8?ykBw<`drw?{9 zy*U}~ukbM!KWJ95J@AP551>H7U4_wV$Ok6EW%}tWqw(0TLO=j%@{2A^!0%WU)el{w zYXB%GX?#F6xZT^jy$r5;?ObFOb}Yx+SM>*k-cWn^-FF-K8UrLtEFYFlj-jDp? z0Uy~IV_ErPA%VZDGc8wtpgsD@3Jv=AT?t<*uml^!msIWb$8XkULUBrkkXJDdjQY#W zDwM#>WUjKA;CgYn4wjoRe=1^UNk=1U;jLz&71*~4n}daU=^eYO*v6&z&CE&{m}cq6 z)s4(GVE4kBb~L<3Vg`yC0c*i;R|^miOs2ED=i@cXxdo_}}}zm1^hGZ$Iz+w4gN z<|t#91$kg7Dhc**IgEz;H$ZTvM`6Joi#fuo^?vrZKK~uPlgGdA9p>{Nf98t~aKK5v ztq{$q|Hy>}`1Qr}K)E}OS&T({_*Pz{1D2k}v$fi8nJM@+BD?V zL3w()kSFL=t%irr0NQ|VUcoG1;rF2_!J{1Er_xY$+8(YNjEez4viY!$2ynkpQCt)#_S;^fj z7{1y6Okr_B)_YlFVka-oM~P!W@qi;lzpZwP5zK|KKU;)zJxZ zP;^#cCv%nJV&%1ivf^4S7uFYPe~g8g$uc&C#b*u^c_S4D>E*MZ-gH)V@<7&RW}N!hSa524N3sMRMw@(3TG_&R7 zdAq7NM9e+``kjJ{v@^pr*4sS$+FohR(mE#zNGNTT^HpRCbUOH|zxK>)XY`@bgxh5}KAPAZx2}&SXbbSBp(i&V&)mqBDt0z(q}~&}>4z`9wnuO= z#(;cX2Sc=xx*WXu-Ip@5=ZdcZ`vy1Lc}h}D;(L#B{{t<@+M~(AVk7mw;LV?YuU51f z!84zd(wOE_NRFT4+jOvmyluX){vJ7dwzN@Mo&t+378X_uw`kfqB`_PBI3w=sVO~_7 zwx75Pwg@Bc%t_cC-JH0PTPiL>V0^eR@hsL9c+N9lTpYW!R#>HFhJK*d5mW-+96n#T zQO!KVbEVAt3hU)c<{X4Y9(&g6!kYe6@&YR=On)jxf!!9^soN5GuLj;LfwBh564=my z7I#WZIJGf)wp507$c-`mU9%sR8z!b;W9&zzU}DbL82eEhQFm<_n6T~*5&0!glGHBss zFi&fk8!LD$XjJl4?~FeyZ>8csw@|5iXAHE5IIiBAyl6Kr2oMUHj1MIj3OI?iE&yZ~ z^dt>m5Slh2c^Qn!=SyqLIeuVATjj?HEO+oT{tT?t3Vc6%_S_N-*)ZkMZcQMQ7P5$T zxoDmaLb~VHvo=~Y?6*O%<|-H!<}8U+G|yOF+GA5mF$&vlVa3(zl=r=7&Q^@(_=rG^& zAiMdVl5fmAMf!-DWCk0Uk}NJ{89~S3DbzjAIYQ_L57ngCZUHEruw<`tB<-0ScRa!H z{=FIDhGDV-J|R4^nj3Gtf-iF=ApTS%I`O~i*z_P0dn`V+S1SaDD8be?nkmYVOXGS3W(K?L-)ZXo$;IW^?Dn_q1W0!TE^T6toc^87)N0@QR(-EyPHE3X{&vP-j;Y;I3^P-D6 z4>f)bwoe2rU(^E9ff=iqDxuqm-;ogv;yCCkV-qZWNe26ZW-~0g>?8Q^oaD<}`@k@c zTcm@Nt%i{rIz7?a!|DzL;8LMtuO`8G3U)owHgV|@Rl8FAh_@&le{tnTWrA#F;XoE0 zI@CF(O@+>Zp;i~^M3)H-DQfXpHdbKB(hnSO?AfsSf_uC8Sjm}*i=WB*ZnOE*K8?CA z*7@{;g}GNmY!xR4abkzjY8BTej#hDCRVZk#8I4HlQRvF1uNO*X4ji^d;&Ej}aUEcK z^dptRO{oB7nl@#^!5g1RiVNk2okI#`-6-=0F@+O2W>nQ%hs_n@)_U4zG!?_UQ(c%N z$D&RoN0C-8GO(phS@wU9tx62MmMpe`+PSG&YPQ7L4D{Snq&GH<%70NZ2*ZBq4&gc= zr_q`e)r!DMGL{tz6c_Ddz~9JFF$lHiK*om!cr7pQ|pk=DW+$kN1ghv#}Bzk2qzX69U=Gw6_ znZ<|^cFI}r?eY1OJfiTRnNhV)L(Xy(C7BDJlxlWWVjq`Zp`QTNq3o1{4gu1mMXYS> zMTyu|wHz4hEq@xqSIn7Gs>0%-t?DX|RA64$;?TkQgf;xUwG2lm>{{$XFjYd@a@vzu z)A5r1{pUeT#xBU^mG~If)&*><-f%(rT_;7cVr}k>RK@Jol(u*?2a{5J3l=+#Ql2Ms zI0PuJ!qE~oWvJ?PWp{@aA#8Hwn2gJIyp@UL6YRPQ>lpFc-U^(`K)VNY&{{K+O{by5 z4n$WTAh&n0mrB>uht9#Ezl5i-ur-_FGr6cLU$}i(JJt$GpaaRe0KSAKTU~0nlSW)n zf8a92H0#(!Z`!o2WQ(OoMnz1G`m=~Yj9f%#yuSRdH*lpi4ZnGd1=&+La!Z@Ja%*8c z<6hSh0=8KXlHKo+ch}R8Unt(@IzYs}klkG#jB$cC56r^hHYGQ-oWFj@F%GMzqAPDu zi9Vv4din{GonRX=;`b>8oxYXtb{VDDW%71%kYQzfmN-n$o3pn!phzFpDRir#>YaL+ zofFv_j7FWFL(Pg_hZef^L9&yz$L+wla<72N#@P`-fx(v^#E$AJdi4&}Zh6`Yd2nCV z3no9~ippdjyc|eAmBLLGN$=@}26d+E#iR23&x4B8M!}OHvFzXl>edC@HMnLYgN(w< zfC#n+$%~55N_X+q4RW8i`ovt+#HP&)H>CHlc!LT8O6u3oqJ%c8zd!RbP)8JD@S12# z*BNmNmk$1iKUc?-VyAnd<3+607qK?$!a*G!Jy{2JcBvvuFsxU2g{R)uLEZBlJ;}RO zT;HL|;twzBbIv>~>#c=s1<7;KZ$EjZW@s}19BAxtu7;0{$1w6 zPgnNg>P{;5R#>%HcdRI_9I^O37MpJf2x!gFoV%McXmmjbYH6si&}RH!2D58Ce13^J z6rpHQ_opUPgvs-#q=~38$vFZA=U}mGIfuJuE_h%h_A}+T)AnST0C!4 z6Zy-S|0Q;OR`H;Z63HG56LMl8M`^yCWY-V6xzubrirZ##gwBYAHS1v)Pf+u2yN`md zx4Epk!NtH~M-vzXN!}fEXxlJTCJTn4j<_}=SDGVvb1BEK9wW~(v`J)9k5a$g^fXW! zhIGpNP~JPMGE z4BDI0N^e2a<@tVT5wkFZ{#v>r1-07@Xhq#qp$b4p9WFP+yJmeBVvXY;1}^4}HDlxj z9O;T*yVx*cwQWsw>DP3Xr-L~U$uXy}|^kQao|V;yfJ|3bwXoq98!II9C%xyPXrW?7b#+4h~qCR;^3E z`aZkWXfA!KU3xIFs0f>oVflxjQ=2+09hz(is2V-mIhMr4d`v|_YsNNGKprz|O&gC! zD+*Kq=!Os@;HVw{vUzE$$~=*xiQ}T$CEa7h2reXVT$jEm-`K7NQZM~`tQYfnD0-UY zvv}3))SOP)(u1ZOxam8LN3CyQ@o*RdU^YB_96xj8quF#;J!zfdB`xlI&G8>*{t}c= zU~Z`GIQJX#7ITDGk@puIR5YNJahl8c(9E{jW+tWzXOu~+>p1ZHE)Yfgoyny*Tr#%) z7@ag&2Zh}-3wX+sw{>~soZbBi^>BIs*-bWz#yx1bvD9_Pa8|1RcPnh8Lv2!V(#}*J zo}P^GEPuI>a!s&!_V&kkc9V^G!Vt+juQaMbgJ|zpIYbY)OJ*=-YTlRHW+B(Kvh6^a z-fyt=`7%585#HcXh}<-6zgliCQ<0;TR-tSZyRwZ`Tc?EX%B}}((q!xxOvj= zz92FUP&shsw%&DxZzO4_E`BK+eI2KHgx;APxY7R{+4Rr@79ytyQCFD=D0k_VN!)<5)K#( z6^F+X@i_i^N)lZ5byb3{4ehQYMnVp(x?{BFBBb`SUDa;;fGaMZ`f5?JAaOL21Fk3D zm@);wJzbSW!&s{ZifMC)9n>9plLbi4;{LzNm4!Xp#hKAM4$1fgu!@i5=*FrQuOg@S z@)-KQ^5KpP=55WE)Zk$edK@%&)fSos3UtP8Gjc(?UAFYx6SQkWk()-AWGg?FrN{jUAb2yq?!s^pl?g72ULIIBhljg9$UlK&)CvB;jL|d7~olJ8Bkv{uI6vVy8 z+;gjPw8{xYyc~t2oAvCd9A;W1e6hLe7G{ zFekbOEfSNJSgBz5T7YqRcpXGvT#oKL2c9))#e?38O9eRqjkb@5H4L*~FXLGh3Sd8H z#~7@Su#C1RtRM*#H*(Gzb%4VqOd^9lmyOzkQGOCBTUXQp-j)bZGh#^wpNZwwc0}-^ z(NWTwt%o@DZuOxJeU50yB(?e^>1R(dqeN&k@;q05GWulXt}VnD4)Ff_Y1mkv**w+g zPrWNh^`84=h(~-8_=ceGXWkROmd=RC<7#f|I-gCmTEBb|E{JepXhYrROyhc_5147r z#=!yh9|W(vFV-^^^#0SQ;8&9uTh#4^e@~59rQmun`XuhDrS=8Ey-T>o(w{mI1b=rK zzXyZh`*9;JbtnjKoyPCsASj&k&C@^5x&||lBYWobd)!%H$8r1j>h}=Rp_HeBp3Ud+ zdp_v-uBY*PA?W$&Rs3EIdj1N3FZJAhuUxT`Yd_*(P&_@yLF?(+v}@F?WyL+Aq`C;n zw{RWHS6;li8NC|erc{$6q7`B;N17k^PB!~SCT=<=?EM$;GT9sS{>uwC8Ezo;oqy(4 zy@7Q8vVXCLb_3ntx@n}oCP=*-H*DS>Jp7iY!NJffLb4g-AAIQs9V`MRyW304Gxj?t z!+7OH2_udT*?ZY-Ueq2;l_ob2uh-q5AyO-?6FO5c5%!mA+Bs%1Q(&|H68E(r{4*Gn z>&Byg3b&K36&H;!>2`ycAE7J9S=wcYLQLw|`nr>dSaZpty>8sm#JT(z$i(~{j>y+} zJKt=&91LAF;qR7fTJ9c8u&f1n&9rWlcOq{uVl54&t^F7>+}I@ZL0=r)f72c@?W`4gt+vPN=T;qC7VB+qJkb zTqpC9c~W1R04TBrojj^Ud7>XGd9L9^B?3oO@VcKkADU^QSpk&FLEp|```CnNPouOU zj+3O*gDqMs7FX#tA3iZao~6Sc|;KcVUBq0;rgEl|)H-2m+2H7qB?glchx1xUFM{nrmbK{Bzt5gf;$IBL!1_Djd4wxT za(XJRk_lp#*S}FUf}O#ZFjg{ZFxsE8fl1I2Z@Dv&cA(DRfRkOS5(r7lVme(Vza`EF(#M-Z=yMP zO<~8h>OXS!86gV?8KKBshH)`$bQ*8Zs=NgXIy4FITdjil+M~fp_$CB4d>Vp=%Ch0% zS@{K3goVkL7`quA?P2^Iz-`p#Xi`P4c9Df%#{3QBwT4Gx4`dA&tl`l_S5e!E_3&&` zf~)PIs1_q*ZIEOu4p)s+uI@jb6~YjyGjq7(e?o2G!_&a^8Cs)*b68cus5@52+IjN@ z2Q!TS7`YQ^wbUoJ;S;~Z8FXj^F=hU5TO8w8?w*jGU))oBH9+U(39FOLAm<-NRmvv! z(&qT_pNAhEF}Dyzy9saRoEmvq>tJRvPDle*7N9!~4De*KsnC!A6|<=c(txQYql$m3 zIxUwg77AD@9Sh(WL$4Exh7)L))nG-Ev0;o=;NUC6(VoPJ>hsDSJr}W8pgS?TOFkrM z`*2f7TgpZ2<5p;NE|d1aJZc*K5%*$2i?BoN!F--R ztGLOSQ9BcRo`_K51#6{283nPA6Hj|eYS?<`Vczz+5$*GlZNfubAYVr}gcyPn_sJE9 zG4gkxIKVGO2KX}^;8`~cbeXhleR>Hy|sx>kYdtD~7o!)-p zP810(cR0bAM+g3?s{{bd?ks#X?X_rVneO-vQi8qccMjx%ur6r;$qwYuU$pb%4$wgt zGr=6f#R|2(qH(Zcf3P^stEN2xCYyTC@CYE($9g@E#%u$5r!z6!e=x>`JD~Hm76giL zF;@p;MjqMNEIsr)*9XOa$PdwrG!riTaKjz;$NlUp1{n3xy zD$?)Hr_14hY+wi!;cvyBdH=dPLNOj$qJlOnNIMhz%~-5(9oM{MuIt|MeO`|hLSZWa z|5o4Yx5c%tAWD5PsR)pW)3B8krs19+b0p_Sd@n&ULElSXUd9diVrB?ZQp5}~p#K}l zy@Lz#i7e@Ja2d<)UvdhBjzZWyy_c6b3o2Hr?v`-R1%hg9{xWXny&$h?2juoJ9juv5<-FwyEb_|!8cbzkI!W(NnjX*`)wEb1PgdwzS<(bHEJ#RSipuNY!oNEyDB7# zAh*{5L%If3UYK}+ZNqy_bqo?sN}<)E#2#|=-L3K(Zz>rVw+cboYY`hMm^h4uV5V|Z zCK-CZ+HAS+rhTW}PdpaJ?4$HV-{AaEt*6UG8J4bo^=dNA(hEx>uoCHtdv#iGk5Zh# z35>BYlNzd3qKDg%X9W?Mp;j!XmXI(WLxesan+2;TAwQ~leJfCKU85yb4Im(QV`l{Q%-+#wnad{o9M z&E-8Mn9^F$!6CLThn)W#GEwx~z<|5!YxkR;Thw)v`l$2x9RkljCklV+Da%TU5 zt9QsA^o!q(`DkD?6A&pc=(e>GVs*R1qy<5#IcQpK<2on@&3aT@cH0CNo^M{ z>2%@|9F5Q$q?)NXPAb@lJk#xe1z1W7$%M)%f$MbcRrX`sC#5awoWK`nk}n$62@&bp zG??HY-!k32aacNOV@`mquO5%AtcR=kFy-M1^k6FVhP6D8?O3DuV@|_?<1pi8O>o(+zT!h;9Ak&(T{e-%sIir(V?6?^#+ByVpht(2u>PcESKG&4C++zBgK%&D(MRmft3AfYRQGKeo8MOL7wi$L zjdggTbz9Z%vfka$fyBAGzg>v0Odg-em5fB24CZ&fmtStcFSU-NM~Q z{T_Iqid$H?EJrj3^~#>}gxY-X1T};g)IWm_#v*;7NV{=2QdzUY+I9^$uVCUxBSO~( z-Am5IzMBKMqk994L?9|TF$j(c2^Uqq5*If`A=5o3KaL@KFw>Io;5f;TbLEevslC_E8>Rvo&1fC-`80eWsY$w1Tz#E5Gc zoe&V$K!pG`u3K8XQEIM+99>o{ijzy`Wr3hqa)ktQ7cOeSZ?Dy=fw;aP-OHY+jP^)v zVz_}}*Wex|lg2da(E%QYa9bQsE={?luMYW+CcPD6lMU0Naz$OgVGcME6E?^@d`uQ>uwhEi#Bd|xk*zIILut-) zI1E9&VXnELM+TB@Te)XhE1KoIs0TBaVTZW@JoU(|s(~lQ)n35UW(KODcZ9(>z7yDY zF+b1+5)C{zZ?#zx-MhWve4Jziq23{Jl882pQ!i*&Pb52|phq|j042thTuv9VYr{Py zX3OqwwG8uV!)Q6~!s6~HJ_7FKmBdZC$!MlV;(=h!c8=@k>6-P_DAMZv+ry-%(Lb%T znffY8jGnlR{4nb>wUQ{)l0vPvPQ;6NZKCWK#`05>`Kjsr)VciB^ZA)^De|z$pVl-U zv{olp0jrkPGzA4Z@?XRfuYG1P2~Y6&-{{y_%UlE+8-wrCLZiA3y+}!U(Pn#EAA5+# z;&}j=y%u5lDo+HMcLHMnUF_7gmr=ogA3OC5UV4cA9lYCc1HZo!JGFWTzrPtfwfWie zGWx3Sk*mm|gBtSuy;$rf{H@~ae~9({_Gjhmo3XyXa5*WaH0BWw5fzLW3d7|RcosKD zSrJnvMX;SSdH`h0-^3pjQ`z>}NXSaMCvEJtIvhO1&v0uK`jY7@uqLjQ3ka@lmc%Dh zwUQKX^l9UjJ})8btp0Fvb-x9x;qBeAEiEe6uP=}2MoaU`LT=eU72~~Nlnt^2!_6@T zg(Rc1-Vkm{@!vcCuPrPr`2K`x37e-^V1Les6|ycFk?F#sX&6&gEl6NR_zYH&#FX3g z;{qG!TKgURU2K2Az)Bkhcu)RsAn|eE7G~L2ZL9su61sxWmD-i|FG*+zp`F@}fO*_k z_J@)+C!GL=otXFe=W*XH)?*1~d_2(2dyfpAe%yE4tV%rjh%&d5HBfBo*-5o&Yht1F z-S&r(>W(@=JqLrg-X;*Sllp$V#-b1p2H&=@!I=>D+k9w_aNj22gXFEZJ$&g;`|;Wb zzCSbsG$;z=w*z!xCwSy1K|qZV2FRq%oI$3^zlD7nc()rAAAh;$0Tt%=ASHKJ20`Zs z2d%^|Wc3BTnikM(u+ zl_v3(s>pc$Ye5CGwgQ(^#xYz8Y_U#I2}p6Yl7Hu@N|>{&61<;wY$csI`sD!n6L7?{ zWOTg$>yEmdvmV9zp&Zt9D*Acg2OckE6AtkH_uYcPWX3Z={PPI9;R|*SAIAS-&_LYC zF;Kh=4eUZGg}C_}6}1^9Qn~*qPYJ zquo=39n++PRE7ejeVylLV$ZP-{AXnzK1Y9YUNdRUtUXzVY{IPu*TI8qMg+LfQ5i&m zlM{#z9v+4#Jey6?b~M1@49KEw+>;~FlMl6xmMgX+nU6xO# z#{dA4TEw>CO#rcRehxSwN_wLr&6Y!3YKzv2e$dK}=9`8Y$k-V7!u2GETyp`>#~7Ox z&n1{WvIUPfL&K<(G-D8*YC?v*wwczSTxcLId56iY^VfVP2B9FkLHs7??s?<$@WR8N zXuEx%gF7*w5zbUF%S_tJ@N6-a927DTJmILI&G6imfn@GP)g_WzUjzzg6ry|AY-fEE zc8fJPul|#w&!-=Qk>#F(Ny7*P_~jBWK!hrqyr@_KGpD{Q^bJR20b1eglxVH3OEv7~k+6qxQS1vAIEj+|{=qQ7X$6R^ z7Gm$Un9AUEx@Byd&z!=Q3kQ!!VYi~WPoRO4IRp{9iu*gQ`e3UbS}DO)qWHwY^Fy$q zV0&L?GB0F8#pW_Cg)8Nw-lT|tq8LHV#(euI%%>rk=0VCL<+CB!xK1B*$Y5M^hk7(j zGn(WYpB4<5nt+Taf&HCI(Dt1W{4d};sNe-V0y}sU)m9+QPOVnarD{$neV$h>Q@hRT zUZtKauS3j+YlF($=fSt^WB}103r7G(dTs-c8@J|rwD7UeC(x)(;aY0=dP}~x`PZW5 z&xcV#ttrqfN8U`bmWB8rS<5GDY;^Bglg3P?nXLu)Ga)SeTo|;Q*UW8^K$vd8|1D(q zQ#!o3I|UKS{qlaZ)Py+;95~>)E5An^d~tg_Rru-&=j)DY9~3M+b%W}6gyD1Dz%l93 zAj@ktnw(LT`nDz$3zW4V-w|9~I>_KuyG0Kr{)p%MHh?j$HF2IYN?eP#{|5XCUV;r0 z$f^uCTYIZE$KOJZ6eF0DH^|X?ZI<6ema#|*^NxlaZnJ)q^@S6d6OSG?V5@05XS4oq z$U16L&_QOL=o%ZF`Ts!XsjgI(8Sfk>TLdhdKiQcm4L5K^NM~}N?qkEl3Cua7#UmMU z+Vk_Fc;Cw|t5UtSKfcUEX|vR-mvmpW5qKdLB6whVK- ztqPpmZtwESeP)?gfpLu?Eg$v9@G|7L>E)g32AK5pvb@%VUzjIJ7}kOs&u39usb#2i zneBo3-D+y`R#W54@;kDOO!aknb7*8)e(E?Rx3a88g4t!f?r6U%74wBk%@?XQUzOTD z`N}VAXSb?58?DU|6QU!5(06lGk)@e(8ekstiHD2qCt{mHY%{ft$B5X$S`)YDGRv#Y z`{mty9Z`feG@w%jt_@!8m_ua>uRK&1Pm@^lqLdpD(c&oWU)VA6fL zu`sBSuNl}ld5aO#V-MyRc$IN4{K5t)?>u?}ByYnVH7WV4lEYB)z;UlN+bYTE)k|Hr{TDQW(E8 z!ewzZ$7XR6ct=I4kZ*q52N_F_eD{S&OPPH4g$*l8r2LLBnwm=a_=k_T-}dnj4#z;Y zeExyZ>C67Wm)no;`U4~F$J_ouzWw;~{y+|SFr9q@eEh?<2s&5rmIe3IB=#uoKLF{HG8Lyg_*Q+H^A-_ASeSlXl1q#zc-)OZAwS^uD zVcXNh5bUm)&P zao!`-zp)?+3M+*yWGcD)jY%Ve5xnIuv&X6=@0@{GE$BuNXS`(3DHJSTlP@1cgfj$yOa=oX zr8F@Gjuq>22%NwWn1CVd|3ldNbJ+FGm<{1GG;AC%Qfts@5@=Fpl4R22!3!4#2QCcE z4a^VDT^O9dFoebpp*qmZ1+(WDu(g+DaK|E19OkJmsyQ*^_lm@_4=5+{L_)pbOilKH zGc_53gFGQPOzf_DX1WKQndt}|qKN%UnDLJBj}4s>VnbL7i0|e zMMAbOCTR|=ovs=AI}shBV^ittqoXk9I&jfDnoc=7vInyPeLFU_cU>set1eD~W1s;` z$ENnK3#EG1Mf4s84JZaSj!o@RmzL_POQMgh>lhrOFp<&=XfGU^?8mhH7#yN7kIkHAP_lz6*B*?TZ#=Jv z6N?F~?QbAFO6O95hqsXVWMjU$-z>0)fjpvhl{F~zU#7v5Ti5Yca#=kSu zX&4w$loPlz%koIQRegZRl+71%8QKEwbiq;`@=fFufJZV=lP)3I1Umu5-nLBKLC(F( zTmYhjce@M3KA-i*aT*DH!y8{V5+`sIi7!M#DL>3(7bBBRekGd&ImJJ{tpUBWo*==< z;m$xi;%7}9MQ}+tec7?vqBH*#sVIRMrVY+|PEP&|3_$(VtcdRc^_Bp=?b{Ckx`k4- zO5hI;qK03B?L+f+fXOhP!MN-U(^iBnHB+YzQ;>z?1V?}dEx4MXC(f~O46lp)$*7)>F5+T; z?nm2w-|G98{yE6JB#yymJu1l_zv7SBaI(^W81Ijrx_$95{;}BU&*A6evD2^N=U<4O zp16C6>>uxw|Nh~N!N)Ited5iRUj6kKCsstwSqRK%{KIK-Hk_bia;1YuXWVZ6(h@s$ zFfuaYy$p_W3%4ZM6qpE(jP&~xq3C3VQJ`kXJK|lxfe^DqgE$9B@@qw#-VwItm#;?3 z+aUeho%)GOhw)FvPW|zh4&&b+JN=c<9LArEo&F{Kd^&de*YWcMvD1HN=`j9-vD4pp z#s^~Y5#$_<#c#cF7$1toZ{J6E597($ zGr#rn(Ar+>`K#1p5*L+v3Bu!66DCgU5b;mD1Sl!=2wiTSbCFO^fRw8f&spycs2I1>WxGAX8hRnYlrdcv5yUX_AtI2``B}D+O|wOK%9CdDwbjIwPT$!zU#k- z{~g9Z8%zA)$`Fik-bLV6EYW{m#_4wK+5hLqy8%hy+Oxqjb$VK+k5(#@sUE_s4{PmH_{hHlUH z`)50oV6Qccg)oZv{QR{`FAWR~^ncASgoDX})Ew?^R;7?S9q#>4o} z#?GWL-G452<`j_n^Rf8vE~Thts8olE{THL{u~1!uunjI0FLEmQY57Pt595D17XQX& zOr~7UTUoxcbkpO+jD!y3e>HZxcqdp%IOdc#8uh*18CM}m0mOXT;=}k~i=DcMCH^18 zPThDJ#2v6NUbq2aQOF92SpH(;u3Hj>d7(ILOBCjvC6OQTE~;%_ zQ%E`Xg5J?^?9bpWoZw4K>RjbrEP2o2X=bt@WU^ zwYNIuBGzkLP`Z~8ACPor+GYu8<7HPrjDIuM_w%m@_%x-E3D`J{|5mK;PhrIW=e{QX z{x5y2FCWH#yYI(<+T@i>mv7EKg7?T9OE0~QFEn>T;vkjNsAReSVd_PAk=}jrd29_* zFLa$-C9?prT$(}quhpgH1^LT;>3U3-8i_M zwQ5P$rs&zm7nN_tbK2#tD_F8g$@lHQ_djDJi zbtL$#I3t0M>@J?0)=<)Fw&5e$eGY{{GS^^7c*rzf(n8-uqXJ?~G0<)&MM++4w^OQC z_Yoy;BZ5QiPV_Ipqk+Awg^Mm=ox|SZdzENE-oTc&;SZCL~5#Jv+h! z*){&5(Xdl5I@^wFnCaT6R;{B1zWcm&Zoj$*I)$4ec>ik~KIn1988+3ASN-{8GQgS| zm%WBwZ`A3>1RkLFg+Lw!Dv>%tPQV;y8-}V6b`EDckjVrdVorVi=GTf?y0KF~eUlua zH#jzi|AQP}=B>I9!0nF0IsZ;ox0^g3@w0D)H}#~m&CLa`&q)5{ipibCGs2;q$x1$1 zd5=a-@Li6-&!*MFDXmtL=>)FYe@#c8|u#jXqF@zu26pr|F{5h zCW$X=Nd{0-e-=RLBvAqR3?NZ|78WxQ4T&^k{HBmQ!I(HHZ?`A)6ss(nYAxFY^}UN& zrqkg>tFe^i?^|5xl?=g^B!6mgvE7~tmkz|5lHrpq-z$TK@P`RuB*~2fwn|v~?Ft$+ zl9ateHVFhLlEG0~wH5;W`@v90(o~fpY0ojO5Gn`#h9vwzX9AA-lJJ8*ni?(vO^77? zP-gT{MzF#$$-BC`l17{Ue@A4V?Yb0)t-Y&g;(wFt;Ir$cBs(jhY(=@40D z%WQdv#7L||AOU1;Ck*n!Kpo=3kq&9mNQ1C&q(c@X1z8a1gpmcoi;E8=FJ*v=xSLsmG_AuAl|khS2Dh4KzrkywW;0uW@e69!pfpblB#NQbOwq(N3V(jkkH zQ{h=Hh8PgYW8OXc=^__nI9c&#lYLI9F%BtP87)Z!+N5Zy1(uo$N;%r0b^0u6lTorG zc|qxeaD1y}@X70?2^RcB1{|d>pm3UW1ZfMt4?lasIBgq#WcRCjql15>H{l6A9`jn zU13G&O3y5&N2~}v3NT1Tv0y%)RHq_c#1_Q%=8nxv;e^ccGa|qOk9%&P!luS+yZ;rS}xLo2E%8M0$`hd_9y_R`7=iWuw9tx2_V4uIZmstE`+dtjx(#P z3jyYzKMH{D!t+M~FkN`zC;+w#FAzXR^`cmU>!2m08X|*gFnOLtDHLshpC?Jmo7}p! z$QnM+ZAJF0kVRa31Ci;ZTEVq95lF%t=}rY>h>H^V;C&IaB_{z9P=Jc2k|Gv)AHpMK zvr>}xad8|O;oe?M$G6_+SvxCXdY*iL5y55eb-hL0K!W4Qd-{?8MH6A@o zX%E})p<_enSo=NnC!GXC$=oaa)@uyy8~ROsc>72B4W5)sLaFw}$Abwww(iJK38KN1s{u200>?5?=du#CG+G_tLbTds{G4M(e z;~z1|kl~!YT*M3vTWx6cr6QJ~iKbzP#$F_P1IrJM1WzLzyV!+j6o^eO>5N7+4voQ7 z58Hr{{g{1;AOlkq%?qLgI#;i6(L#HPy&&Z7X> z*9`9xOU7x#yBvE-eb+}HDLu8XvQs$AmNQP|!)*$37z5HE)MdQ=ZzB)!FTsiSyMkkr z_Ac^5L{MKVUA=zs)hn02DoX`HXu-aE5m;iLMB^ zS8v*wmszw~ujI5b8`DWOk#7Ux>I^5G3-vJ^uYET$gsB;$5Ewtx4S>h#cn`p@GC#8^( zDI3*Gd7#;}ZwAyuUn_KnL0kS|QFEgf*mKz23oa4|QxiEWmBYJ83zxh~jq?4_I>`(f zHxZ$C8I#asl(!2is*|SyVG__K^^^oiJ^OyAAyQGuJ!9iAHHgPzXKSiwe+Ew<{@AFO%q z`#U|lF-&`RT0@*J_AQDz#FZ~);b2sCM`97NeQgNdW3**I6g&OLp_}^Q*y%6cq=^U( zAxWTUpR3G<)C;Hx|G5-pXod{KsuS>VFJyAL;4l2ENcNc-eW z0Cm2I=Ld**@rj7{LZC*F*P>S8cae@C;RhGI6m&PxE*Kx~=3RoO|B*`L30;x3$~dW( z33dj%v)*dC;@!koNyvhlE<7K~3kxwk0BLN9+7P$zfT08X2j-zo?H15CTZ7%m`Rb|> z=SmeK&ee%89wJ>4+-K`45nN_9;)u#Gmj#b#<2TK3h%?d zRc*Yx_-^s=9G3=X^_X@@y!=q~9{VH=IZnl5rB`4VwFz4|L1h!S+(G(MJ75Fr_q9eZ zO`Z`db1;)og0o7@gT^p*Z7FTuFvxEy$3K##B;hPGlo*)-GgV?pcwZQg(WG&hkyDEx z1bj0XB7Si(SKWqn;n-E=tylE*ye1!mI7p}EB`AJQ;j`l=yO#4 zm@BYiVhhHp_wpPPf|0Sxx=|Z*Uz#HMbUcx}5TtS>Ly5pj+JK~! z6B%g9&3p<<(veR};n!5n21x~?x0R`aL^oTc!H6gbAXk5onVoTI{J`xZ%q#&Z_wU(F z-0DFbQ#A?z?S!To(5W{+6J1h@{S3#ObHX89M}Y&>BsM+XWD>A-LHkG$Y!1~b%?Uf_ zabE_uDtN2;EJ3mz^-9xCrRI2NK3Ug^K{IDC%Aj;5$a+hSy`Av#ZcaqA)OTCcomonV z?9P@8s*FtQQN{y3GRNO}$Dc5iD0t^WCRYmk4z?fjb6zun8HZ&u9BDVJz<;%|#zz*q zl=jR;+VgKL$SwxW=i1g@r8*nHXbA--F9zRa@DOfiG&Y7gwNmhSX4~5Lz~yb>**J9x zHdyza`W|c|4X1b@9;80-_Q!VEGT4gH4!HXZRmLY{52i8ckgL1{;|FY8c!>f{6oZ%@ z{yiAX;%R}O{U|;2+2iB7Lw5@BD}2JX!#Pfm7AGr(WF;GZt>MMR`p!DubHHJ5!!s&u z5ZM;&T<~UGRiAPLDTe2rC**{ehXZTJ1@eAg2eT@UGW9fXusrG^dC&vGGFR2?3tE32 zyk41+h`l5Pd9Fuh<7goOojne;%iRTgwg+tS#TP)fE$P{4leY_QBG&^j_>Jn0@K-|W zxK!$mprUifb>WDzQnBu$arjm_7|PFke$w~w(|+^_dn%4t_#f=dZpY62y(KQoq#XD7 zMLWtfKlKJbBkTGwUX8`S`SJ_F@}@}vm=vC_U^ul4M{%+E_^Wo2M+zH0h$KVVa4AI_ z+3i^T;pSm{Cl>$8-$G9zvI7Cd}m=SfG^zK z*kZ^y>T11$mxf&fmPnw;nu$x}5{-jF;L+GqJvZcVT9QewUH;Mzu`4GC0YUH|){2@xJ`^J-M5`4d0NB{p625_T<|wqXNT9lr zd9nAh_$aKjAnz#g)iE6Y?iW~%Of)>TUaJ?1IQBMBP^-kti-vg92u=w)2X2o9|C#AN zJyzpFc-XwZyjC}1Jy4Quu2fg|Hh{SGx+#JJ?U#9?%UGZ za5?ZJ;c{e8I?FMxyWHNYiXRlVk*A`H^Py%3u?nC^2>{n)bOerVMh{@FH3mPpIitYM z7~owx+`^zx)nq_~hEJEk4x=}8ODm#d_?+!AT*OILDBEhL?kpB z2~D|rFr&9z60si?V<;%b(3B1XDqzUm8FHZR!kM^hoVHc_i~Ku#+iYM{`-=!1t2fJV z&}v&xlm%5Y6jaSnP&GrQ>Yy~X@2bND1f{N_a&<{Hecf?WlihJM(;acBZ(^o9uB$Ba z%}m=NTf5uBIl2n&5AS~2USmi>Gr&<8v@onPCWAxu8`DD&WC{erIfG}3z*vOS5uBLm zh?tt}h?to^N)~p6h^wc>&R|7a(Mv>UWrE?tPG%YI0&o{@prE`XBH9H(woazCY7JMP zxR|s{Tr4}-H!IcVTBEiLenOimC*s=ret4lpgk&ICAl0p?knBa7pgogHFx@qTi9#;= zU{l!IGe?_EGwaPwO;$2$jyy6Sbi_@J&IpA8U4WKR`cv7bY42T9zml_x)B&?eYkX!A zS725zNW*P3*Q4#?r*Qww{!~If)vrQgcbm=hK-)H8XMbM8BVNWVX5e? z?rv6vYL&oql(k1e+}-NFP6CO7l{v~YU#P4`BBKtxW)u<^0>*x@oDQ|*u~9gz?d~gX zT|A&EdcrZ1F$5EHNnnP`GAi0+Y!fD1sL2|Mj7o^AU(mq{$=P)nDR7e+YP$AdcY8u3 zbZ(Fchbe=EbslJKIMoRkvw@3O)kXrYCVAa25{cp10#j9@E(E&-PQP1wR`hH#%5z-W zacK<@A!h5^ag9=YCLJpmqfJpvN~GE0Wpqpnxd7cB-W3Pr=?n@L4|d+8l2A%9hEny0 zVoWi*z75ZE!3MexPD#V2FUQ=3G!VG~shHA5*iljxZLBGNg!R!p61B&NL7Fbl`X0t^ zyZrfjL-!x#!HiU<0NaE>tmrwJR^cRwh-xsUCJP)SRv)ZYcgYV1 zs)PjJMA%}-A!fFz5oLqUC}vQfIkMuE)G$&|QCi)@9dX0<1hJrtm6{>65-VtcoVltq zl5x9xV3>eWkx2#7MogiiNu3(U>U|8V3@-_H*yt3VBH7f|^NaV~@8Oyulq5=nHmeVG zdC2*I7}mM6xxdR}K@d^fffGGlmO48^5hcDRp%g&z+?A$v7(9nlq3*+S=d+Y0dIPec zF`$^2^1uSSAlF!R>8Q>KTSz3hQ&Fv%rmo@zwvPUo1hObP_cg+hkT5K4T47j%0swvJn)Py*@1 z3CD_7NO^#+XiNp-7x!{xo|tsYdukA))741CAu(JCCIT)9)g8vhwNHb_95j+?Cz=Td zR8G>8S3|nWw)i*TV)Mco@ zf|JGxf21=?8%z3C;^jSsAdw7eueR}2&L;RiGQ475qky+7XGJ1l03)RMGk^^z34%sv zr!LYSi|DgOCp-4GaAe7zUKuZ^2$QPh53$u9stl>UY1Ou?C7>T~gKRWSt9S_8Yi{Z+ zL2e0gr=+OR<&mvR2OoKKBSSq6ogpp?bH_DOGc_SVl&k&9z#yj_O@dP%fawhCk%S#m z#ac|mE^K<%1i+@ny`*4^b{IoO?$~ld(`BQj8ObKQUYLwrkV094Y^L{SbhqFMmbZyq zUo{BCo1xSU0Ovq62OB&yZMJ^E?!>A253F*q8bOpgaJgSvdsd(u3wTzYjTL^ zi3cWUV{nBp_zH6PxXq~rwtN7&}9i~>m04&rq>m>4>SPml1-ql&$?O#Do-IO{rqH|qQdt04R*ku$m0XVzGC;}q!ZUT44PE9HvBk_tj zofn~mhECcbCfG@I6?CS^Zju<1S=ckpZ7H3-!#>j4JG+T=_D;8r9=XwHIGydN-0?Qt zr9;Gb$DWpT3R0sSkX$qD(C~i_#a&|ohF$iagid+V8 zqfe4`92kRhEEY6rn;foml`w%T05``2KnMhYpxNDlh`VZHlw8QUTL}@ClVkb0{jTn< zLk*!L*Of*gTJK`v$pL}_@lJSO+O6NmU4B8V&X&lr%dAB`R76vDfL#$`=}1Ns1JM?6 zBPs(uw&`3@Q>)PNPiGwbTZw$al2`80a90mGDEABPT#yG81;?K91`n5}<+ePDN=1)K zI?RnK1$U|js+eP+d7>=Pcg)Mo!?_-VR$k}k0?di}Ms!MwcO=t_Br4?70f+ktFwufZ zgA%jR$!V|3Q@_qjOMu0|z;g1eRji&AMGVSdHI$Xnsfk#a;-GOlqj-D(i>^z?1j1{? z=?#>YB4|X2N&y{e?GBL86KfDpYctO2yHFE3jtxv%rD`C4ff}gb6h(0Xj?psWiWC#W z)3#0`6VZU(8r`YNCqzU|CQf)S(-0`zcQ!;$FQaI3;AlTFqsuFZ zfrsjjJTud}mTex9OX+n29m!|{O*YLaX|;|K)bTaBEk78EwB#oeiG4u0gh*d7)@IPb zqK60{9Nl4oz>~E}WsvNat`AA2ahj|y+WXL9p01Bjnsd%)`bQvA3N%<)#m*9e*|r%* zS0Z8+u8Sn7C}acP**=pbzWxmQ9ZYBZtu&kP=;p{E4IwI083pfBW-t*+K@K#o_sqmG zG3eKNZNs2eNRG#Vz^pu+3h7zBv=SApKImhXz#UV%zbB=NfZ zH7x5%J0cN4xz=ez=&>(8xND)` z$!6YFNP8Afwl*rg(Br(K-gFuOhBMjo{r*%WI@x4o`(T~~6m!Gm&g7itEGwm+kdEOS zawSyEZM=z;));^5ws*n%Vn58oPLK;OB0Y5TU~m+!>^vCjj-r86o|kcDv);J(CHAF9 zB$_fNR9-xScsXqiiH`_tdpGN8OTam*M@K6MLu_OQ-|&CJW{#spJob7y+s3XK4>m4l zl86nFpC${0jU6q|N(`TQ#st8mr|2M9LNK$(gXpl9Z`K=PyLIuPu&4x7yrwwEniu`V zg%d;aJ76T6KJ4fcQQ!C3Xh~&n4c3w78Dwr&PioXl9|C5t<~{UN$~F$? zcXuBoCay0+2O$>Uk+yD@;SLA82Nig&8rKw5*EC9Mdg6^0We>+I4aiL!W4i*71hn#! zOU1I|Q`G$DxO1*TQ?A7kB$%6UdmL{^ybJi{^NEwK8CUAYP1wj@0c5R8D z@aKrRc@LIj)pE--A>5-V>r?Zbxn72TBR#x+jWrJ5vVo_|<$1b0`E+(5pIBRz?H^ia zZx^<>I4hKCWWVmIqsc1Yk_NvfY<{)U@A1D(xpJ?Js~2#cgB{%iyPaR(d+RL>@R~kV zUc7vzv~+FdX6Z)p=F;`-Se{u32T%Hfs3nFjiKHt8T22t+O2|SB3Tfqu71O^PU>iJ3 z9PC5O-=k4ol_xeqNYk_LtY!`7 zUssvntY<9f94t86g6*G7+e(ecV8DRsGyAGV;pVA&uU6k{dOGFpd>)m_e;*ohln2Hz zp7LH=zEPz;xgB#f9{V=!tUJmVyf^B5cvHQ;w^h-n&3N}lO`PE+Zo|~hao`N#;H|^k zUk5G<*~$D)T^>|fYvm1sh`gM4L)y_<-~`C~{|3qw+dXjxuB!s(TdprfXHK*3!BmYl zpMuQRCN9HZnekv1pf9oOU9==u47#u=ytPKX*~~*C2g64XMxb#0rB?$`7h$(424vGkmnq*CI6~~xcbNS(JPBxv_OYLJGyrY2{7^;!Y<|{&a_I5i{ za(P~@tv1lT&ZJDf!nId!bS8`f8dzxb09#yVB1+-tjK`xo6VmyL9J@Q?Q2;9g3#Lbc zG;O^z0g#$7eQouO$2v;Pc{lcUfGd^OSWdNuBKzJho`>}0{YkLyVi8Xn!g=7hS^;ae zkp)Judkc4)c-~v)-R2`ealo+OgSvyefyw~;{T4Q)9gGz_OK!Tei7DdrUbQninXjxh zyJ9hF7;OlsyHb!J_v(5<+1~Dq9RU<>cVOk#I@8ch*$L)1_1wIctwu;kzVrC9gY z0VF&joS49pk>kZ8O{iQcQY&0`*}>-7*_3ku01&VsBh2wn3}ZTg5dx6!i4+modX#98 z7K2?igdD2^B1VIi>0U)Ko+i0-95~X7&dwBtdPE{us0>19DJ0-|C~y;<2>=KC4!qHq z$GxY{#Ibw@7(6;1GYLKHT_e)u7=lNjyDCMRuv1J+B^(RDPR&Wb+vM77k>2iX%Evna5@dcJ5x8_m-N8Q8OK2nrGbhRj*1*eq5u)je^A^m0yBfXvQh)VM$<_SbYf!RRH_DmsZ)NMJ2e>I^B~`Vkaf3CClVVJf3T>n z*opz9SptOp#1Xi>w*@9!dr2CT4%(J3Amh@yz~Q!wz0(LX#EC0h9DtifC19N_0PgN( zdJ5*M5^Ui9mRZ05%=64y3u_k3K*U39^{sk?+bd58zSpuctc`J|~ne8xtUrKR7HuoU_dBAPfWYmHeyLZ?RAkKg1_gI^f zD_!ryq0VplUby$UwK>L^OOTL2 z49&AMv}VEt7^Z|Q0b?-3A&W8RBAqEBGJoxAUUhDP_$iyex2**do)sPFxy7~#T!E2& zjZngAqR(}-oE!w3oXtNeN5*DI3>X-4zeG4Lt9AifN5OYf@``k%X!BZz&ovJfhtD-f z9t#Ka_Yzrm{0$?tNi_p#fgFO3x^@EB!W{ABsw4juv>r-1m{oO$?_;Q#?>DB+At4u&!S24{;&z#6PHsRpYt+i^NDDb zvxR86v))y>tiv$UhNg)}D^yP#&Gcf=Oo0Hu17>2@P8Y+2d#f~$g5s8fCmuR+LKJ&u zna*0b2)!xY({2F|s{>jXyWCIC?Lc`o4x+n)8L7@zXr?3!3I`OZ2g<9stWOms#CTFXZ{%2}v9O8* zJ5s;T*Fe-T1iJ|?Pl5VlWpbk6NDNy;Tt$K$gL1*ZmcVLC)MZM|PyEZjN7|FDWM>pv zuDAJh_y7X~w&*QW98BXccTjJ7_iET6vES1J1ihF!%~b>q7IR}Aup!HXewFJjkui&& zLVix%kc3}YEhkPz8IuP@B|l!fdD{2E#gt226n z(6?PgA;sy1@vgPTt%ky8O1yYH3`)gi3P<4t(|9VRHF7{b=!~FdQm$5Ya*nKtv3m;b z06%(;{4YdM5TIjz$$?l_!f0O3(|L)#03=#sz1-Q=8gB^u4 zB6+sdiL;cuialv(f#C=>!OP{wYQxUp?71Uypj`oR!+!IbYIT=FOBg2M1|PRH%%;5Rmlm=#`V(4b^ z_=4FW?~J3VBE9EEyjI)AGJ@g-lT+p)7J<4d2__MxrIg-k=0ws6?p;jJ;<-?X)SS)+ zAo>baPaft;c^fWQG}g1J>AXfHF3y=98U>bXSRC*>!V5WI74+moQ8l>{mGXgiamE{- zE2;(zGcIgEseJQEg=vV87yPKLrJ;QSTwLF7>in-GieTfuf zfwKWD5G@Ojl__WlPL?)sRh+)vb}(v`=0p3SzWV@C2^#Zjlwz9CB;5a6M;|K!fqgoZqb}*fH!3?sB>Uz zxxCe4sL3M=i?Tps{zC%m1hG9$yI4AvBll1(PF*eOmM*0LmJjB6t5hG z-SUR2uQ;+|@r`AZ-vt6OL7?uE#O5?0$DGlo3q`*Se< zF*i;F+a|}c*Z+A|3buR#id_-`C{!O1t*y<(&=CmY%~8h|AwO==+H>iww?J2QV14bR zGN#6ID%D+e(QHksN>IrHaFZ8E7H%T#*fh2Zl(k6}U|>hWdqQQL8!{waOha?8a6cuL z()rRHg||yEw1!c`?hPRTa^FRk7X&;x4@l22Ofu*!2P&i!AXp`L$y!>ufN;j35;fiB zWzI7LT;HxW(Q4sCkH{QwS-E^r#!*D6$65;M;?|>XN1Xwfpmv%YCbC-l2|$?or4$6J za+t^N-21o#lCqv};yzjJ!6?=LxI-<0#B@+{MPkg<2NRA%9S8%6dN8$TJ(z{ovI@e$ zOC;?MZ}}n<#_^#n`2|Q)s>M<~YE@iRm-OU>e08it`v<@z_1W9D8<-A5zz!V)WNsmR# zh29M!xUGF);F$JwU;7Tg#^yL_ zQOeD6Puhu&d5ixH2ByK93)1vPy^mj*(W3^X5E22 ziPW4ERP43s2o&yoAAB3@M<-8SbsBb7l+PwAUJ-mC%%wKq=?G63fEkRSfK(NSDRdx1 zn{3`Xt*wI(7jtZ!VW3=qEJkz>A{`~llquHjkE5I&%3q(t#;P^hLb%!##id7pm{5)(I+xrA(Cr-}SL5%3BFcx8srMp&L>)}leQORZXm*5dry z!1KLF{Q4exoyA`t2SfiBpg%QeALWu||F(Y{Ca$!qW0i>?^)7+=_U;r6vstjyCoQ{R zriq=2G6*!;lM%?$)?B=GbGb?GD%`YVEt?fSt`iqC2ZAA*m|@zk9kE7=ZV+iT%QbAP zC!Me^g1t;9Ij({)lZ_#m1t5d}JZdq$!<7WHqoH@_pT2i)+mqe?Ad%{(@V)!E{t@a* z7RD#nPgYUdP# zt?=@Z+`I2AhUCN>bK>3_?RDC;K$FP>1H@xkEKt?lp~$XUNsGKqC2Df@2xJ780Fmb9 zVQZk!Cv<|nFiA!V zBarCVcX7`M`4YvW#uEoLBk0ysD+T;A5-P+G1SGU<-ePKE42A%!z_k^i8__PsDmea> zD;Rd8D5llM>O3v%@jI;tGn&}#p=I0Vn5BWlziJgT=n!r`>|qNb&u(=Fx)E538_dga zJ3#Issihh9#4?(^)dr<0y34-4S;dVsH}=*_*BG2n8k3rBXtN zBjBaulHQI0Dt|?YeU;cx!Fji`Q7>CyCE*wYF^6ef2EGEwQaVJnTJIi3c zoWkya5gX(C4;`b5N57=mPN82?&>g|%TM*W}OnN_{8Y^6u_{7~L29ZruKW zHjH&6mH^G7DqO~k~awwqc! zX(J>n{!~|FvN@3BGn^m)q@VEm_}|5Eo&Mc#ed{Oj@4F-%`h&aSvtA^#*VlJU<_oCv z@g4X|NZuOHzfjJ?l z)^WWMH+jITthKVb4#2Zy?3LCL+1|i^;?l*WEf!qk>k-vH$gM&VsJt13SZ9R?9Sp(2 zoq`NT5<=MFAScEQ{JGbeFWJnxwgk zD|T2dg_ADNm|PuVQ(M^Sfh@8D*_X{Cw3YD33@CdJ*DxrXkvfb}YhXnFooNX=>#+zp z8qF4TIx%*l{H|>$9h9JZC#}L^D4jTaqBeD4I-Qt0QL)IVowRXo>`z)tWXWS*Mwg|T zmO>HTf|QA=E7#6TmjNp=rBcF_-hd^YMZEIo>kR>xF~&t3&tiS8bZf8ZFD`(wIzn}KnvoA$&0&L=4My>uxJ+YUA#1_#Zt z?HW`a7=ZKz_&eM2(8p*Fpaj~H5KHML&M%7xOJi%Km#=x$w3@PzZ5u4l1-hBi`8rU3 z6QT~a_y^{4qt^eD=g$Nw@Ra1@=T5a){RgXwE{e*zDQ8Bv$SdKlc9Uhy2$=_Q<^ zU@He3L^zRzryt&TXMtYvEHLq^`T?Q6F&q}+u#enRU6IT>b_JUX21wu8^DpjR+I3;h1}JO;Qb_1*>pz>qm}h4cT|lphAR~P zEexaHf@3V>mQOo3b!>e-ib-|Ti`H+Ro(;vOgJaYyo`@gU1DaNXjT10f~?!#i_~LY+sg?-!XMF)fTAW|RP$*vFi>8YdV=cJzd#F3 zh?a!7l=FPnJMSioidrHlzagD6lM;4lqG!oeA;qC)OZSrPGBzUcn;Vea@G`z!@f52J zKGdv~FVN0pBj`xLZKuvzikVzXkR8CwPNQQg27AldzO_F_lm>XZbB^1JsY?6^Hw!W; zeRxkzytZ0x-RDI$A|bFfSJ6<0I}P_)(ZCSF0K+>2I2bs^5=lPv-y&)R4A}whU^h&7 zX*9c|kj0W%OMp2^y!D-_pYBVKuRPhrO6t{Xc;_7TeDcHS#Q9kqfcYLCFVw*t8#Wd0 zd2J*^4Dg6@EIhw^WHu%y%ZG^}D8Q->(4yv;84UX?PJ-(@^v!tbGM=;TyNti5`(DD| zc;CzTd!}#cvY&>;Erx%Gb4LOqgl736UjI#uK+_TUy2JG0m|^CS5?E${qscX%@Ht~l z07A-OY6Y`Tgq%1E(uST>MVTIZ_VBdMVa7i{H{sF}VVI(*R0_guhp|F)?+{wX{`9javr z!cENnao>_86sNco8fCGt#=@Mx9B6E2-K`0@fszb*Z_Nsysa>fxV1{KeUf}V<|7Z}B z0~uRe;+nBjkQ-|uua?(dy<+)q%&iD-YMX+l;mU$%^hXNkgbppA4B9}I8WglTv^>$3 z>!WTr2X~i8ycKf4BFc{{_^IrRFC$IaD^L_hfS{=z7I894yL6zRPWgztv z_4{B()Z7AlMol<5)JdlGFs>i$z9@i})j2fm0Zd<{@yw-m=<`SBlEFfzk6=iZnDj2ytj#(X7V3cPC@4L4H83``I&_%Q$H4h~&F1qG5CvIr; zUIHkJd|G6fMLv`XMdI9L-~xWA)Dt!5sg5~@4}6xa*t0WJqjb>9`=vB!pPbH5L8g^{ zmHzuEUWBa8yQQL+=55>%7SD~^vibh&Mjs3<@GK+-rVuvO6O{n-BK!J9AIu4TgHMVA z7Htd!H!jOecbXIuAKF9M!*LyJ);Qm?(}0Y>41j8Bg(*-Y*n2dBy*G~|<6CG#{1ag- z){Ec|ZXpp2WD?3q*rXN)x3`9{K+)jGJNS3UPbHfLbhG_ZcPhWCiP~ z9Ej^6p|JQJA6zS0T=SKfSleI2Ac4e$*JA+}{vhP#jRmk5))yc)I=pw;e*DVU{GtBj z0QgO(+pZ55>I^)PKccU1O5%Wr|Mk0kk}leC&B=uNK*6HMkB=VYMF%6-S7yC5TDqa! zml>-W|5hXexF_kHMMV7EfheT%OGbq4yvJK)oKpy)3>Zn`$AKt*SP;Xn?$jQ%sr~oc z)c@D~wD&pTRt9D>b_OZd+B)W(d}Y5dP)HR-Od$y2p9j8wIHh|GTz&Eb7Hj|+>-*`? z;jj?v`^!8n#7_N>%a0yDl&<}-zS_YRzJ^Dywzv0-?9mVFyCR`zeH26!^{JRhqPc*u zAcggTmhjUd3y1N4F?K5TqvsY(o526=;yIVy#w?BaJSnE{h1gfV6jXt(c1!N*FOAfU zTjn96C&g{_$k!_lB1ySq8G+X$j?XjWSkVgSi^P4xSJaM4+vRGV_&q5e#xt=~U%wnY z4hGL3iOC))Sw@1oN@;-r!YS1QkUE&?lW76Rb{HRto%)*(fVB9J6yGU+b>W@jI}0!L zfCJ4Nto6P2PZhOA`dClTH`#S$dp=SWPU4)Bwtx%!6mz2puw$0M1y) zSh0c<+I!^+!>!hMmtWhWk?^0fD6?BfU7jPHn9;&hGC_#9auY8-;-lKol*km(C>=ZL zhfIyogFo6z?N{%#qYAs$^(gGpw3(rrT}L%Vt3)K){KI;v1W zh!jAIwlE-OPw7NT>6?OrS$#-Jd14|{lcpvWZ<>mDyl9KEE?YR&MVe`9%en#5vH)UJ z!cbA41E5gDoq@SfoiFf@djJA{ckgn2mx)_n-9?qIz!gm({f!E=q%q1S%h8;sEN z^5toHv{AaAlNlt>qA7}%G=ksnisQM4?uIm>?i5Z<`;oOLx zn(P@pGp*4&ysPEX9%jVz#DQ&0cZzLKcZzLNM@pzw-6^(V-6?2WZq+^VmUZu`!5~uK zcgw-j1uy&Yiq;4$Ctx#84cvoK^DVEk($=YnPY`7?u@*x(y6r`?g zPF8Z-$+>%Q`UQC(e+-lDkC44an7p;*{GP-3CyG8H`@<++Yd^jt0kHKoz)0-kWn*7| zaKSSHB@Lgd@!c0}#u9wESvM0u9B3bmCNQU%iffwNek8<1Op#DxDAYbEu%xavo{;>G zFkZr923akV9t|=X;KIq_AUm>JuWy08pd;psk-Io-HOjk)G+%6pxShb$f*UYL#Zf65 z#&InHdWf;d=|evlMR}n_=?9}gEj3C%7zN^~QTo9s&{B=k56M+Gus~yx#wbu)&7~jh zgH)nU35suinFnN8^XLbowwk6s{m>|rYpcl*0WM$YPT54I61br&z~z^<)o>PNZSo77 z01n1>wY6EV_@Qr;04Y1tG(o>Pv1nU^iN&8_Zu`TW+DyjX0#7C)+JR3_#!Lc+0xmvh zLuQ`hGLp%Uu`~G%-zf1p^hdZz<{y)Jjpf$jR`1Em@+UeXnGvQ?ARAj4~kkM~O=MwgsjI_(a9uMLz@DUpY zvo5SXQw{;q=tzr(wHadxeJR+2mb8hENY*~Wu`~+%N4~5p69R2PDi%^GH3)?$&+yy? z2#@?lABD=2D1p>`v*=q&Gzm(CY?@5M1%d?dJZ8uv#ZkOYgc5A$$0bhqxuAqU*%_-S zMW@zlRd`#FjteQ$uqLA)kz^NU@)%Jf^@Q?FbVO=KmgAu+k}(>|jM;=*IGUL^;(|=H zAzTjAiJ3Raj9`X>3sWGfdB&r0%r=3=MWZ>b%0Zjzie~2Nj@SV5Os^CavHMJTv_a-z z(Z9C&=yBbS^RyXfO-Po<>_~HGA+>d#3?cyi@e=msp#<%=(up-{@itbAIt+~rjRlDmE~t5Hux(!pu8nr+v2a}FcBLXF=7@BQgtHb zLlJC<&4AlH(F}~x446y1d#j*`HbW4>44`uG6VsBH2nPox&*N>gT1^VxB?PQ|vgSKM zyy&3c@z3(kHs$sO@t^=Zkn(DED;%#p56)@Q!JL(WR)F2dcVL`^Yla;fPzppl?+E&d zsh}i;YOvQkL8eHOIlc6#>F^3%Eg5iUjWLe7yK+GbhW(=Y>%c^M>r}IHwbD zzz3Y(AiUqGqp!5ZD|pOFYZK8?h$RH2=C~&mHlpD}DlKHhzJ3>e8LGSR+zqF!^z?~P z1r9(uE5u-Zr)mQc2@eO`#G!j6a$c*Ae&nC;l_^=C?Okt$}S&g5A)MboT(^HZH z5gatj!&I!;h)*IS0Tls!0oOvNeDq}o^@ZM>f)7l3!ouDxhD7g+B#CYlUIBq(Em{Ye zXoBYNQvswL6;JaTG{#Lo=X)Do)LPfeCe{c;5sfVQ{} zur3+f50* zA4Fi;~G2vqCy6Y#0sl_}W_Wf{P8(MyTekZuE>yhOBg z4ezO3D_&XY4^aQ4@e)^^@J`Fh$F{d*G@6CYc|eFH$*FK}mnrA*4gZE*YuFTUFebXp zW5IBO(m(#-uV41DfbrOGzn?`g`GB8r-zCL(oYQi6RJCl%CHt90URc%_m-+T`f}Utt zQ&7adxg9BnX9ME@e*e8X9{7~@n6}EBz9pQkb2$p5?`8YH2yI0;hqPQqR=)74DufR8 z^&loYYOFDWClvT4FxdKN3C0{(!Ztoy%Elg1axCZV;wVc(n;Y}SdpAhBcfS8i{rzgE zAL(TE!A@^fn3GB*GshAu110RpMqA7DBU&25(bFTSv#`ZVw00Z&w60f1*8`o}L9bUYC@sd1nk3Uydg!&rQEUbe9>)GLp#hb-pl4YgR zk){r02QnkW+=Q;*SbAycT7e=?@`uJMw-;}Y<6jTv9LK?c-+uJ%WX{JOcW>A$k;CdY z9vF2kJ$u=hw~50Bai|Xi9_-Lr8WLD0Z?I=BFyA&0IkF^KPVdpd2sn1#sG9)fPfIio z6G1GF!6)b}nARs9K&D=oBZf4SeC5stxJVVwh_UFwSsV~sFyPh$3CTH4e2nD#+1?4jOyGsGZK0U|rKN!^w;2xFBD|Z!J~lLRj+?T2WxSQ={pD zHQJdtJKk-ylX!{FWJql1#nlTPt%OZV#IL7$ULNk3G|7{vyWmX?mNIxv8rJu;U(~cG zwPB*W4eV)|f9eBo?56ai%I1}>1#0%^Pi9(j{BQPCl!2m9bW>VseLEKD%Du8(j zxlQ*ISB`^-D;`e;F7bTF9W;1v5vPiJw^BV+nMSNd8Ui*N$D@4obZqSU!UyYZ2n=|I zpn&4&?=bC=u(lFspQ7~OAk%cwecvwt~8jCBPHR5pv%cF~Wk zJB>O^{s;N1RENnmE8GFP@seNsAb)*NY%sR*bVXx-#s4+`gYhNE z{_`&!^=v!z63X_NuJz2hSiEs)lEzpS)5Al%Z-hcCD0K*N%W=Z7CxX@Os z-&$h6qBuskZU5XW0DAF*+2B?mhEx5Anww>}Kf_-8U&$348zsKnS8c>j*Zd+PpougQ zXHH8V0LR5G_r7(kzYqCFB@#jm-u{dwe%W8pqBtcIR^pcce5BZFH7u~iuOKG5z=L(H z|21~{;#ba!Uu?KmX>H;*AWxYkl#iYMl+-)PR0u>%Wq_$c!c=X>68{8sr@3px5G(fS z8TKKsn>g>8VSkK$`WwiSu^W5r(|;3LMj5muH}>iOiPdYQ<Al}dA>Vo0gorIHLplx$HU22%5Uw*`u=kOJR6R_THV16zEWF_J@Ze| zg0CbOxr}3{|1b6;y|@L}AREot>7U{-EN<5@fusQ+d)r5A5yL4ZG2fj)ohUQ1i1Oy{ zNbEUGSacwW!C7&8yS@{9u86^b+Zva(WZ%c2^kO~s+&O>oD-+>#x#1mqPOzJ10`y(6 z=e|o?i4dl3?9=~%Jt!~{L08pZL7ogFaan6E_S|GDfoNiB*W zo!IGq?MoJ6-h5r%iv7QRJ$XRQ%lG$FA#&Rbd9-OGnF@V-J=!VlsV72Ol@{sVB3nFB zwr5;?(fUE5lE@OzQW7B%SxOYL6^VM*w(ptGz4z1g^WN_-nmKc}IdkUBIrEt-bC3w9 zXV2IQcOsci2RO2lnlvRBPn4nWz})_)h74fzpz9D7MX8q&y*a@93CuMl9wqaQFeA?M zQW{$b$GVOnid-Ebpb!5Ij9*4^U&25=XLwqlPYoFf=p6*c%wO;-E4j5xNzY@b7&{9y z4e-zmk4JGEVAMEq6FdP;$-{C1aYao~B&Fp22nWtk+>eV7=2Ig|2nYJE%wu$vay)eE zxst2Hlq@VgAZz3bU)M0pfs#H;kQusyQzrX4CDRJzpg(3Ictc=R<~_sH7&i!!D2-my zN&ZW`5|0}0L>O^n@A^_BiU?&x#=$|TMXA04fH7{c*;DGL2x-S@@F$rvX-~k*sNYSf z{w6?e;4XaXnvxDCT?QVpBp%~Y>ZhSo-vg3Cz>(Z!!mwu`vC!afO2L9mwLlLVc%hVR z0(9y#{|9O92z5_b_0$l3rX74b0I9c=A)p3N24f(PPYt|525hx`WP2}_xUw@#6 zOtGsM85Zkqcr}2LF9W>cwbkjc~x0h5W-R5dMNn@AR+t{M5egq zpb&u&15rT;HS{$jHQazF;VLB!((R?9?s zV=;t8z%RG+DJfWAHUcCDCE}B!03{^=7Fb}BSCX=1{FE4YVK5~Ho2!jrg180p{o!PN zOR2+XRwQCOoDDX14*i@$lerni*#U!D?xAh+M2eFoDJR^!C)Ug<1UVi1B_j8wIX;9m zON4AIoC+YzG7}9Z7akbJSwi4U#VoRSX(&#fB$JRg<*Welru9oL476j3<|Je!mdx-} z46Ur`ILUsrEWp!{{;FR-)=)t^UZSg1tXF#nt zGai24ijtcK>r#Iv6ID{G7DTUxGZUkkuWTswM*s+c6#3m>2&E{QZendlKCmJ}N!65+ zIYxx`0Y5;32oi+I4`6m~Lm#*uL2fTm(&eJr@*&S%!z;L=xPnsCBgDoDn}z;e9n>lq zD{3L`U9B5HjD!uuxvL){dKb5Vfl#U+0YWr{tanNcGz{*{2P73DRi+qgF=Sc@QYAnl zVE%;HsiP>x!GOVx^pZc}YkB5p+kz7*g*imG=4=my#ULU1^%P10LOC!swu^bZ1-zER zEI@6_HZ$*`KrBxw_=4gbgAUUII8FDX#YlbNs=yihw|R`zk2N{_ z`AHZIB^(hRFp@3YHbc5Yx%BoC|cC89pi07em&2b4w@|3`Ow?i-6oZTH^O^p7gT2*2~#o}Lwv zI4;SWF6Fn#0=tAEM#~s2n%sP6-5mv`-t*?x+6_*??$5J>(O@&}A#pRxeZn@SmCt(- zXG+sQO)W-?1E@OH!t0+#Y*@5I-giPNP5+Z=VAQ!Hr`aGc=Fu~ojw#-;1&uWQ55@(2 z?@mpZ>RxlmZKL}(DXD9kB1IA##K_#Wy0bB9M`l&Y_Em2!64OMT@GL+mMz_B=bVBCFW)>zaCXA%5zw|nE>L;UA%_nO+U1qbr%w%{8WaMwAl%1UX*X*S}kN&%jMJ?pZ zD^i8dW@As7>?;}FK+}?o8>5tU#ZtF4e7;UO>?N0fO5-X`PY{x3eF8>K1p#VO ze*3OnZ=$_!?e%UZf{Q!}Msz)|G{?F!>)h*=Es94zTM+{Nt_LH70B403s{wy1^et$d ztevkqYjxB1;g7{ zT$|+ZBKU~DrZX8tRwoZ;(DGr>l9%39+?LKIkHs(fV@y(0}DsI-!gj%Mh#m@wE{C{>cj5a>rBJUx% z73*Me)VioJ+~Y@((7Fi7GKlCrbXi~;5FaP3XlR0;sm-~m?PL@y& zv%6#DANaY!Qq3c4wC&bMI?GkOB>0Cru<$MdMy>qJ?`6^ntIlXWT{G-(;UP&7CT_s! zQ*je_uEDbVX<6Qv-E*##Nzh@!4UFVxdXK8fimdJO?~DE`_l%?}g;5GdC1V}h^s-_n zI>#E8ofw_H4_uRY7Q_J#EZg;EIz@^b6@T$VPZQ2$T7b)8fkNXF;K-a1N+ya8#6%Gj zMxQ@4pXrG$lvinezw6*V4lF5lGKH}gMyUt?)ck8niErjFQhVDpDK}X4V&sb#ODdo7 zAlY&A`Q2uN?+^L=Kmh;a=9v;R#>RPI&U-(*g?y<@hzLM!1zfjf5)6|caA56$WmptB zVw8UDq?+yd6NX6}V&2_7r<5fzxe$S1G$!6UptshqRV``L$&NiWY7&@9h{|GSmk(*h zsQTux&HL*bxj`FEG{P?o?Um4jFyMtnyKCxB?*+?7>+T(Gx&7PyV-hPY3UUt^nO+U5 ztfu*Si94~%O1D^biTP#%X;@OD1xvOIN~IL`wm&O6###9zgt-|;na^XB4<%Qtyq)js z{p3QVyM%av1EZ(+8tv<6YYTnD!5h~jse@P$b zc2okP@EC&8@oXcvX^y@v>D5bbP^P=;B_w06L;^|HZp9}W(8umi!G-f~X52eF`Eljn z@*oZC6+&afL*Wkm;usjovM)R#VKlxx#-VGh)vwD_pF2O4vO6rH1rqiOMPz4~gw7ag zF3;zf#LGPIKE5HebeQTW35LjRLh_jakTMsWHgj-et%dbVOfyE2vHYTCce`KotDEev78rX{2qdi7* zRwehYon95yc4|Mi*lbrL&#tPx$nAsNg z+;@jG!vqWO=H|Wk2jRrs7?mBXzq4Ryg`JK|(f*u0Wk%vo$VXsgq%(Vjne~ELlg0~2 zhiW>ef<~EyvsQ$@$_pR^8Ltmf4@Q4@9vhZeal8H7t+vENr62E;flN{d=E_di)azMd zd7X4eww05*6HPOzAB?u!ob;3_YvBKB@iOYar_&(vF!CgMAaVr3XtRaI^v;xU=PmXL zH|B2gHX#^EFD##m$Pp1|)_K>OY{xm@`!^!G zC?SQBo1c{5Tcf_TK=0h=%BRaQs1?%tut-G|U*9n@y*294ROQBjIi9AnBY~nYwT01} zW~v7n1Lt<28;R0;h53M2kzB5ZXWn*`WA?G#OX3Hu9`~Y-_&{! zZlKjNJwLt%=b*==)nG4uU}?k|S(2XV{-rs6zB?QynEV??176&j7}%BQcXz~TL8)BR zQqlo=I*j}jnxA;C4l!|_`0MpS`B#W+;(Q)PA*Ngp`SW?3OmdG5)(hMTF_}dA4GxBU4^}AtWJ}2w@po=XCN_3P~luP8RWW}JN){|1Se?$FeFY_VpKJwq4E4Ey}H>ej~wri$pItm zPi|r~N`*UX?5h12@7YY$^D3G71oYxc5}_D1`pz7~pLBTXl2M7R#&6{I!z2jvr5Mfo zlvVfq@~WIuhX+;8-~9*oBX@_ciE78LPSr7L%6Jp^bR#IBKM{+OHsbufck0dw z$$eqXj}HycgSnST-GY;fIGmUJy=ki;{rz%^9c}%0f2q9`sTGM#;4aj*G%Y{r1(2o8^X*p z1b6cs%ikbdxKP>=J`?KB{1*Cgaao^ zT~7lW!Yn!jGD_-$eY^j1X{vow5s(un+(GU8oR=i!b1c?n?J_WGrO$w1OlBS< zDWendM;;E4mGj7*E2kCk8RnQx;$svXwR2g0=CYj)0@HJsQN1qE6Q=wzDs8xZT`qFO z#p&1h`;RRM{s0p67YX3}6LPXG%U88^&fI5NhK7j^zz*pqB?XMGmp(XBvt@mvX5po- zKL2lDVY?%p{Y40j($ZvW+rK4b$LyhkUB4YKhZQLTfrauNo)USnIl$3Zt0igg?nqHz zDA9V-K-=Tm#R-o2BTgC#xD|IG1R&!?1s37+Z5WknDXrz^^yhxsQz7rs|6l@3OgVMl*Ad#lxV=aRxAvhl5^K;wehQ=$CU1@1pAZ#!)X1C z*^dgZgp9qm@=%N8y-~45V{APLqNX;UlTv6+<@U>&k7H8vw3zP2qH+;N>oR5)WK{QD z4_yDt<4T=OTc%rFU&2UFC+3FCNR4K@lf4xS?|kecIuRD5Fq)G5+n7&%)%x|f_`kap zT!Q0=uxbTfcTo%MAaXC? z>)Gx;o=s0d%pZ!07!9l`>YOyVMGj{mv#v1A?Z{U9_H5q9Q zu_!^$-sXYrLvi`^3T}E}b-{R*jyjpwpnL)W(J@AHcHG@I*)t3psReC{dAH<2hM#Mq z7&)KTUY^wzr1hY)WLM?Dw9%mEe=MwGR1;tE;?30qHv=9=4coJ2n=i~JQ;`J=3eUbA zRW)2Tb1uI=+{gPY7@%!`^%f(;sWCla!wd}7ADsQvIWQmMZbMrh6Y4+?;nZ5Go3&D5 z9_9)6r@FhLglF8BmY`XL^MOA8% z0kLpfwz7>8l{&Ig)#>FomyI_38)tDP$ZbpBBZY`(y})T`x5c}Qw`vT0+uCbw$Tc&L zPTw^LS5F^!@sC3;n~{G#y`9}SoYDE@dKpLNS`xWo206xK*c~hc7X=!grg|!m{j2fVzZ%c_HSip{ z2A-qVz;pB(c#au(_J%$-5GQ@b$#^lC3;4(n?b2Wt|8ZHnIM@*Md#2?;PF9N@J*)B1 zxf;(`tbykV9nbcRcLY^KV{JY)Yi9&c51tc<$<@KjgQei^;BCP_3f>*OH~7I|T1~OP z;=VECzCJ7F;x~=2P_^NJK&zP@(lSd7%KIF9wp zX07ViUi^CkxwpUenuorY`J&;sHs-AAxon%oS2evFA02DSMb-9d@~Xb^O|S1$);&3E zeQjSD`pV#@;A?{igYOJ}BKTnNq2QN;-wysbP~eXbP6!r)vw~*_&kL>%ZVK)Q^4}Mn z*=aE)axF0^c@=}T)J2_%s*APkA)h_9=dz6DQ%$j-4Efj-JTVaSswwjYaU}!DQ~%l* zE3eMm;gUzr;k2*L@8Pm`MFDcYEqmzh z_Z;f|#83O{emd0sbuZNZS@BTM^sEoGS$y8#dcL*9;H%o6%E?;x96#)tWsi5s-kw8^ z&k1dR#b+(How!EZP8w`mi|i*2vJcgtlRJNQW$fFJ+4Xy@g|;Bx^Uck&m*^XF@jb3_!EuCT9T<6pOZ zY|_kqB3RAtBd5sn9ISmAPGn7+`=3+z-qX#^ii1Fo_WxzKFT*dezvlk1MqmY9DFM9+^Z0PzUH8L4&D{GyNvG)*bUw_HV5`? z2bm8DkiY_9b^8E*;Pf9`km%K|a+&a^M^^^hxq+C!%CQ-a#-xnu8gP@g0D z<6dUp&R~7;-yeD85q6O$9_A`;?1H_4edOuU;)K?p+j?>~26$?09sTUq^9#>npwU_H zfaKP@7QUr`Py8dVd^3+WFOEKski*us?)jB&k7qAApA5vUzTU)!TLU)HSI;Lr#b0_e zHQ`||{|l1yVC=kmw{`ZNdouO61kM6kBai#wj9^2cu}6-}2DMvt^(PtA z^FW}HZJmAg8#`CdF}tn_70Q7Hw4;42fB$a!~239`$uXoTWgLlb$)No_)~#1 zRknG5L07!Iud|0OcLpV=&i!KMG&;yFon`Nw#We9?v-Y~6`0PW^va5986`oP2m^&L{ zvMa!=-5=le?5TPFyf^cFD_t8iX2*5e$i6XO&|44ed1FP|IGoL*j#mZIBnqnN;ce_^-l%c zf{Kl}IYZ8uy=r<~tC-eW*)Dc+qGtGiQ}EhMi1()hzFTt_9)&TjbdUGOC$n~a;4=*U z?DF}>wvqP_Gl!Qf>v)aXqtQ>EW{kgh%Xa&g0=WgY@62S$DZWF^&(V=Ft45BGj@9z> zXW?Ok7(7-RKAyd^Y!K7cZ1`+=MjONn#FLN9>8rMH&baKBgR;Bd!=`ah>8ZRqPYZ#z zH&8o!f(^k~1AV=yU1t@qTBg_DHwR>jrCh5m`LzCUAQn}_?k;Dyc=?a7?yC&f{c5|f z#Naal9rlo^-4XnoY+{42U5Im?nG7Gb?tbsrD`sU6+2fh|)69vvwOMCMtoXpjuMI8= zwCjWNsgD(X(_)3Uk5$NtUnixf`z=A$5gFc{$$4ua=Enq{i{{;Zcs&~`R_4fgLE^=p z2ZOT%`?USR`2m0A4UhIfaArV`dA_oVy%oFrGM2l_Y3Z!mCCiy-Q{@-WFSPvfqiR9j z^)daG(1$ywzAhvd-w;%e#O{=!a_wvQ;>vDoZ12~u4b4t#V%y8{j$8CnH^%$apqE1j z+S+Nu8XfYpFPJ6o^sKQ>{NzI;^QeH#`Jncq7dkq_gU??4+C#x3K|NY*&jq!f;Y4=5v#|TtAf@z(IR1m6 z?91?=f9h82*Iw7ry)SI29DQrX;@R)7x+lwc*4|%V!``q=&bjljh)BEPKsT8uf3eZ# z`TCw1D8APRa=IxvH|S-cHwWt6_odY8&OrM_V%5_h4ZWOsGVcxSRZok7uUGcG9~$=l z>w*5>f&TW;w?)PsL57dKDZQGgJA*Fw6y5(JK%X(t;@q!qA80k$uk*9$-u7#wUp=|! z@yPQ!1N{r3`~CkuG@nb}Hx2xEHhNdHDc!m^{^fyp zb$)z0xGgaDOuD@r_jX)0=(#BLvEePf&lvP>8R$>t>)^e--wG{W3!RJ)w7HGl+{44Z z2L}301O3W@z9MuVpXY||?cN=l9osvdU(sarF?()e7M68*&GXy&`JKOdwEX`wbnoZ; z2KtQ9WSrP!sFPFMoOga}p0g$YE8CiT%$ny*tsOb6dB)(Wm^!n68oSLE+_%Q=c5?81 ztnqkl+lz$ZiIa+ROHOGgSx4DYB`;6XR<`v=TYv;ny$2Pvc26kuuxXiPK>@z}p z&X8vg*zuIitBv!6zDB+>^LX7)CF4_nabS);7X?~x%dckr*vu9Ge+=EP|Le9+CR^*S z&T#Vlb5FTP=$&i5{b;`E@#u@s7*1$?<+}1(vG4jl_M*>f z{n@SG-TG&?o^SY`-Fk6FU(ossTff-)OIp9T^_R8&d98nb>#u743tRs+t-q%A-c{+j zuJtc#{q?PXMeD^J-_5OmRqOY){xz*%ZvE}8zoYecw*KzczoGSSZ2i}@{_9(RPwT&- z^>1zc+gksPt$(2P`&<7|>;F;f-`V*9{^8cYJH6Om8EEbeF?)Q&p7d%{oR14G z4V(w@enN10aAe@@8GFzA$~Hbay}Qo*F@gBaHCm5$cC72s^rH1>y3u+x8_;?*ThMhz z%O<_`va9ZfvQ2Nj?5jK39C>;W4|Lt9Cp21b-Q90pk9LmGdbIl=tw%dwXg%6Jh_3t4 zxkKx%yQ|T9wDXA8qutGDJ^Hjp>(TCD>vb2;H(GDqJ!)N#cCOKS^rlAZ(VH8sM|=On zuSaifv>ts%qxI-*jn<>LH(HP0(P%w-XQTD#U5(bG&up|FeO9CO=%+PWk3PH6di2v9 ztw--}v>yG8M(fefY_uNjy_)}e^tp}Jqo37iJ^I;=)}zmBv>ttaqxID(0cSGjn<=`f9ra*djPFRyARNMw0i-qM;pWQ8m&iP z(P%yT`N8tvb8LwHn!CyUQ+Lc<#$r)-THRfBM-?9)sJo@^kh&}CPN=hAXMDcx+t~U# zn{@`awfQdssTCYmmKS_YW)ja|23_@ zru8pr{dKK>S?jNF{VQ63W9x5e{aaiAPh0=$*6(Y*`lA2#*58p{&fG29$)7v$p7xCy z_w&bPzNgm@^k01T(d&OS&>tJZ*BdzrSJKE zqVauKTYvAc{yl>o-!{}wCg{& z`JZq7|I_+kYW;^>|B=@JTI+wk^}pHrkGB4ITK{{k|NYkg_tt-+^?%sP}8rz=OY&m;af8!wQ zwFCXCfxd2_uNvq*1ATsI`k&PFpOrECRUC;Cj8(r_G7d86arhl=~^?rMCqo3Kz6h9 zDUH6o(NAu)-;?0~DUH6O(I+?h`Hg;3qpxiAiH*Lh(I+(8_qE8Y&vP$qv{=K{jsB`e ze@&ymve7SU^b;F>O{1UC=odHoD;oWhMjzK`-!G#7*hc&Q1p4ufercoCE_+_qXm=L+ z<&B~qR~e-`jw&U-n}tncP_bp52b4O=8X4dP7U4=XvXiHj1I)^ z8!}c??xmLmo;mIi_sS8$Qo!ehfN$3YVyKbLfBN)dw>xlV(PC@gVxYOZ_)n%WUsltl zzO-H!JLu|dVxz_uIb&mQ%VKDaUNL7w&v!;>au3BewXDsuO{~aF8onSli<#5Mrib3(4Cx?9t z0e$i~&1Y-oVPn8vGOPBgrpRR1sHbeo(z@S?P3zOsTd-fu$~LyU568Hc&2-?|8EE+u z_M^W3{HgYRtzPfZnd|AN4)kK9>CkQteNRw2{!7N{wCMVNAYSnho8tpH?t4C<`Krg~ zZo;Rz*U5D^ofWv7yubFb;43-mLHw74HwWUt-f6sdb?X^UzF&Mxdb!lz9^4bSr?mTm z-;R%D(x>&~2SZ;R^!u+5-S3|d-S6qg_S3I^wTA-wJ-0OLza8}Je->J7H0z%Wdi{SB zy4SxJ`+NE9@Adyo=zjepp?m%RHFU54w?g;&=R@~C_ha^>yUtf=eo(sefZ7N{;$s z)V;&J&j;jP7pNJn_j5IU*1faVexDckZSLAYyfx>T{GQjDE#A_3a+?#AUS_S=o?1U9 zd?yC8;^D4J86A9Hlzp|IO>}-S^5werJ0H&q_;qf;E;YdKvQbUC=d7PM%x?|ty@QALRYUt(6s|i0TGwFZz0KM+F+x*`g=>Iy!=dAQ+ ziA`jS-H%3=d(88qKWFBO=N;kc_s=!nI=ke&E z)9$?Q$vl2~*suyuXUf}Yy7Hi?DKrh-`tIF>Bc_W7mv^UY;cz50{QZ6zdN`uNLU|L#~%!B zZ^fXmA!llGCR?8pn$Y=?t4W_9X`1vtPvFasu}u0uZ@nCv&zJoteZJ&4>GP$yN&ly< z|8(pBr1k%^^?%%YpHIm7qt?4e(4Oo1KWzOUwBFA(n*Vs~{q7(7zqQ`yJoLxXSKRIm zE$8B}76ufX>w{~u7yn|=$L!L~_w)s!j|HS%x`PG^Mc;h`m>ude$M!QqUyRP-)KKF-p=ZkK3YwjjvchkiIIolKD?dkcPBQgQGa*TFnjl*{E zXHs`(EN1l%DsD#vy_}E}`#fi~{_LA`4=e^6*(KB6LhmS3ZP9`EtpOX43^csPc*q84 znjGW)*|!jSG0^DT9N0S-l>PMB%f?>UQfRv9(a0vRboP45-W2qHmYtcN*srd&y#c;G zt+$t4b870$;FO?ZUUsmtY&HgQakm+hD_-QvVcBbrZhAHbqmA-fI>e%M7y})iQ^s_V z+v^bTjR8HzQ2Ce@7kMw8>oYE$yE7uj{iobqS(8qmq zXtAYJE8E$k9>i0u=^SlWHx+CAa?r=R>}C5xpsi%PT2NE+u2%Tr-l}IjTCC>-HkYsE zj~tlO$`7^D`*CULmHglXuz9sR6OZ`drYQo|OG-wL|QkpTpt*p~S!R z{%!az@AV9*ypOdlmTIH&?KvU`&em%2_IYJmynDTUjejw^X4P1)t9U)iRo~+?akVo&?VjvEqtK&d84$Th{yfS`4kx%@)n`MZ79D#%#PIcy@4Rz|Jj!^H}z(Df4uc zz4bK&_Ttl4vbUZ=>WMvUetV#iYYy-g58pNgbS?(kwqQfBJ}AEGi=Vv3Kr4Rs%O|?( zsHe+UeA)vCx<}pD6$d`siI1 zmClOcLz9&+w9k6!FdpsW|6-u=XBtoGbynE19H^O{f#&O>>iw)hEo=(h_geyfv6Y^M zK+gJn>^2D<{b!7s)h{T;!dWR@xHng^tH4tG`U*UD7pC5%wnKT+cV1Q`KQT!QRJ*gnjM~niU)`CRQ>)|tb<*!Ht!u8pg9rsZwg9{%?8eV$5g`9uZY+X8le zeL#=7y8?TSeYV&bh@-h@G}@k?UJhMz@_uyS8E0QTOJ?1V|06v8{pfdIG_m&kGFpE> z{>Fi+N6r0mo9p9GH@fmL?O9##27H;eUODRPNG!?J9y-uXVkiE6jZNEwr=Rcnr^&rK z{Of~R_El~4GVv}3+BBKgSF&~5{<;&V#i(rPed+CCgIdxmUej#o&*ZfIE7{!dEq&rf z?@BiJzK%M_98a@(wf%J$u4F^6w~t}@F)eQWp5FIq`^By2?|J&YrOzEv_n@C4t2@Iz z==^KW=Gl|cqtB+ZuI&lLUcb`$tMi3-G0@mCHyM4tUaH3Wcu(8I*M7d|FS+Fp6?j*> z1HCWzccA+p%`ftcUhd}Ho3rjewXiF2wTbhu=Lczw$NBmEpiQPHHp(BF_SvJZma_gM z`Jo)2!`QeGh?D0=@wkWiEzZVlCTnZ3A*j0KR$t@3++ z#&Z5o0&5Qh>x1_Pnw-CHGJ5p+e%q9}H?_H{0e#g3|Dk^uth(?yn+y0N?tFcmpx4${XKur)9*bL{r$dPUazN@XMUyl^fG$c)8z4|=kIy? zy`{f@7Mz*Ab$5CexI47*esBkwJKbWMdZ0&7H%#-V?)cuO-c~l%^P->c`HQFQ%$AAn z+tShAaSvU(l8Ec3Jc==b+>r^(_+&)@U(drNnJ zu6AW_)vI%bM^hI*pJ<-5b*`Kpt*-&PVf5wi@=SfH-4L03DPNmDT<=YE$`w7vawX^TBmV4L2=JiU$u8(?quy)gI-b6c@Q*z8-Y54p zUd&iiN9%)n$D>!n*T?JU6AN}PH?YaOtM|ozul;=RbNa^oWZyJDH#8oydLP*DU6O1v ztoL&vC-$j(wriukzY%+vGSBDYD?9m7a;>xXlt8N-8MECw+u48?-=f)kd>|LzFRig- zW3U)#l?%MuwZV}A8^m6HdB?dj@b#oK1Gcfbk1c*}S706fOMK)%+vG(rC!T-hYw_{} z5Bu=YJM!?IANKTlvzKf>*uM}g2HKbxKC!izjjy-+_qtjlQ?94kvzpE1?)Sg6xj-DR z3dT5!(a8aMeukf){PFH#pM1!j_<*xGADHK_T#z9yWmA22WA{><$IBPIqyKcC7-(Wk z&YplB4+NTgYZo2pCiTGv^6m=~w#n}a^f9MU*>r|+V_cO-#Gu-!KUL9xQI9y$B#ByWNSY^MfR!L z)BAPiAme+c?0N36=jwsJC3NY$f6D%E8u;Hg(7!RzkIyer^){Y9(9ay`n+N)x1O0si z{nG>eD+B%Mf&Pm8a#wH9_JQ{Iu=@4u2m0#=`rQNl!=dMrugyW7i9gT#pPD&7*xJqi zADJKP;-?0AA0Ftx8t7-_m)0V3BKyqNyD#WgyVp0}$7bxFXM?YY>Yc0NJEHv^>E8GA zBD<%r3yojije(T)qO)B9CzY|UJ)RbT7QmvwiI-t$fGbA*1r^&49+ z#^%LT@6OUcwe|Buzp2sgW_-Smrhj_tpV4~pGw+VjpV#{5wEnrRUu^v)t#_Z`zqIw2 zxBjZud$w42AM0!0vjgq^>H8ZSeRJz?80dYCeogD$)Arxq`a4=b`g3>YFAUBNG;!w> zKd%Ygd#^v{^Y0IyGr+$2Hr|_FJ$c^9aoL{XB){I_!2QT3X9E4o;N!ua4RS4?yMtW0 zkNVnJ&nvg?X3bb_Zx40^M>eoQj?nC*ueZ-W%~>qjW#@9{+~>Ch;^KMAuj1neoAKl2 zlX@jPlAcL3w!dN_E{_Yydut#j;-Lok zq=xWVcmA#k-W(KP$+xHYy!Vw%`^s)SbHQr5m%_u&UgoHqZFFB0Xe0kxZ6JfK`w2-K zeYZ~cs2`tw^zys-=*=s|!FOIY%GUCEn!fV4mow@kgTCJ1o_{sH_JSI9Pn;jHojsa5 zs=sZ5PcyeSz-R8HU{6pr=PaW8dRPkW9$pBv;(1EOcy9{acP9pK3&<_`^^V2&(*iN> z^|`0qMfHAXePiH!PUA1T)V_LtaZr2t&Bj{;OBitW0p9xpGMw>+pzK@BSX-R@|MRgx?h5RI zkH&U7?AsEo55APPEk?dpxiRkT`Q0h@;1OTAt)XYF9m>Ame=!mpF+VS; zToezvcpeP2xdYw7e5$3l2JUNX&VlE3odbKtU9Mjq(B-c2`~v=L3YLO>!SzAKPCW41 zGp%OG)E*AXUix4;U>o^r()lSKK512x_{u-}G&Oy1(ED|5=+Q57`Q@FZ&a^lPY>;3NYloFe~^W*7#9P`At(I5KB5|ciD;!^Re81tp%JE!#a zd&ZdCC(diN@1^1W+q5t04*Ij!nt0h18~N?5sv&Z`H_7?tKz!9l#qzP%qM93Hb0~T% zhjmUWk8JL3otF2t?1`9(eQKG{WNr<_MPs`)Huq~4m$I+ydLVonS=P1%RrB^Q1ngq} zHG#O-oUv!KX5VPT;jqtn?`>pTuZth-Vk3L%yto(8_Xh44&&pQ>d~`pSFUA`Kyy}TR zc69vtoU?d|}V%i}wn7IaELV4Vzhhn7=5{D!x@W zv*LVxc*{2N6lZ?BpXP&|foA`2MYpwg1m_3*(n_|qcLr)&Jy)zf2g&K_9gUVd>*`gb zm(8`m*1aFvU$k29Y3rK(?&D(+X=;&dG(GA>+aJsY^xPV#1MBElx3N0e7nB}y_5^nZ z##aRFS*`YdaLAcGl^3>>Sl)TCXoBH$gkWmGufamn!?2hN+ zjOB`beAv_a7pIrMw*_K{=T*VT!>+ft^|i=&;|v+**J_7anP$h*A;@^c3>jjlId^vi zeDd`RanXy*(ZSn-ii>)d>(>YNh%Xyg+gCdD>dJn09jXkvSKH^jIeYSTO0bq#hiz({ zodb>Co*iPN7aMxSrTX<5zpc%gU+rA)8qRgLe8IEs+I+f$_bfl^&aE@y9Mv6dUEZsAzHSM;>(RlNT01`DxuDiFoY=zN zUcY^6g3Vg#Cr2L1q*Hy1g|QfK3d%0I+#HZiXT@E7MqOl9T~uDSWe)E-fp>@T-FtoJ zdO70CzOuDybVHlJH@!L*1LuK{Rd@CoZ*24S*pKIgfE~v71Z4Pof0ak}J{CLVX|zLJ z7XrFgv%%jUoMr=i;K4wX7xIc$&(_6Uto%)K=SB=FMq(kpwMX6A!@i2IJ^1WVD{?GX zHw0s@)W7}sd)yNGS%F;lHHa5V|7t#bJiLd~2YERZADp$(2l4CU&Tn;8K8Y#1@-X_) z$5hNmd&G+lIVs$n@f`tM#INd-9*|?G9D4WL7*x+DYwrH#2It#5m&OM*=iI+8z~7$_ zV>Y=r=yO-{kFDgb#xGuU$fbSsl&$6}27F^TdE~w&5HDv&6AyNi<-D6$Yx2ZC@tF%M zKJ)^eceb9~djqm+EO!04;;Fws(8wUGXm)519Ox$N;$jcJninIjXg)eO+XD7GTQ>$3 z1ADgwVo-jFIh0-Ux+xID`d$G4dwz1NCdJGCqRB?{sm}xXV$;{?O`%8I_+Y=iYN}#s zzqr6HfxKvZwMVmOZ@>qBlB1y)0_)`yA2f3x57=Eg*)C^v>ebY!vyVwHtImPFYk8jV zhi&-9^2Gsp^0$`fNu8UpPhzo>U38RB;(Bv%N1%zLy*m+Uo>y!r`a_|`qGHsq{dm^I z4=>yOdl+I^^tTVP?i~1U9M-oD>%Y-{rlf57seyjmKwmk~TL*gGK>tDed52xiem-2C zKk!?0$aP;ES}%U?2hU>mh}nN^Ka)}Redj=bZIf@GeCyqNwg1$tn*($7zrX!#MajHx zpr04|*pB~#&}^&yPY+F=XLrqgb>{j!9W%)ItNf8;dF}oF`sR1Z`0rDA-Zk+2VtCY7 z?fHq&y=~t-MaFvv8E*>Dv7L;UP1*Bf!=6iqJ)1&{K`-YM`2)^<41ObY#G<09v z|2#AqCv~Ct@622;|CWJ1ukCRj={>9U?sD-|Z=a0cWN6~* z-sojM+}81H-!#zoh9+B%^ry9czV(}0?+&$2zTQ2kFYwh^9Q5wlzJF??7g}HP&S><; z)^BY+d+jfuJsZ&Hw|=DE_0}(I{l%@{)B5MP{;Jl$u=QWldUvh;*S7v;L+`!Rx;szr zd8NN4xG-R+<_?yh^MacL&+60iP}-h;N8mXGo_+Ie%y#i-tNOG?wkD_btgD#MwK=wU z|GqOlh`BiK4#ZU*&_!m?tDcSuG~@L_*%wnM&rmizr;XXihTcB=H0P&emz~R*dqN;K z-p{><^fvH=z4-C+m953kX6F!Ujl9xRb7TNMK5q{AC6-$8+Y6&z^zh@DKr^<#Vj(UG z??hhz`BHxQq$cptCr|GV>g%K8Sn`dFub$)fK-rCFE?7FfPH6utI>8ugCs-&$llyES*s z&B2+$Lg1XaziJ(AzW8>nvc7Xzf6B0bW1~ksBOjg9>>2sy*T{GJ6uzp*$7N0JRgC4l z&R5N;=bF1OW4T^V?`-3LOW=Mb(`RILV&3`f^XVBPe|rM!&aUxYLCK}dm|gCJxj?)& z1&e`Z-xUEK{557z$vGiodBk&1z`kFL-An1~ecBrR>O;>bci5;;&G3nT?t1&6>dL?A ziKpsj%+uDaEd;COUG1%fZ}S@Y#B7vTK2&V#Go3hVm1p^>yV08a;g-Nza9$o4uvc7O z9*BkWDt>(o#d}|HeIQ2bgL4DC_Vo8EUOZ%K4+mv0eXty`O)NbN`+L3O-}_Mh(Wj}G zdjrqG^6OO@kA9KMFST-dKqr3BMRi%dnnUx2P4fZ!N59Rj<~N;M?{}Xk=Z+0p@8g&! zx<`NLCyO6_{KRF9F<(l4ou_`!7;||M=e63mFT8)7_C?)6fB3PMnt1gT8~Lq%)et%E zAvxb1h_BpKEFWtvz9urp*c^)9@tjm1+1%SYE$_?W;n!OBR9%u=^(O|}wm_Wls3p$; z=S403c8bLKoxyVgcZFu{fA7{7Li4-s>X&4E%0Sbt-5=0Z{9=HAq@7iE(S^r;*d4e_ zjtR_<_ct5ZBYs-~a!+dXuJrcM|LoT~UDU^pJaQ^_r)EsQ zXBgR9<*3f*$V;X4=>E-TjRNFMGD+T2g>9?oq?u3lR-26QO8EgICk=1|14z;%s zti^^|-#fAw)RY)&Re$_CJ)m2C^I2ToCE{XTKNpyjzfFPt*92;NKCrj)=PWoU__qaO zwLRDolr8cJi3i$%RXbG&}LBOFfhw-<9=gYvS`@lhyn5$IU1E`F-{jo}=^ku(CAKf#=ELVQcOAT)q}u zv9SJ;&|=Z+IcbpbGvPV5lkq)M_G}sUykppNM`*tGa&~7hp`GQTKNFeu%m;e4 zYfXH9udOX)Y;99eYroXi@LSv5t^I6U!*6X%xAw2H*4M@NbvnwXYuen_w%;95dKcT8 z=PlXWyS1maHT>3`nc8<+Tf=Y7e64*&TPuD!Ti51_&)la|8}^tE3Nt6Tq~^klF@<2M`53vLg**L`QeZZ@hz5L>t@*qOk~ zv3o}Ita(phPEKmCF&rDzJxAt3;NEA0XVJ+2VCJ;P2l8P*9Ul+w3fOUP;CVS0h}mlc zI@AW8;?KU)e`ChKACO7+odG$$Tsa@*-jTUcE}JVRtonwzD2U*ln)X5VXq+E;VtYi^dT8yZi^x;pfIL0$_E z{(IW=Rh-@VB~#3&&1d@HU9pg{yG9+H6yRsq_Bee{dTVl{(d`V0$1%YuU+t8gbr+R< zwK~dwbLPmOCCj|~@9v;KgJgR5?`q&kiOnq+-vSIU;Agj__)`4e=Z;B=MMBU8l9~NzfYmo#jKaJFzkEM zKtExij~M9BwRic7^QQ*-w+H%{2l_(;{egk@w{ClT-y2$N)X<*6mv70MJKmYo@Hu<> zlY@G0py%4We3U#r9)1702kjZA@8zLA|MkwL{-Q~(?sJqs$8+#^u03Nn1#Du!J4ikEvgu;C`Y*dHzxFu~_PR5whRyLQst*1e zMRc7Q^tO?EN}!3yv4OfFpWWojk$Jc=_*g*iu7Ex8E75ag`qG%nKri0j zH}-gbko}f`J@T&6O&`Cl_c>Z{^^~uFV#IA8wW{{9uc7_YFbSuX(-~oGbC)+-e_{ni@Etb z+t~iPZ)@J!m=EZ&U+j$Oz-zDfezNTE`HN3o;V&M0>~){iol^ST8T|3g<>&TbN5JN# zfSjsvd&s^wxHfoR@QOga*;}@$C$YdwpZSt;QN|is?hkg6q3sFq*M7d6vzHFMHwAQQ zZwr#vN1VCheQU<@N4GsSZ*R%1^Y-@4X;r5^|1_P>{Sg5^_7{(Px#sW5SZwNh3fnSf zU&U39#Fl;XxG^X@&dQi*LTa=tjmwx9+zSR&}@KyX7&jlX(Dwf7&7rA8@T{{DL z`sL_RJ77+XPsm)^N(TGNHu?IwJSg;6w>5G8hQK*tueKbpN6$_+*+cHD1AAWIXu9tT z@Ro0tFMP%y3&=h_AcHLY?5jO`{PThJ;#CvHr+!OM&%2a)`{^hix#j~{Gru{IA3jxV z>#UL|AI>0NwAhs|;%@DsKx32E^Vo;3nwKMT%x2&7S*$l*uD~4)4jF8eoHXx{v3AbAqo8&JE~a473}9BZ66R z+K(x%-gWvoshK`b_$sc>V9D+MFt;4^`@~Evt&K8kt@r=s;hPJprpVeDTp!>khmU&# zapl{a194%Ooa_zo;3vo2!$IjGgPsk6J!-Aa`lgIa7rSTaGGDsXS;e^WOn2GS>#mv+ z3$@|i0{ON^?nQxy2duIAEdf8z4)E5V{*J=m(-ptv%zF>$<5c_Eenn6+>FQ-z7w>*< zHMwMz+zcoC#YF8|E5GP0zr53x4fSG?Beh3WbakM1A)e`!)@#TyGC0_y}g~{xe&M; zoiA-#4EvmXspH9pSvGzt;y5km<)iw6ix`#WjH(|oO88g2Z|vI>*yD^=4Z8<72I}vM zKuvB4O6FSc8?x2DnDq9NSN1Mv?7rx2ri)GW*|@(Sdpp@j$4d6n^~Kn0Kd3+F+jwul zKDz6is?(c-xJs)6!JZnfT?|JKeuTl&0~ZT9r` z(20*<4+I*XvY&5DftZ#};(`_zc2#UD24&}ltkGMwN#bsCi{GnQ~8`$ zPk-2a?w_|}I{L~F^82`qHj+^`vZH)1yZ9_-tJze4mt?d3(g7N z7(6>TGqA@qM;#ka%a!L5ADR9vUMRil$v!vl<$4biYZxS9;%Pi-VdkMiCR$~bm+(W_y?IA z>qE`2rOtc5`ud=&r>kDXd$pP`zxbjS`+Tj%CUsP?rnhQLZHo0;Y?$?Ptl|O>2HGhB zc}06RSXUcjeODkBb$790eNg;jf!}=bv$;M?IwQ{T*9Bva)Uv(!d)yM*zA=9E_O{Zg zHhNpo(`@hWlQ)HDv_+oCCKK)qX59nMwfxxgSn9t2`QH9Kv;A=R_w|u8`X|ohvll#9 zoMSN-*Sp922CkFK_sJy-?b8@22$uOSw?5*eAcwh6Q?6X&^cun(h{{fbR z&pw~y#$3wRQozQAp!fH-Houy`Y~io{<*R(L-`ZpKmu=cBgWn6}n7o~VRzFiAPjuA0 zpWo`~cZODf{oL2JIeW-_$*|{X1O4fIJ*40NGXwpd1HEsc&lqU`PFyeVM+f?K1ARlI zcQt#{t=o~m2cRz>{M)>}%>SC7XYJ`99O!os^sNJZ{y-la+8K}!ck;QxJ;7q|xj>A| zmMinKuXluY7R-ANsR!%M*3Tz-V@|#!{`B_x+a30~&r9wzGS};wYkTIxGanoq;CCO@ zJCwd`aF?KK-55Np`u_ArZ*2XOTYqZn7h3QBvTt+ix3|9b)%uxj{%Ng$M(cN{?|uGI zenE#k&pEyGs#oLs3tE3s`U?YgYGO<0dBIzPmjo{j*s~*0;~+kK!7G>U1n26AU>dJG z?E5>OmuJjg_l-LEiGVHI^#NJ*i1(gAjgU<*U7nrxx^wV4ejwBhHv?9q#&jIQFZ*Cp5k3CeMTaC4JS&X~WvPyS3Ho z@2iHr|FqltC^aogwaau?^?n%s-uk+C>DDSGMo z&Y)~zXRm9#8-J|beLJ&9dw8JthwksnH??)V#|4M`u5@>L?z%JGv6?&6*q!-Zftr1B zE;-Lee!d{^{#5i;8EcmZ)|XpKdSDl><586KJq-&hBm)>!{?5g?g;n@+esr=*z|L+XQVYga(PGFyB z$+*wGuaRGJ`h9iIYrh!Qc$Br8PWtI6ou0R7F}*8bgE6qdIk`DFCfF48w(zrTS)Xy) zQaaWm^Nj2xTf00UlMlvfuxygoTAyay8I6Bmdi!4x%mw1azY_!JU_)?za9glE1A}gtF+uV3c`m3u zVr5P|=`rR{&(A(WUp@8wbylpGKgL%EWYNKQIhMn#gZqLUsmW&>{;IWW zgVTan1kN14-PiW;!~Uu(@nn}Zw%~nYa8vMvpq_W+&`qE534s_H-xJXJvDm?1d&rbC z_Pa;rgD!pM_$3d+ZZ;wu#5KKuop=I|8y@G|Ik2x_dq`|(64H=ns*s~eA+rpQXczc`ZS10_~n8bN+aNlG&iO2f%@g0E+(-767TVZc z*+RCveJ&_|YwW8vcZ_yhushfqkiqvG0=4Q)k#Br^P<-@`>#v=%zMMIFULH87Ck6Dg zMZU`aJsIB^u#dhw0&x)!XO&%#YvW_mJHz67ec=4ES*_Ur=0N`47i=Vpy(MdX#wCjm zvdodA*B%b=kXJs_drt5@LD|g@ci2ME>#9BUYM$?Jn2ZkavXB4bL5F+C?_`f>fG={- zmg2=zHCFx>Pt_SefNg!84`TSU;*;+Im-yLY|nKmzu zH7|#3H^(lZqjF`;A2BTZ?U@hcW_@5?Tq*{=9Pb<@qmMx^LyXCI{tOxNQZg>hc$yt@ zK*p89G&|Hn$+#@zX)-cBk#SXeaVJk+jJE~yBVX=^dxLX>e-SJOp9{$E*S-P-w-J!|seSS^m%I++!yQ$H}#|8MScZSf;ZolURO|EB#bU$%s@Vj#hdMO zjo#j9F|dAiqsxXf8eMjfZ-3dcwb5nImPVIN_TewP$VHcJ^rFi?cAI^q z?r8DCTX*n$qvg-K`^9=ar%!A2$?2^>wb7?EdUvDc!n)^^{q^ppN1L~f4^0l595g-X zsv~xw*=c<~Kv(_n16}pOPqh0C|E9oQXe=hyj6uxNb#~8(*4UZubUqx+joB`Q$5_ZSwd)pt13&fc&EaZU2F8;txIYzdNYCWWPC}+kX4( zKc><2u|vGsPv81rl!KlnCrcB%$?E0o3%wkWuNNaWXl$4jBk|1_9z*oMC8T;n~ zjUDpEmuY!eO$T2}cIjJ-4nAq(E}!ClWuO^fG8rAHG3(QO6zj_ZHd7PNnsn}KF2jj$;-c|io$~jnKx0ScTkVJ!o^1jD-0S?fA<*m7Y|1x9pTVIc7`M0(C|m9RK)|0_@jE?h{5q8QEr;Ko zer+IbTE$6SlIOjN&fdSRp~bx7yVSZg?=hLib z7XRdx+`7AF<&oT3a{Jr8`$&KCU-u)b1J6d zWGsg4bQe2Ua%zuxwpF~x^RcI`+gImDeDL>k6;m}Xf1~cwG3qXx^ z-fOM5gYV?4+oJ-lr~7-!TAwHPm?lqTYu24N`t}CmCq8Ivy${y;T=Ba+6X@?^YY}8hY13kTOa?2O> z=kA&2Ke=S~`zmhsjWw}S9OS<2q)R^Km0f!R`KJpm4m3P+!A|FnJ~1Ef%1lk<;HPJY zi8SNQlhFbHrs-r0U)aJvwy*&&U(t1z?$210bB!(djt=Ye0||$bigKli7mhA!3nrAEC(ccF$r&(tc zo;n-!@f)m{kH+lAtL;C~O+G`CvE0BG=s(wtvgLf1YwQ@> z&(=QfYLCzLyqp$a_fOfY4(vfM1ZuX{=;vGMwN|=}OP9~x#?y51TkYw^ZBxKMG~IGu zYiDGx0rqe(5`3Ot9%iM%5V8ZXVnBfHDA8cdsI;I#q-73;Js^_4d&Ix zN;XW3dmo20vwv3H#~fG87qW-X&Q{g2n2CuzmOb?@Bp(|7np1P?LagQjO%BPedzVa2 ze(Mfr(`r7QAD*@PMBd(jt~~+$?g~D#_xON)<>$!HHh#06PJ8MuB-4I-$mG|iU@_46 zE~fV36Q`cf{$Ac)e9cd*Tee!8 zc6RvMpT~`jUQDmCq0R}KPPR|e^H@HsJV0og`XZNnXGGh7pqs3*f2GeXVr$#3Y7}OaMpVDm%k0t;1P0N3#C-YzG{L?=z|MY*U^Z!_U z|5D`tP+~AG|NZ%MwpKfT&YAmQW8hw_yUD%6mfpw5a!0LZA!E(6r{>(j<1@Zw)g9!nn&n59CTHzUY z?vSH`X?o;=FV6JNHlB8;x;IM?y>yA;{egDkf$rclhTn23R$@|jyFE2;?czWqdo6r? zA)DRP?nZX(3it#+m(N-JW`AK*#@Px~_A~ z=4%4Elz-ooV7EB3febnI4tIP&mYnVhtou68LO`~7l7YX*&Qp!?SIo(i3+v>vi|mpo z{`#Q0vsRes0&bMW3O)T{NXXVAv8d+*jlkaOMqXV+&HFrukSMtfEN6c>z$QRqv zDc_^cS^DR~Tc5Gj?lS|8?x#;ikG5yWlsWaJ^)VZ z3=hUh{9fN^<2pn3_qJQ(zwh6x4{KswxfS0!19xS7U*Ky=E6F3XKReFzreHD9)PnVM zf*%Ub4cN69Xg37oy?RA-vX5)v$+$S_xTNZDd-YfxuSU6XBYeNaBJzkIOH zX1vb$=s&)tpzJK(p00b3Pnvo#wvRkA_I2alj!aKvR~@MpjSO?_u6wiY-i6E=vt3NY ziVihEU-{qDe-}FWEUsdu@9&k0OW7r-8o%czqXXYB;zONJ=M|s0x+98Lj4lgi@tSw; z>}5;+48YztN6z_ed}(^Jt%>oTpmHtlaw6`=Zw)F>a^SgFIog!5eV{(%$zC?t76(_MhGGO-wZOm?W zkT}&l1Dh*0Vp!vflex-)xbTln)sMcgL92Kf(`%kyGUSIHFfC4Gm#)giw0Qk!_{Nx2 zynbxTns{ksmVbQ=#ZtYBnR0XgPx{If?MDLEf&JnF3Hd2e{|k9*&j`Akpr z^v~(qD|bH|o}%%7b^g9jPj4FNa|Zg-(C#z-)jqadoB4E;dZ-%Z$NJz~%%KfLPAe97zI8QAfk!XpNF#B`K{XI=h&6FDVA zU6&r~ugbcbuvZ-Pz1?`eGd#5?_Zs@H7^t*<%uT#`9) zI(wMEq0RSx@M}k)Cqw`A)}NbRPSwvV6AS0R*K>E1hre=vN#i4DbI{9sMx)*H_|@$b z^Ec6or)2zf!08Ht6KlU)_+awuW7w!EVu+rR&8>e`>-V+(HLYK6{q3#4qxE;T{_fVlAw8e?sfin3E=d71z5fFBP_cADI&BQp?qTy}sTpH)?k?lH z&*vIlb;@Szdhsk9$Uv7J$27WZsX8iq&Ti{v)6*JVc6rv2SGJwd=(10ItOI*$Y#x19 zo3jtStI_15<-;E50)0lKy?3MQJUB0CpWpGj)6sQq#1C!Wy4a%S6patPqtWD`>pane z-V)$!20XV@7BB3p;wg4)*O%Ptd--CplKd=Bd?6o3 z`TH`r9MBEMqu=W@w>^+E{(^X_6JvRD{w@v3*c-6D@{g?TfyO_3 z%SP)!pPU%8akV%ugr~PrY|BP5E*sSr8?9Ho<}&{K60eJ5tM=s*x20x_I;wSMLckgPpddKK(-5c8TVNc+0bZ?C|E@#g3?AidYw*Npkxj)IP=K&wax)VG8^|pna zoKf#+8vX7^=eC~j&efKHOgcQv+{J8W>$JPPze~e1k#~|o+83*%&yD9s`NKAi?d6Z> z2K#!O*q*_Uf0H#r>C1u@+VGe zl+3*W8!B$bv*IQ%>w~JH<1^;>LQv<}=NOGVbG?7!gTL}GPvWPx#D_d{=<(gxy#0Kr zoY|vQ&Q8f#&dRRpcV})>Fy^o9k$Z8pZf;f%#Z4SbZuPzVY5w-|v;Cm_F{k7&1^nt` z%4bbXZwr=dh!37V2V`4QE5&E;7#}iMvvYHJ zzF0fiQ1-FyaN8@!l~3o+c%^)bh1gU)H)YJmiWOS?YyFIj#fl!av_6=YQ|ECt-SXVm zjv7R3RYPKA{^)?Nny=bogSCBuF}n_zJ>GMs*<*e+dzQj8+QT;BkK7nv7Krt!Sie_HpqSDpT4q3e<-@;Pg76q6Nftj&G=Q5 z(dX|0JmMn<)9xZR)t%vteT{fql~;54(f; z;K*QBOuPqLFI{Cv>GOP|r*!o_9lb5$VLuzkzPF{%3H@Z&Ju|KE-^uV-Oz`>|4f~yY z_NXQE;EdON)tA}>`Mkc3SIQxu$eQ(jA!qcfnTrBVtS_F74xF)L+IWBK#f%MAvl}xe zM@`VTH;`YoFe}Ct>*~c&T;~J!*bluOc&)8PZ|yJr_KK~%@^9>W-J{NP!vC*=ZGqfX zE{w&2Jo4paF)&x>h8^;QM|{R-Ej!pKKMR3ey)__<9&xcwj(S)r)_BOXr~KQUu{)(- zt33C-^x|{QD?TNs;%&XJefxbcKwMuERGnO#u{?ap?2Vz#Sq}ROM_iOTNZhat+ zd<48>@A*uowbIwe-FeWgmp(lotZfd|Sl#bz6Q|YANXaXE(7S`Og`BF1wfJYhSc$8# zyy<)Ytivq-N}qn3f9?}8Vvn)2R%fc8H+J5R4z>q70{kF1&uHV7>W&Pyiix{MJSw(m zYvNq%;z)MAZ?V5VTa%^XuQ_(BMPRF(YT^du_xYt;(~IBMfX=1B{v(2EzFwJmejkdj z>~)^VSHEll`D7>m`BHSnVBE)6F*zw<1HagAKRKSCbf{ml`uwAuoc#ZQzN0fPzmLecbQ|-P?x(l$N`CW^4!XsCW1z0@ z4>YmU_8;gb&w9^$Ij{TRjEv>0=Ii|QbwJ0V@QdkOz@N%<`N+Q$gI$3!{A_-1Q9LS^ z`b~lJwKBW>+0LOT=3`kK%Duc7VPh9flYOX z<7F$K>v>B*n(t)ReMc4)t)}^9PCo5fYU8>q$f`WyG2YklRBYu-Bb%+e01NB(LCLgVvsN*_U@~(c#^<)N7#{8z_vfu*!GAT(Mt#M57BBzif(?N@=_~ef z4nTQ}${F!AF-P3I9W3v{U*f^d& zepGE3m)+v5;TL!9@<1N=*}tpG-BKW5#gA__esVnL?HB9%nhsf28!vBT=h69ar_r-F zaM$e#%vVmup~m$&+nw*7iVnG~ypBCT|+=E)D!#2 z?e&{iS7Sd*f9>a+d%|9JjeT!>Z!bRYfd4uezb8nhwf9e1bJweh$`Rhm(Y}n;y%=2I z#$v!HF_`w;k?+clSk<`ClekvQr}-_m{OS8ye$$~robJkd8TPwb^@><=YR z&IuWPKg-_A(@%weR-XRNlr?$M_*1b|CzU(B&y+_7ntYm*s~+Ct%cWUlCt>yB=}GgEVTb_~BG zbHx;%y9SPO>uwn6y9fHgf&Q-0 zFuzgc!sm%w4n5zO+E%$m=boJ~RTIoDs` z_^hc-Jyg6t(0*s*xHd=kdozc|w>2nv)_!x)dq%e|w$IM*t%xmMeVtf)f7aO4&y)F* z{7#1ZrLQ0J-<0{%9dg~Th1Rpne4R7DpK@%QKeL&4dmS*<_2^}Ac|bE@@o zTkrXWKEL%BwEm*jU)=gVt@k{}@4nVw(fTV}|AN+E-TD``{>81ow)HPtEgaTU&oy>tCDRGmc-HxSSWrp?3F_-$7aa^z`3B`M2Ts9R8Mo-g+(` zn=!bXxjM@_ut=9)mxwgmQ+Ok=>O z=Aih!!?*{I4vN2Qz|W52Rj0k)y`lMpU&Fr~_?p8wuja1{=+W?+!?!+g-^;63YxvzO z8eMF$rf16)fxXu53lgG7%s)TS$QGlLJ3ajU`GH_D_*}3d*coW!zi;o~^6c0D>p=VW?8U`?dVV0Z zckQD8*}(tJ1O4`ae$znTI?y+Smba4s{Lpgk?24s%aeQXmm*HfdjdcgkWsJYyhbC8F z@7~344(iT4xzWy;vre{VpRx1)(}A=5V4%?@{{CGvHUEY{T#pUZw0d;*a^D@$8*6n-Ez_EW;-*k57;5@?611~_0-?!OO_{g z)}6uL{!IS6(2IdH*~`kWC{Aj;WPd2M8Yuev2m1bjzB#n`X= z&hIa!ZHtkwRg8^$dwzEnd)WP;O=)unx`T062cAvhXHCvO7*yTZTRs}|S*=uzd%sV~ zynK;aHM;!&v3DnMmS1I^@RRO@bc~7vS=G>0y`{Hc(plJq+_t(Cf-D1MBY`Y$bx0>P z2?(+zK!_a@UW{9G6hVhkbWmJIN1Rd7iMTR|;3z1Hj_V*Uh$ExpIIq+5``-RP?aA@p zs$0E)`g%V6IOjR%InRF1|9@{)S2DKmF@gG)hi7C$4ek#%1oEKSr~aNFxbxMLvAyb0 zZBz~Qb8=95-IwuPK(5-Mmksohr;gEV=;hE;a`;*@_+^j1ORbmv__SWWy087coz8H( zZZEy;Fy_Y>2I~X1?+UCf3^X1x=7Z8(=Z@{YzLPVjnHQJ#d1$_5h`Tt7O`mu6g8TFl zQNk|17ud@NGPVco;FJHh9aGY!&=o;$+q^opw74&6^rWv^2Ff!psg!*sz*)U z)uTJ3jW4aF8})P|Up zj!Cw(>lHKd#g`n|9*CE@AB#-u6+3mOCdH5*HLmRs)RJ`#tv1xQ`29q1aUj>DKvP?{ z1g{P3r4!ArqRU2Wuq)Ub(7!PB^=#5_2-qvewO1U#KDw?9tb3>38St4rYwnbj0yh7r zpk&iMA85OSsv-8=9@Jj-M3-7{p4JU?#r6wAi(6|S*)YjBGA8*{d)Rklz*qK_-c1>c zL&c!@Uy!-Fm)TVI8}rNl)))KuTE48!*j-MxT-)!Q%Z2!=T{$kh$eRnqMI-BJf&8}i ztqu*=q4t+wWy6N7*|#Pr-|Xx2i{E^kb9>D3wc>C`#(2x;%Kbx`>vL}}fA}ot#*<>k zK04Z%IWuJI?H9X+K)gxgBa>tk6cQGs9E5E(}czXXQ@%FK-98BV!6xX7o`Rd?jpd8+e#xOMl_ zk#)4{?q{aR%JiYSy{P`$yMat`sypc? zGj=D5Sv?Qxj=Usu6;pTA>x1HDGuzrdArIY`^wxQ%lWl)@Umko;IQ#s-+xo%3y6aBN z_=N#Itsm@a{rH{GWm~-qw0^Lk9aW!o@4mj-S3XVJPuH|Pd~5fF9LIql?5;Stx6S=s z96oRSJmRA`;BDg|J{1SH*PTyS8w+Qrjm4jbu2@)ejuwJG9`?)xS+CS$3% zidDZaQ-_`#;!v^Wqi4p?2Fsn@u#Dra<}2RySxYYV1njC9vmdWmRU9)M+u;o0Ej!rU zKA%F4b;!B%q&~t&LlJVBS z8r⁡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

pNqh`{-GW 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 z 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

kT5XoMOIf4m*1(u9wdou@5`1y+Rl)lL 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

7T~$7f#`%w__T=_`G4t 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

9PQB2PG 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 delta 58044 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%0A#m;#n}G;$d$b;A`V4_0*eX7 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 N1`i%Q!=A0={2x diff --git a/build-aux/ax_func_which_gethostbyname_r.m4 b/build-aux/ax_func_which_gethostbyname_r.m4 new file mode 100644 index 00000000..a318eba9 --- /dev/null +++ b/build-aux/ax_func_which_gethostbyname_r.m4 @@ -0,0 +1,308 @@ +# ================================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_func_which_gethostbyname_r.html +# ================================================================================== +# +# SYNOPSIS +# +# AX_FUNC_WHICH_GETHOSTBYNAME_R +# +# DESCRIPTION +# +# Determines which historical variant of the gethostbyname_r() call +# (taking three, five, or six arguments) is available on the system and +# defines one of the following macros accordingly: +# +# HAVE_FUNC_GETHOSTBYNAME_R_6 +# HAVE_FUNC_GETHOSTBYNAME_R_5 +# HAVE_FUNC_GETHOSTBYNAME_R_3 +# +# as well as +# +# HAVE_GETHOSTBYNAME_R +# +# If used in conjunction with gethostname.c, the API demonstrated in +# test.c can be used regardless of which gethostbyname_r() is available. +# These example files can be found at +# http://www.csn.ul.ie/~caolan/publink/gethostbyname_r +# +# based on David Arnold's autoconf suggestion in the threads faq +# +# Originally named "AC_caolan_FUNC_WHICH_GETHOSTBYNAME_R". Rewritten for +# Autoconf 2.5x, and updated for 2.68 by Daniel Richard G. +# +# LICENSE +# +# Copyright (c) 2008 Caolan McNamara +# Copyright (c) 2008 Daniel Richard G. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 8 + +AC_DEFUN([AX_FUNC_WHICH_GETHOSTBYNAME_R], [ + + AC_LANG_PUSH([C]) + AC_MSG_CHECKING([how many arguments gethostbyname_r() takes]) + + AC_CACHE_VAL([ac_cv_func_which_gethostbyname_r], [ + +################################################################ + +ac_cv_func_which_gethostbyname_r=unknown + +# +# ONE ARGUMENT (sanity check) +# + +# This should fail, as there is no variant of gethostbyname_r() that takes +# a single argument. If it actually compiles, then we can assume that +# netdb.h is not declaring the function, and the compiler is thereby +# assuming an implicit prototype. In which case, we're out of luck. +# +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], + [ + char *name = "www.gnu.org"; + (void)gethostbyname_r(name) /* ; */ + ])], + [ac_cv_func_which_gethostbyname_r=no]) + +# +# SIX ARGUMENTS +# (e.g. Linux) +# + +if test "$ac_cv_func_which_gethostbyname_r" = "unknown"; then + +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], + [ + char *name = "www.gnu.org"; + struct hostent ret, *retp; + char buf@<:@1024@:>@; + int buflen = 1024; + int my_h_errno; + (void)gethostbyname_r(name, &ret, buf, buflen, &retp, &my_h_errno) /* ; */ + ])], + [ac_cv_func_which_gethostbyname_r=six]) + +fi + +# +# FIVE ARGUMENTS +# (e.g. Solaris) +# + +if test "$ac_cv_func_which_gethostbyname_r" = "unknown"; then + +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], + [ + char *name = "www.gnu.org"; + struct hostent ret; + char buf@<:@1024@:>@; + int buflen = 1024; + int my_h_errno; + (void)gethostbyname_r(name, &ret, buf, buflen, &my_h_errno) /* ; */ + ])], + [ac_cv_func_which_gethostbyname_r=five]) + +fi + +# +# THREE ARGUMENTS +# (e.g. AIX, HP-UX, Tru64) +# + +if test "$ac_cv_func_which_gethostbyname_r" = "unknown"; then + +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], + [ + char *name = "www.gnu.org"; + struct hostent ret; + struct hostent_data data; + (void)gethostbyname_r(name, &ret, &data) /* ; */ + ])], + [ac_cv_func_which_gethostbyname_r=three]) + +fi + +################################################################ + +]) dnl end AC_CACHE_VAL + +case "$ac_cv_func_which_gethostbyname_r" in + three|five|six) + AC_DEFINE([HAVE_GETHOSTBYNAME_R], [1], + [Define to 1 if you have some form of gethostbyname_r().]) + ;; +esac + +case "$ac_cv_func_which_gethostbyname_r" in + three) + AC_MSG_RESULT([three]) + AC_DEFINE([HAVE_FUNC_GETHOSTBYNAME_R_3], [1], + [Define to 1 if you have the three-argument form of gethostbyname_r().]) + ;; + + five) + AC_MSG_RESULT([five]) + AC_DEFINE([HAVE_FUNC_GETHOSTBYNAME_R_5], [1], + [Define to 1 if you have the five-argument form of gethostbyname_r().]) + ;; + + six) + AC_MSG_RESULT([six]) + AC_DEFINE([HAVE_FUNC_GETHOSTBYNAME_R_6], [1], + [Define to 1 if you have the six-argument form of gethostbyname_r().]) + ;; + + no) + AC_MSG_RESULT([cannot find function declaration in netdb.h]) + ;; + + unknown) + AC_MSG_RESULT([can't tell]) + ;; + + *) + AC_MSG_ERROR([internal error]) + ;; +esac + +AC_LANG_POP + +]) dnl end AC_DEFUN + +# Added for OCaml, should be submitted to the autoconf archive + +AC_DEFUN([AX_FUNC_WHICH_GETHOSTBYADDR_R], [ + + AC_LANG_PUSH([C]) + AC_MSG_CHECKING([how many arguments gethostbyaddr_r() takes]) + + AC_CACHE_VAL([ac_cv_func_which_gethostbyaddr_r], [ + +################################################################ + +ac_cv_func_which_gethostbyaddr_r=unknown + +# +# ONE ARGUMENT (sanity check) +# + +# This should fail, as there is no variant of gethostbyaddr_r() that takes +# a single argument. If it actually compiles, then we can assume that +# netdb.h is not declaring the function, and the compiler is thereby +# assuming an implicit prototype. In which case, we're out of luck. +# +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], + [ + char *addr = "192.168.1.1"; + (void)gethostbyaddr_r(addr) /* ; */ + ])], + [ac_cv_func_which_gethostbyaddr_r=no]) + +# +# EIGHT ARGUMENTS +# (e.g. Linux) +# + +if test "$ac_cv_func_which_gethostbyaddr_r" = "unknown"; then + +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], + [ + char *addr = "192.168.1.1"; + struct hostent ret, *retp; + char buf@<:@1024@:>@; + int buflen = 1024; + int my_h_errno; + (void)gethostbyaddr_r( + addr, 10, 10, retp, buf, buflen, &retp, &my_h_errno) /* ; */ + ])], + [ac_cv_func_which_gethostbyaddr_r=eight]) + +fi + +# +# SEVEN ARGUMENTS +# (e.g. Solaris) +# + +if test "$ac_cv_func_which_gethostbyaddr_r" = "unknown"; then + +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], + [ + char *addr = "192.168.1.1"; + struct hostent ret; + char buf@<:@1024@:>@; + int buflen = 1024; + int my_h_errno; + (void)gethostbyaddr_r( + addr, 10, 10, buf, buflen, &my_h_errno, 0) /* ; */ + ])], + [ac_cv_func_which_gethostbyaddr_r=seven]) + +fi + +################################################################ + +]) dnl end AC_CACHE_VAL + +case "$ac_cv_func_which_gethostbyaddr_r" in + seven|eight) + AC_DEFINE([HAVE_GETHOSTBYADDR_R], [1], + [Define to 1 if you have some form of gethostbyaddr_r().]) + ;; +esac + +case "$ac_cv_func_which_gethostbyaddr_r" in + eight) + AC_MSG_RESULT([eight]) + AC_DEFINE([HAVE_FUNC_GETHOSTBYADDR_R_8], [1], + [Define to 1 if you have the eight-argument form of gethostbyaddr_r().]) + ;; + + seven) + AC_MSG_RESULT([seven]) + AC_DEFINE([HAVE_FUNC_GETHOSTBYADDR_R_7], [1], + [Define to 1 if you have the seven-argument form of gethostbyaddr_r().]) + ;; + + no) + AC_MSG_RESULT([cannot find function declaration in netdb.h]) + ;; + + unknown) + AC_MSG_RESULT([can't tell]) + ;; + + *) + AC_MSG_ERROR([internal error]) + ;; +esac + +AC_LANG_POP + +]) dnl end AC_DEFUN diff --git a/build-aux/ax_pthread.m4 b/build-aux/ax_pthread.m4 new file mode 100644 index 00000000..5fbf9fe0 --- /dev/null +++ b/build-aux/ax_pthread.m4 @@ -0,0 +1,485 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_pthread.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +# +# DESCRIPTION +# +# This macro figures out how to build C programs using POSIX threads. It +# sets the PTHREAD_LIBS output variable to the threads library and linker +# flags, and the PTHREAD_CFLAGS output variable to any special C compiler +# flags that are needed. (The user can also force certain compiler +# flags/libs to be tested by setting these environment variables.) +# +# Also sets PTHREAD_CC to any special C compiler that is needed for +# multi-threaded programs (defaults to the value of CC otherwise). (This +# is necessary on AIX to use the special cc_r compiler alias.) +# +# NOTE: You are assumed to not only compile your program with these flags, +# but also to link with them as well. For example, you might link with +# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# +# If you are only building threaded programs, you may wish to use these +# variables in your default LIBS, CFLAGS, and CC: +# +# LIBS="$PTHREAD_LIBS $LIBS" +# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CC="$PTHREAD_CC" +# +# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant +# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to +# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# +# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the +# PTHREAD_PRIO_INHERIT symbol is defined when compiling with +# PTHREAD_CFLAGS. +# +# ACTION-IF-FOUND is a list of shell commands to run if a threads library +# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it +# is not found. If ACTION-IF-FOUND is not specified, the default action +# will define HAVE_PTHREAD. +# +# Please let the authors know if this macro fails on any platform, or if +# you have any other suggestions or comments. This macro was based on work +# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help +# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by +# Alejandro Forero Cuervo to the autoconf macro repository. We are also +# grateful for the helpful feedback of numerous users. +# +# Updated for Autoconf 2.68 by Daniel Richard G. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson +# Copyright (c) 2011 Daniel Richard G. +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 24 + +AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) +AC_DEFUN([AX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_PROG_SED]) +AC_LANG_PUSH([C]) +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on Tru64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) + AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], + [ +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + ], + [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) + ;; + + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ;; +esac + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +AS_IF([test "x$GCC" = "xyes"], + [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +AS_IF([test "x$ax_pthread_check_macro" = "x--"], + [ax_pthread_check_cond=0], + [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) + +# Are we compiling with Clang? + +AC_CACHE_CHECK([whether $CC is Clang], + [ax_cv_PTHREAD_CLANG], + [ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], + [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + ], + [ax_cv_PTHREAD_CLANG=yes]) + fi + ]) +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [ac_link="$ax_pthread_2step_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [break]) + ]) + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + ]) + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -mt,pthread) + AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; }], + [pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */])], + [ax_pthread_ok=yes], + []) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + AC_MSG_RESULT([$ax_pthread_ok]) + AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_CACHE_CHECK([for joinable pthread attribute], + [ax_cv_PTHREAD_JOINABLE_ATTR], + [ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $ax_pthread_attr; return attr /* ; */])], + [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], + []) + done + ]) + AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"], + [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], + [$ax_cv_PTHREAD_JOINABLE_ATTR], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + ax_pthread_joinable_attr_defined=yes + ]) + + AC_CACHE_CHECK([whether more special flags are required for pthreads], + [ax_cv_PTHREAD_SPECIAL_FLAGS], + [ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + ]) + AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"], + [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes]) + + AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + [ax_cv_PTHREAD_PRIO_INHERIT], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) + ]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) + ax_pthread_prio_inherit_defined=yes + ]) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + AS_CASE(["x/$CC"], + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + +AC_SUBST([PTHREAD_LIBS]) +AC_SUBST([PTHREAD_CFLAGS]) +AC_SUBST([PTHREAD_CC]) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test "x$ax_pthread_ok" = "xyes"; then + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) + : +else + ax_pthread_ok=no + $2 +fi +AC_LANG_POP +])dnl AX_PTHREAD diff --git a/build-aux/compile b/build-aux/compile new file mode 100755 index 00000000..a85b723c --- /dev/null +++ b/build-aux/compile @@ -0,0 +1,347 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2012-10-14.11; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/config.guess b/build-aux/config.guess new file mode 100755 index 00000000..f50dcdb6 --- /dev/null +++ b/build-aux/config.guess @@ -0,0 +1,1480 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2018 Free Software Foundation, Inc. + +timestamp='2018-02-24' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2018 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > "$dummy.c" ; + for c in cc gcc c89 c99 ; do + if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "$UNAME_SYSTEM" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval "$set_cc_for_build" + cat <<-EOF > "$dummy.c" + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ + echo unknown)` + case "$UNAME_MACHINE_ARCH" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown + ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval "$set_cc_for_build" + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "$UNAME_VERSION" in + Debian*) + release='-gnu' + ;; + *) + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "$machine-${os}${release}${abi}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" + exit ;; + *:ekkoBSD:*:*) + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" + exit ;; + *:SolidBSD:*:*) + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:MirBSD:*:*) + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE=alpha ;; + "EV4.5 (21064)") + UNAME_MACHINE=alpha ;; + "LCA4 (21066/21068)") + UNAME_MACHINE=alpha ;; + "EV5 (21164)") + UNAME_MACHINE=alphaev5 ;; + "EV5.6 (21164A)") + UNAME_MACHINE=alphaev56 ;; + "EV5.6 (21164PC)") + UNAME_MACHINE=alphapca56 ;; + "EV5.7 (21164PC)") + UNAME_MACHINE=alphapca57 ;; + "EV6 (21264)") + UNAME_MACHINE=alphaev6 ;; + "EV6.7 (21264A)") + UNAME_MACHINE=alphaev67 ;; + "EV6.8CB (21264C)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8AL (21264B)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8CX (21264D)") + UNAME_MACHINE=alphaev68 ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE=alphaev69 ;; + "EV7 (21364)") + UNAME_MACHINE=alphaev7 ;; + "EV7.9 (21364A)") + UNAME_MACHINE=alphaev79 ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix"$UNAME_RELEASE" + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux"$UNAME_RELEASE" + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval "$set_cc_for_build" + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos"$UNAME_RELEASE" + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos"$UNAME_RELEASE" + ;; + sun4) + echo sparc-sun-sunos"$UNAME_RELEASE" + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos"$UNAME_RELEASE" + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint"$UNAME_RELEASE" + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint"$UNAME_RELEASE" + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint"$UNAME_RELEASE" + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten"$UNAME_RELEASE" + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten"$UNAME_RELEASE" + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix"$UNAME_RELEASE" + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix"$UNAME_RELEASE" + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix"$UNAME_RELEASE" + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos"$UNAME_RELEASE" + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] + then + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] + then + echo m88k-dg-dgux"$UNAME_RELEASE" + else + echo m88k-dg-dguxbcs"$UNAME_RELEASE" + fi + else + echo i586-dg-dgux"$UNAME_RELEASE" + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "$sc_cpu_version" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "$sc_kernel_bits" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "$HP_ARCH" = "" ]; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ "$HP_ARCH" = hppa2.0w ] + then + eval "$set_cc_for_build" + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH=hppa2.0w + else + HP_ARCH=hppa64 + fi + fi + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" + exit ;; + 3050*:HI-UX:*:*) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo "$UNAME_MACHINE"-unknown-osf1mk + else + echo "$UNAME_MACHINE"-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi"$UNAME_RELEASE" + exit ;; + *:BSD/OS:*:*) + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case "$UNAME_PROCESSOR" in + amd64) + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; + esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" + exit ;; + i*:CYGWIN*:*) + echo "$UNAME_MACHINE"-pc-cygwin + exit ;; + *:MINGW64*:*) + echo "$UNAME_MACHINE"-pc-mingw64 + exit ;; + *:MINGW*:*) + echo "$UNAME_MACHINE"-pc-mingw32 + exit ;; + *:MSYS*:*) + echo "$UNAME_MACHINE"-pc-msys + exit ;; + i*:PW*:*) + echo "$UNAME_MACHINE"-pc-pw32 + exit ;; + *:Interix*:*) + case "$UNAME_MACHINE" in + x86) + echo i586-pc-interix"$UNAME_RELEASE" + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix"$UNAME_RELEASE" + exit ;; + IA64) + echo ia64-unknown-interix"$UNAME_RELEASE" + exit ;; + esac ;; + i*:UWIN*:*) + echo "$UNAME_MACHINE"-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + *:GNU:*:*) + # the GNU system + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" + exit ;; + i*86:Minix:*:*) + echo "$UNAME_MACHINE"-pc-minix + exit ;; + aarch64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arm*:Linux:*:*) + eval "$set_cc_for_build" + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi + else + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + cris:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + crisv32:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + frv:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + hexagon:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:Linux:*:*) + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + exit ;; + ia64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m32r*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m68*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" + test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } + ;; + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-"$LIBC" + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-"$LIBC" + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-"$LIBC" + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-"$LIBC" + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-"$LIBC" + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-"$LIBC" + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" + exit ;; + sh64*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sh*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + tile*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + vax:Linux:*:*) + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" + exit ;; + x86_64:Linux:*:*) + if objdump -f /bin/sh | grep -q elf32-x86-64; then + echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 + else + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + fi + exit ;; + xtensa*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo "$UNAME_MACHINE"-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo "$UNAME_MACHINE"-unknown-stop + exit ;; + i*86:atheos:*:*) + echo "$UNAME_MACHINE"-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo "$UNAME_MACHINE"-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos"$UNAME_RELEASE" + exit ;; + i*86:*DOS:*:*) + echo "$UNAME_MACHINE"-pc-msdosdjgpp + exit ;; + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos"$UNAME_RELEASE" + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos"$UNAME_RELEASE" + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos"$UNAME_RELEASE" + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos"$UNAME_RELEASE" + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv"$UNAME_RELEASE" + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo "$UNAME_MACHINE"-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo "$UNAME_MACHINE"-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux"$UNAME_RELEASE" + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv"$UNAME_RELEASE" + else + echo mips-unknown-sysv"$UNAME_RELEASE" + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux"$UNAME_RELEASE" + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux"$UNAME_RELEASE" + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux"$UNAME_RELEASE" + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux"$UNAME_RELEASE" + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody"$UNAME_RELEASE" + exit ;; + *:Rhapsody:*:*) + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval "$set_cc_for_build" + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = x86; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = 386; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo "$UNAME_MACHINE"-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux"$UNAME_RELEASE" + exit ;; + *:DragonFly:*:*) + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "$UNAME_MACHINE" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" + exit ;; + i*86:rdos:*:*) + echo "$UNAME_MACHINE"-pc-rdos + exit ;; + i*86:AROS:*:*) + echo "$UNAME_MACHINE"-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo "$UNAME_MACHINE"-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; +esac + +echo "$0: unable to guess system type" >&2 + +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 </dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-functions 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/config.sub b/build-aux/config.sub new file mode 100755 index 00000000..1d8e98bc --- /dev/null +++ b/build-aux/config.sub @@ -0,0 +1,1801 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2018 Free Software Foundation, Inc. + +timestamp='2018-02-22' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS + +Canonicalize a configuration name. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2018 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo "$1" + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo "$1" | sed 's/-[^-]*$//'` + if [ "$basic_machine" != "$1" ] + then os=`echo "$1" | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | wasm32 \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ + | pyramid-* \ + | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | wasm32-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-pc + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + asmjs) + basic_machine=asmjs-unknown + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2*) + basic_machine=m68k-bull + os=-sysv3 + ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=$os"spe" + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + x64) + basic_machine=x86_64-pc + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases that might get confused + # with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # es1800 is here to avoid being matched by es* (a different OS) + -es1800*) + os=-ose + ;; + # Now accept the basic system types. + # The portable systems comes first. + # Each alternative MUST end in a * to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ + | -midnightbsd*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -xray | -os68k* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo "$os" | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4*) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; + -nacl*) + ;; + -ios) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + pru-*) + os=-elf + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` + ;; +esac + +echo "$basic_machine$os" +exit + +# Local variables: +# eval: (add-hook 'write-file-functions 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/install-sh b/build-aux/install-sh new file mode 100755 index 00000000..59990a10 --- /dev/null +++ b/build-aux/install-sh @@ -0,0 +1,508 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2014-09-12.12; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + # $RANDOM is not portable (e.g. dash); use it when possible to + # lower collision chance + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 + + # As "mkdir -p" follows symlinks and we work in /tmp possibly; so + # create the $tmpdir first (and fail if unsuccessful) to make sure + # that nobody tries to guess the $tmpdir name. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/libtool.m4 b/build-aux/libtool.m4 new file mode 100644 index 00000000..ab2fd56b --- /dev/null +++ b/build-aux/libtool.m4 @@ -0,0 +1,8387 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), in case it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directories which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + _LT_TAGVAR(link_all_deplibs, $1)=no + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/build-aux/ltmain.sh b/build-aux/ltmain.sh new file mode 100644 index 00000000..22589375 --- /dev/null +++ b/build-aux/ltmain.sh @@ -0,0 +1,11346 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION="2.4.6 Debian-2.4.6-2.1" +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-10-12.13; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # usable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_arg pretty "$2" + eval "$1+=\\ \$func_quote_arg_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_arg pretty "$2" + eval "$1=\$$1\\ \$func_quote_arg_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value returned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list in case some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_portable EVAL ARG +# ---------------------------- +# Internal function to portably implement func_quote_arg. Note that we still +# keep attention to performance here so we as much as possible try to avoid +# calling sed binary (so far O(N) complexity as long as func_append is O(1)). +func_quote_portable () +{ + $debug_cmd + + func_quote_portable_result=$2 + + # one-time-loop (easy break) + while true + do + if $1; then + func_quote_portable_result=`$ECHO "$2" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` + break + fi + + # Quote for eval. + case $func_quote_portable_result in + *[\\\`\"\$]*) + case $func_quote_portable_result in + *[\[\*\?]*) + func_quote_portable_result=`$ECHO "$func_quote_portable_result" | $SED "$sed_quote_subst"` + break + ;; + esac + + func_quote_portable_old_IFS=$IFS + for _G_char in '\' '`' '"' '$' + do + # STATE($1) PREV($2) SEPARATOR($3) + set start "" "" + func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy + IFS=$_G_char + for _G_part in $func_quote_portable_result + do + case $1 in + quote) + func_append func_quote_portable_result "$3$2" + set quote "$_G_part" "\\$_G_char" + ;; + start) + set first "" "" + func_quote_portable_result= + ;; + first) + set quote "$_G_part" "" + ;; + esac + done + done + IFS=$func_quote_portable_old_IFS + ;; + *) ;; + esac + break + done + + func_quote_portable_unquoted_result=$func_quote_portable_result + case $func_quote_portable_result in + # double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # many bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_portable_result=\"$func_quote_portable_result\" + ;; + esac +} + + +# func_quotefast_eval ARG +# ----------------------- +# Quote one ARG (internal). This is equivalent to 'func_quote_arg eval ARG', +# but optimized for speed. Result is stored in $func_quotefast_eval. +if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then + func_quotefast_eval () + { + printf -v func_quotefast_eval_result %q "$1" + } +else + func_quotefast_eval () + { + func_quote_portable false "$1" + func_quotefast_eval_result=$func_quote_portable_result + } +fi + + +# func_quote_arg MODEs ARG +# ------------------------ +# Quote one ARG to be evaled later. MODEs argument may contain zero ore more +# specifiers listed below separated by ',' character. This function returns two +# values: +# i) func_quote_arg_result +# double-quoted (when needed), suitable for a subsequent eval +# ii) func_quote_arg_unquoted_result +# has all characters that are still active within double +# quotes backslashified. Available only if 'unquoted' is specified. +# +# Available modes: +# ---------------- +# 'eval' (default) +# - escape shell special characters +# 'expand' +# - the same as 'eval'; but do not quote variable references +# 'pretty' +# - request aesthetic output, i.e. '"a b"' instead of 'a\ b'. This might +# later used in func_quote to get output like: 'echo "a b"' instead of +# 'echo a\ b'. This is slower than default on some shells. +# 'unquoted' +# - produce also $func_quote_arg_unquoted_result which does not contain +# wrapping double-quotes. +# +# Examples for 'func_quote_arg pretty,unquoted string': +# +# string | *_result | *_unquoted_result +# ------------+-----------------------+------------------- +# " | \" | \" +# a b | "a b" | a b +# "a b" | "\"a b\"" | \"a b\" +# * | "*" | * +# z="${x-$y}" | "z=\"\${x-\$y}\"" | z=\"\${x-\$y}\" +# +# Examples for 'func_quote_arg pretty,unquoted,expand string': +# +# string | *_result | *_unquoted_result +# --------------+---------------------+-------------------- +# z="${x-$y}" | "z=\"${x-$y}\"" | z=\"${x-$y}\" +func_quote_arg () +{ + _G_quote_expand=false + case ,$1, in + *,expand,*) + _G_quote_expand=: + ;; + esac + + case ,$1, in + *,pretty,*|*,expand,*|*,unquoted,*) + func_quote_portable $_G_quote_expand "$2" + func_quote_arg_result=$func_quote_portable_result + func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result + ;; + *) + # Faster quote-for-eval for some shells. + func_quotefast_eval "$2" + func_quote_arg_result=$func_quotefast_eval_result + ;; + esac +} + + +# func_quote MODEs ARGs... +# ------------------------ +# Quote all ARGs to be evaled later and join them into single command. See +# func_quote_arg's description for more info. +func_quote () +{ + $debug_cmd + _G_func_quote_mode=$1 ; shift + func_quote_result= + while test 0 -lt $#; do + func_quote_arg "$_G_func_quote_mode" "$1" + if test -n "$func_quote_result"; then + func_append func_quote_result " $func_quote_arg_result" + else + func_append func_quote_result "$func_quote_arg_result" + fi + shift + done +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_arg pretty,expand "$_G_cmd" + eval "func_notquiet $func_quote_arg_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_arg expand,pretty "$_G_cmd" + eval "func_echo $func_quote_arg_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2015-10-12.13; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + _G_rc_run_hooks=false + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook functions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + if eval $_G_hook '"$@"'; then + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + _G_rc_run_hooks=: + fi + done + + $_G_rc_run_hooks && func_run_hooks_result=$_G_hook_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, you may remove/edit +# any options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. In this case you also must return $EXIT_SUCCESS to let the +# hook's caller know that it should pay attention to +# '_result'. Returning $EXIT_FAILURE signalizes that +# arguments are left untouched by the hook and therefore caller will ignore the +# result variable. +# +# Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# # No change in '$@' (ignored completely by this hook). There is +# # no need to do the equivalent (but slower) action: +# # func_quote eval ${1+"$@"} +# # my_options_prep_result=$func_quote_result +# false +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# args_changed=false +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: +# args_changed=: +# ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# args_changed=: +# ;; +# *) # Make sure the first unrecognised option "$_G_opt" +# # is added back to "$@", we could need that later +# # if $args_changed is true. +# set dummy "$_G_opt" ${1+"$@"}; shift; break ;; +# esac +# done +# +# if $args_changed; then +# func_quote eval ${1+"$@"} +# my_silent_option_result=$func_quote_result +# fi +# +# $args_changed +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# false +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll also need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options_finish [ARG]... +# ---------------------------- +# Finishing the option parse loop (call 'func_options' hooks ATM). +func_options_finish () +{ + $debug_cmd + + _G_func_options_finish_exit=false + if func_run_hooks func_options ${1+"$@"}; then + func_options_finish_result=$func_run_hooks_result + _G_func_options_finish_exit=: + fi + + $_G_func_options_finish_exit +} + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + _G_rc_options=false + + for my_func in options_prep parse_options validate_options options_finish + do + if eval func_$my_func '${1+"$@"}'; then + eval _G_res_var='$'"func_${my_func}_result" + eval set dummy "$_G_res_var" ; shift + _G_rc_options=: + fi + done + + # Save modified positional parameters for caller. As a top-level + # options-parser function we always need to set the 'func_options_result' + # variable (regardless the $_G_rc_options value). + if $_G_rc_options; then + func_options_result=$_G_res_var + else + func_quote eval ${1+"$@"} + func_options_result=$func_quote_result + fi + + $_G_rc_options +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propagate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning $EXIT_SUCCESS (otherwise $EXIT_FAILURE is returned). +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + _G_rc_options_prep=false + if func_run_hooks func_options_prep ${1+"$@"}; then + _G_rc_options_prep=: + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result + fi + + $_G_rc_options_prep +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + _G_rc_parse_options=false + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + if func_run_hooks func_parse_options ${1+"$@"}; then + eval set dummy "$func_run_hooks_result"; shift + _G_rc_parse_options=: + fi + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_match_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + if test $# = 0 && func_missing_arg $_G_opt; then + _G_rc_parse_options=: + break + fi + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) _G_rc_parse_options=: ; break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift + _G_match_parse_options=false + break + ;; + esac + + $_G_match_parse_options && _G_rc_parse_options=: + done + + + if $_G_rc_parse_options; then + # save modified positional parameters for caller + func_quote eval ${1+"$@"} + func_parse_options_result=$func_quote_result + fi + + $_G_rc_parse_options +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + _G_rc_validate_options=false + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + if func_run_hooks func_validate_options ${1+"$@"}; then + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result + _G_rc_validate_options=: + fi + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + $_G_rc_validate_options +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname $scriptversion Debian-2.4.6-2.1 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + _G_rc_lt_options_prep=: + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + *) + _G_rc_lt_options_prep=false + ;; + esac + + if $_G_rc_lt_options_prep; then + # Pass back the list of options. + func_quote eval ${1+"$@"} + libtool_options_prep_result=$func_quote_result + fi + + $_G_rc_lt_options_prep +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + _G_rc_lt_parse_options=false + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_match_lt_parse_options=: + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"} ; shift + _G_match_lt_parse_options=false + break + ;; + esac + $_G_match_lt_parse_options && _G_rc_lt_parse_options=: + done + + if $_G_rc_lt_parse_options; then + # save modified positional parameters for caller + func_quote eval ${1+"$@"} + libtool_parse_options_result=$func_quote_result + fi + + $_G_rc_lt_parse_options +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote eval ${1+"$@"} + libtool_validate_options_result=$func_quote_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_arg pretty "$libobj" + test "X$libobj" != "X$func_quote_arg_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_arg pretty "$srcfile" + qsrcfile=$func_quote_arg_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_arg pretty "$nonopt" + install_prog="$func_quote_arg_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_arg pretty "$arg" + func_append install_prog "$func_quote_arg_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_arg pretty "$arg" + func_append install_prog " $func_quote_arg_result" + if test -n "$arg2"; then + func_quote_arg pretty "$arg2" + fi + func_append install_shared_prog " $func_quote_arg_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_arg pretty "$install_override_mode" + func_append install_shared_prog " -m $func_quote_arg_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_arg expand,pretty "$relink_command" + eval "func_echo $func_quote_arg_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + func_quote_arg pretty "$ECHO" + qECHO=$func_quote_arg_result + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=$qECHO + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_arg pretty,unquoted "$arg" + qarg=$func_quote_arg_unquoted_result + func_append libtool_args " $func_quote_arg_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_arg pretty "$flag" + func_append arg " $func_quote_arg_result" + func_append compiler_flags " $func_quote_arg_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_arg pretty "$flag" + func_append arg " $wl$func_quote_arg_result" + func_append compiler_flags " $wl$func_quote_arg_result" + func_append linker_flags " $func_quote_arg_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -specs=* GCC specs files + # -stdlib=* select c++ std lib with clang + # -fsanitize=* Clang/GCC memory and address sanitizer + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ + -specs=*|-fsanitize=*) + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_arg pretty "$arg" + arg=$func_quote_arg_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + *) + func_fatal_configuration "$modename: unknown library version type '$version_type'" + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_arg expand,pretty "$cmd" + eval "func_echo $func_quote_arg_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_arg expand,pretty "$cmd" + eval "func_echo $func_quote_arg_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_arg pretty "$var_value" + relink_command="$var=$func_quote_arg_result; export $var; $relink_command" + fi + done + func_quote_arg pretty,unquoted "(cd `pwd`; $relink_command)" + relink_command=$func_quote_arg_unquoted_result + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_arg pretty,unquoted "$var_value" + relink_command="$var=$func_quote_arg_unquoted_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + func_quote_arg pretty,unquoted "$relink_command" + relink_command=$func_quote_arg_unquoted_result + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/build-aux/ltoptions.m4 b/build-aux/ltoptions.m4 new file mode 100644 index 00000000..94b08297 --- /dev/null +++ b/build-aux/ltoptions.m4 @@ -0,0 +1,437 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/build-aux/ltsugar.m4 b/build-aux/ltsugar.m4 new file mode 100644 index 00000000..48bc9344 --- /dev/null +++ b/build-aux/ltsugar.m4 @@ -0,0 +1,124 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/build-aux/ltversion.m4 b/build-aux/ltversion.m4 new file mode 100644 index 00000000..fa04b52a --- /dev/null +++ b/build-aux/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/build-aux/lt~obsolete.m4 b/build-aux/lt~obsolete.m4 new file mode 100644 index 00000000..c6b26f88 --- /dev/null +++ b/build-aux/lt~obsolete.m4 @@ -0,0 +1,99 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/build-aux/missing b/build-aux/missing new file mode 100755 index 00000000..f62bbae3 --- /dev/null +++ b/build-aux/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2013-10-28.13; # UTC + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/bytecomp/bytegen.ml b/bytecomp/bytegen.ml index afb6530e..c7343bfc 100644 --- a/bytecomp/bytegen.ml +++ b/bytecomp/bytegen.ml @@ -154,7 +154,7 @@ let rec size_of_lambda env = function | Record_regular | Record_inlined _ -> RHS_block size | Record_unboxed _ -> assert false | Record_float -> RHS_floatblock size - | Record_extension -> RHS_block (size + 1) + | Record_extension _ -> RHS_block (size + 1) end | Llet(_str, _k, id, arg, body) -> size_of_lambda (Ident.add id (size_of_lambda env arg) env) body @@ -177,7 +177,7 @@ let rec size_of_lambda env = function RHS_block size | Lprim (Pduprecord (Record_unboxed _, _), _, _) -> assert false - | Lprim (Pduprecord (Record_extension, size), _, _) -> + | Lprim (Pduprecord (Record_extension _, size), _, _) -> RHS_block (size + 1) | Lprim (Pduprecord (Record_float, size), _, _) -> RHS_floatblock size | Levent (lam, _) -> size_of_lambda env lam @@ -272,7 +272,7 @@ let find_raise_label i = with | Not_found -> Misc.fatal_error - ("exit("^string_of_int i^") outside appropriated catch") + ("exit("^Int.to_string i^") outside appropriated catch") (* Will the translation of l lead to a jump to label ? *) let code_as_jump l sz = match l with @@ -424,9 +424,9 @@ let comp_primitive p args = | Pbintcomp(_, Cgt) -> Kccall("caml_greaterthan", 2) | Pbintcomp(_, Cle) -> Kccall("caml_lessequal", 2) | Pbintcomp(_, Cge) -> Kccall("caml_greaterequal", 2) - | Pbigarrayref(_, n, _, _) -> Kccall("caml_ba_get_" ^ string_of_int n, n + 1) - | Pbigarrayset(_, n, _, _) -> Kccall("caml_ba_set_" ^ string_of_int n, n + 2) - | Pbigarraydim(n) -> Kccall("caml_ba_dim_" ^ string_of_int n, 1) + | Pbigarrayref(_, n, _, _) -> Kccall("caml_ba_get_" ^ Int.to_string n, n + 1) + | Pbigarrayset(_, n, _, _) -> Kccall("caml_ba_set_" ^ Int.to_string n, n + 2) + | Pbigarraydim(n) -> Kccall("caml_ba_dim_" ^ Int.to_string n, 1) | Pbigstring_load_16(_) -> Kccall("caml_ba_uint8_get16", 2) | Pbigstring_load_32(_) -> Kccall("caml_ba_uint8_get32", 2) | Pbigstring_load_64(_) -> Kccall("caml_ba_uint8_get64", 2) @@ -445,7 +445,7 @@ let is_immed n = immed_min <= n && n <= immed_max module Storer = Switch.Store (struct type t = lambda type key = lambda - let compare_key = Pervasives.compare + let compare_key = Stdlib.compare let make_key = Lambda.make_key end) (* Compile an expression. @@ -520,7 +520,7 @@ let rec comp_expr env exp sz cont = let lbl = new_label() in let fv = Ident.Set.elements(free_variables exp) in let to_compile = - { params = params; body = body; label = lbl; + { params = List.map fst params; body = body; label = lbl; free_vars = fv; num_defs = 1; rec_vars = []; rec_pos = 0 } in Stack.push to_compile functions_to_compile; comp_args env (List.map (fun n -> Lvar n) fv) sz @@ -542,8 +542,9 @@ let rec comp_expr env exp sz cont = | (_id, Lfunction{params; body}) :: rem -> let lbl = new_label() in let to_compile = - { params = params; body = body; label = lbl; free_vars = fv; - num_defs = ndecl; rec_vars = rec_idents; rec_pos = pos} in + { params = List.map fst params; body = body; label = lbl; + free_vars = fv; num_defs = ndecl; rec_vars = rec_idents; + rec_pos = pos} in Stack.push to_compile functions_to_compile; lbl :: comp_fun (pos + 1) rem | _ -> assert false in @@ -554,7 +555,8 @@ let rec comp_expr env exp sz cont = (add_pop ndecl cont))) end else begin let decl_size = - List.map (fun (id, exp) -> (id, exp, size_of_lambda Ident.empty exp)) decl in + List.map (fun (id, exp) -> (id, exp, size_of_lambda Ident.empty exp)) + decl in let rec comp_init new_env sz = function | [] -> comp_nonrec new_env sz ndecl decl_size | (id, _exp, RHS_floatblock blocksize) :: rem -> @@ -703,6 +705,7 @@ let rec comp_expr env exp sz cont = | Lprim(p, args, _) -> comp_args env args sz (comp_primitive p args :: cont) | Lstaticcatch (body, (i, vars) , handler) -> + let vars = List.map fst vars in let nvars = List.length vars in let branch1, cont1 = make_branch cont in let r = @@ -842,7 +845,7 @@ let rec comp_expr env exp sz cont = ev_loc = lev.lev_loc; ev_kind = kind; ev_info = info; - ev_typenv = lev.lev_env; + ev_typenv = Env.summary lev.lev_env; ev_typsubst = Subst.identity; ev_compenv = env; ev_stacksize = sz; diff --git a/bytecomp/bytegen.mli b/bytecomp/bytegen.mli index 24855ec6..80c222bf 100644 --- a/bytecomp/bytegen.mli +++ b/bytecomp/bytegen.mli @@ -22,4 +22,5 @@ val compile_implementation: string -> lambda -> instruction list val compile_phrase: lambda -> instruction list * instruction list val reset: unit -> unit -val merge_events : Instruct.debug_event -> Instruct.debug_event -> Instruct.debug_event +val merge_events: + Instruct.debug_event -> Instruct.debug_event -> Instruct.debug_event diff --git a/bytecomp/bytelibrarian.ml b/bytecomp/bytelibrarian.ml index a905801f..294a6976 100644 --- a/bytecomp/bytelibrarian.ml +++ b/bytecomp/bytelibrarian.ml @@ -55,10 +55,10 @@ let add_ccobjs l = lib_dllibs := !lib_dllibs @ l.lib_dllibs end -let copy_object_file ppf oc name = +let copy_object_file oc name = let file_name = try - find_in_path !load_path name + Load_path.find name with Not_found -> raise(Error(File_not_found name)) in let ic = open_in_bin file_name in @@ -68,7 +68,7 @@ let copy_object_file ppf oc name = let compunit_pos = input_binary_int ic in seek_in ic compunit_pos; let compunit = (input_value ic : compilation_unit) in - Bytelink.check_consistency ppf file_name compunit; + Bytelink.check_consistency file_name compunit; copy_compunit ic oc compunit; close_in ic; [compunit] @@ -77,7 +77,7 @@ let copy_object_file ppf oc name = let toc_pos = input_binary_int ic in seek_in ic toc_pos; let toc = (input_value ic : library) in - List.iter (Bytelink.check_consistency ppf file_name) toc.lib_units; + List.iter (Bytelink.check_consistency file_name) toc.lib_units; add_ccobjs toc; List.iter (copy_compunit ic oc) toc.lib_units; close_in ic; @@ -88,31 +88,30 @@ let copy_object_file ppf oc name = End_of_file -> close_in ic; raise(Error(Not_an_object_file file_name)) | x -> close_in ic; raise x -let create_archive ppf file_list lib_name = +let create_archive file_list lib_name = let outchan = open_out_bin lib_name in - try - output_string outchan cma_magic_number; - let ofs_pos_toc = pos_out outchan in - output_binary_int outchan 0; - let units = - List.flatten(List.map (copy_object_file ppf outchan) file_list) in - let toc = - { lib_units = units; - lib_custom = !Clflags.custom_runtime; - lib_ccobjs = !Clflags.ccobjs @ !lib_ccobjs; - lib_ccopts = !Clflags.all_ccopts @ !lib_ccopts; - lib_dllibs = !Clflags.dllibs @ !lib_dllibs } in - let pos_toc = pos_out outchan in - Emitcode.marshal_to_channel_with_possibly_32bit_compat - ~filename:lib_name ~kind:"bytecode library" - outchan toc; - seek_out outchan ofs_pos_toc; - output_binary_int outchan pos_toc; - close_out outchan - with x -> - close_out outchan; - remove_file lib_name; - raise x + Misc.try_finally + ~always:(fun () -> close_out outchan) + ~exceptionally:(fun () -> remove_file lib_name) + (fun () -> + output_string outchan cma_magic_number; + let ofs_pos_toc = pos_out outchan in + output_binary_int outchan 0; + let units = + List.flatten(List.map (copy_object_file outchan) file_list) in + let toc = + { lib_units = units; + lib_custom = !Clflags.custom_runtime; + lib_ccobjs = !Clflags.ccobjs @ !lib_ccobjs; + lib_ccopts = !Clflags.all_ccopts @ !lib_ccopts; + lib_dllibs = !Clflags.dllibs @ !lib_dllibs } in + let pos_toc = pos_out outchan in + Emitcode.marshal_to_channel_with_possibly_32bit_compat + ~filename:lib_name ~kind:"bytecode library" + outchan toc; + seek_out outchan ofs_pos_toc; + output_binary_int outchan pos_toc; + ) open Format diff --git a/bytecomp/bytelibrarian.mli b/bytecomp/bytelibrarian.mli index 04a0316a..3670730d 100644 --- a/bytecomp/bytelibrarian.mli +++ b/bytecomp/bytelibrarian.mli @@ -22,7 +22,7 @@ content table = list of compilation units *) -val create_archive: Format.formatter -> string list -> string -> unit +val create_archive: string list -> string -> unit type error = File_not_found of string diff --git a/bytecomp/bytelink.ml b/bytecomp/bytelink.ml index 87e0d62b..0b964e69 100644 --- a/bytecomp/bytelink.ml +++ b/bytecomp/bytelink.ml @@ -94,17 +94,11 @@ let is_required (rel, _pos) = | _ -> false let add_required compunit = - let add_required_by_reloc (rel, _pos) = - match rel with - Reloc_getglobal id -> - missing_globals := Ident.Set.add id !missing_globals - | _ -> () - in - let add_required_for_effects id = + let add id = missing_globals := Ident.Set.add id !missing_globals in - List.iter add_required_by_reloc compunit.cu_reloc; - List.iter add_required_for_effects compunit.cu_required_globals + List.iter add (Symtable.required_globals compunit.cu_reloc); + List.iter add compunit.cu_required_globals let remove_required (rel, _pos) = match rel with @@ -115,7 +109,7 @@ let remove_required (rel, _pos) = let scan_file obj_name tolink = let file_name = try - find_in_path !load_path obj_name + Load_path.find obj_name with Not_found -> raise(Error(File_not_found obj_name)) in let ic = open_in_bin file_name in @@ -169,7 +163,7 @@ let crc_interfaces = Consistbl.create () let interfaces = ref ([] : string list) let implementations_defined = ref ([] : (string * string) list) -let check_consistency ppf file_name cu = +let check_consistency file_name cu = begin try List.iter (fun (name, crco) -> @@ -186,7 +180,7 @@ let check_consistency ppf file_name cu = end; begin try let source = List.assoc cu.cu_name !implementations_defined in - Location.print_warning (Location.in_file file_name) ppf + Location.prerr_warning (Location.in_file file_name) (Warnings.Multiple_definition(cu.cu_name, Location.show_filename file_name, Location.show_filename source)) @@ -208,11 +202,11 @@ let debug_info = ref ([] : (int * Instruct.debug_event list * string list) list) (* Link in a compilation unit *) -let link_compunit ppf output_fun currpos_fun inchan file_name compunit = - check_consistency ppf file_name compunit; +let link_compunit output_fun currpos_fun inchan file_name compunit = + check_consistency file_name compunit; seek_in inchan compunit.cu_pos; let code_block = LongString.input_bytes inchan compunit.cu_codesize in - Symtable.ls_patch_object code_block compunit.cu_reloc; + Symtable.patch_object code_block compunit.cu_reloc; if !Clflags.debug && compunit.cu_debug > 0 then begin seek_in inchan compunit.cu_debug; let debug_event_list : Instruct.debug_event list = input_value inchan in @@ -230,10 +224,10 @@ let link_compunit ppf output_fun currpos_fun inchan file_name compunit = (* Link in a .cmo file *) -let link_object ppf output_fun currpos_fun file_name compunit = +let link_object output_fun currpos_fun file_name compunit = let inchan = open_in_bin file_name in try - link_compunit ppf output_fun currpos_fun inchan file_name compunit; + link_compunit output_fun currpos_fun inchan file_name compunit; close_in inchan with Symtable.Error msg -> @@ -243,14 +237,14 @@ let link_object ppf output_fun currpos_fun file_name compunit = (* Link in a .cma file *) -let link_archive ppf output_fun currpos_fun file_name units_required = +let link_archive output_fun currpos_fun file_name units_required = let inchan = open_in_bin file_name in try List.iter (fun cu -> let name = file_name ^ "(" ^ cu.cu_name ^ ")" in try - link_compunit ppf output_fun currpos_fun inchan name cu + link_compunit output_fun currpos_fun inchan name cu with Symtable.Error msg -> raise(Error(Symbol_error(name, msg)))) units_required; @@ -259,11 +253,11 @@ let link_archive ppf output_fun currpos_fun file_name units_required = (* Link in a .cmo or .cma file *) -let link_file ppf output_fun currpos_fun = function +let link_file output_fun currpos_fun = function Link_object(file_name, unit) -> - link_object ppf output_fun currpos_fun file_name unit + link_object output_fun currpos_fun file_name unit | Link_archive(file_name, units) -> - link_archive ppf output_fun currpos_fun file_name units + link_archive output_fun currpos_fun file_name units (* Output the debugging information *) (* Format is: @@ -298,7 +292,8 @@ let make_absolute file = (* Create a bytecode executable file *) -let link_bytecode ppf tolink exec_name standalone = +let link_bytecode ?final_name tolink exec_name standalone = + let final_name = Option.value final_name ~default:exec_name in (* Avoid the case where the specified exec output file is the same as one of the objects to be linked *) List.iter (function @@ -309,81 +304,81 @@ let link_bytecode ppf tolink exec_name standalone = let outchan = open_out_gen [Open_wronly; Open_trunc; Open_creat; Open_binary] 0o777 exec_name in - try - if standalone then begin - (* Copy the header *) - try - let header = - if String.length !Clflags.use_runtime > 0 - then "camlheader_ur" else "camlheader" ^ !Clflags.runtime_variant in - let inchan = open_in_bin (find_in_path !load_path header) in - copy_file inchan outchan; - close_in inchan - with Not_found | Sys_error _ -> () - end; - Bytesections.init_record outchan; - (* The path to the bytecode interpreter (in use_runtime mode) *) - if String.length !Clflags.use_runtime > 0 then begin - output_string outchan (make_absolute !Clflags.use_runtime); - output_char outchan '\n'; - Bytesections.record outchan "RNTM" - end; - (* The bytecode *) - let start_code = pos_out outchan in - Symtable.init(); - clear_crc_interfaces (); - let sharedobjs = List.map Dll.extract_dll_name !Clflags.dllibs in - let check_dlls = standalone && Config.target = Config.host in - if check_dlls then begin - (* Initialize the DLL machinery *) - Dll.init_compile !Clflags.no_std_include; - Dll.add_path !load_path; - try Dll.open_dlls Dll.For_checking sharedobjs - with Failure reason -> raise(Error(Cannot_open_dll reason)) - end; - let output_fun = output_bytes outchan - and currpos_fun () = pos_out outchan - start_code in - List.iter (link_file ppf output_fun currpos_fun) tolink; - if check_dlls then Dll.close_all_dlls(); - (* The final STOP instruction *) - output_byte outchan Opcodes.opSTOP; - output_byte outchan 0; output_byte outchan 0; output_byte outchan 0; - Bytesections.record outchan "CODE"; - (* DLL stuff *) - if standalone then begin - (* The extra search path for DLLs *) - output_stringlist outchan !Clflags.dllpaths; - Bytesections.record outchan "DLPT"; - (* The names of the DLLs *) - output_stringlist outchan sharedobjs; - Bytesections.record outchan "DLLS" - end; - (* The names of all primitives *) - Symtable.output_primitive_names outchan; - Bytesections.record outchan "PRIM"; - (* The table of global data *) - Emitcode.marshal_to_channel_with_possibly_32bit_compat - ~filename:exec_name ~kind:"bytecode executable" - outchan (Symtable.initial_global_table()); - Bytesections.record outchan "DATA"; - (* The map of global identifiers *) - Symtable.output_global_map outchan; - Bytesections.record outchan "SYMB"; - (* CRCs for modules *) - output_value outchan (extract_crc_interfaces()); - Bytesections.record outchan "CRCS"; - (* Debug info *) - if !Clflags.debug then begin - output_debug_info outchan; - Bytesections.record outchan "DBUG" - end; - (* The table of contents and the trailer *) - Bytesections.write_toc_and_trailer outchan; - close_out outchan - with x -> - close_out outchan; - remove_file exec_name; - raise x + Misc.try_finally + ~always:(fun () -> close_out outchan) + ~exceptionally:(fun () -> remove_file exec_name) + (fun () -> + if standalone then begin + (* Copy the header *) + try + let header = + if String.length !Clflags.use_runtime > 0 + then "camlheader_ur" else "camlheader" ^ !Clflags.runtime_variant + in + let inchan = open_in_bin (Load_path.find header) in + copy_file inchan outchan; + close_in inchan + with Not_found | Sys_error _ -> () + end; + Bytesections.init_record outchan; + (* The path to the bytecode interpreter (in use_runtime mode) *) + if String.length !Clflags.use_runtime > 0 then begin + output_string outchan (make_absolute !Clflags.use_runtime); + output_char outchan '\n'; + Bytesections.record outchan "RNTM" + end; + (* The bytecode *) + let start_code = pos_out outchan in + Symtable.init(); + clear_crc_interfaces (); + let sharedobjs = List.map Dll.extract_dll_name !Clflags.dllibs in + let check_dlls = standalone && Config.target = Config.host in + if check_dlls then begin + (* Initialize the DLL machinery *) + Dll.init_compile !Clflags.no_std_include; + Dll.add_path (Load_path.get_paths ()); + try Dll.open_dlls Dll.For_checking sharedobjs + with Failure reason -> raise(Error(Cannot_open_dll reason)) + end; + let output_fun = output_bytes outchan + and currpos_fun () = pos_out outchan - start_code in + List.iter (link_file output_fun currpos_fun) tolink; + if check_dlls then Dll.close_all_dlls(); + (* The final STOP instruction *) + output_byte outchan Opcodes.opSTOP; + output_byte outchan 0; output_byte outchan 0; output_byte outchan 0; + Bytesections.record outchan "CODE"; + (* DLL stuff *) + if standalone then begin + (* The extra search path for DLLs *) + output_stringlist outchan !Clflags.dllpaths; + Bytesections.record outchan "DLPT"; + (* The names of the DLLs *) + output_stringlist outchan sharedobjs; + Bytesections.record outchan "DLLS" + end; + (* The names of all primitives *) + Symtable.output_primitive_names outchan; + Bytesections.record outchan "PRIM"; + (* The table of global data *) + Emitcode.marshal_to_channel_with_possibly_32bit_compat + ~filename:final_name ~kind:"bytecode executable" + outchan (Symtable.initial_global_table()); + Bytesections.record outchan "DATA"; + (* The map of global identifiers *) + Symtable.output_global_map outchan; + Bytesections.record outchan "SYMB"; + (* CRCs for modules *) + output_value outchan (extract_crc_interfaces()); + Bytesections.record outchan "CRCS"; + (* Debug info *) + if !Clflags.debug then begin + output_debug_info outchan; + Bytesections.record outchan "DBUG" + end; + (* The table of contents and the trailer *) + Bytesections.write_toc_and_trailer outchan; + ) (* Output a string as a C array of unsigned ints *) @@ -426,29 +421,31 @@ let output_cds_file outfile = let outchan = open_out_gen [Open_wronly; Open_trunc; Open_creat; Open_binary] 0o777 outfile in - try - Bytesections.init_record outchan; - (* The map of global identifiers *) - Symtable.output_global_map outchan; - Bytesections.record outchan "SYMB"; - (* Debug info *) - output_debug_info outchan; - Bytesections.record outchan "DBUG"; - (* The table of contents and the trailer *) - Bytesections.write_toc_and_trailer outchan; - close_out outchan - with x -> - close_out outchan; - remove_file outfile; - raise x + Misc.try_finally + ~always:(fun () -> close_out outchan) + ~exceptionally:(fun () -> remove_file outfile) + (fun () -> + Bytesections.init_record outchan; + (* The map of global identifiers *) + Symtable.output_global_map outchan; + Bytesections.record outchan "SYMB"; + (* Debug info *) + output_debug_info outchan; + Bytesections.record outchan "DBUG"; + (* The table of contents and the trailer *) + Bytesections.write_toc_and_trailer outchan; + ) (* Output a bytecode executable as a C file *) -let link_bytecode_as_c ppf tolink outfile = +let link_bytecode_as_c tolink outfile = let outchan = open_out outfile in - begin try - (* The bytecode *) - output_string outchan "\ + Misc.try_finally + ~always:(fun () -> close_out outchan) + ~exceptionally:(fun () -> remove_file outfile) + (fun () -> + (* The bytecode *) + output_string outchan "\ #define CAML_INTERNALS\ \n\ \n#ifdef __cplusplus\ @@ -456,35 +453,35 @@ let link_bytecode_as_c ppf tolink outfile = \n#endif\ \n#include \ \n#include \n"; - output_string outchan "static int caml_code[] = {\n"; - Symtable.init(); - clear_crc_interfaces (); - let currpos = ref 0 in - let output_fun code = - output_code_string outchan code; - currpos := !currpos + Bytes.length code - and currpos_fun () = !currpos in - List.iter (link_file ppf output_fun currpos_fun) tolink; - (* The final STOP instruction *) - Printf.fprintf outchan "\n0x%x};\n\n" Opcodes.opSTOP; - (* The table of global data *) - output_string outchan "static char caml_data[] = {\n"; - output_data_string outchan - (Marshal.to_string (Symtable.initial_global_table()) []); - output_string outchan "\n};\n\n"; - (* The sections *) - let sections = - [ "SYMB", Symtable.data_global_map(); - "PRIM", Obj.repr(Symtable.data_primitive_names()); - "CRCS", Obj.repr(extract_crc_interfaces()) ] in - output_string outchan "static char caml_sections[] = {\n"; - output_data_string outchan - (Marshal.to_string sections []); - output_string outchan "\n};\n\n"; - (* The table of primitives *) - Symtable.output_primitive_table outchan; - (* The entry point *) - output_string outchan "\ + output_string outchan "static int caml_code[] = {\n"; + Symtable.init(); + clear_crc_interfaces (); + let currpos = ref 0 in + let output_fun code = + output_code_string outchan code; + currpos := !currpos + Bytes.length code + and currpos_fun () = !currpos in + List.iter (link_file output_fun currpos_fun) tolink; + (* The final STOP instruction *) + Printf.fprintf outchan "\n0x%x};\n\n" Opcodes.opSTOP; + (* The table of global data *) + output_string outchan "static char caml_data[] = {\n"; + output_data_string outchan + (Marshal.to_string (Symtable.initial_global_table()) []); + output_string outchan "\n};\n\n"; + (* The sections *) + let sections = + [ "SYMB", Symtable.data_global_map(); + "PRIM", Obj.repr(Symtable.data_primitive_names()); + "CRCS", Obj.repr(extract_crc_interfaces()) ] in + output_string outchan "static char caml_sections[] = {\n"; + output_data_string outchan + (Marshal.to_string sections []); + output_string outchan "\n};\n\n"; + (* The table of primitives *) + Symtable.output_primitive_table outchan; + (* The entry point *) + output_string outchan "\ \nvoid caml_startup(char_os ** argv)\ \n{\ \n caml_startup_code(caml_code, sizeof(caml_code),\ @@ -523,12 +520,7 @@ let link_bytecode_as_c ppf tolink outfile = \n#ifdef __cplusplus\ \n}\ \n#endif\n"; - close_out outchan - with x -> - close_out outchan; - remove_file outfile; - raise x - end; + ); if !Clflags.debug then output_cds_file ((Filename.chop_extension outfile) ^ ".cds") @@ -536,18 +528,21 @@ let link_bytecode_as_c ppf tolink outfile = let build_custom_runtime prim_name exec_name = let runtime_lib = "-lcamlrun" ^ !Clflags.runtime_variant in + let debug_prefix_map = + if Config.c_has_debug_prefix_map && not !Clflags.keep_camlprimc_file then + [Printf.sprintf "-fdebug-prefix-map=%s=camlprim.c" prim_name] + else + [] in Ccomp.call_linker Ccomp.Exe exec_name - ([prim_name] @ List.rev !Clflags.ccobjs @ [runtime_lib]) + (debug_prefix_map @ [prim_name] @ List.rev !Clflags.ccobjs @ [runtime_lib]) (Clflags.std_include_flag "-I" ^ " " ^ Config.bytecomp_c_libraries) -let append_bytecode_and_cleanup bytecode_name exec_name prim_name = +let append_bytecode bytecode_name exec_name = let oc = open_out_gen [Open_wronly; Open_append; Open_binary] 0 exec_name in let ic = open_in_bin bytecode_name in copy_file ic oc; close_in ic; - close_out oc; - remove_file bytecode_name; - remove_file prim_name + close_out oc (* Fix the name of the output file, if the C compiler changes it behind our back. *) @@ -560,14 +555,14 @@ let fix_exec_name name = (* Main entry point (build a custom runtime if needed) *) -let link ppf objfiles output_name = +let link objfiles output_name = let objfiles = if !Clflags.nopervasives then objfiles else if !Clflags.output_c_object then "stdlib.cma" :: objfiles else "stdlib.cma" :: (objfiles @ ["std_exit.cmo"]) in let tolink = List.fold_right scan_file objfiles [] in let missing_modules = - Ident.Set.filter (fun id -> not (Ident.is_predef_exn id)) !missing_globals + Ident.Set.filter (fun id -> not (Ident.is_predef id)) !missing_globals in begin match Ident.Set.elements missing_modules with @@ -579,52 +574,58 @@ let link ppf objfiles output_name = (* put user's opts first *) Clflags.dllibs := !lib_dllibs @ !Clflags.dllibs; (* put user's DLLs first *) if not !Clflags.custom_runtime then - link_bytecode ppf tolink output_name true + link_bytecode tolink output_name true else if not !Clflags.output_c_object then begin let bytecode_name = Filename.temp_file "camlcode" "" in - let prim_name = Filename.temp_file "camlprim" ".c" in - try - link_bytecode ppf tolink bytecode_name false; - let poc = open_out prim_name in - output_string poc "\ - #ifdef __cplusplus\n\ - extern \"C\" {\n\ - #endif\n\ - #ifdef _WIN64\n\ - #ifdef __MINGW32__\n\ - typedef long long value;\n\ - #else\n\ - typedef __int64 value;\n\ - #endif\n\ - #else\n\ - typedef long value;\n\ - #endif\n"; - Symtable.output_primitive_table poc; - output_string poc "\ - #ifdef __cplusplus\n\ - }\n\ - #endif\n"; - close_out poc; - let exec_name = fix_exec_name output_name in - if not (build_custom_runtime prim_name exec_name) - then raise(Error Custom_runtime); - if !Clflags.make_runtime - then (remove_file bytecode_name; remove_file prim_name) - else append_bytecode_and_cleanup bytecode_name exec_name prim_name - with x -> - remove_file bytecode_name; - remove_file prim_name; - raise x + let prim_name = + if !Clflags.keep_camlprimc_file then + output_name ^ ".camlprim.c" + else + Filename.temp_file "camlprim" ".c" in + Misc.try_finally + ~always:(fun () -> + remove_file bytecode_name; + if not !Clflags.keep_camlprimc_file then remove_file prim_name) + (fun () -> + link_bytecode ~final_name:output_name tolink bytecode_name false; + let poc = open_out prim_name in + (* note: builds will not be reproducible if the C code contains macros + such as __FILE__. *) + output_string poc "\ + #ifdef __cplusplus\n\ + extern \"C\" {\n\ + #endif\n\ + #ifdef _WIN64\n\ + #ifdef __MINGW32__\n\ + typedef long long value;\n\ + #else\n\ + typedef __int64 value;\n\ + #endif\n\ + #else\n\ + typedef long value;\n\ + #endif\n"; + Symtable.output_primitive_table poc; + output_string poc "\ + #ifdef __cplusplus\n\ + }\n\ + #endif\n"; + close_out poc; + let exec_name = fix_exec_name output_name in + if not (build_custom_runtime prim_name exec_name) + then raise(Error Custom_runtime); + if not !Clflags.make_runtime then + append_bytecode bytecode_name exec_name + ) end else begin let basename = Filename.chop_extension output_name in - let temps = ref [] in - let c_file = - if !Clflags.output_complete_object && not (Filename.check_suffix output_name ".c") - then Filename.temp_file "camlobj" ".c" + let c_file, stable_name = + if !Clflags.output_complete_object + && not (Filename.check_suffix output_name ".c") + then Filename.temp_file "camlobj" ".c", Some "camlobj.c" else begin let f = basename ^ ".c" in if Sys.file_exists f then raise(Error(File_exists f)); - f + f, None end in let obj_file = @@ -632,32 +633,32 @@ let link ppf objfiles output_name = then (Filename.chop_extension c_file) ^ Config.ext_obj else basename ^ Config.ext_obj in - try - link_bytecode_as_c ppf tolink c_file; - if not (Filename.check_suffix output_name ".c") then begin - temps := c_file :: !temps; - if Ccomp.compile_file ~output:obj_file c_file <> 0 then - raise(Error Custom_runtime); - if not (Filename.check_suffix output_name Config.ext_obj) || - !Clflags.output_complete_object then begin - temps := obj_file :: !temps; - let mode, c_libs = - if Filename.check_suffix output_name Config.ext_obj - then Ccomp.Partial, "" - else Ccomp.MainDll, Config.bytecomp_c_libraries - in - if not ( - let runtime_lib = "-lcamlrun" ^ !Clflags.runtime_variant in - Ccomp.call_linker mode output_name - ([obj_file] @ List.rev !Clflags.ccobjs @ [runtime_lib]) - c_libs - ) then raise (Error Custom_runtime); - end - end; - List.iter remove_file !temps - with x -> - List.iter remove_file !temps; - raise x + let temps = ref [] in + Misc.try_finally + ~always:(fun () -> List.iter remove_file !temps) + (fun () -> + link_bytecode_as_c tolink c_file; + if not (Filename.check_suffix output_name ".c") then begin + temps := c_file :: !temps; + if Ccomp.compile_file ~output:obj_file ?stable_name c_file <> 0 then + raise(Error Custom_runtime); + if not (Filename.check_suffix output_name Config.ext_obj) || + !Clflags.output_complete_object then begin + temps := obj_file :: !temps; + let mode, c_libs = + if Filename.check_suffix output_name Config.ext_obj + then Ccomp.Partial, "" + else Ccomp.MainDll, Config.bytecomp_c_libraries + in + if not ( + let runtime_lib = "-lcamlrun" ^ !Clflags.runtime_variant in + Ccomp.call_linker mode output_name + ([obj_file] @ List.rev !Clflags.ccobjs @ [runtime_lib]) + c_libs + ) then raise (Error Custom_runtime); + end + end; + ) end (* Error report *) diff --git a/bytecomp/bytelink.mli b/bytecomp/bytelink.mli index 56439e26..e3cf98da 100644 --- a/bytecomp/bytelink.mli +++ b/bytecomp/bytelink.mli @@ -15,11 +15,10 @@ (* Link .cmo files and produce a bytecode executable. *) -val link : Format.formatter -> string list -> string -> unit +val link : string list -> string -> unit val reset : unit -> unit -val check_consistency: - Format.formatter -> string -> Cmo_format.compilation_unit -> unit +val check_consistency: string -> Cmo_format.compilation_unit -> unit val extract_crc_interfaces: unit -> (string * Digest.t option) list diff --git a/bytecomp/bytepackager.ml b/bytecomp/bytepackager.ml index ac78c344..ba57ef94 100644 --- a/bytecomp/bytepackager.ml +++ b/bytecomp/bytepackager.ml @@ -19,8 +19,7 @@ open Misc open Instruct open Cmo_format - -module StringSet = Set.Make(String) +module String = Misc.Stdlib.String type error = Forward_reference of string * Ident.t @@ -35,7 +34,7 @@ exception Error of error let relocs = ref ([] : (reloc_info * int) list) let events = ref ([] : debug_event list) -let debug_dirs = ref StringSet.empty +let debug_dirs = ref String.Set.empty let primitives = ref ([] : string list) let force_link = ref false @@ -132,11 +131,11 @@ let read_member_info file = ( Accumulate relocs, debug info, etc. Return size of bytecode. *) -let rename_append_bytecode ppf packagename oc mapping defined ofs prefix subst +let rename_append_bytecode packagename oc mapping defined ofs prefix subst objfile compunit = let ic = open_in_bin objfile in try - Bytelink.check_consistency ppf objfile compunit; + Bytelink.check_consistency objfile compunit; List.iter (rename_relocation packagename objfile mapping defined ofs) compunit.cu_reloc; @@ -148,7 +147,7 @@ let rename_append_bytecode ppf packagename oc mapping defined ofs prefix subst seek_in ic compunit.cu_debug; List.iter (relocate_debug ofs prefix subst) (input_value ic); debug_dirs := List.fold_left - (fun s e -> StringSet.add e s) + (fun s e -> String.Set.add e s) !debug_dirs (input_value ic); end; @@ -161,7 +160,7 @@ let rename_append_bytecode ppf packagename oc mapping defined ofs prefix subst (* Same, for a list of .cmo and .cmi files. Return total size of bytecode. *) -let rec rename_append_bytecode_list ppf packagename oc mapping defined ofs +let rec rename_append_bytecode_list packagename oc mapping defined ofs prefix subst = function [] -> @@ -169,23 +168,23 @@ let rec rename_append_bytecode_list ppf packagename oc mapping defined ofs | m :: rem -> match m.pm_kind with | PM_intf -> - rename_append_bytecode_list ppf packagename oc mapping defined ofs + rename_append_bytecode_list packagename oc mapping defined ofs prefix subst rem | PM_impl compunit -> let size = - rename_append_bytecode ppf packagename oc mapping defined ofs + rename_append_bytecode packagename oc mapping defined ofs prefix subst m.pm_file compunit in let id = Ident.create_persistent m.pm_name in let root = Path.Pident (Ident.create_persistent prefix) in - rename_append_bytecode_list ppf packagename oc mapping (id :: defined) + rename_append_bytecode_list packagename oc mapping (id :: defined) (ofs + size) prefix - (Subst.add_module id (Path.Pdot (root, Ident.name id, Path.nopos)) + (Subst.add_module id (Path.Pdot (root, Ident.name id)) subst) rem (* Generate the code that builds the tuple representing the package module *) -let build_global_target oc target_name members mapping pos coercion = +let build_global_target ~ppf_dump oc target_name members mapping pos coercion = let components = List.map2 (fun m (_id1, id2) -> @@ -197,7 +196,7 @@ let build_global_target oc target_name members mapping pos coercion = Translmod.transl_package components (Ident.create_persistent target_name) coercion in if !Clflags.dump_lambda then - Format.printf "%a@." Printlambda.lambda lam; + Format.fprintf ppf_dump "%a@." Printlambda.lambda lam; let instrs = Bytegen.compile_implementation target_name lam in let rel = @@ -206,7 +205,7 @@ let build_global_target oc target_name members mapping pos coercion = (* Build the .cmo file obtained by packaging the given .cmo files. *) -let package_object_files ppf files targetfile targetname coercion = +let package_object_files ~ppf_dump files targetfile targetname coercion = let members = map_left_right read_member_info files in let required_globals = @@ -241,13 +240,13 @@ let package_object_files ppf files targetfile targetname coercion = let pos_depl = pos_out oc in output_binary_int oc 0; let pos_code = pos_out oc in - let ofs = rename_append_bytecode_list ppf targetname oc mapping [] 0 + let ofs = rename_append_bytecode_list targetname oc mapping [] 0 targetname Subst.identity members in - build_global_target oc targetname members mapping ofs coercion; + build_global_target ~ppf_dump oc targetname members mapping ofs coercion; let pos_debug = pos_out oc in if !Clflags.debug && !events <> [] then begin output_value oc (List.rev !events); - output_value oc (StringSet.elements !debug_dirs); + output_value oc (String.Set.elements !debug_dirs); end; let pos_final = pos_out oc in let imports = @@ -278,22 +277,22 @@ let package_object_files ppf files targetfile targetname coercion = (* The entry point *) -let package_files ppf initial_env files targetfile = +let package_files ~ppf_dump initial_env files targetfile = let files = List.map (fun f -> - try find_in_path !Config.load_path f + try Load_path.find f with Not_found -> raise(Error(File_not_found f))) files in let prefix = chop_extensions targetfile in let targetcmi = prefix ^ ".cmi" in let targetname = String.capitalize_ascii(Filename.basename prefix) in - try - let coercion = - Typemod.package_units initial_env files targetcmi targetname in - package_object_files ppf files targetfile targetname coercion - with x -> - remove_file targetfile; raise x + Misc.try_finally (fun () -> + let coercion = + Typemod.package_units initial_env files targetcmi targetname in + package_object_files ~ppf_dump files targetfile targetname coercion + ) + ~exceptionally:(fun () -> remove_file targetfile) (* Error report *) diff --git a/bytecomp/bytepackager.mli b/bytecomp/bytepackager.mli index c856b632..95177716 100644 --- a/bytecomp/bytepackager.mli +++ b/bytecomp/bytepackager.mli @@ -16,7 +16,8 @@ (* "Package" a set of .cmo files into one .cmo file having the original compilation units as sub-modules. *) -val package_files: Format.formatter -> Env.t -> string list -> string -> unit +val package_files: + ppf_dump:Format.formatter -> Env.t -> string list -> string -> unit type error = Forward_reference of string * Ident.t diff --git a/bytecomp/cmo_format.mli b/bytecomp/cmo_format.mli index 4f4e7bbf..7fbb35a0 100644 --- a/bytecomp/cmo_format.mli +++ b/bytecomp/cmo_format.mli @@ -63,9 +63,3 @@ type library = ... object code for last library member library descriptor *) - -(* Tables for numbering objects *) - -type 'a numtable = - { num_cnt: int; (* The next number *) - num_tbl: ('a, int) Tbl.t } (* The table of already numbered objects *) diff --git a/bytecomp/dll.ml b/bytecomp/dll.ml index c64f43cf..a902a9fc 100644 --- a/bytecomp/dll.ml +++ b/bytecomp/dll.ml @@ -132,32 +132,15 @@ let ld_conf_contents () = (* Split the CAML_LD_LIBRARY_PATH environment variable and return the corresponding list of directories. *) - -let split str sep = - let rec split_rec pos = - if pos >= String.length str then [] else begin - try - let newpos = String.index_from str pos sep in - String.sub str pos (newpos - pos) :: - split_rec (newpos + 1) - with Not_found -> - [String.sub str pos (String.length str - pos)] - end in - split_rec 0 - let ld_library_path_contents () = - let path_separator = - match Sys.os_type with - | "Unix" | "Cygwin" -> ':' - | "Win32" -> ';' - | _ -> assert false in - try - split (Sys.getenv "CAML_LD_LIBRARY_PATH") path_separator - with Not_found -> - [] + match Sys.getenv "CAML_LD_LIBRARY_PATH" with + | exception Not_found -> + [] + | s -> + Misc.split_path_contents s let split_dll_path path = - split path '\000' + Misc.split_path_contents ~sep:'\000' path (* Initialization for separate compilation *) diff --git a/bytecomp/dune b/bytecomp/dune new file mode 100644 index 00000000..b2409cf4 --- /dev/null +++ b/bytecomp/dune @@ -0,0 +1,28 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +(rule + (targets opcodes.ml) + (mode fallback) + (deps (:instr (file ../runtime/caml/instruct.h))) + (action + (bash "%{dep:../tools/make_opcodes.exe} -opcodes < %{instr} > %{targets}"))) + +(rule + (targets runtimedef.ml) + (mode fallback) + (deps (:fail (file ../runtime/caml/fail.h)) + (:prim (file ../runtime/primitives))) + (action (with-stdout-to %{targets} + (run ./generate_runtimedef.sh %{fail} %{prim})))) diff --git a/bytecomp/emitcode.ml b/bytecomp/emitcode.ml index aed2666c..03251eb0 100644 --- a/bytecomp/emitcode.ml +++ b/bytecomp/emitcode.ml @@ -22,8 +22,7 @@ open Lambda open Instruct open Opcodes open Cmo_format - -module StringSet = Set.Make(String) +module String = Misc.Stdlib.String type error = Not_compatible_32 of (string * string) exception Error of error @@ -39,12 +38,15 @@ let marshal_to_channel_with_possibly_32bit_compat ~filename ~kind outchan obj = let report_error ppf (file, kind) = - Format.fprintf ppf "Generated %s %S cannot be used on a 32-bit platform" kind file + Format.fprintf ppf "Generated %s %S cannot be used on a 32-bit platform" + kind file let () = Location.register_error_of_exn (function - | Error (Not_compatible_32 info) -> Some (Location.error_of_printer_file report_error info) - | _ -> None + | Error (Not_compatible_32 info) -> + Some (Location.error_of_printer_file report_error info) + | _ -> + None ) (* Buffering of bytecode *) @@ -162,15 +164,15 @@ and slot_for_c_prim name = (* Debugging events *) let events = ref ([] : debug_event list) -let debug_dirs = ref StringSet.empty +let debug_dirs = ref String.Set.empty let record_event ev = let path = ev.ev_loc.Location.loc_start.Lexing.pos_fname in let abspath = Location.absolute_path path in - debug_dirs := StringSet.add (Filename.dirname abspath) !debug_dirs; + debug_dirs := String.Set.add (Filename.dirname abspath) !debug_dirs; if Filename.is_relative path then begin let cwd = Location.rewrite_absolute_path (Sys.getcwd ()) in - debug_dirs := StringSet.add cwd !debug_dirs; + debug_dirs := String.Set.add cwd !debug_dirs; end; ev.ev_pos <- !out_position; events := ev :: !events @@ -181,7 +183,7 @@ let init () = out_position := 0; label_table := Array.make 16 (Label_undefined []); reloc_info := []; - debug_dirs := StringSet.empty; + debug_dirs := String.Set.empty; events := [] (* Emission of one instruction *) @@ -405,12 +407,12 @@ let to_file outchan unit_name objfile ~required_globals code = LongString.output outchan !out_buffer 0 !out_position; let (pos_debug, size_debug) = if !Clflags.debug then begin - debug_dirs := StringSet.add + debug_dirs := String.Set.add (Filename.dirname (Location.absolute_path objfile)) !debug_dirs; let p = pos_out outchan in output_value outchan !events; - output_value outchan (StringSet.elements !debug_dirs); + output_value outchan (String.Set.elements !debug_dirs); (p, pos_out outchan - p) end else (0, 0) in @@ -442,13 +444,12 @@ let to_memory init_code fun_code = init(); emit init_code; emit fun_code; - let code = Meta.static_alloc !out_position in - LongString.unsafe_blit_to_bytes !out_buffer 0 code 0 !out_position; - let reloc = List.rev !reloc_info - and code_size = !out_position in + let code = LongString.create !out_position in + LongString.blit !out_buffer 0 code 0 !out_position; + let reloc = List.rev !reloc_info in let events = !events in init(); - (code, code_size, reloc, events) + (code, reloc, events) (* Emission to a file for a packed library *) diff --git a/bytecomp/emitcode.mli b/bytecomp/emitcode.mli index 414211cd..95da242e 100644 --- a/bytecomp/emitcode.mli +++ b/bytecomp/emitcode.mli @@ -27,14 +27,14 @@ val to_file: out_channel -> string -> string -> required_globals: list of compilation units that must be evaluated before this one list of instructions to emit *) -val to_memory: instruction list -> instruction list -> - bytes * int * (reloc_info * int) list * debug_event list +val to_memory: + instruction list -> instruction list -> + Misc.LongString.t * (reloc_info * int) list * debug_event list (* Arguments: initialization code (terminated by STOP) function code Results: block of relocatable bytecode - size of this block relocation information debug events *) val to_packed_file: @@ -47,4 +47,5 @@ val to_packed_file: val reset: unit -> unit -val marshal_to_channel_with_possibly_32bit_compat : filename:string -> kind:string -> out_channel -> 'a -> unit +val marshal_to_channel_with_possibly_32bit_compat : + filename:string -> kind:string -> out_channel -> 'a -> unit diff --git a/bytecomp/generate_runtimedef.sh b/bytecomp/generate_runtimedef.sh new file mode 100755 index 00000000..66ccf3ce --- /dev/null +++ b/bytecomp/generate_runtimedef.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 1999 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +echo 'let builtin_exceptions = [|' +cat "$1" | tr -d '\r' | \ + sed -n -e 's|.*/\* \("[A-Za-z_]*"\) \*/$| \1;|p' +echo '|]' + +echo 'let builtin_primitives = [|' +sed -e 's/.*/ "&";/' "$2" +echo '|]' diff --git a/bytecomp/instruct.ml b/bytecomp/instruct.ml index d7dae7fc..99163628 100644 --- a/bytecomp/instruct.ml +++ b/bytecomp/instruct.ml @@ -108,6 +108,6 @@ type instruction = let immed_min = -0x40000000 and immed_max = 0x3FFFFFFF -(* Actually the abstract machine accomodates -0x80000000 to 0x7FFFFFFF, +(* Actually the abstract machine accommodates -0x80000000 to 0x7FFFFFFF, but these numbers overflow the OCaml type int if the compiler runs on a 32-bit processor. *) diff --git a/bytecomp/instruct.mli b/bytecomp/instruct.mli index f52f322d..4c4e9f1c 100644 --- a/bytecomp/instruct.mli +++ b/bytecomp/instruct.mli @@ -37,7 +37,7 @@ type compilation_env = (* Debugging events *) -(* Warning: when you change these types, check byterun/backtrace.c *) +(* Warning: when you change these types, check runtime/backtrace.c *) type debug_event = { mutable ev_pos: int; (* Position in bytecode *) ev_module: string; (* Name of defining module *) diff --git a/bytecomp/lambda.ml b/bytecomp/lambda.ml index 4b396af1..ebdd49a3 100644 --- a/bytecomp/lambda.ml +++ b/bytecomp/lambda.ml @@ -14,7 +14,6 @@ (**************************************************************************) open Misc -open Path open Asttypes type compile_time_constant = @@ -111,10 +110,10 @@ type primitive = | Plsrbint of boxed_integer | Pasrbint of boxed_integer | Pbintcomp of boxed_integer * integer_comparison - (* Operations on big arrays: (unsafe, #dimensions, kind, layout) *) + (* Operations on Bigarrays: (unsafe, #dimensions, kind, layout) *) | Pbigarrayref of bool * int * bigarray_kind * bigarray_layout | Pbigarrayset of bool * int * bigarray_kind * bigarray_layout - (* size of the nth dimension of a big array *) + (* size of the nth dimension of a Bigarray *) | Pbigarraydim of int (* load/set 16,32,64 bits from a string: (unsafe)*) | Pstring_load_16 of bool @@ -181,6 +180,30 @@ and raise_kind = | Raise_reraise | Raise_notrace +let equal_boxed_integer x y = + match x, y with + | Pnativeint, Pnativeint + | Pint32, Pint32 + | Pint64, Pint64 -> + true + | (Pnativeint | Pint32 | Pint64), _ -> + false + +let equal_primitive = + (* Should be implemented like [equal_value_kind] of [equal_boxed_integer], + i.e. by matching over the various constructors but the type has more + than 100 constructors... *) + (=) + +let equal_value_kind x y = + match x, y with + | Pgenval, Pgenval -> true + | Pfloatval, Pfloatval -> true + | Pboxedintval bi1, Pboxedintval bi2 -> equal_boxed_integer bi1 bi2 + | Pintval, Pintval -> true + | (Pgenval | Pfloatval | Pboxedintval _ | Pintval), _ -> false + + type structured_constant = Const_base of constant | Const_pointer of int @@ -194,22 +217,56 @@ type inline_attribute = | Unroll of int (* [@unroll x] *) | Default_inline (* no [@inline] attribute *) +let equal_inline_attribute x y = + match x, y with + | Always_inline, Always_inline + | Never_inline, Never_inline + | Default_inline, Default_inline + -> + true + | Unroll u, Unroll v -> + u = v + | (Always_inline | Never_inline | Unroll _ | Default_inline), _ -> + false + type specialise_attribute = | Always_specialise (* [@specialise] or [@specialise always] *) | Never_specialise (* [@specialise never] *) | Default_specialise (* no [@specialise] attribute *) +let equal_specialise_attribute x y = + match x, y with + | Always_specialise, Always_specialise + | Never_specialise, Never_specialise + | Default_specialise, Default_specialise -> + true + | (Always_specialise | Never_specialise | Default_specialise), _ -> + false + +type local_attribute = + | Always_local (* [@local] or [@local always] *) + | Never_local (* [@local never] *) + | Default_local (* [@local maybe] or no [@local] attribute *) + type function_kind = Curried | Tupled type let_kind = Strict | Alias | StrictOpt | Variable type meth_kind = Self | Public | Cached +let equal_meth_kind x y = + match x, y with + | Self, Self -> true + | Public, Public -> true + | Cached, Cached -> true + | (Self | Public | Cached), _ -> false + type shared_code = (int * int) list type function_attribute = { inline : inline_attribute; specialise : specialise_attribute; + local: local_attribute; is_a_functor: bool; stub: bool; } @@ -226,7 +283,7 @@ type lambda = | Lstringswitch of lambda * (string * lambda) list * lambda option * Location.t | Lstaticraise of int * lambda list - | Lstaticcatch of lambda * (int * Ident.t list) * lambda + | Lstaticcatch of lambda * (int * (Ident.t * value_kind) list) * lambda | Ltrywith of lambda * Ident.t * lambda | Lifthenelse of lambda * lambda * lambda | Lsequence of lambda * lambda @@ -239,7 +296,8 @@ type lambda = and lfunction = { kind: function_kind; - params: Ident.t list; + params: (Ident.t * value_kind) list; + return: value_kind; body: lambda; attr: function_attribute; (* specified with [@inline] attribute *) loc: Location.t; } @@ -263,7 +321,7 @@ and lambda_event = { lev_loc: Location.t; lev_kind: lambda_event_kind; lev_repr: int ref option; - lev_env: Env.summary } + lev_env: Env.t } and lambda_event_kind = Lev_before @@ -285,6 +343,7 @@ let lambda_unit = Lconst const_unit let default_function_attribute = { inline = Default_inline; specialise = Default_specialise; + local = Default_local; is_a_functor = false; stub = false; } @@ -294,7 +353,7 @@ let default_stub_attribute = (* Build sharing keys *) (* - Those keys are later compared with Pervasives.compare. + Those keys are later compared with Stdlib.compare. For that reason, they should not include cycles. *) @@ -303,7 +362,7 @@ exception Not_simple let max_raw = 32 let make_key e = - let count = ref 0 (* Used for controling size *) + let count = ref 0 (* Used for controlling size *) and make_key = Ident.make_key_generator () in (* make_key is used for normalizing let-bound variables *) let rec tr_rec env e = @@ -386,7 +445,9 @@ let make_key e = let name_lambda strict arg fn = match arg with Lvar id -> fn id - | _ -> let id = Ident.create "let" in Llet(strict, Pgenval, id, arg, fn id) + | _ -> + let id = Ident.create_local "let" in + Llet(strict, Pgenval, id, arg, fn id) let name_lambda_list args fn = let rec name_list names = function @@ -394,7 +455,7 @@ let name_lambda_list args fn = | (Lvar _ as arg) :: rem -> name_list (arg :: names) rem | arg :: rem -> - let id = Ident.create "let" in + let id = Ident.create_local "let" in Llet(Strict, Pgenval, id, arg, name_list (Lvar id :: names) rem) in name_list [] args @@ -403,7 +464,7 @@ let iter_opt f = function | None -> () | Some e -> f e -let iter_head_constructor f = function +let shallow_iter ~tail ~non_tail:f = function Lvar _ | Lconst _ -> () | Lapply{ap_func = fn; ap_args = args} -> @@ -411,31 +472,37 @@ let iter_head_constructor f = function | Lfunction{body} -> f body | Llet(_str, _k, _id, arg, body) -> - f arg; f body + f arg; tail body | Lletrec(decl, body) -> - f body; + tail body; List.iter (fun (_id, exp) -> f exp) decl + | Lprim (Pidentity, [l], _) -> + tail l + | Lprim (Psequand, [l1; l2], _) + | Lprim (Psequor, [l1; l2], _) -> + f l1; + tail l2 | Lprim(_p, args, _loc) -> List.iter f args | Lswitch(arg, sw,_) -> f arg; - List.iter (fun (_key, case) -> f case) sw.sw_consts; - List.iter (fun (_key, case) -> f case) sw.sw_blocks; - iter_opt f sw.sw_failaction + List.iter (fun (_key, case) -> tail case) sw.sw_consts; + List.iter (fun (_key, case) -> tail case) sw.sw_blocks; + iter_opt tail sw.sw_failaction | Lstringswitch (arg,cases,default,_) -> f arg ; - List.iter (fun (_,act) -> f act) cases ; - iter_opt f default + List.iter (fun (_,act) -> tail act) cases ; + iter_opt tail default | Lstaticraise (_,args) -> List.iter f args | Lstaticcatch(e1, _, e2) -> - f e1; f e2 + tail e1; tail e2 | Ltrywith(e1, _, e2) -> - f e1; f e2 + f e1; tail e2 | Lifthenelse(e1, e2, e3) -> - f e1; f e2; f e3 + f e1; tail e2; tail e3 | Lsequence(e1, e2) -> - f e1; f e2 + f e1; tail e2 | Lwhile(e1, e2) -> f e1; f e2 | Lfor(_v, e1, e2, _dir, e3) -> @@ -444,10 +511,13 @@ let iter_head_constructor f = function f e | Lsend (_k, met, obj, args, _) -> List.iter f (met::obj::args) - | Levent (lam, _evt) -> - f lam + | Levent (e, _evt) -> + tail e | Lifused (_v, e) -> - f e + tail e + +let iter_head_constructor f l = + shallow_iter ~tail:f ~non_tail:f l let rec free_variables = function | Lvar id -> Ident.Set.singleton id @@ -456,7 +526,7 @@ let rec free_variables = function free_variables_list (free_variables fn) args | Lfunction{body; params} -> Ident.Set.diff (free_variables body) - (Ident.Set.of_list params) + (Ident.Set.of_list (List.map fst params)) | Llet(_str, _k, id, arg, body) -> Ident.Set.union (free_variables arg) @@ -492,7 +562,7 @@ let rec free_variables = function Ident.Set.union (Ident.Set.diff (free_variables handler) - (Ident.Set.of_list params)) + (Ident.Set.of_list (List.map fst params))) (free_variables body) | Ltrywith(body, param, handler) -> Ident.Set.union @@ -554,29 +624,42 @@ let rec patch_guarded patch = function (* Translate an access path *) -let rec transl_normal_path = function - Pident id -> +let rec transl_address loc = function + | Env.Aident id -> if Ident.global id - then Lprim(Pgetglobal id, [], Location.none) + then Lprim(Pgetglobal id, [], loc) else Lvar id - | Pdot(p, _s, pos) -> - Lprim(Pfield pos, [transl_normal_path p], Location.none) - | Papply _ -> - fatal_error "Lambda.transl_path" + | Env.Adot(addr, pos) -> + Lprim(Pfield pos, [transl_address loc addr], loc) + +let transl_path find loc env path = + match find path env with + | exception Not_found -> + fatal_error ("Cannot find address for: " ^ (Path.name path)) + | addr -> transl_address loc addr (* Translation of identifiers *) -let transl_module_path ?(loc=Location.none) env path = - transl_normal_path (Env.normalize_path (Some loc) env path) +let transl_module_path loc env path = + transl_path Env.find_module_address loc env path -let transl_value_path ?(loc=Location.none) env path = - transl_normal_path (Env.normalize_path_prefix (Some loc) env path) +let transl_value_path loc env path = + transl_path Env.find_value_address loc env path -let transl_class_path = transl_value_path -let transl_extension_path = transl_value_path +let transl_extension_path loc env path = + transl_path Env.find_constructor_address loc env path -(* compatibility alias, deprecated in the .mli *) -let transl_path = transl_value_path +let transl_class_path loc env path = + transl_path Env.find_class_address loc env path + +let transl_prim mod_name name = + let pers = Ident.create_persistent mod_name in + let env = Env.add_persistent_structure pers Env.empty in + let lid = Longident.Ldot (Longident.Lident mod_name, name) in + match Env.lookup_value lid env with + | path, _ -> transl_value_path Location.none env path + | exception Not_found -> + fatal_error ("Primitive " ^ name ^ " not found.") (* Compile a sequence of expressions *) @@ -590,136 +673,161 @@ let rec make_sequence fn = function Assumes that the image of the substitution is out of reach of the bound variables of the lambda-term (no capture). *) -let rec subst s lam = - let remove_list l s = - List.fold_left (fun s id -> Ident.Map.remove id s) s l - in - let module M = Ident.Map in - match lam with - | Lvar id as l -> - begin try Ident.Map.find id s with Not_found -> l end - | Lconst _ as l -> l - | Lapply ap -> - Lapply{ap with ap_func = subst s ap.ap_func; - ap_args = subst_list s ap.ap_args} - | Lfunction{kind; params; body; attr; loc} -> - let s = List.fold_right Ident.Map.remove params s in - Lfunction{kind; params; body = subst s body; attr; loc} - | Llet(str, k, id, arg, body) -> - Llet(str, k, id, subst s arg, subst (Ident.Map.remove id s) body) - | Lletrec(decl, body) -> - let s = - List.fold_left (fun s (id, _) -> Ident.Map.remove id s) - s decl - in - Lletrec(List.map (subst_decl s) decl, subst s body) - | Lprim(p, args, loc) -> Lprim(p, subst_list s args, loc) - | Lswitch(arg, sw, loc) -> - Lswitch(subst s arg, - {sw with sw_consts = List.map (subst_case s) sw.sw_consts; - sw_blocks = List.map (subst_case s) sw.sw_blocks; - sw_failaction = subst_opt s sw.sw_failaction; }, - loc) - | Lstringswitch (arg,cases,default,loc) -> - Lstringswitch - (subst s arg,List.map (subst_strcase s) cases,subst_opt s default,loc) - | Lstaticraise (i,args) -> Lstaticraise (i, subst_list s args) - | Lstaticcatch(body, (id, params), handler) -> - Lstaticcatch(subst s body, (id, params), - subst (remove_list params s) handler) - | Ltrywith(body, exn, handler) -> - Ltrywith(subst s body, exn, subst (Ident.Map.remove exn s) handler) - | Lifthenelse(e1, e2, e3) -> Lifthenelse(subst s e1, subst s e2, subst s e3) - | Lsequence(e1, e2) -> Lsequence(subst s e1, subst s e2) - | Lwhile(e1, e2) -> Lwhile(subst s e1, subst s e2) - | Lfor(v, lo, hi, dir, body) -> - Lfor(v, subst s lo, subst s hi, dir, - subst (Ident.Map.remove v s) body) - | Lassign(id, e) -> - assert(not (Ident.Map.mem id s)); - Lassign(id, subst s e) - | Lsend (k, met, obj, args, loc) -> - Lsend (k, subst s met, subst s obj, subst_list s args, loc) - | Levent (lam, evt) -> Levent (subst s lam, evt) - | Lifused (v, e) -> Lifused (v, subst s e) -and subst_list s l = List.map (subst s) l -and subst_decl s (id, exp) = (id, subst s exp) -and subst_case s (key, case) = (key, subst s case) -and subst_strcase s (key, case) = (key, subst s case) -and subst_opt s = function - | None -> None - | Some e -> Some (subst s e) - - -let rec map f lam = - let lam = +let subst update_env s lam = + let rec subst s lam = + let remove_list l s = + List.fold_left (fun s (id, _kind) -> Ident.Map.remove id s) s l + in + let module M = Ident.Map in match lam with - | Lvar _ -> lam - | Lconst _ -> lam - | Lapply { ap_func; ap_args; ap_loc; ap_should_be_tailcall; - ap_inlined; ap_specialised } -> - Lapply { - ap_func = map f ap_func; - ap_args = List.map (map f) ap_args; - ap_loc; - ap_should_be_tailcall; - ap_inlined; - ap_specialised; - } - | Lfunction { kind; params; body; attr; loc; } -> - Lfunction { kind; params; body = map f body; attr; loc; } - | Llet (str, k, v, e1, e2) -> - Llet (str, k, v, map f e1, map f e2) - | Lletrec (idel, e2) -> - Lletrec (List.map (fun (v, e) -> (v, map f e)) idel, map f e2) - | Lprim (p, el, loc) -> - Lprim (p, List.map (map f) el, loc) - | Lswitch (e, sw, loc) -> - Lswitch (map f e, - { sw_numconsts = sw.sw_numconsts; - sw_consts = List.map (fun (n, e) -> (n, map f e)) sw.sw_consts; - sw_numblocks = sw.sw_numblocks; - sw_blocks = List.map (fun (n, e) -> (n, map f e)) sw.sw_blocks; - sw_failaction = Misc.may_map (map f) sw.sw_failaction; - }, - loc) - | Lstringswitch (e, sw, default, loc) -> - Lstringswitch ( - map f e, - List.map (fun (s, e) -> (s, map f e)) sw, - Misc.may_map (map f) default, - loc) - | Lstaticraise (i, args) -> - Lstaticraise (i, List.map (map f) args) - | Lstaticcatch (body, id, handler) -> - Lstaticcatch (map f body, id, map f handler) - | Ltrywith (e1, v, e2) -> - Ltrywith (map f e1, v, map f e2) - | Lifthenelse (e1, e2, e3) -> - Lifthenelse (map f e1, map f e2, map f e3) - | Lsequence (e1, e2) -> - Lsequence (map f e1, map f e2) - | Lwhile (e1, e2) -> - Lwhile (map f e1, map f e2) - | Lfor (v, e1, e2, dir, e3) -> - Lfor (v, map f e1, map f e2, dir, map f e3) - | Lassign (v, e) -> - Lassign (v, map f e) - | Lsend (k, m, o, el, loc) -> - Lsend (k, map f m, map f o, List.map (map f) el, loc) - | Levent (l, ev) -> - Levent (map f l, ev) - | Lifused (v, e) -> - Lifused (v, map f e) + | Lvar id as l -> + begin try Ident.Map.find id s with Not_found -> l end + | Lconst _ as l -> l + | Lapply ap -> + Lapply{ap with ap_func = subst s ap.ap_func; + ap_args = subst_list s ap.ap_args} + | Lfunction lf -> + let s = + List.fold_right + (fun (id, _) s -> Ident.Map.remove id s) + lf.params s + in + Lfunction {lf with body = subst s lf.body} + | Llet(str, k, id, arg, body) -> + Llet(str, k, id, subst s arg, subst (Ident.Map.remove id s) body) + | Lletrec(decl, body) -> + let s = + List.fold_left (fun s (id, _) -> Ident.Map.remove id s) + s decl + in + Lletrec(List.map (subst_decl s) decl, subst s body) + | Lprim(p, args, loc) -> Lprim(p, subst_list s args, loc) + | Lswitch(arg, sw, loc) -> + Lswitch(subst s arg, + {sw with sw_consts = List.map (subst_case s) sw.sw_consts; + sw_blocks = List.map (subst_case s) sw.sw_blocks; + sw_failaction = subst_opt s sw.sw_failaction; }, + loc) + | Lstringswitch (arg,cases,default,loc) -> + Lstringswitch + (subst s arg,List.map (subst_strcase s) cases,subst_opt s default,loc) + | Lstaticraise (i,args) -> Lstaticraise (i, subst_list s args) + | Lstaticcatch(body, (id, params), handler) -> + Lstaticcatch(subst s body, (id, params), + subst (remove_list params s) handler) + | Ltrywith(body, exn, handler) -> + Ltrywith(subst s body, exn, subst (Ident.Map.remove exn s) handler) + | Lifthenelse(e1, e2, e3) -> Lifthenelse(subst s e1, subst s e2, subst s e3) + | Lsequence(e1, e2) -> Lsequence(subst s e1, subst s e2) + | Lwhile(e1, e2) -> Lwhile(subst s e1, subst s e2) + | Lfor(v, lo, hi, dir, body) -> + Lfor(v, subst s lo, subst s hi, dir, + subst (Ident.Map.remove v s) body) + | Lassign(id, e) -> + assert(not (Ident.Map.mem id s)); + Lassign(id, subst s e) + | Lsend (k, met, obj, args, loc) -> + Lsend (k, subst s met, subst s obj, subst_list s args, loc) + | Levent (lam, evt) -> + let lev_env = + Ident.Map.fold (fun id _ env -> + match Env.find_value (Path.Pident id) evt.lev_env with + | exception Not_found -> env + | vd -> update_env id vd env + ) s evt.lev_env + in + Levent (subst s lam, { evt with lev_env }) + | Lifused (v, e) -> Lifused (v, subst s e) + and subst_list s l = List.map (subst s) l + and subst_decl s (id, exp) = (id, subst s exp) + and subst_case s (key, case) = (key, subst s case) + and subst_strcase s (key, case) = (key, subst s case) + and subst_opt s = function + | None -> None + | Some e -> Some (subst s e) + in + subst s lam + +let rename idmap lam = + let update_env oldid vd env = + let newid = Ident.Map.find oldid idmap in + Env.add_value newid vd env in - f lam + let s = Ident.Map.map (fun new_id -> Lvar new_id) idmap in + subst update_env s lam + +let shallow_map f = function + | Lvar _ + | Lconst _ as lam -> lam + | Lapply { ap_func; ap_args; ap_loc; ap_should_be_tailcall; + ap_inlined; ap_specialised } -> + Lapply { + ap_func = f ap_func; + ap_args = List.map f ap_args; + ap_loc; + ap_should_be_tailcall; + ap_inlined; + ap_specialised; + } + | Lfunction { kind; params; return; body; attr; loc; } -> + Lfunction { kind; params; return; body = f body; attr; loc; } + | Llet (str, k, v, e1, e2) -> + Llet (str, k, v, f e1, f e2) + | Lletrec (idel, e2) -> + Lletrec (List.map (fun (v, e) -> (v, f e)) idel, f e2) + | Lprim (p, el, loc) -> + Lprim (p, List.map f el, loc) + | Lswitch (e, sw, loc) -> + Lswitch (f e, + { sw_numconsts = sw.sw_numconsts; + sw_consts = List.map (fun (n, e) -> (n, f e)) sw.sw_consts; + sw_numblocks = sw.sw_numblocks; + sw_blocks = List.map (fun (n, e) -> (n, f e)) sw.sw_blocks; + sw_failaction = Misc.may_map f sw.sw_failaction; + }, + loc) + | Lstringswitch (e, sw, default, loc) -> + Lstringswitch ( + f e, + List.map (fun (s, e) -> (s, f e)) sw, + Misc.may_map f default, + loc) + | Lstaticraise (i, args) -> + Lstaticraise (i, List.map f args) + | Lstaticcatch (body, id, handler) -> + Lstaticcatch (f body, id, f handler) + | Ltrywith (e1, v, e2) -> + Ltrywith (f e1, v, f e2) + | Lifthenelse (e1, e2, e3) -> + Lifthenelse (f e1, f e2, f e3) + | Lsequence (e1, e2) -> + Lsequence (f e1, f e2) + | Lwhile (e1, e2) -> + Lwhile (f e1, f e2) + | Lfor (v, e1, e2, dir, e3) -> + Lfor (v, f e1, f e2, dir, f e3) + | Lassign (v, e) -> + Lassign (v, f e) + | Lsend (k, m, o, el, loc) -> + Lsend (k, f m, f o, List.map f el, loc) + | Levent (l, ev) -> + Levent (f l, ev) + | Lifused (v, e) -> + Lifused (v, f e) + +let map f = + let rec g lam = f (shallow_map g lam) in + g (* To let-bind expressions to variables *) -let bind str var exp body = +let bind_with_value_kind str (var, kind) exp body = match exp with Lvar var' when Ident.same var var' -> body - | _ -> Llet(str, Pgenval, var, exp, body) + | _ -> Llet(str, kind, var, exp, body) + +let bind str var exp body = + bind_with_value_kind str (var, Pgenval) exp body let negate_integer_comparison = function | Ceq -> Cne @@ -774,5 +882,10 @@ let merge_inline_attributes attr1 attr2 = if attr1 = attr2 then Some attr1 else None +let function_is_curried func = + match func.kind with + | Curried -> true + | Tupled -> false + let reset () = raise_count := 0 diff --git a/bytecomp/lambda.mli b/bytecomp/lambda.mli index e82aa3e7..f79ee0c7 100644 --- a/bytecomp/lambda.mli +++ b/bytecomp/lambda.mli @@ -118,10 +118,10 @@ type primitive = | Plsrbint of boxed_integer | Pasrbint of boxed_integer | Pbintcomp of boxed_integer * integer_comparison - (* Operations on big arrays: (unsafe, #dimensions, kind, layout) *) + (* Operations on Bigarrays: (unsafe, #dimensions, kind, layout) *) | Pbigarrayref of bool * int * bigarray_kind * bigarray_layout | Pbigarrayset of bool * int * bigarray_kind * bigarray_layout - (* size of the nth dimension of a big array *) + (* size of the nth dimension of a Bigarray *) | Pbigarraydim of int (* load/set 16,32,64 bits from a string: (unsafe)*) | Pstring_load_16 of bool @@ -188,6 +188,12 @@ and raise_kind = | Raise_reraise | Raise_notrace +val equal_primitive : primitive -> primitive -> bool + +val equal_value_kind : value_kind -> value_kind -> bool + +val equal_boxed_integer : boxed_integer -> boxed_integer -> bool + type structured_constant = Const_base of constant | Const_pointer of int @@ -201,11 +207,23 @@ type inline_attribute = | Unroll of int (* [@unroll x] *) | Default_inline (* no [@inline] attribute *) +val equal_inline_attribute : inline_attribute -> inline_attribute -> bool + type specialise_attribute = | Always_specialise (* [@specialise] or [@specialise always] *) | Never_specialise (* [@specialise never] *) | Default_specialise (* no [@specialise] attribute *) +val equal_specialise_attribute + : specialise_attribute + -> specialise_attribute + -> bool + +type local_attribute = + | Always_local (* [@local] or [@local always] *) + | Never_local (* [@local never] *) + | Default_local (* [@local maybe] or no [@local] attribute *) + type function_kind = Curried | Tupled type let_kind = Strict | Alias | StrictOpt | Variable @@ -222,11 +240,14 @@ type let_kind = Strict | Alias | StrictOpt | Variable type meth_kind = Self | Public | Cached +val equal_meth_kind : meth_kind -> meth_kind -> bool + type shared_code = (int * int) list (* stack size -> code label *) type function_attribute = { inline : inline_attribute; specialise : specialise_attribute; + local: local_attribute; is_a_functor: bool; stub: bool; } @@ -245,7 +266,7 @@ type lambda = | Lstringswitch of lambda * (string * lambda) list * lambda option * Location.t | Lstaticraise of int * lambda list - | Lstaticcatch of lambda * (int * Ident.t list) * lambda + | Lstaticcatch of lambda * (int * (Ident.t * value_kind) list) * lambda | Ltrywith of lambda * Ident.t * lambda | Lifthenelse of lambda * lambda * lambda | Lsequence of lambda * lambda @@ -258,7 +279,8 @@ type lambda = and lfunction = { kind: function_kind; - params: Ident.t list; + params: (Ident.t * value_kind) list; + return: value_kind; body: lambda; attr: function_attribute; (* specified with [@inline] attribute *) loc : Location.t; } @@ -281,7 +303,7 @@ and lambda_event = { lev_loc: Location.t; lev_kind: lambda_event_kind; lev_repr: int ref option; - lev_env: Env.summary } + lev_env: Env.t } and lambda_event_kind = Lev_before @@ -319,28 +341,58 @@ val name_lambda_list: lambda list -> (lambda list -> lambda) -> lambda val iter_head_constructor: (lambda -> unit) -> lambda -> unit (** [iter_head_constructor f lam] apply [f] to only the first level of sub expressions of [lam]. It does not recursively traverse the - expression. *) + expression. +*) -val free_variables: lambda -> Ident.Set.t +val shallow_iter: + tail:(lambda -> unit) -> + non_tail:(lambda -> unit) -> + lambda -> unit +(** Same as [iter_head_constructor], but use a different callback for + sub-terms which are in tail position or not. *) -val transl_normal_path: Path.t -> lambda (* Path.t is already normal *) -val transl_path: ?loc:Location.t -> Env.t -> Path.t -> lambda -[@@ocaml.deprecated "use transl_{module,value,extension,class}_path instead"] +val transl_prim: string -> string -> lambda +(** Translate a value from a persistent module. For instance: -val transl_module_path: ?loc:Location.t -> Env.t -> Path.t -> lambda -val transl_value_path: ?loc:Location.t -> Env.t -> Path.t -> lambda -val transl_extension_path: ?loc:Location.t -> Env.t -> Path.t -> lambda -val transl_class_path: ?loc:Location.t -> Env.t -> Path.t -> lambda + {[ + transl_internal_value "CamlinternalLazy" "force" + ]} +*) + +val free_variables: lambda -> Ident.Set.t + +val transl_module_path: Location.t -> Env.t -> Path.t -> lambda +val transl_value_path: Location.t -> Env.t -> Path.t -> lambda +val transl_extension_path: Location.t -> Env.t -> Path.t -> lambda +val transl_class_path: Location.t -> Env.t -> Path.t -> lambda val make_sequence: ('a -> lambda) -> 'a list -> lambda -val subst: lambda Ident.Map.t -> lambda -> lambda -(** Apply a substitution to a lambda-term. +val subst: (Ident.t -> Types.value_description -> Env.t -> Env.t) -> + lambda Ident.Map.t -> lambda -> lambda +(** [subst env_update_fun s lt] applies a substitution [s] to the lambda-term + [lt]. + Assumes that the image of the substitution is out of reach - of the bound variables of the lambda-term (no capture). *) + of the bound variables of the lambda-term (no capture). + + [env_update_fun] is used to refresh the environment contained in debug + events. *) + +val rename : Ident.t Ident.Map.t -> lambda -> lambda +(** A version of [subst] specialized for the case where we're just renaming + idents. *) val map : (lambda -> lambda) -> lambda -> lambda + (** Bottom-up rewriting, applying the function on + each node from the leaves to the root. *) + +val shallow_map : (lambda -> lambda) -> lambda -> lambda + (** Rewrite each immediate sub-term with the function. *) + val bind : let_kind -> Ident.t -> lambda -> lambda -> lambda +val bind_with_value_kind: + let_kind -> (Ident.t * value_kind) -> lambda -> lambda -> lambda val negate_integer_comparison : integer_comparison -> integer_comparison val swap_integer_comparison : integer_comparison -> integer_comparison @@ -351,6 +403,8 @@ val swap_float_comparison : float_comparison -> float_comparison val default_function_attribute : function_attribute val default_stub_attribute : function_attribute +val function_is_curried : lfunction -> bool + (***********************) (* For static failures *) (***********************) diff --git a/bytecomp/matching.ml b/bytecomp/matching.ml index 6ed69827..0b31ecbc 100644 --- a/bytecomp/matching.ml +++ b/bytecomp/matching.ml @@ -82,11 +82,7 @@ type ctx = {left:pattern list ; right:pattern list} let pretty_ctx ctx = List.iter (fun {left=left ; right=right} -> - prerr_string "LEFT:" ; - pretty_line Format.err_formatter left ; - prerr_string " RIGHT:" ; - pretty_line Format.err_formatter right ; - prerr_endline "") + Format.eprintf "LEFT:%a RIGHT:%a\n" pretty_line left pretty_line right) ctx let le_ctx c1 c2 = @@ -108,7 +104,7 @@ let rec small_enough n = function else small_enough (n-1) rem let ctx_lshift ctx = - if small_enough 31 ctx then + if small_enough (!Clflags.match_context_rows - 1) ctx then List.map lshift ctx else (* Context pruning *) begin get_mins le_ctx (List.map lforget ctx) @@ -396,7 +392,9 @@ type pattern_matching = type pm_or_compiled = {body : pattern_matching ; - handlers : (matrix * int * Ident.t list * pattern_matching) list ; + handlers : + (matrix * int * (Ident.t * Lambda.value_kind) list * pattern_matching) + list; or_matrix : matrix ; } type pm_half_compiled = @@ -416,27 +414,17 @@ let pretty_cases cases = List.iter (fun (ps,_l) -> List.iter - (fun p -> - top_pretty Format.str_formatter p ; - prerr_string " " ; - prerr_string (Format.flush_str_formatter ())) + (fun p -> Format.eprintf " %a%!" top_pretty p) ps ; -(* - prerr_string " -> " ; - Printlambda.lambda Format.str_formatter l ; - prerr_string (Format.flush_str_formatter ()) ; -*) - prerr_endline "") + Format.eprintf "\n") cases let pretty_def def = - prerr_endline "+++++ Defaults +++++" ; + Format.eprintf "+++++ Defaults +++++\n" ; List.iter - (fun (pss,i) -> - Printf.fprintf stderr "Matrix for %d\n" i ; - pretty_matrix Format.err_formatter pss) + (fun (pss,i) -> Format.eprintf "Matrix for %d\n%a" i pretty_matrix pss) def ; - prerr_endline "+++++++++++++++++++++" + Format.eprintf "+++++++++++++++++++++\n" let pretty_pm pm = pretty_cases pm.cases ; @@ -446,13 +434,13 @@ let pretty_pm pm = let rec pretty_precompiled = function | Pm pm -> - prerr_endline "++++ PM ++++" ; + Format.eprintf "++++ PM ++++\n" ; pretty_pm pm | PmVar x -> - prerr_endline "++++ VAR ++++" ; + Format.eprintf "++++ VAR ++++\n" ; pretty_precompiled x.inside | PmOr x -> - prerr_endline "++++ OR ++++" ; + Format.eprintf "++++ OR ++++\n" ; pretty_pm x.body ; pretty_matrix Format.err_formatter x.or_matrix ; List.iter @@ -488,7 +476,7 @@ module StoreExp = (struct type t = lambda type key = lambda - let compare_key = Pervasives.compare + let compare_key = Stdlib.compare let make_key = Lambda.make_key end) @@ -610,12 +598,15 @@ let simplify_cases args cls = match args with | ((pat :: patl, action) as cl) :: rem -> begin match pat.pat_desc with | Tpat_var (id, _) -> - (omega :: patl, bind Alias id arg action) :: + let k = Typeopt.value_kind pat.pat_env pat.pat_type in + (omega :: patl, bind_with_value_kind Alias (id, k) arg action) :: simplify rem | Tpat_any -> cl :: simplify rem | Tpat_alias(p, id,_) -> - simplify ((p :: patl, bind Alias id arg action) :: rem) + let k = Typeopt.value_kind pat.pat_env pat.pat_type in + simplify ((p :: patl, + bind_with_value_kind Alias (id, k) arg action) :: rem) | Tpat_record ([],_) -> (omega :: patl, action):: simplify rem @@ -678,24 +669,6 @@ let default_compat p def = def [] (* Or-pattern expansion, variables are a complication w.r.t. the article *) -let rec extract_vars r p = match p.pat_desc with -| Tpat_var (id, _) -> Ident.Set.add id r -| Tpat_alias (p, id,_ ) -> - extract_vars (Ident.Set.add id r) p -| Tpat_tuple pats -> - List.fold_left extract_vars r pats -| Tpat_record (lpats,_) -> - List.fold_left - (fun r (_, _, p) -> extract_vars r p) - r lpats -| Tpat_construct (_, _, pats) -> - List.fold_left extract_vars r pats -| Tpat_array pats -> - List.fold_left extract_vars r pats -| Tpat_variant (_,Some p, _) -> extract_vars r p -| Tpat_lazy p -> extract_vars r p -| Tpat_or (p,_,_) -> extract_vars r p -| Tpat_constant _|Tpat_any|Tpat_variant (_,None,_) -> r exception Cannot_flatten @@ -707,7 +680,7 @@ let mk_alpha_env arg aliases ids = | Some v -> v | _ -> raise Cannot_flatten else - Ident.create (Ident.name id)) + Ident.create_local (Ident.name id)) ids let rec explode_or_pat arg patl mk_action rem vars aliases = function @@ -736,9 +709,33 @@ let pat_as_constr = function | {pat_desc=Tpat_construct (_, cstr,_)} -> cstr | _ -> fatal_error "Matching.pat_as_constr" -let group_constant = function - | {pat_desc= Tpat_constant _} -> true - | _ -> false +let group_const_int = function + | {pat_desc= Tpat_constant Const_int _ } -> true + | _ -> false + +let group_const_char = function + | {pat_desc= Tpat_constant Const_char _ } -> true + | _ -> false + +let group_const_string = function + | {pat_desc= Tpat_constant Const_string _ } -> true + | _ -> false + +let group_const_float = function + | {pat_desc= Tpat_constant Const_float _ } -> true + | _ -> false + +let group_const_int32 = function + | {pat_desc= Tpat_constant Const_int32 _ } -> true + | _ -> false + +let group_const_int64 = function + | {pat_desc= Tpat_constant Const_int64 _ } -> true + | _ -> false + +let group_const_nativeint = function + | {pat_desc= Tpat_constant Const_nativeint _ } -> true + | _ -> false and group_constructor = function | {pat_desc = Tpat_construct (_,_,_)} -> true @@ -770,7 +767,13 @@ and group_lazy = function let get_group p = match p.pat_desc with | Tpat_any -> group_var -| Tpat_constant _ -> group_constant +| Tpat_constant Const_int _ -> group_const_int +| Tpat_constant Const_char _ -> group_const_char +| Tpat_constant Const_string _ -> group_const_string +| Tpat_constant Const_float _ -> group_const_float +| Tpat_constant Const_int32 _ -> group_const_int32 +| Tpat_constant Const_int64 _ -> group_const_int64 +| Tpat_constant Const_nativeint _ -> group_const_nativeint | Tpat_construct _ -> group_constructor | Tpat_tuple _ -> group_tuple | Tpat_record _ -> group_record @@ -817,8 +820,8 @@ let insert_or_append p ps act ors no = if is_or q then begin if may_compat p q then if - Ident.Set.is_empty (extract_vars Ident.Set.empty p) && - Ident.Set.is_empty (extract_vars Ident.Set.empty q) && + Typedtree.pat_bound_idents p = [] && + Typedtree.pat_bound_idents q = [] && equiv_pat p q then (* attempt insert, for equivalent orpats with no variables *) let _, not_e = get_equiv q rem in @@ -879,7 +882,7 @@ let rebuild_nexts arg nexts k = in actions (cf. simplify_cases). Additionally, if the match argument is a variable, matchings whose - first column is made of variables only are splitted further + first column is made of variables only are split further (cf. precompile_var). *) @@ -1064,7 +1067,7 @@ and precompile_var args cls def k = match args with | [] -> assert false | _::((Lvar v as av,_) as arg)::rargs -> begin match cls with - | [_] -> (* as splitted as it can *) + | [_] -> (* as split as it can *) dont_precompile_var args cls def k | _ -> (* Precompile *) @@ -1112,12 +1115,13 @@ and precompile_or argo cls ors args def k = match ors with | _ -> assert false) others ; args = (match args with _::r -> r | _ -> assert false) ; - default = default_compat orp def} in + default = default_compat orp def} in + let pm_fv = pm_free_variables orpm in let vars = - Ident.Set.elements - (Ident.Set.inter - (extract_vars Ident.Set.empty orp) - (pm_free_variables orpm)) in + Typedtree.pat_bound_idents_full orp + |> List.filter (fun (id, _, _) -> Ident.Set.mem id pm_fv) + |> List.map (fun (id,_,ty) -> id,Typeopt.value_kind orp.pat_env ty) + in let or_num = next_raise_count () in let new_patl = Parmatch.omega_list patl in @@ -1127,7 +1131,7 @@ and precompile_or argo cls ors args def k = match ors with let body,handlers = do_cases rem in explode_or_pat - argo new_patl mk_new_action body vars [] orp, + argo new_patl mk_new_action body (List.map fst vars) [] orp, let mat = [[orp]] in ((mat, or_num, vars , orpm):: handlers) | cl::rem -> @@ -1147,7 +1151,7 @@ let split_precompile argo pm = let {me=next}, nexts = split_or argo pm.cases pm.args pm.default in if dbg && (nexts <> [] || (match next with PmOr _ -> true | _ -> false)) then begin - prerr_endline "** SPLIT **" ; + Format.eprintf "** SPLIT **\n" ; pretty_pm pm ; pretty_precompiled_res next nexts end ; @@ -1231,7 +1235,7 @@ let rec matcher_const cst p rem = match p.pat_desc with let get_key_constant caller = function | {pat_desc= Tpat_constant cst} -> cst | p -> - prerr_endline ("BAD: "^caller) ; + Format.eprintf "BAD: %s" caller ; pretty_pat p ; assert false @@ -1460,24 +1464,22 @@ let prim_obj_tag = let get_mod_field modname field = lazy ( - try - let mod_ident = Ident.create_persistent modname in - let env = Env.open_pers_signature modname Env.initial_safe_string in - let p = try + let mod_ident = Ident.create_persistent modname in + let env = Env.add_persistent_structure mod_ident Env.initial_safe_string in + match Env.open_pers_signature modname env with + | exception Not_found -> fatal_error ("Module "^modname^" unavailable.") + | env -> begin match Env.lookup_value (Longident.Lident field) env with - | (Path.Pdot(_,_,i), _) -> i - | _ -> fatal_error ("Primitive "^modname^"."^field^" not found.") - with Not_found -> - fatal_error ("Primitive "^modname^"."^field^" not found.") - in - Lprim(Pfield p, - [Lprim(Pgetglobal mod_ident, [], Location.none)], - Location.none) - with Not_found -> fatal_error ("Module "^modname^" unavailable.") + | exception Not_found -> + fatal_error ("Primitive "^modname^"."^field^" not found.") + | (path, _) -> transl_value_path Location.none env path + end ) let code_force_lazy_block = get_mod_field "CamlinternalLazy" "force_lazy_block" +let code_force_lazy = + get_mod_field "CamlinternalLazy" "force" ;; (* inline_lazy_force inlines the beginning of the code of Lazy.force. When @@ -1491,9 +1493,9 @@ let code_force_lazy_block = *) let inline_lazy_force_cond arg loc = - let idarg = Ident.create "lzarg" in + let idarg = Ident.create_local "lzarg" in let varg = Lvar idarg in - let tag = Ident.create "tag" in + let tag = Ident.create_local "tag" in let force_fun = Lazy.force code_force_lazy_block in Llet(Strict, Pgenval, idarg, arg, Llet(Alias, Pgenval, tag, Lprim(Pccall prim_obj_tag, [varg], loc), @@ -1518,7 +1520,7 @@ let inline_lazy_force_cond arg loc = varg)))) let inline_lazy_force_switch arg loc = - let idarg = Ident.create "lzarg" in + let idarg = Ident.create_local "lzarg" in let varg = Lvar idarg in let force_fun = Lazy.force code_force_lazy_block in Llet(Strict, Pgenval, idarg, arg, @@ -1540,13 +1542,25 @@ let inline_lazy_force_switch arg loc = sw_failaction = Some varg }, loc )))) let inline_lazy_force arg loc = - if !Clflags.native_code then - (* Lswitch generates compact and efficient native code *) - inline_lazy_force_switch arg loc + if !Clflags.afl_instrument then + (* Disable inlining optimisation if AFL instrumentation active, + so that the GC forwarding optimisation is not visible in the + instrumentation output. + (see https://github.com/stedolan/crowbar/issues/14) *) + Lapply{ap_should_be_tailcall = false; + ap_loc=loc; + ap_func=Lazy.force code_force_lazy; + ap_args=[arg]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise} else - (* generating bytecode: Lswitch would generate too many rather big - tables (~ 250 elts); conditionals are better *) - inline_lazy_force_cond arg loc + if !Clflags.native_code then + (* Lswitch generates compact and efficient native code *) + inline_lazy_force_switch arg loc + else + (* generating bytecode: Lswitch would generate too many rather big + tables (~ 250 elts); conditionals are better *) + inline_lazy_force_cond arg loc let make_lazy_matching def = function [] -> fatal_error "Matching.make_lazy_matching" @@ -1634,7 +1648,7 @@ let make_record_matching loc all_labels def = function Lprim (Pfield lbl.lbl_pos, [arg], loc) | Record_unboxed _ -> arg | Record_float -> Lprim (Pfloatfield lbl.lbl_pos, [arg], loc) - | Record_extension -> Lprim (Pfield (lbl.lbl_pos + 1), [arg], loc) + | Record_extension _ -> Lprim (Pfield (lbl.lbl_pos + 1), [arg], loc) in let str = match lbl.lbl_mut with @@ -1725,7 +1739,7 @@ let prim_string_compare = let bind_sw arg k = match arg with | Lvar _ -> k arg | _ -> - let id = Ident.create "switch" in + let id = Ident.create_local "switch" in Llet (Strict,Pgenval,id,arg,k (Lvar id)) @@ -1918,7 +1932,7 @@ module SArg = struct let newvar,newarg = match arg with | Lvar v -> v,arg | _ -> - let newvar = Ident.create "switcher" in + let newvar = Ident.create_local "switcher" in newvar,Lvar newvar in bind Alias newvar arg (body newarg) let make_const i = Lconst (Const_base (Const_int i)) @@ -2170,7 +2184,7 @@ let mk_failaction_neg partial ctx def = match partial with (* In line with the article and simpler than before *) let mk_failaction_pos partial seen ctx defs = if dbg then begin - prerr_endline "**POS**" ; + Format.eprintf "**POS**\n" ; pretty_def defs ; () end ; @@ -2196,7 +2210,7 @@ let mk_failaction_pos partial seen ctx defs = | _ -> scan_def ((List.map fst now,idef)::env) later rem in let fail_pats = complete_pats_constrs seen in - if List.length fail_pats < 32 then begin + if List.length fail_pats < !Clflags.match_context_rows then begin let fail,jmps = scan_def [] @@ -2322,11 +2336,11 @@ let combine_constructor loc arg ex_pat cstr partial ctx def match nonconsts with [] -> default | _ -> - let tag = Ident.create "tag" in + let tag = Ident.create_local "tag" in let tests = List.fold_right (fun (path, act) rem -> - let ext = transl_extension_path ex_pat.pat_env path in + let ext = transl_extension_path loc ex_pat.pat_env path in Lifthenelse(Lprim(Pintcomp Ceq, [Lvar tag; ext], loc), act, rem)) nonconsts @@ -2336,7 +2350,7 @@ let combine_constructor loc arg ex_pat cstr partial ctx def in List.fold_right (fun (path, act) rem -> - let ext = transl_extension_path ex_pat.pat_env path in + let ext = transl_extension_path loc ex_pat.pat_env path in Lifthenelse(Lprim(Pintcomp Ceq, [arg; ext], loc), act, rem)) consts @@ -2408,7 +2422,7 @@ let call_switcher_variant_constant loc fail arg int_lambda_list = let call_switcher_variant_constr loc fail arg int_lambda_list = - let v = Ident.create "variant" in + let v = Ident.create_local "variant" in Llet(Alias, Pgenval, v, Lprim(Pfield 0, [arg], loc), call_switcher loc fail (Lvar v) min_int max_int int_lambda_list) @@ -2470,7 +2484,7 @@ let combine_array loc arg kind partial ctx def (len_lambda_list, total1, _pats) = let fail, local_jumps = mk_failaction_neg partial ctx def in let lambda1 = - let newvar = Ident.create "len" in + let newvar = Ident.create_local "len" in let switch = call_switcher loc fail (Lvar newvar) @@ -2509,7 +2523,7 @@ let rec event_branch repr lam = compile_list (for compiling switch results) catch Unused - comp_match_handlers (for compiling splitted matches) + comp_match_handlers (for compiling split matches) may reraise Unused @@ -2548,7 +2562,8 @@ let compile_orhandlers compile_fun lambda1 total1 ctx to_catch = match raw_action r with | Lstaticraise (j,args) -> if i=j then - List.fold_right2 (bind Alias) vars args handler_i, + List.fold_right2 (bind_with_value_kind Alias) + vars args handler_i, jumps_map (ctx_rshift_num (ncols mat)) total_i else do_rec r total_r rem @@ -2673,7 +2688,7 @@ let rec name_pattern default = function | Tpat_alias(_, id, _) -> id | _ -> name_pattern default rem end - | _ -> Ident.create default + | _ -> Ident.create_local default let arg_to_var arg cls = match arg with | Lvar v -> v,arg @@ -2718,14 +2733,13 @@ let rec compile_match repr partial ctx m = match m with (* verbose version of do_compile_matching, for debug *) and do_compile_matching_pr repr partial ctx arg x = - prerr_string "COMPILE: " ; - prerr_endline (match partial with Partial -> "Partial" | Total -> "Total") ; - prerr_endline "MATCH" ; + Format.eprintf "COMPILE: %s\nMATCH\n" + (match partial with Partial -> "Partial" | Total -> "Total") ; pretty_precompiled x ; - prerr_endline "CTX" ; + Format.eprintf "CTX\n" ; pretty_ctx ctx ; let (_, jumps) as r = do_compile_matching repr partial ctx arg x in - prerr_endline "JUMPS" ; + Format.eprintf "JUMPS\n" ; pretty_jumps jumps ; r @@ -2824,6 +2838,7 @@ let find_in_pat pred = find_rec p || find_rec q | Tpat_constant _ | Tpat_var _ | Tpat_any | Tpat_variant (_,None,_) -> false + | Tpat_exception _ -> assert false end in find_rec @@ -2833,6 +2848,7 @@ let is_lazy_pat = function | Tpat_tuple _|Tpat_construct _ | Tpat_array _ | Tpat_or _ | Tpat_constant _ | Tpat_var _ | Tpat_any -> false + | Tpat_exception _ -> assert false let is_lazy p = find_in_pat is_lazy_pat p @@ -2849,6 +2865,7 @@ let have_mutable_field p = match p with | Tpat_or _ | Tpat_constant _ | Tpat_var _ | Tpat_any -> false +| Tpat_exception _ -> assert false let is_mutable p = find_in_pat have_mutable_field p @@ -2910,14 +2927,16 @@ let compile_matching repr handler_fun arg pat_act_list partial = let partial_function loc () = - (* [Location.get_pos_info] is too expensive *) + let slot = + transl_extension_path loc + Env.initial_safe_string Predef.path_match_failure + in let (fname, line, char) = Location.get_pos_info loc.Location.loc_start in Lprim(Praise Raise_regular, [Lprim(Pmakeblock(0, Immutable, None), - [transl_normal_path Predef.path_match_failure; - Lconst(Const_block(0, - [Const_base(Const_string (fname, None)); - Const_base(Const_int line); - Const_base(Const_int char)]))], loc)], loc) + [slot; Lconst(Const_block(0, + [Const_base(Const_string (fname, None)); + Const_base(Const_int line); + Const_base(Const_int char)]))], loc)], loc) let for_function loc repr param pat_act_list partial = compile_matching repr (partial_function loc) param pat_act_list partial @@ -3055,9 +3074,14 @@ let for_let loc param pat body = | _ -> let opt = ref false in let nraise = next_raise_count () in - let catch_ids = pat_bound_idents pat in - let bind = map_return (assign_pat opt nraise catch_ids loc pat) param in - if !opt then Lstaticcatch(bind, (nraise, catch_ids), body) + let catch_ids = pat_bound_idents_full pat in + let ids_with_kinds = + List.map (fun (id, _, typ) -> id, Typeopt.value_kind pat.pat_env typ) + catch_ids + in + let ids = List.map (fun (id, _, _) -> id) catch_ids in + let bind = map_return (assign_pat opt nraise ids loc pat) param in + if !opt then Lstaticcatch(bind, (nraise, ids_with_kinds), body) else simple_for_let loc param pat body (* Handling of tupled functions and matchings *) @@ -3166,7 +3190,7 @@ let do_for_multiple_match loc paraml pat_act_list partial = let next, nexts = split_precompile None pm1 in let size = List.length paraml - and idl = List.map (fun _ -> Ident.create "*match*") paraml in + and idl = List.map (fun _ -> Ident.create_local "*match*") paraml in let args = List.map (fun id -> Lvar id, Alias) idl in let flat_next = flatten_precompiled size args next @@ -3203,7 +3227,7 @@ let do_for_multiple_match loc paraml pat_act_list partial = let param_to_var param = match param with | Lvar v -> v,None -| _ -> Ident.create "*match*",Some param +| _ -> Ident.create_local "*match*",Some param let bind_opt (v,eo) k = match eo with | None -> k diff --git a/bytecomp/meta.ml b/bytecomp/meta.ml index 175cce3f..d92ea0d4 100644 --- a/bytecomp/meta.ml +++ b/bytecomp/meta.ml @@ -15,19 +15,15 @@ external global_data : unit -> Obj.t array = "caml_get_global_data" external realloc_global_data : int -> unit = "caml_realloc_global" -external static_alloc : int -> bytes = "caml_static_alloc" -external static_free : bytes -> unit = "caml_static_free" -external static_resize : bytes -> int -> bytes = "caml_static_resize" -external static_release_bytecode : bytes -> int -> unit - = "caml_static_release_bytecode" type closure = unit -> Obj.t -external reify_bytecode : bytes -> int -> closure = "caml_reify_bytecode" +type bytecode +external reify_bytecode : + bytes array -> Instruct.debug_event list array -> string option -> + bytecode * closure + = "caml_reify_bytecode" +external release_bytecode : bytecode -> unit + = "caml_static_release_bytecode" external invoke_traced_function : Obj.t -> Obj.t -> Obj.t -> Obj.t = "caml_invoke_traced_function" external get_section_table : unit -> (string * Obj.t) list = "caml_get_section_table" -external add_debug_info : - bytes -> int -> Instruct.debug_event list array -> unit - = "caml_add_debug_info" -external remove_debug_info : bytes -> unit - = "caml_remove_debug_info" diff --git a/bytecomp/meta.mli b/bytecomp/meta.mli index ab006637..0cf9862a 100644 --- a/bytecomp/meta.mli +++ b/bytecomp/meta.mli @@ -17,19 +17,15 @@ external global_data : unit -> Obj.t array = "caml_get_global_data" external realloc_global_data : int -> unit = "caml_realloc_global" -external static_alloc : int -> bytes = "caml_static_alloc" -external static_free : bytes -> unit = "caml_static_free" -external static_release_bytecode : bytes -> int -> unit - = "caml_static_release_bytecode" -external static_resize : bytes -> int -> bytes = "caml_static_resize" type closure = unit -> Obj.t -external reify_bytecode : bytes -> int -> closure = "caml_reify_bytecode" +type bytecode +external reify_bytecode : + bytes array -> Instruct.debug_event list array -> string option -> + bytecode * closure + = "caml_reify_bytecode" +external release_bytecode : bytecode -> unit + = "caml_static_release_bytecode" external invoke_traced_function : Obj.t -> Obj.t -> Obj.t -> Obj.t = "caml_invoke_traced_function" external get_section_table : unit -> (string * Obj.t) list = "caml_get_section_table" -external add_debug_info : - bytes -> int -> Instruct.debug_event list array -> unit - = "caml_add_debug_info" -external remove_debug_info : bytes -> unit - = "caml_remove_debug_info" diff --git a/bytecomp/printlambda.ml b/bytecomp/printlambda.ml index f128db5e..e4bb26a6 100644 --- a/bytecomp/printlambda.ml +++ b/bytecomp/printlambda.ml @@ -54,11 +54,17 @@ let boxed_integer_name = function | Pint32 -> "int32" | Pint64 -> "int64" -let value_kind = function - | Pgenval -> "" - | Pintval -> "[int]" - | Pfloatval -> "[float]" - | Pboxedintval bi -> Printf.sprintf "[%s]" (boxed_integer_name bi) +let value_kind ppf = function + | Pgenval -> () + | Pintval -> fprintf ppf "[int]" + | Pfloatval -> fprintf ppf "[float]" + | Pboxedintval bi -> fprintf ppf "[%s]" (boxed_integer_name bi) + +let return_kind ppf = function + | Pgenval -> () + | Pintval -> fprintf ppf ": int@ " + | Pfloatval -> fprintf ppf ": float@ " + | Pboxedintval bi -> fprintf ppf ": %s@ " (boxed_integer_name bi) let field_kind = function | Pgenval -> "*" @@ -106,7 +112,7 @@ let record_rep ppf r = | Record_unboxed false -> fprintf ppf "unboxed" | Record_unboxed true -> fprintf ppf "inlined(unboxed)" | Record_float -> fprintf ppf "float" - | Record_extension -> fprintf ppf "ext" + | Record_extension path -> fprintf ppf "ext(%a)" Printtyp.path path ;; let block_shape ppf shape = match shape with @@ -439,7 +445,7 @@ let name_of_primitive = function | Pint_as_pointer -> "Pint_as_pointer" | Popaque -> "Popaque" -let function_attribute ppf { inline; specialise; is_a_functor; stub } = +let function_attribute ppf { inline; specialise; local; is_a_functor; stub } = if is_a_functor then fprintf ppf "is_a_functor@ "; if stub then @@ -454,6 +460,11 @@ let function_attribute ppf { inline; specialise; is_a_functor; stub } = | Default_specialise -> () | Always_specialise -> fprintf ppf "always_specialise@ " | Never_specialise -> fprintf ppf "never_specialise@ " + end; + begin match local with + | Default_local -> () + | Always_local -> fprintf ppf "always_local@ " + | Never_local -> fprintf ppf "never_local@ " end let apply_tailcall_attribute ppf tailcall = @@ -483,34 +494,36 @@ let rec lam ppf = function apply_tailcall_attribute ap.ap_should_be_tailcall apply_inlined_attribute ap.ap_inlined apply_specialised_attribute ap.ap_specialised - | Lfunction{kind; params; body; attr} -> + | Lfunction{kind; params; return; body; attr} -> let pr_params ppf params = match kind with | Curried -> - List.iter (fun param -> fprintf ppf "@ %a" Ident.print param) params + List.iter (fun (param, k) -> + fprintf ppf "@ %a%a" Ident.print param value_kind k) params | Tupled -> fprintf ppf " ("; let first = ref true in List.iter - (fun param -> + (fun (param, k) -> if !first then first := false else fprintf ppf ",@ "; - Ident.print ppf param) + Ident.print ppf param; + value_kind ppf k) params; fprintf ppf ")" in - fprintf ppf "@[<2>(function%a@ %a%a)@]" pr_params params - function_attribute attr lam body + fprintf ppf "@[<2>(function%a@ %a%a%a)@]" pr_params params + function_attribute attr return_kind return lam body | Llet(str, k, id, arg, body) -> let kind = function Alias -> "a" | Strict -> "" | StrictOpt -> "o" | Variable -> "v" in let rec letbody = function | Llet(str, k, id, arg, body) -> - fprintf ppf "@ @[<2>%a =%s%s@ %a@]" - Ident.print id (kind str) (value_kind k) lam arg; + fprintf ppf "@ @[<2>%a =%s%a@ %a@]" + Ident.print id (kind str) value_kind k lam arg; letbody body | expr -> expr in - fprintf ppf "@[<2>(let@ @[(@[<2>%a =%s%s@ %a@]" - Ident.print id (kind str) (value_kind k) lam arg; + fprintf ppf "@[<2>(let@ @[(@[<2>%a =%s%a@ %a@]" + Ident.print id (kind str) value_kind k lam arg; let expr = letbody body in fprintf ppf ")@]@ %a)@]" lam expr | Lletrec(id_arg_list, body) -> @@ -573,12 +586,11 @@ let rec lam ppf = function | Lstaticcatch(lbody, (i, vars), lhandler) -> fprintf ppf "@[<2>(catch@ %a@;<1 -1>with (%d%a)@ %a)@]" lam lbody i - (fun ppf vars -> match vars with - | [] -> () - | _ -> - List.iter - (fun x -> fprintf ppf " %a" Ident.print x) - vars) + (fun ppf vars -> + List.iter + (fun (x, k) -> fprintf ppf " %a%a" Ident.print x value_kind k) + vars + ) vars lam lhandler | Ltrywith(lbody, param, lhandler) -> diff --git a/bytecomp/printlambda.mli b/bytecomp/printlambda.mli index daf0d81a..137190ef 100644 --- a/bytecomp/printlambda.mli +++ b/bytecomp/printlambda.mli @@ -22,4 +22,5 @@ val lambda: formatter -> lambda -> unit val program: formatter -> program -> unit val primitive: formatter -> primitive -> unit val name_of_primitive : primitive -> string -val value_kind : value_kind -> string +val value_kind : formatter -> value_kind -> unit +val array_kind : array_kind -> string diff --git a/bytecomp/simplif.ml b/bytecomp/simplif.ml index ea9513f9..9e1eb926 100644 --- a/bytecomp/simplif.ml +++ b/bytecomp/simplif.ml @@ -206,8 +206,8 @@ let simplify_exits lam = | Lapply ap -> Lapply{ap with ap_func = simplif ap.ap_func; ap_args = List.map simplif ap.ap_args} - | Lfunction{kind; params; body = l; attr; loc} -> - Lfunction{kind; params; body = simplif l; attr; loc} + | Lfunction{kind; params; return; body = l; attr; loc} -> + Lfunction{kind; params; return; body = simplif l; attr; loc} | Llet(str, kind, v, l1, l2) -> Llet(str, kind, v, simplif l1, simplif l2) | Lletrec(bindings, body) -> Lletrec(List.map (fun (v, l) -> (v, simplif l)) bindings, simplif body) @@ -263,14 +263,15 @@ let simplify_exits lam = let ls = List.map simplif ls in begin try let xs,handler = Hashtbl.find subst i in - let ys = List.map Ident.rename xs in + let ys = List.map (fun (x, k) -> Ident.rename x, k) xs in let env = List.fold_right2 - (fun x y t -> Ident.Map.add x (Lvar y) t) - xs ys Ident.Map.empty in + (fun (x, _) (y, _) env -> Ident.Map.add x y env) + xs ys Ident.Map.empty + in List.fold_right2 - (fun y l r -> Llet (Alias, Pgenval, y, l, r)) - ys ls (Lambda.subst env handler) + (fun (y, kind) l r -> Llet (Strict, kind, y, l, r)) + ys ls (Lambda.rename env handler) with | Not_found -> Lstaticraise (i,ls) end @@ -317,7 +318,7 @@ let simplify_exits lam = *) let beta_reduce params body args = - List.fold_left2 (fun l param arg -> Llet(Strict, Pgenval, param, arg, l)) + List.fold_left2 (fun l (param, kind) arg -> Llet(Strict, kind, param, arg, l)) body params args (* Simplification of lets *) @@ -350,12 +351,12 @@ let simplify_lets lam = and bind_var bv v = let r = ref 0 in Hashtbl.add occ v r; - Tbl.add v r bv + Ident.Map.add v r bv (* Record a use of a variable *) and use_var bv v n = try - let r = Tbl.find v bv in r := !r + n + let r = Ident.Map.find v bv in r := !r + n with Not_found -> (* v is not locally bound, therefore this is a use under a lambda or within a loop. Increase use count by 2 -- enough so @@ -380,7 +381,7 @@ let simplify_lets lam = | Lapply{ap_func = l1; ap_args = ll} -> count bv l1; List.iter (count bv) ll | Lfunction {body} -> - count Tbl.empty body + count Ident.Map.empty body | Llet(_str, _k, v, Lvar w, l2) when optimize -> (* v will be replaced by w in l2, so each occurrence of v in l2 increases w's refcount *) @@ -415,8 +416,9 @@ let simplify_lets lam = | Ltrywith(l1, _v, l2) -> count bv l1; count bv l2 | Lifthenelse(l1, l2, l3) -> count bv l1; count bv l2; count bv l3 | Lsequence(l1, l2) -> count bv l1; count bv l2 - | Lwhile(l1, l2) -> count Tbl.empty l1; count Tbl.empty l2 - | Lfor(_, l1, l2, _dir, l3) -> count bv l1; count bv l2; count Tbl.empty l3 + | Lwhile(l1, l2) -> count Ident.Map.empty l1; count Ident.Map.empty l2 + | Lfor(_, l1, l2, _dir, l3) -> + count bv l1; count bv l2; count Ident.Map.empty l3 | Lassign(_v, l) -> (* Lalias-bound variables are never assigned, so don't increase v's refcount *) @@ -440,7 +442,7 @@ let simplify_lets lam = count bv al end in - count Tbl.empty lam; + count Ident.Map.empty lam; (* Second pass: remove Lalias bindings of unused variables, and substitute the bindings of variables used exactly once. *) @@ -472,13 +474,18 @@ let simplify_lets lam = simplif (beta_reduce params body args) | Lapply ap -> Lapply {ap with ap_func = simplif ap.ap_func; ap_args = List.map simplif ap.ap_args} - | Lfunction{kind; params; body = l; attr; loc} -> + | Lfunction{kind; params; return=return1; body = l; attr; loc} -> begin match simplif l with - Lfunction{kind=Curried; params=params'; body; attr; loc} + Lfunction{kind=Curried; params=params'; return=return2; body; attr; loc} when kind = Curried && optimize -> - Lfunction{kind; params = params @ params'; body; attr; loc} + (* The return type is the type of the value returned after + applying all the parameters to the function. The return + type of the merged function taking [params @ params'] as + parameters is the type returned after applying [params']. *) + let return = return2 in + Lfunction{kind; params = params @ params'; return; body; attr; loc} | body -> - Lfunction{kind; params; body; attr; loc} + Lfunction{kind; params; return = return1; body; attr; loc} end | Llet(_str, _k, v, Lvar w, l2) when optimize -> Hashtbl.add subst v (simplif (Lvar w)); @@ -650,10 +657,10 @@ and list_emit_tail_infos is_tail = 'Some' constructor, only to deconstruct it immediately in the function's body. *) -let split_default_wrapper ~id:fun_id ~kind ~params ~body ~attr ~loc = +let split_default_wrapper ~id:fun_id ~kind ~params ~return ~body ~attr ~loc = let rec aux map = function | Llet(Strict, k, id, (Lifthenelse(Lvar optparam, _, _) as def), rest) when - Ident.name optparam = "*opt*" && List.mem optparam params + Ident.name optparam = "*opt*" && List.mem_assoc optparam params && not (List.mem_assoc optparam map) -> let wrapper_body, inner = aux ((optparam, id) :: map) rest in @@ -665,9 +672,9 @@ let split_default_wrapper ~id:fun_id ~kind ~params ~body ~attr ~loc = let fv = Lambda.free_variables body in List.iter (fun (id, _) -> if Ident.Set.mem id fv then raise Exit) map; - let inner_id = Ident.create (Ident.name fun_id ^ "_inner") in + let inner_id = Ident.create_local (Ident.name fun_id ^ "_inner") in let map_param p = try List.assoc p map with Not_found -> p in - let args = List.map (fun p -> Lvar (map_param p)) params in + let args = List.map (fun (p, _) -> Lvar (map_param p)) params in let wrapper_body = Lapply { ap_func = Lvar inner_id; @@ -678,36 +685,164 @@ let split_default_wrapper ~id:fun_id ~kind ~params ~body ~attr ~loc = ap_specialised = Default_specialise; } in - let inner_params = List.map map_param params in + let inner_params = List.map map_param (List.map fst params) in let new_ids = List.map Ident.rename inner_params in - let subst = List.fold_left2 - (fun s id new_id -> - Ident.Map.add id (Lvar new_id) s) - Ident.Map.empty inner_params new_ids + let subst = + List.fold_left2 (fun s id new_id -> + Ident.Map.add id new_id s + ) Ident.Map.empty inner_params new_ids in - let body = Lambda.subst subst body in + let body = Lambda.rename subst body in let inner_fun = - Lfunction { kind = Curried; params = new_ids; body; attr; loc; } + Lfunction { kind = Curried; + params = List.map (fun id -> id, Pgenval) new_ids; + return; body; attr; loc; } in (wrapper_body, (inner_id, inner_fun)) in try let body, inner = aux [] body in let attr = default_stub_attribute in - [(fun_id, Lfunction{kind; params; body; attr; loc}); inner] + [(fun_id, Lfunction{kind; params; return; body; attr; loc}); inner] with Exit -> - [(fun_id, Lfunction{kind; params; body; attr; loc})] + [(fun_id, Lfunction{kind; params; return; body; attr; loc})] module Hooks = Misc.MakeHooks(struct type t = lambda end) +(* Simplify local let-bound functions: if all occurrences are + fully-applied function calls in the same "tail scope", replace the + function by a staticcatch handler (on that scope). + + This handles as a special case functions used exactly once (in any + scope) for a full application. +*) + +type slot = + { + nargs: int; + mutable scope: lambda option; + } + +module LamTbl = Hashtbl.Make(struct + type t = lambda + let equal = (==) + let hash = Hashtbl.hash + end) + +let simplify_local_functions lam = + let slots = Hashtbl.create 16 in + let static_id = Hashtbl.create 16 in (* function id -> static id *) + let static = LamTbl.create 16 in (* scope -> static function on that scope *) + (* We keep track of the current "tail scope", identified + by the outermost lambda for which the the current lambda + is in tail position. *) + let current_scope = ref lam in + let check_static lf = + if lf.attr.local = Always_local then + Location.prerr_warning lf.loc + (Warnings.Inlining_impossible + "This function cannot be compiled into a static continuation") + in + let enabled = function + | {local = Always_local; _} + | {local = Default_local; inline = (Never_inline | Default_inline); _} + -> true + | {local = Default_local; inline = (Always_inline | Unroll _); _} + | {local = Never_local; _} + -> false + in + let rec tail = function + | Llet (_str, _kind, id, Lfunction lf, cont) + when Lambda.function_is_curried lf && enabled lf.attr -> + let r = {nargs=List.length lf.params; scope=None} in + Hashtbl.add slots id r; + tail cont; + begin match Hashtbl.find_opt slots id with + | Some {scope = Some scope; _} -> + let st = next_raise_count () in + let sc = + (* Do not move higher than current lambda *) + if scope == !current_scope then cont + else scope + in + Hashtbl.add static_id id st; + LamTbl.add static sc (st, lf); + (* The body of the function will become an handler + in that "scope". *) + with_scope ~scope lf.body + | _ -> + check_static lf; + (* note: if scope = None, the function is unused *) + non_tail lf.body + end + | Lapply {ap_func = Lvar id; ap_args; _} -> + begin match Hashtbl.find_opt slots id with + | Some {nargs; _} when nargs <> List.length ap_args -> + (* Wrong arity *) + Hashtbl.remove slots id + | Some {scope = Some scope; _} when scope != !current_scope -> + (* Different "tail scope" *) + Hashtbl.remove slots id + | Some ({scope = None; _} as slot) -> + (* First use of the function: remember the current tail scope *) + slot.scope <- Some !current_scope + | _ -> + () + end; + List.iter non_tail ap_args + | Lvar id -> + Hashtbl.remove slots id + | Lfunction lf as lam -> + check_static lf; + Lambda.shallow_iter ~tail ~non_tail lam + | lam -> + Lambda.shallow_iter ~tail ~non_tail lam + and non_tail lam = + with_scope ~scope:lam lam + and with_scope ~scope lam = + let old_scope = !current_scope in + current_scope := scope; + tail lam; + current_scope := old_scope + in + tail lam; + let rec rewrite lam0 = + let lam = + match lam0 with + | Llet (_, _, id, _, cont) when Hashtbl.mem static_id id -> + rewrite cont + | Lapply {ap_func = Lvar id; ap_args; _} when Hashtbl.mem static_id id -> + Lstaticraise (Hashtbl.find static_id id, List.map rewrite ap_args) + | lam -> + Lambda.shallow_map rewrite lam + in + List.fold_right + (fun (st, lf) lam -> + Lstaticcatch (lam, (st, lf.params), rewrite lf.body) + ) + (LamTbl.find_all static lam0) + lam + in + if LamTbl.length static = 0 then + lam + else + rewrite lam + (* The entry point: simplification + emission of tailcall annotations, if needed. *) let simplify_lambda sourcefile lam = - let res = simplify_lets (simplify_exits lam) in - let res = Hooks.apply_hooks { Misc.sourcefile } res in + let lam = + lam + |> (if !Clflags.native_code || not !Clflags.debug + then simplify_local_functions else Fun.id + ) + |> simplify_exits + |> simplify_lets + |> Hooks.apply_hooks { Misc.sourcefile } + in if !Clflags.annotations || Warnings.is_active Warnings.Expect_tailcall - then emit_tail_infos true res; - res + then emit_tail_infos true lam; + lam diff --git a/bytecomp/simplif.mli b/bytecomp/simplif.mli index a1e74b97..daa2f708 100644 --- a/bytecomp/simplif.mli +++ b/bytecomp/simplif.mli @@ -13,7 +13,12 @@ (* *) (**************************************************************************) -(** Lambda simplification and lambda plugin hooks *) +(** Lambda simplification and lambda plugin hooks + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) (* Elimination of useless Llet(Alias) bindings. Transformation of let-bound references into variables. @@ -27,7 +32,8 @@ val simplify_lambda: string -> lambda -> lambda val split_default_wrapper : id:Ident.t -> kind:function_kind - -> params:Ident.t list + -> params:(Ident.t * Lambda.value_kind) list + -> return:Lambda.value_kind -> body:lambda -> attr:function_attribute -> loc:Location.t diff --git a/bytecomp/switch.ml b/bytecomp/switch.ml index b03982dd..89bfe83a 100644 --- a/bytecomp/switch.ml +++ b/bytecomp/switch.ml @@ -17,10 +17,10 @@ type 'a shared = Shared of 'a | Single of 'a type ('a, 'ctx) t_store = - {act_get : unit -> 'a array ; - act_get_shared : unit -> 'a shared array ; - act_store : 'ctx -> 'a -> int ; - act_store_shared : 'ctx -> 'a -> int ; } + {act_get : unit -> 'a array ; + act_get_shared : unit -> 'a shared array ; + act_store : 'ctx -> 'a -> int ; + act_store_shared : 'ctx -> 'a -> int ; } exception Not_simple @@ -42,9 +42,9 @@ module CtxStore(A:CtxStored) = struct Map.Make(struct type t = A.key let compare = A.compare_key end) type intern = - { mutable map : (bool * int) AMap.t ; - mutable next : int ; - mutable acts : (bool * A.t) list; } + { mutable map : (bool * int) AMap.t ; + mutable next : int ; + mutable acts : (bool * A.t) list; } let mk_store () = let st = @@ -59,18 +59,18 @@ module CtxStore(A:CtxStored) = struct i in let store mustshare ctx act = match A.make_key ctx act with - | Some key -> - begin try - let (shared,i) = AMap.find key st.map in - if not shared then st.map <- AMap.add key (true,i) st.map ; - i - with Not_found -> - let i = add mustshare act in - st.map <- AMap.add key (mustshare,i) st.map ; - i - end - | None -> - add mustshare act + | Some key -> + begin try + let (shared,i) = AMap.find key st.map in + if not shared then st.map <- AMap.add key (true,i) st.map ; + i + with Not_found -> + let i = add mustshare act in + st.map <- AMap.add key (mustshare,i) st.map ; + i + end + | None -> + add mustshare act and get () = Array.of_list (List.rev_map (fun (_,act) -> act) st.acts) @@ -79,13 +79,13 @@ module CtxStore(A:CtxStored) = struct Array.of_list (List.rev_map (fun (shared,act) -> - if shared then Shared act else Single act) + if shared then Shared act else Single act) st.acts) in AMap.iter (fun _ (shared,i) -> - if shared then match acts.(i) with - | Single act -> acts.(i) <- Shared act - | Shared _ -> ()) + if shared then match acts.(i) with + | Single act -> acts.(i) <- Shared act + | Shared _ -> ()) st.map ; acts in {act_store = store false ; act_store_shared = store true ; @@ -107,34 +107,34 @@ end module type S = - sig - type primitive - val eqint : primitive - val neint : primitive - val leint : primitive - val ltint : primitive - val geint : primitive - val gtint : primitive - type act - - val bind : act -> (act -> act) -> act - val make_const : int -> act - val make_offset : act -> int -> act - val make_prim : primitive -> act list -> act - val make_isout : act -> act -> act - val make_isin : act -> act -> act - val make_if : act -> act -> act -> act - val make_switch : Location.t -> act -> int array -> act array -> act - val make_catch : act -> int * (act -> act) - val make_exit : int -> act - end +sig + type primitive + val eqint : primitive + val neint : primitive + val leint : primitive + val ltint : primitive + val geint : primitive + val gtint : primitive + type act + + val bind : act -> (act -> act) -> act + val make_const : int -> act + val make_offset : act -> int -> act + val make_prim : primitive -> act list -> act + val make_isout : act -> act -> act + val make_isin : act -> act -> act + val make_if : act -> act -> act -> act + val make_switch : Location.t -> act -> int array -> act array -> act + val make_catch : act -> int * (act -> act) + val make_exit : int -> act +end (* The module will ``produce good code for the case statement'' *) (* Adaptation of R.L. Berstein ``Producing good code for the case statement'' - Sofware Practice and Experience, 15(10) (1985) + Software Practice and Experience, 15(10) (1985) and D.L. Spuler ``Two-Way Comparison Search Trees, a Generalisation of Binary Search Trees @@ -150,16 +150,16 @@ module type S = test sequence in small cases and heuristics otherwise. *) module Make (Arg : S) = - struct +struct - type 'a inter = - {cases : (int * int * int) array ; - actions : 'a array} + type 'a inter = + {cases : (int * int * int) array ; + actions : 'a array} -type 'a t_ctx = {off : int ; arg : 'a} + type 'a t_ctx = {off : int ; arg : 'a} -let cut = ref 8 -and more_cut = ref 16 + let cut = ref 8 + and more_cut = ref 16 (* let pint chan i = @@ -180,19 +180,19 @@ let prerr_inter i = Printf.fprintf stderr "cases=%a" pcases i.cases *) -let get_act cases i = - let _,_,r = cases.(i) in - r -and get_low cases i = - let r,_,_ = cases.(i) in - r + let get_act cases i = + let _,_,r = cases.(i) in + r + and get_low cases i = + let r,_,_ = cases.(i) in + r -type ctests = { + type ctests = { mutable n : int ; mutable ni : int ; } -let too_much = {n=max_int ; ni=max_int} + let too_much = {n=max_int ; ni=max_int} (* let ptests chan {n=n ; ni=ni} = @@ -204,30 +204,30 @@ let pta chan t = done *) -let less_tests c1 c2 = - if c1.n < c2.n then - true - else if c1.n = c2.n then begin - if c1.ni < c2.ni then + let less_tests c1 c2 = + if c1.n < c2.n then true - else + else if c1.n = c2.n then begin + if c1.ni < c2.ni then + true + else + false + end else false - end else - false -and eq_tests c1 c2 = c1.n = c2.n && c1.ni=c2.ni + and eq_tests c1 c2 = c1.n = c2.n && c1.ni=c2.ni -let less2tests (c1,d1) (c2,d2) = - if eq_tests c1 c2 then - less_tests d1 d2 - else - less_tests c1 c2 + let less2tests (c1,d1) (c2,d2) = + if eq_tests c1 c2 then + less_tests d1 d2 + else + less_tests c1 c2 -let add_test t1 t2 = - t1.n <- t1.n + t2.n ; - t1.ni <- t1.ni + t2.ni ; + let add_test t1 t2 = + t1.n <- t1.n + t2.n ; + t1.ni <- t1.ni + t2.ni ; -type t_ret = Inter of int * int | Sep of int | No + type t_ret = Inter of int * int | Sep of int | No (* let pret chan = function @@ -236,84 +236,84 @@ let pret chan = function | No -> Printf.fprintf chan "No" *) -let coupe cases i = - let l,_,_ = cases.(i) in - l, - Array.sub cases 0 i, - Array.sub cases i (Array.length cases-i) - - -let case_append c1 c2 = - let len1 = Array.length c1 - and len2 = Array.length c2 in - match len1,len2 with - | 0,_ -> c2 - | _,0 -> c1 - | _,_ -> - let l1,h1,act1 = c1.(Array.length c1-1) - and l2,h2,act2 = c2.(0) in - if act1 = act2 then - let r = Array.make (len1+len2-1) c1.(0) in - for i = 0 to len1-2 do - r.(i) <- c1.(i) - done ; - - let l = - if len1-2 >= 0 then begin - let _,h,_ = r.(len1-2) in - if h+1 < l1 then - h+1 - else + let coupe cases i = + let l,_,_ = cases.(i) in + l, + Array.sub cases 0 i, + Array.sub cases i (Array.length cases-i) + + + let case_append c1 c2 = + let len1 = Array.length c1 + and len2 = Array.length c2 in + match len1,len2 with + | 0,_ -> c2 + | _,0 -> c1 + | _,_ -> + let l1,h1,act1 = c1.(Array.length c1-1) + and l2,h2,act2 = c2.(0) in + if act1 = act2 then + let r = Array.make (len1+len2-1) c1.(0) in + for i = 0 to len1-2 do + r.(i) <- c1.(i) + done ; + + let l = + if len1-2 >= 0 then begin + let _,h,_ = r.(len1-2) in + if h+1 < l1 then + h+1 + else + l1 + end else l1 - end else - l1 - and h = - if 1 < len2-1 then begin - let l,_,_ = c2.(1) in - if h2+1 < l then - l-1 - else - h2 - end else - h2 in - r.(len1-1) <- (l,h,act1) ; - for i=1 to len2-1 do - r.(len1-1+i) <- c2.(i) - done ; - r - else if h1 > l1 then - let r = Array.make (len1+len2) c1.(0) in - for i = 0 to len1-2 do - r.(i) <- c1.(i) - done ; - r.(len1-1) <- (l1,l2-1,act1) ; - for i=0 to len2-1 do - r.(len1+i) <- c2.(i) - done ; - r - else if h2 > l2 then - let r = Array.make (len1+len2) c1.(0) in - for i = 0 to len1-1 do - r.(i) <- c1.(i) - done ; - r.(len1) <- (h1+1,h2,act2) ; - for i=1 to len2-1 do - r.(len1+i) <- c2.(i) - done ; - r - else - Array.append c1 c2 + and h = + if 1 < len2-1 then begin + let l,_,_ = c2.(1) in + if h2+1 < l then + l-1 + else + h2 + end else + h2 in + r.(len1-1) <- (l,h,act1) ; + for i=1 to len2-1 do + r.(len1-1+i) <- c2.(i) + done ; + r + else if h1 > l1 then + let r = Array.make (len1+len2) c1.(0) in + for i = 0 to len1-2 do + r.(i) <- c1.(i) + done ; + r.(len1-1) <- (l1,l2-1,act1) ; + for i=0 to len2-1 do + r.(len1+i) <- c2.(i) + done ; + r + else if h2 > l2 then + let r = Array.make (len1+len2) c1.(0) in + for i = 0 to len1-1 do + r.(i) <- c1.(i) + done ; + r.(len1) <- (h1+1,h2,act2) ; + for i=1 to len2-1 do + r.(len1+i) <- c2.(i) + done ; + r + else + Array.append c1 c2 -let coupe_inter i j cases = - let lcases = Array.length cases in - let low,_,_ = cases.(i) - and _,high,_ = cases.(j) in - low,high, - Array.sub cases i (j-i+1), - case_append (Array.sub cases 0 i) (Array.sub cases (j+1) (lcases-(j+1))) + let coupe_inter i j cases = + let lcases = Array.length cases in + let low,_,_ = cases.(i) + and _,high,_ = cases.(j) in + low,high, + Array.sub cases i (j-i+1), + case_append (Array.sub cases 0 i) (Array.sub cases (j+1) (lcases-(j+1))) -type kind = Kvalue of int | Kinter of int | Kempty + type kind = Kvalue of int | Kinter of int | Kempty (* let pkind chan = function @@ -328,52 +328,52 @@ let rec pkey chan = function Printf.fprintf chan "%a %a" pkey rem pkind k *) -let t = Hashtbl.create 17 - -let make_key cases = - let seen = ref [] - and count = ref 0 in - let rec got_it act = function - | [] -> - seen := (act,!count):: !seen ; - let r = !count in - incr count ; - r - | (act0,index) :: rem -> - if act0 = act then - index - else - got_it act rem in + let t = Hashtbl.create 17 + + let make_key cases = + let seen = ref [] + and count = ref 0 in + let rec got_it act = function + | [] -> + seen := (act,!count):: !seen ; + let r = !count in + incr count ; + r + | (act0,index) :: rem -> + if act0 = act then + index + else + got_it act rem in - let make_one l h act = - if l=h then - Kvalue (got_it act !seen) - else - Kinter (got_it act !seen) in + let make_one l h act = + if l=h then + Kvalue (got_it act !seen) + else + Kinter (got_it act !seen) in - let rec make_rec i pl = - if i < 0 then - [] - else - let l,h,act = cases.(i) in - if pl = h+1 then - make_one l h act::make_rec (i-1) l + let rec make_rec i pl = + if i < 0 then + [] else - Kempty::make_one l h act::make_rec (i-1) l in + let l,h,act = cases.(i) in + if pl = h+1 then + make_one l h act::make_rec (i-1) l + else + Kempty::make_one l h act::make_rec (i-1) l in - let l,h,act = cases.(Array.length cases-1) in - make_one l h act::make_rec (Array.length cases-2) l + let l,h,act = cases.(Array.length cases-1) in + make_one l h act::make_rec (Array.length cases-2) l - let same_act t = - let len = Array.length t in - let a = get_act t (len-1) in - let rec do_rec i = - if i < 0 then true - else - let b = get_act t i in - b=a && do_rec (i-1) in - do_rec (len-2) + let same_act t = + let len = Array.length t in + let a = get_act t (len-1) in + let rec do_rec i = + if i < 0 then true + else + let b = get_act t i in + b=a && do_rec (i-1) in + do_rec (len-2) (* @@ -390,139 +390,58 @@ let make_key cases = This condition is checked by zyva *) -let inter_limit = 1 lsl 16 - -let ok_inter = ref false - -let rec opt_count top cases = - let key = make_key cases in - try - Hashtbl.find t key - with - | Not_found -> - let r = - let lcases = Array.length cases in - match lcases with - | 0 -> assert false - | _ when same_act cases -> No, ({n=0; ni=0},{n=0; ni=0}) - | _ -> - if lcases < !cut then - enum top cases - else if lcases < !more_cut then - heuristic cases - else - divide cases in - Hashtbl.add t key r ; - r - -and divide cases = - let lcases = Array.length cases in - let m = lcases/2 in - let _,left,right = coupe cases m in - let ci = {n=1 ; ni=0} - and cm = {n=1 ; ni=0} - and _,(cml,cleft) = opt_count false left - and _,(cmr,cright) = opt_count false right in - add_test ci cleft ; - add_test ci cright ; - if less_tests cml cmr then - add_test cm cmr - else - add_test cm cml ; - Sep m,(cm, ci) - -and heuristic cases = - let lcases = Array.length cases in - - let sep,csep = divide cases - - and inter,cinter = - if !ok_inter then begin - let _,_,act0 = cases.(0) - and _,_,act1 = cases.(lcases-1) in - if act0 = act1 then begin - let low, high, inside, outside = coupe_inter 1 (lcases-2) cases in - let _,(cmi,cinside) = opt_count false inside - and _,(cmo,coutside) = opt_count false outside - and cmij = {n=1 ; ni=(if low=high then 0 else 1)} - and cij = {n=1 ; ni=(if low=high then 0 else 1)} in - add_test cij cinside ; - add_test cij coutside ; - if less_tests cmi cmo then - add_test cmij cmo - else - add_test cmij cmi ; - Inter (1,lcases-2),(cmij,cij) - end else - Inter (-1,-1),(too_much, too_much) - end else - Inter (-1,-1),(too_much, too_much) in - if less2tests csep cinter then - sep,csep - else - inter,cinter - - -and enum top cases = - let lcases = Array.length cases in - let lim, with_sep = - let best = ref (-1) and best_cost = ref (too_much,too_much) in - - for i = 1 to lcases-(1) do - let _,left,right = coupe cases i in - let ci = {n=1 ; ni=0} - and cm = {n=1 ; ni=0} - and _,(cml,cleft) = opt_count false left - and _,(cmr,cright) = opt_count false right in - add_test ci cleft ; - add_test ci cright ; - if less_tests cml cmr then - add_test cm cmr - else - add_test cm cml ; - - if - less2tests (cm,ci) !best_cost - then begin - if top then - Printf.fprintf stderr "Get it: %d\n" i ; - best := i ; - best_cost := (cm,ci) - end - done ; - !best, !best_cost in - - let ilow, ihigh, with_inter = - if not !ok_inter then - let rlow = ref (-1) and rhigh = ref (-1) - and best_cost= ref (too_much,too_much) in - for i=1 to lcases-2 do - let low, high, inside, outside = coupe_inter i i cases in - if low=high then begin - let _,(cmi,cinside) = opt_count false inside - and _,(cmo,coutside) = opt_count false outside - and cmij = {n=1 ; ni=0} - and cij = {n=1 ; ni=0} in - add_test cij cinside ; - add_test cij coutside ; - if less_tests cmi cmo then - add_test cmij cmo - else - add_test cmij cmi ; - if less2tests (cmij,cij) !best_cost then begin - rlow := i ; - rhigh := i ; - best_cost := (cmij,cij) - end - end - done ; - !rlow, !rhigh, !best_cost + let inter_limit = 1 lsl 16 + + let ok_inter = ref false + + let rec opt_count top cases = + let key = make_key cases in + try + Hashtbl.find t key + with + | Not_found -> + let r = + let lcases = Array.length cases in + match lcases with + | 0 -> assert false + | _ when same_act cases -> No, ({n=0; ni=0},{n=0; ni=0}) + | _ -> + if lcases < !cut then + enum top cases + else if lcases < !more_cut then + heuristic cases + else + divide cases in + Hashtbl.add t key r ; + r + + and divide cases = + let lcases = Array.length cases in + let m = lcases/2 in + let _,left,right = coupe cases m in + let ci = {n=1 ; ni=0} + and cm = {n=1 ; ni=0} + and _,(cml,cleft) = opt_count false left + and _,(cmr,cright) = opt_count false right in + add_test ci cleft ; + add_test ci cright ; + if less_tests cml cmr then + add_test cm cmr else - let rlow = ref (-1) and rhigh = ref (-1) - and best_cost= ref (too_much,too_much) in - for i=1 to lcases-2 do - for j=i to lcases-2 do - let low, high, inside, outside = coupe_inter i j cases in + add_test cm cml ; + Sep m,(cm, ci) + + and heuristic cases = + let lcases = Array.length cases in + + let sep,csep = divide cases + + and inter,cinter = + if !ok_inter then begin + let _,_,act0 = cases.(0) + and _,_,act1 = cases.(lcases-1) in + if act0 = act1 then begin + let low, high, inside, outside = coupe_inter 1 (lcases-2) cases in let _,(cmi,cinside) = opt_count false inside and _,(cmo,coutside) = opt_count false outside and cmij = {n=1 ; ni=(if low=high then 0 else 1)} @@ -533,47 +452,128 @@ and enum top cases = add_test cmij cmo else add_test cmij cmi ; - if less2tests (cmij,cij) !best_cost then begin - rlow := i ; - rhigh := j ; - best_cost := (cmij,cij) - end - done + Inter (1,lcases-2),(cmij,cij) + end else + Inter (-1,-1),(too_much, too_much) + end else + Inter (-1,-1),(too_much, too_much) in + if less2tests csep cinter then + sep,csep + else + inter,cinter + + + and enum top cases = + let lcases = Array.length cases in + let lim, with_sep = + let best = ref (-1) and best_cost = ref (too_much,too_much) in + + for i = 1 to lcases-(1) do + let _,left,right = coupe cases i in + let ci = {n=1 ; ni=0} + and cm = {n=1 ; ni=0} + and _,(cml,cleft) = opt_count false left + and _,(cmr,cright) = opt_count false right in + add_test ci cleft ; + add_test ci cright ; + if less_tests cml cmr then + add_test cm cmr + else + add_test cm cml ; + + if + less2tests (cm,ci) !best_cost + then begin + if top then + Printf.fprintf stderr "Get it: %d\n" i ; + best := i ; + best_cost := (cm,ci) + end done ; - !rlow, !rhigh, !best_cost in - let r = ref (Inter (ilow,ihigh)) and rc = ref with_inter in - if less2tests with_sep !rc then begin - r := Sep lim ; rc := with_sep - end ; - !r, !rc - - let make_if_test test arg i ifso ifnot = - Arg.make_if - (Arg.make_prim test [arg ; Arg.make_const i]) - ifso ifnot - - let make_if_lt arg i ifso ifnot = match i with + !best, !best_cost in + + let ilow, ihigh, with_inter = + if not !ok_inter then + let rlow = ref (-1) and rhigh = ref (-1) + and best_cost= ref (too_much,too_much) in + for i=1 to lcases-2 do + let low, high, inside, outside = coupe_inter i i cases in + if low=high then begin + let _,(cmi,cinside) = opt_count false inside + and _,(cmo,coutside) = opt_count false outside + and cmij = {n=1 ; ni=0} + and cij = {n=1 ; ni=0} in + add_test cij cinside ; + add_test cij coutside ; + if less_tests cmi cmo then + add_test cmij cmo + else + add_test cmij cmi ; + if less2tests (cmij,cij) !best_cost then begin + rlow := i ; + rhigh := i ; + best_cost := (cmij,cij) + end + end + done ; + !rlow, !rhigh, !best_cost + else + let rlow = ref (-1) and rhigh = ref (-1) + and best_cost= ref (too_much,too_much) in + for i=1 to lcases-2 do + for j=i to lcases-2 do + let low, high, inside, outside = coupe_inter i j cases in + let _,(cmi,cinside) = opt_count false inside + and _,(cmo,coutside) = opt_count false outside + and cmij = {n=1 ; ni=(if low=high then 0 else 1)} + and cij = {n=1 ; ni=(if low=high then 0 else 1)} in + add_test cij cinside ; + add_test cij coutside ; + if less_tests cmi cmo then + add_test cmij cmo + else + add_test cmij cmi ; + if less2tests (cmij,cij) !best_cost then begin + rlow := i ; + rhigh := j ; + best_cost := (cmij,cij) + end + done + done ; + !rlow, !rhigh, !best_cost in + let r = ref (Inter (ilow,ihigh)) and rc = ref with_inter in + if less2tests with_sep !rc then begin + r := Sep lim ; rc := with_sep + end ; + !r, !rc + + let make_if_test test arg i ifso ifnot = + Arg.make_if + (Arg.make_prim test [arg ; Arg.make_const i]) + ifso ifnot + + let make_if_lt arg i ifso ifnot = match i with | 1 -> make_if_test Arg.leint arg 0 ifso ifnot | _ -> make_if_test Arg.ltint arg i ifso ifnot - and make_if_ge arg i ifso ifnot = match i with + and make_if_ge arg i ifso ifnot = match i with | 1 -> make_if_test Arg.gtint arg 0 ifso ifnot | _ -> make_if_test Arg.geint arg i ifso ifnot - and make_if_eq arg i ifso ifnot = - make_if_test Arg.eqint arg i ifso ifnot + and make_if_eq arg i ifso ifnot = + make_if_test Arg.eqint arg i ifso ifnot - and make_if_ne arg i ifso ifnot = - make_if_test Arg.neint arg i ifso ifnot + and make_if_ne arg i ifso ifnot = + make_if_test Arg.neint arg i ifso ifnot - let do_make_if_out h arg ifso ifno = - Arg.make_if (Arg.make_isout h arg) ifso ifno + let do_make_if_out h arg ifso ifno = + Arg.make_if (Arg.make_isout h arg) ifso ifno - let make_if_out ctx l d mk_ifso mk_ifno = match l with + let make_if_out ctx l d mk_ifso mk_ifno = match l with | 0 -> do_make_if_out (Arg.make_const d) ctx.arg (mk_ifso ctx) (mk_ifno ctx) @@ -581,14 +581,14 @@ and enum top cases = Arg.bind (Arg.make_offset ctx.arg (-l)) (fun arg -> - let ctx = {off= (-l+ctx.off) ; arg=arg} in - do_make_if_out - (Arg.make_const d) arg (mk_ifso ctx) (mk_ifno ctx)) + let ctx = {off= (-l+ctx.off) ; arg=arg} in + do_make_if_out + (Arg.make_const d) arg (mk_ifso ctx) (mk_ifno ctx)) - let do_make_if_in h arg ifso ifno = - Arg.make_if (Arg.make_isin h arg) ifso ifno + let do_make_if_in h arg ifso ifno = + Arg.make_if (Arg.make_isin h arg) ifso ifno - let make_if_in ctx l d mk_ifso mk_ifno = match l with + let make_if_in ctx l d mk_ifso mk_ifno = match l with | 0 -> do_make_if_in (Arg.make_const d) ctx.arg (mk_ifso ctx) (mk_ifno ctx) @@ -596,282 +596,282 @@ and enum top cases = Arg.bind (Arg.make_offset ctx.arg (-l)) (fun arg -> - let ctx = {off= (-l+ctx.off) ; arg=arg} in - do_make_if_in - (Arg.make_const d) arg (mk_ifso ctx) (mk_ifno ctx)) + let ctx = {off= (-l+ctx.off) ; arg=arg} in + do_make_if_in + (Arg.make_const d) arg (mk_ifso ctx) (mk_ifno ctx)) - let rec c_test ctx ({cases=cases ; actions=actions} as s) = - let lcases = Array.length cases in - assert(lcases > 0) ; - if lcases = 1 then - actions.(get_act cases 0) ctx + let rec c_test ctx ({cases=cases ; actions=actions} as s) = + let lcases = Array.length cases in + assert(lcases > 0) ; + if lcases = 1 then + actions.(get_act cases 0) ctx - else begin + else begin - let w,_c = opt_count false cases in + let w,_c = opt_count false cases in (* Printf.fprintf stderr "off=%d tactic=%a for %a\n" ctx.off pret w pcases cases ; *) - match w with - | No -> actions.(get_act cases 0) ctx - | Inter (i,j) -> - let low,high,inside, outside = coupe_inter i j cases in - let _,(cinside,_) = opt_count false inside - and _,(coutside,_) = opt_count false outside in -(* Costs are retrieved to put the code with more remaining tests - in the privileged (positive) branch of ``if'' *) - if low=high then begin - if less_tests coutside cinside then - make_if_eq - ctx.arg - (low+ctx.off) - (c_test ctx {s with cases=inside}) - (c_test ctx {s with cases=outside}) - else + match w with + | No -> actions.(get_act cases 0) ctx + | Inter (i,j) -> + let low,high,inside, outside = coupe_inter i j cases in + let _,(cinside,_) = opt_count false inside + and _,(coutside,_) = opt_count false outside in + (* Costs are retrieved to put the code with more remaining tests + in the privileged (positive) branch of ``if'' *) + if low=high then begin + if less_tests coutside cinside then + make_if_eq + ctx.arg + (low+ctx.off) + (c_test ctx {s with cases=inside}) + (c_test ctx {s with cases=outside}) + else + make_if_ne + ctx.arg + (low+ctx.off) + (c_test ctx {s with cases=outside}) + (c_test ctx {s with cases=inside}) + end else begin + if less_tests coutside cinside then + make_if_in + ctx + (low+ctx.off) + (high-low) + (fun ctx -> c_test ctx {s with cases=inside}) + (fun ctx -> c_test ctx {s with cases=outside}) + else + make_if_out + ctx + (low+ctx.off) + (high-low) + (fun ctx -> c_test ctx {s with cases=outside}) + (fun ctx -> c_test ctx {s with cases=inside}) + end + | Sep i -> + let lim,left,right = coupe cases i in + let _,(cleft,_) = opt_count false left + and _,(cright,_) = opt_count false right in + let left = {s with cases=left} + and right = {s with cases=right} in + + if i=1 && (lim+ctx.off)=1 && get_low cases 0+ctx.off=0 then make_if_ne - ctx.arg - (low+ctx.off) - (c_test ctx {s with cases=outside}) - (c_test ctx {s with cases=inside}) - end else begin - if less_tests coutside cinside then - make_if_in - ctx - (low+ctx.off) - (high-low) - (fun ctx -> c_test ctx {s with cases=inside}) - (fun ctx -> c_test ctx {s with cases=outside}) + ctx.arg 0 + (c_test ctx right) (c_test ctx left) + else if less_tests cright cleft then + make_if_lt + ctx.arg (lim+ctx.off) + (c_test ctx left) (c_test ctx right) else - make_if_out - ctx - (low+ctx.off) - (high-low) - (fun ctx -> c_test ctx {s with cases=outside}) - (fun ctx -> c_test ctx {s with cases=inside}) - end - | Sep i -> - let lim,left,right = coupe cases i in - let _,(cleft,_) = opt_count false left - and _,(cright,_) = opt_count false right in - let left = {s with cases=left} - and right = {s with cases=right} in - - if i=1 && (lim+ctx.off)=1 && get_low cases 0+ctx.off=0 then - make_if_ne - ctx.arg 0 - (c_test ctx right) (c_test ctx left) - else if less_tests cright cleft then - make_if_lt - ctx.arg (lim+ctx.off) - (c_test ctx left) (c_test ctx right) - else - make_if_ge - ctx.arg (lim+ctx.off) - (c_test ctx right) (c_test ctx left) - - end - - -(* Minimal density of switches *) -let theta = ref 0.33333 - -(* Minimal number of tests to make a switch *) -let switch_min = ref 3 - -(* Particular case 0, 1, 2 *) -let particular_case cases i j = - j-i = 2 && - (let l1,_h1,act1 = cases.(i) - and l2,_h2,_act2 = cases.(i+1) - and l3,h3,act3 = cases.(i+2) in - l1+1=l2 && l2+1=l3 && l3=h3 && - act1 <> act3) - -let approx_count cases i j = - let l = j-i+1 in - if l < !cut then - let _,(_,{n=ntests}) = opt_count false (Array.sub cases i l) in - ntests - else - l-1 - -(* Sends back a boolean that says whether is switch is worth or not *) - -let dense {cases} i j = - if i=j then true - else - let l,_,_ = cases.(i) - and _,h,_ = cases.(j) in - let ntests = approx_count cases i j in + make_if_ge + ctx.arg (lim+ctx.off) + (c_test ctx right) (c_test ctx left) + + end + + + (* Minimal density of switches *) + let theta = ref 0.33333 + + (* Minimal number of tests to make a switch *) + let switch_min = ref 3 + + (* Particular case 0, 1, 2 *) + let particular_case cases i j = + j-i = 2 && + (let l1,_h1,act1 = cases.(i) + and l2,_h2,_act2 = cases.(i+1) + and l3,h3,act3 = cases.(i+2) in + l1+1=l2 && l2+1=l3 && l3=h3 && + act1 <> act3) + + let approx_count cases i j = + let l = j-i+1 in + if l < !cut then + let _,(_,{n=ntests}) = opt_count false (Array.sub cases i l) in + ntests + else + l-1 + + (* Sends back a boolean that says whether is switch is worth or not *) + + let dense {cases} i j = + if i=j then true + else + let l,_,_ = cases.(i) + and _,h,_ = cases.(j) in + let ntests = approx_count cases i j in (* (ntests+1) >= theta * (h-l+1) *) - particular_case cases i j || - (ntests >= !switch_min && - float_of_int ntests +. 1.0 >= - !theta *. (float_of_int h -. float_of_int l +. 1.0)) - -(* Compute clusters by dynamic programming - Adaptation of the correction to Bernstein - ``Correction to `Producing Good Code for the Case Statement' '' - S.K. Kannan and T.A. Proebsting - Software Practice and Experience Vol. 24(2) 233 (Feb 1994) -*) + particular_case cases i j || + (ntests >= !switch_min && + float_of_int ntests +. 1.0 >= + !theta *. (float_of_int h -. float_of_int l +. 1.0)) + + (* Compute clusters by dynamic programming + Adaptation of the correction to Bernstein + ``Correction to `Producing Good Code for the Case Statement' '' + S.K. Kannan and T.A. Proebsting + Software Practice and Experience Vol. 24(2) 233 (Feb 1994) + *) -let comp_clusters s = - let len = Array.length s.cases in - let min_clusters = Array.make len max_int - and k = Array.make len 0 in - let get_min i = if i < 0 then 0 else min_clusters.(i) in - - for i = 0 to len-1 do - for j = 0 to i do - if - dense s j i && - get_min (j-1) + 1 < min_clusters.(i) - then begin - k.(i) <- j ; - min_clusters.(i) <- get_min (j-1) + 1 - end + let comp_clusters s = + let len = Array.length s.cases in + let min_clusters = Array.make len max_int + and k = Array.make len 0 in + let get_min i = if i < 0 then 0 else min_clusters.(i) in + + for i = 0 to len-1 do + for j = 0 to i do + if + dense s j i && + get_min (j-1) + 1 < min_clusters.(i) + then begin + k.(i) <- j ; + min_clusters.(i) <- get_min (j-1) + 1 + end + done ; done ; - done ; - min_clusters.(len-1),k - -(* Assume j > i *) -let make_switch loc {cases=cases ; actions=actions} i j = - let ll,_,_ = cases.(i) - and _,hh,_ = cases.(j) in - let tbl = Array.make (hh-ll+1) 0 - and t = Hashtbl.create 17 - and index = ref 0 in - let get_index act = - try - Hashtbl.find t act - with - | Not_found -> - let i = !index in - incr index ; - Hashtbl.add t act i ; - i in - - for k=i to j do - let l,h,act = cases.(k) in - let index = get_index act in - for kk=l-ll to h-ll do - tbl.(kk) <- index - done - done ; - let acts = Array.make !index actions.(0) in - Hashtbl.iter - (fun act i -> acts.(i) <- actions.(act)) - t ; - (fun ctx -> - match -ll-ctx.off with - | 0 -> Arg.make_switch loc ctx.arg tbl acts - | _ -> - Arg.bind - (Arg.make_offset ctx.arg (-ll-ctx.off)) - (fun arg -> Arg.make_switch loc arg tbl acts)) - - -let make_clusters loc ({cases=cases ; actions=actions} as s) n_clusters k = - let len = Array.length cases in - let r = Array.make n_clusters (0,0,0) - and t = Hashtbl.create 17 - and index = ref 0 - and bidon = ref (Array.length actions) in - let get_index act = - try - let i,_ = Hashtbl.find t act in - i - with - | Not_found -> - let i = !index in - incr index ; - Hashtbl.add - t act - (i,(fun _ -> actions.(act))) ; + min_clusters.(len-1),k + + (* Assume j > i *) + let make_switch loc {cases=cases ; actions=actions} i j = + let ll,_,_ = cases.(i) + and _,hh,_ = cases.(j) in + let tbl = Array.make (hh-ll+1) 0 + and t = Hashtbl.create 17 + and index = ref 0 in + let get_index act = + try + Hashtbl.find t act + with + | Not_found -> + let i = !index in + incr index ; + Hashtbl.add t act i ; + i in + + for k=i to j do + let l,h,act = cases.(k) in + let index = get_index act in + for kk=l-ll to h-ll do + tbl.(kk) <- index + done + done ; + let acts = Array.make !index actions.(0) in + Hashtbl.iter + (fun act i -> acts.(i) <- actions.(act)) + t ; + (fun ctx -> + match -ll-ctx.off with + | 0 -> Arg.make_switch loc ctx.arg tbl acts + | _ -> + Arg.bind + (Arg.make_offset ctx.arg (-ll-ctx.off)) + (fun arg -> Arg.make_switch loc arg tbl acts)) + + + let make_clusters loc ({cases=cases ; actions=actions} as s) n_clusters k = + let len = Array.length cases in + let r = Array.make n_clusters (0,0,0) + and t = Hashtbl.create 17 + and index = ref 0 + and bidon = ref (Array.length actions) in + let get_index act = + try + let i,_ = Hashtbl.find t act in i - and add_index act = - let i = !index in - incr index ; - incr bidon ; - Hashtbl.add t !bidon (i,act) ; - i in - - let rec zyva j ir = - let i = k.(j) in - begin if i=j then - let l,h,act = cases.(i) in - r.(ir) <- (l,h,get_index act) - else (* assert i < j *) - let l,_,_ = cases.(i) - and _,h,_ = cases.(j) in - r.(ir) <- (l,h,add_index (make_switch loc s i j)) - end ; - if i > 0 then zyva (i-1) (ir-1) in + with + | Not_found -> + let i = !index in + incr index ; + Hashtbl.add + t act + (i,(fun _ -> actions.(act))) ; + i + and add_index act = + let i = !index in + incr index ; + incr bidon ; + Hashtbl.add t !bidon (i,act) ; + i in + + let rec zyva j ir = + let i = k.(j) in + begin if i=j then + let l,h,act = cases.(i) in + r.(ir) <- (l,h,get_index act) + else (* assert i < j *) + let l,_,_ = cases.(i) + and _,h,_ = cases.(j) in + r.(ir) <- (l,h,add_index (make_switch loc s i j)) + end ; + if i > 0 then zyva (i-1) (ir-1) in - zyva (len-1) (n_clusters-1) ; - let acts = Array.make !index (fun _ -> assert false) in - Hashtbl.iter (fun _ (i,act) -> acts.(i) <- act) t ; - {cases = r ; actions = acts} -;; + zyva (len-1) (n_clusters-1) ; + let acts = Array.make !index (fun _ -> assert false) in + Hashtbl.iter (fun _ (i,act) -> acts.(i) <- act) t ; + {cases = r ; actions = acts} + ;; -let do_zyva loc (low,high) arg cases actions = - let old_ok = !ok_inter in - ok_inter := (abs low <= inter_limit && abs high <= inter_limit) ; - if !ok_inter <> old_ok then Hashtbl.clear t ; + let do_zyva loc (low,high) arg cases actions = + let old_ok = !ok_inter in + ok_inter := (abs low <= inter_limit && abs high <= inter_limit) ; + if !ok_inter <> old_ok then Hashtbl.clear t ; - let s = {cases=cases ; actions=actions} in + let s = {cases=cases ; actions=actions} in (* Printf.eprintf "ZYVA: %B [low=%i,high=%i]\n" !ok_inter low high ; pcases stderr cases ; prerr_endline "" ; *) - let n_clusters,k = comp_clusters s in - let clusters = make_clusters loc s n_clusters k in - c_test {arg=arg ; off=0} clusters - -let abstract_shared actions = - let handlers = ref (fun x -> x) in - let actions = - Array.map - (fun act -> match act with - | Single act -> act - | Shared act -> - let i,h = Arg.make_catch act in - let oh = !handlers in - handlers := (fun act -> h (oh act)) ; - Arg.make_exit i) - actions in - !handlers,actions - -let zyva loc lh arg cases actions = - assert (Array.length cases > 0) ; - let actions = actions.act_get_shared () in - let hs,actions = abstract_shared actions in - hs (do_zyva loc lh arg cases actions) - -and test_sequence arg cases actions = - assert (Array.length cases > 0) ; - let actions = actions.act_get_shared () in - let hs,actions = abstract_shared actions in - let old_ok = !ok_inter in - ok_inter := false ; - if !ok_inter <> old_ok then Hashtbl.clear t ; - let s = - {cases=cases ; - actions=Array.map (fun act -> (fun _ -> act)) actions} in + let n_clusters,k = comp_clusters s in + let clusters = make_clusters loc s n_clusters k in + c_test {arg=arg ; off=0} clusters + + let abstract_shared actions = + let handlers = ref (fun x -> x) in + let actions = + Array.map + (fun act -> match act with + | Single act -> act + | Shared act -> + let i,h = Arg.make_catch act in + let oh = !handlers in + handlers := (fun act -> h (oh act)) ; + Arg.make_exit i) + actions in + !handlers,actions + + let zyva loc lh arg cases actions = + assert (Array.length cases > 0) ; + let actions = actions.act_get_shared () in + let hs,actions = abstract_shared actions in + hs (do_zyva loc lh arg cases actions) + + and test_sequence arg cases actions = + assert (Array.length cases > 0) ; + let actions = actions.act_get_shared () in + let hs,actions = abstract_shared actions in + let old_ok = !ok_inter in + ok_inter := false ; + if !ok_inter <> old_ok then Hashtbl.clear t ; + let s = + {cases=cases ; + actions=Array.map (fun act -> (fun _ -> act)) actions} in (* Printf.eprintf "SEQUENCE: %B\n" !ok_inter ; pcases stderr cases ; prerr_endline "" ; *) - hs (c_test {arg=arg ; off=0} s) -;; + hs (c_test {arg=arg ; off=0} s) + ;; end diff --git a/bytecomp/symtable.ml b/bytecomp/symtable.ml index 3af60fb0..8886ab47 100644 --- a/bytecomp/symtable.ml +++ b/bytecomp/symtable.ml @@ -13,6 +13,8 @@ (* *) (**************************************************************************) +[@@@ocaml.warning "-40"] + (* To assign numbers to globals and primitives *) open Misc @@ -20,6 +22,8 @@ open Asttypes open Lambda open Cmo_format +module String = Misc.Stdlib.String + (* Functions for batch linking *) type error = @@ -30,73 +34,84 @@ type error = exception Error of error -let empty_numtable = { num_cnt = 0; num_tbl = Tbl.empty } +module Num_tbl (M : Map.S) = struct -let find_numtable nt key = - Tbl.find key nt.num_tbl + type t = { + cnt: int; (* The next number *) + tbl: int M.t ; (* The table of already numbered objects *) + } -let enter_numtable nt key = - let n = !nt.num_cnt in - nt := { num_cnt = n + 1; num_tbl = Tbl.add key n !nt.num_tbl }; - n + let empty = { cnt = 0; tbl = M.empty } -let incr_numtable nt = - let n = !nt.num_cnt in - nt := { num_cnt = n + 1; num_tbl = !nt.num_tbl }; - n + let find nt key = + M.find key nt.tbl + + let enter nt key = + let n = !nt.cnt in + nt := { cnt = n + 1; tbl = M.add key n !nt.tbl }; + n + + let incr nt = + let n = !nt.cnt in + nt := { cnt = n + 1; tbl = !nt.tbl }; + n + +end +module GlobalMap = Num_tbl(Ident.Map) +module PrimMap = Num_tbl(Misc.Stdlib.String.Map) (* Global variables *) -let global_table = ref(empty_numtable : Ident.t numtable) +let global_table = ref GlobalMap.empty and literal_table = ref([] : (int * structured_constant) list) let is_global_defined id = - Tbl.mem id (!global_table).num_tbl + Ident.Map.mem id (!global_table).tbl let slot_for_getglobal id = try - find_numtable !global_table id + GlobalMap.find !global_table id with Not_found -> raise(Error(Undefined_global(Ident.name id))) let slot_for_setglobal id = - enter_numtable global_table id + GlobalMap.enter global_table id let slot_for_literal cst = - let n = incr_numtable global_table in + let n = GlobalMap.incr global_table in literal_table := (n, cst) :: !literal_table; n (* The C primitives *) -let c_prim_table = ref(empty_numtable : string numtable) +let c_prim_table = ref PrimMap.empty let set_prim_table name = - ignore(enter_numtable c_prim_table name) + ignore(PrimMap.enter c_prim_table name) -let num_of_prim name = +let of_prim name = try - find_numtable !c_prim_table name + PrimMap.find !c_prim_table name with Not_found -> if !Clflags.custom_runtime || Config.host <> Config.target || !Clflags.no_check_prims then - enter_numtable c_prim_table name + PrimMap.enter c_prim_table name else begin let symb = try Dll.find_primitive name with Not_found -> raise(Error(Unavailable_primitive name)) in - let num = enter_numtable c_prim_table name in + let num = PrimMap.enter c_prim_table name in Dll.synchronize_primitive num symb; num end let require_primitive name = - if name.[0] <> '%' then ignore(num_of_prim name) + if name.[0] <> '%' then ignore(of_prim name) let all_primitives () = - let prim = Array.make !c_prim_table.num_cnt "" in - Tbl.iter (fun name number -> prim.(number) <- name) !c_prim_table.num_tbl; + let prim = Array.make !c_prim_table.cnt "" in + String.Map.iter (fun name number -> prim.(number) <- name) !c_prim_table.tbl; prim let data_primitive_names () = @@ -147,59 +162,55 @@ let init () = literal_table := (c, cst) :: !literal_table) Runtimedef.builtin_exceptions; (* Initialize the known C primitives *) - if String.length !Clflags.use_prims > 0 then begin - let ic = open_in !Clflags.use_prims in - try - while true do - set_prim_table (input_line ic) - done - with End_of_file -> close_in ic - | x -> close_in ic; raise x - end else if String.length !Clflags.use_runtime > 0 then begin + let set_prim_table_from_file primfile = + let ic = open_in primfile in + Misc.try_finally + ~always:(fun () -> close_in ic) + (fun () -> + try + while true do + set_prim_table (input_line ic) + done + with End_of_file -> () + ) + in + if String.length !Clflags.use_prims > 0 then + set_prim_table_from_file !Clflags.use_prims + else if String.length !Clflags.use_runtime > 0 then begin let primfile = Filename.temp_file "camlprims" "" in - try - if Sys.command(Printf.sprintf "%s -p > %s" - !Clflags.use_runtime primfile) <> 0 - then raise(Error(Wrong_vm !Clflags.use_runtime)); - let ic = open_in primfile in - try - while true do - set_prim_table (input_line ic) - done - with End_of_file -> close_in ic; remove_file primfile - | x -> close_in ic; raise x - with x -> remove_file primfile; raise x + Misc.try_finally + ~always:(fun () -> remove_file primfile) + (fun () -> + if Sys.command(Printf.sprintf "%s -p > %s" + !Clflags.use_runtime primfile) <> 0 + then raise(Error(Wrong_vm !Clflags.use_runtime)); + set_prim_table_from_file primfile + ) end else begin Array.iter set_prim_table Runtimedef.builtin_primitives end (* Relocate a block of object bytecode *) -(* Must use the unsafe String.set here because the block may be - a "fake" string as returned by Meta.static_alloc. *) +let patch_int buff pos n = + LongString.set buff pos (Char.unsafe_chr n); + LongString.set buff (pos + 1) (Char.unsafe_chr (n asr 8)); + LongString.set buff (pos + 2) (Char.unsafe_chr (n asr 16)); + LongString.set buff (pos + 3) (Char.unsafe_chr (n asr 24)) -let gen_patch_int str_set buff pos n = - str_set buff pos (Char.unsafe_chr n); - str_set buff (pos + 1) (Char.unsafe_chr (n asr 8)); - str_set buff (pos + 2) (Char.unsafe_chr (n asr 16)); - str_set buff (pos + 3) (Char.unsafe_chr (n asr 24)) - -let gen_patch_object str_set buff patchlist = +let patch_object buff patchlist = List.iter (function (Reloc_literal sc, pos) -> - gen_patch_int str_set buff pos (slot_for_literal sc) + patch_int buff pos (slot_for_literal sc) | (Reloc_getglobal id, pos) -> - gen_patch_int str_set buff pos (slot_for_getglobal id) + patch_int buff pos (slot_for_getglobal id) | (Reloc_setglobal id, pos) -> - gen_patch_int str_set buff pos (slot_for_setglobal id) + patch_int buff pos (slot_for_setglobal id) | (Reloc_primitive name, pos) -> - gen_patch_int str_set buff pos (num_of_prim name)) + patch_int buff pos (of_prim name)) patchlist -let patch_object = gen_patch_object Bytes.unsafe_set -let ls_patch_object = gen_patch_object LongString.set - (* Translate structured constants *) let rec transl_const = function @@ -228,7 +239,7 @@ let rec transl_const = function (* Build the initial table of globals *) let initial_global_table () = - let glob = Array.make !global_table.num_cnt (Obj.repr 0) in + let glob = Array.make !global_table.cnt (Obj.repr 0) in List.iter (fun (slot, cst) -> glob.(slot) <- transl_const cst) !literal_table; @@ -248,7 +259,7 @@ let data_global_map () = (* Update the in-core table of globals *) let update_global_table () = - let ng = !global_table.num_cnt in + let ng = !global_table.cnt in if ng > Array.length(Meta.global_data()) then Meta.realloc_global_data ng; let glob = Meta.global_data() in List.iter @@ -287,10 +298,10 @@ let init_toplevel () = try let sect = read_sections () in (* Locations of globals *) - global_table := (Obj.magic (sect.read_struct "SYMB") : Ident.t numtable); + global_table := (Obj.magic (sect.read_struct "SYMB") : GlobalMap.t); (* Primitives *) let prims = sect.read_string "PRIM" in - c_prim_table := empty_numtable; + c_prim_table := PrimMap.empty; let pos = ref 0 in while !pos < String.length prims do let i = String.index_from prims !pos '\000' in @@ -323,15 +334,25 @@ let assign_global_value id v = (* Check that all globals referenced in the given patch list have been initialized already *) +let defined_globals patchlist = + List.fold_left (fun accu rel -> + match rel with + | (Reloc_setglobal id, _pos) -> id :: accu + | _ -> accu) + [] + patchlist + +let required_globals patchlist = + List.fold_left (fun accu rel -> + match rel with + | (Reloc_getglobal id, _pos) -> id :: accu + | _ -> accu) + [] + patchlist + let check_global_initialized patchlist = (* First determine the globals we will define *) - let defined_globals = - List.fold_left - (fun accu rel -> - match rel with - (Reloc_setglobal id, _pos) -> id :: accu - | _ -> accu) - [] patchlist in + let defined_globals = defined_globals patchlist in (* Then check that all referenced, not defined globals have a value *) let check_reference = function (Reloc_getglobal id, _pos) -> @@ -343,28 +364,37 @@ let check_global_initialized patchlist = (* Save and restore the current state *) -type global_map = Ident.t numtable +type global_map = GlobalMap.t let current_state () = !global_table let restore_state st = global_table := st -let hide_additions st = - if st.num_cnt > !global_table.num_cnt then +let hide_additions (st : global_map) = + if st.cnt > !global_table.cnt then fatal_error "Symtable.hide_additions"; global_table := - { num_cnt = !global_table.num_cnt; - num_tbl = st.num_tbl } + {GlobalMap. + cnt = !global_table.cnt; + tbl = st.tbl } (* "Filter" the global map according to some predicate. Used to expunge the global map for the toplevel. *) -let filter_global_map p gmap = - let newtbl = ref Tbl.empty in - Tbl.iter - (fun id num -> if p id then newtbl := Tbl.add id num !newtbl) - gmap.num_tbl; - {num_cnt = gmap.num_cnt; num_tbl = !newtbl} +let filter_global_map p (gmap : global_map) = + let newtbl = ref Ident.Map.empty in + Ident.Map.iter + (fun id num -> if p id then newtbl := Ident.Map.add id num !newtbl) + gmap.tbl; + {GlobalMap. cnt = gmap.cnt; tbl = !newtbl} + +let iter_global_map f (gmap : global_map) = + Ident.Map.iter f gmap.tbl + +let is_defined_in_global_map (gmap : global_map) id = + Ident.Map.mem id gmap.tbl + +let empty_global_map = GlobalMap.empty (* Error report *) @@ -388,6 +418,6 @@ let () = ) let reset () = - global_table := empty_numtable; + global_table := GlobalMap.empty; literal_table := []; - c_prim_table := empty_numtable + c_prim_table := PrimMap.empty diff --git a/bytecomp/symtable.mli b/bytecomp/symtable.mli index 22dec581..782a6086 100644 --- a/bytecomp/symtable.mli +++ b/bytecomp/symtable.mli @@ -20,8 +20,7 @@ open Cmo_format (* Functions for batch linking *) val init: unit -> unit -val patch_object: bytes -> (reloc_info * int) list -> unit -val ls_patch_object: Misc.LongString.t -> (reloc_info * int) list -> unit +val patch_object: Misc.LongString.t -> (reloc_info * int) list -> unit val require_primitive: string -> unit val initial_global_table: unit -> Obj.t array val output_global_map: out_channel -> unit @@ -40,13 +39,18 @@ val is_global_defined: Ident.t -> bool val assign_global_value: Ident.t -> Obj.t -> unit val get_global_position: Ident.t -> int val check_global_initialized: (reloc_info * int) list -> unit +val defined_globals: (reloc_info * int) list -> Ident.t list +val required_globals: (reloc_info * int) list -> Ident.t list type global_map +val empty_global_map: global_map val current_state: unit -> global_map val restore_state: global_map -> unit val hide_additions: global_map -> unit val filter_global_map: (Ident.t -> bool) -> global_map -> global_map +val iter_global_map : (Ident.t -> int -> unit) -> global_map -> unit +val is_defined_in_global_map: global_map -> Ident.t -> bool (* Error report *) diff --git a/bytecomp/translattribute.ml b/bytecomp/translattribute.ml index 8881dc77..1520a3b4 100644 --- a/bytecomp/translattribute.ml +++ b/bytecomp/translattribute.ml @@ -18,31 +18,35 @@ open Lambda open Location let is_inline_attribute = function - | {txt=("inline"|"ocaml.inline")}, _ -> true + | {txt=("inline"|"ocaml.inline")} -> true | _ -> false let is_inlined_attribute = function - | {txt=("inlined"|"ocaml.inlined")}, _ -> true - | {txt=("unrolled"|"ocaml.unrolled")}, _ when Config.flambda -> true + | {txt=("inlined"|"ocaml.inlined")} -> true + | {txt=("unrolled"|"ocaml.unrolled")} when Config.flambda -> true | _ -> false let is_specialise_attribute = function - | {txt=("specialise"|"ocaml.specialise")}, _ when Config.flambda -> true + | {txt=("specialise"|"ocaml.specialise")} when Config.flambda -> true | _ -> false let is_specialised_attribute = function - | {txt=("specialised"|"ocaml.specialised")}, _ when Config.flambda -> true + | {txt=("specialised"|"ocaml.specialised")} when Config.flambda -> true + | _ -> false + +let is_local_attribute = function + | {txt=("local"|"ocaml.local")} -> true | _ -> false let find_attribute p attributes = let inline_attribute, other_attributes = - List.partition p attributes + List.partition (fun a -> p a.Parsetree.attr_name) attributes in let attr = match inline_attribute with | [] -> None | [attr] -> Some attr - | _ :: ({txt;loc}, _) :: _ -> + | _ :: {Parsetree.attr_name = {txt;loc}; _} :: _ -> Location.prerr_warning loc (Warnings.Duplicated_attribute txt); None in @@ -53,10 +57,41 @@ let is_unrolled = function | {txt="inline"|"ocaml.inline"|"inlined"|"ocaml.inlined"} -> false | _ -> assert false +let get_id_payload = + let open Parsetree in + function + | PStr [] -> Some "" + | PStr [{pstr_desc = Pstr_eval ({pexp_desc},[])}] -> + begin match pexp_desc with + | Pexp_ident { txt = Longident.Lident id } -> Some id + | _ -> None + end + | _ -> None + +let parse_id_payload txt loc ~default ~empty cases payload = + let[@local] warn () = + let ( %> ) f g x = g (f x) in + let msg = + cases + |> List.map (fst %> Printf.sprintf "'%s'") + |> String.concat ", " + |> Printf.sprintf "It must be either %s or empty" + in + Location.prerr_warning loc (Warnings.Attribute_payload (txt, msg)); + default + in + match get_id_payload payload with + | Some "" -> empty + | None -> warn () + | Some id -> + match List.assoc_opt id cases with + | Some r -> r + | None -> warn () + let parse_inline_attribute attr = match attr with | None -> Default_inline - | Some ({txt;loc} as id, payload) -> + | Some {Parsetree.attr_name = {txt;loc} as id; attr_payload = payload} -> let open Parsetree in if is_unrolled id then begin (* the 'unrolled' attributes must be used as [@unrolled n]. *) @@ -80,58 +115,42 @@ let parse_inline_attribute attr = | _ -> Location.prerr_warning loc (warning txt); Default_inline - end else begin - (* the 'inline' and 'inlined' attributes can be used as - [@inline], [@inline never] or [@inline always]. - [@inline] is equivalent to [@inline always] *) - let warning txt = - Warnings.Attribute_payload - (txt, "It must be either empty, 'always' or 'never'") - in - match payload with - | PStr [] -> Always_inline - | PStr [{pstr_desc = Pstr_eval ({pexp_desc},[])}] -> begin - match pexp_desc with - | Pexp_ident { txt = Longident.Lident "never" } -> - Never_inline - | Pexp_ident { txt = Longident.Lident "always" } -> - Always_inline - | _ -> - Location.prerr_warning loc (warning txt); - Default_inline - end - | _ -> - Location.prerr_warning loc (warning txt); - Default_inline - end + end else + parse_id_payload txt loc + ~default:Default_inline + ~empty:Always_inline + [ + "never", Never_inline; + "always", Always_inline; + ] + payload let parse_specialise_attribute attr = match attr with | None -> Default_specialise - | Some ({txt; loc}, payload) -> - let open Parsetree in - let warning txt = - Warnings.Attribute_payload - (txt, "It must be either empty, 'always' or 'never'") - in - match payload with - | PStr [] -> Always_specialise - | PStr [{pstr_desc = Pstr_eval ({pexp_desc},[])}] -> begin - (* the 'specialise' and 'specialised' attributes can be used as - [@specialise], [@specialise never] or [@specialise always]. - [@specialise] is equivalent to [@specialise always] *) - match pexp_desc with - | Pexp_ident { txt = Longident.Lident "never" } -> - Never_specialise - | Pexp_ident { txt = Longident.Lident "always" } -> - Always_specialise - | _ -> - Location.prerr_warning loc (warning txt); - Default_specialise - end - | _ -> - Location.prerr_warning loc (warning txt); - Default_specialise + | Some {Parsetree.attr_name = {txt; loc}; attr_payload = payload} -> + parse_id_payload txt loc + ~default:Default_specialise + ~empty:Always_specialise + [ + "never", Never_specialise; + "always", Always_specialise; + ] + payload + +let parse_local_attribute attr = + match attr with + | None -> Default_local + | Some {Parsetree.attr_name = {txt; loc}; attr_payload = payload} -> + parse_id_payload txt loc + ~default:Default_local + ~empty:Always_local + [ + "never", Never_local; + "always", Always_local; + "maybe", Default_local; + ] + payload let get_inline_attribute l = let attr, _ = find_attribute is_inline_attribute l in @@ -141,6 +160,18 @@ let get_specialise_attribute l = let attr, _ = find_attribute is_specialise_attribute l in parse_specialise_attribute attr +let get_local_attribute l = + let attr, _ = find_attribute is_local_attribute l in + parse_local_attribute attr + +let check_local_inline loc attr = + match attr.local, attr.inline with + | Always_local, (Always_inline | Unroll _) -> + Location.prerr_warning loc + (Warnings.Duplicated_attribute "local/inline") + | _ -> + () + let add_inline_attribute expr loc attributes = match expr, get_inline_attribute attributes with | expr, Default_inline -> expr @@ -152,6 +183,7 @@ let add_inline_attribute expr loc attributes = (Warnings.Duplicated_attribute "inline") end; let attr = { attr with inline } in + check_local_inline loc attr; Lfunction { funct with attr = attr } | expr, (Always_inline | Never_inline | Unroll _) -> Location.prerr_warning loc @@ -175,6 +207,24 @@ let add_specialise_attribute expr loc attributes = (Warnings.Misplaced_attribute "specialise"); expr +let add_local_attribute expr loc attributes = + match expr, get_local_attribute attributes with + | expr, Default_local -> expr + | Lfunction({ attr = { stub = false } as attr } as funct), local -> + begin match attr.local with + | Default_local -> () + | Always_local | Never_local -> + Location.prerr_warning loc + (Warnings.Duplicated_attribute "local") + end; + let attr = { attr with local } in + check_local_inline loc attr; + Lfunction { funct with attr } + | expr, (Always_local | Never_local) -> + Location.prerr_warning loc + (Warnings.Misplaced_attribute "local"); + expr + (* Get the [@inlined] attribute payload (or default if not present). It also returns the expression without this attribute. This is used to ensure that this attribute is not misplaced: If it @@ -220,7 +270,7 @@ let get_and_remove_specialised_attribute e = get_inlined_attribute *) let get_tailcall_attribute e = let is_tailcall_attribute = function - | {txt=("tailcall"|"ocaml.tailcall")}, _ -> true + | {Parsetree.attr_name = {txt=("tailcall"|"ocaml.tailcall")}; _} -> true | _ -> false in let tailcalls, exp_attributes = @@ -231,12 +281,12 @@ let get_tailcall_attribute e = | _ :: r -> begin match r with | [] -> () - | ({txt;loc}, _) :: _ -> + | {Parsetree.attr_name = {txt;loc}; _} :: _ -> Location.prerr_warning loc (Warnings.Duplicated_attribute txt) end; true, { e with exp_attributes } -let check_attribute e ({ txt; loc }, _) = +let check_attribute e {Parsetree.attr_name = { txt; loc }; _} = match txt with | "inline" | "ocaml.inline" | "specialise" | "ocaml.specialise" -> begin @@ -254,7 +304,7 @@ let check_attribute e ({ txt; loc }, _) = (Warnings.Misplaced_attribute txt) | _ -> () -let check_attribute_on_module e ({ txt; loc }, _) = +let check_attribute_on_module e {Parsetree.attr_name = { txt; loc }; _} = match txt with | "inline" | "ocaml.inline" -> begin match e.mod_desc with @@ -268,3 +318,15 @@ let check_attribute_on_module e ({ txt; loc }, _) = Location.prerr_warning loc (Warnings.Misplaced_attribute txt) | _ -> () + +let add_function_attributes lam loc attr = + let lam = + add_inline_attribute lam loc attr + in + let lam = + add_specialise_attribute lam loc attr + in + let lam = + add_local_attribute lam loc attr + in + lam diff --git a/bytecomp/translattribute.mli b/bytecomp/translattribute.mli index be855c28..bf22fd1c 100644 --- a/bytecomp/translattribute.mli +++ b/bytecomp/translattribute.mli @@ -15,12 +15,12 @@ val check_attribute : Typedtree.expression - -> string Location.loc * _ + -> Parsetree.attribute -> unit val check_attribute_on_module : Typedtree.module_expr - -> string Location.loc * _ + -> Parsetree.attribute -> unit val add_inline_attribute @@ -43,6 +43,16 @@ val get_specialise_attribute : Parsetree.attributes -> Lambda.specialise_attribute +val add_local_attribute + : Lambda.lambda + -> Location.t + -> Parsetree.attributes + -> Lambda.lambda + +val get_local_attribute + : Parsetree.attributes + -> Lambda.local_attribute + val get_and_remove_inlined_attribute : Typedtree.expression -> Lambda.inline_attribute * Typedtree.expression @@ -58,3 +68,9 @@ val get_and_remove_specialised_attribute val get_tailcall_attribute : Typedtree.expression -> bool * Typedtree.expression + +val add_function_attributes + : Lambda.lambda + -> Location.t + -> Parsetree.attributes + -> Lambda.lambda diff --git a/bytecomp/translclass.ml b/bytecomp/translclass.ml index 4f89faa9..10b09066 100644 --- a/bytecomp/translclass.ml +++ b/bytecomp/translclass.ml @@ -30,10 +30,12 @@ let lfunction params body = if params = [] then body else match body with | Lfunction {kind = Curried; params = params'; body = body'; attr; loc} -> - Lfunction {kind = Curried; params = params @ params'; body = body'; attr; + Lfunction {kind = Curried; params = params @ params'; + return = Pgenval; + body = body'; attr; loc} | _ -> - Lfunction {kind = Curried; params; + Lfunction {kind = Curried; params; return = Pgenval; body; attr = default_function_attribute; loc = Location.none} @@ -96,7 +98,7 @@ let bind_super tbl (vals, meths) cl_init = meths cl_init) let create_object cl obj init = - let obj' = Ident.create "self" in + let obj' = Ident.create_local "self" in let (inh_init, obj_init, has_init) = init obj' in if obj_init = lambda_unit then (inh_init, @@ -117,15 +119,12 @@ let name_pattern default p = match p.pat_desc with | Tpat_var (id, _) -> id | Tpat_alias(_, id, _) -> id - | _ -> Ident.create default - -let normalize_cl_path cl path = - Env.normalize_path (Some cl.cl_loc) cl.cl_env path + | _ -> Ident.create_local default let rec build_object_init cl_table obj params inh_init obj_init cl = match cl.cl_desc with - Tcl_ident ( path, _, _) -> - let obj_init = Ident.create "obj_init" in + Tcl_ident (path, _, _) -> + let obj_init = Ident.create_local "obj_init" in let envs, inh_init = inh_init in let env = match envs with None -> [] @@ -134,8 +133,8 @@ let rec build_object_init cl_table obj params inh_init obj_init cl = [Lvar envs], Location.none)] in - ((envs, (obj_init, normalize_cl_path cl path) - ::inh_init), + let path_lam = transl_class_path cl.cl_loc cl.cl_env path in + ((envs, (path, path_lam, obj_init) :: inh_init), mkappl(Lvar obj_init, env @ [obj])) | Tcl_structure str -> create_object cl_table obj (fun obj -> @@ -167,14 +166,14 @@ let rec build_object_init cl_table obj params inh_init obj_init cl = params obj_init, has_init)) | Tcl_fun (_, pat, vals, cl, partial) -> - let vals = List.map (fun (id, _, e) -> id,e) vals in let (inh_init, obj_init) = build_object_init cl_table obj (vals @ params) inh_init obj_init cl in (inh_init, let build params rem = let param = name_pattern "param" pat in - Lfunction {kind = Curried; params = param::params; + Lfunction {kind = Curried; params = (param, Pgenval)::params; + return = Pgenval; attr = default_function_attribute; loc = pat.pat_loc; body = Matching.for_function @@ -190,30 +189,28 @@ let rec build_object_init cl_table obj params inh_init obj_init cl = in (inh_init, transl_apply obj_init oexprs Location.none) | Tcl_let (rec_flag, defs, vals, cl) -> - let vals = List.map (fun (id, _, e) -> id,e) vals in let (inh_init, obj_init) = build_object_init cl_table obj (vals @ params) inh_init obj_init cl in (inh_init, Translcore.transl_let rec_flag defs obj_init) - | Tcl_open (_, _, _, _, cl) + | Tcl_open (_, cl) | Tcl_constraint (cl, _, _, _, _) -> build_object_init cl_table obj params inh_init obj_init cl let rec build_object_init_0 cl_table params cl copy_env subst_env top ids = match cl.cl_desc with Tcl_let (_rec_flag, _defs, vals, cl) -> - let vals = List.map (fun (id, _, e) -> id,e) vals in build_object_init_0 cl_table (vals@params) cl copy_env subst_env top ids | _ -> - let self = Ident.create "self" in - let env = Ident.create "env" in + let self = Ident.create_local "self" in + let env = Ident.create_local "env" in let obj = if ids = [] then lambda_unit else Lvar self in let envs = if top then None else Some env in let ((_,inh_init), obj_init) = build_object_init cl_table obj params (envs,[]) copy_env cl in let obj_init = - if ids = [] then obj_init else lfunction [self] obj_init in - (inh_init, lfunction [env] (subst_env env inh_init obj_init)) + if ids = [] then obj_init else lfunction [self, Pgenval] obj_init in + (inh_init, lfunction [env, Pgenval] (subst_env env inh_init obj_init)) let bind_method tbl lab id cl_init = @@ -226,7 +223,7 @@ let bind_methods tbl meths vals cl_init = let len = List.length methl and nvals = List.length vals in if len < 2 && nvals = 0 then Meths.fold (bind_method tbl) meths cl_init else if len = 0 && nvals < 2 then transl_vals tbl true Strict vals cl_init else - let ids = Ident.create "ids" in + let ids = Ident.create_local "ids" in let i = ref (len + nvals) in let getter, names = if nvals = 0 then "get_method_labels", [] else @@ -262,18 +259,17 @@ let rec index a = function | b :: l -> if b = a then 0 else 1 + index a l -let bind_id_as_val (id, _, _) = ("", id) +let bind_id_as_val (id, _) = ("", id) let rec build_class_init cla cstr super inh_init cl_init msubst top cl = match cl.cl_desc with - Tcl_ident ( path, _, _) -> + | Tcl_ident _ -> begin match inh_init with - (obj_init, _path')::inh_init -> - let lpath = transl_class_path ~loc:cl.cl_loc cl.cl_env path in + | (_, path_lam, obj_init)::inh_init -> (inh_init, Llet (Strict, Pgenval, obj_init, - mkappl(Lprim(Pfield 1, [lpath], Location.none), Lvar cla :: - if top then [Lprim(Pfield 3, [lpath], Location.none)] + mkappl(Lprim(Pfield 1, [path_lam], Location.none), Lvar cla :: + if top then [Lprim(Pfield 3, [path_lam], Location.none)] else []), bind_super cla super cl_init)) | _ -> @@ -306,7 +302,7 @@ let rec build_class_init cla cstr super inh_init cl_init msubst top cl = let met_code = if !Clflags.native_code && List.length met_code = 1 then (* Force correct naming of method for profiles *) - let met = Ident.create ("method_" ^ name.txt) in + let met = Ident.create_local ("method_" ^ name.txt) in [Llet(Strict, Pgenval, met, List.hd met_code, Lvar met)] else met_code in @@ -351,10 +347,9 @@ let rec build_class_init cla cstr super inh_init cl_init msubst top cl = transl_meth_list concr_meths] in let cl = ignore_cstrs cl in begin match cl.cl_desc, inh_init with - Tcl_ident (path, _, _), (obj_init, path')::inh_init -> - assert (Path.same (normalize_cl_path cl path) path'); - let lpath = transl_normal_path path' in - let inh = Ident.create "inh" + | Tcl_ident (path, _, _), (path', path_lam, obj_init)::inh_init -> + assert (Path.same path path'); + let inh = Ident.create_local "inh" and ofs = List.length vals + 1 and valids, methids = super in let cl_init = @@ -373,7 +368,8 @@ let rec build_class_init cla cstr super inh_init cl_init msubst top cl = (inh_init, Llet (Strict, Pgenval, inh, mkappl(oo_prim "inherits", narrow_args @ - [lpath; Lconst(Const_pointer(if top then 1 else 0))]), + [path_lam; + Lconst(Const_pointer(if top then 1 else 0))]), Llet(StrictOpt, Pgenval, obj_init, lfield inh 0, cl_init))) | _ -> let core cl_init = @@ -387,7 +383,7 @@ let rec build_class_init cla cstr super inh_init cl_init msubst top cl = Lsequence(mkappl (oo_prim "narrow", narrow_args), cl_init)) end - | Tcl_open (_, _, _, _, cl) -> + | Tcl_open (_, cl) -> build_class_init cla cstr super inh_init cl_init msubst top cl let rec build_class_lets cl = @@ -407,7 +403,7 @@ let rec get_class_meths cl = | Tcl_fun (_, _, _, cl, _) | Tcl_let (_, _, _, cl) | Tcl_apply (cl, _) - | Tcl_open (_, _, _, _, cl) + | Tcl_open (_, cl) | Tcl_constraint (cl, _, _, _, _) -> get_class_meths cl (* @@ -422,53 +418,57 @@ let rec transl_class_rebind obj_init cl vf = try if (Env.find_class path cl.cl_env).cty_new = None then raise Exit with Not_found -> raise Exit end; - (normalize_cl_path cl path, obj_init) + let path_lam = transl_class_path cl.cl_loc cl.cl_env path in + (path, path_lam, obj_init) | Tcl_fun (_, pat, _, cl, partial) -> - let path, obj_init = transl_class_rebind obj_init cl vf in + let path, path_lam, obj_init = transl_class_rebind obj_init cl vf in let build params rem = let param = name_pattern "param" pat in - Lfunction {kind = Curried; params = param::params; + Lfunction {kind = Curried; params = (param, Pgenval)::params; + return = Pgenval; attr = default_function_attribute; loc = pat.pat_loc; body = Matching.for_function pat.pat_loc None (Lvar param) [pat, rem] partial} in - (path, + (path, path_lam, match obj_init with Lfunction {kind = Curried; params; body} -> build params body | rem -> build [] rem) | Tcl_apply (cl, oexprs) -> - let path, obj_init = transl_class_rebind obj_init cl vf in - (path, transl_apply obj_init oexprs Location.none) + let path, path_lam, obj_init = transl_class_rebind obj_init cl vf in + (path, path_lam, transl_apply obj_init oexprs Location.none) | Tcl_let (rec_flag, defs, _vals, cl) -> - let path, obj_init = transl_class_rebind obj_init cl vf in - (path, Translcore.transl_let rec_flag defs obj_init) + let path, path_lam, obj_init = transl_class_rebind obj_init cl vf in + (path, path_lam, Translcore.transl_let rec_flag defs obj_init) | Tcl_structure _ -> raise Exit | Tcl_constraint (cl', _, _, _, _) -> - let path, obj_init = transl_class_rebind obj_init cl' vf in + let path, path_lam, obj_init = transl_class_rebind obj_init cl' vf in let rec check_constraint = function Cty_constr(path', _, _) when Path.same path path' -> () | Cty_arrow (_, _, cty) -> check_constraint cty | _ -> raise Exit in check_constraint cl.cl_type; - (path, obj_init) - | Tcl_open (_, _, _, _, cl) -> + (path, path_lam, obj_init) + | Tcl_open (_, cl) -> transl_class_rebind obj_init cl vf -let rec transl_class_rebind_0 self obj_init cl vf = +let rec transl_class_rebind_0 (self:Ident.t) obj_init cl vf = match cl.cl_desc with Tcl_let (rec_flag, defs, _vals, cl) -> - let path, obj_init = transl_class_rebind_0 self obj_init cl vf in - (path, Translcore.transl_let rec_flag defs obj_init) + let path, path_lam, obj_init = + transl_class_rebind_0 self obj_init cl vf + in + (path, path_lam, Translcore.transl_let rec_flag defs obj_init) | _ -> - let path, obj_init = transl_class_rebind obj_init cl vf in - (path, lfunction [self] obj_init) + let path, path_lam, obj_init = transl_class_rebind obj_init cl vf in + (path, path_lam, lfunction [self, Pgenval] obj_init) let transl_class_rebind cl vf = try - let obj_init = Ident.create "obj_init" - and self = Ident.create "self" in + let obj_init = Ident.create_local "obj_init" + and self = Ident.create_local "self" in let obj_init0 = lapply {ap_should_be_tailcall=false; ap_loc=Location.none; @@ -477,25 +477,25 @@ let transl_class_rebind cl vf = ap_inlined=Default_inline; ap_specialised=Default_specialise} in - let path, obj_init' = transl_class_rebind_0 self obj_init0 cl vf in - let id = (obj_init' = lfunction [self] obj_init0) in - if id then transl_normal_path path else - - let cla = Ident.create "class" - and new_init = Ident.create "new_init" - and env_init = Ident.create "env_init" - and table = Ident.create "table" - and envs = Ident.create "envs" in + let _, path_lam, obj_init' = transl_class_rebind_0 self obj_init0 cl vf in + let id = (obj_init' = lfunction [self, Pgenval] obj_init0) in + if id then path_lam else + + let cla = Ident.create_local "class" + and new_init = Ident.create_local "new_init" + and env_init = Ident.create_local "env_init" + and table = Ident.create_local "table" + and envs = Ident.create_local "envs" in Llet( - Strict, Pgenval, new_init, lfunction [obj_init] obj_init', + Strict, Pgenval, new_init, lfunction [obj_init, Pgenval] obj_init', Llet( - Alias, Pgenval, cla, transl_normal_path path, + Alias, Pgenval, cla, path_lam, Lprim(Pmakeblock(0, Immutable, None), [mkappl(Lvar new_init, [lfield cla 0]); - lfunction [table] + lfunction [table, Pgenval] (Llet(Strict, Pgenval, env_init, mkappl(lfield cla 1, [Lvar table]), - lfunction [envs] + lfunction [envs, Pgenval] (mkappl(Lvar new_init, [mkappl(Lvar env_init, [Lvar envs])])))); lfield cla 2; @@ -556,7 +556,7 @@ let rec builtin_meths self env env2 body = | Lsend(Cached, met, arg, [_;_], _) -> let s, args = conv arg in ("send_"^s, met :: args) - | Lfunction {kind = Curried; params = [x]; body} -> + | Lfunction {kind = Curried; params = [x, _]; body} -> let rec enter self = function | Lprim(Parraysetu _, [Lvar s; Lvar n; Lvar x'], _) when Ident.same x x' && List.mem s self -> @@ -639,13 +639,13 @@ let free_methods l = fv := Ident.Set.add meth !fv | Lsend _ -> () | Lfunction{params} -> - List.iter (fun param -> fv := Ident.Set.remove param !fv) params + List.iter (fun (param, _) -> fv := Ident.Set.remove param !fv) params | Llet(_str, _k, id, _arg, _body) -> fv := Ident.Set.remove id !fv | Lletrec(decl, _body) -> List.iter (fun (id, _exp) -> fv := Ident.Set.remove id !fv) decl | Lstaticcatch(_e1, (_,vars), _e2) -> - List.iter (fun id -> fv := Ident.Set.remove id !fv) vars + List.iter (fun (id, _) -> fv := Ident.Set.remove id !fv) vars | Ltrywith(_e1, exn, _e2) -> fv := Ident.Set.remove exn !fv | Lfor(v, _e1, _e2, _dir, _e3) -> @@ -663,12 +663,12 @@ let transl_class ids cl_id pub_meths cl vflag = if rebind <> lambda_unit then rebind else (* Prepare for heavy environment handling *) - let tables = Ident.create (Ident.name cl_id ^ "_tables") in + let tables = Ident.create_local (Ident.name cl_id ^ "_tables") in let (top_env, req) = oo_add_class tables in let top = not req in let cl_env, llets = build_class_lets cl in let new_ids = if top then [] else Env.diff top_env cl_env in - let env2 = Ident.create "env" in + let env2 = Ident.create_local "env" in let meth_ids = get_class_meths cl in let subst env lam i0 new_ids' = let fv = free_variables lam in @@ -693,19 +693,20 @@ let transl_class ids cl_id pub_meths cl vflag = Ident.Map.empty !new_ids' in let new_ids_meths = ref [] in + let no_env_update _ _ env = env in let msubst arr = function - Lfunction {kind = Curried; params = self :: args; body} -> - let env = Ident.create "env" in + Lfunction {kind = Curried; params = (self, Pgenval) :: args; body} -> + let env = Ident.create_local "env" in let body' = if new_ids = [] then body else - Lambda.subst (subst env body 0 new_ids_meths) body in + Lambda.subst no_env_update (subst env body 0 new_ids_meths) body in begin try (* Doesn't seem to improve size for bytecode *) (* if not !Clflags.native_code then raise Not_found; *) if not arr || !Clflags.debug then raise Not_found; builtin_meths [self] env env2 (lfunction args body') with Not_found -> - [lfunction (self :: args) + [lfunction ((self, Pgenval) :: args) (if not (Ident.Set.mem env (free_variables body')) then body' else Llet(Alias, Pgenval, env, Lprim(Pfield_computed, @@ -716,7 +717,7 @@ let transl_class ids cl_id pub_meths cl vflag = | _ -> assert false in let new_ids_init = ref [] in - let env1 = Ident.create "env" and env1' = Ident.create "env'" in + let env1 = Ident.create_local "env" and env1' = Ident.create_local "env'" in let copy_env self = if top then lambda_unit else Lifused(env2, Lprim(Psetfield_computed (Pointer, Assignment), @@ -725,7 +726,7 @@ let transl_class ids cl_id pub_meths cl vflag = and subst_env envs l lam = if top then lam else (* must be called only once! *) - let lam = Lambda.subst (subst env1 lam 1 new_ids_init) lam in + let lam = Lambda.subst no_env_update (subst env1 lam 1 new_ids_init) lam in Llet(Alias, Pgenval, env1, (if l = [] then Lvar envs else lfield envs 0), Llet(Alias, Pgenval, env1', (if !new_ids_init = [] then Lvar env1 else lfield env1 0), @@ -733,7 +734,7 @@ let transl_class ids cl_id pub_meths cl vflag = in (* Now we start compiling the class *) - let cla = Ident.create "class" in + let cla = Ident.create_local "class" in let (inh_init, obj_init) = build_object_init_0 cla [] cl copy_env subst_env top ids in let inh_init' = List.rev inh_init in @@ -741,10 +742,10 @@ let transl_class ids cl_id pub_meths cl vflag = build_class_init cla true ([],[]) inh_init' obj_init msubst top cl in assert (inh_init' = []); - let table = Ident.create "table" - and class_init = Ident.create (Ident.name cl_id ^ "_init") - and env_init = Ident.create "env_init" - and obj_init = Ident.create "obj_init" in + let table = Ident.create_local "table" + and class_init = Ident.create_local (Ident.name cl_id ^ "_init") + and env_init = Ident.create_local "env_init" + and obj_init = Ident.create_local "obj_init" in let pub_meths = List.sort (fun s s' -> compare (Btype.hash_variant s) (Btype.hash_variant s')) @@ -772,7 +773,8 @@ let transl_class ids cl_id pub_meths cl vflag = let cl_init = llets (Lfunction{kind = Curried; attr = default_function_attribute; loc = Location.none; - params = [cla]; body = cl_init}) in + return = Pgenval; + params = [cla, Pgenval]; body = cl_init}) in Llet(Strict, Pgenval, class_init, cl_init, lam (free_variables cl_init)) and lbody fv = if List.for_all (fun id -> not (Ident.Set.mem id fv)) ids then @@ -793,7 +795,8 @@ let transl_class ids cl_id pub_meths cl vflag = [lambda_unit; Lfunction{kind = Curried; attr = default_function_attribute; loc = Location.none; - params = [cla]; body = cl_init}; + return = Pgenval; + params = [cla, Pgenval]; body = cl_init}; lambda_unit; lenvs], Location.none) in @@ -802,8 +805,8 @@ let transl_class ids cl_id pub_meths cl vflag = if top then llets (lbody_virt lambda_unit) else (* Now for the hard stuff: prepare for table caching *) - let envs = Ident.create "envs" - and cached = Ident.create "cached" in + let envs = Ident.create_local "envs" + and cached = Ident.create_local "cached" in let lenvs = if !new_ids_meths = [] && !new_ids_init = [] && inh_init = [] then lambda_unit @@ -820,7 +823,7 @@ let transl_class ids cl_id pub_meths cl vflag = Location.none) and linh_envs = List.map - (fun (_, p) -> Lprim(Pfield 3, [transl_normal_path p], Location.none)) + (fun (_, path_lam, _) -> Lprim(Pfield 3, [path_lam], Location.none)) (List.rev inh_init) in let make_envs lam = @@ -836,16 +839,17 @@ let transl_class ids cl_id pub_meths cl vflag = in let inh_paths = List.filter - (fun (_,path) -> List.mem (Path.head path) new_ids) inh_init + (fun (path, _, _) -> List.mem (Path.head path) new_ids) inh_init in let inh_keys = - List.map (fun (_,p) -> Lprim(Pfield 1, [transl_normal_path p], - Location.none)) + List.map + (fun (_, path_lam, _) -> Lprim(Pfield 1, [path_lam], Location.none)) inh_paths in let lclass lam = Llet(Strict, Pgenval, class_init, - Lfunction{kind = Curried; params = [cla]; + Lfunction{kind = Curried; params = [cla, Pgenval]; + return = Pgenval; attr = default_function_attribute; loc = Location.none; body = def_ids cla cl_init}, lam) @@ -866,9 +870,17 @@ let transl_class ids cl_id pub_meths cl vflag = Lsequence(mkappl (oo_prim "init_class", [Lvar cla]), lset cached 0 (Lvar env_init)))) and lclass_virt () = - lset cached 0 (Lfunction{kind = Curried; attr = default_function_attribute; - loc = Location.none; - params = [cla]; body = def_ids cla cl_init}) + lset cached 0 + (Lfunction + { + kind = Curried; + attr = default_function_attribute; + loc = Location.none; + return = Pgenval; + params = [cla, Pgenval]; + body = def_ids cla cl_init; + } + ) in let lupdate_cache = if ids = [] then ldirect () else @@ -928,7 +940,7 @@ let () = Location.register_error_of_exn (function | Error (loc, err) -> - Some (Location.error_of_printer loc report_error err) + Some (Location.error_of_printer ~loc report_error err) | _ -> None ) diff --git a/bytecomp/translcore.ml b/bytecomp/translcore.ml index 0da506f8..e9098a2f 100644 --- a/bytecomp/translcore.ml +++ b/bytecomp/translcore.ml @@ -65,7 +65,7 @@ let transl_extension_constructor env path ext = Lprim (prim_fresh_oo_id, [Lconst (Const_base (Const_int 0))], loc)], loc) | Text_rebind(path, _lid) -> - transl_extension_path ~loc env path + transl_extension_path loc env path (* To propagate structured constants *) @@ -84,7 +84,7 @@ let extract_float = function type binding = | Bind_value of value_binding list - | Bind_module of Ident.t * string loc * module_expr + | Bind_module of Ident.t * string loc * module_presence * module_expr let rec push_defaults loc bindings cases partial = match cases with @@ -96,17 +96,18 @@ let rec push_defaults loc bindings cases partial = c_rhs={exp with exp_desc = Texp_function { arg_label; param; cases; partial; }}}] | [{c_lhs=pat; c_guard=None; - c_rhs={exp_attributes=[{txt="#default"},_]; + c_rhs={exp_attributes=[{Parsetree.attr_name = {txt="#default"};_}]; exp_desc = Texp_let (Nonrecursive, binds, ({exp_desc = Texp_function _} as e2))}}] -> push_defaults loc (Bind_value binds :: bindings) [{c_lhs=pat;c_guard=None;c_rhs=e2}] partial | [{c_lhs=pat; c_guard=None; - c_rhs={exp_attributes=[{txt="#modulepat"},_]; + c_rhs={exp_attributes=[{Parsetree.attr_name = {txt="#modulepat"};_}]; exp_desc = Texp_letmodule - (id, name, mexpr, ({exp_desc = Texp_function _} as e2))}}] -> - push_defaults loc (Bind_module (id, name, mexpr) :: bindings) + (id, name, pres, mexpr, + ({exp_desc = Texp_function _} as e2))}}] -> + push_defaults loc (Bind_module (id, name, pres, mexpr) :: bindings) [{c_lhs=pat;c_guard=None;c_rhs=e2}] partial | [case] -> @@ -116,24 +117,26 @@ let rec push_defaults loc bindings cases partial = {exp with exp_desc = match binds with | Bind_value binds -> Texp_let(Nonrecursive, binds, exp) - | Bind_module (id, name, mexpr) -> - Texp_letmodule (id, name, mexpr, exp)}) + | Bind_module (id, name, pres, mexpr) -> + Texp_letmodule (id, name, pres, mexpr, exp)}) case.c_rhs bindings in [{case with c_rhs=exp}] | {c_lhs=pat; c_rhs=exp; c_guard=_} :: _ when bindings <> [] -> - let param = Typecore.name_pattern "param" cases in + let param = Typecore.name_cases "param" cases in + let desc = + {val_type = pat.pat_type; val_kind = Val_reg; + val_attributes = []; Types.val_loc = Location.none; } + in + let env = Env.add_value param desc exp.exp_env in let name = Ident.name param in let exp = - { exp with exp_loc = loc; exp_desc = + { exp with exp_loc = loc; exp_env = env; exp_desc = Texp_match - ({exp with exp_type = pat.pat_type; exp_desc = - Texp_ident (Path.Pident param, mknoloc (Longident.Lident name), - {val_type = pat.pat_type; val_kind = Val_reg; - val_attributes = []; - Types.val_loc = Location.none; - })}, - cases, [], partial) } + ({exp with exp_type = pat.pat_type; exp_env = env; exp_desc = + Texp_ident + (Path.Pident param, mknoloc (Longident.Lident name), desc)}, + cases, partial) } in push_defaults loc bindings [{c_lhs={pat with pat_desc = Tpat_var (param, mknoloc name)}; @@ -156,18 +159,23 @@ let event_function exp lam = Levent(body, {lev_loc = exp.exp_loc; lev_kind = Lev_function; lev_repr = repr; - lev_env = Env.summary exp.exp_env})) + lev_env = exp.exp_env})) else lam None (* Assertions *) let assert_failed exp = + let slot = + transl_extension_path Location.none + Env.initial_safe_string Predef.path_assert_failure + in let (fname, line, char) = - Location.get_pos_info exp.exp_loc.Location.loc_start in + Location.get_pos_info exp.exp_loc.Location.loc_start + in Lprim(Praise Raise_regular, [event_after exp (Lprim(Pmakeblock(0, Immutable, None), - [transl_normal_path Predef.path_assert_failure; + [slot; Lconst(Const_block(0, [Const_base(Const_string (fname, None)); Const_base(Const_int line); @@ -181,6 +189,24 @@ let rec cut n l = (* Translation of expressions *) +let rec iter_exn_names f pat = + match pat.pat_desc with + | Tpat_var (id, _) -> f id + | Tpat_alias (p, id, _) -> + f id; + iter_exn_names f p + | _ -> () + +let transl_ident loc env ty path desc = + match desc.val_kind with + | Val_prim p -> + Translprim.transl_primitive loc p env ty (Some path) + | Val_anc _ -> + raise(Error(loc, Free_super_var)) + | Val_reg | Val_self _ -> + transl_value_path loc env path + | _ -> fatal_error "Translcore.transl_exp: bad Texp_ident" + let rec transl_exp e = List.iter (Translattribute.check_attribute e) e.exp_attributes; let eval_once = @@ -194,33 +220,25 @@ let rec transl_exp e = and transl_exp0 e = match e.exp_desc with - | Texp_ident(path, _, {val_kind = Val_prim p}) -> - Translprim.transl_primitive e.exp_loc p e.exp_env e.exp_type (Some path) - | Texp_ident(_, _, {val_kind = Val_anc _}) -> - raise(Error(e.exp_loc, Free_super_var)) - | Texp_ident(path, _, {val_kind = Val_reg | Val_self _}) -> - transl_value_path ~loc:e.exp_loc e.exp_env path - | Texp_ident _ -> fatal_error "Translcore.transl_exp: bad Texp_ident" + | Texp_ident(path, _, desc) -> + transl_ident e.exp_loc e.exp_env e.exp_type path desc | Texp_constant cst -> Lconst(Const_base cst) | Texp_let(rec_flag, pat_expr_list, body) -> transl_let rec_flag pat_expr_list (event_before body (transl_exp body)) | Texp_function { arg_label = _; param; cases; partial; } -> - let ((kind, params), body) = + let ((kind, params, return), body) = event_function e (function repr -> let pl = push_defaults e.exp_loc [] cases partial in - transl_function e.exp_loc !Clflags.native_code repr partial - param pl) - in - let attr = { - default_function_attribute with - inline = Translattribute.get_inline_attribute e.exp_attributes; - specialise = Translattribute.get_specialise_attribute e.exp_attributes; - } + let return_kind = function_return_value_kind e.exp_env e.exp_type in + transl_function e.exp_loc return_kind !Clflags.native_code repr + partial param pl) in + let attr = default_function_attribute in let loc = e.exp_loc in - Lfunction{kind; params; body; attr; loc} + let lam = Lfunction{kind; params; return; body; attr; loc} in + Translattribute.add_function_attributes lam loc e.exp_attributes | Texp_apply({ exp_desc = Texp_ident(path, _, {val_kind = Val_prim p}); exp_type = prim_type } as funct, oargs) when List.length oargs >= p.prim_arity @@ -266,10 +284,10 @@ and transl_exp0 e = event_after e (transl_apply ~should_be_tailcall ~inlined ~specialised (transl_exp funct) oargs e.exp_loc) - | Texp_match(arg, pat_expr_list, exn_pat_expr_list, partial) -> - transl_match e arg pat_expr_list exn_pat_expr_list partial + | Texp_match(arg, pat_expr_list, partial) -> + transl_match e arg pat_expr_list partial | Texp_try(body, pat_expr_list) -> - let id = Typecore.name_pattern "exn" pat_expr_list in + let id = Typecore.name_cases "exn" pat_expr_list in Ltrywith(transl_exp body, id, Matching.for_trywith (Lvar id) (transl_cases_try pat_expr_list)) | Texp_tuple el -> @@ -296,14 +314,14 @@ and transl_exp0 e = Lprim(Pmakeblock(n, Immutable, Some shape), ll, e.exp_loc) end | Cstr_extension(path, is_const) -> - if is_const then - transl_extension_path e.exp_env path + let lam = transl_extension_path e.exp_loc e.exp_env path in + if is_const then lam else Lprim(Pmakeblock(0, Immutable, Some (Pgenval :: shape)), - transl_extension_path e.exp_env path :: ll, e.exp_loc) + lam :: ll, e.exp_loc) end | Texp_extension_constructor (_, path) -> - transl_extension_path e.exp_env path + transl_extension_path e.exp_loc e.exp_env path | Texp_variant(l, arg) -> let tag = Btype.hash_variant l in begin match arg with @@ -327,7 +345,7 @@ and transl_exp0 e = Lprim (Pfield lbl.lbl_pos, [targ], e.exp_loc) | Record_unboxed _ -> targ | Record_float -> Lprim (Pfloatfield lbl.lbl_pos, [targ], e.exp_loc) - | Record_extension -> + | Record_extension _ -> Lprim (Pfield (lbl.lbl_pos + 1), [targ], e.exp_loc) end | Texp_setfield(arg, _, lbl, newval) -> @@ -338,7 +356,7 @@ and transl_exp0 e = Psetfield(lbl.lbl_pos, maybe_pointer newval, Assignment) | Record_unboxed _ -> assert false | Record_float -> Psetfloatfield (lbl.lbl_pos, Assignment) - | Record_extension -> + | Record_extension _ -> Psetfield (lbl.lbl_pos + 1, maybe_pointer newval, Assignment) in Lprim(access, [transl_exp arg; transl_exp newval], e.exp_loc) @@ -417,40 +435,48 @@ and transl_exp0 e = | Texp_new (cl, {Location.loc=loc}, _) -> Lapply{ap_should_be_tailcall=false; ap_loc=loc; - ap_func=Lprim(Pfield 0, [transl_class_path ~loc e.exp_env cl], loc); + ap_func= + Lprim(Pfield 0, [transl_class_path loc e.exp_env cl], loc); ap_args=[lambda_unit]; ap_inlined=Default_inline; ap_specialised=Default_specialise} | Texp_instvar(path_self, path, _) -> - Lprim(Pfield_computed, - [transl_normal_path path_self; transl_normal_path path], e.exp_loc) + let self = transl_value_path e.exp_loc e.exp_env path_self in + let var = transl_value_path e.exp_loc e.exp_env path in + Lprim(Pfield_computed, [self; var], e.exp_loc) | Texp_setinstvar(path_self, path, _, expr) -> - transl_setinstvar e.exp_loc (transl_normal_path path_self) path expr + let self = transl_value_path e.exp_loc e.exp_env path_self in + let var = transl_value_path e.exp_loc e.exp_env path in + transl_setinstvar e.exp_loc self var expr | Texp_override(path_self, modifs) -> - let cpy = Ident.create "copy" in + let self = transl_value_path e.exp_loc e.exp_env path_self in + let cpy = Ident.create_local "copy" in Llet(Strict, Pgenval, cpy, Lapply{ap_should_be_tailcall=false; ap_loc=Location.none; ap_func=Translobj.oo_prim "copy"; - ap_args=[transl_normal_path path_self]; + ap_args=[self]; ap_inlined=Default_inline; ap_specialised=Default_specialise}, List.fold_right (fun (path, _, expr) rem -> + let var = transl_value_path e.exp_loc e.exp_env path in Lsequence(transl_setinstvar Location.none - (Lvar cpy) path expr, rem)) + (Lvar cpy) var expr, rem)) modifs (Lvar cpy)) - | Texp_letmodule(id, loc, modl, body) -> + | Texp_letmodule(id, loc, Mp_present, modl, body) -> let defining_expr = Levent (!transl_module Tcoerce_none None modl, { lev_loc = loc.loc; lev_kind = Lev_module_definition id; lev_repr = None; - lev_env = Env.summary Env.empty; + lev_env = Env.empty; }) in Llet(Strict, Pgenval, id, defining_expr, transl_exp body) + | Texp_letmodule(_, _, Mp_absent, _, body) -> + transl_exp body | Texp_letexception(cd, body) -> Llet(Strict, Pgenval, cd.ext_id, transl_extension_constructor e.exp_env None cd, @@ -493,7 +519,9 @@ and transl_exp0 e = transl_exp e | `Other -> (* other cases compile to a lazy block holding a function *) - let fn = Lfunction {kind = Curried; params = [Ident.create "param"]; + let fn = Lfunction {kind = Curried; + params= [Ident.create_local "param", Pgenval]; + return = Pgenval; attr = default_function_attribute; loc = e.exp_loc; body = transl_exp e} in @@ -501,7 +529,7 @@ and transl_exp0 e = end | Texp_object (cs, meths) -> let cty = cs.cstr_type in - let cl = Ident.create "class" in + let cl = Ident.create_local "class" in !transl_object cl meths { cl_desc = Tcl_structure cs; cl_loc = e.exp_loc; @@ -509,8 +537,37 @@ and transl_exp0 e = cl_env = e.exp_env; cl_attributes = []; } + | Texp_letop{let_; ands; param; body; partial} -> + event_after e + (transl_letop e.exp_loc e.exp_env let_ ands param body partial) | Texp_unreachable -> raise (Error (e.exp_loc, Unreachable_reached)) + | Texp_open (od, e) -> + let pure = pure_module od.open_expr in + (* this optimization shouldn't be needed because Simplif would + actually remove the [Llet] when it's not used. + But since [scan_used_globals] runs before Simplif, we need to + do it. *) + begin match od.open_bound_items with + | [] when pure = Alias -> transl_exp e + | _ -> + let oid = Ident.create_local "open" in + let body, _ = + List.fold_left (fun (body, pos) id -> + Llet(Alias, Pgenval, id, + Lprim(Pfield pos, [Lvar oid], od.open_loc), body), + pos + 1 + ) (transl_exp e, 0) (bound_value_identifiers od.open_bound_items) + in + Llet(pure, Pgenval, oid, + !transl_module Tcoerce_none None od.open_expr, body) + end + +and pure_module m = + match m.mod_desc with + Tmod_ident _ -> Alias + | Tmod_constraint (m,_,_,_) -> pure_module m + | _ -> Strict and transl_list expr_list = List.map transl_exp expr_list @@ -538,19 +595,11 @@ and transl_cases cases = List.map transl_case cases and transl_case_try {c_lhs; c_guard; c_rhs} = - let rec iter_exn_names f pat = - match pat.pat_desc with - | Tpat_var (id, _) -> f id - | Tpat_alias (p, id, _) -> - f id; - iter_exn_names f p - | _ -> () - in iter_exn_names Translprim.add_exception_ident c_lhs; Misc.try_finally (fun () -> c_lhs, transl_guard c_guard c_rhs) - (fun () -> - iter_exn_names Translprim.remove_exception_ident c_lhs) + ~always:(fun () -> + iter_exn_names Translprim.remove_exception_ident c_lhs) and transl_cases_try cases = let cases = @@ -589,7 +638,7 @@ and transl_apply ?(should_be_tailcall=false) ?(inlined = Default_inline) match lam with Lvar _ | Lconst _ -> lam | _ -> - let id = Ident.create name in + let id = Ident.create_local name in defs := (id, lam) :: !defs; Lvar id in @@ -600,18 +649,25 @@ and transl_apply ?(should_be_tailcall=false) ?(inlined = Default_inline) if args = [] then lam else lapply lam (List.rev_map fst args) in let handle = protect "func" lam and l = List.map (fun (arg, opt) -> may_map (protect "arg") arg, opt) l - and id_arg = Ident.create "param" in + and id_arg = Ident.create_local "param" in let body = match build_apply handle ((Lvar id_arg, optional)::args') l with - Lfunction{kind = Curried; params = ids; body = lam; attr; loc} -> - Lfunction{kind = Curried; params = id_arg::ids; body = lam; attr; + Lfunction{kind = Curried; params = ids; return; + body = lam; attr; loc} -> + Lfunction{kind = Curried; + params = (id_arg, Pgenval)::ids; + return; + body = lam; attr; loc} - | Levent(Lfunction{kind = Curried; params = ids; + | Levent(Lfunction{kind = Curried; params = ids; return; body = lam; attr; loc}, _) -> - Lfunction{kind = Curried; params = id_arg::ids; body = lam; attr; + Lfunction{kind = Curried; params = (id_arg, Pgenval)::ids; + return; + body = lam; attr; loc} | lam -> - Lfunction{kind = Curried; params = [id_arg]; body = lam; + Lfunction{kind = Curried; params = [id_arg, Pgenval]; + return = Pgenval; body = lam; attr = default_stub_attribute; loc = loc} in List.fold_left @@ -627,15 +683,18 @@ and transl_apply ?(should_be_tailcall=false) ?(inlined = Default_inline) sargs) : Lambda.lambda) -and transl_function loc untuplify_fn repr partial param cases = +and transl_function loc return untuplify_fn repr partial (param:Ident.t) cases = match cases with [{c_lhs=pat; c_guard=None; c_rhs={exp_desc = Texp_function { arg_label = _; param = param'; cases; - partial = partial'; }} as exp}] + partial = partial'; }; exp_env; exp_type} as exp}] when Parmatch.inactive ~partial pat -> - let ((_, params), body) = - transl_function exp.exp_loc false repr partial' param' cases in - ((Curried, param :: params), + let kind = value_kind pat.pat_env pat.pat_type in + let return_kind = function_return_value_kind exp_env exp_type in + let ((_, params, return), body) = + transl_function exp.exp_loc return_kind false repr partial' param' cases + in + ((Curried, (param, kind) :: params, return), Matching.for_function loc None (Lvar param) [pat, body] partial) | {c_lhs={pat_desc = Tpat_tuple pl}} :: _ when untuplify_fn -> begin try @@ -645,17 +704,50 @@ and transl_function loc untuplify_fn repr partial param cases = (fun {c_lhs; c_guard; c_rhs} -> (Matching.flatten_pattern size c_lhs, c_guard, c_rhs)) cases in - let params = List.map (fun _ -> Ident.create "param") pl in - ((Tupled, params), + let kinds = + (* All the patterns might not share the same types. We must take the + union of the patterns types *) + match pats_expr_list with + | [] -> assert false + | (pats, _, _) :: cases -> + let first_case_kinds = + List.map (fun pat -> value_kind pat.pat_env pat.pat_type) pats + in + List.fold_left + (fun kinds (pats, _, _) -> + List.map2 (fun kind pat -> + value_kind_union kind + (value_kind pat.pat_env pat.pat_type)) + kinds pats) + first_case_kinds cases + in + let tparams = + List.map (fun kind -> Ident.create_local "param", kind) kinds + in + let params = List.map fst tparams in + ((Tupled, tparams, return), Matching.for_tupled_function loc params (transl_tupled_cases pats_expr_list) partial) with Matching.Cannot_flatten -> - ((Curried, [param]), + ((Curried, [param, Pgenval], return), Matching.for_function loc repr (Lvar param) (transl_cases cases) partial) end - | _ -> - ((Curried, [param]), + | {c_lhs=pat} :: other_cases -> + let kind = + (* All the patterns might not share the same types. We must take the + union of the patterns types *) + List.fold_left (fun k {c_lhs=pat} -> + Typeopt.value_kind_union k + (value_kind pat.pat_env pat.pat_type)) + (value_kind pat.pat_env pat.pat_type) other_cases + in + ((Curried, [param, kind], return), + Matching.for_function loc repr (Lvar param) + (transl_cases cases) partial) + | [] -> + (* With Camlp4, a pattern matching might be empty *) + ((Curried, [param, Pgenval], return), Matching.for_function loc repr (Lvar param) (transl_cases cases) partial) @@ -673,12 +765,7 @@ and transl_let rec_flag pat_expr_list = fun body -> body | {vb_pat=pat; vb_expr=expr; vb_attributes=attr; vb_loc} :: rem -> let lam = transl_exp expr in - let lam = - Translattribute.add_inline_attribute lam vb_loc attr - in - let lam = - Translattribute.add_specialise_attribute lam vb_loc attr - in + let lam = Translattribute.add_function_attributes lam vb_loc attr in let mk_body = transl rem in fun body -> Matching.for_let pat.pat_loc lam pat (mk_body body) in transl pat_expr_list @@ -693,12 +780,7 @@ and transl_let rec_flag pat_expr_list = let transl_case {vb_expr=expr; vb_attributes; vb_loc} id = let lam = transl_exp expr in let lam = - Translattribute.add_inline_attribute lam vb_loc - vb_attributes - in - let lam = - Translattribute.add_specialise_attribute lam vb_loc - vb_attributes + Translattribute.add_function_attributes lam vb_loc vb_attributes in (id, lam) in let lam_bds = List.map2 transl_case pat_expr_list idlist in @@ -706,7 +788,7 @@ and transl_let rec_flag pat_expr_list = and transl_setinstvar loc self var expr = Lprim(Psetfield_computed (maybe_pointer expr, Assignment), - [self; transl_normal_path var; transl_exp expr], loc) + [self; var; transl_exp expr], loc) and transl_record loc env fields repres opt_init_expr = let size = Array.length fields in @@ -717,7 +799,7 @@ and transl_record loc env fields repres opt_init_expr = then begin (* Allocate new record with given fields (and remaining fields taken from init_expr if any *) - let init_id = Ident.create "init" in + let init_id = Ident.create_local "init" in let lv = Array.mapi (fun i (_, definition) -> @@ -728,7 +810,7 @@ and transl_record loc env fields repres opt_init_expr = match repres with Record_regular | Record_inlined _ -> Pfield i | Record_unboxed _ -> assert false - | Record_extension -> Pfield (i + 1) + | Record_extension _ -> Pfield (i + 1) | Record_float -> Pfloatfield i in Lprim(access, [Lvar init_id], loc), field_kind | Overridden (_lid, expr) -> @@ -751,7 +833,7 @@ and transl_record loc env fields repres opt_init_expr = | Record_unboxed _ -> Lconst(match cl with [v] -> v | _ -> assert false) | Record_float -> Lconst(Const_float_array(List.map extract_float cl)) - | Record_extension -> + | Record_extension _ -> raise Not_constant with Not_constant -> match repres with @@ -762,14 +844,8 @@ and transl_record loc env fields repres opt_init_expr = | Record_unboxed _ -> (match ll with [v] -> v | _ -> assert false) | Record_float -> Lprim(Pmakearray (Pfloatarray, mut), ll, loc) - | Record_extension -> - let path = - let (label, _) = fields.(0) in - match label.lbl_res.desc with - | Tconstr(p, _, _) -> p - | _ -> assert false - in - let slot = transl_extension_path env path in + | Record_extension path -> + let slot = transl_extension_path loc env path in Lprim(Pmakeblock(0, mut, Some (Pgenval :: shape)), slot :: ll, loc) in begin match opt_init_expr with @@ -780,7 +856,7 @@ and transl_record loc env fields repres opt_init_expr = end else begin (* Take a shallow copy of the init record, then mutate the fields of the copy *) - let copy_id = Ident.create "newrecord" in + let copy_id = Ident.create_local "newrecord" in let update_field cont (lbl, definition) = match definition with | Kept _type -> cont @@ -792,7 +868,7 @@ and transl_record loc env fields repres opt_init_expr = Psetfield(lbl.lbl_pos, maybe_pointer expr, Assignment) | Record_unboxed _ -> assert false | Record_float -> Psetfloatfield (lbl.lbl_pos, Assignment) - | Record_extension -> + | Record_extension _ -> Psetfield(lbl.lbl_pos + 1, maybe_pointer expr, Assignment) in Lsequence(Lprim(upd, [Lvar copy_id; transl_exp expr], loc), cont) @@ -806,11 +882,55 @@ and transl_record loc env fields repres opt_init_expr = end end -and transl_match e arg pat_expr_list exn_pat_expr_list partial = - let id = Typecore.name_pattern "exn" exn_pat_expr_list - and cases = transl_cases pat_expr_list - and exn_cases = transl_cases_try exn_pat_expr_list in +and transl_match e arg pat_expr_list partial = + let rewrite_case (val_cases, exn_cases, static_handlers as acc) + ({ c_lhs; c_guard; c_rhs } as case) = + if c_rhs.exp_desc = Texp_unreachable then acc else + let val_pat, exn_pat = split_pattern c_lhs in + match val_pat, exn_pat with + | None, None -> assert false + | Some pv, None -> + let val_case = + transl_case { case with c_lhs = pv } + in + val_case :: val_cases, exn_cases, static_handlers + | None, Some pe -> + let exn_case = transl_case_try { case with c_lhs = pe } in + val_cases, exn_case :: exn_cases, static_handlers + | Some pv, Some pe -> + assert (c_guard = None); + let lbl = next_raise_count () in + let static_raise ids = + Lstaticraise (lbl, List.map (fun id -> Lvar id) ids) + in + (* Simplif doesn't like it if binders are not uniq, so we make sure to + use different names in the value and the exception branches. *) + let ids_full = Typedtree.pat_bound_idents_full pv in + let ids = List.map (fun (id, _, _) -> id) ids_full in + let ids_kinds = + List.map (fun (id, _, ty) -> id, Typeopt.value_kind pv.pat_env ty) + ids_full + in + let vids = List.map Ident.rename ids in + let pv = alpha_pat (List.combine ids vids) pv in + (* Also register the names of the exception so Re-raise happens. *) + iter_exn_names Translprim.add_exception_ident pe; + let rhs = + Misc.try_finally + (fun () -> event_before c_rhs (transl_exp c_rhs)) + ~always:(fun () -> + iter_exn_names Translprim.remove_exception_ident pe) + in + (pv, static_raise vids) :: val_cases, + (pe, static_raise ids) :: exn_cases, + (lbl, ids_kinds, rhs) :: static_handlers + in + let val_cases, exn_cases, static_handlers = + let x, y, z = List.fold_left rewrite_case ([], [], []) pat_expr_list in + List.rev x, List.rev y, List.rev z + in let static_catch body val_ids handler = + let id = Typecore.name_pattern "exn" (List.map fst exn_cases) in let static_exception_id = next_raise_count () in Lstaticcatch (Ltrywith (Lstaticraise (static_exception_id, body), id, @@ -818,21 +938,81 @@ and transl_match e arg pat_expr_list exn_pat_expr_list partial = (static_exception_id, val_ids), handler) in - match arg, exn_cases with - | {exp_desc = Texp_tuple argl}, [] -> - Matching.for_multiple_match e.exp_loc (transl_list argl) cases partial - | {exp_desc = Texp_tuple argl}, _ :: _ -> - let val_ids = List.map (fun _ -> Typecore.name_pattern "val" []) argl in - let lvars = List.map (fun id -> Lvar id) val_ids in - static_catch (transl_list argl) val_ids - (Matching.for_multiple_match e.exp_loc lvars cases partial) - | arg, [] -> - Matching.for_function e.exp_loc None (transl_exp arg) cases partial - | arg, _ :: _ -> - let val_id = Typecore.name_pattern "val" pat_expr_list in - static_catch [transl_exp arg] [val_id] - (Matching.for_function e.exp_loc None (Lvar val_id) cases partial) + let classic = + match arg, exn_cases with + | {exp_desc = Texp_tuple argl}, [] -> + assert (static_handlers = []); + Matching.for_multiple_match e.exp_loc (transl_list argl) val_cases partial + | {exp_desc = Texp_tuple argl}, _ :: _ -> + let val_ids = + List.map + (fun arg -> + Typecore.name_pattern "val" [], + Typeopt.value_kind arg.exp_env arg.exp_type + ) + argl + in + let lvars = List.map (fun (id, _) -> Lvar id) val_ids in + static_catch (transl_list argl) val_ids + (Matching.for_multiple_match e.exp_loc lvars val_cases partial) + | arg, [] -> + assert (static_handlers = []); + Matching.for_function e.exp_loc None (transl_exp arg) val_cases partial + | arg, _ :: _ -> + let val_id = Typecore.name_cases "val" pat_expr_list in + let k = Typeopt.value_kind arg.exp_env arg.exp_type in + static_catch [transl_exp arg] [val_id, k] + (Matching.for_function e.exp_loc None (Lvar val_id) val_cases partial) + in + List.fold_left (fun body (static_exception_id, val_ids, handler) -> + Lstaticcatch (body, (static_exception_id, val_ids), handler) + ) classic static_handlers +and transl_letop loc env let_ ands param case partial = + let rec loop prev_lam = function + | [] -> prev_lam + | and_ :: rest -> + let left_id = Ident.create_local "left" in + let right_id = Ident.create_local "right" in + let op = + transl_ident and_.bop_op_name.loc env + and_.bop_op_type and_.bop_op_path and_.bop_op_val + in + let exp = transl_exp and_.bop_exp in + let lam = + bind Strict right_id exp + (Lapply{ap_should_be_tailcall = false; + ap_loc = and_.bop_loc; + ap_func = op; + ap_args=[Lvar left_id; Lvar right_id]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise}) + in + bind Strict left_id prev_lam (loop lam rest) + in + let op = + transl_ident let_.bop_op_name.loc env + let_.bop_op_type let_.bop_op_path let_.bop_op_val + in + let exp = loop (transl_exp let_.bop_exp) ands in + let func = + let return_kind = value_kind case.c_rhs.exp_env case.c_rhs.exp_type in + let (kind, params, return), body = + event_function case.c_rhs + (function repr -> + transl_function case.c_rhs.exp_loc return_kind + !Clflags.native_code repr partial param [case]) + in + let attr = default_function_attribute in + let loc = case.c_rhs.exp_loc in + Lfunction{kind; params; return; body; attr; loc} + in + Lapply{ap_should_be_tailcall = false; + ap_loc = loc; + ap_func = op; + ap_args=[exp; func]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise} (* Wrapper for class compilation *) @@ -862,7 +1042,7 @@ let () = Location.register_error_of_exn (function | Error (loc, err) -> - Some (Location.error_of_printer loc report_error err) + Some (Location.error_of_printer ~loc report_error err) | _ -> None ) diff --git a/bytecomp/translcore.mli b/bytecomp/translcore.mli index e27eb20a..7a27dbcb 100644 --- a/bytecomp/translcore.mli +++ b/bytecomp/translcore.mli @@ -20,6 +20,8 @@ open Asttypes open Typedtree open Lambda +val pure_module : module_expr -> let_kind + val transl_exp: expression -> lambda val transl_apply: ?should_be_tailcall:bool -> ?inlined:inline_attribute diff --git a/bytecomp/translmod.ml b/bytecomp/translmod.ml index 63cdf699..c48e4f6e 100644 --- a/bytecomp/translmod.ml +++ b/bytecomp/translmod.ml @@ -18,7 +18,6 @@ open Misc open Asttypes -open Longident open Path open Types open Typedtree @@ -27,8 +26,15 @@ open Translobj open Translcore open Translclass +type unsafe_component = + | Unsafe_module_binding + | Unsafe_functor + | Unsafe_non_function + | Unsafe_typext + +type unsafe_info = { reason:unsafe_component; loc:Location.t; subid:Ident.t } type error = - Circular_dependency of Ident.t list + Circular_dependency of (Ident.t * unsafe_info) list | Conflicting_inline_attributes exception Error of Location.t * error @@ -44,7 +50,7 @@ let functor_path path param = let field_path path field = match path with None -> None - | Some p -> Some(Pdot(p, Ident.name field, Path.nopos)) + | Some p -> Some(Pdot(p, Ident.name field)) (* Compile type extensions *) @@ -74,14 +80,15 @@ let rec apply_coercion loc strict restr arg = in wrap_id_pos_list loc id_pos_list get_field lam) | Tcoerce_functor(cc_arg, cc_res) -> - let param = Ident.create "funarg" in + let param = Ident.create_local "funarg" in let carg = apply_coercion loc Alias cc_arg (Lvar param) in - apply_coercion_result loc strict arg [param] [carg] cc_res + apply_coercion_result loc strict arg [param, Pgenval] [carg] cc_res | Tcoerce_primitive { pc_loc; pc_desc; pc_env; pc_type; } -> Translprim.transl_primitive pc_loc pc_desc pc_env pc_type None - | Tcoerce_alias (path, cc) -> + | Tcoerce_alias (env, path, cc) -> + let lam = transl_module_path loc env path in name_lambda strict arg - (fun _ -> apply_coercion loc Alias cc (transl_normal_path path)) + (fun _ -> apply_coercion loc Alias cc lam) and apply_coercion_field loc get_field (pos, cc) = apply_coercion loc Alias cc (get_field pos) @@ -89,25 +96,30 @@ and apply_coercion_field loc get_field (pos, cc) = and apply_coercion_result loc strict funct params args cc_res = match cc_res with | Tcoerce_functor(cc_arg, cc_res) -> - let param = Ident.create "funarg" in + let param = Ident.create_local "funarg" in let arg = apply_coercion loc Alias cc_arg (Lvar param) in apply_coercion_result loc strict funct - (param :: params) (arg :: args) cc_res + ((param, Pgenval) :: params) (arg :: args) cc_res | _ -> - name_lambda strict funct (fun id -> - Lfunction{kind = Curried; params = List.rev params; - attr = { default_function_attribute with - is_a_functor = true; - stub = true; }; - loc = loc; - body = apply_coercion - loc Strict cc_res - (Lapply{ap_should_be_tailcall=false; - ap_loc=loc; - ap_func=Lvar id; - ap_args=List.rev args; - ap_inlined=Default_inline; - ap_specialised=Default_specialise})}) + name_lambda strict funct + (fun id -> + Lfunction + { + kind = Curried; + params = List.rev params; + return = Pgenval; + attr = { default_function_attribute with + is_a_functor = true; + stub = true; }; + loc = loc; + body = apply_coercion + loc Strict cc_res + (Lapply{ap_should_be_tailcall=false; + ap_loc=loc; + ap_func=Lvar id; + ap_args=List.rev args; + ap_inlined=Default_inline; + ap_specialised=Default_specialise})}) and wrap_id_pos_list loc id_pos_list get_field lam = let fv = free_variables lam in @@ -115,16 +127,16 @@ and wrap_id_pos_list loc id_pos_list get_field lam = Ident.Set.iter (fun id -> Format.eprintf "%a " Ident.print id) fv; Format.eprintf "@.";*) let (lam,s) = - List.fold_left (fun (lam,s) (id',pos,c) -> + List.fold_left (fun (lam, s) (id',pos,c) -> if Ident.Set.mem id' fv then - let id'' = Ident.create (Ident.name id') in + let id'' = Ident.create_local (Ident.name id') in (Llet(Alias, Pgenval, id'', - apply_coercion loc Alias c (get_field pos),lam), - Ident.Map.add id' (Lvar id'') s) - else (lam,s)) + apply_coercion loc Alias c (get_field pos),lam), + Ident.Map.add id' id'' s) + else (lam, s)) (lam, Ident.Map.empty) id_pos_list in - if s == Ident.Map.empty then lam else Lambda.subst s lam + if s == Ident.Map.empty then lam else Lambda.rename s lam (* Compose two coercions @@ -144,17 +156,22 @@ let rec compose_coercions c1 c2 = in Tcoerce_structure (List.map - (function (p1, Tcoerce_primitive p) -> - (p1, Tcoerce_primitive p) - | (p1, c1) -> - let (p2, c2) = v2.(p1) in (p2, compose_coercions c1 c2)) - pc1, + (fun pc -> + match pc with + | _, (Tcoerce_primitive _ | Tcoerce_alias _) -> + (* These cases do not take an argument (the position is -1), + so they do not need adjusting. *) + pc + | (p1, c1) -> + let (p2, c2) = v2.(p1) in + (p2, compose_coercions c1 c2)) + pc1, ids1 @ ids2) | (Tcoerce_functor(arg1, res1), Tcoerce_functor(arg2, res2)) -> Tcoerce_functor(compose_coercions arg2 arg1, compose_coercions res1 res2) - | (c1, Tcoerce_alias (path, c2)) -> - Tcoerce_alias (path, compose_coercions c1 c2) + | (c1, Tcoerce_alias (env, path, c2)) -> + Tcoerce_alias (env, path, compose_coercions c1 c2) | (_, _) -> fatal_error "Translmod.compose_coercions" @@ -175,19 +192,14 @@ let compose_coercions c1 c2 = let primitive_declarations = ref ([] : Primitive.description list) let record_primitive = function - | {val_kind=Val_prim p} -> + | {val_kind=Val_prim p;val_loc} -> + Translprim.check_primitive_arity val_loc p; primitive_declarations := p :: !primitive_declarations | _ -> () (* Utilities for compiling "module rec" definitions *) -let mod_prim name = - try - transl_normal_path - (fst (Env.lookup_value (Ldot (Lident "CamlinternalMod", name)) - Env.empty)) - with Not_found -> - fatal_error ("Primitive " ^ name ^ " not found.") +let mod_prim = Lambda.transl_prim "CamlinternalMod" let undefined_location loc = let (fname, line, char) = Location.get_pos_info loc.Location.loc_start in @@ -196,43 +208,50 @@ let undefined_location loc = Const_base(Const_int line); Const_base(Const_int char)])) -let init_shape modl = - let rec init_shape_mod env mty = +exception Initialization_failure of unsafe_info + +let init_shape id modl = + let rec init_shape_mod subid loc env mty = match Mtype.scrape env mty with Mty_ident _ - | Mty_alias (Mta_present, _) -> - raise Not_found - | Mty_alias (Mta_absent, _) -> - Const_block (1, [Const_pointer 0]) + | Mty_alias _ -> + raise (Initialization_failure {reason=Unsafe_module_binding;loc;subid}) | Mty_signature sg -> Const_block(0, [Const_block(0, init_shape_struct env sg)]) | Mty_functor _ -> - raise Not_found (* can we do better? *) + (* can we do better? *) + raise (Initialization_failure {reason=Unsafe_functor;loc;subid}) and init_shape_struct env sg = match sg with [] -> [] - | Sig_value(_id, {val_kind=Val_reg; val_type=ty}) :: rem -> + | Sig_value(subid, {val_kind=Val_reg; val_type=ty; val_loc=loc},_) :: rem -> let init_v = match Ctype.expand_head env ty with {desc = Tarrow(_,_,_,_)} -> Const_pointer 0 (* camlinternalMod.Function *) | {desc = Tconstr(p, _, _)} when Path.same p Predef.path_lazy_t -> Const_pointer 1 (* camlinternalMod.Lazy *) - | _ -> raise Not_found in + | _ -> + let not_a_function = {reason=Unsafe_non_function; loc; subid } in + raise (Initialization_failure not_a_function) in init_v :: init_shape_struct env rem - | Sig_value(_, {val_kind=Val_prim _}) :: rem -> + | Sig_value(_, {val_kind=Val_prim _}, _) :: rem -> init_shape_struct env rem | Sig_value _ :: _rem -> assert false - | Sig_type(id, tdecl, _) :: rem -> + | Sig_type(id, tdecl, _, _) :: rem -> init_shape_struct (Env.add_type ~check:false id tdecl env) rem - | Sig_typext _ :: _ -> - raise Not_found - | Sig_module(id, md, _) :: rem -> - init_shape_mod env md.md_type :: + | Sig_typext (subid, {ext_loc=loc},_,_) :: _ -> + raise (Initialization_failure {reason=Unsafe_typext; loc; subid}) + | Sig_module(id, Mp_present, md, _, _) :: rem -> + init_shape_mod id md.md_loc env md.md_type :: init_shape_struct (Env.add_module_declaration ~check:false - id md env) rem - | Sig_modtype(id, minfo) :: rem -> + id Mp_present md env) rem + | Sig_module(id, Mp_absent, md, _, _) :: rem -> + init_shape_struct + (Env.add_module_declaration ~check:false + id Mp_absent md env) rem + | Sig_modtype(id, minfo, _) :: rem -> init_shape_struct (Env.add_modtype id minfo env) rem | Sig_class _ :: rem -> Const_pointer 2 (* camlinternalMod.Class *) @@ -241,10 +260,9 @@ let init_shape modl = init_shape_struct env rem in try - Some(undefined_location modl.mod_loc, - Lconst(init_shape_mod modl.mod_env modl.mod_type)) - with Not_found -> - None + Ok(undefined_location modl.mod_loc, + Lconst(init_shape_mod id modl.mod_loc modl.mod_env modl.mod_type)) + with Initialization_failure reason -> Result.Error(reason) (* Reorder bindings to honor dependencies. *) @@ -253,15 +271,15 @@ type binding_status = | Inprogress of int option (** parent node *) | Defined -let extract_unsafe_cycle id status cycle_start = +let extract_unsafe_cycle id status init cycle_start = + let info i = match init.(i) with + | Result.Error r -> id.(i), r + | Ok _ -> assert false in let rec collect stop l i = match status.(i) with | Inprogress None | Undefined | Defined -> assert false - | Inprogress Some i when i = stop -> id.(i) :: l - | Inprogress Some i -> collect stop (id.(i)::l) i in - collect cycle_start [id.(cycle_start)] cycle_start -(* This yields [cycle_start; ...; cycle_start]. The start of the cycle - is duplicated to make the cycle more visible in the corresponding error - message. *) + | Inprogress Some i when i = stop -> info i :: l + | Inprogress Some i -> collect stop (info i::l) i in + collect cycle_start [] cycle_start let reorder_rec_bindings bindings = let id = Array.of_list (List.map (fun (id,_,_,_) -> id) bindings) @@ -272,21 +290,27 @@ let reorder_rec_bindings bindings = let num_bindings = Array.length id in let status = Array.make num_bindings Undefined in let res = ref [] in + let is_unsafe i = match init.(i) with + | Ok _ -> false + | Result.Error _ -> true in + let init_res i = match init.(i) with + | Result.Error _ -> None + | Ok(a,b) -> Some(a,b) in let rec emit_binding parent i = match status.(i) with Defined -> () | Inprogress _ -> status.(i) <- Inprogress parent; - let cycle = extract_unsafe_cycle id status i in + let cycle = extract_unsafe_cycle id status init i in raise(Error(loc.(i), Circular_dependency cycle)) | Undefined -> - if init.(i) = None then begin + if is_unsafe i then begin status.(i) <- Inprogress parent; for j = 0 to num_bindings - 1 do if Ident.Set.mem id.(j) fv.(i) then emit_binding (Some i) j done end; - res := (id.(i), init.(i), rhs.(i)) :: !res; + res := (id.(i), init_res i, rhs.(i)) :: !res; status.(i) <- Defined in for i = 0 to num_bindings - 1 do match status.(i) with @@ -341,25 +365,10 @@ let compile_recmodule compile_rhs bindings cont = (reorder_rec_bindings (List.map (fun {mb_id=id; mb_expr=modl; mb_loc=loc; _} -> - (id, modl.mod_loc, init_shape modl, compile_rhs id modl loc)) + (id, modl.mod_loc, init_shape id modl, compile_rhs id modl loc)) bindings)) cont -(* Extract the list of "value" identifiers bound by a signature. - "Value" identifiers are identifiers for signature components that - correspond to a run-time value: values, extensions, modules, classes. - Note: manifest primitives do not correspond to a run-time value! *) - -let rec bound_value_identifiers = function - [] -> [] - | Sig_value(id, {val_kind = Val_reg}) :: rem -> - id :: bound_value_identifiers rem - | Sig_typext(id, _, _) :: rem -> id :: bound_value_identifiers rem - | Sig_module(id, _, _) :: rem -> id :: bound_value_identifiers rem - | Sig_class(id, _, _) :: rem -> id :: bound_value_identifiers rem - | _ :: rem -> bound_value_identifiers rem - - (* Code to translate class entries in a structure *) let transl_class_bindings cl_list = @@ -416,7 +425,7 @@ let rec compile_functor mexp coercion root_path loc = List.fold_left (fun (params, body) (param, loc, arg_coercion) -> let param' = Ident.rename param in let arg = apply_coercion loc Alias arg_coercion (Lvar param') in - let params = param' :: params in + let params = (param', Pgenval) :: params in let body = Llet (Alias, Pgenval, param, arg, body) in params, body) ([], transl_module res_coercion body_path body) @@ -425,9 +434,11 @@ let rec compile_functor mexp coercion root_path loc = Lfunction { kind = Curried; params; + return = Pgenval; attr = { inline = inline_attribute; specialise = Default_specialise; + local = Default_local; is_a_functor = true; stub = false; }; @@ -441,34 +452,31 @@ and transl_module cc rootpath mexp = List.iter (Translattribute.check_attribute_on_module mexp) mexp.mod_attributes; let loc = mexp.mod_loc in - match mexp.mod_type with - Mty_alias (Mta_absent, _) -> apply_coercion loc Alias cc lambda_unit - | _ -> - match mexp.mod_desc with - Tmod_ident (path,_) -> - apply_coercion loc Strict cc - (transl_module_path ~loc mexp.mod_env path) - | Tmod_structure str -> - fst (transl_struct loc [] cc rootpath str) - | Tmod_functor _ -> - oo_wrap mexp.mod_env true (fun () -> - compile_functor mexp cc rootpath loc) () - | Tmod_apply(funct, arg, ccarg) -> - let inlined_attribute, funct = - Translattribute.get_and_remove_inlined_attribute_on_module funct - in - oo_wrap mexp.mod_env true - (apply_coercion loc Strict cc) - (Lapply{ap_should_be_tailcall=false; - ap_loc=loc; - ap_func=transl_module Tcoerce_none None funct; - ap_args=[transl_module ccarg None arg]; - ap_inlined=inlined_attribute; - ap_specialised=Default_specialise}) - | Tmod_constraint(arg, _, _, ccarg) -> - transl_module (compose_coercions cc ccarg) rootpath arg - | Tmod_unpack(arg, _) -> - apply_coercion loc Strict cc (Translcore.transl_exp arg) + match mexp.mod_desc with + | Tmod_ident (path,_) -> + apply_coercion loc Strict cc + (transl_module_path loc mexp.mod_env path) + | Tmod_structure str -> + fst (transl_struct loc [] cc rootpath str) + | Tmod_functor _ -> + oo_wrap mexp.mod_env true (fun () -> + compile_functor mexp cc rootpath loc) () + | Tmod_apply(funct, arg, ccarg) -> + let inlined_attribute, funct = + Translattribute.get_and_remove_inlined_attribute_on_module funct + in + oo_wrap mexp.mod_env true + (apply_coercion loc Strict cc) + (Lapply{ap_should_be_tailcall=false; + ap_loc=loc; + ap_func=transl_module Tcoerce_none None funct; + ap_args=[transl_module ccarg None arg]; + ap_inlined=inlined_attribute; + ap_specialised=Default_specialise}) + | Tmod_constraint(arg, _, _, ccarg) -> + transl_module (compose_coercions cc ccarg) rootpath arg + | Tmod_unpack(arg, _) -> + apply_coercion loc Strict cc (Translcore.transl_exp arg) and transl_struct loc fields cc rootpath str = transl_structure loc fields cc rootpath str.str_final_env str.str_items @@ -491,8 +499,11 @@ and transl_structure loc fields cc rootpath final_env = function fields; Format.eprintf "@]@.";*) let v = Array.of_list (List.rev fields) in - let get_field pos = Lvar v.(pos) - and ids = List.fold_right Ident.Set.add fields Ident.Set.empty in + let get_field pos = + if pos < 0 then lambda_unit + else Lvar v.(pos) + in + let ids = List.fold_right Ident.Set.add fields Ident.Set.empty in let lam = Lprim(Pmakeblock(0, Immutable, None), List.map @@ -520,7 +531,7 @@ and transl_structure loc fields cc rootpath final_env = function {lev_loc = loc; lev_kind = Lev_pseudo; lev_repr = None; - lev_env = Env.summary final_env}) + lev_env = final_env}) else body), size @@ -553,15 +564,17 @@ and transl_structure loc fields cc rootpath final_env = function in transl_type_extension item.str_env rootpath tyext body, size | Tstr_exception ext -> - let id = ext.ext_id in + let id = ext.tyexn_constructor.ext_id in let path = field_path rootpath id in let body, size = transl_structure loc (id :: fields) cc rootpath final_env rem in Llet(Strict, Pgenval, id, - transl_extension_constructor item.str_env path ext, body), + transl_extension_constructor item.str_env + path + ext.tyexn_constructor, body), size - | Tstr_module mb -> + | Tstr_module ({mb_presence=Mp_present} as mb) -> let id = mb.mb_id in (* Translate module first *) let module_body = @@ -580,12 +593,14 @@ and transl_structure loc fields cc rootpath final_env = function lev_loc = mb.mb_loc; lev_kind = Lev_module_definition id; lev_repr = None; - lev_env = Env.summary Env.empty; + lev_env = Env.empty; }) in Llet(pure_module mb.mb_expr, Pgenval, id, module_body, body), size + | Tstr_module {mb_presence=Mp_absent} -> + transl_structure loc fields cc rootpath final_env rem | Tstr_recmodule bindings -> let ext_fields = List.rev_append (List.map (fun mb -> mb.mb_id) bindings) fields @@ -603,7 +618,7 @@ and transl_structure loc fields cc rootpath final_env = function lev_loc = loc; lev_kind = Lev_module_definition id; lev_repr = None; - lev_env = Env.summary Env.empty; + lev_env = Env.empty; })) bindings body @@ -619,7 +634,7 @@ and transl_structure loc fields cc rootpath final_env = function | Tstr_include incl -> let ids = bound_value_identifiers incl.incl_type in let modl = incl.incl_mod in - let mid = Ident.create "include" in + let mid = Ident.create_local "include" in let rec rebind_idents pos newfields = function [] -> transl_structure loc newfields cc rootpath final_env rem @@ -636,18 +651,38 @@ and transl_structure loc fields cc rootpath final_env = function transl_module Tcoerce_none None modl, body), size + | Tstr_open od -> + let pure = pure_module od.open_expr in + (* this optimization shouldn't be needed because Simplif would + actually remove the [Llet] when it's not used. + But since [scan_used_globals] runs before Simplif, we need to do + it. *) + begin match od.open_bound_items with + | [] when pure = Alias -> + transl_structure loc fields cc rootpath final_env rem + | _ -> + let ids = bound_value_identifiers od.open_bound_items in + let mid = Ident.create_local "open" in + let rec rebind_idents pos newfields = function + [] -> + transl_structure loc newfields cc rootpath final_env rem + | id :: ids -> + let body, size = + rebind_idents (pos + 1) (id :: newfields) ids + in + Llet(Alias, Pgenval, id, + Lprim(Pfield pos, [Lvar mid], od.open_loc), body), + size + in + let body, size = rebind_idents 0 fields ids in + Llet(pure, Pgenval, mid, + transl_module Tcoerce_none None od.open_expr, body), size + end | Tstr_modtype _ - | Tstr_open _ | Tstr_class_type _ | Tstr_attribute _ -> transl_structure loc fields cc rootpath final_env rem -and pure_module m = - match m.mod_desc with - Tmod_ident _ -> Alias - | Tmod_constraint (m,_,_,_) -> pure_module m - | _ -> Strict - (* Update forward declaration in Translcore *) let _ = Translcore.transl_module := transl_module @@ -728,12 +763,14 @@ let rec defined_idents = function | Tstr_typext tyext -> List.map (fun ext -> ext.ext_id) tyext.tyext_constructors @ defined_idents rem - | Tstr_exception ext -> ext.ext_id :: defined_idents rem - | Tstr_module mb -> mb.mb_id :: defined_idents rem + | Tstr_exception ext -> ext.tyexn_constructor.ext_id :: defined_idents rem + | Tstr_module {mb_id; mb_presence=Mp_present} -> mb_id :: defined_idents rem + | Tstr_module {mb_presence=Mp_absent} -> defined_idents rem | Tstr_recmodule decls -> List.map (fun mb -> mb.mb_id) decls @ defined_idents rem | Tstr_modtype _ -> defined_idents rem - | Tstr_open _ -> defined_idents rem + | Tstr_open od -> + bound_value_identifiers od.open_bound_items @ defined_idents rem | Tstr_class cl_list -> List.map (fun (ci, _) -> ci.ci_id_class) cl_list @ defined_idents rem | Tstr_class_type _ -> defined_idents rem @@ -755,7 +792,12 @@ let rec more_idents = function | Tstr_exception _ -> more_idents rem | Tstr_recmodule _ -> more_idents rem | Tstr_modtype _ -> more_idents rem - | Tstr_open _ -> more_idents rem + | Tstr_open od -> + let rest = more_idents rem in + begin match od.open_expr.mod_desc with + | Tmod_structure str -> all_idents str.str_items @ rest + | _ -> rest + end | Tstr_class _ -> more_idents rem | Tstr_class_type _ -> more_idents rem | Tstr_include{incl_mod={mod_desc = @@ -763,10 +805,12 @@ let rec more_idents = function _, _, _)}} -> all_idents str.str_items @ more_idents rem | Tstr_include _ -> more_idents rem - | Tstr_module {mb_expr={mod_desc = Tmod_structure str}} - | Tstr_module{mb_expr={mod_desc = - Tmod_constraint ({mod_desc = Tmod_structure str}, - _, _, _)}} -> + | Tstr_module + {mb_presence=Mp_present; mb_expr={mod_desc = Tmod_structure str}} + | Tstr_module + {mb_presence=Mp_present; + mb_expr={mod_desc= + Tmod_constraint ({mod_desc = Tmod_structure str}, _, _, _)}} -> all_idents str.str_items @ more_idents rem | Tstr_module _ -> more_idents rem | Tstr_attribute _ -> more_idents rem @@ -783,11 +827,19 @@ and all_idents = function | Tstr_typext tyext -> List.map (fun ext -> ext.ext_id) tyext.tyext_constructors @ all_idents rem - | Tstr_exception ext -> ext.ext_id :: all_idents rem + | Tstr_exception ext -> ext.tyexn_constructor.ext_id :: all_idents rem | Tstr_recmodule decls -> List.map (fun mb -> mb.mb_id) decls @ all_idents rem | Tstr_modtype _ -> all_idents rem - | Tstr_open _ -> all_idents rem + | Tstr_open od -> + let rest = all_idents rem in + begin match od.open_expr.mod_desc with + | Tmod_structure str -> + bound_value_identifiers od.open_bound_items + @ all_idents str.str_items + @ rest + | _ -> bound_value_identifiers od.open_bound_items @ rest + end | Tstr_class cl_list -> List.map (fun (ci, _) -> ci.ci_id_class) cl_list @ all_idents rem | Tstr_class_type _ -> all_idents rem @@ -795,17 +847,22 @@ and all_idents = function | Tstr_include{incl_type; incl_mod={mod_desc = Tmod_constraint ({mod_desc = Tmod_structure str}, _, _, _)}} -> - bound_value_identifiers incl_type @ all_idents str.str_items @ all_idents rem + bound_value_identifiers incl_type + @ all_idents str.str_items + @ all_idents rem | Tstr_include incl -> bound_value_identifiers incl.incl_type @ all_idents rem - | Tstr_module {mb_id;mb_expr={mod_desc = Tmod_structure str}} - | Tstr_module{mb_id; - mb_expr={mod_desc = - Tmod_constraint ({mod_desc = Tmod_structure str}, - _, _, _)}} -> + | Tstr_module + {mb_id;mb_presence=Mp_present;mb_expr={mod_desc = Tmod_structure str}} + | Tstr_module + {mb_id;mb_presence=Mp_present; + mb_expr= + {mod_desc = + Tmod_constraint ({mod_desc = Tmod_structure str}, _, _, _)}} -> mb_id :: all_idents str.str_items @ all_idents rem - | Tstr_module mb -> mb.mb_id :: all_idents rem + | Tstr_module {mb_id;mb_presence=Mp_present} -> mb_id :: all_idents rem + | Tstr_module {mb_presence=Mp_absent} -> all_idents rem | Tstr_attribute _ -> all_idents rem @@ -835,31 +892,37 @@ let field_of_str loc str = match cc with | Tcoerce_primitive { pc_loc; pc_desc; pc_env; pc_type; } -> Translprim.transl_primitive pc_loc pc_desc pc_env pc_type None + | Tcoerce_alias (env, path, cc) -> + let lam = transl_module_path loc env path in + apply_coercion loc Alias cc lam | _ -> apply_coercion loc Strict cc (Lvar ids.(pos)) -let transl_store_structure glob map prims str = - let rec transl_store rootpath subst = function +let transl_store_structure glob map prims aliases str = + let no_env_update _ _ env = env in + let rec transl_store rootpath subst cont = function [] -> transl_store_subst := subst; - lambda_unit + Lambda.subst no_env_update subst cont | item :: rem -> match item.str_desc with | Tstr_eval (expr, _attrs) -> - Lsequence(Lambda.subst subst (transl_exp expr), - transl_store rootpath subst rem) + Lsequence(Lambda.subst no_env_update subst (transl_exp expr), + transl_store rootpath subst cont rem) | Tstr_value(rec_flag, pat_expr_list) -> let ids = let_bound_idents pat_expr_list in let lam = - transl_let rec_flag pat_expr_list (store_idents Location.none ids) + transl_let rec_flag pat_expr_list + (store_idents Location.none ids) in - Lsequence(Lambda.subst subst lam, - transl_store rootpath (add_idents false ids subst) rem) + Lsequence(Lambda.subst no_env_update subst lam, + transl_store rootpath + (add_idents false ids subst) cont rem) | Tstr_primitive descr -> record_primitive descr.val_val; - transl_store rootpath subst rem + transl_store rootpath subst cont rem | Tstr_type _ -> - transl_store rootpath subst rem + transl_store rootpath subst cont rem | Tstr_typext(tyext) -> let ids = List.map (fun ext -> ext.ext_id) tyext.tyext_constructors @@ -868,37 +931,45 @@ let transl_store_structure glob map prims str = transl_type_extension item.str_env rootpath tyext (store_idents Location.none ids) in - Lsequence(Lambda.subst subst lam, - transl_store rootpath (add_idents false ids subst) rem) + Lsequence(Lambda.subst no_env_update subst lam, + transl_store rootpath + (add_idents false ids subst) cont rem) | Tstr_exception ext -> - let id = ext.ext_id in + let id = ext.tyexn_constructor.ext_id in let path = field_path rootpath id in - let lam = transl_extension_constructor item.str_env path ext in - Lsequence(Llet(Strict, Pgenval, id, Lambda.subst subst lam, - store_ident ext.ext_loc id), - transl_store rootpath (add_ident false id subst) rem) - | Tstr_module{mb_id=id;mb_loc=loc; + let lam = + transl_extension_constructor item.str_env + path + ext.tyexn_constructor + in + Lsequence(Llet(Strict, Pgenval, id, + Lambda.subst no_env_update subst lam, + store_ident ext.tyexn_constructor.ext_loc id), + transl_store rootpath + (add_ident false id subst) cont rem) + | Tstr_module{mb_id=id;mb_loc=loc;mb_presence=Mp_present; mb_expr={mod_desc = Tmod_structure str} as mexp; mb_attributes} -> List.iter (Translattribute.check_attribute_on_module mexp) mb_attributes; let lam = - transl_store (field_path rootpath id) subst str.str_items + transl_store (field_path rootpath id) subst + lambda_unit str.str_items in (* Careful: see next case *) let subst = !transl_store_subst in Lsequence(lam, Llet(Strict, Pgenval, id, - Lambda.subst subst + Lambda.subst no_env_update subst (Lprim(Pmakeblock(0, Immutable, None), List.map (fun id -> Lvar id) (defined_idents str.str_items), loc)), Lsequence(store_ident loc id, transl_store rootpath (add_ident true id subst) - rem))) + cont rem))) | Tstr_module{ - mb_id=id;mb_loc=loc; + mb_id=id;mb_loc=loc;mb_presence=Mp_present; mb_expr= { mod_desc = Tmod_constraint ( {mod_desc = Tmod_structure str} as mexp, _, _, @@ -910,21 +981,24 @@ let transl_store_structure glob map prims str = List.iter (Translattribute.check_attribute_on_module mexp) mb_attributes; let lam = - transl_store (field_path rootpath id) subst str.str_items + transl_store (field_path rootpath id) subst + lambda_unit str.str_items in (* Careful: see next case *) let subst = !transl_store_subst in let field = field_of_str loc str in Lsequence(lam, Llet(Strict, Pgenval, id, - Lambda.subst subst + Lambda.subst no_env_update subst (Lprim(Pmakeblock(0, Immutable, None), List.map field map, loc)), Lsequence(store_ident loc id, transl_store rootpath (add_ident true id subst) - rem))) - | Tstr_module{mb_id=id; mb_expr=modl; mb_loc=loc; mb_attributes} -> + cont rem))) + | Tstr_module + {mb_id=id; mb_presence=Mp_present; mb_expr=modl; + mb_loc=loc; mb_attributes} -> let lam = Translattribute.add_inline_attribute (transl_module Tcoerce_none (field_path rootpath id) modl) @@ -936,26 +1010,31 @@ let transl_store_structure glob map prims str = the compilation unit (add_ident true returns subst unchanged). If not, we can use the value from the global (add_ident true adds id -> Pgetglobal... to subst). *) - Llet(Strict, Pgenval, id, Lambda.subst subst lam, + Llet(Strict, Pgenval, id, Lambda.subst no_env_update subst lam, Lsequence(store_ident loc id, - transl_store rootpath (add_ident true id subst) rem)) + transl_store rootpath (add_ident true id subst) + cont rem)) + | Tstr_module {mb_presence=Mp_absent} -> + transl_store rootpath subst cont rem | Tstr_recmodule bindings -> let ids = List.map (fun mb -> mb.mb_id) bindings in compile_recmodule (fun id modl _loc -> - Lambda.subst subst + Lambda.subst no_env_update subst (transl_module Tcoerce_none (field_path rootpath id) modl)) bindings (Lsequence(store_idents Location.none ids, - transl_store rootpath (add_idents true ids subst) rem)) + transl_store rootpath (add_idents true ids subst) + cont rem)) | Tstr_class cl_list -> let (ids, class_bindings) = transl_class_bindings cl_list in let lam = Lletrec(class_bindings, store_idents Location.none ids) in - Lsequence(Lambda.subst subst lam, - transl_store rootpath (add_idents false ids subst) rem) + Lsequence(Lambda.subst no_env_update subst lam, + transl_store rootpath (add_idents false ids subst) + cont rem) | Tstr_include{ incl_loc=loc; @@ -971,7 +1050,7 @@ let transl_store_structure glob map prims str = (* Shouldn't we use mod_attributes instead of incl_attributes? Same question for the Tstr_module cases above, btw. *) let lam = - transl_store None subst str.str_items + transl_store None subst lambda_unit str.str_items (* It is tempting to pass rootpath instead of None in order to give a more precise name to exceptions in the included structured, but this would introduce @@ -983,9 +1062,11 @@ let transl_store_structure glob map prims str = let rec loop ids args = match ids, args with | [], [] -> - transl_store rootpath (add_idents true ids0 subst) rem + transl_store rootpath (add_idents true ids0 subst) + cont rem | id :: ids, arg :: args -> - Llet(Alias, Pgenval, id, Lambda.subst subst (field arg), + Llet(Alias, Pgenval, id, + Lambda.subst no_env_update subst (field arg), Lsequence(store_ident loc id, loop ids args)) | _ -> assert false @@ -996,23 +1077,69 @@ let transl_store_structure glob map prims str = | Tstr_include incl -> let ids = bound_value_identifiers incl.incl_type in let modl = incl.incl_mod in - let mid = Ident.create "include" in + let mid = Ident.create_local "include" in let loc = incl.incl_loc in let rec store_idents pos = function - [] -> transl_store rootpath (add_idents true ids subst) rem + | [] -> + transl_store rootpath (add_idents true ids subst) cont rem | id :: idl -> Llet(Alias, Pgenval, id, Lprim(Pfield pos, [Lvar mid], loc), Lsequence(store_ident loc id, store_idents (pos + 1) idl)) in Llet(Strict, Pgenval, mid, - Lambda.subst subst (transl_module Tcoerce_none None modl), + Lambda.subst no_env_update subst + (transl_module Tcoerce_none None modl), store_idents 0 ids) + | Tstr_open od -> + begin match od.open_expr.mod_desc with + | Tmod_structure str -> + let lam = + transl_store rootpath subst lambda_unit str.str_items + in + let ids = Array.of_list (defined_idents str.str_items) in + let ids0 = bound_value_identifiers od.open_bound_items in + let subst = !transl_store_subst in + let rec store_idents pos = function + | [] -> transl_store rootpath subst cont rem + | id :: idl -> + Llet(Alias, Pgenval, id, Lvar ids.(pos), + Lsequence(store_ident od.open_loc id, + store_idents (pos + 1) idl)) + in + Lsequence(lam, Lambda.subst no_env_update subst + (store_idents 0 ids0)) + | _ -> + let pure = pure_module od.open_expr in + (* this optimization shouldn't be needed because Simplif would + actually remove the [Llet] when it's not used. + But since [scan_used_globals] runs before Simplif, we need to + do it. *) + match od.open_bound_items with + | [] when pure = Alias -> transl_store rootpath subst cont rem + | _ -> + let ids = bound_value_identifiers od.open_bound_items in + let mid = Ident.create_local "open" in + let loc = od.open_loc in + let rec store_idents pos = function + [] -> + transl_store rootpath (add_idents true ids subst) cont + rem + | id :: idl -> + Llet(Alias, Pgenval, id, Lprim(Pfield pos, [Lvar mid], + loc), + Lsequence(store_ident loc id, + store_idents (pos + 1) idl)) + in + Llet(pure, Pgenval, mid, + Lambda.subst no_env_update subst + (transl_module Tcoerce_none None od.open_expr), + store_idents 0 ids) + end | Tstr_modtype _ - | Tstr_open _ | Tstr_class_type _ | Tstr_attribute _ -> - transl_store rootpath subst rem + transl_store rootpath subst cont rem and store_ident loc id = try @@ -1053,8 +1180,17 @@ let transl_store_structure glob map prims str = Location.none), cont) - in List.fold_right store_primitive prims - (transl_store (global_path glob) !transl_store_subst str) + and store_alias (pos, env, path, cc) = + let path_lam = transl_module_path Location.none env path in + let init_val = apply_coercion Location.none Strict cc path_lam in + Lprim(Psetfield(pos, Pointer, Root_initialization), + [Lprim(Pgetglobal glob, [], Location.none); + init_val], + Location.none) + in + let aliases = make_sequence store_alias aliases in + List.fold_right store_primitive prims + (transl_store (global_path glob) !transl_store_subst aliases str) (* Transform a coercion and the list of value identifiers defined by a toplevel structure into a table [id -> (pos, coercion)], @@ -1069,32 +1205,39 @@ let transl_store_structure glob map prims str = and the list of all primitives exported as values. *) let build_ident_map restr idlist more_ids = - let rec natural_map pos map prims = function - [] -> - (map, prims, pos) + let rec natural_map pos map prims aliases = function + | [] -> + (map, prims, aliases, pos) | id :: rem -> - natural_map (pos+1) (Ident.add id (pos, Tcoerce_none) map) prims rem in - let (map, prims, pos) = + natural_map (pos+1) + (Ident.add id (pos, Tcoerce_none) map) prims aliases rem + in + let (map, prims, aliases, pos) = match restr with - Tcoerce_none -> - natural_map 0 Ident.empty [] idlist - | Tcoerce_structure (pos_cc_list, _id_pos_list) -> - (* ignore _id_pos_list as the ids are already bound *) + | Tcoerce_none -> + natural_map 0 Ident.empty [] [] idlist + | Tcoerce_structure (pos_cc_list, _id_pos_list) -> + (* ignore _id_pos_list as the ids are already bound *) let idarray = Array.of_list idlist in - let rec export_map pos map prims undef = function - [] -> - natural_map pos map prims undef + let rec export_map pos map prims aliases undef = function + | [] -> + natural_map pos map prims aliases undef | (_source_pos, Tcoerce_primitive p) :: rem -> - export_map (pos + 1) map ((pos, p) :: prims) undef rem + export_map (pos + 1) map + ((pos, p) :: prims) aliases undef rem + | (_source_pos, Tcoerce_alias(env, path, cc)) :: rem -> + export_map (pos + 1) map prims + ((pos, env, path, cc) :: aliases) undef rem | (source_pos, cc) :: rem -> - let id = idarray.(source_pos) in - export_map (pos + 1) (Ident.add id (pos, cc) map) - prims (list_remove id undef) rem - in export_map 0 Ident.empty [] idlist pos_cc_list - | _ -> + let id = idarray.(source_pos) in + export_map (pos + 1) (Ident.add id (pos, cc) map) + prims aliases (list_remove id undef) rem + in + export_map 0 Ident.empty [] [] idlist pos_cc_list + | _ -> fatal_error "Translmod.build_ident_map" in - natural_map pos map prims more_ids + natural_map pos map prims aliases more_ids (* Compile an implementation using transl_store_structure (for the native-code compiler). *) @@ -1104,13 +1247,14 @@ let transl_store_gen module_name ({ str_items = str }, restr) topl = primitive_declarations := []; Translprim.clear_used_primitives (); let module_id = Ident.create_persistent module_name in - let (map, prims, size) = + let (map, prims, aliases, size) = build_ident_map restr (defined_idents str) (more_idents str) in let f = function | [ { str_desc = Tstr_eval (expr, _attrs) } ] when topl -> assert (size = 0); - Lambda.subst !transl_store_subst (transl_exp expr) - | str -> transl_store_structure module_id map prims str in + Lambda.subst (fun _ _ env -> env) !transl_store_subst (transl_exp expr) + | str -> transl_store_structure module_id map prims aliases str + in transl_store_label_init module_id size f str (*size, transl_label_init (transl_store_structure module_id map prims str)*) @@ -1197,10 +1341,10 @@ let transl_toplevel_item item = transl_type_extension item.str_env None tyext (make_sequence toploop_setvalue_id idents) | Tstr_exception ext -> - set_toplevel_unique_name ext.ext_id; - toploop_setvalue ext.ext_id - (transl_extension_constructor item.str_env None ext) - | Tstr_module {mb_id=id; mb_expr=modl} -> + set_toplevel_unique_name ext.tyexn_constructor.ext_id; + toploop_setvalue ext.tyexn_constructor.ext_id + (transl_extension_constructor item.str_env None ext.tyexn_constructor) + | Tstr_module {mb_id=id; mb_presence=Mp_present; mb_expr=modl} -> (* we need to use the unique name for the module because of issues with "open" (PR#1672) *) set_toplevel_unique_name id; @@ -1221,7 +1365,7 @@ let transl_toplevel_item item = | Tstr_include incl -> let ids = bound_value_identifiers incl.incl_type in let modl = incl.incl_mod in - let mid = Ident.create "include" in + let mid = Ident.create_local "include" in let rec set_idents pos = function [] -> lambda_unit @@ -1231,9 +1375,33 @@ let transl_toplevel_item item = set_idents (pos + 1) ids) in Llet(Strict, Pgenval, mid, transl_module Tcoerce_none None modl, set_idents 0 ids) + | Tstr_primitive descr -> + record_primitive descr.val_val; + lambda_unit + | Tstr_open od -> + let pure = pure_module od.open_expr in + (* this optimization shouldn't be needed because Simplif would + actually remove the [Llet] when it's not used. + But since [scan_used_globals] runs before Simplif, we need to do + it. *) + begin match od.open_bound_items with + | [] when pure = Alias -> lambda_unit + | _ -> + let ids = bound_value_identifiers od.open_bound_items in + let mid = Ident.create_local "open" in + let rec set_idents pos = function + [] -> + lambda_unit + | id :: ids -> + Lsequence(toploop_setvalue id + (Lprim(Pfield pos, [Lvar mid], Location.none)), + set_idents (pos + 1) ids) + in + Llet(pure, Pgenval, mid, + transl_module Tcoerce_none None od.open_expr, set_idents 0 ids) + end | Tstr_modtype _ - | Tstr_open _ - | Tstr_primitive _ + | Tstr_module {mb_presence=Mp_absent} | Tstr_type _ | Tstr_class_type _ | Tstr_attribute _ -> @@ -1313,7 +1481,7 @@ let transl_store_package component_names target_name coercion = List.map get_component component_names, Location.none) in - let blk = Ident.create "block" in + let blk = Ident.create_local "block" in (List.length pos_cc_list, Llet (Strict, Pgenval, blk, apply_coercion Location.none Strict coercion components, @@ -1341,27 +1509,41 @@ let transl_store_package component_names target_name coercion = open Format -let print_cycle ppf = - Format.pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf "@ -> ") - Printtyp.ident ppf - -let report_error ppf = function - Circular_dependency cycle -> - let[@manual.ref "s-recursive-modules"] chapter, section = 8, 4 in - fprintf ppf - "@[Cannot safely evaluate the definition of the following cycle@ \ +let print_cycle ppf cycle = + let print_ident ppf (x,_) = Format.pp_print_string ppf (Ident.name x) in + let pp_sep ppf () = fprintf ppf "@ -> " in + Format.fprintf ppf "%a%a%s" + (Format.pp_print_list ~pp_sep print_ident) cycle + pp_sep () + (Ident.name @@ fst @@ List.hd cycle) +(* we repeat the first element to make the cycle more apparent *) + +let explanation_submsg (id, {reason;loc;subid}) = + let print fmt = + let printer = Format.dprintf fmt (Ident.name id) (Ident.name subid) in + Location.mkloc printer loc in + match reason with + | Unsafe_module_binding -> print "Module %s defines an unsafe module, %s ." + | Unsafe_functor -> print "Module %s defines an unsafe functor, %s ." + | Unsafe_typext -> + print "Module %s defines an unsafe extension constructor, %s ." + | Unsafe_non_function -> print "Module %s defines an unsafe value, %s ." + +let report_error loc = function + | Circular_dependency cycle -> + let[@manual.ref "s-recursive-modules"] chapter, section = 8, 2 in + Location.errorf ~loc ~sub:(List.map explanation_submsg cycle) + "Cannot safely evaluate the definition of the following cycle@ \ of recursively-defined modules:@ %a.@ \ - There are no safe modules in this cycle@ (see manual section %d.%d)@]" + There are no safe modules in this cycle@ (see manual section %d.%d)." print_cycle cycle chapter section | Conflicting_inline_attributes -> - fprintf ppf - "@[Conflicting ``inline'' attributes@]" + Location.errorf "@[Conflicting 'inline' attributes@]" let () = Location.register_error_of_exn (function - | Error (loc, err) -> - Some (Location.error_of_printer loc report_error err) + | Error (loc, err) -> Some (report_error loc err) | _ -> None ) diff --git a/bytecomp/translmod.mli b/bytecomp/translmod.mli index 3098e543..d0898c76 100644 --- a/bytecomp/translmod.mli +++ b/bytecomp/translmod.mli @@ -42,12 +42,20 @@ val nat_toplevel_name: Ident.t -> Ident.t * int val primitive_declarations: Primitive.description list ref +type unsafe_component = + | Unsafe_module_binding + | Unsafe_functor + | Unsafe_non_function + | Unsafe_typext + +type unsafe_info = { reason:unsafe_component; loc:Location.t; subid:Ident.t } + type error = - Circular_dependency of Ident.t list + Circular_dependency of (Ident.t * unsafe_info) list | Conflicting_inline_attributes exception Error of Location.t * error -val report_error: Format.formatter -> error -> unit +val report_error: Location.t -> error -> Location.error val reset: unit -> unit diff --git a/bytecomp/translobj.ml b/bytecomp/translobj.ml index dd55acf3..ce063538 100644 --- a/bytecomp/translobj.ml +++ b/bytecomp/translobj.ml @@ -13,19 +13,12 @@ (* *) (**************************************************************************) -open Misc open Asttypes -open Longident open Lambda (* Get oo primitives identifiers *) -let oo_prim name = - try - transl_normal_path - (fst (Env.lookup_value (Ldot (Lident "CamlinternalOO", name)) Env.empty)) - with Not_found -> - fatal_error ("Primitive " ^ name ^ " not found.") +let oo_prim = Lambda.transl_prim "CamlinternalOO" (* Share blocks *) @@ -37,7 +30,7 @@ let share c = begin try Lvar (Hashtbl.find consts c) with Not_found -> - let id = Ident.create "shared" in + let id = Ident.create_local "shared" in Hashtbl.add consts c id; Lvar id end @@ -112,7 +105,7 @@ let transl_label_init_general f = let transl_label_init_flambda f = assert(Config.flambda); - let method_cache_id = Ident.create "method_cache" in + let method_cache_id = Ident.create_local "method_cache" in method_cache := Lvar method_cache_id; (* Calling f (usually Translmod.transl_struct) requires the method_cache variable to be initialised to be able to generate @@ -171,32 +164,28 @@ let oo_add_class id = let oo_wrap env req f x = if !wrapping then if !cache_required then f x else - try cache_required := true; let lam = f x in cache_required := false; lam - with exn -> cache_required := false; raise exn - else try - wrapping := true; - cache_required := req; - top_env := env; - classes := []; - method_ids := Ident.Set.empty; - let lambda = f x in - let lambda = - List.fold_left - (fun lambda id -> - Llet(StrictOpt, Pgenval, id, - Lprim(Pmakeblock(0, Mutable, None), - [lambda_unit; lambda_unit; lambda_unit], - Location.none), - lambda)) - lambda !classes - in - wrapping := false; - top_env := Env.empty; - lambda - with exn -> - wrapping := false; - top_env := Env.empty; - raise exn + Misc.protect_refs [Misc.R (cache_required, true)] (fun () -> + f x + ) + else + Misc.protect_refs [Misc.R (wrapping, true); Misc.R (top_env, env)] + (fun () -> + cache_required := req; + classes := []; + method_ids := Ident.Set.empty; + let lambda = f x in + let lambda = + List.fold_left + (fun lambda id -> + Llet(StrictOpt, Pgenval, id, + Lprim(Pmakeblock(0, Mutable, None), + [lambda_unit; lambda_unit; lambda_unit], + Location.none), + lambda)) + lambda !classes + in + lambda + ) let reset () = Hashtbl.clear consts; diff --git a/bytecomp/translprim.ml b/bytecomp/translprim.ml index 25cc6154..448a2ac8 100644 --- a/bytecomp/translprim.ml +++ b/bytecomp/translprim.ml @@ -38,7 +38,7 @@ let event_before exp lam = match lam with then Levent(lam, {lev_loc = exp.exp_loc; lev_kind = Lev_before; lev_repr = None; - lev_env = Env.summary exp.exp_env}) + lev_env = exp.exp_env}) else lam let event_after exp lam = @@ -46,7 +46,7 @@ let event_after exp lam = then Levent(lam, {lev_loc = exp.exp_loc; lev_kind = Lev_after exp.exp_type; lev_repr = None; - lev_env = Env.summary exp.exp_env}) + lev_env = exp.exp_env}) else lam type comparison = @@ -76,7 +76,8 @@ type loc_kind = | Loc_POS type prim = - | Primitive of Lambda.primitive + | Primitive of Lambda.primitive * int + | External of Primitive.description | Comparison of comparison * comparison_kind | Raise of Lambda.raise_kind | Raise_with_backtrace @@ -90,7 +91,7 @@ let used_primitives = Hashtbl.create 7 let add_used_primitive loc env path = match path with Some (Path.Pdot _ as path) -> - let path = Env.normalize_path (Some loc) env path in + let path = Env.normalize_path_prefix (Some loc) env path in let unit = Path.head path in if Ident.global unit && not (Hashtbl.mem used_primitives path) then Hashtbl.add used_primitives path loc @@ -103,248 +104,268 @@ let get_used_primitives () = let gen_array_kind = if Config.flat_float_array then Pgenarray else Paddrarray -let primitives_table = create_hashtable 57 [ - "%identity", Primitive Pidentity; - "%bytes_to_string", Primitive Pbytes_to_string; - "%bytes_of_string", Primitive Pbytes_of_string; - "%ignore", Primitive Pignore; - "%revapply", Primitive Prevapply; - "%apply", Primitive Pdirapply; - "%loc_LOC", Loc Loc_LOC; - "%loc_FILE", Loc Loc_FILE; - "%loc_LINE", Loc Loc_LINE; - "%loc_POS", Loc Loc_POS; - "%loc_MODULE", Loc Loc_MODULE; - "%field0", Primitive (Pfield 0); - "%field1", Primitive (Pfield 1); - "%setfield0", Primitive (Psetfield(0, Pointer, Assignment)); - "%makeblock", Primitive (Pmakeblock(0, Immutable, None)); - "%makemutable", Primitive (Pmakeblock(0, Mutable, None)); - "%raise", Raise Raise_regular; - "%reraise", Raise Raise_reraise; - "%raise_notrace", Raise Raise_notrace; - "%raise_with_backtrace", Raise_with_backtrace; - "%sequand", Primitive Psequand; - "%sequor", Primitive Psequor; - "%boolnot", Primitive Pnot; - "%big_endian", Primitive (Pctconst Big_endian); - "%backend_type", Primitive (Pctconst Backend_type); - "%word_size", Primitive (Pctconst Word_size); - "%int_size", Primitive (Pctconst Int_size); - "%max_wosize", Primitive (Pctconst Max_wosize); - "%ostype_unix", Primitive (Pctconst Ostype_unix); - "%ostype_win32", Primitive (Pctconst Ostype_win32); - "%ostype_cygwin", Primitive (Pctconst Ostype_cygwin); - "%negint", Primitive Pnegint; - "%succint", Primitive (Poffsetint 1); - "%predint", Primitive (Poffsetint(-1)); - "%addint", Primitive Paddint; - "%subint", Primitive Psubint; - "%mulint", Primitive Pmulint; - "%divint", Primitive (Pdivint Safe); - "%modint", Primitive (Pmodint Safe); - "%andint", Primitive Pandint; - "%orint", Primitive Porint; - "%xorint", Primitive Pxorint; - "%lslint", Primitive Plslint; - "%lsrint", Primitive Plsrint; - "%asrint", Primitive Pasrint; - "%eq", Primitive (Pintcomp Ceq); - "%noteq", Primitive (Pintcomp Cne); - "%ltint", Primitive (Pintcomp Clt); - "%leint", Primitive (Pintcomp Cle); - "%gtint", Primitive (Pintcomp Cgt); - "%geint", Primitive (Pintcomp Cge); - "%incr", Primitive (Poffsetref(1)); - "%decr", Primitive (Poffsetref(-1)); - "%intoffloat", Primitive Pintoffloat; - "%floatofint", Primitive Pfloatofint; - "%negfloat", Primitive Pnegfloat; - "%absfloat", Primitive Pabsfloat; - "%addfloat", Primitive Paddfloat; - "%subfloat", Primitive Psubfloat; - "%mulfloat", Primitive Pmulfloat; - "%divfloat", Primitive Pdivfloat; - "%eqfloat", Primitive (Pfloatcomp CFeq); - "%noteqfloat", Primitive (Pfloatcomp CFneq); - "%ltfloat", Primitive (Pfloatcomp CFlt); - "%lefloat", Primitive (Pfloatcomp CFle); - "%gtfloat", Primitive (Pfloatcomp CFgt); - "%gefloat", Primitive (Pfloatcomp CFge); - "%string_length", Primitive Pstringlength; - "%string_safe_get", Primitive Pstringrefs; - "%string_safe_set", Primitive Pbytessets; - "%string_unsafe_get", Primitive Pstringrefu; - "%string_unsafe_set", Primitive Pbytessetu; - "%bytes_length", Primitive Pbyteslength; - "%bytes_safe_get", Primitive Pbytesrefs; - "%bytes_safe_set", Primitive Pbytessets; - "%bytes_unsafe_get", Primitive Pbytesrefu; - "%bytes_unsafe_set", Primitive Pbytessetu; - "%array_length", Primitive (Parraylength gen_array_kind); - "%array_safe_get", Primitive (Parrayrefs gen_array_kind); - "%array_safe_set", Primitive (Parraysets gen_array_kind); - "%array_unsafe_get", Primitive (Parrayrefu gen_array_kind); - "%array_unsafe_set", Primitive (Parraysetu gen_array_kind); - "%obj_size", Primitive (Parraylength gen_array_kind); - "%obj_field", Primitive (Parrayrefu gen_array_kind); - "%obj_set_field", Primitive (Parraysetu gen_array_kind); - "%floatarray_length", Primitive (Parraylength Pfloatarray); - "%floatarray_safe_get", Primitive (Parrayrefs Pfloatarray); - "%floatarray_safe_set", Primitive (Parraysets Pfloatarray); - "%floatarray_unsafe_get", Primitive (Parrayrefu Pfloatarray); - "%floatarray_unsafe_set", Primitive (Parraysetu Pfloatarray); - "%obj_is_int", Primitive Pisint; - "%lazy_force", Lazy_force; - "%nativeint_of_int", Primitive (Pbintofint Pnativeint); - "%nativeint_to_int", Primitive (Pintofbint Pnativeint); - "%nativeint_neg", Primitive (Pnegbint Pnativeint); - "%nativeint_add", Primitive (Paddbint Pnativeint); - "%nativeint_sub", Primitive (Psubbint Pnativeint); - "%nativeint_mul", Primitive (Pmulbint Pnativeint); - "%nativeint_div", Primitive (Pdivbint { size = Pnativeint; is_safe = Safe }); - "%nativeint_mod", Primitive (Pmodbint { size = Pnativeint; is_safe = Safe }); - "%nativeint_and", Primitive (Pandbint Pnativeint); - "%nativeint_or", Primitive (Porbint Pnativeint); - "%nativeint_xor", Primitive (Pxorbint Pnativeint); - "%nativeint_lsl", Primitive (Plslbint Pnativeint); - "%nativeint_lsr", Primitive (Plsrbint Pnativeint); - "%nativeint_asr", Primitive (Pasrbint Pnativeint); - "%int32_of_int", Primitive (Pbintofint Pint32); - "%int32_to_int", Primitive (Pintofbint Pint32); - "%int32_neg", Primitive (Pnegbint Pint32); - "%int32_add", Primitive (Paddbint Pint32); - "%int32_sub", Primitive (Psubbint Pint32); - "%int32_mul", Primitive (Pmulbint Pint32); - "%int32_div", Primitive (Pdivbint { size = Pint32; is_safe = Safe }); - "%int32_mod", Primitive (Pmodbint { size = Pint32; is_safe = Safe }); - "%int32_and", Primitive (Pandbint Pint32); - "%int32_or", Primitive (Porbint Pint32); - "%int32_xor", Primitive (Pxorbint Pint32); - "%int32_lsl", Primitive (Plslbint Pint32); - "%int32_lsr", Primitive (Plsrbint Pint32); - "%int32_asr", Primitive (Pasrbint Pint32); - "%int64_of_int", Primitive (Pbintofint Pint64); - "%int64_to_int", Primitive (Pintofbint Pint64); - "%int64_neg", Primitive (Pnegbint Pint64); - "%int64_add", Primitive (Paddbint Pint64); - "%int64_sub", Primitive (Psubbint Pint64); - "%int64_mul", Primitive (Pmulbint Pint64); - "%int64_div", Primitive (Pdivbint { size = Pint64; is_safe = Safe }); - "%int64_mod", Primitive (Pmodbint { size = Pint64; is_safe = Safe }); - "%int64_and", Primitive (Pandbint Pint64); - "%int64_or", Primitive (Porbint Pint64); - "%int64_xor", Primitive (Pxorbint Pint64); - "%int64_lsl", Primitive (Plslbint Pint64); - "%int64_lsr", Primitive (Plsrbint Pint64); - "%int64_asr", Primitive (Pasrbint Pint64); - "%nativeint_of_int32", Primitive (Pcvtbint(Pint32, Pnativeint)); - "%nativeint_to_int32", Primitive (Pcvtbint(Pnativeint, Pint32)); - "%int64_of_int32", Primitive (Pcvtbint(Pint32, Pint64)); - "%int64_to_int32", Primitive (Pcvtbint(Pint64, Pint32)); - "%int64_of_nativeint", Primitive (Pcvtbint(Pnativeint, Pint64)); - "%int64_to_nativeint", Primitive (Pcvtbint(Pint64, Pnativeint)); - "%caml_ba_ref_1", +let primitives_table = + create_hashtable 57 [ + "%identity", Primitive (Pidentity, 1); + "%bytes_to_string", Primitive (Pbytes_to_string, 1); + "%bytes_of_string", Primitive (Pbytes_of_string, 1); + "%ignore", Primitive (Pignore, 1); + "%revapply", Primitive (Prevapply, 2); + "%apply", Primitive (Pdirapply, 2); + "%loc_LOC", Loc Loc_LOC; + "%loc_FILE", Loc Loc_FILE; + "%loc_LINE", Loc Loc_LINE; + "%loc_POS", Loc Loc_POS; + "%loc_MODULE", Loc Loc_MODULE; + "%field0", Primitive ((Pfield 0), 1); + "%field1", Primitive ((Pfield 1), 1); + "%setfield0", Primitive ((Psetfield(0, Pointer, Assignment)), 2); + "%makeblock", Primitive ((Pmakeblock(0, Immutable, None)), 1); + "%makemutable", Primitive ((Pmakeblock(0, Mutable, None)), 1); + "%raise", Raise Raise_regular; + "%reraise", Raise Raise_reraise; + "%raise_notrace", Raise Raise_notrace; + "%raise_with_backtrace", Raise_with_backtrace; + "%sequand", Primitive (Psequand, 2); + "%sequor", Primitive (Psequor, 2); + "%boolnot", Primitive (Pnot, 1); + "%big_endian", Primitive ((Pctconst Big_endian), 1); + "%backend_type", Primitive ((Pctconst Backend_type), 1); + "%word_size", Primitive ((Pctconst Word_size), 1); + "%int_size", Primitive ((Pctconst Int_size), 1); + "%max_wosize", Primitive ((Pctconst Max_wosize), 1); + "%ostype_unix", Primitive ((Pctconst Ostype_unix), 1); + "%ostype_win32", Primitive ((Pctconst Ostype_win32), 1); + "%ostype_cygwin", Primitive ((Pctconst Ostype_cygwin), 1); + "%negint", Primitive (Pnegint, 1); + "%succint", Primitive ((Poffsetint 1), 1); + "%predint", Primitive ((Poffsetint(-1)), 1); + "%addint", Primitive (Paddint, 2); + "%subint", Primitive (Psubint, 2); + "%mulint", Primitive (Pmulint, 2); + "%divint", Primitive ((Pdivint Safe), 2); + "%modint", Primitive ((Pmodint Safe), 2); + "%andint", Primitive (Pandint, 2); + "%orint", Primitive (Porint, 2); + "%xorint", Primitive (Pxorint, 2); + "%lslint", Primitive (Plslint, 2); + "%lsrint", Primitive (Plsrint, 2); + "%asrint", Primitive (Pasrint, 2); + "%eq", Primitive ((Pintcomp Ceq), 2); + "%noteq", Primitive ((Pintcomp Cne), 2); + "%ltint", Primitive ((Pintcomp Clt), 2); + "%leint", Primitive ((Pintcomp Cle), 2); + "%gtint", Primitive ((Pintcomp Cgt), 2); + "%geint", Primitive ((Pintcomp Cge), 2); + "%incr", Primitive ((Poffsetref(1)), 1); + "%decr", Primitive ((Poffsetref(-1)), 1); + "%intoffloat", Primitive (Pintoffloat, 1); + "%floatofint", Primitive (Pfloatofint, 1); + "%negfloat", Primitive (Pnegfloat, 1); + "%absfloat", Primitive (Pabsfloat, 1); + "%addfloat", Primitive (Paddfloat, 2); + "%subfloat", Primitive (Psubfloat, 2); + "%mulfloat", Primitive (Pmulfloat, 2); + "%divfloat", Primitive (Pdivfloat, 2); + "%eqfloat", Primitive ((Pfloatcomp CFeq), 2); + "%noteqfloat", Primitive ((Pfloatcomp CFneq), 2); + "%ltfloat", Primitive ((Pfloatcomp CFlt), 2); + "%lefloat", Primitive ((Pfloatcomp CFle), 2); + "%gtfloat", Primitive ((Pfloatcomp CFgt), 2); + "%gefloat", Primitive ((Pfloatcomp CFge), 2); + "%string_length", Primitive (Pstringlength, 1); + "%string_safe_get", Primitive (Pstringrefs, 2); + "%string_safe_set", Primitive (Pbytessets, 3); + "%string_unsafe_get", Primitive (Pstringrefu, 2); + "%string_unsafe_set", Primitive (Pbytessetu, 3); + "%bytes_length", Primitive (Pbyteslength, 1); + "%bytes_safe_get", Primitive (Pbytesrefs, 2); + "%bytes_safe_set", Primitive (Pbytessets, 3); + "%bytes_unsafe_get", Primitive (Pbytesrefu, 2); + "%bytes_unsafe_set", Primitive (Pbytessetu, 3); + "%array_length", Primitive ((Parraylength gen_array_kind), 1); + "%array_safe_get", Primitive ((Parrayrefs gen_array_kind), 2); + "%array_safe_set", Primitive ((Parraysets gen_array_kind), 3); + "%array_unsafe_get", Primitive ((Parrayrefu gen_array_kind), 2); + "%array_unsafe_set", Primitive ((Parraysetu gen_array_kind), 3); + "%obj_size", Primitive ((Parraylength gen_array_kind), 1); + "%obj_field", Primitive ((Parrayrefu gen_array_kind), 2); + "%obj_set_field", Primitive ((Parraysetu gen_array_kind), 3); + "%floatarray_length", Primitive ((Parraylength Pfloatarray), 1); + "%floatarray_safe_get", Primitive ((Parrayrefs Pfloatarray), 2); + "%floatarray_safe_set", Primitive ((Parraysets Pfloatarray), 3); + "%floatarray_unsafe_get", Primitive ((Parrayrefu Pfloatarray), 2); + "%floatarray_unsafe_set", Primitive ((Parraysetu Pfloatarray), 3); + "%obj_is_int", Primitive (Pisint, 1); + "%lazy_force", Lazy_force; + "%nativeint_of_int", Primitive ((Pbintofint Pnativeint), 1); + "%nativeint_to_int", Primitive ((Pintofbint Pnativeint), 1); + "%nativeint_neg", Primitive ((Pnegbint Pnativeint), 1); + "%nativeint_add", Primitive ((Paddbint Pnativeint), 2); + "%nativeint_sub", Primitive ((Psubbint Pnativeint), 2); + "%nativeint_mul", Primitive ((Pmulbint Pnativeint), 2); + "%nativeint_div", + Primitive ((Pdivbint { size = Pnativeint; is_safe = Safe }), 2); + "%nativeint_mod", + Primitive ((Pmodbint { size = Pnativeint; is_safe = Safe }), 2); + "%nativeint_and", Primitive ((Pandbint Pnativeint), 2); + "%nativeint_or", Primitive ( (Porbint Pnativeint), 2); + "%nativeint_xor", Primitive ((Pxorbint Pnativeint), 2); + "%nativeint_lsl", Primitive ((Plslbint Pnativeint), 2); + "%nativeint_lsr", Primitive ((Plsrbint Pnativeint), 2); + "%nativeint_asr", Primitive ((Pasrbint Pnativeint), 2); + "%int32_of_int", Primitive ((Pbintofint Pint32), 1); + "%int32_to_int", Primitive ((Pintofbint Pint32), 1); + "%int32_neg", Primitive ((Pnegbint Pint32), 1); + "%int32_add", Primitive ((Paddbint Pint32), 2); + "%int32_sub", Primitive ((Psubbint Pint32), 2); + "%int32_mul", Primitive ((Pmulbint Pint32), 2); + "%int32_div", Primitive ((Pdivbint { size = Pint32; is_safe = Safe }), 2); + "%int32_mod", Primitive ((Pmodbint { size = Pint32; is_safe = Safe }), 2); + "%int32_and", Primitive ((Pandbint Pint32), 2); + "%int32_or", Primitive ( (Porbint Pint32), 2); + "%int32_xor", Primitive ((Pxorbint Pint32), 2); + "%int32_lsl", Primitive ((Plslbint Pint32), 2); + "%int32_lsr", Primitive ((Plsrbint Pint32), 2); + "%int32_asr", Primitive ((Pasrbint Pint32), 2); + "%int64_of_int", Primitive ((Pbintofint Pint64), 1); + "%int64_to_int", Primitive ((Pintofbint Pint64), 1); + "%int64_neg", Primitive ((Pnegbint Pint64), 1); + "%int64_add", Primitive ((Paddbint Pint64), 2); + "%int64_sub", Primitive ((Psubbint Pint64), 2); + "%int64_mul", Primitive ((Pmulbint Pint64), 2); + "%int64_div", Primitive ((Pdivbint { size = Pint64; is_safe = Safe }), 2); + "%int64_mod", Primitive ((Pmodbint { size = Pint64; is_safe = Safe }), 2); + "%int64_and", Primitive ((Pandbint Pint64), 2); + "%int64_or", Primitive ( (Porbint Pint64), 2); + "%int64_xor", Primitive ((Pxorbint Pint64), 2); + "%int64_lsl", Primitive ((Plslbint Pint64), 2); + "%int64_lsr", Primitive ((Plsrbint Pint64), 2); + "%int64_asr", Primitive ((Pasrbint Pint64), 2); + "%nativeint_of_int32", Primitive ((Pcvtbint(Pint32, Pnativeint)), 1); + "%nativeint_to_int32", Primitive ((Pcvtbint(Pnativeint, Pint32)), 1); + "%int64_of_int32", Primitive ((Pcvtbint(Pint32, Pint64)), 1); + "%int64_to_int32", Primitive ((Pcvtbint(Pint64, Pint32)), 1); + "%int64_of_nativeint", Primitive ((Pcvtbint(Pnativeint, Pint64)), 1); + "%int64_to_nativeint", Primitive ((Pcvtbint(Pint64, Pnativeint)), 1); + "%caml_ba_ref_1", Primitive - (Pbigarrayref(false, 1, Pbigarray_unknown, Pbigarray_unknown_layout)); - "%caml_ba_ref_2", + ((Pbigarrayref(false, 1, Pbigarray_unknown, Pbigarray_unknown_layout)), + 2); + "%caml_ba_ref_2", Primitive - (Pbigarrayref(false, 2, Pbigarray_unknown, Pbigarray_unknown_layout)); - "%caml_ba_ref_3", + ((Pbigarrayref(false, 2, Pbigarray_unknown, Pbigarray_unknown_layout)), + 3); + "%caml_ba_ref_3", Primitive - (Pbigarrayref(false, 3, Pbigarray_unknown, Pbigarray_unknown_layout)); - "%caml_ba_set_1", + ((Pbigarrayref(false, 3, Pbigarray_unknown, Pbigarray_unknown_layout)), + 4); + "%caml_ba_set_1", Primitive - (Pbigarrayset(false, 1, Pbigarray_unknown, Pbigarray_unknown_layout)); - "%caml_ba_set_2", + ((Pbigarrayset(false, 1, Pbigarray_unknown, Pbigarray_unknown_layout)), + 3); + "%caml_ba_set_2", Primitive - (Pbigarrayset(false, 2, Pbigarray_unknown, Pbigarray_unknown_layout)); - "%caml_ba_set_3", + ((Pbigarrayset(false, 2, Pbigarray_unknown, Pbigarray_unknown_layout)), + 4); + "%caml_ba_set_3", Primitive - (Pbigarrayset(false, 3, Pbigarray_unknown, Pbigarray_unknown_layout)); - "%caml_ba_unsafe_ref_1", + ((Pbigarrayset(false, 3, Pbigarray_unknown, Pbigarray_unknown_layout)), + 5); + "%caml_ba_unsafe_ref_1", Primitive - (Pbigarrayref(true, 1, Pbigarray_unknown, Pbigarray_unknown_layout)); - "%caml_ba_unsafe_ref_2", + ((Pbigarrayref(true, 1, Pbigarray_unknown, Pbigarray_unknown_layout)), + 2); + "%caml_ba_unsafe_ref_2", Primitive - (Pbigarrayref(true, 2, Pbigarray_unknown, Pbigarray_unknown_layout)); - "%caml_ba_unsafe_ref_3", + ((Pbigarrayref(true, 2, Pbigarray_unknown, Pbigarray_unknown_layout)), + 3); + "%caml_ba_unsafe_ref_3", Primitive - (Pbigarrayref(true, 3, Pbigarray_unknown, Pbigarray_unknown_layout)); - "%caml_ba_unsafe_set_1", + ((Pbigarrayref(true, 3, Pbigarray_unknown, Pbigarray_unknown_layout)), + 4); + "%caml_ba_unsafe_set_1", Primitive - (Pbigarrayset(true, 1, Pbigarray_unknown, Pbigarray_unknown_layout)); - "%caml_ba_unsafe_set_2", + ((Pbigarrayset(true, 1, Pbigarray_unknown, Pbigarray_unknown_layout)), + 3); + "%caml_ba_unsafe_set_2", Primitive - (Pbigarrayset(true, 2, Pbigarray_unknown, Pbigarray_unknown_layout)); - "%caml_ba_unsafe_set_3", + ((Pbigarrayset(true, 2, Pbigarray_unknown, Pbigarray_unknown_layout)), + 4); + "%caml_ba_unsafe_set_3", Primitive - (Pbigarrayset(true, 3, Pbigarray_unknown, Pbigarray_unknown_layout)); - "%caml_ba_dim_1", Primitive (Pbigarraydim(1)); - "%caml_ba_dim_2", Primitive (Pbigarraydim(2)); - "%caml_ba_dim_3", Primitive (Pbigarraydim(3)); - "%caml_string_get16", Primitive (Pstring_load_16(false)); - "%caml_string_get16u", Primitive (Pstring_load_16(true)); - "%caml_string_get32", Primitive (Pstring_load_32(false)); - "%caml_string_get32u", Primitive (Pstring_load_32(true)); - "%caml_string_get64", Primitive (Pstring_load_64(false)); - "%caml_string_get64u", Primitive (Pstring_load_64(true)); - "%caml_string_set16", Primitive (Pbytes_set_16(false)); - "%caml_string_set16u", Primitive (Pbytes_set_16(true)); - "%caml_string_set32", Primitive (Pbytes_set_32(false)); - "%caml_string_set32u", Primitive (Pbytes_set_32(true)); - "%caml_string_set64", Primitive (Pbytes_set_64(false)); - "%caml_string_set64u", Primitive (Pbytes_set_64(true)); - "%caml_bytes_get16", Primitive (Pbytes_load_16(false)); - "%caml_bytes_get16u", Primitive (Pbytes_load_16(true)); - "%caml_bytes_get32", Primitive (Pbytes_load_32(false)); - "%caml_bytes_get32u", Primitive (Pbytes_load_32(true)); - "%caml_bytes_get64", Primitive (Pbytes_load_64(false)); - "%caml_bytes_get64u", Primitive (Pbytes_load_64(true)); - "%caml_bytes_set16", Primitive (Pbytes_set_16(false)); - "%caml_bytes_set16u", Primitive (Pbytes_set_16(true)); - "%caml_bytes_set32", Primitive (Pbytes_set_32(false)); - "%caml_bytes_set32u", Primitive (Pbytes_set_32(true)); - "%caml_bytes_set64", Primitive (Pbytes_set_64(false)); - "%caml_bytes_set64u", Primitive (Pbytes_set_64(true)); - "%caml_bigstring_get16", Primitive (Pbigstring_load_16(false)); - "%caml_bigstring_get16u", Primitive (Pbigstring_load_16(true)); - "%caml_bigstring_get32", Primitive (Pbigstring_load_32(false)); - "%caml_bigstring_get32u", Primitive (Pbigstring_load_32(true)); - "%caml_bigstring_get64", Primitive (Pbigstring_load_64(false)); - "%caml_bigstring_get64u", Primitive (Pbigstring_load_64(true)); - "%caml_bigstring_set16", Primitive (Pbigstring_set_16(false)); - "%caml_bigstring_set16u", Primitive (Pbigstring_set_16(true)); - "%caml_bigstring_set32", Primitive (Pbigstring_set_32(false)); - "%caml_bigstring_set32u", Primitive (Pbigstring_set_32(true)); - "%caml_bigstring_set64", Primitive (Pbigstring_set_64(false)); - "%caml_bigstring_set64u", Primitive (Pbigstring_set_64(true)); - "%bswap16", Primitive Pbswap16; - "%bswap_int32", Primitive (Pbbswap(Pint32)); - "%bswap_int64", Primitive (Pbbswap(Pint64)); - "%bswap_native", Primitive (Pbbswap(Pnativeint)); - "%int_as_pointer", Primitive Pint_as_pointer; - "%opaque", Primitive Popaque; - "%send", Send; - "%sendself", Send_self; - "%sendcache", Send_cache; - "%equal", Comparison(Equal, Compare_generic); - "%notequal", Comparison(Not_equal, Compare_generic); - "%lessequal", Comparison(Less_equal, Compare_generic); - "%lessthan", Comparison(Less_than, Compare_generic); - "%greaterequal", Comparison(Greater_equal, Compare_generic); - "%greaterthan", Comparison(Greater_than, Compare_generic); - "%compare", Comparison(Compare, Compare_generic); -] - -let lookup_primitive loc p env path = + ((Pbigarrayset(true, 3, Pbigarray_unknown, Pbigarray_unknown_layout)), + 5); + "%caml_ba_dim_1", Primitive ((Pbigarraydim(1)), 1); + "%caml_ba_dim_2", Primitive ((Pbigarraydim(2)), 1); + "%caml_ba_dim_3", Primitive ((Pbigarraydim(3)), 1); + "%caml_string_get16", Primitive ((Pstring_load_16(false)), 2); + "%caml_string_get16u", Primitive ((Pstring_load_16(true)), 2); + "%caml_string_get32", Primitive ((Pstring_load_32(false)), 2); + "%caml_string_get32u", Primitive ((Pstring_load_32(true)), 2); + "%caml_string_get64", Primitive ((Pstring_load_64(false)), 2); + "%caml_string_get64u", Primitive ((Pstring_load_64(true)), 2); + "%caml_string_set16", Primitive ((Pbytes_set_16(false)), 3); + "%caml_string_set16u", Primitive ((Pbytes_set_16(true)), 3); + "%caml_string_set32", Primitive ((Pbytes_set_32(false)), 3); + "%caml_string_set32u", Primitive ((Pbytes_set_32(true)), 3); + "%caml_string_set64", Primitive ((Pbytes_set_64(false)), 3); + "%caml_string_set64u", Primitive ((Pbytes_set_64(true)), 3); + "%caml_bytes_get16", Primitive ((Pbytes_load_16(false)), 2); + "%caml_bytes_get16u", Primitive ((Pbytes_load_16(true)), 2); + "%caml_bytes_get32", Primitive ((Pbytes_load_32(false)), 2); + "%caml_bytes_get32u", Primitive ((Pbytes_load_32(true)), 2); + "%caml_bytes_get64", Primitive ((Pbytes_load_64(false)), 2); + "%caml_bytes_get64u", Primitive ((Pbytes_load_64(true)), 2); + "%caml_bytes_set16", Primitive ((Pbytes_set_16(false)), 3); + "%caml_bytes_set16u", Primitive ((Pbytes_set_16(true)), 3); + "%caml_bytes_set32", Primitive ((Pbytes_set_32(false)), 3); + "%caml_bytes_set32u", Primitive ((Pbytes_set_32(true)), 3); + "%caml_bytes_set64", Primitive ((Pbytes_set_64(false)), 3); + "%caml_bytes_set64u", Primitive ((Pbytes_set_64(true)), 3); + "%caml_bigstring_get16", Primitive ((Pbigstring_load_16(false)), 2); + "%caml_bigstring_get16u", Primitive ((Pbigstring_load_16(true)), 2); + "%caml_bigstring_get32", Primitive ((Pbigstring_load_32(false)), 2); + "%caml_bigstring_get32u", Primitive ((Pbigstring_load_32(true)), 2); + "%caml_bigstring_get64", Primitive ((Pbigstring_load_64(false)), 2); + "%caml_bigstring_get64u", Primitive ((Pbigstring_load_64(true)), 2); + "%caml_bigstring_set16", Primitive ((Pbigstring_set_16(false)), 3); + "%caml_bigstring_set16u", Primitive ((Pbigstring_set_16(true)), 3); + "%caml_bigstring_set32", Primitive ((Pbigstring_set_32(false)), 3); + "%caml_bigstring_set32u", Primitive ((Pbigstring_set_32(true)), 3); + "%caml_bigstring_set64", Primitive ((Pbigstring_set_64(false)), 3); + "%caml_bigstring_set64u", Primitive ((Pbigstring_set_64(true)), 3); + "%bswap16", Primitive (Pbswap16, 1); + "%bswap_int32", Primitive ((Pbbswap(Pint32)), 1); + "%bswap_int64", Primitive ((Pbbswap(Pint64)), 1); + "%bswap_native", Primitive ((Pbbswap(Pnativeint)), 1); + "%int_as_pointer", Primitive (Pint_as_pointer, 1); + "%opaque", Primitive (Popaque, 1); + "%send", Send; + "%sendself", Send_self; + "%sendcache", Send_cache; + "%equal", Comparison(Equal, Compare_generic); + "%notequal", Comparison(Not_equal, Compare_generic); + "%lessequal", Comparison(Less_equal, Compare_generic); + "%lessthan", Comparison(Less_than, Compare_generic); + "%greaterequal", Comparison(Greater_equal, Compare_generic); + "%greaterthan", Comparison(Greater_than, Compare_generic); + "%compare", Comparison(Compare, Compare_generic); + ] + + +let lookup_primitive loc p = match Hashtbl.find primitives_table p.prim_name with | prim -> prim | exception Not_found -> if String.length p.prim_name > 0 && p.prim_name.[0] = '%' then raise(Error(loc, Unknown_builtin_primitive p.prim_name)); - add_used_primitive loc env path; - Primitive (Pccall p) + External p + +let lookup_primitive_and_mark_used loc p env path = + match lookup_primitive loc p with + | External _ as e -> add_used_primitive loc env path; e + | x -> x let simplify_constant_constructor = function | Equal -> true @@ -389,54 +410,54 @@ let specialize_primitive env ty ~has_constant_constructor prim = | Some (p2, _) -> [p1;p2] in match prim, param_tys with - | Primitive (Psetfield(n, Pointer, init)), [_; p2] -> begin + | Primitive (Psetfield(n, Pointer, init), arity), [_; p2] -> begin match maybe_pointer_type env p2 with | Pointer -> None - | Immediate -> Some (Primitive (Psetfield(n, Immediate, init))) + | Immediate -> Some (Primitive (Psetfield(n, Immediate, init), arity)) end - | Primitive (Parraylength t), [p] -> begin + | Primitive (Parraylength t, arity), [p] -> begin let array_type = glb_array_type t (array_type_kind env p) in if t = array_type then None - else Some (Primitive (Parraylength array_type)) + else Some (Primitive (Parraylength array_type, arity)) end - | Primitive (Parrayrefu t), p1 :: _ -> begin + | Primitive (Parrayrefu t, arity), p1 :: _ -> begin let array_type = glb_array_type t (array_type_kind env p1) in if t = array_type then None - else Some (Primitive (Parrayrefu array_type)) + else Some (Primitive (Parrayrefu array_type, arity)) end - | Primitive (Parraysetu t), p1 :: _ -> begin + | Primitive (Parraysetu t, arity), p1 :: _ -> begin let array_type = glb_array_type t (array_type_kind env p1) in if t = array_type then None - else Some (Primitive (Parraysetu array_type)) + else Some (Primitive (Parraysetu array_type, arity)) end - | Primitive (Parrayrefs t), p1 :: _ -> begin + | Primitive (Parrayrefs t, arity), p1 :: _ -> begin let array_type = glb_array_type t (array_type_kind env p1) in if t = array_type then None - else Some (Primitive (Parrayrefs array_type)) + else Some (Primitive (Parrayrefs array_type, arity)) end - | Primitive (Parraysets t), p1 :: _ -> begin + | Primitive (Parraysets t, arity), p1 :: _ -> begin let array_type = glb_array_type t (array_type_kind env p1) in if t = array_type then None - else Some (Primitive (Parraysets array_type)) + else Some (Primitive (Parraysets array_type, arity)) end | Primitive (Pbigarrayref(unsafe, n, Pbigarray_unknown, - Pbigarray_unknown_layout)), p1 :: _ -> begin + Pbigarray_unknown_layout), arity), p1 :: _ -> begin let (k, l) = bigarray_type_kind_and_layout env p1 in match k, l with | Pbigarray_unknown, Pbigarray_unknown_layout -> None - | _, _ -> Some (Primitive (Pbigarrayref(unsafe, n, k, l))) + | _, _ -> Some (Primitive (Pbigarrayref(unsafe, n, k, l), arity)) end | Primitive (Pbigarrayset(unsafe, n, Pbigarray_unknown, - Pbigarray_unknown_layout)), p1 :: _ -> begin + Pbigarray_unknown_layout), arity), p1 :: _ -> begin let (k, l) = bigarray_type_kind_and_layout env p1 in match k, l with | Pbigarray_unknown, Pbigarray_unknown_layout -> None - | _, _ -> Some (Primitive (Pbigarrayset(unsafe, n, k, l))) + | _, _ -> Some (Primitive (Pbigarrayset(unsafe, n, k, l), arity)) end - | Primitive (Pmakeblock(tag, mut, None)), fields -> begin + | Primitive (Pmakeblock(tag, mut, None), arity), fields -> begin let shape = List.map (Typeopt.value_kind env) fields in let useful = List.exists (fun knd -> knd <> Pgenval) shape in - if useful then Some (Primitive (Pmakeblock(tag, mut, Some shape))) + if useful then Some (Primitive (Pmakeblock(tag, mut, Some shape), arity)) else None end | Comparison(comp, Compare_generic), p1 :: _ -> @@ -584,6 +605,11 @@ let comparison_primitive comparison comparison_kind = let lambda_of_loc kind loc = let loc_start = loc.Location.loc_start in let (file, lnum, cnum) = Location.get_pos_info loc_start in + let file = + if Filename.is_relative file then + file + else + Location.rewrite_absolute_path file in let enum = loc.Location.loc_end.Lexing.pos_cnum - loc_start.Lexing.pos_cnum + cnum in match kind with @@ -619,9 +645,11 @@ let remove_exception_ident id = let lambda_of_prim prim_name prim loc args arg_exps = match prim, args with - | Primitive prim, args -> + | Primitive (prim, arity), args when arity = List.length args -> Lprim(prim, args, loc) - | Comparison(comp, knd), args -> + | External prim, args -> + Lprim(Pccall prim, args, loc) + | Comparison(comp, knd), ([_;_] as args) -> let prim = comparison_primitive comp knd in Lprim(prim, args, loc) | Raise kind, [arg] -> @@ -640,7 +668,7 @@ let lambda_of_prim prim_name prim loc args arg_exps = in Lprim(Praise kind, [arg], loc) | Raise_with_backtrace, [exn; bt] -> - let vexn = Ident.create "exn" in + let vexn = Ident.create_local "exn" in let raise_arg = match arg_exps with | None -> Lvar vexn @@ -666,14 +694,30 @@ let lambda_of_prim prim_name prim loc args arg_exps = | Send_cache, [obj; meth; cache; pos] -> Lsend(Cached, meth, obj, [cache; pos], loc) | (Raise _ | Raise_with_backtrace - | Lazy_force | Loc _ + | Lazy_force | Loc _ | Primitive _ | Comparison _ | Send | Send_self | Send_cache), _ -> raise(Error(loc, Wrong_arity_builtin_primitive prim_name)) +let check_primitive_arity loc p = + let prim = lookup_primitive loc p in + let ok = + match prim with + | Primitive (_,arity) -> arity = p.prim_arity + | External _ -> true + | Comparison _ -> p.prim_arity = 2 + | Raise _ -> p.prim_arity = 1 + | Raise_with_backtrace -> p.prim_arity = 2 + | Lazy_force -> p.prim_arity = 1 + | Loc _ -> p.prim_arity = 1 || p.prim_arity = 0 + | Send | Send_self -> p.prim_arity = 2 + | Send_cache -> p.prim_arity = 4 + in + if not ok then raise(Error(loc, Wrong_arity_builtin_primitive p.prim_name)) + (* Eta-expand a primitive *) let transl_primitive loc p env ty path = - let prim = lookup_primitive loc p env path in + let prim = lookup_primitive_and_mark_used loc p env path in let has_constant_constructor = false in let prim = match specialize_primitive env ty ~has_constant_constructor prim with @@ -681,15 +725,18 @@ let transl_primitive loc p env ty path = | Some prim -> prim in let rec make_params n = - if n <= 0 then [] else Ident.create "prim" :: make_params (n-1) + if n <= 0 then [] + else (Ident.create_local "prim", Pgenval) :: make_params (n-1) in let params = make_params p.prim_arity in - let args = List.map (fun id -> Lvar id) params in + let args = List.map (fun (id, _) -> Lvar id) params in let body = lambda_of_prim p.prim_name prim loc args None in match params with | [] -> body | _ -> - Lfunction{ kind = Curried; params; + Lfunction{ kind = Curried; + params; + return = Pgenval; attr = default_stub_attribute; loc = loc; body = body; } @@ -704,14 +751,15 @@ let primitive_is_ccall = function (* Determine if a primitive should be surrounded by an "after" debug event *) let primitive_needs_event_after = function - | Primitive prim -> primitive_is_ccall prim + | Primitive (prim,_) -> primitive_is_ccall prim + | External _ -> true | Comparison(comp, knd) -> primitive_is_ccall (comparison_primitive comp knd) | Lazy_force | Send | Send_self | Send_cache -> true | Raise _ | Raise_with_backtrace | Loc _ -> false let transl_primitive_application loc p env ty path exp args arg_exps = - let prim = lookup_primitive loc p env (Some path) in + let prim = lookup_primitive_and_mark_used loc p env (Some path) in let has_constant_constructor = match arg_exps with | [_; {exp_desc = Texp_construct(_, {cstr_tag = Cstr_constant _}, _)}] @@ -751,7 +799,7 @@ let () = Location.register_error_of_exn (function | Error (loc, err) -> - Some (Location.error_of_printer loc report_error err) + Some (Location.error_of_printer ~loc report_error err) | _ -> None ) diff --git a/bytecomp/translprim.mli b/bytecomp/translprim.mli index d8941656..abf0f7d5 100644 --- a/bytecomp/translprim.mli +++ b/bytecomp/translprim.mli @@ -27,6 +27,8 @@ val remove_exception_ident : Ident.t -> unit val clear_used_primitives : unit -> unit val get_used_primitives: unit -> Path.t list +val check_primitive_arity : Location.t -> Primitive.description -> unit + val transl_primitive : Location.t -> Primitive.description -> Env.t -> Types.type_expr -> Path.t option -> Lambda.lambda diff --git a/byterun/.depend b/byterun/.depend deleted file mode 100644 index c0f81615..00000000 --- a/byterun/.depend +++ /dev/null @@ -1,803 +0,0 @@ -afl.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \ - caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h -alloc.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/stacks.h -array.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ - caml/spacetime.h caml/io.h caml/stack.h -backtrace.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ - caml/exec.h caml/backtrace_prim.h caml/fail.h -backtrace_prim.$(O): backtrace_prim.c caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \ - caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \ - caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h -bigarray.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \ - caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/signals.h -callback.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h -compact.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/gc_ctrl.h caml/weak.h caml/compact.h -compare.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \ - caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -custom.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/signals.h -debugger.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/fail.h caml/fix_code.h caml/instruct.h \ - caml/intext.h caml/io.h caml/stacks.h caml/sys.h -dynlink.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ - caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h -extern.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \ - caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h -fail.$(O): fail.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/printexc.h caml/signals.h caml/stacks.h -finalise.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \ - caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h -fix_code.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \ - caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \ - caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h -floats.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h caml/stacks.h -freelist.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \ - caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ - caml/major_gc.h caml/minor_gc.h caml/address_class.h -gc_ctrl.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ - caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \ - caml/startup_aux.h -globroots.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \ - caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h -hash.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h -instrtrace.$(O): instrtrace.c -intern.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \ - caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h -interp.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ - caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \ - caml/jumptbl.h -ints.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h -io.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h -lexing.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -main.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -major_gc.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \ - caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ - caml/weak.h -md5.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/reverse.h -memory.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ - caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ - caml/signals.h -meta.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ - caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ - caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ - caml/stacks.h -minor_gc.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ - caml/weak.h -misc.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \ - caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h -obj.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \ - caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \ - caml/prims.h caml/spacetime.h caml/io.h caml/stack.h -parsing.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \ - caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/alloc.h -prims.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/prims.h -printexc.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -roots.$(O): roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \ - caml/m.h caml/s.h caml/memory.h caml/gc.h caml/mlvalues.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/globroots.h caml/stacks.h -signals.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/roots.h caml/signals.h \ - caml/signals_machdep.h caml/sys.h -signals_byt.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \ - caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ - caml/signals.h caml/signals_machdep.h -spacetime.$(O): spacetime.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h -stacks.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \ - caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -startup.$(O): startup.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ - caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ - caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \ - caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \ - caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ - caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \ - caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \ - caml/startup_aux.h caml/version.h -startup_aux.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \ - caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/callback.h caml/dynlink.h caml/osdeps.h \ - caml/startup_aux.h -str.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h -sys.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \ - caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \ - caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h -unix.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \ - caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ - caml/signals.h caml/sys.h caml/io.h caml/alloc.h -weak.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/weak.h -afl.d.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \ - caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h -alloc.d.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/stacks.h -array.d.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ - caml/spacetime.h caml/io.h caml/stack.h -backtrace.d.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ - caml/exec.h caml/backtrace_prim.h caml/fail.h -backtrace_prim.d.$(O): backtrace_prim.c caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \ - caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \ - caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h -bigarray.d.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \ - caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/signals.h -callback.d.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h -compact.d.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/gc_ctrl.h caml/weak.h caml/compact.h -compare.d.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \ - caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -custom.d.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/signals.h -debugger.d.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/fail.h caml/fix_code.h caml/instruct.h \ - caml/intext.h caml/io.h caml/stacks.h caml/sys.h -dynlink.d.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ - caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h -extern.d.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \ - caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h -fail.d.$(O): fail.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/printexc.h caml/signals.h caml/stacks.h -finalise.d.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \ - caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h -fix_code.d.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \ - caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \ - caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h -floats.d.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h caml/stacks.h -freelist.d.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \ - caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ - caml/major_gc.h caml/minor_gc.h caml/address_class.h -gc_ctrl.d.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ - caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \ - caml/startup_aux.h -globroots.d.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \ - caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h -hash.d.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h -instrtrace.d.$(O): instrtrace.c caml/instrtrace.h caml/mlvalues.h \ - caml/config.h caml/m.h caml/s.h caml/misc.h caml/instruct.h \ - caml/opnames.h caml/prims.h caml/stacks.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/startup_aux.h -intern.d.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \ - caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h -interp.d.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ - caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h -ints.d.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h -io.d.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h -lexing.d.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -main.d.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -major_gc.d.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \ - caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ - caml/weak.h -md5.d.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/reverse.h -memory.d.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ - caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ - caml/signals.h -meta.d.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ - caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ - caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ - caml/stacks.h -minor_gc.d.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ - caml/weak.h -misc.d.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \ - caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h -obj.d.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \ - caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \ - caml/prims.h caml/spacetime.h caml/io.h caml/stack.h -parsing.d.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \ - caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/alloc.h -prims.d.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/prims.h -printexc.d.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -roots.d.$(O): roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \ - caml/m.h caml/s.h caml/memory.h caml/gc.h caml/mlvalues.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/globroots.h caml/stacks.h -signals.d.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/roots.h caml/signals.h \ - caml/signals_machdep.h caml/sys.h -signals_byt.d.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \ - caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ - caml/signals.h caml/signals_machdep.h -spacetime.d.$(O): spacetime.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h -stacks.d.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \ - caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -startup.d.$(O): startup.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ - caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ - caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \ - caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \ - caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ - caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \ - caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \ - caml/startup_aux.h caml/version.h -startup_aux.d.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \ - caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/callback.h caml/dynlink.h caml/osdeps.h \ - caml/startup_aux.h -str.d.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h -sys.d.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \ - caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \ - caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h -unix.d.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \ - caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ - caml/signals.h caml/sys.h caml/io.h caml/alloc.h -weak.d.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/weak.h -afl.i.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \ - caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h -alloc.i.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/stacks.h -array.i.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ - caml/spacetime.h caml/io.h caml/stack.h -backtrace.i.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ - caml/exec.h caml/backtrace_prim.h caml/fail.h -backtrace_prim.i.$(O): backtrace_prim.c caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \ - caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \ - caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h -bigarray.i.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \ - caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/signals.h -callback.i.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h -compact.i.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/gc_ctrl.h caml/weak.h caml/compact.h -compare.i.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \ - caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -custom.i.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/signals.h -debugger.i.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/fail.h caml/fix_code.h caml/instruct.h \ - caml/intext.h caml/io.h caml/stacks.h caml/sys.h -dynlink.i.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ - caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h -extern.i.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \ - caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h -fail.i.$(O): fail.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/printexc.h caml/signals.h caml/stacks.h -finalise.i.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \ - caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h -fix_code.i.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \ - caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \ - caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h -floats.i.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h caml/stacks.h -freelist.i.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \ - caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ - caml/major_gc.h caml/minor_gc.h caml/address_class.h -gc_ctrl.i.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ - caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \ - caml/startup_aux.h -globroots.i.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \ - caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h -hash.i.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h -instrtrace.i.$(O): instrtrace.c -intern.i.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \ - caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h -interp.i.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ - caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \ - caml/jumptbl.h -ints.i.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h -io.i.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h -lexing.i.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -main.i.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -major_gc.i.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \ - caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ - caml/weak.h -md5.i.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/reverse.h -memory.i.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ - caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ - caml/signals.h -meta.i.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ - caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ - caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ - caml/stacks.h -minor_gc.i.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ - caml/weak.h -misc.i.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \ - caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h -obj.i.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \ - caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \ - caml/prims.h caml/spacetime.h caml/io.h caml/stack.h -parsing.i.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \ - caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/alloc.h -prims.i.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/prims.h -printexc.i.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -roots.i.$(O): roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \ - caml/m.h caml/s.h caml/memory.h caml/gc.h caml/mlvalues.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/globroots.h caml/stacks.h -signals.i.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/roots.h caml/signals.h \ - caml/signals_machdep.h caml/sys.h -signals_byt.i.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \ - caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ - caml/signals.h caml/signals_machdep.h -spacetime.i.$(O): spacetime.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h -stacks.i.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \ - caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -startup.i.$(O): startup.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ - caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ - caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \ - caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \ - caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ - caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \ - caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \ - caml/startup_aux.h caml/version.h -startup_aux.i.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \ - caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/callback.h caml/dynlink.h caml/osdeps.h \ - caml/startup_aux.h -str.i.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h -sys.i.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \ - caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \ - caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h -unix.i.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \ - caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ - caml/signals.h caml/sys.h caml/io.h caml/alloc.h -weak.i.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/weak.h -afl.pic.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \ - caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h -alloc.pic.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/stacks.h -array.pic.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ - caml/spacetime.h caml/io.h caml/stack.h -backtrace.pic.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ - caml/exec.h caml/backtrace_prim.h caml/fail.h -backtrace_prim.pic.$(O): backtrace_prim.c caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \ - caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \ - caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h -bigarray.pic.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \ - caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/signals.h -callback.pic.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h -compact.pic.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/gc_ctrl.h caml/weak.h caml/compact.h -compare.pic.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \ - caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -custom.pic.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/signals.h -debugger.pic.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/fail.h caml/fix_code.h caml/instruct.h \ - caml/intext.h caml/io.h caml/stacks.h caml/sys.h -dynlink.pic.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ - caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h -extern.pic.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \ - caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h -fail.pic.$(O): fail.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/printexc.h caml/signals.h caml/stacks.h -finalise.pic.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \ - caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h -fix_code.pic.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \ - caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \ - caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h -floats.pic.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h caml/stacks.h -freelist.pic.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \ - caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ - caml/major_gc.h caml/minor_gc.h caml/address_class.h -gc_ctrl.pic.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ - caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \ - caml/startup_aux.h -globroots.pic.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \ - caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h -hash.pic.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h -instrtrace.pic.$(O): instrtrace.c -intern.pic.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \ - caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/reverse.h -interp.pic.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ - caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \ - caml/jumptbl.h -ints.pic.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h -io.pic.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h -lexing.pic.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -main.pic.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -major_gc.pic.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \ - caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ - caml/weak.h -md5.pic.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/reverse.h -memory.pic.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ - caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ - caml/signals.h -meta.pic.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ - caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ - caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ - caml/stacks.h -minor_gc.pic.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \ - caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ - caml/weak.h -misc.pic.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \ - caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h -obj.pic.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \ - caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \ - caml/prims.h caml/spacetime.h caml/io.h caml/stack.h -parsing.pic.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \ - caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/alloc.h -prims.pic.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ - caml/misc.h caml/prims.h -printexc.pic.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ - caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \ - caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -roots.pic.$(O): roots.c caml/finalise.h caml/roots.h caml/misc.h caml/config.h \ - caml/m.h caml/s.h caml/memory.h caml/gc.h caml/mlvalues.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ - caml/globroots.h caml/stacks.h -signals.pic.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/roots.h caml/signals.h \ - caml/signals_machdep.h caml/sys.h -signals_byt.pic.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \ - caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ - caml/signals.h caml/signals_machdep.h -spacetime.pic.$(O): spacetime.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ - caml/s.h caml/mlvalues.h -stacks.pic.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \ - caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ - caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h -startup.pic.$(O): startup.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ - caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ - caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \ - caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \ - caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ - caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \ - caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \ - caml/startup_aux.h caml/version.h -startup_aux.pic.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \ - caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/callback.h caml/dynlink.h caml/osdeps.h \ - caml/startup_aux.h -str.pic.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h -sys.pic.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ - caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \ - caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ - caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \ - caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h -unix.pic.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \ - caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ - caml/signals.h caml/sys.h caml/io.h caml/alloc.h -weak.pic.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ - caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ - caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ - caml/weak.h diff --git a/byterun/Makefile b/byterun/Makefile deleted file mode 100644 index 25b7e2c3..00000000 --- a/byterun/Makefile +++ /dev/null @@ -1,234 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include ../config/Makefile -include ../Makefile.common - -# The PROGRAMS (resp. LIBRARIES) variable list the files to build and -# install as programs in $(INSTALL_BINDIR) (resp. libraries in -# $(INSTALL_LIBDIR)) - -PROGRAMS = ocamlrun$(EXE) -LIBRARIES = ld.conf libcamlrun.$(A) -DYNLIBRARIES= - -ifeq "$(RUNTIMED)" "true" -PROGRAMS += ocamlrund$(EXE) -LIBRARIES += libcamlrund.$(A) -endif - -ifeq "$(RUNTIMEI)" "true" -PROGRAMS += ocamlruni$(EXE) -LIBRARIES += libcamlruni.$(A) -endif - -ifeq "$(UNIX_OR_WIN32)" "unix" -ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true" -LIBRARIES += libcamlrun_pic.$(A) -DYNLIBRARIES += libcamlrun_shared.$(SO) -endif -endif - -ifdef BOOTSTRAPPING_FLEXLINK -CFLAGS += -DBOOTSTRAPPING_FLEXLINK -endif - -# On Windows, OCAML_STDLIB_DIR needs to be defined dynamically - -ifeq "$(UNIX_OR_WIN32)" "win32" -# OCAML_STDLIB_DIR needs to arrive in dynlink.c as a string which both gcc and -# msvc are willing parse without warning. This means we can't pass UTF-8 -# directly since, as far as I can tell, cl can cope, but the pre-processor -# can't. So the string needs to be directly translated to L"" form. To do this, -# we take advantage of the fact that Cygwin uses GNU libiconv which includes a -# Java pseudo-encoding which translates any UTF-8 sequences to \uXXXX (and, -# unlike the C99 pseudo-encoding, emits two surrogate values when needed, rather -# than \UXXXXXXXX). The \u is then translated to \x in order to accommodate -# pre-Visual Studio 2013 compilers where \x is a non-standard alias for \u. -OCAML_STDLIB_DIR = $(shell echo $(LIBDIR)| iconv -t JAVA | sed -e 's/\\u/\\x/g') -CFLAGS += -DOCAML_STDLIB_DIR='L"$(OCAML_STDLIB_DIR)"' -endif - -CFLAGS += $(IFLEXDIR) - -ifneq "$(CCOMPTYPE)" "msvc" -CFLAGS += -g -endif - -DFLAGS=$(CFLAGS) -DDEBUG -IFLAGS=$(CFLAGS) -DCAML_INSTR -PICFLAGS=$(CFLAGS) $(SHAREDCCCOMPOPTS) - -DBGO=d.$(O) - -ifeq "$(UNIX_OR_WIN32)" "win32" -LIBS = $(BYTECCLIBS) $(EXTRALIBS) -ifdef BOOTSTRAPPING_FLEXLINK -MAKE_OCAMLRUN=$(MKEXE_BOOT) -else -MAKE_OCAMLRUN = $(MKEXE) -o $(1) $(2) -endif -else -LIBS = $(BYTECCLIBS) -MAKE_OCAMLRUN = $(MKEXE) $(LDFLAGS) -o $(1) $(2) -endif - -PRIMS=\ - alloc.c array.c compare.c extern.c floats.c gc_ctrl.c hash.c \ - intern.c interp.c ints.c io.c lexing.c md5.c meta.c obj.c parsing.c \ - signals.c str.c sys.c callback.c weak.c finalise.c stacks.c \ - dynlink.c backtrace_prim.c backtrace.c spacetime.c afl.c \ - bigarray.c - -OBJS=$(addsuffix .$(O), \ - interp misc stacks fix_code startup_aux startup \ - freelist major_gc minor_gc memory alloc roots globroots \ - fail signals signals_byt printexc backtrace_prim backtrace \ - compare ints floats str array io extern intern \ - hash sys meta parsing gc_ctrl md5 obj \ - lexing callback debugger weak compact finalise custom \ - dynlink spacetime afl $(UNIX_OR_WIN32) bigarray main) - -DOBJS=$(OBJS:.$(O)=.$(DBGO)) instrtrace.$(DBGO) -IOBJS=$(OBJS:.$(O)=.i.$(O)) -PICOBJS=$(OBJS:.$(O)=.pic.$(O)) - -.PHONY: all -all: $(LIBRARIES) $(DYNLIBRARIES) $(PROGRAMS) - -ld.conf: ../config/Makefile - echo "$(STUBLIBDIR)" > $@ - echo "$(LIBDIR)" >> $@ - -INSTALL_INCDIR=$(INSTALL_LIBDIR)/caml - -.PHONY: install -install: - $(INSTALL_PROG) $(PROGRAMS) "$(INSTALL_BINDIR)" - $(INSTALL_DATA) $(LIBRARIES) "$(INSTALL_LIBDIR)" - if test -n "$(DYNLIBRARIES)"; then \ - $(INSTALL_PROG) $(DYNLIBRARIES) "$(INSTALL_LIBDIR)"; \ - fi - mkdir -p "$(INSTALL_INCDIR)" - $(INSTALL_DATA) caml/*.h "$(INSTALL_INCDIR)" - -# If primitives contain duplicated lines (e.g. because the code is defined -# like -# #ifdef X -# CAMLprim value caml_foo() ... -# #else -# CAMLprim value caml_foo() ... -# end), horrible things will happen (duplicated entries in Runtimedef -> -# double registration in Symtable -> empty entry in the PRIM table -> -# the bytecode interpreter is confused). -# We sort the primitive file and remove duplicates to avoid this problem. - -# Warning: we use "sort | uniq" instead of "sort -u" because in the MSVC -# port, the "sort" program in the path is Microsoft's and not cygwin's - -# Warning: POSIX sort is locale dependent, that's why we set LC_ALL explicitly. -# Sort is unstable for "is_directory" and "isatty" -# see http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sort.html: -# "using sort to process pathnames, it is recommended that LC_ALL .. set to C" - - -primitives : $(PRIMS) - sed -n -e "s/CAMLprim value \([a-z0-9_][a-z0-9_]*\).*/\1/p" $(PRIMS) \ - | LC_ALL=C sort | uniq > primitives - -prims.c : primitives - (echo '#define CAML_INTERNALS'; \ - echo '#include "caml/mlvalues.h"'; \ - echo '#include "caml/prims.h"'; \ - sed -e 's/.*/extern value &();/' primitives; \ - echo 'c_primitive caml_builtin_cprim[] = {'; \ - sed -e 's/.*/ &,/' primitives; \ - echo ' 0 };'; \ - echo 'char * caml_names_of_builtin_cprim[] = {'; \ - sed -e 's/.*/ "&",/' primitives; \ - echo ' 0 };') > prims.c - -caml/opnames.h : caml/instruct.h - cat $^ | tr -d '\r' | \ - sed -e '/\/\*/d' \ - -e '/^#/d' \ - -e 's/enum /char * names_of_/' \ - -e 's/{$$/[] = {/' \ - -e 's/\([[:upper:]][[:upper:]_0-9]*\)/"\1"/g' > $@ - -# caml/jumptbl.h is required only if you have GCC 2.0 or later -caml/jumptbl.h : caml/instruct.h - cat $^ | tr -d '\r' | \ - sed -n -e '/^ /s/ \([A-Z]\)/ \&\&lbl_\1/gp' \ - -e '/^}/q' > $@ - -caml/version.h : ../VERSION ../tools/make-version-header.sh - ../tools/make-version-header.sh ../VERSION > caml/version.h - -.PHONY: clean -clean: - rm -f $(LIBRARIES) $(DYNLIBRARIES) $(PROGRAMS) *.$(O) *.$(A) *.$(SO) - rm -f primitives prims.c caml/opnames.h caml/jumptbl.h - rm -f caml/version.h - -ocamlrun$(EXE): prims.$(O) libcamlrun.$(A) - $(call MAKE_OCAMLRUN,$@,$^ $(LIBS)) - -libcamlrun.$(A): $(OBJS) - $(call MKLIB,$@, $^) - -ocamlrund$(EXE): prims.$(O) libcamlrund.$(A) - $(MKEXE) $(MKEXEDEBUGFLAG) -o $@ $^ $(LIBS) - -libcamlrund.$(A): $(DOBJS) - $(call MKLIB,$@, $^) - -ocamlruni$(EXE): prims.$(O) libcamlruni.$(A) - $(MKEXE) -o $@ $^ $(LIBS) - -libcamlruni.$(A): $(IOBJS) - $(call MKLIB,$@, $^) - -libcamlrun_pic.$(A): $(PICOBJS) - $(call MKLIB,$@, $^) - -libcamlrun_shared.$(SO): $(PICOBJS) - $(MKDLL) -o $@ $^ $(BYTECCLIBS) - -%.$(O): %.c - $(CC) -c $(CFLAGS) $(CPPFLAGS) $< - -%.$(DBGO): %.c - $(CC) -c $(DFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $< - -%.i.$(O): %.c - $(CC) -c $(IFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $< - -%.pic.$(O): %.c - $(CC) -c $(PICFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $< - -.PHONY: depend -ifeq "$(TOOLCHAIN)" "msvc" -depend: - $(error Dependencies cannot be regenerated using the MSVC ports) -else -depend: prims.c caml/opnames.h caml/jumptbl.h caml/version.h - $(CC) -MM $(CFLAGS) $(CPPFLAGS) *.c | sed -e 's/\.o/.$$(O)/'>.$@ - $(CC) -MM $(DFLAGS) $(CPPFLAGS) *.c | sed -e 's/\.o/.d.$$(O)/'>>.$@ - $(CC) -MM $(IFLAGS) $(CPPFLAGS) *.c | sed -e 's/\.o/.i.$$(O)/'>>.$@ - $(CC) -MM $(PICFLAGS) $(CPPFLAGS) *.c | sed -e 's/\.o/.pic.$$(O)/'>>.$@ -endif - -include .depend diff --git a/byterun/Makefile.nt b/byterun/Makefile.nt deleted file mode 100644 index ed9900bb..00000000 --- a/byterun/Makefile.nt +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include Makefile diff --git a/byterun/alloc.c b/byterun/alloc.c deleted file mode 100644 index 8924dbc0..00000000 --- a/byterun/alloc.c +++ /dev/null @@ -1,247 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* 1. Allocation functions doing the same work as the macros in the - case where [Setup_for_gc] and [Restore_after_gc] are no-ops. - 2. Convenience functions related to allocation. -*/ - -#include -#include "caml/alloc.h" -#include "caml/custom.h" -#include "caml/major_gc.h" -#include "caml/memory.h" -#include "caml/mlvalues.h" -#include "caml/stacks.h" - -#define Setup_for_gc -#define Restore_after_gc - -CAMLexport value caml_alloc (mlsize_t wosize, tag_t tag) -{ - value result; - mlsize_t i; - - CAMLassert (tag < 256); - CAMLassert (tag != Infix_tag); - if (wosize <= Max_young_wosize){ - if (wosize == 0){ - result = Atom (tag); - }else{ - Alloc_small (result, wosize, tag); - if (tag < No_scan_tag){ - for (i = 0; i < wosize; i++) Field (result, i) = Val_unit; - } - } - }else{ - result = caml_alloc_shr (wosize, tag); - if (tag < No_scan_tag){ - for (i = 0; i < wosize; i++) Field (result, i) = Val_unit; - } - result = caml_check_urgent_gc (result); - } - return result; -} - -CAMLexport value caml_alloc_small (mlsize_t wosize, tag_t tag) -{ - value result; - - CAMLassert (wosize > 0); - CAMLassert (wosize <= Max_young_wosize); - CAMLassert (tag < 256); - Alloc_small (result, wosize, tag); - return result; -} - -CAMLexport value caml_alloc_small_with_my_or_given_profinfo (mlsize_t wosize, - tag_t tag, uintnat profinfo) -{ - if (profinfo == 0) { - return caml_alloc_small(wosize, tag); - } - else { - value result; - - CAMLassert (wosize > 0); - CAMLassert (wosize <= Max_young_wosize); - CAMLassert (tag < 256); - Alloc_small_with_profinfo (result, wosize, tag, profinfo); - return result; - } -} - -/* [n] is a number of words (fields) */ -CAMLexport value caml_alloc_tuple(mlsize_t n) -{ - return caml_alloc(n, 0); -} - -/* [len] is a number of bytes (chars) */ -CAMLexport value caml_alloc_string (mlsize_t len) -{ - value result; - mlsize_t offset_index; - mlsize_t wosize = (len + sizeof (value)) / sizeof (value); - - if (wosize <= Max_young_wosize) { - Alloc_small (result, wosize, String_tag); - }else{ - result = caml_alloc_shr (wosize, String_tag); - result = caml_check_urgent_gc (result); - } - Field (result, wosize - 1) = 0; - offset_index = Bsize_wsize (wosize) - 1; - Byte (result, offset_index) = offset_index - len; - return result; -} - -/* [len] is a number of bytes (chars) */ -CAMLexport value caml_alloc_initialized_string (mlsize_t len, const char *p) -{ - value result = caml_alloc_string (len); - memcpy((char *)String_val(result), p, len); - return result; -} - -/* [len] is a number of words. - [mem] and [max] are relative (without unit). -*/ -CAMLexport value caml_alloc_final (mlsize_t len, final_fun fun, - mlsize_t mem, mlsize_t max) -{ - return caml_alloc_custom(caml_final_custom_operations(fun), - len * sizeof(value), mem, max); -} - -CAMLexport value caml_copy_string(char const *s) -{ - int len; - value res; - - len = strlen(s); - res = caml_alloc_initialized_string(len, s); - return res; -} - -CAMLexport value caml_alloc_array(value (*funct)(char const *), - char const ** arr) -{ - CAMLparam0 (); - mlsize_t nbr, n; - CAMLlocal2 (v, result); - - nbr = 0; - while (arr[nbr] != 0) nbr++; - result = caml_alloc (nbr, 0); - for (n = 0; n < nbr; n++) { - /* The two statements below must be separate because of evaluation - order (don't take the address &Field(result, n) before - calling funct, which may cause a GC and move result). */ - v = funct(arr[n]); - caml_modify(&Field(result, n), v); - } - CAMLreturn (result); -} - -/* [len] is a number of floats */ -value caml_alloc_float_array(mlsize_t len) -{ -#ifdef FLAT_FLOAT_ARRAY - mlsize_t wosize = len * Double_wosize; - value result; - /* For consistency with [caml_make_vect], which can't tell whether it should - create a float array or not when the size is zero, the tag is set to - zero when the size is zero. */ - if (wosize <= Max_young_wosize){ - if (wosize == 0) - return Atom(0); - else - Alloc_small (result, wosize, Double_array_tag); - }else { - result = caml_alloc_shr (wosize, Double_array_tag); - result = caml_check_urgent_gc (result); - } - return result; -#else - return caml_alloc (len, 0); -#endif -} - - -CAMLexport value caml_copy_string_array(char const ** arr) -{ - return caml_alloc_array(caml_copy_string, arr); -} - -CAMLexport int caml_convert_flag_list(value list, int *flags) -{ - int res; - res = 0; - while (list != Val_int(0)) { - res |= flags[Int_val(Field(list, 0))]; - list = Field(list, 1); - } - return res; -} - -/* For compiling let rec over values */ - -/* [size] is a [value] representing number of words (fields) */ -CAMLprim value caml_alloc_dummy(value size) -{ - mlsize_t wosize = Long_val(size); - return caml_alloc (wosize, 0); -} - -/* [size] is a [value] representing number of words (fields) */ -CAMLprim value caml_alloc_dummy_function(value size,value arity) -{ - /* the arity argument is used by the js_of_ocaml runtime */ - return caml_alloc_dummy(size); -} - -/* [size] is a [value] representing number of floats. */ -CAMLprim value caml_alloc_dummy_float (value size) -{ - mlsize_t wosize = Long_val(size) * Double_wosize; - return caml_alloc (wosize, 0); -} - -CAMLprim value caml_update_dummy(value dummy, value newval) -{ - mlsize_t size, i; - tag_t tag; - - size = Wosize_val(newval); - tag = Tag_val (newval); - CAMLassert (size == Wosize_val(dummy)); - CAMLassert (tag < No_scan_tag || tag == Double_array_tag); - - Tag_val(dummy) = tag; - if (tag == Double_array_tag){ - size = Wosize_val (newval) / Double_wosize; - for (i = 0; i < size; i++){ - Store_double_flat_field (dummy, i, Double_flat_field (newval, i)); - } - }else{ - for (i = 0; i < size; i++){ - caml_modify (&Field(dummy, i), Field(newval, i)); - } - } - return Val_unit; -} diff --git a/byterun/array.c b/byterun/array.c deleted file mode 100644 index 5367532b..00000000 --- a/byterun/array.c +++ /dev/null @@ -1,586 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Operations on arrays */ -#include -#include "caml/alloc.h" -#include "caml/fail.h" -#include "caml/memory.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/signals.h" -/* Why is caml/spacetime.h included conditionnally sometimes and not here ? */ -#include "caml/spacetime.h" - -static const mlsize_t mlsize_t_max = -1; - -/* returns number of elements (either fields or floats) */ -/* [ 'a array -> int ] */ -CAMLexport mlsize_t caml_array_length(value array) -{ -#ifdef FLAT_FLOAT_ARRAY - if (Tag_val(array) == Double_array_tag) - return Wosize_val(array) / Double_wosize; - else -#endif - return Wosize_val(array); -} - -CAMLexport int caml_is_double_array(value array) -{ - return (Tag_val(array) == Double_array_tag); -} - -/* Note: the OCaml types on the following primitives will work both with - and without the -no-flat-float-array configure-time option. If you - respect them, your C code should work in both configurations. -*/ - -/* [ 'a array -> int -> 'a ] where 'a != float */ -CAMLprim value caml_array_get_addr(value array, value index) -{ - intnat idx = Long_val(index); - if (idx < 0 || idx >= Wosize_val(array)) caml_array_bound_error(); - return Field(array, idx); -} - -/* [ float array -> int -> float ] */ -CAMLprim value caml_array_get_float(value array, value index) -{ - intnat idx = Long_val(index); -#ifdef FLAT_FLOAT_ARRAY - double d; - value res; - - if (idx < 0 || idx >= Wosize_val(array) / Double_wosize) - caml_array_bound_error(); - d = Double_flat_field(array, idx); -#define Setup_for_gc -#define Restore_after_gc - Alloc_small(res, Double_wosize, Double_tag); -#undef Setup_for_gc -#undef Restore_after_gc - Store_double_val(res, d); - return res; -#else - CAMLassert (Tag_val (array) != Double_array_tag); - if (idx < 0 || idx >= Wosize_val(array)) caml_array_bound_error(); - return Field(array, idx); -#endif /* FLAT_FLOAT_ARRAY */ -} - -/* [ 'a array -> int -> 'a ] */ -CAMLprim value caml_array_get(value array, value index) -{ -#ifdef FLAT_FLOAT_ARRAY - if (Tag_val(array) == Double_array_tag) - return caml_array_get_float(array, index); -#else - CAMLassert (Tag_val(array) != Double_array_tag); -#endif - return caml_array_get_addr(array, index); -} - -/* [ floatarray -> int -> float ] */ -CAMLprim value caml_floatarray_get(value array, value index) -{ - intnat idx = Long_val(index); - double d; - value res; - - CAMLassert (Tag_val(array) == Double_array_tag); - if (idx < 0 || idx >= Wosize_val(array) / Double_wosize) - caml_array_bound_error(); - d = Double_flat_field(array, idx); -#define Setup_for_gc -#define Restore_after_gc - Alloc_small(res, Double_wosize, Double_tag); -#undef Setup_for_gc -#undef Restore_after_gc - Store_double_val(res, d); - return res; -} - -/* [ 'a array -> int -> 'a -> unit ] where 'a != float */ -CAMLprim value caml_array_set_addr(value array, value index, value newval) -{ - intnat idx = Long_val(index); - if (idx < 0 || idx >= Wosize_val(array)) caml_array_bound_error(); - Modify(&Field(array, idx), newval); - return Val_unit; -} - -/* [ float array -> int -> float -> unit ] */ -CAMLprim value caml_array_set_float(value array, value index, value newval) -{ - intnat idx = Long_val(index); -#ifdef FLAT_FLOAT_ARRAY - double d = Double_val (newval); - if (idx < 0 || idx >= Wosize_val(array) / Double_wosize) - caml_array_bound_error(); - Store_double_flat_field(array, idx, d); -#else - CAMLassert (Tag_val (array) != Double_array_tag); - if (idx < 0 || idx >= Wosize_val(array)) caml_array_bound_error(); - Modify(&Field(array, idx), newval); -#endif - return Val_unit; -} - -/* [ 'a array -> int -> 'a -> unit ] */ -CAMLprim value caml_array_set(value array, value index, value newval) -{ -#ifdef FLAT_FLOAT_ARRAY - if (Tag_val(array) == Double_array_tag) - return caml_array_set_float(array, index, newval); -#else - CAMLassert (Tag_val(array) != Double_array_tag); -#endif - return caml_array_set_addr(array, index, newval); -} - -/* [ floatarray -> int -> float -> unit ] */ -CAMLprim value caml_floatarray_set(value array, value index, value newval) -{ - intnat idx = Long_val(index); - double d = Double_val (newval); - CAMLassert (Tag_val(array) == Double_array_tag); - if (idx < 0 || idx >= Wosize_val(array) / Double_wosize) - caml_array_bound_error(); - Store_double_flat_field(array, idx, d); - return Val_unit; -} - -/* [ float array -> int -> float ] */ -CAMLprim value caml_array_unsafe_get_float(value array, value index) -{ - intnat idx = Long_val (index); -#ifdef FLAT_FLOAT_ARRAY - double d; - value res; - - d = Double_flat_field(array, idx); -#define Setup_for_gc -#define Restore_after_gc - Alloc_small(res, Double_wosize, Double_tag); -#undef Setup_for_gc -#undef Restore_after_gc - Store_double_val(res, d); - return res; -#else /* FLAT_FLOAT_ARRAY */ - CAMLassert (Tag_val(array) != Double_array_tag); - return Field(array, idx); -#endif /* FLAT_FLOAT_ARRAY */ -} - -/* [ 'a array -> int -> 'a ] */ -CAMLprim value caml_array_unsafe_get(value array, value index) -{ -#ifdef FLAT_FLOAT_ARRAY - if (Tag_val(array) == Double_array_tag) - return caml_array_unsafe_get_float(array, index); -#else - CAMLassert (Tag_val(array) != Double_array_tag); -#endif - return Field(array, Long_val(index)); -} - -/* [ floatarray -> int -> float ] */ -CAMLprim value caml_floatarray_unsafe_get(value array, value index) -{ - intnat idx = Long_val(index); - double d; - value res; - - CAMLassert (Tag_val(array) == Double_array_tag); - d = Double_flat_field(array, idx); -#define Setup_for_gc -#define Restore_after_gc - Alloc_small(res, Double_wosize, Double_tag); -#undef Setup_for_gc -#undef Restore_after_gc - Store_double_val(res, d); - return res; -} - -/* [ 'a array -> int -> 'a -> unit ] where 'a != float */ -CAMLprim value caml_array_unsafe_set_addr(value array, value index,value newval) -{ - intnat idx = Long_val(index); - Modify(&Field(array, idx), newval); - return Val_unit; -} - -/* [ float array -> int -> float -> unit ] */ -CAMLprim value caml_array_unsafe_set_float(value array,value index,value newval) -{ - intnat idx = Long_val(index); -#ifdef FLAT_FLOAT_ARRAY - double d = Double_val (newval); - Store_double_flat_field(array, idx, d); -#else - Modify(&Field(array, idx), newval); -#endif - return Val_unit; -} - -/* [ 'a array -> int -> 'a -> unit ] */ -CAMLprim value caml_array_unsafe_set(value array, value index, value newval) -{ -#ifdef FLAT_FLOAT_ARRAY - if (Tag_val(array) == Double_array_tag) - return caml_array_unsafe_set_float(array, index, newval); -#else - CAMLassert (Tag_val(array) != Double_array_tag); -#endif - return caml_array_unsafe_set_addr(array, index, newval); -} - -/* [ floatarray -> int -> float -> unit ] */ -CAMLprim value caml_floatarray_unsafe_set(value array, value index,value newval) -{ - intnat idx = Long_val(index); - double d = Double_val (newval); - Store_double_flat_field(array, idx, d); - return Val_unit; -} - -/* [len] is a [value] representing number of floats. */ -/* [ int -> floatarray ] */ -CAMLprim value caml_floatarray_create(value len) -{ - mlsize_t wosize = Long_val(len) * Double_wosize; - value result; - if (wosize <= Max_young_wosize){ - if (wosize == 0) - return Atom(0); - else -#define Setup_for_gc -#define Restore_after_gc - Alloc_small (result, wosize, Double_array_tag); -#undef Setup_for_gc -#undef Restore_after_gc - }else if (wosize > Max_wosize) - caml_invalid_argument("Array.Floatarray.create"); - else { - result = caml_alloc_shr (wosize, Double_array_tag); - result = caml_check_urgent_gc (result); - } - return result; -} - -/* [len] is a [value] representing number of floats */ -/* [ int -> float array ] */ -CAMLprim value caml_make_float_vect(value len) -{ -#ifdef FLAT_FLOAT_ARRAY - return caml_floatarray_create (len); -#else - return caml_alloc (Long_val (len), 0); -#endif -} - -/* [len] is a [value] representing number of words or floats */ -/* Spacetime profiling assumes that this function is only called from OCaml. */ -CAMLprim value caml_make_vect(value len, value init) -{ - CAMLparam2 (len, init); - CAMLlocal1 (res); - mlsize_t size, i; - - size = Long_val(len); - if (size == 0) { - res = Atom(0); -#ifdef FLAT_FLOAT_ARRAY - } else if (Is_block(init) - && Is_in_value_area(init) - && Tag_val(init) == Double_tag) { - mlsize_t wsize; - double d; - d = Double_val(init); - wsize = size * Double_wosize; - if (wsize > Max_wosize) caml_invalid_argument("Array.make"); - res = caml_alloc(wsize, Double_array_tag); - for (i = 0; i < size; i++) { - Store_double_flat_field(res, i, d); - } -#endif - } else { - if (size <= Max_young_wosize) { - uintnat profinfo; - Get_my_profinfo_with_cached_backtrace(profinfo, size); - res = caml_alloc_small_with_my_or_given_profinfo(size, 0, profinfo); - for (i = 0; i < size; i++) Field(res, i) = init; - } - else if (size > Max_wosize) caml_invalid_argument("Array.make"); - else if (Is_block(init) && Is_young(init)) { - /* We don't want to create so many major-to-minor references, - so [init] is moved to the major heap by doing a minor GC. */ - CAML_INSTR_INT ("force_minor/make_vect@", 1); - caml_request_minor_gc (); - caml_gc_dispatch (); - res = caml_alloc_shr(size, 0); - for (i = 0; i < size; i++) Field(res, i) = init; - res = caml_check_urgent_gc (res); - } - else { - res = caml_alloc_shr(size, 0); - for (i = 0; i < size; i++) caml_initialize(&Field(res, i), init); - res = caml_check_urgent_gc (res); - } - } - CAMLreturn (res); -} - -/* This primitive is used internally by the compiler to compile - explicit array expressions. - For float arrays when FLAT_FLOAT_ARRAY is true, it takes an array of - boxed floats and returns the corresponding flat-allocated [float array]. - In all other cases, it just returns its argument unchanged. -*/ -CAMLprim value caml_make_array(value init) -{ -#ifdef FLAT_FLOAT_ARRAY - CAMLparam1 (init); - mlsize_t wsize, size, i; - CAMLlocal2 (v, res); - - size = Wosize_val(init); - if (size == 0) { - CAMLreturn (init); - } else { - v = Field(init, 0); - if (Is_long(v) - || ! Is_in_value_area(v) - || Tag_val(v) != Double_tag) { - CAMLreturn (init); - } else { - wsize = size * Double_wosize; - if (wsize <= Max_young_wosize) { - res = caml_alloc_small(wsize, Double_array_tag); - } else { - res = caml_alloc_shr(wsize, Double_array_tag); - res = caml_check_urgent_gc(res); - } - for (i = 0; i < size; i++) { - double d = Double_val(Field(init, i)); - Store_double_flat_field(res, i, d); - } - CAMLreturn (res); - } - } -#else - return init; -#endif -} - -/* Blitting */ - -CAMLprim value caml_array_blit(value a1, value ofs1, value a2, value ofs2, - value n) -{ - value * src, * dst; - intnat count; - -#ifdef FLAT_FLOAT_ARRAY - if (Tag_val(a2) == Double_array_tag) { - /* Arrays of floats. The values being copied are floats, not - pointer, so we can do a direct copy. memmove takes care of - potential overlap between the copied areas. */ - memmove((double *)a2 + Long_val(ofs2), - (double *)a1 + Long_val(ofs1), - Long_val(n) * sizeof(double)); - return Val_unit; - } -#endif - CAMLassert (Tag_val(a2) != Double_array_tag); - if (Is_young(a2)) { - /* Arrays of values, destination is in young generation. - Here too we can do a direct copy since this cannot create - old-to-young pointers, nor mess up with the incremental major GC. - Again, memmove takes care of overlap. */ - memmove(&Field(a2, Long_val(ofs2)), - &Field(a1, Long_val(ofs1)), - Long_val(n) * sizeof(value)); - return Val_unit; - } - /* Array of values, destination is in old generation. - We must use caml_modify. */ - count = Long_val(n); - if (a1 == a2 && Long_val(ofs1) < Long_val(ofs2)) { - /* Copy in descending order */ - for (dst = &Field(a2, Long_val(ofs2) + count - 1), - src = &Field(a1, Long_val(ofs1) + count - 1); - count > 0; - count--, src--, dst--) { - caml_modify(dst, *src); - } - } else { - /* Copy in ascending order */ - for (dst = &Field(a2, Long_val(ofs2)), src = &Field(a1, Long_val(ofs1)); - count > 0; - count--, src++, dst++) { - caml_modify(dst, *src); - } - } - /* Many caml_modify in a row can create a lot of old-to-young refs. - Give the minor GC a chance to run if it needs to. */ - caml_check_urgent_gc(Val_unit); - return Val_unit; -} - -/* A generic function for extraction and concatenation of sub-arrays */ - -static value caml_array_gather(intnat num_arrays, - value arrays[/*num_arrays*/], - intnat offsets[/*num_arrays*/], - intnat lengths[/*num_arrays*/]) -{ - CAMLparamN(arrays, num_arrays); - value res; /* no need to register it as a root */ -#ifdef FLAT_FLOAT_ARRAY - int isfloat = 0; - mlsize_t wsize; -#endif - mlsize_t i, size, count, pos; - value * src; - - /* Determine total size and whether result array is an array of floats */ - size = 0; - for (i = 0; i < num_arrays; i++) { - if (mlsize_t_max - lengths[i] < size) caml_invalid_argument("Array.concat"); - size += lengths[i]; -#ifdef FLAT_FLOAT_ARRAY - if (Tag_val(arrays[i]) == Double_array_tag) isfloat = 1; -#endif - } - if (size == 0) { - /* If total size = 0, just return empty array */ - res = Atom(0); - } -#ifdef FLAT_FLOAT_ARRAY - else if (isfloat) { - /* This is an array of floats. We can use memcpy directly. */ - if (size > Max_wosize/Double_wosize) caml_invalid_argument("Array.concat"); - wsize = size * Double_wosize; - res = caml_alloc(wsize, Double_array_tag); - for (i = 0, pos = 0; i < num_arrays; i++) { - memcpy((double *)res + pos, - (double *)arrays[i] + offsets[i], - lengths[i] * sizeof(double)); - pos += lengths[i]; - } - CAMLassert(pos == size); - } -#endif - else if (size <= Max_young_wosize) { - /* Array of values, small enough to fit in young generation. - We can use memcpy directly. */ - res = caml_alloc_small(size, 0); - for (i = 0, pos = 0; i < num_arrays; i++) { - memcpy(&Field(res, pos), - &Field(arrays[i], offsets[i]), - lengths[i] * sizeof(value)); - pos += lengths[i]; - } - CAMLassert(pos == size); - } - else if (size > Max_wosize) { - /* Array of values, too big. */ - caml_invalid_argument("Array.concat"); - } else { - /* Array of values, must be allocated in old generation and filled - using caml_initialize. */ - res = caml_alloc_shr(size, 0); - for (i = 0, pos = 0; i < num_arrays; i++) { - for (src = &Field(arrays[i], offsets[i]), count = lengths[i]; - count > 0; - count--, src++, pos++) { - caml_initialize(&Field(res, pos), *src); - } - } - CAMLassert(pos == size); - - /* Many caml_initialize in a row can create a lot of old-to-young - refs. Give the minor GC a chance to run if it needs to. */ - res = caml_check_urgent_gc(res); - } - CAMLreturn (res); -} - -CAMLprim value caml_array_sub(value a, value ofs, value len) -{ - value arrays[1] = { a }; - intnat offsets[1] = { Long_val(ofs) }; - intnat lengths[1] = { Long_val(len) }; - return caml_array_gather(1, arrays, offsets, lengths); -} - -CAMLprim value caml_array_append(value a1, value a2) -{ - value arrays[2] = { a1, a2 }; - intnat offsets[2] = { 0, 0 }; - intnat lengths[2] = { caml_array_length(a1), caml_array_length(a2) }; - return caml_array_gather(2, arrays, offsets, lengths); -} - -CAMLprim value caml_array_concat(value al) -{ -#define STATIC_SIZE 16 - value static_arrays[STATIC_SIZE], * arrays; - intnat static_offsets[STATIC_SIZE], * offsets; - intnat static_lengths[STATIC_SIZE], * lengths; - intnat n, i; - value l, res; - - /* Length of list = number of arrays */ - for (n = 0, l = al; l != Val_int(0); l = Field(l, 1)) n++; - /* Allocate extra storage if too many arrays */ - if (n <= STATIC_SIZE) { - arrays = static_arrays; - offsets = static_offsets; - lengths = static_lengths; - } else { - arrays = caml_stat_alloc(n * sizeof(value)); - offsets = caml_stat_alloc_noexc(n * sizeof(intnat)); - if (offsets == NULL) { - caml_stat_free(arrays); - caml_raise_out_of_memory(); - } - lengths = caml_stat_alloc_noexc(n * sizeof(value)); - if (lengths == NULL) { - caml_stat_free(offsets); - caml_stat_free(arrays); - caml_raise_out_of_memory(); - } - } - /* Build the parameters to caml_array_gather */ - for (i = 0, l = al; l != Val_int(0); l = Field(l, 1), i++) { - arrays[i] = Field(l, 0); - offsets[i] = 0; - lengths[i] = caml_array_length(Field(l, 0)); - } - /* Do the concatenation */ - res = caml_array_gather(n, arrays, offsets, lengths); - /* Free the extra storage if needed */ - if (n > STATIC_SIZE) { - caml_stat_free(arrays); - caml_stat_free(offsets); - caml_stat_free(lengths); - } - return res; -} diff --git a/byterun/backtrace.c b/byterun/backtrace.c deleted file mode 100644 index 8dfe9b7e..00000000 --- a/byterun/backtrace.c +++ /dev/null @@ -1,349 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Stack backtrace for uncaught exceptions */ - -#include -#include -#include - -#include "caml/alloc.h" -#include "caml/memory.h" -#include "caml/backtrace.h" -#include "caml/backtrace_prim.h" -#include "caml/fail.h" - -/* The table of debug information fragments */ -struct ext_table caml_debug_info; - -CAMLexport int32_t caml_backtrace_active = 0; -CAMLexport int32_t caml_backtrace_pos = 0; -CAMLexport backtrace_slot * caml_backtrace_buffer = NULL; -CAMLexport value caml_backtrace_last_exn = Val_unit; - -void caml_init_backtrace(void) -{ - caml_register_global_root(&caml_backtrace_last_exn); -} - -/* Start or stop the backtrace machinery */ -CAMLprim value caml_record_backtrace(value vflag) -{ - int flag = Int_val(vflag); - - if (flag != caml_backtrace_active) { - caml_backtrace_active = flag; - caml_backtrace_pos = 0; - caml_backtrace_last_exn = Val_unit; - /* Note: We do lazy initialization of caml_backtrace_buffer when - needed in order to simplify the interface with the thread - library (thread creation doesn't need to allocate - caml_backtrace_buffer). So we don't have to allocate it here. - */ - } - return Val_unit; -} - -/* Return the status of the backtrace machinery */ -CAMLprim value caml_backtrace_status(value vunit) -{ - return Val_bool(caml_backtrace_active); -} - -/* Print location information -- same behavior as in Printexc - - note that the test for compiler-inserted raises is slightly redundant: - (!li->loc_valid && li->loc_is_raise) - caml_debuginfo_location guarantees that when li->loc_valid is - 0, then li->loc_is_raise is always 1, so the latter test is - useless. We kept it to keep code identical to the byterun/ - implementation. */ -static void print_location(struct caml_loc_info * li, int index) -{ - char * info; - char * inlined; - - /* Ignore compiler-inserted raise */ - if (!li->loc_valid && li->loc_is_raise) return; - - if (li->loc_is_raise) { - /* Initial raise if index == 0, re-raise otherwise */ - if (index == 0) - info = "Raised at"; - else - info = "Re-raised at"; - } else { - if (index == 0) - info = "Raised by primitive operation at"; - else - info = "Called from"; - } - if (li->loc_is_inlined) { - inlined = " (inlined)"; - } else { - inlined = ""; - } - if (! li->loc_valid) { - fprintf(stderr, "%s unknown location%s\n", info, inlined); - } else { - fprintf (stderr, "%s file \"%s\"%s, line %d, characters %d-%d\n", - info, li->loc_filename, inlined, li->loc_lnum, - li->loc_startchr, li->loc_endchr); - } -} - -/* Print a backtrace */ -CAMLexport void caml_print_exception_backtrace(void) -{ - int i; - struct caml_loc_info li; - debuginfo dbg; - - if (!caml_debug_info_available()) { - fprintf(stderr, "(Cannot print stack backtrace: " - "no debug information available)\n"); - return; - } - - for (i = 0; i < caml_backtrace_pos; i++) { - for (dbg = caml_debuginfo_extract(caml_backtrace_buffer[i]); - dbg != NULL; - dbg = caml_debuginfo_next(dbg)) - { - caml_debuginfo_location(dbg, &li); - print_location(&li, i); - } - } -} - -/* Get a copy of the latest backtrace */ -CAMLprim value caml_get_exception_raw_backtrace(value unit) -{ - CAMLparam0(); - CAMLlocal1(res); - - /* Beware: the allocations below may cause finalizers to be run, and another - backtrace---possibly of a different length---to be stashed (for example - if the finalizer raises then catches an exception). We choose to ignore - any such finalizer backtraces and return the original one. */ - - if (!caml_backtrace_active || - caml_backtrace_buffer == NULL || - caml_backtrace_pos == 0) { - res = caml_alloc(0, 0); - } - else { - backtrace_slot saved_caml_backtrace_buffer[BACKTRACE_BUFFER_SIZE]; - int saved_caml_backtrace_pos; - intnat i; - - saved_caml_backtrace_pos = caml_backtrace_pos; - - if (saved_caml_backtrace_pos > BACKTRACE_BUFFER_SIZE) { - saved_caml_backtrace_pos = BACKTRACE_BUFFER_SIZE; - } - - memcpy(saved_caml_backtrace_buffer, caml_backtrace_buffer, - saved_caml_backtrace_pos * sizeof(backtrace_slot)); - - res = caml_alloc(saved_caml_backtrace_pos, 0); - for (i = 0; i < saved_caml_backtrace_pos; i++) { - Field(res, i) = Val_backtrace_slot(saved_caml_backtrace_buffer[i]); - } - } - - CAMLreturn(res); -} - -/* Copy back a backtrace and exception to the global state. - This function should be used only with Printexc.raw_backtrace */ -/* noalloc (caml value): so no CAMLparam* CAMLreturn* */ -CAMLprim value caml_restore_raw_backtrace(value exn, value backtrace) -{ - intnat i; - mlsize_t bt_size; - - caml_backtrace_last_exn = exn; - - bt_size = Wosize_val(backtrace); - if(bt_size > BACKTRACE_BUFFER_SIZE){ - bt_size = BACKTRACE_BUFFER_SIZE; - } - - /* We don't allocate if the backtrace is empty (no -g or backtrace - not activated) */ - if(bt_size == 0){ - caml_backtrace_pos = 0; - return Val_unit; - } - - /* Allocate if needed and copy the backtrace buffer */ - if (caml_backtrace_buffer == NULL && caml_alloc_backtrace_buffer() == -1){ - return Val_unit; - } - - caml_backtrace_pos = bt_size; - for(i=0; i < caml_backtrace_pos; i++){ - caml_backtrace_buffer[i] = Backtrace_slot_val(Field(backtrace, i)); - } - - return Val_unit; -} - -#define Val_debuginfo(bslot) (Val_long((uintnat)(bslot)>>1)) -#define Debuginfo_val(vslot) ((debuginfo)(Long_val(vslot) << 1)) - -/* Convert the raw backtrace to a data structure usable from OCaml */ -static value caml_convert_debuginfo(debuginfo dbg) -{ - CAMLparam0(); - CAMLlocal2(p, fname); - struct caml_loc_info li; - - caml_debuginfo_location(dbg, &li); - - if (li.loc_valid) { - fname = caml_copy_string(li.loc_filename); - p = caml_alloc_small(6, 0); - Field(p, 0) = Val_bool(li.loc_is_raise); - Field(p, 1) = fname; - Field(p, 2) = Val_int(li.loc_lnum); - Field(p, 3) = Val_int(li.loc_startchr); - Field(p, 4) = Val_int(li.loc_endchr); - Field(p, 5) = Val_bool(li.loc_is_inlined); - } else { - p = caml_alloc_small(1, 1); - Field(p, 0) = Val_bool(li.loc_is_raise); - } - - CAMLreturn(p); -} - -CAMLprim value caml_convert_raw_backtrace_slot(value slot) -{ - if (!caml_debug_info_available()) - caml_failwith("No debug information available"); - - return (caml_convert_debuginfo(Debuginfo_val(slot))); -} - -/* Convert the raw backtrace to a data structure usable from OCaml */ -CAMLprim value caml_convert_raw_backtrace(value bt) -{ - CAMLparam1(bt); - CAMLlocal1(array); - intnat i, index; - - if (!caml_debug_info_available()) - caml_failwith("No debug information available"); - - for (i = 0, index = 0; i < Wosize_val(bt); ++i) - { - debuginfo dbg; - for (dbg = caml_debuginfo_extract(Backtrace_slot_val(Field(bt, i))); - dbg != NULL; - dbg = caml_debuginfo_next(dbg)) - index++; - } - - array = caml_alloc(index, 0); - - for (i = 0, index = 0; i < Wosize_val(bt); ++i) - { - debuginfo dbg; - for (dbg = caml_debuginfo_extract(Backtrace_slot_val(Field(bt, i))); - dbg != NULL; - dbg = caml_debuginfo_next(dbg)) - { - Store_field(array, index, caml_convert_debuginfo(dbg)); - index++; - } - } - - CAMLreturn(array); -} - -CAMLprim value caml_raw_backtrace_length(value bt) -{ - return Val_int(Wosize_val(bt)); -} - -CAMLprim value caml_raw_backtrace_slot(value bt, value index) -{ - uintnat i; - debuginfo dbg; - - i = Long_val(index); - if (i >= Wosize_val(bt)) - caml_invalid_argument("Printexc.get_raw_backtrace_slot: " - "index out of bounds"); - dbg = caml_debuginfo_extract(Backtrace_slot_val(Field(bt, i))); - return Val_debuginfo(dbg); -} - -CAMLprim value caml_raw_backtrace_next_slot(value slot) -{ - debuginfo dbg; - - CAMLparam1(slot); - CAMLlocal1(v); - - dbg = Debuginfo_val(slot); - dbg = caml_debuginfo_next(dbg); - - if (dbg == NULL) - v = Val_int(0); /* None */ - else - { - v = caml_alloc(1, 0); - Field(v, 0) = Val_debuginfo(dbg); - } - - CAMLreturn(v); -} - -/* the function below is deprecated: we previously returned directly - the OCaml-usable representation, instead of the raw backtrace as an - abstract type, but this has a large performance overhead if you - store a lot of backtraces and print only some of them. - - It is not used by the Printexc library anymore, or anywhere else in - the compiler, but we have kept it in case some user still depends - on it as an external. */ -CAMLprim value caml_get_exception_backtrace(value unit) -{ - CAMLparam0(); - CAMLlocal3(arr, res, backtrace); - intnat i; - - if (!caml_debug_info_available()) { - res = Val_int(0); /* None */ - } else { - backtrace = caml_get_exception_raw_backtrace(Val_unit); - - arr = caml_alloc(Wosize_val(backtrace), 0); - for (i = 0; i < Wosize_val(backtrace); i++) { - backtrace_slot slot = Backtrace_slot_val(Field(backtrace, i)); - debuginfo dbg = caml_debuginfo_extract(slot); - Store_field(arr, i, caml_convert_debuginfo(dbg)); - } - - res = caml_alloc_small(1, 0); Field(res, 0) = arr; /* Some */ - } - - CAMLreturn(res); -} diff --git a/byterun/backtrace_prim.c b/byterun/backtrace_prim.c deleted file mode 100644 index e69b2568..00000000 --- a/byterun/backtrace_prim.c +++ /dev/null @@ -1,457 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Stack backtrace for uncaught exceptions */ - -#include -#include -#include -#include - -#include "caml/config.h" -#ifdef HAS_UNISTD -#include -#endif - -#include "caml/mlvalues.h" -#include "caml/alloc.h" -#include "caml/custom.h" -#include "caml/io.h" -#include "caml/instruct.h" -#include "caml/intext.h" -#include "caml/exec.h" -#include "caml/fix_code.h" -#include "caml/memory.h" -#include "caml/startup.h" -#include "caml/stacks.h" -#include "caml/sys.h" -#include "caml/backtrace.h" -#include "caml/fail.h" -#include "caml/backtrace_prim.h" - -/* The table of debug information fragments */ -struct ext_table caml_debug_info; - -CAMLexport char_os * caml_cds_file = NULL; - -/* Location of fields in the Instruct.debug_event record */ -enum { - EV_POS = 0, - EV_MODULE = 1, - EV_LOC = 2, - EV_KIND = 3 -}; - -/* Location of fields in the Location.t record. */ -enum { - LOC_START = 0, - LOC_END = 1, - LOC_GHOST = 2 -}; - -/* Location of fields in the Lexing.position record. */ -enum { - POS_FNAME = 0, - POS_LNUM = 1, - POS_BOL = 2, - POS_CNUM = 3 -}; - -/* Runtime representation of the debug information, optimized - for quick lookup */ -struct ev_info { - code_t ev_pc; - char *ev_filename; - int ev_lnum; - int ev_startchr; - int ev_endchr; -}; - -struct debug_info { - code_t start; - code_t end; - mlsize_t num_events; - struct ev_info *events; - int already_read; -}; - -static struct debug_info *find_debug_info(code_t pc) -{ - int i; - for (i = 0; i < caml_debug_info.size; i++) { - struct debug_info *di = caml_debug_info.contents[i]; - if (pc >= di->start && pc < di->end) - return di; - } - return NULL; -} - -static int cmp_ev_info(const void *a, const void *b) -{ - code_t pc_a = ((const struct ev_info*)a)->ev_pc; - code_t pc_b = ((const struct ev_info*)b)->ev_pc; - if (pc_a > pc_b) return 1; - if (pc_a < pc_b) return -1; - return 0; -} - -static struct ev_info *process_debug_events(code_t code_start, value events_heap, - mlsize_t *num_events) -{ - CAMLparam1(events_heap); - CAMLlocal3(l, ev, ev_start); - mlsize_t i, j; - struct ev_info *events; - - /* Compute the size of the required event buffer. */ - *num_events = 0; - for (i = 0; i < caml_array_length(events_heap); i++) - for (l = Field(events_heap, i); l != Val_int(0); l = Field(l, 1)) - (*num_events)++; - - if (*num_events == 0) - CAMLreturnT(struct ev_info *, NULL); - - events = caml_stat_alloc_noexc(*num_events * sizeof(struct ev_info)); - if(events == NULL) - caml_fatal_error ("caml_add_debug_info: out of memory"); - - j = 0; - for (i = 0; i < caml_array_length(events_heap); i++) { - for (l = Field(events_heap, i); l != Val_int(0); l = Field(l, 1)) { - ev = Field(l, 0); - - events[j].ev_pc = (code_t)((char*)code_start - + Long_val(Field(ev, EV_POS))); - - ev_start = Field(Field(ev, EV_LOC), LOC_START); - - { - uintnat fnsz = caml_string_length(Field(ev_start, POS_FNAME)) + 1; - events[j].ev_filename = (char*)caml_stat_alloc_noexc(fnsz); - if(events[j].ev_filename == NULL) - caml_fatal_error ("caml_add_debug_info: out of memory"); - memcpy(events[j].ev_filename, - String_val(Field(ev_start, POS_FNAME)), - fnsz); - } - - events[j].ev_lnum = Int_val(Field(ev_start, POS_LNUM)); - events[j].ev_startchr = - Int_val(Field(ev_start, POS_CNUM)) - - Int_val(Field(ev_start, POS_BOL)); - events[j].ev_endchr = - Int_val(Field(Field(Field(ev, EV_LOC), LOC_END), POS_CNUM)) - - Int_val(Field(ev_start, POS_BOL)); - - j++; - } - } - - CAMLassert(j == *num_events); - - qsort(events, *num_events, sizeof(struct ev_info), cmp_ev_info); - - CAMLreturnT(struct ev_info *, events); -} - -/* Processes a (Instruct.debug_event list array) into a form suitable - for quick lookup and registers it for the (code_start,code_size) pc range. */ -CAMLprim value caml_add_debug_info(code_t code_start, value code_size, - value events_heap) -{ - CAMLparam1(events_heap); - struct debug_info *debug_info; - - /* build the OCaml-side debug_info value */ - debug_info = caml_stat_alloc(sizeof(struct debug_info)); - - debug_info->start = code_start; - debug_info->end = (code_t)((char*) code_start + Long_val(code_size)); - if (events_heap == Val_unit) { - debug_info->events = NULL; - debug_info->num_events = 0; - debug_info->already_read = 0; - } else { - debug_info->events = - process_debug_events(code_start, events_heap, &debug_info->num_events); - debug_info->already_read = 1; - } - - caml_ext_table_add(&caml_debug_info, debug_info); - - CAMLreturn(Val_unit); -} - -CAMLprim value caml_remove_debug_info(code_t start) -{ - CAMLparam0(); - CAMLlocal2(dis, prev); - - int i; - for (i = 0; i < caml_debug_info.size; i++) { - struct debug_info *di = caml_debug_info.contents[i]; - if (di->start == start) { - /* note that caml_ext_table_remove calls caml_stat_free on the - removed resource, bracketing the caml_stat_alloc call in - caml_add_debug_info. */ - caml_ext_table_remove(&caml_debug_info, di); - break; - } - } - - CAMLreturn(Val_unit); -} - -int caml_alloc_backtrace_buffer(void){ - CAMLassert(caml_backtrace_pos == 0); - caml_backtrace_buffer = - caml_stat_alloc_noexc(BACKTRACE_BUFFER_SIZE * sizeof(code_t)); - if (caml_backtrace_buffer == NULL) return -1; - return 0; -} - -/* Store the return addresses contained in the given stack fragment - into the backtrace array */ - -void caml_stash_backtrace(value exn, code_t pc, value * sp, int reraise) -{ - if (pc != NULL) pc = pc - 1; - if (exn != caml_backtrace_last_exn || !reraise) { - caml_backtrace_pos = 0; - caml_backtrace_last_exn = exn; - } - - if (caml_backtrace_buffer == NULL && caml_alloc_backtrace_buffer() == -1) - return; - - if (caml_backtrace_pos >= BACKTRACE_BUFFER_SIZE) return; - /* testing the code region is needed: PR#1554 */ - if (find_debug_info(pc) != NULL) - caml_backtrace_buffer[caml_backtrace_pos++] = pc; - - /* Traverse the stack and put all values pointing into bytecode - into the backtrace buffer. */ - for (/*nothing*/; sp < caml_trapsp; sp++) { - code_t p = (code_t) *sp; - if (caml_backtrace_pos >= BACKTRACE_BUFFER_SIZE) break; - if (find_debug_info(p) != NULL) - caml_backtrace_buffer[caml_backtrace_pos++] = p; - } -} - -/* returns the next frame pointer (or NULL if none is available); - updates *sp to point to the following one, and *trsp to the next - trap frame, which we will skip when we reach it */ - -code_t caml_next_frame_pointer(value ** sp, value ** trsp) -{ - while (*sp < caml_stack_high) { - code_t *p = (code_t*) (*sp)++; - if(&Trap_pc(*trsp) == p) { - *trsp = Trap_link(*trsp); - continue; - } - - if (find_debug_info(*p) != NULL) - return *p; - } - return NULL; -} - -/* Stores upto [max_frames_value] frames of the current call stack to - return to the user. This is used not in an exception-raising - context, but only when the user requests to save the trace - (hopefully less often). Instead of using a bounded buffer as - [caml_stash_backtrace], we first traverse the stack to compute the - right size, then allocate space for the trace. */ - -CAMLprim value caml_get_current_callstack(value max_frames_value) -{ - CAMLparam1(max_frames_value); - CAMLlocal1(trace); - - /* we use `intnat` here because, were it only `int`, passing `max_int` - from the OCaml side would overflow on 64bits machines. */ - intnat max_frames = Long_val(max_frames_value); - intnat trace_size; - - /* first compute the size of the trace */ - { - value * sp = caml_extern_sp; - value * trsp = caml_trapsp; - - for (trace_size = 0; trace_size < max_frames; trace_size++) { - code_t p = caml_next_frame_pointer(&sp, &trsp); - if (p == NULL) break; - } - } - - trace = caml_alloc(trace_size, 0); - - /* then collect the trace */ - { - value * sp = caml_extern_sp; - value * trsp = caml_trapsp; - uintnat trace_pos; - - for (trace_pos = 0; trace_pos < trace_size; trace_pos++) { - code_t p = caml_next_frame_pointer(&sp, &trsp); - CAMLassert(p != NULL); - Field(trace, trace_pos) = Val_backtrace_slot(p); - } - } - - CAMLreturn(trace); -} - -/* Read the debugging info contained in the current bytecode executable. */ - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -static void read_main_debug_info(struct debug_info *di) -{ - CAMLparam0(); - CAMLlocal3(events, evl, l); - char_os *exec_name; - int fd, num_events, orig, i; - struct channel *chan; - struct exec_trailer trail; - - CAMLassert(di->already_read == 0); - di->already_read = 1; - - if (caml_cds_file != NULL) { - exec_name = caml_cds_file; - } else { - exec_name = caml_exe_name; - } - - fd = caml_attempt_open(&exec_name, &trail, 1); - if (fd < 0){ - caml_fatal_error ("executable program file not found"); - CAMLreturn0; - } - - caml_read_section_descriptors(fd, &trail); - if (caml_seek_optional_section(fd, &trail, "DBUG") != -1) { - chan = caml_open_descriptor_in(fd); - - num_events = caml_getword(chan); - events = caml_alloc(num_events, 0); - - for (i = 0; i < num_events; i++) { - orig = caml_getword(chan); - evl = caml_input_val(chan); - caml_input_val(chan); /* Skip the list of absolute directory names */ - /* Relocate events in event list */ - for (l = evl; l != Val_int(0); l = Field(l, 1)) { - value ev = Field(l, 0); - Field(ev, EV_POS) = Val_long(Long_val(Field(ev, EV_POS)) + orig); - } - /* Record event list */ - Store_field(events, i, evl); - } - - caml_close_channel(chan); - - di->events = process_debug_events(caml_start_code, events, &di->num_events); - } - - CAMLreturn0; -} - -CAMLexport void caml_init_debug_info(void) -{ - caml_ext_table_init(&caml_debug_info, 1); - caml_add_debug_info(caml_start_code, Val_long(caml_code_size), Val_unit); -} - -int caml_debug_info_available(void) -{ - return (caml_debug_info.size != 0); -} - -/* Search the event index for the given PC. Return -1 if not found. */ - -static struct ev_info *event_for_location(code_t pc) -{ - uintnat low, high; - struct debug_info *di = find_debug_info(pc); - - if (di == NULL) - return NULL; - - if (!di->already_read) - read_main_debug_info(di); - - if (di->num_events == 0) - return NULL; - - low = 0; - high = di->num_events; - while (low+1 < high) { - uintnat m = (low+high)/2; - if(pc < di->events[m].ev_pc) high = m; - else low = m; - } - if (di->events[low].ev_pc == pc) - return &di->events[low]; - /* ocamlc sometimes moves an event past a following PUSH instruction; - allow mismatch by 1 instruction. */ - if (di->events[low].ev_pc == pc + 1) - return &di->events[low]; - if (low+1 < di->num_events && di->events[low+1].ev_pc == pc + 1) - return &di->events[low+1]; - - return NULL; -} - -/* Extract location information for the given PC */ - -void caml_debuginfo_location(debuginfo dbg, - /*out*/ struct caml_loc_info * li) -{ - code_t pc = dbg; - struct ev_info *event = event_for_location(pc); - li->loc_is_raise = - caml_is_instruction(*pc, RAISE) || - caml_is_instruction(*pc, RERAISE); - if (event == NULL) { - li->loc_valid = 0; - return; - } - li->loc_valid = 1; - li->loc_is_inlined = 0; - li->loc_filename = event->ev_filename; - li->loc_lnum = event->ev_lnum; - li->loc_startchr = event->ev_startchr; - li->loc_endchr = event->ev_endchr; -} - -debuginfo caml_debuginfo_extract(backtrace_slot slot) -{ - return (debuginfo)slot; -} - -debuginfo caml_debuginfo_next(debuginfo dbg) -{ - /* No inlining in bytecode */ - return NULL; -} diff --git a/byterun/bigarray.c b/byterun/bigarray.c deleted file mode 100644 index 3e376799..00000000 --- a/byterun/bigarray.c +++ /dev/null @@ -1,1223 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -#include -#include -#include -#include "caml/alloc.h" -#include "caml/bigarray.h" -#include "caml/custom.h" -#include "caml/fail.h" -#include "caml/intext.h" -#include "caml/hash.h" -#include "caml/memory.h" -#include "caml/mlvalues.h" -#include "caml/signals.h" - -#define int8 caml_ba_int8 -#define uint8 caml_ba_uint8 -#define int16 caml_ba_int16 -#define uint16 caml_ba_uint16 - -/* Compute the number of elements of a big array */ - -CAMLexport uintnat caml_ba_num_elts(struct caml_ba_array * b) -{ - uintnat num_elts; - int i; - num_elts = 1; - for (i = 0; i < b->num_dims; i++) num_elts = num_elts * b->dim[i]; - return num_elts; -} - -/* Size in bytes of a bigarray element, indexed by bigarray kind */ - -CAMLexport int caml_ba_element_size[] = -{ 4 /*FLOAT32*/, 8 /*FLOAT64*/, - 1 /*SINT8*/, 1 /*UINT8*/, - 2 /*SINT16*/, 2 /*UINT16*/, - 4 /*INT32*/, 8 /*INT64*/, - sizeof(value) /*CAML_INT*/, sizeof(value) /*NATIVE_INT*/, - 8 /*COMPLEX32*/, 16 /*COMPLEX64*/, - 1 /*CHAR*/ -}; - -/* Compute the number of bytes for the elements of a big array */ - -CAMLexport uintnat caml_ba_byte_size(struct caml_ba_array * b) -{ - return caml_ba_num_elts(b) - * caml_ba_element_size[b->flags & CAML_BA_KIND_MASK]; -} - -/* Operation table for bigarrays */ - -CAMLexport struct custom_operations caml_ba_ops = { - "_bigarray", - caml_ba_finalize, - caml_ba_compare, - caml_ba_hash, - caml_ba_serialize, - caml_ba_deserialize, - custom_compare_ext_default -}; - -/* Allocation of a big array */ - -#define CAML_BA_MAX_MEMORY 1024*1024*1024 -/* 1 Gb -- after allocating that much, it's probably worth speeding - up the major GC */ - -/* [caml_ba_alloc] will allocate a new bigarray object in the heap. - If [data] is NULL, the memory for the contents is also allocated - (with [malloc]) by [caml_ba_alloc]. - [data] cannot point into the OCaml heap. - [dim] may point into an object in the OCaml heap. -*/ -CAMLexport value -caml_ba_alloc(int flags, int num_dims, void * data, intnat * dim) -{ - uintnat num_elts, asize, size; - int i; - value res; - struct caml_ba_array * b; - intnat dimcopy[CAML_BA_MAX_NUM_DIMS]; - - CAMLassert(num_dims >= 0 && num_dims <= CAML_BA_MAX_NUM_DIMS); - CAMLassert((flags & CAML_BA_KIND_MASK) <= CAML_BA_CHAR); - for (i = 0; i < num_dims; i++) dimcopy[i] = dim[i]; - size = 0; - if (data == NULL) { - num_elts = 1; - for (i = 0; i < num_dims; i++) { - if (caml_umul_overflow(num_elts, dimcopy[i], &num_elts)) - caml_raise_out_of_memory(); - } - if (caml_umul_overflow(num_elts, - caml_ba_element_size[flags & CAML_BA_KIND_MASK], - &size)) - caml_raise_out_of_memory(); - data = malloc(size); - if (data == NULL && size != 0) caml_raise_out_of_memory(); - flags |= CAML_BA_MANAGED; - } - asize = SIZEOF_BA_ARRAY + num_dims * sizeof(intnat); - res = caml_alloc_custom(&caml_ba_ops, asize, size, CAML_BA_MAX_MEMORY); - b = Caml_ba_array_val(res); - b->data = data; - b->num_dims = num_dims; - b->flags = flags; - b->proxy = NULL; - for (i = 0; i < num_dims; i++) b->dim[i] = dimcopy[i]; - return res; -} - -/* Same as caml_ba_alloc, but dimensions are passed as a list of - arguments */ - -CAMLexport value caml_ba_alloc_dims(int flags, int num_dims, void * data, ...) -{ - va_list ap; - intnat dim[CAML_BA_MAX_NUM_DIMS]; - int i; - value res; - - CAMLassert(num_dims <= CAML_BA_MAX_NUM_DIMS); - va_start(ap, data); - for (i = 0; i < num_dims; i++) dim[i] = va_arg(ap, intnat); - va_end(ap); - res = caml_ba_alloc(flags, num_dims, data, dim); - return res; -} - -/* Finalization of a big array */ - -CAMLexport void caml_ba_finalize(value v) -{ - struct caml_ba_array * b = Caml_ba_array_val(v); - - switch (b->flags & CAML_BA_MANAGED_MASK) { - case CAML_BA_EXTERNAL: - break; - case CAML_BA_MANAGED: - if (b->proxy == NULL) { - free(b->data); - } else { - if (-- b->proxy->refcount == 0) { - free(b->proxy->data); - free(b->proxy); - } - } - break; - case CAML_BA_MAPPED_FILE: - /* Bigarrays for mapped files use a different finalization method */ - default: - CAMLassert(0); - } -} - -/* Comparison of two big arrays */ - -CAMLexport int caml_ba_compare(value v1, value v2) -{ - struct caml_ba_array * b1 = Caml_ba_array_val(v1); - struct caml_ba_array * b2 = Caml_ba_array_val(v2); - uintnat n, num_elts; - intnat flags1, flags2; - int i; - - /* Compare kind & layout in case the arguments are of different types */ - flags1 = b1->flags & (CAML_BA_KIND_MASK | CAML_BA_LAYOUT_MASK); - flags2 = b2->flags & (CAML_BA_KIND_MASK | CAML_BA_LAYOUT_MASK); - if (flags1 != flags2) return flags2 - flags1; - /* Compare number of dimensions */ - if (b1->num_dims != b2->num_dims) return b2->num_dims - b1->num_dims; - /* Same number of dimensions: compare dimensions lexicographically */ - for (i = 0; i < b1->num_dims; i++) { - intnat d1 = b1->dim[i]; - intnat d2 = b2->dim[i]; - if (d1 != d2) return d1 < d2 ? -1 : 1; - } - /* Same dimensions: compare contents lexicographically */ - num_elts = caml_ba_num_elts(b1); - -#define DO_INTEGER_COMPARISON(type) \ - { type * p1 = b1->data; type * p2 = b2->data; \ - for (n = 0; n < num_elts; n++) { \ - type e1 = *p1++; type e2 = *p2++; \ - if (e1 < e2) return -1; \ - if (e1 > e2) return 1; \ - } \ - return 0; \ - } -#define DO_FLOAT_COMPARISON(type) \ - { type * p1 = b1->data; type * p2 = b2->data; \ - for (n = 0; n < num_elts; n++) { \ - type e1 = *p1++; type e2 = *p2++; \ - if (e1 < e2) return -1; \ - if (e1 > e2) return 1; \ - if (e1 != e2) { \ - caml_compare_unordered = 1; \ - if (e1 == e1) return 1; \ - if (e2 == e2) return -1; \ - } \ - } \ - return 0; \ - } - - switch (b1->flags & CAML_BA_KIND_MASK) { - case CAML_BA_COMPLEX32: - num_elts *= 2; /*fallthrough*/ - case CAML_BA_FLOAT32: - DO_FLOAT_COMPARISON(float); - case CAML_BA_COMPLEX64: - num_elts *= 2; /*fallthrough*/ - case CAML_BA_FLOAT64: - DO_FLOAT_COMPARISON(double); - case CAML_BA_CHAR: - DO_INTEGER_COMPARISON(caml_ba_uint8); - case CAML_BA_SINT8: - DO_INTEGER_COMPARISON(caml_ba_int8); - case CAML_BA_UINT8: - DO_INTEGER_COMPARISON(caml_ba_uint8); - case CAML_BA_SINT16: - DO_INTEGER_COMPARISON(caml_ba_int16); - case CAML_BA_UINT16: - DO_INTEGER_COMPARISON(caml_ba_uint16); - case CAML_BA_INT32: - DO_INTEGER_COMPARISON(int32_t); - case CAML_BA_INT64: - DO_INTEGER_COMPARISON(int64_t); - case CAML_BA_CAML_INT: - case CAML_BA_NATIVE_INT: - DO_INTEGER_COMPARISON(intnat); - default: - CAMLassert(0); - return 0; /* should not happen */ - } -#undef DO_INTEGER_COMPARISON -#undef DO_FLOAT_COMPARISON -} - -/* Hashing of a bigarray */ - -CAMLexport intnat caml_ba_hash(value v) -{ - struct caml_ba_array * b = Caml_ba_array_val(v); - intnat num_elts, n; - uint32_t h, w; - int i; - - num_elts = 1; - for (i = 0; i < b->num_dims; i++) num_elts = num_elts * b->dim[i]; - h = 0; - - switch (b->flags & CAML_BA_KIND_MASK) { - case CAML_BA_CHAR: - case CAML_BA_SINT8: - case CAML_BA_UINT8: { - caml_ba_uint8 * p = b->data; - if (num_elts > 256) num_elts = 256; - for (n = 0; n + 4 <= num_elts; n += 4, p += 4) { - w = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); - h = caml_hash_mix_uint32(h, w); - } - w = 0; - switch (num_elts & 3) { - case 3: w = p[2] << 16; /* fallthrough */ - case 2: w |= p[1] << 8; /* fallthrough */ - case 1: w |= p[0]; - h = caml_hash_mix_uint32(h, w); - } - break; - } - case CAML_BA_SINT16: - case CAML_BA_UINT16: { - caml_ba_uint16 * p = b->data; - if (num_elts > 128) num_elts = 128; - for (n = 0; n + 2 <= num_elts; n += 2, p += 2) { - w = p[0] | (p[1] << 16); - h = caml_hash_mix_uint32(h, w); - } - if ((num_elts & 1) != 0) - h = caml_hash_mix_uint32(h, p[0]); - break; - } - case CAML_BA_INT32: - { - uint32_t * p = b->data; - if (num_elts > 64) num_elts = 64; - for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_uint32(h, *p); - break; - } - case CAML_BA_CAML_INT: - case CAML_BA_NATIVE_INT: - { - intnat * p = b->data; - if (num_elts > 64) num_elts = 64; - for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_intnat(h, *p); - break; - } - case CAML_BA_INT64: - { - int64_t * p = b->data; - if (num_elts > 32) num_elts = 32; - for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_int64(h, *p); - break; - } - case CAML_BA_COMPLEX32: - num_elts *= 2; /* fallthrough */ - case CAML_BA_FLOAT32: - { - float * p = b->data; - if (num_elts > 64) num_elts = 64; - for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_float(h, *p); - break; - } - case CAML_BA_COMPLEX64: - num_elts *= 2; /* fallthrough */ - case CAML_BA_FLOAT64: - { - double * p = b->data; - if (num_elts > 32) num_elts = 32; - for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_double(h, *p); - break; - } - } - return h; -} - -static void caml_ba_serialize_longarray(void * data, - intnat num_elts, - intnat min_val, intnat max_val) -{ -#ifdef ARCH_SIXTYFOUR - int overflow_32 = 0; - intnat * p, n; - for (n = 0, p = data; n < num_elts; n++, p++) { - if (*p < min_val || *p > max_val) { overflow_32 = 1; break; } - } - if (overflow_32) { - caml_serialize_int_1(1); - caml_serialize_block_8(data, num_elts); - } else { - caml_serialize_int_1(0); - for (n = 0, p = data; n < num_elts; n++, p++) - caml_serialize_int_4((int32_t) *p); - } -#else - caml_serialize_int_1(0); - caml_serialize_block_4(data, num_elts); -#endif -} - -CAMLexport void caml_ba_serialize(value v, - uintnat * wsize_32, - uintnat * wsize_64) -{ - struct caml_ba_array * b = Caml_ba_array_val(v); - intnat num_elts; - int i; - - /* Serialize header information */ - caml_serialize_int_4(b->num_dims); - caml_serialize_int_4(b->flags & (CAML_BA_KIND_MASK | CAML_BA_LAYOUT_MASK)); - /* On a 64-bit machine, if any of the dimensions is >= 2^32, - the size of the marshaled data will be >= 2^32 and - extern_value() will fail. So, it is safe to write the dimensions - as 32-bit unsigned integers. */ - for (i = 0; i < b->num_dims; i++) caml_serialize_int_4(b->dim[i]); - /* Compute total number of elements */ - num_elts = 1; - for (i = 0; i < b->num_dims; i++) num_elts = num_elts * b->dim[i]; - /* Serialize elements */ - switch (b->flags & CAML_BA_KIND_MASK) { - case CAML_BA_CHAR: - case CAML_BA_SINT8: - case CAML_BA_UINT8: - caml_serialize_block_1(b->data, num_elts); break; - case CAML_BA_SINT16: - case CAML_BA_UINT16: - caml_serialize_block_2(b->data, num_elts); break; - case CAML_BA_FLOAT32: - case CAML_BA_INT32: - caml_serialize_block_4(b->data, num_elts); break; - case CAML_BA_COMPLEX32: - caml_serialize_block_4(b->data, num_elts * 2); break; - case CAML_BA_FLOAT64: - case CAML_BA_INT64: - caml_serialize_block_8(b->data, num_elts); break; - case CAML_BA_COMPLEX64: - caml_serialize_block_8(b->data, num_elts * 2); break; - case CAML_BA_CAML_INT: - caml_ba_serialize_longarray(b->data, num_elts, -0x40000000, 0x3FFFFFFF); - break; - case CAML_BA_NATIVE_INT: - caml_ba_serialize_longarray(b->data, num_elts, -0x80000000, 0x7FFFFFFF); - break; - } - /* Compute required size in OCaml heap. Assumes struct caml_ba_array - is exactly 4 + num_dims words */ - CAMLassert(SIZEOF_BA_ARRAY == 4 * sizeof(value)); - *wsize_32 = (4 + b->num_dims) * 4; - *wsize_64 = (4 + b->num_dims) * 8; -} - -static void caml_ba_deserialize_longarray(void * dest, intnat num_elts) -{ - int sixty = caml_deserialize_uint_1(); -#ifdef ARCH_SIXTYFOUR - if (sixty) { - caml_deserialize_block_8(dest, num_elts); - } else { - intnat * p, n; - for (n = 0, p = dest; n < num_elts; n++, p++) - *p = caml_deserialize_sint_4(); - } -#else - if (sixty) - caml_deserialize_error("input_value: cannot read bigarray " - "with 64-bit OCaml ints"); - caml_deserialize_block_4(dest, num_elts); -#endif -} - -CAMLexport uintnat caml_ba_deserialize(void * dst) -{ - struct caml_ba_array * b = dst; - int i; - uintnat num_elts, size; - - /* Read back header information */ - b->num_dims = caml_deserialize_uint_4(); - if (b->num_dims < 0 || b->num_dims > CAML_BA_MAX_NUM_DIMS) - caml_deserialize_error("input_value: wrong number of bigarray dimensions"); - b->flags = caml_deserialize_uint_4() | CAML_BA_MANAGED; - b->proxy = NULL; - for (i = 0; i < b->num_dims; i++) b->dim[i] = caml_deserialize_uint_4(); - /* Compute total number of elements. Watch out for overflows (MPR#7765). */ - num_elts = 1; - for (i = 0; i < b->num_dims; i++) { - if (caml_umul_overflow(num_elts, b->dim[i], &num_elts)) - caml_deserialize_error("input_value: size overflow for bigarray"); - } - /* Determine array size in bytes. Watch out for overflows (MPR#7765). */ - if ((b->flags & CAML_BA_KIND_MASK) > CAML_BA_CHAR) - caml_deserialize_error("input_value: bad bigarray kind"); - if (caml_umul_overflow(num_elts, - caml_ba_element_size[b->flags & CAML_BA_KIND_MASK], - &size)) - caml_deserialize_error("input_value: size overflow for bigarray"); - /* Allocate room for data */ - b->data = malloc(size); - if (b->data == NULL) - caml_deserialize_error("input_value: out of memory for bigarray"); - /* Read data */ - switch (b->flags & CAML_BA_KIND_MASK) { - case CAML_BA_CHAR: - case CAML_BA_SINT8: - case CAML_BA_UINT8: - caml_deserialize_block_1(b->data, num_elts); break; - case CAML_BA_SINT16: - case CAML_BA_UINT16: - caml_deserialize_block_2(b->data, num_elts); break; - case CAML_BA_FLOAT32: - case CAML_BA_INT32: - caml_deserialize_block_4(b->data, num_elts); break; - case CAML_BA_COMPLEX32: - caml_deserialize_block_4(b->data, num_elts * 2); break; - case CAML_BA_FLOAT64: - case CAML_BA_INT64: - caml_deserialize_block_8(b->data, num_elts); break; - case CAML_BA_COMPLEX64: - caml_deserialize_block_8(b->data, num_elts * 2); break; - case CAML_BA_CAML_INT: - case CAML_BA_NATIVE_INT: - caml_ba_deserialize_longarray(b->data, num_elts); break; - } - /* PR#5516: use C99's flexible array types if possible */ - return SIZEOF_BA_ARRAY + b->num_dims * sizeof(intnat); -} - -/* Allocate a bigarray from OCaml */ - -CAMLprim value caml_ba_create(value vkind, value vlayout, value vdim) -{ - intnat dim[CAML_BA_MAX_NUM_DIMS]; - mlsize_t num_dims; - int i, flags; - - num_dims = Wosize_val(vdim); - /* here num_dims is unsigned (mlsize_t) so no need to check (num_dims >= 0) */ - if (num_dims > CAML_BA_MAX_NUM_DIMS) - caml_invalid_argument("Bigarray.create: bad number of dimensions"); - for (i = 0; i < num_dims; i++) { - dim[i] = Long_val(Field(vdim, i)); - if (dim[i] < 0) - caml_invalid_argument("Bigarray.create: negative dimension"); - } - flags = Caml_ba_kind_val(vkind) | Caml_ba_layout_val(vlayout); - return caml_ba_alloc(flags, num_dims, NULL, dim); -} - -/* Given a big array and a vector of indices, check that the indices - are within the bounds and return the offset of the corresponding - array element in the data part of the array. */ - -static long caml_ba_offset(struct caml_ba_array * b, intnat * index) -{ - intnat offset; - int i; - - offset = 0; - if ((b->flags & CAML_BA_LAYOUT_MASK) == CAML_BA_C_LAYOUT) { - /* C-style layout: row major, indices start at 0 */ - for (i = 0; i < b->num_dims; i++) { - if ((uintnat) index[i] >= (uintnat) b->dim[i]) - caml_array_bound_error(); - offset = offset * b->dim[i] + index[i]; - } - } else { - /* Fortran-style layout: column major, indices start at 1 */ - for (i = b->num_dims - 1; i >= 0; i--) { - if ((uintnat) (index[i] - 1) >= (uintnat) b->dim[i]) - caml_array_bound_error(); - offset = offset * b->dim[i] + (index[i] - 1); - } - } - return offset; -} - -/* Helper function to allocate a record of two double floats */ - -static value copy_two_doubles(double d0, double d1) -{ - value res = caml_alloc_small(2 * Double_wosize, Double_array_tag); - Store_double_field(res, 0, d0); - Store_double_field(res, 1, d1); - return res; -} - -/* Generic code to read from a big array */ - -value caml_ba_get_N(value vb, value * vind, int nind) -{ - struct caml_ba_array * b = Caml_ba_array_val(vb); - intnat index[CAML_BA_MAX_NUM_DIMS]; - int i; - intnat offset; - - /* Check number of indices = number of dimensions of array - (maybe not necessary if ML typing guarantees this) */ - if (nind != b->num_dims) - caml_invalid_argument("Bigarray.get: wrong number of indices"); - /* Compute offset and check bounds */ - for (i = 0; i < b->num_dims; i++) index[i] = Long_val(vind[i]); - offset = caml_ba_offset(b, index); - /* Perform read */ - switch ((b->flags) & CAML_BA_KIND_MASK) { - default: - CAMLassert(0); - case CAML_BA_FLOAT32: - return caml_copy_double(((float *) b->data)[offset]); - case CAML_BA_FLOAT64: - return caml_copy_double(((double *) b->data)[offset]); - case CAML_BA_SINT8: - return Val_int(((int8 *) b->data)[offset]); - case CAML_BA_UINT8: - return Val_int(((uint8 *) b->data)[offset]); - case CAML_BA_SINT16: - return Val_int(((int16 *) b->data)[offset]); - case CAML_BA_UINT16: - return Val_int(((uint16 *) b->data)[offset]); - case CAML_BA_INT32: - return caml_copy_int32(((int32_t *) b->data)[offset]); - case CAML_BA_INT64: - return caml_copy_int64(((int64_t *) b->data)[offset]); - case CAML_BA_NATIVE_INT: - return caml_copy_nativeint(((intnat *) b->data)[offset]); - case CAML_BA_CAML_INT: - return Val_long(((intnat *) b->data)[offset]); - case CAML_BA_COMPLEX32: - { float * p = ((float *) b->data) + offset * 2; - return copy_two_doubles(p[0], p[1]); } - case CAML_BA_COMPLEX64: - { double * p = ((double *) b->data) + offset * 2; - return copy_two_doubles(p[0], p[1]); } - case CAML_BA_CHAR: - return Val_int(((unsigned char *) b->data)[offset]); - } -} - -CAMLprim value caml_ba_get_1(value vb, value vind1) -{ - return caml_ba_get_N(vb, &vind1, 1); -} - -CAMLprim value caml_ba_get_2(value vb, value vind1, value vind2) -{ - value vind[2]; - vind[0] = vind1; vind[1] = vind2; - return caml_ba_get_N(vb, vind, 2); -} - -CAMLprim value caml_ba_get_3(value vb, value vind1, value vind2, value vind3) -{ - value vind[3]; - vind[0] = vind1; vind[1] = vind2; vind[2] = vind3; - return caml_ba_get_N(vb, vind, 3); -} - -CAMLprim value caml_ba_get_generic(value vb, value vind) -{ - return caml_ba_get_N(vb, &Field(vind, 0), Wosize_val(vind)); -} - - -CAMLprim value caml_ba_uint8_get16(value vb, value vind) -{ - intnat res; - unsigned char b1, b2; - intnat idx = Long_val(vind); - struct caml_ba_array * b = Caml_ba_array_val(vb); - if (idx < 0 || idx >= b->dim[0] - 1) caml_array_bound_error(); - b1 = ((unsigned char*) b->data)[idx]; - b2 = ((unsigned char*) b->data)[idx+1]; -#ifdef ARCH_BIG_ENDIAN - res = b1 << 8 | b2; -#else - res = b2 << 8 | b1; -#endif - return Val_int(res); -} - -CAMLprim value caml_ba_uint8_get32(value vb, value vind) -{ - intnat res; - unsigned char b1, b2, b3, b4; - intnat idx = Long_val(vind); - struct caml_ba_array * b = Caml_ba_array_val(vb); - if (idx < 0 || idx >= b->dim[0] - 3) caml_array_bound_error(); - b1 = ((unsigned char*) b->data)[idx]; - b2 = ((unsigned char*) b->data)[idx+1]; - b3 = ((unsigned char*) b->data)[idx+2]; - b4 = ((unsigned char*) b->data)[idx+3]; -#ifdef ARCH_BIG_ENDIAN - res = b1 << 24 | b2 << 16 | b3 << 8 | b4; -#else - res = b4 << 24 | b3 << 16 | b2 << 8 | b1; -#endif - return caml_copy_int32(res); -} - -CAMLprim value caml_ba_uint8_get64(value vb, value vind) -{ - uint64_t res; - unsigned char b1, b2, b3, b4, b5, b6, b7, b8; - intnat idx = Long_val(vind); - struct caml_ba_array * b = Caml_ba_array_val(vb); - if (idx < 0 || idx >= b->dim[0] - 7) caml_array_bound_error(); - b1 = ((unsigned char*) b->data)[idx]; - b2 = ((unsigned char*) b->data)[idx+1]; - b3 = ((unsigned char*) b->data)[idx+2]; - b4 = ((unsigned char*) b->data)[idx+3]; - b5 = ((unsigned char*) b->data)[idx+4]; - b6 = ((unsigned char*) b->data)[idx+5]; - b7 = ((unsigned char*) b->data)[idx+6]; - b8 = ((unsigned char*) b->data)[idx+7]; -#ifdef ARCH_BIG_ENDIAN - res = (uint64_t) b1 << 56 | (uint64_t) b2 << 48 - | (uint64_t) b3 << 40 | (uint64_t) b4 << 32 - | (uint64_t) b5 << 24 | (uint64_t) b6 << 16 - | (uint64_t) b7 << 8 | (uint64_t) b8; -#else - res = (uint64_t) b8 << 56 | (uint64_t) b7 << 48 - | (uint64_t) b6 << 40 | (uint64_t) b5 << 32 - | (uint64_t) b4 << 24 | (uint64_t) b3 << 16 - | (uint64_t) b2 << 8 | (uint64_t) b1; -#endif - return caml_copy_int64(res); -} - -/* Generic write to a big array */ - -static value caml_ba_set_aux(value vb, value * vind, intnat nind, value newval) -{ - struct caml_ba_array * b = Caml_ba_array_val(vb); - intnat index[CAML_BA_MAX_NUM_DIMS]; - int i; - intnat offset; - - /* Check number of indices = number of dimensions of array - (maybe not necessary if ML typing guarantees this) */ - if (nind != b->num_dims) - caml_invalid_argument("Bigarray.set: wrong number of indices"); - /* Compute offset and check bounds */ - for (i = 0; i < b->num_dims; i++) index[i] = Long_val(vind[i]); - offset = caml_ba_offset(b, index); - /* Perform write */ - switch (b->flags & CAML_BA_KIND_MASK) { - default: - CAMLassert(0); - case CAML_BA_FLOAT32: - ((float *) b->data)[offset] = Double_val(newval); break; - case CAML_BA_FLOAT64: - ((double *) b->data)[offset] = Double_val(newval); break; - case CAML_BA_CHAR: - case CAML_BA_SINT8: - case CAML_BA_UINT8: - ((int8 *) b->data)[offset] = Int_val(newval); break; - case CAML_BA_SINT16: - case CAML_BA_UINT16: - ((int16 *) b->data)[offset] = Int_val(newval); break; - case CAML_BA_INT32: - ((int32_t *) b->data)[offset] = Int32_val(newval); break; - case CAML_BA_INT64: - ((int64_t *) b->data)[offset] = Int64_val(newval); break; - case CAML_BA_NATIVE_INT: - ((intnat *) b->data)[offset] = Nativeint_val(newval); break; - case CAML_BA_CAML_INT: - ((intnat *) b->data)[offset] = Long_val(newval); break; - case CAML_BA_COMPLEX32: - { float * p = ((float *) b->data) + offset * 2; - p[0] = Double_field(newval, 0); - p[1] = Double_field(newval, 1); - break; } - case CAML_BA_COMPLEX64: - { double * p = ((double *) b->data) + offset * 2; - p[0] = Double_field(newval, 0); - p[1] = Double_field(newval, 1); - break; } - } - return Val_unit; -} - -CAMLprim value caml_ba_set_1(value vb, value vind1, value newval) -{ - return caml_ba_set_aux(vb, &vind1, 1, newval); -} - -CAMLprim value caml_ba_set_2(value vb, value vind1, value vind2, value newval) -{ - value vind[2]; - vind[0] = vind1; vind[1] = vind2; - return caml_ba_set_aux(vb, vind, 2, newval); -} - -CAMLprim value caml_ba_set_3(value vb, value vind1, value vind2, value vind3, - value newval) -{ - value vind[3]; - vind[0] = vind1; vind[1] = vind2; vind[2] = vind3; - return caml_ba_set_aux(vb, vind, 3, newval); -} - -value caml_ba_set_N(value vb, value * vind, int nargs) -{ - return caml_ba_set_aux(vb, vind, nargs - 1, vind[nargs - 1]); -} - -CAMLprim value caml_ba_set_generic(value vb, value vind, value newval) -{ - return caml_ba_set_aux(vb, &Field(vind, 0), Wosize_val(vind), newval); -} - -CAMLprim value caml_ba_uint8_set16(value vb, value vind, value newval) -{ - unsigned char b1, b2; - intnat val; - intnat idx = Long_val(vind); - struct caml_ba_array * b = Caml_ba_array_val(vb); - if (idx < 0 || idx >= b->dim[0] - 1) caml_array_bound_error(); - val = Long_val(newval); -#ifdef ARCH_BIG_ENDIAN - b1 = 0xFF & val >> 8; - b2 = 0xFF & val; -#else - b2 = 0xFF & val >> 8; - b1 = 0xFF & val; -#endif - ((unsigned char*) b->data)[idx] = b1; - ((unsigned char*) b->data)[idx+1] = b2; - return Val_unit; -} - -CAMLprim value caml_ba_uint8_set32(value vb, value vind, value newval) -{ - unsigned char b1, b2, b3, b4; - intnat idx = Long_val(vind); - intnat val; - struct caml_ba_array * b = Caml_ba_array_val(vb); - if (idx < 0 || idx >= b->dim[0] - 3) caml_array_bound_error(); - val = Int32_val(newval); -#ifdef ARCH_BIG_ENDIAN - b1 = 0xFF & val >> 24; - b2 = 0xFF & val >> 16; - b3 = 0xFF & val >> 8; - b4 = 0xFF & val; -#else - b4 = 0xFF & val >> 24; - b3 = 0xFF & val >> 16; - b2 = 0xFF & val >> 8; - b1 = 0xFF & val; -#endif - ((unsigned char*) b->data)[idx] = b1; - ((unsigned char*) b->data)[idx+1] = b2; - ((unsigned char*) b->data)[idx+2] = b3; - ((unsigned char*) b->data)[idx+3] = b4; - return Val_unit; -} - -CAMLprim value caml_ba_uint8_set64(value vb, value vind, value newval) -{ - unsigned char b1, b2, b3, b4, b5, b6, b7, b8; - intnat idx = Long_val(vind); - int64_t val; - struct caml_ba_array * b = Caml_ba_array_val(vb); - if (idx < 0 || idx >= b->dim[0] - 7) caml_array_bound_error(); - val = Int64_val(newval); -#ifdef ARCH_BIG_ENDIAN - b1 = 0xFF & val >> 56; - b2 = 0xFF & val >> 48; - b3 = 0xFF & val >> 40; - b4 = 0xFF & val >> 32; - b5 = 0xFF & val >> 24; - b6 = 0xFF & val >> 16; - b7 = 0xFF & val >> 8; - b8 = 0xFF & val; -#else - b8 = 0xFF & val >> 56; - b7 = 0xFF & val >> 48; - b6 = 0xFF & val >> 40; - b5 = 0xFF & val >> 32; - b4 = 0xFF & val >> 24; - b3 = 0xFF & val >> 16; - b2 = 0xFF & val >> 8; - b1 = 0xFF & val; -#endif - ((unsigned char*) b->data)[idx] = b1; - ((unsigned char*) b->data)[idx+1] = b2; - ((unsigned char*) b->data)[idx+2] = b3; - ((unsigned char*) b->data)[idx+3] = b4; - ((unsigned char*) b->data)[idx+4] = b5; - ((unsigned char*) b->data)[idx+5] = b6; - ((unsigned char*) b->data)[idx+6] = b7; - ((unsigned char*) b->data)[idx+7] = b8; - return Val_unit; -} - -/* Return the number of dimensions of a big array */ - -CAMLprim value caml_ba_num_dims(value vb) -{ - struct caml_ba_array * b = Caml_ba_array_val(vb); - return Val_long(b->num_dims); -} - -/* Return the n-th dimension of a big array */ - -CAMLprim value caml_ba_dim(value vb, value vn) -{ - struct caml_ba_array * b = Caml_ba_array_val(vb); - intnat n = Long_val(vn); - if (n < 0 || n >= b->num_dims) caml_invalid_argument("Bigarray.dim"); - return Val_long(b->dim[n]); -} - -CAMLprim value caml_ba_dim_1(value vb) -{ - return caml_ba_dim(vb, Val_int(0)); -} - -CAMLprim value caml_ba_dim_2(value vb) -{ - return caml_ba_dim(vb, Val_int(1)); -} - -CAMLprim value caml_ba_dim_3(value vb) -{ - return caml_ba_dim(vb, Val_int(2)); -} - -/* Return the kind of a big array */ - -CAMLprim value caml_ba_kind(value vb) -{ - return Val_caml_ba_kind(Caml_ba_array_val(vb)->flags & CAML_BA_KIND_MASK); -} - -/* Return the layout of a big array */ - -CAMLprim value caml_ba_layout(value vb) -{ - int layout = Caml_ba_array_val(vb)->flags & CAML_BA_LAYOUT_MASK; - return Val_caml_ba_layout(layout); -} - -/* Create / update proxy to indicate that b2 is a sub-array of b1 */ - -static void caml_ba_update_proxy(struct caml_ba_array * b1, - struct caml_ba_array * b2) -{ - struct caml_ba_proxy * proxy; - /* Nothing to do for un-managed arrays */ - if ((b1->flags & CAML_BA_MANAGED_MASK) == CAML_BA_EXTERNAL) return; - if (b1->proxy != NULL) { - /* If b1 is already a proxy for a larger array, increment refcount of - proxy */ - b2->proxy = b1->proxy; - ++ b1->proxy->refcount; - } else { - /* Otherwise, create proxy and attach it to both b1 and b2 */ - proxy = malloc(sizeof(struct caml_ba_proxy)); - if (proxy == NULL) caml_raise_out_of_memory(); - proxy->refcount = 2; /* original array + sub array */ - proxy->data = b1->data; - proxy->size = - b1->flags & CAML_BA_MAPPED_FILE ? caml_ba_byte_size(b1) : 0; - b1->proxy = proxy; - b2->proxy = proxy; - } -} - -/* Slicing */ - -CAMLprim value caml_ba_slice(value vb, value vind) -{ - CAMLparam2 (vb, vind); - #define b ((struct caml_ba_array *) Caml_ba_array_val(vb)) - CAMLlocal1 (res); - intnat index[CAML_BA_MAX_NUM_DIMS]; - int num_inds, i; - intnat offset; - intnat * sub_dims; - char * sub_data; - - /* Check number of indices <= number of dimensions of array */ - num_inds = Wosize_val(vind); - if (num_inds > b->num_dims) - caml_invalid_argument("Bigarray.slice: too many indices"); - /* Compute offset and check bounds */ - if ((b->flags & CAML_BA_LAYOUT_MASK) == CAML_BA_C_LAYOUT) { - /* We slice from the left */ - for (i = 0; i < num_inds; i++) index[i] = Long_val(Field(vind, i)); - for (/*nothing*/; i < b->num_dims; i++) index[i] = 0; - offset = caml_ba_offset(b, index); - sub_dims = b->dim + num_inds; - } else { - /* We slice from the right */ - for (i = 0; i < num_inds; i++) - index[b->num_dims - num_inds + i] = Long_val(Field(vind, i)); - for (i = 0; i < b->num_dims - num_inds; i++) index[i] = 1; - offset = caml_ba_offset(b, index); - sub_dims = b->dim; - } - sub_data = - (char *) b->data + - offset * caml_ba_element_size[b->flags & CAML_BA_KIND_MASK]; - /* Allocate an OCaml bigarray to hold the result */ - res = caml_ba_alloc(b->flags, b->num_dims - num_inds, sub_data, sub_dims); - /* Create or update proxy in case of managed bigarray */ - caml_ba_update_proxy(b, Caml_ba_array_val(res)); - /* Return result */ - CAMLreturn (res); - - #undef b -} - -/* Changing the layout of an array (memory is shared) */ - -CAMLprim value caml_ba_change_layout(value vb, value vlayout) -{ - CAMLparam2 (vb, vlayout); - CAMLlocal1 (res); - #define b ((struct caml_ba_array *) Caml_ba_array_val(vb)) - /* if the layout is different, change the flags and reverse the dimensions */ - if (Caml_ba_layout_val(vlayout) != (b->flags & CAML_BA_LAYOUT_MASK)) { - /* change the flags to reflect the new layout */ - int flags = (b->flags & (CAML_BA_KIND_MASK | CAML_BA_MANAGED_MASK)) - | Caml_ba_layout_val(vlayout); - /* reverse the dimensions */ - intnat new_dim[CAML_BA_MAX_NUM_DIMS]; - unsigned int i; - for(i = 0; i < b->num_dims; i++) new_dim[i] = b->dim[b->num_dims - i - 1]; - res = caml_ba_alloc(flags, b->num_dims, b->data, new_dim); - caml_ba_update_proxy(b, Caml_ba_array_val(res)); - CAMLreturn(res); - } else { - /* otherwise, do nothing */ - CAMLreturn(vb); - } - #undef b -} - - -/* Extracting a sub-array of same number of dimensions */ - -CAMLprim value caml_ba_sub(value vb, value vofs, value vlen) -{ - CAMLparam3 (vb, vofs, vlen); - CAMLlocal1 (res); - #define b ((struct caml_ba_array *) Caml_ba_array_val(vb)) - intnat ofs = Long_val(vofs); - intnat len = Long_val(vlen); - int i, changed_dim; - intnat mul; - char * sub_data; - - /* Compute offset and check bounds */ - if ((b->flags & CAML_BA_LAYOUT_MASK) == CAML_BA_C_LAYOUT) { - /* We reduce the first dimension */ - mul = 1; - for (i = 1; i < b->num_dims; i++) mul *= b->dim[i]; - changed_dim = 0; - } else { - /* We reduce the last dimension */ - mul = 1; - for (i = 0; i < b->num_dims - 1; i++) mul *= b->dim[i]; - changed_dim = b->num_dims - 1; - ofs--; /* Fortran arrays start at 1 */ - } - if (ofs < 0 || len < 0 || ofs + len > b->dim[changed_dim]) - caml_invalid_argument("Bigarray.sub: bad sub-array"); - sub_data = - (char *) b->data + - ofs * mul * caml_ba_element_size[b->flags & CAML_BA_KIND_MASK]; - /* Allocate an OCaml bigarray to hold the result */ - res = caml_ba_alloc(b->flags, b->num_dims, sub_data, b->dim); - /* Doctor the changed dimension */ - Caml_ba_array_val(res)->dim[changed_dim] = len; - /* Create or update proxy in case of managed bigarray */ - caml_ba_update_proxy(b, Caml_ba_array_val(res)); - /* Return result */ - CAMLreturn (res); - - #undef b -} - -/* Copying a big array into another one */ - -#define LEAVE_RUNTIME_OP_CUTOFF 4096 -#define is_mmapped(ba) ((ba)->flags & CAML_BA_MAPPED_FILE) - -CAMLprim value caml_ba_blit(value vsrc, value vdst) -{ - CAMLparam2(vsrc, vdst); - struct caml_ba_array * src = Caml_ba_array_val(vsrc); - struct caml_ba_array * dst = Caml_ba_array_val(vdst); - void *src_data = src->data; - void *dst_data = dst->data; - int i; - intnat num_bytes; - int leave_runtime; - - /* Check same numbers of dimensions and same dimensions */ - if (src->num_dims != dst->num_dims) goto blit_error; - for (i = 0; i < src->num_dims; i++) - if (src->dim[i] != dst->dim[i]) goto blit_error; - /* Compute number of bytes in array data */ - num_bytes = - caml_ba_num_elts(src) - * caml_ba_element_size[src->flags & CAML_BA_KIND_MASK]; - leave_runtime = - ( - (num_bytes >= LEAVE_RUNTIME_OP_CUTOFF*sizeof(long)) - || is_mmapped(src) - || is_mmapped(dst) - ); - /* Do the copying */ - if (leave_runtime) caml_enter_blocking_section(); - memmove (dst_data, src_data, num_bytes); - if (leave_runtime) caml_leave_blocking_section(); - CAMLreturn (Val_unit); - blit_error: - caml_invalid_argument("Bigarray.blit: dimension mismatch"); - CAMLreturn (Val_unit); /* not reached */ -} - -/* Filling a big array with a given value */ - -#define FILL_GEN_LOOP(n_ops, loop) do{ \ - int leave_runtime = ((n_ops >= LEAVE_RUNTIME_OP_CUTOFF) || is_mmapped(b)); \ - if (leave_runtime) caml_enter_blocking_section(); \ - loop; \ - if (leave_runtime) caml_leave_blocking_section(); \ -}while(0) - -#define FILL_SCALAR_LOOP \ - FILL_GEN_LOOP(num_elts, \ - for (p = data; num_elts > 0; p++, num_elts--) *p = init) - -#define FILL_COMPLEX_LOOP \ - FILL_GEN_LOOP(num_elts + num_elts, \ - for (p = data; num_elts > 0; num_elts--) { *p++ = init0; *p++ = init1; }) - -CAMLprim value caml_ba_fill(value vb, value vinit) -{ - CAMLparam1(vb); - struct caml_ba_array * b = Caml_ba_array_val(vb); - void *data = b->data; - intnat num_elts = caml_ba_num_elts(b); - - switch (b->flags & CAML_BA_KIND_MASK) { - default: - CAMLassert(0); - case CAML_BA_FLOAT32: { - float init = Double_val(vinit); - float * p; - FILL_SCALAR_LOOP; - break; - } - case CAML_BA_FLOAT64: { - double init = Double_val(vinit); - double * p; - FILL_SCALAR_LOOP; - break; - } - case CAML_BA_CHAR: - case CAML_BA_SINT8: - case CAML_BA_UINT8: { - int init = Int_val(vinit); - unsigned char * p; - FILL_SCALAR_LOOP; - break; - } - case CAML_BA_SINT16: - case CAML_BA_UINT16: { - int init = Int_val(vinit); - int16 * p; - FILL_SCALAR_LOOP; - break; - } - case CAML_BA_INT32: { - int32_t init = Int32_val(vinit); - int32_t * p; - FILL_SCALAR_LOOP; - break; - } - case CAML_BA_INT64: { - int64_t init = Int64_val(vinit); - int64_t * p; - FILL_SCALAR_LOOP; - break; - } - case CAML_BA_NATIVE_INT: { - intnat init = Nativeint_val(vinit); - intnat * p; - FILL_SCALAR_LOOP; - break; - } - case CAML_BA_CAML_INT: { - intnat init = Long_val(vinit); - intnat * p; - FILL_SCALAR_LOOP; - break; - } - case CAML_BA_COMPLEX32: { - float init0 = Double_field(vinit, 0); - float init1 = Double_field(vinit, 1); - float * p; - FILL_COMPLEX_LOOP; - break; - } - case CAML_BA_COMPLEX64: { - double init0 = Double_field(vinit, 0); - double init1 = Double_field(vinit, 1); - double * p; - FILL_COMPLEX_LOOP; - break; - } - } - CAMLreturn (Val_unit); -} - -/* Reshape an array: change dimensions and number of dimensions, preserving - array contents */ - -CAMLprim value caml_ba_reshape(value vb, value vdim) -{ - CAMLparam2 (vb, vdim); - CAMLlocal1 (res); -#define b ((struct caml_ba_array *) Caml_ba_array_val(vb)) - intnat dim[CAML_BA_MAX_NUM_DIMS]; - mlsize_t num_dims; - uintnat num_elts; - int i; - - num_dims = Wosize_val(vdim); - /* here num_dims is unsigned (mlsize_t) so no need to check (num_dims >= 0) */ - if (num_dims > CAML_BA_MAX_NUM_DIMS) - caml_invalid_argument("Bigarray.reshape: bad number of dimensions"); - num_elts = 1; - for (i = 0; i < num_dims; i++) { - dim[i] = Long_val(Field(vdim, i)); - if (dim[i] < 0) - caml_invalid_argument("Bigarray.reshape: negative dimension"); - num_elts *= dim[i]; - } - /* Check that sizes agree */ - if (num_elts != caml_ba_num_elts(b)) - caml_invalid_argument("Bigarray.reshape: size mismatch"); - /* Create bigarray with same data and new dimensions */ - res = caml_ba_alloc(b->flags, num_dims, b->data, dim); - /* Create or update proxy in case of managed bigarray */ - caml_ba_update_proxy(b, Caml_ba_array_val(res)); - /* Return result */ - CAMLreturn (res); - -#undef b -} diff --git a/byterun/caml/backtrace.h b/byterun/caml/backtrace.h deleted file mode 100644 index fc0baf2d..00000000 --- a/byterun/caml/backtrace.h +++ /dev/null @@ -1,136 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#ifndef CAML_BACKTRACE_H -#define CAML_BACKTRACE_H - -#ifdef CAML_INTERNALS - -#include "mlvalues.h" -#include "exec.h" - -/* Runtime support for backtrace generation. - * - * It has two kind of users: - * - high-level API to capture and decode backtraces; - * - low-level runtime routines, to introspect machine state and determine - * whether a backtrace should be generated when using "raise". - * - * Backtrace generation is split in multiple steps. - * The lowest-level one, done by [backtrace_prim.c] just fills the - * [caml_backtrace_buffer] variable each time a frame is unwinded. - * At that point, we don't know whether the backtrace will be useful or not so - * this code should be as fast as possible. - * - * If the backtrace happens to be useful, later passes will read - * [caml_backtrace_buffer] and turn it into a [raw_backtrace] and then a - * [backtrace]. - * This is done in [backtrace.c] and [stdlib/printexc.ml]. - * - * Content of buffers - * ------------------ - * - * [caml_backtrace_buffer] (really cheap) - * Backend and process image dependent, abstracted by C-type backtrace_slot. - * [raw_backtrace] (cheap) - * OCaml values of abstract type [Printexc.raw_backtrace_slot], - * still backend and process image dependent (unsafe to marshal). - * [backtrace] (more expensive) - * OCaml values of algebraic data-type [Printexc.backtrace_slot] - */ - -/* Non zero iff backtraces are recorded. - * One should use to change this variable [caml_record_backtrace]. - */ -CAMLextern int caml_backtrace_active; - -/* The [backtrace_slot] type represents values stored in the - * [caml_backtrace_buffer]. In bytecode, it is the same as a - * [code_t], in native code it as a [frame_descr *]. The difference - * doesn't matter for code outside [backtrace_prim.c], so it is just - * exposed as a [backtrace_slot]. - */ -typedef void * backtrace_slot; - -/* The [caml_backtrace_buffer] and [caml_backtrace_last_exn] - * variables are valid only if [caml_backtrace_active != 0]. - * - * They are part of the state specific to each thread, and threading libraries - * are responsible for copying them on context switch. - * See [otherlibs/systhreads/st_stubs.c] and [otherlibs/threads/scheduler.c]. - */ - -/* [caml_backtrace_buffer] is filled by runtime when unwinding stack. - * It is an array ranging from [0] to [caml_backtrace_pos - 1]. - * [caml_backtrace_pos] is always zero if [!caml_backtrace_active]. - * - * Its maximum size is determined by [BACKTRACE_BUFFER_SIZE] from - * [backtrace_prim.h], but this shouldn't affect users. - */ -CAMLextern backtrace_slot * caml_backtrace_buffer; -CAMLextern int caml_backtrace_pos; - -/* [caml_backtrace_last_exn] stores the last exception value that was raised, - * iff [caml_backtrace_active != 0]. - * It is tested for equality to determine whether a raise is a re-raise of the - * same exception. - * - * FIXME: this shouldn't matter anymore. Since OCaml 4.02, non-parameterized - * exceptions are constant, so physical equality is no longer appropriate. - * raise and re-raise are distinguished by: - * - passing reraise = 1 to [caml_stash_backtrace] (see below) in the bytecode - * interpreter; - * - directly resetting [caml_backtrace_pos] to 0 in native runtimes for raise. - */ -CAMLextern value caml_backtrace_last_exn; - -/* [caml_record_backtrace] toggle backtrace recording on and off. - * This function can be called at runtime by user-code, or during - * initialization if backtraces were requested. - * - * It might be called before GC initialization, so it shouldn't do OCaml - * allocation. - */ -CAMLprim value caml_record_backtrace(value vflag); - - -#ifndef NATIVE_CODE - -/* Path to the file containing debug information, if any, or NULL. */ -CAMLextern char_os * caml_cds_file; - -/* Primitive called _only_ by runtime to record unwinded frames to - * backtrace. A similar primitive exists for native code, but with a - * different prototype. */ -extern void caml_stash_backtrace(value exn, code_t pc, value * sp, int reraise); - -#endif - - -/* Default (C-level) printer for backtraces. It is called if an - * exception causes a termination of the program or of a thread. - * - * [Printexc] provide a higher-level printer mimicking its output but making - * use of registered exception printers, and is used when possible in place of - * this function after [Printexc] initialization. - */ -CAMLextern void caml_print_exception_backtrace(void); - -void caml_init_backtrace(void); -CAMLexport void caml_init_debug_info(void); - -#endif /* CAML_INTERNALS */ - -#endif /* CAML_BACKTRACE_H */ diff --git a/byterun/caml/backtrace_prim.h b/byterun/caml/backtrace_prim.h deleted file mode 100644 index 2484b294..00000000 --- a/byterun/caml/backtrace_prim.h +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#ifndef CAML_BACKTRACE_PRIM_H -#define CAML_BACKTRACE_PRIM_H - -#ifdef CAML_INTERNALS - -#include "backtrace.h" - -/* Backtrace generation is split in [backtrace.c] and [backtrace_prim.c]. - * - * [backtrace_prim.c] contains all backend-specific code, and has two different - * implementations in [byterun/backtrace_prim.c] and [asmrun/backtrace_prim.c]. - * - * [backtrace.c] has a unique implementation, and expose a uniform - * higher level API above [backtrace_prim.c]. - */ - -/* Extract location information for the given raw_backtrace_slot */ - -struct caml_loc_info { - int loc_valid; - int loc_is_raise; - char * loc_filename; - int loc_lnum; - int loc_startchr; - int loc_endchr; - int loc_is_inlined; -}; - -/* When compiling with -g, backtrace slots have debug info associated. - * When a call is inlined in native mode, debuginfos form a linked list. - */ -typedef void * debuginfo; - -/* Check availability of debug information before extracting a trace. - * Relevant for bytecode, always true for native code. */ -int caml_debug_info_available(void); - -/* Return debuginfo associated to a slot or NULL. */ -debuginfo caml_debuginfo_extract(backtrace_slot slot); - -/* In case of an inlined call return next debuginfo or NULL otherwise. */ -debuginfo caml_debuginfo_next(debuginfo dbg); - -/* Extract locations from backtrace_slot */ -void caml_debuginfo_location(debuginfo dbg, /*out*/ struct caml_loc_info * li); - -/* In order to prevent the GC from walking through the debug - information (which have no headers), we transform slots to 31/63 bits - ocaml integers by shifting them by 1 to the right. We do not lose - information as slots are aligned. - - In particular, we do not need to use [caml_modify] when setting - an array element with such a value. - */ -#define Val_backtrace_slot(bslot) (Val_long(((uintnat)(bslot))>>1)) -#define Backtrace_slot_val(vslot) ((backtrace_slot)(Long_val(vslot) << 1)) - -/* Allocate the caml_backtrace_buffer. Returns 0 on success, -1 otherwise */ -int caml_alloc_backtrace_buffer(void); - -#define BACKTRACE_BUFFER_SIZE 1024 - -/* Besides decoding backtrace info, [backtrace_prim] has two other - * responsibilities: - * - * It defines the [caml_stash_backtrace] function, which is called to quickly - * fill the backtrace buffer by walking the stack when an exception is raised. - * - * It also defines the [caml_get_current_callstack] OCaml primitive, which also - * walks the stack but directly turns it into a [raw_backtrace] and is called - * explicitly. - */ - -#endif /* CAML_INTERNALS */ - -#endif /* CAML_BACKTRACE_PRIM_H */ diff --git a/byterun/caml/compatibility.h b/byterun/caml/compatibility.h deleted file mode 100644 index 082943c6..00000000 --- a/byterun/caml/compatibility.h +++ /dev/null @@ -1,375 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Moscova, INRIA Rocquencourt */ -/* */ -/* Copyright 2003 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* definitions for compatibility with old identifiers */ - -#ifndef CAML_COMPATIBILITY_H -#define CAML_COMPATIBILITY_H - -/* internal global variables renamed between 4.02.1 and 4.03.0 */ -#define caml_stat_top_heap_size Bsize_wsize(caml_stat_top_heap_wsz) -#define caml_stat_heap_size Bsize_wsize(caml_stat_heap_wsz) - -#ifndef CAML_NAME_SPACE - -/* - #define --> CAMLextern (defined with CAMLexport or CAMLprim) - (rien) --> CAMLprim - g --> global C identifier - x --> special case - - SP* signals the special cases: - - when the identifier was not simply prefixed with [caml_] - - when the [caml_] version was already used for something else, and - was renamed out of the way (watch out for [caml_alloc] and - [caml_array_bound_error] in *.s) -*/ - -/* a faire: - - ui_* (reverifier que win32.c n'en depend pas) -*/ - - -/* **** alloc.c */ -#define alloc caml_alloc /*SP*/ -#define alloc_small caml_alloc_small -#define alloc_tuple caml_alloc_tuple -#define alloc_string caml_alloc_string -#define alloc_final caml_alloc_final -#define copy_string caml_copy_string -#define alloc_array caml_alloc_array -#define copy_string_array caml_copy_string_array -#define convert_flag_list caml_convert_flag_list - -/* **** array.c */ - -/* **** backtrace.c */ -#define backtrace_active caml_backtrace_active -#define backtrace_pos caml_backtrace_pos -#define backtrace_buffer caml_backtrace_buffer -#define backtrace_last_exn caml_backtrace_last_exn -#define print_exception_backtrace caml_print_exception_backtrace - -/* **** callback.c */ -#define callback_depth caml_callback_depth -#define callbackN_exn caml_callbackN_exn -#define callback_exn caml_callback_exn -#define callback2_exn caml_callback2_exn -#define callback3_exn caml_callback3_exn -#define callback caml_callback -#define callback2 caml_callback2 -#define callback3 caml_callback3 -#define callbackN caml_callbackN - -/* **** compact.c */ - -/* **** compare.c */ -#define compare_unordered caml_compare_unordered - -/* **** custom.c */ -#define alloc_custom caml_alloc_custom -#define register_custom_operations caml_register_custom_operations - -/* **** debugger.c */ - -/* **** dynlink.c */ - -/* **** extern.c */ -#define output_val caml_output_val -#define output_value_to_malloc caml_output_value_to_malloc -#define output_value_to_block caml_output_value_to_block -#define serialize_int_1 caml_serialize_int_1 -#define serialize_int_2 caml_serialize_int_2 -#define serialize_int_4 caml_serialize_int_4 -#define serialize_int_8 caml_serialize_int_8 -#define serialize_float_4 caml_serialize_float_4 -#define serialize_float_8 caml_serialize_float_8 -#define serialize_block_1 caml_serialize_block_1 -#define serialize_block_2 caml_serialize_block_2 -#define serialize_block_4 caml_serialize_block_4 -#define serialize_block_8 caml_serialize_block_8 -#define serialize_block_float_8 caml_serialize_block_float_8 - -/* **** fail.c */ -#define external_raise caml_external_raise -#define mlraise caml_raise /*SP*/ -#define raise_constant caml_raise_constant -#define raise_with_arg caml_raise_with_arg -#define raise_with_string caml_raise_with_string -#define failwith caml_failwith -#define invalid_argument caml_invalid_argument -#define array_bound_error caml_array_bound_error /*SP*/ -#define raise_out_of_memory caml_raise_out_of_memory -#define raise_stack_overflow caml_raise_stack_overflow -#define raise_sys_error caml_raise_sys_error -#define raise_end_of_file caml_raise_end_of_file -#define raise_zero_divide caml_raise_zero_divide -#define raise_not_found caml_raise_not_found -#define raise_sys_blocked_io caml_raise_sys_blocked_io -/* **** asmrun/fail.c */ -/* **** asmrun/.s */ - -/* **** finalise.c */ - -/* **** fix_code.c */ - -/* **** floats.c */ -/*#define Double_val caml_Double_val done in mlvalues.h as needed */ -/*#define Store_double_val caml_Store_double_val done in mlvalues.h as needed */ -#define copy_double caml_copy_double - -/* **** freelist.c */ - -/* **** gc_ctrl.c */ - -/* **** globroots.c */ -#define register_global_root caml_register_global_root -#define remove_global_root caml_remove_global_root - -/* **** hash.c */ -#define hash_variant caml_hash_variant - -/* **** instrtrace.c */ - -/* **** intern.c */ -#define input_val caml_input_val -#define input_val_from_string caml_input_val_from_string -#define input_value_from_malloc caml_input_value_from_malloc -#define input_value_from_block caml_input_value_from_block -#define deserialize_uint_1 caml_deserialize_uint_1 -#define deserialize_sint_1 caml_deserialize_sint_1 -#define deserialize_uint_2 caml_deserialize_uint_2 -#define deserialize_sint_2 caml_deserialize_sint_2 -#define deserialize_uint_4 caml_deserialize_uint_4 -#define deserialize_sint_4 caml_deserialize_sint_4 -#define deserialize_uint_8 caml_deserialize_uint_8 -#define deserialize_sint_8 caml_deserialize_sint_8 -#define deserialize_float_4 caml_deserialize_float_4 -#define deserialize_float_8 caml_deserialize_float_8 -#define deserialize_block_1 caml_deserialize_block_1 -#define deserialize_block_2 caml_deserialize_block_2 -#define deserialize_block_4 caml_deserialize_block_4 -#define deserialize_block_8 caml_deserialize_block_8 -#define deserialize_block_float_8 caml_deserialize_block_float_8 -#define deserialize_error caml_deserialize_error - -/* **** interp.c */ - -/* **** ints.c */ -#define int32_ops caml_int32_ops -#define copy_int32 caml_copy_int32 -/*#define Int64_val caml_Int64_val *** done in mlvalues.h as needed */ -#define int64_ops caml_int64_ops -#define copy_int64 caml_copy_int64 -#define nativeint_ops caml_nativeint_ops -#define copy_nativeint caml_copy_nativeint - -/* **** io.c */ -#define channel_mutex_free caml_channel_mutex_free -#define channel_mutex_lock caml_channel_mutex_lock -#define channel_mutex_unlock caml_channel_mutex_unlock -#define channel_mutex_unlock_exn caml_channel_mutex_unlock_exn -#define all_opened_channels caml_all_opened_channels -#define open_descriptor_in caml_open_descriptor_in /*SP*/ -#define open_descriptor_out caml_open_descriptor_out /*SP*/ -#define close_channel caml_close_channel /*SP*/ -#define channel_size caml_channel_size /*SP*/ -#define channel_binary_mode caml_channel_binary_mode -#define flush_partial caml_flush_partial /*SP*/ -#define flush caml_flush /*SP*/ -#define putword caml_putword -#define putblock caml_putblock -#define really_putblock caml_really_putblock -#define seek_out caml_seek_out /*SP*/ -#define pos_out caml_pos_out /*SP*/ -#define do_read caml_do_read -#define refill caml_refill -#define getword caml_getword -#define getblock caml_getblock -#define really_getblock caml_really_getblock -#define seek_in caml_seek_in /*SP*/ -#define pos_in caml_pos_in /*SP*/ -#define input_scan_line caml_input_scan_line /*SP*/ -#define finalize_channel caml_finalize_channel -#define alloc_channel caml_alloc_channel -/*#define Val_file_offset caml_Val_file_offset *** done in io.h as needed */ -/*#define File_offset_val caml_File_offset_val *** done in io.h as needed */ - -/* **** lexing.c */ - -/* **** main.c */ -/* *** no change */ - -/* **** major_gc.c */ -#define heap_start caml_heap_start -#define page_table caml_page_table - -/* **** md5.c */ -#define md5_string caml_md5_string -#define md5_chan caml_md5_chan -#define MD5Init caml_MD5Init -#define MD5Update caml_MD5Update -#define MD5Final caml_MD5Final -#define MD5Transform caml_MD5Transform - -/* **** memory.c */ -#define alloc_shr caml_alloc_shr -#define initialize caml_initialize -#define modify caml_modify -#define stat_alloc caml_stat_alloc -#define stat_free caml_stat_free -#define stat_resize caml_stat_resize - -/* **** meta.c */ - -/* **** minor_gc.c */ -#define young_start caml_young_start -#define young_end caml_young_end -#define young_ptr caml_young_ptr -#define young_limit caml_young_limit -#define ref_table caml_ref_table -#define minor_collection caml_minor_collection -#define check_urgent_gc caml_check_urgent_gc - -/* **** misc.c */ - -/* **** obj.c */ - -/* **** parsing.c */ - -/* **** prims.c */ - -/* **** printexc.c */ -#define format_caml_exception caml_format_exception /*SP*/ - -/* **** roots.c */ -#define local_roots caml_local_roots -#define scan_roots_hook caml_scan_roots_hook -#define do_local_roots caml_do_local_roots - -/* **** signals.c */ -#define pending_signals caml_pending_signals -#define something_to_do caml_something_to_do -#define enter_blocking_section_hook caml_enter_blocking_section_hook -#define leave_blocking_section_hook caml_leave_blocking_section_hook -#define try_leave_blocking_section_hook caml_try_leave_blocking_section_hook -#define async_action_hook caml_async_action_hook -#define enter_blocking_section caml_enter_blocking_section -#define leave_blocking_section caml_leave_blocking_section -#define convert_signal_number caml_convert_signal_number -/* **** asmrun/signals.c */ -#define garbage_collection caml_garbage_collection - -/* **** stacks.c */ -#define stack_low caml_stack_low -#define stack_high caml_stack_high -#define stack_threshold caml_stack_threshold -#define extern_sp caml_extern_sp -#define trapsp caml_trapsp -#define trap_barrier caml_trap_barrier - -/* **** startup.c */ -#define atom_table caml_atom_table -/* **** asmrun/startup.c */ -#define static_data_start caml_static_data_start -#define static_data_end caml_static_data_end - -/* **** str.c */ -#define string_length caml_string_length - -/* **** sys.c */ -#define sys_error caml_sys_error -#define sys_exit caml_sys_exit - -/* **** terminfo.c */ - -/* **** unix.c & win32.c */ -#define search_exe_in_path caml_search_exe_in_path - -/* **** weak.c */ - -/* **** asmcomp/asmlink.ml */ - -/* **** asmcomp/cmmgen.ml */ - -/* **** asmcomp/asmlink.ml, asmcomp/cmmgen.ml, asmcomp/compilenv.ml */ - -/* ************************************************************* */ - -/* **** otherlibs/bigarray */ -#define int8 caml_ba_int8 -#define uint8 caml_ba_uint8 -#define int16 caml_ba_int16 -#define uint16 caml_ba_uint16 -#define MAX_NUM_DIMS CAML_BA_MAX_NUM_DIMS -#define caml_bigarray_kind caml_ba_kind -#define BIGARRAY_FLOAT32 CAML_BA_FLOAT32 -#define BIGARRAY_FLOAT64 CAML_BA_FLOAT64 -#define BIGARRAY_SINT8 CAML_BA_SINT8 -#define BIGARRAY_UINT8 CAML_BA_UINT8 -#define BIGARRAY_SINT16 CAML_BA_SINT16 -#define BIGARRAY_UINT16 CAML_BA_UINT16 -#define BIGARRAY_INT32 CAML_BA_INT32 -#define BIGARRAY_INT64 CAML_BA_INT64 -#define BIGARRAY_CAML_INT CAML_BA_CAML_INT -#define BIGARRAY_NATIVE_INT CAML_BA_NATIVE_INT -#define BIGARRAY_COMPLEX32 CAML_BA_COMPLEX32 -#define BIGARRAY_COMPLEX64 CAML_BA_COMPLEX64 -#define BIGARRAY_KIND_MASK CAML_BA_KIND_MASK -#define caml_bigarray_layout caml_ba_layout -#define BIGARRAY_C_LAYOUT CAML_BA_C_LAYOUT -#define BIGARRAY_FORTRAN_LAYOUT CAML_BA_FORTRAN_LAYOUT -#define BIGARRAY_LAYOUT_MASK CAML_BA_LAYOUT_MASK -#define caml_bigarray_managed caml_ba_managed -#define BIGARRAY_EXTERNAL CAML_BA_EXTERNAL -#define BIGARRAY_MANAGED CAML_BA_MANAGED -#define BIGARRAY_MAPPED_FILE CAML_BA_MAPPED_FILE -#define BIGARRAY_MANAGED_MASK CAML_BA_MANAGED_MASK -#define caml_bigarray_proxy caml_ba_proxy -#define caml_bigarray caml_ba_array -#define Bigarray_val Caml_ba_array_val -#define Data_bigarray_val Caml_ba_data_val -#define alloc_bigarray caml_ba_alloc -#define alloc_bigarray_dims caml_ba_alloc_dims -#define bigarray_map_file caml_ba_map_file -#define bigarray_unmap_file caml_ba_unmap_file -#define bigarray_element_size caml_ba_element_size -#define bigarray_byte_size caml_ba_byte_size -#define bigarray_deserialize caml_ba_deserialize -#define MAX_BIGARRAY_MEMORY CAML_BA_MAX_MEMORY -#define bigarray_create caml_ba_create -#define bigarray_get_N caml_ba_get_N -#define bigarray_get_1 caml_ba_get_1 -#define bigarray_get_2 caml_ba_get_2 -#define bigarray_get_3 caml_ba_get_3 -#define bigarray_get_generic caml_ba_get_generic -#define bigarray_set_1 caml_ba_set_1 -#define bigarray_set_2 caml_ba_set_2 -#define bigarray_set_3 caml_ba_set_3 -#define bigarray_set_N caml_ba_set_N -#define bigarray_set_generic caml_ba_set_generic -#define bigarray_num_dims caml_ba_num_dims -#define bigarray_dim caml_ba_dim -#define bigarray_kind caml_ba_kind -#define bigarray_layout caml_ba_layout -#define bigarray_slice caml_ba_slice -#define bigarray_sub caml_ba_sub -#define bigarray_blit caml_ba_blit -#define bigarray_fill caml_ba_fill -#define bigarray_reshape caml_ba_reshape -#define bigarray_init caml_ba_init - -#endif /* CAML_NAME_SPACE */ -#endif /* CAML_COMPATIBILITY_H */ diff --git a/byterun/caml/config.h b/byterun/caml/config.h deleted file mode 100644 index 0dba12ad..00000000 --- a/byterun/caml/config.h +++ /dev/null @@ -1,208 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#ifndef CAML_CONFIG_H -#define CAML_CONFIG_H - -/* */ -/* */ -/* */ -#include "m.h" -#include "s.h" -#ifdef BOOTSTRAPPING_FLEXLINK -#undef SUPPORT_DYNAMIC_LINKING -#endif - -#ifndef CAML_NAME_SPACE -#include "compatibility.h" -#endif - -#include - -#ifdef HAS_STDINT_H -#include -#endif - -#ifndef ARCH_SIZET_PRINTF_FORMAT -#define ARCH_SIZET_PRINTF_FORMAT "z" -#endif - -/* Types for 32-bit integers, 64-bit integers, and - native integers (as wide as a pointer type) */ - -#ifndef ARCH_INT32_TYPE -#if SIZEOF_INT == 4 -#define ARCH_INT32_TYPE int -#define ARCH_UINT32_TYPE unsigned int -#define ARCH_INT32_PRINTF_FORMAT "" -#elif SIZEOF_LONG == 4 -#define ARCH_INT32_TYPE long -#define ARCH_UINT32_TYPE unsigned long -#define ARCH_INT32_PRINTF_FORMAT "l" -#elif SIZEOF_SHORT == 4 -#define ARCH_INT32_TYPE short -#define ARCH_UINT32_TYPE unsigned short -#define ARCH_INT32_PRINTF_FORMAT "" -#else -#error "No 32-bit integer type available" -#endif -#endif - -#ifndef ARCH_INT64_TYPE -#if SIZEOF_LONG == 8 -#define ARCH_INT64_TYPE long -#define ARCH_UINT64_TYPE unsigned long -#define ARCH_INT64_PRINTF_FORMAT "l" -#elif SIZEOF_LONGLONG == 8 -#define ARCH_INT64_TYPE long long -#define ARCH_UINT64_TYPE unsigned long long -#define ARCH_INT64_PRINTF_FORMAT "ll" -#else -#error "No 64-bit integer type available" -#endif -#endif - -#ifndef HAS_STDINT_H -/* Not a C99 compiler, typically MSVC. Define the C99 types we use. */ -typedef ARCH_INT32_TYPE int32_t; -typedef ARCH_UINT32_TYPE uint32_t; -typedef ARCH_INT64_TYPE int64_t; -typedef ARCH_UINT64_TYPE uint64_t; -#if SIZEOF_SHORT == 2 -typedef short int16_t; -typedef unsigned short uint16_t; -#else -#error "No 16-bit integer type available" -#endif -#endif - -#if SIZEOF_PTR == SIZEOF_LONG -/* Standard models: ILP32 or I32LP64 */ -typedef long intnat; -typedef unsigned long uintnat; -#define ARCH_INTNAT_PRINTF_FORMAT "l" -#elif SIZEOF_PTR == SIZEOF_INT -/* Hypothetical IP32L64 model */ -typedef int intnat; -typedef unsigned int uintnat; -#define ARCH_INTNAT_PRINTF_FORMAT "" -#elif SIZEOF_PTR == 8 -/* Win64 model: IL32P64 */ -typedef int64_t intnat; -typedef uint64_t uintnat; -#define ARCH_INTNAT_PRINTF_FORMAT ARCH_INT64_PRINTF_FORMAT -#else -#error "No integer type available to represent pointers" -#endif - -/* Endianness of floats */ - -/* ARCH_FLOAT_ENDIANNESS encodes the byte order of doubles as follows: - the value [0xabcdefgh] means that the least significant byte of the - float is at byte offset [a], the next lsb at [b], ..., and the - most significant byte at [h]. */ - -#if defined(__arm__) && !defined(__ARM_EABI__) -#define ARCH_FLOAT_ENDIANNESS 0x45670123 -#elif defined(ARCH_BIG_ENDIAN) -#define ARCH_FLOAT_ENDIANNESS 0x76543210 -#else -#define ARCH_FLOAT_ENDIANNESS 0x01234567 -#endif - - -/* We use threaded code interpretation if the compiler provides labels - as first-class values (GCC 2.x). */ - -#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(DEBUG) \ - && !defined (SHRINKED_GNUC) && !defined(CAML_JIT) -#define THREADED_CODE -#endif - - -/* Memory model parameters */ - -/* The size of a page for memory management (in bytes) is [1 << Page_log]. - [Page_size] must be a multiple of [sizeof (value)]. - [Page_log] must be be >= 8 and <= 20. - Do not change the definition of [Page_size]. */ -#define Page_log 12 /* A page is 4 kilobytes. */ -#define Page_size (1 << Page_log) - -/* Initial size of stack (bytes). */ -#define Stack_size (4096 * sizeof(value)) - -/* Minimum free size of stack (bytes); below that, it is reallocated. */ -#define Stack_threshold (256 * sizeof(value)) - -/* Default maximum size of the stack (words). */ -#define Max_stack_def (1024 * 1024) - - -/* Maximum size of a block allocated in the young generation (words). */ -/* Must be > 4 */ -#define Max_young_wosize 256 -#define Max_young_whsize (Whsize_wosize (Max_young_wosize)) - - -/* Minimum size of the minor zone (words). - This must be at least [2 * Max_young_whsize]. */ -#define Minor_heap_min 4096 - -/* Maximum size of the minor zone (words). - Must be greater than or equal to [Minor_heap_min]. -*/ -#define Minor_heap_max (1 << 28) - -/* Default size of the minor zone. (words) */ -#define Minor_heap_def 262144 - - -/* Minimum size increment when growing the heap (words). - Must be a multiple of [Page_size / sizeof (value)]. */ -#define Heap_chunk_min (15 * Page_size) - -/* Default size increment when growing the heap. - If this is <= 1000, it's a percentage of the current heap size. - If it is > 1000, it's a number of words. */ -#define Heap_chunk_def 15 - -/* Default initial size of the major heap (words); - Must be a multiple of [Page_size / sizeof (value)]. */ -#define Init_heap_def (31 * Page_size) -/* (about 512 kB for a 32-bit platform, 1 MB for a 64-bit platform.) */ - - -/* Default speed setting for the major GC. The heap will grow until - the dead objects and the free list represent this percentage of the - total size of live objects. */ -#define Percent_free_def 80 - -/* Default setting for the compacter: 500% - (i.e. trigger the compacter when 5/6 of the heap is free or garbage) - This can be set quite high because the overhead is over-estimated - when fragmentation occurs. - */ -#define Max_percent_free_def 500 - -/* Default setting for the major GC slice smoothing window: 1 - (i.e. no smoothing) -*/ -#define Major_window_def 1 - -/* Maximum size of the major GC slice smoothing window. */ -#define Max_major_window 50 - -#endif /* CAML_CONFIG_H */ diff --git a/byterun/caml/custom.h b/byterun/caml/custom.h deleted file mode 100644 index 6bc3aa95..00000000 --- a/byterun/caml/custom.h +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#ifndef CAML_CUSTOM_H -#define CAML_CUSTOM_H - - -#ifndef CAML_NAME_SPACE -#include "compatibility.h" -#endif -#include "mlvalues.h" - -struct custom_operations { - char *identifier; - void (*finalize)(value v); - int (*compare)(value v1, value v2); - intnat (*hash)(value v); - void (*serialize)(value v, - /*out*/ uintnat * bsize_32 /*size in bytes*/, - /*out*/ uintnat * bsize_64 /*size in bytes*/); - uintnat (*deserialize)(void * dst); - int (*compare_ext)(value v1, value v2); -}; - -#define custom_finalize_default NULL -#define custom_compare_default NULL -#define custom_hash_default NULL -#define custom_serialize_default NULL -#define custom_deserialize_default NULL -#define custom_compare_ext_default NULL - -#define Custom_ops_val(v) (*((struct custom_operations **) (v))) - -#ifdef __cplusplus -extern "C" { -#endif - - -CAMLextern value caml_alloc_custom(struct custom_operations * ops, - uintnat size, /*size in bytes*/ - mlsize_t mem, /*resources consumed*/ - mlsize_t max /*max resources*/); - -CAMLextern void caml_register_custom_operations(struct custom_operations * ops); - -CAMLextern int caml_compare_unordered; - /* Used by custom comparison to report unordered NaN-like cases. */ - -#ifdef CAML_INTERNALS -extern struct custom_operations * caml_find_custom_operations(char * ident); -extern struct custom_operations * - caml_final_custom_operations(void (*fn)(value)); - -extern void caml_init_custom_operations(void); -#endif /* CAML_INTERNALS */ - -#ifdef __cplusplus -} -#endif - -#endif /* CAML_CUSTOM_H */ diff --git a/byterun/caml/exec.h b/byterun/caml/exec.h deleted file mode 100644 index 38ab7ae8..00000000 --- a/byterun/caml/exec.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* exec.h : format of executable bytecode files */ - -#ifndef CAML_EXEC_H -#define CAML_EXEC_H - -#ifdef CAML_INTERNALS - -/* Executable bytecode files are composed of a number of sections, - identified by 4-character names. A table of contents at the - end of the file lists the section names along with their sizes, - in the order in which they appear in the file: - - offset 0 ---> initial junk - data for section 1 - data for section 2 - ... - data for section N - table of contents: - descriptor for section 1 - ... - descriptor for section N - trailer - end of file ---> -*/ - -/* Structure of t.o.c. entries - Numerical quantities are 32-bit unsigned integers, big endian */ - -struct section_descriptor { - char name[4]; /* Section name */ - uint32_t len; /* Length of data in bytes */ -}; - -/* Structure of the trailer. */ - -struct exec_trailer { - uint32_t num_sections; /* Number of sections */ - char magic[12]; /* The magic number */ - struct section_descriptor * section; /* Not part of file */ -}; - -#define TRAILER_SIZE (4+12) - -/* Magic number for this release */ - -#define EXEC_MAGIC "Caml1999X023" - -#endif /* CAML_INTERNALS */ - -#endif /* CAML_EXEC_H */ diff --git a/byterun/caml/finalise.h b/byterun/caml/finalise.h deleted file mode 100644 index 5315ac21..00000000 --- a/byterun/caml/finalise.h +++ /dev/null @@ -1,36 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Moscova, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#ifndef CAML_FINALISE_H -#define CAML_FINALISE_H - -#ifdef CAML_INTERNALS - -#include "roots.h" - -void caml_final_update_mark_phase (void); -void caml_final_update_clean_phase (void); -void caml_final_do_calls (void); -void caml_final_do_roots (scanning_action f); -void caml_final_invert_finalisable_values (); -void caml_final_oldify_young_roots (); -void caml_final_empty_young (void); -void caml_final_update_minor_roots(void); -value caml_final_register (value f, value v); -void caml_final_invariant_check(void); - -#endif /* CAML_INTERNALS */ - -#endif /* CAML_FINALISE_H */ diff --git a/byterun/caml/gc.h b/byterun/caml/gc.h deleted file mode 100644 index a646a756..00000000 --- a/byterun/caml/gc.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#ifndef CAML_GC_H -#define CAML_GC_H - - -#include "mlvalues.h" - -#define Caml_white (0 << 8) -#define Caml_gray (1 << 8) -#define Caml_blue (2 << 8) -#define Caml_black (3 << 8) - -#define Color_hd(hd) ((color_t) ((hd) & Caml_black)) -#define Color_hp(hp) (Color_hd (Hd_hp (hp))) -#define Color_val(val) (Color_hd (Hd_val (val))) - -#define Is_white_hd(hd) (Color_hd (hd) == Caml_white) -#define Is_gray_hd(hd) (Color_hd (hd) == Caml_gray) -#define Is_blue_hd(hd) (Color_hd (hd) == Caml_blue) -#define Is_black_hd(hd) (Color_hd (hd) == Caml_black) - -#define Whitehd_hd(hd) (((hd) & ~Caml_black)/*| Caml_white*/) -#define Grayhd_hd(hd) (((hd) & ~Caml_black) | Caml_gray) -#define Blackhd_hd(hd) (((hd)/*& ~Caml_black*/)| Caml_black) -#define Bluehd_hd(hd) (((hd) & ~Caml_black) | Caml_blue) - -/* This depends on the layout of the header. See [mlvalues.h]. */ -#define Make_header(wosize, tag, color) \ - (/*CAMLassert ((wosize) <= Max_wosize),*/ \ - ((header_t) (((header_t) (wosize) << 10) \ - + (color) \ - + (tag_t) (tag))) \ - ) - -#ifdef WITH_PROFINFO -#define Make_header_with_profinfo(wosize, tag, color, profinfo) \ - (Make_header(wosize, tag, color) \ - | ((((intnat) profinfo) & PROFINFO_MASK) << PROFINFO_SHIFT) \ - ) -#else -#define Make_header_with_profinfo(wosize, tag, color, profinfo) \ - Make_header(wosize, tag, color) -#endif - -#ifdef WITH_SPACETIME -struct ext_table; -extern uintnat caml_spacetime_my_profinfo(struct ext_table**, uintnat); -#define Make_header_allocated_here(wosize, tag, color) \ - (Make_header_with_profinfo(wosize, tag, color, \ - caml_spacetime_my_profinfo(NULL, wosize)) \ - ) -#else -#define Make_header_allocated_here Make_header -#endif - -#define Is_white_val(val) (Color_val(val) == Caml_white) -#define Is_gray_val(val) (Color_val(val) == Caml_gray) -#define Is_blue_val(val) (Color_val(val) == Caml_blue) -#define Is_black_val(val) (Color_val(val) == Caml_black) - -/* For extern.c */ -#define Colornum_hd(hd) ((color_t) (((hd) >> 8) & 3)) -#define Coloredhd_hd(hd,colnum) (((hd) & ~Caml_black) | ((colnum) << 8)) - -#endif /* CAML_GC_H */ diff --git a/byterun/caml/gc_ctrl.h b/byterun/caml/gc_ctrl.h deleted file mode 100644 index ebf1a40b..00000000 --- a/byterun/caml/gc_ctrl.h +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#ifndef CAML_GC_CTRL_H -#define CAML_GC_CTRL_H - -#ifdef CAML_INTERNALS - -#include "misc.h" - -extern double - caml_stat_minor_words, - caml_stat_promoted_words, - caml_stat_major_words; - -extern intnat - caml_stat_minor_collections, - caml_stat_major_collections, - caml_stat_heap_wsz, - caml_stat_top_heap_wsz, - caml_stat_compactions, - caml_stat_heap_chunks; - -uintnat caml_normalize_heap_increment (uintnat); - -/* - minor_size: cf. minor_heap_size in gc.mli - major_size: Size in words of the initial major heap - major_incr: cf. major_heap_increment in gc.mli - percent_fr: cf. space_overhead in gc.mli - percent_m : cf. max_overhead in gc.mli - window : cf. window_size in gc.mli -*/ -void caml_init_gc (uintnat minor_size, uintnat major_size, uintnat major_incr, - uintnat percent_fr, uintnat percent_m, uintnat window); - - -CAMLextern value caml_gc_stat(value v); - -#ifdef DEBUG -void caml_heap_check (void); -#endif - -#endif /* CAML_INTERNALS */ - -#endif /* CAML_GC_CTRL_H */ diff --git a/byterun/caml/instrtrace.h b/byterun/caml/instrtrace.h deleted file mode 100644 index 2e42a80a..00000000 --- a/byterun/caml/instrtrace.h +++ /dev/null @@ -1,35 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* Trace the instructions executed */ - -#ifndef _instrtrace_ -#define _instrtrace_ - -#ifdef CAML_INTERNALS - -#include "mlvalues.h" -#include "misc.h" - -extern intnat caml_icount; -void caml_stop_here (void); -void caml_disasm_instr (code_t pc); -void caml_trace_value_file (value v, code_t prog, int proglen, FILE * f); -void caml_trace_accu_sp_file(value accu, value * sp, code_t prog, int proglen, - FILE * f); - -#endif /* CAML_INTERNALS */ - -#endif diff --git a/byterun/caml/intext.h b/byterun/caml/intext.h deleted file mode 100644 index f67c98b5..00000000 --- a/byterun/caml/intext.h +++ /dev/null @@ -1,207 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* Structured input/output */ - -#ifndef CAML_INTEXT_H -#define CAML_INTEXT_H - -#ifndef CAML_NAME_SPACE -#include "compatibility.h" -#endif -#include "misc.h" -#include "mlvalues.h" - -#ifdef CAML_INTERNALS -#include "io.h" - -/* Magic number */ - -#define Intext_magic_number_small 0x8495A6BE -#define Intext_magic_number_big 0x8495A6BF - -/* Header format for the "small" model: 20 bytes - 0 "small" magic number - 4 length of marshaled data, in bytes - 8 number of shared blocks - 12 size in words when read on a 32-bit platform - 16 size in words when read on a 64-bit platform - The 4 numbers are 32 bits each, in big endian. - - Header format for the "big" model: 32 bytes - 0 "big" magic number - 4 four reserved bytes, currently set to 0 - 8 length of marshaled data, in bytes - 16 number of shared blocks - 24 size in words when read on a 64-bit platform - The 3 numbers are 64 bits each, in big endian. -*/ - -/* Codes for the compact format */ - -#define PREFIX_SMALL_BLOCK 0x80 -#define PREFIX_SMALL_INT 0x40 -#define PREFIX_SMALL_STRING 0x20 -#define CODE_INT8 0x0 -#define CODE_INT16 0x1 -#define CODE_INT32 0x2 -#define CODE_INT64 0x3 -#define CODE_SHARED8 0x4 -#define CODE_SHARED16 0x5 -#define CODE_SHARED32 0x6 -#define CODE_SHARED64 0x14 -#define CODE_BLOCK32 0x8 -#define CODE_BLOCK64 0x13 -#define CODE_STRING8 0x9 -#define CODE_STRING32 0xA -#define CODE_STRING64 0x15 -#define CODE_DOUBLE_BIG 0xB -#define CODE_DOUBLE_LITTLE 0xC -#define CODE_DOUBLE_ARRAY8_BIG 0xD -#define CODE_DOUBLE_ARRAY8_LITTLE 0xE -#define CODE_DOUBLE_ARRAY32_BIG 0xF -#define CODE_DOUBLE_ARRAY32_LITTLE 0x7 -#define CODE_DOUBLE_ARRAY64_BIG 0x16 -#define CODE_DOUBLE_ARRAY64_LITTLE 0x17 -#define CODE_CODEPOINTER 0x10 -#define CODE_INFIXPOINTER 0x11 -#define CODE_CUSTOM 0x12 - -#if ARCH_FLOAT_ENDIANNESS == 0x76543210 -#define CODE_DOUBLE_NATIVE CODE_DOUBLE_BIG -#define CODE_DOUBLE_ARRAY8_NATIVE CODE_DOUBLE_ARRAY8_BIG -#define CODE_DOUBLE_ARRAY32_NATIVE CODE_DOUBLE_ARRAY32_BIG -#define CODE_DOUBLE_ARRAY64_NATIVE CODE_DOUBLE_ARRAY64_BIG -#else -#define CODE_DOUBLE_NATIVE CODE_DOUBLE_LITTLE -#define CODE_DOUBLE_ARRAY8_NATIVE CODE_DOUBLE_ARRAY8_LITTLE -#define CODE_DOUBLE_ARRAY32_NATIVE CODE_DOUBLE_ARRAY32_LITTLE -#define CODE_DOUBLE_ARRAY64_NATIVE CODE_DOUBLE_ARRAY64_LITTLE -#endif - -/* Size-ing data structures for extern. Chosen so that - sizeof(struct trail_block) and sizeof(struct output_block) - are slightly below 8Kb. */ - -#define ENTRIES_PER_TRAIL_BLOCK 1025 -#define SIZE_EXTERN_OUTPUT_BLOCK 8100 - -/* The entry points */ - -void caml_output_val (struct channel * chan, value v, value flags); - /* Output [v] with flags [flags] on the channel [chan]. */ - -#endif /* CAML_INTERNALS */ - -#ifdef __cplusplus -extern "C" { -#endif - -CAMLextern void caml_output_value_to_malloc(value v, value flags, - /*out*/ char ** buf, - /*out*/ intnat * len); - /* Output [v] with flags [flags] to a memory buffer allocated with - malloc. On return, [*buf] points to the buffer and [*len] - contains the number of bytes in buffer. */ -CAMLextern intnat caml_output_value_to_block(value v, value flags, - char * data, intnat len); - /* Output [v] with flags [flags] to a user-provided memory buffer. - [data] points to the start of this buffer, and [len] is its size - in bytes. Return the number of bytes actually written in buffer. - Raise [Failure] if buffer is too short. */ - -#ifdef CAML_INTERNALS -value caml_input_val (struct channel * chan); - /* Read a structured value from the channel [chan]. */ - -extern value caml_input_value_to_outside_heap (value channel); - /* As for [caml_input_value], but the value is unmarshalled into - malloc blocks that are not added to the heap. Not for the - casual user. */ - -extern int caml_extern_allow_out_of_heap; - /* Permit the marshaller to traverse structures that look like OCaml - values but do not live in the OCaml heap. */ - -extern value caml_output_value(value vchan, value v, value flags); -#endif /* CAML_INTERNALS */ - -CAMLextern value caml_input_val_from_string (value str, intnat ofs); - /* Read a structured value from the OCaml string [str], starting - at offset [ofs]. */ -CAMLextern value caml_input_value_from_malloc(char * data, intnat ofs); - /* Read a structured value from a malloced buffer. [data] points - to the beginning of the buffer, and [ofs] is the offset of the - beginning of the externed data in this buffer. The buffer is - deallocated with [free] on return, or if an exception is raised. */ -CAMLextern value caml_input_value_from_block(char * data, intnat len); - /* Read a structured value from a user-provided buffer. [data] points - to the beginning of the externed data in this buffer, - and [len] is the length in bytes of valid data in this buffer. - The buffer is never deallocated by this routine. */ - -/* Functions for writing user-defined marshallers */ - -CAMLextern void caml_serialize_int_1(int i); -CAMLextern void caml_serialize_int_2(int i); -CAMLextern void caml_serialize_int_4(int32_t i); -CAMLextern void caml_serialize_int_8(int64_t i); -CAMLextern void caml_serialize_float_4(float f); -CAMLextern void caml_serialize_float_8(double f); -CAMLextern void caml_serialize_block_1(void * data, intnat len); -CAMLextern void caml_serialize_block_2(void * data, intnat len); -CAMLextern void caml_serialize_block_4(void * data, intnat len); -CAMLextern void caml_serialize_block_8(void * data, intnat len); -CAMLextern void caml_serialize_block_float_8(void * data, intnat len); - -CAMLextern int caml_deserialize_uint_1(void); -CAMLextern int caml_deserialize_sint_1(void); -CAMLextern int caml_deserialize_uint_2(void); -CAMLextern int caml_deserialize_sint_2(void); -CAMLextern uint32_t caml_deserialize_uint_4(void); -CAMLextern int32_t caml_deserialize_sint_4(void); -CAMLextern uint64_t caml_deserialize_uint_8(void); -CAMLextern int64_t caml_deserialize_sint_8(void); -CAMLextern float caml_deserialize_float_4(void); -CAMLextern double caml_deserialize_float_8(void); -CAMLextern void caml_deserialize_block_1(void * data, intnat len); -CAMLextern void caml_deserialize_block_2(void * data, intnat len); -CAMLextern void caml_deserialize_block_4(void * data, intnat len); -CAMLextern void caml_deserialize_block_8(void * data, intnat len); -CAMLextern void caml_deserialize_block_float_8(void * data, intnat len); -CAMLextern void caml_deserialize_error(char * msg); - -#ifdef CAML_INTERNALS - -/* Auxiliary stuff for sending code pointers */ - -struct code_fragment { - char * code_start; - char * code_end; - unsigned char digest[16]; - char digest_computed; -}; - -CAMLextern struct code_fragment * caml_extern_find_code(char *addr); - -extern struct ext_table caml_code_fragments_table; - -#endif /* CAML_INTERNALS */ - -#ifdef __cplusplus -} -#endif - -#endif /* CAML_INTEXT_H */ diff --git a/byterun/caml/memory.h b/byterun/caml/memory.h deleted file mode 100644 index 1ba489b2..00000000 --- a/byterun/caml/memory.h +++ /dev/null @@ -1,595 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* Allocation macros and functions */ - -#ifndef CAML_MEMORY_H -#define CAML_MEMORY_H - -#ifndef CAML_NAME_SPACE -#include "compatibility.h" -#endif -#include "config.h" -#ifdef CAML_INTERNALS -#include "gc.h" -#include "major_gc.h" -#include "minor_gc.h" -#endif /* CAML_INTERNALS */ -#include "misc.h" -#include "mlvalues.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -CAMLextern value caml_alloc_shr (mlsize_t wosize, tag_t); -#ifdef WITH_PROFINFO -CAMLextern value caml_alloc_shr_with_profinfo (mlsize_t, tag_t, intnat); -CAMLextern value caml_alloc_shr_preserving_profinfo (mlsize_t, tag_t, - header_t); -#else -#define caml_alloc_shr_with_profinfo(size, tag, profinfo) \ - caml_alloc_shr(size, tag) -#define caml_alloc_shr_preserving_profinfo(size, tag, header) \ - caml_alloc_shr(size, tag) -#endif /* WITH_PROFINFO */ -CAMLextern value caml_alloc_shr_no_raise (mlsize_t wosize, tag_t); -CAMLextern void caml_adjust_gc_speed (mlsize_t, mlsize_t); -CAMLextern void caml_alloc_dependent_memory (mlsize_t bsz); -CAMLextern void caml_free_dependent_memory (mlsize_t bsz); -CAMLextern void caml_modify (value *, value); -CAMLextern void caml_initialize (value *, value); -CAMLextern value caml_check_urgent_gc (value); -CAMLextern int caml_init_alloc_for_heap (void); -CAMLextern char *caml_alloc_for_heap (asize_t request); /* Size in bytes. */ -CAMLextern void caml_free_for_heap (char *mem); -CAMLextern void caml_disown_for_heap (char *mem); -CAMLextern int caml_add_to_heap (char *mem); -CAMLextern color_t caml_allocation_color (void *hp); - -CAMLextern int caml_huge_fallback_count; - - -/* [caml_stat_*] functions below provide an interface to the static memory - manager built into the runtime, which can be used for managing static - (that is, non-moving) blocks of heap memory. - - Function arguments that have type [caml_stat_block] must always be pointers - to blocks returned by the [caml_stat_*] functions below. Attempting to use - these functions on memory blocks allocated by a different memory manager - (e.g. the one from the C runtime) will cause undefined behaviour. -*/ -typedef void* caml_stat_block; - -#ifdef CAML_INTERNALS - -/* The pool must be initialized with a call to [caml_stat_create_pool] - before it is possible to use any of the [caml_stat_*] functions below. - - If the pool is not initialized, [caml_stat_*] functions will still work in - backward compatibility mode, becoming thin wrappers around [malloc] family - of functions. In this case, calling [caml_stat_destroy_pool] will not free - the claimed heap memory, resulting in leaks. -*/ -CAMLextern void caml_stat_create_pool(void); - -/* [caml_stat_destroy_pool] frees all the heap memory claimed by the pool. - - Once the pool is destroyed, [caml_stat_*] functions will continue to work - in backward compatibility mode, becoming thin wrappers around [malloc] - family of functions. -*/ -CAMLextern void caml_stat_destroy_pool(void); - -#endif /* CAML_INTERNALS */ - -/* [caml_stat_alloc(size)] allocates a memory block of the requested [size] - (in bytes) and returns a pointer to it. It throws an OCaml exception in case - the request fails, and so requires the runtime lock to be held. -*/ -CAMLextern caml_stat_block caml_stat_alloc(asize_t); - -/* [caml_stat_alloc_noexc(size)] allocates a memory block of the requested [size] - (in bytes) and returns a pointer to it, or NULL in case the request fails. -*/ -CAMLextern caml_stat_block caml_stat_alloc_noexc(asize_t); - -/* [caml_stat_alloc_aligned(size, modulo, block*)] allocates a memory block of - the requested [size] (in bytes), the starting address of which is aligned to - the provided [modulo] value. The function returns the aligned address, as - well as the unaligned [block] (as an output parameter). It throws an OCaml - exception in case the request fails, and so requires the runtime lock. -*/ -CAMLextern void* caml_stat_alloc_aligned(asize_t, int modulo, caml_stat_block*); - -/* [caml_stat_alloc_aligned_noexc] is a variant of [caml_stat_alloc_aligned] - that returns NULL in case the request fails, and doesn't require the runtime - lock to be held. -*/ -CAMLextern void* caml_stat_alloc_aligned_noexc(asize_t, int modulo, - caml_stat_block*); - -/* [caml_stat_calloc_noexc(num, size)] allocates a block of memory for an array - of [num] elements, each of them [size] bytes long, and initializes all its - bits to zero, effectively allocating a zero-initialized memory block of - [num * size] bytes. It returns NULL in case the request fails. -*/ -CAMLextern caml_stat_block caml_stat_calloc_noexc(asize_t, asize_t); - -/* [caml_stat_free(block)] deallocates the provided [block]. */ -CAMLextern void caml_stat_free(caml_stat_block); - -/* [caml_stat_resize(block, size)] changes the size of the provided [block] to - [size] bytes. The function may move the memory block to a new location (whose - address is returned by the function). The content of the [block] is preserved - up to the smaller of the new and old sizes, even if the block is moved to a - new location. If the new size is larger, the value of the newly allocated - portion is indeterminate. The function throws an OCaml exception in case the - request fails, and so requires the runtime lock to be held. -*/ -CAMLextern caml_stat_block caml_stat_resize(caml_stat_block, asize_t); - -/* [caml_stat_resize_noexc] is a variant of [caml_stat_resize] that returns NULL - in case the request fails, and doesn't require the runtime lock. -*/ -CAMLextern caml_stat_block caml_stat_resize_noexc(caml_stat_block, asize_t); - - -/* A [caml_stat_block] containing a NULL-terminated string */ -typedef char* caml_stat_string; - -/* [caml_stat_strdup(s)] returns a pointer to a heap-allocated string which is a - copy of the NULL-terminated string [s]. It throws an OCaml exception in case - the request fails, and so requires the runtime lock to be held. -*/ -CAMLextern caml_stat_string caml_stat_strdup(const char *s); -#ifdef _WIN32 -CAMLextern wchar_t* caml_stat_wcsdup(const wchar_t *s); -#endif - -/* [caml_stat_strdup_noexc] is a variant of [caml_stat_strdup] that returns NULL - in case the request fails, and doesn't require the runtime lock. -*/ -CAMLextern caml_stat_string caml_stat_strdup_noexc(const char *s); - -/* [caml_stat_strconcat(nargs, strings)] concatenates NULL-terminated [strings] - (an array of [char*] of size [nargs]) into a new string, dropping all NULLs, - except for the very last one. It throws an OCaml exception in case the - request fails, and so requires the runtime lock to be held. -*/ -CAMLextern caml_stat_string caml_stat_strconcat(int n, ...); -#ifdef _WIN32 -CAMLextern wchar_t* caml_stat_wcsconcat(int n, ...); -#endif - - -/* void caml_shrink_heap (char *); Only used in compact.c */ - -#ifdef CAML_INTERNALS - -extern uintnat caml_use_huge_pages; - -#ifdef HAS_HUGE_PAGES -#include -#define Heap_page_size HUGE_PAGE_SIZE -#define Round_mmap_size(x) \ - (((x) + (Heap_page_size - 1)) & ~ (Heap_page_size - 1)) -#endif - - -int caml_page_table_add(int kind, void * start, void * end); -int caml_page_table_remove(int kind, void * start, void * end); -int caml_page_table_initialize(mlsize_t bytesize); - -#ifdef DEBUG -#define DEBUG_clear(result, wosize) do{ \ - uintnat caml__DEBUG_i; \ - for (caml__DEBUG_i = 0; caml__DEBUG_i < (wosize); ++ caml__DEBUG_i){ \ - Field ((result), caml__DEBUG_i) = Debug_uninit_minor; \ - } \ -}while(0) -#else -#define DEBUG_clear(result, wosize) -#endif - -#define Alloc_small_with_profinfo(result, wosize, tag, profinfo) do { \ - CAMLassert ((wosize) >= 1); \ - CAMLassert ((tag_t) (tag) < 256); \ - CAMLassert ((wosize) <= Max_young_wosize); \ - caml_young_ptr -= Whsize_wosize (wosize); \ - if (caml_young_ptr < caml_young_trigger){ \ - caml_young_ptr += Whsize_wosize (wosize); \ - CAML_INSTR_INT ("force_minor/alloc_small@", 1); \ - Setup_for_gc; \ - caml_gc_dispatch (); \ - Restore_after_gc; \ - caml_young_ptr -= Whsize_wosize (wosize); \ - } \ - Hd_hp (caml_young_ptr) = \ - Make_header_with_profinfo ((wosize), (tag), Caml_black, profinfo); \ - (result) = Val_hp (caml_young_ptr); \ - DEBUG_clear ((result), (wosize)); \ -}while(0) - -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) -extern uintnat caml_spacetime_my_profinfo(struct ext_table**, uintnat); -#define Alloc_small(result, wosize, tag) \ - Alloc_small_with_profinfo(result, wosize, tag, \ - caml_spacetime_my_profinfo(NULL, wosize)) -#else -#define Alloc_small(result, wosize, tag) \ - Alloc_small_with_profinfo(result, wosize, tag, (uintnat) 0) -#endif - -/* Deprecated alias for [caml_modify] */ - -#define Modify(fp,val) caml_modify((fp), (val)) - -#endif /* CAML_INTERNALS */ - -struct caml__roots_block { - struct caml__roots_block *next; - intnat ntables; - intnat nitems; - value *tables [5]; -}; - -CAMLextern struct caml__roots_block *caml_local_roots; /* defined in roots.c */ - -/* The following macros are used to declare C local variables and - function parameters of type [value]. - - The function body must start with one of the [CAMLparam] macros. - If the function has no parameter of type [value], use [CAMLparam0]. - If the function has 1 to 5 [value] parameters, use the corresponding - [CAMLparam] with the parameters as arguments. - If the function has more than 5 [value] parameters, use [CAMLparam5] - for the first 5 parameters, and one or more calls to the [CAMLxparam] - macros for the others. - If the function takes an array of [value]s as argument, use - [CAMLparamN] to declare it (or [CAMLxparamN] if you already have a - call to [CAMLparam] for some other arguments). - - If you need local variables of type [value], declare them with one - or more calls to the [CAMLlocal] macros at the beginning of the - function, after the call to CAMLparam. Use [CAMLlocalN] (at the - beginning of the function) to declare an array of [value]s. - - Your function may raise an exception or return a [value] with the - [CAMLreturn] macro. Its argument is simply the [value] returned by - your function. Do NOT directly return a [value] with the [return] - keyword. If your function returns void, use [CAMLreturn0]. If you - un-register the local roots (i.e. undo the effects of the [CAMLparam*] - and [CAMLlocal] macros) without returning immediately, use [CAMLdrop]. - - All the identifiers beginning with "caml__" are reserved by OCaml. - Do not use them for anything (local or global variables, struct or - union tags, macros, etc.) -*/ - -#define CAMLparam0() \ - struct caml__roots_block *caml__frame = caml_local_roots - -#define CAMLparam1(x) \ - CAMLparam0 (); \ - CAMLxparam1 (x) - -#define CAMLparam2(x, y) \ - CAMLparam0 (); \ - CAMLxparam2 (x, y) - -#define CAMLparam3(x, y, z) \ - CAMLparam0 (); \ - CAMLxparam3 (x, y, z) - -#define CAMLparam4(x, y, z, t) \ - CAMLparam0 (); \ - CAMLxparam4 (x, y, z, t) - -#define CAMLparam5(x, y, z, t, u) \ - CAMLparam0 (); \ - CAMLxparam5 (x, y, z, t, u) - -#define CAMLparamN(x, size) \ - CAMLparam0 (); \ - CAMLxparamN (x, (size)) - -/* CAMLunused is preserved for compatibility reasons. - Instead of the legacy GCC/Clang-only - CAMLunused foo; - you should prefer - CAMLunused_start foo CAMLunused_end; - which supports both GCC/Clang and MSVC. -*/ -#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 7)) - #define CAMLunused_start __attribute__ ((unused)) - #define CAMLunused_end - #define CAMLunused __attribute__ ((unused)) -#elif _MSC_VER >= 1500 - #define CAMLunused_start __pragma( warning (push) ) \ - __pragma( warning (disable:4189 ) ) - #define CAMLunused_end __pragma( warning (pop)) - #define CAMLunused -#else - #define CAMLunused_start - #define CAMLunused_end - #define CAMLunused -#endif - -#define CAMLxparam1(x) \ - struct caml__roots_block caml__roots_##x; \ - CAMLunused_start int caml__dummy_##x = ( \ - (void) caml__frame, \ - (caml__roots_##x.next = caml_local_roots), \ - (caml_local_roots = &caml__roots_##x), \ - (caml__roots_##x.nitems = 1), \ - (caml__roots_##x.ntables = 1), \ - (caml__roots_##x.tables [0] = &x), \ - 0) \ - CAMLunused_end - -#define CAMLxparam2(x, y) \ - struct caml__roots_block caml__roots_##x; \ - CAMLunused_start int caml__dummy_##x = ( \ - (void) caml__frame, \ - (caml__roots_##x.next = caml_local_roots), \ - (caml_local_roots = &caml__roots_##x), \ - (caml__roots_##x.nitems = 1), \ - (caml__roots_##x.ntables = 2), \ - (caml__roots_##x.tables [0] = &x), \ - (caml__roots_##x.tables [1] = &y), \ - 0) \ - CAMLunused_end - -#define CAMLxparam3(x, y, z) \ - struct caml__roots_block caml__roots_##x; \ - CAMLunused_start int caml__dummy_##x = ( \ - (void) caml__frame, \ - (caml__roots_##x.next = caml_local_roots), \ - (caml_local_roots = &caml__roots_##x), \ - (caml__roots_##x.nitems = 1), \ - (caml__roots_##x.ntables = 3), \ - (caml__roots_##x.tables [0] = &x), \ - (caml__roots_##x.tables [1] = &y), \ - (caml__roots_##x.tables [2] = &z), \ - 0) \ - CAMLunused_end - -#define CAMLxparam4(x, y, z, t) \ - struct caml__roots_block caml__roots_##x; \ - CAMLunused_start int caml__dummy_##x = ( \ - (void) caml__frame, \ - (caml__roots_##x.next = caml_local_roots), \ - (caml_local_roots = &caml__roots_##x), \ - (caml__roots_##x.nitems = 1), \ - (caml__roots_##x.ntables = 4), \ - (caml__roots_##x.tables [0] = &x), \ - (caml__roots_##x.tables [1] = &y), \ - (caml__roots_##x.tables [2] = &z), \ - (caml__roots_##x.tables [3] = &t), \ - 0) \ - CAMLunused_end - -#define CAMLxparam5(x, y, z, t, u) \ - struct caml__roots_block caml__roots_##x; \ - CAMLunused_start int caml__dummy_##x = ( \ - (void) caml__frame, \ - (caml__roots_##x.next = caml_local_roots), \ - (caml_local_roots = &caml__roots_##x), \ - (caml__roots_##x.nitems = 1), \ - (caml__roots_##x.ntables = 5), \ - (caml__roots_##x.tables [0] = &x), \ - (caml__roots_##x.tables [1] = &y), \ - (caml__roots_##x.tables [2] = &z), \ - (caml__roots_##x.tables [3] = &t), \ - (caml__roots_##x.tables [4] = &u), \ - 0) \ - CAMLunused_end - -#define CAMLxparamN(x, size) \ - struct caml__roots_block caml__roots_##x; \ - CAMLunused_start int caml__dummy_##x = ( \ - (void) caml__frame, \ - (caml__roots_##x.next = caml_local_roots), \ - (caml_local_roots = &caml__roots_##x), \ - (caml__roots_##x.nitems = (size)), \ - (caml__roots_##x.ntables = 1), \ - (caml__roots_##x.tables[0] = &(x[0])), \ - 0) \ - CAMLunused_end - -#define CAMLlocal1(x) \ - value x = Val_unit; \ - CAMLxparam1 (x) - -#define CAMLlocal2(x, y) \ - value x = Val_unit, y = Val_unit; \ - CAMLxparam2 (x, y) - -#define CAMLlocal3(x, y, z) \ - value x = Val_unit, y = Val_unit, z = Val_unit; \ - CAMLxparam3 (x, y, z) - -#define CAMLlocal4(x, y, z, t) \ - value x = Val_unit, y = Val_unit, z = Val_unit, t = Val_unit; \ - CAMLxparam4 (x, y, z, t) - -#define CAMLlocal5(x, y, z, t, u) \ - value x = Val_unit, y = Val_unit, z = Val_unit, t = Val_unit, u = Val_unit; \ - CAMLxparam5 (x, y, z, t, u) - -#define CAMLlocalN(x, size) \ - value x [(size)]; \ - int caml__i_##x; \ - for (caml__i_##x = 0; caml__i_##x < size; caml__i_##x ++) { \ - x[caml__i_##x] = Val_unit; \ - } \ - CAMLxparamN (x, (size)) - - -#define CAMLdrop caml_local_roots = caml__frame - -#define CAMLreturn0 do{ \ - CAMLdrop; \ - return; \ -}while (0) - -#define CAMLreturnT(type, result) do{ \ - type caml__temp_result = (result); \ - CAMLdrop; \ - return caml__temp_result; \ -}while(0) - -#define CAMLreturn(result) CAMLreturnT(value, result) - -#define CAMLnoreturn ((void) caml__frame) - - -/* convenience macro */ -#define Store_field(block, offset, val) do{ \ - mlsize_t caml__temp_offset = (offset); \ - value caml__temp_val = (val); \ - caml_modify (&Field ((block), caml__temp_offset), caml__temp_val); \ -}while(0) - -/* - NOTE: [Begin_roots] and [End_roots] are superseded by [CAMLparam]*, - [CAMLxparam]*, [CAMLlocal]*, [CAMLreturn]. - - [Begin_roots] and [End_roots] are used for C variables that are GC roots. - It must contain all values in C local variables and function parameters - at the time the minor GC is called. - Usage: - After initialising your local variables to legal OCaml values, but before - calling allocation functions, insert [Begin_roots_n(v1, ... vn)], where - v1 ... vn are your variables of type [value] that you want to be updated - across allocations. - At the end, insert [End_roots()]. - - Note that [Begin_roots] opens a new block, and [End_roots] closes it. - Thus they must occur in matching pairs at the same brace nesting level. - - You can use [Val_unit] as a dummy initial value for your variables. -*/ - -#define Begin_root Begin_roots1 - -#define Begin_roots1(r0) { \ - struct caml__roots_block caml__roots_block; \ - caml__roots_block.next = caml_local_roots; \ - caml_local_roots = &caml__roots_block; \ - caml__roots_block.nitems = 1; \ - caml__roots_block.ntables = 1; \ - caml__roots_block.tables[0] = &(r0); - -#define Begin_roots2(r0, r1) { \ - struct caml__roots_block caml__roots_block; \ - caml__roots_block.next = caml_local_roots; \ - caml_local_roots = &caml__roots_block; \ - caml__roots_block.nitems = 1; \ - caml__roots_block.ntables = 2; \ - caml__roots_block.tables[0] = &(r0); \ - caml__roots_block.tables[1] = &(r1); - -#define Begin_roots3(r0, r1, r2) { \ - struct caml__roots_block caml__roots_block; \ - caml__roots_block.next = caml_local_roots; \ - caml_local_roots = &caml__roots_block; \ - caml__roots_block.nitems = 1; \ - caml__roots_block.ntables = 3; \ - caml__roots_block.tables[0] = &(r0); \ - caml__roots_block.tables[1] = &(r1); \ - caml__roots_block.tables[2] = &(r2); - -#define Begin_roots4(r0, r1, r2, r3) { \ - struct caml__roots_block caml__roots_block; \ - caml__roots_block.next = caml_local_roots; \ - caml_local_roots = &caml__roots_block; \ - caml__roots_block.nitems = 1; \ - caml__roots_block.ntables = 4; \ - caml__roots_block.tables[0] = &(r0); \ - caml__roots_block.tables[1] = &(r1); \ - caml__roots_block.tables[2] = &(r2); \ - caml__roots_block.tables[3] = &(r3); - -#define Begin_roots5(r0, r1, r2, r3, r4) { \ - struct caml__roots_block caml__roots_block; \ - caml__roots_block.next = caml_local_roots; \ - caml_local_roots = &caml__roots_block; \ - caml__roots_block.nitems = 1; \ - caml__roots_block.ntables = 5; \ - caml__roots_block.tables[0] = &(r0); \ - caml__roots_block.tables[1] = &(r1); \ - caml__roots_block.tables[2] = &(r2); \ - caml__roots_block.tables[3] = &(r3); \ - caml__roots_block.tables[4] = &(r4); - -#define Begin_roots_block(table, size) { \ - struct caml__roots_block caml__roots_block; \ - caml__roots_block.next = caml_local_roots; \ - caml_local_roots = &caml__roots_block; \ - caml__roots_block.nitems = (size); \ - caml__roots_block.ntables = 1; \ - caml__roots_block.tables[0] = (table); - -#define End_roots() caml_local_roots = caml__roots_block.next; } - - -/* [caml_register_global_root] registers a global C variable as a memory root - for the duration of the program, or until [caml_remove_global_root] is - called. */ - -CAMLextern void caml_register_global_root (value *); - -/* [caml_remove_global_root] removes a memory root registered on a global C - variable with [caml_register_global_root]. */ - -CAMLextern void caml_remove_global_root (value *); - -/* [caml_register_generational_global_root] registers a global C - variable as a memory root for the duration of the program, or until - [caml_remove_generational_global_root] is called. - The program guarantees that the value contained in this variable - will not be assigned directly. If the program needs to change - the value of this variable, it must do so by calling - [caml_modify_generational_global_root]. The [value *] pointer - passed to [caml_register_generational_global_root] must contain - a valid OCaml value before the call. - In return for these constraints, scanning of memory roots during - minor collection is made more efficient. */ - -CAMLextern void caml_register_generational_global_root (value *); - -/* [caml_remove_generational_global_root] removes a memory root - registered on a global C variable with - [caml_register_generational_global_root]. */ - -CAMLextern void caml_remove_generational_global_root (value *); - -/* [caml_modify_generational_global_root(r, newval)] - modifies the value contained in [r], storing [newval] inside. - In other words, the assignment [*r = newval] is performed, - but in a way that is compatible with the optimized scanning of - generational global roots. [r] must be a global memory root - previously registered with [caml_register_generational_global_root]. */ - -CAMLextern void caml_modify_generational_global_root(value *r, value newval); - -#ifdef __cplusplus -} -#endif - -#endif /* CAML_MEMORY_H */ diff --git a/byterun/caml/minor_gc.h b/byterun/caml/minor_gc.h deleted file mode 100644 index 6c48c761..00000000 --- a/byterun/caml/minor_gc.h +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#ifndef CAML_MINOR_GC_H -#define CAML_MINOR_GC_H - - -#include "address_class.h" -#include "config.h" - -CAMLextern value *caml_young_start, *caml_young_end; -CAMLextern value *caml_young_alloc_start, *caml_young_alloc_end; -CAMLextern value *caml_young_ptr, *caml_young_limit; -CAMLextern value *caml_young_trigger; -extern asize_t caml_minor_heap_wsz; -extern int caml_in_minor_collection; -extern double caml_extra_heap_resources_minor; - -#define CAML_TABLE_STRUCT(t) { \ - t *base; \ - t *end; \ - t *threshold; \ - t *ptr; \ - t *limit; \ - asize_t size; \ - asize_t reserve; \ -} - -struct caml_ref_table CAML_TABLE_STRUCT(value *); -CAMLextern struct caml_ref_table caml_ref_table; - -struct caml_ephe_ref_elt { - value ephe; /* an ephemeron in major heap */ - mlsize_t offset; /* the offset that points in the minor heap */ -}; - -struct caml_ephe_ref_table CAML_TABLE_STRUCT(struct caml_ephe_ref_elt); -CAMLextern struct caml_ephe_ref_table caml_ephe_ref_table; - -struct caml_custom_elt { - value block; /* The finalized block in the minor heap. */ - mlsize_t mem; /* The parameters for adjusting GC speed. */ - mlsize_t max; -}; - -struct caml_custom_table CAML_TABLE_STRUCT(struct caml_custom_elt); -CAMLextern struct caml_custom_table caml_custom_table; - -extern void caml_set_minor_heap_size (asize_t); /* size in bytes */ -extern void caml_empty_minor_heap (void); -CAMLextern void caml_gc_dispatch (void); -CAMLextern void garbage_collection (void); /* def in asmrun/signals_asm.c */ -extern void caml_realloc_ref_table (struct caml_ref_table *); -extern void caml_alloc_table (struct caml_ref_table *, asize_t, asize_t); -extern void caml_realloc_ephe_ref_table (struct caml_ephe_ref_table *); -extern void caml_alloc_ephe_table (struct caml_ephe_ref_table *, - asize_t, asize_t); -extern void caml_realloc_custom_table (struct caml_custom_table *); -extern void caml_alloc_custom_table (struct caml_custom_table *, - asize_t, asize_t); -extern void caml_oldify_one (value, value *); -extern void caml_oldify_mopup (void); - -#define Oldify(p) do{ \ - value __oldify__v__ = *p; \ - if (Is_block (__oldify__v__) && Is_young (__oldify__v__)){ \ - caml_oldify_one (__oldify__v__, (p)); \ - } \ - }while(0) - -static inline void add_to_ref_table (struct caml_ref_table *tbl, value *p) -{ - if (tbl->ptr >= tbl->limit){ - CAMLassert (tbl->ptr == tbl->limit); - caml_realloc_ref_table (tbl); - } - *tbl->ptr++ = p; -} - -static inline void add_to_ephe_ref_table (struct caml_ephe_ref_table *tbl, - value ar, mlsize_t offset) -{ - struct caml_ephe_ref_elt *ephe_ref; - if (tbl->ptr >= tbl->limit){ - CAMLassert (tbl->ptr == tbl->limit); - caml_realloc_ephe_ref_table (tbl); - } - ephe_ref = tbl->ptr++; - ephe_ref->ephe = ar; - ephe_ref->offset = offset; - CAMLassert(ephe_ref->offset < Wosize_val(ephe_ref->ephe)); -} - -static inline void add_to_custom_table (struct caml_custom_table *tbl, value v, - mlsize_t mem, mlsize_t max) -{ - struct caml_custom_elt *elt; - if (tbl->ptr >= tbl->limit){ - CAMLassert (tbl->ptr == tbl->limit); - caml_realloc_custom_table (tbl); - } - elt = tbl->ptr++; - elt->block = v; - elt->mem = mem; - elt->max = max; -} - -#endif /* CAML_MINOR_GC_H */ diff --git a/byterun/caml/misc.h b/byterun/caml/misc.h deleted file mode 100644 index 8244de93..00000000 --- a/byterun/caml/misc.h +++ /dev/null @@ -1,525 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* Miscellaneous macros and variables. */ - -#ifndef CAML_MISC_H -#define CAML_MISC_H - -#ifndef CAML_NAME_SPACE -#include "compatibility.h" -#endif -#include "config.h" - -/* Standard definitions */ - -#include -#include - -/* Basic types and constants */ - -typedef size_t asize_t; - -#ifndef NULL -#define NULL 0 -#endif - -#ifdef CAML_INTERNALS -typedef char * addr; -#endif /* CAML_INTERNALS */ - -/* Noreturn is preserved for compatibility reasons. - Instead of the legacy GCC/Clang-only - foo Noreturn; - you should prefer - CAMLnoreturn_start foo CAMLnoreturn_end; - which supports both GCC/Clang and MSVC. - - Note: CAMLnoreturn is a different macro defined in memory.h, - to be used in function bodies rather than as a prototype attribute. -*/ -#ifdef __GNUC__ - /* Works only in GCC 2.5 and later */ - #define CAMLnoreturn_start - #define CAMLnoreturn_end __attribute__ ((noreturn)) - #define Noreturn __attribute__ ((noreturn)) -#elif _MSC_VER >= 1500 - #define CAMLnoreturn_start __declspec(noreturn) - #define CAMLnoreturn_end - #define Noreturn -#else - #define CAMLnoreturn_start - #define CAMLnoreturn_end - #define Noreturn -#endif - - - -/* Export control (to mark primitives and to handle Windows DLL) */ - -#define CAMLexport -#define CAMLprim -#define CAMLextern extern - -/* Weak function definitions that can be overridden by external libs */ -/* Conservatively restricted to ELF and MacOSX platforms */ -#if defined(__GNUC__) && (defined (__ELF__) || defined(__APPLE__)) -#define CAMLweakdef __attribute__((weak)) -#else -#define CAMLweakdef -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* GC timing hooks. These can be assigned by the user. - [caml_minor_gc_begin_hook] must not allocate nor change any heap value. - The others can allocate and even call back to OCaml code. -*/ -typedef void (*caml_timing_hook) (void); -extern caml_timing_hook caml_major_slice_begin_hook, caml_major_slice_end_hook; -extern caml_timing_hook caml_minor_gc_begin_hook, caml_minor_gc_end_hook; -extern caml_timing_hook caml_finalise_begin_hook, caml_finalise_end_hook; - -/* Assertions */ - -#ifdef DEBUG -#define CAMLassert(x) \ - ((x) ? (void) 0 : caml_failed_assert ( #x , __FILE__, __LINE__)) -CAMLnoreturn_start -CAMLextern int caml_failed_assert (char *, char *, int) -CAMLnoreturn_end; -#else -#define CAMLassert(x) ((void) 0) -#endif - -CAMLnoreturn_start -CAMLextern void caml_fatal_error (char *msg) -CAMLnoreturn_end; - -CAMLnoreturn_start -CAMLextern void caml_fatal_error_arg (char *fmt, char *arg) -CAMLnoreturn_end; - -CAMLnoreturn_start -CAMLextern void caml_fatal_error_arg2 (char *fmt1, char *arg1, - char *fmt2, char *arg2) -CAMLnoreturn_end; - -/* Detection of available C built-in functions, the Clang way. */ - -#ifdef __has_builtin -#define Caml_has_builtin(x) __has_builtin(x) -#else -#define Caml_has_builtin(x) 0 -#endif - -/* Integer arithmetic with overflow detection. - The functions return 0 if no overflow, 1 if overflow. - The result of the operation is always stored at [*res]. - If no overflow is reported, this is the exact result. - If overflow is reported, this is the exact result modulo 2 to the word size. -*/ - -static inline int caml_uadd_overflow(uintnat a, uintnat b, uintnat * res) -{ -#if __GNUC__ >= 5 || Caml_has_builtin(__builtin_add_overflow) - return __builtin_add_overflow(a, b, res); -#else - uintnat c = a + b; - *res = c; - return c < a; -#endif -} - -static inline int caml_usub_overflow(uintnat a, uintnat b, uintnat * res) -{ -#if __GNUC__ >= 5 || Caml_has_builtin(__builtin_sub_overflow) - return __builtin_sub_overflow(a, b, res); -#else - uintnat c = a - b; - *res = c; - return a < b; -#endif -} - -#if __GNUC__ >= 5 || Caml_has_builtin(__builtin_mul_overflow) -static inline int caml_umul_overflow(uintnat a, uintnat b, uintnat * res) -{ - return __builtin_mul_overflow(a, b, res); -} -#else -extern int caml_umul_overflow(uintnat a, uintnat b, uintnat * res); -#endif - -/* Windows Unicode support */ - -#ifdef _WIN32 - -typedef wchar_t char_os; - -#define _T(x) L ## x - -#define access_os _waccess -#define open_os _wopen -#define stat_os _wstati64 -#define unlink_os _wunlink -#define rename_os caml_win32_rename -#define chdir_os _wchdir -#define getcwd_os _wgetcwd -#define system_os _wsystem -#define rmdir_os _wrmdir -#define putenv_os _wputenv -#define chmod_os _wchmod -#define execv_os _wexecv -#define execve_os _wexecve -#define execvp_os _wexecvp -#define execvpe_os _wexecvpe -#define strcmp_os wcscmp -#define strlen_os wcslen -#define sscanf_os swscanf - -#define caml_stat_strdup_os caml_stat_wcsdup -#define caml_stat_strconcat_os caml_stat_wcsconcat - -#define caml_stat_strdup_to_os caml_stat_strdup_to_utf16 -#define caml_stat_strdup_of_os caml_stat_strdup_of_utf16 -#define caml_copy_string_of_os caml_copy_string_of_utf16 - -#else /* _WIN32 */ - -typedef char char_os; - -#define _T(x) x - -#define access_os access -#define open_os open -#define stat_os stat -#define unlink_os unlink -#define rename_os rename -#define chdir_os chdir -#define getcwd_os getcwd -#define system_os system -#define rmdir_os rmdir -#define putenv_os putenv -#define chmod_os chmod -#define execv_os execv -#define execve_os execve -#define execvp_os execvp -#define execvpe_os execvpe -#define strcmp_os strcmp -#define strlen_os strlen -#define sscanf_os sscanf - -#define caml_stat_strdup_os caml_stat_strdup -#define caml_stat_strconcat_os caml_stat_strconcat - -#define caml_stat_strdup_to_os caml_stat_strdup -#define caml_stat_strdup_of_os caml_stat_strdup -#define caml_copy_string_of_os caml_copy_string - -#endif /* _WIN32 */ - - -/* Use macros for some system calls being called from OCaml itself. - These calls can be either traced for security reasons, or changed to - virtualize the program. */ - - -#ifndef CAML_WITH_CPLUGINS - -#define CAML_SYS_EXIT(retcode) exit(retcode) -#define CAML_SYS_OPEN(filename,flags,perm) open_os(filename,flags,perm) -#define CAML_SYS_CLOSE(fd) close(fd) -#define CAML_SYS_STAT(filename,st) stat_os(filename,st) -#define CAML_SYS_UNLINK(filename) unlink_os(filename) -#define CAML_SYS_RENAME(old_name,new_name) rename_os(old_name, new_name) -#define CAML_SYS_CHDIR(dirname) chdir_os(dirname) -#define CAML_SYS_GETENV(varname) getenv(varname) -#define CAML_SYS_SYSTEM(command) system_os(command) -#define CAML_SYS_READ_DIRECTORY(dirname,tbl) caml_read_directory(dirname,tbl) - -#else - - -#define CAML_CPLUGINS_EXIT 0 -#define CAML_CPLUGINS_OPEN 1 -#define CAML_CPLUGINS_CLOSE 2 -#define CAML_CPLUGINS_STAT 3 -#define CAML_CPLUGINS_UNLINK 4 -#define CAML_CPLUGINS_RENAME 5 -#define CAML_CPLUGINS_CHDIR 6 -#define CAML_CPLUGINS_GETENV 7 -#define CAML_CPLUGINS_SYSTEM 8 -#define CAML_CPLUGINS_READ_DIRECTORY 9 -#define CAML_CPLUGINS_PRIMS_MAX 9 - -#define CAML_CPLUGINS_PRIMS_BITMAP ((1 << CAML_CPLUGINS_PRIMS_MAX)-1) - -extern intnat (*caml_cplugins_prim)(int,intnat,intnat,intnat); - -#define CAML_SYS_PRIM_1(code,prim,arg1) \ - (caml_cplugins_prim == NULL) ? prim(arg1) : \ - caml_cplugins_prim(code,(intnat) (arg1),0,0) -#define CAML_SYS_STRING_PRIM_1(code,prim,arg1) \ - (caml_cplugins_prim == NULL) ? prim(arg1) : \ - (char_os*)caml_cplugins_prim(code,(intnat) (arg1),0,0) -#define CAML_SYS_VOID_PRIM_1(code,prim,arg1) \ - (caml_cplugins_prim == NULL) ? prim(arg1) : \ - (void)caml_cplugins_prim(code,(intnat) (arg1),0,0) -#define CAML_SYS_PRIM_2(code,prim,arg1,arg2) \ - (caml_cplugins_prim == NULL) ? prim(arg1,arg2) : \ - caml_cplugins_prim(code,(intnat) (arg1), (intnat) (arg2),0) -#define CAML_SYS_PRIM_3(code,prim,arg1,arg2,arg3) \ - (caml_cplugins_prim == NULL) ? prim(arg1,arg2,arg3) : \ - caml_cplugins_prim(code,(intnat) (arg1), (intnat) (arg2),(intnat) (arg3)) - -#define CAML_SYS_EXIT(retcode) \ - CAML_SYS_VOID_PRIM_1(CAML_CPLUGINS_EXIT,exit,retcode) -#define CAML_SYS_OPEN(filename,flags,perm) \ - CAML_SYS_PRIM_3(CAML_CPLUGINS_OPEN,open_os,filename,flags,perm) -#define CAML_SYS_CLOSE(fd) \ - CAML_SYS_PRIM_1(CAML_CPLUGINS_CLOSE,close,fd) -#define CAML_SYS_STAT(filename,st) \ - CAML_SYS_PRIM_2(CAML_CPLUGINS_STAT,stat_os,filename,st) -#define CAML_SYS_UNLINK(filename) \ - CAML_SYS_PRIM_1(CAML_CPLUGINS_UNLINK,unlink_os,filename) -#define CAML_SYS_RENAME(old_name,new_name) \ - CAML_SYS_PRIM_2(CAML_CPLUGINS_RENAME,rename_os,old_name,new_name) -#define CAML_SYS_CHDIR(dirname) \ - CAML_SYS_PRIM_1(CAML_CPLUGINS_CHDIR,chdir_os,dirname) -#define CAML_SYS_GETENV(varname) \ - CAML_SYS_STRING_PRIM_1(CAML_CPLUGINS_GETENV,getenv,varname) -#define CAML_SYS_SYSTEM(command) \ - CAML_SYS_PRIM_1(CAML_CPLUGINS_SYSTEM,system_os,command) -#define CAML_SYS_READ_DIRECTORY(dirname,tbl) \ - CAML_SYS_PRIM_2(CAML_CPLUGINS_READ_DIRECTORY,caml_read_directory, \ - dirname,tbl) - -#define CAML_CPLUGIN_CONTEXT_API 0 - -struct cplugin_context { - int api_version; - int prims_bitmap; - char_os *exe_name; - char_os** argv; - char_os *plugin; /* absolute filename of plugin, do a copy if you need it ! */ - char *ocaml_version; -/* end of CAML_CPLUGIN_CONTEXT_API version 0 */ -}; - -extern void caml_cplugins_init(char_os * exe_name, char_os **argv); - -/* A plugin MUST define a symbol "caml_cplugin_init" with the prototype: - -void caml_cplugin_init(struct cplugin_context *ctx) -*/ - -/* to write plugins for CAML_SYS_READ_DIRECTORY, we will need the - definition of struct ext_table to be public. */ - -#endif /* CAML_WITH_CPLUGINS */ - -/* Data structures */ - -struct ext_table { - int size; - int capacity; - void ** contents; -}; - -extern void caml_ext_table_init(struct ext_table * tbl, int init_capa); -extern int caml_ext_table_add(struct ext_table * tbl, void * data); -extern void caml_ext_table_remove(struct ext_table * tbl, void * data); -extern void caml_ext_table_free(struct ext_table * tbl, int free_entries); -extern void caml_ext_table_clear(struct ext_table * tbl, int free_entries); - -CAMLextern int caml_read_directory(char_os * dirname, struct ext_table * contents); - -/* Deprecated aliases */ -#define caml_aligned_malloc caml_stat_alloc_aligned_noexc -#define caml_strdup caml_stat_strdup -#define caml_strconcat caml_stat_strconcat - -#ifdef CAML_INTERNALS - -/* GC flags and messages */ - -extern uintnat caml_verb_gc; -void caml_gc_message (int, char *, ...) -#ifdef __GNUC__ - __attribute__ ((format (printf, 2, 3))) -#endif -; - -/* Runtime warnings */ -extern uintnat caml_runtime_warnings; -int caml_runtime_warnings_active(void); - -#ifdef DEBUG -#ifdef ARCH_SIXTYFOUR -#define Debug_tag(x) (0xD700D7D7D700D6D7ul \ - | ((uintnat) (x) << 16) \ - | ((uintnat) (x) << 48)) -#else -#define Debug_tag(x) (0xD700D6D7ul | ((uintnat) (x) << 16)) -#endif /* ARCH_SIXTYFOUR */ - -/* - 00 -> free words in minor heap - 01 -> fields of free list blocks in major heap - 03 -> heap chunks deallocated by heap shrinking - 04 -> fields deallocated by [caml_obj_truncate] - 10 -> uninitialised fields of minor objects - 11 -> uninitialised fields of major objects - 15 -> uninitialised words of [caml_stat_alloc_aligned] blocks - 85 -> filler bytes of [caml_stat_alloc_aligned] - 99 -> the magic prefix of a memory block allocated by [caml_stat_alloc] - - special case (byte by byte): - D7 -> uninitialised words of [caml_stat_alloc] blocks -*/ -#define Debug_free_minor Debug_tag (0x00) -#define Debug_free_major Debug_tag (0x01) -#define Debug_free_shrink Debug_tag (0x03) -#define Debug_free_truncate Debug_tag (0x04) -#define Debug_uninit_minor Debug_tag (0x10) -#define Debug_uninit_major Debug_tag (0x11) -#define Debug_uninit_align Debug_tag (0x15) -#define Debug_filler_align Debug_tag (0x85) -#define Debug_pool_magic Debug_tag (0x99) - -#define Debug_uninit_stat 0xD7 - -/* Note: the first argument is in fact a [value] but we don't have this - type available yet because we can't include [mlvalues.h] in this file. -*/ -extern void caml_set_fields (intnat v, unsigned long, unsigned long); -#endif /* DEBUG */ - - -/* snprintf emulation for Win32 */ - -#if defined(_WIN32) && !defined(_UCRT) -extern int caml_snprintf(char * buf, size_t size, const char * format, ...); -#define snprintf caml_snprintf -#endif - -#ifdef CAML_INSTR -/* Timers and counters for GC latency profiling (Linux-only) */ - -#include -#include - -extern intnat caml_stat_minor_collections; -extern intnat CAML_INSTR_STARTTIME, CAML_INSTR_STOPTIME; - -struct CAML_INSTR_BLOCK { - struct timespec ts[10]; - char *tag[10]; - int index; - struct CAML_INSTR_BLOCK *next; -}; - -extern struct CAML_INSTR_BLOCK *CAML_INSTR_LOG; - -/* Declare a timer/counter name. [t] must be a new variable name. */ -#define CAML_INSTR_DECLARE(t) \ - struct CAML_INSTR_BLOCK *t = NULL - -/* Allocate the data block for a given name. - [t] must have been declared with [CAML_INSTR_DECLARE]. */ -#define CAML_INSTR_ALLOC(t) do{ \ - if (caml_stat_minor_collections >= CAML_INSTR_STARTTIME \ - && caml_stat_minor_collections < CAML_INSTR_STOPTIME){ \ - t = caml_stat_alloc_noexc (sizeof (struct CAML_INSTR_BLOCK)); \ - t->index = 0; \ - t->tag[0] = ""; \ - t->next = CAML_INSTR_LOG; \ - CAML_INSTR_LOG = t; \ - } \ - }while(0) - -/* Allocate the data block and start the timer. - [t] must have been declared with [CAML_INSTR_DECLARE] - and allocated with [CAML_INSTR_ALLOC]. */ -#define CAML_INSTR_START(t, msg) do{ \ - if (t != NULL){ \ - t->tag[0] = msg; \ - clock_gettime (CLOCK_REALTIME, &(t->ts[0])); \ - } \ - }while(0) - -/* Declare a timer, allocate its data, and start it. - [t] must be a new variable name. */ -#define CAML_INSTR_SETUP(t, msg) \ - CAML_INSTR_DECLARE (t); \ - CAML_INSTR_ALLOC (t); \ - CAML_INSTR_START (t, msg) - -/* Record an intermediate time within a given timer. - [t] must have been declared, allocated, and started. */ -#define CAML_INSTR_TIME(t, msg) do{ \ - if (t != NULL){ \ - ++ t->index; \ - t->tag[t->index] = (msg); \ - clock_gettime (CLOCK_REALTIME, &(t->ts[t->index])); \ - } \ - }while(0) - -/* Record an integer data point. - If [msg] ends with # it will be interpreted as an integer-valued event. - If it ends with @ it will be interpreted as an event counter. -*/ -#define CAML_INSTR_INT(msg, data) do{ \ - CAML_INSTR_SETUP (__caml_tmp, ""); \ - if (__caml_tmp != NULL){ \ - __caml_tmp->index = 1; \ - __caml_tmp->tag[1] = msg; \ - __caml_tmp->ts[1].tv_sec = 0; \ - __caml_tmp->ts[1].tv_nsec = (data); \ - } \ - }while(0) - -/* This function is called at the start of the program to set up - the data for the above macros. -*/ -extern void CAML_INSTR_INIT (void); - -/* This function is automatically called by the runtime to output - the collected data to the dump file. */ -extern void CAML_INSTR_ATEXIT (void); - -#else /* CAML_INSTR */ - -#define CAML_INSTR_DECLARE(t) /**/ -#define CAML_INSTR_ALLOC(t) /**/ -#define CAML_INSTR_START(t, name) /**/ -#define CAML_INSTR_SETUP(t, name) /**/ -#define CAML_INSTR_TIME(t, msg) /**/ -#define CAML_INSTR_INT(msg, c) /**/ -#define CAML_INSTR_INIT() /**/ -#define CAML_INSTR_ATEXIT() /**/ - -#endif /* CAML_INSTR */ - -#endif /* CAML_INTERNALS */ - -#ifdef __cplusplus -} -#endif - -#endif /* CAML_MISC_H */ diff --git a/byterun/caml/osdeps.h b/byterun/caml/osdeps.h deleted file mode 100644 index b65503d8..00000000 --- a/byterun/caml/osdeps.h +++ /dev/null @@ -1,152 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* Operating system - specific stuff */ - -#ifndef CAML_OSDEPS_H -#define CAML_OSDEPS_H - -#ifdef _WIN32 -extern unsigned short caml_win32_major; -extern unsigned short caml_win32_minor; -extern unsigned short caml_win32_build; -extern unsigned short caml_win32_revision; -#endif - -#ifdef CAML_INTERNALS - -#include "misc.h" -#include "memory.h" - -/* Read at most [n] bytes from file descriptor [fd] into buffer [buf]. - [flags] indicates whether [fd] is a socket - (bit [CHANNEL_FLAG_FROM_SOCKET] is set in this case, see [io.h]). - (This distinction matters for Win32, but not for Unix.) - Return number of bytes read. - In case of error, raises [Sys_error] or [Sys_blocked_io]. */ -extern int caml_read_fd(int fd, int flags, void * buf, int n); - -/* Write at most [n] bytes from buffer [buf] onto file descriptor [fd]. - [flags] indicates whether [fd] is a socket - (bit [CHANNEL_FLAG_FROM_SOCKET] is set in this case, see [io.h]). - (This distinction matters for Win32, but not for Unix.) - Return number of bytes written. - In case of error, raises [Sys_error] or [Sys_blocked_io]. */ -extern int caml_write_fd(int fd, int flags, void * buf, int n); - -/* Decompose the given path into a list of directories, and add them - to the given table. */ -extern char_os * caml_decompose_path(struct ext_table * tbl, char_os * path); - -/* Search the given file in the given list of directories. - If not found, return a copy of [name]. */ -extern char_os * caml_search_in_path(struct ext_table * path, const char_os * name); - -/* Same, but search an executable name in the system path for executables. */ -CAMLextern char_os * caml_search_exe_in_path(const char_os * name); - -/* Same, but search a shared library in the given path. */ -extern char_os * caml_search_dll_in_path(struct ext_table * path, const char_os * name); - -/* Open a shared library and return a handle on it. - If [for_execution] is true, perform full symbol resolution and - execute initialization code so that functions from the shared library - can be called. If [for_execution] is false, functions from this - shared library will not be called, but just checked for presence, - so symbol resolution can be skipped. - If [global] is true, symbols from the shared library can be used - to resolve for other libraries to be opened later on. - Return [NULL] on error. */ -extern void * caml_dlopen(char_os * libname, int for_execution, int global); - -/* Close a shared library handle */ -extern void caml_dlclose(void * handle); - -/* Look up the given symbol in the given shared library. - Return [NULL] if not found, or symbol value if found. */ -extern void * caml_dlsym(void * handle, const char * name); - -extern void * caml_globalsym(const char * name); - -/* Return an error message describing the most recent dynlink failure. */ -extern char * caml_dlerror(void); - -/* Add to [contents] the (short) names of the files contained in - the directory named [dirname]. No entries are added for [.] and [..]. - Return 0 on success, -1 on error; set errno in the case of error. */ -extern int caml_read_directory(char_os * dirname, struct ext_table * contents); - -/* Recover executable name if possible (/proc/sef/exe under Linux, - GetModuleFileName under Windows). Return NULL on error, - string allocated with [caml_stat_alloc] on success. */ -extern char_os * caml_executable_name(void); - -/* Secure version of [getenv]: returns NULL if the process has special - privileges (setuid bit, setgid bit, capabilities). -*/ -extern char_os *caml_secure_getenv(char_os const *var); - -/* If [fd] refers to a terminal or console, return the number of rows - (lines) that it displays. Otherwise, or if the number of rows - cannot be determined, return -1. */ -extern int caml_num_rows_fd(int fd); - -#ifdef _WIN32 - -extern int caml_win32_rename(const wchar_t *, const wchar_t *); - -extern void caml_probe_win32_version(void); -extern void caml_setup_win32_terminal(void); -extern void caml_restore_win32_terminal(void); - -extern wchar_t *caml_win32_getenv(wchar_t const *); - -/* Windows Unicode support */ - -extern int win_multi_byte_to_wide_char(const char* s, int slen, wchar_t *out, int outlen); -extern int win_wide_char_to_multi_byte(const wchar_t* s, int slen, char *out, int outlen); - -/* [caml_stat_strdup_to_utf16(s)] returns a NULL-terminated copy of [s], - re-encoded in UTF-16. The encoding of [s] is assumed to be UTF-8 if - [caml_windows_unicode_runtime_enabled] is non-zero **and** [s] is valid - UTF-8, or the current Windows code page otherwise. - - The returned string is allocated with [caml_stat_alloc], so it should be free - using [caml_stat_free]. -*/ -extern wchar_t* caml_stat_strdup_to_utf16(const char *s); - -/* [caml_stat_strdup_of_utf16(s)] returns a NULL-terminated copy of [s], - re-encoded in UTF-8 if [caml_windows_unicode_runtime_enabled] is non-zero or - the current Windows code page otherwise. - - The returned string is allocated with [caml_stat_alloc], so it should be free - using [caml_stat_free]. -*/ -extern char* caml_stat_strdup_of_utf16(const wchar_t *s); - -/* [caml_copy_string_of_utf16(s)] returns an OCaml string containing a copy of - [s] re-encoded in UTF-8 if [caml_windows_unicode_runtime_enabled] is non-zero - or in the current code page otherwise. -*/ -extern value caml_copy_string_of_utf16(const wchar_t *s); - -extern int caml_win32_isatty(int fd); - -#endif /* _WIN32 */ - -#endif /* CAML_INTERNALS */ - -#endif /* CAML_OSDEPS_H */ diff --git a/byterun/caml/signals.h b/byterun/caml/signals.h deleted file mode 100644 index 99924e4f..00000000 --- a/byterun/caml/signals.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#ifndef CAML_SIGNALS_H -#define CAML_SIGNALS_H - -#ifndef CAML_NAME_SPACE -#include "compatibility.h" -#endif -#include "misc.h" -#include "mlvalues.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef CAML_INTERNALS -CAMLextern intnat volatile caml_signals_are_pending; -CAMLextern intnat volatile caml_pending_signals[]; -CAMLextern int volatile caml_something_to_do; -extern int volatile caml_requested_major_slice; -extern int volatile caml_requested_minor_gc; - -void caml_request_major_slice (void); -void caml_request_minor_gc (void); -CAMLextern int caml_convert_signal_number (int); -CAMLextern int caml_rev_convert_signal_number (int); -void caml_execute_signal(int signal_number, int in_signal_handler); -void caml_record_signal(int signal_number); -void caml_process_pending_signals(void); -void caml_process_event(void); -int caml_set_signal_action(int signo, int action); - -CAMLextern void (*caml_enter_blocking_section_hook)(void); -CAMLextern void (*caml_leave_blocking_section_hook)(void); -CAMLextern int (*caml_try_leave_blocking_section_hook)(void); -CAMLextern void (* volatile caml_async_action_hook)(void); -#endif /* CAML_INTERNALS */ - -CAMLextern void caml_enter_blocking_section (void); -CAMLextern void caml_leave_blocking_section (void); - -#ifdef __cplusplus -} -#endif - -#endif /* CAML_SIGNALS_H */ diff --git a/byterun/caml/stack.h b/byterun/caml/stack.h deleted file mode 100644 index 26686398..00000000 --- a/byterun/caml/stack.h +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* Machine-dependent interface with the asm code */ - -#ifndef CAML_STACK_H -#define CAML_STACK_H - -#ifdef CAML_INTERNALS - -/* Macros to access the stack frame */ - -#ifdef TARGET_i386 -#define Saved_return_address(sp) *((intnat *)((sp) - 4)) -#ifndef SYS_win32 -#define Callback_link(sp) ((struct caml_context *)((sp) + 16)) -#else -#define Callback_link(sp) ((struct caml_context *)((sp) + 8)) -#endif -#endif - -#ifdef TARGET_power -#if defined(MODEL_ppc) -#define Saved_return_address(sp) *((intnat *)((sp) - 4)) -#define Callback_link(sp) ((struct caml_context *)((sp) + 16)) -#elif defined(MODEL_ppc64) -#define Saved_return_address(sp) *((intnat *)((sp) + 16)) -#define Callback_link(sp) ((struct caml_context *)((sp) + (48 + 32))) -#elif defined(MODEL_ppc64le) -#define Saved_return_address(sp) *((intnat *)((sp) + 16)) -#define Callback_link(sp) ((struct caml_context *)((sp) + (32 + 32))) -#else -#error "TARGET_power: wrong MODEL" -#endif -#define Already_scanned(sp, retaddr) ((retaddr) & 1) -#define Mask_already_scanned(retaddr) ((retaddr) & ~1) -#define Mark_scanned(sp, retaddr) Saved_return_address(sp) = (retaddr) | 1 -#endif - -#ifdef TARGET_s390x -#define Saved_return_address(sp) *((intnat *)((sp) - SIZEOF_PTR)) -#define Trap_frame_size 16 -#define Callback_link(sp) ((struct caml_context *)((sp) + Trap_frame_size)) -#endif - -#ifdef TARGET_arm -#define Saved_return_address(sp) *((intnat *)((sp) - 4)) -#define Callback_link(sp) ((struct caml_context *)((sp) + 8)) -#endif - -#ifdef TARGET_amd64 -#define Saved_return_address(sp) *((intnat *)((sp) - 8)) -#define Callback_link(sp) ((struct caml_context *)((sp) + 16)) -#endif - -#ifdef TARGET_arm64 -#define Saved_return_address(sp) *((intnat *)((sp) - 8)) -#define Callback_link(sp) ((struct caml_context *)((sp) + 16)) -#endif - -/* Structure of OCaml callback contexts */ - -struct caml_context { - char * bottom_of_stack; /* beginning of OCaml stack chunk */ - uintnat last_retaddr; /* last return address in OCaml code */ - value * gc_regs; /* pointer to register block */ -#ifdef WITH_SPACETIME - void* trie_node; -#endif -}; - -/* Structure of frame descriptors */ - -typedef struct { - uintnat retaddr; - unsigned short frame_size; - unsigned short num_live; - unsigned short live_ofs[1]; -} frame_descr; - -/* Hash table of frame descriptors */ - -extern frame_descr ** caml_frame_descriptors; -extern int caml_frame_descriptors_mask; - -#define Hash_retaddr(addr) \ - (((uintnat)(addr) >> 3) & caml_frame_descriptors_mask) - -extern void caml_init_frame_descriptors(void); -extern void caml_register_frametable(intnat *); -extern void caml_unregister_frametable(intnat *); -extern void caml_register_dyn_global(void *); - -extern uintnat caml_stack_usage (void); -extern uintnat (*caml_stack_usage_hook)(void); - -/* Declaration of variables used in the asm code */ -extern char * caml_top_of_stack; -extern char * caml_bottom_of_stack; -extern uintnat caml_last_return_address; -extern value * caml_gc_regs; -extern char * caml_exception_pointer; -extern value * caml_globals[]; -extern char caml_globals_map[]; -extern intnat caml_globals_inited; -extern intnat * caml_frametable[]; - -CAMLextern frame_descr * caml_next_frame_descriptor(uintnat * pc, char ** sp); - -#endif /* CAML_INTERNALS */ - -#endif /* CAML_STACK_H */ diff --git a/byterun/caml/startup.h b/byterun/caml/startup.h deleted file mode 100644 index 2b26e916..00000000 --- a/byterun/caml/startup.h +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#ifndef CAML_STARTUP_H -#define CAML_STARTUP_H - -#ifdef CAML_INTERNALS - -#include "mlvalues.h" -#include "exec.h" - -CAMLextern void caml_main(char_os **argv); - -CAMLextern void caml_startup_code( - code_t code, asize_t code_size, - char *data, asize_t data_size, - char *section_table, asize_t section_table_size, - int pooling, - char_os **argv); - -CAMLextern value caml_startup_code_exn( - code_t code, asize_t code_size, - char *data, asize_t data_size, - char *section_table, asize_t section_table_size, - int pooling, - char_os **argv); - -enum { FILE_NOT_FOUND = -1, BAD_BYTECODE = -2 }; - -extern int caml_attempt_open(char_os **name, struct exec_trailer *trail, - int do_open_script); -extern void caml_read_section_descriptors(int fd, struct exec_trailer *trail); -extern int32_t caml_seek_optional_section(int fd, struct exec_trailer *trail, - char *name); -extern int32_t caml_seek_section(int fd, struct exec_trailer *trail, - char *name); - -#endif /* CAML_INTERNALS */ - -#endif /* CAML_STARTUP_H */ diff --git a/byterun/caml/startup_aux.h b/byterun/caml/startup_aux.h deleted file mode 100644 index 7286bc98..00000000 --- a/byterun/caml/startup_aux.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, Jane Street Group, LLC */ -/* */ -/* Copyright 2015 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#ifndef CAML_STARTUP_AUX_H -#define CAML_STARTUP_AUX_H - -#ifdef CAML_INTERNALS - -#include "config.h" - -extern void caml_init_atom_table (void); - -extern uintnat caml_init_percent_free; -extern uintnat caml_init_max_percent_free; -extern uintnat caml_init_minor_heap_wsz; -extern uintnat caml_init_heap_chunk_sz; -extern uintnat caml_init_heap_wsz; -extern uintnat caml_init_max_stack_wsz; -extern uintnat caml_init_major_window; -extern uintnat caml_trace_level; -extern uintnat caml_cleanup_on_exit; - -extern void caml_parse_ocamlrunparam (void); - -/* Common entry point to caml_startup. - Returns 0 if the runtime is already initialized. - If [pooling] is 0, [caml_stat_*] functions will not be backed by a pool. */ -extern int caml_startup_aux (int pooling); - -#endif /* CAML_INTERNALS */ - -#endif /* CAML_STARTUP_AUX_H */ diff --git a/byterun/caml/sys.h b/byterun/caml/sys.h deleted file mode 100644 index 0f372771..00000000 --- a/byterun/caml/sys.h +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#ifndef CAML_SYS_H -#define CAML_SYS_H - -#ifdef CAML_INTERNALS - -#include "misc.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define NO_ARG Val_int(0) - -CAMLextern void caml_sys_error (value); -CAMLextern void caml_sys_io_error (value); -CAMLextern double caml_sys_time_unboxed(value); -CAMLextern void caml_sys_init (char_os * exe_name, char_os ** argv); -CAMLextern value caml_sys_exit (value); -extern double caml_sys_time_unboxed(value); -CAMLextern value caml_sys_get_argv(value unit); - -extern char_os * caml_exe_name; - -#ifdef __cplusplus -} -#endif - -#endif /* CAML_INTERNALS */ - -#endif /* CAML_SYS_H */ diff --git a/byterun/caml/weak.h b/byterun/caml/weak.h deleted file mode 100644 index a8563867..00000000 --- a/byterun/caml/weak.h +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1997 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* Operations on weak arrays */ - -#ifndef CAML_WEAK_H -#define CAML_WEAK_H - -#ifdef CAML_INTERNALS - -#include "mlvalues.h" - -extern value caml_ephe_list_head; -extern value caml_ephe_none; - - -/** The first field 0: weak list; - second field 1: data; - others 2..: keys; - - A weak pointer is an ephemeron with the data at caml_ephe_none - If fields are added, don't forget to update weak.ml [additional_values]. - */ - -#define CAML_EPHE_LINK_OFFSET 0 -#define CAML_EPHE_DATA_OFFSET 1 -#define CAML_EPHE_FIRST_KEY 2 - - -/* In the header, in order to let major_gc.c - and weak.c see the body of the function */ -static inline void caml_ephe_clean (value v){ - value child; - int release_data = 0; - mlsize_t size, i; - header_t hd; - CAMLassert(caml_gc_phase == Phase_clean); - - hd = Hd_val (v); - size = Wosize_hd (hd); - for (i = 2; i < size; i++){ - child = Field (v, i); - ephemeron_again: - if (child != caml_ephe_none - && Is_block (child) && Is_in_heap_or_young (child)){ - if (Tag_val (child) == Forward_tag){ - value f = Forward_val (child); - if (Is_block (f)) { - if (!Is_in_value_area(f) || Tag_val (f) == Forward_tag - || Tag_val (f) == Lazy_tag || Tag_val (f) == Double_tag){ - /* Do not short-circuit the pointer. */ - }else{ - Field (v, i) = child = f; - if (Is_block (f) && Is_young (f)) - add_to_ephe_ref_table(&caml_ephe_ref_table, v, i); - goto ephemeron_again; - } - } - } - if (Is_white_val (child) && !Is_young (child)){ - release_data = 1; - Field (v, i) = caml_ephe_none; - } - } - } - - child = Field (v, 1); - if(child != caml_ephe_none){ - if (release_data){ - Field (v, 1) = caml_ephe_none; - } else { - /* The mark phase must have marked it */ - CAMLassert( !(Is_block (child) && Is_in_heap (child) - && Is_white_val (child)) ); - } - } -} - -#endif /* CAML_INTERNALS */ - -#endif /* CAML_WEAK_H */ diff --git a/byterun/compact.c b/byterun/compact.c deleted file mode 100644 index 7b7188ab..00000000 --- a/byterun/compact.c +++ /dev/null @@ -1,562 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -#include - -#include "caml/address_class.h" -#include "caml/config.h" -#include "caml/finalise.h" -#include "caml/freelist.h" -#include "caml/gc.h" -#include "caml/gc_ctrl.h" -#include "caml/major_gc.h" -#include "caml/memory.h" -#include "caml/mlvalues.h" -#include "caml/roots.h" -#include "caml/weak.h" -#include "caml/compact.h" - -extern uintnat caml_percent_free; /* major_gc.c */ -extern void caml_shrink_heap (char *); /* memory.c */ - -/* Encoded headers: the color is stored in the 2 least significant bits. - (For pointer inversion, we need to distinguish headers from pointers.) - s is a Wosize, t is a tag, and c is a color (a two-bit number) - - For the purpose of compaction, "colors" are: - 0: pointers (direct or inverted) - 1: integer or (unencoded) infix header - 2: inverted pointer for infix header - 3: integer or encoded (noninfix) header - - XXX Should be fixed: - XXX The above assumes that all roots are aligned on a 4-byte boundary, - XXX which is not always guaranteed by C. - XXX (see [caml_register_global_roots]) - XXX Should be able to fix it to only assume 2-byte alignment. -*/ -#ifdef WITH_PROFINFO -#define Make_ehd(s,t,c,p) \ - (((s) << 10) | (t) << 2 | (c) | ((p) << PROFINFO_SHIFT)) -#else -#define Make_ehd(s,t,c,p) (((s) << 10) | (t) << 2 | (c)) -#endif -#define Whsize_ehd(h) Whsize_hd (h) -#define Wosize_ehd(h) Wosize_hd (h) -#define Tag_ehd(h) (((h) >> 2) & 0xFF) -#define Profinfo_ehd(hd) Profinfo_hd(hd) -#define Ecolor(w) ((w) & 3) - -typedef uintnat word; - -static void invert_pointer_at (word *p) -{ - word q = *p; - CAMLassert (Ecolor ((intnat) p) == 0); - - /* Use Ecolor (q) == 0 instead of Is_block (q) because q could be an - inverted pointer for an infix header (with Ecolor == 2). */ - if (Ecolor (q) == 0 && Is_in_heap (q)){ - switch (Ecolor (Hd_val (q))){ - case 0: - case 3: /* Pointer or header: insert in inverted list. */ - *p = Hd_val (q); - Hd_val (q) = (header_t) p; - break; - case 1: /* Infix header: make inverted infix list. */ - /* Double inversion: the last of the inverted infix list points to - the next infix header in this block. The last of the last list - contains the original block header. */ - { - /* This block as a value. */ - value val = (value) q - Infix_offset_val (q); - /* Get the block header. */ - word *hp = (word *) Hp_val (val); - - while (Ecolor (*hp) == 0) hp = (word *) *hp; - CAMLassert (Ecolor (*hp) == 3); - if (Tag_ehd (*hp) == Closure_tag){ - /* This is the first infix found in this block. */ - /* Save original header. */ - *p = *hp; - /* Link inverted infix list. */ - Hd_val (q) = (header_t) ((word) p | 2); - /* Change block header's tag to Infix_tag, and change its size - to point to the infix list. */ - *hp = Make_ehd (Wosize_bhsize (q - val), Infix_tag, 3, (uintnat) 0); - }else{ - CAMLassert (Tag_ehd (*hp) == Infix_tag); - /* Point the last of this infix list to the current first infix - list of the block. */ - *p = (word) &Field (val, Wosize_ehd (*hp)) | 1; - /* Point the head of this infix list to the above. */ - Hd_val (q) = (header_t) ((word) p | 2); - /* Change block header's size to point to this infix list. */ - *hp = Make_ehd (Wosize_bhsize (q - val), Infix_tag, 3, (uintnat) 0); - } - } - break; - case 2: /* Inverted infix list: insert. */ - *p = Hd_val (q); - Hd_val (q) = (header_t) ((word) p | 2); - break; - } - } -} - -void caml_invert_root (value v, value *p) -{ - invert_pointer_at ((word *) p); -} - -static char *compact_fl; - -static void init_compact_allocate (void) -{ - char *ch = caml_heap_start; - while (ch != NULL){ - Chunk_alloc (ch) = 0; - ch = Chunk_next (ch); - } - compact_fl = caml_heap_start; -} - -/* [size] is a number of bytes and includes the header size */ -static char *compact_allocate (mlsize_t size) -{ - char *chunk, *adr; - - while (Chunk_size (compact_fl) - Chunk_alloc (compact_fl) <= Bhsize_wosize (3) - && Chunk_size (Chunk_next (compact_fl)) - - Chunk_alloc (Chunk_next (compact_fl)) - <= Bhsize_wosize (3)){ - compact_fl = Chunk_next (compact_fl); - } - chunk = compact_fl; - while (Chunk_size (chunk) - Chunk_alloc (chunk) < size){ - chunk = Chunk_next (chunk); - CAMLassert (chunk != NULL); - } - adr = chunk + Chunk_alloc (chunk); - Chunk_alloc (chunk) += size; - return adr; -} - -static void do_compaction (void) -{ - char *ch, *chend; - CAMLassert (caml_gc_phase == Phase_idle); - caml_gc_message (0x10, "Compacting heap...\n"); - -#ifdef DEBUG - caml_heap_check (); -#endif - - /* First pass: encode all noninfix headers. */ - { - ch = caml_heap_start; - while (ch != NULL){ - header_t *p = (header_t *) ch; - - chend = ch + Chunk_size (ch); - while ((char *) p < chend){ - header_t hd = Hd_hp (p); - mlsize_t sz = Wosize_hd (hd); - - if (Is_blue_hd (hd)){ - /* Free object. Give it a string tag. */ - Hd_hp (p) = Make_ehd (sz, String_tag, 3, (uintnat) 0); - }else{ - CAMLassert (Is_white_hd (hd)); - /* Live object. Keep its tag. */ - Hd_hp (p) = Make_ehd (sz, Tag_hd (hd), 3, Profinfo_hd (hd)); - } - p += Whsize_wosize (sz); - } - ch = Chunk_next (ch); - } - } - - - /* Second pass: invert pointers. - Link infix headers in each block in an inverted list of inverted lists. - Don't forget roots and weak pointers. */ - { - /* Invert roots first because the threads library needs some heap - data structures to find its roots. Fortunately, it doesn't need - the headers (see above). */ - caml_do_roots (caml_invert_root, 1); - /* The values to be finalised are not roots but should still be inverted */ - caml_final_invert_finalisable_values (); - - ch = caml_heap_start; - while (ch != NULL){ - word *p = (word *) ch; - chend = ch + Chunk_size (ch); - - while ((char *) p < chend){ - word q = *p; - size_t sz, i; - tag_t t; - word *infixes; - - while (Ecolor (q) == 0) q = * (word *) q; - sz = Whsize_ehd (q); - t = Tag_ehd (q); - - if (t == Infix_tag){ - /* Get the original header of this block. */ - infixes = p + sz; - q = *infixes; - while (Ecolor (q) != 3) q = * (word *) (q & ~(uintnat)3); - sz = Whsize_ehd (q); - t = Tag_ehd (q); - } - - if (t < No_scan_tag){ - for (i = 1; i < sz; i++) invert_pointer_at (&(p[i])); - } - p += sz; - } - ch = Chunk_next (ch); - } - /* Invert weak pointers. */ - { - value *pp = &caml_ephe_list_head; - value p; - word q; - size_t sz, i; - - while (1){ - p = *pp; - if (p == (value) NULL) break; - q = Hd_val (p); - while (Ecolor (q) == 0) q = * (word *) q; - sz = Wosize_ehd (q); - for (i = 1; i < sz; i++){ - if (Field (p,i) != caml_ephe_none){ - invert_pointer_at ((word *) &(Field (p,i))); - } - } - invert_pointer_at ((word *) pp); - pp = &Field (p, 0); - } - } - } - - - /* Third pass: reallocate virtually; revert pointers; decode headers. - Rebuild infix headers. */ - { - init_compact_allocate (); - ch = caml_heap_start; - while (ch != NULL){ - word *p = (word *) ch; - - chend = ch + Chunk_size (ch); - while ((char *) p < chend){ - word q = *p; - - if (Ecolor (q) == 0 || Tag_ehd (q) == Infix_tag){ - /* There were (normal or infix) pointers to this block. */ - size_t sz; - tag_t t; - char *newadr; -#ifdef WITH_PROFINFO - uintnat profinfo; -#endif - word *infixes = NULL; - - while (Ecolor (q) == 0) q = * (word *) q; - sz = Whsize_ehd (q); - t = Tag_ehd (q); -#ifdef WITH_PROFINFO - profinfo = Profinfo_ehd (q); -#endif - if (t == Infix_tag){ - /* Get the original header of this block. */ - infixes = p + sz; - q = *infixes; - CAMLassert (Ecolor (q) == 2); - while (Ecolor (q) != 3) q = * (word *) (q & ~(uintnat)3); - sz = Whsize_ehd (q); - t = Tag_ehd (q); - } - - newadr = compact_allocate (Bsize_wsize (sz)); - q = *p; - while (Ecolor (q) == 0){ - word next = * (word *) q; - * (word *) q = (word) Val_hp (newadr); - q = next; - } - *p = Make_header_with_profinfo (Wosize_whsize (sz), t, Caml_white, - profinfo); - - if (infixes != NULL){ - /* Rebuild the infix headers and revert the infix pointers. */ - while (Ecolor ((word) infixes) != 3){ - infixes = (word *) ((word) infixes & ~(uintnat) 3); - q = *infixes; - while (Ecolor (q) == 2){ - word next; - q = (word) q & ~(uintnat) 3; - next = * (word *) q; - * (word *) q = (word) Val_hp ((word *) newadr + (infixes - p)); - q = next; - } - CAMLassert (Ecolor (q) == 1 || Ecolor (q) == 3); - /* No need to preserve any profinfo value on the [Infix_tag] - headers; the Spacetime profiling heap snapshot code doesn't - look at them. */ - *infixes = Make_header (infixes - p, Infix_tag, Caml_white); - infixes = (word *) q; - } - } - p += sz; - }else{ - CAMLassert (Ecolor (q) == 3); - /* This is guaranteed only if caml_compact_heap was called after a - nonincremental major GC: CAMLassert (Tag_ehd (q) == String_tag); - */ - /* No pointers to the header and no infix header: - the object was free. */ - *p = Make_header (Wosize_ehd (q), Tag_ehd (q), Caml_blue); - p += Whsize_ehd (q); - } - } - ch = Chunk_next (ch); - } - } - - - /* Fourth pass: reallocate and move objects. - Use the exact same allocation algorithm as pass 3. */ - { - init_compact_allocate (); - ch = caml_heap_start; - while (ch != NULL){ - word *p = (word *) ch; - - chend = ch + Chunk_size (ch); - while ((char *) p < chend){ - word q = *p; - if (Color_hd (q) == Caml_white){ - size_t sz = Bhsize_hd (q); - char *newadr = compact_allocate (sz); - memmove (newadr, p, sz); - p += Wsize_bsize (sz); - }else{ - CAMLassert (Color_hd (q) == Caml_blue); - p += Whsize_hd (q); - } - } - ch = Chunk_next (ch); - } - } - - /* Shrink the heap if needed. */ - { - /* Find the amount of live data and the unshrinkable free space. */ - asize_t live = 0; - asize_t free = 0; - asize_t wanted; - - ch = caml_heap_start; - while (ch != NULL){ - if (Chunk_alloc (ch) != 0){ - live += Wsize_bsize (Chunk_alloc (ch)); - free += Wsize_bsize (Chunk_size (ch) - Chunk_alloc (ch)); - } - ch = Chunk_next (ch); - } - - /* Add up the empty chunks until there are enough, then remove the - other empty chunks. */ - wanted = caml_percent_free * (live / 100 + 1); - ch = caml_heap_start; - while (ch != NULL){ - char *next_chunk = Chunk_next (ch); /* Chunk_next (ch) will be erased */ - - if (Chunk_alloc (ch) == 0){ - if (free < wanted){ - free += Wsize_bsize (Chunk_size (ch)); - }else{ - caml_shrink_heap (ch); - } - } - ch = next_chunk; - } - } - - /* Rebuild the free list. */ - { - ch = caml_heap_start; - caml_fl_reset (); - while (ch != NULL){ - if (Chunk_size (ch) > Chunk_alloc (ch)){ - caml_make_free_blocks ((value *) (ch + Chunk_alloc (ch)), - Wsize_bsize (Chunk_size(ch)-Chunk_alloc(ch)), 1, - Caml_white); - } - ch = Chunk_next (ch); - } - } - ++ caml_stat_compactions; - caml_gc_message (0x10, "done.\n"); -} - -uintnat caml_percent_max; /* used in gc_ctrl.c and memory.c */ - -void caml_compact_heap (void) -{ - uintnat target_wsz, live; - CAML_INSTR_SETUP(tmr, "compact"); - - CAMLassert (caml_young_ptr == caml_young_alloc_end); - CAMLassert (caml_ref_table.ptr == caml_ref_table.base); - CAMLassert (caml_ephe_ref_table.ptr == caml_ephe_ref_table.base); - CAMLassert (caml_custom_table.ptr == caml_custom_table.base); - - do_compaction (); - CAML_INSTR_TIME (tmr, "compact/main"); - /* Compaction may fail to shrink the heap to a reasonable size - because it deals in complete chunks: if a very large chunk - is at the beginning of the heap, everything gets moved to - it and it is not freed. - - In that case, we allocate a new chunk of the desired heap - size, chain it at the beginning of the heap (thus pretending - its address is smaller), and launch a second compaction. - This will move all data to this new chunk and free the - very large chunk. - - See PR#5389 - */ - /* We compute: - freewords = caml_fl_cur_wsz (exact) - heapwords = Wsize_bsize (caml_heap_size) (exact) - live = heapwords - freewords - wanted = caml_percent_free * (live / 100 + 1) (same as in do_compaction) - target_wsz = live + wanted - We add one page to make sure a small difference in counting sizes - won't make [do_compaction] keep the second block (and break all sorts - of invariants). - - We recompact if target_wsz < heap_size / 2 - */ - live = caml_stat_heap_wsz - caml_fl_cur_wsz; - target_wsz = live + caml_percent_free * (live / 100 + 1) - + Wsize_bsize (Page_size); - target_wsz = caml_clip_heap_chunk_wsz (target_wsz); - -#ifdef HAS_HUGE_PAGES - if (caml_use_huge_pages - && Bsize_wsize (caml_stat_heap_wsz) <= HUGE_PAGE_SIZE) - return; -#endif - - if (target_wsz < caml_stat_heap_wsz / 2){ - /* Recompact. */ - char *chunk; - - caml_gc_message (0x10, "Recompacting heap (target=%" - ARCH_INTNAT_PRINTF_FORMAT "uk words)\n", - target_wsz / 1024); - - chunk = caml_alloc_for_heap (Bsize_wsize (target_wsz)); - if (chunk == NULL) return; - /* PR#5757: we need to make the new blocks blue, or they won't be - recognized as free by the recompaction. */ - caml_make_free_blocks ((value *) chunk, - Wsize_bsize (Chunk_size (chunk)), 0, Caml_blue); - if (caml_page_table_add (In_heap, chunk, chunk + Chunk_size (chunk)) != 0){ - caml_free_for_heap (chunk); - return; - } - Chunk_next (chunk) = caml_heap_start; - caml_heap_start = chunk; - ++ caml_stat_heap_chunks; - caml_stat_heap_wsz += Wsize_bsize (Chunk_size (chunk)); - if (caml_stat_heap_wsz > caml_stat_top_heap_wsz){ - caml_stat_top_heap_wsz = caml_stat_heap_wsz; - } - do_compaction (); - CAMLassert (caml_stat_heap_chunks == 1); - CAMLassert (Chunk_next (caml_heap_start) == NULL); - CAMLassert (caml_stat_heap_wsz == Wsize_bsize (Chunk_size (chunk))); - CAML_INSTR_TIME (tmr, "compact/recompact"); - } -} - -void caml_compact_heap_maybe (void) -{ - /* Estimated free+garbage words in the heap: - FW = fl_size_at_phase_change + 3 * (caml_fl_cur_wsz - - caml_fl_wsz_at_phase_change) - FW = 3 * caml_fl_cur_wsz - 2 * caml_fl_wsz_at_phase_change - Estimated live words: LW = caml_stat_heap_wsz - FW - Estimated free percentage: FP = 100 * FW / LW - We compact the heap if FP > caml_percent_max - */ - float fw, fp; - CAMLassert (caml_gc_phase == Phase_idle); - if (caml_percent_max >= 1000000) return; - if (caml_stat_major_collections < 3) return; - if (caml_stat_heap_wsz <= 2 * caml_clip_heap_chunk_wsz (0)) return; - -#ifdef HAS_HUGE_PAGES - if (caml_use_huge_pages - && Bsize_wsize (caml_stat_heap_wsz) <= HUGE_PAGE_SIZE) - return; -#endif - - fw = 3.0 * caml_fl_cur_wsz - 2.0 * caml_fl_wsz_at_phase_change; - if (fw < 0) fw = caml_fl_cur_wsz; - - if (fw >= caml_stat_heap_wsz){ - fp = 1000000.0; - }else{ - fp = 100.0 * fw / (caml_stat_heap_wsz - fw); - if (fp > 1000000.0) fp = 1000000.0; - } - caml_gc_message (0x200, "FL size at phase change = %" - ARCH_INTNAT_PRINTF_FORMAT "u words\n", - (uintnat) caml_fl_wsz_at_phase_change); - caml_gc_message (0x200, "FL current size = %" - ARCH_INTNAT_PRINTF_FORMAT "u words\n", - (uintnat) caml_fl_cur_wsz); - caml_gc_message (0x200, "Estimated overhead = %" - ARCH_INTNAT_PRINTF_FORMAT "u%%\n", - (uintnat) fp); - if (fp >= caml_percent_max){ - caml_gc_message (0x200, "Automatic compaction triggered.\n"); - caml_empty_minor_heap (); /* minor heap must be empty for compaction */ - caml_finish_major_cycle (); - - fw = caml_fl_cur_wsz; - fp = 100.0 * fw / (caml_stat_heap_wsz - fw); - caml_gc_message (0x200, "Measured overhead: %" - ARCH_INTNAT_PRINTF_FORMAT "u%%\n", - (uintnat) fp); - if (fp >= caml_percent_max) - caml_compact_heap (); - else - caml_gc_message (0x200, "Automatic compaction aborted.\n"); - - } -} diff --git a/byterun/compare.c b/byterun/compare.c deleted file mode 100644 index 382c9dff..00000000 --- a/byterun/compare.c +++ /dev/null @@ -1,363 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -#include -#include -#include "caml/custom.h" -#include "caml/fail.h" -#include "caml/memory.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" - -#if defined(LACKS_SANE_NAN) && !defined(isnan) -#define isnan _isnan -#endif - -/* Structural comparison on trees. */ - -struct compare_item { value * v1, * v2; mlsize_t count; }; - -#define COMPARE_STACK_INIT_SIZE 8 -#define COMPARE_STACK_MIN_ALLOC_SIZE 32 -#define COMPARE_STACK_MAX_SIZE (1024*1024) -CAMLexport int caml_compare_unordered; - -struct compare_stack { - struct compare_item init_stack[COMPARE_STACK_INIT_SIZE]; - struct compare_item* stack; - struct compare_item* limit; -}; - -/* Free the compare stack if needed */ -static void compare_free_stack(struct compare_stack* stk) -{ - if (stk->stack != stk->init_stack) { - caml_stat_free(stk->stack); - stk->stack = NULL; - } -} - -/* Same, then raise Out_of_memory */ -static void compare_stack_overflow(struct compare_stack* stk) -{ - caml_gc_message (0x04, "Stack overflow in structural comparison\n"); - compare_free_stack(stk); - caml_raise_out_of_memory(); -} - -/* Grow the compare stack */ -static struct compare_item * compare_resize_stack(struct compare_stack* stk, - struct compare_item * sp) -{ - asize_t newsize; - asize_t sp_offset = sp - stk->stack; - struct compare_item * newstack; - - if (stk->stack == stk->init_stack) { - newsize = COMPARE_STACK_MIN_ALLOC_SIZE; - newstack = caml_stat_alloc_noexc(sizeof(struct compare_item) * newsize); - if (newstack == NULL) compare_stack_overflow(stk); - memcpy(newstack, stk->init_stack, - sizeof(struct compare_item) * COMPARE_STACK_INIT_SIZE); - } else { - newsize = 2 * (stk->limit - stk->stack); - if (newsize >= COMPARE_STACK_MAX_SIZE) compare_stack_overflow(stk); - newstack = caml_stat_resize_noexc(stk->stack, - sizeof(struct compare_item) * newsize); - if (newstack == NULL) compare_stack_overflow(stk); - } - stk->stack = newstack; - stk->limit = newstack + newsize; - return newstack + sp_offset; -} - - -static intnat do_compare_val(struct compare_stack* stk, - value v1, value v2, int total); - -static intnat compare_val(value v1, value v2, int total) -{ - struct compare_stack stk; - intnat res; - stk.stack = stk.init_stack; - stk.limit = stk.stack + COMPARE_STACK_INIT_SIZE; - res = do_compare_val(&stk, v1, v2, total); - compare_free_stack(&stk); - return res; -} - -/* Structural comparison */ - - -#define LESS -1 -#define EQUAL 0 -#define GREATER 1 -#define UNORDERED ((intnat)1 << (8 * sizeof(value) - 1)) - -/* The return value of compare_val is as follows: - > 0 v1 is greater than v2 - 0 v1 is equal to v2 - < 0 and > UNORDERED v1 is less than v2 - UNORDERED v1 and v2 cannot be compared */ - -static intnat do_compare_val(struct compare_stack* stk, - value v1, value v2, int total) -{ - struct compare_item * sp; - tag_t t1, t2; - - sp = stk->stack; - while (1) { - if (v1 == v2 && total) goto next_item; - if (Is_long(v1)) { - if (v1 == v2) goto next_item; - if (Is_long(v2)) - return Long_val(v1) - Long_val(v2); - /* Subtraction above cannot overflow and cannot result in UNORDERED */ - if (Is_in_value_area(v2)) { - switch (Tag_val(v2)) { - case Forward_tag: - v2 = Forward_val(v2); - continue; - case Custom_tag: { - int res; - int (*compare)(value v1, value v2) = Custom_ops_val(v2)->compare_ext; - if (compare == NULL) break; /* for backward compatibility */ - caml_compare_unordered = 0; - res = compare(v1, v2); - if (caml_compare_unordered && !total) return UNORDERED; - if (res != 0) return res; - goto next_item; - } - default: /*fallthrough*/; - } - } - return LESS; /* v1 long < v2 block */ - } - if (Is_long(v2)) { - if (Is_in_value_area(v1)) { - switch (Tag_val(v1)) { - case Forward_tag: - v1 = Forward_val(v1); - continue; - case Custom_tag: { - int res; - int (*compare)(value v1, value v2) = Custom_ops_val(v1)->compare_ext; - if (compare == NULL) break; /* for backward compatibility */ - caml_compare_unordered = 0; - res = compare(v1, v2); - if (caml_compare_unordered && !total) return UNORDERED; - if (res != 0) return res; - goto next_item; - } - default: /*fallthrough*/; - } - } - return GREATER; /* v1 block > v2 long */ - } - /* If one of the objects is outside the heap (but is not an atom), - use address comparison. Since both addresses are 2-aligned, - shift lsb off to avoid overflow in subtraction. */ - if (! Is_in_value_area(v1) || ! Is_in_value_area(v2)) { - if (v1 == v2) goto next_item; - return (v1 >> 1) - (v2 >> 1); - /* Subtraction above cannot result in UNORDERED */ - } - t1 = Tag_val(v1); - t2 = Tag_val(v2); - if (t1 == Forward_tag) { v1 = Forward_val (v1); continue; } - if (t2 == Forward_tag) { v2 = Forward_val (v2); continue; } - if (t1 != t2) return (intnat)t1 - (intnat)t2; - switch(t1) { - case String_tag: { - mlsize_t len1, len2; - int res; - if (v1 == v2) break; - len1 = caml_string_length(v1); - len2 = caml_string_length(v2); - res = memcmp(String_val(v1), String_val(v2), len1 <= len2 ? len1 : len2); - if (res < 0) return LESS; - if (res > 0) return GREATER; - if (len1 != len2) return len1 - len2; - break; - } - case Double_tag: { - double d1 = Double_val(v1); - double d2 = Double_val(v2); -#ifdef LACKS_SANE_NAN - if (isnan(d2)) { - if (! total) return UNORDERED; - if (isnan(d1)) break; - return GREATER; - } else if (isnan(d1)) { - if (! total) return UNORDERED; - return LESS; - } -#endif - if (d1 < d2) return LESS; - if (d1 > d2) return GREATER; -#ifndef LACKS_SANE_NAN - if (d1 != d2) { - if (! total) return UNORDERED; - /* One or both of d1 and d2 is NaN. Order according to the - convention NaN = NaN and NaN < f for all other floats f. */ - if (d1 == d1) return GREATER; /* d1 is not NaN, d2 is NaN */ - if (d2 == d2) return LESS; /* d2 is not NaN, d1 is NaN */ - /* d1 and d2 are both NaN, thus equal: continue comparison */ - } -#endif - break; - } - case Double_array_tag: { - mlsize_t sz1 = Wosize_val(v1) / Double_wosize; - mlsize_t sz2 = Wosize_val(v2) / Double_wosize; - mlsize_t i; - if (sz1 != sz2) return sz1 - sz2; - for (i = 0; i < sz1; i++) { - double d1 = Double_flat_field(v1, i); - double d2 = Double_flat_field(v2, i); - #ifdef LACKS_SANE_NAN - if (isnan(d2)) { - if (! total) return UNORDERED; - if (isnan(d1)) break; - return GREATER; - } else if (isnan(d1)) { - if (! total) return UNORDERED; - return LESS; - } - #endif - if (d1 < d2) return LESS; - if (d1 > d2) return GREATER; - #ifndef LACKS_SANE_NAN - if (d1 != d2) { - if (! total) return UNORDERED; - /* See comment for Double_tag case */ - if (d1 == d1) return GREATER; - if (d2 == d2) return LESS; - } - #endif - } - break; - } - case Abstract_tag: - compare_free_stack(stk); - caml_invalid_argument("compare: abstract value"); - case Closure_tag: - case Infix_tag: - compare_free_stack(stk); - caml_invalid_argument("compare: functional value"); - case Object_tag: { - intnat oid1 = Oid_val(v1); - intnat oid2 = Oid_val(v2); - if (oid1 != oid2) return oid1 - oid2; - break; - } - case Custom_tag: { - int res; - int (*compare)(value v1, value v2) = Custom_ops_val(v1)->compare; - /* Hardening against comparisons between different types */ - if (compare != Custom_ops_val(v2)->compare) { - return strcmp(Custom_ops_val(v1)->identifier, - Custom_ops_val(v2)->identifier) < 0 - ? LESS : GREATER; - } - if (compare == NULL) { - compare_free_stack(stk); - caml_invalid_argument("compare: abstract value"); - } - caml_compare_unordered = 0; - res = compare(v1, v2); - if (caml_compare_unordered && !total) return UNORDERED; - if (res != 0) return res; - break; - } - default: { - mlsize_t sz1 = Wosize_val(v1); - mlsize_t sz2 = Wosize_val(v2); - /* Compare sizes first for speed */ - if (sz1 != sz2) return sz1 - sz2; - if (sz1 == 0) break; - /* Remember that we still have to compare fields 1 ... sz - 1 */ - if (sz1 > 1) { - sp++; - if (sp >= stk->limit) sp = compare_resize_stack(stk, sp); - sp->v1 = &Field(v1, 1); - sp->v2 = &Field(v2, 1); - sp->count = sz1 - 1; - } - /* Continue comparison with first field */ - v1 = Field(v1, 0); - v2 = Field(v2, 0); - continue; - } - } - next_item: - /* Pop one more item to compare, if any */ - if (sp == stk->stack) return EQUAL; /* we're done */ - v1 = *((sp->v1)++); - v2 = *((sp->v2)++); - if (--(sp->count) == 0) sp--; - } -} - -CAMLprim value caml_compare(value v1, value v2) -{ - intnat res = compare_val(v1, v2, 1); - /* Free stack if needed */ - if (res < 0) - return Val_int(LESS); - else if (res > 0) - return Val_int(GREATER); - else - return Val_int(EQUAL); -} - -CAMLprim value caml_equal(value v1, value v2) -{ - intnat res = compare_val(v1, v2, 0); - return Val_int(res == 0); -} - -CAMLprim value caml_notequal(value v1, value v2) -{ - intnat res = compare_val(v1, v2, 0); - return Val_int(res != 0); -} - -CAMLprim value caml_lessthan(value v1, value v2) -{ - intnat res = compare_val(v1, v2, 0); - return Val_int(res < 0 && res != UNORDERED); -} - -CAMLprim value caml_lessequal(value v1, value v2) -{ - intnat res = compare_val(v1, v2, 0); - return Val_int(res <= 0 && res != UNORDERED); -} - -CAMLprim value caml_greaterthan(value v1, value v2) -{ - intnat res = compare_val(v1, v2, 0); - return Val_int(res > 0); -} - -CAMLprim value caml_greaterequal(value v1, value v2) -{ - intnat res = compare_val(v1, v2, 0); - return Val_int(res >= 0); -} diff --git a/byterun/custom.c b/byterun/custom.c deleted file mode 100644 index b6a5c4e3..00000000 --- a/byterun/custom.c +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -#include - -#include "caml/alloc.h" -#include "caml/custom.h" -#include "caml/fail.h" -#include "caml/memory.h" -#include "caml/mlvalues.h" -#include "caml/signals.h" - -/* [size] is a number of bytes */ -CAMLexport value caml_alloc_custom(struct custom_operations * ops, - uintnat size, - mlsize_t mem, - mlsize_t max) -{ - mlsize_t wosize; - CAMLparam0(); - CAMLlocal1(result); - - wosize = 1 + (size + sizeof(value) - 1) / sizeof(value); - if (wosize <= Max_young_wosize) { - result = caml_alloc_small(wosize, Custom_tag); - Custom_ops_val(result) = ops; - if (ops->finalize != NULL || mem != 0) { - /* Remember that the block needs processing after minor GC. */ - add_to_custom_table (&caml_custom_table, result, mem, max); - /* Keep track of extra resources held by custom block in - minor heap. */ - if (mem != 0) { - if (max == 0) max = 1; - caml_extra_heap_resources_minor += (double) mem / (double) max; - if (caml_extra_heap_resources_minor > 1.0) { - caml_request_minor_gc (); - caml_gc_dispatch (); - } - } - } - } else { - result = caml_alloc_shr(wosize, Custom_tag); - Custom_ops_val(result) = ops; - caml_adjust_gc_speed(mem, max); - result = caml_check_urgent_gc(result); - } - CAMLreturn(result); -} - -struct custom_operations_list { - struct custom_operations * ops; - struct custom_operations_list * next; -}; - -static struct custom_operations_list * custom_ops_table = NULL; - -CAMLexport void caml_register_custom_operations(struct custom_operations * ops) -{ - struct custom_operations_list * l = - caml_stat_alloc(sizeof(struct custom_operations_list)); - CAMLassert(ops->identifier != NULL); - CAMLassert(ops->deserialize != NULL); - l->ops = ops; - l->next = custom_ops_table; - custom_ops_table = l; -} - -struct custom_operations * caml_find_custom_operations(char * ident) -{ - struct custom_operations_list * l; - for (l = custom_ops_table; l != NULL; l = l->next) - if (strcmp(l->ops->identifier, ident) == 0) return l->ops; - return NULL; -} - -static struct custom_operations_list * custom_ops_final_table = NULL; - -struct custom_operations * caml_final_custom_operations(final_fun fn) -{ - struct custom_operations_list * l; - struct custom_operations * ops; - for (l = custom_ops_final_table; l != NULL; l = l->next) - if (l->ops->finalize == fn) return l->ops; - ops = caml_stat_alloc(sizeof(struct custom_operations)); - ops->identifier = "_final"; - ops->finalize = fn; - ops->compare = custom_compare_default; - ops->hash = custom_hash_default; - ops->serialize = custom_serialize_default; - ops->deserialize = custom_deserialize_default; - ops->compare_ext = custom_compare_ext_default; - l = caml_stat_alloc(sizeof(struct custom_operations_list)); - l->ops = ops; - l->next = custom_ops_final_table; - custom_ops_final_table = l; - return ops; -} - -extern struct custom_operations caml_int32_ops, - caml_nativeint_ops, - caml_int64_ops, - caml_ba_ops; - -void caml_init_custom_operations(void) -{ - caml_register_custom_operations(&caml_int32_ops); - caml_register_custom_operations(&caml_nativeint_ops); - caml_register_custom_operations(&caml_int64_ops); - caml_register_custom_operations(&caml_ba_ops); -} diff --git a/byterun/debugger.c b/byterun/debugger.c deleted file mode 100644 index 1c416cd6..00000000 --- a/byterun/debugger.c +++ /dev/null @@ -1,454 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Interface with the byte-code debugger */ - -#ifdef _WIN32 -#include -#endif /* _WIN32 */ - -#include - -#include "caml/alloc.h" -#include "caml/config.h" -#include "caml/debugger.h" -#include "caml/misc.h" -#include "caml/osdeps.h" - -int caml_debugger_in_use = 0; -uintnat caml_event_count; -int caml_debugger_fork_mode = 1; /* parent by default */ - -#if !defined(HAS_SOCKETS) || defined(NATIVE_CODE) - -void caml_debugger_init(void) -{ -} - -void caml_debugger(enum event_kind event) -{ -} - -void caml_debugger_cleanup_fork(void) -{ -} - -#else - -#ifdef HAS_UNISTD -#include -#endif -#include -#include -#ifndef _WIN32 -#include -#include -#include -#include -#include -#include -#else -#define ATOM ATOM_WS -#include -#undef ATOM -#include -#endif - -#include "caml/fail.h" -#include "caml/fix_code.h" -#include "caml/instruct.h" -#include "caml/intext.h" -#include "caml/io.h" -#include "caml/mlvalues.h" -#include "caml/stacks.h" -#include "caml/sys.h" - -static value marshal_flags = Val_emptylist; - -static int sock_domain; /* Socket domain for the debugger */ -static union { /* Socket address for the debugger */ - struct sockaddr s_gen; -#ifndef _WIN32 - struct sockaddr_un s_unix; -#endif - struct sockaddr_in s_inet; -} sock_addr; -static int sock_addr_len; /* Length of sock_addr */ - -static int dbg_socket = -1; /* The socket connected to the debugger */ -static struct channel * dbg_in; /* Input channel on the socket */ -static struct channel * dbg_out;/* Output channel on the socket */ - -static char *dbg_addr = NULL; - -static void open_connection(void) -{ -#ifdef _WIN32 - /* Set socket to synchronous mode so that file descriptor-oriented - functions (read()/write() etc.) can be used */ - - int oldvalue, oldvaluelen, newvalue, retcode; - oldvaluelen = sizeof(oldvalue); - retcode = getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, - (char *) &oldvalue, &oldvaluelen); - if (retcode == 0) { - newvalue = SO_SYNCHRONOUS_NONALERT; - setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, - (char *) &newvalue, sizeof(newvalue)); - } -#endif - dbg_socket = socket(sock_domain, SOCK_STREAM, 0); -#ifdef _WIN32 - if (retcode == 0) { - /* Restore initial mode */ - setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, - (char *) &oldvalue, oldvaluelen); - } -#endif - if (dbg_socket == -1 || - connect(dbg_socket, &sock_addr.s_gen, sock_addr_len) == -1){ - caml_fatal_error_arg2 ("cannot connect to debugger at %s\n", (dbg_addr ? dbg_addr : "(none)"), - "error: %s\n", strerror (errno)); - } -#ifdef _WIN32 - dbg_socket = _open_osfhandle(dbg_socket, 0); - if (dbg_socket == -1) - caml_fatal_error("_open_osfhandle failed"); -#endif - dbg_in = caml_open_descriptor_in(dbg_socket); - dbg_out = caml_open_descriptor_out(dbg_socket); - if (!caml_debugger_in_use) caml_putword(dbg_out, -1); /* first connection */ -#ifdef _WIN32 - caml_putword(dbg_out, _getpid()); -#else - caml_putword(dbg_out, getpid()); -#endif - caml_flush(dbg_out); -} - -static void close_connection(void) -{ - caml_close_channel(dbg_in); - caml_close_channel(dbg_out); - dbg_socket = -1; /* was closed by caml_close_channel */ -} - -#ifdef _WIN32 -static void winsock_startup(void) -{ - WSADATA wsaData; - int err = WSAStartup(MAKEWORD(2, 0), &wsaData); - if (err) caml_fatal_error("WSAStartup failed"); -} - -static void winsock_cleanup(void) -{ - WSACleanup(); -} -#endif - -void caml_debugger_init(void) -{ - char * address; - char_os * a; - size_t a_len; - char * port, * p; - struct hostent * host; - int n; - - caml_register_global_root(&marshal_flags); - marshal_flags = caml_alloc(2, Tag_cons); - Store_field(marshal_flags, 0, Val_int(1)); /* Marshal.Closures */ - Store_field(marshal_flags, 1, Val_emptylist); - - a = caml_secure_getenv(_T("CAML_DEBUG_SOCKET")); - address = a ? caml_stat_strdup_of_os(a) : NULL; - if (address == NULL) return; - if (dbg_addr != NULL) caml_stat_free(dbg_addr); - dbg_addr = address; - -#ifdef _WIN32 - winsock_startup(); - (void)atexit(winsock_cleanup); -#endif - /* Parse the address */ - port = NULL; - for (p = address; *p != 0; p++) { - if (*p == ':') { *p = 0; port = p+1; break; } - } - if (port == NULL) { -#ifndef _WIN32 - /* Unix domain */ - sock_domain = PF_UNIX; - sock_addr.s_unix.sun_family = AF_UNIX; - a_len = strlen(address); - if (a_len >= sizeof(sock_addr.s_unix.sun_path)) { - caml_fatal_error("Debug socket path length exceeds maximum permitted length"); - } - strncpy(sock_addr.s_unix.sun_path, address, - sizeof(sock_addr.s_unix.sun_path) - 1); - sock_addr.s_unix.sun_path[sizeof(sock_addr.s_unix.sun_path) - 1] = '\0'; - sock_addr_len = - ((char *)&(sock_addr.s_unix.sun_path) - (char *)&(sock_addr.s_unix)) - + a_len; -#else - caml_fatal_error("Unix sockets not supported"); -#endif - } else { - /* Internet domain */ - sock_domain = PF_INET; - for (p = (char *) &sock_addr.s_inet, n = sizeof(sock_addr.s_inet); - n > 0; n--) *p++ = 0; - sock_addr.s_inet.sin_family = AF_INET; - sock_addr.s_inet.sin_addr.s_addr = inet_addr(address); - if (sock_addr.s_inet.sin_addr.s_addr == -1) { - host = gethostbyname(address); - if (host == NULL) - caml_fatal_error_arg("Unknown debugging host %s\n", address); - memmove(&sock_addr.s_inet.sin_addr, host->h_addr, host->h_length); - } - sock_addr.s_inet.sin_port = htons(atoi(port)); - sock_addr_len = sizeof(sock_addr.s_inet); - } - open_connection(); - caml_debugger_in_use = 1; - caml_trap_barrier = caml_stack_high; -} - -static value getval(struct channel *chan) -{ - value res; - if (caml_really_getblock(chan, (char *) &res, sizeof(res)) < sizeof(res)) - caml_raise_end_of_file(); /* Bad, but consistent with caml_getword */ - return res; -} - -static void putval(struct channel *chan, value val) -{ - caml_really_putblock(chan, (char *) &val, sizeof(val)); -} - -static void safe_output_value(struct channel *chan, value val) -{ - struct longjmp_buffer raise_buf, * saved_external_raise; - - /* Catch exceptions raised by [caml_output_val] */ - saved_external_raise = caml_external_raise; - if (sigsetjmp(raise_buf.buf, 0) == 0) { - caml_external_raise = &raise_buf; - caml_output_val(chan, val, marshal_flags); - } else { - /* Send wrong magic number, will cause [caml_input_value] to fail */ - caml_really_putblock(chan, "\000\000\000\000", 4); - } - caml_external_raise = saved_external_raise; -} - -#define Pc(sp) ((code_t)((sp)[0])) -#define Env(sp) ((sp)[1]) -#define Extra_args(sp) (Long_val(((sp)[2]))) -#define Locals(sp) ((sp) + 3) - -void caml_debugger(enum event_kind event) -{ - value * frame; - intnat i, pos; - value val; - - if (dbg_socket == -1) return; /* Not connected to a debugger. */ - - /* Reset current frame */ - frame = caml_extern_sp + 1; - - /* Report the event to the debugger */ - switch(event) { - case PROGRAM_START: /* Nothing to report */ - goto command_loop; - case EVENT_COUNT: - caml_putch(dbg_out, REP_EVENT); - break; - case BREAKPOINT: - caml_putch(dbg_out, REP_BREAKPOINT); - break; - case PROGRAM_EXIT: - caml_putch(dbg_out, REP_EXITED); - break; - case TRAP_BARRIER: - caml_putch(dbg_out, REP_TRAP); - break; - case UNCAUGHT_EXC: - caml_putch(dbg_out, REP_UNCAUGHT_EXC); - break; - } - caml_putword(dbg_out, caml_event_count); - if (event == EVENT_COUNT || event == BREAKPOINT) { - caml_putword(dbg_out, caml_stack_high - frame); - caml_putword(dbg_out, (Pc(frame) - caml_start_code) * sizeof(opcode_t)); - } else { - /* No PC and no stack frame associated with other events */ - caml_putword(dbg_out, 0); - caml_putword(dbg_out, 0); - } - caml_flush(dbg_out); - - command_loop: - - /* Read and execute the commands sent by the debugger */ - while(1) { - switch(caml_getch(dbg_in)) { - case REQ_SET_EVENT: - pos = caml_getword(dbg_in); - CAMLassert (pos >= 0); - CAMLassert (pos < caml_code_size); - caml_set_instruction(caml_start_code + pos / sizeof(opcode_t), EVENT); - break; - case REQ_SET_BREAKPOINT: - pos = caml_getword(dbg_in); - CAMLassert (pos >= 0); - CAMLassert (pos < caml_code_size); - caml_set_instruction(caml_start_code + pos / sizeof(opcode_t), BREAK); - break; - case REQ_RESET_INSTR: - pos = caml_getword(dbg_in); - CAMLassert (pos >= 0); - CAMLassert (pos < caml_code_size); - pos = pos / sizeof(opcode_t); - caml_set_instruction(caml_start_code + pos, caml_saved_code[pos]); - break; - case REQ_CHECKPOINT: -#ifndef _WIN32 - i = fork(); - if (i == 0) { - close_connection(); /* Close parent connection. */ - open_connection(); /* Open new connection with debugger */ - } else { - caml_putword(dbg_out, i); - caml_flush(dbg_out); - } -#else - caml_fatal_error("error: REQ_CHECKPOINT command"); - exit(-1); -#endif - break; - case REQ_GO: - caml_event_count = caml_getword(dbg_in); - return; - case REQ_STOP: - exit(0); - break; - case REQ_WAIT: -#ifndef _WIN32 - wait(NULL); -#else - caml_fatal_error("Fatal error: REQ_WAIT command"); - exit(-1); -#endif - break; - case REQ_INITIAL_FRAME: - frame = caml_extern_sp + 1; - /* Fall through */ - case REQ_GET_FRAME: - caml_putword(dbg_out, caml_stack_high - frame); - if (frame < caml_stack_high){ - caml_putword(dbg_out, (Pc(frame) - caml_start_code) * sizeof(opcode_t)); - }else{ - caml_putword (dbg_out, 0); - } - caml_flush(dbg_out); - break; - case REQ_SET_FRAME: - i = caml_getword(dbg_in); - frame = caml_stack_high - i; - break; - case REQ_UP_FRAME: - i = caml_getword(dbg_in); - if (frame + Extra_args(frame) + i + 3 >= caml_stack_high) { - caml_putword(dbg_out, -1); - } else { - frame += Extra_args(frame) + i + 3; - caml_putword(dbg_out, caml_stack_high - frame); - caml_putword(dbg_out, (Pc(frame) - caml_start_code) * sizeof(opcode_t)); - } - caml_flush(dbg_out); - break; - case REQ_SET_TRAP_BARRIER: - i = caml_getword(dbg_in); - caml_trap_barrier = caml_stack_high - i; - break; - case REQ_GET_LOCAL: - i = caml_getword(dbg_in); - putval(dbg_out, Locals(frame)[i]); - caml_flush(dbg_out); - break; - case REQ_GET_ENVIRONMENT: - i = caml_getword(dbg_in); - putval(dbg_out, Field(Env(frame), i)); - caml_flush(dbg_out); - break; - case REQ_GET_GLOBAL: - i = caml_getword(dbg_in); - putval(dbg_out, Field(caml_global_data, i)); - caml_flush(dbg_out); - break; - case REQ_GET_ACCU: - putval(dbg_out, *caml_extern_sp); - caml_flush(dbg_out); - break; - case REQ_GET_HEADER: - val = getval(dbg_in); - caml_putword(dbg_out, Hd_val(val)); - caml_flush(dbg_out); - break; - case REQ_GET_FIELD: - val = getval(dbg_in); - i = caml_getword(dbg_in); - if (Tag_val(val) != Double_array_tag) { - caml_putch(dbg_out, 0); - putval(dbg_out, Field(val, i)); - } else { - double d = Double_flat_field(val, i); - caml_putch(dbg_out, 1); - caml_really_putblock(dbg_out, (char *) &d, 8); - } - caml_flush(dbg_out); - break; - case REQ_MARSHAL_OBJ: - val = getval(dbg_in); - safe_output_value(dbg_out, val); - caml_flush(dbg_out); - break; - case REQ_GET_CLOSURE_CODE: - val = getval(dbg_in); - caml_putword(dbg_out, (Code_val(val)-caml_start_code) * sizeof(opcode_t)); - caml_flush(dbg_out); - break; - case REQ_SET_FORK_MODE: - caml_debugger_fork_mode = caml_getword(dbg_in); - break; - } - } -} - -void caml_debugger_cleanup_fork(void) -{ - /* We could remove all of the breakpoints, but closing the connection - * means that they'll just be skipped anyway. */ - close_connection(); - caml_debugger_in_use = 0; -} - -#endif diff --git a/byterun/dynlink.c b/byterun/dynlink.c deleted file mode 100644 index 7c339bf5..00000000 --- a/byterun/dynlink.c +++ /dev/null @@ -1,300 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Dynamic loading of C primitives. */ - -#include -#include -#include -#include -#include -#include "caml/config.h" -#ifdef HAS_UNISTD -#include -#endif -#include "caml/alloc.h" -#include "caml/dynlink.h" -#include "caml/fail.h" -#include "caml/mlvalues.h" -#include "caml/memory.h" -#include "caml/misc.h" -#include "caml/osdeps.h" -#include "caml/prims.h" -#include "caml/signals.h" - -#ifndef NATIVE_CODE - -/* The table of primitives */ -struct ext_table caml_prim_table; - -#ifdef DEBUG -/* The names of primitives (for instrtrace.c) */ -struct ext_table caml_prim_name_table; -#endif - -/* The table of shared libraries currently opened */ -static struct ext_table shared_libs; - -/* The search path for shared libraries */ -struct ext_table caml_shared_libs_path; - -/* Look up the given primitive name in the built-in primitive table, - then in the opened shared libraries (shared_libs) */ -static c_primitive lookup_primitive(char * name) -{ - int i; - void * res; - - for (i = 0; caml_names_of_builtin_cprim[i] != NULL; i++) { - if (strcmp(name, caml_names_of_builtin_cprim[i]) == 0) - return caml_builtin_cprim[i]; - } - for (i = 0; i < shared_libs.size; i++) { - res = caml_dlsym(shared_libs.contents[i], name); - if (res != NULL) return (c_primitive) res; - } - return NULL; -} - -/* Parse the OCAML_STDLIB_DIR/ld.conf file and add the directories - listed there to the search path */ - -#define LD_CONF_NAME _T("ld.conf") - -static char_os * parse_ld_conf(void) -{ - char_os * stdlib, * ldconfname, * wconfig, * p, * q; - char * config; -#ifdef _WIN32 - struct _stati64 st; -#else - struct stat st; -#endif - int ldconf, nread; - - stdlib = caml_secure_getenv(_T("OCAMLLIB")); - if (stdlib == NULL) stdlib = caml_secure_getenv(_T("CAMLLIB")); - if (stdlib == NULL) stdlib = OCAML_STDLIB_DIR; - ldconfname = caml_stat_strconcat_os(3, stdlib, _T("/"), LD_CONF_NAME); - if (stat_os(ldconfname, &st) == -1) { - caml_stat_free(ldconfname); - return NULL; - } - ldconf = open_os(ldconfname, O_RDONLY, 0); - if (ldconf == -1) - caml_fatal_error_arg("Fatal error: cannot read loader config file %s\n", - caml_stat_strdup_of_os(ldconfname)); - config = caml_stat_alloc(st.st_size + 1); - nread = read(ldconf, config, st.st_size); - if (nread == -1) - caml_fatal_error_arg - ("Fatal error: error while reading loader config file %s\n", - caml_stat_strdup_of_os(ldconfname)); - config[nread] = 0; - wconfig = caml_stat_strdup_to_os(config); - caml_stat_free(config); - q = wconfig; - for (p = wconfig; *p != 0; p++) { - if (*p == _T('\n')) { - *p = 0; - caml_ext_table_add(&caml_shared_libs_path, q); - q = p + 1; - } - } - if (q < p) caml_ext_table_add(&caml_shared_libs_path, q); - close(ldconf); - caml_stat_free(ldconfname); - return wconfig; -} - -/* Open the given shared library and add it to shared_libs. - Abort on error. */ -static void open_shared_lib(char_os * name) -{ - char_os * realname; - char * u8; - void * handle; - - realname = caml_search_dll_in_path(&caml_shared_libs_path, name); - u8 = caml_stat_strdup_of_os(realname); - caml_gc_message(0x100, "Loading shared library %s\n", u8); - caml_stat_free(u8); - caml_enter_blocking_section(); - handle = caml_dlopen(realname, 1, 1); - caml_leave_blocking_section(); - if (handle == NULL) - caml_fatal_error_arg2("Fatal error: cannot load shared library %s\n", - caml_stat_strdup_of_os(name), - "Reason: %s\n", caml_dlerror()); - caml_ext_table_add(&shared_libs, handle); - caml_stat_free(realname); -} - -/* Build the table of primitives, given a search path and a list - of shared libraries (both 0-separated in a char array). - Abort the runtime system on error. */ -void caml_build_primitive_table(char_os * lib_path, - char_os * libs, - char * req_prims) -{ - char_os * tofree1, * tofree2; - char_os * p; - char * q; - - /* Initialize the search path for dynamic libraries: - - directories specified on the command line with the -I option - - directories specified in the CAML_LD_LIBRARY_PATH - - directories specified in the executable - - directories specified in the file /ld.conf */ - tofree1 = caml_decompose_path(&caml_shared_libs_path, - caml_secure_getenv(_T("CAML_LD_LIBRARY_PATH"))); - if (lib_path != NULL) - for (p = lib_path; *p != 0; p += strlen_os(p) + 1) - caml_ext_table_add(&caml_shared_libs_path, p); - tofree2 = parse_ld_conf(); - /* Open the shared libraries */ - caml_ext_table_init(&shared_libs, 8); - if (libs != NULL) - for (p = libs; *p != 0; p += strlen_os(p) + 1) - open_shared_lib(p); - /* Build the primitive table */ - caml_ext_table_init(&caml_prim_table, 0x180); -#ifdef DEBUG - caml_ext_table_init(&caml_prim_name_table, 0x180); -#endif - for (q = req_prims; *q != 0; q += strlen(q) + 1) { - c_primitive prim = lookup_primitive(q); - if (prim == NULL) - caml_fatal_error_arg("Fatal error: unknown C primitive `%s'\n", q); - caml_ext_table_add(&caml_prim_table, (void *) prim); -#ifdef DEBUG - caml_ext_table_add(&caml_prim_name_table, caml_stat_strdup(q)); -#endif - } - /* Clean up */ - caml_stat_free(tofree1); - caml_stat_free(tofree2); - caml_ext_table_free(&caml_shared_libs_path, 0); -} - -/* Build the table of primitives as a copy of the builtin primitive table. - Used for executables generated by ocamlc -output-obj. */ - -void caml_build_primitive_table_builtin(void) -{ - int i; - caml_ext_table_init(&caml_prim_table, 0x180); -#ifdef DEBUG - caml_ext_table_init(&caml_prim_name_table, 0x180); -#endif - for (i = 0; caml_builtin_cprim[i] != 0; i++) { - caml_ext_table_add(&caml_prim_table, (void *) caml_builtin_cprim[i]); -#ifdef DEBUG - caml_ext_table_add(&caml_prim_name_table, - caml_stat_strdup(caml_names_of_builtin_cprim[i])); -#endif - } -} - -void caml_free_shared_libs(void) -{ - while (shared_libs.size > 0) - caml_dlclose(shared_libs.contents[--shared_libs.size]); -} - -#endif /* NATIVE_CODE */ - -/** dlopen interface for the bytecode linker **/ - -#define Handle_val(v) (*((void **) (v))) - -CAMLprim value caml_dynlink_open_lib(value mode, value filename) -{ - void * handle; - value result; - char_os * p; - - caml_gc_message(0x100, "Opening shared library %s\n", - String_val(filename)); - p = caml_stat_strdup_to_os(String_val(filename)); - caml_enter_blocking_section(); - handle = caml_dlopen(p, Int_val(mode), 1); - caml_leave_blocking_section(); - caml_stat_free(p); - if (handle == NULL) caml_failwith(caml_dlerror()); - result = caml_alloc_small(1, Abstract_tag); - Handle_val(result) = handle; - return result; -} - -CAMLprim value caml_dynlink_close_lib(value handle) -{ - caml_dlclose(Handle_val(handle)); - return Val_unit; -} - -/*#include */ -CAMLprim value caml_dynlink_lookup_symbol(value handle, value symbolname) -{ - void * symb; - value result; - symb = caml_dlsym(Handle_val(handle), String_val(symbolname)); - /* printf("%s = 0x%lx\n", String_val(symbolname), symb); - fflush(stdout); */ - if (symb == NULL) return Val_unit /*caml_failwith(caml_dlerror())*/; - result = caml_alloc_small(1, Abstract_tag); - Handle_val(result) = symb; - return result; -} - -#ifndef NATIVE_CODE - -CAMLprim value caml_dynlink_add_primitive(value handle) -{ - return Val_int(caml_ext_table_add(&caml_prim_table, Handle_val(handle))); -} - -CAMLprim value caml_dynlink_get_current_libs(value unit) -{ - CAMLparam0(); - CAMLlocal1(res); - int i; - - res = caml_alloc_tuple(shared_libs.size); - for (i = 0; i < shared_libs.size; i++) { - value v = caml_alloc_small(1, Abstract_tag); - Handle_val(v) = shared_libs.contents[i]; - Store_field(res, i, v); - } - CAMLreturn(res); -} - -#else - -value caml_dynlink_add_primitive(value handle) -{ - caml_invalid_argument("dynlink_add_primitive"); - return Val_unit; /* not reached */ -} - -value caml_dynlink_get_current_libs(value unit) -{ - caml_invalid_argument("dynlink_get_current_libs"); - return Val_unit; /* not reached */ -} - -#endif /* NATIVE_CODE */ diff --git a/byterun/extern.c b/byterun/extern.c deleted file mode 100644 index db7163cd..00000000 --- a/byterun/extern.c +++ /dev/null @@ -1,925 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Structured output */ - -/* The interface of this file is "caml/intext.h" */ - -#include -#include "caml/alloc.h" -#include "caml/config.h" -#include "caml/custom.h" -#include "caml/fail.h" -#include "caml/gc.h" -#include "caml/intext.h" -#include "caml/io.h" -#include "caml/md5.h" -#include "caml/memory.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/reverse.h" - -static uintnat obj_counter; /* Number of objects emitted so far */ -static uintnat size_32; /* Size in words of 32-bit block for struct. */ -static uintnat size_64; /* Size in words of 64-bit block for struct. */ - -/* Flags affecting marshaling */ - -enum { - NO_SHARING = 1, /* Flag to ignore sharing */ - CLOSURES = 2, /* Flag to allow marshaling code pointers */ - COMPAT_32 = 4 /* Flag to ensure that output can safely - be read back on a 32-bit platform */ -}; - -static int extern_flags; /* logical or of some of the flags above */ - -/* Trail mechanism to undo forwarding pointers put inside objects */ - -struct trail_entry { - value obj; /* address of object + initial color in low 2 bits */ - value field0; /* initial contents of field 0 */ -}; - -struct trail_block { - struct trail_block * previous; - struct trail_entry entries[ENTRIES_PER_TRAIL_BLOCK]; -}; - -static struct trail_block extern_trail_first; -static struct trail_block * extern_trail_block; -static struct trail_entry * extern_trail_cur, * extern_trail_limit; - - -/* Stack for pending values to marshal */ - -struct extern_item { value * v; mlsize_t count; }; - -#define EXTERN_STACK_INIT_SIZE 256 -#define EXTERN_STACK_MAX_SIZE (1024*1024*100) - -static struct extern_item extern_stack_init[EXTERN_STACK_INIT_SIZE]; - -static struct extern_item * extern_stack = extern_stack_init; -static struct extern_item * extern_stack_limit = extern_stack_init - + EXTERN_STACK_INIT_SIZE; - -/* Forward declarations */ - -CAMLnoreturn_start -static void extern_out_of_memory(void) -CAMLnoreturn_end; - -CAMLnoreturn_start -static void extern_invalid_argument(char *msg) -CAMLnoreturn_end; - -CAMLnoreturn_start -static void extern_failwith(char *msg) -CAMLnoreturn_end; - -CAMLnoreturn_start -static void extern_stack_overflow(void) -CAMLnoreturn_end; - -static void extern_replay_trail(void); -static void free_extern_output(void); - -/* Free the extern stack if needed */ -static void extern_free_stack(void) -{ - if (extern_stack != extern_stack_init) { - caml_stat_free(extern_stack); - /* Reinitialize the globals for next time around */ - extern_stack = extern_stack_init; - extern_stack_limit = extern_stack + EXTERN_STACK_INIT_SIZE; - } -} - -static struct extern_item * extern_resize_stack(struct extern_item * sp) -{ - asize_t newsize = 2 * (extern_stack_limit - extern_stack); - asize_t sp_offset = sp - extern_stack; - struct extern_item * newstack; - - if (newsize >= EXTERN_STACK_MAX_SIZE) extern_stack_overflow(); - if (extern_stack == extern_stack_init) { - newstack = caml_stat_alloc_noexc(sizeof(struct extern_item) * newsize); - if (newstack == NULL) extern_stack_overflow(); - memcpy(newstack, extern_stack_init, - sizeof(struct extern_item) * EXTERN_STACK_INIT_SIZE); - } else { - newstack = caml_stat_resize_noexc(extern_stack, - sizeof(struct extern_item) * newsize); - if (newstack == NULL) extern_stack_overflow(); - } - extern_stack = newstack; - extern_stack_limit = newstack + newsize; - return newstack + sp_offset; -} - -/* Initialize the trail */ - -static void init_extern_trail(void) -{ - extern_trail_block = &extern_trail_first; - extern_trail_cur = extern_trail_block->entries; - extern_trail_limit = extern_trail_block->entries + ENTRIES_PER_TRAIL_BLOCK; -} - -/* Replay the trail, undoing the in-place modifications - performed on objects */ - -static void extern_replay_trail(void) -{ - struct trail_block * blk, * prevblk; - struct trail_entry * ent, * lim; - - blk = extern_trail_block; - lim = extern_trail_cur; - while (1) { - for (ent = &(blk->entries[0]); ent < lim; ent++) { - value obj = ent->obj; - color_t colornum = obj & 3; - obj = obj & ~3; - Hd_val(obj) = Coloredhd_hd(Hd_val(obj), colornum); - Field(obj, 0) = ent->field0; - } - if (blk == &extern_trail_first) break; - prevblk = blk->previous; - caml_stat_free(blk); - blk = prevblk; - lim = &(blk->entries[ENTRIES_PER_TRAIL_BLOCK]); - } - /* Protect against a second call to extern_replay_trail */ - extern_trail_block = &extern_trail_first; - extern_trail_cur = extern_trail_block->entries; -} - -/* Set forwarding pointer on an object and add corresponding entry - to the trail. */ - -static void extern_record_location(value obj) -{ - header_t hdr; - - if (extern_flags & NO_SHARING) return; - if (extern_trail_cur == extern_trail_limit) { - struct trail_block * new_block = caml_stat_alloc_noexc(sizeof(struct trail_block)); - if (new_block == NULL) extern_out_of_memory(); - new_block->previous = extern_trail_block; - extern_trail_block = new_block; - extern_trail_cur = extern_trail_block->entries; - extern_trail_limit = extern_trail_block->entries + ENTRIES_PER_TRAIL_BLOCK; - } - hdr = Hd_val(obj); - extern_trail_cur->obj = obj | Colornum_hd(hdr); - extern_trail_cur->field0 = Field(obj, 0); - extern_trail_cur++; - Hd_val(obj) = Bluehd_hd(hdr); - Field(obj, 0) = (value) obj_counter; - obj_counter++; -} - -/* To buffer the output */ - -static char * extern_userprovided_output; -static char * extern_ptr, * extern_limit; - -struct output_block { - struct output_block * next; - char * end; - char data[SIZE_EXTERN_OUTPUT_BLOCK]; -}; - -static struct output_block * extern_output_first, * extern_output_block; - -static void init_extern_output(void) -{ - extern_userprovided_output = NULL; - extern_output_first = caml_stat_alloc_noexc(sizeof(struct output_block)); - if (extern_output_first == NULL) caml_raise_out_of_memory(); - extern_output_block = extern_output_first; - extern_output_block->next = NULL; - extern_ptr = extern_output_block->data; - extern_limit = extern_output_block->data + SIZE_EXTERN_OUTPUT_BLOCK; -} - -static void close_extern_output(void) -{ - if (extern_userprovided_output == NULL){ - extern_output_block->end = extern_ptr; - } -} - -static void free_extern_output(void) -{ - struct output_block * blk, * nextblk; - - if (extern_userprovided_output != NULL) return; - for (blk = extern_output_first; blk != NULL; blk = nextblk) { - nextblk = blk->next; - caml_stat_free(blk); - } - extern_output_first = NULL; - extern_free_stack(); -} - -static void grow_extern_output(intnat required) -{ - struct output_block * blk; - intnat extra; - - if (extern_userprovided_output != NULL) { - extern_failwith("Marshal.to_buffer: buffer overflow"); - } - extern_output_block->end = extern_ptr; - if (required <= SIZE_EXTERN_OUTPUT_BLOCK / 2) - extra = 0; - else - extra = required; - blk = caml_stat_alloc_noexc(sizeof(struct output_block) + extra); - if (blk == NULL) extern_out_of_memory(); - extern_output_block->next = blk; - extern_output_block = blk; - extern_output_block->next = NULL; - extern_ptr = extern_output_block->data; - extern_limit = extern_output_block->data + SIZE_EXTERN_OUTPUT_BLOCK + extra; -} - -static intnat extern_output_length(void) -{ - struct output_block * blk; - intnat len; - - if (extern_userprovided_output != NULL) { - return extern_ptr - extern_userprovided_output; - } else { - for (len = 0, blk = extern_output_first; blk != NULL; blk = blk->next) - len += blk->end - blk->data; - return len; - } -} - -/* Exception raising, with cleanup */ - -static void extern_out_of_memory(void) -{ - extern_replay_trail(); - free_extern_output(); - caml_raise_out_of_memory(); -} - -static void extern_invalid_argument(char *msg) -{ - extern_replay_trail(); - free_extern_output(); - caml_invalid_argument(msg); -} - -static void extern_failwith(char *msg) -{ - extern_replay_trail(); - free_extern_output(); - caml_failwith(msg); -} - -static void extern_stack_overflow(void) -{ - caml_gc_message (0x04, "Stack overflow in marshaling value\n"); - extern_replay_trail(); - free_extern_output(); - caml_raise_out_of_memory(); -} - -/* Conversion to big-endian */ - -static inline void store16(char * dst, int n) -{ - dst[0] = n >> 8; dst[1] = n; -} - -static inline void store32(char * dst, intnat n) -{ - dst[0] = n >> 24; dst[1] = n >> 16; dst[2] = n >> 8; dst[3] = n; -} - -static inline void store64(char * dst, int64_t n) -{ - dst[0] = n >> 56; dst[1] = n >> 48; dst[2] = n >> 40; dst[3] = n >> 32; - dst[4] = n >> 24; dst[5] = n >> 16; dst[6] = n >> 8; dst[7] = n; -} - -/* Write characters, integers, and blocks in the output buffer */ - -static inline void write(int c) -{ - if (extern_ptr >= extern_limit) grow_extern_output(1); - *extern_ptr++ = c; -} - -static void writeblock(const char * data, intnat len) -{ - if (extern_ptr + len > extern_limit) grow_extern_output(len); - memcpy(extern_ptr, data, len); - extern_ptr += len; -} - -static inline void writeblock_float8(const double * data, intnat ndoubles) -{ -#if ARCH_FLOAT_ENDIANNESS == 0x01234567 || ARCH_FLOAT_ENDIANNESS == 0x76543210 - writeblock((const char *) data, ndoubles * 8); -#else - caml_serialize_block_float_8(data, ndoubles); -#endif -} - -static void writecode8(int code, intnat val) -{ - if (extern_ptr + 2 > extern_limit) grow_extern_output(2); - extern_ptr[0] = code; - extern_ptr[1] = val; - extern_ptr += 2; -} - -static void writecode16(int code, intnat val) -{ - if (extern_ptr + 3 > extern_limit) grow_extern_output(3); - extern_ptr[0] = code; - store16(extern_ptr + 1, val); - extern_ptr += 3; -} - -static void writecode32(int code, intnat val) -{ - if (extern_ptr + 5 > extern_limit) grow_extern_output(5); - extern_ptr[0] = code; - store32(extern_ptr + 1, val); - extern_ptr += 5; -} - -#ifdef ARCH_SIXTYFOUR -static void writecode64(int code, intnat val) -{ - if (extern_ptr + 9 > extern_limit) grow_extern_output(9); - extern_ptr[0] = code; - store64(extern_ptr + 1, val); - extern_ptr += 9; -} -#endif - -/* Marshal the given value in the output buffer */ - -int caml_extern_allow_out_of_heap = 0; - -static void extern_rec(value v) -{ - struct code_fragment * cf; - struct extern_item * sp; - sp = extern_stack; - - while(1) { - if (Is_long(v)) { - intnat n = Long_val(v); - if (n >= 0 && n < 0x40) { - write(PREFIX_SMALL_INT + n); - } else if (n >= -(1 << 7) && n < (1 << 7)) { - writecode8(CODE_INT8, n); - } else if (n >= -(1 << 15) && n < (1 << 15)) { - writecode16(CODE_INT16, n); -#ifdef ARCH_SIXTYFOUR - } else if (n < -((intnat)1 << 30) || n >= ((intnat)1 << 30)) { - if (extern_flags & COMPAT_32) - extern_failwith("output_value: integer cannot be read back on " - "32-bit platform"); - writecode64(CODE_INT64, n); -#endif - } else - writecode32(CODE_INT32, n); - goto next_item; - } - if (Is_in_value_area(v) || caml_extern_allow_out_of_heap) { - header_t hd = Hd_val(v); - tag_t tag = Tag_hd(hd); - mlsize_t sz = Wosize_hd(hd); - - if (tag == Forward_tag) { - value f = Forward_val (v); - if (Is_block (f) - && (!Is_in_value_area(f) || Tag_val (f) == Forward_tag - || Tag_val (f) == Lazy_tag -#ifdef FLAT_FLOAT_ARRAY - || Tag_val (f) == Double_tag -#endif - )){ - /* Do not short-circuit the pointer. */ - }else{ - v = f; - continue; - } - } - /* Atoms are treated specially for two reasons: they are not allocated - in the externed block, and they are automatically shared. */ - if (sz == 0) { - if (tag < 16) { - write(PREFIX_SMALL_BLOCK + tag); - } else { -#ifdef WITH_PROFINFO - writecode32(CODE_BLOCK32, Hd_no_profinfo(hd)); -#else - writecode32(CODE_BLOCK32, hd); -#endif - } - goto next_item; - } - /* Check if already seen */ - if (Color_hd(hd) == Caml_blue) { - uintnat d = obj_counter - (uintnat) Field(v, 0); - if (d < 0x100) { - writecode8(CODE_SHARED8, d); - } else if (d < 0x10000) { - writecode16(CODE_SHARED16, d); -#ifdef ARCH_SIXTYFOUR - } else if (d >= (uintnat)1 << 32) { - writecode64(CODE_SHARED64, d); -#endif - } else { - writecode32(CODE_SHARED32, d); - } - goto next_item; - } - - /* Output the contents of the object */ - switch(tag) { - case String_tag: { - mlsize_t len = caml_string_length(v); - if (len < 0x20) { - write(PREFIX_SMALL_STRING + len); - } else if (len < 0x100) { - writecode8(CODE_STRING8, len); - } else { -#ifdef ARCH_SIXTYFOUR - if (len > 0xFFFFFB && (extern_flags & COMPAT_32)) - extern_failwith("output_value: string cannot be read back on " - "32-bit platform"); - if (len < (uintnat)1 << 32) - writecode32(CODE_STRING32, len); - else - writecode64(CODE_STRING64, len); -#else - writecode32(CODE_STRING32, len); -#endif - } - writeblock(String_val(v), len); - size_32 += 1 + (len + 4) / 4; - size_64 += 1 + (len + 8) / 8; - extern_record_location(v); - break; - } - case Double_tag: { - if (sizeof(double) != 8) - extern_invalid_argument("output_value: non-standard floats"); - write(CODE_DOUBLE_NATIVE); - writeblock_float8((double *) v, 1); - size_32 += 1 + 2; - size_64 += 1 + 1; - extern_record_location(v); - break; - } - case Double_array_tag: { - mlsize_t nfloats; - if (sizeof(double) != 8) - extern_invalid_argument("output_value: non-standard floats"); - nfloats = Wosize_val(v) / Double_wosize; - if (nfloats < 0x100) { - writecode8(CODE_DOUBLE_ARRAY8_NATIVE, nfloats); - } else { -#ifdef ARCH_SIXTYFOUR - if (nfloats > 0x1FFFFF && (extern_flags & COMPAT_32)) - extern_failwith("output_value: float array cannot be read back on " - "32-bit platform"); - if (nfloats < (uintnat) 1 << 32) - writecode32(CODE_DOUBLE_ARRAY32_NATIVE, nfloats); - else - writecode64(CODE_DOUBLE_ARRAY64_NATIVE, nfloats); -#else - writecode32(CODE_DOUBLE_ARRAY32_NATIVE, nfloats); -#endif - } - writeblock_float8((double *) v, nfloats); - size_32 += 1 + nfloats * 2; - size_64 += 1 + nfloats; - extern_record_location(v); - break; - } - case Abstract_tag: - extern_invalid_argument("output_value: abstract value (Abstract)"); - break; - case Infix_tag: - writecode32(CODE_INFIXPOINTER, Infix_offset_hd(hd)); - v = v - Infix_offset_hd(hd); /* PR#5772 */ - continue; - case Custom_tag: { - uintnat sz_32, sz_64; - char * ident = Custom_ops_val(v)->identifier; - void (*serialize)(value v, uintnat * bsize_32, - uintnat * bsize_64) - = Custom_ops_val(v)->serialize; - if (serialize == NULL) - extern_invalid_argument("output_value: abstract value (Custom)"); - write(CODE_CUSTOM); - writeblock(ident, strlen(ident) + 1); - Custom_ops_val(v)->serialize(v, &sz_32, &sz_64); - size_32 += 2 + ((sz_32 + 3) >> 2); /* header + ops + data */ - size_64 += 2 + ((sz_64 + 7) >> 3); - extern_record_location(v); - break; - } - default: { - value field0; - if (tag < 16 && sz < 8) { - write(PREFIX_SMALL_BLOCK + tag + (sz << 4)); - } else { -#ifdef ARCH_SIXTYFOUR -#ifdef WITH_PROFINFO - header_t hd_erased = Hd_no_profinfo(hd); -#else - header_t hd_erased = hd; -#endif - if (sz > 0x3FFFFF && (extern_flags & COMPAT_32)) - extern_failwith("output_value: array cannot be read back on " - "32-bit platform"); - if (hd_erased < (uintnat)1 << 32) - writecode32(CODE_BLOCK32, Whitehd_hd (hd_erased)); - else - writecode64(CODE_BLOCK64, Whitehd_hd (hd_erased)); -#else - writecode32(CODE_BLOCK32, Whitehd_hd (hd)); -#endif - } - size_32 += 1 + sz; - size_64 += 1 + sz; - field0 = Field(v, 0); - extern_record_location(v); - /* Remember that we still have to serialize fields 1 ... sz - 1 */ - if (sz > 1) { - sp++; - if (sp >= extern_stack_limit) sp = extern_resize_stack(sp); - sp->v = &Field(v,1); - sp->count = sz-1; - } - /* Continue serialization with the first field */ - v = field0; - continue; - } - } - } - else if ((cf = caml_extern_find_code((char *) v)) != NULL) { - if ((extern_flags & CLOSURES) == 0) - extern_invalid_argument("output_value: functional value"); - writecode32(CODE_CODEPOINTER, (char *) v - cf->code_start); - writeblock((const char *)cf->digest, 16); - } else { - extern_invalid_argument("output_value: abstract value (outside heap)"); - } - next_item: - /* Pop one more item to marshal, if any */ - if (sp == extern_stack) { - /* We are done. Cleanup the stack and leave the function */ - extern_free_stack(); - return; - } - v = *((sp->v)++); - if (--(sp->count) == 0) sp--; - } - /* Never reached as function leaves with return */ -} - -static int extern_flag_values[] = { NO_SHARING, CLOSURES, COMPAT_32 }; - -static intnat extern_value(value v, value flags, - /*out*/ char header[32], - /*out*/ int * header_len) -{ - intnat res_len; - /* Parse flag list */ - extern_flags = caml_convert_flag_list(flags, extern_flag_values); - /* Initializations */ - init_extern_trail(); - obj_counter = 0; - size_32 = 0; - size_64 = 0; - /* Marshal the object */ - extern_rec(v); - /* Record end of output */ - close_extern_output(); - /* Undo the modifications done on externed blocks */ - extern_replay_trail(); - /* Write the header */ - res_len = extern_output_length(); -#ifdef ARCH_SIXTYFOUR - if (res_len >= ((intnat)1 << 32) || - size_32 >= ((intnat)1 << 32) || size_64 >= ((intnat)1 << 32)) { - /* The object is too big for the small header format. - Fail if we are in compat32 mode, or use big header. */ - if (extern_flags & COMPAT_32) { - free_extern_output(); - caml_failwith("output_value: object too big to be read back on " - "32-bit platform"); - } - store32(header, Intext_magic_number_big); - store32(header + 4, 0); - store64(header + 8, res_len); - store64(header + 16, obj_counter); - store64(header + 24, size_64); - *header_len = 32; - return res_len; - } -#endif - /* Use the small header format */ - store32(header, Intext_magic_number_small); - store32(header + 4, res_len); - store32(header + 8, obj_counter); - store32(header + 12, size_32); - store32(header + 16, size_64); - *header_len = 20; - return res_len; -} - -void caml_output_val(struct channel *chan, value v, value flags) -{ - char header[32]; - int header_len; - struct output_block * blk, * nextblk; - - if (! caml_channel_binary_mode(chan)) - caml_failwith("output_value: not a binary channel"); - init_extern_output(); - extern_value(v, flags, header, &header_len); - /* During [caml_really_putblock], concurrent [caml_output_val] operations - can take place (via signal handlers or context switching in systhreads), - and [extern_output_first] may change. So, save it in a local variable. */ - blk = extern_output_first; - caml_really_putblock(chan, header, header_len); - while (blk != NULL) { - caml_really_putblock(chan, blk->data, blk->end - blk->data); - nextblk = blk->next; - caml_stat_free(blk); - blk = nextblk; - } -} - -CAMLprim value caml_output_value(value vchan, value v, value flags) -{ - CAMLparam3 (vchan, v, flags); - struct channel * channel = Channel(vchan); - - Lock(channel); - caml_output_val(channel, v, flags); - Unlock(channel); - CAMLreturn (Val_unit); -} - -CAMLprim value caml_output_value_to_bytes(value v, value flags) -{ - char header[32]; - int header_len; - intnat data_len, ofs; - value res; - struct output_block * blk, * nextblk; - - init_extern_output(); - data_len = extern_value(v, flags, header, &header_len); - /* PR#4030: it is prudent to save extern_output_first before allocating - the result, as in caml_output_val */ - blk = extern_output_first; - res = caml_alloc_string(header_len + data_len); - ofs = 0; - memcpy(&Byte(res, ofs), header, header_len); - ofs += header_len; - while (blk != NULL) { - int n = blk->end - blk->data; - memcpy(&Byte(res, ofs), blk->data, n); - ofs += n; - nextblk = blk->next; - caml_stat_free(blk); - blk = nextblk; - } - return res; -} - -CAMLprim value caml_output_value_to_string(value v, value flags) -{ - return caml_output_value_to_bytes(v,flags); -} - -CAMLexport intnat caml_output_value_to_block(value v, value flags, - char * buf, intnat len) -{ - char header[32]; - int header_len; - intnat data_len; - /* At this point we don't know the size of the header. - Guess that it is small, and fix up later if not. */ - extern_userprovided_output = buf + 20; - extern_ptr = extern_userprovided_output; - extern_limit = buf + len; - data_len = extern_value(v, flags, header, &header_len); - if (header_len != 20) { - /* Bad guess! Need to shift the output to make room for big header. - Make sure there is room. */ - if (header_len + data_len > len) - caml_failwith("Marshal.to_buffer: buffer overflow"); - memmove(buf + header_len, buf + 20, data_len); - } - memcpy(buf, header, header_len); - return header_len + data_len; -} - -CAMLprim value caml_output_value_to_buffer(value buf, value ofs, value len, - value v, value flags) -{ - intnat l = - caml_output_value_to_block(v, flags, - &Byte(buf, Long_val(ofs)), Long_val(len)); - return Val_long(l); -} - -CAMLexport void caml_output_value_to_malloc(value v, value flags, - /*out*/ char ** buf, - /*out*/ intnat * len) -{ - char header[32]; - int header_len; - intnat data_len; - char * res; - struct output_block * blk; - - init_extern_output(); - data_len = extern_value(v, flags, header, &header_len); - res = caml_stat_alloc_noexc(header_len + data_len); - if (res == NULL) extern_out_of_memory(); - *buf = res; - *len = header_len + data_len; - memcpy(res, header, header_len); - res += header_len; - for (blk = extern_output_first; blk != NULL; blk = blk->next) { - int n = blk->end - blk->data; - memcpy(res, blk->data, n); - res += n; - } - free_extern_output(); -} - -/* Functions for writing user-defined marshallers */ - -CAMLexport void caml_serialize_int_1(int i) -{ - if (extern_ptr + 1 > extern_limit) grow_extern_output(1); - extern_ptr[0] = i; - extern_ptr += 1; -} - -CAMLexport void caml_serialize_int_2(int i) -{ - if (extern_ptr + 2 > extern_limit) grow_extern_output(2); - store16(extern_ptr, i); - extern_ptr += 2; -} - -CAMLexport void caml_serialize_int_4(int32_t i) -{ - if (extern_ptr + 4 > extern_limit) grow_extern_output(4); - store32(extern_ptr, i); - extern_ptr += 4; -} - -CAMLexport void caml_serialize_int_8(int64_t i) -{ - if (extern_ptr + 8 > extern_limit) grow_extern_output(8); - store64(extern_ptr, i); - extern_ptr += 8; -} - -CAMLexport void caml_serialize_float_4(float f) -{ - caml_serialize_block_4(&f, 1); -} - -CAMLexport void caml_serialize_float_8(double f) -{ - caml_serialize_block_float_8(&f, 1); -} - -CAMLexport void caml_serialize_block_1(void * data, intnat len) -{ - if (extern_ptr + len > extern_limit) grow_extern_output(len); - memcpy(extern_ptr, data, len); - extern_ptr += len; -} - -CAMLexport void caml_serialize_block_2(void * data, intnat len) -{ - if (extern_ptr + 2 * len > extern_limit) grow_extern_output(2 * len); -#ifndef ARCH_BIG_ENDIAN - { - unsigned char * p; - char * q; - for (p = data, q = extern_ptr; len > 0; len--, p += 2, q += 2) - Reverse_16(q, p); - extern_ptr = q; - } -#else - memcpy(extern_ptr, data, len * 2); - extern_ptr += len * 2; -#endif -} - -CAMLexport void caml_serialize_block_4(void * data, intnat len) -{ - if (extern_ptr + 4 * len > extern_limit) grow_extern_output(4 * len); -#ifndef ARCH_BIG_ENDIAN - { - unsigned char * p; - char * q; - for (p = data, q = extern_ptr; len > 0; len--, p += 4, q += 4) - Reverse_32(q, p); - extern_ptr = q; - } -#else - memcpy(extern_ptr, data, len * 4); - extern_ptr += len * 4; -#endif -} - -CAMLexport void caml_serialize_block_8(void * data, intnat len) -{ - if (extern_ptr + 8 * len > extern_limit) grow_extern_output(8 * len); -#ifndef ARCH_BIG_ENDIAN - { - unsigned char * p; - char * q; - for (p = data, q = extern_ptr; len > 0; len--, p += 8, q += 8) - Reverse_64(q, p); - extern_ptr = q; - } -#else - memcpy(extern_ptr, data, len * 8); - extern_ptr += len * 8; -#endif -} - -CAMLexport void caml_serialize_block_float_8(void * data, intnat len) -{ - if (extern_ptr + 8 * len > extern_limit) grow_extern_output(8 * len); -#if ARCH_FLOAT_ENDIANNESS == 0x01234567 - memcpy(extern_ptr, data, len * 8); - extern_ptr += len * 8; -#elif ARCH_FLOAT_ENDIANNESS == 0x76543210 - { - unsigned char * p; - char * q; - for (p = data, q = extern_ptr; len > 0; len--, p += 8, q += 8) - Reverse_64(q, p); - extern_ptr = q; - } -#else - { - unsigned char * p; - char * q; - for (p = data, q = extern_ptr; len > 0; len--, p += 8, q += 8) - Permute_64(q, 0x01234567, p, ARCH_FLOAT_ENDIANNESS); - extern_ptr = q; - } -#endif -} - -/* Find where a code pointer comes from */ - -CAMLexport struct code_fragment * caml_extern_find_code(char *addr) -{ - int i; - for (i = caml_code_fragments_table.size - 1; i >= 0; i--) { - struct code_fragment * cf = caml_code_fragments_table.contents[i]; - if (! cf->digest_computed) { - caml_md5_block(cf->digest, cf->code_start, cf->code_end - cf->code_start); - cf->digest_computed = 1; - } - if (cf->code_start <= addr && addr < cf->code_end) return cf; - } - return NULL; -} diff --git a/byterun/fail.c b/byterun/fail.c deleted file mode 100644 index 6b4dee5f..00000000 --- a/byterun/fail.c +++ /dev/null @@ -1,204 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Raising exceptions from C. */ - -#include -#include -#include "caml/alloc.h" -#include "caml/fail.h" -#include "caml/io.h" -#include "caml/gc.h" -#include "caml/memory.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/printexc.h" -#include "caml/signals.h" -#include "caml/stacks.h" - -CAMLexport struct longjmp_buffer * caml_external_raise = NULL; -value caml_exn_bucket; - -CAMLexport void caml_raise(value v) -{ - Unlock_exn(); - caml_exn_bucket = v; - if (caml_external_raise == NULL) caml_fatal_uncaught_exception(v); - siglongjmp(caml_external_raise->buf, 1); -} - -CAMLexport void caml_raise_constant(value tag) -{ - caml_raise(tag); -} - -CAMLexport void caml_raise_with_arg(value tag, value arg) -{ - CAMLparam2 (tag, arg); - CAMLlocal1 (bucket); - - bucket = caml_alloc_small (2, 0); - Field(bucket, 0) = tag; - Field(bucket, 1) = arg; - caml_raise(bucket); - CAMLnoreturn; -} - -CAMLexport void caml_raise_with_args(value tag, int nargs, value args[]) -{ - CAMLparam1 (tag); - CAMLxparamN (args, nargs); - value bucket; - int i; - - CAMLassert(1 + nargs <= Max_young_wosize); - bucket = caml_alloc_small (1 + nargs, 0); - Field(bucket, 0) = tag; - for (i = 0; i < nargs; i++) Field(bucket, 1 + i) = args[i]; - caml_raise(bucket); - CAMLnoreturn; -} - -CAMLexport void caml_raise_with_string(value tag, char const *msg) -{ - CAMLparam1(tag); - value v_msg = caml_copy_string(msg); - caml_raise_with_arg(tag, v_msg); - CAMLnoreturn; -} - -/* PR#5115: Built-in exceptions can be triggered by input_value - while reading the initial value of [caml_global_data]. - - We check against this issue here in byterun/fail.c instead of - byterun/intern.c. Having the check here means that these calls will - be slightly slower for all bytecode programs (not just the calls - coming from intern). Because intern.c is shared between byterun/ - and asmrun/, putting checks there would slow do input_value for - natively-compiled programs that do not need these checks. -*/ -static void check_global_data(char const *exception_name) -{ - if (caml_global_data == 0) { - fprintf(stderr, "Fatal error: exception %s\n", exception_name); - exit(2); - } -} - -static void check_global_data_param(char const *exception_name, char const *msg) -{ - if (caml_global_data == 0) { - fprintf(stderr, "Fatal error: exception %s(\"%s\")\n", exception_name, msg); - exit(2); - } -} - -static inline value caml_get_failwith_tag (char const *msg) -{ - check_global_data_param("Failure", msg); - return Field(caml_global_data, FAILURE_EXN); -} - -CAMLexport void caml_failwith (char const *msg) -{ - caml_raise_with_string(caml_get_failwith_tag(msg), msg); -} - -CAMLexport void caml_failwith_value (value msg) -{ - CAMLparam1(msg); - value tag = caml_get_failwith_tag(String_val(msg)); - caml_raise_with_arg(tag, msg); - CAMLnoreturn; -} - -static inline value caml_get_invalid_argument_tag (char const *msg) -{ - check_global_data_param("Invalid_argument", msg); - return Field(caml_global_data, INVALID_EXN); -} - -CAMLexport void caml_invalid_argument (char const *msg) -{ - caml_raise_with_string(caml_get_invalid_argument_tag(msg), msg); -} - -CAMLexport void caml_invalid_argument_value (value msg) -{ - CAMLparam1(msg); - value tag = caml_get_invalid_argument_tag(String_val(msg)); - caml_raise_with_arg(tag, msg); - CAMLnoreturn; -} - -CAMLexport void caml_array_bound_error(void) -{ - caml_invalid_argument("index out of bounds"); -} - -CAMLexport void caml_raise_out_of_memory(void) -{ - check_global_data("Out_of_memory"); - caml_raise_constant(Field(caml_global_data, OUT_OF_MEMORY_EXN)); -} - -CAMLexport void caml_raise_stack_overflow(void) -{ - check_global_data("Stack_overflow"); - caml_raise_constant(Field(caml_global_data, STACK_OVERFLOW_EXN)); -} - -CAMLexport void caml_raise_sys_error(value msg) -{ - check_global_data_param("Sys_error", String_val(msg)); - caml_raise_with_arg(Field(caml_global_data, SYS_ERROR_EXN), msg); -} - -CAMLexport void caml_raise_end_of_file(void) -{ - check_global_data("End_of_file"); - caml_raise_constant(Field(caml_global_data, END_OF_FILE_EXN)); -} - -CAMLexport void caml_raise_zero_divide(void) -{ - check_global_data("Division_by_zero"); - caml_raise_constant(Field(caml_global_data, ZERO_DIVIDE_EXN)); -} - -CAMLexport void caml_raise_not_found(void) -{ - check_global_data("Not_found"); - caml_raise_constant(Field(caml_global_data, NOT_FOUND_EXN)); -} - -CAMLexport void caml_raise_sys_blocked_io(void) -{ - check_global_data("Sys_blocked_io"); - caml_raise_constant(Field(caml_global_data, SYS_BLOCKED_IO)); -} - -int caml_is_special_exception(value exn) { - /* this function is only used in caml_format_exception to produce - a more readable textual representation of some exceptions. It is - better to fall back to the general, less readable representation - than to abort with a fatal error as above. */ - if (caml_global_data == 0) return 0; - return exn == Field(caml_global_data, MATCH_FAILURE_EXN) - || exn == Field(caml_global_data, ASSERT_FAILURE_EXN) - || exn == Field(caml_global_data, UNDEFINED_RECURSIVE_MODULE_EXN); -} diff --git a/byterun/fix_code.c b/byterun/fix_code.c deleted file mode 100644 index ec2f08cc..00000000 --- a/byterun/fix_code.c +++ /dev/null @@ -1,195 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Handling of blocks of bytecode (endianness switch, threading). */ - -#include "caml/config.h" - -#ifdef HAS_UNISTD -#include -#else -#include -#endif - -#include "caml/debugger.h" -#include "caml/fix_code.h" -#include "caml/instruct.h" -#include "caml/intext.h" -#include "caml/md5.h" -#include "caml/memory.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/reverse.h" - -code_t caml_start_code; -asize_t caml_code_size; -unsigned char * caml_saved_code; -struct ext_table caml_code_fragments_table; - -/* Read the main bytecode block from a file */ - -void caml_init_code_fragments(void) { - struct code_fragment * cf; - /* Register the code in the table of code fragments */ - cf = caml_stat_alloc(sizeof(struct code_fragment)); - cf->code_start = (char *) caml_start_code; - cf->code_end = (char *) caml_start_code + caml_code_size; - caml_md5_block(cf->digest, caml_start_code, caml_code_size); - cf->digest_computed = 1; - caml_ext_table_init(&caml_code_fragments_table, 8); - caml_ext_table_add(&caml_code_fragments_table, cf); -} - -void caml_load_code(int fd, asize_t len) -{ - int i; - - caml_code_size = len; - caml_start_code = (code_t) caml_stat_alloc(caml_code_size); - if (read(fd, (char *) caml_start_code, caml_code_size) != caml_code_size) - caml_fatal_error("Fatal error: truncated bytecode file.\n"); - caml_init_code_fragments(); - /* Prepare the code for execution */ -#ifdef ARCH_BIG_ENDIAN - caml_fixup_endianness(caml_start_code, caml_code_size); -#endif - if (caml_debugger_in_use) { - len /= sizeof(opcode_t); - caml_saved_code = (unsigned char *) caml_stat_alloc(len); - for (i = 0; i < len; i++) caml_saved_code[i] = caml_start_code[i]; - } -#ifdef THREADED_CODE - /* Better to thread now than at the beginning of [caml_interprete], - since the debugger interface needs to perform SET_EVENT requests - on the code. */ - caml_thread_code(caml_start_code, caml_code_size); -#endif -} - -/* This code is needed only if the processor is big endian */ - -#ifdef ARCH_BIG_ENDIAN - -void caml_fixup_endianness(code_t code, asize_t len) -{ - code_t p; - len /= sizeof(opcode_t); - for (p = code; p < code + len; p++) { - Reverse_32(p, p); - } -} - -#endif - -/* This code is needed only if we're using threaded code */ - -#ifdef THREADED_CODE - -char ** caml_instr_table; -char * caml_instr_base; - -static int* opcode_nargs = NULL; -int* caml_init_opcode_nargs(void) -{ - if( opcode_nargs == NULL ){ - int* l = (int*)caml_stat_alloc(sizeof(int) * FIRST_UNIMPLEMENTED_OP); - int i; - - for (i = 0; i < FIRST_UNIMPLEMENTED_OP; i++) { - l [i] = 0; - } - /* Instructions with one operand */ - l[PUSHACC] = l[ACC] = l[POP] = l[ASSIGN] = - l[PUSHENVACC] = l[ENVACC] = l[PUSH_RETADDR] = l[APPLY] = - l[APPTERM1] = l[APPTERM2] = l[APPTERM3] = l[RETURN] = - l[GRAB] = l[PUSHGETGLOBAL] = l[GETGLOBAL] = l[SETGLOBAL] = - l[PUSHATOM] = l[ATOM] = l[MAKEBLOCK1] = l[MAKEBLOCK2] = - l[MAKEBLOCK3] = l[MAKEFLOATBLOCK] = l[GETFIELD] = - l[GETFLOATFIELD] = l[SETFIELD] = l[SETFLOATFIELD] = - l[BRANCH] = l[BRANCHIF] = l[BRANCHIFNOT] = l[PUSHTRAP] = - l[C_CALL1] = l[C_CALL2] = l[C_CALL3] = l[C_CALL4] = l[C_CALL5] = - l[CONSTINT] = l[PUSHCONSTINT] = l[OFFSETINT] = - l[OFFSETREF] = l[OFFSETCLOSURE] = l[PUSHOFFSETCLOSURE] = 1; - - /* Instructions with two operands */ - l[APPTERM] = l[CLOSURE] = l[PUSHGETGLOBALFIELD] = - l[GETGLOBALFIELD] = l[MAKEBLOCK] = l[C_CALLN] = - l[BEQ] = l[BNEQ] = l[BLTINT] = l[BLEINT] = l[BGTINT] = l[BGEINT] = - l[BULTINT] = l[BUGEINT] = l[GETPUBMET] = 2; - - opcode_nargs = l; - } - return opcode_nargs; -} - -void caml_thread_code (code_t code, asize_t len) -{ - code_t p; - int* l = caml_init_opcode_nargs(); - len /= sizeof(opcode_t); - for (p = code; p < code + len; /*nothing*/) { - opcode_t instr = *p; - if (instr < 0 || instr >= FIRST_UNIMPLEMENTED_OP){ - /* FIXME -- should Assert(false) ? - caml_fatal_error_arg ("Fatal error in fix_code: bad opcode (%lx)\n", - (char *)(long)instr); - */ - instr = STOP; - } - *p++ = (opcode_t)(caml_instr_table[instr] - caml_instr_base); - if (instr == SWITCH) { - uint32_t sizes = *p++; - uint32_t const_size = sizes & 0xFFFF; - uint32_t block_size = sizes >> 16; - p += const_size + block_size; - } else if (instr == CLOSUREREC) { - uint32_t nfuncs = *p++; - p++; /* skip nvars */ - p += nfuncs; - } else { - p += l[instr]; - } - } - CAMLassert(p == code + len); -} - -#else - -int* caml_init_opcode_nargs() -{ - return NULL; -} - -#endif /* THREADED_CODE */ - -void caml_set_instruction(code_t pos, opcode_t instr) -{ -#ifdef THREADED_CODE - *pos = (opcode_t)(caml_instr_table[instr] - caml_instr_base); -#else - *pos = instr; -#endif -} - -int caml_is_instruction(opcode_t instr1, opcode_t instr2) -{ -#ifdef THREADED_CODE - return instr1 == (opcode_t)(caml_instr_table[instr2] - caml_instr_base); -#else - return instr1 == instr2; -#endif -} diff --git a/byterun/floats.c b/byterun/floats.c deleted file mode 100644 index 4d2494cf..00000000 --- a/byterun/floats.c +++ /dev/null @@ -1,720 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* The interface of this file is in "caml/mlvalues.h" and "caml/alloc.h" */ - -#include -#include -#include -#include -#include -#include - -#include "caml/alloc.h" -#include "caml/fail.h" -#include "caml/memory.h" -#include "caml/mlvalues.h" -#include "caml/misc.h" -#include "caml/reverse.h" -#include "caml/stacks.h" - -#ifdef _MSC_VER -#include -#ifndef isnan -#define isnan _isnan -#endif -#ifndef isfinite -#define isfinite _finite -#endif -#endif - -#ifdef ARCH_ALIGN_DOUBLE - -CAMLexport double caml_Double_val(value val) -{ - union { value v[2]; double d; } buffer; - - CAMLassert(sizeof(double) == 2 * sizeof(value)); - buffer.v[0] = Field(val, 0); - buffer.v[1] = Field(val, 1); - return buffer.d; -} - -CAMLexport void caml_Store_double_val(value val, double dbl) -{ - union { value v[2]; double d; } buffer; - - CAMLassert(sizeof(double) == 2 * sizeof(value)); - buffer.d = dbl; - Field(val, 0) = buffer.v[0]; - Field(val, 1) = buffer.v[1]; -} - -#endif - -CAMLexport value caml_copy_double(double d) -{ - value res; - -#define Setup_for_gc -#define Restore_after_gc - Alloc_small(res, Double_wosize, Double_tag); -#undef Setup_for_gc -#undef Restore_after_gc - Store_double_val(res, d); - return res; -} - -#ifndef FLAT_FLOAT_ARRAY -CAMLexport void caml_Store_double_array_field(value val, mlsize_t i, double dbl) -{ - CAMLparam1 (val); - value d = caml_copy_double (dbl); - - CAMLassert (Tag_val (val) != Double_array_tag); - caml_modify (&Field(val, i), d); - CAMLreturn0; -} -#endif /* ! FLAT_FLOAT_ARRAY */ - -CAMLprim value caml_format_float(value fmt, value arg) -{ - value res; - double d = Double_val(arg); - -#ifdef HAS_BROKEN_PRINTF - if (isfinite(d)) { -#endif - res = caml_alloc_sprintf(String_val(fmt), d); -#ifdef HAS_BROKEN_PRINTF - } else { - if (isnan(d)) { - res = caml_copy_string("nan"); - } else { - if (d > 0) - res = caml_copy_string("inf"); - else - res = caml_copy_string("-inf"); - } - } -#endif - return res; -} - -CAMLprim value caml_hexstring_of_float(value arg, value vprec, value vstyle) -{ - union { uint64_t i; double d; } u; - int sign, exp; - uint64_t m; - char buffer[64]; - char * buf, * p; - intnat prec; - int d; - value res; - - /* Allocate output buffer */ - prec = Long_val(vprec); - /* 12 chars for sign, 0x, decimal point, exponent */ - buf = (prec + 12 <= 64 ? buffer : caml_stat_alloc(prec + 12)); - /* Extract sign, mantissa, and exponent */ - u.d = Double_val(arg); - sign = u.i >> 63; - exp = (u.i >> 52) & 0x7FF; - m = u.i & (((uint64_t) 1 << 52) - 1); - /* Put sign */ - p = buf; - if (sign) { - *p++ = '-'; - } else { - switch (Int_val(vstyle)) { - case '+': *p++ = '+'; break; - case ' ': *p++ = ' '; break; - } - } - /* Treat special cases */ - if (exp == 0x7FF) { - char * txt; - if (m == 0) txt = "infinity"; else txt = "nan"; - memcpy(p, txt, strlen(txt)); - p[strlen(txt)] = 0; - res = caml_copy_string(buf); - } else { - /* Output "0x" prefix */ - *p++ = '0'; *p++ = 'x'; - /* Normalize exponent and mantissa */ - if (exp == 0) { - if (m != 0) exp = -1022; /* denormal */ - } else { - exp = exp - 1023; - m = m | ((uint64_t) 1 << 52); - } - /* If a precision is given, and is small, round mantissa accordingly */ - prec = Long_val(vprec); - if (prec >= 0 && prec < 13) { - int i = 52 - prec * 4; - uint64_t unit = (uint64_t) 1 << i; - uint64_t half = unit >> 1; - uint64_t mask = unit - 1; - uint64_t frac = m & mask; - m = m & ~mask; - /* Round to nearest, ties to even */ - if (frac > half || (frac == half && (m & unit) != 0)) { - m += unit; - } - } - /* Leading digit */ - d = m >> 52; - *p++ = (d < 10 ? d + '0' : d - 10 + 'a'); - m = (m << 4) & (((uint64_t) 1 << 56) - 1); - /* Fractional digits. If a precision is given, print that number of - digits. Otherwise, print as many digits as needed to represent - the mantissa exactly. */ - if (prec >= 0 ? prec > 0 : m != 0) { - *p++ = '.'; - while (prec >= 0 ? prec > 0 : m != 0) { - d = m >> 52; - *p++ = (d < 10 ? d + '0' : d - 10 + 'a'); - m = (m << 4) & (((uint64_t) 1 << 56) - 1); - prec--; - } - } - *p = 0; - /* Add exponent */ - res = caml_alloc_sprintf("%sp%+d", buf, exp); - } - if (buf != buffer) caml_stat_free(buf); - return res; -} - -static int caml_float_of_hex(const char * s, double * res) -{ - int64_t m = 0; /* the mantissa - top 60 bits at most */ - int n_bits = 0; /* total number of bits read */ - int m_bits = 0; /* number of bits in mantissa */ - int x_bits = 0; /* number of bits after mantissa */ - int dec_point = -1; /* bit count corresponding to decimal point */ - /* -1 if no decimal point seen */ - int exp = 0; /* exponent */ - char * p; /* for converting the exponent */ - double f; - - while (*s != 0) { - char c = *s++; - switch (c) { - case '_': - break; - case '.': - if (dec_point >= 0) return -1; /* multiple decimal points */ - dec_point = n_bits; - break; - case 'p': case 'P': { - long e; - if (*s == 0) return -1; /* nothing after exponent mark */ - e = strtol(s, &p, 10); - if (*p != 0) return -1; /* ill-formed exponent */ - /* Handle exponents larger than int by returning 0/∞ directly. - Mind that INT_MIN/INT_MAX are included in the test so as to capture - the overflow case of strtol on Win64 — long and int have the same - size there. */ - if (e <= INT_MIN) { - *res = 0.; - return 0; - } - else if (e >= INT_MAX) { - *res = m == 0 ? 0. : HUGE_VAL; - return 0; - } - /* regular exponent value */ - exp = e; - s = p; /* stop at next loop iteration */ - break; - } - default: { /* Nonzero digit */ - int d; - if (c >= '0' && c <= '9') d = c - '0'; - else if (c >= 'A' && c <= 'F') d = c - 'A' + 10; - else if (c >= 'a' && c <= 'f') d = c - 'a' + 10; - else return -1; /* bad digit */ - n_bits += 4; - if (d == 0 && m == 0) break; /* leading zeros are skipped */ - if (m_bits < 60) { - /* There is still room in m. Add this digit to the mantissa. */ - m = (m << 4) + d; - m_bits += 4; - } else { - /* We've already collected 60 significant bits in m. - Now all we care about is whether there is a nonzero bit - after. In this case, round m to odd so that the later - rounding of m to FP produces the correct result. */ - if (d != 0) m |= 1; /* round to odd */ - x_bits += 4; - } - break; - } - } - } - if (n_bits == 0) return -1; - /* Convert mantissa to FP. We use a signed conversion because we can - (m has 60 bits at most) and because it is faster - on several architectures. */ - f = (double) (int64_t) m; - /* Adjust exponent to take decimal point and extra digits into account */ - { - int adj = x_bits; - if (dec_point >= 0) adj = adj + (dec_point - n_bits); - /* saturated addition exp + adj */ - if (adj > 0 && exp > INT_MAX - adj) - exp = INT_MAX; - else if (adj < 0 && exp < INT_MIN - adj) - exp = INT_MIN; - else - exp = exp + adj; - } - /* Apply exponent if needed */ - if (exp != 0) f = ldexp(f, exp); - /* Done! */ - *res = f; - return 0; -} - -CAMLprim value caml_float_of_string(value vs) -{ - char parse_buffer[64]; - char * buf, * dst, * end; - const char *src; - mlsize_t len; - int sign; - double d; - - /* Check for hexadecimal FP constant */ - src = String_val(vs); - sign = 1; - if (*src == '-') { sign = -1; src++; } - else if (*src == '+') { src++; }; - if (src[0] == '0' && (src[1] == 'x' || src[1] == 'X')) { - if (caml_float_of_hex(src + 2, &d) == -1) - caml_failwith("float_of_string"); - return caml_copy_double(sign < 0 ? -d : d); - } - /* Remove '_' characters before calling strtod () */ - len = caml_string_length(vs); - buf = len < sizeof(parse_buffer) ? parse_buffer : caml_stat_alloc(len + 1); - src = String_val(vs); - dst = buf; - while (len--) { - char c = *src++; - if (c != '_') *dst++ = c; - } - *dst = 0; - if (dst == buf) goto error; - /* Convert using strtod */ - d = strtod((const char *) buf, &end); - if (end != dst) goto error; - if (buf != parse_buffer) caml_stat_free(buf); - return caml_copy_double(d); - error: - if (buf != parse_buffer) caml_stat_free(buf); - caml_failwith("float_of_string"); - return Val_unit; /* not reached */ -} - -CAMLprim value caml_int_of_float(value f) -{ - return Val_long((intnat) Double_val(f)); -} - -CAMLprim value caml_float_of_int(value n) -{ - return caml_copy_double((double) Long_val(n)); -} - -CAMLprim value caml_neg_float(value f) -{ - return caml_copy_double(- Double_val(f)); -} - -CAMLprim value caml_abs_float(value f) -{ - return caml_copy_double(fabs(Double_val(f))); -} - -CAMLprim value caml_add_float(value f, value g) -{ - return caml_copy_double(Double_val(f) + Double_val(g)); -} - -CAMLprim value caml_sub_float(value f, value g) -{ - return caml_copy_double(Double_val(f) - Double_val(g)); -} - -CAMLprim value caml_mul_float(value f, value g) -{ - return caml_copy_double(Double_val(f) * Double_val(g)); -} - -CAMLprim value caml_div_float(value f, value g) -{ - return caml_copy_double(Double_val(f) / Double_val(g)); -} - -CAMLprim value caml_exp_float(value f) -{ - return caml_copy_double(exp(Double_val(f))); -} - -CAMLprim value caml_floor_float(value f) -{ - return caml_copy_double(floor(Double_val(f))); -} - -CAMLprim value caml_fmod_float(value f1, value f2) -{ - return caml_copy_double(fmod(Double_val(f1), Double_val(f2))); -} - -CAMLprim value caml_frexp_float(value f) -{ - CAMLparam1 (f); - CAMLlocal2 (res, mantissa); - int exponent; - - mantissa = caml_copy_double(frexp (Double_val(f), &exponent)); - res = caml_alloc_tuple(2); - Field(res, 0) = mantissa; - Field(res, 1) = Val_int(exponent); - CAMLreturn (res); -} - -// Seems dumb but intnat could not correspond to int type. -double caml_ldexp_float_unboxed(double f, intnat i) -{ - return ldexp(f, i); -} - - -CAMLprim value caml_ldexp_float(value f, value i) -{ - return caml_copy_double(ldexp(Double_val(f), Int_val(i))); -} - -CAMLprim value caml_log_float(value f) -{ - return caml_copy_double(log(Double_val(f))); -} - -CAMLprim value caml_log10_float(value f) -{ - return caml_copy_double(log10(Double_val(f))); -} - -CAMLprim value caml_modf_float(value f) -{ - double frem; - - CAMLparam1 (f); - CAMLlocal3 (res, quo, rem); - - quo = caml_copy_double(modf (Double_val(f), &frem)); - rem = caml_copy_double(frem); - res = caml_alloc_tuple(2); - Field(res, 0) = quo; - Field(res, 1) = rem; - CAMLreturn (res); -} - -CAMLprim value caml_sqrt_float(value f) -{ - return caml_copy_double(sqrt(Double_val(f))); -} - -CAMLprim value caml_power_float(value f, value g) -{ - return caml_copy_double(pow(Double_val(f), Double_val(g))); -} - -CAMLprim value caml_sin_float(value f) -{ - return caml_copy_double(sin(Double_val(f))); -} - -CAMLprim value caml_sinh_float(value f) -{ - return caml_copy_double(sinh(Double_val(f))); -} - -CAMLprim value caml_cos_float(value f) -{ - return caml_copy_double(cos(Double_val(f))); -} - -CAMLprim value caml_cosh_float(value f) -{ - return caml_copy_double(cosh(Double_val(f))); -} - -CAMLprim value caml_tan_float(value f) -{ - return caml_copy_double(tan(Double_val(f))); -} - -CAMLprim value caml_tanh_float(value f) -{ - return caml_copy_double(tanh(Double_val(f))); -} - -CAMLprim value caml_asin_float(value f) -{ - return caml_copy_double(asin(Double_val(f))); -} - -CAMLprim value caml_acos_float(value f) -{ - return caml_copy_double(acos(Double_val(f))); -} - -CAMLprim value caml_atan_float(value f) -{ - return caml_copy_double(atan(Double_val(f))); -} - -CAMLprim value caml_atan2_float(value f, value g) -{ - return caml_copy_double(atan2(Double_val(f), Double_val(g))); -} - -CAMLprim value caml_ceil_float(value f) -{ - return caml_copy_double(ceil(Double_val(f))); -} - -CAMLexport double caml_hypot(double x, double y) -{ -#ifdef HAS_C99_FLOAT_OPS - return hypot(x, y); -#else - double tmp, ratio; - x = fabs(x); y = fabs(y); - if (x != x) /* x is NaN */ - return y > DBL_MAX ? y : x; /* PR#6321 */ - if (y != y) /* y is NaN */ - return x > DBL_MAX ? x : y; /* PR#6321 */ - if (x < y) { tmp = x; x = y; y = tmp; } - if (x == 0.0) return 0.0; - ratio = y / x; - return x * sqrt(1.0 + ratio * ratio); -#endif -} - -CAMLprim value caml_hypot_float(value f, value g) -{ - return caml_copy_double(caml_hypot(Double_val(f), Double_val(g))); -} - -/* These emulations of expm1() and log1p() are due to William Kahan. - See http://www.plunk.org/~hatch/rightway.php */ -CAMLexport double caml_expm1(double x) -{ -#ifdef HAS_C99_FLOAT_OPS - return expm1(x); -#else - double u = exp(x); - if (u == 1.) - return x; - if (u - 1. == -1.) - return -1.; - return (u - 1.) * x / log(u); -#endif -} - -CAMLexport double caml_log1p(double x) -{ -#ifdef HAS_C99_FLOAT_OPS - return log1p(x); -#else - double u = 1. + x; - if (u == 1.) - return x; - else - return log(u) * x / (u - 1.); -#endif -} - -CAMLprim value caml_expm1_float(value f) -{ - return caml_copy_double(caml_expm1(Double_val(f))); -} - -CAMLprim value caml_log1p_float(value f) -{ - return caml_copy_double(caml_log1p(Double_val(f))); -} - -union double_as_two_int32 { - double d; -#if defined(ARCH_BIG_ENDIAN) || (defined(__arm__) && !defined(__ARM_EABI__)) - struct { uint32_t h; uint32_t l; } i; -#else - struct { uint32_t l; uint32_t h; } i; -#endif -}; - -CAMLexport double caml_copysign(double x, double y) -{ -#ifdef HAS_C99_FLOAT_OPS - return copysign(x, y); -#else - union double_as_two_int32 ux, uy; - ux.d = x; - uy.d = y; - ux.i.h &= 0x7FFFFFFFU; - ux.i.h |= (uy.i.h & 0x80000000U); - return ux.d; -#endif -} - -CAMLprim value caml_copysign_float(value f, value g) -{ - return caml_copy_double(caml_copysign(Double_val(f), Double_val(g))); -} - -#ifdef LACKS_SANE_NAN - -CAMLprim value caml_neq_float(value vf, value vg) -{ - double f = Double_val(vf); - double g = Double_val(vg); - return Val_bool(isnan(f) || isnan(g) || f != g); -} - -#define DEFINE_NAN_CMP(op) (value vf, value vg) \ -{ \ - double f = Double_val(vf); \ - double g = Double_val(vg); \ - return Val_bool(!isnan(f) && !isnan(g) && f op g); \ -} - -intnat caml_float_compare_unboxed(double f, double g) -{ - /* Insane => nan == everything && nan < everything && nan > everything */ - if (isnan(f) && isnan(g)) return 0; - if (!isnan(g) && f < g) return -1; - if (f != g) return 1; - return 0; -} - -#else - -CAMLprim value caml_neq_float(value f, value g) -{ - return Val_bool(Double_val(f) != Double_val(g)); -} - -#define DEFINE_NAN_CMP(op) (value f, value g) \ -{ \ - return Val_bool(Double_val(f) op Double_val(g)); \ -} - -intnat caml_float_compare_unboxed(double f, double g) -{ - /* If one or both of f and g is NaN, order according to the convention - NaN = NaN and NaN < x for all other floats x. */ - /* This branchless implementation is from GPR#164. - Note that [f == f] if and only if f is not NaN. */ - return (f > g) - (f < g) + (f == f) - (g == g); -} - -#endif - -CAMLprim value caml_eq_float DEFINE_NAN_CMP(==) -CAMLprim value caml_le_float DEFINE_NAN_CMP(<=) -CAMLprim value caml_lt_float DEFINE_NAN_CMP(<) -CAMLprim value caml_ge_float DEFINE_NAN_CMP(>=) -CAMLprim value caml_gt_float DEFINE_NAN_CMP(>) - -CAMLprim value caml_float_compare(value vf, value vg) -{ - return Val_int(caml_float_compare_unboxed(Double_val(vf),Double_val(vg))); -} - -enum { FP_normal, FP_subnormal, FP_zero, FP_infinite, FP_nan }; - -value caml_classify_float_unboxed(double vd) -{ -#ifdef ARCH_SIXTYFOUR - union { double d; uint64_t i; } u; - uint64_t n; - uint32_t e; - - u.d = vd; - n = u.i << 1; /* shift sign bit off */ - if (n == 0) return Val_int(FP_zero); - e = n >> 53; /* extract exponent */ - if (e == 0) return Val_int(FP_subnormal); - if (e == 0x7FF) { - if (n << 11 == 0) /* shift exponent off */ - return Val_int(FP_infinite); - else - return Val_int(FP_nan); - } - return Val_int(FP_normal); -#else - union double_as_two_int32 u; - uint32_t h, l; - - u.d = vd; - h = u.i.h; l = u.i.l; - l = l | (h & 0xFFFFF); - h = h & 0x7FF00000; - if ((h | l) == 0) - return Val_int(FP_zero); - if (h == 0) - return Val_int(FP_subnormal); - if (h == 0x7FF00000) { - if (l == 0) - return Val_int(FP_infinite); - else - return Val_int(FP_nan); - } - return Val_int(FP_normal); -#endif -} - -CAMLprim value caml_classify_float(value vd) -{ - return caml_classify_float_unboxed(Double_val(vd)); -} - -/* The [caml_init_ieee_float] function should initialize floating-point hardware - so that it behaves as much as possible like the IEEE standard. - In particular, return special numbers like Infinity and NaN instead - of signalling exceptions. Currently, everyone is in IEEE mode - at program startup, except FreeBSD prior to 4.0R. */ - -#ifdef __FreeBSD__ -#include -#if (__FreeBSD_version < 400017) -#include -#endif -#endif - -void caml_init_ieee_floats(void) -{ -#if defined(__FreeBSD__) && (__FreeBSD_version < 400017) - fpsetmask(0); -#endif -} diff --git a/byterun/freelist.c b/byterun/freelist.c deleted file mode 100644 index 4782800e..00000000 --- a/byterun/freelist.c +++ /dev/null @@ -1,621 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -#define FREELIST_DEBUG 0 -#if FREELIST_DEBUG -#include -#endif - -#include - -#include "caml/config.h" -#include "caml/freelist.h" -#include "caml/gc.h" -#include "caml/gc_ctrl.h" -#include "caml/memory.h" -#include "caml/major_gc.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" - -/* The free-list is kept sorted by increasing addresses. - This makes the merging of adjacent free blocks possible. - (See [caml_fl_merge_block].) -*/ - -/* A free list block is a [value] (integer representing a pointer to the - first word after the block's header). The end of the list is NULL. */ -#define Val_NULL ((value) NULL) - -/* The sentinel can be located anywhere in memory, but it must not be - adjacent to any heap object. */ -static struct { - value filler1; /* Make sure the sentinel is never adjacent to any block. */ - header_t h; - value first_field; - value filler2; /* Make sure the sentinel is never adjacent to any block. */ -} sentinel = {0, Make_header (0, 0, Caml_blue), Val_NULL, 0}; - -#define Fl_head (Val_bp (&(sentinel.first_field))) -static value fl_prev = Fl_head; /* Current allocation pointer. */ -static value fl_last = Val_NULL; /* Last block in the list. Only valid - just after [caml_fl_allocate] returns NULL. */ -value caml_fl_merge = Fl_head; /* Current insertion pointer. Managed - jointly with [sweep_slice]. */ -asize_t caml_fl_cur_wsz = 0; /* Number of words in the free list, - including headers but not fragments. */ - -#define FLP_MAX 1000 -static value flp [FLP_MAX]; -static int flp_size = 0; -static value beyond = Val_NULL; - -#define Next(b) (Field (b, 0)) - -#define Policy_next_fit 0 -#define Policy_first_fit 1 -uintnat caml_allocation_policy = Policy_next_fit; -#define policy caml_allocation_policy - -#ifdef DEBUG -static void fl_check (void) -{ - value cur, prev; - int prev_found = 0, flp_found = 0, merge_found = 0; - uintnat size_found = 0; - int sz = 0; - - prev = Fl_head; - cur = Next (prev); - while (cur != Val_NULL){ - size_found += Whsize_bp (cur); - CAMLassert (Is_in_heap (cur)); - if (cur == fl_prev) prev_found = 1; - if (policy == Policy_first_fit && Wosize_bp (cur) > sz){ - sz = Wosize_bp (cur); - if (flp_found < flp_size){ - CAMLassert (Next (flp[flp_found]) == cur); - ++ flp_found; - }else{ - CAMLassert (beyond == Val_NULL || cur >= Next (beyond)); - } - } - if (cur == caml_fl_merge) merge_found = 1; - prev = cur; - cur = Next (prev); - } - if (policy == Policy_next_fit) CAMLassert (prev_found || fl_prev == Fl_head); - if (policy == Policy_first_fit) CAMLassert (flp_found == flp_size); - CAMLassert (merge_found || caml_fl_merge == Fl_head); - CAMLassert (size_found == caml_fl_cur_wsz); -} - -#endif - -/* [allocate_block] is called by [caml_fl_allocate]. Given a suitable free - block and the requested size, it allocates a new block from the free - block. There are three cases: - 0. The free block has the requested size. Detach the block from the - free-list and return it. - 1. The free block is 1 word longer than the requested size. Detach - the block from the free list. The remaining word cannot be linked: - turn it into an empty block (header only), and return the rest. - 2. The free block is large enough. Split it in two and return the right - block. - In all cases, the allocated block is right-justified in the free block: - it is located in the high-address words of the free block, so that - the linking of the free-list does not change in case 2. -*/ -static header_t *allocate_block (mlsize_t wh_sz, int flpi, value prev, - value cur) -{ - header_t h = Hd_bp (cur); - CAMLassert (Whsize_hd (h) >= wh_sz); - if (Wosize_hd (h) < wh_sz + 1){ /* Cases 0 and 1. */ - caml_fl_cur_wsz -= Whsize_hd (h); - Next (prev) = Next (cur); - CAMLassert (Is_in_heap (Next (prev)) || Next (prev) == Val_NULL); - if (caml_fl_merge == cur) caml_fl_merge = prev; -#ifdef DEBUG - fl_last = Val_NULL; -#endif - /* In case 1, the following creates the empty block correctly. - In case 0, it gives an invalid header to the block. The function - calling [caml_fl_allocate] will overwrite it. */ - Hd_op (cur) = Make_header (0, 0, Caml_white); - if (policy == Policy_first_fit){ - if (flpi + 1 < flp_size && flp[flpi + 1] == cur){ - flp[flpi + 1] = prev; - }else if (flpi == flp_size - 1){ - beyond = (prev == Fl_head) ? Val_NULL : prev; - -- flp_size; - } - } - }else{ /* Case 2. */ - caml_fl_cur_wsz -= wh_sz; - Hd_op (cur) = Make_header (Wosize_hd (h) - wh_sz, 0, Caml_blue); - } - if (policy == Policy_next_fit) fl_prev = prev; - return (header_t *) &Field (cur, Wosize_hd (h) - wh_sz); -} - -#ifdef CAML_INSTR -static uintnat instr_size [20] = - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -static char *instr_name [20] = { - NULL, - "alloc01@", - "alloc02@", - "alloc03@", - "alloc04@", - "alloc05@", - "alloc06@", - "alloc07@", - "alloc08@", - "alloc09@", - "alloc10-19@", - "alloc20-29@", - "alloc30-39@", - "alloc40-49@", - "alloc50-59@", - "alloc60-69@", - "alloc70-79@", - "alloc80-89@", - "alloc90-99@", - "alloc_large@", -}; -uintnat caml_instr_alloc_jump = 0; -/* number of pointers followed to allocate from the free list */ -#endif /*CAML_INSTR*/ - -/* [caml_fl_allocate] does not set the header of the newly allocated block. - The calling function must do it before any GC function gets called. - [caml_fl_allocate] returns a head pointer. -*/ -header_t *caml_fl_allocate (mlsize_t wo_sz) -{ - value cur = Val_NULL, prev; - header_t *result; - int i; - mlsize_t sz, prevsz; - CAMLassert (sizeof (char *) == sizeof (value)); - CAMLassert (wo_sz >= 1); -#ifdef CAML_INSTR - if (wo_sz < 10){ - ++instr_size[wo_sz]; - }else if (wo_sz < 100){ - ++instr_size[wo_sz/10 + 9]; - }else{ - ++instr_size[19]; - } -#endif /* CAML_INSTR */ - - switch (policy){ - case Policy_next_fit: - CAMLassert (fl_prev != Val_NULL); - /* Search from [fl_prev] to the end of the list. */ - prev = fl_prev; - cur = Next (prev); - while (cur != Val_NULL){ - CAMLassert (Is_in_heap (cur)); - if (Wosize_bp (cur) >= wo_sz){ - return allocate_block (Whsize_wosize (wo_sz), 0, prev, cur); - } - prev = cur; - cur = Next (prev); -#ifdef CAML_INSTR - ++ caml_instr_alloc_jump; -#endif - } - fl_last = prev; - /* Search from the start of the list to [fl_prev]. */ - prev = Fl_head; - cur = Next (prev); - while (prev != fl_prev){ - if (Wosize_bp (cur) >= wo_sz){ - return allocate_block (Whsize_wosize (wo_sz), 0, prev, cur); - } - prev = cur; - cur = Next (prev); -#ifdef CAML_INSTR - ++ caml_instr_alloc_jump; -#endif - } - /* No suitable block was found. */ - return NULL; - break; - - case Policy_first_fit: { - /* Search in the flp array. */ - for (i = 0; i < flp_size; i++){ - sz = Wosize_bp (Next (flp[i])); - if (sz >= wo_sz){ -#if FREELIST_DEBUG - if (i > 5) fprintf (stderr, "FLP: found at %d size=%d\n", i, wo_sz); -#endif - result = allocate_block (Whsize_wosize (wo_sz), i, flp[i], - Next (flp[i])); - goto update_flp; - } - } - /* Extend the flp array. */ - if (flp_size == 0){ - prev = Fl_head; - prevsz = 0; - }else{ - prev = Next (flp[flp_size - 1]); - prevsz = Wosize_bp (prev); - if (beyond != Val_NULL) prev = beyond; - } - while (flp_size < FLP_MAX){ - cur = Next (prev); - if (cur == Val_NULL){ - fl_last = prev; - beyond = (prev == Fl_head) ? Val_NULL : prev; - return NULL; - }else{ - sz = Wosize_bp (cur); - if (sz > prevsz){ - flp[flp_size] = prev; - ++ flp_size; - if (sz >= wo_sz){ - beyond = cur; - i = flp_size - 1; -#if FREELIST_DEBUG - if (flp_size > 5){ - fprintf (stderr, "FLP: extended to %d\n", flp_size); - } -#endif - result = allocate_block (Whsize_wosize (wo_sz), flp_size - 1, prev, - cur); - goto update_flp; - } - prevsz = sz; - } - } - prev = cur; - } - beyond = cur; - - /* The flp table is full. Do a slow first-fit search. */ -#if FREELIST_DEBUG - fprintf (stderr, "FLP: table is full -- slow first-fit\n"); -#endif - if (beyond != Val_NULL){ - prev = beyond; - }else{ - prev = flp[flp_size - 1]; - } - prevsz = Wosize_bp (Next (flp[FLP_MAX-1])); - CAMLassert (prevsz < wo_sz); - cur = Next (prev); - while (cur != Val_NULL){ - CAMLassert (Is_in_heap (cur)); - sz = Wosize_bp (cur); - if (sz < prevsz){ - beyond = cur; - }else if (sz >= wo_sz){ - return allocate_block (Whsize_wosize (wo_sz), flp_size, prev, cur); - } - prev = cur; - cur = Next (prev); - } - fl_last = prev; - return NULL; - - update_flp: /* (i, sz) */ - /* The block at [i] was removed or reduced. Update the table. */ - CAMLassert (0 <= i && i < flp_size + 1); - if (i < flp_size){ - if (i > 0){ - prevsz = Wosize_bp (Next (flp[i-1])); - }else{ - prevsz = 0; - } - if (i == flp_size - 1){ - if (Wosize_bp (Next (flp[i])) <= prevsz){ - beyond = Next (flp[i]); - -- flp_size; - }else{ - beyond = Val_NULL; - } - }else{ - value buf [FLP_MAX]; - int j = 0; - mlsize_t oldsz = sz; - - prev = flp[i]; - while (prev != flp[i+1] && j < FLP_MAX - i){ - cur = Next (prev); - sz = Wosize_bp (cur); - if (sz > prevsz){ - buf[j++] = prev; - prevsz = sz; - if (sz >= oldsz){ - CAMLassert (sz == oldsz); - break; - } - } - prev = cur; - } -#if FREELIST_DEBUG - if (j > 2) fprintf (stderr, "FLP: update; buf size = %d\n", j); -#endif - if (FLP_MAX >= flp_size + j - 1){ - if (j != 1){ - memmove (&flp[i+j], &flp[i+1], sizeof (value) * (flp_size-i-1)); - } - if (j > 0) memmove (&flp[i], &buf[0], sizeof (value) * j); - flp_size += j - 1; - }else{ - if (FLP_MAX > i + j){ - if (j != 1){ - memmove (&flp[i+j], &flp[i+1], sizeof (value) * (FLP_MAX-i-j)); - } - if (j > 0) memmove (&flp[i], &buf[0], sizeof (value) * j); - }else{ - if (i != FLP_MAX){ - memmove (&flp[i], &buf[0], sizeof (value) * (FLP_MAX - i)); - } - } - flp_size = FLP_MAX - 1; - beyond = Next (flp[FLP_MAX - 1]); - } - } - } - return result; - } - break; - - default: - CAMLassert (0); /* unknown policy */ - break; - } - return NULL; /* NOT REACHED */ -} - -/* Location of the last fragment seen by the sweeping code. - This is a pointer to the first word after the fragment, which is - the header of the next block. - Note that [last_fragment] doesn't point to the fragment itself, - but to the block after it. -*/ -static header_t *last_fragment; - -void caml_fl_init_merge (void) -{ -#ifdef CAML_INSTR - int i; - for (i = 1; i < 20; i++){ - CAML_INSTR_INT (instr_name[i], instr_size[i]); - instr_size[i] = 0; - } -#endif /* CAML_INSTR */ - last_fragment = NULL; - caml_fl_merge = Fl_head; -#ifdef DEBUG - fl_check (); -#endif -} - -static void truncate_flp (value changed) -{ - if (changed == Fl_head){ - flp_size = 0; - beyond = Val_NULL; - }else{ - while (flp_size > 0 && Next (flp[flp_size - 1]) >= changed) - -- flp_size; - if (beyond >= changed) beyond = Val_NULL; - } -} - -/* This is called by caml_compact_heap. */ -void caml_fl_reset (void) -{ - Next (Fl_head) = Val_NULL; - switch (policy){ - case Policy_next_fit: - fl_prev = Fl_head; - break; - case Policy_first_fit: - truncate_flp (Fl_head); - break; - default: - CAMLassert (0); - break; - } - caml_fl_cur_wsz = 0; - caml_fl_init_merge (); -} - -/* [caml_fl_merge_block] returns the head pointer of the next block after [bp], - because merging blocks may change the size of [bp]. */ -header_t *caml_fl_merge_block (value bp) -{ - value prev, cur; - header_t *adj; - header_t hd = Hd_val (bp); - mlsize_t prev_wosz; - - caml_fl_cur_wsz += Whsize_hd (hd); - -#ifdef DEBUG - caml_set_fields (bp, 0, Debug_free_major); -#endif - prev = caml_fl_merge; - cur = Next (prev); - /* The sweep code makes sure that this is the right place to insert - this block: */ - CAMLassert (prev < bp || prev == Fl_head); - CAMLassert (cur > bp || cur == Val_NULL); - - if (policy == Policy_first_fit) truncate_flp (prev); - - /* If [last_fragment] and [bp] are adjacent, merge them. */ - if (last_fragment == Hp_bp (bp)){ - mlsize_t bp_whsz = Whsize_val (bp); - if (bp_whsz <= Max_wosize){ - hd = Make_header (bp_whsz, 0, Caml_white); - bp = (value) last_fragment; - Hd_val (bp) = hd; - caml_fl_cur_wsz += Whsize_wosize (0); - } - } - - /* If [bp] and [cur] are adjacent, remove [cur] from the free-list - and merge them. */ - adj = (header_t *) &Field (bp, Wosize_hd (hd)); - if (adj == Hp_val (cur)){ - value next_cur = Next (cur); - mlsize_t cur_whsz = Whsize_val (cur); - - if (Wosize_hd (hd) + cur_whsz <= Max_wosize){ - Next (prev) = next_cur; - if (policy == Policy_next_fit && fl_prev == cur) fl_prev = prev; - hd = Make_header (Wosize_hd (hd) + cur_whsz, 0, Caml_blue); - Hd_val (bp) = hd; - adj = (header_t *) &Field (bp, Wosize_hd (hd)); -#ifdef DEBUG - fl_last = Val_NULL; - Next (cur) = (value) Debug_free_major; - Hd_val (cur) = Debug_free_major; -#endif - cur = next_cur; - } - } - /* If [prev] and [bp] are adjacent merge them, else insert [bp] into - the free-list if it is big enough. */ - prev_wosz = Wosize_val (prev); - if ((header_t *) &Field (prev, prev_wosz) == Hp_val (bp) - && prev_wosz + Whsize_hd (hd) < Max_wosize){ - Hd_val (prev) = Make_header (prev_wosz + Whsize_hd (hd), 0,Caml_blue); -#ifdef DEBUG - Hd_val (bp) = Debug_free_major; -#endif - CAMLassert (caml_fl_merge == prev); - }else if (Wosize_hd (hd) != 0){ - Hd_val (bp) = Bluehd_hd (hd); - Next (bp) = cur; - Next (prev) = bp; - caml_fl_merge = bp; - }else{ - /* This is a fragment. Leave it in white but remember it for eventual - merging with the next block. */ - last_fragment = (header_t *) bp; - caml_fl_cur_wsz -= Whsize_wosize (0); - } - return adj; -} - -/* This is a heap extension. We have to insert it in the right place - in the free-list. - [caml_fl_add_blocks] can only be called right after a call to - [caml_fl_allocate] that returned Val_NULL. - Most of the heap extensions are expected to be at the end of the - free list. (This depends on the implementation of [malloc].) - - [bp] must point to a list of blocks chained by their field 0, - terminated by Val_NULL, and field 1 of the first block must point to - the last block. -*/ -void caml_fl_add_blocks (value bp) -{ - value cur = bp; - CAMLassert (fl_last != Val_NULL); - CAMLassert (Next (fl_last) == Val_NULL); - do { - caml_fl_cur_wsz += Whsize_bp (cur); - cur = Field(cur, 0); - } while (cur != Val_NULL); - - if (bp > fl_last){ - Next (fl_last) = bp; - if (fl_last == caml_fl_merge && (char *) bp < caml_gc_sweep_hp){ - caml_fl_merge = Field (bp, 1); - } - if (policy == Policy_first_fit && flp_size < FLP_MAX){ - flp [flp_size++] = fl_last; - } - }else{ - value prev; - - prev = Fl_head; - cur = Next (prev); - while (cur != Val_NULL && cur < bp){ - CAMLassert (prev < bp || prev == Fl_head); - /* XXX TODO: extend flp on the fly */ - prev = cur; - cur = Next (prev); - } - CAMLassert (prev < bp || prev == Fl_head); - CAMLassert (cur > bp || cur == Val_NULL); - Next (Field (bp, 1)) = cur; - Next (prev) = bp; - /* When inserting blocks between [caml_fl_merge] and [caml_gc_sweep_hp], - we must advance [caml_fl_merge] to the new block, so that [caml_fl_merge] - is always the last free-list block before [caml_gc_sweep_hp]. */ - if (prev == caml_fl_merge && (char *) bp < caml_gc_sweep_hp){ - caml_fl_merge = Field (bp, 1); - } - if (policy == Policy_first_fit) truncate_flp (bp); - } -} - -/* Cut a block of memory into Max_wosize pieces, give them headers, - and optionally merge them into the free list. - arguments: - p: pointer to the first word of the block - size: size of the block (in words) - do_merge: 1 -> do merge; 0 -> do not merge - color: which color to give to the pieces; if [do_merge] is 1, this - is overridden by the merge code, but we have historically used - [Caml_white]. -*/ -void caml_make_free_blocks (value *p, mlsize_t size, int do_merge, int color) -{ - mlsize_t sz; - - while (size > 0){ - if (size > Whsize_wosize (Max_wosize)){ - sz = Whsize_wosize (Max_wosize); - }else{ - sz = size; - } - *(header_t *)p = - Make_header (Wosize_whsize (sz), 0, color); - if (do_merge) caml_fl_merge_block (Val_hp (p)); - size -= sz; - p += sz; - } -} - -void caml_set_allocation_policy (uintnat p) -{ - switch (p){ - case Policy_next_fit: - fl_prev = Fl_head; - policy = p; - break; - case Policy_first_fit: - flp_size = 0; - beyond = Val_NULL; - policy = p; - break; - default: - break; - } -} diff --git a/byterun/gc_ctrl.c b/byterun/gc_ctrl.c deleted file mode 100644 index 1cec4a25..00000000 --- a/byterun/gc_ctrl.c +++ /dev/null @@ -1,691 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -#include "caml/alloc.h" -#include "caml/backtrace.h" -#include "caml/compact.h" -#include "caml/custom.h" -#include "caml/fail.h" -#include "caml/finalise.h" -#include "caml/freelist.h" -#include "caml/gc.h" -#include "caml/gc_ctrl.h" -#include "caml/major_gc.h" -#include "caml/memory.h" -#include "caml/minor_gc.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/signals.h" -#ifdef NATIVE_CODE -#include "caml/stack.h" -#else -#include "caml/stacks.h" -#endif -#include "caml/startup_aux.h" - -#ifndef NATIVE_CODE -extern uintnat caml_max_stack_size; /* defined in stacks.c */ -#endif - -double caml_stat_minor_words = 0.0, - caml_stat_promoted_words = 0.0, - caml_stat_major_words = 0.0; - -intnat caml_stat_minor_collections = 0, - caml_stat_major_collections = 0, - caml_stat_heap_wsz = 0, - caml_stat_top_heap_wsz = 0, - caml_stat_compactions = 0, - caml_stat_heap_chunks = 0; - -extern uintnat caml_major_heap_increment; /* percent or words; see major_gc.c */ -extern uintnat caml_percent_free; /* see major_gc.c */ -extern uintnat caml_percent_max; /* see compact.c */ -extern uintnat caml_allocation_policy; /* see freelist.c */ - -#define Next(hp) ((hp) + Whsize_hp (hp)) - -#ifdef DEBUG - -/* Check that [v]'s header looks good. [v] must be a block in the heap. */ -static void check_head (value v) -{ - CAMLassert (Is_block (v)); - CAMLassert (Is_in_heap (v)); - - CAMLassert (Wosize_val (v) != 0); - CAMLassert (Color_hd (Hd_val (v)) != Caml_blue); - CAMLassert (Is_in_heap (v)); - if (Tag_val (v) == Infix_tag){ - int offset = Wsize_bsize (Infix_offset_val (v)); - value trueval = Val_op (&Field (v, -offset)); - CAMLassert (Tag_val (trueval) == Closure_tag); - CAMLassert (Wosize_val (trueval) > offset); - CAMLassert (Is_in_heap (&Field (trueval, Wosize_val (trueval) - 1))); - }else{ - CAMLassert (Is_in_heap (&Field (v, Wosize_val (v) - 1))); - } - if (Tag_val (v) == Double_tag){ - CAMLassert (Wosize_val (v) == Double_wosize); - }else if (Tag_val (v) == Double_array_tag){ - CAMLassert (Wosize_val (v) % Double_wosize == 0); - } -} - -static void check_block (header_t *hp) -{ - mlsize_t i; - value v = Val_hp (hp); - value f; - - check_head (v); - switch (Tag_hp (hp)){ - case Abstract_tag: break; - case String_tag: - break; - case Double_tag: - CAMLassert (Wosize_val (v) == Double_wosize); - break; - case Double_array_tag: - CAMLassert (Wosize_val (v) % Double_wosize == 0); - break; - case Custom_tag: - CAMLassert (!Is_in_heap (Custom_ops_val (v))); - break; - - case Infix_tag: - CAMLassert (0); - break; - - default: - CAMLassert (Tag_hp (hp) < No_scan_tag); - for (i = 0; i < Wosize_hp (hp); i++){ - f = Field (v, i); - if (Is_block (f) && Is_in_heap (f)){ - check_head (f); - CAMLassert (Color_val (f) != Caml_blue); - } - } - } -} - -#endif /* DEBUG */ - -/* Check the heap structure (if compiled in debug mode) and - gather statistics; return the stats if [returnstats] is true, - otherwise return [Val_unit]. -*/ -static value heap_stats (int returnstats) -{ - CAMLparam0 (); - intnat live_words = 0, live_blocks = 0, - free_words = 0, free_blocks = 0, largest_free = 0, - fragments = 0, heap_chunks = 0; - char *chunk = caml_heap_start, *chunk_end; - header_t *cur_hp; -#ifdef DEBUG - header_t *prev_hp; -#endif - header_t cur_hd; - -#ifdef DEBUG - caml_gc_message (-1, "### OCaml runtime: heap check ###\n"); -#endif - - while (chunk != NULL){ - ++ heap_chunks; - chunk_end = chunk + Chunk_size (chunk); -#ifdef DEBUG - prev_hp = NULL; -#endif - cur_hp = (header_t *) chunk; - while (cur_hp < (header_t *) chunk_end){ - cur_hd = Hd_hp (cur_hp); - CAMLassert (Next (cur_hp) <= (header_t *) chunk_end); - switch (Color_hd (cur_hd)){ - case Caml_white: - if (Wosize_hd (cur_hd) == 0){ - ++ fragments; - CAMLassert (prev_hp == NULL - || Color_hp (prev_hp) != Caml_blue - || cur_hp == (header_t *) caml_gc_sweep_hp); - }else{ - if (caml_gc_phase == Phase_sweep - && cur_hp >= (header_t *) caml_gc_sweep_hp){ - ++ free_blocks; - free_words += Whsize_hd (cur_hd); - if (Whsize_hd (cur_hd) > largest_free){ - largest_free = Whsize_hd (cur_hd); - } - }else{ - ++ live_blocks; - live_words += Whsize_hd (cur_hd); -#ifdef DEBUG - check_block (cur_hp); -#endif - } - } - break; - case Caml_gray: case Caml_black: - CAMLassert (Wosize_hd (cur_hd) > 0); - ++ live_blocks; - live_words += Whsize_hd (cur_hd); -#ifdef DEBUG - check_block (cur_hp); -#endif - break; - case Caml_blue: - CAMLassert (Wosize_hd (cur_hd) > 0); - ++ free_blocks; - free_words += Whsize_hd (cur_hd); - if (Whsize_hd (cur_hd) > largest_free){ - largest_free = Whsize_hd (cur_hd); - } - /* not true any more with big heap chunks - CAMLassert (prev_hp == NULL - || (Color_hp (prev_hp) != Caml_blue - && Wosize_hp (prev_hp) > 0) - || cur_hp == caml_gc_sweep_hp); - CAMLassert (Next (cur_hp) == chunk_end - || (Color_hp (Next (cur_hp)) != Caml_blue - && Wosize_hp (Next (cur_hp)) > 0) - || (Whsize_hd (cur_hd) + Wosize_hp (Next (cur_hp)) - > Max_wosize) - || Next (cur_hp) == caml_gc_sweep_hp); - */ - break; - } -#ifdef DEBUG - prev_hp = cur_hp; -#endif - cur_hp = Next (cur_hp); - } - CAMLassert (cur_hp == (header_t *) chunk_end); - chunk = Chunk_next (chunk); - } - -#ifdef DEBUG - caml_final_invariant_check(); -#endif - - CAMLassert (heap_chunks == caml_stat_heap_chunks); - CAMLassert (live_words + free_words + fragments == caml_stat_heap_wsz); - - if (returnstats){ - CAMLlocal1 (res); - - /* get a copy of these before allocating anything... */ - double minwords = caml_stat_minor_words - + (double) (caml_young_alloc_end - caml_young_ptr); - double prowords = caml_stat_promoted_words; - double majwords = caml_stat_major_words + (double) caml_allocated_words; - intnat mincoll = caml_stat_minor_collections; - intnat majcoll = caml_stat_major_collections; - intnat heap_words = caml_stat_heap_wsz; - intnat cpct = caml_stat_compactions; - intnat top_heap_words = caml_stat_top_heap_wsz; - - res = caml_alloc_tuple (16); - Store_field (res, 0, caml_copy_double (minwords)); - Store_field (res, 1, caml_copy_double (prowords)); - Store_field (res, 2, caml_copy_double (majwords)); - Store_field (res, 3, Val_long (mincoll)); - Store_field (res, 4, Val_long (majcoll)); - Store_field (res, 5, Val_long (heap_words)); - Store_field (res, 6, Val_long (heap_chunks)); - Store_field (res, 7, Val_long (live_words)); - Store_field (res, 8, Val_long (live_blocks)); - Store_field (res, 9, Val_long (free_words)); - Store_field (res, 10, Val_long (free_blocks)); - Store_field (res, 11, Val_long (largest_free)); - Store_field (res, 12, Val_long (fragments)); - Store_field (res, 13, Val_long (cpct)); - Store_field (res, 14, Val_long (top_heap_words)); - Store_field (res, 15, Val_long (caml_stack_usage())); - CAMLreturn (res); - }else{ - CAMLreturn (Val_unit); - } -} - -#ifdef DEBUG -void caml_heap_check (void) -{ - heap_stats (0); -} -#endif - -CAMLprim value caml_gc_stat(value v) -{ - value result; - CAML_INSTR_SETUP (tmr, ""); - CAMLassert (v == Val_unit); - result = heap_stats (1); - CAML_INSTR_TIME (tmr, "explicit/gc_stat"); - return result; -} - -CAMLprim value caml_gc_quick_stat(value v) -{ - CAMLparam0 (); - CAMLlocal1 (res); - - /* get a copy of these before allocating anything... */ - double minwords = caml_stat_minor_words - + (double) (caml_young_alloc_end - caml_young_ptr); - double prowords = caml_stat_promoted_words; - double majwords = caml_stat_major_words + (double) caml_allocated_words; - intnat mincoll = caml_stat_minor_collections; - intnat majcoll = caml_stat_major_collections; - intnat heap_words = caml_stat_heap_wsz; - intnat top_heap_words = caml_stat_top_heap_wsz; - intnat cpct = caml_stat_compactions; - intnat heap_chunks = caml_stat_heap_chunks; - - res = caml_alloc_tuple (16); - Store_field (res, 0, caml_copy_double (minwords)); - Store_field (res, 1, caml_copy_double (prowords)); - Store_field (res, 2, caml_copy_double (majwords)); - Store_field (res, 3, Val_long (mincoll)); - Store_field (res, 4, Val_long (majcoll)); - Store_field (res, 5, Val_long (heap_words)); - Store_field (res, 6, Val_long (heap_chunks)); - Store_field (res, 7, Val_long (0)); - Store_field (res, 8, Val_long (0)); - Store_field (res, 9, Val_long (0)); - Store_field (res, 10, Val_long (0)); - Store_field (res, 11, Val_long (0)); - Store_field (res, 12, Val_long (0)); - Store_field (res, 13, Val_long (cpct)); - Store_field (res, 14, Val_long (top_heap_words)); - Store_field (res, 15, Val_long (caml_stack_usage())); - CAMLreturn (res); -} - -double caml_gc_minor_words_unboxed() -{ - return (caml_stat_minor_words - + (double) (caml_young_alloc_end - caml_young_ptr)); -} - -CAMLprim value caml_gc_minor_words(value v) -{ - CAMLparam0 (); /* v is ignored */ - CAMLreturn(caml_copy_double(caml_gc_minor_words_unboxed())); -} - -CAMLprim value caml_gc_counters(value v) -{ - CAMLparam0 (); /* v is ignored */ - CAMLlocal1 (res); - - /* get a copy of these before allocating anything... */ - double minwords = caml_stat_minor_words - + (double) (caml_young_alloc_end - caml_young_ptr); - double prowords = caml_stat_promoted_words; - double majwords = caml_stat_major_words + (double) caml_allocated_words; - - res = caml_alloc_tuple (3); - Store_field (res, 0, caml_copy_double (minwords)); - Store_field (res, 1, caml_copy_double (prowords)); - Store_field (res, 2, caml_copy_double (majwords)); - CAMLreturn (res); -} - -CAMLprim value caml_gc_huge_fallback_count (value v) -{ - return Val_long (caml_huge_fallback_count); -} - -CAMLprim value caml_gc_get(value v) -{ - CAMLparam0 (); /* v is ignored */ - CAMLlocal1 (res); - - res = caml_alloc_tuple (8); - Store_field (res, 0, Val_long (caml_minor_heap_wsz)); /* s */ - Store_field (res, 1, Val_long (caml_major_heap_increment)); /* i */ - Store_field (res, 2, Val_long (caml_percent_free)); /* o */ - Store_field (res, 3, Val_long (caml_verb_gc)); /* v */ - Store_field (res, 4, Val_long (caml_percent_max)); /* O */ -#ifndef NATIVE_CODE - Store_field (res, 5, Val_long (caml_max_stack_size)); /* l */ -#else - Store_field (res, 5, Val_long (0)); -#endif - Store_field (res, 6, Val_long (caml_allocation_policy)); /* a */ - Store_field (res, 7, Val_long (caml_major_window)); /* w */ - CAMLreturn (res); -} - -#define Max(x,y) ((x) < (y) ? (y) : (x)) - -static uintnat norm_pfree (uintnat p) -{ - return Max (p, 1); -} - -static uintnat norm_pmax (uintnat p) -{ - return p; -} - -static intnat norm_minsize (intnat s) -{ - if (s < Minor_heap_min) s = Minor_heap_min; - if (s > Minor_heap_max) s = Minor_heap_max; - return s; -} - -static uintnat norm_window (intnat w) -{ - if (w < 1) w = 1; - if (w > Max_major_window) w = Max_major_window; - return w; -} - -CAMLprim value caml_gc_set(value v) -{ - uintnat newpf, newpm; - asize_t newheapincr; - asize_t newminwsz; - uintnat oldpolicy; - CAML_INSTR_SETUP (tmr, ""); - - caml_verb_gc = Long_val (Field (v, 3)); - -#ifndef NATIVE_CODE - caml_change_max_stack_size (Long_val (Field (v, 5))); -#endif - - newpf = norm_pfree (Long_val (Field (v, 2))); - if (newpf != caml_percent_free){ - caml_percent_free = newpf; - caml_gc_message (0x20, "New space overhead: %" - ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_percent_free); - } - - newpm = norm_pmax (Long_val (Field (v, 4))); - if (newpm != caml_percent_max){ - caml_percent_max = newpm; - caml_gc_message (0x20, "New max overhead: %" - ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_percent_max); - } - - newheapincr = Long_val (Field (v, 1)); - if (newheapincr != caml_major_heap_increment){ - caml_major_heap_increment = newheapincr; - if (newheapincr > 1000){ - caml_gc_message (0x20, "New heap increment size: %" - ARCH_INTNAT_PRINTF_FORMAT "uk words\n", - caml_major_heap_increment/1024); - }else{ - caml_gc_message (0x20, "New heap increment size: %" - ARCH_INTNAT_PRINTF_FORMAT "u%%\n", - caml_major_heap_increment); - } - } - oldpolicy = caml_allocation_policy; - caml_set_allocation_policy (Long_val (Field (v, 6))); - if (oldpolicy != caml_allocation_policy){ - caml_gc_message (0x20, "New allocation policy: %" - ARCH_INTNAT_PRINTF_FORMAT "u\n", caml_allocation_policy); - } - - /* This field was added in 4.03.0. */ - if (Wosize_val (v) >= 8){ - int old_window = caml_major_window; - caml_set_major_window (norm_window (Long_val (Field (v, 7)))); - if (old_window != caml_major_window){ - caml_gc_message (0x20, "New smoothing window size: %d\n", - caml_major_window); - } - } - - /* Minor heap size comes last because it will trigger a minor collection - (thus invalidating [v]) and it can raise [Out_of_memory]. */ - newminwsz = norm_minsize (Long_val (Field (v, 0))); - if (newminwsz != caml_minor_heap_wsz){ - caml_gc_message (0x20, "New minor heap size: %" - ARCH_SIZET_PRINTF_FORMAT "uk words\n", newminwsz / 1024); - caml_set_minor_heap_size (Bsize_wsize (newminwsz)); - } - CAML_INSTR_TIME (tmr, "explicit/gc_set"); - return Val_unit; -} - -CAMLprim value caml_gc_minor(value v) -{ - CAML_INSTR_SETUP (tmr, ""); - CAMLassert (v == Val_unit); - caml_request_minor_gc (); - caml_gc_dispatch (); - CAML_INSTR_TIME (tmr, "explicit/gc_minor"); - return Val_unit; -} - -static void test_and_compact (void) -{ - float fp; - - fp = 100.0 * caml_fl_cur_wsz / (caml_stat_heap_wsz - caml_fl_cur_wsz); - if (fp > 999999.0) fp = 999999.0; - caml_gc_message (0x200, "Estimated overhead (lower bound) = %" - ARCH_INTNAT_PRINTF_FORMAT "u%%\n", - (uintnat) fp); - if (fp >= caml_percent_max){ - caml_gc_message (0x200, "Automatic compaction triggered.\n"); - caml_compact_heap (); - } -} - -CAMLprim value caml_gc_major(value v) -{ - CAML_INSTR_SETUP (tmr, ""); - CAMLassert (v == Val_unit); - caml_gc_message (0x1, "Major GC cycle requested\n"); - caml_empty_minor_heap (); - caml_finish_major_cycle (); - test_and_compact (); - caml_final_do_calls (); - CAML_INSTR_TIME (tmr, "explicit/gc_major"); - return Val_unit; -} - -CAMLprim value caml_gc_full_major(value v) -{ - CAML_INSTR_SETUP (tmr, ""); - CAMLassert (v == Val_unit); - caml_gc_message (0x1, "Full major GC cycle requested\n"); - caml_empty_minor_heap (); - caml_finish_major_cycle (); - caml_final_do_calls (); - caml_empty_minor_heap (); - caml_finish_major_cycle (); - test_and_compact (); - caml_final_do_calls (); - CAML_INSTR_TIME (tmr, "explicit/gc_full_major"); - return Val_unit; -} - -CAMLprim value caml_gc_major_slice (value v) -{ - CAML_INSTR_SETUP (tmr, ""); - CAMLassert (Is_long (v)); - caml_major_collection_slice (Long_val (v)); - CAML_INSTR_TIME (tmr, "explicit/gc_major_slice"); - return Val_long (0); -} - -CAMLprim value caml_gc_compaction(value v) -{ - CAML_INSTR_SETUP (tmr, ""); - CAMLassert (v == Val_unit); - caml_gc_message (0x10, "Heap compaction requested\n"); - caml_empty_minor_heap (); - caml_finish_major_cycle (); - caml_final_do_calls (); - caml_empty_minor_heap (); - caml_finish_major_cycle (); - caml_compact_heap (); - caml_final_do_calls (); - CAML_INSTR_TIME (tmr, "explicit/gc_compact"); - return Val_unit; -} - -CAMLprim value caml_get_minor_free (value v) -{ - return Val_int (caml_young_ptr - caml_young_alloc_start); -} - -CAMLprim value caml_get_major_bucket (value v) -{ - long i = Long_val (v); - if (i < 0) caml_invalid_argument ("Gc.get_bucket"); - if (i < caml_major_window){ - i += caml_major_ring_index; - if (i >= caml_major_window) i -= caml_major_window; - CAMLassert (0 <= i && i < caml_major_window); - return Val_long ((long) (caml_major_ring[i] * 1e6)); - }else{ - return Val_long (0); - } -} - -CAMLprim value caml_get_major_credit (value v) -{ - CAMLassert (v == Val_unit); - return Val_long ((long) (caml_major_work_credit * 1e6)); -} - -uintnat caml_normalize_heap_increment (uintnat i) -{ - if (i < Bsize_wsize (Heap_chunk_min)){ - i = Bsize_wsize (Heap_chunk_min); - } - return ((i + Page_size - 1) >> Page_log) << Page_log; -} - -/* [minor_size] and [major_size] are numbers of words - [major_incr] is either a percentage or a number of words */ -void caml_init_gc (uintnat minor_size, uintnat major_size, - uintnat major_incr, uintnat percent_fr, - uintnat percent_m, uintnat window) -{ - uintnat major_heap_size = - Bsize_wsize (caml_normalize_heap_increment (major_size)); - - CAML_INSTR_INIT (); - if (caml_init_alloc_for_heap () != 0){ - caml_fatal_error ("cannot initialize heap: mmap failed\n"); - } - if (caml_page_table_initialize(Bsize_wsize(minor_size) + major_heap_size)){ - caml_fatal_error ("OCaml runtime error: cannot initialize page table\n"); - } - caml_set_minor_heap_size (Bsize_wsize (norm_minsize (minor_size))); - caml_major_heap_increment = major_incr; - caml_percent_free = norm_pfree (percent_fr); - caml_percent_max = norm_pmax (percent_m); - caml_init_major_heap (major_heap_size); - caml_major_window = norm_window (window); - caml_gc_message (0x20, "Initial minor heap size: %" - ARCH_SIZET_PRINTF_FORMAT "uk words\n", - caml_minor_heap_wsz / 1024); - caml_gc_message (0x20, "Initial major heap size: %" - ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n", - major_heap_size / 1024); - caml_gc_message (0x20, "Initial space overhead: %" - ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_percent_free); - caml_gc_message (0x20, "Initial max overhead: %" - ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_percent_max); - if (caml_major_heap_increment > 1000){ - caml_gc_message (0x20, "Initial heap increment: %" - ARCH_INTNAT_PRINTF_FORMAT "uk words\n", - caml_major_heap_increment / 1024); - }else{ - caml_gc_message (0x20, "Initial heap increment: %" - ARCH_INTNAT_PRINTF_FORMAT "u%%\n", - caml_major_heap_increment); - } - caml_gc_message (0x20, "Initial allocation policy: %" - ARCH_INTNAT_PRINTF_FORMAT "u\n", caml_allocation_policy); - caml_gc_message (0x20, "Initial smoothing window: %d\n", - caml_major_window); -} - - -/* FIXME After the startup_aux.c unification, move these functions there. */ - -CAMLprim value caml_runtime_variant (value unit) -{ - CAMLassert (unit == Val_unit); -#if defined (DEBUG) - return caml_copy_string ("d"); -#elif defined (CAML_INSTR) - return caml_copy_string ("i"); -#else - return caml_copy_string (""); -#endif -} - -extern int caml_parser_trace; - -CAMLprim value caml_runtime_parameters (value unit) -{ -#define F_Z ARCH_INTNAT_PRINTF_FORMAT -#define F_S ARCH_SIZET_PRINTF_FORMAT - - CAMLassert (unit == Val_unit); - return caml_alloc_sprintf - ("a=%d,b=%d,H=%"F_Z"u,i=%"F_Z"u,l=%"F_Z"u,o=%"F_Z"u,O=%"F_Z"u,p=%d,s=%"F_S"u,t=%"F_Z"u,v=%"F_Z"u,w=%d,W=%"F_Z"u", - /* a */ (int) caml_allocation_policy, - /* b */ caml_backtrace_active, - /* h */ /* missing */ /* FIXME add when changed to min_heap_size */ - /* H */ caml_use_huge_pages, - /* i */ caml_major_heap_increment, -#ifdef NATIVE_CODE - /* l */ (uintnat) 0, -#else - /* l */ caml_max_stack_size, -#endif - /* o */ caml_percent_free, - /* O */ caml_percent_max, - /* p */ caml_parser_trace, - /* R */ /* missing */ - /* s */ caml_minor_heap_wsz, - /* t */ caml_trace_level, - /* v */ caml_verb_gc, - /* w */ caml_major_window, - /* W */ caml_runtime_warnings - ); -#undef F_Z -#undef F_S -} - -/* Control runtime warnings */ - -CAMLprim value caml_ml_enable_runtime_warnings(value vbool) -{ - caml_runtime_warnings = Bool_val(vbool); - return Val_unit; -} - -CAMLprim value caml_ml_runtime_warnings_enabled(value unit) -{ - CAMLassert (unit == Val_unit); - return Val_bool(caml_runtime_warnings); -} diff --git a/byterun/instrtrace.c b/byterun/instrtrace.c deleted file mode 100644 index 824562e1..00000000 --- a/byterun/instrtrace.c +++ /dev/null @@ -1,269 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Trace the instructions executed */ - -#ifdef DEBUG - -#include -#include -#include - -#include "caml/instrtrace.h" -#include "caml/instruct.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/opnames.h" -#include "caml/prims.h" -#include "caml/stacks.h" -#include "caml/startup_aux.h" - -extern code_t caml_start_code; - -intnat caml_icount = 0; - -void caml_stop_here () {} - -void caml_disasm_instr(pc) - code_t pc; -{ - int instr = *pc; - printf("%6ld %s", (long) (pc - caml_start_code), - instr < 0 || instr > STOP ? "???" : names_of_instructions[instr]); - pc++; - switch(instr) { - /* Instructions with one integer operand */ - case PUSHACC: case ACC: case POP: case ASSIGN: - case PUSHENVACC: case ENVACC: case PUSH_RETADDR: case APPLY: - case APPTERM1: case APPTERM2: case APPTERM3: case RETURN: - case GRAB: case PUSHGETGLOBAL: case GETGLOBAL: case SETGLOBAL: - case PUSHATOM: case ATOM: case MAKEBLOCK1: case MAKEBLOCK2: - case MAKEBLOCK3: case MAKEFLOATBLOCK: - case GETFIELD: case SETFIELD: case GETFLOATFIELD: case SETFLOATFIELD: - case BRANCH: case BRANCHIF: case BRANCHIFNOT: case PUSHTRAP: - case CONSTINT: case PUSHCONSTINT: case OFFSETINT: case OFFSETREF: - case OFFSETCLOSURE: case PUSHOFFSETCLOSURE: - printf(" %d\n", pc[0]); break; - /* Instructions with two operands */ - case APPTERM: case CLOSURE: case CLOSUREREC: case PUSHGETGLOBALFIELD: - case GETGLOBALFIELD: case MAKEBLOCK: - case BEQ: case BNEQ: case BLTINT: case BLEINT: case BGTINT: case BGEINT: - case BULTINT: case BUGEINT: - printf(" %d, %d\n", pc[0], pc[1]); break; - /* Instructions with a C primitive as operand */ - case C_CALLN: - printf(" %d,", pc[0]); pc++; - /* fallthrough */ - case C_CALL1: case C_CALL2: case C_CALL3: case C_CALL4: case C_CALL5: - if (pc[0] < 0 || pc[0] >= caml_prim_name_table.size) - printf(" unknown primitive %d\n", pc[0]); - else - printf(" %s\n", (char *) caml_prim_name_table.contents[pc[0]]); - break; - default: - printf("\n"); - } - fflush (stdout); -} - -char * caml_instr_string (code_t pc) -{ - static char buf[256]; - char nambuf[128]; - int instr = *pc; - char *nam; - - nam = (instr < 0 || instr > STOP) - ? (snprintf (nambuf, sizeof(nambuf), "???%d", instr), nambuf) - : names_of_instructions[instr]; - pc++; - switch (instr) { - /* Instructions with one integer operand */ - case PUSHACC: - case ACC: - case POP: - case ASSIGN: - case PUSHENVACC: - case ENVACC: - case PUSH_RETADDR: - case APPLY: - case APPTERM1: - case APPTERM2: - case APPTERM3: - case RETURN: - case GRAB: - case PUSHGETGLOBAL: - case GETGLOBAL: - case SETGLOBAL: - case PUSHATOM: - case ATOM: - case MAKEBLOCK1: - case MAKEBLOCK2: - case MAKEBLOCK3: - case MAKEFLOATBLOCK: - case GETFIELD: - case SETFIELD: - case GETFLOATFIELD: - case SETFLOATFIELD: - case BRANCH: - case BRANCHIF: - case BRANCHIFNOT: - case PUSHTRAP: - case CONSTINT: - case PUSHCONSTINT: - case OFFSETINT: - case OFFSETREF: - case OFFSETCLOSURE: - case PUSHOFFSETCLOSURE: - snprintf(buf, sizeof(buf), "%s %d", nam, pc[0]); - break; - /* Instructions with two operands */ - case APPTERM: - case CLOSURE: - case CLOSUREREC: - case PUSHGETGLOBALFIELD: - case GETGLOBALFIELD: - case MAKEBLOCK: - case BEQ: - case BNEQ: - case BLTINT: - case BLEINT: - case BGTINT: - case BGEINT: - case BULTINT: - case BUGEINT: - snprintf(buf, sizeof(buf), "%s %d, %d", nam, pc[0], pc[1]); - break; - case SWITCH: - snprintf(buf, sizeof(buf), "SWITCH sz%#lx=%ld::ntag%ld nint%ld", - (long) pc[0], (long) pc[0], (unsigned long) pc[0] >> 16, - (unsigned long) pc[0] & 0xffff); - break; - /* Instructions with a C primitive as operand */ - case C_CALLN: - snprintf(buf, sizeof(buf), "%s %d,", nam, pc[0]); - pc++; - /* fallthrough */ - case C_CALL1: - case C_CALL2: - case C_CALL3: - case C_CALL4: - case C_CALL5: - if (pc[0] < 0 || pc[0] >= caml_prim_name_table.size) - snprintf(buf, sizeof(buf), "%s unknown primitive %d", nam, pc[0]); - else - snprintf(buf, sizeof(buf), "%s %s", - nam, (char *) caml_prim_name_table.contents[pc[0]]); - break; - default: - snprintf(buf, sizeof(buf), "%s", nam); - break; - }; - return buf; -} - - -void -caml_trace_value_file (value v, code_t prog, int proglen, FILE * f) -{ - int i; - fprintf (f, "%#" ARCH_INTNAT_PRINTF_FORMAT "x", v); - if (!v) - return; - if (prog && v % sizeof (int) == 0 - && (code_t) v >= prog - && (code_t) v < (code_t) ((char *) prog + proglen)) - fprintf (f, "=code@%ld", (long) ((code_t) v - prog)); - else if (Is_long (v)) - fprintf (f, "=long%" ARCH_INTNAT_PRINTF_FORMAT "d", Long_val (v)); - else if ((void*)v >= (void*)caml_stack_low - && (void*)v < (void*)caml_stack_high) - fprintf (f, "=stack_%ld", (long) ((intnat*)caml_stack_high - (intnat*)v)); - else if (Is_block (v)) { - int s = Wosize_val (v); - int tg = Tag_val (v); - int l = 0; - switch (tg) { - case Closure_tag: - fprintf (f, "=closure[s%d,cod%ld]", - s, (long) ((code_t) (Code_val (v)) - prog)); - goto displayfields; - case String_tag: - l = caml_string_length (v); - fprintf (f, "=string[s%dL%d]'", s, l); - for (i = 0; i < ((l>0x1f)?0x1f:l) ; i++) { - if (isprint ((int) Byte (v, i))) - putc (Byte (v, i), f); - else - putc ('?', f); - }; - fprintf (f, "'"); - goto displayfields; - case Double_tag: - fprintf (f, "=float[s%d]=%g", s, Double_val (v)); - goto displayfields; - case Double_array_tag: - fprintf (f, "=floatarray[s%d]", s); - for (i = 0; i < ((s>0xf)?0xf:s); i++) - fprintf (f, " %g", Double_flat_field (v, i)); - goto displayfields; - case Abstract_tag: - fprintf (f, "=abstract[s%d]", s); - goto displayfields; - case Custom_tag: - fprintf (f, "=custom[s%d]", s); - goto displayfields; - default: - fprintf (f, "=block", tg, s); - displayfields: - if (s > 0) - fputs ("=(", f); - for (i = 0; i < s; i++) { - if (i > 20) { - fputs ("....", f); - break; - }; - if (i > 0) - putc (' ', f); - fprintf (f, "%#" ARCH_INTNAT_PRINTF_FORMAT "x", Field (v, i)); - }; - if (s > 0) - putc (')', f); - }; - } -} - -void -caml_trace_accu_sp_file (value accu, value * sp, code_t prog, int proglen, - FILE * f) -{ - int i; - value *p; - fprintf (f, "accu="); - caml_trace_value_file (accu, prog, proglen, f); - fprintf (f, "\n sp=%#" ARCH_INTNAT_PRINTF_FORMAT "x @%ld:", - (intnat) sp, (long) (caml_stack_high - sp)); - for (p = sp, i = 0; i < 12 + (1 << caml_trace_level) && p < caml_stack_high; - p++, i++) { - fprintf (f, "\n[%ld] ", (long) (caml_stack_high - p)); - caml_trace_value_file (*p, prog, proglen, f); - }; - putc ('\n', f); - fflush (f); -} - -#endif /* DEBUG */ diff --git a/byterun/intern.c b/byterun/intern.c deleted file mode 100644 index 565ed10d..00000000 --- a/byterun/intern.c +++ /dev/null @@ -1,1048 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Structured input, compact format */ - -/* The interface of this file is "caml/intext.h" */ - -#include -#include -#include "caml/alloc.h" -#include "caml/callback.h" -#include "caml/config.h" -#include "caml/custom.h" -#include "caml/fail.h" -#include "caml/gc.h" -#include "caml/intext.h" -#include "caml/io.h" -#include "caml/md5.h" -#include "caml/memory.h" -#include "caml/mlvalues.h" -#include "caml/misc.h" -#include "caml/reverse.h" - -static unsigned char * intern_src; -/* Reading pointer in block holding input data. */ - -static unsigned char * intern_input = NULL; -/* Pointer to beginning of block holding input data, - if non-NULL this pointer will be freed by the cleanup function. */ - -static header_t * intern_dest; -/* Writing pointer in destination block */ - -static char * intern_extra_block = NULL; -/* If non-NULL, point to new heap chunk allocated with caml_alloc_for_heap. */ - -static asize_t obj_counter; -/* Count how many objects seen so far */ - -static value * intern_obj_table = NULL; -/* The pointers to objects already seen */ - -static unsigned int intern_color; -/* Color to assign to newly created headers */ - -static header_t intern_header; -/* Original header of the destination block. - Meaningful only if intern_extra_block is NULL. */ - -static value intern_block = 0; -/* Point to the heap block allocated as destination block. - Meaningful only if intern_extra_block is NULL. */ - -static char * intern_resolve_code_pointer(unsigned char digest[16], - asize_t offset); - -CAMLnoreturn_start -static void intern_bad_code_pointer(unsigned char digest[16]) -CAMLnoreturn_end; - -static void intern_free_stack(void); - -static inline unsigned char read8u(void) -{ return *intern_src++; } - -static inline signed char read8s(void) -{ return *intern_src++; } - -static inline uint16_t read16u(void) -{ - uint16_t res = (intern_src[0] << 8) + intern_src[1]; - intern_src += 2; - return res; -} - -static inline int16_t read16s(void) -{ - int16_t res = (intern_src[0] << 8) + intern_src[1]; - intern_src += 2; - return res; -} - -static inline uint32_t read32u(void) -{ - uint32_t res = - ((uint32_t)(intern_src[0]) << 24) + (intern_src[1] << 16) - + (intern_src[2] << 8) + intern_src[3]; - intern_src += 4; - return res; -} - -static inline int32_t read32s(void) -{ - int32_t res = - ((uint32_t)(intern_src[0]) << 24) + (intern_src[1] << 16) - + (intern_src[2] << 8) + intern_src[3]; - intern_src += 4; - return res; -} - -#ifdef ARCH_SIXTYFOUR -static uintnat read64u(void) -{ - uintnat res = - ((uintnat) (intern_src[0]) << 56) - + ((uintnat) (intern_src[1]) << 48) - + ((uintnat) (intern_src[2]) << 40) - + ((uintnat) (intern_src[3]) << 32) - + ((uintnat) (intern_src[4]) << 24) - + ((uintnat) (intern_src[5]) << 16) - + ((uintnat) (intern_src[6]) << 8) - + (uintnat) (intern_src[7]); - intern_src += 8; - return res; -} -#endif - -static inline void readblock(void * dest, intnat len) -{ - memcpy(dest, intern_src, len); - intern_src += len; -} - -static void intern_init(void * src, void * input) -{ - /* This is asserted at the beginning of demarshaling primitives. - If it fails, it probably means that an exception was raised - without calling intern_cleanup() during the previous demarshaling. */ - CAMLassert (intern_input == NULL && intern_obj_table == NULL \ - && intern_extra_block == NULL && intern_block == 0); - intern_src = src; - intern_input = input; -} - -static void intern_cleanup(void) -{ - if (intern_input != NULL) { - caml_stat_free(intern_input); - intern_input = NULL; - } - if (intern_obj_table != NULL) { - caml_stat_free(intern_obj_table); - intern_obj_table = NULL; - } - if (intern_extra_block != NULL) { - /* free newly allocated heap chunk */ - caml_free_for_heap(intern_extra_block); - intern_extra_block = NULL; - } else if (intern_block != 0) { - /* restore original header for heap block, otherwise GC is confused */ - Hd_val(intern_block) = intern_header; - intern_block = 0; - } - /* free the recursion stack */ - intern_free_stack(); -} - -static void readfloat(double * dest, unsigned int code) -{ - if (sizeof(double) != 8) { - intern_cleanup(); - caml_invalid_argument("input_value: non-standard floats"); - } - readblock((char *) dest, 8); - /* Fix up endianness, if needed */ -#if ARCH_FLOAT_ENDIANNESS == 0x76543210 - /* Host is big-endian; fix up if data read is little-endian */ - if (code != CODE_DOUBLE_BIG) Reverse_64(dest, dest); -#elif ARCH_FLOAT_ENDIANNESS == 0x01234567 - /* Host is little-endian; fix up if data read is big-endian */ - if (code != CODE_DOUBLE_LITTLE) Reverse_64(dest, dest); -#else - /* Host is neither big nor little; permute as appropriate */ - if (code == CODE_DOUBLE_LITTLE) - Permute_64(dest, ARCH_FLOAT_ENDIANNESS, dest, 0x01234567) - else - Permute_64(dest, ARCH_FLOAT_ENDIANNESS, dest, 0x76543210); -#endif -} - -/* [len] is a number of floats */ -static void readfloats(double * dest, mlsize_t len, unsigned int code) -{ - mlsize_t i; - if (sizeof(double) != 8) { - intern_cleanup(); - caml_invalid_argument("input_value: non-standard floats"); - } - readblock((char *) dest, len * 8); - /* Fix up endianness, if needed */ -#if ARCH_FLOAT_ENDIANNESS == 0x76543210 - /* Host is big-endian; fix up if data read is little-endian */ - if (code != CODE_DOUBLE_ARRAY8_BIG && - code != CODE_DOUBLE_ARRAY32_BIG) { - for (i = 0; i < len; i++) Reverse_64(dest + i, dest + i); - } -#elif ARCH_FLOAT_ENDIANNESS == 0x01234567 - /* Host is little-endian; fix up if data read is big-endian */ - if (code != CODE_DOUBLE_ARRAY8_LITTLE && - code != CODE_DOUBLE_ARRAY32_LITTLE) { - for (i = 0; i < len; i++) Reverse_64(dest + i, dest + i); - } -#else - /* Host is neither big nor little; permute as appropriate */ - if (code == CODE_DOUBLE_ARRAY8_LITTLE || - code == CODE_DOUBLE_ARRAY32_LITTLE) { - for (i = 0; i < len; i++) - Permute_64(dest + i, ARCH_FLOAT_ENDIANNESS, dest + i, 0x01234567); - } else { - for (i = 0; i < len; i++) - Permute_64(dest + i, ARCH_FLOAT_ENDIANNESS, dest + i, 0x76543210); - } -#endif -} - -/* Item on the stack with defined operation */ -struct intern_item { - value * dest; - intnat arg; - enum { - OReadItems, /* read arg items and store them in dest[0], dest[1], ... */ - OFreshOID, /* generate a fresh OID and store it in *dest */ - OShift /* offset *dest by arg */ - } op; -}; - -/* FIXME: This is duplicated in two other places, with the only difference of - the type of elements stored in the stack. Possible solution in C would - be to instantiate stack these function via. C preprocessor macro. - */ - -#define INTERN_STACK_INIT_SIZE 256 -#define INTERN_STACK_MAX_SIZE (1024*1024*100) - -static struct intern_item intern_stack_init[INTERN_STACK_INIT_SIZE]; - -static struct intern_item * intern_stack = intern_stack_init; -static struct intern_item * intern_stack_limit = intern_stack_init - + INTERN_STACK_INIT_SIZE; - -/* Free the recursion stack if needed */ -static void intern_free_stack(void) -{ - if (intern_stack != intern_stack_init) { - caml_stat_free(intern_stack); - /* Reinitialize the globals for next time around */ - intern_stack = intern_stack_init; - intern_stack_limit = intern_stack + INTERN_STACK_INIT_SIZE; - } -} - -/* Same, then raise Out_of_memory */ -static void intern_stack_overflow(void) -{ - caml_gc_message (0x04, "Stack overflow in un-marshaling value\n"); - intern_free_stack(); - caml_raise_out_of_memory(); -} - -static struct intern_item * intern_resize_stack(struct intern_item * sp) -{ - asize_t newsize = 2 * (intern_stack_limit - intern_stack); - asize_t sp_offset = sp - intern_stack; - struct intern_item * newstack; - - if (newsize >= INTERN_STACK_MAX_SIZE) intern_stack_overflow(); - if (intern_stack == intern_stack_init) { - newstack = caml_stat_alloc_noexc(sizeof(struct intern_item) * newsize); - if (newstack == NULL) intern_stack_overflow(); - memcpy(newstack, intern_stack_init, - sizeof(struct intern_item) * INTERN_STACK_INIT_SIZE); - } else { - newstack = caml_stat_resize_noexc(intern_stack, - sizeof(struct intern_item) * newsize); - if (newstack == NULL) intern_stack_overflow(); - } - intern_stack = newstack; - intern_stack_limit = newstack + newsize; - return newstack + sp_offset; -} - -/* Convenience macros for requesting operation on the stack */ -#define PushItem() \ - do { \ - sp++; \ - if (sp >= intern_stack_limit) sp = intern_resize_stack(sp); \ - } while(0) - -#define ReadItems(_dest,_n) \ - do { \ - if (_n > 0) { \ - PushItem(); \ - sp->op = OReadItems; \ - sp->dest = _dest; \ - sp->arg = _n; \ - } \ - } while(0) - -static void intern_rec(value *dest) -{ - unsigned int code; - tag_t tag; - mlsize_t size, len, ofs_ind; - value v; - asize_t ofs; - header_t header; - unsigned char digest[16]; - struct custom_operations * ops; - char * codeptr; - struct intern_item * sp; - - sp = intern_stack; - - /* Initially let's try to read the first object from the stream */ - ReadItems(dest, 1); - - /* The un-marshaler loop, the recursion is unrolled */ - while(sp != intern_stack) { - - /* Interpret next item on the stack */ - dest = sp->dest; - switch (sp->op) { - case OFreshOID: - /* Refresh the object ID */ - /* but do not do it for predefined exception slots */ - if (Long_val(Field((value)dest, 1)) >= 0) - caml_set_oo_id((value)dest); - /* Pop item and iterate */ - sp--; - break; - case OShift: - /* Shift value by an offset */ - *dest += sp->arg; - /* Pop item and iterate */ - sp--; - break; - case OReadItems: - /* Pop item */ - sp->dest++; - if (--(sp->arg) == 0) sp--; - /* Read a value and set v to this value */ - code = read8u(); - if (code >= PREFIX_SMALL_INT) { - if (code >= PREFIX_SMALL_BLOCK) { - /* Small block */ - tag = code & 0xF; - size = (code >> 4) & 0x7; - read_block: - if (size == 0) { - v = Atom(tag); - } else { - v = Val_hp(intern_dest); - if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; - *intern_dest = Make_header_allocated_here(size, tag, intern_color); - intern_dest += 1 + size; - /* For objects, we need to freshen the oid */ - if (tag == Object_tag) { - CAMLassert(size >= 2); - /* Request to read rest of the elements of the block */ - ReadItems(&Field(v, 2), size - 2); - /* Request freshing OID */ - PushItem(); - sp->op = OFreshOID; - sp->dest = (value*) v; - sp->arg = 1; - /* Finally read first two block elements: method table and old OID */ - ReadItems(&Field(v, 0), 2); - } else - /* If it's not an object then read the contents of the block */ - ReadItems(&Field(v, 0), size); - } - } else { - /* Small integer */ - v = Val_int(code & 0x3F); - } - } else { - if (code >= PREFIX_SMALL_STRING) { - /* Small string */ - len = (code & 0x1F); - read_string: - size = (len + sizeof(value)) / sizeof(value); - v = Val_hp(intern_dest); - if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; - *intern_dest = Make_header_allocated_here(size, String_tag, intern_color); - intern_dest += 1 + size; - Field(v, size - 1) = 0; - ofs_ind = Bsize_wsize(size) - 1; - Byte(v, ofs_ind) = ofs_ind - len; - readblock((char *)String_val(v), len); - } else { - switch(code) { - case CODE_INT8: - v = Val_long(read8s()); - break; - case CODE_INT16: - v = Val_long(read16s()); - break; - case CODE_INT32: - v = Val_long(read32s()); - break; - case CODE_INT64: -#ifdef ARCH_SIXTYFOUR - v = Val_long((intnat) (read64u())); - break; -#else - intern_cleanup(); - caml_failwith("input_value: integer too large"); - break; -#endif - case CODE_SHARED8: - ofs = read8u(); - read_shared: - CAMLassert (ofs > 0); - CAMLassert (ofs <= obj_counter); - CAMLassert (intern_obj_table != NULL); - v = intern_obj_table[obj_counter - ofs]; - break; - case CODE_SHARED16: - ofs = read16u(); - goto read_shared; - case CODE_SHARED32: - ofs = read32u(); - goto read_shared; -#ifdef ARCH_SIXTYFOUR - case CODE_SHARED64: - ofs = read64u(); - goto read_shared; -#endif - case CODE_BLOCK32: - header = (header_t) read32u(); - tag = Tag_hd(header); - size = Wosize_hd(header); - goto read_block; -#ifdef ARCH_SIXTYFOUR - case CODE_BLOCK64: - header = (header_t) read64u(); - tag = Tag_hd(header); - size = Wosize_hd(header); - goto read_block; -#endif - case CODE_STRING8: - len = read8u(); - goto read_string; - case CODE_STRING32: - len = read32u(); - goto read_string; -#ifdef ARCH_SIXTYFOUR - case CODE_STRING64: - len = read64u(); - goto read_string; -#endif - case CODE_DOUBLE_LITTLE: - case CODE_DOUBLE_BIG: - v = Val_hp(intern_dest); - if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; - *intern_dest = Make_header_allocated_here(Double_wosize, Double_tag, - intern_color); - intern_dest += 1 + Double_wosize; - readfloat((double *) v, code); - break; - case CODE_DOUBLE_ARRAY8_LITTLE: - case CODE_DOUBLE_ARRAY8_BIG: - len = read8u(); - read_double_array: - size = len * Double_wosize; - v = Val_hp(intern_dest); - if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; - *intern_dest = Make_header_allocated_here(size, Double_array_tag, - intern_color); - intern_dest += 1 + size; - readfloats((double *) v, len, code); - break; - case CODE_DOUBLE_ARRAY32_LITTLE: - case CODE_DOUBLE_ARRAY32_BIG: - len = read32u(); - goto read_double_array; -#ifdef ARCH_SIXTYFOUR - case CODE_DOUBLE_ARRAY64_LITTLE: - case CODE_DOUBLE_ARRAY64_BIG: - len = read64u(); - goto read_double_array; -#endif - case CODE_CODEPOINTER: - ofs = read32u(); - readblock(digest, 16); - codeptr = intern_resolve_code_pointer(digest, ofs); - if (codeptr != NULL) { - v = (value) codeptr; - } else { - value * function_placeholder = - caml_named_value ("Debugger.function_placeholder"); - if (function_placeholder != NULL) { - v = *function_placeholder; - } else { - intern_cleanup(); - intern_bad_code_pointer(digest); - } - } - break; - case CODE_INFIXPOINTER: - ofs = read32u(); - /* Read a value to *dest, then offset *dest by ofs */ - PushItem(); - sp->dest = dest; - sp->op = OShift; - sp->arg = ofs; - ReadItems(dest, 1); - continue; /* with next iteration of main loop, skipping *dest = v */ - case CODE_CUSTOM: - ops = caml_find_custom_operations((char *) intern_src); - if (ops == NULL) { - intern_cleanup(); - caml_failwith("input_value: unknown custom block identifier"); - } - while (*intern_src++ != 0) /*nothing*/; /*skip identifier*/ - size = ops->deserialize((void *) (intern_dest + 2)); - size = 1 + (size + sizeof(value) - 1) / sizeof(value); - v = Val_hp(intern_dest); - if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; - *intern_dest = Make_header_allocated_here(size, Custom_tag, - intern_color); - Custom_ops_val(v) = ops; - - if (ops->finalize != NULL && Is_young(v)) { - /* Remember that the block has a finalizer. */ - add_to_custom_table (&caml_custom_table, v, 0, 1); - } - - intern_dest += 1 + size; - break; - default: - intern_cleanup(); - caml_failwith("input_value: ill-formed message"); - } - } - } - /* end of case OReadItems */ - *dest = v; - break; - default: - CAMLassert(0); - } - } - /* We are done. Cleanup the stack and leave the function */ - intern_free_stack(); -} - -static void intern_alloc(mlsize_t whsize, mlsize_t num_objects, - int outside_heap) -{ - mlsize_t wosize; - - if (whsize == 0) { - CAMLassert (intern_extra_block == NULL && intern_block == 0 - && intern_obj_table == NULL); - return; - } - wosize = Wosize_whsize(whsize); - if (outside_heap || wosize > Max_wosize) { - /* Round desired size up to next page */ - asize_t request = - ((Bsize_wsize(whsize) + Page_size - 1) >> Page_log) << Page_log; - intern_extra_block = caml_alloc_for_heap(request); - if (intern_extra_block == NULL) { - intern_cleanup(); - caml_raise_out_of_memory(); - } - intern_color = - outside_heap ? Caml_black : caml_allocation_color(intern_extra_block); - intern_dest = (header_t *) intern_extra_block; - CAMLassert (intern_block == 0); - } else { - /* this is a specialised version of caml_alloc from alloc.c */ - if (wosize <= Max_young_wosize){ - if (wosize == 0){ - intern_block = Atom (String_tag); - } else { - intern_block = caml_alloc_small (wosize, String_tag); - } - }else{ - intern_block = caml_alloc_shr_no_raise (wosize, String_tag); - /* do not do the urgent_gc check here because it might darken - intern_block into gray and break the intern_color assertion below */ - if (intern_block == 0) { - intern_cleanup(); - caml_raise_out_of_memory(); - } - } - intern_header = Hd_val(intern_block); - intern_color = Color_hd(intern_header); - CAMLassert (intern_color == Caml_white || intern_color == Caml_black); - intern_dest = (header_t *) Hp_val(intern_block); - CAMLassert (intern_extra_block == NULL); - } - obj_counter = 0; - if (num_objects > 0) { - intern_obj_table = (value *) caml_stat_alloc_noexc(num_objects * sizeof(value)); - if (intern_obj_table == NULL) { - intern_cleanup(); - caml_raise_out_of_memory(); - } - } else - CAMLassert(intern_obj_table == NULL); -} - -static void intern_add_to_heap(mlsize_t whsize) -{ - /* Add new heap chunk to heap if needed */ - if (intern_extra_block != NULL) { - /* If heap chunk not filled totally, build free block at end */ - asize_t request = Chunk_size (intern_extra_block); - header_t * end_extra_block = - (header_t *) intern_extra_block + Wsize_bsize(request); - CAMLassert(intern_block == 0); - CAMLassert(intern_dest <= end_extra_block); - if (intern_dest < end_extra_block){ - caml_make_free_blocks ((value *) intern_dest, - end_extra_block - intern_dest, 0, Caml_white); - } - caml_allocated_words += - Wsize_bsize ((char *) intern_dest - intern_extra_block); - caml_add_to_heap(intern_extra_block); - intern_extra_block = NULL; // To prevent intern_cleanup freeing it - } else { - intern_block = 0; // To prevent intern_cleanup rewriting its header - } -} - -/* Parsing the header */ - -struct marshal_header { - uint32_t magic; - int header_len; - uintnat data_len; - uintnat num_objects; - uintnat whsize; -}; - -static void caml_parse_header(char * fun_name, - /*out*/ struct marshal_header * h) -{ - char errmsg[100]; - - h->magic = read32u(); - switch(h->magic) { - case Intext_magic_number_small: - h->header_len = 20; - h->data_len = read32u(); - h->num_objects = read32u(); -#ifdef ARCH_SIXTYFOUR - read32u(); - h->whsize = read32u(); -#else - h->whsize = read32u(); - read32u(); -#endif - break; - case Intext_magic_number_big: -#ifdef ARCH_SIXTYFOUR - h->header_len = 32; - read32u(); - h->data_len = read64u(); - h->num_objects = read64u(); - h->whsize = read64u(); -#else - errmsg[sizeof(errmsg) - 1] = 0; - snprintf(errmsg, sizeof(errmsg) - 1, - "%s: object too large to be read back on a 32-bit platform", - fun_name); - caml_failwith(errmsg); -#endif - break; - default: - errmsg[sizeof(errmsg) - 1] = 0; - snprintf(errmsg, sizeof(errmsg) - 1, - "%s: bad object", - fun_name); - caml_failwith(errmsg); - } -} - -/* Reading from a channel */ - -static value caml_input_val_core(struct channel *chan, int outside_heap) -{ - intnat r; - char header[32]; - struct marshal_header h; - char * block; - value res; - - if (! caml_channel_binary_mode(chan)) - caml_failwith("input_value: not a binary channel"); - /* Read and parse the header */ - r = caml_really_getblock(chan, header, 20); - if (r == 0) - caml_raise_end_of_file(); - else if (r < 20) - caml_failwith("input_value: truncated object"); - intern_src = (unsigned char *) header; - if (read32u() == Intext_magic_number_big) { - /* Finish reading the header */ - if (caml_really_getblock(chan, header + 20, 32 - 20) < 32 - 20) - caml_failwith("input_value: truncated object"); - } - intern_src = (unsigned char *) header; - caml_parse_header("input_value", &h); - /* Read block from channel */ - block = caml_stat_alloc(h.data_len); - /* During [caml_really_getblock], concurrent [caml_input_val] operations - can take place (via signal handlers or context switching in systhreads), - and [intern_input] may change. So, wait until [caml_really_getblock] - is over before using [intern_input] and the other global vars. */ - if (caml_really_getblock(chan, block, h.data_len) < h.data_len) { - caml_stat_free(block); - caml_failwith("input_value: truncated object"); - } - /* Initialize global state */ - intern_init(block, block); - intern_alloc(h.whsize, h.num_objects, outside_heap); - /* Fill it in */ - intern_rec(&res); - if (!outside_heap) { - intern_add_to_heap(h.whsize); - } else { - caml_disown_for_heap(intern_extra_block); - intern_extra_block = NULL; - intern_block = 0; - } - /* Free everything */ - intern_cleanup(); - return caml_check_urgent_gc(res); -} - -value caml_input_val(struct channel* chan) -{ - return caml_input_val_core(chan, 0); -} - -CAMLprim value caml_input_value(value vchan) -{ - CAMLparam1 (vchan); - struct channel * chan = Channel(vchan); - CAMLlocal1 (res); - - Lock(chan); - res = caml_input_val(chan); - Unlock(chan); - CAMLreturn (res); -} - -/* Reading from memory-resident blocks */ - -CAMLprim value caml_input_value_to_outside_heap(value vchan) -{ - CAMLparam1 (vchan); - struct channel * chan = Channel(vchan); - CAMLlocal1 (res); - - Lock(chan); - res = caml_input_val_core(chan, 1); - Unlock(chan); - CAMLreturn (res); -} - -CAMLexport value caml_input_val_from_bytes(value str, intnat ofs) -{ - CAMLparam1 (str); - CAMLlocal1 (obj); - struct marshal_header h; - - /* Initialize global state */ - intern_init(&Byte_u(str, ofs), NULL); - caml_parse_header("input_val_from_string", &h); - if (ofs + h.header_len + h.data_len > caml_string_length(str)) - caml_failwith("input_val_from_string: bad length"); - /* Allocate result */ - intern_alloc(h.whsize, h.num_objects, 0); - intern_src = &Byte_u(str, ofs + h.header_len); /* If a GC occurred */ - /* Fill it in */ - intern_rec(&obj); - intern_add_to_heap(h.whsize); - /* Free everything */ - intern_cleanup(); - CAMLreturn (caml_check_urgent_gc(obj)); -} - -CAMLprim value caml_input_value_from_string(value str, value ofs) -{ - return caml_input_val_from_bytes(str, Long_val(ofs)); -} - -CAMLprim value caml_input_value_from_bytes(value str, value ofs) -{ - return caml_input_val_from_bytes(str, Long_val(ofs)); -} - -static value input_val_from_block(struct marshal_header * h) -{ - value obj; - /* Allocate result */ - intern_alloc(h->whsize, h->num_objects, 0); - /* Fill it in */ - intern_rec(&obj); - intern_add_to_heap(h->whsize); - /* Free internal data structures */ - intern_cleanup(); - return caml_check_urgent_gc(obj); -} - -CAMLexport value caml_input_value_from_malloc(char * data, intnat ofs) -{ - struct marshal_header h; - - intern_init(data + ofs, data); - - caml_parse_header("input_value_from_malloc", &h); - - return input_val_from_block(&h); -} - -/* [len] is a number of bytes */ -CAMLexport value caml_input_value_from_block(char * data, intnat len) -{ - struct marshal_header h; - - /* Initialize global state */ - intern_init(data, NULL); - caml_parse_header("input_value_from_block", &h); - if (h.header_len + h.data_len > len) - caml_failwith("input_val_from_block: bad length"); - return input_val_from_block(&h); -} - -/* [ofs] is a [value] that represents a number of bytes - result is a [value] that represents a number of bytes - To handle both the small and the big format, - we assume 20 bytes are available at [buff + ofs], - and we return the data size + the length of the part of the header - that remains to be read. */ - -CAMLprim value caml_marshal_data_size(value buff, value ofs) -{ - uint32_t magic; - int header_len; - uintnat data_len; - - intern_src = &Byte_u(buff, Long_val(ofs)); - magic = read32u(); - switch(magic) { - case Intext_magic_number_small: - header_len = 20; - data_len = read32u(); - break; - case Intext_magic_number_big: -#ifdef ARCH_SIXTYFOUR - header_len = 32; - read32u(); - data_len = read64u(); -#else - caml_failwith("Marshal.data_size: " - "object too large to be read back on a 32-bit platform"); -#endif - break; - default: - caml_failwith("Marshal.data_size: bad object"); - } - return Val_long((header_len - 20) + data_len); -} - -/* Resolution of code pointers */ - -static char * intern_resolve_code_pointer(unsigned char digest[16], - asize_t offset) -{ - int i; - for (i = caml_code_fragments_table.size - 1; i >= 0; i--) { - struct code_fragment * cf = caml_code_fragments_table.contents[i]; - if (! cf->digest_computed) { - caml_md5_block(cf->digest, cf->code_start, cf->code_end - cf->code_start); - cf->digest_computed = 1; - } - if (memcmp(digest, cf->digest, 16) == 0) { - if (cf->code_start + offset < cf->code_end) - return cf->code_start + offset; - else - return NULL; - } - } - return NULL; -} - -static void intern_bad_code_pointer(unsigned char digest[16]) -{ - char msg[256]; - snprintf(msg, sizeof(msg), - "input_value: unknown code module " - "%02X%02X%02X%02X%02X%02X%02X%02X" - "%02X%02X%02X%02X%02X%02X%02X%02X", - digest[0], digest[1], digest[2], digest[3], - digest[4], digest[5], digest[6], digest[7], - digest[8], digest[9], digest[10], digest[11], - digest[12], digest[13], digest[14], digest[15]); - caml_failwith(msg); -} - -/* Functions for writing user-defined marshallers */ - -CAMLexport int caml_deserialize_uint_1(void) -{ - return read8u(); -} - -CAMLexport int caml_deserialize_sint_1(void) -{ - return read8s(); -} - -CAMLexport int caml_deserialize_uint_2(void) -{ - return read16u(); -} - -CAMLexport int caml_deserialize_sint_2(void) -{ - return read16s(); -} - -CAMLexport uint32_t caml_deserialize_uint_4(void) -{ - return read32u(); -} - -CAMLexport int32_t caml_deserialize_sint_4(void) -{ - return read32s(); -} - -CAMLexport uint64_t caml_deserialize_uint_8(void) -{ - uint64_t i; - caml_deserialize_block_8(&i, 1); - return i; -} - -CAMLexport int64_t caml_deserialize_sint_8(void) -{ - int64_t i; - caml_deserialize_block_8(&i, 1); - return i; -} - -CAMLexport float caml_deserialize_float_4(void) -{ - float f; - caml_deserialize_block_4(&f, 1); - return f; -} - -CAMLexport double caml_deserialize_float_8(void) -{ - double f; - caml_deserialize_block_float_8(&f, 1); - return f; -} - -CAMLexport void caml_deserialize_block_1(void * data, intnat len) -{ - memcpy(data, intern_src, len); - intern_src += len; -} - -CAMLexport void caml_deserialize_block_2(void * data, intnat len) -{ -#ifndef ARCH_BIG_ENDIAN - unsigned char * p, * q; - for (p = intern_src, q = data; len > 0; len--, p += 2, q += 2) - Reverse_16(q, p); - intern_src = p; -#else - memcpy(data, intern_src, len * 2); - intern_src += len * 2; -#endif -} - -CAMLexport void caml_deserialize_block_4(void * data, intnat len) -{ -#ifndef ARCH_BIG_ENDIAN - unsigned char * p, * q; - for (p = intern_src, q = data; len > 0; len--, p += 4, q += 4) - Reverse_32(q, p); - intern_src = p; -#else - memcpy(data, intern_src, len * 4); - intern_src += len * 4; -#endif -} - -CAMLexport void caml_deserialize_block_8(void * data, intnat len) -{ -#ifndef ARCH_BIG_ENDIAN - unsigned char * p, * q; - for (p = intern_src, q = data; len > 0; len--, p += 8, q += 8) - Reverse_64(q, p); - intern_src = p; -#else - memcpy(data, intern_src, len * 8); - intern_src += len * 8; -#endif -} - -CAMLexport void caml_deserialize_block_float_8(void * data, intnat len) -{ -#if ARCH_FLOAT_ENDIANNESS == 0x01234567 - memcpy(data, intern_src, len * 8); - intern_src += len * 8; -#elif ARCH_FLOAT_ENDIANNESS == 0x76543210 - unsigned char * p, * q; - for (p = intern_src, q = data; len > 0; len--, p += 8, q += 8) - Reverse_64(q, p); - intern_src = p; -#else - unsigned char * p, * q; - for (p = intern_src, q = data; len > 0; len--, p += 8, q += 8) - Permute_64(q, ARCH_FLOAT_ENDIANNESS, p, 0x01234567); - intern_src = p; -#endif -} - -CAMLexport void caml_deserialize_error(char * msg) -{ - intern_cleanup(); - caml_failwith(msg); -} diff --git a/byterun/interp.c b/byterun/interp.c deleted file mode 100644 index 0b74df3d..00000000 --- a/byterun/interp.c +++ /dev/null @@ -1,1172 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* The bytecode interpreter */ -#include -#include "caml/alloc.h" -#include "caml/backtrace.h" -#include "caml/callback.h" -#include "caml/debugger.h" -#include "caml/fail.h" -#include "caml/fix_code.h" -#include "caml/instrtrace.h" -#include "caml/instruct.h" -#include "caml/interp.h" -#include "caml/major_gc.h" -#include "caml/memory.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/prims.h" -#include "caml/signals.h" -#include "caml/stacks.h" -#include "caml/startup_aux.h" - -/* Registers for the abstract machine: - pc the code pointer - sp the stack pointer (grows downward) - accu the accumulator - env heap-allocated environment - caml_trapsp pointer to the current trap frame - extra_args number of extra arguments provided by the caller - -sp is a local copy of the global variable caml_extern_sp. */ - -/* Instruction decoding */ - -#ifdef THREADED_CODE -# define Instruct(name) lbl_##name -# if defined(ARCH_SIXTYFOUR) && !defined(ARCH_CODE32) -# define Jumptbl_base ((char *) &&lbl_ACC0) -# else -# define Jumptbl_base ((char *) 0) -# define jumptbl_base ((char *) 0) -# endif -# ifdef DEBUG -# define Next goto next_instr -# else -# define Next goto *(void *)(jumptbl_base + *pc++) -# endif -#else -# define Instruct(name) case name -# define Next break -#endif - -/* GC interface */ - -#define Setup_for_gc \ - { sp -= 2; sp[0] = accu; sp[1] = env; caml_extern_sp = sp; } -#define Restore_after_gc \ - { accu = sp[0]; env = sp[1]; sp += 2; } -#define Setup_for_c_call \ - { saved_pc = pc; *--sp = env; caml_extern_sp = sp; } -#define Restore_after_c_call \ - { sp = caml_extern_sp; env = *sp++; saved_pc = NULL; } - -/* An event frame must look like accu + a C_CALL frame + a RETURN 1 frame */ -#define Setup_for_event \ - { sp -= 6; \ - sp[0] = accu; /* accu */ \ - sp[1] = Val_unit; /* C_CALL frame: dummy environment */ \ - sp[2] = Val_unit; /* RETURN frame: dummy local 0 */ \ - sp[3] = (value) pc; /* RETURN frame: saved return address */ \ - sp[4] = env; /* RETURN frame: saved environment */ \ - sp[5] = Val_long(extra_args); /* RETURN frame: saved extra args */ \ - caml_extern_sp = sp; } -#define Restore_after_event \ - { sp = caml_extern_sp; accu = sp[0]; \ - pc = (code_t) sp[3]; env = sp[4]; extra_args = Long_val(sp[5]); \ - sp += 6; } - -/* Debugger interface */ - -#define Setup_for_debugger \ - { sp -= 4; \ - sp[0] = accu; sp[1] = (value)(pc - 1); \ - sp[2] = env; sp[3] = Val_long(extra_args); \ - caml_extern_sp = sp; } -#define Restore_after_debugger { sp += 4; } - -#ifdef THREADED_CODE -#define Restart_curr_instr \ - goto *(jumptable[caml_saved_code[pc - 1 - caml_start_code]]) -#else -#define Restart_curr_instr \ - curr_instr = caml_saved_code[pc - 1 - caml_start_code]; \ - goto dispatch_instr -#endif - -/* Register optimization. - Some compilers underestimate the use of the local variables representing - the abstract machine registers, and don't put them in hardware registers, - which slows down the interpreter considerably. - For GCC, I have hand-assigned hardware registers for several architectures. -*/ - -#if defined(__GNUC__) && !defined(DEBUG) && !defined(__INTEL_COMPILER) \ - && !defined(__llvm__) -#ifdef __mips__ -#define PC_REG asm("$16") -#define SP_REG asm("$17") -#define ACCU_REG asm("$18") -#endif -#ifdef __sparc__ -#define PC_REG asm("%l0") -#define SP_REG asm("%l1") -#define ACCU_REG asm("%l2") -#endif -#ifdef __alpha__ -#ifdef __CRAY__ -#define PC_REG asm("r9") -#define SP_REG asm("r10") -#define ACCU_REG asm("r11") -#define JUMPTBL_BASE_REG asm("r12") -#else -#define PC_REG asm("$9") -#define SP_REG asm("$10") -#define ACCU_REG asm("$11") -#define JUMPTBL_BASE_REG asm("$12") -#endif -#endif -#ifdef __i386__ -#define PC_REG asm("%esi") -#define SP_REG asm("%edi") -#define ACCU_REG -#endif -#if defined(__ppc__) || defined(__ppc64__) -#define PC_REG asm("26") -#define SP_REG asm("27") -#define ACCU_REG asm("28") -#endif -#ifdef __hppa__ -#define PC_REG asm("%r18") -#define SP_REG asm("%r17") -#define ACCU_REG asm("%r16") -#endif -#ifdef __mc68000__ -#define PC_REG asm("a5") -#define SP_REG asm("a4") -#define ACCU_REG asm("d7") -#endif -/* PR#4953: these specific registers not available in Thumb mode */ -#if defined (__arm__) && !defined(__thumb__) -#define PC_REG asm("r6") -#define SP_REG asm("r8") -#define ACCU_REG asm("r7") -#endif -#ifdef __ia64__ -#define PC_REG asm("36") -#define SP_REG asm("37") -#define ACCU_REG asm("38") -#define JUMPTBL_BASE_REG asm("39") -#endif -#ifdef __x86_64__ -#define PC_REG asm("%r15") -#define SP_REG asm("%r14") -#define ACCU_REG asm("%r13") -#endif -#ifdef __aarch64__ -#define PC_REG asm("%x19") -#define SP_REG asm("%x20") -#define ACCU_REG asm("%x21") -#define JUMPTBL_BASE_REG asm("%x22") -#endif -#endif - -#ifdef DEBUG -static intnat caml_bcodcount; -#endif - -/* The interpreter itself */ - -value caml_interprete(code_t prog, asize_t prog_size) -{ -#ifdef PC_REG - register code_t pc PC_REG; - register value * sp SP_REG; - register value accu ACCU_REG; -#else - register code_t pc; - register value * sp; - register value accu; -#endif -#if defined(THREADED_CODE) && defined(ARCH_SIXTYFOUR) && !defined(ARCH_CODE32) -#ifdef JUMPTBL_BASE_REG - register char * jumptbl_base JUMPTBL_BASE_REG; -#else - register char * jumptbl_base; -#endif -#endif - value env; - intnat extra_args; - struct longjmp_buffer * initial_external_raise; - int initial_sp_offset; - /* volatile ensures that initial_local_roots and saved_pc - will keep correct value across longjmp */ - struct caml__roots_block * volatile initial_local_roots; - volatile code_t saved_pc = NULL; - struct longjmp_buffer raise_buf; -#ifndef THREADED_CODE - opcode_t curr_instr; -#endif - -#ifdef THREADED_CODE - static void * jumptable[] = { -# include "caml/jumptbl.h" - }; -#endif - - if (prog == NULL) { /* Interpreter is initializing */ -#ifdef THREADED_CODE - caml_instr_table = (char **) jumptable; - caml_instr_base = Jumptbl_base; -#endif - return Val_unit; - } - -#if defined(THREADED_CODE) && defined(ARCH_SIXTYFOUR) && !defined(ARCH_CODE32) - jumptbl_base = Jumptbl_base; -#endif - initial_local_roots = caml_local_roots; - initial_sp_offset = (char *) caml_stack_high - (char *) caml_extern_sp; - initial_external_raise = caml_external_raise; - caml_callback_depth++; - saved_pc = NULL; - - if (sigsetjmp(raise_buf.buf, 0)) { - caml_local_roots = initial_local_roots; - sp = caml_extern_sp; - accu = caml_exn_bucket; - pc = saved_pc; saved_pc = NULL; - if (pc != NULL) pc += 2; - /* +2 adjustement for the sole purpose of backtraces */ - goto raise_exception; - } - caml_external_raise = &raise_buf; - - sp = caml_extern_sp; - pc = prog; - extra_args = 0; - env = Atom(0); - accu = Val_int(0); - -#ifdef THREADED_CODE -#ifdef DEBUG - next_instr: - if (caml_icount-- == 0) caml_stop_here (); - CAMLassert(sp >= caml_stack_low); - CAMLassert(sp <= caml_stack_high); -#endif - goto *(void *)(jumptbl_base + *pc++); /* Jump to the first instruction */ -#else - while(1) { -#ifdef DEBUG - caml_bcodcount++; - if (caml_icount-- == 0) caml_stop_here (); - if (caml_trace_level>1) printf("\n##%" ARCH_INTNAT_PRINTF_FORMAT "d\n", - caml_bcodcount); - if (caml_trace_level>0) caml_disasm_instr(pc); - if (caml_trace_level>1) { - printf("env="); - caml_trace_value_file(env,prog,prog_size,stdout); - putchar('\n'); - caml_trace_accu_sp_file(accu,sp,prog,prog_size,stdout); - fflush(stdout); - }; - CAMLassert(sp >= caml_stack_low); - CAMLassert(sp <= caml_stack_high); -#endif - curr_instr = *pc++; - - dispatch_instr: - switch(curr_instr) { -#endif - -/* Basic stack operations */ - - Instruct(ACC0): - accu = sp[0]; Next; - Instruct(ACC1): - accu = sp[1]; Next; - Instruct(ACC2): - accu = sp[2]; Next; - Instruct(ACC3): - accu = sp[3]; Next; - Instruct(ACC4): - accu = sp[4]; Next; - Instruct(ACC5): - accu = sp[5]; Next; - Instruct(ACC6): - accu = sp[6]; Next; - Instruct(ACC7): - accu = sp[7]; Next; - - Instruct(PUSH): Instruct(PUSHACC0): - *--sp = accu; Next; - Instruct(PUSHACC1): - *--sp = accu; accu = sp[1]; Next; - Instruct(PUSHACC2): - *--sp = accu; accu = sp[2]; Next; - Instruct(PUSHACC3): - *--sp = accu; accu = sp[3]; Next; - Instruct(PUSHACC4): - *--sp = accu; accu = sp[4]; Next; - Instruct(PUSHACC5): - *--sp = accu; accu = sp[5]; Next; - Instruct(PUSHACC6): - *--sp = accu; accu = sp[6]; Next; - Instruct(PUSHACC7): - *--sp = accu; accu = sp[7]; Next; - - Instruct(PUSHACC): - *--sp = accu; - /* Fallthrough */ - Instruct(ACC): - accu = sp[*pc++]; - Next; - - Instruct(POP): - sp += *pc++; - Next; - Instruct(ASSIGN): - sp[*pc++] = accu; - accu = Val_unit; - Next; - -/* Access in heap-allocated environment */ - - Instruct(ENVACC1): - accu = Field(env, 1); Next; - Instruct(ENVACC2): - accu = Field(env, 2); Next; - Instruct(ENVACC3): - accu = Field(env, 3); Next; - Instruct(ENVACC4): - accu = Field(env, 4); Next; - - Instruct(PUSHENVACC1): - *--sp = accu; accu = Field(env, 1); Next; - Instruct(PUSHENVACC2): - *--sp = accu; accu = Field(env, 2); Next; - Instruct(PUSHENVACC3): - *--sp = accu; accu = Field(env, 3); Next; - Instruct(PUSHENVACC4): - *--sp = accu; accu = Field(env, 4); Next; - - Instruct(PUSHENVACC): - *--sp = accu; - /* Fallthrough */ - Instruct(ENVACC): - accu = Field(env, *pc++); - Next; - -/* Function application */ - - Instruct(PUSH_RETADDR): { - sp -= 3; - sp[0] = (value) (pc + *pc); - sp[1] = env; - sp[2] = Val_long(extra_args); - pc++; - Next; - } - Instruct(APPLY): { - extra_args = *pc - 1; - pc = Code_val(accu); - env = accu; - goto check_stacks; - } - Instruct(APPLY1): { - value arg1 = sp[0]; - sp -= 3; - sp[0] = arg1; - sp[1] = (value)pc; - sp[2] = env; - sp[3] = Val_long(extra_args); - pc = Code_val(accu); - env = accu; - extra_args = 0; - goto check_stacks; - } - Instruct(APPLY2): { - value arg1 = sp[0]; - value arg2 = sp[1]; - sp -= 3; - sp[0] = arg1; - sp[1] = arg2; - sp[2] = (value)pc; - sp[3] = env; - sp[4] = Val_long(extra_args); - pc = Code_val(accu); - env = accu; - extra_args = 1; - goto check_stacks; - } - Instruct(APPLY3): { - value arg1 = sp[0]; - value arg2 = sp[1]; - value arg3 = sp[2]; - sp -= 3; - sp[0] = arg1; - sp[1] = arg2; - sp[2] = arg3; - sp[3] = (value)pc; - sp[4] = env; - sp[5] = Val_long(extra_args); - pc = Code_val(accu); - env = accu; - extra_args = 2; - goto check_stacks; - } - - Instruct(APPTERM): { - int nargs = *pc++; - int slotsize = *pc; - value * newsp; - int i; - /* Slide the nargs bottom words of the current frame to the top - of the frame, and discard the remainder of the frame */ - newsp = sp + slotsize - nargs; - for (i = nargs - 1; i >= 0; i--) newsp[i] = sp[i]; - sp = newsp; - pc = Code_val(accu); - env = accu; - extra_args += nargs - 1; - goto check_stacks; - } - Instruct(APPTERM1): { - value arg1 = sp[0]; - sp = sp + *pc - 1; - sp[0] = arg1; - pc = Code_val(accu); - env = accu; - goto check_stacks; - } - Instruct(APPTERM2): { - value arg1 = sp[0]; - value arg2 = sp[1]; - sp = sp + *pc - 2; - sp[0] = arg1; - sp[1] = arg2; - pc = Code_val(accu); - env = accu; - extra_args += 1; - goto check_stacks; - } - Instruct(APPTERM3): { - value arg1 = sp[0]; - value arg2 = sp[1]; - value arg3 = sp[2]; - sp = sp + *pc - 3; - sp[0] = arg1; - sp[1] = arg2; - sp[2] = arg3; - pc = Code_val(accu); - env = accu; - extra_args += 2; - goto check_stacks; - } - - Instruct(RETURN): { - sp += *pc++; - if (extra_args > 0) { - extra_args--; - pc = Code_val(accu); - env = accu; - } else { - pc = (code_t)(sp[0]); - env = sp[1]; - extra_args = Long_val(sp[2]); - sp += 3; - } - Next; - } - - Instruct(RESTART): { - int num_args = Wosize_val(env) - 2; - int i; - sp -= num_args; - for (i = 0; i < num_args; i++) sp[i] = Field(env, i + 2); - env = Field(env, 1); - extra_args += num_args; - Next; - } - - Instruct(GRAB): { - int required = *pc++; - if (extra_args >= required) { - extra_args -= required; - } else { - mlsize_t num_args, i; - num_args = 1 + extra_args; /* arg1 + extra args */ - Alloc_small(accu, num_args + 2, Closure_tag); - Field(accu, 1) = env; - for (i = 0; i < num_args; i++) Field(accu, i + 2) = sp[i]; - Code_val(accu) = pc - 3; /* Point to the preceding RESTART instr. */ - sp += num_args; - pc = (code_t)(sp[0]); - env = sp[1]; - extra_args = Long_val(sp[2]); - sp += 3; - } - Next; - } - - Instruct(CLOSURE): { - int nvars = *pc++; - int i; - if (nvars > 0) *--sp = accu; - if (nvars < Max_young_wosize) { - /* nvars + 1 <= Max_young_wosize, can allocate in minor heap */ - Alloc_small(accu, 1 + nvars, Closure_tag); - for (i = 0; i < nvars; i++) Field(accu, i + 1) = sp[i]; - } else { - /* PR#6385: must allocate in major heap */ - /* caml_alloc_shr and caml_initialize never trigger a GC, - so no need to Setup_for_gc */ - accu = caml_alloc_shr(1 + nvars, Closure_tag); - for (i = 0; i < nvars; i++) caml_initialize(&Field(accu, i + 1), sp[i]); - } - /* The code pointer is not in the heap, so no need to go through - caml_initialize. */ - Code_val(accu) = pc + *pc; - pc++; - sp += nvars; - Next; - } - - Instruct(CLOSUREREC): { - int nfuncs = *pc++; - int nvars = *pc++; - mlsize_t blksize = nfuncs * 2 - 1 + nvars; - int i; - value * p; - if (nvars > 0) *--sp = accu; - if (blksize <= Max_young_wosize) { - Alloc_small(accu, blksize, Closure_tag); - p = &Field(accu, nfuncs * 2 - 1); - for (i = 0; i < nvars; i++, p++) *p = sp[i]; - } else { - /* PR#6385: must allocate in major heap */ - /* caml_alloc_shr and caml_initialize never trigger a GC, - so no need to Setup_for_gc */ - accu = caml_alloc_shr(blksize, Closure_tag); - p = &Field(accu, nfuncs * 2 - 1); - for (i = 0; i < nvars; i++, p++) caml_initialize(p, sp[i]); - } - sp += nvars; - /* The code pointers and infix headers are not in the heap, - so no need to go through caml_initialize. */ - p = &Field(accu, 0); - *p = (value) (pc + pc[0]); - *--sp = accu; - p++; - for (i = 1; i < nfuncs; i++) { - *p = Make_header(i * 2, Infix_tag, Caml_white); /* color irrelevant. */ - p++; - *p = (value) (pc + pc[i]); - *--sp = (value) p; - p++; - } - pc += nfuncs; - Next; - } - - Instruct(PUSHOFFSETCLOSURE): - *--sp = accu; /* fallthrough */ - Instruct(OFFSETCLOSURE): - accu = env + *pc++ * sizeof(value); Next; - - Instruct(PUSHOFFSETCLOSUREM2): - *--sp = accu; /* fallthrough */ - Instruct(OFFSETCLOSUREM2): - accu = env - 2 * sizeof(value); Next; - Instruct(PUSHOFFSETCLOSURE0): - *--sp = accu; /* fallthrough */ - Instruct(OFFSETCLOSURE0): - accu = env; Next; - Instruct(PUSHOFFSETCLOSURE2): - *--sp = accu; /* fallthrough */ - Instruct(OFFSETCLOSURE2): - accu = env + 2 * sizeof(value); Next; - - -/* Access to global variables */ - - Instruct(PUSHGETGLOBAL): - *--sp = accu; - /* Fallthrough */ - Instruct(GETGLOBAL): - accu = Field(caml_global_data, *pc); - pc++; - Next; - - Instruct(PUSHGETGLOBALFIELD): - *--sp = accu; - /* Fallthrough */ - Instruct(GETGLOBALFIELD): { - accu = Field(caml_global_data, *pc); - pc++; - accu = Field(accu, *pc); - pc++; - Next; - } - - Instruct(SETGLOBAL): - caml_modify(&Field(caml_global_data, *pc), accu); - accu = Val_unit; - pc++; - Next; - -/* Allocation of blocks */ - - Instruct(PUSHATOM0): - *--sp = accu; - /* Fallthrough */ - Instruct(ATOM0): - accu = Atom(0); Next; - - Instruct(PUSHATOM): - *--sp = accu; - /* Fallthrough */ - Instruct(ATOM): - accu = Atom(*pc++); Next; - - Instruct(MAKEBLOCK): { - mlsize_t wosize = *pc++; - tag_t tag = *pc++; - mlsize_t i; - value block; - if (wosize <= Max_young_wosize) { - Alloc_small(block, wosize, tag); - Field(block, 0) = accu; - for (i = 1; i < wosize; i++) Field(block, i) = *sp++; - } else { - block = caml_alloc_shr(wosize, tag); - caml_initialize(&Field(block, 0), accu); - for (i = 1; i < wosize; i++) caml_initialize(&Field(block, i), *sp++); - } - accu = block; - Next; - } - Instruct(MAKEBLOCK1): { - tag_t tag = *pc++; - value block; - Alloc_small(block, 1, tag); - Field(block, 0) = accu; - accu = block; - Next; - } - Instruct(MAKEBLOCK2): { - tag_t tag = *pc++; - value block; - Alloc_small(block, 2, tag); - Field(block, 0) = accu; - Field(block, 1) = sp[0]; - sp += 1; - accu = block; - Next; - } - Instruct(MAKEBLOCK3): { - tag_t tag = *pc++; - value block; - Alloc_small(block, 3, tag); - Field(block, 0) = accu; - Field(block, 1) = sp[0]; - Field(block, 2) = sp[1]; - sp += 2; - accu = block; - Next; - } - Instruct(MAKEFLOATBLOCK): { - mlsize_t size = *pc++; - mlsize_t i; - value block; - if (size <= Max_young_wosize / Double_wosize) { - Alloc_small(block, size * Double_wosize, Double_array_tag); - } else { - block = caml_alloc_shr(size * Double_wosize, Double_array_tag); - } - Store_double_flat_field(block, 0, Double_val(accu)); - for (i = 1; i < size; i++){ - Store_double_flat_field(block, i, Double_val(*sp)); - ++ sp; - } - accu = block; - Next; - } - -/* Access to components of blocks */ - - Instruct(GETFIELD0): - accu = Field(accu, 0); Next; - Instruct(GETFIELD1): - accu = Field(accu, 1); Next; - Instruct(GETFIELD2): - accu = Field(accu, 2); Next; - Instruct(GETFIELD3): - accu = Field(accu, 3); Next; - Instruct(GETFIELD): - accu = Field(accu, *pc); pc++; Next; - Instruct(GETFLOATFIELD): { - double d = Double_flat_field(accu, *pc); - Alloc_small(accu, Double_wosize, Double_tag); - Store_double_val(accu, d); - pc++; - Next; - } - - Instruct(SETFIELD0): - caml_modify(&Field(accu, 0), *sp++); - accu = Val_unit; - Next; - Instruct(SETFIELD1): - caml_modify(&Field(accu, 1), *sp++); - accu = Val_unit; - Next; - Instruct(SETFIELD2): - caml_modify(&Field(accu, 2), *sp++); - accu = Val_unit; - Next; - Instruct(SETFIELD3): - caml_modify(&Field(accu, 3), *sp++); - accu = Val_unit; - Next; - Instruct(SETFIELD): - caml_modify(&Field(accu, *pc), *sp++); - accu = Val_unit; - pc++; - Next; - Instruct(SETFLOATFIELD): - Store_double_flat_field(accu, *pc, Double_val(*sp)); - accu = Val_unit; - sp++; - pc++; - Next; - -/* Array operations */ - - Instruct(VECTLENGTH): { - /* Todo: when FLAT_FLOAT_ARRAY is false, this instruction should - be split into VECTLENGTH and FLOATVECTLENGTH because we know - statically which one it is. */ - mlsize_t size = Wosize_val(accu); - if (Tag_val(accu) == Double_array_tag) size = size / Double_wosize; - accu = Val_long(size); - Next; - } - Instruct(GETVECTITEM): - accu = Field(accu, Long_val(sp[0])); - sp += 1; - Next; - Instruct(SETVECTITEM): - caml_modify(&Field(accu, Long_val(sp[0])), sp[1]); - accu = Val_unit; - sp += 2; - Next; - -/* Bytes/String operations */ - Instruct(GETSTRINGCHAR): - Instruct(GETBYTESCHAR): - accu = Val_int(Byte_u(accu, Long_val(sp[0]))); - sp += 1; - Next; - Instruct(SETBYTESCHAR): - Byte_u(accu, Long_val(sp[0])) = Int_val(sp[1]); - sp += 2; - accu = Val_unit; - Next; - -/* Branches and conditional branches */ - - Instruct(BRANCH): - pc += *pc; - Next; - Instruct(BRANCHIF): - if (accu != Val_false) pc += *pc; else pc++; - Next; - Instruct(BRANCHIFNOT): - if (accu == Val_false) pc += *pc; else pc++; - Next; - Instruct(SWITCH): { - uint32_t sizes = *pc++; - if (Is_block(accu)) { - intnat index = Tag_val(accu); - CAMLassert ((uintnat) index < (sizes >> 16)); - pc += pc[(sizes & 0xFFFF) + index]; - } else { - intnat index = Long_val(accu); - CAMLassert ((uintnat) index < (sizes & 0xFFFF)) ; - pc += pc[index]; - } - Next; - } - Instruct(BOOLNOT): - accu = Val_not(accu); - Next; - -/* Exceptions */ - - Instruct(PUSHTRAP): - sp -= 4; - Trap_pc(sp) = pc + *pc; - Trap_link(sp) = caml_trapsp; - sp[2] = env; - sp[3] = Val_long(extra_args); - caml_trapsp = sp; - pc++; - Next; - - Instruct(POPTRAP): - if (caml_something_to_do) { - /* We must check here so that if a signal is pending and its - handler triggers an exception, the exception is trapped - by the current try...with, not the enclosing one. */ - pc--; /* restart the POPTRAP after processing the signal */ - goto process_signal; - } - caml_trapsp = Trap_link(sp); - sp += 4; - Next; - - Instruct(RAISE_NOTRACE): - if (caml_trapsp >= caml_trap_barrier) caml_debugger(TRAP_BARRIER); - goto raise_notrace; - - Instruct(RERAISE): - if (caml_trapsp >= caml_trap_barrier) caml_debugger(TRAP_BARRIER); - if (caml_backtrace_active) caml_stash_backtrace(accu, pc, sp, 1); - goto raise_notrace; - - Instruct(RAISE): - raise_exception: - if (caml_trapsp >= caml_trap_barrier) caml_debugger(TRAP_BARRIER); - if (caml_backtrace_active) caml_stash_backtrace(accu, pc, sp, 0); - raise_notrace: - if ((char *) caml_trapsp - >= (char *) caml_stack_high - initial_sp_offset) { - caml_external_raise = initial_external_raise; - caml_extern_sp = (value *) ((char *) caml_stack_high - - initial_sp_offset); - caml_callback_depth--; - return Make_exception_result(accu); - } - sp = caml_trapsp; - pc = Trap_pc(sp); - caml_trapsp = Trap_link(sp); - env = sp[2]; - extra_args = Long_val(sp[3]); - sp += 4; - Next; - -/* Stack checks */ - - check_stacks: - if (sp < caml_stack_threshold) { - caml_extern_sp = sp; - caml_realloc_stack(Stack_threshold / sizeof(value)); - sp = caml_extern_sp; - } - /* Fall through CHECK_SIGNALS */ - -/* Signal handling */ - - Instruct(CHECK_SIGNALS): /* accu not preserved */ - if (caml_something_to_do) goto process_signal; - Next; - - process_signal: - caml_something_to_do = 0; - Setup_for_event; - caml_process_event(); - Restore_after_event; - Next; - -/* Calling C functions */ - - Instruct(C_CALL1): - Setup_for_c_call; - accu = Primitive(*pc)(accu); - Restore_after_c_call; - pc++; - Next; - Instruct(C_CALL2): - Setup_for_c_call; - accu = Primitive(*pc)(accu, sp[1]); - Restore_after_c_call; - sp += 1; - pc++; - Next; - Instruct(C_CALL3): - Setup_for_c_call; - accu = Primitive(*pc)(accu, sp[1], sp[2]); - Restore_after_c_call; - sp += 2; - pc++; - Next; - Instruct(C_CALL4): - Setup_for_c_call; - accu = Primitive(*pc)(accu, sp[1], sp[2], sp[3]); - Restore_after_c_call; - sp += 3; - pc++; - Next; - Instruct(C_CALL5): - Setup_for_c_call; - accu = Primitive(*pc)(accu, sp[1], sp[2], sp[3], sp[4]); - Restore_after_c_call; - sp += 4; - pc++; - Next; - Instruct(C_CALLN): { - int nargs = *pc++; - *--sp = accu; - Setup_for_c_call; - accu = Primitive(*pc)(sp + 1, nargs); - Restore_after_c_call; - sp += nargs; - pc++; - Next; - } - -/* Integer constants */ - - Instruct(CONST0): - accu = Val_int(0); Next; - Instruct(CONST1): - accu = Val_int(1); Next; - Instruct(CONST2): - accu = Val_int(2); Next; - Instruct(CONST3): - accu = Val_int(3); Next; - - Instruct(PUSHCONST0): - *--sp = accu; accu = Val_int(0); Next; - Instruct(PUSHCONST1): - *--sp = accu; accu = Val_int(1); Next; - Instruct(PUSHCONST2): - *--sp = accu; accu = Val_int(2); Next; - Instruct(PUSHCONST3): - *--sp = accu; accu = Val_int(3); Next; - - Instruct(PUSHCONSTINT): - *--sp = accu; - /* Fallthrough */ - Instruct(CONSTINT): - accu = Val_int(*pc); - pc++; - Next; - -/* Integer arithmetic */ - - Instruct(NEGINT): - accu = (value)(2 - (intnat)accu); Next; - Instruct(ADDINT): - accu = (value)((intnat) accu + (intnat) *sp++ - 1); Next; - Instruct(SUBINT): - accu = (value)((intnat) accu - (intnat) *sp++ + 1); Next; - Instruct(MULINT): - accu = Val_long(Long_val(accu) * Long_val(*sp++)); Next; - - Instruct(DIVINT): { - intnat divisor = Long_val(*sp++); - if (divisor == 0) { Setup_for_c_call; caml_raise_zero_divide(); } - accu = Val_long(Long_val(accu) / divisor); - Next; - } - Instruct(MODINT): { - intnat divisor = Long_val(*sp++); - if (divisor == 0) { Setup_for_c_call; caml_raise_zero_divide(); } - accu = Val_long(Long_val(accu) % divisor); - Next; - } - Instruct(ANDINT): - accu = (value)((intnat) accu & (intnat) *sp++); Next; - Instruct(ORINT): - accu = (value)((intnat) accu | (intnat) *sp++); Next; - Instruct(XORINT): - accu = (value)(((intnat) accu ^ (intnat) *sp++) | 1); Next; - Instruct(LSLINT): - accu = (value)((((intnat) accu - 1) << Long_val(*sp++)) + 1); Next; - Instruct(LSRINT): - accu = (value)((((uintnat) accu) >> Long_val(*sp++)) | 1); Next; - Instruct(ASRINT): - accu = (value)((((intnat) accu) >> Long_val(*sp++)) | 1); Next; - -#define Integer_comparison(typ,opname,tst) \ - Instruct(opname): \ - accu = Val_int((typ) accu tst (typ) *sp++); Next; - - Integer_comparison(intnat,EQ, ==) - Integer_comparison(intnat,NEQ, !=) - Integer_comparison(intnat,LTINT, <) - Integer_comparison(intnat,LEINT, <=) - Integer_comparison(intnat,GTINT, >) - Integer_comparison(intnat,GEINT, >=) - Integer_comparison(uintnat,ULTINT, <) - Integer_comparison(uintnat,UGEINT, >=) - -#define Integer_branch_comparison(typ,opname,tst,debug) \ - Instruct(opname): \ - if ( *pc++ tst (typ) Long_val(accu)) { \ - pc += *pc ; \ - } else { \ - pc++ ; \ - } ; Next; - - Integer_branch_comparison(intnat,BEQ, ==, "==") - Integer_branch_comparison(intnat,BNEQ, !=, "!=") - Integer_branch_comparison(intnat,BLTINT, <, "<") - Integer_branch_comparison(intnat,BLEINT, <=, "<=") - Integer_branch_comparison(intnat,BGTINT, >, ">") - Integer_branch_comparison(intnat,BGEINT, >=, ">=") - Integer_branch_comparison(uintnat,BULTINT, <, "<") - Integer_branch_comparison(uintnat,BUGEINT, >=, ">=") - - Instruct(OFFSETINT): - accu += *pc << 1; - pc++; - Next; - Instruct(OFFSETREF): - Field(accu, 0) += *pc << 1; - accu = Val_unit; - pc++; - Next; - Instruct(ISINT): - accu = Val_long(accu & 1); - Next; - -/* Object-oriented operations */ - -#define Lookup(obj, lab) Field (Field (obj, 0), Int_val(lab)) - - /* please don't forget to keep below code in sync with the - functions caml_cache_public_method and - caml_cache_public_method2 in obj.c */ - - Instruct(GETMETHOD): - accu = Lookup(sp[0], accu); - Next; - -#define CAML_METHOD_CACHE -#ifdef CAML_METHOD_CACHE - Instruct(GETPUBMET): { - /* accu == object, pc[0] == tag, pc[1] == cache */ - value meths = Field (accu, 0); - value ofs; -#ifdef CAML_TEST_CACHE - static int calls = 0, hits = 0; - if (calls >= 10000000) { - fprintf(stderr, "cache hit = %d%%\n", hits / 100000); - calls = 0; hits = 0; - } - calls++; -#endif - *--sp = accu; - accu = Val_int(*pc++); - ofs = *pc & Field(meths,1); - if (*(value*)(((char*)&Field(meths,3)) + ofs) == accu) { -#ifdef CAML_TEST_CACHE - hits++; -#endif - accu = *(value*)(((char*)&Field(meths,2)) + ofs); - } - else - { - int li = 3, hi = Field(meths,0), mi; - while (li < hi) { - mi = ((li+hi) >> 1) | 1; - if (accu < Field(meths,mi)) hi = mi-2; - else li = mi; - } - *pc = (li-3)*sizeof(value); - accu = Field (meths, li-1); - } - pc++; - Next; - } -#else - Instruct(GETPUBMET): - *--sp = accu; - accu = Val_int(*pc); - pc += 2; - /* Fallthrough */ -#endif - Instruct(GETDYNMET): { - /* accu == tag, sp[0] == object, *pc == cache */ - value meths = Field (sp[0], 0); - int li = 3, hi = Field(meths,0), mi; - while (li < hi) { - mi = ((li+hi) >> 1) | 1; - if (accu < Field(meths,mi)) hi = mi-2; - else li = mi; - } - accu = Field (meths, li-1); - Next; - } - -/* Debugging and machine control */ - - Instruct(STOP): - caml_external_raise = initial_external_raise; - caml_extern_sp = sp; - caml_callback_depth--; - return accu; - - Instruct(EVENT): - if (--caml_event_count == 0) { - Setup_for_debugger; - caml_debugger(EVENT_COUNT); - Restore_after_debugger; - } - Restart_curr_instr; - - Instruct(BREAK): - Setup_for_debugger; - caml_debugger(BREAKPOINT); - Restore_after_debugger; - Restart_curr_instr; - -#ifndef THREADED_CODE - default: -#if _MSC_VER >= 1200 - __assume(0); -#else - caml_fatal_error_arg("Fatal error: bad opcode (%" - ARCH_INTNAT_PRINTF_FORMAT "x)\n", - (char *) (intnat) *(pc-1)); -#endif - } - } -#endif -} - -void caml_prepare_bytecode(code_t prog, asize_t prog_size) { - /* other implementations of the interpreter (such as an hypothetical - JIT translator) might want to do something with a bytecode before - running it */ - CAMLassert(prog); - CAMLassert(prog_size>0); - /* actually, the threading of the bytecode might be done here */ -} - -void caml_release_bytecode(code_t prog, asize_t prog_size) { - /* other implementations of the interpreter (such as an hypothetical - JIT translator) might want to know when a bytecode is removed */ - /* check that we have a program */ - CAMLassert(prog); - CAMLassert(prog_size>0); -} diff --git a/byterun/ints.c b/byterun/ints.c deleted file mode 100644 index 76ae11d4..00000000 --- a/byterun/ints.c +++ /dev/null @@ -1,830 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -#include -#include -#include "caml/alloc.h" -#include "caml/custom.h" -#include "caml/fail.h" -#include "caml/intext.h" -#include "caml/memory.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" - -static const char * parse_sign_and_base(const char * p, - /*out*/ int * base, - /*out*/ int * signedness, - /*out*/ int * sign) -{ - *sign = 1; - if (*p == '-') { - *sign = -1; - p++; - } else if (*p == '+') - p++; - *base = 10; *signedness = 1; - if (*p == '0') { - switch (p[1]) { - case 'x': case 'X': - *base = 16; *signedness = 0; p += 2; break; - case 'o': case 'O': - *base = 8; *signedness = 0; p += 2; break; - case 'b': case 'B': - *base = 2; *signedness = 0; p += 2; break; - case 'u': case 'U': - *signedness = 0; p += 2; break; - } - } - return p; -} - -static int parse_digit(char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - else if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - else if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - else - return -1; -} - -#define INT_ERRMSG "int_of_string" -#define INT32_ERRMSG "Int32.of_string" -#define INT64_ERRMSG "Int64.of_string" -#define INTNAT_ERRMSG "Nativeint.of_string" - -static intnat parse_intnat(value s, int nbits, const char *errmsg) -{ - const char * p; - uintnat res, threshold; - int sign, base, signedness, d; - - p = parse_sign_and_base(String_val(s), &base, &signedness, &sign); - threshold = ((uintnat) -1) / base; - d = parse_digit(*p); - if (d < 0 || d >= base) caml_failwith(errmsg); - for (p++, res = d; /*nothing*/; p++) { - char c = *p; - if (c == '_') continue; - d = parse_digit(c); - if (d < 0 || d >= base) break; - /* Detect overflow in multiplication base * res */ - if (res > threshold) caml_failwith(errmsg); - res = base * res + d; - /* Detect overflow in addition (base * res) + d */ - if (res < (uintnat) d) caml_failwith(errmsg); - } - if (p != String_val(s) + caml_string_length(s)){ - caml_failwith(errmsg); - } - if (signedness) { - /* Signed representation expected, allow -2^(nbits-1) to 2^(nbits-1) - 1 */ - if (sign >= 0) { - if (res >= (uintnat)1 << (nbits - 1)) caml_failwith(errmsg); - } else { - if (res > (uintnat)1 << (nbits - 1)) caml_failwith(errmsg); - } - } else { - /* Unsigned representation expected, allow 0 to 2^nbits - 1 - and tolerate -(2^nbits - 1) to 0 */ - if (nbits < sizeof(uintnat) * 8 && res >= (uintnat)1 << nbits) - caml_failwith(errmsg); - } - return sign < 0 ? -((intnat) res) : (intnat) res; -} - -value caml_bswap16_direct(value x) -{ - return ((((x & 0x00FF) << 8) | - ((x & 0xFF00) >> 8))); -} - -CAMLprim value caml_bswap16(value v) -{ - intnat x = Int_val(v); - return (Val_int ((((x & 0x00FF) << 8) | - ((x & 0xFF00) >> 8)))); -} - -/* Tagged integers */ - -CAMLprim value caml_int_compare(value v1, value v2) -{ - int res = (v1 > v2) - (v1 < v2); - return Val_int(res); -} - -CAMLprim value caml_int_of_string(value s) -{ - return Val_long(parse_intnat(s, 8 * sizeof(value) - 1, INT_ERRMSG)); -} - -#define FORMAT_BUFFER_SIZE 32 - -static char parse_format(value fmt, - char * suffix, - char format_string[FORMAT_BUFFER_SIZE]) -{ - char * p; - char lastletter; - mlsize_t len, len_suffix; - - /* Copy OCaml format fmt to format_string, - adding the suffix before the last letter of the format */ - len = caml_string_length(fmt); - len_suffix = strlen(suffix); - if (len + len_suffix + 1 >= FORMAT_BUFFER_SIZE) - caml_invalid_argument("format_int: format too long"); - memmove(format_string, String_val(fmt), len); - p = format_string + len - 1; - lastletter = *p; - /* Compress two-letter formats, ignoring the [lnL] annotation */ - if (p[-1] == 'l' || p[-1] == 'n' || p[-1] == 'L') p--; - memmove(p, suffix, len_suffix); p += len_suffix; - *p++ = lastletter; - *p = 0; - /* Return the conversion type (last letter) */ - return lastletter; -} - -CAMLprim value caml_format_int(value fmt, value arg) -{ - char format_string[FORMAT_BUFFER_SIZE]; - char conv; - value res; - - conv = parse_format(fmt, ARCH_INTNAT_PRINTF_FORMAT, format_string); - switch (conv) { - case 'u': case 'x': case 'X': case 'o': - res = caml_alloc_sprintf(format_string, Unsigned_long_val(arg)); - break; - default: - res = caml_alloc_sprintf(format_string, Long_val(arg)); - break; - } - return res; -} - -/* 32-bit integers */ - -static int int32_cmp(value v1, value v2) -{ - int32_t i1 = Int32_val(v1); - int32_t i2 = Int32_val(v2); - return (i1 > i2) - (i1 < i2); -} - -static intnat int32_hash(value v) -{ - return Int32_val(v); -} - -static void int32_serialize(value v, uintnat * bsize_32, - uintnat * bsize_64) -{ - caml_serialize_int_4(Int32_val(v)); - *bsize_32 = *bsize_64 = 4; -} - -static uintnat int32_deserialize(void * dst) -{ - *((int32_t *) dst) = caml_deserialize_sint_4(); - return 4; -} - -CAMLexport struct custom_operations caml_int32_ops = { - "_i", - custom_finalize_default, - int32_cmp, - int32_hash, - int32_serialize, - int32_deserialize, - custom_compare_ext_default -}; - -CAMLexport value caml_copy_int32(int32_t i) -{ - value res = caml_alloc_custom(&caml_int32_ops, 4, 0, 1); - Int32_val(res) = i; - return res; -} - -CAMLprim value caml_int32_neg(value v) -{ return caml_copy_int32(- Int32_val(v)); } - -CAMLprim value caml_int32_add(value v1, value v2) -{ return caml_copy_int32(Int32_val(v1) + Int32_val(v2)); } - -CAMLprim value caml_int32_sub(value v1, value v2) -{ return caml_copy_int32(Int32_val(v1) - Int32_val(v2)); } - -CAMLprim value caml_int32_mul(value v1, value v2) -{ return caml_copy_int32(Int32_val(v1) * Int32_val(v2)); } - -CAMLprim value caml_int32_div(value v1, value v2) -{ - int32_t dividend = Int32_val(v1); - int32_t divisor = Int32_val(v2); - if (divisor == 0) caml_raise_zero_divide(); - /* PR#4740: on some processors, division crashes on overflow. - Implement the same behavior as for type "int". */ - if (dividend == (1<<31) && divisor == -1) return v1; - return caml_copy_int32(dividend / divisor); -} - -CAMLprim value caml_int32_mod(value v1, value v2) -{ - int32_t dividend = Int32_val(v1); - int32_t divisor = Int32_val(v2); - if (divisor == 0) caml_raise_zero_divide(); - /* PR#4740: on some processors, modulus crashes if division overflows. - Implement the same behavior as for type "int". */ - if (dividend == (1<<31) && divisor == -1) return caml_copy_int32(0); - return caml_copy_int32(dividend % divisor); -} - -CAMLprim value caml_int32_and(value v1, value v2) -{ return caml_copy_int32(Int32_val(v1) & Int32_val(v2)); } - -CAMLprim value caml_int32_or(value v1, value v2) -{ return caml_copy_int32(Int32_val(v1) | Int32_val(v2)); } - -CAMLprim value caml_int32_xor(value v1, value v2) -{ return caml_copy_int32(Int32_val(v1) ^ Int32_val(v2)); } - -CAMLprim value caml_int32_shift_left(value v1, value v2) -{ return caml_copy_int32(Int32_val(v1) << Int_val(v2)); } - -CAMLprim value caml_int32_shift_right(value v1, value v2) -{ return caml_copy_int32(Int32_val(v1) >> Int_val(v2)); } - -CAMLprim value caml_int32_shift_right_unsigned(value v1, value v2) -{ return caml_copy_int32((uint32_t)Int32_val(v1) >> Int_val(v2)); } - -static int32_t caml_swap32(int32_t x) -{ - return (((x & 0x000000FF) << 24) | - ((x & 0x0000FF00) << 8) | - ((x & 0x00FF0000) >> 8) | - ((x & 0xFF000000) >> 24)); -} - -value caml_int32_direct_bswap(value v) -{ return caml_swap32(v); } - -CAMLprim value caml_int32_bswap(value v) -{ return caml_copy_int32(caml_swap32(Int32_val(v))); } - -CAMLprim value caml_int32_of_int(value v) -{ return caml_copy_int32(Long_val(v)); } - -CAMLprim value caml_int32_to_int(value v) -{ return Val_long(Int32_val(v)); } - -int32_t caml_int32_of_float_unboxed(double x) -{ return x; } - -CAMLprim value caml_int32_of_float(value v) -{ return caml_copy_int32((int32_t)(Double_val(v))); } - -double caml_int32_to_float_unboxed(int32_t x) -{ return x; } - -CAMLprim value caml_int32_to_float(value v) -{ return caml_copy_double((double)(Int32_val(v))); } - -intnat caml_int32_compare_unboxed(int32_t i1, int32_t i2) -{ - return (i1 > i2) - (i1 < i2); -} - -CAMLprim value caml_int32_compare(value v1, value v2) -{ - return Val_int(caml_int32_compare_unboxed(Int32_val(v1),Int32_val(v2))); -} - -CAMLprim value caml_int32_format(value fmt, value arg) -{ - char format_string[FORMAT_BUFFER_SIZE]; - - parse_format(fmt, ARCH_INT32_PRINTF_FORMAT, format_string); - return caml_alloc_sprintf(format_string, Int32_val(arg)); -} - -CAMLprim value caml_int32_of_string(value s) -{ - return caml_copy_int32(parse_intnat(s, 32, INT32_ERRMSG)); -} - -int32_t caml_int32_bits_of_float_unboxed(double d) -{ - union { float d; int32_t i; } u; - u.d = d; - return u.i; -} - -double caml_int32_float_of_bits_unboxed(int32_t i) -{ - union { float d; int32_t i; } u; - u.i = i; - return u.d; -} - -CAMLprim value caml_int32_bits_of_float(value vd) -{ - return caml_copy_int32(caml_int32_bits_of_float_unboxed(Double_val(vd))); -} - -CAMLprim value caml_int32_float_of_bits(value vi) -{ - return caml_copy_double(caml_int32_float_of_bits_unboxed(Int32_val(vi))); -} - -/* 64-bit integers */ - -#ifdef ARCH_ALIGN_INT64 - -CAMLexport int64_t caml_Int64_val(value v) -{ - union { int32_t i[2]; int64_t j; } buffer; - buffer.i[0] = ((int32_t *) Data_custom_val(v))[0]; - buffer.i[1] = ((int32_t *) Data_custom_val(v))[1]; - return buffer.j; -} - -#endif - -static int int64_cmp(value v1, value v2) -{ - int64_t i1 = Int64_val(v1); - int64_t i2 = Int64_val(v2); - return (i1 > i2) - (i1 < i2); -} - -static intnat int64_hash(value v) -{ - int64_t x = Int64_val(v); - uint32_t lo = (uint32_t) x, hi = (uint32_t) (x >> 32); - return hi ^ lo; -} - -static void int64_serialize(value v, uintnat * bsize_32, - uintnat * bsize_64) -{ - caml_serialize_int_8(Int64_val(v)); - *bsize_32 = *bsize_64 = 8; -} - -static uintnat int64_deserialize(void * dst) -{ -#ifndef ARCH_ALIGN_INT64 - *((int64_t *) dst) = caml_deserialize_sint_8(); -#else - union { int32_t i[2]; int64_t j; } buffer; - buffer.j = caml_deserialize_sint_8(); - ((int32_t *) dst)[0] = buffer.i[0]; - ((int32_t *) dst)[1] = buffer.i[1]; -#endif - return 8; -} - -CAMLexport struct custom_operations caml_int64_ops = { - "_j", - custom_finalize_default, - int64_cmp, - int64_hash, - int64_serialize, - int64_deserialize, - custom_compare_ext_default -}; - -CAMLexport value caml_copy_int64(int64_t i) -{ - value res = caml_alloc_custom(&caml_int64_ops, 8, 0, 1); -#ifndef ARCH_ALIGN_INT64 - Int64_val(res) = i; -#else - union { int32_t i[2]; int64_t j; } buffer; - buffer.j = i; - ((int32_t *) Data_custom_val(res))[0] = buffer.i[0]; - ((int32_t *) Data_custom_val(res))[1] = buffer.i[1]; -#endif - return res; -} - -CAMLprim value caml_int64_neg(value v) -{ return caml_copy_int64(- Int64_val(v)); } - -CAMLprim value caml_int64_add(value v1, value v2) -{ return caml_copy_int64(Int64_val(v1) + Int64_val(v2)); } - -CAMLprim value caml_int64_sub(value v1, value v2) -{ return caml_copy_int64(Int64_val(v1) - Int64_val(v2)); } - -CAMLprim value caml_int64_mul(value v1, value v2) -{ return caml_copy_int64(Int64_val(v1) * Int64_val(v2)); } - -#define Int64_min_int ((intnat) 1 << (sizeof(intnat) * 8 - 1)) - -CAMLprim value caml_int64_div(value v1, value v2) -{ - int64_t dividend = Int64_val(v1); - int64_t divisor = Int64_val(v2); - if (divisor == 0) caml_raise_zero_divide(); - /* PR#4740: on some processors, division crashes on overflow. - Implement the same behavior as for type "int". */ - if (dividend == ((int64_t)1 << 63) && divisor == -1) return v1; - return caml_copy_int64(Int64_val(v1) / divisor); -} - -CAMLprim value caml_int64_mod(value v1, value v2) -{ - int64_t dividend = Int64_val(v1); - int64_t divisor = Int64_val(v2); - if (divisor == 0) caml_raise_zero_divide(); - /* PR#4740: on some processors, division crashes on overflow. - Implement the same behavior as for type "int". */ - if (dividend == ((int64_t)1 << 63) && divisor == -1){ - return caml_copy_int64(0); - } - return caml_copy_int64(Int64_val(v1) % divisor); -} - -CAMLprim value caml_int64_and(value v1, value v2) -{ return caml_copy_int64(Int64_val(v1) & Int64_val(v2)); } - -CAMLprim value caml_int64_or(value v1, value v2) -{ return caml_copy_int64(Int64_val(v1) | Int64_val(v2)); } - -CAMLprim value caml_int64_xor(value v1, value v2) -{ return caml_copy_int64(Int64_val(v1) ^ Int64_val(v2)); } - -CAMLprim value caml_int64_shift_left(value v1, value v2) -{ return caml_copy_int64(Int64_val(v1) << Int_val(v2)); } - -CAMLprim value caml_int64_shift_right(value v1, value v2) -{ return caml_copy_int64(Int64_val(v1) >> Int_val(v2)); } - -CAMLprim value caml_int64_shift_right_unsigned(value v1, value v2) -{ return caml_copy_int64((uint64_t) (Int64_val(v1)) >> Int_val(v2)); } - -#ifdef ARCH_SIXTYFOUR -static value caml_swap64(value x) -{ - return (((((x) & 0x00000000000000FF) << 56) | - (((x) & 0x000000000000FF00) << 40) | - (((x) & 0x0000000000FF0000) << 24) | - (((x) & 0x00000000FF000000) << 8) | - (((x) & 0x000000FF00000000) >> 8) | - (((x) & 0x0000FF0000000000) >> 24) | - (((x) & 0x00FF000000000000) >> 40) | - (((x) & 0xFF00000000000000) >> 56))); -} - -value caml_int64_direct_bswap(value v) -{ return caml_swap64(v); } -#endif - -CAMLprim value caml_int64_bswap(value v) -{ - int64_t x = Int64_val(v); - return caml_copy_int64 - (((x & INT64_LITERAL(0x00000000000000FFU)) << 56) | - ((x & INT64_LITERAL(0x000000000000FF00U)) << 40) | - ((x & INT64_LITERAL(0x0000000000FF0000U)) << 24) | - ((x & INT64_LITERAL(0x00000000FF000000U)) << 8) | - ((x & INT64_LITERAL(0x000000FF00000000U)) >> 8) | - ((x & INT64_LITERAL(0x0000FF0000000000U)) >> 24) | - ((x & INT64_LITERAL(0x00FF000000000000U)) >> 40) | - ((x & INT64_LITERAL(0xFF00000000000000U)) >> 56)); -} - -CAMLprim value caml_int64_of_int(value v) -{ return caml_copy_int64((int64_t) (Long_val(v))); } - -CAMLprim value caml_int64_to_int(value v) -{ return Val_long((intnat) (Int64_val(v))); } - -int64_t caml_int64_of_float_unboxed(double x) -{ return x; } - -CAMLprim value caml_int64_of_float(value v) -{ return caml_copy_int64((int64_t) (Double_val(v))); } - -double caml_int64_to_float_unboxed(int64_t x) -{ return x; } - -CAMLprim value caml_int64_to_float(value v) -{ return caml_copy_double((double) (Int64_val(v))); } - -CAMLprim value caml_int64_of_int32(value v) -{ return caml_copy_int64((int64_t) (Int32_val(v))); } - -CAMLprim value caml_int64_to_int32(value v) -{ return caml_copy_int32((int32_t) (Int64_val(v))); } - -CAMLprim value caml_int64_of_nativeint(value v) -{ return caml_copy_int64((int64_t) (Nativeint_val(v))); } - -CAMLprim value caml_int64_to_nativeint(value v) -{ return caml_copy_nativeint((intnat) (Int64_val(v))); } - -intnat caml_int64_compare_unboxed(int64_t i1, int64_t i2) -{ - return (i1 > i2) - (i1 < i2); -} - -CAMLprim value caml_int64_compare(value v1, value v2) -{ - return Val_int(caml_int64_compare_unboxed(Int64_val(v1),Int64_val(v2))); -} - -CAMLprim value caml_int64_format(value fmt, value arg) -{ - char format_string[FORMAT_BUFFER_SIZE]; - - parse_format(fmt, ARCH_INT64_PRINTF_FORMAT, format_string); - return caml_alloc_sprintf(format_string, Int64_val(arg)); -} - -CAMLprim value caml_int64_of_string(value s) -{ - const char * p; - uint64_t res, threshold; - int sign, base, signedness, d; - - p = parse_sign_and_base(String_val(s), &base, &signedness, &sign); - threshold = ((uint64_t) -1) / base; - d = parse_digit(*p); - if (d < 0 || d >= base) caml_failwith(INT64_ERRMSG); - res = d; - for (p++; /*nothing*/; p++) { - char c = *p; - if (c == '_') continue; - d = parse_digit(c); - if (d < 0 || d >= base) break; - /* Detect overflow in multiplication base * res */ - if (res > threshold) caml_failwith(INT64_ERRMSG); - res = base * res + d; - /* Detect overflow in addition (base * res) + d */ - if (res < (uint64_t) d) caml_failwith(INT64_ERRMSG); - } - if (p != String_val(s) + caml_string_length(s)){ - caml_failwith(INT64_ERRMSG); - } - if (signedness) { - /* Signed representation expected, allow -2^63 to 2^63 - 1 only */ - if (sign >= 0) { - if (res >= (uint64_t)1 << 63) caml_failwith(INT64_ERRMSG); - } else { - if (res > (uint64_t)1 << 63) caml_failwith(INT64_ERRMSG); - } - } - if (sign < 0) res = - res; - return caml_copy_int64(res); -} - -int64_t caml_int64_bits_of_float_unboxed(double d) -{ - union { double d; int64_t i; int32_t h[2]; } u; - u.d = d; -#if defined(__arm__) && !defined(__ARM_EABI__) - { int32_t t = u.h[0]; u.h[0] = u.h[1]; u.h[1] = t; } -#endif - return u.i; -} - -double caml_int64_float_of_bits_unboxed(int64_t i) -{ - union { double d; int64_t i; int32_t h[2]; } u; - u.i = i; -#if defined(__arm__) && !defined(__ARM_EABI__) - { int32_t t = u.h[0]; u.h[0] = u.h[1]; u.h[1] = t; } -#endif - return u.d; -} - -CAMLprim value caml_int64_bits_of_float(value vd) -{ - return caml_copy_int64(caml_int64_bits_of_float_unboxed(Double_val(vd))); -} - -CAMLprim value caml_int64_float_of_bits(value vi) -{ - return caml_copy_double(caml_int64_float_of_bits_unboxed(Int64_val(vi))); -} - -/* Native integers */ - -static int nativeint_cmp(value v1, value v2) -{ - intnat i1 = Nativeint_val(v1); - intnat i2 = Nativeint_val(v2); - return (i1 > i2) - (i1 < i2); -} - -static intnat nativeint_hash(value v) -{ - intnat n = Nativeint_val(v); -#ifdef ARCH_SIXTYFOUR - /* 32/64 bits compatibility trick. See explanations in file "hash.c", - function caml_hash_mix_intnat. */ - return (n >> 32) ^ (n >> 63) ^ n; -#else - return n; -#endif -} - -static void nativeint_serialize(value v, uintnat * bsize_32, - uintnat * bsize_64) -{ - intnat l = Nativeint_val(v); -#ifdef ARCH_SIXTYFOUR - if (l >= -((intnat)1 << 31) && l < ((intnat)1 << 31)) { - caml_serialize_int_1(1); - caml_serialize_int_4((int32_t) l); - } else { - caml_serialize_int_1(2); - caml_serialize_int_8(l); - } -#else - caml_serialize_int_1(1); - caml_serialize_int_4(l); -#endif - *bsize_32 = 4; - *bsize_64 = 8; -} - -static uintnat nativeint_deserialize(void * dst) -{ - switch (caml_deserialize_uint_1()) { - case 1: - *((intnat *) dst) = caml_deserialize_sint_4(); - break; - case 2: -#ifdef ARCH_SIXTYFOUR - *((intnat *) dst) = caml_deserialize_sint_8(); -#else - caml_deserialize_error("input_value: native integer value too large"); -#endif - break; - default: - caml_deserialize_error("input_value: ill-formed native integer"); - } - return sizeof(intnat); -} - -CAMLexport struct custom_operations caml_nativeint_ops = { - "_n", - custom_finalize_default, - nativeint_cmp, - nativeint_hash, - nativeint_serialize, - nativeint_deserialize, - custom_compare_ext_default -}; - -CAMLexport value caml_copy_nativeint(intnat i) -{ - value res = caml_alloc_custom(&caml_nativeint_ops, sizeof(intnat), 0, 1); - Nativeint_val(res) = i; - return res; -} - -CAMLprim value caml_nativeint_neg(value v) -{ return caml_copy_nativeint(- Nativeint_val(v)); } - -CAMLprim value caml_nativeint_add(value v1, value v2) -{ return caml_copy_nativeint(Nativeint_val(v1) + Nativeint_val(v2)); } - -CAMLprim value caml_nativeint_sub(value v1, value v2) -{ return caml_copy_nativeint(Nativeint_val(v1) - Nativeint_val(v2)); } - -CAMLprim value caml_nativeint_mul(value v1, value v2) -{ return caml_copy_nativeint(Nativeint_val(v1) * Nativeint_val(v2)); } - -#define Nativeint_min_int ((intnat) 1 << (sizeof(intnat) * 8 - 1)) - -CAMLprim value caml_nativeint_div(value v1, value v2) -{ - intnat dividend = Nativeint_val(v1); - intnat divisor = Nativeint_val(v2); - if (divisor == 0) caml_raise_zero_divide(); - /* PR#4740: on some processors, modulus crashes if division overflows. - Implement the same behavior as for type "int". */ - if (dividend == Nativeint_min_int && divisor == -1) return v1; - return caml_copy_nativeint(dividend / divisor); -} - -CAMLprim value caml_nativeint_mod(value v1, value v2) -{ - intnat dividend = Nativeint_val(v1); - intnat divisor = Nativeint_val(v2); - if (divisor == 0) caml_raise_zero_divide(); - /* PR#4740: on some processors, modulus crashes if division overflows. - Implement the same behavior as for type "int". */ - if (dividend == Nativeint_min_int && divisor == -1){ - return caml_copy_nativeint(0); - } - return caml_copy_nativeint(dividend % divisor); -} - -CAMLprim value caml_nativeint_and(value v1, value v2) -{ return caml_copy_nativeint(Nativeint_val(v1) & Nativeint_val(v2)); } - -CAMLprim value caml_nativeint_or(value v1, value v2) -{ return caml_copy_nativeint(Nativeint_val(v1) | Nativeint_val(v2)); } - -CAMLprim value caml_nativeint_xor(value v1, value v2) -{ return caml_copy_nativeint(Nativeint_val(v1) ^ Nativeint_val(v2)); } - -CAMLprim value caml_nativeint_shift_left(value v1, value v2) -{ return caml_copy_nativeint(Nativeint_val(v1) << Int_val(v2)); } - -CAMLprim value caml_nativeint_shift_right(value v1, value v2) -{ return caml_copy_nativeint(Nativeint_val(v1) >> Int_val(v2)); } - -CAMLprim value caml_nativeint_shift_right_unsigned(value v1, value v2) -{ return caml_copy_nativeint((uintnat)Nativeint_val(v1) >> Int_val(v2)); } - -value caml_nativeint_direct_bswap(value v) -{ -#ifdef ARCH_SIXTYFOUR - return caml_swap64(v); -#else - return caml_swap32(v); -#endif -} - -CAMLprim value caml_nativeint_bswap(value v) -{ -#ifdef ARCH_SIXTYFOUR - return caml_copy_nativeint(caml_swap64(Nativeint_val(v))); -#else - return caml_copy_nativeint(caml_swap32(Nativeint_val(v))); -#endif -} - -CAMLprim value caml_nativeint_of_int(value v) -{ return caml_copy_nativeint(Long_val(v)); } - -CAMLprim value caml_nativeint_to_int(value v) -{ return Val_long(Nativeint_val(v)); } - -intnat caml_nativeint_of_float_unboxed(double x) -{ return x; } - -CAMLprim value caml_nativeint_of_float(value v) -{ return caml_copy_nativeint((intnat)(Double_val(v))); } - -double caml_nativeint_to_float_unboxed(intnat x) -{ return x; } - -CAMLprim value caml_nativeint_to_float(value v) -{ return caml_copy_double((double)(Nativeint_val(v))); } - -CAMLprim value caml_nativeint_of_int32(value v) -{ return caml_copy_nativeint(Int32_val(v)); } - -CAMLprim value caml_nativeint_to_int32(value v) -{ return caml_copy_int32(Nativeint_val(v)); } - -intnat caml_nativeint_compare_unboxed(intnat i1, intnat i2) -{ - return (i1 > i2) - (i1 < i2); -} - -CAMLprim value caml_nativeint_compare(value v1, value v2) -{ - return Val_int(caml_nativeint_compare_unboxed(Nativeint_val(v1), - Nativeint_val(v2))); -} - -CAMLprim value caml_nativeint_format(value fmt, value arg) -{ - char format_string[FORMAT_BUFFER_SIZE]; - - parse_format(fmt, ARCH_INTNAT_PRINTF_FORMAT, format_string); - return caml_alloc_sprintf(format_string, Nativeint_val(arg)); -} - -CAMLprim value caml_nativeint_of_string(value s) -{ - return caml_copy_nativeint(parse_intnat(s, 8 * sizeof(value), INTNAT_ERRMSG)); -} diff --git a/byterun/io.c b/byterun/io.c deleted file mode 100644 index d124b56a..00000000 --- a/byterun/io.c +++ /dev/null @@ -1,828 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Buffered input/output. */ - -#include -#include -#include -#include -#include -#include -#include "caml/config.h" -#ifdef HAS_UNISTD -#include -#endif -#ifdef __CYGWIN__ -#include -#endif -#include "caml/alloc.h" -#include "caml/custom.h" -#include "caml/fail.h" -#include "caml/io.h" -#include "caml/memory.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/osdeps.h" -#include "caml/signals.h" -#include "caml/sys.h" - -#ifndef SEEK_SET -#define SEEK_SET 0 -#define SEEK_CUR 1 -#define SEEK_END 2 -#endif - -/* Hooks for locking channels */ - -CAMLexport void (*caml_channel_mutex_free) (struct channel *) = NULL; -CAMLexport void (*caml_channel_mutex_lock) (struct channel *) = NULL; -CAMLexport void (*caml_channel_mutex_unlock) (struct channel *) = NULL; -CAMLexport void (*caml_channel_mutex_unlock_exn) (void) = NULL; - -/* List of opened channels */ -CAMLexport struct channel * caml_all_opened_channels = NULL; - -/* Basic functions over type struct channel *. - These functions can be called directly from C. - No locking is performed. */ - -/* Functions shared between input and output */ - -CAMLexport struct channel * caml_open_descriptor_in(int fd) -{ - struct channel * channel; - - channel = (struct channel *) caml_stat_alloc(sizeof(struct channel)); - channel->fd = fd; - caml_enter_blocking_section(); - channel->offset = lseek(fd, 0, SEEK_CUR); - caml_leave_blocking_section(); - channel->curr = channel->max = channel->buff; - channel->end = channel->buff + IO_BUFFER_SIZE; - channel->mutex = NULL; - channel->revealed = 0; - channel->old_revealed = 0; - channel->refcount = 0; - channel->flags = 0; - channel->next = caml_all_opened_channels; - channel->prev = NULL; - channel->name = NULL; - if (caml_all_opened_channels != NULL) - caml_all_opened_channels->prev = channel; - caml_all_opened_channels = channel; - return channel; -} - -CAMLexport struct channel * caml_open_descriptor_out(int fd) -{ - struct channel * channel; - - channel = caml_open_descriptor_in(fd); - channel->max = NULL; - return channel; -} - -static void unlink_channel(struct channel *channel) -{ - if (channel->prev == NULL) { - CAMLassert (channel == caml_all_opened_channels); - caml_all_opened_channels = caml_all_opened_channels->next; - if (caml_all_opened_channels != NULL) - caml_all_opened_channels->prev = NULL; - } else { - channel->prev->next = channel->next; - if (channel->next != NULL) channel->next->prev = channel->prev; - } -} - -CAMLexport void caml_close_channel(struct channel *channel) -{ - CAML_SYS_CLOSE(channel->fd); - if (channel->refcount > 0) return; - if (caml_channel_mutex_free != NULL) (*caml_channel_mutex_free)(channel); - unlink_channel(channel); - caml_stat_free(channel->name); - caml_stat_free(channel); -} - -CAMLexport file_offset caml_channel_size(struct channel *channel) -{ - file_offset offset; - file_offset end; - int fd; - - /* We extract data from [channel] before dropping the OCaml lock, in case - someone else touches the block. */ - fd = channel->fd; - offset = channel->offset; - caml_enter_blocking_section(); - end = lseek(fd, 0, SEEK_END); - if (end == -1 || lseek(fd, offset, SEEK_SET) != offset) { - caml_leave_blocking_section(); - caml_sys_error(NO_ARG); - } - caml_leave_blocking_section(); - return end; -} - -CAMLexport int caml_channel_binary_mode(struct channel *channel) -{ -#if defined(_WIN32) || defined(__CYGWIN__) - int oldmode = setmode(channel->fd, O_BINARY); - if (oldmode == O_TEXT) setmode(channel->fd, O_TEXT); - return oldmode == O_BINARY; -#else - return 1; -#endif -} - -/* Output */ - -/* Attempt to flush the buffer. This will make room in the buffer for - at least one character. Returns true if the buffer is empty at the - end of the flush, or false if some data remains in the buffer. - */ - -CAMLexport int caml_flush_partial(struct channel *channel) -{ - int towrite, written; - - towrite = channel->curr - channel->buff; - CAMLassert (towrite >= 0); - if (towrite > 0) { - written = caml_write_fd(channel->fd, channel->flags, - channel->buff, towrite); - channel->offset += written; - if (written < towrite) - memmove(channel->buff, channel->buff + written, towrite - written); - channel->curr -= written; - } - return (channel->curr == channel->buff); -} - -/* Flush completely the buffer. */ - -CAMLexport void caml_flush(struct channel *channel) -{ - while (! caml_flush_partial(channel)) /*nothing*/; -} - -/* Output data */ - -CAMLexport void caml_putword(struct channel *channel, uint32_t w) -{ - if (! caml_channel_binary_mode(channel)) - caml_failwith("output_binary_int: not a binary channel"); - caml_putch(channel, w >> 24); - caml_putch(channel, w >> 16); - caml_putch(channel, w >> 8); - caml_putch(channel, w); -} - -CAMLexport int caml_putblock(struct channel *channel, char *p, intnat len) -{ - int n, free, towrite, written; - - n = len >= INT_MAX ? INT_MAX : (int) len; - free = channel->end - channel->curr; - if (n < free) { - /* Write request small enough to fit in buffer: transfer to buffer. */ - memmove(channel->curr, p, n); - channel->curr += n; - return n; - } else { - /* Write request overflows buffer (or just fills it up): transfer whatever - fits to buffer and write the buffer */ - memmove(channel->curr, p, free); - towrite = channel->end - channel->buff; - written = caml_write_fd(channel->fd, channel->flags, - channel->buff, towrite); - if (written < towrite) - memmove(channel->buff, channel->buff + written, towrite - written); - channel->offset += written; - channel->curr = channel->end - written; - return free; - } -} - -CAMLexport void caml_really_putblock(struct channel *channel, - char *p, intnat len) -{ - int written; - while (len > 0) { - written = caml_putblock(channel, p, len); - p += written; - len -= written; - } -} - -CAMLexport void caml_seek_out(struct channel *channel, file_offset dest) -{ - caml_flush(channel); - caml_enter_blocking_section(); - if (lseek(channel->fd, dest, SEEK_SET) != dest) { - caml_leave_blocking_section(); - caml_sys_error(NO_ARG); - } - caml_leave_blocking_section(); - channel->offset = dest; -} - -CAMLexport file_offset caml_pos_out(struct channel *channel) -{ - return channel->offset + (file_offset)(channel->curr - channel->buff); -} - -/* Input */ - -/* caml_do_read is exported for Cash */ -CAMLexport int caml_do_read(int fd, char *p, unsigned int n) -{ - return caml_read_fd(fd, 0, p, n); -} - -CAMLexport unsigned char caml_refill(struct channel *channel) -{ - int n; - - n = caml_read_fd(channel->fd, channel->flags, - channel->buff, channel->end - channel->buff); - if (n == 0) caml_raise_end_of_file(); - channel->offset += n; - channel->max = channel->buff + n; - channel->curr = channel->buff + 1; - return (unsigned char)(channel->buff[0]); -} - -CAMLexport uint32_t caml_getword(struct channel *channel) -{ - int i; - uint32_t res; - - if (! caml_channel_binary_mode(channel)) - caml_failwith("input_binary_int: not a binary channel"); - res = 0; - for(i = 0; i < 4; i++) { - res = (res << 8) + caml_getch(channel); - } - return res; -} - -CAMLexport int caml_getblock(struct channel *channel, char *p, intnat len) -{ - int n, avail, nread; - - n = len >= INT_MAX ? INT_MAX : (int) len; - avail = channel->max - channel->curr; - if (n <= avail) { - memmove(p, channel->curr, n); - channel->curr += n; - return n; - } else if (avail > 0) { - memmove(p, channel->curr, avail); - channel->curr += avail; - return avail; - } else { - nread = caml_read_fd(channel->fd, channel->flags, channel->buff, - channel->end - channel->buff); - channel->offset += nread; - channel->max = channel->buff + nread; - if (n > nread) n = nread; - memmove(p, channel->buff, n); - channel->curr = channel->buff + n; - return n; - } -} - -/* Returns the number of bytes read. */ -CAMLexport intnat caml_really_getblock(struct channel *chan, char *p, intnat n) -{ - intnat k = n; - int r; - while (k > 0) { - r = caml_getblock(chan, p, k); - if (r == 0) break; - p += r; - k -= r; - } - return n - k; -} - -CAMLexport void caml_seek_in(struct channel *channel, file_offset dest) -{ - if (dest >= channel->offset - (channel->max - channel->buff) && - dest <= channel->offset) { - channel->curr = channel->max - (channel->offset - dest); - } else { - caml_enter_blocking_section(); - if (lseek(channel->fd, dest, SEEK_SET) != dest) { - caml_leave_blocking_section(); - caml_sys_error(NO_ARG); - } - caml_leave_blocking_section(); - channel->offset = dest; - channel->curr = channel->max = channel->buff; - } -} - -CAMLexport file_offset caml_pos_in(struct channel *channel) -{ - return channel->offset - (file_offset)(channel->max - channel->curr); -} - -CAMLexport intnat caml_input_scan_line(struct channel *channel) -{ - char * p; - int n; - - p = channel->curr; - do { - if (p >= channel->max) { - /* No more characters available in the buffer */ - if (channel->curr > channel->buff) { - /* Try to make some room in the buffer by shifting the unread - portion at the beginning */ - memmove(channel->buff, channel->curr, channel->max - channel->curr); - n = channel->curr - channel->buff; - channel->curr -= n; - channel->max -= n; - p -= n; - } - if (channel->max >= channel->end) { - /* Buffer is full, no room to read more characters from the input. - Return the number of characters in the buffer, with negative - sign to indicate that no newline was encountered. */ - return -(channel->max - channel->curr); - } - /* Fill the buffer as much as possible */ - n = caml_read_fd(channel->fd, channel->flags, - channel->max, channel->end - channel->max); - if (n == 0) { - /* End-of-file encountered. Return the number of characters in the - buffer, with negative sign since we haven't encountered - a newline. */ - return -(channel->max - channel->curr); - } - channel->offset += n; - channel->max += n; - } - } while (*p++ != '\n'); - /* Found a newline. Return the length of the line, newline included. */ - return (p - channel->curr); -} - -/* OCaml entry points for the I/O functions. Wrap struct channel * - objects into a heap-allocated object. Perform locking - and unlocking around the I/O operations. */ - -/* FIXME CAMLexport, but not in io.h exported for Cash ? */ -CAMLexport void caml_finalize_channel(value vchan) -{ - struct channel * chan = Channel(vchan); - if ((chan->flags & CHANNEL_FLAG_MANAGED_BY_GC) == 0) return; - if (--chan->refcount > 0) return; - if (caml_channel_mutex_free != NULL) (*caml_channel_mutex_free)(chan); - - if (chan->fd != -1 && chan->name && caml_runtime_warnings_active()) - fprintf(stderr, - "[ocaml] channel opened on file '%s' dies without being closed\n", - chan->name - ); - - if (chan->max == NULL && chan->curr != chan->buff){ - /* - This is an unclosed out channel (chan->max == NULL) with a - non-empty buffer: keep it around so the OCaml [at_exit] function - gets a chance to flush it. We would want to simply flush the - channel now, but (i) flushing can raise exceptions, and (ii) it - is potentially a blocking operation. Both are forbidden in a - finalization function. - - Refs: - http://caml.inria.fr/mantis/view.php?id=6902 - https://github.com/ocaml/ocaml/pull/210 - */ - if (chan->name && caml_runtime_warnings_active()) - fprintf(stderr, - "[ocaml] (moreover, it has unflushed data)\n" - ); - } else { - unlink_channel(chan); - caml_stat_free(chan->name); - caml_stat_free(chan); - } -} - -static int compare_channel(value vchan1, value vchan2) -{ - struct channel * chan1 = Channel(vchan1); - struct channel * chan2 = Channel(vchan2); - return (chan1 == chan2) ? 0 : (chan1 < chan2) ? -1 : 1; -} - -static intnat hash_channel(value vchan) -{ - return (intnat) (Channel(vchan)); -} - -static struct custom_operations channel_operations = { - "_chan", - caml_finalize_channel, - compare_channel, - hash_channel, - custom_serialize_default, - custom_deserialize_default, - custom_compare_ext_default -}; - -CAMLexport value caml_alloc_channel(struct channel *chan) -{ - value res; - chan->refcount++; /* prevent finalization during next alloc */ - res = caml_alloc_custom(&channel_operations, sizeof(struct channel *), - 1, 1000); - Channel(res) = chan; - return res; -} - -CAMLprim value caml_ml_open_descriptor_in(value fd) -{ - struct channel * chan = caml_open_descriptor_in(Int_val(fd)); - chan->flags |= CHANNEL_FLAG_MANAGED_BY_GC; - return caml_alloc_channel(chan); -} - -CAMLprim value caml_ml_open_descriptor_out(value fd) -{ - struct channel * chan = caml_open_descriptor_out(Int_val(fd)); - chan->flags |= CHANNEL_FLAG_MANAGED_BY_GC; - return caml_alloc_channel(chan); -} - -CAMLprim value caml_ml_set_channel_name(value vchannel, value vname) -{ - struct channel * channel = Channel(vchannel); - caml_stat_free(channel->name); - if (caml_string_length(vname) > 0) - channel->name = caml_stat_strdup(String_val(vname)); - else - channel->name = NULL; - return Val_unit; -} - -#define Pair_tag 0 - -CAMLprim value caml_ml_out_channels_list (value unit) -{ - CAMLparam0 (); - CAMLlocal3 (res, tail, chan); - struct channel * channel; - - res = Val_emptylist; - for (channel = caml_all_opened_channels; - channel != NULL; - channel = channel->next) - /* Testing channel->fd >= 0 looks unnecessary, as - caml_ml_close_channel changes max when setting fd to -1. */ - if (channel->max == NULL) { - chan = caml_alloc_channel (channel); - tail = res; - res = caml_alloc_small (2, Pair_tag); - Field (res, 0) = chan; - Field (res, 1) = tail; - } - CAMLreturn (res); -} - -CAMLprim value caml_channel_descriptor(value vchannel) -{ - int fd = Channel(vchannel)->fd; - if (fd == -1) { errno = EBADF; caml_sys_error(NO_ARG); } - return Val_int(fd); -} - -CAMLprim value caml_ml_close_channel(value vchannel) -{ - int result; - int do_syscall; - int fd; - - /* For output channels, must have flushed before */ - struct channel * channel = Channel(vchannel); - if (channel->fd != -1){ - fd = channel->fd; - channel->fd = -1; - do_syscall = 1; - }else{ - do_syscall = 0; - result = 0; - } - /* Ensure that every read or write on the channel will cause an - immediate caml_flush_partial or caml_refill, thus raising a Sys_error - exception */ - channel->curr = channel->max = channel->end; - - if (do_syscall) { - caml_enter_blocking_section(); - result = CAML_SYS_CLOSE(fd); - caml_leave_blocking_section(); - } - - if (result == -1) caml_sys_error (NO_ARG); - return Val_unit; -} - -/* EOVERFLOW is the Unix98 error indicating that a file position or file - size is not representable. - ERANGE is the ANSI C error indicating that some argument to some - function is out of range. This is less precise than EOVERFLOW, - but guaranteed to be defined on all ANSI C environments. */ -#ifndef EOVERFLOW -#define EOVERFLOW ERANGE -#endif - -CAMLprim value caml_ml_channel_size(value vchannel) -{ - file_offset size = caml_channel_size(Channel(vchannel)); - if (size > Max_long) { errno = EOVERFLOW; caml_sys_error(NO_ARG); } - return Val_long(size); -} - -CAMLprim value caml_ml_channel_size_64(value vchannel) -{ - return Val_file_offset(caml_channel_size(Channel(vchannel))); -} - -CAMLprim value caml_ml_set_binary_mode(value vchannel, value mode) -{ -#if defined(_WIN32) || defined(__CYGWIN__) - struct channel * channel = Channel(vchannel); -#if defined(_WIN32) - /* The implementation of [caml_read_fd] and [caml_write_fd] in win32.c - doesn't support socket I/O with CRLF conversion. */ - if ((channel->flags & CHANNEL_FLAG_FROM_SOCKET) != 0 - && ! Bool_val(mode)) { - errno = EINVAL; - caml_sys_error(NO_ARG); - } -#endif - if (setmode(channel->fd, Bool_val(mode) ? O_BINARY : O_TEXT) == -1) - caml_sys_error(NO_ARG); -#endif - return Val_unit; -} - -/* - If the channel is closed, DO NOT raise a "bad file descriptor" - exception, but do nothing (the buffer is already empty). - This is because some libraries will flush at exit, even on - file descriptors that may be closed. -*/ - -CAMLprim value caml_ml_flush_partial(value vchannel) -{ - CAMLparam1 (vchannel); - struct channel * channel = Channel(vchannel); - int res; - - if (channel->fd == -1) CAMLreturn(Val_true); - Lock(channel); - res = caml_flush_partial(channel); - Unlock(channel); - CAMLreturn (Val_bool(res)); -} - -CAMLprim value caml_ml_flush(value vchannel) -{ - CAMLparam1 (vchannel); - struct channel * channel = Channel(vchannel); - - if (channel->fd == -1) CAMLreturn(Val_unit); - Lock(channel); - caml_flush(channel); - Unlock(channel); - CAMLreturn (Val_unit); -} - -CAMLprim value caml_ml_output_char(value vchannel, value ch) -{ - CAMLparam2 (vchannel, ch); - struct channel * channel = Channel(vchannel); - - Lock(channel); - caml_putch(channel, Long_val(ch)); - Unlock(channel); - CAMLreturn (Val_unit); -} - -CAMLprim value caml_ml_output_int(value vchannel, value w) -{ - CAMLparam2 (vchannel, w); - struct channel * channel = Channel(vchannel); - - Lock(channel); - caml_putword(channel, Long_val(w)); - Unlock(channel); - CAMLreturn (Val_unit); -} - -CAMLprim value caml_ml_output_partial(value vchannel, value buff, value start, - value length) -{ - CAMLparam4 (vchannel, buff, start, length); - struct channel * channel = Channel(vchannel); - int res; - - Lock(channel); - res = caml_putblock(channel, &Byte(buff, Long_val(start)), Long_val(length)); - Unlock(channel); - CAMLreturn (Val_int(res)); -} - -CAMLprim value caml_ml_output_bytes(value vchannel, value buff, value start, - value length) -{ - CAMLparam4 (vchannel, buff, start, length); - struct channel * channel = Channel(vchannel); - intnat pos = Long_val(start); - intnat len = Long_val(length); - - Lock(channel); - /* We cannot call caml_really_putblock here because buff may move - during caml_write_fd */ - while (len > 0) { - int written = caml_putblock(channel, &Byte(buff, pos), len); - pos += written; - len -= written; - } - Unlock(channel); - CAMLreturn (Val_unit); -} - -CAMLprim value caml_ml_output(value vchannel, value buff, value start, - value length) -{ - return caml_ml_output_bytes (vchannel, buff, start, length); -} - -CAMLprim value caml_ml_seek_out(value vchannel, value pos) -{ - CAMLparam2 (vchannel, pos); - struct channel * channel = Channel(vchannel); - - Lock(channel); - caml_seek_out(channel, Long_val(pos)); - Unlock(channel); - CAMLreturn (Val_unit); -} - -CAMLprim value caml_ml_seek_out_64(value vchannel, value pos) -{ - CAMLparam2 (vchannel, pos); - struct channel * channel = Channel(vchannel); - - Lock(channel); - caml_seek_out(channel, File_offset_val(pos)); - Unlock(channel); - CAMLreturn (Val_unit); -} - -CAMLprim value caml_ml_pos_out(value vchannel) -{ - file_offset pos = caml_pos_out(Channel(vchannel)); - if (pos > Max_long) { errno = EOVERFLOW; caml_sys_error(NO_ARG); } - return Val_long(pos); -} - -CAMLprim value caml_ml_pos_out_64(value vchannel) -{ - return Val_file_offset(caml_pos_out(Channel(vchannel))); -} - -CAMLprim value caml_ml_input_char(value vchannel) -{ - CAMLparam1 (vchannel); - struct channel * channel = Channel(vchannel); - unsigned char c; - - Lock(channel); - c = caml_getch(channel); - Unlock(channel); - CAMLreturn (Val_long(c)); -} - -CAMLprim value caml_ml_input_int(value vchannel) -{ - CAMLparam1 (vchannel); - struct channel * channel = Channel(vchannel); - intnat i; - - Lock(channel); - i = caml_getword(channel); - Unlock(channel); -#ifdef ARCH_SIXTYFOUR - i = (i << 32) >> 32; /* Force sign extension */ -#endif - CAMLreturn (Val_long(i)); -} - -CAMLprim value caml_ml_input(value vchannel, value buff, value vstart, - value vlength) -{ - CAMLparam4 (vchannel, buff, vstart, vlength); - struct channel * channel = Channel(vchannel); - intnat start, len; - int n, avail, nread; - - Lock(channel); - /* We cannot call caml_getblock here because buff may move during - caml_read_fd */ - start = Long_val(vstart); - len = Long_val(vlength); - n = len >= INT_MAX ? INT_MAX : (int) len; - avail = channel->max - channel->curr; - if (n <= avail) { - memmove(&Byte(buff, start), channel->curr, n); - channel->curr += n; - } else if (avail > 0) { - memmove(&Byte(buff, start), channel->curr, avail); - channel->curr += avail; - n = avail; - } else { - nread = caml_read_fd(channel->fd, channel->flags, channel->buff, - channel->end - channel->buff); - channel->offset += nread; - channel->max = channel->buff + nread; - if (n > nread) n = nread; - memmove(&Byte(buff, start), channel->buff, n); - channel->curr = channel->buff + n; - } - Unlock(channel); - CAMLreturn (Val_long(n)); -} - -CAMLprim value caml_ml_seek_in(value vchannel, value pos) -{ - CAMLparam2 (vchannel, pos); - struct channel * channel = Channel(vchannel); - - Lock(channel); - caml_seek_in(channel, Long_val(pos)); - Unlock(channel); - CAMLreturn (Val_unit); -} - -CAMLprim value caml_ml_seek_in_64(value vchannel, value pos) -{ - CAMLparam2 (vchannel, pos); - struct channel * channel = Channel(vchannel); - - Lock(channel); - caml_seek_in(channel, File_offset_val(pos)); - Unlock(channel); - CAMLreturn (Val_unit); -} - -CAMLprim value caml_ml_pos_in(value vchannel) -{ - file_offset pos = caml_pos_in(Channel(vchannel)); - if (pos > Max_long) { errno = EOVERFLOW; caml_sys_error(NO_ARG); } - return Val_long(pos); -} - -CAMLprim value caml_ml_pos_in_64(value vchannel) -{ - return Val_file_offset(caml_pos_in(Channel(vchannel))); -} - -CAMLprim value caml_ml_input_scan_line(value vchannel) -{ - CAMLparam1 (vchannel); - struct channel * channel = Channel(vchannel); - intnat res; - - Lock(channel); - res = caml_input_scan_line(channel); - Unlock(channel); - CAMLreturn (Val_long(res)); -} - -CAMLprim value caml_terminfo_rows(value vchannel) -{ - return Val_int(caml_num_rows_fd(Channel(vchannel)->fd)); -} diff --git a/byterun/major_gc.c b/byterun/major_gc.c deleted file mode 100644 index bfac0e44..00000000 --- a/byterun/major_gc.c +++ /dev/null @@ -1,936 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -#include -#include - -#include "caml/compact.h" -#include "caml/custom.h" -#include "caml/config.h" -#include "caml/fail.h" -#include "caml/finalise.h" -#include "caml/freelist.h" -#include "caml/gc.h" -#include "caml/gc_ctrl.h" -#include "caml/major_gc.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/roots.h" -#include "caml/signals.h" -#include "caml/weak.h" - -#if defined (NATIVE_CODE) && defined (NO_NAKED_POINTERS) -#define NATIVE_CODE_AND_NO_NAKED_POINTERS -#else -#undef NATIVE_CODE_AND_NO_NAKED_POINTERS -#endif - -#ifdef _MSC_VER -static inline double fmin(double a, double b) { - return (a < b) ? a : b; -} -#endif - -uintnat caml_percent_free; -uintnat caml_major_heap_increment; -CAMLexport char *caml_heap_start; -char *caml_gc_sweep_hp; -int caml_gc_phase; /* always Phase_mark, Pase_clean, - Phase_sweep, or Phase_idle */ -static value *gray_vals; -static value *gray_vals_cur, *gray_vals_end; -static asize_t gray_vals_size; -static int heap_is_pure; /* The heap is pure if the only gray objects - below [markhp] are also in [gray_vals]. */ -uintnat caml_allocated_words; -uintnat caml_dependent_size, caml_dependent_allocated; -double caml_extra_heap_resources; -uintnat caml_fl_wsz_at_phase_change = 0; - -extern char *caml_fl_merge; /* Defined in freelist.c. */ - -static char *markhp, *chunk, *limit; - -int caml_gc_subphase; /* Subphase_{mark_roots,mark_main,mark_final} */ - -/** - Ephemerons: - During mark phase the list caml_ephe_list_head of ephemerons - is iterated by different pointers that follow the invariants: - caml_ephe_list_head ->* ephes_checked_if_pure ->* ephes_to_check ->* null - | | | - (1) (2) (3) - - At the start of mark phase, (1) and (2) are empty. - - In mark phase: - - the ephemerons in (1) have a data alive or none - (nb: new ephemerons are added in this part by weak.c) - - the ephemerons in (2) have at least a white key or are white - if ephe_list_pure is true, otherwise they are in an unknown state and - must be checked again. - - the ephemerons in (3) are in an unknown state and must be checked - - At the end of mark phase, (3) is empty and ephe_list_pure is true. - The ephemeron in (1) and (2) will be cleaned (white keys and datas - replaced by none or the ephemeron is removed from the list if it is white) - in clean phase. - - In clean phase: - caml_ephe_list_head ->* ephes_to_check ->* null - | | - (1) (3) - - In clean phase, (2) is not used, ephes_to_check is initialized at - caml_ephe_list_head: - - the ephemerons in (1) are clean. - - the ephemerons in (3) should be cleaned or removed if white. - - */ -static int ephe_list_pure; -/** The ephemerons is pure if since the start of its iteration - no value have been darken. */ -static value *ephes_checked_if_pure; -static value *ephes_to_check; - -int caml_major_window = 1; -double caml_major_ring[Max_major_window] = { 0. }; -int caml_major_ring_index = 0; -double caml_major_work_credit = 0.0; -double caml_gc_clock = 0.0; - -#ifdef DEBUG -static unsigned long major_gc_counter = 0; -#endif - -void (*caml_major_gc_hook)(void) = NULL; - -static void realloc_gray_vals (void) -{ - value *new; - - CAMLassert (gray_vals_cur == gray_vals_end); - if (gray_vals_size < caml_stat_heap_wsz / 32){ - caml_gc_message (0x08, "Growing gray_vals to %" - ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n", - (intnat) gray_vals_size * sizeof (value) / 512); - new = (value *) caml_stat_resize_noexc ((char *) gray_vals, - 2 * gray_vals_size * - sizeof (value)); - if (new == NULL){ - caml_gc_message (0x08, "No room for growing gray_vals\n"); - gray_vals_cur = gray_vals; - heap_is_pure = 0; - }else{ - gray_vals = new; - gray_vals_cur = gray_vals + gray_vals_size; - gray_vals_size *= 2; - gray_vals_end = gray_vals + gray_vals_size; - } - }else{ - gray_vals_cur = gray_vals + gray_vals_size / 2; - heap_is_pure = 0; - } -} - -void caml_darken (value v, value *p /* not used */) -{ -#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS - if (Is_block (v) && !Is_young (v) && Wosize_val (v) > 0) { -#else - if (Is_block (v) && Is_in_heap (v)) { -#endif - header_t h = Hd_val (v); - tag_t t = Tag_hd (h); - if (t == Infix_tag){ - v -= Infix_offset_val(v); - h = Hd_val (v); - t = Tag_hd (h); - } -#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS - /* We insist that naked pointers to outside the heap point to things that - look like values with headers coloured black. This isn't always - strictly necessary but is essential in certain cases---in particular - when the value is allocated in a read-only section. (For the values - where it would be safe it is a performance improvement since we avoid - putting them on the grey list.) */ - CAMLassert (Is_in_heap (v) || Is_black_hd (h)); -#endif - CAMLassert (!Is_blue_hd (h)); - if (Is_white_hd (h)){ - ephe_list_pure = 0; - if (t < No_scan_tag){ - Hd_val (v) = Grayhd_hd (h); - *gray_vals_cur++ = v; - if (gray_vals_cur >= gray_vals_end) realloc_gray_vals (); - }else{ - Hd_val (v) = Blackhd_hd (h); - } - } - } -} - -static void start_cycle (void) -{ - CAMLassert (caml_gc_phase == Phase_idle); - CAMLassert (gray_vals_cur == gray_vals); - caml_gc_message (0x01, "Starting new major GC cycle\n"); - caml_darken_all_roots_start (); - caml_gc_phase = Phase_mark; - caml_gc_subphase = Subphase_mark_roots; - markhp = NULL; - ephe_list_pure = 1; - ephes_checked_if_pure = &caml_ephe_list_head; - ephes_to_check = &caml_ephe_list_head; -#ifdef DEBUG - ++ major_gc_counter; - caml_heap_check (); -#endif -} - -/* We may stop the slice inside values, in order to avoid large latencies - on large arrays. In this case, [current_value] is the partially-marked - value and [current_index] is the index of the next field to be marked. -*/ -static value current_value = 0; -static mlsize_t current_index = 0; - -/* For instrumentation */ -#ifdef CAML_INSTR -#define INSTR(x) x -#else -#define INSTR(x) /**/ -#endif - -static void init_sweep_phase(void) -{ - /* Phase_clean is done. */ - /* Initialise the sweep phase. */ - caml_gc_sweep_hp = caml_heap_start; - caml_fl_init_merge (); - caml_gc_phase = Phase_sweep; - chunk = caml_heap_start; - caml_gc_sweep_hp = chunk; - limit = chunk + Chunk_size (chunk); - caml_fl_wsz_at_phase_change = caml_fl_cur_wsz; - if (caml_major_gc_hook) (*caml_major_gc_hook)(); -} - -/* auxillary function of mark_slice */ -static inline value* mark_slice_darken(value *gray_vals_ptr, value v, int i, - int in_ephemeron, int *slice_pointers) -{ - value child; - header_t chd; - - child = Field (v, i); - -#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS - if (Is_block (child) - && ! Is_young (child) - && Wosize_val (child) > 0 /* Atoms never need to be marked. */ - /* Closure blocks contain code pointers at offsets that cannot - be reliably determined, so we always use the page table when - marking such values. */ - && (!(Tag_val (v) == Closure_tag || Tag_val (v) == Infix_tag) || - Is_in_heap (child))) { -#else - if (Is_block (child) && Is_in_heap (child)) { -#endif - INSTR (++ *slice_pointers;) - chd = Hd_val (child); - if (Tag_hd (chd) == Forward_tag){ - value f = Forward_val (child); - if ((in_ephemeron && Is_long(f)) || - (Is_block (f) - && (!Is_in_value_area(f) || Tag_val (f) == Forward_tag - || Tag_val (f) == Lazy_tag -#ifdef FLAT_FLOAT_ARRAY - || Tag_val (f) == Double_tag -#endif - ))){ - /* Do not short-circuit the pointer. */ - }else{ - /* The variable child is not changed because it must be mark alive */ - Field (v, i) = f; - if (Is_block (f) && Is_young (f) && !Is_young (child)){ - if(in_ephemeron){ - add_to_ephe_ref_table (&caml_ephe_ref_table, v, i); - }else{ - add_to_ref_table (&caml_ref_table, &Field (v, i)); - } - } - } - } - else if (Tag_hd(chd) == Infix_tag) { - child -= Infix_offset_val(child); - chd = Hd_val(child); - } -#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS - /* See [caml_darken] for a description of this assertion. */ - CAMLassert (Is_in_heap (child) || Is_black_hd (chd)); -#endif - if (Is_white_hd (chd)){ - ephe_list_pure = 0; - Hd_val (child) = Grayhd_hd (chd); - *gray_vals_ptr++ = child; - if (gray_vals_ptr >= gray_vals_end) { - gray_vals_cur = gray_vals_ptr; - realloc_gray_vals (); - gray_vals_ptr = gray_vals_cur; - } - } - } - - return gray_vals_ptr; -} - -static value* mark_ephe_aux (value *gray_vals_ptr, intnat *work, - int *slice_pointers) -{ - value v, data, key; - header_t hd; - mlsize_t size, i; - - v = *ephes_to_check; - hd = Hd_val(v); - CAMLassert(Tag_val (v) == Abstract_tag); - data = Field(v,CAML_EPHE_DATA_OFFSET); - if ( data != caml_ephe_none && - Is_block (data) && Is_in_heap (data) && Is_white_val (data)){ - - int alive_data = 1; - - /* The liveness of the ephemeron is one of the condition */ - if (Is_white_hd (hd)) alive_data = 0; - - /* The liveness of the keys not caml_ephe_none is the other condition */ - size = Wosize_hd (hd); - for (i = CAML_EPHE_FIRST_KEY; alive_data && i < size; i++){ - key = Field (v, i); - ephemeron_again: - if (key != caml_ephe_none && - Is_block (key) && Is_in_heap (key)){ - if (Tag_val (key) == Forward_tag){ - value f = Forward_val (key); - if (Is_long (f) || - (Is_block (f) && - (!Is_in_value_area(f) || Tag_val (f) == Forward_tag - || Tag_val (f) == Lazy_tag -#ifdef FLAT_FLOAT_ARRAY - || Tag_val (f) == Double_tag -#endif - ))){ - /* Do not short-circuit the pointer. */ - }else{ - Field (v, i) = key = f; - goto ephemeron_again; - } - } - if (Is_white_val (key)){ - alive_data = 0; - } - } - } - *work -= Whsize_wosize(i); - - if (alive_data){ - gray_vals_ptr = mark_slice_darken(gray_vals_ptr,v, - CAML_EPHE_DATA_OFFSET, - /*in_ephemeron=*/1, - slice_pointers); - } else { /* not triggered move to the next one */ - ephes_to_check = &Field(v,CAML_EPHE_LINK_OFFSET); - return gray_vals_ptr; - } - } else { /* a simily weak pointer or an already alive data */ - *work -= 1; - } - - /* all keys black or data none or black - move the ephemerons from (3) to the end of (1) */ - if ( ephes_checked_if_pure == ephes_to_check ) { - /* corner case and optim */ - ephes_checked_if_pure = &Field(v,CAML_EPHE_LINK_OFFSET); - ephes_to_check = ephes_checked_if_pure; - } else { - /* - remove v from the list (3) */ - *ephes_to_check = Field(v,CAML_EPHE_LINK_OFFSET); - /* - insert it at the end of (1) */ - Field(v,CAML_EPHE_LINK_OFFSET) = *ephes_checked_if_pure; - *ephes_checked_if_pure = v; - ephes_checked_if_pure = &Field(v,CAML_EPHE_LINK_OFFSET); - } - return gray_vals_ptr; -} - - - -static void mark_slice (intnat work) -{ - value *gray_vals_ptr; /* Local copy of [gray_vals_cur] */ - value v; - header_t hd; - mlsize_t size, i, start, end; /* [start] is a local copy of [current_index] */ -#ifdef CAML_INSTR - int slice_fields = 0; -#endif - int slice_pointers = 0; /** gcc removes it when not in CAML_INSTR */ - - caml_gc_message (0x40, "Marking %"ARCH_INTNAT_PRINTF_FORMAT"d words\n", work); - caml_gc_message (0x40, "Subphase = %d\n", caml_gc_subphase); - gray_vals_ptr = gray_vals_cur; - v = current_value; - start = current_index; - while (work > 0){ - if (v == 0 && gray_vals_ptr > gray_vals){ - CAMLassert (start == 0); - v = *--gray_vals_ptr; - CAMLassert (Is_gray_val (v)); - } - if (v != 0){ - hd = Hd_val(v); - CAMLassert (Is_gray_hd (hd)); - size = Wosize_hd (hd); - end = start + work; - if (Tag_hd (hd) < No_scan_tag){ - start = size < start ? size : start; - end = size < end ? size : end; - CAMLassert (end >= start); - INSTR (slice_fields += end - start;) - INSTR (if (size > end) - CAML_INSTR_INT ("major/mark/slice/remain", size - end);) - for (i = start; i < end; i++){ - gray_vals_ptr = mark_slice_darken(gray_vals_ptr,v,i, - /*in_ephemeron=*/ 0, - &slice_pointers); - } - if (end < size){ - work = 0; - start = end; - /* [v] doesn't change. */ - CAMLassert (Is_gray_val (v)); - }else{ - CAMLassert (end == size); - Hd_val (v) = Blackhd_hd (hd); - work -= Whsize_wosize(end - start); - start = 0; - v = 0; - } - }else{ - /* The block doesn't contain any pointers. */ - CAMLassert (start == 0); - Hd_val (v) = Blackhd_hd (hd); - work -= Whsize_wosize(size); - v = 0; - } - }else if (markhp != NULL){ - if (markhp == limit){ - chunk = Chunk_next (chunk); - if (chunk == NULL){ - markhp = NULL; - }else{ - markhp = chunk; - limit = chunk + Chunk_size (chunk); - } - }else{ - if (Is_gray_val (Val_hp (markhp))){ - CAMLassert (gray_vals_ptr == gray_vals); - CAMLassert (v == 0 && start == 0); - v = Val_hp (markhp); - } - markhp += Bhsize_hp (markhp); - } - }else if (!heap_is_pure){ - heap_is_pure = 1; - chunk = caml_heap_start; - markhp = chunk; - limit = chunk + Chunk_size (chunk); - } else if (caml_gc_subphase == Subphase_mark_roots) { - gray_vals_cur = gray_vals_ptr; - work = caml_darken_all_roots_slice (work); - gray_vals_ptr = gray_vals_cur; - if (work > 0){ - caml_gc_subphase = Subphase_mark_main; - } - } else if (*ephes_to_check != (value) NULL) { - /* Continue to scan the list of ephe */ - gray_vals_ptr = mark_ephe_aux(gray_vals_ptr,&work,&slice_pointers); - } else if (!ephe_list_pure){ - /* We must scan again the list because some value have been darken */ - ephe_list_pure = 1; - ephes_to_check = ephes_checked_if_pure; - }else{ - switch (caml_gc_subphase){ - case Subphase_mark_main: { - /* Subphase_mark_main is done. - Mark finalised values. */ - gray_vals_cur = gray_vals_ptr; - caml_final_update_mark_phase (); - gray_vals_ptr = gray_vals_cur; - if (gray_vals_ptr > gray_vals){ - v = *--gray_vals_ptr; - CAMLassert (start == 0); - } - /* Complete the marking */ - ephes_to_check = ephes_checked_if_pure; - caml_gc_subphase = Subphase_mark_final; - } - break; - case Subphase_mark_final: { - /** The set of unreachable value will not change anymore for - this cycle. Start clean phase. */ - caml_gc_phase = Phase_clean; - caml_final_update_clean_phase (); - if (caml_ephe_list_head != (value) NULL){ - /* Initialise the clean phase. */ - ephes_to_check = &caml_ephe_list_head; - } else { - /* Initialise the sweep phase. */ - init_sweep_phase(); - } - work = 0; - } - break; - default: CAMLassert (0); - } - } - } - gray_vals_cur = gray_vals_ptr; - current_value = v; - current_index = start; - INSTR (CAML_INSTR_INT ("major/mark/slice/fields#", slice_fields);) - INSTR (CAML_INSTR_INT ("major/mark/slice/pointers#", slice_pointers);) -} - -/* Clean ephemerons */ -static void clean_slice (intnat work) -{ - value v; - - caml_gc_message (0x40, "Cleaning %" - ARCH_INTNAT_PRINTF_FORMAT "d words\n", work); - while (work > 0){ - v = *ephes_to_check; - if (v != (value) NULL){ - if (Is_white_val (v)){ - /* The whole array is dead, remove it from the list. */ - *ephes_to_check = Field (v, CAML_EPHE_LINK_OFFSET); - work -= 1; - }else{ - caml_ephe_clean(v); - ephes_to_check = &Field (v, CAML_EPHE_LINK_OFFSET); - work -= Whsize_val (v); - } - }else{ /* End of list reached */ - /* Phase_clean is done. */ - /* Initialise the sweep phase. */ - init_sweep_phase(); - work = 0; - } - } -} - -static void sweep_slice (intnat work) -{ - char *hp; - header_t hd; - - caml_gc_message (0x40, "Sweeping %" - ARCH_INTNAT_PRINTF_FORMAT "d words\n", work); - while (work > 0){ - if (caml_gc_sweep_hp < limit){ - hp = caml_gc_sweep_hp; - hd = Hd_hp (hp); - work -= Whsize_hd (hd); - caml_gc_sweep_hp += Bhsize_hd (hd); - switch (Color_hd (hd)){ - case Caml_white: - if (Tag_hd (hd) == Custom_tag){ - void (*final_fun)(value) = Custom_ops_val(Val_hp(hp))->finalize; - if (final_fun != NULL) final_fun(Val_hp(hp)); - } - caml_gc_sweep_hp = (char *) caml_fl_merge_block (Val_hp (hp)); - break; - case Caml_blue: - /* Only the blocks of the free-list are blue. See [freelist.c]. */ - caml_fl_merge = Bp_hp (hp); - break; - default: /* gray or black */ - CAMLassert (Color_hd (hd) == Caml_black); - Hd_hp (hp) = Whitehd_hd (hd); - break; - } - CAMLassert (caml_gc_sweep_hp <= limit); - }else{ - chunk = Chunk_next (chunk); - if (chunk == NULL){ - /* Sweeping is done. */ - ++ caml_stat_major_collections; - work = 0; - caml_gc_phase = Phase_idle; - caml_request_minor_gc (); - }else{ - caml_gc_sweep_hp = chunk; - limit = chunk + Chunk_size (chunk); - } - } - } -} - -#ifdef CAML_INSTR -static char *mark_slice_name[] = { - /* 0 */ NULL, - /* 1 */ NULL, - /* 2 */ NULL, - /* 3 */ NULL, - /* 4 */ NULL, - /* 5 */ NULL, - /* 6 */ NULL, - /* 7 */ NULL, - /* 8 */ NULL, - /* 9 */ NULL, - /* 10 */ "major/mark_roots", - /* 11 */ "major/mark_main", - /* 12 */ "major/mark_weak1", - /* 13 */ "major/mark_weak2", - /* 14 */ "major/mark_final", -}; -#endif - -/* The main entry point for the major GC. Called about once for each - minor GC. [howmuch] is the amount of work to do: - -1 if the GC is triggered automatically - 0 to let the GC compute the amount of work - [n] to make the GC do enough work to (on average) free [n] words - */ -void caml_major_collection_slice (intnat howmuch) -{ - double p, dp, filt_p, spend; - intnat computed_work; - int i; - /* - Free memory at the start of the GC cycle (garbage + free list) (assumed): - FM = caml_stat_heap_wsz * caml_percent_free - / (100 + caml_percent_free) - - Assuming steady state and enforcing a constant allocation rate, then - FM is divided in 2/3 for garbage and 1/3 for free list. - G = 2 * FM / 3 - G is also the amount of memory that will be used during this cycle - (still assuming steady state). - - Proportion of G consumed since the previous slice: - PH = caml_allocated_words / G - = caml_allocated_words * 3 * (100 + caml_percent_free) - / (2 * caml_stat_heap_wsz * caml_percent_free) - Proportion of extra-heap resources consumed since the previous slice: - PE = caml_extra_heap_resources - Proportion of total work to do in this slice: - P = max (PH, PE) - - Here, we insert a time-based filter on the P variable to avoid large - latency spikes in the GC, so the P below is a smoothed-out version of - the P above. - - Amount of marking work for the GC cycle: - MW = caml_stat_heap_wsz * 100 / (100 + caml_percent_free) - + caml_incremental_roots_count - Amount of sweeping work for the GC cycle: - SW = caml_stat_heap_wsz - - In order to finish marking with a non-empty free list, we will - use 40% of the time for marking, and 60% for sweeping. - - Let MT be the time spent marking, ST the time spent sweeping, and TT - the total time for this cycle. We have: - MT = 40/100 * TT - ST = 60/100 * TT - - Amount of time to spend on this slice: - T = P * TT = P * MT / (40/100) = P * ST / (60/100) - - Since we must do MW work in MT time or SW work in ST time, the amount - of work for this slice is: - MS = P * MW / (40/100) if marking - SS = P * SW / (60/100) if sweeping - - Amount of marking work for a marking slice: - MS = P * MW / (40/100) - MS = P * (caml_stat_heap_wsz * 250 / (100 + caml_percent_free) - + 2.5 * caml_incremental_roots_count) - Amount of sweeping work for a sweeping slice: - SS = P * SW / (60/100) - SS = P * caml_stat_heap_wsz * 5 / 3 - - This slice will either mark MS words or sweep SS words. - */ - - if (caml_major_slice_begin_hook != NULL) (*caml_major_slice_begin_hook) (); - CAML_INSTR_SETUP (tmr, "major"); - - p = (double) caml_allocated_words * 3.0 * (100 + caml_percent_free) - / caml_stat_heap_wsz / caml_percent_free / 2.0; - if (caml_dependent_size > 0){ - dp = (double) caml_dependent_allocated * (100 + caml_percent_free) - / caml_dependent_size / caml_percent_free; - }else{ - dp = 0.0; - } - if (p < dp) p = dp; - if (p < caml_extra_heap_resources) p = caml_extra_heap_resources; - if (p > 0.3) p = 0.3; - CAML_INSTR_INT ("major/work/extra#", - (uintnat) (caml_extra_heap_resources * 1000000)); - - caml_gc_message (0x40, "ordered work = %" - ARCH_INTNAT_PRINTF_FORMAT "d words\n", howmuch); - caml_gc_message (0x40, "allocated_words = %" - ARCH_INTNAT_PRINTF_FORMAT "u\n", - caml_allocated_words); - caml_gc_message (0x40, "extra_heap_resources = %" - ARCH_INTNAT_PRINTF_FORMAT "uu\n", - (uintnat) (caml_extra_heap_resources * 1000000)); - caml_gc_message (0x40, "raw work-to-do = %" - ARCH_INTNAT_PRINTF_FORMAT "du\n", - (intnat) (p * 1000000)); - - for (i = 0; i < caml_major_window; i++){ - caml_major_ring[i] += p / caml_major_window; - } - - if (caml_gc_clock >= 1.0){ - caml_gc_clock -= 1.0; - ++caml_major_ring_index; - if (caml_major_ring_index >= caml_major_window){ - caml_major_ring_index = 0; - } - } - if (howmuch == -1){ - /* auto-triggered GC slice: spend work credit on the current bucket, - then do the remaining work, if any */ - /* Note that the minor GC guarantees that the major slice is called in - automatic mode (with [howmuch] = -1) at least once per clock tick. - This means we never leave a non-empty bucket behind. */ - spend = fmin (caml_major_work_credit, - caml_major_ring[caml_major_ring_index]); - caml_major_work_credit -= spend; - filt_p = caml_major_ring[caml_major_ring_index] - spend; - caml_major_ring[caml_major_ring_index] = 0.0; - }else{ - /* forced GC slice: do work and add it to the credit */ - if (howmuch == 0){ - /* automatic setting: size of next bucket - we do not use the current bucket, as it may be empty */ - int i = caml_major_ring_index + 1; - if (i >= caml_major_window) i = 0; - filt_p = caml_major_ring[i]; - }else{ - /* manual setting */ - filt_p = (double) howmuch * 3.0 * (100 + caml_percent_free) - / caml_stat_heap_wsz / caml_percent_free / 2.0; - } - caml_major_work_credit += filt_p; - } - - p = filt_p; - - caml_gc_message (0x40, "filtered work-to-do = %" - ARCH_INTNAT_PRINTF_FORMAT "du\n", - (intnat) (p * 1000000)); - - if (caml_gc_phase == Phase_idle){ - if (caml_young_ptr == caml_young_alloc_end){ - /* We can only start a major GC cycle if the minor allocation arena - is empty, otherwise we'd have to treat it as a set of roots. */ - start_cycle (); - CAML_INSTR_TIME (tmr, "major/roots"); - } - p = 0; - goto finished; - } - - if (p < 0){ - p = 0; - goto finished; - } - - if (caml_gc_phase == Phase_mark || caml_gc_phase == Phase_clean){ - computed_work = (intnat) (p * ((double) caml_stat_heap_wsz * 250 - / (100 + caml_percent_free) - + caml_incremental_roots_count)); - }else{ - computed_work = (intnat) (p * caml_stat_heap_wsz * 5 / 3); - } - caml_gc_message (0x40, "computed work = %" - ARCH_INTNAT_PRINTF_FORMAT "d words\n", computed_work); - if (caml_gc_phase == Phase_mark){ - CAML_INSTR_INT ("major/work/mark#", computed_work); - mark_slice (computed_work); - CAML_INSTR_TIME (tmr, mark_slice_name[caml_gc_subphase]); - caml_gc_message (0x02, "!"); - }else if (caml_gc_phase == Phase_clean){ - clean_slice (computed_work); - caml_gc_message (0x02, "%%"); - }else{ - CAMLassert (caml_gc_phase == Phase_sweep); - CAML_INSTR_INT ("major/work/sweep#", computed_work); - sweep_slice (computed_work); - CAML_INSTR_TIME (tmr, "major/sweep"); - caml_gc_message (0x02, "$"); - } - - if (caml_gc_phase == Phase_idle){ - caml_compact_heap_maybe (); - CAML_INSTR_TIME (tmr, "major/check_and_compact"); - } - - finished: - caml_gc_message (0x40, "work-done = %" - ARCH_INTNAT_PRINTF_FORMAT "du\n", - (intnat) (p * 1000000)); - - /* if some of the work was not done, take it back from the credit - or spread it over the buckets. */ - p = filt_p - p; - spend = fmin (p, caml_major_work_credit); - caml_major_work_credit -= spend; - if (p > spend){ - p -= spend; - p /= caml_major_window; - for (i = 0; i < caml_major_window; i++) caml_major_ring[i] += p; - } - - caml_stat_major_words += caml_allocated_words; - caml_allocated_words = 0; - caml_dependent_allocated = 0; - caml_extra_heap_resources = 0.0; - if (caml_major_slice_end_hook != NULL) (*caml_major_slice_end_hook) (); -} - -/* This does not call [caml_compact_heap_maybe] because the estimates of - free and live memory are only valid for a cycle done incrementally. - Besides, this function itself is called by [caml_compact_heap_maybe]. -*/ -void caml_finish_major_cycle (void) -{ - if (caml_gc_phase == Phase_idle) start_cycle (); - while (caml_gc_phase == Phase_mark) mark_slice (LONG_MAX); - while (caml_gc_phase == Phase_clean) clean_slice (LONG_MAX); - CAMLassert (caml_gc_phase == Phase_sweep); - while (caml_gc_phase == Phase_sweep) sweep_slice (LONG_MAX); - CAMLassert (caml_gc_phase == Phase_idle); - caml_stat_major_words += caml_allocated_words; - caml_allocated_words = 0; -} - -/* Call this function to make sure [bsz] is greater than or equal - to both [Heap_chunk_min] and the current heap increment. -*/ -asize_t caml_clip_heap_chunk_wsz (asize_t wsz) -{ - asize_t result = wsz; - uintnat incr; - - /* Compute the heap increment as a word size. */ - if (caml_major_heap_increment > 1000){ - incr = caml_major_heap_increment; - }else{ - incr = caml_stat_heap_wsz / 100 * caml_major_heap_increment; - } - - if (result < incr){ - result = incr; - } - if (result < Heap_chunk_min){ - result = Heap_chunk_min; - } - return result; -} - -/* [heap_size] is a number of bytes */ -void caml_init_major_heap (asize_t heap_size) -{ - int i; - - caml_stat_heap_wsz = caml_clip_heap_chunk_wsz (Wsize_bsize (heap_size)); - caml_stat_top_heap_wsz = caml_stat_heap_wsz; - CAMLassert (Bsize_wsize (caml_stat_heap_wsz) % Page_size == 0); - caml_heap_start = - (char *) caml_alloc_for_heap (Bsize_wsize (caml_stat_heap_wsz)); - if (caml_heap_start == NULL) - caml_fatal_error ("Fatal error: cannot allocate initial major heap.\n"); - Chunk_next (caml_heap_start) = NULL; - caml_stat_heap_wsz = Wsize_bsize (Chunk_size (caml_heap_start)); - caml_stat_heap_chunks = 1; - caml_stat_top_heap_wsz = caml_stat_heap_wsz; - - if (caml_page_table_add(In_heap, caml_heap_start, - caml_heap_start + Bsize_wsize (caml_stat_heap_wsz)) - != 0) { - caml_fatal_error ("Fatal error: cannot allocate " - "initial page table.\n"); - } - - caml_fl_init_merge (); - caml_make_free_blocks ((value *) caml_heap_start, - caml_stat_heap_wsz, 1, Caml_white); - caml_gc_phase = Phase_idle; - gray_vals_size = 2048; - gray_vals = (value *) caml_stat_alloc_noexc (gray_vals_size * sizeof (value)); - if (gray_vals == NULL) - caml_fatal_error ("Fatal error: not enough memory for the gray cache.\n"); - gray_vals_cur = gray_vals; - gray_vals_end = gray_vals + gray_vals_size; - heap_is_pure = 1; - caml_allocated_words = 0; - caml_extra_heap_resources = 0.0; - for (i = 0; i < Max_major_window; i++) caml_major_ring[i] = 0.0; -} - -void caml_set_major_window (int w){ - uintnat total = 0; - int i; - if (w == caml_major_window) return; - CAMLassert (w <= Max_major_window); - /* Collect the current work-to-do from the buckets. */ - for (i = 0; i < caml_major_window; i++){ - total += caml_major_ring[i]; - } - /* Redistribute to the new buckets. */ - for (i = 0; i < w; i++){ - caml_major_ring[i] = total / w; - } - caml_major_window = w; -} - -void caml_finalise_heap (void) -{ - /* Finishing major cycle (all values become white) */ - caml_empty_minor_heap (); - caml_finish_major_cycle (); - CAMLassert (caml_gc_phase == Phase_idle); - - /* Finalising all values (by means of forced sweeping) */ - caml_fl_init_merge (); - caml_gc_phase = Phase_sweep; - chunk = caml_heap_start; - caml_gc_sweep_hp = chunk; - limit = chunk + Chunk_size (chunk); - while (caml_gc_phase == Phase_sweep) - sweep_slice (LONG_MAX); -} diff --git a/byterun/memory.c b/byterun/memory.c deleted file mode 100644 index f92b23c4..00000000 --- a/byterun/memory.c +++ /dev/null @@ -1,1016 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -#include -#include -#include -#include -#include "caml/address_class.h" -#include "caml/config.h" -#include "caml/fail.h" -#include "caml/freelist.h" -#include "caml/gc.h" -#include "caml/gc_ctrl.h" -#include "caml/major_gc.h" -#include "caml/memory.h" -#include "caml/major_gc.h" -#include "caml/minor_gc.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/signals.h" - -int caml_huge_fallback_count = 0; -/* Number of times that mmapping big pages fails and we fell back to small - pages. This counter is available to the program through - [Gc.huge_fallback_count]. -*/ - -uintnat caml_use_huge_pages = 0; -/* True iff the program allocates heap chunks by mmapping huge pages. - This is set when parsing [OCAMLRUNPARAM] and must stay constant - after that. -*/ - -extern uintnat caml_percent_free; /* major_gc.c */ - -/* Page table management */ - -#define Page(p) ((uintnat) (p) >> Page_log) -#define Page_mask ((uintnat) -1 << Page_log) - -#ifdef ARCH_SIXTYFOUR - -/* 64-bit implementation: - The page table is represented sparsely as a hash table - with linear probing */ - -struct page_table { - mlsize_t size; /* size == 1 << (wordsize - shift) */ - int shift; - mlsize_t mask; /* mask == size - 1 */ - mlsize_t occupancy; - uintnat * entries; /* [size] */ -}; - -static struct page_table caml_page_table; - -/* Page table entries are the logical 'or' of - - the key: address of a page (low Page_log bits = 0) - - the data: a 8-bit integer */ - -#define Page_entry_matches(entry,addr) \ - ((((entry) ^ (addr)) & Page_mask) == 0) - -/* Multiplicative Fibonacci hashing - (Knuth, TAOCP vol 3, section 6.4, page 518). - HASH_FACTOR is (sqrt(5) - 1) / 2 * 2^wordsize. */ -#ifdef ARCH_SIXTYFOUR -#define HASH_FACTOR 11400714819323198486UL -#else -#define HASH_FACTOR 2654435769UL -#endif -#define Hash(v) (((v) * HASH_FACTOR) >> caml_page_table.shift) - -int caml_page_table_lookup(void * addr) -{ - uintnat h, e; - - h = Hash(Page(addr)); - /* The first hit is almost always successful, so optimize for this case */ - e = caml_page_table.entries[h]; - if (Page_entry_matches(e, (uintnat)addr)) return e & 0xFF; - while(1) { - if (e == 0) return 0; - h = (h + 1) & caml_page_table.mask; - e = caml_page_table.entries[h]; - if (Page_entry_matches(e, (uintnat)addr)) return e & 0xFF; - } -} - -int caml_page_table_initialize(mlsize_t bytesize) -{ - uintnat pagesize = Page(bytesize); - - caml_page_table.size = 1; - caml_page_table.shift = 8 * sizeof(uintnat); - /* Aim for initial load factor between 1/4 and 1/2 */ - while (caml_page_table.size < 2 * pagesize) { - caml_page_table.size <<= 1; - caml_page_table.shift -= 1; - } - caml_page_table.mask = caml_page_table.size - 1; - caml_page_table.occupancy = 0; - caml_page_table.entries = - caml_stat_calloc_noexc(caml_page_table.size, sizeof(uintnat)); - if (caml_page_table.entries == NULL) - return -1; - else - return 0; -} - -static int caml_page_table_resize(void) -{ - struct page_table old = caml_page_table; - uintnat * new_entries; - uintnat i, h; - - caml_gc_message (0x08, "Growing page table to %" - ARCH_INTNAT_PRINTF_FORMAT "u entries\n", - caml_page_table.size); - - new_entries = caml_stat_calloc_noexc(2 * old.size, sizeof(uintnat)); - if (new_entries == NULL) { - caml_gc_message (0x08, "No room for growing page table\n"); - return -1; - } - - caml_page_table.size = 2 * old.size; - caml_page_table.shift = old.shift - 1; - caml_page_table.mask = caml_page_table.size - 1; - caml_page_table.occupancy = old.occupancy; - caml_page_table.entries = new_entries; - - for (i = 0; i < old.size; i++) { - uintnat e = old.entries[i]; - if (e == 0) continue; - h = Hash(Page(e)); - while (caml_page_table.entries[h] != 0) - h = (h + 1) & caml_page_table.mask; - caml_page_table.entries[h] = e; - } - - caml_stat_free(old.entries); - return 0; -} - -static int caml_page_table_modify(uintnat page, int toclear, int toset) -{ - uintnat h; - - CAMLassert ((page & ~Page_mask) == 0); - - /* Resize to keep load factor below 1/2 */ - if (caml_page_table.occupancy * 2 >= caml_page_table.size) { - if (caml_page_table_resize() != 0) return -1; - } - h = Hash(Page(page)); - while (1) { - if (caml_page_table.entries[h] == 0) { - caml_page_table.entries[h] = page | toset; - caml_page_table.occupancy++; - break; - } - if (Page_entry_matches(caml_page_table.entries[h], page)) { - caml_page_table.entries[h] = - (caml_page_table.entries[h] & ~toclear) | toset; - break; - } - h = (h + 1) & caml_page_table.mask; - } - return 0; -} - -#else - -/* 32-bit implementation: - The page table is represented as a 2-level array of unsigned char */ - -CAMLexport unsigned char * caml_page_table[Pagetable1_size]; -static unsigned char caml_page_table_empty[Pagetable2_size] = { 0, }; - -int caml_page_table_initialize(mlsize_t bytesize) -{ - int i; - for (i = 0; i < Pagetable1_size; i++) - caml_page_table[i] = caml_page_table_empty; - return 0; -} - -static int caml_page_table_modify(uintnat page, int toclear, int toset) -{ - uintnat i = Pagetable_index1(page); - uintnat j = Pagetable_index2(page); - - if (caml_page_table[i] == caml_page_table_empty) { - unsigned char * new_tbl = caml_stat_calloc_noexc(Pagetable2_size, 1); - if (new_tbl == 0) return -1; - caml_page_table[i] = new_tbl; - } - caml_page_table[i][j] = (caml_page_table[i][j] & ~toclear) | toset; - return 0; -} - -#endif - -int caml_page_table_add(int kind, void * start, void * end) -{ - uintnat pstart = (uintnat) start & Page_mask; - uintnat pend = ((uintnat) end - 1) & Page_mask; - uintnat p; - - for (p = pstart; p <= pend; p += Page_size) - if (caml_page_table_modify(p, 0, kind) != 0) return -1; - return 0; -} - -int caml_page_table_remove(int kind, void * start, void * end) -{ - uintnat pstart = (uintnat) start & Page_mask; - uintnat pend = ((uintnat) end - 1) & Page_mask; - uintnat p; - - for (p = pstart; p <= pend; p += Page_size) - if (caml_page_table_modify(p, kind, 0) != 0) return -1; - return 0; -} - - -/* Initialize the [alloc_for_heap] system. - This function must be called exactly once, and it must be called - before the first call to [alloc_for_heap]. - It returns 0 on success and -1 on failure. -*/ -int caml_init_alloc_for_heap (void) -{ - return 0; -} - -/* Allocate a block of the requested size, to be passed to - [caml_add_to_heap] later. - [request] will be rounded up to some implementation-dependent size. - The caller must use [Chunk_size] on the result to recover the actual - size. - Return NULL if the request cannot be satisfied. The returned pointer - is a hp, but the header (and the contents) must be initialized by the - caller. -*/ -char *caml_alloc_for_heap (asize_t request) -{ - if (caml_use_huge_pages){ -#ifdef HAS_HUGE_PAGES - uintnat size = Round_mmap_size (sizeof (heap_chunk_head) + request); - void *block; - char *mem; - block = mmap (NULL, size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0); - if (block == MAP_FAILED) return NULL; - mem = (char *) block + sizeof (heap_chunk_head); - Chunk_size (mem) = size - sizeof (heap_chunk_head); - Chunk_block (mem) = block; - return mem; -#else - return NULL; -#endif - }else{ - char *mem; - void *block; - - request = ((request + Page_size - 1) >> Page_log) << Page_log; - mem = caml_stat_alloc_aligned_noexc (request + sizeof (heap_chunk_head), - sizeof (heap_chunk_head), &block); - if (mem == NULL) return NULL; - mem += sizeof (heap_chunk_head); - Chunk_size (mem) = request; - Chunk_block (mem) = block; - return mem; - } -} - -/* Use this function if a block allocated with [caml_alloc_for_heap] is - not actually going to be added to the heap. The caller is responsible - for freeing it. */ -void caml_disown_for_heap (char* mem) -{ - /* Currently a no-op. */ - (void)mem; /* can CAMLunused_{start,end} be used here? */ -} - -/* Use this function to free a block allocated with [caml_alloc_for_heap] - if you don't add it with [caml_add_to_heap]. -*/ -void caml_free_for_heap (char *mem) -{ - if (caml_use_huge_pages){ -#ifdef HAS_HUGE_PAGES - munmap (Chunk_block (mem), Chunk_size (mem) + sizeof (heap_chunk_head)); -#else - CAMLassert (0); -#endif - }else{ - caml_stat_free (Chunk_block (mem)); - } -} - -/* Take a chunk of memory as argument, which must be the result of a - call to [caml_alloc_for_heap], and insert it into the heap chaining. - The contents of the chunk must be a sequence of valid blocks and - fragments: no space between blocks and no trailing garbage. If - some blocks are blue, they must be added to the free list by the - caller. All other blocks must have the color [caml_allocation_color(m)]. - The caller must update [caml_allocated_words] if applicable. - Return value: 0 if no error; -1 in case of error. - - See also: caml_compact_heap, which duplicates most of this function. -*/ -int caml_add_to_heap (char *m) -{ -#ifdef DEBUG - /* Should check the contents of the block. */ -#endif /* DEBUG */ - - caml_gc_message (0x04, "Growing heap to %" - ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n", - (Bsize_wsize (caml_stat_heap_wsz) + Chunk_size (m)) / 1024); - - /* Register block in page table */ - if (caml_page_table_add(In_heap, m, m + Chunk_size(m)) != 0) - return -1; - - /* Chain this heap chunk. */ - { - char **last = &caml_heap_start; - char *cur = *last; - - while (cur != NULL && cur < m){ - last = &(Chunk_next (cur)); - cur = *last; - } - Chunk_next (m) = cur; - *last = m; - - ++ caml_stat_heap_chunks; - } - - caml_stat_heap_wsz += Wsize_bsize (Chunk_size (m)); - if (caml_stat_heap_wsz > caml_stat_top_heap_wsz){ - caml_stat_top_heap_wsz = caml_stat_heap_wsz; - } - return 0; -} - -/* Allocate more memory from malloc for the heap. - Return a blue block of at least the requested size. - The blue block is chained to a sequence of blue blocks (through their - field 0); the last block of the chain is pointed by field 1 of the - first. There may be a fragment after the last block. - The caller must insert the blocks into the free list. - [request] is a number of words and must be less than or equal - to [Max_wosize]. - Return NULL when out of memory. -*/ -static value *expand_heap (mlsize_t request) -{ - /* these point to headers, but we do arithmetic on them, hence [value *]. */ - value *mem, *hp, *prev; - asize_t over_request, malloc_request, remain; - - CAMLassert (request <= Max_wosize); - over_request = request + request / 100 * caml_percent_free; - malloc_request = caml_clip_heap_chunk_wsz (over_request); - mem = (value *) caml_alloc_for_heap (Bsize_wsize (malloc_request)); - if (mem == NULL){ - caml_gc_message (0x04, "No room for growing heap\n"); - return NULL; - } - remain = Wsize_bsize (Chunk_size (mem)); - prev = hp = mem; - /* FIXME find a way to do this with a call to caml_make_free_blocks */ - while (Wosize_whsize (remain) > Max_wosize){ - Hd_hp (hp) = Make_header (Max_wosize, 0, Caml_blue); -#ifdef DEBUG - caml_set_fields (Val_hp (hp), 0, Debug_free_major); -#endif - hp += Whsize_wosize (Max_wosize); - remain -= Whsize_wosize (Max_wosize); - Field (Val_hp (mem), 1) = Field (Val_hp (prev), 0) = Val_hp (hp); - prev = hp; - } - if (remain > 1){ - Hd_hp (hp) = Make_header (Wosize_whsize (remain), 0, Caml_blue); -#ifdef DEBUG - caml_set_fields (Val_hp (hp), 0, Debug_free_major); -#endif - Field (Val_hp (mem), 1) = Field (Val_hp (prev), 0) = Val_hp (hp); - Field (Val_hp (hp), 0) = (value) NULL; - }else{ - Field (Val_hp (prev), 0) = (value) NULL; - if (remain == 1) { - Hd_hp (hp) = Make_header_allocated_here (0, 0, Caml_white); - } - } - CAMLassert (Wosize_hp (mem) >= request); - if (caml_add_to_heap ((char *) mem) != 0){ - caml_free_for_heap ((char *) mem); - return NULL; - } - return Op_hp (mem); -} - -/* Remove the heap chunk [chunk] from the heap and give the memory back - to [free]. -*/ -void caml_shrink_heap (char *chunk) -{ - char **cp; - - /* Never deallocate the first chunk, because caml_heap_start is both the - first block and the base address for page numbers, and we don't - want to shift the page table, it's too messy (see above). - It will never happen anyway, because of the way compaction works. - (see compact.c) - XXX FIXME this has become false with the fix to PR#5389 (see compact.c) - */ - if (chunk == caml_heap_start) return; - - caml_stat_heap_wsz -= Wsize_bsize (Chunk_size (chunk)); - caml_gc_message (0x04, "Shrinking heap to %" - ARCH_INTNAT_PRINTF_FORMAT "uk words\n", - caml_stat_heap_wsz / 1024); - -#ifdef DEBUG - { - mlsize_t i; - for (i = 0; i < Wsize_bsize (Chunk_size (chunk)); i++){ - ((value *) chunk) [i] = Debug_free_shrink; - } - } -#endif - - -- caml_stat_heap_chunks; - - /* Remove [chunk] from the list of chunks. */ - cp = &caml_heap_start; - while (*cp != chunk) cp = &(Chunk_next (*cp)); - *cp = Chunk_next (chunk); - - /* Remove the pages of [chunk] from the page table. */ - caml_page_table_remove(In_heap, chunk, chunk + Chunk_size (chunk)); - - /* Free the [malloc] block that contains [chunk]. */ - caml_free_for_heap (chunk); -} - -color_t caml_allocation_color (void *hp) -{ - if (caml_gc_phase == Phase_mark || caml_gc_phase == Phase_clean - || (caml_gc_phase == Phase_sweep && (addr)hp >= (addr)caml_gc_sweep_hp)){ - return Caml_black; - }else{ - CAMLassert (caml_gc_phase == Phase_idle - || (caml_gc_phase == Phase_sweep - && (addr)hp < (addr)caml_gc_sweep_hp)); - return Caml_white; - } -} - -static inline value caml_alloc_shr_aux (mlsize_t wosize, tag_t tag, - int raise_oom, uintnat profinfo) -{ - header_t *hp; - value *new_block; - - if (wosize > Max_wosize) { - if (raise_oom) - caml_raise_out_of_memory (); - else - return 0; - } - hp = caml_fl_allocate (wosize); - if (hp == NULL){ - new_block = expand_heap (wosize); - if (new_block == NULL) { - if (!raise_oom) - return 0; - else if (caml_in_minor_collection) - caml_fatal_error ("Fatal error: out of memory.\n"); - else - caml_raise_out_of_memory (); - } - caml_fl_add_blocks ((value) new_block); - hp = caml_fl_allocate (wosize); - } - - CAMLassert (Is_in_heap (Val_hp (hp))); - - /* Inline expansion of caml_allocation_color. */ - if (caml_gc_phase == Phase_mark || caml_gc_phase == Phase_clean - || (caml_gc_phase == Phase_sweep && (addr)hp >= (addr)caml_gc_sweep_hp)){ - Hd_hp (hp) = Make_header_with_profinfo (wosize, tag, Caml_black, profinfo); - }else{ - CAMLassert (caml_gc_phase == Phase_idle - || (caml_gc_phase == Phase_sweep - && (addr)hp < (addr)caml_gc_sweep_hp)); - Hd_hp (hp) = Make_header_with_profinfo (wosize, tag, Caml_white, profinfo); - } - CAMLassert (Hd_hp (hp) - == Make_header_with_profinfo (wosize, tag, caml_allocation_color (hp), - profinfo)); - caml_allocated_words += Whsize_wosize (wosize); - if (caml_allocated_words > caml_minor_heap_wsz){ - CAML_INSTR_INT ("request_major/alloc_shr@", 1); - caml_request_major_slice (); - } -#ifdef DEBUG - { - uintnat i; - for (i = 0; i < wosize; i++){ - Field (Val_hp (hp), i) = Debug_uninit_major; - } - } -#endif - return Val_hp (hp); -} - -CAMLexport value caml_alloc_shr_no_raise (mlsize_t wosize, tag_t tag) -{ - return caml_alloc_shr_aux(wosize, tag, 0, 0); -} - -#ifdef WITH_PROFINFO - -/* Use this to debug problems with macros... */ -#define NO_PROFINFO 0xff - -CAMLexport value caml_alloc_shr_with_profinfo (mlsize_t wosize, tag_t tag, - intnat profinfo) -{ - return caml_alloc_shr_aux(wosize, tag, 1, profinfo); -} - -CAMLexport value caml_alloc_shr_preserving_profinfo (mlsize_t wosize, - tag_t tag, header_t old_header) -{ - return caml_alloc_shr_with_profinfo (wosize, tag, Profinfo_hd(old_header)); -} - -#else -#define NO_PROFINFO 0 -#endif /* WITH_PROFINFO */ - -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) -#include "caml/spacetime.h" - -CAMLexport value caml_alloc_shr (mlsize_t wosize, tag_t tag) -{ - return caml_alloc_shr_with_profinfo (wosize, tag, - caml_spacetime_my_profinfo (NULL, wosize)); -} -#else -CAMLexport value caml_alloc_shr (mlsize_t wosize, tag_t tag) -{ - return caml_alloc_shr_aux (wosize, tag, 1, NO_PROFINFO); -} -#endif - -/* Dependent memory is all memory blocks allocated out of the heap - that depend on the GC (and finalizers) for deallocation. - For the GC to take dependent memory into account when computing - its automatic speed setting, - you must call [caml_alloc_dependent_memory] when you alloate some - dependent memory, and [caml_free_dependent_memory] when you - free it. In both cases, you pass as argument the size (in bytes) - of the block being allocated or freed. -*/ -CAMLexport void caml_alloc_dependent_memory (mlsize_t nbytes) -{ - caml_dependent_size += nbytes / sizeof (value); - caml_dependent_allocated += nbytes / sizeof (value); -} - -CAMLexport void caml_free_dependent_memory (mlsize_t nbytes) -{ - if (caml_dependent_size < nbytes / sizeof (value)){ - caml_dependent_size = 0; - }else{ - caml_dependent_size -= nbytes / sizeof (value); - } -} - -/* Use this function to tell the major GC to speed up when you use - finalized blocks to automatically deallocate resources (other - than memory). The GC will do at least one cycle every [max] - allocated resources; [res] is the number of resources allocated - this time. - Note that only [res/max] is relevant. The units (and kind of - resource) can change between calls to [caml_adjust_gc_speed]. -*/ -CAMLexport void caml_adjust_gc_speed (mlsize_t res, mlsize_t max) -{ - if (max == 0) max = 1; - if (res > max) res = max; - caml_extra_heap_resources += (double) res / (double) max; - if (caml_extra_heap_resources > 1.0){ - CAML_INSTR_INT ("request_major/adjust_gc_speed_1@", 1); - caml_extra_heap_resources = 1.0; - caml_request_major_slice (); - } - if (caml_extra_heap_resources - > (double) caml_minor_heap_wsz / 2.0 - / (double) caml_stat_heap_wsz) { - CAML_INSTR_INT ("request_major/adjust_gc_speed_2@", 1); - caml_request_major_slice (); - } -} - -/* You must use [caml_initialize] to store the initial value in a field of - a shared block, unless you are sure the value is not a young block. - A block value [v] is a shared block if and only if [Is_in_heap (v)] - is true. -*/ -/* [caml_initialize] never calls the GC, so you may call it while a block is - unfinished (i.e. just after a call to [caml_alloc_shr].) */ -/* PR#6084 workaround: define it as a weak symbol */ -CAMLexport CAMLweakdef void caml_initialize (value *fp, value val) -{ - CAMLassert(Is_in_heap_or_young(fp)); - *fp = val; - if (!Is_young((value)fp) && Is_block (val) && Is_young (val)) { - add_to_ref_table (&caml_ref_table, fp); - } -} - -/* You must use [caml_modify] to change a field of an existing shared block, - unless you are sure the value being overwritten is not a shared block and - the value being written is not a young block. */ -/* [caml_modify] never calls the GC. */ -/* [caml_modify] can also be used to do assignment on data structures that are - in the minor heap instead of in the major heap. In this case, it - is a bit slower than simple assignment. - In particular, you can use [caml_modify] when you don't know whether the - block being changed is in the minor heap or the major heap. */ -/* PR#6084 workaround: define it as a weak symbol */ - -CAMLexport CAMLweakdef void caml_modify (value *fp, value val) -{ - /* The write barrier implemented by [caml_modify] checks for the - following two conditions and takes appropriate action: - 1- a pointer from the major heap to the minor heap is created - --> add [fp] to the remembered set - 2- a pointer from the major heap to the major heap is overwritten, - while the GC is in the marking phase - --> call [caml_darken] on the overwritten pointer so that the - major GC treats it as an additional root. - */ - value old; - - if (Is_young((value)fp)) { - /* The modified object resides in the minor heap. - Conditions 1 and 2 cannot occur. */ - *fp = val; - } else { - /* The modified object resides in the major heap. */ - CAMLassert(Is_in_heap(fp)); - old = *fp; - *fp = val; - if (Is_block(old)) { - /* If [old] is a pointer within the minor heap, we already - have a major->minor pointer and [fp] is already in the - remembered set. Conditions 1 and 2 cannot occur. */ - if (Is_young(old)) return; - /* Here, [old] can be a pointer within the major heap. - Check for condition 2. */ - if (caml_gc_phase == Phase_mark) caml_darken(old, NULL); - } - /* Check for condition 1. */ - if (Is_block(val) && Is_young(val)) { - add_to_ref_table (&caml_ref_table, fp); - } - } -} - - -/* Global memory pool. - - The pool is structured as a ring of blocks, where each block's header - contains two links: to the previous and to the next block. The data - structure allows for insertions and removals of blocks in constant time, - given that a pointer to the operated block is provided. - - Initially, the pool contains a single block -- a pivot with no data, the - guaranteed existence of which makes for a more concise implementation. - - The API functions that operate on the pool receive not pointers to the - block's header, but rather pointers to the block's "data" field. This - behaviour is required to maintain compatibility with the interfaces of - [malloc], [realloc], and [free] family of functions, as well as to hide - the implementation from the user. -*/ - -/* A type with the most strict alignment requirements */ -union max_align { - char c; - short s; - long l; - int i; - float f; - double d; - void *v; - void (*q)(void); -}; - -struct pool_block { -#ifdef DEBUG - long magic; -#endif - struct pool_block *next; - struct pool_block *prev; - /* Use C99's flexible array types if possible */ -#if (__STDC_VERSION__ >= 199901L) - union max_align data[]; /* not allocated, used for alignment purposes */ -#else - union max_align data[1]; -#endif -}; - -#if (__STDC_VERSION__ >= 199901L) -#define SIZEOF_POOL_BLOCK sizeof(struct pool_block) -#else -#define SIZEOF_POOL_BLOCK offsetof(struct pool_block, data) -#endif - -static struct pool_block *pool = NULL; - - -/* Returns a pointer to the block header, given a pointer to "data" */ -static struct pool_block* get_pool_block(caml_stat_block b) -{ - if (b == NULL) - return NULL; - - else { - struct pool_block *pb = - (struct pool_block*)(((char*)b) - SIZEOF_POOL_BLOCK); -#ifdef DEBUG - CAMLassert(pb->magic == Debug_pool_magic); -#endif - return pb; - } -} - -CAMLexport void caml_stat_create_pool(void) -{ - if (pool == NULL) { - pool = malloc(SIZEOF_POOL_BLOCK); - if (pool == NULL) - caml_fatal_error("Fatal error: out of memory.\n"); -#ifdef DEBUG - pool->magic = Debug_pool_magic; -#endif - pool->next = pool; - pool->prev = pool; - } -} - -CAMLexport void caml_stat_destroy_pool(void) -{ - if (pool != NULL) { - pool->prev->next = NULL; - while (pool != NULL) { - struct pool_block *next = pool->next; - free(pool); - pool = next; - } - pool = NULL; - } -} - -/* [sz] and [modulo] are numbers of bytes */ -CAMLexport void* caml_stat_alloc_aligned_noexc(asize_t sz, int modulo, - caml_stat_block *b) -{ - char *raw_mem; - uintnat aligned_mem; - CAMLassert (modulo < Page_size); - raw_mem = (char *) caml_stat_alloc_noexc(sz + Page_size); - if (raw_mem == NULL) return NULL; - *b = raw_mem; - raw_mem += modulo; /* Address to be aligned */ - aligned_mem = (((uintnat) raw_mem / Page_size + 1) * Page_size); -#ifdef DEBUG - { - uintnat *p; - uintnat *p0 = (void *) *b; - uintnat *p1 = (void *) (aligned_mem - modulo); - uintnat *p2 = (void *) (aligned_mem - modulo + sz); - uintnat *p3 = (void *) ((char *) *b + sz + Page_size); - for (p = p0; p < p1; p++) *p = Debug_filler_align; - for (p = p1; p < p2; p++) *p = Debug_uninit_align; - for (p = p2; p < p3; p++) *p = Debug_filler_align; - } -#endif - return (char *) (aligned_mem - modulo); -} - -/* [sz] and [modulo] are numbers of bytes */ -CAMLexport void* caml_stat_alloc_aligned(asize_t sz, int modulo, - caml_stat_block *b) -{ - void *result = caml_stat_alloc_aligned_noexc(sz, modulo, b); - /* malloc() may return NULL if size is 0 */ - if ((result == NULL) && (sz != 0)) - caml_raise_out_of_memory(); - return result; -} - -/* [sz] is a number of bytes */ -CAMLexport caml_stat_block caml_stat_alloc_noexc(asize_t sz) -{ - /* Backward compatibility mode */ - if (pool == NULL) - return malloc(sz); - else { - struct pool_block *pb = malloc(sz + SIZEOF_POOL_BLOCK); - if (pb == NULL) return NULL; -#ifdef DEBUG - memset(&(pb->data), Debug_uninit_stat, sz); - pb->magic = Debug_pool_magic; -#endif - - /* Linking the block into the ring */ - pb->next = pool->next; - pb->prev = pool; - pool->next->prev = pb; - pool->next = pb; - - return &(pb->data); - } -} - -/* [sz] is a number of bytes */ -CAMLexport caml_stat_block caml_stat_alloc(asize_t sz) -{ - void *result = caml_stat_alloc_noexc(sz); - /* malloc() may return NULL if size is 0 */ - if ((result == NULL) && (sz != 0)) - caml_raise_out_of_memory(); - return result; -} - -CAMLexport void caml_stat_free(caml_stat_block b) -{ - /* Backward compatibility mode */ - if (pool == NULL) - free(b); - else { - struct pool_block *pb = get_pool_block(b); - if (pb == NULL) return; - - /* Unlinking the block from the ring */ - pb->prev->next = pb->next; - pb->next->prev = pb->prev; - - free(pb); - } -} - -/* [sz] is a number of bytes */ -CAMLexport caml_stat_block caml_stat_resize_noexc(caml_stat_block b, asize_t sz) -{ - /* Backward compatibility mode */ - if (pool == NULL) - return realloc(b, sz); - else { - struct pool_block *pb = get_pool_block(b); - struct pool_block *pb_new = realloc(pb, sz + SIZEOF_POOL_BLOCK); - if (pb_new == NULL) return NULL; - - /* Relinking the new block into the ring in place of the old one */ - pb_new->prev->next = pb_new; - pb_new->next->prev = pb_new; - - return &(pb_new->data); - } -} - -/* [sz] is a number of bytes */ -CAMLexport caml_stat_block caml_stat_resize(caml_stat_block b, asize_t sz) -{ - void *result = caml_stat_resize_noexc(b, sz); - if (result == NULL) - caml_raise_out_of_memory(); - return result; -} - -/* [sz] is a number of bytes */ -CAMLexport caml_stat_block caml_stat_calloc_noexc(asize_t num, asize_t sz) -{ - uintnat total; - if (caml_umul_overflow(sz, num, &total)) - return NULL; - else { - caml_stat_block result = caml_stat_alloc_noexc(total); - if (result != NULL) - memset(result, 0, total); - return result; - } -} - -CAMLexport caml_stat_string caml_stat_strdup_noexc(const char *s) -{ - size_t slen = strlen(s); - caml_stat_block result = caml_stat_alloc_noexc(slen + 1); - if (result == NULL) - return NULL; - memcpy(result, s, slen + 1); - return result; -} - -CAMLexport caml_stat_string caml_stat_strdup(const char *s) -{ - caml_stat_string result = caml_stat_strdup_noexc(s); - if (result == NULL) - caml_raise_out_of_memory(); - return result; -} - -#ifdef _WIN32 - -CAMLexport wchar_t * caml_stat_wcsdup(const wchar_t *s) -{ - int slen = wcslen(s); - wchar_t* result = caml_stat_alloc((slen + 1)*sizeof(wchar_t)); - if (result == NULL) - caml_raise_out_of_memory(); - memcpy(result, s, (slen + 1)*sizeof(wchar_t)); - return result; -} - -#endif - -CAMLexport caml_stat_string caml_stat_strconcat(int n, ...) -{ - va_list args; - char *result, *p; - size_t len = 0; - int i; - - va_start(args, n); - for (i = 0; i < n; i++) { - const char *s = va_arg(args, const char*); - len += strlen(s); - } - va_end(args); - - result = caml_stat_alloc(len + 1); - - va_start(args, n); - p = result; - for (i = 0; i < n; i++) { - const char *s = va_arg(args, const char*); - size_t l = strlen(s); - memcpy(p, s, l); - p += l; - } - va_end(args); - - *p = 0; - return result; -} - -#ifdef _WIN32 - -CAMLexport wchar_t* caml_stat_wcsconcat(int n, ...) -{ - va_list args; - wchar_t *result, *p; - size_t len = 0; - int i; - - va_start(args, n); - for (i = 0; i < n; i++) { - const wchar_t *s = va_arg(args, const wchar_t*); - len += wcslen(s); - } - va_end(args); - - result = caml_stat_alloc((len + 1)*sizeof(wchar_t)); - - va_start(args, n); - p = result; - for (i = 0; i < n; i++) { - const wchar_t *s = va_arg(args, const wchar_t*); - size_t l = wcslen(s); - memcpy(p, s, l*sizeof(wchar_t)); - p += l; - } - va_end(args); - - *p = 0; - return result; -} - -#endif diff --git a/byterun/meta.c b/byterun/meta.c deleted file mode 100644 index 03e0479d..00000000 --- a/byterun/meta.c +++ /dev/null @@ -1,234 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Primitives for the toplevel */ - -#include -#include "caml/alloc.h" -#include "caml/config.h" -#include "caml/fail.h" -#include "caml/fix_code.h" -#include "caml/interp.h" -#include "caml/intext.h" -#include "caml/major_gc.h" -#include "caml/memory.h" -#include "caml/minor_gc.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/prims.h" -#include "caml/stacks.h" - -#ifndef NATIVE_CODE - -CAMLprim value caml_get_global_data(value unit) -{ - return caml_global_data; -} - -char * caml_section_table = NULL; -asize_t caml_section_table_size; - -CAMLprim value caml_get_section_table(value unit) -{ - if (caml_section_table == NULL) caml_raise_not_found(); - return caml_input_value_from_block(caml_section_table, - caml_section_table_size); -} - -CAMLprim value caml_reify_bytecode(value prog, value len) -{ - struct code_fragment * cf = caml_stat_alloc(sizeof(struct code_fragment)); - value clos; - - cf->code_start = (char *) prog; - cf->code_end = (char *) prog + Long_val(len); - cf->digest_computed = 0; - caml_ext_table_add(&caml_code_fragments_table, cf); - -#ifdef ARCH_BIG_ENDIAN - caml_fixup_endianness((code_t) prog, (asize_t) Long_val(len)); -#endif -#ifdef THREADED_CODE - caml_thread_code((code_t) prog, (asize_t) Long_val(len)); -#endif - caml_prepare_bytecode((code_t) prog, (asize_t) Long_val(len)); - clos = caml_alloc_small (1, Closure_tag); - Code_val(clos) = (code_t) prog; - return clos; -} - -/* signal to the interpreter machinery that a bytecode is no more - needed (before freeing it) - this might be useful for a JIT - implementation */ - -CAMLprim value caml_static_release_bytecode(value prog, value len) -{ - struct code_fragment * cf = NULL, * cfi; - int i; - for (i = 0; i < caml_code_fragments_table.size; i++) { - cfi = (struct code_fragment *) caml_code_fragments_table.contents[i]; - if (cfi->code_start == (char *) prog && - cfi->code_end == (char *) prog + Long_val(len)) { - cf = cfi; - break; - } - } - - if (!cf) { - /* [cf] Not matched with a caml_reify_bytecode call; impossible. */ - CAMLassert (0); - } else { - caml_ext_table_remove(&caml_code_fragments_table, cf); - } - -#ifndef NATIVE_CODE - caml_release_bytecode((code_t) prog, (asize_t) Long_val(len)); -#else - caml_failwith("Meta.static_release_bytecode impossible with native code"); -#endif - return Val_unit; -} - -CAMLprim value caml_register_code_fragment(value prog, value len, value digest) -{ - struct code_fragment * cf = caml_stat_alloc(sizeof(struct code_fragment)); - cf->code_start = (char *) prog; - cf->code_end = (char *) prog + Long_val(len); - memcpy(cf->digest, String_val(digest), 16); - cf->digest_computed = 1; - caml_ext_table_add(&caml_code_fragments_table, cf); - return Val_unit; -} - -CAMLprim value caml_realloc_global(value size) -{ - mlsize_t requested_size, actual_size, i; - value new_global_data; - - requested_size = Long_val(size); - actual_size = Wosize_val(caml_global_data); - if (requested_size >= actual_size) { - requested_size = (requested_size + 0x100) & 0xFFFFFF00; - caml_gc_message (0x08, "Growing global data to %" - ARCH_INTNAT_PRINTF_FORMAT "u entries\n", - requested_size); - new_global_data = caml_alloc_shr(requested_size, 0); - for (i = 0; i < actual_size; i++) - caml_initialize(&Field(new_global_data, i), Field(caml_global_data, i)); - for (i = actual_size; i < requested_size; i++){ - Field (new_global_data, i) = Val_long (0); - } - caml_global_data = new_global_data; - } - return Val_unit; -} - -CAMLprim value caml_get_current_environment(value unit) -{ - return *caml_extern_sp; -} - -CAMLprim value caml_invoke_traced_function(value codeptr, value env, value arg) -{ - /* Stack layout on entry: - return frame into instrument_closure function - arg3 to call_original_code (arg) - arg2 to call_original_code (env) - arg1 to call_original_code (codeptr) - arg3 to call_original_code (arg) - arg2 to call_original_code (env) - saved env */ - - /* Stack layout on exit: - return frame into instrument_closure function - actual arg to code (arg) - pseudo return frame into codeptr: - extra_args = 0 - environment = env - PC = codeptr - arg3 to call_original_code (arg) same 6 bottom words as - arg2 to call_original_code (env) on entrance, but - arg1 to call_original_code (codeptr) shifted down 4 words - arg3 to call_original_code (arg) - arg2 to call_original_code (env) - saved env */ - - value * osp, * nsp; - int i; - - osp = caml_extern_sp; - caml_extern_sp -= 4; - nsp = caml_extern_sp; - for (i = 0; i < 6; i++) nsp[i] = osp[i]; - nsp[6] = codeptr; - nsp[7] = env; - nsp[8] = Val_int(0); - nsp[9] = arg; - return Val_unit; -} - -#else - -/* Dummy definitions to support compilation of ocamlc.opt */ - -value caml_get_global_data(value unit) -{ - caml_invalid_argument("Meta.get_global_data"); - return Val_unit; /* not reached */ -} - -value caml_get_section_table(value unit) -{ - caml_invalid_argument("Meta.get_section_table"); - return Val_unit; /* not reached */ -} - -value caml_realloc_global(value size) -{ - caml_invalid_argument("Meta.realloc_global"); - return Val_unit; /* not reached */ -} - -value caml_invoke_traced_function(value codeptr, value env, value arg) -{ - caml_invalid_argument("Meta.invoke_traced_function"); - return Val_unit; /* not reached */ -} - -value caml_reify_bytecode(value prog, value len) -{ - caml_invalid_argument("Meta.reify_bytecode"); - return Val_unit; /* not reached */ -} - -value caml_static_release_bytecode(value prog, value len) -{ - caml_invalid_argument("Meta.static_release_bytecode"); - return Val_unit; /* not reached */ -} - -value * caml_stack_low; -value * caml_stack_high; -value * caml_stack_threshold; -value * caml_extern_sp; -value * caml_trapsp; -int caml_callback_depth; -int volatile caml_something_to_do; -void (* volatile caml_async_action_hook)(void); -struct longjmp_buffer * caml_external_raise; - -#endif diff --git a/byterun/minor_gc.c b/byterun/minor_gc.c deleted file mode 100644 index 6aa5ed72..00000000 --- a/byterun/minor_gc.c +++ /dev/null @@ -1,558 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -#include -#include "caml/custom.h" -#include "caml/config.h" -#include "caml/fail.h" -#include "caml/finalise.h" -#include "caml/gc.h" -#include "caml/gc_ctrl.h" -#include "caml/major_gc.h" -#include "caml/memory.h" -#include "caml/minor_gc.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/roots.h" -#include "caml/signals.h" -#include "caml/weak.h" - -/* Pointers into the minor heap. - [caml_young_base] - The [malloc] block that contains the heap. - [caml_young_start] ... [caml_young_end] - The whole range of the minor heap: all young blocks are inside - this interval. - [caml_young_alloc_start]...[caml_young_alloc_end] - The allocation arena: newly-allocated blocks are carved from - this interval, starting at [caml_young_alloc_end]. - [caml_young_alloc_mid] is the mid-point of this interval. - [caml_young_ptr], [caml_young_trigger], [caml_young_limit] - These pointers are all inside the allocation arena. - - [caml_young_ptr] is where the next allocation will take place. - - [caml_young_trigger] is how far we can allocate before triggering - [caml_gc_dispatch]. Currently, it is either [caml_young_alloc_start] - or the mid-point of the allocation arena. - - [caml_young_limit] is the pointer that is compared to - [caml_young_ptr] for allocation. It is either - [caml_young_alloc_end] if a signal is pending and we are in - native code, or [caml_young_trigger]. -*/ - -struct generic_table CAML_TABLE_STRUCT(char); - -asize_t caml_minor_heap_wsz; -static void *caml_young_base = NULL; -CAMLexport value *caml_young_start = NULL, *caml_young_end = NULL; -CAMLexport value *caml_young_alloc_start = NULL, - *caml_young_alloc_mid = NULL, - *caml_young_alloc_end = NULL; -CAMLexport value *caml_young_ptr = NULL, *caml_young_limit = NULL; -CAMLexport value *caml_young_trigger = NULL; - -CAMLexport struct caml_ref_table - caml_ref_table = { NULL, NULL, NULL, NULL, NULL, 0, 0}; - -CAMLexport struct caml_ephe_ref_table - caml_ephe_ref_table = { NULL, NULL, NULL, NULL, NULL, 0, 0}; - -CAMLexport struct caml_custom_table - caml_custom_table = { NULL, NULL, NULL, NULL, NULL, 0, 0}; -/* Table of custom blocks in the minor heap that contain finalizers - or GC speed parameters. */ - -int caml_in_minor_collection = 0; - -double caml_extra_heap_resources_minor = 0; - -/* [sz] and [rsv] are numbers of entries */ -static void alloc_generic_table (struct generic_table *tbl, asize_t sz, - asize_t rsv, asize_t element_size) -{ - void *new_table; - - tbl->size = sz; - tbl->reserve = rsv; - new_table = (void *) caml_stat_alloc_noexc((tbl->size + tbl->reserve) * - element_size); - if (new_table == NULL) caml_fatal_error ("Fatal error: not enough memory\n"); - if (tbl->base != NULL) caml_stat_free (tbl->base); - tbl->base = new_table; - tbl->ptr = tbl->base; - tbl->threshold = tbl->base + tbl->size * element_size; - tbl->limit = tbl->threshold; - tbl->end = tbl->base + (tbl->size + tbl->reserve) * element_size; -} - -void caml_alloc_table (struct caml_ref_table *tbl, asize_t sz, asize_t rsv) -{ - alloc_generic_table ((struct generic_table *) tbl, sz, rsv, sizeof (value *)); -} - -void caml_alloc_ephe_table (struct caml_ephe_ref_table *tbl, asize_t sz, - asize_t rsv) -{ - alloc_generic_table ((struct generic_table *) tbl, sz, rsv, - sizeof (struct caml_ephe_ref_elt)); -} - -void caml_alloc_custom_table (struct caml_custom_table *tbl, asize_t sz, - asize_t rsv) -{ - alloc_generic_table ((struct generic_table *) tbl, sz, rsv, - sizeof (struct caml_custom_elt)); -} - -static void reset_table (struct generic_table *tbl) -{ - tbl->size = 0; - tbl->reserve = 0; - if (tbl->base != NULL) caml_stat_free (tbl->base); - tbl->base = tbl->ptr = tbl->threshold = tbl->limit = tbl->end = NULL; -} - -static void clear_table (struct generic_table *tbl) -{ - tbl->ptr = tbl->base; - tbl->limit = tbl->threshold; -} - -void caml_set_minor_heap_size (asize_t bsz) -{ - char *new_heap; - void *new_heap_base; - - CAMLassert (bsz >= Bsize_wsize(Minor_heap_min)); - CAMLassert (bsz <= Bsize_wsize(Minor_heap_max)); - CAMLassert (bsz % sizeof (value) == 0); - if (caml_young_ptr != caml_young_alloc_end){ - CAML_INSTR_INT ("force_minor/set_minor_heap_size@", 1); - caml_requested_minor_gc = 0; - caml_young_trigger = caml_young_alloc_mid; - caml_young_limit = caml_young_trigger; - caml_empty_minor_heap (); - } - CAMLassert (caml_young_ptr == caml_young_alloc_end); - new_heap = caml_stat_alloc_aligned_noexc(bsz, 0, &new_heap_base); - if (new_heap == NULL) caml_raise_out_of_memory(); - if (caml_page_table_add(In_young, new_heap, new_heap + bsz) != 0) - caml_raise_out_of_memory(); - - if (caml_young_start != NULL){ - caml_page_table_remove(In_young, caml_young_start, caml_young_end); - caml_stat_free (caml_young_base); - } - caml_young_base = new_heap_base; - caml_young_start = (value *) new_heap; - caml_young_end = (value *) (new_heap + bsz); - caml_young_alloc_start = caml_young_start; - caml_young_alloc_mid = caml_young_alloc_start + Wsize_bsize (bsz) / 2; - caml_young_alloc_end = caml_young_end; - caml_young_trigger = caml_young_alloc_start; - caml_young_limit = caml_young_trigger; - caml_young_ptr = caml_young_alloc_end; - caml_minor_heap_wsz = Wsize_bsize (bsz); - - reset_table ((struct generic_table *) &caml_ref_table); - reset_table ((struct generic_table *) &caml_ephe_ref_table); - reset_table ((struct generic_table *) &caml_custom_table); -} - -static value oldify_todo_list = 0; - -/* Note that the tests on the tag depend on the fact that Infix_tag, - Forward_tag, and No_scan_tag are contiguous. */ - -void caml_oldify_one (value v, value *p) -{ - value result; - header_t hd; - mlsize_t sz, i; - tag_t tag; - - tail_call: - if (Is_block (v) && Is_young (v)){ - CAMLassert ((value *) Hp_val (v) >= caml_young_ptr); - hd = Hd_val (v); - if (hd == 0){ /* If already forwarded */ - *p = Field (v, 0); /* then forward pointer is first field. */ - }else{ - tag = Tag_hd (hd); - if (tag < Infix_tag){ - value field0; - - sz = Wosize_hd (hd); - result = caml_alloc_shr_preserving_profinfo (sz, tag, hd); - *p = result; - field0 = Field (v, 0); - Hd_val (v) = 0; /* Set forward flag */ - Field (v, 0) = result; /* and forward pointer. */ - if (sz > 1){ - Field (result, 0) = field0; - Field (result, 1) = oldify_todo_list; /* Add this block */ - oldify_todo_list = v; /* to the "to do" list. */ - }else{ - CAMLassert (sz == 1); - p = &Field (result, 0); - v = field0; - goto tail_call; - } - }else if (tag >= No_scan_tag){ - sz = Wosize_hd (hd); - result = caml_alloc_shr_preserving_profinfo (sz, tag, hd); - for (i = 0; i < sz; i++) Field (result, i) = Field (v, i); - Hd_val (v) = 0; /* Set forward flag */ - Field (v, 0) = result; /* and forward pointer. */ - *p = result; - }else if (tag == Infix_tag){ - mlsize_t offset = Infix_offset_hd (hd); - caml_oldify_one (v - offset, p); /* Cannot recurse deeper than 1. */ - *p += offset; - }else{ - value f = Forward_val (v); - tag_t ft = 0; - int vv = 1; - - CAMLassert (tag == Forward_tag); - if (Is_block (f)){ - if (Is_young (f)){ - vv = 1; - ft = Tag_val (Hd_val (f) == 0 ? Field (f, 0) : f); - }else{ - vv = Is_in_value_area(f); - if (vv){ - ft = Tag_val (f); - } - } - } - if (!vv || ft == Forward_tag || ft == Lazy_tag -#ifdef FLAT_FLOAT_ARRAY - || ft == Double_tag -#endif - ){ - /* Do not short-circuit the pointer. Copy as a normal block. */ - CAMLassert (Wosize_hd (hd) == 1); - result = caml_alloc_shr_preserving_profinfo (1, Forward_tag, hd); - *p = result; - Hd_val (v) = 0; /* Set (GC) forward flag */ - Field (v, 0) = result; /* and forward pointer. */ - p = &Field (result, 0); - v = f; - goto tail_call; - }else{ - v = f; /* Follow the forwarding */ - goto tail_call; /* then oldify. */ - } - } - } - }else{ - *p = v; - } -} - -/* Test if the ephemeron is alive, everything outside minor heap is alive */ -static inline int ephe_check_alive_data(struct caml_ephe_ref_elt *re){ - mlsize_t i; - value child; - for (i = CAML_EPHE_FIRST_KEY; i < Wosize_val(re->ephe); i++){ - child = Field (re->ephe, i); - if(child != caml_ephe_none - && Is_block (child) && Is_young (child) - && Hd_val (child) != 0){ /* Value not copied to major heap */ - return 0; - } - } - return 1; -} - -/* Finish the work that was put off by [caml_oldify_one]. - Note that [caml_oldify_one] itself is called by oldify_mopup, so we - have to be careful to remove the first entry from the list before - oldifying its fields. */ -void caml_oldify_mopup (void) -{ - value v, new_v, f; - mlsize_t i; - struct caml_ephe_ref_elt *re; - int redo = 0; - - while (oldify_todo_list != 0){ - v = oldify_todo_list; /* Get the head. */ - CAMLassert (Hd_val (v) == 0); /* It must be forwarded. */ - new_v = Field (v, 0); /* Follow forward pointer. */ - oldify_todo_list = Field (new_v, 1); /* Remove from list. */ - - f = Field (new_v, 0); - if (Is_block (f) && Is_young (f)){ - caml_oldify_one (f, &Field (new_v, 0)); - } - for (i = 1; i < Wosize_val (new_v); i++){ - f = Field (v, i); - if (Is_block (f) && Is_young (f)){ - caml_oldify_one (f, &Field (new_v, i)); - }else{ - Field (new_v, i) = f; - } - } - } - - /* Oldify the data in the minor heap of alive ephemeron - During minor collection keys outside the minor heap are considered alive */ - for (re = caml_ephe_ref_table.base; - re < caml_ephe_ref_table.ptr; re++){ - /* look only at ephemeron with data in the minor heap */ - if (re->offset == 1){ - value *data = &Field(re->ephe,1); - if (*data != caml_ephe_none && Is_block (*data) && Is_young (*data)){ - if (Hd_val (*data) == 0){ /* Value copied to major heap */ - *data = Field (*data, 0); - } else { - if (ephe_check_alive_data(re)){ - caml_oldify_one(*data,data); - redo = 1; /* oldify_todo_list can still be 0 */ - } - } - } - } - } - - if (redo) caml_oldify_mopup (); -} - -/* Make sure the minor heap is empty by performing a minor collection - if needed. -*/ -void caml_empty_minor_heap (void) -{ - value **r; - struct caml_custom_elt *elt; - uintnat prev_alloc_words; - struct caml_ephe_ref_elt *re; - - if (caml_young_ptr != caml_young_alloc_end){ - if (caml_minor_gc_begin_hook != NULL) (*caml_minor_gc_begin_hook) (); - CAML_INSTR_SETUP (tmr, "minor"); - prev_alloc_words = caml_allocated_words; - caml_in_minor_collection = 1; - caml_gc_message (0x02, "<"); - caml_oldify_local_roots(); - CAML_INSTR_TIME (tmr, "minor/local_roots"); - for (r = caml_ref_table.base; r < caml_ref_table.ptr; r++){ - caml_oldify_one (**r, *r); - } - CAML_INSTR_TIME (tmr, "minor/ref_table"); - caml_oldify_mopup (); - CAML_INSTR_TIME (tmr, "minor/copy"); - /* Update the ephemerons */ - for (re = caml_ephe_ref_table.base; - re < caml_ephe_ref_table.ptr; re++){ - if(re->offset < Wosize_val(re->ephe)){ - /* If it is not the case, the ephemeron has been truncated */ - value *key = &Field(re->ephe,re->offset); - if (*key != caml_ephe_none && Is_block (*key) && Is_young (*key)){ - if (Hd_val (*key) == 0){ /* Value copied to major heap */ - *key = Field (*key, 0); - }else{ /* Value not copied so it's dead */ - CAMLassert(!ephe_check_alive_data(re)); - *key = caml_ephe_none; - Field(re->ephe,1) = caml_ephe_none; - } - } - } - } - /* Update the OCaml finalise_last values */ - caml_final_update_minor_roots(); - /* Run custom block finalisation of dead minor values */ - for (elt = caml_custom_table.base; elt < caml_custom_table.ptr; elt++){ - value v = elt->block; - if (Hd_val (v) == 0){ - /* Block was copied to the major heap: adjust GC speed numbers. */ - caml_adjust_gc_speed(elt->mem, elt->max); - }else{ - /* Block will be freed: call finalization function, if any. */ - void (*final_fun)(value) = Custom_ops_val(v)->finalize; - if (final_fun != NULL) final_fun(v); - } - } - CAML_INSTR_TIME (tmr, "minor/update_weak"); - caml_stat_minor_words += caml_young_alloc_end - caml_young_ptr; - caml_gc_clock += (double) (caml_young_alloc_end - caml_young_ptr) - / caml_minor_heap_wsz; - caml_young_ptr = caml_young_alloc_end; - clear_table ((struct generic_table *) &caml_ref_table); - clear_table ((struct generic_table *) &caml_ephe_ref_table); - clear_table ((struct generic_table *) &caml_custom_table); - caml_extra_heap_resources_minor = 0; - caml_gc_message (0x02, ">"); - caml_in_minor_collection = 0; - caml_final_empty_young (); - CAML_INSTR_TIME (tmr, "minor/finalized"); - caml_stat_promoted_words += caml_allocated_words - prev_alloc_words; - CAML_INSTR_INT ("minor/promoted#", caml_allocated_words - prev_alloc_words); - ++ caml_stat_minor_collections; - if (caml_minor_gc_end_hook != NULL) (*caml_minor_gc_end_hook) (); - }else{ - /* The minor heap is empty nothing to do. */ - caml_final_empty_young (); - } -#ifdef DEBUG - { - value *p; - for (p = caml_young_alloc_start; p < caml_young_alloc_end; ++p){ - *p = Debug_free_minor; - } - } -#endif -} - -#ifdef CAML_INSTR -extern uintnat caml_instr_alloc_jump; -#endif - -/* Do a minor collection or a slice of major collection, call finalisation - functions, etc. - Leave enough room in the minor heap to allocate at least one object. -*/ -CAMLexport void caml_gc_dispatch (void) -{ - value *trigger = caml_young_trigger; /* save old value of trigger */ -#ifdef CAML_INSTR - CAML_INSTR_SETUP(tmr, "dispatch"); - CAML_INSTR_TIME (tmr, "overhead"); - CAML_INSTR_INT ("alloc/jump#", caml_instr_alloc_jump); - caml_instr_alloc_jump = 0; -#endif - - if (trigger == caml_young_alloc_start || caml_requested_minor_gc){ - /* The minor heap is full, we must do a minor collection. */ - /* reset the pointers first because the end hooks might allocate */ - caml_requested_minor_gc = 0; - caml_young_trigger = caml_young_alloc_mid; - caml_young_limit = caml_young_trigger; - caml_empty_minor_heap (); - /* The minor heap is empty, we can start a major collection. */ - if (caml_gc_phase == Phase_idle) caml_major_collection_slice (-1); - CAML_INSTR_TIME (tmr, "dispatch/minor"); - - caml_final_do_calls (); - CAML_INSTR_TIME (tmr, "dispatch/finalizers"); - - while (caml_young_ptr - caml_young_alloc_start < Max_young_whsize){ - /* The finalizers or the hooks have filled up the minor heap, we must - repeat the minor collection. */ - caml_requested_minor_gc = 0; - caml_young_trigger = caml_young_alloc_mid; - caml_young_limit = caml_young_trigger; - caml_empty_minor_heap (); - /* The minor heap is empty, we can start a major collection. */ - if (caml_gc_phase == Phase_idle) caml_major_collection_slice (-1); - CAML_INSTR_TIME (tmr, "dispatch/finalizers_minor"); - } - } - if (trigger != caml_young_alloc_start || caml_requested_major_slice){ - /* The minor heap is half-full, do a major GC slice. */ - caml_requested_major_slice = 0; - caml_young_trigger = caml_young_alloc_start; - caml_young_limit = caml_young_trigger; - caml_major_collection_slice (-1); - CAML_INSTR_TIME (tmr, "dispatch/major"); - } -} - -/* For backward compatibility with Lablgtk: do a minor collection to - ensure that the minor heap is empty. -*/ -CAMLexport void caml_minor_collection (void) -{ - caml_requested_minor_gc = 1; - caml_gc_dispatch (); -} - -CAMLexport value caml_check_urgent_gc (value extra_root) -{ - CAMLparam1 (extra_root); - if (caml_requested_major_slice || caml_requested_minor_gc){ - CAML_INSTR_INT ("force_minor/check_urgent_gc@", 1); - caml_gc_dispatch(); - } - CAMLreturn (extra_root); -} - -static void realloc_generic_table -(struct generic_table *tbl, asize_t element_size, - char * msg_intr_int, char *msg_threshold, char *msg_growing, char *msg_error) -{ - CAMLassert (tbl->ptr == tbl->limit); - CAMLassert (tbl->limit <= tbl->end); - CAMLassert (tbl->limit >= tbl->threshold); - - if (tbl->base == NULL){ - alloc_generic_table (tbl, caml_minor_heap_wsz / 8, 256, - element_size); - }else if (tbl->limit == tbl->threshold){ - CAML_INSTR_INT (msg_intr_int, 1); - caml_gc_message (0x08, msg_threshold, 0); - tbl->limit = tbl->end; - caml_request_minor_gc (); - }else{ - asize_t sz; - asize_t cur_ptr = tbl->ptr - tbl->base; - CAMLassert (caml_requested_minor_gc); - - tbl->size *= 2; - sz = (tbl->size + tbl->reserve) * element_size; - caml_gc_message (0x08, msg_growing, (intnat) sz/1024); - tbl->base = caml_stat_resize_noexc (tbl->base, sz); - if (tbl->base == NULL){ - caml_fatal_error (msg_error); - } - tbl->end = tbl->base + (tbl->size + tbl->reserve) * element_size; - tbl->threshold = tbl->base + tbl->size * element_size; - tbl->ptr = tbl->base + cur_ptr; - tbl->limit = tbl->end; - } -} - -void caml_realloc_ref_table (struct caml_ref_table *tbl) -{ - realloc_generic_table - ((struct generic_table *) tbl, sizeof (value *), - "request_minor/realloc_ref_table@", - "ref_table threshold crossed\n", - "Growing ref_table to %" ARCH_INTNAT_PRINTF_FORMAT "dk bytes\n", - "Fatal error: ref_table overflow\n"); -} - -void caml_realloc_ephe_ref_table (struct caml_ephe_ref_table *tbl) -{ - realloc_generic_table - ((struct generic_table *) tbl, sizeof (struct caml_ephe_ref_elt), - "request_minor/realloc_ephe_ref_table@", - "ephe_ref_table threshold crossed\n", - "Growing ephe_ref_table to %" ARCH_INTNAT_PRINTF_FORMAT "dk bytes\n", - "Fatal error: ephe_ref_table overflow\n"); -} - -void caml_realloc_custom_table (struct caml_custom_table *tbl) -{ - realloc_generic_table - ((struct generic_table *) tbl, sizeof (struct caml_custom_elt), - "request_minor/realloc_custom_table@", - "custom_table threshold crossed\n", - "Growing custom_table to %" ARCH_INTNAT_PRINTF_FORMAT "dk bytes\n", - "Fatal error: custom_table overflow\n"); -} diff --git a/byterun/misc.c b/byterun/misc.c deleted file mode 100644 index 46e40992..00000000 --- a/byterun/misc.c +++ /dev/null @@ -1,276 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -#include -#include -#include -#include "caml/config.h" -#include "caml/misc.h" -#include "caml/memory.h" -#include "caml/osdeps.h" -#include "caml/version.h" - -caml_timing_hook caml_major_slice_begin_hook = NULL; -caml_timing_hook caml_major_slice_end_hook = NULL; -caml_timing_hook caml_minor_gc_begin_hook = NULL; -caml_timing_hook caml_minor_gc_end_hook = NULL; -caml_timing_hook caml_finalise_begin_hook = NULL; -caml_timing_hook caml_finalise_end_hook = NULL; - -#ifdef DEBUG - -int caml_failed_assert (char * expr, char * file, int line) -{ - fprintf (stderr, "file %s; line %d ### Assertion failed: %s\n", - file, line, expr); - fflush (stderr); - abort(); -} - -void caml_set_fields (value v, unsigned long start, unsigned long filler) -{ - mlsize_t i; - for (i = start; i < Wosize_val (v); i++){ - Field (v, i) = (value) filler; - } -} - -#endif /* DEBUG */ - -uintnat caml_verb_gc = 0; - -void caml_gc_message (int level, char *msg, ...) -{ - if ((caml_verb_gc & level) != 0){ - va_list ap; - va_start(ap, msg); - vfprintf (stderr, msg, ap); - va_end(ap); - fflush (stderr); - } -} - -CAMLexport void caml_fatal_error (char *msg) -{ - fprintf (stderr, "%s", msg); - exit(2); -} - -CAMLexport void caml_fatal_error_arg (char *fmt, char *arg) -{ - fprintf (stderr, fmt, arg); - exit(2); -} - -CAMLexport void caml_fatal_error_arg2 (char *fmt1, char *arg1, - char *fmt2, char *arg2) -{ - fprintf (stderr, fmt1, arg1); - fprintf (stderr, fmt2, arg2); - exit(2); -} - -/* If you change the caml_ext_table* functions, also update - asmrun/spacetime.c:find_trie_node_from_libunwind. */ - -void caml_ext_table_init(struct ext_table * tbl, int init_capa) -{ - tbl->size = 0; - tbl->capacity = init_capa; - tbl->contents = caml_stat_alloc(sizeof(void *) * init_capa); -} - -int caml_ext_table_add(struct ext_table * tbl, caml_stat_block data) -{ - int res; - if (tbl->size >= tbl->capacity) { - tbl->capacity *= 2; - tbl->contents = - caml_stat_resize(tbl->contents, sizeof(void *) * tbl->capacity); - } - res = tbl->size; - tbl->contents[res] = data; - tbl->size++; - return res; -} - -void caml_ext_table_remove(struct ext_table * tbl, caml_stat_block data) -{ - int i; - for (i = 0; i < tbl->size; i++) { - if (tbl->contents[i] == data) { - caml_stat_free(tbl->contents[i]); - memmove(&tbl->contents[i], &tbl->contents[i + 1], - (tbl->size - i - 1) * sizeof(void *)); - tbl->size--; - } - } -} - -void caml_ext_table_clear(struct ext_table * tbl, int free_entries) -{ - int i; - if (free_entries) { - for (i = 0; i < tbl->size; i++) caml_stat_free(tbl->contents[i]); - } - tbl->size = 0; -} - -void caml_ext_table_free(struct ext_table * tbl, int free_entries) -{ - caml_ext_table_clear(tbl, free_entries); - caml_stat_free(tbl->contents); -} - -/* Integer arithmetic with overflow detection */ - -#if ! (__GNUC__ >= 5 || Caml_has_builtin(__builtin_mul_overflow)) -CAMLexport int caml_umul_overflow(uintnat a, uintnat b, uintnat * res) -{ -#define HALF_SIZE (sizeof(uintnat) * 4) -#define HALF_MASK (((uintnat)1 << HALF_SIZE) - 1) -#define LOW_HALF(x) ((x) & HALF_MASK) -#define HIGH_HALF(x) ((x) >> HALF_SIZE) - /* Cut in half words */ - uintnat al = LOW_HALF(a); - uintnat ah = HIGH_HALF(a); - uintnat bl = LOW_HALF(b); - uintnat bh = HIGH_HALF(b); - /* Exact product is: - al * bl - + ah * bl << HALF_SIZE - + al * bh << HALF_SIZE - + ah * bh << 2*HALF_SIZE - Overflow occurs if: - ah * bh is not 0, i.e. ah != 0 and bh != 0 - OR ah * bl has high half != 0 - OR al * bh has high half != 0 - OR the sum al * bl + LOW_HALF(ah * bl) << HALF_SIZE - + LOW_HALF(al * bh) << HALF_SIZE overflows. - This sum is equal to p = (a * b) modulo word size. */ - uintnat p = a * b; - uintnat p1 = al * bh; - uintnat p2 = ah * bl; - *res = p; - if (ah == 0 && bh == 0) return 0; - if (ah != 0 && bh != 0) return 1; - if (HIGH_HALF(p1) != 0 || HIGH_HALF(p2) != 0) return 1; - p1 <<= HALF_SIZE; - p2 <<= HALF_SIZE; - p1 += p2; - if (p < p1 || p1 < p2) return 1; /* overflow in sums */ - return 0; -#undef HALF_SIZE -#undef HALF_MASK -#undef LOW_HALF -#undef HIGH_HALF -} -#endif - -/* Runtime warnings */ - -uintnat caml_runtime_warnings = 0; -static int caml_runtime_warnings_first = 1; - -int caml_runtime_warnings_active(void) -{ - if (!caml_runtime_warnings) return 0; - if (caml_runtime_warnings_first) { - fprintf(stderr, "[ocaml] (use Sys.enable_runtime_warnings to control " - "these warnings)\n"); - caml_runtime_warnings_first = 0; - } - return 1; -} - -#ifdef CAML_INSTR -/* Timers for profiling GC and allocation (experimental, Linux-only) */ - -#include -#include -#include - -struct CAML_INSTR_BLOCK *CAML_INSTR_LOG = NULL; -intnat CAML_INSTR_STARTTIME, CAML_INSTR_STOPTIME; - -#define Get_time(p,i) ((p)->ts[(i)].tv_nsec + 1000000000 * (p)->ts[(i)].tv_sec) - -void CAML_INSTR_INIT (void) -{ - char *s; - - CAML_INSTR_STARTTIME = 0; - s = caml_secure_getenv ("OCAML_INSTR_START"); - if (s != NULL) CAML_INSTR_STARTTIME = atol (s); - CAML_INSTR_STOPTIME = LONG_MAX; - s = caml_secure_getenv ("OCAML_INSTR_STOP"); - if (s != NULL) CAML_INSTR_STOPTIME = atol (s); -} - -void CAML_INSTR_ATEXIT (void) -{ - int i; - struct CAML_INSTR_BLOCK *p, *prev, *next; - FILE *f = NULL; - char *fname; - - fname = caml_secure_getenv ("OCAML_INSTR_FILE"); - if (fname != NULL){ - char *mode = "a"; - char buf [1000]; - char *name = fname; - - if (name[0] == '@'){ - snprintf (buf, sizeof(buf), "%s.%d", name + 1, getpid ()); - name = buf; - } - if (name[0] == '+'){ - mode = "a"; - name = name + 1; - }else if (name [0] == '>' || name[0] == '-'){ - mode = "w"; - name = name + 1; - } - f = fopen (name, mode); - } - - if (f != NULL){ - /* reverse the list */ - prev = NULL; - p = CAML_INSTR_LOG; - while (p != NULL){ - next = p->next; - p->next = prev; - prev = p; - p = next; - } - CAML_INSTR_LOG = prev; - fprintf (f, "==== OCAML INSTRUMENTATION DATA %s\n", OCAML_VERSION_STRING); - for (p = CAML_INSTR_LOG; p != NULL; p = p->next){ - for (i = 0; i < p->index; i++){ - fprintf (f, "@@ %19ld %19ld %s\n", - (long) Get_time (p, i), (long) Get_time(p, i+1), p->tag[i+1]); - } - if (p->tag[0][0] != '\000'){ - fprintf (f, "@@ %19ld %19ld %s\n", - (long) Get_time (p, 0), (long) Get_time(p, p->index), p->tag[0]); - } - } - fclose (f); - } -} -#endif /* CAML_INSTR */ diff --git a/byterun/printexc.c b/byterun/printexc.c deleted file mode 100644 index 735c2994..00000000 --- a/byterun/printexc.c +++ /dev/null @@ -1,155 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Print an uncaught exception and abort */ - -#include -#include -#include -#include "caml/backtrace.h" -#include "caml/callback.h" -#include "caml/debugger.h" -#include "caml/fail.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/printexc.h" -#include "caml/memory.h" - -struct stringbuf { - char * ptr; - char * end; - char data[256]; -}; - -static void add_char(struct stringbuf *buf, char c) -{ - if (buf->ptr < buf->end) *(buf->ptr++) = c; -} - -static void add_string(struct stringbuf *buf, const char *s) -{ - int len = strlen(s); - if (buf->ptr + len > buf->end) len = buf->end - buf->ptr; - if (len > 0) memmove(buf->ptr, s, len); - buf->ptr += len; -} - -CAMLexport char * caml_format_exception(value exn) -{ - mlsize_t start, i; - value bucket, v; - struct stringbuf buf; - char intbuf[64]; - char * res; - - buf.ptr = buf.data; - buf.end = buf.data + sizeof(buf.data) - 1; - if (Tag_val(exn) == 0) { - add_string(&buf, String_val(Field(Field(exn, 0), 0))); - /* Check for exceptions in the style of Match_failure and Assert_failure */ - if (Wosize_val(exn) == 2 && - Is_block(Field(exn, 1)) && - Tag_val(Field(exn, 1)) == 0 && - caml_is_special_exception(Field(exn, 0))) { - bucket = Field(exn, 1); - start = 0; - } else { - bucket = exn; - start = 1; - } - add_char(&buf, '('); - for (i = start; i < Wosize_val(bucket); i++) { - if (i > start) add_string(&buf, ", "); - v = Field(bucket, i); - if (Is_long(v)) { - snprintf(intbuf, sizeof(intbuf), - "%" ARCH_INTNAT_PRINTF_FORMAT "d", Long_val(v)); - add_string(&buf, intbuf); - } else if (Tag_val(v) == String_tag) { - add_char(&buf, '"'); - add_string(&buf, String_val(v)); - add_char(&buf, '"'); - } else { - add_char(&buf, '_'); - } - } - add_char(&buf, ')'); - } else - add_string(&buf, String_val(Field(exn, 0))); - - *buf.ptr = 0; /* Terminate string */ - i = buf.ptr - buf.data + 1; - res = caml_stat_alloc_noexc(i); - if (res == NULL) return NULL; - memmove(res, buf.data, i); - return res; -} - - -#ifdef NATIVE_CODE -# define DEBUGGER_IN_USE 0 -#else -# define DEBUGGER_IN_USE caml_debugger_in_use -#endif - -/* Default C implementation in case the OCaml one is not registered. */ -static void default_fatal_uncaught_exception(value exn) -{ - char * msg; - value * at_exit; - int saved_backtrace_active, saved_backtrace_pos; - - /* Build a string representation of the exception */ - msg = caml_format_exception(exn); - /* Perform "at_exit" processing, ignoring all exceptions that may - be triggered by this */ - saved_backtrace_active = caml_backtrace_active; - saved_backtrace_pos = caml_backtrace_pos; - caml_backtrace_active = 0; - at_exit = caml_named_value("Pervasives.do_at_exit"); - if (at_exit != NULL) caml_callback_exn(*at_exit, Val_unit); - caml_backtrace_active = saved_backtrace_active; - caml_backtrace_pos = saved_backtrace_pos; - /* Display the uncaught exception */ - fprintf(stderr, "Fatal error: exception %s\n", msg); - caml_stat_free(msg); - /* Display the backtrace if available */ - if (caml_backtrace_active && !DEBUGGER_IN_USE) - caml_print_exception_backtrace(); -} - -int caml_abort_on_uncaught_exn = 0; /* see afl.c */ - -void caml_fatal_uncaught_exception(value exn) -{ - value *handle_uncaught_exception; - - handle_uncaught_exception = - caml_named_value("Printexc.handle_uncaught_exception"); - if (handle_uncaught_exception != NULL) - /* [Printexc.handle_uncaught_exception] does not raise exception. */ - caml_callback2(*handle_uncaught_exception, exn, Val_bool(DEBUGGER_IN_USE)); - else - default_fatal_uncaught_exception(exn); - /* Terminate the process */ - if (caml_abort_on_uncaught_exn) { - abort(); - } else { - CAML_SYS_EXIT(2); - exit(2); /* Second exit needed for the Noreturn flag */ - } -} diff --git a/byterun/roots.c b/byterun/roots.c deleted file mode 100644 index 1445495a..00000000 --- a/byterun/roots.c +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* To walk the memory roots for garbage collection */ - -#include "caml/finalise.h" -#include "caml/globroots.h" -#include "caml/major_gc.h" -#include "caml/memory.h" -#include "caml/minor_gc.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/roots.h" -#include "caml/stacks.h" - -CAMLexport struct caml__roots_block *caml_local_roots = NULL; - -CAMLexport void (*caml_scan_roots_hook) (scanning_action f) = NULL; - -/* FIXME should rename to [caml_oldify_minor_roots] and synchronise with - asmrun/roots.c */ -/* Call [caml_oldify_one] on (at least) all the roots that point to the minor - heap. */ -void caml_oldify_local_roots (void) -{ - register value * sp; - struct caml__roots_block *lr; - intnat i, j; - - /* The stack */ - for (sp = caml_extern_sp; sp < caml_stack_high; sp++) { - caml_oldify_one (*sp, sp); - } - /* Local C roots */ /* FIXME do the old-frame trick ? */ - for (lr = caml_local_roots; lr != NULL; lr = lr->next) { - for (i = 0; i < lr->ntables; i++){ - for (j = 0; j < lr->nitems; j++){ - sp = &(lr->tables[i][j]); - caml_oldify_one (*sp, sp); - } - } - } - /* Global C roots */ - caml_scan_global_young_roots(&caml_oldify_one); - /* Finalised values */ - caml_final_oldify_young_roots (); - /* Hook */ - if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(&caml_oldify_one); -} - -/* Call [caml_darken] on all roots */ - -void caml_darken_all_roots_start (void) -{ - caml_do_roots (caml_darken, 1); -} - -uintnat caml_incremental_roots_count = 1; - -intnat caml_darken_all_roots_slice (intnat work) -{ - return work; -} - -/* Note, in byte-code there is only one global root, so [do_globals] is - ignored and [caml_darken_all_roots_slice] does nothing. */ -void caml_do_roots (scanning_action f, int do_globals) -{ - CAML_INSTR_SETUP (tmr, "major_roots"); - /* Global variables */ - f(caml_global_data, &caml_global_data); - CAML_INSTR_TIME (tmr, "major_roots/global"); - /* The stack and the local C roots */ - caml_do_local_roots(f, caml_extern_sp, caml_stack_high, caml_local_roots); - CAML_INSTR_TIME (tmr, "major_roots/local"); - /* Global C roots */ - caml_scan_global_roots(f); - CAML_INSTR_TIME (tmr, "major_roots/C"); - /* Finalised values */ - caml_final_do_roots (f); - CAML_INSTR_TIME (tmr, "major_roots/finalised"); - /* Hook */ - if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(f); - CAML_INSTR_TIME (tmr, "major_roots/hook"); -} - -CAMLexport void caml_do_local_roots (scanning_action f, value *stack_low, - value *stack_high, - struct caml__roots_block *local_roots) -{ - register value * sp; - struct caml__roots_block *lr; - int i, j; - - for (sp = stack_low; sp < stack_high; sp++) { - f (*sp, sp); - } - for (lr = local_roots; lr != NULL; lr = lr->next) { - for (i = 0; i < lr->ntables; i++){ - for (j = 0; j < lr->nitems; j++){ - sp = &(lr->tables[i][j]); - f (*sp, sp); - } - } - } -} diff --git a/byterun/signals.c b/byterun/signals.c deleted file mode 100644 index 15addf1b..00000000 --- a/byterun/signals.c +++ /dev/null @@ -1,398 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Signal handling, code common to the bytecode and native systems */ - -#include -#include -#include "caml/alloc.h" -#include "caml/callback.h" -#include "caml/config.h" -#include "caml/fail.h" -#include "caml/memory.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/roots.h" -#include "caml/signals.h" -#include "caml/signals_machdep.h" -#include "caml/sys.h" - -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) -#include "caml/spacetime.h" -#endif - -#ifndef NSIG -#define NSIG 64 -#endif - -/* The set of pending signals (received but not yet processed) */ - -CAMLexport intnat volatile caml_signals_are_pending = 0; -CAMLexport intnat volatile caml_pending_signals[NSIG]; - -/* Execute all pending signals */ - -void caml_process_pending_signals(void) -{ - int i; - - if (caml_signals_are_pending) { - caml_signals_are_pending = 0; - for (i = 0; i < NSIG; i++) { - if (caml_pending_signals[i]) { - caml_pending_signals[i] = 0; - caml_execute_signal(i, 0); - } - } - } -} - -/* Record the delivery of a signal, and arrange for it to be processed - as soon as possible: - - in bytecode: via caml_something_to_do, processed in caml_process_event - - in native-code: by playing with the allocation limit, processed - in caml_garbage_collection -*/ - -void caml_record_signal(int signal_number) -{ - caml_pending_signals[signal_number] = 1; - caml_signals_are_pending = 1; -#ifndef NATIVE_CODE - caml_something_to_do = 1; -#else - caml_young_limit = caml_young_alloc_end; -#endif -} - -/* Management of blocking sections. */ - -static intnat volatile caml_async_signal_mode = 0; - -static void caml_enter_blocking_section_default(void) -{ - CAMLassert (caml_async_signal_mode == 0); - caml_async_signal_mode = 1; -} - -static void caml_leave_blocking_section_default(void) -{ - CAMLassert (caml_async_signal_mode == 1); - caml_async_signal_mode = 0; -} - -static int caml_try_leave_blocking_section_default(void) -{ - intnat res; - Read_and_clear(res, caml_async_signal_mode); - return res; -} - -CAMLexport void (*caml_enter_blocking_section_hook)(void) = - caml_enter_blocking_section_default; -CAMLexport void (*caml_leave_blocking_section_hook)(void) = - caml_leave_blocking_section_default; -CAMLexport int (*caml_try_leave_blocking_section_hook)(void) = - caml_try_leave_blocking_section_default; - -CAMLexport void caml_enter_blocking_section(void) -{ - while (1){ - /* Process all pending signals now */ - caml_process_pending_signals(); - caml_enter_blocking_section_hook (); - /* Check again for pending signals. - If none, done; otherwise, try again */ - if (! caml_signals_are_pending) break; - caml_leave_blocking_section_hook (); - } -} - -CAMLexport void caml_leave_blocking_section(void) -{ - int saved_errno; - /* Save the value of errno (PR#5982). */ - saved_errno = errno; - caml_leave_blocking_section_hook (); - caml_process_pending_signals(); - errno = saved_errno; -} - -/* Execute a signal handler immediately */ - -static value caml_signal_handlers = 0; - -void caml_execute_signal(int signal_number, int in_signal_handler) -{ - value res; - value handler; -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - void* saved_spacetime_trie_node_ptr; -#endif -#ifdef POSIX_SIGNALS - sigset_t nsigs, sigs; - /* Block the signal before executing the handler, and record in sigs - the original signal mask */ - sigemptyset(&nsigs); - sigaddset(&nsigs, signal_number); - sigprocmask(SIG_BLOCK, &nsigs, &sigs); -#endif -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - /* We record the signal handler's execution separately, in the same - trie used for finalisers. */ - saved_spacetime_trie_node_ptr - = caml_spacetime_trie_node_ptr; - caml_spacetime_trie_node_ptr - = caml_spacetime_finaliser_trie_root; -#endif -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - /* Handled action may have no associated handler, which we interpret - as meaning the signal should be handled by a call to exit. This is - is used to allow spacetime profiles to be completed on interrupt */ - if (caml_signal_handlers == 0) { - res = caml_sys_exit(Val_int(2)); - } else { - handler = Field(caml_signal_handlers, signal_number); - if (!Is_block(handler)) { - res = caml_sys_exit(Val_int(2)); - } else { -#else - handler = Field(caml_signal_handlers, signal_number); -#endif - res = caml_callback_exn( - handler, - Val_int(caml_rev_convert_signal_number(signal_number))); -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - } - } - caml_spacetime_trie_node_ptr = saved_spacetime_trie_node_ptr; -#endif -#ifdef POSIX_SIGNALS - if (! in_signal_handler) { - /* Restore the original signal mask */ - sigprocmask(SIG_SETMASK, &sigs, NULL); - } else if (Is_exception_result(res)) { - /* Restore the original signal mask and unblock the signal itself */ - sigdelset(&sigs, signal_number); - sigprocmask(SIG_SETMASK, &sigs, NULL); - } -#endif - if (Is_exception_result(res)) caml_raise(Extract_exception(res)); -} - -/* Arrange for a garbage collection to be performed as soon as possible */ - -int volatile caml_requested_major_slice = 0; -int volatile caml_requested_minor_gc = 0; - -void caml_request_major_slice (void) -{ - caml_requested_major_slice = 1; -#ifndef NATIVE_CODE - caml_something_to_do = 1; -#else - caml_young_limit = caml_young_alloc_end; - /* This is only moderately effective on ports that cache [caml_young_limit] - in a register, since [caml_modify] is called directly, not through - [caml_c_call], so it may take a while before the register is reloaded - from [caml_young_limit]. */ -#endif -} - -void caml_request_minor_gc (void) -{ - caml_requested_minor_gc = 1; -#ifndef NATIVE_CODE - caml_something_to_do = 1; -#else - caml_young_limit = caml_young_alloc_end; - /* Same remark as above in [caml_request_major_slice]. */ -#endif -} - -/* OS-independent numbering of signals */ - -#ifndef SIGABRT -#define SIGABRT -1 -#endif -#ifndef SIGALRM -#define SIGALRM -1 -#endif -#ifndef SIGFPE -#define SIGFPE -1 -#endif -#ifndef SIGHUP -#define SIGHUP -1 -#endif -#ifndef SIGILL -#define SIGILL -1 -#endif -#ifndef SIGINT -#define SIGINT -1 -#endif -#ifndef SIGKILL -#define SIGKILL -1 -#endif -#ifndef SIGPIPE -#define SIGPIPE -1 -#endif -#ifndef SIGQUIT -#define SIGQUIT -1 -#endif -#ifndef SIGSEGV -#define SIGSEGV -1 -#endif -#ifndef SIGTERM -#define SIGTERM -1 -#endif -#ifndef SIGUSR1 -#define SIGUSR1 -1 -#endif -#ifndef SIGUSR2 -#define SIGUSR2 -1 -#endif -#ifndef SIGCHLD -#define SIGCHLD -1 -#endif -#ifndef SIGCONT -#define SIGCONT -1 -#endif -#ifndef SIGSTOP -#define SIGSTOP -1 -#endif -#ifndef SIGTSTP -#define SIGTSTP -1 -#endif -#ifndef SIGTTIN -#define SIGTTIN -1 -#endif -#ifndef SIGTTOU -#define SIGTTOU -1 -#endif -#ifndef SIGVTALRM -#define SIGVTALRM -1 -#endif -#ifndef SIGPROF -#define SIGPROF -1 -#endif -#ifndef SIGBUS -#define SIGBUS -1 -#endif -#ifndef SIGPOLL -#define SIGPOLL -1 -#endif -#ifndef SIGSYS -#define SIGSYS -1 -#endif -#ifndef SIGTRAP -#define SIGTRAP -1 -#endif -#ifndef SIGURG -#define SIGURG -1 -#endif -#ifndef SIGXCPU -#define SIGXCPU -1 -#endif -#ifndef SIGXFSZ -#define SIGXFSZ -1 -#endif - -static int posix_signals[] = { - SIGABRT, SIGALRM, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGKILL, SIGPIPE, - SIGQUIT, SIGSEGV, SIGTERM, SIGUSR1, SIGUSR2, SIGCHLD, SIGCONT, - SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGVTALRM, SIGPROF, SIGBUS, - SIGPOLL, SIGSYS, SIGTRAP, SIGURG, SIGXCPU, SIGXFSZ -}; - -CAMLexport int caml_convert_signal_number(int signo) -{ - if (signo < 0 && signo >= -(sizeof(posix_signals) / sizeof(int))) - return posix_signals[-signo-1]; - else - return signo; -} - -CAMLexport int caml_rev_convert_signal_number(int signo) -{ - int i; - for (i = 0; i < sizeof(posix_signals) / sizeof(int); i++) - if (signo == posix_signals[i]) return -i - 1; - return signo; -} - -/* Installation of a signal handler (as per [Sys.signal]) */ - -CAMLprim value caml_install_signal_handler(value signal_number, value action) -{ - CAMLparam2 (signal_number, action); - CAMLlocal1 (res); - int sig, act, oldact; - - sig = caml_convert_signal_number(Int_val(signal_number)); - if (sig < 0 || sig >= NSIG) - caml_invalid_argument("Sys.signal: unavailable signal"); - switch(action) { - case Val_int(0): /* Signal_default */ - act = 0; - break; - case Val_int(1): /* Signal_ignore */ - act = 1; - break; - default: /* Signal_handle */ - act = 2; - break; - } - oldact = caml_set_signal_action(sig, act); - switch (oldact) { - case 0: /* was Signal_default */ - res = Val_int(0); - break; - case 1: /* was Signal_ignore */ - res = Val_int(1); - break; - case 2: /* was Signal_handle */ - #if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - /* Handled action may have no associated handler - which we treat as Signal_default */ - if (caml_signal_handlers == 0) { - res = Val_int(0); - } else { - if (!Is_block(Field(caml_signal_handlers, sig))) { - res = Val_int(0); - } else { - res = caml_alloc_small (1, 0); - Field(res, 0) = Field(caml_signal_handlers, sig); - } - } - #else - res = caml_alloc_small (1, 0); - Field(res, 0) = Field(caml_signal_handlers, sig); - #endif - break; - default: /* error in caml_set_signal_action */ - caml_sys_error(NO_ARG); - } - if (Is_block(action)) { - if (caml_signal_handlers == 0) { - caml_signal_handlers = caml_alloc(NSIG, 0); - caml_register_global_root(&caml_signal_handlers); - } - caml_modify(&Field(caml_signal_handlers, sig), Field(action, 0)); - } - caml_process_pending_signals(); - CAMLreturn (res); -} diff --git a/byterun/startup.c b/byterun/startup.c deleted file mode 100644 index 037f30d0..00000000 --- a/byterun/startup.c +++ /dev/null @@ -1,531 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Start-up code */ - -#include -#include -#include -#include -#include "caml/config.h" -#ifdef HAS_UNISTD -#include -#endif -#ifdef _WIN32 -#include -#endif -#include "caml/alloc.h" -#include "caml/backtrace.h" -#include "caml/callback.h" -#include "caml/custom.h" -#include "caml/debugger.h" -#include "caml/dynlink.h" -#include "caml/exec.h" -#include "caml/fail.h" -#include "caml/fix_code.h" -#include "caml/freelist.h" -#include "caml/gc_ctrl.h" -#include "caml/instrtrace.h" -#include "caml/interp.h" -#include "caml/intext.h" -#include "caml/io.h" -#include "caml/memory.h" -#include "caml/minor_gc.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/osdeps.h" -#include "caml/prims.h" -#include "caml/printexc.h" -#include "caml/reverse.h" -#include "caml/signals.h" -#include "caml/stacks.h" -#include "caml/sys.h" -#include "caml/startup.h" -#include "caml/startup_aux.h" -#include "caml/version.h" - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -#ifndef SEEK_END -#define SEEK_END 2 -#endif - -/* Read the trailer of a bytecode file */ - -static void fixup_endianness_trailer(uint32_t * p) -{ -#ifndef ARCH_BIG_ENDIAN - Reverse_32(p, p); -#endif -} - -static int read_trailer(int fd, struct exec_trailer *trail) -{ - if (lseek(fd, (long) -TRAILER_SIZE, SEEK_END) == -1) - return BAD_BYTECODE; - if (read(fd, (char *) trail, TRAILER_SIZE) < TRAILER_SIZE) - return BAD_BYTECODE; - fixup_endianness_trailer(&trail->num_sections); - if (strncmp(trail->magic, EXEC_MAGIC, 12) == 0) - return 0; - else - return BAD_BYTECODE; -} - -int caml_attempt_open(char_os **name, struct exec_trailer *trail, - int do_open_script) -{ - char_os * truename; - int fd; - int err; - char buf [2], * u8; - - truename = caml_search_exe_in_path(*name); - u8 = caml_stat_strdup_of_os(truename); - caml_gc_message(0x100, "Opening bytecode executable %s\n", u8); - caml_stat_free(u8); - fd = open_os(truename, O_RDONLY | O_BINARY); - if (fd == -1) { - caml_stat_free(truename); - caml_gc_message(0x100, "Cannot open file\n"); - return FILE_NOT_FOUND; - } - if (!do_open_script) { - err = read (fd, buf, 2); - if (err < 2 || (buf [0] == '#' && buf [1] == '!')) { - close(fd); - caml_stat_free(truename); - caml_gc_message(0x100, "Rejected #! script\n"); - return BAD_BYTECODE; - } - } - err = read_trailer(fd, trail); - if (err != 0) { - close(fd); - caml_stat_free(truename); - caml_gc_message(0x100, "Not a bytecode executable\n"); - return err; - } - *name = truename; - return fd; -} - -/* Read the section descriptors */ - -void caml_read_section_descriptors(int fd, struct exec_trailer *trail) -{ - int toc_size, i; - - toc_size = trail->num_sections * 8; - trail->section = caml_stat_alloc(toc_size); - lseek(fd, - (long) (TRAILER_SIZE + toc_size), SEEK_END); - if (read(fd, (char *) trail->section, toc_size) != toc_size) - caml_fatal_error("Fatal error: cannot read section table\n"); - /* Fixup endianness of lengths */ - for (i = 0; i < trail->num_sections; i++) - fixup_endianness_trailer(&(trail->section[i].len)); -} - -/* Position fd at the beginning of the section having the given name. - Return the length of the section data in bytes, or -1 if no section - found with that name. */ - -int32_t caml_seek_optional_section(int fd, struct exec_trailer *trail, - char *name) -{ - long ofs; - int i; - - ofs = TRAILER_SIZE + trail->num_sections * 8; - for (i = trail->num_sections - 1; i >= 0; i--) { - ofs += trail->section[i].len; - if (strncmp(trail->section[i].name, name, 4) == 0) { - lseek(fd, -ofs, SEEK_END); - return trail->section[i].len; - } - } - return -1; -} - -/* Position fd at the beginning of the section having the given name. - Return the length of the section data in bytes. */ - -int32_t caml_seek_section(int fd, struct exec_trailer *trail, char *name) -{ - int32_t len = caml_seek_optional_section(fd, trail, name); - if (len == -1) - caml_fatal_error_arg("Fatal_error: section `%s' is missing\n", name); - return len; -} - -/* Read and return the contents of the section having the given name. - Add a terminating 0. Return NULL if no such section. */ - -static char * read_section(int fd, struct exec_trailer *trail, char *name) -{ - int32_t len; - char * data; - - len = caml_seek_optional_section(fd, trail, name); - if (len == -1) return NULL; - data = caml_stat_alloc(len + 1); - if (read(fd, data, len) != len) - caml_fatal_error_arg("Fatal error: error reading section %s\n", name); - data[len] = 0; - return data; -} - -#ifdef _WIN32 - -static char_os * read_section_to_os(int fd, struct exec_trailer *trail, char *name) -{ - int32_t len, wlen; - char * data; - wchar_t * wdata; - - len = caml_seek_optional_section(fd, trail, name); - if (len == -1) return NULL; - data = caml_stat_alloc(len + 1); - if (read(fd, data, len) != len) - caml_fatal_error_arg("Fatal error: error reading section %s\n", name); - data[len] = 0; - wlen = win_multi_byte_to_wide_char(data, len, NULL, 0); - wdata = caml_stat_alloc((wlen + 1)*sizeof(wchar_t)); - win_multi_byte_to_wide_char(data, len, wdata, wlen); - wdata[wlen] = 0; - caml_stat_free(data); - return wdata; -} - -#else - -#define read_section_to_os read_section - -#endif - -/* Invocation of ocamlrun: 4 cases. - - 1. runtime + bytecode - user types: ocamlrun [options] bytecode args... - arguments: ocamlrun [options] bytecode args... - - 2. bytecode script - user types: bytecode args... - 2a (kernel 1) arguments: ocamlrun ./bytecode args... - 2b (kernel 2) arguments: bytecode bytecode args... - - 3. concatenated runtime and bytecode - user types: composite args... - arguments: composite args... - -Algorithm: - 1- If argument 0 is a valid byte-code file that does not start with #!, - then we are in case 3 and we pass the same command line to the - OCaml program. - 2- In all other cases, we parse the command line as: - (whatever) [options] bytecode args... - and we strip "(whatever) [options]" from the command line. - -*/ - -/* Parse options on the command line */ - -static int parse_command_line(char_os **argv) -{ - int i, j; - - for(i = 1; argv[i] != NULL && argv[i][0] == _T('-'); i++) { - switch(argv[i][1]) { - case _T('t'): - ++ caml_trace_level; /* ignored unless DEBUG mode */ - break; - case _T('v'): - if (!strcmp_os (argv[i], _T("-version"))){ - printf ("The OCaml runtime, version " OCAML_VERSION_STRING "\n"); - exit (0); - }else if (!strcmp_os (argv[i], _T("-vnum"))){ - printf (OCAML_VERSION_STRING "\n"); - exit (0); - }else{ - caml_verb_gc = 0x001+0x004+0x008+0x010+0x020; - } - break; - case _T('p'): - for (j = 0; caml_names_of_builtin_cprim[j] != NULL; j++) - printf("%s\n", caml_names_of_builtin_cprim[j]); - exit(0); - break; - case _T('b'): - caml_record_backtrace(Val_true); - break; - case _T('I'): - if (argv[i + 1] != NULL) { - caml_ext_table_add(&caml_shared_libs_path, argv[i + 1]); - i++; - } - break; - default: - caml_fatal_error_arg("Unknown option %s.\n", caml_stat_strdup_of_os(argv[i])); - } - } - return i; -} - -extern void caml_init_ieee_floats (void); - -#ifdef _WIN32 -extern void caml_signal_thread(void * lpParam); -#endif - -#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L - -/* PR 4887: avoid crash box of windows runtime on some system calls */ -extern void caml_install_invalid_parameter_handler(); - -#endif - -extern int caml_ensure_spacetime_dot_o_is_included; - -/* Main entry point when loading code from a file */ - -CAMLexport void caml_main(char_os **argv) -{ - int fd, pos; - struct exec_trailer trail; - struct channel * chan; - value res; - char * req_prims; - char_os * shared_lib_path, * shared_libs; - char_os * exe_name, * proc_self_exe; - - caml_ensure_spacetime_dot_o_is_included++; - - /* Determine options */ -#ifdef DEBUG - caml_verb_gc = 0x3F; -#endif - caml_parse_ocamlrunparam(); -#ifdef DEBUG - caml_gc_message (-1, "### OCaml runtime: debug mode ###\n"); -#endif - if (!caml_startup_aux(/* pooling */ caml_cleanup_on_exit)) - return; - - /* Machine-dependent initialization of the floating-point hardware - so that it behaves as much as possible as specified in IEEE */ - caml_init_ieee_floats(); -#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L - caml_install_invalid_parameter_handler(); -#endif - caml_init_custom_operations(); - caml_ext_table_init(&caml_shared_libs_path, 8); - caml_external_raise = NULL; - - /* Determine position of bytecode file */ - pos = 0; - - /* First, try argv[0] (when ocamlrun is called by a bytecode program) */ - exe_name = argv[0]; - fd = caml_attempt_open(&exe_name, &trail, 0); - - /* Little grasshopper wonders why we do that at all, since - "The current executable is ocamlrun itself, it's never a bytecode - program". Little grasshopper "ocamlc -custom" in mind should keep. - With -custom, we have an executable that is ocamlrun itself - concatenated with the bytecode. So, if the attempt with argv[0] - failed, it is worth trying again with executable_name. */ - if (fd < 0 && (proc_self_exe = caml_executable_name()) != NULL) { - exe_name = proc_self_exe; - fd = caml_attempt_open(&exe_name, &trail, 0); - } - - if (fd < 0) { - pos = parse_command_line(argv); - if (argv[pos] == 0) - caml_fatal_error("No bytecode file specified.\n"); - exe_name = argv[pos]; - fd = caml_attempt_open(&exe_name, &trail, 1); - switch(fd) { - case FILE_NOT_FOUND: - caml_fatal_error_arg("Fatal error: cannot find file '%s'\n", caml_stat_strdup_of_os(argv[pos])); - break; - case BAD_BYTECODE: - caml_fatal_error_arg( - "Fatal error: the file '%s' is not a bytecode executable file\n", - caml_stat_strdup_of_os(exe_name)); - break; - } - } - /* Read the table of contents (section descriptors) */ - caml_read_section_descriptors(fd, &trail); - /* Initialize the abstract machine */ - caml_init_gc (caml_init_minor_heap_wsz, caml_init_heap_wsz, - caml_init_heap_chunk_sz, caml_init_percent_free, - caml_init_max_percent_free, caml_init_major_window); - caml_init_stack (caml_init_max_stack_wsz); - caml_init_atom_table(); - caml_init_backtrace(); - /* Initialize the interpreter */ - caml_interprete(NULL, 0); - /* Initialize the debugger, if needed */ - caml_debugger_init(); - /* Load the code */ - caml_code_size = caml_seek_section(fd, &trail, "CODE"); - caml_load_code(fd, caml_code_size); - caml_init_debug_info(); - /* Build the table of primitives */ - shared_lib_path = read_section_to_os(fd, &trail, "DLPT"); - shared_libs = read_section_to_os(fd, &trail, "DLLS"); - req_prims = read_section(fd, &trail, "PRIM"); - if (req_prims == NULL) caml_fatal_error("Fatal error: no PRIM section\n"); - caml_build_primitive_table(shared_lib_path, shared_libs, req_prims); - caml_stat_free(shared_lib_path); - caml_stat_free(shared_libs); - caml_stat_free(req_prims); - /* Load the globals */ - caml_seek_section(fd, &trail, "DATA"); - chan = caml_open_descriptor_in(fd); - caml_global_data = caml_input_val(chan); - caml_close_channel(chan); /* this also closes fd */ - caml_stat_free(trail.section); - /* Ensure that the globals are in the major heap. */ - caml_oldify_one (caml_global_data, &caml_global_data); - caml_oldify_mopup (); - /* Initialize system libraries */ - caml_sys_init(exe_name, argv + pos); -#ifdef _WIN32 - /* Start a thread to handle signals */ - if (caml_secure_getenv(_T("CAMLSIGPIPE"))) - _beginthread(caml_signal_thread, 4096, NULL); -#endif - /* Execute the program */ - caml_debugger(PROGRAM_START); - res = caml_interprete(caml_start_code, caml_code_size); - if (Is_exception_result(res)) { - caml_exn_bucket = Extract_exception(res); - if (caml_debugger_in_use) { - caml_extern_sp = &caml_exn_bucket; /* The debugger needs the - exception value.*/ - caml_debugger(UNCAUGHT_EXC); - } - caml_fatal_uncaught_exception(caml_exn_bucket); - } -} - -/* Main entry point when code is linked in as initialized data */ - -CAMLexport value caml_startup_code_exn( - code_t code, asize_t code_size, - char *data, asize_t data_size, - char *section_table, asize_t section_table_size, - int pooling, - char_os **argv) -{ - char_os * cds_file; - char_os * exe_name; - - /* Determine options */ -#ifdef DEBUG - caml_verb_gc = 0x3F; -#endif - caml_parse_ocamlrunparam(); -#ifdef DEBUG - caml_gc_message (-1, "### OCaml runtime: debug mode ###\n"); -#endif - if (caml_cleanup_on_exit) - pooling = 1; - if (!caml_startup_aux(pooling)) - return Val_unit; - - caml_init_ieee_floats(); -#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L - caml_install_invalid_parameter_handler(); -#endif - caml_init_custom_operations(); - cds_file = caml_secure_getenv(_T("CAML_DEBUG_FILE")); - if (cds_file != NULL) { - caml_cds_file = caml_stat_strdup_os(cds_file); - } - exe_name = caml_executable_name(); - if (exe_name == NULL) exe_name = caml_search_exe_in_path(argv[0]); - caml_external_raise = NULL; - /* Initialize the abstract machine */ - caml_init_gc (caml_init_minor_heap_wsz, caml_init_heap_wsz, - caml_init_heap_chunk_sz, caml_init_percent_free, - caml_init_max_percent_free, caml_init_major_window); - caml_init_stack (caml_init_max_stack_wsz); - caml_init_atom_table(); - caml_init_backtrace(); - /* Initialize the interpreter */ - caml_interprete(NULL, 0); - /* Initialize the debugger, if needed */ - caml_debugger_init(); - /* Load the code */ - caml_start_code = code; - caml_code_size = code_size; - caml_init_code_fragments(); - caml_init_debug_info(); - if (caml_debugger_in_use) { - int len, i; - len = code_size / sizeof(opcode_t); - caml_saved_code = (unsigned char *) caml_stat_alloc(len); - for (i = 0; i < len; i++) caml_saved_code[i] = caml_start_code[i]; - } -#ifdef THREADED_CODE - caml_thread_code(caml_start_code, code_size); -#endif - /* Use the builtin table of primitives */ - caml_build_primitive_table_builtin(); - /* Load the globals */ - caml_global_data = caml_input_value_from_block(data, data_size); - /* Ensure that the globals are in the major heap. */ - caml_oldify_one (caml_global_data, &caml_global_data); - caml_oldify_mopup (); - /* Record the sections (for caml_get_section_table in meta.c) */ - caml_section_table = section_table; - caml_section_table_size = section_table_size; - /* Initialize system libraries */ - caml_sys_init(exe_name, argv); - /* Execute the program */ - caml_debugger(PROGRAM_START); - return caml_interprete(caml_start_code, caml_code_size); -} - -CAMLexport void caml_startup_code( - code_t code, asize_t code_size, - char *data, asize_t data_size, - char *section_table, asize_t section_table_size, - int pooling, - char_os **argv) -{ - value res; - - res = caml_startup_code_exn(code, code_size, data, data_size, - section_table, section_table_size, - pooling, argv); - if (Is_exception_result(res)) { - caml_exn_bucket = Extract_exception(res); - if (caml_debugger_in_use) { - caml_extern_sp = &caml_exn_bucket; /* The debugger needs the - exception value.*/ - caml_debugger(UNCAUGHT_EXC); - } - caml_fatal_uncaught_exception(caml_exn_bucket); - } -} diff --git a/byterun/startup_aux.c b/byterun/startup_aux.c deleted file mode 100644 index b913bfae..00000000 --- a/byterun/startup_aux.c +++ /dev/null @@ -1,168 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Some runtime initialization functions that are common to bytecode - and native code. */ - -#include -#include "caml/backtrace.h" -#include "caml/memory.h" -#include "caml/callback.h" -#include "caml/major_gc.h" -#ifndef NATIVE_CODE -#include "caml/dynlink.h" -#endif -#include "caml/osdeps.h" -#include "caml/startup_aux.h" - - -/* Initialize the atom table */ - -CAMLexport header_t caml_atom_table[256]; -void caml_init_atom_table(void) -{ - int i; - for(i = 0; i < 256; i++) { -#ifdef NATIVE_CODE - caml_atom_table[i] = Make_header_allocated_here(0, i, Caml_white); -#else - caml_atom_table[i] = Make_header(0, i, Caml_white); -#endif - } - if (caml_page_table_add(In_static_data, - caml_atom_table, caml_atom_table + 256) != 0) { - caml_fatal_error("Fatal error: not enough memory for initial page table"); - } -} - - -/* Parse the OCAMLRUNPARAM environment variable. */ - -uintnat caml_init_percent_free = Percent_free_def; -uintnat caml_init_max_percent_free = Max_percent_free_def; -uintnat caml_init_minor_heap_wsz = Minor_heap_def; -uintnat caml_init_heap_chunk_sz = Heap_chunk_def; -uintnat caml_init_heap_wsz = Init_heap_def; -uintnat caml_init_max_stack_wsz = Max_stack_def; -uintnat caml_init_major_window = Major_window_def; -extern int caml_parser_trace; -uintnat caml_trace_level = 0; -uintnat caml_cleanup_on_exit = 0; - - -static void scanmult (char_os *opt, uintnat *var) -{ - char_os mult = _T(' '); - unsigned int val = 1; - sscanf_os (opt, _T("=%u%c"), &val, &mult); - sscanf_os (opt, _T("=0x%x%c"), &val, &mult); - switch (mult) { - case _T('k'): *var = (uintnat) val * 1024; break; - case _T('M'): *var = (uintnat) val * (1024 * 1024); break; - case _T('G'): *var = (uintnat) val * (1024 * 1024 * 1024); break; - default: *var = (uintnat) val; break; - } -} - -void caml_parse_ocamlrunparam(void) -{ - char_os *opt = caml_secure_getenv (_T("OCAMLRUNPARAM")); - uintnat p; - - if (opt == NULL) opt = caml_secure_getenv (_T("CAMLRUNPARAM")); - - if (opt != NULL){ - while (*opt != _T('\0')){ - switch (*opt++){ - case _T('a'): scanmult (opt, &p); caml_set_allocation_policy (p); break; - case _T('b'): scanmult (opt, &p); caml_record_backtrace(Val_bool (p)); break; - case _T('c'): scanmult (opt, &p); caml_cleanup_on_exit = p; break; - case _T('h'): scanmult (opt, &caml_init_heap_wsz); break; - case _T('H'): scanmult (opt, &caml_use_huge_pages); break; - case _T('i'): scanmult (opt, &caml_init_heap_chunk_sz); break; - case _T('l'): scanmult (opt, &caml_init_max_stack_wsz); break; - case _T('o'): scanmult (opt, &caml_init_percent_free); break; - case _T('O'): scanmult (opt, &caml_init_max_percent_free); break; - case _T('p'): scanmult (opt, &p); caml_parser_trace = p; break; - case _T('R'): break; /* see stdlib/hashtbl.mli */ - case _T('s'): scanmult (opt, &caml_init_minor_heap_wsz); break; - case _T('t'): scanmult (opt, &caml_trace_level); break; - case _T('v'): scanmult (opt, &caml_verb_gc); break; - case _T('w'): scanmult (opt, &caml_init_major_window); break; - case _T('W'): scanmult (opt, &caml_runtime_warnings); break; - } - while (*opt != _T('\0')){ - if (*opt++ == ',') break; - } - } - } -} - - -/* The number of outstanding calls to caml_startup */ -static int startup_count = 0; - -/* Has the runtime been shut down already? */ -static int shutdown_happened = 0; - - -int caml_startup_aux(int pooling) -{ - if (shutdown_happened == 1) - caml_fatal_error("Fatal error: caml_startup was called after the runtime " - "was shut down with caml_shutdown"); - - /* Second and subsequent calls are ignored, - since the runtime has already started */ - startup_count++; - if (startup_count > 1) - return 0; - - if (pooling) - caml_stat_create_pool(); - - return 1; -} - -static void call_registered_value(char* name) -{ - value *f = caml_named_value(name); - if (f != NULL) - caml_callback_exn(*f, Val_unit); -} - -CAMLexport void caml_shutdown(void) -{ - if (startup_count <= 0) - caml_fatal_error("Fatal error: a call to caml_shutdown has no " - "corresponding call to caml_startup"); - - /* Do nothing unless it's the last call remaining */ - startup_count--; - if (startup_count > 0) - return; - - call_registered_value("Pervasives.do_at_exit"); - call_registered_value("Thread.at_shutdown"); - caml_finalise_heap(); -#ifndef NATIVE_CODE - caml_free_shared_libs(); -#endif - caml_stat_destroy_pool(); - - shutdown_happened = 1; -} diff --git a/byterun/str.c b/byterun/str.c deleted file mode 100644 index 8e07cb03..00000000 --- a/byterun/str.c +++ /dev/null @@ -1,474 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Operations on strings */ - -#include -#include -#include -#include -#include "caml/alloc.h" -#include "caml/fail.h" -#include "caml/memory.h" -#include "caml/mlvalues.h" -#include "caml/misc.h" - -/* returns a number of bytes (chars) */ -CAMLexport mlsize_t caml_string_length(value s) -{ - mlsize_t temp; - temp = Bosize_val(s) - 1; - CAMLassert (Byte (s, temp - Byte (s, temp)) == 0); - return temp - Byte (s, temp); -} - -/* returns a value that represents a number of bytes (chars) */ -CAMLprim value caml_ml_string_length(value s) -{ - mlsize_t temp; - temp = Bosize_val(s) - 1; - CAMLassert (Byte (s, temp - Byte (s, temp)) == 0); - return Val_long(temp - Byte (s, temp)); -} - -CAMLprim value caml_ml_bytes_length(value s) -{ - return caml_ml_string_length(s); -} - -CAMLexport int caml_string_is_c_safe (value s) -{ - return strlen(String_val(s)) == caml_string_length(s); -} - -/** - * [caml_create_string] is deprecated, - * use [caml_create_bytes] instead - */ -CAMLprim value caml_create_string(value len) -{ - mlsize_t size = Long_val(len); - if (size > Bsize_wsize (Max_wosize) - 1){ - caml_invalid_argument("String.create"); - } - return caml_alloc_string(size); -} - -/* [len] is a value that represents a number of bytes (chars) */ -CAMLprim value caml_create_bytes(value len) -{ - mlsize_t size = Long_val(len); - if (size > Bsize_wsize (Max_wosize) - 1){ - caml_invalid_argument("Bytes.create"); - } - return caml_alloc_string(size); -} - - - -CAMLprim value caml_string_get(value str, value index) -{ - intnat idx = Long_val(index); - if (idx < 0 || idx >= caml_string_length(str)) caml_array_bound_error(); - return Val_int(Byte_u(str, idx)); -} - -CAMLprim value caml_bytes_get(value str, value index) -{ - return caml_string_get(str, index); -} - -CAMLprim value caml_bytes_set(value str, value index, value newval) -{ - intnat idx = Long_val(index); - if (idx < 0 || idx >= caml_string_length(str)) caml_array_bound_error(); - Byte_u(str, idx) = Int_val(newval); - return Val_unit; -} - -/** - * [caml_string_set] is deprecated, - * use [caml_bytes_set] instead - */ -CAMLprim value caml_string_set(value str, value index, value newval) -{ - return caml_bytes_set(str,index,newval); -} - - -CAMLprim value caml_string_get16(value str, value index) -{ - intnat res; - unsigned char b1, b2; - intnat idx = Long_val(index); - if (idx < 0 || idx + 1 >= caml_string_length(str)) caml_array_bound_error(); - b1 = Byte_u(str, idx); - b2 = Byte_u(str, idx + 1); -#ifdef ARCH_BIG_ENDIAN - res = b1 << 8 | b2; -#else - res = b2 << 8 | b1; -#endif - return Val_int(res); -} - -CAMLprim value caml_bytes_get16(value str, value index) -{ - return caml_string_get16(str,index); -} - -CAMLprim value caml_string_get32(value str, value index) -{ - intnat res; - unsigned char b1, b2, b3, b4; - intnat idx = Long_val(index); - if (idx < 0 || idx + 3 >= caml_string_length(str)) caml_array_bound_error(); - b1 = Byte_u(str, idx); - b2 = Byte_u(str, idx + 1); - b3 = Byte_u(str, idx + 2); - b4 = Byte_u(str, idx + 3); -#ifdef ARCH_BIG_ENDIAN - res = b1 << 24 | b2 << 16 | b3 << 8 | b4; -#else - res = b4 << 24 | b3 << 16 | b2 << 8 | b1; -#endif - return caml_copy_int32(res); -} - -CAMLprim value caml_bytes_get32(value str, value index) -{ - return caml_string_get32(str,index); -} - -CAMLprim value caml_string_get64(value str, value index) -{ - uint64_t res; - unsigned char b1, b2, b3, b4, b5, b6, b7, b8; - intnat idx = Long_val(index); - if (idx < 0 || idx + 7 >= caml_string_length(str)) caml_array_bound_error(); - b1 = Byte_u(str, idx); - b2 = Byte_u(str, idx + 1); - b3 = Byte_u(str, idx + 2); - b4 = Byte_u(str, idx + 3); - b5 = Byte_u(str, idx + 4); - b6 = Byte_u(str, idx + 5); - b7 = Byte_u(str, idx + 6); - b8 = Byte_u(str, idx + 7); -#ifdef ARCH_BIG_ENDIAN - res = (uint64_t) b1 << 56 | (uint64_t) b2 << 48 - | (uint64_t) b3 << 40 | (uint64_t) b4 << 32 - | (uint64_t) b5 << 24 | (uint64_t) b6 << 16 - | (uint64_t) b7 << 8 | (uint64_t) b8; -#else - res = (uint64_t) b8 << 56 | (uint64_t) b7 << 48 - | (uint64_t) b6 << 40 | (uint64_t) b5 << 32 - | (uint64_t) b4 << 24 | (uint64_t) b3 << 16 - | (uint64_t) b2 << 8 | (uint64_t) b1; -#endif - return caml_copy_int64(res); -} - -CAMLprim value caml_bytes_get64(value str, value index) -{ - return caml_string_get64(str,index); -} - -CAMLprim value caml_bytes_set16(value str, value index, value newval) -{ - unsigned char b1, b2; - intnat val; - intnat idx = Long_val(index); - if (idx < 0 || idx + 1 >= caml_string_length(str)) caml_array_bound_error(); - val = Long_val(newval); -#ifdef ARCH_BIG_ENDIAN - b1 = 0xFF & val >> 8; - b2 = 0xFF & val; -#else - b2 = 0xFF & val >> 8; - b1 = 0xFF & val; -#endif - Byte_u(str, idx) = b1; - Byte_u(str, idx + 1) = b2; - return Val_unit; -} - -CAMLprim value caml_bytes_set32(value str, value index, value newval) -{ - unsigned char b1, b2, b3, b4; - intnat val; - intnat idx = Long_val(index); - if (idx < 0 || idx + 3 >= caml_string_length(str)) caml_array_bound_error(); - val = Int32_val(newval); -#ifdef ARCH_BIG_ENDIAN - b1 = 0xFF & val >> 24; - b2 = 0xFF & val >> 16; - b3 = 0xFF & val >> 8; - b4 = 0xFF & val; -#else - b4 = 0xFF & val >> 24; - b3 = 0xFF & val >> 16; - b2 = 0xFF & val >> 8; - b1 = 0xFF & val; -#endif - Byte_u(str, idx) = b1; - Byte_u(str, idx + 1) = b2; - Byte_u(str, idx + 2) = b3; - Byte_u(str, idx + 3) = b4; - return Val_unit; -} - -CAMLprim value caml_bytes_set64(value str, value index, value newval) -{ - unsigned char b1, b2, b3, b4, b5, b6, b7, b8; - int64_t val; - intnat idx = Long_val(index); - if (idx < 0 || idx + 7 >= caml_string_length(str)) caml_array_bound_error(); - val = Int64_val(newval); -#ifdef ARCH_BIG_ENDIAN - b1 = 0xFF & val >> 56; - b2 = 0xFF & val >> 48; - b3 = 0xFF & val >> 40; - b4 = 0xFF & val >> 32; - b5 = 0xFF & val >> 24; - b6 = 0xFF & val >> 16; - b7 = 0xFF & val >> 8; - b8 = 0xFF & val; -#else - b8 = 0xFF & val >> 56; - b7 = 0xFF & val >> 48; - b6 = 0xFF & val >> 40; - b5 = 0xFF & val >> 32; - b4 = 0xFF & val >> 24; - b3 = 0xFF & val >> 16; - b2 = 0xFF & val >> 8; - b1 = 0xFF & val; -#endif - Byte_u(str, idx) = b1; - Byte_u(str, idx + 1) = b2; - Byte_u(str, idx + 2) = b3; - Byte_u(str, idx + 3) = b4; - Byte_u(str, idx + 4) = b5; - Byte_u(str, idx + 5) = b6; - Byte_u(str, idx + 6) = b7; - Byte_u(str, idx + 7) = b8; - return Val_unit; -} - -CAMLprim value caml_string_equal(value s1, value s2) -{ - mlsize_t sz1, sz2; - value * p1, * p2; - - if (s1 == s2) return Val_true; - sz1 = Wosize_val(s1); - sz2 = Wosize_val(s2); - if (sz1 != sz2) return Val_false; - for(p1 = Op_val(s1), p2 = Op_val(s2); sz1 > 0; sz1--, p1++, p2++) - if (*p1 != *p2) return Val_false; - return Val_true; -} - -CAMLprim value caml_bytes_equal(value s1, value s2) -{ - return caml_string_equal(s1,s2); -} - -CAMLprim value caml_string_notequal(value s1, value s2) -{ - return Val_not(caml_string_equal(s1, s2)); -} - -CAMLprim value caml_bytes_notequal(value s1, value s2) -{ - return caml_string_notequal(s1,s2); -} - -CAMLprim value caml_string_compare(value s1, value s2) -{ - mlsize_t len1, len2; - int res; - - if (s1 == s2) return Val_int(0); - len1 = caml_string_length(s1); - len2 = caml_string_length(s2); - res = memcmp(String_val(s1), String_val(s2), len1 <= len2 ? len1 : len2); - if (res < 0) return Val_int(-1); - if (res > 0) return Val_int(1); - if (len1 < len2) return Val_int(-1); - if (len1 > len2) return Val_int(1); - return Val_int(0); -} - -CAMLprim value caml_bytes_compare(value s1, value s2) -{ - return caml_string_compare(s1,s2); -} - -CAMLprim value caml_string_lessthan(value s1, value s2) -{ - return caml_string_compare(s1, s2) < Val_int(0) ? Val_true : Val_false; -} - -CAMLprim value caml_bytes_lessthan(value s1, value s2) -{ - return caml_string_lessthan(s1,s2); -} - - -CAMLprim value caml_string_lessequal(value s1, value s2) -{ - return caml_string_compare(s1, s2) <= Val_int(0) ? Val_true : Val_false; -} - -CAMLprim value caml_bytes_lessequal(value s1, value s2) -{ - return caml_string_lessequal(s1,s2); -} - - -CAMLprim value caml_string_greaterthan(value s1, value s2) -{ - return caml_string_compare(s1, s2) > Val_int(0) ? Val_true : Val_false; -} - -CAMLprim value caml_bytes_greaterthan(value s1, value s2) -{ - return caml_string_greaterthan(s1,s2); -} - -CAMLprim value caml_string_greaterequal(value s1, value s2) -{ - return caml_string_compare(s1, s2) >= Val_int(0) ? Val_true : Val_false; -} - -CAMLprim value caml_bytes_greaterequal(value s1, value s2) -{ - return caml_string_greaterequal(s1,s2); -} - -CAMLprim value caml_blit_bytes(value s1, value ofs1, value s2, value ofs2, - value n) -{ - memmove(&Byte(s2, Long_val(ofs2)), &Byte(s1, Long_val(ofs1)), Long_val(n)); - return Val_unit; -} - -CAMLprim value caml_blit_string(value s1, value ofs1, value s2, value ofs2, - value n) -{ - return caml_blit_bytes (s1, ofs1, s2, ofs2, n); -} - -CAMLprim value caml_fill_bytes(value s, value offset, value len, value init) -{ - memset(&Byte(s, Long_val(offset)), Int_val(init), Long_val(len)); - return Val_unit; -} - -/** - * [caml_fill_string] is deprecated, use [caml_fill_bytes] instead - */ -CAMLprim value caml_fill_string(value s, value offset, value len, value init) -{ - return caml_fill_bytes (s, offset, len, init); -} - -CAMLexport value caml_alloc_sprintf(const char * format, ...) -{ - va_list args; - char buf[128]; - int n; - value res; - -#if !defined(_WIN32) || defined(_UCRT) - /* C99-compliant implementation */ - va_start(args, format); - /* "vsnprintf(dest, sz, format, args)" writes at most "sz" characters - into "dest", including the terminating '\0'. - It returns the number of characters of the formatted string, - excluding the terminating '\0'. */ - n = vsnprintf(buf, sizeof(buf), format, args); - va_end(args); - if (n < sizeof(buf)) { - /* All output characters were written to buf, including the - terminating '\0'. Allocate a Caml string with length "n" - as computed by vsnprintf, and copy the output of vsnprintf into it. */ - res = caml_alloc_initialized_string(n, buf); - } else { - /* PR#7568: if the format is in the Caml heap, the following - caml_alloc_string could move or free the format. To prevent - this, take a copy of the format outside the Caml heap. */ - char * saved_format = caml_stat_strdup(format); - /* Allocate a Caml string with length "n" as computed by vsnprintf. */ - res = caml_alloc_string(n); - /* Re-do the formatting, outputting directly in the Caml string. - Note that caml_alloc_string left room for a '\0' at position n, - so the size passed to vsnprintf is n+1. */ - va_start(args, format); - vsnprintf((char *)String_val(res), n + 1, saved_format, args); - va_end(args); - caml_stat_free(saved_format); - } - return res; -#else - /* Implementation specific to the Microsoft CRT library */ - va_start(args, format); - /* "_vsnprintf(dest, sz, format, args)" writes at most "sz" characters - into "dest". Let "len" be the number of characters of the formatted - string. - If "len" < "sz", a null terminator was appended, and "len" is returned. - If "len" == "sz", no null termination, and "len" is returned. - If "len" > "sz", a negative value is returned. */ - n = _vsnprintf(buf, sizeof(buf), format, args); - va_end(args); - if (n >= 0 && n <= sizeof(buf)) { - /* All output characters were written to buf. - "n" is the actual length of the output. - Allocate a Caml string of length "n" and copy the characters into it. */ - res = caml_alloc_string(n); - memcpy(String_val(res), buf, n); - } else { - /* PR#7568: if the format is in the Caml heap, the following - caml_alloc_string could move or free the format. To prevent - this, take a copy of the format outside the Caml heap. */ - char * saved_format = caml_stat_strdup(format); - /* Determine actual length of output, excluding final '\0' */ - va_start(args, format); - n = _vscprintf(format, args); - va_end(args); - res = caml_alloc_string(n); - /* Re-do the formatting, outputting directly in the Caml string. - Note that caml_alloc_string left room for a '\0' at position n, - so the size passed to _vsnprintf is n+1. */ - va_start(args, format); - _vsnprintf(String_val(res), n + 1, saved_format, args); - va_end(args); - caml_stat_free(saved_format); - } - return res; -#endif -} - -CAMLprim value caml_string_of_bytes(value bv) -{ - return bv; -} - -CAMLprim value caml_bytes_of_string(value bv) -{ - return bv; -} diff --git a/byterun/sys.c b/byterun/sys.c deleted file mode 100644 index a428fd73..00000000 --- a/byterun/sys.c +++ /dev/null @@ -1,718 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Basic system calls */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef _WIN32 -#include /* for _wchdir and _wgetcwd */ -#else -#include -#endif -#include "caml/config.h" -#ifdef HAS_UNISTD -#include -#endif -#ifdef HAS_TIMES -#include -#endif -#ifdef HAS_GETRUSAGE -#include -#include -#endif -#ifdef HAS_GETTIMEOFDAY -#include -#endif -#include "caml/alloc.h" -#include "caml/debugger.h" -#include "caml/fail.h" -#include "caml/gc_ctrl.h" -#include "caml/io.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/osdeps.h" -#include "caml/signals.h" -#include "caml/stacks.h" -#include "caml/sys.h" -#include "caml/version.h" -#include "caml/callback.h" -#include "caml/startup_aux.h" - -static char * error_message(void) -{ - return strerror(errno); -} - -#ifndef EAGAIN -#define EAGAIN (-1) -#endif -#ifndef EWOULDBLOCK -#define EWOULDBLOCK (-1) -#endif - -CAMLexport void caml_sys_error(value arg) -{ - CAMLparam1 (arg); - char * err; - CAMLlocal1 (str); - - err = error_message(); - if (arg == NO_ARG) { - str = caml_copy_string(err); - } else { - int err_len = strlen(err); - int arg_len = caml_string_length(arg); - str = caml_alloc_string(arg_len + 2 + err_len); - memmove(&Byte(str, 0), String_val(arg), arg_len); - memmove(&Byte(str, arg_len), ": ", 2); - memmove(&Byte(str, arg_len + 2), err, err_len); - } - caml_raise_sys_error(str); - CAMLnoreturn; -} - -CAMLexport void caml_sys_io_error(value arg) -{ - if (errno == EAGAIN || errno == EWOULDBLOCK) { - caml_raise_sys_blocked_io(); - } else { - caml_sys_error(arg); - } -} - -/* Check that [name] can safely be used as a file path */ - -static void caml_sys_check_path(value name) -{ - if (! caml_string_is_c_safe(name)) { - errno = ENOENT; - caml_sys_error(name); - } -} - -CAMLprim value caml_sys_exit(value retcode_v) -{ - int retcode = Int_val(retcode_v); - - if ((caml_verb_gc & 0x400) != 0) { - /* cf caml_gc_counters */ - double minwords = caml_stat_minor_words - + (double) (caml_young_end - caml_young_ptr); - double prowords = caml_stat_promoted_words; - double majwords = caml_stat_major_words + (double) caml_allocated_words; - double allocated_words = minwords + majwords - prowords; - intnat mincoll = caml_stat_minor_collections; - intnat majcoll = caml_stat_major_collections; - intnat heap_words = caml_stat_heap_wsz; - intnat heap_chunks = caml_stat_heap_chunks; - intnat top_heap_words = caml_stat_top_heap_wsz; - intnat cpct = caml_stat_compactions; - caml_gc_message(0x400, "allocated_words: %.0f\n", allocated_words); - caml_gc_message(0x400, "minor_words: %.0f\n", minwords); - caml_gc_message(0x400, "promoted_words: %.0f\n", prowords); - caml_gc_message(0x400, "major_words: %.0f\n", majwords); - caml_gc_message(0x400, "minor_collections: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", - mincoll); - caml_gc_message(0x400, "major_collections: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", - majcoll); - caml_gc_message(0x400, "heap_words: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", - heap_words); - caml_gc_message(0x400, "heap_chunks: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", - heap_chunks); - caml_gc_message(0x400, "top_heap_words: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", - top_heap_words); - caml_gc_message(0x400, "compactions: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", - cpct); - } - -#ifndef NATIVE_CODE - caml_debugger(PROGRAM_EXIT); -#endif - CAML_INSTR_ATEXIT (); - if (caml_cleanup_on_exit) - caml_shutdown(); -#ifdef _WIN32 - caml_restore_win32_terminal(); -#endif - CAML_SYS_EXIT(retcode); - return Val_unit; -} - -#ifndef O_BINARY -#define O_BINARY 0 -#endif -#ifndef O_TEXT -#define O_TEXT 0 -#endif -#ifndef O_NONBLOCK -#ifdef O_NDELAY -#define O_NONBLOCK O_NDELAY -#else -#define O_NONBLOCK 0 -#endif -#endif - -static int sys_open_flags[] = { - O_RDONLY, O_WRONLY, O_APPEND | O_WRONLY, O_CREAT, O_TRUNC, O_EXCL, - O_BINARY, O_TEXT, O_NONBLOCK -}; - -CAMLprim value caml_sys_open(value path, value vflags, value vperm) -{ - CAMLparam3(path, vflags, vperm); - int fd, flags, perm; - char_os * p; - -#if defined(O_CLOEXEC) - flags = O_CLOEXEC; -#elif defined(_WIN32) - flags = _O_NOINHERIT; -#else - flags = 0; -#endif - - caml_sys_check_path(path); - p = caml_stat_strdup_to_os(String_val(path)); - flags |= caml_convert_flag_list(vflags, sys_open_flags); - perm = Int_val(vperm); - /* open on a named FIFO can block (PR#1533) */ - caml_enter_blocking_section(); - fd = CAML_SYS_OPEN(p, flags, perm); - /* fcntl on a fd can block (PR#5069)*/ -#if defined(F_SETFD) && defined(FD_CLOEXEC) && !defined(_WIN32) \ - && !defined(O_CLOEXEC) - if (fd != -1) - fcntl(fd, F_SETFD, FD_CLOEXEC); -#endif - caml_leave_blocking_section(); - caml_stat_free(p); - if (fd == -1) caml_sys_error(path); - CAMLreturn(Val_long(fd)); -} - -CAMLprim value caml_sys_close(value fd_v) -{ - int fd = Int_val(fd_v); - caml_enter_blocking_section(); - CAML_SYS_CLOSE(fd); - caml_leave_blocking_section(); - return Val_unit; -} - -CAMLprim value caml_sys_file_exists(value name) -{ -#ifdef _WIN32 - struct _stati64 st; -#else - struct stat st; -#endif - char_os * p; - int ret; - - if (! caml_string_is_c_safe(name)) return Val_false; - p = caml_stat_strdup_to_os(String_val(name)); - caml_enter_blocking_section(); - ret = CAML_SYS_STAT(p, &st); - caml_leave_blocking_section(); - caml_stat_free(p); - - return Val_bool(ret == 0); -} - -CAMLprim value caml_sys_is_directory(value name) -{ - CAMLparam1(name); -#ifdef _WIN32 - struct _stati64 st; -#else - struct stat st; -#endif - char_os * p; - int ret; - - caml_sys_check_path(name); - p = caml_stat_strdup_to_os(String_val(name)); - caml_enter_blocking_section(); - ret = CAML_SYS_STAT(p, &st); - caml_leave_blocking_section(); - caml_stat_free(p); - - if (ret == -1) caml_sys_error(name); -#ifdef S_ISDIR - CAMLreturn(Val_bool(S_ISDIR(st.st_mode))); -#else - CAMLreturn(Val_bool(st.st_mode & S_IFDIR)); -#endif -} - -CAMLprim value caml_sys_remove(value name) -{ - CAMLparam1(name); - char_os * p; - int ret; - caml_sys_check_path(name); - p = caml_stat_strdup_to_os(String_val(name)); - caml_enter_blocking_section(); - ret = CAML_SYS_UNLINK(p); - caml_leave_blocking_section(); - caml_stat_free(p); - if (ret != 0) caml_sys_error(name); - CAMLreturn(Val_unit); -} - -CAMLprim value caml_sys_rename(value oldname, value newname) -{ - char_os * p_old; - char_os * p_new; - int ret; - caml_sys_check_path(oldname); - caml_sys_check_path(newname); - p_old = caml_stat_strdup_to_os(String_val(oldname)); - p_new = caml_stat_strdup_to_os(String_val(newname)); - caml_enter_blocking_section(); - ret = CAML_SYS_RENAME(p_old, p_new); - caml_leave_blocking_section(); - caml_stat_free(p_new); - caml_stat_free(p_old); - if (ret != 0) - caml_sys_error(NO_ARG); - return Val_unit; -} - -CAMLprim value caml_sys_chdir(value dirname) -{ - CAMLparam1(dirname); - char_os * p; - int ret; - caml_sys_check_path(dirname); - p = caml_stat_strdup_to_os(String_val(dirname)); - caml_enter_blocking_section(); - ret = CAML_SYS_CHDIR(p); - caml_leave_blocking_section(); - caml_stat_free(p); - if (ret != 0) caml_sys_error(dirname); - CAMLreturn(Val_unit); -} - -CAMLprim value caml_sys_getcwd(value unit) -{ - char_os buff[4096]; - char_os * ret; -#ifdef HAS_GETCWD - ret = getcwd_os(buff, sizeof(buff)/sizeof(*buff)); -#else - caml_invalid_argument("Sys.getcwd not implemented"); -#endif /* HAS_GETCWD */ - if (ret == 0) caml_sys_error(NO_ARG); - return caml_copy_string_of_os(buff); -} - -CAMLprim value caml_sys_unsafe_getenv(value var) -{ - char_os * res, * p; - value val; - - if (! caml_string_is_c_safe(var)) caml_raise_not_found(); - p = caml_stat_strdup_to_os(String_val(var)); -#ifdef _WIN32 - res = caml_win32_getenv(p); -#else - res = CAML_SYS_GETENV(p); -#endif - caml_stat_free(p); - if (res == 0) caml_raise_not_found(); - val = caml_copy_string_of_os(res); -#ifdef _WIN32 - caml_stat_free(res); -#endif - return val; -} - -CAMLprim value caml_sys_getenv(value var) -{ - char_os * res, * p; - value val; - - if (! caml_string_is_c_safe(var)) caml_raise_not_found(); - p = caml_stat_strdup_to_os(String_val(var)); -#ifdef _WIN32 - res = caml_win32_getenv(p); -#else - res = caml_secure_getenv(p); -#endif - caml_stat_free(p); - if (res == 0) caml_raise_not_found(); - val = caml_copy_string_of_os(res); -#ifdef _WIN32 - caml_stat_free(res); -#endif - return val; -} - -char_os * caml_exe_name; -char_os ** caml_main_argv; - -CAMLprim value caml_sys_get_argv(value unit) -{ - CAMLparam0 (); /* unit is unused */ - CAMLlocal3 (exe_name, argv, res); - exe_name = caml_copy_string_of_os(caml_exe_name); - argv = caml_alloc_array((void *)caml_copy_string_of_os, (char const **) caml_main_argv); - res = caml_alloc_small(2, 0); - Field(res, 0) = exe_name; - Field(res, 1) = argv; - CAMLreturn(res); -} - -void caml_sys_init(char_os * exe_name, char_os **argv) -{ -#ifdef _WIN32 - /* Initialises the caml_win32_* globals on Windows with the version of - Windows which is running */ - caml_probe_win32_version(); -#if WINDOWS_UNICODE - caml_setup_win32_terminal(); -#endif -#endif -#ifdef CAML_WITH_CPLUGINS - caml_cplugins_init(exe_name, argv); -#endif - caml_exe_name = exe_name; - caml_main_argv = argv; -} - -#ifdef _WIN32 -#define WIFEXITED(status) 1 -#define WEXITSTATUS(status) (status) -#else -#if !(defined(WIFEXITED) && defined(WEXITSTATUS)) -/* Assume old-style V7 status word */ -#define WIFEXITED(status) (((status) & 0xFF) == 0) -#define WEXITSTATUS(status) (((status) >> 8) & 0xFF) -#endif -#endif - -CAMLprim value caml_sys_system_command(value command) -{ - CAMLparam1 (command); - int status, retcode; - char_os *buf; - - if (! caml_string_is_c_safe (command)) { - errno = EINVAL; - caml_sys_error(command); - } - buf = caml_stat_strdup_to_os(String_val(command)); - caml_enter_blocking_section (); - status = CAML_SYS_SYSTEM(buf); - caml_leave_blocking_section (); - caml_stat_free(buf); - if (status == -1) caml_sys_error(command); - if (WIFEXITED(status)) - retcode = WEXITSTATUS(status); - else - retcode = 255; - CAMLreturn (Val_int(retcode)); -} - -double caml_sys_time_include_children_unboxed(value include_children) -{ -#ifdef HAS_GETRUSAGE - struct rusage ru; - double acc = 0.; - - getrusage (RUSAGE_SELF, &ru); - acc += ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1e6 - + ru.ru_stime.tv_sec + ru.ru_stime.tv_usec / 1e6; - - if (Bool_val(include_children)) { - getrusage (RUSAGE_CHILDREN, &ru); - acc += ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1e6 - + ru.ru_stime.tv_sec + ru.ru_stime.tv_usec / 1e6; - } - - return acc; -#else - #ifdef HAS_TIMES - #ifndef CLK_TCK - #ifdef HZ - #define CLK_TCK HZ - #else - #define CLK_TCK 60 - #endif - #endif - struct tms t; - clock_t acc = 0; - times(&t); - acc += t.tms_utime + t.tms_stime; - if (Bool_val(include_children)) { - acc += t.tms_cutime + t.tms_cstime; - } - return (double)acc / CLK_TCK; - #else - /* clock() is standard ANSI C. We have no way of getting - subprocess times in this branch. */ - return (double)clock() / CLOCKS_PER_SEC; - #endif -#endif -} - -CAMLprim value caml_sys_time_include_children(value include_children) -{ - return caml_copy_double(caml_sys_time_include_children_unboxed(include_children)); -} - -double caml_sys_time_unboxed(value unit) { - return caml_sys_time_include_children_unboxed(Val_false); -} - -CAMLprim value caml_sys_time(value unit) -{ - return caml_copy_double(caml_sys_time_unboxed(unit)); -} - -#ifdef _WIN32 -extern int caml_win32_random_seed (intnat data[16]); -#endif - -CAMLprim value caml_sys_random_seed (value unit) -{ - intnat data[16]; - int n, i; - value res; -#ifdef _WIN32 - n = caml_win32_random_seed(data); -#else - int fd; - n = 0; - /* Try /dev/urandom first */ - fd = open("/dev/urandom", O_RDONLY, 0); - if (fd != -1) { - unsigned char buffer[12]; - int nread = read(fd, buffer, 12); - close(fd); - while (nread > 0) data[n++] = buffer[--nread]; - } - /* If the read from /dev/urandom fully succeeded, we now have 96 bits - of good random data and can stop here. Otherwise, complement - whatever we got (probably nothing) with some not-very-random data. */ - if (n < 12) { -#ifdef HAS_GETTIMEOFDAY - struct timeval tv; - gettimeofday(&tv, NULL); - data[n++] = tv.tv_usec; - data[n++] = tv.tv_sec; -#else - data[n++] = time(NULL); -#endif -#ifdef HAS_UNISTD - data[n++] = getpid(); - data[n++] = getppid(); -#endif - } -#endif - /* Convert to an OCaml array of ints */ - res = caml_alloc_small(n, 0); - for (i = 0; i < n; i++) Field(res, i) = Val_long(data[i]); - return res; -} - -CAMLprim value caml_sys_const_big_endian(value unit) -{ -#ifdef ARCH_BIG_ENDIAN - return Val_true; -#else - return Val_false; -#endif -} - -/* returns a value that represents a number of bits */ -CAMLprim value caml_sys_const_word_size(value unit) -{ - return Val_long(8 * sizeof(value)); -} - -/* returns a value that represents a number of bits */ -CAMLprim value caml_sys_const_int_size(value unit) -{ - return Val_long(8 * sizeof(value) - 1) ; -} - -/* returns a value that represents a number of words */ -CAMLprim value caml_sys_const_max_wosize(value unit) -{ - return Val_long(Max_wosize) ; -} - -CAMLprim value caml_sys_const_ostype_unix(value unit) -{ - return Val_bool(0 == strcmp(OCAML_OS_TYPE,"Unix")); -} - -CAMLprim value caml_sys_const_ostype_win32(value unit) -{ - return Val_bool(0 == strcmp(OCAML_OS_TYPE,"Win32")); -} - -CAMLprim value caml_sys_const_ostype_cygwin(value unit) -{ - return Val_bool(0 == strcmp(OCAML_OS_TYPE,"Cygwin")); -} - -CAMLprim value caml_sys_const_backend_type(value unit) -{ - return Val_int(1); /* Bytecode backed */ -} -CAMLprim value caml_sys_get_config(value unit) -{ - CAMLparam0 (); /* unit is unused */ - CAMLlocal2 (result, ostype); - - ostype = caml_copy_string(OCAML_OS_TYPE); - result = caml_alloc_small (3, 0); - Field(result, 0) = ostype; - Field(result, 1) = Val_long (8 * sizeof(value)); -#ifdef ARCH_BIG_ENDIAN - Field(result, 2) = Val_true; -#else - Field(result, 2) = Val_false; -#endif - CAMLreturn (result); -} - -CAMLprim value caml_sys_read_directory(value path) -{ - CAMLparam1(path); - CAMLlocal1(result); - struct ext_table tbl; - char_os * p; - int ret; - - caml_sys_check_path(path); - caml_ext_table_init(&tbl, 50); - p = caml_stat_strdup_to_os(String_val(path)); - caml_enter_blocking_section(); - ret = CAML_SYS_READ_DIRECTORY(p, &tbl); - caml_leave_blocking_section(); - caml_stat_free(p); - if (ret == -1){ - caml_ext_table_free(&tbl, 1); - caml_sys_error(path); - } - caml_ext_table_add(&tbl, NULL); - result = caml_copy_string_array((char const **) tbl.contents); - caml_ext_table_free(&tbl, 1); - CAMLreturn(result); -} - -/* Return true if the value is a filedescriptor (int) that is - * (presumably) open on an interactive terminal */ -CAMLprim value caml_sys_isatty(value chan) -{ - int fd; - value ret; - - fd = (Channel(chan))->fd; -#ifdef _WIN32 - ret = Val_bool(caml_win32_isatty(fd)); -#else - ret = Val_bool(isatty(fd)); -#endif - - return ret; -} - -/* Load dynamic plugins indicated in the CAML_CPLUGINS environment - variable. These plugins can be used to set currently existing - hooks, such as GC hooks and system calls tracing (see misc.h). - */ - -#ifdef CAML_WITH_CPLUGINS - -value (*caml_cplugins_prim)(int,value,value,value) = NULL; - -#define DLL_EXECUTABLE 1 -#define DLL_NOT_GLOBAL 0 - -static struct cplugin_context cplugin_context; - -void caml_load_plugin(char_os *plugin) -{ - void* dll_handle = NULL; - char* u8; - - dll_handle = caml_dlopen(plugin, DLL_EXECUTABLE, DLL_NOT_GLOBAL); - if( dll_handle != NULL ){ - void (* dll_init)(struct cplugin_context*) = - caml_dlsym(dll_handle, "caml_cplugin_init"); - if( dll_init != NULL ){ - cplugin_context.plugin=plugin; - dll_init(&cplugin_context); - } else { - caml_dlclose(dll_handle); - } - } else { - u8 = caml_stat_strdup_of_os(plugin); - fprintf(stderr, "Cannot load C plugin %s\nReason: %s\n", - u8, caml_dlerror()); - caml_stat_free(u8); - } -} - -void caml_cplugins_load(char_os *env_variable) -{ - char_os *plugins = caml_secure_getenv(env_variable); - if(plugins != NULL){ - char_os* curs = plugins; - while(*curs != 0){ - if(*curs == _T(',')){ - if(curs > plugins){ - *curs = 0; - caml_load_plugin(plugins); - } - plugins = curs+1; - } - curs++; - } - if(curs > plugins) caml_load_plugin(plugins); - } -} - -void caml_cplugins_init(char_os * exe_name, char_os **argv) -{ - cplugin_context.api_version = CAML_CPLUGIN_CONTEXT_API; - cplugin_context.prims_bitmap = CAML_CPLUGINS_PRIMS_BITMAP; - cplugin_context.exe_name = exe_name; - cplugin_context.argv = argv; - cplugin_context.ocaml_version = OCAML_VERSION_STRING; - caml_cplugins_load(_T("CAML_CPLUGINS")); -#ifdef NATIVE_CODE - caml_cplugins_load(_T("CAML_NATIVE_CPLUGINS")); -#else - caml_cplugins_load(_T("CAML_BYTE_CPLUGINS")); -#endif -} - -#endif /* CAML_WITH_CPLUGINS */ diff --git a/byterun/unix.c b/byterun/unix.c deleted file mode 100644 index da139195..00000000 --- a/byterun/unix.c +++ /dev/null @@ -1,447 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Unix-specific stuff */ - -#define _GNU_SOURCE - /* Helps finding RTLD_DEFAULT in glibc */ - /* also secure_getenv */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "caml/config.h" -#ifdef SUPPORT_DYNAMIC_LINKING -#ifdef __CYGWIN__ -#include "flexdll.h" -#else -#include -#endif -#endif -#ifdef HAS_UNISTD -#include -#endif -#ifdef HAS_DIRENT -#include -#else -#include -#endif -#ifdef __APPLE__ -#include -#endif -#include "caml/fail.h" -#include "caml/memory.h" -#include "caml/misc.h" -#include "caml/osdeps.h" -#include "caml/signals.h" -#include "caml/sys.h" -#include "caml/io.h" -#include "caml/alloc.h" - -#ifndef S_ISREG -#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) -#endif - -#ifndef EINTR -#define EINTR (-1) -#endif -#ifndef EAGAIN -#define EAGAIN (-1) -#endif -#ifndef EWOULDBLOCK -#define EWOULDBLOCK (-1) -#endif - -int caml_read_fd(int fd, int flags, void * buf, int n) -{ - int retcode; - do { - caml_enter_blocking_section(); - retcode = read(fd, buf, n); - caml_leave_blocking_section(); - } while (retcode == -1 && errno == EINTR); - if (retcode == -1) caml_sys_io_error(NO_ARG); - return retcode; -} - -int caml_write_fd(int fd, int flags, void * buf, int n) -{ - int retcode; - again: -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - if (flags & CHANNEL_FLAG_BLOCKING_WRITE) { - retcode = write(fd, buf, n); - } else { -#endif - caml_enter_blocking_section(); - retcode = write(fd, buf, n); - caml_leave_blocking_section(); -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - } -#endif - if (retcode == -1) { - if (errno == EINTR) goto again; - if ((errno == EAGAIN || errno == EWOULDBLOCK) && n > 1) { - /* We couldn't do a partial write here, probably because - n <= PIPE_BUF and POSIX says that writes of less than - PIPE_BUF characters must be atomic. - We first try again with a partial write of 1 character. - If that fails too, we'll return an error code. */ - n = 1; goto again; - } - } - if (retcode == -1) caml_sys_io_error(NO_ARG); - CAMLassert (retcode > 0); - return retcode; -} - -caml_stat_string caml_decompose_path(struct ext_table * tbl, char * path) -{ - char * p, * q; - size_t n; - - if (path == NULL) return NULL; - p = caml_stat_strdup(path); - q = p; - while (1) { - for (n = 0; q[n] != 0 && q[n] != ':'; n++) /*nothing*/; - caml_ext_table_add(tbl, q); - q = q + n; - if (*q == 0) break; - *q = 0; - q += 1; - } - return p; -} - -caml_stat_string caml_search_in_path(struct ext_table * path, const char * name) -{ - const char * p; - char * dir, * fullname; - int i; - struct stat st; - - for (p = name; *p != 0; p++) { - if (*p == '/') goto not_found; - } - for (i = 0; i < path->size; i++) { - dir = path->contents[i]; - if (dir[0] == 0) dir = "."; /* empty path component = current dir */ - fullname = caml_stat_strconcat(3, dir, "/", name); - if (stat(fullname, &st) == 0 && S_ISREG(st.st_mode)) - return fullname; - caml_stat_free(fullname); - } - not_found: - return caml_stat_strdup(name); -} - -#ifdef __CYGWIN__ - -/* Cygwin needs special treatment because of the implicit ".exe" at the - end of executable file names */ - -static int cygwin_file_exists(const char * name) -{ - int fd, ret; - struct stat st; - /* Cannot use stat() here because it adds ".exe" implicitly */ - fd = open(name, O_RDONLY); - if (fd == -1) return 0; - ret = fstat(fd, &st); - close(fd); - return ret == 0 && S_ISREG(st.st_mode); -} - -static caml_stat_string cygwin_search_exe_in_path(struct ext_table * path, const char * name) -{ - const char * p; - char * dir, * fullname; - int i; - - for (p = name; *p != 0; p++) { - if (*p == '/' || *p == '\\') goto not_found; - } - for (i = 0; i < path->size; i++) { - dir = path->contents[i]; - if (dir[0] == 0) dir = "."; /* empty path component = current dir */ - fullname = caml_stat_strconcat(3, dir, "/", name); - if (cygwin_file_exists(fullname)) return fullname; - caml_stat_free(fullname); - fullname = caml_stat_strconcat(4, dir, "/", name, ".exe"); - if (cygwin_file_exists(fullname)) return fullname; - caml_stat_free(fullname); - } - not_found: - if (cygwin_file_exists(name)) return caml_stat_strdup(name); - fullname = caml_stat_strconcat(2, name, ".exe"); - if (cygwin_file_exists(fullname)) return fullname; - caml_stat_free(fullname); - return caml_stat_strdup(name); -} - -#endif - -caml_stat_string caml_search_exe_in_path(const char * name) -{ - struct ext_table path; - char * tofree; - caml_stat_string res; - - caml_ext_table_init(&path, 8); - tofree = caml_decompose_path(&path, getenv("PATH")); -#ifndef __CYGWIN__ - res = caml_search_in_path(&path, name); -#else - res = cygwin_search_exe_in_path(&path, name); -#endif - caml_stat_free(tofree); - caml_ext_table_free(&path, 0); - return res; -} - -caml_stat_string caml_search_dll_in_path(struct ext_table * path, const char * name) -{ - caml_stat_string dllname; - caml_stat_string res; - - dllname = caml_stat_strconcat(2, name, ".so"); - res = caml_search_in_path(path, dllname); - caml_stat_free(dllname); - return res; -} - -#ifdef SUPPORT_DYNAMIC_LINKING -#ifdef __CYGWIN__ -/* Use flexdll */ - -void * caml_dlopen(char * libname, int for_execution, int global) -{ - int flags = (global ? FLEXDLL_RTLD_GLOBAL : 0); - if (!for_execution) flags |= FLEXDLL_RTLD_NOEXEC; - return flexdll_dlopen(libname, flags); -} - -void caml_dlclose(void * handle) -{ - flexdll_dlclose(handle); -} - -void * caml_dlsym(void * handle, const char * name) -{ - return flexdll_dlsym(handle, name); -} - -void * caml_globalsym(const char * name) -{ - return flexdll_dlsym(flexdll_dlopen(NULL,0), name); -} - -char * caml_dlerror(void) -{ - return flexdll_dlerror(); -} - -#else -/* Use normal dlopen */ - -#ifndef RTLD_GLOBAL -#define RTLD_GLOBAL 0 -#endif -#ifndef RTLD_LOCAL -#define RTLD_LOCAL 0 -#endif - -void * caml_dlopen(char * libname, int for_execution, int global) -{ - return dlopen(libname, RTLD_NOW | (global ? RTLD_GLOBAL : RTLD_LOCAL)); - /* Could use RTLD_LAZY if for_execution == 0, but needs testing */ -} - -void caml_dlclose(void * handle) -{ - dlclose(handle); -} - -void * caml_dlsym(void * handle, const char * name) -{ -#ifdef DL_NEEDS_UNDERSCORE - char _name[1000] = "_"; - strncat (_name, name, 998); - name = _name; -#endif - return dlsym(handle, name); -} - -void * caml_globalsym(const char * name) -{ -#ifdef RTLD_DEFAULT - return caml_dlsym(RTLD_DEFAULT, name); -#else - return NULL; -#endif -} - -char * caml_dlerror(void) -{ - return (char*) dlerror(); -} - -#endif -#else - -void * caml_dlopen(char * libname, int for_execution, int global) -{ - return NULL; -} - -void caml_dlclose(void * handle) -{ -} - -void * caml_dlsym(void * handle, const char * name) -{ - return NULL; -} - -void * caml_globalsym(const char * name) -{ - return NULL; -} - -char * caml_dlerror(void) -{ - return "dynamic loading not supported on this platform"; -} - -#endif - -/* Add to [contents] the (short) names of the files contained in - the directory named [dirname]. No entries are added for [.] and [..]. - Return 0 on success, -1 on error; set errno in the case of error. */ - -CAMLexport int caml_read_directory(char * dirname, struct ext_table * contents) -{ - DIR * d; -#ifdef HAS_DIRENT - struct dirent * e; -#else - struct direct * e; -#endif - - d = opendir(dirname); - if (d == NULL) return -1; - while (1) { - e = readdir(d); - if (e == NULL) break; - if (strcmp(e->d_name, ".") == 0 || strcmp(e->d_name, "..") == 0) continue; - caml_ext_table_add(contents, caml_stat_strdup(e->d_name)); - } - closedir(d); - return 0; -} - -/* Recover executable name from /proc/self/exe if possible */ - -char * caml_executable_name(void) -{ -#if defined(__linux__) - int namelen, retcode; - char * name; - struct stat st; - - /* lstat("/proc/self/exe") returns st_size == 0 so we cannot use it - to determine the size of the buffer. Instead, we guess and adjust. */ - namelen = 256; - while (1) { - name = caml_stat_alloc(namelen); - retcode = readlink("/proc/self/exe", name, namelen); - if (retcode == -1) { caml_stat_free(name); return NULL; } - if (retcode < namelen) break; - caml_stat_free(name); - if (namelen >= 1024*1024) return NULL; /* avoid runaway and overflow */ - namelen *= 2; - } - /* readlink() does not zero-terminate its result. - There is room for a final zero since retcode < namelen. */ - name[retcode] = 0; - /* Make sure that the contents of /proc/self/exe is a regular file. - (Old Linux kernels return an inode number instead.) */ - if (stat(name, &st) == -1 || ! S_ISREG(st.st_mode)) { - caml_stat_free(name); return NULL; - } - return name; - -#elif defined(__APPLE__) - unsigned int namelen; - char * name; - - namelen = 256; - name = caml_stat_alloc(namelen); - if (_NSGetExecutablePath(name, &namelen) == 0) return name; - caml_stat_free(name); - /* Buffer is too small, but namelen now contains the size needed */ - name = caml_stat_alloc(namelen); - if (_NSGetExecutablePath(name, &namelen) == 0) return name; - caml_stat_free(name); - return NULL; - -#else - return NULL; - -#endif -} - -char *caml_secure_getenv (char const *var) -{ -#ifdef HAS_SECURE_GETENV - return secure_getenv (var); -#elif defined (HAS___SECURE_GETENV) - return __secure_getenv (var); -#elif defined(HAS_ISSETUGID) - if (!issetugid ()) - return CAML_SYS_GETENV (var); - else - return NULL; -#else - if (geteuid () == getuid () && getegid () == getgid ()) - return CAML_SYS_GETENV (var); - else - return NULL; -#endif -} - -int caml_num_rows_fd(int fd) -{ -#ifdef TIOCGWINSZ - struct winsize w; - w.ws_row = -1; - if (ioctl(fd, TIOCGWINSZ, &w) == 0) - return w.ws_row; - else - return -1; -#else - return -1; -#endif -} - - diff --git a/byterun/weak.c b/byterun/weak.c deleted file mode 100644 index f430ef8f..00000000 --- a/byterun/weak.c +++ /dev/null @@ -1,427 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1997 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Operations on weak arrays and ephemerons (named ephe here)*/ - -#include - -#include "caml/alloc.h" -#include "caml/fail.h" -#include "caml/major_gc.h" -#include "caml/memory.h" -#include "caml/mlvalues.h" -#include "caml/weak.h" - -value caml_ephe_list_head = 0; - -static value ephe_dummy = 0; -value caml_ephe_none = (value) &ephe_dummy; - -#if defined (NATIVE_CODE) && defined (NO_NAKED_POINTERS) -/** The minor heap is considered alive. - Outside minor and major heap, x must be black. -*/ -static inline int Is_Dead_during_clean(value x){ - CAMLassert (x != caml_ephe_none); - CAMLassert (caml_gc_phase == Phase_clean); - return Is_block (x) && !Is_young (x) && Is_white_val(x); -} -/** The minor heap doesn't have to be marked, outside they should - already be black -*/ -static inline int Must_be_Marked_during_mark(value x){ - CAMLassert (x != caml_ephe_none); - CAMLassert (caml_gc_phase == Phase_mark); - return Is_block (x) && !Is_young (x); -} -#else -static inline int Is_Dead_during_clean(value x){ - CAMLassert (x != caml_ephe_none); - CAMLassert (caml_gc_phase == Phase_clean); - return Is_block (x) && Is_in_heap (x) && Is_white_val(x); -} -static inline int Must_be_Marked_during_mark(value x){ - CAMLassert (x != caml_ephe_none); - CAMLassert (caml_gc_phase == Phase_mark); - return Is_block (x) && Is_in_heap (x); -} -#endif - - -/* [len] is a value that represents a number of words (fields) */ -CAMLprim value caml_ephe_create (value len) -{ - mlsize_t size, i; - value res; - - size = Long_val (len) + CAML_EPHE_FIRST_KEY; - if (size < CAML_EPHE_FIRST_KEY || size > Max_wosize) - caml_invalid_argument ("Weak.create"); - res = caml_alloc_shr (size, Abstract_tag); - for (i = 1; i < size; i++) Field (res, i) = caml_ephe_none; - Field (res, CAML_EPHE_LINK_OFFSET) = caml_ephe_list_head; - caml_ephe_list_head = res; - return res; -} - -CAMLprim value caml_weak_create (value len) -{ - return caml_ephe_create(len); -} - -/** - Specificity of the cleaning phase (Phase_clean): - - The dead keys must be removed from the ephemerons and data removed - when one the keys is dead. Here we call it cleaning the ephemerons. - A specific phase of the GC is dedicated to this, Phase_clean. This - phase is just after the mark phase, so the white values are dead - values. It iterates the function caml_ephe_clean through all the - ephemerons. - - However the GC is incremental and ocaml code can run on the middle - of this cleaning phase. In order to respect the semantic of the - ephemerons concerning dead values, the getter and setter must work - as if the cleaning of all the ephemerons have been done at once. - - - key getter: Even if a dead key have not yet been replaced by - caml_ephe_none, getting it should return none. - - key setter: If we replace a dead key we need to set the data to - caml_ephe_none and clean the ephemeron. - - This two cases are dealt by a call to do_check_key_clean that - trigger the cleaning of the ephemerons when the accessed key is - dead. This test is fast. - - In the case of value getter and value setter, there is no fast - test because the removing of the data depend of the deadliness of the keys. - We must always try to clean the ephemerons. - - */ - -#define None_val (Val_int(0)) -#define Some_tag 0 - -/* If we are in Phase_clean we need to check if the key - that is going to disappear is dead and so should trigger a cleaning - */ -static void do_check_key_clean(value ar, mlsize_t offset){ - CAMLassert (offset >= CAML_EPHE_FIRST_KEY); - if (caml_gc_phase == Phase_clean){ - value elt = Field (ar, offset); - if (elt != caml_ephe_none && Is_Dead_during_clean(elt)){ - Field(ar,offset) = caml_ephe_none; - Field(ar,CAML_EPHE_DATA_OFFSET) = caml_ephe_none; - }; - }; -} - -/* If we are in Phase_clean we need to do as if the key is empty when - it will be cleaned during this phase */ -static inline int is_ephe_key_none(value ar, mlsize_t offset){ - value elt = Field (ar, offset); - if (elt == caml_ephe_none){ - return 1; - }else if (caml_gc_phase == Phase_clean && Is_Dead_during_clean(elt)){ - Field(ar,offset) = caml_ephe_none; - Field(ar,CAML_EPHE_DATA_OFFSET) = caml_ephe_none; - return 1; - } else { - return 0; - } -} - - -static void do_set (value ar, mlsize_t offset, value v) -{ - if (Is_block (v) && Is_young (v)){ - /* modified version of Modify */ - value old = Field (ar, offset); - Field (ar, offset) = v; - if (!(Is_block (old) && Is_young (old))){ - add_to_ephe_ref_table (&caml_ephe_ref_table, ar, offset); - } - }else{ - Field (ar, offset) = v; - } -} - -CAMLprim value caml_ephe_set_key (value ar, value n, value el) -{ - mlsize_t offset = Long_val (n) + CAML_EPHE_FIRST_KEY; - CAMLassert (Is_in_heap (ar)); - if (offset < CAML_EPHE_FIRST_KEY || offset >= Wosize_val (ar)){ - caml_invalid_argument ("Weak.set"); - } - do_check_key_clean(ar,offset); - do_set (ar, offset, el); - return Val_unit; -} - -CAMLprim value caml_ephe_unset_key (value ar, value n) -{ - mlsize_t offset = Long_val (n) + CAML_EPHE_FIRST_KEY; - CAMLassert (Is_in_heap (ar)); - if (offset < CAML_EPHE_FIRST_KEY || offset >= Wosize_val (ar)){ - caml_invalid_argument ("Weak.set"); - } - do_check_key_clean(ar,offset); - Field (ar, offset) = caml_ephe_none; - return Val_unit; -} - -value caml_ephe_set_key_option (value ar, value n, value el) -{ - mlsize_t offset = Long_val (n) + CAML_EPHE_FIRST_KEY; - CAMLassert (Is_in_heap (ar)); - if (offset < CAML_EPHE_FIRST_KEY || offset >= Wosize_val (ar)){ - caml_invalid_argument ("Weak.set"); - } - do_check_key_clean(ar,offset); - if (el != None_val && Is_block (el)){ - CAMLassert (Wosize_val (el) == 1); - do_set (ar, offset, Field (el, 0)); - }else{ - Field (ar, offset) = caml_ephe_none; - } - return Val_unit; -} - -CAMLprim value caml_weak_set (value ar, value n, value el){ - return caml_ephe_set_key_option(ar,n,el); -} - -CAMLprim value caml_ephe_set_data (value ar, value el) -{ - CAMLassert (Is_in_heap (ar)); - if (caml_gc_phase == Phase_clean){ - /* During this phase since we don't know which ephemeron have been - cleaned we always need to check it. */ - caml_ephe_clean(ar); - }; - do_set (ar, CAML_EPHE_DATA_OFFSET, el); - return Val_unit; -} - -CAMLprim value caml_ephe_unset_data (value ar) -{ - CAMLassert (Is_in_heap (ar)); - Field (ar, CAML_EPHE_DATA_OFFSET) = caml_ephe_none; - return Val_unit; -} - -CAMLprim value caml_ephe_get_key (value ar, value n) -{ - CAMLparam2 (ar, n); - mlsize_t offset = Long_val (n) + CAML_EPHE_FIRST_KEY; - CAMLlocal2 (res, elt); - CAMLassert (Is_in_heap (ar)); - if (offset < CAML_EPHE_FIRST_KEY || offset >= Wosize_val (ar)){ - caml_invalid_argument ("Weak.get_key"); - } - if (is_ephe_key_none(ar, offset)){ - res = None_val; - }else{ - elt = Field (ar, offset); - if (caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(elt)){ - caml_darken (elt, NULL); - } - res = caml_alloc_small (1, Some_tag); - Field (res, 0) = elt; - } - CAMLreturn (res); -} - -CAMLprim value caml_weak_get (value ar, value n){ - return caml_ephe_get_key(ar, n); -} - -CAMLprim value caml_ephe_get_data (value ar) -{ - CAMLparam1 (ar); - CAMLlocal2 (res, elt); - CAMLassert (Is_in_heap (ar)); - elt = Field (ar, CAML_EPHE_DATA_OFFSET); - if(caml_gc_phase == Phase_clean) caml_ephe_clean(ar); - if (elt == caml_ephe_none){ - res = None_val; - }else{ - if (caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(elt)){ - caml_darken (elt, NULL); - } - res = caml_alloc_small (1, Some_tag); - Field (res, 0) = elt; - } - CAMLreturn (res); -} - -CAMLprim value caml_ephe_get_key_copy (value ar, value n) -{ - CAMLparam2 (ar, n); - mlsize_t offset = Long_val (n) + CAML_EPHE_FIRST_KEY; - CAMLlocal2 (res, elt); - value v; /* Caution: this is NOT a local root. */ - CAMLassert (Is_in_heap (ar)); - if (offset < CAML_EPHE_FIRST_KEY || offset >= Wosize_val (ar)){ - caml_invalid_argument ("Weak.get_copy"); - } - - if (is_ephe_key_none(ar, offset)) CAMLreturn (None_val); - v = Field (ar, offset); - /** Don't copy custom_block #7279 */ - if (Is_block (v) && Is_in_heap_or_young(v) && Tag_val(v) != Custom_tag ) { - elt = caml_alloc (Wosize_val (v), Tag_val (v)); - /* The GC may erase or move v during this call to caml_alloc. */ - v = Field (ar, offset); - if (is_ephe_key_none(ar, offset)) CAMLreturn (None_val); - if (Tag_val (v) < No_scan_tag){ - mlsize_t i; - for (i = 0; i < Wosize_val (v); i++){ - value f = Field (v, i); - if (caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(f)){ - caml_darken (f, NULL); - } - Modify (&Field (elt, i), f); - } - }else{ - memmove (Bp_val (elt), Bp_val (v), Bosize_val (v)); - } - }else{ - if ( caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(v) ){ - caml_darken (v, NULL); - }; - elt = v; - } - res = caml_alloc_small (1, Some_tag); - Field (res, 0) = elt; - - CAMLreturn (res); -} - -CAMLprim value caml_weak_get_copy (value ar, value n){ - return caml_ephe_get_key_copy(ar,n); -} - -CAMLprim value caml_ephe_get_data_copy (value ar) -{ - CAMLparam1 (ar); - mlsize_t offset = CAML_EPHE_DATA_OFFSET; - CAMLlocal2 (res, elt); - value v; /* Caution: this is NOT a local root. */ - CAMLassert (Is_in_heap (ar)); - - v = Field (ar, offset); - if (caml_gc_phase == Phase_clean) caml_ephe_clean(ar); - if (v == caml_ephe_none) CAMLreturn (None_val); - /** Don't copy custom_block #7279 */ - if (Is_block (v) && Is_in_heap_or_young(v) && Tag_val(v) != Custom_tag ) { - elt = caml_alloc (Wosize_val (v), Tag_val (v)); - /* The GC may erase or move v during this call to caml_alloc. */ - v = Field (ar, offset); - if (caml_gc_phase == Phase_clean) caml_ephe_clean(ar); - if (v == caml_ephe_none) CAMLreturn (None_val); - if (Tag_val (v) < No_scan_tag){ - mlsize_t i; - for (i = 0; i < Wosize_val (v); i++){ - value f = Field (v, i); - if (caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(f)){ - caml_darken (f, NULL); - } - Modify (&Field (elt, i), f); - } - }else{ - memmove (Bp_val (elt), Bp_val (v), Bosize_val (v)); - } - }else{ - if ( caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(v) ){ - caml_darken (v, NULL); - }; - elt = v; - } - res = caml_alloc_small (1, Some_tag); - Field (res, 0) = elt; - - CAMLreturn (res); -} - -CAMLprim value caml_ephe_check_key (value ar, value n) -{ - mlsize_t offset = Long_val (n) + CAML_EPHE_FIRST_KEY; - CAMLassert (Is_in_heap (ar)); - if (offset < CAML_EPHE_FIRST_KEY || offset >= Wosize_val (ar)){ - caml_invalid_argument ("Weak.check"); - } - return Val_bool (!is_ephe_key_none(ar, offset)); -} - -CAMLprim value caml_weak_check (value ar, value n) -{ - return caml_ephe_check_key(ar,n); -} - -CAMLprim value caml_ephe_check_data (value ar) -{ - if(caml_gc_phase == Phase_clean) caml_ephe_clean(ar); - return Val_bool (Field (ar, CAML_EPHE_DATA_OFFSET) != caml_ephe_none); -} - -CAMLprim value caml_ephe_blit_key (value ars, value ofs, - value ard, value ofd, value len) -{ - mlsize_t offset_s = Long_val (ofs) + CAML_EPHE_FIRST_KEY; - mlsize_t offset_d = Long_val (ofd) + CAML_EPHE_FIRST_KEY; - mlsize_t length = Long_val (len); - long i; - CAMLassert (Is_in_heap (ars)); - CAMLassert (Is_in_heap (ard)); - if (offset_s < CAML_EPHE_FIRST_KEY || offset_s + length > Wosize_val (ars)){ - caml_invalid_argument ("Weak.blit"); - } - if (offset_d < CAML_EPHE_FIRST_KEY || offset_d + length > Wosize_val (ard)){ - caml_invalid_argument ("Weak.blit"); - } - if (caml_gc_phase == Phase_clean){ - caml_ephe_clean(ars); - caml_ephe_clean(ard); - } - if (offset_d < offset_s){ - for (i = 0; i < length; i++){ - do_set (ard, offset_d + i, Field (ars, offset_s + i)); - } - }else{ - for (i = length - 1; i >= 0; i--){ - do_set (ard, offset_d + i, Field (ars, offset_s + i)); - } - } - return Val_unit; -} - -CAMLprim value caml_ephe_blit_data (value ars, value ard) -{ - if(caml_gc_phase == Phase_clean) { - caml_ephe_clean(ars); - caml_ephe_clean(ard); - }; - do_set (ard, CAML_EPHE_DATA_OFFSET, Field (ars, CAML_EPHE_DATA_OFFSET)); - return Val_unit; -} - -CAMLprim value caml_weak_blit (value ars, value ofs, - value ard, value ofd, value len) -{ - return caml_ephe_blit_key (ars, ofs, ard, ofd, len); -} diff --git a/byterun/win32.c b/byterun/win32.c deleted file mode 100644 index 1ce8ad5e..00000000 --- a/byterun/win32.c +++ /dev/null @@ -1,1019 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* Win32-specific stuff */ - -/* FILE_INFO_BY_HANDLE_CLASS and FILE_NAME_INFO are only available from Windows - Vista onwards */ -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0600 - -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "caml/alloc.h" -#include "caml/address_class.h" -#include "caml/fail.h" -#include "caml/io.h" -#include "caml/memory.h" -#include "caml/misc.h" -#include "caml/osdeps.h" -#include "caml/signals.h" -#include "caml/sys.h" - -#include "caml/config.h" -#ifdef SUPPORT_DYNAMIC_LINKING -#include -#endif - -#ifndef S_ISREG -#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) -#endif - -unsigned short caml_win32_major = 0; -unsigned short caml_win32_minor = 0; -unsigned short caml_win32_build = 0; -unsigned short caml_win32_revision = 0; - -CAMLnoreturn_start -static void caml_win32_sys_error (int errnum) -CAMLnoreturn_end; - -static void caml_win32_sys_error(int errnum) -{ - wchar_t buffer[512]; - value msg; - if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - errnum, - 0, - buffer, - sizeof(buffer)/sizeof(wchar_t), - NULL)) { - msg = caml_copy_string_of_utf16(buffer); - } else { - msg = caml_alloc_sprintf("unknown error #%d", errnum); - } - caml_raise_sys_error(msg); -} - -int caml_read_fd(int fd, int flags, void * buf, int n) -{ - int retcode; - if ((flags & CHANNEL_FLAG_FROM_SOCKET) == 0) { - caml_enter_blocking_section(); - retcode = read(fd, buf, n); - /* Large reads from console can fail with ENOMEM. Reduce requested size - and try again. */ - if (retcode == -1 && errno == ENOMEM && n > 16384) { - retcode = read(fd, buf, 16384); - } - caml_leave_blocking_section(); - if (retcode == -1) caml_sys_io_error(NO_ARG); - } else { - caml_enter_blocking_section(); - retcode = recv((SOCKET) _get_osfhandle(fd), buf, n, 0); - caml_leave_blocking_section(); - if (retcode == -1) caml_win32_sys_error(WSAGetLastError()); - } - return retcode; -} - -int caml_write_fd(int fd, int flags, void * buf, int n) -{ - int retcode; - if ((flags & CHANNEL_FLAG_FROM_SOCKET) == 0) { -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - if (flags & CHANNEL_FLAG_BLOCKING_WRITE) { - retcode = write(fd, buf, n); - } else { -#endif - caml_enter_blocking_section(); - retcode = write(fd, buf, n); - caml_leave_blocking_section(); -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - } -#endif - if (retcode == -1) caml_sys_io_error(NO_ARG); - } else { - caml_enter_blocking_section(); - retcode = send((SOCKET) _get_osfhandle(fd), buf, n, 0); - caml_leave_blocking_section(); - if (retcode == -1) caml_win32_sys_error(WSAGetLastError()); - } - CAMLassert (retcode > 0); - return retcode; -} - -wchar_t * caml_decompose_path(struct ext_table * tbl, wchar_t * path) -{ - wchar_t * p, * q; - int n; - - if (path == NULL) return NULL; - p = caml_stat_wcsdup(path); - q = p; - while (1) { - for (n = 0; q[n] != 0 && q[n] != L';'; n++) /*nothing*/; - caml_ext_table_add(tbl, q); - q = q + n; - if (*q == 0) break; - *q = 0; - q += 1; - } - return p; -} - -wchar_t * caml_search_in_path(struct ext_table * path, const wchar_t * name) -{ - wchar_t * dir, * fullname; - char * u8; - const wchar_t * p; - int i; - struct _stati64 st; - - for (p = name; *p != 0; p++) { - if (*p == '/' || *p == '\\') goto not_found; - } - for (i = 0; i < path->size; i++) { - dir = path->contents[i]; - if (dir[0] == 0) continue; - /* not sure what empty path components mean under Windows */ - fullname = caml_stat_wcsconcat(3, dir, L"\\", name); - u8 = caml_stat_strdup_of_utf16(fullname); - caml_gc_message(0x100, "Searching %s\n", u8); - caml_stat_free(u8); - if (_wstati64(fullname, &st) == 0 && S_ISREG(st.st_mode)) - return fullname; - caml_stat_free(fullname); - } - not_found: - u8 = caml_stat_strdup_of_utf16(name); - caml_gc_message(0x100, "%s not found in search path\n", u8); - caml_stat_free(u8); - return caml_stat_wcsdup(name); -} - -CAMLexport wchar_t * caml_search_exe_in_path(const wchar_t * name) -{ - wchar_t * fullname, * filepart; - char * u8; - size_t fullnamelen; - DWORD retcode; - - fullnamelen = wcslen(name) + 1; - if (fullnamelen < 256) fullnamelen = 256; - while (1) { - fullname = caml_stat_alloc(fullnamelen*sizeof(wchar_t)); - retcode = SearchPath(NULL, /* use system search path */ - name, - L".exe", /* add .exe extension if needed */ - fullnamelen, - fullname, - &filepart); - if (retcode == 0) { - u8 = caml_stat_strdup_of_utf16(name); - caml_gc_message(0x100, "%s not found in search path\n", u8); - caml_stat_free(u8); - caml_stat_free(fullname); - return caml_stat_strdup_os(name); - } - if (retcode < fullnamelen) - return fullname; - caml_stat_free(fullname); - fullnamelen = retcode + 1; - } -} - -wchar_t * caml_search_dll_in_path(struct ext_table * path, const wchar_t * name) -{ - wchar_t * dllname; - wchar_t * res; - - dllname = caml_stat_wcsconcat(2, name, L".dll"); - res = caml_search_in_path(path, dllname); - caml_stat_free(dllname); - return res; -} - -#ifdef SUPPORT_DYNAMIC_LINKING - -void * caml_dlopen(wchar_t * libname, int for_execution, int global) -{ - void *handle; - int flags = (global ? FLEXDLL_RTLD_GLOBAL : 0); - if (!for_execution) flags |= FLEXDLL_RTLD_NOEXEC; - handle = flexdll_wdlopen(libname, flags); - if ((handle != NULL) && ((caml_verb_gc & 0x100) != 0)) { - flexdll_dump_exports(handle); - fflush(stdout); - } - return handle; -} - -void caml_dlclose(void * handle) -{ - flexdll_dlclose(handle); -} - -void * caml_dlsym(void * handle, const char * name) -{ - return flexdll_dlsym(handle, name); -} - -void * caml_globalsym(const char * name) -{ - return flexdll_dlsym(flexdll_dlopen(NULL,0), name); -} - -char * caml_dlerror(void) -{ - return flexdll_dlerror(); -} - -#else - -void * caml_dlopen(wchar_t * libname, int for_execution, int global) -{ - return NULL; -} - -void caml_dlclose(void * handle) -{ -} - -void * caml_dlsym(void * handle, const char * name) -{ - return NULL; -} - -void * caml_globalsym(const char * name) -{ - return NULL; -} - -char * caml_dlerror(void) -{ - return "dynamic loading not supported on this platform"; -} - -#endif - -/* Proper emulation of signal(), including ctrl-C and ctrl-break */ - -typedef void (*sighandler)(int sig); -static int ctrl_handler_installed = 0; -static volatile sighandler ctrl_handler_action = SIG_DFL; - -static BOOL WINAPI ctrl_handler(DWORD event) -{ - /* Only ctrl-C and ctrl-Break are handled */ - if (event != CTRL_C_EVENT && event != CTRL_BREAK_EVENT) return FALSE; - /* Default behavior is to exit, which we get by not handling the event */ - if (ctrl_handler_action == SIG_DFL) return FALSE; - /* Ignore behavior is to do nothing, which we get by claiming that we - have handled the event */ - if (ctrl_handler_action == SIG_IGN) return TRUE; - /* Win32 doesn't like it when we do a longjmp() at this point - (it looks like we're running in a different thread than - the main program!). So, just record the signal. */ - caml_record_signal(SIGINT); - /* We have handled the event */ - return TRUE; -} - -sighandler caml_win32_signal(int sig, sighandler action) -{ - sighandler oldaction; - - if (sig != SIGINT) return signal(sig, action); - if (! ctrl_handler_installed) { - SetConsoleCtrlHandler(ctrl_handler, TRUE); - ctrl_handler_installed = 1; - } - oldaction = ctrl_handler_action; - ctrl_handler_action = action; - return oldaction; -} - -/* Expansion of @responsefile and *? file patterns in the command line */ - -static int argc; -static wchar_t ** argv; -static int argvsize; - -static void store_argument(wchar_t * arg); -static void expand_argument(wchar_t * arg); -static void expand_pattern(wchar_t * arg); - -static void out_of_memory(void) -{ - fprintf(stderr, "Out of memory while expanding command line\n"); - exit(2); -} - -static void store_argument(wchar_t * arg) -{ - if (argc + 1 >= argvsize) { - argvsize *= 2; - argv = (wchar_t **) caml_stat_resize_noexc(argv, argvsize * sizeof(wchar_t *)); - if (argv == NULL) out_of_memory(); - } - argv[argc++] = arg; -} - -static void expand_argument(wchar_t * arg) -{ - wchar_t * p; - - for (p = arg; *p != 0; p++) { - if (*p == L'*' || *p == L'?') { - expand_pattern(arg); - return; - } - } - store_argument(arg); -} - -static void expand_pattern(wchar_t * pat) -{ - wchar_t * prefix, * p, * name; - intptr_t handle; - struct _wfinddata_t ffblk; - size_t i; - - handle = _wfindfirst(pat, &ffblk); - if (handle == -1) { - store_argument(pat); /* a la Bourne shell */ - return; - } - prefix = caml_stat_wcsdup(pat); - /* We need to stop at the first directory or drive boundary, because the - * _findata_t structure contains the filename, not the leading directory. */ - for (i = wcslen(prefix); i > 0; i--) { - wchar_t c = prefix[i - 1]; - if (c == L'\\' || c == L'/' || c == L':') { prefix[i] = 0; break; } - } - /* No separator was found, it's a filename pattern without a leading directory. */ - if (i == 0) - prefix[0] = 0; - do { - name = caml_stat_wcsconcat(2, prefix, ffblk.name); - store_argument(name); - } while (_wfindnext(handle, &ffblk) != -1); - _findclose(handle); - caml_stat_free(prefix); -} - - -CAMLexport void caml_expand_command_line(int * argcp, wchar_t *** argvp) -{ - int i; - argc = 0; - argvsize = 16; - argv = (wchar_t **) caml_stat_alloc_noexc(argvsize * sizeof(wchar_t *)); - if (argv == NULL) out_of_memory(); - for (i = 0; i < *argcp; i++) expand_argument((*argvp)[i]); - argv[argc] = NULL; - *argcp = argc; - *argvp = argv; -} - -/* Add to [contents] the (short) names of the files contained in - the directory named [dirname]. No entries are added for [.] and [..]. - Return 0 on success, -1 on error; set errno in the case of error. */ - -int caml_read_directory(wchar_t * dirname, struct ext_table * contents) -{ - size_t dirnamelen; - wchar_t * template; - intptr_t h; - struct _wfinddata_t fileinfo; - - dirnamelen = wcslen(dirname); - if (dirnamelen > 0 && - (dirname[dirnamelen - 1] == L'/' - || dirname[dirnamelen - 1] == L'\\' - || dirname[dirnamelen - 1] == L':')) - template = caml_stat_wcsconcat(2, dirname, L"*.*"); - else - template = caml_stat_wcsconcat(2, dirname, L"\\*.*"); - h = _wfindfirst(template, &fileinfo); - if (h == -1) { - caml_stat_free(template); - return errno == ENOENT ? 0 : -1; - } - do { - if (wcscmp(fileinfo.name, L".") != 0 && wcscmp(fileinfo.name, L"..") != 0) { - caml_ext_table_add(contents, caml_stat_strdup_of_utf16(fileinfo.name)); - } - } while (_wfindnext(h, &fileinfo) == 0); - _findclose(h); - caml_stat_free(template); - return 0; -} - -#ifndef NATIVE_CODE - -/* Set up a new thread for control-C emulation and termination */ - -void caml_signal_thread(void * lpParam) -{ - wchar_t *endptr; - HANDLE h; - /* Get an hexa-code raw handle through the environment */ - h = (HANDLE) (uintptr_t) - wcstol(caml_secure_getenv(_T("CAMLSIGPIPE")), &endptr, 16); - while (1) { - DWORD numread; - BOOL ret; - char iobuf[2]; - /* This shall always return a single character */ - ret = ReadFile(h, iobuf, 1, &numread, NULL); - if (!ret || numread != 1) caml_sys_exit(Val_int(2)); - switch (iobuf[0]) { - case 'C': - caml_record_signal(SIGINT); - break; - case 'T': - raise(SIGTERM); - return; - } - } -} - -#endif /* NATIVE_CODE */ - -#if defined(NATIVE_CODE) - -/* Handling of system stack overflow. - * Based on code provided by Olivier Andrieu. - - * An EXCEPTION_STACK_OVERFLOW is signaled when the guard page at the - * end of the stack has been accessed. Windows clears the PAGE_GUARD - * protection (making it a regular PAGE_READWRITE) and then calls our - * exception handler. This means that although we're handling an "out - * of stack" condition, there is a bit of stack available to call - * functions and allocate temporaries. - * - * PAGE_GUARD is a one-shot access protection mechanism: we need to - * restore the PAGE_GUARD protection on this page otherwise the next - * stack overflow won't be detected and the program will abruptly exit - * with STATUS_ACCESS_VIOLATION. - * - * Visual Studio 2003 and later (_MSC_VER >= 1300) have a - * _resetstkoflw() function that resets this protection. - * Unfortunately, it cannot work when called directly from the - * exception handler because at this point we are using the page that - * is to be protected. - * - * A solution is to use an alternate stack when restoring the - * protection. However it's not possible to use _resetstkoflw() then - * since it determines the stack pointer by calling alloca(): it would - * try to protect the alternate stack. - * - * Finally, we call caml_raise_stack_overflow; it will either call - * caml_raise_exception which switches back to the normal stack, or - * call caml_fatal_uncaught_exception which terminates the program - * quickly. - */ - -static uintnat win32_alt_stack[0x100]; - -static void caml_reset_stack (void *faulting_address) -{ - SYSTEM_INFO si; - DWORD page_size; - MEMORY_BASIC_INFORMATION mbi; - DWORD oldprot; - - /* get the system's page size. */ - GetSystemInfo (&si); - page_size = si.dwPageSize; - - /* get some information on the page the fault occurred */ - if (! VirtualQuery (faulting_address, &mbi, sizeof mbi)) - goto failed; - - VirtualProtect (mbi.BaseAddress, page_size, - mbi.Protect | PAGE_GUARD, &oldprot); - - failed: - caml_raise_stack_overflow(); -} - - -#ifndef _WIN64 -static LONG CALLBACK - caml_stack_overflow_VEH (EXCEPTION_POINTERS* exn_info) -{ - DWORD code = exn_info->ExceptionRecord->ExceptionCode; - CONTEXT *ctx = exn_info->ContextRecord; - DWORD *ctx_ip = &(ctx->Eip); - DWORD *ctx_sp = &(ctx->Esp); - - if (code == EXCEPTION_STACK_OVERFLOW && Is_in_code_area (*ctx_ip)) - { - uintnat faulting_address; - uintnat * alt_esp; - - /* grab the address that caused the fault */ - faulting_address = exn_info->ExceptionRecord->ExceptionInformation[1]; - - /* call caml_reset_stack(faulting_address) using the alternate stack */ - alt_esp = win32_alt_stack + sizeof(win32_alt_stack) / sizeof(uintnat); - *--alt_esp = faulting_address; - *ctx_sp = (uintnat) (alt_esp - 1); - *ctx_ip = (uintnat) &caml_reset_stack; - - return EXCEPTION_CONTINUE_EXECUTION; - } - - return EXCEPTION_CONTINUE_SEARCH; -} - -#else -extern char *caml_exception_pointer; -extern value *caml_young_ptr; - -/* Do not use the macro from address_class.h here. */ -#undef Is_in_code_area -#define Is_in_code_area(pc) \ - ( ((char *)(pc) >= caml_code_area_start && \ - (char *)(pc) <= caml_code_area_end) \ -|| ((char *)(pc) >= &caml_system__code_begin && \ - (char *)(pc) <= &caml_system__code_end) \ -|| (Classify_addr(pc) & In_code_area) ) -extern char caml_system__code_begin, caml_system__code_end; - - -static LONG CALLBACK - caml_stack_overflow_VEH (EXCEPTION_POINTERS* exn_info) -{ - DWORD code = exn_info->ExceptionRecord->ExceptionCode; - CONTEXT *ctx = exn_info->ContextRecord; - - if (code == EXCEPTION_STACK_OVERFLOW && Is_in_code_area (ctx->Rip)) - { - uintnat faulting_address; - uintnat * alt_rsp; - - /* grab the address that caused the fault */ - faulting_address = exn_info->ExceptionRecord->ExceptionInformation[1]; - - /* refresh runtime parameters from registers */ - caml_exception_pointer = (char *) ctx->R14; - caml_young_ptr = (value *) ctx->R15; - - /* call caml_reset_stack(faulting_address) using the alternate stack */ - alt_rsp = win32_alt_stack + sizeof(win32_alt_stack) / sizeof(uintnat); - ctx->Rcx = faulting_address; - ctx->Rsp = (uintnat) (alt_rsp - 4 - 1); - ctx->Rip = (uintnat) &caml_reset_stack; - - return EXCEPTION_CONTINUE_EXECUTION; - } - - return EXCEPTION_CONTINUE_SEARCH; -} -#endif /* _WIN64 */ - -void caml_win32_overflow_detection(void) -{ - AddVectoredExceptionHandler(1, caml_stack_overflow_VEH); -} - -#endif /* NATIVE_CODE */ - -/* Seeding of pseudo-random number generators */ - -int caml_win32_random_seed (intnat data[16]) -{ - /* For better randomness, consider: - http://msdn.microsoft.com/library/en-us/seccrypto/security/rtlgenrandom.asp - http://blogs.msdn.com/b/michael_howard/archive/2005/01/14/353379.aspx - */ - FILETIME t; - LARGE_INTEGER pc; - GetSystemTimeAsFileTime(&t); - QueryPerformanceCounter(&pc); /* PR#6032 */ - data[0] = t.dwLowDateTime; - data[1] = t.dwHighDateTime; - data[2] = GetCurrentProcessId(); - data[3] = pc.LowPart; - data[4] = pc.HighPart; - return 5; -} - - -#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L - -static void invalid_parameter_handler(const wchar_t* expression, - const wchar_t* function, - const wchar_t* file, - unsigned int line, - uintptr_t pReserved) -{ - /* no crash box */ -} - - -void caml_install_invalid_parameter_handler() -{ - _set_invalid_parameter_handler(invalid_parameter_handler); -} - -#endif - - -/* Recover executable name */ - -wchar_t * caml_executable_name(void) -{ - wchar_t * name; - DWORD namelen, ret; - - namelen = 256; - while (1) { - name = caml_stat_alloc(namelen*sizeof(wchar_t)); - ret = GetModuleFileName(NULL, name, namelen); - if (ret == 0) { caml_stat_free(name); return NULL; } - if (ret < namelen) break; - caml_stat_free(name); - if (namelen >= 1024*1024) return NULL; /* avoid runaway and overflow */ - namelen *= 2; - } - return name; -} - -/* snprintf emulation */ - -#ifdef LACKS_VSCPRINTF -/* No _vscprintf until Visual Studio .NET 2002 and sadly no version number - in the CRT headers until Visual Studio 2005 so forced to predicate this - on the compiler version instead */ -int _vscprintf(const char * format, va_list args) -{ - int n; - int sz = 5; - char* buf = (char*)malloc(sz); - n = _vsnprintf(buf, sz, format, args); - while (n < 0 || n > sz) { - sz += 512; - buf = (char*)realloc(buf, sz); - n = _vsnprintf(buf, sz, format, args); - } - free(buf); - return n; -} -#endif - -#if defined(_WIN32) && !defined(_UCRT) -int caml_snprintf(char * buf, size_t size, const char * format, ...) -{ - int len; - va_list args; - - if (size > 0) { - va_start(args, format); - len = _vsnprintf(buf, size, format, args); - va_end(args); - if (len >= 0 && len < size) { - /* [len] characters were stored in [buf], - a null-terminator was appended. */ - return len; - } - /* [size] characters were stored in [buf], without null termination. - Put a null terminator, truncating the output. */ - buf[size - 1] = 0; - } - /* Compute the actual length of output, excluding null terminator */ - va_start(args, format); - len = _vscprintf(format, args); - va_end(args); - return len; -} -#endif - -wchar_t *caml_secure_getenv (wchar_t const *var) -{ - /* Win32 doesn't have a notion of setuid bit, so getenv is safe. */ - return _wgetenv(var); -} - -/* caml_win32_getenv is used to implement Sys.getenv and Unix.getenv in such a - way that they get direct access to the Win32 environment rather than to the - copy that is cached by the C runtime system. The result of caml_win32_getenv - is dynamically allocated and must be explicitly deallocated. - - In contrast, the OCaml runtime system still calls _wgetenv from the C runtime - system, via caml_secure_getenv. The result is statically allocated and needs - no deallocation. */ -CAMLexport wchar_t *caml_win32_getenv(wchar_t const *lpName) -{ - wchar_t * lpBuffer; - DWORD nSize = 256, res; - - lpBuffer = caml_stat_alloc_noexc(nSize * sizeof(wchar_t)); - - if (lpBuffer == NULL) - return NULL; - - res = GetEnvironmentVariable(lpName, lpBuffer, nSize); - - if (res == 0) { - caml_stat_free(lpBuffer); - return NULL; - } - - if (res < nSize) - return lpBuffer; - - nSize = res; - lpBuffer = caml_stat_resize_noexc(lpBuffer, nSize * sizeof(wchar_t)); - - if (lpBuffer == NULL) - return NULL; - - res = GetEnvironmentVariable(lpName, lpBuffer, nSize); - - if (res == 0 || res >= nSize) { - caml_stat_free(lpBuffer); - return NULL; - } - - return lpBuffer; -} - -/* The rename() implementation in MSVC's CRT is based on MoveFile() - and therefore fails if the new name exists. This is inconsistent - with POSIX and a problem in practice. Here we reimplement - rename() using MoveFileEx() to make it more POSIX-like. - There are no official guarantee that the rename operation is atomic, - but it is widely believed to be atomic on NTFS. */ - -int caml_win32_rename(const wchar_t * oldpath, const wchar_t * newpath) -{ - /* MOVEFILE_REPLACE_EXISTING: to be closer to POSIX - MOVEFILE_COPY_ALLOWED: MoveFile performs a copy if old and new - paths are on different devices, so we do the same here for - compatibility with the old rename()-based implementation. - MOVEFILE_WRITE_THROUGH: not sure it's useful; affects only - the case where a copy is done. */ - if (MoveFileEx(oldpath, newpath, - MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH | - MOVEFILE_COPY_ALLOWED)) { - return 0; - } - /* Modest attempt at mapping Win32 error codes to POSIX error codes. - The __dosmaperr() function from the CRT does a better job but is - generally not accessible. */ - switch (GetLastError()) { - case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: - errno = ENOENT; break; - case ERROR_ACCESS_DENIED: case ERROR_WRITE_PROTECT: case ERROR_CANNOT_MAKE: - errno = EACCES; break; - case ERROR_CURRENT_DIRECTORY: case ERROR_BUSY: - errno = EBUSY; break; - case ERROR_NOT_SAME_DEVICE: - errno = EXDEV; break; - case ERROR_ALREADY_EXISTS: - errno = EEXIST; break; - default: - errno = EINVAL; - } - return -1; -} - -/* Windows Unicode support */ -static uintnat windows_unicode_enabled = WINDOWS_UNICODE; - -/* If [windows_unicode_strict] is non-zero, then illegal UTF-8 characters (on - the OCaml side) or illegal UTF-16 characters (on the Windows side) cause an - error to be signaled. What happens then depends on the variable - [windows_unicode_fallback]. - - If [windows_unicode_strict] is zero, then illegal characters are silently - dropped. */ -static uintnat windows_unicode_strict = 1; - -/* If [windows_unicode_fallback] is non-zero, then if an error is signaled when - translating to UTF-16, the translation is re-done under the assumption that - the argument string is encoded in the local codepage. */ -static uintnat windows_unicode_fallback = 1; - -CAMLexport int win_multi_byte_to_wide_char(const char *s, int slen, wchar_t *out, int outlen) -{ - int retcode; - - CAMLassert (s != NULL); - - if (slen == 0) - return 0; - - if (windows_unicode_enabled != 0) { - retcode = MultiByteToWideChar(CP_UTF8, windows_unicode_strict ? MB_ERR_INVALID_CHARS : 0, s, slen, out, outlen); - if (retcode == 0 && windows_unicode_fallback != 0) - retcode = MultiByteToWideChar(CP_THREAD_ACP, 0, s, slen, out, outlen); - } else { - retcode = MultiByteToWideChar(CP_THREAD_ACP, 0, s, slen, out, outlen); - } - - if (retcode == 0) - caml_win32_sys_error(GetLastError()); - - return retcode; -} - -#ifndef WC_ERR_INVALID_CHARS /* For old versions of Windows we simply ignore the flag */ -#define WC_ERR_INVALID_CHARS 0 -#endif - -CAMLexport int win_wide_char_to_multi_byte(const wchar_t *s, int slen, char *out, int outlen) -{ - int retcode; - - CAMLassert(s != NULL); - - if (slen == 0) - return 0; - - if (windows_unicode_enabled != 0) - retcode = WideCharToMultiByte(CP_UTF8, windows_unicode_strict ? WC_ERR_INVALID_CHARS : 0, s, slen, out, outlen, NULL, NULL); - else - retcode = WideCharToMultiByte(CP_THREAD_ACP, 0, s, slen, out, outlen, NULL, NULL); - - if (retcode == 0) - caml_win32_sys_error(GetLastError()); - - return retcode; -} - -CAMLexport value caml_copy_string_of_utf16(const wchar_t *s) -{ - int retcode, slen; - value v; - - slen = wcslen(s); - retcode = win_wide_char_to_multi_byte(s, slen, NULL, 0); /* Do not include final NULL */ - v = caml_alloc_string(retcode); - win_wide_char_to_multi_byte(s, slen, String_val(v), retcode); - - return v; -} - -CAMLexport inline wchar_t* caml_stat_strdup_to_utf16(const char *s) -{ - wchar_t * ws; - int retcode; - - retcode = win_multi_byte_to_wide_char(s, -1, NULL, 0); - ws = malloc(retcode * sizeof(*ws)); - win_multi_byte_to_wide_char(s, -1, ws, retcode); - - return ws; -} - -CAMLexport caml_stat_string caml_stat_strdup_of_utf16(const wchar_t *s) -{ - caml_stat_string out; - int retcode; - - retcode = win_wide_char_to_multi_byte(s, -1, NULL, 0); - out = caml_stat_alloc(retcode); - win_wide_char_to_multi_byte(s, -1, out, retcode); - - return out; -} - -void caml_probe_win32_version(void) -{ - /* Determine the version of Windows we're running, and cache it */ - WCHAR fileName[MAX_PATH]; - DWORD size = - GetModuleFileName(GetModuleHandle(L"kernel32"), fileName, MAX_PATH); - DWORD dwHandle = 0; - BYTE* versionInfo; - fileName[size] = 0; - size = GetFileVersionInfoSize(fileName, &dwHandle); - versionInfo = (BYTE*)malloc(size * sizeof(BYTE)); - if (GetFileVersionInfo(fileName, 0, size, versionInfo)) { - UINT len = 0; - VS_FIXEDFILEINFO* vsfi = NULL; - VerQueryValue(versionInfo, L"\\", (void**)&vsfi, &len); - caml_win32_major = HIWORD(vsfi->dwProductVersionMS); - caml_win32_minor = LOWORD(vsfi->dwProductVersionMS); - caml_win32_build = HIWORD(vsfi->dwProductVersionLS); - caml_win32_revision = LOWORD(vsfi->dwProductVersionLS); - } - free(versionInfo); -} - -static UINT startup_codepage = 0; - -void caml_setup_win32_terminal(void) -{ - if (caml_win32_major >= 10) { - startup_codepage = GetConsoleOutputCP(); - if (startup_codepage != CP_UTF8) - SetConsoleOutputCP(CP_UTF8); - } -} - -void caml_restore_win32_terminal(void) -{ - if (startup_codepage != 0) - SetConsoleOutputCP(startup_codepage); -} - -/* Detect if a named pipe corresponds to a Cygwin/MSYS pty: see - https://github.com/mirror/newlib-cygwin/blob/00e9bf2/winsup/cygwin/dtable.cc#L932 -*/ -typedef -BOOL (WINAPI *tGetFileInformationByHandleEx)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, - LPVOID, DWORD); - -static int caml_win32_is_cygwin_pty(HANDLE hFile) -{ - char buffer[1024]; - FILE_NAME_INFO * nameinfo = (FILE_NAME_INFO *) buffer; - static tGetFileInformationByHandleEx pGetFileInformationByHandleEx = INVALID_HANDLE_VALUE; - - if (pGetFileInformationByHandleEx == INVALID_HANDLE_VALUE) - pGetFileInformationByHandleEx = - (tGetFileInformationByHandleEx)GetProcAddress(GetModuleHandle(L"KERNEL32.DLL"), - "GetFileInformationByHandleEx"); - - if (pGetFileInformationByHandleEx == NULL) - return 0; - - /* Get pipe name. GetFileInformationByHandleEx does not NULL-terminate the string, so reduce - the buffer size to allow for adding one. */ - if (! pGetFileInformationByHandleEx(hFile, FileNameInfo, buffer, sizeof(buffer) - sizeof(WCHAR))) - return 0; - - nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0'; - - /* check if this could be a msys pty pipe ('msys-XXXX-ptyN-XX') - or a cygwin pty pipe ('cygwin-XXXX-ptyN-XX') */ - if ((wcsstr(nameinfo->FileName, L"msys-") || - wcsstr(nameinfo->FileName, L"cygwin-")) && wcsstr(nameinfo->FileName, L"-pty")) - return 1; - - return 0; -} - -CAMLexport int caml_win32_isatty(int fd) -{ - DWORD lpMode; - HANDLE hFile = (HANDLE)_get_osfhandle(fd); - - if (hFile == INVALID_HANDLE_VALUE) - return 0; - - switch (GetFileType(hFile)) { - case FILE_TYPE_CHAR: - /* Both console handles and the NUL device are FILE_TYPE_CHAR. The NUL - device returns FALSE for a GetConsoleMode call. _isatty incorrectly - only uses GetFileType (see GPR#1321). */ - return GetConsoleMode(hFile, &lpMode); - case FILE_TYPE_PIPE: - /* Cygwin PTYs are implemented using named pipes */ - return caml_win32_is_cygwin_pty(hFile); - default: - break; - } - - return 0; -} - -int caml_num_rows_fd(int fd) -{ - return -1; -} diff --git a/config/Makefile-templ b/config/Makefile-templ deleted file mode 100644 index 34af691e..00000000 --- a/config/Makefile-templ +++ /dev/null @@ -1,202 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -### Compile-time configuration - -########## General configuration - -### Where to install the binaries -BINDIR=/usr/local/bin - -### Where to install the standard library -LIBDIR=/usr/local/lib/ocaml -STUBLIBDIR=$(LIBDIR)/stublibs - -### Where to install the man pages -# Man pages for commands go in $(MANDIR)/man$(MANEXT) -# Man pages for the library go in $(MANDIR)/mano -MANDIR=/usr/local/man -MANEXT=1 - -### Do #! scripts work on your system? -### Beware: on some systems (e.g. SunOS 4), this will work only if -### the string "#!$(BINDIR)/ocamlrun" is less than 32 characters long. -### In doubt, set HASHBANGSCRIPTS to false. -HASHBANGSCRIPTS=true -#HASHBANGSCRIPTS=false - -########## Configuration for the bytecode compiler - -### Which C compiler to use for the bytecode interpreter. -### Performance of the bytecode interpreter is *much* improved -### if Gnu CC version 2 is used. -#CC=gcc -#BYTECFLAGS= - -### Additional compile-time options for $(BYTECC). -# If using gcc on Intel x86: -# (the -fno-defer-pop option circumvents a bug in certain versions of gcc) -#BYTECCCOMPOPTS=-fno-defer-pop -Wall -# If using gcc and being cautious: -#BYTECCCOMPOPTS=-Wall -# Otherwise: -#BYTECCCOMPOPTS= - -### Additional link-time options for $(BYTECC) -# To support dynamic loading of shared libraries (they need to look at -# our own symbols): -#LDFLAGS=-Wl,-E -# Otherwise: -#LDFLAGS= - -### Libraries needed -# On most platforms: -#CCLIBS=-lcurses -ltermcap -lm - -### How to invoke the C preprocessor -# This is not needed anymore. Leave these lines commented out. -# On most machines: -#CPP=/lib/cpp -P -# Under Solaris: -#CPP=/usr/ccs/lib/cpp -P -# Under FreeBSD: -#CPP=cpp -P - -### How to invoke ranlib -RANLIB=ranlib -RANLIBCMD=ranlib - -# If ranlib is not needed: -#RANLIB=ar rs -#RANLIBCMD= - -### How to invoke ar -#ARCMD=ar - -### Shared library support -# Extension for shared libraries: so if supported, a if not supported -#SO=so -#SO=a -# Set to nothing if shared libraries supported, and to -custom if not supported -#CUSTOM_IF_NOT_SHARED= -#CUSTOM_IF_NOT_SHARED=-custom -# Options to $(BYTECC) to produce shared objects (e.g. PIC) -#SHAREDCCCOMPOPTS=-fPIC -# How to build a shared library, invoked with output .so as first arg -# and object files as remaining args -#MKSHAREDLIB=gcc -shared -o -# Compile-time option to $(BYTECC) to add a directory to be searched -# at run-time for shared libraries -#RPATH=-Wl,-rpath - -############# Configuration for the native-code compiler - -### Name of architecture for the native-code compiler -### Currently supported: -### -### i386 Intel Pentium PCs under Linux, *BSD*, NextStep -### power Macintosh under Mac OS X and Linux -### arm ARM under Linux -### -### Set ARCH=none if your machine is not supported -#ARCH=i386 -#ARCH=power -#ARCH=arm -#ARCH=none - -### Name of architecture model for the native-code compiler. -### Some architectures come in several slightly different flavors -### that share a common code generator. This variable tailors the -### behavior of the code generator to the particular flavor used. -### Currently needed only if ARCH=power; leave MODEL=default for -### other architectures. -### If ARCH=power: set MODEL=ppc -### For other architectures: leave MODEL=default -### -#MODEL=ppc -#MODEL=default - -### Name of operating system family for the native-code compiler. -#SYSTEM=solaris -#SYSTEM=linux -#SYSTEM=linux_elf -#SYSTEM=bsd -#SYSTEM=unknown - -#NATIVECFLAGS= - -# For gcc if cautious: -#NATIVECCCOMPOPTS=-Wall - -# Compile-time option to $(NATIVECC) to add a directory to be searched -# at run-time for shared libraries -#RPATH=-Wl,-rpath - -### Command and flags to use for assembling ocamlopt-generated code -#ASM=as - -### Command and flags to use for assembling .S files (often with preprocessing) -# If gcc is available: -#ASPP=gcc -c -# On Solaris: -#ASPP=as -P - -### Extra flags to use for assembling .S files in profiling mode -#ASPPPROFFLAGS=-DPROFILING - -### Whether profiling with gprof is supported -# If yes: (e.g. x86/Linux): -#PROFILING=true -# If no: -#PROFILING=false - -### Option to give to the C compiler for profiling -#CC_PROFILE=-pg -#CC_PROFILE=-xpg - -############# Configuration for the contributed libraries - -### Which libraries to compile and install -# Currently available: -# unix Unix system calls -# str Regular expressions and high-level string processing -# threads Lightweight concurrent processes -# systhreads Same as threads, requires POSIX threads -# graph Portable drawing primitives for X11 -# dynlink Dynamic linking of bytecode -# bigarray Large, multidimensional numerical arrays - -OTHERLIBRARIES=unix str threads graph dynlink bigarray - -### Link-time options to ocamlc or ocamlopt for linking with POSIX threads -# Needed for the "systhreads" package -# Usually: -#PTHREAD_LINK=-cclib -lpthread -# For Solaris: -#PTHREAD_LINK=-cclib -lpthread -cclib -lposix4 - -### -I options for finding the X11/*.h includes -# Needed for the "graph" package -# Usually: -#X11_INCLUDES=-I/usr/X11R6/include -# For SunOS with OpenLook: -#X11_INCLUDES=/usr/openwin/include - -### Link-time options to ocamlc or ocamlopt for linking with X11 libraries -# Needed for the "graph" package -# Usually: -#X11_LINK=-lX11 -# For SunOS with OpenLook: -#X11_LINK=-L$(X11_LIB) -lX11 diff --git a/config/Makefile.mingw b/config/Makefile.mingw index 3f1eb9b4..c5a78f7b 100644 --- a/config/Makefile.mingw +++ b/config/Makefile.mingw @@ -28,11 +28,8 @@ WITH_OCAMLDOC=ocamldoc ### Where to install the binaries BINDIR=$(PREFIX)/bin -### Standard runtime system -BYTERUN=ocamlrun - ### Where to install the standard library -LIBDIR=$(PREFIX)/lib +LIBDIR=$(PREFIX)/lib/ocaml ### Where to install the stub DLLs STUBLIBDIR=$(LIBDIR)/stublibs @@ -75,9 +72,8 @@ X11_INCLUDES= X11_LINK= RPATH= SUPPORTS_SHARED_LIBRARIES=true -SHAREDCCCOMPOPTS= +SHAREDLIB_CFLAGS= MKSHAREDLIBRPATH= -NATIVECCPROFOPTS= ASM=$(TOOLPREF)as ASPP=$(TOOLPREF)gcc -c ASPPPROFFLAGS= @@ -108,20 +104,21 @@ DEFAULT_SAFE_STRING=true WINDOWS_UNICODE=1 AFL_INSTRUMENT=false AWK=gawk +CC_HAS_DEBUG_PREFIX_MAP=false +AS_HAS_DEBUG_PREFIX_MAP=false ########## Configuration for the bytecode compiler ### Which C compiler to use for the bytecode interpreter. CC=$(TOOLPREF)gcc -CFLAGS=-O -mms-bitfields -Wall -Wno-unused -fno-tree-vrp +OC_CFLAGS=-O -mms-bitfields -Wall -Wno-unused -fno-tree-vrp # -fno-tree-vrp is here to try to work around the Skylake/Kaby lake bug, # and only works on GCC 4.2 and later. -CPPFLAGS=-DCAML_NAME_SPACE -DUNICODE -D_UNICODE -DWINDOWS_UNICODE=$(WINDOWS_UNICODE) +OC_CPPFLAGS=-DCAML_NAME_SPACE -DUNICODE -D_UNICODE \ + -DWINDOWS_UNICODE=$(WINDOWS_UNICODE) OCAMLC_CFLAGS=-O -mms-bitfields -BYTECCDBGCOMPOPTS=-g - -LDFLAGS=-municode +OC_LDFLAGS=-municode ### Libraries needed BYTECCLIBS=-lws2_32 -lversion @@ -147,25 +144,21 @@ endif # $(FLEXLINK_CMD) $(FLEXLINK_FLAGS) [-exe|-maindll] # or OCAML_FLEXLINK overriding will not work (see utils/config.mlp) MKDLL=$(FLEXLINK) -MKEXE=$(MKEXE_ANSI) $(if $(LDFLAGS),-link "$(LDFLAGS)") +MKEXE=$(MKEXE_ANSI) $(if $(OC_LDFLAGS),-link "$(OC_LDFLAGS)") MKEXEDEBUGFLAG=-g MKMAINDLL=$(FLEXLINK) -maindll ### Native command to build ocamlrun.exe without flexlink -MKEXE_BOOT=$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUTEXE)$(1) $(2) +MKEXE_BOOT=$(CC) $(OC_CFLAGS) $(OC_LDFLAGS) $(OUTPUTEXE)$(1) $(2) ### Native command to build an ANSI executable MKEXE_ANSI=$(FLEXLINK) -exe ### How to build a static library MKLIB=rm -f $(1) && $(TOOLPREF)ar rcs $(1) $(2) -#ml let mklib out files opts = -#ml Printf.sprintf "%sar rcs %s %s %s" -#ml toolpref opts out files;; ### Canonicalize the name of a system library SYSLIB=-l$(1) -#ml let syslib x = "-l"^x;; ### The ranlib command RANLIB=$(TOOLPREF)ranlib @@ -178,6 +171,7 @@ ARCMD=$(TOOLPREF)ar ### Name of architecture for the native-code compiler ARCH=i386 +ARCH64=false ### Name of architecture model for the native-code compiler. MODEL=default @@ -190,12 +184,14 @@ OCAMLOPT_CFLAGS=-O -mms-bitfields ### Build partially-linked object file PACKLD=$(TOOLPREF)ld -r -o # must have a space after '-o' +### Set to "true" to install ".byte" executables (ocamlc.byte, etc.) +INSTALL_BYTECODE_PROGRAMS=true + ############# Configuration for the contributed libraries OTHERLIBRARIES=win32unix str win32graph dynlink bigarray systhreads ############# for the testsuite makefiles -#ml let topdir = "" and wintopdir = "";; OTOPDIR=$(WINTOPDIR) CTOPDIR=$(TOPDIR) CYGPATH=cygpath -m diff --git a/config/Makefile.mingw64 b/config/Makefile.mingw64 index df605a9f..4c50467c 100644 --- a/config/Makefile.mingw64 +++ b/config/Makefile.mingw64 @@ -28,11 +28,8 @@ WITH_OCAMLDOC=ocamldoc ### Where to install the binaries BINDIR=$(PREFIX)/bin -### Standard runtime system -BYTERUN=ocamlrun - ### Where to install the standard library -LIBDIR=$(PREFIX)/lib +LIBDIR=$(PREFIX)/lib/ocaml ### Where to install the stub DLLs STUBLIBDIR=$(LIBDIR)/stublibs @@ -75,9 +72,8 @@ X11_INCLUDES= X11_LINK= RPATH= SUPPORTS_SHARED_LIBRARIES=true -SHAREDCCCOMPOPTS= +SHAREDLIB_CFLAGS= MKSHAREDLIBRPATH= -NATIVECCPROFOPTS= ASM=$(TOOLPREF)as ASPP=$(TOOLPREF)gcc -c ASPPPROFFLAGS= @@ -108,20 +104,21 @@ DEFAULT_SAFE_STRING=true WINDOWS_UNICODE=1 AFL_INSTRUMENT=false AWK=gawk +CC_HAS_DEBUG_PREFIX_MAP=false +AS_HAS_DEBUG_PREFIX_MAP=false ########## Configuration for the bytecode compiler ### Which C compiler to use for the bytecode interpreter. CC=$(TOOLPREF)gcc -CFLAGS=-O -mms-bitfields -Wall -Wno-unused -fno-tree-vrp +OC_CFLAGS=-O -mms-bitfields -Wall -Wno-unused -fno-tree-vrp # -fno-tree-vrp is here to try to work around the Skylake/Kaby lake bug, # and only works on GCC 4.2 and later. -CPPFLAGS=-DCAML_NAME_SPACE -DUNICODE -D_UNICODE -DWINDOWS_UNICODE=$(WINDOWS_UNICODE) +OC_CPPFLAGS=-DCAML_NAME_SPACE -DUNICODE -D_UNICODE \ + -DWINDOWS_UNICODE=$(WINDOWS_UNICODE) OCAMLC_CFLAGS=-O -mms-bitfields -BYTECCDBGCOMPOPTS=-g - -LDFLAGS=-municode +OC_LDFLAGS=-municode ### Libraries needed BYTECCLIBS=-lws2_32 -lversion @@ -147,25 +144,21 @@ endif # $(FLEXLINK_CMD) $(FLEXLINK_FLAGS) [-exe|-maindll] # or OCAML_FLEXLINK overriding will not work (see utils/config.mlp) MKDLL=$(FLEXLINK) -MKEXE=$(MKEXE_ANSI) $(if $(LDFLAGS),-link "$(LDFLAGS)") +MKEXE=$(MKEXE_ANSI) $(if $(OC_LDFLAGS),-link "$(OC_LDFLAGS)") MKEXEDEBUGFLAG=-g MKMAINDLL=$(FLEXLINK) -maindll ### Native command to build ocamlrun.exe without flexlink -MKEXE_BOOT=$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUTEXE)$(1) $(2) +MKEXE_BOOT=$(CC) $(OC_CFLAGS) $(OC_LDFLAGS) $(OUTPUTEXE)$(1) $(2) ### Native command to build an ANSI executable MKEXE_ANSI=$(FLEXLINK) -exe ### How to build a static library MKLIB=rm -f $(1) && $(TOOLPREF)ar rcs $(1) $(2) -#ml let mklib out files opts = -#ml Printf.sprintf "%sar rcs %s %s %s" -#ml toolpref opts out files;; ### Canonicalize the name of a system library SYSLIB=-l$(1) -#ml let syslib x = "-l"^x;; ### The ranlib command RANLIB=$(TOOLPREF)ranlib @@ -178,6 +171,7 @@ ARCMD=$(TOOLPREF)ar ### Name of architecture for the native-code compiler ARCH=amd64 +ARCH64=true ### Name of architecture model for the native-code compiler. MODEL=default @@ -190,12 +184,14 @@ OCAMLOPT_CFLAGS=-O -mms-bitfields ### Build partially-linked object file PACKLD=$(TOOLPREF)ld -r -o # must have a space after '-o' +### Set to "true" to install ".byte" executables (ocamlc.byte, etc.) +INSTALL_BYTECODE_PROGRAMS=true + ############# Configuration for the contributed libraries OTHERLIBRARIES=win32unix str win32graph dynlink bigarray systhreads ############# for the testsuite makefiles -#ml let topdir = "" and wintopdir = "";; OTOPDIR=$(WINTOPDIR) CTOPDIR=$(TOPDIR) CYGPATH=cygpath -m diff --git a/config/Makefile.msvc b/config/Makefile.msvc index 743d3687..827e61e4 100644 --- a/config/Makefile.msvc +++ b/config/Makefile.msvc @@ -22,11 +22,8 @@ PREFIX=C:/ocamlms ### Where to install the binaries. BINDIR=$(PREFIX)/bin -### Standard runtime system -BYTERUN=ocamlrun - ### Where to install the standard library -LIBDIR=$(PREFIX)/lib +LIBDIR=$(PREFIX)/lib/ocaml ### Where to install the stub DLLs STUBLIBDIR=$(LIBDIR)/stublibs @@ -69,8 +66,7 @@ X11_INCLUDES= X11_LINK= RPATH= SUPPORTS_SHARED_LIBRARIES=true -SHAREDCCCOMPOPTS= -NATIVECCPROFOPTS= +SHAREDLIB_CFLAGS= ASM=ml -nologo -coff -Cp -c -Fo ASPP= ASPPPROFFLAGS= @@ -101,18 +97,20 @@ DEFAULT_SAFE_STRING=true WINDOWS_UNICODE=1 AFL_INSTRUMENT=false AWK=gawk +CC_HAS_DEBUG_PREFIX_MAP=false +AS_HAS_DEBUG_PREFIX_MAP=false ########## Configuration for the bytecode compiler ### Which C compiler to use for the bytecode interpreter. CC=cl -CFLAGS=-nologo -O2 -Gy- -MD -CPPFLAGS=-D_CRT_SECURE_NO_DEPRECATE -DCAML_NAME_SPACE -DUNICODE -D_UNICODE -DWINDOWS_UNICODE=$(WINDOWS_UNICODE) +OC_CFLAGS=-nologo -O2 -Gy- -MD +OC_CPPFLAGS=-D_CRT_SECURE_NO_DEPRECATE -DCAML_NAME_SPACE -DUNICODE -D_UNICODE \ + -DWINDOWS_UNICODE=$(WINDOWS_UNICODE) OCAMLC_CFLAGS=-nologo -O2 -Gy- -MD OCAMLC_CPPFLAGS=-D_CRT_SECURE_NO_DEPRECATE -BYTECCDBGCOMPOPTS=-Zi -LDFLAGS=/ENTRY:wmainCRTStartup +OC_LDFLAGS=/ENTRY:wmainCRTStartup ### Libraries needed BYTECCLIBS=advapi32.lib ws2_32.lib version.lib @@ -138,7 +136,7 @@ endif # $(FLEXLINK_CMD) $(FLEXLINK_FLAGS) [-exe|-maindll] # or OCAML_FLEXLINK overriding will not work (see utils/config.mlp) MKDLL=$(FLEXLINK) -MKEXE=$(MKEXE_ANSI) $(if $(LDFLAGS),-link "$(LDFLAGS)") +MKEXE=$(MKEXE_ANSI) $(if $(OC_LDFLAGS),-link "$(OC_LDFLAGS)") MKEXEDEBUGFLAG= MKMAINDLL=$(FLEXLINK) -maindll @@ -146,21 +144,18 @@ MKMAINDLL=$(FLEXLINK) -maindll MERGEMANIFESTEXE=test ! -f $(1).manifest \ || mt -nologo -outputresource:$(1) -manifest $(1).manifest \ && rm -f $(1).manifest -MKEXE_BOOT=$(CC) $(CFLAGS) $(OUTPUTEXE)$(1) $(2) /link /subsystem:console $(LDFLAGS) \ - && ($(MERGEMANIFESTEXE)) +MKEXE_BOOT=$(CC) $(OC_CFLAGS) $(OUTPUTEXE)$(1) $(2) \ + /link /subsystem:console $(OC_LDFLAGS) && ($(MERGEMANIFESTEXE)) ### Native command to build an ANSI executable MKEXE_ANSI=$(FLEXLINK) -exe ### How to build a static library MKLIB=link -lib -nologo -out:$(1) $(2) -#ml let mklib out files opts = -#ml Printf.sprintf "link -lib -nologo -out:%s %s %s" out opts files;; MKSHAREDLIBRPATH= ### Canonicalize the name of a system library SYSLIB=$(1).lib -#ml let syslib x = x ^ ".lib";; ### The ranlib command RANLIB=echo @@ -173,6 +168,7 @@ ARCMD= ### Name of architecture for the native-code compiler ARCH=i386 +ARCH64=false ### Name of architecture model for the native-code compiler. MODEL=default @@ -186,6 +182,9 @@ OCAMLOPT_CPPFLAGS=-D_CRT_SECURE_NO_DEPRECATE ### Build partially-linked object file PACKLD=link -lib -nologo -out:# there must be no space after this '-out:' +### Set to "true" to install ".byte" executables (ocamlc.byte, etc.) +INSTALL_BYTECODE_PROGRAMS=true + ### Clear this to disable compiling ocamldebug WITH_DEBUGGER=ocamldebugger @@ -197,7 +196,6 @@ WITH_OCAMLDOC=ocamldoc OTHERLIBRARIES=win32unix systhreads str win32graph dynlink bigarray ############# for the testsuite makefiles -#ml let topdir = "" and wintopdir = "";; OTOPDIR=$(WINTOPDIR) CTOPDIR=$(WINTOPDIR) CYGPATH=cygpath -m diff --git a/config/Makefile.msvc64 b/config/Makefile.msvc64 index 67bf16a2..b992a525 100644 --- a/config/Makefile.msvc64 +++ b/config/Makefile.msvc64 @@ -22,11 +22,8 @@ PREFIX=C:/ocamlms64 ### Where to install the binaries. BINDIR=$(PREFIX)/bin -### Standard runtime system -BYTERUN=ocamlrun - ### Where to install the standard library -LIBDIR=$(PREFIX)/lib +LIBDIR=$(PREFIX)/lib/ocaml ### Where to install the stub DLLs STUBLIBDIR=$(LIBDIR)/stublibs @@ -69,8 +66,7 @@ X11_INCLUDES= X11_LINK= RPATH= SUPPORTS_SHARED_LIBRARIES=true -SHAREDCCCOMPOPTS= -NATIVECCPROFOPTS= +SHAREDLIB_CFLAGS= ASM=ml64 -nologo -Cp -c -Fo ASPP= ASPPPROFFLAGS= @@ -100,19 +96,20 @@ DEFAULT_SAFE_STRING=true WINDOWS_UNICODE=1 AFL_INSTRUMENT=false AWK=gawk +CC_HAS_DEBUG_PREFIX_MAP=false +AS_HAS_DEBUG_PREFIX_MAP=false ########## Configuration for the bytecode compiler ### Which C compiler to use for the bytecode interpreter. CC=cl -CFLAGS=-nologo -O2 -Gy- -MD -CPPFLAGS=-D_CRT_SECURE_NO_DEPRECATE -DCAML_NAME_SPACE -DUNICODE -D_UNICODE -DWINDOWS_UNICODE=$(WINDOWS_UNICODE) +OC_CFLAGS=-nologo -O2 -Gy- -MD +OC_CPPFLAGS=-D_CRT_SECURE_NO_DEPRECATE -DCAML_NAME_SPACE -DUNICODE -D_UNICODE \ + -DWINDOWS_UNICODE=$(WINDOWS_UNICODE) OCAMLC_CFLAGS=-nologo -O2 -Gy- -MD OCAMLC_CPPFLAGS=-D_CRT_SECURE_NO_DEPRECATE -BYTECCDBGCOMPOPTS=-Zi - -LDFLAGS=/ENTRY:wmainCRTStartup +OC_LDFLAGS=/ENTRY:wmainCRTStartup ### Libraries needed #EXTRALIBS=bufferoverflowu.lib # for the old PSDK compiler only @@ -140,7 +137,7 @@ endif # $(FLEXLINK_CMD) $(FLEXLINK_FLAGS) [-exe|-maindll] # or OCAML_FLEXLINK overriding will not work (see utils/config.mlp) MKDLL=$(FLEXLINK) -MKEXE=$(MKEXE_ANSI) $(if $(LDFLAGS),-link "$(LDFLAGS)") +MKEXE=$(MKEXE_ANSI) $(if $(OC_LDFLAGS),-link "$(OC_LDFLAGS)") MKEXEDEBUGFLAG= MKMAINDLL=$(FLEXLINK) -maindll @@ -148,22 +145,18 @@ MKMAINDLL=$(FLEXLINK) -maindll MERGEMANIFESTEXE=test ! -f $(1).manifest \ || mt -nologo -outputresource:$(1) -manifest $(1).manifest \ && rm -f $(1).manifest -MKEXE_BOOT=$(CC) $(CFLAGS) $(OUTPUTEXE)$(1) $(2) /link /subsystem:console $(LDFLAGS) \ - && ($(MERGEMANIFESTEXE)) +MKEXE_BOOT=$(CC) $(OC_CFLAGS) $(OUTPUTEXE)$(1) $(2) \ + /link /subsystem:console $(OC_LDFLAGS) && ($(MERGEMANIFESTEXE)) ### Native command to build an ANSI executable MKEXE_ANSI=$(FLEXLINK) -exe ### How to build a static library MKLIB=link -lib -nologo -machine:AMD64 /out:$(1) $(2) -#ml let mklib out files opts = -#ml Printf.sprintf "link -lib -nologo -machine:AMD64 -out:%s %s %s" -#ml out opts files;; MKSHAREDLIBRPATH= ### Canonicalize the name of a system library SYSLIB=$(1).lib -#ml let syslib x = x ^ ".lib";; ### The ranlib command RANLIB=echo @@ -176,6 +169,7 @@ ARCMD= ### Name of architecture for the native-code compiler ARCH=amd64 +ARCH64=true ### Name of architecture model for the native-code compiler. MODEL=default @@ -189,6 +183,9 @@ OCAMLOPT_CPPFLAGS=-D_CRT_SECURE_NO_DEPRECATE ### Build partially-linked object file PACKLD=link -lib -nologo -machine:AMD64 -out:# must have no space after '-out:' +### Set to "true" to install ".byte" executables (ocamlc.byte, etc.) +INSTALL_BYTECODE_PROGRAMS=true + ### Clear this to disable compiling ocamldebug WITH_DEBUGGER=ocamldebugger @@ -200,7 +197,6 @@ WITH_OCAMLDOC=ocamldoc OTHERLIBRARIES=win32unix systhreads str win32graph dynlink bigarray ############# for the testsuite makefiles -#ml let topdir = "" and wintopdir = "";; OTOPDIR=$(WINTOPDIR) CTOPDIR=$(WINTOPDIR) CYGPATH=cygpath -m diff --git a/config/auto-aux/simple.S b/config/auto-aux/simple.S new file mode 100644 index 00000000..c27acb72 --- /dev/null +++ b/config/auto-aux/simple.S @@ -0,0 +1,3 @@ +camlPervasives__loop_1128: + .file 1 "pervasives.ml" + .loc 1 193 diff --git a/config/m-nt.h b/config/m-nt.h index 97ae9cf0..eae64b66 100644 --- a/config/m-nt.h +++ b/config/m-nt.h @@ -55,11 +55,4 @@ #define PROFINFO_WIDTH 0 -/* Microsoft introduced the LL integer literal suffix in Visual C++ .NET 2003 */ -#if defined(_MSC_VER) && _MSC_VER < 1400 -#define INT64_LITERAL(s) s ## i64 -#else -#define INT64_LITERAL(s) s ## LL -#endif - #define FLAT_FLOAT_ARRAY diff --git a/config/m-templ.h b/config/m-templ.h deleted file mode 100644 index 74ce64e1..00000000 --- a/config/m-templ.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* Processor dependencies */ - -#define ARCH_SIXTYFOUR - -/* Define ARCH_SIXTYFOUR if the processor has a natural word size of 64 bits. - That is, sizeof(char *) = 8. - Otherwise, leave ARCH_SIXTYFOUR undefined. - This assumes sizeof(char *) = 4. */ - -#define ARCH_BIG_ENDIAN - -/* Define ARCH_BIG_ENDIAN if the processor is big endian (the most - significant byte of an integer stored in memory comes first). - Leave ARCH_BIG_ENDIAN undefined if the processor is little-endian - (the least significant byte comes first). -*/ - -#define ARCH_ALIGN_DOUBLE - -/* Define ARCH_ALIGN_DOUBLE if the processor requires doubles to be - doubleword-aligned. Leave ARCH_ALIGN_DOUBLE undefined if the processor - supports word-aligned doubles. */ - -#undef ARCH_CODE32 - -/* Define ARCH_CODE32 if, on a 64-bit machine, code pointers fit in 32 bits, - i.e. the code segment resides in the low 4G of the addressing space. - ARCH_CODE32 is ignored on 32-bit machines. */ - -#define SIZEOF_INT 4 -#define SIZEOF_LONG 4 -#define SIZEOF_PTR 4 -#define SIZEOF_SHORT 2 - -/* Define SIZEOF_INT, SIZEOF_LONG, SIZEOF_PTR and SIZEOF_SHORT - to the sizes in bytes of the C types "int", "long", "char *" and "short", - respectively. */ - -#define ARCH_INT64_TYPE long long -#define ARCH_UINT64_TYPE unsigned long long - -/* Define ARCH_INT64_TYPE and ARCH_UINT64_TYPE to 64-bit integer types, - typically "long long" and "unsigned long long" on 32-bit platforms, - and "long" and "unsigned long" on 64-bit platforms. - If the C compiler doesn't support any 64-bit integer type, - leave both ARCH_INT64_TYPE and ARCH_UINT64_TYPE undefined. */ - -#define ARCH_INT64_PRINTF_FORMAT "ll" - -/* Define ARCH_INT64_PRINTF_FORMAT to the printf format used for formatting - values of type ARCH_INT64_TYPE. This is usually "ll" on 32-bit - platforms and "l" on 64-bit platforms. - Leave undefined if ARCH_INT64_TYPE is undefined. */ - -#define ARCH_ALIGN_INT64 - -/* Define ARCH_ALIGN_INT64 if the processor requires 64-bit integers to be - doubleword-aligned. Leave ARCH_ALIGN_INT64 undefined if the processor - supports word-aligned 64-bit integers. Leave undefined if - 64-bit integers are not supported. */ - -#undef NONSTANDARD_DIV_MOD - -/* Leave NONSTANDARD_DIV_MOD undefined if the C operators / and % implement - round-towards-zero semantics, as specified by ISO C 9x and implemented - by most contemporary processors. Otherwise, or if you don't know, - define NONSTANDARD_DIV_MOD: this will select a slower but correct - software emulation of division and modulus. */ diff --git a/config/s-nt.h b/config/s-nt.h index ab4046b3..9947158e 100644 --- a/config/s-nt.h +++ b/config/s-nt.h @@ -29,7 +29,10 @@ #define HAS_GETHOSTNAME #define HAS_MKTIME #define HAS_PUTENV -#define HAS_LOCALE +#ifndef __MINGW32__ +#define HAS_LOCALE_H +#define HAS_STRTOD_L +#endif #define HAS_BROKEN_PRINTF #define HAS_IPV6 #define HAS_NICE diff --git a/config/s-templ.h b/config/s-templ.h deleted file mode 100644 index 1df4eb31..00000000 --- a/config/s-templ.h +++ /dev/null @@ -1,214 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* Operating system and standard library dependencies. */ - -/* 0. Operating system type string. */ - -#define OCAML_OS_TYPE "Unix" -/* #define OCAML_OS_TYPE "Win32" */ -/* #define OCAML_OS_TYPE "MacOS" */ - -/* 1. For the runtime system. */ - -#define POSIX_SIGNALS - -/* Define POSIX_SIGNALS if signal handling is POSIX-compliant. - In particular, sigaction(), sigprocmask() and the operations on - sigset_t are provided. */ - -#define BSD_SIGNALS - -/* Define BSD_SIGNALS if signal handlers have the BSD semantics: the handler - remains attached to the signal when the signal is received. Leave it - undefined if signal handlers have the System V semantics: the signal - resets the behavior to default. */ - -#define HAS_SIGSETMASK - -/* Define HAS_SIGSETMASK if you have sigsetmask(), as in BSD. */ - -#define SUPPORT_DYNAMIC_LINKING - -/* Define SUPPORT_DYNAMIC_LINKING if dynamic loading of C stub code - via dlopen() is available. */ - -#define HAS_C99_FLOAT_OPS - -/* Define HAS_C99_FLOAT_OPS if conforms to ISO C99. - In particular, it should provide expm1(), log1p(), hypot(), copysign(). */ - -/* 2. For the Unix library. */ - -#define HAS_SOCKETS - -/* Define HAS_SOCKETS if you have BSD sockets. */ - -#define HAS_SOCKLEN_T - -/* Define HAS_SOCKLEN_T if the type socklen_t is defined in - /usr/include/sys/socket.h. */ - -#define HAS_UNISTD - -/* Define HAS_UNISTD if you have /usr/include/unistd.h. */ - -#define HAS_DIRENT - -/* Define HAS_DIRENT if you have /usr/include/dirent.h and the result of - readdir() is of type struct dirent *. - Otherwise, we'll load /usr/include/sys/dir.h, and readdir() is expected to - return a struct direct *. */ - -#define HAS_REWINDDIR - -/* Define HAS_REWINDDIR if you have rewinddir(). */ - -#define HAS_LOCKF - -/* Define HAS_LOCKF if the library provides the lockf() function. */ - -#define HAS_MKFIFO - -/* Define HAS_MKFIFO if the library provides the mkfifo() function. */ - -#define HAS_GETCWD - -/* Define HAS_GETCWD if the library provides the getcwd() function. */ - -#define HAS_GETPRIORITY - -/* Define HAS_GETPRIORITY if the library provides getpriority() and - setpriority(). Otherwise, we'll use nice(). */ - -#define HAS_UTIME -#define HAS_UTIMES - -/* Define HAS_UTIME if you have /usr/include/utime.h and the library - provides utime(). Define HAS_UTIMES if the library provides utimes(). */ - -#define HAS_DUP2 - -/* Define HAS_DUP2 if you have dup2(). */ - -#define HAS_FCHMOD - -/* Define HAS_FCHMOD if you have fchmod() and fchown(). */ - -#define HAS_TRUNCATE - -/* Define HAS_TRUNCATE if you have truncate() and - ftruncate(). */ - -#define HAS_SELECT - -/* Define HAS_SELECT if you have select(). */ - -#define HAS_SYS_SELECT_H - -/* Define HAS_SYS_SELECT_H if /usr/include/sys/select.h exists - and should be included before using select(). */ - -#define HAS_NANOSLEEP -/* Define HAS_NANOSLEEP if you have nanosleep(). */ - -#define HAS_SYMLINK - -/* Define HAS_SYMLINK if you have symlink() and readlink() and lstat(). */ - -#define HAS_WAIT4 -#define HAS_WAITPID - -/* Define HAS_WAIT4 if you have wait4(). - Define HAS_WAITPID if you have waitpid(). */ - -#define HAS_GETGROUPS - -/* Define HAS_GETGROUPS if you have getgroups(). */ - -#define HAS_SETGROUPS - -/* Define HAS_SETGROUPS if you have setgroups(). */ - -#define HAS_INITGROUPS - -/* Define HAS_INITGROUPS if you have initgroups(). */ - -#define HAS_TERMIOS - -/* Define HAS_TERMIOS if you have /usr/include/termios.h and it is - Posix-compliant. */ - -#define HAS_ASYNC_IO - -/* Define HAS_ASYNC_IO if BSD-style asynchronous I/O are supported - (the process can request to be sent a SIGIO signal when a descriptor - is ready for reading). */ - -#define HAS_SETITIMER - -/* Define HAS_SETITIMER if you have setitimer(). */ - -#define HAS_GETHOSTNAME - -/* Define HAS_GETHOSTNAME if you have gethostname(). */ - -#define HAS_UNAME - -/* Define HAS_UNAME if you have uname(). */ - -#define HAS_GETTIMEOFDAY - -/* Define HAS_GETTIMEOFDAY if you have gettimeofday(). */ - -#define HAS_MKTIME - -/* Define HAS_MKTIME if you have mktime(). */ - -#define HAS_SETSID - -/* Define HAS_SETSID if you have setsid(). */ - -#define HAS_PUTENV - -/* Define HAS_PUTENV if you have putenv(). */ - -#define HAS_LOCALE - -/* Define HAS_LOCALE if you have the include file and the - setlocale() function. */ - -#define HAS_MMAP - -/* Define HAS_MMAP if you have the include file and the - functions mmap() and munmap(). */ - -#define HAS_GETHOSTBYNAME_R 6 - -/* Define HAS_GETHOSTBYNAME_R if gethostbyname_r() is available. - The value of this symbol is the number of arguments of - gethostbyname_r(): either 5 or 6 depending on prototype. - (5 is the Solaris version, 6 is the Linux version). */ - -#define HAS_GETHOSTBYADDR_R 8 - -/* Define HAS_GETHOSTBYADDR_R if gethostbyname_r() is available. - The value of this symbol is the number of arguments of - gethostbyaddr_r(): either 7 or 8 depending on prototype. - (7 is the Solaris version, 8 is the Linux version). */ - -#define HAS_NICE - -/* Define HAS_NICE if you have nice(). */ diff --git a/configure b/configure index 1316b3c1..4e8ad00a 100755 --- a/configure +++ b/configure @@ -1,2320 +1,19167 @@ #! /bin/sh - -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -ocamlversion=`head -1 VERSION` -echo "Configuring OCaml version $ocamlversion" - -configure_options="$*" -prefix=/usr/local -bindir='' -target_bindir='' -libdir='' -mandir='' -programs_man_section=1 -libraries_man_section=3 -host_type=unknown -target_type="" -ccoption='' -cpp='cpp' -asoption='' -asppoption='' -cclibs='' -mathlib='-lm' -dllib='' -x11_include_dir='' -x11_lib_dir='' -libunwind_include_dir='' -libunwind_lib_dir='' -libunwind_available=false -disable_libunwind=false -graph_wanted=yes -pthread_wanted=yes -dl_defs='' -verbose=false -debugruntime=true -with_sharedlibs=true -partialld="ld -r" -with_debugger=ocamldebugger -with_ocamldoc=ocamldoc -with_frame_pointers=false -with_spacetime=false -enable_call_counts=true -with_profinfo=false -profinfo_width=0 -no_naked_pointers=false -native_compiler=true -TOOLPREF="" -with_cfi=true -flambda=false -force_safe_string=false -default_safe_string=true -afl_instrument=false -max_testsuite_dir_retries=0 -with_cplugins=false -with_fpic=false -flat_float_array=true -with_flambda_invariants=false - -# we distinguish '' (not set) from 'true' (explicitly set by the user) -with_instrumented_runtime='' - -# Try to turn internationalization off, can cause config.guess to malfunction! -unset LANG -unset LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME - -# Turn off some MacOS X debugging stuff, same reason -unset RC_TRACE_ARCHIVES RC_TRACE_DYLIBS RC_TRACE_PREBINDING_DISABLED - -# The inf(), wrn(), err() functions below can be used to provide a consistent -# way to notify the user. The notification is always given to the stdout -# descriptor. +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for OCaml 4.08.0. # -# Their output is redirected to a file-descriptor "3" which is then redirected -# to fd 1 at the level of the whole configure script. This is done to not -# conflict with how values are returned from functions in shell script. -# Consider the following where "It works!" would be mixed with "42". -# do_foo() { -# if some_command; then -# inf "It works!" -# echo "42" -# fi -# } -inf() { - printf "%b\n" "$*" 1>&3 -} - -wrn() { - printf "[WARNING] %b\n" "$*" 1>&3 -} - -err() { - printf "[ERROR!] %b\n" "$*" 1>&3 - exit 2 -} - -exec 3>&1 - -# Parse command-line arguments - -while : ; do - case "$1" in - "") break;; - -prefix|--prefix) - prefix=$2; shift;; - -bindir|--bindir) - bindir=$2; shift;; - -target-bindir|--target-bindir) - target_bindir="$2"; shift;; - -libdir|--libdir) - libdir=$2; shift;; - -mandir|--mandir) - case "$2" in - */man[1-9ln]) - mandir=`echo $2 | sed -e 's|^\(.*\)/man.$|\1|'` - programs_man_section=`echo $2 | sed -e 's/^.*\(.\)$/\1/'`;; - *) - mandir=$2;; - esac - shift;; - -libunwinddir|--libunwinddir) - libunwind_include_dir=$2/include; - libunwind_lib_dir=$2/lib; - shift;; - -libunwindlib|--libunwindlib) - libunwind_lib_dir=$2; shift;; - -libunwindinclude|--libunwindinclude) - libunwind_include_dir=$2; shift;; - -disable-libunwind|--disable-libunwind) - disable_libunwind=true;; - -host*|--host*) - host_type=$2; shift;; - -target*|--target*) - target_type=$2; shift;; - -cc*) - ccoption="$2"; shift;; - -as) - asoption="$2"; shift;; - -aspp) - asppoption="$2"; shift;; - -lib*) - cclibs="$2 $cclibs"; shift;; - -no-curses|--no-curses) - ;; # Ignored for backward compatibility - -no-shared-libs|--no-shared-libs) - with_sharedlibs=false;; - -x11include*|--x11include*) - x11_include_dir=$2; shift;; - -x11lib*|--x11lib*) - x11_lib_dir=$2; shift;; - -no-graph|--no-graph) graph_wanted=no;; - -with-pthread*|--with-pthread*) - ;; # Ignored for backward compatibility - -no-pthread*|--no-pthread*) - pthread_wanted=no;; - -partialld|--partialld) - partialld="$2"; shift;; - -dldefs*|--dldefs*) - dl_defs="$2"; shift;; - -dllibs*|--dllibs*) - dllib="$2"; shift;; - -verbose|--verbose) - verbose=true;; - -with-debug-runtime|--with-debug-runtime) - debugruntime=true;; # default - -no-debug-runtime|--no-debug-runtime) - debugruntime=false;; - -with-instrumented-runtime|--with-instrumented-runtime) - with_instrumented_runtime=true;; - -no-instrumented-runtime|--no-instrumented-runtime) - with_instrumented_runtime=false;; - -no-debugger|--no-debugger) - with_debugger="";; - -no-ocamldoc|--no-ocamldoc) - with_ocamldoc="";; - -no-ocamlbuild|--no-ocamlbuild) - ;; # ignored for backward compatibility - -with-frame-pointers|--with-frame-pointers) - with_frame_pointers=true;; - -no-naked-pointers|--no-naked-pointers) - no_naked_pointers=true;; - -spacetime|--spacetime) - with_spacetime=true; with_profinfo=true; profinfo_width=26;; - -disable-call-counts|--disable-call-counts) - enable_call_counts=false;; - -reserved-header-bits|--reserved-header-bits) - with_spacetime=false; with_profinfo=true; profinfo_width=$2;shift - case $profinfo_width in - 0) with_profinfo=false;; - [0123456789]);; - 1?|2?);; - 3[012]);; - *) err "--reserved-header-bits argument must be less than 32" - esac - ;; - -no-cfi|--no-cfi) - with_cfi=false;; - -no-native-compiler|--no-native-compiler) - native_compiler=false;; - -flambda|--flambda) - flambda=true;; - -with-flambda-invariants|--with-flambda-invariants) - with_flambda_invariants=true;; - -with-cplugins|--with-cplugins) - with_cplugins=true;; - -no-cplugins|--no-cplugins) - ;; # Ignored for backward compatibility - -fPIC|--fPIC) - with_fpic=true;; - - # There are two configure-time string safety options, - # -(no-)force-safe-string and -default-(un)safe-string that - # interact with a compile-time (un)safe-string option. - # - # If -force-safe-string is set at configure time, then the compiler - # will always enforce that string and bytes are distinct: the - # compile-time -unsafe-string option is disabled. This lets us - # assume pervasive string immutability, for code optimizations and - # in the C layer. - # - # If -no-force-safe-string is set at configure-time, the compiler - # will use the compile-time (un)safe-string option to decide whether - # string and bytes are compatible on a per-file basis. The - # configure-time options default-(un)safe-string decide which - # setting will be chosen by default, if no compile-time option is - # explicitly passed. - # - # The configure-time behavior of OCaml 4.05 and older was equivalent - # to -no-force-safe-string -default-unsafe-string. OCaml 4.06 - # uses -no-force-safe-string -default-safe-string. We - # expect -force-safe-string to become the default in the future. - -force-safe-string|--force-safe-string) - force_safe_string=true;; - -no-force-safe-string|--no-force-safe-string) - force_safe_string=false;; - -default-safe-string|--default-safe-string) - default_safe_string=true;; - -default-unsafe-string|--default-unsafe-string) - default_safe_string=false;; - -flat-float-array|--flat-float-array) - flat_float_array=true;; - -no-flat-float-array|--no-flat-float-array) - flat_float_array=false;; - -afl-instrument) - afl_instrument=true;; - *) if echo "$1" | grep -q -e '^--\?[a-zA-Z0-9-]\+='; then - err "configure expects arguments of the form '-prefix /foo/bar'," \ - "not '-prefix=/foo/bar' (note the '=')." - else - err "Unknown option \"$1\"." - fi;; - esac - shift -done - -# Sanity checks +# Report bugs to . +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## -case "$prefix" in - /*) ;; - *) err "The -prefix directory must be absolute.";; -esac -case "$bindir" in - /*) ;; - "") ;; - '$(PREFIX)/'*) ;; - *) err 'The -bindir directory must be absolute or relative to $(PREFIX).';; -esac -case "$libdir" in - /*) ;; - "") ;; - '$(PREFIX)/'*) ;; - *) err 'The -libdir directory must be absolute or relative to $(PREFIX).';; -esac -case "$mandir" in - /*) ;; - "") ;; - '$(PREFIX)/'*) ;; - *) err 'The -mandir directory must be absolute or relative to $(PREFIX).';; +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; esac +fi -# Generate the files - -cd config/auto-aux -rm -f s.h m.h Makefile -touch s.h m.h Makefile -# Write options to Makefile +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi -config() { -# This function hardens the generated Makefile against '#' symbols -# present in a source path (opam-compiler-conf may pick such directory -# names if working from a branch named 'PR#4242-answer-all-questions') -# by escaping them into '\#'. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi -# When injecting data in Makefiles, it is customary to also escape -# '$', which get turned into '$$'. However, this transformation is -# invalid here as some of the variables are meant to be code -# interpreted by make: for example, passing -# --bindir "$(PREFIX)/bin2" -# is explicitly supported (see "or relative to $(PREFIX)" messages above). -# Finally, it is also impossible for the user to escape the '#' signs -# before calling this configure script, given that -# $(PREFIX) is also injected in C code where this escape is invalid -# -- see the definition of the OCAML_STDLIB_DIR macro below. +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" - echo "$1=$2" | sed 's/#/\\#/g' >> Makefile -} +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS -echo "# generated by ./configure $configure_options" >> Makefile -config CONFIGURE_ARGS "$configure_options" + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi -# Where to install +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' -config PREFIX "$prefix" -case "$bindir" in - "") config BINDIR '$(PREFIX)/bin' - bindir="$prefix/bin";; - *) config BINDIR "$bindir";; -esac +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE -config BYTERUN '$(BINDIR)/ocamlrun' +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH -case "$libdir" in - "") config LIBDIR '$(PREFIX)/lib/ocaml' - libdir="$prefix/lib/ocaml";; - *) config LIBDIR "$libdir";; +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; esac -config STUBLIBDIR '$(LIBDIR)/stublibs' -case "$mandir" in - "") config MANDIR '$(PREFIX)/man' - mandir="$prefix/man";; - *) config MANDIR "$mandir";; +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; esac -config PROGRAMS_MAN_SECTION "$programs_man_section" -config LIBRARIES_MAN_SECTION "$libraries_man_section" +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } -# Determine the system type +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : -if test "$host_type" = "unknown"; then - if host_type=`sh ../gnu/config.guess`; then :; else - err "Cannot guess host type. You must specify one with the -host option." - fi -fi -if host=`sh ../gnu/config.sub $host_type`; then :; else - err "Please specify the correct host type with the -host option" +else + exitcode=1; echo positional parameters were not saved. fi -inf "Configuring for host $host ..." +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 -if test -n "$target_type"; then - target="$target_type" - TOOLPREF="${target}-" + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes else - target="$host" + as_have_required=no fi -inf "Configuring for target $target ..." + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : -if [ x"$host" = x"$target" ]; then - cross_compiler=false else - cross_compiler=true + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + -# Do we have gcc? + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi -if test -z "$ccoption"; then - if sh ./searchpath "${TOOLPREF}gcc"; then - cc="${TOOLPREF}gcc" + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." else - if $cross_compiler; then - err "No cross-compiler found for ${target}.\n" \ - "It should be named ${TOOLPREF}gcc and be in the PATH." - else - cc="cc" - fi + $as_echo "$0: Please tell bug-autoconf@gnu.org and caml-list@inria.fr +$0: about your system, including any error possibly output +$0: before this message. Then install a modern shell, or +$0: manually run the script under such a shell if you do +$0: have one." fi -else - cc="$ccoption" + exit 1 +fi fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS -inf "Using compiler $cc." +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset -# Configure compiler to use in further tests. +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status -export cc verbose +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit -# Determine the C compiler family (GCC, Clang, etc) +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ -ccfamily=`$cc -E cckind.c | grep '^[a-z]' | tr -s ' ' '-'` -case $? in - 0) inf "Compiler family and version: $ccfamily.";; - *) err "Unable to preprocess the test program.\n" \ - "Make sure the C compiler $cc is properly installed.";; -esac + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" -# The BYTECODE_C_COMPILER make variable says how the C compiler should be -# invoked to process a third-party C source file passed to ocamlc -# when no -cc command-line option has been specified. -# The BYTECCCOMPOPTS make variable contains options to pass to the C -# compiler but only when compiling C files that belong to the OCaml -# distribution. -# In other words, when ocamlc is called to compile a third-party C -# source file, it will _not_ pass these options to the C compiler. +} # as_fn_mkdir_p -# The SHAREDCCCOMPOPTS make variable contains options to use to compile C -# source files so that the resulting object files can then be integrated -# into shared libraries. It is passed to BYTECC for both C source files -# in the OCaml distribution and third-party C source files compiled -# with ocamlc. +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append -mkexe="\$(CC) \$(CFLAGS) \$(CPPFLAGS) \$(LDFLAGS)" -mkexedebugflag="-g" -common_cflags="" -common_cppflags="" -internal_cflags="" -internal_cppflags="" -ocamlc_cflags="" -ocamlc_cppflags="" -ocamlopt_cflags="" -ocamlopt_cppflags="" -ldflags="" -ostype="Unix" -exe="" -iflexdir="" -SO="so" -TOOLCHAIN="cc" +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith -# Choose reasonable options based on compiler kind -# We select high optimization levels, provided we can turn off: -# - strict type-based aliasing analysis (too risky for the OCaml runtime) -# - strict no-overflow conditions on signed integer arithmetic -# (the OCaml runtime assumes Java-style behavior of signed integer arith.) -# Concerning optimization level, -O3 is somewhat risky, so take -O2. -# Concerning language version, gnu99 is ISO C99 plus GNU extensions -# that are often used in standard headers. Older GCC versions -# defaults to gnu89, which is not C99. Clang defaults to gnu99 or -# gnu11, which is fine. -case "$ocamlversion" in - *+dev*) gcc_warnings="-Wall -Werror";; - *) gcc_warnings="-Wall";; -esac +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error -case "$ccfamily" in - clang-*) - common_cflags="-O2 -fno-strict-aliasing -fwrapv"; - internal_cflags="$gcc_warnings";; - gcc-[012]-*) - # Some versions known to miscompile OCaml, e,g, 2.7.2.1, some 2.96. - # Plus: C99 support unknown. - err "This version of GCC is too old. Please use GCC version 4.2 or above.";; - gcc-3-*|gcc-4-[01]) - # No -fwrapv option before GCC 3.4. - # Known problems with -fwrapv fixed in 4.2 only. - wrn "This version of GCC is rather old. Reducing optimization level." - wrn "Consider using GCC version 4.2 or above." - common_cflags="-std=gnu99 -O"; - internal_cflags="$gcc_warnings";; - gcc-4-*) - common_cflags="-std=gnu99 -O2 -fno-strict-aliasing -fwrapv \ --fno-builtin-memcmp"; - internal_cflags="$gcc_warnings";; - gcc-*) - common_cflags="-O2 -fno-strict-aliasing -fwrapv"; - internal_cflags="$gcc_warnings";; - *) - common_cflags="-O";; -esac +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi -internal_cppflags="-DCAML_NAME_SPACE $internal_cppflags" +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi -# Adjust according to target +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi -case "$cc,$target" in - *,*-*-rhapsody*) - common_cppflags="-DSHRINKED_GNUC $common_cppflags" - mathlib="";; - *,*-*-darwin*) - mathlib="" - mkexe="$mkexe -Wl,-no_compact_unwind" - # Tell gcc that we can use 32-bit code addresses for threaded code - # unless we are compiled for a shared library (-fPIC option) - echo "#ifndef __PIC__" >> m.h - echo "# define ARCH_CODE32" >> m.h - echo "#endif" >> m.h;; - *,*-*-haiku*) - # No -lm library - mathlib="";; - *,*-*-beos*) - # No -lm library - mathlib="";; - *gcc,alpha*-*-osf*) - if sh ./hasgot -mieee; then - common_cflags="-mieee $common_cflags"; - fi - # Put code and static data in lower 4GB - ldflags="-Wl,-T,12000000 -Wl,-D,14000000" - # Tell gcc that we can use 32-bit code addresses for threaded code - echo "#define ARCH_CODE32" >> m.h;; - cc,alpha*-*-osf*) - common_cflags="-std1 -ieee";; - *gcc*,alpha*-*-linux*) - if sh ./hasgot -mieee; then - common_cflags="-mieee $common_cflags"; - fi;; - *,mips-*-irix6*) - # Turn off warning "unused library" - ldflags="-n32 -Wl,-woff,84";; - *,alpha*-*-unicos*) - # For the Cray T3E - common_cppflags="$common_cppflags -DUMK";; - *,powerpc-*-aix*) - # Avoid name-space pollution by requiring Unix98-conformant includes - common_cppflags="$common_cppflags -D_XOPEN_SOURCE=500 -D_ALL_SOURCE";; - *,*-*-cygwin*) - case $target in - i686-*) flavor=cygwin;; - x86_64-*) flavor=cygwin64;; - *) err "unknown cygwin variant";; - esac - common_cppflags="$common_cppflags -U_WIN32" - if $with_sharedlibs; then - flexlink="flexlink -chain $flavor -merge-manifest -stack 16777216" - flexdir=`$flexlink -where | tr -d '\015'` - if test -z "$flexdir"; then - wrn "flexlink not found: native shared libraries won't be available." - with_sharedlibs=false - else - iflexdir="-I\"$flexdir\"" - mkexe="$flexlink -exe" - mkexedebugflag="-link -g" - fi - fi - if ! $with_sharedlibs; then - mkexe="$mkexe -Wl,--stack,16777216" - ldflags="-Wl,--stack,16777216" - fi - exe=".exe" - ostype="Cygwin";; - *,*-*-mingw*) - if $with_sharedlibs; then - case "$target" in - i686-*-*) flexlink_chain="mingw";; - x86_64-*-*) flexlink_chain="mingw64";; - esac - flexlink="flexlink -chain $flexlink_chain -merge-manifest -stack 16777216" - flexdir=`$flexlink -where` - if test -z "$flexdir"; then - wrn "flexlink not found: native shared libraries won't be available." - with_sharedlibs=false - else - iflexdir="-I\"$flexdir\"" - mkexe="$flexlink -exe" - mkexedebugflag="-link -g" - fi - fi - exe=".exe" - ostype="Win32" - TOOLCHAIN="mingw" - SO="dll" - ;; - *,x86_64-*-linux*) - # Tell gcc that we can use 32-bit code addresses for threaded code - # unless we are compiled for a shared library (-fPIC option) - echo "#ifndef __PIC__" >> m.h - echo "# define ARCH_CODE32" >> m.h - echo "#endif" >> m.h;; -esac +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` -# Configure compiler options to use in further tests. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits -export cclibs ldflags -# Check C compiler. + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } -cflags="$common_cflags $internal_cflags" sh ./runtest ansi.c -case $? in - 0) inf "The C compiler is ISO C99 compliant." ;; - 1) wrn "The C compiler is ANSI / ISO C90 compliant, but not ISO C99" \ - "compliant.";; - 2) err "The C compiler $cc is not ISO C compliant.\n" \ - "You need an ISO C99 compiler to build OCaml.";; - *) - if $cross_compiler; then - wrn "Unable to compile the test program.\n" \ - "This failure is expected for cross-compilation:\n" \ - "we will assume the C compiler is ISO C99-compliant." - else - err "Unable to compile the test program.\n" \ - "Make sure the C compiler $cc is properly installed." - fi;; -esac - -# For cross-compilation, we need a host-based ocamlrun and ocamlyacc, -# and the user must specify the target BINDIR -if $cross_compiler; then - if ! sh ./searchpath ocamlrun; then - err "Cross-compilation requires an ocaml runtime environment\n" \ - "(the ocamlrun binary). Moreover, its version must be the same\n" \ - "as the one you're trying to build (`cut -f1 -d+ < ../../VERSION`)." - else - ocaml_system_version=`ocamlrun -version | sed 's/[^0-9]*\([0-9.]*\).*/\1/'` - ocaml_source_version=`sed -n '1 s/\([0-9\.]*\).*/\1/ p' < ../../VERSION` - if test x"$ocaml_system_version" != x"$ocaml_source_version"; then - err "While you have an ocaml runtime environment, its version\n" \ - "($ocaml_system_version) doesn't match the version of these\n" \ - "sources ($ocaml_source_version)." - else - config CAMLRUN "`./searchpath -p ocamlrun`" - fi - fi + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} - if ! sh ./searchpath ocamlyacc; then - err "Cross-compilation requires an ocamlyacc binary." +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln else - ocamlyacc 2>/dev/null - if test "$?" -ne 1; then - err "While you have an ocamlyacc binary, it cannot be executed" \ - "successfully." - else - config CAMLYACC "`./searchpath -p ocamlyacc`" - fi + as_ln_s='cp -pR' fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null - if [ -z "$target_bindir" ]; then - err "Cross-compilation requires -target-bindir." - else - config TARGET_BINDIR "$target_bindir" - fi -fi # cross-compiler - - -# Check the sizes of data types -# OCaml needs a 32 or 64 bit architecture, a 32-bit integer type and -# a 64-bit integer type - -inf "Checking the sizes of integers and pointers..." -ret=`sh ./runtest sizes.c` -# $1 = sizeof(int) -# $2 = sizeof(long) -# $3 = sizeof(pointers) -# $4 = sizeof(short) -# $5 = sizeof(long long) - -if test "$?" -eq 0; then - set $ret - case "$3" in - 4) inf "OK, this is a regular 32 bit architecture." - echo "#undef ARCH_SIXTYFOUR" >> m.h - arch64=false;; - 8) inf "Wow! A 64 bit architecture!" - echo "#define ARCH_SIXTYFOUR" >> m.h - arch64=true;; - *) err "This architecture seems to be neither 32 bits nor 64 bits.\n" \ - "OCaml won't run on this architecture.";; - esac +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' else - # For cross-compilation, runtest always fails: add special handling. - case "$target" in - i686-*-mingw*) inf "OK, this is a regular 32 bit architecture." - echo "#undef ARCH_SIXTYFOUR" >> m.h - set 4 4 4 2 8 - arch64=false;; - x86_64-*-mingw*) inf "Wow! A 64 bit architecture!" - echo "#define ARCH_SIXTYFOUR" >> m.h - set 4 4 8 2 8 - arch64=true;; - *) err "Since datatype sizes cannot be guessed when cross-compiling,\n" \ - "a hardcoded list is used but your architecture isn't known yet.\n" \ - "You need to determine the sizes yourself.\n" \ - "Please submit a bug report in order to expand the list." ;; - esac + test -d ./-p && rmdir ./-p + as_mkdir_p=false fi -if test $1 != 4 && test $2 != 4 && test $4 != 4; then - err "Sorry, we can't find a 32-bit integer type\n" \ - "(sizeof(short) = $4, sizeof(int) = $1, sizeof(long) = $2)\n" \ - "OCaml won't run on this architecture." -fi - -if test $2 != 8 && test $5 != 8; then - err "Sorry, we can't find a 64-bit integer type\n" \ - "(sizeof(long) = $2, sizeof(long long) = $5)\n" \ - "OCaml won't run on this architecture." -fi - -echo "#define SIZEOF_INT $1" >> m.h -echo "#define SIZEOF_LONG $2" >> m.h -echo "#define SIZEOF_PTR $3" >> m.h -echo "#define SIZEOF_SHORT $4" >> m.h -echo "#define SIZEOF_LONGLONG $5" >> m.h -echo "#define INT64_LITERAL(s) s ## LL" >> m.h - -# Determine endianness - -sh ./runtest endian.c -case $? in - 0) inf "This is a big-endian architecture." - echo "#define ARCH_BIG_ENDIAN" >> m.h;; - 1) inf "This is a little-endian architecture." - echo "#undef ARCH_BIG_ENDIAN" >> m.h;; - 2) err "This architecture seems to be neither big endian nor little" \ - "endian.\n OCaml won't run on this architecture.";; - *) case $target in - *-*-mingw*) inf "This is a little-endian architecture." - echo "#undef ARCH_BIG_ENDIAN" >> m.h;; - *) wrn "Something went wrong during endianness determination.\n" \ - "You will have to figure out endianness yourself\n" \ - "(option ARCH_BIG_ENDIAN in m.h).";; - esac;; -esac - -# Determine alignment constraints - -case "$target" in - sparc*-*-*|hppa*-*-*|arm*-*-*|mips*-*-*) - # On Sparc V9 with certain versions of gcc, determination of double - # alignment is not reliable (PR#1521), hence force it. - # Same goes for hppa. - # PR#5088 suggests same problem on ARM. - # PR#5280 reports same problem on MIPS. - # But there's a knack (PR#2572): - # if we're in 64-bit mode (sizeof(long) == 8), - # we must not doubleword-align floats... - if test $2 = 8; then - inf "Doubles can be word-aligned." - echo "#undef ARCH_ALIGN_DOUBLE" >> m.h - else - inf "Doubles must be doubleword-aligned." - echo "#define ARCH_ALIGN_DOUBLE" >> m.h - fi;; - *) - sh ./runtest dblalign.c - case $? in - 0) inf "Doubles can be word-aligned." - echo "#undef ARCH_ALIGN_DOUBLE" >> m.h;; - 1) inf "Doubles must be doubleword-aligned." - echo "#define ARCH_ALIGN_DOUBLE" >> m.h;; - *) case "$target" in - *-*-mingw*) inf "Doubles can be word-aligned." - echo "#undef ARCH_ALIGN_DOUBLE" >> m.h;; - *) wrn "Something went wrong during alignment determination for" \ - "doubles.\n" \ - "We will assume alignment constraints over doubles.\n" \ - "That's a safe bet: OCaml will work even if\n" \ - "this architecture actually has no alignment constraints." - echo "#define ARCH_ALIGN_DOUBLE" >> m.h;; - esac;; - esac;; -esac - -case "$target" in - # PR#5088: autodetection is unreliable on ARM. PR#5280: also on MIPS. - sparc*-*-*|hppa*-*-*|arm*-*-*|mips*-*-*) - if test $2 = 8; then - inf "64-bit integers can be word-aligned." - echo "#undef ARCH_ALIGN_INT64" >> m.h - else - inf "64-bit integers must be doubleword-aligned." - echo "#define ARCH_ALIGN_INT64" >> m.h - fi;; - *-*-mingw*) true;; # Nothing is in config/m-nt.h so don't add anything. - *) - sh ./runtest int64align.c - case $? in - 0) inf "64-bit integers can be word-aligned." - echo "#undef ARCH_ALIGN_INT64" >> m.h;; - 1) inf "64-bit integers must be doubleword-aligned." - echo "#define ARCH_ALIGN_INT64" >> m.h;; - *) wrn "Something went wrong during alignment determination for\n" \ - "64-bit integers. I'm going to assume this architecture has\n" \ - "alignment constraints. That's a safe bet: OCaml will work\n" \ - "even if this architecture has actually no alignment\n" \ - "constraints." - echo "#define ARCH_ALIGN_INT64" >> m.h;; - esac -esac +as_test_x='test -x' +as_executable_p=as_fn_executable_p -# Shared library support +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" -shared_libraries_supported=false -dl_needs_underscore=false -sharedcccompopts='' -mksharedlib='shared-libs-not-available' -rpath='' -mksharedlibrpath='' -natdynlinkopts="" +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" -if $with_sharedlibs; then - case "$target" in - *-*-cygwin*) - mksharedlib="$flexlink" - mkmaindll="$flexlink -maindll" - shared_libraries_supported=true;; - *-*-mingw*) - mksharedlib="$flexlink" - mkmaindll="$flexlink -maindll" - shared_libraries_supported=true;; - alpha*-*-osf*) - case "$cc" in - *gcc*) - sharedcccompopts="-fPIC" - mksharedlib="$cc -shared" - rpath="-Wl,-rpath," - mksharedlibrpath="-Wl,-rpath," - shared_libraries_supported=true;; - cc*) - sharedcccompopts="" - mksharedlib="ld -shared -expect_unresolved '*'" - rpath="-Wl,-rpath," - mksharedlibrpath="-rpath " - shared_libraries_supported=true;; - esac;; - *-*-solaris2*) - case "$cc" in - *gcc*) - sharedcccompopts="-fPIC" - if sh ./solaris-ld; then - mksharedlib="ld -G" - rpath="-R" - mksharedlibrpath="-R" - else - mksharedlib="$cc -shared" - ldflags="$ldflags -Wl,-E" - natdynlinkopts="-Wl,-E" - rpath="-Wl,-rpath," - mksharedlibrpath="-Wl,-rpath," - fi - shared_libraries_supported=true;; - *) - sharedcccompopts="-KPIC" - rpath="-R" - mksharedlibrpath="-R" - mksharedlib="/usr/ccs/bin/ld -G" - shared_libraries_supported=true;; - esac;; - mips*-*-irix[56]*) - case "$cc" in - cc*) sharedcccompopts="";; - *gcc*) sharedcccompopts="-fPIC";; - esac - mksharedlib="ld -shared -rdata_shared" - rpath="-Wl,-rpath," - mksharedlibrpath="-rpath " - shared_libraries_supported=true;; - i[3456]86-*-darwin[89].*) - mksharedlib="$cc -shared -flat_namespace -undefined suppress \ - -read_only_relocs suppress" - common_cflags="$dl_defs $common_cflags" - dl_needs_underscore=false - shared_libraries_supported=true;; - *-apple-darwin*) - mksharedlib="$cc -shared -flat_namespace -undefined suppress \ - -Wl,-no_compact_unwind" - common_cflags="$dl_defs $common_cflags" - dl_needs_underscore=false - shared_libraries_supported=true;; - *-*-linux*|*-*-freebsd[3-9]*|*-*-freebsd[1-9][0-9]*\ - |*-*-openbsd*|*-*-netbsd*|*-*-dragonfly*|*-*-gnu*|*-*-haiku*) - sharedcccompopts="-fPIC" - mksharedlib="$cc -shared" - ldflags="$ldflags -Wl,-E" - rpath="-Wl,-rpath," - mksharedlibrpath="-Wl,-rpath," - natdynlinkopts="-Wl,-E" - shared_libraries_supported=true;; - powerpc-*-aix*) - case "$ccfamily" in - xlc-*)sharedcccompopts="-qpic" - mksharedlib="$cc -qmkshrobj -G" - mksharedlibrpath="-Wl,-blibpath," - ldflags="$ldflags -brtl -bexpfull" - dl_needs_underscore=false - rpath="-Wl,-blibpath," - shared_libraries_supported=true;; - esac - esac -fi +SHELL=${CONFIG_SHELL-/bin/sh} -if test -z "$mkmaindll"; then - mkmaindll=$mksharedlib -fi -# Configure native dynlink +test -n "$DJDIR" || exec 7<&0 &1 -natdynlink=false +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` -if $with_sharedlibs; then - case "$target" in - *-*-cygwin*) natdynlink=true;; - *-*-mingw*) natdynlink=true;; - i[3456]86-*-linux*) natdynlink=true;; - i[3456]86-*-gnu*) natdynlink=true;; - x86_64-*-linux*) natdynlink=true;; - i[3456]86-*-darwin[89].*) natdynlink=true;; - i[3456]86-*-darwin*) - if test $arch64 == true; then - natdynlink=true - fi;; - x86_64-*-darwin*) natdynlink=true;; - s390x*-*-linux*) natdynlink=true;; - powerpc*-*-linux*) natdynlink=true;; - i686-*-kfreebsd*) natdynlink=true;; - x86_64-*-kfreebsd*) natdynlink=true;; - x86_64-*-dragonfly*) natdynlink=true;; - i[3456]86-*-freebsd*) natdynlink=true;; - x86_64-*-freebsd*) natdynlink=true;; - i[3456]86-*-openbsd*) natdynlink=true;; - x86_64-*-openbsd*) natdynlink=true;; - i[3456]86-*-netbsd*) natdynlink=true;; - x86_64-*-netbsd*) natdynlink=true;; - i386-*-gnu0.3) natdynlink=true;; - i[3456]86-*-haiku*) natdynlink=true;; - arm*-*-linux*) natdynlink=true;; - arm*-*-freebsd*) natdynlink=true;; - earm*-*-netbsd*) natdynlink=true;; - aarch64-*-linux*) natdynlink=true;; - esac -fi +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= -if test $natdynlink = "true"; then - cmxs="cmxs" -else - cmxs="cmxa" -fi +# Identity of this package. +PACKAGE_NAME='OCaml' +PACKAGE_TARNAME='ocaml' +PACKAGE_VERSION='4.08.0' +PACKAGE_STRING='OCaml 4.08.0' +PACKAGE_BUGREPORT='caml-list@inria.fr' +PACKAGE_URL='http://www.ocaml.org' +ac_unique_file="runtime/interp.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" -# Try to work around the Skylake/Kaby Lake processor bug. -case "$cc,$target" in - *gcc*,x86_64-*|*gcc*,i686-*) - if sh ./hasgot -Werror -fno-tree-vrp; then - internal_cflags="$internal_cflags -fno-tree-vrp" - inf "Adding -fno-tree-vrp option to work around PR#7452" - fi;; -esac +ac_subst_vars='LTLIBOBJS +LIBOBJS +XMKMF +PTHREAD_CFLAGS +PTHREAD_LIBS +PTHREAD_CC +ax_pthread_config +DIRECT_LD +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +CPP +LT_SYS_LIBRARY_PATH +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +AWK +STRIP +ac_ct_AR +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +FGREP +EGREP +GREP +SED +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +LIBTOOL +ac_ct_LD +LD +DEFAULT_STRING +WINDOWS_UNICODE_MODE +LIBUNWIND_LIB_DIR +LIBUNWIND_INCLUDE_DIR +DLLIBS +PARTIALLD +target_os +target_vendor +target_cpu +target +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +PACKLD +flexlink_flags +flexdll_chain +default_safe_string +force_safe_string +afl +flat_float_array +windows_unicode +max_testsuite_dir_retries +flambda_invariants +flambda +libunwind_link_flags +libunwind_include_flags +libunwind_available +call_counts +spacetime +frame_pointers +cc_profile +profinfo_width +profinfo +profiling +install_source_artifacts +install_bytecode_programs +mksharedlibrpath +mkmaindll +mksharedlib +rpath +sharedlib_cflags +asm_cfi_supported +AS +ASPP +asppprofflags +libbfd_link +libbfd_include +x_libraries +x_includes +pthread_link +ocamldoc +with_camltex +with_debugger +as_has_debug_prefix_map +cc_has_debug_prefix_map +otherlibraries +instrumented_runtime +debug_runtime +cmxs +natdynlinkopts +natdynlink +supports_shared_libraries +mklib +RANLIBCMD +RANLIB +AR +hashbangscripts +iflexdir +ocamlopt_cppflags +ocamlopt_cflags +ocamlc_cppflags +ocamlc_cflags +nativecclibs +bytecclibs +oc_ldflags +oc_cppflags +oc_cflags +toolchain +ccomptype +mkexedebugflag +mkexe +fpic +libraries_man_section +programs_man_section +extralibs +syslib +outputobj +outputexe +graphlib +unixlib +unix_or_win32 +systhread_support +system +model +arch64 +arch +SO +S +libext +OBJEXT +exeext +ac_tool_prefix +DIRECT_CPP +CC +VERSION +CONFIGURE_ARGS +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_debug_runtime +enable_debugger +enable_instrumented_runtime +enable_vmthreads +enable_systhreads +with_libunwind +enable_graph_lib +enable_str_lib +enable_unix_lib +enable_bigarray_lib +enable_ocamldoc +enable_frame_pointers +enable_naked_pointers +enable_spacetime +enable_call_counts +enable_cfi +enable_installing_source_artifacts +enable_installing_bytecode_programs +enable_native_compiler +enable_flambda +enable_flambda_invariants +with_target_bindir +enable_reserved_header_bits +enable_force_safe_string +enable_flat_float_array +with_afl +enable_shared +enable_static +with_pic +enable_fast_install +with_aix_soname +with_gnu_ld +with_sysroot +enable_libtool_lock +with_x +' + ac_precious_vars='build_alias +host_alias +target_alias +AS +ASPP +PARTIALLD +DLLIBS +LIBUNWIND_INCLUDE_DIR +LIBUNWIND_LIB_DIR +WINDOWS_UNICODE_MODE +DEFAULT_STRING +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +LT_SYS_LIBRARY_PATH +CPP +XMKMF' -# Configure the native-code compiler +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE -arch=none -model=default -system=unknown +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' -case "$target" in - i[3456]86-*-linux*) arch=i386; system=linux_`sh ./runtest elf.c`;; - i[3456]86-*-*bsd*) arch=i386; system=bsd_`sh ./runtest elf.c`;; - i[3456]86-*-solaris*) if $arch64; then - arch=amd64; system=solaris - else - arch=i386; system=solaris - fi;; - i[3456]86-*-haiku*) arch=i386; system=beos;; - i[3456]86-*-beos*) arch=i386; system=beos;; - i[3456]86-*-cygwin*) arch=i386; system=cygwin;; - i[3456]86-*-darwin*) if $arch64; then - arch=amd64; system=macosx - else - arch=i386; system=macosx - fi;; - i[3456]86-*-gnu*) arch=i386; system=gnu;; - i[3456]86-*-mingw*) arch=i386; system=mingw;; - powerpc64le*-*-linux*) arch=power; model=ppc64le; system=elf;; - powerpc*-*-linux*) arch=power; - if $arch64; then model=ppc64; else model=ppc; fi - system=elf;; - powerpc-*-netbsd*) arch=power; model=ppc; system=netbsd;; - powerpc-*-openbsd*) arch=power; model=ppc; system=bsd_elf;; - s390x*-*-linux*) arch=s390x; model=z10; system=elf;; - armv6*-*-linux-gnueabihf) arch=arm; model=armv6; system=linux_eabihf;; - armv7*-*-linux-gnueabihf) arch=arm; model=armv7; system=linux_eabihf;; - armv8*-*-linux-gnueabihf) arch=arm; model=armv8; system=linux_eabihf;; - armv8*-*-linux-gnueabi) arch=arm; model=armv8; system=linux_eabi;; - armv7*-*-linux-gnueabi) arch=arm; model=armv7; system=linux_eabi;; - armv6t2*-*-linux-gnueabi) arch=arm; model=armv6t2; system=linux_eabi;; - armv6*-*-linux-gnueabi) arch=arm; model=armv6; system=linux_eabi;; - armv6*-*-freebsd*) arch=arm; model=armv6; system=freebsd;; - earmv6*-*-netbsd*) arch=arm; model=armv6; system=netbsd;; - earmv7*-*-netbsd*) arch=arm; model=armv7; system=netbsd;; - armv5te*-*-linux-gnueabi) arch=arm; model=armv5te; system=linux_eabi;; - armv5*-*-linux-gnueabi) arch=arm; model=armv5; system=linux_eabi;; - arm*-*-linux-gnueabi) arch=arm; system=linux_eabi;; - arm*-*-openbsd*) arch=arm; system=bsd;; - zaurus*-*-openbsd*) arch=arm; system=bsd;; - x86_64-*-linux*) arch=amd64; system=linux;; - x86_64-*-gnu*) arch=amd64; system=gnu;; - x86_64-*-dragonfly*) arch=amd64; system=dragonfly;; - x86_64-*-freebsd*) arch=amd64; system=freebsd;; - x86_64-*-netbsd*) arch=amd64; system=netbsd;; - x86_64-*-openbsd*) arch=amd64; system=openbsd;; - x86_64-*-darwin*) arch=amd64; system=macosx;; - x86_64-*-mingw*) arch=amd64; system=mingw;; - aarch64-*-linux*) arch=arm64; system=linux;; - x86_64-*-cygwin*) arch=amd64; system=cygwin;; -esac - -# Some platforms exist both in 32-bit and 64-bit variants, not distinguished -# by $target. Turn off native code compilation on platforms where 64-bit mode -# is not supported (PR#4441). -# Sometimes, it's 32-bit mode that is not supported (PR#6722). - -case "$arch64,$arch,$model" in - true,power,ppc|false,amd64,*) - arch=none; model=default; system=unknown;; -esac - -case "$native_compiler" in - true) ;; - false) - arch=none; model=default; system=unknown; natdynlink=false;; -esac - -nativeccprofopts='' - -case "$arch,$cc,$system,$model" in - *,*,rhapsody,*) if $arch64; then partialld="ld -r -arch ppc64"; fi;; - amd64,gcc*,macosx,*) partialld="ld -r -arch x86_64";; - amd64,gcc*,solaris,*) partialld="ld -r -m elf_x86_64";; - power,gcc*,elf,ppc) partialld="ld -r -m elf32ppclinux";; - power,gcc*,elf,ppc64) partialld="ld -r -m elf64ppc";; - power,gcc*,elf,ppc64le) partialld="ld -r -m elf64lppc";; -esac - -asppprofflags='-DPROFILING' - -case "$arch,$system" in - amd64,macosx) if sh ./searchpath clang; then - as='clang -arch x86_64 -Wno-trigraphs -c' - aspp='clang -arch x86_64 -Wno-trigraphs -c' - else - as="${TOOLPREF}as -arch x86_64" - aspp="${TOOLPREF}gcc -arch x86_64 -c" - fi;; - amd64,solaris) as="${TOOLPREF}as --64" - aspp="${TOOLPREF}gcc -m64 -c";; - i386,solaris) as="${TOOLPREF}as" - aspp="${TOOLPREF}gcc -c";; - power,elf) if $arch64; then - as="${TOOLPREF}as -a64 -mppc64" - aspp="${TOOLPREF}gcc -m64 -c" - else - as="${TOOLPREF}as -mppc" - aspp="${TOOLPREF}gcc -m32 -c" - fi;; - s390x,elf) as="${TOOLPREF}as -m 64 -march=$model" - aspp="${TOOLPREF}gcc -c -Wa,-march=$model";; - arm,freebsd) as="${TOOLPREF}cc -c" - aspp="${TOOLPREF}cc -c";; - *,dragonfly) as="${TOOLPREF}as" - aspp="${TOOLPREF}cc -c";; - *,freebsd) as="${TOOLPREF}as" - aspp="${TOOLPREF}cc -c";; - amd64,*|arm,*|arm64,*|i386,*|power,bsd*|power,netbsd) - as="${TOOLPREF}as" - case "$ccfamily" in - clang-*) - aspp="${TOOLPREF}clang -c -Wno-trigraphs" - ;; - *) - aspp="${TOOLPREF}gcc -c" - ;; - esac;; -esac - -if test -n "$asoption"; then as="$asoption"; fi -if test -n "$asppoption"; then aspp="$asppoption"; fi - -cc_profile='-pg' -case "$arch,$system" in - i386,linux_elf) profiling='true';; - i386,gnu) profiling='true';; - i386,bsd_elf) profiling='true';; - amd64,macosx) profiling='true';; - i386,macosx) profiling='true';; - amd64,linux) profiling='true';; - amd64,openbsd) profiling='true';; - amd64,freebsd) profiling='true';; - amd64,netbsd) profiling='true';; - arm,netbsd) profiling='true';; - amd64,gnu) profiling='true';; - arm,linux*) profiling='true';; - power,elf) profiling='true';; - power,bsd*) profiling='true';; - power,netbsd) profiling='true';; - *) profiling='false';; -esac - -# Where is ranlib? - -if sh ./searchpath ${TOOLPREF}ranlib; then - inf "ranlib found" - config RANLIB "${TOOLPREF}ranlib" - config RANLIBCMD "${TOOLPREF}ranlib" -else - inf "ranlib not used" - config RANLIB "${TOOLPREF}ar rs" - config RANLIBCMD "" -fi - -config ARCMD "${TOOLPREF}ar" - - -# Write the OS type (Unix or Cygwin) - -echo "#define OCAML_OS_TYPE \"$ostype\"" >> s.h -echo "#define OCAML_STDLIB_DIR \"$libdir\"" >> s.h - -# Do #! scripts work? - -printf "#!%s\nexit 1\n" `command -v cat` > hashbang4 -chmod +x hashbang4 - -if ( (./hashbang || ./hashbang2 || ./hashbang3 || ./hashbang4) >/dev/null); then - inf "#! appears to work in shell scripts." - case "$target" in - *-*-sunos*|*-*-unicos*) - wrn "We won't use it, though, because under SunOS and Unicos it breaks " \ - "on pathnames longer than 30 characters" - config HASHBANGSCRIPTS "false";; - *-*-cygwin*) - wrn "We won't use it, though, because of conflicts with .exe extension " \ - "under Cygwin" - config HASHBANGSCRIPTS "false";; - *-*-mingw*) - inf "We won't use it, though, because it's on the target platform " \ - "it would be used and windows doesn't support it." - config HASHBANGSCRIPTS "false";; - *) - config HASHBANGSCRIPTS "true";; - esac -else - inf "No support for #! in shell scripts" - config HASHBANGSCRIPTS "false" -fi +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi -# Use 64-bit file offset if possible + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac -common_cppflags="$common_cppflags -D_FILE_OFFSET_BITS=64" + # Accept the important Cygnus configure options, so we can diagnose typos. -# Check the semantics of signal handlers + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; -if sh ./hasgot sigaction sigprocmask; then - inf "POSIX signal handling found." - echo "#define POSIX_SIGNALS" >> s.h -else - if sh ./runtest signals.c; then - inf "Signals have the BSD semantics." - echo "#define BSD_SIGNALS" >> s.h - else - inf "Signals have the System V semantics." - fi - if sh ./hasgot sigsetmask; then - inf "sigsetmask() found" - echo "#define HAS_SIGSETMASK" >> s.h - fi -fi + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; -# For the Pervasives module + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; -if sh ./hasgot2 -i math.h $mathlib expm1 log1p hypot copysign; then - inf "expm1(), log1p(), hypot(), copysign() found." - echo "#define HAS_C99_FLOAT_OPS" >> s.h -fi + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; -# For the Sys module + --config-cache | -C) + cache_file=config.cache ;; -if sh ./hasgot getrusage; then - inf "getrusage() found." - echo "#define HAS_GETRUSAGE" >> s.h -fi + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; -if sh ./hasgot times; then - inf "times() found." - echo "#define HAS_TIMES" >> s.h -fi + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; -if sh ./hasgot2 -D_GNU_SOURCE -i stdlib.h secure_getenv; then - inf "secure_getenv() found." - echo "#define HAS_SECURE_GETENV" >> s.h -elif sh ./hasgot2 -D_GNU_SOURCE -i stdlib.h __secure_getenv; then - inf "__secure_getenv() found." - echo "#define HAS___SECURE_GETENV" >> s.h -fi + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; -if sh ./hasgot -i unistd.h issetugid; then - inf "issetugid() found." - echo "#define HAS_ISSETUGID" >> s.h -fi + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; -# For instrumented runtime -# (clock_gettime needs -lrt for glibc before 2.17) -if test "$with_instrumented_runtime" != "false"; then - instrumented_runtime_support="nonsupported" - for libs in "" "-lrt"; do - if sh ./hasgot $libs clock_gettime; then - inf "clock_gettime functions found (with libraries '$libs')" - instrumented_runtime_libs="${libs}" - instrumented_runtime_support="supported"; - break - fi - done - case "$with_instrumented_runtime,$instrumented_runtime_support" in - *,supported) - with_instrumented_runtime=true;; - true,nonsupported) - with_instrumented_runtime=false; - err "clock_gettime functions not found. " \ - "Instrumented runtime can't be built.";; - ,nonsupported) - with_instrumented_runtime=false; - inf "clock_gettime functions not found. " \ - "Instrumented runtime can't be built.";; - esac -fi + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; -# Configuration for the libraries + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; -case "$system" in - mingw) unix_or_win32="win32"; unixlib="win32unix"; graphlib="win32graph";; - *) unix_or_win32="unix"; unixlib="unix"; graphlib="graph";; -esac + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; -config UNIX_OR_WIN32 "$unix_or_win32" -config UNIXLIB "$unixlib" -config GRAPHLIB "$graphlib" + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; -otherlibraries="$unixlib str dynlink bigarray" + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; -# Spacetime profiling is only available for native code on 64-bit targets. + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; -case "$arch" in - none) ;; - *) - if $arch64; then - otherlibraries="$otherlibraries raw_spacetime_lib" - fi - ;; -esac + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; -# For the Unix library - -has_sockets=no -if sh ./hasgot socket socketpair bind listen accept connect; then - inf "You have BSD sockets." - echo "#define HAS_SOCKETS" >> s.h - has_sockets=yes -elif sh ./hasgot -lnsl -lsocket socket socketpair bind listen accept connect -then - inf "You have BSD sockets (with libraries '-lnsl -lsocket')" - cclibs="$cclibs -lnsl -lsocket" - echo "#define HAS_SOCKETS" >> s.h - has_sockets=yes -elif sh ./hasgot -lnetwork socket socketpair bind listen accept connect; then - echo "You have BSD sockets (with library '-lnetwork')" - cclibs="$cclibs -lnetwork" - echo "#define HAS_SOCKETS" >> s.h - has_sockets=yes -else - case "$target" in - *-*-mingw*) - inf "You have BSD sockets (with libraries '-lws2_32')" - cclibs="$cclibs -lws2_32" - echo "#define HAS_SOCKETS" >> s.h - has_sockets=yes ;; - *) ;; - esac -fi + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; -if sh ./hasgot -i sys/socket.h -t socklen_t; then - inf "socklen_t is defined in " - echo "#define HAS_SOCKLEN_T" >> s.h -fi + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; -if sh ./hasgot inet_aton; then - inf "inet_aton() found." - echo "#define HAS_INET_ATON" >> s.h -fi + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; -if sh ./hasgot -i sys/types.h -i sys/socket.h -i netinet/in.h \ - -t 'struct sockaddr_in6' \ -&& sh ./hasgot getaddrinfo getnameinfo inet_pton inet_ntop; then - inf "IPv6 is supported." - echo "#define HAS_IPV6" >> s.h -fi + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; -if sh ./hasgot -i stdint.h; then - inf "stdint.h found." - echo "#define HAS_STDINT_H" >> s.h -fi + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; -if sh ./hasgot -i unistd.h; then - inf "unistd.h found." - echo "#define HAS_UNISTD" >> s.h -fi + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; -if sh ./hasgot -i sys/types.h -t off_t; then - inf "off_t is defined in " - echo "#define HAS_OFF_T" >> s.h -fi + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; -if sh ./hasgot -i sys/types.h -i dirent.h; then - inf "dirent.h found." - echo "#define HAS_DIRENT" >> s.h -fi + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; -if sh ./hasgot rewinddir; then - inf "rewinddir() found." - echo "#define HAS_REWINDDIR" >> s.h -fi + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; -if sh ./hasgot lockf; then - inf "lockf() found." - echo "#define HAS_LOCKF" >> s.h -fi + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; -if sh ./hasgot mkfifo; then - inf "mkfifo() found." - echo "#define HAS_MKFIFO" >> s.h -fi + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; -if sh ./hasgot getcwd; then - inf "getcwd() found." - echo "#define HAS_GETCWD" >> s.h -fi + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; -if sh ./hasgot getpriority setpriority; then - inf "getpriority() found." - echo "#define HAS_GETPRIORITY" >> s.h -fi + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; -if sh ./hasgot -i sys/types.h -i utime.h && sh ./hasgot utime; then - inf "utime() found." - echo "#define HAS_UTIME" >> s.h -fi + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; -if sh ./hasgot utimes; then - inf "utimes() found." - echo "#define HAS_UTIMES" >> s.h -fi + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; -if sh ./hasgot dup2; then - inf "dup2() found." - echo "#define HAS_DUP2" >> s.h -fi + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; -if sh ./hasgot fchmod fchown; then - inf "fchmod() found." - echo "#define HAS_FCHMOD" >> s.h -fi + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; -if sh ./hasgot truncate ftruncate; then - inf "truncate() found." - echo "#define HAS_TRUNCATE" >> s.h -fi + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; -select_include='' -if sh ./hasgot -i sys/types.h -i sys/select.h; then - inf "sys/select.h found." - echo "#define HAS_SYS_SELECT_H" >> s.h - select_include='-i sys/select.h' -fi + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; -has_select=no -if sh ./hasgot select && \ - sh ./hasgot -i sys/types.h $select_include -t fd_set ; then - inf "select() found." - echo "#define HAS_SELECT" >> s.h - has_select=yes -fi + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; -if sh ./hasgot nanosleep ; then - inf "nanosleep() found." - echo "#define HAS_NANOSLEEP" >> s.h -fi + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; -if sh ./hasgot symlink readlink lstat; then - inf "symlink() found." - echo "#define HAS_SYMLINK" >> s.h -fi + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; -has_wait=no -if sh ./hasgot waitpid; then - inf "waitpid() found." - echo "#define HAS_WAITPID" >> s.h - has_wait=yes -fi + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; -if sh ./hasgot wait4; then - inf "wait4() found." - echo "#define HAS_WAIT4" >> s.h - has_wait=yes -fi + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; -if sh ./hasgot -i limits.h && sh ./runtest getgroups.c; then - inf "getgroups() found." - echo "#define HAS_GETGROUPS" >> s.h -fi + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; -if sh ./hasgot -i limits.h -i grp.h && sh ./runtest setgroups.c; then - inf "setgroups() found." - echo "#define HAS_SETGROUPS" >> s.h -fi + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; -if sh ./hasgot -i limits.h -i grp.h && sh ./runtest initgroups.c; then - inf "initgroups() found." - echo "#define HAS_INITGROUPS" >> s.h -fi + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; -if sh ./hasgot -i termios.h && - sh ./hasgot tcgetattr tcsetattr tcsendbreak tcflush tcflow; then - inf "POSIX termios found." - echo "#define HAS_TERMIOS" >> s.h -fi + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; -if sh ./runtest async_io.c; then - inf "Asynchronous I/O are supported." - echo "#define HAS_ASYNC_IO" >> s.h -fi + --x) + # Obsolete; use --with-x. + with_x=yes ;; -has_setitimer=no -if sh ./hasgot setitimer; then - inf "setitimer() found." - echo "#define HAS_SETITIMER" >> s.h - has_setitimer="yes" -fi + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; -if sh ./hasgot gethostname; then - inf "gethostname() found." - echo "#define HAS_GETHOSTNAME" >> s.h -fi + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; -if sh ./hasgot -i sys/utsname.h && sh ./hasgot uname; then - inf "uname() found." - echo "#define HAS_UNAME" >> s.h -fi + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; -has_gettimeofday=no -if sh ./hasgot gettimeofday; then - inf "gettimeofday() found." - echo "#define HAS_GETTIMEOFDAY" >> s.h - has_gettimeofday="yes" -fi + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; -if sh ./hasgot mktime; then - inf "mktime() found." - echo "#define HAS_MKTIME" >> s.h -fi + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; -case "$target" in - *-*-cygwin*) ;; # setsid emulation under Cygwin breaks the debugger - *) if sh ./hasgot setsid; then - inf "setsid() found." - echo "#define HAS_SETSID" >> s.h - fi;; -esac + esac +done -if sh ./hasgot putenv; then - inf "putenv() found." - echo "#define HAS_PUTENV" >> s.h +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" fi -if sh ./hasgot -i locale.h && sh ./hasgot setlocale; then - inf "setlocale() and found." - echo "#define HAS_LOCALE" >> s.h +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac fi - -if sh ./hasgot $dllib dlopen; then - inf "dlopen() found." -elif sh ./hasgot $dllib -ldl dlopen; then - inf "dlopen() found in -ldl." - dllib="$dllib -ldl" -else - case "$target" in - *-*-mingw*) ;; - *) shared_libraries_supported=false +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; esac -fi + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias -if $shared_libraries_supported; then - inf "Dynamic loading of shared libraries is supported." - echo "#define SUPPORT_DYNAMIC_LINKING" >> s.h - if $dl_needs_underscore; then - echo '#define DL_NEEDS_UNDERSCORE' >>s.h +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes fi fi -if sh ./hasgot -i sys/types.h -i sys/mman.h && sh ./hasgot mmap munmap; then - inf "mmap() found." - echo "#define HAS_MMAP" >> s.h -fi +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- -if sh ./hasgot pwrite; then - inf "pwrite() found" - echo "#define HAS_PWRITE" >> s.h -fi +test "$silent" = yes && exec 6>/dev/null -nanosecond_stat=none -for i in 1 2 3; do - if sh ./trycompile -DHAS_NANOSECOND_STAT=$i nanosecond_stat.c; then - nanosecond_stat=$i; break - fi -done -if test $nanosecond_stat != "none"; then - inf "stat() supports nanosecond precision." - echo "#define HAS_NANOSECOND_STAT $nanosecond_stat" >> s.h -fi -nargs=none -for i in 5 6; do - if sh ./trycompile -DSYS_${system} -DNUM_ARGS=${i} gethostbyname.c; then - nargs=$i; - break; - fi -done -if test $nargs != "none"; then - inf "gethostbyname_r() found (with ${nargs} arguments)." - echo "#define HAS_GETHOSTBYNAME_R $nargs" >> s.h -fi +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" -nargs=none -for i in 7 8; do - if sh ./trycompile -DSYS_${system} -DNUM_ARGS=${i} gethostbyaddr.c; then - nargs=$i; - break; + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. fi -done -if test $nargs != "none"; then - inf "gethostbyaddr_r() found (with ${nargs} arguments)." - echo "#define HAS_GETHOSTBYADDR_R $nargs" >> s.h +else + ac_srcdir_defaulted=no fi - -if sh ./hasgot mkstemp; then - inf "mkstemp() found" - echo "#define HAS_MKSTEMP" >> s.h +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi - -if sh ./hasgot nice; then - inf "nice() found" - echo "#define HAS_NICE" >> s.h +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done -if sh ./hasgot dup3; then - inf "dup3() found" - echo "#define HAS_DUP3" >> s.h -fi +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures OCaml 4.08.0 to adapt to many kinds of systems. -if sh ./hasgot pipe2; then - inf "pipe2() found" - echo "#define HAS_PIPE2" >> s.h -fi +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/ocaml] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF -if sh ./hasgot accept4; then - inf "accept4() found" - echo "#define HAS_ACCEPT4" >> s.h + cat <<\_ACEOF + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF fi -if sh ./hasgot getauxval; then - inf "getauxval() found." - echo "#define HAS_GETAUXVAL" >> s.h +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of OCaml 4.08.0:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-debug-runtime do not build runtime with debugging support + --enable-debugger build the debugger [default=auto] + --enable-instrumented-runtime + build the instrumented runtime [default=auto] + --disable-vmthreads disable the bytecode threads library + --disable-systhreads disable the Win32/POSIX threads library + --disable-graph-lib do not build the graphics library + --disable-str-lib do not build the str library + --disable-unix-lib do not build the unix library + --disable-bigarray-lib do not build the legacy separate bigarray library + --disable-ocamldoc do not build the ocamldoc documentation system + --enable-frame-pointers use frame pointers in runtime and generated code + --disable-naked-pointers + do not allow naked pointers + --enable-spacetime build the spacetime profiler + --disable-call-counts disable the call counts in spacetime + --disable-cfi disable the CFI directives in assembly files + --enable-installing-source-artifacts + install *.cmt* and *.mli files + --enable-installing-bytecode-programs + also install the bytecode versions of programs + --disable-native-compiler + do not build the native compiler + --enable-flambda enable flambda optimizations + --enable-flambda-invariants + enable invariants checks in flambda + --enable-reserved-header-bits=BITS + reserve BITS (between 0 and 31) bits in block + headers for profiling info + --enable-force-safe-string + force strings to be safe + --disable-flat-float-array + do not use flat float arrays + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --without-libunwind disable libunwind support for Spacetime profiling + --with-target-bindir location of binary programs on target system + --with-afl use the AFL fuzzer + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). + --with-x use the X Window System + +Some influential environment variables: + AS which assembler to use + ASPP which assembler (with preprocessor) to use + PARTIALLD how to build partial (relocatable) object files + DLLIBS which libraries to use (in addition to -ldl) to load dynamic + libs + LIBUNWIND_INCLUDE_DIR + location of header files for libunwind + LIBUNWIND_LIB_DIR + location of library files for libunwind + WINDOWS_UNICODE_MODE + how to handle Unicode under Windows: ansi, compatible + DEFAULT_STRING + whether strings should be safe (default) or unsafe + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. + CPP C preprocessor + XMKMF Path to xmkmf, Makefile generator for X Window System + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +OCaml home page: . +_ACEOF +ac_status=$? fi -if sh ./hasgot -i sys/shm.h; then - inf "sys/shm.h found." - echo "#define HAS_SYS_SHM_H" >> s.h +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done fi -if sh ./hasgot execvpe; then - inf "execvpe() found." - echo "#define HAS_EXECVPE" >> s.h +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +OCaml configure 4.08.0 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit fi -# Determine if the debugger is supported +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## -if test -n "$with_debugger"; then - if test "$has_sockets" = "yes"; then - inf "Replay debugger supported." - with_debugger="ocamldebugger" - else - inf "No replay debugger (missing system calls)" - with_debugger="" +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval -# Determine if system stack overflows can be detected +} # ac_fn_c_try_compile -case "$arch,$system" in - i386,linux_elf|amd64,linux|power,rhapsody|amd64,macosx|i386,macosx \ - |amd64,openbsd|i386,bsd_elf) - inf "System stack overflow can be detected." - echo "#define HAS_STACK_OVERFLOW_DETECTION" >> s.h;; - *) - inf "Cannot detect system stack overflow.";; -esac - -# Determine if the POSIX threads library is supported - -systhread_support=false - -if test "$pthread_wanted" = "yes"; then - case "$target" in - *-*-solaris*) pthread_link="-lpthread -lposix4" - pthread_caml_link="-cclib -lpthread -cclib -lposix4";; - *-*-dragon*) pthread_link="-pthread" - pthread_caml_link="-cclib -pthread";; - *-*-freebsd*) pthread_link="-pthread" - pthread_caml_link="-cclib -pthread";; - *-*-openbsd*) pthread_link="-pthread" - pthread_caml_link="-cclib -pthread";; - *-*-haiku*) pthread_link="" - pthread_caml_link="";; - *) pthread_link="-lpthread" - pthread_caml_link="-cclib -lpthread";; - esac - if sh ./hasgot -i pthread.h $pthread_link pthread_self; then - inf "POSIX threads library supported." - systhread_support=true - otherlibraries="$otherlibraries systhreads" - common_cppflags="$common_cppflags -D_REENTRANT" - case "$target" in - *-*-freebsd*|*-*-dragonfly*) - common_cppflags="$common_cppflags -D_THREAD_SAFE";; - *-*-openbsd*) - common_cflags="$common_cflags -pthread"; - asppflags="$asppflags -pthread";; - esac - inf "Options for linking with POSIX threads: $pthread_link" - if sh ./hasgot $pthread_link sigwait; then - inf "sigwait() found" - echo "#define HAS_SIGWAIT" >> s.h - fi - else - inf "POSIX threads not found." - pthread_link="" +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 else - pthread_link="" + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 fi -config PTHREAD_LINK "$pthread_link" -config PTHREAD_CAML_LINK "$pthread_caml_link" + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval -# Determine if the bytecode thread library is supported +} # ac_fn_c_try_link -if test "$has_select" = "yes" \ -&& test "$has_setitimer" = "yes" \ -&& test "$has_gettimeofday" = "yes" \ -&& test "$has_wait" = "yes"; then - inf "Bytecode threads library supported." - otherlibraries="$otherlibraries threads" +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 else - inf "Bytecode threads library not supported (missing system calls)" -fi - -# Determine the location of X include files and libraries - -# If the user specified -x11include and/or -x11lib, these settings -# are used. Otherwise, we check whether there is pkg-config, and take -# the flags from there. Otherwise, we search the location. - -x11_include="not found" -x11_link="not found" - -if test -z "$x11_include_dir" -a -z "$x11_lib_dir"; then - if pkg-config --exists x11 2>/dev/null; then - x11_include=`pkg-config --cflags x11` - x11_link=`pkg-config --libs x11` - fi -fi - -if test "$x11_include" = "not found"; then - for dir in \ - $x11_include_dir \ - \ - /usr/X11R7/include \ - /usr/include/X11R7 \ - /usr/local/X11R7/include \ - /usr/local/include/X11R7 \ - /opt/X11R7/include \ - \ - /usr/X11R6/include \ - /usr/include/X11R6 \ - /usr/local/X11R6/include \ - /usr/local/include/X11R6 \ - /opt/X11R6/include \ - \ - /usr/X11/include \ - /usr/include/X11 \ - /usr/local/X11/include \ - /usr/local/include/X11 \ - /opt/X11/include \ - \ - /usr/X11R5/include \ - /usr/include/X11R5 \ - /usr/local/X11R5/include \ - /usr/local/include/X11R5 \ - /usr/local/x11r5/include \ - /opt/X11R5/include \ - \ - /usr/X11R4/include \ - /usr/include/X11R4 \ - /usr/local/X11R4/include \ - /usr/local/include/X11R4 \ - \ - /usr/X386/include \ - /usr/x386/include \ - /usr/XFree86/include/X11 \ - \ - /usr/include \ - /usr/local/include \ - /usr/unsupported/include \ - /usr/athena/include \ - /usr/lpp/Xamples/include \ - \ - /usr/openwin/include \ - /usr/openwin/share/include \ - ; \ - do - if test -f $dir/X11/X.h; then - x11_include_dir=$dir - x11_include="-I$dir" - break - fi - done - - if test "$x11_include" = "not found"; then - x11_try_lib_dir='' - else - x11_try_lib_dir=`echo $x11_include_dir | sed -e 's|include|lib|'` - fi - - for dir in \ - $x11_lib_dir \ - $x11_try_lib_dir \ - \ - /usr/X11R6/lib64 \ - /usr/X11R6/lib \ - /usr/lib/X11R6 \ - /usr/local/X11R6/lib \ - /usr/local/lib/X11R6 \ - /opt/X11R6/lib \ - \ - /usr/X11/lib \ - /usr/lib/X11 \ - /usr/local/X11/lib \ - /usr/local/lib/X11 \ - /opt/X11/lib \ - \ - /usr/X11R5/lib \ - /usr/lib/X11R5 \ - /usr/local/X11R5/lib \ - /usr/local/lib/X11R5 \ - /usr/local/x11r5/lib \ - /opt/X11R5/lib \ - \ - /usr/X11R4/lib \ - /usr/lib/X11R4 \ - /usr/local/X11R4/lib \ - /usr/local/lib/X11R4 \ - \ - /usr/X386/lib \ - /usr/x386/lib \ - /usr/XFree86/lib/X11 \ - \ - /usr/lib64 \ - /usr/lib \ - /usr/local/lib \ - /usr/unsupported/lib \ - /usr/athena/lib \ - /usr/lpp/Xamples/lib \ - /lib/usr/lib/X11 \ - \ - /usr/openwin/lib \ - /usr/openwin/share/lib \ - \ - /usr/lib/i386-linux-gnu \ - /usr/lib/x86_64-linux-gnu \ - \ - /usr/lib/`echo $target | sed -e "s/-[^-]*//"` \ - ; \ - do - if test -f $dir/libX11.a || \ - test -f $dir/libX11.so || \ - test -f $dir/libX11.dll.a || \ - test -f $dir/libX11.dylib || \ - test -f $dir/libX11.sa; then - if test $dir = /usr/lib; then - x11_link="-lX11" - else - case "$target" in - *-*-freebsd*|*-*-dragonfly*) x11_link="-L$dir -lX11";; - *-kfreebsd*-gnu) x11_link="-L$dir -lX11";; - *-*-*bsd*) x11_link="-R$dir -L$dir -lX11";; - *) x11_link="-L$dir -lX11";; - esac - fi - break - fi - done + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno -if test "$x11_include" != "not found"; then - if test "$x11_include" = "-I/usr/include"; then - x11_include="" - fi - if sh ./hasgot $x11_include $x11_link -i X11/Xlib.h XrmInitialize; then - inf "X11 works" - else - wrn "Cannot compile X11 program." - x11_include="not found" - fi -fi - -has_graph=false -if test "$x11_include" = "not found" || test "$x11_link" = "not found" -then - wrn 'X11 not found, the "graph" library will not be supported.' - x11_include="not found" - x11_link="not found" -else - inf "Options for compiling for X11: $x11_include" - inf "Options for linking with X11: $x11_link" - if test "$graph_wanted" = yes - then - has_graph=true - otherlibraries="$otherlibraries graph" - fi -fi -echo "X11_INCLUDES=$x11_include" >> Makefile -echo "X11_LINK=$x11_link" >> Makefile - -# Look for BFD library - -if $shared_libraries_supported && ./hasgot -DPACKAGE=ocaml -i bfd.h ; then - inf "BFD library found." - if sh ./hasgot -DPACKAGE=ocaml -lbfd bfd_openr; then - LIBBFD_LINK="-lbfd" - inf "BFD links with $LIBBFD_LINK" - echo "#define HAS_LIBBFD" >> s.h - elif sh ./hasgot -DPACKAGE=ocaml -lbfd -ldl bfd_openr; then - LIBBFD_LINK="-lbfd -ldl" - inf "BFD links with $LIBBFD_LINK" - echo "#define HAS_LIBBFD" >> s.h - elif sh ./hasgot -DPACKAGE=ocaml -lbfd -ldl -liberty bfd_openr; then - LIBBFD_LINK="-lbfd -ldl -liberty" - inf "BFD links with $LIBBFD_LINK" - echo "#define HAS_LIBBFD" >> s.h - elif sh ./hasgot -DPACKAGE=ocaml -lbfd -ldl -liberty -lz bfd_openr; then - LIBBFD_LINK="-lbfd -ldl -liberty -lz" - inf "BFD links with $LIBBFD_LINK" - echo "#define HAS_LIBBFD" >> s.h - else - wrn "Could not determine link options for the BFD library" - LIBBFD_LINK= +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err fi - echo "LIBBFD_LINK=$LIBBFD_LINK" >> Makefile - echo LIBBFD_INCLUDE= >>Makefile -elif sh ./hasgot -DPACKAGE=ocaml -I/opt/local/include -i bfd.h && \ - sh ./hasgot -DPACKAGE=ocaml -L/opt/local/lib -lbfd -ldl \ - -liberty -lz -lintl bfd_openr -then - # MacOSX with binutils from MacPorts - inf "BFD library found." - echo "#define HAS_LIBBFD" >> s.h - echo "LIBBFD_LINK=-L/opt/local/lib -lbfd -ldl -liberty -lz -lintl" >> Makefile - echo LIBBFD_INCLUDE=-I/opt/local/include >>Makefile + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 else - wrn "BFD library not found, 'objinfo' will be unable to display info" \ - " on .cmxs files." - echo "LIBBFD_LINK=" >> Makefile - echo "LIBBFD_INCLUDE=" >> Makefile + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval -# Check whether assembler supports CFI directives +} # ac_fn_c_try_cpp -asm_cfi_supported=false +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 -export as aspp + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval -if ! $with_cfi; then - echo "CFI support: disabled by command-line option -no-cfi" -elif sh ./tryassemble cfi.S; then - echo "#define ASM_CFI_SUPPORTED" >> m.h - asm_cfi_supported=true - inf "Assembler supports CFI" +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" else - inf "Assembler does not support CFI" + eval "$3=no" fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno -if test "$with_frame_pointers" = "true"; then - case "$target,$cc" in - x86_64-*-linux*,gcc*|x86_64-*-linux*,clang*) - common_cflags="$common_cflags -g -fno-omit-frame-pointer" - echo "#define WITH_FRAME_POINTERS" >> m.h - ;; - *) err "Unsupported architecture with frame pointers";; - esac +} # ac_fn_c_check_func + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } -if $no_naked_pointers; then - echo "#define NO_NAKED_POINTERS" >> m.h +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } -# Check for mmap support for huge pages and contiguous heap -if sh ./runtest mmap-huge.c; then - has_huge_pages=true - echo "#define HAS_HUGE_PAGES" >>s.h - echo "#define HUGE_PAGE_SIZE (4 * 1024 * 1024)" >>s.h - inf "mmap supports huge pages" +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## --------------------------------- ## +## Report this to caml-list@inria.fr ## +## --------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 else - has_huge_pages=false + eval "$3=\$ac_header_compiler" fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno -# Spacetime profiling, including libunwind detection +} # ac_fn_c_check_header_mongrel -# The number of bits used for profiling information is configurable here. -# The more bits used for profiling, the smaller will be Max_wosize. -# Note that PROFINFO_WIDTH must still be defined even if not configuring -# for Spacetime (see comment in byterun/caml/mlvalues.h on [Profinfo_hd]). -echo "#define PROFINFO_WIDTH $profinfo_width" >> m.h -if $with_profinfo; then - echo "#define WITH_PROFINFO" >> m.h -fi +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : -if $with_spacetime; then - case "$arch,$system" in - amd64,*) - spacetime_supported=true - ;; - *) - spacetime_supported=false - ;; - esac - libunwind_warning=false - if $spacetime_supported; then - echo "Spacetime profiling will be available." - echo "#define WITH_SPACETIME" >> m.h - if $enable_call_counts; then - echo "#define ENABLE_CALL_COUNTS" >> m.h - fi - if $disable_libunwind; then - has_libunwind=no - libunwind_available=false - echo "libunwind support for Spacetime profiling was explicitly disabled." - else - # On Mac OS X, we always use the system libunwind. - if test "$libunwind_lib_dir" != ""; then - case "$arch,$system" in - amd64,macosx) - inf "[WARNING] -libunwind* options are ignored on Mac OS X" - libunwind_warning=true - libunwind_lib="-framework System" - libunwind_lib_temp="$libunwind_lib" - # We need unwinding information at runtime, but since we use - # -no_compact_unwind, we also need -keep_dwarf_unwind otherwise - # the OS X linker will chuck away the DWARF-like (.eh_frame) - # information. (Older versions of OS X don't provide this.) - mkexe="$mkexe -Wl,-keep_dwarf_unwind" - mksharedlib="$mksharedlib -Wl,-keep_dwarf_unwind" - ;; - *) - libunwind_lib="-L$libunwind_lib_dir -lunwind -lunwind-x86_64" - libunwind_lib_temp="-Xl $libunwind_lib" - ;; - esac - else - case "$arch,$system" in - amd64,macosx) - libunwind_lib="-framework System" - libunwind_lib_temp="$libunwind_lib" - mkexe="$mkexe -Wl,-keep_dwarf_unwind" - mksharedlib="$mksharedlib -Wl,-keep_dwarf_unwind" - ;; - *) - libunwind_lib="-lunwind -lunwind-x86_64" - libunwind_lib_temp="$libunwind_lib" - ;; - esac - fi - if test "$libunwind_include_dir" != ""; then - case "$arch,$system" in - amd64,macosx) - if ! $libunwind_warning; then - inf "[WARNING] -libunwind* options are ignored on Mac OS X" - fi - libunwind_include="" - ;; - *) - libunwind_include="-I$libunwind_include_dir" - ;; - esac - else - libunwind_include="" - fi - if sh ./hasgot -i libunwind.h $libunwind_lib_temp $libunwind_include; \ - then - echo "#define HAS_LIBUNWIND" >> s.h - has_libunwind=yes - libunwind_available=true - echo "libunwind support for Spacetime profiling will be available." - else - has_libunwind=no - libunwind_available=false - echo "libunwind support for Spacetime profiling will not be available." - fi - fi - else - echo "Spacetime profiling unavailable: it needs a 64-bit platform with" - echo " support for the native code OCaml compiler." - with_spacetime=false - libunwind_available=false - has_libunwind=no - fi +else + eval "$3=yes" fi - -if ! $shared_libraries_supported; then - with_cplugins=false +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES +# -------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_c_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; -if $with_fpic; then - common_cflags="$common_cflags $sharedcccompopts" - aspp="$aspp $sharedcccompopts" + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid; break +else + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0; +return test_array [0]; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; -if $with_cplugins; then - echo "#define CAML_WITH_CPLUGINS" >> m.h + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=$ac_mid; break +else + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; -if $with_fpic; then - echo "#define CAML_WITH_FPIC" >> m.h + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid +else + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; -if $force_safe_string; then - echo "#define CAML_SAFE_STRING" >> m.h + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + echo >>conftest.val; read $3 > m.h +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno -# Finish generated files +} # ac_fn_c_check_member +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. -cclibs="$cclibs $mathlib" +It was created by OCaml $as_me 4.08.0, which was +generated by GNU Autoconf 2.69. Invocation command line was -config CC "$cc" -config CPP "$cpp" -config CFLAGS "$common_cflags $internal_cflags" -config CPPFLAGS "$common_cppflags $internal_cppflags" -config OCAMLC_CFLAGS "$common_cflags $sharedcccompopts" -config OCAMLC_CPPFLAGS "$common_cppflags" -config LDFLAGS "$ldflags" -config BYTECCLIBS "$cclibs $dllib $pthread_link $instrumented_runtime_libs" -config RPATH "$rpath" -config EXE "$exe" -config EMPTY "" -config OUTPUTEXE "-o \$(EMPTY)" -config SUPPORTS_SHARED_LIBRARIES "$shared_libraries_supported" -config SHAREDCCCOMPOPTS "$sharedcccompopts" -config MKSHAREDLIBRPATH "$mksharedlibrpath" -config NATDYNLINKOPTS "$natdynlinkopts" -cat >> Makefile <>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac fi + as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; - esac - if $with_cplugins; then - inf " C plugins................. yes" - else - inf " C plugins................. no" - fi - if $with_fpic; then - inf " compile with -fPIC........ yes" - else - inf " compile with -fPIC........ no" - fi - inf " native dynlink ........... $natdynlink" - if $profiling; then - inf " profiling with gprof ..... supported" - else - inf " profiling with gprof ..... not supported" - fi - if test "$flambda" = "true"; then - inf " using flambda middle-end . yes" - if test "$with_flambda_invariants" = "true"; then - inf " ... with flambda invariants checks . yes" - else - inf " ... with flambda invariants checks . no" + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo fi - else - inf " using flambda middle-end . no" - fi - if $force_safe_string; then - inf " force safe strings ............. yes" - else - inf " force safe strings ............. no" - if $default_safe_string; then - inf " (-safe-string is the default per-file option)" - else - inf " (-unsafe-string is the default per-file option)" + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo fi - fi - if $flat_float_array; then - inf " flat float arrays ........ yes" - else - inf " flat float arrays ........ no" - fi - if test "$afl_instrument" = "true"; then - inf " afl-fuzz always enabled .. yes" - else - inf " afl-fuzz always enabled .. no" - fi -fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 -if test "$with_debugger" = "ocamldebugger"; then - inf "Source-level replay debugger: supported" -else - inf "Source-level replay debugger: not supported" -fi +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h -if $debugruntime; then - inf "Debug runtime will be compiled and installed" -fi +$as_echo "/* confdefs.h */" > confdefs.h -if $with_instrumented_runtime; then - inf "Instrumented runtime will be compiled and installed" -fi +# Predefined preprocessor variables. -inf "Additional libraries supported:" -inf " $otherlibraries" +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF -if $has_graph; then -inf "Configuration for the \"graph\" library:" -inf " options for compiling .... $x11_include" -inf " options for linking ...... $x11_link" +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site else -inf "The \"graph\" library: not supported" + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done -inf -inf "** OCaml configuration completed successfully **" -inf - -if test ! -z "$MACOSX_DEPLOYMENT_TARGET"; then - wrn "The environment variable MACOSX_DEPLOYMENT_TARGET is set.\n" \ - "This will probably prevent compiling the OCaml system." +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: Configuring OCaml version 4.08.0" >&5 +$as_echo "$as_me: Configuring OCaml version 4.08.0" >&6;} + +# Configuration variables + +## Command-line arguments passed to configure +CONFIGURE_ARGS="$*" + +# Command-line tools section of the Unix manual +programs_man_section=1 + +# Library section of the Unix manual +libraries_man_section=3 + +# Command to build executalbes +mkexe="\$(CC) \$(OC_CFLAGS) \$(OC_CPPFLAGS) \$(OC_LDFLAGS)" + +# Flags for building executable files with debugging symbols +mkexedebugflag="-g" +common_cflags="" +common_cppflags="" +internal_cflags="" +internal_cppflags="" +ocamlc_cflags="" +ocamlc_cppflags="" +ocamlopt_cflags="" +ocamlopt_cppflags="" +oc_ldflags="" +with_sharedlibs=true +ostype="Unix" +iflexdir="" +SO="so" +toolchain="cc" +profinfo=false +profinfo_width=0 +extralibs= + +# Information about the package + +## Source directory + + +## Directory containing auxiliary scripts used dugring build +ac_aux_dir= +for ac_dir in build-aux "$srcdir"/build-aux; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +## Output variables + + +VERSION=4.08.0 + + +# Note: This is present for the flexdll bootstrap where it exposed as the old +# TOOLPREF variable. It would be better if flexdll where updated to require +# WINDRES instead. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # TODO: rename this variable + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## Generated files + +ac_config_files="$ac_config_files Makefile.common" + +ac_config_files="$ac_config_files Makefile.config" + +ac_config_headers="$ac_config_headers runtime/caml/m.h" + +ac_config_headers="$ac_config_headers runtime/caml/s.h" + + +# Checks for system types + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 +$as_echo_n "checking target system type... " >&6; } +if ${ac_cv_target+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 +$as_echo "$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +case $host in #( + *-pc-windows) : + CC=cl + ccomptype=msvc + S=asm + SO=dll + outputexe=-Fe + mkexedebugflag='' + syslib='$(1).lib' ;; #( + *) : + ccomptype=cc + S=s + SO=so + outputexe='-o $(EMPTY)' + syslib='-l$(1)' ;; +esac + +# Environment variables that are taken into account + + + + + +# Command-line arguments to configure + +# Check whether --enable-debug-runtime was given. +if test "${enable_debug_runtime+set}" = set; then : + enableval=$enable_debug_runtime; +fi + + +# Check whether --enable-debugger was given. +if test "${enable_debugger+set}" = set; then : + enableval=$enable_debugger; +else + enable_debugger=auto +fi + + + + +# Check whether --enable-instrumented-runtime was given. +if test "${enable_instrumented_runtime+set}" = set; then : + enableval=$enable_instrumented_runtime; +else + enable_instrumented_runtime=auto +fi + + +# Check whether --enable-vmthreads was given. +if test "${enable_vmthreads+set}" = set; then : + enableval=$enable_vmthreads; +fi + + +# Check whether --enable-systhreads was given. +if test "${enable_systhreads+set}" = set; then : + enableval=$enable_systhreads; +fi + + + +# Check whether --with-libunwind was given. +if test "${with_libunwind+set}" = set; then : + withval=$with_libunwind; +fi + + + + + + +# Check whether --enable-graph-lib was given. +if test "${enable_graph_lib+set}" = set; then : + enableval=$enable_graph_lib; +fi + + +# Check whether --enable-str-lib was given. +if test "${enable_str_lib+set}" = set; then : + enableval=$enable_str_lib; +fi + + +# Check whether --enable-unix-lib was given. +if test "${enable_unix_lib+set}" = set; then : + enableval=$enable_unix_lib; +fi + + +# Check whether --enable-bigarray-lib was given. +if test "${enable_bigarray_lib+set}" = set; then : + enableval=$enable_bigarray_lib; +fi + + +# Check whether --enable-ocamldoc was given. +if test "${enable_ocamldoc+set}" = set; then : + enableval=$enable_ocamldoc; +else + ocamldoc=auto +fi + + +# Check whether --enable-frame-pointers was given. +if test "${enable_frame_pointers+set}" = set; then : + enableval=$enable_frame_pointers; +fi + + +# Check whether --enable-naked-pointers was given. +if test "${enable_naked_pointers+set}" = set; then : + enableval=$enable_naked_pointers; +fi + + +# Check whether --enable-spacetime was given. +if test "${enable_spacetime+set}" = set; then : + enableval=$enable_spacetime; +fi + + +# Check whether --enable-call-counts was given. +if test "${enable_call_counts+set}" = set; then : + enableval=$enable_call_counts; +fi + + +# Check whether --enable-cfi was given. +if test "${enable_cfi+set}" = set; then : + enableval=$enable_cfi; +fi + + +# Check whether --enable-installing-source-artifacts was given. +if test "${enable_installing_source_artifacts+set}" = set; then : + enableval=$enable_installing_source_artifacts; +fi + +# Check whether --enable-installing-bytecode-programs was given. +if test "${enable_installing_bytecode_programs+set}" = set; then : + enableval=$enable_installing_bytecode_programs; +fi + + +# Check whether --enable-native-compiler was given. +if test "${enable_native_compiler+set}" = set; then : + enableval=$enable_native_compiler; +fi + + +# Check whether --enable-flambda was given. +if test "${enable_flambda+set}" = set; then : + enableval=$enable_flambda; +fi + + +# Check whether --enable-flambda-invariants was given. +if test "${enable_flambda_invariants+set}" = set; then : + enableval=$enable_flambda_invariants; +fi + + + +# Check whether --with-target-bindir was given. +if test "${with_target_bindir+set}" = set; then : + withval=$with_target_bindir; +fi + + +# Check whether --enable-reserved-header-bits was given. +if test "${enable_reserved_header_bits+set}" = set; then : + enableval=$enable_reserved_header_bits; case $enable_reserved_header_bits in #( + 0) : + with_profinfo=false + profinfo_width=0 ;; #( + [1-9]|1[0-9]|2[0-1]) : + with_profinfo=true + profinfo_width="$enable_reserved_header_bits" ;; #( + *) : + as_fn_error $? "invalid argument to --enable-reserved-header-bits" "$LINENO" 5 ;; +esac +fi + + + + +# There are two configure-time string safety options, +# --(enable|disable)-force-safe-string and +# DEFAULT_STRING=safe|unsafe that +# interact with a compile-time (un)safe-string option. +# +# If --enable-force-safe-string is set at configure time, then the compiler +# will always enforce that string and bytes are distinct: the +# compile-time -unsafe-string option is disabled. This lets us +# assume pervasive string immutability, for code optimizations and +# in the C layer. +# +# If --disable-force-safe-string is set at configure-time, the compiler +# will use the compile-time (un)safe-string option to decide whether +# string and bytes are compatible on a per-file basis. The +# configuration variable DEFAULT_STRING=safe|unsafe decides which +# setting will be chosen by default, if no compile-time option is +# explicitly passed. +# +# The configure-time behavior of OCaml 4.05 and older was equivalent +# to --disable-force-safe-string DEFAULT_STRING=unsafe. OCaml 4.06 +# and later use --disable-force-safe-string DEFAULT_STRING=safe. We +# expect --enable-force-safe-string to become the default in the future. + +# Check whether --enable-force-safe-string was given. +if test "${enable_force_safe_string+set}" = set; then : + enableval=$enable_force_safe_string; +fi + + + + +# Check whether --enable-flat-float-array was given. +if test "${enable_flat_float_array+set}" = set; then : + enableval=$enable_flat_float_array; +fi + + + +# Check whether --with-afl was given. +if test "${with_afl+set}" = set; then : + withval=$with_afl; +fi + + +if test x"$enable_unix_lib" = "xno"; then : + if test x"$enable_debugger" = "xyes"; then : + as_fn_error $? "replay debugger requires the unix library" "$LINENO" 5 +else + enable_debugger="no" +fi + if test x"$enable_bigarray_lib" = "xyes"; then : + as_fn_error $? "legacy bigarray library requires the unix library" "$LINENO" 5 +fi +fi + +if test x"$enable_unix_lib" = "xno" -o x"$enable_str_lib" = "xno"; then : + if test x"$enable_ocamldoc" = "xyes"; then : + as_fn_error $? "ocamldoc requires the unix and str libraries" "$LINENO" 5 +else + enable_ocamldoc="no" + with_camltex="" +fi +else + with_camltex="true" +fi + +# Initialization of libtool +# Allow the MSVC linker to be found even if ld isn't installed. +# User-specified LD still takes precedence. +if test -n "$ac_tool_prefix"; then + for ac_prog in ld link + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LD"; then + ac_cv_prog_LD="$LD" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LD="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LD=$ac_cv_prog_LD +if test -n "$LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$LD" && break + done +fi +if test -z "$LD"; then + ac_ct_LD=$LD + for ac_prog in ld link +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LD"; then + ac_cv_prog_ac_ct_LD="$ac_ct_LD" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LD="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LD=$ac_cv_prog_ac_ct_LD +if test -n "$ac_ct_LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LD" >&5 +$as_echo "$ac_ct_LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_LD" && break +done + + if test "x$ac_ct_LD" = x; then + LD="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LD=$ac_ct_LD + fi +fi + +# libtool expects host_os=mingw for native Windows +old_host_os=$host_os +if test x"$host_os" = "xwindows"; then : + host_os=mingw +fi +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.6' +macro_revision='2.4.6' + + + + + + + + + + + + + +ltmain=$ac_aux_dir/ltmain.sh + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case $ECHO in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n "$lt_cv_sys_max_cmd_len"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test yes != "$GCC"; then + reload_cmds=false + fi + ;; + darwin*) + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[012][,.]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + pic_mode=default +fi + + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC=$CC +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test yes = "$GCC"; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + lt_prog_compiler_pic='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works"; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works"; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + link_all_deplibs=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='$wl--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test no = "$ld_shlibs"; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + link_all_deplibs=no + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + else + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + osf3*) + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='$wl-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='$wl-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test no = "$ld_shlibs" && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directories which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test yes = "$hardcode_automatic"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen=shl_load +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen=dlopen +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report what library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + +host_os=$old_host_os + +# Extracting information from libtool's configuration +if test -n "$RANLIB" ; then : + RANLIBCMD="$RANLIB" +else + RANLIB="$AR rs"; RANLIBCMD="" + +fi + +case $host in #( + # In config/Makefile.mingw*, we had: + # TARGET=i686-w64-mingw32 and x86_64-w64-mingw32 + # TOOLPREF=$(TARGET)- + # ARCMD=$(TOOLPREF)ar + # RANLIB=$(TOOLPREF)ranlib + # RANLIBCMD=$(TOOLPREF)ranlib + # However autoconf and libtool seem to use ar and ranlib + # So we let them do, at the moment + *-pc-windows) : + + libext=lib + AR=""; RANLIB=echo; RANLIBCMD="" + if test "$host_cpu" = "x86_64" ; then : + machine="-machine:AMD64 " +else + machine="" +fi + mklib="link -lib -nologo $machine /out:\$(1) \$(2)" + ;; #( + *) : + + mklib="rm -f \$(1) && ${AR} rc \$(1) \$(2) && ${RANLIB} \$(1)" + ;; +esac + +# Determine how to call the C preprocessor directly. +# Most of the time, calling the C preprocessor through the C compiler is +# desirable and even important. +# In some cases, though, we want to use the C preprocessor only to +# expand macros. In such cases, it is much more convenient to be able +# to invoke it directly rather than through the C compiler, for instance +# because, when invoked directly, the C preprocessor does not require +# to be invoked on a file with a '.c' extension +# We thus figure out how to invoke the C preprocessor directly but +# let the CPP variable untouched, except for the MSVC port where we set it +# manually to make sure the backward compatibility is preserved +case $host in #( + *-pc-windows) : + CPP="$CC -nologo -EP" ;; #( + *) : + ;; +esac + +# Libraries to build depending on the host + +case $host in #( + *-*-mingw32|*-pc-windows) : + unix_or_win32="win32" + unixlib="win32unix" + graphlib="win32graph" + cc_profile='' ;; #( + *) : + unix_or_win32="unix" + unixlib="unix" + graphlib="graph" + cc_profile='-pg' ;; +esac +case $host in #( + *-*-cygwin*|*-*-mingw32|*-pc-windows) : + exeext=".exe" ;; #( + *) : + exeext='' ;; +esac + +otherlibraries="dynlink" +if test x"$enable_unix_lib" != "xno"; then : + if test x"$enable_bigarray_lib" != "xno"; then : + otherlibraries="$otherlibraries $unixlib bigarray" +else + otherlibraries="$otherlibraries $unixlib" +fi +fi +if test x"$enable_str_lib" != "xno"; then : + otherlibraries="$otherlibraries str" +fi + +# Checks for system services + +## Test whether #! scripts are supported +## TODO: have two values, one for host and one for target +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether #! works in shell scripts" >&5 +$as_echo_n "checking whether #! works in shell scripts... " >&6; } +if ${ac_cv_sys_interpreter+:} false; then : + $as_echo_n "(cached) " >&6 +else + echo '#! /bin/cat +exit 69 +' >conftest +chmod u+x conftest +(SHELL=/bin/sh; export SHELL; ./conftest >/dev/null 2>&1) +if test $? -ne 69; then + ac_cv_sys_interpreter=yes +else + ac_cv_sys_interpreter=no +fi +rm -f conftest +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_interpreter" >&5 +$as_echo "$ac_cv_sys_interpreter" >&6; } +interpval=$ac_cv_sys_interpreter + + +if test "x$interpval" = "xyes"; then : + case $host in #( + *-cygwin|*-*-mingw32|*-pc-windows) : + hashbangscripts=false ;; #( + *) : + hashbangscripts=true + ;; +esac +else + hashbangscripts=false + +fi + +# Are we building a cross-compiler + +if test x"$host" = x"$target"; then : + cross_compiler=false +else + cross_compiler=true +fi + +# Checks for programs + +## Check for the C compiler: done by libtool +## AC_PROG_CC + +## Check for C99 support: done by libtool +## AC_PROG_CC_C99 + +## Find vendor of the C compiler + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking C compiler vendor" >&5 +$as_echo_n "checking C compiler vendor... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if defined(_MSC_VER) +msvc _MSC_VER +#elif defined(__INTEL_COMPILER) +icc __INTEL_COMPILER +#elif defined(__clang_major__) && defined(__clang_minor__) +clang __clang_major__ __clang_minor__ +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) +gcc __GNUC__ __GNUC_MINOR__ +#elif defined(__xlc__) && defined(__xlC__) +xlc __xlC__ __xlC_ver__ +#else +unknown +#endif + +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + if ${ocaml_cv_cc_vendor+:} false; then : + $as_echo_n "(cached) " >&6 +else + ocaml_cv_cc_vendor=`grep '^[a-z]' conftest.i | tr -s ' ' '-'` +fi + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "unexpected preprocessor failure +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.err conftest.i conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ocaml_cv_cc_vendor" >&5 +$as_echo "$ocaml_cv_cc_vendor" >&6; } + + +## Determine which flags to use for the C compiler + +case $ocaml_cv_cc_vendor in #( + xlc-*) : + outputobj='-o $(EMPTY)'; gcc_warnings="-qflag=i:i" ;; #( + # all warnings enabled + msvc-*) : + outputobj=-Fo; CPP="cl -nologo -EP"; gcc_warnings="" ;; #( + *) : + outputobj='-o $(EMPTY)'; case 4.08.0 in #( + *+dev*) : + gcc_warnings="-Wall -Werror" ;; #( + *) : + gcc_warnings="-Wall" + ;; +esac + ;; +esac + +# We select high optimization levels, provided we can turn off: +# - strict type-based aliasing analysis (too risky for the OCaml runtime) +# - strict no-overflow conditions on signed integer arithmetic +# (the OCaml runtime assumes Java-style behavior of signed integer arith.) +# Concerning optimization level, -O3 is somewhat risky, so take -O2. +# Concerning language version, gnu99 is ISO C99 plus GNU extensions +# that are often used in standard headers. Older GCC versions +# defaults to gnu89, which is not C99. Clang defaults to gnu99 or +# gnu11, which is fine. + +# Note: the vendor macro can not recognize MinGW because it calls the +# C preprocessor directly so no compiler specific macro like __MING32__ +# is defined. We thus catch MinGW first by looking at host and examine +# the vendor only as a fall-back. We could put tis part of the logic +# in the macro itself, too +case $host in #( + *-*-mingw32) : + internal_cflags="-Wno-unused $gcc_warnings" + # TODO: see whether the code can be fixed to avoid -Wno-unused + common_cflags="-O -mms-bitfields" + internal_cppflags='-DUNICODE -D_UNICODE' + internal_cppflags="$internal_cppflags -DWINDOWS_UNICODE=" + internal_cppflags="${internal_cppflags}\$(WINDOWS_UNICODE)" ;; #( + *) : + case $ocaml_cv_cc_vendor in #( + clang-*) : + common_cflags="-O2 -fno-strict-aliasing -fwrapv"; + internal_cflags="$gcc_warnings" ;; #( + gcc-012-*) : + # Some versions known to miscompile OCaml, e,g, 2.7.2.1, some 2.96. + # Plus: C99 support unknown. + as_fn_error $? "This version of GCC is too old. + Please use GCC version 4.2 or above." "$LINENO" 5 ;; #( + gcc-3-*|gcc-4-01) : + # No -fwrapv option before GCC 3.4. + # Known problems with -fwrapv fixed in 4.2 only. + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: This version of GCC is rather old. + Reducing optimization level.\"" >&5 +$as_echo "$as_me: WARNING: This version of GCC is rather old. + Reducing optimization level.\"" >&2;}; + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Consider using GCC version 4.2 or above." >&5 +$as_echo "$as_me: WARNING: Consider using GCC version 4.2 or above." >&2;}; + common_cflags="-std=gnu99 -O"; + internal_cflags="$gcc_warnings" ;; #( + gcc-4-*) : + common_cflags="-std=gnu99 -O2 -fno-strict-aliasing -fwrapv \ +-fno-builtin-memcmp"; + internal_cflags="$gcc_warnings" ;; #( + gcc-*) : + common_cflags="-O2 -fno-strict-aliasing -fwrapv"; + internal_cflags="$gcc_warnings" ;; #( + msvc-*) : + common_cflags="-nologo -O2 -Gy- -MD" + common_cppflags="-D_CRT_SECURE_NO_DEPRECATE" + internal_cppflags='-DUNICODE -D_UNICODE' + internal_cppflags="$internal_cppflags -DWINDOWS_UNICODE=" + internal_cppflags="${internal_cppflags}\$(WINDOWS_UNICODE)" ;; #( + xlc-*) : + common_cflags="-O5 -qtune=balanced -qnoipa -qinline $CFLAGS"; + internal_cflags="$gcc_warnings" ;; #( + *) : + common_cflags="-O" ;; +esac ;; +esac + +internal_cppflags="-DCAML_NAME_SPACE $internal_cppflags" + +# Enable SSE2 on x86 mingw to avoid using 80-bit registers. +case $host in #( + i686-*-mingw32) : + internal_cflags="$internal_cflags -mfpmath=sse -msse2" ;; #( + *) : + ;; +esac + +# Use 64-bit file offset if possible +# See also AC_SYS_LARGEFILE +# Problem: flags are added to CC rather than CPPFLAGS +case $host in #( + *-*-mingw32|*-pc-windows) : + ;; #( + *) : + common_cppflags="$common_cppflags -D_FILE_OFFSET_BITS=64" ;; +esac + +# Adjust according to target + +# On Windows we do not take $enable_shared because it does not seem +# to work. This should be better understood later +#AS_CASE([$target], +# [*-pc-windows], +# [enable_shared=yes]) + +if test x"$enable_shared" = "xno"; then : + with_sharedlibs=false +fi + +case $CC,$host in #( + *,*-*-darwin*) : + mkexe="$mkexe -Wl,-no_compact_unwind"; + $as_echo "#define HAS_ARCH_CODE32 1" >>confdefs.h + ;; #( + *,*-*-haiku*) : + mathlib="" ;; #( + *,*-*-cygwin*) : + case $target in #( + i686-*) : + flavor=cygwin ;; #( + x86_64-*) : + flavor=cygwin64 ;; #( + *) : + as_fn_error $? "unknown cygwin variant" "$LINENO" 5 ;; +esac + common_cppflags="$common_cppflags -U_WIN32" + if $with_sharedlibs; then : + flexlink="flexlink -chain $flavor -merge-manifest -stack 16777216" + flexdir=`$flexlink -where | tr -d '\015'` + if test -z "$flexdir"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: flexlink not found: native shared libraries won't be available. + " >&5 +$as_echo "$as_me: WARNING: flexlink not found: native shared libraries won't be available. + " >&2;} + with_sharedlibs=false +else + iflexdir="-I\"$flexdir\"" + mkexe="$flexlink -exe" + mkexedebugflag="-link -g" + +fi + +fi + if ! $with_sharedlibs; then : + mkexe="$mkexe -Wl,--stack,16777216" + oc_ldflags="-Wl,--stack,16777216" + +fi + ostype="Cygwin" ;; #( + *,*-*-mingw32) : + if $with_sharedlibs; then : + case $host in #( + i686-*-*) : + flexdll_chain="mingw" ;; #( + x86_64-*-*) : + flexdll_chain="mingw64" ;; #( + *) : + ;; +esac + flexlink="flexlink -chain $flexdll_chain -merge-manifest -stack 16777216" + flexdir=`$flexlink -where | tr -d '\015'` + if test -z "$flexdir"; then : + flexdir='$(ROOTDIR)/flexdll' +fi + iflexdir="-I\"$flexdir\"" + mkexedebugflag="-link -g" +fi + ostype="Win32" + toolchain="mingw" + mkexe='$(MKEXE_ANSI) $(if $(OC_LDFLAGS),-link "$(OC_LDFLAGS)")' + oc_ldflags='-municode' + SO="dll" ;; #( + *,*-pc-windows) : + toolchain=msvc + ostype="Win32" + mkexe='$(MKEXE_ANSI) $(if $(OC_LDFLAGS),-link "$(OC_LDFLAGS)")' + oc_ldflags='/ENTRY:wmainCRTStartup' + case $host in #( + i686-pc-windows) : + flexdll_chain=msvc ;; #( + x86_64-pc-windows) : + flexdll_chain=msvc64 ;; #( + *) : + ;; +esac + if $with_sharedlibs; then : + flexlink="flexlink -chain $flexdll_chain -merge-manifest -stack 16777216" + flexdir=`$flexlink -where | tr -d '\015'` + if test -z "$flexdir"; then : + flexdir='$(ROOTDIR)/flexdll' +fi + iflexdir="-I\"$flexdir\"" + mkexedebugflag="-link -g" +fi ;; #( + *,x86_64-*-linux*) : + $as_echo "#define HAS_ARCH_CODE32 1" >>confdefs.h + ;; #( + xlc*,powerpc-ibm-aix*) : + mkexe="$mkexe " + oc_ldflags="-brtl -bexpfull" + $as_echo "#define HAS_ARCH_CODE32 1" >>confdefs.h + ;; #( + *) : + ;; +esac + + +## Program to use to install files +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +# Checks for libraries + +## Mathematical library +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 +$as_echo_n "checking for cos in -lm... " >&6; } +if ${ac_cv_lib_m_cos+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cos (); +int +main () +{ +return cos (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_cos=yes +else + ac_cv_lib_m_cos=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_cos" >&5 +$as_echo "$ac_cv_lib_m_cos" >&6; } +if test "x$ac_cv_lib_m_cos" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBM 1 +_ACEOF + + LIBS="-lm $LIBS" + +fi + + +if test "x$ac_cv_lib_m_cos" = xyes ; then : + mathlib="-lm" +else + mathlib="" +fi + +# Checks for header files + +ac_fn_c_check_header_mongrel "$LINENO" "math.h" "ac_cv_header_math_h" "$ac_includes_default" +if test "x$ac_cv_header_math_h" = xyes; then : + +fi + + +for ac_header in unistd.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" +if test "x$ac_cv_header_unistd_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UNISTD_H 1 +_ACEOF + $as_echo "#define HAS_UNISTD 1" >>confdefs.h + +fi + +done + +ac_fn_c_check_header_mongrel "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default" +if test "x$ac_cv_header_stdint_h" = xyes; then : + $as_echo "#define HAS_STDINT_H 1" >>confdefs.h + +fi + + +ac_fn_c_check_header_mongrel "$LINENO" "sys/shm.h" "ac_cv_header_sys_shm_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_shm_h" = xyes; then : + $as_echo "#define HAS_SYS_SHM_H 1" >>confdefs.h + +fi + + +ac_fn_c_check_header_compile "$LINENO" "dirent.h" "ac_cv_header_dirent_h" "#include +" +if test "x$ac_cv_header_dirent_h" = xyes; then : + $as_echo "#define HAS_DIRENT 1" >>confdefs.h + +fi + + + +ac_fn_c_check_header_compile "$LINENO" "sys/select.h" "ac_cv_header_sys_select_h" "#include +" +if test "x$ac_cv_header_sys_select_h" = xyes; then : + $as_echo "#define HAS_SYS_SELECT_H 1" >>confdefs.h + +fi + + + +# Checks for types + +## off_t +ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default" +if test "x$ac_cv_type_off_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define off_t long int +_ACEOF + +fi + +$as_echo "#define HAS_OFF_T 1" >>confdefs.h + + +# Checks for structures + +# Checks for compiler characteristics + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 +$as_echo_n "checking size of int... " >&6; } +if ${ac_cv_sizeof_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_int" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (int) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_int=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 +$as_echo "$ac_cv_sizeof_int" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_INT $ac_cv_sizeof_int +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 +$as_echo_n "checking size of long... " >&6; } +if ${ac_cv_sizeof_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 +$as_echo "$ac_cv_sizeof_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long *" >&5 +$as_echo_n "checking size of long *... " >&6; } +if ${ac_cv_sizeof_long_p+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long *))" "ac_cv_sizeof_long_p" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long_p" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long *) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long_p=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_p" >&5 +$as_echo "$ac_cv_sizeof_long_p" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG_P $ac_cv_sizeof_long_p +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5 +$as_echo_n "checking size of short... " >&6; } +if ${ac_cv_sizeof_short+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_short" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (short) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_short=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5 +$as_echo "$ac_cv_sizeof_short" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SHORT $ac_cv_sizeof_short +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5 +$as_echo_n "checking size of long long... " >&6; } +if ${ac_cv_sizeof_long_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5 +$as_echo "$ac_cv_sizeof_long_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long +_ACEOF + + + +if test "x$ac_cv_sizeof_long_p" = "x4" ; then : + bits=32; arch64=false +elif test "x$ac_cv_sizeof_long_p" = "x8" ; then : + bits=64; arch64=true + $as_echo "#define ARCH_SIXTYFOUR 1" >>confdefs.h + +else + as_fn_error $? "Neither 32 nor 64 bits architecture." "$LINENO" 5 + +fi + +if test "x$ac_cv_sizeof_int" != "x4" && test "x$ac_cv_sizeof_long" != "x4" \ + && test "x$ac_cv_sizeof_short" != "x4"; then : + as_fn_error $? "Sorry, we can't find a 32-bit integer type." "$LINENO" 5 + +fi + +if test "x$ac_cv_sizeof_long" != "x8" && + test "x$ac_cv_sizeof_long_long" != "x8"; then : + as_fn_error $? "Sorry, we can't find a 64-bit integer type." "$LINENO" 5 + +fi + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_PTR $ac_cv_sizeof_long_p +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONGLONG $ac_cv_sizeof_long_long +_ACEOF + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: Target is a $bits bits architecture" >&5 +$as_echo "$as_me: Target is a $bits bits architecture" >&6;} + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define ARCH_BIG_ENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + as_fn_error $? "unable to handle universal endianness" "$LINENO" 5 + + ;; #( + *) + as_fn_error $? "could not determine endianness." "$LINENO" 5 ;; + esac + + +# The cast to long int works around a bug in the HP C Compiler, +# see AC_CHECK_SIZEOF for more information. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of double" >&5 +$as_echo_n "checking alignment of double... " >&6; } +if ${ac_cv_alignof_double+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_double" "$ac_includes_default +#ifndef offsetof +# define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0) +#endif +typedef struct { char x; double y; } ac__type_alignof_;"; then : + +else + if test "$ac_cv_type_double" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute alignment of double +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_alignof_double=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_double" >&5 +$as_echo "$ac_cv_alignof_double" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define ALIGNOF_DOUBLE $ac_cv_alignof_double +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler, +# see AC_CHECK_SIZEOF for more information. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of long" >&5 +$as_echo_n "checking alignment of long... " >&6; } +if ${ac_cv_alignof_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_long" "$ac_includes_default +#ifndef offsetof +# define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0) +#endif +typedef struct { char x; long y; } ac__type_alignof_;"; then : + +else + if test "$ac_cv_type_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute alignment of long +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_alignof_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_long" >&5 +$as_echo "$ac_cv_alignof_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define ALIGNOF_LONG $ac_cv_alignof_long +_ACEOF + + + +if ! $arch64; then : + case $target_cpu in #( + i686) : + ;; #( + *) : + if test "$ac_cv_alignof_double" -gt 4; then : + $as_echo "#define ARCH_ALIGN_DOUBLE 1" >>confdefs.h + +fi + if test "$ac_cv_alignof_long" -gt 4; then : + $as_echo "#define ARCH_ALIGN_LONG 1" >>confdefs.h + +fi + ;; +esac +fi + +# Shared library support + +shared_libraries_supported=false +sharedlib_cflags='' +mksharedlib='shared-libs-not-available' +rpath='' +mksharedlibrpath='' +natdynlinkopts="" + +if test x"$enable_shared" != "xno"; then : + case $host in #( + *-apple-darwin*) : + mksharedlib="$CC -shared -flat_namespace -undefined suppress \ + -Wl,-no_compact_unwind" + shared_libraries_supported=true ;; #( + *-*-mingw32) : + mksharedlib='$(FLEXLINK)' + mkmaindll='$(FLEXLINK) -maindll' + shared_libraries_supported=$with_sharedlibs ;; #( + *-pc-windows) : + mksharedlib='$(FLEXLINK)' + mkmaindll='$(FLEXLINK) -maindll' + shared_libraries_supported=$with_sharedlibs ;; #( + *-*-cygwin*) : + mksharedlib="$flexlink" + mkmaindll="$flexlink -maindll" + shared_libraries_supported=true ;; #( + powerpc-ibm-aix*) : + case $CC in #( + xlc*) : + mksharedlib="$CC -qmkshrobj -G" + shared_libraries_supported=true ;; #( + *) : + ;; +esac ;; #( + *-*-linux*|*-*-freebsd[3-9]*|*-*-freebsd[1-9][0-9]*\ + |*-*-openbsd*|*-*-netbsd*|*-*-dragonfly*|*-*-gnu*|*-*-haiku*) : + sharedlib_cflags="-fPIC" + mksharedlib="$CC -shared" + oc_ldflags="$oc_ldflags -Wl,-E" + rpath="-Wl,-rpath," + mksharedlibrpath="-Wl,-rpath," + natdynlinkopts="-Wl,-E" + shared_libraries_supported=true ;; #( + *) : + ;; +esac +fi + +if test -z "$mkmaindll"; then : + mkmaindll=$mksharedlib +fi + +# Configure native dynlink + +natdynlink=false + +if test x"$enable_shared" != "xno"; then : + case "$host" in #( + *-*-cygwin*) : + natdynlink=true ;; #( + *-*-mingw32) : + natdynlink=true ;; #( + *-pc-windows) : + natdynlink=true ;; #( + i[3456]86-*-linux*) : + natdynlink=true ;; #( + i[3456]86-*-gnu*) : + natdynlink=true ;; #( + x86_64-*-linux*) : + natdynlink=true ;; #( + i[3456]86-*-darwin*) : + if $arch64; then : + natdynlink=true +fi ;; #( + x86_64-*-darwin*) : + natdynlink=true ;; #( + s390x*-*-linux*) : + natdynlink=true ;; #( + powerpc*-*-linux*) : + natdynlink=true ;; #( + i686-*-kfreebsd*) : + natdynlink=true ;; #( + x86_64-*-kfreebsd*) : + natdynlink=true ;; #( + x86_64-*-dragonfly*) : + natdynlink=true ;; #( + i[3456]86-*-freebsd*) : + natdynlink=true ;; #( + x86_64-*-freebsd*) : + natdynlink=true ;; #( + i[3456]86-*-openbsd*) : + natdynlink=true ;; #( + x86_64-*-openbsd*) : + natdynlink=true ;; #( + i[3456]86-*-netbsd*) : + natdynlink=true ;; #( + x86_64-*-netbsd*) : + natdynlink=true ;; #( + i386-*-gnu0.3) : + natdynlink=true ;; #( + i[3456]86-*-haiku*) : + natdynlink=true ;; #( + arm*-*-linux*) : + natdynlink=true ;; #( + arm*-*-freebsd*) : + natdynlink=true ;; #( + earm*-*-netbsd*) : + natdynlink=true ;; #( + aarch64-*-linux*) : + natdynlink=true ;; #( + *) : + ;; +esac +fi + +# Try to work around the Skylake/Kaby Lake processor bug. +case "$CC,$host" in #( + *gcc*,x86_64-*|*gcc*,i686-*) : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler supports -fno-tree-vrp" >&5 +$as_echo_n "checking whether the C compiler supports -fno-tree-vrp... " >&6; } + saved_CFLAGS="$CFLAGS" + CFLAGS="-Werror -fno-tree-vrp $CFLAGS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main() { return 0; } +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cc_has_fno_tree_vrp=true + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + cc_has_fno_tree_vrp=false + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$saved_CFLAGS" + + if $cc_has_fno_tree_vrp; then : + internal_cflags="$internal_cflags -fno-tree-vrp" +fi ;; #( + *) : + ;; +esac + +# Configure the native-code compiler + +arch=none +model=default +system=unknown + +case $host in #( + i[3456]86-*-linux*) : + arch=i386; system=linux_elf ;; #( + i[3456]86-*-*bsd*) : + arch=i386; system=bsd_elf ;; #( + i[3456]86-*-haiku*) : + arch=i386; system=beos ;; #( + i[3456]86-*-cygwin) : + arch=i386; system=cygwin ;; #( + i[3456]86-*-darwin*) : + if $arch64; then : + arch=amd64 +else + arch=i386 +fi; system=macosx ;; #( + i[3456]86-*-gnu*) : + arch=i386; system=gnu ;; #( + i[3456]86-*-mingw32) : + arch=i386; system=mingw ;; #( + i686-pc-windows) : + arch=i386; system=win32 ;; #( + x86_64-pc-windows) : + arch=amd64; system=win64 ;; #( + powerpc64le*-*-linux*) : + arch=power; model=ppc64le; system=elf ;; #( + powerpc*-*-linux*) : + arch=power; if $arch64; then : + model=ppc64 +else + model=ppc +fi; system=elf ;; #( + powerpc-*-netbsd*) : + arch=power; model=ppc; system=netbsd ;; #( + powerpc-*-openbsd*) : + arch=power; model=ppc; system=bsd_elf ;; #( + s390x*-*-linux*) : + arch=s390x; model=z10; system=elf ;; #( + armv6*-*-linux-gnueabihf) : + arch=arm; model=armv6; system=linux_eabihf ;; #( + armv7*-*-linux-gnueabihf) : + arch=arm; model=armv7; system=linux_eabihf ;; #( + armv8*-*-linux-gnueabihf) : + arch=arm; model=armv8; system=linux_eabihf ;; #( + armv8*-*-linux-gnueabi) : + arch=arm; model=armv8; system=linux_eabi ;; #( + armv7*-*-linux-gnueabi) : + arch=arm; model=armv7; system=linux_eabi ;; #( + armv6t2*-*-linux-gnueabi) : + arch=arm; model=armv6t2; system=linux_eabi ;; #( + armv6*-*-linux-gnueabi) : + arch=arm; model=armv6; system=linux_eabi ;; #( + armv6*-*-freebsd*) : + arch=arm; model=armv6; system=freebsd ;; #( + earmv6*-*-netbsd*) : + arch=arm; model=armv6; system=netbsd ;; #( + earmv7*-*-netbsd*) : + arch=arm; model=armv7; system=netbsd ;; #( + armv5te*-*-linux-gnueabi) : + arch=arm; model=armv5te; system=linux_eabi ;; #( + armv5*-*-linux-gnueabi) : + arch=arm; model=armv5; system=linux_eabi ;; #( + arm*-*-linux-gnueabi) : + arch=arm; system=linux_eabi ;; #( + arm*-*-openbsd*) : + arch=arm; system=bsd ;; #( + zaurus*-*-openbsd*) : + arch=arm; system=bsd ;; #( + x86_64-*-linux*) : + arch=amd64; system=linux ;; #( + x86_64-*-gnu*) : + arch=amd64; system=gnu ;; #( + x86_64-*-dragonfly*) : + arch=amd64; system=dragonfly ;; #( + x86_64-*-freebsd*) : + arch=amd64; system=freebsd ;; #( + x86_64-*-netbsd*) : + arch=amd64; system=netbsd ;; #( + x86_64-*-openbsd*) : + arch=amd64; system=openbsd ;; #( + x86_64-*-darwin*) : + arch=amd64; system=macosx ;; #( + x86_64-*-mingw32) : + arch=amd64; system=mingw64 ;; #( + aarch64-*-linux*) : + arch=arm64; system=linux ;; #( + x86_64-*-cygwin*) : + arch=amd64; system=cygwin + ;; #( + *) : + ;; +esac + +if test x"$enable_native_compiler" = "xno"; then : + arch=none; model=default; system=unknown; native_compiler=false + { $as_echo "$as_me:${as_lineno-$LINENO}: the native compiler is disabled" >&5 +$as_echo "$as_me: the native compiler is disabled" >&6;} +else + native_compiler=true +fi + +if ! $native_compiler; then : + natdynlink=false +fi + +if $natdynlink; then : + cmxs="cmxs" +else + cmxs="cmx" +fi + +cat >>confdefs.h <<_ACEOF +#define OCAML_OS_TYPE "$ostype" +_ACEOF + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args. +set dummy ${ac_tool_prefix}ld; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DIRECT_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DIRECT_LD"; then + ac_cv_prog_DIRECT_LD="$DIRECT_LD" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DIRECT_LD="${ac_tool_prefix}ld" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DIRECT_LD=$ac_cv_prog_DIRECT_LD +if test -n "$DIRECT_LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DIRECT_LD" >&5 +$as_echo "$DIRECT_LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DIRECT_LD"; then + ac_ct_DIRECT_LD=$DIRECT_LD + # Extract the first word of "ld", so it can be a program name with args. +set dummy ld; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DIRECT_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DIRECT_LD"; then + ac_cv_prog_ac_ct_DIRECT_LD="$ac_ct_DIRECT_LD" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DIRECT_LD="ld" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DIRECT_LD=$ac_cv_prog_ac_ct_DIRECT_LD +if test -n "$ac_ct_DIRECT_LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DIRECT_LD" >&5 +$as_echo "$ac_ct_DIRECT_LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DIRECT_LD" = x; then + DIRECT_LD="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DIRECT_LD=$ac_ct_DIRECT_LD + fi +else + DIRECT_LD="$ac_cv_prog_DIRECT_LD" +fi + +if test -z "$PARTIALLD"; then : + # The string for PACKLD must be capable of being concatenated with the + # output filename. Don't assume that all C compilers understand GNU -ofoo + # form, so ensure that the definition includes a space at the end (which is + # achieved using the $(EMPTY) expansion trick). + case "$arch,$CC,$system,$model" in #( + amd64,gcc*,macosx,*) : + PACKLD='ld -r -arch x86_64 -o $(EMPTY)' ;; #( + amd64,gcc*,solaris,*) : + PACKLD='ld -r -m elf_x86_64 -o $(EMPTY)' ;; #( + power,gcc*,elf,ppc) : + PACKLD='ld -r -m elf32ppclinux -o $(EMPTY)' ;; #( + power,gcc*,elf,ppc64) : + PACKLD='ld -r -m elf64ppc -o $(EMPTY)' ;; #( + power,gcc*,elf,ppc64le) : + PACKLD='ld -r -m elf64lppc -o $(EMPTY)' ;; #( + # For the Microsoft C compiler there must be no space at the end of the + # string. + *,cl,*,*) : + PACKLD="link -lib -nologo $machine -out:" ;; #( + *) : + PACKLD="$DIRECT_LD -r -o \$(EMPTY)" ;; +esac +else + PACKLD="$PARTIALLD -o \$(EMPTY)" +fi + +if test $arch != "none" && $arch64 ; then : + otherlibraries="$otherlibraries raw_spacetime_lib" +fi + +# Profiling + +case "$arch,$system" in #( + i386,linux_elf) : + profiling=true ;; #( + i386,gnu) : + profiling=true ;; #( + i386,bsd_elf) : + profiling=true ;; #( + amd64,macosx) : + profiling=true ;; #( + i386,macosx) : + profiling=true ;; #( + amd64,linux) : + profiling=true ;; #( + amd64,openbsd) : + profiling=true ;; #( + amd64,freebsd) : + profiling=true ;; #( + amd64,netbsd) : + profiling=true ;; #( + arm,netbsd) : + profiling=true ;; #( + amd64,gnu) : + profiling=true ;; #( + arm,linux*) : + profiling=true ;; #( + power,elf) : + profiling=true ;; #( + power,bsd*) : + profiling=true ;; #( + power,netbsd) : + profiling=true ;; #( + *) : + profiling=false ;; +esac + +# Assembler + +case $host in #( + *-*-mingw32|*-pc-windows) : + asppprofflags='' ;; #( + *) : + asppprofflags='-DPROFILING' ;; +esac + +if test -n "$host_alias"; then : + toolpref="${host}-" +else + toolpref="" +fi + +# We first compute default values for as and aspp +# If values have been given by the user then they take precedence over +# those just computed +# One may want to check whether the user provided values first +# and only compute values if none has been provided + +case "$arch,$system" in #( + i386,win32) : + default_as="ml -nologo -coff -Cp -c -Fo" ;; #( + amd64,win64) : + default_as="ml64 -nologo -Cp -c -Fo" ;; #( + amd64,macosx) : + case $ocaml_cv_cc_vendor in #( + clang-*) : + default_as='clang -arch x86_64 -Wno-trigraphs -c' + default_aspp='clang -arch x86_64 -Wno-trigraphs -c' ;; #( + *) : + default_as="${toolpref}as -arch x86_64" + default_aspp="${toolpref}gcc -arch x86_64 -c" ;; +esac ;; #( + amd64,solaris) : + default_as="${toolpref}as --64" + default_aspp="${toolpref}gcc -m64 -c" ;; #( + i386,solaris) : + default_as="${toolpref}as" + default_aspp="${toolpref}gcc -c" ;; #( + power,elf) : + case $model in #( + ppc64le) : + default_as="${toolpref}as -a64 -mpower8" + default_aspp="${toolpref}gcc -m64 -mcpu=powerpc64le -c" ;; #( + ppc64) : + default_as="${toolpref}as -a64 -mppc64" + default_aspp="${toolpref}gcc -m64 -c" ;; #( + ppc) : + default_as="${toolpref}as -mppc" + default_aspp="${toolpref}gcc -m32 -c" ;; #( + *) : + ;; +esac ;; #( + s390x,elf) : + default_as="${toolpref}as -m 64 -march=$model" + default_aspp="${toolpref}gcc -c -Wa,-march=$model" ;; #( + arm,freebsd) : + default_as="${toolpref}cc -c" + default_aspp="${toolpref}cc -c" ;; #( + *,dragonfly) : + default_as="${toolpref}as" + default_aspp="${toolpref}cc -c" ;; #( + *,freebsd) : + default_as="${toolpref}as" + default_aspp="${toolpref}cc -c" ;; #( + amd64,*|arm,*|arm64,*|i386,*|power,bsd*|power,netbsd) : + default_as="${toolpref}as" + case $ocaml_cv_cc_vendor in #( + clang-*) : + default_aspp="${toolpref}clang -c -Wno-trigraphs" ;; #( + *) : + default_aspp="${toolpref}gcc -c" ;; +esac ;; #( + *) : + ;; +esac + +if test "$with_pic"; then : + fpic=true + $as_echo "#define CAML_WITH_FPIC 1" >>confdefs.h + + internal_cflags="$internal_cflags $sharedlib_cflags" + default_aspp="$default_aspp $sharedlib_cflags" +else + fpic=false +fi + +if test -z "$AS"; then : + AS="$default_as" +fi + +if test -z "$ASPP"; then : + ASPP="$default_aspp" +fi + +# Checks for library functions + +## Check the semantics of signal handlers + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking semantics of signal handlers" >&5 +$as_echo "$as_me: checking semantics of signal handlers" >&6;} + ac_fn_c_check_func "$LINENO" "sigaction" "ac_cv_func_sigaction" +if test "x$ac_cv_func_sigaction" = xyes; then : + has_sigaction=true +else + has_sigaction=false +fi + + ac_fn_c_check_func "$LINENO" "sigprocmask" "ac_cv_func_sigprocmask" +if test "x$ac_cv_func_sigprocmask" = xyes; then : + has_sigprocmask=true +else + has_sigprocmask=false +fi + + if $has_sigaction && $has_sigprocmask; then : + $as_echo "#define POSIX_SIGNALS 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: POSIX signal handling found." >&5 +$as_echo "$as_me: POSIX signal handling found." >&6;} +else + { $as_echo "$as_me:${as_lineno-$LINENO}: assuming signals have the System V semantics." >&5 +$as_echo "$as_me: assuming signals have the System V semantics." >&6;} + for ac_func in sigsetmask +do : + ac_fn_c_check_func "$LINENO" "sigsetmask" "ac_cv_func_sigsetmask" +if test "x$ac_cv_func_sigsetmask" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SIGSETMASK 1 +_ACEOF + $as_echo "#define HAS_SIGSETMASK 1" >>confdefs.h + +fi +done + + + +fi + + +## Check for C99 float ops + +# Note: this was disabled on Windows but the autoconf-generated script +# does find the function it is looking for. +# however the fma test does not pass so we disable the feature +# for the moment, to be backward-compatible + +case $host in #( + *-*-mingw32|*-pc-windows) : + ;; #( + *) : + has_c99_float_ops=true + ac_fn_c_check_func "$LINENO" "expm1" "ac_cv_func_expm1" +if test "x$ac_cv_func_expm1" = xyes; then : + +else + has_c99_float_ops=false +fi + + if $has_c99_float_ops; then : + ac_fn_c_check_func "$LINENO" "log1p" "ac_cv_func_log1p" +if test "x$ac_cv_func_log1p" = xyes; then : + +else + has_c99_float_ops=false +fi + +fi + if $has_c99_float_ops; then : + ac_fn_c_check_func "$LINENO" "hypot" "ac_cv_func_hypot" +if test "x$ac_cv_func_hypot" = xyes; then : + +else + has_c99_float_ops=false +fi + +fi + if $has_c99_float_ops; then : + ac_fn_c_check_func "$LINENO" "fma" "ac_cv_func_fma" +if test "x$ac_cv_func_fma" = xyes; then : + + case $target in #( + x86_64-*-cygwin) : + ;; #( + *) : + $as_echo "#define HAS_WORKING_FMA 1" >>confdefs.h + ;; +esac +else + has_c99_float_ops=false +fi + +fi + if $has_c99_float_ops; then : + ac_fn_c_check_func "$LINENO" "copysign" "ac_cv_func_copysign" +if test "x$ac_cv_func_copysign" = xyes; then : + $as_echo "#define HAS_C99_FLOAT_OPS 1" >>confdefs.h + +fi + +fi ;; +esac + +## getrusage +ac_fn_c_check_func "$LINENO" "getrusage" "ac_cv_func_getrusage" +if test "x$ac_cv_func_getrusage" = xyes; then : + $as_echo "#define HAS_GETRUSAGE 1" >>confdefs.h + +fi + + +## times +ac_fn_c_check_func "$LINENO" "times" "ac_cv_func_times" +if test "x$ac_cv_func_times" = xyes; then : + $as_echo "#define HAS_TIMES 1" >>confdefs.h + +fi + + +## secure_getenv and __secure_getenv + +saved_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="-D_GNU_SOURCE $CPPFLAGS" + +ac_fn_c_check_func "$LINENO" "secure_getenv" "ac_cv_func_secure_getenv" +if test "x$ac_cv_func_secure_getenv" = xyes; then : + $as_echo "#define HAS_SECURE_GETENV 1" >>confdefs.h + +else + ac_fn_c_check_func "$LINENO" "__secure_getenv" "ac_cv_func___secure_getenv" +if test "x$ac_cv_func___secure_getenv" = xyes; then : + $as_echo "#define HAS___SECURE_GETENV 1" >>confdefs.h + +fi + +fi + + +CPP_FLAGS="$saved_CPPFLAGS" + +## issetugid + +ac_fn_c_check_func "$LINENO" "issetugid" "ac_cv_func_issetugid" +if test "x$ac_cv_func_issetugid" = xyes; then : + $as_echo "#define HAS_ISSETUGID 1" >>confdefs.h + +fi + + +## clock_gettime, for the instrumented runtime + +## Note: on MinGW, configure finds a clock_gettime and thus the build +# system tries to build the instrumented runtime, which causes +# warnings. For the moment we simply disable it on MinGW +# but this would need to be further investigated +case $host in #( + *-*-mingw32) : + instrumented_runtime=false ;; #( + *) : + if test "x$enable_instrumented_runtime" = "xno" ; then : + instrumented_runtime=false; instrumented_runtime_libs="" +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 +$as_echo_n "checking for library containing clock_gettime... " >&6; } +if ${ac_cv_search_clock_gettime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +for ac_lib in '' rt; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_clock_gettime=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_clock_gettime+:} false; then : + break +fi +done +if ${ac_cv_search_clock_gettime+:} false; then : + +else + ac_cv_search_clock_gettime=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 +$as_echo "$ac_cv_search_clock_gettime" >&6; } +ac_res=$ac_cv_search_clock_gettime +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + has_clock_gettime=true +else + has_clock_gettime=false +fi + + case $enable_instrumented_runtime,$has_clock_gettime in #( + *,true) : + instrumented_runtime=true + if test "x$ac_cv_search_clock_gettime" = "xnone required"; then : + instrumented_runtime_libs="" +else + instrumented_runtime_libs=$ac_cv_search_clock_gettime +fi ;; #( + auto,*) : + instrumented_runtime=false ;; #( + yes,*) : + as_fn_error $? "the instrumented runtime can not be built" "$LINENO" 5 ;; #( + *) : + ;; +esac +fi ;; +esac + +## Sockets + +## TODO: check whether the different libraries are really useful + +sockets=false + +case $host in #( + *-*-mingw32|*-pc-windows) : + cclibs="$cclibs -lws2_32" + sockets=true ;; #( + *) : + + ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket" +if test "x$ac_cv_func_socket" = xyes; then : + +fi + + ac_fn_c_check_func "$LINENO" "socketpair" "ac_cv_func_socketpair" +if test "x$ac_cv_func_socketpair" = xyes; then : + +fi + + ac_fn_c_check_func "$LINENO" "bind" "ac_cv_func_bind" +if test "x$ac_cv_func_bind" = xyes; then : + +fi + + ac_fn_c_check_func "$LINENO" "listen" "ac_cv_func_listen" +if test "x$ac_cv_func_listen" = xyes; then : + +fi + + ac_fn_c_check_func "$LINENO" "accept" "ac_cv_func_accept" +if test "x$ac_cv_func_accept" = xyes; then : + +fi + + ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect" +if test "x$ac_cv_func_connect" = xyes; then : + +fi + + sockets=true + + ;; +esac + +if $sockets; then : + $as_echo "#define HAS_SOCKETS 1" >>confdefs.h + +fi + +## socklen_t in sys/socket.h + +ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "#include +" +if test "x$ac_cv_type_socklen_t" = xyes; then : + $as_echo "#define HAS_SOCKLEN_T 1" >>confdefs.h + +fi + + +ac_fn_c_check_func "$LINENO" "inet_aton" "ac_cv_func_inet_aton" +if test "x$ac_cv_func_inet_aton" = xyes; then : + $as_echo "#define HAS_INET_ATON 1" >>confdefs.h + +fi + + +## IPv6 support + +ipv6=true + +ac_fn_c_check_type "$LINENO" "struct sockaddr_in6" "ac_cv_type_struct_sockaddr_in6" " +#include +#include +#include + + +" +if test "x$ac_cv_type_struct_sockaddr_in6" = xyes; then : + +else + ipv6=false +fi + + +if $ipv6; then : + ac_fn_c_check_func "$LINENO" "getaddrinfo" "ac_cv_func_getaddrinfo" +if test "x$ac_cv_func_getaddrinfo" = xyes; then : + +else + ipv6=false +fi + +fi + +if $ipv6; then : + ac_fn_c_check_func "$LINENO" "getnameinfo" "ac_cv_func_getnameinfo" +if test "x$ac_cv_func_getnameinfo" = xyes; then : + +else + ipv6=false +fi + +fi + +if $ipv6; then : + ac_fn_c_check_func "$LINENO" "inet_pton" "ac_cv_func_inet_pton" +if test "x$ac_cv_func_inet_pton" = xyes; then : + +else + ipv6=false +fi + +fi + +if $ipv6; then : + ac_fn_c_check_func "$LINENO" "inet_ntop" "ac_cv_func_inet_ntop" +if test "x$ac_cv_func_inet_ntop" = xyes; then : + $as_echo "#define HAS_IPV6 1" >>confdefs.h + +fi + +fi + +ac_fn_c_check_func "$LINENO" "rewinddir" "ac_cv_func_rewinddir" +if test "x$ac_cv_func_rewinddir" = xyes; then : + $as_echo "#define HAS_REWINDDIR 1" >>confdefs.h + +fi + + +ac_fn_c_check_func "$LINENO" "lockf" "ac_cv_func_lockf" +if test "x$ac_cv_func_lockf" = xyes; then : + $as_echo "#define HAS_LOCKF 1" >>confdefs.h + +fi + + +ac_fn_c_check_func "$LINENO" "mkfifo" "ac_cv_func_mkfifo" +if test "x$ac_cv_func_mkfifo" = xyes; then : + $as_echo "#define HAS_MKFIFO 1" >>confdefs.h + +fi + + +ac_fn_c_check_func "$LINENO" "getcwd" "ac_cv_func_getcwd" +if test "x$ac_cv_func_getcwd" = xyes; then : + $as_echo "#define HAS_GETCWD 1" >>confdefs.h + +fi + + +ac_fn_c_check_func "$LINENO" "getpriority" "ac_cv_func_getpriority" +if test "x$ac_cv_func_getpriority" = xyes; then : + ac_fn_c_check_func "$LINENO" "setpriority" "ac_cv_func_setpriority" +if test "x$ac_cv_func_setpriority" = xyes; then : + $as_echo "#define HAS_GETPRIORITY 1" >>confdefs.h + +fi + +fi + + +## utime +## Note: this was defined in config/s-nt.h but the autoconf macros do not +# seem to detect it properly on Windows so we hardcode the definition +# of HAS_UTIME on Windows but this will probably need to be clarified +case $host in #( + *-*-mingw32|*-pc-windows) : + $as_echo "#define HAS_UTIME 1" >>confdefs.h + ;; #( + *) : + ac_fn_c_check_header_mongrel "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_types_h" = xyes; then : + ac_fn_c_check_header_mongrel "$LINENO" "utime.h" "ac_cv_header_utime_h" "$ac_includes_default" +if test "x$ac_cv_header_utime_h" = xyes; then : + ac_fn_c_check_func "$LINENO" "utime" "ac_cv_func_utime" +if test "x$ac_cv_func_utime" = xyes; then : + $as_echo "#define HAS_UTIME 1" >>confdefs.h + +fi + +fi + + +fi + + ;; +esac + +ac_fn_c_check_func "$LINENO" "utimes" "ac_cv_func_utimes" +if test "x$ac_cv_func_utimes" = xyes; then : + $as_echo "#define HAS_UTIMES 1" >>confdefs.h + +fi + + +ac_fn_c_check_func "$LINENO" "dup2" "ac_cv_func_dup2" +if test "x$ac_cv_func_dup2" = xyes; then : + $as_echo "#define HAS_DUP2 1" >>confdefs.h + +fi + + +ac_fn_c_check_func "$LINENO" "fchmod" "ac_cv_func_fchmod" +if test "x$ac_cv_func_fchmod" = xyes; then : + ac_fn_c_check_func "$LINENO" "fchown" "ac_cv_func_fchown" +if test "x$ac_cv_func_fchown" = xyes; then : + $as_echo "#define HAS_FCHMOD 1" >>confdefs.h + +fi + +fi + + +ac_fn_c_check_func "$LINENO" "truncate" "ac_cv_func_truncate" +if test "x$ac_cv_func_truncate" = xyes; then : + ac_fn_c_check_func "$LINENO" "ftruncate" "ac_cv_func_ftruncate" +if test "x$ac_cv_func_ftruncate" = xyes; then : + $as_echo "#define HAS_TRUNCATE 1" >>confdefs.h + +fi + +fi + + +## select +ac_fn_c_check_func "$LINENO" "select" "ac_cv_func_select" +if test "x$ac_cv_func_select" = xyes; then : + ac_fn_c_check_type "$LINENO" "fd_set" "ac_cv_type_fd_set" " +#include +#include + +" +if test "x$ac_cv_type_fd_set" = xyes; then : + $as_echo "#define HAS_SELECT 1" >>confdefs.h + + select=true +else + select=false +fi + +fi + + +ac_fn_c_check_func "$LINENO" "nanosleep" "ac_cv_func_nanosleep" +if test "x$ac_cv_func_nanosleep" = xyes; then : + $as_echo "#define HAS_NANOSLEEP 1" >>confdefs.h + +fi + + +ac_fn_c_check_func "$LINENO" "symlink" "ac_cv_func_symlink" +if test "x$ac_cv_func_symlink" = xyes; then : + ac_fn_c_check_func "$LINENO" "readlink" "ac_cv_func_readlink" +if test "x$ac_cv_func_readlink" = xyes; then : + ac_fn_c_check_func "$LINENO" "lstat" "ac_cv_func_lstat" +if test "x$ac_cv_func_lstat" = xyes; then : + $as_echo "#define HAS_SYMLINK 1" >>confdefs.h + +fi + +fi + +fi + + +# wait +ac_fn_c_check_func "$LINENO" "waitpid" "ac_cv_func_waitpid" +if test "x$ac_cv_func_waitpid" = xyes; then : + + wait=true + $as_echo "#define HAS_WAITPID 1" >>confdefs.h + + +else + wait=false +fi + + +ac_fn_c_check_func "$LINENO" "wait4" "ac_cv_func_wait4" +if test "x$ac_cv_func_wait4" = xyes; then : + + has_wait=true + $as_echo "#define HAS_WAIT4 1" >>confdefs.h + + +fi + + +## getgroups +ac_fn_c_check_func "$LINENO" "getgroups" "ac_cv_func_getgroups" +if test "x$ac_cv_func_getgroups" = xyes; then : + $as_echo "#define HAS_GETGROUPS 1" >>confdefs.h + +fi + + +## setgroups +ac_fn_c_check_func "$LINENO" "setgroups" "ac_cv_func_setgroups" +if test "x$ac_cv_func_setgroups" = xyes; then : + $as_echo "#define HAS_SETGROUPS 1" >>confdefs.h + +fi + + +## initgroups +ac_fn_c_check_func "$LINENO" "initgroups" "ac_cv_func_initgroups" +if test "x$ac_cv_func_initgroups" = xyes; then : + $as_echo "#define HAS_INITGROUPS 1" >>confdefs.h + +fi + + +## termios + +ac_fn_c_check_header_mongrel "$LINENO" "termios.h" "ac_cv_header_termios_h" "$ac_includes_default" +if test "x$ac_cv_header_termios_h" = xyes; then : + ac_fn_c_check_func "$LINENO" "tcgetattr" "ac_cv_func_tcgetattr" +if test "x$ac_cv_func_tcgetattr" = xyes; then : + ac_fn_c_check_func "$LINENO" "tcsetattr" "ac_cv_func_tcsetattr" +if test "x$ac_cv_func_tcsetattr" = xyes; then : + ac_fn_c_check_func "$LINENO" "tcsendbreak" "ac_cv_func_tcsendbreak" +if test "x$ac_cv_func_tcsendbreak" = xyes; then : + ac_fn_c_check_func "$LINENO" "tcflush" "ac_cv_func_tcflush" +if test "x$ac_cv_func_tcflush" = xyes; then : + ac_fn_c_check_func "$LINENO" "tcflow" "ac_cv_func_tcflow" +if test "x$ac_cv_func_tcflow" = xyes; then : + $as_echo "#define HAS_TERMIOS 1" >>confdefs.h + +fi + +fi + +fi + +fi + +fi + +fi + + + +## Asynchronous I/O + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for asynchronous I/O" >&5 +$as_echo_n "checking for asynchronous I/O... " >&6; } +if test "$cross_compiling" = yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#include +#include +#include +#include + +int signalled; + +void sigio_handler(int arg) +{ + signalled = 1; +} + +int main(void) +{ +#if defined(SIGIO) && defined(FASYNC) && defined(F_SETFL) && defined(F_SETOWN) + int p[2]; + int ret; +#define OUT 0 +#define IN 1 + if (socketpair(PF_UNIX, SOCK_STREAM, 0, p) == -1) return 1; + signalled = 0; + signal(SIGIO, sigio_handler); + ret = fcntl(p[OUT], F_GETFL, 0); + fcntl(p[OUT], F_SETFL, ret | FASYNC); + fcntl(p[OUT], F_SETOWN, getpid()); + switch(fork()) { + case -1: + return 1; + case 0: + close(p[OUT]); + write(p[IN], "x", 1); + sleep(1); + exit(0); + default: + close(p[IN]); + while(wait(NULL) == -1 && errno == EINTR) /*nothing*/; + } + if (signalled) return 0; else return 1; +#else + return 1; +#endif +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + + $as_echo "#define HAS_ASYNC_IO 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +## setitimer + +ac_fn_c_check_func "$LINENO" "setitimer" "ac_cv_func_setitimer" +if test "x$ac_cv_func_setitimer" = xyes; then : + + setitimer=true + $as_echo "#define HAS_SETITIMER 1" >>confdefs.h + + +else + setitimer=false +fi + + +## gethostname +# Note: detection fails on Windows so hardcoding the result +# (should be debugged later) +case $host in #( + *-*-mingw32|*-pc-windows) : + $as_echo "#define HAS_GETHOSTNAME 1" >>confdefs.h + ;; #( + *) : + ac_fn_c_check_func "$LINENO" "gethostname" "ac_cv_func_gethostname" +if test "x$ac_cv_func_gethostname" = xyes; then : + $as_echo "#define HAS_GETHOSTNAME 1" >>confdefs.h + +fi + ;; +esac + +## uname + +ac_fn_c_check_header_mongrel "$LINENO" "sys/utsname.h" "ac_cv_header_sys_utsname_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_utsname_h" = xyes; then : + ac_fn_c_check_func "$LINENO" "uname" "ac_cv_func_uname" +if test "x$ac_cv_func_uname" = xyes; then : + $as_echo "#define HAS_UNAME 1" >>confdefs.h + +fi + +fi + + + +## gettimeofday + +ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" +if test "x$ac_cv_func_gettimeofday" = xyes; then : + + gettimeofday=true + $as_echo "#define HAS_GETTIMEOFDAY 1" >>confdefs.h + + +else + gettimeofday=false +fi + + +## mktime + +ac_fn_c_check_func "$LINENO" "mktime" "ac_cv_func_mktime" +if test "x$ac_cv_func_mktime" = xyes; then : + $as_echo "#define HAS_MKTIME 1" >>confdefs.h + +fi + + +## setsid + +case $host in #( + *-cygwin|*-*-mingw32|*-pc-windows) : + ;; #( + *) : + ac_fn_c_check_func "$LINENO" "setsid" "ac_cv_func_setsid" +if test "x$ac_cv_func_setsid" = xyes; then : + $as_echo "#define HAS_SETSID 1" >>confdefs.h + +fi + ;; +esac + +## putenv + +ac_fn_c_check_func "$LINENO" "putenv" "ac_cv_func_putenv" +if test "x$ac_cv_func_putenv" = xyes; then : + $as_echo "#define HAS_PUTENV 1" >>confdefs.h + +fi + + +## newlocale() and +# Note: the detection fails on msvc so we hardcode the result +# (should be debugged later) +case $host in #( + *-pc-windows) : + $as_echo "#define HAS_LOCALE_H 1" >>confdefs.h + ;; #( + *) : + ac_fn_c_check_header_mongrel "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default" +if test "x$ac_cv_header_locale_h" = xyes; then : + ac_fn_c_check_func "$LINENO" "newlocale" "ac_cv_func_newlocale" +if test "x$ac_cv_func_newlocale" = xyes; then : + ac_fn_c_check_func "$LINENO" "freelocale" "ac_cv_func_freelocale" +if test "x$ac_cv_func_freelocale" = xyes; then : + ac_fn_c_check_func "$LINENO" "uselocale" "ac_cv_func_uselocale" +if test "x$ac_cv_func_uselocale" = xyes; then : + $as_echo "#define HAS_LOCALE_H 1" >>confdefs.h + +fi + +fi + +fi + +fi + + ;; +esac + +ac_fn_c_check_header_mongrel "$LINENO" "xlocale.h" "ac_cv_header_xlocale_h" "$ac_includes_default" +if test "x$ac_cv_header_xlocale_h" = xyes; then : + ac_fn_c_check_func "$LINENO" "newlocale" "ac_cv_func_newlocale" +if test "x$ac_cv_func_newlocale" = xyes; then : + ac_fn_c_check_func "$LINENO" "freelocale" "ac_cv_func_freelocale" +if test "x$ac_cv_func_freelocale" = xyes; then : + ac_fn_c_check_func "$LINENO" "uselocale" "ac_cv_func_uselocale" +if test "x$ac_cv_func_uselocale" = xyes; then : + $as_echo "#define HAS_XLOCALE_H 1" >>confdefs.h + +fi + +fi + +fi + +fi + + + +## strtod_l +# Note: not detected on MSVC so hardcoding the result +# (should be debugged later) +case $host in #( + *-pc-windows) : + $as_echo "#define HAS_STRTOD_L 1" >>confdefs.h + ;; #( + *) : + ac_fn_c_check_func "$LINENO" "strtod_l" "ac_cv_func_strtod_l" +if test "x$ac_cv_func_strtod_l" = xyes; then : + $as_echo "#define HAS_STRTOD_L 1" >>confdefs.h + +fi + ;; +esac + +## shared library support +if $shared_libraries_supported; then : + case $host in #( + *-*-mingw32|*-pc-windows) : + supports_shared_libraries=$shared_libraries_supported; DLLIBS="" ;; #( + *) : + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + supports_shared_libraries=true DLLIBS="" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + supports_shared_libraries=true DLLIBS="-ldl $DLLIBS" +else + supports_shared_libraries=false +fi + +fi + ;; +esac +else + supports_shared_libraries=false +fi + +if $supports_shared_libraries; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: Dynamic loading of shared libraries is supported." >&5 +$as_echo "$as_me: Dynamic loading of shared libraries is supported." >&6;} + $as_echo "#define SUPPORT_DYNAMIC_LINKING 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: Dynamic loading of shared libraries is not supported." >&5 +$as_echo "$as_me: Dynamic loading of shared libraries is not supported." >&6;} +fi + +## mmap + +ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_mman_h" = xyes; then : + ac_fn_c_check_func "$LINENO" "mmap" "ac_cv_func_mmap" +if test "x$ac_cv_func_mmap" = xyes; then : + ac_fn_c_check_func "$LINENO" "munmap" "ac_cv_func_munmap" +if test "x$ac_cv_func_munmap" = xyes; then : + $as_echo "#define HAS_MMAP 1" >>confdefs.h + +fi + +fi + +fi + + + +## pwrite + +ac_fn_c_check_func "$LINENO" "pwrite" "ac_cv_func_pwrite" +if test "x$ac_cv_func_pwrite" = xyes; then : + $as_echo "#define HAS_PWRITE 1" >>confdefs.h + +fi + + +## -fdebug-prefix-map support by the C compiler +case $CC,$host in #( + *,*-*-mingw32) : + cc_has_debug_prefix_map=false ;; #( + *,*-pc-windows) : + cc_has_debug_prefix_map=false ;; #( + xlc*,powerpc-ibm-aix*) : + cc_has_debug_prefix_map=false ;; #( + *) : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler supports -fdebug-prefix-map" >&5 +$as_echo_n "checking whether the C compiler supports -fdebug-prefix-map... " >&6; } + saved_CFLAGS="$CFLAGS" + CFLAGS="-fdebug-prefix-map=old=new $CFLAGS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main() { return 0; } +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cc_has_debug_prefix_map=true + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + cc_has_debug_prefix_map=false + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$saved_CFLAGS" + ;; +esac + +## Does stat support nanosecond precision + +ac_fn_c_check_member "$LINENO" "struct stat" "st_atim.tv_nsec" "ac_cv_member_struct_stat_st_atim_tv_nsec" " + $ac_includes_default + #include + +" +if test "x$ac_cv_member_struct_stat_st_atim_tv_nsec" = xyes; then : + stat_has_ns_precision=true + $as_echo "#define HAS_NANOSECOND_STAT 1" >>confdefs.h + +fi + + + +if ! $stat_has_ns_precision; then : + ac_fn_c_check_member "$LINENO" "struct stat" "st_atimespec.tv_nsec" "ac_cv_member_struct_stat_st_atimespec_tv_nsec" " + $ac_includes_default + #include + +" +if test "x$ac_cv_member_struct_stat_st_atimespec_tv_nsec" = xyes; then : + stat_has_ns_precision=true + $as_echo "#define HAS_NANOSECOND_STAT 2" >>confdefs.h + +fi + +fi + +if ! $stat_has_ns_precision; then : + ac_fn_c_check_member "$LINENO" "struct stat" "st_atimensec" "ac_cv_member_struct_stat_st_atimensec" " + $ac_includes_default + #include + +" +if test "x$ac_cv_member_struct_stat_st_atimensec" = xyes; then : + stat_has_ns_precision=true + $as_echo "#define HAS_NANOSECOND_STAT 3" >>confdefs.h + +fi + +fi + +if $stat_has_ns_precision; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: stat supports nanosecond precision" >&5 +$as_echo "$as_me: stat supports nanosecond precision" >&6;} +else + { $as_echo "$as_me:${as_lineno-$LINENO}: stat does not support nanosecond precision" >&5 +$as_echo "$as_me: stat does not support nanosecond precision" >&6;} +fi + +# Number of arguments of gethostbyname_r + + + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how many arguments gethostbyname_r() takes" >&5 +$as_echo_n "checking how many arguments gethostbyname_r() takes... " >&6; } + + if ${ac_cv_func_which_gethostbyname_r+:} false; then : + $as_echo_n "(cached) " >&6 +else + + +################################################################ + +ac_cv_func_which_gethostbyname_r=unknown + +# +# ONE ARGUMENT (sanity check) +# + +# This should fail, as there is no variant of gethostbyname_r() that takes +# a single argument. If it actually compiles, then we can assume that +# netdb.h is not declaring the function, and the compiler is thereby +# assuming an implicit prototype. In which case, we're out of luck. +# +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + char *name = "www.gnu.org"; + (void)gethostbyname_r(name) /* ; */ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_which_gethostbyname_r=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +# +# SIX ARGUMENTS +# (e.g. Linux) +# + +if test "$ac_cv_func_which_gethostbyname_r" = "unknown"; then + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + char *name = "www.gnu.org"; + struct hostent ret, *retp; + char buf[1024]; + int buflen = 1024; + int my_h_errno; + (void)gethostbyname_r(name, &ret, buf, buflen, &retp, &my_h_errno) /* ; */ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_which_gethostbyname_r=six +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi + +# +# FIVE ARGUMENTS +# (e.g. Solaris) +# + +if test "$ac_cv_func_which_gethostbyname_r" = "unknown"; then + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + char *name = "www.gnu.org"; + struct hostent ret; + char buf[1024]; + int buflen = 1024; + int my_h_errno; + (void)gethostbyname_r(name, &ret, buf, buflen, &my_h_errno) /* ; */ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_which_gethostbyname_r=five +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi + +# +# THREE ARGUMENTS +# (e.g. AIX, HP-UX, Tru64) +# + +if test "$ac_cv_func_which_gethostbyname_r" = "unknown"; then + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + char *name = "www.gnu.org"; + struct hostent ret; + struct hostent_data data; + (void)gethostbyname_r(name, &ret, &data) /* ; */ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_which_gethostbyname_r=three +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi + +################################################################ + + +fi + +case "$ac_cv_func_which_gethostbyname_r" in + three|five|six) + +$as_echo "#define HAVE_GETHOSTBYNAME_R 1" >>confdefs.h + + ;; +esac + +case "$ac_cv_func_which_gethostbyname_r" in + three) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: three" >&5 +$as_echo "three" >&6; } + +$as_echo "#define HAVE_FUNC_GETHOSTBYNAME_R_3 1" >>confdefs.h + + ;; + + five) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: five" >&5 +$as_echo "five" >&6; } + +$as_echo "#define HAVE_FUNC_GETHOSTBYNAME_R_5 1" >>confdefs.h + + ;; + + six) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: six" >&5 +$as_echo "six" >&6; } + +$as_echo "#define HAVE_FUNC_GETHOSTBYNAME_R_6 1" >>confdefs.h + + ;; + + no) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: cannot find function declaration in netdb.h" >&5 +$as_echo "cannot find function declaration in netdb.h" >&6; } + ;; + + unknown) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: can't tell" >&5 +$as_echo "can't tell" >&6; } + ;; + + *) + as_fn_error $? "internal error" "$LINENO" 5 + ;; +esac + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + +case $ac_cv_func_which_gethostbyname_r in #( + six) : + $as_echo "#define HAS_GETHOSTBYNAME_R 6" >>confdefs.h + ;; #( + five) : + $as_echo "#define HAS_GETHOSTBYNAME_R 5" >>confdefs.h + ;; #( + three) : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: OCaml does not support this variant" >&5 +$as_echo "$as_me: WARNING: OCaml does not support this variant" >&2;} ;; #( + *) : + ;; +esac + +# Number of arguments of gethostbyaddr_r + + + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how many arguments gethostbyaddr_r() takes" >&5 +$as_echo_n "checking how many arguments gethostbyaddr_r() takes... " >&6; } + + if ${ac_cv_func_which_gethostbyaddr_r+:} false; then : + $as_echo_n "(cached) " >&6 +else + + +################################################################ + +ac_cv_func_which_gethostbyaddr_r=unknown + +# +# ONE ARGUMENT (sanity check) +# + +# This should fail, as there is no variant of gethostbyaddr_r() that takes +# a single argument. If it actually compiles, then we can assume that +# netdb.h is not declaring the function, and the compiler is thereby +# assuming an implicit prototype. In which case, we're out of luck. +# +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + char *addr = "192.168.1.1"; + (void)gethostbyaddr_r(addr) /* ; */ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_which_gethostbyaddr_r=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +# +# EIGHT ARGUMENTS +# (e.g. Linux) +# + +if test "$ac_cv_func_which_gethostbyaddr_r" = "unknown"; then + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + char *addr = "192.168.1.1"; + struct hostent ret, *retp; + char buf[1024]; + int buflen = 1024; + int my_h_errno; + (void)gethostbyaddr_r( + addr, 10, 10, retp, buf, buflen, &retp, &my_h_errno) /* ; */ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_which_gethostbyaddr_r=eight +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi + +# +# SEVEN ARGUMENTS +# (e.g. Solaris) +# + +if test "$ac_cv_func_which_gethostbyaddr_r" = "unknown"; then + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + char *addr = "192.168.1.1"; + struct hostent ret; + char buf[1024]; + int buflen = 1024; + int my_h_errno; + (void)gethostbyaddr_r( + addr, 10, 10, buf, buflen, &my_h_errno, 0) /* ; */ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_which_gethostbyaddr_r=seven +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi + +################################################################ + + +fi + +case "$ac_cv_func_which_gethostbyaddr_r" in + seven|eight) + +$as_echo "#define HAVE_GETHOSTBYADDR_R 1" >>confdefs.h + + ;; +esac + +case "$ac_cv_func_which_gethostbyaddr_r" in + eight) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: eight" >&5 +$as_echo "eight" >&6; } + +$as_echo "#define HAVE_FUNC_GETHOSTBYADDR_R_8 1" >>confdefs.h + + ;; + + seven) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: seven" >&5 +$as_echo "seven" >&6; } + +$as_echo "#define HAVE_FUNC_GETHOSTBYADDR_R_7 1" >>confdefs.h + + ;; + + no) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: cannot find function declaration in netdb.h" >&5 +$as_echo "cannot find function declaration in netdb.h" >&6; } + ;; + + unknown) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: can't tell" >&5 +$as_echo "can't tell" >&6; } + ;; + + *) + as_fn_error $? "internal error" "$LINENO" 5 + ;; +esac + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + +case $ac_cv_func_which_gethostbyaddr_r in #( + eight) : + $as_echo "#define HAS_GETHOSTBYADDR_R 8" >>confdefs.h + ;; #( + seven) : + $as_echo "#define HAS_GETHOSTBYADDR_R 7" >>confdefs.h + ;; #( + *) : + ;; +esac + +## mkstemp + +ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp" +if test "x$ac_cv_func_mkstemp" = xyes; then : + $as_echo "#define HAS_MKSTEMP 1" >>confdefs.h + +fi + + +## nice + +ac_fn_c_check_func "$LINENO" "nice" "ac_cv_func_nice" +if test "x$ac_cv_func_nice" = xyes; then : + $as_echo "#define HAS_NICE 1" >>confdefs.h + +fi + + +## dup3 + +ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3" +if test "x$ac_cv_func_dup3" = xyes; then : + $as_echo "#define HAS_DUP3 1" >>confdefs.h + +fi + + +## pipe2 + +ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2" +if test "x$ac_cv_func_pipe2" = xyes; then : + $as_echo "#define HAS_PIPE2 1" >>confdefs.h + +fi + + +## accept4 + +ac_fn_c_check_func "$LINENO" "accept4" "ac_cv_func_accept4" +if test "x$ac_cv_func_accept4" = xyes; then : + $as_echo "#define HAS_ACCEPT4 1" >>confdefs.h + +fi + + +## getauxval + +ac_fn_c_check_func "$LINENO" "getauxval" "ac_cv_func_getauxval" +if test "x$ac_cv_func_getauxval" = xyes; then : + $as_echo "#define HAS_GETAUXVAL 1" >>confdefs.h + +fi + + +## execvpe + +ac_fn_c_check_func "$LINENO" "execvpe" "ac_cv_func_execvpe" +if test "x$ac_cv_func_execvpe" = xyes; then : + $as_echo "#define HAS_EXECVPE 1" >>confdefs.h + +fi + + +## Determine whether the debugger should/can be built + +case $enable_debugger in #( + no) : + with_debugger="" + { $as_echo "$as_me:${as_lineno-$LINENO}: replay debugger disabled" >&5 +$as_echo "$as_me: replay debugger disabled" >&6;} ;; #( + *) : + if $sockets; then : + with_debugger="ocamldebugger" + { $as_echo "$as_me:${as_lineno-$LINENO}: replay debugger supported" >&5 +$as_echo "$as_me: replay debugger supported" >&6;} +else + with_debugger="" + { $as_echo "$as_me:${as_lineno-$LINENO}: replay debugger not supported" >&5 +$as_echo "$as_me: replay debugger not supported" >&6;} +fi + ;; +esac + +## Should the runtime with debugging support be built +case $enable_debug_runtime in #( + no) : + debug_runtime=false ;; #( + *) : + debug_runtime=true ;; +esac + +## Determine if system stack overflows can be detected + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stack overflows can be detected" >&5 +$as_echo_n "checking whether stack overflows can be detected... " >&6; } + +case $arch,$system in #( + i386,linux_elf|amd64,linux|amd64,macosx|i386,macosx \ + |amd64,openbsd|i386,bsd_elf) : + $as_echo "#define HAS_STACK_OVERFLOW_DETECTION 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } ;; #( + *) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } ;; +esac + +## Determine if the POSIX threads library is supported + +if test x"$enable_systhreads" = "xno"; then : + systhread_support=false + { $as_echo "$as_me:${as_lineno-$LINENO}: the Win32/POSIX threads library is disabled" >&5 +$as_echo "$as_me: the Win32/POSIX threads library is disabled" >&6;} +else + case $host in #( + *-*-mingw32|*-pc-windows) : + systhread_support=true + otherlibraries="$otherlibraries systhreads" + { $as_echo "$as_me:${as_lineno-$LINENO}: the Win32 threads library is supported" >&5 +$as_echo "$as_me: the Win32 threads library is supported" >&6;} ;; #( + *) : + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on Tru64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + if test "x$PTHREAD_CC" != "x"; then : + CC="$PTHREAD_CC" +fi + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS" >&5 +$as_echo_n "checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_join (); +int +main () +{ +return pthread_join (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_ZOS_MISSING" >/dev/null 2>&1; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&5 +$as_echo "$as_me: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&2;} +fi +rm -f conftest* + + ;; + + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ;; +esac + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +if test "x$GCC" = "xyes"; then : + ax_pthread_flags="-pthread -pthreads $ax_pthread_flags" +fi + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +if test "x$ax_pthread_check_macro" = "x--"; then : + ax_pthread_check_cond=0 +else + ax_pthread_check_cond="!defined($ax_pthread_check_macro)" +fi + +# Are we compiling with Clang? + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC is Clang" >&5 +$as_echo_n "checking whether $CC is Clang... " >&6; } +if ${ax_cv_PTHREAD_CLANG+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_CC_IS_CLANG" >/dev/null 2>&1; then : + ax_cv_PTHREAD_CLANG=yes +fi +rm -f conftest* + + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG" >&6; } +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread" >&5 +$as_echo_n "checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread... " >&6; } +if ${ax_cv_PTHREAD_CLANG_NO_WARN_FLAG+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + if test "x$ax_pthread_try" = "xunknown"; then : + break +fi + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_link="$ax_pthread_2step_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + if test "x$ax_pthread_try" = "x"; then : + ax_pthread_try=no +fi + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&6; } + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in + none) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 +$as_echo_n "checking whether pthreads work without any flags... " >&6; } + ;; + + -mt,pthread) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with -mt -lpthread" >&5 +$as_echo_n "checking whether pthreads work with -mt -lpthread... " >&6; } + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + + -*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $ax_pthread_try_flag" >&5 +$as_echo_n "checking whether pthreads work with $ax_pthread_try_flag... " >&6; } + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + # Extract the first word of "pthread-config", so it can be a program name with args. +set dummy pthread-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ax_pthread_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ax_pthread_config"; then + ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ax_pthread_config="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no" +fi +fi +ax_pthread_config=$ac_cv_prog_ax_pthread_config +if test -n "$ax_pthread_config"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5 +$as_echo "$ax_pthread_config" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$ax_pthread_config" = "xno"; then : + continue +fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$ax_pthread_try_flag" >&5 +$as_echo_n "checking for the pthreads library -l$ax_pthread_try_flag... " >&6; } + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; } +int +main () +{ +pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xyes"; then : + break +fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 +$as_echo_n "checking for joinable pthread attribute... " >&6; } +if ${ax_cv_PTHREAD_JOINABLE_ATTR+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int attr = $ax_pthread_attr; return attr /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_JOINABLE_ATTR" >&5 +$as_echo "$ax_cv_PTHREAD_JOINABLE_ATTR" >&6; } + if test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"; then : + +cat >>confdefs.h <<_ACEOF +#define PTHREAD_CREATE_JOINABLE $ax_cv_PTHREAD_JOINABLE_ATTR +_ACEOF + + ax_pthread_joinable_attr_defined=yes + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether more special flags are required for pthreads" >&5 +$as_echo_n "checking whether more special flags are required for pthreads... " >&6; } +if ${ax_cv_PTHREAD_SPECIAL_FLAGS+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_SPECIAL_FLAGS" >&5 +$as_echo "$ax_cv_PTHREAD_SPECIAL_FLAGS" >&6; } + if test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"; then : + PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5 +$as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; } +if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int i = PTHREAD_PRIO_INHERIT; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_PTHREAD_PRIO_INHERIT=yes +else + ax_cv_PTHREAD_PRIO_INHERIT=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5 +$as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; } + if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"; then : + +$as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h + + ax_pthread_prio_inherit_defined=yes + +fi + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + case "x/$CC" in #( + x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) : + #handle absolute path differently from PATH based program lookup + case "x$CC" in #( + x/*) : + if as_fn_executable_p ${CC}_r; then : + PTHREAD_CC="${CC}_r" +fi ;; #( + *) : + for ac_prog in ${CC}_r +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PTHREAD_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PTHREAD_CC"; then + ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PTHREAD_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PTHREAD_CC=$ac_cv_prog_PTHREAD_CC +if test -n "$PTHREAD_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 +$as_echo "$PTHREAD_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PTHREAD_CC" && break +done +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + ;; +esac ;; #( + *) : + ;; +esac + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + + + + + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test "x$ax_pthread_ok" = "xyes"; then + systhread_support=true + otherlibraries="$otherlibraries systhreads" + case $host in #( + *-*-solaris*) : + pthread_link="-lpthread -lposix4" ;; #( + *-*-haiku*) : + pthread_link="" ;; #( + *) : + pthread_link="-lpthread" ;; +esac + common_cppflags="$common_cppflags -D_REENTRANT" + { $as_echo "$as_me:${as_lineno-$LINENO}: the POSIX threads library is supported" >&5 +$as_echo "$as_me: the POSIX threads library is supported" >&6;} + saved_CFLAGS="$CFLAGS" + saved_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$LIBS $pthread_link" + ac_fn_c_check_func "$LINENO" "sigwait" "ac_cv_func_sigwait" +if test "x$ac_cv_func_sigwait" = xyes; then : + $as_echo "#define HAS_SIGWAIT 1" >>confdefs.h + +fi + + LIBS="$saved_LIBS" + CFLAGS="$saved_CFLAGS" + : +else + ax_pthread_ok=no + if test x"$enable_systhreads" = "xyes"; then : + as_fn_error $? "the POSIX thread library is not available" "$LINENO" 5 +else + systhread_support=false + { $as_echo "$as_me:${as_lineno-$LINENO}: the POSIX threads library is not supported" >&5 +$as_echo "$as_me: the POSIX threads library is not supported" >&6;} +fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + ;; +esac +fi + +## Determine if the bytecode thread library is supported + +if test x"$enable_vmthreads" = "xno"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: the bytecode threads library is disabled" >&5 +$as_echo "$as_me: the bytecode threads library is disabled" >&6;} +else + if $select && $setitimer && $gettimeofday && $wait; then : + otherlibraries="$otherlibraries threads" + { $as_echo "$as_me:${as_lineno-$LINENO}: the bytecode threads library is supported" >&5 +$as_echo "$as_me: the bytecode threads library is supported" >&6;} +else + if test x"$enable_vmthreads" = "xyes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: the bytecode threads library is not available" >&5 +$as_echo "$as_me: the bytecode threads library is not available" >&6;} +else + { $as_echo "$as_me:${as_lineno-$LINENO}: the bytecode threads library is not supported" >&5 +$as_echo "$as_me: the bytecode threads library is not supported" >&6;} +fi +fi +fi + +## XWindow + +if test x"$enable_graph_lib" = "xno" ; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: the graph library has been disabled" >&5 +$as_echo "$as_me: the graph library has been disabled" >&6;} +else + case $host in #( + *-*-mingw32|*-pc-windows) : + otherlibraries="$otherlibraries win32graph" ;; #( + *) : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5 +$as_echo_n "checking for X... " >&6; } + + +# Check whether --with-x was given. +if test "${with_x+set}" = set; then : + withval=$with_x; +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + case $x_includes,$x_libraries in #( + *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( + *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then : + $as_echo_n "(cached) " >&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no ac_x_libraries=no +rm -f -r conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + cat >Imakefile <<'_ACEOF' +incroot: + @echo incroot='${INCROOT}' +usrlibdir: + @echo usrlibdir='${USRLIBDIR}' +libdir: + @echo libdir='${LIBDIR}' +_ACEOF + if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. + for ac_var in incroot usrlibdir libdir; do + eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" + done + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl dylib la dll; do + if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && + test -f "$ac_im_libdir/libX11.$ac_extension"; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ac_x_includes= ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /usr/lib64 | /lib | /lib64) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -f -r conftest.dir +fi + +# Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R7/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R7 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R7/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R7 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Xlib.h. + # First, try using that file with no special directory specified. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # We can compile using X headers with no special include directory. +ac_x_includes= +else + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Xlib.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lX11 $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +XrmInitialize () + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + LIBS=$ac_save_LIBS +for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl dylib la dll; do + if test -r "$ac_dir/libX11.$ac_extension"; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +case $ac_x_includes,$ac_x_libraries in #( + no,* | *,no | *\'*) + # Didn't find X, or a directory has "'" in its name. + ac_cv_have_x="have_x=no";; #( + *) + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$ac_x_includes'\ + ac_x_libraries='$ac_x_libraries'" +esac +fi +;; #( + *) have_x=yes;; + esac + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5 +$as_echo "$have_x" >&6; } + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$x_includes'\ + ac_x_libraries='$x_libraries'" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5 +$as_echo "libraries $x_libraries, headers $x_includes" >&6; } +fi + + if test -z "$no_x"; then : + if test -z $x_libraries; then : + x_libraries="-lX11" +else + x_libraries="-L$x_libraries -lX11" +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: X has been found" >&5 +$as_echo "$as_me: X has been found" >&6;} + otherlibraries="$otherlibraries graph" + { $as_echo "$as_me:${as_lineno-$LINENO}: the graph library will be built" >&5 +$as_echo "$as_me: the graph library will be built" >&6;} +else + { $as_echo "$as_me:${as_lineno-$LINENO}: X has not been found" >&5 +$as_echo "$as_me: X has not been found" >&6;} + if test x"$enable_graph_lib" = "xyes" ; then : + as_fn_error $? "can not build the graph library which was requested" "$LINENO" 5 +else + { $as_echo "$as_me:${as_lineno-$LINENO}: the graph library will not be built" >&5 +$as_echo "$as_me: the graph library will not be built" >&6;} +fi +fi ;; +esac +fi + +## libbfd + +ac_fn_c_check_header_mongrel "$LINENO" "bfd.h" "ac_cv_header_bfd_h" "$ac_includes_default" +if test "x$ac_cv_header_bfd_h" = xyes; then : + libbfd_ling="" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bfd_openr in -lbfd" >&5 +$as_echo_n "checking for bfd_openr in -lbfd... " >&6; } +if ${ac_cv_lib_bfd_bfd_openr+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbfd $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char bfd_openr (); +int +main () +{ +return bfd_openr (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bfd_bfd_openr=yes +else + ac_cv_lib_bfd_bfd_openr=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bfd_bfd_openr" >&5 +$as_echo "$ac_cv_lib_bfd_bfd_openr" >&6; } +if test "x$ac_cv_lib_bfd_bfd_openr" = xyes; then : + libbfd_link="-lbfd" +fi + + if test -z "$libbfd_link"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bfd_openr in -lbfd" >&5 +$as_echo_n "checking for bfd_openr in -lbfd... " >&6; } +if ${ac_cv_lib_bfd_bfd_openr+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbfd -ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char bfd_openr (); +int +main () +{ +return bfd_openr (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bfd_bfd_openr=yes +else + ac_cv_lib_bfd_bfd_openr=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bfd_bfd_openr" >&5 +$as_echo "$ac_cv_lib_bfd_bfd_openr" >&6; } +if test "x$ac_cv_lib_bfd_bfd_openr" = xyes; then : + libbfd_link="-lbfd -ldl" +fi + +fi + if test -z "$libbfd_link"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bfd_openr in -lbfd" >&5 +$as_echo_n "checking for bfd_openr in -lbfd... " >&6; } +if ${ac_cv_lib_bfd_bfd_openr+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbfd -ldl -liberty $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char bfd_openr (); +int +main () +{ +return bfd_openr (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bfd_bfd_openr=yes +else + ac_cv_lib_bfd_bfd_openr=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bfd_bfd_openr" >&5 +$as_echo "$ac_cv_lib_bfd_bfd_openr" >&6; } +if test "x$ac_cv_lib_bfd_bfd_openr" = xyes; then : + libbfd_link="-lbfd -ldl -liberty" +fi + +fi + if test -z "$libbfd_link"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bfd_openr in -lbfd" >&5 +$as_echo_n "checking for bfd_openr in -lbfd... " >&6; } +if ${ac_cv_lib_bfd_bfd_openr+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbfd -ldl -liberty -lz $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char bfd_openr (); +int +main () +{ +return bfd_openr (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bfd_bfd_openr=yes +else + ac_cv_lib_bfd_bfd_openr=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bfd_bfd_openr" >&5 +$as_echo "$ac_cv_lib_bfd_bfd_openr" >&6; } +if test "x$ac_cv_lib_bfd_bfd_openr" = xyes; then : + libbfd_link="-lbfd -ldl -liberty -lz" +fi + +fi + if test -z "$libbfd_link"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bfd_openr in -lbfd" >&5 +$as_echo_n "checking for bfd_openr in -lbfd... " >&6; } +if ${ac_cv_lib_bfd_bfd_openr+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbfd -ldl -liberty -lz -lintl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char bfd_openr (); +int +main () +{ +return bfd_openr (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bfd_bfd_openr=yes +else + ac_cv_lib_bfd_bfd_openr=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bfd_bfd_openr" >&5 +$as_echo "$ac_cv_lib_bfd_bfd_openr" >&6; } +if test "x$ac_cv_lib_bfd_bfd_openr" = xyes; then : + libbfd_link="-lbfd -ldl -liberty -lz -lintl" +fi + +fi + if test -n "$libbfd_link"; then : + $as_echo "#define HAS_LIBBFD 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: BFD library not found, 'objinfo' will be unable to display info on .cmxs files." >&5 +$as_echo "$as_me: BFD library not found, 'objinfo' will be unable to display info on .cmxs files." >&6;} +fi + +fi + + + +## Does the assembler support debug prefix map and CFI directives +as_has_debug_prefix_map=false +asm_cfi_supported=false +if $native_compiler; then : + case $host in #( + *-*-mingw32|*-pc-windows) : + ;; #( + *) : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the assembler supports --debug-prefix-map" >&5 +$as_echo_n "checking whether the assembler supports --debug-prefix-map... " >&6; } + + + saved_CC="$CC" + saved_CFLAGS="$CFLAGS" + saved_CPPFLAGS="$CPPFLAGS" + saved_ac_ext="$ac_ext" + saved_ac_compile="$ac_compile" + # Move the content of confdefs.h to another file so it does not + # get included + mv confdefs.h confdefs.h.bak + touch confdefs.h + + + # Modify C-compiler variables to use the assembler + CC="$AS" + CFLAGS="--debug-prefix-map old=new -o conftest.$ac_objext" + CPPFLAGS="" + ac_ext="S" + ac_compile='$CC $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +camlPervasives__loop_1128: + .file 1 "pervasives.ml" + .loc 1 193 + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + as_has_debug_prefix_map=true + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + ashas_debug_prefix_map=false + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + + # Restore the content of confdefs.h + mv confdefs.h.bak confdefs.h + ac_compile="$saved_ac_compile" + ac_ext="$saved_ac_ext" + CPPFLAGS="$saved_CPPFLAGS" + CFLAGS="$saved_CFLAGS" + CC="$saved_CC" + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the assembler supports CFI directives" >&5 +$as_echo_n "checking whether the assembler supports CFI directives... " >&6; } + + if test x"$enable_cfi" = "xno"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 +$as_echo "disabled" >&6; } +else + + saved_CC="$CC" + saved_CFLAGS="$CFLAGS" + saved_CPPFLAGS="$CPPFLAGS" + saved_ac_ext="$ac_ext" + saved_ac_compile="$ac_compile" + # Move the content of confdefs.h to another file so it does not + # get included + mv confdefs.h confdefs.h.bak + touch confdefs.h + + + # Modify C-compiler variables to use the assembler + CC="$ASPP" + CFLAGS="-o conftest.$ac_objext" + CPPFLAGS="" + ac_ext="S" + ac_compile='$CC $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +camlPervasives__loop_1128: + .file 1 "pervasives.ml" + .loc 1 193 + .cfi_startproc + .cfi_adjust_cfa_offset 8 + .cfi_endproc + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + aspp_ok=true +else + aspp_ok=false +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + if test "$AS" = "$ASPP"; then : + as_ok="$aspp_ok" +else + CC="$AS" + ac_compile='$CC $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +camlPervasives__loop_1128: + .file 1 "pervasives.ml" + .loc 1 193 + .cfi_startproc + .cfi_adjust_cfa_offset 8 + .cfi_endproc + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + as_ok=true +else + as_ok=false +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + + # Restore the content of confdefs.h + mv confdefs.h.bak confdefs.h + ac_compile="$saved_ac_compile" + ac_ext="$saved_ac_ext" + CPPFLAGS="$saved_CPPFLAGS" + CFLAGS="$saved_CFLAGS" + CC="$saved_CC" + + + if $aspp_ok && $as_ok; then : + asm_cfi_supported=true + $as_echo "#define ASM_CFI_SUPPORTED 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + if test x"$enable_cfi" = "xyes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: requested but not available + as_fn_error $? "exiting" "$LINENO" 5" >&5 +$as_echo "requested but not available + as_fn_error $? "exiting" "$LINENO" 5" >&6; } +else + asm_cfi_supported=false + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +fi + +fi ;; +esac +fi + +## Frame pointers + +if test x"$enable_frame_pointers" = "xyes"; then : + case "$host,$CC" in #( + x86_64-*-linux*,gcc*|x86_64-*-linux*,clang*) : + common_cflags="$common_cflags -g -fno-omit-frame-pointer" + frame_pointers=true + $as_echo "#define WITH_FRAME_POINTERS 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: using frame pointers" >&5 +$as_echo "$as_me: using frame pointers" >&6;} ;; #( + *) : + as_fn_error $? "frame pointers not supported on this platform" "$LINENO" 5 + ;; +esac +else + { $as_echo "$as_me:${as_lineno-$LINENO}: not using frame pointers" >&5 +$as_echo "$as_me: not using frame pointers" >&6;} + frame_pointers=false +fi + +## No naked pointers + +if test x"$enable_naked_pointers" = "xno" ; then : + $as_echo "#define NO_NAKED_POINTERS 1" >>confdefs.h + +fi + +## Check for mmap support for huge pages and contiguous heap + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mmap supports huge pages" >&5 +$as_echo_n "checking whether mmap supports huge pages... " >&6; } + if test "$cross_compiling" = yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no assumed" >&5 +$as_echo "no assumed" >&6; } +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#include + +#define huge_page_size (4 * 1024 * 1024) + +/* Test for the possible availability of huge pages. Answer yes + if the OS knows about huge pages, even if they are not available + on the build machine at configure time, because (on Linux) huge + pages can be activated and deactivated easily while the system + is running. +*/ + +int main (int argc, char *argv[]){ + void *block; + char *p; + int i, res; + block = mmap (NULL, huge_page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, + -1, 0); + if (block == MAP_FAILED){ + block = mmap (NULL, huge_page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + } + if (block == MAP_FAILED){ + perror ("mmap"); + return 3; + } + /*printf ("block = %p\n", block);*/ + p = (char *) block; + for (i = 0; i < huge_page_size; i += 4096){ + p[i] = (char) i; + } + return 0; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + $as_echo "#define HAS_HUGE_PAGES 1" >>confdefs.h + + cat >>confdefs.h <<_ACEOF +#define HUGE_PAGE_SIZE (4 * 1024 * 1024) +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + + +# Spacetime profiling, including libunwind detection + +# The number of bits used for profiling information is configurable here. +# The more bits used for profiling, the smaller will be Max_wosize. +# Note that PROFINFO_WIDTH must still be defined even if not configuring +# for Spacetime (see comment in runtime/caml/mlvalues.h on [Profinfo_hd]). +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build spacetime" >&5 +$as_echo_n "checking whether to build spacetime... " >&6; } +if test x"$enable_spacetime" != "xyes" ; then : + spacetime=false + call_counts=true # as in original script but should probably be false + libunwind_available=false + libunwind_include_flags= + libunwind_link_flags= + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + case $arch in #( + amd64) : + spacetime_supported=true ;; #( + *) : + spacetime_supported=false ;; +esac + if $spacetime_supported; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + spacetime=true + profinfo=true + profinfo_width=26 + $as_echo "#define WITH_SPACETIME 1" >>confdefs.h + + if test x"$enable_call_counts" != "xno"; then : + call_counts=true + $as_echo "#define ENABLE_CALL_COUNTS 1" >>confdefs.h + +else + call_counts=false +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use libunwind" >&5 +$as_echo_n "checking whether to use libunwind... " >&6; } + if test x"$with_libunwind" = "xno"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 +$as_echo "disabled" >&6; } +else + if test x"$with_libunwind" = "x"; then : + libunwind_requested=false + { $as_echo "$as_me:${as_lineno-$LINENO}: result: if available" >&5 +$as_echo "if available" >&6; } +else + libunwind_requested=true + { $as_echo "$as_me:${as_lineno-$LINENO}: result: requested" >&5 +$as_echo "requested" >&6; } + if test x"$with_libunwind" != "xyes"; then : + if test x"$LIBUNWIND_INCLUDE_DIR" = "x"; then : + LIBUNWIND_INCLUDE_DIR="$with_libunwind/include" +fi + if test x"$LIBUNWIND_LIB_DIR" = "x"; then : + LIBUNWIND_LIB_DIR="$with_libunwind/lib" +fi + +fi + +fi + if test "$system" = "macosx"; then : + if test x"$LIBUNWIND_INCLUDE_DIR" != x -o \ + x"$LIBUNWIND_LIB_DIR" != x; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: On MacOSX, specifying paths for libunwind headers or libraries is strongly discouraged. It is recommended to rely on the defaults provided by the configure script" >&5 +$as_echo "$as_me: WARNING: On MacOSX, specifying paths for libunwind headers or libraries is strongly discouraged. It is recommended to rely on the defaults provided by the configure script" >&2;} +fi +fi + + if test x"$LIBUNWIND_INCLUDE_DIR" != x; then : + libunwind_include_flags="-I$LIBUNWIND_INCLUDE_DIR" +else + libunwind_include_flags="" +fi + + case "$system" in #( + "macosx") : + libunwind_link_flags="-framework System" ;; #( + *) : + libunwind_link_flags="-lunwind -lunwind-x86_64" ;; +esac + + if test x"$LIBUNWIND_LIB_DIR" != x; then : + libunwind_link_flags="-L$LIBUNWIND_LIB_DIR $libunwind_link_flags" +fi + + + SAVED_CFLAGS="$CFLAGS" + SAVED_LDFLAGS="$LDFLAGS" + CFLAGS="$CFLAGS $libunwind_include_flags" + LDFLAGS="$LDFLAGS $libunwind_link_flags" + ac_fn_c_check_header_mongrel "$LINENO" "libunwind.h" "ac_cv_header_libunwind_h" "$ac_includes_default" +if test "x$ac_cv_header_libunwind_h" = xyes; then : + $as_echo "#define HAS_LIBUNWIND 1" >>confdefs.h + + libunwind_available=true +else + libunwind_available=false +fi + + + LDFLAGS="$SAVED_LDFLAGS" + CFLAGS="$SAVED_CFLAGS" + + + if $libunwind_requested && ! $libunwind_available; then : + as_fn_error $? "libunwind was requested but can not be found" "$LINENO" 5 +fi + + # We need unwinding information at runtime, but since we use + # -no_compact_unwind, we also need -keep_dwarf_unwind otherwise + # the OS X linker will chuck away the DWARF-like (.eh_frame) + # information. (Older versions of OS X don't provide this.) + + if $libunwind_available && test x"$system" = "xmacosx"; then : + extra_flags="-Wl,-keep_dwarf_unwind" + mkexe="$mkexe $extra_flags" + mksharedlib="$mksharedlib $extra_flags" +fi +fi + +else + if test x"$enable_spacetime" = "xyes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: requested but not supported" >&5 +$as_echo "requested but not supported" >&6; } + as_fn_error $? "exiting" "$LINENO" 5 +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +fi + +fi + +cat >>confdefs.h <<_ACEOF +#define PROFINFO_WIDTH $profinfo_width +_ACEOF + +if $profinfo; then : + $as_echo "#define WITH_PROFINFO 1" >>confdefs.h + +fi + +if test x"$enable_installing_bytecode_programs" = "xno"; then : + install_bytecode_programs=false +else + install_bytecode_programs=true +fi + +if test x"$enable_installing_source_artifacts" = "xno"; then : + install_source_artifacts=false +else + install_source_artifacts=true +fi + +if test x"$enable_ocamldoc" = "xno"; then : + ocamldoc="" +else + ocamldoc=ocamldoc +fi + +if test x"$enable_flambda" = "xyes"; then : + flambda=true + if test x"$enable_flambda_invariants" = "xyes"; then : + flambda_invariants=true +else + flambda_invariants=false +fi +else + flambda=false + flambda_invariants=false +fi + +if test x"$enable_flat_float_array" = "xno"; then : + flat_float_array=false +else + $as_echo "#define FLAT_FLOAT_ARRAY 1" >>confdefs.h + + flat_float_array=true +fi + +if test x"$with_afl" = "xyes"; then : + afl=true +else + afl=false +fi + +if test x"$enable_force_safe_string" = "xyes"; then : + $as_echo "#define CAML_SAFE_STRING 1" >>confdefs.h + + force_safe_string=true +else + force_safe_string=false +fi + +if test x"$DEFAULT_STRING" = "xunsafe"; then : + default_safe_string=false +else + default_safe_string=true +fi + +oc_cflags="$common_cflags $internal_cflags" +oc_cppflags="$common_cppflags $internal_cppflags" +ocamlc_cflags="$common_cflags $sharedlib_cflags" +ocamlc_cppflags="$common_cppflags" +ocamlopt_cflags="$common_cflags" +ocamlopt_cppflags="$common_cppflags" +cclibs="$cclibs $mathlib" + +case $host in #( + *-*-mingw32) : + bytecclibs="-lws2_32 -lversion" + nativecclibs="-lws2_32 -lversion" ;; #( + *-pc-windows) : + bytecclibs="advapi32.lib ws2_32.lib version.lib" + nativecclibs="advapi32.lib ws2_32.lib version.lib" ;; #( + *) : + bytecclibs="$cclibs $DLLIBS $pthread_link $instrumented_runtime_libs" + nativecclibs="$cclibs $DLLIBS" ;; +esac + +if test x"$libdir" = x'${exec_prefix}/lib'; then : + libdir="$libdir"/ocaml +fi + +if test x"$mandir" = x'${datarootdir}/man'; then : + mandir='${prefix}/man' +fi + +case $host in #( + *-*-mingw32|*-pc-windows) : + max_testsuite_dir_retries=1 + case $WINDOWS_UNICODE_MODE in #( + ansi) : + windows_unicode=0 ;; #( + compatible|"") : + windows_unicode=1 ;; #( + *) : + as_fn_error $? "unexpected windows unicode mode" "$LINENO" 5 ;; +esac ;; #( + *) : + max_testsuite_dir_retries=0 + windows_unicode=0 ;; +esac + +# Define flexlink chain and flags correctly for the different Windows ports +case $host in #( + i686-w64-mingw32) : + flexdll_chain='mingw' + flexlink_flags="-chain $flexdll_chain -stack 16777216" ;; #( + x86_64-w64-mingw32) : + flexdll_chain='mingw64' + flexlink_flags="-chain $flexdll_chain -stack 33554432" ;; #( + i686-pc-windows) : + flexdll_chain='msvc' + flexlink_flags="-merge-manifest -stack 16777216" ;; #( + x86_64-pc-windows) : + flexdll_chain='msvc64' + flexlink_flags="-x64 -merge-manifest -stack 33554432" ;; #( + *) : + ;; +esac + +# Define default prefix correctly for the different Windows ports +if test x"$prefix" = "xNONE"; then : + case $host in #( + i686-w64-mingw32) : + prefix='C:/ocamlmgw' ;; #( + x86_64-w64-mingw32) : + prefix='C:/ocamlmgw64' ;; #( + i686-pc-windows) : + prefix='C:/ocamlms' ;; #( + x86_64-pc-windows) : + prefix='C:/ocamlms64' ;; #( + *) : + ;; +esac +fi + +# Define a few macros that were defined in config/m-nt.h +# but whose value is not guessed properly by configure +# (all this should be understood and fixed) +case $host in #( + *-*-mingw32|*-pc-windows) : + $as_echo "#define HAS_BROKEN_PRINTF 1" >>confdefs.h + + $as_echo "#define HAS_STRERROR 1" >>confdefs.h + + $as_echo "#define HAS_IPV6 1" >>confdefs.h + + $as_echo "#define HAS_NICE 1" >>confdefs.h + ;; #( + *) : + ;; +esac + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by OCaml $as_me 4.08.0, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to . +OCaml home page: ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +OCaml config.status 4.08.0 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ +nm_file_list_spec \ +lt_cv_truncate_bin \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' + +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "Makefile.common") CONFIG_FILES="$CONFIG_FILES Makefile.common" ;; + "Makefile.config") CONFIG_FILES="$CONFIG_FILES Makefile.config" ;; + "runtime/caml/m.h") CONFIG_HEADERS="$CONFIG_HEADERS runtime/caml/m.h" ;; + "runtime/caml/s.h") CONFIG_HEADERS="$CONFIG_HEADERS runtime/caml/s.h" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "libtool":C) + + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +# The names of the tagged configurations supported by this script. +available_tags='' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot=$lt_sysroot + +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain=$ac_aux_dir/ltmain.sh + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000..5bb06116 --- /dev/null +++ b/configure.ac @@ -0,0 +1,1813 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Sebastien Hinderer, projet Gallium, INRIA Paris * +#* * +#* Copyright 2018 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +# Process this file with autoconf to produce a configure script. + +AC_INIT([OCaml], + m4_esyscmd([head -n1 VERSION | tr -d '\r\n']), + [caml-list@inria.fr], + [ocaml], + [http://www.ocaml.org]) + +AC_MSG_NOTICE([Configuring OCaml version AC_PACKAGE_VERSION]) + +# Configuration variables + +## Command-line arguments passed to configure +CONFIGURE_ARGS="$*" + +# Command-line tools section of the Unix manual +programs_man_section=1 + +# Library section of the Unix manual +libraries_man_section=3 + +# Command to build executalbes +mkexe="\$(CC) \$(OC_CFLAGS) \$(OC_CPPFLAGS) \$(OC_LDFLAGS)" + +# Flags for building executable files with debugging symbols +mkexedebugflag="-g" +common_cflags="" +common_cppflags="" +internal_cflags="" +internal_cppflags="" +ocamlc_cflags="" +ocamlc_cppflags="" +ocamlopt_cflags="" +ocamlopt_cppflags="" +oc_ldflags="" +with_sharedlibs=true +ostype="Unix" +iflexdir="" +SO="so" +toolchain="cc" +profinfo=false +profinfo_width=0 +extralibs= + +# Information about the package + +## Source directory +AC_CONFIG_SRCDIR([runtime/interp.c]) + +## Directory containing auxiliary scripts used dugring build +AC_CONFIG_AUX_DIR([build-aux]) + +## Output variables + +AC_SUBST([CONFIGURE_ARGS]) +AC_SUBST([VERSION], [AC_PACKAGE_VERSION]) +AC_SUBST([CC]) +# Note: This is present for the flexdll bootstrap where it exposed as the old +# TOOLPREF variable. It would be better if flexdll where updated to require +# WINDRES instead. +AC_SUBST([DIRECT_CPP]) +AC_SUBST([ac_tool_prefix]) +AC_SUBST([exeext]) +AC_SUBST([OBJEXT]) +AC_SUBST([libext]) +AC_SUBST([S]) +AC_SUBST([SO]) +AC_SUBST([arch]) +AC_SUBST([arch64]) +AC_SUBST([model]) +AC_SUBST([system]) +AC_SUBST([systhread_support]) +AC_SUBST([unix_or_win32]) +AC_SUBST([unixlib]) +AC_SUBST([graphlib]) +AC_SUBST([outputexe]) +AC_SUBST([outputobj]) +AC_SUBST([syslib]) +AC_SUBST([extralibs]) +AC_SUBST([programs_man_section]) +AC_SUBST([libraries_man_section]) +AC_SUBST([fpic]) +AC_SUBST([mkexe]) +AC_SUBST([mkexedebugflag]) +AC_SUBST([ccomptype]) +AC_SUBST([toolchain]) +AC_SUBST([oc_cflags]) +AC_SUBST([oc_cppflags]) +AC_SUBST([oc_ldflags]) +AC_SUBST([bytecclibs]) +AC_SUBST([nativecclibs]) +AC_SUBST([ocamlc_cflags]) +AC_SUBST([ocamlc_cppflags]) +AC_SUBST([ocamlopt_cflags]) +AC_SUBST([ocamlopt_cppflags]) +AC_SUBST([iflexdir]) +AC_SUBST([hashbangscripts]) +AC_SUBST([AR]) +AC_SUBST([RANLIB]) +AC_SUBST([RANLIBCMD]) +AC_SUBST([mklib]) +AC_SUBST([supports_shared_libraries]) +AC_SUBST([natdynlink]) +AC_SUBST([natdynlinkopts]) +AC_SUBST([cmxs]) +AC_SUBST([debug_runtime]) +AC_SUBST([instrumented_runtime]) +AC_SUBST([otherlibraries]) +AC_SUBST([cc_has_debug_prefix_map]) +AC_SUBST([as_has_debug_prefix_map]) +AC_SUBST([with_debugger]) # TODO: rename this variable +AC_SUBST([with_camltex]) +AC_SUBST([ocamldoc]) +AC_SUBST([pthread_link]) +AC_SUBST([x_includes]) +AC_SUBST([x_libraries]) +AC_SUBST([libbfd_include]) +AC_SUBST([libbfd_link]) +AC_SUBST([asppprofflags]) +AC_SUBST([ASPP]) +AC_SUBST([AS]) +AC_SUBST([asm_cfi_supported]) +AC_SUBST([sharedlib_cflags]) +AC_SUBST([rpath]) +AC_SUBST([mksharedlib]) +AC_SUBST([mkmaindll]) +AC_SUBST([mksharedlibrpath]) +AC_SUBST([install_bytecode_programs]) +AC_SUBST([install_source_artifacts]) +AC_SUBST([profiling]) +AC_SUBST([profinfo]) +AC_SUBST([profinfo_width]) +AC_SUBST([cc_profile]) +AC_SUBST([frame_pointers]) +AC_SUBST([spacetime]) +AC_SUBST([call_counts]) +AC_SUBST([libunwind_available]) +AC_SUBST([libunwind_include_flags]) +AC_SUBST([libunwind_link_flags]) +AC_SUBST([flambda]) +AC_SUBST([flambda_invariants]) +AC_SUBST([max_testsuite_dir_retries]) +AC_SUBST([windows_unicode]) +AC_SUBST([flat_float_array]) +AC_SUBST([afl]) +AC_SUBST([force_safe_string]) +AC_SUBST([default_safe_string]) +AC_SUBST([flexdll_chain]) +AC_SUBST([flexlink_flags]) +AC_SUBST([PACKLD]) + +## Generated files + +AC_CONFIG_FILES([Makefile.common]) +AC_CONFIG_FILES([Makefile.config]) +AC_CONFIG_HEADERS([runtime/caml/m.h]) +AC_CONFIG_HEADERS([runtime/caml/s.h]) + +# Checks for system types + +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +AC_CANONICAL_TARGET + +AS_CASE([$host], + [*-pc-windows], + [CC=cl + ccomptype=msvc + S=asm + SO=dll + outputexe=-Fe + mkexedebugflag='' + syslib='$(1).lib'], + [ccomptype=cc + S=s + SO=so + outputexe='-o $(EMPTY)' + syslib='-l$(1)']) + +# Environment variables that are taken into account + +AC_ARG_VAR([AS], [which assembler to use]) +AC_ARG_VAR([ASPP], [which assembler (with preprocessor) to use]) +AC_ARG_VAR([PARTIALLD], [how to build partial (relocatable) object files]) + +# Command-line arguments to configure + +AC_ARG_ENABLE([debug-runtime], + [AS_HELP_STRING([--disable-debug-runtime], + [do not build runtime with debugging support])]) + +AC_ARG_ENABLE([debugger], + [AS_HELP_STRING([--enable-debugger], + [build the debugger @<:@default=auto@:>@])], + [], + [enable_debugger=auto]) + +AC_ARG_VAR([DLLIBS], + [which libraries to use (in addition to -ldl) to load dynamic libs]) + +AC_ARG_ENABLE([instrumented-runtime], + [AS_HELP_STRING([--enable-instrumented-runtime], + [build the instrumented runtime @<:@default=auto@:>@])], + [], + [enable_instrumented_runtime=auto]) + +AC_ARG_ENABLE([vmthreads], + [AS_HELP_STRING([--disable-vmthreads], + [disable the bytecode threads library])]) + +AC_ARG_ENABLE([systhreads], + [AS_HELP_STRING([--disable-systhreads], + [disable the Win32/POSIX threads library])]) + +AC_ARG_WITH([libunwind], + [AS_HELP_STRING([--without-libunwind], + [disable libunwind support for Spacetime profiling])]) + +AC_ARG_VAR([LIBUNWIND_INCLUDE_DIR], + [location of header files for libunwind]) + +AC_ARG_VAR([LIBUNWIND_LIB_DIR], + [location of library files for libunwind]) + +AC_ARG_ENABLE([graph-lib], + [AS_HELP_STRING([--disable-graph-lib], + [do not build the graphics library])]) + +AC_ARG_ENABLE([str-lib], + [AS_HELP_STRING([--disable-str-lib], + [do not build the str library])]) + +AC_ARG_ENABLE([unix-lib], + [AS_HELP_STRING([--disable-unix-lib], + [do not build the unix library])]) + +AC_ARG_ENABLE([bigarray-lib], + [AS_HELP_STRING([--disable-bigarray-lib], + [do not build the legacy separate bigarray library])]) + +AC_ARG_ENABLE([ocamldoc], + [AS_HELP_STRING([--disable-ocamldoc], + [do not build the ocamldoc documentation system])], + [], + [ocamldoc=auto]) + +AC_ARG_ENABLE([frame-pointers], + [AS_HELP_STRING([--enable-frame-pointers], + [use frame pointers in runtime and generated code])]) + +AC_ARG_ENABLE([naked-pointers], + [AS_HELP_STRING([--disable-naked-pointers], + [do not allow naked pointers])]) + +AC_ARG_ENABLE([spacetime], + [AS_HELP_STRING([--enable-spacetime], + [build the spacetime profiler])]) + +AC_ARG_ENABLE([call-counts], + [AS_HELP_STRING([--disable-call-counts], + [disable the call counts in spacetime])]) + +AC_ARG_ENABLE([cfi], + [AS_HELP_STRING([--disable-cfi], + [disable the CFI directives in assembly files])]) + +AC_ARG_ENABLE([installing-source-artifacts], + [AS_HELP_STRING([--enable-installing-source-artifacts], + [install *.cmt* and *.mli files])]) +AC_ARG_ENABLE([installing-bytecode-programs], + [AS_HELP_STRING([--enable-installing-bytecode-programs], + [also install the bytecode versions of programs])]) + +AC_ARG_ENABLE([native-compiler], + [AS_HELP_STRING([--disable-native-compiler], + [do not build the native compiler])]) + +AC_ARG_ENABLE([flambda], + [AS_HELP_STRING([--enable-flambda], + [enable flambda optimizations])]) + +AC_ARG_ENABLE([flambda-invariants], + [AS_HELP_STRING([--enable-flambda-invariants], + [enable invariants checks in flambda])]) + +AC_ARG_WITH([target-bindir], + [AS_HELP_STRING([--with-target-bindir], + [location of binary programs on target system])]) + +AC_ARG_ENABLE([reserved-header-bits], + [AS_HELP_STRING([--enable-reserved-header-bits=BITS], + [reserve BITS (between 0 and 31) bits in block headers for profiling info])], + [AS_CASE([$enable_reserved_header_bits], + [0], + [with_profinfo=false + profinfo_width=0], + [[[1-9]]|1[[0-9]]|2[[0-1]]], + [with_profinfo=true + profinfo_width="$enable_reserved_header_bits"], + [AC_MSG_ERROR([invalid argument to --enable-reserved-header-bits])])]) + +AC_ARG_VAR([WINDOWS_UNICODE_MODE], + [how to handle Unicode under Windows: ansi, compatible]) + +# There are two configure-time string safety options, +# --(enable|disable)-force-safe-string and +# DEFAULT_STRING=safe|unsafe that +# interact with a compile-time (un)safe-string option. +# +# If --enable-force-safe-string is set at configure time, then the compiler +# will always enforce that string and bytes are distinct: the +# compile-time -unsafe-string option is disabled. This lets us +# assume pervasive string immutability, for code optimizations and +# in the C layer. +# +# If --disable-force-safe-string is set at configure-time, the compiler +# will use the compile-time (un)safe-string option to decide whether +# string and bytes are compatible on a per-file basis. The +# configuration variable DEFAULT_STRING=safe|unsafe decides which +# setting will be chosen by default, if no compile-time option is +# explicitly passed. +# +# The configure-time behavior of OCaml 4.05 and older was equivalent +# to --disable-force-safe-string DEFAULT_STRING=unsafe. OCaml 4.06 +# and later use --disable-force-safe-string DEFAULT_STRING=safe. We +# expect --enable-force-safe-string to become the default in the future. + +AC_ARG_ENABLE([force-safe-string], + [AS_HELP_STRING([--enable-force-safe-string], + [force strings to be safe])]) + +AC_ARG_VAR([DEFAULT_STRING], + [whether strings should be safe (default) or unsafe]) + +AC_ARG_ENABLE([flat-float-array], + [AS_HELP_STRING([--disable-flat-float-array], + [do not use flat float arrays])]) + +AC_ARG_WITH([afl], + [AS_HELP_STRING([--with-afl], + [use the AFL fuzzer])]) + +AS_IF([test x"$enable_unix_lib" = "xno"], + [AS_IF([test x"$enable_debugger" = "xyes"], + [AC_MSG_ERROR([replay debugger requires the unix library])], + [enable_debugger="no"]) + AS_IF([test x"$enable_bigarray_lib" = "xyes"], + [AC_MSG_ERROR([legacy bigarray library requires the unix library])])]) + +AS_IF([test x"$enable_unix_lib" = "xno" -o x"$enable_str_lib" = "xno"], + [AS_IF([test x"$enable_ocamldoc" = "xyes"], + [AC_MSG_ERROR([ocamldoc requires the unix and str libraries])], + [enable_ocamldoc="no" + with_camltex=""])], + [with_camltex="true"]) + +# Initialization of libtool +# Allow the MSVC linker to be found even if ld isn't installed. +# User-specified LD still takes precedence. +AC_CHECK_TOOLS([LD],[ld link]) +# libtool expects host_os=mingw for native Windows +old_host_os=$host_os +AS_IF([test x"$host_os" = "xwindows"],[host_os=mingw]) +LT_INIT +host_os=$old_host_os + +# Extracting information from libtool's configuration +AS_IF([test -n "$RANLIB" ], + [RANLIBCMD="$RANLIB"], + [RANLIB="$AR rs"; RANLIBCMD=""] +) + +AS_CASE([$host], + # In config/Makefile.mingw*, we had: + # TARGET=i686-w64-mingw32 and x86_64-w64-mingw32 + # TOOLPREF=$(TARGET)- + # ARCMD=$(TOOLPREF)ar + # RANLIB=$(TOOLPREF)ranlib + # RANLIBCMD=$(TOOLPREF)ranlib + # However autoconf and libtool seem to use ar and ranlib + # So we let them do, at the moment + [*-pc-windows], + [ + libext=lib + AR=""; RANLIB=echo; RANLIBCMD="" + AS_IF([test "$host_cpu" = "x86_64" ], + [machine="-machine:AMD64 "], + [machine=""]) + mklib="link -lib -nologo $machine /out:\$(1) \$(2)" + ], + [ + mklib="rm -f \$(1) && ${AR} rc \$(1) \$(2) && ${RANLIB} \$(1)" + ]) + +# Determine how to call the C preprocessor directly. +# Most of the time, calling the C preprocessor through the C compiler is +# desirable and even important. +# In some cases, though, we want to use the C preprocessor only to +# expand macros. In such cases, it is much more convenient to be able +# to invoke it directly rather than through the C compiler, for instance +# because, when invoked directly, the C preprocessor does not require +# to be invoked on a file with a '.c' extension +# We thus figure out how to invoke the C preprocessor directly but +# let the CPP variable untouched, except for the MSVC port where we set it +# manually to make sure the backward compatibility is preserved +AS_CASE([$host], + [*-pc-windows], + [CPP="$CC -nologo -EP"]) + +# Libraries to build depending on the host + +AS_CASE([$host], + [*-*-mingw32|*-pc-windows], + [unix_or_win32="win32" + unixlib="win32unix" + graphlib="win32graph" + cc_profile=''], + [unix_or_win32="unix" + unixlib="unix" + graphlib="graph" + cc_profile='-pg']) +AS_CASE([$host], + [*-*-cygwin*|*-*-mingw32|*-pc-windows], + [exeext=".exe"], + [exeext='']) + +otherlibraries="dynlink" +AS_IF([test x"$enable_unix_lib" != "xno"], + [AS_IF([test x"$enable_bigarray_lib" != "xno"], + [otherlibraries="$otherlibraries $unixlib bigarray"], + [otherlibraries="$otherlibraries $unixlib"])]) +AS_IF([test x"$enable_str_lib" != "xno"], + [otherlibraries="$otherlibraries str"]) + +# Checks for system services + +## Test whether #! scripts are supported +## TODO: have two values, one for host and one for target +AC_SYS_INTERPRETER + +AS_IF( + [test "x$interpval" = "xyes"], + [AS_CASE([$host], + [*-cygwin|*-*-mingw32|*-pc-windows], + [hashbangscripts=false], + [hashbangscripts=true] + )], + [hashbangscripts=false] +) + +# Are we building a cross-compiler + +AS_IF( + [test x"$host" = x"$target"], + [cross_compiler=false], + [cross_compiler=true]) + +# Checks for programs + +## Check for the C compiler: done by libtool +## AC_PROG_CC + +## Check for C99 support: done by libtool +## AC_PROG_CC_C99 + +## Find vendor of the C compiler +OCAML_CC_VENDOR + +## Determine which flags to use for the C compiler + +AS_CASE([$ocaml_cv_cc_vendor], + [xlc-*], + [outputobj='-o $(EMPTY)'; gcc_warnings="-qflag=i:i"], # all warnings enabled + [msvc-*], + [outputobj=-Fo; CPP="cl -nologo -EP"; gcc_warnings=""], + [outputobj='-o $(EMPTY)'; AS_CASE([AC_PACKAGE_VERSION], + [*+dev*], + [gcc_warnings="-Wall -Werror"], + [gcc_warnings="-Wall"] + )] +) + +# We select high optimization levels, provided we can turn off: +# - strict type-based aliasing analysis (too risky for the OCaml runtime) +# - strict no-overflow conditions on signed integer arithmetic +# (the OCaml runtime assumes Java-style behavior of signed integer arith.) +# Concerning optimization level, -O3 is somewhat risky, so take -O2. +# Concerning language version, gnu99 is ISO C99 plus GNU extensions +# that are often used in standard headers. Older GCC versions +# defaults to gnu89, which is not C99. Clang defaults to gnu99 or +# gnu11, which is fine. + +# Note: the vendor macro can not recognize MinGW because it calls the +# C preprocessor directly so no compiler specific macro like __MING32__ +# is defined. We thus catch MinGW first by looking at host and examine +# the vendor only as a fall-back. We could put tis part of the logic +# in the macro itself, too +AS_CASE([$host], + [*-*-mingw32], + [internal_cflags="-Wno-unused $gcc_warnings" + # TODO: see whether the code can be fixed to avoid -Wno-unused + common_cflags="-O -mms-bitfields" + internal_cppflags='-DUNICODE -D_UNICODE' + internal_cppflags="$internal_cppflags -DWINDOWS_UNICODE=" + internal_cppflags="${internal_cppflags}\$(WINDOWS_UNICODE)"], + [AS_CASE([$ocaml_cv_cc_vendor], + [clang-*], + [common_cflags="-O2 -fno-strict-aliasing -fwrapv"; + internal_cflags="$gcc_warnings"], + [gcc-[012]-*], + # Some versions known to miscompile OCaml, e,g, 2.7.2.1, some 2.96. + # Plus: C99 support unknown. + [AC_MSG_ERROR([This version of GCC is too old. + Please use GCC version 4.2 or above.])], + [gcc-3-*|gcc-4-[01]], + # No -fwrapv option before GCC 3.4. + # Known problems with -fwrapv fixed in 4.2 only. + [AC_MSG_WARN([This version of GCC is rather old. + Reducing optimization level."]); + AC_MSG_WARN([Consider using GCC version 4.2 or above.]); + common_cflags="-std=gnu99 -O"; + internal_cflags="$gcc_warnings"], + [gcc-4-*], + [common_cflags="-std=gnu99 -O2 -fno-strict-aliasing -fwrapv \ +-fno-builtin-memcmp"; + internal_cflags="$gcc_warnings"], + [gcc-*], + [common_cflags="-O2 -fno-strict-aliasing -fwrapv"; + internal_cflags="$gcc_warnings"], + [msvc-*], + [common_cflags="-nologo -O2 -Gy- -MD" + common_cppflags="-D_CRT_SECURE_NO_DEPRECATE" + internal_cppflags='-DUNICODE -D_UNICODE' + internal_cppflags="$internal_cppflags -DWINDOWS_UNICODE=" + internal_cppflags="${internal_cppflags}\$(WINDOWS_UNICODE)"], + [xlc-*], + [common_cflags="-O5 -qtune=balanced -qnoipa -qinline $CFLAGS"; + internal_cflags="$gcc_warnings"], + [common_cflags="-O"])]) + +internal_cppflags="-DCAML_NAME_SPACE $internal_cppflags" + +# Enable SSE2 on x86 mingw to avoid using 80-bit registers. +AS_CASE([$host], + [i686-*-mingw32], + [internal_cflags="$internal_cflags -mfpmath=sse -msse2"]) + +# Use 64-bit file offset if possible +# See also AC_SYS_LARGEFILE +# Problem: flags are added to CC rather than CPPFLAGS +AS_CASE([$host], + [*-*-mingw32|*-pc-windows], [], + [common_cppflags="$common_cppflags -D_FILE_OFFSET_BITS=64"]) + +# Adjust according to target + +# On Windows we do not take $enable_shared because it does not seem +# to work. This should be better understood later +#AS_CASE([$target], +# [*-pc-windows], +# [enable_shared=yes]) + +AS_IF([test x"$enable_shared" = "xno"],[with_sharedlibs=false]) + +AS_CASE([$CC,$host], + [*,*-*-darwin*], + [mkexe="$mkexe -Wl,-no_compact_unwind"; + AC_DEFINE([HAS_ARCH_CODE32], [1])], + [*,*-*-haiku*], [mathlib=""], + [*,*-*-cygwin*], + [AS_CASE([$target], + [i686-*], [flavor=cygwin], + [x86_64-*], [flavor=cygwin64], + [AC_MSG_ERROR([unknown cygwin variant])]) + common_cppflags="$common_cppflags -U_WIN32" + AS_IF([$with_sharedlibs], + [flexlink="flexlink -chain $flavor -merge-manifest -stack 16777216" + flexdir=`$flexlink -where | tr -d '\015'` + AS_IF([test -z "$flexdir"], + [AC_MSG_WARN( + [flexlink not found: native shared libraries won't be available.] + ) + with_sharedlibs=false], + [iflexdir="-I\"$flexdir\"" + mkexe="$flexlink -exe" + mkexedebugflag="-link -g"] + )] + ) + AS_IF([! $with_sharedlibs], + [mkexe="$mkexe -Wl,--stack,16777216" + oc_ldflags="-Wl,--stack,16777216"] + ) + ostype="Cygwin"], + [*,*-*-mingw32], + [AS_IF([$with_sharedlibs], + [AS_CASE([$host], + [i686-*-*], [flexdll_chain="mingw"], + [x86_64-*-*], [flexdll_chain="mingw64"]) + flexlink="flexlink -chain $flexdll_chain -merge-manifest -stack 16777216" + flexdir=`$flexlink -where | tr -d '\015'` + AS_IF([test -z "$flexdir"], [flexdir='$(ROOTDIR)/flexdll']) + iflexdir="-I\"$flexdir\"" + mkexedebugflag="-link -g"]) + ostype="Win32" + toolchain="mingw" + mkexe='$(MKEXE_ANSI) $(if $(OC_LDFLAGS),-link "$(OC_LDFLAGS)")' + oc_ldflags='-municode' + SO="dll"], + [*,*-pc-windows], + [toolchain=msvc + ostype="Win32" + mkexe='$(MKEXE_ANSI) $(if $(OC_LDFLAGS),-link "$(OC_LDFLAGS)")' + oc_ldflags='/ENTRY:wmainCRTStartup' + AS_CASE([$host], + [i686-pc-windows], [flexdll_chain=msvc], + [x86_64-pc-windows], [flexdll_chain=msvc64]) + AS_IF([$with_sharedlibs], + [flexlink="flexlink -chain $flexdll_chain -merge-manifest -stack 16777216" + flexdir=`$flexlink -where | tr -d '\015'` + AS_IF([test -z "$flexdir"], [flexdir='$(ROOTDIR)/flexdll']) + iflexdir="-I\"$flexdir\"" + mkexedebugflag="-link -g"])], + [*,x86_64-*-linux*], + AC_DEFINE([HAS_ARCH_CODE32], [1]), + [xlc*,powerpc-ibm-aix*], + [mkexe="$mkexe " + oc_ldflags="-brtl -bexpfull" + AC_DEFINE([HAS_ARCH_CODE32], [1])], +) + + +## Program to use to install files +AC_PROG_INSTALL + +# Checks for libraries + +## Mathematical library +AC_CHECK_LIB([m],[cos]) + +AS_IF([test "x$ac_cv_lib_m_cos" = xyes ], [mathlib="-lm"], [mathlib=""]) + +# Checks for header files + +AC_CHECK_HEADER([math.h]) +AC_CHECK_HEADERS([unistd.h],[AC_DEFINE([HAS_UNISTD])]) +AC_CHECK_HEADER([stdint.h],[AC_DEFINE([HAS_STDINT_H])]) +AC_CHECK_HEADER([sys/shm.h],[AC_DEFINE([HAS_SYS_SHM_H])]) +AC_CHECK_HEADER([dirent.h], [AC_DEFINE([HAS_DIRENT])], [], + [#include ]) + +AC_CHECK_HEADER([sys/select.h], [AC_DEFINE([HAS_SYS_SELECT_H])], [], + [#include ]) + +# Checks for types + +## off_t +AC_TYPE_OFF_T +AC_DEFINE([HAS_OFF_T]) + +# Checks for structures + +# Checks for compiler characteristics + +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(long) +AC_CHECK_SIZEOF(long *) +AC_CHECK_SIZEOF(short) +AC_CHECK_SIZEOF(long long) + +AS_IF( + [test "x$ac_cv_sizeof_long_p" = "x4" ], + [bits=32; arch64=false], + [test "x$ac_cv_sizeof_long_p" = "x8" ], + [bits=64; arch64=true + AC_DEFINE([ARCH_SIXTYFOUR], [1])], + [AC_MSG_ERROR([Neither 32 nor 64 bits architecture.])] +) + +AS_IF([test "x$ac_cv_sizeof_int" != "x4" && test "x$ac_cv_sizeof_long" != "x4" \ + && test "x$ac_cv_sizeof_short" != "x4"], + [AC_MSG_ERROR([Sorry, we can't find a 32-bit integer type.])] +) + +AS_IF( + [test "x$ac_cv_sizeof_long" != "x8" && + test "x$ac_cv_sizeof_long_long" != "x8"], + [AC_MSG_ERROR([Sorry, we can't find a 64-bit integer type.])] +) + +AC_DEFINE_UNQUOTED([SIZEOF_PTR], [$ac_cv_sizeof_long_p]) +AC_DEFINE_UNQUOTED([SIZEOF_LONGLONG], [$ac_cv_sizeof_long_long]) + +AC_MSG_NOTICE([Target is a $bits bits architecture]) + +AC_C_BIGENDIAN( + [AC_DEFINE([ARCH_BIG_ENDIAN], [1])], + [], + [AC_MSG_ERROR([could not determine endianness.])], + [AC_MSG_ERROR([unable to handle universal endianness])] +) + +AC_CHECK_ALIGNOF([double]) +AC_CHECK_ALIGNOF([long]) + +AS_IF([! $arch64], + [AS_CASE([$target_cpu], + [i686], [], + [AS_IF([test "$ac_cv_alignof_double" -gt 4], + [AC_DEFINE([ARCH_ALIGN_DOUBLE], [1])]) + AS_IF([test "$ac_cv_alignof_long" -gt 4], + [AC_DEFINE([ARCH_ALIGN_LONG], [1])]) + ])]) + +# Shared library support + +shared_libraries_supported=false +sharedlib_cflags='' +mksharedlib='shared-libs-not-available' +rpath='' +mksharedlibrpath='' +natdynlinkopts="" + +AS_IF([test x"$enable_shared" != "xno"], + [AS_CASE([$host], + [*-apple-darwin*], + [mksharedlib="$CC -shared -flat_namespace -undefined suppress \ + -Wl,-no_compact_unwind" + shared_libraries_supported=true], + [*-*-mingw32], + [mksharedlib='$(FLEXLINK)' + mkmaindll='$(FLEXLINK) -maindll' + shared_libraries_supported=$with_sharedlibs], + [*-pc-windows], + [mksharedlib='$(FLEXLINK)' + mkmaindll='$(FLEXLINK) -maindll' + shared_libraries_supported=$with_sharedlibs], + [*-*-cygwin*], + [mksharedlib="$flexlink" + mkmaindll="$flexlink -maindll" + shared_libraries_supported=true], + [powerpc-ibm-aix*], + [AS_CASE([$CC], + [xlc*], + [mksharedlib="$CC -qmkshrobj -G" + shared_libraries_supported=true])], + [[*-*-linux*|*-*-freebsd[3-9]*|*-*-freebsd[1-9][0-9]*\ + |*-*-openbsd*|*-*-netbsd*|*-*-dragonfly*|*-*-gnu*|*-*-haiku*]], + [sharedlib_cflags="-fPIC" + mksharedlib="$CC -shared" + oc_ldflags="$oc_ldflags -Wl,-E" + rpath="-Wl,-rpath," + mksharedlibrpath="-Wl,-rpath," + natdynlinkopts="-Wl,-E" + shared_libraries_supported=true])]) + +AS_IF([test -z "$mkmaindll"], [mkmaindll=$mksharedlib]) + +# Configure native dynlink + +natdynlink=false + +AS_IF([test x"$enable_shared" != "xno"], + [AS_CASE(["$host"], + [*-*-cygwin*], [natdynlink=true], + [*-*-mingw32], [natdynlink=true], + [*-pc-windows], [natdynlink=true], + [[i[3456]86-*-linux*]], [natdynlink=true], + [[i[3456]86-*-gnu*]], [natdynlink=true], + [[x86_64-*-linux*]], [natdynlink=true], + [[i[3456]86-*-darwin*]], [AS_IF([$arch64], [natdynlink=true])], + [x86_64-*-darwin*], [natdynlink=true], + [s390x*-*-linux*], [natdynlink=true], + [powerpc*-*-linux*], [natdynlink=true], + [i686-*-kfreebsd*], [natdynlink=true], + [x86_64-*-kfreebsd*], [natdynlink=true], + [x86_64-*-dragonfly*], [natdynlink=true], + [[i[3456]86-*-freebsd*]], [natdynlink=true], + [x86_64-*-freebsd*], [natdynlink=true], + [[i[3456]86-*-openbsd*]], [natdynlink=true], + [x86_64-*-openbsd*], [natdynlink=true], + [[i[3456]86-*-netbsd*]], [natdynlink=true], + [x86_64-*-netbsd*], [natdynlink=true], + [i386-*-gnu0.3], [natdynlink=true], + [[i[3456]86-*-haiku*]], [natdynlink=true], + [arm*-*-linux*], [natdynlink=true], + [arm*-*-freebsd*], [natdynlink=true], + [earm*-*-netbsd*], [natdynlink=true], + [aarch64-*-linux*], [natdynlink=true])]) + +# Try to work around the Skylake/Kaby Lake processor bug. +AS_CASE(["$CC,$host"], + [*gcc*,x86_64-*|*gcc*,i686-*], + [OCAML_CC_HAS_FNO_TREE_VRP + AS_IF([$cc_has_fno_tree_vrp], + [internal_cflags="$internal_cflags -fno-tree-vrp"])]) + +# Configure the native-code compiler + +arch=none +model=default +system=unknown + +AS_CASE([$host], + [[i[3456]86-*-linux*]], + [arch=i386; system=linux_elf], + [[i[3456]86-*-*bsd*]], + [arch=i386; system=bsd_elf], + [[i[3456]86-*-haiku*]], + [arch=i386; system=beos], + [[i[3456]86-*-cygwin]], + [arch=i386; system=cygwin], + [[i[3456]86-*-darwin*]], + [AS_IF([$arch64], [arch=amd64], [arch=i386]); system=macosx], + [[i[3456]86-*-gnu*]], + [arch=i386; system=gnu], + [[i[3456]86-*-mingw32]], + [arch=i386; system=mingw], + [i686-pc-windows], + [arch=i386; system=win32], + [x86_64-pc-windows], + [arch=amd64; system=win64], + [[powerpc64le*-*-linux*]], + [arch=power; model=ppc64le; system=elf], + [[powerpc*-*-linux*]], + [arch=power; AS_IF([$arch64],[model=ppc64],[model=ppc]); system=elf], + [[powerpc-*-netbsd*]], + [arch=power; model=ppc; system=netbsd], + [[powerpc-*-openbsd*]], + [arch=power; model=ppc; system=bsd_elf], + [[s390x*-*-linux*]], + [arch=s390x; model=z10; system=elf], + [armv6*-*-linux-gnueabihf], + [arch=arm; model=armv6; system=linux_eabihf], + [armv7*-*-linux-gnueabihf], + [arch=arm; model=armv7; system=linux_eabihf], + [armv8*-*-linux-gnueabihf], + [arch=arm; model=armv8; system=linux_eabihf], + [armv8*-*-linux-gnueabi], + [arch=arm; model=armv8; system=linux_eabi], + [armv7*-*-linux-gnueabi], + [arch=arm; model=armv7; system=linux_eabi], + [armv6t2*-*-linux-gnueabi], + [arch=arm; model=armv6t2; system=linux_eabi], + [armv6*-*-linux-gnueabi], + [arch=arm; model=armv6; system=linux_eabi], + [armv6*-*-freebsd*], + [arch=arm; model=armv6; system=freebsd], + [earmv6*-*-netbsd*], + [arch=arm; model=armv6; system=netbsd], + [earmv7*-*-netbsd*], + [arch=arm; model=armv7; system=netbsd], + [armv5te*-*-linux-gnueabi], + [arch=arm; model=armv5te; system=linux_eabi], + [armv5*-*-linux-gnueabi], + [arch=arm; model=armv5; system=linux_eabi], + [arm*-*-linux-gnueabi], + [arch=arm; system=linux_eabi], + [arm*-*-openbsd*], + [arch=arm; system=bsd], + [zaurus*-*-openbsd*], + [arch=arm; system=bsd], + [x86_64-*-linux*], + [arch=amd64; system=linux], + [x86_64-*-gnu*], + [arch=amd64; system=gnu], + [x86_64-*-dragonfly*], + [arch=amd64; system=dragonfly], + [x86_64-*-freebsd*], + [arch=amd64; system=freebsd], + [x86_64-*-netbsd*], + [arch=amd64; system=netbsd], + [x86_64-*-openbsd*], + [arch=amd64; system=openbsd], + [x86_64-*-darwin*], + [arch=amd64; system=macosx], + [x86_64-*-mingw32], + [arch=amd64; system=mingw64], + [aarch64-*-linux*], + [arch=arm64; system=linux], + [x86_64-*-cygwin*], + [arch=amd64; system=cygwin] +) + +AS_IF([test x"$enable_native_compiler" = "xno"], + [arch=none; model=default; system=unknown; native_compiler=false + AC_MSG_NOTICE([the native compiler is disabled])], + [native_compiler=true]) + +AS_IF([! $native_compiler], [natdynlink=false]) + +AS_IF([$natdynlink], [cmxs="cmxs"], [cmxs="cmx"]) + +AC_DEFINE_UNQUOTED([OCAML_OS_TYPE], ["$ostype"]) + +AC_CHECK_TOOL([DIRECT_LD],[ld]) +AS_IF([test -z "$PARTIALLD"], + # The string for PACKLD must be capable of being concatenated with the + # output filename. Don't assume that all C compilers understand GNU -ofoo + # form, so ensure that the definition includes a space at the end (which is + # achieved using the $(EMPTY) expansion trick). + [AS_CASE(["$arch,$CC,$system,$model"], + [amd64,gcc*,macosx,*], [PACKLD='ld -r -arch x86_64 -o $(EMPTY)'], + [amd64,gcc*,solaris,*], [PACKLD='ld -r -m elf_x86_64 -o $(EMPTY)'], + [power,gcc*,elf,ppc], [PACKLD='ld -r -m elf32ppclinux -o $(EMPTY)'], + [power,gcc*,elf,ppc64], [PACKLD='ld -r -m elf64ppc -o $(EMPTY)'], + [power,gcc*,elf,ppc64le], [PACKLD='ld -r -m elf64lppc -o $(EMPTY)'], + # For the Microsoft C compiler there must be no space at the end of the + # string. + [*,cl,*,*], [PACKLD="link -lib -nologo $machine -out:"], + [PACKLD="$DIRECT_LD -r -o \$(EMPTY)"])], + [PACKLD="$PARTIALLD -o \$(EMPTY)"]) + +AS_IF([test $arch != "none" && $arch64 ], + [otherlibraries="$otherlibraries raw_spacetime_lib"]) + +# Profiling + +AS_CASE(["$arch,$system"], + [i386,linux_elf], [profiling=true], + [i386,gnu], [profiling=true], + [i386,bsd_elf], [profiling=true], + [amd64,macosx], [profiling=true], + [i386,macosx], [profiling=true], + [amd64,linux], [profiling=true], + [amd64,openbsd], [profiling=true], + [amd64,freebsd], [profiling=true], + [amd64,netbsd], [profiling=true], + [arm,netbsd], [profiling=true], + [amd64,gnu], [profiling=true], + [arm,linux*], [profiling=true], + [power,elf], [profiling=true], + [power,bsd*], [profiling=true], + [power,netbsd], [profiling=true], + [profiling=false]) + +# Assembler + +AS_CASE([$host], + [*-*-mingw32|*-pc-windows], [asppprofflags=''], + [asppprofflags='-DPROFILING']) + +AS_IF([test -n "$host_alias"], [toolpref="${host}-"], [toolpref=""]) + +# We first compute default values for as and aspp +# If values have been given by the user then they take precedence over +# those just computed +# One may want to check whether the user provided values first +# and only compute values if none has been provided + +AS_CASE(["$arch,$system"], + [i386,win32], + [default_as="ml -nologo -coff -Cp -c -Fo"], + [amd64,win64], + [default_as="ml64 -nologo -Cp -c -Fo"], + [amd64,macosx], + [AS_CASE([$ocaml_cv_cc_vendor], + [clang-*], + [default_as='clang -arch x86_64 -Wno-trigraphs -c' + default_aspp='clang -arch x86_64 -Wno-trigraphs -c'], + [default_as="${toolpref}as -arch x86_64" + default_aspp="${toolpref}gcc -arch x86_64 -c"])], + [amd64,solaris], + [default_as="${toolpref}as --64" + default_aspp="${toolpref}gcc -m64 -c"], + [i386,solaris], + [default_as="${toolpref}as" + default_aspp="${toolpref}gcc -c"], + [power,elf], + [AS_CASE([$model], + [ppc64le], + [default_as="${toolpref}as -a64 -mpower8" + default_aspp="${toolpref}gcc -m64 -mcpu=powerpc64le -c"], + [ppc64], + [default_as="${toolpref}as -a64 -mppc64" + default_aspp="${toolpref}gcc -m64 -c"], + [ppc], + [default_as="${toolpref}as -mppc" + default_aspp="${toolpref}gcc -m32 -c"])], + [s390x,elf], + [default_as="${toolpref}as -m 64 -march=$model" + default_aspp="${toolpref}gcc -c -Wa,-march=$model"], + [arm,freebsd], + [default_as="${toolpref}cc -c" + default_aspp="${toolpref}cc -c"], + [*,dragonfly], + [default_as="${toolpref}as" + default_aspp="${toolpref}cc -c"], + [*,freebsd], + [default_as="${toolpref}as" + default_aspp="${toolpref}cc -c"], + [amd64,*|arm,*|arm64,*|i386,*|power,bsd*|power,netbsd], + [default_as="${toolpref}as" + AS_CASE([$ocaml_cv_cc_vendor], + [clang-*], [default_aspp="${toolpref}clang -c -Wno-trigraphs"], + [default_aspp="${toolpref}gcc -c"])]) + +AS_IF([test "$with_pic"], + [fpic=true + AC_DEFINE([CAML_WITH_FPIC]) + internal_cflags="$internal_cflags $sharedlib_cflags" + default_aspp="$default_aspp $sharedlib_cflags"], + [fpic=false]) + +AS_IF([test -z "$AS"], [AS="$default_as"]) + +AS_IF([test -z "$ASPP"], [ASPP="$default_aspp"]) + +# Checks for library functions + +## Check the semantics of signal handlers +OCAML_SIGNAL_HANDLERS_SEMANTICS + +## Check for C99 float ops + +# Note: this was disabled on Windows but the autoconf-generated script +# does find the function it is looking for. +# however the fma test does not pass so we disable the feature +# for the moment, to be backward-compatible + +AS_CASE([$host], + [*-*-mingw32|*-pc-windows], [], + [has_c99_float_ops=true + AC_CHECK_FUNC([expm1], [], [has_c99_float_ops=false]) + AS_IF([$has_c99_float_ops], + [AC_CHECK_FUNC([log1p], [], [has_c99_float_ops=false])]) + AS_IF([$has_c99_float_ops], + [AC_CHECK_FUNC([hypot], [], [has_c99_float_ops=false])]) + AS_IF([$has_c99_float_ops], + [AC_CHECK_FUNC([fma], [ + AS_CASE([$target],[x86_64-*-cygwin],[],[AC_DEFINE([HAS_WORKING_FMA])])], + [has_c99_float_ops=false])]) + AS_IF([$has_c99_float_ops], + [AC_CHECK_FUNC([copysign], [AC_DEFINE([HAS_C99_FLOAT_OPS])])])]) + +## getrusage +AC_CHECK_FUNC([getrusage], [AC_DEFINE([HAS_GETRUSAGE])]) + +## times +AC_CHECK_FUNC([times], [AC_DEFINE([HAS_TIMES])]) + +## secure_getenv and __secure_getenv + +saved_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="-D_GNU_SOURCE $CPPFLAGS" + +AC_CHECK_FUNC([secure_getenv], + [AC_DEFINE([HAS_SECURE_GETENV])], + [AC_CHECK_FUNC([__secure_getenv], [AC_DEFINE([HAS___SECURE_GETENV])])]) + +CPP_FLAGS="$saved_CPPFLAGS" + +## issetugid + +AC_CHECK_FUNC([issetugid], [AC_DEFINE([HAS_ISSETUGID])]) + +## clock_gettime, for the instrumented runtime + +## Note: on MinGW, configure finds a clock_gettime and thus the build +# system tries to build the instrumented runtime, which causes +# warnings. For the moment we simply disable it on MinGW +# but this would need to be further investigated +AS_CASE([$host], + [*-*-mingw32], [instrumented_runtime=false], + [AS_IF([test "x$enable_instrumented_runtime" = "xno" ], + [instrumented_runtime=false; instrumented_runtime_libs=""], + [ + AC_SEARCH_LIBS([clock_gettime], [rt], + [has_clock_gettime=true], + [has_clock_gettime=false]) + AS_CASE([$enable_instrumented_runtime,$has_clock_gettime], + [*,true], + [instrumented_runtime=true + AS_IF([test "x$ac_cv_search_clock_gettime" = "xnone required"], + [instrumented_runtime_libs=""], + [instrumented_runtime_libs=$ac_cv_search_clock_gettime])], + [auto,*], + [instrumented_runtime=false], + [yes,*], + [AC_MSG_ERROR([the instrumented runtime can not be built])])])]) + +## Sockets + +## TODO: check whether the different libraries are really useful + +sockets=false + +AS_CASE([$host], + [*-*-mingw32|*-pc-windows], + [cclibs="$cclibs -lws2_32" + sockets=true], + [ + AC_CHECK_FUNC([socket]) + AC_CHECK_FUNC([socketpair]) + AC_CHECK_FUNC([bind]) + AC_CHECK_FUNC([listen]) + AC_CHECK_FUNC([accept]) + AC_CHECK_FUNC([connect]) + sockets=true + ] +) + +AS_IF([$sockets], [AC_DEFINE([HAS_SOCKETS])]) + +## socklen_t in sys/socket.h + +AC_CHECK_TYPE( + [socklen_t], + [AC_DEFINE([HAS_SOCKLEN_T])], [], + [#include ]) + +AC_CHECK_FUNC([inet_aton], [AC_DEFINE([HAS_INET_ATON])]) + +## IPv6 support + +ipv6=true + +AC_CHECK_TYPE( + [struct sockaddr_in6], [], [ipv6=false], +[ +#include +#include +#include +] +) + +AS_IF([$ipv6], + [AC_CHECK_FUNC([getaddrinfo], [], [ipv6=false])]) + +AS_IF([$ipv6], + [AC_CHECK_FUNC([getnameinfo], [], [ipv6=false])]) + +AS_IF([$ipv6], + [AC_CHECK_FUNC([inet_pton], [], [ipv6=false])]) + +AS_IF([$ipv6], + [AC_CHECK_FUNC([inet_ntop], [AC_DEFINE([HAS_IPV6])])]) + +AC_CHECK_FUNC([rewinddir], [AC_DEFINE([HAS_REWINDDIR])]) + +AC_CHECK_FUNC([lockf], [AC_DEFINE([HAS_LOCKF])]) + +AC_CHECK_FUNC([mkfifo], [AC_DEFINE([HAS_MKFIFO])]) + +AC_CHECK_FUNC([getcwd], [AC_DEFINE([HAS_GETCWD])]) + +AC_CHECK_FUNC([getpriority], + [AC_CHECK_FUNC([setpriority], + [AC_DEFINE([HAS_GETPRIORITY])])]) + +## utime +## Note: this was defined in config/s-nt.h but the autoconf macros do not +# seem to detect it properly on Windows so we hardcode the definition +# of HAS_UTIME on Windows but this will probably need to be clarified +AS_CASE([$host], + [*-*-mingw32|*-pc-windows], [AC_DEFINE([HAS_UTIME])], + [AC_CHECK_HEADER([sys/types.h], + [AC_CHECK_HEADER([utime.h], + [AC_CHECK_FUNC([utime], [AC_DEFINE([HAS_UTIME])])])])]) + +AC_CHECK_FUNC([utimes], [AC_DEFINE([HAS_UTIMES])]) + +AC_CHECK_FUNC([dup2], [AC_DEFINE([HAS_DUP2])]) + +AC_CHECK_FUNC([fchmod], + [AC_CHECK_FUNC([fchown], [AC_DEFINE([HAS_FCHMOD])])]) + +AC_CHECK_FUNC([truncate], + [AC_CHECK_FUNC([ftruncate], [AC_DEFINE([HAS_TRUNCATE])])]) + +## select +AC_CHECK_FUNC([select], + [AC_CHECK_TYPE([fd_set], + [AC_DEFINE([HAS_SELECT]) + select=true], [select=false], [ +#include +#include + ])]) + +AC_CHECK_FUNC([nanosleep], [AC_DEFINE([HAS_NANOSLEEP])]) + +AC_CHECK_FUNC([symlink], + [AC_CHECK_FUNC([readlink], + [AC_CHECK_FUNC([lstat], [AC_DEFINE([HAS_SYMLINK])])])]) + +# wait +AC_CHECK_FUNC( + [waitpid], + [ + wait=true + AC_DEFINE([HAS_WAITPID]) + ], + [wait=false]) + +AC_CHECK_FUNC( + [wait4], + [ + has_wait=true + AC_DEFINE([HAS_WAIT4]) + ]) + +## getgroups +AC_CHECK_FUNC([getgroups], [AC_DEFINE([HAS_GETGROUPS])]) + +## setgroups +AC_CHECK_FUNC([setgroups], [AC_DEFINE([HAS_SETGROUPS])]) + +## initgroups +AC_CHECK_FUNC([initgroups], [AC_DEFINE([HAS_INITGROUPS])]) + +## termios + +AC_CHECK_HEADER([termios.h], + [AC_CHECK_FUNC([tcgetattr], + [AC_CHECK_FUNC([tcsetattr], + [AC_CHECK_FUNC([tcsendbreak], + [AC_CHECK_FUNC([tcflush], + [AC_CHECK_FUNC([tcflow], [AC_DEFINE([HAS_TERMIOS])])])])])])]) + +## Asynchronous I/O + +AC_MSG_CHECKING([for asynchronous I/O]) +AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +#include +#include +#include +#include + +int signalled; + +void sigio_handler(int arg) +{ + signalled = 1; +} + +int main(void) +{ +#if defined(SIGIO) && defined(FASYNC) && defined(F_SETFL) && defined(F_SETOWN) + int p[2]; + int ret; +#define OUT 0 +#define IN 1 + if (socketpair(PF_UNIX, SOCK_STREAM, 0, p) == -1) return 1; + signalled = 0; + signal(SIGIO, sigio_handler); + ret = fcntl(p[OUT], F_GETFL, 0); + fcntl(p[OUT], F_SETFL, ret | FASYNC); + fcntl(p[OUT], F_SETOWN, getpid()); + switch(fork()) { + case -1: + return 1; + case 0: + close(p[OUT]); + write(p[IN], "x", 1); + sleep(1); + exit(0); + default: + close(p[IN]); + while(wait(NULL) == -1 && errno == EINTR) /*nothing*/; + } + if (signalled) return 0; else return 1; +#else + return 1; +#endif +} + ]])], + [ + AC_DEFINE([HAS_ASYNC_IO]) + AC_MSG_RESULT([yes]) + ], + [AC_MSG_RESULT([no])], + [AC_MSG_RESULT([no])] +) + +## setitimer + +AC_CHECK_FUNC([setitimer], + [ + setitimer=true + AC_DEFINE([HAS_SETITIMER]) + ], + [setitimer=false]) + +## gethostname +# Note: detection fails on Windows so hardcoding the result +# (should be debugged later) +AS_CASE([$host], + [*-*-mingw32|*-pc-windows], [AC_DEFINE([HAS_GETHOSTNAME])], + [AC_CHECK_FUNC([gethostname], [AC_DEFINE([HAS_GETHOSTNAME])])]) + +## uname + +AC_CHECK_HEADER([sys/utsname.h], + [AC_CHECK_FUNC([uname], [AC_DEFINE([HAS_UNAME])])]) + +## gettimeofday + +AC_CHECK_FUNC([gettimeofday], + [ + gettimeofday=true + AC_DEFINE([HAS_GETTIMEOFDAY]) + ], + [gettimeofday=false]) + +## mktime + +AC_CHECK_FUNC([mktime], [AC_DEFINE([HAS_MKTIME])]) + +## setsid + +AS_CASE([$host], + [*-cygwin|*-*-mingw32|*-pc-windows], [], + [AC_CHECK_FUNC([setsid], [AC_DEFINE([HAS_SETSID])])]) + +## putenv + +AC_CHECK_FUNC([putenv], [AC_DEFINE([HAS_PUTENV])]) + +## newlocale() and +# Note: the detection fails on msvc so we hardcode the result +# (should be debugged later) +AS_CASE([$host], + [*-pc-windows], [AC_DEFINE([HAS_LOCALE_H])], + [AC_CHECK_HEADER([locale.h], + [AC_CHECK_FUNC([newlocale], + [AC_CHECK_FUNC([freelocale], + [AC_CHECK_FUNC([uselocale], [AC_DEFINE([HAS_LOCALE_H])])])])])]) + +AC_CHECK_HEADER([xlocale.h], + [AC_CHECK_FUNC([newlocale], + [AC_CHECK_FUNC([freelocale], + [AC_CHECK_FUNC([uselocale], [AC_DEFINE([HAS_XLOCALE_H])])])])]) + +## strtod_l +# Note: not detected on MSVC so hardcoding the result +# (should be debugged later) +AS_CASE([$host], + [*-pc-windows], [AC_DEFINE([HAS_STRTOD_L])], + [AC_CHECK_FUNC([strtod_l], [AC_DEFINE([HAS_STRTOD_L])])]) + +## shared library support +AS_IF([$shared_libraries_supported], + [AS_CASE([$host], + [*-*-mingw32|*-pc-windows], + [supports_shared_libraries=$shared_libraries_supported; DLLIBS=""], + [AC_CHECK_FUNC([dlopen], + [supports_shared_libraries=true DLLIBS=""], + [AC_CHECK_LIB([dl], [dlopen], + [supports_shared_libraries=true DLLIBS="-ldl $DLLIBS"], + [supports_shared_libraries=false])])])], + [supports_shared_libraries=false]) + +AS_IF([$supports_shared_libraries], + [AC_MSG_NOTICE([Dynamic loading of shared libraries is supported.]) + AC_DEFINE([SUPPORT_DYNAMIC_LINKING])], + [AC_MSG_NOTICE([Dynamic loading of shared libraries is not supported.])]) + +## mmap + +AC_CHECK_HEADER([sys/mman.h], + [AC_CHECK_FUNC([mmap], + [AC_CHECK_FUNC([munmap], [AC_DEFINE([HAS_MMAP])])])]) + +## pwrite + +AC_CHECK_FUNC([pwrite], [AC_DEFINE([HAS_PWRITE])]) + +## -fdebug-prefix-map support by the C compiler +AS_CASE([$CC,$host], + [*,*-*-mingw32], [cc_has_debug_prefix_map=false], + [*,*-pc-windows], [cc_has_debug_prefix_map=false], + [xlc*,powerpc-ibm-aix*], [cc_has_debug_prefix_map=false], + [OCAML_CC_HAS_DEBUG_PREFIX_MAP]) + +## Does stat support nanosecond precision + +AC_CHECK_MEMBER([struct stat.st_atim.tv_nsec], + [stat_has_ns_precision=true + AC_DEFINE([HAS_NANOSECOND_STAT], [1])], + [], + [ + AC_INCLUDES_DEFAULT + #include + ]) + + +AS_IF([! $stat_has_ns_precision], + [AC_CHECK_MEMBER([struct stat.st_atimespec.tv_nsec], + [stat_has_ns_precision=true + AC_DEFINE([HAS_NANOSECOND_STAT], [2])], + [], + [ + AC_INCLUDES_DEFAULT + #include + ])]) + +AS_IF([! $stat_has_ns_precision], + [AC_CHECK_MEMBER([struct stat.st_atimensec], + [stat_has_ns_precision=true + AC_DEFINE([HAS_NANOSECOND_STAT], [3])], + [], + [ + AC_INCLUDES_DEFAULT + #include + ])]) + +AS_IF([$stat_has_ns_precision], + [AC_MSG_NOTICE([stat supports nanosecond precision])], + [AC_MSG_NOTICE([stat does not support nanosecond precision])]) + +# Number of arguments of gethostbyname_r + +AX_FUNC_WHICH_GETHOSTBYNAME_R + +AS_CASE([$ac_cv_func_which_gethostbyname_r], + [six], [AC_DEFINE([HAS_GETHOSTBYNAME_R],[6])], + [five], [AC_DEFINE([HAS_GETHOSTBYNAME_R],[5])], + [three], [AC_MSG_WARN([OCaml does not support this variant])]) + +# Number of arguments of gethostbyaddr_r + +AX_FUNC_WHICH_GETHOSTBYADDR_R + +AS_CASE([$ac_cv_func_which_gethostbyaddr_r], + [eight], [AC_DEFINE([HAS_GETHOSTBYADDR_R],[8])], + [seven], [AC_DEFINE([HAS_GETHOSTBYADDR_R],[7])]) + +## mkstemp + +AC_CHECK_FUNC([mkstemp], [AC_DEFINE([HAS_MKSTEMP])]) + +## nice + +AC_CHECK_FUNC([nice], [AC_DEFINE([HAS_NICE])]) + +## dup3 + +AC_CHECK_FUNC([dup3], [AC_DEFINE([HAS_DUP3])]) + +## pipe2 + +AC_CHECK_FUNC([pipe2], [AC_DEFINE([HAS_PIPE2])]) + +## accept4 + +AC_CHECK_FUNC([accept4], [AC_DEFINE([HAS_ACCEPT4])]) + +## getauxval + +AC_CHECK_FUNC([getauxval], [AC_DEFINE([HAS_GETAUXVAL])]) + +## execvpe + +AC_CHECK_FUNC([execvpe], [AC_DEFINE([HAS_EXECVPE])]) + +## Determine whether the debugger should/can be built + +AS_CASE([$enable_debugger], + [no], + [with_debugger="" + AC_MSG_NOTICE([replay debugger disabled])], + [AS_IF([$sockets], + [with_debugger="ocamldebugger" + AC_MSG_NOTICE([replay debugger supported])], + [with_debugger="" + AC_MSG_NOTICE([replay debugger not supported])]) + ]) + +## Should the runtime with debugging support be built +AS_CASE([$enable_debug_runtime], + [no], [debug_runtime=false], + [debug_runtime=true]) + +## Determine if system stack overflows can be detected + +AC_MSG_CHECKING([whether stack overflows can be detected]) + +AS_CASE([$arch,$system], + [i386,linux_elf|amd64,linux|amd64,macosx|i386,macosx \ + |amd64,openbsd|i386,bsd_elf], + [AC_DEFINE([HAS_STACK_OVERFLOW_DETECTION]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) + +## Determine if the POSIX threads library is supported + +AS_IF([test x"$enable_systhreads" = "xno"], + [systhread_support=false + AC_MSG_NOTICE([the Win32/POSIX threads library is disabled])], + [AS_CASE([$host], + [*-*-mingw32|*-pc-windows], + [systhread_support=true + otherlibraries="$otherlibraries systhreads" + AC_MSG_NOTICE([the Win32 threads library is supported])], + [AX_PTHREAD( + [systhread_support=true + otherlibraries="$otherlibraries systhreads" + AS_CASE([$host], + [*-*-solaris*], [pthread_link="-lpthread -lposix4"], + [*-*-haiku*], [pthread_link=""], + [pthread_link="-lpthread"]) + common_cppflags="$common_cppflags -D_REENTRANT" + AC_MSG_NOTICE([the POSIX threads library is supported]) + saved_CFLAGS="$CFLAGS" + saved_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$LIBS $pthread_link" + AC_CHECK_FUNC([sigwait], [AC_DEFINE([HAS_SIGWAIT])]) + LIBS="$saved_LIBS" + CFLAGS="$saved_CFLAGS"], + [AS_IF([test x"$enable_systhreads" = "xyes"], + [AC_MSG_ERROR([the POSIX thread library is not available])], + [systhread_support=false + AC_MSG_NOTICE([the POSIX threads library is not supported])])])])]) + +## Determine if the bytecode thread library is supported + +AS_IF([test x"$enable_vmthreads" = "xno"], + [AC_MSG_NOTICE([the bytecode threads library is disabled])], + [AS_IF([$select && $setitimer && $gettimeofday && $wait], + [otherlibraries="$otherlibraries threads" + AC_MSG_NOTICE([the bytecode threads library is supported])], + [AS_IF([test x"$enable_vmthreads" = "xyes"], + [AC_MSG_NOTICE([the bytecode threads library is not available])], + [AC_MSG_NOTICE([the bytecode threads library is not supported])])])]) + +## XWindow + +AS_IF([test x"$enable_graph_lib" = "xno" ], + [AC_MSG_NOTICE([the graph library has been disabled])], + [AS_CASE([$host], + [*-*-mingw32|*-pc-windows], [otherlibraries="$otherlibraries win32graph"], + [AC_PATH_X + AS_IF([test -z "$no_x"], + [AS_IF([test -z $x_libraries], + [x_libraries="-lX11"], + [x_libraries="-L$x_libraries -lX11"]) + AC_MSG_NOTICE([X has been found]) + otherlibraries="$otherlibraries graph" + AC_MSG_NOTICE([the graph library will be built])], + [AC_MSG_NOTICE([X has not been found]) + AS_IF([test x"$enable_graph_lib" = "xyes" ], + [AC_MSG_ERROR([can not build the graph library which was requested])], + [AC_MSG_NOTICE([the graph library will not be built])])])])]) + +## libbfd + +AC_CHECK_HEADER([bfd.h], + [libbfd_ling="" + AC_CHECK_LIB([bfd], [bfd_openr], [libbfd_link="-lbfd"]) + AS_IF([test -z "$libbfd_link"], + [AC_CHECK_LIB([bfd], [bfd_openr], [libbfd_link="-lbfd -ldl"], [], [-ldl])]) + AS_IF([test -z "$libbfd_link"], + [AC_CHECK_LIB([bfd], [bfd_openr], + [libbfd_link="-lbfd -ldl -liberty"], [], [-ldl -liberty])]) + AS_IF([test -z "$libbfd_link"], + [AC_CHECK_LIB([bfd], [bfd_openr], + [libbfd_link="-lbfd -ldl -liberty -lz"], [], [-ldl -liberty -lz])]) + AS_IF([test -z "$libbfd_link"], + [AC_CHECK_LIB([bfd], [bfd_openr], + [libbfd_link="-lbfd -ldl -liberty -lz -lintl"], [], + [-ldl -liberty -lz -lintl])]) + AS_IF([test -n "$libbfd_link"], + [AC_DEFINE([HAS_LIBBFD])], + [AC_MSG_NOTICE(m4_normalize([ + BFD library not found, 'objinfo' will be unable to display + info on .cmxs files. + ]))]) + ]) + +## Does the assembler support debug prefix map and CFI directives +as_has_debug_prefix_map=false +asm_cfi_supported=false +AS_IF([$native_compiler], + [AS_CASE([$host], + [*-*-mingw32|*-pc-windows], [], + [OCAML_AS_HAS_DEBUG_PREFIX_MAP + OCAML_AS_HAS_CFI_DIRECTIVES])]) + +## Frame pointers + +AS_IF([test x"$enable_frame_pointers" = "xyes"], + [AS_CASE(["$host,$CC"], + [x86_64-*-linux*,gcc*|x86_64-*-linux*,clang*], + [common_cflags="$common_cflags -g -fno-omit-frame-pointer" + frame_pointers=true + AC_DEFINE([WITH_FRAME_POINTERS]) + AC_MSG_NOTICE([using frame pointers])], + [AC_MSG_ERROR([frame pointers not supported on this platform])] + )], + [AC_MSG_NOTICE([not using frame pointers]) + frame_pointers=false]) + +## No naked pointers + +AS_IF([test x"$enable_naked_pointers" = "xno" ], + [AC_DEFINE([NO_NAKED_POINTERS])]) + +## Check for mmap support for huge pages and contiguous heap +OCAML_MMAP_SUPPORTS_HUGE_PAGES + +# Spacetime profiling, including libunwind detection + +# The number of bits used for profiling information is configurable here. +# The more bits used for profiling, the smaller will be Max_wosize. +# Note that PROFINFO_WIDTH must still be defined even if not configuring +# for Spacetime (see comment in runtime/caml/mlvalues.h on [Profinfo_hd]). +AC_MSG_CHECKING([whether to build spacetime]) +AS_IF([test x"$enable_spacetime" != "xyes" ], + [spacetime=false + call_counts=true # as in original script but should probably be false + libunwind_available=false + libunwind_include_flags= + libunwind_link_flags= + AC_MSG_RESULT([no])], + [AS_CASE([$arch], + [amd64], [spacetime_supported=true], + [spacetime_supported=false]) + AS_IF([$spacetime_supported], + [AC_MSG_RESULT([yes]) + spacetime=true + profinfo=true + profinfo_width=26 + AC_DEFINE([WITH_SPACETIME]) + AS_IF([test x"$enable_call_counts" != "xno"], + [call_counts=true + AC_DEFINE([ENABLE_CALL_COUNTS])], + [call_counts=false]) + AC_MSG_CHECKING([whether to use libunwind]) + AS_IF([test x"$with_libunwind" = "xno"], + [AC_MSG_RESULT([disabled])], + [AS_IF([test x"$with_libunwind" = "x"], + [libunwind_requested=false + AC_MSG_RESULT([if available])], + [libunwind_requested=true + AC_MSG_RESULT([requested]) + AS_IF([test x"$with_libunwind" != "xyes"], + [AS_IF([test x"$LIBUNWIND_INCLUDE_DIR" = "x"], + [LIBUNWIND_INCLUDE_DIR="$with_libunwind/include"]) + AS_IF([test x"$LIBUNWIND_LIB_DIR" = "x"], + [LIBUNWIND_LIB_DIR="$with_libunwind/lib"]) + ]) + ]) + AS_IF([test "$system" = "macosx"], + [AS_IF([test x"$LIBUNWIND_INCLUDE_DIR" != x -o \ + x"$LIBUNWIND_LIB_DIR" != x], + [AC_MSG_WARN(m4_normalize([ + On MacOSX, specifying paths for libunwind headers or libraries + is strongly discouraged. It is recommended to rely on the + defaults provided by the configure script + ]))])]) + + AS_IF([test x"$LIBUNWIND_INCLUDE_DIR" != x], + [libunwind_include_flags="-I$LIBUNWIND_INCLUDE_DIR"], + [libunwind_include_flags=""]) + + AS_CASE(["$system"], + ["macosx"], [libunwind_link_flags="-framework System"], + [libunwind_link_flags="-lunwind -lunwind-x86_64"]) + + AS_IF([test x"$LIBUNWIND_LIB_DIR" != x], + [libunwind_link_flags="-L$LIBUNWIND_LIB_DIR $libunwind_link_flags"]) + + OCAML_CHECK_LIBUNWIND + + AS_IF([$libunwind_requested && ! $libunwind_available], + [AC_MSG_ERROR([libunwind was requested but can not be found])]) + + # We need unwinding information at runtime, but since we use + # -no_compact_unwind, we also need -keep_dwarf_unwind otherwise + # the OS X linker will chuck away the DWARF-like (.eh_frame) + # information. (Older versions of OS X don't provide this.) + + AS_IF([$libunwind_available && test x"$system" = "xmacosx"], + [extra_flags="-Wl,-keep_dwarf_unwind" + mkexe="$mkexe $extra_flags" + mksharedlib="$mksharedlib $extra_flags"])]) + ], + [AS_IF([test x"$enable_spacetime" = "xyes"], + [AC_MSG_RESULT([requested but not supported]) + AC_MSG_ERROR([exiting])], + [AC_MSG_RESULT([no])]) + ]) + ]) + +AC_DEFINE_UNQUOTED([PROFINFO_WIDTH], [$profinfo_width]) +AS_IF([$profinfo], [AC_DEFINE([WITH_PROFINFO])]) + +AS_IF([test x"$enable_installing_bytecode_programs" = "xno"], + [install_bytecode_programs=false], + [install_bytecode_programs=true]) + +AS_IF([test x"$enable_installing_source_artifacts" = "xno"], + [install_source_artifacts=false], + [install_source_artifacts=true]) + +AS_IF([test x"$enable_ocamldoc" = "xno"], + [ocamldoc=""], + [ocamldoc=ocamldoc]) + +AS_IF([test x"$enable_flambda" = "xyes"], + [flambda=true + AS_IF([test x"$enable_flambda_invariants" = "xyes"], + [flambda_invariants=true], + [flambda_invariants=false])], + [flambda=false + flambda_invariants=false]) + +AS_IF([test x"$enable_flat_float_array" = "xno"], + [flat_float_array=false], + [AC_DEFINE([FLAT_FLOAT_ARRAY]) + flat_float_array=true]) + +AS_IF([test x"$with_afl" = "xyes"], + [afl=true], + [afl=false]) + +AS_IF([test x"$enable_force_safe_string" = "xyes"], + [AC_DEFINE([CAML_SAFE_STRING]) + force_safe_string=true], + [force_safe_string=false]) + +AS_IF([test x"$DEFAULT_STRING" = "xunsafe"], + [default_safe_string=false], + [default_safe_string=true]) + +oc_cflags="$common_cflags $internal_cflags" +oc_cppflags="$common_cppflags $internal_cppflags" +ocamlc_cflags="$common_cflags $sharedlib_cflags" +ocamlc_cppflags="$common_cppflags" +ocamlopt_cflags="$common_cflags" +ocamlopt_cppflags="$common_cppflags" +cclibs="$cclibs $mathlib" + +AS_CASE([$host], + [*-*-mingw32], + [bytecclibs="-lws2_32 -lversion" + nativecclibs="-lws2_32 -lversion"], + [*-pc-windows], + [bytecclibs="advapi32.lib ws2_32.lib version.lib" + nativecclibs="advapi32.lib ws2_32.lib version.lib"], + [bytecclibs="$cclibs $DLLIBS $pthread_link $instrumented_runtime_libs" + nativecclibs="$cclibs $DLLIBS"]) + +AS_IF([test x"$libdir" = x'${exec_prefix}/lib'], + [libdir="$libdir"/ocaml]) + +AS_IF([test x"$mandir" = x'${datarootdir}/man'], + [mandir='${prefix}/man']) + +AS_CASE([$host], + [*-*-mingw32|*-pc-windows], + [max_testsuite_dir_retries=1 + AS_CASE([$WINDOWS_UNICODE_MODE], + [ansi], + [windows_unicode=0], + [compatible|""], + [windows_unicode=1], + [AC_MSG_ERROR([unexpected windows unicode mode])])], + [max_testsuite_dir_retries=0 + windows_unicode=0]) + +# Define flexlink chain and flags correctly for the different Windows ports +AS_CASE([$host], + [i686-w64-mingw32], + [flexdll_chain='mingw' + flexlink_flags="-chain $flexdll_chain -stack 16777216"], + [x86_64-w64-mingw32], + [flexdll_chain='mingw64' + flexlink_flags="-chain $flexdll_chain -stack 33554432"], + [i686-pc-windows], + [flexdll_chain='msvc' + flexlink_flags="-merge-manifest -stack 16777216"], + [x86_64-pc-windows], + [flexdll_chain='msvc64' + flexlink_flags="-x64 -merge-manifest -stack 33554432"]) + +# Define default prefix correctly for the different Windows ports +AS_IF([test x"$prefix" = "xNONE"], + [AS_CASE([$host], + [i686-w64-mingw32], [prefix='C:/ocamlmgw'], + [x86_64-w64-mingw32], [prefix='C:/ocamlmgw64'], + [i686-pc-windows], [prefix='C:/ocamlms'], + [x86_64-pc-windows], [prefix='C:/ocamlms64'])]) + +# Define a few macros that were defined in config/m-nt.h +# but whose value is not guessed properly by configure +# (all this should be understood and fixed) +AS_CASE([$host], + [*-*-mingw32|*-pc-windows], + [AC_DEFINE([HAS_BROKEN_PRINTF]) + AC_DEFINE([HAS_STRERROR]) + AC_DEFINE([HAS_IPV6]) + AC_DEFINE([HAS_NICE])]) + +AC_OUTPUT diff --git a/debugger/.depend b/debugger/.depend index 5e1310c4..841f8fe2 100644 --- a/debugger/.depend +++ b/debugger/.depend @@ -1,204 +1,626 @@ -breakpoints.cmo : symbols.cmi pos.cmi parameters.cmi \ - ../bytecomp/instruct.cmi exec.cmi debugcom.cmi checkpoints.cmi \ +breakpoints.cmo : \ + symbols.cmi \ + pos.cmi \ + parameters.cmi \ + ../bytecomp/instruct.cmi \ + exec.cmi \ + debugcom.cmi \ + checkpoints.cmi \ breakpoints.cmi -breakpoints.cmx : symbols.cmx pos.cmx parameters.cmx \ - ../bytecomp/instruct.cmx exec.cmx debugcom.cmx checkpoints.cmx \ +breakpoints.cmx : \ + symbols.cmx \ + pos.cmx \ + parameters.cmx \ + ../bytecomp/instruct.cmx \ + exec.cmx \ + debugcom.cmx \ + checkpoints.cmx \ breakpoints.cmi -breakpoints.cmi : ../bytecomp/instruct.cmi -checkpoints.cmo : primitives.cmi int64ops.cmi debugcom.cmi checkpoints.cmi -checkpoints.cmx : primitives.cmx int64ops.cmx debugcom.cmx checkpoints.cmi -checkpoints.cmi : primitives.cmi debugcom.cmi -command_line.cmo : unix_tools.cmi $(UNIXDIR)/unix.cmi \ - ../typing/types.cmi time_travel.cmi symbols.cmi source.cmi \ - show_source.cmi show_information.cmi question.cmi program_management.cmi \ - program_loading.cmi printval.cmi primitives.cmi pos.cmi parser_aux.cmi \ - parser.cmi parameters.cmi ../utils/misc.cmi ../parsing/longident.cmi \ - ../parsing/location.cmi loadprinter.cmi lexer.cmi int64ops.cmi \ - ../bytecomp/instruct.cmi input_handling.cmi history.cmi frames.cmi \ - events.cmi eval.cmi ../typing/envaux.cmi ../typing/env.cmi \ - debugger_config.cmi debugcom.cmi ../typing/ctype.cmi ../utils/config.cmi \ - checkpoints.cmi breakpoints.cmi command_line.cmi -command_line.cmx : unix_tools.cmx $(UNIXDIR)/unix.cmx \ - ../typing/types.cmx time_travel.cmx symbols.cmx source.cmx \ - show_source.cmx show_information.cmx question.cmx program_management.cmx \ - program_loading.cmx printval.cmx primitives.cmx pos.cmx parser_aux.cmi \ - parser.cmx parameters.cmx ../utils/misc.cmx ../parsing/longident.cmx \ - ../parsing/location.cmx loadprinter.cmx lexer.cmx int64ops.cmx \ - ../bytecomp/instruct.cmx input_handling.cmx history.cmx frames.cmx \ - events.cmx eval.cmx ../typing/envaux.cmx ../typing/env.cmx \ - debugger_config.cmx debugcom.cmx ../typing/ctype.cmx ../utils/config.cmx \ - checkpoints.cmx breakpoints.cmx command_line.cmi +breakpoints.cmi : \ + ../bytecomp/instruct.cmi +checkpoints.cmo : \ + primitives.cmi \ + int64ops.cmi \ + debugcom.cmi \ + checkpoints.cmi +checkpoints.cmx : \ + primitives.cmx \ + int64ops.cmx \ + debugcom.cmx \ + checkpoints.cmi +checkpoints.cmi : \ + primitives.cmi \ + debugcom.cmi +command_line.cmo : \ + unix_tools.cmi \ + $(UNIXDIR)/unix.cmi \ + ../typing/types.cmi \ + time_travel.cmi \ + symbols.cmi \ + source.cmi \ + show_source.cmi \ + show_information.cmi \ + question.cmi \ + program_management.cmi \ + program_loading.cmi \ + printval.cmi \ + primitives.cmi \ + pos.cmi \ + parser_aux.cmi \ + parser.cmi \ + parameters.cmi \ + ../parsing/longident.cmi \ + ../parsing/location.cmi \ + loadprinter.cmi \ + ../utils/load_path.cmi \ + lexer.cmi \ + int64ops.cmi \ + ../bytecomp/instruct.cmi \ + input_handling.cmi \ + history.cmi \ + frames.cmi \ + events.cmi \ + eval.cmi \ + ../typing/envaux.cmi \ + ../typing/env.cmi \ + debugger_config.cmi \ + debugcom.cmi \ + ../typing/ctype.cmi \ + checkpoints.cmi \ + breakpoints.cmi \ + command_line.cmi +command_line.cmx : \ + unix_tools.cmx \ + $(UNIXDIR)/unix.cmx \ + ../typing/types.cmx \ + time_travel.cmx \ + symbols.cmx \ + source.cmx \ + show_source.cmx \ + show_information.cmx \ + question.cmx \ + program_management.cmx \ + program_loading.cmx \ + printval.cmx \ + primitives.cmx \ + pos.cmx \ + parser_aux.cmi \ + parser.cmx \ + parameters.cmx \ + ../parsing/longident.cmx \ + ../parsing/location.cmx \ + loadprinter.cmx \ + ../utils/load_path.cmx \ + lexer.cmx \ + int64ops.cmx \ + ../bytecomp/instruct.cmx \ + input_handling.cmx \ + history.cmx \ + frames.cmx \ + events.cmx \ + eval.cmx \ + ../typing/envaux.cmx \ + ../typing/env.cmx \ + debugger_config.cmx \ + debugcom.cmx \ + ../typing/ctype.cmx \ + checkpoints.cmx \ + breakpoints.cmx \ + command_line.cmi command_line.cmi : -debugcom.cmo : primitives.cmi ../utils/misc.cmi int64ops.cmi \ - input_handling.cmi debugcom.cmi -debugcom.cmx : primitives.cmx ../utils/misc.cmx int64ops.cmx \ - input_handling.cmx debugcom.cmi -debugcom.cmi : primitives.cmi -debugger_config.cmo : int64ops.cmi debugger_config.cmi -debugger_config.cmx : int64ops.cmx debugger_config.cmi +debugcom.cmo : \ + primitives.cmi \ + ../utils/misc.cmi \ + int64ops.cmi \ + input_handling.cmi \ + debugcom.cmi +debugcom.cmx : \ + primitives.cmx \ + ../utils/misc.cmx \ + int64ops.cmx \ + input_handling.cmx \ + debugcom.cmi +debugcom.cmi : \ + primitives.cmi +debugger_config.cmo : \ + int64ops.cmi \ + debugger_config.cmi +debugger_config.cmx : \ + int64ops.cmx \ + debugger_config.cmi debugger_config.cmi : -eval.cmo : ../typing/types.cmi ../bytecomp/symtable.cmi ../typing/subst.cmi \ - printval.cmi ../typing/printtyp.cmi ../typing/predef.cmi \ - ../typing/path.cmi parser_aux.cmi ../utils/misc.cmi \ - ../parsing/longident.cmi ../bytecomp/instruct.cmi ../typing/ident.cmi \ - frames.cmi ../typing/env.cmi debugcom.cmi ../typing/ctype.cmi \ - ../typing/btype.cmi eval.cmi -eval.cmx : ../typing/types.cmx ../bytecomp/symtable.cmx ../typing/subst.cmx \ - printval.cmx ../typing/printtyp.cmx ../typing/predef.cmx \ - ../typing/path.cmx parser_aux.cmi ../utils/misc.cmx \ - ../parsing/longident.cmx ../bytecomp/instruct.cmx ../typing/ident.cmx \ - frames.cmx ../typing/env.cmx debugcom.cmx ../typing/ctype.cmx \ - ../typing/btype.cmx eval.cmi -eval.cmi : ../typing/types.cmi ../typing/path.cmi parser_aux.cmi \ - ../parsing/longident.cmi ../bytecomp/instruct.cmi ../typing/ident.cmi \ - ../typing/env.cmi debugcom.cmi -events.cmo : ../parsing/location.cmi ../bytecomp/instruct.cmi events.cmi -events.cmx : ../parsing/location.cmx ../bytecomp/instruct.cmx events.cmi -events.cmi : ../bytecomp/instruct.cmi -exec.cmo : exec.cmi -exec.cmx : exec.cmi +eval.cmo : \ + ../typing/types.cmi \ + ../bytecomp/symtable.cmi \ + ../typing/subst.cmi \ + printval.cmi \ + ../typing/printtyp.cmi \ + ../typing/predef.cmi \ + ../typing/path.cmi \ + parser_aux.cmi \ + ../utils/misc.cmi \ + ../parsing/longident.cmi \ + ../bytecomp/instruct.cmi \ + ../typing/ident.cmi \ + frames.cmi \ + ../typing/env.cmi \ + debugcom.cmi \ + ../typing/ctype.cmi \ + ../typing/btype.cmi \ + eval.cmi +eval.cmx : \ + ../typing/types.cmx \ + ../bytecomp/symtable.cmx \ + ../typing/subst.cmx \ + printval.cmx \ + ../typing/printtyp.cmx \ + ../typing/predef.cmx \ + ../typing/path.cmx \ + parser_aux.cmi \ + ../utils/misc.cmx \ + ../parsing/longident.cmx \ + ../bytecomp/instruct.cmx \ + ../typing/ident.cmx \ + frames.cmx \ + ../typing/env.cmx \ + debugcom.cmx \ + ../typing/ctype.cmx \ + ../typing/btype.cmx \ + eval.cmi +eval.cmi : \ + ../typing/types.cmi \ + ../typing/path.cmi \ + parser_aux.cmi \ + ../parsing/longident.cmi \ + ../bytecomp/instruct.cmi \ + ../typing/ident.cmi \ + ../typing/env.cmi \ + debugcom.cmi +events.cmo : \ + ../parsing/location.cmi \ + ../bytecomp/instruct.cmi \ + events.cmi +events.cmx : \ + ../parsing/location.cmx \ + ../bytecomp/instruct.cmx \ + events.cmi +events.cmi : \ + ../bytecomp/instruct.cmi +exec.cmo : \ + exec.cmi +exec.cmx : \ + exec.cmi exec.cmi : -frames.cmo : symbols.cmi ../utils/misc.cmi ../bytecomp/instruct.cmi \ - events.cmi debugcom.cmi frames.cmi -frames.cmx : symbols.cmx ../utils/misc.cmx ../bytecomp/instruct.cmx \ - events.cmx debugcom.cmx frames.cmi -frames.cmi : ../bytecomp/instruct.cmi -history.cmo : primitives.cmi int64ops.cmi debugger_config.cmi \ - checkpoints.cmi history.cmi -history.cmx : primitives.cmx int64ops.cmx debugger_config.cmx \ - checkpoints.cmx history.cmi +frames.cmo : \ + symbols.cmi \ + ../utils/misc.cmi \ + ../bytecomp/instruct.cmi \ + events.cmi \ + debugcom.cmi \ + frames.cmi +frames.cmx : \ + symbols.cmx \ + ../utils/misc.cmx \ + ../bytecomp/instruct.cmx \ + events.cmx \ + debugcom.cmx \ + frames.cmi +frames.cmi : \ + ../bytecomp/instruct.cmi +history.cmo : \ + primitives.cmi \ + int64ops.cmi \ + debugger_config.cmi \ + checkpoints.cmi \ + history.cmi +history.cmx : \ + primitives.cmx \ + int64ops.cmx \ + debugger_config.cmx \ + checkpoints.cmx \ + history.cmi history.cmi : -input_handling.cmo : $(UNIXDIR)/unix.cmi primitives.cmi \ - parameters.cmi input_handling.cmi -input_handling.cmx : $(UNIXDIR)/unix.cmx primitives.cmx \ - parameters.cmx input_handling.cmi -input_handling.cmi : primitives.cmi -int64ops.cmo : int64ops.cmi -int64ops.cmx : int64ops.cmi +input_handling.cmo : \ + $(UNIXDIR)/unix.cmi \ + primitives.cmi \ + parameters.cmi \ + input_handling.cmi +input_handling.cmx : \ + $(UNIXDIR)/unix.cmx \ + primitives.cmx \ + parameters.cmx \ + input_handling.cmi +input_handling.cmi : \ + primitives.cmi +int64ops.cmo : \ + int64ops.cmi +int64ops.cmx : \ + int64ops.cmi int64ops.cmi : -lexer.cmo : parser.cmi lexer.cmi -lexer.cmx : parser.cmx lexer.cmi -lexer.cmi : parser.cmi -loadprinter.cmo : ../typing/types.cmi ../bytecomp/symtable.cmi printval.cmi \ - ../typing/printtyp.cmi ../typing/path.cmi parameters.cmi \ - ../utils/misc.cmi ../parsing/longident.cmi ../parsing/location.cmi \ - ../typing/ident.cmi ../typing/env.cmi ../typing/ctype.cmi \ - ../utils/config.cmi ../driver/compdynlink.cmi loadprinter.cmi -loadprinter.cmx : ../typing/types.cmx ../bytecomp/symtable.cmx printval.cmx \ - ../typing/printtyp.cmx ../typing/path.cmx parameters.cmx \ - ../utils/misc.cmx ../parsing/longident.cmx ../parsing/location.cmx \ - ../typing/ident.cmx ../typing/env.cmx ../typing/ctype.cmx \ - ../utils/config.cmx ../driver/compdynlink.cmi loadprinter.cmi -loadprinter.cmi : ../parsing/longident.cmi ../driver/compdynlink.cmi -main.cmo : unix_tools.cmi $(UNIXDIR)/unix.cmi time_travel.cmi \ - show_information.cmi question.cmi program_management.cmi primitives.cmi \ - parameters.cmi ../utils/misc.cmi loadprinter.cmi input_handling.cmi \ - frames.cmi exec.cmi ../typing/env.cmi debugger_config.cmi \ - ../utils/config.cmi command_line.cmi ../typing/cmi_format.cmi \ - ../utils/clflags.cmi checkpoints.cmi -main.cmx : unix_tools.cmx $(UNIXDIR)/unix.cmx time_travel.cmx \ - show_information.cmx question.cmx program_management.cmx primitives.cmx \ - parameters.cmx ../utils/misc.cmx loadprinter.cmx input_handling.cmx \ - frames.cmx exec.cmx ../typing/env.cmx debugger_config.cmx \ - ../utils/config.cmx command_line.cmx ../typing/cmi_format.cmx \ - ../utils/clflags.cmx checkpoints.cmx -parameters.cmo : primitives.cmi ../typing/envaux.cmi debugger_config.cmi \ - ../utils/config.cmi parameters.cmi -parameters.cmx : primitives.cmx ../typing/envaux.cmx debugger_config.cmx \ - ../utils/config.cmx parameters.cmi +lexer.cmo : \ + parser.cmi \ + lexer.cmi +lexer.cmx : \ + parser.cmx \ + lexer.cmi +lexer.cmi : \ + parser.cmi +loadprinter.cmo : \ + ../typing/types.cmi \ + ../bytecomp/symtable.cmi \ + printval.cmi \ + ../typing/printtyp.cmi \ + ../typing/path.cmi \ + parameters.cmi \ + ../utils/misc.cmi \ + ../parsing/longident.cmi \ + ../utils/load_path.cmi \ + ../typing/env.cmi \ + ../typing/ctype.cmi \ + ../driver/compdynlink.cmi \ + loadprinter.cmi +loadprinter.cmx : \ + ../typing/types.cmx \ + ../bytecomp/symtable.cmx \ + printval.cmx \ + ../typing/printtyp.cmx \ + ../typing/path.cmx \ + parameters.cmx \ + ../utils/misc.cmx \ + ../parsing/longident.cmx \ + ../utils/load_path.cmx \ + ../typing/env.cmx \ + ../typing/ctype.cmx \ + ../driver/compdynlink.cmi \ + loadprinter.cmi +loadprinter.cmi : \ + ../parsing/longident.cmi \ + ../driver/compdynlink.cmi +main.cmo : \ + unix_tools.cmi \ + $(UNIXDIR)/unix.cmi \ + time_travel.cmi \ + show_information.cmi \ + question.cmi \ + program_management.cmi \ + primitives.cmi \ + parameters.cmi \ + ../utils/misc.cmi \ + loadprinter.cmi \ + ../utils/load_path.cmi \ + input_handling.cmi \ + frames.cmi \ + exec.cmi \ + ../typing/env.cmi \ + debugger_config.cmi \ + ../utils/config.cmi \ + command_line.cmi \ + ../typing/cmi_format.cmi \ + ../utils/clflags.cmi \ + checkpoints.cmi +main.cmx : \ + unix_tools.cmx \ + $(UNIXDIR)/unix.cmx \ + time_travel.cmx \ + show_information.cmx \ + question.cmx \ + program_management.cmx \ + primitives.cmx \ + parameters.cmx \ + ../utils/misc.cmx \ + loadprinter.cmx \ + ../utils/load_path.cmx \ + input_handling.cmx \ + frames.cmx \ + exec.cmx \ + ../typing/env.cmx \ + debugger_config.cmx \ + ../utils/config.cmx \ + command_line.cmx \ + ../typing/cmi_format.cmx \ + ../utils/clflags.cmx \ + checkpoints.cmx +parameters.cmo : \ + ../utils/load_path.cmi \ + ../typing/envaux.cmi \ + debugger_config.cmi \ + ../utils/config.cmi \ + parameters.cmi +parameters.cmx : \ + ../utils/load_path.cmx \ + ../typing/envaux.cmx \ + debugger_config.cmx \ + ../utils/config.cmx \ + parameters.cmi parameters.cmi : -parser.cmo : parser_aux.cmi ../parsing/longident.cmi int64ops.cmi \ - input_handling.cmi parser.cmi -parser.cmx : parser_aux.cmi ../parsing/longident.cmx int64ops.cmx \ - input_handling.cmx parser.cmi -parser.cmi : parser_aux.cmi ../parsing/longident.cmi -parser_aux.cmi : ../parsing/longident.cmi -pattern_matching.cmo : ../typing/typedtree.cmi parser_aux.cmi \ - ../utils/misc.cmi debugger_config.cmi debugcom.cmi ../typing/ctype.cmi \ +parser.cmo : \ + parser_aux.cmi \ + ../parsing/longident.cmi \ + int64ops.cmi \ + input_handling.cmi \ + parser.cmi +parser.cmx : \ + parser_aux.cmi \ + ../parsing/longident.cmx \ + int64ops.cmx \ + input_handling.cmx \ + parser.cmi +parser.cmi : \ + parser_aux.cmi \ + ../parsing/longident.cmi +parser_aux.cmi : \ + ../parsing/longident.cmi +pattern_matching.cmo : \ + ../typing/typedtree.cmi \ + parser_aux.cmi \ + ../utils/misc.cmi \ + debugger_config.cmi \ + debugcom.cmi \ + ../typing/ctype.cmi \ pattern_matching.cmi -pattern_matching.cmx : ../typing/typedtree.cmx parser_aux.cmi \ - ../utils/misc.cmx debugger_config.cmx debugcom.cmx ../typing/ctype.cmx \ +pattern_matching.cmx : \ + ../typing/typedtree.cmx \ + parser_aux.cmi \ + ../utils/misc.cmx \ + debugger_config.cmx \ + debugcom.cmx \ + ../typing/ctype.cmx \ pattern_matching.cmi -pattern_matching.cmi : ../typing/typedtree.cmi parser_aux.cmi debugcom.cmi -pos.cmo : ../parsing/location.cmi ../bytecomp/instruct.cmi pos.cmi -pos.cmx : ../parsing/location.cmx ../bytecomp/instruct.cmx pos.cmi -pos.cmi : ../bytecomp/instruct.cmi -primitives.cmo : $(UNIXDIR)/unix.cmi primitives.cmi -primitives.cmx : $(UNIXDIR)/unix.cmx primitives.cmi -primitives.cmi : $(UNIXDIR)/unix.cmi -printval.cmo : ../typing/types.cmi ../bytecomp/symtable.cmi \ - ../typing/printtyp.cmi ../typing/path.cmi parser_aux.cmi \ - ../typing/outcometree.cmi ../typing/oprint.cmi \ - ../toplevel/genprintval.cmi debugcom.cmi printval.cmi -printval.cmx : ../typing/types.cmx ../bytecomp/symtable.cmx \ - ../typing/printtyp.cmx ../typing/path.cmx parser_aux.cmi \ - ../typing/outcometree.cmi ../typing/oprint.cmx \ - ../toplevel/genprintval.cmx debugcom.cmx printval.cmi -printval.cmi : ../typing/types.cmi ../typing/path.cmi parser_aux.cmi \ - ../typing/env.cmi debugcom.cmi -program_loading.cmo : unix_tools.cmi $(UNIXDIR)/unix.cmi \ - primitives.cmi parameters.cmi input_handling.cmi debugger_config.cmi \ +pattern_matching.cmi : \ + ../typing/typedtree.cmi \ + parser_aux.cmi \ + debugcom.cmi +pos.cmo : \ + ../parsing/location.cmi \ + ../bytecomp/instruct.cmi \ + pos.cmi +pos.cmx : \ + ../parsing/location.cmx \ + ../bytecomp/instruct.cmx \ + pos.cmi +pos.cmi : \ + ../bytecomp/instruct.cmi +primitives.cmo : \ + $(UNIXDIR)/unix.cmi \ + primitives.cmi +primitives.cmx : \ + $(UNIXDIR)/unix.cmx \ + primitives.cmi +primitives.cmi : \ + $(UNIXDIR)/unix.cmi +printval.cmo : \ + ../typing/types.cmi \ + ../bytecomp/symtable.cmi \ + ../typing/printtyp.cmi \ + parser_aux.cmi \ + ../typing/outcometree.cmi \ + ../typing/oprint.cmi \ + ../toplevel/genprintval.cmi \ + ../typing/env.cmi \ + debugcom.cmi \ + printval.cmi +printval.cmx : \ + ../typing/types.cmx \ + ../bytecomp/symtable.cmx \ + ../typing/printtyp.cmx \ + parser_aux.cmi \ + ../typing/outcometree.cmi \ + ../typing/oprint.cmx \ + ../toplevel/genprintval.cmx \ + ../typing/env.cmx \ + debugcom.cmx \ + printval.cmi +printval.cmi : \ + ../typing/types.cmi \ + ../typing/path.cmi \ + parser_aux.cmi \ + ../typing/env.cmi \ + debugcom.cmi +program_loading.cmo : \ + unix_tools.cmi \ + $(UNIXDIR)/unix.cmi \ + primitives.cmi \ + parameters.cmi \ + input_handling.cmi \ + debugger_config.cmi \ program_loading.cmi -program_loading.cmx : unix_tools.cmx $(UNIXDIR)/unix.cmx \ - primitives.cmx parameters.cmx input_handling.cmx debugger_config.cmx \ +program_loading.cmx : \ + unix_tools.cmx \ + $(UNIXDIR)/unix.cmx \ + primitives.cmx \ + parameters.cmx \ + input_handling.cmx \ + debugger_config.cmx \ program_loading.cmi -program_loading.cmi : primitives.cmi -program_management.cmo : unix_tools.cmi $(UNIXDIR)/unix.cmi \ - time_travel.cmi symbols.cmi question.cmi program_loading.cmi \ - primitives.cmi parameters.cmi int64ops.cmi input_handling.cmi history.cmi \ - ../typing/envaux.cmi debugger_config.cmi ../utils/config.cmi \ - breakpoints.cmi program_management.cmi -program_management.cmx : unix_tools.cmx $(UNIXDIR)/unix.cmx \ - time_travel.cmx symbols.cmx question.cmx program_loading.cmx \ - primitives.cmx parameters.cmx int64ops.cmx input_handling.cmx history.cmx \ - ../typing/envaux.cmx debugger_config.cmx ../utils/config.cmx \ - breakpoints.cmx program_management.cmi +program_loading.cmi : \ + primitives.cmi +program_management.cmo : \ + unix_tools.cmi \ + $(UNIXDIR)/unix.cmi \ + time_travel.cmi \ + symbols.cmi \ + question.cmi \ + program_loading.cmi \ + primitives.cmi \ + parameters.cmi \ + ../utils/load_path.cmi \ + int64ops.cmi \ + input_handling.cmi \ + history.cmi \ + ../typing/envaux.cmi \ + debugger_config.cmi \ + breakpoints.cmi \ + program_management.cmi +program_management.cmx : \ + unix_tools.cmx \ + $(UNIXDIR)/unix.cmx \ + time_travel.cmx \ + symbols.cmx \ + question.cmx \ + program_loading.cmx \ + primitives.cmx \ + parameters.cmx \ + ../utils/load_path.cmx \ + int64ops.cmx \ + input_handling.cmx \ + history.cmx \ + ../typing/envaux.cmx \ + debugger_config.cmx \ + breakpoints.cmx \ + program_management.cmi program_management.cmi : -question.cmo : primitives.cmi lexer.cmi input_handling.cmi question.cmi -question.cmx : primitives.cmx lexer.cmx input_handling.cmx question.cmi +question.cmo : \ + primitives.cmi \ + lexer.cmi \ + input_handling.cmi \ + question.cmi +question.cmx : \ + primitives.cmx \ + lexer.cmx \ + input_handling.cmx \ + question.cmi question.cmi : -show_information.cmo : symbols.cmi source.cmi show_source.cmi printval.cmi \ - parameters.cmi ../utils/misc.cmi ../bytecomp/instruct.cmi frames.cmi \ - events.cmi debugcom.cmi checkpoints.cmi breakpoints.cmi \ +show_information.cmo : \ + symbols.cmi \ + source.cmi \ + show_source.cmi \ + printval.cmi \ + parameters.cmi \ + ../utils/misc.cmi \ + ../bytecomp/instruct.cmi \ + frames.cmi \ + events.cmi \ + debugcom.cmi \ + checkpoints.cmi \ + breakpoints.cmi \ show_information.cmi -show_information.cmx : symbols.cmx source.cmx show_source.cmx printval.cmx \ - parameters.cmx ../utils/misc.cmx ../bytecomp/instruct.cmx frames.cmx \ - events.cmx debugcom.cmx checkpoints.cmx breakpoints.cmx \ +show_information.cmx : \ + symbols.cmx \ + source.cmx \ + show_source.cmx \ + printval.cmx \ + parameters.cmx \ + ../utils/misc.cmx \ + ../bytecomp/instruct.cmx \ + frames.cmx \ + events.cmx \ + debugcom.cmx \ + checkpoints.cmx \ + breakpoints.cmx \ show_information.cmi -show_information.cmi : ../bytecomp/instruct.cmi -show_source.cmo : source.cmi primitives.cmi parameters.cmi \ - ../parsing/location.cmi ../bytecomp/instruct.cmi events.cmi \ - debugger_config.cmi show_source.cmi -show_source.cmx : source.cmx primitives.cmx parameters.cmx \ - ../parsing/location.cmx ../bytecomp/instruct.cmx events.cmx \ - debugger_config.cmx show_source.cmi -show_source.cmi : ../bytecomp/instruct.cmi -source.cmo : primitives.cmi ../utils/misc.cmi debugger_config.cmi \ - ../utils/config.cmi source.cmi -source.cmx : primitives.cmx ../utils/misc.cmx debugger_config.cmx \ - ../utils/config.cmx source.cmi +show_information.cmi : \ + ../bytecomp/instruct.cmi +show_source.cmo : \ + source.cmi \ + primitives.cmi \ + parameters.cmi \ + ../parsing/location.cmi \ + ../bytecomp/instruct.cmi \ + events.cmi \ + debugger_config.cmi \ + show_source.cmi +show_source.cmx : \ + source.cmx \ + primitives.cmx \ + parameters.cmx \ + ../parsing/location.cmx \ + ../bytecomp/instruct.cmx \ + events.cmx \ + debugger_config.cmx \ + show_source.cmi +show_source.cmi : \ + ../bytecomp/instruct.cmi +source.cmo : \ + primitives.cmi \ + ../utils/misc.cmi \ + ../utils/load_path.cmi \ + debugger_config.cmi \ + source.cmi +source.cmx : \ + primitives.cmx \ + ../utils/misc.cmx \ + ../utils/load_path.cmx \ + debugger_config.cmx \ + source.cmi source.cmi : -symbols.cmo : ../bytecomp/symtable.cmi program_loading.cmi \ - ../bytecomp/instruct.cmi events.cmi debugger_config.cmi debugcom.cmi \ - checkpoints.cmi ../bytecomp/bytesections.cmi symbols.cmi -symbols.cmx : ../bytecomp/symtable.cmx program_loading.cmx \ - ../bytecomp/instruct.cmx events.cmx debugger_config.cmx debugcom.cmx \ - checkpoints.cmx ../bytecomp/bytesections.cmx symbols.cmi -symbols.cmi : ../bytecomp/instruct.cmi -time_travel.cmo : trap_barrier.cmi symbols.cmi question.cmi \ - program_loading.cmi primitives.cmi ../utils/misc.cmi int64ops.cmi \ - ../bytecomp/instruct.cmi input_handling.cmi exec.cmi events.cmi \ - debugger_config.cmi debugcom.cmi checkpoints.cmi breakpoints.cmi \ +symbols.cmo : \ + ../bytecomp/symtable.cmi \ + program_loading.cmi \ + ../utils/misc.cmi \ + ../bytecomp/instruct.cmi \ + events.cmi \ + debugger_config.cmi \ + debugcom.cmi \ + checkpoints.cmi \ + ../bytecomp/bytesections.cmi \ + symbols.cmi +symbols.cmx : \ + ../bytecomp/symtable.cmx \ + program_loading.cmx \ + ../utils/misc.cmx \ + ../bytecomp/instruct.cmx \ + events.cmx \ + debugger_config.cmx \ + debugcom.cmx \ + checkpoints.cmx \ + ../bytecomp/bytesections.cmx \ + symbols.cmi +symbols.cmi : \ + ../bytecomp/instruct.cmi +time_travel.cmo : \ + trap_barrier.cmi \ + symbols.cmi \ + question.cmi \ + program_loading.cmi \ + primitives.cmi \ + ../utils/misc.cmi \ + int64ops.cmi \ + ../bytecomp/instruct.cmi \ + input_handling.cmi \ + exec.cmi \ + events.cmi \ + debugger_config.cmi \ + debugcom.cmi \ + checkpoints.cmi \ + breakpoints.cmi \ time_travel.cmi -time_travel.cmx : trap_barrier.cmx symbols.cmx question.cmx \ - program_loading.cmx primitives.cmx ../utils/misc.cmx int64ops.cmx \ - ../bytecomp/instruct.cmx input_handling.cmx exec.cmx events.cmx \ - debugger_config.cmx debugcom.cmx checkpoints.cmx breakpoints.cmx \ +time_travel.cmx : \ + trap_barrier.cmx \ + symbols.cmx \ + question.cmx \ + program_loading.cmx \ + primitives.cmx \ + ../utils/misc.cmx \ + int64ops.cmx \ + ../bytecomp/instruct.cmx \ + input_handling.cmx \ + exec.cmx \ + events.cmx \ + debugger_config.cmx \ + debugcom.cmx \ + checkpoints.cmx \ + breakpoints.cmx \ time_travel.cmi -time_travel.cmi : primitives.cmi -trap_barrier.cmo : exec.cmi debugcom.cmi checkpoints.cmi trap_barrier.cmi -trap_barrier.cmx : exec.cmx debugcom.cmx checkpoints.cmx trap_barrier.cmi +time_travel.cmi : \ + primitives.cmi +trap_barrier.cmo : \ + exec.cmi \ + debugcom.cmi \ + checkpoints.cmi \ + trap_barrier.cmi +trap_barrier.cmx : \ + exec.cmx \ + debugcom.cmx \ + checkpoints.cmx \ + trap_barrier.cmi trap_barrier.cmi : -unix_tools.cmo : $(UNIXDIR)/unix.cmi ../utils/misc.cmi unix_tools.cmi -unix_tools.cmx : $(UNIXDIR)/unix.cmx ../utils/misc.cmx unix_tools.cmi -unix_tools.cmi : $(UNIXDIR)/unix.cmi +unix_tools.cmo : \ + $(UNIXDIR)/unix.cmi \ + ../utils/misc.cmi \ + unix_tools.cmi +unix_tools.cmx : \ + $(UNIXDIR)/unix.cmx \ + ../utils/misc.cmx \ + unix_tools.cmi +unix_tools.cmi : \ + $(UNIXDIR)/unix.cmi diff --git a/debugger/Makefile b/debugger/Makefile index 571e91bb..4d7a0966 100644 --- a/debugger/Makefile +++ b/debugger/Makefile @@ -13,88 +13,68 @@ #* * #************************************************************************** -include ../config/Makefile -include ../Makefile.common +ROOTDIR = .. -UNIXDIR=../otherlibs/$(UNIXLIB) -CAMLRUN ?= ../boot/ocamlrun -CAMLYACC ?= ../boot/ocamlyacc +include $(ROOTDIR)/Makefile.config +include $(ROOTDIR)/Makefile.common -CAMLC=$(CAMLRUN) ../ocamlc -nostdlib -I ../stdlib +UNIXDIR=$(ROOTDIR)/otherlibs/$(UNIXLIB) +CAMLRUN ?= $(ROOTDIR)/boot/ocamlrun +CAMLYACC ?= $(ROOTDIR)/yacc/ocamlyacc$(EXE) + +CAMLC=$(CAMLRUN) $(ROOTDIR)/ocamlc -g -nostdlib -I $(ROOTDIR)/stdlib COMPFLAGS=$(INCLUDES) -absname -w +a-4-9-41-42-44-45-48 -warn-error A \ -safe-string -strict-sequence -strict-formats LINKFLAGS=-linkall -I $(UNIXDIR) YACCFLAGS= -CAMLLEX=$(CAMLRUN) ../boot/ocamllex -CAMLDEP=$(CAMLRUN) ../tools/ocamldep -DEPFLAGS=$(INCLUDES) - -INCLUDES=\ - -I ../utils -I ../parsing -I ../typing -I ../bytecomp -I ../toplevel \ - -I ../driver -I $(UNIXDIR) - -OTHEROBJS=\ - $(UNIXDIR)/unix.cma \ - ../utils/config.cmo ../utils/tbl.cmo ../utils/misc.cmo \ - ../utils/identifiable.cmo ../utils/numbers.cmo \ - ../utils/arg_helper.cmo ../utils/clflags.cmo \ - ../utils/consistbl.cmo ../utils/warnings.cmo \ - ../utils/build_path_prefix_map.cmo \ - ../utils/terminfo.cmo \ - ../parsing/location.cmo ../parsing/longident.cmo ../parsing/docstrings.cmo \ - ../parsing/syntaxerr.cmo \ - ../parsing/ast_helper.cmo ../parsing/ast_mapper.cmo \ - ../parsing/ast_iterator.cmo ../parsing/attr_helper.cmo \ - ../parsing/builtin_attributes.cmo \ - ../typing/ident.cmo ../typing/path.cmo ../typing/types.cmo \ - ../typing/btype.cmo ../typing/primitive.cmo ../typing/typedtree.cmo \ - ../typing/subst.cmo ../typing/predef.cmo \ - ../typing/datarepr.cmo ../typing/cmi_format.cmo ../typing/env.cmo \ - ../typing/oprint.cmo \ - ../typing/ctype.cmo ../typing/printtyp.cmo ../typing/mtype.cmo \ - ../typing/envaux.cmo \ - ../bytecomp/runtimedef.cmo ../bytecomp/bytesections.cmo \ - ../bytecomp/dll.cmo ../bytecomp/meta.cmo ../bytecomp/symtable.cmo \ - ../bytecomp/opcodes.cmo ../driver/compdynlink.cmo \ - ../toplevel/genprintval.cmo - - -OBJS=\ - int64ops.cmo \ - primitives.cmo \ - unix_tools.cmo \ - debugger_config.cmo \ - parameters.cmo \ - lexer.cmo \ - input_handling.cmo \ - question.cmo \ - debugcom.cmo \ - exec.cmo \ - source.cmo \ - pos.cmo \ - checkpoints.cmo \ - events.cmo \ - program_loading.cmo \ - symbols.cmo \ - breakpoints.cmo \ - trap_barrier.cmo \ - history.cmo \ - printval.cmo \ - show_source.cmo \ - time_travel.cmo \ - program_management.cmo \ - frames.cmo \ - eval.cmo \ - show_information.cmo \ - loadprinter.cmo \ - parser.cmo \ - command_line.cmo \ - main.cmo +CAMLLEX=$(CAMLRUN) $(ROOTDIR)/boot/ocamllex +CAMLDEP=$(CAMLRUN) $(ROOTDIR)/boot/ocamlc -depend +DEPFLAGS=-slash +DEPINCLUDES=$(INCLUDES) + +DIRECTORIES=$(UNIXDIR) $(addprefix $(ROOTDIR)/,\ + utils parsing typing bytecomp toplevel driver) + +INCLUDES=$(addprefix -I ,$(DIRECTORIES)) + +utils_modules := $(addprefix utils/,\ + config build_path_prefix_map misc identifiable numbers arg_helper clflags \ + consistbl warnings terminfo load_path) + +parsing_modules := $(addprefix parsing/,\ + location longident docstrings syntaxerr ast_helper ast_mapper ast_iterator \ + attr_helper builtin_attributes pprintast) + +typing_modules := $(addprefix typing/,\ + ident path types btype primitive typedtree subst predef datarepr \ + cmi_format env oprint ctype printtyp mtype envaux) + +bytecomp_modules := $(addprefix bytecomp/,\ + runtimedef bytesections dll meta symtable opcodes) + +other_compiler_modules := driver/compdynlink_types \ + driver/compdynlink_platform_intf \ + driver/compdynlink_common driver/compdynlink toplevel/genprintval + +compiler_modules := $(addprefix $(ROOTDIR)/,\ + $(utils_modules) $(parsing_modules) $(typing_modules) \ + $(bytecomp_modules) $(other_compiler_modules)) + +debugger_modules := \ + int64ops primitives unix_tools debugger_config parameters lexer \ + input_handling question debugcom exec source pos checkpoints events \ + program_loading symbols breakpoints trap_barrier history printval \ + show_source time_travel program_management frames eval \ + show_information loadprinter parser command_line main + +all_modules := $(compiler_modules) $(debugger_modules) + +all_objects := $(addsuffix .cmo,$(all_modules)) all: ocamldebug$(EXE) -ocamldebug$(EXE): $(OBJS) $(OTHEROBJS) - $(CAMLC) $(LINKFLAGS) -o ocamldebug$(EXE) -linkall $(OTHEROBJS) $(OBJS) +ocamldebug$(EXE): $(UNIXDIR)/unix.cma $(all_objects) + $(CAMLC) $(LINKFLAGS) -o $@ -linkall $^ install: $(INSTALL_PROG) ocamldebug$(EXE) "$(INSTALL_BINDIR)/ocamldebug$(EXE)" @@ -113,7 +93,7 @@ clean:: $(CAMLC) -c $(COMPFLAGS) $< depend: beforedepend - $(CAMLDEP) -slash $(DEPFLAGS) *.mli *.ml \ + $(CAMLDEP) $(DEPFLAGS) $(DEPINCLUDES) *.mli *.ml \ | sed -e 's,$(UNIXDIR)/,$$(UNIXDIR)/,' > .depend lexer.ml: lexer.mll diff --git a/debugger/Makefile.nt b/debugger/Makefile.nt deleted file mode 100644 index ed9900bb..00000000 --- a/debugger/Makefile.nt +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include Makefile diff --git a/debugger/breakpoints.ml b/debugger/breakpoints.ml index 62e8ecfb..4751bde6 100644 --- a/debugger/breakpoints.ml +++ b/debugger/breakpoints.ml @@ -193,7 +193,7 @@ let remove_breakpoint number = ) with Not_found -> - prerr_endline ("No breakpoint number " ^ (string_of_int number) ^ "."); + prerr_endline ("No breakpoint number " ^ (Int.to_string number) ^ "."); raise Not_found let remove_all_breakpoints () = diff --git a/debugger/command_line.ml b/debugger/command_line.ml index 8c1c9760..0cd25ccb 100644 --- a/debugger/command_line.ml +++ b/debugger/command_line.ml @@ -18,7 +18,6 @@ open Int64ops open Format -open Misc open Instruct open Unix open Debugger_config @@ -263,7 +262,7 @@ let instr_dir ppf lexbuf = let new_directory = argument_list_eol argument lexbuf in if new_directory = [] then begin if yes_or_no "Reinitialize directory list" then begin - Config.load_path := !default_load_path; + Load_path.init !default_load_path; Envaux.reset_cache (); Hashtbl.clear Debugger_config.load_path_for; flush_buffer_list () @@ -279,7 +278,7 @@ let instr_dir ppf lexbuf = List.iter (function x -> add_path (expand_path x)) new_directory' end; let print_dirs ppf l = List.iter (function x -> fprintf ppf "@ %s" x) l in - fprintf ppf "@[<2>Directories: %a@]@." print_dirs !Config.load_path; + fprintf ppf "@[<2>Directories: %a@]@." print_dirs (Load_path.get_paths ()); Hashtbl.iter (fun mdl dirs -> fprintf ppf "@[<2>Source directories for %s: %a@]@." mdl print_dirs @@ -562,7 +561,7 @@ let instr_source ppf lexbuf = let io_chan = try io_channel_of_descr - (openfile (find_in_path !Config.load_path (expand_path file)) + (openfile (Load_path.find (expand_path file)) [O_RDONLY] 0) with | Not_found -> error "Source file not found." @@ -695,7 +694,7 @@ let instr_frame ppf lexbuf = show_current_frame ppf true with | Not_found -> - error ("No frame number " ^ string_of_int frame_number ^ ".") + error ("No frame number " ^ Int.to_string frame_number ^ ".") let instr_backtrace ppf lexbuf = let number = @@ -983,7 +982,7 @@ let info_events _ppf lexbuf = (match ev.ev_repr with Event_none -> "" | Event_parent _ -> "(repr)" - | Event_child repr -> string_of_int !repr)) + | Event_child repr -> Int.to_string !repr)) (events_in_module mdle) (** User-defined printers **) @@ -1044,7 +1043,7 @@ With no argument, reset the search path." }; "exit the debugger." }; { instr_name = "shell"; instr_prio = false; instr_action = instr_shell; instr_repeat = true; instr_help = -"Execute a given COMMAND thru the system shell." }; +"Execute a given COMMAND through the system shell." }; { instr_name = "environment"; instr_prio = false; instr_action = instr_env; instr_repeat = false; instr_help = "environment variable to give to program being debugged when it is started." }; diff --git a/debugger/dune b/debugger/dune new file mode 100644 index 00000000..97560943 --- /dev/null +++ b/debugger/dune @@ -0,0 +1,25 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +(ocamllex lexer) +(ocamlyacc parser) + +(executable + (name main) + (modes byte) + (flags (:standard -w -9)) + (modules_without_implementation parser_aux) + (libraries ocamlcommon ocamltoplevel runtime stdlib unix)) + +(rule (copy main.exe ocamldebug.byte)) diff --git a/debugger/eval.ml b/debugger/eval.ml index e6baa80b..e3bacfa6 100644 --- a/debugger/eval.ml +++ b/debugger/eval.ml @@ -37,10 +37,10 @@ type error = exception Error of error let abstract_type = - Btype.newgenty (Tconstr (Pident (Ident.create ""), [], ref Mnil)) + Btype.newgenty (Tconstr (Pident (Ident.create_local ""), [], ref Mnil)) -let rec path event = function - Pident id -> +let rec address path event = function + | Env.Aident id -> if Ident.global id then try Debugcom.Remote_value.global (Symtable.get_global_position id) @@ -61,13 +61,17 @@ let rec path event = function | None -> raise(Error(Unbound_identifier id)) end - | Pdot(root, _fieldname, pos) -> - let v = path event root in + | Env.Adot(root, pos) -> + let v = address path event root in if not (Debugcom.Remote_value.is_block v) then - raise(Error(Not_initialized_yet root)); + raise(Error(Not_initialized_yet path)); Debugcom.Remote_value.field v pos - | Papply _ -> - fatal_error "Eval.path: Papply" + +let value_path event env path = + match Env.find_value_address path env with + | addr -> address path event addr + | exception Not_found -> + fatal_error ("Cannot find address for: " ^ (Path.name path)) let rec expression event env = function E_ident lid -> @@ -78,11 +82,11 @@ let rec expression event env = function let (p0, _) = Env.lookup_value (Longident.Lident ("self-" ^ cl_num)) env in - let v = path event p0 in - let i = path event p in + let v = value_path event env p0 in + let i = value_path event env p in Debugcom.Remote_value.field v (Debugcom.Remote_value.obj i) | _ -> - path event p + value_path event env p end, Ctype.correct_levels valdesc.val_type) with Not_found -> diff --git a/debugger/input_handling.ml b/debugger/input_handling.ml index e69c5f4b..b043629b 100644 --- a/debugger/input_handling.ml +++ b/debugger/input_handling.ml @@ -110,7 +110,7 @@ let resume_user_input () = if not (List.mem_assoc !user_channel.io_fd !active_files) then begin if !interactif && !Parameters.prompt then begin print_string !current_prompt; - flush Pervasives.stdout + flush Stdlib.stdout end; add_file !user_channel exit_main_loop end diff --git a/debugger/loadprinter.ml b/debugger/loadprinter.ml index b657331b..fd1a9d35 100644 --- a/debugger/loadprinter.ml +++ b/debugger/loadprinter.ml @@ -17,7 +17,6 @@ open Misc open Longident -open Path open Types (* Error report *) @@ -41,20 +40,17 @@ let use_debugger_symtable fn arg = let old_symtable = Symtable.current_state() in begin match !debugger_symtable with | None -> - Compdynlink.init(); Compdynlink.allow_unsafe_modules true; debugger_symtable := Some(Symtable.current_state()) | Some st -> Symtable.restore_state st end; - try - let result = fn arg in - debugger_symtable := Some(Symtable.current_state()); - Symtable.restore_state old_symtable; - result - with exn -> - Symtable.restore_state old_symtable; - raise exn + Misc.try_finally (fun () -> + let result = fn arg in + debugger_symtable := Some(Symtable.current_state()); + result + ) + ~always:(fun () -> Symtable.restore_state old_symtable) (* Load a .cmo or .cma file *) @@ -62,12 +58,12 @@ open Format let rec loadfiles ppf name = try - let filename = find_in_path !Config.load_path name in + let filename = Load_path.find name in use_debugger_symtable Compdynlink.loadfile filename; let d = Filename.dirname name in if d <> Filename.current_dir_name then begin - if not (List.mem d !Config.load_path) then - Config.load_path := d :: !Config.load_path; + if not (List.mem d (Load_path.get_paths ())) then + Load_path.add_dir d; end; fprintf ppf "File %s loaded@." filename; true @@ -92,15 +88,17 @@ let loadfile ppf name = (* Note: evaluation proceeds in the debugger memory space, not in the debuggee. *) -let rec eval_path = function - Pident id -> Symtable.get_global_value id - | Pdot(p, _, pos) -> Obj.field (eval_path p) pos - | Papply _ -> fatal_error "Loadprinter.eval_path" +let rec eval_address = function + | Env.Aident id -> Symtable.get_global_value id + | Env.Adot(addr, pos) -> Obj.field (eval_address addr) pos (* PR#7258: get rid of module aliases before evaluating paths *) -let eval_path path = - eval_path (Env.normalize_path (Some Location.none) Env.empty path) +let eval_value_path env path = + match Env.find_value_address path env with + | addr -> eval_address addr + | exception Not_found -> + fatal_error ("Cannot find address for: " ^ (Path.name path)) (* Install, remove a printer (as in toplevel/topdirs) *) @@ -117,7 +115,6 @@ let match_printer_type desc typename = Env.lookup_type (Ldot(Lident "Topdirs", typename)) Env.empty with Not_found -> raise (Error(Unbound_identifier(Ldot(Lident "Topdirs", typename)))) in - Ctype.init_def(Ident.current_time()); Ctype.begin_def(); let ty_arg = Ctype.newvar() in Ctype.unify Env.empty @@ -144,7 +141,7 @@ let install_printer ppf lid = let (ty_arg, path, is_old_style) = find_printer_type lid in let v = try - use_debugger_symtable eval_path path + use_debugger_symtable (eval_value_path Env.empty) path with Symtable.Error(Symtable.Undefined_global s) -> raise(Error(Unavailable_module(s, lid))) in let print_function = diff --git a/debugger/main.ml b/debugger/main.ml index 87027596..41429a3b 100644 --- a/debugger/main.ml +++ b/debugger/main.ml @@ -207,9 +207,9 @@ let main () = "Win32" -> (Unix.string_of_inet_addr Unix.inet_addr_loopback)^ ":"^ - (string_of_int (10000 + ((Unix.getpid ()) mod 10000))) + (Int.to_string (10000 + ((Unix.getpid ()) mod 10000))) | _ -> Filename.concat (Filename.get_temp_dir_name ()) - ("camldebug" ^ (string_of_int (Unix.getpid ()))) + ("camldebug" ^ (Int.to_string (Unix.getpid ()))) ); begin try Arg.parse speclist anonymous ""; @@ -226,7 +226,7 @@ let main () = if !Parameters.version then printf "\tOCaml Debugger version %s@.@." Config.version; Loadprinter.init(); - Config.load_path := !default_load_path; + Load_path.init !default_load_path; Clflags.recursive_types := true; (* Allow recursive types. *) toplevel_loop (); (* Toplevel. *) kill_program (); diff --git a/debugger/parameters.ml b/debugger/parameters.ml index ea11698a..6b5b6c48 100644 --- a/debugger/parameters.ml +++ b/debugger/parameters.ml @@ -16,8 +16,6 @@ (* Miscellaneous parameters *) -open Primitives -open Config open Debugger_config let program_name = ref "" @@ -35,7 +33,7 @@ let version = ref true let topdirs_path = ref (Filename.concat Config.standard_library "compiler-libs") let add_path dir = - load_path := dir :: except dir !load_path; + Load_path.add_dir dir; Envaux.reset_cache() let add_path_for mdl dir = diff --git a/debugger/printval.ml b/debugger/printval.ml index 1175a96c..a6d83ce7 100644 --- a/debugger/printval.ml +++ b/debugger/printval.ml @@ -18,7 +18,6 @@ open Format open Parser_aux -open Path open Types (* To name printed and ellipsed values *) @@ -43,27 +42,25 @@ let find_named_value name = let check_depth depth obj ty = if depth <= 0 then begin let n = name_value obj ty in - Some (Outcometree.Oval_stuff ("$" ^ string_of_int n)) + Some (Outcometree.Oval_stuff ("$" ^ Int.to_string n)) end else None module EvalPath = struct type valu = Debugcom.Remote_value.t exception Error - let rec eval_path env = function - Pident id -> + let rec eval_address = function + | Env.Aident id -> begin try Debugcom.Remote_value.global (Symtable.get_global_position id) with Symtable.Error _ -> raise Error end - | Pdot(root, _fieldname, pos) -> - let v = eval_path env root in + | Env.Adot(root, pos) -> + let v = eval_address root in if not (Debugcom.Remote_value.is_block v) then raise Error else Debugcom.Remote_value.field v pos - | Papply _ -> - raise Error let same_value = Debugcom.Remote_value.same end diff --git a/debugger/program_management.ml b/debugger/program_management.ml index c8d81e43..a232be2b 100644 --- a/debugger/program_management.ml +++ b/debugger/program_management.ml @@ -119,7 +119,7 @@ let ask_kill_program () = let initialize_loading () = if !debug_loading then begin prerr_endline "Loading debugging information..."; - Printf.fprintf Pervasives.stderr "\tProgram: [%s]\n%!" !program_name; + Printf.fprintf Stdlib.stderr "\tProgram: [%s]\n%!" !program_name; end; begin try access !program_name [F_OK] with Unix_error _ -> @@ -127,7 +127,7 @@ let initialize_loading () = raise Toplevel; end; Symbols.read_symbols !program_name; - Config.load_path := !Config.load_path @ !Symbols.program_source_dirs; + Load_path.init (Load_path.get_paths () @ !Symbols.program_source_dirs); Envaux.reset_cache (); if !debug_loading then prerr_endline "Opening a socket..."; @@ -141,7 +141,7 @@ let initialize_loading () = let ensure_loaded () = if not !loaded then begin print_string "Loading program... "; - flush Pervasives.stdout; + flush Stdlib.stdout; if !program_name = "" then begin prerr_endline "No program specified."; raise Toplevel diff --git a/debugger/source.ml b/debugger/source.ml index ff41e3fc..b1f9b2ea 100644 --- a/debugger/source.ml +++ b/debugger/source.ml @@ -40,7 +40,7 @@ let source_of_module pos mdle = else acc) Debugger_config.load_path_for - !Config.load_path in + (Load_path.get_paths ()) in let fname = pos.Lexing.pos_fname in if fname = "" then let innermost_module = diff --git a/debugger/symbols.ml b/debugger/symbols.ml index 2318c10f..d22f1a17 100644 --- a/debugger/symbols.ml +++ b/debugger/symbols.ml @@ -19,8 +19,7 @@ open Instruct open Debugger_config (* Toplevel *) open Program_loading - -module StringSet = Set.Make(String) +module String = Misc.Stdlib.String let modules = ref ([] : string list) @@ -72,7 +71,7 @@ let read_symbols' bytecode_file = raise Toplevel end; let num_eventlists = input_binary_int ic in - let dirs = ref StringSet.empty in + let dirs = ref String.Set.empty in let eventlists = ref [] in for _i = 1 to num_eventlists do let orig = input_binary_int ic in @@ -82,7 +81,7 @@ let read_symbols' bytecode_file = let evll = partition_modules evl in eventlists := evll @ !eventlists; dirs := - List.fold_left (fun s e -> StringSet.add e s) !dirs (input_value ic) + List.fold_left (fun s e -> String.Set.add e s) !dirs (input_value ic) done; begin try ignore (Bytesections.seek_section ic "CODE") @@ -98,7 +97,7 @@ let read_symbols bytecode_file = let all_events, all_dirs = read_symbols' bytecode_file in modules := []; events := []; - program_source_dirs := StringSet.elements all_dirs; + program_source_dirs := String.Set.elements all_dirs; Hashtbl.clear events_by_pc; Hashtbl.clear events_by_module; Hashtbl.clear all_events_by_module; diff --git a/debugger/time_travel.ml b/debugger/time_travel.ml index cf7d47cb..c239a20c 100644 --- a/debugger/time_travel.ml +++ b/debugger/time_travel.ml @@ -95,7 +95,7 @@ let wait_for_connection checkpoint = (* Select a checkpoint as current. *) let set_current_checkpoint checkpoint = if !debug_time_travel then - prerr_endline ("Select: " ^ (string_of_int checkpoint.c_pid)); + prerr_endline ("Select: " ^ (Int.to_string checkpoint.c_pid)); if not checkpoint.c_valid then wait_for_connection checkpoint; current_checkpoint := checkpoint; @@ -104,7 +104,7 @@ let set_current_checkpoint checkpoint = (* Kill `checkpoint'. *) let kill_checkpoint checkpoint = if !debug_time_travel then - prerr_endline ("Kill: " ^ (string_of_int checkpoint.c_pid)); + prerr_endline ("Kill: " ^ (Int.to_string checkpoint.c_pid)); if checkpoint.c_pid > 0 then (* Ghosts don't have to be killed ! *) (if not checkpoint.c_valid then wait_for_connection checkpoint; @@ -241,7 +241,7 @@ let duplicate_current_checkpoint () = Checkpoint_done pid -> (new_checkpoint.c_pid <- pid; if !debug_time_travel then - prerr_endline ("Waiting for connection: " ^ string_of_int pid)) + prerr_endline ("Waiting for connection: " ^ Int.to_string pid)) | Checkpoint_failed -> prerr_endline "A fork failed. Reducing maximum number of checkpoints."; @@ -257,7 +257,7 @@ let duplicate_current_checkpoint () = (* --- about this exception. *) let interrupted = ref false -(* Informations about last breakpoint encountered *) +(* Information about last breakpoint encountered *) let last_breakpoint = ref None (* Ensure we stop on an event. *) @@ -373,7 +373,7 @@ let set_file_descriptor pid fd = true) in if !debug_time_travel then - prerr_endline ("New connection: " ^(string_of_int pid)); + prerr_endline ("New connection: " ^(Int.to_string pid)); find (!current_checkpoint::!checkpoints) (* Kill all the checkpoints. *) diff --git a/debugger/unix_tools.ml b/debugger/unix_tools.ml index 4771253b..e9e3f85c 100644 --- a/debugger/unix_tools.ml +++ b/debugger/unix_tools.ml @@ -16,6 +16,7 @@ (****************** Tools for Unix *************************************) +module Real_stdlib = Stdlib open Misc open Unix @@ -58,7 +59,7 @@ let report_error = function (* Return the full path if found. *) (* Raise `Not_found' otherwise. *) let search_in_path name = - Printf.fprintf Pervasives.stderr "search_in_path [%s]\n%!" name; + Printf.fprintf Real_stdlib.stderr "search_in_path [%s]\n%!" name; let check name = try access name [X_OK]; name with Unix_error _ -> raise Not_found in diff --git a/driver/compdynlink.mlno b/driver/compdynlink.mlno deleted file mode 100644 index d7d685bb..00000000 --- a/driver/compdynlink.mlno +++ /dev/null @@ -1,57 +0,0 @@ -#2 "driver/compdynlink.mlno" -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -(* Dynamic loading of .cmx files *) - -type linking_error = - Undefined_global of string - | Unavailable_primitive of string - | Uninitialized_global of string - -type error = - Not_a_bytecode_file of string - | Inconsistent_import of string - | Unavailable_unit of string - | Unsafe_file - | Linking_error of string * linking_error - | Corrupted_interface of string - | File_not_found of string - | Cannot_open_dll of string - | Inconsistent_implementation of string - -exception Error of error - -let not_available _ = - failwith "No support for native dynlink on this OS" - -let default_available_units = not_available - -let init = not_available - -let loadfile = not_available -let loadfile_private = not_available -let allow_only = not_available -let prohibit = not_available - -let digest_interface = not_available -let add_interfaces = not_available -let add_available_units = not_available -let clear_available_units = not_available -let allow_unsafe_modules = not_available -let error_message = not_available - -let is_native = true -let adapt_filename f = Filename.chop_extension f ^ ".cmxs" diff --git a/driver/compenv.ml b/driver/compenv.ml index 704a65f5..c4b62d63 100644 --- a/driver/compenv.ml +++ b/driver/compenv.ml @@ -48,7 +48,6 @@ let default_output = function | Some s -> s | None -> Config.default_executable_name -let implicit_modules = ref [] let first_include_dirs = ref [] let last_include_dirs = ref [] let first_ccopts = ref [] @@ -77,13 +76,13 @@ let is_unit_name name = with Exit -> false ;; -let check_unit_name ppf filename name = +let check_unit_name filename name = if not (is_unit_name name) then - Location.print_warning (Location.in_file filename) ppf + Location.prerr_warning (Location.in_file filename) (Warnings.Bad_module_name name);; (* Compute name of module from output file name *) -let module_of_filename ppf inputfile outputprefix = +let module_of_filename inputfile outputprefix = let basename = Filename.basename outputprefix in let name = try @@ -92,7 +91,7 @@ let module_of_filename ppf inputfile outputprefix = with Not_found -> basename in let name = String.capitalize_ascii name in - check_unit_name ppf inputfile name; + check_unit_name inputfile name; name ;; @@ -106,6 +105,10 @@ type readenv_position = or ':', '|', ';', ' ' or ',' *) exception SyntaxError of string +let print_error ppf msg = + Location.print_warning Location.none ppf + (Warnings.Bad_env_variable ("OCAMLPARAM", msg)) + let parse_args s = let args = let len = String.length s in @@ -149,25 +152,22 @@ let setter ppf f name options s = in List.iter (fun b -> b := f bool) options with Not_found -> - Location.print_warning Location.none ppf - (Warnings.Bad_env_variable ("OCAMLPARAM", - Printf.sprintf "bad value for %s" name)) + Printf.ksprintf (print_error ppf) + "bad value %s for %s" s name let int_setter ppf name option s = try option := int_of_string s with _ -> - Location.print_warning Location.none ppf - (Warnings.Bad_env_variable - ("OCAMLPARAM", Printf.sprintf "non-integer parameter for \"%s\"" name)) + Printf.ksprintf (print_error ppf) + "non-integer parameter %s for %S" s name let int_option_setter ppf name option s = try option := Some (int_of_string s) with _ -> - Location.print_warning Location.none ppf - (Warnings.Bad_env_variable - ("OCAMLPARAM", Printf.sprintf "non-integer parameter for \"%s\"" name)) + Printf.ksprintf (print_error ppf) + "non-integer parameter %s for %S" s name (* let float_setter ppf name option s = @@ -186,9 +186,8 @@ let check_bool ppf name s = | "0" -> false | "1" -> true | _ -> - Location.print_warning Location.none ppf - (Warnings.Bad_env_variable ("OCAMLPARAM", - Printf.sprintf "bad value for %s" name)); + Printf.ksprintf (print_error ppf) + "bad value %s for %s" s name; false (* 'can-discard=' specifies which arguments can be discarded without warning @@ -206,7 +205,7 @@ let read_one_param ppf position name v = | "afl-inst-ratio" -> int_setter ppf "afl-inst-ratio" afl_inst_ratio v | "annot" -> set "annot" [ Clflags.annotations ] v - | "absname" -> set "absname" [ Location.absname ] v + | "absname" -> set "absname" [ Clflags.absname ] v | "compat-32" -> set "compat-32" [ bytecode_compatible_32 ] v | "noassert" -> set "noassert" [ noassert ] v | "noautolink" -> set "noautolink" [ no_auto_link ] v @@ -220,7 +219,7 @@ let read_one_param ppf position name v = | "strict-formats" -> set "strict-formats" [ strict_formats ] v | "thread" -> set "thread" [ use_threads ] v | "unboxed-types" -> set "unboxed-types" [ unboxed_types ] v - | "unsafe" -> set "unsafe" [ fast ] v + | "unsafe" -> set "unsafe" [ unsafe ] v | "verbose" -> set "verbose" [ verbose ] v | "nopervasives" -> set "nopervasives" [ nopervasives ] v | "slash" -> set "slash" [ force_slash ] v (* for ocamldep *) @@ -236,6 +235,8 @@ let read_one_param ppf position name v = | "pp" -> preprocessor := Some v | "runtime-variant" -> runtime_variant := v + | "open" -> + open_modules := List.rev_append (String.split_on_char ',' v) !open_modules | "cc" -> c_compiler := Some v | "clambda-checks" -> set "clambda-checks" [ clambda_checks ] v @@ -252,6 +253,8 @@ let read_one_param ppf position name v = | "w" -> Warnings.parse_options false v (* warn-errors *) | "wwe" -> Warnings.parse_options false v + (* alerts *) + | "alert" -> Warnings.parse_alert_option v (* inlining *) | "inline" -> @@ -259,12 +262,8 @@ let read_one_param ppf position name v = begin match F.parse_no_error v inline_threshold with | F.Ok -> () | F.Parse_failed exn -> - let error = - Printf.sprintf "bad syntax for \"inline\": %s" - (Printexc.to_string exn) - in - Location.print_warning Location.none ppf - (Warnings.Bad_env_variable ("OCAMLPARAM", error)) + Printf.ksprintf (print_error ppf) + "bad syntax %s for \"inline\": %s" v (Printexc.to_string exn) end | "inline-toplevel" -> @@ -345,15 +344,21 @@ let read_one_param ppf position name v = (* color output *) | "color" -> - begin match parse_color_setting v with + begin match color_reader.parse v with | None -> - Location.print_warning Location.none ppf - (Warnings.Bad_env_variable ("OCAMLPARAM", - "bad value for \"color\", \ - (expected \"auto\", \"always\" or \"never\")")) + Printf.ksprintf (print_error ppf) + "bad value %s for \"color\", (%s)" v color_reader.usage | Some setting -> color := Some setting end + | "error-style" -> + begin match error_style_reader.parse v with + | None -> + Printf.ksprintf (print_error ppf) + "bad value %s for \"error-style\", (%s)" v error_style_reader.usage + | Some setting -> error_style := Some setting + end + | "intf-suffix" -> Config.interface_suffix := v | "I" -> begin @@ -425,10 +430,24 @@ let read_one_param ppf position name v = | "plugin" -> !load_plugin v + | "stop-after" -> + let module P = Clflags.Compiler_pass in + begin match P.of_string v with + | None -> + Printf.ksprintf (print_error ppf) + "bad value %s for option \"stop-after\" (expected one of: %s)" + v (String.concat ", " P.pass_names) + | Some pass -> + Clflags.stop_after := Some pass; + begin match pass with + | P.Parsing | P.Typing -> + compile_only := true + end; + end | _ -> if not (List.mem name !can_discard) then begin can_discard := name :: !can_discard; - Printf.eprintf + Printf.ksprintf (print_error ppf) "Warning: discarding value of variable %S in OCAMLPARAM\n%!" name end @@ -440,9 +459,8 @@ let read_OCAMLPARAM ppf position = try parse_args s with SyntaxError s -> - Location.print_warning Location.none ppf - (Warnings.Bad_env_variable ("OCAMLPARAM", s)); - [],[] + print_error ppf s; + [],[] in List.iter (fun (name, v) -> read_one_param ppf position name v) (match position with @@ -475,8 +493,9 @@ let scan_line ic = let load_config ppf filename = match open_in_bin filename with | exception e -> - Location.print_error ppf (Location.in_file filename); - Format.fprintf ppf "Cannot open file %s@." (Printexc.to_string e); + Location.errorf ~loc:(Location.in_file filename) + "Cannot open file %s" (Printexc.to_string e) + |> Location.print_report ppf; raise Exit | ic -> let sic = Scanf.Scanning.from_channel ic in @@ -499,8 +518,8 @@ let load_config ppf filename = loc_ghost = false; } in - Location.print_error ppf loc; - Format.fprintf ppf "Configuration file error %s@." error; + Location.errorf ~loc "Configuration file error %s" error + |> Location.print_report ppf; close_in ic; raise Exit | line -> @@ -575,12 +594,12 @@ let process_action | ProcessImplementation name -> readenv ppf (Before_compile name); let opref = output_prefix name in - implementation ppf name opref; + implementation ~source_file:name ~output_prefix:opref; objfiles := (opref ^ ocaml_mod_ext) :: !objfiles | ProcessInterface name -> readenv ppf (Before_compile name); let opref = output_prefix name in - interface ppf name opref; + interface ~source_file:name ~output_prefix:opref; if !make_package then objfiles := (opref ^ ".cmi") :: !objfiles | ProcessCFile name -> readenv ppf (Before_compile name); diff --git a/driver/compenv.mli b/driver/compenv.mli index 0ee9871a..f9465b62 100644 --- a/driver/compenv.mli +++ b/driver/compenv.mli @@ -13,7 +13,7 @@ (* *) (**************************************************************************) -val module_of_filename : Format.formatter -> string -> string -> string +val module_of_filename : string -> string -> string val output_prefix : string -> string val extract_output : string option -> string @@ -28,7 +28,6 @@ val first_ccopts : string list ref val first_ppx : string list ref val first_include_dirs : string list ref val last_include_dirs : string list ref -val implicit_modules : string list ref (* function to call on plugin=XXX *) val load_plugin : (string -> unit) ref @@ -50,7 +49,7 @@ val readenv : Format.formatter -> readenv_position -> unit val is_unit_name : string -> bool (* [check_unit_name ppf filename name] prints a warning in [filename] on [ppf] if [name] should not be used as a module name. *) -val check_unit_name : Format.formatter -> string -> string -> unit +val check_unit_name : string -> string -> unit (* Deferred actions of the compiler, while parsing arguments *) @@ -71,8 +70,10 @@ val intf : string -> unit val process_deferred_actions : Format.formatter * - (Format.formatter -> string -> string -> unit) * (* compile implementation *) - (Format.formatter -> string -> string -> unit) * (* compile interface *) + (source_file:string -> output_prefix:string -> unit) * + (* compile implementation *) + (source_file:string -> output_prefix:string -> unit) * + (* compile interface *) string * (* ocaml module extension *) string -> (* ocaml library extension *) unit diff --git a/driver/compify_dynlink.sh b/driver/compify_dynlink.sh new file mode 100755 index 00000000..63bb86bb --- /dev/null +++ b/driver/compify_dynlink.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +grep -v 'REMOVE_ME for ' $1 | sed 's/Dynlink_/Compdynlink_/g' > $2 diff --git a/driver/compile.ml b/driver/compile.ml index 75a2470f..ba63a63b 100644 --- a/driver/compile.ml +++ b/driver/compile.ml @@ -13,107 +13,51 @@ (* *) (**************************************************************************) -(* The batch compiler *) - open Misc -open Format -open Typedtree -open Compenv - -(* Compile a .mli file *) - -(* Keep in sync with the copy in optcompile.ml *) +open Compile_common let tool_name = "ocamlc" -let interface ppf sourcefile outputprefix = - Profile.record_call sourcefile (fun () -> - Compmisc.init_path false; - let modulename = module_of_filename ppf sourcefile outputprefix in - Env.set_unit_name modulename; - let initial_env = Compmisc.initial_env () in - let ast = Pparse.parse_interface ~tool_name ppf sourcefile in - - if !Clflags.dump_parsetree then fprintf ppf "%a@." Printast.interface ast; - if !Clflags.dump_source then fprintf ppf "%a@." Pprintast.signature ast; - Profile.(record_call typing) (fun () -> - let tsg = Typemod.type_interface sourcefile initial_env ast in - if !Clflags.dump_typedtree then fprintf ppf "%a@." Printtyped.interface tsg; - let sg = tsg.sig_type in - if !Clflags.print_types then - Printtyp.wrap_printing_env ~error:false initial_env (fun () -> - fprintf std_formatter "%a@." - Printtyp.signature (Typemod.simplify_signature sg)); - ignore (Includemod.signatures initial_env sg sg); - Typecore.force_delayed_checks (); - Warnings.check_fatal (); - if not !Clflags.print_types then begin - let deprecated = Builtin_attributes.deprecated_of_sig ast in - let sg = - Env.save_signature ~deprecated sg modulename (outputprefix ^ ".cmi") - in - Typemod.save_signature modulename tsg outputprefix sourcefile - initial_env sg ; - end +let with_info = + Compile_common.with_info ~native:false ~tool_name + +let interface ~source_file ~output_prefix = + with_info ~source_file ~output_prefix ~dump_ext:"cmi" @@ fun info -> + Compile_common.interface info + +(** Bytecode compilation backend for .ml files. *) + +let to_bytecode i (typedtree, coercion) = + (typedtree, coercion) + |> Profile.(record transl) + (Translmod.transl_implementation i.module_name) + |> Profile.(record ~accumulate:true generate) + (fun { Lambda.code = lambda; required_globals } -> + lambda + |> print_if i.ppf_dump Clflags.dump_rawlambda Printlambda.lambda + |> Simplif.simplify_lambda i.source_file + |> print_if i.ppf_dump Clflags.dump_lambda Printlambda.lambda + |> Bytegen.compile_implementation i.module_name + |> print_if i.ppf_dump Clflags.dump_instr Printinstr.instrlist + |> fun bytecode -> bytecode, required_globals ) - ) -(* Compile a .ml file *) - -let print_if ppf flag printer arg = - if !flag then fprintf ppf "%a@." printer arg; - arg - -let (++) x f = f x +let emit_bytecode i (bytecode, required_globals) = + let cmofile = cmo i in + let oc = open_out_bin cmofile in + Misc.try_finally + ~always:(fun () -> close_out oc) + ~exceptionally:(fun () -> Misc.remove_file cmofile) + (fun () -> + bytecode + |> Profile.(record ~accumulate:true generate) + (Emitcode.to_file oc i.module_name cmofile ~required_globals); + ) -let implementation ppf sourcefile outputprefix = - Profile.record_call sourcefile (fun () -> - Compmisc.init_path false; - let modulename = module_of_filename ppf sourcefile outputprefix in - Env.set_unit_name modulename; - let env = Compmisc.initial_env() in - try - let (typedtree, coercion) = - Pparse.parse_implementation ~tool_name ppf sourcefile - ++ print_if ppf Clflags.dump_parsetree Printast.implementation - ++ print_if ppf Clflags.dump_source Pprintast.structure - ++ Profile.(record typing) - (Typemod.type_implementation sourcefile outputprefix modulename env) - ++ print_if ppf Clflags.dump_typedtree - Printtyped.implementation_with_coercion - in - if !Clflags.print_types then begin - Warnings.check_fatal (); - Stypes.dump (Some (outputprefix ^ ".annot")) - end else begin - let bytecode, required_globals = - (typedtree, coercion) - ++ Profile.(record transl) - (Translmod.transl_implementation modulename) - ++ Profile.(record ~accumulate:true generate) - (fun { Lambda.code = lambda; required_globals } -> - print_if ppf Clflags.dump_rawlambda Printlambda.lambda lambda - ++ Simplif.simplify_lambda sourcefile - ++ print_if ppf Clflags.dump_lambda Printlambda.lambda - ++ Bytegen.compile_implementation modulename - ++ print_if ppf Clflags.dump_instr Printinstr.instrlist - ++ fun bytecode -> bytecode, required_globals) - in - let objfile = outputprefix ^ ".cmo" in - let oc = open_out_bin objfile in - try - bytecode - ++ Profile.(record ~accumulate:true generate) - (Emitcode.to_file oc modulename objfile ~required_globals); - Warnings.check_fatal (); - close_out oc; - Stypes.dump (Some (outputprefix ^ ".annot")) - with x -> - close_out oc; - remove_file objfile; - raise x - end - with x -> - Stypes.dump (Some (outputprefix ^ ".annot")); - raise x - ) +let implementation ~source_file ~output_prefix = + let backend info typed = + let bytecode = to_bytecode info typed in + emit_bytecode info bytecode + in + with_info ~source_file ~output_prefix ~dump_ext:"cmo" @@ fun info -> + Compile_common.implementation info ~backend diff --git a/driver/compile.mli b/driver/compile.mli index defc101b..7c564c3e 100644 --- a/driver/compile.mli +++ b/driver/compile.mli @@ -13,9 +13,23 @@ (* *) (**************************************************************************) -(* Compile a .ml or .mli file *) +(** Bytecode compilation for .ml and .mli files. *) -open Format +val interface: + source_file:string -> output_prefix:string -> unit +val implementation: + source_file:string -> output_prefix:string -> unit -val interface: formatter -> string -> string -> unit -val implementation: formatter -> string -> string -> unit +(** {2 Internal functions} **) + +val to_bytecode : + Compile_common.info -> + Typedtree.structure * Typedtree.module_coercion -> + Instruct.instruction list * Ident.Set.t +(** [to_bytecode info typed] takes a typechecked implementation + and returns its bytecode. +*) + +val emit_bytecode : + Compile_common.info -> Instruct.instruction list * Ident.Set.t -> unit +(** [emit_bytecode bytecode] output the bytecode executable. *) diff --git a/driver/compile_common.ml b/driver/compile_common.ml new file mode 100644 index 00000000..2dc00d10 --- /dev/null +++ b/driver/compile_common.ml @@ -0,0 +1,129 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +open Misc +open Compenv + +type info = { + source_file : string; + module_name : string; + output_prefix : string; + env : Env.t; + ppf_dump : Format.formatter; + tool_name : string; + native : bool; +} + +let cmx i = i.output_prefix ^ ".cmx" +let obj i = i.output_prefix ^ Config.ext_obj +let cmo i = i.output_prefix ^ ".cmo" +let annot i = i.output_prefix ^ ".annot" + +let with_info ~native ~tool_name ~source_file ~output_prefix ~dump_ext k = + Compmisc.init_path native; + let module_name = module_of_filename source_file output_prefix in + Env.set_unit_name module_name; + let env = Compmisc.initial_env() in + let dump_file = String.concat "." [output_prefix; dump_ext] in + Compmisc.with_ppf_dump ~file_prefix:dump_file @@ fun ppf_dump -> + k { + module_name; + output_prefix; + env; + source_file; + ppf_dump; + tool_name; + native; + } + +(** Compile a .mli file *) + +let parse_intf i = + Pparse.parse_interface ~tool_name:i.tool_name i.source_file + |> print_if i.ppf_dump Clflags.dump_parsetree Printast.interface + |> print_if i.ppf_dump Clflags.dump_source Pprintast.signature + +let typecheck_intf info ast = + Profile.(record_call typing) @@ fun () -> + let tsg = + ast + |> Typemod.type_interface info.source_file info.env + |> print_if info.ppf_dump Clflags.dump_typedtree Printtyped.interface + in + let sg = tsg.Typedtree.sig_type in + if !Clflags.print_types then + Printtyp.wrap_printing_env ~error:false info.env (fun () -> + Format.(fprintf std_formatter) "%a@." + (Printtyp.printed_signature info.source_file) + sg); + ignore (Includemod.signatures info.env sg sg); + Typecore.force_delayed_checks (); + Warnings.check_fatal (); + tsg + +let emit_signature info ast tsg = + let sg = + let alerts = Builtin_attributes.alerts_of_sig ast in + Env.save_signature ~alerts tsg.Typedtree.sig_type + info.module_name (info.output_prefix ^ ".cmi") + in + Typemod.save_signature info.module_name tsg + info.output_prefix info.source_file info.env sg + +let interface info = + Profile.record_call info.source_file @@ fun () -> + let ast = parse_intf info in + if Clflags.(should_stop_after Compiler_pass.Parsing) then () else begin + let tsg = typecheck_intf info ast in + if not !Clflags.print_types then begin + emit_signature info ast tsg + end + end + + +(** Frontend for a .ml file *) + +let parse_impl i = + Pparse.parse_implementation ~tool_name:i.tool_name i.source_file + |> print_if i.ppf_dump Clflags.dump_parsetree Printast.implementation + |> print_if i.ppf_dump Clflags.dump_source Pprintast.structure + +let typecheck_impl i parsetree = + let always () = Stypes.dump (Some (annot i)) in + Misc.try_finally ~always (fun () -> + parsetree + |> Profile.(record typing) + (Typemod.type_implementation + i.source_file i.output_prefix i.module_name i.env) + |> print_if i.ppf_dump Clflags.dump_typedtree + Printtyped.implementation_with_coercion + ) + +let implementation info ~backend = + Profile.record_call info.source_file @@ fun () -> + let exceptionally () = + let sufs = if info.native then [ cmx; obj ] else [ cmo ] in + List.iter (fun suf -> remove_file (suf info)) sufs; + in + Misc.try_finally ?always:None ~exceptionally (fun () -> + let parsed = parse_impl info in + if Clflags.(should_stop_after Compiler_pass.Parsing) then () else begin + let typed = typecheck_impl info parsed in + if Clflags.(should_stop_after Compiler_pass.Typing) then () else begin + backend info typed + end; + end; + Warnings.check_fatal (); + ) diff --git a/driver/compile_common.mli b/driver/compile_common.mli new file mode 100644 index 00000000..b43125d6 --- /dev/null +++ b/driver/compile_common.mli @@ -0,0 +1,92 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Gabriel Radanne *) +(* *) +(* Copyright 2018 Gabriel Radanne *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** Common compilation pipeline between bytecode and native. *) + +(** {2 Initialization} *) + +type info = { + source_file : string; + module_name : string; + output_prefix : string; + env : Env.t; + ppf_dump : Format.formatter; + tool_name : string; + native : bool; +} +(** Information needed to compile a file. *) + +val with_info : + native:bool -> + tool_name:string -> + source_file:string -> + output_prefix:string -> + dump_ext:string -> + (info -> 'a) -> 'a +(** [with_info ~native ~tool_name ~source_file ~output_prefix ~dump_ext k] + invokes its continuation [k] with an [info] structure built from + its input, after initializing various global variables. This info + structure and the initialized global state are not valid anymore + after the continuation returns. + + Due to current implementation limitations in the compiler, it is + unsafe to try to compile several distinct compilation units by + calling [with_info] several times. +*) + +(** {2 Interfaces} *) + +val parse_intf : info -> Parsetree.signature +(** [parse_intf info] parses an interface (usually an [.mli] file). *) + +val typecheck_intf : info -> Parsetree.signature -> Typedtree.signature +(** [typecheck_intf info parsetree] typechecks an interface and returns + the typedtree of the associated signature. +*) + +val emit_signature : info -> Parsetree.signature -> Typedtree.signature -> unit +(** [emit_signature info parsetree typedtree] emits the [.cmi] file + containing the given signature. +*) + +val interface : info -> unit +(** The complete compilation pipeline for interfaces. *) + +(** {2 Implementations} *) + +val parse_impl : info -> Parsetree.structure +(** [parse_impl info] parses an implementation (usually an [.ml] file). *) + +val typecheck_impl : + info -> Parsetree.structure -> Typedtree.structure * Typedtree.module_coercion +(** [typecheck_impl info parsetree] typechecks an implementation and returns + the typedtree of the associated module, along with a coercion against + its public interface. +*) + +val implementation : + info -> + backend:(info -> Typedtree.structure * Typedtree.module_coercion -> unit) -> + unit +(** The complete compilation pipeline for implementations. *) + +(** {2 Build artifacts} *) + +val cmo : info -> string +val cmx : info -> string +val obj : info -> string +val annot : info -> string +(** Return the filename of some compiler build artifacts associated + with the file being compiled. +*) diff --git a/driver/compmisc.ml b/driver/compmisc.ml index b1bed14b..7cf81f2e 100644 --- a/driver/compmisc.ml +++ b/driver/compmisc.ml @@ -34,8 +34,7 @@ let init_path ?(dir="") native = in let exp_dirs = List.map (Misc.expand_directory Config.standard_library) dirs in - Config.load_path := dir :: - List.rev_append exp_dirs (Clflags.std_include_dir ()); + Load_path.init (dir :: List.rev_append exp_dirs (Clflags.std_include_dir ())); Env.reset_cache () (* Return the initial environment in which compilation proceeds. *) @@ -55,18 +54,35 @@ let initial_env () = ~loc:(Location.in_file "command line") ~safe_string:(Config.safe_string || not !Clflags.unsafe_string) ~initially_opened_module - ~open_implicit_modules:(!implicit_modules @ List.rev !Clflags.open_modules) + ~open_implicit_modules:(List.rev !Clflags.open_modules) -let read_color_env ppf = +let set_from_env flag Clflags.{ parse; usage; env_var } = try - match Clflags.parse_color_setting (Sys.getenv "OCAML_COLOR") with + match parse (Sys.getenv env_var) with | None -> - Location.print_warning Location.none ppf - (Warnings.Bad_env_variable - ("OCAML_COLOR", - "expected \"auto\", \"always\" or \"never\"")); - | Some x -> match !Clflags.color with - | None -> Clflags.color := Some x + Location.prerr_warning Location.none + (Warnings.Bad_env_variable (env_var, usage)) + | Some x -> match !flag with + | None -> flag := Some x | Some _ -> () with Not_found -> () + +let read_clflags_from_env () = + set_from_env Clflags.color Clflags.color_reader; + set_from_env Clflags.error_style Clflags.error_style_reader; + () + +let with_ppf_dump ~file_prefix f = + let ppf_dump, finally = + if not !Clflags.dump_into_file + then Format.err_formatter, ignore + else + let ch = open_out (file_prefix ^ ".dump") in + let ppf = Format.formatter_of_out_channel ch in + ppf, + (fun () -> + Format.pp_print_flush ppf (); + close_out ch) + in + Misc.try_finally (fun () -> f ppf_dump) ~always:finally diff --git a/driver/compmisc.mli b/driver/compmisc.mli index 3dbcdaeb..dd1ded47 100644 --- a/driver/compmisc.mli +++ b/driver/compmisc.mli @@ -16,4 +16,8 @@ val init_path : ?dir:string -> bool -> unit val initial_env : unit -> Env.t -val read_color_env : Format.formatter -> unit +(* Support for flags that can also be set from an environment variable *) +val set_from_env : 'a option ref -> 'a Clflags.env_reader -> unit +val read_clflags_from_env : unit -> unit + +val with_ppf_dump : file_prefix:string -> (Format.formatter -> 'a) -> 'a diff --git a/driver/compplugin.ml b/driver/compplugin.ml index 481692c1..ad29cc91 100644 --- a/driver/compplugin.ml +++ b/driver/compplugin.ml @@ -28,9 +28,10 @@ let load plugin_name = if Filename.is_implicit plugin_name then try Compmisc.init_path !Clflags.native_code; - Misc.find_in_path !Config.load_path plugin_name + Load_path.find plugin_name with Not_found -> - raise (Compdynlink.Error (Compdynlink.File_not_found plugin_name)) + failwith (Printf.sprintf "Cannot find plugin %s in load path" + plugin_name) else plugin_name in diff --git a/driver/dune b/driver/dune new file mode 100644 index 00000000..7f2697e1 --- /dev/null +++ b/driver/dune @@ -0,0 +1,55 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +(rule + (targets compdynlink.ml) + (deps (:ml ../otherlibs/dynlink/dynlink.ml) + (:sh ./compify_dynlink.sh)) + (action (run %{sh} %{ml} %{targets}))) + +(rule + (targets compdynlink.mli) + (deps (:ml ../otherlibs/dynlink/dynlink.mli) + (:sh ./compify_dynlink.sh)) + (action (run %{sh} %{ml} %{targets}))) + +(rule + (targets compdynlink_types.ml) + (deps (:ml ../otherlibs/dynlink/dynlink_types.ml) + (:sh ./compify_dynlink.sh)) + (action (run %{sh} %{ml} %{targets}))) + +(rule + (targets compdynlink_types.mli) + (deps (:ml ../otherlibs/dynlink/dynlink_types.mli) + (:sh ./compify_dynlink.sh)) + (action (run %{sh} %{ml} %{targets}))) + +(rule + (targets compdynlink_common.ml) + (deps (:ml ../otherlibs/dynlink/dynlink_common.ml) + (:sh ./compify_dynlink.sh)) + (action (run %{sh} %{ml} %{targets}))) + +(rule + (targets compdynlink_common.mli) + (deps (:ml ../otherlibs/dynlink/dynlink_common.mli) + (:sh ./compify_dynlink.sh)) + (action (run %{sh} %{ml} %{targets}))) + +(rule + (targets compdynlink_platform_intf.ml) + (deps (:ml ../otherlibs/dynlink/dynlink_platform_intf.ml) + (:sh ./compify_dynlink.sh)) + (action (run %{sh} %{ml} %{targets}))) diff --git a/driver/main.ml b/driver/main.ml index 5fc9387b..93299aed 100644 --- a/driver/main.ml +++ b/driver/main.ml @@ -21,16 +21,12 @@ let usage = "Usage: ocamlc \nOptions are:" (* Error messages to standard error formatter *) let ppf = Format.err_formatter -let show_config () = - Config.print_config stdout; - exit 0; -;; - module Options = Main_args.Make_bytecomp_options (struct let set r () = r := true let unset r () = r := false let _a = set make_archive - let _absname = set Location.absname + let _absname = set Clflags.absname + let _alert = Warnings.parse_alert_option let _annot = set annotations let _binannot = set binary_annotations let _c = set compile_only @@ -38,14 +34,30 @@ module Options = Main_args.Make_bytecomp_options (struct let _cclib s = Compenv.defer (ProcessObjects (Misc.rev_split_words s)) let _ccopt s = first_ccopts := s :: !first_ccopts let _compat_32 = set bytecode_compatible_32 - let _config = show_config + let _config = Misc.show_config_and_exit + let _config_var = Misc.show_config_variable_and_exit let _custom = set custom_runtime let _no_check_prims = set no_check_prims let _dllib s = defer (ProcessDLLs (Misc.rev_split_words s)) let _dllpath s = dllpaths := !dllpaths @ [s] let _for_pack s = for_package := Some s let _g = set debug - let _i () = print_types := true; compile_only := true + let _i () = + print_types := true; + compile_only := true; + stop_after := Some Compiler_pass.Typing; + () + let _stop_after pass = + let module P = Compiler_pass in + begin match P.of_string pass with + | None -> () (* this should not occur as we use Arg.Symbol *) + | Some pass -> + stop_after := Some pass; + begin match pass with + | P.Parsing | P.Typing -> + compile_only := true + end; + end let _I s = include_dirs := s :: !include_dirs let _impl = impl let _intf = intf @@ -93,7 +105,7 @@ module Options = Main_args.Make_bytecomp_options (struct let _vmthread = set use_vmthreads let _unboxed_types = set unboxed_types let _no_unboxed_types = unset unboxed_types - let _unsafe = set fast + let _unsafe = set unsafe let _unsafe_string = set unsafe_string let _use_prims s = use_prims := s let _use_runtime s = use_runtime := s @@ -103,22 +115,22 @@ module Options = Main_args.Make_bytecomp_options (struct let _w = (Warnings.parse_options false) let _warn_error = (Warnings.parse_options true) let _warn_help = Warnings.help_warnings - let _color option = - begin match parse_color_setting option with - | None -> () - | Some setting -> color := Some setting - end + let _color = Misc.set_or_ignore color_reader.parse color + let _error_style = Misc.set_or_ignore error_style_reader.parse error_style let _where = print_standard_library let _verbose = set verbose let _nopervasives = set nopervasives + let _match_context_rows n = match_context_rows := n + let _dump_into_file = set dump_into_file let _dno_unique_ids = unset unique_ids - let _dunique_ids = set unique_ids + let _dunique_ids = set unique_ids let _dsource = set dump_source let _dparsetree = set dump_parsetree let _dtypedtree = set dump_typedtree let _drawlambda = set dump_rawlambda let _dlambda = set dump_lambda let _dinstr = set dump_instr + let _dcamlprimc = set keep_camlprimc_file let _dtimings () = profile_columns := [ `Time ] let _dprofile () = profile_columns := Profile.all_columns @@ -128,6 +140,12 @@ module Options = Main_args.Make_bytecomp_options (struct let anonymous = anonymous end) +let vmthread_deprecated_message = "\ +The -vmthread argument of ocamlc is deprecated\n\ +since OCaml 4.08.0. Please switch to system threads, which have the\n\ +same API. Lightweight threads with VM-level scheduling are provided by\n\ +third-party libraries such as Lwt, but with a different API." + let main () = Clflags.add_arguments __LOC__ Options.list; Clflags.add_arguments __LOC__ @@ -136,7 +154,9 @@ let main () = try readenv ppf Before_args; Clflags.parse_arguments anonymous usage; - Compmisc.read_color_env ppf; + Compmisc.read_clflags_from_env (); + if !Clflags.use_vmthreads then + Location.deprecated Location.none vmthread_deprecated_message; begin try Compenv.process_deferred_actions (ppf, @@ -153,28 +173,36 @@ let main () = end; readenv ppf Before_link; if - List.length (List.filter (fun x -> !x) - [make_archive;make_package;compile_only;output_c_object]) + List.length + (List.filter (fun x -> !x) + [make_archive;make_package;compile_only;output_c_object]) > 1 - then - if !print_types then - fatal "Option -i is incompatible with -pack, -a, -output-obj" - else + then begin + let module P = Clflags.Compiler_pass in + match !stop_after with + | None -> fatal "Please specify at most one of -pack, -a, -c, -output-obj"; + | Some (P.Parsing | P.Typing) -> + Printf.ksprintf fatal + "Options -i and -stop-after (%s)\ + are incompatible with -pack, -a, -output-obj" + (String.concat "|" P.pass_names) + end; if !make_archive then begin Compmisc.init_path false; - Bytelibrarian.create_archive ppf - (Compenv.get_objfiles ~with_ocamlparam:false) - (extract_output !output_name); + Bytelibrarian.create_archive + (Compenv.get_objfiles ~with_ocamlparam:false) + (extract_output !output_name); Warnings.check_fatal (); end else if !make_package then begin Compmisc.init_path false; let extracted_output = extract_output !output_name in let revd = get_objfiles ~with_ocamlparam:false in - Bytepackager.package_files ppf (Compmisc.initial_env ()) - revd (extracted_output); + Compmisc.with_ppf_dump ~file_prefix:extracted_output (fun ppf_dump -> + Bytepackager.package_files ~ppf_dump (Compmisc.initial_env ()) + revd (extracted_output)); Warnings.check_fatal (); end else if not !compile_only && !objfiles <> [] then begin @@ -195,7 +223,7 @@ let main () = default_output !output_name in Compmisc.init_path false; - Bytelink.link ppf (get_objfiles ~with_ocamlparam:true) target; + Bytelink.link (get_objfiles ~with_ocamlparam:true) target; Warnings.check_fatal (); end; with x -> diff --git a/driver/main_args.ml b/driver/main_args.ml index 47e427eb..456850eb 100644 --- a/driver/main_args.ml +++ b/driver/main_args.ml @@ -17,6 +17,17 @@ let mk_a f = "-a", Arg.Unit f, " Build a library" ;; +let mk_alert f = + "-alert", Arg.String f, + Printf.sprintf + " Enable or disable alerts according to :\n\ + \ + enable alert \n\ + \ - disable alert \n\ + \ ++ treat as fatal error\n\ + \ -- treat as non-fatal\n\ + \ @ enable and treat it as fatal error\n\ + \ can be 'all' to refer to all alert names";; + let mk_absname f = "-absname", Arg.Unit f, " Show absolute filenames in error messages" ;; @@ -64,6 +75,12 @@ let mk_config f = "-config", Arg.Unit f, " Print configuration values and exit" ;; +let mk_config_var f = + "-config-var", Arg.String f, + " Print the value of a configuration variable, a newline, and exit\n\ +\ (print nothing and exit with error value if the variable does not exist)" +;; + let mk_custom f = "-custom", Arg.Unit f, " Link in custom mode" ;; @@ -77,6 +94,11 @@ let mk_dllpath f = "

Add to the run-time search path for shared libraries" ;; +let mk_stop_after f = + "-stop-after", Arg.Symbol (Clflags.Compiler_pass.pass_names, f), + " Stop after the given compilation pass." +;; + let mk_dtypes f = "-dtypes", Arg.Unit f, " (deprecated) same as -annot" ;; @@ -542,8 +564,8 @@ let mk_no_version f = let mk_vmthread f = "-vmthread", Arg.Unit f, - " Generate code that supports the threads library with VM-level\n\ - \ scheduling" + " (deprecated) Generate code that supports the threads library\n\ + \ with VM-level scheduling" ;; let mk_vnum f = @@ -586,7 +608,22 @@ let mk_color f = \ never disable colors\n\ \ The default setting is 'auto', and the current heuristic\n\ \ checks that the TERM environment variable exists and is\n\ - \ not empty or \"dumb\", and that isatty(stderr) holds." + \ not empty or \"dumb\", and that isatty(stderr) holds.\n\ + \ If the option is not specified, these setting can alternatively\n\ + \ be set through the OCAML_COLOR environment variable." +;; + +let mk_error_style f = + "-error-style", Arg.Symbol (["contextual"; "short"], f), + Printf.sprintf + " Control the way error messages and warnings are printed\n\ + \ The following settings are supported:\n\ + \ short only print the error and its location\n\ + \ contextual like \"short\", but also display the source code\n\ + \ snippet corresponding to the location of the error\n\ + \ The default setting is 'contextual'.\n\ + \ If the option is not specified, these setting can alternatively\n\ + \ be set through the OCAML_ERROR_STYLE environment variable." ;; let mk_where f = @@ -597,10 +634,21 @@ let mk_nopervasives f = "-nopervasives", Arg.Unit f, " (undocumented)" ;; +let mk_match_context_rows f = + "-match-context-rows", Arg.Int f, + let[@manual.ref "s:comp-options"] chapter, section = 9, 2 in + Printf.sprintf + " (advanced, see manual section %d.%d.)" chapter section +;; + let mk_use_prims f = "-use-prims", Arg.String f, " (undocumented)" ;; +let mk_dump_into_file f = + "-dump-into-file", Arg.Unit f, " dump output like -dlambda into .dump" +;; + let mk_dparsetree f = "-dparsetree", Arg.Unit f, " (undocumented)" ;; @@ -669,6 +717,10 @@ let mk_dinstr f = "-dinstr", Arg.Unit f, " (undocumented)" ;; +let mk_dcamlprimc f = + "-dcamlprimc", Arg.Unit f, " (undocumented)" +;; + let mk_dcmm f = "-dcmm", Arg.Unit f, " (undocumented)" ;; @@ -791,6 +843,7 @@ let mk__ f = module type Common_options = sig val _absname : unit -> unit + val _alert : string -> unit val _I : string -> unit val _labels : unit -> unit val _alias_deps : unit -> unit @@ -800,6 +853,7 @@ module type Common_options = sig val _noassert : unit -> unit val _nolabels : unit -> unit val _nostdlib : unit -> unit + val _nopervasives : unit -> unit val _open : string -> unit val _ppx : string -> unit val _principal : unit -> unit @@ -842,8 +896,10 @@ module type Compiler_options = sig val _cclib : string -> unit val _ccopt : string -> unit val _config : unit -> unit + val _config_var : string -> unit val _for_pack : string -> unit val _g : unit -> unit + val _stop_after : string -> unit val _i : unit -> unit val _impl : string -> unit val _intf : string -> unit @@ -872,10 +928,12 @@ module type Compiler_options = sig val _verbose : unit -> unit val _where : unit -> unit val _color : string -> unit + val _error_style : string -> unit - val _nopervasives : unit -> unit + val _match_context_rows : int -> unit val _dtimings : unit -> unit val _dprofile : unit -> unit + val _dump_into_file : unit -> unit val _args: string -> string array val _args0: string -> string array @@ -892,6 +950,8 @@ module type Toplevel_options = sig val _stdin : unit -> unit val _args : string -> string array val _args0 : string -> string array + val _color : string -> unit + val _error_style : string -> unit end ;; @@ -908,6 +968,7 @@ module type Bytecomp_options = sig val _use_runtime : string -> unit val _dinstr : unit -> unit + val _dcamlprimc : unit -> unit val _use_prims : string -> unit end;; @@ -1017,6 +1078,7 @@ module Make_bytecomp_options (F : Bytecomp_options) = struct let list = [ mk_a F._a; + mk_alert F._alert; mk_absname F._absname; mk_annot F._annot; mk_binannot F._binannot; @@ -1025,14 +1087,17 @@ struct mk_cclib F._cclib; mk_ccopt F._ccopt; mk_color F._color; + mk_error_style F._error_style; mk_compat_32 F._compat_32; mk_config F._config; + mk_config_var F._config_var; mk_custom F._custom; mk_dllib F._dllib; mk_dllpath F._dllpath; mk_dtypes F._annot; mk_for_pack_byt F._for_pack; mk_g_byt F._g; + mk_stop_after F._stop_after; mk_i F._i; mk_I F._I; mk_impl F._impl; @@ -1057,6 +1122,7 @@ struct mk_noautolink_byt F._noautolink; mk_nolabels F._nolabels; mk_nostdlib F._nostdlib; + mk_nopervasives F._nopervasives; mk_o F._o; mk_opaque F._opaque; mk_open F._open; @@ -1096,7 +1162,7 @@ struct mk_where F._where; mk__ F.anonymous; - mk_nopervasives F._nopervasives; + mk_match_context_rows F._match_context_rows; mk_use_prims F._use_prims; mk_dno_unique_ids F._dno_unique_ids; mk_dunique_ids F._dunique_ids; @@ -1106,8 +1172,10 @@ struct mk_drawlambda F._drawlambda; mk_dlambda F._dlambda; mk_dinstr F._dinstr; + mk_dcamlprimc F._dcamlprimc; mk_dtimings F._dtimings; mk_dprofile F._dprofile; + mk_dump_into_file F._dump_into_file; mk_args F._args; mk_args0 F._args0; @@ -1118,6 +1186,7 @@ module Make_bytetop_options (F : Bytetop_options) = struct let list = [ mk_absname F._absname; + mk_alert F._alert; mk_I F._I; mk_init F._init; mk_labels F._labels; @@ -1131,6 +1200,7 @@ struct mk_noprompt F._noprompt; mk_nopromptcont F._nopromptcont; mk_nostdlib F._nostdlib; + mk_nopervasives F._nopervasives; mk_open F._open; mk_ppx F._ppx; mk_principal F._principal; @@ -1156,6 +1226,8 @@ struct mk_warn_error F._warn_error; mk_warn_help F._warn_help; mk__ F.anonymous; + mk_color F._color; + mk_error_style F._error_style; mk_dno_unique_ids F._dno_unique_ids; mk_dunique_ids F._dunique_ids; @@ -1175,6 +1247,7 @@ module Make_optcomp_options (F : Optcomp_options) = struct let list = [ mk_a F._a; + mk_alert F._alert; mk_absname F._absname; mk_afl_instrument F._afl_instrument; mk_afl_inst_ratio F._afl_inst_ratio; @@ -1188,11 +1261,14 @@ struct mk_clambda_checks F._clambda_checks; mk_classic_inlining F._classic_inlining; mk_color F._color; + mk_error_style F._error_style; mk_compact F._compact; mk_config F._config; + mk_config_var F._config_var; mk_dtypes F._annot; mk_for_pack_opt F._for_pack; mk_g_opt F._g; + mk_stop_after F._stop_after; mk_i F._i; mk_I F._I; mk_impl F._impl; @@ -1225,6 +1301,7 @@ struct mk_nodynlink F._nodynlink; mk_nolabels F._nolabels; mk_nostdlib F._nostdlib; + mk_nopervasives F._nopervasives; mk_no_unbox_free_vars_of_closures F._no_unbox_free_vars_of_closures; mk_no_unbox_specialised_args F._no_unbox_specialised_args; mk_o F._o; @@ -1273,7 +1350,7 @@ struct mk_where F._where; mk__ F.anonymous; - mk_nopervasives F._nopervasives; + mk_match_context_rows F._match_context_rows; mk_dno_unique_ids F._dno_unique_ids; mk_dunique_ids F._dunique_ids; mk_dsource F._dsource; @@ -1308,6 +1385,7 @@ struct mk_dstartup F._dstartup; mk_dtimings F._dtimings; mk_dprofile F._dprofile; + mk_dump_into_file F._dump_into_file; mk_dump_pass F._dump_pass; mk_args F._args; @@ -1318,6 +1396,7 @@ end;; module Make_opttop_options (F : Opttop_options) = struct let list = [ mk_absname F._absname; + mk_alert F._alert; mk_compact F._compact; mk_I F._I; mk_init F._init; @@ -1345,6 +1424,7 @@ module Make_opttop_options (F : Opttop_options) = struct mk_noprompt F._noprompt; mk_nopromptcont F._nopromptcont; mk_nostdlib F._nostdlib; + mk_nopervasives F._nopervasives; mk_no_unbox_free_vars_of_closures F._no_unbox_free_vars_of_closures; mk_no_unbox_specialised_args F._no_unbox_specialised_args; mk_o2 F._o2; @@ -1379,6 +1459,8 @@ module Make_opttop_options (F : Opttop_options) = struct mk_warn_error F._warn_error; mk_warn_help F._warn_help; mk__ F.anonymous; + mk_color F._color; + mk_error_style F._error_style; mk_dsource F._dsource; mk_dparsetree F._dparsetree; @@ -1412,6 +1494,7 @@ module Make_ocamldoc_options (F : Ocamldoc_options) = struct let list = [ mk_absname F._absname; + mk_alert F._alert; mk_I F._I; mk_impl F._impl; mk_intf F._intf; diff --git a/driver/main_args.mli b/driver/main_args.mli index 4777f6b4..1dff86e7 100644 --- a/driver/main_args.mli +++ b/driver/main_args.mli @@ -18,6 +18,7 @@ module type Common_options = sig val _absname : unit -> unit + val _alert : string -> unit val _I : string -> unit val _labels : unit -> unit val _alias_deps : unit -> unit @@ -27,6 +28,7 @@ module type Common_options = sig val _noassert : unit -> unit val _nolabels : unit -> unit val _nostdlib : unit -> unit + val _nopervasives : unit -> unit val _open : string -> unit val _ppx : string -> unit val _principal : unit -> unit @@ -69,8 +71,10 @@ module type Compiler_options = sig val _cclib : string -> unit val _ccopt : string -> unit val _config : unit -> unit + val _config_var : string -> unit val _for_pack : string -> unit val _g : unit -> unit + val _stop_after : string -> unit val _i : unit -> unit val _impl : string -> unit val _intf : string -> unit @@ -99,10 +103,12 @@ module type Compiler_options = sig val _verbose : unit -> unit val _where : unit -> unit val _color : string -> unit + val _error_style : string -> unit - val _nopervasives : unit -> unit + val _match_context_rows : int -> unit val _dtimings : unit -> unit val _dprofile : unit -> unit + val _dump_into_file : unit -> unit val _args: string -> string array val _args0: string -> string array @@ -119,6 +125,8 @@ module type Toplevel_options = sig val _stdin : unit -> unit val _args: string -> string array val _args0: string -> string array + val _color : string -> unit + val _error_style : string -> unit end ;; @@ -136,6 +144,7 @@ module type Bytecomp_options = sig val _use_runtime : string -> unit val _dinstr : unit -> unit + val _dcamlprimc : unit -> unit val _use_prims : string -> unit end;; diff --git a/driver/makedepend.ml b/driver/makedepend.ml index 32d6e9d7..655a2510 100644 --- a/driver/makedepend.ml +++ b/driver/makedepend.ml @@ -15,7 +15,7 @@ open Compenv open Parsetree -module StringMap = Depend.StringMap +module String = Misc.Stdlib.String let ppf = Format.err_formatter (* Print the dependencies *) @@ -34,10 +34,10 @@ let sort_files = ref false let all_dependencies = ref false let one_line = ref false let files = - ref ([] : (string * file_kind * Depend.StringSet.t * string list) list) + ref ([] : (string * file_kind * String.Set.t * string list) list) let allow_approximation = ref false let map_files = ref [] -let module_map = ref StringMap.empty +let module_map = ref String.Map.empty let debug = ref false (* Fix path to use '/' as directory separator instead of '\'. @@ -50,10 +50,10 @@ let fix_slash s = (* Since we reinitialize load_path after reading OCAMLCOMP, we must use a cache instead of calling Sys.readdir too often. *) -let dirs = ref StringMap.empty +let dirs = ref String.Map.empty let readdir dir = try - StringMap.find dir !dirs + String.Map.find dir !dirs with Not_found -> let contents = try @@ -63,7 +63,7 @@ let readdir dir = error_occurred := true; [||] in - dirs := StringMap.add dir contents !dirs; + dirs := String.Map.add dir contents !dirs; contents let add_to_list li s = @@ -189,21 +189,36 @@ let print_filename s = ;; let print_dependencies target_files deps = - let rec print_items pos = function - [] -> print_string "\n" - | dep :: rem -> - if !one_line || (pos + 1 + String.length dep <= 77) then begin - if pos <> 0 then print_string " "; print_filename dep; - print_items (pos + String.length dep + 1) rem - end else begin - print_string escaped_eol; print_filename dep; - print_items (String.length dep + 4) rem - end in - print_items 0 (target_files @ [depends_on] @ deps) + let pos = ref 0 in + let print_on_same_line item = + if !pos <> 0 then print_string " "; + print_filename item; + pos := !pos + String.length item + 1; + in + let print_on_new_line item = + print_string escaped_eol; + print_filename item; + pos := String.length item + 4; + in + let print_compact item = + if !one_line || (!pos + 1 + String.length item <= 77) + then print_on_same_line item + else print_on_new_line item + in + let print_dep item = + if !one_line + then print_on_same_line item + else print_on_new_line item + in + List.iter print_compact target_files; + print_string " "; print_string depends_on; + pos := !pos + String.length depends_on + 1; + List.iter print_dep deps; + print_string "\n" let print_raw_dependencies source_file deps = print_filename source_file; print_string depends_on; - Depend.StringSet.iter + String.Set.iter (fun dep -> (* filter out "*predef*" *) if (String.length dep > 0) @@ -240,7 +255,7 @@ let rec lexical_approximation lexbuf = match Lexer.token lexbuf with | Parser.UIDENT name -> Depend.free_structure_names := - Depend.StringSet.add name !Depend.free_structure_names; + String.Set.add name !Depend.free_structure_names; process false lexbuf | Parser.LIDENT _ -> process true lexbuf | Parser.DOT when after_lident -> process false lexbuf @@ -259,7 +274,7 @@ let rec lexical_approximation lexbuf = let read_and_approximate inputfile = error_occurred := false; - Depend.free_structure_names := Depend.StringSet.empty; + Depend.free_structure_names := String.Set.empty; let ic = open_in_bin inputfile in try seek_in ic 0; @@ -277,14 +292,11 @@ let read_and_approximate inputfile = let read_parse_and_extract parse_function extract_function def ast_kind source_file = Depend.pp_deps := []; - Depend.free_structure_names := Depend.StringSet.empty; + Depend.free_structure_names := String.Set.empty; try let input_file = Pparse.preprocess source_file in begin try - let ast = - Pparse.file ~tool_name Format.err_formatter - input_file parse_function ast_kind - in + let ast = Pparse.file ~tool_name input_file parse_function ast_kind in let bound_vars = List.fold_left (fun bv modname -> @@ -301,7 +313,7 @@ let read_parse_and_extract parse_function extract_function def ast_kind with x -> begin report_err x; if not !allow_approximation - then (Depend.StringSet.empty, def) + then (String.Set.empty, def) else (read_and_approximate source_file, def) end @@ -323,7 +335,7 @@ let print_ml_dependencies source_file extracted_deps pp_deps = (if !all_dependencies then [cmi_name] else []) in let (byt_deps, native_deps) = - Depend.StringSet.fold (find_dependency ML) + String.Set.fold (find_dependency ML) extracted_deps init_deps in if not !native_only then print_dependencies (byte_targets @ extra_targets) (byt_deps @ pp_deps); @@ -339,7 +351,7 @@ let print_ml_dependencies source_file extracted_deps pp_deps = let print_mli_dependencies source_file extracted_deps pp_deps = let basename = Filename.chop_extension source_file in let (byt_deps, _opt_deps) = - Depend.StringSet.fold (find_dependency MLI) + String.Set.fold (find_dependency MLI) extracted_deps ([], []) in print_dependencies [basename ^ ".cmi"] (byt_deps @ pp_deps) @@ -425,7 +437,7 @@ let sort_files_by_dependencies files = let add_dep modname kind = new_deps := (modname, kind) :: !new_deps; in - Depend.StringSet.iter (fun modname -> + String.Set.iter (fun modname -> match file_kind with ML -> (* ML depends both on ML and MLI *) if Hashtbl.mem h (modname, MLI) then add_dep modname MLI; @@ -463,9 +475,8 @@ let sort_files_by_dependencies files = done; if !worklist <> [] then begin - Format.fprintf Format.err_formatter - "@[%t: cycle in dependencies. End of list is not sorted.@]@." - Location.print_error_prefix; + Location.error "cycle in dependencies. End of list is not sorted." + |> Location.print_report Format.err_formatter; let sorted_deps = let li = ref [] in Hashtbl.iter (fun _ file_deps -> li := file_deps :: !li) h; @@ -488,30 +499,30 @@ let sort_files_by_dependencies files = let rec dump_map s0 ppf m = let open Depend in - StringMap.iter + String.Map.iter (fun key (Node(s1,m')) -> - let s = StringSet.diff s1 s0 in - if StringSet.is_empty s then + let s = String.Set.diff s1 s0 in + if String.Set.is_empty s then Format.fprintf ppf "@ @[module %s : sig%a@;<1 -2>end@]" - key (dump_map (StringSet.union s1 s0)) m' + key (dump_map (String.Set.union s1 s0)) m' else - Format.fprintf ppf "@ module %s = %s" key (StringSet.choose s)) + Format.fprintf ppf "@ module %s = %s" key (String.Set.choose s)) m let process_ml_map = read_parse_and_extract Parse.implementation Depend.add_implementation_binding - StringMap.empty Pparse.Structure + String.Map.empty Pparse.Structure let process_mli_map = read_parse_and_extract Parse.interface Depend.add_signature_binding - StringMap.empty Pparse.Signature + String.Map.empty Pparse.Signature let parse_map fname = map_files := fname :: !map_files ; let old_transp = !Clflags.transparent_modules in Clflags.transparent_modules := true; let (deps, m) = - process_file fname ~def:(Depend.StringSet.empty, StringMap.empty) + process_file fname ~def:(String.Set.empty, String.Map.empty) ~ml_file:process_ml_map ~mli_file:process_mli_map in @@ -519,16 +530,16 @@ let parse_map fname = let modname = String.capitalize_ascii (Filename.basename (Filename.chop_extension fname)) in - if StringMap.is_empty m then + if String.Map.is_empty m then report_err (Failure (fname ^ " : empty map file or parse error")); let mm = Depend.make_node m in if !debug then begin Format.printf "@[%s:%t%a@]@." fname - (fun ppf -> Depend.StringSet.iter (Format.fprintf ppf " %s") deps) - (dump_map deps) (StringMap.add modname mm StringMap.empty) + (fun ppf -> String.Set.iter (Format.fprintf ppf " %s") deps) + (dump_map deps) (String.Map.add modname mm String.Map.empty) end; - let mm = Depend.(weaken_map (StringSet.singleton modname) mm) in - module_map := StringMap.add modname mm !module_map + let mm = Depend.(weaken_map (String.Set.singleton modname) mm) in + module_map := String.Map.add modname mm !module_map ;; @@ -550,7 +561,7 @@ let main () = Compenv.readenv ppf Before_args; Clflags.reset_arguments (); (* reset arguments from ocamlc/ocamlopt *) Clflags.add_arguments __LOC__ [ - "-absname", Arg.Set Location.absname, + "-absname", Arg.Set Clflags.absname, " Show absolute filenames in error messages"; "-all", Arg.Set all_dependencies, " Generate dependencies on all files"; diff --git a/driver/optcompile.ml b/driver/optcompile.ml index d5b64c0f..85c655e9 100644 --- a/driver/optcompile.ml +++ b/driver/optcompile.ml @@ -13,133 +13,75 @@ (* *) (**************************************************************************) -(* The batch compiler *) +(** The batch compiler *) open Misc -open Config -open Format -open Typedtree -open Compenv +open Compile_common -(* Compile a .mli file *) +let tool_name = "ocamlopt" -(* Keep in sync with the copy in compile.ml *) +let with_info = + Compile_common.with_info ~native:true ~tool_name -let tool_name = "ocamlopt" +let interface ~source_file ~output_prefix = + with_info ~source_file ~output_prefix ~dump_ext:"cmi" @@ fun info -> + Compile_common.interface info -let interface ppf sourcefile outputprefix = - Profile.record_call sourcefile (fun () -> - Compmisc.init_path false; - let modulename = module_of_filename ppf sourcefile outputprefix in - Env.set_unit_name modulename; - let initial_env = Compmisc.initial_env () in - let ast = Pparse.parse_interface ~tool_name ppf sourcefile in - if !Clflags.dump_parsetree then fprintf ppf "%a@." Printast.interface ast; - if !Clflags.dump_source then fprintf ppf "%a@." Pprintast.signature ast; - Profile.(record_call typing) (fun () -> - let tsg = Typemod.type_interface sourcefile initial_env ast in - if !Clflags.dump_typedtree then fprintf ppf "%a@." Printtyped.interface tsg; - let sg = tsg.sig_type in - if !Clflags.print_types then - Printtyp.wrap_printing_env ~error:false initial_env (fun () -> - fprintf std_formatter "%a@." - Printtyp.signature (Typemod.simplify_signature sg)); - ignore (Includemod.signatures initial_env sg sg); - Typecore.force_delayed_checks (); - Warnings.check_fatal (); - if not !Clflags.print_types then begin - let deprecated = Builtin_attributes.deprecated_of_sig ast in - let sg = - Env.save_signature ~deprecated sg modulename (outputprefix ^ ".cmi") - in - Typemod.save_signature modulename tsg outputprefix sourcefile - initial_env sg ; - end - ) - ) +let (|>>) (x, y) f = (x, f y) -(* Compile a .ml file *) +(** Native compilation backend for .ml files. *) -let print_if ppf flag printer arg = - if !flag then fprintf ppf "%a@." printer arg; - arg +let flambda i backend typed = + if !Clflags.classic_inlining then begin + Clflags.default_simplify_rounds := 1; + Clflags.use_inlining_arguments_set Clflags.classic_arguments; + Clflags.unbox_free_vars_of_closures := false; + Clflags.unbox_specialised_args := false + end; + typed + |> Profile.(record transl) + (Translmod.transl_implementation_flambda i.module_name) + |> Profile.(record generate) + (fun {Lambda.module_ident; main_module_block_size; + required_globals; code } -> + ((module_ident, main_module_block_size), code) + |>> print_if i.ppf_dump Clflags.dump_rawlambda Printlambda.lambda + |>> Simplif.simplify_lambda i.source_file + |>> print_if i.ppf_dump Clflags.dump_lambda Printlambda.lambda + |> (fun ((module_ident, size), lam) -> + Middle_end.middle_end + ~ppf_dump:i.ppf_dump + ~prefixname:i.output_prefix + ~size + ~filename:i.source_file + ~module_ident + ~backend + ~module_initializer:lam) + |> Asmgen.compile_implementation_flambda + i.output_prefix ~required_globals ~backend ~ppf_dump:i.ppf_dump; + Compilenv.save_unit_info (cmx i)) -let (++) x f = f x -let (+++) (x, y) f = (x, f y) +let clambda i typed = + Clflags.use_inlining_arguments_set Clflags.classic_arguments; + typed + |> Profile.(record transl) + (Translmod.transl_store_implementation i.module_name) + |> print_if i.ppf_dump Clflags.dump_rawlambda Printlambda.program + |> Profile.(record generate) + (fun program -> + let code = Simplif.simplify_lambda i.source_file program.Lambda.code in + { program with Lambda.code } + |> print_if i.ppf_dump Clflags.dump_lambda Printlambda.program + |> Asmgen.compile_implementation_clambda + i.output_prefix ~ppf_dump:i.ppf_dump; + Compilenv.save_unit_info (cmx i)) -let implementation ~backend ppf sourcefile outputprefix = - Profile.record_call sourcefile (fun () -> - Compmisc.init_path true; - let modulename = module_of_filename ppf sourcefile outputprefix in - Env.set_unit_name modulename; - let env = Compmisc.initial_env() in - Compilenv.reset ?packname:!Clflags.for_package modulename; - let cmxfile = outputprefix ^ ".cmx" in - let objfile = outputprefix ^ ext_obj in - let comp ast = - let (typedtree, coercion) = - ast - ++ print_if ppf Clflags.dump_parsetree Printast.implementation - ++ print_if ppf Clflags.dump_source Pprintast.structure - ++ Profile.(record typing) - (Typemod.type_implementation sourcefile outputprefix modulename env) - ++ print_if ppf Clflags.dump_typedtree - Printtyped.implementation_with_coercion - in - if not !Clflags.print_types then begin - if Config.flambda then begin - if !Clflags.classic_inlining then begin - Clflags.default_simplify_rounds := 1; - Clflags.use_inlining_arguments_set Clflags.classic_arguments; - Clflags.unbox_free_vars_of_closures := false; - Clflags.unbox_specialised_args := false - end; - (typedtree, coercion) - ++ Profile.(record transl) - (Translmod.transl_implementation_flambda modulename) - ++ Profile.(record generate) - (fun { Lambda.module_ident; main_module_block_size; - required_globals; code } -> - ((module_ident, main_module_block_size), code) - +++ print_if ppf Clflags.dump_rawlambda Printlambda.lambda - +++ Simplif.simplify_lambda sourcefile - +++ print_if ppf Clflags.dump_lambda Printlambda.lambda - ++ (fun ((module_ident, size), lam) -> - Middle_end.middle_end ppf - ~prefixname:outputprefix - ~size - ~filename:sourcefile - ~module_ident - ~backend - ~module_initializer:lam) - ++ Asmgen.compile_implementation_flambda - outputprefix ~required_globals ~backend ppf; - Compilenv.save_unit_info cmxfile) - end - else begin - Clflags.use_inlining_arguments_set Clflags.classic_arguments; - (typedtree, coercion) - ++ Profile.(record transl) - (Translmod.transl_store_implementation modulename) - ++ print_if ppf Clflags.dump_rawlambda Printlambda.program - ++ Profile.(record generate) - (fun program -> - { program with - Lambda.code = Simplif.simplify_lambda sourcefile - program.Lambda.code } - ++ print_if ppf Clflags.dump_lambda Printlambda.program - ++ Asmgen.compile_implementation_clambda - outputprefix ppf; - Compilenv.save_unit_info cmxfile) - end - end; - Warnings.check_fatal (); - Stypes.dump (Some (outputprefix ^ ".annot")) - in - try comp (Pparse.parse_implementation ~tool_name ppf sourcefile) - with x -> - Stypes.dump (Some (outputprefix ^ ".annot")); - remove_file objfile; - remove_file cmxfile; - raise x - ) +let implementation ~backend ~source_file ~output_prefix = + let backend info typed = + Compilenv.reset ?packname:!Clflags.for_package info.module_name; + if Config.flambda + then flambda info backend typed + else clambda info typed + in + with_info ~source_file ~output_prefix ~dump_ext:"cmx" @@ fun info -> + Compile_common.implementation info ~backend diff --git a/driver/optcompile.mli b/driver/optcompile.mli index 3f308138..27cd1e0d 100644 --- a/driver/optcompile.mli +++ b/driver/optcompile.mli @@ -13,15 +13,27 @@ (* *) (**************************************************************************) -(* Compile a .ml or .mli file *) +(** Native compilation for .ml and .mli files. *) -open Format - -val interface: formatter -> string -> string -> unit +val interface: source_file:string -> output_prefix:string -> unit val implementation: backend:(module Backend_intf.S) - -> formatter - -> string - -> string - -> unit + -> source_file:string -> output_prefix:string -> unit + +(** {2 Internal functions} **) + +val clambda : + Compile_common.info -> + Typedtree.structure * Typedtree.module_coercion -> unit +(** [clambda info typed] applies the regular compilation pipeline to the + given typechecked implementation and outputs the resulting files. +*) + +val flambda : + Compile_common.info -> + (module Backend_intf.S) -> + Typedtree.structure * Typedtree.module_coercion -> unit +(** [flambda info backend typed] applies the Flambda compilation pipeline to the + given typechecked implementation and outputs the resulting files. +*) diff --git a/driver/optmain.ml b/driver/optmain.ml index 44b49304..b6881571 100644 --- a/driver/optmain.ml +++ b/driver/optmain.ml @@ -36,19 +36,15 @@ let backend = (module Backend : Backend_intf.S) let usage = "Usage: ocamlopt \nOptions are:" -let show_config () = - Config.print_config stdout; - exit 0; -;; - module Options = Main_args.Make_optcomp_options (struct let set r () = r := true let clear r () = r := false let _a = set make_archive - let _absname = set Location.absname + let _absname = set Clflags.absname let _afl_instrument = set afl_instrument let _afl_inst_ratio n = afl_inst_ratio := n + let _alert = Warnings.parse_alert_option let _annot = set annotations let _binannot = set binary_annotations let _c = set compile_only @@ -57,10 +53,26 @@ module Options = Main_args.Make_optcomp_options (struct let _ccopt s = first_ccopts := s :: !first_ccopts let _clambda_checks () = clambda_checks := true let _compact = clear optimize_for_speed - let _config () = show_config () + let _config = Misc.show_config_and_exit + let _config_var = Misc.show_config_variable_and_exit let _for_pack s = for_package := Some s let _g = set debug - let _i () = print_types := true; compile_only := true + let _i () = + print_types := true; + compile_only := true; + stop_after := Some Compiler_pass.Typing; + () + let _stop_after pass = + let module P = Compiler_pass in + begin match P.of_string pass with + | None -> () (* this should not occur as we use Arg.Symbol *) + | Some pass -> + stop_after := Some pass; + begin match pass with + | P.Parsing | P.Typing -> + compile_only := true + end; + end let _I dir = include_dirs := dir :: !include_dirs let _impl = impl let _inline spec = @@ -178,7 +190,7 @@ module Options = Main_args.Make_optcomp_options (struct let _unbox_closures_factor f = unbox_closures_factor := f let _unboxed_types = set unboxed_types let _no_unboxed_types = clear unboxed_types - let _unsafe = set fast + let _unsafe = set unsafe let _unsafe_string = set unsafe_string let _v () = print_version_and_library "native-code compiler" let _version () = print_version_string () @@ -187,14 +199,12 @@ module Options = Main_args.Make_optcomp_options (struct let _w s = Warnings.parse_options false s let _warn_error s = Warnings.parse_options true s let _warn_help = Warnings.help_warnings - let _color option = - begin match parse_color_setting option with - | None -> () - | Some setting -> color := Some setting - end + let _color = Misc.set_or_ignore color_reader.parse color + let _error_style = Misc.set_or_ignore error_style_reader.parse error_style let _where () = print_standard_library () - let _nopervasives = set nopervasives + let _match_context_rows n = match_context_rows := n + let _dump_into_file = set dump_into_file let _dno_unique_ids = clear unique_ids let _dunique_ids = set unique_ids let _dsource = set dump_source @@ -247,9 +257,10 @@ let main () = Clflags.add_arguments __LOC__ (Arch.command_line_options @ Options.list); Clflags.add_arguments __LOC__ ["-depend", Arg.Unit Makedepend.main_from_option, - " Compute dependencies (use 'ocamlopt -depend -help' for details)"]; + " Compute dependencies \ + (use 'ocamlopt -depend -help' for details)"]; Clflags.parse_arguments anonymous usage; - Compmisc.read_color_env ppf; + Compmisc.read_clflags_from_env (); if !gprofile && not Config.profiling then fatal "Profiling with \"gprof\" is not supported on this platform."; begin try @@ -272,24 +283,29 @@ let main () = [make_package; make_archive; shared; compile_only; output_c_object]) > 1 then - fatal "Please specify at most one of -pack, -a, -shared, -c, -output-obj"; + fatal "Please specify at most one of -pack, -a, -shared, -c, \ + -output-obj"; if !make_archive then begin Compmisc.init_path true; let target = extract_output !output_name in - Asmlibrarian.create_archive (get_objfiles ~with_ocamlparam:false) target; + Asmlibrarian.create_archive + (get_objfiles ~with_ocamlparam:false) target; Warnings.check_fatal (); end else if !make_package then begin Compmisc.init_path true; let target = extract_output !output_name in - Asmpackager.package_files ppf (Compmisc.initial_env ()) - (get_objfiles ~with_ocamlparam:false) target ~backend; + Compmisc.with_ppf_dump ~file_prefix:target (fun ppf_dump -> + Asmpackager.package_files ~ppf_dump (Compmisc.initial_env ()) + (get_objfiles ~with_ocamlparam:false) target ~backend); Warnings.check_fatal (); end else if !shared then begin Compmisc.init_path true; let target = extract_output !output_name in - Asmlink.link_shared ppf (get_objfiles ~with_ocamlparam:false) target; + Compmisc.with_ppf_dump ~file_prefix:target (fun ppf_dump -> + Asmlink.link_shared ~ppf_dump + (get_objfiles ~with_ocamlparam:false) target); Warnings.check_fatal (); end else if not !compile_only && !objfiles <> [] then begin @@ -309,7 +325,8 @@ let main () = default_output !output_name in Compmisc.init_path true; - Asmlink.link ppf (get_objfiles ~with_ocamlparam:true) target; + Compmisc.with_ppf_dump ~file_prefix:target (fun ppf_dump -> + Asmlink.link ~ppf_dump (get_objfiles ~with_ocamlparam:true) target); Warnings.check_fatal (); end; with x -> diff --git a/driver/pparse.ml b/driver/pparse.ml index cb78d848..0b08b8c8 100644 --- a/driver/pparse.ml +++ b/driver/pparse.ml @@ -92,19 +92,15 @@ let apply_rewriter kind fn_in ppx = let read_ast (type a) (kind : a ast_kind) fn : a = let ic = open_in_bin fn in - try - let magic = magic_of_kind kind in - let buffer = really_input_string ic (String.length magic) in - assert(buffer = magic); (* already checked by apply_rewriter *) - Location.input_name := (input_value ic : string); - let ast = (input_value ic : a) in - close_in ic; - Misc.remove_file fn; - ast - with exn -> - close_in ic; - Misc.remove_file fn; - raise exn + Misc.try_finally + ~always:(fun () -> close_in ic; Misc.remove_file fn) + (fun () -> + let magic = magic_of_kind kind in + let buffer = really_input_string ic (String.length magic) in + assert(buffer = magic); (* already checked by apply_rewriter *) + Location.input_name := (input_value ic : string); + (input_value ic : a) + ) let rewrite kind ppxs ast = let fn = Filename.temp_file "camlppx" "" in @@ -116,19 +112,25 @@ let apply_rewriters_str ?(restore = true) ~tool_name ast = match !Clflags.all_ppx with | [] -> ast | ppxs -> - ast - |> Ast_mapper.add_ppx_context_str ~tool_name - |> rewrite Structure ppxs - |> Ast_mapper.drop_ppx_context_str ~restore + let ast = + ast + |> Ast_mapper.add_ppx_context_str ~tool_name + |> rewrite Structure ppxs + |> Ast_mapper.drop_ppx_context_str ~restore + in + Ast_invariants.structure ast; ast let apply_rewriters_sig ?(restore = true) ~tool_name ast = match !Clflags.all_ppx with | [] -> ast | ppxs -> - ast - |> Ast_mapper.add_ppx_context_sig ~tool_name - |> rewrite Signature ppxs - |> Ast_mapper.drop_ppx_context_sig ~restore + let ast = + ast + |> Ast_mapper.add_ppx_context_sig ~tool_name + |> rewrite Signature ppxs + |> Ast_mapper.drop_ppx_context_sig ~restore + in + Ast_invariants.signature ast; ast let apply_rewriters ?restore ~tool_name (type a) (kind : a ast_kind) (ast : a) : a = @@ -163,36 +165,37 @@ let parse (type a) (kind : a ast_kind) lexbuf : a = | Structure -> Parse.implementation lexbuf | Signature -> Parse.interface lexbuf -let file_aux ppf ~tool_name inputfile (type a) parse_fun invariant_fun - (kind : a ast_kind) = +let file_aux ~tool_name inputfile (type a) parse_fun invariant_fun + (kind : a ast_kind) : a = let ast_magic = magic_of_kind kind in let (ic, is_ast_file) = open_and_check_magic inputfile ast_magic in let ast = try if is_ast_file then begin - if !Clflags.fast then - (* FIXME make this a proper warning *) - fprintf ppf "@[Warning: %s@]@." - "option -unsafe used with a preprocessor returning a syntax tree"; Location.input_name := (input_value ic : string); - (input_value ic : a) + if !Clflags.unsafe then + Location.prerr_warning (Location.in_file !Location.input_name) + Warnings.Unsafe_without_parsing; + let ast = (input_value ic : a) in + if !Clflags.all_ppx = [] then invariant_fun ast; + (* if all_ppx <> [], invariant_fun will be called by apply_rewriters *) + ast end else begin seek_in ic 0; let lexbuf = Lexing.from_channel ic in Location.init lexbuf inputfile; + Location.input_lexbuf := Some lexbuf; Profile.record_call "parser" (fun () -> parse_fun lexbuf) end with x -> close_in ic; raise x in close_in ic; - let ast = - Profile.record_call "-ppx" (fun () -> - apply_rewriters ~restore:false ~tool_name kind ast) in - if is_ast_file || !Clflags.all_ppx <> [] then invariant_fun ast; - ast + Profile.record_call "-ppx" (fun () -> + apply_rewriters ~restore:false ~tool_name kind ast + ) -let file ppf ~tool_name inputfile parse_fun ast_kind = - file_aux ppf ~tool_name inputfile parse_fun ignore ast_kind +let file ~tool_name inputfile parse_fun ast_kind = + file_aux ~tool_name inputfile parse_fun ignore ast_kind let report_error ppf = function | CannotRun cmd -> @@ -209,18 +212,14 @@ let () = | _ -> None ) -let parse_file ~tool_name invariant_fun apply_hooks kind ppf sourcefile = +let parse_file ~tool_name invariant_fun parse kind sourcefile = Location.input_name := sourcefile; let inputfile = preprocess sourcefile in - let ast = - try file_aux ppf ~tool_name inputfile (parse kind) invariant_fun kind - with exn -> - remove_preprocessed inputfile; - raise exn - in - remove_preprocessed inputfile; - let ast = apply_hooks { Misc.sourcefile } ast in - ast + Misc.try_finally + (fun () -> + Profile.record_call "parsing" @@ fun () -> + file_aux ~tool_name inputfile parse invariant_fun kind) + ~always:(fun () -> remove_preprocessed inputfile) module ImplementationHooks = Misc.MakeHooks(struct type t = Parsetree.structure @@ -229,11 +228,12 @@ module InterfaceHooks = Misc.MakeHooks(struct type t = Parsetree.signature end) -let parse_implementation ppf ~tool_name sourcefile = - Profile.record_call "parsing" (fun () -> - parse_file ~tool_name Ast_invariants.structure - ImplementationHooks.apply_hooks Structure ppf sourcefile) -let parse_interface ppf ~tool_name sourcefile = - Profile.record_call "parsing" (fun () -> - parse_file ~tool_name Ast_invariants.signature - InterfaceHooks.apply_hooks Signature ppf sourcefile) +let parse_implementation ~tool_name sourcefile = + parse_file ~tool_name Ast_invariants.structure + (parse Structure) Structure sourcefile + |> ImplementationHooks.apply_hooks { Misc.sourcefile } + +let parse_interface ~tool_name sourcefile = + parse_file ~tool_name Ast_invariants.signature + (parse Signature) Signature sourcefile + |> InterfaceHooks.apply_hooks { Misc.sourcefile } diff --git a/driver/pparse.mli b/driver/pparse.mli index 4c5fc0f6..73eff187 100644 --- a/driver/pparse.mli +++ b/driver/pparse.mli @@ -13,7 +13,12 @@ (* *) (**************************************************************************) -(** Driver for the parser, external preprocessors and ast plugin hooks *) +(** Driver for the parser, external preprocessors and ast plugin hooks + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) open Format @@ -33,7 +38,7 @@ type 'a ast_kind = val read_ast : 'a ast_kind -> string -> 'a val write_ast : 'a ast_kind -> string -> 'a -> unit -val file : formatter -> tool_name:string -> string -> +val file : tool_name:string -> string -> (Lexing.lexbuf -> 'a) -> 'a ast_kind -> 'a val apply_rewriters: ?restore:bool -> tool_name:string -> @@ -52,9 +57,9 @@ val report_error : formatter -> error -> unit val parse_implementation: - formatter -> tool_name:string -> string -> Parsetree.structure + tool_name:string -> string -> Parsetree.structure val parse_interface: - formatter -> tool_name:string -> string -> Parsetree.signature + tool_name:string -> string -> Parsetree.signature (* [call_external_preprocessor sourcefile pp] *) val call_external_preprocessor : string -> string -> string diff --git a/dune b/dune new file mode 100644 index 00000000..a528f184 --- /dev/null +++ b/dune @@ -0,0 +1,177 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +(env + (dev (flags (:standard -w +a-4-9-41-42-44-45-48))) + (release (flags (:standard -w +a-4-9-41-42-44-45-48)))) + +;; Too annoying to get to work. Use (copy_files# ...) instead +; (include_subdirs unqualified) +; (ignored_subdirs (lex yacc testsuite ocamldoc ocamltest toplevel otherlibs)) + +(copy_files# utils/*.ml{,i}) +(copy_files# parsing/*.ml{,i}) +(copy_files# typing/*.ml{,i}) +(copy_files# bytecomp/*.ml{,i}) +(copy_files# driver/*.ml{,i}) +(copy_files# asmcomp/*.ml{,i}) +(copy_files# asmcomp/debug/*.ml{,i}) +(copy_files# middle_end/*.ml{,i}) +(copy_files# middle_end/base_types/*.ml{,i}) + +(library + (name ocamlcommon) + (wrapped false) + (flags (:standard -principal -nostdlib)) + (libraries stdlib) + (modules_without_implementation + annot asttypes cmo_format outcometree parsetree) + (modules + ;; UTILS + config build_path_prefix_map misc identifiable numbers arg_helper clflags + profile terminfo ccomp warnings consistbl strongly_connected_components + targetint load_path + + ;; PARSING + location longident docstrings syntaxerr ast_helper camlinternalMenhirLib + parser lexer parse printast pprintast ast_mapper ast_iterator attr_helper + builtin_attributes ast_invariants depend + ; manual update: mli only files + asttypes parsetree + + ;; TYPING + ident path primitive types btype oprint subst predef datarepr cmi_format env + typedtree printtyped ctype printtyp includeclass mtype envaux includecore + typedtreeIter tast_mapper cmt_format untypeast includemod + typetexp printpat parmatch stypes typedecl typeopt rec_check typecore + typeclass typemod typedecl_variance typedecl_properties typedecl_immediacy + typedecl_unboxed + ; manual update: mli only files + annot outcometree + + ;; COMP + lambda printlambda semantics_of_primitives switch matching translobj + translattribute translprim translcore translclass translmod simplif + runtimedef meta opcodes bytesections dll symtable pparse main_args compenv + compmisc compdynlink_types compdynlink_platform_intf compdynlink_common + compdynlink compplugin makedepend compile_common + ; manual update: mli only files + cmo_format + ; manual update: this is required. + instruct + )) + +(library + (name ocamlbytecomp) + (wrapped false) + (flags (:standard -principal -nostdlib)) + (libraries stdlib ocamlcommon) + (modules + bytegen printinstr emitcode bytelink bytelibrarian bytepackager errors + compile)) + +(library + (name ocamloptcomp) + (wrapped false) + (flags (:standard -principal -nostdlib)) + (libraries stdlib ocamlcommon) + (modules_without_implementation + cmx_format x86_ast backend_intf inlining_decision_intf + simplify_boxed_integer_ops_intf) + (modules + ;; ASMCOMP + arch backend_var cmm printcmm reg reg_with_debug_info reg_availability_set + mach proc clambda printclambda export_info export_info_for_pack compilenv + closure traverse_for_exported_symbols build_export_info closure_offsets + flambda_to_clambda import_approx un_anf afl_instrument strmatch cmmgen + interval printmach selectgen spacetime_profiling selection comballoc CSEgen + CSE liveness spill split interf coloring linscan reloadgen reload deadcode + printlinear linearize available_regs schedgen scheduling + branch_relaxation_intf branch_relaxation emitaux emit asmgen asmlink + asmlibrarian asmpackager opterrors optcompile + ; manual update: mli only files + cmx_format + + ; arch specific files: we always include them even though depending on the + ; target architecture they might not be used. + x86_ast + x86_proc + x86_dsl + x86_gas + x86_masm + + ;; MIDDLE_END + int_replace_polymorphic_compare debuginfo tag linkage_name compilation_unit + internal_variable_names variable mutable_variable id_types set_of_closures_id + set_of_closures_origin closure_element closure_id closure_origin + var_within_closure static_exception export_id symbol pass_wrapper + allocated_const parameter projection flambda flambda_iterators flambda_utils + inlining_cost effect_analysis freshening simple_value_approx lift_code + closure_conversion_aux closure_conversion initialize_symbol_to_let_symbol + lift_let_to_initialize_symbol find_recursive_functions invariant_params + inconstant_idents alias_analysis lift_constants share_constants + simplify_common remove_unused_arguments remove_unused_closure_vars + remove_unused_program_constructs simplify_boxed_integer_ops + simplify_primitives inlining_stats_types inlining_stats + inline_and_simplify_aux remove_free_vars_equal_to_args extract_projections + augment_specialised_args unbox_free_vars_of_closures unbox_specialised_args + unbox_closures inlining_transforms inlining_decision inline_and_simplify + ref_to_variables flambda_invariants middle_end + ; manual update: mli only files + backend_intf inlining_decision_intf simplify_boxed_integer_ops_intf + ) +) + +;;;;;;;;;;;;;; +;;; ocamlc ;;; +;;;;;;;;;;;;;; + +(executable + (name main) + (modes byte) + (flags (:standard -principal -nostdlib)) + (libraries ocamlbytecomp ocamlcommon runtime stdlib) + (modules main)) + +(rule + (copy main.exe ocamlc.byte)) + +;;;;;;;;;;;;;;;; +;;; ocamlopt ;;; +;;;;;;;;;;;;;;;; + +(executable + (name optmain) + (modes byte) + (flags (:standard -principal -nostdlib)) + (libraries ocamloptcomp ocamlcommon runtime stdlib) + (modules optmain)) + +(rule + (copy optmain.exe ocamlopt.byte)) + +;;;;;;;;;;;;;;; +;;; aliases ;;; +;;;;;;;;;;;;;;; + +(alias + (name world) + (deps ocamlc.byte + ocamlopt.byte + debugger/ocamldebug.byte + ocamldoc/ocamldoc.byte + ocamltest/ocamltest.byte + toplevel/ocaml.byte + toplevel/expunge.exe + )) diff --git a/dune-project b/dune-project new file mode 100644 index 00000000..ce151941 --- /dev/null +++ b/dune-project @@ -0,0 +1,2 @@ +(lang dune 1.3) +(using experimental_building_ocaml_compiler_with_dune 0.1) diff --git a/emacs/COPYING b/emacs/COPYING deleted file mode 100644 index 5b6e7c66..00000000 --- a/emacs/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/emacs/Makefile b/emacs/Makefile deleted file mode 100644 index dcb7a958..00000000 --- a/emacs/Makefile +++ /dev/null @@ -1,85 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1997 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU General Public License. * -#* * -#************************************************************************** - -include ../config/Makefile -include ../Makefile.common - -# Files to install -FILES= caml-font.el caml-hilit.el caml.el camldebug.el \ - inf-caml.el caml-compat.el caml-help.el caml-types.el \ - caml-xemacs.el caml-emacs.el - -# Where to install. If empty, automatically determined. -#EMACSDIR= - -# Name of Emacs executable -EMACS=emacs - -# Where to install ocamltags script -SCRIPTDIR = $(BINDIR) - -# Command for byte-compiling the files -COMPILECMD=(progn \ - (setq load-path (cons "." load-path)) \ - (byte-compile-file "caml-xemacs.el") \ - (byte-compile-file "caml-emacs.el") \ - (byte-compile-file "caml.el") \ - (byte-compile-file "inf-caml.el") \ - (byte-compile-file "caml-help.el") \ - (byte-compile-file "caml-types.el") \ - (byte-compile-file "caml-font.el") \ - (byte-compile-file "camldebug.el")) - -install: - @if test "$(EMACSDIR)" = ""; then \ - $(EMACS) --batch --eval 't; see PR#5403'; \ - set xxx `($(EMACS) --batch --eval "(mapcar 'print load-path)") \ - 2>/dev/null | \ - sed -n -e 's/^"\(.*\/site-lisp\).*/\1/gp' | \ - sort -u`; \ - if test "$$2" = "" -o "$$3" != ""; then \ - echo "Cannot determine Emacs site-lisp directory:"; \ - shift; while test "$$1" != ""; do echo "\t$$1"; shift; done; \ - else \ - $(MAKE) EMACSDIR="$$2" simple-install; \ - fi; \ - else \ - $(MAKE) simple-install; \ - fi - -# install the .el files, but do not compile them. -install-el: - $(MAKE) NOCOMPILE=true install - -simple-install: - @echo "Installing in $(EMACSDIR)..." - if test -d $(EMACSDIR); then : ; else mkdir -p $(EMACSDIR); fi - $(INSTALL_DATA) $(FILES) $(EMACSDIR) - if [ -z "$(NOCOMPILE)" ]; then \ - cd $(EMACSDIR); $(EMACS) --batch --eval '$(COMPILECMD)'; \ - fi - -ocamltags: ocamltags.in - sed -e 's:@EMACS@:$(EMACS):' ocamltags.in >ocamltags - chmod a+x ocamltags - -install-ocamltags: ocamltags - $(INSTALL_DATA) ocamltags $(SCRIPTDIR)/ocamltags - -# This is for testing purposes -compile-only: - $(EMACS) --batch --eval '$(COMPILECMD)' - -clean: - rm -f ocamltags *~ \#*# *.elc diff --git a/emacs/README b/emacs/README deleted file mode 100644 index 9c30c889..00000000 --- a/emacs/README +++ /dev/null @@ -1,209 +0,0 @@ - OCaml emacs mode, snapshot of $Date$ - -The files in this archive define a caml-mode for emacs, for editing -OCaml and Objective Label programs, as well as an -inferior-caml-mode, to run a toplevel. - -Caml-mode supports indentation, compilation and error retrieving, -sending phrases to the toplevel. Moreover support for hilit, -font-lock and imenu was added. - -This package is based on the original caml-mode for caml-light by -Xavier Leroy, extended with indentation by Ian Zimmerman. For details -see README.itz, which is the README from Ian Zimmerman's package. - -To use it, just put the .el files in your emacs load path, and add the -following lines in your .emacs. - - (add-to-list 'auto-mode-alist '("\\.ml[iylp]?$" . caml-mode)) - (autoload 'caml-mode "caml" "Major mode for editing OCaml code." t) - (autoload 'run-caml "inf-caml" "Run an inferior OCaml process." t) - (autoload 'camldebug "camldebug" "Run ocamldebug on program." t) - (add-to-list 'interpreter-mode-alist '("ocamlrun" . caml-mode)) - (add-to-list 'interpreter-mode-alist '("ocaml" . caml-mode)) - -or put the .el files in, eg. "/usr/share/emacs/site-lisp/caml-mode/" -and add the following line in addtion to the four lines above: - - (add-to-list 'load-path "/usr/share/emacs/site-lisp/caml-mode") - -To install the mode itself, edit the Makefile and do - - % make install - -To install ocamltags, do - - % make install-ocamltags - -To use highlighting capabilities, add ONE of the following two lines -to your .emacs. The second one works better on recent versions of -emacs. - - (if window-system (require 'caml-hilit)) - (if window-system (require 'caml-font)) - -caml.el and inf-caml.el can be used collectively, but it might be a -good idea to copy caml-hilit.el or caml-font.el to you own directory, -and edit it to your taste and colors. - -Main key bindings: - -TAB indent current line -M-C-q indent phrase -M-C-h mark phrase -C-c C-a switch between interface and implementation -C-c C-c compile (usually make) -C-x` goto next error (also mouse button 2 in the compilation log) - -Once you have started caml by M-x run-caml: - -M-C-x send phrase to inferior caml process -C-c C-r send region to inferior caml process -C-c C-s show inferior caml process -C-c` goto error in expression sent by M-C-x - -For other bindings, see C-h b. - -Changes log: ------------ -Version 3.10.1: ---------------- -* use caml-font.el from Olivier Andrieu - old version is left as caml-font-old.el for compatibility - -Version 3.07: -------------- -* support for showing type information - -Version 3.05: -------------- -* improved interaction with inferior caml mode - -* access help from the source - -* fixes in indentation code - -Version 3.03: -------------- -* process ;; properly - -Version 3.00: -------------- -* adapt to new label syntax - -* intelligent indentation of parenthesis - -Version 2.02: -------------- -* improved ocamltags - -* added support for multibyte characters in emacs 20 - -Version 2.01+: --------------- -* corrected a bug in caml-font.el - -* corrected abbreviations and added ocamltags script - -Version 2.01: ------------- -* code for interactive errors added by ITZ - -Version 2.00: ------------- -* changed the algorithm to skip comments - -* adapted for the new object syntax - -Version 1.07: ------------- -* next-error bug fix by John Malecki - -* camldebug.el modified by Xavier Leroy - -Version 1.06: ------------- -* new keywords in Objective Caml 1.06 - -* compatibility with GNU Emacs 20 - -* changed from caml-imenu-disable to caml-imenu-enable (off by default) - -Version 1.05: ------------- -* a few indentation bugs corrected. let, val ... are now indented - correctly even when you write them at the beginning of a line. - -* added a Caml menu, and Imenu support. Imenu menu can be disabled - by setting the variable caml-imenu-disable to t. - Xemacs support for the Menu, but no Imenu. - -* key bindings closer to lisp-mode. - -* O'Labl compatibility (":" is part of words) may be switched off by - setting caml-olabl-disable to t. - -* camldebug.el was updated by Xavier Leroy. - -Version 1.03b: -------------- -* many bugs corrected. - -* (partial) compatibility with Caml-Light added. - (setq caml-quote-char "`") - (setq inferior-caml-program "camllight") - Literals will be correctly understood and highlighted. However, - indentation rules are still OCaml's: this just happens to - work well in most cases, but is only intended for occasional use. - -* as many people asked for it, application is now indented. This seems - to work well: this time differences in indentation between the - compiler's source and this mode are really exceptionnal. On the - other hand, you may think that some special cases are strange. No - miracle. - -* nicer behaviour when sending a phrase/region to the inferior caml - process. - -Version 1.03: ------------- -* support of OCaml and Objective Label. - -* an indentation very close to mine, which happens to be the same as - Xavier's, since the sources of the OCaml compiler do not - change if you indent them in this mode. - -* highlighting. - -Some remarks about the style supported: --------------------------------------- - -Since OCaml's syntax is very liberal (more than 100 -shift-reduce conflicts with yacc), automatic indentation is far from -easy. Moreover, you expect the indentation to be not purely syntactic, -but also semantic: reflecting the meaning of your program. - -This mode tries to be intelligent. For instance some operators are -indented differently in the middle and at the end of a line (thanks to -Ian Zimmerman). Also, we do not indent after if .. then .. else, when -else is on the same line, to reflect that this idiom is equivalent to -a return instruction in a more imperative language, or after the in of -let .. in, since you may see that as an assignment. - -However, you may want to use a different indentation style. This is -made partly possible by a number of variables at the beginning of -caml.el. Try to set them. However this only changes the size of -indentations, not really the look of your program. This is enough to -disable the two idioms above, but to do anything more you will have to -edit the code... Enjoy! - -This mode does not force you to put ;; in your program. This means -that we had to use a heuristic to decide where a phrase starts and -stops, to speed up the code. A phrase starts when any of the keywords -let, type, class, module, functor, exception, val, external, appears -at the beginning of a line. Using the first column for such keywords -in other cases may confuse the phrase selection function. - -Comments and bug reports to - - Jacques Garrigue diff --git a/emacs/README.itz b/emacs/README.itz deleted file mode 100644 index 7bcc7aa0..00000000 --- a/emacs/README.itz +++ /dev/null @@ -1,177 +0,0 @@ -DESCRIPTION: - -This directory contains files to help editing OCaml code, running a -OCaml toplevel, and running the OCaml debugger under the Gnu Emacs editor. - -AUTHORS: - -Ian T Zimmerman added indentation to caml mode, beefed -up camldebug to work much like gud/gdb. - -Xavier Leroy (Xavier.Leroy@inria.fr), Jerome Vouillon (Jerome.Vouillon@ens.fr). -camldebug.el is derived from FSF code. - -CONTENTS: - - caml.el A major mode for editing OCaml code in Gnu Emacs - inf-caml.el To run a OCaml toplevel under Emacs, with input and - output in an Emacs buffer. - camldebug.el To run the OCaml debugger under Emacs. - - -NOTE FOR EMACS 18 USERS: - -This package will no longer work with Emacs 18.x. Sorry. You really -should consider upgrading to Emacs 19. - -USAGE: - -Add the following lines to your .emacs file: - -(setq auto-mode-alist (cons '("\\.ml[iylp]?" . caml-mode) auto-mode-alist)) -(autoload 'caml-mode "caml" "Major mode for editing OCaml code." t) -(autoload 'run-caml "inf-caml" "Run an inferior OCaml process." t) -(autoload 'camldebug "camldebug" "Run the OCaml debugger." t) - -The Caml major mode is triggered by visiting a file with extension .ml, -.mli, .mly. .mll or .mlp, or manually by M-x caml-mode. It gives you the -correct syntax table for the OCaml language. For a brief description of -the indentation capabilities, see below under NEWS. - -The Caml mode also allows you to run batch Caml compilations from -Emacs (using M-x compile) and browse the errors (C-x `). Typing C-x ` -sets the point at the beginning of the erroneous program fragment, and -the mark at the end. Under Emacs 19, the program fragment is -temporarily highlighted. - -M-x run-caml starts an OCaml toplevel with input and output in an Emacs -buffer named *inferior-caml*. This gives you the full power of Emacs -to edit the input to the OCaml toplevel. This mode is based on comint -so you get all the usual comint features, including command history. - -After M-x run-caml, typing C-c C-e or M-C-x in a buffer in Caml mode -sends the current phrase (containing the point) to the OCaml toplevel, -and evaluates it. - -M-x camldebug FILE starts the OCaml debugger camldebug on the executable -FILE, with input and output in an Emacs buffer named *camldebug-FILE*. -For a brief description of the commands available in this buffer, see -NEWS below. - -NEWS: - -Ok, so this is the really important part of this file :-) I took the -original package from the contrib subdirectory of the caml-light -distribution, and hacked on it. First, I added real syntax dependent -indentation to caml mode. Like Xavier has said, it was hard (and I -knew it would be), but I refused to believe it was impossible, partly -because I knew of a Standard ML mode with indentation (written by -Matthew Morley). - -Indentation works pretty much like in other programming modes. C-j at -the end of a line starts a new line properly indented. M-C-\ indents -the current region (this may take a while :-)). I incorporated a -slightly different TAB function, one that I use in other modes: if TAB -is pressed while the point is not in line indentation, the line is -indented to the column where point is (instead of just inserting a TAB -character - you can always to that with C-q C-i). This way, you can -indent a line any time, regardless of where the point lies, by hitting -TAB twice in succession. If you don't like this behaviour (but you -should), it's quite easy to add to your startup code like this: - -(defun caml-old-style-indent () - (if (caml-in-indentation) - (caml-indent-command) - (insert "\t"))) - -(add-hook 'caml-mode-hook - (function (lambda () - (define-key 'caml-mode-map "\t" - caml-old-style-indent)))) - -You can customize the appearance of your caml code by twiddling the -variables listed at the start of caml.el. Good luck. :-) - -Other news in caml mode are the various caml-insert-*-form commands. I -believe they are self-explanatory - just do a C-h m in a caml buffer -to see what you've got. - -The ohter major news is that I changed camldebug mode considerably. I -took many clues from the gud "Grand Unified Debugger" mode distributed -with modern versions of Emacs. The main benefit here is that you can -do debugger commands _from your caml source buffer_. Commands with the -C-c prefix in the debugger buffer have counterparts which do the same -thing (well, a similar thing) in the source buffer, with the C-x C-a -prefix. - -I made the existing debugger commands smarter in that they now attempt -to guess the correct parameter to the underlying camldebug command. A -numeric argument will always override that guess. For example, the -guess for C-c C-b (camldebug-break) is to set a breakpoint at the -current event (which was the only behaviour provided with the old -camldebug.el). But C-u 1 C-c C-b will now send "break 1" to the -camldebug process, setting a break at code address 1. - -This also allowed me to add many more commands for which the -underlying camldebug commands require a parameter. The best way to -learn about them is to do C-h m in the camldebug buffer, and then C-h -f for the commands you'll see listed. - -Finally, I added command completion. To use it, you'll have to apply -the provided patch to the debugger itself -(contrib/debugger/command_line_interpreter.ml), and recompile it -(you'll get one warning from the compiler; it is safe to ignore -it). Then hitting TAB in the following situation, for example: - -(cdb) pri_ - -will complete the "pri" to "print". - -CAVEATS: - -I don't use X and haven't tested this stuff under the X mode of -emacs. It is entirely possible (though not very probable) that I -introduced some undesirable interaction between X (fontification, -highlighting,...) and caml mode. I will welcome reports of such -problems (see REPORTING below), but I won't be able to do much about -them unless you also provide a patch. - -I don't know if the informational messages produced by camldebug are -internationalized. If they are, the debugger mode won't work unless -you set the language to English. The mode uses the messages to -synchronize with camldebug, and looks for fixed Emacs regular -expressions that match them. This may be fixed (if necessary) in a -future release. - -BUGS: - -In the debugger buffer, it's possible to overflow your mental stack by -asking for help on help on help on help on help on help on help on -help... - -THANKS: - -Xavier Leroy for Caml-light. Used together with the -Emacs interface, it is about the most pleasant programming environment -I've known on any platform. - -Eric Raymond for gud, which camldebug mode apes. - -Barry Warsaw for elp, without which I wouldn't have -been able to get the indentation code to perform acceptably. - -Gareth Rees for suggestions how to speed up -Emacs regular expression search, even if I didn't use them in the end. - -Bill Dubuque for alerting me to the -necessity of guarding against C-g inside Emacs code which modifies -syntax tables. - -REPORTING: - -Bug reports (preferably with patches), suggestions, donations etc. to: - -Ian T Zimmerman +-------------------------------------------+ -Box 13445 I With so many executioners available, I -Berkeley CA 94712 USA I suicide is a really foolish thing to do. I -mailto:itz@rahul.net +-------------------------------------------+ diff --git a/emacs/caml-compat.el b/emacs/caml-compat.el deleted file mode 100644 index 782d2d47..00000000 --- a/emacs/caml-compat.el +++ /dev/null @@ -1,41 +0,0 @@ -;************************************************************************** -;* * -;* OCaml * -;* * -;* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -;* * -;* Copyright 1998 Institut National de Recherche en Informatique et * -;* en Automatique. * -;* * -;* All rights reserved. This file is distributed under the terms of * -;* the GNU General Public License. * -;* * -;************************************************************************** - -;; function definitions for old versions of emacs - -;; indent-line-to - -(if (not (fboundp 'indent-line-to)) - (defun indent-line-to (column) - "Indent current line to COLUMN. - -This function removes or adds spaces and tabs at beginning of line -only if necessary. It leaves point at end of indentation." - (if (= (current-indentation) column) - (back-to-indentation) - (beginning-of-line 1) - (delete-horizontal-space) - (indent-to column)))) - -;; buffer-substring-no-properties - -(cond - ((fboundp 'buffer-substring-no-properties)) - ((fboundp 'buffer-substring-without-properties) - (defalias 'buffer-substring-no-properties - 'buffer-substring-without-properties)) - (t - (defalias 'buffer-substring-no-properties 'buffer-substring))) - -(provide 'caml-compat) diff --git a/emacs/caml-emacs.el b/emacs/caml-emacs.el deleted file mode 100644 index 13f72c46..00000000 --- a/emacs/caml-emacs.el +++ /dev/null @@ -1,45 +0,0 @@ -;************************************************************************** -;* * -;* OCaml * -;* * -;* Didier Remy, projet Cristal, INRIA Rocquencourt * -;* * -;* Copyright 2003 Institut National de Recherche en Informatique et * -;* en Automatique. * -;* * -;* All rights reserved. This file is distributed under the terms of * -;* the GNU General Public License. * -;* * -;************************************************************************** - -;; for caml-help.el -(defalias 'caml-info-other-window 'info-other-window) - -;; for caml-types.el - -(defalias 'caml-line-beginning-position 'line-beginning-position) - -(defalias 'caml-read-event 'read-event) -(defalias 'caml-window-edges 'window-edges) -(defun caml-mouse-vertical-position () - (cddr (mouse-position))) -(defalias 'caml-ignore-event-p 'integer-or-marker-p) -(defalias 'caml-mouse-movement-p 'mouse-movement-p) -(defalias 'caml-sit-for 'sit-for) - -(defalias 'caml-track-mouse 'track-mouse) - -(defun caml-event-window (e) (posn-window (event-start e))) -(defun caml-event-point-start (e) (posn-point (event-start e))) -(defun caml-event-point-end (e) (posn-point (event-end e))) - -(defun caml-release-event-p (original event) - (and (equal (event-basic-type original) (event-basic-type event)) - (let ((modifiers (event-modifiers event))) - (or (member 'drag modifiers) - (member 'click modifiers))))) - -(defalias 'caml-string-to-int (if (fboundp 'string-to-number) - 'string-to-number 'string-to-int)) - -(provide 'caml-emacs) diff --git a/emacs/caml-font-old.el b/emacs/caml-font-old.el deleted file mode 100644 index fb39c223..00000000 --- a/emacs/caml-font-old.el +++ /dev/null @@ -1,141 +0,0 @@ -;************************************************************************** -;* * -;* OCaml * -;* * -;* Jacques Garrigue and Ian T Zimmerman * -;* * -;* Copyright 1997 Institut National de Recherche en Informatique et * -;* en Automatique. * -;* * -;* All rights reserved. This file is distributed under the terms of * -;* the GNU General Public License. * -;* * -;************************************************************************** - -;; useful colors - -(cond - ((x-display-color-p) - (require 'font-lock) - (cond - ((not (boundp 'font-lock-type-face)) - ; make the necessary faces - (make-face 'Firebrick) - (set-face-foreground 'Firebrick "Firebrick") - (make-face 'RosyBrown) - (set-face-foreground 'RosyBrown "RosyBrown") - (make-face 'Purple) - (set-face-foreground 'Purple "Purple") - (make-face 'MidnightBlue) - (set-face-foreground 'MidnightBlue "MidnightBlue") - (make-face 'DarkGoldenRod) - (set-face-foreground 'DarkGoldenRod "DarkGoldenRod") - (make-face 'DarkOliveGreen) - (set-face-foreground 'DarkOliveGreen "DarkOliveGreen4") - (make-face 'CadetBlue) - (set-face-foreground 'CadetBlue "CadetBlue") - ; assign them as standard faces - (setq font-lock-comment-face 'Firebrick) - (setq font-lock-string-face 'RosyBrown) - (setq font-lock-keyword-face 'Purple) - (setq font-lock-function-name-face 'MidnightBlue) - (setq font-lock-variable-name-face 'DarkGoldenRod) - (setq font-lock-type-face 'DarkOliveGreen) - (setq font-lock-reference-face 'CadetBlue))) - ; extra faces for documentation - (make-face 'Stop) - (set-face-foreground 'Stop "White") - (set-face-background 'Stop "Red") - (make-face 'Doc) - (set-face-foreground 'Doc "Red") - (setq font-lock-stop-face 'Stop) - (setq font-lock-doccomment-face 'Doc) -)) - -; The same definition is in caml.el: -; we don't know in which order they will be loaded. -(defvar caml-quote-char "'" - "*Quote for character constants. \"'\" for OCaml, \"`\" for Caml-Light.") - -(defconst caml-font-lock-keywords - (list -;stop special comments - '("\\(^\\|[^\"]\\)\\((\\*\\*/\\*\\*)\\)" - 2 font-lock-stop-face) -;doccomments - '("\\(^\\|[^\"]\\)\\((\\*\\*[^*]*\\([^)*][^*]*\\*+\\)*)\\)" - 2 font-lock-doccomment-face) -;comments - '("\\(^\\|[^\"]\\)\\((\\*[^*]*\\*+\\([^)*][^*]*\\*+\\)*)\\)" - 2 font-lock-comment-face) -;character literals - (cons (concat caml-quote-char "\\(\\\\\\([ntbr" caml-quote-char "\\]\\|" - "[0-9][0-9][0-9]\\)\\|.\\)" caml-quote-char - "\\|\"[^\"\\]*\\(\\\\\\(.\\|\n\\)[^\"\\]*\\)*\"") - 'font-lock-string-face) -;modules and constructors - '("`?\\<[A-Z][A-Za-z0-9_']*\\>" . font-lock-function-name-face) -;definition - (cons (concat - "\\<\\(a\\(nd\\|s\\)\\|c\\(onstraint\\|lass\\)" - "\\|ex\\(ception\\|ternal\\)\\|fun\\(ct\\(ion\\|or\\)\\)?" - "\\|in\\(herit\\|itializer\\)?\\|let" - "\\|m\\(ethod\\|utable\\|odule\\)" - "\\|of\\|p\\(arser\\|rivate\\)\\|rec\\|type" - "\\|v\\(al\\|irtual\\)\\)\\>") - 'font-lock-type-face) -;blocking - '("\\<\\(begin\\|end\\|object\\|s\\(ig\\|truct\\)\\)\\>" - . font-lock-keyword-face) -;control - (cons (concat - "\\<\\(do\\(ne\\|wnto\\)?\\|else\\|for\\|i\\(f\\|gnore\\)" - "\\|lazy\\|match\\|new\\|or\\|t\\(hen\\|o\\|ry\\)" - "\\|w\\(h\\(en\\|ile\\)\\|ith\\)\\)\\>" - "\\|\|\\|->\\|&\\|#") - 'font-lock-reference-face) - '("\\" . font-lock-comment-face) -;labels (and open) - '("\\(\\([~?]\\|\\<\\)[a-z][a-zA-Z0-9_']*:\\)[^:=]" 1 - font-lock-variable-name-face) - '("\\<\\(assert\\|open\\|include\\)\\>\\|[~?][ (]*[a-z][a-zA-Z0-9_']*" - . font-lock-variable-name-face))) - -(defconst inferior-caml-font-lock-keywords - (append - (list -;inferior - '("^[#-]" . font-lock-comment-face)) - caml-font-lock-keywords)) - -;; font-lock commands are similar for caml-mode and inferior-caml-mode -(defun caml-mode-font-hook () - (cond - ((fboundp 'global-font-lock-mode) - (make-local-variable 'font-lock-defaults) - (setq font-lock-defaults - '(caml-font-lock-keywords nil nil ((?' . "w") (?_ . "w"))))) - (t - (setq font-lock-keywords caml-font-lock-keywords))) - (make-local-variable 'font-lock-keywords-only) - (setq font-lock-keywords-only t) - (font-lock-mode 1)) - -(add-hook 'caml-mode-hook 'caml-mode-font-hook) - -(defun inferior-caml-mode-font-hook () - (cond - ((fboundp 'global-font-lock-mode) - (make-local-variable 'font-lock-defaults) - (setq font-lock-defaults - '(inferior-caml-font-lock-keywords - nil nil ((?' . "w") (?_ . "w"))))) - (t - (setq font-lock-keywords inferior-caml-font-lock-keywords))) - (make-local-variable 'font-lock-keywords-only) - (setq font-lock-keywords-only t) - (font-lock-mode 1)) - -(add-hook 'inferior-caml-mode-hooks 'inferior-caml-mode-font-hook) - -(provide 'caml-font) diff --git a/emacs/caml-font.el b/emacs/caml-font.el deleted file mode 100644 index 91c6fce9..00000000 --- a/emacs/caml-font.el +++ /dev/null @@ -1,440 +0,0 @@ -;************************************************************************** -;* * -;* OCaml * -;* * -;* Jacques Garrigue, Ian T Zimmerman, Damien Doligez * -;* * -;* Copyright 1997 Institut National de Recherche en Informatique et * -;* en Automatique. * -;* * -;* All rights reserved. This file is distributed under the terms of * -;* the GNU General Public License. * -;* * -;************************************************************************** - -;; caml-font: font-lock support for OCaml files -;; now with perfect parsing of comments and strings - -(require 'font-lock) - -(defvar caml-font-stop-face - (progn - (make-face 'caml-font-stop-face) - (set-face-foreground 'caml-font-stop-face "White") - (set-face-background 'caml-font-stop-face "Red") - 'caml-font-stop-face)) - -(defvar caml-font-doccomment-face - (progn - (make-face 'caml-font-doccomment-face) - (set-face-foreground 'caml-font-doccomment-face "Red") - 'caml-font-doccomment-face)) - -(unless (facep 'font-lock-preprocessor-face) - (defvar font-lock-preprocessor-face - (copy-face 'font-lock-builtin-face - 'font-lock-preprocessor-face))) - -(defconst caml-font-lock-keywords - `( -;modules and constructors - ("`?\\<[A-Z][A-Za-z0-9_']*\\>" . font-lock-function-name-face) -;definition - (,(regexp-opt '("and" "as" "constraint" "class" - "exception" "external" "fun" "function" "functor" - "in" "inherit" "initializer" "let" - "method" "mutable" "module" "of" "private" "rec" - "type" "val" "virtual") - 'words) - . font-lock-type-face) -;blocking - (,(regexp-opt '("begin" "end" "object" "sig" "struct") 'words) - . font-lock-keyword-face) -;linenums - ("# *[0-9]+" . font-lock-preprocessor-face) -;infix operators - (,(regexp-opt '("asr" "land" "lor" "lsl" "lsr" "lxor" "mod") 'words) - . font-lock-builtin-face) -;control - (,(concat "[|#&]\\|->\\|" - (regexp-opt '("do" "done" "downto" "else" "for" "if" "ignore" - "lazy" "match" "new" "or" "then" "to" "try" - "when" "while" "with") - 'words)) - . font-lock-constant-face) - ("\\<\\(raise\\|failwith\\|invalid_arg\\)\\>" - . font-lock-comment-face) -;labels (and open) - ("\\(\\([~?]\\|\\<\\)[a-z][a-zA-Z0-9_']*:\\)[^:=]" - 1 font-lock-variable-name-face) - ("\\<\\(assert\\|open\\|include\\)\\>\\|[~?][ (]*[a-z][a-zA-Z0-9_']*" - . font-lock-variable-name-face))) - - -(defun caml-font-syntactic-face (s) - (let ((in-string (nth 3 s)) - (in-comment (nth 4 s)) - (start (nth 8 s))) - (cond - (in-string 'font-lock-string-face) - (in-comment - (save-excursion - (goto-char start) - (cond - ((looking-at "(\\*\\*/\\*\\*)") 'caml-font-stop-face) - ((looking-at "(\\*\\*[^*]") 'caml-font-doccomment-face) - (t 'font-lock-comment-face))))))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; In order to correctly fontify an OCaml buffer, it is necessary to -; lex the buffer to tell what is a comment and what is a string. -; We do this incrementally in a hook -; (font-lock-extend-after-change-region-function), which is called -; whenever the buffer changes. It sets the syntax-table property -; on each beginning and end of chars, strings, and comments. - -; This mode handles correctly all the strange cases in the following -; OCaml code. -; -; let l' _ = ();; -; let _' _ = ();; -; let l' = ();; -; let b2_' = ();; -; let a'a' = ();; -; let f2 _ _ = ();; -; let f3 _ _ _ = ();; -; let f' _ _ _ _ _ = ();; -; let hello = ();; -; -; (* ==== easy stuff ==== *) -; -; (* a comment *) -; (* "a string" in a comment *) -; (* "another string *)" in a comment *) -; (* not a string '"' in a comment *) -; "a string";; -; '"';; (* not a string *) -; -; (* ==== hard stuff ==== *) -; -; l'"' not not a string ";; -; _'"' also not not a string";; -; f2 0l'"';; (* not not not a string *) -; f2 0_'"';; (* also not not not a string *) -; f3 0.0l'"' not not not not a string ";; -; f3 0.0_'"';; (* not not not not not a string *) -; f2 0b01_'"';; (* not not not a string *) -; f3 0b2_'"' not not not not a string ";; -; f3 0b02_'"';; (* not not not not not a string *) -; '\'';; (* a char *) -; ' -; ';; (* a char *) -; '^M -; ';; (* also a char [replace ^M with one CR character] *) -; a'a';; (* not a char *) -; type ' -; a' t = X;; (* also not a char *) -; -; (* ==== far-out stuff ==== *) -; -; f'"'" "*) print_endline "hello";;(* \"" ;; -; (* f'"'" "*) print_endline "hello";;(* \"" ;; *) - - -(defconst caml-font-ident-re - (concat "[A-Za-z_\300-\326\330-\366\370-\377]" - "[A-Za-z_\300-\326\330-\366\370-\377'0-9]*") -) - -(defconst caml-font-int-re - (concat "\\(0[xX][0-9A-Fa-f][0-9A-Fa-f_]*\\|0[oO][0-7][0-7_]*" - "\\|0[bB][01][01_]*\\)[lLn]?") -) - -; decimal integers are folded into the RE for floats to get longest-match -; without using posix-looking-at -(defconst caml-font-decimal-re - "[0-9][0-9_]*\\([lLn]\\|\\.[0-9_]*\\)?\\([eE][+-]?[0-9][0-9_]*\\)?" -) - -; match any ident or numeral token -(defconst caml-font-ident-or-num-re - (concat caml-font-ident-re "\\|" caml-font-int-re "\\|" caml-font-decimal-re) -) - -; match any char token -(defconst caml-font-char-re - (concat "'\\(\015\012\\|[^\\']\\|" - "\\(\\\\\\([\\'\"ntbr ]\\|[0-9][0-9][0-9]" - "\\|x[0-9A-Fa-f][0-9A-Fa-f]\\)\\)\\)'") -) - -; match a quote followed by a newline -(defconst caml-font-quote-newline-re - "'\\(\015\012\\|[\012\015]\\)" -) - -; match an opening delimiter for a quoted string -(defconst caml-font-quoted-string-start-re - "{\\([a-z]*\\)|" -) - -; match any token or sequence of tokens that cannot contain a -; quote, double quote, a start of comment or quoted string, or a newline -; note: this is only to go faster than one character at a time -(defconst caml-font-other-re - "[^A-Za-z_0-9\012\015\300-\326\330-\366\370-\377'\"({]+" -) - -; match any sequence of non-special characters in a comment -; note: this is only to go faster than one character at a time -(defconst caml-font-other-comment-re - "[^{(*\"'\012\015]+" -) - -; match any sequence of non-special characters in a string -; note: this is only to go faster than one character at a time -(defconst caml-font-other-string-re - "[^|\\\"\012\015]" -) - -; match a newline -(defconst caml-font-newline-re - "\\(\015\012\\|[\012\015]\\)" -) - -; Put the 'caml-font-state property with the given state on the -; character before pos. Return nil if it was already there, t if not. -(defun caml-font-put-state (pos state) - (if (equal state (get-text-property (1- pos) 'caml-font-state)) - nil - (put-text-property (1- pos) pos 'caml-font-state state) - t) -) - -; Same as looking-at, but erase properties 'caml-font-state and -; 'syntax-table from the matched range -(defun caml-font-looking-at (re) - (let ((result (looking-at re))) - (when result - (remove-text-properties (match-beginning 0) (match-end 0) - '(syntax-table nil caml-font-state nil))) - result) -) - -; Annotate the buffer starting at point in state (st . depth) -; Set the 'syntax-table property on beginnings and ends of: -; - strings -; - chars -; - comments -; Also set the 'caml-font-state property on each LF character that is -; not preceded by a single quote. The property gives the state of the -; lexer (nil or t) after reading that character. - -; Leave the point at a point where the pre-existing 'caml-font-state -; property is consistent with the new parse, or at the end of the buffer. - -; depth is the depth of nested comments at this point -; it must be a non-negative integer -; st can be: -; nil -- we are in the base state -; t -- we are within a string -; a string -- we are within a quoted string and st is the closing delimiter - -(defun caml-font-annotate (st depth) - (let ((continue t)) - (while (and continue (not (eobp))) - (cond - ((and (equal st nil) (= depth 0)) ; base state, outside comment - (cond - ((caml-font-looking-at caml-font-ident-or-num-re) - (goto-char (match-end 0))) - ((caml-font-looking-at caml-font-char-re) - (put-text-property (point) (1+ (point)) - 'syntax-table (string-to-syntax "|")) - (put-text-property (1- (match-end 0)) (match-end 0) - 'syntax-table (string-to-syntax "|")) - (goto-char (match-end 0))) - ((caml-font-looking-at caml-font-quote-newline-re) - (goto-char (match-end 0))) - ((caml-font-looking-at "\"") - (put-text-property (point) (1+ (point)) - 'syntax-table (string-to-syntax "|")) - (goto-char (match-end 0)) - (setq st t)) - ((caml-font-looking-at caml-font-quoted-string-start-re) - (put-text-property (point) (1+ (point)) - 'syntax-table (string-to-syntax "|")) - (goto-char (match-end 0)) - (setq st (concat "|" (match-string 1) "}"))) - ((caml-font-looking-at "(\\*") - (put-text-property (point) (1+ (point)) - 'syntax-table (string-to-syntax "!")) - (goto-char (match-end 0)) - (setq depth 1)) - ((looking-at caml-font-newline-re) - (goto-char (match-end 0)) - (setq continue (caml-font-put-state (match-end 0) '(nil . 0)))) - ((caml-font-looking-at caml-font-other-re) - (goto-char (match-end 0))) - (t - (remove-text-properties (point) (1+ (point)) - '(syntax-table nil caml-font-state nil)) - (goto-char (1+ (point)))))) - ((equal st nil) ; base state inside comment - (cond - ((caml-font-looking-at "(\\*") - (goto-char (match-end 0)) - (setq depth (1+ depth))) - ((caml-font-looking-at "\\*)") - (goto-char (match-end 0)) - (setq depth (1- depth)) - (when (= depth 0) - (put-text-property (1- (point)) (point) - 'syntax-table (string-to-syntax "!")))) - ((caml-font-looking-at "\"") - (goto-char (match-end 0)) - (setq st t)) - ((caml-font-looking-at caml-font-char-re) - (goto-char (match-end 0))) - ((caml-font-looking-at caml-font-quote-newline-re) - (goto-char (match-end 0))) - ((caml-font-looking-at "''") - (goto-char (match-end 0))) - ((looking-at caml-font-newline-re) - (goto-char (match-end 0)) - (setq continue (caml-font-put-state (match-end 0) (cons nil depth)))) - ((caml-font-looking-at caml-font-other-comment-re) - (goto-char (match-end 0))) - (t - (remove-text-properties (point) (1+ (point)) - '(syntax-table nil caml-font-state nil)) - (goto-char (1+ (point)))))) - ((equal st t) ; string state inside or outside a comment - (cond - ((caml-font-looking-at "\"") - (when (= depth 0) - (put-text-property (point) (1+ (point)) - 'syntax-table (string-to-syntax "|"))) - (goto-char (1+ (point))) - (setq st nil)) - ((caml-font-looking-at "\\\\[\"\\]") - (goto-char (match-end 0))) - ((looking-at caml-font-newline-re) - (goto-char (match-end 0)) - (setq continue (caml-font-put-state (match-end 0) (cons t depth)))) - ((caml-font-looking-at caml-font-other-string-re) - (goto-char (match-end 0))) - (t - (remove-text-properties (point) (1+ (point)) - '(syntax-table nil caml-font-state nil)) - (goto-char (1+ (point)))))) - ((stringp st) ; quoted-string state inside or outside comment - (cond - ((caml-font-looking-at st) - (when (= depth 0) - (put-text-property (1- (match-end 0)) (match-end 0) - 'syntax-table (string-to-syntax "|"))) - (goto-char (match-end 0)) - (setq st nil)) - ((caml-font-looking-at caml-font-other-string-re) - (goto-char (match-end 0))) - (t - (remove-text-properties (point) (1+ (point)) - '(syntax-table nil caml-font-state nil)) - (goto-char (1+ (point)))))) - (t ; should not happen - (remove-text-properties (point) (1+ (point)) - '(syntax-table nil caml-font-state nil)))))) -) - -; This is the hook function for font-lock-extend-after-change-function -; It finds the nearest saved state at the left of the changed text, -; calls caml-font-annotate to set the 'caml-font-state and 'syntax-table -; properties, then returns the range that was parsed by caml-font-annotate. -(defun caml-font-extend-after-change (beg end &optional old-len) - (save-excursion - (save-match-data - (let ((caml-font-modified (buffer-modified-p)) - start-at - end-at - state) - (remove-text-properties beg end '(syntax-table nil caml-font-state nil)) - (setq start-at - (or (and (> beg (point-min)) - (get-text-property (1- beg) 'caml-font-state) - beg) - (previous-single-property-change beg 'caml-font-state) - (point-min))) - (setq state (or (and (> start-at (point-min)) - (get-text-property (1- start-at) 'caml-font-state)) - (cons nil 0))) - (goto-char start-at) - (caml-font-annotate (car state) (cdr state)) - (setq end-at (point)) - (restore-buffer-modified-p caml-font-modified) - (cons start-at end-at)))) -) - -; We don't use the normal caml-mode syntax table because it contains an -; approximation of strings and comments that interferes with our -; annotations. -(defconst caml-font-syntax-table - (let ((tbl (make-syntax-table))) - (modify-syntax-entry ?' "w" tbl) - (modify-syntax-entry ?_ "w" tbl) - (modify-syntax-entry ?\" "." tbl) - (let ((i 192)) - (while (< i 256) - (or (= i 215) (= i 247) (modify-syntax-entry i "w" tbl)) - (setq i (1+ i)))) - tbl)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; font-lock commands are similar for caml-mode and inferior-caml-mode -(defun caml-font-set-font-lock () - (setq parse-sexp-lookup-properties t) - (setq font-lock-defaults - (list - 'caml-font-lock-keywords ; keywords - nil ; keywords-only - nil ; case-fold - nil ; syntax-alist - nil ; syntax-begin - (cons 'font-lock-syntax-table caml-font-syntax-table) - '(font-lock-extend-after-change-region-function - . caml-font-extend-after-change) - '(font-lock-syntactic-face-function . caml-font-syntactic-face) - )) - (caml-font-extend-after-change (point-min) (point-max) 0) - (font-lock-mode 1) -) -(add-hook 'caml-mode-hook 'caml-font-set-font-lock) - - - -(defconst inferior-caml-font-lock-keywords - `(("^[#-]" . font-lock-comment-face) - ,@caml-font-lock-keywords)) - -(defun inferior-caml-set-font-lock () - (setq parse-sexp-lookup-properties t) - (setq font-lock-defaults - (list - 'inferior-caml-font-lock-keywords ; keywords - nil ; keywords-only - nil ; case-fold - nil ; syntax-alist - nil ; syntax-begin - (cons 'font-lock-syntax-table caml-font-syntax-table) - '(font-lock-extend-after-change-region-function - . caml-font-extend-after-change) - '(font-lock-syntactic-face-function . caml-font-syntactic-face) - )) - (caml-font-extend-after-change (point-min) (point-max) 0) - (font-lock-mode 1) -) -(add-hook 'inferior-caml-mode-hooks 'inferior-caml-set-font-lock) - -(provide 'caml-font) diff --git a/emacs/caml-help.el b/emacs/caml-help.el deleted file mode 100644 index 9e3a221b..00000000 --- a/emacs/caml-help.el +++ /dev/null @@ -1,857 +0,0 @@ -;;; caml-help.el --- Contextual completion and help to caml-mode -;************************************************************************** -;* * -;* OCaml * -;* * -;* Didier Remy, projet Cristal, INRIA Rocquencourt * -;* * -;* Copyright 2001 Institut National de Recherche en Informatique et * -;* en Automatique. * -;* * -;* All rights reserved. This file is distributed under the terms of * -;* the GNU General Public License. * -;* * -;************************************************************************** - -;; Author: Didier Remy, November 2001. - -;;; Commentary: - -;; This provides two functions: completion and help. -;; Look for caml-complete and caml-help. - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; This is a preliminary version. -;; -;; Possible improvements? -;; - dump some databases: Info, Lib, ... -;; - accept a search path for local libraries instead of current dir -;; (then distinguish between different modules lying in different -;; directories) -;; - improve the construction for info files. -;; -;; Abstract over -;; - the viewing method and the database, so that the documentation for -;; an identifier could be -;; * searched in info / html / man / mli's sources -;; * viewed in Emacs or using an external previewer. -;; -;; Take all identifiers (labels, Constructors, exceptions, etc.) -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; Code: - -(eval-and-compile - (if (featurep 'xemacs) - (require 'caml-xemacs) - (require 'caml-emacs))) - -;; Loading or building databases. -;; - -;; variables to be customized - -(defvar ocaml-lib-path 'lazy - "Path list for ocaml lib sources (mli files). - -`lazy' means ask ocaml to find it for you at first use.") -(defun ocaml-lib-path () - "Compute if necessary and return the path for ocaml libs." - (if (listp ocaml-lib-path) nil - (setq ocaml-lib-path - (split-string - (shell-command-to-string - (or - (and (boundp 'inferior-caml-program) - (string-match "\\([^ ]*/ocaml\\)\\( \\|$\\)" - inferior-caml-program) - (let ((file - (concat (match-string 1 inferior-caml-program) - "c"))) - (and (file-executable-p file) - (concat file " -where")))) - "ocamlc -where"))))) - ocaml-lib-path) - - - -;; General purpose auxiliary functions - -(defun ocaml-capitalize (s) - (concat (capitalize (substring s 0 1)) (substring s 1))) - -(defun ocaml-uncapitalize (s) - (if (> (length s) 0) - (concat (downcase (substring s 0 1)) (substring s 1)) - s)) - -(defun ocaml-find-files (path filter &optional depth split) - (let* ((path-string - (if (stringp path) - (if (file-directory-p path) path nil) - (mapconcat (lambda (d) (if (file-directory-p d) d)) - path " "))) - (command - (and path-string - (concat "find " path-string - " '(' " filter " ')' " - (if depth (concat " -maxdepth " (int-to-string depth))) - (if split nil " -printf '%\p '") - ))) - (files - (and command (shell-command-to-string command)))) - (if (and split (stringp files)) (split-string files "\n") files) - )) - -;; Specialized auxiliary functions - - -;; Global table of modules contents of modules loaded lazily. - -(defvar ocaml-module-alist 'lazy - "A-list of modules with how and where to find help information. -`delay' means non computed yet.") - -(defun ocaml-add-mli-modules (modules tag &optional path) - (let ((files - (ocaml-find-files (or path (ocaml-lib-path)) - "-type f -name '*.mli'" 1 t))) - (while (consp files) - (if (string-match "\\([^/]*\\).mli" (car files)) - (let* ((module (ocaml-capitalize (match-string 1 (car files)))) - (dir (file-name-directory (car files))) - (dirp (member dir (ocaml-lib-path)))) - (if (and (consp dirp) (string-equal dir (car dirp))) - (setq dir (car dirp))) - (if (assoc module modules) nil - (setq modules - (cons (cons module (cons (cons tag dir) 'lazy)) modules)) - ))) - (setq files (cdr files))) - modules)) - -(defun ocaml-add-path (dir &optional path) - "Extend `ocaml-module-alist' with modules of DIR relative to PATH." - (interactive "D") - (let* ((old (ocaml-lib-path)) - (new - (if (file-name-absolute-p dir) dir - (concat - (or (find-if (lambda (p) (file-directory-p (concat p "/" dir))) - (cons default-directory old)) - (error "Directory not found")) - "/" dir)))) - (setq ocaml-lib-path (cons (car old) (cons new (cdr old)))) - (setq ocaml-module-alist - (ocaml-add-mli-modules (ocaml-module-alist) 'lib new)))) - -(defun ocaml-module-alist () - "Call by need value of variable `ocaml-module-alist'." - (if (listp ocaml-module-alist) - nil - ;; build list of mli files - (setq ocaml-module-alist (ocaml-add-mli-modules nil 'lib)) - ;; dumping information ? TODO - ) - ocaml-module-alist) - -(defun ocaml-get-or-make-module (module &optional tag) - (let ((info (assoc module (ocaml-module-alist)))) - (if info nil - (setq info (cons module (cons (cons 'local default-directory) 'lazy))) - (setq ocaml-module-alist (cons info ocaml-module-alist)) - ) - info)) - -;; Symbols of module are lazily computed - -(defun ocaml-module-filename (module) - (let ((module (ocaml-uncapitalize module)) (name)) - (if (file-exists-p (setq name (concat module ".mli"))) nil - (let ((tmp (ocaml-lib-path))) - (while (consp tmp) - (setq name (concat (car tmp) "/" module ".mli")) - (if (file-exists-p name) (setq tmp nil) - (setq name nil))))) - name)) - -(defun ocaml-module-symbols (module-info) - (let* ((module (car module-info)) - (tail (and module-info (cdr module-info))) - (tag (caar tail)) - (dir (cdar tail)) - (file) - (alist)) - (if (listp (cdr tail)) - (cdr tail) - (if (equal tag 'info) - (setq dir (car ocaml-lib-path)) ; XXX to be fixed - ) - (setq file (concat dir "/" (ocaml-uncapitalize module) ".mli")) - (message file) - (save-window-excursion - (set-buffer (get-buffer-create "*caml-help*")) - (if (and file (file-exists-p file)) - (progn - (message "Scanning module %s" file) - (insert-file-contents file)) - (message "Module %s not found" module)) - (while (re-search-forward - (concat "\\([ \t]*val\\|let\\|exception\\|external\\| [|]\\) \\([a-zA-Z_0-9'][a-zA-Z_0-9']*\\)" - "\\|^ *[{]* \\([a-z_][A-Za-z_0-9]*\\) : [^;\n][^;\n]*;") - (point-max) 'move) - (pop-to-buffer (current-buffer)) - (setq alist (cons (or (match-string 2) (match-string 3)) alist))) - (erase-buffer) - ) - (setcdr tail alist) - alist) - )) - -;; Local list of visible modules. - -(defvar ocaml-visible-modules 'lazy - "A-list of open modules, local to every file.") -(make-variable-buffer-local 'ocaml-visible-modules) -(defun ocaml-visible-modules () - (if (listp ocaml-visible-modules) nil - (progn - (setq ocaml-visible-modules - (list (ocaml-get-or-make-module "Pervasives"))) - (save-excursion - (goto-char (point-min)) - (while (re-search-forward "^ *open *\\([A-Z][a-zA-Z'_0-9]*\\)" - (point-max) t) - (let ((module (match-string 1))) - (if (assoc module ocaml-visible-modules) nil - (setq ocaml-visible-modules - (cons (ocaml-get-or-make-module module) - ocaml-visible-modules))))) - ))) - ocaml-visible-modules) - -(defun ocaml-open-module (arg) - "*Make module of name ARG visible when ARG is a string. -When call interactively, make completion over known modules." - (interactive "P") - (if (not (stringp arg)) - (let ((modules (ocaml-module-alist))) - (setq arg - (completing-read "Open module: " modules)))) - (if (and (stringp arg) (not (equal arg ""))) - (progn - (if (assoc arg (ocaml-visible-modules)) - (ocaml-close-module arg)) - (setq ocaml-visible-modules - (cons (ocaml-get-or-make-module arg) (ocaml-visible-modules))) - )) - (message "%S" (mapcar 'car (ocaml-visible-modules)))) - -(defun ocaml-close-module (arg) - "*Close module of name ARG when ARG is a string. -When call interactively, make completion over visible modules. -Otherwise if ARG is true, close all modules and reset to default." - (interactive "P") - (if (= (prefix-numeric-value arg) 4) - (setq ocaml-visible-modules 'lazy) - (let* ((modules (ocaml-visible-modules))) - (if (null modules) (error "No visible module to close")) - (unless (stringp arg) - (setq arg - (completing-read - (concat "Close module [" (caar modules) "] : ") - modules)) - (if (equal arg "") (setq arg (caar modules)))) - (setq ocaml-visible-modules - (remove-if (lambda (m) (equal (car m) arg)) - ocaml-visible-modules)) - )) - (message "%S" (mapcar 'car (ocaml-visible-modules)))) - - -;; Look for identifiers around point - -(defun ocaml-qualified-identifier (&optional show) - "Search for a qualified identifier (Path. entry) around point. - -Entry may be nil. -Currently, the path may only be nil or a single Module. -For paths is of the form Module.Path', it returns Module -and always nil for entry. - -If defined Module and Entry are represented by a region in the buffer, -and are nil otherwise. - -For debugging purposes, it returns the string Module.entry if called -with an optional non-nil argument." - (save-excursion - (let ((module) (entry)) - (if (looking-at "[ \n]") (skip-chars-backward " ")) - (if (re-search-backward - "\\([^A-Za-z0-9_.']\\|\\`\\)\\([A-Za-z0-9_']*[.]\\)*[A-Za-z0-9_']*\\=" - (- (point) 100) t) - (progn - (or (looking-at "\\`[A-Za-z)-9_.]") (forward-char 1)) - (if (looking-at "\\<\\([A-Za-z_][A-Za-z0-9_']*\\)[.]") - (progn - (setq module (cons (match-beginning 1) (match-end 1))) - (goto-char (match-end 0)))) - (if (looking-at "\\<\\([A-Za-z_][A-Za-z0-9_']*\\)\\>") - (setq entry (cons (match-beginning 1) (match-end 1)))))) - (if show - (concat - (and module (buffer-substring (car module) (cdr module))) - "." - (and entry (buffer-substring (car entry) (cdr entry)))) - (cons module entry)) - ))) - -;; completion around point - -(defun ocaml-completion (pattern module) - (let ((list - (or - (and module - (list - (or (assoc module (ocaml-module-alist)) - (error "Unknown module %s" module)))) - (ocaml-visible-modules)))) - (message "Completion from %s" (mapconcat 'car list " ")) - (if (null pattern) - (apply 'append (mapcar 'ocaml-module-symbols list)) - (let ((pat (concat "^" (regexp-quote pattern))) (res)) - (mapc - (lambda (l) - (mapc (lambda (x) - (if (string-match pat (car l)) - (if (member x res) nil (setq res (cons x res))))) - (ocaml-module-symbols l))) - list) - res) - ))) - -(defun caml-complete (arg) - "Does completion for OCaml identifiers qualified. - -It attemps to recognize a qualified identifier Module . entry -around point using function \\[ocaml-qualified-identifier]. - -If Module is defined, it does completion for identifier in Module. - -If Module is undefined, it does completion in visible modules. -Then, if completion fails, it does completion among all modules -where identifier is defined." - (interactive "p") - (let* ((module-entry (ocaml-qualified-identifier)) (entry) - (module) - (beg) (end) (pattern)) - (if (car module-entry) - (progn - (setq module - (buffer-substring (caar module-entry) (cdar module-entry))) - (or (assoc module (ocaml-module-alist)) - (and (setq module - (completing-read "Module: " (ocaml-module-alist) - nil nil module)) - (save-excursion - (goto-char (caar module-entry)) - (delete-region (caar module-entry) (cdar module-entry)) - (insert module) t) - (setq module-entry (ocaml-qualified-identifier)) - (car module-entry) - (progn (setq entry (cdr module-entry)) t)) - (error "Unknown module %s" module)))) - (if (consp (cdr module-entry)) - (progn - (setq beg (cadr module-entry)) - (setq end (cddr module-entry))) - (if (and module - (save-excursion - (goto-char (cdar module-entry)) - (looking-at " *[.]"))) - (progn - (setq beg (match-end 0)) - (setq end beg)))) - (if (not (and beg end)) - (error "Did not find anything to complete around point") - - (setq pattern (buffer-substring beg end)) - (let* ((all-completions (ocaml-completion pattern module)) - (completion - (try-completion pattern (mapcar 'list all-completions)))) - (cond ((eq completion t)) - - ((null completion) - (let* - ((modules (ocaml-find-module pattern)) - (visible (intersection modules (ocaml-visible-modules))) - (hist) - (module - (cond - ((null modules) - nil) - ((equal (length modules) 1) - (caar modules)) - ((equal (length visible) 1) - (caar visible)) - (t - (setq hist (mapcar 'car modules)) - (completing-read "Module: " modules nil t - "" (cons hist 0))) - ))) - (if (null module) - (error "Can't find completion for \"%s\"" pattern) - (message "Completion found in module %s" module) - (if (and (consp module-entry) (consp (cdr module-entry))) - (delete-region (caar module-entry) end) - (delete-region beg end)) - (insert module "." pattern)))) - - ((not (string-equal pattern completion)) - (delete-region beg end) - (goto-char beg) - (insert completion)) - - (t - (with-output-to-temp-buffer "*Completions*" - (display-completion-list all-completions)) - )) - )))) - - -;; Info files (only in ocamldoc style) - - -(defvar ocaml-info-prefix "ocaml-lib" - "Prefix of ocaml info files describing library modules. -Suffix .info will be added to info files. -Additional suffix .gz may be added if info files are compressed.") -;; - -(defun ocaml-hevea-info-add-entries (entries dir name) - (let* - ((filter - (concat "-type f -regex '.*/" name - "\\(.info\\|\\)\\(-[0-9]*\\|\\)\\([.]gz\\|\\)'" - )) - (section-regexp - "\\* \\(Section [1-9][0-9--]*\\)::[ \t][ \t]*Module *\\([A-Z][A-Za-z_0-9]*\\)") - (files (ocaml-find-files dir filter)) - (command)) - ;; scanning info files - (if (or (null files) - (not (stringp files)) - (string-match files "^ *$")) - (message "No info file found: %s." (mapconcat 'identity files " ")) - (message "Scanning info files %s." files) - (save-window-excursion - (set-buffer (get-buffer-create "*caml-help*")) - (setq command - (concat "zcat -f " files - " | grep -e '" section-regexp "'")) - (message "Scanning files with: %s" command) - (or (shell-command command (current-buffer)) - (error "Error while scanning")) - (goto-char (point-min)) - (while (re-search-forward section-regexp (point-max) t) - (let* ((module (match-string 2)) - (section (match-string 1))) - ;; (message "%s %s" module section) - (if (assoc module entries) nil - (setq entries - (cons (cons module (concat "(" name ")" section)) - entries)) - ))) - (let ((buf (get-buffer "*caml-help*"))) - (if buf (kill-buffer buf))))) - entries)) - -(defun ocaml-hevea-info () - "The default way to create an info data base from the value -of \\[Info-default-directory-list] and the base name \\[ocaml-info-name] -of files to look for. - -This uses info files produced by HeVeA." - (let ((collect) (seen)) - (mapc (lambda (d) - (if (member d seen) nil - (setq collect - (ocaml-hevea-info-add-entries - collect d ocaml-info-prefix)) - (setq seen (cons d seen)))) - Info-directory-list) - collect)) - -(defun ocaml-ocamldoc-info-add-entries (entries dir name) - (let* - ((module-regexp "^Node: \\([A-Z][A-Za-z_0-9]*\\)[^ ]") - (command - (concat - "find " dir " -type f -regex '.*/" name - "\\(.info\\|\\)\\([.]gz\\|\\)' -print0" - " | xargs -0 zcat -f | grep '" module-regexp "'"))) - (message "Scanning info files in %s" dir) - (save-window-excursion - (set-buffer (get-buffer-create "*caml-help*")) - (or (shell-command command (current-buffer)) - (error "Could not run:%s" command)) - (goto-char (point-min)) - (while (re-search-forward module-regexp (point-max) t) - (if (equal (char-after (match-end 1)) 127) - (let* ((module (match-string 1))) - (if (assoc module entries) nil - (setq entries - (cons (cons module (concat "(" name ")" module)) - entries)) - )))) - ; (kill-buffer (current-buffer)) - ) - entries)) - -(defun ocaml-ocamldoc-info () - "The default way to create an info data base from the value -of \\[Info-default-directory-list] and the base name \\[ocaml-info-name] -of files to look for. - -This uses info files produced by ocamldoc." - (require 'info) - (let ((collect) (seen)) - (mapc (lambda (d) - (if (member d seen) nil - (setq collect - (ocaml-ocamldoc-info-add-entries collect d - ocaml-info-prefix)) - (setq seen (cons d seen)))) - Info-directory-list) - collect)) - -;; Continuing - -(defvar ocaml-info-alist 'ocaml-ocamldoc-info - "A-list binding module names to info entries: - - nil means do not use info. - - A function to build the list lazily (at the first call). The result of -the function call will be assign permanently to this variable for future -uses. We provide two default functions `ocaml-hevea-info' -\(info produced by HeVeA is the default) and `ocaml-ocamldoc-info' -\(info produced by ocamldoc). - - Otherwise, this value should be an alist binding module names to info -entries of the form to \"(entry)section\" be taken by the \\[info] -command. An entry may be an info module or a complete file name." -) - -(defun ocaml-info-alist () - "Call by need value of variable `ocaml-info-alist'." - (cond - ((listp ocaml-info-alist)) - ((functionp ocaml-info-alist) - (setq ocaml-info-alist (apply ocaml-info-alist nil))) - (t - (error "wrong type for ocaml-info-alist"))) - ocaml-info-alist) - -;; help around point - -(defun ocaml-find-module (symbol &optional module-list) - (let ((list (or module-list (ocaml-module-alist))) - (collect)) - (while (consp list) - (if (member symbol (ocaml-module-symbols (car list))) - (setq collect (cons (car list) collect))) - (setq list (cdr list))) - (nreverse collect) - )) - -(defun ocaml-buffer-substring (region) - (and region (buffer-substring-no-properties (car region) (cdr region)))) - -;; Help function. - -(defvar view-return-to-alist) -(defvar view-exit-action) - -(defun ocaml-goto-help (&optional module entry same-window) - "Search info manual for MODULE and ENTRY in MODULE. -If unspecified, MODULE and ENTRY are inferred from the position in the -current buffer using \\[ocaml-qualified-identifier]." - (interactive) - (let ((window (selected-window)) - (info-section (assoc module (ocaml-info-alist)))) - (if info-section - (caml-info-other-window (cdr info-section)) - (ocaml-visible-modules) - (let* ((module-info - (or (assoc module (ocaml-module-alist)) - (and (file-exists-p - (concat (ocaml-uncapitalize module) ".mli")) - (ocaml-get-or-make-module module)))) - (location (cdr (cadr module-info)))) - (cond - (location - (let ((file (concat location (ocaml-uncapitalize module) ".mli"))) - (if (window-live-p same-window) - (progn (select-window same-window) - (view-mode-exit view-return-to-alist view-exit-action)) - ;; (view-buffer (find-file-noselect file) 'view)) - ) - (view-file-other-window file) - (bury-buffer (current-buffer)))) - (info-section (error "Aborted")) - (t (error "No help for module %s" module)))) - ) - (if (stringp entry) - (let ((here (point)) - (regex (regexp-quote entry)) - (case-fold-search nil)) - (goto-char (point-min)) - (if (or (re-search-forward - (concat "\\(val\\|exception\\|type\\|external\\|[|{;]\\) +" - regex) - ;; (concat "\\(val\\|exception\\|external\\) +\\(" - ;; regex "\\|( *" regex " *)\\)") - (point-max) t) - (re-search-forward - (concat "type [^{]*{[^}]*" regex " :") - ;; (concat "\\(type\\|[|{;]\\) +" regex) - (point-max) t) - (progn - (if (window-live-p window) (select-window window)) - (error "Entry %s not found in module %s" - entry module)) - ;; (search-forward entry (point-max) t) - ) - (ocaml-help-show -1) - (progn - (message "Help for entry %s not found in module %s" - entry module) - (goto-char here))) - )) - (ocaml-link-activate (cdr info-section)) - (if (window-live-p window) (select-window window)) - )) - -(defface ocaml-help-face - '((t :background "#88FF44")) - "Face to highlight expressions and types.") - -(defvar ocaml-help-ovl - (let ((ovl (make-overlay 1 1))) - (overlay-put ovl 'face 'ocaml-help-face) - ovl)) - -(defun caml-help (arg) - "Find documentation for OCaml qualified identifiers. - -It attempts to recognize a qualified identifier of the form -``Module . entry'' around point using function `ocaml-qualified-identifier'. - -If Module is undetermined it is temptatively guessed from the identifier name -and according to visible modules. If this is still unsuccessful, the user is -then prompted for a Module name. - -The documentation for Module is first searched in the info manual, if available, -then in the ``module.mli'' source file. The entry is then searched in the -documentation. - -Visible modules are computed only once, at the first call. -Modules can be made visible explicitly with `ocaml-open-module' and -hidden with `ocaml-close-module'. - -Prefix arg 0 forces recompilation of visible modules (and their content) -from the file content. - -Prefix arg 4 prompts for Module and identifier instead of guessing values -from the position of point in the current buffer." - (interactive "p") - (delete-overlay ocaml-help-ovl) - (let ((module) (entry) (module-entry)) - (cond - ((= arg 4) - (or (and - (setq module - (completing-read "Module: " (ocaml-module-alist) - nil t "" (cons 'hist 0))) - (not (string-equal module ""))) - (error "Quit")) - (let ((symbols - (mapcar 'list - (ocaml-module-symbols - (assoc module (ocaml-module-alist)))))) - (setq entry - (completing-read (format "Value: %s." module) symbols nil t))) - (if (string-equal entry "") (setq entry nil)) - ) - (t - (if (= arg 0) (setq ocaml-visible-modules 'lazy)) - (setq module-entry (ocaml-qualified-identifier)) - (setq entry (ocaml-buffer-substring (cdr module-entry))) - (setq module - (or (ocaml-buffer-substring (car module-entry)) - (let ((modules - (or (ocaml-find-module entry (ocaml-visible-modules)) - (ocaml-find-module entry))) - (hist) (default)) - (cond - ((null modules) - (error "No module found for entry %s" entry)) - ((equal (length modules) 1) - (caar modules)) - (t - (setq hist (mapcar 'car modules)) - (setq default (car hist)) - (setq module - (completing-read - (concat "Module: " - (and default (concat "[" default "] "))) - modules nil t "" (cons 'hist 0))) - (if (string-equal module "") default module)) - )))) - )) - (message "Help for %s%s%s" module (if entry "." "") (or entry "")) - (ocaml-goto-help module entry) - )) - -;; auto-links - -(defconst ocaml-link-regexp - "\\(type\\|and\\) \\('[a-z] +\\|(\\('[a-z], *\\)*'[a-z])\\|\\) *\\([a-zA-Z0-9_]*\\)\\( *$\\| =\\)") -(defconst ocaml-longident-regexp - "\\([A-Z][a-zA-Z_0]*\\)[.]\\([a-zA-Z][A-Za-z0-9_]*\\)") - -(defvar ocaml-links nil - "Local links in the current of last info node or interface file. - -The car of the list is a key that identifies the module to prevent -recompilation when next help command is relative to the same module. -The cdr is a list of elements, each of which is a string and a pair of -buffer positions." -) -(make-variable-buffer-local 'ocaml-links) - -(defun ocaml-info-links (section) - (cdr - (if (and ocaml-links section (equal (car ocaml-links) section)) - ocaml-links - (save-excursion - (goto-char (point-min)) - (let ((regexp (concat (if (equal major-mode 'Info-mode) "^ - " "^") - ocaml-link-regexp)) - (all)) - (while (re-search-forward regexp (point-max) t) - (setq all - (cons (cons (match-string 4) - (cons (match-beginning 4) - (match-end 4))) - all))) - (setq ocaml-links (cons section all)) - ))))) - -(defvar ocaml-link-map - (let ((map (make-sparse-keymap))) - (define-key map [mouse-2] 'ocaml-link-goto) - map)) - -(defun ocaml-help-show (arg) - (let ((right (point)) - (left (progn (forward-word arg) (point)))) - (goto-char right) - (move-overlay ocaml-help-ovl left right (current-buffer)) - (recenter 1) - )) - -(defun ocaml-link-goto (click) - "Follow link at point." - (interactive "e") - (let* ((pos (caml-event-point-start click)) - (win (caml-event-window click)) - (buf (window-buffer win)) - (window (selected-window)) - (link)) - (setq link - (with-current-buffer buf - (buffer-substring - (previous-single-property-change (+ pos 1) 'local-map - buf (- pos 100)) - (next-single-property-change pos 'local-map - buf (+ pos 100))))) - (if (string-match (concat "^" ocaml-longident-regexp "$") link) - (ocaml-goto-help (match-string 1 link) (match-string 2 link) win) - (if (not (equal (window-buffer window) buf)) - (switch-to-buffer-other-window buf)) - (if (setq link (assoc link (cdr ocaml-links))) - (progn - (goto-char (cadr link)) - (ocaml-help-show 1))) - (if (window-live-p window) (select-window window)) - ))) - - -(defface ocaml-link-face - '((((class color)) :foreground "Purple")) - "Face to highlight hyperlinks.") - -(defun ocaml-link-activate (section) - (let ((links (ocaml-info-links section))) - (if links - (let ((regexp (concat "[^A-Za-z0-9'_]\\(" - ocaml-longident-regexp "\\|" - (mapconcat 'car links "\\|") - "\\)[^A-Za-z0-9'_]")) - (case-fold-search nil)) - (save-excursion - (goto-char (point-min)) - (let ((buffer-read-only nil) - ;; use of dynamic scoping, need not be restored! - (modified-p (buffer-modified-p))) - (unwind-protect - (save-excursion - (goto-char (point-min)) - (while (re-search-forward regexp (point-max) t) - (put-text-property (match-beginning 1) (match-end 1) - 'mouse-face 'highlight) - (put-text-property (match-beginning 1) (match-end 1) - 'local-map ocaml-link-map) - (if (x-display-color-p) - (put-text-property (match-beginning 1) (match-end 1) - 'face 'ocaml-link-face))) - ) - ;; need to restore flag if buffer was unmodified. - (unless modified-p (set-buffer-modified-p nil)) - )) - ))))) - - - -;; bindings ---now in caml.el - -; (and -; (boundp 'caml-mode-map) -; (keymapp caml-mode-map) -; (progn -; (define-key caml-mode-map [?\C-c?i] 'ocaml-add-path) -; (define-key caml-mode-map [?\C-c?]] 'ocaml-close-module) -; (define-key caml-mode-map [?\C-c?[] 'ocaml-open-module) -; (define-key caml-mode-map [?\C-c?\C-h] 'caml-help) -; (define-key caml-mode-map [?\C-c?\t] 'caml-complete) -; (let ((map (lookup-key caml-mode-map [menu-bar caml]))) -; (and -; (keymapp map) -; (progn -; (define-key map [separator-help] '("---")) -; (define-key map [open] '("Open add path" . ocaml-add-path )) -; (define-key map [close] -; '("Close module for help" . ocaml-close-module)) -; (define-key map [open] '("Open module for help" . ocaml-open-module)) -; (define-key map [help] '("Help for identifier" . caml-help)) -; (define-key map [complete] '("Complete identifier" . caml-complete)) -; ) -; )))) - - -(provide 'caml-help) -;;; caml-help.el ends here diff --git a/emacs/caml-hilit.el b/emacs/caml-hilit.el deleted file mode 100644 index 03d6465c..00000000 --- a/emacs/caml-hilit.el +++ /dev/null @@ -1,67 +0,0 @@ -;************************************************************************** -;* * -;* OCaml * -;* * -;* Jacques Garrigue and Ian T Zimmerman * -;* * -;* Copyright 1997 Institut National de Recherche en Informatique et * -;* en Automatique. * -;* * -;* All rights reserved. This file is distributed under the terms of * -;* the GNU General Public License. * -;* * -;************************************************************************** - -; Highlighting patterns for hilit19 under caml-mode - -; defined also in caml.el -(defvar caml-quote-char "'" - "*Quote for character constants. \"'\" for OCaml, \"`\" for Caml-Light.") - -(defconst caml-mode-patterns - (list -;comments - '("\\(^\\|[^\"]\\)\\((\\*[^*]*\\*+\\([^)*][^*]*\\*+\\)*)\\)" - 2 comment) -;string - (list 'hilit-string-find (string-to-char caml-quote-char) 'string) - (list (concat caml-quote-char "\\(\\\\\\([ntbr" caml-quote-char "\\]\\|" - "[0-9][0-9][0-9]\\)\\|.\\)" caml-quote-char) - nil - 'string) -;labels - '("\\(\\([~?]\\|\\<\\)[a-z][a-zA-Z0-9_']*:\\)[^:=]" 1 brown) - '("[~?][ (]*[a-z][a-zA-Z0-9_']*" nil brown) -;modules - '("\\<\\(assert\\|open\\|include\\)\\>" nil brown) - '("`?\\<[A-Z][A-Za-z0-9_\']*\\>" nil MidnightBlue) -;definition - (list (concat - "\\<\\(a\\(nd\\|s\\)\\|c\\(onstraint\\|lass\\)" - "\\|ex\\(ception\\|ternal\\)\\|fun\\(ct\\(ion\\|or\\)\\)?" - "\\|in\\(herit\\)?\\|let\\|m\\(ethod\\|utable\\|odule\\)" - "\\|of\\|p\\(arser\\|rivate\\)\\|rec\\|type" - "\\|v\\(al\\|irtual\\)\\)\\>") - nil 'ForestGreen) -;blocking - '("\\<\\(object\\|struct\\|sig\\|begin\\|end\\)\\>" 2 include) -;control - (list (concat - "\\<\\(do\\(ne\\|wnto\\)?\\|else\\|for\\|i\\(f\\|gnore\\)" - "\\|lazy\\|match\\|new\\|or\\|t\\(hen\\|o\\|ry\\)" - "\\|w\\(h\\(en\\|ile\\)\\|ith\\)\\)\\>" - "\\|\|\\|->\\|&\\|#") - nil 'keyword) - '(";" nil struct)) - "Hilit19 patterns used for OCaml mode") - -(hilit-set-mode-patterns 'caml-mode caml-mode-patterns) -(hilit-set-mode-patterns - 'inferior-caml-mode - (append - (list -;inferior - '("^[#-]" nil firebrick)) - caml-mode-patterns)) - -(provide 'caml-hilit) diff --git a/emacs/caml-types.el b/emacs/caml-types.el deleted file mode 100644 index dc01af64..00000000 --- a/emacs/caml-types.el +++ /dev/null @@ -1,762 +0,0 @@ -;************************************************************************** -;* * -;* OCaml * -;* * -;* Damien Doligez, projet Moscova, INRIA Rocquencourt * -;* * -;* Copyright 2003 Institut National de Recherche en Informatique et * -;* en Automatique. * -;* * -;* All rights reserved. This file is distributed under the terms of * -;* the GNU General Public License. * -;* * -;************************************************************************** - -; An emacs-lisp complement to the "-annot" option of ocamlc and ocamlopt. - -;; XEmacs compatibility - -(eval-and-compile - (if (and (boundp 'running-xemacs) running-xemacs) - (require 'caml-xemacs) - (require 'caml-emacs))) - -(defun caml-types-feedback (info format) - "Displays INFO using the given FORMAT." - (message (format format info)) - (with-current-buffer caml-types-buffer - (erase-buffer) - (insert info))) - -(defvar caml-types-build-dirs '("_build" "_obuild") - "List of possible compilation directories created by build systems. -It is expected that the files under `caml-types-build-dir' preserve -the paths relative to the parent directory of `caml-types-build-dir'.") -(make-variable-buffer-local 'caml-types-build-dir) - -(defvar caml-annot-dir nil - "A directory, generally relative to the file location, containing the -.annot file. Intended to be set as a local variable in the .ml file. -See \"Specifying File Variables\" in the Emacs info manual.") -(make-variable-buffer-local 'caml-annot-dir) -(put 'caml-annot-dir 'safe-local-variable #'stringp) - -(defvar caml-types-location-re nil "Regexp to parse *.annot files. - -Annotation files *.annot may be generated with the \"-annot\" option -of ocamlc and ocamlopt. - -Their format is: - - file ::= block * - block ::= position position annotation * - position ::= filename num num num - annotation ::= keyword open-paren data close-paren - - is a space character (ASCII 0x20) - is a line-feed character (ASCII 0x0A) - num is a sequence of decimal digits - filename is a string with the lexical conventions of OCaml - open-paren is an open parenthesis (ASCII 0x28) - close-paren is a closed parenthesis (ASCII 0x29) - data is any sequence of characters where is always followed by - at least two space characters. - -- in each block, the two positions are respectively the start and the - end of the range described by the block. -- in a position, the filename is the name of the file, the first num - is the line number, the second num is the offset of the beginning - of the line, the third num is the offset of the position itself. -- the char number within the line is the difference between the third - and second nums. - -The current list of keywords is: -type call ident") - -(defvar caml-types-position-re nil) - -(let* ((caml-types-filename-re "\"\\(\\([^\\\"]\\|\\\\.\\)*\\)\"") - (caml-types-number-re "\\([0-9]*\\)")) - (setq caml-types-position-re - (concat caml-types-filename-re " " - caml-types-number-re " " - caml-types-number-re " " - caml-types-number-re)) - (setq caml-types-location-re - (concat "^" caml-types-position-re " " caml-types-position-re))) - -(defvar caml-types-expr-ovl (make-overlay 1 1)) -(make-face 'caml-types-expr-face) -(set-face-doc-string 'caml-types-expr-face - "face for hilighting expressions and types") -(if (not (face-differs-from-default-p 'caml-types-expr-face)) - (set-face-background 'caml-types-expr-face "#88FF44")) -(overlay-put caml-types-expr-ovl 'face 'caml-types-expr-face) - -(defvar caml-types-typed-ovl (make-overlay 1 1)) -(make-face 'caml-types-typed-face) -(set-face-doc-string 'caml-types-typed-face - "face for hilighting typed expressions") -(if (not (face-differs-from-default-p 'caml-types-typed-face)) - (set-face-background 'caml-types-typed-face "#FF8844")) -(overlay-put caml-types-typed-ovl 'face 'caml-types-typed-face) - -(defvar caml-types-scope-ovl (make-overlay 1 1)) -(make-face 'caml-types-scope-face) -(set-face-doc-string 'caml-types-scope-face - "face for hilighting variable scopes") -(if (not (face-differs-from-default-p 'caml-types-scope-face)) - (set-face-background 'caml-types-scope-face "#BBFFFF")) -(overlay-put caml-types-scope-ovl 'face 'caml-types-scope-face) - -(defvar caml-types-def-ovl (make-overlay 1 1)) -(make-face 'caml-types-def-face) -(set-face-doc-string 'caml-types-def-face - "face for hilighting binding occurrences") -(if (not (face-differs-from-default-p 'caml-types-def-face)) - (set-face-background 'caml-types-def-face "#FF4444")) -(overlay-put caml-types-def-ovl 'face 'caml-types-def-face) - -(defvar caml-types-occ-ovl (make-overlay 1 1)) -(make-face 'caml-types-occ-face) -(set-face-doc-string 'caml-types-occ-face - "face for hilighting variable occurrences") -(if (not (face-differs-from-default-p 'caml-types-occ-face)) - (set-face-background 'caml-types-occ-face "#44FF44")) -(overlay-put caml-types-occ-ovl 'face 'caml-types-occ-face) - - -(defvar caml-types-annotation-tree nil) -(defvar caml-types-annotation-date nil) -(make-variable-buffer-local 'caml-types-annotation-tree) -(make-variable-buffer-local 'caml-types-annotation-date) - -(defvar caml-types-buffer-name "*caml-types*" - "Name of buffer for displaying caml types.") -(defvar caml-types-buffer nil - "Buffer for displaying caml types.") - -(defun caml-types-show-type (arg) - "Show the type of expression or pattern at point. - -The smallest expression or pattern that contains point is -temporarily highlighted. Its type is highlighted in the .annot -file and the mark is set to the beginning of the type. The type -is also displayed in the mini-buffer. - -Hints on using the type display: -. If you want the type of an identifier, put point within any -occurrence of this identifier. -. If you want the result type of a function application, put -point at the first space after the function name. . If you want -the type of a list, put point on a bracket, on a semicolon, or on -the :: constructor. -. Even if type checking fails, you can still look at the types -in the file, up to where the type checker failed. - -Types are also displayed in the buffer *caml-types*, which is -displayed when the command is called with Prefix argument 4. - -See also `caml-types-explore' for exploration by mouse dragging. -See `caml-types-location-re' for annotation file format." - (interactive "p") - (let* ((target-buf (current-buffer)) - (target-file (file-name-nondirectory (buffer-file-name))) - (target-line (1+ (count-lines (point-min) - (caml-line-beginning-position)))) - (target-bol (caml-line-beginning-position)) - (target-cnum (point))) - (caml-types-preprocess (buffer-file-name)) - (setq caml-types-buffer (get-buffer-create caml-types-buffer-name)) - (let* ((targ-loc (vector target-file target-line target-bol target-cnum)) - (node (caml-types-find-location targ-loc "type" () - caml-types-annotation-tree))) - (cond - ((null node) - (delete-overlay caml-types-expr-ovl) - (message "Point is not within a typechecked expression or pattern.")) - (t - (let ((left (caml-types-get-pos target-buf (elt node 0))) - (right (caml-types-get-pos target-buf (elt node 1))) - (type (cdr (assoc "type" (elt node 2))))) - (move-overlay caml-types-expr-ovl left right target-buf) - (caml-types-feedback type "type: %s"))))) - (if (and (= arg 4) - (not (window-live-p (get-buffer-window caml-types-buffer)))) - (display-buffer caml-types-buffer)) - (unwind-protect - (caml-sit-for 60) - (delete-overlay caml-types-expr-ovl)))) - -(defun caml-types-show-call (arg) - "Show the kind of call at point. - -The smallest function call that contains point is temporarily -highlighted. Its kind is highlighted in the .annot file and the -mark is set to the beginning of the kind. The kind is also -displayed in the mini-buffer. - -The kind is also displayed in the buffer *caml-types*, which is -displayed when the command is called with Prefix argument 4. - -See `caml-types-location-re' for annotation file format." - (interactive "p") - (let* ((target-buf (current-buffer)) - (target-file (file-name-nondirectory (buffer-file-name))) - (target-line (1+ (count-lines (point-min) - (caml-line-beginning-position)))) - (target-bol (caml-line-beginning-position)) - (target-cnum (point))) - (caml-types-preprocess (buffer-file-name)) - (setq caml-types-buffer (get-buffer-create caml-types-buffer-name)) - (let* ((targ-loc (vector target-file target-line target-bol target-cnum)) - (node (caml-types-find-location targ-loc "call" () - caml-types-annotation-tree))) - (cond - ((null node) - (delete-overlay caml-types-expr-ovl) - (message "Point is not within a function call.")) - (t - (let ((left (caml-types-get-pos target-buf (elt node 0))) - (right (caml-types-get-pos target-buf (elt node 1))) - (kind (cdr (assoc "call" (elt node 2))))) - (move-overlay caml-types-expr-ovl left right target-buf) - (caml-types-feedback kind "%s call"))))) - (if (and (= arg 4) - (not (window-live-p (get-buffer-window caml-types-buffer)))) - (display-buffer caml-types-buffer)) - (unwind-protect - (caml-sit-for 60) - (delete-overlay caml-types-expr-ovl)))) - -(defun caml-types-show-ident (arg) - "Show the binding of identifier at point. - -The identifier that contains point is temporarily highlighted. -Its binding is highlighted in the .annot file and the mark is set -to the beginning of the binding. The binding is also displayed -in the mini-buffer. - -The binding is also displayed in the buffer *caml-types*, which is -displayed when the command is called with Prefix argument 4. - -See `caml-types-location-re' for annotation file format." - (interactive "p") - (let* ((target-buf (current-buffer)) - (target-file (file-name-nondirectory (buffer-file-name))) - (target-line (1+ (count-lines (point-min) - (caml-line-beginning-position)))) - (target-bol (caml-line-beginning-position)) - (target-cnum (point))) - (caml-types-preprocess (buffer-file-name)) - (setq caml-types-buffer (get-buffer-create caml-types-buffer-name)) - (let* ((targ-loc (vector target-file target-line target-bol target-cnum)) - (node (caml-types-find-location targ-loc "ident" () - caml-types-annotation-tree))) - (cond - ((null node) - (delete-overlay caml-types-expr-ovl) - (message "Point is not within an identifier.")) - (t - (let ((left (caml-types-get-pos target-buf (elt node 0))) - (right (caml-types-get-pos target-buf (elt node 1))) - (kind (cdr (assoc "ident" (elt node 2))))) - (move-overlay caml-types-expr-ovl left right target-buf) - (let* ((loc-re (concat caml-types-position-re " " - caml-types-position-re)) - (end-re (concat caml-types-position-re " --")) - (def-re (concat "def \\([^ ]*\\) " loc-re)) - (def-end-re (concat "def \\([^ ]*\\) " end-re)) - (internal-re (concat "int_ref \\([^ ]*\\) " loc-re)) - (external-re "ext_ref \\(.*\\)")) - (cond - ((string-match def-re kind) - (let ((var-name (match-string 1 kind)) - (l-file (file-name-nondirectory (match-string 2 kind))) - (l-line (caml-string-to-int (match-string 4 kind))) - (l-bol (caml-string-to-int (match-string 5 kind))) - (l-cnum (caml-string-to-int (match-string 6 kind))) - (r-file (file-name-nondirectory (match-string 7 kind))) - (r-line (caml-string-to-int (match-string 9 kind))) - (r-bol (caml-string-to-int (match-string 10 kind))) - (r-cnum (caml-string-to-int (match-string 11 kind)))) - (let* ((lpos (vector l-file l-line l-bol l-cnum)) - (rpos (vector r-file r-line r-bol r-cnum)) - (left (caml-types-get-pos target-buf lpos)) - (right (caml-types-get-pos target-buf rpos))) - (message (format "local variable %s is bound here" var-name)) - (move-overlay caml-types-scope-ovl left right target-buf)))) - ((string-match def-end-re kind) - (let ((var-name (match-string 1 kind)) - (l-file (file-name-nondirectory (match-string 2 kind))) - (l-line (caml-string-to-int (match-string 4 kind))) - (l-bol (caml-string-to-int (match-string 5 kind))) - (l-cnum (caml-string-to-int (match-string 6 kind)))) - (let* ((lpos (vector l-file l-line l-bol l-cnum)) - (left (caml-types-get-pos target-buf lpos)) - (right (buffer-size target-buf))) - (message (format "global variable %s is bound here" var-name)) - (move-overlay caml-types-scope-ovl left right target-buf)))) - ((string-match internal-re kind) - (let ((var-name (match-string 1 kind)) - (l-file (file-name-nondirectory (match-string 2 kind))) - (l-line (caml-string-to-int (match-string 4 kind))) - (l-bol (caml-string-to-int (match-string 5 kind))) - (l-cnum (caml-string-to-int (match-string 6 kind))) - (r-file (file-name-nondirectory (match-string 7 kind))) - (r-line (caml-string-to-int (match-string 9 kind))) - (r-bol (caml-string-to-int (match-string 10 kind))) - (r-cnum (caml-string-to-int (match-string 11 kind)))) - (let* ((lpos (vector l-file l-line l-bol l-cnum)) - (rpos (vector r-file r-line r-bol r-cnum)) - (left (caml-types-get-pos target-buf lpos)) - (right (caml-types-get-pos target-buf rpos))) - (move-overlay caml-types-def-ovl left right target-buf) - (message (format "%s is bound at line %d char %d" - var-name l-line (- l-cnum l-bol)))))) - ((string-match external-re kind) - (let ((fullname (match-string 1 kind))) - (caml-types-feedback fullname "external ident: %s"))))))))) - (if (and (= arg 4) - (not (window-live-p (get-buffer-window caml-types-buffer)))) - (display-buffer caml-types-buffer)) - (unwind-protect - (caml-sit-for 60) - (delete-overlay caml-types-expr-ovl) - (delete-overlay caml-types-def-ovl) - (delete-overlay caml-types-scope-ovl)))) - -(defun caml-types-preprocess (target-path) - (let* ((type-path (caml-types-locate-type-file target-path)) - (type-date (nth 5 (file-attributes (file-chase-links type-path)))) - (target-date (nth 5 (file-attributes target-file)))) - (unless (and caml-types-annotation-tree - type-date - caml-types-annotation-date - (not (caml-types-date< caml-types-annotation-date type-date))) - (if (and type-date target-date (caml-types-date< type-date target-date)) - (error (format "`%s' is more recent than `%s'" - target-path type-path))) - (message "Reading annotation file...") - (let* ((type-buf (caml-types-find-file type-path)) - (tree (with-current-buffer type-buf - (widen) - (goto-char (point-min)) - (caml-types-build-tree - (file-name-nondirectory target-path))))) - (setq caml-types-annotation-tree tree - caml-types-annotation-date type-date) - (kill-buffer type-buf) - (message "done"))))) - -(defun caml-types-parent-dir (d) (file-name-directory (directory-file-name d))) - -(defun caml-types-locate-type-file (target-path) - "Given the path to an OCaml file, try to locate and return the -corresponding .annot file." - (let ((sibling (concat (file-name-sans-extension target-path) ".annot"))) - (if (file-exists-p sibling) - sibling - (let* ((dir (file-name-directory sibling))) - (if caml-annot-dir - ;; Use the relative path set by the user - (let* ((annot-dir (expand-file-name caml-annot-dir dir)) - (fname (file-name-nondirectory sibling)) - (path-fname (expand-file-name fname annot-dir))) - (if (file-exists-p path-fname) - path-fname - (error (concat "No annotation file in " caml-annot-dir - ". Compile with option \"-annot\".")))) - ;; Else, try to get the .annot from one of build dirs. - (let* ((is-build (regexp-opt caml-types-build-dirs)) - (project-dir (locate-dominating-file - dir - (lambda(d) (directory-files d nil is-build)))) - (annot - (if project-dir - (locate-file - (file-relative-name sibling project-dir) - (mapcar (lambda(d) (expand-file-name d project-dir)) - caml-types-build-dirs))))) - (if annot - annot - (error (concat "No annotation file. Compile with option " - "\"-annot\" or set `caml-annot-dir'."))))))))) - -(defun caml-types-date< (date1 date2) - (or (< (car date1) (car date2)) - (and (= (car date1) (car date2)) - (< (nth 1 date1) (nth 1 date2))))) - - -; we use an obarray for hash-consing the strings within each tree - -(defun caml-types-make-hash-table () - (make-vector 255 0)) - -(defun caml-types-hcons (elem table) - (symbol-name (intern elem table))) - - -(defun next-annotation () - (forward-char 1) - (if (re-search-forward "^[a-z\"]" () t) - (forward-char -1) - (goto-char (point-max))) - (looking-at "[a-z]")) - -; tree of intervals -; each node is a vector -; [ pos-left pos-right annotation child child child... ] -; annotation is a list of: -; (kind . info) where kind = "type" "call" etc. -; and info = the contents of the annotation - -(defun caml-types-build-tree (target-file) - (let ((stack ()) - (accu ()) - (table (caml-types-make-hash-table)) - (annotation ())) - (while (re-search-forward caml-types-location-re () t) - (let ((l-file (file-name-nondirectory (match-string 1))) - (l-line (caml-string-to-int (match-string 3))) - (l-bol (caml-string-to-int (match-string 4))) - (l-cnum (caml-string-to-int (match-string 5))) - (r-file (file-name-nondirectory (match-string 6))) - (r-line (caml-string-to-int (match-string 8))) - (r-bol (caml-string-to-int (match-string 9))) - (r-cnum (caml-string-to-int (match-string 10)))) - (unless (caml-types-not-in-file l-file r-file target-file) - (setq annotation ()) - (while (next-annotation) - (cond ((looking-at "^\\([a-z]+\\)(\n \\(\\(.*\n \\)*.*\\)\n)") - (let ((kind (caml-types-hcons (match-string 1) table)) - (info (caml-types-hcons (match-string 2) table))) - (setq annotation (cons (cons kind info) annotation)))))) - (setq accu ()) - (while (and stack - (caml-types-pos-contains l-cnum r-cnum (car stack))) - (setq accu (cons (car stack) accu)) - (setq stack (cdr stack))) - (let* ((left-pos (vector l-file l-line l-bol l-cnum)) - (right-pos (vector r-file r-line r-bol r-cnum)) - (node (caml-types-make-node left-pos right-pos annotation - accu))) - (setq stack (cons node stack)))))) - (if (null stack) - (error "No annotations found for this source file") - (let* ((left-pos (elt (car (last stack)) 0)) - (right-pos (elt (car stack) 1))) - (if (null (cdr stack)) - (car stack) - (caml-types-make-node left-pos right-pos () (nreverse stack))))))) - -(defun caml-types-not-in-file (l-file r-file target-file) - (or (and (not (string= l-file target-file)) - (not (string= l-file ""))) - (and (not (string= r-file target-file)) - (not (string= r-file ""))))) - -(defun caml-types-make-node (left-pos right-pos annotation children) - (let ((result (make-vector (+ 3 (length children)) ())) - (i 3)) - (aset result 0 left-pos) - (aset result 1 right-pos) - (aset result 2 annotation) - (while children - (aset result i (car children)) - (setq children (cdr children)) - (setq i (1+ i))) - result)) - -(defun caml-types-pos-contains (l-cnum r-cnum node) - (and (<= l-cnum (elt (elt node 0) 3)) - (>= r-cnum (elt (elt node 1) 3)))) - -(defun caml-types-find-location (targ-pos kind curr node) - (if (not (caml-types-pos-inside targ-pos node)) - curr - (if (and (elt node 2) (assoc kind (elt node 2))) - (setq curr node)) - (let ((i (caml-types-search node targ-pos))) - (if (and (> i 3) - (caml-types-pos-inside targ-pos (elt node (1- i)))) - (caml-types-find-location targ-pos kind curr (elt node (1- i))) - curr)))) - -; trouve le premier fils qui commence apres la position -; ou (length node) si tous commencent avant -(defun caml-types-search (node pos) - (let ((min 3) - (max (length node)) - med) - (while (< min max) - (setq med (/ (+ min max) 2)) - (if (caml-types-pos<= (elt (elt node med) 0) pos) - (setq min (1+ med)) - (setq max med))) - min)) - -(defun caml-types-pos-inside (pos node) - (let ((left-pos (elt node 0)) - (right-pos (elt node 1))) - (and (caml-types-pos<= left-pos pos) - (caml-types-pos> right-pos pos)))) - -(defun caml-types-find-interval (buf targ-pos node) - (let ((nleft (elt node 0)) - (nright (elt node 1)) - (left ()) - (right ()) - i) - (cond - ((not (caml-types-pos-inside targ-pos node)) - (if (not (caml-types-pos<= nleft targ-pos)) - (setq right nleft)) - (if (not (caml-types-pos> nright targ-pos)) - (setq left nright))) - (t - (setq left nleft - right nright) - (setq i (caml-types-search node targ-pos)) - (if (< i (length node)) - (setq right (elt (elt node i) 0))) - (if (> i 3) - (setq left (elt (elt node (1- i)) 1))))) - (cons (if left - (caml-types-get-pos buf left) - (with-current-buffer buf (point-min))) - (if right - (caml-types-get-pos buf right) - (with-current-buffer buf (point-max)))))) - - -;; Warning: these comparison functions are not symmetric. -;; The first argument determines the format: -;; when its file component is empty, only the cnum is compared. - -(defun caml-types-pos<= (pos1 pos2) - (let ((file1 (elt pos1 0)) - (line1 (elt pos1 1)) - (bol1 (elt pos1 2)) - (cnum1 (elt pos1 3)) - (file2 (elt pos2 0)) - (line2 (elt pos2 1)) - (bol2 (elt pos2 2)) - (cnum2 (elt pos2 3))) - (if (string= file1 "") - (<= cnum1 cnum2) - (and (string= file1 file2) - (or (< line1 line2) - (and (= line1 line2) - (<= (- cnum1 bol1) (- cnum2 bol2)))))))) - -(defun caml-types-pos> (pos1 pos2) - (let ((file1 (elt pos1 0)) - (line1 (elt pos1 1)) - (bol1 (elt pos1 2)) - (cnum1 (elt pos1 3)) - (file2 (elt pos2 0)) - (line2 (elt pos2 1)) - (bol2 (elt pos2 2)) - (cnum2 (elt pos2 3))) - (if (string= file1 "") - (> cnum1 cnum2) - (and (string= file1 file2) - (or (> line1 line2) - (and (= line1 line2) - (> (- cnum1 bol1) (- cnum2 bol2)))))))) - -(defun caml-types-get-pos (buf pos) - (save-excursion - (set-buffer buf) - (goto-line (elt pos 1)) - (forward-char (- (elt pos 3) (elt pos 2))) - (point))) - -; find-file-read-only-noselect seems to be missing from emacs... -(defun caml-types-find-file (name) - (let (buf) - (cond - ((setq buf (get-file-buffer name)) - (unless (verify-visited-file-modtime buf) - (if (buffer-modified-p buf) - (find-file-noselect name) - (with-current-buffer buf (revert-buffer t t))))) - ((and (file-readable-p name) - (setq buf (find-file-noselect name))) - (with-current-buffer buf (toggle-read-only 1))) - (t - (error (format "Can't read the annotation file `%s'" name)))) - buf)) - -(defun caml-types-mouse-ignore (event) - (interactive "e") - nil) - -(defun caml-types-time () - (let ((time (current-time))) - (+ (* (mod (cadr time) 1000) 1000) - (/ (cadr (cdr time)) 1000)))) - -(defun caml-types-explore (event) - "Explore type annotations by mouse dragging. - -The expression under the mouse is highlighted and its type is displayed -in the minibuffer, until the move is released, much as `caml-types-show-type'. -The function uses two overlays. - - . One overlay delimits the largest region whose all subnodes - are well-typed. - . Another overlay delimits the current node under the mouse (whose type - annotation is being displayed)." - (interactive "e") - (set-buffer (window-buffer (caml-event-window event))) - (let* ((target-buf (current-buffer)) - (target-file (file-name-nondirectory (buffer-file-name))) - (target-line) (target-bol) - target-pos - Left Right limits cnum node mes type - region - (window (caml-event-window event)) - target-tree - (speed 100) - (last-time (caml-types-time)) - (original-event event)) - (select-window window) - (unwind-protect - (progn - (caml-types-preprocess (buffer-file-name)) - (setq target-tree caml-types-annotation-tree) - (setq caml-types-buffer (get-buffer-create caml-types-buffer-name)) - ;; (message "Drag the mouse to explore types") - (unwind-protect - (caml-track-mouse - (while event - (cond - ;; we ignore non mouse events - ((caml-ignore-event-p event)) - ;; we stop when the original button is released - ((caml-release-event-p original-event event) - (setq event nil)) - ;; we scroll when the motion is outside the window - ((and (caml-mouse-movement-p event) - (not (and (equal window (caml-event-window event)) - (integer-or-marker-p - (caml-event-point-end event))))) - (let* ((win (caml-window-edges window)) - (top (nth 1 win)) - (bottom (- (nth 3 win) 1)) - mouse - time) - (while (and - (caml-sit-for 0 (/ 500 speed)) - (setq time (caml-types-time)) - (> (- time last-time) (/ 500 speed)) - (setq mouse (caml-mouse-vertical-position)) - (or (< mouse top) (>= mouse bottom))) - (setq last-time time) - (cond - ((< mouse top) - (setq speed (- top mouse)) - (condition-case nil - (scroll-down 1) - (error (message "Beginning of buffer!")))) - ((>= mouse bottom) - (setq speed (+ 1 (- mouse bottom))) - (condition-case nil - (scroll-up 1) - (error (message "End of buffer!"))))) - (setq speed (* speed speed))))) - ;; main action, when the motion is inside the window - ;; or on original button down event - ((or (caml-mouse-movement-p event) - (equal original-event event)) - (setq cnum (caml-event-point-end event)) - (if (and region - (<= (car region) cnum) (< cnum (cdr region))) - ;; mouse remains in outer region - nil - ;; otherwise, reset the outer region - (setq region - (caml-types-typed-make-overlay - target-buf (caml-event-point-start event)))) - (if - (and limits - (>= cnum (car limits)) (< cnum (cdr limits))) - ;; inner region is unchanged - nil - ;; recompute the inner region and type annotation - (setq target-bol - (save-excursion - (goto-char cnum) (caml-line-beginning-position)) - target-line (1+ (count-lines (point-min) - target-bol)) - target-pos - (vector target-file target-line target-bol cnum)) - (save-excursion - (setq node (caml-types-find-location target-pos "type" () - target-tree)) - (set-buffer caml-types-buffer) - (erase-buffer) - (cond - ((null node) - (delete-overlay caml-types-expr-ovl) - (setq type "*no type information*") - (setq limits - (caml-types-find-interval - target-buf target-pos target-tree))) - (t - (let ((left - (caml-types-get-pos target-buf (elt node 0))) - (right - (caml-types-get-pos target-buf (elt node 1)))) - (move-overlay - caml-types-expr-ovl left right target-buf) - (setq limits - (caml-types-find-interval target-buf - target-pos node) - type (cdr (assoc "type" (elt node 2))))))) - (setq mes (format "type: %s" type)) - (insert type))) - (message mes))) - ;; we read next event, unless it is nil, and loop back. - (if event (setq event (caml-read-event))))) - ;; delete overlays at end of exploration - (delete-overlay caml-types-expr-ovl) - (delete-overlay caml-types-typed-ovl))) - ;; When an error occurs, the mouse release event has not been read. - ;; We could wait for mouse release to prevent execution of - ;; a binding of mouse release, such as cut or paste. - ;; In most common cases, next event will be the mouse release. - ;; However, it could also be a key stroke before mouse release. - ;; Emacs does not allow to test whether mouse is up or down. - ;; Not sure it is robust to loop for mouse release after an error - ;; occurred, as is done for exploration. - ;; So far, we just ignore next event. (Next line also be uncommenting.) - (if event (caml-read-event))))) - -(defun caml-types-typed-make-overlay (target-buf pos) - (interactive "p") - (let ((start pos) (end pos) len node left right) - (setq len (length caml-types-annotation-tree)) - (while (> len 3) - (setq len (- len 1)) - (setq node (aref caml-types-annotation-tree len)) - (if (and (equal target-buf (current-buffer)) - (setq left (caml-types-get-pos target-buf (elt node 0)) - right (caml-types-get-pos target-buf (elt node 1))) - (<= left pos) (> right pos)) - (setq start (min start left) - end (max end right)))) - (move-overlay caml-types-typed-ovl - (max (point-min) (- start 1)) - (min (point-max) (+ end 1)) target-buf) - (cons start end))) - -(defun caml-types-version () - "Internal version number of caml-types.el." - (interactive) - (message "4")) - -(provide 'caml-types) diff --git a/emacs/caml-xemacs.el b/emacs/caml-xemacs.el deleted file mode 100644 index 110817ff..00000000 --- a/emacs/caml-xemacs.el +++ /dev/null @@ -1,57 +0,0 @@ -;************************************************************************** -;* * -;* OCaml * -;* * -;* Didier Remy, projet Cristal, INRIA Rocquencourt * -;* * -;* Copyright 2003 Institut National de Recherche en Informatique et * -;* en Automatique. * -;* * -;* All rights reserved. This file is distributed under the terms of * -;* the GNU General Public License. * -;* * -;************************************************************************** - -(require 'overlay) - -;; for caml-help.el -(defun caml-info-other-window (arg) - (save-excursion (info arg)) - (view-buffer-other-window "*info*")) - -;; for caml-types.el -(defun caml-line-beginning-position () - (save-excursion (beginning-of-line) (point))) - -(defalias 'caml-read-event 'next-event) -(defalias 'caml-window-edges 'window-pixel-edges) -(defun caml-mouse-vertical-position () - (let ((e (mouse-position-as-motion-event))) - (and e (event-y-pixel e)))) -(defalias 'caml-mouse-movement-p 'motion-event-p) -(defun caml-event-window (e) - (and (mouse-event-p e) (event-window e))) -(defun caml-event-point-start (e) (event-closest-point e)) -(defun caml-event-point-end (e) (event-closest-point e)) -(defun caml-ignore-event-p (e) - (if (and (key-press-event-p e) (equal (key-binding e) 'keyboard-quit)) - (keyboard-quit)) - (not (mouse-event-p e))) - - -(defun caml-sit-for (sec &optional mili) - (sit-for (+ sec (if mili (* 0.001 mili) 0)))) - - - -(defmacro caml-track-mouse (&rest body) (cons 'progn body)) - -(defun caml-release-event-p (original event) - (and (button-release-event-p event) - (equal (event-button original) (event-button event)))) - -(if (fboundp 'string-to-number) - (defalias 'caml-string-to-int 'string-to-number) - (defalias 'caml-string-to-int 'string-to-int)) - -(provide 'caml-xemacs) diff --git a/emacs/caml.el b/emacs/caml.el deleted file mode 100644 index 1945fbad..00000000 --- a/emacs/caml.el +++ /dev/null @@ -1,1986 +0,0 @@ -;;; caml.el --- OCaml code editing commands for Emacs - -;; Copyright (C) 1997-2017 Institut National de Recherche en Informatique et en Automatique. - -;; Author: Jacques Garrigue -;; Ian T Zimmerman -;; Maintainer: Damien Doligez -;; Created: July 1993 -;; Keywords: OCaml -;; Homepage: https://github.com/ocaml/ocaml/ - -;; This file is not part of GNU Emacs. - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; A major mode for editing OCaml code (see ) in Emacs. - -;; Some of its major features include: - -;; - syntax highlighting (font lock); -;; - automatic indentation; -;; - querying the type of expressions (using compiler generated annot files); -;; - running an OCaml REPL within Emacs; -;; - scans declarations and places them in a menu. - - -;; The original indentation code was the work of Ian T Zimmerman and -;; was adapted for OCaml by Jacques Garrigue in July 1997. - -;;; Code: - -;;user customizable variables -(defvar caml-quote-char "'" - "*Quote for character constants. \"'\" for OCaml, \"`\" for Caml-Light.") - -(defvar caml-imenu-enable nil - "*Enable Imenu support.") - -(defvar caml-mode-indentation 2 - "*Used for \\[caml-unindent-command].") - -(defvar caml-lookback-limit 5000 - "*How far to look back for syntax things in caml mode.") - -(defvar caml-max-indent-priority 8 - "*Bounds priority of operators permitted to affect caml indentation. - -Priorities are assigned to `interesting' caml operators as follows: - - all keywords 0 to 7 8 - type, val, ... + 0 7 - :: ^ 6 - @ 5 - := <- 4 - if 3 - fun, let, match ... 2 - module 1 - opening keywords 0.") - -(defvar caml-apply-extra-indent 2 - "*How many spaces to add to indentation for an application in caml mode.") -(make-variable-buffer-local 'caml-apply-extra-indent) - -(defvar caml-begin-indent 2 - "*How many spaces to indent from a \"begin\" keyword in caml mode.") -(make-variable-buffer-local 'caml-begin-indent) - -(defvar caml-class-indent 2 - "*How many spaces to indent from a \"class\" keyword in caml mode.") -(make-variable-buffer-local 'caml-class-indent) - -(defvar caml-exception-indent 2 - "*How many spaces to indent from an \"exception\" keyword in caml mode.") -(make-variable-buffer-local 'caml-exception-indent) - -(defvar caml-for-indent 2 - "*How many spaces to indent from a \"for\" keyword in caml mode.") -(make-variable-buffer-local 'caml-for-indent) - -(defvar caml-fun-indent 2 - "*How many spaces to indent from a \"fun\" keyword in caml mode.") -(make-variable-buffer-local 'caml-fun-indent) - -(defvar caml-function-indent 4 - "*How many spaces to indent from a \"function\" keyword in caml mode.") -(make-variable-buffer-local 'caml-function-indent) - -(defvar caml-if-indent 2 - "*How many spaces to indent from an \"if\" keyword in caml mode.") -(make-variable-buffer-local 'caml-if-indent) - -(defvar caml-if-else-indent 0 - "*How many spaces to indent from an \"if .. else\" line in caml mode.") -(make-variable-buffer-local 'caml-if-else-indent) - -(defvar caml-inherit-indent 2 - "*How many spaces to indent from an \"inherit\" keyword in caml mode.") -(make-variable-buffer-local 'caml-inherit-indent) - -(defvar caml-initializer-indent 2 - "*How many spaces to indent from an \"initializer\" keyword in caml mode.") -(make-variable-buffer-local 'caml-initializer-indent) - -(defvar caml-include-indent 2 - "*How many spaces to indent from an \"include\" keyword in caml mode.") -(make-variable-buffer-local 'caml-include-indent) - -(defvar caml-let-indent 2 - "*How many spaces to indent from a \"let\" keyword in caml mode.") -(make-variable-buffer-local 'caml-let-indent) - -(defvar caml-let-in-indent 0 - "*How many spaces to indent from a \"let .. in\" keyword in caml mode.") -(make-variable-buffer-local 'caml-let-in-indent) - -(defvar caml-match-indent 2 - "*How many spaces to indent from a \"match\" keyword in caml mode.") -(make-variable-buffer-local 'caml-match-indent) - -(defvar caml-method-indent 2 - "*How many spaces to indent from a \"method\" keyword in caml mode.") -(make-variable-buffer-local 'caml-method-indent) - -(defvar caml-module-indent 2 - "*How many spaces to indent from a \"module\" keyword in caml mode.") -(make-variable-buffer-local 'caml-module-indent) - -(defvar caml-object-indent 2 - "*How many spaces to indent from an \"object\" keyword in caml mode.") -(make-variable-buffer-local 'caml-object-indent) - -(defvar caml-of-indent 2 - "*How many spaces to indent from an \"of\" keyword in caml mode.") -(make-variable-buffer-local 'caml-of-indent) - -(defvar caml-parser-indent 4 - "*How many spaces to indent from a \"parser\" keyword in caml mode.") -(make-variable-buffer-local 'caml-parser-indent) - -(defvar caml-sig-indent 2 - "*How many spaces to indent from a \"sig\" keyword in caml mode.") -(make-variable-buffer-local 'caml-sig-indent) - -(defvar caml-struct-indent 2 - "*How many spaces to indent from a \"struct\" keyword in caml mode.") -(make-variable-buffer-local 'caml-struct-indent) - -(defvar caml-try-indent 2 - "*How many spaces to indent from a \"try\" keyword in caml mode.") -(make-variable-buffer-local 'caml-try-indent) - -(defvar caml-type-indent 4 - "*How many spaces to indent from a \"type\" keyword in caml mode.") -(make-variable-buffer-local 'caml-type-indent) - -(defvar caml-val-indent 2 - "*How many spaces to indent from a \"val\" keyword in caml mode.") -(make-variable-buffer-local 'caml-val-indent) - -(defvar caml-while-indent 2 - "*How many spaces to indent from a \"while\" keyword in caml mode.") -(make-variable-buffer-local 'caml-while-indent) - -(defvar caml-::-indent 2 - "*How many spaces to indent from a \"::\" operator in caml mode.") -(make-variable-buffer-local 'caml-::-indent) - -(defvar caml-@-indent 2 - "*How many spaces to indent from a \"@\" operator in caml mode.") -(make-variable-buffer-local 'caml-@-indent) - -(defvar caml-:=-indent 2 - "*How many spaces to indent from a \":=\" operator in caml mode.") -(make-variable-buffer-local 'caml-:=-indent) - -(defvar caml-<--indent 2 - "*How many spaces to indent from a \"<-\" operator in caml mode.") -(make-variable-buffer-local 'caml-<--indent) - -(defvar caml-->-indent 2 - "*How many spaces to indent from a \"->\" operator in caml mode.") -(make-variable-buffer-local 'caml-->-indent) - -(defvar caml-lb-indent 2 - "*How many spaces to indent from a \"\[\" operator in caml mode.") -(make-variable-buffer-local 'caml-lb-indent) - -(defvar caml-lc-indent 2 - "*How many spaces to indent from a \"\{\" operator in caml mode.") -(make-variable-buffer-local 'caml-lc-indent) - -(defvar caml-lp-indent 1 - "*How many spaces to indent from a \"\(\" operator in caml mode.") -(make-variable-buffer-local 'caml-lp-indent) - -(defvar caml-and-extra-indent nil - "*Extra indent for caml lines starting with the \"and\" keyword. -Usually negative. nil is align on master.") -(make-variable-buffer-local 'caml-and-extra-indent) - -(defvar caml-do-extra-indent nil - "*Extra indent for caml lines starting with the \"do\" keyword. -Usually negative. nil is align on master.") -(make-variable-buffer-local 'caml-do-extra-indent) - -(defvar caml-done-extra-indent nil - "*Extra indent for caml lines starting with the \"done\" keyword. -Usually negative. nil is align on master.") -(make-variable-buffer-local 'caml-done-extra-indent) - -(defvar caml-else-extra-indent nil - "*Extra indent for caml lines starting with the \"else\" keyword. -Usually negative. nil is align on master.") -(make-variable-buffer-local 'caml-else-extra-indent) - -(defvar caml-end-extra-indent nil - "*Extra indent for caml lines starting with the \"end\" keyword. -Usually negative. nil is align on master.") -(make-variable-buffer-local 'caml-end-extra-indent) - -(defvar caml-in-extra-indent nil - "*Extra indent for caml lines starting with the \"in\" keyword. -Usually negative. nil is align on master.") -(make-variable-buffer-local 'caml-in-extra-indent) - -(defvar caml-then-extra-indent nil - "*Extra indent for caml lines starting with the \"then\" keyword. -Usually negative. nil is align on master.") -(make-variable-buffer-local 'caml-then-extra-indent) - -(defvar caml-to-extra-indent -1 - "*Extra indent for caml lines starting with the \"to\" keyword. -Usually negative. nil is align on master.") -(make-variable-buffer-local 'caml-to-extra-indent) - -(defvar caml-with-extra-indent nil - "*Extra indent for caml lines starting with the \"with\" keyword. -Usually negative. nil is align on master.") -(make-variable-buffer-local 'caml-with-extra-indent) - -(defvar caml-comment-indent 3 - "*Indent inside comments.") -(make-variable-buffer-local 'caml-comment-indent) - -(defvar caml-|-extra-indent -2 - "*Extra indent for caml lines starting with the | operator. -Usually negative. nil is align on master.") -(make-variable-buffer-local 'caml-|-extra-indent) - -(defvar caml-rb-extra-indent -2 - "*Extra indent for caml lines starting with ]. -Usually negative. nil is align on master.") - -(defvar caml-rc-extra-indent -2 - "*Extra indent for caml lines starting with }. -Usually negative. nil is align on master.") - -(defvar caml-rp-extra-indent -1 - "*Extra indent for caml lines starting with ). -Usually negative. nil is align on master.") - -(defvar caml-electric-indent t - "*Non-nil means electrically indent lines starting with |, ] or }. - -Many people find electric keys irritating, so you can disable them if -you are one.") - -(defvar caml-electric-close-vector t - "*Non-nil means electrically insert a | before a vector-closing ]. - -Many people find electric keys irritating, so you can disable them if -you are one. You should probably have this on, though, if you also -have caml-electric-indent on, which see.") - -;;code -(if (or (not (fboundp 'indent-line-to)) - (not (fboundp 'buffer-substring-no-properties))) - (require 'caml-compat)) - -(defvar caml-shell-active nil - "Non nil when a subshell is running.") - -(defvar caml-mode-map nil - "Keymap used in Caml mode.") -(if caml-mode-map - () - (setq caml-mode-map (make-sparse-keymap)) - (define-key caml-mode-map "|" 'caml-electric-pipe) - (define-key caml-mode-map "}" 'caml-electric-pipe) - (define-key caml-mode-map "]" 'caml-electric-rb) - (define-key caml-mode-map "\t" 'caml-indent-command) - (define-key caml-mode-map [backtab] 'caml-unindent-command) - -;itz 04-21-96 instead of defining a new function, use defadvice -;that way we get out effect even when we do \C-x` in compilation buffer -; (define-key caml-mode-map "\C-x`" 'caml-next-error) - - (if (featurep 'xemacs) - (define-key caml-mode-map 'backspace 'backward-delete-char-untabify) - (define-key caml-mode-map "\177" 'backward-delete-char-untabify)) - - ;; caml-types - (define-key caml-mode-map [?\C-c?\C-t] 'caml-types-show-type) ; "type" - (define-key caml-mode-map [?\C-c?\C-f] 'caml-types-show-call) ; "function" - (define-key caml-mode-map [?\C-c?\C-l] 'caml-types-show-ident) ; "let" - ;; must be a mouse-down event. Can be any button and any prefix - (define-key caml-mode-map [?\C-c down-mouse-1] 'caml-types-explore) - ;; caml-help - (define-key caml-mode-map [?\C-c?i] 'ocaml-add-path) - (define-key caml-mode-map [?\C-c?\]] 'ocaml-close-module) - (define-key caml-mode-map [?\C-c?\[] 'ocaml-open-module) - (define-key caml-mode-map [?\C-c?\C-h] 'caml-help) - (define-key caml-mode-map [?\C-c?\t] 'caml-complete) - ;; others - (define-key caml-mode-map "\C-cb" 'caml-insert-begin-form) - (define-key caml-mode-map "\C-cf" 'caml-insert-for-form) - (define-key caml-mode-map "\C-ci" 'caml-insert-if-form) - (define-key caml-mode-map "\C-cl" 'caml-insert-let-form) - (define-key caml-mode-map "\C-cm" 'caml-insert-match-form) - (define-key caml-mode-map "\C-ct" 'caml-insert-try-form) - (define-key caml-mode-map "\C-cw" 'caml-insert-while-form) - (define-key caml-mode-map "\C-c`" 'caml-goto-phrase-error) - (define-key caml-mode-map "\C-c\C-a" 'caml-find-alternate-file) - (define-key caml-mode-map "\C-c\C-c" 'compile) - (define-key caml-mode-map "\C-c\C-e" 'caml-eval-phrase) - (define-key caml-mode-map "\C-c\C-[" 'caml-backward-to-less-indent) - (define-key caml-mode-map "\C-c\C-]" 'caml-forward-to-less-indent) - (define-key caml-mode-map "\C-c\C-q" 'caml-indent-phrase) - (define-key caml-mode-map "\C-c\C-r" 'caml-eval-region) - (define-key caml-mode-map "\C-c\C-s" 'caml-show-subshell) - (define-key caml-mode-map "\M-\C-h" 'caml-mark-phrase) - (define-key caml-mode-map "\M-\C-q" 'caml-indent-phrase) - (define-key caml-mode-map "\M-\C-x" 'caml-eval-phrase) - - (if (featurep 'xemacs) nil - (let ((map (make-sparse-keymap "Caml")) - (forms (make-sparse-keymap "Forms"))) - (define-key caml-mode-map "\C-c\C-d" 'caml-show-imenu) - (define-key caml-mode-map [menu-bar] (make-sparse-keymap)) - (define-key caml-mode-map [menu-bar caml] (cons "Caml" map)) - ;; caml-help - - (define-key map [open] '("Open add path" . ocaml-add-path )) - (define-key map [close] - '("Close module for help" . ocaml-close-module)) - (define-key map [open] '("Open module for help" . ocaml-open-module)) - (define-key map [help] '("Help for identifier" . caml-help)) - (define-key map [complete] '("Complete identifier" . caml-complete)) - (define-key map [separator-help] '("---")) - - ;; caml-types - (define-key map [show-type] - '("Show type at point" . caml-types-show-type )) - (define-key map [separator-types] '("---")) - - ;; others - (define-key map [camldebug] '("Call debugger..." . camldebug)) - (define-key map [run-caml] '("Start subshell..." . run-caml)) - (define-key map [compile] '("Compile..." . compile)) - (define-key map [switch-view] - '("Switch view" . caml-find-alternate-file)) - (define-key map [separator-format] '("--")) - (define-key map [forms] (cons "Forms" forms)) - (define-key map [show-imenu] '("Show index" . caml-show-imenu)) - (put 'caml-show-imenu 'menu-enable '(not caml-imenu-shown)) - (define-key map [show-subshell] '("Show subshell" . caml-show-subshell)) - (put 'caml-show-subshell 'menu-enable 'caml-shell-active) - (define-key map [eval-phrase] '("Eval phrase" . caml-eval-phrase)) - (put 'caml-eval-phrase 'menu-enable 'caml-shell-active) - (define-key map [indent-phrase] '("Indent phrase" . caml-indent-phrase)) - (define-key forms [while] - '("while .. do .. done" . caml-insert-while-form)) - (define-key forms [try] '("try .. with .." . caml-insert-try-form)) - (define-key forms [match] '("match .. with .." . caml-insert-match-form)) - (define-key forms [let] '("let .. in .." . caml-insert-let-form)) - (define-key forms [if] '("if .. then .. else .." . caml-insert-if-form)) - (define-key forms [begin] '("for .. do .. done" . caml-insert-for-form)) - (define-key forms [begin] '("begin .. end" . caml-insert-begin-form))))) - -(defvar caml-mode-xemacs-menu - (if (featurep 'xemacs) - '("Caml" - [ "Indent phrase" caml-indent-phrase :keys "C-M-q" ] - [ "Eval phrase" caml-eval-phrase - :active caml-shell-active :keys "C-M-x" ] - [ "Show subshell" caml-show-subshell caml-shell-active ] - ("Forms" - [ "while .. do .. done" caml-insert-while-form t] - [ "try .. with .." caml-insert-try-form t ] - [ "match .. with .." caml-insert-match-form t ] - [ "let .. in .." caml-insert-let-form t ] - [ "if .. then .. else .." caml-insert-if-form t ] - [ "for .. do .. done" caml-insert-for-form t ] - [ "begin .. end" caml-insert-begin-form t ]) - "---" - [ "Switch view" caml-find-alternate-file t ] - [ "Compile..." compile t ] - [ "Start subshell..." run-caml t ] - "---" - [ "Show type at point" caml-types-show-type t ] - "---" - [ "Complete identifier" caml-complete t ] - [ "Help for identifier" caml-help t ] - [ "Add path for documentation" ocaml-add-path t ] - [ "Open module for documentation" ocaml-open t ] - [ "Close module for documentation" ocaml-close t ] - )) - "Menu to add to the menubar when running Xemacs") - -(defvar caml-mode-syntax-table nil - "Syntax table in use in Caml mode buffers.") -(if caml-mode-syntax-table - () - (let ((n (if (featurep 'xemacs) "" "n"))) - (setq caml-mode-syntax-table (make-syntax-table)) - ; backslash is an escape sequence - (modify-syntax-entry ?\\ "\\" caml-mode-syntax-table) - ; ( is first character of comment start - (modify-syntax-entry ?\( (concat "()1" n) caml-mode-syntax-table) - ; * is second character of comment start, - ; and first character of comment end - (modify-syntax-entry ?* (concat ". 23" n) caml-mode-syntax-table) - ; ) is last character of comment end - (modify-syntax-entry ?\) ")(4" caml-mode-syntax-table) - ; backquote was a string-like delimiter (for character literals) - ; (modify-syntax-entry ?` "\"" caml-mode-syntax-table) - ; quote and underscore are part of words - (modify-syntax-entry ?' "w" caml-mode-syntax-table) - (modify-syntax-entry ?_ "w" caml-mode-syntax-table) - ; ISO-latin accented letters and EUC kanjis are part of words - (let ((i 160)) - (while (< i 256) - (modify-syntax-entry i "w" caml-mode-syntax-table) - (setq i (1+ i)))))) - -(defvar caml-mode-abbrev-table nil - "Abbrev table used for Caml mode buffers.") -(if caml-mode-abbrev-table nil - (define-abbrev-table 'caml-mode-abbrev-table - (mapcar (lambda (keyword) - `(,keyword ,keyword caml-abbrev-hook nil t)) - '("and" "do" "done" "else" "end" "in" "then" "with")))) - -;; Other internal variables - -(defvar caml-last-noncomment-pos nil - "Caches last buffer position determined not inside a caml comment.") -(make-variable-buffer-local 'caml-last-noncomment-pos) - -;;last-noncomment-pos can be a simple position, because we nil it -;;anyway whenever buffer changes upstream. last-comment-start and -end -;;have to be markers, because we preserve them when the changes' end -;;doesn't overlap with the comment's start. - -(defvar caml-last-comment-start nil - "A marker caching last determined caml comment start.") -(make-variable-buffer-local 'caml-last-comment-start) - -(defvar caml-last-comment-end nil - "A marker caching last determined caml comment end.") -(make-variable-buffer-local 'caml-last-comment-end) - -(make-variable-buffer-local 'before-change-function) - -(defvar caml-imenu-shown nil - "True if we have computed definition list.") -(make-variable-buffer-local 'caml-imenu-shown) - -(defconst caml-imenu-search-regexp - (concat "\\\\|" - "^[ \t]*\\(let\\|class\\|type\\|m\\(odule\\|ethod\\)" - "\\|functor\\|and\\|val\\)[ \t]+" - "\\(\\('[a-zA-Z0-9]+\\|([^)]+)" - "\\|mutable\\|private\\|rec\\|type\\)[ \t]+\\)?" - "\\([a-zA-Z][a-zA-Z0-9_']*\\)")) - -;;; The major mode -(eval-when-compile - (if (featurep 'xemacs) nil - (require 'imenu))) - -;; -(defvar caml-mode-hook nil - "Hook for caml-mode") - -(defun caml-mode () - "Major mode for editing OCaml code. - -\\{caml-mode-map}" - - (interactive) - (kill-all-local-variables) - (setq major-mode 'caml-mode) - (setq mode-name "caml") - (use-local-map caml-mode-map) - (set-syntax-table caml-mode-syntax-table) - (setq local-abbrev-table caml-mode-abbrev-table) - (make-local-variable 'paragraph-start) - (setq paragraph-start (concat "^$\\|" page-delimiter)) - (make-local-variable 'paragraph-separate) - (setq paragraph-separate paragraph-start) - (make-local-variable 'paragraph-ignore-fill-prefix) - (setq paragraph-ignore-fill-prefix t) - (make-local-variable 'require-final-newline) - (setq require-final-newline t) - (make-local-variable 'comment-start) - (setq comment-start "(*") - (make-local-variable 'comment-end) - (setq comment-end "*)") - (make-local-variable 'comment-column) - (setq comment-column 40) - (make-local-variable 'comment-start-skip) - (setq comment-start-skip "(\\*+ *") - (make-local-variable 'parse-sexp-ignore-comments) - (setq parse-sexp-ignore-comments nil) - (make-local-variable 'indent-line-function) - (setq indent-line-function 'caml-indent-command) - ;itz Fri Sep 25 13:23:49 PDT 1998 - (make-local-variable 'add-log-current-defun-function) - (setq add-log-current-defun-function 'caml-current-defun) - ;itz 03-25-96 - (setq before-change-function 'caml-before-change-function) - (setq caml-last-noncomment-pos nil) - (setq caml-last-comment-start (make-marker)) - (setq caml-last-comment-end (make-marker)) - ;garrigue 27-11-96 - (setq case-fold-search nil) - ;garrigue july 97 - (if (featurep 'xemacs) - (if (and (featurep 'menubar) - current-menubar) - (progn - ;; make a local copy of the menubar, so our modes don't - ;; change the global menubar - (set-buffer-menubar current-menubar) - (add-submenu nil caml-mode-xemacs-menu))) - ;imenu support (not for Xemacs) - (make-local-variable 'imenu-create-index-function) - (setq imenu-create-index-function 'caml-create-index-function) - (make-local-variable 'imenu-generic-expression) - (setq imenu-generic-expression caml-imenu-search-regexp) - (if (and caml-imenu-enable (< (buffer-size) 10000)) - (caml-show-imenu))) - (run-hooks 'caml-mode-hook)) - - -;; Disabled because it assumes make and does not play well with ocamlbuild. -;; See PR#4469 for details. - -;; (defun caml-set-compile-command () -;; "Hook to set compile-command locally, unless there is a Makefile or -;; a _build directory or a _tags file in the current directory." -;; (interactive) -;; (unless (or (null buffer-file-name) -;; (file-exists-p "makefile") -;; (file-exists-p "Makefile") -;; (file-exists-p "_build") -;; (file-exists-p "_tags")) -;; (let* ((filename (file-name-nondirectory buffer-file-name)) -;; (basename (file-name-sans-extension filename)) -;; (command nil)) -;; (cond -;; ((string-match ".*\\.mli\$" filename) -;; (setq command "ocamlc -c")) -;; ((string-match ".*\\.ml\$" filename) -;; (setq command "ocamlc -c") ; (concat "ocamlc -o " basename) -;; ) -;; ((string-match ".*\\.mll\$" filename) -;; (setq command "ocamllex")) -;; ((string-match ".*\\.mll\$" filename) -;; (setq command "ocamlyacc")) -;; ) -;; (if command -;; (progn -;; (make-local-variable 'compile-command) -;; (setq compile-command (concat command " " filename)))) -;; ))) - -;; (add-hook 'caml-mode-hook 'caml-set-compile-command) - - -;;; Auxiliary function. Garrigue 96-11-01. - -(defun caml-find-alternate-file () - (interactive) - (let ((name (buffer-file-name))) - (if (string-match "^\\(.*\\)\\.\\(ml\\|mli\\)$" name) - (find-file - (concat - (caml-match-string 1 name) - (if (string= "ml" (caml-match-string 2 name)) ".mli" ".ml")))))) - -;;; subshell support - -(defun caml-eval-region (start end) - "Send the current region to the inferior OCaml process." - (interactive"r") - (require 'inf-caml) - (inferior-caml-eval-region start end)) - -;; old version ---to be deleted later -; -; (defun caml-eval-phrase () -; "Send the current OCaml phrase to the inferior Caml process." -; (interactive) -; (save-excursion -; (let ((bounds (caml-mark-phrase))) -; (inferior-caml-eval-region (car bounds) (cdr bounds))))) - -(defun caml-eval-phrase (arg &optional min max) - "Send the phrase containing the point to the CAML process. -With prefix-arg send as many phrases as its numeric value, -If an error occurs during evaluation, stop at this phrase and -report the error. - -Return nil if noerror and position of error if any. - -If arg's numeric value is zero or negative, evaluate the current phrase -or as many as prefix arg, ignoring evaluation errors. -This allows to jump other erroneous phrases. - -Optional arguments min max defines a region within which the phrase -should lies." - (interactive "p") - (require 'inf-caml) - (inferior-caml-eval-phrase arg min max)) - -(defun caml-eval-buffer (arg) - "Evaluate the buffer from the beginning to the phrase under the point. -With prefix arg, evaluate past the whole buffer, no stopping at -the current point." - (interactive "p") - (let ((here (point)) err) - (goto-char (point-min)) - (setq err - (caml-eval-phrase 500 (point-min) (if arg (point-max) here))) - (if err (set-mark err)) - (goto-char here))) - -(defun caml-show-subshell () - (interactive) - (require 'inf-caml) - (inferior-caml-show-subshell)) - - -;;; Imenu support -(defun caml-show-imenu () - (interactive) - (require 'imenu) - (switch-to-buffer (current-buffer)) - (imenu-add-to-menubar "Defs") - (setq caml-imenu-shown t)) - -(defun caml-prev-index-position-function () - (let (found data) - (while (and (setq found - (re-search-backward caml-imenu-search-regexp nil 'move)) - (progn (setq data (match-data)) t) - (or (caml-in-literal-p) - (caml-in-comment-p) - (if (looking-at "in") (caml-find-in-match))))) - (set-match-data data) - found)) -(defun caml-create-index-function () - (let (value-alist - type-alist - class-alist - method-alist - module-alist - and-alist - all-alist - menu-alist - (prev-pos (point-max)) - index) - (goto-char prev-pos) - (imenu-progress-message prev-pos 0 t) - ;; collect definitions - (while (caml-prev-index-position-function) - (setq index (cons (caml-match-string 5) (point))) - (imenu-progress-message prev-pos nil t) - (setq all-alist (cons index all-alist)) - (cond - ((looking-at "[ \t]*and") - (setq and-alist (cons index and-alist))) - ((looking-at "[ \t]*let") - (setq value-alist (cons index (append and-alist value-alist))) - (setq and-alist nil)) - ((looking-at "[ \t]*type") - (setq type-alist (cons index (append and-alist type-alist))) - (setq and-alist nil)) - ((looking-at "[ \t]*class") - (setq class-alist (cons index (append and-alist class-alist))) - (setq and-alist nil)) - ((looking-at "[ \t]*val") - (setq value-alist (cons index value-alist))) - ((looking-at "[ \t]*\\(module\\|functor\\)") - (setq module-alist (cons index module-alist))) - ((looking-at "[ \t]*method") - (setq method-alist (cons index method-alist))))) - ;; build menu - (mapc - (lambda (pair) - (if (symbol-value (cdr pair)) - (setq menu-alist - (cons - (cons (car pair) - (sort (symbol-value (cdr pair)) 'imenu--sort-by-name)) - menu-alist)))) - '(("Values" . value-alist) - ("Types" . type-alist) - ("Modules" . module-alist) - ("Methods" . method-alist) - ("Classes" . class-alist))) - (if all-alist (setq menu-alist (cons (cons "Index" all-alist) menu-alist))) - (imenu-progress-message prev-pos 100 t) - menu-alist)) - -;;; Indentation stuff - -(defun caml-in-indentation () - "Tests whether all characters between beginning of line and point -are blanks." - (save-excursion - (skip-chars-backward " \t") - (bolp))) - -;;; The command -;;; Sorry, I didn't like the previous behaviour... Garrigue 96/11/01 - -(defun caml-indent-command (&optional p) - "Indent the current line in Caml mode. - -Compute new indentation based on caml syntax. If prefixed, indent -the line all the way to where point is." - - (interactive "*p") - (cond - ((and p (> p 1)) (indent-line-to (current-column))) - ((caml-in-indentation) (indent-line-to (caml-compute-final-indent))) - (t (save-excursion - (indent-line-to - (caml-compute-final-indent)))))) - -(defun caml-unindent-command () - - "Decrease indentation by one level in Caml mode. - -Works only if the point is at the beginning of an indented line -\(i.e. all characters between beginning of line and point are -blanks\). Does nothing otherwise. The unindent size is given by the -variable caml-mode-indentation." - - (interactive "*") - (let* ((begline - (save-excursion - (beginning-of-line) - (point))) - (current-offset - (- (point) begline))) - (if (and (>= current-offset caml-mode-indentation) - (caml-in-indentation)) - (backward-delete-char-untabify caml-mode-indentation)))) - -;;; -;;; Error processing -;;; - -;; Error positions are given in bytes, not in characters -;; This function switches to monobyte mode - -(if (not (fboundp 'char-bytes)) - (defalias 'forward-byte 'forward-char) - (defun caml-char-bytes (ch) - (let ((l (char-bytes ch))) - (if (> l 1) (- l 1) l))) - (defun forward-byte (count) - (if (> count 0) - (while (> count 0) - (let ((char (char-after))) - (if (null char) - (setq count 0) - (setq count (- count (caml-char-bytes (char-after)))) - (forward-char)))) - (while (< count 0) - (let ((char (char-after))) - (if (null char) - (setq count 0) - (setq count (+ count (caml-char-bytes (char-before)))) - (backward-char)))) - ))) - -(require 'compile) - -;; In Emacs 19, the regexps in compilation-error-regexp-alist do not -;; match the error messages when the language is not English. -;; Hence we add a regexp. -;; FIXME do we (still) have i18n of error messages ??? - -(defconst caml-error-regexp - "^[ A-\377]+ \"\\([^\"\n]+\\)\", [A-\377]+ \\([0-9]+\\)[-,:]" - "Regular expression matching the error messages produced by camlc.") - -;; Newer emacs versions support line/char ranges -;; We will adapt OCaml to output error messages in a compatible format. -;; In the meantime we add new formats here in addition to the old one. -(defconst caml-error-regexp-newstyle - (concat "^[ A-\377]+ \"\\([^\"\n]+\\)\", line \\([0-9]+\\)," - "char \\([0-9]+\\) to line \\([0-9]+\\), char \\([0-9]+\\):") - "Regular expression matching the error messages produced by ocamlc/ocamlopt.") - -(defconst caml-error-regexp-new-newstyle - (concat "^[ A-\377]+ \"\\([^\"\n]+\\)\", line \\([0-9]+\\), " - "characters \\([0-9]+\\)-\\([0-9]+\\):") - "Regular expression matching the error messages produced by ocamlc/ocamlopt.") - - -(if (boundp 'compilation-error-regexp-alist) - (progn - (or (assoc caml-error-regexp - compilation-error-regexp-alist) - (setq compilation-error-regexp-alist - (cons (list caml-error-regexp 1 2) - compilation-error-regexp-alist))) - (or (assoc caml-error-regexp-newstyle - compilation-error-regexp-alist) - (setq compilation-error-regexp-alist - (cons (list caml-error-regexp-newstyle 1 '(2 . 4) '(3 . 5)) - compilation-error-regexp-alist))) - (or (assoc caml-error-regexp-new-newstyle - compilation-error-regexp-alist) - (setq compilation-error-regexp-alist - (cons (list caml-error-regexp-new-newstyle 1 2 '(3 . 4)) - compilation-error-regexp-alist))))) - -;; A regexp to extract the range info - -(defconst caml-error-chars-regexp - ".*, .*, [A-\377]+ \\([0-9]+\\)-\\([0-9]+\\):?" - "Regular expression extracting the character numbers -from an error message produced by camlc.") - -;; Wrapper around next-error. - -(defvar caml-error-overlay nil) -(defvar caml-next-error-skip-warnings-flag nil) - -(if (fboundp 'string-to-number) - (defalias 'caml-string-to-int 'string-to-number) - (defalias 'caml-string-to-int 'string-to-int)) - -;;itz 04-21-96 somebody didn't get the documentation for next-error -;;right. When the optional argument is a number n, it should move -;;forward n errors, not reparse. - -;itz 04-21-96 instead of defining a new function, use defadvice -;that way we get our effect even when we do \C-x` in compilation buffer - -(defadvice next-error (after caml-next-error activate) - "Reads the extra positional information provided by the OCaml compiler. - -Puts the point and the mark exactly around the erroneous program -fragment. The erroneous fragment is also temporarily highlighted if -possible." - - (if (eq major-mode 'caml-mode) - (let (skip bol beg end) - (save-excursion - (with-current-buffer - (if (boundp 'compilation-last-buffer) - compilation-last-buffer ;Emacs 19 - "*compilation*") ;Emacs 18 - (save-excursion - (goto-char (window-point (get-buffer-window (current-buffer)))) - (if (looking-at caml-error-chars-regexp) - (setq beg - (caml-string-to-int - (buffer-substring (match-beginning 1) (match-end 1))) - end - (caml-string-to-int - (buffer-substring (match-beginning 2) (match-end 2))))) - (forward-line 1) - (beginning-of-line) - (if (and (looking-at "Warning") - caml-next-error-skip-warnings-flag) - (setq skip 't))))) - (cond - (skip (next-error)) - (beg - (setq end (- end beg)) - (beginning-of-line) - (forward-byte beg) - (setq beg (point)) - (forward-byte end) - (setq end (point)) - (goto-char beg) - (push-mark end t) - (cond ((fboundp 'make-overlay) - (if caml-error-overlay () - (setq caml-error-overlay (make-overlay 1 1)) - (overlay-put caml-error-overlay 'face 'region)) - (unwind-protect - (progn - (move-overlay caml-error-overlay - beg end (current-buffer)) - (sit-for 60)) - (delete-overlay caml-error-overlay))))))))) - -(defun caml-next-error-skip-warnings (&rest args) - (let ((old-flag caml-next-error-skip-warnings-flag)) - (unwind-protect - (progn (setq caml-next-error-skip-warnings-flag 't) - (apply 'next-error args)) - (setq caml-next-error-skip-warnings-flag old-flag)))) - - -;; Usual match-string doesn't work properly with font-lock-mode -;; on some emacs. - -(defun caml-match-string (num &optional string) - - "Return string of text matched by last search, without properties. - -NUM specifies which parenthesized expression in the last regexp. -Value is nil if NUMth pair didn't match, or there were less than NUM -pairs. Zero means the entire text matched by the whole regexp or -whole string." - - (let* ((data (match-data)) - (begin (nth (* 2 num) data)) - (end (nth (1+ (* 2 num)) data))) - (if string (substring string begin end) - (buffer-substring-no-properties begin end)))) - -;; itz Thu Sep 24 19:02:42 PDT 1998 this is to have some level of -;; comfort when sending phrases to the toplevel and getting errors. -(defun caml-goto-phrase-error () - "Find the error location in current OCaml phrase." - (interactive) - (require 'inf-caml) - (let ((bounds (save-excursion (caml-mark-phrase)))) - (inferior-caml-goto-error (car bounds) (cdr bounds)))) - -;;; Phrases - -;itz the heuristics used to see if we're `between two phrases' -;didn't seem right to me. - -(defconst caml-phrase-start-keywords - (concat "\\<\\(class\\|ex\\(ternal\\|ception\\)\\|functor" - "\\|let\\|module\\|open\\|type\\|val\\)\\>") - "Keywords starting phrases in files") - -;; a phrase starts when a toplevel keyword is at the beginning of a line -(defun caml-at-phrase-start-p () - (and (bolp) - (or (looking-at "#") - (looking-at caml-phrase-start-keywords)))) - -(defun caml-skip-comments-forward () - (skip-chars-forward " \n\t") - (while (or (looking-at comment-start-skip) (caml-in-comment-p)) - (if (= (following-char) ?\)) (forward-char) - (search-forward comment-end)) - (skip-chars-forward " \n\t"))) - -(defun caml-skip-comments-backward () - (skip-chars-backward " \n\t") - (while (and (eq (preceding-char) ?\)) (eq (char-after (- (point) 2)) ?*)) - (backward-char) - (while (caml-in-comment-p) (search-backward comment-start)) - (skip-chars-backward " \n\t"))) - -(defconst caml-phrase-sep-keywords (concat ";;\\|" caml-phrase-start-keywords)) - -(defun caml-find-phrase (&optional min-pos max-pos) - "Find the CAML phrase containing the point. -Return the position of the beginning of the phrase, and move point -to the end. -" - (interactive) - (if (not min-pos) (setq min-pos (point-min))) - (if (not max-pos) (setq max-pos (point-max))) - (let (beg end use-semi kwop) - ;(caml-skip-comments-backward) - (cond - ; shall we have special processing for semicolons? - ;((and (eq (char-before (- (point) 1)) ?\;) (eq (char-before) ?\;)) - ; (forward-char) - ; (caml-skip-comments-forward) - ; (setq beg (point)) - ; (while (and (search-forward ";;" max-pos 'move) - ; (or (caml-in-comment-p) (caml-in-literal-p))))) - (t - (caml-skip-comments-forward) - (if (caml-at-phrase-start-p) (forward-char)) - (while (and (cond - ((re-search-forward caml-phrase-sep-keywords max-pos 'move) - (goto-char (match-beginning 0)) t)) - (or (not (or (bolp) (looking-at ";;"))) - (caml-in-comment-p) - (caml-in-literal-p))) - (forward-char)) - (setq end (+ (point) (if (looking-at ";;") 2 0))) - (while (and - (setq kwop (caml-find-kwop caml-phrase-sep-keywords min-pos)) - (not (string= kwop ";;")) - (not (bolp)))) - (if (string= kwop ";;") (forward-char 2)) - (if (not kwop) (goto-char min-pos)) - (caml-skip-comments-forward) - (setq beg (point)) - (if (>= beg end) (error "no phrase before point")) - (goto-char end))) - (caml-skip-comments-forward) - beg)) - -(defun caml-mark-phrase (&optional min-pos max-pos) - "Put mark at end of this OCaml phrase, point at beginning. -" - (interactive) - (let* ((beg (caml-find-phrase min-pos max-pos)) (end (point))) - (push-mark) - (goto-char beg) - (cons beg end))) - -;;itz Fri Sep 25 12:58:13 PDT 1998 support for adding change-log entries -(defun caml-current-defun () - (save-excursion - (caml-mark-phrase) - (if (not (looking-at caml-phrase-start-keywords)) nil - (re-search-forward caml-phrase-start-keywords) - (let ((done nil)) - (while (not done) - (cond - ((looking-at "\\s ") - (skip-syntax-forward " ")) - ((char-equal (following-char) ?\( ) - (forward-sexp 1)) - ((char-equal (following-char) ?') - (skip-syntax-forward "w_")) - (t (setq done t))))) - (re-search-forward "\\(\\sw\\|\\s_\\)+") - (match-string 0)))) - -(defun caml-overlap (b1 e1 b2 e2) - (<= (max b1 b2) (min e1 e2))) - -;this clears the last comment cache if necessary -(defun caml-before-change-function (begin end) - (if (and caml-last-noncomment-pos - (> caml-last-noncomment-pos begin)) - (setq caml-last-noncomment-pos nil)) - (if (and (marker-position caml-last-comment-start) - (marker-position caml-last-comment-end) - (caml-overlap begin end - caml-last-comment-start - caml-last-comment-end)) - (prog2 - (set-marker caml-last-comment-start nil) - (set-marker caml-last-comment-end nil))) - (let ((orig-function (default-value 'before-change-function))) - (if orig-function (funcall orig-function begin end)))) - -(defun caml-in-literal-p () - "Returns non-nil if point is inside a caml literal." - (let* ((start-literal (concat "[\"" caml-quote-char "]")) - (char-literal - (concat "\\([^\\]\\|\\\\\\.\\|\\\\[0-9][0-9][0-9]\\)" - caml-quote-char)) - (pos (point)) - (eol (progn (end-of-line 1) (point))) - state in-str) - (beginning-of-line 1) - (while (and (not state) - (re-search-forward start-literal eol t) - (<= (point) pos)) - (cond - ((string= (caml-match-string 0) "\"") - (setq in-str t) - (while (and in-str (not state) - (re-search-forward "\"\\|\\\\\"" eol t)) - (if (> (point) pos) (setq state t)) - (if (string= (caml-match-string 0) "\"") (setq in-str nil))) - (if in-str (setq state t))) - ((looking-at char-literal) - (if (and (>= pos (match-beginning 0)) (< pos (match-end 0))) - (setq state t) - (goto-char (match-end 0)))))) - (goto-char pos) - state)) - -(defun caml-forward-comment () - "Skip one (eventually nested) comment." - (let ((count 1) match) - (while (> count 0) - (if (not (re-search-forward "(\\*\\|\\*)" nil 'move)) - (setq count -1) - (setq match (caml-match-string 0)) - (cond - ((caml-in-literal-p) - nil) - ((string= match comment-start) - (setq count (1+ count))) - (t - (setq count (1- count)))))) - (= count 0))) - -(defun caml-backward-comment () - "Skip one (eventually nested) comment." - (let ((count 1) match) - (while (> count 0) - (if (not (re-search-backward "(\\*\\|\\*)" nil 'move)) - (setq count -1) - (setq match (caml-match-string 0)) - (cond - ((caml-in-literal-p) - nil) - ((string= match comment-start) - (setq count (1- count))) - (t - (setq count (1+ count)))))) - (= count 0))) - -(defun caml-in-comment-p () - "Returns non-nil if point is inside a caml comment. -Returns nil for the parenthesis opening a comment." - ;;we look for comments differently than literals. there are two - ;;reasons for this. first, caml has nested comments and it is not so - ;;clear that parse-partial-sexp supports them; second, if proper - ;;style is used, literals are never split across lines, so we don't - ;;have to worry about bogus phrase breaks inside literals, while we - ;;have to account for that possibility in comments. - (if caml-last-comment-start - (save-excursion - (let* ((cached-pos caml-last-noncomment-pos) - (cached-begin (marker-position caml-last-comment-start)) - (cached-end (marker-position caml-last-comment-end))) - (cond - ((and cached-begin cached-end - (< cached-begin (point)) (< (point) cached-end)) t) - ((and cached-pos (= cached-pos (point))) nil) - ((and cached-pos (> cached-pos (point)) - (< (abs (- cached-pos (point))) caml-lookback-limit)) - (let (end found (here (point))) - ; go back to somewhere sure - (goto-char cached-pos) - (while (> (point) here) - ; look for the end of a comment - (while (and (if (search-backward comment-end (1- here) 'move) - (setq end (match-end 0)) - (setq end nil)) - (caml-in-literal-p))) - (if end (setq found (caml-backward-comment)))) - (if (and found (= (point) here)) (setq end nil)) - (if (not end) - (setq caml-last-noncomment-pos here) - (set-marker caml-last-comment-start (point)) - (set-marker caml-last-comment-end end)) - end)) - (t - (let (begin found (here (point))) - ;; go back to somewhere sure (or far enough) - (goto-char - (if cached-pos cached-pos (- (point) caml-lookback-limit))) - (while (< (point) here) - ;; look for the beginning of a comment - (while (and (if (search-forward comment-start (1+ here) 'move) - (setq begin (match-beginning 0)) - (setq begin nil)) - (caml-in-literal-p))) - (if begin (setq found (caml-forward-comment)))) - (if (and found (= (point) here)) (setq begin nil)) - (if (not begin) - (setq caml-last-noncomment-pos here) - (set-marker caml-last-comment-start begin) - (set-marker caml-last-comment-end (point))) - begin))))))) - -;; Various constants and regexps - -(defconst caml-before-expr-prefix - (concat "\\<\\(asr\\|begin\\|class\\|do\\(wnto\\)?\\|else" - "\\|i\\(f\\|n\\(herit\\|itializer\\)?\\)" - "\\|f\\(or\\|un\\(ct\\(ion\\|or\\)\\)?\\)" - "\\|l\\(and\\|or\\|s[lr]\\|xor\\)\\|m\\(atch\\|od\\)" - "\\|o[fr]\\|parser\\|s\\(ig\\|truct\\)\\|t\\(hen\\|o\\|ry\\)" - "\\|w\\(h\\(en\\|ile\\)\\|ith\\)\\)\\>\\|:begin\\>" - "\\|[=<>@^|&+-*/$%][!$%*+-./:<=>?@^|~]*\\|:[:=]\\|[[({,;]") - - "Keywords that may appear immediately before an expression. -Used to distinguish it from toplevel let construct.") - -(defconst caml-matching-kw-regexp - (concat - "\\<\\(and\\|do\\(ne\\|wnto\\)?\\|e\\(lse\\|nd\\)\\|in\\|t\\(hen\\|o\\)" - "\\|with\\)\\>\\|[^[|]|") - "Regexp used in caml mode for skipping back over nested blocks.") - -(defconst caml-matching-kw-alist - '(("|" . caml-find-pipe-match) - (";" . caml-find-semi-match) - ("," . caml-find-comma-match) - ("end" . caml-find-end-match) - ("done" . caml-find-done-match) - ("in" . caml-find-in-match) - ("with" . caml-find-with-match) - ("else" . caml-find-else-match) - ("then" . caml-find-then-match) - ("to" . caml-find-done-match) - ("downto" . caml-find-done-match) - ("do" . caml-find-done-match) - ("and" . caml-find-and-match)) - - "Association list used in caml mode for skipping back over nested blocks.") - -(defconst caml-kwop-regexps (make-vector 9 nil) - "Array of regexps representing caml keywords of different priorities.") - -(defun caml-in-shebang-line () - (save-excursion - (beginning-of-line) - (and (= 1 (point)) (looking-at "#!")))) - -(defun caml-in-expr-p () - (let ((pos (point)) (in-expr t)) - (caml-find-kwop - (concat caml-before-expr-prefix "\\|" - caml-matching-kw-regexp "\\|" - (aref caml-kwop-regexps caml-max-indent-priority))) - (cond - ; special case for #! at beginning of file - ((caml-in-shebang-line) (setq in-expr nil)) - ; special case for ;; - ((and (> (point) 1) (= (preceding-char) ?\;) (= (following-char) ?\;)) - (setq in-expr nil)) - ((looking-at caml-before-expr-prefix) - (if (not (looking-at "(\\*")) (goto-char (match-end 0))) - (skip-chars-forward " \t\n") - (while (looking-at "(\\*") - (forward-char) - (caml-forward-comment) - (skip-chars-forward " \t\n")) - (if (<= pos (point)) (setq in-expr nil)))) - (goto-char pos) - in-expr)) - -(defun caml-at-sexp-close-p () - (or (char-equal ?\) (following-char)) - (char-equal ?\] (following-char)) - (char-equal ?\} (following-char)))) - -(defun caml-find-kwop (kwop-regexp &optional min-pos) - "Look back for a caml keyword or operator matching KWOP-REGEXP. -Second optional argument MIN-POS bounds the search. - -Ignore occurrences inside literals. If found, return a list of two -values: the actual text of the keyword or operator, and a boolean -indicating whether the keyword was one we looked for explicitly -{non-nil}, or on the other hand one of the block-terminating -keywords." - - (let ((start-literal (concat "[\"" caml-quote-char "]")) - found kwop) - (while (and (> (point) 1) (not found) - (re-search-backward kwop-regexp min-pos 'move)) - (setq kwop (caml-match-string 0)) - (cond - ((looking-at "(\\*") - (if (> (point) 1) (backward-char))) - ((caml-in-comment-p) - (search-backward "(" min-pos 'move)) - ((looking-at start-literal)) - ((caml-in-literal-p) - (re-search-backward start-literal min-pos 'move)) ;ugly hack - ((setq found t)))) - (if found - (if (not (string-match "\\`[^|[]|[^]|]?\\'" kwop)) ;arrrrgh!! - kwop - (forward-char 1) "|") nil))) - -; Association list of indentation values based on governing keywords. -; -;Each element is of the form (KEYWORD OP-TYPE PRIO INDENT). OP-TYPE is -;non-nil for operator-type nodes, which affect indentation in a -;different way from keywords: subsequent lines are indented to the -;actual occurrence of an operator, but relative to the indentation of -;the line where the governing keyword occurs. - -(defconst caml-no-indent 0) - -(defconst caml-kwop-alist - '(("begin" nil 6 caml-begin-indent) - (":begin" nil 6 caml-begin-indent) ; hack - ("class" nil 0 caml-class-indent) - ("constraint" nil 0 caml-val-indent) - ("sig" nil 1 caml-sig-indent) - ("struct" nil 1 caml-struct-indent) - ("exception" nil 0 caml-exception-indent) - ("for" nil 6 caml-for-indent) - ("fun" nil 3 caml-fun-indent) - ("function" nil 3 caml-function-indent) - ("if" nil 6 caml-if-indent) - ("if-else" nil 6 caml-if-else-indent) - ("include" nil 0 caml-include-indent) - ("inherit" nil 0 caml-inherit-indent) - ("initializer" nil 0 caml-initializer-indent) - ("let" nil 6 caml-let-indent) - ("let-in" nil 6 caml-let-in-indent) - ("match" nil 6 caml-match-indent) - ("method" nil 0 caml-method-indent) - ("module" nil 0 caml-module-indent) - ("object" nil 6 caml-object-indent) - ("of" nil 7 caml-of-indent) - ("open" nil 0 caml-no-indent) - ("parser" nil 3 caml-parser-indent) - ("try" nil 6 caml-try-indent) - ("type" nil 0 caml-type-indent) - ("val" nil 0 caml-val-indent) - ("when" nil 2 caml-if-indent) - ("while" nil 6 caml-while-indent) - ("::" t 5 caml-::-indent) - ("@" t 4 caml-@-indent) - ("^" t 4 caml-@-indent) - (":=" nil 3 caml-:=-indent) - ("<-" nil 3 caml-<--indent) - ("->" nil 2 caml-->-indent) - ("\[" t 8 caml-lb-indent) - ("{" t 8 caml-lc-indent) - ("\(" t 8 caml-lp-indent) - ("|" nil 2 caml-no-indent) - (";;" nil 0 caml-no-indent)) -; if-else and let-in are not keywords but idioms -; "|" is not in the regexps -; all these 3 values correspond to hard-coded names - -"Association list of indentation values based on governing keywords. - -Each element is of the form (KEYWORD OP-TYPE PRIO INDENT). OP-TYPE is -non-nil for operator-type nodes, which affect indentation in a -different way from keywords: subsequent lines are indented to the -actual occurrence of an operator, but relative to the indentation of -the line where the governing keyword occurs.") - -;;Originally, we had caml-kwop-regexp create these at runtime, from an -;;additional field in caml-kwop-alist. That proved way too slow, -;;although I still can't understand why. itz - -(aset caml-kwop-regexps 0 - (concat - "\\<\\(begin\\|object\\|for\\|s\\(ig\\|truct\\)\\|while\\)\\>" - "\\|:begin\\>\\|[[({]\\|;;")) -(aset caml-kwop-regexps 1 - (concat (aref caml-kwop-regexps 0) "\\|\\<\\(class\\|module\\)\\>")) -(aset caml-kwop-regexps 2 - (concat - (aref caml-kwop-regexps 1) - "\\|\\<\\(fun\\(ction\\)?\\|initializer\\|let\\|m\\(atch\\|ethod\\)" - "\\|parser\\|try\\|val\\)\\>\\|->")) -(aset caml-kwop-regexps 3 - (concat (aref caml-kwop-regexps 2) "\\|\\")) -(aset caml-kwop-regexps 4 - (concat (aref caml-kwop-regexps 3) "\\|:=\\|<-")) -(aset caml-kwop-regexps 5 - (concat (aref caml-kwop-regexps 4) "\\|@")) -(aset caml-kwop-regexps 6 - (concat (aref caml-kwop-regexps 5) "\\|::\\|\\^")) -(aset caml-kwop-regexps 7 - (concat - (aref caml-kwop-regexps 0) - "\\|\\<\\(constraint\\|exception\\|in\\(herit\\|clude\\)" - "\\|o\\(f\\|pen\\)\\|type\\|val\\)\\>")) -(aset caml-kwop-regexps 8 - (concat (aref caml-kwop-regexps 6) - "\\|\\<\\(constraint\\|exception\\|in\\(herit\\|clude\\)" - "\\|o\\(f\\|pen\\)\\|type\\)\\>")) - -(defun caml-find-done-match () - (let ((unbalanced 1) (kwop t)) - (while (and (not (= 0 unbalanced)) kwop) - (setq kwop (caml-find-kwop "\\<\\(done\\|for\\|while\\)\\>")) - (cond - ((not kwop)) - ((string= kwop "done") (setq unbalanced (1+ unbalanced))) - (t (setq unbalanced (1- unbalanced))))) - kwop)) - -(defun caml-find-end-match () - (let ((unbalanced 1) (kwop t)) - (while (and (not (= 0 unbalanced)) kwop) - (setq kwop - (caml-find-kwop - "\\<\\(end\\|begin\\|object\\|s\\(ig\\|truct\\)\\)\\>\\|:begin\\>\\|;;")) - (cond - ((not kwop)) - ((string= kwop ";;") (setq kwop nil) (forward-line 1)) - ((string= kwop "end") (setq unbalanced (1+ unbalanced))) - ( t (setq unbalanced (1- unbalanced))))) - (if (string= kwop ":begin") "begin" - kwop))) - -(defun caml-find-in-match () - (let ((unbalanced 1) (kwop t)) - (while (and (not (= 0 unbalanced)) kwop) - (setq kwop (caml-find-kwop "\\<\\(in\\|let\\|end\\)\\>")) - (cond - ((not kwop)) - ((string= kwop "end") (caml-find-end-match)) - ((string= kwop "in") (setq unbalanced (1+ unbalanced))) - (t (setq unbalanced (1- unbalanced))))) - kwop)) - -(defun caml-find-with-match () - (let ((unbalanced 1) (kwop t)) - (while (and (not (= 0 unbalanced)) kwop) - (setq kwop - (caml-find-kwop - "\\<\\(with\\|try\\|m\\(atch\\|odule\\)\\|functor\\)\\>\\|[{}()]")) - (cond - ((not kwop)) - ((caml-at-sexp-close-p) - (caml-find-paren-match (following-char))) - ((string= kwop "with") - (setq unbalanced (1+ unbalanced))) - ((or (string= kwop "module") - (string= kwop "functor") - (string= kwop "{") - (string= kwop "(")) - (setq unbalanced 0)) - (t (setq unbalanced (1- unbalanced))))) - kwop)) - -(defun caml-find-paren-match (close) - (let ((unbalanced 1) - (regexp (cond ((= close ?\)) "[()]") - ((= close ?\]) "[][]") - ((= close ?\}) "[{}]")))) - (while (and (> unbalanced 0) - (caml-find-kwop regexp)) - (if (= close (following-char)) - (setq unbalanced (1+ unbalanced)) - (setq unbalanced (1- unbalanced)))))) - -(defun caml-find-then-match (&optional from-else) - (let ((bol (if from-else - (save-excursion - (progn (beginning-of-line) (point))))) - kwop done matching-fun) - (while (not done) - (setq kwop - (caml-find-kwop - "\\<\\(e\\(nd\\|lse\\)\\|done\\|then\\|if\\|with\\)\\>\\|[])};]")) - (cond - ((not kwop) (setq done t)) - ((caml-at-sexp-close-p) - (caml-find-paren-match (following-char))) - ((string= kwop "if") (setq done t)) - ((string= kwop "then") - (if (not from-else) (setq kwop (caml-find-then-match)))) - ((setq matching-fun (cdr-safe (assoc kwop caml-matching-kw-alist))) - (setq kwop (funcall matching-fun))))) - (if (and bol (>= (point) bol)) - "if-else" - kwop))) - -(defun caml-find-pipe-match () - (let ((done nil) (kwop) - (re (concat - "\\<\\(try\\|match\\|with\\|function\\|parser\\|type" - "\\|e\\(nd\\|lse\\)\\|done\\|then\\|in\\)\\>" - "\\|[^[|]|\\|[])}]"))) - (while (not done) - (setq kwop (caml-find-kwop re)) - (cond - ((not kwop) (setq done t)) - ((looking-at "[^[|]\\(|\\)") - (goto-char (match-beginning 1)) - (setq kwop "|") - (setq done t)) - ((caml-at-sexp-close-p) - (caml-find-paren-match (following-char))) - ((string= kwop "with") - (setq kwop (caml-find-with-match)) - (setq done t)) - ((string= kwop "parser") - (if (re-search-backward "\\" (- (point) 5) t) - (setq kwop (caml-find-with-match))) - (setq done t)) - ((string= kwop "done") (caml-find-done-match)) - ((string= kwop "end") (caml-find-end-match)) - ((string= kwop "then") (caml-find-then-match)) - ((string= kwop "else") (caml-find-else-match)) - ((string= kwop "in") (caml-find-in-match)) - (t (setq done t)))) - kwop)) - -(defun caml-find-and-match () - (let ((done nil) (kwop)) - (while (not done) - (setq kwop (caml-find-kwop - "\\<\\(object\\|exception\\|let\\|type\\|end\\|in\\)\\>")) - (cond - ((not kwop) (setq done t)) - ((string= kwop "end") (caml-find-end-match)) - ((string= kwop "in") (caml-find-in-match)) - (t (setq done t)))) - kwop)) - -(defun caml-find-else-match () - (caml-find-then-match t)) - -(defun caml-find-semi-match () - (caml-find-kwop-skipping-blocks 2)) - -(defun caml-find-comma-match () - (caml-find-kwop-skipping-blocks 3)) - -(defun caml-find-kwop-skipping-blocks (prio) - "Look back for a caml keyword matching caml-kwop-regexps [PRIO]. - - Skip nested blocks." - - (let ((done nil) (kwop nil) (matching-fun) - (kwop-list (aref caml-kwop-regexps prio))) - (while (not done) - (setq kwop (caml-find-kwop - (concat caml-matching-kw-regexp - (cond ((> prio 3) "\\|[])},;]\\|") - ((> prio 2) "\\|[])};]\\|") - (t "\\|[])}]\\|")) - kwop-list))) - (cond - ((not kwop) (setq done t)) - ((caml-at-sexp-close-p) - (caml-find-paren-match (following-char))) - ((or (string= kwop ";;") - (and (string= kwop ";") (= (preceding-char) ?\;))) - (forward-line 1) - (setq kwop ";;") - (setq done t)) - ((and (>= prio 2) (string= kwop "|")) (setq done t)) - ((string= kwop "end") (caml-find-end-match)) - ((string= kwop "done") (caml-find-done-match)) - ((string= kwop "in") - (cond ((and (caml-find-in-match) (>= prio 2)) - (setq kwop "let-in") - (setq done t)))) - ((and (string= kwop "parser") (>= prio 2) - (re-search-backward "\\" (- (point) 5) t)) - (setq kwop (caml-find-with-match)) - (setq done t)) - ((setq matching-fun (cdr-safe (assoc kwop caml-matching-kw-alist))) - (setq kwop (funcall matching-fun)) - (if (looking-at kwop-list) (setq done t))) - (t (let* ((kwop-info (assoc kwop caml-kwop-alist)) - (is-op (and (nth 1 kwop-info) - ; check that we are not at beginning of line - (let ((pos (point)) bti) - (back-to-indentation) - (setq bti (point)) - (goto-char pos) - (< bti pos))))) - (if (and is-op (looking-at - (concat (regexp-quote kwop) - "|?[ \t]*\\(\n\\|(\\*\\)"))) - (setq kwop-list - (aref caml-kwop-regexps (nth 2 kwop-info))) - (setq done t)))))) - kwop)) - -(defun caml-compute-basic-indent (prio) - "Compute indent of current caml line, ignoring leading keywords. - -Find the `governing node' for current line. Compute desired -indentation based on the node and the indentation alists. -Assumes point is exactly at line indentation. -Does not preserve point." - - (let* (in-expr - (kwop (cond - ((looking-at ";;") - (beginning-of-line 1)) - ((looking-at "|\\([^]|]\\|\\'\\)") - (caml-find-pipe-match)) - ((and (looking-at caml-phrase-start-keywords) - (caml-in-expr-p)) - (caml-find-end-match)) - ((and (looking-at caml-matching-kw-regexp) - (assoc (caml-match-string 0) caml-matching-kw-alist)) - (funcall (cdr-safe (assoc (caml-match-string 0) - caml-matching-kw-alist)))) - ((looking-at - (aref caml-kwop-regexps caml-max-indent-priority)) - (let* ((kwop (caml-match-string 0)) - (kwop-info (assoc kwop caml-kwop-alist)) - (prio (if kwop-info (nth 2 kwop-info) - caml-max-indent-priority))) - (if (and (looking-at (aref caml-kwop-regexps 0)) - (not (looking-at "object")) - (caml-in-expr-p)) - (setq in-expr t)) - (caml-find-kwop-skipping-blocks prio))) - (t - (if (and (= prio caml-max-indent-priority) (caml-in-expr-p)) - (setq in-expr t)) - (caml-find-kwop-skipping-blocks prio)))) - (kwop-info (assoc kwop caml-kwop-alist)) - (indent-diff - (cond - ((not kwop-info) (beginning-of-line 1) 0) - ((looking-at "[[({][|<]?[ \t]*") - (length (caml-match-string 0))) - ((nth 1 kwop-info) (symbol-value (nth 3 kwop-info))) - (t - (let ((pos (point))) - (back-to-indentation) -; (if (looking-at "\\") (goto-char pos)) - (- (symbol-value (nth 3 kwop-info)) - (if (looking-at "|") caml-|-extra-indent 0)))))) - (extra (if in-expr caml-apply-extra-indent 0))) - (+ indent-diff extra (current-column)))) - -(defconst caml-leading-kwops-regexp - (concat - "\\<\\(and\\|do\\(ne\\|wnto\\)?\\|e\\(lse\\|nd\\)\\|in" - "\\|t\\(hen\\|o\\)\\|with\\)\\>\\|[]|})]") - - "Regexp matching caml keywords which need special indentation.") - -(defconst caml-leading-kwops-alist - '(("and" caml-and-extra-indent 2) - ("do" caml-do-extra-indent 0) - ("done" caml-done-extra-indent 0) - ("else" caml-else-extra-indent 3) - ("end" caml-end-extra-indent 0) - ("in" caml-in-extra-indent 2) - ("then" caml-then-extra-indent 3) - ("to" caml-to-extra-indent 0) - ("downto" caml-to-extra-indent 0) - ("with" caml-with-extra-indent 2) - ("|" caml-|-extra-indent 2) - ("]" caml-rb-extra-indent 0) - ("}" caml-rc-extra-indent 0) - (")" caml-rp-extra-indent 0)) - - "Association list of special caml keyword indent values. - -Each member is of the form (KEYWORD EXTRA-INDENT PRIO) where -EXTRA-INDENT is the variable holding extra indentation amount for -KEYWORD (usually negative) and PRIO is upper bound on priority of -matching nodes to determine KEYWORD's final indentation.") - -(defun caml-compute-final-indent () - (save-excursion - (back-to-indentation) - (cond - ((and (bolp) (looking-at comment-start-skip)) (current-column)) - ((caml-in-comment-p) - (let ((closing (looking-at "\\*)")) - (comment-mark (looking-at "\\*"))) - (caml-backward-comment) - (looking-at comment-start-skip) - (+ (current-column) - (cond - (closing 1) - (comment-mark 1) - (t (- (match-end 0) (match-beginning 0))))))) - (t (let* ((leading (looking-at caml-leading-kwops-regexp)) - (assoc-val (if leading (assoc (caml-match-string 0) - caml-leading-kwops-alist))) - (extra (if leading (symbol-value (nth 1 assoc-val)) 0)) - (prio (if leading (nth 2 assoc-val) - caml-max-indent-priority)) - (basic (caml-compute-basic-indent prio))) - (max 0 (if extra (+ extra basic) (current-column)))))))) - - - -(defun caml-split-string () - "Called whenever a line is broken inside a caml string literal." - (insert-before-markers "\"^\"") - (backward-char 1)) - -(defadvice indent-new-comment-line (around - caml-indent-new-comment-line - activate) - - "Handle multi-line strings in caml mode." - -;this advice doesn't make sense in other modes. I wish there were a -;cleaner way to do this: I haven't found one. - - (let ((hooked (and (eq major-mode 'caml-mode) (caml-in-literal-p))) - (split-mark)) - (if (not hooked) nil - (setq split-mark (set-marker (make-marker) (point))) - (caml-split-string)) - ad-do-it - (if (not hooked) nil - (goto-char split-mark) - (set-marker split-mark nil)))) - -(defadvice newline-and-indent (around - caml-newline-and-indent - activate) - - "Handle multi-line strings in caml mode." - - (let ((hooked (and (eq major-mode 'caml-mode) (caml-in-literal-p))) - (split-mark)) - (if (not hooked) nil - (setq split-mark (set-marker (make-marker) (point))) - (caml-split-string)) - ad-do-it - (if (not hooked) nil - (goto-char split-mark) - (set-marker split-mark nil)))) - -(defun caml-electric-pipe () - "If inserting a | or } operator at beginning of line, reindent the line. - -Unfortunately there is a situation where this mechanism gets -confused. It's when | is the first character of a |] sequence. This is -a misfeature of caml syntax and cannot be fixed, however, as a -workaround, the electric ] inserts | itself if the matching [ is -followed by |." - - (interactive "*") - (let ((electric (and caml-electric-indent - (caml-in-indentation) - (not (caml-in-comment-p))))) - (self-insert-command 1) - (if electric (save-excursion (caml-indent-command))))) - -(defun caml-electric-rb () - "If inserting a ] operator at beginning of line, reindent the line. - -Also, if the matching [ is followed by a | and this ] is not preceded -by |, insert one." - - (interactive "*") - (let* ((prec (preceding-char)) - (use-pipe (and caml-electric-close-vector - (not (caml-in-comment-p)) - (not (caml-in-literal-p)) - (or (not (numberp prec)) - (not (char-equal ?| prec))))) - (electric (and caml-electric-indent - (caml-in-indentation) - (not (caml-in-comment-p))))) - (self-insert-command 1) - (if electric (save-excursion (caml-indent-command))) - (if (and use-pipe - (save-excursion - (condition-case nil - (prog2 - (backward-list 1) - (looking-at "\\[|")) - (error "")))) - (save-excursion - (backward-char 1) - (insert "|"))))) - -(defun caml-abbrev-hook () - "If inserting a leading keyword at beginning of line, reindent the line." - ;itz unfortunately we need a special case - (if (and (not (caml-in-comment-p)) (not (= last-command-event ?_))) - (let* ((bol (save-excursion (beginning-of-line) (point))) - (kw (save-excursion - (and (re-search-backward "^[ \t]*\\(\\sw+\\)\\=" bol t) - (caml-match-string 1))))) - (if kw - (let ((indent (save-excursion - (goto-char (match-beginning 1)) - (caml-indent-command) - (current-column))) - (abbrev-correct (if (= last-command-event ?\ ) 1 0))) - (indent-to (- indent - (or - (symbol-value - (nth 1 - (assoc kw caml-leading-kwops-alist))) - 0) - abbrev-correct))))))) - -; (defun caml-indent-phrase () -; (interactive "*") -; (let ((bounds (caml-mark-phrase))) -; (indent-region (car bounds) (cdr bounds) nil))) - -;;; Additional commands by Didier to report errors in toplevel mode - -(defun caml-skip-blank-forward () - (if (looking-at "[ \t\n]*\\((\\*\\([^*]\\|[^(]\\*[^)]\\)*\\*)[ \t\n]*\\)*") - (goto-char (match-end 0)))) - -;; to mark phrases, so that repeated calls will take several of them -;; knows little about OCaml except literals and comments, so it should work -;; with other dialects as long as ;; marks the end of phrase. - -(defun caml-indent-phrase (arg) - "Indent current phrase -with prefix arg, indent that many phrases starting with the current phrase." - (interactive "p") - (save-excursion - (let ((beg (caml-find-phrase))) - (while (progn (setq arg (- arg 1)) (> arg 0)) (caml-find-phrase)) - (indent-region beg (point) nil)))) - -(defun caml-indent-buffer () - (interactive) - (indent-region (point-min) (point-max) nil)) - -(defun caml-backward-to-less-indent (&optional n) - "Move cursor back N lines with less or same indentation." - (interactive "p") - (beginning-of-line 1) - (if (< n 0) (caml-forward-to-less-indent (- n)) - (while (> n 0) - (let ((i (current-indentation))) - (forward-line -1) - (while (or (> (current-indentation) i) - (caml-in-comment-p) - (looking-at - (concat "[ \t]*\\(\n\\|" comment-start-skip "\\)"))) - (forward-line -1))) - (setq n (1- n)))) - (back-to-indentation)) - -(defun caml-forward-to-less-indent (&optional n) - "Move cursor back N lines with less or same indentation." - (interactive "p") - (beginning-of-line 1) - (if (< n 0) (caml-backward-to-less-indent (- n)) - (while (> n 0) - (let ((i (current-indentation))) - (forward-line 1) - (while (or (> (current-indentation) i) - (caml-in-comment-p) - (looking-at - (concat "[ \t]*\\(\n\\|" comment-start-skip "\\)"))) - (forward-line 1))) - (setq n (1- n)))) - (back-to-indentation)) - -(defun caml-insert-begin-form () - "Inserts a nicely formatted begin-end form, leaving a mark after end." - (interactive "*") - (let ((prec (preceding-char))) - (if (and (numberp prec) (not (char-equal ?\ (char-syntax prec)))) - (insert " "))) - (let* ((c (current-indentation)) (i (+ caml-begin-indent c))) - (insert "begin\n\nend") - (push-mark) - (indent-line-to c) - (forward-line -1) - (indent-line-to i))) - -(defun caml-insert-for-form () - "Inserts a nicely formatted for-do-done form, leaving a mark after do(ne)." - (interactive "*") - (let ((prec (preceding-char))) - (if (and (numberp prec) (not (char-equal ?\ (char-syntax prec)))) - (insert " "))) - (let* ((c (current-indentation)) (i (+ caml-for-indent c))) - (insert "for do\n\ndone") - (push-mark) - (indent-line-to c) - (forward-line -1) - (indent-line-to i) - (push-mark) - (beginning-of-line 1) - (backward-char 4))) - -(defun caml-insert-if-form () - "Insert nicely formatted if-then-else form leaving mark after then, else." - (interactive "*") - (let ((prec (preceding-char))) - (if (and (numberp prec) (not (char-equal ?\ (char-syntax prec)))) - (insert " "))) - (let* ((c (current-indentation)) (i (+ caml-if-indent c))) - (insert "if\n\nthen\n\nelse\n") - (indent-line-to i) - (push-mark) - (forward-line -1) - (indent-line-to c) - (forward-line -1) - (indent-line-to i) - (push-mark) - (forward-line -1) - (indent-line-to c) - (forward-line -1) - (indent-line-to i))) - -(defun caml-insert-match-form () - "Insert nicely formatted match-with form leaving mark after with." - (interactive "*") - (let ((prec (preceding-char))) - (if (and (numberp prec) (not (char-equal ?\ (char-syntax prec)))) - (insert " "))) - (let* ((c (current-indentation)) (i (+ caml-match-indent c))) - (insert "match\n\nwith\n") - (indent-line-to i) - (push-mark) - (forward-line -1) - (indent-line-to c) - (forward-line -1) - (indent-line-to i))) - -(defun caml-insert-let-form () - "Insert nicely formatted let-in form leaving mark after in." - (interactive "*") - (let ((prec (preceding-char))) - (if (and (numberp prec) (not (char-equal ?\ (char-syntax prec)))) - (insert " "))) - (let* ((c (current-indentation))) - (insert "let in\n") - (indent-line-to c) - (push-mark) - (forward-line -1) - (forward-char (+ c 4)))) - -(defun caml-insert-try-form () - "Insert nicely formatted try-with form leaving mark after with." - (interactive "*") - (let ((prec (preceding-char))) - (if (and (numberp prec) (not (char-equal ?\ (char-syntax prec)))) - (insert " "))) - (let* ((c (current-indentation)) (i (+ caml-try-indent c))) - (insert "try\n\nwith\n") - (indent-line-to i) - (push-mark) - (forward-line -1) - (indent-line-to c) - (forward-line -1) - (indent-line-to i))) - -(defun caml-insert-while-form () - "Insert nicely formatted while-do-done form leaving mark after do, done." - (interactive "*") - (let ((prec (preceding-char))) - (if (and (numberp prec) (not (char-equal ?\ (char-syntax prec)))) - (insert " "))) - (let* ((c (current-indentation)) (i (+ caml-if-indent c))) - (insert "while do\n\ndone") - (push-mark) - (indent-line-to c) - (forward-line -1) - (indent-line-to i) - (push-mark) - (beginning-of-line 1) - (backward-char 4))) - -(autoload 'run-caml "inf-caml" "Run an inferior OCaml process." t) - -(autoload 'caml-types-show-type "caml-types" - "Show the type of expression or pattern at point." t) -(autoload 'caml-types-explore "caml-types" - "Explore type annotations by mouse dragging." t) - -(autoload 'caml-help "caml-help" - "Show documentation for qualified OCaml identifier." t) -(autoload 'caml-complete "caml-help" - "Does completion for documented qualified OCaml identifier." t) -(autoload 'ocaml-open-module "caml-help" - "Add module in documentation search path." t) -(autoload 'ocaml-close-module "caml-help" - "Remove module from documentation search path." t) -(autoload 'ocaml-add-path "caml-help" - "Add search path for documentation." t) - -(provide 'caml) - -;;; caml.el ends here diff --git a/emacs/camldebug.el b/emacs/camldebug.el deleted file mode 100644 index 8b59942f..00000000 --- a/emacs/camldebug.el +++ /dev/null @@ -1,795 +0,0 @@ -;************************************************************************** -;* * -;* OCaml * -;* * -;* Jacques Garrigue and Ian T Zimmerman * -;* * -;* Copyright 1997 Institut National de Recherche en Informatique et * -;* en Automatique. * -;* * -;* All rights reserved. This file is distributed under the terms of * -;* the GNU General Public License. * -;* * -;************************************************************************** - -;;; Run camldebug under Emacs -;;; Derived from gdb.el. -;;; gdb.el is Copyright (C) 1988 Free Software Foundation, Inc, and is part -;;; of GNU Emacs -;;; Modified by Jerome Vouillon, 1994. -;;; Modified by Ian T. Zimmerman, 1996. -;;; Modified by Xavier Leroy, 1997. - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 1, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;;itz 04-06-96 I pondered basing this on gud. The potential advantages -;;were: automatic bugfix , keymaps and menus propagation. -;;Disadvantages: gud is not so clean itself, there is little common -;;functionality it abstracts (most of the stuff is done in the -;;debugger specific parts anyway), and, most seriously, gud sees it -;;fit to add C-x C-a bindings to the _global_ map, so there would be a -;;conflict between camldebug and gdb, for instance. While it's OK to -;;assume that a sane person doesn't use gdb and dbx at the same time, -;;it's not so OK (IMHO) for gdb and camldebug. - -;; Xavier Leroy, 21/02/97: adaptation to ocamldebug. - -(require 'comint) -(require 'shell) -(require 'caml) -(require 'derived) -(require 'thingatpt) - -;;; Variables. - -(defvar camldebug-last-frame) -(defvar camldebug-delete-prompt-marker) -(defvar camldebug-filter-accumulator nil) -(defvar camldebug-last-frame-displayed-p) -(defvar camldebug-filter-function) - -(defvar camldebug-prompt-pattern "^(ocd) *" - "A regexp to recognize the prompt for ocamldebug.") - -(defvar camldebug-overlay-event nil - "Overlay for displaying the current event.") -(defvar camldebug-overlay-under nil - "Overlay for displaying the current event.") -(defvar camldebug-event-marker nil - "Marker for displaying the current event.") - -(defvar camldebug-track-frame t - "*If non-nil, always display current frame position in another window.") - -(cond - (window-system - (make-face 'camldebug-event) - (make-face 'camldebug-underline) - (if (not (face-differs-from-default-p 'camldebug-event)) - (invert-face 'camldebug-event)) - (if (not (face-differs-from-default-p 'camldebug-underline)) - (set-face-underline-p 'camldebug-underline t)) - (setq camldebug-overlay-event (make-overlay 1 1)) - (overlay-put camldebug-overlay-event 'face 'camldebug-event) - (setq camldebug-overlay-under (make-overlay 1 1)) - (overlay-put camldebug-overlay-under 'face 'camldebug-underline)) - (t - (setq camldebug-event-marker (make-marker)) - (setq overlay-arrow-string "=>"))) - -;;; Camldebug mode. - -(define-derived-mode camldebug-mode comint-mode "Inferior CDB" - - "Major mode for interacting with an inferior ocamldebug process. - -The following commands are available: - -\\{camldebug-mode-map} - -\\[camldebug-display-frame] displays in the other window -the last line referred to in the camldebug buffer. - -\\[camldebug-step], \\[camldebug-back] and \\[camldebug-next], in the camldebug -window, call camldebug to step, backstep or next and then update the other window -with the current file and position. - -If you are in a source file, you may select a point to break -at, by doing \\[camldebug-break]. - -Commands: -Many commands are inherited from comint mode. -Additionally we have: - -\\[camldebug-display-frame] display frames file in other window -\\[camldebug-step] advance one line in program -C-x SPACE sets break point at current line." - - (mapcar 'make-local-variable - '(camldebug-last-frame-displayed-p camldebug-last-frame - camldebug-delete-prompt-marker camldebug-filter-function - camldebug-filter-accumulator paragraph-start)) - (setq - camldebug-last-frame nil - camldebug-delete-prompt-marker (make-marker) - camldebug-filter-accumulator "" - camldebug-filter-function 'camldebug-marker-filter - comint-prompt-regexp camldebug-prompt-pattern - comint-dynamic-complete-functions (cons 'camldebug-complete - comint-dynamic-complete-functions) - paragraph-start comint-prompt-regexp - camldebug-last-frame-displayed-p t) - (make-local-variable 'shell-dirtrackp) - (setq shell-dirtrackp t) - (setq comint-input-sentinel 'shell-directory-tracker)) - -;;; Keymaps. - -(defun camldebug-numeric-arg (arg) - (and arg (prefix-numeric-value arg))) - -(defmacro def-camldebug (name key &optional doc args) - - "Define camldebug-NAME to be a command sending NAME ARGS and bound -to KEY, with optional doc string DOC. Certain %-escapes in ARGS are -interpreted specially if present. These are: - - %m module name of current module. - %d directory of current source file. - %c number of current character position - %e text of the caml variable surrounding point. - - The `current' source file is the file of the current buffer (if -we're in a caml buffer) or the source file current at the last break -or step (if we're in the camldebug buffer), and the `current' module -name is the filename stripped of any *.ml* suffixes (this assumes the -usual correspondence between module and file naming is observed). The -`current' position is that of the current buffer (if we're in a source -file) or the position of the last break or step (if we're in the -camldebug buffer). - -If a numeric is present, it overrides any ARGS flags and its string -representation is simply concatenated with the COMMAND." - - (let* ((fun (intern (format "camldebug-%s" name)))) - (list 'progn - (if doc - (list 'defun fun '(arg) - doc - '(interactive "P") - (list 'camldebug-call name args - '(camldebug-numeric-arg arg)))) - (list 'define-key 'camldebug-mode-map - (concat "\C-c" key) - (list 'quote fun)) - (list 'define-key 'caml-mode-map - (concat "\C-x\C-a" key) - (list 'quote fun))))) - -(def-camldebug "step" "\C-s" "Step one event forward.") -(def-camldebug "backstep" "\C-k" "Step one event backward.") -(def-camldebug "run" "\C-r" "Run the program.") -(def-camldebug "reverse" "\C-v" "Run the program in reverse.") -(def-camldebug "last" "\C-l" "Go to latest time in execution history.") -(def-camldebug "backtrace" "\C-t" "Print the call stack.") -(def-camldebug "finish" "\C-f" "Finish executing current function.") -(def-camldebug "print" "\C-p" "Print value of symbol at point." "%e") -(def-camldebug "display" "\C-d" "Display value of symbol at point." "%e") -(def-camldebug "next" "\C-n" "Step one event forward (skip functions)") -(def-camldebug "up" "<" "Go up N stack frames (numeric arg) with display") -(def-camldebug "down" ">" "Go down N stack frames (numeric arg) with display") -(def-camldebug "break" "\C-b" "Set breakpoint at current line." - "@ \"%m\" # %c") - -(defun camldebug-mouse-display (click) - "Display value of $NNN clicked on." - (interactive "e") - (let* ((start (event-start click)) - (window (car start)) - (pos (car (cdr start))) - symb) - (save-excursion - (select-window window) - (goto-char pos) - (setq symb (thing-at-point 'symbol)) - (if (string-match "^\\$[0-9]+$" symb) - (camldebug-call "display" symb))))) - -(define-key camldebug-mode-map [mouse-2] 'camldebug-mouse-display) - -(defun camldebug-kill-filter (string) - ;gob up stupid questions :-) - (setq camldebug-filter-accumulator - (concat camldebug-filter-accumulator string)) - (if (not (string-match "\\(.* \\)(y or n) " - camldebug-filter-accumulator)) nil - (setq camldebug-kill-output - (cons t (match-string 1 camldebug-filter-accumulator))) - (setq camldebug-filter-accumulator "")) - (if (string-match comint-prompt-regexp camldebug-filter-accumulator) - (let ((output (substring camldebug-filter-accumulator - (match-beginning 0)))) - (setq camldebug-kill-output - (cons nil (substring camldebug-filter-accumulator 0 - (1- (match-beginning 0))))) - (setq camldebug-filter-accumulator "") - output) - "")) - -(def-camldebug "kill" "\C-k") - -(defun camldebug-kill () - "Kill the program." - (interactive) - (let ((camldebug-kill-output)) - (save-excursion - (set-buffer current-camldebug-buffer) - (let ((proc (get-buffer-process (current-buffer))) - (camldebug-filter-function 'camldebug-kill-filter)) - (camldebug-call "kill") - (while (not (and camldebug-kill-output - (zerop (length camldebug-filter-accumulator)))) - (accept-process-output proc)))) - (if (not (car camldebug-kill-output)) - (error (cdr camldebug-kill-output)) - (sit-for 0 300) - (camldebug-call-1 (if (y-or-n-p (cdr camldebug-kill-output)) "y" "n"))))) -;;FIXME: camldebug doesn't output the Hide marker on kill - -(defun camldebug-goto-filter (string) - ;accumulate onto previous output - (setq camldebug-filter-accumulator - (concat camldebug-filter-accumulator string)) - (if (not (or (string-match (concat "\\(\n\\|\\`\\)[ \t]*\\([0-9]+\\)[ \t]+" - camldebug-goto-position - "-[0-9]+[ \t]*\\(before\\).*\n") - camldebug-filter-accumulator) - (string-match (concat "\\(\n\\|\\`\\)[ \t]*\\([0-9]+\\)" - "[ \t]+[0-9]+-" - camldebug-goto-position - "[ \t]*\\(after\\).*\n") - camldebug-filter-accumulator))) - nil - (setq camldebug-goto-output - (match-string 2 camldebug-filter-accumulator)) - (setq camldebug-filter-accumulator - (substring camldebug-filter-accumulator (1- (match-end 0))))) - (if (not (string-match comint-prompt-regexp - camldebug-filter-accumulator)) nil - (setq camldebug-goto-output (or camldebug-goto-output 'fail)) - (setq camldebug-filter-accumulator "")) - (if (string-match "\n\\(.*\\)\\'" camldebug-filter-accumulator) - (setq camldebug-filter-accumulator - (match-string 1 camldebug-filter-accumulator))) - "") - -(def-camldebug "goto" "\C-g") -(defun camldebug-goto (&optional time) - - "Go to the execution time TIME. - -Without TIME, the command behaves as follows: In the camldebug buffer, -if the point at buffer end, goto time 0\; otherwise, try to obtain the -time from context around point. In a caml mode buffer, try to find the -time associated in execution history with the current point location. - -With a negative TIME, move that many lines backward in the camldebug -buffer, then try to obtain the time from context around point." - - (interactive "P") - (cond - (time - (let ((ntime (camldebug-numeric-arg time))) - (if (>= ntime 0) (camldebug-call "goto" nil ntime) - (save-selected-window - (select-window (get-buffer-window current-camldebug-buffer)) - (save-excursion - (if (re-search-backward "^Time : [0-9]+ - pc : [0-9]+ " - nil t (- 1 ntime)) - (camldebug-goto nil) - (error "I don't have %d times in my history" - (- 1 ntime)))))))) - ((eq (current-buffer) current-camldebug-buffer) - (let ((time (cond - ((eobp) 0) - ((save-excursion - (beginning-of-line 1) - (looking-at "^Time : \\([0-9]+\\) - pc : [0-9]+ ")) - (caml-string-to-int (match-string 1))) - ((caml-string-to-int (camldebug-format-command "%e")))))) - (camldebug-call "goto" nil time))) - (t - (let ((module (camldebug-module-name (buffer-file-name))) - (camldebug-goto-position (int-to-string (1- (point)))) - (camldebug-goto-output) (address)) - ;get a list of all events in the current module - (save-excursion - (set-buffer current-camldebug-buffer) - (let* ((proc (get-buffer-process (current-buffer))) - (camldebug-filter-function 'camldebug-goto-filter)) - (camldebug-call-1 (concat "info events " module)) - (while (not (and camldebug-goto-output - (zerop (length camldebug-filter-accumulator)))) - (accept-process-output proc)) - (setq address (if (eq camldebug-goto-output 'fail) nil - (re-search-backward - (concat "^Time : \\([0-9]+\\) - pc : " - camldebug-goto-output - " - module " - module "$") nil t) - (match-string 1))))) - (if address (camldebug-call "goto" nil (caml-string-to-int address)) - (error "No time at %s at %s" module camldebug-goto-position)))))) - - -(defun camldebug-delete-filter (string) - (setq camldebug-filter-accumulator - (concat camldebug-filter-accumulator string)) - (if (not (string-match - (concat "\\(\n\\|\\`\\)[ \t]*\\([0-9]+\\)[ \t]+[0-9]+[ \t]*in " - (regexp-quote camldebug-delete-file) - ", character " - camldebug-delete-position "\n") - camldebug-filter-accumulator)) nil - (setq camldebug-delete-output - (match-string 2 camldebug-filter-accumulator)) - (setq camldebug-filter-accumulator - (substring camldebug-filter-accumulator (1- (match-end 0))))) - (if (not (string-match comint-prompt-regexp - camldebug-filter-accumulator)) nil - (setq camldebug-delete-output (or camldebug-delete-output 'fail)) - (setq camldebug-filter-accumulator "")) - (if (string-match "\n\\(.*\\)\\'" camldebug-filter-accumulator) - (setq camldebug-filter-accumulator - (match-string 1 camldebug-filter-accumulator))) - "") - - -(def-camldebug "delete" "\C-d") - -(defun camldebug-delete (&optional arg) - "Delete the breakpoint numbered ARG. - -Without ARG, the command behaves as follows: In the camldebug buffer, -try to obtain the time from context around point. In a caml mode -buffer, try to find the breakpoint associated with the current point -location. - -With a negative ARG, look for the -ARGth breakpoint pattern in the -camldebug buffer, then try to obtain the breakpoint info from context -around point." - - (interactive "P") - (cond - (arg - (let ((narg (camldebug-numeric-arg arg))) - (if (> narg 0) (camldebug-call "delete" nil narg) - (save-excursion - (set-buffer current-camldebug-buffer) - (if (re-search-backward "^Breakpoint [0-9]+ at [0-9]+ : file " - nil t (- 1 narg)) - (camldebug-delete nil) - (error "I don't have %d breakpoints in my history" - (- 1 narg))))))) - ((eq (current-buffer) current-camldebug-buffer) - (let* ((bpline "^Breakpoint \\([0-9]+\\) at [0-9]+ : file ") - (arg (cond - ((eobp) - (save-excursion (re-search-backward bpline nil t)) - (caml-string-to-int (match-string 1))) - ((save-excursion - (beginning-of-line 1) - (looking-at bpline)) - (caml-string-to-int (match-string 1))) - ((caml-string-to-int (camldebug-format-command "%e")))))) - (camldebug-call "delete" nil arg))) - (t - (let ((camldebug-delete-file - (concat (camldebug-format-command "%m") ".ml")) - (camldebug-delete-position (camldebug-format-command "%c"))) - (save-excursion - (set-buffer current-camldebug-buffer) - (let ((proc (get-buffer-process (current-buffer))) - (camldebug-filter-function 'camldebug-delete-filter) - (camldebug-delete-output)) - (camldebug-call-1 "info break") - (while (not (and camldebug-delete-output - (zerop (length - camldebug-filter-accumulator)))) - (accept-process-output proc)) - (if (eq camldebug-delete-output 'fail) - (error "No breakpoint in %s at %s" - camldebug-delete-file - camldebug-delete-position) - (camldebug-call "delete" nil - (caml-string-to-int camldebug-delete-output))))))))) - -(defun camldebug-complete-filter (string) - (setq camldebug-filter-accumulator - (concat camldebug-filter-accumulator string)) - (while (string-match "\\(\n\\|\\`\\)\\(.+\\)\n" - camldebug-filter-accumulator) - (setq camldebug-complete-list - (cons (match-string 2 camldebug-filter-accumulator) - camldebug-complete-list)) - (setq camldebug-filter-accumulator - (substring camldebug-filter-accumulator - (1- (match-end 0))))) - (if (not (string-match comint-prompt-regexp - camldebug-filter-accumulator)) nil - (setq camldebug-complete-list - (or camldebug-complete-list 'fail)) - (setq camldebug-filter-accumulator "")) - (if (string-match "\n\\(.*\\)\\'" camldebug-filter-accumulator) - (setq camldebug-filter-accumulator - (match-string 1 camldebug-filter-accumulator))) - "") - -(defun camldebug-complete () - - "Perform completion on the camldebug command preceding point." - - (interactive) - (let* ((end (point)) - (command (save-excursion - (beginning-of-line) - (and (looking-at comint-prompt-regexp) - (goto-char (match-end 0))) - (buffer-substring (point) end))) - (camldebug-complete-list nil) (command-word)) - - ;; Find the word break. This match will always succeed. - (string-match "\\(\\`\\| \\)\\([^ ]*\\)\\'" command) - (setq command-word (match-string 2 command)) - - ;itz 04-21-96 if we are trying to complete a word of nonzero - ;length, chop off the last character. This is a nasty hack, but it - ;works - in general, not just for this set of words: the comint - ;call below will weed out false matches - and it avoids further - ;mucking with camldebug's lexer. - (if (> (length command-word) 0) - (setq command (substring command 0 (1- (length command))))) - - (let ((camldebug-filter-function 'camldebug-complete-filter)) - (camldebug-call-1 (concat "complete " command)) - (set-marker camldebug-delete-prompt-marker nil) - (while (not (and camldebug-complete-list - (zerop (length camldebug-filter-accumulator)))) - (accept-process-output (get-buffer-process - (current-buffer))))) - (if (eq camldebug-complete-list 'fail) - (setq camldebug-complete-list nil)) - (setq camldebug-complete-list - (sort camldebug-complete-list 'string-lessp)) - (comint-dynamic-simple-complete command-word camldebug-complete-list))) - -(define-key camldebug-mode-map "\C-l" 'camldebug-refresh) -(define-key camldebug-mode-map "\t" 'comint-dynamic-complete) -(define-key camldebug-mode-map "\M-?" 'comint-dynamic-list-completions) - -(define-key caml-mode-map "\C-x " 'camldebug-break) - - -(defvar current-camldebug-buffer nil) - - -;;;###autoload -(defvar camldebug-command-name "ocamldebug" - "*Pathname for executing camldebug.") - -;;;###autoload -(defun camldebug (path) - "Run camldebug on program FILE in buffer *camldebug-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for camldebug. If you wish to change this, use -the camldebug commands `cd DIR' and `directory'." - (interactive "fRun ocamldebug on file: ") - (setq path (expand-file-name path)) - (let ((file (file-name-nondirectory path))) - (pop-to-buffer (concat "*camldebug-" file "*")) - (setq default-directory (file-name-directory path)) - (message "Current directory is %s" default-directory) - (make-comint (concat "camldebug-" file) - (substitute-in-file-name camldebug-command-name) - nil - "-emacs" "-cd" default-directory file) - (set-process-filter (get-buffer-process (current-buffer)) - 'camldebug-filter) - (set-process-sentinel (get-buffer-process (current-buffer)) - 'camldebug-sentinel) - (camldebug-mode) - (camldebug-set-buffer))) - -(defun camldebug-set-buffer () - (if (eq major-mode 'camldebug-mode) - (setq current-camldebug-buffer (current-buffer)) - (save-selected-window (pop-to-buffer current-camldebug-buffer)))) - -;;; Filter and sentinel. - -(defun camldebug-marker-filter (string) - (setq camldebug-filter-accumulator - (concat camldebug-filter-accumulator string)) - (let ((output "") (begin)) - ;; Process all the complete markers in this chunk. - (while (setq begin - (string-match - "\032\032\\(H\\|M\\(.+\\):\\(.+\\):\\(.+\\):\\(before\\|after\\)\\)\n" - camldebug-filter-accumulator)) - (setq camldebug-last-frame - (if (char-equal ?H (aref camldebug-filter-accumulator - (1+ (1+ begin)))) nil - (let ((isbefore - (string= "before" - (match-string 5 camldebug-filter-accumulator))) - (startpos (caml-string-to-int - (match-string 3 camldebug-filter-accumulator))) - (endpos (caml-string-to-int - (match-string 4 camldebug-filter-accumulator)))) - (list (match-string 2 camldebug-filter-accumulator) - (if isbefore startpos endpos) - isbefore - startpos - endpos - ))) - output (concat output - (substring camldebug-filter-accumulator - 0 begin)) - ;; Set the accumulator to the remaining text. - camldebug-filter-accumulator (substring - camldebug-filter-accumulator - (match-end 0)) - camldebug-last-frame-displayed-p nil)) - - - ;; Does the remaining text look like it might end with the - ;; beginning of another marker? If it does, then keep it in - ;; camldebug-filter-accumulator until we receive the rest of it. Since we - ;; know the full marker regexp above failed, it's pretty simple to - ;; test for marker starts. - (if (string-match "\032.*\\'" camldebug-filter-accumulator) - (progn - ;; Everything before the potential marker start can be output. - (setq output (concat output (substring camldebug-filter-accumulator - 0 (match-beginning 0)))) - - ;; Everything after, we save, to combine with later input. - (setq camldebug-filter-accumulator - (substring camldebug-filter-accumulator (match-beginning 0)))) - - (setq output (concat output camldebug-filter-accumulator) - camldebug-filter-accumulator "")) - - output)) - -(defun camldebug-filter (proc string) - (let ((output)) - (if (buffer-name (process-buffer proc)) - (let ((process-window)) - ;; it does not seem necessary to save excursion here, - ;; since set-buffer as a temporary effect. - ;; comint-output-filter explicitly avoids it. - ;; in version 23, it prevents the marker to stay at end of buffer - ;; (save-excursion - (set-buffer (process-buffer proc)) - ;; If we have been so requested, delete the debugger prompt. - (if (marker-buffer camldebug-delete-prompt-marker) - (progn - (delete-region (process-mark proc) - camldebug-delete-prompt-marker) - (set-marker camldebug-delete-prompt-marker nil))) - (setq output (funcall camldebug-filter-function string)) - ;; Don't display the specified file unless - ;; (1) point is at or after the position where output appears - ;; and (2) this buffer is on the screen. - (setq process-window (and camldebug-track-frame - (not camldebug-last-frame-displayed-p) - (>= (point) (process-mark proc)) - (get-buffer-window (current-buffer)))) - ;; Insert the text, moving the process-marker. - (comint-output-filter proc output) - ;; ) - ;; this was the end of save-excursion. - ;; if save-excursion is used (comint-next-prompt 1) would be needed - ;; to move the mark past then next prompt, but this is not as good - ;; as solution. - (if process-window - (save-selected-window - (select-window process-window) - (camldebug-display-frame))))))) - -(defun camldebug-sentinel (proc msg) - (cond ((null (buffer-name (process-buffer proc))) - ;; buffer killed - ;; Stop displaying an arrow in a source file. - (camldebug-remove-current-event) - (set-process-buffer proc nil)) - ((memq (process-status proc) '(signal exit)) - ;; Stop displaying an arrow in a source file. - (camldebug-remove-current-event) - ;; Fix the mode line. - (setq mode-line-process - (concat ": " - (symbol-name (process-status proc)))) - (let* ((obuf (current-buffer))) - ;; save-excursion isn't the right thing if - ;; process-buffer is current-buffer - (unwind-protect - (progn - ;; Write something in *compilation* and hack its mode line, - (set-buffer (process-buffer proc)) - ;; Force mode line redisplay soon - (set-buffer-modified-p (buffer-modified-p)) - (if (eobp) - (insert ?\n mode-name " " msg) - (save-excursion - (goto-char (point-max)) - (insert ?\n mode-name " " msg))) - ;; If buffer and mode line will show that the process - ;; is dead, we can delete it now. Otherwise it - ;; will stay around until M-x list-processes. - (delete-process proc)) - ;; Restore old buffer, but don't restore old point - ;; if obuf is the cdb buffer. - (set-buffer obuf)))))) - - -(defun camldebug-refresh (&optional arg) - "Fix up a possibly garbled display, and redraw the mark." - (interactive "P") - (camldebug-display-frame) - (recenter arg)) - -(defun camldebug-display-frame () - "Find, obey and delete the last filename-and-line marker from CDB. -The marker looks like \\032\\032Mfilename:startchar:endchar:beforeflag\\n. -Obeying it means displaying in another window the specified file and line." - (interactive) - (camldebug-set-buffer) - (if (not camldebug-last-frame) - (camldebug-remove-current-event) - (camldebug-display-line (nth 0 camldebug-last-frame) - (nth 3 camldebug-last-frame) - (nth 4 camldebug-last-frame) - (nth 2 camldebug-last-frame))) - (setq camldebug-last-frame-displayed-p t)) - -;; Make sure the file named TRUE-FILE is in a buffer that appears on the screen -;; and that its character CHARACTER is visible. -;; Put the mark on this character in that buffer. - -(defun camldebug-display-line (true-file schar echar kind) - (let* ((pre-display-buffer-function nil) ; screw it, put it all in one screen - (pop-up-windows t) - (buffer (find-file-noselect true-file)) - (window (display-buffer buffer t)) - (spos) (epos) (pos)) - (save-excursion - (set-buffer buffer) - (save-restriction - (widen) - (setq spos (+ (point-min) schar)) - (setq epos (+ (point-min) echar)) - (setq pos (if kind spos epos)) - (camldebug-set-current-event spos epos (current-buffer) kind)) - (cond ((or (< pos (point-min)) (> pos (point-max))) - (widen) - (goto-char pos)))) - (set-window-point window pos))) - -;;; Events. - -(defun camldebug-remove-current-event () - (if window-system - (progn - (delete-overlay camldebug-overlay-event) - (delete-overlay camldebug-overlay-under)) - (setq overlay-arrow-position nil))) - -(defun camldebug-set-current-event (spos epos buffer before) - (if window-system - (if before - (progn - (move-overlay camldebug-overlay-event spos (1+ spos) buffer) - (move-overlay camldebug-overlay-under - (+ spos 1) epos buffer)) - (move-overlay camldebug-overlay-event (1- epos) epos buffer) - (move-overlay camldebug-overlay-under spos (- epos 1) buffer)) - (save-excursion - (set-buffer buffer) - (goto-char spos) - (beginning-of-line) - (move-marker camldebug-event-marker (point)) - (setq overlay-arrow-position camldebug-event-marker)))) - -;;; Miscellaneous. - -(defun camldebug-module-name (filename) - (substring filename (string-match "\\([^/]*\\)\\.ml$" filename) - (match-end 1))) - -;;; The camldebug-call function must do the right thing whether its -;;; invoking keystroke is from the camldebug buffer itself (via -;;; major-mode binding) or a caml buffer. In the former case, we want -;;; to supply data from camldebug-last-frame. Here's how we do it: - -(defun camldebug-format-command (str) - (let* ((insource (not (eq (current-buffer) current-camldebug-buffer))) - (frame (if insource nil camldebug-last-frame)) (result)) - (while (and str (string-match "\\([^%]*\\)%\\([mdcep]\\)" str)) - (let ((key (string-to-char (substring str (match-beginning 2)))) - (cmd (substring str (match-beginning 1) (match-end 1))) - (subst)) - (setq str (substring str (match-end 2))) - (cond - ((eq key ?m) - (setq subst (camldebug-module-name - (if insource (buffer-file-name) (nth 0 frame))))) - ((eq key ?d) - (setq subst (file-name-directory - (if insource (buffer-file-name) (nth 0 frame))))) - ((eq key ?c) - (setq subst (int-to-string - (if insource (1- (point)) (nth 1 frame))))) - ((eq key ?e) - (setq subst (thing-at-point 'symbol)))) - (setq result (concat result cmd subst)))) - ;; There might be text left in STR when the loop ends. - (concat result str))) - -(defun camldebug-call (command &optional fmt arg) - "Invoke camldebug COMMAND displaying source in other window. - -Certain %-escapes in FMT are interpreted specially if present. -These are: - - %m module name of current module. - %d directory of current source file. - %c number of current character position - %e text of the caml variable surrounding point. - - The `current' source file is the file of the current buffer (if -we're in a caml buffer) or the source file current at the last break -or step (if we're in the camldebug buffer), and the `current' module -name is the filename stripped of any *.ml* suffixes (this assumes the -usual correspondence between module and file naming is observed). The -`current' position is that of the current buffer (if we're in a source -file) or the position of the last break or step (if we're in the -camldebug buffer). - -If ARG is present, it overrides any FMT flags and its string -representation is simply concatenated with the COMMAND." - - ;; Make sure debugger buffer is displayed in a window. - (camldebug-set-buffer) - (message "Command: %s" (camldebug-call-1 command fmt arg))) - -(defun camldebug-call-1 (command &optional fmt arg) - - ;; Record info on the last prompt in the buffer and its position. - (save-excursion - (set-buffer current-camldebug-buffer) - (goto-char (process-mark (get-buffer-process current-camldebug-buffer))) - (let ((pt (point))) - (beginning-of-line) - (if (looking-at comint-prompt-regexp) - (set-marker camldebug-delete-prompt-marker (point))))) - (let ((cmd (cond - (arg (concat command " " (int-to-string arg))) - (fmt (camldebug-format-command - (concat command " " fmt))) - (command)))) - (process-send-string (get-buffer-process current-camldebug-buffer) - (concat cmd "\n")) - cmd)) - - -(provide 'camldebug) diff --git a/emacs/inf-caml.el b/emacs/inf-caml.el deleted file mode 100644 index 3d2b2dc9..00000000 --- a/emacs/inf-caml.el +++ /dev/null @@ -1,364 +0,0 @@ -;************************************************************************** -;* * -;* OCaml * -;* * -;* Xavier Leroy and Jacques Garrigue * -;* * -;* Copyright 1997 Institut National de Recherche en Informatique et * -;* en Automatique. * -;* * -;* All rights reserved. This file is distributed under the terms of * -;* the GNU General Public License. * -;* * -;************************************************************************** - -;;; inf-caml.el --- run the OCaml toplevel in an Emacs buffer - -;; Xavier Leroy, july 1993. - -;; modified by Jacques Garrigue, july 1997. - -(require 'comint) -(require 'caml) - -;; User modifiable variables - -;; Whether you want the output buffer to be displayed when you send a phrase - -(defvar caml-display-when-eval t - "*If true, display the inferior caml buffer when evaluating expressions.") - - -;; End of User modifiable variables - - -(defvar inferior-caml-mode-map nil) -(if inferior-caml-mode-map nil - (setq inferior-caml-mode-map - (copy-keymap comint-mode-map))) - -;; Augment Caml mode, so you can process OCaml code in the source files. - -(defvar inferior-caml-program "ocaml" - "*Program name for invoking an inferior OCaml from Emacs.") - -(defun inferior-caml-mode () - "Major mode for interacting with an inferior OCaml process. -Runs an OCaml toplevel as a subprocess of Emacs, with I/O through an -Emacs buffer. A history of input phrases is maintained. Phrases can -be sent from another buffer in Caml mode. - -\\{inferior-caml-mode-map}" - (interactive) - (comint-mode) - (setq comint-prompt-regexp "^# ?") - (setq major-mode 'inferior-caml-mode) - (setq mode-name "Inferior Caml") - (make-local-variable 'paragraph-start) - (setq paragraph-start (concat "^$\\|" page-delimiter)) - (make-local-variable 'paragraph-separate) - (setq paragraph-separate paragraph-start) - (make-local-variable 'paragraph-ignore-fill-prefix) - (setq paragraph-ignore-fill-prefix t) - (make-local-variable 'require-final-newline) - (setq require-final-newline t) - (make-local-variable 'comment-start) - (setq comment-start "(*") - (make-local-variable 'comment-end) - (setq comment-end "*)") - (make-local-variable 'comment-column) - (setq comment-column 40) - (make-local-variable 'comment-start-skip) - (setq comment-start-skip "(\\*+ *") - (make-local-variable 'parse-sexp-ignore-comments) - (setq parse-sexp-ignore-comments nil) - (use-local-map inferior-caml-mode-map) - (run-hooks 'inferior-caml-mode-hooks)) - - -(defconst inferior-caml-buffer-subname "inferior-caml") -(defconst inferior-caml-buffer-name - (concat "*" inferior-caml-buffer-subname "*")) - -;; for compatibility with xemacs - -(defun caml-sit-for (second &optional mili redisplay) - (if (and (boundp 'running-xemacs) running-xemacs) - (sit-for (if mili (+ second (* mili 0.001)) second) redisplay) - (sit-for second mili redisplay))) - -;; To show result of evaluation at toplevel - -(defvar inferior-caml-output nil) -(defun inferior-caml-signal-output (s) - (if (string-match "[^ ]" s) (setq inferior-caml-output t))) - -(defun inferior-caml-mode-output-hook () - (set-variable 'comint-output-filter-functions - (list (function inferior-caml-signal-output)) - t)) -(add-hook 'inferior-caml-mode-hooks 'inferior-caml-mode-output-hook) - -;; To launch ocaml whenever needed - -(defun caml-run-process-if-needed (&optional cmd) - (if (comint-check-proc inferior-caml-buffer-name) nil - (if (not cmd) - (if (comint-check-proc inferior-caml-buffer-name) - (setq cmd inferior-caml-program) - (setq cmd (read-from-minibuffer "OCaml toplevel to run: " - inferior-caml-program)))) - (setq inferior-caml-program cmd) - (let ((cmdlist (inferior-caml-args-to-list cmd)) - (process-connection-type nil)) - (set-buffer (apply (function make-comint) - inferior-caml-buffer-subname - (car cmdlist) nil (cdr cmdlist))) - (inferior-caml-mode) - (display-buffer inferior-caml-buffer-name) - t) - (setq caml-shell-active t) - )) - -;; patched to from original run-caml sharing code with -;; caml-run-process-when-needed - -(defun run-caml (&optional cmd) - "Run an inferior OCaml process. -Input and output via buffer `*inferior-caml*'." - (interactive - (list (if (not (comint-check-proc inferior-caml-buffer-name)) - (read-from-minibuffer "OCaml toplevel to run: " - inferior-caml-program)))) - (caml-run-process-if-needed cmd) - (switch-to-buffer-other-window inferior-caml-buffer-name)) - - -(defun inferior-caml-args-to-list (string) - (let ((where (string-match "[ \t]" string))) - (cond ((null where) (list string)) - ((not (= where 0)) - (cons (substring string 0 where) - (inferior-caml-args-to-list (substring string (+ 1 where) - (length string))))) - (t (let ((pos (string-match "[^ \t]" string))) - (if (null pos) - nil - (inferior-caml-args-to-list (substring string pos - (length string))))))))) - -(defun inferior-caml-show-subshell () - (interactive) - (caml-run-process-if-needed) - (display-buffer inferior-caml-buffer-name) - ; Added by Didier to move the point of inferior-caml to end of buffer - (let ((buf (current-buffer)) - (caml-buf (get-buffer inferior-caml-buffer-name)) - (count 0)) - (while - (and (< count 10) - (not (equal (buffer-name (current-buffer)) - inferior-caml-buffer-name))) - (next-multiframe-window) - (setq count (+ count 1))) - (if (equal (buffer-name (current-buffer)) - inferior-caml-buffer-name) - (goto-char (point-max))) - (while - (> count 0) - (previous-multiframe-window) - (setq count (- count 1))) - ) -) - -;; patched by Didier to move cursor after evaluation - -(defun inferior-caml-eval-region (start end) - "Send the current region to the inferior OCaml process." - (interactive "r") - (save-excursion (caml-run-process-if-needed)) - (save-excursion - (goto-char end) - (caml-skip-comments-backward) - (comint-send-region inferior-caml-buffer-name start (point)) - ;; normally, ";;" are part of the region - (if (and (>= (point) 2) - (prog2 (backward-char 2) (looking-at ";;"))) - (comint-send-string inferior-caml-buffer-name "\n") - (comint-send-string inferior-caml-buffer-name ";;\n")) - ;; the user may not want to see the output buffer - (if caml-display-when-eval - (display-buffer inferior-caml-buffer-name t)))) - -;; jump to errors produced by ocaml compiler - -(defun inferior-caml-goto-error (start end) - "Jump to the location of the last error as indicated by inferior toplevel." - (interactive "r") - (let ((loc (+ start - (save-excursion - (set-buffer (get-buffer inferior-caml-buffer-name)) - (re-search-backward - (concat comint-prompt-regexp - "[ \t]*Characters[ \t]+\\([0-9]+\\)-[0-9]+:$")) - (caml-string-to-int (match-string 1)))))) - (goto-char loc))) - - -;;; original inf-caml.el ended here - -;; as eval-phrase, but ignores errors. - -(defun inferior-caml-just-eval-phrase (arg &optional min max) - "Send the phrase containing the point to the CAML process. -With prefix-arg send as many phrases as its numeric value, -ignoring possible errors during evaluation. - -Optional arguments min max defines a region within which the phrase -should lies." - (interactive "p") - (let ((beg)) - (while (> arg 0) - (setq arg (- arg 1)) - (setq beg (caml-find-phrase min max)) - (caml-eval-region beg (point))) - beg)) - -(defvar caml-previous-output nil - "Tells the beginning of output in the shell-output buffer, so that the -output can be retrieved later, asynchronously.") - -;; enriched version of eval-phrase, to report errors. - -(defun inferior-caml-eval-phrase (arg &optional min max) - "Send the phrase containing the point to the CAML process. -With prefix-arg send as many phrases as its numeric value, -If an error occurs during evaluation, stop at this phrase and -report the error. - -Return nil if noerror and position of error if any. - -If arg's numeric value is zero or negative, evaluate the current phrase -or as many as prefix arg, ignoring evaluation errors. -This allows to jump other erroneous phrases. - -Optional arguments min max defines a region within which the phrase -should lies." - (interactive "p") - (if (save-excursion (caml-run-process-if-needed)) - (progn - (setq inferior-caml-output nil) - (caml-wait-output 10 1))) - (if (< arg 1) (inferior-caml-just-eval-phrase (max 1 (- 0 arg)) min max) - (let ((proc (get-buffer-process inferior-caml-buffer-name)) - (buf (current-buffer)) - previous-output orig beg end err) - (save-window-excursion - (while (and (> arg 0) (not err)) - (setq previous-output (marker-position (process-mark proc))) - (setq caml-previous-output previous-output) - (setq inferior-caml-output nil) - (setq orig (inferior-caml-just-eval-phrase 1 min max)) - (caml-wait-output) - (switch-to-buffer inferior-caml-buffer-name nil) - (goto-char previous-output) - (cond ((re-search-forward - " *Characters \\([01-9][01-9]*\\)-\\([1-9][01-9]*\\):\n[^W]" - (point-max) t) - (setq beg (caml-string-to-int (caml-match-string 1))) - (setq end (caml-string-to-int (caml-match-string 2))) - (switch-to-buffer buf) - (goto-char orig) - (forward-byte end) - (setq end (point)) - (goto-char orig) - (forward-byte beg) - (setq beg (point)) - (setq err beg) - ) - ((looking-at - "Toplevel input:\n[>]\\([^\n]*\\)\n[>]\\(\\( *\\)^*\\)\n") - (let ((expr (caml-match-string 1)) - (column (- (match-end 3) (match-beginning 3))) - (width (- (match-end 2) (match-end 3)))) - (if (string-match "^\\(.*\\)[<]EOF[>]$" expr) - (setq expr (substring expr (match-beginning 1) - (match-end 1)))) - (switch-to-buffer buf) - (re-search-backward - (concat "^" (regexp-quote expr) "$") - (- orig 10)) - (goto-char (+ (match-beginning 0) column)) - (setq end (+ (point) width))) - (setq err beg)) - ((looking-at - "Toplevel input:\n>[.]*\\([^.].*\n\\)\\([>].*\n\\)*[>]\\(.*[^.]\\)[.]*\n") - (let* ((e1 (caml-match-string 1)) - (e2 (caml-match-string 3)) - (expr - (concat - (regexp-quote e1) "\\(.*\n\\)*" (regexp-quote e2)))) - (switch-to-buffer buf) - (re-search-backward expr orig 'move) - (setq end (match-end 0))) - (setq err beg)) - (t - (switch-to-buffer buf))) - (setq arg (- arg 1)) - ) - (pop-to-buffer inferior-caml-buffer-name) - (if err - (goto-char (point-max)) - (goto-char previous-output) - (goto-char (point-max))) - (pop-to-buffer buf)) - (if err (progn (beep) (caml-overlay-region (point) end)) - (if inferior-caml-output - (message "No error") - (message "No output yet...") - )) - err))) - -(defun caml-overlay-region (beg end &optional wait) - (interactive "%r") - (cond ((fboundp 'make-overlay) - (if caml-error-overlay () - (setq caml-error-overlay (make-overlay 1 1)) - (overlay-put caml-error-overlay 'face 'region)) - (unwind-protect - (progn - (move-overlay caml-error-overlay beg end (current-buffer)) - (beep) (if wait (read-event) (caml-sit-for 60))) - (delete-overlay caml-error-overlay))))) - -;; wait some amount for output, that is, until inferior-caml-output is set -;; to true. Hence, interleaves sitting for shorts delays and checking the -;; flag. Give up after some time. Typing into the source buffer will cancel -;; waiting, i.e. may report 'No result yet' - -(defun caml-wait-output (&optional before after) - (let ((c 1)) - (caml-sit-for 0 (or before 1)) - (let ((c 1)) - (while (and (not inferior-caml-output) (< c 99) (caml-sit-for 0 c t)) - (setq c (+ c 1)))) - (caml-sit-for (or after 0) 1))) - -;; To insert the last output from caml at point -(defun caml-insert-last-output () - "Insert the result of the evaluation of previous phrase" - (interactive) - (let ((pos (process-mark (get-buffer-process inferior-caml-buffer-name)))) - (insert-buffer-substring inferior-caml-buffer-name - caml-previous-output (- pos 2)))) - -;; additional bindings - -;(let ((map (lookup-key caml-mode-map [menu-bar caml]))) -; (define-key map [indent-buffer] '("Indent buffer" . caml-indent-buffer)) -; (define-key map [eval-buffer] '("Eval buffer" . caml-eval-buffer)) -;) -;(define-key caml-mode-map "\C-c\C-b" 'caml-eval-buffer) - - -(provide 'inf-caml) diff --git a/emacs/ocamltags.in b/emacs/ocamltags.in deleted file mode 100644 index 4be9e79d..00000000 --- a/emacs/ocamltags.in +++ /dev/null @@ -1,141 +0,0 @@ -":" ; @EMACS@ -batch -l $0 "$@" ; status=$? ; : '--*-Emacs-Lisp-*--' <<';' - -;************************************************************************** -;* * -;* OCaml * -;* * -;* Jacques Garrigue and Ian T Zimmerman * -;* * -;* Copyright 1998 Institut National de Recherche en Informatique et * -;* en Automatique. * -;* * -;* All rights reserved. This file is distributed under the terms of * -;* the GNU General Public License. * -;* * -;************************************************************************** - -;; Copyright (C) 1998 Ian Zimmerman -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 2 of the -;; License, or (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -(require 'caml) - -;;itz Fri Oct 30 13:08:37 PST 1998 support for creating TAGS files -;; itz Sun Dec 27 10:26:08 PST 1998 adapted very slightly from -;; Jacques' caml-create-index-function -(defun caml-tags-create-index-function () - (let (all-alist index) - (goto-char (point-max)) - ;; collect definitions - (while (caml-prev-index-position-function) - (if (looking-at "[ \t]*val") nil - (setq index (cons (caml-match-string 5) (point))) - (setq all-alist (cons index all-alist)))) - all-alist)) - -(defun caml-tags-file (filename) - (let* ((output-buffer (current-buffer)) - (basename (file-name-nondirectory filename)) - (backpatch (prog2 - (insert " \n" basename) - (point)))) - (find-file-read-only filename) - (caml-mode) - (let ((all-alist (caml-tags-create-index-function)) - (done nil) - (current-line 1) - (last-point (point-min))) - (mapcar - (lambda (pair) - (let ((tag-name (car pair)) (tag-pos (cdr pair))) - (goto-char tag-pos) - (setq current-line - (+ current-line (count-lines last-point (point)))) - (setq last-point (point)) - (end-of-line 1) - (let ((output-line (format "%s%s%d,%d\n" - (buffer-substring last-point (point)) - tag-name current-line tag-pos))) - (save-excursion - (set-buffer output-buffer) - (insert output-line))))) - all-alist)) - (kill-buffer (current-buffer)) - (set-buffer output-buffer) - (let ((index-size (- (point) backpatch))) - (goto-char backpatch) - (insert "," (int-to-string index-size) "\n") - (goto-char (point-max))))) - -(defsubst prefix-p (prefix str) - (and (<= (length prefix) (length str)) - (string= prefix (substring str 0 (length prefix))))) - -(defsubst eat-args (n) - (setq command-line-args-left (nthcdr n command-line-args-left))) - -;; see Emacs source file print.c -(defun print-error-message (data) - (let ((errname (car data)) errmsg is-file-error tail i) - (if (eq errname 'error) - (progn - (setq data (cdr data)) - (if (not (consp data)) (setq data nil)) - (setq errmsg (car data)) - (setq is-file-error nil)) - (setq errmsg (get errname 'error-message)) - (setq is-file-error (memq 'file-error (get errname 'error-conditions)))) - (setq tail (cdr-safe data)) - (if (and is-file-error tail) - (setq errmsg (car tail) tail (cdr tail))) - (if (stringp errmsg) (princ errmsg) - (princ "peculiar error")) - (setq i 0) - (while (consp tail) - (princ (if (eq i 0) ": " ", ")) - (if is-file-error (princ (car tail)) - (prin1 (car tail))) - (setq tail (cdr tail) i (1+ i))) - (princ "\n"))) - - -(setq gc-cons-threshold 1000000) - -(setq output-file "TAGS") -(setq append-flag nil) -(setq status 0) - -(condition-case foobar - (progn - (while (and command-line-args-left - (let ((arg (car command-line-args-left))) - (cond - ((prefix-p arg "-output-file") - (setq output-file (nth 1 command-line-args-left)) - (eat-args 2) t) - ((prefix-p arg "-append") - (setq append-flag t) - (eat-args 1) t) - (t nil))))) - - (find-file output-file) - (if append-flag (goto-char (point-max)) - (erase-buffer)) - (while command-line-args-left - (caml-tags-file (car command-line-args-left)) - (setq command-line-args-left (cdr command-line-args-left))) - (save-buffer 0)) - (error (setq status 1) (print-error-message foobar))) - -(kill-emacs status) - -; - -":" ; exit $status diff --git a/lex/.depend b/lex/.depend index 4c22eeb9..d6835394 100644 --- a/lex/.depend +++ b/lex/.depend @@ -1,34 +1,118 @@ -common.cmo : syntax.cmi lexgen.cmi common.cmi -common.cmx : syntax.cmx lexgen.cmx common.cmi -common.cmi : syntax.cmi lexgen.cmi -compact.cmo : table.cmi lexgen.cmi compact.cmi -compact.cmx : table.cmx lexgen.cmx compact.cmi -compact.cmi : lexgen.cmi -cset.cmo : cset.cmi -cset.cmx : cset.cmi +common.cmo : \ + syntax.cmi \ + lexgen.cmi \ + common.cmi +common.cmx : \ + syntax.cmx \ + lexgen.cmx \ + common.cmi +common.cmi : \ + syntax.cmi \ + lexgen.cmi +compact.cmo : \ + table.cmi \ + lexgen.cmi \ + compact.cmi +compact.cmx : \ + table.cmx \ + lexgen.cmx \ + compact.cmi +compact.cmi : \ + lexgen.cmi +cset.cmo : \ + cset.cmi +cset.cmx : \ + cset.cmi cset.cmi : -lexer.cmo : syntax.cmi parser.cmi lexer.cmi -lexer.cmx : syntax.cmx parser.cmx lexer.cmi -lexer.cmi : parser.cmi -lexgen.cmo : table.cmi syntax.cmi cset.cmi lexgen.cmi -lexgen.cmx : table.cmx syntax.cmx cset.cmx lexgen.cmi -lexgen.cmi : syntax.cmi -main.cmo : syntax.cmi parser.cmi outputbis.cmi output.cmi lexgen.cmi \ - lexer.cmi cset.cmi compact.cmi common.cmi -main.cmx : syntax.cmx parser.cmx outputbis.cmx output.cmx lexgen.cmx \ - lexer.cmx cset.cmx compact.cmx common.cmx -output.cmo : lexgen.cmi compact.cmi common.cmi output.cmi -output.cmx : lexgen.cmx compact.cmx common.cmx output.cmi -output.cmi : syntax.cmi lexgen.cmi compact.cmi common.cmi -outputbis.cmo : lexgen.cmi common.cmi outputbis.cmi -outputbis.cmx : lexgen.cmx common.cmx outputbis.cmi -outputbis.cmi : syntax.cmi lexgen.cmi common.cmi -parser.cmo : syntax.cmi cset.cmi parser.cmi -parser.cmx : syntax.cmx cset.cmx parser.cmi -parser.cmi : syntax.cmi -syntax.cmo : cset.cmi syntax.cmi -syntax.cmx : cset.cmx syntax.cmi -syntax.cmi : cset.cmi -table.cmo : table.cmi -table.cmx : table.cmi +lexer.cmo : \ + syntax.cmi \ + parser.cmi \ + lexer.cmi +lexer.cmx : \ + syntax.cmx \ + parser.cmx \ + lexer.cmi +lexer.cmi : \ + parser.cmi +lexgen.cmo : \ + table.cmi \ + syntax.cmi \ + cset.cmi \ + lexgen.cmi +lexgen.cmx : \ + table.cmx \ + syntax.cmx \ + cset.cmx \ + lexgen.cmi +lexgen.cmi : \ + syntax.cmi +main.cmo : \ + syntax.cmi \ + parser.cmi \ + outputbis.cmi \ + output.cmi \ + lexgen.cmi \ + lexer.cmi \ + cset.cmi \ + compact.cmi \ + common.cmi +main.cmx : \ + syntax.cmx \ + parser.cmx \ + outputbis.cmx \ + output.cmx \ + lexgen.cmx \ + lexer.cmx \ + cset.cmx \ + compact.cmx \ + common.cmx +output.cmo : \ + lexgen.cmi \ + compact.cmi \ + common.cmi \ + output.cmi +output.cmx : \ + lexgen.cmx \ + compact.cmx \ + common.cmx \ + output.cmi +output.cmi : \ + syntax.cmi \ + lexgen.cmi \ + compact.cmi \ + common.cmi +outputbis.cmo : \ + lexgen.cmi \ + common.cmi \ + outputbis.cmi +outputbis.cmx : \ + lexgen.cmx \ + common.cmx \ + outputbis.cmi +outputbis.cmi : \ + syntax.cmi \ + lexgen.cmi \ + common.cmi +parser.cmo : \ + syntax.cmi \ + cset.cmi \ + parser.cmi +parser.cmx : \ + syntax.cmx \ + cset.cmx \ + parser.cmi +parser.cmi : \ + syntax.cmi +syntax.cmo : \ + cset.cmi \ + syntax.cmi +syntax.cmx : \ + cset.cmx \ + syntax.cmi +syntax.cmi : \ + cset.cmi +table.cmo : \ + table.cmi +table.cmx : \ + table.cmi table.cmi : diff --git a/lex/Makefile b/lex/Makefile index 5e3848fb..6c0d8a93 100644 --- a/lex/Makefile +++ b/lex/Makefile @@ -14,40 +14,40 @@ #************************************************************************** # The lexer generator -include ../config/Makefile -CAMLRUN ?= ../boot/ocamlrun -CAMLYACC ?= ../boot/ocamlyacc -ROOTDIR=.. +ROOTDIR = .. -ifeq "$(wildcard $(ROOTDIR)/flexdll/Makefile)" "" -export OCAML_FLEXLINK:= -else -export OCAML_FLEXLINK:=$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/flexdll/flexlink.exe -endif +include $(ROOTDIR)/Makefile.config +include $(ROOTDIR)/Makefile.common -CAMLC=$(CAMLRUN) ../boot/ocamlc -strict-sequence -nostdlib -I ../boot \ - -use-prims ../byterun/primitives -CAMLOPT=$(CAMLRUN) ../ocamlopt -nostdlib -I ../stdlib -COMPFLAGS=$(INCLUDES) -absname -w +a-4-9-41-42-44-45-48 -warn-error A \ - -safe-string -strict-sequence -strict-formats -bin-annot -LINKFLAGS= -YACCFLAGS=-v -CAMLLEX=$(CAMLRUN) ../boot/ocamllex -CAMLDEP=$(CAMLRUN) ../tools/ocamldep +CAMLRUN ?= $(ROOTDIR)/boot/ocamlrun +CAMLYACC ?= $(ROOTDIR)/yacc/ocamlyacc +CAMLC = $(CAMLRUN) $(ROOTDIR)/boot/ocamlc -strict-sequence -nostdlib \ + -I $(ROOTDIR)/boot -use-prims $(ROOTDIR)/runtime/primitives +CAMLOPT = $(CAMLRUN) $(ROOTDIR)/ocamlopt -nostdlib -I $(ROOTDIR)/stdlib +COMPFLAGS = $(INCLUDES) -absname -w +a-4-9-41-42-44-45-48 -warn-error A \ + -safe-string -strict-sequence -strict-formats -bin-annot +LINKFLAGS = +YACCFLAGS = -v +CAMLLEX = $(CAMLRUN) $(ROOTDIR)/boot/ocamllex +CAMLDEP = $(CAMLRUN) $(ROOTDIR)/boot/ocamlc -depend +DEPFLAGS = -slash +DEPINCLUDES = OBJS=cset.cmo syntax.cmo parser.cmo lexer.cmo table.cmo lexgen.cmo \ compact.cmo common.cmo output.cmo outputbis.cmo main.cmo +.PHONY: all allopt opt.opt # allopt and opt.opt are synonyms all: ocamllex allopt: ocamllex.opt +opt.opt: allopt ocamllex: $(OBJS) $(CAMLC) $(LINKFLAGS) -compat-32 -o ocamllex $(OBJS) ocamllex.opt: $(OBJS:.cmo=.cmx) - $(CAMLOPT) -o ocamllex.opt $(OBJS:.cmo=.cmx) + $(CAMLOPT_CMD) -o ocamllex.opt $(OBJS:.cmo=.cmx) clean:: rm -f ocamllex ocamllex.opt @@ -82,6 +82,6 @@ beforedepend:: lexer.ml $(CAMLOPT) -c $(COMPFLAGS) $< depend: beforedepend - $(CAMLDEP) -slash *.mli *.ml > .depend + $(CAMLDEP) $(DEPFLAGS) $(DEPINCLUDES) *.mli *.ml > .depend include .depend diff --git a/lex/Makefile.nt b/lex/Makefile.nt deleted file mode 100644 index ed9900bb..00000000 --- a/lex/Makefile.nt +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include Makefile diff --git a/lex/common.ml b/lex/common.ml index 5024c829..82f74eda 100644 --- a/lex/common.ml +++ b/lex/common.ml @@ -135,7 +135,7 @@ let output_env ic oc tr env = let env = List.sort (fun ((_,p1),_) ((_,p2),_) -> - Pervasives.compare p1.start_pos p2.start_pos) + Stdlib.compare p1.start_pos p2.start_pos) env in List.iter diff --git a/lex/lexer.mll b/lex/lexer.mll index 748f5e16..ac63aa08 100644 --- a/lex/lexer.mll +++ b/lex/lexer.mll @@ -33,6 +33,7 @@ let string_buff = Buffer.create 256 let reset_string_buffer () = Buffer.clear string_buff let store_string_char c = Buffer.add_char string_buff c +let store_string_uchar u = Buffer.add_utf_8_uchar string_buff u let store_string_chars s = Buffer.add_string string_buff s let get_stored_string () = Buffer.contents string_buff @@ -70,21 +71,31 @@ let warning lexbuf msg = (p.Lexing.pos_cnum - p.Lexing.pos_bol + 1) msg; flush stderr -let decimal_code c d u = +let hex_digit_value d = + let d = Char.code d in + if d >= 97 then d - 87 else + if d >= 65 then d - 55 else + d - 48 + +let decimal_code c d u = 100 * (Char.code c - 48) + 10 * (Char.code d - 48) + (Char.code u - 48) +let hexadecimal_code s = + let rec loop acc i = + if i < String.length s then + let value = hex_digit_value s.[i] in + loop (16 * acc + value) (i + 1) + else acc in + loop 0 0 + +let char_for_octal_code c d u = + let c = 64 * (Char.code c - 48) + + 8 * (Char.code d - 48) + + (Char.code u - 48) in + Char.chr c + let char_for_hexadecimal_code d u = - let d1 = Char.code d in - let val1 = if d1 >= 97 then d1 - 87 - else if d1 >= 65 then d1 - 55 - else d1 - 48 - in - let d2 = Char.code u in - let val2 = if d2 >= 97 then d2 - 87 - else if d2 >= 65 then d2 - 55 - else d2 - 48 - in - Char.chr (val1 * 16 + val2) + Char.chr (16 * (hex_digit_value d) + (hex_digit_value u)) let incr_loc lexbuf delta = let pos = lexbuf.Lexing.lex_curr_p in @@ -160,6 +171,8 @@ rule main = parse (Printf.sprintf "illegal escape sequence \\%c%c%c" c d u) else Tchar v } + | "'" '\\' 'o' (['0'-'3'] as c) (['0'-'7'] as d) (['0'-'7'] as u) "'" + { Tchar(Char.code(char_for_octal_code c d u)) } | "'" '\\' 'x' (['0'-'9' 'a'-'f' 'A'-'F'] as d) (['0'-'9' 'a'-'f' 'A'-'F'] as u) "'" { Tchar(Char.code(char_for_hexadecimal_code d u)) } @@ -200,7 +213,7 @@ rule main = parse and string = parse '"' { () } - | '\\' ('\013'* '\010') ([' ' '\009'] * as spaces) + | '\\' ('\013'* '\010') ([' ' '\009'] * as spaces) { incr_loc lexbuf (String.length spaces); string lexbuf } | '\\' (backslash_escapes as c) @@ -208,15 +221,30 @@ and string = parse string lexbuf } | '\\' (['0'-'9'] as c) (['0'-'9'] as d) (['0'-'9'] as u) { let v = decimal_code c d u in - if in_pattern () && v > 255 then - warning lexbuf - (Printf.sprintf - "illegal backslash escape in string: '\\%c%c%c'" c d u) ; - store_string_char (Char.chr v); + if in_pattern () then + if v > 255 then + raise_lexical_error lexbuf + (Printf.sprintf + "illegal backslash escape in string: '\\%c%c%c'" c d u) + else + store_string_char (Char.chr v); + string lexbuf } + | '\\' 'o' (['0'-'3'] as c) (['0'-'7'] as d) (['0'-'7'] as u) + { store_string_char (char_for_octal_code c d u); string lexbuf } - | '\\' 'x' (['0'-'9' 'a'-'f' 'A'-'F'] as d) (['0'-'9' 'a'-'f' 'A'-'F'] as u) + | '\\' 'x' (['0'-'9' 'a'-'f' 'A'-'F'] as d) (['0'-'9' 'a'-'f' 'A'-'F'] as u) { store_string_char (char_for_hexadecimal_code d u) ; string lexbuf } + | '\\' 'u' '{' (['0'-'9' 'a'-'f' 'A'-'F'] + as s) '}' + { let v = hexadecimal_code s in + if in_pattern () then + if not (Uchar.is_valid v) then + raise_lexical_error lexbuf + (Printf.sprintf + "illegal uchar escape in string: '\\u{%s}'" s) + else + store_string_uchar (Uchar.unsafe_of_int v); + string lexbuf } | '\\' (_ as c) {if in_pattern () then warning lexbuf @@ -236,10 +264,22 @@ and string = parse { store_string_char c; string lexbuf } +and quoted_string delim = parse + | '\013'* '\010' + { incr_loc lexbuf 0; + quoted_string delim lexbuf } + | eof + { raise (Lexical_error ("unterminated string", "", 0, 0)) } + | '|' (['a'-'z' '_'] * as delim') '}' + { if delim <> delim' then + quoted_string delim lexbuf } + | _ + { quoted_string delim lexbuf } + (* - Lexers comment and action are quite similar, - they should lex both strings and characters, - in order not to be confused by what is inside then + Lexers comment and action are quite similar. + They should lex strings, quoted strings and characters, + in order not to be confused by what is inside them. *) and comment = parse @@ -253,6 +293,9 @@ and comment = parse string lexbuf; reset_string_buffer(); comment lexbuf } + | '{' (['a'-'z' '_'] * as delim) '|' + { quoted_string delim lexbuf; + comment lexbuf } | "'" { skip_char lexbuf ; comment lexbuf } @@ -261,6 +304,8 @@ and comment = parse | '\010' { incr_loc lexbuf 0; comment lexbuf } + | identstart identbody * + { comment lexbuf } | _ { comment lexbuf } @@ -276,10 +321,13 @@ and action = parse handle_lexical_error string lexbuf; reset_string_buffer(); action lexbuf } - | "'" + | '{' (['a'-'z' '_'] * as delim) '|' + { quoted_string delim lexbuf; + action lexbuf } + | "'" { skip_char lexbuf ; action lexbuf } - | "(*" + | "(*" { comment_depth := 1; comment lexbuf; action lexbuf } @@ -288,17 +336,20 @@ and action = parse | '\010' { incr_loc lexbuf 0; action lexbuf } + | identstart identbody * + { action lexbuf } | _ { action lexbuf } and skip_char = parse - | '\\'? '\010' "'" + | '\\'? ('\013'* '\010') "'" { incr_loc lexbuf 1; } - | [^ '\\' '\''] "'" (* regular character *) + | [^ '\\' '\'' '\010' '\013'] "'" (* regular character *) (* one character and numeric escape sequences *) | '\\' _ "'" | '\\' ['0'-'9'] ['0'-'9'] ['0'-'9'] "'" + | '\\' 'o' ['0'-'7'] ['0'-'7'] ['0'-'7'] "'" | '\\' 'x' ['0'-'9' 'a'-'f' 'A'-'F'] ['0'-'9' 'a'-'f' 'A'-'F'] "'" {()} (* Perilous *) diff --git a/lex/lexgen.ml b/lex/lexgen.ml index ac3751cd..184a8066 100644 --- a/lex/lexgen.ml +++ b/lex/lexgen.ml @@ -85,7 +85,7 @@ module Ints = let id_compare (id1,_) (id2,_) = String.compare id1 id2 -let tag_compare t1 t2 = Pervasives.compare t1 t2 +let tag_compare t1 t2 = Stdlib.compare t1 t2 module Tags = Set.Make(struct type t = tag_info let compare = tag_compare end) @@ -528,7 +528,7 @@ type t_transition = type transition = t_transition * Tags.t let trans_compare (t1,tags1) (t2,tags2) = - match Pervasives.compare t1 t2 with + match Stdlib.compare t1 t2 with | 0 -> Tags.compare tags1 tags2 | r -> r @@ -606,12 +606,12 @@ let followpos size entry_list = let no_action = max_int module StateSet = - Set.Make (struct type t = t_transition let compare = Pervasives.compare end) + Set.Make (struct type t = t_transition let compare = Stdlib.compare end) module MemMap = Map.Make (struct type t = int - let compare (x:t) y = Pervasives.compare x y end) + let compare (x:t) y = Stdlib.compare x y end) type 'a dfa_state = {final : int * ('a * int TagMap.t) ; @@ -672,7 +672,7 @@ module MemKey = (struct type t = t_equiv - let compare e1 e2 = match Pervasives.compare e1.tag e2.tag with + let compare e1 e2 = match Stdlib.compare e1.tag e2.tag with | 0 -> StateSetSet.compare e1.equiv e2.equiv | r -> r end) diff --git a/lex/main.ml b/lex/main.ml index fd01325d..3155a38a 100644 --- a/lex/main.ml +++ b/lex/main.ml @@ -88,6 +88,7 @@ let main () = close_out oc; Common.close_tracker tr; with exn -> + let bt = Printexc.get_raw_backtrace () in close_in ic; close_out oc; Common.close_tracker tr; @@ -118,7 +119,7 @@ let main () = "File \"%s\":\ntransition table overflow, automaton is too big\n" source_name | _ -> - raise exn + Printexc.raise_with_backtrace exn bt end; exit 3 diff --git a/lex/output.ml b/lex/output.ml index 9716a2aa..d5ce76eb 100644 --- a/lex/output.ml +++ b/lex/output.ml @@ -72,15 +72,18 @@ let output_tables oc tbl = (* Output the entries *) -let output_entry ic oc has_refill oci e = +let output_entry some_mem_code ic oc has_refill oci e = let init_num, init_moves = e.auto_initial_state in + (* Will use "memory" instructions when (1) some memory instructions are + here and (2) this entry point needs memory. *) + let some_mem_code = some_mem_code && e.auto_mem_size > 0 in fprintf oc "%s %alexbuf =\ \n %a%a __ocaml_lex_%s_rec %alexbuf %d\n" e.auto_name output_args e.auto_args (fun oc x -> - if x > 0 then + if some_mem_code then fprintf oc "lexbuf.Lexing.lex_mem <- Array.make %d (-1);" x) e.auto_mem_size (output_memory_actions " ") init_moves @@ -90,7 +93,7 @@ let output_entry ic oc has_refill oci e = fprintf oc "and __ocaml_lex_%s_rec %alexbuf __ocaml_lex_state =\n" e.auto_name output_args e.auto_args; fprintf oc " match Lexing.%sengine" - (if e.auto_mem_size == 0 then "" else "new_"); + (if some_mem_code then "new_" else ""); fprintf oc " __ocaml_lex_tables __ocaml_lex_state lexbuf with\n "; List.iter (fun (num, env, loc) -> @@ -138,15 +141,16 @@ let output_lexdef ic oc oci header rh tables entry_points trailer = copy_chunk ic oc oci header false; let has_refill = output_refill_handler ic oc oci rh in output_tables oc tables; + let some_mem_code = Array.length tables.tbl_code > 0 in begin match entry_points with [] -> () | entry1 :: entries -> output_string oc "let rec "; - output_entry ic oc has_refill oci entry1; + output_entry some_mem_code ic oc has_refill oci entry1; List.iter (fun e -> output_string oc "and "; - output_entry ic oc has_refill oci e) + output_entry some_mem_code ic oc has_refill oci e) entries; output_string oc ";;\n\n"; end; diff --git a/lex/outputbis.ml b/lex/outputbis.ml index 37ff25b0..97740b04 100644 --- a/lex/outputbis.ml +++ b/lex/outputbis.ml @@ -31,7 +31,8 @@ let pr ctx = fprintf ctx.oc let output_auto_defs ctx = if ctx.has_refill then begin pr ctx "\n"; - pr ctx "let rec __ocaml_lex_refill_buf lexbuf _buf _len _curr _last _last_action state k =\n"; + pr ctx "let rec __ocaml_lex_refill_buf lexbuf _buf _len _curr _last \ + _last_action state k =\n"; pr ctx " if lexbuf.Lexing.lex_eof_reached then\n"; pr ctx " state lexbuf _last_action _buf _len _curr _last k 256\n"; pr ctx " else begin\n"; @@ -44,10 +45,12 @@ let output_auto_defs ctx = pr ctx " let _len = lexbuf.Lexing.lex_buffer_len in\n"; pr ctx " let _buf = lexbuf.Lexing.lex_buffer in\n"; pr ctx " if _curr < _len then\n"; - pr ctx " state lexbuf _last_action _buf _len (_curr + 1) _last k\n"; + pr ctx " state lexbuf _last_action _buf _len (_curr + 1) \ + _last k\n"; pr ctx " (Char.code (Bytes.unsafe_get _buf _curr))\n"; pr ctx " else\n"; - pr ctx " __ocaml_lex_refill_buf lexbuf _buf _len _curr _last _last_action\n"; + pr ctx " __ocaml_lex_refill_buf lexbuf _buf _len _curr _last \ + _last_action\n"; pr ctx " state k\n"; pr ctx " )\n"; pr ctx " lexbuf\n"; @@ -67,7 +70,8 @@ let output_auto_defs ctx = pr ctx " let _len = lexbuf.Lexing.lex_buffer_len in\n"; pr ctx " let _buf = lexbuf.Lexing.lex_buffer in\n"; pr ctx " if _curr < _len then\n"; - pr ctx " Char.code (Bytes.unsafe_get _buf _curr), _buf, _len, (_curr + 1), _last\n"; + pr ctx " Char.code (Bytes.unsafe_get _buf _curr), _buf, _len, \ + (_curr + 1), _last\n"; pr ctx " else\n"; pr ctx " __ocaml_lex_refill_buf lexbuf _buf _len _curr _last\n"; pr ctx " end\n"; @@ -220,7 +224,8 @@ let output_trans_body pref ctx = function output_moves ctx pref move; pr ctx "%sin\n\ %sif _curr >= _len then\n\ - %s __ocaml_lex_refill_buf lexbuf _buf _len _curr _last _last_action state k\n\ + %s __ocaml_lex_refill_buf lexbuf _buf _len _curr _last \ + _last_action state k\n\ %selse\n\ %s state lexbuf _last_action _buf _len (_curr + 1) _last k\n\ %s (Char.code (Bytes.unsafe_get _buf _curr))\n" @@ -279,7 +284,8 @@ let output_rules ic ctx pref tr e = pr ctx "%s lexbuf.Lexing.lex_start_p <- _curr_p;\n" pref; pr ctx "%s lexbuf.Lexing.lex_curr_p <-\n" pref; pr ctx "%s {_curr_p with Lexing.pos_cnum =\n" pref; - pr ctx "%s lexbuf.Lexing.lex_abs_pos+lexbuf.Lexing.lex_curr_pos}\n" pref; + pr ctx "%s lexbuf.Lexing.lex_abs_pos+lexbuf.Lexing.lex_curr_pos}\n" + pref; pr ctx "%s end\n" pref; pr ctx "%send;\n" pref; pr ctx "%smatch __ocaml_lex_result with\n" pref; diff --git a/man/Makefile b/man/Makefile index 2b678d83..179d7421 100644 --- a/man/Makefile +++ b/man/Makefile @@ -13,7 +13,8 @@ #* * #************************************************************************** -include ../config/Makefile +ROOTDIR = .. +include $(ROOTDIR)/Makefile.config INSTALL_DIR=$(DESTDIR)$(MANDIR)/man$(PROGRAMS_MAN_SECTION) diff --git a/man/ocaml.m b/man/ocaml.m index edfc2b6b..7d436e69 100644 --- a/man/ocaml.m +++ b/man/ocaml.m @@ -239,6 +239,49 @@ option. See for the syntax of the .I warning\-list argument. +.TP +.BI \-color \ mode +Enable or disable colors in compiler messages (especially warnings and errors). +The following modes are supported: + +.B auto +use heuristics to enable colors only if the output supports them (an +ANSI-compatible tty terminal); + +.B always +enable colors unconditionally; + +.B never +disable color output. + +The default setting is +.B auto, +and the current heuristic +checks that the "TERM" environment variable exists and is +not empty or "dumb", and that isatty(stderr) holds. + +The environment variable "OCAML_COLOR" is considered if \-color is not +provided. Its values are auto/always/never as above. + +.TP +.BI \-error\-style \ mode +Control the way error messages and warnings are printed. +The following modes are supported: + +.B short +only print the error and its location; + +.B contextual +like "short", but also display the source code snippet corresponding +to the location of the error. + +The default setting is +.B contextual. + +The environment variable "OCAML_ERROR_STYLE" is considered if +\-error\-style is not provided. Its values are short/contextual as +above. + .TP .B \-warn\-help Show the description of all available warning numbers. diff --git a/man/ocamlc.m b/man/ocamlc.m index 810e821a..c3744fda 100644 --- a/man/ocamlc.m +++ b/man/ocamlc.m @@ -285,6 +285,25 @@ not empty or "dumb", and that isatty(stderr) holds. The environment variable "OCAML_COLOR" is considered if \-color is not provided. Its values are auto/always/never as above. +.TP +.BI \-error\-style \ mode +Control the way error messages and warnings are printed. +The following modes are supported: + +.B short +only print the error and its location; + +.B contextual +like "short", but also display the source code snippet corresponding +to the location of the error. + +The default setting is +.B contextual. + +The environment variable "OCAML_ERROR_STYLE" is considered if +\-error\-style is not provided. Its values are short/contextual as +above. + .TP .B \-compat\-32 Check that the generated bytecode executable can run on 32-bit @@ -296,6 +315,13 @@ Print the version number of .BR ocamlc (1) and a detailed summary of its configuration, then exit. .TP +.BI \-config-var +Print the value of a specific configuration variable +from the +.B \-config +output, then exit. If the variable does not exist, +the exit code is non-zero. +.TP .B \-custom Link in "custom runtime" mode. In the default linking mode, the linker produces bytecode that is intended to be executed with the @@ -452,6 +478,11 @@ bytecode executables produced with the option .B ocamlc\ \-use\-runtime .IR runtime-name . .TP +.B \-match\-context\-rows +Set number of rows of context used during pattern matching +compilation. Lower values cause faster compilation, but +less optimized code. The default value is 32. +.TP .B \-no-alias-deps Do not record dependencies for module aliases. .TP @@ -608,6 +639,12 @@ then the .B d suffix is supported and gives a debug version of the runtime. .TP +.BI \-stop\-after \ pass +Stop compilation after the given compilation pass. The currently +supported passes are: +.BR parsing , +.BR typing . +.TP .B \-safe\-string Enforce the separation between types .BR string \ and\ bytes , @@ -667,8 +704,8 @@ invocations of the C compiler and linker in mode. Useful to debug C library problems. .TP .B \-vmthread -Compile or link multithreaded programs, in combination with the -VM-level threads library described in +Deprecated since OCaml 4.08.0. Compile or link multithreaded programs, +in combination with the VM-level threads library described in .IR The\ OCaml\ user's\ manual . .TP .BR \-vnum \ or\ \-version @@ -927,6 +964,21 @@ mutually recursive types. 61 \ \ Unannotated unboxable type in primitive declaration. +62 +\ \ Type constraint on GADT type declaration + +63 +\ \ Erroneous printed signature + +64 +\ \ -unsafe used with a preprocessor returning a syntax tree + +65 +\ \ Type declaration defining a new '()' constructor + +66 +\ \ Unused open! statement. + The letters stand for the following sets of warnings. Any letter not mentioned here corresponds to the empty set. @@ -980,7 +1032,7 @@ mentioned here corresponds to the empty set. .IP The default setting is -.BR \-w\ +a\-4\-6\-7\-9\-27\-29\-32..42\-44\-45\-48\-50\-60 . +.BR \-w\ +a\-4\-6\-7\-9\-27\-29\-32..42\-44\-45\-48\-50\-60\-66 . Note that warnings .BR 5 \ and \ 10 are not always triggered, depending on the internals of the type checker. diff --git a/man/ocamldep.m b/man/ocamldep.m index b9b58b9a..98d1b273 100644 --- a/man/ocamldep.m +++ b/man/ocamldep.m @@ -158,17 +158,17 @@ following files. .BI \-plugin \ plugin Dynamically load the code of the given .I plugin -(a .cmo, .cma or .cmxs file) in +(a .cmo, .cma or .cmxs file) in .BR ocamldep (1). The plugin must exist in the same kind of code as the tool ( -.BR ocamldep.byte +.BR ocamldep.byte must load bytecode -plugins, while +plugins, while .BR ocamldep.opt must load native code plugins), and extension adaptation is done automatically for .cma files (to .cmxs files -if +if .BR ocamldep (1) is compiled in native code). .TP diff --git a/man/ocamldoc.m b/man/ocamldoc.m index 01c05bb8..7cc09484 100644 --- a/man/ocamldoc.m +++ b/man/ocamldoc.m @@ -115,7 +115,7 @@ displaying and processing by The .IR dot (1) tool is available from -.IR http://www.research.att.com/sw/tools/graphviz/ . +.IR https://graphviz.org/ . The textual representation of the graph is written to the file .IR ocamldoc.out , or to the file specified with the @@ -236,6 +236,11 @@ This option is meaningful only in conjunction with the .BR \-latex , \ \-texi ,\ or \ \-dot options. .TP +.BI \-open \ module +Opens +.I module +before typing. +.TP .BI \-pp \ command Pipe sources through preprocessor .IR command . diff --git a/man/ocamlopt.m b/man/ocamlopt.m index 9bd34f4f..9ba40a23 100644 --- a/man/ocamlopt.m +++ b/man/ocamlopt.m @@ -241,6 +241,25 @@ not empty or "dumb", and that isatty(stderr) holds. The environment variable "OCAML_COLOR" is considered if \-color is not provided. Its values are auto/always/never as above. +.TP +.BI \-error\-style \ mode +Control the way error messages and warnings are printed. +The following modes are supported: + +.B short +only print the error and its location; + +.B contextual +like "short", but also display the source code snippet corresponding +to the location of the error. + +The default setting is +.B contextual. + +The environment variable "OCAML_ERROR_STYLE" is considered if +\-error\-style is not provided. Its values are short/contextual as +above. + .TP .B \-compact Optimize the produced code for space rather than for time. This @@ -252,6 +271,13 @@ Print the version number of .BR ocamlopt (1) and a detailed summary of its configuration, then exit. .TP +.BI \-config-var +Print the value of a specific configuration variable +from the +.B \-config +output, then exit. If the variable does not exist, +the exit code is non-zero. +.TP .BI \-depend\ ocamldep-args Compute dependencies, as ocamldep would do. .TP @@ -366,6 +392,11 @@ than with the usual graph coloring allocator, sometimes quite drastically so for long functions and modules. On the other hand, the generated code can be a bit slower. .TP +.B \-match\-context\-rows +Set number of rows of context used during pattern matching +compilation. Lower values cause faster compilation, but +less optimized code. The default value is 32. +.TP .B \-no-alias-deps Do not record dependencies for module aliases. .TP @@ -396,7 +427,7 @@ Allow the compiler to use some optimizations that are valid only for code that is never dynlinked. .TP .B -nostdlib -Do not automatically add the standard library directory the list of +Do not automatically add the standard library directory to the list of directories searched for compiled interface files (.cmi), compiled object code files (.cmx), and libraries (.cmxa). See also option .BR \-I . @@ -557,6 +588,12 @@ code for the source file is saved in the file .IR x .s. .TP +.BI \-stop\-after \ pass +Stop compilation after the given compilation pass. The currently +supported passes are: +.BR parsing , +.BR typing . +.TP .B \-safe\-string Enforce the separation between types .BR string \ and\ bytes , diff --git a/man/ocamlrun.m b/man/ocamlrun.m index 737ac696..eb44f830 100644 --- a/man/ocamlrun.m +++ b/man/ocamlrun.m @@ -125,6 +125,7 @@ last six correspond to the fields of the record documented in .IR "The OCaml user's manual", chapter "Standard Library", section "Gc". +\" FIXME missing: c, H, t, w, W see MPR#7870 .TP .B b Trigger the printing of a stack backtrace @@ -168,6 +169,42 @@ The heap compaction trigger setting. .BR l \ (stack_limit) The limit (in words) of the stack size. .TP +.BR M \ (custom_major_ratio) +Target ratio of floating garbage to +major heap size for out-of-heap memory held by custom values +located in the major heap. The GC speed is adjusted +to try to use this much memory for dead values that are not yet +collected. Expressed as a percentage of major heap size. +The default value keeps the out-of-heap floating garbage about the +same size as the in-heap overhead. +Note: this only applies to values allocated with +.B caml_alloc_custom_mem +(e.g. bigarrays). +Default: 44. +.TP +.BR m \ (custom_minor_ratio) +Bound on floating garbage for out-of-heap memory +held by custom values in the minor heap. A minor GC is triggered +when this much memory is held by custom values located in the minor +heap. Expressed as a percentage of minor heap size. +Note: this only applies to values allocated with +.B caml_alloc_custom_mem +(e.g. bigarrays). + Default: 100. +.TP +.BR n \ (custom_minor_max_size) +Maximum amount of out-of-heap +memory for each custom value allocated in the minor heap. When a custom +value is allocated on the minor heap and holds more than this many +bytes, only this value is counted against +.B custom_minor_ratio +and the rest is directly counted against +.BR custom_major_ratio . +Note: this only applies to values allocated with +.B caml_alloc_custom_mem +(e.g. bigarrays). +Default: 8192 bytes. +.TP .BR v \ (verbose) What GC messages to print to stderr. This is a sum of values selected from the following: diff --git a/manual/Makefile b/manual/Makefile index d866494d..0ccbf188 100644 --- a/manual/Makefile +++ b/manual/Makefile @@ -1,32 +1,42 @@ -all: tools - cd manual; ${MAKE} all - ${MAKE} tests -# cd fpcl; ${MAKE} all +all: tools manual tests -clean: - cd manual; ${MAKE} clean - cd tools; ${MAKE} clean -# cd fpcl; ${MAKE} clean -release: - cd manual; ${MAKE} release -# cd fpcl; ${MAKE} release +# The tools and the tests are rebuilt each time in order to avoid issues with +# different compiler versions +tests: manual + $(MAKE) -C tests clean + $(MAKE) -C tests all -.PHONY: tools tools: - cd tools; ${MAKE} clean; ${MAKE} all + $(MAKE) -C tools clean + $(MAKE) -C tools all + $(MAKE) -C tests tools + +manual: tools + $(MAKE) -C manual all + +html: tools + $(MAKE) -C manual html + +release: + $(MAKE) -C manual release # The pregen-etex target generates the latex files from the .etex # files to ensure that this phase of the manual build process, which # may execute OCaml fragments and expect certain outputs, is correct pregen-etex: tools - cd manual; $(MAKE) etex-files + $(MAKE) -C manual etex-files # pregen builds both .etex files and the documentation of the standard library pregen: tools - cd manual; $(MAKE) files + $(MAKE) -C manual files + + +.PHONY: tests manual tools -# test the consistency of the manual and the compiler source -.PHONY:tests -tests: - ${MAKE} -C tests all + +.PHONY: clean +clean: + $(MAKE) -C manual clean + $(MAKE) -C tools clean + $(MAKE) -C tests clean diff --git a/manual/README.md b/manual/README.md index 26f818c0..d3f9fcd1 100644 --- a/manual/README.md +++ b/manual/README.md @@ -6,11 +6,9 @@ Prerequisites - Any prerequisites required to build OCaml from sources. -- The Unix editor 'ed', no longer installed by default on some systems. - - A LaTeX installation. -- The HeVeA LaTeX-to-HTML convertor (available in OPAM): +- The HeVeA LaTeX-to-HTML converter (available in OPAM): Note that you must make sure `hevea.sty` is installed into TeX properly. Your @@ -39,9 +37,7 @@ In the manual: - The Info manual is in directory `infoman`. -- The DVI manual is in directory `texstuff` as file `manual.dvi`. - -- The PDF manual is in directory `texstuff` as file `pdfmanual.pdf`. +- The PDF manual is in directory `texstuff` as file `manual.pdf`. Source files ------------ @@ -119,7 +115,7 @@ Latex extensions ### Caml environments -The tool `tool/caml-tex2` is used to generate the latex code for the examples +The tool `tools/caml-tex` is used to generate the latex code for the examples in the introduction and language extension parts of the manual. It implements two pseudo-environments: `caml_example` and `caml_eval`. @@ -138,19 +134,26 @@ let f x = x \end{caml_example*} ``` -The `{verbatim}` or `{toplevel}` argument of the environment corresponds -to the the mode of the example, two modes are available `toplevel` and -`verbatim`. +The {verbatim} or {toplevel} argument of the environment corresponds +to the the mode of the example, three modes are available toplevel, verbatim and signature. The `toplevel` mode mimics the appearance and behavior of the toplevel. In particular, toplevel examples must end with a double semi-colon `;;`, otherwise an error would be raised. The `verbatim` does not require a final `;;` and is intended to be a lighter mode for code examples. +If you want to declare a signature instead of ocaml code, +you must use the `{signature}` argument to the `caml_example` environment. + +```latex +\begin{caml_example*}{signature} +val none : 'a option +\end{caml_example*} +``` -By default, `caml_tex2` raises an error and stops if the output of one +By default, `caml-tex` raises an error and stops if the output of one the `caml_example` environment contains an unexpected error or warning. If such an error or warning is, in fact, expected, it is necessary to -indicate the expected output status to `caml_tex2` by adding either +indicate the expected output status to `caml-tex` by adding either an option to the `caml_example` environment: ```latex \begin{caml_example}{toplevel}[error] diff --git a/manual/manual/Makefile b/manual/manual/Makefile index 9cc3d819..51871610 100644 --- a/manual/manual/Makefile +++ b/manual/manual/Makefile @@ -1,128 +1,141 @@ -# $Id$ - -FILES=allfiles.tex biblio.tex foreword.tex version.tex warnings-help.etex -TEXINPUTS=.:..:../refman:../library:../cmds:../tutorials:../../styles: -TEXFONTS=../../styles: -RELEASE=$$HOME/release/$${RELEASENAME} -HEVEA=hevea -HACHA=hacha -INFO=-fix -exec xxdate.exe -info -w 79 -HTML=-fix -exec xxdate.exe -O -TEXT=-fix -exec xxdate.exe -text -w 79 -SRC = $(abspath ../../) - -export LD_LIBRARY_PATH ?= $(SRC)/otherlibs/unix/:$(SRC)/otherlibs/str/ -export DYLD_LIBRARY_PATH ?= $(SRC)/otherlibs/unix/:$(SRC)/otherlibs/str/ -SET_LD_PATH=CAML_LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) - -OCAMLDOC=$(if $(wildcard $(SRC)/ocamldoc/ocamldoc.opt),\ - $(SRC)/ocamldoc/ocamldoc.opt,\ - $(SET_LD_PATH) $(SRC)/byterun/ocamlrun $(SRC)/ocamldoc/ocamldoc)\ - -hide Pervasives -nostdlib -initially-opened-module Pervasives +SRC = $(abspath ../..) -manual: files - cd texstuff; \ - TEXINPUTS=$(TEXINPUTS) latex manual.tex +export LD_LIBRARY_PATH ?= "$(SRC)/otherlibs/unix/:$(SRC)/otherlibs/str/" +export DYLD_LIBRARY_PATH ?= "$(SRC)/otherlibs/unix/:$(SRC)/otherlibs/str/" +SET_LD_PATH = CAML_LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) + +OCAMLDOC = $(if $(wildcard $(SRC)/ocamldoc/ocamldoc.opt),\ + $(SRC)/ocamldoc/ocamldoc.opt,\ + $(SET_LD_PATH) $(SRC)/runtime/ocamlrun $(SRC)/ocamldoc/ocamldoc)\ + -hide Stdlib -lib Stdlib -nostdlib \ + -pp "$(AWK) -v ocamldoc=true -f $(SRC)/stdlib/expand_module_aliases.awk" + + +# Import the list of mli files for the library docs +include $(SRC)/ocamldoc/Makefile.docfiles -index:: - cd texstuff && \ - sh ../../tools/fix_index.sh manual.idx && \ - makeindex manual.idx - cd texstuff; makeindex manual.kwd.idx +TEXQUOTE = $(SRC)/runtime/ocamlrun ../tools/texquote2 -pdfmanual: files - cd texstuff; \ - TEXINPUTS=$(TEXINPUTS) pdflatex pdfmanual.tex -index:: - cd texstuff && \ - sh ../../tools/fix_index.sh pdfmanual.idx && \ - makeindex pdfmanual.idx - cd texstuff; makeindex pdfmanual.kwd.idx +FILES = allfiles.tex biblio.tex foreword.tex version.tex warnings-help.etex +TEXINPUTS = ".:..:../refman:../library:../cmds:../tutorials:../../styles:" +RELEASE = $$HOME/release/$${RELEASENAME} +HEVEA = hevea +HACHA = hacha +INFO_FLAGS = -fix -exec xxdate.exe -info -w 79 +HTML_FLAGS = -fix -exec xxdate.exe -O +TEXT_FLAGS = -fix -exec xxdate.exe -text -w 79 -# Copy and unprefix the standard library when needed -include $(SRC)/ocamldoc/Makefile.unprefix -html: files $(STDLIB_CMIS) - cd htmlman; \ - mkdir -p libref ; \ +manual: files + cd texstuff \ + && TEXINPUTS=$(TEXINPUTS) pdflatex manual.tex + +index: + cd texstuff \ + && sh ../../tools/fix_index.sh manual.idx \ + && makeindex manual.idx \ + && makeindex manual.kwd.idx + + +# libref/style.css and comilerlibref/style.css are used as witness +# for the generation of the html stdlib and compilerlibs reference. +html: htmlman/libref/style.css htmlman/compilerlibref/style.css etex-files + cd htmlman \ + && $(HEVEA) $(HTML_FLAGS) \ + -I .. -I ../cmds -I ../library -I ../refman -I ../tutorials \ + -I ../../styles -I ../texstuff \ + manual.hva -e macros.tex ../manual.tex \ + && $(HACHA) -tocter manual.html + +htmlman/libref/style.css: style.css $(STDLIB_MLIS) $(DOC_STDLIB_TEXT) + mkdir -p htmlman/libref $(OCAMLDOC) -colorize-code -sort -html \ - -d libref \ - -I $(STDLIB_UNPREFIXED) \ - $(STDLIB_MLIS) ; \ - cp -f ../style.css libref ; \ - ${HEVEA} ${HTML} -I .. -I ../refman -I ../library -I ../cmds \ - -I ../tutorials -I ../../styles -I ../texstuff manual.hva \ - -e macros.tex ../manual.tex ; \ - ${HACHA} -tocter manual.html ; \ + -d htmlman/libref \ + $(DOC_STDLIB_INCLUDES) \ + $(DOC_STDLIB_TEXT:%=-text %) \ + $(STDLIB_MLIS) + cp style.css $@ + +COMPILERLIBS_MODULES=$(shell echo $(basename $(notdir $(COMPILERLIBS_MLIS))) \ +| sed "s/\<./\U&/g") + +library/compiler_libs.txt: library/compiler_libs.mld + cp $< $@ && echo "{!modules:$(COMPILERLIBS_MODULES)}" >> $@ + + +htmlman/compilerlibref/style.css: library/compiler_libs.txt style.css \ + $(COMPILERLIBS_MLIS) + mkdir -p htmlman/compilerlibref + $(OCAMLDOC) -colorize-code -sort -html \ + -d htmlman/compilerlibref \ + -I $(SRC)/stdlib \ + $(DOC_COMPILERLIBS_INCLUDES) \ + -intro library/compiler_libs.txt \ + library/compiler_libs.txt \ + $(COMPILERLIBS_MLIS) + cp style.css $@ + info: files - cd infoman; rm -f ocaml.info*; \ - ${HEVEA} ${INFO} -o ocaml.info.body -I .. -I ../refman -I ../library \ - -I ../cmds -I ../tutorials -I ../../styles -I ../texstuff \ - ../manual.inf -e macros.tex ../manual.tex + cd infoman \ + && rm -f ocaml.info* \ + && $(HEVEA) $(INFO_FLAGS) -o ocaml.info.body \ + -I .. -I ../cmds -I ../library -I ../refman -I ../tutorials \ + -I ../../styles -I ../texstuff \ + ../manual.inf -e macros.tex ../manual.tex cat manual.info.header infoman/ocaml.info.body > infoman/ocaml.info - cd infoman; rm -f ocaml.info.tmp ocaml.info.body ; gzip -9 ocaml.info* + cd infoman \ + && rm -f ocaml.info.tmp ocaml.info.body \ + && gzip -9 ocaml.info* text: files - cd textman; \ - ${HEVEA} ${TEXT} -I .. -I ../refman -I ../library -I ../cmds \ - -I ../tutorials -I ../../styles -I ../texstuff \ - ../manual.inf -e macros.tex ../manual.tex + cd textman \ + && $(HEVEA) $(TEXT_FLAGS) \ + -I .. -I ../cmds -I ../library -I ../refman -I ../tutorials \ + -I ../../styles -I ../texstuff \ + ../manual.inf -e macros.tex ../manual.tex -etex-files: $(FILES) - cd refman; $(MAKE) etex-files RELEASEDIR=$(SRC) - cd library; $(MAKE) etex-files RELEASEDIR=$(SRC) - cd cmds; $(MAKE) etex-files RELEASEDIR=$(SRC) - cd tutorials; $(MAKE) etex-files RELEASEDIR=$(SRC) - -files: $(FILES) - cd refman; $(MAKE) all RELEASEDIR=$(SRC) - cd library; $(MAKE) all RELEASEDIR=$(SRC) - cd cmds; $(MAKE) all RELEASEDIR=$(SRC) - cd tutorials; $(MAKE) all RELEASEDIR=$(SRC) all: - $(MAKE) manual pdfmanual RELEASEDIR=$(SRC) - $(MAKE) manual pdfmanual RELEASEDIR=$(SRC) - $(MAKE) index RELEASEDIR=$(SRC) - $(MAKE) manual pdfmanual RELEASEDIR=$(SRC) - $(MAKE) html text info RELEASEDIR=$(SRC) + $(MAKE) html text info manual + $(MAKE) manual + $(MAKE) index + $(MAKE) manual -clean: - rm -f $(FILES) - cd refman; $(MAKE) clean - cd library; $(MAKE) clean - cd cmds; $(MAKE) clean - cd tutorials; $(MAKE) clean - -rm -f texstuff/* - cd htmlman; rm -rf libref index.html manual*.html *.haux *.hind - cd textman; rm -f manual.txt *.haux *.hind - cd infoman; rm -f ocaml.info ocaml.info-* *.haux *.hind - rm -f warnings-help.etex - -release: - gzip < texstuff/manual.dvi > $(RELEASE)refman.dvi.gz - dvips -o '!gzip > $(RELEASE)refman.ps.gz' texstuff/manual.dvi +release: all cp htmlman/manual.html $(RELEASE)refman.html rm -f htmlman/manual.{html,haux,hmanual*,htoc} - tar zcf $(RELEASE)refman-html.tar.gz htmlman/*.* htmlman/libref - zip -8 $(RELEASE)refman-html.zip htmlman/*.* htmlman/libref/*.* - cp texstuff/pdfmanual.pdf $(RELEASE)refman.pdf + tar zcf $(RELEASE)refman-html.tar.gz \ + htmlman/*.* htmlman/libref htmlman/compilerlibref htmlman/fonts + zip -8 $(RELEASE)refman-html.zip \ + htmlman/*.* htmlman/libref/*.* htmlman/compilerlibref/*.* \ + htmlman/fonts/*.* + cp texstuff/manual.pdf $(RELEASE)refman.pdf cp textman/manual.txt $(RELEASE)refman.txt tar cf - infoman/ocaml.info* | gzip > $(RELEASE)refman.info.tar.gz -.SUFFIXES: -.SUFFIXES: .tex .etex .htex + +files: $(FILES) + $(MAKE) -C cmds all + $(MAKE) -C library all + $(MAKE) -C refman all + $(MAKE) -C tutorials all + +etex-files: $(FILES) + $(MAKE) -C cmds etex-files + $(MAKE) -C library etex-files + $(MAKE) -C refman etex-files + $(MAKE) -C tutorials etex-files -.etex.tex: - ../tools/texquote2 < $*.etex > $*.tex +%.tex: %.etex + $(TEXQUOTE) < $< > $*.texquote_error.tex + mv $*.texquote_error.tex $@ version.tex: $(SRC)/VERSION - sed -n -e '1s/^\([0-9]*\.[0-9]*\).*$$/\\def\\ocamlversion{\1}/p' \ - $(SRC)/VERSION > version.tex + sed -n -e '1s/^\([0-9]*\.[0-9]*\).*$$/\\def\\ocamlversion{\1}/p' $< > $@ warnings-help.etex: $(SRC)/utils/warnings.ml $(SRC)/ocamlc (echo "% This file is generated from (ocamlc -warn-help)";\ @@ -131,13 +144,27 @@ warnings-help.etex: $(SRC)/utils/warnings.ml $(SRC)/ocamlc echo "% are inserted through the Makefile, which should be updated";\ echo "% when a new warning is documented.";\ echo "%";\ - $(SET_LD_PATH) $(SRC)/boot/ocamlrun $(SRC)/ocamlc -warn-help \ - | sed -e 's/^ *\([0-9A-Z][0-9]*\)\(.*\)/\\item[\1] \2/'\ + $(SET_LD_PATH) $(SRC)/boot/ocamlrun $(SRC)/ocamlc -warn-help \ + | sed -e 's/^ *\([0-9A-Z][0-9]*\)\(.*\)/\\item[\1] \2/'\ ) >$@ # sed --inplace is not portable, emulate for i in 52 57; do\ - sed\ - s'/\\item\['$$i'\]/\\item\['$$i' (see \\ref{ss:warn'$$i'})\]/'\ - $@ > $@.tmp;\ - mv $@.tmp $@;\ + sed\ + s'/\\item\['$$i'\]/\\item\['$$i' (see \\ref{ss:warn'$$i'})\]/'\ + $@ > $@.tmp;\ + mv $@.tmp $@;\ done + + +.PHONY: clean +clean: + rm -f $(FILES) *.texquote_error + $(MAKE) -C cmds clean + $(MAKE) -C library clean + $(MAKE) -C refman clean + $(MAKE) -C tutorials clean + -rm -f texstuff/* + cd htmlman; rm -rf libref compilerlibref index.html \ + manual*.html *.haux *.hind *.svg + cd textman; rm -f manual.txt *.haux *.hind + cd infoman; rm -f ocaml.info ocaml.info-* *.haux *.hind diff --git a/manual/manual/allfiles.etex b/manual/manual/allfiles.etex index 7380648f..d2b3b81e 100644 --- a/manual/manual/allfiles.etex +++ b/manual/manual/allfiles.etex @@ -12,7 +12,7 @@ release \ocamlversion \\[1cm] \Large Documentation and user's manual \\[1cm] \large Xavier Leroy, \\ - Damien Doligez, Alain Frisch, Jacques Garrigue, Didier Rémy and Jérôme Vouillon \\[1cm] + Damien Doligez, Alain Frisch, Jacques Garrigue, Didier Rémy and Jérôme Vouillon \\[1cm] \today \\ ~ \vfill @@ -28,8 +28,6 @@ \rule{}{} This manual is also available in \ahref{http://caml.inria.fr/distrib/ocaml-\ocamlversion/ocaml-\ocamlversion-refman.pdf}{PDF}. -\ahref{http://caml.inria.fr/distrib/ocaml-\ocamlversion/ocaml-\ocamlversion-refman.ps.gz}{Postscript}, -\ahref{http://caml.inria.fr/distrib/ocaml-\ocamlversion/ocaml-\ocamlversion-refman.dvi.gz}{DVI}, \ahref{http://caml.inria.fr/distrib/ocaml-\ocamlversion/ocaml-\ocamlversion-refman.txt}{plain text}, as a \ahref{http://caml.inria.fr/distrib/ocaml-\ocamlversion/ocaml-\ocamlversion-refman-html.tar.gz}{bundle of HTML files}, diff --git a/manual/manual/biblio.etex b/manual/manual/biblio.etex index dd4c26dd..c1677702 100644 --- a/manual/manual/biblio.etex +++ b/manual/manual/biblio.etex @@ -15,7 +15,7 @@ semantics. \begin{itemize} \item Pierre Weis and Xavier Leroy. {\it Le langage Caml.} -InterÉditions, 1993. +InterÉditions, 1993. The natural companion to this manual, provided you read French. This book is a step-by-step introduction to programming in Caml, and @@ -44,9 +44,9 @@ examples, but a very detailed presentation of the language constructs. A short, but nice introduction to programming in Standard ML. -\item Thérèse Accart Hardin and Véronique Donzeau-Gouge Viguié. {\em -Concepts et outils de la programmation. Du fonctionnel à -l'impératif avec Caml et Ada.} InterÉditions, 1992. +\item Thérèse Accart Hardin and Véronique Donzeau-Gouge Viguié. {\em +Concepts et outils de la programmation. Du fonctionnel à +l'impératif avec Caml et Ada.} InterÉditions, 1992. A first course in programming, that first introduces the main programming notions in Caml, then shows them underlying Ada. Intended for @@ -60,8 +60,8 @@ types. Uses intensively the Standard ML module system. \item Harold Abelson and Gerald Jay Sussman. {\em Structure and Interpretation of Computer Programs.} The MIT -press, 1985. (French translation: {\em Structure et interprétation -des programmes informatiques}, InterÉditions, 1989.) +press, 1985. (French translation: {\em Structure et interprétation +des programmes informatiques}, InterÉditions, 1989.) An outstanding course on programming, taught in Scheme, the modern dialect of Lisp. Well worth reading, even if you are more interested @@ -76,8 +76,8 @@ languages from the ML family. They assume some familiarity with ML. \begin{itemize} -\item Xavier Leroy and Pierre Weis. {\em Manuel de référence du -langage Caml.} InterÉditions, 1993. +\item Xavier Leroy and Pierre Weis. {\em Manuel de référence du +langage Caml.} InterÉditions, 1993. The French edition of the present reference manual and user's manual. @@ -104,7 +104,7 @@ A commentary on the book above, that attempts to explain the most delicate parts and motivate the design choices. Easier to read than the Definition, but still rather involving. -\item Guy Cousineau and Gérard Huet. {\em The CAML primer.} Technical +\item Guy Cousineau and Gérard Huet. {\em The CAML primer.} Technical report~122, INRIA, 1990. A short description of the original Caml system, from which Caml Light @@ -190,18 +190,18 @@ unexpected, areas. \begin{itemize} \item Emmanuel Chailloux and Guy Cousineau. {\em The MLgraph primer.} -Technical report 92-15, École Normale Supérieure, 1992. (Available by +Technical report 92-15, École Normale Supérieure, 1992. (Available by anonymous FTP on "ftp.ens.fr".) -%, répertoire "biblio", fichier +%, répertoire "biblio", fichier % "liens-92-15.A4.300dpi.ps.Z".) Describes a Caml Light library that produces Postscript pictures through high-level drawing functions. -\item Xavier Leroy. {\em Programmation du système Unix en Caml Light.} +\item Xavier Leroy. {\em Programmation du système Unix en Caml Light.} Technical report~147, INRIA, 1992. (Available by anonymous FTP on "ftp.inria.fr".) -%, répertoire "INRIA/publication", fichier "RT-0147.ps.Z".) +%, répertoire "INRIA/publication", fichier "RT-0147.ps.Z".) A Unix systems programming course, demonstrating the use of the Caml Light library that gives access to Unix system calls. @@ -209,7 +209,7 @@ Light library that gives access to Unix system calls. \item John H.\ Reppy. {\em Concurrent programming with events --- The concurrent ML manual.} Cornell University, 1990. (Available by anonymous FTP on "research.att.com".) -%, répertoire "dist/ml", fichier "CML-0.9.8.tar.Z".) +%, répertoire "dist/ml", fichier "CML-0.9.8.tar.Z".) Concurrent ML extends Standard ML of New Jersey with concurrent processes that communicate through channels and events. @@ -219,13 +219,13 @@ Scottt Nettles. {\em Extensions to Standard ML to support transactions.} Technical report CMU-CS-92-132, Carnegie-Mellon University, 1992. (Available by anonymous FTP on "reports.adm.cs.cmu.edu".) -% , répertoire "1992", fichier "CMU-CS-92-132.ps".) +% , répertoire "1992", fichier "CMU-CS-92-132.ps".) How to integrate the basic database operations to Standard ML. \item Emden R.\ Gansner and John H.\ Reppy. {\em eXene.} Bell Labs, 1991. (Available by anonymous FTP on "research.att.com".) -%, répertoire "dist/ml", fichier "eXene-0.4.tar.Z".) +%, répertoire "dist/ml", fichier "eXene-0.4.tar.Z".) An interface between Standard ML of New Jersey and the X Windows windowing system. @@ -233,7 +233,7 @@ windowing system. %% \item Daniel de Rauglaudre. {\em X toolkit in Caml Light.} INRIA, %% 1992. (Included in the Caml Light distribution.) %% % Disponible par FTP anonyme sur -%% % "ftp.inria.fr", répertoire "lang/caml-light", fichier "rt5.tar.Z".) +%% % "ftp.inria.fr", répertoire "lang/caml-light", fichier "rt5.tar.Z".) %% %% An interface between Caml Light and the X Windows windowing system. diff --git a/manual/manual/cmds/Makefile b/manual/manual/cmds/Makefile index 3ff916ed..c1dbacb3 100644 --- a/manual/manual/cmds/Makefile +++ b/manual/manual/cmds/Makefile @@ -1,60 +1,52 @@ -FILES=comp.tex top.tex runtime.tex native.tex lexyacc.tex intf-c.tex \ - depend.tex profil.tex debugger.tex browser.tex ocamldoc.tex \ - warnings-help.tex ocamlbuild.tex flambda.tex spacetime.tex \ - afl-fuzz.tex plugins.tex unified-options.tex - -TOPDIR=../../.. +TOPDIR = ../../.. include $(TOPDIR)/Makefile.tools -LD_PATH="$(TOPDIR)/otherlibs/str:$(TOPDIR)/otherlibs/unix" +LD_PATH = "$(TOPDIR)/otherlibs/str:$(TOPDIR)/otherlibs/unix" -TRANSF=$(SET_LD_PATH) $(OCAMLRUN) ../../tools/transf -TEXQUOTE=../../tools/texquote2 -FORMAT=../../tools/format-intf +TOOLS = ../../tools +CAMLLATEX = $(SET_LD_PATH) \ + $(OCAMLRUN) $(TOPDIR)/tools/caml-tex \ + -repo-root $(TOPDIR) -n 80 -v false +TEXQUOTE = $(OCAMLRUN) $(TOOLS)/texquote2 +TRANSF = $(SET_LD_PATH) $(OCAMLRUN) $(TOOLS)/transf -CAMLLATEX=$(SET_LD_PATH) $(OCAMLRUN) ../../tools/caml-tex2 \ --caml "TERM=norepeat $(OCAML)" -n 80 -v false +FILES = comp.tex top.tex runtime.tex native.tex lexyacc.tex intf-c.tex \ + depend.tex profil.tex debugger.tex browser.tex ocamldoc.tex \ + warnings-help.tex ocamlbuild.tex flambda.tex spacetime.tex \ + afl-fuzz.tex plugins.tex unified-options.tex -WITH_TRANSF= top.tex intf-c.tex flambda.tex spacetime.tex \ +WITH_TRANSF = top.tex intf-c.tex flambda.tex spacetime.tex \ afl-fuzz.tex lexyacc.tex debugger.tex WITH_CAMLEXAMPLE = ocamldoc.tex -etex-files: $(FILES) +etex-files: $(FILES) all: $(FILES) -clean:: - rm -f $(FILES) - rm -f *~ #*# -.SUFFIXES: -.SUFFIXES: .tex .etex +%.tex: %.etex + $(TEXQUOTE) < $< > $*.texquote_error.tex + mv $*.texquote_error.tex $@ -.etex.tex: - @$(TEXQUOTE) < $*.etex > $*.texquote_error.tex\ - && mv $*.texquote_error.tex $*.tex\ - || printf "Failure when generating %s\n" $*.tex +$(WITH_TRANSF): %.tex: %.etex + $(TRANSF) < $< > $*.transf_error.tex + mv $*.transf_error.tex $*.transf_gen.tex + $(TEXQUOTE) < $*.transf_gen.tex > $*.texquote_error.tex + mv $*.texquote_error.tex $@ -$(WITH_TRANSF):%.tex:%.etex - @$(TRANSF) < $*.etex > $*.transf_error.tex \ - && mv $*.transf_error.tex $*.transf_gen.tex \ - && $(TEXQUOTE) < $*.transf_gen.tex > $*.texquote_error.tex \ - && mv $*.texquote_error.tex $*.tex \ - || printf "Failure when generating %s\n" $*.tex - - -$(WITH_CAMLEXAMPLE):%.tex:%.etex - @$(CAMLLATEX) -o $*.caml_tex_error.tex $*.etex \ - && mv $*.caml_tex_error.tex $*.gen.tex \ - && $(TRANSF) < $*.gen.tex > $*.transf_error.tex \ - && mv $*.transf_error.tex $*.gen.tex\ - && $(TEXQUOTE) < $*.gen.tex > $*.texquote_error.tex\ - && mv $*.texquote_error.tex $*.tex\ - || printf "Failure when generating %s\n" $*.tex +$(WITH_CAMLEXAMPLE): %.tex: %.etex + $(CAMLLATEX) $< -o $*.gen.tex + $(TRANSF) < $*.gen.tex > $*.transf_error.tex + mv $*.transf_error.tex $*.transf_gen.tex + $(TEXQUOTE) < $*.transf_gen.tex > $*.texquote_error.tex + mv $*.texquote_error.tex $@ warnings-help.etex: ../warnings-help.etex - cp ../warnings-help.etex . + cp $< $@ + -clean:: +.PHONY: clean +clean: + rm -f *.tex rm -f warnings-help.etex diff --git a/manual/manual/cmds/afl-fuzz.etex b/manual/manual/cmds/afl-fuzz.etex index 5e8a4beb..9cda1b5d 100644 --- a/manual/manual/cmds/afl-fuzz.etex +++ b/manual/manual/cmds/afl-fuzz.etex @@ -1,5 +1,4 @@ \chapter{Fuzzing with afl-fuzz} -\pdfchapterfold{-9}{Fuzzing with afl-fuzz} %HEVEA\cutname{afl-fuzz.html} \section{Overview} diff --git a/manual/manual/cmds/browser.etex b/manual/manual/cmds/browser.etex index 5eb5a4ff..0731e8a4 100644 --- a/manual/manual/cmds/browser.etex +++ b/manual/manual/cmds/browser.etex @@ -1,5 +1,4 @@ \chapter{The browser/editor (ocamlbrowser)} \label{c:browser} -\pdfchapter{The browser/editor (ocamlbrowser)} %HEVEA\cutname{browser.html} Since OCaml version 4.02, the OCamlBrowser tool and the Labltk library diff --git a/manual/manual/cmds/comp.etex b/manual/manual/cmds/comp.etex index 3e601014..6cdd9367 100644 --- a/manual/manual/cmds/comp.etex +++ b/manual/manual/cmds/comp.etex @@ -1,5 +1,4 @@ \chapter{Batch compilation (ocamlc)} \label{c:camlc} -\pdfchapter{Batch compilation (ocamlc)} %HEVEA\cutname{comp.html} This chapter describes the OCaml batch compiler "ocamlc", @@ -272,12 +271,12 @@ are two ways to fix this error: type (without type variables) to \var{name}. For instance, instead of writing \begin{verbatim} - let sort_int_list = Sort.list (<) + let sort_int_list = List.sort Stdlib.compare (* inferred type 'a list -> 'a list, with 'a not generalized *) \end{verbatim} write \begin{verbatim} - let sort_int_list = (Sort.list (<) : int list -> int list);; + let sort_int_list = (List.sort Stdlib.compare : int list -> int list);; \end{verbatim} \item If you really need \var{name} to have a polymorphic type, turn its defining expression into a function by adding an extra parameter. @@ -424,6 +423,11 @@ let dy { y; _ } = y (* explicit field elision: do not trigger warning 9 *) this attribute set: "Invalid_argument", "Failure", "Sys_error" will all raise this warning if you match for a specific string argument. + Additionally, built-in exceptions with a structured argument that + includes a string also have the attribute set: "Assert_failure" and + "Match_failure" will raise the warning for a pattern that uses a + literal string to match the first element of their tuple argument. + If your code raises this warning, you should {\em not} change the way you test for the specific string to avoid the warning (for example using a string equality inside the right-hand-side instead diff --git a/manual/manual/cmds/debugger.etex b/manual/manual/cmds/debugger.etex index 31a2ad65..d77361e9 100644 --- a/manual/manual/cmds/debugger.etex +++ b/manual/manual/cmds/debugger.etex @@ -1,5 +1,4 @@ \chapter{The debugger (ocamldebug)} \label{c:debugger} -\pdfchapter{The debugger (ocamldebug)} %HEVEA\cutname{debugger.html} This chapter describes the OCaml source-level replay debugger diff --git a/manual/manual/cmds/depend.etex b/manual/manual/cmds/depend.etex index b5dadd58..00696681 100644 --- a/manual/manual/cmds/depend.etex +++ b/manual/manual/cmds/depend.etex @@ -1,5 +1,4 @@ \chapter{Dependency generator (ocamldep)} \label{c:camldep} -\pdfchapter{Dependency generator (ocamldep)} %HEVEA\cutname{depend.html} The "ocamldep" command scans a set of OCaml source files diff --git a/manual/manual/cmds/flambda.etex b/manual/manual/cmds/flambda.etex index 063029ec..eff8c84a 100644 --- a/manual/manual/cmds/flambda.etex +++ b/manual/manual/cmds/flambda.etex @@ -1,5 +1,4 @@ \chapter{Optimisation with Flambda} -\pdfchapterfold{-9}{Optimisation with Flambda} %HEVEA\cutname{flambda.html} \section{Overview} @@ -553,7 +552,7 @@ let rec iter f l = and used like this: \begin{verbatim} let print_int x = - print_endline (string_of_int x) + print_endline (Int.to_string x) let run xs = iter print_int (List.rev xs) @@ -595,7 +594,7 @@ let run xs = match l with | [] -> () | h :: t -> - print_endline (string_of_int h); + print_endline (Int.to_string h); iter' f t in iter' print_int (List.rev xs) @@ -607,7 +606,7 @@ let run xs = match l with | [] -> () | h :: t -> - print_endline (string_of_int h); + print_endline (Int.to_string h); iter' t in iter' (List.rev xs) diff --git a/manual/manual/cmds/intf-c.etex b/manual/manual/cmds/intf-c.etex index b8b5fcf7..ca5ff63b 100644 --- a/manual/manual/cmds/intf-c.etex +++ b/manual/manual/cmds/intf-c.etex @@ -1,5 +1,4 @@ \chapter{Interfacing\label{c:intf-c} C with OCaml} -\pdfchapterfold{-9}{Interfacing C with OCaml} %HEVEA\cutname{intfc.html} This chapter describes how user-defined primitives, written in C, can @@ -7,7 +6,6 @@ be linked with OCaml code and called from OCaml functions, and how these C functions can call back to OCaml code. \section{Overview and compilation information} -\pdfsection{Overview and compilation information} \subsection{Declaring primitives} @@ -436,7 +434,6 @@ bytecode executable (so that the bytecode from "unix.cma" and "threads.cma" is actually linked in). \section{The \texttt{value} type} -\pdfsection{The value type} All OCaml objects are represented by the C type "value", defined in the include file "caml/mlvalues.h", along with macros to @@ -481,7 +478,7 @@ floating-point numbers.} \entree{"Abstract_tag"}{A block representing an abstract datatype.} \entree{"Custom_tag"}{A block representing an abstract datatype with user-defined finalization, comparison, hashing, - serialization and deserialization functions atttached.} + serialization and deserialization functions attached.} \end{tableau} \subsection{Pointers outside the heap} @@ -503,7 +500,6 @@ these problems, it is preferable to wrap the pointer in a OCaml block with tag "Abstract_tag" or "Custom_tag". \section{Representation of OCaml data types} -\pdfsection{Representation of OCaml data types} This section describes how OCaml data types are encoded in the "value" type. @@ -657,7 +653,6 @@ pair "("\var{v}", "\var{w}")", rather than a block of size 3 containing \var{v} and \var{w} in fields 1 and 2. \section{Operations on values} -\pdfsection{Operations on values} \subsection{Kind tests} @@ -871,7 +866,6 @@ the C string \var{s} as argument. \end{itemize} \section{Living in harmony with the garbage collector} -\pdfsection{Living in harmony with the garbage collector} Unused blocks in the heap are automatically reclaimed by the garbage collector. This requires some cooperation from C code that @@ -1174,7 +1168,6 @@ has taken place since "r" was allocated. \section{A complete example} -\pdfsection{A complete example} This section outlines how the functions from the Unix "curses" library can be made available to OCaml programs. First of all, here is @@ -1221,7 +1214,8 @@ static struct custom_operations curses_window_ops = { custom_hash_default, custom_serialize_default, custom_deserialize_default, - custom_compare_ext_default + custom_compare_ext_default, + custom_fixed_length_default }; /* Accessing the WINDOW * part of an OCaml custom block */ @@ -1336,7 +1330,6 @@ instead of "-cclib -lcurses".) %% and not "world". Why? \section{Advanced topic: callbacks from C to OCaml} \label{s:callback} -\pdfsection{Advanced topic: callbacks from C to OCaml} So far, we have described how to call C functions from OCaml. In this section, we show how C functions can call OCaml functions, either as @@ -1373,7 +1366,7 @@ arguments as their non-"_exn" counterparts, but catch escaping exceptions and return them to the C code. The return value \var{v} of the "caml_callback*_exn" functions must be tested with the macro "Is_exception_result("\var{v}")". If the macro returns ``false'', no -exception occured, and \var{v} is the value returned by the OCaml +exception occurred, and \var{v} is the value returned by the OCaml function. If "Is_exception_result("\var{v}")" returns ``true'', an exception escaped, and its value (the exception descriptor) can be recovered using "Extract_exception("\var{v}")". @@ -1600,8 +1593,8 @@ With "ocamlopt", you should do: \paragraph{Warning:} On some ports, special options are required on the final linking phase that links together the object file produced by the "-output-obj" option and the remainder of the program. Those options -are shown in the configuration file "config/Makefile" generated during -compilation of OCaml, as the variable "LDFLAGS". +are shown in the configuration file "Makefile.config" generated during +compilation of OCaml, as the variable "OC_LDFLAGS". \begin{itemize} \item Windows with the MSVC compiler: the object file produced by OCaml have been compiled with the "/MD" flag, and therefore @@ -1659,7 +1652,6 @@ facility is only useful for building reloadable shared libraries. \section{Advanced example with callbacks} -\pdfsection{Advanced example with callbacks} This section illustrates the callback facilities described in section~\ref{s:callback}. We are going to package some OCaml functions @@ -1754,7 +1746,6 @@ To build the whole program, just invoke the C compiler as follows: "-lcurses -ltermcap" instead of "-lcurses".) \section{Advanced topic: custom blocks} \label{s:custom} -\pdfsection{Advanced topic: custom blocks} Blocks with tag "Custom_tag" contain both arbitrary user data and a pointer to a C struct, with type "struct custom_operations", that @@ -1806,7 +1797,7 @@ default comparison function simply raises "Failure". \item "intnat (*hash)(value v)" \\ The "hash" field contains a pointer to a C function that is called -whenever OCaml's generic hash operator (see module "Hashtbl") is +whenever OCaml's generic hash operator (see module \stdmoduleref{Hashtbl}) is applied to a custom block. The C function can return an arbitrary integer representing the hash value of the data contained in the given custom block. The hash value must be compatible with the @@ -1817,7 +1808,7 @@ the same hash value. The "hash" field can be set to "custom_hash_default", in which case the custom block is ignored during hash computation. -\item "void (*serialize)(value v, uintnat * wsize_32, uintnat * wsize_64)" \\ +\item "void (*serialize)(value v, uintnat * bsize_32, uintnat * bsize_64)" \\ The "serialize" field contains a pointer to a C function that is called whenever the custom block needs to be serialized (marshaled) using the OCaml functions "output_value" or "Marshal.to_...". @@ -1827,7 +1818,7 @@ then call the user-provided "serialize" function. That function is responsible for writing the data contained in the custom block, using the "serialize_..." functions defined in "" and listed below. The user-provided "serialize" function must then store in its -"wsize_32" and "wsize_64" parameters the sizes in bytes of the data +"bsize_32" and "bsize_64" parameters the sizes in bytes of the data part of the custom block on a 32-bit architecture and on a 64-bit architecture, respectively. @@ -1853,6 +1844,15 @@ The "deserialize" field can be set to "custom_deserialize_default" to indicate that deserialization is not supported. In this case, do not register the "struct custom_operations" with the deserializer using "register_custom_operations" (see below). + +\item "const struct custom_fixed_length* fixed_length" \\ +Normally, space in the serialized output is reserved to write the +"bsize_32" and "bsize_64" fields returned by "serialize". However, for +very short custom blocks, this space can be larger than the data +itself! As a space optimisation, if "serialize" always returns the +same values for "bsize_32" and "bsize_64", then these values may be +specified in the "fixed_length" structure, and do not consume space in +the serialized output. \end{itemize} Note: the "finalize", "compare", "hash", "serialize" and "deserialize" @@ -1864,7 +1864,8 @@ functions, and do not use "CAMLreturn" to return the result. \subsection{Allocating custom blocks} -Custom blocks must be allocated via the "caml_alloc_custom" function: +Custom blocks must be allocated via "caml_alloc_custom" or +"caml_alloc_custom_mem": \begin{center} "caml_alloc_custom("\var{ops}", "\var{size}", "\var{used}", "\var{max}")" \end{center} @@ -1916,6 +1917,18 @@ $\var{used} = 0$ and $\var{max} = 1$. But if you later find that the finalization functions are not called ``often enough'', consider increasing the $\var{used} / \var{max}$ ratio. +\begin{center} +"caml_alloc_custom_mem("\var{ops}", "\var{size}", "\var{used}")" +\end{center} +Use this function when your custom block holds only out-of-heap memory +(memory allocated with "malloc" or "caml_stat_alloc") and no other +resources. "used" should be the number of bytes of out-of-heap +memory that are held by your custom block. This function works like +"caml_alloc_custom" except that the "max" parameter is under the +control of the user (via the "custom_major_ratio", +"custom_minor_ratio", and "custom_minor_max_size" parameters) and +proportional to the heap sizes. + \subsection{Accessing custom blocks} The data part of a custom block \var{v} can be @@ -2011,11 +2024,11 @@ word is reserved for storing the custom operations; the other \var{used} and \var{max} are used to control the speed of garbage collection, as described for "caml_alloc_custom". -\section{Advanced topic: Big arrays and the OCaml-C interface} +\section{Advanced topic: Bigarrays and the OCaml-C interface} \label{s:C-Bigarrays} This section explains how C stub code that interfaces C or Fortran -code with OCaml code can use big arrays. +code with OCaml code can use Bigarrays. \subsection{Include file} @@ -2025,12 +2038,12 @@ below. \subsection{Accessing an OCaml bigarray from C or Fortran} -If \var{v} is a OCaml "value" representing a big array, the expression +If \var{v} is a OCaml "value" representing a Bigarray, the expression "Caml_ba_data_val("\var{v}")" returns a pointer to the data part of the array. This pointer is of type "void *" and can be cast to the appropriate C type for the array (e.g. "double []", "char [][10]", etc). -Various characteristics of the OCaml big array can be consulted from C +Various characteristics of the OCaml Bigarray can be consulted from C as follows: \begin{tableau}{|l|l|}{C expression}{Returns} \entree{"Caml_ba_array_val("\var{v}")->num_dims"}{number of dimensions} @@ -2051,7 +2064,7 @@ The kind of array elements is one of the following constants: \entree{"CAML_BA_NATIVE_INT"}{32- or 64-bit (platform-native) integers} \end{tableau} % -The following example shows the passing of a two-dimensional big array +The following example shows the passing of a two-dimensional Bigarray to a C function and a Fortran function. \begin{verbatim} extern void my_c_function(double * data, int dimx, int dimy); @@ -2069,16 +2082,16 @@ to a C function and a Fortran function. } \end{verbatim} -\subsection{Wrapping a C or Fortran array as an OCaml big array} +\subsection{Wrapping a C or Fortran array as an OCaml Bigarray} A pointer \var{p} to an already-allocated C or Fortran array can be -wrapped and returned to OCaml as a big array using the "caml_ba_alloc" +wrapped and returned to OCaml as a Bigarray using the "caml_ba_alloc" or "caml_ba_alloc_dims" functions. \begin{itemize} \item "caml_ba_alloc("\var{kind} "|" \var{layout}, \var{numdims}, \var{p}, \var{dims}")" -Return an OCaml big array wrapping the data pointed to by \var{p}. +Return an OCaml Bigarray wrapping the data pointed to by \var{p}. \var{kind} is the kind of array elements (one of the "CAML_BA_" kind constants above). \var{layout} is "CAML_BA_C_LAYOUT" for an array with C layout and "CAML_BA_FORTRAN_LAYOUT" for an array with diff --git a/manual/manual/cmds/lexyacc.etex b/manual/manual/cmds/lexyacc.etex index 6053de89..5456acee 100644 --- a/manual/manual/cmds/lexyacc.etex +++ b/manual/manual/cmds/lexyacc.etex @@ -1,6 +1,5 @@ \chapter{Lexer and parser generators (ocamllex, ocamlyacc)} \label{c:ocamlyacc} -\pdfchapter{Lexer and parser generators (ocamllex, ocamlyacc)} %HEVEA\cutname{lexyacc.html} This chapter describes two program generators: "ocamllex", that @@ -53,8 +52,8 @@ The following command-line options are recognized by "ocamllex". \item["-ml"] Output code that does not use OCaml's built-in automata interpreter. Instead, the automaton is encoded by OCaml functions. -This option mainly is useful for debugging "ocamllex", using it for -production lexers is not recommended. +This option improves performance when using the native compiler, but +decreases it when using the bytecode compiler. \item["-o" \var{output-file}] Specify the name of the output file produced by "ocamllex". @@ -119,7 +118,7 @@ In regular expressions that follow this declaration, the identifier The names of the entry points must be valid identifiers for OCaml values (starting with a lowercase letter). -Similarily, the arguments \texttt{\var{arg$_1$}\ldots{} +Similarly, the arguments \texttt{\var{arg$_1$}\ldots{} \var{arg$_n$}} must be valid identifiers for OCaml. Each entry point becomes an OCaml function that takes $n+1$ arguments, diff --git a/manual/manual/cmds/native.etex b/manual/manual/cmds/native.etex index c06a8186..c1f3d925 100644 --- a/manual/manual/cmds/native.etex +++ b/manual/manual/cmds/native.etex @@ -1,5 +1,4 @@ \chapter{Native-code compilation (ocamlopt)} \label{c:nativecomp} -\pdfchapter{Native-code compilation (ocamlopt)} %HEVEA\cutname{native.html} This chapter describes the OCaml high-performance diff --git a/manual/manual/cmds/ocamlbuild.etex b/manual/manual/cmds/ocamlbuild.etex index 9a55b48a..66c7101a 100644 --- a/manual/manual/cmds/ocamlbuild.etex +++ b/manual/manual/cmds/ocamlbuild.etex @@ -1,5 +1,4 @@ \chapter{The ocamlbuild compilation manager} \label{c:ocamlbuild} -\pdfchapter{The ocamlbuild compilation manager} Since OCaml version 4.03, the ocamlbuild compilation manager is distributed separately from the OCaml compiler. The project is now diff --git a/manual/manual/cmds/ocamldoc.etex b/manual/manual/cmds/ocamldoc.etex index d7346bb4..484e6350 100644 --- a/manual/manual/cmds/ocamldoc.etex +++ b/manual/manual/cmds/ocamldoc.etex @@ -1,5 +1,4 @@ \chapter{The documentation generator (ocamldoc)} \label{c:ocamldoc} -\pdfchapter{The documentation generator (ocamldoc)} %HEVEA\cutname{ocamldoc.html} This chapter describes OCamldoc, a tool that generates documentation from @@ -62,7 +61,7 @@ with the {\bf\tt -d} option. \item["-dot"] Generate a dependency graph for the toplevel modules, in a format suitable for displaying and processing by "dot". The "dot" tool is available from -\url{http://www.research.att.com/sw/tools/graphviz/}. +\url{https://graphviz.org/}. The textual representation of the graph is written to the file "ocamldoc.out", or to the file specified with the {\bf\tt -o} option. Use "dot ocamldoc.out" to display it. @@ -542,7 +541,7 @@ class type my_class_type = (** The comment for variable x. *) val mutable x : int - (** The commend for method m. *) + (** The comment for method m. *) method m : int -> int end @@ -638,7 +637,7 @@ class type my_class_type = object (** The comment for the instance variable x. *) val mutable x : int - (** The commend for method m. *) + (** The comment for method m. *) method m : int -> int end diff --git a/manual/manual/cmds/plugins.etex b/manual/manual/cmds/plugins.etex index 7fd02e4f..89d652ef 100644 --- a/manual/manual/cmds/plugins.etex +++ b/manual/manual/cmds/plugins.etex @@ -1,5 +1,4 @@ \chapter{Compiler plugins\label{c:plugins}} -\pdfchapterfold{-9}{Compiler plugind} %HEVEA\cutname{plugins.html} \section{Overview} diff --git a/manual/manual/cmds/profil.etex b/manual/manual/cmds/profil.etex index 31b6ed95..e286f6a4 100644 --- a/manual/manual/cmds/profil.etex +++ b/manual/manual/cmds/profil.etex @@ -1,5 +1,4 @@ \chapter{Profiling (ocamlprof)} \label{c:profiler} -\pdfchapter{Profiling (ocamlprof)} %HEVEA\cutname{profil.html} This chapter describes how the execution of OCaml diff --git a/manual/manual/cmds/runtime.etex b/manual/manual/cmds/runtime.etex index 97232f67..5b146508 100644 --- a/manual/manual/cmds/runtime.etex +++ b/manual/manual/cmds/runtime.etex @@ -1,5 +1,4 @@ \chapter{The runtime system (ocamlrun)} \label{c:runtime} -\pdfchapter{The runtime system (ocamlrun)} %HEVEA\cutname{runtime.html} The "ocamlrun" command executes bytecode files produced by the @@ -63,6 +62,11 @@ in the "OCAMLRUNPARAM" environment variable (see below). Search the directory \var{dir} for dynamically-loaded libraries, in addition to the standard search path (see section~\ref{s-ocamlrun-dllpath}). +\item["-m"] +Print the magic number of the bytecode executable given as argument +and exit. +\item["-M"] +Print the magic number expected by this version of the runtime and exit. \item["-p"] Print the names of the primitives known to this version of "ocamlrun" and exit. @@ -153,6 +157,28 @@ The following environment variables are also consulted: "caml_shutdown" in section~\ref{s:embedded-code}). The option also enables pooling (as in "caml_startup_pooled"). This mode can be used to detect leaks with a third-party memory debugger. + % FIXME missing: H, t, w, W see MPR#7870 + \item[M] ("custom_major_ratio") Target ratio of floating garbage to + major heap size for out-of-heap memory held by custom values + (e.g. bigarrays) located in the major heap. The GC speed is adjusted + to try to use this much memory for dead values that are not yet + collected. Expressed as a percentage of major heap size. Default: + 44. Note: this only applies to values allocated with + "caml_alloc_custom_mem". + \item[m] ("custom_minor_ratio") Bound on floating garbage for + out-of-heap memory + held by custom values in the minor heap. A minor GC is triggered + when this much memory is held by custom values located in the minor + heap. Expressed as a percentage of minor heap size. Default: + 100. Note: this only applies to values allocated with + "caml_alloc_custom_mem". + \item[n] ("custom_minor_max_size") Maximum amount of out-of-heap + memory for each custom value allocated in the minor heap. When a custom + value is allocated on the minor heap and holds more than this many + bytes, only this value is counted against "custom_minor_ratio" and + the rest is directly counted against "custom_major_ratio". + Default: 8192 bytes. Note: + this only applies to values allocated with "caml_alloc_custom_mem". \end{options} The multiplier is "k", "M", or "G", for multiplication by $2^{10}$, $2^{20}$, and $2^{30}$ respectively. diff --git a/manual/manual/cmds/spacetime.etex b/manual/manual/cmds/spacetime.etex index 7abc7095..0c39a2e8 100644 --- a/manual/manual/cmds/spacetime.etex +++ b/manual/manual/cmds/spacetime.etex @@ -1,5 +1,4 @@ \chapter{Memory profiling with Spacetime} -\pdfchapterfold{-9}{Memory profiling with Spacetime} %HEVEA\cutname{spacetime.html} \section{Overview} diff --git a/manual/manual/cmds/top.etex b/manual/manual/cmds/top.etex index 0ac39a22..ddf68915 100644 --- a/manual/manual/cmds/top.etex +++ b/manual/manual/cmds/top.etex @@ -1,5 +1,4 @@ \chapter{The toplevel system or REPL (ocaml)} \label{c:camllight} -\pdfchapter{The toplevel system or REPL (ocaml)} %HEVEA\cutname{toplevel.html} This chapter describes the toplevel system for OCaml, that permits @@ -126,6 +125,11 @@ The following command-line options are recognized by the "ocaml" command. \begin{unix} The following environment variables are also consulted: \begin{options} +\item["OCAMLTOP_INCLUDE_PATH"] Additional directories to search for compiled + object code files (".cmi", ".cmo" and ".cma"). The specified directories are + considered from left to right, after the include directories specified on the + command line via "-I" have been searched. Available since OCaml 4.08. + \item["OCAMLTOP_UTF_8"] When printing string values, non-ascii bytes ($ {} > "\0x7E" $) are printed as decimal escape sequence if "OCAMLTOP_UTF_8" is set to false. Otherwise, they are printed unescaped. @@ -213,7 +217,7 @@ directories: \item Directories added with the "#directory" directive. \item Directories given on the command line with "-I" options. \item The standard library directory. -\end{enumerate} +\end{enumerate} \item[Environment queries] \begin{options} diff --git a/manual/manual/cmds/unified-options.etex b/manual/manual/cmds/unified-options.etex index 796d65a5..bb543426 100644 --- a/manual/manual/cmds/unified-options.etex +++ b/manual/manual/cmds/unified-options.etex @@ -33,7 +33,7 @@ % } % These macros can be also used to add information that are only relevant to % some tools or differ slightly from one tool to another. For instance, we -% define the following macro for the pairs cma/cmxa cmo/cmxo and ocamlc/ocamlopt +% define the following macro for the pairs cma/cmxa cmo/cmxo and ocamlc/ocamlopt % \def\cma{\comp{.cma}\nat{.cmxa}} \def\cmo{\comp{.cmo}\nat{.cmx}} @@ -75,7 +75,8 @@ Read additional newline-terminated command line arguments from \var{filename}. \top{It is not possible to pass a \var{scriptfile} via file to the toplevel. }%top \item["-args0" \var{filename}] - Read additional null character terminated command line arguments from \var{filename}. + Read additional null character terminated command line arguments from + \var{filename}. \top{It is not possible to pass a \var{scriptfile} via file to the toplevel. }%top @@ -126,7 +127,8 @@ directory \var{dir}.\comp{(See the "-custom" option.)} Enable or disable colors in compiler messages (especially warnings and errors). The following modes are supported: \begin{description} - \item["auto"] use heuristics to enable colors only if the output supports them (an ANSI-compatible tty terminal); + \item["auto"] use heuristics to enable colors only if the output supports them + (an ANSI-compatible tty terminal); \item["always"] enable colors unconditionally; \item["never"] disable color output. \end{description} @@ -138,6 +140,21 @@ The environment variable "OCAML_COLOR" is considered if "-color" is not provided. Its values are auto/always/never as above. }%notop +\notop{% +\item["-error-style" \var{mode}] +Control the way error messages and warnings are printed. +The following modes are supported: +\begin{description} + \item["short"] only print the error and its location; + \item["contextual"] like "short", but also display the source code snippet + corresponding to the location of the error. + \end{description} +The default setting is "contextual". + +The environment variable "OCAML_ERROR_STYLE" is considered if "-error-style" is +not provided. Its values are short/contextual as above. +}%notop + \comp{% \item["-compat-32"] Check that the generated bytecode executable can run on 32-bit @@ -152,9 +169,19 @@ results in slightly smaller but slightly slower programs. The default is to optimize for speed. }%nat +\notop{% \item["-config"] Print the version number of {\machine\ocamlx} and a detailed summary of its configuration, then exit. +}%notop + +\notop{% +\item["-config-var" \var{var}] +Print the value of a specific configuration variable from the +"-config" output, then exit. If the variable does not exist, the exit +code is non-zero. This option is only available since OCaml 4.08, +so script authors should have a fallback for older versions. +}%notop \comp{% \item["-custom"] @@ -326,6 +353,15 @@ bytecode executables produced with the See section~\ref{s:custom-runtime} for more information. }%comp +\notop{% +\item["-match-context-rows"] +Set the number of rows of context used for optimization during +pattern matching compilation. The default value is 32. Lower values +cause faster compilation, but less optimized code. This advanced +option is meant for use in the event that a pattern-match-heavy +program leads to significant increases in compilation time. +}%notop + \notop{% \item["-no-alias-deps"] Do not record dependencies for module aliases. See @@ -388,7 +424,7 @@ compiled interface files (".cmi"), compiled object code files "-cclib -lxxx". See also option "-I". }%comp \nat{% -Do not automatically add the standard library directory the list of +Do not automatically add the standard library directory to the list of directories searched for compiled interface files (".cmi"), compiled object code files (".cmx"), and libraries (".cmxa"). See also option "-I". @@ -456,8 +492,8 @@ This is useful to wrap OCaml code as a C library, callable from any C program. See chapter~\ref{c:intf-c}, section~\ref{s:embedded-code}. The name of the output object file must be set with the "-o" option. -This option can also be used to produce a \comp{C source file (".c" extension) or -a} compiled shared/dynamic library (".so" extension, ".dll" under Windows). +This option can also be used to produce a \comp{C source file (".c" extension) +or a} compiled shared/dynamic library (".so" extension, ".dll" under Windows). }%notop \nat{% @@ -538,10 +574,10 @@ of the program. \item["-plugin" \var{plugin}] Dynamically load the code of the given \var{plugin} (a ".cmo", ".cma" or ".cmxs" file) in the compiler. \var{plugin} must exist in -the same kind of code as the compiler ({\machine \ocamlx.byte} must load bytecode -plugins, while {\machine \ocamlx.opt} must load native code plugins), and -extension adaptation is done automatically for ".cma" files (to ".cmxs" files -if the compiler is compiled in native code). +the same kind of code as the compiler ({\machine \ocamlx.byte} must load +bytecode plugins, while {\machine \ocamlx.opt} must load native code plugins), +and extension adaptation is done automatically for ".cma" files (to ".cmxs" +files if the compiler is compiled in native code). }%notop \notop{% @@ -556,7 +592,8 @@ errors, the intermediate file is deleted afterwards. After parsing, pipe the abstract syntax tree through the preprocessor \var{command}. The module "Ast_mapper", described in \ifouthtml -chapter~\ref{c:parsinglib}: \ahref{libref/Ast\_mapper.html}{ \texttt{Ast_mapper} } +chapter~\ref{c:parsinglib}: +\ahref{libref/Ast\_mapper.html}{ \texttt{Ast_mapper} } \else section~\ref{Ast-underscoremapper}\fi, implements the external interface of a preprocessor. @@ -587,6 +624,12 @@ runtime, which is useful for debugging pointer problems in low-level code such as C stubs. }%notop +\notop{ +\item["-stop-after" \var{pass}] +Stop compilation after the given compilation pass. The currently +supported passes are: "parsing", "typing". +}%notop + \nat{% \item["-S"] Keep the assembly code produced during the compilation. The assembly @@ -682,8 +725,9 @@ Useful to debug C library problems. \comp{% \item["-vmthread"] -Compile or link multithreaded programs, in combination with the -VM-level "threads" library described in chapter~\ref{c:threads}. +Deprecated since OCaml 4.08.0. Compile or link multithreaded programs, +in combination with the VM-level "threads" library described in +chapter~\ref{c:threads}. }%comp \notop{% diff --git a/manual/manual/htmlman/.gitignore b/manual/manual/htmlman/.gitignore index 3cecdc2c..3500ccc3 100644 --- a/manual/manual/htmlman/.gitignore +++ b/manual/manual/htmlman/.gitignore @@ -1,8 +1,10 @@ *.html *.haux *.hind +compilerlibref libref manual.hmanual manual.hmanual.kwd manual.css *.htoc +*.svg diff --git a/manual/manual/library/.cvsignore b/manual/manual/library/.cvsignore deleted file mode 100644 index 8955ee04..00000000 --- a/manual/manual/library/.cvsignore +++ /dev/null @@ -1,5 +0,0 @@ -*.tex -*.htex -arithstatus.mli -ocamldoc.out -ocamldoc.sty diff --git a/manual/manual/library/.gitignore b/manual/manual/library/.gitignore index 8955ee04..40a8907a 100644 --- a/manual/manual/library/.gitignore +++ b/manual/manual/library/.gitignore @@ -3,3 +3,5 @@ arithstatus.mli ocamldoc.out ocamldoc.sty +compiler_libs.txt + diff --git a/manual/manual/library/Makefile b/manual/manual/library/Makefile index d085f504..453607eb 100644 --- a/manual/manual/library/Makefile +++ b/manual/manual/library/Makefile @@ -1,86 +1,79 @@ -CORE_INTF=Pervasives.tex +SRC = ../../.. -CSLDIR=$(RELEASEDIR) +CSLDIR = $(SRC) -STDLIB_INTF= Arg.tex Array.tex ArrayLabels.tex Char.tex Complex.tex \ - Digest.tex Filename.tex Format.tex \ - Gc.tex Genlex.tex Hashtbl.tex Int32.tex Int64.tex \ - Lazy.tex Lexing.tex List.tex ListLabels.tex Map.tex Marshal.tex \ - MoreLabels.tex Nativeint.tex Obj.tex Oo.tex \ - Parsing.tex Printexc.tex Printf.tex Queue.tex Random.tex Scanf.tex \ - Set.tex Sort.tex Stack.tex Stream.tex String.tex StringLabels.tex Sys.tex \ - Weak.tex Callback.tex Buffer.tex StdLabels.tex \ - Bytes.tex BytesLabels.tex Spacetime.tex +LD_PATH := "$(SRC)/otherlibs/unix/:$(SRC)/otherlibs/str/" +SET_LD_PATH = CAML_LD_LIBRARY_PATH=$(LD_PATH) -COMPILER_LIBS_PLUGIN_HOOKS=Pparse.tex Typemod.tex -COMPILER_LIBS_INTF=Asthelper.tex Astmapper.tex Asttypes.tex \ - Lexer.tex Location.tex Longident.tex Parse.tex Pprintast.tex Printast.tex \ - $(COMPILER_LIBS_PLUGIN_HOOKS) +OCAMLDOC = $(if $(wildcard $(CSLDIR)/ocamldoc/ocamldoc.opt),\ + $(CSLDIR)/ocamldoc/ocamldoc.opt,\ + $(SET_LD_PATH) $(CSLDIR)/runtime/ocamlrun $(CSLDIR)/ocamldoc/ocamldoc) \ + -hide Stdlib -lib Stdlib -nostdlib \ + -pp "$(AWK) -v ocamldoc=true -f $(SRC)/stdlib/expand_module_aliases.awk" + + +#Import mli file lists +include $(SRC)/ocamldoc/Makefile.docfiles + + +TEXQUOTE = $(SRC)/runtime/ocamlrun ../../tools/texquote2 -OTHERLIB_INTF=Unix.tex UnixLabels.tex Str.tex \ +CORE_INTF = Stdlib.tex + +STDLIB_INTF = $(STDLIB_MODs:%=%.tex) + +COMPILER_LIBS_PLUGIN_HOOKS = Pparse.tex Typemod.tex + +COMPILER_LIBS_INTF = Asthelper.tex Astmapper.tex Asttypes.tex \ + Lexer.tex Location.tex Longident.tex Parse.tex Pprintast.tex Printast.tex \ + $(COMPILER_LIBS_PLUGIN_HOOKS) + +OTHERLIB_INTF = Unix.tex UnixLabels.tex Str.tex \ Graphics.tex GraphicsX11.tex \ Thread.tex Mutex.tex Condition.tex Event.tex ThreadUnix.tex \ Dynlink.tex Bigarray.tex -INTF=$(CORE_INTF) $(STDLIB_INTF) $(COMPILER_LIBS_INTF) $(OTHERLIB_INTF) +INTF = $(CORE_INTF) $(STDLIB_INTF) $(COMPILER_LIBS_INTF) $(OTHERLIB_INTF) -BLURB=core.tex builtin.tex stdlib.tex compilerlibs.tex \ +BLURB = core.tex builtin.tex stdlib.tex compilerlibs.tex \ libunix.tex libstr.tex libnum.tex libgraph.tex \ libthreads.tex libdynlink.tex libbigarray.tex -FILES=$(BLURB) $(INTF) - -SRC=../../.. +FILES = $(BLURB) $(INTF) -LD_PATH := $(SRC)/otherlibs/unix/:$(SRC)/otherlibs/str/ -SET_LD_PATH=CAML_LD_LIBRARY_PATH=$(LD_PATH) - -FORMAT=../../tools/format-intf -TEXQUOTE=../../tools/texquote2 - -VPATH=.:$(STDLIB_DIR):$(CSLDIR)/parsing:$(CSLDIR)/otherlibs/unix:$(CSLDIR)/otherlibs/str:$(CSLDIR)/otherlibs/graph:$(CSLDIR)/otherlibs/threads:$(CSLDIR)/otherlibs/dynlink:$(CSLDIR)/otherlibs/bigarray etex-files: $(BLURB) all: libs libs: $(FILES) -OCAMLDOC=$(if $(wildcard $(CSLDIR)/ocamldoc/ocamldoc.opt),\ - $(CSLDIR)/ocamldoc/ocamldoc.opt,\ - $(SET_LD_PATH) $(CSLDIR)/byterun/ocamlrun $(CSLDIR)/ocamldoc/ocamldoc) \ - -nostdlib -initially-opened-module Pervasives - -# Copy and unprefix the standard library when needed -include $(SRC)/ocamldoc/Makefile.unprefix - -$(INTF): interfaces -interfaces: $(STDLIB_CMIS) +# ocamldoc.out is used as witness for the generation of the stdlib tex files to +# avoid issues with parallel make invocations. +$(INTF): ocamldoc.out +ocamldoc.out: $(DOC_ALL) $(OCAMLDOC) -latex \ - -I $(STDLIB_UNPREFIXED) \ - $(STDLIB_MLIS) \ - -sepfiles \ - -latextitle "1,subsection*" \ - -latextitle "2,subsubsection*" \ - -latex-type-prefix "TYP" \ - -latex-module-prefix "" \ - -latex-module-type-prefix "" \ - -latex-value-prefix "" - mv -f Ast_helper.tex Asthelper.tex - mv -f Ast_mapper.tex Astmapper.tex - + $(DOC_ALL_INCLUDES) \ + $(DOC_ALL_MLIS) \ + $(DOC_ALL_TEXT:%=-text %) \ + -sepfiles \ + -latextitle "1,subsection*" \ + -latextitle "2,subsubsection*" \ + -latex-type-prefix "TYP" \ + -latex-module-prefix "" \ + -latex-module-type-prefix "" \ + -latex-value-prefix "" + mv Ast_helper.tex Asthelper.tex + mv Ast_mapper.tex Astmapper.tex + mv Ocaml_operators.tex Ocamloperators.tex + +%.tex: %.etex + $(TEXQUOTE) < $< > $*.texquote_error.tex + mv $*.texquote_error.tex $@ + + +.PHONY: clean clean: - rm -f $(FILES) - -.SUFFIXES: -.SUFFIXES: .tex .etex .mli - -.etex.tex: $(TEXQUOTE) - @$(TEXQUOTE) < $*.etex > $*.texquote_error.tex\ - && mv $*.texquote_error.tex $*.tex\ - || printf "Failure when generating %s\n" $*.tex - - -.mli.tex: $(FORMAT) - $(FORMAT) $< > $*.tex < $< + rm -f *.tex ocamldoc.out ocamldoc.sty + rm -f compiler_libs.txt diff --git a/manual/manual/library/builtin.etex b/manual/manual/library/builtin.etex index 404f5608..81c7f429 100644 --- a/manual/manual/library/builtin.etex +++ b/manual/manual/library/builtin.etex @@ -103,7 +103,8 @@ type int32 \index{int32@\verb`int32`} \begin{ocamldocdescription} The type of signed 32-bit integers. - See the "Int32"[\moduleref{Int32}] module. + Literals for 32-bit integers are suffixed by l. + See the \stdmoduleref{Int32} module. \end{ocamldocdescription} \begin{ocamldoccode} @@ -112,7 +113,8 @@ type int64 \index{int64@\verb`int64`} \begin{ocamldocdescription} The type of signed 64-bit integers. - See the "Int64"[\moduleref{Int64}] module. + Literals for 64-bit integers are suffixed by L. + See the \stdmoduleref{Int64} module. \end{ocamldocdescription} \begin{ocamldoccode} @@ -122,7 +124,8 @@ type nativeint \begin{ocamldocdescription} The type of signed, platform-native integers (32 bits on 32-bit processors, 64 bits on 64-bit processors). - See the "Nativeint"[\moduleref{Nativeint}] module. + Literals for native integers are suffixed by n. + See the \stdmoduleref{Nativeint} module. \end{ocamldocdescription} \begin{ocamldoccode} @@ -133,13 +136,12 @@ type ('a, 'b, 'c, 'd, 'e, 'f) format6 The type of format strings. "'a" is the type of the parameters of the format, "'f" is the result type for the "printf"-style functions, "'b" is the type of the first argument given to "%a" and - "%t" printing functions (see module "Printf"[\moduleref{Printf}]), + "%t" printing functions (see module \stdmoduleref{Printf}), "'c" is the result type of these functions, and also the type of the argument transmitted to the first argument of "kprintf"-style functions, "'d" is the result type for the "scanf"-style functions - (see module "Scanf"[\moduleref{Scanf}]), - and "'e" is the type of the receiver function for the "scanf"-style - functions. + (see module \stdmoduleref{Scanf}), and "'e" is the type of the receiver function + for the "scanf"-style functions. \end{ocamldocdescription} \begin{ocamldoccode} @@ -147,7 +149,7 @@ type 'a lazy_t \end{ocamldoccode} \index{lazyt@\verb`lazy_t`} \begin{ocamldocdescription} - This type is used to implement the "Lazy"[\moduleref{Lazy}] module. + This type is used to implement the \stdmoduleref{Lazy} module. It should not be used directly. \end{ocamldocdescription} diff --git a/manual/manual/library/compiler_libs.mld b/manual/manual/library/compiler_libs.mld new file mode 100644 index 00000000..6e77aa9a --- /dev/null +++ b/manual/manual/library/compiler_libs.mld @@ -0,0 +1,9 @@ +{!indexlist} + +{1 Warning} + This library is part of the internal OCaml compiler API, and is +not the language standard library. + There are no compatibility guarantees between releases, so code written +against these modules must be willing to depend on specific OCaml compiler +versions. + diff --git a/manual/manual/library/compilerlibs.etex b/manual/manual/library/compilerlibs.etex index db924cc5..88abbb82 100644 --- a/manual/manual/library/compilerlibs.etex +++ b/manual/manual/library/compilerlibs.etex @@ -1,5 +1,5 @@ \chapter{The compiler front-end} \label{c:parsinglib}\cutname{parsing.html} -\pdfchapterfold{-1}{The compiler front-end} +\label{Compiler-underscorelibs} % redirect references to compiler_libs.mld here This chapter describes the OCaml front-end, which declares the abstract syntax tree used by the compiler, provides a way to parse, print @@ -29,16 +29,16 @@ type\\*"#load \"compiler-libs/ocamlcommon.cma\";;". \ifouthtml \begin{links} -\item \ahref{libref/Ast\_helper.html}{Module \texttt{Ast_helper}: helper functions for AST construction} -\item \ahref{libref/Ast\_mapper.html}{Module \texttt{Ast_mapper}: -ppx rewriter interface} -\item \ahref{libref/Asttypes.html}{Module \texttt{Asttypes}: auxiliary types used by Parsetree} -% \item \ahref{libref/Lexer.html}{Module \texttt{Lexer}: OCaml syntax lexing} -\item \ahref{libref/Location.html}{Module \texttt{Location}: source code locations} -\item \ahref{libref/Longident.html}{Module \texttt{Longident}: long identifiers} -\item \ahref{libref/Parse.html}{Module \texttt{Parse}: OCaml syntax parsing} -\item \ahref{libref/Parsetree.html}{Module \texttt{Parsetree}: OCaml syntax tree} -\item \ahref{libref/Pprintast.html}{Module \texttt{Pprintast}: OCaml syntax printing} -% \item \ahref{libref/Printast.html}{Module \texttt{Printast}: AST printing} +\item \ahref{compilerlibref/Ast\_helper.html}{Module \texttt{Ast_helper}: helper functions for AST construction} +\item \ahref{compilerlibref/Ast\_mapper.html}{Module \texttt{Ast_mapper}: -ppx rewriter interface} +\item \ahref{compilerlibref/Asttypes.html}{Module \texttt{Asttypes}: auxiliary types used by Parsetree} +% \item \ahref{compilerlibref/Lexer.html}{Module \texttt{Lexer}: OCaml syntax lexing} +\item \ahref{compilerlibref/Location.html}{Module \texttt{Location}: source code locations} +\item \ahref{compilerlibref/Longident.html}{Module \texttt{Longident}: long identifiers} +\item \ahref{compilerlibref/Parse.html}{Module \texttt{Parse}: OCaml syntax parsing} +\item \ahref{compilerlibref/Parsetree.html}{Module \texttt{Parsetree}: OCaml syntax tree} +\item \ahref{compilerlibref/Pprintast.html}{Module \texttt{Pprintast}: OCaml syntax printing} +% \item \ahref{compilerlibref/Printast.html}{Module \texttt{Printast}: AST printing} \end{links} \else @@ -60,11 +60,11 @@ type\\*"#load \"compiler-libs/ocamlcommon.cma\";;". \ifouthtml The following modules provides hooks for compiler plugins: \begin{links} -\item \ahref{libref/Pparse.html}{Module \texttt{Pparse}: OCaml parser driver} -\item \ahref{libref/Typemod.html}{Module \texttt{Typemod}: +\item \ahref{compilerlibref/Pparse.html}{Module \texttt{Pparse}: OCaml parser driver} +\item \ahref{compilerlibref/Typemod.html}{Module \texttt{Typemod}: OCaml module type checking} -\item \ahref{libref/Simplif.html}{Module \texttt{Simplif}: Lambda simplification} -\item \ahref{libref/Clflags.html}{Module \texttt{Clflags}: command line flags} +\item \ahref{compilerlibref/Simplif.html}{Module \texttt{Simplif}: Lambda simplification} +\item \ahref{compilerlibref/Clflags.html}{Module \texttt{Clflags}: command line flags} \end{links} \else \input{Pparse.tex} diff --git a/manual/manual/library/core.etex b/manual/manual/library/core.etex index 58297eab..69707615 100644 --- a/manual/manual/library/core.etex +++ b/manual/manual/library/core.etex @@ -1,5 +1,4 @@ \chapter{The core library} \label{c:corelib}\cutname{core.html} -\pdfchapterfold{-1}{The core library} This chapter describes the OCaml core library, which is composed of declarations for built-in types and exceptions, plus @@ -26,11 +25,12 @@ indexed at the end of this report. \input{builtin.tex} \ifouthtml -\section{Module {\tt Pervasives}: the initially opened module} +\section{Module {\tt Stdlib}: the initially opened module} \begin{links} -\item \ahref{libref/Pervasives.html}{Module \texttt{Pervasives}: the initially opened module} +\item \ahref{libref/Stdlib.html}{Module \texttt{Stdlib}: the initially opened module} +\item \ahref{libref/Pervasives.html}{Module \texttt{Pervasives}: deprecated alias for Stdlib} \end{links} \else -\input{Pervasives.tex} +\input{Stdlib.tex} \fi diff --git a/manual/manual/library/libbigarray.etex b/manual/manual/library/libbigarray.etex index a11d0589..8c8691f8 100644 --- a/manual/manual/library/libbigarray.etex +++ b/manual/manual/library/libbigarray.etex @@ -1,5 +1,4 @@ \chapter{The bigarray library} -\pdfchapterfold{-1}{The bigarray library} %HEVEA\cutname{libbigarray.html} The "bigarray" library has now been integrated into OCaml's standard diff --git a/manual/manual/library/libdynlink.etex b/manual/manual/library/libdynlink.etex index 2d4d92d9..4481ebd4 100644 --- a/manual/manual/library/libdynlink.etex +++ b/manual/manual/library/libdynlink.etex @@ -1,5 +1,4 @@ \chapter{The dynlink library: dynamic loading and linking of object files} -\pdfchapterfold{-1}{The dynlink library: dynamic loading and linking of object files} %HEVEA\cutname{libdynlink.html} The "dynlink" library supports type-safe dynamic loading and linking diff --git a/manual/manual/library/libgraph.etex b/manual/manual/library/libgraph.etex index 28759f5b..7b5b70b4 100644 --- a/manual/manual/library/libgraph.etex +++ b/manual/manual/library/libgraph.etex @@ -1,5 +1,4 @@ \chapter{The graphics library} -\pdfchapterfold{-1}{The graphics library} %HEVEA\cutname{libgraph.html} The "graphics" library provides a set of portable drawing primitives. diff --git a/manual/manual/library/libnum.etex b/manual/manual/library/libnum.etex index 5e53a196..5b5944af 100644 --- a/manual/manual/library/libnum.etex +++ b/manual/manual/library/libnum.etex @@ -1,5 +1,4 @@ \chapter{The num library: arbitrary-precision rational arithmetic} -\pdfchapterfold{-3}{The num library: arbitrary-precision integer and rational arithmetic} %HEVEA\cutname{libnum.html} The "num" library implements integer arithmetic and rational diff --git a/manual/manual/library/libstr.etex b/manual/manual/library/libstr.etex index a1939f8a..10015d80 100644 --- a/manual/manual/library/libstr.etex +++ b/manual/manual/library/libstr.etex @@ -1,5 +1,4 @@ \chapter{The str library: regular expressions and string processing} -\pdfchapterfold{-1}{The str library: regular expressions and string processing} %HEVEA\cutname{libstr.html} The "str" library provides high-level string processing functions, diff --git a/manual/manual/library/libthreads.etex b/manual/manual/library/libthreads.etex index 795373c8..7ad9c7e6 100644 --- a/manual/manual/library/libthreads.etex +++ b/manual/manual/library/libthreads.etex @@ -1,8 +1,12 @@ \chapter{The threads library} \label{c:threads}\cutname{threads.html} -\pdfchapterfold{-5}{The threads library} %HEVEA\cutname{libthreads.html} +\textbf{Warning:} the "threads" library is deprecated since version +4.08.0 of OCaml. Please switch to system threads, which have the same +API. Lightweight threads with VM-level scheduling are provided by +third-party libraries such as Lwt, but with a different API. + The "threads" library allows concurrent programming in OCaml. It provides multiple threads of control (also called lightweight processes) that execute concurrently in the same memory space. Threads diff --git a/manual/manual/library/libunix.etex b/manual/manual/library/libunix.etex index 6514a9f1..42ef42b5 100644 --- a/manual/manual/library/libunix.etex +++ b/manual/manual/library/libunix.etex @@ -1,5 +1,4 @@ \chapter{The unix library: Unix system calls} -\pdfchapterfold{-1}{The unix library: Unix system calls} %HEVEA\cutname{libunix.html} \label{c:unix} @@ -45,7 +44,6 @@ more information on the functions that are not supported under Windows. \section{Module \texttt{UnixLabels}: labelized version of the interface} \label{UnixLabels} \index{UnixLabels (module)@\verb~UnixLabels~ (module)}% -\pdfsection{Module UnixLabels: labelized version of the interface} This module is identical to "Unix"~(\ref{Unix}), and only differs by the addition of labels. You may see these labels directly by looking diff --git a/manual/manual/library/stdlib.etex b/manual/manual/library/stdlib.etex index fb0e5578..7c5c41d2 100644 --- a/manual/manual/library/stdlib.etex +++ b/manual/manual/library/stdlib.etex @@ -1,5 +1,4 @@ \chapter{The standard library} \label{c:stdlib}\cutname{stdlib.html} -\pdfchapterfold{-32}{The standard library} This chapter describes the functions provided by the OCaml standard library. The modules from the standard library are @@ -41,9 +40,13 @@ Here is a short listing, by theme, of the standard library modules. "List" & p.~\pageref{List} & list operations \\ "StdLabels" & p.~\pageref{StdLabels} & labelized versions of the above 4 modules \\ +"Unit" & p.~\pageref{Unit} & unit values \\ +"Bool" & p.~\pageref{Bool} & boolean values \\ "Char" & p.~\pageref{Char} & character operations \\ "Uchar" & p.~\pageref{Uchar} & Unicode characters \\ -"Sort" & p.~\pageref{Sort} & (deprecated) \\ +"Int" & p.~\pageref{Int} & integer values \\ +"Option" & p.~\pageref{Option} & option values \\ +"Result" & p.~\pageref{Result} & result values \\ "Hashtbl" & p.~\pageref{Hashtbl} & hash tables and hash functions \\ "Random" & p.~\pageref{Random} & pseudo-random number generator \\ "Set" & p.~\pageref{Set} & sets over ordered types \\ @@ -97,6 +100,10 @@ be called from C \\ "Spacetime" & p.~\pageref{Spacetime} & memory profiler \\ "Sys" & p.~\pageref{Sys} & system interface \\ \end{tabular} +\subsubsection{Misc:} +\begin{tabular}{lll} +"Fun" & p.~\pageref{Fun} & function values \\ +\end{tabular} \end{latexonly} \ifouthtml @@ -105,6 +112,7 @@ be called from C \\ \item \ahref{libref/Array.html}{Module \texttt{Array}: array operations} \item \ahref{libref/ArrayLabels.html}{Module \texttt{ArrayLabels}: array operations (with labels)} \item \ahref{libref/Bigarray.html}{Module \texttt{Bigarray}: large, multi-dimensional, numerical arrays} +\item \ahref{libref/Bool.html}{Module \texttt{Bool}: boolean values} \item \ahref{libref/Buffer.html}{Module \texttt{Buffer}: extensible buffers} \item \ahref{libref/Bytes.html}{Module \texttt{Bytes}: byte sequences} \item \ahref{libref/BytesLabels.html}{Module \texttt{BytesLabels}: byte sequences (with labels)} @@ -116,9 +124,11 @@ be called from C \\ \item \ahref{libref/Filename.html}{Module \texttt{Filename}: operations on file names} \item \ahref{libref/Float.html}{Module \texttt{Float}: Floating-point numbers} \item \ahref{libref/Format.html}{Module \texttt{Format}: pretty printing} +\item \ahref{libref/Fun.html}{Module \texttt{Fun}: function values} \item \ahref{libref/Gc.html}{Module \texttt{Gc}: memory management control and statistics; finalized values} \item \ahref{libref/Genlex.html}{Module \texttt{Genlex}: a generic lexical analyzer} \item \ahref{libref/Hashtbl.html}{Module \texttt{Hashtbl}: hash tables and hash functions} +\item \ahref{libref/Int}{Module \texttt{Int}: integers} \item \ahref{libref/Int32.html}{Module \texttt{Int32}: 32-bit integers} \item \ahref{libref/Int64.html}{Module \texttt{Int64}: 64-bit integers} \item \ahref{libref/Lazy.html}{Module \texttt{Lazy}: deferred computations} @@ -130,15 +140,16 @@ be called from C \\ \item \ahref{libref/MoreLabels.html}{Module \texttt{MoreLabels}: Include modules \texttt{Hashtbl}, \texttt{Map} and \texttt{Set} with labels} \item \ahref{libref/Nativeint.html}{Module \texttt{Nativeint}: processor-native integers} \item \ahref{libref/Oo.html}{Module \texttt{Oo}: object-oriented extension} +\item \ahref{libref/Option.html}{Module \texttt{Option}: option values} \item \ahref{libref/Parsing.html}{Module \texttt{Parsing}: the run-time library for parsers generated by \texttt{ocamlyacc}} \item \ahref{libref/Printexc.html}{Module \texttt{Printexc}: facilities for printing exceptions} \item \ahref{libref/Printf.html}{Module \texttt{Printf}: formatting printing functions} \item \ahref{libref/Queue.html}{Module \texttt{Queue}: first-in first-out queues} \item \ahref{libref/Random.html}{Module \texttt{Random}: pseudo-random number generator (PRNG)} +\item \ahref{libref/Result.html}{Module \texttt{Result}: result values} \item \ahref{libref/Scanf.html}{Module \texttt{Scanf}: formatted input functions} \item \ahref{libref/Seq.html}{Module \texttt{Seq}: functional iterators} \item \ahref{libref/Set.html}{Module \texttt{Set}: sets over ordered types} -\item \ahref{libref/Sort.html}{Module \texttt{Sort}: deprecated} \item \ahref{libref/Spacetime.html}{Module \texttt{Spacetime}: memory profiler} \item \ahref{libref/Stack.html}{Module \texttt{Stack}: last-in first-out stacks} \item \ahref{libref/StdLabels.html}{Module \texttt{StdLabels}: Include modules \texttt{Array}, \texttt{List} and \texttt{String} with labels} @@ -147,6 +158,7 @@ be called from C \\ \item \ahref{libref/StringLabels.html}{Module \texttt{StringLabels}: string operations (with labels)} \item \ahref{libref/Sys.html}{Module \texttt{Sys}: system interface} \item \ahref{libref/Uchar.html}{Module \texttt{Uchar}: Unicode characters} +\item \ahref{libref/Unit.html}{Module \texttt{Unit}: unit values} \item \ahref{libref/Weak.html}{Module \texttt{Weak}: arrays of weak pointers} \end{links} \else @@ -154,6 +166,7 @@ be called from C \\ \input{Array.tex} \input{ArrayLabels.tex} \input{Bigarray.tex} +\input{Bool.tex} \input{Buffer.tex} \input{Bytes.tex} \input{BytesLabels.tex} @@ -165,9 +178,11 @@ be called from C \\ \input{Filename.tex} \input{Float.tex} \input{Format.tex} +\input{Fun.tex} \input{Gc.tex} \input{Genlex.tex} \input{Hashtbl.tex} +\input{Int.tex} \input{Int32.tex} \input{Int64.tex} \input{Lazy.tex} @@ -179,15 +194,16 @@ be called from C \\ \input{MoreLabels.tex} \input{Nativeint.tex} \input{Oo.tex} +\input{Option.tex} \input{Parsing.tex} \input{Printexc.tex} \input{Printf.tex} \input{Queue.tex} \input{Random.tex} +\input{Result.tex} \input{Scanf.tex} \input{Seq.tex} \input{Set.tex} -\input{Sort.tex} \input{Spacetime.tex} \input{Stack.tex} \input{StdLabels.tex} @@ -196,5 +212,7 @@ be called from C \\ \input{StringLabels.tex} \input{Sys.tex} \input{Uchar.tex} +\input{Unit.tex} \input{Weak.tex} +\input{Ocamloperators.tex} \fi diff --git a/manual/manual/macros.hva b/manual/manual/macros.hva index 343eb7d6..38b816b6 100644 --- a/manual/manual/macros.hva +++ b/manual/manual/macros.hva @@ -12,13 +12,13 @@ font-family: 'Fira Sans'; font-style: normal; font-weight: 400; - src: url('/pub/docs/manual-ocaml/fonts/fira-sans-v8-latin-regular.eot'); /* IE9 Compat Modes */ + src: url('fonts/fira-sans-v8-latin-regular.eot'); /* IE9 Compat Modes */ src: local('Fira Sans Regular'), local('FiraSans-Regular'), - url('/pub/docs/manual-ocaml/fonts/fira-sans-v8-latin-regular.eot?\#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('/pub/docs/manual-ocaml/fonts/fira-sans-v8-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ - url('/pub/docs/manual-ocaml/fonts/fira-sans-v8-latin-regular.woff') format('woff'), /* Modern Browsers */ - url('/pub/docs/manual-ocaml/fonts/fira-sans-v8-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ - url('/pub/docs/manual-ocaml/fonts/fira-sans-v8-latin-regular.svg\#FiraSans') format('svg'); /* Legacy iOS */ + url('fonts/fira-sans-v8-latin-regular.eot?\#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('fonts/fira-sans-v8-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ + url('fonts/fira-sans-v8-latin-regular.woff') format('woff'), /* Modern Browsers */ + url('fonts/fira-sans-v8-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ + url('fonts/fira-sans-v8-latin-regular.svg\#FiraSans') format('svg'); /* Legacy iOS */ \}} % Compact layout @@ -198,3 +198,6 @@ {\enditemize} \newenvironment{maintitle}{\@open{div}{class="maintitle"}}{\@close{div}} + +%%% References to modules in the standard library +\newcommand{\stdmoduleref}[1]{\ahref{libref/#1.html}{\texttt{#1}}} \ No newline at end of file diff --git a/manual/manual/macros.tex b/manual/manual/macros.tex index 454bff2a..471861f8 100644 --- a/manual/manual/macros.tex +++ b/manual/manual/macros.tex @@ -10,12 +10,6 @@ \def\event{$\bowtie$} \def\fromoneto#1#2{$#1 = 1, \ldots, #2$} -% Pour avoir les exposants sur la ligne au-dessus (???) - -\ifplaintext -\fontdimen14\tensy=12pt -\fi - % Numerotation \setcounter{secnumdepth}{2} % Pour numeroter les \subsection \setcounter{tocdepth}{1} % Pour ne pas mettre les \subsection @@ -27,14 +21,10 @@ \def\_{\hbox{\tt\char95}} \def_{\ifmmode\else\_\fi} -\ifplaintext -\def\ttstretch{\tt} -\else \def\ttstretch{\tt\spaceskip=5.77pt plus 1.83pt minus 1.22pt} % La fonte cmr10 a normalement des espaces de 5.25pt non extensibles. % En 11 pt ca fait 5.77 pt. On lui ajoute la meme flexibilite que % cmr10 agrandie a 11 pt. -\fi % Pour la traduction "xxxx" -> {\machine{xxxx}} faite par texquote2 \def\machine#1{\mbox{\ttstretch{#1}}} @@ -178,9 +168,7 @@ %%% Augmenter l'espace entre numero de section % et nom de section dans la table des matieres. -\ifplaintext\else \def\l@section{\@dottedtocline{1}{1.5em}{2.8em}} % D'origine: 2.3 -\fi % Pour alltt @@ -210,42 +198,10 @@ \newpage \phantomsection \twocolumn[{\Large\bf #2 \vskip4ex}] \markright{\uppercase{#2}} \addcontentsline{toc}{chapter}{#2} - \pdfsection{#2} \@input{#1.ind}} -% PDF stuff -- no longer needed, Hyperref does the job - -\def\pdfchapterfold#1#2{} -\def\pdfchapter#1{} -\def\pdfsection#1{} - -%\ifpdf -%\newcount\pdflabel -%\pdflabel=1 -%\def\pdfchapterfold#1#2{ -%\pdfdest num \pdflabel fit -%\pdfoutline goto num \pdflabel count #1 {\arabic{chapter}. #2} -%\global\advance\pdflabel by 1 -%} -%\def\pdfsection#1{ -%\pdfdest num \pdflabel fit -%\pdfoutline goto num \pdflabel {#1} -%\global\advance\pdflabel by 1 -%} -%\else -%\def\pdfchapterfold#1#2{} -%\def\pdfsection#1{} -%\fi -% -%\def\pdfchapter{\pdfchapterfold{0}} - -%%% Pour camlidl - -\def\transl#1{$[\![\mbox{#1}]\!]$} - -%%% Pour les references des modules -\newcommand{\moduleref}[1]{\ref{#1}} -%%% Fin des hacks +%%% References to modules in the standard library +\newcommand{\stdmoduleref}[1]{\hyperref[#1]{\texttt{#1}}[\ref{#1}]} \newenvironment{maintitle}{\begin{center}}{\end{center}} diff --git a/manual/manual/manual.tex b/manual/manual/manual.tex index c318ba76..dbdc5698 100644 --- a/manual/manual/manual.tex +++ b/manual/manual/manual.tex @@ -1,6 +1,8 @@ \documentclass[11pt]{book} -\usepackage[latin1]{inputenc} -%HEVEA\@def@charset{US-ASCII}% +\usepackage{ae} +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +% HEVEA\@def@charset{UTF-8}% \usepackage{alltt} \usepackage{fullpage} \usepackage{syntaxdef} @@ -10,10 +12,6 @@ \usepackage{caml-sl} \usepackage{ocamldoc} \usepackage{xspace} -\newif\ifplaintext -\plaintextfalse -%\newif\ifpdf -%\pdffalse \input{macros.tex} @@ -28,7 +26,7 @@ } \fi -\usepackage{hyperref} +\usepackage[colorlinks,linkcolor=blue]{hyperref} %\makeatletter \def\@wrindex#1#2{\xdef \@indexfile{\csname #1@idxfile\endcsname}\@@wrindex#2||\\}\makeatother \def\th{^{\hbox{\scriptsize th}}} diff --git a/manual/manual/pdfmanual.tex b/manual/manual/pdfmanual.tex deleted file mode 100644 index 73264605..00000000 --- a/manual/manual/pdfmanual.tex +++ /dev/null @@ -1,31 +0,0 @@ -%\pdfoutput=1 -\pdfpagewidth=21cm -\pdfpageheight=11in -\pdfcompresslevel=7 - -\documentclass[11pt]{book} - -\usepackage[latin1]{inputenc} -\usepackage{alltt} -\usepackage{fullpage} -\usepackage{syntaxdef} -\usepackage{multind} -\usepackage{html} -\usepackage{textcomp} -\usepackage{caml-sl} -\usepackage{ocamldoc} -\usepackage{xspace} - -\newif\ifplaintext -\plaintextfalse -%\newif\ifpdf -%\pdftrue -\input macros.tex - -\usepackage[colorlinks,linkcolor=blue]{hyperref} -\def\th{^{\hbox{\scriptsize th}}} - -\raggedbottom -\input{version.tex} - -\input allfiles.tex diff --git a/manual/manual/plaintext.tex b/manual/manual/plaintext.tex deleted file mode 100644 index 86201b4b..00000000 --- a/manual/manual/plaintext.tex +++ /dev/null @@ -1,17 +0,0 @@ -\documentclass[11pt]{report} - -\usepackage{plaintext} -\usepackage[latin1]{inputenc} -\usepackage{alltt} -\usepackage{fullpage} -\usepackage{syntaxdef} -\usepackage{multind} -\usepackage{html} -\usepackage{caml-sl} - -\newif\ifplaintext -\plaintexttrue -%\newif\ifpdf -%\pdffalse -\input macros.tex -\input allfiles.tex diff --git a/manual/manual/refman/.cvsignore b/manual/manual/refman/.cvsignore deleted file mode 100644 index 81ccbe71..00000000 --- a/manual/manual/refman/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -*.tex -*.htex diff --git a/manual/manual/refman/Makefile b/manual/manual/refman/Makefile index 61883ae5..2310e992 100644 --- a/manual/manual/refman/Makefile +++ b/manual/manual/refman/Makefile @@ -1,43 +1,35 @@ -FILES= refman.tex lex.tex names.tex values.tex const.tex types.tex \ +TOPDIR = ../../.. +include $(TOPDIR)/Makefile.tools + +LD_PATH = "$(TOPDIR)/otherlibs/str:$(TOPDIR)/otherlibs/unix" + +TOOLS = ../../tools +CAMLLATEX = $(SET_LD_PATH) \ + $(OCAMLRUN) $(TOPDIR)/tools/caml-tex \ + -repo-root $(TOPDIR) -n 80 -v false +TEXQUOTE = $(OCAMLRUN) $(TOOLS)/texquote2 +TRANSF = $(SET_LD_PATH) $(OCAMLRUN) $(TOOLS)/transf + + +FILES = refman.tex lex.tex names.tex values.tex const.tex types.tex \ patterns.tex expr.tex typedecl.tex modtypes.tex modules.tex compunit.tex \ exten.tex classes.tex -TOPDIR=../../.. -include $(TOPDIR)/Makefile.tools +etex-files: $(FILES) +all: $(FILES) -LD_PATH="$(TOPDIR)/otherlibs/str:$(TOPDIR)/otherlibs/unix" -CAMLLATEX=$(SET_LD_PATH) $(OCAMLRUN) ../../tools/caml-tex2 \ - -caml "TERM=norepeat $(OCAML)" -n 80 -v false -TRANSF=$(SET_LD_PATH) $(OCAMLRUN) ../../tools/transf -TEXQUOTE=../../tools/texquote2 +%.gen.tex: %.etex + $(CAMLLATEX) $< -o $*_camltex.tex + $(TRANSF) < $*_camltex.tex > $*.transf_error.tex + mv $*.transf_error.tex $@ -ALLFILES=$(FILES) +%.tex: %.gen.tex + $(TEXQUOTE) < $< > $*.texquote_error.tex + mv $*.texquote_error.tex $@ -etex-files: $(ALLFILES) -all: $(ALLFILES) +.PHONY: clean clean: - rm -f $(ALLFILES) - -.SUFFIXES: -.SUFFIXES: .etex .tex - -exten.tex:exten.etex - @$(CAMLLATEX) -o $*.caml_tex_error.tex $*.etex \ - && mv $*.caml_tex_error.tex $*.gen.tex \ - && $(TRANSF) < $*.gen.tex > $*.transf_error.tex \ - && mv $*.transf_error.tex $*.gen.tex\ - && $(TEXQUOTE) < $*.gen.tex > $*.texquote_error.tex\ - && mv $*.texquote_error.tex $*.tex\ - || printf "Failure when generating %s\n" $*.tex -.etex.tex: - @$(TRANSF) < $*.etex > $*.transf_error.tex \ - && mv $*.transf_error.tex $*.gen.tex\ - && $(TEXQUOTE) < $*.gen.tex > $*.texquote_error.tex\ - && mv $*.texquote_error.tex $*.tex\ - || printf "Failure when generating %s\n" $*.tex - - -$(ALLFILES): ../../tools/transf $(TEXQUOTE) + rm -f *.tex diff --git a/manual/manual/refman/classes.etex b/manual/manual/refman/classes.etex index 2480357c..d9ee57bc 100644 --- a/manual/manual/refman/classes.etex +++ b/manual/manual/refman/classes.etex @@ -1,5 +1,4 @@ \section{Classes} -\pdfsection{Classes} %HEVEA\cutname{classes.html} Classes are defined using a small language, similar to the module language. @@ -275,7 +274,7 @@ class-body: ['(' pattern [':' typexpr] ')'] { class-field } The expression @'object' class-body 'end'@ denotes a class body. This is the prototype for an object : it lists the -instance variables and methods of an objet of this class. +instance variables and methods of an object of this class. A class body is a class value: it is not evaluated at once. Rather, its components are evaluated each time an object is created. diff --git a/manual/manual/refman/compunit.etex b/manual/manual/refman/compunit.etex index 6c8c09f7..14d5d996 100644 --- a/manual/manual/refman/compunit.etex +++ b/manual/manual/refman/compunit.etex @@ -1,5 +1,4 @@ \section{Compilation units} -\pdfsection{Compilation units} %HEVEA\cutname{compunit.html} \begin{syntax} diff --git a/manual/manual/refman/const.etex b/manual/manual/refman/const.etex index c503668d..9789522c 100644 --- a/manual/manual/refman/const.etex +++ b/manual/manual/refman/const.etex @@ -1,5 +1,4 @@ \section{Constants} -\pdfsection{Constants} %HEVEA\cutname{const.html} \ikwd{false\@\texttt{false}} @@ -10,6 +9,9 @@ \begin{syntax} constant: integer-literal + | int32-literal + | int64-literal + | nativeint-literal | float-literal | char-literal | string-literal @@ -22,14 +24,13 @@ constant: | "[|""|]" | "`"tag-name \end{syntax} -See also the following language extensions: -\hyperref[s:ext-integer]{integer literals for types \texttt{int32}, \texttt{int64} -and \texttt{nativeint}}, \hyperref[s:quoted-strings]{quoted strings} -and \hyperref[s:extension-literals]{extension literals}. +See also the following language extension: +\hyperref[s:extension-literals]{extension literals}. The syntactic class of constants comprises literals from the four base types (integers, floating-point numbers, characters, character -strings), and constant constructors from both normal and polymorphic -variants, as well as the special constants @"false"@, @"true"@, @"("")"@, +strings), the integer variants, and constant constructors +from both normal and polymorphic variants, as well as the special +constants @"false"@, @"true"@, @"("")"@, @"[""]"@, and @"[|""|]"@, which behave like constant constructors, and @"begin" "end"@, which is equivalent to @'('')'@. diff --git a/manual/manual/refman/expr.etex b/manual/manual/refman/expr.etex index 6e47c03a..faf50231 100644 --- a/manual/manual/refman/expr.etex +++ b/manual/manual/refman/expr.etex @@ -1,5 +1,4 @@ \section{Expressions\label{s:value-expr}} -\pdfsection{Expressions} %HEVEA\cutname{expr.html} \ikwd{in\@\texttt{in}|see{\texttt{let}}} \ikwd{and\@\texttt{and}} @@ -63,6 +62,7 @@ expr: | 'fun' {{ parameter }} [ ':' typexpr ] '->' expr | 'try' expr 'with' pattern-matching | 'let' ['rec'] let-binding { 'and' let-binding } 'in' expr + | "let" "exception" constr-decl "in" expr | 'new' class-path | 'object' class-body 'end' | expr '#' method-name @@ -70,7 +70,7 @@ expr: | inst-var-name '<-' expr | '(' expr ':>' typexpr ')' | '(' expr ':' typexpr ':>' typexpr ')' - | '{<' [ inst-var-name '=' expr { ';' inst-var-name '=' expr } [';'] ] '>}' + | '{<' [ inst-var-name ['=' expr] { ';' inst-var-name ['=' expr] } [';'] ] '>}' | 'assert' expr | 'lazy' expr | 'let' 'module' module-name { '(' module-name ':' module-type ')' } @@ -113,19 +113,20 @@ parameter: | '?' label-name ':' '(' pattern [':' typexpr] ['=' expr] ')' \end{syntax} See also the following language extensions: -\hyperref[s:object-notations]{object notations}, \hyperref[s-first-class-modules]{first-class modules}, \hyperref[s:explicit-overriding-open]{overriding in open statements}, \hyperref[s:bigarray-access]{syntax for Bigarray access}, \hyperref[s:attributes]{attributes}, -\hyperref[s:extension-nodes]{extension nodes}, -\hyperref[s:local-exceptions]{local exceptions} +\hyperref[s:extension-nodes]{extension nodes} and \hyperref[s:index-operators]{extended indexing operators}. +\subsection{Precedence and associativity} The table below shows the relative precedences and associativity of operators and non-closed constructions. The constructions with higher precedence come first. For infix and prefix symbols, we write ``"*"\ldots'' to mean ``any symbol starting with "*"''. +% Note that this table is duplicated in stdlib/ocaml_operators.mld, +% these tables should be kept in sync with the one below. \ikwd{or\@\texttt{or}}% \ikwd{if\@\texttt{if}}% \ikwd{fun\@\texttt{fun}}% @@ -143,7 +144,7 @@ precedence come first. For infix and prefix symbols, we write \begin{tableau}{|l|l|}{Construction or operator}{Associativity} \entree{prefix-symbol}{--} \entree{". .( .[ .{" (see section~\ref{s:bigarray-access})}{--} -\entree{"#"\ldots}{--} +\entree{"#"\ldots}{left} \entree{function application, constructor application, tag application, "assert", "lazy"}{left} @@ -430,6 +431,19 @@ and allow one to use this polymorphism in recursive occurrences (when using @"let" "rec"@). Note however that this is a normal polymorphic type, unifiable with any instance of itself. +It is possible to define local exceptions in expressions: +@ "let" exception constr-decl "in" expr @ . +The syntactic scope of the exception constructor is the inner +expression, but nothing prevents exception values created with this +constructor from escaping this scope. Two executions of the definition +above result in two incompatible exception constructors (as for any +exception definition). For instance, the following assertion is +true: +\begin{verbatim} + let gen () = let exception A in A + let () = assert(gen () <> gen ()) +\end{verbatim} + \subsection{Control structures} \subsubsection*{Sequence} @@ -806,13 +820,12 @@ variable @inst-var-name@, which must be mutable. The whole expression \subsubsection*{Object duplication} An object can be duplicated using the library function "Oo.copy" -(see -\ifouthtml \ahref{libref/Oo.html}{Module \texttt{Oo}}\else -section~\ref{Oo}\fi). Inside a method, the expression -@ '{<' inst-var-name '=' expr { ';' inst-var-name '=' expr } '>}'@ +(see module \stdmoduleref{Oo}). Inside a method, the expression +@ '{<' [inst-var-name ['=' expr] { ';' inst-var-name ['=' expr] }] '>}'@ returns a copy of self with the given instance variables replaced by -the values of the associated expressions; other instance variables -have the same value in the returned object as in self. +the values of the associated expressions. A single instance variable +name @id@ stands for @id '=' id@. Other instance variables have the same +value in the returned object as in self. \subsection{Coercions} \label{s:coercions} @@ -970,14 +983,14 @@ The expression locally binds the module expression @module-expr@ to the identifier @module-name@ during the evaluation of the expression @expr@. It then returns the value of @expr@. For example: -\begin{verbatim} - let remove_duplicates comparison_fun string_list = - let module StringSet = - Set.Make(struct type t = string - let compare = comparison_fun end) in - StringSet.elements - (List.fold_right StringSet.add string_list StringSet.empty) -\end{verbatim} +\begin{caml_example}{verbatim} +let remove_duplicates comparison_fun string_list = + let module StringSet = + Set.Make(struct type t = string + let compare = comparison_fun end) in + StringSet.elements + (List.fold_right StringSet.add string_list StringSet.empty) +\end{caml_example} \subsubsection*{Local opens} \ikwd{let\@\texttt{let}} diff --git a/manual/manual/refman/exten.etex b/manual/manual/refman/exten.etex index 080354d8..c9a3756f 100644 --- a/manual/manual/refman/exten.etex +++ b/manual/manual/refman/exten.etex @@ -1,39 +1,12 @@ \chapter{Language extensions} \label{c:extensions} -\pdfchapter{Language extensions} %HEVEA\cutname{extn.html} This chapter describes language extensions and convenience features that are implemented in OCaml, but not described in the OCaml reference manual. -\section{Integer literals for types \texttt{int32}, \texttt{int64} - and \texttt{nativeint}} \label{s:ext-integer} - -(Introduced in Objective Caml 3.07) - -\begin{syntax} -constant: ... - | int32-literal - | int64-literal - | nativeint-literal -; -int32-literal: integer-literal 'l' -; -int64-literal: integer-literal 'L' -; -nativeint-literal: integer-literal 'n' -\end{syntax} - -An integer literal can be followed by one of the letters "l", "L" or "n" -to indicate that this integer has type "int32", "int64" or "nativeint" -respectively, instead of the default type "int" for integer literals. -\index{int32\@\verb`int32`} -\index{int64\@\verb`int64`} -\index{nativeint\@\verb`nativeint`} -The library modules "Int32"[\moduleref{Int32}], -"Int64"[\moduleref{Int64}] and "Nativeint"[\moduleref{Nativeint}] -provide operations on these integer types. +%HEVEA\cutdef{section} \section{Recursive definitions of values} \label{s:letrecvalues} (Introduced in Objective Caml 1.00) @@ -103,34 +76,6 @@ An expression @@e@@ is said to be {\em immediately linked to} the variable is immediately linked to @name@. \end{itemize} -\section{Lazy patterns} \label{s:lazypat} - -\ikwd{lazy\@\texttt{lazy}} - -(Introduced in Objective Caml 3.11) - -\begin{syntax} -pattern: ... - | 'lazy' pattern -\end{syntax} - -The pattern @"lazy" pattern@ matches a value \var{v} of type "Lazy.t", -provided @pattern@ matches the result of forcing \var{v} with -"Lazy.force". A successful match of a pattern containing @"lazy"@ -sub-patterns forces the corresponding parts of the value being matched, even -those that imply no test such as @"lazy" value-name@ or @"lazy" "_"@. -Matching a value with a @pattern-matching@ where some patterns -contain @"lazy"@ sub-patterns may imply forcing parts of the value, -even when the pattern selected in the end has no @"lazy"@ sub-pattern. - -For more information, see the description of module "Lazy" in the -standard library ( -\ifouthtml -\ahref{libref/Lazy.html}{Module \texttt{Lazy}}\else section~\ref{Lazy}\fi). -% -\index{Lazy (module)\@\verb`Lazy` (module)}% -\index{force\@\verb`force`}% - \section{Recursive modules} \label{s-recursive-modules} \ikwd{module\@\texttt{module}} \ikwd{and\@\texttt{and}} @@ -158,31 +103,31 @@ Recursive module definitions, introduced by the @"module rec"@ \ldots @module-expr@ and the @module-type@ to refer recursively to the module identifiers being defined. A typical example of a recursive module definition is: -\begin{verbatim} - module rec A : sig - type t = Leaf of string | Node of ASet.t - val compare: t -> t -> int - end - = struct - type t = Leaf of string | Node of ASet.t - let compare t1 t2 = - match (t1, t2) with - (Leaf s1, Leaf s2) -> Pervasives.compare s1 s2 - | (Leaf _, Node _) -> 1 - | (Node _, Leaf _) -> -1 - | (Node n1, Node n2) -> ASet.compare n1 n2 - end - and ASet : Set.S with type elt = A.t - = Set.Make(A) -\end{verbatim} +\begin{caml_example*}{verbatim} +module rec A : sig + type t = Leaf of string | Node of ASet.t + val compare: t -> t -> int +end = struct + type t = Leaf of string | Node of ASet.t + let compare t1 t2 = + match (t1, t2) with + | (Leaf s1, Leaf s2) -> Stdlib.compare s1 s2 + | (Leaf _, Node _) -> 1 + | (Node _, Leaf _) -> -1 + | (Node n1, Node n2) -> ASet.compare n1 n2 +end +and ASet + : Set.S with type elt = A.t + = Set.Make(A) +\end{caml_example*} It can be given the following specification: -\begin{verbatim} - module rec A : sig - type t = Leaf of string | Node of ASet.t - val compare: t -> t -> int - end - and ASet : Set.S with type elt = A.t -\end{verbatim} +\begin{caml_example*}{signature} +module rec A : sig + type t = Leaf of string | Node of ASet.t + val compare: t -> t -> int +end +and ASet : Set.S with type elt = A.t +\end{caml_example*} This is an experimental extension of OCaml: the class of recursive definitions accepted, as well as its dynamic semantics are @@ -253,18 +198,17 @@ The typical use of private types is in the export signature of a module, to ensure that construction of values of the private type always go through the functions provided by the module, while still allowing pattern-matching outside the defining module. For example: -\begin{verbatim} - module M : sig - type t = private A | B of int - val a : t - val b : int -> t - end - = struct - type t = A | B of int - let a = A - let b n = assert (n > 0); B n - end -\end{verbatim} +\begin{caml_example*}{verbatim} +module M : sig + type t = private A | B of int + val a : t + val b : int -> t +end = struct + type t = A | B of int + let a = A + let b n = assert (n > 0); B n +end +\end{caml_example*} Here, the @"private"@ declaration ensures that in any value of type "M.t", the argument to the "B" constructor is always a positive integer. @@ -291,18 +235,17 @@ advantage of this knowledge to perform type-directed optimizations. The following example uses a private type abbreviation to define a module of nonnegative integers: -\begin{verbatim} - module N : sig - type t = private int - val of_int: int -> t - val to_int: t -> int - end - = struct - type t = int - let of_int n = assert (n >= 0); n - let to_int n = n - end -\end{verbatim} +\begin{caml_example*}{verbatim} +module N : sig + type t = private int + val of_int: int -> t + val to_int: t -> int +end = struct + type t = int + let of_int n = assert (n >= 0); n + let to_int n = n +end +\end{caml_example*} The type "N.t" is incompatible with "int", ensuring that nonnegative integers and regular integers are not confused. However, if "x" has type "N.t", the coercion "(x :> int)" is legal and returns the @@ -336,48 +279,48 @@ above should denote either an object type or a polymorphic variant type, with some possibility of refinement left. If the private declaration is used in an interface, the corresponding implementation may either provide a ground instance, or a refined private type. -\begin{verbatim} - module M : sig type c = private < x : int; .. > val o : c end = - struct - class c = object method x = 3 method y = 2 end - let o = new c - end -\end{verbatim} +\begin{caml_example*}{verbatim} +module M : sig type c = private < x : int; .. > val o : c end = +struct + class c = object method x = 3 method y = 2 end + let o = new c +end +\end{caml_example*} This declaration does more than hiding the "y" method, it also makes the type "c" incompatible with any other closed object type, meaning that only "o" will be of type "c". In that respect it behaves similarly to private record types. But private row types are more flexible with respect to incremental refinement. This feature can be used in combination with functors. -\begin{verbatim} - module F(X : sig type c = private < x : int; .. > end) = - struct - let get_x (o : X.c) = o#x - end - module G(X : sig type c = private < x : int; y : int; .. > end) = - struct - include F(X) - let get_y (o : X.c) = o#y - end -\end{verbatim} +\begin{caml_example*}{verbatim} +module F(X : sig type c = private < x : int; .. > end) = +struct + let get_x (o : X.c) = o#x +end +module G(X : sig type c = private < x : int; y : int; .. > end) = +struct + include F(X) + let get_y (o : X.c) = o#y +end +\end{caml_example*} A polymorphic variant type [t], for example -\begin{verbatim} - type t = [ `A of int | `B of bool ] -\end{verbatim} +\begin{caml_example*}{verbatim} +type t = [ `A of int | `B of bool ] +\end{caml_example*} can be refined in two ways. A definition [u] may add new field to [t], and the declaration -\begin{verbatim} - type u = private [> t] -\end{verbatim} +\begin{caml_example*}{verbatim} +type u = private [> t] +\end{caml_example*} will keep those new fields abstract. Construction of values of type [u] is possible using the known variants of [t], but any pattern-matching will require a default case to handle the potential extra fields. Dually, a declaration [u] may restrict the fields of [t] through abstraction: the declaration -\begin{verbatim} - type v = private [< t > `A] -\end{verbatim} +\begin{caml_example*}{verbatim} +type v = private [< t > `A] +\end{caml_example*} corresponds to private variant types. One cannot create a value of the private type [v], except using the constructors that are explicitly listed as present, "(`A n)" in this example; yet, when @@ -415,30 +358,6 @@ For example, @module-path'.['pattern']'@ is equivalent to @module-path'.(['pattern'])'@, and @module-path'.[|' pattern '|]'@ is equivalent to @module-path'.([|' pattern '|])'@. -\section{Object copy short notations} \label{s:object-notations} -\ikwd{with\@\texttt{with}} - -(Introduced in OCaml 4.03) - -\begin{syntax} -expr: - ... - | '{' '<' expr 'with' field ['=' expr] { ';' field ['=' expr] } [';'] '>' '}' -\end{syntax} - -In an object copy expression, -a single identifier @id@ stands for @id '=' id@, and a qualified identifier -@module-path '.' id@ stands for @module-path '.' id '=' id@. -For example, all following methods are equivalent: -\begin{verbatim} - object - val x=0. val y=0. val z=0. - method f_0 x y = {< x; y >} - method f_1 x y = {< x = x; y >} - method f_2 x y = {< x=x ; y = y >} - end -\end{verbatim} - \section{Locally abstract types} \ikwd{type\@\texttt{type}} \ikwd{fun\@\texttt{fun}} \label{s:locally-abstract} @@ -461,11 +380,11 @@ syntax has been chosen to fit nicely in the context of function declarations, where it is generally used. It is possible to freely mix regular function parameters with pseudo type parameters, as in: \begin{caml_example*}{verbatim} - let f = fun (type t) (foo : t list) -> assert false[@ellipsis] +let f = fun (type t) (foo : t list) -> (assert false)[@ellipsis] \end{caml_example*} and even use the alternative syntax for declaring functions: \begin{caml_example*}{verbatim} - let f (type t) (foo : t list) = assert false[@ellipsis] +let f (type t) (foo : t list) = (assert false)[@ellipsis] \end{caml_example*} If several locally abstract types need to be introduced, it is possible to use the syntax @@ -473,27 +392,27 @@ the syntax as syntactic sugar for @"fun" '(' "type" typeconstr-name_1 ')' "->" \ldots "->" "fun" '(' "type" typeconstr-name_n ')' "->" expr@. For instance, \begin{caml_example*}{verbatim} - let f = fun (type t u v) -> fun (foo : (t * u * v) list) -> assert false[@ellipsis] - let f' (type t u v) (foo : (t * u * v) list) = assert false[@ellipsis] +let f = fun (type t u v) -> fun (foo : (t * u * v) list) -> (assert false)[@ellipsis] +let f' (type t u v) (foo : (t * u * v) list) = (assert false)[@ellipsis] \end{caml_example} This construction is useful because the type constructors it introduces can be used in places where a type variable is not allowed. For instance, one can use it to define an exception in a local module within a polymorphic function. -\begin{verbatim} - let f (type t) () = - let module M = struct exception E of t end in - (fun x -> M.E x), (function M.E x -> Some x | _ -> None) -\end{verbatim} +\begin{caml_example*}{verbatim} +let f (type t) () = + let module M = struct exception E of t end in + (fun x -> M.E x), (function M.E x -> Some x | _ -> None) +\end{caml_example*} Here is another example: -\begin{verbatim} - let sort_uniq (type s) (cmp : s -> s -> int) = - let module S = Set.Make(struct type t = s let compare = cmp end) in - fun l -> - S.elements (List.fold_right S.add l S.empty) -\end{verbatim} +\begin{caml_example*}{verbatim} +let sort_uniq (type s) (cmp : s -> s -> int) = + let module S = Set.Make(struct type t = s let compare = cmp end) in + fun l -> + S.elements (List.fold_right S.add l S.empty) +\end{caml_example*} It is also extremely useful for first-class modules (see section~\ref{s-first-class-modules}) and generalized algebraic datatypes @@ -519,13 +438,13 @@ polymorphic the type variable it introduces, but it can be combined with explicit polymorphic annotations where needed. The above rule is provided as syntactic sugar to make this easier: \begin{caml_example*}{verbatim} - let rec f : type t1 t2. t1 * t2 list -> t1 = assert false[@ellipsis] +let rec f : type t1 t2. t1 * t2 list -> t1 = (assert false)[@ellipsis] \end{caml_example*} \noindent is automatically expanded into \begin{caml_example*}{verbatim} - let rec f : 't1 't2. 't1 * 't2 list -> 't1 = - fun (type t1) (type t2) -> ( assert false[@ellipsis] : t1 * t2 list -> t1) +let rec f : 't1 't2. 't1 * 't2 list -> 't1 = + fun (type t1) (type t2) -> ( (assert false)[@ellipsis] : t1 * t2 list -> t1) \end{caml_example*} This syntax can be very useful when defining recursive functions involving GADTs, see the section~\ref{s:gadts} for a more detailed explanation. @@ -621,53 +540,60 @@ Each implementation is a structure that we can encapsulate as a first-class module, then store in a data structure such as a hash table: \begin{caml_example*}{verbatim} - module type DEVICE = sig [@@@ellipsis] end - let devices : (string, (module DEVICE)) Hashtbl.t = Hashtbl.create 17 +type picture = unit[@ellipsis] +module type DEVICE = sig + val draw : picture -> unit + [@@@ellipsis] +end +let devices : (string, (module DEVICE)) Hashtbl.t = Hashtbl.create 17 - module SVG = struct [@@@ellipsis] end - let _ = Hashtbl.add devices "SVG" (module SVG : DEVICE) +module SVG = struct let draw () = () [@@ellipsis] end +let _ = Hashtbl.add devices "SVG" (module SVG : DEVICE) - module PDF = struct [@@@ellipsis] end - let _ = Hashtbl.add devices "PDF" (module PDF: DEVICE) +module PDF = struct let draw () = () [@@ellipsis] end +let _ = Hashtbl.add devices "PDF" (module PDF: DEVICE) \end{caml_example*} + We can then select one implementation based on command-line arguments, for instance: -\begin{verbatim} - module Device = - (val (try Hashtbl.find devices (parse_cmdline()) - with Not_found -> eprintf "Unknown device %s\n"; exit 2) - : DEVICE) -\end{verbatim} +\begin{caml_example*}{verbatim} +let parse_cmdline () = "SVG"[@ellipsis] +module Device = + (val (let device_name = parse_cmdline () in + try Hashtbl.find devices device_name + with Not_found -> + Printf.eprintf "Unknown device %s\n" device_name; + exit 2) + : DEVICE) +\end{caml_example*} Alternatively, the selection can be performed within a function: -\begin{verbatim} - let draw_using_device device_name picture = - let module Device = - (val (Hashtbl.find devices device_name) : DEVICE) - in - Device.draw picture -\end{verbatim} +\begin{caml_example*}{verbatim} +let draw_using_device device_name picture = + let module Device = + (val (Hashtbl.find devices device_name) : DEVICE) + in + Device.draw picture +\end{caml_example*} \paragraph{Advanced examples} With first-class modules, it is possible to parametrize some code over the implementation of a module without using a functor. -\begin{verbatim} - let sort (type s) (module Set : Set.S with type elt = s) l = - Set.elements (List.fold_right Set.add l Set.empty) - val sort : (module Set.S with type elt = 'a) -> 'a list -> 'a list -\end{verbatim} +\begin{caml_example}{verbatim} +let sort (type s) (module Set : Set.S with type elt = s) l = + Set.elements (List.fold_right Set.add l Set.empty) +\end{caml_example} To use this function, one can wrap the "Set.Make" functor: -\begin{verbatim} - let make_set (type s) cmp = - let module S = Set.Make(struct - type t = s - let compare = cmp - end) in - (module S : Set.S with type elt = s) - val make_set : ('a -> 'a -> int) -> (module Set.S with type elt = 'a) -\end{verbatim} +\begin{caml_example}{verbatim} +let make_set (type s) cmp = + let module S = Set.Make(struct + type t = s + let compare = cmp + end) in + (module S : Set.S with type elt = s) +\end{caml_example} \iffalse Another advanced use of first-class module is to encode existential @@ -675,38 +601,38 @@ types. In particular, they can be used to simulate generalized algebraic data types (GADT). To demonstrate this, we first define a type of witnesses for type equalities: -\begin{verbatim} - module TypEq : sig - type ('a, 'b) t - val apply: ('a, 'b) t -> 'a -> 'b - val refl: ('a, 'a) t - val sym: ('a, 'b) t -> ('b, 'a) t - end = struct - type ('a, 'b) t = ('a -> 'b) * ('b -> 'a) - let refl = (fun x -> x), (fun x -> x) - let apply (f, _) x = f x - let sym (f, g) = (g, f) - end -\end{verbatim} +\begin{caml_example*}{verbatim} +module TypEq : sig + type ('a, 'b) t + val apply: ('a, 'b) t -> 'a -> 'b + val refl: ('a, 'a) t + val sym: ('a, 'b) t -> ('b, 'a) t +end = struct + type ('a, 'b) t = ('a -> 'b) * ('b -> 'a) + let refl = (fun x -> x), (fun x -> x) + let apply (f, _) x = f x + let sym (f, g) = (g, f) +end +\end{caml_example*} We can then define a parametrized algebraic data type whose constructors provide some information about the type parameter: -\begin{verbatim} - module rec Typ : sig - module type PAIR = sig - type t and t1 and t2 - val eq: (t, t1 * t2) TypEq.t - val t1: t1 Typ.typ - val t2: t2 Typ.typ - end - - type 'a typ = - | Int of ('a, int) TypEq.t - | String of ('a, string) TypEq.t - | Pair of (module PAIR with type t = 'a) - end = Typ -\end{verbatim} +\begin{caml_example*}{verbatim} +module rec Typ : sig + module type PAIR = sig + type t and t1 and t2 + val eq: (t, t1 * t2) TypEq.t + val t1: t1 Typ.typ + val t2: t2 Typ.typ + end + + type 'a typ = + | Int of ('a, int) TypEq.t + | String of ('a, string) TypEq.t + | Pair of (module PAIR with type t = 'a) +end = Typ +\end{caml_example*} Values of type "'a typ" are supposed to be runtime representations for the type "'a". The constructors "Int" and "String" are easy: they @@ -719,40 +645,40 @@ shows how to use first-class modules to simulate existentials. Here is how to construct values of type "'a typ": -\begin{verbatim} - let int = Typ.Int TypEq.refl - - let str = Typ.String TypEq.refl - - let pair (type s1) (type s2) t1 t2 = - let module P = struct - type t = s1 * s2 - type t1 = s1 - type t2 = s2 - let eq = TypEq.refl - let t1 = t1 - let t2 = t2 - end in - let pair = (module P : Typ.PAIR with type t = s1 * s2) in - Typ.Pair pair -\end{verbatim} +\begin{caml_example*}{verbatim} +let int = Typ.Int TypEq.refl + +let str = Typ.String TypEq.refl + +let pair (type s1) (type s2) t1 t2 = + let module P = struct + type t = s1 * s2 + type t1 = s1 + type t2 = s2 + let eq = TypEq.refl + let t1 = t1 + let t2 = t2 + end in + let pair = (module P : Typ.PAIR with type t = s1 * s2) in + Typ.Pair pair +\end{caml_example*} And finally, here is an example of a polymorphic function that takes the runtime representation of some type "'a" and a value of the same type, then pretty-prints the value into a string: -\begin{verbatim} - open Typ - let rec to_string: 'a. 'a Typ.typ -> 'a -> string = - fun (type s) t x -> - match t with - | Int eq -> string_of_int (TypEq.apply eq x) - | String eq -> Printf.sprintf "%S" (TypEq.apply eq x) - | Pair p -> - let module P = (val p : PAIR with type t = s) in - let (x1, x2) = TypEq.apply P.eq x in - Printf.sprintf "(%s,%s)" (to_string P.t1 x1) (to_string P.t2 x2) -\end{verbatim} +\begin{caml_example*}{verbatim} +open Typ +let rec to_string: 'a. 'a Typ.typ -> 'a -> string = + fun (type s) t x -> + match t with + | Int eq -> Int.to_string (TypEq.apply eq x) + | String eq -> Printf.sprintf "%S" (TypEq.apply eq x) + | Pair p -> + let module P = (val p : PAIR with type t = s) in + let (x1, x2) = TypEq.apply P.eq x in + Printf.sprintf "(%s,%s)" (to_string P.t1 x1) (to_string P.t2 x2) +\end{caml_example*} Note that this function uses an explicit polymorphic annotation to obtain polymorphic recursion. @@ -784,31 +710,31 @@ A typical use, in conjunction with the signature-level @'include'@ construct, is to extend the signature of an existing structure. In that case, one wants to keep the types equal to types in the original module. This can done using the following idiom. -\begin{verbatim} - module type MYHASH = sig - include module type of struct include Hashtbl end - val replace: ('a, 'b) t -> 'a -> 'b -> unit - end -\end{verbatim} +\begin{caml_example*}{verbatim} +module type MYHASH = sig + include module type of struct include Hashtbl end + val replace: ('a, 'b) t -> 'a -> 'b -> unit +end +\end{caml_example*} The signature "MYHASH" then contains all the fields of the signature of the module "Hashtbl" (with strengthened type definitions), plus the new field "replace". An implementation of this signature can be obtained easily by using the @'include'@ construct again, but this time at the structure level: -\begin{verbatim} - module MyHash : MYHASH = struct - include Hashtbl - let replace t k v = remove t k; add t k v - end -\end{verbatim} +\begin{caml_example*}{verbatim} +module MyHash : MYHASH = struct + include Hashtbl + let replace t k v = remove t k; add t k v +end +\end{caml_example*} Another application where the absence of strengthening comes handy, is to provide an alternative implementation for an existing module. -\begin{verbatim} - module MySet : module type of Set = struct - ... - end -\end{verbatim} +\begin{caml_example*}{verbatim} +module MySet : module type of Set = struct + include Set[@@ellipsis] +end +\end{caml_example*} This idiom guarantees that "Myset" is compatible with Set, but allows it to represent sets internally in a different way. @@ -818,6 +744,9 @@ it to represent sets internally in a different way. \ikwd{type\@\texttt{type}} \label{s:signature-substitution} +\subsection{Destructive substitutions} +\label{ss:destructive-substitution} + (Introduced in OCaml 3.12, generalized in 4.06) \begin{syntax} @@ -839,18 +768,18 @@ same type parameters. A natural application of destructive substitution is merging two signatures sharing a type name. \begin{caml_example*}{verbatim} - module type Printable = sig - type t - val print : Format.formatter -> t -> unit - end - module type Comparable = sig - type t - val compare : t -> t -> int - end - module type PrintableComparable = sig - include Printable - include Comparable with type t := t - end +module type Printable = sig + type t + val print : Format.formatter -> t -> unit +end +module type Comparable = sig + type t + val compare : t -> t -> int +end +module type PrintableComparable = sig + include Printable + include Comparable with type t := t +end \end{caml_example*} One can also use this to completely remove a field: @@ -872,6 +801,51 @@ module type ComparableInt = Comparable with type t = int ;; module type CompareInt = ComparableInt with type t := int \end{caml_example} +\subsection{Local substitution declarations} +\label{ss:local-substitution} + +(Introduced in OCaml 4.08) + +\begin{syntax} +specification: + ... + | 'type' type-subst { 'and' type-subst } + | 'module' module-name ':=' extended-module-path +; + +type-subst: + [type-params] typeconstr-name ':=' typexpr { type-constraint } +\end{syntax} + + +Local substitutions behave like destructive substitutions (@'with' ... ':=' ...@) +but instead of being applied to a whole signature after the fact, they are +introduced during the specification of the signature, and will apply to all the +items that follow. + +This provides a convenient way to introduce local names for types and modules +when defining a signature: + +\begin{caml_example}{verbatim} +module type S = sig + type t + module Sub : sig + type outer := t + type t + val to_outer : t -> outer + end +end +\end{caml_example} + +Note that, unlike type declarations, type substitution declarations are not +recursive, so substitutions like the following are rejected: + +\begin{caml_example}{toplevel} +module type S = sig + type 'a poly_list := [ `Cons of 'a * 'a poly_list | `Nil ] +end [@@expect error];; +\end{caml_example} + \section{Type-level module aliases} \ikwd{module\@\texttt{module}} \label{s:module-alias} @@ -940,7 +914,7 @@ place of the @'-pack'@ mechanism. Suppose that you have a library @'Mylib'@ composed of modules @'A'@ and @'B'@. Using @'-pack'@, one would issue the command line \begin{verbatim} - ocamlc -pack a.cmo b.cmo -o mylib.cmo +ocamlc -pack a.cmo b.cmo -o mylib.cmo \end{verbatim} and as a result obtain a @'Mylib'@ compilation unit, containing physically @'A'@ and @'B'@ as submodules, and with no dependencies on @@ -952,21 +926,21 @@ Here is a concrete example of a possible alternative approach: \item Create a packing interface @'Mylib.ml'@, containing the following lines. \begin{verbatim} - module A = Mylib__A - module B = Mylib__B +module A = Mylib__A +module B = Mylib__B \end{verbatim} \item Compile @'Mylib.ml'@ using @'-no-alias-deps'@, and the other files using @'-no-alias-deps'@ and @'-open' 'Mylib'@ (the last one is equivalent to adding the line @'open!' 'Mylib'@ at the top of each file). \begin{verbatim} - ocamlc -c -no-alias-deps Mylib.ml - ocamlc -c -no-alias-deps -open Mylib Mylib__*.mli Mylib__*.ml +ocamlc -c -no-alias-deps Mylib.ml +ocamlc -c -no-alias-deps -open Mylib Mylib__*.mli Mylib__*.ml \end{verbatim} \item Finally, create a library containing all the compilation units, and export all the compiled interfaces. \begin{verbatim} - ocamlc -a Mylib*.cmo -o Mylib.cma +ocamlc -a Mylib*.cmo -o Mylib.cma \end{verbatim} \end{enumerate} This approach lets you access @'A'@ and @'B'@ directly inside the @@ -1068,37 +1042,32 @@ scope of this branch. \paragraph{Recursive functions} Here is a concrete example: -\begin{verbatim} - type _ term = - | Int : int -> int term - | Add : (int -> int -> int) term - | App : ('b -> 'a) term * 'b term -> 'a term - - let rec eval : type a. a term -> a = function - | Int n -> n (* a = int *) - | Add -> (fun x y -> x+y) (* a = int -> int -> int *) - | App(f,x) -> (eval f) (eval x) - (* eval called at types (b->a) and b for fresh b *) - - let two = eval (App (App (Add, Int 1), Int 1)) - val two : int = 2 -\end{verbatim} +\begin{caml_example*}{verbatim} +type _ term = + | Int : int -> int term + | Add : (int -> int -> int) term + | App : ('b -> 'a) term * 'b term -> 'a term + +let rec eval : type a. a term -> a = function + | Int n -> n (* a = int *) + | Add -> (fun x y -> x+y) (* a = int -> int -> int *) + | App(f,x) -> (eval f) (eval x) + (* eval called at types (b->a) and b for fresh b *) +\end{caml_example*} +\begin{caml_example}{verbatim} +let two = eval (App (App (Add, Int 1), Int 1)) +\end{caml_example} It is important to remark that the function "eval" is using the polymorphic syntax for locally abstract types. When defining a recursive function that manipulates a GADT, explicit polymorphic recursion should generally be used. For instance, the following definition fails with a type error: -\begin{verbatim} - let rec eval (type a) : a term -> a = function - | Int n -> n - | Add -> (fun x y -> x+y) - | App(f,x) -> (eval f) (eval x) -(* ^ - Error: This expression has type ($App_'b -> a) term but an expression was - expected of type 'a - The type constructor $App_'b would escape its scope -*) -\end{verbatim} +\begin{caml_example}{verbatim}[error] +let rec eval (type a) : a term -> a = function + | Int n -> n + | Add -> (fun x y -> x+y) + | App(f,x) -> (eval f) (eval x) +\end{caml_example} In absence of an explicit polymorphic annotation, a monomorphic type is inferred for the recursive function. If a recursive call occurs inside the function definition at a type that involves an existential @@ -1139,16 +1108,15 @@ Moreover, the notion of ambiguity used is stronger: a type is only seen as ambiguous if it was mixed with incompatible types (equated by constraints), without type annotations between them. For instance, the following program types correctly. -\begin{verbatim} - let rec sum : type a. a term -> _ = fun x -> - let y = - match x with - | Int n -> n - | Add -> 0 - | App(f,x) -> sum f + sum x - in y + 1 - val sum : 'a term -> int = -\end{verbatim} +\begin{caml_example}{verbatim} +let rec sum : type a. a term -> _ = fun x -> + let y = + match x with + | Int n -> n + | Add -> 0 + | App(f,x) -> sum f + sum x + in y + 1 +\end{caml_example} Here the return type "int" is never mixed with "a", so it is seen as non-ambiguous, and can be inferred. When using such partial type annotations we strongly suggest @@ -1159,11 +1127,11 @@ The exhaustiveness check is aware of GADT constraints, and can automatically infer that some cases cannot happen. For instance, the following pattern matching is correctly seen as exhaustive (the "Add" case cannot happen). -\begin{verbatim} - let get_int : int term -> int = function - | Int n -> n - | App(_,_) -> 0 -\end{verbatim} +\begin{caml_example*}{verbatim} +let get_int : int term -> int = function + | Int n -> n + | App(_,_) -> 0 +\end{caml_example*} \paragraph{Refutation cases} (Introduced in OCaml 4.03) @@ -1188,15 +1156,15 @@ constructors, to avoid non-termination). We also split tuples and variant types with only one case, since they may contain GADTs inside. For instance, the following code is deemed exhaustive: -\begin{verbatim} - type _ t = - | Int : int t - | Bool : bool t +\begin{caml_example*}{verbatim} +type _ t = + | Int : int t + | Bool : bool t - let deep : (char t * int) option -> char = function - | None -> 'c' - | _ -> . -\end{verbatim} +let deep : (char t * int) option -> char = function + | None -> 'c' + | _ -> . +\end{caml_example*} Namely, the inferred remaining case is "Some _", which is split into "Some (Int, _)" and "Some (Bool, _)", which are both untypable because @@ -1220,28 +1188,28 @@ polytypic behavior. Here is an example of a polymorphic function that takes the runtime representation of some type "t" and a value of the same type, then pretty-prints the value as a string: -\begin{verbatim} - type _ typ = - | Int : int typ - | String : string typ - | Pair : 'a typ * 'b typ -> ('a * 'b) typ - - let rec to_string: type t. t typ -> t -> string = - fun t x -> - match t with - | Int -> string_of_int x - | String -> Printf.sprintf "%S" x - | Pair(t1,t2) -> - let (x1, x2) = x in - Printf.sprintf "(%s,%s)" (to_string t1 x1) (to_string t2 x2) -\end{verbatim} +\begin{caml_example*}{verbatim} +type _ typ = + | Int : int typ + | String : string typ + | Pair : 'a typ * 'b typ -> ('a * 'b) typ + +let rec to_string: type t. t typ -> t -> string = + fun t x -> + match t with + | Int -> Int.to_string x + | String -> Printf.sprintf "%S" x + | Pair(t1,t2) -> + let (x1, x2) = x in + Printf.sprintf "(%s,%s)" (to_string t1 x1) (to_string t2 x2) +\end{caml_example*} Another frequent application of GADTs is equality witnesses. -\begin{verbatim} - type (_,_) eq = Eq : ('a,'a) eq +\begin{caml_example*}{verbatim} +type (_,_) eq = Eq : ('a,'a) eq - let cast : type a b. (a,b) eq -> a -> b = fun Eq x -> x -\end{verbatim} +let cast : type a b. (a,b) eq -> a -> b = fun Eq x -> x +\end{caml_example*} Here type "eq" has only one constructor, and by matching on it one adds a local constraint allowing the conversion between "a" and "b". By building such equality witnesses, one can make equal types which @@ -1249,27 +1217,27 @@ are syntactically different. Here is an example using both singleton types and equality witnesses to implement dynamic types. -\begin{verbatim} - let rec eq_type : type a b. a typ -> b typ -> (a,b) eq option = - fun a b -> - match a, b with - | Int, Int -> Some Eq - | String, String -> Some Eq - | Pair(a1,a2), Pair(b1,b2) -> - begin match eq_type a1 b1, eq_type a2 b2 with - | Some Eq, Some Eq -> Some Eq - | _ -> None - end - | _ -> None - - type dyn = Dyn : 'a typ * 'a -> dyn - - let get_dyn : type a. a typ -> dyn -> a option = - fun a (Dyn(b,x)) -> - match eq_type a b with - | None -> None - | Some Eq -> Some x -\end{verbatim} +\begin{caml_example*}{verbatim} +let rec eq_type : type a b. a typ -> b typ -> (a,b) eq option = + fun a b -> + match a, b with + | Int, Int -> Some Eq + | String, String -> Some Eq + | Pair(a1,a2), Pair(b1,b2) -> + begin match eq_type a1 b1, eq_type a2 b2 with + | Some Eq, Some Eq -> Some Eq + | _ -> None + end + | _ -> None + +type dyn = Dyn : 'a typ * 'a -> dyn + +let get_dyn : type a. a typ -> dyn -> a option = + fun a (Dyn(b,x)) -> + match eq_type a b with + | None -> None + | Some Eq -> Some x +\end{caml_example*} \paragraph{Existential type names in error messages}% \label{p:existential-names} @@ -1317,15 +1285,15 @@ and may be improved in future versions. GADT pattern-matching may also add type equations to non-local abstract types. The behaviour is the same as with local abstract types. Reusing the above "eq" type, one can write: -\begin{verbatim} - module M : sig type t val x : t val e : (t,int) eq end = struct - type t = int - let x = 33 - let e = Eq - end +\begin{caml_example*}{verbatim} +module M : sig type t val x : t val e : (t,int) eq end = struct + type t = int + let x = 33 + let e = Eq +end - let x : int = let Eq = M.e in M.x -\end{verbatim} +let x : int = let Eq = M.e in M.x +\end{caml_example*} Of course, not all abstract types can be refined, as this would contradict the exhaustiveness check. Namely, builtin types (those @@ -1345,8 +1313,7 @@ expr: \end{syntax} This extension provides syntactic sugar for getting and setting -elements in the arrays provided by the -"Bigarray"[\moduleref{Bigarray}] library. +elements in the arrays provided by the \stdmoduleref{Bigarray} module. The short expressions are translated into calls to functions of the "Bigarray" module as described in the following table. @@ -1582,29 +1549,26 @@ Some attributes are understood by the type-checker: (such as an expression, or a type expression) in which case its scope is limited to that item. Note that it is not well-defined which scope is used for a specific - warning. This is implementation dependant and can change between versions. + warning. This is implementation dependent and can change between versions. Some warnings are even completely outside the control of ``ocaml.warning'' (for instance, warnings 1, 2, 14, 29 and 50). \item ``ocaml.warnerror'' or ``warnerror'', with a string literal payload. Same as ``ocaml.warning'', for the "-warn-error" command-line option. + +\item + ``ocaml.alert'' or ``alert'': see section~\ref{s:alerts}. + \item - ``ocaml.deprecated'' or ``deprecated''. - Can be applied to most kind of items in signatures or - structures. When the element is later referenced, a warning (3) is - triggered. If the payload of the attribute is a string literal, - the warning message includes this text. It is also possible - to use this ``ocaml.deprecated'' as a floating attribute - on top of an ``.mli'' file (i.e. before any other non-attribute - item) or on top of an ``.ml'' file without a corresponding - interface; this marks the unit itself as being deprecated. + ``ocaml.deprecated'' or ``deprecated'': alias for the + ``deprecated'' alert, see section~\ref{s:alerts}. \item ``ocaml.deprecated_mutable'' or ``deprecated_mutable''. Can be applied to a mutable record label. If the label is later - used to modify the field (with ``expr.l <- expr''), a warning (3) + used to modify the field (with ``expr.l <- expr''), the ``deprecated'' alert will be triggered. If the payload of the attribute is a string literal, - the warning message includes this text. + the alert message includes this text. \item ``ocaml.ppwarning'' or ``ppwarning'', in any context, with a string literal payload. The text is reported as warning (22) @@ -1662,49 +1626,86 @@ Some attributes are understood by the type-checker: the opposite of "ocaml.unboxed": keep the unoptimized representation of the type. When there is no annotation, the default is currently "boxed" but it may change in the future. + \item + "ocaml.local" or "local" take either "never", "always", "maybe" or + nothing as payload on a function definition. If no payload is + provided, the default is "always". The attribute controls an + optimization which consists in compiling a function into a static + continuation. Contrary to inlining, this optimization does not + duplicate the function's body. This is possible when all + references to the function are full applications, all sharing the + same continuation (for instance, the returned value of several + branches of a pattern matching). "never" disables the optimization, + "always" asserts that the optimization applies (otherwise a warning + 55 is emitted) and "maybe" lets the optimization apply when + possible (this is the default behavior when the attribute is not + specified). The optimization is implicitly disabled when using the + bytecode compiler in debug mode (-g), and for functions marked with + an "ocaml.inline always" or "ocaml.unrolled" attribute which + supersede "ocaml.local". \end{itemize} -\begin{verbatim} +\begin{caml_example*}{verbatim} module X = struct [@@@warning "+9"] (* locally enable warning 9 in this structure *) - ... + [@@@ellipsis] end - [@@deprecated "Please use module 'Y' instead."] +[@@deprecated "Please use module 'Y' instead."] -let x = begin[@warning "+9"] ... end in .... +let x = begin[@warning "+9"] [()[@ellipsis]] end type t = A | B [@@deprecated "Please use type 's' instead."] +\end{caml_example*} -let f x = - assert (x >= 0) [@ppwarning "TODO: remove this later"]; +\begin{caml_example*}{verbatim}[warning=22] +let fires_warning_22 x = + assert (x >= 0) [@ppwarning "TODO: remove this later"] +\end{caml_example*} -let rec no_op = function +\begin{caml_example*}{verbatim}[warning=51] +let rec is_a_tail_call = function | [] -> () - | _ :: q -> (no_op[@tailcall]) q;; + | _ :: q -> (is_a_tail_call[@tailcall]) q +let rec not_a_tail_call = function + | [] -> [] + | x :: q -> x :: (not_a_tail_call[@tailcall]) q +\end{caml_example*} + +\begin{caml_example*}{verbatim} let f x = x [@@inline] let () = (f[@inlined]) () +\end{caml_example} +\begin{caml_example*}{verbatim} type fragile = | Int of int [@warn_on_literal_pattern] | String of string [@warn_on_literal_pattern] +\end{caml_example*} + +\begin{caml_example}{verbatim}[warning=52] +let fragile_match_1 = function +| Int 0 -> () +| _ -> () +\end{caml_example} -let f = function -| Int 0 | String "constant" -> () (* trigger warning 52 *) +\begin{caml_example}{verbatim}[warning=52] +let fragile_match_2 = function +| String "constant" -> () | _ -> () +\end{caml_example} +\begin{caml_example*}{verbatim} module Immediate: sig type t [@@immediate] val x: t ref end = struct type t = A | B - let x = ref 0 + let x = ref A end - .... - -\end{verbatim} +\end{caml_example*} \section{Extension nodes}\label{s:extension-nodes} @@ -1792,6 +1793,20 @@ the attributes are considered to apply to the payload: fun%foo[@bar] x -> x + 1 === [%foo (fun x -> x + 1)[@bar ] ]; \end{verbatim} +Quoted strings "{|...|}" are particularly interesting for payloads +that embed foreign syntax fragments. Those fragments can be interpreted +by a preprocessor and turned into OCaml code without requiring escaping +quotes. For instance, you can use "[%sql {|...|}]" to +represent arbitrary SQL statements -- assuming you have a ppx-rewriter +that recognizes the "%sql" extension. + +Note that the word-delimited form, for example "{sql|...|sql}", should +not be used for signaling that an extension is in use. +Indeed, the user cannot see from the code whether this string literal has +different semantics than they expect. Moreover, giving semantics to a +specific delimiter limits the freedom to change the delimiter to avoid +escaping issues. + \subsection{Built-in extension nodes} (Introduced in OCaml 4.03) @@ -1815,81 +1830,6 @@ let y = [%extension_constructor Y] x <> y;; \end{caml_example} -\section{Quoted strings}\label{s:quoted-strings} - -(Introduced in OCaml 4.02) - -Quoted strings "{foo|...|foo}" provide a different lexical syntax to -write string literals in OCaml code. They are useful to represent -strings of arbitrary content without escaping -- as long as the -delimiter you chose (here "|foo}") does not occur in the string -itself. - -\begin{syntax} -string-literal: ... - | '{' quoted-string-id '|' ........ '|' quoted-string-id '}' -; -quoted-string-id: - { 'a'...'z' || '_' } -; -\end{syntax} - -The opening delimiter has the form "{id|" where "id" is a (possibly -empty) sequence of lowercase letters and underscores. The -corresponding closing delimiter is "|id}" (with the same -identifier). Unlike regular OCaml string literals, quoted -strings do not interpret any character in a special way. - -Example: - -\begin{verbatim} -String.length {|\"|} (* returns 2 *) -String.length {foo|\"|foo} (* returns 2 *) -\end{verbatim} - -Quoted strings are interesting in particular in conjunction to -extension nodes "[%foo ...]" (see \ref{s:extension-nodes}) to embed -foreign syntax fragments to be interpreted by a preprocessor and -turned into OCaml code: you can use "[%sql {|...|}]" for example to -represent arbitrary SQL statements -- assuming you have a ppx-rewriter -that recognizes the "%sql" extension -- without requiring escaping -quotes. - -Note that the non-extension form, for example "{sql|...|sql}", should -not be used for this purpose, as the user cannot see in the code that -this string literal has a different semantics than they expect, and -giving a semantics to a specific delimiter limits the freedom to -change the delimiter to avoid escaping issues. - -\section{Exception cases in pattern matching}\label{s:exception-match} - -(Introduced in OCaml 4.02) - -A new form of exception patterns is allowed, only as a toplevel -pattern under a "match"..."with" pattern-matching (other occurrences -are rejected by the type-checker). - -\begin{syntax} -pattern: ... - | 'exception' pattern -; -\end{syntax} - -Cases with such a toplevel pattern are called ``exception cases'', -as opposed to regular ``value cases''. Exception cases are applied -when the evaluation of the matched expression raises an exception. -The exception value is then matched against all the exception cases -and re-raised if none of them accept the exception (as for a -"try"..."with" block). Since the bodies of all exception and value -cases is outside the scope of the exception handler, they are all -considered to be in tail-position: if the "match"..."with" block -itself is in tail position in the current function, any function call -in tail position in one of the case bodies results in an actual tail -call. - -It is an error if all cases are exception cases in a given pattern -matching. - \section{Extensible variant types}\label{s:extensible-variants} (Introduced in OCaml 4.02) @@ -1920,52 +1860,69 @@ constr-def: Extensible variant types are variant types which can be extended with new variant constructors. Extensible variant types are defined using "..". New variant constructors are added using "+=". -\begin{verbatim} - type attr = .. +\begin{caml_example*}{verbatim} +module Expr = struct + type attr = .. - type attr += Str of string + type attr += Str of string - type attr += - | Int of int - | Float of float -\end{verbatim} + type attr += + | Int of int + | Float of float +end +\end{caml_example*} Pattern matching on an extensible variant type requires a default case to handle unknown variant constructors: -\begin{verbatim} - let to_string = function - | Str s -> s - | Int i -> string_of_int i - | Float f -> string_of_float f - | _ -> "?" -\end{verbatim} +\begin{caml_example*}{verbatim} +let to_string = function + | Expr.Str s -> s + | Expr.Int i -> Int.to_string i + | Expr.Float f -> string_of_float f + | _ -> "?" +\end{caml_example*} A preexisting example of an extensible variant type is the built-in "exn" type used for exceptions. Indeed, exception constructors can be declared using the type extension syntax: -\begin{verbatim} - type exn += Exc of int -\end{verbatim} +\begin{caml_example*}{verbatim} +type exn += Exc of int +\end{caml_example*} Extensible variant constructors can be rebound to a different name. This allows exporting variants from another module. -\begin{verbatim} - type Expr.attr += Str = Expr.Str -\end{verbatim} +\begin{caml_example}{toplevel}[error] +let not_in_scope = Str "Foo";; +\end{caml_example} +\begin{caml_example*}{verbatim} +type Expr.attr += Str = Expr.Str +\end{caml_example*} +\begin{caml_example}{toplevel} +let now_works = Str "foo";; +\end{caml_example} Extensible variant constructors can be declared "private". As with regular variants, this prevents them from being constructed directly by constructor application while still allowing them to be de-structured in pattern-matching. -\begin{verbatim} - module Bool : sig - type attr += private Bool of int - val bool : bool -> attr - end = struct - type attr += Bool of int - let bool p = if p then Bool 1 else Bool 0 - end -\end{verbatim} +\begin{caml_example*}{verbatim} +module B : sig + type Expr.attr += private Bool of int + val bool : bool -> Expr.attr +end = struct + type Expr.attr += Bool of int + let bool p = if p then Bool 1 else Bool 0 +end +\end{caml_example*} + +\begin{caml_example}{toplevel} +let inspection_works = function + | B.Bool p -> (p = 1) + | _ -> true;; +\end{caml_example} +\begin{caml_example}{toplevel}[error] +let construction_is_forbidden = B.Bool 1;; +\end{caml_example} \subsection{Private extensible variant types} @@ -1981,19 +1938,19 @@ type-representation: Extensible variant types can be declared "private". This prevents new constructors from being declared directly, but allows extension constructors to be referred to in interfaces. -\begin{verbatim} - module Msg : sig - type t = private .. - module MkConstr (X : sig type t end) : sig - type t += C of X.t - end - end = struct - type t = .. - module MkConstr (X : sig type t end) = struct - type t += C of X.t - end - end -\end{verbatim} +\begin{caml_example*}{verbatim} +module Msg : sig + type t = private .. + module MkConstr (X : sig type t end) : sig + type t += C of X.t + end +end = struct + type t = .. + module MkConstr (X : sig type t end) = struct + type t += C of X.t + end +end +\end{caml_example*} \section{Generative functors}\label{s:generative-functors} @@ -2094,7 +2051,7 @@ range @["g".."z"||"G".."Z"]@ are extension-only literals. ; \end{syntax} -The arguments of a sum-type constructors can now be defined using the +The arguments of sum-type constructors can now be defined using the same syntax as records. Mutable and polymorphic fields are allowed. GADT syntax is supported. Attributes can be specified on individual fields. @@ -2106,52 +2063,30 @@ the inline record as a pseudo-value, but the record cannot escape the scope of the binding and can only be used with the dot-notation to extract or modify fields or to build new constructor values. -\begin{verbatim} +\begin{caml_example*}{verbatim} type t = | Point of {width: int; mutable x: float; mutable y: float} - | ... + | Other let v = Point {width = 10; x = 0.; y = 0.} let scale l = function | Point p -> Point {p with x = l *. p.x; y = l *. p.y} - | .... + | Other -> Other let print = function | Point {x; y; _} -> Printf.printf "%f/%f" x y - | .... + | Other -> () let reset = function | Point p -> p.x <- 0.; p.y <- 0. - | ... + | Other -> () +\end{caml_example*} +\begin{caml_example}{verbatim}[error] let invalid = function - | Point p -> p (* INVALID *) - | ... -\end{verbatim} - - -\section{Local exceptions} -\ikwd{let\@\texttt{let}} -\ikwd{exception\@\texttt{exception}} \label{s:local-exceptions} - -(Introduced in OCaml 4.04) - -It is possible to define local exceptions in expressions: - -\begin{syntax} -expr: - ... - | "let" "exception" constr-decl "in" expr -\end{syntax} - - -The syntactic scope of the exception constructor is the inner -expression, but nothing prevents exception values created with this -constructor from escaping this scope. Two executions of the definition -above result in two incompatible exception constructors (as for any -exception definition). - + | Point p -> p +\end{caml_example} \section{Documentation comments} (Introduced in OCaml 4.03) @@ -2177,23 +2112,23 @@ Comments surrounded by blank lines that appear within structures, signatures, classes or class types are converted into @floating-attribute@s. For example: -\begin{verbatim} +\begin{caml_example*}{verbatim} type t = T (** Now some definitions for [t] *) let mkT = T -\end{verbatim} +\end{caml_example*} will be converted to: -\begin{verbatim} +\begin{caml_example*}{verbatim} type t = T [@@@ocaml.text " Now some definitions for [t] "] let mkT = T -\end{verbatim} +\end{caml_example*} \subsection{Item comments} @@ -2203,44 +2138,44 @@ are converted into @item-attribute@s. Immediately before or immediately after means that there must be no blank lines, ";;", or other documentation comments between them. For example: -\begin{verbatim} +\begin{caml_example*}{verbatim} type t = T (** A description of [t] *) -\end{verbatim} +\end{caml_example*} or -\begin{verbatim} +\begin{caml_example*}{verbatim} (** A description of [t] *) type t = T -\end{verbatim} +\end{caml_example*} will be converted to: -\begin{verbatim} +\begin{caml_example*}{verbatim} type t = T [@@ocaml.doc " A description of [t] "] -\end{verbatim} +\end{caml_example*} Note that, if a comment appears immediately next to multiple items, as in: -\begin{verbatim} +\begin{caml_example*}{verbatim} type t = T (** An ambiguous comment *) type s = S -\end{verbatim} +\end{caml_example*} then it will be attached to both items: -\begin{verbatim} +\begin{caml_example*}{verbatim} type t = T [@@ocaml.doc " An ambiguous comment "] type s = S [@@ocaml.doc " An ambiguous comment "] -\end{verbatim} +\end{caml_example*} and the compiler will emit warning 50. @@ -2252,7 +2187,7 @@ constructor are are converted into @attribute@s. Immediately after means that there must be no blank lines or other documentation comments between them. For example: -\begin{verbatim} +\begin{caml_example*}{verbatim} type t1 = lbl:int (** Labelled argument *) -> unit type t2 = { @@ -2269,11 +2204,11 @@ type t4 = < meth: int * int; (** Object method *) > type t5 = [ `PCstr (** Polymorphic variant constructor *) ] -\end{verbatim} +\end{caml_example*} will be converted to: -\begin{verbatim} +\begin{caml_example*}{verbatim} type t1 = lbl:(int [@ocaml.doc " Labelled argument "]) -> unit type t2 = { @@ -2290,51 +2225,51 @@ type t4 = < meth : int * int [@ocaml.doc " Object method "] > type t5 = [ `PCstr [@ocaml.doc " Polymorphic variant constructor "] ] -\end{verbatim} +\end{caml_example*} Note that label comments take precedence over item comments, so: -\begin{verbatim} +\begin{caml_example*}{verbatim} type t = T of string (** Attaches to T not t *) -\end{verbatim} +\end{caml_example*} will be converted to: -\begin{verbatim} +\begin{caml_example*}{verbatim} type t = T of string [@ocaml.doc " Attaches to T not t "] -\end{verbatim} +\end{caml_example*} whilst: -\begin{verbatim} +\begin{caml_example*}{verbatim} type t = T of string (** Attaches to T not t *) (** Attaches to t *) -\end{verbatim} +\end{caml_example*} will be converted to: -\begin{verbatim} +\begin{caml_example*}{verbatim} type t = T of string [@ocaml.doc " Attaches to T not t "] [@@ocaml.doc " Attaches to t "] -\end{verbatim} +\end{caml_example*} In the absence of meaningful comment on the last constructor of a type, an empty comment~"(**)" can be used instead: -\begin{verbatim} +\begin{caml_example*}{verbatim} type t = T of string (**) (** Attaches to t *) -\end{verbatim} +\end{caml_example*} will be converted directly to -\begin{verbatim} +\begin{caml_example*}{verbatim} type t = T of string [@@ocaml.doc " Attaches to t "] -\end{verbatim} +\end{caml_example*} \section{Extended indexing operators \label{s:index-operators} } (Introduced in 4.06) @@ -2391,3 +2326,348 @@ Empty variant type can be eliminated by refutation case of pattern matching. type t = | let f (x: t) = match x with _ -> . \end{caml_example*} + +\section{Alerts \label{s:alerts} } +(Introduced in 4.08) + +Since OCaml 4.08, it is possible to mark components (such as value or +type declarations) in signatures with ``alerts'' that will be reported +when those components are referenced. This generalizes the notion of +``deprecated'' components which were previously reported as warning 3. +Those alerts can be used for instance to report usage of unsafe +features, or of features which are only available on some platforms, +etc. + +Alert categories are identified by a symbolic identifier (a lowercase +identifier, following the usual lexical rules) and an optional +message. The identifier is used to control which alerts are enabled, +and which ones are turned into fatal errors. The message is reported +to the user when the alert is triggered (i.e. when the marked +component is referenced). + +The "ocaml.alert" or "alert" attribute serves two purposes: (i) to +mark component with an alert to be triggered when the component is +referenced, and (ii) to control which alert names are enabled. In the +first form, the attribute takes an identifier possibly +followed by a message. Here is an example of a value declaration marked +with an alert: + +\begin{verbatim} +module U: sig + val fork: unit -> bool + [@@alert unix "This function is only available under Unix."] +end +\end{verbatim} + +Here "unix" is the identifier for the alert. If this alert category +is enabled, any reference to "U.fork" will produce a message at +compile time, which can be turned or not into a fatal error. + +And here is another example as a floating attribute on top +of an ``.mli'' file (i.e. before any other non-attribute item) +or on top of an ``.ml'' file without a corresponding interface file, +so that any reference to that unit will trigger the alert: + +\begin{verbatim} +[@@@alert unsafe "This module is unsafe!"] +\end{verbatim} + + +Controlling which alerts are enabled and whether they are turned into +fatal errors is done either through the compiler's command-line option +"-alert " or locally in the code through the "alert" or +"ocaml.alert" attribute taking a single string payload "". In +both cases, the syntax for "" is a concatenation of items of the +form: + +\begin{itemize} +\item "+id" enables alert "id". +\item "-id" disables alert "id". +\item "++id" turns alert "id" into a fatal error. +\item "--id" turns alert "id" into non-fatal mode. +\item "\@id" equivalent to "++id+id" (enables "id" and turns it into a fatal-error) +\end{itemize} + +As a special case, if "id" is "all", it stands for all alerts. + +Here are some examples: + +\begin{verbatim} + +(* Disable all alerts, reenables just unix (as a soft alert) and window + (as a fatal-error), for the rest of the current structure *) + +[@@@alert "-all--all+unix@window"] + ... + +let x = + (* Locally disable the window alert *) + begin[@alert "-window"] + ... + end +\end{verbatim} + +Before OCaml 4.08, there was support for a single kind of deprecation +alert. It is now known as the "deprecated" alert, but legacy +attributes to trigger it and the legacy ways to control it as warning +3 are still supported. For instance, passing "-w +3" on the +command-line is equivant to "-alert +deprecated", and: + +\begin{verbatim} +val x: int + [@@@ocaml.deprecated "Please do something else"] +\end{verbatim} + +is equivalent to: + +\begin{verbatim} +val x: int + [@@@ocaml.alert deprecated "Please do something else"] +\end{verbatim} + +\section{Generalized open statements\label{s:generalized-open}} + +(Introduced in 4.08) + +\begin{syntax} +definition: + ... + | 'open' module-expr + | 'open!' module-expr +; +specification: + ... + | 'open' extended-module-path + | 'open!' extended-module-path +; +expr: + ... + | 'let' 'open' module-expr 'in' expr + | 'let' 'open!' module-expr 'in' expr +; +\end{syntax} + + +This extension makes it possible to open any module expression in +module structures and expressions. A similar mechanism is also available +inside module types, but only for extended module paths (e.g. "F(X).G(Y)"). + +For instance, a module can be constrained when opened with + +\begin{caml_example*}{verbatim}[error] +module M = struct let x = 0 let hidden = 1 end +open (M:sig val x: int end) +let y = hidden +\end{caml_example*} + + +Another possibility is to immediately open the result of a functor application + +\begin{caml_example}{verbatim} + let sort (type x) (x:x list) = + let open Set.Make(struct type t = x let compare=compare end) in + elements (of_list x) +\end{caml_example} + +Going further, this construction can introduce local components inside a +structure, + +\begin{caml_example}{verbatim} +module M = struct + let x = 0 + open! struct + let x = 0 + let y = 1 + end + let w = x + y +end +\end{caml_example} + +One important restriction is that types introduced by @'open' 'struct' ... +'end'@ cannot appear in the signature of the enclosing structure, unless they +are defined equal to some non-local type. +So: + +\begin{caml_example}{verbatim} +module M = struct + open struct type 'a t = 'a option = None | Some of 'a end + let x : int t = Some 1 +end +\end{caml_example} +is OK, but: + +\begin{caml_example}{verbatim}[error] +module M = struct + open struct type t = A end + let x = A +end +\end{caml_example} +is not because "x" cannot be given any type other than "t", which only exists +locally. Although the above would be OK if "x" too was local: + +\begin{caml_example}{verbatim} +module M: sig end = struct + open struct + type t = A + end + [@@@ellipsis] + open struct let x = A end + [@@@ellipsis] +end +\end{caml_example} + +Inside signatures, extended opens are limited to extended module paths, +\begin{caml_example}{verbatim} +module type S = sig + module F: sig end -> sig type t end + module X: sig end + open F(X) + val f: t +end +\end{caml_example} + +and not + +\begin{verbatim} + open struct type t = int end +\end{verbatim} + +In those situations, local substitutions(see \ref{ss:local-substitution}) +can be used instead. + +Beware that this extension is not available inside class definitions: + +\begin{verbatim} +class c = + let open Set.Make(Int) in + ... +\end{verbatim} + +\section{Binding operators\label{s:binding-operators} } +(Introduced in 4.08.0) + +\begin{syntax} +let-operator: + | 'let' ('$'||'&'||'*'||'+'||'-'||'/'||'<'||'='||'>'||'@'||'^'||'|') { operator-char } +; +and-operator: + | 'and' ('$'||'&'||'*'||'+'||'-'||'/'||'<'||'='||'>'||'@'||'^'||'|') { operator-char } +; +operator-name : + ... + | let-operator + | and-operator +; +expr: + ... + | let-operator let-binding { and-operator let-binding } in expr +; +\end{syntax} + +Users can define {\em let operators}: + +\begin{caml_example}{verbatim} +let ( let* ) o f = + match o with + | None -> None + | Some x -> f x + +let return x = Some x +\end{caml_example} + +and then apply them using this convenient syntax: + +\begin{caml_example}{verbatim} +let find_and_sum tbl k1 k2 = + let* x1 = Hashtbl.find_opt tbl k1 in + let* x2 = Hashtbl.find_opt tbl k2 in + return (x1 + x2) +\end{caml_example} + +which is equivalent to this expanded form: + +\begin{caml_example}{verbatim} +let find_and_sum tbl k1 k2 = + ( let* ) (Hashtbl.find_opt tbl k1) + (fun x1 -> + ( let* ) (Hashtbl.find_opt tbl k2) + (fun x2 -> return (x1 + x2))) +\end{caml_example} + +Users can also define {\em and operators}: + +\begin{caml_example}{verbatim} +module ZipSeq = struct + + type 'a t = 'a Seq.t + + open Seq + + let rec return x = + fun () -> Cons(x, return x) + + let rec prod a b = + fun () -> + match a (), b () with + | Nil, _ | _, Nil -> Nil + | Cons(x, a), Cons(y, b) -> Cons((x, y), prod a b) + + let ( let+ ) f s = map s f + let ( and+ ) a b = prod a b + +end +\end{caml_example} + +to support the syntax: + +\begin{caml_example}{verbatim} +open ZipSeq +let sum3 z1 z2 z3 = + let+ x1 = z1 + and+ x2 = z2 + and+ x3 = z3 in + x1 + x2 + x3 +\end{caml_example} + +which is equivalent to this expanded form: + +\begin{caml_example}{verbatim} +open ZipSeq +let sum3 z1 z2 z3 = + ( let+ ) (( and+ ) (( and+ ) z1 z2) z3) + (fun ((x1, x2), x3) -> x1 + x2 + x3) +\end{caml_example} + +\subsection{Rationale} + +This extension is intended to provide a convenient syntax for working +with monads and applicatives. + +An applicative should provide a module implementing the following +interface: + +\begin{caml_example*}{verbatim} +module type Applicative_syntax = sig + type 'a t + val ( let+ ) : 'a t -> ('a -> 'b) -> 'b t + val ( and+ ): 'a t -> 'b t -> ('a * 'b) t +end +\end{caml_example*} + +where "(let+)" is bound to the "map" operation and "(and+)" is bound to +the monoidal product operation. + +A monad should provide a module implementing the following interface: + +\begin{caml_example*}{verbatim} +module type Monad_syntax = sig + include Applicative_syntax + val ( let* ) : 'a t -> ('a -> 'b t) -> 'b t + val ( and* ): 'a t -> 'b t -> ('a * 'b) t +end +\end{caml_example*} + +where "(let*)" is bound to the "bind" operation, and "(and*)" is also +bound to the monoidal product operation. + +%HEVEA\cutend diff --git a/manual/manual/refman/lex.etex b/manual/manual/refman/lex.etex index f1ac3ea1..3ae76ee5 100644 --- a/manual/manual/refman/lex.etex +++ b/manual/manual/refman/lex.etex @@ -1,5 +1,4 @@ \section{Lexical conventions} -\pdfsection{Lexical conventions} %HEVEA\cutname{lex.html} \subsubsection*{Blanks} @@ -55,6 +54,12 @@ integer-literal: { "0"\ldots"9"||"A"\ldots"F"||"a"\ldots"f"||"_" } | ["-"] ("0o"||"0O") ("0"\ldots"7") { "0"\ldots"7"||"_" } | ["-"] ("0b"||"0B") ("0"\ldots"1") { "0"\ldots"1"||"_" } +; +int32-literal: integer-literal 'l' +; +int64-literal: integer-literal 'L' +; +nativeint-literal: integer-literal 'n' \end{syntax} An integer literal is a sequence of one or more digits, optionally @@ -66,6 +71,9 @@ preceded by a minus sign. By default, integer literals are in decimal \entree{"0b", "0B"}{binary (radix 2)} \end{tableau} (The initial @"0"@ is the digit zero; the @"O"@ for octal is the letter O.) +An integer literal can be followed by one of the letters "l", "L" or "n" +to indicate that this integer has type "int32", "int64" or "nativeint" +respectively, instead of the default type "int" for integer literals. The interpretation of integer literals that fall outside the range of representable integer values is undefined. @@ -147,6 +155,11 @@ The two single quotes enclose either one character different from \begin{syntax} string-literal: '"' { string-character } '"' + | '{' quoted-string-id '|' { any-char } '|' quoted-string-id '}' +; +quoted-string-id: + { 'a'...'z' || '_' } +; ; string-character: regular-string-char @@ -171,6 +184,18 @@ To allow splitting long string literals across lines, the sequence followed by any number of spaces and horizontal tabulations at the beginning of the next line) is ignored inside string literals. +Quoted string literals provide an alternative lexical syntax for +string literals. They are useful to represent strings of arbitrary content +without escaping. Quoted strings are delimited by a matching pair +of @'{' quoted-string-id '|'@ and @'|' quoted-string-id '}'@ with +the same @quoted-string-id@ on both sides. Quoted strings do not interpret +any character in a special way but requires that the +sequence @'|' quoted-string-id '}'@ does not occur in the string itself. +The identifier @quoted-string-id@ is a (possibly empty) sequence of +lowercase letters and underscores that can be freely chosen to avoid +such issue (e.g. "{|hello|}", "{ext|hello {|world|}|ext}", ...). + + The current implementation places practically no restrictions on the length of string literals. @@ -255,9 +280,9 @@ The following character sequences are also keywords: % \begin{alltt} " != # & && ' ( ) * + , -" -" -. -> . .. : :: := :> ; ;; <" -" <- = > >] >} ? [ [< [> [| ]" -" _ ` { {< | |] || } ~" +" -. -> . .. .~ : :: := :> ; ;;" +" < <- = > >] >} ? [ [< [> [|" +" ] _ ` { {< | |] || } ~" \end{alltt} % Note that the following identifiers are keywords of the Camlp4 diff --git a/manual/manual/refman/modtypes.etex b/manual/manual/refman/modtypes.etex index cbcbaab5..6eaa7433 100644 --- a/manual/manual/refman/modtypes.etex +++ b/manual/manual/refman/modtypes.etex @@ -1,5 +1,4 @@ \section{Module types (module specifications)} -\pdfsection{Module types (module specifications)} %HEVEA\cutname{modtypes.html} Module types are the module-level equivalent of type expressions: they diff --git a/manual/manual/refman/modules.etex b/manual/manual/refman/modules.etex index 431ad83d..26216e59 100644 --- a/manual/manual/refman/modules.etex +++ b/manual/manual/refman/modules.etex @@ -1,5 +1,4 @@ \section{Module\label{s:module-expr} expressions (module implementations)} -\pdfsection{Module expressions (module implementations)} %HEVEA\cutname{modules.html} Module expressions are the module-level equivalent of value @@ -197,19 +196,18 @@ the @"open"@ stops at the end of the structure expression. The expression @'include' module-expr@ in a structure re-exports in the current structure all definitions of the structure denoted by -@module-expr@. For instance, if the identifier "S" is bound to the -module -\begin{verbatim} - struct type t = int let x = 2 end -\end{verbatim} -the module expression -\begin{verbatim} - struct include S let y = (x + 1 : t) end -\end{verbatim} -is equivalent to the module expression -\begin{verbatim} - struct type t = S.t let x = S.x let y = (x + 1 : t) end -\end{verbatim} +@module-expr@. For instance, if you define a module "S" as below +\begin{caml_example*}{verbatim} +module S = struct type t = int let x = 2 end +\end{caml_example} +defining the module "B" as +\begin{caml_example*}{verbatim} +module B = struct include S let y = (x + 1 : t) end +\end{caml_example} +is equivalent to defining it as +\begin{caml_example*}{verbatim} +module B = struct type t = S.t let x = S.x let y = (x + 1 : t) end +\end{caml_example} The difference between @'open'@ and @'include'@ is that @'open'@ simply provides short names for the components of the opened structure, without defining any components of the current structure, diff --git a/manual/manual/refman/names.etex b/manual/manual/refman/names.etex index 4f85eed4..030347e9 100644 --- a/manual/manual/refman/names.etex +++ b/manual/manual/refman/names.etex @@ -1,5 +1,4 @@ \section{Names} \label{s:names} -\pdfsection{Names} %HEVEA\cutname{names.html} Identifiers are used to give names to several classes of language diff --git a/manual/manual/refman/patterns.etex b/manual/manual/refman/patterns.etex index 8abdce5e..36b8679c 100644 --- a/manual/manual/refman/patterns.etex +++ b/manual/manual/refman/patterns.etex @@ -1,5 +1,4 @@ \section{Patterns} -\pdfsection{Patterns} \ikwd{as\@\texttt{as}} %HEVEA\cutname{patterns.html} \begin{syntax} @@ -21,13 +20,14 @@ pattern: | pattern '::' pattern | '[|' pattern { ';' pattern } [ ';' ] '|]' | char-literal '..' char-literal + | 'lazy' pattern + | 'exception' pattern \end{syntax} -See also the following language extensions: \hyperref[s:lazypat]{lazy patterns}, +See also the following language extensions: \hyperref[s:local-opens]{local opens}, \hyperref[s-first-class-modules]{first-class modules}, -\hyperref[s:attributes]{attributes}, -\hyperref[s:extension-nodes]{extension nodes} and -\hyperref[s:exception-match]{exception cases in pattern matching}. +\hyperref[s:attributes]{attributes} and +\hyperref[s:extension-nodes]{extension nodes}. The table below shows the relative precedences and associativity of operators and non-closed pattern constructions. The constructions with @@ -176,3 +176,52 @@ The pattern where \nth{c}{1}, \nth{c}{2}, \ldots, \nth{c}{n} are the characters that occur between \var{c} and \var{d} in the ASCII character set. For instance, the pattern "'0'"@'..'@"'9'" matches all characters that are digits. + +\subsubsection{Lazy patterns} \label{s:lazypat} + +\ikwd{lazy\@\texttt{lazy}} + +(Introduced in Objective Caml 3.11) + +\begin{syntax} +pattern: ... +\end{syntax} + +The pattern @"lazy" pattern@ matches a value \var{v} of type "Lazy.t", +provided @pattern@ matches the result of forcing \var{v} with +"Lazy.force". A successful match of a pattern containing @"lazy"@ +sub-patterns forces the corresponding parts of the value being matched, even +those that imply no test such as @"lazy" value-name@ or @"lazy" "_"@. +Matching a value with a @pattern-matching@ where some patterns +contain @"lazy"@ sub-patterns may imply forcing parts of the value, +even when the pattern selected in the end has no @"lazy"@ sub-pattern. + +For more information, see the description of module "Lazy" in the +standard library (module \stdmoduleref{Lazy}). +% +\index{Lazy (module)\@\verb`Lazy` (module)}% +\index{force\@\verb`force`}% + +\subsubsection*{Exception patterns} \label{s:exception-match} +(Introduced in OCaml 4.02) + +A new form of exception pattern, @ 'exception' pattern @, is allowed +only as a toplevel pattern or inside a toplevel or-pattern under +a "match"..."with" pattern-matching +(other occurrences are rejected by the type-checker). + +Cases with such a toplevel pattern are called ``exception cases'', +as opposed to regular ``value cases''. Exception cases are applied +when the evaluation of the matched expression raises an exception. +The exception value is then matched against all the exception cases +and re-raised if none of them accept the exception (as with a +"try"..."with" block). Since the bodies of all exception and value +cases are outside the scope of the exception handler, they are all +considered to be in tail-position: if the "match"..."with" block +itself is in tail position in the current function, any function call +in tail position in one of the case bodies results in an actual tail +call. + +A pattern match must contain at least one value case. It is an error if +all cases are exceptions, because there would be no code to handle +the return of a value. diff --git a/manual/manual/refman/refman.etex b/manual/manual/refman/refman.etex index a7daea02..496e9805 100644 --- a/manual/manual/refman/refman.etex +++ b/manual/manual/refman/refman.etex @@ -1,5 +1,4 @@ \chapter{The OCaml language} \label{c:refman} -\pdfchapterfold{-12}{Reference manual for the OCaml language} %HEVEA\cutname{language.html} %better html output that way, sniff. diff --git a/manual/manual/refman/typedecl.etex b/manual/manual/refman/typedecl.etex index 9961f182..0370a73b 100644 --- a/manual/manual/refman/typedecl.etex +++ b/manual/manual/refman/typedecl.etex @@ -1,6 +1,5 @@ \section{Type and exception definitions} %HEVEA\cutname{typedecl.html}% -\pdfsection{Type and exception definitions} \subsection{Type definitions} \label{s:type-defs} diff --git a/manual/manual/refman/types.etex b/manual/manual/refman/types.etex index 231a1f87..5528ec42 100644 --- a/manual/manual/refman/types.etex +++ b/manual/manual/refman/types.etex @@ -1,5 +1,4 @@ \section{Type expressions} -\pdfsection{Type expressions} %HEVEA\cutname{types.html} \ikwd{as\@\texttt{as}} diff --git a/manual/manual/refman/values.etex b/manual/manual/refman/values.etex index d5d01f0f..dd9ff953 100644 --- a/manual/manual/refman/values.etex +++ b/manual/manual/refman/values.etex @@ -1,5 +1,4 @@ \section{Values} -\pdfsection{Values} %HEVEA\cutname{values.html} This section describes the kinds of values that are manipulated by diff --git a/manual/manual/style.css b/manual/manual/style.css index 8711a22e..201f1118 100644 --- a/manual/manual/style.css +++ b/manual/manual/style.css @@ -3,13 +3,13 @@ font-family: 'Fira Sans'; font-style: normal; font-weight: 400; - src: url('/pub/docs/manual-ocaml/fonts/fira-sans-v8-latin-regular.eot'); /* IE9 Compat Modes */ + src: url('../fonts/fira-sans-v8-latin-regular.eot'); /* IE9 Compat Modes */ src: local('Fira Sans Regular'), local('FiraSans-Regular'), - url('/pub/docs/manual-ocaml/fonts/fira-sans-v8-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('/pub/docs/manual-ocaml/fonts/fira-sans-v8-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ - url('/pub/docs/manual-ocaml/fonts/fira-sans-v8-latin-regular.woff') format('woff'), /* Modern Browsers */ - url('/pub/docs/manual-ocaml/fonts/fira-sans-v8-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ - url('/pub/docs/manual-ocaml/fonts/fira-sans-v8-latin-regular.svg#FiraSans') format('svg'); /* Legacy iOS */ + url('../fonts/fira-sans-v8-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('../fonts/fira-sans-v8-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ + url('../fonts/fira-sans-v8-latin-regular.woff') format('woff'), /* Modern Browsers */ + url('../fonts/fira-sans-v8-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ + url('../fonts/fira-sans-v8-latin-regular.svg#FiraSans') format('svg'); /* Legacy iOS */ } diff --git a/manual/manual/texstuff/.cvsignore b/manual/manual/texstuff/.cvsignore deleted file mode 100644 index 84eade83..00000000 --- a/manual/manual/texstuff/.cvsignore +++ /dev/null @@ -1,13 +0,0 @@ -*.aux -*.dvi -*.idx -*.ilg -*.ind -*.log -*.toc -*.ipr -*.txt -*.pdf -*.ps -pdfmanual.out -manual.out diff --git a/manual/manual/texstuff/.gitignore b/manual/manual/texstuff/.gitignore index 84eade83..4a604497 100644 --- a/manual/manual/texstuff/.gitignore +++ b/manual/manual/texstuff/.gitignore @@ -9,5 +9,5 @@ *.txt *.pdf *.ps -pdfmanual.out +manual.out manual.out diff --git a/manual/manual/textman/.cvsignore b/manual/manual/textman/.cvsignore deleted file mode 100644 index 72475845..00000000 --- a/manual/manual/textman/.cvsignore +++ /dev/null @@ -1,5 +0,0 @@ -manual.txt -manual.hmanual.kwd -*.haux -*.hind -*.htoc diff --git a/manual/manual/tutorials/.cvsignore b/manual/manual/tutorials/.cvsignore deleted file mode 100644 index 81ccbe71..00000000 --- a/manual/manual/tutorials/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -*.tex -*.htex diff --git a/manual/manual/tutorials/Makefile b/manual/manual/tutorials/Makefile index b454374d..bf941a54 100644 --- a/manual/manual/tutorials/Makefile +++ b/manual/manual/tutorials/Makefile @@ -1,31 +1,32 @@ -FILES= coreexamples.tex lablexamples.tex objectexamples.tex moduleexamples.tex\ -advexamples.tex polymorphism.tex - -TOPDIR=../../.. +TOPDIR = ../../.. include $(TOPDIR)/Makefile.tools -LD_PATH="$(TOPDIR)/otherlibs/str:$(TOPDIR)/otherlibs/unix" +LD_PATH = "$(TOPDIR)/otherlibs/str:$(TOPDIR)/otherlibs/unix" -CAMLLATEX=$(SET_LD_PATH) $(OCAMLRUN) ../../tools/caml-tex2 -TEXQUOTE=../../tools/texquote2 +TOOLS = ../../tools +CAMLLATEX = $(SET_LD_PATH) \ + $(OCAMLRUN) $(TOPDIR)/tools/caml-tex \ + -repo-root $(TOPDIR) -n 80 -v false +TEXQUOTE = $(OCAMLRUN) $(TOOLS)/texquote2 +TRANSF = $(SET_LD_PATH) $(OCAMLRUN) $(TOOLS)/transf -ALLFILES=$(FILES) -etex-files: $(ALLFILES) -all: $(ALLFILES) +FILES = coreexamples.tex lablexamples.tex objectexamples.tex \ + moduleexamples.tex advexamples.tex polymorphism.tex -clean: - rm -f $(ALLFILES) -.SUFFIXES: -.SUFFIXES: .etex .tex +etex-files: $(FILES) +all: $(FILES) + -.etex.tex: - @$(CAMLLATEX) -caml "TERM=norepeat $(OCAML)" -n 80 -v false\ - -o $*.caml_tex_error.tex $*.etex\ - && mv $*.caml_tex_error.tex $*.gen.tex\ - && $(TEXQUOTE) < $*.gen.tex > $*.texquote_error.tex\ - && mv $*.texquote_error.tex $*.tex\ - || printf "Failure when generating %s\n" $*.tex +%.gen.tex: %.etex + $(CAMLLATEX) $< -o $@ -$(ALLFILES): ../../tools/caml-tex2 $(TEXQUOTE) +%.tex: %.gen.tex + $(TEXQUOTE) < $< > $*.texquote_error.tex + mv $*.texquote_error.tex $@ + + +.PHONY: clean +clean: + rm -f *.tex diff --git a/manual/manual/tutorials/advexamples.etex b/manual/manual/tutorials/advexamples.etex index 2be639d5..c3037eb3 100644 --- a/manual/manual/tutorials/advexamples.etex +++ b/manual/manual/tutorials/advexamples.etex @@ -1,9 +1,8 @@ \chapter{Advanced examples with classes and modules} -\pdfchapterfold{-3}{Tutorial: Advanced examples with classes and modules} %HEVEA\cutname{advexamples.html} \label{c:advexamples} -{\it (Chapter written by Didier Rémy)} +{\it (Chapter written by Didier Rémy)} \bigskip @@ -17,7 +16,6 @@ programming pattern known as {\em virtual types} through the example of window managers. \section{Extended example: bank accounts} -\pdfsection{Extended example: bank accounts} \label{ss:bank-accounts} In this section, we illustrate most aspects of Object and inheritance @@ -300,7 +298,6 @@ new Client.account (new Euro.c 100.);; \section{Simple modules as classes} -\pdfsection{Simple modules as classes} \label{ss:modules-as-classes} One may wonder whether it is possible to treat primitive types such as @@ -533,7 +530,6 @@ module Set : SET = \end{caml_example*} \section{The subject/observer pattern} -\pdfsection{The subject/observer pattern} \label{ss:subject-observer} The following example, known as the subject/observer pattern, is often diff --git a/manual/manual/tutorials/coreexamples.etex b/manual/manual/tutorials/coreexamples.etex index 396265b0..f105327e 100644 --- a/manual/manual/tutorials/coreexamples.etex +++ b/manual/manual/tutorials/coreexamples.etex @@ -1,5 +1,4 @@ \chapter{The core language} \label{c:core-xamples} -\pdfchapterfold{-9}{Tutorial: The core language} %HEVEA\cutname{coreexamples.html} This part of the manual is a tutorial introduction to the @@ -13,7 +12,6 @@ extensions to the core language (labeled arguments and polymorphic variants), and chapter~\ref{c:advexamples} gives some advanced examples. \section{Basics} -\pdfsection{Basics} For this overview of OCaml, we use the interactive system, which is started by running "ocaml" from the Unix shell, or by launching the @@ -51,15 +49,29 @@ fib 10;; \end{caml_example} \section{Data types} -\pdfsection{Data types} In addition to integers and floating-point numbers, OCaml offers the -usual basic data types: booleans, characters, and immutable character strings. +usual basic data types: +\begin{itemize}% +\item booleans \begin{caml_example}{toplevel} (1 < 2) = false;; -'a';; -"Hello world";; +let one = if true then 1 else 2;; \end{caml_example} +\item characters +\begin{caml_example}{toplevel} + 'a';; + int_of_char '\n';; +\end{caml_example} +\item immutable character strings +\begin{caml_example}{toplevel} +"Hello" ^ " " ^ "world";; +{|This is a quoted string, here, neither \ nor " are special characters|};; +{|"\\"|}="\"\\\\\"";; + {delimiter|the end of this|}quoted string is here|delimiter} += "the end of this|}quoted string is here";; +\end{caml_example} +\end{itemize} Predefined data structures include tuples, arrays, and lists. There are also general mechanisms for defining your own data structures, such as records and @@ -121,7 +133,6 @@ the type inferred for "insert", "'a -> 'a list -> 'a list", means that "insert" takes two arguments, an element of any type "'a" and a list with elements of the same type "'a" and returns a list of the same type. \section{Functions as values} -\pdfsection{Functions as values} OCaml is a functional language: functions in the full mathematical sense are supported and can be passed around freely just as any other @@ -159,7 +170,6 @@ let rec map f l = \end{caml_example} \section{Records and variants} -\pdfsection{Records and variants} \label{s:tut-recvariants} User-defined data structures include records and variants. Both are @@ -378,7 +388,6 @@ Consequently, adding explicit type annotations to guide disambiguation is more robust than relying on the last defined type disambiguation. \section{Imperative features} -\pdfsection{Imperative features} Though all examples so far were written in purely applicative style, OCaml is also equipped with full imperative features. This includes the @@ -463,7 +472,6 @@ g r;; \end{caml_example} \section{Exceptions} -\pdfsection{Exceptions} OCaml provides exceptions for signalling and handling exceptional conditions. Exceptions can also be used as a general-purpose non-local @@ -506,7 +514,18 @@ name_of_binary_digit (-1);; The "with" part does pattern matching on the exception value with the same syntax and behavior as "match". Thus, several exceptions can be caught by one -"try"\ldots"with" construct. Also, finalization can be performed by +"try"\ldots"with" construct: +\begin{caml_example}{toplevel} +let rec first_named_value values names = + try + List.assoc (head values) names + with + | Empty_list -> "no named value" + | Not_found -> first_named_value (List.tl values) names;; +first_named_value [ 0; 10 ] [ 1, "one"; 10, "ten"];; +\end{caml_example} + +Also, finalization can be performed by trapping all exceptions, performing the finalization, then re-raising the exception: \begin{caml_example}{toplevel} @@ -522,8 +541,119 @@ let temporarily_set_reference ref newval funct = raise x;; \end{caml_example} +An alternative to "try"\ldots"with" is to catch the exception while +pattern matching: +\begin{caml_example}{toplevel} +let assoc_may_map f x l = + match List.assoc x l with + | exception Not_found -> None + | y -> f y;; +\end{caml_example} +Note that this construction is only useful if the exception is raised +between "match"\ldots"with". Exception patterns can be combined +with ordinary patterns at the toplevel, +\begin{caml_example}{toplevel} +let flat_assoc_opt x l = + match List.assoc x l with + | None | exception Not_found -> None + | Some _ as v -> v;; +\end{caml_example} +but they cannot be nested inside other patterns. For instance, +the pattern "Some (exception A)" is invalid. + +When exceptions are used as a control structure, it can be useful to make +them as local as possible by using a locally defined exception. +For instance, with +\begin{caml_eval} + let ref x: _ ref = {contents=x};; +\end{caml_eval} +\begin{caml_example}{toplevel} +let fixpoint f x = + let exception Done in + let x = ref x in + try while true do + let y = f !x in + if !x = y then raise Done else x := y + done; assert false + with Done -> !x;; +\end{caml_example} +the function "f" cannot raise a "Done" exception, which removes an +entire class of misbehaving functions. + +\section{Lazy expressions} + +OCaml allows us to defer some computation until later when we need the result of + that computation. + +We use "lazy (expr)" to delay the evaluation of some expression "expr". For +example, we can defer the computation of "1+1" until we need the result of that +expression, "2". Let us see how we initialize a lazy expression. + +\begin{caml_example}{toplevel} + let lazy_two = lazy ( print_endline "lazy_two evaluation"; 1 + 1 );; +\end{caml_example} + +We added "print_endline \"lazy_two evaluation\"" to see when the lazy + expression is being evaluated. + +The value of "lazy_two" is displayed as "", which means the expression +has not been evaluated yet, and its final value is unknown. + +Note that "lazy_two" has type "int lazy_t". However, the type "'a lazy_t" is an +internal type name, so the type "'a Lazy.t" should be preferred when possible. + +When we finally need the result of a lazy expression, we can call "Lazy.force" +on that expression to force its evaluation. The function "force" comes from +standard-library module \stdmoduleref{Lazy}. + +\begin{caml_example}{toplevel} + Lazy.force lazy_two;; +\end{caml_example} + +Notice that our function call above prints ``lazy_two evaluation'' and then +returns the plain value of the computation. + +Now if we look at the value of "lazy_two", we see that it is not displayed as +"" anymore but as "lazy 2". + +\begin{caml_example}{toplevel} + lazy_two;; +\end{caml_example} + +This is because "Lazy.force" memoizes the result of the forced expression. In other +words, every subsequent call of "Lazy.force" on that expression returns the +result of the first computation without recomputing the lazy expression. Let us +force "lazy_two" once again. + +\begin{caml_example}{toplevel} + Lazy.force lazy_two;; +\end{caml_example} + +The expression is not evaluated this time; notice that ``lazy_two evaluation'' is +not printed. The result of the initial computation is simply returned. + +Lazy patterns provide another way to force a lazy expression. + +\begin{caml_example}{toplevel} + let lazy_l = lazy ([1; 2] @ [3; 4]);; + let lazy l = lazy_l;; +\end{caml_example} + +We can also use lazy patterns in pattern matching. + +\begin{caml_example}{toplevel} + let maybe_eval lazy_guard lazy_expr = + match lazy_guard, lazy_expr with + | lazy false, _ -> "matches if (Lazy.force lazy_guard = false); lazy_expr not forced" + | lazy true, lazy _ -> "matches if (Lazy.force lazy_guard = true); lazy_expr forced";; +\end{caml_example} + +The lazy expression "lazy_expr" is forced only if the "lazy_guard" value yields +"true" once computed. Indeed, a simple wildcard pattern (not lazy) never forces +the lazy expression's evaluation. However, a pattern with keyword "lazy", even +if it is wildcard, always forces the evaluation of the deferred computation. + \section{Symbolic processing of expressions} -\pdfsection{Symbolic processing of expressions} We finish this introduction with a more complete example representative of the use of OCaml for symbolic processing: formal @@ -574,7 +704,6 @@ deriv (Quot(Const 1.0, Var "x")) "x";; \end{caml_example} \section{Pretty-printing} -\pdfsection{Pretty-printing} As shown in the examples above, the internal representation (also called {\em abstract syntax\/}) of expressions quickly becomes hard to @@ -621,6 +750,93 @@ print_expr e; print_newline ();; print_expr (deriv e "x"); print_newline ();; \end{caml_example} +\section{Printf formats} + +There is a "printf" function in the \stdmoduleref{Printf} module +(see chapter~\ref{c:moduleexamples}) that allows you to make formatted +output more concisely. +It follows the behavior of the "printf" function from the C standard library. +The "printf" function takes a format string that describes the desired output +as a text interspered with specifiers (for instance "%d", "%f"). +Next, the specifiers are substituted by the following arguments in their order +of apparition in the format string: +\begin{caml_example}{toplevel} +Printf.printf "%i + %i is an integer value, %F * %F is a float, %S\n" +3 2 4.5 1. "this is a string";; +\end{caml_example} +The OCaml type system checks that the type of the arguments and the specifiers are +compatible. If you pass it an argument of a type that does not correspond to +the format specifier, the compiler will display an error message: +\begin{caml_example}{toplevel}[error] +Printf.printf "Float value: %F" 42;; +\end{caml_example} +The "fprintf" function is like "printf" except that it takes an output channel as +the first argument. The "%a" specifier can be useful to define custom printer +(for custom types). For instance, we can create a printing template that converts +an integer argument to signed decimal: +\begin{caml_example}{toplevel} +let pp_int ppf n = Printf.fprintf ppf "%d" n;; +Printf.printf "Outputting an integer using a custom printer: %a " pp_int 42;; +\end{caml_example} +The advantage of those printers based on the "%a" specifier is that they can be +composed together to create more complex printers step by step. +We can define a combinator that can turn a printer for "'a" type into a printer +for "'a optional": +\begin{caml_example}{toplevel} +let pp_option printer ppf = function + | None -> Printf.fprintf ppf "None" + | Some v -> Printf.fprintf ppf "Some(%a)" printer v;; +Printf.fprintf stdout + "The current setting is %a. \nThere is only %a\n" + (pp_option pp_int) (Some 3) + (pp_option pp_int) None +;; +\end{caml_example} +If the value of its argument its "None", the printer returned by pp_option +printer prints "None" otherwise it uses the provided printer to print "Some ". + +Here is how to rewrite the pretty-printer using "fprintf": +\begin{caml_example}{toplevel} +let pp_expr ppf expr = + let open_paren prec op_prec output = + if prec > op_prec then Printf.fprintf output "%s" "(" in + let close_paren prec op_prec output = + if prec > op_prec then Printf.fprintf output "%s" ")" in + let rec print prec ppf expr = + match expr with + | Const c -> Printf.fprintf ppf "%F" c + | Var v -> Printf.fprintf ppf "%s" v + | Sum(f, g) -> + open_paren prec 0 ppf; + Printf.fprintf ppf "%a + %a" (print 0) f (print 0) g; + close_paren prec 0 ppf + | Diff(f, g) -> + open_paren prec 0 ppf; + Printf.fprintf ppf "%a - %a" (print 0) f (print 1) g; + close_paren prec 0 ppf + | Prod(f, g) -> + open_paren prec 2 ppf; + Printf.fprintf ppf "%a * %a" (print 2) f (print 2) g; + close_paren prec 2 ppf + | Quot(f, g) -> + open_paren prec 2 ppf; + Printf.fprintf ppf "%a / %a" (print 2) f (print 3) g; + close_paren prec 2 ppf + in print 0 ppf expr;; +pp_expr stdout e; print_newline ();; +pp_expr stdout (deriv e "x"); print_newline ();; +\end{caml_example} + +Due to the way that format string are build, storing a format string requires +an explicit type annotation: +\begin{caml_example*}{toplevel} +let str : _ format = + "%i is an integer value, %F is a float, %S\n";; +\end{caml_example*} +\begin{caml_example}{toplevel} +Printf.printf str 3 4.5 "string value";; +\end{caml_example} + %%%%%%%%%%% Should be moved to the camlp4 documentation. %% Parsing (transforming concrete syntax into abstract syntax) is usually %% more delicate. OCaml offers several tools to help write parsers: @@ -712,7 +928,6 @@ print_expr (deriv e "x"); print_newline ();; %% expected tokens: "Ident \"x\"", then "Kwd \"-\"", then "Int(1)". \section{Standalone OCaml programs} -\pdfsection{Standalone OCaml programs} All examples given so far were executed under the interactive system. OCaml code can also be compiled separately and executed diff --git a/manual/manual/tutorials/lablexamples.etex b/manual/manual/tutorials/lablexamples.etex index d4ceef17..ef792715 100644 --- a/manual/manual/tutorials/lablexamples.etex +++ b/manual/manual/tutorials/lablexamples.etex @@ -1,5 +1,4 @@ \chapter{Labels and variants} \label{c:labl-examples} -\pdfchapterfold{-2}{Tutorial: Labels and variants} %HEVEA\cutname{lablexamples.html} {\it (Chapter written by Jacques Garrigue)} @@ -9,7 +8,6 @@ OCaml 3: labels, and polymorphic variants. \section{Labels} -\pdfsection{Labels} If you have a look at modules ending in "Labels" in the standard library, you will see that function types have annotations you did not @@ -119,8 +117,9 @@ non-optional argument. The criterion for deciding whether an optional argument has been omitted is the non-labeled application of an argument appearing after this optional argument in the function type. Note that if that argument is labeled, you will only be able to -eliminate optional arguments through the special case for total -applications. +eliminate optional arguments by totally applying the function, +omitting all optional arguments and omitting all labels for all +remaining arguments. \begin{caml_example}{toplevel} let test ?(x = 0) ?(y = 0) () ?(z = 0) () = (x, y, z);; @@ -312,7 +311,6 @@ is only used when a more detailed specification is needed. \section{Polymorphic variants} -\pdfsection{Polymorphic variants} Variants as presented in section~\ref{s:tut-recvariants} are a powerful tool to build data structures and algorithms. However they diff --git a/manual/manual/tutorials/moduleexamples.etex b/manual/manual/tutorials/moduleexamples.etex index a9a4f648..bb68975c 100644 --- a/manual/manual/tutorials/moduleexamples.etex +++ b/manual/manual/tutorials/moduleexamples.etex @@ -1,11 +1,9 @@ \chapter{The module system} \label{c:moduleexamples} -\pdfchapterfold{-5}{Tutorial: The module system} %HEVEA\cutname{moduleexamples.html} This chapter introduces the module system of OCaml. \section{Structures} -\pdfsection{Structures} A primary motivation for modules is to package together related definitions (such as the definitions of a data type and associated @@ -121,7 +119,6 @@ an exception when the priority queue is empty. \end{caml_example} \section{Signatures} -\pdfsection{Signatures} Signatures are interfaces for structures. A signature specifies which components of a structure are accessible from the outside, and @@ -176,7 +173,6 @@ module type PRIOQUEUE_WITH_OPT = \section{Functors} -\pdfsection{Functors} Functors are ``functions'' from modules to modules. Functors let you create parameterized modules and then provide other modules as parameter(s) to get @@ -228,7 +224,6 @@ StringSet.member "bar" (StringSet.add "foo" StringSet.empty);; \end{caml_example} \section{Functors and type abstraction} -\pdfsection{Functors and type abstraction} As in the "PrioQueue" example, it would be good style to hide the actual implementation of the type "set", so that users of the @@ -318,7 +313,6 @@ operations from "AbstractStringSet" to values of type lists that violate the invariants of "NoCaseStringSet". \section{Modules and separate compilation} -\pdfsection{Modules and separate compilation} All examples of modules so far have been given in the context of the interactive system. However, modules are most useful for large, diff --git a/manual/manual/tutorials/objectexamples.etex b/manual/manual/tutorials/objectexamples.etex index 9166c3cd..919d3b7a 100644 --- a/manual/manual/tutorials/objectexamples.etex +++ b/manual/manual/tutorials/objectexamples.etex @@ -1,8 +1,7 @@ \chapter{Objects in OCaml} \label{c:objectexamples} -\pdfchapterfold{-15}{Tutorial: Objects in OCaml} %HEVEA\cutname{objectexamples.html} -{\it (Chapter written by J\'er\^ome Vouillon, Didier R\'emy and Jacques Garrigue)} +{\it (Chapter written by Jérôme Vouillon, Didier Rémy and Jacques Garrigue)} \bigskip @@ -51,7 +50,6 @@ at all. \end{htmlonly} \section{Classes and objects} -\pdfsection{Classes and objects} \label{ss:classes-and-objects} The class "point" below defines one instance variable "x" and two methods @@ -186,7 +184,6 @@ alternative is to use initializers, as described below in section \ref{ss:initializers}. \section{Immediate objects} -\pdfsection{Immediate objects} \label{ss:immediate-objects} There is another, more direct way to create an object: create it @@ -222,7 +219,6 @@ weaknesses can be advantages in some situations, as we will see in sections \ref{ss:reference-to-self} and \ref{ss:parameterized-classes}. \section{Reference to self} -\pdfsection{Reference to self} \label{ss:reference-to-self} A method or an initializer can invoke methods on self (that is, @@ -270,7 +266,6 @@ let my_int = \end{caml_example} \section{Initializers} -\pdfsection{Initializers} \label{ss:initializers} Let-bindings within class definitions are evaluated before the object @@ -297,7 +292,6 @@ Another example can be seen in section \ref{ss:bank-accounts}. \section{Virtual methods} -\pdfsection{Virtual methods and variables} \label{ss:virtual-methods} It is possible to declare a method without actually defining it, using @@ -339,7 +333,6 @@ class point2 x_init = \end{caml_example} \section{Private methods} -\pdfsection{Private methods} \label{ss:private-methods} Private methods are methods that do not appear in object interfaces. @@ -406,7 +399,6 @@ Of course, private methods can also be virtual. Then, the keywords must appear in this order "method private virtual". \section{Class interfaces} -\pdfsection{Class interfaces} \label{ss:class-interfaces} @@ -450,7 +442,6 @@ end;; \end{caml_example} \section{Inheritance} -\pdfsection{Inheritance} \label{ss:inheritance} We illustrate inheritance by defining a class of colored points that @@ -483,7 +474,6 @@ let incr p = set_x p (get_succ_x p);; \end{caml_example} \section{Multiple inheritance} -\pdfsection{Multiple inheritance} \label{ss:multiple-inheritance} Multiple inheritance is allowed. Only the last definition of a method @@ -536,7 +526,6 @@ class another_printable_colored_point y c c' = \end{caml_example} \section{Parameterized classes} -\pdfsection{Parameterized classes} \label{ss:parameterized-classes} Reference cells can be implemented as objects. @@ -643,7 +632,6 @@ class ['a] colored_circle c = \end{caml_example} \section{Polymorphic methods} -\pdfsection{Polymorphic methods} \label{ss:polymorphic-methods} While parameterized classes may be polymorphic in their contents, they @@ -664,7 +652,7 @@ does not work in practice. let l = new intlist [1; 2; 3];; l#fold (fun x y -> x+y) 0;; l;; -l#fold (fun s x -> s ^ string_of_int x ^ " ") "" [@@expect error];; +l#fold (fun s x -> s ^ Int.to_string x ^ " ") "" [@@expect error];; \end{caml_example} Our iterator works, as shows its first use for summation. However, since objects themselves are not polymorphic (only their constructors @@ -684,7 +672,7 @@ class intlist (l : int list) = end;; let l = new intlist [1; 2; 3];; l#fold (fun x y -> x+y) 0;; -l#fold (fun s x -> s ^ string_of_int x ^ " ") "";; +l#fold (fun s x -> s ^ Int.to_string x ^ " ") "";; \end{caml_example} As you can see in the class type shown by the compiler, while polymorphic method types must be fully explicit in class definitions @@ -711,7 +699,7 @@ The following idiom separates description and definition. \begin{caml_example*}{toplevel} class type ['a] iterator = object method fold : ('b -> 'a -> 'b) -> 'b -> 'b end;; -class intlist l = +class intlist' l = object (self : int #iterator) method empty = (l = []) method fold f accu = List.fold_left f accu l @@ -735,7 +723,7 @@ parameter. let sum (lst : _ #iterator) = lst#fold (fun x y -> x+y) 0;; \end{caml_example} Of course the constraint may also be an explicit method type. -Only occurences of quantified variables are required. +Only occurrences of quantified variables are required. \begin{caml_example}{toplevel} let sum lst = (lst : < fold : 'a. ('a -> _ -> 'a) -> 'a -> 'a; .. >)#fold (+) 0;; @@ -774,7 +762,6 @@ itself polymorphic. In method "m2", the argument of "n2" and "x" must have the same type, which is quantified at the same level as "'a". \section{Using coercions} -\pdfsection{Using coercions} \label{ss:using-coercions} Subtyping is never implicit. There are, however, two ways to perform @@ -970,7 +957,6 @@ type 'a c'_class = 'a constraint 'a = < m : int; .. >;; with an extra type variable capturing the open object type. \section{Functional objects} -\pdfsection{Functional objects} \label{ss:functional-objects} It is possible to write a version of class "point" without assignments @@ -983,12 +969,16 @@ class functional_point y = val x = y method get_x = x method move d = {< x = x + d >} + method move_to x = {< x >} end;; let p = new functional_point 7;; p#get_x;; (p#move 3)#get_x;; +(p#move_to 15)#get_x;; p#get_x;; \end{caml_example} +As with records, the form "{< x >}" is an elided version of +"{< x = x >}" which avoids the repetition of the instance variable name. Note that the type abbreviation "functional_point" is recursive, which can be seen in the class type of "functional_point": the type of self is "'a" and "'a" appears inside the type of the method "move". @@ -1001,6 +991,7 @@ class bad_functional_point y = val x = y method get_x = x method move d = new bad_functional_point (x+d) + method move_to x = new bad_functional_point x end;; \end{caml_example} While objects of either class will behave the same, objects of their @@ -1014,7 +1005,6 @@ Functional update is often used in conjunction with binary methods as illustrated in section \ref{module:string}. \section{Cloning objects} -\pdfsection{Cloning objects} \label{ss:cloning-objects} Objects can also be cloned, whether they are functional or imperative. @@ -1114,7 +1104,6 @@ p # save; p # set 1; p # save; p # set 2; \section{Recursive classes} -\pdfsection{Recursive classes} \label{ss:recursive-classes} Recursive classes can be used to define objects whose types are @@ -1136,7 +1125,6 @@ Although their types are mutually recursive, the classes "widget" and \section{Binary methods} -\pdfsection{Binary methods} \label{ss:binary-methods} A binary method is a method which takes an argument of the same type @@ -1226,7 +1214,6 @@ class money x = \end{caml_example} \section{Friends} -\pdfsection{Friends} \label{ss:friends} The above class "money" reveals a problem that often occurs with binary diff --git a/manual/manual/tutorials/polymorphism.etex b/manual/manual/tutorials/polymorphism.etex index 5402ec36..5e62979a 100644 --- a/manual/manual/tutorials/polymorphism.etex +++ b/manual/manual/tutorials/polymorphism.etex @@ -1,7 +1,6 @@ \chapter{Polymorphism and its limitations}% \label{c:polymorphism} -\pdfchapterfold{0}{Tutorial: Polymorphism limitations} %HEVEA\cutname{polymorphism.html} \bigskip @@ -79,7 +78,7 @@ Therefore, after placing an "int" in "store", we cannot use it to store any value other than an "int". More generally, weak types protect the program from undue mutation of values with a polymorphic type. -%todo: fix indentation in pdfmanual +%todo: fix indentation in manual.pdf Moreover, weak types cannot appear in the signature of toplevel modules: types must be known at compilation time. Otherwise, different compilation units could replace the weak type with different and incompatible types. diff --git a/manual/styles/ocamldoc.hva b/manual/styles/ocamldoc.hva index 58b7bb12..efabdbd4 100644 --- a/manual/styles/ocamldoc.hva +++ b/manual/styles/ocamldoc.hva @@ -14,7 +14,5 @@ {\endocamldocindent \noindent\quad\texttt{end}\medskip} -\newcommand{\moduleref}[1]{\ifhtml\ahref{libref/#1.html}{\texttt{#1}}\fi} - # For processing .tex generated by ocamldoc (for text manual) \newcommand{\ocamldocvspace}[1]{\vspace{#1}} \ No newline at end of file diff --git a/manual/styles/plaintext.sty b/manual/styles/plaintext.sty deleted file mode 100644 index 2d1b366c..00000000 --- a/manual/styles/plaintext.sty +++ /dev/null @@ -1,268 +0,0 @@ -% Plain text style file. - -\typeout{Style option Plaintext} - -% Version from John Pavel's dvidoc.sty, March 1987 -% Heavily hacked by Xavier Leroy, June 1993. - -% Redefine all fonts to be the "doc" pseudo-font, with fixed spacing. -% Since rm, tt and mi have different character encodings, we keep -% several copies of the doc font, with different names, so that dvi2txt -% can select the right encoding according to the name. Also, we use -% different names for boldface and italics, so that dvi2txt can select -% the right style whenever possible. - -\def\sl{\rm} -\def\sc{\rm} - -\def\vpt{} -\def\vipt{} -\def\viipt{} -\def\viiipt{} -\def\ixpt{} -\def\xipt{} -\def\xiipt{} -\def\xivpt{} -\def\xviipt{} -\def\xxpt{} -\def\xxvpt{} - -%%% for i in fiv six sev egt nin ten elv twl frtn svnt twty twfv; do -%%% echo "\\font\\${i}rm = docrm" -%%% echo "\\font\\${i}mi = docmi" -%%% echo "\\font\\${i}sy = cmsy10" -%%% echo "\\font\\${i}it = docit" -%%% echo "\\font\\${i}bf = docbf" -%%% echo "\\font\\${i}tt = doctt" -%%% echo "\\font\\${i}sf = docrm" -%%% done - -\font\fivrm = docrm -\font\fivmi = docmi -\font\fivsy = cmsy10 -\font\fivit = docit -\font\fivbf = docbf -\font\fivtt = doctt -\font\fivsf = docrm -\font\sixrm = docrm -\font\sixmi = docmi -\font\sixsy = cmsy10 -\font\sixit = docit -\font\sixbf = docbf -\font\sixtt = doctt -\font\sixsf = docrm -\font\sevrm = docrm -\font\sevmi = docmi -\font\sevsy = cmsy10 -\font\sevit = docit -\font\sevbf = docbf -\font\sevtt = doctt -\font\sevsf = docrm -\font\egtrm = docrm -\font\egtmi = docmi -\font\egtsy = cmsy10 -\font\egtit = docit -\font\egtbf = docbf -\font\egttt = doctt -\font\egtsf = docrm -\font\ninrm = docrm -\font\ninmi = docmi -\font\ninsy = cmsy10 -\font\ninit = docit -\font\ninbf = docbf -\font\nintt = doctt -\font\ninsf = docrm -\font\tenrm = docrm -\font\tenmi = docmi -\font\tensy = cmsy10 -\font\tenit = docit -\font\tenbf = docbf -\font\tentt = doctt -\font\tensf = docrm -\font\elvrm = docrm -\font\elvmi = docmi -\font\elvsy = cmsy10 -\font\elvit = docit -\font\elvbf = docbf -\font\elvtt = doctt -\font\elvsf = docrm -\font\twlrm = docrm -\font\twlmi = docmi -\font\twlsy = cmsy10 -\font\twlit = docit -\font\twlbf = docbf -\font\twltt = doctt -\font\twlsf = docrm -\font\frtnrm = docrm -\font\frtnmi = docmi -\font\frtnsy = cmsy10 -\font\frtnit = docit -\font\frtnbf = docbf -\font\frtntt = doctt -\font\frtnsf = docrm -\font\svtnrm = docrm -\font\svtnmi = docmi -\font\svtnsy = cmsy10 -\font\svtnit = docit -\font\svtnbf = docbf -\font\svtntt = doctt -\font\svtnsf = docrm -\font\twtyrm = docrm -\font\twtymi = docmi -\font\twtysy = cmsy10 -\font\twtyit = docit -\font\twtybf = docbf -\font\twtytt = doctt -\font\twtysf = docrm -\font\twfvrm = docrm -\font\twfvmi = docmi -\font\twfvsy = cmsy10 -\font\twfvit = docit -\font\twfvbf = docbf -\font\twfvtt = doctt -\font\twfvsf = docrm - -\rm - -% Dimensions - -\hsize 78 em % 78 characters per line so fit any screen -\textwidth 78 em -\raggedright % Do not try to align on the right -\parindent=2em % Two blanks for paragraph indentation -\def\enspace{\kern 1em} \def\enskip{\hskip 1em\relax} - -% Vertical skips may best be multiples of \baselineskip -\baselineskip=12pt % 6 lines per inch -\normalbaselineskip=\baselineskip -\vsize 58\baselineskip % 58 lines per page -\textheight 58\baselineskip -\voffset=0pt -\parskip=0pt -\smallskipamount=0pt -\medskipamount= \baselineskip -\bigskipamount=2\baselineskip -\raggedbottom % do not try to align the page bottom - -% By default itemize is done with bullets, which don't look good. - -\def\labelitemi{-} -\def\labelitemii{-} -\def\labelitemiii{-} -\def\labelitemiv{-} - -% Fix up table of contents. Default latex uses fractional spacing between -% the section number and title. This comes out as no space in the doc file -% so we add a space to numberline, and expand tempdima by one em to allow -% for it. Also, go out of math mode for the dot in the leader. Dots in -% math mode turn out to be colons! -% -\def\@dottedtocline#1#2#3#4#5{\ifnum #1>\c@tocdepth \else - \vskip \z@ plus .2pt - {\hangindent #2\relax \rightskip \@tocrmarg \parfillskip -\rightskip - \parindent #2\relax\@afterindenttrue - \interlinepenalty\@M - \leavevmode - \@tempdima #3\relax - \addtolength\@tempdima{1em} - #4\nobreak\leaders\hbox to 2em{\hss.\hss}\hfill \nobreak \hbox to\@pnumwidth{\hfil\rm #5}\par}\fi} -\def\numberline#1{\advance\hangindent\@tempdima \hbox to\@tempdima{#1\hfil}\ } -% -% Can't really do superscripts, so do footnotes with [] -% -\def\@makefnmark{\hbox{(\@thefnmark)}} -\long\def\@makefntext#1{\parindent 1em\noindent - \hbox to 3em{\hss\@thefnmark.}\ #1} -\skip\footins 24pt plus 4pt minus 2pt -\def\footnoterule{\kern-12\p@ -\hbox to .4\columnwidth{\leaders\hbox{-}\hfill}} -% -% \arrayrulewidth 1em \doublerulesep 1em -% -% Some fairly obvious hacks. No odd/even pages in doc files. Can't do the -% fancy TeX symbols. -% -\oddsidemargin 0pt \evensidemargin 0pt -\def\TeX{TeX} -\def\LaTeX{LaTeX} -\def\SliTeX{SliTeX} -\def\BibTeX{BibTeX} -% -% special versions of stuff from xxx10.sty, since only one font size -% -\def\@normalsize{\@setsize\normalsize{12pt}\xpt\@xpt -\abovedisplayskip 12pt -\belowdisplayskip 12pt -\abovedisplayshortskip 12pt -\belowdisplayshortskip 12pt -\let\@listi\@listI} % Setting of \@listi added 9 Jun 87 -\let\small\@normalsize -\let\footnotesize\@normalsize -\normalsize -\footnotesep 12pt -\labelsep 10pt -\def\@listI{\leftmargin\leftmargini \parsep 12pt% -\topsep 12pt% -\partopsep 0pt% -\itemsep 0pt} -\let\@listi\@listI -\let\@listii\@listI -\let\@listiii\@listI -\let\@listiv\@listI -\let\@listv\@listI -\let\@listvi\@listI -\@listI - -% We had sort of random numbers of blank lines around section numbers. -% Turns out they used various fractional spacing. Rather than depend -% upon the definition of startsection, just wrap something around it -% that normalizes the arguments to 12pt. Negative args have special -% meanings. -\let\@oldstartsec\@startsection -\def\@startsection#1#2#3#4#5#6{ - \@tempskipa #4\relax - \@tempskipb #5\relax - \ifdim \@tempskipa <\z@ \@tempskipa -12pt \else \@tempskipa 12pt \fi - \ifdim \@tempskipb >\z@ \@tempskipb 12pt \fi -\@oldstartsec{#1}{#2}{#3}{\@tempskipa}{\@tempskipb}{#6} -} - -% To get even spacing in the table of contents - -\def\@pnumwidth{3em} - -\def\l@part#1#2{\addpenalty{-\@highpenalty}% - \addvspace{12pt}% space above part line - \begingroup - \@tempdima 3em - \parindent \z@ \rightskip \@pnumwidth - \parfillskip -\@pnumwidth - {\large \bf - \leavevmode - #1\hfil \hbox to\@pnumwidth{\hss #2}}\par - \nobreak - \global\@nobreaktrue - \everypar{\global\@nobreakfalse\everypar{}}%% suggested by - - \endgroup} - -\def\l@chapter#1#2{\addpenalty{-\@highpenalty}% - \vskip 12pt - \@tempdima 2em - \begingroup - \parindent \z@ \rightskip \@pnumwidth - \parfillskip -\@pnumwidth - \bf - \leavevmode - \advance\leftskip\@tempdima - \hskip -\leftskip - #1\nobreak\hfil \nobreak\hbox to\@pnumwidth{\hss #2}\par - \penalty\@highpenalty - \endgroup} - -\def\l@section{\@dottedtocline{1}{2em}{3em}} -\def\l@subsection{\@dottedtocline{2}{4em}{3em}} -\def\l@subsubsection{\@dottedtocline{3}{7em}{4em}} -\def\l@paragraph{\@dottedtocline{4}{10em}{5em}} -\def\l@subparagraph{\@dottedtocline{5}{12em}{6em}} - diff --git a/manual/tests/.gitignore b/manual/tests/.gitignore new file mode 100644 index 00000000..0229a346 --- /dev/null +++ b/manual/tests/.gitignore @@ -0,0 +1 @@ +/cross-reference-checker diff --git a/manual/tests/Makefile b/manual/tests/Makefile index 3947b175..802f43a0 100644 --- a/manual/tests/Makefile +++ b/manual/tests/Makefile @@ -5,16 +5,28 @@ MANUAL=$(TOPDIR)/manual/manual .PHONY: all all: check-cross-references check-stdlib +.PHONY: tools +tools: cross-reference-checker + cross-reference-checker: cross_reference_checker.ml - $(OCAMLC) $(TOPDIR)/compilerlibs/ocamlcommon.cma -I $(TOPDIR)/parsing \ - -I $(TOPDIR)/driver \ - cross_reference_checker.ml -o cross-reference-checker + $(OCAMLC) $(TOPDIR)/compilerlibs/ocamlcommon.cma \ + -I $(TOPDIR)/parsing -I $(TOPDIR)/driver \ + $< -o $@ +.PHONY: check-cross-references check-cross-references: cross-reference-checker - $(OCAMLRUN) ./cross-reference-checker \ - -auxfile $(MANUAL)/texstuff/manual.aux \ - $(TOPDIR)/utils/warnings.ml \ - $(TOPDIR)/bytecomp/translmod.ml + $(SET_LD_PATH) \ + $(OCAMLRUN) ./cross-reference-checker \ + -auxfile $(MANUAL)/texstuff/manual.aux \ + $(TOPDIR)/utils/warnings.ml \ + $(TOPDIR)/driver/main_args.ml \ + $(TOPDIR)/bytecomp/translmod.ml +.PHONY: check-stdlib check-stdlib: ./check-stdlib-modules $(TOPDIR) + + +.PHONY: clean +clean: + rm -f *.cm? *.cmx? cross-reference-checker diff --git a/manual/tests/cross_reference_checker.ml b/manual/tests/cross_reference_checker.ml index 98eb598d..c451e635 100644 --- a/manual/tests/cross_reference_checker.ml +++ b/manual/tests/cross_reference_checker.ml @@ -28,7 +28,7 @@ let pp_ref ppf = Format.pp_print_list ~pp_sep:( fun ppf () -> Format.pp_print_string ppf ".") Format.pp_print_int ppf let print_error error = - Location.report_error Format.std_formatter @@ match error with + Location.print_report Format.std_formatter @@ match error with | Tuple_expected loc -> Location.errorf ~loc "Integer tuple expected after manual reference annotation@." @@ -130,22 +130,22 @@ end (** {1 Extract references from Ocaml source files} *) module OCaml_refs = struct - let parse ppf sourcefile = - Pparse.parse_implementation ppf ~tool_name:"manual_cross_reference_check" + let parse sourcefile = + Pparse.parse_implementation ~tool_name:"manual_cross_reference_check" sourcefile (** search for an attribute [[@manual.ref "tex_label_name"]] *) - let manual_reference_attribute (s, payload) = - if s.Location.txt = "manual.ref" then - match payload with - | Parsetree.( - PStr [{pstr_desc= Pstr_eval - ({ pexp_desc = Pexp_constant Pconst_string (s,_) },_) } ] ) -> + let manual_reference_attribute attr = + let open Parsetree in + if attr.attr_name.Location.txt <> "manual.ref" + then None + else begin match attr.attr_payload with + | PStr [{pstr_desc= Pstr_eval + ({ pexp_desc = Pexp_constant Pconst_string (s,_) },_) } ] -> Some s - | _ -> print_error (Wrong_attribute_payload s.Location.loc); + | _ -> print_error (Wrong_attribute_payload attr.attr_loc); Some "" (* triggers an error *) - else - None + end let rec label_from_attributes = function | [] -> None @@ -213,7 +213,7 @@ module OCaml_refs = struct iterator.structure iterator ast let from_file m f = - from_ast m @@ parse Format.std_formatter f + from_ast m @@ parse f end diff --git a/manual/tools/.gitignore b/manual/tools/.gitignore index db7f8368..f59594f4 100644 --- a/manual/tools/.gitignore +++ b/manual/tools/.gitignore @@ -6,7 +6,6 @@ htmlgen htmlquote latexscan.ml dvi2txt -caml-tex2 *.dSYM *.cm[io] *.o diff --git a/manual/tools/.ignore b/manual/tools/.ignore deleted file mode 100644 index 12c72e4a..00000000 --- a/manual/tools/.ignore +++ /dev/null @@ -1,11 +0,0 @@ -transf.ml -texquote2 -htmltransf.ml -transf -htmlgen -htmlquote -latexscan.ml -dvi2txt -caml-tex2 -*.dSYM -*.cm[io] diff --git a/manual/tools/Makefile b/manual/tools/Makefile index b3500acb..ea379824 100644 --- a/manual/tools/Makefile +++ b/manual/tools/Makefile @@ -2,53 +2,29 @@ TOPDIR=../.. COMPFLAGS=-I $(OTOPDIR)/otherlibs/str -I $(OTOPDIR)/otherlibs/unix include $(TOPDIR)/Makefile.tools -CFLAGS=-g -O +all: texquote2 transf -all: texquote2 transf htmlquote htmlgen dvi2txt caml-tex2 - -dvi2txt: - cd dvi_to_txt; ${MAKE} transf: transf.cmo htmltransf.cmo transfmain.cmo - $(OCAMLC) -o transf -g transf.cmo htmltransf.cmo transfmain.cmo - -transf.ml: transf.mll - $(OCAMLLEX) transf.mll - -htmltransf.ml: htmltransf.mll - $(OCAMLLEX) htmltransf.mll - -htmlgen: latexmacros.cmo latexscan.cmo latexmain.cmo - $(OCAMLC) -o htmlgen -g latexmacros.cmo latexscan.cmo latexmain.cmo + $(OCAMLC) -o $@ -g $^ -latexscan.ml: latexscan.mll - ocamllex latexscan.mll - -caml-tex2: caml_tex2.ml - $(OCAMLC) $(TOPDIR)/compilerlibs/ocamlcommon.cma -I $(TOPDIR)/parsing \ - -o caml-tex2 str.cma unix.cma caml_tex2.ml +transfmain.cmo: transf.cmo htmltransf.cmo -.SUFFIXES: -.SUFFIXES: .ml .cmo .mli .cmi .c +texquote2: texquote2.ml + $(OCAMLC) -o $@ $< -.ml.cmo: +%.cmo: %.ml $(OCAMLC) -c $< -.mli.cmi: +%.cmi: %.mli $(OCAMLC) -c $< -.c: - $(CC) $(CFLAGS) -o $@ $< +%.ml: %.mll + $(OCAMLLEX) $< + +.PHONY: clean clean: - rm -f transf.ml latexscan.ml htmltransf.ml - rm -f texquote2 transf htmlquote htmlgen dvi2txt - rm -f transf.ml latex.ml - rm -f *.o *.cm? *.cmxa - rm -f *~ #*# - cd dvi_to_txt; ${MAKE} clean - -latexmacros.cmo: latexmacros.cmi -latexmain.cmo: latexscan.cmo -latexscan.cmo: latexmacros.cmi -transfmain.cmo: transf.cmo htmltransf.cmo + rm -f *.o *.cm? *.cmx? + rm -f transf.ml htmltransf.ml + rm -f texquote2 transf diff --git a/manual/tools/caml-tex b/manual/tools/caml-tex deleted file mode 100755 index 7eea11b5..00000000 --- a/manual/tools/caml-tex +++ /dev/null @@ -1,131 +0,0 @@ -#!/usr/bin/perl - -$camllight = "TERM=dumb ocaml"; -$camlbegin = "\\caml\n"; -$camlend = "\\endcaml\n"; -$camlin = "\\?"; -$camlout = "\\:"; -$camlblank = "\\;\n"; - -$linelen = 72; -$output = ""; -$cut_at_blanks = 0; - -while ($#ARGV >= 0) { - $_ = $ARGV[0]; - last unless (/^-/); - $linelen = $ARGV[1], shift, shift, next if (/^-n$/); - $output = $ARGV[1], shift, shift, next if (/^-o$/); - $camllight = $ARGV[1], shift, shift, next if (/^-caml$/); - $cut_at_blanks = 1, shift, next if (/^-w$/); - printf STDERR ("Unknown option '%s', ignored\n", $_); - shift; -} - -# First pass: extract the Caml phrases to evaluate - -open(ML, "> .input.ml") || die("Cannot create .input.ml : $!"); - -foreach $infile (@ARGV) { - open(IN, $infile) || die("Cannot open $infile : $!"); - while() { - if (m/^\\begin{caml_(example|example\*|eval)}\s*$/) { - while() { - last if m/^\\end{caml_(example|example\*|eval)}\s*$/; - print ML $_; - } - } - } - close(IN); -} - -close(ML); - -# Feed the phrases to a Caml toplevel - -open(TOPLEVEL, "$camllight 2>&1 < .input.ml |") || - die("Cannot start camllight : $!"); - -; ; # skip the banner -$lastread = ; -$lastread =~ s/^# //; - -# Second pass: shuffle the TeX source and the output of the toplevel - -if ($output) { - if ($output eq "-") { - open(OUT, ">&STDOUT"); - } else { - open(OUT, ">$output") || die("Cannot create $output: $!"); - } -} - -foreach $infile (@ARGV) { - open(IN, $infile) || die("Cannot open $infile: $!"); - if (! $output) { - $outfile = $infile; - $outfile =~ s/\.tex$//; - open(OUT, "> $outfile.ml.tex") || die("Cannot create $outfile.ml.tex: $!"); - } - while() { - if (m/^\\begin{caml_example(\*?)}\s*$/) { - $omit_answer = $1; # true if caml_example*, false if caml_example - print OUT $camlbegin; - $severalphrases = 0; - while() { - last if m/\\end{caml_example\*?}\s*$/; - print OUT $camlblank if ($severalphrases); - while(1) { - s/\\/\\\\/g; - print OUT $camlin, $_; - last if m/;; *$/; - $_ = ; - } - while ($lastread =~ s/^ //) { } - while($lastread) { - last if $lastread =~ s/^# //; - print STDERR $lastread; - if (! $omit_answer) { - while (length($lastread) > $linelen) { - if ($cut_at_blanks) { - $cutpos = rindex($lastread, ' ', $linelen); - if ($cutpos == -1) { $cutpos = $linelen; } else { $cutpos++; } - } else { - $cutpos = $linelen; - } - $line = substr($lastread, 0, $cutpos); - $line =~ s/\\/\\\\/g; - print OUT $camlout, $line, "\n"; - $lastread = substr($lastread, $cutpos, - length($lastread) - $cutpos); - } - $lastread =~ s/\\/\\\\/g; - print OUT $camlout, $lastread; - } - $lastread = ; - } - $severalphrases = 1; - } - print OUT $camlend; - } - elsif (m/^\\begin{caml_eval}\s*$/) { - while() { - last if m/^\\end{caml_eval}\s*$/; - if (m/;; *$/) { - while ($lastread =~ s/^ //) { } - while($lastread) { - last if $lastread =~ s/^#//; - print STDERR $lastread; - $lastread = ; - } - } - } - } - else { - print OUT $_; - } - } - close(IN); -} - -close(TOPLEVEL); diff --git a/manual/tools/caml_tex2.ml b/manual/tools/caml_tex2.ml deleted file mode 100644 index d115b274..00000000 --- a/manual/tools/caml_tex2.ml +++ /dev/null @@ -1,605 +0,0 @@ -(* $Id$ *) - -open StdLabels -open Printf -open Str - -let camlbegin = "\\caml" -let camlend = "\\endcaml" -let camlin = {|\\?\1|} -let camlout = {|\\:\1|} -let camlbunderline = "\\<" -let camleunderline = "\\>" - -let start newline out s args = - Printf.fprintf out "%s%s" camlbegin s; - List.iter (Printf.fprintf out "{%s}") args; - if newline then Printf.fprintf out "\n" - -let stop newline out s = - Printf.fprintf out "%s%s" camlend s; - if newline then Printf.fprintf out "\n" - -let code_env ?(newline=true) env out s = - Printf.fprintf out "%a%s\n%a" - (fun ppf env -> start false ppf env []) env s (stop newline) env - -let main = "example" -type example_mode = Toplevel | Verbatim | Signature -let string_of_mode = function - | Toplevel -> "toplevel" - | Verbatim -> "verbatim" - | Signature -> "signature" - -let input_env = "input" -let ok_output ="output" -let error ="error" -let warning ="warn" -let phrase_env = "" - - -let camllight = ref "TERM=norepeat ocaml" -let verbose = ref true -let linelen = ref 72 -let outfile = ref "" -let cut_at_blanks = ref false -let files = ref [] - -let _ = - Arg.parse ["-n", Arg.Int (fun n -> linelen := n), "line length"; - "-o", Arg.String (fun s -> outfile := s), "output"; - "-caml", Arg.String (fun s -> camllight := s), "toplevel"; - "-w", Arg.Set cut_at_blanks, "cut at blanks"; - "-v", Arg.Bool (fun b -> verbose := b ), "output result on stderr" - ] - (fun s -> files := s :: !files) - "caml-tex2: " - -let (~!) = - let memo = ref [] in - fun key -> - try List.assq key !memo - with Not_found -> - let data = Str.regexp key in - memo := (key, data) :: !memo; - data - -(** The Output module deals with the analysis and classification - of the interpreter output and the parsing of status-related options - or annotations for the caml_example environment *) -module Output = struct - - (** Interpreter output status *) - type status = - | Ok - | Warning of int - | Error - - type kind = - | Annotation (** Local annotation: [ [@@expect (*annotation*) ] ]*) - | Option (** Global environment option: - [\begin{caml_example}[option[=value]] - ... - \end{caml_example}] *) - - (** Pretty printer for status *) - let pp_status ppf = function - | Error -> Printf.fprintf ppf "error" - | Ok -> Printf.fprintf ppf "ok" - | Warning n -> Printf.fprintf ppf "warning %d" n - - (** Pretty printer for status preceded with an undefined determinant *) - let pp_a_status ppf = function - | Error -> Printf.fprintf ppf "an error" - | Ok -> Printf.fprintf ppf "an ok" - | Warning n -> Printf.fprintf ppf "a warning %d" n - - (** {1 Related latex environment } *) - let env = function - | Error -> error - | Warning _ -> warning - | Ok -> ok_output - - (** {1 Exceptions } *) - exception Parsing_error of kind * string - - type source = { file:string; lines:int * int; phrase:string; output:string } - type unexpected_report = {source:source; expected:status; got:status} - exception Unexpected_status of unexpected_report - - let print_source ppf {file; lines = (start, stop); phrase; output} = - Printf.fprintf ppf "%s, lines %d to %d:\n\"\n%s\n\"\n\"\n%s\n\"." - file start stop phrase output - - let print_unexpected {source; expected; got} = - if expected = Ok then - Printf.eprintf - "Error when evaluating a caml_example environment in %a\n\ - Unexpected %a status.\n\ - If %a status was expected, add an [@@expect %a] annotation.\n" - print_source source - pp_status got - pp_a_status got - pp_status got - else - Printf.eprintf - "Error when evaluating a guarded caml_example environment in %a\n\ - Unexpected %a status, %a status was expected.\n\ - If %a status was in fact expected, change the status annotation to \ - [@@expect %a].\n" - print_source source - pp_status got - pp_a_status expected - pp_a_status got - pp_status got; - flush stderr - - let print_parsing_error k s = - match k with - | Option -> - Printf.eprintf - "Unknown caml_example option: [%s].\n\ - Supported options are \"ok\",\"error\", or \"warning=n\" (with n \ - a warning number).\n" s - | Annotation -> - Printf.eprintf - "Unknown caml_example phrase annotation: [@@expect %s].\n\ - Supported annotations are [@@expect ok], [@@expect error],\n\ - and [@@expect warning n] (with n a warning number).\n" s - - (** {1 Output analysis} *) - let catch_error s = - if string_match ~!{|Error:|} s 0 then Some Error else None - - let catch_warning s = - if string_match ~!{|Warning \([0-9]+\):|} s 0 then - Some (Warning (int_of_string @@ matched_group 1 s)) - else - None - - let status s = match catch_warning s, catch_error s with - | Some w, _ -> w - | None, Some e -> e - | None, None -> Ok - - (** {1 Parsing caml_example options } *) - - (** Parse [warning=n] options for caml_example options *) - let parse_warning s = - if string_match ~!{|warning=\([0-9]+\)|} s 0 then - Some (Warning (int_of_string @@ matched_group 1 s)) - else - None - - (** Parse [warning n] annotations *) - let parse_local_warning s = - if string_match ~!{|warning \([0-9]+\)|} s 0 then - Some (Warning (int_of_string @@ matched_group 1 s)) - else - None - - let parse_error s = - if s="error" then Some Error else None - - let parse_ok s = - if s = "ok" then Some Ok else None - - (** Parse the environment-wide expected status output *) - let expected s = - match parse_warning s, parse_error s with - | Some w, _ -> w - | None, Some e -> e - | None, None -> raise (Parsing_error (Option,s)) - - (** Parse the local (i.e. phrase-wide) expected status output *) - let local_expected s = - match parse_local_warning s, parse_error s, parse_ok s with - | Some w, _, _ -> w - | None, Some e, _ -> e - | None, None, Some ok -> ok - | None, None, None -> raise (Parsing_error (Annotation,s)) - -end - -module Text_transform = struct - - type kind = - | Underline - | Ellipsis - - exception Intersection of - {line:int; file:string; left:kind; stop:int; start:int; right:kind} - - let pp ppf = function - | Underline -> Format.fprintf ppf "underline" - | Ellipsis -> Format.fprintf ppf "ellipsis" - - type t = { kind:kind; start:int; stop:int} - let escape_specials s = - let s1 = global_replace ~!"\\\\" "\\\\\\\\" s in - let s2 = global_replace ~!"'" "\\\\textquotesingle\\\\-" s1 in - let s3 = global_replace ~!"`" "\\\\textasciigrave\\\\-" s2 in - s3 - - let rec apply_transform input (pos,underline_stop,out) t = - if pos >= String.length input then pos, underline_stop, out - else match underline_stop with - | Some stop when stop <= t.start -> - let f = escape_specials (String.sub input ~pos ~len:(stop - pos)) in - let out = {|\>|} :: f :: out in - apply_transform input (stop,None,out) t - | _ -> - let out = - escape_specials (String.sub input ~pos ~len:(t.start - pos))::out in - match t.kind with - | Ellipsis -> t.stop, underline_stop, {|\ldots|} :: out - | Underline -> - t.start, Some t.stop, {|\<|} :: out - - (** Check that all ellipsis are strictly nested inside underline transform - and that otherwise no transform starts before the end of the previous - transform in a list of transforms *) - type partition = U of t * t list | E of t - let check_partition line file l = - let init = Ellipsis, 0 in - let rec partition = function - | [] -> [] - | {kind=Underline; _ } as t :: q -> underline t [] q - | {kind=Ellipsis; _ } as t :: q -> E t :: partition q - and underline u n = function - | [] -> end_underline u n [] - | {kind=Underline; _ } :: _ as q -> end_underline u n q - | {kind=Ellipsis; _ } as t :: q -> - if t.stop < u.stop then underline u (t::n) q - else end_underline u n (t::q) - and end_underline u n l = U(u,List.rev n) :: partition l in - let check_elt (left,stop) t = - if t.start < stop then - raise (Intersection{line;file;left;stop;start=t.start;right=t.kind}) - else - (t.kind,t.stop) in - let check acc = function - | E t -> check_elt acc t - | U(u,n) -> - let _ = check_elt acc u in - let _ = List.fold_left ~f:check_elt ~init n in - u.kind, u.stop in - List.fold_left ~f:check ~init (partition l) - |> ignore - - let apply ts file line s = - let ts = List.sort (fun x y -> compare x.start y.start) ts in - check_partition line file ts; - let last, underline, ls = - List.fold_left ~f:(apply_transform s) ~init:(0,None,[]) ts in - let last, ls = match underline with - | None -> last, ls - | Some stop -> - let f = escape_specials (String.sub s ~pos:last ~len:(stop - last)) in - stop, {|\>|} :: f :: ls in - let ls = - let n = String.length s in - if last = n then ls else - escape_specials (String.sub s last (n-last)) :: ls in - String.concat "" (List.rev ls) -end - - -let caml_input, caml_output = - let cmd = !camllight ^ " 2>&1" in - try Unix.open_process cmd with _ -> failwith "Cannot start toplevel" -let () = - at_exit (fun () -> ignore (Unix.close_process (caml_input, caml_output))); - ignore (input_line caml_input); - ignore (input_line caml_input) - -let read_output () = - let input = ref (input_line caml_input) in - input := replace_first ~!{|^#\( *\*\)* *|} "" !input; - (* the inner ( *\* )* group is here to clean the starting "*" - introduced for multiline comments *) - let underline = - if string_match ~!"Characters *\\([0-9]+\\)-\\([0-9]+\\):$" !input 0 - then - let start = int_of_string (matched_group 1 !input) - and stop = int_of_string (matched_group 2 !input) in - input := input_line caml_input; - Text_transform.[{kind=Underline; start; stop}] - else [] - in - let output = Buffer.create 256 in - let first_line = ref true in - while not (string_match ~!".*\"end_of_input\"$" !input 0) do - if !verbose then prerr_endline !input; - if not !first_line then Buffer.add_char output '\n' else first_line:=false; - Buffer.add_string output !input; - input := input_line caml_input; - done; - Buffer.contents output, underline - -exception Missing_double_semicolon of string * int - -exception Missing_mode of string * int - -type incompatibility = - | Signature_with_visible_answer of string * int -exception Incompatible_options of incompatibility - -exception Phrase_parsing of string - -module Ellipsis = struct - (** This module implements the extraction of ellipsis locations - from phrases. - - An ellipsis is either an [[@ellipsis]] attribute, or a pair - of [[@@@ellipsis.start]...[@@@ellipsis.stop]] attributes. *) - - exception Unmatched_ellipsis of {kind:string; start:int; stop:int} - (** raised when an [[@@@ellipsis.start]] or [[@@@ellipsis.stop]] is - not paired with another ellipsis attribute *) - - exception Nested_ellipses of {first:int ; second:int } - (** raised by [[@@@ellipsis.start][@@@ellipsis.start]] *) - - let extract f x = - let transforms = ref [] in - let last_loc = ref Location.none in - let left_mark = ref None (* stored position of [@@@ellipsis.start]*) in - let location _this loc = - (* we rely on the fact that the default iterator call first - the location subiterator, then the attribute subiterator *) - last_loc := loc in - let attribute _this (attr,_) = - let name = attr.Location.txt in - let loc = !last_loc in - let start = loc.Location.loc_start.Lexing.pos_cnum in - let attr_start = attr.Location.loc.loc_start.Lexing.pos_cnum in - let attr_stop = 1 + attr.Location.loc.loc_end.Lexing.pos_cnum in - let stop = loc.Location.loc_end.Lexing.pos_cnum in - let check_nested () = match !left_mark with - | Some (first,_) -> raise (Nested_ellipses {first; second=attr_start}) - | None -> () in - match name with - | "ellipsis" -> - check_nested (); - transforms := - {Text_transform.kind=Ellipsis; start; stop=max attr_stop stop } - :: !transforms - | "ellipsis.start" -> - check_nested (); - left_mark := Some (start, stop) - | "ellipsis.stop" -> - begin match !left_mark with - | None -> raise (Unmatched_ellipsis {kind="right"; start; stop}) - | Some (start, _ ) -> - transforms := {kind=Ellipsis; start ; stop } :: !transforms; - left_mark := None - end - | _ -> () - in - f {Ast_iterator.default_iterator with location; attribute} x; - (match !left_mark with - | None -> () - | Some (start,stop) -> - raise (Unmatched_ellipsis {kind="left"; start; stop }) - ); - !transforms - - let find fname mode s = - let lex = Lexing.from_string s in - Location.init lex fname; - Location.input_name := fname; - Location.input_lexbuf := Some lex; - try - match mode with - | Toplevel -> begin - match Parse.toplevel_phrase lex with - | Ptop_dir _ -> [] - | Ptop_def str -> extract (fun it -> it.structure it) str - end - | Verbatim -> - extract (fun it -> it.structure it) (Parse.implementation lex) - | Signature -> - extract (fun it -> it.signature it) (Parse.interface lex) - with Syntaxerr.Error _ -> raise (Phrase_parsing s) - -end - -let process_file file = - prerr_endline ("Processing " ^ file); - let ic = try open_in file with _ -> failwith "Cannot read input file" in - let phrase_start = ref 1 and phrase_stop = ref 1 in - let incr_phrase_start () = - incr phrase_start; - phrase_stop := !phrase_start in - let oc = - try if !outfile = "-" then - stdout - else if !outfile = "" then - open_out (replace_first ~!"\\.tex$" "" file ^ ".ml.tex") - else - open_out_gen [Open_wronly; Open_creat; Open_append; Open_text] - 0x666 !outfile - with _ -> failwith "Cannot open output file" in - let fatal fmt = - Format.kfprintf - (fun ppf -> Format.fprintf ppf "@]@."; close_in ic; close_out oc; exit 1) - Format.err_formatter ("@[ Error " ^^ fmt) in - let re_spaces = "[ \t]*" in - let re_start = ~!( - {|\\begin{caml_example\(\*?\)}|} ^ re_spaces - ^ {|\({toplevel}\|{verbatim}\|{signature}\)?|} ^ re_spaces - ^ {|\(\[\(.*\)\]\)?|} ^ re_spaces - ^ "$" - ) in - try while true do - let input = ref (input_line ic) in - incr_phrase_start(); - if string_match re_start !input 0 - then begin - let omit_answer = matched_group 1 !input = "*" in - let mode = - match matched_group 2 !input with - | exception Not_found -> raise (Missing_mode(file, !phrase_stop)) - | "{toplevel}" -> Toplevel - | "{verbatim}" -> Verbatim - | "{signature}" -> Signature - | _ -> assert false in - if mode = Signature && not omit_answer then raise - (Incompatible_options( - Signature_with_visible_answer(file,!phrase_stop)) - ); - let explicit_stop = match mode with - | Verbatim | Signature -> false - | Toplevel -> true in - let global_expected = try Output.expected @@ matched_group 4 !input - with Not_found -> Output.Ok in - start true oc main [string_of_mode mode]; - let first = ref true in - let read_phrase () = - let phrase = Buffer.create 256 in - let rec read () = - let input = incr phrase_stop; input_line ic in - let implicit_stop = - if string_match ~!"\\\\end{caml_example\\*?}[ \t]*$" - input 0 - then - begin - if !phrase_stop = 1 + !phrase_start then - raise End_of_file - else if explicit_stop then - raise @@ Missing_double_semicolon (file,!phrase_stop) - else - true - end - else false in - if Buffer.length phrase > 0 then Buffer.add_char phrase '\n'; - let stop = - implicit_stop || - ( not (mode = Signature) - && string_match ~!"\\(.*\\)[ \t]*;;[ \t]*$" input 0 ) - in - if not stop then ( - Buffer.add_string phrase input; read () - ) - else begin - decr phrase_stop; - let last_input = if implicit_stop then "" else matched_group 1 input in - let expected = - if string_match ~!{|\(.*\)\[@@expect \(.*\)\]|} last_input 0 then - ( Buffer.add_string phrase (matched_group 1 last_input); - Output.local_expected @@ matched_group 2 last_input ) - else - (Buffer.add_string phrase last_input; global_expected) - in - if not implicit_stop then Buffer.add_string phrase ";;"; - implicit_stop, Buffer.contents phrase, expected - end in - read () - in - try while true do - let implicit_stop, phrase, expected = read_phrase () in - let ellipses = Ellipsis.find file mode phrase in - if mode = Signature then fprintf caml_output "module type Wrap = sig\n"; - fprintf caml_output "%s%s%s" phrase - (if mode = Signature then "\nend" else "") - (if implicit_stop then ";;\n" else "\n"); - flush caml_output; - output_string caml_output "\"end_of_input\";;\n"; - flush caml_output; - let output, underline = read_output () in - let status = Output.status output in - if status <> expected then ( - let source = Output.{ - file; - lines = (!phrase_start, !phrase_stop); - phrase; - output - } in - raise (Output.Unexpected_status - {Output.got=status; expected; source} ) ) - else ( incr phrase_stop; phrase_start := !phrase_stop ); - let phrase = - Text_transform.apply (underline @ ellipses) - file !phrase_stop phrase in - (* Special characters may also appear in output strings -Didier *) - let output = Text_transform.escape_specials output in - let phrase = global_replace ~!{|^\(.\)|} camlin phrase - and output = global_replace ~!{|^\(.\)|} camlout output in - start false oc phrase_env []; - code_env ~newline:omit_answer input_env oc phrase; - if not omit_answer then - code_env ~newline:false (Output.env status) oc output; - stop true oc phrase_env; - flush oc; - first := false; - if implicit_stop then raise End_of_file - done - with End_of_file -> phrase_start:= !phrase_stop; stop true oc main - end - else if string_match ~!"\\\\begin{caml_eval}[ \t]*$" !input 0 - then begin - while input := input_line ic; - not (string_match ~!"\\\\end{caml_eval}[ \t]*$" !input 0) - do - fprintf caml_output "%s\n" !input; - if string_match ~!".*;;[ \t]*$" !input 0 then begin - flush caml_output; - output_string caml_output "\"end_of_input\";;\n"; - flush caml_output; - ignore (read_output ()) - end - done - end else begin - fprintf oc "%s\n" !input; - flush oc - end - done with - | End_of_file -> close_in ic; close_out oc - | Output.Unexpected_status r -> - ( Output.print_unexpected r; close_in ic; close_out oc; exit 1 ) - | Output.Parsing_error (k,s) -> - ( Output.print_parsing_error k s; - close_in ic; close_out oc; exit 1 ) - | Phrase_parsing s -> fatal "when parsing the following phrase:@ %s" s - | Missing_double_semicolon (file, line_number) -> - fatal - "when evaluating a caml_example environment in %s:@;\ - missing \";;\" at line %d@]@." file (line_number-2) - | Missing_mode (file, line_number) -> - fatal "when parsing a caml_example environment in %s:@;\ - missing mode argument at line %d,@ \ - available modes {toplevel,verbatim}@]@." - file (line_number-2) - | Incompatible_options Signature_with_visible_answer (file, line_number) -> - fatal - "when parsing a caml_example environment in@ \ - %s, line %d:@,\ - the signature mode is only compatible with \"caml_example*\"@ \ - Hint: did you forget to add \"*\"?@]@." - file (line_number-2); - | Text_transform.Intersection {line;file;left;stop;start;right} -> - fatal - "when evaluating a caml_example environment in %s, line %d:@ \ - Textual transforms must be well-separated.@ The \"%a\" transform \ - ended at %d,@ after the start at %d of another \"%a\" transform.@ \ - Hind: did you try to elide a code fragment which raised a warning?\ - @]@." - file (line-2) - Text_transform.pp left stop start Text_transform.pp right - | Ellipsis.Unmatched_ellipsis {kind;start;stop} -> - fatal "when evaluating a caml_example environment,@ \ - the %s mark at position %d-%d was unmatched" - kind start stop - | Ellipsis.Nested_ellipses {first;second} -> - fatal "when evaluating a caml_example environment,@ \ - there were two nested ellipsis attribute.@ The first one \ - started at position %d,@ the second one at %d" - first second - -let _ = - if !outfile <> "-" && !outfile <> "" then begin - try close_out (open_out !outfile) - with _ -> failwith "Cannot open output file" - end; - List.iter process_file (List.rev !files) diff --git a/manual/tools/dvi_to_txt/Makefile b/manual/tools/dvi_to_txt/Makefile deleted file mode 100644 index 852996a9..00000000 --- a/manual/tools/dvi_to_txt/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -OBJS=io.o interp.o output.o main.o print.o print_rtf.o print_styl.o -CFLAGS=-g - -../dvi2txt: $(OBJS) - $(CC) $(CFLAGS) -o ../dvi2txt $(OBJS) - -clean: - rm -f ../dvi2txt *.o *~ #*# diff --git a/manual/tools/dvi_to_txt/dvi.h b/manual/tools/dvi_to_txt/dvi.h deleted file mode 100644 index 8dfb25dc..00000000 --- a/manual/tools/dvi_to_txt/dvi.h +++ /dev/null @@ -1,8 +0,0 @@ -enum { - SET_CHAR_0=0, SET_CHAR_127=127, SET1=128, SET2, SET3, SET4, SET_RULE, - PUT1, PUT2, PUT3, PUT4, PUT_RULE, NOP, BOP, EOP, PUSH, POP, RIGHT1, - RIGHT2, RIGHT3, RIGHT4, W0, W1, W2, W3, W4, X0, X1, X2, X3, X4, DOWN1, - DOWN2, DOWN3, DOWN4, Y0, Y1, Y2, Y3, Y4, Z0, Z1, Z2, Z3, Z4, - FNT_NUM_0=171, FNT_NUM_63=234, FNT1=235, FNT2, FNT3, FNT4, XXX1, XXX2, - XXX3, XXX4, FNT_DEF1, FNT_DEF2, FNT_DEF3, FNT_DEF4, PRE, POST, POST_POST -}; diff --git a/manual/tools/dvi_to_txt/interp.c b/manual/tools/dvi_to_txt/interp.c deleted file mode 100644 index e50aed36..00000000 --- a/manual/tools/dvi_to_txt/interp.c +++ /dev/null @@ -1,305 +0,0 @@ -#include -#include -#include -#include -#include "io.h" -#include "dvi.h" -#include "output.h" - -#define SEEK_CUR 1 - -int h, v, w, x, y, z, sp; -int currfont; -int encoding; -int style; - -#define FONT_NAME_SIZE 31 -#define NUM_FONTS 256 - -struct { - char name[FONT_NAME_SIZE+1]; - int encoding; - int style; -} font[NUM_FONTS]; - -#define TYPEWRITER 0 -#define ROMAN 1 -#define MATH_ITALIC 2 -#define MATH_SYMBOL 3 -#define MATH_EXTENSION 4 -#define LINE_SEGMENTS 5 -#define CIRCLE_SEGMENTS 6 -#define LATEX_SYMBOLS 7 - -char * transcode[] = { -/* 0.......+.......1.......+.......2.......+.......3.......+.......4.......+.......5.......+.......6.......+.......7.......+....... */ -/* TYPEWRITER */ - "GDTLXPSUPYO##################### !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~#", -/* ROMAN */ - "GDTLXPSUPYO***** 0'!\"#$%&'()*+,-./0123456789:;!=??@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\"]^.`abcdefghijklmnopqrstuvwxyz--\"~#", -/* MATH_ITALIC */ - "GDTLXPSUPYOabgdezhtiklmnxpystupxyoeuorsp----`'><0123456789.,*dABCDEFGHIJKLMNOPQRSTUVWXYZ#####labcdefghijklmnopqrstuvwxyzij###", -/* MATH_SYMBOL */ - "-.x*/###+-x/.ooo==##<><>==##<><><>||####<>||####'#####/|###0RIT##ABCDEFGHIJKLMNOPQRSTUVWXYZ###########{}<>||||\\|################", -/* MATH_EXTENSION */ - "()[]||||{}<>||##()[]||||{}<>||##()[]||||{}<>||##########################################################[]||||{}################", -/* LINE_SEGMENTS */ - "/||||| _ / / _/ // _ / / __// / _ / \\||||| \\ \\ \\ _\\ \\\\ _ \\ \\ __\\\\ \\ _ \\ ", -/* CIRCLE_SEGMENTS */ - " ", -/* LATEX_SYMBOLS */ - " <<>> U#O0 ~~[] " -}; - -#define STACK_SIZE 100 - -struct { int sh, sv, sw, sx, sy, sz; } stack[STACK_SIZE]; - -struct known_font_struct { - char * prefix; - int encoding, style; -} known_fonts[] = { - "docrm", ROMAN, PLAIN, - "doctt", TYPEWRITER, MONOSPACED, - "docit", ROMAN, ITALICS, - "docbf", ROMAN, BOLD, - "docmi", MATH_ITALIC, PLAIN, - "cmsy", MATH_SYMBOL, PLAIN, - "cmex", MATH_EXTENSION, PLAIN, - "line", LINE_SEGMENTS, PLAIN, - "lcircle", CIRCLE_SEGMENTS, PLAIN, - "lasy", LATEX_SYMBOLS, PLAIN -}; - -void fontdef(input, fontnum) - FILE * input; - int fontnum; -{ - int a, l, i; - - assert(fontnum >= 0 && fontnum < NUM_FONTS); - fseek(input, 12, SEEK_CUR); /* skip c, s and d parameters */ - a = get8u(input); - l = get8u(input); - assert(l < FONT_NAME_SIZE); - fseek(input, a, SEEK_CUR); /* skip the "area" part */ - fread(font[fontnum].name, 1, l, input); /* read the font name */ - font[fontnum].name[l] = 0; - for (i = 0; - i < sizeof(known_fonts) / sizeof(struct known_font_struct); - i++) { - if (strncmp(font[fontnum].name, known_fonts[i].prefix, - strlen(known_fonts[i].prefix)) == 0) { - font[fontnum].encoding = known_fonts[i].encoding; - font[fontnum].style = known_fonts[i].style; - return; - } - } - fprintf(stderr, "Warning: unknown font `%s'\n", font[fontnum].name); - font[fontnum].encoding = ROMAN; - font[fontnum].style = PLAIN; -} - -void setfont(fontnum) - int fontnum; -{ - currfont = fontnum; - encoding = font[fontnum].encoding; - style = font[fontnum].style; -} - -int outchar(c) - int c; -{ - if (c < 0 || c > 127) - out(h, v, '#', PLAIN); - else - out(h, v, transcode[encoding][c], style); - return scalex; -} - -void outrule(height, width) - int height, width; -{ - char c; - int dx, dy; - - if (height <= 0 || width <= 0) return; - c = height >= width ? '|' : '-'; - dy = 0; - do { - dx = 0; - do { - out(h + dx, v - dy, c, PLAIN); - dx += scalex; - } while (dx <= width); - dy += scaley; - } while (dy < height); -} - -void interprete(input) - FILE * input; -{ - int c, n, height, width, mag; - - sp = 0; - c = get8u(input); - n = get8u(input); - if (c != PRE || n != 2) { - fprintf(stderr, "File does not start with DVI preamble.\n"); - exit(2); - } - (void) get32s(input); - (void) get32s(input); - mag = get32s(input); - scalex = SCALEX * mag / 1000; - scaley = SCALEY * mag / 1000; - n = get8u(input); - fseek(input, n, SEEK_CUR); /* skip comment */ - - begin_document(); - - while (1) { - c = get8u(input); - if (c >= SET_CHAR_0 && c <= SET_CHAR_127) - h += outchar(c); - else if (c >= FNT_NUM_0 && c <= FNT_NUM_63) - setfont(c - FNT_NUM_0); - else switch(c) { - case SET1: - h += outchar(get8u(input)); break; - case SET2: - h += outchar(get16u(input)); break; - case SET3: - h += outchar(get24u(input)); break; - case SET4: - h += outchar(get32s(input)); break; - case SET_RULE: - height = get32s(input); - width = get32s(input); - outrule(height, width); - h += width; - break; - case PUT1: - (void) outchar(get8u(input)); break; - case PUT2: - (void) outchar(get16u(input)); break; - case PUT3: - (void) outchar(get24u(input)); break; - case PUT4: - (void) outchar(get32s(input)); break; - case PUT_RULE: - height = get32s(input); - width = get32s(input); - outrule(height, width); - break; - case NOP: - break; - case BOP: - clear_page(); - h = v = w = x = y = z = 0; - sp = 0; - fseek(input, 44, SEEK_CUR); /* skip c0...c9 and ptr to previous page */ - break; - case EOP: - output_page(); - break; - case PUSH: - assert(sp < STACK_SIZE); - stack[sp].sh = h; stack[sp].sv = v; stack[sp].sw = w; - stack[sp].sx = x; stack[sp].sy = y; stack[sp].sz = z; - sp++; - break; - case POP: - assert(sp > 0); - sp--; - h = stack[sp].sh; v = stack[sp].sv; w = stack[sp].sw; - x = stack[sp].sx; y = stack[sp].sy; z = stack[sp].sz; - break; - case RIGHT1: - h += get8s(input); break; - case RIGHT2: - h += get16s(input); break; - case RIGHT3: - h += get24s(input); break; - case RIGHT4: - h += get32s(input); break; - case W0: - h += w; break; - case W1: - w = get8s(input); h += w; break; - case W2: - w = get16s(input); h += w; break; - case W3: - w = get24s(input); h += w; break; - case W4: - w = get32s(input); h += w; break; - case X0: - h += x; break; - case X1: - x = get8s(input); h += x; break; - case X2: - x = get16s(input); h += x; break; - case X3: - x = get24s(input); h += x; break; - case X4: - x = get32s(input); h += x; break; - case DOWN1: - v += get8s(input); break; - case DOWN2: - v += get16s(input); break; - case DOWN3: - v += get24s(input); break; - case DOWN4: - v += get32s(input); break; - case Y0: - v += y; break; - case Y1: - y = get8s(input); v += y; break; - case Y2: - y = get16s(input); v += y; break; - case Y3: - y = get24s(input); v += y; break; - case Y4: - y = get32s(input); v += y; break; - case Z0: - v += z; break; - case Z1: - z = get8s(input); v += z; break; - case Z2: - z = get16s(input); v += z; break; - case Z3: - z = get24s(input); v += z; break; - case Z4: - z = get32s(input); v += z; break; - case FNT1: - setfont(get8u(input)); break; - case FNT2: - setfont(get16u(input)); break; - case FNT3: - setfont(get24u(input)); break; - case FNT4: - setfont(get32s(input)); break; - case XXX1: - n = get8u(input); fseek(input, n, SEEK_CUR); break; - case XXX2: - n = get16u(input); fseek(input, n, SEEK_CUR); break; - case XXX3: - n = get24u(input); fseek(input, n, SEEK_CUR); break; - case XXX4: - n = get32s(input); fseek(input, n, SEEK_CUR); break; - case FNT_DEF1: - fontdef(input, get8u(input)); break; - case FNT_DEF2: - fontdef(input, get16u(input)); break; - case FNT_DEF3: - fontdef(input, get24u(input)); break; - case FNT_DEF4: - fontdef(input, get32s(input)); break; - case POST: - end_document(); return; - default: - assert(0); - } - } -} diff --git a/manual/tools/dvi_to_txt/io.c b/manual/tools/dvi_to_txt/io.c deleted file mode 100644 index 5dfe1ccc..00000000 --- a/manual/tools/dvi_to_txt/io.c +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include "io.h" - -int get16u(input) - FILE * input; -{ - int b1 = getc(input); - int b2 = getc(input); - return (b1 << 8) + b2; -} -int get16s(input) - FILE * input; -{ - int b1 = (schar) getc(input); - int b2 = getc(input); - return (b1 << 8) + b2; -} -int get24u(input) - FILE * input; -{ - int b1 = getc(input); - int b2 = getc(input); - int b3 = getc(input); - return (b1 << 16) + (b2 << 8) + b3; -} -int get24s(input) - FILE * input; -{ - int b1 = (schar) getc(input); - int b2 = getc(input); - int b3 = getc(input); - return (b1 << 16) + (b2 << 8) + b3; -} -int get32s(input) - FILE * input; -{ - int b1 = (schar) getc(input); - int b2 = getc(input); - int b3 = getc(input); - int b4 = getc(input); - return (b1 << 24) + (b2 << 16) + (b3 << 8) + b4; -} - diff --git a/manual/tools/dvi_to_txt/io.h b/manual/tools/dvi_to_txt/io.h deleted file mode 100644 index f9a800d4..00000000 --- a/manual/tools/dvi_to_txt/io.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifdef __STDC__ -typedef signed char schar; -#else -typedef char schar; -#endif - -#define get8u(input) getc(input) -#define get8s(input) (schar) getc(input) - -int get16u(), get16s(), get24u(), get24s(), get32u(), get32s(); diff --git a/manual/tools/dvi_to_txt/main.c b/manual/tools/dvi_to_txt/main.c deleted file mode 100644 index 0fb03c43..00000000 --- a/manual/tools/dvi_to_txt/main.c +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include "output.h" - -void interprete(FILE *input); - -char * input_name; - -int main(argc, argv) - int argc; - char ** argv; -{ - FILE * f; - int i; - - output_device = OUTPUT_PLAIN; - standout_tt = 0; - for (i = 1; i < argc && argv[i][0] == '-'; i++) { - switch(argv[i][1]) { - case 'p': - output_device = OUTPUT_PRINTER; break; - case 'r': - output_device = OUTPUT_RTF; break; - case 's': - output_device = OUTPUT_STYL; break; - case 't': - standout_tt = 1; break; - default: - fprintf(stderr, "Unknown option `%s', ignored\n", argv[i]); - } - } - if (i >= argc) { - input_name = "unknown.dvi"; - interprete(stdin); - } else { - for (/*nothing*/; i < argc; i++) { - f = fopen(argv[i], "r"); - if (f == NULL) { - perror(argv[i]); - continue; - } - input_name = argv[i]; - interprete(f); - fclose(f); - } - } - return 0; -} diff --git a/manual/tools/dvi_to_txt/output.c b/manual/tools/dvi_to_txt/output.c deleted file mode 100644 index fc79ed80..00000000 --- a/manual/tools/dvi_to_txt/output.c +++ /dev/null @@ -1,209 +0,0 @@ -#include -#include -#include -#include "output.h" - -void null(), print_FF(), plain_line(), printer_line(); -void begin_rtf_document(), end_rtf_document(), end_rtf_page(), rtf_line(); -void begin_styl_page(), end_styl_page(), styl_line(); - -struct output_device { - void (*begin_document)(); - void (*end_document)(); - void (*begin_page)(); - void (*end_page)(); - void (*line)(); -} device[] = { - null, null, null, print_FF, plain_line, - null, null, null, print_FF, printer_line, - begin_rtf_document, end_rtf_document, null, end_rtf_page, rtf_line, - null, null, begin_styl_page, end_styl_page, styl_line -}; - -#define SIZEX 160 - -struct line { - int ypos; - int len; - char * contents; - char * styles; - struct line * next_in_bucket; -}; - -#define NBUCKETS 101 - -struct line * screenlines[NBUCKETS]; - -int numlines; - -char * xmalloc(size) - int size; -{ - char * res = (char *) malloc(size); - if (res == NULL) { - fprintf(stderr, "Out of memory\n"); - exit(2); - } - return res; -} - -char * xrealloc(ptr, size) - char * ptr; - int size; -{ - char * res = (char *) realloc(ptr, size); - if (res == NULL) { - fprintf(stderr, "Out of memory\n"); - exit(2); - } - return res; -} - -void begin_document() -{ - device[output_device].begin_document(); -} - -void end_document() -{ - device[output_device].end_document(); -} - -void clear_page() -{ - int i; - - for (i = 0; i < NBUCKETS; i++) screenlines[i] = NULL; - numlines = 0; -} - -void out(x, y, c, style) - int x, y; - char c; - char style; -{ - unsigned int h; - struct line * line; - - h = ((unsigned int) y) % NBUCKETS; - line = screenlines[h]; - while (line != NULL && line->ypos != y) line = line->next_in_bucket; - if (line == NULL) { - line = (struct line *) xmalloc(sizeof(struct line)); - line->ypos = y; - line->len = 80; - line->contents = (char *) xmalloc(line->len); - memset(line->contents, ' ', line->len); - line->styles = (char *) xmalloc(line->len); - memset(line->styles, PLAIN, line->len); - line->next_in_bucket = screenlines[h]; - screenlines[h] = line; - numlines++; - } - x = x / scalex; - if (x < 0) return; - while (x >= line->len) { - int newlen = 2 * line->len; - line->contents = (char *) xrealloc(line->contents, newlen); - memset(line->contents + line->len, ' ', newlen - line->len); - line->styles = (char *) xrealloc(line->styles, newlen); - memset(line->styles + line->len, PLAIN, newlen - line->len); - line->len = newlen; - } - line->contents[x] = c; - line->styles[x] = style; -} - -static void free_bucket(l) - struct line * l; -{ - if (l != NULL) { - free(l->contents); - free(l->styles); - free_bucket(l->next_in_bucket); - free(l); - } -} - -static void free_buckets() -{ - int i; - for (i = 0; i < NBUCKETS; i++) free_bucket(screenlines[i]); -} - -static int compare_lines(l1, l2) - struct line ** l1, ** l2; -{ - return (**l1).ypos - (**l2).ypos; -} - -void output_page() -{ - struct line ** lines; - struct line * l; - int i, j, k, y; - char * p, * q, * style_p, * style_q, * s; - - device[output_device].begin_page(); - - /* First, sort the lines by y coordinate */ - lines = (struct line **) malloc(numlines * sizeof(struct line *)); - if (lines == NULL) { - printf("*** Out of memory ***\n\014"); - free_buckets(); - return; - } - j = 0; - for (i = 0; i < NBUCKETS; i++) - for (l = screenlines[i]; l != NULL; l = l->next_in_bucket) - lines[j++] = l; - qsort(lines, numlines, sizeof(struct line *), compare_lines); - - /* Output the lines */ - - y = 0; - for (i = 0; i < numlines; i++) { - /* Emit blank lines to reach the current line ypos */ - while (lines[i]->ypos - y >= 3 * scaley / 2) { - device[output_device].line(NULL, NULL, 0); - y += scaley; - } - /* If next line is close to current line, attempt to merge them */ - while (i + 1 < numlines && - lines[i+1]->ypos - lines[i]->ypos < scaley) { - p = lines[i]->contents; - q = lines[i+1]->contents; - style_p = lines[i]->styles; - style_q = lines[i+1]->styles; - for (j = lines[i]->len; j < lines[i+1]->len; j++) - if (q[j] != ' ') goto cannot_merge; - for (j = lines[i+1]->len; j < lines[i]->len; j++) - if (p[j] != ' ') goto cannot_merge; - k = lines[i]->len; - if (k > lines[i+1]->len) k = lines[i+1]->len; - for (j = 0; j < k; j++) - if (p[j] != ' ' && q[j] != ' ') goto cannot_merge; - /* Seems OK, do the merging */ - for (j = 0; j < k; j++) - if (p[j] != ' ') { - q[j] = p[j]; - style_q[j] = style_p[j]; - } - /* Now consider next line */ - i++; - } - cannot_merge: - /* Now print the current line */ - p = lines[i]->contents; - q = p + lines[i]->len; - while (q >= p && *--q == ' ') /*nothing*/; - device[output_device].line(p, lines[i]->styles, q-p+1); - /* Go on with next line */ - y = lines[i]->ypos; - } - - device[output_device].end_page(); - free(lines); - free_buckets(); -} - diff --git a/manual/tools/dvi_to_txt/output.h b/manual/tools/dvi_to_txt/output.h deleted file mode 100644 index 43ce317b..00000000 --- a/manual/tools/dvi_to_txt/output.h +++ /dev/null @@ -1,24 +0,0 @@ -#define SCALEX 404685 -#define SCALEY 786432 - -int scalex; -int scaley; - -#define PLAIN 0 -#define ITALICS 1 -#define BOLD 2 -#define MONOSPACED 3 - -void begin_document(); -void end_document(); -void clear_page(); -void output_page(); -void out(); - -int output_device; -int standout_tt; - -#define OUTPUT_PLAIN 0 -#define OUTPUT_PRINTER 1 -#define OUTPUT_RTF 2 -#define OUTPUT_STYL 3 diff --git a/manual/tools/dvi_to_txt/print.c b/manual/tools/dvi_to_txt/print.c deleted file mode 100644 index d0f02cc3..00000000 --- a/manual/tools/dvi_to_txt/print.c +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include "output.h" - -/* Low-level output functions */ - -void null() -{ -} - -void print_FF() -{ - putchar('\014'); -} - -void plain_line(txt, style, len) - char * txt, * style; - int len; -{ - fwrite(txt, 1, len, stdout); - putchar('\n'); -} - -void printer_line(txt, style, len) - char * txt, * style; - int len; -{ - for (/*nothing*/; len > 0; len--, txt++, style++) { - putchar(*txt); - switch(*style) { - case ITALICS: - putchar('\b'); putchar('_'); break; - case BOLD: - putchar('\b'); putchar(*txt); break; - case MONOSPACED: - if (standout_tt) { putchar('\b'); putchar(*txt); } - break; - } - } - putchar('\n'); -} - diff --git a/manual/tools/dvi_to_txt/print_rtf.c b/manual/tools/dvi_to_txt/print_rtf.c deleted file mode 100644 index c12c67a3..00000000 --- a/manual/tools/dvi_to_txt/print_rtf.c +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include "output.h" - -/* Rich Text Format */ - -void begin_rtf_document() -{ - printf("{\\rtf1\\ansi\\deff0\n"); - printf("{\\fonttbl{\\f0\\fmodern Courier;}}\n"); - printf("\\f0\\fs20\n"); -} - -void end_rtf_document() -{ - printf("}\n"); -} - -void end_rtf_page() -{ - printf("\\page\n"); -} - -void rtf_line(txt, style, len) - char * txt, * style; - int len; -{ - int currstyle; - - for (currstyle = PLAIN; len > 0; len--, txt++, style++) { - if (*txt != ' ') { - switch(*style) { - case PLAIN: - if (currstyle != PLAIN) { - putchar('}'); - currstyle = PLAIN; - } - break; - case ITALICS: - if (currstyle != ITALICS) { - if (currstyle != PLAIN) putchar('}'); - printf("{\\i "); - currstyle = ITALICS; - } - break; - case BOLD: - if (currstyle != BOLD) { - if (currstyle != PLAIN) putchar('}'); - printf("{\\b "); - currstyle = BOLD; - } - break; - case MONOSPACED: - if (standout_tt) { - if (currstyle != BOLD) { - if (currstyle != PLAIN) putchar('}'); - printf("{\\b "); - currstyle = BOLD; - } - } else { - if (currstyle != PLAIN) { - putchar('}'); - currstyle = PLAIN; - } - } - break; - } - } - switch(*txt) { - case '\\': - case '{': - case '}': - putchar('\\'); putchar(*txt); break; - default: - putchar(*txt); break; - } - } - if (currstyle != PLAIN) putchar('}'); - printf("\\par\n"); -} - diff --git a/manual/tools/dvi_to_txt/print_styl.c b/manual/tools/dvi_to_txt/print_styl.c deleted file mode 100644 index 39135f23..00000000 --- a/manual/tools/dvi_to_txt/print_styl.c +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include -#include -#include "output.h" - -/* Macintosh STYL tables */ - -extern char * input_name; - -static FILE * text; -static FILE * styl; -static int partnum = 0; -static int currstyle; -static int currstart; -static int currpos; - -static void output_current_style() -{ - int style_code; - - switch(currstyle) { - case PLAIN: - style_code = 0; break; - case ITALICS: - style_code = 2; break; - case BOLD: - style_code = 1 + 32; break; /* bold condensed */ - case MONOSPACED: - style_code = standout_tt ? 1 + 32 : 0; break; - } - fprintf(styl, "%d %d Monaco %d 9 0 0 0\n", currstart, currpos, style_code); -} - - -static void output_style_change(newstyle) - int newstyle; -{ - if (!standout_tt && (newstyle == PLAIN && currstyle == MONOSPACED || - newstyle == MONOSPACED && currstyle == PLAIN)) { - currstyle = newstyle; - return; - } - output_current_style(); - currstyle = newstyle; - currstart = currpos; -} - -void begin_styl_page() -{ - char name[1024], buffer[1024]; - int n; - - strcpy(name, input_name); - n = strlen(name); - if (n >= 4 && strcmp(name + n - 4, ".dvi") == 0) name[n - 4] = 0; - partnum++; - sprintf(buffer, "%s.%03d.txt", name, partnum); - text = fopen(buffer, "w"); - if (text == NULL) { perror(buffer); exit(2); } - sprintf(buffer, "%s.%03d.stl", name, partnum); - styl = fopen(buffer, "w"); - if (styl == NULL) { perror(buffer); exit(2); } - currstyle = PLAIN; - currstart = 0; - currpos = 0; -} - -void end_styl_page() -{ - output_current_style(); - fclose(text); - fclose(styl); -} - -void styl_line(txt, style, len) - char * txt, * style; - int len; -{ - for (/*nothing*/; len > 0; len--, txt++, style++, currpos++) { - putc(*txt, text); - if (*txt != ' ' && *style != currstyle) { - output_style_change(*style); - } - } - putc('\n', text); - currpos++; -} - - - diff --git a/manual/tools/fix_index.sh b/manual/tools/fix_index.sh index d2402b40..1deea537 100755 --- a/manual/tools/fix_index.sh +++ b/manual/tools/fix_index.sh @@ -39,14 +39,13 @@ case $# in *) usage;; esac -ed "$1" <<'EOF' -/-pipe-pipe/s/verb`("|hyperindexformat{\\"}/verb`("|"|)`|hyperpage/ -/-pipe-gt/s/verb`("|hyperindexformat{\\>)`}/verb`("|>)`|hyperpage/ -w -q -EOF +sed < "$1" > "$1.new" \ + -e 's/verb`("|hyperindexformat{\\"}/verb`("|"|)`|hyperpage/' \ + -e 's/verb`("|hyperindexformat{\\>)`}/verb`("|>)`|hyperpage/' case $? in 0) echo "fix_index.sh: fixed $1 successfully.";; - *) echo "fix_index.sh: some error occurred."; exit 0;; + *) echo "fix_index.sh: some error occurred."; exit 1;; esac + +mv "$1.new" "$1" diff --git a/manual/tools/format-intf b/manual/tools/format-intf deleted file mode 100755 index 0228ecc1..00000000 --- a/manual/tools/format-intf +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/perl - -$sep = "\246"; - -$html = 0; -if ($ARGV[0] eq "-html") { - $html = 1; - shift; -} - -# Skip initial junk - -while(($_ = <>) && ! m/^\(\* Module \[(.*)\]:/) { } -m/^\(\* Module \[(.*)\]:/; -$modname = $1; -chop; -s/^\(\* *//; -s/ *\*\) *$//; -s/\[/{\\tt /g; -s/\]/}/g; -print "\\section{$_}\n\n"; -$label = $modname; $label =~ s/[^A-Za-z0-9]//g; -print "\\label{s:$label}\n"; -print "\\index{$modname (module)@\\verb~$modname~ (module)}%\n\n"; -s/{\\tt //g; -s/}//g; -s/_//g; -print "\\pdfsection{$_}\n\n"; - -$incomment = 0; -$inverbatim = 0; - -line: -while(<>) { - chop; - last line if /^\s*\(\*--/; - if (s/^\(\*- //) { - s/ *\*\)$//; - } - if (m/^\s*\(\*\*\*\s*(.*)\*\)\s*$/) { - if ($inverbatim) { - do end_verbatim(); - } - print "\\subsection*{", $1, "}\n"; - next line; - } - if (m/^\s*\(\*\*\s*(.*)\*\)\s*$/) { - if ($inverbatim) { - do end_verbatim(); - } - print "\\subsubsection*{", $1, "}\n"; - next line; - } - if (s/^\s*\(\*//) { - if ($inverbatim) { - do end_verbatim(); - } - print "\\begin{comment}\n"; - $incomment = 1; - } - if ($incomment) { - $endcomment = s/\*\)\s*$//; - if (m/^\s*\[\s*$/) { - print "\\begin{restoreindent}\n" unless $html; - print "\\begin{verbatim}\n"; - while (($_ = <>) && ! m/^\s*\]\s*$/) { - print $_; - } - print "\\end{verbatim}\n"; - print "\\end{restoreindent}\n" unless $html; - } else { - if (s/^-//) { - print "\\\\"; - print "[\\smallskipamount]" unless $html; - } - s/^\s*//; - $count = 0; - foreach $part (split(/(\\?[\[\]])/, $_)) { - if ($part eq "[") { - print ($count == 0 ? "\\verb$sep" : "["); - $count++; - } elsif ($part eq "]") { - $count--; - print ($count == 0 ? "$sep" : "]"); - } elsif ($part =~ m/^\\([\[\]])$/) { - print $1; - } else { - print $part; - } - } - } - if ($endcomment) { - print "\n\\end{comment}"; - $incomment = 0; - $inverbatim = 0; - } - } else { - next line if /^$/; - if (! $inverbatim) { - print "\\begin{verbatim}\n"; - $inverbatim = 1; - } - s/^external /val /; - s/ = ("[^"]*"\s*)+$//; - next line if /^\s*$/; - s/^val \( ([^ )]+) \)/val (\1)/; - { - do indexentry($1, " (operator)"), last - if (m/^val \(([^)]*)\)/); - do indexentry($1, ""), last - if (m/^val ([a-zA-Z0-9_']*)/); - do indexentry($1, " (type)"), last - if (m/^type\s.*([a-zA-Z0-9_']*)\s*=/); - do indexentry($1, " (exception)"), last - if (m/^exception ([a-zA-Z0-9_']*)/); - do indexentry($1, " (module type)"), last - if (m/^module type ([a-zA-Z0-9_']*)/); - do indexentry($1, " (functor)"), last - if (m/^module ([a-zA-Z0-9_']*)\s*\(/); - do indexentry($1, " (module)"), last - if (m/^module ([a-zA-Z0-9_']*)/); - } - print $_; - } - print "\n"; -} -do end_verbatim() if $inverbatim; -print "\\end{comment}\n" if $incomment; - -sub indexentry { - local ($_, $comment) = @_; - return if m/^$/ || m/^[a-zA-Z]$/; - s/([@|!])/"$1/g; - if (! m|`|) { - $s = "`"; - } elsif (! m|~|) { - $s = "~"; - } elsif (! m/\|/) { - $s = "|"; - } else { - die("Can't find quote character for $_"); - } - push (@index, "\\index{$_$comment@\\verb$s$_$s$comment}"); -} - -sub end_verbatim { - print "\\end{verbatim}\n"; - foreach $idx (@index) { - print $idx, "%\n"; - } - undef(@index); - $inverbatim = 0; -} diff --git a/manual/tools/htmlcut b/manual/tools/htmlcut deleted file mode 100755 index be079abb..00000000 --- a/manual/tools/htmlcut +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/local/bin/perl -# Split an HTML file into smaller nodes. -# Split at

headers and also at some

headers. - -$h0 = "H0"; -$h1 = "H1"; -$h2 = "H2"; - -# Parse options - -option: -while(1) { - $_ = $ARGV[0]; - if (/^-([0-9]+)$/) { - $split2[$1] = 1; - } - elsif (/^-article/) { - $h0 = "H1"; - $h1 = "H2"; - $h2 = "H3"; - } - else { - last option; - } - shift(@ARGV); -} - -$infile = $ARGV[0]; - -# Find URL's for the links - -$level0 = 0; -$level1 = 0; -$uselabel = 1; -open(INPUT, $infile); -while() { - if (m|^<$h0>(.*)|o) { - $level0++; - $currfile = "node" . ($level1 + 1) . ".html"; - $lblnum = $level0; - $uselabel = 0; - } - if (m|^<$h1>(.*)|o) { - $level1++; - $level2 = 0; - $currfile = "node$level1.html"; - $lblnum = $level1; - $uselabel = 1; - } - if (m|^<$h2>(.*)|o) { - $level2++; - if ($split2[$level1]) { $currfile = "node$level1.$level2.html"; } - $lblnum = "$level1.$level2"; - } - s||do set_url($1)|ige; -} - -sub set_url { - local ($lbl) = @_; - if ($uselabel) { - $url{$lbl} = "$currfile#$lbl"; - } else { - $url{$lbl} = $currfile; - } - $label{$lbl} = $lblnum; -} - -# Cut the file - -$level1 = 0; -open(INPUT, $infile); -while() { - if (m|^<$h0>(.*)|o) { - if ($level2 > 0) { print FILE1 "\n"; } - select(STDOUT); - if ($level1 >= 1) { print ""; } - print "<$h2>$1\n"; - if ($level1 >= 1) { print "
    "; } - next; - } - if (m|^<$h1>(.*)|o) { - if ($level2 > 0) { print FILE1 "
\n"; } - $level1++; - $level2 = 0; - select(STDOUT); - if ($level1 == 1) { print "

    \n"; } - print "
  • $1\n"; - open(FILE1, "> node$level1.html"); - select(FILE1); - &print_title($1); - } - if ($split2[$level1] && m|^<$h2>(.*)|o) { - $level2++; - select(FILE1); - if ($level2 == 1) { print "

      \n"; } - print "
    • $1\n"; - open(FILE2, "> node$level1.$level2.html"); - select(FILE2); - &print_title($1); - } - s|X|'' . $label{$1} . ''|ige; - print $_; -} -select(STDOUT); -if ($level1 >= 1) { print "
    \n"; } - -sub print_title { - local ($title) = @_; - $title =~ s|<[a-zA-Z/]+>||g; - print "$title\n"; -} diff --git a/manual/tools/htmlquote.c b/manual/tools/htmlquote.c deleted file mode 100644 index 1d11eca5..00000000 --- a/manual/tools/htmlquote.c +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include - -#define LINE_LENGTH 1024 - -char line[LINE_LENGTH]; - -int isprefix(s, pref) - char * s; - char * pref; -{ - while (1) { - if (*pref == 0) return 1; - if (*s == 0) return 0; - if (*s != *pref) return 0; - s++; - pref++; - } -} - -int main(argc, argv) - int argc; - char * argv []; -{ - unsigned char * p; - int c; - int inquote; - int inverb; - int inverbatim; - - inverbatim = 0; - inquote = 0; - - while(fgets(line, LINE_LENGTH, stdin) != NULL) { - if (inverbatim) { - fputs(line, stdout); - if (isprefix(line, "\\end{verbatim") - || isprefix(line, "\\end{alltt}")) inverbatim = 0; - continue; - } - if (isprefix(line, "\\begin{verbatim") - || isprefix(line, "\\begin{alltt}")) { - fputs(line, stdout); - inverbatim = 1; - continue; - } - inverb = 0; - for (p = (unsigned char *) line; *p != 0; p++) { - c = *p; - if (inverb) { - if (c == inverb) inverb = 0; - putchar(c); - continue; - } - switch(c) { - case '"': - if (inquote) { - fputs("\001", stdout); - inquote = 0; - } else { - fputs("\\verb\001", stdout); - inquote = 1; - } - break; - case '\\': - if (isprefix(p, "\\verb") && p[5] != 0 && !isalpha(p[5])) { - inverb = p[5]; - p = p + 5; - fputs("\\verb", stdout); - putchar(inverb); - } else if (inquote) { - if (p[1] == '"' || p[1] == '\\') { - c = p[1]; - p++; - } - putchar(c); - } else { - putchar('\\'); - } - break; - default: - putchar(c); - } - } - } - return 0; -} diff --git a/manual/tools/htmltbl b/manual/tools/htmltbl deleted file mode 100755 index 4b7b41a7..00000000 --- a/manual/tools/htmltbl +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/local/bin/perl - -while (<>) { - if (m|^ ]|) { - while (! m|$|) { $_ .= <>; } - s/\n//g; - print "
    \n";
    -    do format_table($_);
    -    print "
    \n"; - } else { - print $_; - } -} - -sub format_table { -# On input, $_ contains: -# Header 1Header2...Header M -# Data11Data12...Data1M -# ... -# DataN1DataN2...DataNM -# - -# Extract the entries and compute the number of lines and columns - - $numlines = 0; - $numcols = 0; - $border = 0; - $header = 0; - $x = 0; - $y = 0; - foreach $_ (split(/(||||<\/tbl>)/, $_)) { - if (/^$/) { next; } - elsif (//) { $border = 1; } - elsif (//i) { - if ($x > $numcols) { $numcols = $x; } - $x = 0; - $y++; - } - elsif (//) { $header = 1; } - elsif (!/(||||<\/tbl>)/) { - s|||g; # Remove embedded tags - s/^\s*//; # and initial blanks - s/\s*$//; # and final blanks - s/\s\s\s*/ /g; # and extra blanks - s/<//g; - s/&/&/g; - $entry{$x, $y} = $_; - $x++; - } - } - $numlines = $y; - -# Compute the max width of each column - - $totalwidth = 0; - - for ($x = 0; $x < $numcols; $x++) { - $max = 0; - for ($y = 0; $y < $numlines; $y++) { - $len = length($entry{$x, $y}); - if ($len > $max) { $max = $len; } - } - $width[$x] = $max; - $totalwidth += $max; - } - -# If it does not fit in one line, turn wide fields into multi-line fields - - if ($totalwidth >= 65) { - $totalwidth = 0; - $maxwidth = 65 / $numcols; - for ($x = 0; $x < $numcols; $x++) { - if ($width[$x] > $maxwidth) { - if ($x < $numcols - 1) { - $width[$x] = $maxwidth; - } else { - $width[$x] = 70 - $totalwidth; - } - } - $totalwidth += $width[$x]; - } - } - -# Compute the separators - - if ($border) { - $horsep = '+-'; - for ($x = 0; $x < $numcols; $x++) { - if ($x > 0) { $horsep .= '-+-'; } - $horsep .= '-' x $width[$x]; - } - $horsep .= '-+'; - $verleft = '| '; - $versep = ' | '; - $verright = ' |'; - } else { - $horsep = ''; - $verleft = ' '; - $versep = ' '; - $verright = ' '; - } - -# Print the table - print $horsep, "\n"; - for ($y = 0; $y < $numlines; $y++) { - do { - $overflow = 0; - print $verleft; - for ($x = 0; $x < $numcols; $x++) { - if ($x > 0) { print $versep; } - $_ = $entry{$x, $y}; - if (length($_) > $width[$x]) { - $pos = rindex($_, ' ', $width[$x]); - if ($pos < 0) { $pos = $width[$x]; } else { $pos++; } - $entry{$x, $y} = substr($_, $pos); - $_ = substr($_, 0, $pos - 1); - $overflow = 1; - } else { - $entry{$x, $y} = ''; - } - $len = length($_); - s/&/&/g; - s//>/g; - print $_, ' ' x ($width[$x] - $len); - } - print $verright, "\n"; - } while($overflow); - if ($header && $y == 0) { print $horsep, "\n"; } - } - print $horsep, "\n"; -} - diff --git a/manual/tools/htmlthread b/manual/tools/htmlthread deleted file mode 100755 index fa66cdb2..00000000 --- a/manual/tools/htmlthread +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/local/bin/perl -# Insert Next/Previous/Contents buttons in a set of pages. - -@pages = sort fragmentorder @ARGV; - -sub fragmentorder { - $a =~ /^node([0-9]+)/; $na = $1; - if ($a =~ /^node[0-9]+\.([0-9]+)\.html/) { $fa = $1; } else { $fa = 0; } - $b =~ /^node([0-9]+)/; $nb = $1; - if ($b =~ /^node[0-9]+\.([0-9]+)\.html/) { $fb = $1; } else { $fb = 0; } - return (($na <=> $nb) || ($fa <=> $fb)); -} - -for ($i = 0; $i <= $#pages; $i++) { - open(SRC, $pages[$i]); - open(DST, "> newpage.html"); - select(DST); - $_ = ; # Title line - print "\n"; - print $_; - do links(); - print "\n"; - print "\n"; - do buttons(); - print "
    \n"; - $numlines = 0; - while () { - $numlines++; - print $_; - } - if ($numlines >= 40) { - print "
    \n"; - do buttons(); - } - close(SRC); - close(DST); - rename("newpage.html", $pages[$i]); -} - -sub links { - if ($i > 0) { - print '\n"; - } - if ($i < $#pages) { - print '\n"; - } - print "\n"; -} - -sub buttons { - if ($i > 0) { - print 'Previous', "\n"; - } - if ($i < $#pages) { - print 'Next', "\n"; - } - print 'Contents', "\n"; -} diff --git a/manual/tools/latexmacros.ml b/manual/tools/latexmacros.ml deleted file mode 100644 index 7353b494..00000000 --- a/manual/tools/latexmacros.ml +++ /dev/null @@ -1,149 +0,0 @@ -type action = - Print of string - | Print_arg - | Skip_arg;; - -let cmdtable = (Hashtbl.create 19 : (string, action list) Hashtbl.t);; - -let def_macro name action = - Hashtbl.add cmdtable name action;; - -let find_macro name = - try - Hashtbl.find cmdtable name - with Not_found -> - prerr_string "Unknown macro: "; prerr_endline name; [];; - -(* General LaTeX macros *) - -def_macro "\\part" - [Print ""; Print_arg; Print "\n"]; -def_macro "\\chapter" - [Print "

    "; Print_arg; Print "

    \n"]; -def_macro "\\chapter*" - [Print "

    "; Print_arg; Print "

    \n"]; -def_macro "\\section" - [Print "

    "; Print_arg; Print "

    \n"]; -def_macro "\\section*" - [Print "

    "; Print_arg; Print "

    \n"]; -def_macro "\\subsection" - [Print "

    "; Print_arg; Print "

    \n"]; -def_macro "\\subsection*" - [Print "

    "; Print_arg; Print "

    \n"]; -def_macro "\\subsubsection" - [Print "

    "; Print_arg; Print "

    \n"]; -def_macro "\\subsubsection*" - [Print "

    "; Print_arg; Print "

    \n"]; -def_macro "\\paragraph" - [Print ""; Print_arg; Print "  \n"]; -def_macro "\\begin{alltt}" [Print "
    "];
    -def_macro "\\end{alltt}" [Print "
    "]; -def_macro "\\begin{itemize}" [Print "

      "]; -def_macro "\\end{itemize}" [Print "
    "]; -def_macro "\\begin{enumerate}" [Print "

      "]; -def_macro "\\end{enumerate}" [Print "
    "]; -def_macro "\\begin{description}" [Print "

    "]; -def_macro "\\end{description}" [Print "
    "]; -def_macro "\\begin{center}" [Print "
    "]; -def_macro "\\end{center}" [Print "
    "]; -def_macro "\\begin{quote}" [Print "
    "]; -def_macro "\\end{quote}" [Print "
    "]; -def_macro "\\begin{quotation}" [Print "
    "]; -def_macro "\\end{quotation}" [Print "
    "]; -def_macro "\\smallskip" []; -def_macro "\\medskip" []; -def_macro "\\bigskip" []; -def_macro "\\markboth" [Skip_arg; Skip_arg]; -def_macro "\\ldots" [Print "..."]; -def_macro "\\ " [Print " "]; -def_macro "\\{" [Print "{"]; -def_macro "\\}" [Print "}"]; -def_macro "\\%" [Print "%"]; -def_macro "\\$" [Print "$"]; -def_macro "\\#" [Print "#"]; -def_macro "\\/" []; -def_macro "\\newpage" []; -def_macro "\\label" [Print ""]; -def_macro "\\ref" [Print "X"]; -def_macro "\\pageref" [Print "X"]; -def_macro "\\index" [Skip_arg]; -def_macro "\\oe" [Print "oe"]; -def_macro "\\&" [Print "&"]; -def_macro "\\_" [Print "_"]; -def_macro "\\leq" [Print "<="]; -def_macro "\\geq" [Print ">="]; -def_macro "\\hbox" [Print_arg]; -def_macro "\\copyright" [Print "\169"]; -def_macro "\\noindent" []; -def_macro "\\begin{flushleft}" [Print "
    "]; -def_macro "\\end{flushleft}" [Print "
    "]; -def_macro "\\\\" [Print "
    "]; -def_macro "\\begin{htmlonly}" []; -def_macro "\\end{htmlonly}" []; -();; - -(* Macros specific to the Caml manual *) - -def_macro "\\begin{options}" [Print "

    "]; -def_macro "\\end{options}" [Print "
    "]; -def_macro "\\var" [Print ""; Print_arg; Print ""]; -def_macro "\\optvar" [Print "["; Print_arg; Print "]"]; -def_macro "\\nth" [Print ""; Print_arg; - Print ""; Print_arg; Print ""]; -def_macro "\\nmth" [Print ""; Print_arg; - Print ""; Print_arg; - Print ""; Print_arg; - Print ""]; -def_macro "\\begin{unix}" [Print "
    Unix:
    "]; -def_macro "\\end{unix}" [Print "
    "]; -def_macro "\\begin{macos}" [Print "
    MacOS:
    "]; -def_macro "\\end{macos}" [Print "
    "]; -def_macro "\\begin{windows}" [Print "
    Windows:
    "]; -def_macro "\\end{windows}" [Print "
    "]; -def_macro "\\begin{requirements}" [Print "
    Requirements:
    "]; -def_macro "\\end{requirements}" [Print "
    "]; -def_macro "\\begin{troubleshooting}" [Print "
    Troubleshooting:
    "]; -def_macro "\\end{troubleshooting}" [Print "
    "]; -def_macro "\\begin{installation}" [Print "
    Installation:
    "]; -def_macro "\\end{installation}" [Print "
    "]; -def_macro "\\index" [Skip_arg]; -def_macro "\\ikwd" [Skip_arg]; -def_macro "\\th" [Print "-th"]; -def_macro "\\begin{library}" []; -def_macro "\\end{library}" []; -def_macro "\\begin{comment}" [Print "
    "]; -def_macro "\\end{comment}" [Print "
    "]; -def_macro "\\begin{tableau}" - [Skip_arg; - Print "\n"]; -def_macro "\\entree" - [Print ""]; -def_macro "\\end{tableau}" [Print "
    "; - Print_arg; - Print ""; - Print_arg; - Print "
    "; Print_arg; - Print ""; Print_arg; Print "
    "]; -def_macro "\\begin{gcrule}" [Print "
    Rule:
    "]; -def_macro "\\end{gcrule}" [Print "
    "]; -def_macro "\\begin{tableauoperateurs}" - [Print "\n"]; -def_macro "\\end{tableauoperateurs}" [Print "
    OperatorAssociated identBehavior in the default environment
    \n"]; -def_macro "\\entreeoperateur" - [Print ""; Print_arg; Print ""; Print_arg; - Print ""; Print_arg; Print ""]; -def_macro "\\fromoneto" - [Print ""; Print_arg; Print " = 1, ..., "; - Print_arg; Print ""]; -def_macro "\\caml" [Print "
    "];
    -def_macro "\\endcaml" [Print "
    "]; -def_macro "\\<" [Print ""]; -def_macro "\\>" [Print ""]; -def_macro "\\rminalltt" [Print_arg]; -def_macro "\\event" [Print "*"]; -def_macro "\\pdfchapter" [Skip_arg]; -def_macro "\\pdfchapterfold" [Skip_arg; Skip_arg]; -def_macro "\\pdfsection" [Skip_arg]; -def_macro "\\transl" [Print "<"; Print_arg; Print ">"]; -();; - diff --git a/manual/tools/latexmacros.mli b/manual/tools/latexmacros.mli deleted file mode 100644 index e7e4066f..00000000 --- a/manual/tools/latexmacros.mli +++ /dev/null @@ -1,8 +0,0 @@ -type action = - Print of string - | Print_arg - | Skip_arg;; - -val find_macro: string -> action list;; - -val def_macro: string -> action list -> unit;; diff --git a/manual/tools/latexmain.ml b/manual/tools/latexmain.ml deleted file mode 100644 index 02d936f5..00000000 --- a/manual/tools/latexmain.ml +++ /dev/null @@ -1,4 +0,0 @@ -let main () = - Latexscan.main (Lexing.from_channel stdin);; - -Printexc.print main (); exit 0;; diff --git a/manual/tools/latexscan.mll b/manual/tools/latexscan.mll deleted file mode 100644 index 1acc5231..00000000 --- a/manual/tools/latexscan.mll +++ /dev/null @@ -1,166 +0,0 @@ -{ -open Lexing;; -open Latexmacros;; - -let delimiter = ref (char_of_int 0);; - -let upto delim lexfun lexbuf = - let old_delim = !delimiter in - delimiter := delim; - lexfun lexbuf; - delimiter := old_delim;; - -let verb_delim = ref (char_of_int 0);; - -let brace_nesting = ref 0;; - -let rindex c s = - let rec find i = - if i < 0 then raise Not_found else - if s.[i] = c then i else find (i-1) in - find (String.length s - 1);; - -let first_caml_line = ref true;; -let in_caml = ref false;; -} - -rule main = parse -(* Comments *) - '%' [^ '\n'] * '\n' { main lexbuf } -(* Paragraphs *) - | "\n\n" '\n' * - { print_string "

    \n"; main lexbuf } -(* Font changes *) - | "{\\it" " "* | "{\\em" " "* - { print_string ""; upto '}' main lexbuf; - print_string ""; main lexbuf } - | "{\\bf" " "* { print_string ""; upto '}' main lexbuf; - print_string ""; main lexbuf } - | "{\\rm" " "* { print_string ""; upto '}' main lexbuf; - print_string ""; main lexbuf } - | "{\\tt" " "* { print_string ""; upto '}' main lexbuf; - print_string ""; main lexbuf } - | '"' { print_string ""; indoublequote lexbuf; - print_string ""; main lexbuf } -(* Verb, verbatim *) - | "\\verb" _ { verb_delim := lexeme_char lexbuf 5; - print_string ""; inverb lexbuf; print_string ""; - main lexbuf } - | "\\begin{verbatim}" - { print_string "

    "; inverbatim lexbuf;
    -                  print_string "
    "; main lexbuf } -(* Caml programs *) - | "\\caml" - { print_string "
    ";
    -                  first_caml_line := true; in_caml := false;
    -                  camlprog lexbuf; print_string "
    "; main lexbuf } -(* Raw html, latex only *) - | "\\begin{rawhtml}" - { rawhtml lexbuf; main lexbuf } - | "\\begin{latexonly}" - { latexonly lexbuf; main lexbuf } -(* Itemize and similar environments *) - | "\\item[" { print_string "
    "; upto ']' main lexbuf; - print_string "
    "; main lexbuf } - | "\\item" { print_string "
  • "; main lexbuf } -(* Math mode (hmph) *) - | "$" { main lexbuf } -(* Special characters *) - | "\\char" ['0'-'9']+ - { let lxm = lexeme lexbuf in - let code = String.sub lxm 5 (String.length lxm - 5) in - print_char(char_of_int(int_of_string code)); - main lexbuf } - | "<" { print_string "<"; main lexbuf } - | ">" { print_string ">"; main lexbuf } - | "~" { print_string " "; main lexbuf } -(* Definitions of very simple macros *) - | "\\def\\" (['A'-'Z' 'a'-'z']+ | [^ 'A'-'Z' 'a'-'z']) "{" [^ '{' '}']* "}" - { let s = lexeme lexbuf in - let l = String.length s in - let p = rindex '{' s in - let name = String.sub s 4 (p - 4) in - let expansion = String.sub s (p + 1) (l - p - 2) in - def_macro name [Print expansion]; - main lexbuf } -(* General case for environments and commands *) - | ("\\begin{" | "\\end{") ['A'-'Z' 'a'-'z']+ "}" | - "\\" (['A'-'Z' 'a'-'z']+ '*'? | [^ 'A'-'Z' 'a'-'z']) - { let exec_action = function - Print str -> print_string str - | Print_arg -> print_arg lexbuf - | Skip_arg -> skip_arg lexbuf in - List.iter exec_action (find_macro(lexeme lexbuf)); - main lexbuf } -(* Default rule for other characters *) - | eof { () } - | _ { let c = lexeme_char lexbuf 0 in - if c == !delimiter then () else (print_char c; main lexbuf) } - -and indoublequote = parse - '"' { () } - | "<" { print_string "<"; indoublequote lexbuf } - | ">" { print_string ">"; indoublequote lexbuf } - | "&" { print_string "&"; indoublequote lexbuf } - | "\\\"" { print_string "\""; indoublequote lexbuf } - | "\\\\" { print_string "\\"; indoublequote lexbuf } - | _ { print_char(lexeme_char lexbuf 0); indoublequote lexbuf } - -and inverb = parse - "<" { print_string "<"; inverb lexbuf } - | ">" { print_string ">"; inverb lexbuf } - | "&" { print_string "&"; inverb lexbuf } - | _ { let c = lexeme_char lexbuf 0 in - if c == !verb_delim then () - else (print_char c; inverb lexbuf) } -and inverbatim = parse - "<" { print_string "<"; inverbatim lexbuf } - | ">" { print_string ">"; inverbatim lexbuf } - | "&" { print_string "&"; inverbatim lexbuf } - | "\\end{verbatim}" { () } - | _ { print_char(lexeme_char lexbuf 0); inverbatim lexbuf } - -and camlprog = parse - "<" { print_string "<"; camlprog lexbuf } - | ">" { print_string ">"; camlprog lexbuf } - | "&" { print_string "&"; camlprog lexbuf } - | "\\?" { if !first_caml_line then begin - print_string "# "; - first_caml_line := false - end else - print_string " "; - in_caml := true; - camlprog lexbuf } - | "\\:" { print_string ""; - in_caml := true; - camlprog lexbuf } - | "\\;" { first_caml_line := true; camlprog lexbuf } - | "\\\\" { print_string "\\"; camlprog lexbuf } - | "\\endcaml" { () } - | "\n" { if !in_caml then begin - print_string ""; - in_caml := false - end; - print_char '\n'; - camlprog lexbuf } - | _ { print_char(lexeme_char lexbuf 0); camlprog lexbuf } - -and rawhtml = parse - "\\end{rawhtml}" { () } - | _ { print_char(lexeme_char lexbuf 0); rawhtml lexbuf } - -and latexonly = parse - "\\end{latexonly}" { () } - | _ { latexonly lexbuf } - -and print_arg = parse - [' ' '\n'] * "{" { upto '}' main lexbuf } - | _ { print_char(lexeme_char lexbuf 0); rawhtml lexbuf } - -and skip_arg = parse - "{" { incr brace_nesting; skip_arg lexbuf } - | "}" { decr brace_nesting; - if !brace_nesting > 0 then skip_arg lexbuf } - | _ { skip_arg lexbuf } - - diff --git a/manual/tools/texexpand b/manual/tools/texexpand deleted file mode 100755 index b2d8032f..00000000 --- a/manual/tools/texexpand +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/local/bin/perl -# Expand \input commands - -@path = split(/:/, $ENV{'TEXINPUTS'}); - -while(<>) { - if (/^\\input\s*([^\s]*)/) { - do expand($1); - } else { - print $_; - } -} - -sub expand { - local ($filename) = @_; - local (*INPUT); - $filename =~ s/\.tex$//; - $filename = do find_in_path($filename); - open(INPUT, $filename) || (warn("cannot find $filename"), return); - print "%%% $filename\n"; - while() { - if (/^\\input\s*([^\s]*)/) { - do expand($1); - } else { - print $_; - } - } - close(INPUT); -} - -sub find_in_path { - local ($name) = @_; - local ($dir); - foreach $dir (@path) { - return "$dir/$name.htex" if (-f "$dir/$name.htex"); - return "$dir/$name.tex" if (-f "$dir/$name.tex"); - } - return $name; -} - diff --git a/manual/tools/texquote2.c b/manual/tools/texquote2.c deleted file mode 100644 index 23ef01e5..00000000 --- a/manual/tools/texquote2.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -char * transl[256]; - -#define LINE_LENGTH 1024 - -char line[LINE_LENGTH]; - -int isprefix(s, pref) - char * s; - char * pref; -{ - while (1) { - if (*pref == 0) return 1; - if (*s == 0) return 0; - if (*s != *pref) return 0; - s++; - pref++; - } -} - -int main(argc, argv) - int argc; - char * argv []; -{ - unsigned char * p; - int c; - int inquote; - int inverb; - int inverbatim_like; - int incaml; - int inverbatim = 0; - char *verbatim_end_in = ""; - char *verbatim_end_out = ""; - - for (c = 0; c < 256; c++) transl[c] = NULL; -#ifdef TIE_BLANKS - transl[' '] = "~"; - transl['\n'] = "~"; -#else - transl[' '] = "\\ "; - transl['\n'] = "\\ "; -#endif - transl['{'] = "{\\char123}"; - transl['}'] = "{\\char125}"; - transl['^'] = "{\\char94}"; - transl['_'] = "{\\char95}"; - transl['\\'] = "{\\char92}"; - transl['~'] = "{\\char126}"; - transl['$'] = "\\$"; - transl['&'] = "{\\char38}"; - transl['#'] = "\\#"; - transl['%'] = "\\%"; - transl['\''] = "{\\textquotesingle}"; - transl['`'] = "{\\textasciigrave}"; - inverbatim_like = 0; - incaml = 0; - inquote = 0; - inverbatim = 0; - - puts ("% THIS FILE IS GENERATED.\n"); - - while(fgets(line, LINE_LENGTH, stdin) != NULL) { - if (inverbatim_like) { - fputs(line, stdout); - if (isprefix(line, "\\end{caml_") - || isprefix(line, "\\end{rawhtml}")) inverbatim_like = 0; - continue; - } - if (incaml) { - fputs(line, stdout); - if (isprefix(line, "\\endcamlexample")) incaml = 0; - continue; - } - if (inverbatim){ - if (isprefix (line, verbatim_end_in)){ - fputs (verbatim_end_out, stdout); - inverbatim = 0; - }else{ - for (p = (unsigned char *) line; *p != 0; p++){ - c = *p; - if (c == ' ' || c == '\n' || transl[c] == NULL){ - putchar (c); - }else{ - fputs (transl[c], stdout); - } - } - } - continue; - } - if (isprefix(line, "\\begin{caml_") - || isprefix(line, "\\begin{rawhtml}")) { - fputs(line, stdout); - inverbatim_like = 1; - continue; - } - if (isprefix(line, "\\camlexample")) { - fputs(line, stdout); - incaml = 1; - continue; - } - if (isprefix (line, "\\begin{verbatim}")){ - fputs ("\\begin{machineenv}", stdout); - inverbatim = 1; - verbatim_end_in = "\\end{verbatim}"; - verbatim_end_out = "\\end{machineenv}"; - continue; - } - if (isprefix (line, "\\begin{ocamldoccode}")){ - fputs ("\\begin{ocamldoccode}", stdout); - inverbatim = 1; - verbatim_end_in = "\\end{ocamldoccode}"; - verbatim_end_out = "\\end{ocamldoccode}"; - continue; - } - inverb = 0; - for (p = (unsigned char *) line; *p != 0; p++) { - c = *p; - if (inverb) { - if (c == inverb){ - inverb = 0; - }else if (c == '\'' || c == '`'){ - fprintf (stderr, "Warning: %c found in \\verb\n", c); - } - putchar(c); - continue; - } - switch(c) { - case '"': - if (inquote) { - fputs("}}", stdout); - inquote = 0; - } else { - fputs("{\\machine{", stdout); - inquote = 1; - } - break; - case '\\': - if (inquote) { - if (p[1] == '"' || p[1] == '\\') { - c = p[1]; - p++; - } - if (transl[c] != NULL) - fputs(transl[c], stdout); - else - putchar(c); - } else if (isprefix(p, "\\verb") && p[5] != 0 && !isalpha(p[5])) { - inverb = p[5]; - p = p + 5; - fputs("\\verb", stdout); - putchar(inverb); - } else { - putchar('\\'); - } - break; - default: - if (inquote && transl[c] != NULL) - fputs(transl[c], stdout); - else - putchar(c); - } - } - } - return 0; -} diff --git a/manual/tools/texquote2.ml b/manual/tools/texquote2.ml new file mode 100644 index 00000000..d6e8a8f5 --- /dev/null +++ b/manual/tools/texquote2.ml @@ -0,0 +1,137 @@ +type environment = + | Normal + | Caml + | Verbatim of string * string + | Verbatim_like + +let in_quotes = ref false + +let is_alpha c = + ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') + +let is_prefix prefix str = + let length_prefix = String.length prefix in + let length_str = String.length str in + if length_prefix > length_str + then false + else (String.sub str 0 length_prefix) = prefix + +let escape = function + | ' ' | '\n' -> "\\ " + | '{' -> "{\\char123}" + | '}' -> "{\\char125}" + | '^' -> "{\\char94}" + | '_' -> "{\\char95}" + | '\\' -> "{\\char92}" + | '~' -> "{\\char126}" + | '$' -> "\\$" + | '&' -> "{\\char38}" + | '#' -> "\\#" + | '%' -> "\\%" + | '\'' -> "{\\textquotesingle}" + | '`' -> "{\\textasciigrave}" + | _ -> "" + +let process_normal_line line = + let (verb_mark : char option ref) = ref None in + let l = String.length line in + let i = ref 0 in + while !i + (match line.[!i] with + | '"' -> + let r = if !in_quotes then "}}" else "{\\machine{" in + print_string r; + in_quotes := not !in_quotes; + incr i; + | '\\' -> + if !in_quotes + then begin + if (!i < l-1) && (line.[!i+1] = '"' || line.[!i+1] = '\\') + then incr i; + let t = escape line.[!i] in + if t<>"" then print_string t else print_char line.[!i]; + incr i; + end else if is_prefix "\\verb" (String.sub line !i (l - !i)) + && not (is_alpha line.[!i+5]) + then begin + i := !i+5; + verb_mark := Some line.[!i]; + print_string "\\verb"; + print_char line.[!i]; + incr i; + end else (print_char '\\'; incr i) + | _ -> + if !in_quotes && (escape line.[!i] <> "") + then print_string (escape line.[!i]) + else print_char line.[!i]; + incr i; + ) + | Some mark -> + if line.[!i] = mark + then verb_mark := None + else if line.[!i] = '\'' || line.[!i] = '`' + then Printf.eprintf "Warning: %c found in \\verb\n" line.[!i]; + print_char line.[!i]; + incr i; + done + +let process_line line = function + | Normal -> + if is_prefix "\\begin{caml_" line || is_prefix "\\begin{rawhtml}" line + then (print_string line; Verbatim_like) + else if is_prefix "\\camlexample" line + then (print_endline line; Caml) + else if is_prefix "\\begin{verbatim}" line + then begin + print_string "\\begin{machineenv}"; + (Verbatim ("\\end{verbatim}", "\\end{machineenv}")) + end else if is_prefix "\\begin{ocamldoccode}" line + then begin + print_string "\\begin{ocamldoccode}"; + (Verbatim ("\\end{ocamldoccode}", "\\end{ocamldoccode}")) + end else begin + process_normal_line line; + if !in_quotes + then print_string (escape '\n') + else print_newline(); + Normal + end + | Caml -> + print_endline line; + if is_prefix "\\endcamlexample" line then Normal else Caml + | Verbatim (verbatim_end_in, verbatim_end_out) as env -> + if is_prefix verbatim_end_in line + then begin + print_string verbatim_end_out; + Normal + end else begin + for i=0 to (String.length line) - 1 do + let c = line.[i] in + let t = escape c in + if c=' ' || c='\n' || t="" + then print_char c + else print_string t + done; + print_newline(); + env + end + | Verbatim_like -> + print_endline line; + if is_prefix "\\end{caml_" line || is_prefix "\\end{rawhtml}" line + then Normal + else Verbatim_like + +let rec process_input env = match input_line stdin with + | exception End_of_file -> () + | line -> + let env = process_line line env in + process_input env + +let main() = + print_endline "% THIS FILE IS GENERATED."; + print_newline(); + process_input Normal + +let _ = main() diff --git a/middle_end/alias_analysis.ml b/middle_end/alias_analysis.ml index 0ed9ae29..fe97a36f 100755 --- a/middle_end/alias_analysis.ml +++ b/middle_end/alias_analysis.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare type allocation_point = | Symbol of Symbol.t diff --git a/middle_end/allocated_const.ml b/middle_end/allocated_const.ml index f6e9d8e5..78dc4ee1 100644 --- a/middle_end/allocated_const.ml +++ b/middle_end/allocated_const.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare type t = | Float of float @@ -43,13 +44,13 @@ let compare (x : t) (y : t) = in match x, y with | Float x, Float y -> compare_floats x y - | Int32 x, Int32 y -> compare x y - | Int64 x, Int64 y -> compare x y - | Nativeint x, Nativeint y -> compare x y + | Int32 x, Int32 y -> Int32.compare x y + | Int64 x, Int64 y -> Int64.compare x y + | Nativeint x, Nativeint y -> Nativeint.compare x y | Float_array x, Float_array y -> compare_float_lists x y | Immutable_float_array x, Immutable_float_array y -> compare_float_lists x y - | String x, String y -> compare x y - | Immutable_string x, Immutable_string y -> compare x y + | String x, String y -> String.compare x y + | Immutable_string x, Immutable_string y -> String.compare x y | Float _, _ -> -1 | _, Float _ -> 1 | Int32 _, _ -> -1 diff --git a/middle_end/augment_specialised_args.ml b/middle_end/augment_specialised_args.ml index 83b45377..c3a30785 100755 --- a/middle_end/augment_specialised_args.ml +++ b/middle_end/augment_specialised_args.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module E = Inline_and_simplify_aux.Env module B = Inlining_cost.Benefit @@ -751,7 +752,8 @@ module Make (T : S) = struct Some (expr, benefit) let rewrite_set_of_closures ~env ~duplicate_function ~set_of_closures = - Pass_wrapper.with_dump ~pass_name:T.pass_name ~input:set_of_closures + Pass_wrapper.with_dump ~ppf_dump:(Inline_and_simplify_aux.Env.ppf_dump env) + ~pass_name:T.pass_name ~input:set_of_closures ~print_input:Flambda.print_set_of_closures ~print_output:(fun ppf (expr, _) -> Flambda.print ppf expr) ~f:(fun () -> diff --git a/middle_end/base_types/closure_element.ml b/middle_end/base_types/closure_element.ml index a1c866e2..561e0803 100644 --- a/middle_end/base_types/closure_element.ml +++ b/middle_end/base_types/closure_element.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare include Variable diff --git a/middle_end/base_types/closure_id.ml b/middle_end/base_types/closure_id.ml index 4003a609..466f59a2 100644 --- a/middle_end/base_types/closure_id.ml +++ b/middle_end/base_types/closure_id.ml @@ -14,6 +14,7 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare include Closure_element diff --git a/middle_end/base_types/closure_origin.ml b/middle_end/base_types/closure_origin.ml index 324e7189..2285c687 100644 --- a/middle_end/base_types/closure_origin.ml +++ b/middle_end/base_types/closure_origin.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare include Closure_id diff --git a/middle_end/base_types/compilation_unit.ml b/middle_end/base_types/compilation_unit.ml index 18031724..7fb48167 100644 --- a/middle_end/base_types/compilation_unit.ml +++ b/middle_end/base_types/compilation_unit.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare type t = { id : Ident.t; diff --git a/middle_end/base_types/export_id.ml b/middle_end/base_types/export_id.ml index 52db870a..681ac955 100644 --- a/middle_end/base_types/export_id.ml +++ b/middle_end/base_types/export_id.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module Id : Id_types.Id = Id_types.Id (struct end) module Unit_id = Id_types.UnitId (Id) (Compilation_unit) diff --git a/middle_end/base_types/id_types.ml b/middle_end/base_types/id_types.ml index 172e8af5..6d2e2743 100644 --- a/middle_end/base_types/id_types.ml +++ b/middle_end/base_types/id_types.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module type BaseId = sig type t @@ -53,7 +54,7 @@ module Id(E:sig end) : Id = struct else Some name let to_string (t,name) = if name == empty_string - then string_of_int t + then Int.to_string t else Printf.sprintf "%s_%i" name t let output fd t = output_string fd (to_string t) let print ppf v = Format.pp_print_string ppf (to_string v) diff --git a/middle_end/base_types/linkage_name.ml b/middle_end/base_types/linkage_name.ml index 83b790b2..46febfba 100644 --- a/middle_end/base_types/linkage_name.ml +++ b/middle_end/base_types/linkage_name.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare type t = string diff --git a/middle_end/base_types/mutable_variable.ml b/middle_end/base_types/mutable_variable.ml index 04e952d0..07fe3152 100644 --- a/middle_end/base_types/mutable_variable.ml +++ b/middle_end/base_types/mutable_variable.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare include Variable diff --git a/middle_end/base_types/set_of_closures_id.ml b/middle_end/base_types/set_of_closures_id.ml index 52db870a..681ac955 100644 --- a/middle_end/base_types/set_of_closures_id.ml +++ b/middle_end/base_types/set_of_closures_id.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module Id : Id_types.Id = Id_types.Id (struct end) module Unit_id = Id_types.UnitId (Id) (Compilation_unit) diff --git a/middle_end/base_types/set_of_closures_origin.ml b/middle_end/base_types/set_of_closures_origin.ml index 9e7db69f..a5ef8c7c 100644 --- a/middle_end/base_types/set_of_closures_origin.ml +++ b/middle_end/base_types/set_of_closures_origin.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare include Set_of_closures_id diff --git a/middle_end/base_types/static_exception.ml b/middle_end/base_types/static_exception.ml index 3701befa..6cecae63 100644 --- a/middle_end/base_types/static_exception.ml +++ b/middle_end/base_types/static_exception.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare include Numbers.Int diff --git a/middle_end/base_types/symbol.ml b/middle_end/base_types/symbol.ml index 940fc10d..22a2e0a7 100644 --- a/middle_end/base_types/symbol.ml +++ b/middle_end/base_types/symbol.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare type t = diff --git a/middle_end/base_types/tag.ml b/middle_end/base_types/tag.ml index a781cee1..cfa51ddb 100644 --- a/middle_end/base_types/tag.ml +++ b/middle_end/base_types/tag.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare type t = int @@ -30,3 +31,5 @@ let to_int t = t let zero = 0 let object_tag = Obj.object_tag + +let compare : t -> t -> int = Stdlib.compare diff --git a/middle_end/base_types/tag.mli b/middle_end/base_types/tag.mli index 20f8bcad..12ce5525 100644 --- a/middle_end/base_types/tag.mli +++ b/middle_end/base_types/tag.mli @@ -25,3 +25,5 @@ val to_int : t -> int val zero : t val object_tag : t + +val compare : t -> t -> int diff --git a/middle_end/base_types/var_within_closure.ml b/middle_end/base_types/var_within_closure.ml index 4003a609..466f59a2 100644 --- a/middle_end/base_types/var_within_closure.ml +++ b/middle_end/base_types/var_within_closure.ml @@ -14,6 +14,7 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare include Closure_element diff --git a/middle_end/base_types/variable.ml b/middle_end/base_types/variable.ml index edfdf1f8..64099a73 100644 --- a/middle_end/base_types/variable.ml +++ b/middle_end/base_types/variable.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare type t = { compilation_unit : Compilation_unit.t; @@ -42,7 +43,7 @@ include Identifiable.Make (struct let output chan t = output_string chan t.name; output_string chan "_"; - output_string chan (string_of_int t.name_stamp) + output_string chan (Int.to_string t.name_stamp) let hash t = t.name_stamp lxor (Compilation_unit.hash t.compilation_unit) @@ -94,7 +95,7 @@ let get_compilation_unit t = t.compilation_unit let name t = t.name let unique_name t = - t.name ^ "_" ^ (string_of_int t.name_stamp) + t.name ^ "_" ^ (Int.to_string t.name_stamp) let print_list ppf ts = List.iter (fun t -> Format.fprintf ppf "@ %a" print t) ts diff --git a/middle_end/closure_conversion.ml b/middle_end/closure_conversion.ml index 7831b0b1..a852ae8d 100755 --- a/middle_end/closure_conversion.ml +++ b/middle_end/closure_conversion.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module Env = Closure_conversion_aux.Env module Function_decls = Closure_conversion_aux.Function_decls @@ -42,7 +43,7 @@ let add_default_argument_wrappers lam = Lfunction {kind; params; body = fbody; attr; loc}, body) -> begin match Simplif.split_default_wrapper ~id ~kind ~params - ~body:fbody ~attr ~loc + ~body:fbody ~return:Pgenval ~attr ~loc with | [fun_id, def] -> Llet (Alias, Pgenval, fun_id, def, body) | [fun_id, def; inner_fun_id, def_inner] -> @@ -58,7 +59,7 @@ let add_default_argument_wrappers lam = (function | (id, Lambda.Lfunction {kind; params; body; attr; loc}) -> Simplif.split_default_wrapper ~id ~kind ~params ~body - ~attr ~loc + ~return:Pgenval ~attr ~loc | _ -> assert false) defs) in @@ -204,7 +205,7 @@ let rec close t env (lam : Lambda.lambda) : Flambda.t = let set_of_closures = let decl = Function_decl.create ~let_rec_ident:None ~closure_bound_var ~kind - ~params ~body ~attr ~loc + ~params:(List.map fst params) ~body ~attr ~loc in close_functions t env (Function_decls.create [decl]) in @@ -249,7 +250,7 @@ let rec close t env (lam : Lambda.lambda) : Flambda.t = in let function_declaration = Function_decl.create ~let_rec_ident:(Some let_rec_ident) - ~closure_bound_var ~kind ~params ~body + ~closure_bound_var ~kind ~params:(List.map fst params) ~body ~attr ~loc in Some function_declaration @@ -314,7 +315,7 @@ let rec close t env (lam : Lambda.lambda) : Flambda.t = | Lprim ((Pdivint Safe | Pmodint Safe | Pdivbint { is_safe = Safe } | Pmodbint { is_safe = Safe }) as prim, [arg1; arg2], loc) - when not !Clflags.fast -> (* not -unsafe *) + when not !Clflags.unsafe -> let arg2 = close t env arg2 in let arg1 = close t env arg1 in let numerator = Variable.create Names.numerator in @@ -373,7 +374,7 @@ let rec close t env (lam : Lambda.lambda) : Flambda.t = (Prim (prim, [numerator; denominator], dbg)))))))) | Lprim ((Pdivint Safe | Pmodint Safe | Pdivbint { is_safe = Safe } | Pmodbint { is_safe = Safe }), _, _) - when not !Clflags.fast -> + when not !Clflags.unsafe -> Misc.fatal_error "Pdivint / Pmodint must have exactly two arguments" | Lprim (Psequor, [arg1; arg2], _) -> let arg1 = close t env arg1 in @@ -423,7 +424,7 @@ let rec close t env (lam : Lambda.lambda) : Flambda.t = | Lprim (Psetfield (_, _, _), [Lprim (Pgetglobal _, [], _); _], _) -> Misc.fatal_errorf "[Psetfield (Pgetglobal ...)] is \ forbidden upon entry to the middle end" - | Lprim (Pgetglobal id, [], _) when Ident.is_predef_exn id -> + | Lprim (Pgetglobal id, [], _) when Ident.is_predef id -> let symbol = t.symbol_for_global' id in t.imported_symbols <- Symbol.Set.add symbol t.imported_symbols; name_expr (Symbol symbol) ~name:Names.predef_exn @@ -481,7 +482,8 @@ let rec close t env (lam : Lambda.lambda) : Flambda.t = | Lstaticcatch (body, (i, ids), handler) -> let st_exn = Static_exception.create () in let env = Env.add_static_exception env i st_exn in - let vars = List.map (Variable.create_with_same_name_as_ident) ids in + let ids = List.map fst ids in + let vars = List.map Variable.create_with_same_name_as_ident ids in Static_catch (st_exn, vars, close t env body, close t (Env.add_vars env ids vars) handler) | Ltrywith (body, id, handler) -> @@ -621,8 +623,8 @@ and close_let_bound_expression t ?let_rec_ident let_bound_var env names. *) let closure_bound_var = Variable.rename let_bound_var in let decl = - Function_decl.create ~let_rec_ident ~closure_bound_var ~kind ~params - ~body ~attr ~loc + Function_decl.create ~let_rec_ident ~closure_bound_var ~kind + ~params:(List.map fst params) ~body ~attr ~loc in let set_of_closures_var = Variable.rename let_bound_var in let set_of_closures = diff --git a/middle_end/closure_conversion_aux.ml b/middle_end/closure_conversion_aux.ml index b3e67a6f..cfcaf34d 100644 --- a/middle_end/closure_conversion_aux.ml +++ b/middle_end/closure_conversion_aux.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module Env = struct type t = { @@ -64,7 +65,7 @@ module Env = struct try Numbers.Int.Map.find st_exn t.static_exceptions with Not_found -> Misc.fatal_error ("Closure_conversion.Env.find_static_exception: exn " - ^ string_of_int st_exn) + ^ Int.to_string st_exn) let add_global t pos symbol = { t with globals = Numbers.Int.Map.add pos symbol t.globals } @@ -73,7 +74,7 @@ module Env = struct try Numbers.Int.Map.find pos t.globals with Not_found -> Misc.fatal_error ("Closure_conversion.Env.find_global: global " - ^ string_of_int pos) + ^ Int.to_string pos) let at_toplevel t = t.at_toplevel @@ -97,7 +98,7 @@ module Function_decls = struct ~attr ~loc = let let_rec_ident = match let_rec_ident with - | None -> Ident.create "unnamed_function" + | None -> Ident.create_local "unnamed_function" | Some let_rec_ident -> let_rec_ident in { let_rec_ident; diff --git a/middle_end/debuginfo.ml b/middle_end/debuginfo.ml index d979cc1e..7a339022 100644 --- a/middle_end/debuginfo.ml +++ b/middle_end/debuginfo.ml @@ -13,6 +13,7 @@ (* *) (**************************************************************************) +open! Int_replace_polymorphic_compare open Lexing open Location @@ -21,6 +22,9 @@ type item = { dinfo_line: int; dinfo_char_start: int; dinfo_char_end: int; + dinfo_start_bol: int; + dinfo_end_bol: int; + dinfo_end_line: int; } type t = item list @@ -45,13 +49,22 @@ let to_string dbg = "{" ^ String.concat ";" items ^ "}" let item_from_location loc = + let valid_endpos = + String.equal loc.loc_end.pos_fname loc.loc_start.pos_fname in { dinfo_file = loc.loc_start.pos_fname; dinfo_line = loc.loc_start.pos_lnum; dinfo_char_start = loc.loc_start.pos_cnum - loc.loc_start.pos_bol; dinfo_char_end = - if loc.loc_end.pos_fname = loc.loc_start.pos_fname + if valid_endpos then loc.loc_end.pos_cnum - loc.loc_start.pos_bol else loc.loc_start.pos_cnum - loc.loc_start.pos_bol; + dinfo_start_bol = loc.loc_start.pos_bol; + dinfo_end_bol = + if valid_endpos then loc.loc_end.pos_bol + else loc.loc_start.pos_bol; + dinfo_end_line = + if valid_endpos then loc.loc_end.pos_lnum + else loc.loc_start.pos_lnum; } let from_location loc = @@ -63,10 +76,15 @@ let to_location = function let loc_start = { pos_fname = d.dinfo_file; pos_lnum = d.dinfo_line; - pos_bol = 0; - pos_cnum = d.dinfo_char_start; + pos_bol = d.dinfo_start_bol; + pos_cnum = d.dinfo_start_bol + d.dinfo_char_start; + } in + let loc_end = + { pos_fname = d.dinfo_file; + pos_lnum = d.dinfo_end_line; + pos_bol = d.dinfo_end_bol; + pos_cnum = d.dinfo_start_bol + d.dinfo_char_end; } in - let loc_end = { loc_start with pos_cnum = d.dinfo_char_end; } in { loc_ghost = false; loc_start; loc_end; } let inline loc t = @@ -88,7 +106,7 @@ let compare dbg1 dbg2 = | _ :: _, [] -> 1 | [], _ :: _ -> -1 | d1 :: ds1, d2 :: ds2 -> - let c = compare d1.dinfo_file d2.dinfo_file in + let c = String.compare d1.dinfo_file d2.dinfo_file in if c <> 0 then c else let c = compare d1.dinfo_line d2.dinfo_line in if c <> 0 then c else @@ -96,6 +114,12 @@ let compare dbg1 dbg2 = if c <> 0 then c else let c = compare d1.dinfo_char_start d2.dinfo_char_start in if c <> 0 then c else + let c = compare d1.dinfo_start_bol d2.dinfo_start_bol in + if c <> 0 then c else + let c = compare d1.dinfo_end_bol d2.dinfo_end_bol in + if c <> 0 then c else + let c = compare d1.dinfo_end_line d2.dinfo_end_line in + if c <> 0 then c else loop ds1 ds2 in loop (List.rev dbg1) (List.rev dbg2) diff --git a/middle_end/debuginfo.mli b/middle_end/debuginfo.mli index 26a8bb19..4dc5e599 100644 --- a/middle_end/debuginfo.mli +++ b/middle_end/debuginfo.mli @@ -17,7 +17,10 @@ type item = private { dinfo_file: string; dinfo_line: int; dinfo_char_start: int; - dinfo_char_end: int + dinfo_char_end: int; + dinfo_start_bol: int; + dinfo_end_bol: int; + dinfo_end_line: int; } type t = item list diff --git a/middle_end/effect_analysis.ml b/middle_end/effect_analysis.ml index 011dee47..b5ab6186 100644 --- a/middle_end/effect_analysis.ml +++ b/middle_end/effect_analysis.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare let no_effects_prim (prim : Lambda.primitive) = match Semantics_of_primitives.for_primitive prim with diff --git a/middle_end/extract_projections.ml b/middle_end/extract_projections.ml index e00dd6de..33cd473e 100644 --- a/middle_end/extract_projections.ml +++ b/middle_end/extract_projections.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module A = Simple_value_approx module E = Inline_and_simplify_aux.Env diff --git a/middle_end/find_recursive_functions.ml b/middle_end/find_recursive_functions.ml index e701e096..e6943303 100644 --- a/middle_end/find_recursive_functions.ml +++ b/middle_end/find_recursive_functions.ml @@ -14,13 +14,16 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare let in_function_declarations (function_decls : Flambda.function_declarations) ~backend = let module VCC = Strongly_connected_components.Make (Variable) in let directed_graph = - Flambda_utils.fun_vars_referenced_in_decls function_decls ~backend + let module B = (val backend : Backend_intf.S) in + Flambda_utils.fun_vars_referenced_in_decls function_decls + ~closure_symbol:B.closure_symbol in let connected_components = VCC.connected_components_sorted_from_roots_to_leaf directed_graph diff --git a/middle_end/flambda.ml b/middle_end/flambda.ml index e781af20..a16b51a1 100644 --- a/middle_end/flambda.ml +++ b/middle_end/flambda.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare type call_kind = | Indirect @@ -242,7 +243,7 @@ let rec lam ppf (flam : t) = let print_kind ppf (kind : Lambda.value_kind) = match kind with | Pgenval -> () - | _ -> Format.fprintf ppf " %s" (Printlambda.value_kind kind) + | _ -> Format.fprintf ppf " %a" Printlambda.value_kind kind in fprintf ppf "@[<2>(let_mutable%a@ @[<2>%a@ %a@]@ %a)@]" print_kind contents_kind @@ -534,9 +535,9 @@ let rec variables_usage ?ignore_uses_as_callee ?ignore_uses_as_argument defining_expr; body; _ } -> bound_variable var; if all_used_variables - || ignore_uses_as_callee <> None - || ignore_uses_as_argument <> None - || ignore_uses_in_project_var <> None + || Misc.Stdlib.Option.is_some ignore_uses_as_callee + || Misc.Stdlib.Option.is_some ignore_uses_as_argument + || Misc.Stdlib.Option.is_some ignore_uses_in_project_var then begin (* In these cases we can't benefit from the pre-computed free variable sets. *) @@ -1184,7 +1185,7 @@ let used_params function_decl = let compare_const (c1:const) (c2:const) = match c1, c2 with | Int i1, Int i2 -> compare i1 i2 - | Char i1, Char i2 -> compare i1 i2 + | Char i1, Char i2 -> Char.compare i1 i2 | Const_pointer i1, Const_pointer i2 -> compare i1 i2 | Int _, (Char _ | Const_pointer _) -> -1 | (Char _ | Const_pointer _), Int _ -> 1 @@ -1249,6 +1250,12 @@ module Constant_defining_value = struct end) end +let equal_call_kind (call_kind1 : call_kind) (call_kind2 : call_kind) = + match call_kind1, call_kind2 with + | Indirect, Indirect -> true + | Direct cid1, Direct cid2 -> Closure_id.equal cid1 cid2 + | (Indirect | Direct _), _ -> false + let equal_specialised_to (spec_to1 : specialised_to) (spec_to2 : specialised_to) = Variable.equal spec_to1.var spec_to2.var diff --git a/middle_end/flambda.mli b/middle_end/flambda.mli index 00e9dd16..a301dd47 100755 --- a/middle_end/flambda.mli +++ b/middle_end/flambda.mli @@ -688,11 +688,21 @@ val print_specialised_to -> specialised_to -> unit +val equal_call_kind + : call_kind + -> call_kind + -> bool + val equal_specialised_to : specialised_to -> specialised_to -> bool +val compare_const + : const + -> const + -> int + val compare_project_var : project_var -> project_var -> int val compare_move_within_set_of_closures diff --git a/middle_end/flambda_invariants.ml b/middle_end/flambda_invariants.ml index 5c49a4b7..f236fd08 100755 --- a/middle_end/flambda_invariants.ml +++ b/middle_end/flambda_invariants.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-30-40-41-42"] +[@@@ocaml.warning "+a-4-30-40-41-42-66"] +open! Int_replace_polymorphic_compare type flambda_kind = | Normal @@ -463,7 +464,7 @@ let primitive_invariants flam ~no_access_to_global_module_identifiers = raise (Sequential_logical_operator_primitives_must_be_expanded prim) | Pgetglobal id -> if no_access_to_global_module_identifiers - && not (Ident.is_predef_exn id) then + && not (Ident.is_predef id) then begin raise (Access_to_global_module_identifier prim) end diff --git a/middle_end/flambda_iterators.ml b/middle_end/flambda_iterators.ml index 19f7d067..a69575da 100644 --- a/middle_end/flambda_iterators.ml +++ b/middle_end/flambda_iterators.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare let apply_on_subexpressions f f_named (flam : Flambda.t) = match flam with diff --git a/middle_end/flambda_utils.ml b/middle_end/flambda_utils.ml index e5d2b715..1bb3a2a8 100644 --- a/middle_end/flambda_utils.ml +++ b/middle_end/flambda_utils.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare let name_expr ~name (named : Flambda.named) : Flambda.t = let var = @@ -77,15 +78,13 @@ let description_of_toplevel_node (expr : Flambda.t) = | While _ -> "while" | For _ -> "for" -let compare_const (c1 : Flambda.const) (c2 : Flambda.const) = - match c1, c2 with - | Int v1, Int v2 -> compare v1 v2 - | Char v1, Char v2 -> compare v1 v2 - | Const_pointer v1, Const_pointer v2 -> compare v1 v2 - | Int _, _ -> -1 - | _, Int _ -> 1 - | Char _, _ -> -1 - | _, Char _ -> 1 +let equal_direction_flag + (x : Asttypes.direction_flag) + (y : Asttypes.direction_flag) = + match x, y with + | Upto, Upto -> true + | Downto, Downto -> true + | (Upto | Downto), _ -> false let rec same (l1 : Flambda.t) (l2 : Flambda.t) = l1 == l2 || (* it is ok for the string case: if they are physically the same, @@ -94,7 +93,7 @@ let rec same (l1 : Flambda.t) (l2 : Flambda.t) = | Var v1 , Var v2 -> Variable.equal v1 v2 | Var _, _ | _, Var _ -> false | Apply a1 , Apply a2 -> - a1.kind = a2.kind + Flambda.equal_call_kind a1.kind a2.kind && Variable.equal a1.func a2.func && Misc.Stdlib.List.equal Variable.equal a1.args a2.args | Apply _, _ | _, Apply _ -> false @@ -108,7 +107,7 @@ let rec same (l1 : Flambda.t) (l2 : Flambda.t) = -> Mutable_variable.equal mv1 mv2 && Variable.equal v1 v2 - && ck1 = ck2 + && Lambda.equal_value_kind ck1 ck2 && same b1 b2 | Let_mutable _, _ | _, Let_mutable _ -> false | Let_rec (bl1, a1), Let_rec (bl2, a2) -> @@ -120,7 +119,7 @@ let rec same (l1 : Flambda.t) (l2 : Flambda.t) = | String_switch (a1, s1, d1), String_switch (a2, s2, d2) -> Variable.equal a1 a2 && Misc.Stdlib.List.equal - (fun (s1, e1) (s2, e2) -> s1 = s2 && same e1 e2) s1 s2 + (fun (s1, e1) (s2, e2) -> String.equal s1 s2 && same e1 e2) s1 s2 && Misc.Stdlib.Option.equal same d1 d2 | String_switch _, _ | _, String_switch _ -> false | Static_raise (e1, a1), Static_raise (e2, a2) -> @@ -148,7 +147,7 @@ let rec same (l1 : Flambda.t) (l2 : Flambda.t) = Variable.equal bound_var1 bound_var2 && Variable.equal from_value1 from_value2 && Variable.equal to_value1 to_value2 - && direction1 = direction2 + && equal_direction_flag direction1 direction2 && same body1 body2 | For _, _ | _, For _ -> false | Assign { being_assigned = being_assigned1; new_value = new_value1; }, @@ -158,7 +157,7 @@ let rec same (l1 : Flambda.t) (l2 : Flambda.t) = | Assign _, _ | _, Assign _ -> false | Send { kind = kind1; meth = meth1; obj = obj1; args = args1; dbg = _; }, Send { kind = kind2; meth = meth2; obj = obj2; args = args2; dbg = _; } -> - kind1 = kind2 + Lambda.equal_meth_kind kind1 kind2 && Variable.equal meth1 meth2 && Variable.equal obj1 obj2 && Misc.Stdlib.List.equal Variable.equal args1 args2 @@ -169,7 +168,7 @@ and same_named (named1 : Flambda.named) (named2 : Flambda.named) = match named1, named2 with | Symbol s1 , Symbol s2 -> Symbol.equal s1 s2 | Symbol _, _ | _, Symbol _ -> false - | Const c1, Const c2 -> compare_const c1 c2 = 0 + | Const c1, Const c2 -> Flambda.compare_const c1 c2 = 0 | Const _, _ | _, Const _ -> false | Allocated_const c1, Allocated_const c2 -> Allocated_const.compare c1 c2 = 0 @@ -193,7 +192,8 @@ and same_named (named1 : Flambda.named) (named2 : Flambda.named) = | Move_within_set_of_closures _, _ | _, Move_within_set_of_closures _ -> false | Prim (p1, al1, _), Prim (p2, al2, _) -> - p1 = p2 && Misc.Stdlib.List.equal Variable.equal al1 al2 + Lambda.equal_primitive p1 p2 + && Misc.Stdlib.List.equal Variable.equal al1 al2 | Prim _, _ | _, Prim _ -> false | Expr e1, Expr e2 -> same e1 e2 @@ -226,8 +226,8 @@ and samebinding (v1, n1) (v2, n2) = and sameswitch (fs1 : Flambda.switch) (fs2 : Flambda.switch) = let samecase (n1, a1) (n2, a2) = n1 = n2 && same a1 a2 in - fs1.numconsts = fs2.numconsts - && fs1.numblocks = fs2.numblocks + Numbers.Int.Set.equal fs1.numconsts fs2.numconsts + && Numbers.Int.Set.equal fs1.numblocks fs2.numblocks && Misc.Stdlib.List.equal samecase fs1.consts fs2.consts && Misc.Stdlib.List.equal samecase fs1.blocks fs2.blocks && Misc.Stdlib.Option.equal same fs1.failaction fs2.failaction @@ -797,14 +797,14 @@ module Switch_storer = Switch.Store (struct | Symbol s1, Symbol s2 -> Symbol.compare s1 s2 | Symbol _, (Const _ | Expr _ | Prim _) -> -1 | (Const _ | Expr _ | Prim _), Symbol _ -> 1 - | Const c1, Const c2 -> compare c1 c2 + | Const c1, Const c2 -> Flambda.compare_const c1 c2 | Const _, (Expr _ | Prim _) -> -1 | (Expr _ | Prim _), Const _ -> 1 | Expr e1, Expr e2 -> compare_expr env e1 e2 | Expr _, Prim _ -> -1 | Prim _, Expr _ -> 1 | Prim (prim1, args1), Prim (prim2, args2) -> - let comp_prim = Pervasives.compare prim1 prim2 in + let comp_prim = Stdlib.compare prim1 prim2 in if comp_prim <> 0 then comp_prim else Misc.Stdlib.List.compare (compare_var env) args1 args2 in @@ -812,13 +812,12 @@ module Switch_storer = Switch.Store (struct end) let fun_vars_referenced_in_decls - (function_decls : Flambda.function_declarations) ~backend = + (function_decls : Flambda.function_declarations) ~closure_symbol = let fun_vars = Variable.Map.keys function_decls.funs in let symbols_to_fun_vars = - let module Backend = (val backend : Backend_intf.S) in Variable.Set.fold (fun fun_var symbols_to_fun_vars -> let closure_id = Closure_id.wrap fun_var in - let symbol = Backend.closure_symbol closure_id in + let symbol = closure_symbol closure_id in Symbol.Map.add symbol fun_var symbols_to_fun_vars) fun_vars Symbol.Map.empty @@ -840,10 +839,10 @@ let fun_vars_referenced_in_decls Variable.Set.union from_symbols from_variables) function_decls.funs -let closures_required_by_entry_point ~(entry_point : Closure_id.t) ~backend - (function_decls : Flambda.function_declarations) = +let closures_required_by_entry_point ~(entry_point : Closure_id.t) + ~closure_symbol (function_decls : Flambda.function_declarations) = let dependencies = - fun_vars_referenced_in_decls function_decls ~backend + fun_vars_referenced_in_decls function_decls ~closure_symbol in let set = ref Variable.Set.empty in let queue = Queue.create () in diff --git a/middle_end/flambda_utils.mli b/middle_end/flambda_utils.mli index 34a33db0..0f7b3186 100644 --- a/middle_end/flambda_utils.mli +++ b/middle_end/flambda_utils.mli @@ -98,8 +98,6 @@ val name_expr_from_var -> Flambda.named -> Flambda.t -val compare_const : Flambda.const -> Flambda.const -> int - val initialize_symbols : Flambda.program -> (Symbol.t * Tag.t * Flambda.t list) list @@ -180,14 +178,14 @@ end *) val fun_vars_referenced_in_decls : Flambda.function_declarations - -> backend:(module Backend_intf.S) + -> closure_symbol:(Closure_id.t -> Symbol.t) -> Variable.Set.t Variable.Map.t (** Computes the set of closure_id in the set of closures that are required used (transitively) the entry_point *) val closures_required_by_entry_point : entry_point:Closure_id.t - -> backend:(module Backend_intf.S) + -> closure_symbol:(Closure_id.t -> Symbol.t) -> Flambda.function_declarations -> Variable.Set.t diff --git a/middle_end/freshening.ml b/middle_end/freshening.ml index 839d5414..891861a3 100644 --- a/middle_end/freshening.ml +++ b/middle_end/freshening.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare type tbl = { sb_var : Variable.t Variable.Map.t; @@ -67,6 +68,10 @@ let print ppf = function let empty = Inactive +let is_empty = function + | Inactive -> true + | Active _ -> false + let empty_preserving_activation_state = function | Inactive -> Inactive | Active _ -> Active empty_tbl diff --git a/middle_end/freshening.mli b/middle_end/freshening.mli index 6af21415..1550797a 100644 --- a/middle_end/freshening.mli +++ b/middle_end/freshening.mli @@ -26,6 +26,8 @@ type subst = t freshening. *) val empty : t +val is_empty : t -> bool + (** Activate the freshening. Without activation, operations to request freshenings have no effect (cf. the documentation below for [add_variable]). As such, the inactive renaming is unique. *) diff --git a/middle_end/inconstant_idents.ml b/middle_end/inconstant_idents.ml index dde1cba1..3d8ba904 100755 --- a/middle_end/inconstant_idents.ml +++ b/middle_end/inconstant_idents.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare (* This cannot be done in a single simple pass due to expressions like: diff --git a/middle_end/initialize_symbol_to_let_symbol.ml b/middle_end/initialize_symbol_to_let_symbol.ml index 634c68ad..31246b0d 100644 --- a/middle_end/initialize_symbol_to_let_symbol.ml +++ b/middle_end/initialize_symbol_to_let_symbol.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare let constant_field (expr:Flambda.t) : Flambda.constant_defining_value_block_field option = diff --git a/middle_end/inline_and_simplify.ml b/middle_end/inline_and_simplify.ml index c25d3f5f..c1e6ff56 100755 --- a/middle_end/inline_and_simplify.ml +++ b/middle_end/inline_and_simplify.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module A = Simple_value_approx module B = Inlining_cost.Benefit @@ -524,7 +525,7 @@ let rec simplify_project_var env r ~(project_var : Flambda.project_var) The rewriting occurs in an environment filled with: * The approximation of the free variables - * An explicitely unknown approximation for function parameters, + * An explicitly unknown approximation for function parameters, except for those where it is known to be safe: those present in the [specialised_args] set. * An approximation for the closures in the set. It contains the code of @@ -936,7 +937,8 @@ and simplify_named env r (tree : Flambda.named) : Flambda.named * R.t = the [Unbox_closures] output, this also prevents applying [Unbox_closures] over and over.) *) let set_of_closures = - match Remove_free_vars_equal_to_args.run set_of_closures with + let ppf_dump = Inline_and_simplify_aux.Env.ppf_dump env in + match Remove_free_vars_equal_to_args.run ~ppf_dump set_of_closures with | None -> set_of_closures | Some set_of_closures -> set_of_closures in @@ -1361,7 +1363,7 @@ and simplify env r (tree : Flambda.t) : Flambda.t * R.t = String_switch (arg, sw, def), ret r (A.value_unknown Other) | Some arg_string -> let branch = - match List.find (fun (str, _) -> str = arg_string) sw with + match List.find (fun (str, _) -> String.equal str arg_string) sw with | (_, branch) -> branch | exception Not_found -> match def with @@ -1455,7 +1457,7 @@ let constant_defining_value_approx (* At toplevel, there is no freshening currently happening (this cannot be the body of a currently inlined function), so we can keep the original set_of_closures in the approximation. *) - assert(E.freshening env = Freshening.empty); + assert(Freshening.is_empty (E.freshening env)); assert(Variable.Map.is_empty free_vars); assert(Variable.Map.is_empty specialised_args); let invariant_params = @@ -1664,7 +1666,7 @@ let simplify_program env r (program : Flambda.program) = let add_predef_exns_to_environment ~env ~backend = let module Backend = (val backend : Backend_intf.S) in List.fold_left (fun env predef_exn -> - assert (Ident.is_predef_exn predef_exn); + assert (Ident.is_predef predef_exn); let symbol = Backend.symbol_for_global' predef_exn in let name = Ident.name predef_exn in let approx = @@ -1677,13 +1679,13 @@ let add_predef_exns_to_environment ~env ~backend = env Predef.all_predef_exns -let run ~never_inline ~backend ~prefixname ~round program = +let run ~never_inline ~backend ~prefixname ~round ~ppf_dump program = let r = R.create () in let report = !Clflags.inlining_report in if never_inline then Clflags.inlining_report := false; let initial_env = add_predef_exns_to_environment - ~env:(E.create ~never_inline ~backend ~round) + ~env:(E.create ~never_inline ~backend ~round ~ppf_dump) ~backend in let result, r = simplify_program initial_env r program in diff --git a/middle_end/inline_and_simplify.mli b/middle_end/inline_and_simplify.mli index ad0845e2..9a8e6e8b 100644 --- a/middle_end/inline_and_simplify.mli +++ b/middle_end/inline_and_simplify.mli @@ -27,6 +27,7 @@ val run -> backend:(module Backend_intf.S) -> prefixname:string -> round:int + -> ppf_dump:Format.formatter -> Flambda.program -> Flambda.program diff --git a/middle_end/inline_and_simplify_aux.ml b/middle_end/inline_and_simplify_aux.ml index 39cb54f0..bb725e8c 100644 --- a/middle_end/inline_and_simplify_aux.ml +++ b/middle_end/inline_and_simplify_aux.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module Env = struct type scope = Current | Outer @@ -22,6 +23,7 @@ module Env = struct type t = { backend : (module Backend_intf.S); round : int; + ppf_dump : Format.formatter; approx : (scope * Simple_value_approx.t) Variable.Map.t; approx_mutable : Simple_value_approx.t Mutable_variable.Map.t; approx_sym : Simple_value_approx.t Symbol.Map.t; @@ -44,9 +46,10 @@ module Env = struct inlined_debuginfo : Debuginfo.t; } - let create ~never_inline ~backend ~round = + let create ~never_inline ~backend ~round ~ppf_dump = { backend; round; + ppf_dump; approx = Variable.Map.empty; approx_mutable = Mutable_variable.Map.empty; approx_sym = Symbol.Map.empty; @@ -69,6 +72,7 @@ module Env = struct let backend t = t.backend let round t = t.round + let ppf_dump t = t.ppf_dump let local env = { env with diff --git a/middle_end/inline_and_simplify_aux.mli b/middle_end/inline_and_simplify_aux.mli index 43619b2f..79d84a31 100755 --- a/middle_end/inline_and_simplify_aux.mli +++ b/middle_end/inline_and_simplify_aux.mli @@ -33,6 +33,7 @@ module Env : sig : never_inline:bool -> backend:(module Backend_intf.S) -> round:int + -> ppf_dump:Format.formatter -> t (** Obtain the first-class module that gives information about the @@ -47,6 +48,9 @@ module Env : sig (** Which simplification round we are currently in. *) val round : t -> int + (** Where to print intermediate asts and similar debug information *) + val ppf_dump : t -> Format.formatter + (** Add the approximation of a variable---that is to say, some knowledge about the value(s) the variable may take on at runtime---to the environment. *) diff --git a/middle_end/inlining_cost.ml b/middle_end/inlining_cost.ml index d288316a..f2af293f 100644 --- a/middle_end/inlining_cost.ml +++ b/middle_end/inlining_cost.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare (* Simple approximation of the space cost of a primitive. *) @@ -176,6 +177,14 @@ module Threshold = struct | Can_inline_if_no_larger_than i1, Can_inline_if_no_larger_than i2 -> Can_inline_if_no_larger_than (min i1 i2) + let equal t1 t2 = + match t1, t2 with + | Never_inline, Never_inline -> true + | Can_inline_if_no_larger_than i1, Can_inline_if_no_larger_than i2 -> + i1 = i2 + | (Never_inline | Can_inline_if_no_larger_than _), _ -> + false + end let can_try_inlining lam inlining_threshold ~number_of_arguments @@ -201,7 +210,9 @@ let can_try_inlining lam inlining_threshold ~number_of_arguments (inlining_threshold - size + bonus) let lambda_smaller lam ~than = - lambda_smaller' lam ~than <> None + match lambda_smaller' lam ~than with + | Some _ -> true + | None -> false let can_inline lam inlining_threshold ~bonus = match inlining_threshold with @@ -421,9 +432,14 @@ module Whether_sufficient_benefit = struct new_size; evaluated_benefit; estimate = true; } + let is_nan f = + match Float.classify_float f with + | FP_nan -> true + | FP_normal | FP_subnormal | FP_zero | FP_infinite -> false + let correct_branch_factor f = - f = f (* is not nan *) - && f >= 0. + (not (is_nan f)) + && (Float.compare f 0. >= 0) let estimated_benefit t = if t.toplevel && t.lifting && t.branch_depth = 0 then begin @@ -448,9 +464,9 @@ module Whether_sufficient_benefit = struct Clflags.Float_arg_helper.get ~key:t.round !Clflags.inline_branch_factor in - if not (factor = factor) (* nan *) then + if is_nan factor then Clflags.default_inline_branch_factor - else if factor < 0. then + else if Float.compare factor 0. < 0 then 0. else factor @@ -465,7 +481,9 @@ module Whether_sufficient_benefit = struct end let evaluate t = - float t.new_size -. estimated_benefit t <= float t.original_size + Float.compare + (float t.new_size -. estimated_benefit t) + (float t.original_size) <= 0 let to_string t = let lifting = t.toplevel && t.lifting && t.branch_depth = 0 in diff --git a/middle_end/inlining_cost.mli b/middle_end/inlining_cost.mli index 72327602..345f67ab 100644 --- a/middle_end/inlining_cost.mli +++ b/middle_end/inlining_cost.mli @@ -30,6 +30,7 @@ module Threshold : sig val add : t -> t -> t val sub : t -> t -> t val min : t -> t -> t + val equal : t -> t -> bool end diff --git a/middle_end/inlining_decision.ml b/middle_end/inlining_decision.ml index b8ac437a..ca462a56 100755 --- a/middle_end/inlining_decision.ml +++ b/middle_end/inlining_decision.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module A = Simple_value_approx module E = Inline_and_simplify_aux.Env @@ -97,7 +98,7 @@ let inline env r ~lhs_of_application else if not (E.unrolling_allowed env set_of_closures_origin) && (Lazy.force recursive) then Don't_try_it S.Not_inlined.Unrolling_depth_exceeded - else if remaining_inlining_threshold = T.Never_inline then + else if T.equal remaining_inlining_threshold T.Never_inline then let threshold = match inlining_threshold with | T.Never_inline -> assert false @@ -348,7 +349,7 @@ let specialise env r ~lhs_of_application Try_it else if never_specialise then Don't_try_it S.Not_specialised.Annotation - else if remaining_inlining_threshold = T.Never_inline then + else if T.equal remaining_inlining_threshold T.Never_inline then let threshold = match inlining_threshold with | T.Never_inline -> assert false @@ -492,7 +493,8 @@ let for_call_site ~env ~r ~(function_decls : A.function_declarations) | Some _ -> Default_inline | None -> inline_requested end - | Always_inline | Default_inline | Never_inline -> inline_requested + | Always_inline | Default_inline | Never_inline -> + inline_requested in let original = Flambda.Apply { @@ -541,10 +543,11 @@ let for_call_site ~env ~r ~(function_decls : A.function_declarations) let try_inlining = if self_call then Don't_try_it S.Not_inlined.Self_call - else if not (E.inlining_allowed env function_decl.closure_origin) then - Don't_try_it S.Not_inlined.Unrolling_depth_exceeded else - Try_it + if not (E.inlining_allowed env function_decl.closure_origin) then + Don't_try_it S.Not_inlined.Unrolling_depth_exceeded + else + Try_it in match try_inlining with | Don't_try_it decision -> Original decision @@ -553,17 +556,20 @@ let for_call_site ~env ~r ~(function_decls : A.function_declarations) let body, r = Inlining_transforms.inline_by_copying_function_body ~env ~r ~function_body ~lhs_of_application - ~closure_id_being_applied ~specialise_requested ~inline_requested - ~function_decl ~fun_vars ~args ~dbg ~simplify + ~closure_id_being_applied ~specialise_requested + ~inline_requested ~function_decl ~fun_vars ~args ~dbg ~simplify in let env = E.note_entering_inlined env in let env = (* We decrement the unrolling count even if the function is not recursive to avoid having to check whether or not it is recursive *) - E.inside_unrolled_function env function_decls.set_of_closures_origin + E.inside_unrolled_function env + function_decls.set_of_closures_origin + in + let env = + E.inside_inlined_function env function_decl.closure_origin in - let env = E.inside_inlined_function env function_decl.closure_origin in Changed ((simplify env r body), S.Inlined.Classic_mode) in let res, decision = @@ -619,7 +625,8 @@ let for_call_site ~env ~r ~(function_decls : A.function_declarations) Inline_and_simplify_aux.initial_inlining_toplevel_threshold ~round:(E.round env) else - Inline_and_simplify_aux.initial_inlining_threshold ~round:(E.round env) + Inline_and_simplify_aux.initial_inlining_threshold + ~round:(E.round env) in let unthrottled_inlining_threshold = match raw_inlining_threshold with @@ -680,12 +687,14 @@ let for_call_site ~env ~r ~(function_decls : A.function_declarations) let size_from_approximation = let fun_var = Closure_id.unwrap closure_id_being_applied in match - Variable.Map.find fun_var (Lazy.force value_set_of_closures.size) + Variable.Map.find fun_var + (Lazy.force value_set_of_closures.size) with | size -> size | exception Not_found -> Misc.fatal_errorf "Approximation does not give a size for the \ - function having fun_var %a. value_set_of_closures: %a" + function having fun_var %a. \ + value_set_of_closures: %a" Variable.print fun_var A.print_value_set_of_closures value_set_of_closures in diff --git a/middle_end/inlining_stats.ml b/middle_end/inlining_stats.ml index 0c7cc033..6809d4cb 100644 --- a/middle_end/inlining_stats.ml +++ b/middle_end/inlining_stats.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module Closure_stack = struct type t = node list diff --git a/middle_end/inlining_stats_types.ml b/middle_end/inlining_stats_types.ml index 801ed84b..7aef0796 100644 --- a/middle_end/inlining_stats_types.ml +++ b/middle_end/inlining_stats_types.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module Wsb = Inlining_cost.Whether_sufficient_benefit diff --git a/middle_end/inlining_transforms.ml b/middle_end/inlining_transforms.ml index b905c50b..b08e62bb 100755 --- a/middle_end/inlining_transforms.ml +++ b/middle_end/inlining_transforms.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module B = Inlining_cost.Benefit module E = Inline_and_simplify_aux.Env @@ -107,9 +108,14 @@ let inline_by_copying_function_body ~env ~r ~function_decl ~function_body in let body = - if function_body.stub && - ((inline_requested <> Lambda.Default_inline) - || (specialise_requested <> Lambda.Default_specialise)) then + let default_inline = + Lambda.equal_inline_attribute inline_requested Default_inline + in + let default_specialise = + Lambda.equal_specialise_attribute specialise_requested Default_specialise + in + if function_body.stub + && ((not default_inline) || (not default_specialise)) then (* When the function inlined function is a stub, the annotation is reported to the function applications inside the stub. This allows to report the annotation to the application the @@ -185,7 +191,7 @@ type state = { (* List of functions that still need to be copied to the new set of closures *) new_funs : Flambda.function_declaration Variable.Map.t; - (* The function declerations for the new set of closures *) + (* The function declarations for the new set of closures *) new_free_vars_with_old_projections : Flambda.specialised_to Variable.Map.t; (* The free variables for the new set of closures, but the projection fields still point to old free variables. *) @@ -508,8 +514,8 @@ let rewrite_function ~lhs_of_application ~closure_id_being_applied match expr with | Apply ({ kind = Direct closure_id } as apply) -> begin match - rewrite_direct_call ~specialised_args ~funs ~direct_call_surrogates - ~state:!state_ref ~closure_id ~apply + rewrite_direct_call ~specialised_args ~funs + ~direct_call_surrogates ~state:!state_ref ~closure_id ~apply with | None -> expr | Some (state, expr) -> diff --git a/middle_end/int_replace_polymorphic_compare.ml b/middle_end/int_replace_polymorphic_compare.ml new file mode 100644 index 00000000..7cd6bf10 --- /dev/null +++ b/middle_end/int_replace_polymorphic_compare.ml @@ -0,0 +1,8 @@ +let ( = ) : int -> int -> bool = Stdlib.( = ) +let ( <> ) : int -> int -> bool = Stdlib.( <> ) +let ( < ) : int -> int -> bool = Stdlib.( < ) +let ( > ) : int -> int -> bool = Stdlib.( > ) +let ( <= ) : int -> int -> bool = Stdlib.( <= ) +let ( >= ) : int -> int -> bool = Stdlib.( >= ) + +let compare : int -> int -> int = Stdlib.compare diff --git a/middle_end/int_replace_polymorphic_compare.mli b/middle_end/int_replace_polymorphic_compare.mli new file mode 100644 index 00000000..689e741b --- /dev/null +++ b/middle_end/int_replace_polymorphic_compare.mli @@ -0,0 +1,8 @@ +val ( = ) : int -> int -> bool +val ( <> ) : int -> int -> bool +val ( < ) : int -> int -> bool +val ( > ) : int -> int -> bool +val ( <= ) : int -> int -> bool +val ( >= ) : int -> int -> bool + +val compare : int -> int -> int diff --git a/middle_end/internal_variable_names.ml b/middle_end/internal_variable_names.ml index 93ce10f7..ee400856 100644 --- a/middle_end/internal_variable_names.ml +++ b/middle_end/internal_variable_names.ml @@ -12,11 +12,11 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare type t = string -let anon_fn = "anon_fn" let apply_arg = "apply_arg" let apply_funct = "apply_funct" let block_symbol = "block_symbol" @@ -290,12 +290,15 @@ let toplevel_substitution_named = "toplevel_substitution_named" let unbox_free_vars_of_closures = "unbox_free_vars_of_closures" let zero = "zero" -let anon_fn_with_loc_fmt = format_of_string "anon_fn[%a]" -let anon_fn_with_loc loc = - if loc = Location.none then anon_fn - else begin - Format.asprintf anon_fn_with_loc_fmt Location.print_compact loc - end +let anon_fn_with_loc (loc: Location.t) = + let (file, line, startchar) = Location.get_pos_info loc.loc_start in + let endchar = loc.loc_end.pos_cnum - loc.loc_start.pos_bol in + let pp_chars ppf = + if startchar >= 0 then Format.fprintf ppf ",%i--%i" startchar endchar in + if loc.Location.loc_ghost then "anon_fn" + else + Format.asprintf "anon_fn[%a:%i%t]" + Location.print_filename file line pp_chars let of_primitive : Lambda.primitive -> string = function | Pidentity -> pidentity diff --git a/middle_end/invariant_params.ml b/middle_end/invariant_params.ml index 065ab22c..a43cfdac 100755 --- a/middle_end/invariant_params.ml +++ b/middle_end/invariant_params.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare (* CR-someday pchambart to pchambart: in fact partial application doesn't work because there are no 'known' partial application left: they are diff --git a/middle_end/lift_code.ml b/middle_end/lift_code.ml index 070bde9e..02292c46 100644 --- a/middle_end/lift_code.ml +++ b/middle_end/lift_code.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare type lifter = Flambda.program -> Flambda.program diff --git a/middle_end/lift_constants.ml b/middle_end/lift_constants.ml index c5f78235..dd60de9c 100644 --- a/middle_end/lift_constants.ml +++ b/middle_end/lift_constants.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare (* CR-someday mshinwell: move to Flambda_utils *) let rec tail_variable : Flambda.t -> Variable.t option = function @@ -526,7 +527,7 @@ let constant_dependencies ~backend:_ | Allocated_const _ -> Symbol.Set.empty | Block (_, fields) -> let symbol_fields = - Misc.Stdlib.List.filter_map + List.filter_map (function | (Symbol s : Flambda.constant_defining_value_block_field) -> Some s | Flambda.Const _ -> None) diff --git a/middle_end/lift_let_to_initialize_symbol.ml b/middle_end/lift_let_to_initialize_symbol.ml index 169d5e0d..ccef0d8a 100644 --- a/middle_end/lift_let_to_initialize_symbol.ml +++ b/middle_end/lift_let_to_initialize_symbol.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare type ('a, 'b) kind = | Initialisation of (Symbol.t * Tag.t * Flambda.t list) diff --git a/middle_end/middle_end.ml b/middle_end/middle_end.ml index 02720645..e604a328 100644 --- a/middle_end/middle_end.ml +++ b/middle_end/middle_end.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare let _dump_function_sizes flam ~backend = let module Backend = (val backend : Backend_intf.S) in @@ -30,29 +31,29 @@ let _dump_function_sizes flam ~backend = | None -> assert false) set_of_closures.function_decls.funs) -let middle_end ppf ~prefixname ~backend +let middle_end ~ppf_dump ~prefixname ~backend ~size ~filename ~module_ident ~module_initializer = Profile.record_call "flambda" (fun () -> - let previous_warning_printer = !Location.warning_printer in + let previous_warning_reporter = !Location.warning_reporter in let module WarningSet = Set.Make (struct type t = Location.t * Warnings.t - let compare = Pervasives.compare + let compare = Stdlib.compare end) in let warning_set = ref WarningSet.empty in - let flambda_warning_printer loc _fmt w = + let flambda_warning_reporter loc w = let elt = loc, w in if not (WarningSet.mem elt !warning_set) then begin warning_set := WarningSet.add elt !warning_set; - previous_warning_printer loc !Location.formatter_for_warnings w - end; + previous_warning_reporter loc w + end else None in Misc.protect_refs - [Misc.R (Location.warning_printer, flambda_warning_printer)] + [Misc.R (Location.warning_reporter, flambda_warning_reporter)] (fun () -> let pass_number = ref 0 in let round_number = ref 0 in @@ -68,10 +69,10 @@ let middle_end ppf ~prefixname ~backend let (+-+) flam (name, pass) = incr pass_number; if !Clflags.dump_flambda_verbose then begin - Format.fprintf ppf "@.PASS: %s@." name; - Format.fprintf ppf "Before pass %d, round %d:@ %a@." !pass_number - !round_number Flambda.print_program flam; - Format.eprintf "\n@?" + Format.fprintf ppf_dump "@.PASS: %s@." name; + Format.fprintf ppf_dump "Before pass %d, round %d:@ %a@." + !pass_number !round_number Flambda.print_program flam; + Format.fprintf ppf_dump "\n@?" end; let flam = Profile.record ~accumulate:true name pass flam in if !Clflags.flambda_invariant_checks then begin @@ -89,7 +90,7 @@ let middle_end ppf ~prefixname ~backend in if !Clflags.dump_rawflambda then - Format.fprintf ppf "After closure conversion:@ %a@." + Format.fprintf ppf_dump "After closure conversion:@ %a@." Flambda.print_program flam; check flam; let fast_mode flam = @@ -103,7 +104,7 @@ let middle_end ppf ~prefixname ~backend Lift_let_to_initialize_symbol.lift ~backend) +-+ ("Inline_and_simplify", Inline_and_simplify.run ~never_inline:false ~backend - ~prefixname ~round) + ~prefixname ~round ~ppf_dump) +-+ ("Remove_unused_closure_vars 2", Remove_unused_closure_vars.remove_unused_closure_variables ~remove_direct_call_surrogates:false) @@ -125,7 +126,7 @@ let middle_end ppf ~prefixname ~backend +-+ ("Lift_constants", Lift_constants.lift_constants ~backend) +-+ ("Share_constants", Share_constants.share_constants) +-+ ("Remove_unused_program_constructs", - Remove_unused_program_constructs.remove_unused_program_constructs) + Remove_unused_program_constructs.remove_unused_program_constructs) +-+ ("Lift_let_to_initialize_symbol", Lift_let_to_initialize_symbol.lift ~backend) +-+ ("lift_lets 2", Lift_code.lift_lets) @@ -134,14 +135,14 @@ let middle_end ppf ~prefixname ~backend ~remove_direct_call_surrogates:false) +-+ ("Inline_and_simplify", Inline_and_simplify.run ~never_inline:false ~backend - ~prefixname ~round) + ~prefixname ~round ~ppf_dump) +-+ ("Remove_unused_closure_vars 2", Remove_unused_closure_vars.remove_unused_closure_variables ~remove_direct_call_surrogates:false) +-+ ("lift_lets 3", Lift_code.lift_lets) +-+ ("Inline_and_simplify noinline", Inline_and_simplify.run ~never_inline:true ~backend - ~prefixname ~round) + ~prefixname ~round ~ppf_dump) +-+ ("Remove_unused_closure_vars 3", Remove_unused_closure_vars.remove_unused_closure_variables ~remove_direct_call_surrogates:false) @@ -159,7 +160,7 @@ let middle_end ppf ~prefixname ~backend +-+ ("Lift_constants", Lift_constants.lift_constants ~backend) +-+ ("Share_constants", Share_constants.share_constants) +-+ ("Remove_unused_program_constructs", - Remove_unused_program_constructs.remove_unused_program_constructs) + Remove_unused_program_constructs.remove_unused_program_constructs) in let flam = if !Clflags.classic_inlining then @@ -190,7 +191,7 @@ let middle_end ppf ~prefixname ~backend was being applied)")); if !Clflags.dump_flambda then - Format.fprintf ppf "End of middle end:@ %a@." + Format.fprintf ppf_dump "End of middle end:@ %a@." Flambda.print_program flam; check flam; (* CR-someday mshinwell: add -d... option for this *) diff --git a/middle_end/middle_end.mli b/middle_end/middle_end.mli index 0f715b9d..584cb45a 100644 --- a/middle_end/middle_end.mli +++ b/middle_end/middle_end.mli @@ -19,7 +19,7 @@ (* Translate Lambda code to Flambda code and then optimize it. *) val middle_end - : Format.formatter + : ppf_dump:Format.formatter -> prefixname:string -> backend:(module Backend_intf.S) -> size:int diff --git a/middle_end/parameter.ml b/middle_end/parameter.ml index 020fb5b1..0c916dd7 100644 --- a/middle_end/parameter.ml +++ b/middle_end/parameter.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare [@@@ocaml.warning "+9"] (* Warning 9 is enabled to ensure correct update of each function when diff --git a/middle_end/pass_wrapper.ml b/middle_end/pass_wrapper.ml index 0907583e..a2005332 100644 --- a/middle_end/pass_wrapper.ml +++ b/middle_end/pass_wrapper.ml @@ -14,21 +14,22 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare let register ~pass_name = Clflags.all_passes := pass_name :: !Clflags.all_passes -let with_dump ~pass_name ~f ~input ~print_input ~print_output = +let with_dump ~ppf_dump ~pass_name ~f ~input ~print_input ~print_output = let dump = Clflags.dumped_pass pass_name in let result = f () in match result with | None -> - if dump then Format.eprintf "%s: no-op.\n\n%!" pass_name; + if dump then Format.fprintf ppf_dump "%s: no-op.\n\n%!" pass_name; None | Some result -> if dump then begin - Format.eprintf "Before %s:@ %a@.@." pass_name print_input input; - Format.eprintf "After %s:@ %a@.@." pass_name print_output result + Format.fprintf ppf_dump "Before %s:@ %a@.@." pass_name print_input input; + Format.fprintf ppf_dump "After %s:@ %a@.@." pass_name print_output result; end; Some result diff --git a/middle_end/pass_wrapper.mli b/middle_end/pass_wrapper.mli index a6d3bf9d..3a30e61d 100644 --- a/middle_end/pass_wrapper.mli +++ b/middle_end/pass_wrapper.mli @@ -17,7 +17,8 @@ val register : pass_name:string -> unit val with_dump - : pass_name:string + : ppf_dump:Format.formatter + -> pass_name:string -> f:(unit -> 'b option) -> input:'a -> print_input:(Format.formatter -> 'a -> unit) diff --git a/middle_end/projection.ml b/middle_end/projection.ml index 8183727d..2c660a2a 100644 --- a/middle_end/projection.ml +++ b/middle_end/projection.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare (* CR-someday mshinwell: Move these three types into their own modules. *) diff --git a/middle_end/ref_to_variables.ml b/middle_end/ref_to_variables.ml index f21ffb1a..f93948f9 100644 --- a/middle_end/ref_to_variables.ml +++ b/middle_end/ref_to_variables.ml @@ -14,10 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] - - (* Variable.rename var *) - (* ~current_compilation_unit:(Compilation_unit.get_current_exn ()) *) +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare let variables_not_used_as_local_reference (tree:Flambda.t) = let set = ref Variable.Set.empty in diff --git a/middle_end/remove_free_vars_equal_to_args.ml b/middle_end/remove_free_vars_equal_to_args.ml index fdb38ff4..6327d30c 100755 --- a/middle_end/remove_free_vars_equal_to_args.ml +++ b/middle_end/remove_free_vars_equal_to_args.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare let pass_name = "remove-free-vars-equal-to-args" let () = Pass_wrapper.register ~pass_name @@ -91,8 +92,8 @@ let rewrite_one_set_of_closures (set_of_closures : Flambda.set_of_closures) = in Some set_of_closures -let run set_of_closures = - Pass_wrapper.with_dump ~pass_name ~input:set_of_closures +let run ~ppf_dump set_of_closures = + Pass_wrapper.with_dump ~ppf_dump ~pass_name ~input:set_of_closures ~print_input:Flambda.print_set_of_closures ~print_output:Flambda.print_set_of_closures ~f:(fun () -> rewrite_one_set_of_closures set_of_closures) diff --git a/middle_end/remove_free_vars_equal_to_args.mli b/middle_end/remove_free_vars_equal_to_args.mli index ae92d44d..49f25ac1 100644 --- a/middle_end/remove_free_vars_equal_to_args.mli +++ b/middle_end/remove_free_vars_equal_to_args.mli @@ -17,4 +17,7 @@ (** Replace free variables in closures known to be equal to specialised arguments of such closures with those specialised arguments. *) -val run : Flambda.set_of_closures -> Flambda.set_of_closures option +val run + : ppf_dump:Format.formatter + -> Flambda.set_of_closures + -> Flambda.set_of_closures option diff --git a/middle_end/remove_unused_arguments.ml b/middle_end/remove_unused_arguments.ml index ea276b68..f70da729 100644 --- a/middle_end/remove_unused_arguments.ml +++ b/middle_end/remove_unused_arguments.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare let pass_name = "remove-unused-arguments" let () = Clflags.all_passes := pass_name :: !Clflags.all_passes diff --git a/middle_end/remove_unused_closure_vars.ml b/middle_end/remove_unused_closure_vars.ml index 90036d82..0d4ad621 100644 --- a/middle_end/remove_unused_closure_vars.ml +++ b/middle_end/remove_unused_closure_vars.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare (** A variable in a closure can either be used by the closure itself or by an inlined version of the function. *) diff --git a/middle_end/remove_unused_program_constructs.ml b/middle_end/remove_unused_program_constructs.ml index 6311a44a..059d68bc 100644 --- a/middle_end/remove_unused_program_constructs.ml +++ b/middle_end/remove_unused_program_constructs.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare let dependency (expr:Flambda.t) = Flambda.free_symbols expr @@ -27,7 +28,7 @@ let constant_dependencies (const:Flambda.constant_defining_value) = | Allocated_const _ -> Symbol.Set.empty | Block (_, fields) -> let symbol_fields = - Misc.Stdlib.List.filter_map (function + List.filter_map (function | (Symbol s : Flambda.constant_defining_value_block_field) -> Some s | Flambda.Const _ -> None) @@ -69,8 +70,10 @@ let rec loop (program : Flambda.program_body) let dep = let_rec_dep defs dep in let defs = List.filter (fun (sym, _) -> Symbol.Set.mem sym dep) defs - in - Let_rec_symbol (defs, program), dep + in begin match defs with + | [] -> program, dep + | _ -> Let_rec_symbol (defs, program), dep + end | Initialize_symbol (sym, tag, fields, program) -> let program, dep = loop program in if Symbol.Set.mem sym dep then diff --git a/middle_end/share_constants.ml b/middle_end/share_constants.ml index 2655d77c..2bbd7134 100644 --- a/middle_end/share_constants.ml +++ b/middle_end/share_constants.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module Constant_defining_value = Flambda.Constant_defining_value diff --git a/middle_end/simple_value_approx.ml b/middle_end/simple_value_approx.ml index 29c320be..34fc5ce0 100644 --- a/middle_end/simple_value_approx.ml +++ b/middle_end/simple_value_approx.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module U = Flambda_utils @@ -115,7 +116,8 @@ let descr t = t.descr let print_value_set_of_closures ppf { function_decls = { funs }; invariant_params; freshening; size; _ } = - Format.fprintf ppf "(set_of_closures:@ %a invariant_params=%a freshening=%a size=%a)" + Format.fprintf ppf + "(set_of_closures:@ %a invariant_params=%a freshening=%a size=%a)" (fun ppf -> Variable.Map.iter (fun id _ -> Variable.print ppf id)) funs (Variable.Map.print Variable.Set.print) (Lazy.force invariant_params) Freshening.Project_var.print freshening @@ -677,7 +679,7 @@ let equal_floats f1 f2 = The approximation for [f 1] and [f 2] could both contain the description of [g]. But if [f] where inlined, a new [g] would be created in each branch, leading to incompatible description. - And we must never make the descrition for a function less + And we must never make the description for a function less precise that it used to be: its information are needed for rewriting [Project_var] and [Project_closure] constructions in [Flambdainline.loop] @@ -697,7 +699,7 @@ let rec meet_descr ~really_import_approx d1 d2 = match d1, d2 with equal_boxed_int bi1 i1 bi2 i2 -> d1 | Value_block (tag1, a1), Value_block (tag2, a2) - when tag1 = tag2 && Array.length a1 = Array.length a2 -> + when Tag.compare tag1 tag2 = 0 && Array.length a1 = Array.length a2 -> let fields = Array.mapi (fun i v -> meet ~really_import_approx v a2.(i)) a1 in diff --git a/middle_end/simple_value_approx.mli b/middle_end/simple_value_approx.mli index a193e77e..dd38652f 100644 --- a/middle_end/simple_value_approx.mli +++ b/middle_end/simple_value_approx.mli @@ -171,10 +171,10 @@ and function_declaration = private { (* CR-soon mshinwell: add support for the approximations of the results, so we can do all of the tricky higher-order cases. *) (* when [is_classic_mode] is [false], functions in [function_declarations] - are guranteed to have function bodies (ie: + are guaranteed to have function bodies (ie: [function_declaration.function_body] will be of the [Some] variant). - When it [is_classic_mode] is [true], however, no gurantees about the + When it [is_classic_mode] is [true], however, no guarantees about the function_bodies are given. *) and value_set_of_closures = private { diff --git a/middle_end/simplify_boxed_integer_ops.ml b/middle_end/simplify_boxed_integer_ops.ml index 31b66923..24d51e53 100644 --- a/middle_end/simplify_boxed_integer_ops.ml +++ b/middle_end/simplify_boxed_integer_ops.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module S = Simplify_common @@ -44,19 +45,21 @@ end) : Simplify_boxed_integer_ops_intf.S with type t := I.t = struct module A = Simple_value_approx module C = Inlining_cost + let equal_kind = Lambda.equal_boxed_integer + let simplify_unop (p : Lambda.primitive) (kind : I.t A.boxed_int) expr (n : I.t) = let eval op = S.const_boxed_int_expr expr kind (op n) in let eval_conv kind op = S.const_boxed_int_expr expr kind (op n) in let eval_unboxed op = S.const_int_expr expr (op n) in match p with - | Pintofbint kind when kind = I.kind -> eval_unboxed I.to_int - | Pcvtbint (kind, Pint32) when kind = I.kind -> + | Pintofbint kind when equal_kind kind I.kind -> eval_unboxed I.to_int + | Pcvtbint (kind, Pint32) when equal_kind kind I.kind -> eval_conv A.Int32 I.to_int32 - | Pcvtbint (kind, Pint64) when kind = I.kind -> + | Pcvtbint (kind, Pint64) when equal_kind kind I.kind -> eval_conv A.Int64 I.to_int64 - | Pnegbint kind when kind = I.kind -> eval I.neg - | Pbbswap kind when kind = I.kind -> eval I.swap + | Pnegbint kind when equal_kind kind I.kind -> eval I.neg + | Pbbswap kind when equal_kind kind I.kind -> eval I.swap | _ -> expr, A.value_unknown Other, C.Benefit.zero let simplify_binop (p : Lambda.primitive) (kind : I.t A.boxed_int) @@ -64,15 +67,17 @@ end) : Simplify_boxed_integer_ops_intf.S with type t := I.t = struct let eval op = S.const_boxed_int_expr expr kind (op n1 n2) in let non_zero n = (I.compare I.zero n) <> 0 in match p with - | Paddbint kind when kind = I.kind -> eval I.add - | Psubbint kind when kind = I.kind -> eval I.sub - | Pmulbint kind when kind = I.kind -> eval I.mul - | Pdivbint {size=kind} when kind = I.kind && non_zero n2 -> eval I.div - | Pmodbint {size=kind} when kind = I.kind && non_zero n2 -> eval I.rem - | Pandbint kind when kind = I.kind -> eval I.logand - | Porbint kind when kind = I.kind -> eval I.logor - | Pxorbint kind when kind = I.kind -> eval I.logxor - | Pbintcomp (kind, c) when kind = I.kind -> + | Paddbint kind when equal_kind kind I.kind -> eval I.add + | Psubbint kind when equal_kind kind I.kind -> eval I.sub + | Pmulbint kind when equal_kind kind I.kind -> eval I.mul + | Pdivbint {size=kind} when equal_kind kind I.kind && non_zero n2 -> + eval I.div + | Pmodbint {size=kind} when equal_kind kind I.kind && non_zero n2 -> + eval I.rem + | Pandbint kind when equal_kind kind I.kind -> eval I.logand + | Porbint kind when equal_kind kind I.kind -> eval I.logor + | Pxorbint kind when equal_kind kind I.kind -> eval I.logxor + | Pbintcomp (kind, c) when equal_kind kind I.kind -> S.const_integer_comparison_expr expr c n1 n2 | _ -> expr, A.value_unknown Other, C.Benefit.zero @@ -81,9 +86,10 @@ end) : Simplify_boxed_integer_ops_intf.S with type t := I.t = struct let eval op = S.const_boxed_int_expr expr kind (op n1 n2) in let precond = 0 <= n2 && n2 < 8 * size_int in match p with - | Plslbint kind when kind = I.kind && precond -> eval I.shift_left - | Plsrbint kind when kind = I.kind && precond -> eval I.shift_right_logical - | Pasrbint kind when kind = I.kind && precond -> eval I.shift_right + | Plslbint kind when equal_kind kind I.kind && precond -> eval I.shift_left + | Plsrbint kind when equal_kind kind I.kind && precond -> + eval I.shift_right_logical + | Pasrbint kind when equal_kind kind I.kind && precond -> eval I.shift_right | _ -> expr, A.value_unknown Other, C.Benefit.zero end diff --git a/middle_end/simplify_common.ml b/middle_end/simplify_common.ml index 3b408be2..fcbbcfbc 100644 --- a/middle_end/simplify_common.ml +++ b/middle_end/simplify_common.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module A = Simple_value_approx module C = Inlining_cost @@ -53,9 +54,10 @@ let const_boxed_int_expr expr t i = else expr, A.value_boxed_int t i, C.Benefit.zero let const_integer_comparison_expr expr (cmp : Lambda.integer_comparison) x y = - (* Using the [Pervasives] comparison functions here in the compiler + (* Using the [Stdlib] comparison functions here in the compiler coincides with the definitions of such functions in the code compiled by the user, and is thus correct. *) + let open! Stdlib in const_bool_expr expr (match cmp with | Ceq -> x = y @@ -66,9 +68,10 @@ let const_integer_comparison_expr expr (cmp : Lambda.integer_comparison) x y = | Cge -> x >= y) let const_float_comparison_expr expr (cmp : Lambda.float_comparison) x y = - (* Using the [Pervasives] comparison functions here in the compiler + (* Using the [Stdlib] comparison functions here in the compiler coincides with the definitions of such functions in the code compiled by the user, and is thus correct. *) + let open! Stdlib in const_bool_expr expr (match cmp with | CFeq -> x = y diff --git a/middle_end/simplify_common.mli b/middle_end/simplify_common.mli index ef0c0cf7..c667bfff 100644 --- a/middle_end/simplify_common.mli +++ b/middle_end/simplify_common.mli @@ -68,8 +68,8 @@ val const_integer_comparison_expr val const_float_comparison_expr : Flambda.named -> Lambda.float_comparison - -> 'a - -> 'a + -> float + -> float -> Flambda.named * Simple_value_approx.t * Inlining_cost.Benefit.t (** Functions for transposing the order of bytes within words of various diff --git a/middle_end/simplify_primitives.ml b/middle_end/simplify_primitives.ml index 75c6a7f3..a7107f72 100644 --- a/middle_end/simplify_primitives.ml +++ b/middle_end/simplify_primitives.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module A = Simple_value_approx module C = Inlining_cost @@ -78,6 +79,30 @@ let phys_different (approxs:A.t list) = | [a1; a2] -> structurally_different a1 a2 +let is_empty = function + | [] -> true + | _ :: _ -> false + +let is_pisint = function + | Lambda.Pisint -> true + | _ -> false + +let is_pstring_length = function + | Lambda.Pstringlength -> true + | _ -> false + +let is_pbytes_length = function + | Lambda.Pbyteslength -> true + | _ -> false + +let is_pstringrefs = function + | Lambda.Pstringrefs -> true + | _ -> false + +let is_pbytesrefs = function + | Lambda.Pbytesrefs -> true + | _ -> false + let primitive (p : Lambda.primitive) (args, approxs) expr dbg ~size_int ~big_endian : Flambda.named * A.t * Inlining_cost.Benefit.t = let fpc = !Clflags.float_const_prop in @@ -100,7 +125,7 @@ let primitive (p : Lambda.primitive) (args, approxs) expr dbg ~size_int S.const_ptr_expr (Flambda.Expr (Var arg)) 0 | _ -> S.const_ptr_expr expr 0 end - | Pmakearray(_, _) when approxs = [] -> + | Pmakearray(_, _) when is_empty approxs -> Prim (Pmakeblock(0, Asttypes.Immutable, Some []), [], dbg), A.value_block (Tag.create_exn 0) [||], C.Benefit.zero | Pmakearray (Pfloatarray, Mutable) -> @@ -199,9 +224,12 @@ let primitive (p : Lambda.primitive) (args, approxs) expr dbg ~size_int | Max_wosize -> (* CR-someday mshinwell: this function should maybe not live here. *) S.const_int_expr expr ((1 lsl ((8*size_int) - 10)) - 1) - | Ostype_unix -> S.const_bool_expr expr (Sys.os_type = "Unix") - | Ostype_win32 -> S.const_bool_expr expr (Sys.os_type = "Win32") - | Ostype_cygwin -> S.const_bool_expr expr (Sys.os_type = "Cygwin") + | Ostype_unix -> + S.const_bool_expr expr (String.equal Sys.os_type "Unix") + | Ostype_win32 -> + S.const_bool_expr expr (String.equal Sys.os_type "Win32") + | Ostype_cygwin -> + S.const_bool_expr expr (String.equal Sys.os_type "Cygwin") | Backend_type -> S.const_ptr_expr expr 0 (* tag 0 is the same as Native *) end @@ -245,10 +273,10 @@ let primitive (p : Lambda.primitive) (args, approxs) expr dbg ~size_int | [A.Value_boxed_int(A.Int64, n1); Value_int n2] -> I.Simplify_boxed_int64.simplify_binop_int p Int64 expr n1 n2 ~size_int - | [Value_block _] when p = Lambda.Pisint -> + | [Value_block _] when is_pisint p -> S.const_bool_expr expr false | [Value_string { size }] - when (p = Lambda.Pstringlength || p = Lambda.Pbyteslength) -> + when (is_pstring_length p || is_pbytes_length p) -> S.const_int_expr expr size | [Value_string { size; contents = Some s }; (Value_int x | Value_constptr x)] when x >= 0 && x < size -> @@ -262,14 +290,14 @@ let primitive (p : Lambda.primitive) (args, approxs) expr dbg ~size_int end | [Value_string { size; contents = None }; (Value_int x | Value_constptr x)] - when x >= 0 && x < size && p = Lambda.Pstringrefs -> + when x >= 0 && x < size && is_pstringrefs p -> Flambda.Prim (Pstringrefu, args, dbg), A.value_unknown Other, (* we improved it, but there is no way to account for that: *) C.Benefit.zero | [Value_string { size; contents = None }; (Value_int x | Value_constptr x)] - when x >= 0 && x < size && p = Lambda.Pbytesrefs -> + when x >= 0 && x < size && is_pbytesrefs p -> Flambda.Prim (Pbytesrefu, args, dbg), A.value_unknown Other, (* we improved it, but there is no way to account for that: *) diff --git a/middle_end/unbox_closures.ml b/middle_end/unbox_closures.ml index 00c696b2..5c86bed3 100644 --- a/middle_end/unbox_closures.ml +++ b/middle_end/unbox_closures.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module ASA = Augment_specialised_args module W = ASA.What_to_specialise diff --git a/middle_end/unbox_free_vars_of_closures.ml b/middle_end/unbox_free_vars_of_closures.ml index be556c13..7a4e48ed 100644 --- a/middle_end/unbox_free_vars_of_closures.ml +++ b/middle_end/unbox_free_vars_of_closures.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module B = Inlining_cost.Benefit @@ -162,7 +163,8 @@ let run ~env ~(set_of_closures : Flambda.set_of_closures) = Some (expr, benefit) let run ~env ~set_of_closures = - Pass_wrapper.with_dump ~pass_name ~input:set_of_closures + Pass_wrapper.with_dump ~ppf_dump:(Inline_and_simplify_aux.Env.ppf_dump env) + ~pass_name ~input:set_of_closures ~print_input:Flambda.print_set_of_closures ~print_output:(fun ppf (expr, _) -> Flambda.print ppf expr) ~f:(fun () -> run ~env ~set_of_closures) diff --git a/middle_end/unbox_specialised_args.ml b/middle_end/unbox_specialised_args.ml index 64e54eaf..70eb8760 100755 --- a/middle_end/unbox_specialised_args.ml +++ b/middle_end/unbox_specialised_args.ml @@ -14,7 +14,8 @@ (* *) (**************************************************************************) -[@@@ocaml.warning "+a-4-9-30-40-41-42"] +[@@@ocaml.warning "+a-4-9-30-40-41-42-66"] +open! Int_replace_polymorphic_compare module ASA = Augment_specialised_args module W = ASA.What_to_specialise diff --git a/ocaml-variants.opam b/ocaml-variants.opam new file mode 100644 index 00000000..51b6e7c1 --- /dev/null +++ b/ocaml-variants.opam @@ -0,0 +1,29 @@ +opam-version: "2.0" +version: "4.08.0" +synopsis: "OCaml release 4.08.0" +depends: [ + "ocaml" {= "4.08.0" & post} + "base-unix" {post} + "base-bigarray" {post} + "base-threads" {post} +] +conflict-class: "ocaml-core-compiler" +flags: compiler +setenv: CAML_LD_LIBRARY_PATH = "%{lib}%/stublibs" +build: [ + ["./configure" "--prefix=%{prefix}%"] + [make "-j%{jobs}%" "world"] + [make "-j%{jobs}%" "world.opt"] +] +install: [make "install"] +maintainer: "caml-list@inria.fr" +homepage: "https://github.com/ocaml/ocaml/" +bug-reports: "https://github.com/ocaml/ocaml/issues" +authors: [ + "Xavier Leroy" + "Damien Doligez" + "Alain Frisch" + "Jacques Garrigue" + "Didier Rémy" + "Jérôme Vouillon" +] diff --git a/ocamldoc/.depend b/ocamldoc/.depend index ab7dcf5b..3b33fb26 100644 --- a/ocamldoc/.depend +++ b/ocamldoc/.depend @@ -1,276 +1,877 @@ -odoc.cmo : odoc_messages.cmo odoc_info.cmi odoc_global.cmi odoc_gen.cmi \ - odoc_config.cmi odoc_args.cmi odoc_analyse.cmi -odoc.cmx : odoc_messages.cmx odoc_info.cmx odoc_global.cmx odoc_gen.cmx \ - odoc_config.cmx odoc_args.cmx odoc_analyse.cmx -odoc_analyse.cmo : ../utils/warnings.cmi ../typing/types.cmi \ - ../typing/typemod.cmi ../typing/typedtree.cmi ../parsing/syntaxerr.cmi \ - ../driver/pparse.cmi ../parsing/parse.cmi odoc_types.cmi odoc_text.cmi \ - odoc_sig.cmi odoc_module.cmo odoc_misc.cmi odoc_messages.cmo \ - odoc_merge.cmi odoc_global.cmi odoc_dep.cmo odoc_cross.cmi \ - odoc_comments.cmi odoc_class.cmo odoc_ast.cmi ../parsing/location.cmi \ - ../parsing/lexer.cmi ../typing/env.cmi ../utils/config.cmi \ - ../utils/clflags.cmi odoc_analyse.cmi -odoc_analyse.cmx : ../utils/warnings.cmx ../typing/types.cmx \ - ../typing/typemod.cmx ../typing/typedtree.cmx ../parsing/syntaxerr.cmx \ - ../driver/pparse.cmx ../parsing/parse.cmx odoc_types.cmx odoc_text.cmx \ - odoc_sig.cmx odoc_module.cmx odoc_misc.cmx odoc_messages.cmx \ - odoc_merge.cmx odoc_global.cmx odoc_dep.cmx odoc_cross.cmx \ - odoc_comments.cmx odoc_class.cmx odoc_ast.cmx ../parsing/location.cmx \ - ../parsing/lexer.cmx ../typing/env.cmx ../utils/config.cmx \ - ../utils/clflags.cmx odoc_analyse.cmi -odoc_analyse.cmi : odoc_module.cmo odoc_global.cmi -odoc_args.cmo : ../utils/warnings.cmi odoc_types.cmi odoc_texi.cmo \ - odoc_messages.cmo odoc_man.cmo odoc_latex.cmo odoc_html.cmo \ - odoc_global.cmi odoc_gen.cmi odoc_dot.cmo odoc_config.cmi \ - ../utils/misc.cmi ../driver/main_args.cmi ../parsing/location.cmi \ - ../utils/config.cmi ../driver/compenv.cmi ../utils/clflags.cmi \ +odoc.cmo : \ + odoc_messages.cmo \ + odoc_info.cmi \ + odoc_global.cmi \ + odoc_gen.cmi \ + odoc_config.cmi \ + odoc_args.cmi \ + odoc_analyse.cmi +odoc.cmx : \ + odoc_messages.cmx \ + odoc_info.cmx \ + odoc_global.cmx \ + odoc_gen.cmx \ + odoc_config.cmx \ + odoc_args.cmx \ + odoc_analyse.cmx +odoc_analyse.cmo : \ + ../utils/warnings.cmi \ + ../typing/types.cmi \ + ../typing/typemod.cmi \ + ../typing/typedtree.cmi \ + ../parsing/syntaxerr.cmi \ + ../driver/pparse.cmi \ + ../parsing/parse.cmi \ + odoc_types.cmi \ + odoc_text.cmi \ + odoc_sig.cmi \ + odoc_module.cmo \ + odoc_misc.cmi \ + odoc_messages.cmo \ + odoc_merge.cmi \ + odoc_global.cmi \ + odoc_dep.cmo \ + odoc_cross.cmi \ + odoc_comments.cmi \ + odoc_class.cmo \ + odoc_ast.cmi \ + ../parsing/location.cmi \ + ../parsing/lexer.cmi \ + ../typing/env.cmi \ + ../utils/config.cmi \ + ../driver/compmisc.cmi \ + ../utils/clflags.cmi \ + odoc_analyse.cmi +odoc_analyse.cmx : \ + ../utils/warnings.cmx \ + ../typing/types.cmx \ + ../typing/typemod.cmx \ + ../typing/typedtree.cmx \ + ../parsing/syntaxerr.cmx \ + ../driver/pparse.cmx \ + ../parsing/parse.cmx \ + odoc_types.cmx \ + odoc_text.cmx \ + odoc_sig.cmx \ + odoc_module.cmx \ + odoc_misc.cmx \ + odoc_messages.cmx \ + odoc_merge.cmx \ + odoc_global.cmx \ + odoc_dep.cmx \ + odoc_cross.cmx \ + odoc_comments.cmx \ + odoc_class.cmx \ + odoc_ast.cmx \ + ../parsing/location.cmx \ + ../parsing/lexer.cmx \ + ../typing/env.cmx \ + ../utils/config.cmx \ + ../driver/compmisc.cmx \ + ../utils/clflags.cmx \ + odoc_analyse.cmi +odoc_analyse.cmi : \ + odoc_module.cmo \ + odoc_global.cmi +odoc_args.cmo : \ + ../utils/warnings.cmi \ + odoc_types.cmi \ + odoc_texi.cmo \ + odoc_messages.cmo \ + odoc_man.cmo \ + odoc_latex.cmo \ + odoc_html.cmo \ + odoc_global.cmi \ + odoc_gen.cmi \ + odoc_dot.cmo \ + odoc_config.cmi \ + ../driver/main_args.cmi \ + ../utils/config.cmi \ + ../driver/compenv.cmi \ + ../utils/clflags.cmi \ odoc_args.cmi -odoc_args.cmx : ../utils/warnings.cmx odoc_types.cmx odoc_texi.cmx \ - odoc_messages.cmx odoc_man.cmx odoc_latex.cmx odoc_html.cmx \ - odoc_global.cmx odoc_gen.cmx odoc_dot.cmx odoc_config.cmx \ - ../utils/misc.cmx ../driver/main_args.cmx ../parsing/location.cmx \ - ../utils/config.cmx ../driver/compenv.cmx ../utils/clflags.cmx \ +odoc_args.cmx : \ + ../utils/warnings.cmx \ + odoc_types.cmx \ + odoc_texi.cmx \ + odoc_messages.cmx \ + odoc_man.cmx \ + odoc_latex.cmx \ + odoc_html.cmx \ + odoc_global.cmx \ + odoc_gen.cmx \ + odoc_dot.cmx \ + odoc_config.cmx \ + ../driver/main_args.cmx \ + ../utils/config.cmx \ + ../driver/compenv.cmx \ + ../utils/clflags.cmx \ odoc_args.cmi -odoc_args.cmi : odoc_gen.cmi -odoc_ast.cmo : ../typing/types.cmi ../typing/typedtree.cmi \ - ../typing/predef.cmi ../typing/path.cmi ../parsing/parsetree.cmi \ - odoc_value.cmo odoc_types.cmi odoc_type.cmo odoc_sig.cmi \ - odoc_parameter.cmo odoc_module.cmo odoc_messages.cmo odoc_global.cmi \ - odoc_extension.cmo odoc_exception.cmo odoc_env.cmi odoc_class.cmo \ - ../utils/misc.cmi ../parsing/location.cmi ../typing/ident.cmi \ - ../parsing/asttypes.cmi odoc_ast.cmi -odoc_ast.cmx : ../typing/types.cmx ../typing/typedtree.cmx \ - ../typing/predef.cmx ../typing/path.cmx ../parsing/parsetree.cmi \ - odoc_value.cmx odoc_types.cmx odoc_type.cmx odoc_sig.cmx \ - odoc_parameter.cmx odoc_module.cmx odoc_messages.cmx odoc_global.cmx \ - odoc_extension.cmx odoc_exception.cmx odoc_env.cmx odoc_class.cmx \ - ../utils/misc.cmx ../parsing/location.cmx ../typing/ident.cmx \ - ../parsing/asttypes.cmi odoc_ast.cmi -odoc_ast.cmi : ../typing/types.cmi ../typing/typedtree.cmi \ - ../parsing/parsetree.cmi odoc_sig.cmi odoc_name.cmi odoc_module.cmo -odoc_class.cmo : ../typing/types.cmi odoc_value.cmo odoc_types.cmi \ - odoc_parameter.cmo odoc_name.cmi -odoc_class.cmx : ../typing/types.cmx odoc_value.cmx odoc_types.cmx \ - odoc_parameter.cmx odoc_name.cmx -odoc_comments.cmo : odoc_types.cmi odoc_text.cmi odoc_see_lexer.cmo \ - odoc_parser.cmi odoc_misc.cmi odoc_messages.cmo odoc_merge.cmi \ - odoc_lexer.cmo odoc_global.cmi odoc_cross.cmi odoc_comments_global.cmi \ +odoc_args.cmi : \ + odoc_gen.cmi +odoc_ast.cmo : \ + ../typing/types.cmi \ + ../typing/typedtree.cmi \ + ../typing/predef.cmi \ + ../typing/path.cmi \ + ../parsing/parsetree.cmi \ + odoc_value.cmo \ + odoc_types.cmi \ + odoc_type.cmo \ + odoc_sig.cmi \ + odoc_parameter.cmo \ + odoc_module.cmo \ + odoc_messages.cmo \ + odoc_global.cmi \ + odoc_extension.cmo \ + odoc_exception.cmo \ + odoc_env.cmi \ + odoc_class.cmo \ + ../utils/misc.cmi \ + ../parsing/location.cmi \ + ../typing/ident.cmi \ + ../parsing/asttypes.cmi \ + odoc_ast.cmi +odoc_ast.cmx : \ + ../typing/types.cmx \ + ../typing/typedtree.cmx \ + ../typing/predef.cmx \ + ../typing/path.cmx \ + ../parsing/parsetree.cmi \ + odoc_value.cmx \ + odoc_types.cmx \ + odoc_type.cmx \ + odoc_sig.cmx \ + odoc_parameter.cmx \ + odoc_module.cmx \ + odoc_messages.cmx \ + odoc_global.cmx \ + odoc_extension.cmx \ + odoc_exception.cmx \ + odoc_env.cmx \ + odoc_class.cmx \ + ../utils/misc.cmx \ + ../parsing/location.cmx \ + ../typing/ident.cmx \ + ../parsing/asttypes.cmi \ + odoc_ast.cmi +odoc_ast.cmi : \ + ../typing/types.cmi \ + ../typing/typedtree.cmi \ + ../parsing/parsetree.cmi \ + odoc_sig.cmi \ + odoc_name.cmi \ + odoc_module.cmo +odoc_class.cmo : \ + ../typing/types.cmi \ + odoc_value.cmo \ + odoc_types.cmi \ + odoc_parameter.cmo \ + odoc_name.cmi +odoc_class.cmx : \ + ../typing/types.cmx \ + odoc_value.cmx \ + odoc_types.cmx \ + odoc_parameter.cmx \ + odoc_name.cmx +odoc_comments.cmo : \ + odoc_types.cmi \ + odoc_text.cmi \ + odoc_see_lexer.cmo \ + odoc_parser.cmi \ + odoc_misc.cmi \ + odoc_messages.cmo \ + odoc_merge.cmi \ + odoc_lexer.cmo \ + odoc_global.cmi \ + odoc_cross.cmi \ + odoc_comments_global.cmi \ odoc_comments.cmi -odoc_comments.cmx : odoc_types.cmx odoc_text.cmx odoc_see_lexer.cmx \ - odoc_parser.cmx odoc_misc.cmx odoc_messages.cmx odoc_merge.cmx \ - odoc_lexer.cmx odoc_global.cmx odoc_cross.cmx odoc_comments_global.cmx \ +odoc_comments.cmx : \ + odoc_types.cmx \ + odoc_text.cmx \ + odoc_see_lexer.cmx \ + odoc_parser.cmx \ + odoc_misc.cmx \ + odoc_messages.cmx \ + odoc_merge.cmx \ + odoc_lexer.cmx \ + odoc_global.cmx \ + odoc_cross.cmx \ + odoc_comments_global.cmx \ odoc_comments.cmi -odoc_comments.cmi : odoc_types.cmi odoc_module.cmo -odoc_comments_global.cmo : odoc_comments_global.cmi -odoc_comments_global.cmx : odoc_comments_global.cmi +odoc_comments.cmi : \ + odoc_types.cmi \ + odoc_module.cmo +odoc_comments_global.cmo : \ + odoc_comments_global.cmi +odoc_comments_global.cmx : \ + odoc_comments_global.cmi odoc_comments_global.cmi : -odoc_config.cmo : ../utils/config.cmi odoc_config.cmi -odoc_config.cmx : ../utils/config.cmx odoc_config.cmi +odoc_config.cmo : \ + ../utils/config.cmi \ + odoc_config.cmi +odoc_config.cmx : \ + ../utils/config.cmx \ + odoc_config.cmi odoc_config.cmi : odoc_control.cmo : odoc_control.cmx : -odoc_cross.cmo : odoc_value.cmo odoc_types.cmi odoc_type.cmo odoc_search.cmi \ - odoc_scan.cmo odoc_parameter.cmo odoc_name.cmi odoc_module.cmo \ - odoc_misc.cmi odoc_messages.cmo odoc_global.cmi odoc_extension.cmo \ - odoc_exception.cmo odoc_class.cmo odoc_cross.cmi -odoc_cross.cmx : odoc_value.cmx odoc_types.cmx odoc_type.cmx odoc_search.cmx \ - odoc_scan.cmx odoc_parameter.cmx odoc_name.cmx odoc_module.cmx \ - odoc_misc.cmx odoc_messages.cmx odoc_global.cmx odoc_extension.cmx \ - odoc_exception.cmx odoc_class.cmx odoc_cross.cmi -odoc_cross.cmi : odoc_types.cmi odoc_module.cmo -odoc_dag2html.cmo : odoc_info.cmi odoc_dag2html.cmi -odoc_dag2html.cmx : odoc_info.cmx odoc_dag2html.cmi -odoc_dag2html.cmi : odoc_info.cmi -odoc_dep.cmo : ../parsing/parsetree.cmi odoc_type.cmo odoc_print.cmi \ - odoc_module.cmo ../parsing/depend.cmi -odoc_dep.cmx : ../parsing/parsetree.cmi odoc_type.cmx odoc_print.cmx \ - odoc_module.cmx ../parsing/depend.cmx -odoc_dot.cmo : odoc_messages.cmo odoc_info.cmi -odoc_dot.cmx : odoc_messages.cmx odoc_info.cmx -odoc_env.cmo : ../typing/types.cmi ../typing/printtyp.cmi \ - ../typing/predef.cmi ../typing/path.cmi odoc_name.cmi ../utils/misc.cmi \ - ../typing/btype.cmi odoc_env.cmi -odoc_env.cmx : ../typing/types.cmx ../typing/printtyp.cmx \ - ../typing/predef.cmx ../typing/path.cmx odoc_name.cmx ../utils/misc.cmx \ - ../typing/btype.cmx odoc_env.cmi -odoc_env.cmi : ../typing/types.cmi odoc_name.cmi -odoc_exception.cmo : ../typing/types.cmi odoc_types.cmi odoc_type.cmo \ +odoc_cross.cmo : \ + odoc_value.cmo \ + odoc_types.cmi \ + odoc_type.cmo \ + odoc_search.cmi \ + odoc_scan.cmo \ + odoc_parameter.cmo \ + odoc_name.cmi \ + odoc_module.cmo \ + odoc_misc.cmi \ + odoc_messages.cmo \ + odoc_global.cmi \ + odoc_extension.cmo \ + odoc_exception.cmo \ + odoc_class.cmo \ + ../utils/misc.cmi \ + odoc_cross.cmi +odoc_cross.cmx : \ + odoc_value.cmx \ + odoc_types.cmx \ + odoc_type.cmx \ + odoc_search.cmx \ + odoc_scan.cmx \ + odoc_parameter.cmx \ + odoc_name.cmx \ + odoc_module.cmx \ + odoc_misc.cmx \ + odoc_messages.cmx \ + odoc_global.cmx \ + odoc_extension.cmx \ + odoc_exception.cmx \ + odoc_class.cmx \ + ../utils/misc.cmx \ + odoc_cross.cmi +odoc_cross.cmi : \ + odoc_types.cmi \ + odoc_module.cmo +odoc_dag2html.cmo : \ + odoc_info.cmi \ + odoc_dag2html.cmi +odoc_dag2html.cmx : \ + odoc_info.cmx \ + odoc_dag2html.cmi +odoc_dag2html.cmi : \ + odoc_info.cmi +odoc_dep.cmo : \ + ../parsing/parsetree.cmi \ + odoc_type.cmo \ + odoc_print.cmi \ + odoc_module.cmo \ + ../utils/misc.cmi \ + ../parsing/depend.cmi +odoc_dep.cmx : \ + ../parsing/parsetree.cmi \ + odoc_type.cmx \ + odoc_print.cmx \ + odoc_module.cmx \ + ../utils/misc.cmx \ + ../parsing/depend.cmx +odoc_dot.cmo : \ + odoc_messages.cmo \ + odoc_info.cmi +odoc_dot.cmx : \ + odoc_messages.cmx \ + odoc_info.cmx +odoc_env.cmo : \ + ../typing/types.cmi \ + ../typing/printtyp.cmi \ + ../typing/predef.cmi \ + ../typing/path.cmi \ + odoc_name.cmi \ + ../utils/misc.cmi \ + ../typing/btype.cmi \ + odoc_env.cmi +odoc_env.cmx : \ + ../typing/types.cmx \ + ../typing/printtyp.cmx \ + ../typing/predef.cmx \ + ../typing/path.cmx \ + odoc_name.cmx \ + ../utils/misc.cmx \ + ../typing/btype.cmx \ + odoc_env.cmi +odoc_env.cmi : \ + ../typing/types.cmi \ odoc_name.cmi -odoc_exception.cmx : ../typing/types.cmx odoc_types.cmx odoc_type.cmx \ +odoc_exception.cmo : \ + ../typing/types.cmi \ + odoc_types.cmi \ + odoc_type.cmo \ + odoc_name.cmi +odoc_exception.cmx : \ + ../typing/types.cmx \ + odoc_types.cmx \ + odoc_type.cmx \ odoc_name.cmx -odoc_extension.cmo : ../typing/types.cmi odoc_types.cmi odoc_type.cmo \ - odoc_name.cmi ../parsing/asttypes.cmi -odoc_extension.cmx : ../typing/types.cmx odoc_types.cmx odoc_type.cmx \ - odoc_name.cmx ../parsing/asttypes.cmi -odoc_gen.cmo : odoc_texi.cmo odoc_module.cmo odoc_man.cmo odoc_latex.cmo \ - odoc_html.cmo odoc_dot.cmo odoc_gen.cmi -odoc_gen.cmx : odoc_texi.cmx odoc_module.cmx odoc_man.cmx odoc_latex.cmx \ - odoc_html.cmx odoc_dot.cmx odoc_gen.cmi -odoc_gen.cmi : odoc_texi.cmo odoc_module.cmo odoc_man.cmo odoc_latex.cmo \ - odoc_html.cmo odoc_dot.cmo -odoc_global.cmo : odoc_types.cmi odoc_messages.cmo odoc_config.cmi \ - ../utils/clflags.cmi odoc_global.cmi -odoc_global.cmx : odoc_types.cmx odoc_messages.cmx odoc_config.cmx \ - ../utils/clflags.cmx odoc_global.cmi -odoc_global.cmi : odoc_types.cmi -odoc_html.cmo : odoc_text.cmi odoc_ocamlhtml.cmo odoc_messages.cmo \ - odoc_info.cmi odoc_global.cmi odoc_dag2html.cmi ../parsing/asttypes.cmi -odoc_html.cmx : odoc_text.cmx odoc_ocamlhtml.cmx odoc_messages.cmx \ - odoc_info.cmx odoc_global.cmx odoc_dag2html.cmx ../parsing/asttypes.cmi -odoc_info.cmo : ../typing/printtyp.cmi odoc_value.cmo odoc_types.cmi \ - odoc_type.cmo odoc_text.cmi odoc_str.cmi odoc_search.cmi odoc_scan.cmo \ - odoc_print.cmi odoc_parameter.cmo odoc_name.cmi odoc_module.cmo \ - odoc_misc.cmi odoc_global.cmi odoc_extension.cmo odoc_exception.cmo \ - odoc_dep.cmo odoc_config.cmi odoc_comments.cmi odoc_class.cmo \ - odoc_analyse.cmi ../parsing/location.cmi odoc_info.cmi -odoc_info.cmx : ../typing/printtyp.cmx odoc_value.cmx odoc_types.cmx \ - odoc_type.cmx odoc_text.cmx odoc_str.cmx odoc_search.cmx odoc_scan.cmx \ - odoc_print.cmx odoc_parameter.cmx odoc_name.cmx odoc_module.cmx \ - odoc_misc.cmx odoc_global.cmx odoc_extension.cmx odoc_exception.cmx \ - odoc_dep.cmx odoc_config.cmx odoc_comments.cmx odoc_class.cmx \ - odoc_analyse.cmx ../parsing/location.cmx odoc_info.cmi -odoc_info.cmi : ../typing/types.cmi odoc_value.cmo odoc_types.cmi \ - odoc_type.cmo odoc_search.cmi odoc_parameter.cmo odoc_module.cmo \ - odoc_global.cmi odoc_extension.cmo odoc_exception.cmo odoc_class.cmo \ - ../parsing/location.cmi ../parsing/asttypes.cmi +odoc_extension.cmo : \ + ../typing/types.cmi \ + odoc_types.cmi \ + odoc_type.cmo \ + odoc_name.cmi \ + ../parsing/asttypes.cmi +odoc_extension.cmx : \ + ../typing/types.cmx \ + odoc_types.cmx \ + odoc_type.cmx \ + odoc_name.cmx \ + ../parsing/asttypes.cmi +odoc_gen.cmo : \ + odoc_texi.cmo \ + odoc_module.cmo \ + odoc_man.cmo \ + odoc_latex.cmo \ + odoc_html.cmo \ + odoc_dot.cmo \ + odoc_gen.cmi +odoc_gen.cmx : \ + odoc_texi.cmx \ + odoc_module.cmx \ + odoc_man.cmx \ + odoc_latex.cmx \ + odoc_html.cmx \ + odoc_dot.cmx \ + odoc_gen.cmi +odoc_gen.cmi : \ + odoc_texi.cmo \ + odoc_module.cmo \ + odoc_man.cmo \ + odoc_latex.cmo \ + odoc_html.cmo \ + odoc_dot.cmo +odoc_global.cmo : \ + odoc_types.cmi \ + odoc_messages.cmo \ + odoc_config.cmi \ + ../utils/clflags.cmi \ + odoc_global.cmi +odoc_global.cmx : \ + odoc_types.cmx \ + odoc_messages.cmx \ + odoc_config.cmx \ + ../utils/clflags.cmx \ + odoc_global.cmi +odoc_global.cmi : \ + odoc_types.cmi +odoc_html.cmo : \ + odoc_text.cmi \ + odoc_ocamlhtml.cmo \ + odoc_messages.cmo \ + odoc_info.cmi \ + odoc_global.cmi \ + odoc_dag2html.cmi \ + ../utils/misc.cmi \ + ../parsing/asttypes.cmi +odoc_html.cmx : \ + odoc_text.cmx \ + odoc_ocamlhtml.cmx \ + odoc_messages.cmx \ + odoc_info.cmx \ + odoc_global.cmx \ + odoc_dag2html.cmx \ + ../utils/misc.cmx \ + ../parsing/asttypes.cmi +odoc_info.cmo : \ + ../typing/printtyp.cmi \ + odoc_value.cmo \ + odoc_types.cmi \ + odoc_type.cmo \ + odoc_text.cmi \ + odoc_str.cmi \ + odoc_search.cmi \ + odoc_scan.cmo \ + odoc_print.cmi \ + odoc_parameter.cmo \ + odoc_name.cmi \ + odoc_module.cmo \ + odoc_misc.cmi \ + odoc_global.cmi \ + odoc_extension.cmo \ + odoc_exception.cmo \ + odoc_dep.cmo \ + odoc_config.cmi \ + odoc_comments.cmi \ + odoc_class.cmo \ + odoc_analyse.cmi \ + ../parsing/location.cmi \ + odoc_info.cmi +odoc_info.cmx : \ + ../typing/printtyp.cmx \ + odoc_value.cmx \ + odoc_types.cmx \ + odoc_type.cmx \ + odoc_text.cmx \ + odoc_str.cmx \ + odoc_search.cmx \ + odoc_scan.cmx \ + odoc_print.cmx \ + odoc_parameter.cmx \ + odoc_name.cmx \ + odoc_module.cmx \ + odoc_misc.cmx \ + odoc_global.cmx \ + odoc_extension.cmx \ + odoc_exception.cmx \ + odoc_dep.cmx \ + odoc_config.cmx \ + odoc_comments.cmx \ + odoc_class.cmx \ + odoc_analyse.cmx \ + ../parsing/location.cmx \ + odoc_info.cmi +odoc_info.cmi : \ + ../typing/types.cmi \ + odoc_value.cmo \ + odoc_types.cmi \ + odoc_type.cmo \ + odoc_search.cmi \ + odoc_parameter.cmo \ + odoc_module.cmo \ + odoc_global.cmi \ + odoc_extension.cmo \ + odoc_exception.cmo \ + odoc_class.cmo \ + ../parsing/location.cmi \ + ../parsing/asttypes.cmi odoc_inherit.cmo : odoc_inherit.cmx : -odoc_latex.cmo : odoc_to_text.cmo odoc_messages.cmo odoc_latex_style.cmo \ - odoc_info.cmi ../parsing/asttypes.cmi -odoc_latex.cmx : odoc_to_text.cmx odoc_messages.cmx odoc_latex_style.cmx \ - odoc_info.cmx ../parsing/asttypes.cmi +odoc_latex.cmo : \ + odoc_to_text.cmo \ + odoc_messages.cmo \ + odoc_latex_style.cmo \ + odoc_info.cmi \ + ../parsing/asttypes.cmi +odoc_latex.cmx : \ + odoc_to_text.cmx \ + odoc_messages.cmx \ + odoc_latex_style.cmx \ + odoc_info.cmx \ + ../parsing/asttypes.cmi odoc_latex_style.cmo : odoc_latex_style.cmx : -odoc_lexer.cmo : odoc_parser.cmi odoc_messages.cmo odoc_global.cmi \ +odoc_lexer.cmo : \ + odoc_parser.cmi \ + odoc_messages.cmo \ + odoc_global.cmi \ odoc_comments_global.cmi -odoc_lexer.cmx : odoc_parser.cmx odoc_messages.cmx odoc_global.cmx \ +odoc_lexer.cmx : \ + odoc_parser.cmx \ + odoc_messages.cmx \ + odoc_global.cmx \ odoc_comments_global.cmx -odoc_man.cmo : odoc_str.cmi odoc_print.cmi odoc_misc.cmi odoc_messages.cmo \ - odoc_info.cmi ../utils/misc.cmi ../parsing/asttypes.cmi -odoc_man.cmx : odoc_str.cmx odoc_print.cmx odoc_misc.cmx odoc_messages.cmx \ - odoc_info.cmx ../utils/misc.cmx ../parsing/asttypes.cmi -odoc_merge.cmo : odoc_value.cmo odoc_types.cmi odoc_type.cmo \ - odoc_parameter.cmo odoc_module.cmo odoc_messages.cmo odoc_global.cmi \ - odoc_extension.cmo odoc_exception.cmo odoc_class.cmo odoc_merge.cmi -odoc_merge.cmx : odoc_value.cmx odoc_types.cmx odoc_type.cmx \ - odoc_parameter.cmx odoc_module.cmx odoc_messages.cmx odoc_global.cmx \ - odoc_extension.cmx odoc_exception.cmx odoc_class.cmx odoc_merge.cmi -odoc_merge.cmi : odoc_types.cmi odoc_module.cmo -odoc_messages.cmo : ../utils/config.cmi -odoc_messages.cmx : ../utils/config.cmx -odoc_misc.cmo : ../typing/types.cmi ../typing/predef.cmi ../typing/path.cmi \ - odoc_types.cmi odoc_messages.cmo ../parsing/longident.cmi \ - ../typing/ctype.cmi ../typing/btype.cmi odoc_misc.cmi -odoc_misc.cmx : ../typing/types.cmx ../typing/predef.cmx ../typing/path.cmx \ - odoc_types.cmx odoc_messages.cmx ../parsing/longident.cmx \ - ../typing/ctype.cmx ../typing/btype.cmx odoc_misc.cmi -odoc_misc.cmi : ../typing/types.cmi odoc_types.cmi ../parsing/longident.cmi \ +odoc_man.cmo : \ + odoc_str.cmi \ + odoc_print.cmi \ + odoc_misc.cmi \ + odoc_messages.cmo \ + odoc_info.cmi \ + ../utils/misc.cmi \ + ../parsing/asttypes.cmi +odoc_man.cmx : \ + odoc_str.cmx \ + odoc_print.cmx \ + odoc_misc.cmx \ + odoc_messages.cmx \ + odoc_info.cmx \ + ../utils/misc.cmx \ ../parsing/asttypes.cmi -odoc_module.cmo : ../typing/types.cmi odoc_value.cmo odoc_types.cmi \ - odoc_type.cmo odoc_name.cmi odoc_extension.cmo odoc_exception.cmo \ - odoc_class.cmo ../utils/misc.cmi -odoc_module.cmx : ../typing/types.cmx odoc_value.cmx odoc_types.cmx \ - odoc_type.cmx odoc_name.cmx odoc_extension.cmx odoc_exception.cmx \ - odoc_class.cmx ../utils/misc.cmx -odoc_name.cmo : ../typing/path.cmi odoc_misc.cmi ../typing/ident.cmi \ +odoc_merge.cmo : \ + odoc_value.cmo \ + odoc_types.cmi \ + odoc_type.cmo \ + odoc_parameter.cmo \ + odoc_module.cmo \ + odoc_messages.cmo \ + odoc_global.cmi \ + odoc_extension.cmo \ + odoc_exception.cmo \ + odoc_class.cmo \ + odoc_merge.cmi +odoc_merge.cmx : \ + odoc_value.cmx \ + odoc_types.cmx \ + odoc_type.cmx \ + odoc_parameter.cmx \ + odoc_module.cmx \ + odoc_messages.cmx \ + odoc_global.cmx \ + odoc_extension.cmx \ + odoc_exception.cmx \ + odoc_class.cmx \ + odoc_merge.cmi +odoc_merge.cmi : \ + odoc_types.cmi \ + odoc_module.cmo +odoc_messages.cmo : \ + ../utils/config.cmi +odoc_messages.cmx : \ + ../utils/config.cmx +odoc_misc.cmo : \ + ../typing/types.cmi \ + ../typing/predef.cmi \ + ../typing/path.cmi \ + odoc_types.cmi \ + odoc_messages.cmo \ + ../parsing/longident.cmi \ + ../typing/ctype.cmi \ + ../typing/btype.cmi \ + odoc_misc.cmi +odoc_misc.cmx : \ + ../typing/types.cmx \ + ../typing/predef.cmx \ + ../typing/path.cmx \ + odoc_types.cmx \ + odoc_messages.cmx \ + ../parsing/longident.cmx \ + ../typing/ctype.cmx \ + ../typing/btype.cmx \ + odoc_misc.cmi +odoc_misc.cmi : \ + ../typing/types.cmi \ + odoc_types.cmi \ + ../parsing/longident.cmi \ + ../parsing/asttypes.cmi +odoc_module.cmo : \ + ../typing/types.cmi \ + odoc_value.cmo \ + odoc_types.cmi \ + odoc_type.cmo \ + odoc_name.cmi \ + odoc_extension.cmo \ + odoc_exception.cmo \ + odoc_class.cmo \ + ../utils/misc.cmi +odoc_module.cmx : \ + ../typing/types.cmx \ + odoc_value.cmx \ + odoc_types.cmx \ + odoc_type.cmx \ + odoc_name.cmx \ + odoc_extension.cmx \ + odoc_exception.cmx \ + odoc_class.cmx \ + ../utils/misc.cmx +odoc_name.cmo : \ + ../typing/path.cmi \ + odoc_misc.cmi \ + ../typing/ident.cmi \ odoc_name.cmi -odoc_name.cmx : ../typing/path.cmx odoc_misc.cmx ../typing/ident.cmx \ +odoc_name.cmx : \ + ../typing/path.cmx \ + odoc_misc.cmx \ + ../typing/ident.cmx \ odoc_name.cmi -odoc_name.cmi : ../typing/path.cmi ../parsing/longident.cmi \ +odoc_name.cmi : \ + ../typing/path.cmi \ + ../parsing/longident.cmi \ ../typing/ident.cmi odoc_ocamlhtml.cmo : odoc_ocamlhtml.cmx : -odoc_parameter.cmo : ../typing/types.cmi odoc_types.cmi -odoc_parameter.cmx : ../typing/types.cmx odoc_types.cmx -odoc_parser.cmo : odoc_types.cmi odoc_comments_global.cmi odoc_parser.cmi -odoc_parser.cmx : odoc_types.cmx odoc_comments_global.cmx odoc_parser.cmi -odoc_parser.cmi : odoc_types.cmi -odoc_print.cmo : ../typing/types.cmi ../typing/printtyp.cmi \ - ../utils/misc.cmi odoc_print.cmi -odoc_print.cmx : ../typing/types.cmx ../typing/printtyp.cmx \ - ../utils/misc.cmx odoc_print.cmi -odoc_print.cmi : ../typing/types.cmi -odoc_scan.cmo : odoc_value.cmo odoc_types.cmi odoc_type.cmo odoc_module.cmo \ - odoc_extension.cmo odoc_exception.cmo odoc_class.cmo -odoc_scan.cmx : odoc_value.cmx odoc_types.cmx odoc_type.cmx odoc_module.cmx \ - odoc_extension.cmx odoc_exception.cmx odoc_class.cmx -odoc_search.cmo : odoc_value.cmo odoc_types.cmi odoc_type.cmo \ - odoc_module.cmo odoc_extension.cmo odoc_exception.cmo odoc_class.cmo \ +odoc_parameter.cmo : \ + ../typing/types.cmi \ + odoc_types.cmi +odoc_parameter.cmx : \ + ../typing/types.cmx \ + odoc_types.cmx +odoc_parser.cmo : \ + odoc_types.cmi \ + odoc_comments_global.cmi \ + odoc_parser.cmi +odoc_parser.cmx : \ + odoc_types.cmx \ + odoc_comments_global.cmx \ + odoc_parser.cmi +odoc_parser.cmi : \ + odoc_types.cmi +odoc_print.cmo : \ + ../typing/types.cmi \ + ../typing/printtyp.cmi \ + ../utils/misc.cmi \ + ../typing/btype.cmi \ + odoc_print.cmi +odoc_print.cmx : \ + ../typing/types.cmx \ + ../typing/printtyp.cmx \ + ../utils/misc.cmx \ + ../typing/btype.cmx \ + odoc_print.cmi +odoc_print.cmi : \ + ../typing/types.cmi +odoc_scan.cmo : \ + odoc_value.cmo \ + odoc_types.cmi \ + odoc_type.cmo \ + odoc_module.cmo \ + odoc_extension.cmo \ + odoc_exception.cmo \ + odoc_class.cmo +odoc_scan.cmx : \ + odoc_value.cmx \ + odoc_types.cmx \ + odoc_type.cmx \ + odoc_module.cmx \ + odoc_extension.cmx \ + odoc_exception.cmx \ + odoc_class.cmx +odoc_search.cmo : \ + odoc_value.cmo \ + odoc_types.cmi \ + odoc_type.cmo \ + odoc_module.cmo \ + odoc_extension.cmo \ + odoc_exception.cmo \ + odoc_class.cmo \ odoc_search.cmi -odoc_search.cmx : odoc_value.cmx odoc_types.cmx odoc_type.cmx \ - odoc_module.cmx odoc_extension.cmx odoc_exception.cmx odoc_class.cmx \ +odoc_search.cmx : \ + odoc_value.cmx \ + odoc_types.cmx \ + odoc_type.cmx \ + odoc_module.cmx \ + odoc_extension.cmx \ + odoc_exception.cmx \ + odoc_class.cmx \ odoc_search.cmi -odoc_search.cmi : odoc_value.cmo odoc_types.cmi odoc_type.cmo \ - odoc_module.cmo odoc_extension.cmo odoc_exception.cmo odoc_class.cmo -odoc_see_lexer.cmo : odoc_parser.cmi -odoc_see_lexer.cmx : odoc_parser.cmx -odoc_sig.cmo : ../typing/types.cmi ../typing/typedtree.cmi \ - ../parsing/parsetree.cmi odoc_value.cmo odoc_types.cmi odoc_type.cmo \ - odoc_parameter.cmo odoc_module.cmo odoc_misc.cmi odoc_messages.cmo \ - odoc_merge.cmi odoc_global.cmi odoc_extension.cmo odoc_exception.cmo \ - odoc_env.cmi odoc_class.cmo ../utils/misc.cmi ../parsing/longident.cmi \ - ../parsing/location.cmi ../typing/ident.cmi ../typing/ctype.cmi \ - ../typing/btype.cmi ../parsing/asttypes.cmi odoc_sig.cmi -odoc_sig.cmx : ../typing/types.cmx ../typing/typedtree.cmx \ - ../parsing/parsetree.cmi odoc_value.cmx odoc_types.cmx odoc_type.cmx \ - odoc_parameter.cmx odoc_module.cmx odoc_misc.cmx odoc_messages.cmx \ - odoc_merge.cmx odoc_global.cmx odoc_extension.cmx odoc_exception.cmx \ - odoc_env.cmx odoc_class.cmx ../utils/misc.cmx ../parsing/longident.cmx \ - ../parsing/location.cmx ../typing/ident.cmx ../typing/ctype.cmx \ - ../typing/btype.cmx ../parsing/asttypes.cmi odoc_sig.cmi -odoc_sig.cmi : ../typing/types.cmi ../typing/typedtree.cmi \ - ../parsing/parsetree.cmi odoc_types.cmi odoc_type.cmo odoc_name.cmi \ - odoc_module.cmo odoc_env.cmi odoc_class.cmo ../parsing/location.cmi -odoc_str.cmo : ../typing/types.cmi ../typing/printtyp.cmi odoc_value.cmo \ - odoc_type.cmo odoc_print.cmi odoc_name.cmi odoc_misc.cmi \ - odoc_messages.cmo odoc_extension.cmo odoc_exception.cmo odoc_class.cmo \ - ../parsing/asttypes.cmi odoc_str.cmi -odoc_str.cmx : ../typing/types.cmx ../typing/printtyp.cmx odoc_value.cmx \ - odoc_type.cmx odoc_print.cmx odoc_name.cmx odoc_misc.cmx \ - odoc_messages.cmx odoc_extension.cmx odoc_exception.cmx odoc_class.cmx \ - ../parsing/asttypes.cmi odoc_str.cmi -odoc_str.cmi : ../typing/types.cmi odoc_value.cmo odoc_type.cmo \ - odoc_extension.cmo odoc_exception.cmo odoc_class.cmo -odoc_test.cmo : odoc_info.cmi odoc_gen.cmi odoc_args.cmi -odoc_test.cmx : odoc_info.cmx odoc_gen.cmx odoc_args.cmx -odoc_texi.cmo : ../typing/types.cmi odoc_to_text.cmo odoc_messages.cmo \ - odoc_info.cmi ../parsing/asttypes.cmi -odoc_texi.cmx : ../typing/types.cmx odoc_to_text.cmx odoc_messages.cmx \ - odoc_info.cmx ../parsing/asttypes.cmi -odoc_text.cmo : odoc_types.cmi odoc_text_parser.cmi odoc_text_lexer.cmo \ +odoc_search.cmi : \ + odoc_value.cmo \ + odoc_types.cmi \ + odoc_type.cmo \ + odoc_module.cmo \ + odoc_extension.cmo \ + odoc_exception.cmo \ + odoc_class.cmo +odoc_see_lexer.cmo : \ + odoc_parser.cmi +odoc_see_lexer.cmx : \ + odoc_parser.cmx +odoc_sig.cmo : \ + ../typing/types.cmi \ + ../typing/typedtree.cmi \ + ../parsing/parsetree.cmi \ + odoc_value.cmo \ + odoc_types.cmi \ + odoc_type.cmo \ + odoc_parameter.cmo \ + odoc_module.cmo \ + odoc_misc.cmi \ + odoc_messages.cmo \ + odoc_merge.cmi \ + odoc_global.cmi \ + odoc_extension.cmo \ + odoc_exception.cmo \ + odoc_env.cmi \ + odoc_class.cmo \ + ../utils/misc.cmi \ + ../parsing/longident.cmi \ + ../parsing/location.cmi \ + ../typing/ident.cmi \ + ../typing/ctype.cmi \ + ../typing/btype.cmi \ + ../parsing/asttypes.cmi \ + odoc_sig.cmi +odoc_sig.cmx : \ + ../typing/types.cmx \ + ../typing/typedtree.cmx \ + ../parsing/parsetree.cmi \ + odoc_value.cmx \ + odoc_types.cmx \ + odoc_type.cmx \ + odoc_parameter.cmx \ + odoc_module.cmx \ + odoc_misc.cmx \ + odoc_messages.cmx \ + odoc_merge.cmx \ + odoc_global.cmx \ + odoc_extension.cmx \ + odoc_exception.cmx \ + odoc_env.cmx \ + odoc_class.cmx \ + ../utils/misc.cmx \ + ../parsing/longident.cmx \ + ../parsing/location.cmx \ + ../typing/ident.cmx \ + ../typing/ctype.cmx \ + ../typing/btype.cmx \ + ../parsing/asttypes.cmi \ + odoc_sig.cmi +odoc_sig.cmi : \ + ../typing/types.cmi \ + ../typing/typedtree.cmi \ + ../parsing/parsetree.cmi \ + odoc_types.cmi \ + odoc_type.cmo \ + odoc_name.cmi \ + odoc_module.cmo \ + odoc_env.cmi \ + odoc_class.cmo \ + ../parsing/location.cmi +odoc_str.cmo : \ + ../typing/types.cmi \ + ../typing/printtyp.cmi \ + odoc_value.cmo \ + odoc_type.cmo \ + odoc_print.cmi \ + odoc_name.cmi \ + odoc_misc.cmi \ + odoc_messages.cmo \ + odoc_extension.cmo \ + odoc_exception.cmo \ + odoc_class.cmo \ + ../parsing/asttypes.cmi \ + odoc_str.cmi +odoc_str.cmx : \ + ../typing/types.cmx \ + ../typing/printtyp.cmx \ + odoc_value.cmx \ + odoc_type.cmx \ + odoc_print.cmx \ + odoc_name.cmx \ + odoc_misc.cmx \ + odoc_messages.cmx \ + odoc_extension.cmx \ + odoc_exception.cmx \ + odoc_class.cmx \ + ../parsing/asttypes.cmi \ + odoc_str.cmi +odoc_str.cmi : \ + ../typing/types.cmi \ + odoc_value.cmo \ + odoc_type.cmo \ + odoc_extension.cmo \ + odoc_exception.cmo \ + odoc_class.cmo +odoc_test.cmo : \ + odoc_info.cmi \ + odoc_gen.cmi \ + odoc_args.cmi +odoc_test.cmx : \ + odoc_info.cmx \ + odoc_gen.cmx \ + odoc_args.cmx +odoc_texi.cmo : \ + ../typing/types.cmi \ + odoc_to_text.cmo \ + odoc_messages.cmo \ + odoc_info.cmi \ + ../parsing/asttypes.cmi +odoc_texi.cmx : \ + ../typing/types.cmx \ + odoc_to_text.cmx \ + odoc_messages.cmx \ + odoc_info.cmx \ + ../parsing/asttypes.cmi +odoc_text.cmo : \ + odoc_types.cmi \ + odoc_text_parser.cmi \ + odoc_text_lexer.cmo \ odoc_text.cmi -odoc_text.cmx : odoc_types.cmx odoc_text_parser.cmx odoc_text_lexer.cmx \ +odoc_text.cmx : \ + odoc_types.cmx \ + odoc_text_parser.cmx \ + odoc_text_lexer.cmx \ odoc_text.cmi -odoc_text.cmi : odoc_types.cmi -odoc_text_lexer.cmo : odoc_text_parser.cmi odoc_misc.cmi -odoc_text_lexer.cmx : odoc_text_parser.cmx odoc_misc.cmx -odoc_text_parser.cmo : odoc_types.cmi odoc_misc.cmi odoc_text_parser.cmi -odoc_text_parser.cmx : odoc_types.cmx odoc_misc.cmx odoc_text_parser.cmi -odoc_text_parser.cmi : odoc_types.cmi -odoc_to_text.cmo : odoc_str.cmi odoc_module.cmo odoc_messages.cmo \ +odoc_text.cmi : \ + odoc_types.cmi +odoc_text_lexer.cmo : \ + odoc_text_parser.cmi \ + odoc_misc.cmi +odoc_text_lexer.cmx : \ + odoc_text_parser.cmx \ + odoc_misc.cmx +odoc_text_parser.cmo : \ + odoc_types.cmi \ + odoc_misc.cmi \ + odoc_text_parser.cmi +odoc_text_parser.cmx : \ + odoc_types.cmx \ + odoc_misc.cmx \ + odoc_text_parser.cmi +odoc_text_parser.cmi : \ + odoc_types.cmi +odoc_to_text.cmo : \ + odoc_str.cmi \ + odoc_module.cmo \ + odoc_messages.cmo \ odoc_info.cmi -odoc_to_text.cmx : odoc_str.cmx odoc_module.cmx odoc_messages.cmx \ +odoc_to_text.cmx : \ + odoc_str.cmx \ + odoc_module.cmx \ + odoc_messages.cmx \ odoc_info.cmx -odoc_type.cmo : ../typing/types.cmi odoc_types.cmi odoc_name.cmi \ +odoc_type.cmo : \ + ../typing/types.cmi \ + odoc_types.cmi \ + odoc_name.cmi \ + ../parsing/asttypes.cmi +odoc_type.cmx : \ + ../typing/types.cmx \ + odoc_types.cmx \ + odoc_name.cmx \ + ../parsing/asttypes.cmi +odoc_types.cmo : \ + odoc_messages.cmo \ + ../parsing/location.cmi \ + odoc_types.cmi +odoc_types.cmx : \ + odoc_messages.cmx \ + ../parsing/location.cmx \ + odoc_types.cmi +odoc_types.cmi : \ + ../parsing/location.cmi +odoc_value.cmo : \ + ../typing/types.cmi \ + ../typing/printtyp.cmi \ + odoc_types.cmi \ + odoc_parameter.cmo \ + odoc_name.cmi \ + odoc_misc.cmi \ ../parsing/asttypes.cmi -odoc_type.cmx : ../typing/types.cmx odoc_types.cmx odoc_name.cmx \ +odoc_value.cmx : \ + ../typing/types.cmx \ + ../typing/printtyp.cmx \ + odoc_types.cmx \ + odoc_parameter.cmx \ + odoc_name.cmx \ + odoc_misc.cmx \ ../parsing/asttypes.cmi -odoc_types.cmo : odoc_messages.cmo ../parsing/location.cmi odoc_types.cmi -odoc_types.cmx : odoc_messages.cmx ../parsing/location.cmx odoc_types.cmi -odoc_types.cmi : ../parsing/location.cmi -odoc_value.cmo : ../typing/types.cmi ../typing/printtyp.cmi odoc_types.cmi \ - odoc_parameter.cmo odoc_name.cmi odoc_misc.cmi ../parsing/asttypes.cmi -odoc_value.cmx : ../typing/types.cmx ../typing/printtyp.cmx odoc_types.cmx \ - odoc_parameter.cmx odoc_name.cmx odoc_misc.cmx ../parsing/asttypes.cmi -generators/odoc_literate.cmo : odoc_info.cmi odoc_html.cmo odoc_gen.cmi \ +generators/odoc_literate.cmo : \ + odoc_info.cmi \ + odoc_html.cmo \ + odoc_gen.cmi \ + odoc_args.cmi +generators/odoc_literate.cmx : \ + odoc_info.cmx \ + odoc_html.cmx \ + odoc_gen.cmx \ + odoc_args.cmx +generators/odoc_literate.cmxs : \ + odoc_info.cmx \ + odoc_html.cmx \ + odoc_gen.cmx \ + odoc_args.cmx +generators/odoc_todo.cmo : \ + odoc_module.cmo \ + odoc_info.cmi \ + odoc_html.cmo \ + odoc_gen.cmi \ odoc_args.cmi -generators/odoc_literate.cmx : odoc_info.cmx odoc_html.cmx odoc_gen.cmx \ +generators/odoc_todo.cmx : \ + odoc_module.cmx \ + odoc_info.cmx \ + odoc_html.cmx \ + odoc_gen.cmx \ odoc_args.cmx -generators/odoc_literate.cmxs : odoc_info.cmx odoc_html.cmx odoc_gen.cmx \ +generators/odoc_todo.cmxs : \ + odoc_module.cmx \ + odoc_info.cmx \ + odoc_html.cmx \ + odoc_gen.cmx \ odoc_args.cmx -generators/odoc_todo.cmo : odoc_module.cmo odoc_info.cmi odoc_html.cmo \ - odoc_gen.cmi odoc_args.cmi -generators/odoc_todo.cmx : odoc_module.cmx odoc_info.cmx odoc_html.cmx \ - odoc_gen.cmx odoc_args.cmx -generators/odoc_todo.cmxs : odoc_module.cmx odoc_info.cmx odoc_html.cmx \ - odoc_gen.cmx odoc_args.cmx diff --git a/ocamldoc/Changes.txt b/ocamldoc/Changes.txt index 49ed84d2..194e664a 100644 --- a/ocamldoc/Changes.txt +++ b/ocamldoc/Changes.txt @@ -80,7 +80,7 @@ Release 3.08.0: - mod: one section per to module in latex output + improve latex output - mod: odoc_latex: use buffers instead of string concatenation - add: new ocamldoc man page, thanks to Samuel Mimram - - fix: useless parenthesis around agruments of arguments of a type constructor in + - fix: useless parentheses around arguments of arguments of a type constructor in type definitions, and aournd arguments of exceptions in exception definitions. - fix: blank lines in verbatim, latex, code pre, code and ele ref modes are now accepted @@ -110,7 +110,7 @@ Release 3.08.0: - fix: bug preventing to get the code in a .mli - fix: missing spaces after carriage return in types (Odoc_misc.string_of_type_expr) - fixes: some bugs in the text parser - ( ]} meaning end of code and somehting else instead of end of precode) + ( ]} meaning end of code and something else instead of end of precode) - add: in Odoc_info: text_of_string, text_string_of_text, info_of_string - fix: better output of titles in html (use more the style) - add: -intro option to use a file content as ocamldoc comment to use as @@ -144,7 +144,7 @@ Release 3.05 : .ml and .mli when merging - option -werr becomes -warn-error - possibility to define and reference section labels - Exemple: + Example: (** {2:mysectionlabel My title bla bla bla} *) in module Foo diff --git a/ocamldoc/Makefile b/ocamldoc/Makefile index 2757bde8..f8b8cf63 100644 --- a/ocamldoc/Makefile +++ b/ocamldoc/Makefile @@ -15,25 +15,17 @@ ROOTDIR = .. -include $(ROOTDIR)/config/Makefile +include $(ROOTDIR)/Makefile.config include $(ROOTDIR)/Makefile.common OCAMLRUN ?= $(ROOTDIR)/boot/ocamlrun -OCAMLYACC ?= $(ROOTDIR)/boot/ocamlyacc +OCAMLYACC ?= $(ROOTDIR)/yacc/ocamlyacc STDLIBFLAGS = -nostdlib -I $(ROOTDIR)/stdlib OCAMLC = $(OCAMLRUN) $(ROOTDIR)/ocamlc $(STDLIBFLAGS) -ifeq "$(UNIX_OR_WIN32)" "unix" OCAMLOPT = $(OCAMLRUN) $(ROOTDIR)/ocamlopt $(STDLIBFLAGS) -else # Windows - ifeq "$(wildcard $(ROOTDIR)/flexdll/Makefile)" "" - FLEXLINK_ENV= - else - FLEXLINK_ENV=OCAML_FLEXLINK="$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/flexdll/flexlink.exe" - endif - OCAMLOPT = $(FLEXLINK_ENV) $(OCAMLRUN) $(ROOTDIR)/ocamlopt $(STDLIBFLAGS) -endif -OCAMLDEP = $(OCAMLRUN) $(ROOTDIR)/tools/ocamldep -slash +OCAMLDEP = $(OCAMLRUN) $(ROOTDIR)/boot/ocamlc -depend +DEPFLAGS = -slash OCAMLLEX = $(OCAMLRUN) $(ROOTDIR)/boot/ocamllex # TODO: figure out whether the DEBUG lines the following preprocessor removes # are actually useful. @@ -65,7 +57,8 @@ ifeq "$(UNIX_OR_WIN32)" "unix" OCAMLDOC_RUN=$(OCAMLRUN) ./$(OCAMLDOC) endif else # Windows - OCAMLDOC_RUN = CAML_LD_LIBRARY_PATH="../otherlibs/win32unix;../otherlibs/str" $(OCAMLRUN) ./$(OCAMLDOC) + OCAMLDOC_RUN = \ + CAML_LD_LIBRARY_PATH="$(ROOTDIR)/otherlibs/win32unix;$(ROOTDIR)/otherlibs/str" $(OCAMLRUN) ./$(OCAMLDOC) endif OCAMLDOC_OPT=$(OCAMLDOC).opt @@ -107,6 +100,7 @@ INCLUDES_NODEP=\ -I $(ROOTDIR)/otherlibs/$(UNIXLIB) \ -I $(ROOTDIR)/otherlibs/$(GRAPHLIB) +DEPINCLUDES=$(INCLUDES_DEP) INCLUDES=$(INCLUDES_DEP) $(INCLUDES_NODEP) COMPFLAGS=$(INCLUDES) -absname -w +a-4-9-41-42-44-45-48 -warn-error A -safe-string -strict-sequence -strict-formats -bin-annot @@ -189,8 +183,9 @@ lib: $(OCAMLDOC_LIBCMA) $(OCAMLDOC_LIBCMI) $(ODOC_TEST) .PHONY: generators generators: $(GENERATORS_CMOS) -.PHONY: opt.opt +.PHONY: opt.opt allopt # allopt and opt.opt are synonyms opt.opt: exeopt libopt generatorsopt +allopt: opt.opt .PHONY: exeopt exeopt: $(OCAMLDOC_OPT) @@ -215,7 +210,7 @@ $(OCAMLDOC): $(EXECMOFILES) $(OCAMLC) -o $@ -linkall $(LINKFLAGS) $(OCAMLDOC_BCLIBRARIES) $^ $(OCAMLDOC_OPT): $(EXECMXFILES) - $(OCAMLOPT) -o $@ -linkall $(LINKFLAGS) $(OCAMLDOC_NCLIBRARIES) $^ + $(OCAMLOPT_CMD) -o $@ -linkall $(LINKFLAGS) $(OCAMLDOC_NCLIBRARIES) $^ $(OCAMLDOC_LIBCMA): $(LIBCMOFILES) $(OCAMLC) -a -o $@ $(LINKFLAGS) $^ @@ -224,10 +219,16 @@ $(OCAMLDOC_LIBCMXA): $(LIBCMXFILES) $(OCAMLOPT) -a -o $@ $(LINKFLAGS) $^ .PHONY: manpages -manpages: stdlib_man/Pervasives.3o +manpages: stdlib_man/Stdlib.3o .PHONY: html_doc -html_doc: stdlib_html/Pervasives.html +html_doc: stdlib_html/Stdlib.html + +.PHONY: pdf_doc +pdf_doc: stdlib_latex/stdlib.pdf + +.PHONY: texi_doc +texi_doc: stdlib_texi/stdlib.texi .PHONY: dot dot: ocamldoc.dot @@ -267,16 +268,16 @@ odoc_see_lexer.ml: odoc_see_lexer.mll $(OCAMLOPT) $(OCAMLPP) $(COMPFLAGS) -c $< .ml.cmxs: - $(OCAMLOPT) -shared -o $@ $(OCAMLPP) $(COMPFLAGS) $< + $(OCAMLOPT_CMD) -shared -o $@ $(OCAMLPP) $(COMPFLAGS) $< .mll.ml: $(OCAMLLEX) $< .mly.ml: - $(OCAMLYACC) -v $< + $(OCAMLYACC) --strict -v $< .mly.mli: - $(OCAMLYACC) -v $< + $(OCAMLYACC) --strict -v $< # Installation targets ###################### @@ -296,8 +297,13 @@ install: ocamldoc.hva *.cmi $(OCAMLDOC_LIBCMA) \ "$(INSTALL_LIBDIR)/ocamldoc" $(INSTALL_DATA) \ - $(OCAMLDOC_LIBMLIS) $(OCAMLDOC_LIBCMIS) $(OCAMLDOC_LIBCMTS) \ + $(OCAMLDOC_LIBCMIS) \ + "$(INSTALL_LIBDIR)/ocamldoc" +ifeq "$(INSTALL_SOURCE_ARTIFACTS)" "true" + $(INSTALL_DATA) \ + $(OCAMLDOC_LIBMLIS) $(OCAMLDOC_LIBCMTS) \ "$(INSTALL_LIBDIR)/ocamldoc" +endif if test -d stdlib_man; then \ $(INSTALL_DATA) stdlib_man/* "$(INSTALL_MANODIR)"; \ else : ; fi @@ -316,8 +322,13 @@ installopt_really: $(INSTALL_PROG) \ $(OCAMLDOC_OPT) "$(INSTALL_BINDIR)/$(OCAMLDOC_OPT)$(EXE)" $(INSTALL_DATA) \ - $(OCAMLDOC_LIBMLIS) $(OCAMLDOC_LIBCMIS) $(OCAMLDOC_LIBCMTS) \ + $(OCAMLDOC_LIBCMIS) \ + "$(INSTALL_LIBDIR)/ocamldoc" +ifeq "$(INSTALL_SOURCE_ARTIFACTS)" "true" + $(INSTALL_DATA) \ + $(OCAMLDOC_LIBMLIS) $(OCAMLDOC_LIBCMTS) \ "$(INSTALL_LIBDIR)/ocamldoc" +endif $(INSTALL_DATA) \ ocamldoc.hva *.cmx $(OCAMLDOC_LIBA) $(OCAMLDOC_LIBCMXA) \ "$(INSTALL_LIBDIR)/ocamldoc" @@ -340,17 +351,17 @@ test: test_stdlib: $(MKDIR) $@ $(OCAMLDOC_RUN) -html -colorize-code -sort -d $@ $(INCLUDES) -dump $@/stdlib.odoc -keep-code \ - ../stdlib/*.mli \ - ../otherlibs/$(UNIXLIB)/unix.mli \ - ../otherlibs/str/str.mli + $(ROOTDIR)/stdlib/*.mli \ + $(ROOTDIR)/otherlibs/$(UNIXLIB)/unix.mli \ + $(ROOTDIR)/otherlibs/str/str.mli .PHONY: test_stdlib_code test_stdlib_code: $(MKDIR) $@ $(OCAMLDOC_RUN) -html -colorize-code -sort -d $@ $(INCLUDES) -dump $@/stdlib.odoc -keep-code \ - `ls ../stdlib/*.ml | grep -v Labels` \ - ../otherlibs/$(UNIXLIB)/unix.ml \ - ../otherlibs/str/str.ml + `ls $(ROOTDIR)/stdlib/*.ml | grep -v Labels` \ + $(ROOTDIR)/otherlibs/$(UNIXLIB)/unix.ml \ + $(ROOTDIR)/otherlibs/str/str.ml .PHONY: test_framed test_framed: @@ -361,17 +372,17 @@ test_framed: test_latex: $(MKDIR) $@ $(OCAMLDOC_RUN) -latex -sort -o $@/test.tex -d $@ $(INCLUDES) odoc*.ml \ - odoc*.mli test2.txt ../stdlib/*.mli ../otherlibs/unix/unix.mli + odoc*.mli test2.txt $(ROOTDIR)/stdlib/*.mli $(ROOTDIR)/otherlibs/unix/unix.mli .PHONY: test_latex_simple test_latex_simple: $(MKDIR) $@ $(OCAMLDOC_RUN) -latex -sort -o $@/test.tex -d $@ $(INCLUDES) \ -latextitle 6,subsection -latextitle 7,subsubection \ - ../stdlib/hashtbl.mli \ - ../stdlib/arg.mli \ - ../otherlibs/$(UNIXLIB)/unix.mli \ - ../stdlib/map.mli + $(ROOTDIR)/stdlib/hashtbl.mli \ + $(ROOTDIR)/stdlib/arg.mli \ + $(ROOTDIR)/otherlibs/$(UNIXLIB)/unix.mli \ + $(ROOTDIR)/stdlib/map.mli .PHONY: test_man test_man: @@ -386,28 +397,60 @@ test_texi: # stdlib non-prefixed : ####################### SRC=$(ROOTDIR) -include Makefile.unprefix -stdlib_man/Pervasives.3o: $(OCAMLDOC) $(STDLIB_MLIS) $(STDLIB_CMIS) - $(MKDIR) stdlib_man - $(OCAMLDOC_RUN) -man -d stdlib_man -nostdlib -I stdlib_non_prefixed \ - -t "OCaml library" -man-mini $(STDLIB_MLIS) \ - -initially-opened-module Pervasives +# Documented modules: stdlib + otherlib + utils(?) + parsing(for compiler-libs) + +include Makefile.docfiles -stdlib_html/Pervasives.html: $(OCAMLDOC) $(STDLIB_MLIS) $(STDLIB_CMIS) +stdlib_man/Stdlib.3o: $(OCAMLDOC) $(DOC_ALL) + $(MKDIR) stdlib_man + $(OCAMLDOC_RUN) -man -d stdlib_man -nostdlib \ + -hide Stdlib -lib Stdlib $(DOC_ALL_INCLUDES) \ + -pp "$(AWK) -v ocamldoc=true -f $(SRC)/stdlib/expand_module_aliases.awk" \ + -t "OCaml library" -man-mini \ + $(DOC_ALL_TEXT:%=-text %) \ + $(DOC_ALL_MLIS) + +stdlib_html/Stdlib.html: $(OCAMLDOC) $(DOC_ALL) $(MKDIR) stdlib_html - $(OCAMLDOC_RUN) -d stdlib_html -html -nostdlib -I stdlib_non_prefixed \ - -t "OCaml library" $(STDLIB_MLIS) \ - -initially-opened-module Pervasives + $(OCAMLDOC_RUN) -html -d stdlib_html -nostdlib \ + -hide Stdlib -lib Stdlib $(DOC_ALL_INCLUDES) \ + -pp "$(AWK) -v ocamldoc=true -f $(SRC)/stdlib/expand_module_aliases.awk" \ + -t "OCaml library" \ + $(DOC_ALL_TEXT:%=-text %) \ + $(DOC_ALL_MLIS) + +stdlib_texi/stdlib.texi: $(OCAMLDOC) $(DOC_ALL) + $(MKDIR) stdlib_texi + $(OCAMLDOC_RUN) -texi -o stdlib_texi/stdlib.texi -nostdlib \ + -hide Stdlib -lib Stdlib $(DOC_ALL_INCLUDES) \ + -pp "$(AWK) -v ocamldoc=true -f $(SRC)/stdlib/expand_module_aliases.awk" \ + -t "OCaml library" \ + $(DOC_ALL_TEXT:%=-text %) \ + $(DOC_ALL_MLIS) + + +stdlib_latex/stdlib.tex: $(OCAMLDOC) $(DOC_ALL) + $(MKDIR) stdlib_latex + $(OCAMLDOC_RUN) -latex -o stdlib_latex/stdlib.tex -nostdlib \ + -hide Stdlib -lib Stdlib $(DOC_ALL_INCLUDES) \ + -pp "$(AWK) -v ocamldoc=true -f $(SRC)/stdlib/expand_module_aliases.awk" \ + -t "OCaml library" \ + $(DOC_ALL_TEXT:%=-text %) \ + $(DOC_ALL_MLIS) + +stdlib_latex/stdlib.pdf: stdlib_latex/stdlib.tex + cd stdlib_latex && pdflatex stdlib && pdflatex stdlib + .PHONY: autotest_stdlib autotest_stdlib: $(MKDIR) $@ $(OCAMLDOC_RUN) -g autotest/odoc_test.cmo\ $(INCLUDES) -keep-code \ - ../stdlib/*.mli \ - ../otherlibs/$(UNIXLIB)/unix.mli \ - ../otherlibs/str/str.mli + $(ROOTDIR)/stdlib/*.mli \ + $(ROOTDIR)/otherlibs/$(UNIXLIB)/unix.mli \ + $(ROOTDIR)/otherlibs/str/str.mli # odoc rules : @@ -418,22 +461,22 @@ odoc: rm -rf odoc $(MKDIR) odoc # .cmti --> .odoc - for fn in ../stdlib/stdlib*.cmti; do \ - odoc compile $(INCLUDES) --package stdlib ../stdlib/$$fn; \ + for fn in $(ROOTDIR)/stdlib/stdlib*.cmti; do \ + odoc compile $(INCLUDES) --package stdlib $(ROOTDIR)/stdlib/$$fn; \ done for lib in str bigarray; do \ - odoc compile $(INCLUDES) --package $$lib ../otherlibs/$$lib/$$lib.cmti; \ + odoc compile $(INCLUDES) --package $$lib $(ROOTDIR)/otherlibs/$$lib/$$lib.cmti; \ done - odoc compile $(INCLUDES) --package unix ../otherlibs/$(UNIXLIB)/unix.cmti - for fn in ../parsing/*.cmti; do \ - odoc compile $(INCLUDES) --package parsing ../parsing/$$fn; \ + odoc compile $(INCLUDES) --package unix $(ROOTDIR)/otherlibs/$(UNIXLIB)/unix.cmti + for fn in $(ROOTDIR)/parsing/*.cmti; do \ + odoc compile $(INCLUDES) --package parsing $(ROOTDIR)/parsing/$$fn; \ done # .odoc --> .html - odoc html $(INCLUDES) --output-dir odoc ../stdlib/stdlib.odoc + odoc html $(INCLUDES) --output-dir odoc $(ROOTDIR)/stdlib/stdlib.odoc for lib in str bigarray $(UNIXLIB); do \ - odoc html $(INCLUDES) --output-dir odoc ../otherlibs/$$lib/$$lib.odoc; \ + odoc html $(INCLUDES) --output-dir odoc $(ROOTDIR)/otherlibs/$$lib/$$lib.odoc; \ done - for fn in ../parsing/*.odoc; do \ + for fn in $(ROOTDIR)/parsing/*.odoc; do \ odoc html $(INCLUDES) --output-dir odoc $$fn; \ done for d in odoc/*; do \ @@ -457,9 +500,8 @@ clean: rm -f odoc_parser.output odoc_text_parser.output rm -f odoc_lexer.ml odoc_text_lexer.ml odoc_see_lexer.ml odoc_ocamlhtml.ml rm -f odoc_parser.ml odoc_parser.mli odoc_text_parser.ml odoc_text_parser.mli - rm -rf stdlib_man stdlib_html + rm -rf stdlib_man stdlib_html stdlib_texi stdlib_latex rm -f generators/*.cm[taiox] generators/*.$(A) generators/*.$(O) generators/*.cmx[as] - rm -f stdlib_non_prefixed/*.mli stdlib_non_prefixed/*.cmi .PHONY: depend depend: @@ -469,7 +511,7 @@ depend: $(OCAMLLEX) odoc_lexer.mll $(OCAMLLEX) odoc_ocamlhtml.mll $(OCAMLLEX) odoc_see_lexer.mll - $(OCAMLDEP) $(INCLUDES_DEP) *.mll *.mly *.ml *.mli > .depend - $(OCAMLDEP) $(INCLUDES_DEP) -shared generators/*.ml >> .depend + $(OCAMLDEP) $(DEPFLAGS) $(DEPINCLUDES) *.mll *.mly *.ml *.mli > .depend + $(OCAMLDEP) $(DEPFLAGS) $(DEPINCLUDES) -shared generators/*.ml >> .depend include .depend diff --git a/ocamldoc/Makefile.docfiles b/ocamldoc/Makefile.docfiles new file mode 100644 index 00000000..fdeb7bf1 --- /dev/null +++ b/ocamldoc/Makefile.docfiles @@ -0,0 +1,72 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Florian Angeletti * +#* * +#* Copyright 2018 * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +# Define the lists of mli file used by ocamldoc to generate the stdlib +# + otherlibs + compilerlibs + plugin hooks documentation + +include $(SRC)/Makefile.config +include $(SRC)/stdlib/StdlibModules +PARSING_MLIS := $(wildcard $(SRC)/parsing/*.mli) +UTILS_MLIS := $(wildcard $(SRC)/utils/*.mli) +TYPING_MLIS := $(SRC)/typing/typemod.mli +BYTECOMP_MLIS := $(SRC)/bytecomp/simplif.mli +STR_MLIS = $(addprefix $(SRC)/otherlibs/str/, str.mli) +UNIX_MLIS = $(addprefix $(SRC)/otherlibs/unix/, unix.mli unixLabels.mli) +GRAPHICS_MLIS = $(addprefix $(SRC)/otherlibs/graph/, graphics.mli graphicsX11.mli) +DYNLINK_MLIS = $(addprefix $(SRC)/otherlibs/dynlink/, dynlink.mli) +THREAD_MLIS = $(addprefix $(SRC)/otherlibs/systhreads/, \ + thread.mli condition.mli mutex.mli event.mli threadUnix.mli) +DRIVER_MLIS = $(SRC)/driver/pparse.mli + + +DOC_STDLIB_DIRS = stdlib \ + otherlibs/str \ + otherlibs/$(UNIXLIB) otherlibs/graphics otherlibs/dynlink \ + otherlibs/systhreads + +DOC_COMPILERLIBS_DIRS= parsing utils typing bytecomp driver + +DOC_ALL_DIRS = $(DOC_COMPILERLIBS) $(DOC_STDLIB_DIRS) + +DOC_STDLIB_INCLUDES = $(addprefix -I $(SRC)/, $(DOC_STDLIB_DIRS)) +DOC_COMPILERLIBS_INCLUDES = $(addprefix -I $(SRC)/, $(DOC_COMPILERLIBS_DIRS)) + +DOC_ALL_INCLUDES = $(DOC_STDLIB_INCLUDES) $(DOC_COMPILERLIBS_INCLUDES) + +STDLIB_MODS = $(STDLIB_MODULES:stdlib__%=%) + +STDLIB_MOD_WP = $(filter-out stdlib__pervasives, $(STDLIB_MODULES)) +STDLIB_MLI0 = $(SRC)/stdlib/pervasives.ml $(STDLIB_MOD_WP:%=$(SRC)/stdlib/%.mli) +STDLIB_MLIS=\ + $(STDLIB_MLI0:$(SRC)/stdlib/stdlib__%=$(SRC)/stdlib/%) \ + $(STR_MLIS) \ + $(UNIX_MLIS) \ + $(THREAD_MLIS) \ + $(GRAPHICS_MLIS) \ + $(DYNLINK_MLIS) + +COMPILERLIBS_MLIS=\ + $(PARSING_MLIS) \ + $(UTILS_MLIS) \ + $(TYPING_MLIS) \ + $(BYTECOMP_MLIS) \ + $(DRIVER_MLIS) + +DOC_STDLIB_TEXT = $(SRC)/stdlib/ocaml_operators.mld +DOC_COMPILERLIBS_TEXT = $(SRC)/manual/manual/library/compiler_libs.mld +DOC_ALL_TEXT = $(DOC_STDLIB_TEXT) $(DOC_COMPILERLIBS_TEXT) + + +DOC_ALL_MLIS= $(STDLIB_MLIS) $(COMPILERLIBS_MLIS) +DOC_ALL = $(DOC_ALL_MLIS) $(DOC_ALL_TEXT) diff --git a/ocamldoc/Makefile.nt b/ocamldoc/Makefile.nt deleted file mode 100644 index 46ed1c31..00000000 --- a/ocamldoc/Makefile.nt +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Maxence Guesdon, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 2001 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include Makefile diff --git a/ocamldoc/Makefile.unprefix b/ocamldoc/Makefile.unprefix deleted file mode 100644 index 1b036773..00000000 --- a/ocamldoc/Makefile.unprefix +++ /dev/null @@ -1,102 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Florian Angeletti * -#* * -#* Copyright 2017 * -#* * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - - -include $(SRC)/config/Makefile - -P := -VPATH=.:$(SRC) -include $(SRC)/stdlib/StdlibModules - -STDLIB_UNPREFIXED=$(SRC)/ocamldoc/stdlib_non_prefixed - -STDLIB_MODULES := pervasives $(filter-out stdlib,$(STDLIB_MODULES)) -PARSING_MLIS := $(wildcard $(SRC)/parsing/*.mli) -UTILS_MLIS := $(wildcard $(SRC)/utils/*.mli) -TYPING_MLIS := $(wildcard $(SRC)/typing/*.mli) -BYTECOMP_MLIS := $(wildcard $(SRC)/bytecomp/*.mli) - -# Documented modules: stdlib + otherlib + utils(?) + parsing(for compiler-libs) -STDLIB_MLIS=\ - $(STDLIB_MODULES:%=%.mli) \ - $(PARSING_MLIS:$(SRC)/parsing/%.mli=%.mli) \ - $(UTILS_MLIS:$(SRC)/utils/%.mli=%.mli) \ - str.mli \ - unix.mli unixLabels.mli \ - graphics.mli graphicsX11.mli \ - dynlink.mli \ - thread.mli mutex.mli condition.mli event.mli threadUnix.mli \ - pparse.mli - -STDLIB_MLIS:=$(addprefix $(STDLIB_UNPREFIXED)/, $(STDLIB_MLIS)) - -# Dependencies for the documented modules -STDLIB_DEPS:=$(STDLIB_MLIS) \ - $(TYPING_MLIS:$(SRC)/typing/%.mli=$(STDLIB_UNPREFIXED)/%.mli) \ - $(BYTECOMP_MLIS:$(SRC)/bytecomp/%.mli=$(STDLIB_UNPREFIXED)/%.mli) - -# Add back the isolated modules in typing and bytecomp -STDLIB_MLIS:= $(STDLIB_MLIS) \ -$(addprefix $(STDLIB_UNPREFIXED)/, typemod.mli simplif.mli) - - -STDLIB_CMIS=$(STDLIB_DEPS:%.mli=%.cmi) - - -# Copy mli files from the main source directory - -$(STDLIB_UNPREFIXED)/%.mli: $(SRC)/stdlib/%.mli - cp $< $@ - -$(STDLIB_UNPREFIXED)/%.mli: $(SRC)/parsing/%.mli - cp $< $@ - -$(STDLIB_UNPREFIXED)/%.mli: $(SRC)/utils/%.mli - cp $< $@ - -$(STDLIB_UNPREFIXED)/%.mli: $(SRC)/otherlibs/$(UNIXLIB)/%.mli - sed 's/Stdlib\.//g' $< > $@ - -$(STDLIB_UNPREFIXED)/%.mli: $(SRC)/otherlibs/str/%.mli - cp $< $@ - -$(STDLIB_UNPREFIXED)/%.mli: $(SRC)/otherlibs/num/%.mli - cp $< $@ - -$(STDLIB_UNPREFIXED)/%.mli: $(SRC)/otherlibs/graph/%.mli - cp $< $@ - -$(STDLIB_UNPREFIXED)/%.mli: $(SRC)/otherlibs/threads/%.mli - cp $< $@ - -$(STDLIB_UNPREFIXED)/%.mli: $(SRC)/otherlibs/dynlink/%.mli - cp $< $@ - -$(STDLIB_UNPREFIXED)/%.mli: $(SRC)/driver/%.mli - cp $< $@ - -$(STDLIB_UNPREFIXED)/%.mli: $(SRC)/typing/%.mli - cp $< $@ - -$(STDLIB_UNPREFIXED)/%.mli: $(SRC)/bytecomp/%.mli - cp $< $@ - -#Extract the pervasives module from stdlib.mli -$(STDLIB_UNPREFIXED)/pervasives.mli: $(SRC)/stdlib/stdlib.mli $(STDLIB_UNPREFIXED)/extract_pervasives.awk - $(AWK) -f $(STDLIB_UNPREFIXED)/extract_pervasives.awk $< > $@ - -# Build cmis file inside the STDLIB_UNPREFIXED directories -$(STDLIB_CMIS): $(STDLIB_DEPS) - cd $(STDLIB_UNPREFIXED); $(MAKE) $(notdir $(STDLIB_CMIS)) diff --git a/ocamldoc/dune b/ocamldoc/dune new file mode 100644 index 00000000..be7a042f --- /dev/null +++ b/ocamldoc/dune @@ -0,0 +1,25 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +(ocamllex odoc_lexer odoc_ocamlhtml odoc_see_lexer odoc_text_lexer) +(ocamlyacc odoc_parser odoc_text_parser) + +(executable + (name odoc) + (modes byte) + (flags (:standard -nostdlib -w -9-32)) + (libraries dynlink ocamlcommon stdlib runtime str unix)) + +(rule + (copy odoc.exe ocamldoc.byte)) diff --git a/ocamldoc/odoc_analyse.ml b/ocamldoc/odoc_analyse.ml index ff79ece7..8cae70af 100644 --- a/ocamldoc/odoc_analyse.ml +++ b/ocamldoc/odoc_analyse.ml @@ -26,25 +26,27 @@ open Typedtree The current directory is always searched first, then the directories specified with the -I option (in command-line order), then the standard library directory. *) -let init_path () = - Config.load_path := - "" :: List.rev ( Clflags.std_include_dir () @ !Clflags.include_dirs); - Env.reset_cache () +let init_path () = Compmisc.init_path false (** Return the initial environment in which compilation proceeds. *) let initial_env () = + let current = Env.get_unit_name () in + let initial = !Odoc_global.initially_opened_module in let initially_opened_module = - let m = !Odoc_global.initially_opened_module in - if m = Env.get_unit_name () then + if initial = current then None else - Some m + Some initial in + let open_implicit_modules = + let ln = !Odoc_global.library_namespace in + let ln = if current = ln || ln = initial || ln = "" then [] else [ln] in + ln @ List.rev !Clflags.open_modules in Typemod.initial_env ~loc:(Location.in_file "ocamldoc command line") ~safe_string:(Config.safe_string || not !Clflags.unsafe_string) + ~open_implicit_modules ~initially_opened_module - ~open_implicit_modules:(List.rev !Clflags.open_modules) (** Optionally preprocess a source file *) let preprocess sourcefile = @@ -76,7 +78,7 @@ let process_implementation_file sourcefile = let env = initial_env () in try let parsetree = - Pparse.file ~tool_name Format.err_formatter inputfile + Pparse.file ~tool_name inputfile (no_docstring Parse.implementation) Pparse.Structure in let typedtree = @@ -85,18 +87,19 @@ let process_implementation_file sourcefile = in (Some (parsetree, typedtree), inputfile) with - e -> - match e with - Syntaxerr.Error err -> + | Syntaxerr.Error _ as exn -> + begin match Location.error_of_exn exn with + | Some (`Ok err) -> fprintf Format.err_formatter "@[%a@]@." - Syntaxerr.report_error err; - None, inputfile - | Failure s -> - prerr_endline s; - incr Odoc_global.errors ; - None, inputfile - | e -> - raise e + Location.print_report err + | _ -> + assert false + end; + None, inputfile + | Failure s -> + prerr_endline s; + incr Odoc_global.errors ; + None, inputfile (** Analysis of an interface file. Returns (Some signature) if no error occurred, else None and an error message is printed.*) @@ -107,7 +110,7 @@ let process_interface_file sourcefile = Env.set_unit_name modulename; let inputfile = preprocess sourcefile in let ast = - Pparse.file ~tool_name Format.err_formatter inputfile + Pparse.file ~tool_name inputfile (no_docstring Parse.interface) Pparse.Signature in let sg = Typemod.type_interface sourcefile (initial_env()) ast in diff --git a/ocamldoc/odoc_args.ml b/ocamldoc/odoc_args.ml index cdaf1993..ff86aa6d 100644 --- a/ocamldoc/odoc_args.ml +++ b/ocamldoc/odoc_args.ml @@ -199,9 +199,9 @@ let anonymous f = module Options = Main_args.Make_ocamldoc_options(struct let set r () = r := true let unset r () = r := false - let _absname = set Location.absname - let _I s = Odoc_global.include_dirs := - (Misc.expand_directory Config.standard_library s) :: !Odoc_global.include_dirs + let _absname = set Clflags.absname + let _alert = Warnings.parse_alert_option + let _I s = Odoc_global.include_dirs := s :: !Odoc_global.include_dirs let _impl s = Odoc_global.files := !Odoc_global.files @ [Odoc_global.Impl_file s] let _intf s = Odoc_global.files := !Odoc_global.files @ [Odoc_global.Intf_file s] let _intf_suffix s = Config.interface_suffix := s @@ -250,6 +250,7 @@ module Options = Main_args.Make_ocamldoc_options(struct let _dlambda = set Clflags.dump_lambda let _dflambda = set Clflags.dump_flambda let _dinstr = set Clflags.dump_instr + let _dcamlprimc = set Clflags.keep_camlprimc_file let anonymous = anonymous end) @@ -258,6 +259,7 @@ let default_options = Options.list @ [ "-initially-opened-module", Arg.Set_string Odoc_global.initially_opened_module, M.initially_opened_module; + "-lib", Arg.Set_string Odoc_global.library_namespace, M.library_namespace; "-text", Arg.String (fun s -> Odoc_global.files := !Odoc_global.files @ [Odoc_global.Text_file s]), M.option_text ; diff --git a/ocamldoc/odoc_ast.ml b/ocamldoc/odoc_ast.ml index a6a5e55c..ac9a5dbe 100644 --- a/ocamldoc/odoc_ast.ml +++ b/ocamldoc/odoc_ast.ml @@ -77,7 +77,7 @@ module Typedtree_search = | ext :: _ -> Hashtbl.add table (X (Name.from_ident ext.ext_id)) tt end | Typedtree.Tstr_exception ext -> - Hashtbl.add table (E (Name.from_ident ext.ext_id)) tt + Hashtbl.add table (E (Name.from_ident ext.tyexn_constructor.ext_id)) tt | Typedtree.Tstr_type (rf, ident_type_decl_list) -> List.iter (fun td -> @@ -935,7 +935,7 @@ module Analyser = let f = match ele with Element_module m -> (function - Types.Sig_module (ident,md,_) -> + Types.Sig_module (ident,_,md,_,_) -> let n1 = Name.simple m.m_name and n2 = Ident.name ident in ( @@ -946,7 +946,7 @@ module Analyser = | _ -> false) | Element_module_type mt -> (function - Types.Sig_modtype (ident,{Types.mtd_type=Some t}) -> + Types.Sig_modtype (ident,{Types.mtd_type=Some t},_) -> let n1 = Name.simple mt.mt_name and n2 = Ident.name ident in ( @@ -957,14 +957,14 @@ module Analyser = | _ -> false) | Element_value v -> (function - Types.Sig_value (ident,_) -> + Types.Sig_value (ident,_, _) -> let n1 = Name.simple v.val_name and n2 = Ident.name ident in n1 = n2 | _ -> false) | Element_type t -> (function - Types.Sig_type (ident,_,_) -> + Types.Sig_type (ident,_,_,_) -> (* FIXME: type details can be hidden *) let n1 = Name.simple t.ty_name and n2 = Ident.name ident in @@ -980,21 +980,21 @@ module Analyser = else (fun _ -> false) | Element_exception e -> (function - Types.Sig_typext (ident,_,_) -> + Types.Sig_typext (ident,_,_, _) -> let n1 = Name.simple e.ex_name and n2 = Ident.name ident in n1 = n2 | _ -> false) | Element_class c -> (function - Types.Sig_class (ident,_,_) -> + Types.Sig_class (ident,_,_, _) -> let n1 = Name.simple c.cl_name and n2 = Ident.name ident in n1 = n2 | _ -> false) | Element_class_type ct -> (function - Types.Sig_class_type (ident,_,_) -> + Types.Sig_class_type (ident,_,_, _) -> let n1 = Name.simple ct.clt_name and n2 = Ident.name ident in n1 = n2 @@ -1010,7 +1010,7 @@ module Analyser = let pred xt = List.exists (function - Types.Sig_typext (ident, _, _) -> + Types.Sig_typext (ident, _, _, _) -> let n1 = Name.simple xt.xt_name and n2 = Ident.name ident in n1 = n2 @@ -1344,7 +1344,7 @@ module Analyser = (maybe_more, new_env, [ Element_type_extension new_te ]) | Parsetree.Pstr_exception ext -> - let name = ext.Parsetree.pext_name in + let name = ext.Parsetree.ptyexn_constructor.Parsetree.pext_name in (* a new exception is defined *) let complete_name = Name.concat current_module_name name.txt in (* we get the exception declaration in the typed tree *) @@ -1355,7 +1355,7 @@ module Analyser = in let new_env = Odoc_env.add_extension env complete_name in let new_ext = - match tt_ext.ext_kind with + match tt_ext.Typedtree.tyexn_constructor.ext_kind with Text_decl(tt_args, tt_ret_type) -> let loc_start = loc.Location.loc_start.Lexing.pos_cnum in let loc_end = loc.Location.loc_end.Lexing.pos_cnum in diff --git a/ocamldoc/odoc_comments.ml b/ocamldoc/odoc_comments.ml index 4ccd6dd1..e408829b 100644 --- a/ocamldoc/odoc_comments.ml +++ b/ocamldoc/odoc_comments.ml @@ -151,8 +151,8 @@ module Info_retriever = (n, acc) | (n2, Some i) -> print_DEBUG ("all_special: avant String.sub new_s="^s2); - print_DEBUG ("n2="^(string_of_int n2)) ; - print_DEBUG ("len(s2)="^(string_of_int (String.length s2))) ; + print_DEBUG ("n2="^(Int.to_string n2)) ; + print_DEBUG ("len(s2)="^(Int.to_string (String.length s2))) ; let new_s = String.sub s2 n2 ((String.length s2) - n2) in print_DEBUG ("all_special: apres String.sub new_s="^new_s); iter (acc @ [i]) (n + n2) new_s diff --git a/ocamldoc/odoc_cross.ml b/ocamldoc/odoc_cross.ml index 57f461fc..143c675d 100644 --- a/ocamldoc/odoc_cross.ml +++ b/ocamldoc/odoc_cross.ml @@ -31,7 +31,7 @@ open Odoc_parameter module S = Set.Make ( struct type t = string * ref_kind option - let compare = Pervasives.compare + let compare = Stdlib.compare end ) @@ -138,13 +138,7 @@ let get_alias_names module_list = Hashtbl.clear exception_aliases; build_alias_list (Search_alias.search module_list 0) -module Map_ord = - struct - type t = string - let compare (x:t) y = Pervasives.compare x y - end - -module Ele_map = Map.Make (Map_ord) +module Ele_map = Misc.Stdlib.String.Map let known_elements = ref Ele_map.empty let add_known_element name k = @@ -406,8 +400,12 @@ and associate_in_module_type module_list (acc_b_modif, acc_incomplete_top_module Some _ -> (acc_b, acc_inc, acc_names) | None -> + let mta_name = + Name.get_relative_opt + !Odoc_global.library_namespace + mta.mta_name in let mt_opt = - try Some (lookup_module_type mta.mta_name) + try Some (lookup_module_type mta_name) with Not_found -> None in match mt_opt with @@ -418,7 +416,7 @@ and associate_in_module_type module_list (acc_b_modif, acc_incomplete_top_module mta.mta_name = Odoc_messages.sig_end then acc_names else - (NF_mt mta.mta_name) :: acc_names) + (NF_mt mta_name) :: acc_names) ) | Some mt -> mta.mta_module <- Some mt ; diff --git a/ocamldoc/odoc_dep.ml b/ocamldoc/odoc_dep.ml index 5f8bd065..5e6c7837 100644 --- a/ocamldoc/odoc_dep.ml +++ b/ocamldoc/odoc_dep.ml @@ -15,24 +15,23 @@ (** Top modules dependencies. *) -module StrS = Depend.StringSet -module StrM = Depend.StringMap module Module = Odoc_module module Type = Odoc_type +module String = Misc.Stdlib.String let set_to_list s = let l = ref [] in - StrS.iter (fun e -> l := e :: !l) s; + String.Set.iter (fun e -> l := e :: !l) s; !l let impl_dependencies ast = - Depend.free_structure_names := StrS.empty; - Depend.add_use_file StrM.empty [Parsetree.Ptop_def ast]; + Depend.free_structure_names := String.Set.empty; + Depend.add_use_file String.Map.empty [Parsetree.Ptop_def ast]; set_to_list !Depend.free_structure_names let intf_dependencies ast = - Depend.free_structure_names := StrS.empty; - Depend.add_signature StrM.empty ast; + Depend.free_structure_names := String.Set.empty; + Depend.add_signature String.Map.empty ast; set_to_list !Depend.free_structure_names @@ -40,20 +39,15 @@ module Dep = struct type id = string - module S = Set.Make (struct - type t = string - let compare (x:t) y = compare x y - end) - let set_to_list s = let l = ref [] in - S.iter (fun e -> l := e :: !l) s; + String.Set.iter (fun e -> l := e :: !l) s; !l type node = { id : id ; - mutable near : S.t ; (** direct children *) - mutable far : (id * S.t) list ; (** indirect children, from which children path *) + mutable near : String.Set.t ; (** direct children *) + mutable far : (id * String.Set.t) list ; (** indirect children, from which children path *) reflex : bool ; (** reflexive or not, we keep information here to remove the node itself from its direct children *) } @@ -62,12 +56,12 @@ module Dep = let make_node s children = let set = List.fold_right - S.add + String.Set.add children - S.empty + String.Set.empty in { id = s; - near = S.remove s set ; + near = String.Set.remove s set ; far = [] ; reflex = List.mem s children ; } @@ -78,20 +72,20 @@ module Dep = make_node s [] let rec trans_closure graph acc n = - if S.mem n.id acc then + if String.Set.mem n.id acc then acc else (* potential optimisation: use far field if nonempty? *) - S.fold + String.Set.fold (fun child -> fun acc2 -> trans_closure graph acc2 (get_node graph child)) n.near - (S.add n.id acc) + (String.Set.add n.id acc) let node_trans_closure graph n = let far = List.map (fun child -> - let set = trans_closure graph S.empty (get_node graph child) in + let set = trans_closure graph String.Set.empty (get_node graph child) in (child, set) ) (set_to_list n.near) @@ -102,22 +96,22 @@ module Dep = List.iter (node_trans_closure graph) graph let prune_node graph node = - S.iter + String.Set.iter (fun child -> let set_reachables = List.fold_left (fun acc -> fun (ch, reachables) -> if child = ch then acc else - S.union acc reachables + String.Set.union acc reachables ) - S.empty + String.Set.empty node.far in - let set = S.remove node.id set_reachables in - if S.exists (fun n2 -> S.mem child (get_node graph n2).near) set then + let set = String.Set.remove node.id set_reachables in + if String.Set.exists (fun n2 -> String.Set.mem child (get_node graph n2).near) set then ( - node.near <- S.remove child node.near ; + node.near <- String.Set.remove child node.near ; node.far <- List.filter (fun (ch,_) -> ch <> child) node.far ) else @@ -125,7 +119,7 @@ module Dep = ) node.near; if node.reflex then - node.near <- S.add node.id node.near + node.near <- String.Set.add node.id node.near else () @@ -192,7 +186,7 @@ let kernel_deps_of_modules modules = (fun m -> let node = Dep.get_node k m.Module.m_name in m.Module.m_top_deps <- - List.filter (fun m2 -> Dep.S.mem m2 node.Dep.near) m.Module.m_top_deps) + List.filter (fun m2 -> String.Set.mem m2 node.Dep.near) m.Module.m_top_deps) modules (** Return the list of dependencies between the given types, diff --git a/ocamldoc/odoc_env.ml b/ocamldoc/odoc_env.ml index ffb1dd20..446ad121 100644 --- a/ocamldoc/odoc_env.ml +++ b/ocamldoc/odoc_env.ml @@ -53,17 +53,17 @@ let rec add_signature env root ?rel signat = in let f env item = match item with - Types.Sig_value (ident, _) -> { env with env_values = (rel_name ident, qualify ident) :: env.env_values } - | Types.Sig_type (ident,_,_) -> { env with env_types = (rel_name ident, qualify ident) :: env.env_types } - | Types.Sig_typext (ident, _, _) -> { env with env_extensions = (rel_name ident, qualify ident) :: env.env_extensions } - | Types.Sig_module (ident, md, _) -> + Types.Sig_value (ident, _, _) -> { env with env_values = (rel_name ident, qualify ident) :: env.env_values } + | Types.Sig_type (ident,_,_,_) -> { env with env_types = (rel_name ident, qualify ident) :: env.env_types } + | Types.Sig_typext (ident, _, _, _) -> { env with env_extensions = (rel_name ident, qualify ident) :: env.env_extensions } + | Types.Sig_module (ident, _, md, _, _) -> let env2 = match md.Types.md_type with (* FIXME: we don't have signature for identifiers *) Types.Mty_signature s -> add_signature env (qualify ident) ~rel: (rel_name ident) s | _ -> env in { env2 with env_modules = (rel_name ident, qualify ident) :: env2.env_modules } - | Types.Sig_modtype (ident, modtype_decl) -> + | Types.Sig_modtype (ident, modtype_decl, _) -> let env2 = match modtype_decl.Types.mtd_type with None -> @@ -75,8 +75,8 @@ let rec add_signature env root ?rel signat = | _ -> env in { env2 with env_module_types = (rel_name ident, qualify ident) :: env2.env_module_types } - | Types.Sig_class (ident, _, _) -> { env with env_classes = (rel_name ident, qualify ident) :: env.env_classes } - | Types.Sig_class_type (ident, _, _) -> { env with env_class_types = (rel_name ident, qualify ident) :: env.env_class_types } + | Types.Sig_class (ident, _, _, _) -> { env with env_classes = (rel_name ident, qualify ident) :: env.env_classes } + | Types.Sig_class_type (ident, _, _, _) -> { env with env_class_types = (rel_name ident, qualify ident) :: env.env_class_types } in List.fold_left f env signat diff --git a/ocamldoc/odoc_global.ml b/ocamldoc/odoc_global.ml index 92b9308e..3bb1a67c 100644 --- a/ocamldoc/odoc_global.ml +++ b/ocamldoc/odoc_global.ml @@ -79,3 +79,5 @@ let with_toc = ref true let with_index = ref true let initially_opened_module = ref "Stdlib" + +let library_namespace = ref "" diff --git a/ocamldoc/odoc_global.mli b/ocamldoc/odoc_global.mli index 509f0243..c85b4534 100644 --- a/ocamldoc/odoc_global.mli +++ b/ocamldoc/odoc_global.mli @@ -105,3 +105,6 @@ val with_trailer : bool ref (** Name of the module that is initially opened. *) val initially_opened_module : string ref + +(** Name of the library namespace for a prefixed library *) +val library_namespace: string ref diff --git a/ocamldoc/odoc_html.ml b/ocamldoc/odoc_html.ml index 93c279c1..e9b98fd1 100644 --- a/ocamldoc/odoc_html.ml +++ b/ocamldoc/odoc_html.ml @@ -24,6 +24,7 @@ open Extension open Exception open Class open Module +module String = Misc.Stdlib.String let with_parameter_list = ref false let css_style = ref None @@ -230,11 +231,6 @@ module Naming = type_prefix^name^".html" end -module StringSet = Set.Make (struct - type t = string - let compare (x:t) y = compare x y -end) - (** A class with a method to colorize a string which represents OCaml code. *) class ocaml_code = object @@ -946,17 +942,17 @@ class html = (** The known types names. Used to know if we must create a link to a type when printing a type. *) - val mutable known_types_names = StringSet.empty + val mutable known_types_names = String.Set.empty (** The known class and class type names. Used to know if we must create a link to a class or class type or not when printing a type. *) - val mutable known_classes_names = StringSet.empty + val mutable known_classes_names = String.Set.empty (** The known modules and module types names. Used to know if we must create a link to a type or not when printing a module type. *) - val mutable known_modules_names = StringSet.empty + val mutable known_modules_names = String.Set.empty method index_prefix = if !Odoc_global.out_file = Odoc_messages.default_out_file then @@ -1244,20 +1240,30 @@ class html = type (or class or class type) idents have been replaced by links to the type referenced by the ident.*) method create_fully_qualified_idents_links m_name s = + let ln = !Odoc_global.library_namespace in let f str_t = let match_s = Str.matched_string str_t in + let known_type = String.Set.mem match_s known_types_names in + let known_class = String.Set.mem match_s known_classes_names in + let retry, match_s = if not (known_type || known_class) && ln <> "" then + true, Name.get_relative_opt ln match_s + else + false, match_s + in let rel = Name.get_relative m_name match_s in let s_final = Odoc_info.apply_if_equal Odoc_info.use_hidden_modules match_s rel in - if StringSet.mem match_s known_types_names then + if known_type || + (retry && String.Set.mem match_s known_types_names) then ""^ s_final^ "" else - if StringSet.mem match_s known_classes_names then + if known_class || + (retry && String.Set.mem match_s known_classes_names) then let (html_file, _) = Naming.html_files match_s in ""^s_final^"" else @@ -1273,13 +1279,21 @@ class html = method create_fully_qualified_module_idents_links m_name s = let f str_t = let match_s = Str.matched_string str_t in + let known_module = String.Set.mem match_s known_modules_names in + let ln = !Odoc_global.library_namespace in + let retry, match_s = + if not known_module && ln <> "" then + true, Name.get_relative_opt ln match_s + else + false, match_s in let rel = Name.get_relative m_name match_s in let s_final = Odoc_info.apply_if_equal Odoc_info.use_hidden_modules match_s rel in - if StringSet.mem match_s known_modules_names then + if known_module || + (retry && String.Set.mem match_s known_modules_names) then let (html_file, _) = Naming.html_files match_s in ""^s_final^"" else @@ -2404,12 +2418,17 @@ class html = let f_ele e = let simple_name = Name.simple (name e) in let father_name = Name.father (name e) in + if father_name = "Stdlib" && father_name <> simple_name then + (* avoid duplicata *) () + else + begin bp b "%s " (target e) (self#escape simple_name); if simple_name <> father_name && father_name <> "" then bp b "[%s]" (fst (Naming.html_files father_name)) father_name; bs b "\n"; self#html_of_info_first_sentence b (info e); - bs b "\n"; + bs b "\n" + end in let f_group l = match l with @@ -2860,7 +2879,7 @@ class html = let types = Odoc_info.Search.types module_list in known_types_names <- List.fold_left - (fun acc t -> StringSet.add t.ty_name acc) + (fun acc t -> String.Set.add t.ty_name acc) known_types_names types ; (* Get the names of all class and class types. *) @@ -2868,12 +2887,12 @@ class html = let class_types = Odoc_info.Search.class_types module_list in known_classes_names <- List.fold_left - (fun acc c -> StringSet.add c.cl_name acc) + (fun acc c -> String.Set.add c.cl_name acc) known_classes_names classes ; known_classes_names <- List.fold_left - (fun acc ct -> StringSet.add ct.clt_name acc) + (fun acc ct -> String.Set.add ct.clt_name acc) known_classes_names class_types ; (* Get the names of all known modules and module types. *) @@ -2881,12 +2900,12 @@ class html = let modules = Odoc_info.Search.modules module_list in known_modules_names <- List.fold_left - (fun acc m -> StringSet.add m.m_name acc) + (fun acc m -> String.Set.add m.m_name acc) known_modules_names modules ; known_modules_names <- List.fold_left - (fun acc mt -> StringSet.add mt.mt_name acc) + (fun acc mt -> String.Set.add mt.mt_name acc) known_modules_names module_types ; (* generate html for each module *) diff --git a/ocamldoc/odoc_info.mli b/ocamldoc/odoc_info.mli index d0d183b4..006a28b9 100644 --- a/ocamldoc/odoc_info.mli +++ b/ocamldoc/odoc_info.mli @@ -128,6 +128,10 @@ module Name : (** Take two names n1 and n2 = n3.n4 and return n4 if n3=n1 or else n2. *) val get_relative : t -> t -> t + (** Take two names n1 and n2 = n3.n4 and return n4 if n3=n1 and n1<>"" or else n2. *) + val get_relative_opt : t -> t -> t + + (** Return the name of the 'father' (like [dirname] for a file name).*) val father : t -> t end diff --git a/ocamldoc/odoc_latex.ml b/ocamldoc/odoc_latex.ml index 76f6d731..621ceec8 100644 --- a/ocamldoc/odoc_latex.ml +++ b/ocamldoc/odoc_latex.ml @@ -403,8 +403,12 @@ class text = | Some t -> t ) | Some (RK_section _) -> - self#latex_of_text_element fmt - (Latex ("["^(self#make_ref (self#label ~no_:false (Name.simple name)))^"]")) + let text = match text_opt with + | None -> [] + | Some x -> x in + let label= self#make_ref (self#label ~no_:false (Name.simple name)) in + self#latex_of_text fmt + (text @ [Latex ("["^label^"]")] ) | Some kind -> let f_label = match kind with diff --git a/ocamldoc/odoc_man.ml b/ocamldoc/odoc_man.ml index 04e66e70..5b1d1e53 100644 --- a/ocamldoc/odoc_man.ml +++ b/ocamldoc/odoc_man.ml @@ -319,7 +319,8 @@ class man = self#man_of_text2 b t; bs b "\n.sp\n" | Odoc_info.Title (_, _, t) -> - self#man_of_text2 b [Odoc_info.Code (Odoc_info.string_of_text t)] + let txt = Odoc_info.string_of_text t in + bp b ".SS %s\n" txt | Odoc_info.Latex _ -> (* don't care about LaTeX stuff in HTML. *) () @@ -810,13 +811,13 @@ class man = (** Print groff string for a module comment.*) method man_of_module_comment b text = bs b "\n.PP\n"; - self#man_of_text b [Code ("=== "^(Odoc_misc.string_of_text text)^" ===")]; + self#man_of_text b text; bs b "\n.PP\n" (** Print groff string for a class comment.*) method man_of_class_comment b text = bs b "\n.PP\n"; - self#man_of_text b [Code ("=== "^(Odoc_misc.string_of_text text)^" ===")]; + self#man_of_text b text; bs b "\n.PP\n" method man_of_recfield b modname f = diff --git a/ocamldoc/odoc_merge.ml b/ocamldoc/odoc_merge.ml index 7f9434db..f11ab5da 100644 --- a/ocamldoc/odoc_merge.ml +++ b/ocamldoc/odoc_merge.ml @@ -117,7 +117,7 @@ let merge_info merge_options (m1 : info) (m2 : info) = else l1 in let new_before = List.map (fun (v, t) -> (Str.split version_separators v, v, t)) new_before in - let new_before = List.sort Pervasives.compare new_before in + let new_before = List.sort Stdlib.compare new_before in let new_before = List.map (fun (_, v, t) -> (v, t)) new_before in let new_dep = match m1.i_deprecated, m2.i_deprecated with diff --git a/ocamldoc/odoc_messages.ml b/ocamldoc/odoc_messages.ml index 0f72c800..72dd6c08 100644 --- a/ocamldoc/odoc_messages.ml +++ b/ocamldoc/odoc_messages.ml @@ -108,9 +108,9 @@ let no_header = " Suppress header in generated documentation\n\t\t"^latex_texi_o let no_trailer = " Suppress trailer in generated documentation\n\t\t"^latex_texi_only let separate_files = " Generate one file per toplevel module "^latex_only let latex_title ref_titles = - "n,style Associate {n } to the given sectionning style\n"^ + "n,style Associate {n } to the given sectioning style\n"^ "\t\t(e.g. 'section') in the latex output "^latex_only^"\n"^ - "\t\tDefault sectionning is:\n\t\t"^ + "\t\tDefault sectioning is:\n\t\t"^ (String.concat "\n\t\t" (List.map (fun (n,t) -> Printf.sprintf " %d -> %s" n t) !ref_titles)) @@ -204,9 +204,9 @@ let merge_all = ('A', "merge all") let no_index = " Do not build index for Info files "^texi_only let esc_8bits = " Escape accentuated characters in Info files "^texi_only let texinfo_title r= - "n,style Associate {n } to the given sectionning style\n"^ + "n,style Associate {n } to the given sectioning style\n"^ "\t\t(e.g. 'section') in the texInfo output "^texi_only^"\n"^ - "\t\tDefault sectionning is:\n\t\t"^ + "\t\tDefault sectioning is:\n\t\t"^ (String.concat "\n\t\t" (List.map (fun (n,(t,h)) -> Printf.sprintf " %d -> %s, %s " n t h) !r)) @@ -240,6 +240,11 @@ let merge_options = let initially_opened_module = " Name of the module that is initially opened" +let library_namespace = + " Name of the library namespace for a prefixed library.\ + Note: very experimental." + + let help = " Display this list of options" @@ -257,7 +262,7 @@ let bad_magic_number = let not_a_module_name s = s^" is not a valid module name" let load_file_error f e = "Error while loading file "^f^":\n"^e let wrong_format s = "Wrong format for \""^s^"\"" -let errors_occured n = (string_of_int n)^" error(s) encountered" +let errors_occured n = (Int.to_string n)^" error(s) encountered" let parse_error = "Parse error" let text_parse_error l c s = let lines = Str.split (Str.regexp_string "\n") s in @@ -311,7 +316,7 @@ let module_not_found_in_typedtree m = "Module "^m^" was not found in typed tree. let class_not_found_in_typedtree c = "Class "^c^" was not found in typed tree." let class_type_not_found_in_typedtree ct = "Class type "^ct^" was not found in typed tree." let inherit_classexp_not_found_in_typedtree n = - "Inheritance class expression number "^(string_of_int n)^" was not found in typed tree." + "Inheritance class expression number "^(Int.to_string n)^" was not found in typed tree." let attribute_not_found_in_typedtree att = "Class attribute "^att^" was not found in typed tree." let method_not_found_in_typedtree met = "Class method "^met^" was not found in typed tree." let misplaced_comment file pos = diff --git a/ocamldoc/odoc_misc.ml b/ocamldoc/odoc_misc.ml index cffffffd..163c154b 100644 --- a/ocamldoc/odoc_misc.ml +++ b/ocamldoc/odoc_misc.ml @@ -116,7 +116,7 @@ let rec string_of_text t = let rec f n = function [] -> "\n" | t :: q -> - "\n"^(string_of_int n)^". "^(string_of_text t)^ + "\n"^(Int.to_string n)^". "^(string_of_text t)^ (f (n + 1) q) in f 1 l @@ -229,14 +229,14 @@ let apply_opt f v_opt = let string_of_date ?(absolute=false) ?(hour=true) d = let add_0 s = if String.length s < 2 then "0"^s else s in let t = (if absolute then Unix.gmtime else Unix.localtime) d in - (string_of_int (t.Unix.tm_year + 1900))^"-"^ - (add_0 (string_of_int (t.Unix.tm_mon + 1)))^"-"^ - (add_0 (string_of_int t.Unix.tm_mday))^ + (Int.to_string (t.Unix.tm_year + 1900))^"-"^ + (add_0 (Int.to_string (t.Unix.tm_mon + 1)))^"-"^ + (add_0 (Int.to_string t.Unix.tm_mday))^ ( if hour then " "^ - (add_0 (string_of_int t.Unix.tm_hour))^":"^ - (add_0 (string_of_int t.Unix.tm_min)) + (add_0 (Int.to_string t.Unix.tm_hour))^":"^ + (add_0 (Int.to_string t.Unix.tm_min)) else "" ) diff --git a/ocamldoc/odoc_module.ml b/ocamldoc/odoc_module.ml index 790a812d..1b9cb180 100644 --- a/ocamldoc/odoc_module.ml +++ b/ocamldoc/odoc_module.ml @@ -13,6 +13,8 @@ (* *) (**************************************************************************) +module String = Misc.Stdlib.String + (** Representation and manipulation of modules and module types. *) let print_DEBUG s = print_string s ; print_newline () @@ -219,9 +221,6 @@ let included_modules l = [] l -module S = Misc.StringSet - - (** Returns the list of elements of a module type. @param trans indicates if, for aliased modules, we must perform a transitive search.*) let rec module_type_elements ?(trans=true) mt = @@ -263,10 +262,10 @@ let module_elements ?(trans=true) m = match ma.ma_module with None -> [] | Some (Mod m') -> - if S.mem m'.m_name visited then + if String.Set.mem m'.m_name visited then [] else - module_elements (S.add m'.m_name visited) m' + module_elements (String.Set.add m'.m_name visited) m' | Some (Modtype mt) -> module_type_elements mt else [] @@ -305,7 +304,7 @@ let module_elements ?(trans=true) m = *) in iter_kind m.m_kind in - module_elements S.empty ~trans m + module_elements String.Set.empty ~trans m (** Returns the list of values of a module. @param trans indicates if, for aliased modules, we must perform a transitive search.*) @@ -476,18 +475,18 @@ let module_is_functor m = Module_functor _ -> true | Module_alias ma -> ( - not (S.mem ma.ma_name visited) + not (String.Set.mem ma.ma_name visited) && match ma.ma_module with None -> false - | Some (Mod mo) -> iter (S.add ma.ma_name visited) mo.m_kind + | Some (Mod mo) -> iter (String.Set.add ma.ma_name visited) mo.m_kind | Some (Modtype mt) -> module_type_is_functor mt ) | Module_constraint (k, _) -> iter visited k | _ -> false in - iter S.empty m.m_kind + iter String.Set.empty m.m_kind (** Returns the list of values of a module type. @param trans indicates if, for aliased modules, we must perform a transitive search.*) diff --git a/ocamldoc/odoc_name.ml b/ocamldoc/odoc_name.ml index 6ed5363d..5cb798bd 100644 --- a/ocamldoc/odoc_name.ml +++ b/ocamldoc/odoc_name.ml @@ -185,6 +185,28 @@ let get_relative n1 n2 = else n2 +let get_relative_opt n1 n2 = + if n1 = "" then n2 else + if prefix n1 n2 then + let len1 = String.length n1 in + try + String.sub n2 (len1+1) ((String.length n2) - len1 - 1) + with + _ -> n2 + else + n2 + + +let alias_unprefix ln s = + if ln = "" then s else + let p = ln ^ "__" in + let n, k = String.(length p, length s) in + if k > n && + String.sub s 0 n = p then + String.( capitalize_ascii @@ sub s n (k-n) ) + else + s + let hide_given_modules l s = let rec iter = function [] -> s @@ -209,8 +231,8 @@ let to_path n = List.fold_left (fun acc_opt -> fun s -> match acc_opt with - None -> Some (Path.Pident (Ident.create s)) - | Some acc -> Some (Path.Pdot (acc, s, 0))) + None -> Some (Path.Pident (Ident.create_local s)) + | Some acc -> Some (Path.Pdot (acc, s))) None (Str.split (Str.regexp "\\.") n) with diff --git a/ocamldoc/odoc_name.mli b/ocamldoc/odoc_name.mli index ac2bc0d3..5da8d7d4 100644 --- a/ocamldoc/odoc_name.mli +++ b/ocamldoc/odoc_name.mli @@ -44,9 +44,18 @@ val depth : t -> int If the two names are equal, then it is false (strict prefix).*) val prefix : t -> t -> bool +(** remove a [Library__] prefix and capitalize the resulting name *) +val alias_unprefix: t -> t -> t + (** Take two names n1 and n2 = n3.n4 and return n4 if n3=n1 or else n2. *) val get_relative : t -> t -> t + +(** [get_relative_opt n1 n2] is [n2] if [n1=""] and + [get_relative n1 n2] otherwise *) +val get_relative_opt : t -> t -> t + + (** Take two names n1=n3.n4 and n2 = n5.n6 and return n6 if n3=n5 or else n2. *) val get_relative_raw : t -> t -> t diff --git a/ocamldoc/odoc_print.ml b/ocamldoc/odoc_print.ml index 0ce40dcc..b21dff00 100644 --- a/ocamldoc/odoc_print.ml +++ b/ocamldoc/odoc_print.ml @@ -14,6 +14,7 @@ (**************************************************************************) open Format +let () = Printtyp.Naming_context.enable false let new_fmt () = let buf = Buffer.create 512 in @@ -54,7 +55,7 @@ let simpl_module_type ?code t = let rec iter t = match t with Types.Mty_ident _ - | Types.Mty_alias(_, _) -> t + | Types.Mty_alias _ -> t | Types.Mty_signature _ -> ( match code with @@ -84,8 +85,8 @@ let simpl_class_type t = (* we delete vals and methods in order to not print them when displaying the type *) let tnil = - { Types.desc = Types.Tnil ; Types.level = 0; Types.scope = None - ; Types.id = 0 } + { Types.desc = Types.Tnil ; Types.level = 0 + ; Types.scope = Btype.lowest_level ; Types.id = 0 } in Types.Cty_signature { Types.csig_self = { cs.Types.csig_self with Types.desc = Types.Tobject (tnil, ref None) }; diff --git a/ocamldoc/odoc_sig.ml b/ocamldoc/odoc_sig.ml index 9f9396f6..fb2eac67 100644 --- a/ocamldoc/odoc_sig.ml +++ b/ocamldoc/odoc_sig.ml @@ -45,19 +45,19 @@ module Signature_search = let add_to_hash table signat = match signat with - Types.Sig_value (ident, _) -> + Types.Sig_value (ident, _, _) -> Hashtbl.add table (V (Name.from_ident ident)) signat - | Types.Sig_typext (ident, _, _) -> + | Types.Sig_typext (ident, _, _, _) -> Hashtbl.add table (X (Name.from_ident ident)) signat - | Types.Sig_type (ident, _, _) -> + | Types.Sig_type (ident, _, _, _) -> Hashtbl.add table (T (Name.from_ident ident)) signat - | Types.Sig_class (ident, _, _) -> + | Types.Sig_class (ident, _, _, _) -> Hashtbl.add table (C (Name.from_ident ident)) signat - | Types.Sig_class_type (ident, _, _) -> + | Types.Sig_class_type (ident, _, _, _) -> Hashtbl.add table (CT (Name.from_ident ident)) signat - | Types.Sig_module (ident, _, _) -> + | Types.Sig_module (ident, _, _, _, _) -> Hashtbl.add table (M (Name.from_ident ident)) signat - | Types.Sig_modtype (ident,_) -> + | Types.Sig_modtype (ident,_,_) -> Hashtbl.add table (MT (Name.from_ident ident)) signat let table signat = @@ -67,39 +67,39 @@ module Signature_search = let search_value table name = match Hashtbl.find table (V name) with - | (Types.Sig_value (_, val_desc)) -> val_desc.Types.val_type + | (Types.Sig_value (_, val_desc, _)) -> val_desc.Types.val_type | _ -> assert false let search_extension table name = match Hashtbl.find table (X name) with - | (Types.Sig_typext (_, ext, _)) -> ext + | (Types.Sig_typext (_, ext, _, _)) -> ext | _ -> assert false let search_type table name = match Hashtbl.find table (T name) with - | (Types.Sig_type (_, type_decl, _)) -> type_decl + | (Types.Sig_type (_, type_decl, _, _)) -> type_decl | _ -> assert false let search_class table name = match Hashtbl.find table (C name) with - | (Types.Sig_class (_, class_decl, _)) -> class_decl + | (Types.Sig_class (_, class_decl, _, _)) -> class_decl | _ -> assert false let search_class_type table name = match Hashtbl.find table (CT name) with - | (Types.Sig_class_type (_, cltype_decl, _)) -> cltype_decl + | (Types.Sig_class_type (_, cltype_decl, _, _)) -> cltype_decl | _ -> assert false let search_module table name = match Hashtbl.find table (M name) with - | (Types.Sig_module (_ident, md, _)) -> md.Types.md_type + | (Types.Sig_module (_ident, _, md, _, _)) -> md.Types.md_type | _ -> assert false let search_module_type table name = match Hashtbl.find table (MT name) with - | (Types.Sig_modtype (_, {Types.mtd_type = Some module_type})) -> + | (Types.Sig_modtype (_, {Types.mtd_type = Some module_type}, _)) -> Some module_type - | (Types.Sig_modtype (_, {Types.mtd_type = None})) -> + | (Types.Sig_modtype (_, {Types.mtd_type = None}, _)) -> None | _ -> assert false @@ -288,17 +288,18 @@ module Analyser = | Some core_ty -> begin match core_ty.ptyp_desc with | Ptyp_object (fields, _) -> + let fields = List.map (fun {pof_desc; _} -> pof_desc) fields in let rec f = function | [] -> [] - | Otag ({txt=""},_,_) :: _ -> + | Otag ({txt=""},_) :: _ -> (* Fields with no name have been eliminated previously. *) assert false - | Otag ({txt=name}, _atts, ct) :: [] -> + | Otag ({txt=name}, ct) :: [] -> let pos = Loc.ptyp_end ct in let (_,comment_opt) = just_after_special pos pos_end in [name, comment_opt] - | Otag ({txt=name}, _, ct) :: - ((Oinherit ct2 | Otag (_, _, ct2)) as ele2) :: q -> + | Otag ({txt=name}, ct) :: + ((Oinherit ct2 | Otag (_, ct2)) as ele2) :: q -> let pos = Loc.ptyp_end ct in let pos2 = Loc.ptyp_start ct2 in let (_,comment_opt) = just_after_special pos pos2 in @@ -307,7 +308,7 @@ module Analyser = in let is_named_field field = match field with - | Otag ({txt=""},_,_) -> false + | Otag ({txt=""},_) -> false | _ -> true in (0, f @@ List.filter is_named_field fields) @@ -485,19 +486,23 @@ module Analyser = | Parsetree.Psig_include _ | Parsetree.Psig_class _ | Parsetree.Psig_class_type _ as tp -> take_item tp + | Parsetree.Psig_typesubst _ -> acc | Parsetree.Psig_type (rf, types) -> (match List.filter (fun td -> not (is_erased td.Parsetree.ptype_name.txt erased)) types with | [] -> acc | types -> take_item (Parsetree.Psig_type (rf, types))) + | Parsetree.Psig_modsubst _ -> acc | Parsetree.Psig_module ({Parsetree.pmd_name=name; - pmd_type=module_type} as r) as m -> + pmd_type=module_type} as r) + as m -> begin match Name.Map.find name.txt erased with | exception Not_found -> take_item m | `Removed -> acc | `Constrained constraints -> take_item (Parsetree.Psig_module - { r with Parsetree.pmd_type = + { r with + Parsetree.pmd_type = apply_constraint module_type constraints }) end | Parsetree.Psig_modtype {Parsetree.pmtd_name=name} as m -> @@ -863,7 +868,7 @@ module Analyser = (maybe_more + maybe_more2, new_env, [ Element_type_extension new_te ]) | Parsetree.Psig_exception ext -> - let name = ext.Parsetree.pext_name in + let name = ext.Parsetree.ptyexn_constructor.Parsetree.pext_name in let types_ext = try Signature_search.search_extension table name.txt with Not_found -> @@ -959,6 +964,114 @@ module Analyser = (* DEBUG *) print_DEBUG ("constructor/field "^name^": "^comm) (* DEBUG *) in (* DEBUG *) List.iter f_DEBUG name_comment_list; +(* DEBUG *) end; + (* get the information for the type in the signature *) + let sig_type_decl = + try Signature_search.search_type table name.txt + with Not_found -> + raise (Failure (Odoc_messages.type_not_found current_module_name name.txt)) + in + (* get the type kind with the associated comments *) + let type_kind = get_type_kind env name_comment_list sig_type_decl.Types.type_kind in + let loc_start = Loc.start type_decl.Parsetree.ptype_loc in + let new_end = Loc.end_ type_decl.Parsetree.ptype_loc + + maybe_more in + (* associate the comments to each constructor and build the [Type.t_type] *) + let new_type = + { + ty_name = Name.concat current_module_name name.txt ; + ty_info = assoc_com ; + ty_parameters = + List.map2 (fun p v -> + let (co, cn) = Types.Variance.get_upper v in + (Odoc_env.subst_type env p,co, cn)) + sig_type_decl.Types.type_params + sig_type_decl.Types.type_variance; + ty_kind = type_kind; + ty_private = sig_type_decl.Types.type_private; + ty_manifest = + begin match sig_type_decl.Types.type_manifest with + | None -> None + | Some t -> + Some (manifest_structure env name_comment_list t) + end ; + ty_loc = { loc_impl = None ; loc_inter = Some sig_item_loc } ; + ty_code = + ( + if !Odoc_global.keep_code then + Some (get_string_of_file loc_start new_end) + else + None + ) ; + } + in + let (maybe_more2, info_after_opt) = + My_ir.just_after_special + !file_name + (get_string_of_file new_end pos_limit2) + in + new_type.ty_info <- merge_infos new_type.ty_info info_after_opt ; + let (new_maybe_more, eles) = f + (maybe_more + maybe_more2) + (new_end + maybe_more2) + q + in + (new_maybe_more, (ele_comments @ [Element_type new_type]) @ eles) + in + let (maybe_more, types) = f ~first: true 0 pos_start_ele name_type_decl_list in + (maybe_more, extended_env, types) + + | Parsetree.Psig_typesubst (name_type_decl_list) (* FIXME *) -> + let extended_env = + List.fold_left + (fun acc_env td -> + let complete_name = Name.concat current_module_name td.Parsetree.ptype_name.txt in + Odoc_env.add_type acc_env complete_name + ) + env + name_type_decl_list + in + let rec f ?(first=false) acc_maybe_more last_pos name_type_decl_list = + match name_type_decl_list with + [] -> + (acc_maybe_more, []) + | type_decl :: q -> + let name = type_decl.Parsetree.ptype_name in + let (assoc_com, ele_comments) = + if first then + (comment_opt, []) + else + get_comments_in_module + last_pos + (Loc.start type_decl.Parsetree.ptype_loc) + in + let pos_limit2 = + match q with + [] -> pos_limit + | td :: _ -> Loc.start (td.Parsetree.ptype_loc) + in + let (maybe_more, name_comment_list) = + name_comment_from_type_decl + (Loc.end_ type_decl.Parsetree.ptype_loc) + pos_limit2 + type_decl + in +(* DEBUG *) begin +(* DEBUG *) let comm = +(* DEBUG *) match assoc_com with +(* DEBUG *) | None -> "sans commentaire" +(* DEBUG *) | Some c -> Odoc_misc.string_of_info c +(* DEBUG *) in +(* DEBUG *) print_DEBUG ("Type "^name.txt^" : "^comm); +(* DEBUG *) let f_DEBUG (name, c_opt) = +(* DEBUG *) let comm = +(* DEBUG *) match c_opt with +(* DEBUG *) | None -> "sans commentaire" +(* DEBUG *) | Some c -> Odoc_misc.string_of_info c +(* DEBUG *) in +(* DEBUG *) print_DEBUG ("constructor/field "^name^": "^comm) +(* DEBUG *) in +(* DEBUG *) List.iter f_DEBUG name_comment_list; (* DEBUG *) end; (* get the information for the type in the signature *) let sig_type_decl = @@ -1026,6 +1139,9 @@ module Analyser = in (0, env, ele_comments) + | Parsetree.Psig_modsubst _ -> (* FIXME *) + (0, env, []) + | Parsetree.Psig_module {Parsetree.pmd_name=name; pmd_type=module_type} -> let complete_name = Name.concat current_module_name name.txt in (* get the module type in the signature by the module name *) @@ -1221,8 +1337,14 @@ module Analyser = | Parsetree.Pmty_with (mt, _) -> f mt.Parsetree.pmty_desc | Parsetree.Pmty_typeof mexpr -> - begin match mexpr.Parsetree.pmod_desc with - Parsetree.Pmod_ident longident -> Name.from_longident longident.txt + let open Parsetree in + begin match mexpr.pmod_desc with + Pmod_ident longident -> Name.from_longident longident.txt + | Pmod_structure [ + {pstr_desc=Pstr_include + {pincl_mod={pmod_desc=Pmod_ident longident}} + }] -> (* include module type of struct include M end*) + Name.from_longident longident.txt | _ -> "??" end | Parsetree.Pmty_extension _ -> assert false @@ -1401,7 +1523,7 @@ module Analyser = | Parsetree.Pmty_alias longident -> let name = match sig_module_type with - Types.Mty_alias(_, path) -> Name.from_path path + Types.Mty_alias path -> Name.from_path path | _ -> Name.from_longident longident.txt in (* Wrong naming... *) @@ -1490,8 +1612,10 @@ module Analyser = | Parsetree.Pmty_alias _longident -> begin match sig_module_type with - Types.Mty_alias(_, path) -> - let alias_name = Odoc_env.full_module_name env (Name.from_path path) in + Types.Mty_alias path -> + let ln = !Odoc_global.library_namespace in + let alias_name = Odoc_env.full_module_name env + Name.(alias_unprefix ln @@ from_path path) in let ma = { ma_name = alias_name ; ma_module = None } in Module_alias ma | _ -> diff --git a/ocamldoc/odoc_str.ml b/ocamldoc/odoc_str.ml index 1189ead5..e250f161 100644 --- a/ocamldoc/odoc_str.ml +++ b/ocamldoc/odoc_str.ml @@ -16,6 +16,7 @@ (** The functions to get a string from different kinds of elements (types, modules, ...). *) module Name = Odoc_name +let () = Printtyp.Naming_context.enable false let string_of_variance t (co,cn) = if ( t.Odoc_type.ty_kind = Odoc_type.Type_abstract || diff --git a/ocamldoc/odoc_text_parser.mly b/ocamldoc/odoc_text_parser.mly index f71ab377..3d590d45 100644 --- a/ocamldoc/odoc_text_parser.mly +++ b/ocamldoc/odoc_text_parser.mly @@ -82,6 +82,9 @@ let print_DEBUG s = print_string s; print_newline () %token EOF %token Char +%nonassoc below_Char +%nonassoc Char + /* Start Symbols */ %start main located_element_list %type main @@ -177,7 +180,6 @@ text_element: list: | string { [] (* TODO: a test to check that there is only space characters *) } | string list { $2 } -| list string { $1 } | item { [ $1 ] } | item list { $1 :: $2 } @@ -207,7 +209,7 @@ shortcut_enum2: string: - Char { $1 } + Char %prec below_Char { $1 } | Char string { $1^$2 } ; diff --git a/ocamldoc/stdlib_non_prefixed/.depend b/ocamldoc/stdlib_non_prefixed/.depend deleted file mode 100644 index 25c847fd..00000000 --- a/ocamldoc/stdlib_non_prefixed/.depend +++ /dev/null @@ -1,185 +0,0 @@ -annot.cmi : location.cmi -arg.cmi : -arg_helper.cmi : map.cmi -array.cmi : seq.cmi -arrayLabels.cmi : seq.cmi -ast_helper.cmi : parsetree.cmi longident.cmi location.cmi docstrings.cmi \ - asttypes.cmi -ast_invariants.cmi : parsetree.cmi -ast_iterator.cmi : parsetree.cmi location.cmi -ast_mapper.cmi : parsetree.cmi location.cmi -asttypes.cmi : location.cmi -attr_helper.cmi : parsetree.cmi location.cmi format.cmi asttypes.cmi -bigarray.cmi : complex.cmi -btype.cmi : types.cmi set.cmi path.cmi map.cmi hashtbl.cmi format.cmi \ - asttypes.cmi -buffer.cmi : uchar.cmi seq.cmi -build_path_prefix_map.cmi : -builtin_attributes.cmi : parsetree.cmi location.cmi -bytegen.cmi : lambda.cmi instruct.cmi -bytelibrarian.cmi : format.cmi -bytelink.cmi : symtable.cmi format.cmi digest.cmi cmo_format.cmi -bytepackager.cmi : ident.cmi format.cmi env.cmi -bytes.cmi : seq.cmi -bytesLabels.cmi : seq.cmi -bytesections.cmi : -callback.cmi : -camlinternalFormat.cmi : camlinternalFormatBasics.cmi buffer.cmi -camlinternalFormatBasics.cmi : -camlinternalLazy.cmi : -camlinternalMod.cmi : obj.cmi -camlinternalOO.cmi : obj.cmi -ccomp.cmi : -char.cmi : -clflags.cmi : profile.cmi misc.cmi arg.cmi -cmi_format.cmi : types.cmi format.cmi digest.cmi -cmo_format.cmi : tbl.cmi lambda.cmi ident.cmi digest.cmi -cmt_format.cmi : types.cmi typedtree.cmi location.cmi env.cmi digest.cmi \ - cmi_format.cmi -complex.cmi : -condition.cmi : mutex.cmi -config.cmi : -consistbl.cmi : digest.cmi -ctype.cmi : types.cmi path.cmi longident.cmi ident.cmi env.cmi asttypes.cmi -datarepr.cmi : types.cmi path.cmi ident.cmi -depend.cmi : set.cmi parsetree.cmi map.cmi longident.cmi -digest.cmi : -dll.cmi : -docstrings.cmi : parsetree.cmi location.cmi lexing.cmi lazy.cmi -dynlink.cmi : digest.cmi -emitcode.cmi : instruct.cmi ident.cmi cmo_format.cmi -env.cmi : warnings.cmi types.cmi subst.cmi path.cmi misc.cmi map.cmi \ - longident.cmi location.cmi ident.cmi format.cmi digest.cmi consistbl.cmi \ - cmi_format.cmi asttypes.cmi -envaux.cmi : subst.cmi path.cmi format.cmi env.cmi -ephemeron.cmi : hashtbl.cmi -event.cmi : -filename.cmi : -float.cmi : pervasives.cmi -format.cmi : pervasives.cmi buffer.cmi -gc.cmi : -genlex.cmi : stream.cmi -graphics.cmi : -graphicsX11.cmi : -hashtbl.cmi : seq.cmi -ident.cmi : identifiable.cmi -identifiable.cmi : set.cmi map.cmi hashtbl.cmi format.cmi -includeclass.cmi : types.cmi location.cmi format.cmi env.cmi ctype.cmi -includecore.cmi : types.cmi typedtree.cmi location.cmi ident.cmi format.cmi \ - env.cmi -includemod.cmi : types.cmi typedtree.cmi path.cmi location.cmi \ - includecore.cmi ident.cmi format.cmi env.cmi ctype.cmi -instruct.cmi : types.cmi subst.cmi location.cmi lambda.cmi ident.cmi env.cmi -int32.cmi : -int64.cmi : -lambda.cmi : types.cmi primitive.cmi path.cmi location.cmi ident.cmi env.cmi \ - asttypes.cmi -lazy.cmi : -lexer.cmi : parser.cmi location.cmi lexing.cmi format.cmi -lexing.cmi : -list.cmi : seq.cmi -listLabels.cmi : seq.cmi -location.cmi : warnings.cmi lexing.cmi format.cmi -longident.cmi : -map.cmi : seq.cmi -marshal.cmi : -matching.cmi : typedtree.cmi location.cmi lambda.cmi ident.cmi -meta.cmi : obj.cmi instruct.cmi -misc.cmi : set.cmi map.cmi hashtbl.cmi format.cmi -moreLabels.cmi : set.cmi seq.cmi map.cmi hashtbl.cmi -mtype.cmi : types.cmi path.cmi ident.cmi env.cmi -mutex.cmi : -nativeint.cmi : -numbers.cmi : set.cmi int64.cmi identifiable.cmi -obj.cmi : int32.cmi -oo.cmi : camlinternalOO.cmi -oprint.cmi : outcometree.cmi format.cmi -outcometree.cmi : format.cmi asttypes.cmi -parmatch.cmi : types.cmi typedtree.cmi parsetree.cmi location.cmi \ - hashtbl.cmi env.cmi asttypes.cmi -parse.cmi : parsetree.cmi lexing.cmi -parser.cmi : parsetree.cmi location.cmi lexing.cmi docstrings.cmi -parsetree.cmi : longident.cmi location.cmi asttypes.cmi -parsing.cmi : obj.cmi lexing.cmi -path.cmi : ident.cmi -pervasives.cmi : camlinternalFormatBasics.cmi -pparse.cmi : parsetree.cmi misc.cmi lexing.cmi format.cmi -pprintast.cmi : parsetree.cmi format.cmi -predef.cmi : types.cmi path.cmi ident.cmi -primitive.cmi : parsetree.cmi outcometree.cmi location.cmi -printast.cmi : parsetree.cmi format.cmi -printexc.cmi : -printf.cmi : buffer.cmi -printinstr.cmi : instruct.cmi format.cmi -printlambda.cmi : lambda.cmi format.cmi -printpat.cmi : typedtree.cmi format.cmi asttypes.cmi -printtyp.cmi : types.cmi path.cmi outcometree.cmi longident.cmi ident.cmi \ - format.cmi env.cmi asttypes.cmi -printtyped.cmi : typedtree.cmi format.cmi -profile.cmi : format.cmi -queue.cmi : seq.cmi -random.cmi : nativeint.cmi int64.cmi int32.cmi -runtimedef.cmi : -scanf.cmi : pervasives.cmi -semantics_of_primitives.cmi : lambda.cmi -seq.cmi : -set.cmi : seq.cmi -simplif.cmi : misc.cmi location.cmi lambda.cmi ident.cmi -sort.cmi : -spacetime.cmi : -stack.cmi : seq.cmi -stdLabels.cmi : stringLabels.cmi listLabels.cmi bytesLabels.cmi \ - arrayLabels.cmi -str.cmi : -stream.cmi : -string.cmi : seq.cmi -stringLabels.cmi : seq.cmi -strongly_connected_components.cmi : identifiable.cmi -stypes.cmi : typedtree.cmi location.cmi annot.cmi -subst.cmi : types.cmi path.cmi ident.cmi -switch.cmi : location.cmi -symtable.cmi : obj.cmi misc.cmi lambda.cmi ident.cmi format.cmi digest.cmi \ - cmo_format.cmi -syntaxerr.cmi : location.cmi format.cmi -sys.cmi : -targetint.cmi : -tast_mapper.cmi : typedtree.cmi env.cmi asttypes.cmi -tbl.cmi : format.cmi -terminfo.cmi : -thread.cmi : unix.cmi -threadUnix.cmi : unix.cmi -translattribute.cmi : typedtree.cmi parsetree.cmi location.cmi lambda.cmi -translclass.cmi : typedtree.cmi location.cmi lambda.cmi ident.cmi format.cmi \ - asttypes.cmi -translcore.cmi : typedtree.cmi path.cmi location.cmi lambda.cmi ident.cmi \ - format.cmi env.cmi asttypes.cmi -translmod.cmi : typedtree.cmi primitive.cmi location.cmi lambda.cmi \ - ident.cmi format.cmi -translobj.cmi : lambda.cmi ident.cmi env.cmi -translprim.cmi : types.cmi typedtree.cmi primitive.cmi path.cmi location.cmi \ - lambda.cmi ident.cmi format.cmi env.cmi -typeclass.cmi : types.cmi typedtree.cmi parsetree.cmi longident.cmi \ - location.cmi ident.cmi format.cmi env.cmi ctype.cmi asttypes.cmi -typecore.cmi : types.cmi typedtree.cmi path.cmi parsetree.cmi longident.cmi \ - location.cmi ident.cmi format.cmi env.cmi asttypes.cmi annot.cmi -typedecl.cmi : types.cmi typedtree.cmi path.cmi parsetree.cmi longident.cmi \ - location.cmi includecore.cmi ident.cmi format.cmi env.cmi asttypes.cmi -typedtree.cmi : types.cmi primitive.cmi path.cmi parsetree.cmi longident.cmi \ - location.cmi ident.cmi env.cmi asttypes.cmi -typedtreeIter.cmi : typedtree.cmi asttypes.cmi -typedtreeMap.cmi : typedtree.cmi -typemod.cmi : types.cmi typedtree.cmi path.cmi parsetree.cmi misc.cmi \ - longident.cmi location.cmi includemod.cmi ident.cmi format.cmi env.cmi \ - cmi_format.cmi asttypes.cmi -typeopt.cmi : types.cmi typedtree.cmi path.cmi lambda.cmi env.cmi -types.cmi : set.cmi primitive.cmi path.cmi parsetree.cmi map.cmi \ - longident.cmi location.cmi ident.cmi asttypes.cmi -typetexp.cmi : types.cmi typedtree.cmi path.cmi parsetree.cmi longident.cmi \ - location.cmi includemod.cmi format.cmi env.cmi asttypes.cmi -uchar.cmi : -unix.cmi : bigarray.cmi -unixLabels.cmi : unix.cmi bigarray.cmi -untypeast.cmi : typedtree.cmi path.cmi parsetree.cmi longident.cmi \ - location.cmi asttypes.cmi -warnings.cmi : lexing.cmi lazy.cmi -weak.cmi : hashtbl.cmi diff --git a/ocamldoc/stdlib_non_prefixed/Makefile b/ocamldoc/stdlib_non_prefixed/Makefile deleted file mode 100644 index 801007ef..00000000 --- a/ocamldoc/stdlib_non_prefixed/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -TOPDIR=../.. -include $(TOPDIR)/Makefile.tools - -.SUFFIXES: - -OCAMLDEP= $(OCAMLRUN) $(TOPDIR)/tools/ocamldep -slash -OCAMLC_SNP= $(OCAMLRUN) $(TOPDIR)/ocamlc -nostdlib -nopervasives -I $(HERE) - -pervasives.cmi: pervasives.mli camlinternalFormatBasics.cmi - $(OCAMLC_SNP) -c $< - -camlinternalFormatBasics.cmi: \ -camlinternalFormatBasics.mli - $(OCAMLC_SNP) -c $< - -%.cmi: %.mli pervasives.cmi - $(OCAMLC_SNP) -c -open Pervasives $< - -depend: - $(OCAMLDEP) *.mli > .depend - -include .depend - -clean: - rm *.mli *.cmi diff --git a/ocamldoc/stdlib_non_prefixed/extract_pervasives.awk b/ocamldoc/stdlib_non_prefixed/extract_pervasives.awk deleted file mode 100644 index e0f7f872..00000000 --- a/ocamldoc/stdlib_non_prefixed/extract_pervasives.awk +++ /dev/null @@ -1,23 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Jeremie Dimino, Jane Street Europe * -#* * -#* Copyright 2017 Jane Street Group LLC * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -# This script extract the Pervasives submodule from stdlib.mli into -# pervasives.mli, for ocamldoc -BEGIN { state=0 } -/^module Pervasives : sig\r?$/ && state == 0 { state=1 } -/^end\r?$/ && state == 2 { state=3 } -{ - if (state == 1) state=2; - else if (state == 2) print -} diff --git a/ocamltest/.depend b/ocamltest/.depend index 55dacc8d..e730c76a 100644 --- a/ocamltest/.depend +++ b/ocamltest/.depend @@ -1,154 +1,429 @@ -run_unix.$(O): run_unix.c run.h ../byterun/caml/misc.h \ - ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \ +run_unix.$(O): run_unix.c run.h ../runtime/caml/misc.h \ + ../runtime/caml/config.h ../runtime/caml/m.h ../runtime/caml/s.h \ run_common.h -run_stubs.$(O): run_stubs.c run.h ../byterun/caml/misc.h \ - ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \ - ../byterun/caml/mlvalues.h ../byterun/caml/memory.h \ - ../byterun/caml/gc.h ../byterun/caml/major_gc.h \ - ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \ - ../byterun/caml/address_class.h ../byterun/caml/io.h \ - ../byterun/caml/osdeps.h +run_stubs.$(O): run_stubs.c run.h ../runtime/caml/misc.h \ + ../runtime/caml/config.h ../runtime/caml/m.h ../runtime/caml/s.h \ + ../runtime/caml/mlvalues.h ../runtime/caml/memory.h \ + ../runtime/caml/gc.h ../runtime/caml/major_gc.h \ + ../runtime/caml/freelist.h ../runtime/caml/minor_gc.h \ + ../runtime/caml/address_class.h ../runtime/caml/io.h \ + ../runtime/caml/osdeps.h ocamltest_stdlib_stubs.$(O): ocamltest_stdlib_stubs.c \ - ../byterun/caml/config.h ../byterun/caml/m.h ../byterun/caml/s.h \ - ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \ - ../byterun/caml/memory.h ../byterun/caml/gc.h \ - ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \ - ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \ - ../byterun/caml/alloc.h ../byterun/caml/signals.h \ - ../byterun/caml/osdeps.h -actions.cmo : result.cmi environments.cmi actions.cmi -actions.cmx : result.cmx environments.cmx actions.cmi -actions.cmi : result.cmi environments.cmi -actions_helpers.cmo : variables.cmi run_command.cmi result.cmi \ - ocamltest_stdlib.cmi filecompare.cmi environments.cmi \ - builtin_variables.cmi actions_helpers.cmi -actions_helpers.cmx : variables.cmx run_command.cmx result.cmx \ - ocamltest_stdlib.cmx filecompare.cmx environments.cmx \ - builtin_variables.cmx actions_helpers.cmi -actions_helpers.cmi : variables.cmi result.cmi environments.cmi actions.cmi -builtin_actions.cmo : result.cmi ocamltest_stdlib.cmi ocamltest_config.cmi \ - environments.cmi builtin_variables.cmi actions_helpers.cmi actions.cmi \ + ../runtime/caml/config.h ../runtime/caml/m.h ../runtime/caml/s.h \ + ../runtime/caml/mlvalues.h ../runtime/caml/misc.h \ + ../runtime/caml/memory.h ../runtime/caml/gc.h \ + ../runtime/caml/major_gc.h ../runtime/caml/freelist.h \ + ../runtime/caml/minor_gc.h ../runtime/caml/address_class.h \ + ../runtime/caml/alloc.h ../runtime/caml/signals.h \ + ../runtime/caml/osdeps.h +actions.cmo : \ + result.cmi \ + environments.cmi \ + actions.cmi +actions.cmx : \ + result.cmx \ + environments.cmx \ + actions.cmi +actions.cmi : \ + result.cmi \ + environments.cmi +actions_helpers.cmo : \ + variables.cmi \ + run_command.cmi \ + result.cmi \ + ocamltest_stdlib.cmi \ + filecompare.cmi \ + environments.cmi \ + builtin_variables.cmi \ + actions.cmi \ + actions_helpers.cmi +actions_helpers.cmx : \ + variables.cmx \ + run_command.cmx \ + result.cmx \ + ocamltest_stdlib.cmx \ + filecompare.cmx \ + environments.cmx \ + builtin_variables.cmx \ + actions.cmx \ + actions_helpers.cmi +actions_helpers.cmi : \ + variables.cmi \ + result.cmi \ + environments.cmi \ + actions.cmi +builtin_actions.cmo : \ + result.cmi \ + ocamltest_stdlib.cmi \ + ocamltest_config.cmi \ + environments.cmi \ + builtin_variables.cmi \ + actions_helpers.cmi \ + actions.cmi \ builtin_actions.cmi -builtin_actions.cmx : result.cmx ocamltest_stdlib.cmx ocamltest_config.cmx \ - environments.cmx builtin_variables.cmx actions_helpers.cmx actions.cmx \ +builtin_actions.cmx : \ + result.cmx \ + ocamltest_stdlib.cmx \ + ocamltest_config.cmx \ + environments.cmx \ + builtin_variables.cmx \ + actions_helpers.cmx \ + actions.cmx \ builtin_actions.cmi -builtin_actions.cmi : actions.cmi -builtin_variables.cmo : variables.cmi builtin_variables.cmi -builtin_variables.cmx : variables.cmx builtin_variables.cmi -builtin_variables.cmi : variables.cmi -environments.cmo : variables.cmi ocamltest_stdlib.cmi environments.cmi -environments.cmx : variables.cmx ocamltest_stdlib.cmx environments.cmi -environments.cmi : variables.cmi -filecompare.cmo : run_command.cmi ocamltest_stdlib.cmi filecompare.cmi -filecompare.cmx : run_command.cmx ocamltest_stdlib.cmx filecompare.cmi +builtin_actions.cmi : \ + actions.cmi +builtin_variables.cmo : \ + variables.cmi \ + builtin_variables.cmi +builtin_variables.cmx : \ + variables.cmx \ + builtin_variables.cmi +builtin_variables.cmi : \ + variables.cmi +environments.cmo : \ + variables.cmi \ + tsl_lexer.cmi \ + ocamltest_stdlib.cmi \ + environments.cmi +environments.cmx : \ + variables.cmx \ + tsl_lexer.cmx \ + ocamltest_stdlib.cmx \ + environments.cmi +environments.cmi : \ + variables.cmi +filecompare.cmo : \ + run_command.cmi \ + ocamltest_stdlib.cmi \ + filecompare.cmi +filecompare.cmx : \ + run_command.cmx \ + ocamltest_stdlib.cmx \ + filecompare.cmi filecompare.cmi : -main.cmo : tsl_semantics.cmi tsl_parser.cmi tsl_lexer.cmi tests.cmi \ - result.cmi options.cmi ocamltest_stdlib.cmi environments.cmi \ - builtin_variables.cmi actions_helpers.cmi actions.cmi main.cmi -main.cmx : tsl_semantics.cmx tsl_parser.cmx tsl_lexer.cmx tests.cmx \ - result.cmx options.cmx ocamltest_stdlib.cmx environments.cmx \ - builtin_variables.cmx actions_helpers.cmx actions.cmx main.cmi +main.cmo : \ + tsl_semantics.cmi \ + tsl_parser.cmi \ + tsl_lexer.cmi \ + tests.cmi \ + result.cmi \ + options.cmi \ + ocamltest_stdlib.cmi \ + environments.cmi \ + builtin_variables.cmi \ + actions_helpers.cmi \ + actions.cmi \ + main.cmi +main.cmx : \ + tsl_semantics.cmx \ + tsl_parser.cmx \ + tsl_lexer.cmx \ + tests.cmx \ + result.cmx \ + options.cmx \ + ocamltest_stdlib.cmx \ + environments.cmx \ + builtin_variables.cmx \ + actions_helpers.cmx \ + actions.cmx \ + main.cmi main.cmi : -ocaml_actions.cmo : result.cmi ocamltest_stdlib.cmi ocamltest_config.cmi \ - ocaml_variables.cmi ocaml_toplevels.cmi ocaml_tools.cmi \ - ocaml_modifiers.cmi ocaml_flags.cmi ocaml_filetypes.cmi ocaml_files.cmi \ - ocaml_directories.cmi ocaml_compilers.cmi ocaml_commands.cmi \ - ocaml_backends.cmi filecompare.cmi environments.cmi builtin_variables.cmi \ - actions_helpers.cmi actions.cmi ocaml_actions.cmi -ocaml_actions.cmx : result.cmx ocamltest_stdlib.cmx ocamltest_config.cmx \ - ocaml_variables.cmx ocaml_toplevels.cmx ocaml_tools.cmx \ - ocaml_modifiers.cmx ocaml_flags.cmx ocaml_filetypes.cmx ocaml_files.cmx \ - ocaml_directories.cmx ocaml_compilers.cmx ocaml_commands.cmx \ - ocaml_backends.cmx filecompare.cmx environments.cmx builtin_variables.cmx \ - actions_helpers.cmx actions.cmx ocaml_actions.cmi -ocaml_actions.cmi : actions.cmi -ocaml_backends.cmo : ocaml_backends.cmi -ocaml_backends.cmx : ocaml_backends.cmi +ocaml_actions.cmo : \ + result.cmi \ + ocamltest_stdlib.cmi \ + ocamltest_config.cmi \ + ocaml_variables.cmi \ + ocaml_toplevels.cmi \ + ocaml_tools.cmi \ + ocaml_modifiers.cmi \ + ocaml_flags.cmi \ + ocaml_filetypes.cmi \ + ocaml_files.cmi \ + ocaml_directories.cmi \ + ocaml_compilers.cmi \ + ocaml_commands.cmi \ + ocaml_backends.cmi \ + filecompare.cmi \ + environments.cmi \ + builtin_variables.cmi \ + actions_helpers.cmi \ + actions.cmi \ + ocaml_actions.cmi +ocaml_actions.cmx : \ + result.cmx \ + ocamltest_stdlib.cmx \ + ocamltest_config.cmx \ + ocaml_variables.cmx \ + ocaml_toplevels.cmx \ + ocaml_tools.cmx \ + ocaml_modifiers.cmx \ + ocaml_flags.cmx \ + ocaml_filetypes.cmx \ + ocaml_files.cmx \ + ocaml_directories.cmx \ + ocaml_compilers.cmx \ + ocaml_commands.cmx \ + ocaml_backends.cmx \ + filecompare.cmx \ + environments.cmx \ + builtin_variables.cmx \ + actions_helpers.cmx \ + actions.cmx \ + ocaml_actions.cmi +ocaml_actions.cmi : \ + actions.cmi +ocaml_backends.cmo : \ + ocaml_backends.cmi +ocaml_backends.cmx : \ + ocaml_backends.cmi ocaml_backends.cmi : -ocaml_commands.cmo : ocaml_files.cmi ocaml_commands.cmi -ocaml_commands.cmx : ocaml_files.cmx ocaml_commands.cmi +ocaml_commands.cmo : \ + ocaml_files.cmi \ + ocaml_commands.cmi +ocaml_commands.cmx : \ + ocaml_files.cmx \ + ocaml_commands.cmi ocaml_commands.cmi : -ocaml_compilers.cmo : variables.cmi ocamltest_stdlib.cmi ocaml_variables.cmi \ - ocaml_tools.cmi ocaml_files.cmi ocaml_commands.cmi ocaml_backends.cmi \ - builtin_variables.cmi ocaml_compilers.cmi -ocaml_compilers.cmx : variables.cmx ocamltest_stdlib.cmx ocaml_variables.cmx \ - ocaml_tools.cmx ocaml_files.cmx ocaml_commands.cmx ocaml_backends.cmx \ - builtin_variables.cmx ocaml_compilers.cmi -ocaml_compilers.cmi : variables.cmi ocaml_tools.cmi ocaml_backends.cmi -ocaml_directories.cmo : ocamltest_stdlib.cmi ocamltest_config.cmi \ - ocaml_backends.cmi ocaml_directories.cmi -ocaml_directories.cmx : ocamltest_stdlib.cmx ocamltest_config.cmx \ - ocaml_backends.cmx ocaml_directories.cmi -ocaml_directories.cmi : ocaml_backends.cmi -ocaml_files.cmo : ocamltest_stdlib.cmi ocaml_files.cmi -ocaml_files.cmx : ocamltest_stdlib.cmx ocaml_files.cmi +ocaml_compilers.cmo : \ + variables.cmi \ + ocamltest_stdlib.cmi \ + ocaml_variables.cmi \ + ocaml_tools.cmi \ + ocaml_files.cmi \ + ocaml_commands.cmi \ + ocaml_backends.cmi \ + builtin_variables.cmi \ + ocaml_compilers.cmi +ocaml_compilers.cmx : \ + variables.cmx \ + ocamltest_stdlib.cmx \ + ocaml_variables.cmx \ + ocaml_tools.cmx \ + ocaml_files.cmx \ + ocaml_commands.cmx \ + ocaml_backends.cmx \ + builtin_variables.cmx \ + ocaml_compilers.cmi +ocaml_compilers.cmi : \ + variables.cmi \ + ocaml_tools.cmi \ + ocaml_backends.cmi +ocaml_directories.cmo : \ + ocamltest_stdlib.cmi \ + ocamltest_config.cmi \ + ocaml_directories.cmi +ocaml_directories.cmx : \ + ocamltest_stdlib.cmx \ + ocamltest_config.cmx \ + ocaml_directories.cmi +ocaml_directories.cmi : +ocaml_files.cmo : \ + ocamltest_stdlib.cmi \ + ocamltest_config.cmi \ + ocaml_files.cmi +ocaml_files.cmx : \ + ocamltest_stdlib.cmx \ + ocamltest_config.cmx \ + ocaml_files.cmi ocaml_files.cmi : -ocaml_filetypes.cmo : ocaml_backends.cmi ocaml_filetypes.cmi -ocaml_filetypes.cmx : ocaml_backends.cmx ocaml_filetypes.cmi -ocaml_filetypes.cmi : ocaml_backends.cmi -ocaml_flags.cmo : ocaml_files.cmi ocaml_directories.cmi ocaml_backends.cmi \ +ocaml_filetypes.cmo : \ + ocamltest_config.cmi \ + ocaml_backends.cmi \ + ocaml_filetypes.cmi +ocaml_filetypes.cmx : \ + ocamltest_config.cmx \ + ocaml_backends.cmx \ + ocaml_filetypes.cmi +ocaml_filetypes.cmi : \ + ocaml_backends.cmi +ocaml_flags.cmo : \ + ocaml_variables.cmi \ + ocaml_files.cmi \ + ocaml_directories.cmi \ + ocaml_backends.cmi \ + environments.cmi \ ocaml_flags.cmi -ocaml_flags.cmx : ocaml_files.cmx ocaml_directories.cmx ocaml_backends.cmx \ +ocaml_flags.cmx : \ + ocaml_variables.cmx \ + ocaml_files.cmx \ + ocaml_directories.cmx \ + ocaml_backends.cmx \ + environments.cmx \ ocaml_flags.cmi -ocaml_flags.cmi : ocaml_backends.cmi -ocaml_modifiers.cmo : ocamltest_stdlib.cmi ocamltest_config.cmi \ - ocaml_variables.cmi environments.cmi ocaml_modifiers.cmi -ocaml_modifiers.cmx : ocamltest_stdlib.cmx ocamltest_config.cmx \ - ocaml_variables.cmx environments.cmx ocaml_modifiers.cmi -ocaml_modifiers.cmi : environments.cmi -ocaml_tests.cmo : tests.cmi ocamltest_config.cmi ocaml_actions.cmi \ - builtin_actions.cmi ocaml_tests.cmi -ocaml_tests.cmx : tests.cmx ocamltest_config.cmx ocaml_actions.cmx \ - builtin_actions.cmx ocaml_tests.cmi -ocaml_tests.cmi : tests.cmi -ocaml_tools.cmo : variables.cmi ocamltest_stdlib.cmi ocaml_variables.cmi \ - ocaml_files.cmi environments.cmi actions_helpers.cmi ocaml_tools.cmi -ocaml_tools.cmx : variables.cmx ocamltest_stdlib.cmx ocaml_variables.cmx \ - ocaml_files.cmx environments.cmx actions_helpers.cmx ocaml_tools.cmi -ocaml_tools.cmi : variables.cmi environments.cmi -ocaml_toplevels.cmo : variables.cmi ocamltest_stdlib.cmi ocaml_variables.cmi \ - ocaml_tools.cmi ocaml_files.cmi ocaml_compilers.cmi ocaml_commands.cmi \ - ocaml_backends.cmi ocaml_toplevels.cmi -ocaml_toplevels.cmx : variables.cmx ocamltest_stdlib.cmx ocaml_variables.cmx \ - ocaml_tools.cmx ocaml_files.cmx ocaml_compilers.cmx ocaml_commands.cmx \ - ocaml_backends.cmx ocaml_toplevels.cmi -ocaml_toplevels.cmi : variables.cmi ocaml_tools.cmi ocaml_compilers.cmi \ +ocaml_flags.cmi : \ + ocaml_backends.cmi \ + environments.cmi +ocaml_modifiers.cmo : \ + ocamltest_stdlib.cmi \ + ocamltest_config.cmi \ + ocaml_variables.cmi \ + environments.cmi \ + ocaml_modifiers.cmi +ocaml_modifiers.cmx : \ + ocamltest_stdlib.cmx \ + ocamltest_config.cmx \ + ocaml_variables.cmx \ + environments.cmx \ + ocaml_modifiers.cmi +ocaml_modifiers.cmi : \ + environments.cmi +ocaml_tests.cmo : \ + tests.cmi \ + ocamltest_config.cmi \ + ocaml_actions.cmi \ + builtin_actions.cmi \ + actions_helpers.cmi \ + ocaml_tests.cmi +ocaml_tests.cmx : \ + tests.cmx \ + ocamltest_config.cmx \ + ocaml_actions.cmx \ + builtin_actions.cmx \ + actions_helpers.cmx \ + ocaml_tests.cmi +ocaml_tests.cmi : \ + tests.cmi +ocaml_tools.cmo : \ + variables.cmi \ + ocamltest_stdlib.cmi \ + ocaml_variables.cmi \ + ocaml_files.cmi \ + environments.cmi \ + actions_helpers.cmi \ + ocaml_tools.cmi +ocaml_tools.cmx : \ + variables.cmx \ + ocamltest_stdlib.cmx \ + ocaml_variables.cmx \ + ocaml_files.cmx \ + environments.cmx \ + actions_helpers.cmx \ + ocaml_tools.cmi +ocaml_tools.cmi : \ + variables.cmi \ + environments.cmi +ocaml_toplevels.cmo : \ + variables.cmi \ + ocamltest_stdlib.cmi \ + ocaml_variables.cmi \ + ocaml_tools.cmi \ + ocaml_files.cmi \ + ocaml_compilers.cmi \ + ocaml_commands.cmi \ + ocaml_backends.cmi \ + ocaml_toplevels.cmi +ocaml_toplevels.cmx : \ + variables.cmx \ + ocamltest_stdlib.cmx \ + ocaml_variables.cmx \ + ocaml_tools.cmx \ + ocaml_files.cmx \ + ocaml_compilers.cmx \ + ocaml_commands.cmx \ + ocaml_backends.cmx \ + ocaml_toplevels.cmi +ocaml_toplevels.cmi : \ + variables.cmi \ + ocaml_tools.cmi \ + ocaml_compilers.cmi \ ocaml_backends.cmi -ocaml_variables.cmo : variables.cmi ocamltest_stdlib.cmi ocaml_variables.cmi -ocaml_variables.cmx : variables.cmx ocamltest_stdlib.cmx ocaml_variables.cmi -ocaml_variables.cmi : variables.cmi -ocamltest_config.cmo : ocamltest_config.cmi -ocamltest_config.cmx : ocamltest_config.cmi +ocaml_variables.cmo : \ + variables.cmi \ + ocamltest_stdlib.cmi \ + ocaml_variables.cmi +ocaml_variables.cmx : \ + variables.cmx \ + ocamltest_stdlib.cmx \ + ocaml_variables.cmi +ocaml_variables.cmi : \ + variables.cmi +ocamltest_config.cmo : \ + ocamltest_config.cmi +ocamltest_config.cmx : \ + ocamltest_config.cmi ocamltest_config.cmi : -ocamltest_stdlib.cmo : ocamltest_stdlib.cmi -ocamltest_stdlib.cmx : ocamltest_stdlib.cmi +ocamltest_stdlib.cmo : \ + ocamltest_stdlib.cmi +ocamltest_stdlib.cmx : \ + ocamltest_stdlib.cmi ocamltest_stdlib.cmi : -options.cmo : tests.cmi actions.cmi options.cmi -options.cmx : tests.cmx actions.cmx options.cmi +options.cmo : \ + variables.cmi \ + tests.cmi \ + actions.cmi \ + options.cmi +options.cmx : \ + variables.cmx \ + tests.cmx \ + actions.cmx \ + options.cmi options.cmi : -result.cmo : result.cmi -result.cmx : result.cmi +result.cmo : \ + result.cmi +result.cmx : \ + result.cmi result.cmi : -run_command.cmo : ocamltest_stdlib.cmi run_command.cmi -run_command.cmx : ocamltest_stdlib.cmx run_command.cmi +run_command.cmo : \ + ocamltest_stdlib.cmi \ + run_command.cmi +run_command.cmx : \ + ocamltest_stdlib.cmx \ + run_command.cmi run_command.cmi : -tests.cmo : result.cmi actions.cmi tests.cmi -tests.cmx : result.cmx actions.cmx tests.cmi -tests.cmi : result.cmi environments.cmi actions.cmi -tsl_ast.cmo : tsl_ast.cmi -tsl_ast.cmx : tsl_ast.cmi +tests.cmo : \ + result.cmi \ + actions.cmi \ + tests.cmi +tests.cmx : \ + result.cmx \ + actions.cmx \ + tests.cmi +tests.cmi : \ + result.cmi \ + environments.cmi \ + actions.cmi +tsl_ast.cmo : \ + tsl_ast.cmi +tsl_ast.cmx : \ + tsl_ast.cmi tsl_ast.cmi : -tsl_lexer.cmo : tsl_parser.cmi tsl_lexer.cmi -tsl_lexer.cmx : tsl_parser.cmx tsl_lexer.cmi -tsl_lexer.cmi : tsl_parser.cmi -tsl_parser.cmo : tsl_ast.cmi tsl_parser.cmi -tsl_parser.cmx : tsl_ast.cmx tsl_parser.cmi -tsl_parser.cmi : tsl_ast.cmi -tsl_semantics.cmo : variables.cmi tsl_ast.cmi tests.cmi environments.cmi \ - actions.cmi tsl_semantics.cmi -tsl_semantics.cmx : variables.cmx tsl_ast.cmx tests.cmx environments.cmx \ - actions.cmx tsl_semantics.cmi -tsl_semantics.cmi : tsl_ast.cmi tests.cmi environments.cmi actions.cmi -variables.cmo : variables.cmi -variables.cmx : variables.cmi +tsl_lexer.cmo : \ + tsl_parser.cmi \ + tsl_lexer.cmi +tsl_lexer.cmx : \ + tsl_parser.cmx \ + tsl_lexer.cmi +tsl_lexer.cmi : \ + tsl_parser.cmi +tsl_parser.cmo : \ + tsl_ast.cmi \ + tsl_parser.cmi +tsl_parser.cmx : \ + tsl_ast.cmx \ + tsl_parser.cmi +tsl_parser.cmi : \ + tsl_ast.cmi +tsl_semantics.cmo : \ + variables.cmi \ + tsl_ast.cmi \ + tests.cmi \ + environments.cmi \ + actions.cmi \ + tsl_semantics.cmi +tsl_semantics.cmx : \ + variables.cmx \ + tsl_ast.cmx \ + tests.cmx \ + environments.cmx \ + actions.cmx \ + tsl_semantics.cmi +tsl_semantics.cmi : \ + tsl_ast.cmi \ + tests.cmi \ + environments.cmi \ + actions.cmi +variables.cmo : \ + variables.cmi +variables.cmx : \ + variables.cmi variables.cmi : diff --git a/ocamltest/Makefile b/ocamltest/Makefile index bbae0208..f226e550 100644 --- a/ocamltest/Makefile +++ b/ocamltest/Makefile @@ -15,25 +15,54 @@ # The Makefile for ocamltest -include ../config/Makefile +ROOTDIR = .. + +include $(ROOTDIR)/Makefile.config +include $(ROOTDIR)/Makefile.common + +ifeq "$(filter str,$(OTHERLIBRARIES))" "" + str := false +else + str := true +endif + +ifeq "$(filter systhreads,$(OTHERLIBRARIES))" "" + systhreads := false +else + systhreads := true +endif + +ifeq "$(filter $(UNIXLIB),$(OTHERLIBRARIES))" "" + unix := None +else + ifeq "$(UNIX_OR_WIN32)" "win32" + unix := Some false + else + unix := Some true + endif +endif ifeq "$(UNIX_OR_WIN32)" "win32" - unix := false ocamlsrcdir := $(shell echo "$(abspath $(shell pwd)/..)"|cygpath -w -f - \ | sed 's/\\/\\\\\\\\/g') - ifeq "$(wildcard ../flexdll/Makefile)" "" - FLEXLINK_ENV= - else - FLEXLINK_ENV=OCAML_FLEXLINK="../boot/ocamlrun ../flexdll/flexlink.exe" - endif + mkexe := $(MKEXE_ANSI) -link $(OC_LDFLAGS) else - unix := true ocamlsrcdir := $(abspath $(shell pwd)/..) - FLEXLINK_ENV= + mkexe := $(MKEXE) endif ifeq "$(TOOLCHAIN)" "msvc" CPP := $(CPP) 2> nul +CSC := csc +ifeq "$(HOST)" "i686-pc-windows" +CSCFLAGS := /platform:x86 +else +CSCFLAGS := +endif +CSCFLAGS += /nologo /nowarn:1668 +else +CSC := +CSCFLAGS := endif ifeq "$(WITH_OCAMLDOC)" "ocamldoc" @@ -48,7 +77,7 @@ else WITH_OCAMLDEBUG := false endif -CPPFLAGS += -I../byterun -DCAML_INTERNALS +OC_CPPFLAGS += -I$(ROOTDIR)/runtime -DCAML_INTERNALS run := run_$(UNIX_OR_WIN32) @@ -67,13 +96,13 @@ core := \ run_command.mli run_command.ml \ filecompare.mli filecompare.ml \ variables.mli variables.ml \ - environments.mli environments.ml \ result.mli result.ml \ actions.mli actions.ml \ tests.mli tests.ml \ tsl_ast.mli tsl_ast.ml \ tsl_parser.mly \ tsl_lexer.mli tsl_lexer.mll \ + environments.mli environments.ml \ tsl_semantics.mli tsl_semantics.ml \ builtin_variables.mli builtin_variables.ml \ actions_helpers.mli actions_helpers.ml \ @@ -138,7 +167,8 @@ bytecode_modules := $(o_files) $(cmo_files) native_modules := $(o_files) $(cmx_files) -directories := ../utils ../parsing ../stdlib ../compilerlibs +directories := $(addprefix $(ROOTDIR)/,utils bytecomp parsing stdlib \ + compilerlibs) include_directories := $(addprefix -I , $(directories)) @@ -146,28 +176,35 @@ flags := -g -nostdlib $(include_directories) \ -strict-sequence -safe-string -strict-formats \ -w +a-4-9-41-42-44-45-48 -warn-error A -ocamlc := $(FLEXLINK_ENV) ../byterun/ocamlrun ../ocamlc $(flags) +ocamlc := $(ROOTDIR)/runtime/ocamlrun $(ROOTDIR)/ocamlc $(flags) -ocamlopt := $(FLEXLINK_ENV) ../byterun/ocamlrun ../ocamlopt $(flags) +ocamlopt := $(ROOTDIR)/runtime/ocamlrun $(ROOTDIR)/ocamlopt $(flags) -ocamldep := ../byterun/ocamlrun ../tools/ocamldep -slash +ocamldep := $(ROOTDIR)/runtime/ocamlrun $(ROOTDIR)/boot/ocamlc -depend +depflags := -slash +depincludes := -ocamllex := ../byterun/ocamlrun ../lex/ocamllex +ocamllex := $(ROOTDIR)/runtime/ocamlrun $(ROOTDIR)/lex/ocamllex -ocamlyacc := ../yacc/ocamlyacc +ocamlyacc := $(ROOTDIR)/yacc/ocamlyacc ocamlcdefaultflags := ocamloptdefaultflags := $(shell ./getocamloptdefaultflags $(TARGET)) +.PHONY: all allopt opt.opt # allopt and opt.opt are synonyms +all: ocamltest$(EXE) +allopt: ocamltest.opt$(EXE) +opt.opt: allopt + ocamltest$(EXE): $(bytecode_modules) - $(ocamlc) -custom ocamlcommon.cma -o $@ $^ + $(ocamlc_cmd) -custom ocamlcommon.cma ocamlbytecomp.cma -o $@ $^ %.cmo: %.ml $(ocamlc) -c $< ocamltest.opt$(EXE): $(native_modules) - $(ocamlopt) ocamlcommon.cmxa -o $@ $^ + $(ocamlopt_cmd) ocamlcommon.cmxa ocamlbytecomp.cmxa -o $@ $^ %.cmx: %.ml $(ocamlopt) -c $< @@ -182,14 +219,16 @@ ocamltest.opt$(EXE): $(native_modules) $(ocamllex) -q $< %.$(O): %.c - $(CC) $(CFLAGS) $(CPPFLAGS) $(BYTECCCOMPOPTS) -c $< + $(CC) $(OC_CFLAGS) $(OC_CPPFLAGS) -c $< -ocamltest_config.ml: ocamltest_config.ml.in +ocamltest_config.ml: ocamltest_config.ml.in Makefile ../Makefile.config sed \ -e 's|@@AFL_INSTRUMENT@@|$(AFL_INSTRUMENT)|' \ -e 's|@@ARCH@@|$(ARCH)|' \ -e 's|@@SHARED_LIBRARIES@@|$(SUPPORTS_SHARED_LIBRARIES)|' \ -e 's|@@UNIX@@|$(unix)|' \ + -e 's|@@SYSTHREADS@@|$(systhreads)|' \ + -e 's|@@STR@@|$(str)|' \ -e 's|@@SYSTEM@@|$(SYSTEM)|' \ -e 's|@@CPP@@|$(CPP)|' \ -e 's|@@OCAMLCDEFAULTFLAGS@@|$(ocamlcdefaultflags)|' \ @@ -201,6 +240,21 @@ ocamltest_config.ml: ocamltest_config.ml.in -e 's|@@FLAT_FLOAT_ARRAY@@|$(FLAT_FLOAT_ARRAY)|' \ -e 's|@@OCAMLDOC@@|$(WITH_OCAMLDOC)|' \ -e 's|@@OCAMLDEBUG@@|$(WITH_OCAMLDEBUG)|' \ + -e 's|@@OBJEXT@@|$(O)|' \ + -e 's|@@NATIVE_DYNLINK@@|$(NATDYNLINK)|' \ + -e 's|@@SHARED_LIBRARY_CFLAGS@@|$(SHAREDLIB_CFLAGS)|' \ + -e 's|@@SHAREDOBJEXT@@|$(SO)|' \ + -e 's|@@CSC@@|$(CSC)|' \ + -e 's|@@CSCFLAGS@@|$(CSCFLAGS)|' \ + -e 's|@@MKDLL@@|$(MKDLL)|' \ + -e 's|@@MKEXE@@|$(mkexe)|' \ + -e 's|@@BYTECCLIBS@@|$(BYTECCLIBS)|' \ + -e 's|@@NATIVECCLIBS@@|$(NATIVECCLIBS)|' \ + -e 's|@@ASM@@|$(ASM)|' \ + -e 's|@@CC@@|$(CC)|' \ + -e 's|@@CFLAGS@@|$(OC_CFLAGS)|' \ + -e 's|@@CCOMPTYPE@@|$(CCOMPTYPE)|' \ + -e 's|@@WINDOWS_UNICODE@@|$(WINDOWS_UNICODE)|' \ $< > $@ .PHONY: clean @@ -215,9 +269,10 @@ clean: ifneq "$(TOOLCHAIN)" "msvc" .PHONY: depend depend: $(dependencies_generated_prereqs) - $(CC) -MM $(CPPFLAGS) $(c_files) \ + $(CC) -MM $(OC_CPPFLAGS) $(c_files) \ | sed -e 's/\.o/.$$(O)/' > .depend - $(ocamldep) $(mli_files) $(ml_files) >> .depend + $(ocamldep) $(depflags) $(depincludes) $(mli_files) $(ml_files) \ + >> .depend endif -include .depend diff --git a/ocamltest/README b/ocamltest/README index 012f98b7..f54dc5d0 100644 --- a/ocamltest/README +++ b/ocamltest/README @@ -45,11 +45,11 @@ ocamltest needs to know two things: 1. Where the sources of the OCaml compiler to test are located. This is determined while OCaml is built. The default location can be -overriden by defining the OCAMLSRCDIR environment variable. +overridden by defining the OCAMLSRCDIR environment variable. 2. Which directory to use to build tests. The default value for this is "ocamltest" under Filename.get_temp_dir_name(). This value can be -overriden by defining the OCAMLTESTDIR environemnt variable. +overridden by defining the OCAMLTESTDIR environment variable. # Running tests @@ -122,7 +122,7 @@ find tests -name 'Makefile' In other words, the directories that still need to be migrated are the subdirectories of testsuite/tests that still contain a Makefile. -Once you knwo which directory you want to migrate, say foo, here is +Once you know which directory you want to migrate, say foo, here is what you should do: Read foo/Makefile to see how many tests the directory contains and how @@ -146,7 +146,7 @@ comment that looks like this: *) In particular, if the test's main file is foo.ml and the test uses -modules m1.ml and m2.ml, the test block will look like ths: +modules m1.ml and m2.ml, the test block will look like this: (* TEST modules = "m1.ml m2.ml" diff --git a/ocamltest/actions.ml b/ocamltest/actions.ml index cce0571e..e9614371 100644 --- a/ocamltest/actions.ml +++ b/ocamltest/actions.ml @@ -27,7 +27,7 @@ let action_name a = a.name let make n c = { name = n; body = c; hook = None } -let update action code = { action with body = code } +let update action code = { action with body = code } let compare a1 a2 = String.compare a1.name a2.name diff --git a/ocamltest/actions_helpers.ml b/ocamltest/actions_helpers.ml index 875ce1e2..210b2f25 100644 --- a/ocamltest/actions_helpers.ml +++ b/ocamltest/actions_helpers.ml @@ -17,6 +17,13 @@ open Ocamltest_stdlib +let skip_with_reason reason = + let code _log env = + let result = Result.skip_with_reason reason in + (result, env) + in + Actions.make "skip" code + let pass_or_skip test pass_reason skip_reason _log env = let open Result in let result = @@ -191,20 +198,32 @@ let run_script log env = Builtin_variables.ocamltest_response response_file env in let (result, newenv) = run "Running script" - false + true true Builtin_variables.script None log scriptenv in - if Result.is_pass result then begin - let modifiers = Environments.modifiers_of_file response_file in - let modified_env = Environments.apply_modifiers newenv modifiers in - (result, modified_env) - end else begin - let reason = String.trim (Sys.string_of_file response_file) in - let newresult = { result with Result.reason = Some reason } in - (newresult, newenv) - end + let final_value = + if Result.is_pass result then begin + match Environments.modifiers_of_file response_file with + | modifiers -> + let modified_env = Environments.apply_modifiers newenv modifiers in + (result, modified_env) + | exception Failure reason -> + (Result.fail_with_reason reason, newenv) + | exception Variables.No_such_variable name -> + let reason = + Printf.sprintf "error in script response: unknown variable %s" name + in + (Result.fail_with_reason reason, newenv) + end else begin + let reason = String.trim (Sys.string_of_file response_file) in + let newresult = { result with Result.reason = Some reason } in + (newresult, newenv) + end + in + Sys.force_remove response_file; + final_value let run_hook hook_name log input_env = Printf.fprintf log "Entering run_hook for hook %s\n%!" hook_name; @@ -227,17 +246,29 @@ let run_hook hook_name log input_env = timeout = 0; log = log; } in let exit_status = run settings in - match exit_status with + let final_value = match exit_status with | 0 -> - let modifiers = Environments.modifiers_of_file response_file in - let modified_env = Environments.apply_modifiers hookenv modifiers in - (Result.pass, modified_env) + begin match Environments.modifiers_of_file response_file with + | modifiers -> + let modified_env = Environments.apply_modifiers hookenv modifiers in + (Result.pass, modified_env) + | exception Failure reason -> + (Result.fail_with_reason reason, hookenv) + | exception Variables.No_such_variable name -> + let reason = + Printf.sprintf "error in script response: unknown variable %s" name + in + (Result.fail_with_reason reason, hookenv) + end | _ -> Printf.fprintf log "Hook returned %d" exit_status; let reason = String.trim (Sys.string_of_file response_file) in if exit_status=125 then (Result.skip_with_reason reason, hookenv) else (Result.fail_with_reason reason, hookenv) + in + Sys.force_remove response_file; + final_value let check_output kind_of_output output_variable reference_variable log env = diff --git a/ocamltest/actions_helpers.mli b/ocamltest/actions_helpers.mli index 5e7d6904..8c305ff7 100644 --- a/ocamltest/actions_helpers.mli +++ b/ocamltest/actions_helpers.mli @@ -15,6 +15,8 @@ (* Helper functions when writing actions *) +val skip_with_reason : string -> Actions.t + val pass_or_skip : bool -> string -> string -> out_channel -> Environments.t -> Result.t * Environments.t diff --git a/ocamltest/builtin_actions.ml b/ocamltest/builtin_actions.ml index 6d636583..4b1c2a32 100644 --- a/ocamltest/builtin_actions.ml +++ b/ocamltest/builtin_actions.ml @@ -55,25 +55,43 @@ let cd = make let reason = "Could not chidir to \"" ^ cwd ^ "\"" in let result = Result.fail_with_reason reason in (result, env) - end) + end) let dumpenv = make "dumpenv" (fun log env -> Environments.dump log env; (Result.pass, env)) +let hasunix = make + "hasunix" + (Actions_helpers.pass_or_skip (Ocamltest_config.libunix <> None) + "unix library available" + "unix library not available") + let libunix = make "libunix" - (Actions_helpers.pass_or_skip Ocamltest_config.libunix + (Actions_helpers.pass_or_skip (Ocamltest_config.libunix = Some true) "libunix available" "libunix not available") let libwin32unix = make "libwin32unix" - (Actions_helpers.pass_or_skip (not Ocamltest_config.libunix) + (Actions_helpers.pass_or_skip (Ocamltest_config.libunix = Some false) "libwin32unix available" "libwin32unix not available") +let hassysthreads = make + "hassysthreads" + (Actions_helpers.pass_or_skip Ocamltest_config.systhreads + "systhreads library available" + "systhreads library not available") + +let hasstr = make + "hasstr" + (Actions_helpers.pass_or_skip Ocamltest_config.str + "str library available" + "str library not available") + let windows_OS = "Windows_NT" let get_OS () = Sys.safe_getenv "OS" @@ -90,20 +108,31 @@ let not_windows = make "not running on Windows" "running on Windows") -let bsd_system = "bsd_elf" +let is_bsd_system s = + match s with + | "bsd_elf" | "netbsd" | "freebsd" | "openbsd" -> true + | _ -> false let bsd = make "bsd" - (Actions_helpers.pass_or_skip (Ocamltest_config.system = bsd_system) + (Actions_helpers.pass_or_skip (is_bsd_system Ocamltest_config.system) "on a BSD system" "not on a BSD system") let not_bsd = make "not-bsd" - (Actions_helpers.pass_or_skip (Ocamltest_config.system <> bsd_system) + (Actions_helpers.pass_or_skip (not (is_bsd_system Ocamltest_config.system)) "not on a BSD system" "on a BSD system") +let macos_system = "macosx" + +let macos = make + "macos" + (Actions_helpers.pass_or_skip (Ocamltest_config.system = macos_system) + "on a MacOS system" + "not on a MacOS system") + let arch32 = make "arch32" (Actions_helpers.pass_or_skip (Sys.word_size = 32) @@ -162,12 +191,16 @@ let _ = fail; cd; dumpenv; + hasunix; + hassysthreads; + hasstr; libunix; libwin32unix; windows; not_windows; bsd; not_bsd; + macos; arch32; arch64; has_symlink; diff --git a/ocamltest/builtin_actions.mli b/ocamltest/builtin_actions.mli index ba82a428..6fbedc6b 100644 --- a/ocamltest/builtin_actions.mli +++ b/ocamltest/builtin_actions.mli @@ -21,6 +21,7 @@ val fail : Actions.t val dumpenv : Actions.t +val hasunix : Actions.t val libunix : Actions.t val libwin32unix : Actions.t diff --git a/ocamltest/builtin_variables.ml b/ocamltest/builtin_variables.ml index 1bfd843c..6ea498f6 100644 --- a/ocamltest/builtin_variables.ml +++ b/ocamltest/builtin_variables.ml @@ -22,89 +22,95 @@ should be similar. Is there a way to enforce this? *) -open Variables (* Should not be necessary with a ppx *) - -let arguments = make ("arguments", +let arguments = Variables.make ("arguments", "Arguments passed to executed programs and scripts") -let cwd = make ("cwd", +let cwd = Variables.make ("cwd", "Used to change current working directory, but not updated") -let exit_status = make ("exit_status", +let commandline = Variables.make ("commandline", + "Specify the commandline of a tool") + +let exit_status = Variables.make ("exit_status", "Expected program exit status") -let files = make ("files", +let files = Variables.make ("files", "Files used by the tests") -let ocamltest_response = make ("ocamltest_response", +let make = Variables.make ("MAKE", + "Command used to invoke make") + +let ocamltest_response = Variables.make ("ocamltest_response", "File used by hooks to send back information.") -let ocamltest_log = make ("ocamltest_log", +let ocamltest_log = Variables.make ("ocamltest_log", "Path to log file for the current test") -let output = make ("output", +let output = Variables.make ("output", "Where the output of executing the program is saved") -let program = make ("program", +let program = Variables.make ("program", "Name of program produced by ocamlc.byte and ocamlopt.byte") -let program2 = make ("program2", +let program2 = Variables.make ("program2", "Name of program produced by ocamlc.opt and ocamlopt.opt") -let promote = make ("promote", +let promote = Variables.make ("promote", "Set to \"true\" to overwrite reference files with the test output") -let reason = make ("reason", +let reason = Variables.make ("reason", "Let a test report why it passed/skipped/failed.") -let reference = make ("reference", +let reference = Variables.make ("reference", "Path of file to which program output should be compared") let skip_header_lines = - make ( "skip_header_lines", + Variables.make ( "skip_header_lines", "The number of lines to skip when comparing program output \ with the reference file") let skip_header_bytes = - make ( "skip_header_bytes", + Variables.make ( "skip_header_bytes", "The number of bytes to skip when comparing program output \ with the reference file") -let script = make ("script", +let script = Variables.make ("script", "External script to run") -let stdin = make ("stdin", "Default standard input") -let stdout = make ("stdout", "Default standard output") -let stderr = make ("stderr", "Default standard error") +let stdin = Variables.make ("stdin", "Default standard input") +let stdout = Variables.make ("stdout", "Default standard output") +let stderr = Variables.make ("stderr", "Default standard error") -let test_build_directory = make ("test_build_directory", +let test_build_directory = Variables.make ("test_build_directory", "Directory for files produced during a test") -let test_build_directory_prefix = make ("test_build_directory_prefix", +let test_build_directory_prefix = Variables.make ("test_build_directory_prefix", "Directory under which all test directories should be created") -let test_file = make ("test_file", +let test_file = Variables.make ("test_file", "Name of file containing the specification of which tests to run") -let test_source_directory = make ("test_source_directory", +let test_source_directory = Variables.make ("test_source_directory", "Directory containing the test source files") -let test_pass = make ("TEST_PASS", +let test_pass = Variables.make ("TEST_PASS", "Exit code to let a script report success") -let test_skip = make ("TEST_SKIP", +let test_skip = Variables.make ("TEST_SKIP", "Exit code to let a script report skipping") -let test_fail = make ("TEST_FAIL", +let test_fail = Variables.make ("TEST_FAIL", "Exit code to let a script report failure") -let _ = List.iter register_variable +let _ = List.iter Variables.register_variable [ arguments; cwd; + commandline; exit_status; files; + make; ocamltest_response; ocamltest_log; output; diff --git a/ocamltest/builtin_variables.mli b/ocamltest/builtin_variables.mli index 126a3968..2e82174d 100644 --- a/ocamltest/builtin_variables.mli +++ b/ocamltest/builtin_variables.mli @@ -21,10 +21,14 @@ val arguments : Variables.t val cwd : Variables.t +val commandline : Variables.t + val exit_status : Variables.t val files : Variables.t +val make : Variables.t + val ocamltest_response : Variables.t val ocamltest_log : Variables.t diff --git a/ocamltest/dune b/ocamltest/dune new file mode 100644 index 00000000..9d3361a2 --- /dev/null +++ b/ocamltest/dune @@ -0,0 +1,52 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +(ocamllex + (modules tsl_lexer) + (mode fallback)) + +(ocamlyacc + (modules tsl_parser) + (mode fallback)) + +(rule + (targets ocamltest_config.ml) + (deps ../Makefile.config ../Makefile.common Makefile + ./ocamltest_config.ml.in ./getocamloptdefaultflags) + (action (run make %{targets}))) + +;; FIXME: handle UNIX_OR_WIN32 or something similar +(library + (name ocamltest_core_and_plugin) + (modes byte) + (wrapped false) + (flags (:standard -nostdlib)) + (libraries ocamlcommon stdlib) + (modules (:standard \ options main)) + (c_flags (-DCAML_INTERNALS -I%{project_root}/runtime)) ; fixme + (c_names run_unix run_stubs ocamltest_stdlib_stubs)) + +(rule + (targets empty.ml) + (deps (source_tree %{project_root}/runtime/caml)) + (action (write-file %{targets} "(* hack *)"))) + +(executable + (name main) + (modes byte) + (flags (:standard -nostdlib)) + (modules options main) + (libraries ocamltest_core_and_plugin runtime stdlib)) + +(rule (copy main.exe ocamltest.byte)) diff --git a/ocamltest/environments.ml b/ocamltest/environments.ml index 17338682..cac5e21f 100644 --- a/ocamltest/environments.ml +++ b/ocamltest/environments.ml @@ -144,36 +144,17 @@ and apply_modifiers environment modifiers = List.fold_left apply_modifier environment modifiers let modifier_of_string str = - let invalid_argument = (Invalid_argument "modifier_of_string") in - if str="" then raise invalid_argument else begin - let l = String.length str in - if str.[0] = '-' then begin - let variable_name = String.sub str 1 (l-1) in - match Variables.find_variable variable_name with - | None -> raise (Variables.No_such_variable variable_name) - | Some variable -> Remove variable - end else begin match String.index_opt str '=' with - | None -> raise invalid_argument - | Some pos_eq -> if pos_eq <= 0 then raise invalid_argument else - let (append, varname_length) = - (match String.index_opt str '+' with - | None -> (false, pos_eq) - | Some pos_plus -> - if pos_plus = pos_eq-1 - then (true, pos_plus) - else raise invalid_argument) in - let variable_name = String.sub str 0 varname_length in - match Variables.find_variable variable_name with - | None -> raise (Variables.No_such_variable variable_name) - | Some variable -> - if pos_eq >= l-2 || str.[pos_eq+1]<>'"' || str.[l-1]<>'"' - then raise invalid_argument - else let value_length = l - pos_eq - 3 in - let value = String.sub str (pos_eq+2) value_length in - if append then Append (variable, value) - else Add (variable, value) - end - end + let lexbuf = Lexing.from_string str in + let variable_name, result = Tsl_lexer.modifier lexbuf in + let variable = + match Variables.find_variable variable_name with + | None -> raise (Variables.No_such_variable variable_name) + | Some variable -> variable + in + match result with + | `Remove -> Remove variable + | `Add value -> Add (variable, value) + | `Append value -> Append (variable, value) let modifiers_of_file filename = let ic = open_in filename in diff --git a/ocamltest/filecompare.ml b/ocamltest/filecompare.ml index 9e88d31e..f9a59609 100644 --- a/ocamltest/filecompare.ml +++ b/ocamltest/filecompare.ml @@ -88,7 +88,7 @@ let compare_text_files dropped_lines file1 file2 = else Different -(* Version of Pervasives.really_input which stops at EOF, rather than raising +(* Version of Stdlib.really_input which stops at EOF, rather than raising an exception. *) let really_input_up_to ic = let block_size = 8192 in @@ -173,5 +173,9 @@ let diff files = files.output_filename; "> " ^ temporary_file ] in - if (Sys.command diff_commandline) = 2 then Pervasives.Error "diff" - else Ok (Sys.string_of_file temporary_file) + let result = + if (Sys.command diff_commandline) = 2 then Stdlib.Error "diff" + else Ok (Sys.string_of_file temporary_file) + in + Sys.force_remove temporary_file; + result diff --git a/ocamltest/filecompare.mli b/ocamltest/filecompare.mli index b1cb8569..42b493ae 100644 --- a/ocamltest/filecompare.mli +++ b/ocamltest/filecompare.mli @@ -45,4 +45,4 @@ val check_file : ?tool:tool -> files -> result val cmp_result_of_exitcode : string -> int -> result -val diff : files -> (string, string) Pervasives.result +val diff : files -> (string, string) Stdlib.result diff --git a/ocamltest/main.ml b/ocamltest/main.ml index 22c16fcb..cfe38d07 100644 --- a/ocamltest/main.ml +++ b/ocamltest/main.ml @@ -71,7 +71,7 @@ let rec run_test log common_prefix path behavior = function Node (testenvspec, test, env_modifiers, subtrees) -> Printf.printf "%s %s (%s) => %!" common_prefix path test.Tests.test_name; let (msg, b) = match behavior with - | Skip_all_tests -> "skipped", Skip_all_tests + | Skip_all_tests -> "n/a", Skip_all_tests | Run env -> let testenv0 = interprete_environment_statements env testenvspec in let testenv = List.fold_left apply_modifiers testenv0 env_modifiers in @@ -100,10 +100,16 @@ let get_test_build_directory_prefix test_dirname = if test_dirname = "." then root else Filename.concat root test_dirname +let tests_to_skip = ref [] + +let init_tests_to_skip () = + tests_to_skip := String.words (Sys.safe_getenv "OCAMLTEST_SKIP_TESTS") + let test_file test_filename = (* Printf.printf "# reading test file %s\n%!" test_filename; *) (* Save current working directory *) let cwd = Sys.getcwd() in + let skip_test = List.mem test_filename !tests_to_skip in let tsl_block = tsl_block_of_file_safe test_filename in let (rootenv_statements, test_trees) = test_trees_of_tsl_block tsl_block in let test_trees = match test_trees with @@ -115,8 +121,8 @@ let test_file test_filename = let used_tests = tests_in_trees test_trees in let used_actions = actions_in_tests used_tests in let action_names = - let f act names = StringSet.add (Actions.action_name act) names in - Actions.ActionSet.fold f used_actions StringSet.empty in + let f act names = String.Set.add (Actions.action_name act) names in + Actions.ActionSet.fold f used_actions String.Set.empty in let test_dirname = Filename.dirname test_filename in let test_basename = Filename.basename test_filename in let test_prefix = Filename.chop_extension test_basename in @@ -143,12 +149,14 @@ let test_file test_filename = let hook = Actions_helpers.run_hook hook_name in Actions.set_hook name hook end in - StringSet.iter install_hook action_names; + String.Set.iter install_hook action_names; let reference_filename = Filename.concat test_source_directory (test_prefix ^ ".reference") in + let make = try Sys.getenv "MAKE" with Not_found -> "make" in let initial_environment = Environments.from_bindings [ + Builtin_variables.make, make; Builtin_variables.test_file, test_basename; Builtin_variables.reference, reference_filename; Builtin_variables.test_source_directory, test_source_directory; @@ -161,8 +169,11 @@ let test_file test_filename = initial_environment rootenv_statements in let rootenv = Environments.initialize log root_environment in let common_prefix = " ... testing '" ^ test_basename ^ "' with" in + let initial_status = + if skip_test then Skip_all_tests else Run rootenv + in List.iteri - (run_test_i log common_prefix "" (Run rootenv)) + (run_test_i log common_prefix "" initial_status) test_trees; Actions.clear_all_hooks(); if not !Options.log_to_stderr then close_out log @@ -175,6 +186,7 @@ let main () = print_usage(); exit 1 end; + init_tests_to_skip(); List.iter test_file !Options.files_to_test let _ = main() diff --git a/ocamltest/ocaml_actions.ml b/ocamltest/ocaml_actions.ml index 4d9c7845..be3664da 100644 --- a/ocamltest/ocaml_actions.ml +++ b/ocamltest/ocaml_actions.ml @@ -49,6 +49,8 @@ let directory_flags env = let flags env = Environments.safe_lookup Ocaml_variables.flags env +let last_flags env = Environments.safe_lookup Ocaml_variables.last_flags env + let ocamllex_flags env = Environments.safe_lookup Ocaml_variables.ocamllex_flags env @@ -68,7 +70,7 @@ let libraries backend env = let binary_modules backend env = let extension = Ocaml_backends.module_extension backend in filelist env Ocaml_variables.binary_modules extension - + let backend_default_flags env = get_backend_value_from_env env Ocaml_variables.ocamlc_default_flags @@ -152,7 +154,7 @@ let prepare_module ocamlsrcdir output_variable log env input = let input_type = snd input in let open Ocaml_filetypes in match input_type with - | Implementation | Interface | C -> [input] + | Implementation | Interface | C | Obj -> [input] | Binary_interface -> [input] | Backend_specific _ -> [input] | C_minus_minus -> assert false @@ -173,6 +175,30 @@ let get_program_file backend env = Actions_helpers.test_build_directory env in Filename.make_path [test_build_directory; program_filename] +let is_c_file (_filename, filetype) = filetype=Ocaml_filetypes.C + +let cmas_need_dynamic_loading directories libraries = + let loads_c_code library = + let library = Misc.find_in_path directories library in + let ic = open_in_bin library in + try + let len_magic_number = String.length Config.cma_magic_number in + let magic_number = really_input_string ic len_magic_number in + if magic_number = Config.cma_magic_number then + let toc_pos = input_binary_int ic in + seek_in ic toc_pos; + let toc = (input_value ic : Cmo_format.library) in + close_in ic; + if toc.Cmo_format.lib_dllibs <> [] then Some (Ok ()) else None + else + raise End_of_file + with End_of_file + | Sys_error _ -> + begin try close_in ic with Sys_error _ -> () end; + Some (Error ("Corrupt or non-CMA file: " ^ library)) + in + Misc.Stdlib.List.find_map loads_c_code (String.words libraries) + let compile_program ocamlsrcdir (compiler : Ocaml_compilers.compiler) log env = let program_variable = compiler#program_variable in let program_file = Environments.safe_lookup program_variable env in @@ -182,7 +208,6 @@ let compile_program ocamlsrcdir (compiler : Ocaml_compilers.compiler) log env = let prepare = prepare_module ocamlsrcdir output_variable log env in let modules = List.concatmap prepare (List.map Ocaml_filetypes.filetype all_modules) in - let is_c_file (_filename, filetype) = filetype=Ocaml_filetypes.C in let has_c_file = List.exists is_c_file modules in let c_headers_flags = if has_c_file then Ocaml_flags.c_includes ocamlsrcdir else "" in @@ -201,47 +226,68 @@ let compile_program ocamlsrcdir (compiler : Ocaml_compilers.compiler) log env = if compile_only then " -c " else "" in let output = if compile_only then "" else "-o " ^ program_file in - let commandline = - [ - compiler#name ocamlsrcdir; - Ocaml_flags.runtime_flags ocamlsrcdir compiler#target has_c_file; - c_headers_flags; - Ocaml_flags.stdlib ocamlsrcdir; - directory_flags env; - flags env; - libraries compiler#target env; - backend_default_flags env compiler#target; - backend_flags env compiler#target; - compile_flags; - output; - module_names - ] in - let exit_status = - Actions_helpers.run_cmd - ~environment:dumb_term - ~stdin_variable: Ocaml_variables.compiler_stdin - ~stdout_variable:compiler#output_variable - ~stderr_variable:compiler#output_variable - ~append:true - log env commandline in - if exit_status=expected_exit_status - then (Result.pass, env) - else begin - let reason = - (Actions_helpers.mkreason - what (String.concat " " commandline) exit_status) in - (Result.fail_with_reason reason, env) - end + let libraries = libraries compiler#target env in + let cmas_need_dynamic_loading = + if not Config.supports_shared_libraries && + compiler#target = Ocaml_backends.Bytecode then + cmas_need_dynamic_loading (directories env) libraries + else + None + in + match cmas_need_dynamic_loading with + | Some (Error reason) -> + (Result.fail_with_reason reason, env) + | _ -> + let bytecode_links_c_code = (cmas_need_dynamic_loading = Some (Ok ())) in + let commandline = + [ + compiler#name ocamlsrcdir; + Ocaml_flags.runtime_flags ocamlsrcdir env compiler#target + (has_c_file || bytecode_links_c_code); + c_headers_flags; + Ocaml_flags.stdlib ocamlsrcdir; + directory_flags env; + flags env; + libraries; + backend_default_flags env compiler#target; + backend_flags env compiler#target; + compile_flags; + output; + (Environments.safe_lookup Ocaml_variables.ocaml_filetype_flag env); + module_names; + last_flags env + ] in + let exit_status = + Actions_helpers.run_cmd + ~environment:dumb_term + ~stdin_variable: Ocaml_variables.compiler_stdin + ~stdout_variable:compiler#output_variable + ~stderr_variable:compiler#output_variable + ~append:true + log env commandline in + if exit_status=expected_exit_status + then (Result.pass, env) + else begin + let reason = + (Actions_helpers.mkreason + what (String.concat " " commandline) exit_status) in + (Result.fail_with_reason reason, env) + end let compile_module ocamlsrcdir compiler module_ log env = let expected_exit_status = Ocaml_tools.expected_exit_status env (compiler :> Ocaml_tools.tool) in let what = Printf.sprintf "Compiling module %s" module_ in Printf.fprintf log "%s\n%!" what; + let module_with_filetype = Ocaml_filetypes.filetype module_ in + let is_c = is_c_file module_with_filetype in + let c_headers_flags = + if is_c then Ocaml_flags.c_includes ocamlsrcdir else "" in let commandline = [ compiler#name ocamlsrcdir; Ocaml_flags.stdlib ocamlsrcdir; + c_headers_flags; directory_flags env; flags env; libraries compiler#target env; @@ -375,7 +421,7 @@ let setup_ocamlc_byte_build_env = Ocaml_compilers.ocamlc_byte let setup_ocamlc_opt_build_env = - native_action + native_action (mk_compiler_env_setup "setup-ocamlc.opt-build-env" Ocaml_compilers.ocamlc_opt) @@ -405,9 +451,35 @@ let setup_ocamlnat_build_env = let compile (compiler : Ocaml_compilers.compiler) log env = let ocamlsrcdir = Ocaml_directories.srcdir () in - match Environments.lookup_nonempty Ocaml_variables.module_ env with - | None -> compile_program ocamlsrcdir compiler log env - | Some module_ -> compile_module ocamlsrcdir compiler module_ log env + match Environments.lookup_nonempty Builtin_variables.commandline env with + | None -> + begin + match Environments.lookup_nonempty Ocaml_variables.module_ env with + | None -> compile_program ocamlsrcdir compiler log env + | Some module_ -> compile_module ocamlsrcdir compiler module_ log env + end + | Some cmdline -> + let expected_exit_status = + Ocaml_tools.expected_exit_status env (compiler :> Ocaml_tools.tool) in + let what = Printf.sprintf "Compiling using commandline %s" cmdline in + Printf.fprintf log "%s\n%!" what; + let commandline = [compiler#name ocamlsrcdir; cmdline] in + let exit_status = + Actions_helpers.run_cmd + ~environment:dumb_term + ~stdin_variable: Ocaml_variables.compiler_stdin + ~stdout_variable:compiler#output_variable + ~stderr_variable:compiler#output_variable + ~append:true + log env commandline in + if exit_status=expected_exit_status + then (Result.pass, env) + else begin + let reason = + (Actions_helpers.mkreason + what (String.concat " " commandline) exit_status) in + (Result.fail_with_reason reason, env) + end (* Compile actions *) @@ -519,6 +591,171 @@ let objinfo log env = let ocamlobjinfo = Actions.make "ocamlobjinfo" objinfo +let mklib log env = + let ocamlsrcdir = Ocaml_directories.srcdir () in + let program = Environments.safe_lookup Builtin_variables.program env in + let what = Printf.sprintf "Running ocamlmklib to produce %s" program in + Printf.fprintf log "%s\n%!" what; + let ocamlc_command = + String.concat " " + [ + Ocaml_commands.ocamlrun_ocamlc ocamlsrcdir; + Ocaml_flags.stdlib ocamlsrcdir; + ] + in + let commandline = + [ + Ocaml_commands.ocamlrun_ocamlmklib ocamlsrcdir; + "-ocamlc '" ^ ocamlc_command ^ "'"; + "-o " ^ program + ] @ modules env in + let expected_exit_status = 0 in + let exit_status = + Actions_helpers.run_cmd + ~environment:dumb_term + ~stdout_variable:Ocaml_variables.compiler_output + ~stderr_variable:Ocaml_variables.compiler_output + ~append:true + log env commandline in + if exit_status=expected_exit_status + then (Result.pass, env) + else begin + let reason = + (Actions_helpers.mkreason + what (String.concat " " commandline) exit_status) in + (Result.fail_with_reason reason, env) + end + +let ocamlmklib = Actions.make "ocamlmklib" mklib + +let finalise_codegen_cc ocamlsrcdir test_basename _log env = + let test_module = + Filename.make_filename test_basename "s" + in + let archmod = Ocaml_files.asmgen_archmod ocamlsrcdir in + let modules = test_module ^ " " ^ archmod in + let program = Filename.make_filename test_basename "out" in + let env = Environments.add_bindings + [ + Ocaml_variables.modules, modules; + Builtin_variables.program, program; + ] env in + (Result.pass, env) + +let finalise_codegen_msvc ocamlsrcdir test_basename log env = + let obj = Filename.make_filename test_basename Ocamltest_config.objext in + let src = Filename.make_filename test_basename "s" in + let what = "Running Microsoft assembler" in + Printf.fprintf log "%s\n%!" what; + let commandline = [Ocamltest_config.asm; obj; src] in + let expected_exit_status = 0 in + let exit_status = + Actions_helpers.run_cmd + ~environment:dumb_term + ~stdout_variable:Ocaml_variables.compiler_output + ~stderr_variable:Ocaml_variables.compiler_output + ~append:true + log env commandline in + if exit_status=expected_exit_status + then begin + let archmod = Ocaml_files.asmgen_archmod ocamlsrcdir in + let modules = obj ^ " " ^ archmod in + let program = Filename.make_filename test_basename "out" in + let env = Environments.add_bindings + [ + Ocaml_variables.modules, modules; + Builtin_variables.program, program; + ] env in + (Result.pass, env) + end else begin + let reason = + (Actions_helpers.mkreason + what (String.concat " " commandline) exit_status) in + (Result.fail_with_reason reason, env) + end + +let run_codegen log env = + let ocamlsrcdir = Ocaml_directories.srcdir () in + let testfile = Actions_helpers.testfile env in + let what = Printf.sprintf "Running codegen on %s" testfile in + Printf.fprintf log "%s\n%!" what; + let test_build_directory = + Actions_helpers.test_build_directory env in + let compiler_output = + Filename.make_path [test_build_directory; "compiler-output"] + in + let env = + Environments.add_if_undefined + Ocaml_variables.compiler_output + compiler_output + env + in + let commandline = + [ + Ocaml_commands.ocamlrun_codegen ocamlsrcdir; + "-S " ^ testfile + ] in + let expected_exit_status = 0 in + let exit_status = + Actions_helpers.run_cmd + ~environment:dumb_term + ~stdout_variable:Ocaml_variables.compiler_output + ~stderr_variable:Ocaml_variables.compiler_output + ~append:true + log env commandline in + if exit_status=expected_exit_status + then begin + let testfile_basename = Filename.chop_extension testfile in + let finalise = + if Ocamltest_config.ccomptype="msvc" + then finalise_codegen_msvc + else finalise_codegen_cc + in + finalise ocamlsrcdir testfile_basename log env + end else begin + let reason = + (Actions_helpers.mkreason + what (String.concat " " commandline) exit_status) in + (Result.fail_with_reason reason, env) + end + +let codegen = Actions.make "codegen" run_codegen + +let run_cc log env = + let ocamlsrcdir = Ocaml_directories.srcdir () in + let program = Environments.safe_lookup Builtin_variables.program env in + let what = Printf.sprintf "Running C compiler to build %s" program in + Printf.fprintf log "%s\n%!" what; + let output_exe = + if Ocamltest_config.ccomptype="msvc" then "/Fe" else "-o " + in + let commandline = + [ + Ocamltest_config.cc; + Ocamltest_config.cflags; + "-I" ^ Ocaml_directories.runtime ocamlsrcdir; + output_exe ^ program; + Environments.safe_lookup Builtin_variables.arguments env; + ] @ modules env in + let expected_exit_status = 0 in + let exit_status = + Actions_helpers.run_cmd + ~environment:dumb_term + ~stdout_variable:Ocaml_variables.compiler_output + ~stderr_variable:Ocaml_variables.compiler_output + ~append:true + log env commandline in + if exit_status=expected_exit_status + then (Result.pass, env) + else begin + let reason = + (Actions_helpers.mkreason + what (String.concat " " commandline) exit_status) in + (Result.fail_with_reason reason, env) + end + +let cc = Actions.make "cc" run_cc + let run_expect_once ocamlsrcdir input_file principal log env = let expect_flags = Sys.safe_getenv "EXPECT_FLAGS" in let repo_root = "-repo-root " ^ ocamlsrcdir in @@ -752,71 +989,89 @@ let compile_modules compile_mods initial_env modules_with_filetypes let run_test_program_in_toplevel (toplevel : Ocaml_toplevels.toplevel) log env = - let testfile = Actions_helpers.testfile env in - let expected_exit_status = - Ocaml_tools.expected_exit_status env (toplevel :> Ocaml_tools.tool) in - let compiler_output_variable = toplevel#output_variable in - let ocamlsrcdir = Ocaml_directories.srcdir () in - let compiler = toplevel#compiler in - let compiler_name = compiler#name ocamlsrcdir in - let modules_with_filetypes = - List.map Ocaml_filetypes.filetype (modules env) in - let (result, env) = compile_modules - ocamlsrcdir compiler compiler_name compiler_output_variable - modules_with_filetypes log env in - if Result.is_pass result then begin - let what = - Printf.sprintf "Running %s in %s toplevel (expected exit status: %d)" - testfile - (Ocaml_backends.string_of_backend toplevel#backend) - expected_exit_status in - Printf.fprintf log "%s\n%!" what; - let toplevel_name = toplevel#name ocamlsrcdir in - let ocaml_script_as_argument = - match - Environments.lookup_as_bool - Ocaml_variables.ocaml_script_as_argument env - with - | None -> false - | Some b -> b - in - let commandline = - [ - toplevel_name; - Ocaml_flags.toplevel_default_flags; - toplevel#flags; - Ocaml_flags.stdlib ocamlsrcdir; - directory_flags env; - Ocaml_flags.include_toplevel_directory ocamlsrcdir; - flags env; - libraries toplevel#backend env; - binary_modules toplevel#backend env; - if ocaml_script_as_argument then testfile else ""; - Environments.safe_lookup Builtin_variables.arguments env - ] in - let exit_status = - if ocaml_script_as_argument - then Actions_helpers.run_cmd - ~environment:dumb_term - ~stdout_variable:compiler_output_variable - ~stderr_variable:compiler_output_variable - log env commandline - else Actions_helpers.run_cmd - ~environment:dumb_term - ~stdin_variable:Builtin_variables.test_file - ~stdout_variable:compiler_output_variable - ~stderr_variable:compiler_output_variable - log env commandline - in - if exit_status=expected_exit_status - then (Result.pass, env) - else begin - let reason = - (Actions_helpers.mkreason - what (String.concat " " commandline) exit_status) in - (Result.fail_with_reason reason, env) - end - end else (result, env) + let backend = toplevel#backend in + let libraries = libraries backend env in + (* This is a sub-optimal check - skip the test if any libraries requiring + C stubs are loaded. It would be better at this point to build a custom + toplevel. *) + let toplevel_can_run = + Config.supports_shared_libraries || backend <> Ocaml_backends.Bytecode + in + if not toplevel_can_run then + (Result.skip, env) + else + match cmas_need_dynamic_loading (directories env) libraries with + | Some (Error reason) -> + (Result.fail_with_reason reason, env) + | Some (Ok ()) -> + (Result.skip, env) + | None -> + let testfile = Actions_helpers.testfile env in + let expected_exit_status = + Ocaml_tools.expected_exit_status env (toplevel :> Ocaml_tools.tool) in + let compiler_output_variable = toplevel#output_variable in + let ocamlsrcdir = Ocaml_directories.srcdir () in + let compiler = toplevel#compiler in + let compiler_name = compiler#name ocamlsrcdir in + let modules_with_filetypes = + List.map Ocaml_filetypes.filetype (modules env) in + let (result, env) = compile_modules + ocamlsrcdir compiler compiler_name compiler_output_variable + modules_with_filetypes log env in + if Result.is_pass result then begin + let what = + Printf.sprintf "Running %s in %s toplevel \ + (expected exit status: %d)" + testfile + (Ocaml_backends.string_of_backend backend) + expected_exit_status in + Printf.fprintf log "%s\n%!" what; + let toplevel_name = toplevel#name ocamlsrcdir in + let ocaml_script_as_argument = + match + Environments.lookup_as_bool + Ocaml_variables.ocaml_script_as_argument env + with + | None -> false + | Some b -> b + in + let commandline = + [ + toplevel_name; + Ocaml_flags.toplevel_default_flags; + toplevel#flags; + Ocaml_flags.stdlib ocamlsrcdir; + directory_flags env; + Ocaml_flags.include_toplevel_directory ocamlsrcdir; + flags env; + libraries; + binary_modules backend env; + if ocaml_script_as_argument then testfile else ""; + Environments.safe_lookup Builtin_variables.arguments env + ] in + let exit_status = + if ocaml_script_as_argument + then Actions_helpers.run_cmd + ~environment:dumb_term + ~stdout_variable:compiler_output_variable + ~stderr_variable:compiler_output_variable + log env commandline + else Actions_helpers.run_cmd + ~environment:dumb_term + ~stdin_variable:Builtin_variables.test_file + ~stdout_variable:compiler_output_variable + ~stderr_variable:compiler_output_variable + log env commandline + in + if exit_status=expected_exit_status + then (Result.pass, env) + else begin + let reason = + (Actions_helpers.mkreason + what (String.concat " " commandline) exit_status) in + (Result.fail_with_reason reason, env) + end + end else (result, env) let ocaml = Actions.make "ocaml" @@ -836,9 +1091,25 @@ let check_ocamlnat_output = (make_check_tool_output "check-ocamlnat-output" Ocaml_toplevels.ocamlnat) -let config_variables _log env = Environments.add_bindings +let config_variables _log env = + let ocamlsrcdir = Ocaml_directories.srcdir () in + Environments.add_bindings [ + Ocaml_variables.ocamlrun, Ocaml_files.ocamlrun ocamlsrcdir; + Ocaml_variables.ocamlc_byte, Ocaml_files.ocamlc ocamlsrcdir; + Ocaml_variables.ocamlopt_byte, Ocaml_files.ocamlopt ocamlsrcdir; + Ocaml_variables.bytecc_libs, Ocamltest_config.bytecc_libs; + Ocaml_variables.nativecc_libs, Ocamltest_config.nativecc_libs; + Ocaml_variables.mkdll, + Sys.getenv_with_default_value "MKDLL" Ocamltest_config.mkdll; + Ocaml_variables.mkexe, Ocamltest_config.mkexe; Ocaml_variables.c_preprocessor, Ocamltest_config.c_preprocessor; + Ocaml_variables.csc, Ocamltest_config.csc; + Ocaml_variables.csc_flags, Ocamltest_config.csc_flags; + Ocaml_variables.shared_library_cflags, + Ocamltest_config.shared_library_cflags; + Ocaml_variables.objext, Ocamltest_config.objext; + Ocaml_variables.sharedobjext, Ocamltest_config.sharedobjext; Ocaml_variables.ocamlc_default_flags, Ocamltest_config.ocamlc_default_flags; Ocaml_variables.ocamlopt_default_flags, @@ -890,12 +1161,42 @@ let shared_libraries = Actions.make "Shared libraries are supported." "Shared libraries are not supported.") +let no_shared_libraries = Actions.make + "no-shared-libraries" + (Actions_helpers.pass_or_skip (not Ocamltest_config.shared_libraries) + "Shared libraries are not supported." + "Shared libraries are supported.") + let native_compiler = Actions.make "native-compiler" (Actions_helpers.pass_or_skip (Ocamltest_config.arch <> "none") "native compiler available" "native compiler not available") +let native_dynlink = Actions.make + "native-dynlink" + (Actions_helpers.pass_or_skip (Ocamltest_config.native_dynlink) + "native dynlink support available" + "native dynlink support not available") + +let debugger = Actions.make + "debugger" + (Actions_helpers.pass_or_skip Ocamltest_config.ocamldebug + "debugger available" + "debugger not available") + +let csharp_compiler = Actions.make + "csharp-compiler" + (Actions_helpers.pass_or_skip (Ocamltest_config.csc<>"") + "C# compiler available" + "C# compiler not available") + +let windows_unicode = Actions.make + "windows-unicode" + (Actions_helpers.pass_or_skip (Ocamltest_config.windows_unicode ) + "Windows Unicode support available" + "Windows Unicode support not available") + let afl_instrument = Actions.make "afl-instrument" (Actions_helpers.pass_or_skip Ocamltest_config.afl_instrument @@ -1034,7 +1335,7 @@ let run_ocamldoc = let load_all = List.map (fun name -> "-load " ^ compiled_doc_name (fst name)) @@ (* sort module in alphabetical order *) - List.sort Pervasives.compare modules in + List.sort Stdlib.compare modules in let with_plugins = List.map (fun name -> "-g " ^ ocamldoc_plugin (fst name)) plugins in let commandline = @@ -1095,12 +1396,20 @@ let _ = spacetime; no_spacetime; shared_libraries; + no_shared_libraries; native_compiler; + native_dynlink; + debugger; + csharp_compiler; + windows_unicode; afl_instrument; no_afl_instrument; setup_ocamldoc_build_env; run_ocamldoc; check_ocamldoc_output; ocamldebug; + ocamlmklib; + codegen; + cc; ocamlobjinfo ] diff --git a/ocamltest/ocaml_actions.mli b/ocamltest/ocaml_actions.mli index ab4d302a..efa05a10 100644 --- a/ocamltest/ocaml_actions.mli +++ b/ocamltest/ocaml_actions.mli @@ -45,8 +45,13 @@ val flat_float_array : Actions.t val no_flat_float_array : Actions.t val shared_libraries : Actions.t +val no_shared_libraries : Actions.t val native_compiler : Actions.t val afl_instrument : Actions.t val no_afl_instrument : Actions.t + +val codegen : Actions.t + +val cc : Actions.t diff --git a/ocamltest/ocaml_commands.ml b/ocamltest/ocaml_commands.ml index e0bf9aa0..59bbb6c9 100644 --- a/ocamltest/ocaml_commands.ml +++ b/ocamltest/ocaml_commands.ml @@ -37,3 +37,9 @@ let ocamlrun_ocamldebug ocamlsrcdir = let ocamlrun_ocamlobjinfo ocamlsrcdir = ocamlrun ocamlsrcdir Ocaml_files.ocamlobjinfo + +let ocamlrun_ocamlmklib ocamlsrcdir = + ocamlrun ocamlsrcdir Ocaml_files.ocamlmklib + +let ocamlrun_codegen ocamlsrcdir = + ocamlrun ocamlsrcdir Ocaml_files.codegen diff --git a/ocamltest/ocaml_commands.mli b/ocamltest/ocaml_commands.mli index 9adcad3a..9a1474e2 100644 --- a/ocamltest/ocaml_commands.mli +++ b/ocamltest/ocaml_commands.mli @@ -30,3 +30,6 @@ val ocamlrun_ocamldoc : string -> string val ocamlrun_ocamldebug : string -> string val ocamlrun_ocamlobjinfo : string -> string + +val ocamlrun_ocamlmklib : string -> string +val ocamlrun_codegen : string -> string diff --git a/ocamltest/ocaml_directories.ml b/ocamltest/ocaml_directories.ml index 22ebef75..b85ff07c 100644 --- a/ocamltest/ocaml_directories.ml +++ b/ocamltest/ocaml_directories.ml @@ -31,13 +31,7 @@ let toplevel ocamlsrcdir = Filename.make_path [ocamlsrcdir; "toplevel"] let runtime ocamlsrcdir = - Filename.make_path [ocamlsrcdir; "byterun"] - -let runtime_library backend ocamlsrcdir = - let backend_lib_dir = match backend with - | Ocaml_backends.Native -> "asmrun" - | Ocaml_backends.Bytecode -> "byterun" in - Filename.make_path [ocamlsrcdir; backend_lib_dir] + Filename.make_path [ocamlsrcdir; "runtime"] let tools ocamlsrcdir = Filename.make_path [ocamlsrcdir; "tools"] diff --git a/ocamltest/ocaml_directories.mli b/ocamltest/ocaml_directories.mli index 929e7b05..d689f34e 100644 --- a/ocamltest/ocaml_directories.mli +++ b/ocamltest/ocaml_directories.mli @@ -25,6 +25,4 @@ val toplevel : string -> string val runtime : string -> string -val runtime_library : Ocaml_backends.t -> string -> string - val tools : string -> string diff --git a/ocamltest/ocaml_files.ml b/ocamltest/ocaml_files.ml index 288cdeb4..70e24d7d 100644 --- a/ocamltest/ocaml_files.ml +++ b/ocamltest/ocaml_files.ml @@ -34,7 +34,7 @@ let ocamlrun ocamlsrcdir = | Debug -> "ocamlrund" | Instrumented -> "ocamlruni" in let ocamlrunfile = Filename.mkexe runtime in - Filename.make_path [ocamlsrcdir; "byterun"; ocamlrunfile] + Filename.make_path [ocamlsrcdir; "runtime"; ocamlrunfile] let ocamlc ocamlsrcdir = Filename.make_path [ocamlsrcdir; "ocamlc"] @@ -75,3 +75,15 @@ let ocamldebug ocamlsrcdir = let ocamlobjinfo ocamlsrcdir = Filename.make_path [ocamlsrcdir; "tools"; "ocamlobjinfo"] + +let ocamlmklib ocamlsrcdir = + Filename.make_path [ocamlsrcdir; "tools"; "ocamlmklib"] + +let codegen ocamlsrcdir = + Filename.make_path [ocamlsrcdir; "testsuite"; "tools"; "codegen"] + +let asmgen_archmod ocamlsrcdir = + let objname = + "asmgen_" ^ Ocamltest_config.arch ^ "." ^ Ocamltest_config.objext + in + Filename.make_path [ocamlsrcdir; "testsuite"; "tools"; objname] diff --git a/ocamltest/ocaml_files.mli b/ocamltest/ocaml_files.mli index c30d990b..95c93179 100644 --- a/ocamltest/ocaml_files.mli +++ b/ocamltest/ocaml_files.mli @@ -47,3 +47,7 @@ val ocamlyacc : string -> string val ocamldoc : string -> string val ocamldebug : string -> string val ocamlobjinfo : string -> string +val ocamlmklib : string -> string +val codegen : string -> string + +val asmgen_archmod : string -> string diff --git a/ocamltest/ocaml_filetypes.ml b/ocamltest/ocaml_filetypes.ml index 997cc1b7..c399cf7c 100644 --- a/ocamltest/ocaml_filetypes.ml +++ b/ocamltest/ocaml_filetypes.ml @@ -25,6 +25,7 @@ type t = | Lexer | Grammar | Binary_interface + | Obj | Backend_specific of Ocaml_backends.t * backend_specific | Text (* used by ocamldoc for text only documentation *) @@ -41,6 +42,7 @@ let string_of_filetype = function | Lexer -> "lexer" | Grammar -> "grammar" | Binary_interface -> "binary interface" + | Obj -> "object" | Backend_specific (backend, filetype) -> ((Ocaml_backends.string_of_backend backend) ^ " " ^ (string_of_backend_specific filetype)) @@ -54,6 +56,7 @@ let extension_of_filetype = function | Lexer -> "mll" | Grammar -> "mly" | Binary_interface -> "cmi" + | Obj -> Ocamltest_config.objext | Backend_specific (backend, filetype) -> begin match (backend, filetype) with | (Ocaml_backends.Native, Object) -> "cmx" @@ -73,6 +76,8 @@ let filetype_of_extension = function | "mll" -> Lexer | "mly" -> Grammar | "cmi" -> Binary_interface + | "o" -> Obj + | "obj" -> Obj | "cmx" -> Backend_specific (Ocaml_backends.Native, Object) | "cmxa" -> Backend_specific (Ocaml_backends.Native, Library) | "opt" -> Backend_specific (Ocaml_backends.Native, Program) @@ -80,7 +85,7 @@ let filetype_of_extension = function | "cma" -> Backend_specific (Ocaml_backends.Bytecode, Library) | "byte" -> Backend_specific (Ocaml_backends.Bytecode, Program) | "txt" -> Text - | _ -> raise Not_found + | _ as e -> Printf.eprintf "Unknown file extension %s\n%!" e; exit 2 let split_filename name = let l = String.length name in diff --git a/ocamltest/ocaml_filetypes.mli b/ocamltest/ocaml_filetypes.mli index 89911d4b..542d13ae 100644 --- a/ocamltest/ocaml_filetypes.mli +++ b/ocamltest/ocaml_filetypes.mli @@ -25,6 +25,7 @@ type t = | Lexer | Grammar | Binary_interface + | Obj | Backend_specific of Ocaml_backends.t * backend_specific | Text (** text-only documentation file *) diff --git a/ocamltest/ocaml_flags.ml b/ocamltest/ocaml_flags.ml index b45dcf47..520b2451 100644 --- a/ocamltest/ocaml_flags.ml +++ b/ocamltest/ocaml_flags.ml @@ -31,9 +31,9 @@ let runtime_variant_flags () = match Ocaml_files.runtime_variant() with | Ocaml_files.Debug -> " -runtime-variant d" | Ocaml_files.Instrumented -> " -runtime-variant i" -let runtime_flags ocamlsrcdir backend c_files = +let runtime_flags ocamlsrcdir env backend c_files = let runtime_library_flags = "-I " ^ - (Ocaml_directories.runtime_library backend ocamlsrcdir) in + (Ocaml_directories.runtime ocamlsrcdir) in let rt_flags = match backend with | Ocaml_backends.Native -> runtime_variant_flags () | Ocaml_backends.Bytecode -> @@ -41,7 +41,12 @@ let runtime_flags ocamlsrcdir backend c_files = if c_files then begin (* custom mode *) "-custom " ^ (runtime_variant_flags ()) end else begin (* non-custom mode *) - "-use-runtime " ^ (Ocaml_files.ocamlrun ocamlsrcdir) + let use_runtime = + Environments.lookup_as_bool Ocaml_variables.use_runtime env + in + if use_runtime = Some false + then "" + else "-use-runtime " ^ (Ocaml_files.ocamlrun ocamlsrcdir) end end in rt_flags ^ " " ^ runtime_library_flags diff --git a/ocamltest/ocaml_flags.mli b/ocamltest/ocaml_flags.mli index a2513786..7bfb3a32 100644 --- a/ocamltest/ocaml_flags.mli +++ b/ocamltest/ocaml_flags.mli @@ -21,7 +21,8 @@ val include_toplevel_directory : string -> string val c_includes : string -> string -val runtime_flags : string -> Ocaml_backends.t -> bool -> string +val runtime_flags : + string -> Environments.t -> Ocaml_backends.t -> bool -> string val toplevel_default_flags : string diff --git a/ocamltest/ocaml_modifiers.ml b/ocamltest/ocaml_modifiers.ml index 50d57a23..6bf8ed23 100644 --- a/ocamltest/ocaml_modifiers.ml +++ b/ocamltest/ocaml_modifiers.ml @@ -84,6 +84,9 @@ let unixlibdir = if Sys.os_type="Win32" then "win32unix" else "unix" let unix = make_library_modifier "unix" (compiler_subdir ["otherlibs"; unixlibdir]) +let dynlink = + make_library_modifier "dynlink" (compiler_subdir ["otherlibs"; "dynlink"]) + let str = make_library_modifier "str" (compiler_subdir ["otherlibs"; "str"]) @@ -109,6 +112,7 @@ let _ = register_modifiers "config" config; register_modifiers "testing" testing; register_modifiers "unix" unix; + register_modifiers "dynlink" dynlink; register_modifiers "str" str; register_modifiers "ocamlcommon" ocamlcommon; register_modifiers "systhreads" systhreads; diff --git a/ocamltest/ocaml_tests.ml b/ocamltest/ocaml_tests.ml index 35cfa75d..964eaa2f 100644 --- a/ocamltest/ocaml_tests.ml +++ b/ocamltest/ocaml_tests.ml @@ -105,6 +105,35 @@ let ocamldoc = [ skip ] } +let asmgen_skip_on_bytecode_only = + Actions_helpers.skip_with_reason "native compiler disabled" + +let asmgen_skip_on_spacetime = + Actions_helpers.skip_with_reason "not ported to Spacetime yet" + +let msvc64 = + Ocamltest_config.ccomptype = "msvc" && Ocamltest_config.arch="amd64" + +let asmgen_skip_on_msvc64 = + Actions_helpers.skip_with_reason "not ported to MSVC64 yet" + +let asmgen_actions = + if Ocamltest_config.arch="none" then [asmgen_skip_on_bytecode_only] + else if Ocamltest_config.spacetime then [asmgen_skip_on_spacetime] + else if msvc64 then [asmgen_skip_on_msvc64] + else [ + setup_simple_build_env; + codegen; + cc; + ] + +let asmgen = +{ + test_name = "asmgen"; + test_run_by_default = false; + test_actions = asmgen_actions +} + let _ = List.iter register [ @@ -113,4 +142,5 @@ let _ = toplevel; expect; ocamldoc; + asmgen; ] diff --git a/ocamltest/ocaml_tests.mli b/ocamltest/ocaml_tests.mli index b9cd0225..8ace884a 100644 --- a/ocamltest/ocaml_tests.mli +++ b/ocamltest/ocaml_tests.mli @@ -24,3 +24,5 @@ val toplevel : Tests.t val expect : Tests.t val ocamldoc : Tests.t + +val asmgen : Tests.t diff --git a/ocamltest/ocaml_variables.ml b/ocamltest/ocaml_variables.ml index 271d73f5..f118d2c6 100644 --- a/ocamltest/ocaml_variables.ml +++ b/ocamltest/ocaml_variables.ml @@ -28,10 +28,13 @@ open Variables (* Should not be necessary with a ppx *) let all_modules = make ("all_modules", "All the modules to compile and link") - + let binary_modules = make ("binary_modules", "Additional binary modules to link") +let bytecc_libs = make ("bytecc_libs", + "Libraries to link with for bytecode") + let c_preprocessor = make ("c_preprocessor", "Command to use to invoke the C preprocessor") @@ -80,11 +83,9 @@ let compiler_stdin = make ("compiler_stdin", let compile_only = make ("compile_only", "Compile only (do not link)") -let ocamlc_flags = make ("ocamlc_flags", - "Flags passed to ocamlc.byte and ocamlc.opt") +let csc = make ("csc", "Path to the CSharp compiler") -let ocamlc_default_flags = make ("ocamlc_default_flags", - "Flags passed by default to ocamlc.byte and ocamlc.opt") +let csc_flags = make ("csc_flags", "Flags for the CSharp compiler") let directories = make ("directories", "Directories to include by all the compilers") @@ -92,15 +93,47 @@ let directories = make ("directories", let flags = make ("flags", "Flags passed to all the compilers") +let last_flags = make ("last_flags", + "Flags passed to all the compilers at the end of the commandline") + let libraries = make ("libraries", "Libraries the program should be linked with") +let mkdll = make ("mkdll", + "Command to use to build a DLL") + +let mkexe = make ("mkexe", + "Command used to build an executable program DLL") + let module_ = make ("module", "Compile one module at once") let modules = make ("modules", "Other modules of the test") +let nativecc_libs = make ("nativecc_libs", + "Libraries to link with for native code") + +let objext = make ("objext", + "Extension of object files") + +let ocamlc_byte = make ("ocamlc_byte", + "Path of the ocamlc.byte executable") + +let ocamlopt_byte = make ("ocamlopt_byte", + "Path of the ocamlopt.byte executable") + +let ocamlrun = make ("ocamlrun", + "Path of the ocamlrun executable") + +let ocamlc_flags = make ("ocamlc_flags", + "Flags passed to ocamlc.byte and ocamlc.opt") + +let ocamlc_default_flags = make ("ocamlc_default_flags", + "Flags passed by default to ocamlc.byte and ocamlc.opt") + + + let ocamllex_flags = make ("ocamllex_flags", "Flags passed to ocamllex") @@ -116,6 +149,9 @@ let ocamlyacc_flags = make ("ocamlyacc_flags", let ocaml_exit_status = make ("ocaml_exit_status", "Expected exit status of ocaml") +let ocaml_filetype_flag = make ("ocaml_filetype_flag", + "Filetype of the testfile (-impl, -intf, etc.)") + let ocamlc_byte_exit_status = make ("ocamlc_byte_exit_status", "Expected exit status of ocac.byte") @@ -175,10 +211,23 @@ let ocaml_script_as_argument = let plugins = Variables.make ( "plugins", "plugins for ocamlc,ocamlopt or ocamldoc" ) +let shared_library_cflags = + Variables.make ("shared_library_cflags", + "Flags used to compile C files for inclusion in shared libraries") + +let sharedobjext = + Variables.make ("sharedobjext", + "Extension of shared object files") + +let use_runtime = + Variables.make ("use_runtime", + "Whether the -use-runtime option should be used" ) + let _ = List.iter register_variable [ all_modules; binary_modules; + bytecc_libs; c_preprocessor; caml_ld_library_path; compare_programs; @@ -190,23 +239,32 @@ let _ = List.iter register_variable compiler_output2; compiler_stdin; compile_only; + csc; + csc_flags; directories; flags; + last_flags; libraries; + mkdll; module_; modules; + nativecc_libs; + objext; + ocamlc_byte; + ocamlopt_byte; + ocamlrun; ocamlc_flags; ocamlc_default_flags; ocamlopt_flags; ocamlopt_default_flags; ocaml_exit_status; + ocaml_filetype_flag; ocamlc_byte_exit_status; ocamlopt_byte_exit_status; ocamlnat_exit_status; ocamlc_opt_exit_status; ocamlopt_opt_exit_status; ocamlrunparam; - os_type; ocamllex_flags; ocamlyacc_flags; ocamldoc_flags; @@ -217,5 +275,9 @@ let _ = List.iter register_variable ocamldebug_flags; ocamldebug_script; ocaml_script_as_argument; - plugins + os_type; + plugins; + shared_library_cflags; + sharedobjext; + use_runtime; ] diff --git a/ocamltest/ocaml_variables.mli b/ocamltest/ocaml_variables.mli index 458fd4e3..c0b75154 100644 --- a/ocamltest/ocaml_variables.mli +++ b/ocamltest/ocaml_variables.mli @@ -21,6 +21,9 @@ val all_modules : Variables.t val binary_modules : Variables.t +val bytecc_libs : Variables.t +(** Libraries to link with for bytecode *) + val c_preprocessor : Variables.t val caml_ld_library_path : Variables.t @@ -43,16 +46,37 @@ val compiler_stdin : Variables.t val compile_only : Variables.t +val csc : Variables.t + +val csc_flags : Variables.t + val directories : Variables.t val flags : Variables.t +val last_flags : Variables.t + val libraries : Variables.t +val mkdll : Variables.t +(** Command used to make a DLL *) + +val mkexe : Variables.t +(** Command used to build an executable program *) + val module_ : Variables.t val modules : Variables.t +val nativecc_libs : Variables.t +(** Libraries to link with for native code *) + +val objext : Variables.t + +val ocamlc_byte : Variables.t +val ocamlopt_byte : Variables.t +val ocamlrun : Variables.t + val ocamlc_flags : Variables.t val ocamlc_default_flags : Variables.t @@ -65,6 +89,8 @@ val ocamlyacc_flags : Variables.t val ocaml_exit_status : Variables.t +val ocaml_filetype_flag : Variables.t + val ocamlc_byte_exit_status : Variables.t val ocamlopt_byte_exit_status : Variables.t @@ -93,4 +119,10 @@ val ocamldoc_reference : Variables.t val ocaml_script_as_argument : Variables.t -val plugins: Variables.t +val plugins : Variables.t + +val shared_library_cflags : Variables.t + +val sharedobjext : Variables.t + +val use_runtime : Variables.t diff --git a/ocamltest/ocamltest_config.ml.in b/ocamltest/ocamltest_config.ml.in index 2ff85316..90bf0d3c 100644 --- a/ocamltest/ocamltest_config.ml.in +++ b/ocamltest/ocamltest_config.ml.in @@ -19,10 +19,24 @@ let arch = "@@ARCH@@" let afl_instrument = @@AFL_INSTRUMENT@@ +let asm = "@@ASM@@" + +let cc = "@@CC@@" + +let cflags = "@@CFLAGS@@" + +let ccomptype = "@@CCOMPTYPE@@" + let shared_libraries = @@SHARED_LIBRARIES@@ let libunix = @@UNIX@@ +let systhreads = @@SYSTHREADS@@ + +let str = @@STR@@ + +let objext = "@@OBJEXT@@" + let system = "@@SYSTEM@@" let c_preprocessor = "@@CPP@@" @@ -42,4 +56,23 @@ let flat_float_array = @@FLAT_FLOAT_ARRAY@@ let ocamldoc = @@OCAMLDOC@@ -let ocamldebug = @@OCAMLDOC@@ +let ocamldebug = @@OCAMLDEBUG@@ + +let native_dynlink = @@NATIVE_DYNLINK@@ + +let shared_library_cflags = "@@SHARED_LIBRARY_CFLAGS@@" + +let sharedobjext = "@@SHAREDOBJEXT@@" + +let csc = "@@CSC@@" + +let csc_flags = "@@CSCFLAGS@@" + +let mkdll = "@@MKDLL@@" +let mkexe = "@@MKEXE@@" + +let bytecc_libs = "@@BYTECCLIBS@@" + +let nativecc_libs = "@@NATIVECCLIBS@@" + +let windows_unicode = @@WINDOWS_UNICODE@@ != 0 diff --git a/ocamltest/ocamltest_config.mli b/ocamltest/ocamltest_config.mli index d8199f62..933d1ae3 100644 --- a/ocamltest/ocamltest_config.mli +++ b/ocamltest/ocamltest_config.mli @@ -21,11 +21,33 @@ val arch : string val afl_instrument : bool (** Whether AFL support has been enabled in the compiler *) +val asm : string +(** Path to the assembler*) + +val cc : string +(** Path to the C compiler*) + +val cflags : string +(** Flags to pass to the C compiler *) + +val ccomptype : string +(** Type of C compiler (msvc, cc, etc.) *) + val shared_libraries : bool (** [true] if shared libraries are supported, [false] otherwise *) -val libunix : bool -(** [true] for unix, [false] for win32unix *) +val libunix : bool option +(** [Some true] for unix, [Some false] for win32unix, or [None] if neither is + built. *) + +val systhreads : bool +(** Indicates whether systhreads is available. *) + +val str : bool +(** Indicates whether str is available. *) + +val objext : string +(** Extension of object files *) val system : string (** The content of the SYSTEM Make variable *) @@ -59,3 +81,27 @@ val ocamldoc : bool val ocamldebug : bool (** Whether ocamldebug has been enabled at configure time *) + +val native_dynlink : bool +(** Whether support for native dynlink is available or not *) + +val shared_library_cflags : string +(** Flags to use when compiling a C object for a shared library *) + +val sharedobjext : string +(** Extension of shared object files *) + +val csc : string +(** Path of the CSharp compiler, empty if not available *) + +val csc_flags : string +(** Flags for the CSharp compiler *) + +val mkdll : string +val mkexe : string + +val bytecc_libs : string + +val nativecc_libs : string + +val windows_unicode : bool diff --git a/ocamltest/ocamltest_stdlib.ml b/ocamltest/ocamltest_stdlib.ml index 24ff3452..2d667299 100644 --- a/ocamltest/ocamltest_stdlib.ml +++ b/ocamltest/ocamltest_stdlib.ml @@ -56,7 +56,7 @@ module List = struct end module String = struct - include String + include Misc.Stdlib.String let string_of_char = String.make 1 let words s = @@ -175,10 +175,3 @@ module Sys = struct try Sys.getenv variable with Not_found -> default_value let safe_getenv variable = getenv_with_default_value variable "" end - -module StringSet = struct - include Set.Make (String) - let string_of_stringset s = String.concat ", " (elements s) -end - -module StringMap : Map.S with type key = string = Map.Make (String) diff --git a/ocamltest/ocamltest_stdlib.mli b/ocamltest/ocamltest_stdlib.mli index 35420505..2200b3d5 100644 --- a/ocamltest/ocamltest_stdlib.mli +++ b/ocamltest/ocamltest_stdlib.mli @@ -39,7 +39,7 @@ module List : sig end module String : sig - include module type of String + include module type of Misc.Stdlib.String val words : string -> string list end @@ -56,10 +56,3 @@ module Sys : sig val getenv_with_default_value : string -> string -> string val safe_getenv : string -> string end - -module StringSet : sig - include Set.S with type elt = string - val string_of_stringset : t -> string -end - -module StringMap : Map.S with type key = string diff --git a/ocamltest/ocamltest_stdlib_stubs.c b/ocamltest/ocamltest_stdlib_stubs.c index 125275ef..18f4f519 100644 --- a/ocamltest/ocamltest_stdlib_stubs.c +++ b/ocamltest/ocamltest_stdlib_stubs.c @@ -60,7 +60,8 @@ CAMLprim value caml_has_symlink(value unit) if (!GetTokenInformation(hProcess, TokenPrivileges, NULL, 0, &length)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - TOKEN_PRIVILEGES* privileges = (TOKEN_PRIVILEGES*)caml_stat_alloc(length); + TOKEN_PRIVILEGES* privileges = + (TOKEN_PRIVILEGES*)caml_stat_alloc(length); if (GetTokenInformation(hProcess, TokenPrivileges, privileges, @@ -70,7 +71,9 @@ CAMLprim value caml_has_symlink(value unit) if (count) { LUID_AND_ATTRIBUTES* privs = privileges->Privileges; - while (count-- && !(result = luid_eq(privs->Luid, seCreateSymbolicLinkPrivilege))) + while (count-- && + !(result = luid_eq(privs->Luid, + seCreateSymbolicLinkPrivilege))) privs++; } } diff --git a/ocamltest/options.ml b/ocamltest/options.ml index 782e314d..1547735c 100644 --- a/ocamltest/options.ml +++ b/ocamltest/options.ml @@ -28,6 +28,11 @@ let string_of_test test = then (test.Tests.test_name ^ " (run by default)") else test.Tests.test_name +let string_of_variable v = + Printf.sprintf "%s: %s" + (Variables.name_of_variable v) + (Variables.description_of_variable v) + let show_actions () = let actions = Actions.get_registered_actions () in show_objects "Available actions are:" string_of_action actions @@ -36,6 +41,10 @@ let show_tests () = let tests = Tests.get_registered_tests () in show_objects "Available tests are:" string_of_test tests +let show_variables () = + let variables = Variables.get_registered_variables () in + show_objects "Available variables are:" string_of_variable variables + let log_to_stderr = ref false let promote = ref false @@ -47,6 +56,7 @@ let commandline_options = "Overwrite reference files with the test output (experimental, unstable)"); ("-show-actions", Arg.Unit show_actions, "Show available actions."); ("-show-tests", Arg.Unit show_tests, "Show available tests."); + ("-show-variables", Arg.Unit show_variables, "Show available variables."); ] let files_to_test = ref [] diff --git a/ocamltest/run_unix.c b/ocamltest/run_unix.c index 4a89ed87..5fc70e7e 100644 --- a/ocamltest/run_unix.c +++ b/ocamltest/run_unix.c @@ -105,17 +105,21 @@ static int paths_same_file( if (realpath1 == NULL) realpath_error(path1); realpath2 = realpath(path2, NULL); - if ( (realpath2 == NULL) && (errno != ENOENT) ) + if (realpath2 == NULL) { free(realpath1); - realpath_error(path2); + if (errno == ENOENT) return 0; + else realpath_error(path2); } #else char realpath1[PATH_MAX], realpath2[PATH_MAX]; if (realpath(path1, realpath1) == NULL) realpath_error(path1); - if ((realpath(path2, realpath2) == NULL) && (errno != ENOENT)) - realpath_error(path2); + if (realpath(path2, realpath2) == NULL) + { + if (errno == ENOENT) return 0; + else realpath_error(path2); + } #endif /* __GLIBC__ */ if (strcmp(realpath1, realpath2) == 0) same_file = 1; @@ -148,7 +152,7 @@ static void update_environment(array local_env) } /* - This function should retunr an exitcode that can itslef be returned + This function should return an exitcode that can itself be returned to its father through the exit system call. So it returns 0 to report success and 1 to report an error @@ -231,7 +235,7 @@ child_failed: * Its termination status as returned by wait(2) * A string giving a prefix for the core file name. (the file will be called prefix.pid.core but may come from a - diffferent process) + different process) * Returns the code to return if this is the child process */ static int handle_process_termination( diff --git a/ocamltest/run_win32.c b/ocamltest/run_win32.c index cd9e2512..f5353575 100644 --- a/ocamltest/run_win32.c +++ b/ocamltest/run_win32.c @@ -256,9 +256,16 @@ int run_command(const command_settings *settings) LPCWSTR current_directory = NULL; STARTUPINFO startup_info; PROCESS_INFORMATION process_info; - DWORD wait_result, status; + BOOL wait_result; + DWORD status, stamp, cur; DWORD timeout = (settings->timeout > 0) ? settings->timeout * 1000 : INFINITE; + JOBOBJECT_ASSOCIATE_COMPLETION_PORT port = {NULL, NULL}; + HANDLE hJob = NULL; + DWORD completion_code; + ULONG_PTR completion_key; + LPOVERLAPPED pOverlapped; + ZeroMemory(&startup_info, sizeof(STARTUPINFO)); startup_info.cb = sizeof(STARTUPINFO); startup_info.dwFlags = STARTF_USESTDHANDLES; @@ -328,7 +335,7 @@ int run_command(const command_settings *settings) NULL, /* SECURITY_ATTRIBUTES process_attributes */ NULL, /* SECURITY_ATTRIBUTES thread_attributes */ TRUE, /* BOOL inherit_handles */ - CREATE_UNICODE_ENVIRONMENT, /* DWORD creation_flags */ + CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT, /* DWORD creation_flags */ environment, NULL, /* LPCSTR current_directory */ &startup_info, @@ -336,23 +343,52 @@ int run_command(const command_settings *settings) ); checkerr( (! process_created), "CreateProcess failed", NULL); - CloseHandle(process_info.hThread); /* Not needed so closed ASAP */ - - wait_result = WaitForSingleObject(process_info.hProcess, timeout); - if (wait_result == WAIT_OBJECT_0) + hJob = CreateJobObject(NULL, NULL); + checkerr( (hJob == NULL), "CreateJobObject failed", NULL); + checkerr( !AssignProcessToJobObject(hJob, process_info.hProcess), + "AssignProcessToJob failed", NULL); + port.CompletionPort = + CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); + checkerr( (port.CompletionPort == NULL), + "CreateIoCompletionPort failed", NULL); + checkerr( !SetInformationJobObject( + hJob, + JobObjectAssociateCompletionPortInformation, + &port, sizeof(port)), "SetInformationJobObject failed", NULL); + + ResumeThread(process_info.hThread); + CloseHandle(process_info.hThread); + + stamp = GetTickCount(); + while ((wait_result = GetQueuedCompletionStatus(port.CompletionPort, + &completion_code, + &completion_key, + &pOverlapped, + timeout)) + && completion_code != JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO) + { + if (timeout != INFINITE) + { + cur = GetTickCount(); + stamp = (cur > stamp ? cur - stamp : MAXDWORD - stamp + cur); + timeout = (timeout > stamp ? timeout - stamp : 0); + stamp = cur; + } + } + if (wait_result) { /* The child has terminated before the timeout has expired */ checkerr( (! GetExitCodeProcess(process_info.hProcess, &status)), "GetExitCodeProcess failed", NULL); - } else if (wait_result == WAIT_TIMEOUT) { + } else if (pOverlapped == NULL) { /* The timeout has expired, terminate the process */ - checkerr( (! TerminateProcess(process_info.hProcess, 0)), - "TerminateProcess failed", NULL); + checkerr( (! TerminateJobObject(hJob, 0)), + "TerminateJob failed", NULL); status = -1; wait_again = 1; } else { error_with_location(__FILE__, __LINE__, settings, - "WaitForSingleObject failed\n"); + "GetQueuedCompletionStatus failed\n"); report_error(__FILE__, __LINE__, settings, "Failure while waiting for process termination", NULL); status = -1; @@ -370,5 +406,7 @@ cleanup: WaitForSingleObject(process_info.hProcess, 1000); } if (process_created) CloseHandle(process_info.hProcess); + if (hJob != NULL) CloseHandle(hJob); + if (port.CompletionPort != NULL) CloseHandle(port.CompletionPort); return status; } diff --git a/ocamltest/tsl_ast.ml b/ocamltest/tsl_ast.ml index fda94cb6..47180b66 100644 --- a/ocamltest/tsl_ast.ml +++ b/ocamltest/tsl_ast.ml @@ -23,7 +23,7 @@ type 'a located = { type environment_statement = | Assignment of bool * string located * string located (* variable = value *) | Append of string located * string located - | Include of string located (* include named environemnt *) + | Include of string located (* include named environment *) type tsl_item = | Environment_statement of environment_statement located diff --git a/ocamltest/tsl_ast.mli b/ocamltest/tsl_ast.mli index 9fc47c21..06a61a19 100644 --- a/ocamltest/tsl_ast.mli +++ b/ocamltest/tsl_ast.mli @@ -23,7 +23,7 @@ type 'a located = { type environment_statement = | Assignment of bool * string located * string located (* variable = value *) | Append of string located * string located (* variable += value *) - | Include of string located (* include named environemnt *) + | Include of string located (* include named environment *) type tsl_item = | Environment_statement of environment_statement located diff --git a/ocamltest/tsl_lexer.mli b/ocamltest/tsl_lexer.mli index a92ad67b..b25e9f85 100644 --- a/ocamltest/tsl_lexer.mli +++ b/ocamltest/tsl_lexer.mli @@ -16,3 +16,5 @@ (* Interface to the Tsl_lexer module *) val token : Lexing.lexbuf -> Tsl_parser.token +val modifier : + Lexing.lexbuf -> string * [`Remove | `Add of string | `Append of string] diff --git a/ocamltest/tsl_lexer.mll b/ocamltest/tsl_lexer.mll index 966483a3..90a30836 100644 --- a/ocamltest/tsl_lexer.mll +++ b/ocamltest/tsl_lexer.mll @@ -13,7 +13,8 @@ (* *) (**************************************************************************) -(* Lexer definitions for the Tests Specification Language *) +(* Lexer definitions for the Tests Specification Language and for + response files *) { open Tsl_parser @@ -54,12 +55,8 @@ rule token = parse comment_start_pos := [Lexing.lexeme_start_p lexbuf]; comment lexbuf } - | "\"" [^'"']* "\"" - { let s = Lexing.lexeme lexbuf in - let string_length = (String.length s) -2 in - let s' = String.sub s 1 string_length in - STRING s' - } + | '"' + { STRING (string "" lexbuf) } | _ { let pos = Lexing.lexeme_start_p lexbuf in @@ -70,6 +67,28 @@ rule token = parse file line column (Lexing.lexeme lexbuf) in lexer_error message } +(* Backslashes are ignored in strings except at the end of lines where they + cause the newline to be ignored. After an escaped newline, any blank + characters at the start of the line are ignored and optionally one blank + character may be escaped with a backslash. + + In particular, this means that the following: +script = "some-directory\\ + \ foo" + is interpreted as the OCaml string "some-directory\\ foo". + *) +and string acc = parse + | [^ '\\' '"' ]+ + { string (acc ^ Lexing.lexeme lexbuf) lexbuf } + | '\\' newline blank* ('\\' (blank as blank))? + { let space = + match blank with None -> "" | Some blank -> String.make 1 blank + in + string (acc ^ space) lexbuf } + | '\\' + {string (acc ^ "\\") lexbuf} + | '"' + {acc} and comment = parse | "(*" { @@ -96,3 +115,14 @@ and comment = parse { comment lexbuf } + +(* Parse one line of a response file (for scripts and hooks) *) +and modifier = parse + | '-' (identchar* as variable) + { variable, `Remove } + | (identchar* as variable) "=\"" (_* as str) '"' + { variable, `Add str } + | (identchar* as variable) "+=\"" (_* as str) '"' + { variable, `Append str } + | _ + { failwith "syntax error in script response file" } diff --git a/ocamltest/variables.ml b/ocamltest/variables.ml index 9f8fa1b4..e72bf1c5 100644 --- a/ocamltest/variables.ml +++ b/ocamltest/variables.ml @@ -66,3 +66,7 @@ let find_variable variable_name = let string_of_binding variable value = variable.variable_exporter value + +let get_registered_variables () = + let f _variable_name variable variable_list = variable::variable_list in + List.sort compare (Hashtbl.fold f variables []) diff --git a/ocamltest/variables.mli b/ocamltest/variables.mli index 86b093d9..8a70c7ff 100644 --- a/ocamltest/variables.mli +++ b/ocamltest/variables.mli @@ -42,3 +42,5 @@ val register_variable : t -> unit val find_variable : string -> t option val string_of_binding : t -> value -> string + +val get_registered_variables : unit -> t list diff --git a/otherlibs/Makefile b/otherlibs/Makefile index 98d6d470..cc77536b 100644 --- a/otherlibs/Makefile +++ b/otherlibs/Makefile @@ -2,9 +2,9 @@ #* * #* OCaml * #* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* Gabriel Scherer, projet Parsifal, INRIA Saclay * #* * -#* Copyright 1999 Institut National de Recherche en Informatique et * +#* Copyright 2018 Institut National de Recherche en Informatique et * #* en Automatique. * #* * #* All rights reserved. This file is distributed under the terms of * @@ -13,112 +13,23 @@ #* * #************************************************************************** -# Common Makefile for otherlibs - -ROOTDIR=../.. -include $(ROOTDIR)/config/Makefile +ROOTDIR=.. +include $(ROOTDIR)/Makefile.config include $(ROOTDIR)/Makefile.common -CAMLRUN ?= $(ROOTDIR)/boot/ocamlrun -CAMLYACC ?= $(ROOTDIR)/boot/ocamlyacc - -ifeq "$(wildcard $(ROOTDIR)/flexdll/Makefile)" "" -export OCAML_FLEXLINK:= -else -export OCAML_FLEXLINK:=$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/flexdll/flexlink.exe -endif - -CAMLC=$(CAMLRUN) $(ROOTDIR)/ocamlc -nostdlib -I $(ROOTDIR)/stdlib -CAMLOPT=$(CAMLRUN) $(ROOTDIR)/ocamlopt -nostdlib \ - -I $(ROOTDIR)/stdlib -CFLAGS += $(SHAREDCCCOMPOPTS) $(EXTRACFLAGS) -CPPFLAGS += -I$(ROOTDIR)/byterun - -# Compilation options -COMPFLAGS=-absname -w +a-4-9-41-42-44-45-48 -warn-error A -bin-annot -g \ - -safe-string -strict-sequence -strict-formats $(EXTRACAMLFLAGS) -ifeq "$(FLAMBDA)" "true" -OPTCOMPFLAGS=-O3 -else -OPTCOMPFLAGS= -endif -MKLIB=$(CAMLRUN) $(ROOTDIR)/tools/ocamlmklib - -# Variables to be defined by individual libraries: -#LIBNAME= -#CLIBNAME= -#CMIFILES= -#CAMLOBJS= -#COBJS= -#EXTRACFLAGS= -#EXTRACAMLFLAGS= -#LINKOPTS= -#LDOPTS= -#HEADERS= - -CMIFILES ?= $(CAMLOBJS:.cmo=.cmi) -CAMLOBJS_NAT ?= $(CAMLOBJS:.cmo=.cmx) -CLIBNAME ?= $(LIBNAME) - -all: lib$(CLIBNAME).$(A) $(LIBNAME).cma $(CMIFILES) - -allopt: lib$(CLIBNAME).$(A) $(LIBNAME).cmxa $(LIBNAME).$(CMXS) $(CMIFILES) - -$(LIBNAME).cma: $(CAMLOBJS) - $(MKLIB) -o $(LIBNAME) -oc $(CLIBNAME) -ocamlc '$(CAMLC)' -linkall \ - $(CAMLOBJS) $(LINKOPTS) - -$(LIBNAME).cmxa: $(CAMLOBJS_NAT) - $(MKLIB) -o $(LIBNAME) -oc $(CLIBNAME) -ocamlopt '$(CAMLOPT)' -linkall \ - $(CAMLOBJS_NAT) $(LINKOPTS) - -$(LIBNAME).cmxs: $(LIBNAME).cmxa lib$(CLIBNAME).$(A) - $(CAMLOPT) -shared -o $(LIBNAME).cmxs -I . $(LIBNAME).cmxa - -lib$(CLIBNAME).$(A): $(COBJS) - $(MKLIB) -oc $(CLIBNAME) $(COBJS) $(LDOPTS) - -install:: - if test -f dll$(CLIBNAME)$(EXT_DLL); then \ - $(INSTALL_PROG) \ - dll$(CLIBNAME)$(EXT_DLL) \ - "$(INSTALL_STUBLIBDIR)/"; \ - fi - $(INSTALL_DATA) lib$(CLIBNAME).$(A) "$(INSTALL_LIBDIR)/" - cd "$(INSTALL_LIBDIR)"; $(RANLIB) lib$(CLIBNAME).$(A) - $(INSTALL_DATA) \ - $(LIBNAME).cma $(CMIFILES) $(CMIFILES:.cmi=.mli) \ - $(CMIFILES:.cmi=.cmti) \ - "$(INSTALL_LIBDIR)/" - if test -n "$(HEADERS)"; then \ - $(INSTALL_DATA) $(HEADERS) "$(INSTALL_LIBDIR)/caml/"; \ - fi - -installopt: - $(INSTALL_DATA) \ - $(CAMLOBJS_NAT) $(LIBNAME).cmxa $(LIBNAME).$(A) \ - "$(INSTALL_LIBDIR)/" - cd "$(INSTALL_LIBDIR)"; $(RANLIB) $(LIBNAME).a - if test -f $(LIBNAME).cmxs; then \ - $(INSTALL_PROG) $(LIBNAME).cmxs "$(INSTALL_LIBDIR)/"; \ - fi - -partialclean: - rm -f *.cm* - -clean:: partialclean - rm -f *.dll *.so *.a *.lib *.o *.obj - -.SUFFIXES: .ml .mli .cmi .cmo .cmx .$(O) - -.mli.cmi: - $(CAMLC) -c $(COMPFLAGS) $< - -.ml.cmo: - $(CAMLC) -c $(COMPFLAGS) $< - -.ml.cmx: - $(CAMLOPT) -c $(COMPFLAGS) $(OPTCOMPFLAGS) $< - -.c.$(O): - $(CC) -c $(CFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $< +# $1: target name to dispatch to all otherlibs/*/Makefile +define dispatch_ +$1: + @for lib in $$(OTHERLIBRARIES); do \ + ($$(MAKE) -C $$$$lib $1) || exit $$$$?; \ + done +endef +define dispatch +$(eval $(call dispatch_,$1)) +endef + +.PHONY: all allopt clean partialclean +$(call dispatch,all) +$(call dispatch,allopt) +$(call dispatch,clean) +$(call dispatch,partialclean) diff --git a/otherlibs/Makefile.otherlibs.common b/otherlibs/Makefile.otherlibs.common new file mode 100644 index 00000000..b121b0cd --- /dev/null +++ b/otherlibs/Makefile.otherlibs.common @@ -0,0 +1,141 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 1999 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +# Common Makefile for otherlibs + +ROOTDIR=../.. +include $(ROOTDIR)/Makefile.config +include $(ROOTDIR)/Makefile.common + +CAMLRUN ?= $(ROOTDIR)/boot/ocamlrun + +CAMLC=$(CAMLRUN) $(ROOTDIR)/ocamlc -nostdlib -I $(ROOTDIR)/stdlib +CAMLOPT=$(CAMLRUN) $(ROOTDIR)/ocamlopt -nostdlib \ + -I $(ROOTDIR)/stdlib +OC_CFLAGS += $(SHAREDLIB_CFLAGS) $(EXTRACFLAGS) +OC_CPPFLAGS += -I$(ROOTDIR)/runtime + +# Compilation options +COMPFLAGS=-absname -w +a-4-9-41-42-44-45-48 -warn-error A -bin-annot -g \ + -safe-string -strict-sequence -strict-formats $(EXTRACAMLFLAGS) +ifeq "$(FLAMBDA)" "true" +OPTCOMPFLAGS=-O3 +else +OPTCOMPFLAGS= +endif +MKLIB=$(CAMLRUN) $(ROOTDIR)/tools/ocamlmklib + +# Variables to be defined by individual libraries: +#LIBNAME= +#CLIBNAME= +#CMIFILES= +#CAMLOBJS= +#COBJS= +#EXTRACFLAGS= +#EXTRACAMLFLAGS= +#LINKOPTS= +#LDOPTS= +#HEADERS= + +CMIFILES ?= $(CAMLOBJS:.cmo=.cmi) +CAMLOBJS_NAT ?= $(CAMLOBJS:.cmo=.cmx) +CLIBNAME ?= $(LIBNAME) + +ifeq "$(COBJS)" "" +STUBSLIB= +else +STUBSLIB=lib$(CLIBNAME).$(A) +endif + +.PHONY: all allopt opt.opt # allopt and opt.opt are synonyms +all: $(STUBSLIB) $(LIBNAME).cma $(CMIFILES) + +allopt: $(STUBSLIB) $(LIBNAME).cmxa $(LIBNAME).$(CMXS) $(CMIFILES) +opt.opt: allopt + +$(LIBNAME).cma: $(CAMLOBJS) +ifeq "$(COBJS)" "" + $(CAMLC) -o $@ -a -linkall $(CAMLOBJS) $(LINKOPTS) +else + $(MKLIB) -o $(LIBNAME) -oc $(CLIBNAME) -ocamlc '$(CAMLC)' -linkall \ + $(CAMLOBJS) $(LINKOPTS) +endif + +$(LIBNAME).cmxa: $(CAMLOBJS_NAT) +ifeq "$(COBJS)" "" + $(CAMLOPT) -o $@ -a -linkall $(CAMLOBJS_NAT) $(LINKOPTS) +else + $(MKLIB) -o $(LIBNAME) -oc $(CLIBNAME) -ocamlopt '$(CAMLOPT)' -linkall \ + $(CAMLOBJS_NAT) $(LINKOPTS) +endif + +$(LIBNAME).cmxs: $(LIBNAME).cmxa $(STUBSLIB) + $(CAMLOPT_CMD) -shared -o $(LIBNAME).cmxs -I . $(LIBNAME).cmxa + +lib$(CLIBNAME).$(A): $(COBJS) + $(MKLIB_CMD) -oc $(CLIBNAME) $(COBJS) $(LDOPTS) + +install:: + if test -f dll$(CLIBNAME)$(EXT_DLL); then \ + $(INSTALL_PROG) \ + dll$(CLIBNAME)$(EXT_DLL) \ + "$(INSTALL_STUBLIBDIR)/"; \ + fi +ifneq "$(STUBSLIB)" "" + $(INSTALL_DATA) $(STUBSLIB) "$(INSTALL_LIBDIR)/" + cd "$(INSTALL_LIBDIR)"; $(RANLIB) lib$(CLIBNAME).$(A) +endif + + $(INSTALL_DATA) \ + $(LIBNAME).cma $(CMIFILES) \ + "$(INSTALL_LIBDIR)/" +ifeq "$(INSTALL_SOURCE_ARTIFACTS)" "true" + $(INSTALL_DATA) \ + $(CMIFILES:.cmi=.mli) \ + $(CMIFILES:.cmi=.cmti) \ + "$(INSTALL_LIBDIR)/" +endif + if test -n "$(HEADERS)"; then \ + $(INSTALL_DATA) $(HEADERS) "$(INSTALL_LIBDIR)/caml/"; \ + fi + +installopt: + $(INSTALL_DATA) \ + $(CAMLOBJS_NAT) $(LIBNAME).cmxa $(LIBNAME).$(A) \ + "$(INSTALL_LIBDIR)/" + cd "$(INSTALL_LIBDIR)"; $(RANLIB) $(LIBNAME).a + if test -f $(LIBNAME).cmxs; then \ + $(INSTALL_PROG) $(LIBNAME).cmxs "$(INSTALL_LIBDIR)/"; \ + fi + +partialclean: + rm -f *.cm* + +clean:: partialclean + rm -f *.dll *.so *.a *.lib *.o *.obj + +.SUFFIXES: .ml .mli .cmi .cmo .cmx .$(O) + +.mli.cmi: + $(CAMLC) -c $(COMPFLAGS) $< + +.ml.cmo: + $(CAMLC) -c $(COMPFLAGS) $< + +.ml.cmx: + $(CAMLOPT) -c $(COMPFLAGS) $(OPTCOMPFLAGS) $< + +.c.$(O): + $(CC) -c $(OC_CFLAGS) $(OC_CPPFLAGS) $(OUTPUTOBJ)$@ $< diff --git a/otherlibs/bigarray/.depend b/otherlibs/bigarray/.depend index a58e2688..24e7963a 100644 --- a/otherlibs/bigarray/.depend +++ b/otherlibs/bigarray/.depend @@ -1,3 +1,5 @@ -bigarray.cmo : bigarray.cmi -bigarray.cmx : bigarray.cmi +bigarray.cmo : \ + bigarray.cmi +bigarray.cmx : \ + bigarray.cmi bigarray.cmi : diff --git a/otherlibs/bigarray/Makefile b/otherlibs/bigarray/Makefile index f24de2d1..577b4f1b 100644 --- a/otherlibs/bigarray/Makefile +++ b/otherlibs/bigarray/Makefile @@ -14,25 +14,13 @@ #************************************************************************** LIBNAME=bigarray -EXTRACFLAGS=-I../$(UNIXLIB) -DIN_OCAML_BIGARRAY -EXTRACAMLFLAGS=-I ../$(UNIXLIB) -COBJS=mmap_ba.$(O) mmap.$(O) CAMLOBJS=bigarray.cmo -include ../Makefile - -ifeq "$(SYSTEM)" "mingw" -LDOPTS=-ldopt "-link -static-libgcc" -endif - -mmap.$(O): ../$(UNIXLIB)/mmap.c - $(CC) -c $(CFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $< -mmap_ba.$(O): ../unix/mmap_ba.c - $(CC) -c $(CFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ $< +include ../Makefile.otherlibs.common .PHONY: depend depend: - $(CAMLRUN) $(ROOTDIR)/tools/ocamldep -slash *.mli *.ml > .depend + $(CAMLRUN) $(ROOTDIR)/boot/ocamlc -depend -slash *.mli *.ml > .depend include .depend diff --git a/otherlibs/bigarray/Makefile.nt b/otherlibs/bigarray/Makefile.nt deleted file mode 100644 index ed9900bb..00000000 --- a/otherlibs/bigarray/Makefile.nt +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include Makefile diff --git a/otherlibs/bigarray/bigarray.ml b/otherlibs/bigarray/bigarray.ml index e9dd59ff..d7c9354e 100644 --- a/otherlibs/bigarray/bigarray.ml +++ b/otherlibs/bigarray/bigarray.ml @@ -12,40 +12,4 @@ (* *) (**************************************************************************) -module Super = Stdlib.Bigarray - -include (Super : module type of struct include Super end - with module Genarray := Super.Genarray - with module Array1 := Super.Array1 - with module Array2 := Super.Array2 - with module Array3 := Super.Array3) - -module Genarray = struct - include Super.Genarray - external map_internal: Unix.file_descr -> ('a, 'b) kind -> 'c layout -> - bool -> int array -> int64 -> ('a, 'b, 'c) t - = "caml_ba_map_file_bytecode" "caml_ba_map_file" - let map_file fd ?(pos = 0L) kind layout shared dims = - map_internal fd kind layout shared dims pos -end - -module Array1 = struct - include Super.Array1 - let map_file fd ?pos kind layout shared dim = - array1_of_genarray - (Genarray.map_file fd ?pos kind layout shared [|dim|]) -end - -module Array2 = struct - include Super.Array2 - let map_file fd ?pos kind layout shared dim1 dim2 = - array2_of_genarray - (Genarray.map_file fd ?pos kind layout shared [|dim1;dim2|]) -end - -module Array3 = struct - include Super.Array3 - let map_file fd ?pos kind layout shared dim1 dim2 dim3 = - array3_of_genarray - (Genarray.map_file fd ?pos kind layout shared [|dim1;dim2;dim3|]) -end +include Stdlib.Bigarray diff --git a/otherlibs/bigarray/bigarray.mli b/otherlibs/bigarray/bigarray.mli index 9b8952fc..9dcaed96 100644 --- a/otherlibs/bigarray/bigarray.mli +++ b/otherlibs/bigarray/bigarray.mli @@ -13,48 +13,3 @@ (**************************************************************************) include module type of struct include Stdlib.Bigarray end - with module Genarray := Stdlib.Bigarray.Genarray - with module Array1 := Stdlib.Bigarray.Array1 - with module Array2 := Stdlib.Bigarray.Array2 - with module Array3 := Stdlib.Bigarray.Array3 - -module Genarray : sig - include module type of struct include Stdlib.Bigarray.Genarray end - val map_file: - Unix.file_descr -> ?pos:int64 -> ('a, 'b) kind -> 'c layout -> - bool -> int array -> ('a, 'b, 'c) t - [@@ocaml.deprecated "\ -Use Unix.map_file instead.\n\ -Note that Bigarray.Genarray.map_file raises Sys_error while\n\ -Unix.map_file raises Unix_error."] -end - -module Array1 : sig - include module type of struct include Stdlib.Bigarray.Array1 end - val map_file: Unix.file_descr -> ?pos:int64 -> ('a, 'b) kind -> 'c layout -> - bool -> int -> ('a, 'b, 'c) t - [@@ocaml.deprecated "\ -Use [array1_of_genarray (Unix.map_file ...)] instead.\n\ -Note that Bigarray.Array1.map_file raises Sys_error while\n\ -Unix.map_file raises Unix_error."] -end - -module Array2 : sig - include module type of struct include Stdlib.Bigarray.Array2 end - val map_file: Unix.file_descr -> ?pos:int64 -> ('a, 'b) kind -> 'c layout -> - bool -> int -> int -> ('a, 'b, 'c) t - [@@ocaml.deprecated "\ -Use [array2_of_genarray (Unix.map_file ...)] instead.\n\ -Note that Bigarray.Array2.map_file raises Sys_error while\n\ -Unix.map_file raises Unix_error."] -end - -module Array3 : sig - include module type of struct include Stdlib.Bigarray.Array3 end - val map_file: Unix.file_descr -> ?pos:int64 -> ('a, 'b) kind -> 'c layout -> - bool -> int -> int -> int -> ('a, 'b, 'c) t - [@@ocaml.deprecated "\ -Use [array3_of_genarray (Unix.map_file ...)] instead.\n\ -Note that Bigarray.Array3.map_file raises Sys_error while\n\ -Unix.map_file raises Unix_error."] -end diff --git a/testsuite/tests/letrec/allowed.reference b/otherlibs/bigarray/empty.c similarity index 100% rename from testsuite/tests/letrec/allowed.reference rename to otherlibs/bigarray/empty.c diff --git a/otherlibs/dynlink/Makefile b/otherlibs/dynlink/Makefile index 6ed6c34c..6e7c4238 100644 --- a/otherlibs/dynlink/Makefile +++ b/otherlibs/dynlink/Makefile @@ -17,19 +17,19 @@ # FIXME reduce redundancy by including ../Makefile -include ../../config/Makefile -include ../../Makefile.common +ROOTDIR = ../.. -CAMLRUN ?= ../../boot/ocamlrun -CAMLYACC ?= ../../boot/ocamlyacc +include $(ROOTDIR)/Makefile.config +include $(ROOTDIR)/Makefile.common + +CAMLRUN ?= $(ROOTDIR)/boot/ocamlrun -ROOTDIR = ../.. OCAMLC = $(CAMLRUN) $(ROOTDIR)/ocamlc -nostdlib -I $(ROOTDIR)/stdlib OCAMLOPT = $(CAMLRUN) $(ROOTDIR)/ocamlopt -nostdlib -I $(ROOTDIR)/stdlib -INCLUDES=-I ../../utils -I ../../typing -I ../../bytecomp -I ../../asmcomp -COMPFLAGS=$(INCLUDES) -absname -w +a-4-9-41-42-44-45-48 -bin-annot -g \ - -I ../../stdlib -warn-error A \ +INCLUDES=$(addprefix -I $(ROOTDIR)/,utils typing bytecomp asmcomp) +COMPFLAGS=$(INCLUDES) -absname -w +a-4-9-40-41-42-44-45-48 -bin-annot -g \ + -I $(ROOTDIR)/stdlib -warn-error A \ -safe-string -strict-sequence -strict-formats ifeq "$(FLAMBDA)" "true" OPTCOMPFLAGS=-O3 @@ -37,63 +37,121 @@ else OPTCOMPFLAGS= endif -OBJS=dynlinkaux.cmo dynlink.cmo - -COMPILEROBJS=\ - ../../utils/misc.cmo ../../utils/config.cmo \ - ../../utils/identifiable.cmo ../../utils/numbers.cmo \ - ../../utils/arg_helper.cmo ../../utils/clflags.cmo \ - ../../utils/tbl.cmo ../../utils/consistbl.cmo \ - ../../utils/terminfo.cmo ../../utils/warnings.cmo \ - ../../utils/build_path_prefix_map.cmo \ - ../../parsing/asttypes.cmi \ - ../../parsing/location.cmo ../../parsing/longident.cmo \ - ../../parsing/docstrings.cmo ../../parsing/syntaxerr.cmo \ - ../../parsing/ast_helper.cmo \ - ../../parsing/ast_mapper.cmo ../../parsing/ast_iterator.cmo \ - ../../parsing/attr_helper.cmo \ - ../../parsing/builtin_attributes.cmo \ - ../../typing/ident.cmo ../../typing/path.cmo \ - ../../typing/primitive.cmo ../../typing/types.cmo \ - ../../typing/btype.cmo ../../typing/subst.cmo ../../typing/predef.cmo \ - ../../typing/datarepr.cmo ../../typing/cmi_format.cmo ../../typing/env.cmo \ - ../../bytecomp/lambda.cmo ../../bytecomp/instruct.cmo \ - ../../bytecomp/cmo_format.cmi ../../bytecomp/opcodes.cmo \ - ../../bytecomp/runtimedef.cmo ../../bytecomp/bytesections.cmo \ - ../../bytecomp/dll.cmo ../../bytecomp/meta.cmo \ - ../../bytecomp/symtable.cmo - -NATOBJS=dynlink.cmx +OBJS=dynlink_compilerlibs.cmo dynlink_types.cmo \ + dynlink_platform_intf.cmo dynlink_common.cmo dynlink.cmo +NATOBJS=dynlink_types.cmx dynlink_platform_intf.cmx \ + dynlink_common.cmx dynlink.cmx + +COMPILEROBJS = $(addprefix $(ROOTDIR)/,\ + utils/config.cmo utils/build_path_prefix_map.cmo utils/misc.cmo \ + utils/identifiable.cmo utils/numbers.cmo utils/arg_helper.cmo \ + utils/clflags.cmo utils/consistbl.cmo \ + utils/terminfo.cmo utils/warnings.cmo utils/load_path.cmo \ + parsing/location.cmo parsing/longident.cmo \ + parsing/docstrings.cmo parsing/syntaxerr.cmo \ + parsing/ast_helper.cmo parsing/ast_mapper.cmo parsing/ast_iterator.cmo \ + parsing/attr_helper.cmo parsing/builtin_attributes.cmo \ + typing/ident.cmo typing/path.cmo typing/primitive.cmo typing/types.cmo \ + typing/btype.cmo typing/subst.cmo typing/predef.cmo \ + typing/datarepr.cmo typing/cmi_format.cmo typing/env.cmo \ + bytecomp/lambda.cmo bytecomp/instruct.cmo \ + bytecomp/opcodes.cmo bytecomp/runtimedef.cmo bytecomp/bytesections.cmo \ + bytecomp/dll.cmo bytecomp/meta.cmo bytecomp/symtable.cmo) + +COMPILERINTFS = $(addprefix $(ROOTDIR)/,\ + bytecomp/cmo_format.cmi) all: dynlink.cma extract_crc allopt: dynlink.cmxa dynlink.cma: $(OBJS) - $(OCAMLC) $(COMPFLAGS) -ccopt "$(NATDYNLINKOPTS)" -a -o dynlink.cma \ - $(OBJS) + $(OCAMLC) $(COMPFLAGS) -ccopt "$(NATDYNLINKOPTS)" -a -o $@ $^ dynlink.cmxa: $(NATOBJS) - $(OCAMLOPT) $(COMPFLAGS) -ccopt "$(NATDYNLINKOPTS)" -a -o dynlink.cmxa \ - $(NATOBJS) - -dynlinkaux.cmo: $(COMPILEROBJS) - $(OCAMLC) $(COMPFLAGS) -pack -o dynlinkaux.cmo $(COMPILEROBJS) - -dynlinkaux.cmi: dynlinkaux.cmo - -dynlink.cmx: dynlink.cmi natdynlink.ml - cp natdynlink.ml dynlink.mlopt + $(OCAMLOPT) $(COMPFLAGS) -ccopt "$(NATDYNLINKOPTS)" -a -o $@ $^ + +dynlink_compilerlibs.cmo: $(COMPILEROBJS) $(COMPILERINTFS) + $(OCAMLC) $(COMPFLAGS) -pack -o $@ $^ + +# This rule is ok since there is no corresponding rule for native code +# compilation (otherwise we would fall foul of the problem in the next +# comment). +dynlink_compilerlibs.cmi: dynlink_compilerlibs.cmo + +# Since there is no .mli for [Dynlink_platform_intf], we need to be +# careful that compilation of the .cmx file does not write the .cmi file again, +# which would cause rebuilding of ocamlopt. The easiest way to do this seems +# to be to copy the .ml file, which is a valid .mli, to the .mli. +dynlink_platform_intf.mli: dynlink_platform_intf.ml + cp $< $@ +dynlink_platform_intf.cmi: dynlink_platform_intf.mli \ + dynlink_types.cmi + $(OCAMLC) $(COMPFLAGS) -c $< + +dynlink_platform_intf.cmo: dynlink_platform_intf.ml \ + dynlink_platform_intf.cmi \ + dynlink_types.cmo + $(OCAMLC) $(COMPFLAGS) -c dynlink_platform_intf.ml + +dynlink_platform_intf.cmx: dynlink_platform_intf.ml \ + dynlink_platform_intf.cmi \ + dynlink_types.cmx + $(OCAMLOPT) $(COMPFLAGS) -c dynlink_platform_intf.ml + +dynlink_types.cmi: dynlink_types.mli + $(OCAMLC) $(COMPFLAGS) -c dynlink_types.mli + +dynlink_types.cmo: dynlink_types.ml dynlink_types.cmi + $(OCAMLC) $(COMPFLAGS) -c dynlink_types.ml + +dynlink_types.cmx: dynlink_types.ml dynlink_types.cmi + $(OCAMLOPT) $(COMPFLAGS) -c dynlink_types.ml + +dynlink_common.cmi: dynlink_common.mli \ + dynlink_platform_intf.cmi \ + dynlink_types.cmi + $(OCAMLC) $(COMPFLAGS) -c dynlink_common.mli + +dynlink_common.cmo: dynlink_common.ml \ + dynlink_common.cmi \ + dynlink_platform_intf.cmo + $(OCAMLC) $(COMPFLAGS) -c dynlink_common.ml + +dynlink_common.cmx: dynlink_common.ml \ + dynlink_common.cmi \ + dynlink_platform_intf.cmx + $(OCAMLOPT) $(COMPFLAGS) -c dynlink_common.ml + +dynlink.cmi: dynlink.mli dynlink_compilerlibs.cmi + $(OCAMLC) -c $(COMPFLAGS) dynlink.mli + +dynlink.cmo: dynlink.cmi dynlink_common.cmi \ + dynlink_types.cmo dynlink_common.cmo dynlink.ml \ + dynlink_compilerlibs.cmo + $(OCAMLC) -c $(COMPFLAGS) -impl dynlink.ml + +dynlink.cmx: dynlink.cmi dynlink_common.cmi \ + dynlink_types.cmx dynlink_common.cmx natdynlink.ml + cp natdynlink.ml dynlink.mlopt $(OCAMLOPT) -c $(COMPFLAGS) -impl dynlink.mlopt rm -f dynlink.mlopt -extract_crc: dynlink.cma extract_crc.cmo - $(OCAMLC) -o extract_crc dynlink.cma extract_crc.cmo +extract_crc.cmo: extract_crc.ml dynlink.cmi + $(OCAMLC) -c $(COMPFLAGS) extract_crc.ml + +extract_crc: $(COMPILEROBJS) dynlink.cma extract_crc.cmo + $(OCAMLC) -o $@ $^ install: $(INSTALL_DATA) \ - dynlink.cmi dynlink.cmti dynlink.cma dynlink.mli \ + dynlink.cmi dynlink.cma \ + "$(INSTALL_LIBDIR)" +ifeq "$(INSTALL_SOURCE_ARTIFACTS)" "true" + $(INSTALL_DATA) \ + dynlink.cmti dynlink.mli \ "$(INSTALL_LIBDIR)" +endif $(INSTALL_PROG) \ extract_crc "$(INSTALL_LIBDIR)/extract_crc$(EXE)" @@ -109,21 +167,7 @@ partialclean: rm -f extract_crc *.cm[ioaxt] *.cmti *.cmxa clean: partialclean - rm -f *.$(A) *.$(O) *.so *.dll dynlink.mlopt - -.SUFFIXES: .ml .mli .cmo .cmi .cmx - -.mli.cmi: - $(OCAMLC) -c $(COMPFLAGS) $< - -.ml.cmo: - $(OCAMLC) -c $(COMPFLAGS) $< - -.ml.cmx: - $(OCAMLOPT) -c $(COMPFLAGS) $(OPTCOMPFLAGS) $< + rm -f *.$(A) *.$(O) *.so *.dll dynlink.mlopt \ + dynlink_platform_intf.mli depend: - -dynlink.cmi: dynlinkaux.cmi -dynlink.cmo: dynlink.cmi dynlinkaux.cmo -extract_crc.cmo: dynlink.cmi diff --git a/otherlibs/dynlink/Makefile.nt b/otherlibs/dynlink/Makefile.nt deleted file mode 100644 index 2fb4e17b..00000000 --- a/otherlibs/dynlink/Makefile.nt +++ /dev/null @@ -1,18 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -# Makefile for the dynamic link library - -include Makefile diff --git a/otherlibs/dynlink/dune b/otherlibs/dynlink/dune new file mode 100644 index 00000000..83b8879c --- /dev/null +++ b/otherlibs/dynlink/dune @@ -0,0 +1,27 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +(library + (name dynlink) + (wrapped false) + (modules dynlink dynlink_compilerlibs dynlink_common dynlink_types + dynlink_platform_intf) + ; the -33 is specific to the hackery done with dune. + (flags (:standard -nostdlib -w -33)) + (libraries ocamlcommon stdlib)) + +(rule + (targets dynlink_compilerlibs.ml) + (action (write-file %{targets} + "(* empty because we are linking with ocamlcommon *)"))) diff --git a/otherlibs/dynlink/dynlink.ml b/otherlibs/dynlink/dynlink.ml index cbb15194..09289db5 100644 --- a/otherlibs/dynlink/dynlink.ml +++ b/otherlibs/dynlink/dynlink.ml @@ -1,12 +1,14 @@ -#2 "otherlibs/dynlink/dynlink.ml" +#3 "otherlibs/dynlink/dynlink.ml" (**************************************************************************) (* *) (* OCaml *) (* *) (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* Mark Shinwell and Leo White, Jane Street Europe *) (* *) (* Copyright 1996 Institut National de Recherche en Informatique et *) (* en Automatique. *) +(* Copyright 2017--2018 Jane Street Group LLC *) (* *) (* All rights reserved. This file is distributed under the terms of *) (* the GNU Lesser General Public License version 2.1, with the *) @@ -14,325 +16,179 @@ (* *) (**************************************************************************) -(* Dynamic loading of .cmo files *) +[@@@ocaml.warning "+a-4-30-40-41-42"] -open Dynlinkaux (* REMOVE_ME for ../../debugger/dynlink.ml *) -open Cmo_format +open! Dynlink_compilerlibs (* REMOVE_ME for ../../debugger/dynlink.ml *) -type linking_error = - Undefined_global of string - | Unavailable_primitive of string - | Uninitialized_global of string - -type error = - Not_a_bytecode_file of string - | Inconsistent_import of string - | Unavailable_unit of string - | Unsafe_file - | Linking_error of string * linking_error - | Corrupted_interface of string - | File_not_found of string - | Cannot_open_dll of string - | Inconsistent_implementation of string - -exception Error of error - -let () = - Printexc.register_printer - (function - | Error err -> - let msg = match err with - | Not_a_bytecode_file s -> - Printf.sprintf "Not_a_bytecode_file %S" s - | Inconsistent_import s -> - Printf.sprintf "Inconsistent_import %S" s - | Unavailable_unit s -> - Printf.sprintf "Unavailable_unit %S" s - | Unsafe_file -> - "Unsafe_file" - | Linking_error (s, Undefined_global s') -> - Printf.sprintf "Linking_error (%S, Dynlink.Undefined_global %S)" - s s' - | Linking_error (s, Unavailable_primitive s') -> - Printf.sprintf "Linking_error (%S, Dynlink.Unavailable_primitive \ - %S)" s s' - | Linking_error (s, Uninitialized_global s') -> - Printf.sprintf "Linking_error (%S, Dynlink.Uninitialized_global \ - %S)" s s' - | Corrupted_interface s -> - Printf.sprintf "Corrupted_interface %S" s - | File_not_found s -> - Printf.sprintf "File_not_found %S" s - | Cannot_open_dll s -> - Printf.sprintf "Cannot_open_dll %S" s - | Inconsistent_implementation s -> - Printf.sprintf "Inconsistent_implementation %S" s in - Some (Printf.sprintf "Dynlink.Error(Dynlink.%s)" msg) - | _ -> None) - -(* Management of interface CRCs *) +module DC = Dynlink_common +module DT = Dynlink_types -let crc_interfaces = ref (Consistbl.create ()) -let allow_extension = ref true +module Bytecode = struct + type filename = string -(* Check that the object file being loaded has been compiled against - the same interfaces as the program itself. In addition, check that - only authorized compilation units are referenced. *) + module Unit_header = struct + type t = Cmo_format.compilation_unit -let check_consistency file_name cu = - try - List.iter - (fun (name, crco) -> - match crco with - None -> () - | Some crc -> - if name = cu.cu_name then - Consistbl.set !crc_interfaces name crc file_name - else if !allow_extension then - Consistbl.check !crc_interfaces name crc file_name - else - Consistbl.check_noadd !crc_interfaces name crc file_name) - cu.cu_imports - with Consistbl.Inconsistency(name, _user, _auth) -> - raise(Error(Inconsistent_import name)) - | Consistbl.Not_available(name) -> - raise(Error(Unavailable_unit name)) + let name (t : t) = t.cu_name + let crc _t = None -(* Empty the crc_interfaces table *) + let interface_imports (t : t) = t.cu_imports + let implementation_imports (t : t) = + let required = + t.cu_required_globals + @ Symtable.required_globals t.cu_reloc + in + let required = + List.filter (fun id -> not (Ident.is_predef id)) required + in + List.map + (fun ident -> Ident.name ident, None) + required -let clear_available_units () = - Consistbl.clear !crc_interfaces; - allow_extension := false + let defined_symbols (t : t) = + List.map (fun ident -> Ident.name ident) + (Symtable.defined_globals t.cu_reloc) -(* Allow only access to the units with the given names *) - -let allow_only names = - Consistbl.filter (fun name -> List.mem name names) !crc_interfaces; - allow_extension := false - -(* Prohibit access to the units with the given names *) - -let prohibit names = - Consistbl.filter (fun name -> not (List.mem name names)) !crc_interfaces; - allow_extension := false - -(* Initialize the crc_interfaces table with a list of units with fixed CRCs *) - -let add_available_units units = - List.iter - (fun (unit, crc) -> Consistbl.set !crc_interfaces unit crc "") - units - -(* Default interface CRCs: those found in the current executable *) -let default_crcs = ref [] - -let default_available_units () = - clear_available_units(); - List.iter - (fun (unit, crco) -> - match crco with - None -> () - | Some crc -> Consistbl.set !crc_interfaces unit crc "") - !default_crcs; - allow_extension := true - -(* Initialize the linker tables and everything *) - -let inited = ref false - -let init () = - if not !inited then begin - if !Sys.interactive then (* PR#6802 *) - invalid_arg "The dynlink.cma library cannot be used \ - inside the OCaml toplevel"; - default_crcs := Symtable.init_toplevel(); - default_available_units (); - inited := true; + let unsafe_module (t : t) = t.cu_primitives <> [] end -let clear_available_units () = init(); clear_available_units () -let allow_only l = init(); allow_only l -let prohibit l = init(); prohibit l -let add_available_units l = init(); add_available_units l -let default_available_units () = init(); default_available_units () + type handle = Stdlib.in_channel * filename * Digest.t -(* Read the CRC of an interface from its .cmi file *) + let default_crcs = ref [] + let default_global_map = ref Symtable.empty_global_map -let digest_interface unit loadpath = - let filename = - let shortname = unit ^ ".cmi" in + let init () = + if !Sys.interactive then begin (* PR#6802 *) + invalid_arg "The dynlink.cma library cannot be used \ + inside the OCaml toplevel" + end; + default_crcs := Symtable.init_toplevel (); + default_global_map := Symtable.current_state () + + let is_native = false + let adapt_filename f = f + + let num_globals_inited () = + Misc.fatal_error "Should never be called for bytecode dynlink" + + let fold_initial_units ~init ~f = + List.fold_left (fun acc (comp_unit, interface) -> + let id = Ident.create_persistent comp_unit in + let defined = + Symtable.is_defined_in_global_map !default_global_map id + in + let implementation = + if defined then Some (None, DT.Loaded) + else None + in + let defined_symbols = + if defined then [comp_unit] + else [] + in + f acc ~comp_unit ~interface ~implementation ~defined_symbols) + init + !default_crcs + + let run_shared_startup _ = () + + let run (ic, file_name, file_digest) ~unit_header ~priv = + let open Misc in + let old_state = Symtable.current_state () in + let compunit : Cmo_format.compilation_unit = unit_header in + seek_in ic compunit.cu_pos; + let code_size = compunit.cu_codesize + 8 in + let code = LongString.create code_size in + LongString.input_bytes_into code ic compunit.cu_codesize; + LongString.set code compunit.cu_codesize (Char.chr Opcodes.opRETURN); + LongString.blit_string "\000\000\000\001\000\000\000" 0 + code (compunit.cu_codesize + 1) 7; + begin try + Symtable.patch_object code compunit.cu_reloc; + Symtable.check_global_initialized compunit.cu_reloc; + Symtable.update_global_table () + with Symtable.Error error -> + let new_error : DT.linking_error = + match error with + | Symtable.Undefined_global s -> Undefined_global s + | Symtable.Unavailable_primitive s -> Unavailable_primitive s + | Symtable.Uninitialized_global s -> Uninitialized_global s + | Symtable.Wrong_vm _ -> assert false + in + raise (DT.Error (Linking_error (file_name, new_error))) + end; + (* PR#5215: identify this code fragment by + digest of file contents + unit name. + Unit name is needed for .cma files, which produce several code + fragments. *) + let digest = Digest.string (file_digest ^ compunit.cu_name) in + let events = + if compunit.cu_debug = 0 then [| |] + else begin + seek_in ic compunit.cu_debug; + [| input_value ic |] + end in + if priv then Symtable.hide_additions old_state; + let _, clos = Meta.reify_bytecode code events (Some digest) in + try ignore ((clos ()) : Obj.t) + with exn -> raise (DT.Error (Library's_module_initializers_failed exn)) + + let load ~filename:file_name ~priv:_ = + let ic = open_in_bin file_name in + let file_digest = Digest.channel ic (-1) in + seek_in ic 0; try - Misc.find_in_path_uncap loadpath shortname - with Not_found -> - raise (Error(File_not_found shortname)) in - let ic = open_in_bin filename in - try - let buffer = - really_input_string ic (String.length Config.cmi_magic_number) - in - if buffer <> Config.cmi_magic_number then begin + let buffer = + try really_input_string ic (String.length Config.cmo_magic_number) + with End_of_file -> raise (DT.Error (Not_a_bytecode_file file_name)) + in + let handle = ic, file_name, file_digest in + if buffer = Config.cmo_magic_number then begin + let compunit_pos = input_binary_int ic in (* Go to descriptor *) + seek_in ic compunit_pos; + let cu = (input_value ic : Cmo_format.compilation_unit) in + handle, [cu] + end else + if buffer = Config.cma_magic_number then begin + let toc_pos = input_binary_int ic in (* Go to table of contents *) + seek_in ic toc_pos; + let lib = (input_value ic : Cmo_format.library) in + begin try + Dll.open_dlls Dll.For_execution + (List.map Dll.extract_dll_name lib.lib_dllibs) + with exn -> + raise (DT.Error (Cannot_open_dynamic_library exn)) + end; + handle, lib.lib_units + end else begin + raise (DT.Error (Not_a_bytecode_file file_name)) + end + with exc -> close_in ic; - raise(Error(Corrupted_interface filename)) - end; - let cmi = Cmi_format.input_cmi ic in - close_in ic; - let crc = - match cmi.Cmi_format.cmi_crcs with - (_, Some crc) :: _ -> crc - | _ -> raise(Error(Corrupted_interface filename)) - in - crc - with End_of_file | Failure _ -> - close_in ic; - raise(Error(Corrupted_interface filename)) - -(* Initialize the crc_interfaces table with a list of units. - Their CRCs are read from their interfaces. *) - -let add_interfaces units loadpath = - add_available_units - (List.map (fun unit -> (unit, digest_interface unit loadpath)) units) - -(* Check whether the object file being loaded was compiled in unsafe mode *) - -let unsafe_allowed = ref false - -let allow_unsafe_modules b = - unsafe_allowed := b - -let check_unsafe_module cu = - if (not !unsafe_allowed) && cu.cu_primitives <> [] - then raise(Error(Unsafe_file)) - -(* Load in-core and execute a bytecode object file *) + raise exc -external register_code_fragment: bytes -> int -> string -> unit - = "caml_register_code_fragment" - -let load_compunit ic file_name file_digest compunit = - check_consistency file_name compunit; - check_unsafe_module compunit; - seek_in ic compunit.cu_pos; - let code_size = compunit.cu_codesize + 8 in - let code = Meta.static_alloc code_size in - unsafe_really_input ic code 0 compunit.cu_codesize; - Bytes.unsafe_set code compunit.cu_codesize (Char.chr Opcodes.opRETURN); - Bytes.unsafe_set code (compunit.cu_codesize + 1) '\000'; - Bytes.unsafe_set code (compunit.cu_codesize + 2) '\000'; - Bytes.unsafe_set code (compunit.cu_codesize + 3) '\000'; - Bytes.unsafe_set code (compunit.cu_codesize + 4) '\001'; - Bytes.unsafe_set code (compunit.cu_codesize + 5) '\000'; - Bytes.unsafe_set code (compunit.cu_codesize + 6) '\000'; - Bytes.unsafe_set code (compunit.cu_codesize + 7) '\000'; - let initial_symtable = Symtable.current_state() in - begin try - Symtable.patch_object code compunit.cu_reloc; - Symtable.check_global_initialized compunit.cu_reloc; - Symtable.update_global_table() - with Symtable.Error error -> - let new_error = - match error with - Symtable.Undefined_global s -> Undefined_global s - | Symtable.Unavailable_primitive s -> Unavailable_primitive s - | Symtable.Uninitialized_global s -> Uninitialized_global s - | _ -> assert false in - raise(Error(Linking_error (file_name, new_error))) - end; - (* PR#5215: identify this code fragment by - digest of file contents + unit name. - Unit name is needed for .cma files, which produce several code fragments.*) - let digest = Digest.string (file_digest ^ compunit.cu_name) in - register_code_fragment code code_size digest; - let events = - if compunit.cu_debug = 0 then [| |] - else begin - seek_in ic compunit.cu_debug; - [| input_value ic |] - end in - Meta.add_debug_info code code_size events; - begin try - ignore((Meta.reify_bytecode code code_size) ()) - with exn -> - Symtable.restore_state initial_symtable; - raise exn - end - -let loadfile file_name = - init(); - if not (Sys.file_exists file_name) - then raise (Error (File_not_found file_name)); - let ic = open_in_bin file_name in - let file_digest = Digest.channel ic (-1) in - seek_in ic 0; - try - let buffer = - try really_input_string ic (String.length Config.cmo_magic_number) - with End_of_file -> raise (Error (Not_a_bytecode_file file_name)) - in - if buffer = Config.cmo_magic_number then begin - let compunit_pos = input_binary_int ic in (* Go to descriptor *) - seek_in ic compunit_pos; - let cu = (input_value ic : compilation_unit) in - load_compunit ic file_name file_digest cu - end else - if buffer = Config.cma_magic_number then begin - let toc_pos = input_binary_int ic in (* Go to table of contents *) - seek_in ic toc_pos; - let lib = (input_value ic : library) in - begin try - Dll.open_dlls Dll.For_execution - (List.map Dll.extract_dll_name lib.lib_dllibs) - with Failure reason -> - raise(Error(Cannot_open_dll reason)) - end; - List.iter (load_compunit ic file_name file_digest) lib.lib_units - end else - raise(Error(Not_a_bytecode_file file_name)); + let finish (ic, _filename, _digest) = close_in ic - with exc -> - close_in ic; raise exc +end -let loadfile_private file_name = - init(); - let initial_symtable = Symtable.current_state() - and initial_crc = !crc_interfaces in - try - loadfile file_name; - Symtable.hide_additions initial_symtable; - crc_interfaces := initial_crc - with exn -> - Symtable.hide_additions initial_symtable; - crc_interfaces := initial_crc; - raise exn +include DC.Make (Bytecode) -(* Error report *) +type linking_error = DT.linking_error = + | Undefined_global of string + | Unavailable_primitive of string + | Uninitialized_global of string -let error_message = function - Not_a_bytecode_file name -> - name ^ " is not a bytecode object file" - | Inconsistent_import name -> - "interface mismatch on " ^ name - | Unavailable_unit name -> - "no implementation available for " ^ name - | Unsafe_file -> - "this object file uses unsafe features" - | Linking_error (name, Undefined_global s) -> - "error while linking " ^ name ^ ".\n" ^ - "Reference to undefined global `" ^ s ^ "'" - | Linking_error (name, Unavailable_primitive s) -> - "error while linking " ^ name ^ ".\n" ^ - "The external function `" ^ s ^ "' is not available" - | Linking_error (name, Uninitialized_global s) -> - "error while linking " ^ name ^ ".\n" ^ - "The module `" ^ s ^ "' is not yet initialized" - | Corrupted_interface name -> - "corrupted interface file " ^ name - | File_not_found name -> - "cannot find file " ^ name ^ " in search path" - | Cannot_open_dll reason -> - "error loading shared library: " ^ reason - | Inconsistent_implementation name -> - "implementation mismatch on " ^ name +type error = DT.error = + | Not_a_bytecode_file of string + | Inconsistent_import of string + | Unavailable_unit of string + | Unsafe_file + | Linking_error of string * linking_error + | Corrupted_interface of string + | Cannot_open_dynamic_library of exn + | Library's_module_initializers_failed of exn + | Inconsistent_implementation of string + | Module_already_loaded of string + | Private_library_cannot_implement_interface of string -let is_native = false -let adapt_filename f = f +exception Error = DT.Error +let error_message = DT.error_message diff --git a/otherlibs/dynlink/dynlink.mli b/otherlibs/dynlink/dynlink.mli index fabbe6d3..3b81e752 100644 --- a/otherlibs/dynlink/dynlink.mli +++ b/otherlibs/dynlink/dynlink.mli @@ -3,9 +3,11 @@ (* OCaml *) (* *) (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* Mark Shinwell and Leo White, Jane Street Europe *) (* *) (* Copyright 1996 Institut National de Recherche en Informatique et *) (* en Automatique. *) +(* Copyright 2017--2018 Jane Street Group LLC *) (* *) (* All rights reserved. This file is distributed under the terms of *) (* the GNU Lesser General Public License version 2.1, with the *) @@ -13,9 +15,11 @@ (* *) (**************************************************************************) -(** Dynamic loading of object files. *) +(** Dynamic loading of .cmo, .cma and .cmxs files. *) -val is_native: bool +[@@@ocaml.warning "+a-4-30-40-41-42"] + +val is_native : bool (** [true] if the program is native, [false] if the program is bytecode. *) @@ -25,18 +29,44 @@ val loadfile : string -> unit (** In bytecode: load the given bytecode object file ([.cmo] file) or bytecode library file ([.cma] file), and link it with the running program. In native code: load the given OCaml plugin file (usually - [.cmxs]), and link it with the running - program. + [.cmxs]), and link it with the running program. + All toplevel expressions in the loaded compilation units are evaluated. No facilities are provided to access value names defined by the unit. Therefore, the unit - must register itself its entry points with the main program, - e.g. by modifying tables of functions. *) + must itself register its entry points with the main program (or a + previously-loaded library) e.g. by modifying tables of functions. + + An exception will be raised if the given library defines toplevel + modules whose names clash with modules existing either in the main + program or a shared library previously loaded with [loadfile]. + Modules from shared libraries previously loaded with + [loadfile_private] are not included in this restriction. + + The compilation units loaded by this function are added to the + "allowed units" list (see {!set_allowed_units}). *) val loadfile_private : string -> unit (** Same as [loadfile], except that the compilation units just loaded are hidden (cannot be referenced) from other modules dynamically - loaded afterwards. *) + loaded afterwards. + + An exception will be raised if the given library defines toplevel + modules whose names clash with modules existing in either the main + program or a shared library previously loaded with [loadfile]. + Modules from shared libraries previously loaded with + [loadfile_private] are not included in this restriction. + + An exception will also be raised if the given library defines + toplevel modules whose name matches that of an interface depended + on by a module existing in either the main program or a shared + library previously loaded with [loadfile]. This applies even if + such dependency is only a "module alias" dependency (i.e. just on + the name rather than the contents of the interface). + + The compilation units loaded by this function are not added to the + "allowed units" list (see {!set_allowed_units}) since they cannot + be referenced from other compilation units. *) val adapt_filename : string -> string (** In bytecode, the identity function. In native code, replace the last @@ -44,34 +74,43 @@ val adapt_filename : string -> string (** {1 Access control} *) -val allow_only: string list -> unit -(** [allow_only units] restricts the compilation units that - dynamically-linked units can reference: it forbids all references - to units other than those named in the list [units]. References - to any other compilation unit will cause a [Unavailable_unit] - error during [loadfile] or [loadfile_private]. - - Initially (or after calling [default_available_units]) all - compilation units composing the program currently running are - available for reference from dynamically-linked units. - [allow_only] can be used to restrict access to a subset of these +val set_allowed_units : string list -> unit +(** Set the list of compilation units that may be referenced from units that + are dynamically loaded in the future to be exactly the given value. + + Initially all compilation units composing the program currently running + are available for reference from dynamically-linked units. + [set_allowed_units] can be used to restrict access to a subset of these units, e.g. to the units that compose the API for dynamically-linked code, and prevent access to all other units, - e.g. private, internal modules of the running program. If - [allow_only] is called several times, access will be restricted to - the intersection of the given lists (i.e. a call to [allow_only] - can never increase the set of available units). *) + e.g. private, internal modules of the running program. + + Note that {!loadfile} changes the allowed-units list. *) -val prohibit: string list -> unit +val allow_only: string list -> unit +(** [allow_only units] sets the list of allowed units to be the intersection + of the existing allowed units and the given list of units. As such it + can never increase the set of allowed units. *) + +val prohibit : string list -> unit (** [prohibit units] prohibits dynamically-linked units from referencing - the units named in list [units]. This can be used to prevent - access to selected units, e.g. private, internal modules of - the running program. *) + the units named in list [units] by removing such units from the allowed + units list. This can be used to prevent access to selected units, + e.g. private, internal modules of the running program. *) + +val main_program_units : unit -> string list +(** Return the list of compilation units that form the main program (i.e. + are not dynamically linked). *) -val default_available_units: unit -> unit -(** Reset the set of units that can be referenced from dynamically-linked - code to its default value, that is, all units composing the currently - running program. *) +val public_dynamically_loaded_units : unit -> string list +(** Return the list of compilation units that have been dynamically loaded via + [loadfile] (and not via [loadfile_private]). Note that compilation units + loaded dynamically cannot be unloaded. *) + +val all_units : unit -> string list +(** Return the list of compilation units that form the main program together + with those that have been dynamically loaded via [loadfile] (and not via + [loadfile_private]). *) val allow_unsafe_modules : bool -> unit (** Govern whether unsafe object files are allowed to be @@ -81,68 +120,32 @@ val allow_unsafe_modules : bool -> unit not allowed. In native code, this function does nothing; object files with external functions are always allowed to be dynamically linked. *) -(** {1 Deprecated, low-level API for access control} *) - -(** @deprecated The functions [add_interfaces], [add_available_units] - and [clear_available_units] should not be used in new programs, - since the default initialization of allowed units, along with the - [allow_only] and [prohibit] function, provides a better, safer - mechanism to control access to program units. The three functions - below are provided for backward compatibility only and are not - available in native code. *) - -val add_interfaces : string list -> string list -> unit -(** [add_interfaces units path] grants dynamically-linked object - files access to the compilation units named in list [units]. - The interfaces ([.cmi] files) for these units are searched in - [path] (a list of directory names). *) - -val add_available_units : (string * Digest.t) list -> unit -(** Same as {!Dynlink.add_interfaces}, but instead of searching [.cmi] files - to find the unit interfaces, uses the interface digests given - for each unit. This way, the [.cmi] interface files need not be - available at run-time. The digests can be extracted from [.cmi] - files using the [extract_crc] program installed in the - OCaml standard library directory. *) - -val clear_available_units : unit -> unit -(** Empty the list of compilation units accessible to dynamically-linked - programs. *) - -(** {1 Deprecated, initialization} *) - -val init : unit -> unit -(** @deprecated Initialize the [Dynlink] library. This function is called - automatically when needed. *) - (** {1 Error reporting} *) -type linking_error = - Undefined_global of string +type linking_error = private + | Undefined_global of string | Unavailable_primitive of string | Uninitialized_global of string -type error = - Not_a_bytecode_file of string +type error = private + | Not_a_bytecode_file of string | Inconsistent_import of string | Unavailable_unit of string | Unsafe_file | Linking_error of string * linking_error | Corrupted_interface of string - | File_not_found of string - | Cannot_open_dll of string + | Cannot_open_dynamic_library of exn + | Library's_module_initializers_failed of exn | Inconsistent_implementation of string + | Module_already_loaded of string + | Private_library_cannot_implement_interface of string exception Error of error (** Errors in dynamic linking are reported by raising the [Error] - exception with a description of the error. *) + exception with a description of the error. + A common case is the dynamic library not being found on the system: this + is reported via [Cannot_open_dynamic_library] (the enclosed exception may + be platform-specific). *) val error_message : error -> string (** Convert an error description to a printable message. *) - - -(**/**) - -(** {1 Internal functions} *) - -val digest_interface : string -> string list -> Digest.t diff --git a/otherlibs/dynlink/dynlink_common.ml b/otherlibs/dynlink/dynlink_common.ml new file mode 100644 index 00000000..4ce7c63a --- /dev/null +++ b/otherlibs/dynlink/dynlink_common.ml @@ -0,0 +1,360 @@ +#2 "otherlibs/dynlink/dynlink_common.ml" +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* Copyright 2017--2018 Jane Street Group LLC *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-30-40-41-42"] + +(* This compilation unit cannot depend on compilerlibs. *) +module String = struct + include String + + module Set = Set.Make (String) + + module Map = struct + include Map.Make (String) + + let keys t = + fold (fun key _data keys -> Set.add key keys) t Set.empty + end +end + +module Make (P : Dynlink_platform_intf.S) = struct + module DT = Dynlink_types + module UH = P.Unit_header + + type interface_dep = + | Name (* the only use of the interface can be via a module alias *) + | Contents of Digest.t + + type implem = Digest.t option * DT.filename * DT.implem_state + + module State = struct + type t = { + ifaces : (interface_dep * DT.filename) String.Map.t; + (* Interfaces that have been depended upon. *) + implems : implem String.Map.t; + (* Implementations that exist in the main program or have been + dynamically loaded. *) + defined_symbols : String.Set.t; + (* Symbols corresponding to compilation units or packed modules (cf. + [Asmpackager.build_package_cmx]). Used as a sanity check. *) + allowed_units : String.Set.t; + (* Units that are allowed to be referenced by a subsequently-loaded + dynamic library. *) + main_program_units : String.Set.t; + (* Units forming part of the main program (i.e. not dynamically + linked). *) + public_dynamically_loaded_units : String.Set.t; + (* All units that have been dynamically linked, not including those that + were privately loaded. *) + } + + let invariant t = + let ifaces = String.Map.keys t.ifaces in + let implems = String.Map.keys t.implems in + assert (String.Set.subset implems ifaces); + assert (String.Set.subset t.main_program_units ifaces); + assert (String.Set.subset t.main_program_units implems); + assert (String.Set.subset t.public_dynamically_loaded_units ifaces); + assert (String.Set.subset t.public_dynamically_loaded_units implems) + + let empty = { + ifaces = String.Map.empty; + implems = String.Map.empty; + defined_symbols = String.Set.empty; + allowed_units = String.Set.empty; + main_program_units = String.Set.empty; + public_dynamically_loaded_units = String.Set.empty; + } + end + + let global_state = ref State.empty + + let inited = ref false + + let unsafe_allowed = ref false + + let allow_unsafe_modules b = + unsafe_allowed := b + + let check_symbols_disjoint ~descr syms1 syms2 = + let exe = Sys.executable_name in + let overlap = String.Set.inter syms1 syms2 in + if not (String.Set.is_empty overlap) then begin + let msg = + Format.asprintf "%s: symbols multiply-defined %s: %a" + exe (Lazy.force descr) + (Format.pp_print_list ~pp_sep:(fun ppf () -> Format.fprintf ppf ", ") + Format.pp_print_string) + (String.Set.elements overlap) + in + failwith msg + end + + let default_available_units () = + let exe = Sys.executable_name in + let ifaces, implems, defined_symbols = + P.fold_initial_units + ~init:(String.Map.empty, String.Map.empty, String.Set.empty) + ~f:(fun (ifaces, implems, defined_symbols) + ~comp_unit ~interface ~implementation + ~defined_symbols:defined_symbols_this_unit -> + let ifaces = + match interface with + | None -> String.Map.add comp_unit (Name, exe) ifaces + | Some crc -> String.Map.add comp_unit (Contents crc, exe) ifaces + in + let implems = + match implementation with + | None -> implems + | Some (crc, state) -> + String.Map.add comp_unit (crc, exe, state) implems + in + let defined_symbols_this_unit = + String.Set.of_list defined_symbols_this_unit + in + check_symbols_disjoint ~descr:(lazy "in the executable file") + defined_symbols_this_unit defined_symbols; + let defined_symbols = + String.Set.union defined_symbols_this_unit defined_symbols + in + ifaces, implems, defined_symbols) + in + let main_program_units = String.Map.keys implems in + let state : State.t = + { ifaces; + implems; + defined_symbols; + allowed_units = main_program_units; + main_program_units; + public_dynamically_loaded_units = String.Set.empty; + } + in + global_state := state + + let init () = + if not !inited then begin + P.init (); + default_available_units (); + inited := true + end + + let set_loaded_implem filename ui implems = + String.Map.add (UH.name ui) (UH.crc ui, filename, DT.Loaded) implems + + let set_loaded filename ui (state : State.t) = + { state with implems = set_loaded_implem filename ui state.implems } + + let check_interface_imports filename ui ifaces = + List.fold_left (fun ifaces (name, crc) -> + match String.Map.find name ifaces with + | exception Not_found -> begin + match crc with + | None -> String.Map.add name (Name, filename) ifaces + | Some crc -> String.Map.add name (Contents crc, filename) ifaces + end + | old_crc, _old_src -> + match old_crc, crc with + | (Name | Contents _), None -> ifaces + | Name, Some crc -> + String.Map.add name (Contents crc, filename) ifaces + | Contents old_crc, Some crc -> + if old_crc <> crc then raise (DT.Error (Inconsistent_import name)) + else ifaces) + ifaces + (UH.interface_imports ui) + + let check_implementation_imports ~allowed_units filename ui implems = + List.iter (fun (name, crc) -> + if not (String.Set.mem name allowed_units) then begin + raise (DT.Error (Unavailable_unit name)) + end; + match String.Map.find name implems with + | exception Not_found -> raise (DT.Error (Unavailable_unit name)) + | ((old_crc, _old_src, unit_state) : implem) -> + begin match old_crc, crc with + | (None | Some _), None -> () + | None, Some _crc -> + (* The [None] behaves like a CRC different from every other. *) + raise (DT.Error (Inconsistent_implementation name)) + | Some old_crc, Some crc -> + if old_crc <> crc then begin + raise (DT.Error (Inconsistent_implementation name)) + end + end; + match unit_state with + | Not_initialized -> + raise (DT.Error (Linking_error ( + filename, Uninitialized_global name))) + | Check_inited i -> + if P.num_globals_inited () < i then begin + raise (DT.Error (Linking_error ( + filename, Uninitialized_global name))) + end + | Loaded -> ()) + (UH.implementation_imports ui) + + let check_name filename ui priv ifaces implems = + let name = UH.name ui in + if String.Map.mem name implems then begin + raise (DT.Error (Module_already_loaded name)) + end; + if priv && String.Map.mem name ifaces then begin + raise (DT.Error (Private_library_cannot_implement_interface name)) + end; + String.Map.add name (UH.crc ui, filename, DT.Not_initialized) implems + + let check_unsafe_module ui = + if (not !unsafe_allowed) && UH.unsafe_module ui then begin + raise (DT.Error Unsafe_file) + end + + let check filename (units : UH.t list) (state : State.t) ~priv = + List.iter (fun ui -> check_unsafe_module ui) units; + let new_units = + String.Set.of_list (List.map (fun ui -> UH.name ui) units) + in + let implems = + List.fold_left (fun implems ui -> + check_name filename ui priv state.ifaces implems) + state.implems units + in + let ifaces = + List.fold_left (fun ifaces ui -> + check_interface_imports filename ui ifaces) + state.ifaces units + in + let allowed_units = String.Set.union state.allowed_units new_units in + let (_ : implem String.Map.t) = + List.fold_left + (fun acc ui -> + check_implementation_imports ~allowed_units filename ui acc; + set_loaded_implem filename ui acc) + implems units + in + let defined_symbols = + List.fold_left (fun defined_symbols ui -> + let descr = + lazy (Printf.sprintf "between the executable file (and any \ + existing dynamically-loaded units) and the unit `%s' being \ + dynamically loaded from %s" + (UH.name ui) + filename) + in + let symbols = String.Set.of_list (UH.defined_symbols ui) in + check_symbols_disjoint ~descr symbols defined_symbols; + String.Set.union symbols defined_symbols) + state.defined_symbols + units + in + if priv then begin + state + end else begin + let public_dynamically_loaded_units = + String.Set.union state.public_dynamically_loaded_units new_units + in + let state = + { state with + implems; + ifaces; + defined_symbols; + allowed_units; + public_dynamically_loaded_units; + } + in + State.invariant state; + state + end + + let set_allowed_units allowed_units = + let allowed_units = String.Set.of_list allowed_units in + let state = + let state = !global_state in + { state with + allowed_units; + } + in + global_state := state + + let allow_only units = + let allowed_units = + String.Set.inter (!global_state).allowed_units + (String.Set.of_list units) + in + let state = + let state = !global_state in + { state with + allowed_units; + } + in + global_state := state + + let prohibit units = + let allowed_units = + String.Set.diff (!global_state).allowed_units + (String.Set.of_list units) + in + let state = + let state = !global_state in + { state with + allowed_units; + } + in + global_state := state + + let main_program_units () = + String.Set.elements (!global_state).main_program_units + + let public_dynamically_loaded_units () = + String.Set.elements (!global_state).public_dynamically_loaded_units + + let all_units () = + String.Set.elements (String.Set.union + (!global_state).main_program_units + (!global_state).public_dynamically_loaded_units) + + let dll_filename fname = + if Filename.is_implicit fname then Filename.concat (Sys.getcwd ()) fname + else fname + + let load priv filename = + init (); + let filename = dll_filename filename in + match P.load ~filename ~priv with + | exception exn -> raise (DT.Error (Cannot_open_dynamic_library exn)) + | handle, units -> + try + global_state := check filename units !global_state ~priv; + P.run_shared_startup handle; + List.iter + (fun unit_header -> + P.run handle ~unit_header ~priv; + if not priv then begin + global_state := set_loaded filename unit_header !global_state + end) + units; + P.finish handle + with exn -> + P.finish handle; + raise exn + + let loadfile filename = load false filename + let loadfile_private filename = load true filename + + let is_native = P.is_native + let adapt_filename = P.adapt_filename +end diff --git a/otherlibs/dynlink/dynlink_common.mli b/otherlibs/dynlink/dynlink_common.mli new file mode 100644 index 00000000..a4c001ea --- /dev/null +++ b/otherlibs/dynlink/dynlink_common.mli @@ -0,0 +1,34 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* Copyright 2017--2018 Jane Street Group LLC *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-30-40-41-42"] + +(** Construction of dynlink functionality given the platform-specific code. *) + +module Make (P : Dynlink_platform_intf.S) : sig + val is_native : bool + val loadfile : string -> unit + val loadfile_private : string -> unit + val adapt_filename : string -> string + val set_allowed_units : string list -> unit + val allow_only: string list -> unit + val prohibit : string list -> unit + val main_program_units : unit -> string list + val public_dynamically_loaded_units : unit -> string list + val all_units : unit -> string list + val allow_unsafe_modules : bool -> unit +end diff --git a/otherlibs/dynlink/dynlink_platform_intf.ml b/otherlibs/dynlink/dynlink_platform_intf.ml new file mode 100644 index 00000000..900f595c --- /dev/null +++ b/otherlibs/dynlink/dynlink_platform_intf.ml @@ -0,0 +1,67 @@ +#2 "otherlibs/dynlink/dynlink_platform_intf.ml" +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* Copyright 2017--2018 Jane Street Group LLC *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** Interface for platform-specific dynlink providers. + Note that this file needs to be a valid .mli file. *) + +[@@@ocaml.warning "+a-4-30-40-41-42"] + +module type S = sig + type handle + + module Unit_header : sig + type t + + val name : t -> string + val crc : t -> Digest.t option + + val interface_imports : t -> (string * Digest.t option) list + val implementation_imports : t -> (string * Digest.t option) list + + val defined_symbols : t -> string list + val unsafe_module : t -> bool + end + + val init : unit -> unit + + val is_native : bool + + val adapt_filename : Dynlink_types.filename -> Dynlink_types.filename + + val num_globals_inited : unit -> int + + val fold_initial_units + : init:'a + -> f:('a + -> comp_unit:string + -> interface:Digest.t option + -> implementation:(Digest.t option * Dynlink_types.implem_state) option + -> defined_symbols:string list + -> 'a) + -> 'a + + val load + : filename:Dynlink_types.filename + -> priv:bool + -> handle * (Unit_header.t list) + + val run_shared_startup : handle -> unit + val run : handle -> unit_header:Unit_header.t -> priv:bool -> unit + + val finish : handle -> unit +end diff --git a/otherlibs/dynlink/dynlink_types.ml b/otherlibs/dynlink/dynlink_types.ml new file mode 100644 index 00000000..ebfd2d1c --- /dev/null +++ b/otherlibs/dynlink/dynlink_types.ml @@ -0,0 +1,116 @@ +#2 "otherlibs/dynlink/dynlink_types.ml" +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* Copyright 2017--2018 Jane Street Group LLC *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** Types shared amongst the various parts of the dynlink code. *) + +[@@@ocaml.warning "+a-4-30-40-41-42"] + +type implem_state = + | Loaded + | Not_initialized + | Check_inited of int + +type filename = string + +type linking_error = + | Undefined_global of string + | Unavailable_primitive of string + | Uninitialized_global of string + +type error = + | Not_a_bytecode_file of string + | Inconsistent_import of string + | Unavailable_unit of string + | Unsafe_file + | Linking_error of string * linking_error + | Corrupted_interface of string + | Cannot_open_dynamic_library of exn + | Library's_module_initializers_failed of exn + | Inconsistent_implementation of string + | Module_already_loaded of string + | Private_library_cannot_implement_interface of string + +exception Error of error + +let error_message = function + | Not_a_bytecode_file name -> + name ^ " is not an object file" + | Inconsistent_import name -> + "interface mismatch on " ^ name + | Unavailable_unit name -> + "no implementation available for " ^ name + | Unsafe_file -> + "this object file uses unsafe features" + | Linking_error (name, Undefined_global s) -> + "error while linking " ^ name ^ ".\n" ^ + "Reference to undefined global `" ^ s ^ "'" + | Linking_error (name, Unavailable_primitive s) -> + "error while linking " ^ name ^ ".\n" ^ + "The external function `" ^ s ^ "' is not available" + | Linking_error (name, Uninitialized_global s) -> + "error while linking " ^ name ^ ".\n" ^ + "The module `" ^ s ^ "' is not yet initialized" + | Corrupted_interface name -> + "corrupted interface file " ^ name + | Cannot_open_dynamic_library exn -> + "error loading shared library: " ^ (Printexc.to_string exn) + | Inconsistent_implementation name -> + "implementation mismatch on " ^ name + | Library's_module_initializers_failed exn -> + "execution of module initializers in the shared library failed: " + ^ (Printexc.to_string exn) + | Module_already_loaded name -> + "The module `" ^ name ^ "' is already loaded \ + (either by the main program or a previously-dynlinked library)" + | Private_library_cannot_implement_interface name -> + "The interface `" ^ name ^ "' cannot be implemented by a \ + library loaded privately" + +let () = + Printexc.register_printer (function + | Error err -> + let msg = match err with + | Not_a_bytecode_file s -> Printf.sprintf "Not_a_bytecode_file %S" s + | Inconsistent_import s -> Printf.sprintf "Inconsistent_import %S" s + | Unavailable_unit s -> Printf.sprintf "Unavailable_unit %S" s + | Unsafe_file -> "Unsafe_file" + | Linking_error (s, Undefined_global s') -> + Printf.sprintf "Linking_error (%S, Dynlink.Undefined_global %S)" + s s' + | Linking_error (s, Unavailable_primitive s') -> + Printf.sprintf "Linking_error (%S, Dynlink.Unavailable_primitive %S)" + s s' + | Linking_error (s, Uninitialized_global s') -> + Printf.sprintf "Linking_error (%S, Dynlink.Uninitialized_global %S)" + s s' + | Corrupted_interface s -> + Printf.sprintf "Corrupted_interface %S" s + | Cannot_open_dynamic_library exn -> + Printf.sprintf "Cannot_open_dll %S" (Printexc.to_string exn) + | Inconsistent_implementation s -> + Printf.sprintf "Inconsistent_implementation %S" s + | Library's_module_initializers_failed exn -> + Printf.sprintf "Library's_module_initializers_failed %S" + (Printexc.to_string exn) + | Module_already_loaded name -> + Printf.sprintf "Module_already_loaded %S" name + | Private_library_cannot_implement_interface name -> + Printf.sprintf "Private_library_cannot_implement_interface %S" name + in + Some (Printf.sprintf "Dynlink.Error (Dynlink.%s)" msg) + | _ -> None) diff --git a/otherlibs/dynlink/dynlink_types.mli b/otherlibs/dynlink/dynlink_types.mli new file mode 100644 index 00000000..6adf9b89 --- /dev/null +++ b/otherlibs/dynlink/dynlink_types.mli @@ -0,0 +1,49 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* Copyright 2017--2018 Jane Street Group LLC *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** Types shared amongst the various parts of the dynlink code. *) + +[@@@ocaml.warning "+a-4-30-40-41-42"] + +type implem_state = + | Loaded + | Not_initialized + | Check_inited of int + +type filename = string + +type linking_error = + | Undefined_global of string + | Unavailable_primitive of string + | Uninitialized_global of string + +type error = + | Not_a_bytecode_file of string + | Inconsistent_import of string + | Unavailable_unit of string + | Unsafe_file + | Linking_error of string * linking_error + | Corrupted_interface of string + | Cannot_open_dynamic_library of exn + | Library's_module_initializers_failed of exn + | Inconsistent_implementation of string + | Module_already_loaded of string + | Private_library_cannot_implement_interface of string + +exception Error of error + +val error_message : error -> string diff --git a/otherlibs/dynlink/extract_crc.ml b/otherlibs/dynlink/extract_crc.ml index 9b9dc66c..2ccbda86 100644 --- a/otherlibs/dynlink/extract_crc.ml +++ b/otherlibs/dynlink/extract_crc.ml @@ -18,9 +18,41 @@ let load_path = ref [] let first = ref true +exception Corrupted_interface + +let digest_interface unit loadpath = + let filename = + let shortname = unit ^ ".cmi" in + try + Misc.find_in_path_uncap loadpath shortname + with Not_found -> + failwith (Printf.sprintf "Cannot find interface %s in load path" + shortname) + in + let ic = open_in_bin filename in + try + let buffer = + really_input_string ic (String.length Config.cmi_magic_number) + in + if buffer <> Config.cmi_magic_number then begin + close_in ic; + raise Corrupted_interface + end; + let cmi = Cmi_format.input_cmi ic in + close_in ic; + let crc = + match cmi.Cmi_format.cmi_crcs with + (_, Some crc) :: _ -> crc + | _ -> raise Corrupted_interface + in + crc + with End_of_file | Failure _ -> + close_in ic; + raise Corrupted_interface + let print_crc unit = try - let crc = Dynlink.digest_interface unit (!load_path @ ["."]) in + let crc = digest_interface unit (!load_path @ ["."]) in if !first then first := false else print_string ";\n"; print_string " \""; print_string (String.capitalize_ascii unit); print_string "\",\n \""; @@ -33,9 +65,8 @@ let print_crc unit = prerr_endline unit; begin match exn with Sys_error msg -> prerr_endline msg - | Dynlink.Error(Dynlink.File_not_found name) -> - prerr_string "Cannot find file "; prerr_endline name - | Dynlink.Error _ -> prerr_endline "Ill-formed .cmi file" + | Corrupted_interface -> + Printf.eprintf "Ill-formed .cmi file (%s)\n" (Printexc.to_string exn) | _ -> raise exn end; exit 2 diff --git a/otherlibs/dynlink/natdynlink.ml b/otherlibs/dynlink/natdynlink.ml index fcf748c4..24f04f50 100644 --- a/otherlibs/dynlink/natdynlink.ml +++ b/otherlibs/dynlink/natdynlink.ml @@ -1,12 +1,14 @@ -#2 "otherlibs/dynlink/natdynlink.ml" +#3 "otherlibs/dynlink/natdynlink.ml" (**************************************************************************) (* *) (* OCaml *) (* *) -(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* Mark Shinwell and Leo White, Jane Street Europe *) (* *) (* Copyright 1996 Institut National de Recherche en Informatique et *) (* en Automatique. *) +(* Copyright 2017--2018 Jane Street Group LLC *) (* *) (* All rights reserved. This file is distributed under the terms of *) (* the GNU Lesser General Public License version 2.1, with the *) @@ -16,241 +18,105 @@ (* Dynamic loading of .cmx files *) -open Cmx_format +[@@@ocaml.warning "+a-4-30-40-41-42"] -type handle +module DC = Dynlink_common +module DT = Dynlink_types type global_map = { name : string; - crc_intf : Digest.t; - crc_impl : Digest.t; + crc_intf : Digest.t option; + crc_impl : Digest.t option; syms : string list } -external ndl_open: string -> bool -> handle * dynheader = "caml_natdynlink_open" -external ndl_run: handle -> string -> unit = "caml_natdynlink_run" -external ndl_getmap: unit -> global_map list = "caml_natdynlink_getmap" -external ndl_globals_inited: unit -> int = "caml_natdynlink_globals_inited" +module Native = struct + type handle -type linking_error = - Undefined_global of string - | Unavailable_primitive of string - | Uninitialized_global of string - -type error = - Not_a_bytecode_file of string - | Inconsistent_import of string - | Unavailable_unit of string - | Unsafe_file - | Linking_error of string * linking_error - | Corrupted_interface of string - | File_not_found of string - | Cannot_open_dll of string - | Inconsistent_implementation of string - -exception Error of error + external ndl_open : string -> bool -> handle * Cmx_format.dynheader + = "caml_natdynlink_open" + external ndl_run : handle -> string -> unit = "caml_natdynlink_run" + external ndl_getmap : unit -> global_map list = "caml_natdynlink_getmap" + external ndl_globals_inited : unit -> int = "caml_natdynlink_globals_inited" -(* Copied from config.ml to avoid dependencies *) -let cmxs_magic_number = "Caml1999D023" + module Unit_header = struct + type t = Cmx_format.dynunit -let dll_filename fname = - if Filename.is_implicit fname then Filename.concat (Sys.getcwd ()) fname - else fname + let name (t : t) = t.dynu_name + let crc (t : t) = Some t.dynu_crc -let read_file filename priv = - let dll = dll_filename filename in - if not (Sys.file_exists dll) then raise (Error (File_not_found dll)); + let interface_imports (t : t) = t.dynu_imports_cmi + let implementation_imports (t : t) = t.dynu_imports_cmx - let (handle,header) = try - ndl_open dll (not priv) - with Failure s -> raise (Error (Cannot_open_dll s)) in + let defined_symbols (t : t) = t.dynu_defines + let unsafe_module _t = false + end - if header.dynu_magic <> cmxs_magic_number - then raise(Error(Not_a_bytecode_file dll)); - (dll, handle, header.dynu_units) + let init () = () + let is_native = true + let adapt_filename f = Filename.chop_extension f ^ ".cmxs" + let num_globals_inited () = ndl_globals_inited () -(* Management of interface and implementation CRCs *) + (* Copied from config.ml -- this file cannot depend on that. *) + let cmxs_magic_number = "Caml1999D025" -module StrMap = Map.Make(String) - -type implem_state = - | Loaded - | Check_inited of int - -type state = { - ifaces: (string*string) StrMap.t; - implems: (string*string*implem_state) StrMap.t; -} - -let empty_state = { - ifaces = StrMap.empty; - implems = StrMap.empty; -} - -let global_state = ref empty_state - -let allow_extension = ref true - -let inited = ref false - -let default_available_units () = - let map = ndl_getmap () in - let exe = Sys.executable_name in - let rank = ref 0 in - global_state := - List.fold_left - (fun st {name;crc_intf;crc_impl;syms} -> + let fold_initial_units ~init ~f = + let rank = ref 0 in + List.fold_left (fun acc { name; crc_intf; crc_impl; syms; } -> rank := !rank + List.length syms; - { - ifaces = StrMap.add name (crc_intf,exe) st.ifaces; - implems = StrMap.add name (crc_impl,exe,Check_inited !rank) st.implems; - } - ) - empty_state - map; - allow_extension := true; - inited := true - -let init () = - if not !inited then default_available_units () - -let add_check_ifaces allow_ext filename ui ifaces = - List.fold_left - (fun ifaces (name, crco) -> - match crco with - None -> ifaces - | Some crc -> - if name = ui.dynu_name - then StrMap.add name (crc,filename) ifaces - else - try - let (old_crc, _old_src) = StrMap.find name ifaces in - if old_crc <> crc - then raise(Error(Inconsistent_import name)) - else ifaces - with Not_found -> - if allow_ext then StrMap.add name (crc,filename) ifaces - else raise (Error(Unavailable_unit name)) - ) ifaces ui.dynu_imports_cmi - -let check_implems ui implems = - List.iter - (fun (name, crco) -> - match name with - |"Out_of_memory" - |"Sys_error" - |"Failure" - |"Invalid_argument" - |"End_of_file" - |"Division_by_zero" - |"Not_found" - |"Match_failure" - |"Stack_overflow" - |"Sys_blocked_io" - |"Assert_failure" - |"Undefined_recursive_module" -> () - | _ -> - try - let (old_crc, _old_src, state) = StrMap.find name implems in - match crco with - Some crc when old_crc <> crc -> - raise(Error(Inconsistent_implementation name)) - | _ -> - match state with - | Check_inited i -> - if ndl_globals_inited() < i - then raise(Error(Unavailable_unit name)) - | Loaded -> () - with Not_found -> - raise (Error(Unavailable_unit name)) - ) ui.dynu_imports_cmx - -let loadunits filename handle units state = - let new_ifaces = - List.fold_left - (fun accu ui -> add_check_ifaces !allow_extension filename ui accu) - state.ifaces units in - let new_implems = - List.fold_left - (fun accu ui -> - check_implems ui accu; - StrMap.add ui.dynu_name (ui.dynu_crc,filename,Loaded) accu) - state.implems units in - - let defines = List.flatten (List.map (fun ui -> ui.dynu_defines) units) in - - ndl_run handle "_shared_startup"; - List.iter (ndl_run handle) defines; - { implems = new_implems; ifaces = new_ifaces } - -let load priv filename = - init(); - let (filename,handle,units) = read_file filename priv in - let nstate = loadunits filename handle units !global_state in - if not priv then global_state := nstate - -let loadfile filename = load false filename -let loadfile_private filename = load true filename - -let allow_only names = - init(); - let old = !global_state.ifaces in - let ifaces = - List.fold_left - (fun ifaces name -> - try StrMap.add name (StrMap.find name old) ifaces - with Not_found -> ifaces) - StrMap.empty names in - global_state := { !global_state with ifaces = ifaces }; - allow_extension := false - -let prohibit names = - init(); - let ifaces = List.fold_right StrMap.remove names !global_state.ifaces in - global_state := { !global_state with ifaces = ifaces }; - allow_extension := false - -let digest_interface _ _ = - failwith "Dynlink.digest_interface: not implemented in native code" -let add_interfaces _ _ = - failwith "Dynlink.add_interfaces: not implemented in native code" -let add_available_units _ = - failwith "Dynlink.add_available_units: not implemented in native code" -let clear_available_units _ = - failwith "Dynlink.clear_available_units: not implemented in native code" -let allow_unsafe_modules _ = - () - -(* Error report *) + let implementation = + match crc_impl with + | None -> None + | Some _ as crco -> Some (crco, DT.Check_inited !rank) + in + f acc ~comp_unit:name ~interface:crc_intf + ~implementation ~defined_symbols:syms) + init + (ndl_getmap ()) + + let run_shared_startup handle = + ndl_run handle "_shared_startup" + + let run handle ~unit_header ~priv:_ = + List.iter (fun cu -> + try ndl_run handle cu + with exn -> raise (DT.Error (Library's_module_initializers_failed exn))) + (Unit_header.defined_symbols unit_header) + + let load ~filename ~priv = + let handle, header = + try ndl_open filename (not priv) + with exn -> raise (DT.Error (Cannot_open_dynamic_library exn)) + in + if header.dynu_magic <> cmxs_magic_number then begin + raise (DT.Error (Not_a_bytecode_file filename)) + end; + handle, header.dynu_units + + let finish _handle = () +end + +include DC.Make (Native) + +type linking_error = DT.linking_error = + | Undefined_global of string + | Unavailable_primitive of string + | Uninitialized_global of string -let error_message = function - Not_a_bytecode_file name -> - name ^ " is not an object file" - | Inconsistent_import name -> - "interface mismatch on " ^ name - | Unavailable_unit name -> - "no implementation available for " ^ name - | Unsafe_file -> - "this object file uses unsafe features" - | Linking_error (name, Undefined_global s) -> - "error while linking " ^ name ^ ".\n" ^ - "Reference to undefined global `" ^ s ^ "'" - | Linking_error (name, Unavailable_primitive s) -> - "error while linking " ^ name ^ ".\n" ^ - "The external function `" ^ s ^ "' is not available" - | Linking_error (name, Uninitialized_global s) -> - "error while linking " ^ name ^ ".\n" ^ - "The module `" ^ s ^ "' is not yet initialized" - | Corrupted_interface name -> - "corrupted interface file " ^ name - | File_not_found name -> - "cannot find file " ^ name ^ " in search path" - | Cannot_open_dll reason -> - "error loading shared library: " ^ reason - | Inconsistent_implementation name -> - "implementation mismatch on " ^ name +type error = DT.error = + | Not_a_bytecode_file of string + | Inconsistent_import of string + | Unavailable_unit of string + | Unsafe_file + | Linking_error of string * linking_error + | Corrupted_interface of string + | Cannot_open_dynamic_library of exn + | Library's_module_initializers_failed of exn + | Inconsistent_implementation of string + | Module_already_loaded of string + | Private_library_cannot_implement_interface of string -let is_native = true -let adapt_filename f = Filename.chop_extension f ^ ".cmxs" +exception Error = DT.Error +let error_message = DT.error_message diff --git a/otherlibs/dynlink/nodynlink.ml b/otherlibs/dynlink/nodynlink.ml new file mode 100644 index 00000000..4556e775 --- /dev/null +++ b/otherlibs/dynlink/nodynlink.ml @@ -0,0 +1,79 @@ +#2 "otherlibs/dynlink/nodynlink.ml" +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* Copyright 2017--2018 Jane Street Group LLC *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-30-40-41-42"] + +module DC = Dynlink_common +module DT = Dynlink_types + +let not_available _ = + failwith "No support for native dynlink on this platform" + +module Not_available = struct + module Unit_header = struct + type t = unit + + let name = not_available + let crc = not_available + + let interface_imports = not_available + let implementation_imports = not_available + + let defined_symbols = not_available + let unsafe_module = not_available + end + + type handle = unit + + let init = not_available + + let is_native = false + let adapt_filename = not_available + + let num_globals_inited = not_available + + let fold_initial_units ~init ~f:_ = not_available init + + let run_shared_startup _ = not_available () + let run _ ~unit_header:_ ~priv:_ = not_available () + let load ~filename:_ ~priv:_ = not_available () + let finish = not_available +end + +include DC.Make (Not_available) + +type linking_error = DT.linking_error = + | Undefined_global of string + | Unavailable_primitive of string + | Uninitialized_global of string + +type error = DT.error = + | Not_a_bytecode_file of string + | Inconsistent_import of string + | Unavailable_unit of string + | Unsafe_file + | Linking_error of string * linking_error + | Corrupted_interface of string + | Cannot_open_dynamic_library of exn + | Library's_module_initializers_failed of exn + | Inconsistent_implementation of string + | Module_already_loaded of string + | Private_library_cannot_implement_interface of string + +exception Error = DT.Error +let error_message = DT.error_message diff --git a/otherlibs/graph/.depend b/otherlibs/graph/.depend index fdfa6200..cb4dfd44 100644 --- a/otherlibs/graph/.depend +++ b/otherlibs/graph/.depend @@ -1,6 +1,12 @@ -graphics.cmo : graphics.cmi -graphics.cmx : graphics.cmi +graphics.cmo : \ + graphics.cmi +graphics.cmx : \ + graphics.cmi graphics.cmi : -graphicsX11.cmo : graphics.cmi graphicsX11.cmi -graphicsX11.cmx : graphics.cmx graphicsX11.cmi +graphicsX11.cmo : \ + graphics.cmi \ + graphicsX11.cmi +graphicsX11.cmx : \ + graphics.cmx \ + graphicsX11.cmi graphicsX11.cmi : diff --git a/otherlibs/graph/Makefile b/otherlibs/graph/Makefile index ff8f45b0..fee153f6 100644 --- a/otherlibs/graph/Makefile +++ b/otherlibs/graph/Makefile @@ -25,10 +25,10 @@ LDOPTS=-ldopt "$(X11_LINK)" EXTRACFLAGS=$(X11_INCLUDES) -include ../Makefile +include ../Makefile.otherlibs.common depend: - $(CC) -MM $(CPPFLAGS) *.c | sed -e 's, /[^ ]*\.h,,g' > .depend - $(CAMLRUN) ../../tools/ocamldep -slash *.mli *.ml >> .depend + $(CC) -MM $(OC_CPPFLAGS) *.c | sed -e 's, /[^ ]*\.h,,g' > .depend + $(CAMLRUN) $(ROOTDIR)/boot/ocamlc -depend -slash *.mli *.ml >> .depend include .depend diff --git a/otherlibs/graph/events.c b/otherlibs/graph/events.c index 37146c9d..b858b037 100644 --- a/otherlibs/graph/events.c +++ b/otherlibs/graph/events.c @@ -79,7 +79,7 @@ void caml_gr_handle_event(XEvent * event) if (caml_gr_window.w > caml_gr_bstore.w || caml_gr_window.h > caml_gr_bstore.h) { - /* Allocate a new backing store large enough to accomodate + /* Allocate a new backing store large enough to accommodate both the old backing store and the current window. */ struct canvas newbstore; newbstore.w = max(caml_gr_window.w, caml_gr_bstore.w); diff --git a/otherlibs/graph/graphics.mli b/otherlibs/graph/graphics.mli index 2373241c..1acbd0d4 100644 --- a/otherlibs/graph/graphics.mli +++ b/otherlibs/graph/graphics.mli @@ -48,7 +48,7 @@ external size_y : unit -> int = "caml_gr_size_y" (** Return the size of the graphics window. Coordinates of the screen pixels range over [0 .. size_x()-1] and [0 .. size_y()-1]. Drawings outside of this rectangle are clipped, without causing - an error. The origin (0,0) is at the lower left corner. + an error. The origin (0,0) is at the lower left corner. Some implementation (e.g. X Windows) represent coordinates by 16-bit integers, hence wrong clipping may occur with coordinates below [-32768] or above [32676]. *) @@ -237,7 +237,10 @@ val fill_circle : int -> int -> int -> unit type image (** The abstract type for images, in internal representation. - Externally, images are represented as matrices of colors. *) + Externally, images are represented as matrices of colors. + Images are bound to the current graphics window and should not be reused + after closing this graphics window with {!close_graph}. +*) val transp : color (** In matrices of colors, this color represent a 'transparent' diff --git a/otherlibs/graph/image.c b/otherlibs/graph/image.c index 1d72e0da..baa85540 100644 --- a/otherlibs/graph/image.c +++ b/otherlibs/graph/image.c @@ -31,7 +31,8 @@ static struct custom_operations image_ops = { custom_hash_default, custom_serialize_default, custom_deserialize_default, - custom_compare_ext_default + custom_compare_ext_default, + custom_fixed_length_default }; #define Max_image_mem 2000000 diff --git a/otherlibs/graph/open.c b/otherlibs/graph/open.c index 10a0c4ad..7fac8c9e 100644 --- a/otherlibs/graph/open.c +++ b/otherlibs/graph/open.c @@ -374,8 +374,8 @@ void caml_gr_fail(const char *fmt, const char *arg) if (graphic_failure_exn == NULL) { graphic_failure_exn = caml_named_value("Graphics.Graphic_failure"); if (graphic_failure_exn == NULL) - caml_invalid_argument("Exception Graphics.Graphic_failure not initialized," - " must link graphics.cma"); + caml_invalid_argument("Exception Graphics.Graphic_failure not " + "initialized, must link graphics.cma"); } sprintf(buffer, fmt, arg); caml_raise_with_string(*graphic_failure_exn, buffer); diff --git a/otherlibs/raw_spacetime_lib/.depend b/otherlibs/raw_spacetime_lib/.depend index ea80dabb..381a50d2 100644 --- a/otherlibs/raw_spacetime_lib/.depend +++ b/otherlibs/raw_spacetime_lib/.depend @@ -1,14 +1,16 @@ -spacetime_offline.$(O): spacetime_offline.c ../../byterun/caml/alloc.h \ - ../../byterun/caml/misc.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h \ - ../../byterun/caml/gc.h ../../byterun/caml/intext.h \ - ../../byterun/caml/io.h ../../byterun/caml/major_gc.h \ - ../../byterun/caml/freelist.h ../../byterun/caml/memory.h \ - ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \ - ../../byterun/caml/roots.h ../../byterun/caml/signals.h \ - ../../byterun/caml/stack.h ../../byterun/caml/sys.h \ - ../../byterun/caml/spacetime.h -raw_spacetime_lib.cmo : raw_spacetime_lib.cmi -raw_spacetime_lib.cmx : raw_spacetime_lib.cmi +spacetime_offline.$(O): spacetime_offline.c ../../runtime/caml/alloc.h \ + ../../runtime/caml/misc.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/mlvalues.h ../../runtime/caml/fail.h \ + ../../runtime/caml/gc.h ../../runtime/caml/intext.h \ + ../../runtime/caml/io.h ../../runtime/caml/major_gc.h \ + ../../runtime/caml/freelist.h ../../runtime/caml/memory.h \ + ../../runtime/caml/minor_gc.h ../../runtime/caml/address_class.h \ + ../../runtime/caml/roots.h ../../runtime/caml/signals.h \ + ../../runtime/caml/stack.h ../../runtime/caml/sys.h \ + ../../runtime/caml/spacetime.h +raw_spacetime_lib.cmo : \ + raw_spacetime_lib.cmi +raw_spacetime_lib.cmx : \ + raw_spacetime_lib.cmi raw_spacetime_lib.cmi : diff --git a/otherlibs/raw_spacetime_lib/Makefile b/otherlibs/raw_spacetime_lib/Makefile index 5ba21859..0a87a553 100644 --- a/otherlibs/raw_spacetime_lib/Makefile +++ b/otherlibs/raw_spacetime_lib/Makefile @@ -19,15 +19,15 @@ LIBNAME=raw_spacetime_lib COBJS=spacetime_offline.$(O) CAMLOBJS=raw_spacetime_lib.cmo -include ../Makefile +include ../Makefile.otherlibs.common .PHONY: depend depend: ifeq "$(TOOLCHAIN)" "msvc" $(error Dependencies cannot be regenerated using the MSVC ports) else - $(CC) -MM $(CPPFLAGS) *.c | sed -e 's/\.o/.$$(O)/g' > .depend - $(CAMLRUN) $(ROOTDIR)/tools/ocamldep -slash *.mli *.ml >> .depend + $(CC) -MM $(OC_CPPFLAGS) *.c | sed -e 's/\.o/.$$(O)/g' > .depend + $(CAMLRUN) $(ROOTDIR)/boot/ocamlc -depend -slash *.mli *.ml >> .depend endif include .depend diff --git a/otherlibs/raw_spacetime_lib/Makefile.nt b/otherlibs/raw_spacetime_lib/Makefile.nt deleted file mode 100644 index 16e27354..00000000 --- a/otherlibs/raw_spacetime_lib/Makefile.nt +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include Makefile diff --git a/otherlibs/raw_spacetime_lib/spacetime_offline.c b/otherlibs/raw_spacetime_lib/spacetime_offline.c index fa93e5da..d022c5de 100644 --- a/otherlibs/raw_spacetime_lib/spacetime_offline.c +++ b/otherlibs/raw_spacetime_lib/spacetime_offline.c @@ -83,7 +83,6 @@ CAMLprim value caml_spacetime_unmarshal_trie (value v_channel) CAMLprim value caml_spacetime_node_num_header_words(value unit) { - unit = Val_unit; return Val_long(Node_num_header_words); } diff --git a/otherlibs/str/.depend b/otherlibs/str/.depend index f4d34d1a..4a2d288d 100644 --- a/otherlibs/str/.depend +++ b/otherlibs/str/.depend @@ -1,8 +1,10 @@ -strstubs.$(O): strstubs.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/memory.h \ - ../../byterun/caml/fail.h -str.cmo : str.cmi -str.cmx : str.cmi +strstubs.$(O): strstubs.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/memory.h \ + ../../runtime/caml/fail.h +str.cmo : \ + str.cmi +str.cmx : \ + str.cmi str.cmi : diff --git a/otherlibs/str/Makefile b/otherlibs/str/Makefile index 5ec61d37..6b0f025e 100644 --- a/otherlibs/str/Makefile +++ b/otherlibs/str/Makefile @@ -20,7 +20,7 @@ COBJS=strstubs.$(O) CLIBNAME=camlstr CAMLOBJS=str.cmo -include ../Makefile +include ../Makefile.otherlibs.common str.cmo: str.cmi str.cmx: str.cmi @@ -29,8 +29,8 @@ depend: ifeq "$(TOOLCHAIN)" "msvc" $(error Dependencies cannot be regenerated using the MSVC ports) else - $(CC) -MM $(CPPFLAGS) *.c | sed -e 's/\.o/.$$(O)/g' > .depend - $(CAMLRUN) $(ROOTDIR)/tools/ocamldep -slash *.mli *.ml >> .depend + $(CC) -MM $(OC_CPPFLAGS) *.c | sed -e 's/\.o/.$$(O)/g' > .depend + $(CAMLRUN) $(ROOTDIR)/boot/ocamlc -depend -slash *.mli *.ml >> .depend endif include .depend diff --git a/otherlibs/str/Makefile.nt b/otherlibs/str/Makefile.nt deleted file mode 100644 index ed9900bb..00000000 --- a/otherlibs/str/Makefile.nt +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include Makefile diff --git a/otherlibs/str/dune b/otherlibs/str/dune new file mode 100644 index 00000000..0c96b638 --- /dev/null +++ b/otherlibs/str/dune @@ -0,0 +1,20 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +(library + (name str) + (modes byte) + (flags (:standard -nostdlib)) + (libraries stdlib) + (c_names strstubs)) diff --git a/otherlibs/str/str.mli b/otherlibs/str/str.mli index 636e5812..d8299bbe 100644 --- a/otherlibs/str/str.mli +++ b/otherlibs/str/str.mli @@ -124,7 +124,7 @@ val matched_string : string -> string - {!Str.global_substitute} - {!Str.substitute_first} - provided that none of the following functions was called inbetween: + provided that none of the following functions was called in between: - {!Str.global_replace} - {!Str.replace_first} - {!Str.split} diff --git a/otherlibs/systhreads/.depend b/otherlibs/systhreads/.depend index 7210c5fa..a8016531 100644 --- a/otherlibs/systhreads/.depend +++ b/otherlibs/systhreads/.depend @@ -1,41 +1,60 @@ -st_stubs_b.$(O): st_stubs.c ../../byterun/caml/alloc.h \ - ../../byterun/caml/misc.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/backtrace.h \ - ../../byterun/caml/exec.h ../../byterun/caml/callback.h \ - ../../byterun/caml/custom.h ../../byterun/caml/fail.h \ - ../../byterun/caml/io.h ../../byterun/caml/memory.h \ - ../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \ - ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \ - ../../byterun/caml/address_class.h ../../byterun/caml/printexc.h \ - ../../byterun/caml/roots.h ../../byterun/caml/signals.h \ - ../../byterun/caml/stacks.h ../../byterun/caml/sys.h threads.h \ +st_stubs_b.$(O): st_stubs.c ../../runtime/caml/alloc.h \ + ../../runtime/caml/misc.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/mlvalues.h ../../runtime/caml/backtrace.h \ + ../../runtime/caml/exec.h ../../runtime/caml/callback.h \ + ../../runtime/caml/custom.h ../../runtime/caml/fail.h \ + ../../runtime/caml/io.h ../../runtime/caml/memory.h \ + ../../runtime/caml/gc.h ../../runtime/caml/major_gc.h \ + ../../runtime/caml/freelist.h ../../runtime/caml/minor_gc.h \ + ../../runtime/caml/address_class.h ../../runtime/caml/printexc.h \ + ../../runtime/caml/roots.h ../../runtime/caml/signals.h \ + ../../runtime/caml/stacks.h ../../runtime/caml/sys.h threads.h \ st_posix.h -st_stubs_n.$(O): st_stubs.c ../../byterun/caml/alloc.h \ - ../../byterun/caml/misc.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/backtrace.h \ - ../../byterun/caml/exec.h ../../byterun/caml/callback.h \ - ../../byterun/caml/custom.h ../../byterun/caml/fail.h \ - ../../byterun/caml/io.h ../../byterun/caml/memory.h \ - ../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \ - ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \ - ../../byterun/caml/address_class.h ../../byterun/caml/printexc.h \ - ../../byterun/caml/roots.h ../../byterun/caml/signals.h \ - ../../byterun/caml/stack.h ../../byterun/caml/sys.h threads.h \ +st_stubs_n.$(O): st_stubs.c ../../runtime/caml/alloc.h \ + ../../runtime/caml/misc.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/mlvalues.h ../../runtime/caml/backtrace.h \ + ../../runtime/caml/exec.h ../../runtime/caml/callback.h \ + ../../runtime/caml/custom.h ../../runtime/caml/fail.h \ + ../../runtime/caml/io.h ../../runtime/caml/memory.h \ + ../../runtime/caml/gc.h ../../runtime/caml/major_gc.h \ + ../../runtime/caml/freelist.h ../../runtime/caml/minor_gc.h \ + ../../runtime/caml/address_class.h ../../runtime/caml/printexc.h \ + ../../runtime/caml/roots.h ../../runtime/caml/signals.h \ + ../../runtime/caml/stack.h ../../runtime/caml/sys.h threads.h \ st_posix.h -condition.cmo : mutex.cmi condition.cmi -condition.cmx : mutex.cmx condition.cmi -condition.cmi : mutex.cmi -event.cmo : mutex.cmi condition.cmi event.cmi -event.cmx : mutex.cmx condition.cmx event.cmi +condition.cmo : \ + mutex.cmi \ + condition.cmi +condition.cmx : \ + mutex.cmx \ + condition.cmi +condition.cmi : \ + mutex.cmi +event.cmo : \ + mutex.cmi \ + condition.cmi \ + event.cmi +event.cmx : \ + mutex.cmx \ + condition.cmx \ + event.cmi event.cmi : -mutex.cmo : mutex.cmi -mutex.cmx : mutex.cmi +mutex.cmo : \ + mutex.cmi +mutex.cmx : \ + mutex.cmi mutex.cmi : -thread.cmo : thread.cmi -thread.cmx : thread.cmi +thread.cmo : \ + thread.cmi +thread.cmx : \ + thread.cmi thread.cmi : -threadUnix.cmo : thread.cmi threadUnix.cmi -threadUnix.cmx : thread.cmx threadUnix.cmi +threadUnix.cmo : \ + thread.cmi \ + threadUnix.cmi +threadUnix.cmx : \ + thread.cmx \ + threadUnix.cmi threadUnix.cmi : diff --git a/otherlibs/systhreads/Makefile b/otherlibs/systhreads/Makefile index 6b163d8f..d0b59a8d 100644 --- a/otherlibs/systhreads/Makefile +++ b/otherlibs/systhreads/Makefile @@ -15,17 +15,10 @@ ROOTDIR=../.. -include $(ROOTDIR)/config/Makefile +include $(ROOTDIR)/Makefile.config include $(ROOTDIR)/Makefile.common CAMLRUN ?= $(ROOTDIR)/boot/ocamlrun -CAMLYACC ?= $(ROOTDIR)/boot/ocamlyacc - -ifeq "$(wildcard $(ROOTDIR)/flexdll/Makefile)" "" -export OCAML_FLEXLINK:= -else -export OCAML_FLEXLINK:=$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/flexdll/flexlink.exe -endif LIBS = -nostdlib -I $(ROOTDIR)/stdlib -I $(ROOTDIR)/otherlibs/$(UNIXLIB) @@ -68,20 +61,22 @@ all: lib$(LIBNAME).$(A) $(LIBNAME).cma $(CMIFILES) allopt: lib$(LIBNAME)nat.$(A) $(LIBNAME).cmxa $(CMIFILES) lib$(LIBNAME).$(A): $(BYTECODE_C_OBJS) - $(MKLIB) -o $(LIBNAME) $(BYTECODE_C_OBJS) $(PTHREAD_LINK) + $(MKLIB_CMD) -o $(LIBNAME) $(BYTECODE_C_OBJS) $(PTHREAD_LINK) lib$(LIBNAME)nat.$(A): $(NATIVECODE_C_OBJS) - $(MKLIB) -o $(LIBNAME)nat $^ + $(MKLIB_CMD) -o $(LIBNAME)nat $^ $(LIBNAME).cma: $(THREADS_BCOBJS) ifeq "$(UNIX_OR_WIN32)" "unix" - $(MKLIB) -o $(LIBNAME) -ocamlc '$(CAMLC)' -cclib -lunix -linkall $(PTHREAD_CAML_LINK) $^ + $(MKLIB) -o $(LIBNAME) -ocamlc '$(CAMLC)' -cclib -lunix -linkall \ + $(PTHREAD_CAML_LINK) $^ # TODO: Figure out why -cclib -lunix is used here. # It may be because of the threadsUnix module which is deprecated. # It may hence be good to figure out whether this module shouldn't be # removed, and then -cclib -lunix arguments. else # Windows - $(MKLIB) -o $(LIBNAME) -ocamlc "$(CAMLC)" -linkall $(PTHREAD_CAML_LINK) $^ + $(MKLIB) -o $(LIBNAME) -ocamlc "$(CAMLC)" -linkall \ + $(PTHREAD_CAML_LINK) $^ endif # See remark above: force static linking of libthreadsnat.a @@ -98,12 +93,12 @@ $(LIBNAME).cmxa: $(THREADS_NCOBJS) # twice, each time with different options). st_stubs_b.$(O): st_stubs.c $(HEADER) - $(CC) -c $(CFLAGS) $(CPPFLAGS) -I$(ROOTDIR)/byterun \ - $(SHAREDCCCOMPOPTS) $(OUTPUTOBJ)$@ $< + $(CC) -c $(OC_CFLAGS) $(OC_CPPFLAGS) -I$(ROOTDIR)/runtime \ + $(SHAREDLIB_CFLAGS) $(OUTPUTOBJ)$@ $< st_stubs_n.$(O): st_stubs.c $(HEADER) - $(CC) $(CFLAGS) $(CPPFLAGS) -I$(ROOTDIR)/asmrun -I$(ROOTDIR)/byterun \ - $(SHAREDCCCOMPOPTS) -DNATIVE_CODE \ + $(CC) $(OC_CFLAGS) $(OC_CPPFLAGS) \ + -I$(ROOTDIR)/runtime $(SHAREDLIB_CFLAGS) -DNATIVE_CODE \ -DTARGET_$(ARCH) -DMODEL_$(MODEL) -DSYS_$(SYSTEM) \ $(OUTPUTOBJ)$@ -c $< @@ -124,9 +119,14 @@ install: cd "$(INSTALL_LIBDIR)"; $(RANLIB) libthreads.$(A) mkdir -p "$(INSTALL_THREADSLIBDIR)" $(INSTALL_DATA) \ - $(CMIFILES) $(CMIFILES:.cmi=.cmti) threads.cma \ + $(CMIFILES) threads.cma \ "$(INSTALL_THREADSLIBDIR)" - $(INSTALL_DATA) $(MLIFILES) "$(INSTALL_LIBDIR)" +ifeq "$(INSTALL_SOURCE_ARTIFACTS)" "true" + $(INSTALL_DATA) \ + $(CMIFILES:.cmi=.cmti) \ + "$(INSTALL_THREADSLIBDIR)" + $(INSTALL_DATA) $(MLIFILES) "$(INSTALL_THREADSLIBDIR)" +endif $(INSTALL_DATA) threads.h "$(INSTALL_LIBDIR)/caml" installopt: @@ -154,14 +154,14 @@ depend: $(error Dependencies cannot be regenerated using the MSVC ports) else depend: - $(CC) -MM $(CPPFLAGS) -I$(ROOTDIR)/byterun st_stubs.c \ + $(CC) -MM $(OC_CPPFLAGS) -I$(ROOTDIR)/runtime st_stubs.c \ | sed -e 's/st_stubs\.o/st_stubs_b.$$(O)/' \ -e 's/ st_\(posix\|win32\)\.h//g' > .depend - $(CC) -MM $(CPPFLAGS) -I$(ROOTDIR)/asmrun -I$(ROOTDIR)/byterun \ + $(CC) -MM $(OC_CPPFLAGS) -I$(ROOTDIR)/runtime \ -DNATIVE_CODE -DTARGET_$(ARCH) -DMODEL_$(MODEL) -DSYS_$(SYSTEM) \ st_stubs.c | sed -e 's/st_stubs\.o/st_stubs_n.$$(O)/' \ -e 's/ st_\(posix\|win32\)\.h//g' >> .depend - $(CAMLRUN) ../../tools/ocamldep -slash *.mli *.ml >> .depend + $(CAMLRUN) $(ROOTDIR)/boot/ocamlc -depend -slash *.mli *.ml >> .depend endif include .depend diff --git a/otherlibs/systhreads/Makefile.nt b/otherlibs/systhreads/Makefile.nt deleted file mode 100644 index ed9900bb..00000000 --- a/otherlibs/systhreads/Makefile.nt +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include Makefile diff --git a/otherlibs/systhreads/st_posix.h b/otherlibs/systhreads/st_posix.h index 55199338..386d4563 100644 --- a/otherlibs/systhreads/st_posix.h +++ b/otherlibs/systhreads/st_posix.h @@ -44,6 +44,7 @@ typedef int st_retcode; static int st_initialize(void) { + caml_sigmask_hook = pthread_sigmask; return 0; } @@ -76,6 +77,10 @@ static INLINE void st_thread_cleanup(void) /* Thread termination */ +CAMLnoreturn_start +static void st_thread_exit(void) +CAMLnoreturn_end; + static void st_thread_exit(void) { pthread_exit(NULL); @@ -89,7 +94,7 @@ static void st_thread_join(st_thread_id thr) /* Scheduling hints */ -static void INLINE st_thread_yield(void) +static INLINE void st_thread_yield(void) { #ifdef __linux__ /* sched_yield() doesn't do what we want in Linux 2.6 and up (PR#2663) */ @@ -262,7 +267,8 @@ static int st_event_create(st_event * res) rc = pthread_mutex_init(&e->lock, NULL); if (rc != 0) { caml_stat_free(e); return rc; } rc = pthread_cond_init(&e->triggered, NULL); - if (rc != 0) { pthread_mutex_destroy(&e->lock); caml_stat_free(e); return rc; } + if (rc != 0) + { pthread_mutex_destroy(&e->lock); caml_stat_free(e); return rc; } e->status = 0; *res = e; return 0; diff --git a/otherlibs/systhreads/st_stubs.c b/otherlibs/systhreads/st_stubs.c index f7816860..c751ffbc 100644 --- a/otherlibs/systhreads/st_stubs.c +++ b/otherlibs/systhreads/st_stubs.c @@ -39,8 +39,10 @@ #include "caml/spacetime.h" #endif +#ifndef NATIVE_CODE /* Initial size of bytecode stack when a thread is created (4 Ko) */ #define Thread_stack_size (Stack_size / 4) +#endif /* Max computation time before rescheduling, in milliseconds */ #define Thread_timeout 50 @@ -85,17 +87,17 @@ struct caml_thread_struct { value* spacetime_finaliser_trie_root; #endif #else - value * stack_low; /* The execution stack for this thread */ + value * stack_low; /* The execution stack for this thread */ value * stack_high; value * stack_threshold; - value * sp; /* Saved value of caml_extern_sp for this thread */ - value * trapsp; /* Saved value of caml_trapsp for this thread */ + value * sp; /* Saved value of caml_extern_sp for this thread */ + value * trapsp; /* Saved value of caml_trapsp for this thread */ struct caml__roots_block * local_roots; /* Saved value of caml_local_roots */ struct longjmp_buffer * external_raise; /* Saved caml_external_raise */ #endif - int backtrace_pos; /* Saved caml_backtrace_pos */ - backtrace_slot * backtrace_buffer; /* Saved caml_backtrace_buffer */ - value backtrace_last_exn; /* Saved caml_backtrace_last_exn (root) */ + int backtrace_pos; /* Saved caml_backtrace_pos */ + backtrace_slot * backtrace_buffer; /* Saved caml_backtrace_buffer */ + value backtrace_last_exn; /* Saved caml_backtrace_last_exn (root) */ }; typedef struct caml_thread_struct * caml_thread_t; @@ -548,6 +550,8 @@ static ST_THREAD_FUNCTION caml_thread_start(void * arg) #ifdef NATIVE_CODE struct longjmp_buffer termination_buf; char tos; + /* Record top of stack (approximative) */ + th->top_of_stack = &tos; #endif /* Associate the thread descriptor with the thread */ @@ -555,8 +559,6 @@ static ST_THREAD_FUNCTION caml_thread_start(void * arg) /* Acquire the global mutex */ caml_leave_blocking_section(); #ifdef NATIVE_CODE - /* Record top of stack (approximative) */ - th->top_of_stack = &tos; /* Setup termination handler (for caml_thread_exit) */ if (sigsetjmp(termination_buf.buf, 0) == 0) { th->exit_buf = &termination_buf; @@ -674,7 +676,8 @@ CAMLexport int caml_c_thread_unregister(void) CAMLprim value caml_thread_self(value unit) /* ML */ { - if (curr_thread == NULL) caml_invalid_argument("Thread.self: not initialized"); + if (curr_thread == NULL) + caml_invalid_argument("Thread.self: not initialized"); return curr_thread->descr; } @@ -704,7 +707,8 @@ CAMLprim value caml_thread_exit(value unit) /* ML */ { struct longjmp_buffer * exit_buf = NULL; - if (curr_thread == NULL) caml_invalid_argument("Thread.exit: not initialized"); + if (curr_thread == NULL) + caml_invalid_argument("Thread.exit: not initialized"); /* In native code, we cannot call pthread_exit here because on some systems this raises a C++ exception, and ocamlopt-generated stack @@ -775,7 +779,9 @@ static struct custom_operations caml_mutex_ops = { caml_mutex_compare, caml_mutex_hash, custom_serialize_default, - custom_deserialize_default + custom_deserialize_default, + custom_compare_ext_default, + custom_fixed_length_default }; CAMLprim value caml_mutex_new(value unit) /* ML */ @@ -854,7 +860,8 @@ static struct custom_operations caml_condition_ops = { caml_condition_hash, custom_serialize_default, custom_deserialize_default, - custom_compare_ext_default + custom_compare_ext_default, + custom_fixed_length_default }; CAMLprim value caml_condition_new(value unit) /* ML */ @@ -920,7 +927,8 @@ static struct custom_operations caml_threadstatus_ops = { custom_hash_default, custom_serialize_default, custom_deserialize_default, - custom_compare_ext_default + custom_compare_ext_default, + custom_fixed_length_default }; static value caml_threadstatus_new (void) diff --git a/otherlibs/systhreads/st_win32.h b/otherlibs/systhreads/st_win32.h index d24ea8cd..2f2ea665 100644 --- a/otherlibs/systhreads/st_win32.h +++ b/otherlibs/systhreads/st_win32.h @@ -83,6 +83,10 @@ static void st_thread_cleanup(void) /* Thread termination */ +CAMLnoreturn_start +static void st_thread_exit(void) +CAMLnoreturn_end; + static void st_thread_exit(void) { TRACE("st_thread_exit"); @@ -377,7 +381,8 @@ static void st_check_error(DWORD retcode, char * msg) sizeof(err)/sizeof(wchar_t), NULL); if (! ret) { - ret = swprintf(err, sizeof(err)/sizeof(wchar_t), L"error code %lx", retcode); + ret = + swprintf(err, sizeof(err)/sizeof(wchar_t), L"error code %lx", retcode); } msglen = strlen(msg); errlen = win_wide_char_to_multi_byte(err, ret, NULL, 0); diff --git a/otherlibs/threads/.depend b/otherlibs/threads/.depend index af34b81b..e6ce803b 100644 --- a/otherlibs/threads/.depend +++ b/otherlibs/threads/.depend @@ -1,35 +1,76 @@ -scheduler.o: scheduler.c ../../byterun/caml/alloc.h \ - ../../byterun/caml/misc.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/backtrace.h \ - ../../byterun/caml/exec.h ../../byterun/caml/callback.h \ - ../../byterun/caml/fail.h ../../byterun/caml/io.h \ - ../../byterun/caml/memory.h ../../byterun/caml/gc.h \ - ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \ - ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \ - ../../byterun/caml/printexc.h ../../byterun/caml/roots.h \ - ../../byterun/caml/signals.h ../../byterun/caml/stacks.h \ - ../../byterun/caml/sys.h -condition.cmo : thread.cmi mutex.cmi condition.cmi -condition.cmx : thread.cmx mutex.cmx condition.cmi -condition.cmi : mutex.cmi -event.cmo : mutex.cmi condition.cmi event.cmi -event.cmx : mutex.cmx condition.cmx event.cmi +scheduler.o: scheduler.c ../../runtime/caml/alloc.h \ + ../../runtime/caml/misc.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/mlvalues.h ../../runtime/caml/backtrace.h \ + ../../runtime/caml/exec.h ../../runtime/caml/callback.h \ + ../../runtime/caml/fail.h ../../runtime/caml/io.h \ + ../../runtime/caml/memory.h ../../runtime/caml/gc.h \ + ../../runtime/caml/major_gc.h ../../runtime/caml/freelist.h \ + ../../runtime/caml/minor_gc.h ../../runtime/caml/address_class.h \ + ../../runtime/caml/printexc.h ../../runtime/caml/roots.h \ + ../../runtime/caml/signals.h ../../runtime/caml/stacks.h \ + ../../runtime/caml/sys.h +condition.cmo : \ + thread.cmi \ + mutex.cmi \ + condition.cmi +condition.cmx : \ + thread.cmx \ + mutex.cmx \ + condition.cmi +condition.cmi : \ + mutex.cmi +event.cmo : \ + mutex.cmi \ + condition.cmi \ + event.cmi +event.cmx : \ + mutex.cmx \ + condition.cmx \ + event.cmi event.cmi : marshal.cmo : marshal.cmx : -mutex.cmo : thread.cmi mutex.cmi -mutex.cmx : thread.cmx mutex.cmi +mutex.cmo : \ + thread.cmi \ + mutex.cmi +mutex.cmx : \ + thread.cmx \ + mutex.cmi mutex.cmi : -stdlib.cmo : unix.cmi marshal.cmo stdlib.cmi -stdlib.cmx : unix.cmx marshal.cmx stdlib.cmi -stdlib.cmi : marshal.cmo -thread.cmo : unix.cmi thread.cmi -thread.cmx : unix.cmx thread.cmi -thread.cmi : unix.cmi -threadUnix.cmo : unix.cmi thread.cmi threadUnix.cmi -threadUnix.cmx : unix.cmx thread.cmx threadUnix.cmi -threadUnix.cmi : unix.cmi -unix.cmo : stdlib.cmi unix.cmi -unix.cmx : stdlib.cmx unix.cmi -unix.cmi : stdlib.cmi +stdlib.cmo : \ + unix.cmi \ + marshal.cmo \ + stdlib.cmi +stdlib.cmx : \ + unix.cmx \ + marshal.cmx \ + stdlib.cmi +stdlib.cmi : \ + marshal.cmo +thread.cmo : \ + unix.cmi \ + thread.cmi +thread.cmx : \ + unix.cmx \ + thread.cmi +thread.cmi : \ + unix.cmi +threadUnix.cmo : \ + unix.cmi \ + thread.cmi \ + threadUnix.cmi +threadUnix.cmx : \ + unix.cmx \ + thread.cmx \ + threadUnix.cmi +threadUnix.cmi : \ + unix.cmi +unix.cmo : \ + stdlib.cmi \ + unix.cmi +unix.cmx : \ + stdlib.cmx \ + unix.cmi +unix.cmi : \ + stdlib.cmi diff --git a/otherlibs/threads/Makefile b/otherlibs/threads/Makefile index aca35887..9b81940e 100644 --- a/otherlibs/threads/Makefile +++ b/otherlibs/threads/Makefile @@ -15,44 +15,48 @@ # FIXME reduce redundancy by including ../Makefile -include ../../config/Makefile -include ../../Makefile.common +ROOTDIR = ../.. -CAMLRUN ?= ../../boot/ocamlrun -CAMLYACC ?= ../../boot/ocamlyacc +include $(ROOTDIR)/Makefile.config +include $(ROOTDIR)/Makefile.common -CFLAGS += $(SHAREDCCCOMPOPTS) -CPPFLAGS += -I../../byterun -ROOTDIR=../.. +CAMLRUN ?= $(ROOTDIR)/boot/ocamlrun + +OC_CFLAGS += $(SHAREDLIB_CFLAGS) +OC_CPPFLAGS += -I$(ROOTDIR)/runtime CAMLC=$(CAMLRUN) $(ROOTDIR)/ocamlc -nostdlib \ -I $(ROOTDIR)/stdlib -I $(ROOTDIR)/otherlibs/unix -MKLIB=$(CAMLRUN) ../../tools/ocamlmklib +MKLIB=$(CAMLRUN) $(ROOTDIR)/tools/ocamlmklib COMPFLAGS=-w +33..39 -warn-error A -bin-annot -g -safe-string C_OBJS=scheduler.o CAML_OBJS=thread.cmo mutex.cmo condition.cmo event.cmo threadUnix.cmo -LIB=../../stdlib +LIB=$(ROOTDIR)/stdlib # Object file prefix P=stdlib__ -LIB_OBJS=$(LIB)/camlinternalFormatBasics.cmo stdlib.cmo \ - $(LIB)/$(P)seq.cmo $(LIB)/$(P)array.cmo $(LIB)/$(P)list.cmo $(LIB)/$(P)char.cmo $(LIB)/$(P)bytes.cmo \ - $(LIB)/$(P)string.cmo $(LIB)/$(P)sys.cmo $(LIB)/$(P)sort.cmo marshal.cmo \ - $(LIB)/$(P)obj.cmo $(LIB)/$(P)int32.cmo $(LIB)/$(P)int64.cmo \ - $(LIB)/$(P)nativeint.cmo $(LIB)/$(P)lexing.cmo $(LIB)/$(P)parsing.cmo \ - $(LIB)/$(P)set.cmo $(LIB)/$(P)map.cmo $(LIB)/$(P)stack.cmo $(LIB)/$(P)queue.cmo \ - $(LIB)/camlinternalLazy.cmo $(LIB)/$(P)lazy.cmo $(LIB)/$(P)stream.cmo \ - $(LIB)/$(P)buffer.cmo $(LIB)/camlinternalFormat.cmo $(LIB)/$(P)printf.cmo \ - $(LIB)/$(P)arg.cmo $(LIB)/$(P)printexc.cmo $(LIB)/$(P)gc.cmo $(LIB)/$(P)digest.cmo \ - $(LIB)/$(P)random.cmo $(LIB)/$(P)hashtbl.cmo $(LIB)/$(P)format.cmo \ - $(LIB)/$(P)scanf.cmo $(LIB)/$(P)callback.cmo $(LIB)/camlinternalOO.cmo \ - $(LIB)/$(P)oo.cmo $(LIB)/camlinternalMod.cmo $(LIB)/$(P)genlex.cmo \ - $(LIB)/$(P)weak.cmo $(LIB)/$(P)ephemeron.cmo $(LIB)/$(P)filename.cmo \ - $(LIB)/$(P)complex.cmo $(LIB)/$(P)arrayLabels.cmo $(LIB)/$(P)listLabels.cmo \ - $(LIB)/$(P)bytesLabels.cmo $(LIB)/$(P)stringLabels.cmo \ +LIB_OBJS=$(LIB)/camlinternalFormatBasics.cmo stdlib.cmo $(LIB)/$(P)bool.cmo \ + $(LIB)/$(P)seq.cmo $(LIB)/$(P)option.cmo $(LIB)/$(P)result.cmo \ + $(LIB)/$(P)fun.cmo $(LIB)/$(P)unit.cmo \ + $(LIB)/$(P)array.cmo $(LIB)/$(P)list.cmo \ + $(LIB)/$(P)char.cmo $(LIB)/$(P)bytes.cmo $(LIB)/$(P)string.cmo \ + $(LIB)/$(P)sys.cmo marshal.cmo $(LIB)/$(P)obj.cmo \ + $(LIB)/$(P)int.cmo $(LIB)/$(P)int32.cmo $(LIB)/$(P)int64.cmo \ + $(LIB)/$(P)nativeint.cmo $(LIB)/$(P)lexing.cmo $(LIB)/$(P)parsing.cmo \ + $(LIB)/$(P)set.cmo $(LIB)/$(P)map.cmo $(LIB)/$(P)stack.cmo \ + $(LIB)/$(P)queue.cmo $(LIB)/camlinternalLazy.cmo $(LIB)/$(P)lazy.cmo \ + $(LIB)/$(P)stream.cmo $(LIB)/$(P)buffer.cmo $(LIB)/camlinternalFormat.cmo \ + $(LIB)/$(P)printf.cmo $(LIB)/$(P)arg.cmo $(LIB)/$(P)printexc.cmo \ + $(LIB)/$(P)gc.cmo $(LIB)/$(P)digest.cmo \ + $(LIB)/$(P)random.cmo $(LIB)/$(P)hashtbl.cmo $(LIB)/$(P)format.cmo \ + $(LIB)/$(P)scanf.cmo $(LIB)/$(P)callback.cmo $(LIB)/camlinternalOO.cmo \ + $(LIB)/$(P)oo.cmo $(LIB)/camlinternalMod.cmo $(LIB)/$(P)genlex.cmo \ + $(LIB)/$(P)weak.cmo $(LIB)/$(P)ephemeron.cmo $(LIB)/$(P)filename.cmo \ + $(LIB)/$(P)complex.cmo $(LIB)/$(P)arrayLabels.cmo $(LIB)/$(P)listLabels.cmo \ + $(LIB)/$(P)bytesLabels.cmo $(LIB)/$(P)stringLabels.cmo \ $(LIB)/$(P)moreLabels.cmo $(LIB)/$(P)stdLabels.cmo UNIXLIB=../unix @@ -67,13 +71,13 @@ libvmthreads.a: $(C_OBJS) $(MKLIB) -o threads -oc vmthreads $(C_OBJS) threads.cma: $(CAML_OBJS) - $(MKLIB) -ocamlc '$(CAMLC)' -o threads -oc vmthreads $(CAML_OBJS) + $(MKLIB) -ocamlc '$(CAMLC)' -o threads -oc vmthreads $^ stdlib.cma: $(LIB_OBJS) - $(CAMLC) -a -o stdlib.cma $(LIB_OBJS) + $(CAMLC) -a -o $@ $^ unix.cma: $(UNIXLIB_OBJS) - $(MKLIB) -ocamlc '$(CAMLC)' -o unix -linkall $(UNIXLIB_OBJS) + $(MKLIB) -ocamlc '$(CAMLC)' -o unix -linkall $^ stdlib.cmo: stdlib.mli stdlib.cmi stdlib.ml $(CAMLC) ${COMPFLAGS} -nopervasives \ @@ -83,23 +87,23 @@ stdlib.mli: $(LIB)/stdlib.mli ln -s $(LIB)/stdlib.mli stdlib.mli stdlib.cmi: $(LIB)/stdlib.cmi - rm -f stdlib.cmi - ln -s $(LIB)/stdlib.cmi stdlib.cmi + rm -f $@ + ln -s $< $@ -$(P)marshal.cmo: marshal.mli $(P)marshal.cmi marshal.ml - $(CAMLC) ${COMPFLAGS} -o$@ -c marshal.ml +$(P)marshal.cmo: marshal.ml marshal.mli $(P)marshal.cmi + $(CAMLC) ${COMPFLAGS} -o$@ -c $< marshal.mli: $(LIB)/marshal.mli - ln -s $(LIB)/marshal.mli marshal.mli + ln -s $< $@ $(P)marshal.cmi: $(LIB)/$(P)marshal.cmi - ln -s $(LIB)/$(P)marshal.cmi $(P)marshal.cmi + ln -s $< $@ unix.mli: $(UNIXLIB)/unix.mli - ln -s -f $(UNIXLIB)/unix.mli unix.mli + ln -s -f $< $@ unix.cmi: $(UNIXLIB)/unix.cmi - ln -s -f $(UNIXLIB)/unix.cmi unix.cmi + ln -s -f $< $@ unix.cmo: unix.mli unix.cmi $(UNIXLIB)/unixLabels.cmo $(CAMLC) ${COMPFLAGS} -c unix.ml @@ -121,9 +125,14 @@ install: $(INSTALL_DATA) libvmthreads.a "$(INSTALL_LIBDIR)/vmthreads" cd "$(INSTALL_LIBDIR)/vmthreads"; $(RANLIB) libvmthreads.a $(INSTALL_DATA) \ - $(CMIFILES) $(CMIFILES:.cmi=.mli) $(CMIFILES:.cmi=.cmti) \ + $(CMIFILES) \ threads.cma stdlib.cma unix.cma \ "$(INSTALL_LIBDIR)/vmthreads" +ifeq "$(INSTALL_SOURCE_ARTIFACTS)" "true" + $(INSTALL_DATA) \ + $(CMIFILES:.cmi=.mli) $(CMIFILES:.cmi=.cmti) \ + "$(INSTALL_LIBDIR)/vmthreads" +endif installopt: @@ -135,13 +144,16 @@ installopt: .ml.cmo: $(CAMLC) -c $(COMPFLAGS) $< +%.$(O): %.c + $(CC) -c $(OC_CFLAGS) $(OC_CPPFLAGS) $(OUTPUTOBJ)$@ $< + .PHONY: depend depend: ifeq "$(TOOLCHAIN)" "msvc" $(error Dependencies cannot be regenerated using the MSVC ports) else - $(CC) -MM $(CPPFLAGS) *.c > .depend - $(CAMLRUN) ../../tools/ocamldep -slash *.mli *.ml >> .depend + $(CC) -MM $(OC_CPPFLAGS) *.c > .depend + $(CAMLRUN) $(ROOTDIR)/boot/ocamlc -depend -slash *.mli *.ml >> .depend endif include .depend diff --git a/otherlibs/threads/scheduler.c b/otherlibs/threads/scheduler.c index f434dc49..7a69bfca 100644 --- a/otherlibs/threads/scheduler.c +++ b/otherlibs/threads/scheduler.c @@ -569,7 +569,7 @@ value thread_sleep(value unit) /* ML */ static value thread_wait_rw(int kind, value fd) { /* Don't do an error if we're not initialized yet - (we can be called from thread-safe Pervasives before initialization), + (we can be called from thread-safe Stdlib before initialization), just return immediately. */ if (curr_thread == NULL) return RESUMED_WAKEUP; /* As a special case, if we're in a callback, don't fail but block diff --git a/otherlibs/threads/stdlib.ml b/otherlibs/threads/stdlib.ml index a2d2c859..d256f00a 100644 --- a/otherlibs/threads/stdlib.ml +++ b/otherlibs/threads/stdlib.ml @@ -17,16 +17,13 @@ been redefined to not block the whole process, but only the calling thread. *) -module Pervasives = struct -(* type 'a option = None | Some of 'a *) - (* Exceptions *) external register_named_value : string -> 'a -> unit = "caml_register_named_value" let () = - (* for asmrun/fail.c *) + (* for runtime/fail_nat.c *) register_named_value "Pervasives.array_bound_error" (Invalid_argument "index out of bounds") @@ -38,6 +35,18 @@ let failwith s = raise(Failure s) let invalid_arg s = raise(Invalid_argument s) exception Exit +exception Match_failure = Match_failure +exception Assert_failure = Assert_failure +exception Invalid_argument = Invalid_argument +exception Failure = Failure +exception Not_found = Not_found +exception Out_of_memory = Out_of_memory +exception Stack_overflow = Stack_overflow +exception Sys_error = Sys_error +exception End_of_file = End_of_file +exception Division_by_zero = Division_by_zero +exception Sys_blocked_io = Sys_blocked_io +exception Undefined_recursive_module = Undefined_recursive_module (* Composition operators *) @@ -629,7 +638,7 @@ let at_exit f = (* MPR#7253, MPR#7796: make sure "f" is executed only once *) let f_already_ran = ref false in exit_function := - (fun () -> + (fun () -> if not !f_already_ran then begin f_already_ran := true; f() end; g()) @@ -640,15 +649,13 @@ let exit retcode = sys_exit retcode let _ = register_named_value "Pervasives.do_at_exit" do_at_exit -end - -include Pervasives (*MODULE_ALIASES*) module Arg = Arg module Array = Array module ArrayLabels = ArrayLabels module Bigarray = Bigarray +module Bool = Bool module Buffer = Buffer module Bytes = Bytes module BytesLabels = BytesLabels @@ -660,9 +667,11 @@ module Ephemeron = Ephemeron module Filename = Filename module Float = Float module Format = Format +module Fun = Fun module Gc = Gc module Genlex = Genlex module Hashtbl = Hashtbl +module Int = Int module Int32 = Int32 module Int64 = Int64 module Lazy = Lazy @@ -675,15 +684,17 @@ module MoreLabels = MoreLabels module Nativeint = Nativeint module Obj = Obj module Oo = Oo +module Option = Option module Parsing = Parsing +module Pervasives = Pervasives module Printexc = Printexc module Printf = Printf module Queue = Queue module Random = Random +module Result = Result module Scanf = Scanf module Seq = Seq module Set = Set -module Sort = Sort module Spacetime = Spacetime module Stack = Stack module StdLabels = StdLabels @@ -692,4 +703,5 @@ module String = String module StringLabels = StringLabels module Sys = Sys module Uchar = Uchar +module Unit = Unit module Weak = Weak diff --git a/otherlibs/threads/unix.ml b/otherlibs/threads/unix.ml index b4635570..86d04667 100644 --- a/otherlibs/threads/unix.ml +++ b/otherlibs/threads/unix.ml @@ -63,6 +63,8 @@ let _ = thread_initialize() (* Back to the Unix module *) +let shell = "/bin/sh" + type error = E2BIG | EACCES @@ -210,6 +212,7 @@ external openfile : string -> open_flag list -> file_perm -> file_descr = "unix_open" external close : file_descr -> unit = "unix_close" +external fsync : file_descr -> unit = "unix_fsync" external unsafe_read : file_descr -> bytes -> int -> int -> int = "unix_read" external unsafe_write : file_descr -> bytes -> int -> int -> int = "unix_write" @@ -293,7 +296,7 @@ external fstat : file_descr -> stats = "unix_fstat" external isatty : file_descr -> bool = "unix_isatty" external unlink : string -> unit = "unix_unlink" external rename : string -> string -> unit = "unix_rename" -external link : string -> string -> unit = "unix_link" +external link : ?follow:bool -> string -> string -> unit = "unix_link" module LargeFile = struct @@ -573,7 +576,7 @@ type msg_flag = | MSG_DONTROUTE | MSG_PEEK -external _socket : +external _socket : ?cloexec: bool -> socket_domain -> socket_type -> int -> file_descr = "unix_socket" external _socketpair : @@ -884,7 +887,7 @@ let getnameinfo_emulation addr opts = let kind = if List.mem NI_DGRAM opts then "udp" else "tcp" in (getservbyport p kind).s_name with Not_found -> - string_of_int p in + Int.to_string p in { ni_hostname = hostname; ni_service = service } let getnameinfo addr opts = @@ -962,7 +965,7 @@ let rec waitpid_non_intr pid = let system cmd = match fork() with 0 -> begin try - execv "/bin/sh" [| "/bin/sh"; "-c"; cmd |] + execv shell [| shell; "-c"; cmd |] with _ -> exit 127 end @@ -1016,25 +1019,23 @@ type popen_process = let popen_processes = (Hashtbl.create 7 : (popen_process, int) Hashtbl.t) -let open_proc cmd envopt proc input output error = +let open_proc prog args envopt proc input output error = match fork() with 0 -> begin try perform_redirections input output error; - let shell = "/bin/sh" in - let argv = [| shell; "-c"; cmd |] in match envopt with - | Some env -> execve shell argv env - | None -> execv shell argv + | Some env -> execve prog args env + | None -> execv prog args with _ -> exit 127 end | id -> Hashtbl.add popen_processes proc id -let open_process_in cmd = +let open_process_args_in prog args = let (in_read, in_write) = pipe ~cloexec:true () in let inchan = in_channel_of_descr in_read in try - open_proc cmd None (Process_in inchan) stdin in_write stderr; + open_proc prog args None (Process_in inchan) stdin in_write stderr; close in_write; inchan with e -> @@ -1042,11 +1043,11 @@ let open_process_in cmd = close in_write; raise e -let open_process_out cmd = +let open_process_args_out prog args = let (out_read, out_write) = pipe ~cloexec:true () in let outchan = out_channel_of_descr out_write in try - open_proc cmd None (Process_out outchan) out_read stdout stderr; + open_proc prog args None (Process_out outchan) out_read stdout stderr; close out_read; outchan with e -> @@ -1054,14 +1055,15 @@ let open_process_out cmd = close out_read; raise e -let open_process cmd = +let open_process_args prog args = let (in_read, in_write) = pipe ~cloexec:true () in let inchan = in_channel_of_descr in_read in try let (out_read, out_write) = pipe ~cloexec:true () in let outchan = out_channel_of_descr out_write in try - open_proc cmd None (Process(inchan, outchan)) out_read in_write stderr; + open_proc prog args None + (Process(inchan, outchan)) out_read in_write stderr; close out_read; close in_write; (inchan, outchan) @@ -1072,9 +1074,9 @@ let open_process cmd = with e -> close_in inchan; close in_write; - raise e + raise e -let open_process_full cmd env = +let open_process_args_full prog args env = let (in_read, in_write) = pipe ~cloexec:true () in let inchan = in_channel_of_descr in_read in try @@ -1084,7 +1086,7 @@ let open_process_full cmd env = let (err_read, err_write) = pipe ~cloexec:true () in let errchan = in_channel_of_descr err_read in try - open_proc cmd (Some env) (Process_full(inchan, outchan, errchan)) + open_proc prog args (Some env) (Process_full(inchan, outchan, errchan)) out_read in_write err_write; close out_read; close in_write; @@ -1101,75 +1103,66 @@ let open_process_full cmd env = with e -> close_in inchan; close in_write; - raise e + raise e + +let open_process_shell fn cmd = + fn shell [|shell; "-c"; cmd|] +let open_process_in cmd = + open_process_shell open_process_args_in cmd +let open_process_out cmd = + open_process_shell open_process_args_out cmd +let open_process cmd = + open_process_shell open_process_args cmd +let open_process_full cmd = + open_process_shell open_process_args_full cmd let find_proc_id fun_name proc = try - let pid = Hashtbl.find popen_processes proc in - Hashtbl.remove popen_processes proc; - pid + Hashtbl.find popen_processes proc with Not_found -> raise(Unix_error(EBADF, fun_name, "")) +let remove_proc_id proc = + Hashtbl.remove popen_processes proc + +let process_in_pid inchan = + find_proc_id "process_in_pid" (Process_in inchan) +let process_out_pid outchan = + find_proc_id "process_out_pid" (Process_out outchan) +let process_pid (inchan, outchan) = + find_proc_id "process_pid" (Process(inchan, outchan)) +let process_full_pid (inchan, outchan, errchan) = + find_proc_id "process_full_pid" + (Process_full(inchan, outchan, errchan)) + let close_process_in inchan = - let pid = find_proc_id "close_process_in" (Process_in inchan) in + let proc = Process_in inchan in + let pid = find_proc_id "close_process_in" proc in + remove_proc_id proc; close_in inchan; snd(waitpid_non_intr pid) let close_process_out outchan = - let pid = find_proc_id "close_process_out" (Process_out outchan) in + let proc = Process_out outchan in + let pid = find_proc_id "close_process_out" proc in + remove_proc_id proc; (* The application may have closed [outchan] already to signal end-of-input to the process. *) begin try close_out outchan with Sys_error _ -> () end; snd(waitpid_non_intr pid) let close_process (inchan, outchan) = - let pid = find_proc_id "close_process" (Process(inchan, outchan)) in - close_in inchan; - begin try close_out outchan with Sys_error _ -> () end; - snd(waitpid_non_intr pid) - -let close_process_full (inchan, outchan, errchan) = - let pid = - find_proc_id "close_process_full" - (Process_full(inchan, outchan, errchan)) in - close_in inchan; - begin try close_out outchan with Sys_error _ -> () end; - close_in errchan; - snd(waitpid_non_intr pid) - -let find_proc_id fun_name proc = - try - let pid = Hashtbl.find popen_processes proc in - Hashtbl.remove popen_processes proc; - pid - with Not_found -> - raise(Unix_error(EBADF, fun_name, "")) - -let rec waitpid_non_intr pid = - try waitpid [] pid - with Unix_error (EINTR, _, _) -> waitpid_non_intr pid - -let close_process_in inchan = - let pid = find_proc_id "close_process_in" (Process_in inchan) in - close_in inchan; - snd(waitpid_non_intr pid) - -let close_process_out outchan = - let pid = find_proc_id "close_process_out" (Process_out outchan) in - close_out outchan; - snd(waitpid_non_intr pid) - -let close_process (inchan, outchan) = - let pid = find_proc_id "close_process" (Process(inchan, outchan)) in + let proc = Process(inchan, outchan) in + let pid = find_proc_id "close_process" proc in + remove_proc_id proc; close_in inchan; begin try close_out outchan with Sys_error _ -> () end; snd(waitpid_non_intr pid) let close_process_full (inchan, outchan, errchan) = - let pid = - find_proc_id "close_process_full" - (Process_full(inchan, outchan, errchan)) in + let proc = Process_full(inchan, outchan, errchan) in + let pid = find_proc_id "close_process_full" proc in + remove_proc_id proc; close_in inchan; begin try close_out outchan with Sys_error _ -> () end; close_in errchan; diff --git a/otherlibs/unix/.depend b/otherlibs/unix/.depend index cf12de60..80a9f4a8 100644 --- a/otherlibs/unix/.depend +++ b/otherlibs/unix/.depend @@ -1,452 +1,468 @@ -accept.o: accept.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h \ - ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h \ +accept.o: accept.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h \ + ../../runtime/caml/memory.h ../../runtime/caml/signals.h unixsupport.h \ socketaddr.h -access.o: access.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/memory.h \ - ../../byterun/caml/signals.h ../../byterun/caml/osdeps.h unixsupport.h -addrofstr.o: addrofstr.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/fail.h unixsupport.h \ +access.o: access.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/memory.h \ + ../../runtime/caml/signals.h ../../runtime/caml/osdeps.h unixsupport.h +addrofstr.o: addrofstr.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/fail.h unixsupport.h \ socketaddr.h -alarm.o: alarm.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h -bind.o: bind.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h unixsupport.h \ +alarm.o: alarm.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h unixsupport.h +bind.o: bind.c ../../runtime/caml/fail.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h unixsupport.h \ socketaddr.h -chdir.o: chdir.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/gc.h \ - ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \ - ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \ - ../../byterun/caml/signals.h ../../byterun/caml/osdeps.h unixsupport.h -chmod.o: chmod.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/gc.h \ - ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \ - ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \ - ../../byterun/caml/signals.h ../../byterun/caml/osdeps.h unixsupport.h -chown.o: chown.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h -chroot.o: chroot.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h -close.o: close.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/signals.h unixsupport.h -closedir.o: closedir.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h -connect.o: connect.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/signals.h unixsupport.h socketaddr.h -cst2constr.o: cst2constr.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/fail.h cst2constr.h -cstringv.o: cstringv.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/gc.h \ - ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \ - ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \ - ../../byterun/caml/osdeps.h unixsupport.h -dup.o: dup.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/misc.h unixsupport.h -dup2.o: dup2.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/misc.h unixsupport.h -envir.o: envir.c ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/misc.h ../../byterun/caml/alloc.h -errmsg.o: errmsg.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h -execv.o: execv.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/gc.h \ - ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \ - ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \ - ../../byterun/caml/osdeps.h unixsupport.h -execve.o: execve.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/gc.h \ - ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \ - ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \ - ../../byterun/caml/osdeps.h unixsupport.h -execvp.o: execvp.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/osdeps.h unixsupport.h -exit.o: exit.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/misc.h unixsupport.h -fchmod.o: fchmod.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/signals.h unixsupport.h -fchown.o: fchown.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/signals.h unixsupport.h -fcntl.o: fcntl.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h unixsupport.h -fork.o: fork.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/misc.h ../../byterun/caml/debugger.h unixsupport.h -ftruncate.o: ftruncate.c ../../byterun/caml/fail.h \ - ../../byterun/caml/misc.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/io.h \ - ../../byterun/caml/signals.h unixsupport.h -getaddrinfo.o: getaddrinfo.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h \ - ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h \ +channels.o: channels.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/io.h ../../runtime/caml/signals.h unixsupport.h \ + socketaddr.h +chdir.o: chdir.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/gc.h \ + ../../runtime/caml/major_gc.h ../../runtime/caml/freelist.h \ + ../../runtime/caml/minor_gc.h ../../runtime/caml/address_class.h \ + ../../runtime/caml/signals.h ../../runtime/caml/osdeps.h unixsupport.h +chmod.o: chmod.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/gc.h \ + ../../runtime/caml/major_gc.h ../../runtime/caml/freelist.h \ + ../../runtime/caml/minor_gc.h ../../runtime/caml/address_class.h \ + ../../runtime/caml/signals.h ../../runtime/caml/osdeps.h unixsupport.h +chown.o: chown.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/signals.h unixsupport.h +chroot.o: chroot.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/signals.h unixsupport.h +close.o: close.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/signals.h unixsupport.h +closedir.o: closedir.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/signals.h unixsupport.h +connect.o: connect.c ../../runtime/caml/fail.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/signals.h unixsupport.h socketaddr.h +cst2constr.o: cst2constr.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/fail.h cst2constr.h +cstringv.o: cstringv.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/gc.h \ + ../../runtime/caml/major_gc.h ../../runtime/caml/freelist.h \ + ../../runtime/caml/minor_gc.h ../../runtime/caml/address_class.h \ + ../../runtime/caml/osdeps.h unixsupport.h +dup.o: dup.c ../../runtime/caml/mlvalues.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/misc.h unixsupport.h +dup2.o: dup2.c ../../runtime/caml/mlvalues.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/misc.h unixsupport.h +envir.o: envir.c ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/misc.h ../../runtime/caml/alloc.h +errmsg.o: errmsg.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h +execv.o: execv.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/gc.h \ + ../../runtime/caml/major_gc.h ../../runtime/caml/freelist.h \ + ../../runtime/caml/minor_gc.h ../../runtime/caml/address_class.h \ + ../../runtime/caml/osdeps.h unixsupport.h +execve.o: execve.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/gc.h \ + ../../runtime/caml/major_gc.h ../../runtime/caml/freelist.h \ + ../../runtime/caml/minor_gc.h ../../runtime/caml/address_class.h \ + ../../runtime/caml/osdeps.h unixsupport.h +execvp.o: execvp.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/osdeps.h unixsupport.h +exit.o: exit.c ../../runtime/caml/mlvalues.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/misc.h unixsupport.h +fchmod.o: fchmod.c ../../runtime/caml/fail.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/signals.h unixsupport.h +fchown.o: fchown.c ../../runtime/caml/fail.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/signals.h unixsupport.h +fcntl.o: fcntl.c ../../runtime/caml/fail.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h unixsupport.h +fork.o: fork.c ../../runtime/caml/mlvalues.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/misc.h ../../runtime/caml/debugger.h unixsupport.h +fsync.o: fsync.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/signals.h unixsupport.h +ftruncate.o: ftruncate.c ../../runtime/caml/fail.h \ + ../../runtime/caml/misc.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/mlvalues.h ../../runtime/caml/io.h \ + ../../runtime/caml/signals.h unixsupport.h +getaddrinfo.o: getaddrinfo.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h \ + ../../runtime/caml/memory.h ../../runtime/caml/signals.h unixsupport.h \ cst2constr.h socketaddr.h -getcwd.o: getcwd.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h \ - ../../byterun/caml/osdeps.h ../../byterun/caml/memory.h \ - ../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \ - ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \ - ../../byterun/caml/address_class.h unixsupport.h -getegid.o: getegid.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h -geteuid.o: geteuid.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h -getgid.o: getgid.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h -getgr.o: getgr.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/fail.h ../../byterun/caml/alloc.h \ - ../../byterun/caml/memory.h unixsupport.h -getgroups.o: getgroups.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h -gethost.o: gethost.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h \ - ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h \ +getcwd.o: getcwd.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h \ + ../../runtime/caml/osdeps.h ../../runtime/caml/memory.h \ + ../../runtime/caml/gc.h ../../runtime/caml/major_gc.h \ + ../../runtime/caml/freelist.h ../../runtime/caml/minor_gc.h \ + ../../runtime/caml/address_class.h unixsupport.h +getegid.o: getegid.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h unixsupport.h +geteuid.o: geteuid.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h unixsupport.h +getgid.o: getgid.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h unixsupport.h +getgr.o: getgr.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/fail.h ../../runtime/caml/alloc.h \ + ../../runtime/caml/memory.h unixsupport.h +getgroups.o: getgroups.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h unixsupport.h +gethost.o: gethost.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h \ + ../../runtime/caml/memory.h ../../runtime/caml/signals.h unixsupport.h \ socketaddr.h -gethostname.o: gethostname.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h -getlogin.o: getlogin.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h unixsupport.h -getnameinfo.o: getnameinfo.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h \ - ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h \ +gethostname.o: gethostname.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h unixsupport.h +getlogin.o: getlogin.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h unixsupport.h +getnameinfo.o: getnameinfo.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h \ + ../../runtime/caml/memory.h ../../runtime/caml/signals.h unixsupport.h \ socketaddr.h -getpeername.o: getpeername.c ../../byterun/caml/fail.h \ - ../../byterun/caml/misc.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/mlvalues.h unixsupport.h socketaddr.h -getpid.o: getpid.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h -getppid.o: getppid.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h -getproto.o: getproto.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h \ - ../../byterun/caml/memory.h unixsupport.h -getpw.o: getpw.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/memory.h \ - ../../byterun/caml/fail.h unixsupport.h -getserv.o: getserv.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h \ - ../../byterun/caml/memory.h unixsupport.h -getsockname.o: getsockname.c ../../byterun/caml/fail.h \ - ../../byterun/caml/misc.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/mlvalues.h unixsupport.h socketaddr.h -gettimeofday.o: gettimeofday.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h -getuid.o: getuid.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h -gmtime.o: gmtime.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h \ - ../../byterun/caml/memory.h unixsupport.h -initgroups.o: initgroups.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h -isatty.o: isatty.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h -itimer.o: itimer.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h \ - ../../byterun/caml/memory.h unixsupport.h -kill.o: kill.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/misc.h ../../byterun/caml/fail.h unixsupport.h \ - ../../byterun/caml/signals.h -link.o: link.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/misc.h ../../byterun/caml/memory.h \ - ../../byterun/caml/signals.h unixsupport.h -listen.o: listen.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h unixsupport.h -lockf.o: lockf.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/signals.h unixsupport.h -lseek.o: lseek.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/io.h \ - ../../byterun/caml/signals.h unixsupport.h -mkdir.o: mkdir.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h -mkfifo.o: mkfifo.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h -mmap.o: mmap.c ../../byterun/caml/bigarray.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/misc.h \ - ../../byterun/caml/fail.h ../../byterun/caml/io.h \ - ../../byterun/caml/signals.h ../../byterun/caml/sys.h unixsupport.h -mmap_ba.o: mmap_ba.c ../../byterun/caml/alloc.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/bigarray.h ../../byterun/caml/custom.h \ - ../../byterun/caml/memory.h ../../byterun/caml/gc.h \ - ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \ - ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h -nice.o: nice.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/misc.h unixsupport.h -open.o: open.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/misc.h ../../byterun/caml/alloc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h -opendir.o: opendir.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/alloc.h \ - ../../byterun/caml/signals.h unixsupport.h -pipe.o: pipe.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/misc.h ../../byterun/caml/alloc.h unixsupport.h -putenv.o: putenv.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/memory.h ../../byterun/caml/gc.h \ - ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \ - ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \ - ../../byterun/caml/osdeps.h unixsupport.h -read.o: read.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/misc.h ../../byterun/caml/memory.h \ - ../../byterun/caml/signals.h unixsupport.h -readdir.o: readdir.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/fail.h ../../byterun/caml/alloc.h \ - ../../byterun/caml/signals.h unixsupport.h -readlink.o: readlink.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/alloc.h \ - ../../byterun/caml/fail.h ../../byterun/caml/signals.h unixsupport.h -rename.o: rename.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h -rewinddir.o: rewinddir.c ../../byterun/caml/fail.h \ - ../../byterun/caml/misc.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/mlvalues.h unixsupport.h -rmdir.o: rmdir.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/gc.h \ - ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \ - ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \ - ../../byterun/caml/signals.h ../../byterun/caml/osdeps.h unixsupport.h -select.o: select.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h \ - ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h -sendrecv.o: sendrecv.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h \ - ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h \ +getpeername.o: getpeername.c ../../runtime/caml/fail.h \ + ../../runtime/caml/misc.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/mlvalues.h unixsupport.h socketaddr.h +getpid.o: getpid.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h unixsupport.h +getppid.o: getppid.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h unixsupport.h +getproto.o: getproto.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h \ + ../../runtime/caml/memory.h unixsupport.h +getpw.o: getpw.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/memory.h \ + ../../runtime/caml/fail.h unixsupport.h +getserv.o: getserv.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h \ + ../../runtime/caml/memory.h unixsupport.h +getsockname.o: getsockname.c ../../runtime/caml/fail.h \ + ../../runtime/caml/misc.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/mlvalues.h unixsupport.h socketaddr.h +gettimeofday.o: gettimeofday.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h unixsupport.h +getuid.o: getuid.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h unixsupport.h +gmtime.o: gmtime.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h \ + ../../runtime/caml/memory.h unixsupport.h +initgroups.o: initgroups.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h unixsupport.h +isatty.o: isatty.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h unixsupport.h +itimer.o: itimer.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h \ + ../../runtime/caml/memory.h unixsupport.h +kill.o: kill.c ../../runtime/caml/mlvalues.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/misc.h ../../runtime/caml/fail.h unixsupport.h \ + ../../runtime/caml/signals.h +link.o: link.c ../../runtime/caml/mlvalues.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/misc.h ../../runtime/caml/memory.h \ + ../../runtime/caml/signals.h unixsupport.h +listen.o: listen.c ../../runtime/caml/fail.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h unixsupport.h +lockf.o: lockf.c ../../runtime/caml/fail.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/signals.h unixsupport.h +lseek.o: lseek.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/io.h \ + ../../runtime/caml/signals.h unixsupport.h +mkdir.o: mkdir.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/signals.h unixsupport.h +mkfifo.o: mkfifo.c ../../runtime/caml/fail.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/memory.h ../../runtime/caml/signals.h unixsupport.h +mmap.o: mmap.c ../../runtime/caml/bigarray.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/mlvalues.h ../../runtime/caml/misc.h \ + ../../runtime/caml/fail.h ../../runtime/caml/io.h \ + ../../runtime/caml/signals.h ../../runtime/caml/sys.h unixsupport.h +mmap_ba.o: mmap_ba.c ../../runtime/caml/alloc.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/bigarray.h ../../runtime/caml/custom.h \ + ../../runtime/caml/memory.h ../../runtime/caml/gc.h \ + ../../runtime/caml/major_gc.h ../../runtime/caml/freelist.h \ + ../../runtime/caml/minor_gc.h ../../runtime/caml/address_class.h +nice.o: nice.c ../../runtime/caml/mlvalues.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/misc.h unixsupport.h +open.o: open.c ../../runtime/caml/mlvalues.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/misc.h ../../runtime/caml/alloc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/signals.h unixsupport.h +opendir.o: opendir.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/alloc.h \ + ../../runtime/caml/signals.h unixsupport.h +pipe.o: pipe.c ../../runtime/caml/mlvalues.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/misc.h ../../runtime/caml/alloc.h unixsupport.h +putenv.o: putenv.c ../../runtime/caml/fail.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/memory.h ../../runtime/caml/gc.h \ + ../../runtime/caml/major_gc.h ../../runtime/caml/freelist.h \ + ../../runtime/caml/minor_gc.h ../../runtime/caml/address_class.h \ + ../../runtime/caml/osdeps.h unixsupport.h +read.o: read.c ../../runtime/caml/mlvalues.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/misc.h ../../runtime/caml/memory.h \ + ../../runtime/caml/signals.h unixsupport.h +readdir.o: readdir.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/fail.h ../../runtime/caml/alloc.h \ + ../../runtime/caml/signals.h unixsupport.h +readlink.o: readlink.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/alloc.h \ + ../../runtime/caml/fail.h ../../runtime/caml/signals.h unixsupport.h +rename.o: rename.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/signals.h unixsupport.h +rewinddir.o: rewinddir.c ../../runtime/caml/fail.h \ + ../../runtime/caml/misc.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/mlvalues.h unixsupport.h +rmdir.o: rmdir.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/gc.h \ + ../../runtime/caml/major_gc.h ../../runtime/caml/freelist.h \ + ../../runtime/caml/minor_gc.h ../../runtime/caml/address_class.h \ + ../../runtime/caml/signals.h ../../runtime/caml/osdeps.h unixsupport.h +select.o: select.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h \ + ../../runtime/caml/memory.h ../../runtime/caml/signals.h unixsupport.h +sendrecv.o: sendrecv.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h \ + ../../runtime/caml/memory.h ../../runtime/caml/signals.h unixsupport.h \ socketaddr.h -setgid.o: setgid.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h -setgroups.o: setgroups.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h \ - ../../byterun/caml/memory.h unixsupport.h -setsid.o: setsid.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h unixsupport.h -setuid.o: setuid.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h -shutdown.o: shutdown.c ../../byterun/caml/fail.h \ - ../../byterun/caml/misc.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/mlvalues.h unixsupport.h -signals.o: signals.c ../../byterun/caml/alloc.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/fail.h ../../byterun/caml/memory.h \ - ../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \ - ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \ - ../../byterun/caml/address_class.h ../../byterun/caml/signals.h \ +setgid.o: setgid.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h unixsupport.h +setgroups.o: setgroups.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h \ + ../../runtime/caml/memory.h unixsupport.h +setsid.o: setsid.c ../../runtime/caml/fail.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h unixsupport.h +setuid.o: setuid.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h unixsupport.h +shutdown.o: shutdown.c ../../runtime/caml/fail.h \ + ../../runtime/caml/misc.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/mlvalues.h unixsupport.h +signals.o: signals.c ../../runtime/caml/alloc.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/fail.h ../../runtime/caml/memory.h \ + ../../runtime/caml/gc.h ../../runtime/caml/major_gc.h \ + ../../runtime/caml/freelist.h ../../runtime/caml/minor_gc.h \ + ../../runtime/caml/address_class.h ../../runtime/caml/signals.h \ unixsupport.h -sleep.o: sleep.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/signals.h unixsupport.h -socket.o: socket.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h unixsupport.h -socketaddr.o: socketaddr.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/memory.h unixsupport.h \ +sleep.o: sleep.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/signals.h unixsupport.h +socket.o: socket.c ../../runtime/caml/fail.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h unixsupport.h +socketaddr.o: socketaddr.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/memory.h unixsupport.h \ socketaddr.h -socketpair.o: socketpair.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h -sockopt.o: sockopt.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/alloc.h \ - ../../byterun/caml/fail.h unixsupport.h socketaddr.h -stat.o: stat.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/misc.h ../../byterun/caml/memory.h \ - ../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \ - ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \ - ../../byterun/caml/address_class.h ../../byterun/caml/alloc.h \ - ../../byterun/caml/signals.h ../../byterun/caml/io.h unixsupport.h \ +socketpair.o: socketpair.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h unixsupport.h +sockopt.o: sockopt.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/alloc.h \ + ../../runtime/caml/fail.h unixsupport.h socketaddr.h +stat.o: stat.c ../../runtime/caml/mlvalues.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/misc.h ../../runtime/caml/memory.h \ + ../../runtime/caml/gc.h ../../runtime/caml/major_gc.h \ + ../../runtime/caml/freelist.h ../../runtime/caml/minor_gc.h \ + ../../runtime/caml/address_class.h ../../runtime/caml/alloc.h \ + ../../runtime/caml/signals.h ../../runtime/caml/io.h unixsupport.h \ cst2constr.h nanosecond_stat.h -strofaddr.o: strofaddr.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h \ +strofaddr.o: strofaddr.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h unixsupport.h \ socketaddr.h -symlink.o: symlink.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h -termios.o: termios.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h -time.o: time.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/misc.h ../../byterun/caml/alloc.h unixsupport.h -times.o: times.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/memory.h unixsupport.h -truncate.o: truncate.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/gc.h \ - ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \ - ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \ - ../../byterun/caml/fail.h ../../byterun/caml/signals.h \ - ../../byterun/caml/io.h unixsupport.h -umask.o: umask.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h unixsupport.h -unixsupport.o: unixsupport.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/callback.h \ - ../../byterun/caml/memory.h ../../byterun/caml/fail.h unixsupport.h \ +symlink.o: symlink.c ../../runtime/caml/fail.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/memory.h ../../runtime/caml/signals.h unixsupport.h +termios.o: termios.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h unixsupport.h +time.o: time.c ../../runtime/caml/mlvalues.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/misc.h ../../runtime/caml/alloc.h unixsupport.h +times.o: times.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/memory.h unixsupport.h +truncate.o: truncate.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/gc.h \ + ../../runtime/caml/major_gc.h ../../runtime/caml/freelist.h \ + ../../runtime/caml/minor_gc.h ../../runtime/caml/address_class.h \ + ../../runtime/caml/fail.h ../../runtime/caml/signals.h \ + ../../runtime/caml/io.h unixsupport.h +umask.o: umask.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h unixsupport.h +unixsupport.o: unixsupport.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/callback.h \ + ../../runtime/caml/memory.h ../../runtime/caml/fail.h unixsupport.h \ cst2constr.h -unlink.o: unlink.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/gc.h \ - ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \ - ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \ - ../../byterun/caml/signals.h ../../byterun/caml/osdeps.h unixsupport.h -utimes.o: utimes.c ../../byterun/caml/fail.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/memory.h ../../byterun/caml/gc.h \ - ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \ - ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h \ - ../../byterun/caml/signals.h ../../byterun/caml/osdeps.h unixsupport.h -wait.o: wait.c ../../byterun/caml/mlvalues.h ../../byterun/caml/config.h \ - ../../byterun/caml/m.h ../../byterun/caml/s.h \ - ../../byterun/caml/misc.h ../../byterun/caml/alloc.h \ - ../../byterun/caml/fail.h ../../byterun/caml/memory.h \ - ../../byterun/caml/gc.h ../../byterun/caml/major_gc.h \ - ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \ - ../../byterun/caml/address_class.h ../../byterun/caml/signals.h \ +unlink.o: unlink.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/gc.h \ + ../../runtime/caml/major_gc.h ../../runtime/caml/freelist.h \ + ../../runtime/caml/minor_gc.h ../../runtime/caml/address_class.h \ + ../../runtime/caml/signals.h ../../runtime/caml/osdeps.h unixsupport.h +utimes.o: utimes.c ../../runtime/caml/fail.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/memory.h ../../runtime/caml/gc.h \ + ../../runtime/caml/major_gc.h ../../runtime/caml/freelist.h \ + ../../runtime/caml/minor_gc.h ../../runtime/caml/address_class.h \ + ../../runtime/caml/signals.h ../../runtime/caml/osdeps.h unixsupport.h +wait.o: wait.c ../../runtime/caml/mlvalues.h ../../runtime/caml/config.h \ + ../../runtime/caml/m.h ../../runtime/caml/s.h \ + ../../runtime/caml/misc.h ../../runtime/caml/alloc.h \ + ../../runtime/caml/fail.h ../../runtime/caml/memory.h \ + ../../runtime/caml/gc.h ../../runtime/caml/major_gc.h \ + ../../runtime/caml/freelist.h ../../runtime/caml/minor_gc.h \ + ../../runtime/caml/address_class.h ../../runtime/caml/signals.h \ unixsupport.h -write.o: write.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/memory.h ../../byterun/caml/signals.h unixsupport.h -unix.cmo : unix.cmi -unix.cmx : unix.cmi +write.o: write.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/memory.h ../../runtime/caml/signals.h unixsupport.h +unix.cmo : \ + unix.cmi +unix.cmx : \ + unix.cmi unix.cmi : -unixLabels.cmo : unix.cmi unixLabels.cmi -unixLabels.cmx : unix.cmx unixLabels.cmi -unixLabels.cmi : unix.cmi +unixLabels.cmo : \ + unix.cmi \ + unixLabels.cmi +unixLabels.cmx : \ + unix.cmx \ + unixLabels.cmi +unixLabels.cmi : \ + unix.cmi diff --git a/otherlibs/unix/Makefile b/otherlibs/unix/Makefile index 39dfdcaa..2eaa5097 100644 --- a/otherlibs/unix/Makefile +++ b/otherlibs/unix/Makefile @@ -22,9 +22,9 @@ EXTRACAMLFLAGS=-nolabels # dllunix.so particularly requires libm for modf symbols LDOPTS=$(NATIVECCLIBS) -COBJS=accept.o access.o addrofstr.o alarm.o bind.o chdir.o chmod.o \ - chown.o chroot.o close.o closedir.o connect.o cst2constr.o cstringv.o \ - dup.o dup2.o envir.o errmsg.o execv.o execve.o execvp.o exit.o \ +COBJS=accept.o access.o addrofstr.o alarm.o bind.o channels.o chdir.o \ + chmod.o chown.o chroot.o close.o fsync.o closedir.o connect.o cst2constr.o \ + cstringv.o dup.o dup2.o envir.o errmsg.o execv.o execve.o execvp.o exit.o \ fchmod.o fchown.o fcntl.o fork.o ftruncate.o \ getaddrinfo.o getcwd.o getegid.o geteuid.o getgid.o \ getgr.o getgroups.o gethost.o gethostname.o getlogin.o \ @@ -44,15 +44,15 @@ CAMLOBJS=unix.cmo unixLabels.cmo HEADERS=unixsupport.h socketaddr.h -include ../Makefile +include ../Makefile.otherlibs.common .PHONY: depend depend: ifeq "$(TOOLCHAIN)" "msvc" $(error Dependencies cannot be regenerated using the MSVC ports) else - $(CC) -MM $(CPPFLAGS) *.c > .depend - $(CAMLRUN) ../../tools/ocamldep -slash *.mli *.ml >> .depend + $(CC) -MM $(OC_CPPFLAGS) *.c > .depend + $(CAMLRUN) $(ROOTDIR)/boot/ocamlc -depend -slash *.mli *.ml >> .depend endif include .depend diff --git a/otherlibs/unix/access.c b/otherlibs/unix/access.c index 4b6ba7f7..07cbcf62 100644 --- a/otherlibs/unix/access.c +++ b/otherlibs/unix/access.c @@ -37,7 +37,7 @@ static int access_permission_table[] = { R_OK, - W_OK, + W_OK, #ifdef _WIN32 /* Since there is no concept of execute permission on Windows, we fall b+ack to the read permission */ diff --git a/otherlibs/unix/channels.c b/otherlibs/unix/channels.c new file mode 100644 index 00000000..ecf0cc2f --- /dev/null +++ b/otherlibs/unix/channels.c @@ -0,0 +1,89 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Gallium, INRIA Paris */ +/* */ +/* Copyright 2017 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +#include +#include +#include +#include +#include +#include +#include "unixsupport.h" + +#ifdef HAS_SOCKETS +#include +#include "socketaddr.h" +#endif + +/* Check that the given file descriptor has "stream semantics" and + can therefore be used as part of buffered I/O. Things that + don't have "stream semantics" include block devices and + UDP (datagram) sockets. + Returns 0 if OK, a nonzero error code if error. */ + +static int unix_check_stream_semantics(int fd) +{ + struct stat buf; + + if (fstat(fd, &buf) == -1) return errno; + switch (buf.st_mode & S_IFMT) { + case S_IFREG: case S_IFCHR: case S_IFIFO: + /* These have stream semantics */ + return 0; +#ifdef HAS_SOCKETS + case S_IFSOCK: { + int so_type; + socklen_param_type so_type_len = sizeof(so_type); + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &so_type, &so_type_len) == -1) + return errno; + switch (so_type) { + case SOCK_STREAM: + return 0; + default: + return EINVAL; + } + } +#endif + default: + /* All other file types are suspect: block devices, directories, + symbolic links, whatnot. */ + return EINVAL; + } +} + +/* From runtime/io.c. To be declared in ? */ +extern value caml_ml_open_descriptor_in(value fd); +extern value caml_ml_open_descriptor_out(value fd); + +CAMLprim value unix_inchannel_of_filedescr(value fd) +{ + int err; + caml_enter_blocking_section(); + err = unix_check_stream_semantics(Int_val(fd)); + caml_leave_blocking_section(); + if (err != 0) unix_error(err, "in_channel_of_descr", Nothing); + return caml_ml_open_descriptor_in(fd); +} + +CAMLprim value unix_outchannel_of_filedescr(value fd) +{ + int err; + caml_enter_blocking_section(); + err = unix_check_stream_semantics(Int_val(fd)); + caml_leave_blocking_section(); + if (err != 0) unix_error(err, "out_channel_of_descr", Nothing); + return caml_ml_open_descriptor_out(fd); +} diff --git a/otherlibs/unix/cstringv.c b/otherlibs/unix/cstringv.c index d537c6d8..cb5eb596 100644 --- a/otherlibs/unix/cstringv.c +++ b/otherlibs/unix/cstringv.c @@ -31,7 +31,8 @@ char_os ** cstringvect(value arg, char * cmdname) if (! caml_string_is_c_safe(Field(arg, i))) unix_error(EINVAL, cmdname, Field(arg, i)); res = (char_os **) caml_stat_alloc((size + 1) * sizeof(char_os *)); - for (i = 0; i < size; i++) res[i] = caml_stat_strdup_to_os(String_val(Field(arg, i))); + for (i = 0; i < size; i++) + res[i] = caml_stat_strdup_to_os(String_val(Field(arg, i))); res[size] = NULL; return res; } diff --git a/otherlibs/unix/dune b/otherlibs/unix/dune new file mode 100644 index 00000000..eadac1a2 --- /dev/null +++ b/otherlibs/unix/dune @@ -0,0 +1,33 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +(library + (name unix) + (wrapped false) + (modes byte) + (flags (:standard -nostdlib -nolabels)) + (c_flags (-I %{project_root}/runtime)) + (libraries stdlib) + (c_names + accept access addrofstr alarm bind channels chdir chmod chown chroot close + fsync closedir connect cst2constr cstringv dup dup2 envir errmsg execv execve + execvp exit fchmod fchown fcntl fork ftruncate getaddrinfo getcwd getegid + geteuid getgid getgr getgroups gethost gethostname getlogin getnameinfo + getpeername getpid getppid getproto getpw gettimeofday getserv getsockname + getuid gmtime initgroups isatty itimer kill link listen lockf lseek mkdir + mkfifo mmap mmap_ba nice open opendir pipe putenv read readdir readlink + rename rewinddir rmdir select sendrecv setgid setgroups setsid setuid + shutdown signals sleep socket socketaddr socketpair sockopt stat strofaddr + symlink termios time times truncate umask unixsupport unlink utimes wait + write)) diff --git a/otherlibs/unix/execvp.c b/otherlibs/unix/execvp.c index 1eb43164..90ea1d01 100644 --- a/otherlibs/unix/execvp.c +++ b/otherlibs/unix/execvp.c @@ -65,4 +65,3 @@ CAMLprim value unix_execvpe(value path, value args, value env) } #endif - diff --git a/otherlibs/unix/fsync.c b/otherlibs/unix/fsync.c new file mode 100644 index 00000000..efeadd49 --- /dev/null +++ b/otherlibs/unix/fsync.c @@ -0,0 +1,40 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Francois Berenger, Kyushu Institute of Technology */ +/* */ +/* Copyright 2018 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#include +#include +#include "unixsupport.h" + +#ifdef _WIN32 +#include +#define fsync(fd) _commit(fd) +#else +#define fsync(fd) fsync(fd) +#endif + +CAMLprim value unix_fsync(value v) +{ + int ret; +#ifdef _WIN32 + int fd = win_CRT_fd_of_filedescr(v); +#else + int fd = Int_val(v); +#endif + caml_enter_blocking_section(); + ret = fsync(fd); + caml_leave_blocking_section(); + if (ret == -1) uerror("fsync", Nothing); + return Val_unit; +} diff --git a/otherlibs/unix/getaddrinfo.c b/otherlibs/unix/getaddrinfo.c index ab605bd2..4b2cd6e3 100644 --- a/otherlibs/unix/getaddrinfo.c +++ b/otherlibs/unix/getaddrinfo.c @@ -65,7 +65,7 @@ CAMLprim value unix_getaddrinfo(value vnode, value vserv, value vopts) int retcode; if (! (caml_string_is_c_safe(vnode) && caml_string_is_c_safe(vserv))) - return Val_int(0); + CAMLreturn (Val_int(0)); /* Extract "node" parameter */ if (caml_string_length(vnode) == 0) { diff --git a/otherlibs/unix/getgr.c b/otherlibs/unix/getgr.c index 5c26fb7a..7d120aa5 100644 --- a/otherlibs/unix/getgr.c +++ b/otherlibs/unix/getgr.c @@ -29,7 +29,8 @@ static value alloc_group_entry(struct group *entry) Begin_roots3 (name, pass, mem); name = caml_copy_string(entry->gr_name); - /* on some platforms, namely Android, gr_passwd can be NULL - hence this workaround */ + /* on some platforms, namely Android, gr_passwd can be NULL, + hence this workaround */ pass = caml_copy_string(entry->gr_passwd ? entry->gr_passwd : ""); mem = caml_copy_string_array((const char**)entry->gr_mem); res = caml_alloc_small(4, 0); diff --git a/otherlibs/unix/gethost.c b/otherlibs/unix/gethost.c index 49e5bdea..4a72c098 100644 --- a/otherlibs/unix/gethost.c +++ b/otherlibs/unix/gethost.c @@ -70,7 +70,8 @@ static value alloc_host_entry(struct hostent *entry) aliases = Atom(0); entry_h_length = entry->h_length; #ifdef h_addr - addr_list = caml_alloc_array(alloc_one_addr, (const char**)entry->h_addr_list); + addr_list = + caml_alloc_array(alloc_one_addr, (const char**)entry->h_addr_list); #else adr = alloc_one_addr(entry->h_addr); addr_list = caml_alloc_small(1, 0); diff --git a/otherlibs/unix/getnameinfo.c b/otherlibs/unix/getnameinfo.c index cd2ec336..d3721d8c 100644 --- a/otherlibs/unix/getnameinfo.c +++ b/otherlibs/unix/getnameinfo.c @@ -50,7 +50,8 @@ CAMLprim value unix_getnameinfo(value vaddr, value vopts) getnameinfo((const struct sockaddr *) &addr.s_gen, addr_len, host, sizeof(host), serv, sizeof(serv), opts); caml_leave_blocking_section(); - if (retcode != 0) caml_raise_not_found(); /* TODO: detailed error reporting? */ + /* TODO: detailed error reporting? */ + if (retcode != 0) caml_raise_not_found(); vhost = caml_copy_string(host); vserv = caml_copy_string(serv); vres = caml_alloc_small(2, 0); diff --git a/otherlibs/unix/link.c b/otherlibs/unix/link.c index 6454aaed..c5dc603b 100644 --- a/otherlibs/unix/link.c +++ b/otherlibs/unix/link.c @@ -13,14 +13,22 @@ /* */ /**************************************************************************/ +/* Needed to get linkat exposed in compliant OS. + Must be defined before the first system .h is included. */ +#define _XOPEN_SOURCE 700 + #include #include #include #include "unixsupport.h" -CAMLprim value unix_link(value path1, value path2) +#include +#include +#include + +CAMLprim value unix_link(value follow, value path1, value path2) { - CAMLparam2(path1, path2); + CAMLparam3(follow, path1, path2); char * p1; char * p2; int ret; @@ -29,7 +37,19 @@ CAMLprim value unix_link(value path1, value path2) p1 = caml_stat_strdup(String_val(path1)); p2 = caml_stat_strdup(String_val(path2)); caml_enter_blocking_section(); - ret = link(p1, p2); + if (follow == Val_int(0) /* None */) + ret = link(p1, p2); + else { /* Some bool */ +# ifdef AT_SYMLINK_FOLLOW + int flags = + Is_block(follow) && Bool_val(Field(follow, 0)) /* Some true */ + ? AT_SYMLINK_FOLLOW + : 0; + ret = linkat(AT_FDCWD, p1, AT_FDCWD, p2, flags); +# else + ret = -1; errno = ENOSYS; +# endif + } caml_leave_blocking_section(); caml_stat_free(p1); caml_stat_free(p2); diff --git a/otherlibs/unix/mmap_ba.c b/otherlibs/unix/mmap_ba.c index a9b227bb..f85bcc2f 100644 --- a/otherlibs/unix/mmap_ba.c +++ b/otherlibs/unix/mmap_ba.c @@ -40,7 +40,7 @@ CAMLextern void UNMAP_FILE_FUNCTION(void * addr, uintnat len); static void caml_ba_mapped_finalize(value v) { struct caml_ba_array * b = Caml_ba_array_val(v); - CAMLassert(b->flags & CAML_BA_MANAGED_MASK == CAML_BA_MAPPED_FILE); + CAMLassert((b->flags & CAML_BA_MANAGED_MASK) == CAML_BA_MAPPED_FILE); if (b->proxy == NULL) { UNMAP_FILE_FUNCTION(b->data, caml_ba_byte_size(b)); } else { @@ -61,7 +61,8 @@ static struct custom_operations caml_ba_mapped_ops = { caml_ba_hash, caml_ba_serialize, caml_ba_deserialize, - custom_compare_ext_default + custom_compare_ext_default, + custom_fixed_length_default }; /* [caml_ba_mapped_alloc] allocates a new bigarray object in the heap diff --git a/otherlibs/unix/signals.c b/otherlibs/unix/signals.c index 945e7d16..ff59a726 100644 --- a/otherlibs/unix/signals.c +++ b/otherlibs/unix/signals.c @@ -69,16 +69,20 @@ CAMLprim value unix_sigprocmask(value vaction, value vset) how = sigprocmask_cmd[Int_val(vaction)]; decode_sigset(vset, &set); caml_enter_blocking_section(); - retcode = sigprocmask(how, &set, &oldset); + retcode = caml_sigmask_hook(how, &set, &oldset); caml_leave_blocking_section(); - if (retcode == -1) uerror("sigprocmask", Nothing); + if (retcode != 0) unix_error(retcode, "sigprocmask", Nothing); return encode_sigset(&oldset); } CAMLprim value unix_sigpending(value unit) { sigset_t pending; + int i; if (sigpending(&pending) == -1) uerror("sigpending", Nothing); + for (i = 1; i < NSIG; i++) + if(caml_pending_signals[i]) + sigaddset(&pending, i); return encode_sigset(&pending); } diff --git a/otherlibs/unix/socketaddr.c b/otherlibs/unix/socketaddr.c index 69fc52cc..8f7eeeb1 100644 --- a/otherlibs/unix/socketaddr.c +++ b/otherlibs/unix/socketaddr.c @@ -115,7 +115,8 @@ value alloc_sockaddr(union sock_addr_union * adr /*in*/, mlsize_t path_length = strnlen(adr->s_unix.sun_path, adr_len - offsetof(struct sockaddr_un, sun_path)); - n = caml_alloc_initialized_string(path_length, (char *)adr->s_unix.sun_path); + n = caml_alloc_initialized_string(path_length, + (char *)adr->s_unix.sun_path); Begin_root (n); res = caml_alloc_small(1, 0); Field(res,0) = n; diff --git a/otherlibs/unix/times.c b/otherlibs/unix/times.c index 7ad3f59a..90e79c5a 100644 --- a/otherlibs/unix/times.c +++ b/otherlibs/unix/times.c @@ -25,14 +25,6 @@ #include #endif -#ifndef CLK_TCK -#ifdef HZ -#define CLK_TCK HZ -#else -#define CLK_TCK 60 -#endif -#endif - CAMLprim value unix_times(value unit) { #ifdef HAS_GETRUSAGE @@ -52,6 +44,14 @@ CAMLprim value unix_times(value unit) #else +#ifndef CLK_TCK +#ifdef HZ +#define CLK_TCK HZ +#else +#define CLK_TCK 60 +#endif +#endif + value res; struct tms buffer; diff --git a/otherlibs/unix/unix.ml b/otherlibs/unix/unix.ml index 95e825b2..ae9b1fc8 100644 --- a/otherlibs/unix/unix.ml +++ b/otherlibs/unix/unix.ml @@ -13,6 +13,8 @@ (* *) (**************************************************************************) +let shell = "/bin/sh" + type error = E2BIG | EACCES @@ -216,7 +218,7 @@ let execvpe_ml name args env = let argc = Array.length args in (* Drop the original args.(0) if it is there *) let new_args = Array.append - [| "/bin/sh"; file |] + [| shell; file |] (if argc = 0 then args else Array.sub args 1 (argc - 1)) in execve new_args.(0) new_args env in (* Try each path element in turn *) @@ -260,7 +262,7 @@ let execvpe_ml name args env = which looks up the PATH environment variable whether SUID or not. *) let execvpe name args env = - try + try execvpe_c name args env with Unix_error(ENOSYS, _, _) -> execvpe_ml name args env @@ -301,8 +303,8 @@ type file_perm = int external openfile : string -> open_flag list -> file_perm -> file_descr = "unix_open" - external close : file_descr -> unit = "unix_close" +external fsync : file_descr -> unit = "unix_fsync" external unsafe_read : file_descr -> bytes -> int -> int -> int = "unix_read" external unsafe_write : file_descr -> bytes -> int -> int -> int = "unix_write" @@ -332,9 +334,9 @@ let single_write_substring fd buf ofs len = single_write fd (Bytes.unsafe_of_string buf) ofs len external in_channel_of_descr : file_descr -> in_channel - = "caml_ml_open_descriptor_in" + = "unix_inchannel_of_filedescr" external out_channel_of_descr : file_descr -> out_channel - = "caml_ml_open_descriptor_out" + = "unix_outchannel_of_filedescr" external descr_of_in_channel : in_channel -> file_descr = "caml_channel_descriptor" external descr_of_out_channel : out_channel -> file_descr @@ -378,7 +380,7 @@ external fstat : file_descr -> stats = "unix_fstat" external isatty : file_descr -> bool = "unix_isatty" external unlink : string -> unit = "unix_unlink" external rename : string -> string -> unit = "unix_rename" -external link : string -> string -> unit = "unix_link" +external link : ?follow:bool -> string -> string -> unit = "unix_link" module LargeFile = struct @@ -597,7 +599,7 @@ type msg_flag = | MSG_DONTROUTE | MSG_PEEK -external socket : +external socket : ?cloexec: bool -> socket_domain -> socket_type -> int -> file_descr = "unix_socket" external socketpair : @@ -861,7 +863,7 @@ let getnameinfo_emulation addr opts = let kind = if List.mem NI_DGRAM opts then "udp" else "tcp" in (getservbyport p kind).s_name with Not_found -> - string_of_int p in + Int.to_string p in { ni_hostname = hostname; ni_service = service } let getnameinfo addr opts = @@ -941,7 +943,7 @@ external sys_exit : int -> 'a = "caml_sys_exit" let system cmd = match fork() with 0 -> begin try - execv "/bin/sh" [| "/bin/sh"; "-c"; cmd |] + execv shell [| shell; "-c"; cmd |] with _ -> sys_exit 127 end @@ -1006,26 +1008,24 @@ type popen_process = let popen_processes = (Hashtbl.create 7 : (popen_process, int) Hashtbl.t) -let open_proc cmd envopt proc input output error = - match fork() with - 0 -> perform_redirections input output error; - let shell = "/bin/sh" in - let argv = [| shell; "-c"; cmd |] in - begin try - match envopt with - | Some env -> execve shell argv env - | None -> execv shell argv - with _ -> - sys_exit 127 - end - | id -> Hashtbl.add popen_processes proc id +let open_proc prog args envopt proc input output error = + match fork() with + 0 -> perform_redirections input output error; + begin try + match envopt with + | Some env -> execve prog args env + | None -> execv prog args + with _ -> + sys_exit 127 + end + | id -> Hashtbl.add popen_processes proc id -let open_process_in cmd = +let open_process_args_in prog args = let (in_read, in_write) = pipe ~cloexec:true () in let inchan = in_channel_of_descr in_read in begin try - open_proc cmd None (Process_in inchan) stdin in_write stderr + open_proc prog args None (Process_in inchan) stdin in_write stderr with e -> close_in inchan; close in_write; @@ -1034,12 +1034,12 @@ let open_process_in cmd = close in_write; inchan -let open_process_out cmd = +let open_process_args_out prog args = let (out_read, out_write) = pipe ~cloexec:true () in let outchan = out_channel_of_descr out_write in begin try - open_proc cmd None (Process_out outchan) out_read stdout stderr + open_proc prog args None (Process_out outchan) out_read stdout stderr with e -> close_out outchan; close out_read; @@ -1048,7 +1048,7 @@ let open_process_out cmd = close out_read; outchan -let open_process cmd = +let open_process_args prog args = let (in_read, in_write) = pipe ~cloexec:true () in let (out_read, out_write) = try pipe ~cloexec:true () @@ -1057,7 +1057,8 @@ let open_process cmd = let outchan = out_channel_of_descr out_write in begin try - open_proc cmd None (Process(inchan, outchan)) out_read in_write stderr + open_proc prog args None + (Process(inchan, outchan)) out_read in_write stderr with e -> close out_read; close out_write; close in_read; close in_write; @@ -1067,7 +1068,7 @@ let open_process cmd = close in_write; (inchan, outchan) -let open_process_full cmd env = +let open_process_args_full prog args env = let (in_read, in_write) = pipe ~cloexec:true () in let (out_read, out_write) = try pipe ~cloexec:true () @@ -1081,12 +1082,12 @@ let open_process_full cmd env = let errchan = in_channel_of_descr err_read in begin try - open_proc cmd (Some env) (Process_full(inchan, outchan, errchan)) + open_proc prog args (Some env) (Process_full(inchan, outchan, errchan)) out_read in_write err_write with e -> close out_read; close out_write; close in_read; close in_write; - close err_read; close err_write; + close err_read; close err_write; raise e end; close out_read; @@ -1094,36 +1095,64 @@ let open_process_full cmd env = close err_write; (inchan, outchan, errchan) +let open_process_shell fn cmd = + fn shell [|shell; "-c"; cmd|] +let open_process_in cmd = + open_process_shell open_process_args_in cmd +let open_process_out cmd = + open_process_shell open_process_args_out cmd +let open_process cmd = + open_process_shell open_process_args cmd +let open_process_full cmd = + open_process_shell open_process_args_full cmd + let find_proc_id fun_name proc = try - let pid = Hashtbl.find popen_processes proc in - Hashtbl.remove popen_processes proc; - pid + Hashtbl.find popen_processes proc with Not_found -> raise(Unix_error(EBADF, fun_name, "")) +let remove_proc_id proc = + Hashtbl.remove popen_processes proc + +let process_in_pid inchan = + find_proc_id "process_in_pid" (Process_in inchan) +let process_out_pid outchan = + find_proc_id "process_out_pid" (Process_out outchan) +let process_pid (inchan, outchan) = + find_proc_id "process_pid" (Process(inchan, outchan)) +let process_full_pid (inchan, outchan, errchan) = + find_proc_id "process_full_pid" + (Process_full(inchan, outchan, errchan)) + let close_process_in inchan = - let pid = find_proc_id "close_process_in" (Process_in inchan) in + let proc = Process_in inchan in + let pid = find_proc_id "close_process_in" proc in + remove_proc_id proc; close_in inchan; snd(waitpid_non_intr pid) let close_process_out outchan = - let pid = find_proc_id "close_process_out" (Process_out outchan) in + let proc = Process_out outchan in + let pid = find_proc_id "close_process_out" proc in + remove_proc_id proc; (* The application may have closed [outchan] already to signal end-of-input to the process. *) begin try close_out outchan with Sys_error _ -> () end; snd(waitpid_non_intr pid) let close_process (inchan, outchan) = - let pid = find_proc_id "close_process" (Process(inchan, outchan)) in + let proc = Process(inchan, outchan) in + let pid = find_proc_id "close_process" proc in + remove_proc_id proc; close_in inchan; begin try close_out outchan with Sys_error _ -> () end; snd(waitpid_non_intr pid) let close_process_full (inchan, outchan, errchan) = - let pid = - find_proc_id "close_process_full" - (Process_full(inchan, outchan, errchan)) in + let proc = Process_full(inchan, outchan, errchan) in + let pid = find_proc_id "close_process_full" proc in + remove_proc_id proc; close_in inchan; begin try close_out outchan with Sys_error _ -> () end; close_in errchan; diff --git a/otherlibs/unix/unix.mli b/otherlibs/unix/unix.mli index 1e6b475a..84a55eac 100644 --- a/otherlibs/unix/unix.mli +++ b/otherlibs/unix/unix.mli @@ -307,6 +307,9 @@ val openfile : string -> open_flag list -> file_perm -> file_descr val close : file_descr -> unit (** Close a file descriptor. *) +val fsync : file_descr -> unit +(** Flush file buffers to disk. *) + val read : file_descr -> bytes -> int -> int -> int (** [read fd buff ofs len] reads [len] bytes from descriptor [fd], storing them in byte sequence [buff], starting at position [ofs] in @@ -426,7 +429,7 @@ type stats = st_nlink : int; (** Number of links *) st_uid : int; (** User id of the owner *) st_gid : int; (** Group ID of the file's group *) - st_rdev : int; (** Device minor number *) + st_rdev : int; (** Device ID (if special file) *) st_size : int; (** Size in bytes *) st_atime : float; (** Last access time *) st_mtime : float; (** Last modification time *) @@ -470,7 +473,7 @@ module LargeFile : st_nlink : int; (** Number of links *) st_uid : int; (** User id of the owner *) st_gid : int; (** Group ID of the file's group *) - st_rdev : int; (** Device minor number *) + st_rdev : int; (** Device ID (if special file) *) st_size : int64; (** Size in bytes *) st_atime : float; (** Last access time *) st_mtime : float; (** Last modification time *) @@ -490,17 +493,17 @@ module LargeFile : regular integers (type [int]), thus allowing operating on files whose sizes are greater than [max_int]. *) -(** {6 Mapping files into memory} *) +(** {1 Mapping files into memory} *) val map_file : file_descr -> ?pos:int64 -> ('a, 'b) Stdlib.Bigarray.kind -> 'c Stdlib.Bigarray.layout -> bool -> int array -> ('a, 'b, 'c) Stdlib.Bigarray.Genarray.t -(** Memory mapping of a file as a big array. +(** Memory mapping of a file as a Bigarray. [map_file fd kind layout shared dims] - returns a big array of kind [kind], layout [layout], + returns a Bigarray of kind [kind], layout [layout], and dimensions as specified in [dims]. The data contained in - this big array are the contents of the file referred to by + this Bigarray are the contents of the file referred to by the file descriptor [fd] (as opened previously with [Unix.openfile], for example). The optional [pos] parameter is the byte offset in the file of the data being mapped; @@ -514,10 +517,10 @@ val map_file : affected. [Genarray.map_file] is much more efficient than reading - the whole file in a big array, modifying that big array, + the whole file in a Bigarray, modifying that Bigarray, and writing it afterwards. - To adjust automatically the dimensions of the big array to + To adjust automatically the dimensions of the Bigarray to the actual size of the file, the major dimension (that is, the first dimension for an array with C layout, and the last dimension for an array with Fortran layout) can be given as @@ -526,11 +529,11 @@ val map_file : number of sub-arrays as determined by the non-major dimensions, otherwise [Failure] is raised. - If all dimensions of the big array are given, the file size is - matched against the size of the big array. If the file is larger - than the big array, only the initial portion of the file is - mapped to the big array. If the file is smaller than the big - array, the file is automatically grown to the size of the big array. + If all dimensions of the Bigarray are given, the file size is + matched against the size of the Bigarray. If the file is larger + than the Bigarray, only the initial portion of the file is + mapped to the Bigarray. If the file is smaller than the big + array, the file is automatically grown to the size of the Bigarray. This requires write permissions on [fd]. Array accesses are bounds-checked, but the bounds are determined by @@ -564,9 +567,19 @@ val rename : string -> string -> unit owner, etc) of [new] can either be preserved or be replaced by those of [old]. *) -val link : string -> string -> unit -(** [link source dest] creates a hard link named [dest] to the file - named [source]. *) +val link : ?follow:bool -> string -> string -> unit +(** [link ?follow source dest] creates a hard link named [dest] to the file + named [source]. + + @param follow indicates whether a [source] symlink is followed or a + hardlink to [source] itself will be created. On {e Unix} systems this is + done using the [linkat(2)] function. If [?follow] is not provided, then the + [link(2)] function is used whose behaviour is OS-dependent, but more widely + available. + + @raise ENOSYS On {e Unix} if [~follow:_] is requested, but linkat is + unavailable. + @raise ENOSYS On {e Windows} if [~follow:false] is requested. *) (** {1 File permissions and ownership} *) @@ -646,7 +659,7 @@ val set_close_on_exec : file_descr -> unit to the private file and can do bad things with it. Hence, it is highly recommended to set all file descriptors ``close-on-exec'', except in the very few cases where a file descriptor actually needs - to be transmitted to another program. + to be transmitted to another program. The best way to set a file descriptor ``close-on-exec'' is to create it in this state. To this end, the [openfile] function has @@ -778,7 +791,7 @@ val open_process_out : string -> out_channel the command to a pipe. Data written to the returned output channel is sent to the standard input of the command. Warning: writes on output channels are buffered, hence be careful - to call {!Pervasives.flush} at the right times to ensure + to call {!Stdlib.flush} at the right times to ensure correct synchronization. *) val open_process : string -> in_channel * out_channel @@ -794,6 +807,66 @@ val open_process_full : of channels connected respectively to the standard output, standard input, and standard error of the command. *) +val open_process_args_in : string -> string array -> in_channel +(** High-level pipe and process management. The first argument specifies the + command to run, and the second argument specifies the argument array passed + to the command. This function runs the command in parallel with the program. + The standard output of the command is redirected to a pipe, which can be read + via the returned input channel. + + @since 4.08.0 *) + +val open_process_args_out : string -> string array -> out_channel +(** Same as {!Unix.open_process_args_in}, but redirect the standard input of the + command to a pipe. Data written to the returned output channel is sent to + the standard input of the command. Warning: writes on output channels are + buffered, hence be careful to call {!Stdlib.flush} at the right times to + ensure correct synchronization. + + @since 4.08.0 *) + +val open_process_args : string -> string array -> in_channel * out_channel +(** Same as {!Unix.open_process_args_out}, but redirects both the standard input + and standard output of the command to pipes connected to the two returned + channels. The input channel is connected to the output of the command, and + the output channel to the input of the command. + + @since 4.08.0 *) + +val open_process_args_full : + string -> string array -> string array -> + in_channel * out_channel * in_channel +(** Similar to {!Unix.open_process_args}, but the third argument specifies the + environment passed to the command. The result is a triple of channels + connected respectively to the standard output, standard input, and standard + error of the command. + + @since 4.08.0 *) + +val process_in_pid : in_channel -> int +(** Return the pid of a process opened via {!Unix.open_process_in} or + {!Unix.open_process_args_in}. + + @since 4.08.0 *) + +val process_out_pid : out_channel -> int +(** Return the pid of a process opened via {!Unix.open_process_out} or + {!Unix.open_process_args_out}. + + @since 4.08.0 *) + +val process_pid : in_channel * out_channel -> int +(** Return the pid of a process opened via {!Unix.open_process} or + {!Unix.open_process_args}. + + @since 4.08.0 *) + +val process_full_pid : in_channel * out_channel * in_channel -> int +(** Return the pid of a process opened via {!Unix.open_process_full} or + {!Unix.open_process_args_full}. + + @since 4.08.0 *) + val close_process_in : in_channel -> process_status (** Close channels opened by {!Unix.open_process_in}, wait for the associated command to terminate, @@ -950,6 +1023,10 @@ val sigprocmask : sigprocmask_command -> int list -> int list from the set of blocked signals. [sigprocmask] returns the set of previously blocked signals. + When the systhreads version of the [Thread] module is loaded, this + function redirects to [Thread.sigmask]. I.e., [sigprocmask] only + changes the mask of the current thread. + On Windows: not implemented (no inter-process signals on Windows). *) val sigpending : unit -> int list @@ -1415,7 +1492,7 @@ val getsockopt_error : file_descr -> error option val open_connection : sockaddr -> in_channel * out_channel (** Connect to a server at the given address. Return a pair of buffered channels connected to the server. - Remember to call {!Pervasives.flush} on the output channel at the right + Remember to call {!Stdlib.flush} on the output channel at the right times to ensure correct synchronization. *) val shutdown_connection : in_channel -> unit @@ -1423,7 +1500,7 @@ val shutdown_connection : in_channel -> unit that is, transmit an end-of-file condition to the server reading on the other side of the connection. This does not fully close the file descriptor associated with the channel, which you must remember - to free via {!Pervasives.close_in}. *) + to free via {!Stdlib.close_in}. *) val establish_server : (in_channel -> out_channel -> unit) -> sockaddr -> unit (** Establish a server on the given address. diff --git a/otherlibs/unix/unixLabels.mli b/otherlibs/unix/unixLabels.mli index a78738bb..16c066a1 100644 --- a/otherlibs/unix/unixLabels.mli +++ b/otherlibs/unix/unixLabels.mli @@ -370,7 +370,7 @@ type stats = Unix.stats = st_nlink : int; (** Number of links *) st_uid : int; (** User id of the owner *) st_gid : int; (** Group ID of the file's group *) - st_rdev : int; (** Device minor number *) + st_rdev : int; (** Device ID (if special file) *) st_size : int; (** Size in bytes *) st_atime : float; (** Last access time *) st_mtime : float; (** Last modification time *) @@ -408,7 +408,7 @@ module LargeFile : st_nlink : int; (** Number of links *) st_uid : int; (** User id of the owner *) st_gid : int; (** Group ID of the file's group *) - st_rdev : int; (** Device minor number *) + st_rdev : int; (** Device ID (if special file) *) st_size : int64; (** Size in bytes *) st_atime : float; (** Last access time *) st_mtime : float; (** Last modification time *) @@ -436,11 +436,11 @@ val map_file : file_descr -> ?pos:int64 -> kind:('a, 'b) Stdlib.Bigarray.kind -> layout:'c Stdlib.Bigarray.layout -> shared:bool -> dims:int array -> ('a, 'b, 'c) Stdlib.Bigarray.Genarray.t -(** Memory mapping of a file as a big array. +(** Memory mapping of a file as a Bigarray. [map_file fd kind layout shared dims] - returns a big array of kind [kind], layout [layout], + returns a Bigarray of kind [kind], layout [layout], and dimensions as specified in [dims]. The data contained in - this big array are the contents of the file referred to by + this Bigarray are the contents of the file referred to by the file descriptor [fd] (as opened previously with [Unix.openfile], for example). The optional [pos] parameter is the byte offset in the file of the data being mapped; @@ -454,10 +454,10 @@ val map_file : affected. [Genarray.map_file] is much more efficient than reading - the whole file in a big array, modifying that big array, + the whole file in a Bigarray, modifying that Bigarray, and writing it afterwards. - To adjust automatically the dimensions of the big array to + To adjust automatically the dimensions of the Bigarray to the actual size of the file, the major dimension (that is, the first dimension for an array with C layout, and the last dimension for an array with Fortran layout) can be given as @@ -466,11 +466,11 @@ val map_file : number of sub-arrays as determined by the non-major dimensions, otherwise [Failure] is raised. - If all dimensions of the big array are given, the file size is - matched against the size of the big array. If the file is larger - than the big array, only the initial portion of the file is - mapped to the big array. If the file is smaller than the big - array, the file is automatically grown to the size of the big array. + If all dimensions of the Bigarray are given, the file size is + matched against the size of the Bigarray. If the file is larger + than the Bigarray, only the initial portion of the file is + mapped to the Bigarray. If the file is smaller than the big + array, the file is automatically grown to the size of the Bigarray. This requires write permissions on [fd]. Array accesses are bounds-checked, but the bounds are determined by @@ -492,9 +492,19 @@ val unlink : string -> unit val rename : src:string -> dst:string -> unit (** [rename old new] changes the name of a file from [old] to [new]. *) -val link : src:string -> dst:string -> unit -(** [link source dest] creates a hard link named [dest] to the file - named [source]. *) +val link : ?follow:bool -> src:string -> dst:string -> unit +(** [link ?follow source dest] creates a hard link named [dest] to the file + named [source]. + + @param follow indicates whether a [source] symlink is followed or a + hardlink to [source] itself will be created. On {e Unix} systems this is + done using the [linkat(2)] function. If [?follow] is not provided, then the + [link(2)] function is used whose behaviour is OS-dependent, but more widely + available. + + @raise ENOSYS On {e Unix} if [~follow:_] is requested, but linkat is + unavailable. + @raise ENOSYS On {e Windows} if [~follow:false] is requested. *) (** {1 File permissions and ownership} *) @@ -650,7 +660,7 @@ val open_process_out : string -> out_channel the command to a pipe. Data written to the returned output channel is sent to the standard input of the command. Warning: writes on output channels are buffered, hence be careful - to call {!Pervasives.flush} at the right times to ensure + to call {!Stdlib.flush} at the right times to ensure correct synchronization. *) val open_process : string -> in_channel * out_channel @@ -666,6 +676,42 @@ val open_process_full : of channels connected respectively to the standard output, standard input, and standard error of the command. *) +val open_process_args_in : string -> string array -> in_channel +(** High-level pipe and process management. The first argument specifies the + command to run, and the second argument specifies the argument array passed + to the command. This function runs the command in parallel with the program. + The standard output of the command is redirected to a pipe, which can be read + via the returned input channel. + + @since 4.08.0 *) + +val open_process_args_out : string -> string array -> out_channel +(** Same as {!Unix.open_process_args_in}, but redirect the standard input of the + command to a pipe. Data written to the returned output channel is sent to + the standard input of the command. Warning: writes on output channels are + buffered, hence be careful to call {!Stdlib.flush} at the right times to + ensure correct synchronization. + + @since 4.08.0 *) + +val open_process_args : string -> string array -> in_channel * out_channel +(** Same as {!Unix.open_process_args_out}, but redirects both the standard input + and standard output of the command to pipes connected to the two returned + channels. The input channel is connected to the output of the command, and + the output channel to the input of the command. + + @since 4.08.0 *) + +val open_process_args_full : + string -> string array -> string array -> + in_channel * out_channel * in_channel +(** Similar to {!Unix.open_process_args}, but the third argument specifies the + environment passed to the command. The result is a triple of channels + connected respectively to the standard output, standard input, and standard + error of the command. + + @since 4.08.0 *) + val close_process_in : in_channel -> process_status (** Close channels opened by {!UnixLabels.open_process_in}, wait for the associated command to terminate, @@ -1206,7 +1252,7 @@ val getsockopt_error : file_descr -> error option val open_connection : sockaddr -> in_channel * out_channel (** Connect to a server at the given address. Return a pair of buffered channels connected to the server. - Remember to call {!Pervasives.flush} on the output channel at the right + Remember to call {!Stdlib.flush} on the output channel at the right times to ensure correct synchronization. *) val shutdown_connection : in_channel -> unit diff --git a/otherlibs/win32graph/Makefile b/otherlibs/win32graph/Makefile index 85d683c5..66cd62b2 100644 --- a/otherlibs/win32graph/Makefile +++ b/otherlibs/win32graph/Makefile @@ -20,7 +20,7 @@ WIN32LIBS=$(call SYSLIB,kernel32) $(call SYSLIB,gdi32) $(call SYSLIB,user32) LINKOPTS=-cclib "\"$(WIN32LIBS)\"" LDOPTS=-ldopt "$(WIN32LIBS)" -include ../Makefile +include ../Makefile.otherlibs.common graphics.ml: ../graph/graphics.ml cp ../graph/graphics.ml graphics.ml diff --git a/otherlibs/win32graph/Makefile.nt b/otherlibs/win32graph/Makefile.nt deleted file mode 100644 index 39ad54ae..00000000 --- a/otherlibs/win32graph/Makefile.nt +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 2001 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include Makefile diff --git a/otherlibs/win32graph/draw.c b/otherlibs/win32graph/draw.c index d33d12b6..3c76eb8a 100644 --- a/otherlibs/win32graph/draw.c +++ b/otherlibs/win32graph/draw.c @@ -447,7 +447,8 @@ static struct custom_operations image_ops = { custom_hash_default, custom_serialize_default, custom_deserialize_default, - custom_compare_ext_default + custom_compare_ext_default, + custom_fixed_length_default }; CAMLprim value caml_gr_create_image(value vw, value vh) diff --git a/otherlibs/win32graph/open.c b/otherlibs/win32graph/open.c index d1db56e0..3bde8a2f 100644 --- a/otherlibs/win32graph/open.c +++ b/otherlibs/win32graph/open.c @@ -359,8 +359,8 @@ void gr_fail(char *fmt, char *arg) if (graphic_failure_exn == NULL) { graphic_failure_exn = caml_named_value("Graphics.Graphic_failure"); if (graphic_failure_exn == NULL) - caml_invalid_argument("Exception Graphics.Graphic_failure not initialized, " - "must link graphics.cma"); + caml_invalid_argument("Exception Graphics.Graphic_failure not " + "initialized, must link graphics.cma"); } sprintf(buffer, fmt, arg); caml_raise_with_string(*graphic_failure_exn, buffer); diff --git a/otherlibs/win32unix/.depend b/otherlibs/win32unix/.depend index 000683a0..6de1127e 100644 --- a/otherlibs/win32unix/.depend +++ b/otherlibs/win32unix/.depend @@ -1,18 +1,25 @@ windbug.$(O): windbug.c windbug.h -cst2constr.$(O): cst2constr.c ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/misc.h \ - ../../byterun/caml/fail.h ../unix/cst2constr.h -mmap_ba.$(O): mmap_ba.c ../../byterun/caml/alloc.h ../../byterun/caml/misc.h \ - ../../byterun/caml/config.h ../../byterun/caml/m.h \ - ../../byterun/caml/s.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/bigarray.h ../../byterun/caml/custom.h \ - ../../byterun/caml/memory.h ../../byterun/caml/gc.h \ - ../../byterun/caml/major_gc.h ../../byterun/caml/freelist.h \ - ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h -unix.cmo : unix.cmi -unix.cmx : unix.cmi +cst2constr.$(O): cst2constr.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/fail.h ../unix/cst2constr.h +mmap_ba.$(O): mmap_ba.c ../../runtime/caml/alloc.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/bigarray.h ../../runtime/caml/custom.h \ + ../../runtime/caml/memory.h ../../runtime/caml/gc.h \ + ../../runtime/caml/major_gc.h ../../runtime/caml/freelist.h \ + ../../runtime/caml/minor_gc.h ../../runtime/caml/address_class.h +unix.cmo : \ + unix.cmi +unix.cmx : \ + unix.cmi unix.cmi : -unixLabels.cmo : unix.cmi unixLabels.cmi -unixLabels.cmx : unix.cmx unixLabels.cmi -unixLabels.cmi : unix.cmi +unixLabels.cmo : \ + unix.cmi \ + unixLabels.cmi +unixLabels.cmx : \ + unix.cmx \ + unixLabels.cmi +unixLabels.cmi : \ + unix.cmi diff --git a/otherlibs/win32unix/Makefile b/otherlibs/win32unix/Makefile index 31607eed..ffcb1afc 100644 --- a/otherlibs/win32unix/Makefile +++ b/otherlibs/win32unix/Makefile @@ -34,7 +34,7 @@ UNIX_FILES = access.c addrofstr.c chdir.c chmod.c cst2constr.c \ exit.c getaddrinfo.c getcwd.c gethost.c gethostname.c \ getnameinfo.c getproto.c \ getserv.c gmtime.c mmap_ba.c putenv.c rmdir.c \ - socketaddr.c strofaddr.c time.c unlink.c + socketaddr.c strofaddr.c time.c unlink.c fsync.c UNIX_CAML_FILES = unix.mli unixLabels.mli unixLabels.ml @@ -50,7 +50,7 @@ EXTRACFLAGS=-I../unix HEADERS=unixsupport.h socketaddr.h -include ../Makefile +include ../Makefile.otherlibs.common ifeq "$(SYSTEM)" "mingw" LDOPTS=-ldopt "-link -static-libgcc" $(addprefix -ldopt ,$(WIN32_LIBS)) @@ -70,9 +70,9 @@ depend: $(error Dependencies cannot be regenerated using the MSVC ports) else depend: $(ALL_FILES) $(UNIX_CAML_FILES) unix.ml - $(CC) -MM $(CPPFLAGS) -I../unix $(ALL_FILES) \ + $(CC) -MM $(OC_CPPFLAGS) -I../unix $(ALL_FILES) \ | sed -e 's/\.o/.$$(O)/g' > .depend - $(CAMLRUN) $(ROOTDIR)/tools/ocamldep -slash $(UNIX_CAML_FILES) \ + $(CAMLRUN) $(ROOTDIR)/boot/ocamlc -depend -slash $(UNIX_CAML_FILES) \ unix.ml >> .depend endif diff --git a/otherlibs/win32unix/Makefile.nt b/otherlibs/win32unix/Makefile.nt deleted file mode 100644 index ed9900bb..00000000 --- a/otherlibs/win32unix/Makefile.nt +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include Makefile diff --git a/otherlibs/win32unix/channels.c b/otherlibs/win32unix/channels.c index 5dbc86f4..863ca431 100644 --- a/otherlibs/win32unix/channels.c +++ b/otherlibs/win32unix/channels.c @@ -23,6 +23,42 @@ #include #include +/* Check that the given file descriptor has "stream semantics" and + can therefore be used as part of buffered I/O. Things that + don't have "stream semantics" include block devices and + UDP (datagram) sockets. + Returns 0 if OK, a Win32 error code if error. */ + +static DWORD win_check_stream_semantics(value handle) +{ + switch (Descr_kind_val(handle)) { + case KIND_HANDLE: + switch (GetFileType(Handle_val(handle)) & ~FILE_TYPE_REMOTE) { + case FILE_TYPE_DISK: case FILE_TYPE_CHAR: case FILE_TYPE_PIPE: + return 0; + default: { + DWORD err = GetLastError(); + return err == NO_ERROR ? ERROR_INVALID_ACCESS : err; + } + } + case KIND_SOCKET: { + int so_type; + int so_type_len = sizeof(so_type); + if (getsockopt(Socket_val(handle), SOL_SOCKET, SO_TYPE, + (void *) &so_type, &so_type_len) != 0) + return WSAGetLastError(); + switch (so_type) { + case SOCK_STREAM: + return 0; + default: + return ERROR_INVALID_ACCESS; + } + } + default: + return ERROR_INVALID_ACCESS; + } +} + int win_CRT_fd_of_filedescr(value handle) { if (CRT_fd_val(handle) != NO_CRT_FD) { @@ -40,10 +76,13 @@ CAMLprim value win_inchannel_of_filedescr(value handle) CAMLparam1(handle); CAMLlocal1(vchan); struct channel * chan; + DWORD err; #if defined(_MSC_VER) && _MSC_VER < 1400 fflush(stdin); #endif + err = win_check_stream_semantics(handle); + if (err != 0) { win32_maperr(err); uerror("in_channel_of_descr", Nothing); } chan = caml_open_descriptor_in(win_CRT_fd_of_filedescr(handle)); chan->flags |= CHANNEL_FLAG_MANAGED_BY_GC; /* as in caml_ml_open_descriptor_in() */ @@ -59,7 +98,10 @@ CAMLprim value win_outchannel_of_filedescr(value handle) CAMLlocal1(vchan); int fd; struct channel * chan; + DWORD err; + err = win_check_stream_semantics(handle); + if (err != 0) { win32_maperr(err); uerror("out_channel_of_descr", Nothing); } chan = caml_open_descriptor_out(win_CRT_fd_of_filedescr(handle)); chan->flags |= CHANNEL_FLAG_MANAGED_BY_GC; /* as in caml_ml_open_descriptor_out() */ diff --git a/otherlibs/win32unix/createprocess.c b/otherlibs/win32unix/createprocess.c index e1a13441..d238e53e 100644 --- a/otherlibs/win32unix/createprocess.c +++ b/otherlibs/win32unix/createprocess.c @@ -24,8 +24,9 @@ static int win_has_console(void); -static DWORD do_create_process_native(wchar_t * exefile, wchar_t * cmdline, wchar_t * env, - HANDLE fd1, HANDLE fd2, HANDLE fd3, HANDLE * hProcess) +static DWORD do_create_process_native(wchar_t * exefile, wchar_t * cmdline, + wchar_t * env, HANDLE fd1, HANDLE fd2, + HANDLE fd3, HANDLE * hProcess) { PROCESS_INFORMATION pi; STARTUPINFO si; @@ -100,16 +101,20 @@ value win_create_process_native(value cmd, value cmdline, value env, if (env != Val_int(0)) { env = Field(env, 0); - size = win_multi_byte_to_wide_char(String_val(env), caml_string_length(env), NULL, 0); + size = + win_multi_byte_to_wide_char(String_val(env), + caml_string_length(env), NULL, 0); wenv = caml_stat_alloc((size + 1)*sizeof(wchar_t)); - win_multi_byte_to_wide_char(String_val(env), caml_string_length(env), wenv, size); + win_multi_byte_to_wide_char(String_val(env), + caml_string_length(env), wenv, size); wenv[size] = 0; } else { wenv = NULL; } - err = do_create_process_native(exefile, wcmdline, wenv, - Handle_val(fd1), Handle_val(fd2), Handle_val(fd3), &hProcess); + err = + do_create_process_native(exefile, wcmdline, wenv, Handle_val(fd1), + Handle_val(fd2), Handle_val(fd3), &hProcess); if (wenv != NULL) caml_stat_free(wenv); caml_stat_free(wcmdline); diff --git a/otherlibs/win32unix/errmsg.c b/otherlibs/win32unix/errmsg.c index aea3fd0b..d910df55 100644 --- a/otherlibs/win32unix/errmsg.c +++ b/otherlibs/win32unix/errmsg.c @@ -41,6 +41,7 @@ CAMLprim value unix_error_message(value err) sizeof(buffer)/sizeof(wchar_t), NULL)) return caml_copy_string_of_utf16(buffer); - swprintf(buffer, sizeof(buffer)/sizeof(wchar_t), L"unknown error #%d", errnum); + swprintf(buffer, sizeof(buffer)/sizeof(wchar_t), + L"unknown error #%d", errnum); return caml_copy_string_of_utf16(buffer); } diff --git a/otherlibs/win32unix/link.c b/otherlibs/win32unix/link.c index 51dc7c06..32ea0023 100644 --- a/otherlibs/win32unix/link.c +++ b/otherlibs/win32unix/link.c @@ -20,6 +20,7 @@ #include #include #include "unixsupport.h" +#include #include typedef @@ -29,12 +30,16 @@ BOOL (WINAPI *tCreateHardLink)( LPSECURITY_ATTRIBUTES lpSecurityAttributes ); -CAMLprim value unix_link(value path1, value path2) +CAMLprim value unix_link(value follow, value path1, value path2) { HMODULE hModKernel32; tCreateHardLink pCreateHardLink; BOOL result; wchar_t * wpath1, * wpath2; + if (Is_block(follow) && !Bool_val(Field(follow, 0))) { /* Some false */ + errno = ENOSYS; + uerror("link", path2); + } hModKernel32 = GetModuleHandle(L"KERNEL32.DLL"); pCreateHardLink = (tCreateHardLink) GetProcAddress(hModKernel32, "CreateHardLinkW"); diff --git a/otherlibs/win32unix/lockf.c b/otherlibs/win32unix/lockf.c index 83bf4a96..f48e7ce6 100644 --- a/otherlibs/win32unix/lockf.c +++ b/otherlibs/win32unix/lockf.c @@ -124,7 +124,7 @@ CAMLprim value unix_lockf(value fd, value cmd, value span) err = GetLastError(); break; case 3: /* F_TEST - check whether a write lock can be obtained */ - /* I'm doing this by aquiring an immediate write + /* I'm doing this by acquiring an immediate write * lock and then releasing it. It is not clear that * this behavior matches anything in particular, but * it is not clear the nature of the lock test performed diff --git a/otherlibs/win32unix/mmap.c b/otherlibs/win32unix/mmap.c index 75cfb2a3..6a97e7f0 100644 --- a/otherlibs/win32unix/mmap.c +++ b/otherlibs/win32unix/mmap.c @@ -180,7 +180,8 @@ static void caml_ba_sys_error(void) buffer, sizeof(buffer)/sizeof(wchar_t), NULL)) - swprintf(buffer, sizeof(buffer)/sizeof(wchar_t), L"Unknown error %ld\n", errnum); + swprintf(buffer, sizeof(buffer)/sizeof(wchar_t), + L"Unknown error %ld\n", errnum); caml_raise_sys_error(caml_copy_string_of_utf16(buffer)); } diff --git a/otherlibs/win32unix/readlink.c b/otherlibs/win32unix/readlink.c index b57e525c..381ec868 100644 --- a/otherlibs/win32unix/readlink.c +++ b/otherlibs/win32unix/readlink.c @@ -75,9 +75,13 @@ CAMLprim value unix_readlink(value opath) if (point->ReparseTag == IO_REPARSE_TAG_SYMLINK) { int cbLen = point->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR); int len; - len = win_wide_char_to_multi_byte(point->SymbolicLinkReparseBuffer.PathBuffer + point->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR), cbLen, NULL, 0); + len = + win_wide_char_to_multi_byte( + point->SymbolicLinkReparseBuffer.PathBuffer + point->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR), + cbLen, NULL, 0); result = caml_alloc_string(len); - win_wide_char_to_multi_byte(point->SymbolicLinkReparseBuffer.PathBuffer + point->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR), + win_wide_char_to_multi_byte( + point->SymbolicLinkReparseBuffer.PathBuffer + point->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR), cbLen, String_val(result), len); diff --git a/otherlibs/win32unix/select.c b/otherlibs/win32unix/select.c index dd263869..203c18ae 100644 --- a/otherlibs/win32unix/select.c +++ b/otherlibs/win32unix/select.c @@ -630,7 +630,7 @@ LPSELECTDATA socket_poll_add (LPSELECTDATA lpSelectData, candidate = NULL; aQueries = NULL; - /* Polling socket can be done mulitple handle at the same time. You just + /* Polling socket can be done multiple handle at the same time. You just need one worker to use it. Try to find if there is already a worker handling this kind of request. Only one event can be associated with a given socket which means diff --git a/otherlibs/win32unix/unix.ml b/otherlibs/win32unix/unix.ml index b999dd72..315ca8e6 100644 --- a/otherlibs/win32unix/unix.ml +++ b/otherlibs/win32unix/unix.ml @@ -182,6 +182,7 @@ type file_perm = int external openfile : string -> open_flag list -> file_perm -> file_descr = "unix_open" external close : file_descr -> unit = "unix_close" +external fsync : file_descr -> unit = "unix_fsync" external unsafe_read : file_descr -> bytes -> int -> int -> int = "unix_read" external unsafe_write : file_descr -> bytes -> int -> int -> int @@ -265,7 +266,7 @@ external isatty : file_descr -> bool = "unix_isatty" external unlink : string -> unit = "unix_unlink" external rename : string -> string -> unit = "unix_rename" -external link : string -> string -> unit = "unix_link" +external link : ?follow:bool -> string -> string -> unit = "unix_link" (* Operations on large files *) @@ -401,10 +402,12 @@ external symlink_stub : bool -> string -> string -> unit = "unix_symlink" Windows call GetFullPathName to do this because we need relative paths to stay relative. *) let normalize_slashes path = - if String.length path >= 4 && path.[0] = '\\' && path.[1] = '\\' && path.[2] = '?' && path.[3] = '\\' then + if String.length path >= 4 && path.[0] = '\\' && path.[1] = '\\' + && path.[2] = '?' && path.[3] = '\\' then path else - String.init (String.length path) (fun i -> match path.[i] with '/' -> '\\' | c -> c) + String.init (String.length path) + (fun i -> match path.[i] with '/' -> '\\' | c -> c) let symlink ?to_dir source dest = let to_dir = @@ -579,7 +582,8 @@ type msg_flag = external socket : ?cloexec: bool -> socket_domain -> socket_type -> int -> file_descr = "unix_socket" -let socketpair ?cloexec:_ _dom _ty _proto = invalid_arg "Unix.socketpair not implemented" +let socketpair ?cloexec:_ _dom _ty _proto = + invalid_arg "Unix.socketpair not implemented" external accept : ?cloexec: bool -> file_descr -> file_descr * sockaddr = "unix_accept" external bind : file_descr -> sockaddr -> unit = "unix_bind" @@ -840,7 +844,7 @@ let getnameinfo_emulation addr opts = let kind = if List.mem NI_DGRAM opts then "udp" else "tcp" in (getservbyport p kind).s_name with Not_found -> - string_of_int p in + Int.to_string p in { ni_hostname = hostname; ni_service = service } let getnameinfo addr opts = @@ -889,21 +893,18 @@ type popen_process = let popen_processes = (Hashtbl.create 7 : (popen_process, int) Hashtbl.t) -let open_proc cmd optenv proc input output error = - let shell = - try Sys.getenv "COMSPEC" - with Not_found -> raise(Unix_error(ENOEXEC, "open_proc", cmd)) in +let open_proc prog cmdline optenv proc input output error = let pid = - win_create_process shell (shell ^ " /c " ^ cmd) optenv + win_create_process prog cmdline optenv input output error in Hashtbl.add popen_processes proc pid -let open_process_in cmd = +let open_process_cmdline_in prog cmdline = let (in_read, in_write) = pipe ~cloexec:true () in let inchan = in_channel_of_descr in_read in begin try - open_proc cmd None (Process_in inchan) stdin in_write stderr + open_proc prog cmdline None (Process_in inchan) stdin in_write stderr with e -> close_in inchan; close in_write; @@ -912,12 +913,12 @@ let open_process_in cmd = close in_write; inchan -let open_process_out cmd = +let open_process_cmdline_out prog cmdline = let (out_read, out_write) = pipe ~cloexec:true () in let outchan = out_channel_of_descr out_write in begin try - open_proc cmd None (Process_out outchan) out_read stdout stderr + open_proc prog cmdline None (Process_out outchan) out_read stdout stderr with e -> close_out outchan; close out_read; @@ -926,7 +927,7 @@ let open_process_out cmd = close out_read; outchan -let open_process cmd = +let open_process_cmdline prog cmdline = let (in_read, in_write) = pipe ~cloexec:true () in let (out_read, out_write) = try pipe ~cloexec:true () @@ -935,7 +936,8 @@ let open_process cmd = let outchan = out_channel_of_descr out_write in begin try - open_proc cmd None (Process(inchan, outchan)) out_read in_write stderr + open_proc prog cmdline None + (Process(inchan, outchan)) out_read in_write stderr with e -> close out_read; close out_write; close in_read; close in_write; @@ -945,7 +947,7 @@ let open_process cmd = close in_write; (inchan, outchan) -let open_process_full cmd env = +let open_process_cmdline_full prog cmdline env = let (in_read, in_write) = pipe ~cloexec:true () in let (out_read, out_write) = try pipe ~cloexec:true () @@ -959,7 +961,7 @@ let open_process_full cmd env = let errchan = in_channel_of_descr err_read in begin try - open_proc cmd (Some (make_process_env env)) + open_proc prog cmdline (Some (make_process_env env)) (Process_full(inchan, outchan, errchan)) out_read in_write err_write with e -> @@ -973,33 +975,73 @@ let open_process_full cmd env = close err_write; (inchan, outchan, errchan) +let open_process_args_in prog args = + open_process_cmdline_in prog (make_cmdline args) +let open_process_args_out prog args = + open_process_cmdline_out prog (make_cmdline args) +let open_process_args prog args = + open_process_cmdline prog (make_cmdline args) +let open_process_args_full prog args = + open_process_cmdline_full prog (make_cmdline args) + +let open_process_shell fn cmd = + let shell = + try Sys.getenv "COMSPEC" + with Not_found -> raise(Unix_error(ENOEXEC, "open_process_shell", cmd)) in + fn shell (shell ^ " /c " ^ cmd) +let open_process_in cmd = + open_process_shell open_process_cmdline_in cmd +let open_process_out cmd = + open_process_shell open_process_cmdline_out cmd +let open_process cmd = + open_process_shell open_process_cmdline cmd +let open_process_full cmd = + open_process_shell open_process_cmdline_full cmd + let find_proc_id fun_name proc = try - let pid = Hashtbl.find popen_processes proc in - Hashtbl.remove popen_processes proc; - pid + Hashtbl.find popen_processes proc with Not_found -> raise(Unix_error(EBADF, fun_name, "")) +let remove_proc_id proc = + Hashtbl.remove popen_processes proc + +let process_in_pid inchan = + find_proc_id "process_in_pid" (Process_in inchan) +let process_out_pid outchan = + find_proc_id "process_out_pid" (Process_out outchan) +let process_pid (inchan, outchan) = + find_proc_id "process_pid" (Process(inchan, outchan)) +let process_full_pid (inchan, outchan, errchan) = + find_proc_id "process_full_pid" + (Process_full(inchan, outchan, errchan)) + let close_process_in inchan = - let pid = find_proc_id "close_process_in" (Process_in inchan) in + let proc = Process_in inchan in + let pid = find_proc_id "close_process_in" proc in + remove_proc_id proc; close_in inchan; snd(waitpid [] pid) let close_process_out outchan = - let pid = find_proc_id "close_process_out" (Process_out outchan) in + let proc = Process_out outchan in + let pid = find_proc_id "close_process_out" proc in + remove_proc_id proc; close_out outchan; snd(waitpid [] pid) let close_process (inchan, outchan) = - let pid = find_proc_id "close_process" (Process(inchan, outchan)) in + let proc = Process(inchan, outchan) in + let pid = find_proc_id "close_process" proc in + remove_proc_id proc; close_in inchan; close_out outchan; snd(waitpid [] pid) let close_process_full (inchan, outchan, errchan) = - let pid = - find_proc_id "close_process_full" - (Process_full(inchan, outchan, errchan)) in + let proc = Process_full(inchan, outchan, errchan) in + let pid = find_proc_id "close_process_full" proc in + remove_proc_id proc; close_in inchan; close_out outchan; close_in errchan; snd(waitpid [] pid) diff --git a/otherlibs/win32unix/unixsupport.c b/otherlibs/win32unix/unixsupport.c index 4ed2383b..71769e94 100644 --- a/otherlibs/win32unix/unixsupport.c +++ b/otherlibs/win32unix/unixsupport.c @@ -45,12 +45,14 @@ static struct custom_operations win_handle_ops = { win_handle_hash, custom_serialize_default, custom_deserialize_default, - custom_compare_ext_default + custom_compare_ext_default, + custom_fixed_length_default }; value win_alloc_handle(HANDLE h) { - value res = caml_alloc_custom(&win_handle_ops, sizeof(struct filedescr), 0, 1); + value res = + caml_alloc_custom(&win_handle_ops, sizeof(struct filedescr), 0, 1); Handle_val(res) = h; Descr_kind_val(res) = KIND_HANDLE; CRT_fd_val(res) = NO_CRT_FD; @@ -60,7 +62,8 @@ value win_alloc_handle(HANDLE h) value win_alloc_socket(SOCKET s) { - value res = caml_alloc_custom(&win_handle_ops, sizeof(struct filedescr), 0, 1); + value res = + caml_alloc_custom(&win_handle_ops, sizeof(struct filedescr), 0, 1); Socket_val(res) = s; Descr_kind_val(res) = KIND_SOCKET; CRT_fd_val(res) = NO_CRT_FD; diff --git a/otherlibs/win32unix/utimes.c b/otherlibs/win32unix/utimes.c index 486119d4..cf448c2a 100644 --- a/otherlibs/win32unix/utimes.c +++ b/otherlibs/win32unix/utimes.c @@ -30,7 +30,8 @@ static void convert_time(double unixTime, FILETIME* ft) /* There are 11644473600 seconds between 1 January 1601 (the NT Epoch) and 1 * January 1970 (the Unix Epoch). FILETIME is measured in 100ns ticks. */ - u.QuadPart = (ULONGLONG)(unixTime * 10000000.0) + INT64_LITERAL(116444736000000000U); + u.QuadPart = + (ULONGLONG)(unixTime * 10000000.0) + INT64_LITERAL(116444736000000000U); ft->dwLowDateTime = u.LowPart; ft->dwHighDateTime = u.HighPart; } @@ -52,7 +53,11 @@ CAMLprim value unix_utimes(value path, value atime, value mtime) caml_enter_blocking_section(); hFile = CreateFile(wpath, FILE_WRITE_ATTRIBUTES, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); caml_leave_blocking_section(); caml_stat_free(wpath); if (hFile == INVALID_HANDLE_VALUE) { diff --git a/otherlibs/win32unix/winworker.c b/otherlibs/win32unix/winworker.c index 8007bc2d..17ac60f5 100644 --- a/otherlibs/win32unix/winworker.c +++ b/otherlibs/win32unix/winworker.c @@ -182,7 +182,7 @@ LPWORKER worker_pop (void) } nWorkersCurrent++; nWorkersMax = (nWorkersCurrent > nWorkersMax ? nWorkersCurrent : nWorkersMax); - DEBUG_PRINT("Workers running current/runnning max/waiting: %d/%d/%d", + DEBUG_PRINT("Workers running current/running max/waiting: %d/%d/%d", nWorkersCurrent, nWorkersMax, list_length((LPLIST)lpWorkers)); @@ -222,7 +222,7 @@ void worker_push(LPWORKER lpWorker) bFreeWorker = FALSE; }; nWorkersCurrent--; - DEBUG_PRINT("Workers running current/runnning max/waiting: %d/%d/%d", + DEBUG_PRINT("Workers running current/running max/waiting: %d/%d/%d", nWorkersCurrent, nWorkersMax, list_length((LPLIST)lpWorkers)); diff --git a/parsing/CONFLICTS.md b/parsing/CONFLICTS.md new file mode 100644 index 00000000..b2a84fcb --- /dev/null +++ b/parsing/CONFLICTS.md @@ -0,0 +1,54 @@ +# Conflicts + +Some of the conflicts and issues in the grammar are documented here. + +## A variant type that lists a single atomic type + +Why can't `[t]` be considered a valid atomic type? (A variant type.) + +(This is related to MPR #3835.) + +A class type that begins with `[t] foo` could continue as follows: + +``` + [t] foo -> +``` + +Here `t` is understood as a variant type, +and is used as an actual parameter of the parameterized type `'a foo`. + +Or it could continue as follows: + +``` + [t] foo +``` + +Here `t` is a type (there is no variant type) +and is used as an actual parameter of the class `['a] foo`. + +After we have read the closing bracket and are looking ahead at `foo`, +we need to decide which of the above two situations we have. (The first +situation requires a reduction; the second situation requires shifting.) +But we cannot decide yet; we would need to look at the arrow `->` beyond +`foo` in order to decide. In this example LR(2) is required; in general, +`foo` could be replaced with an arbitrary qualified name, so unbounded +lookahead is required. + +As a result of this issue, we must abandon the idea that `[t]` could be +a well-formed variant type. In the syntax of atomic types, instead of: + +``` + atomic_type: LBRACKET row_field RBRACKET +``` + +we must use the more restricted form: + +``` + atomic_type: LBRACKET tag_field RBRACKET +``` + +In other words, we rule out exactly the following: + +``` + atomic_type: LBRACKET atomic_type RBRACKET +``` diff --git a/parsing/HACKING.adoc b/parsing/HACKING.adoc index 7da8b22f..0566c013 100644 --- a/parsing/HACKING.adoc +++ b/parsing/HACKING.adoc @@ -7,3 +7,70 @@ link:location.mli[Location]:: This module contains utilities related to locations and error handling. In particular, it contains handlers that are used for all the error reporting in the compiler. +link:parser.mly[parser.mly]:: This file contains the grammar used to +generated the parser -- using the +link:http://gallium.inria.fr/~fpottier/menhir/[menhir] parser +generator, which is an external tool that you need to install if you +wish to modify the parser. + +=== Working on the parser grammar + +To avoid depending on an external tool, the compiler build system does +not rebuild the parser from the source grammar link:parser.mly[] each +time. It works from a versioned copy of the generated parser stored +in the `boot/menhir` subdirectory. + +If you change link:parser.mly[], you need to run the `promote-menhir` +target of the root Makefile to rebuild the compiler parser. See +link:../Makefile.menhir[] for the details of the various +Menhir-related targets and their use. + +==== Testing the grammar + +The root Makefile contains a `build-all-asts` target that will build, +for each source `.ml` or `.mli` file in the repository, a `.ml.ast` or +`.mli.ast` file describing the parsed abstract syntax tree (AST) in +`-dparsetree` format. +This rule is rather slow to run, and can safely be run in parallel, so +we recommend using `-j` (without a number) to maximize parallelism: + +---- +make -j build-all-asts +---- + +Finally, the 'list-all-asts' target lists all such '.ast' files. + +This is intended to be used to test parser changes, in particular +those that should not modify the parsed AST at all: + +1. Before performing any changes, build all AST files and add them to + the git index (`make list-all-asts | xargs git add`). + +2. Perform any parser change of interest. + +3. To test your changes, build AST files again; `git diff` will show + any change to an AST file. + +4. Before committing any change, remember to remove the `.ast` files + from your index (using `git reset HEAD`), and maybe remove them + completely (unless you plan to check further changes). + +---- +# save pre-change ASTs +make -j build-all-asts +make list-all-asts | xargs git add + +# do your parser changes +# ... +make promote-menhir + +# compare new ASTs +make -j build-all-asts +git diff # shows any .ml.ast difference + +# remove AST files from the index +make list-all-asts | xargs git reset HEAD + +# remove the files (if no further parser change planned) +make list-all-asts | xargs rm +---- diff --git a/parsing/VIPs.md b/parsing/VIPs.md new file mode 100644 index 00000000..baae0244 --- /dev/null +++ b/parsing/VIPs.md @@ -0,0 +1,20 @@ +# VIPs + +A VIP is a common syntax error, for which a good error message should be +given. + +## Structures versus signatures + +Everything that is allowed in a structure but forbidden in a signature, +or vice-versa, is a VIP. For instance, writing: + +``` + exception A = B +``` + +is allowed in a structure, but forbidden in a signature. (Here, we might +wish to make the error message depend on the lookahead token; the token +`=` suggests that the user confuses a structure and a signature.) + +Similarly, writing `struct` where `sig` is expected, or vice-versa, is +probably a common mistake. diff --git a/parsing/ast_helper.ml b/parsing/ast_helper.ml index 2c284933..9aa40bca 100644 --- a/parsing/ast_helper.ml +++ b/parsing/ast_helper.ml @@ -19,22 +19,21 @@ open Asttypes open Parsetree open Docstrings -type lid = Longident.t loc -type str = string loc +type 'a with_loc = 'a Location.loc type loc = Location.t + +type lid = Longident.t with_loc +type str = string with_loc type attrs = attribute list let default_loc = ref Location.none let with_default_loc l f = - let old = !default_loc in - default_loc := l; - try let r = f () in default_loc := old; r - with exn -> default_loc := old; raise exn + Misc.protect_refs [Misc.R (default_loc, l)] f module Const = struct let integer ?suffix i = Pconst_integer (i, suffix) - let int ?suffix i = integer ?suffix (string_of_int i) + let int ?suffix i = integer ?suffix (Int.to_string i) let int32 ?(suffix='l') i = integer ~suffix (Int32.to_string i) let int64 ?(suffix='L') i = integer ~suffix (Int64.to_string i) let nativeint ?(suffix='n') i = integer ~suffix (Nativeint.to_string i) @@ -43,9 +42,20 @@ module Const = struct let string ?quotation_delimiter s = Pconst_string (s, quotation_delimiter) end +module Attr = struct + let mk ?(loc= !default_loc) name payload = + { attr_name = name; + attr_payload = payload; + attr_loc = loc } +end + module Typ = struct let mk ?(loc = !default_loc) ?(attrs = []) d = - {ptyp_desc = d; ptyp_loc = loc; ptyp_attributes = attrs} + {ptyp_desc = d; + ptyp_loc = loc; + ptyp_loc_stack = []; + ptyp_attributes = attrs} + let attr d a = {d with ptyp_attributes = d.ptyp_attributes @ [a]} let any ?loc ?attrs () = mk ?loc ?attrs Ptyp_any @@ -106,18 +116,22 @@ module Typ = struct Ptyp_extension (s, arg) in {t with ptyp_desc = desc} - and loop_row_field = - function - | Rtag(label,attrs,flag,lst) -> - Rtag(label,attrs,flag,List.map loop lst) + and loop_row_field field = + let prf_desc = match field.prf_desc with + | Rtag(label,flag,lst) -> + Rtag(label,flag,List.map loop lst) | Rinherit t -> Rinherit (loop t) - and loop_object_field = - function - | Otag(label, attrs, t) -> - Otag(label, attrs, loop t) + in + { field with prf_desc; } + and loop_object_field field = + let pof_desc = match field.pof_desc with + | Otag(label, t) -> + Otag(label, loop t) | Oinherit t -> Oinherit (loop t) + in + { field with pof_desc; } in loop t @@ -125,7 +139,10 @@ end module Pat = struct let mk ?(loc = !default_loc) ?(attrs = []) d = - {ppat_desc = d; ppat_loc = loc; ppat_attributes = attrs} + {ppat_desc = d; + ppat_loc = loc; + ppat_loc_stack = []; + ppat_attributes = attrs} let attr d a = {d with ppat_attributes = d.ppat_attributes @ [a]} let any ?loc ?attrs () = mk ?loc ?attrs Ppat_any @@ -150,7 +167,10 @@ end module Exp = struct let mk ?(loc = !default_loc) ?(attrs = []) d = - {pexp_desc = d; pexp_loc = loc; pexp_attributes = attrs} + {pexp_desc = d; + pexp_loc = loc; + pexp_loc_stack = []; + pexp_attributes = attrs} let attr d a = {d with pexp_attributes = d.pexp_attributes @ [a]} let ident ?loc ?attrs a = mk ?loc ?attrs (Pexp_ident a) @@ -186,7 +206,9 @@ module Exp = struct let object_ ?loc ?attrs a = mk ?loc ?attrs (Pexp_object a) let newtype ?loc ?attrs a b = mk ?loc ?attrs (Pexp_newtype (a, b)) let pack ?loc ?attrs a = mk ?loc ?attrs (Pexp_pack a) - let open_ ?loc ?attrs a b c = mk ?loc ?attrs (Pexp_open (a, b, c)) + let open_ ?loc ?attrs a b = mk ?loc ?attrs (Pexp_open (a, b)) + let letop ?loc ?attrs let_ ands body = + mk ?loc ?attrs (Pexp_letop {let_; ands; body}) let extension ?loc ?attrs a = mk ?loc ?attrs (Pexp_extension a) let unreachable ?loc ?attrs () = mk ?loc ?attrs Pexp_unreachable @@ -196,6 +218,14 @@ module Exp = struct pc_guard = guard; pc_rhs = rhs; } + + let binding_op op pat exp loc = + { + pbop_op = op; + pbop_pat = pat; + pbop_exp = exp; + pbop_loc = loc; + } end module Mty = struct @@ -232,9 +262,11 @@ module Sig = struct let value ?loc a = mk ?loc (Psig_value a) let type_ ?loc rec_flag a = mk ?loc (Psig_type (rec_flag, a)) + let type_subst ?loc a = mk ?loc (Psig_typesubst a) let type_extension ?loc a = mk ?loc (Psig_typext a) let exception_ ?loc a = mk ?loc (Psig_exception a) let module_ ?loc a = mk ?loc (Psig_module a) + let mod_subst ?loc a = mk ?loc (Psig_modsubst a) let rec_module ?loc a = mk ?loc (Psig_recmodule a) let modtype ?loc a = mk ?loc (Psig_modtype a) let open_ ?loc a = mk ?loc (Psig_open a) @@ -291,7 +323,7 @@ module Cl = struct let let_ ?loc ?attrs a b c = mk ?loc ?attrs (Pcl_let (a, b, c)) let constraint_ ?loc ?attrs a b = mk ?loc ?attrs (Pcl_constraint (a, b)) let extension ?loc ?attrs a = mk ?loc ?attrs (Pcl_extension a) - let open_ ?loc ?attrs a b c = mk ?loc ?attrs (Pcl_open (a, b, c)) + let open_ ?loc ?attrs a b = mk ?loc ?attrs (Pcl_open (a, b)) end module Cty = struct @@ -307,7 +339,7 @@ module Cty = struct let signature ?loc ?attrs a = mk ?loc ?attrs (Pcty_signature a) let arrow ?loc ?attrs a b c = mk ?loc ?attrs (Pcty_arrow (a, b, c)) let extension ?loc ?attrs a = mk ?loc ?attrs (Pcty_extension a) - let open_ ?loc ?attrs a b c = mk ?loc ?attrs (Pcty_open (a, b, c)) + let open_ ?loc ?attrs a b = mk ?loc ?attrs (Pcty_open (a, b)) end module Ctf = struct @@ -388,6 +420,18 @@ module Md = struct } end +module Ms = struct + let mk ?(loc = !default_loc) ?(attrs = []) + ?(docs = empty_docs) ?(text = []) name syn = + { + pms_name = name; + pms_manifest = syn; + pms_attributes = + add_text_attrs text (add_docs_attrs docs attrs); + pms_loc = loc; + } +end + module Mtd = struct let mk ?(loc = !default_loc) ?(attrs = []) ?(docs = empty_docs) ?(text = []) ?typ name = @@ -414,9 +458,9 @@ end module Opn = struct let mk ?(loc = !default_loc) ?(attrs = []) ?(docs = empty_docs) - ?(override = Fresh) lid = + ?(override = Fresh) expr = { - popen_lid = lid; + popen_expr = expr; popen_override = override; popen_loc = loc; popen_attributes = add_docs_attrs docs attrs; @@ -505,16 +549,25 @@ end (** Type extensions *) module Te = struct - let mk ?(attrs = []) ?(docs = empty_docs) + let mk ?(loc = !default_loc) ?(attrs = []) ?(docs = empty_docs) ?(params = []) ?(priv = Public) path constructors = { ptyext_path = path; ptyext_params = params; ptyext_constructors = constructors; ptyext_private = priv; + ptyext_loc = loc; ptyext_attributes = add_docs_attrs docs attrs; } + let mk_exception ?(loc = !default_loc) ?(attrs = []) ?(docs = empty_docs) + constructor = + { + ptyexn_constructor = constructor; + ptyexn_loc = loc; + ptyexn_attributes = add_docs_attrs docs attrs; + } + let constructor ?(loc = !default_loc) ?(attrs = []) ?(docs = empty_docs) ?(info = empty_info) name kind = { @@ -559,3 +612,29 @@ module Cstr = struct pcstr_fields = fields; } end + +(** Row fields *) +module Rf = struct + let mk ?(loc = !default_loc) ?(attrs = []) desc = { + prf_desc = desc; + prf_loc = loc; + prf_attributes = attrs; + } + let tag ?loc ?attrs label const tys = + mk ?loc ?attrs (Rtag (label, const, tys)) + let inherit_?loc ty = + mk ?loc (Rinherit ty) +end + +(** Object fields *) +module Of = struct + let mk ?(loc = !default_loc) ?(attrs=[]) desc = { + pof_desc = desc; + pof_loc = loc; + pof_attributes = attrs; + } + let tag ?loc ?attrs label ty = + mk ?loc ?attrs (Otag (label, ty)) + let inherit_ ?loc ty = + mk ?loc (Oinherit ty) +end diff --git a/parsing/ast_helper.mli b/parsing/ast_helper.mli index efc1dfca..9bb0aad0 100644 --- a/parsing/ast_helper.mli +++ b/parsing/ast_helper.mli @@ -13,15 +13,22 @@ (* *) (**************************************************************************) -(** Helpers to produce Parsetree fragments *) +(** Helpers to produce Parsetree fragments + + {b Warning} This module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) open Asttypes open Docstrings open Parsetree -type lid = Longident.t loc -type str = string loc +type 'a with_loc = 'a Location.loc type loc = Location.t + +type lid = Longident.t with_loc +type str = string with_loc type attrs = attribute list (** {1 Default locations} *) @@ -46,6 +53,11 @@ module Const : sig val float : ?suffix:char -> string -> constant end +(** {1 Attributes} *) +module Attr : sig + val mk: ?loc:loc -> str -> payload -> attribute +end + (** {1 Core language} *) (** Type expressions *) @@ -168,12 +180,15 @@ module Exp: val object_: ?loc:loc -> ?attrs:attrs -> class_structure -> expression val newtype: ?loc:loc -> ?attrs:attrs -> str -> expression -> expression val pack: ?loc:loc -> ?attrs:attrs -> module_expr -> expression - val open_: ?loc:loc -> ?attrs:attrs -> override_flag -> lid -> expression + val open_: ?loc:loc -> ?attrs:attrs -> open_declaration -> expression -> expression + val letop: ?loc:loc -> ?attrs:attrs -> binding_op + -> binding_op list -> expression -> expression val extension: ?loc:loc -> ?attrs:attrs -> extension -> expression val unreachable: ?loc:loc -> ?attrs:attrs -> unit -> expression val case: pattern -> ?guard:expression -> expression -> case + val binding_op: str -> pattern -> expression -> loc -> binding_op end (** Value declarations *) @@ -202,10 +217,13 @@ module Type: (** Type extensions *) module Te: sig - val mk: ?attrs:attrs -> ?docs:docs -> + val mk: ?loc:loc -> ?attrs:attrs -> ?docs:docs -> ?params:(core_type * variance) list -> ?priv:private_flag -> lid -> extension_constructor list -> type_extension + val mk_exception: ?loc:loc -> ?attrs:attrs -> ?docs:docs -> + extension_constructor -> type_exception + val constructor: ?loc:loc -> ?attrs:attrs -> ?docs:docs -> ?info:info -> str -> extension_constructor_kind -> extension_constructor @@ -260,9 +278,11 @@ module Sig: val value: ?loc:loc -> value_description -> signature_item val type_: ?loc:loc -> rec_flag -> type_declaration list -> signature_item + val type_subst: ?loc:loc -> type_declaration list -> signature_item val type_extension: ?loc:loc -> type_extension -> signature_item - val exception_: ?loc:loc -> extension_constructor -> signature_item + val exception_: ?loc:loc -> type_exception -> signature_item val module_: ?loc:loc -> module_declaration -> signature_item + val mod_subst: ?loc:loc -> module_substitution -> signature_item val rec_module: ?loc:loc -> module_declaration list -> signature_item val modtype: ?loc:loc -> module_type_declaration -> signature_item val open_: ?loc:loc -> open_description -> signature_item @@ -284,11 +304,11 @@ module Str: val primitive: ?loc:loc -> value_description -> structure_item val type_: ?loc:loc -> rec_flag -> type_declaration list -> structure_item val type_extension: ?loc:loc -> type_extension -> structure_item - val exception_: ?loc:loc -> extension_constructor -> structure_item + val exception_: ?loc:loc -> type_exception -> structure_item val module_: ?loc:loc -> module_binding -> structure_item val rec_module: ?loc:loc -> module_binding list -> structure_item val modtype: ?loc:loc -> module_type_declaration -> structure_item - val open_: ?loc:loc -> open_description -> structure_item + val open_: ?loc:loc -> open_declaration -> structure_item val class_: ?loc:loc -> class_declaration list -> structure_item val class_type: ?loc:loc -> class_type_declaration list -> structure_item val include_: ?loc:loc -> include_declaration -> structure_item @@ -304,6 +324,13 @@ module Md: str -> module_type -> module_declaration end +(** Module substitutions *) +module Ms: + sig + val mk: ?loc:loc -> ?attrs:attrs -> ?docs:docs -> ?text:text -> + str -> lid -> module_substitution + end + (** Module type declarations *) module Mtd: sig @@ -322,7 +349,7 @@ module Mb: module Opn: sig val mk: ?loc: loc -> ?attrs:attrs -> ?docs:docs -> - ?override:override_flag -> lid -> open_description + ?override:override_flag -> 'a -> 'a open_infos end (** Includes *) @@ -352,7 +379,7 @@ module Cty: val arrow: ?loc:loc -> ?attrs:attrs -> arg_label -> core_type -> class_type -> class_type val extension: ?loc:loc -> ?attrs:attrs -> extension -> class_type - val open_: ?loc:loc -> ?attrs:attrs -> override_flag -> lid -> class_type + val open_: ?loc:loc -> ?attrs:attrs -> open_description -> class_type -> class_type end @@ -392,7 +419,7 @@ module Cl: val constraint_: ?loc:loc -> ?attrs:attrs -> class_expr -> class_type -> class_expr val extension: ?loc:loc -> ?attrs:attrs -> extension -> class_expr - val open_: ?loc:loc -> ?attrs:attrs -> override_flag -> lid -> class_expr + val open_: ?loc:loc -> ?attrs:attrs -> open_description -> class_expr -> class_expr end @@ -440,3 +467,22 @@ module Cstr: sig val mk: pattern -> class_field list -> class_structure end + +(** Row fields *) +module Rf: + sig + val mk: ?loc:loc -> ?attrs:attrs -> row_field_desc -> row_field + val tag: ?loc:loc -> ?attrs:attrs -> + label with_loc -> bool -> core_type list -> row_field + val inherit_: ?loc:loc -> core_type -> row_field + end + +(** Object fields *) +module Of: + sig + val mk: ?loc:loc -> ?attrs:attrs -> + object_field_desc -> object_field + val tag: ?loc:loc -> ?attrs:attrs -> + label with_loc -> core_type -> object_field + val inherit_: ?loc:loc -> core_type -> object_field + end diff --git a/parsing/ast_invariants.ml b/parsing/ast_invariants.ml index 32e5f8fc..7ecdae96 100644 --- a/parsing/ast_invariants.ml +++ b/parsing/ast_invariants.ml @@ -87,8 +87,7 @@ let iterator = | Pexp_construct (id, _) | Pexp_field (_, id) | Pexp_setfield (_, id, _) - | Pexp_new id - | Pexp_open (_, id, _) -> simple_longident id + | Pexp_new id -> simple_longident id | Pexp_record (fields, _) -> List.iter (fun (id, _) -> simple_longident id) fields | _ -> () @@ -114,8 +113,7 @@ let iterator = | _ -> () in let open_description self opn = - super.open_description self opn; - simple_longident opn.popen_lid + super.open_description self opn in let with_constraint self wc = super.with_constraint self wc; @@ -145,6 +143,30 @@ let iterator = | Psig_type (_, []) -> empty_type loc | _ -> () in + let row_field self field = + super.row_field self field; + let loc = field.prf_loc in + match field.prf_desc with + | Rtag _ -> () + | Rinherit _ -> + if field.prf_attributes = [] + then () + else err loc + "In variant types, attaching attributes to inherited \ + subtypes is not allowed." + in + let object_field self field = + super.object_field self field; + let loc = field.pof_loc in + match field.pof_desc with + | Otag _ -> () + | Oinherit _ -> + if field.pof_attributes = [] + then () + else err loc + "In object types, attaching attributes to inherited \ + subtypes is not allowed." + in { super with type_declaration ; typ @@ -158,6 +180,8 @@ let iterator = ; with_constraint ; structure_item ; signature_item + ; row_field + ; object_field } let structure st = iterator.structure iterator st diff --git a/parsing/ast_invariants.mli b/parsing/ast_invariants.mli index 51d3f9de..fdb56aa5 100644 --- a/parsing/ast_invariants.mli +++ b/parsing/ast_invariants.mli @@ -12,7 +12,12 @@ (* *) (**************************************************************************) -(** Check AST invariants *) +(** Check AST invariants + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) val structure : Parsetree.structure -> unit val signature : Parsetree.signature -> unit diff --git a/parsing/ast_iterator.ml b/parsing/ast_iterator.ml index aa601e64..c6806a9b 100755 --- a/parsing/ast_iterator.ml +++ b/parsing/ast_iterator.ml @@ -27,6 +27,7 @@ open Location type iterator = { attribute: iterator -> attribute -> unit; attributes: iterator -> attribute list -> unit; + binding_op: iterator -> binding_op -> unit; case: iterator -> case -> unit; cases: iterator -> case list -> unit; class_declaration: iterator -> class_declaration -> unit; @@ -48,9 +49,11 @@ type iterator = { location: iterator -> Location.t -> unit; module_binding: iterator -> module_binding -> unit; module_declaration: iterator -> module_declaration -> unit; + module_substitution: iterator -> module_substitution -> unit; module_expr: iterator -> module_expr -> unit; module_type: iterator -> module_type -> unit; module_type_declaration: iterator -> module_type_declaration -> unit; + open_declaration: iterator -> open_declaration -> unit; open_description: iterator -> open_description -> unit; pat: iterator -> pattern -> unit; payload: iterator -> payload -> unit; @@ -59,8 +62,11 @@ type iterator = { structure: iterator -> structure -> unit; structure_item: iterator -> structure_item -> unit; typ: iterator -> core_type -> unit; + row_field: iterator -> row_field -> unit; + object_field: iterator -> object_field -> unit; type_declaration: iterator -> type_declaration -> unit; type_extension: iterator -> type_extension -> unit; + type_exception: iterator -> type_exception -> unit; type_kind: iterator -> type_kind -> unit; value_binding: iterator -> value_binding -> unit; value_description: iterator -> value_description -> unit; @@ -82,14 +88,26 @@ let iter_loc sub {loc; txt = _} = sub.location sub loc module T = struct (* Type expressions for the core language *) - let row_field sub = function - | Rtag (_, attrs, _, tl) -> - sub.attributes sub attrs; List.iter (sub.typ sub) tl + let row_field sub { + prf_desc; + prf_loc; + prf_attributes; + } = + sub.location sub prf_loc; + sub.attributes sub prf_attributes; + match prf_desc with + | Rtag (_, _, tl) -> List.iter (sub.typ sub) tl | Rinherit t -> sub.typ sub t - let object_field sub = function - | Otag (_, attrs, t) -> - sub.attributes sub attrs; sub.typ sub t + let object_field sub { + pof_desc; + pof_loc; + pof_attributes; + } = + sub.location sub pof_loc; + sub.attributes sub pof_attributes; + match pof_desc with + | Otag (_, t) -> sub.typ sub t | Oinherit t -> sub.typ sub t let iter sub {ptyp_desc = desc; ptyp_loc = loc; ptyp_attributes = attrs} = @@ -149,12 +167,20 @@ module T = struct {ptyext_path; ptyext_params; ptyext_constructors; ptyext_private = _; + ptyext_loc; ptyext_attributes} = iter_loc sub ptyext_path; List.iter (sub.extension_constructor sub) ptyext_constructors; List.iter (iter_fst (sub.typ sub)) ptyext_params; + sub.location sub ptyext_loc; sub.attributes sub ptyext_attributes + let iter_type_exception sub + {ptyexn_constructor; ptyexn_loc; ptyexn_attributes} = + sub.extension_constructor sub ptyexn_constructor; + sub.location sub ptyexn_loc; + sub.attributes sub ptyexn_attributes + let iter_extension_constructor_kind sub = function Pext_decl(ctl, cto) -> iter_constructor_arguments sub ctl; iter_opt (sub.typ sub) cto @@ -186,8 +212,8 @@ module CT = struct | Pcty_arrow (_lab, t, ct) -> sub.typ sub t; sub.class_type sub ct | Pcty_extension x -> sub.extension sub x - | Pcty_open (_ovf, lid, e) -> - iter_loc sub lid; sub.class_type sub e + | Pcty_open (o, e) -> + sub.open_description sub o; sub.class_type sub e let iter_field sub {pctf_desc = desc; pctf_loc = loc; pctf_attributes = attrs} = @@ -241,10 +267,13 @@ module MT = struct sub.location sub loc; match desc with | Psig_value vd -> sub.value_description sub vd - | Psig_type (_rf, l) -> List.iter (sub.type_declaration sub) l + | Psig_type (_, l) + | Psig_typesubst l -> + List.iter (sub.type_declaration sub) l | Psig_typext te -> sub.type_extension sub te - | Psig_exception ed -> sub.extension_constructor sub ed + | Psig_exception ed -> sub.type_exception sub ed | Psig_module x -> sub.module_declaration sub x + | Psig_modsubst x -> sub.module_substitution sub x | Psig_recmodule l -> List.iter (sub.module_declaration sub) l | Psig_modtype x -> sub.module_type_declaration sub x @@ -254,7 +283,8 @@ module MT = struct | Psig_class_type l -> List.iter (sub.class_type_declaration sub) l | Psig_extension (x, attrs) -> - sub.extension sub x; sub.attributes sub attrs + sub.attributes sub attrs; + sub.extension sub x | Psig_attribute x -> sub.attribute sub x end @@ -283,22 +313,22 @@ module M = struct sub.location sub loc; match desc with | Pstr_eval (x, attrs) -> - sub.expr sub x; sub.attributes sub attrs + sub.attributes sub attrs; sub.expr sub x | Pstr_value (_r, vbs) -> List.iter (sub.value_binding sub) vbs | Pstr_primitive vd -> sub.value_description sub vd | Pstr_type (_rf, l) -> List.iter (sub.type_declaration sub) l | Pstr_typext te -> sub.type_extension sub te - | Pstr_exception ed -> sub.extension_constructor sub ed + | Pstr_exception ed -> sub.type_exception sub ed | Pstr_module x -> sub.module_binding sub x | Pstr_recmodule l -> List.iter (sub.module_binding sub) l | Pstr_modtype x -> sub.module_type_declaration sub x - | Pstr_open x -> sub.open_description sub x + | Pstr_open x -> sub.open_declaration sub x | Pstr_class l -> List.iter (sub.class_declaration sub) l | Pstr_class_type l -> List.iter (sub.class_type_declaration sub) l | Pstr_include x -> sub.include_declaration sub x | Pstr_extension (x, attrs) -> - sub.extension sub x; sub.attributes sub attrs + sub.attributes sub attrs; sub.extension sub x | Pstr_attribute x -> sub.attribute sub x end @@ -372,10 +402,21 @@ module E = struct | Pexp_object cls -> sub.class_structure sub cls | Pexp_newtype (_s, e) -> sub.expr sub e | Pexp_pack me -> sub.module_expr sub me - | Pexp_open (_ovf, lid, e) -> - iter_loc sub lid; sub.expr sub e + | Pexp_open (o, e) -> + sub.open_declaration sub o; sub.expr sub e + | Pexp_letop {let_; ands; body} -> + sub.binding_op sub let_; + List.iter (sub.binding_op sub) ands; + sub.expr sub body | Pexp_extension x -> sub.extension sub x | Pexp_unreachable -> () + + let iter_binding_op sub {pbop_op; pbop_pat; pbop_exp; pbop_loc} = + iter_loc sub pbop_op; + sub.pat sub pbop_pat; + sub.expr sub pbop_exp; + sub.location sub pbop_loc + end module P = struct @@ -434,8 +475,8 @@ module CE = struct | Pcl_constraint (ce, ct) -> sub.class_expr sub ce; sub.class_type sub ct | Pcl_extension x -> sub.extension sub x - | Pcl_open (_ovf, lid, e) -> - iter_loc sub lid; sub.class_expr sub e + | Pcl_open (o, e) -> + sub.open_description sub o; sub.class_expr sub e let iter_kind sub = function | Cfk_concrete (_o, e) -> sub.expr sub e @@ -496,47 +537,65 @@ let default_iterator = type_declaration = T.iter_type_declaration; type_kind = T.iter_type_kind; typ = T.iter; + row_field = T.row_field; + object_field = T.object_field; type_extension = T.iter_type_extension; + type_exception = T.iter_type_exception; extension_constructor = T.iter_extension_constructor; value_description = (fun this {pval_name; pval_type; pval_prim = _; pval_loc; pval_attributes} -> iter_loc this pval_name; this.typ this pval_type; + this.location this pval_loc; this.attributes this pval_attributes; - this.location this pval_loc ); pat = P.iter; expr = E.iter; + binding_op = E.iter_binding_op; module_declaration = (fun this {pmd_name; pmd_type; pmd_attributes; pmd_loc} -> iter_loc this pmd_name; this.module_type this pmd_type; + this.location this pmd_loc; this.attributes this pmd_attributes; - this.location this pmd_loc + ); + + module_substitution = + (fun this {pms_name; pms_manifest; pms_attributes; pms_loc} -> + iter_loc this pms_name; + iter_loc this pms_manifest; + this.location this pms_loc; + this.attributes this pms_attributes; ); module_type_declaration = (fun this {pmtd_name; pmtd_type; pmtd_attributes; pmtd_loc} -> iter_loc this pmtd_name; iter_opt (this.module_type this) pmtd_type; + this.location this pmtd_loc; this.attributes this pmtd_attributes; - this.location this pmtd_loc ); module_binding = (fun this {pmb_name; pmb_expr; pmb_attributes; pmb_loc} -> iter_loc this pmb_name; this.module_expr this pmb_expr; + this.location this pmb_loc; this.attributes this pmb_attributes; - this.location this pmb_loc ); + open_declaration = + (fun this {popen_expr; popen_override = _; popen_attributes; popen_loc} -> + this.module_expr this popen_expr; + this.location this popen_loc; + this.attributes this popen_attributes + ); open_description = - (fun this {popen_lid; popen_override = _; popen_attributes; popen_loc} -> - iter_loc this popen_lid; + (fun this {popen_expr; popen_override = _; popen_attributes; popen_loc} -> + iter_loc this popen_expr; this.location this popen_loc; this.attributes this popen_attributes ); @@ -594,7 +653,11 @@ let default_iterator = location = (fun _this _l -> ()); extension = (fun this (s, e) -> iter_loc this s; this.payload this e); - attribute = (fun this (s, e) -> iter_loc this s; this.payload this e); + attribute = (fun this a -> + iter_loc this a.attr_name; + this.payload this a.attr_payload; + this.location this a.attr_loc + ); attributes = (fun this l -> List.iter (this.attribute this) l); payload = (fun this -> function diff --git a/parsing/ast_iterator.mli b/parsing/ast_iterator.mli index bd8e0816..5dc1c0ec 100755 --- a/parsing/ast_iterator.mli +++ b/parsing/ast_iterator.mli @@ -15,7 +15,12 @@ (** {!iterator} allows to implement AST inspection using open recursion. A typical mapper would be based on {!default_iterator}, a trivial iterator, - and will fall back on it for handling the syntax it does not modify. *) + and will fall back on it for handling the syntax it does not modify. + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) open Parsetree @@ -24,6 +29,7 @@ open Parsetree type iterator = { attribute: iterator -> attribute -> unit; attributes: iterator -> attribute list -> unit; + binding_op: iterator -> binding_op -> unit; case: iterator -> case -> unit; cases: iterator -> case list -> unit; class_declaration: iterator -> class_declaration -> unit; @@ -45,9 +51,11 @@ type iterator = { location: iterator -> Location.t -> unit; module_binding: iterator -> module_binding -> unit; module_declaration: iterator -> module_declaration -> unit; + module_substitution: iterator -> module_substitution -> unit; module_expr: iterator -> module_expr -> unit; module_type: iterator -> module_type -> unit; module_type_declaration: iterator -> module_type_declaration -> unit; + open_declaration: iterator -> open_declaration -> unit; open_description: iterator -> open_description -> unit; pat: iterator -> pattern -> unit; payload: iterator -> payload -> unit; @@ -56,8 +64,11 @@ type iterator = { structure: iterator -> structure -> unit; structure_item: iterator -> structure_item -> unit; typ: iterator -> core_type -> unit; + row_field: iterator -> row_field -> unit; + object_field: iterator -> object_field -> unit; type_declaration: iterator -> type_declaration -> unit; type_extension: iterator -> type_extension -> unit; + type_exception: iterator -> type_exception -> unit; type_kind: iterator -> type_kind -> unit; value_binding: iterator -> value_binding -> unit; value_description: iterator -> value_description -> unit; diff --git a/parsing/ast_mapper.ml b/parsing/ast_mapper.ml index 783d0e2e..f2fcd92f 100644 --- a/parsing/ast_mapper.ml +++ b/parsing/ast_mapper.ml @@ -20,14 +20,16 @@ (* Ensure that record patterns don't miss any field. *) *) - open Parsetree open Ast_helper open Location +module String = Misc.Stdlib.String + type mapper = { attribute: mapper -> attribute -> attribute; attributes: mapper -> attribute list -> attribute list; + binding_op: mapper -> binding_op -> binding_op; case: mapper -> case -> case; cases: mapper -> case list -> case list; class_declaration: mapper -> class_declaration -> class_declaration; @@ -52,10 +54,12 @@ type mapper = { location: mapper -> Location.t -> Location.t; module_binding: mapper -> module_binding -> module_binding; module_declaration: mapper -> module_declaration -> module_declaration; + module_substitution: mapper -> module_substitution -> module_substitution; module_expr: mapper -> module_expr -> module_expr; module_type: mapper -> module_type -> module_type; module_type_declaration: mapper -> module_type_declaration -> module_type_declaration; + open_declaration: mapper -> open_declaration -> open_declaration; open_description: mapper -> open_description -> open_description; pat: mapper -> pattern -> pattern; payload: mapper -> payload -> payload; @@ -66,6 +70,7 @@ type mapper = { typ: mapper -> core_type -> core_type; type_declaration: mapper -> type_declaration -> type_declaration; type_extension: mapper -> type_extension -> type_extension; + type_exception: mapper -> type_exception -> type_exception; type_kind: mapper -> type_kind -> type_kind; value_binding: mapper -> value_binding -> value_binding; value_description: mapper -> value_description -> value_description; @@ -83,16 +88,31 @@ let map_loc sub {loc; txt} = {loc = sub.location sub loc; txt} module T = struct (* Type expressions for the core language *) - let row_field sub = function - | Rtag (l, attrs, b, tl) -> - Rtag (map_loc sub l, sub.attributes sub attrs, - b, List.map (sub.typ sub) tl) - | Rinherit t -> Rinherit (sub.typ sub t) - - let object_field sub = function - | Otag (l, attrs, t) -> - Otag (map_loc sub l, sub.attributes sub attrs, sub.typ sub t) - | Oinherit t -> Oinherit (sub.typ sub t) + let row_field sub { + prf_desc; + prf_loc; + prf_attributes; + } = + let loc = sub.location sub prf_loc in + let attrs = sub.attributes sub prf_attributes in + let desc = match prf_desc with + | Rtag (l, b, tl) -> Rtag (map_loc sub l, b, List.map (sub.typ sub) tl) + | Rinherit t -> Rinherit (sub.typ sub t) + in + Rf.mk ~loc ~attrs desc + + let object_field sub { + pof_desc; + pof_loc; + pof_attributes; + } = + let loc = sub.location sub pof_loc in + let attrs = sub.attributes sub pof_attributes in + let desc = match pof_desc with + | Otag (l, t) -> Otag (map_loc sub l, sub.typ sub t) + | Oinherit t -> Oinherit (sub.typ sub t) + in + Of.mk ~loc ~attrs desc let map sub {ptyp_desc = desc; ptyp_loc = loc; ptyp_attributes = attrs} = let open Typ in @@ -127,7 +147,9 @@ module T = struct ptype_manifest; ptype_attributes; ptype_loc} = - Type.mk (map_loc sub ptype_name) + let loc = sub.location sub ptype_loc in + let attrs = sub.attributes sub ptype_attributes in + Type.mk ~loc ~attrs (map_loc sub ptype_name) ~params:(List.map (map_fst (sub.typ sub)) ptype_params) ~priv:ptype_private ~cstrs:(List.map @@ -135,8 +157,6 @@ module T = struct ptype_cstrs) ~kind:(sub.type_kind sub ptype_kind) ?manifest:(map_opt (sub.typ sub) ptype_manifest) - ~loc:(sub.location sub ptype_loc) - ~attrs:(sub.attributes sub ptype_attributes) let map_type_kind sub = function | Ptype_abstract -> Ptype_abstract @@ -154,13 +174,22 @@ module T = struct {ptyext_path; ptyext_params; ptyext_constructors; ptyext_private; + ptyext_loc; ptyext_attributes} = - Te.mk + let loc = sub.location sub ptyext_loc in + let attrs = sub.attributes sub ptyext_attributes in + Te.mk ~loc ~attrs (map_loc sub ptyext_path) (List.map (sub.extension_constructor sub) ptyext_constructors) ~params:(List.map (map_fst (sub.typ sub)) ptyext_params) ~priv:ptyext_private - ~attrs:(sub.attributes sub ptyext_attributes) + + let map_type_exception sub + {ptyexn_constructor; ptyexn_loc; ptyexn_attributes} = + let loc = sub.location sub ptyexn_loc in + let attrs = sub.attributes sub ptyexn_attributes in + Te.mk_exception ~loc ~attrs + (sub.extension_constructor sub ptyexn_constructor) let map_extension_constructor_kind sub = function Pext_decl(ctl, cto) -> @@ -173,11 +202,11 @@ module T = struct pext_kind; pext_loc; pext_attributes} = - Te.constructor + let loc = sub.location sub pext_loc in + let attrs = sub.attributes sub pext_attributes in + Te.constructor ~loc ~attrs (map_loc sub pext_name) (map_extension_constructor_kind sub pext_kind) - ~loc:(sub.location sub pext_loc) - ~attrs:(sub.attributes sub pext_attributes) end @@ -195,8 +224,8 @@ module CT = struct | Pcty_arrow (lab, t, ct) -> arrow ~loc ~attrs lab (sub.typ sub t) (sub.class_type sub ct) | Pcty_extension x -> extension ~loc ~attrs (sub.extension sub x) - | Pcty_open (ovf, lid, ct) -> - open_ ~loc ~attrs ovf (map_loc sub lid) (sub.class_type sub ct) + | Pcty_open (o, ct) -> + open_ ~loc ~attrs (sub.open_description sub o) (sub.class_type sub ct) let map_field sub {pctf_desc = desc; pctf_loc = loc; pctf_attributes = attrs} = @@ -256,10 +285,14 @@ module MT = struct let loc = sub.location sub loc in match desc with | Psig_value vd -> value ~loc (sub.value_description sub vd) - | Psig_type (rf, l) -> type_ ~loc rf (List.map (sub.type_declaration sub) l) + | Psig_type (rf, l) -> + type_ ~loc rf (List.map (sub.type_declaration sub) l) + | Psig_typesubst l -> + type_subst ~loc (List.map (sub.type_declaration sub) l) | Psig_typext te -> type_extension ~loc (sub.type_extension sub te) - | Psig_exception ed -> exception_ ~loc (sub.extension_constructor sub ed) + | Psig_exception ed -> exception_ ~loc (sub.type_exception sub ed) | Psig_module x -> module_ ~loc (sub.module_declaration sub x) + | Psig_modsubst x -> mod_subst ~loc (sub.module_substitution sub x) | Psig_recmodule l -> rec_module ~loc (List.map (sub.module_declaration sub) l) | Psig_modtype x -> modtype ~loc (sub.module_type_declaration sub x) @@ -269,7 +302,8 @@ module MT = struct | Psig_class_type l -> class_type ~loc (List.map (sub.class_type_declaration sub) l) | Psig_extension (x, attrs) -> - extension ~loc (sub.extension sub x) ~attrs:(sub.attributes sub attrs) + let attrs = sub.attributes sub attrs in + extension ~loc ~attrs (sub.extension sub x) | Psig_attribute x -> attribute ~loc (sub.attribute sub x) end @@ -301,22 +335,24 @@ module M = struct let loc = sub.location sub loc in match desc with | Pstr_eval (x, attrs) -> - eval ~loc ~attrs:(sub.attributes sub attrs) (sub.expr sub x) + let attrs = sub.attributes sub attrs in + eval ~loc ~attrs (sub.expr sub x) | Pstr_value (r, vbs) -> value ~loc r (List.map (sub.value_binding sub) vbs) | Pstr_primitive vd -> primitive ~loc (sub.value_description sub vd) | Pstr_type (rf, l) -> type_ ~loc rf (List.map (sub.type_declaration sub) l) | Pstr_typext te -> type_extension ~loc (sub.type_extension sub te) - | Pstr_exception ed -> exception_ ~loc (sub.extension_constructor sub ed) + | Pstr_exception ed -> exception_ ~loc (sub.type_exception sub ed) | Pstr_module x -> module_ ~loc (sub.module_binding sub x) | Pstr_recmodule l -> rec_module ~loc (List.map (sub.module_binding sub) l) | Pstr_modtype x -> modtype ~loc (sub.module_type_declaration sub x) - | Pstr_open x -> open_ ~loc (sub.open_description sub x) + | Pstr_open x -> open_ ~loc (sub.open_declaration sub x) | Pstr_class l -> class_ ~loc (List.map (sub.class_declaration sub) l) | Pstr_class_type l -> class_type ~loc (List.map (sub.class_type_declaration sub) l) | Pstr_include x -> include_ ~loc (sub.include_declaration sub x) | Pstr_extension (x, attrs) -> - extension ~loc (sub.extension sub x) ~attrs:(sub.attributes sub attrs) + let attrs = sub.attributes sub attrs in + extension ~loc ~attrs (sub.extension sub x) | Pstr_attribute x -> attribute ~loc (sub.attribute sub x) end @@ -394,10 +430,22 @@ module E = struct | Pexp_newtype (s, e) -> newtype ~loc ~attrs (map_loc sub s) (sub.expr sub e) | Pexp_pack me -> pack ~loc ~attrs (sub.module_expr sub me) - | Pexp_open (ovf, lid, e) -> - open_ ~loc ~attrs ovf (map_loc sub lid) (sub.expr sub e) + | Pexp_open (o, e) -> + open_ ~loc ~attrs (sub.open_declaration sub o) (sub.expr sub e) + | Pexp_letop {let_; ands; body} -> + letop ~loc ~attrs (sub.binding_op sub let_) + (List.map (sub.binding_op sub) ands) (sub.expr sub body) | Pexp_extension x -> extension ~loc ~attrs (sub.extension sub x) | Pexp_unreachable -> unreachable ~loc ~attrs () + + let map_binding_op sub {pbop_op; pbop_pat; pbop_exp; pbop_loc} = + let open Exp in + let op = map_loc sub pbop_op in + let pat = sub.pat sub pbop_pat in + let exp = sub.expr sub pbop_exp in + let loc = sub.location sub pbop_loc in + binding_op op pat exp loc + end module P = struct @@ -458,8 +506,8 @@ module CE = struct | Pcl_constraint (ce, ct) -> constraint_ ~loc ~attrs (sub.class_expr sub ce) (sub.class_type sub ct) | Pcl_extension x -> extension ~loc ~attrs (sub.extension sub x) - | Pcl_open (ovf, lid, ce) -> - open_ ~loc ~attrs ovf (map_loc sub lid) (sub.class_expr sub ce) + | Pcl_open (o, ce) -> + open_ ~loc ~attrs (sub.open_description sub o) (sub.class_expr sub ce) let map_kind sub = function | Cfk_concrete (o, e) -> Cfk_concrete (o, sub.expr sub e) @@ -490,13 +538,13 @@ module CE = struct let class_infos sub f {pci_virt; pci_params = pl; pci_name; pci_expr; pci_loc; pci_attributes} = - Ci.mk + let loc = sub.location sub pci_loc in + let attrs = sub.attributes sub pci_attributes in + Ci.mk ~loc ~attrs ~virt:pci_virt ~params:(List.map (map_fst (sub.typ sub)) pl) (map_loc sub pci_name) (f pci_expr) - ~loc:(sub.location sub pci_loc) - ~attrs:(sub.attributes sub pci_attributes) end (* Now, a generic AST mapper, to be extended to cover all kinds and @@ -528,6 +576,7 @@ let default_mapper = type_kind = T.map_type_kind; typ = T.map; type_extension = T.map_type_extension; + type_exception = T.map_type_exception; extension_constructor = T.map_extension_constructor; value_description = (fun this {pval_name; pval_type; pval_prim; pval_loc; @@ -542,6 +591,7 @@ let default_mapper = pat = P.map; expr = E.map; + binding_op = E.map_binding_op; module_declaration = (fun this {pmd_name; pmd_type; pmd_attributes; pmd_loc} -> @@ -552,6 +602,15 @@ let default_mapper = ~loc:(this.location this pmd_loc) ); + module_substitution = + (fun this {pms_name; pms_manifest; pms_attributes; pms_loc} -> + Ms.mk + (map_loc this pms_name) + (map_loc this pms_manifest) + ~attrs:(this.attributes this pms_attributes) + ~loc:(this.location this pms_loc) + ); + module_type_declaration = (fun this {pmtd_name; pmtd_type; pmtd_attributes; pmtd_loc} -> Mtd.mk @@ -569,14 +628,21 @@ let default_mapper = ); - open_description = - (fun this {popen_lid; popen_override; popen_attributes; popen_loc} -> - Opn.mk (map_loc this popen_lid) + open_declaration = + (fun this {popen_expr; popen_override; popen_attributes; popen_loc} -> + Opn.mk (this.module_expr this popen_expr) ~override:popen_override ~loc:(this.location this popen_loc) ~attrs:(this.attributes this popen_attributes) ); + open_description = + (fun this {popen_expr; popen_override; popen_attributes; popen_loc} -> + Opn.mk (map_loc this popen_expr) + ~override:popen_override + ~loc:(this.location this popen_loc) + ~attrs:(this.attributes this popen_attributes) + ); include_description = (fun this {pincl_mod; pincl_attributes; pincl_loc} -> @@ -638,7 +704,13 @@ let default_mapper = location = (fun _this l -> l); extension = (fun this (s, e) -> (map_loc this s, this.payload this e)); - attribute = (fun this (s, e) -> (map_loc this s, this.payload this e)); + attribute = (fun this a -> + { + attr_name = map_loc this a.attr_name; + attr_payload = this.payload this a.attr_payload; + attr_loc = this.location this a.attr_loc + } + ); attributes = (fun this l -> List.map (this.attribute this) l); payload = (fun this -> function @@ -649,29 +721,31 @@ let default_mapper = ); } -let rec extension_of_error {loc; msg; if_highlight; sub} = - { loc; txt = "ocaml.error" }, - PStr ([Str.eval (Exp.constant (Pconst_string (msg, None))); - Str.eval (Exp.constant (Pconst_string (if_highlight, None)))] @ - (List.map (fun ext -> Str.extension (extension_of_error ext)) sub)) +let extension_of_error {kind; main; sub} = + if kind <> Location.Report_error then + raise (Invalid_argument "extension_of_error: expected kind Report_error"); + let str_of_pp pp_msg = Format.asprintf "%t" pp_msg in + let extension_of_sub sub = + { loc = sub.loc; txt = "ocaml.error" }, + PStr ([Str.eval (Exp.constant (Pconst_string (str_of_pp sub.txt, None)))]) + in + { loc = main.loc; txt = "ocaml.error" }, + PStr (Str.eval (Exp.constant (Pconst_string (str_of_pp main.txt, None))) :: + List.map (fun msg -> Str.extension (extension_of_sub msg)) sub) let attribute_of_warning loc s = - { loc; txt = "ocaml.ppwarning" }, - PStr ([Str.eval ~loc (Exp.constant (Pconst_string (s, None)))]) - -module StringMap = Map.Make(struct - type t = string - let compare = compare -end) + Attr.mk + {loc; txt = "ocaml.ppwarning" } + (PStr ([Str.eval ~loc (Exp.constant (Pconst_string (s, None)))])) -let cookies = ref StringMap.empty +let cookies = ref String.Map.empty let get_cookie k = - try Some (StringMap.find k !cookies) + try Some (String.Map.find k !cookies) with Not_found -> None let set_cookie k v = - cookies := StringMap.add k v !cookies + cookies := String.Map.add k v !cookies let tool_name_ref = ref "_none_" @@ -710,23 +784,31 @@ module PpxContext = struct let get_cookies () = lid "cookies", make_list (make_pair make_string (fun x -> x)) - (StringMap.bindings !cookies) + (String.Map.bindings !cookies) let mk fields = - { txt = "ocaml.ppx.context"; loc = Location.none }, - Parsetree.PStr [Str.eval (Exp.record fields None)] + { + attr_name = { txt = "ocaml.ppx.context"; loc = Location.none }; + attr_payload = Parsetree.PStr [Str.eval (Exp.record fields None)]; + attr_loc = Location.none + } let make ~tool_name () = let fields = [ lid "tool_name", make_string tool_name; lid "include_dirs", make_list make_string !Clflags.include_dirs; - lid "load_path", make_list make_string !Config.load_path; + lid "load_path", make_list make_string (Load_path.get_paths ()); lid "open_modules", make_list make_string !Clflags.open_modules; lid "for_package", make_option make_string !Clflags.for_package; lid "debug", make_bool !Clflags.debug; lid "use_threads", make_bool !Clflags.use_threads; lid "use_vmthreads", make_bool !Clflags.use_vmthreads; + lid "recursive_types", make_bool !Clflags.recursive_types; + lid "principal", make_bool !Clflags.principal; + lid "transparent_modules", make_bool !Clflags.transparent_modules; + lid "unboxed_types", make_bool !Clflags.unboxed_types; + lid "unsafe_string", make_bool !Clflags.unsafe_string; get_cookies () ] in @@ -786,7 +868,7 @@ module PpxContext = struct | "include_dirs" -> Clflags.include_dirs := get_list get_string payload | "load_path" -> - Config.load_path := get_list get_string payload + Load_path.init (get_list get_string payload) | "open_modules" -> Clflags.open_modules := get_list get_string payload | "for_package" -> @@ -797,11 +879,21 @@ module PpxContext = struct Clflags.use_threads := get_bool payload | "use_vmthreads" -> Clflags.use_vmthreads := get_bool payload + | "recursive_types" -> + Clflags.recursive_types := get_bool payload + | "principal" -> + Clflags.principal := get_bool payload + | "transparent_modules" -> + Clflags.transparent_modules := get_bool payload + | "unboxed_types" -> + Clflags.unboxed_types := get_bool payload + | "unsafe_string" -> + Clflags.unsafe_string := get_bool payload | "cookies" -> let l = get_list (get_pair get_string (fun x -> x)) payload in cookies := List.fold_left - (fun s (k, v) -> StringMap.add k v s) StringMap.empty + (fun s (k, v) -> String.Map.add k v s) String.Map.empty l | _ -> () @@ -822,7 +914,8 @@ let ppx_context = PpxContext.make let extension_of_exn exn = match error_of_exn exn with | Some (`Ok error) -> extension_of_error error - | Some `Already_displayed -> { loc = Location.none; txt = "ocaml.error" }, PStr [] + | Some `Already_displayed -> + { loc = Location.none; txt = "ocaml.error" }, PStr [] | None -> raise exn @@ -830,7 +923,8 @@ let apply_lazy ~source ~target mapper = let implem ast = let fields, ast = match ast with - | {pstr_desc = Pstr_attribute ({txt = "ocaml.ppx.context"}, x)} :: l -> + | {pstr_desc = Pstr_attribute ({attr_name = {txt = "ocaml.ppx.context"}; + attr_payload = x})} :: l -> PpxContext.get_fields x, l | _ -> [], ast in @@ -849,7 +943,9 @@ let apply_lazy ~source ~target mapper = let iface ast = let fields, ast = match ast with - | {psig_desc = Psig_attribute ({txt = "ocaml.ppx.context"}, x)} :: l -> + | {psig_desc = Psig_attribute ({attr_name = {txt = "ocaml.ppx.context"}; + attr_payload = x; + attr_loc = _})} :: l -> PpxContext.get_fields x, l | _ -> [], ast in @@ -893,7 +989,10 @@ let apply_lazy ~source ~target mapper = else fail () let drop_ppx_context_str ~restore = function - | {pstr_desc = Pstr_attribute({Location.txt = "ocaml.ppx.context"}, a)} + | {pstr_desc = Pstr_attribute + {attr_name = {Location.txt = "ocaml.ppx.context"}; + attr_payload = a; + attr_loc = _}} :: items -> if restore then PpxContext.restore (PpxContext.get_fields a); @@ -901,7 +1000,10 @@ let drop_ppx_context_str ~restore = function | items -> items let drop_ppx_context_sig ~restore = function - | {psig_desc = Psig_attribute({Location.txt = "ocaml.ppx.context"}, a)} + | {psig_desc = Psig_attribute + {attr_name = {Location.txt = "ocaml.ppx.context"}; + attr_payload = a; + attr_loc = _}} :: items -> if restore then PpxContext.restore (PpxContext.get_fields a); diff --git a/parsing/ast_mapper.mli b/parsing/ast_mapper.mli index 85b59e9c..b342ca8a 100644 --- a/parsing/ast_mapper.mli +++ b/parsing/ast_mapper.mli @@ -46,6 +46,9 @@ let () = the constant [42], can be compiled using [ocamlc -o ppx_test -I +compiler-libs ocamlcommon.cma ppx_test.ml]. + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + *) open Parsetree @@ -55,6 +58,7 @@ open Parsetree type mapper = { attribute: mapper -> attribute -> attribute; attributes: mapper -> attribute list -> attribute list; + binding_op: mapper -> binding_op -> binding_op; case: mapper -> case -> case; cases: mapper -> case list -> case list; class_declaration: mapper -> class_declaration -> class_declaration; @@ -79,10 +83,12 @@ type mapper = { location: mapper -> Location.t -> Location.t; module_binding: mapper -> module_binding -> module_binding; module_declaration: mapper -> module_declaration -> module_declaration; + module_substitution: mapper -> module_substitution -> module_substitution; module_expr: mapper -> module_expr -> module_expr; module_type: mapper -> module_type -> module_type; module_type_declaration: mapper -> module_type_declaration -> module_type_declaration; + open_declaration: mapper -> open_declaration -> open_declaration; open_description: mapper -> open_description -> open_description; pat: mapper -> pattern -> pattern; payload: mapper -> payload -> payload; @@ -93,6 +99,7 @@ type mapper = { typ: mapper -> core_type -> core_type; type_declaration: mapper -> type_declaration -> type_declaration; type_extension: mapper -> type_extension -> type_extension; + type_exception: mapper -> type_exception -> type_exception; type_kind: mapper -> type_kind -> type_kind; value_binding: mapper -> value_binding -> value_binding; value_description: mapper -> value_description -> value_description; @@ -114,7 +121,7 @@ val tool_name: unit -> string ["ocaml"], ... Some global variables that reflect command-line options are automatically synchronized between the calling tool and the ppx preprocessor: {!Clflags.include_dirs}, - {!Config.load_path}, {!Clflags.open_modules}, {!Clflags.for_package}, + {!Load_path}, {!Clflags.open_modules}, {!Clflags.for_package}, {!Clflags.debug}. *) diff --git a/parsing/asttypes.mli b/parsing/asttypes.mli index 8cab1c6b..150d9e5f 100644 --- a/parsing/asttypes.mli +++ b/parsing/asttypes.mli @@ -13,7 +13,12 @@ (* *) (**************************************************************************) -(** Auxiliary AST types used by parsetree and typedtree. *) +(** Auxiliary AST types used by parsetree and typedtree. + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) type constant = Const_int of int diff --git a/parsing/attr_helper.ml b/parsing/attr_helper.ml index ecf87787..0a616cd7 100644 --- a/parsing/attr_helper.ml +++ b/parsing/attr_helper.ml @@ -23,12 +23,12 @@ type error = exception Error of Location.t * error let get_no_payload_attribute alt_names attrs = - match List.filter (fun (n, _) -> List.mem n.txt alt_names) attrs with + match List.filter (fun a -> List.mem a.attr_name.txt alt_names) attrs with | [] -> None - | [ (name, PStr []) ] -> Some name - | [ (name, _) ] -> + | [ {attr_name = name; attr_payload = PStr []; attr_loc = _} ] -> Some name + | [ {attr_name = name; _} ] -> raise (Error (name.loc, No_payload_expected name.txt)) - | _ :: (name, _) :: _ -> + | _ :: {attr_name = name; _} :: _ -> raise (Error (name.loc, Multiple_attributes name.txt)) let has_no_payload_attribute alt_names attrs = @@ -48,7 +48,7 @@ let () = Location.register_error_of_exn (function | Error (loc, err) -> - Some (Location.error_of_printer loc report_error err) + Some (Location.error_of_printer ~loc report_error err) | _ -> None ) diff --git a/parsing/attr_helper.mli b/parsing/attr_helper.mli index 3d7145c3..a3ddc0c9 100644 --- a/parsing/attr_helper.mli +++ b/parsing/attr_helper.mli @@ -13,7 +13,12 @@ (* *) (**************************************************************************) -(** Helpers for attributes *) +(** Helpers for attributes + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) open Asttypes open Parsetree diff --git a/parsing/builtin_attributes.ml b/parsing/builtin_attributes.ml index a8eb33b6..dbebed80 100755 --- a/parsing/builtin_attributes.ml +++ b/parsing/builtin_attributes.ml @@ -30,58 +30,106 @@ let string_of_opt_payload p = | Some s -> s | None -> "" -let rec error_of_extension ext = +let error_of_extension ext = + let submessage_from main_loc main_txt = function + | {pstr_desc=Pstr_extension + (({txt = ("ocaml.error"|"error"); loc}, p), _)} -> + begin match p with + | PStr([{pstr_desc=Pstr_eval + ({pexp_desc=Pexp_constant(Pconst_string(msg,_))}, _)}]) -> + { Location.loc; txt = fun ppf -> Format.pp_print_text ppf msg } + | _ -> + { Location.loc; txt = fun ppf -> + Format.fprintf ppf + "Invalid syntax for sub-message of extension '%s'." main_txt } + end + | {pstr_desc=Pstr_extension (({txt; loc}, _), _)} -> + { Location.loc; txt = fun ppf -> + Format.fprintf ppf "Uninterpreted extension '%s'." txt } + | _ -> + { Location.loc = main_loc; txt = fun ppf -> + Format.fprintf ppf + "Invalid syntax for sub-message of extension '%s'." main_txt } + in match ext with | ({txt = ("ocaml.error"|"error") as txt; loc}, p) -> - let rec sub_from inner = - match inner with - | {pstr_desc=Pstr_extension (ext, _)} :: rest -> - error_of_extension ext :: sub_from rest - | _ :: rest -> - (Location.errorf ~loc - "Invalid syntax for sub-error of extension '%s'." txt) :: - sub_from rest - | [] -> [] - in - begin match p with - | PStr [] -> raise Location.Already_displayed_error - | PStr({pstr_desc=Pstr_eval - ({pexp_desc=Pexp_constant(Pconst_string(msg,_))}, _)}:: - {pstr_desc=Pstr_eval - ({pexp_desc=Pexp_constant(Pconst_string(if_highlight,_))}, _)}:: - inner) -> - Location.error ~loc ~if_highlight ~sub:(sub_from inner) msg - | PStr({pstr_desc=Pstr_eval - ({pexp_desc=Pexp_constant(Pconst_string(msg,_))}, _)}::inner) -> - Location.error ~loc ~sub:(sub_from inner) msg - | _ -> Location.errorf ~loc "Invalid syntax for extension '%s'." txt - end + begin match p with + | PStr [] -> raise Location.Already_displayed_error + | PStr({pstr_desc=Pstr_eval + ({pexp_desc=Pexp_constant(Pconst_string(msg,_))}, _)}:: + inner) -> + let sub = List.map (submessage_from loc txt) inner in + Location.error_of_printer ~loc ~sub Format.pp_print_text msg + | _ -> + Location.errorf ~loc "Invalid syntax for extension '%s'." txt + end | ({txt; loc}, _) -> Location.errorf ~loc "Uninterpreted extension '%s'." txt +let kind_and_message = function + | PStr[ + {pstr_desc= + Pstr_eval + ({pexp_desc=Pexp_apply + ({pexp_desc=Pexp_ident{txt=Longident.Lident id}}, + [Nolabel,{pexp_desc=Pexp_constant (Pconst_string(s,_))}]) + },_)}] -> + Some (id, s) + | PStr[ + {pstr_desc= + Pstr_eval + ({pexp_desc=Pexp_ident{txt=Longident.Lident id}},_)}] -> + Some (id, "") + | _ -> None + let cat s1 s2 = if s2 = "" then s1 else s1 ^ "\n" ^ s2 -let rec deprecated_of_attrs = function - | [] -> None - | ({txt = "ocaml.deprecated"|"deprecated"; _}, p) :: _ -> - Some (string_of_opt_payload p) - | _ :: tl -> deprecated_of_attrs tl +let alert_attr x = + match x.attr_name.txt with + | "ocaml.deprecated"|"deprecated" -> + Some (x, "deprecated", string_of_opt_payload x.attr_payload) + | "ocaml.alert"|"alert" -> + begin match kind_and_message x.attr_payload with + | Some (kind, message) -> Some (x, kind, message) + | None -> None (* note: bad payloads detected by warning_attribute *) + end + | _ -> None -let check_deprecated loc attrs s = - match deprecated_of_attrs attrs with - | None -> () - | Some txt -> Location.deprecated loc (cat s txt) +let alert_attrs l = + List.filter_map alert_attr l -let check_deprecated_inclusion ~def ~use loc attrs1 attrs2 s = - match deprecated_of_attrs attrs1, deprecated_of_attrs attrs2 with - | None, _ | Some _, Some _ -> () - | Some txt, None -> Location.deprecated ~def ~use loc (cat s txt) +let alerts_of_attrs l = + List.fold_left + (fun acc (_, kind, message) -> + let upd = function + | None | Some "" -> Some message + | Some s -> Some (cat s message) + in + Misc.Stdlib.String.Map.update kind upd acc + ) + Misc.Stdlib.String.Map.empty + (alert_attrs l) + +let check_alerts loc attrs s = + Misc.Stdlib.String.Map.iter + (fun kind message -> Location.alert loc ~kind (cat s message)) + (alerts_of_attrs attrs) + +let check_alerts_inclusion ~def ~use loc attrs1 attrs2 s = + let m2 = alerts_of_attrs attrs2 in + Misc.Stdlib.String.Map.iter + (fun kind msg -> + if not (Misc.Stdlib.String.Map.mem kind m2) then + Location.alert ~def ~use ~kind loc (cat s msg) + ) + (alerts_of_attrs attrs1) let rec deprecated_mutable_of_attrs = function | [] -> None - | ({txt = "ocaml.deprecated_mutable"|"deprecated_mutable"; _}, p) :: _ -> - Some (string_of_opt_payload p) + | {attr_name = {txt = "ocaml.deprecated_mutable"|"deprecated_mutable"; _}; + attr_payload = p} :: _ -> + Some (string_of_opt_payload p) | _ :: tl -> deprecated_mutable_of_attrs tl let check_deprecated_mutable loc attrs s = @@ -99,51 +147,87 @@ let check_deprecated_mutable_inclusion ~def ~use loc attrs1 attrs2 s = Location.deprecated ~def ~use loc (Printf.sprintf "mutating field %s" (cat s txt)) -let rec deprecated_of_sig = function +let rec attrs_of_sig = function | {psig_desc = Psig_attribute a} :: tl -> - begin match deprecated_of_attrs [a] with - | None -> deprecated_of_sig tl - | Some _ as r -> r - end - | _ -> None + a :: attrs_of_sig tl + | _ -> + [] +let alerts_of_sig sg = alerts_of_attrs (attrs_of_sig sg) -let rec deprecated_of_str = function +let rec attrs_of_str = function | {pstr_desc = Pstr_attribute a} :: tl -> - begin match deprecated_of_attrs [a] with - | None -> deprecated_of_str tl - | Some _ as r -> r - end - | _ -> None + a :: attrs_of_str tl + | _ -> + [] + +let alerts_of_str str = alerts_of_attrs (attrs_of_str str) + +let check_no_alert attrs = + List.iter + (fun (a, _, _) -> + Location.prerr_warning a.attr_loc + (Warnings.Misplaced_attribute a.attr_name.txt) + ) + (alert_attrs attrs) +let warn_payload loc txt msg = + Location.prerr_warning loc (Warnings.Attribute_payload (txt, msg)) let warning_attribute ?(ppwarning = true) = let process loc txt errflag payload = match string_of_payload payload with | Some s -> begin try Warnings.parse_options errflag s - with Arg.Bad _ -> - Location.prerr_warning loc - (Warnings.Attribute_payload - (txt, "Ill-formed list of warnings")) + with Arg.Bad msg -> warn_payload loc txt msg end | None -> - Location.prerr_warning loc - (Warnings.Attribute_payload - (txt, "A single string literal is expected")) + warn_payload loc txt "A single string literal is expected" + in + let process_alert loc txt = function + | PStr[{pstr_desc= + Pstr_eval( + {pexp_desc=Pexp_constant(Pconst_string(s,_))}, + _) + }] -> + begin try Warnings.parse_alert_option s + with Arg.Bad msg -> warn_payload loc txt msg + end + | k -> + match kind_and_message k with + | Some ("all", _) -> + warn_payload loc txt "The alert name 'all' is reserved" + | Some _ -> () + | None -> warn_payload loc txt "Invalid payload" in function - | ({txt = ("ocaml.warning"|"warning") as txt; loc}, payload) -> - process loc txt false payload - | ({txt = ("ocaml.warnerror"|"warnerror") as txt; loc}, payload) -> - process loc txt true payload - | {txt="ocaml.ppwarning"|"ppwarning"}, - PStr[{pstr_desc=Pstr_eval({pexp_desc=Pexp_constant - (Pconst_string (s, _))},_); - pstr_loc}] when ppwarning -> - Location.prerr_warning pstr_loc (Warnings.Preprocessor s) + | {attr_name = {txt = ("ocaml.warning"|"warning") as txt; _}; + attr_loc; + attr_payload; + } -> + process attr_loc txt false attr_payload + | {attr_name = {txt = ("ocaml.warnerror"|"warnerror") as txt; _}; + attr_loc; + attr_payload + } -> + process attr_loc txt true attr_payload + | {attr_name = {txt="ocaml.ppwarning"|"ppwarning"; _}; + attr_loc = _; + attr_payload = + PStr [ + { pstr_desc= + Pstr_eval({pexp_desc=Pexp_constant (Pconst_string (s, _))},_); + pstr_loc } + ]; + } when ppwarning -> + Location.prerr_warning pstr_loc (Warnings.Preprocessor s) + | {attr_name = {txt = ("ocaml.alert"|"alert") as txt; _}; + attr_loc; + attr_payload; + } -> + process_alert attr_loc txt attr_payload | _ -> - () + () let warning_scope ?ppwarning attrs f = let prev = Warnings.backup () in @@ -159,24 +243,23 @@ let warning_scope ?ppwarning attrs f = let warn_on_literal_pattern = List.exists - (function - | ({txt="ocaml.warn_on_literal_pattern"|"warn_on_literal_pattern"; _}, _) - -> true - | _ -> false + (fun a -> match a.attr_name.txt with + | "ocaml.warn_on_literal_pattern"|"warn_on_literal_pattern" -> true + | _ -> false ) let explicit_arity = List.exists - (function - | ({txt="ocaml.explicit_arity"|"explicit_arity"; _}, _) -> true - | _ -> false + (fun a -> match a.attr_name.txt with + | "ocaml.explicit_arity"|"explicit_arity" -> true + | _ -> false ) let immediate = List.exists - (function - | ({txt="ocaml.immediate"|"immediate"; _}, _) -> true - | _ -> false + (fun a -> match a.attr_name.txt with + | "ocaml.immediate"|"immediate" -> true + | _ -> false ) (* The "ocaml.boxed (default)" and "ocaml.unboxed (default)" @@ -186,7 +269,7 @@ let immediate = source file because the default can change between compiler invocations. *) -let check l (x, _) = List.mem x.txt l +let check l a = List.mem a.attr_name.txt l let has_unboxed attr = List.exists (check ["ocaml.unboxed"; "unboxed"]) diff --git a/parsing/builtin_attributes.mli b/parsing/builtin_attributes.mli index 056316a6..35e78abf 100755 --- a/parsing/builtin_attributes.mli +++ b/parsing/builtin_attributes.mli @@ -13,28 +13,33 @@ (* *) (**************************************************************************) -(* Support for some of the builtin attributes: - - ocaml.deprecated - ocaml.error - ocaml.ppwarning - ocaml.warning - ocaml.warnerror - ocaml.explicit_arity (for camlp4/camlp5) - ocaml.warn_on_literal_pattern - ocaml.deprecated_mutable - ocaml.immediate - ocaml.boxed / ocaml.unboxed +(** Support for some of the builtin attributes + + - ocaml.deprecated + - ocaml.alert + - ocaml.error + - ocaml.ppwarning + - ocaml.warning + - ocaml.warnerror + - ocaml.explicit_arity (for camlp4/camlp5) + - ocaml.warn_on_literal_pattern + - ocaml.deprecated_mutable + - ocaml.immediate + - ocaml.boxed / ocaml.unboxed + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + *) -val check_deprecated: Location.t -> Parsetree.attributes -> string -> unit -val check_deprecated_inclusion: +val check_alerts: Location.t -> Parsetree.attributes -> string -> unit +val check_alerts_inclusion: def:Location.t -> use:Location.t -> Location.t -> Parsetree.attributes -> Parsetree.attributes -> string -> unit -val deprecated_of_attrs: Parsetree.attributes -> string option -val deprecated_of_sig: Parsetree.signature -> string option -val deprecated_of_str: Parsetree.structure -> string option +val alerts_of_attrs: Parsetree.attributes -> string Misc.Stdlib.String.Map.t +val alerts_of_sig: Parsetree.signature -> string Misc.Stdlib.String.Map.t +val alerts_of_str: Parsetree.structure -> string Misc.Stdlib.String.Map.t val check_deprecated_mutable: Location.t -> Parsetree.attributes -> string -> unit @@ -42,6 +47,8 @@ val check_deprecated_mutable_inclusion: def:Location.t -> use:Location.t -> Location.t -> Parsetree.attributes -> Parsetree.attributes -> string -> unit +val check_no_alert: Parsetree.attributes -> unit + val error_of_extension: Parsetree.extension -> Location.error val warning_attribute: ?ppwarning:bool -> Parsetree.attribute -> unit diff --git a/parsing/depend.ml b/parsing/depend.ml index 9e872fbc..ddaf182d 100644 --- a/parsing/depend.ml +++ b/parsing/depend.ml @@ -17,26 +17,24 @@ open Asttypes open Location open Longident open Parsetree +module String = Misc.Stdlib.String let pp_deps = ref [] -module StringSet = Set.Make(struct type t = string let compare = compare end) -module StringMap = Map.Make(String) - (* Module resolution map *) (* Node (set of imports for this path, map for submodules) *) -type map_tree = Node of StringSet.t * bound_map -and bound_map = map_tree StringMap.t -let bound = Node (StringSet.empty, StringMap.empty) +type map_tree = Node of String.Set.t * bound_map +and bound_map = map_tree String.Map.t +let bound = Node (String.Set.empty, String.Map.empty) (*let get_free (Node (s, _m)) = s*) let get_map (Node (_s, m)) = m -let make_leaf s = Node (StringSet.singleton s, StringMap.empty) -let make_node m = Node (StringSet.empty, m) +let make_leaf s = Node (String.Set.singleton s, String.Map.empty) +let make_node m = Node (String.Set.empty, m) let rec weaken_map s (Node(s0,m0)) = - Node (StringSet.union s s0, StringMap.map (weaken_map s) m0) + Node (String.Set.union s s0, String.Map.map (weaken_map s) m0) let rec collect_free (Node (s, m)) = - StringMap.fold (fun _ n -> StringSet.union (collect_free n)) m s + String.Map.fold (fun _ n -> String.Set.union (collect_free n)) m s (* Returns the imports required to access the structure at path p *) (* Only raises Not_found if the head of p is not in the toplevel map *) @@ -44,29 +42,29 @@ let rec lookup_free p m = match p with [] -> raise Not_found | s::p -> - let Node (f, m') = StringMap.find s m in + let Node (f, m') = String.Map.find s m in try lookup_free p m' with Not_found -> f (* Returns the node corresponding to the structure at path p *) let rec lookup_map lid m = match lid with - Lident s -> StringMap.find s m - | Ldot (l, s) -> StringMap.find s (get_map (lookup_map l m)) + Lident s -> String.Map.find s m + | Ldot (l, s) -> String.Map.find s (get_map (lookup_map l m)) | Lapply _ -> raise Not_found (* Collect free module identifiers in the a.s.t. *) -let free_structure_names = ref StringSet.empty +let free_structure_names = ref String.Set.empty let add_names s = - free_structure_names := StringSet.union s !free_structure_names + free_structure_names := String.Set.union s !free_structure_names let rec add_path bv ?(p=[]) = function | Lident s -> let free = - try lookup_free (s::p) bv with Not_found -> StringSet.singleton s + try lookup_free (s::p) bv with Not_found -> String.Set.singleton s in - (*StringSet.iter (fun s -> Printf.eprintf "%s " s) free; + (*String.Set.iter (fun s -> Printf.eprintf "%s " s) free; prerr_endline "";*) add_names free | Ldot(l, s) -> add_path bv ~p:(s::p) l @@ -76,7 +74,7 @@ let open_module bv lid = match lookup_map lid bv with | Node (s, m) -> add_names s; - StringMap.fold StringMap.add m bv + String.Map.fold String.Map.add m bv | exception Not_found -> add_path bv lid; bv @@ -106,13 +104,15 @@ let rec add_type bv ty = | Ptyp_constr(c, tl) -> add bv c; List.iter (add_type bv) tl | Ptyp_object (fl, _) -> List.iter - (function Otag (_, _, t) -> add_type bv t + (fun {pof_desc; _} -> match pof_desc with + | Otag (_, t) -> add_type bv t | Oinherit t -> add_type bv t) fl | Ptyp_class(c, tl) -> add bv c; List.iter (add_type bv) tl | Ptyp_alias(t, _) -> add_type bv t | Ptyp_variant(fl, _, _) -> List.iter - (function Rtag(_,_,_,stl) -> List.iter (add_type bv) stl + (fun {prf_desc; _} -> match prf_desc with + | Rtag(_, _, stl) -> List.iter (add_type bv) stl | Rinherit sty -> add_type bv sty) fl | Ptyp_poly(_, t) -> add_type bv t @@ -160,34 +160,10 @@ let add_type_extension bv te = add bv te.ptyext_path; List.iter (add_extension_constructor bv) te.ptyext_constructors -let rec add_class_type bv cty = - match cty.pcty_desc with - Pcty_constr(l, tyl) -> - add bv l; List.iter (add_type bv) tyl - | Pcty_signature { pcsig_self = ty; pcsig_fields = fieldl } -> - add_type bv ty; - List.iter (add_class_type_field bv) fieldl - | Pcty_arrow(_, ty1, cty2) -> - add_type bv ty1; add_class_type bv cty2 - | Pcty_extension e -> handle_extension e - | Pcty_open (_ovf, m, e) -> - let bv = open_module bv m.txt in add_class_type bv e +let add_type_exception bv te = + add_extension_constructor bv te.ptyexn_constructor -and add_class_type_field bv pctf = - match pctf.pctf_desc with - Pctf_inherit cty -> add_class_type bv cty - | Pctf_val(_, _, _, ty) -> add_type bv ty - | Pctf_method(_, _, _, ty) -> add_type bv ty - | Pctf_constraint(ty1, ty2) -> add_type bv ty1; add_type bv ty2 - | Pctf_attribute _ -> () - | Pctf_extension e -> handle_extension e - -let add_class_description bv infos = - add_class_type bv infos.pci_expr - -let add_class_type_declaration = add_class_description - -let pattern_bv = ref StringMap.empty +let pattern_bv = ref String.Map.empty let rec add_pattern bv pat = match pat.ppat_desc with @@ -206,7 +182,7 @@ let rec add_pattern bv pat = | Ppat_variant(_, op) -> add_opt add_pattern bv op | Ppat_type li -> add bv li | Ppat_lazy p -> add_pattern bv p - | Ppat_unpack id -> pattern_bv := StringMap.add id.txt bound !pattern_bv + | Ppat_unpack id -> pattern_bv := String.Map.add id.txt bound !pattern_bv | Ppat_open ( m, p) -> let bv = open_module bv m.txt in add_pattern bv p | Ppat_exception p -> add_pattern bv p | Ppat_extension e -> handle_extension e @@ -258,7 +234,7 @@ let rec add_expr bv exp = | Pexp_override sel -> List.iter (fun (_s, e) -> add_expr bv e) sel | Pexp_letmodule(id, m, e) -> let b = add_module_binding bv m in - add_expr (StringMap.add id.txt b bv) e + add_expr (String.Map.add id.txt b bv) e | Pexp_letexception(_, e) -> add_expr bv e | Pexp_assert (e) -> add_expr bv e | Pexp_lazy (e) -> add_expr bv e @@ -267,8 +243,13 @@ let rec add_expr bv exp = let bv = add_pattern bv pat in List.iter (add_class_field bv) fieldl | Pexp_newtype (_, e) -> add_expr bv e | Pexp_pack m -> add_module_expr bv m - | Pexp_open (_ovf, m, e) -> - let bv = open_module bv m.txt in add_expr bv e + | Pexp_open (o, e) -> + let bv = open_declaration bv o in + add_expr bv e + | Pexp_letop {let_; ands; body} -> + let bv' = add_binding_op bv bv let_ in + let bv' = List.fold_left (add_binding_op bv) bv' ands in + add_expr bv' body | Pexp_extension (({ txt = ("ocaml.extension_constructor"| "extension_constructor"); _ }, PStr [item]) as e) -> @@ -293,6 +274,10 @@ and add_bindings recf bv pel = List.iter (fun x -> add_expr bv x.pvb_expr) pel; bv' +and add_binding_op bv bv' pbop = + add_expr bv pbop.pbop_exp; + add_pattern bv' pbop.pbop_pat + and add_modtype bv mty = match mty.pmty_desc with Pmty_ident l -> add bv l @@ -300,7 +285,7 @@ and add_modtype bv mty = | Pmty_signature s -> add_signature bv s | Pmty_functor(id, mty1, mty2) -> Misc.may (add_modtype bv) mty1; - add_modtype (StringMap.add id.txt bound bv) mty2 + add_modtype (String.Map.add id.txt bound bv) mty2 | Pmty_with(mty, cstrl) -> add_modtype bv mty; List.iter @@ -340,25 +325,30 @@ and add_signature bv sg = ignore (add_signature_binding bv sg) and add_signature_binding bv sg = - snd (List.fold_left add_sig_item (bv, StringMap.empty) sg) + snd (List.fold_left add_sig_item (bv, String.Map.empty) sg) and add_sig_item (bv, m) item = match item.psig_desc with Psig_value vd -> add_type bv vd.pval_type; (bv, m) - | Psig_type (_, dcls) -> + | Psig_type (_, dcls) + | Psig_typesubst dcls-> List.iter (add_type_declaration bv) dcls; (bv, m) | Psig_typext te -> add_type_extension bv te; (bv, m) - | Psig_exception pext -> - add_extension_constructor bv pext; (bv, m) + | Psig_exception te -> + add_type_exception bv te; (bv, m) | Psig_module pmd -> let m' = add_modtype_binding bv pmd.pmd_type in - let add = StringMap.add pmd.pmd_name.txt m' in + let add = String.Map.add pmd.pmd_name.txt m' in + (add bv, add m) + | Psig_modsubst pms -> + let m' = add_module_alias bv pms.pms_manifest in + let add = String.Map.add pms.pms_name.txt m' in (add bv, add m) | Psig_recmodule decls -> let add = - List.fold_right (fun pmd -> StringMap.add pmd.pmd_name.txt bound) + List.fold_right (fun pmd -> String.Map.add pmd.pmd_name.txt bound) decls in let bv' = add bv and m' = add m in @@ -371,11 +361,11 @@ and add_sig_item (bv, m) item = end; (bv, m) | Psig_open od -> - (open_module bv od.popen_lid.txt, m) + (open_description bv od, m) | Psig_include incl -> let Node (s, m') = add_modtype_binding bv incl.pincl_mod in add_names s; - let add = StringMap.fold StringMap.add m' in + let add = String.Map.fold String.Map.add m' in (add bv, add m) | Psig_class cdl -> List.iter (add_class_description bv) cdl; (bv, m) @@ -386,6 +376,16 @@ and add_sig_item (bv, m) item = handle_extension e; (bv, m) +and open_description bv od = + let Node(s, m) = add_module_alias bv od.popen_expr in + add_names s; + String.Map.fold String.Map.add m bv + +and open_declaration bv od = + let Node (s, m) = add_module_binding bv od.popen_expr in + add_names s; + String.Map.fold String.Map.add m bv + and add_module_binding bv modl = match modl.pmod_desc with Pmod_ident l -> add_module_alias bv l @@ -399,7 +399,7 @@ and add_module_expr bv modl = | Pmod_structure s -> ignore (add_structure bv s) | Pmod_functor(id, mty, modl) -> Misc.may (add_modtype bv) mty; - add_module_expr (StringMap.add id.txt bound bv) modl + add_module_expr (String.Map.add id.txt bound bv) modl | Pmod_apply(mod1, mod2) -> add_module_expr bv mod1; add_module_expr bv mod2 | Pmod_constraint(modl, mty) -> @@ -409,15 +409,43 @@ and add_module_expr bv modl = | Pmod_extension e -> handle_extension e +and add_class_type bv cty = + match cty.pcty_desc with + Pcty_constr(l, tyl) -> + add bv l; List.iter (add_type bv) tyl + | Pcty_signature { pcsig_self = ty; pcsig_fields = fieldl } -> + add_type bv ty; + List.iter (add_class_type_field bv) fieldl + | Pcty_arrow(_, ty1, cty2) -> + add_type bv ty1; add_class_type bv cty2 + | Pcty_extension e -> handle_extension e + | Pcty_open (o, e) -> + let bv = open_description bv o in + add_class_type bv e + +and add_class_type_field bv pctf = + match pctf.pctf_desc with + Pctf_inherit cty -> add_class_type bv cty + | Pctf_val(_, _, _, ty) -> add_type bv ty + | Pctf_method(_, _, _, ty) -> add_type bv ty + | Pctf_constraint(ty1, ty2) -> add_type bv ty1; add_type bv ty2 + | Pctf_attribute _ -> () + | Pctf_extension e -> handle_extension e + +and add_class_description bv infos = + add_class_type bv infos.pci_expr + +and add_class_type_declaration bv infos = add_class_description bv infos + and add_structure bv item_list = let (bv, m) = add_structure_binding bv item_list in add_names (collect_free (make_node m)); bv and add_structure_binding bv item_list = - List.fold_left add_struct_item (bv, StringMap.empty) item_list + List.fold_left add_struct_item (bv, String.Map.empty) item_list -and add_struct_item (bv, m) item : _ StringMap.t * _ StringMap.t = +and add_struct_item (bv, m) item : _ String.Map.t * _ String.Map.t = match item.pstr_desc with Pstr_eval (e, _attrs) -> add_expr bv e; (bv, m) @@ -430,15 +458,16 @@ and add_struct_item (bv, m) item : _ StringMap.t * _ StringMap.t = | Pstr_typext te -> add_type_extension bv te; (bv, m) - | Pstr_exception pext -> - add_extension_constructor bv pext; (bv, m) + | Pstr_exception te -> + add_type_exception bv te; + (bv, m) | Pstr_module x -> let b = add_module_binding bv x.pmb_expr in - let add = StringMap.add x.pmb_name.txt b in + let add = String.Map.add x.pmb_name.txt b in (add bv, add m) | Pstr_recmodule bindings -> let add = - List.fold_right (fun x -> StringMap.add x.pmb_name.txt bound) bindings + List.fold_right (fun x -> String.Map.add x.pmb_name.txt bound) bindings in let bv' = add bv and m = add m in List.iter @@ -452,7 +481,7 @@ and add_struct_item (bv, m) item : _ StringMap.t * _ StringMap.t = end; (bv, m) | Pstr_open od -> - (open_module bv od.popen_lid.txt, m) + (open_declaration bv od, m) | Pstr_class cdl -> List.iter (add_class_declaration bv) cdl; (bv, m) | Pstr_class_type cdtl -> @@ -465,7 +494,7 @@ and add_struct_item (bv, m) item : _ StringMap.t * _ StringMap.t = (* If we are not in the delayed dependency mode, we need to collect all delayed dependencies imported by the include statement *) add_names (collect_free n); - let add = StringMap.fold StringMap.add m' in + let add = String.Map.fold String.Map.add m' in (add bv, add m) | Pstr_attribute _ -> (bv, m) | Pstr_extension (e, _) -> @@ -483,7 +512,7 @@ and add_implementation_binding bv l = and add_top_phrase bv = function | Ptop_def str -> add_structure bv str - | Ptop_dir (_, _) -> bv + | Ptop_dir _ -> bv and add_class_expr bv ce = match ce.pcl_desc with @@ -501,8 +530,9 @@ and add_class_expr bv ce = | Pcl_constraint(ce, ct) -> add_class_expr bv ce; add_class_type bv ct | Pcl_extension e -> handle_extension e - | Pcl_open (_ovf, m, e) -> - let bv = open_module bv m.txt in add_class_expr bv e + | Pcl_open (o, e) -> + let bv = open_description bv o in + add_class_expr bv e and add_class_field bv pcf = match pcf.pcf_desc with diff --git a/parsing/depend.mli b/parsing/depend.mli index 6efd5e09..cbed53b9 100644 --- a/parsing/depend.mli +++ b/parsing/depend.mli @@ -13,20 +13,24 @@ (* *) (**************************************************************************) -(** Module dependencies. *) +(** Module dependencies. -module StringSet : Set.S with type elt = string -module StringMap : Map.S with type key = string + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. -type map_tree = Node of StringSet.t * bound_map -and bound_map = map_tree StringMap.t +*) + +module String = Misc.Stdlib.String + +type map_tree = Node of String.Set.t * bound_map +and bound_map = map_tree String.Map.t val make_leaf : string -> map_tree val make_node : bound_map -> map_tree -val weaken_map : StringSet.t -> map_tree -> map_tree +val weaken_map : String.Set.t -> map_tree -> map_tree -val free_structure_names : StringSet.t ref +val free_structure_names : String.Set.t ref -(* dependencies found by preprocessing tools (plugins) *) +(** dependencies found by preprocessing tools (plugins) *) val pp_deps : string list ref val open_module : bound_map -> Longident.t -> bound_map diff --git a/parsing/docstrings.ml b/parsing/docstrings.ml index d70b0bfa..7e3a2bec 100644 --- a/parsing/docstrings.ml +++ b/parsing/docstrings.ml @@ -92,12 +92,15 @@ let docs_attr ds = let exp = { pexp_desc = Pexp_constant (Pconst_string(ds.ds_body, None)); pexp_loc = ds.ds_loc; + pexp_loc_stack = []; pexp_attributes = []; } in let item = { pstr_desc = Pstr_eval (exp, []); pstr_loc = exp.pexp_loc } in - (doc_loc, PStr [item]) + { attr_name = doc_loc; + attr_payload = PStr [item]; + attr_loc = Location.none } let add_docs_attrs docs attrs = let attrs = @@ -139,12 +142,15 @@ let text_attr ds = let exp = { pexp_desc = Pexp_constant (Pconst_string(ds.ds_body, None)); pexp_loc = ds.ds_loc; + pexp_loc_stack = []; pexp_attributes = []; } in let item = { pstr_desc = Pstr_eval (exp, []); pstr_loc = exp.pexp_loc } in - (text_loc, PStr [item]) + { attr_name = text_loc; + attr_payload = PStr [item]; + attr_loc = Location.none } let add_text_attrs dsl attrs = let fdsl = List.filter (function {ds_body=""} -> false| _ ->true) dsl in @@ -276,7 +282,7 @@ let get_post_extra_text pos = with Not_found -> [] (* Docstrings from parser actions *) - +module WithParsing = struct let symbol_docs () = { docs_pre = get_pre_docs (Parsing.symbol_start_pos ()); docs_post = get_post_docs (Parsing.symbol_end_pos ()); } @@ -339,7 +345,70 @@ let rhs_pre_extra_text pos = let rhs_post_extra_text pos = get_post_extra_text (Parsing.rhs_end_pos pos) +end + +include WithParsing + +module WithMenhir = struct +let symbol_docs (startpos, endpos) = + { docs_pre = get_pre_docs startpos; + docs_post = get_post_docs endpos; } + +let symbol_docs_lazy (p1, p2) = + lazy { docs_pre = get_pre_docs p1; + docs_post = get_post_docs p2; } + +let rhs_docs pos1 pos2 = + { docs_pre = get_pre_docs pos1; + docs_post = get_post_docs pos2; } + +let rhs_docs_lazy p1 p2 = + lazy { docs_pre = get_pre_docs p1; + docs_post = get_post_docs p2; } + +let mark_symbol_docs (startpos, endpos) = + mark_pre_docs startpos; + mark_post_docs endpos; + () + +let mark_rhs_docs pos1 pos2 = + mark_pre_docs pos1; + mark_post_docs pos2; + () + +let symbol_info endpos = + get_info endpos + +let rhs_info endpos = + get_info endpos +let symbol_text startpos = + get_text startpos + +let symbol_text_lazy startpos = + lazy (get_text startpos) + +let rhs_text pos = + get_text pos + +let rhs_post_text pos = + get_post_text pos + +let rhs_text_lazy pos = + lazy (get_text pos) + +let symbol_pre_extra_text startpos = + get_pre_extra_text startpos + +let symbol_post_extra_text endpos = + get_post_extra_text endpos + +let rhs_pre_extra_text pos = + get_pre_extra_text pos + +let rhs_post_extra_text pos = + get_post_extra_text pos +end (* (Re)Initialise all comment state *) diff --git a/parsing/docstrings.mli b/parsing/docstrings.mli index 49cea954..bf2508fd 100644 --- a/parsing/docstrings.mli +++ b/parsing/docstrings.mli @@ -13,7 +13,12 @@ (* *) (**************************************************************************) -(** Documentation comments *) +(** Documentation comments + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) (** (Re)Initialise all docstring state *) val init : unit -> unit @@ -158,3 +163,61 @@ val rhs_post_extra_text : int -> text (** Fetch text following the symbol at the given position *) val rhs_post_text : int -> text + +module WithMenhir: sig +(** Fetch the item documentation for the current symbol. This also + marks this documentation (for ambiguity warnings). *) +val symbol_docs : Lexing.position * Lexing.position -> docs +val symbol_docs_lazy : Lexing.position * Lexing.position -> docs Lazy.t + +(** Fetch the item documentation for the symbols between two + positions. This also marks this documentation (for ambiguity + warnings). *) +val rhs_docs : Lexing.position -> Lexing.position -> docs +val rhs_docs_lazy : Lexing.position -> Lexing.position -> docs Lazy.t + +(** Mark the item documentation for the current symbol (for ambiguity + warnings). *) +val mark_symbol_docs : Lexing.position * Lexing.position -> unit + +(** Mark as associated the item documentation for the symbols between + two positions (for ambiguity warnings) *) +val mark_rhs_docs : Lexing.position -> Lexing.position -> unit + +(** Fetch the field info for the current symbol. *) +val symbol_info : Lexing.position -> info + +(** Fetch the field info following the symbol at a given position. *) +val rhs_info : Lexing.position -> info + +(** Fetch the text preceding the current symbol. *) +val symbol_text : Lexing.position -> text +val symbol_text_lazy : Lexing.position -> text Lazy.t + +(** Fetch the text preceding the symbol at the given position. *) +val rhs_text : Lexing.position -> text +val rhs_text_lazy : Lexing.position -> text Lazy.t + +(** {3 Extra text} + + There may be additional text attached to the delimiters of a block + (e.g. [struct] and [end]). This is fetched by the following + functions, which are applied to the contents of the block rather + than the delimiters. *) + +(** Fetch additional text preceding the current symbol *) +val symbol_pre_extra_text : Lexing.position -> text + +(** Fetch additional text following the current symbol *) +val symbol_post_extra_text : Lexing.position -> text + +(** Fetch additional text preceding the symbol at the given position *) +val rhs_pre_extra_text : Lexing.position -> text + +(** Fetch additional text following the symbol at the given position *) +val rhs_post_extra_text : Lexing.position -> text + +(** Fetch text following the symbol at the given position *) +val rhs_post_text : Lexing.position -> text + +end diff --git a/parsing/dune b/parsing/dune new file mode 100644 index 00000000..4198c6b1 --- /dev/null +++ b/parsing/dune @@ -0,0 +1,48 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +;; We're just reusing the stuff from boot/ here. +;; One could add a dune file in boot/menhir/ with the appropriate rules if we +;; want to regenerate the parser while building with dune, but it doesn't seem +;; essential right now. + +(rule + (targets camlinternalMenhirLib.ml) + (mode fallback) + (action (copy# ../boot/menhir/menhirLib.ml %{targets}))) + +(rule + (targets camlinternalMenhirLib.mli) + (mode fallback) + (action (copy# ../boot/menhir/menhirLib.mli %{targets}))) + +(rule + (targets parser.ml) + (mode fallback) + (deps (:dep ../boot/menhir/parser.ml)) + (action + (with-stdout-to %{targets} + (bash "cat %{dep} | sed 's/MenhirLib/CamlinternalMenhirLib/g'")))) + +(rule + (targets parser.mli) + (mode fallback) + (deps (:dep ../boot/menhir/parser.mli)) + (action + (with-stdout-to %{targets} + (bash "cat %{dep} | sed 's/MenhirLib/CamlinternalMenhirLib/g'")))) + +(ocamllex + (modules lexer) + (mode fallback)) diff --git a/parsing/lexer.mli b/parsing/lexer.mli index 63617b48..cde2ad5c 100644 --- a/parsing/lexer.mli +++ b/parsing/lexer.mli @@ -13,7 +13,12 @@ (* *) (**************************************************************************) -(* The lexical analyzer *) +(** The lexical analyzer + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) val init : unit -> unit val token: Lexing.lexbuf -> Parser.token @@ -21,7 +26,8 @@ val skip_hash_bang: Lexing.lexbuf -> unit type error = | Illegal_character of char - | Illegal_escape of string + | Illegal_escape of string * string option + | Reserved_sequence of string * string option | Unterminated_comment of Location.t | Unterminated_string | Unterminated_string_in_comment of Location.t * Location.t @@ -32,11 +38,6 @@ type error = exception Error of error * Location.t -open Format - -val report_error: formatter -> error -> unit - (* Deprecated. Use Location.{error_of_exn, report_error}. *) - val in_comment : unit -> bool;; val in_string : unit -> bool;; diff --git a/parsing/lexer.mll b/parsing/lexer.mll index 89079d4b..64547e2d 100644 --- a/parsing/lexer.mll +++ b/parsing/lexer.mll @@ -22,7 +22,8 @@ open Parser type error = | Illegal_character of char - | Illegal_escape of string + | Illegal_escape of string * string option + | Reserved_sequence of string * string option | Unterminated_comment of Location.t | Unterminated_string | Unterminated_string_in_comment of Location.t * Location.t @@ -133,22 +134,26 @@ let with_comment_buffer comment lexbuf = let loc = { start_loc with Location.loc_end = end_loc.Location.loc_end } in s, loc -(* To translate escape sequences *) +let error lexbuf e = raise (Error(e, Location.curr lexbuf)) +let error_loc loc e = raise (Error(e, loc)) -let hex_digit_value d = (* assert (d in '0'..'9' 'a'..'f' 'A'..'F') *) - let d = Char.code d in - if d >= 97 then d - 87 else - if d >= 65 then d - 55 else - d - 48 +(* to translate escape sequences *) -let hex_num_value lexbuf ~first ~last = - let rec loop acc i = match i > last with - | true -> acc - | false -> - let value = hex_digit_value (Lexing.lexeme_char lexbuf i) in - loop (16 * acc + value) (i + 1) - in - loop 0 first +let digit_value c = + match c with + | 'a' .. 'f' -> 10 + Char.code c - Char.code 'a' + | 'A' .. 'F' -> 10 + Char.code c - Char.code 'A' + | '0' .. '9' -> Char.code c - Char.code '0' + | _ -> assert false + +let num_value lexbuf ~base ~first ~last = + let c = ref 0 in + for i = first to last do + let v = digit_value (Lexing.lexeme_char lexbuf i) in + assert(v < base); + c := (base * !c) + v + done; + !c let char_for_backslash = function | 'n' -> '\010' @@ -157,52 +162,54 @@ let char_for_backslash = function | 't' -> '\009' | c -> c +let illegal_escape lexbuf reason = + let error = Illegal_escape (Lexing.lexeme lexbuf, Some reason) in + raise (Error (error, Location.curr lexbuf)) + let char_for_decimal_code lexbuf i = - let c = 100 * (Char.code(Lexing.lexeme_char lexbuf i) - 48) + - 10 * (Char.code(Lexing.lexeme_char lexbuf (i+1)) - 48) + - (Char.code(Lexing.lexeme_char lexbuf (i+2)) - 48) in + let c = num_value lexbuf ~base:10 ~first:i ~last:(i+2) in if (c < 0 || c > 255) then if in_comment () then 'x' - else raise (Error(Illegal_escape (Lexing.lexeme lexbuf), - Location.curr lexbuf)) + else + illegal_escape lexbuf + (Printf.sprintf + "%d is outside the range of legal characters (0-255)." c) else Char.chr c let char_for_octal_code lexbuf i = - let c = 64 * (Char.code(Lexing.lexeme_char lexbuf i) - 48) + - 8 * (Char.code(Lexing.lexeme_char lexbuf (i+1)) - 48) + - (Char.code(Lexing.lexeme_char lexbuf (i+2)) - 48) in - Char.chr c + let c = num_value lexbuf ~base:8 ~first:i ~last:(i+2) in + if (c < 0 || c > 255) then + if in_comment () + then 'x' + else + illegal_escape lexbuf + (Printf.sprintf + "o%o (=%d) is outside the range of legal characters (0-255)." c c) + else Char.chr c let char_for_hexadecimal_code lexbuf i = - let byte = hex_num_value lexbuf ~first:i ~last:(i+1) in - Char.chr byte + Char.chr (num_value lexbuf ~base:16 ~first:i ~last:(i+1)) let uchar_for_uchar_escape lexbuf = - let err e = - raise - (Error (Illegal_escape (Lexing.lexeme lexbuf ^ e), Location.curr lexbuf)) - in let len = Lexing.lexeme_end lexbuf - Lexing.lexeme_start lexbuf in let first = 3 (* skip opening \u{ *) in let last = len - 2 (* skip closing } *) in let digit_count = last - first + 1 in match digit_count > 6 with - | true -> err ", too many digits, expected 1 to 6 hexadecimal digits" + | true -> + illegal_escape lexbuf + "too many digits, expected 1 to 6 hexadecimal digits" | false -> - let cp = hex_num_value lexbuf ~first ~last in + let cp = num_value lexbuf ~base:16 ~first ~last in if Uchar.is_valid cp then Uchar.unsafe_of_int cp else - err (", " ^ Printf.sprintf "%X" cp ^ " is not a Unicode scalar value") + illegal_escape lexbuf + (Printf.sprintf "%X is not a Unicode scalar value" cp) -(* recover the name from a LABEL or OPTLABEL token *) +let is_keyword name = Hashtbl.mem keyword_table name -let get_label_name lexbuf = - let s = Lexing.lexeme lexbuf in - let name = String.sub s 1 (String.length s - 2) in - if Hashtbl.mem keyword_table name then - raise (Error(Keyword_as_label name, Location.curr lexbuf)); - name -;; +let check_label_name lexbuf name = + if is_keyword name then error lexbuf (Keyword_as_label name) (* Update the current location with file name and line number. *) @@ -226,7 +233,9 @@ let escaped_newlines = ref false (* Warn about Latin-1 characters used in idents *) let warn_latin1 lexbuf = - Location.deprecated (Location.curr lexbuf)"ISO-Latin1 characters in identifiers" + Location.deprecated + (Location.curr lexbuf) + "ISO-Latin1 characters in identifiers" let handle_docstrings = ref true let comment_list = ref [] @@ -246,35 +255,45 @@ let comments () = List.rev !comment_list open Format -let report_error ppf = function +let prepare_error loc = function | Illegal_character c -> - fprintf ppf "Illegal character (%s)" (Char.escaped c) - | Illegal_escape s -> - fprintf ppf "Illegal backslash escape in string or character (%s)" s + Location.errorf ~loc "Illegal character (%s)" (Char.escaped c) + | Illegal_escape (s, explanation) -> + Location.errorf ~loc + "Illegal backslash escape in string or character (%s)%t" s + (fun ppf -> match explanation with + | None -> () + | Some expl -> fprintf ppf ": %s" expl) + | Reserved_sequence (s, explanation) -> + Location.errorf ~loc + "Reserved character sequence: %s%t" s + (fun ppf -> match explanation with + | None -> () + | Some expl -> fprintf ppf " %s" expl) | Unterminated_comment _ -> - fprintf ppf "Comment not terminated" + Location.errorf ~loc "Comment not terminated" | Unterminated_string -> - fprintf ppf "String literal not terminated" - | Unterminated_string_in_comment (_, loc) -> - fprintf ppf "This comment contains an unterminated string literal@.\ - %aString literal begins here" - Location.print_error loc + Location.errorf ~loc "String literal not terminated" + | Unterminated_string_in_comment (_, literal_loc) -> + Location.errorf ~loc + "This comment contains an unterminated string literal" + ~sub:[Location.msg ~loc:literal_loc "String literal begins here"] | Keyword_as_label kwd -> - fprintf ppf "`%s' is a keyword, it cannot be used as label name" kwd + Location.errorf ~loc + "`%s' is a keyword, it cannot be used as label name" kwd | Invalid_literal s -> - fprintf ppf "Invalid literal %s" s + Location.errorf ~loc "Invalid literal %s" s | Invalid_directive (dir, explanation) -> - fprintf ppf "Invalid lexer directive %S" dir; - begin match explanation with - | None -> () - | Some expl -> fprintf ppf ": %s" expl - end + Location.errorf ~loc "Invalid lexer directive %S%t" dir + (fun ppf -> match explanation with + | None -> () + | Some expl -> fprintf ppf ": %s" expl) let () = Location.register_error_of_exn (function | Error (err, loc) -> - Some (Location.error_of_printer loc report_error err) + Some (prepare_error loc err) | _ -> None ) @@ -293,7 +312,10 @@ let identchar_latin1 = let symbolchar = ['!' '$' '%' '&' '*' '+' '-' '.' '/' ':' '<' '=' '>' '?' '@' '^' '|' '~'] let dotsymbolchar = - ['!' '$' '%' '&' '*' '+' '-' '/' ':' '=' '>' '?' '@' '^' '|' '~'] + ['!' '$' '%' '&' '*' '+' '-' '/' ':' '=' '>' '?' '@' '^' '|'] +let kwdopchar = + ['$' '&' '*' '+' '-' '/' '<' '=' '>' '@' '^' '|'] + let decimal_literal = ['0'-'9'] ['0'-'9' '_']* let hex_digit = @@ -318,10 +340,8 @@ let hex_float_literal = let literal_modifier = ['G'-'Z' 'g'-'z'] rule token = parse - | "\\" newline { - if not !escaped_newlines then - raise (Error(Illegal_character (Lexing.lexeme_char lexbuf 0), - Location.curr lexbuf)); + | ('\\' as bs) newline { + if not !escaped_newlines then error lexbuf (Illegal_character bs); update_loc lexbuf None 1 false 0; token lexbuf } | newline @@ -333,36 +353,41 @@ rule token = parse { UNDERSCORE } | "~" { TILDE } - | "~" lowercase identchar * ':' - { LABEL (get_label_name lexbuf) } - | "~" lowercase_latin1 identchar_latin1 * ':' - { warn_latin1 lexbuf; LABEL (get_label_name lexbuf) } + | ".~" + { error lexbuf + (Reserved_sequence (".~", Some "is reserved for use in MetaOCaml")) } + | "~" (lowercase identchar * as name) ':' + { check_label_name lexbuf name; + LABEL name } + | "~" (lowercase_latin1 identchar_latin1 * as name) ':' + { warn_latin1 lexbuf; + LABEL name } | "?" { QUESTION } - | "?" lowercase identchar * ':' - { OPTLABEL (get_label_name lexbuf) } - | "?" lowercase_latin1 identchar_latin1 * ':' - { warn_latin1 lexbuf; OPTLABEL (get_label_name lexbuf) } - | lowercase identchar * - { let s = Lexing.lexeme lexbuf in - try Hashtbl.find keyword_table s - with Not_found -> LIDENT s } - | lowercase_latin1 identchar_latin1 * - { warn_latin1 lexbuf; LIDENT (Lexing.lexeme lexbuf) } - | uppercase identchar * - { UIDENT(Lexing.lexeme lexbuf) } (* No capitalized keywords *) - | uppercase_latin1 identchar_latin1 * - { warn_latin1 lexbuf; UIDENT(Lexing.lexeme lexbuf) } - | int_literal { INT (Lexing.lexeme lexbuf, None) } + | "?" (lowercase identchar * as name) ':' + { check_label_name lexbuf name; + OPTLABEL name } + | "?" (lowercase_latin1 identchar_latin1 * as name) ':' + { warn_latin1 lexbuf; + OPTLABEL name } + | lowercase identchar * as name + { try Hashtbl.find keyword_table name + with Not_found -> LIDENT name } + | lowercase_latin1 identchar_latin1 * as name + { warn_latin1 lexbuf; LIDENT name } + | uppercase identchar * as name + { UIDENT name } (* No capitalized keywords *) + | uppercase_latin1 identchar_latin1 * as name + { warn_latin1 lexbuf; UIDENT name } + | int_literal as lit { INT (lit, None) } | (int_literal as lit) (literal_modifier as modif) { INT (lit, Some modif) } - | float_literal | hex_float_literal - { FLOAT (Lexing.lexeme lexbuf, None) } - | ((float_literal | hex_float_literal) as lit) (literal_modifier as modif) + | float_literal | hex_float_literal as lit + { FLOAT (lit, None) } + | (float_literal | hex_float_literal as lit) (literal_modifier as modif) { FLOAT (lit, Some modif) } - | (float_literal | hex_float_literal | int_literal) identchar+ - { raise (Error(Invalid_literal (Lexing.lexeme lexbuf), - Location.curr lexbuf)) } + | (float_literal | hex_float_literal | int_literal) identchar+ as invalid + { error lexbuf (Invalid_literal invalid) } | "\"" { reset_string_buffer(); is_in_string := true; @@ -372,10 +397,8 @@ rule token = parse is_in_string := false; lexbuf.lex_start_p <- string_start; STRING (get_stored_string(), None) } - | "{" lowercase* "|" + | "{" (lowercase* as delim) "|" { reset_string_buffer(); - let delim = Lexing.lexeme lexbuf in - let delim = String.sub delim 1 (String.length delim - 2) in is_in_string := true; let string_start = lexbuf.lex_start_p in string_start_loc := Location.curr lexbuf; @@ -385,22 +408,20 @@ rule token = parse STRING (get_stored_string(), Some delim) } | "\'" newline "\'" { update_loc lexbuf None 1 false 1; - CHAR (Lexing.lexeme_char lexbuf 1) } - | "\'" [^ '\\' '\'' '\010' '\013'] "\'" - { CHAR(Lexing.lexeme_char lexbuf 1) } - | "\'\\" ['\\' '\'' '\"' 'n' 't' 'b' 'r' ' '] "\'" - { CHAR(char_for_backslash (Lexing.lexeme_char lexbuf 2)) } + (* newline is ('\013'* '\010') *) + CHAR '\n' } + | "\'" ([^ '\\' '\'' '\010' '\013'] as c) "\'" + { CHAR c } + | "\'\\" (['\\' '\'' '\"' 'n' 't' 'b' 'r' ' '] as c) "\'" + { CHAR (char_for_backslash c) } | "\'\\" ['0'-'9'] ['0'-'9'] ['0'-'9'] "\'" { CHAR(char_for_decimal_code lexbuf 2) } - | "\'\\" 'o' ['0'-'3'] ['0'-'7'] ['0'-'7'] "\'" + | "\'\\" 'o' ['0'-'7'] ['0'-'7'] ['0'-'7'] "\'" { CHAR(char_for_octal_code lexbuf 3) } | "\'\\" 'x' ['0'-'9' 'a'-'f' 'A'-'F'] ['0'-'9' 'a'-'f' 'A'-'F'] "\'" { CHAR(char_for_hexadecimal_code lexbuf 3) } - | "\'\\" _ - { let l = Lexing.lexeme lexbuf in - let esc = String.sub l 1 (String.length l - 1) in - raise (Error(Illegal_escape esc, Location.curr lexbuf)) - } + | "\'" ("\\" _ as esc) + { error lexbuf (Illegal_escape (esc, None)) } | "(*" { let s, loc = with_comment_buffer comment lexbuf in COMMENT (s, loc) } @@ -456,7 +477,7 @@ rule token = parse | "->" { MINUSGREATER } | "." { DOT } | ".." { DOTDOT } - | "." (dotsymbolchar symbolchar* as s) { DOTOP s } + | "." (dotsymbolchar symbolchar* as op) { DOTOP op } | ":" { COLON } | "::" { COLONCOLON } | ":=" { COLONEQUAL } @@ -493,28 +514,30 @@ rule token = parse | "-" { MINUS } | "-." { MINUSDOT } - | "!" symbolchar + - { PREFIXOP(Lexing.lexeme lexbuf) } - | ['~' '?'] symbolchar + - { PREFIXOP(Lexing.lexeme lexbuf) } - | ['=' '<' '>' '|' '&' '$'] symbolchar * - { INFIXOP0(Lexing.lexeme lexbuf) } - | ['@' '^'] symbolchar * - { INFIXOP1(Lexing.lexeme lexbuf) } - | ['+' '-'] symbolchar * - { INFIXOP2(Lexing.lexeme lexbuf) } - | "**" symbolchar * - { INFIXOP4(Lexing.lexeme lexbuf) } + | "!" symbolchar + as op + { PREFIXOP op } + | ['~' '?'] symbolchar + as op + { PREFIXOP op } + | ['=' '<' '>' '|' '&' '$'] symbolchar * as op + { INFIXOP0 op } + | ['@' '^'] symbolchar * as op + { INFIXOP1 op } + | ['+' '-'] symbolchar * as op + { INFIXOP2 op } + | "**" symbolchar * as op + { INFIXOP4 op } | '%' { PERCENT } - | ['*' '/' '%'] symbolchar * - { INFIXOP3(Lexing.lexeme lexbuf) } - | '#' (symbolchar | '#') + - { HASHOP(Lexing.lexeme lexbuf) } + | ['*' '/' '%'] symbolchar * as op + { INFIXOP3 op } + | '#' (symbolchar | '#') + as op + { HASHOP op } + | "let" kwdopchar dotsymbolchar * as op + { LETOP op } + | "and" kwdopchar dotsymbolchar * as op + { ANDOP op } | eof { EOF } - | _ - { raise (Error(Illegal_character (Lexing.lexeme_char lexbuf 0), - Location.curr lexbuf)) - } + | (_ as illegal_char) + { error lexbuf (Illegal_character illegal_char) } and directive = parse | ([' ' '\t']* (['0'-'9']+ as num) [' ' '\t']* @@ -524,10 +547,8 @@ and directive = parse match int_of_string num with | exception _ -> (* PR#7165 *) - let loc = Location.curr lexbuf in let explanation = "line number out of range" in - let error = Invalid_directive ("#" ^ directive, Some explanation) in - raise (Error (error, loc)) + error lexbuf (Invalid_directive ("#" ^ directive, Some explanation)) | line_num -> (* Documentation says that the line number should be positive, but we have never guarded against this and it @@ -561,16 +582,13 @@ and comment = parse | loc :: _ -> let start = List.hd (List.rev !comment_start_loc) in comment_start_loc := []; - raise (Error (Unterminated_string_in_comment (start, str_start), - loc)) + error_loc loc (Unterminated_string_in_comment (start, str_start)) end; is_in_string := false; store_string_char '\"'; comment lexbuf } - | "{" lowercase* "|" + | "{" (lowercase* as delim) "|" { - let delim = Lexing.lexeme lexbuf in - let delim = String.sub delim 1 (String.length delim - 2) in string_start_loc := Location.curr lexbuf; store_lexeme lexbuf; is_in_string := true; @@ -581,8 +599,7 @@ and comment = parse | loc :: _ -> let start = List.hd (List.rev !comment_start_loc) in comment_start_loc := []; - raise (Error (Unterminated_string_in_comment (start, str_start), - loc)) + error_loc loc (Unterminated_string_in_comment (start, str_start)) end; is_in_string := false; store_string_char '|'; @@ -611,7 +628,7 @@ and comment = parse | loc :: _ -> let start = List.hd (List.rev !comment_start_loc) in comment_start_loc := []; - raise (Error (Unterminated_comment start, loc)) + error_loc loc (Unterminated_comment start) } | newline { update_loc lexbuf None 1 false 0; @@ -629,14 +646,13 @@ and string = parse if in_comment () then store_lexeme lexbuf; string lexbuf } - | '\\' ['\\' '\'' '\"' 'n' 't' 'b' 'r' ' '] - { store_escaped_char lexbuf - (char_for_backslash(Lexing.lexeme_char lexbuf 1)); + | '\\' (['\\' '\'' '\"' 'n' 't' 'b' 'r' ' '] as c) + { store_escaped_char lexbuf (char_for_backslash c); string lexbuf } | '\\' ['0'-'9'] ['0'-'9'] ['0'-'9'] { store_escaped_char lexbuf (char_for_decimal_code lexbuf 1); string lexbuf } - | '\\' 'o' ['0'-'3'] ['0'-'7'] ['0'-'7'] + | '\\' 'o' ['0'-'7'] ['0'-'7'] ['0'-'7'] { store_escaped_char lexbuf (char_for_octal_code lexbuf 2); string lexbuf } | '\\' 'x' ['0'-'9' 'a'-'f' 'A'-'F'] ['0'-'9' 'a'-'f' 'A'-'F'] @@ -648,8 +664,7 @@ and string = parse | '\\' _ { if not (in_comment ()) then begin (* Should be an error, but we are very lax. - raise (Error (Illegal_escape (Lexing.lexeme lexbuf), - Location.curr lexbuf)) + error lexbuf (Illegal_escape (Lexing.lexeme lexbuf, None)) *) let loc = Location.curr lexbuf in Location.prerr_warning loc Warnings.Illegal_backslash; @@ -666,9 +681,9 @@ and string = parse } | eof { is_in_string := false; - raise (Error (Unterminated_string, !string_start_loc)) } - | _ - { store_string_char(Lexing.lexeme_char lexbuf 0); + error_loc !string_start_loc Unterminated_string } + | (_ as c) + { store_string_char c; string lexbuf } and quoted_string delim = parse @@ -679,23 +694,21 @@ and quoted_string delim = parse } | eof { is_in_string := false; - raise (Error (Unterminated_string, !string_start_loc)) } - | "|" lowercase* "}" + error_loc !string_start_loc Unterminated_string } + | "|" (lowercase* as edelim) "}" { - let edelim = Lexing.lexeme lexbuf in - let edelim = String.sub edelim 1 (String.length edelim - 2) in if delim = edelim then () else (store_lexeme lexbuf; quoted_string delim lexbuf) } - | _ - { store_string_char(Lexing.lexeme_char lexbuf 0); + | (_ as c) + { store_string_char c; quoted_string delim lexbuf } and skip_hash_bang = parse | "#!" [^ '\n']* '\n' [^ '\n']* "\n!#\n" - { update_loc lexbuf None 3 false 0 } + { update_loc lexbuf None 3 false 0 } | "#!" [^ '\n']* '\n' - { update_loc lexbuf None 1 false 0 } + { update_loc lexbuf None 1 false 0 } | "" { () } { diff --git a/parsing/location.ml b/parsing/location.ml index 35184547..1c0cda3a 100644 --- a/parsing/location.ml +++ b/parsing/location.ml @@ -15,19 +15,11 @@ open Lexing -let absname = ref false - (* This reference should be in Clflags, but it would create an additional - dependency and make bootstrapping Camlp4 more difficult. *) - -type t = Warnings.loc = { loc_start: position; loc_end: position; loc_ghost: bool };; +type t = Warnings.loc = + { loc_start: position; loc_end: position; loc_ghost: bool };; let in_file name = - let loc = { - pos_fname = name; - pos_lnum = 1; - pos_bol = 0; - pos_cnum = -1; - } in + let loc = { dummy_pos with pos_fname = name } in { loc_start = loc; loc_end = loc; loc_ghost = true } ;; @@ -66,15 +58,63 @@ let rhs_loc n = { loc_ghost = false; };; +let rhs_interval m n = { + loc_start = Parsing.rhs_start_pos m; + loc_end = Parsing.rhs_end_pos n; + loc_ghost = false; +};; + +(* return file, line, char from the given position *) +let get_pos_info pos = + (pos.pos_fname, pos.pos_lnum, pos.pos_cnum - pos.pos_bol) +;; + +type 'a loc = { + txt : 'a; + loc : t; +} + +let mkloc txt loc = { txt ; loc } +let mknoloc txt = mkloc txt none + +(******************************************************************************) +(* Input info *) + let input_name = ref "_none_" let input_lexbuf = ref (None : lexbuf option) +(******************************************************************************) (* Terminal info *) let status = ref Terminfo.Uninitialised -let num_loc_lines = ref 0 (* number of lines already printed after input *) +let setup_terminal () = + if !status = Terminfo.Uninitialised then + status := Terminfo.setup stdout + +(* The number of lines already printed after input. + + This is used by [highlight_terminfo] to identify the current position of the + input in the terminal. This would not be possible without this information, + since printing several warnings/errors adds text between the user input and + the bottom of the terminal. +*) +let num_loc_lines = ref 0 + +(* This is used by the toplevel to reset [num_loc_lines] before each phrase *) +let reset () = + num_loc_lines := 0 + +(* This is used by the toplevel *) +let echo_eof () = + print_newline (); + incr num_loc_lines +(* Code printing errors and warnings must be wrapped using this function, in + order to update [num_loc_lines]. + + [print_updating_num_loc_lines ppf f arg] is equivalent to calling [f ppf + arg], and additionally updates [num_loc_lines]. *) let print_updating_num_loc_lines ppf f arg = let open Format in let out_functions = pp_get_formatter_out_functions ppf () in @@ -91,9 +131,190 @@ let print_updating_num_loc_lines ppf f arg = pp_print_flush ppf (); pp_set_formatter_out_functions ppf out_functions -(* Highlight the locations using standout mode. *) +let setup_colors () = + Misc.Color.setup !Clflags.color + +(******************************************************************************) +(* Printing locations, e.g. 'File "foo.ml", line 3, characters 10-12' *) + +let rewrite_absolute_path path = + match Misc.get_build_path_prefix_map () with + | None -> path + | Some map -> Build_path_prefix_map.rewrite map path -let highlight_terminfo ppf lb locs = +let absolute_path s = (* This function could go into Filename *) + let open Filename in + let s = + if not (is_relative s) then s + else (rewrite_absolute_path (concat (Sys.getcwd ()) s)) + in + (* Now simplify . and .. components *) + let rec aux s = + let base = basename s in + let dir = dirname s in + if dir = s then dir + else if base = current_dir_name then aux dir + else if base = parent_dir_name then dirname (aux dir) + else concat (aux dir) base + in + aux s + +let show_filename file = + if !Clflags.absname then absolute_path file else file + +let print_filename ppf file = + Format.pp_print_string ppf (show_filename file) + +(* Best-effort printing of the text describing a location, of the form + 'File "foo.ml", line 3, characters 10-12'. + + Some of the information (filename, line number or characters numbers) in the + location might be invalid; in which case we do not print it. + *) +let print_loc ppf loc = + setup_colors (); + let file_valid = function + | "_none_" -> + (* This is a dummy placeholder, but we print it anyway to please editors + that parse locations in error messages (e.g. Emacs). *) + true + | "" | "//toplevel//" -> false + | _ -> true + in + let line_valid line = line > 0 in + let chars_valid ~startchar ~endchar = startchar <> -1 && endchar <> -1 in + + let file = + (* According to the comment in location.mli, if [pos_fname] is "", we must + use [!input_name]. *) + if loc.loc_start.pos_fname = "" then !input_name + else loc.loc_start.pos_fname + in + let line = loc.loc_start.pos_lnum in + let startchar = loc.loc_start.pos_cnum - loc.loc_start.pos_bol in + let endchar = loc.loc_end.pos_cnum - loc.loc_start.pos_bol in + + let first = ref true in + let capitalize s = + if !first then (first := false; String.capitalize_ascii s) + else s in + let comma () = + if !first then () else Format.fprintf ppf ", " in + + Format.fprintf ppf "@{"; + + if file_valid file then + Format.fprintf ppf "%s \"%a\"" (capitalize "file") print_filename file; + + (* Print "line 1" in the case of a dummy line number. This is to please the + existing setup of editors that parse locations in error messages (e.g. + Emacs). *) + comma (); + Format.fprintf ppf "%s %i" (capitalize "line") + (if line_valid line then line else 1); + + if chars_valid ~startchar ~endchar then ( + comma (); + Format.fprintf ppf "%s %i-%i" (capitalize "characters") startchar endchar + ); + + Format.fprintf ppf "@}" + +(* Print a comma-separated list of locations *) +let print_locs ppf locs = + Format.pp_print_list ~pp_sep:(fun ppf () -> Format.fprintf ppf ",@ ") + print_loc ppf locs + +(******************************************************************************) +(* An interval set structure; additionally, it stores user-provided information + at interval boundaries. + + The implementation provided here is naive and assumes the number of intervals + to be small, but the interface would allow for a more efficient + implementation if needed. + + Note: the structure only stores maximal intervals (that therefore do not + overlap). +*) + +module ISet : sig + type 'a bound = 'a * int + type 'a t + (* bounds are included *) + val of_intervals : ('a bound * 'a bound) list -> 'a t + + val mem : 'a t -> pos:int -> bool + val find_bound_in : 'a t -> range:(int * int) -> 'a bound option + + val is_start : 'a t -> pos:int -> 'a option + val is_end : 'a t -> pos:int -> 'a option + + val extrema : 'a t -> ('a bound * 'a bound) option +end += +struct + type 'a bound = 'a * int + + (* non overlapping intervals *) + type 'a t = ('a bound * 'a bound) list + + let of_intervals intervals = + let pos = + List.map (fun ((a, x), (b, y)) -> + if x > y then [] else [((a, x), `S); ((b, y), `E)] + ) intervals + |> List.flatten + |> List.sort (fun ((_, x), k) ((_, y), k') -> + (* Make `S come before `E so that consecutive intervals get merged + together in the fold below *) + let kn = function `S -> 0 | `E -> 1 in + compare (x, kn k) (y, kn k')) + in + let nesting, acc = + List.fold_left (fun (nesting, acc) (a, kind) -> + match kind, nesting with + | `S, `Outside -> `Inside (a, 0), acc + | `S, `Inside (s, n) -> `Inside (s, n+1), acc + | `E, `Outside -> assert false + | `E, `Inside (s, 0) -> `Outside, ((s, a) :: acc) + | `E, `Inside (s, n) -> `Inside (s, n-1), acc + ) (`Outside, []) pos in + assert (nesting = `Outside); + List.rev acc + + let mem iset ~pos = + List.exists (fun ((_, s), (_, e)) -> s <= pos && pos <= e) iset + + let find_bound_in iset ~range:(start, end_) = + Misc.Stdlib.List.find_map (fun ((a, x), (b, y)) -> + if start <= x && x <= end_ then Some (a, x) + else if start <= y && y <= end_ then Some (b, y) + else None + ) iset + + let is_start iset ~pos = + Misc.Stdlib.List.find_map (fun ((a, x), _) -> + if pos = x then Some a else None + ) iset + + let is_end iset ~pos = + Misc.Stdlib.List.find_map (fun (_, (b, y)) -> + if pos = y then Some b else None + ) iset + + let extrema iset = + if iset = [] then None + else Some (fst (List.hd iset), snd (List.hd (List.rev iset))) +end + +(******************************************************************************) +(* Toplevel: highlighting and quoting locations *) + +(* Highlight the locations using standout mode. + + If [locs] is empty, this function is a no-op. +*) +let highlight_terminfo lb ppf locs = Format.pp_print_flush ppf (); (* avoid mixing Format and normal output *) (* Char 0 is at offset -lb.lex_abs_pos in lb.lex_buffer. *) let pos0 = -lb.lex_abs_pos in @@ -127,294 +348,515 @@ let highlight_terminfo ppf lb locs = Terminfo.resume stdout !num_loc_lines; flush stdout -(* Highlight the location by printing it again. *) +let highlight_terminfo lb ppf locs = + try highlight_terminfo lb ppf locs + with Exit -> () -let highlight_dumb ~print_chars ppf lb loc = - (* Char 0 is at offset -lb.lex_abs_pos in lb.lex_buffer. *) - let pos0 = -lb.lex_abs_pos in - (* Do nothing if the buffer does not contain the whole phrase. *) - if pos0 < 0 then raise Exit; - let end_pos = lb.lex_buffer_len - pos0 - 1 in - (* Determine line numbers for the start and end points *) - let line_start = ref 0 and line_end = ref 0 in - for pos = 0 to end_pos do - if Bytes.get lb.lex_buffer (pos + pos0) = '\n' then begin - if loc.loc_start.pos_cnum > pos then incr line_start; - if loc.loc_end.pos_cnum > pos then incr line_end; - end - done; - Format.fprintf ppf "@["; - (* Print character location (useful for Emacs) *) - if print_chars then begin - Format.fprintf ppf "Characters %i-%i:@," - loc.loc_start.pos_cnum loc.loc_end.pos_cnum - end; - (* Print the input, underlining the location *) - Format.pp_print_string ppf " "; - let line = ref 0 in - let pos_at_bol = ref 0 in - for pos = 0 to end_pos do - match Bytes.get lb.lex_buffer (pos + pos0) with - | '\n' -> - if !line = !line_start && !line = !line_end then begin - (* loc is on one line: underline location *) - Format.fprintf ppf "@, "; - for _i = !pos_at_bol to loc.loc_start.pos_cnum - 1 do - Format.pp_print_char ppf ' ' - done; - for _i = loc.loc_start.pos_cnum to loc.loc_end.pos_cnum - 1 do - Format.pp_print_char ppf '^' - done - end; - if !line >= !line_start && !line <= !line_end then begin - Format.fprintf ppf "@,"; - if pos < loc.loc_end.pos_cnum then Format.pp_print_string ppf " " - end; - incr line; - pos_at_bol := pos + 1 - | '\r' -> () (* discard *) - | c -> - if !line = !line_start && !line = !line_end then - (* loc is on one line: print whole line *) - Format.pp_print_char ppf c - else if !line = !line_start then - (* first line of multiline loc: - print a dot for each char before loc_start *) - if pos < loc.loc_start.pos_cnum then - Format.pp_print_char ppf '.' - else - Format.pp_print_char ppf c - else if !line = !line_end then - (* last line of multiline loc: print a dot for each char - after loc_end, even whitespaces *) - if pos < loc.loc_end.pos_cnum then - Format.pp_print_char ppf c - else - Format.pp_print_char ppf '.' - else if !line > !line_start && !line < !line_end then - (* intermediate line of multiline loc: print whole line *) - Format.pp_print_char ppf c - done; - Format.fprintf ppf "@]" - -let show_code_at_location ppf lb loc = - highlight_dumb ~print_chars:false ppf lb loc - -(* Highlight the location using one of the supported modes. *) - -let rec highlight_locations ppf locs = - match !status with - Terminfo.Uninitialised -> - status := Terminfo.setup stdout; highlight_locations ppf locs - | Terminfo.Bad_term -> - begin match !input_lexbuf with - None -> false - | Some lb -> - let norepeat = - try Sys.getenv "TERM" = "norepeat" with Not_found -> false in - if norepeat then false else - let loc1 = List.hd locs in - try highlight_dumb ~print_chars:true ppf lb loc1; true - with Exit -> false - end - | Terminfo.Good_term -> - begin match !input_lexbuf with - None -> false - | Some lb -> - try highlight_terminfo ppf lb locs; true - with Exit -> false - end +(* Highlight the location by printing it again. -(* Print the location in some way or another *) - -open Format - -let rewrite_absolute_path = - let init = ref false in - let map_cache = ref None in - fun path -> - if not !init then begin - init := true; - match Sys.getenv "BUILD_PATH_PREFIX_MAP" with - | exception Not_found -> () - | encoded_map -> - match Build_path_prefix_map.decode_map encoded_map with - | Error err -> - Misc.fatal_errorf - "Invalid value for the environment variable \ - BUILD_PATH_PREFIX_MAP: %s" err - | Ok map -> map_cache := Some map - end; - match !map_cache with - | None -> path - | Some map -> Build_path_prefix_map.rewrite map path + There are two different styles for highlighting errors in "dumb" mode, + depending if the error fits on a single line or spans across several lines. -let absolute_path s = (* This function could go into Filename *) - let open Filename in - let s = - if not (is_relative s) then s - else (rewrite_absolute_path (concat (Sys.getcwd ()) s)) - in - (* Now simplify . and .. components *) - let rec aux s = - let base = basename s in - let dir = dirname s in - if dir = s then dir - else if base = current_dir_name then aux dir - else if base = parent_dir_name then dirname (aux dir) - else concat (aux dir) base - in - aux s + For single-line errors, -let show_filename file = - if !absname then absolute_path file else file + foo the_error bar -let print_filename ppf file = - Format.fprintf ppf "%s" (show_filename file) + gets displayed as follows, where X is the line number: -let reset () = - num_loc_lines := 0 + X | foo the_error bar + ^^^^^^^^^ -let (msg_file, msg_line, msg_chars, msg_to, msg_colon) = - ("File \"", "\", line ", ", characters ", "-", ":") -(* return file, line, char from the given position *) -let get_pos_info pos = - (pos.pos_fname, pos.pos_lnum, pos.pos_cnum - pos.pos_bol) -;; + For multi-line errors, -let setup_colors () = - Misc.Color.setup !Clflags.color + foo the_ + error bar -let print_loc ppf loc = - setup_colors (); - let (file, line, startchar) = get_pos_info loc.loc_start in - let endchar = loc.loc_end.pos_cnum - loc.loc_start.pos_cnum + startchar in - if file = "//toplevel//" then begin - if highlight_locations ppf [loc] then () else - fprintf ppf "Characters %i-%i" - loc.loc_start.pos_cnum loc.loc_end.pos_cnum + gets displayed as: + + X1 | ....the_ + X2 | error.... + + An ellipsis hides the middle lines of the multi-line error if it has more + than [max_lines] lines. + + If [locs] is empty then this function is a no-op. +*) + +type input_line = { + text : string; + start_pos : int; +} + +(* Takes a list of lines with possibly missing line numbers. + + If the line numbers that are present are consistent with the number of lines + between them, then infer the intermediate line numbers. + + This is not always the case, typically if lexer line directives are + involved... *) +let infer_line_numbers + (lines: (int option * input_line) list): + (int option * input_line) list + = + let (_, offset, consistent) = + List.fold_left (fun (i, offset, consistent) (lnum, _) -> + match lnum, offset with + | None, _ -> (i+1, offset, consistent) + | Some n, None -> (i+1, Some (n - i), consistent) + | Some n, Some m -> (i+1, offset, consistent && n = m + i) + ) (0, None, true) lines + in + match offset, consistent with + | Some m, true -> + List.mapi (fun i (_, line) -> (Some (m + i), line)) lines + | _, _ -> + lines + +(* [get_lines] must return the lines to highlight, given starting and ending + positions. + + See [lines_around_from_current_input] below for an instantiation of + [get_lines] that reads from the current input. +*) +let highlight_quote ppf + ~(get_lines: start_pos:position -> end_pos:position -> input_line list) + ?(max_lines = 10) + highlight_tag + locs + = + let iset = ISet.of_intervals @@ List.filter_map (fun loc -> + let s, e = loc.loc_start, loc.loc_end in + if s.pos_cnum = -1 || e.pos_cnum = -1 then None + else Some ((s, s.pos_cnum), (e, e.pos_cnum - 1)) + ) locs in + match ISet.extrema iset with + | None -> () + | Some ((leftmost, _), (rightmost, _)) -> + let lines = + get_lines ~start_pos:leftmost ~end_pos:rightmost + |> List.map (fun ({ text; start_pos } as line) -> + let end_pos = start_pos + String.length text - 1 in + let line_nb = + match ISet.find_bound_in iset ~range:(start_pos, end_pos) with + | None -> None + | Some (p, _) -> Some p.pos_lnum + in + (line_nb, line)) + |> infer_line_numbers + |> List.map (fun (lnum, { text; start_pos }) -> + (text, + Misc.Stdlib.Option.value_default Int.to_string ~default:"" lnum, + start_pos)) + in + Format.fprintf ppf "@["; + begin match lines with + | [] | [("", _, _)] -> () + | [(line, line_nb, line_start_cnum)] -> + (* Single-line error *) + Format.fprintf ppf "%s | %s@," line_nb line; + Format.fprintf ppf "%*s " (String.length line_nb) ""; + for pos = line_start_cnum to rightmost.pos_cnum - 1 do + if ISet.is_start iset ~pos <> None then + Format.fprintf ppf "@{<%s>" highlight_tag; + if ISet.mem iset ~pos then Format.pp_print_char ppf '^' + else Format.pp_print_char ppf ' '; + if ISet.is_end iset ~pos <> None then + Format.fprintf ppf "@}" + done; + Format.fprintf ppf "@}@," + | _ -> + (* Multi-line error *) + Misc.pp_two_columns ~sep:"|" ~max_lines ppf + @@ List.map (fun (line, line_nb, line_start_cnum) -> + let line = String.mapi (fun i car -> + if ISet.mem iset ~pos:(line_start_cnum + i) then car else '.' + ) line in + (line_nb, line) + ) lines + end; + Format.fprintf ppf "@]" + + + +let lines_around + ~(start_pos: position) ~(end_pos: position) + ~(seek: int -> unit) + ~(read_char: unit -> char option): + input_line list + = + seek start_pos.pos_bol; + let lines = ref [] in + let bol = ref start_pos.pos_bol in + let cur = ref start_pos.pos_bol in + let b = Buffer.create 80 in + let add_line () = + if !bol < !cur then begin + let text = Buffer.contents b in + Buffer.clear b; + lines := { text; start_pos = !bol } :: !lines; + bol := !cur + end + in + let rec loop () = + if !bol >= end_pos.pos_cnum then () + else begin + match read_char () with + | None -> + (* end of input *) + add_line () + | Some c -> + incr cur; + match c with + | '\r' -> loop () + | '\n' -> add_line (); loop () + | _ -> Buffer.add_char b c; loop () + end + in + loop (); + List.rev !lines + +(* Try to get lines from a lexbuf *) +let lines_around_from_lexbuf + ~(start_pos: position) ~(end_pos: position) + (lb: lexbuf): + input_line list + = + (* Converts a global position to one that is relative to the lexing buffer *) + let rel n = n - lb.lex_abs_pos in + if rel start_pos.pos_bol < 0 then begin + (* Do nothing if the buffer does not contain the input (because it has been + refilled while lexing it) *) + [] end else begin - fprintf ppf "%s@{%a%s%i" msg_file print_filename file msg_line line; - if startchar >= 0 then - fprintf ppf "%s%i%s%i" msg_chars startchar msg_to endchar; - fprintf ppf "@}" + let pos = ref 0 in (* relative position *) + let seek n = pos := rel n in + let read_char () = + if !pos >= lb.lex_buffer_len then (* end of buffer *) None + else + let c = Bytes.get lb.lex_buffer !pos in + incr pos; Some c + in + lines_around ~start_pos ~end_pos ~seek ~read_char end -;; -let default_printer ppf loc = - setup_colors (); - if loc.loc_start.pos_fname = "//toplevel//" - && highlight_locations ppf [loc] then () - else fprintf ppf "@{%a@}%s@," print_loc loc msg_colon -;; +(* Get lines from a file *) +let lines_around_from_file + ~(start_pos: position) ~(end_pos: position) + (filename: string): + input_line list + = + try + let cin = open_in_bin filename in + let read_char () = + try Some (input_char cin) with End_of_file -> None + in + let lines = + lines_around ~start_pos ~end_pos ~seek:(seek_in cin) ~read_char + in + close_in cin; + lines + with Sys_error _ -> [] + +(* A [get_lines] function for [highlight_quote] that reads from the current + input. + + It first tries to read from [!input_lexbuf], then if that fails (because the + lexbuf no longer contains the input we want), it reads from [!input_name] + directly *) +let lines_around_from_current_input ~start_pos ~end_pos = + (* Be a bit defensive, and do not try to open one of the possible + [!input_name] values that we know do not denote valid filenames. *) + let file_valid = function + | "//toplevel//" | "_none_" | "" -> false + | _ -> true + in + let from_file () = + if file_valid !input_name then + lines_around_from_file !input_name ~start_pos ~end_pos + else + [] + in + match !input_lexbuf with + | Some lb -> + begin match lines_around_from_lexbuf lb ~start_pos ~end_pos with + | [] -> (* The input is likely not in the lexbuf anymore *) + from_file () + | lines -> + lines + end + | None -> + from_file () -let printer = ref default_printer -let print ppf loc = !printer ppf loc +(******************************************************************************) +(* Reporting errors and warnings *) -let error_prefix = "Error" -let warning_prefix = "Warning" +type msg = (Format.formatter -> unit) loc -let print_error_prefix ppf = - setup_colors (); - fprintf ppf "@{%s@}" error_prefix; -;; +let msg ?(loc = none) fmt = + Format.kdprintf (fun txt -> { loc; txt }) fmt -let print_compact ppf loc = - if loc.loc_start.pos_fname = "//toplevel//" - && highlight_locations ppf [loc] then () - else begin - let (file, line, startchar) = get_pos_info loc.loc_start in - let endchar = loc.loc_end.pos_cnum - loc.loc_start.pos_cnum + startchar in - fprintf ppf "%a:%i" print_filename file line; - if startchar >= 0 then fprintf ppf ",%i--%i" startchar endchar - end -;; +type report_kind = + | Report_error + | Report_warning of string + | Report_warning_as_error of string + | Report_alert of string + | Report_alert_as_error of string -let print_error ppf loc = - fprintf ppf "%a%t:" print loc print_error_prefix; -;; +type report = { + kind : report_kind; + main : msg; + sub : msg list; +} -let print_error_cur_file ppf () = print_error ppf (in_file !input_name);; +type report_printer = { + (* The entry point *) + pp : report_printer -> + Format.formatter -> report -> unit; + + pp_report_kind : report_printer -> report -> + Format.formatter -> report_kind -> unit; + pp_main_loc : report_printer -> report -> + Format.formatter -> t -> unit; + pp_main_txt : report_printer -> report -> + Format.formatter -> (Format.formatter -> unit) -> unit; + pp_submsgs : report_printer -> report -> + Format.formatter -> msg list -> unit; + pp_submsg : report_printer -> report -> + Format.formatter -> msg -> unit; + pp_submsg_loc : report_printer -> report -> + Format.formatter -> t -> unit; + pp_submsg_txt : report_printer -> report -> + Format.formatter -> (Format.formatter -> unit) -> unit; +} -let default_warning_printer loc ppf w = - match Warnings.report w with - | `Inactive -> () - | `Active { Warnings. number; message; is_error; sub_locs } -> +let is_dummy_loc loc = + (* Fixme: this should be just [loc.loc_ghost] and the function should be + inlined below. However, currently, the compiler emits in some places ghost + locations with valid ranges that should still be printed. These locations + should be made non-ghost -- in the meantime we just check if the ranges are + valid. *) + loc.loc_start.pos_cnum = -1 || loc.loc_end.pos_cnum = -1 + +(* It only makes sense to highlight (i.e. quote or underline the corresponding + source code) locations that originate from the current input. + + As of now, this should only happen in the following cases: + + - if dummy locs or ghost locs leak out of the compiler or a buggy ppx; + + - more generally, if some code uses the compiler-libs API and feeds it + locations that do not match the current values of [!Location.input_name], + [!Location.input_lexbuf]; + + - when calling the compiler on a .ml file that contains lexer line directives + indicating an other file. This should happen relatively rarely in practice -- + in particular this is not what happens when using -pp or -ppx or a ppx + driver. +*) +let is_quotable_loc loc = + not (is_dummy_loc loc) + && loc.loc_start.pos_fname = !input_name + && loc.loc_end.pos_fname = !input_name + +let error_style () = + let open Misc.Error_style in + match !Clflags.error_style with + | Some Contextual | None -> Contextual + | Some Short -> Short + +let batch_mode_printer : report_printer = + let pp_loc _self report ppf loc = + let tag = match report.kind with + | Report_warning_as_error _ + | Report_alert_as_error _ + | Report_error -> "error" + | Report_warning _ + | Report_alert _ -> "warning" + in + let highlight ppf loc = + match error_style () with + | Misc.Error_style.Contextual -> + if is_quotable_loc loc then + highlight_quote ppf + ~get_lines:lines_around_from_current_input + tag [loc] + | Misc.Error_style.Short -> + () + in + Format.fprintf ppf "@[%a:@ %a@]" print_loc loc highlight loc + in + let pp_txt ppf txt = Format.fprintf ppf "@[%t@]" txt in + let pp self ppf report = setup_colors (); - fprintf ppf "@["; - print ppf loc; - if is_error - then - fprintf ppf "%t (%s %d): %s@," print_error_prefix - (String.uncapitalize_ascii warning_prefix) number message - else fprintf ppf "@{%s@} %d: %s@," warning_prefix number message; - List.iter - (fun (loc, msg) -> - if loc <> none then fprintf ppf " %a %s@," print loc msg - ) - sub_locs; - fprintf ppf "@]" -;; + (* Make sure we keep [num_loc_lines] updated. *) + print_updating_num_loc_lines ppf (fun ppf () -> + Format.fprintf ppf "@[%a%a: %a%a@]@." + (self.pp_main_loc self report) report.main.loc + (self.pp_report_kind self report) report.kind + (self.pp_main_txt self report) report.main.txt + (self.pp_submsgs self report) report.sub + ) () + in + let pp_report_kind _self _ ppf = function + | Report_error -> Format.fprintf ppf "@{Error@}" + | Report_warning w -> Format.fprintf ppf "@{Warning@} %s" w + | Report_warning_as_error w -> + Format.fprintf ppf "@{Error@} (warning %s)" w + | Report_alert w -> Format.fprintf ppf "@{Alert@} %s" w + | Report_alert_as_error w -> + Format.fprintf ppf "@{Error@} (alert %s)" w + in + let pp_main_loc self report ppf loc = + pp_loc self report ppf loc + in + let pp_main_txt _self _ ppf txt = + pp_txt ppf txt + in + let pp_submsgs self report ppf msgs = + List.iter (fun msg -> + Format.fprintf ppf "@,%a" (self.pp_submsg self report) msg + ) msgs + in + let pp_submsg self report ppf { loc; txt } = + Format.fprintf ppf "@[%a %a@]" + (self.pp_submsg_loc self report) loc + (self.pp_submsg_txt self report) txt + in + let pp_submsg_loc self report ppf loc = + if not loc.loc_ghost then + pp_loc self report ppf loc + in + let pp_submsg_txt _self _ ppf loc = + pp_txt ppf loc + in + { pp; pp_report_kind; pp_main_loc; pp_main_txt; + pp_submsgs; pp_submsg; pp_submsg_loc; pp_submsg_txt } + +let terminfo_toplevel_printer (lb: lexbuf): report_printer = + let pp self ppf err = + setup_colors (); + (* Highlight all toplevel locations of the report, instead of displaying + the main location. Do it now instead of in [pp_main_loc], to avoid + messing with Format boxes. *) + let sub_locs = List.map (fun { loc; _ } -> loc) err.sub in + let all_locs = err.main.loc :: sub_locs in + let locs_highlighted = List.filter is_quotable_loc all_locs in + highlight_terminfo lb ppf locs_highlighted; + batch_mode_printer.pp self ppf err + in + let pp_main_loc _ _ _ _ = () in + let pp_submsg_loc _ _ ppf loc = + Format.fprintf ppf "%a:@ " print_loc loc in + { batch_mode_printer with pp; pp_main_loc; pp_submsg_loc } -let warning_printer = ref default_warning_printer ;; +let best_toplevel_printer () = + setup_terminal (); + match !status, !input_lexbuf with + | Terminfo.Good_term, Some lb -> + terminfo_toplevel_printer lb + | _, _ -> + batch_mode_printer -let print_warning loc ppf w = - print_updating_num_loc_lines ppf (!warning_printer loc) w -;; +(* Creates a printer for the current input *) +let default_report_printer () : report_printer = + if !input_name = "//toplevel//" then + best_toplevel_printer () + else + batch_mode_printer -let formatter_for_warnings = ref err_formatter;; -let prerr_warning loc w = print_warning loc !formatter_for_warnings w;; +let report_printer = ref default_report_printer -let echo_eof () = - print_newline (); - incr num_loc_lines +let print_report ppf report = + let printer = !report_printer () in + printer.pp printer ppf report -type 'a loc = { - txt : 'a; - loc : t; -} +(******************************************************************************) +(* Reporting errors *) -let mkloc txt loc = { txt ; loc } -let mknoloc txt = mkloc txt none +type error = report +let report_error ppf err = + print_report ppf err -type error = - { - loc: t; - msg: string; - sub: error list; - if_highlight: string; (* alternative message if locations are highlighted *) - } +let mkerror loc sub txt = + { kind = Report_error; main = { loc; txt }; sub } + +let errorf ?(loc = none) ?(sub = []) = + Format.kdprintf (mkerror loc sub) + +let error ?(loc = none) ?(sub = []) msg_str = + mkerror loc sub (fun ppf -> Format.pp_print_string ppf msg_str) + +let error_of_printer ?(loc = none) ?(sub = []) pp x = + mkerror loc sub (fun ppf -> pp ppf x) + +let error_of_printer_file print x = + error_of_printer ~loc:(in_file !input_name) print x + +(******************************************************************************) +(* Reporting warnings: generating a report from a warning number using the + information in [Warnings] + convenience functions. *) + +let default_warning_alert_reporter report mk (loc: t) w : report option = + match report w with + | `Inactive -> None + | `Active { Warnings.id; message; is_error; sub_locs } -> + let msg_of_str str = fun ppf -> Format.pp_print_string ppf str in + let kind = mk is_error id in + let main = { loc; txt = msg_of_str message } in + let sub = List.map (fun (loc, sub_message) -> + { loc; txt = msg_of_str sub_message } + ) sub_locs in + Some { kind; main; sub } + + +let default_warning_reporter = + default_warning_alert_reporter + Warnings.report + (fun is_error id -> + if is_error then Report_warning_as_error id + else Report_warning id + ) + +let warning_reporter = ref default_warning_reporter +let report_warning loc w = !warning_reporter loc w -let pp_ksprintf ?before k fmt = - let buf = Buffer.create 64 in - let ppf = Format.formatter_of_buffer buf in - Misc.Color.set_color_tag_handling ppf; - begin match before with - | None -> () - | Some f -> f ppf - end; - kfprintf - (fun _ -> - pp_print_flush ppf (); - let msg = Buffer.contents buf in - k msg) - ppf fmt - -(* Shift the formatter's offset by the length of the error prefix, which - is always added by the compiler after the message has been formatted *) -let print_phanton_error_prefix ppf = - Format.pp_print_as ppf (String.length error_prefix + 2 (* ": " *)) "" - -let errorf ?(loc = none) ?(sub = []) ?(if_highlight = "") fmt = - pp_ksprintf - ~before:print_phanton_error_prefix - (fun msg -> {loc; msg; sub; if_highlight}) - fmt - -let error ?(loc = none) ?(sub = []) ?(if_highlight = "") msg = - {loc; msg; sub; if_highlight} +let formatter_for_warnings = ref Format.err_formatter + +let print_warning loc ppf w = + match report_warning loc w with + | None -> () + | Some report -> print_report ppf report + +let prerr_warning loc w = print_warning loc !formatter_for_warnings w + +let default_alert_reporter = + default_warning_alert_reporter + Warnings.report_alert + (fun is_error id -> + if is_error then Report_alert_as_error id + else Report_alert id + ) + +let alert_reporter = ref default_alert_reporter +let report_alert loc w = !alert_reporter loc w + +let print_alert loc ppf w = + match report_alert loc w with + | None -> () + | Some report -> print_report ppf report + +let prerr_alert loc w = print_alert loc !formatter_for_warnings w + +let alert ?(def = none) ?(use = none) ~kind loc message = + prerr_alert loc {Warnings.kind; message; def; use} + +let deprecated ?def ?use loc message = + alert ?def ?use ~kind:"deprecated" loc message + +(******************************************************************************) +(* Reporting errors on exceptions *) let error_of_exn : (exn -> error option) list ref = ref [] @@ -435,69 +877,36 @@ let error_of_exn exn = in loop !error_of_exn -let rec default_error_reporter ppf ({loc; msg; sub; if_highlight} as err) = - let highlighted = - if if_highlight <> "" && loc.loc_start.pos_fname = "//toplevel//" then - let rec collect_locs locs {loc; sub; _} = - List.fold_left collect_locs (loc :: locs) sub - in - let locs = collect_locs [] err in - highlight_locations ppf locs - else - false - in - if highlighted then - Format.pp_print_string ppf if_highlight - else begin - fprintf ppf "@[%a %s" print_error loc msg; - List.iter (Format.fprintf ppf "@,@[<2>%a@]" default_error_reporter) sub; - fprintf ppf "@]" - end - -let error_reporter = ref default_error_reporter - -let report_error ppf err = - print_updating_num_loc_lines ppf !error_reporter err -;; - -let error_of_printer loc print x = - errorf ~loc "%a@?" print x - -let error_of_printer_file print x = - error_of_printer (in_file !input_name) print x - let () = register_error_of_exn (function | Sys_error msg -> - Some (errorf ~loc:(in_file !input_name) - "I/O error: %s" msg) + Some (errorf ~loc:(in_file !input_name) "I/O error: %s" msg) | Misc.HookExnWrapper {error = e; hook_name; hook_info={Misc.sourcefile}} -> let sub = match error_of_exn e with - | None | Some `Already_displayed -> error (Printexc.to_string e) - | Some (`Ok err) -> err + | None | Some `Already_displayed -> + [msg "%s" (Printexc.to_string e)] + | Some (`Ok err) -> + (msg ~loc:err.main.loc "%t" err.main.txt) :: err.sub in Some - (errorf ~loc:(in_file sourcefile) - "In hook %S:" hook_name - ~sub:[sub]) + (errorf ~loc:(in_file sourcefile) ~sub "In hook %S:" hook_name) | _ -> None ) external reraise : exn -> 'a = "%reraise" -let rec report_exception_rec n ppf exn = - try +let report_exception ppf exn = + let rec loop n exn = match error_of_exn exn with | None -> reraise exn | Some `Already_displayed -> () - | Some (`Ok err) -> fprintf ppf "@[%a@]@." report_error err - with exn when n > 0 -> report_exception_rec (n-1) ppf exn - -let report_exception ppf exn = report_exception_rec 5 ppf exn - + | Some (`Ok err) -> report_error ppf err + | exception exn when n > 0 -> loop (n-1) exn + in + loop 5 exn exception Error of error @@ -508,10 +917,5 @@ let () = | _ -> None ) -let raise_errorf ?(loc = none) ?(sub = []) ?(if_highlight = "") = - pp_ksprintf - ~before:print_phanton_error_prefix - (fun msg -> raise (Error ({loc; msg; sub; if_highlight}))) - -let deprecated ?(def = none) ?(use = none) loc msg = - prerr_warning loc (Warnings.Deprecated (msg, def, use)) +let raise_errorf ?(loc = none) ?(sub = []) = + Format.kdprintf (fun txt -> raise (Error (mkerror loc sub txt))) diff --git a/parsing/location.mli b/parsing/location.mli index bf93f168..b1c3e013 100644 --- a/parsing/location.mli +++ b/parsing/location.mli @@ -13,7 +13,12 @@ (* *) (**************************************************************************) -(** Source code locations (ranges of positions), used in parsetree. *) +(** {1 Source code locations (ranges of positions), used in parsetree} + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) open Format @@ -50,32 +55,10 @@ val symbol_gloc: unit -> t at 1, in the current parser rule. *) val rhs_loc: int -> t -val input_name: string ref -val input_lexbuf: Lexing.lexbuf option ref - -val get_pos_info: Lexing.position -> string * int * int (* file, line, char *) -val print_loc: formatter -> t -> unit -val print_error_prefix: formatter -> unit -val print_error: formatter -> t -> unit -val print_error_cur_file: formatter -> unit -> unit -val print_warning: t -> formatter -> Warnings.t -> unit -val formatter_for_warnings : formatter ref -val prerr_warning: t -> Warnings.t -> unit -val echo_eof: unit -> unit -val reset: unit -> unit - -val default_printer : formatter -> t -> unit -val printer : (formatter -> t -> unit) ref - -val warning_printer : (t -> formatter -> Warnings.t -> unit) ref -(** Hook for intercepting warnings. *) - -val default_warning_printer : t -> formatter -> Warnings.t -> unit -(** Original warning printer for use in hooks. *) - -val highlight_locations: formatter -> t list -> bool +val rhs_interval: int -> int -> t -val show_code_at_location: formatter -> Lexing.lexbuf -> t -> unit +val get_pos_info: Lexing.position -> string * int * int +(** file, line, char *) type 'a loc = { txt : 'a; @@ -85,9 +68,20 @@ type 'a loc = { val mknoloc : 'a -> 'a loc val mkloc : 'a -> t -> 'a loc -val print: formatter -> t -> unit -val print_compact: formatter -> t -> unit -val print_filename: formatter -> string -> unit + +(** {1 Input info} *) + +val input_name: string ref +val input_lexbuf: Lexing.lexbuf option ref + + +(** {1 Toplevel-specific functions} *) + +val echo_eof: unit -> unit +val reset: unit -> unit + + +(** {1 Printing locations} *) val rewrite_absolute_path: string -> string (** rewrite absolute path to honor the BUILD_PATH_PREFIX_MAP @@ -100,35 +94,163 @@ val show_filename: string -> string (** In -absname mode, return the absolute path for this filename. Otherwise, returns the filename unchanged. *) +val print_filename: formatter -> string -> unit -val absname: bool ref +val print_loc: formatter -> t -> unit +val print_locs: formatter -> t list -> unit -(** Support for located errors *) -type error = - { - loc: t; - msg: string; - sub: error list; - if_highlight: string; (* alternative message if locations are highlighted *) - } +(** {1 Toplevel-specific location highlighting} *) -exception Already_displayed_error -exception Error of error +val highlight_terminfo: + Lexing.lexbuf -> formatter -> t list -> unit + + +(** {1 Reporting errors and warnings} *) + +(** {2 The type of reports and report printers} *) + +type msg = (Format.formatter -> unit) loc + +val msg: ?loc:t -> ('a, Format.formatter, unit, msg) format4 -> 'a + +type report_kind = + | Report_error + | Report_warning of string + | Report_warning_as_error of string + | Report_alert of string + | Report_alert_as_error of string + +type report = { + kind : report_kind; + main : msg; + sub : msg list; +} + +type report_printer = { + (* The entry point *) + pp : report_printer -> + Format.formatter -> report -> unit; + + pp_report_kind : report_printer -> report -> + Format.formatter -> report_kind -> unit; + pp_main_loc : report_printer -> report -> + Format.formatter -> t -> unit; + pp_main_txt : report_printer -> report -> + Format.formatter -> (Format.formatter -> unit) -> unit; + pp_submsgs : report_printer -> report -> + Format.formatter -> msg list -> unit; + pp_submsg : report_printer -> report -> + Format.formatter -> msg -> unit; + pp_submsg_loc : report_printer -> report -> + Format.formatter -> t -> unit; + pp_submsg_txt : report_printer -> report -> + Format.formatter -> (Format.formatter -> unit) -> unit; +} +(** A printer for [report]s, defined using open-recursion. + The goal is to make it easy to define new printers by re-using code from + existing ones. +*) -val error: ?loc:t -> ?sub:error list -> ?if_highlight:string -> string -> error +(** {2 Report printers used in the compiler} *) -val errorf: ?loc:t -> ?sub:error list -> ?if_highlight:string - -> ('a, Format.formatter, unit, error) format4 -> 'a +val batch_mode_printer: report_printer -val raise_errorf: ?loc:t -> ?sub:error list -> ?if_highlight:string - -> ('a, Format.formatter, unit, 'b) format4 -> 'a +val terminfo_toplevel_printer: Lexing.lexbuf -> report_printer -val error_of_printer: t -> (formatter -> 'a -> unit) -> 'a -> error +val best_toplevel_printer: unit -> report_printer +(** Detects the terminal capabilities and selects an adequate printer *) + +(** {2 Printing a [report]} *) + +val print_report: formatter -> report -> unit +(** Display an error or warning report. *) + +val report_printer: (unit -> report_printer) ref +(** Hook for redefining the printer of reports. + + The hook is a [unit -> report_printer] and not simply a [report_printer]: + this is useful so that it can detect the type of the output (a file, a + terminal, ...) and select a printer accordingly. *) + +val default_report_printer: unit -> report_printer +(** Original report printer for use in hooks. *) + + +(** {1 Reporting warnings} *) + +(** {2 Converting a [Warnings.t] into a [report]} *) + +val report_warning: t -> Warnings.t -> report option +(** [report_warning loc w] produces a report for the given warning [w], or + [None] if the warning is not to be printed. *) + +val warning_reporter: (t -> Warnings.t -> report option) ref +(** Hook for intercepting warnings. *) + +val default_warning_reporter: t -> Warnings.t -> report option +(** Original warning reporter for use in hooks. *) + +(** {2 Printing warnings} *) + +val formatter_for_warnings : formatter ref + +val print_warning: t -> formatter -> Warnings.t -> unit +(** Prints a warning. This is simply the composition of [report_warning] and + [print_report]. *) + +val prerr_warning: t -> Warnings.t -> unit +(** Same as [print_warning], but uses [!formatter_for_warnings] as output + formatter. *) + +(** {1 Reporting alerts} *) + +(** {2 Converting an [Alert.t] into a [report]} *) + +val report_alert: t -> Warnings.alert -> report option +(** [report_alert loc w] produces a report for the given alert [w], or + [None] if the alert is not to be printed. *) + +val alert_reporter: (t -> Warnings.alert -> report option) ref +(** Hook for intercepting alerts. *) + +val default_alert_reporter: t -> Warnings.alert -> report option +(** Original alert reporter for use in hooks. *) + +(** {2 Printing alerts} *) + +val print_alert: t -> formatter -> Warnings.alert -> unit +(** Prints an alert. This is simply the composition of [report_alert] and + [print_report]. *) + +val prerr_alert: t -> Warnings.alert -> unit +(** Same as [print_alert], but uses [!formatter_for_warnings] as output + formatter. *) + +val deprecated: ?def:t -> ?use:t -> t -> string -> unit +(** Prints a deprecation alert. *) + +val alert: ?def:t -> ?use:t -> kind:string -> t -> string -> unit +(** Prints an arbitrary alert. *) + + +(** {1 Reporting errors} *) + +type error = report +(** An [error] is a [report] which [report_kind] must be [Report_error]. *) + +val error: ?loc:t -> ?sub:msg list -> string -> error + +val errorf: ?loc:t -> ?sub:msg list -> + ('a, Format.formatter, unit, error) format4 -> 'a + +val error_of_printer: ?loc:t -> ?sub:msg list -> + (formatter -> 'a -> unit) -> 'a -> error val error_of_printer_file: (formatter -> 'a -> unit) -> 'a -> error -val error_of_exn: exn -> [ `Ok of error | `Already_displayed ] option + +(** {1 Automatically reporting errors for raised exceptions} *) val register_error_of_exn: (exn -> error option) -> unit (** Each compiler module which defines a custom type of exception @@ -138,15 +260,18 @@ val register_error_of_exn: (exn -> error option) -> unit a location, a message, and optionally sub-messages (each of them being located as well). *) -val report_error: formatter -> error -> unit +val error_of_exn: exn -> [ `Ok of error | `Already_displayed ] option -val error_reporter : (formatter -> error -> unit) ref -(** Hook for intercepting error reports. *) +exception Error of error +(** Raising [Error e] signals an error [e]; the exception will be caught and the + error will be printed. *) + +exception Already_displayed_error +(** Raising [Already_displayed_error] signals an error which has already been + printed. The exception will be caught, but nothing will be printed *) -val default_error_reporter : formatter -> error -> unit -(** Original error reporter for use in hooks. *) +val raise_errorf: ?loc:t -> ?sub:msg list -> + ('a, Format.formatter, unit, 'b) format4 -> 'a val report_exception: formatter -> exn -> unit (** Reraise the exception if it is unknown. *) - -val deprecated: ?def:t -> ?use:t -> t -> string -> unit diff --git a/parsing/longident.mli b/parsing/longident.mli index 5ffb16a8..b3079452 100644 --- a/parsing/longident.mli +++ b/parsing/longident.mli @@ -13,7 +13,12 @@ (* *) (**************************************************************************) -(** Long identifiers, used in parsetree. *) +(** Long identifiers, used in parsetree. + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) type t = Lident of string @@ -24,3 +29,6 @@ val flatten: t -> string list val unflatten: string list -> t option val last: t -> string val parse: string -> t + +(** To print a longident, see {!Pprintast.longident}, using + {!Format.asprintf} to convert to a string. *) diff --git a/parsing/parse.ml b/parsing/parse.ml index ba89f0e2..e7455947 100644 --- a/parsing/parse.ml +++ b/parsing/parse.ml @@ -17,31 +17,37 @@ (* Skip tokens to the end of the phrase *) +let last_token = ref Parser.EOF + +let token lexbuf = + let token = Lexer.token lexbuf in + last_token := token; + token + let rec skip_phrase lexbuf = - try - match Lexer.token lexbuf with - Parser.SEMISEMI | Parser.EOF -> () - | _ -> skip_phrase lexbuf - with - | Lexer.Error (Lexer.Unterminated_comment _, _) - | Lexer.Error (Lexer.Unterminated_string, _) - | Lexer.Error (Lexer.Unterminated_string_in_comment _, _) - | Lexer.Error (Lexer.Illegal_character _, _) -> skip_phrase lexbuf -;; + match token lexbuf with + | Parser.SEMISEMI | Parser.EOF -> () + | _ -> skip_phrase lexbuf + | exception (Lexer.Error (Lexer.Unterminated_comment _, _) + | Lexer.Error (Lexer.Unterminated_string, _) + | Lexer.Error (Lexer.Reserved_sequence _, _) + | Lexer.Error (Lexer.Unterminated_string_in_comment _, _) + | Lexer.Error (Lexer.Illegal_character _, _)) -> + skip_phrase lexbuf let maybe_skip_phrase lexbuf = - if Parsing.is_current_lookahead Parser.SEMISEMI - || Parsing.is_current_lookahead Parser.EOF - then () - else skip_phrase lexbuf + match !last_token with + | Parser.SEMISEMI | Parser.EOF -> () + | _ -> skip_phrase lexbuf let wrap parsing_fun lexbuf = try Docstrings.init (); Lexer.init (); - let ast = parsing_fun Lexer.token lexbuf in + let ast = parsing_fun lexbuf in Parsing.clear_parser(); Docstrings.warn_bad_docstrings (); + last_token := Parser.EOF; ast with | Lexer.Error(Lexer.Illegal_character _, _) as err @@ -58,10 +64,104 @@ let wrap parsing_fun lexbuf = then maybe_skip_phrase lexbuf; raise(Syntaxerr.Error(Syntaxerr.Other loc)) -let implementation = wrap Parser.implementation -and interface = wrap Parser.interface -and toplevel_phrase = wrap Parser.toplevel_phrase -and use_file = wrap Parser.use_file -and core_type = wrap Parser.parse_core_type -and expression = wrap Parser.parse_expression -and pattern = wrap Parser.parse_pattern +let rec loop lexbuf in_error checkpoint = + let module I = Parser.MenhirInterpreter in + match checkpoint with + | I.InputNeeded _env -> + let triple = + if in_error then + (* The parser detected an error. + At this point we don't want to consume input anymore. In the + top-level, it would translate into waiting for the user to type + something, just to raise an error at some earlier position, rather + than just raising the error immediately. + + This worked before with yacc because, AFAICT (@let-def): + - yacc eagerly reduces "default reduction" (when the next action + is to reduce the same production no matter what token is read, + yacc reduces it immediately rather than waiting for that token + to be read) + - error productions in OCaml grammar are always in a position that + allows default reduction ("error" symbol is the last producer, + and the lookahead token will not be used to disambiguate between + two possible error rules) + This solution is fragile because it relies on an optimization + (default reduction), that changes the semantics of the parser the + way it is implemented in Yacc (an optimization that changes + semantics? hmmmm). + + Rather than relying on implementation details of the parser, when + an error is detected in this loop we stop looking at the input and + fill the parser with EOF tokens. + The skip_phrase logic will resynchronize the input stream by + looking for the next ';;'. *) + (Parser.EOF, lexbuf.Lexing.lex_curr_p, lexbuf.Lexing.lex_curr_p) + else + let token = token lexbuf in + (token, lexbuf.Lexing.lex_start_p, lexbuf.Lexing.lex_curr_p) + in + let checkpoint = I.offer checkpoint triple in + loop lexbuf in_error checkpoint + | I.Shifting _ | I.AboutToReduce _ -> + loop lexbuf in_error (I.resume checkpoint) + | I.Accepted v -> v + | I.Rejected -> raise Parser.Error + | I.HandlingError _ -> + loop lexbuf true (I.resume checkpoint) + +let wrap_menhir entry lexbuf = + let initial = entry lexbuf.Lexing.lex_curr_p in + wrap (fun lexbuf -> loop lexbuf false initial) lexbuf + +let implementation = wrap_menhir Parser.Incremental.implementation +and interface = wrap_menhir Parser.Incremental.interface +and toplevel_phrase = wrap_menhir Parser.Incremental.toplevel_phrase +and use_file = wrap_menhir Parser.Incremental.use_file +and core_type = wrap_menhir Parser.Incremental.parse_core_type +and expression = wrap_menhir Parser.Incremental.parse_expression +and pattern = wrap_menhir Parser.Incremental.parse_pattern + + + +(* Error reporting for Syntaxerr *) +(* The code has been moved here so that one can reuse Pprintast.tyvar *) + +let prepare_error err = + let open Syntaxerr in + match err with + | Unclosed(opening_loc, opening, closing_loc, closing) -> + Location.errorf + ~loc:closing_loc + ~sub:[ + Location.msg ~loc:opening_loc + "This '%s' might be unmatched" opening + ] + "Syntax error: '%s' expected" closing + + | Expecting (loc, nonterm) -> + Location.errorf ~loc "Syntax error: %s expected." nonterm + | Not_expecting (loc, nonterm) -> + Location.errorf ~loc "Syntax error: %s not expected." nonterm + | Applicative_path loc -> + Location.errorf ~loc + "Syntax error: applicative paths of the form F(X).t \ + are not supported when the option -no-app-func is set." + | Variable_in_scope (loc, var) -> + Location.errorf ~loc + "In this scoped type, variable %a \ + is reserved for the local type %s." + Pprintast.tyvar var var + | Other loc -> + Location.errorf ~loc "Syntax error" + | Ill_formed_ast (loc, s) -> + Location.errorf ~loc + "broken invariant in parsetree: %s" s + | Invalid_package_type (loc, s) -> + Location.errorf ~loc "invalid package type: %s" s + +let () = + Location.register_error_of_exn + (function + | Syntaxerr.Error err -> Some (prepare_error err) + | _ -> None + ) diff --git a/parsing/parse.mli b/parsing/parse.mli index 8e6eb454..eb8b0b0d 100644 --- a/parsing/parse.mli +++ b/parsing/parse.mli @@ -13,7 +13,12 @@ (* *) (**************************************************************************) -(** Entry points in the parser *) +(** Entry points in the parser + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) val implementation : Lexing.lexbuf -> Parsetree.structure val interface : Lexing.lexbuf -> Parsetree.signature diff --git a/parsing/parser.mly b/parsing/parser.mly index 65e364e6..6bfe8d23 100644 --- a/parsing/parser.mly +++ b/parsing/parser.mly @@ -16,38 +16,97 @@ /* The parser definition */ %{ -open Location + open Asttypes open Longident open Parsetree open Ast_helper open Docstrings - -let mktyp d = Typ.mk ~loc:(symbol_rloc()) d -let mkpat d = Pat.mk ~loc:(symbol_rloc()) d -let mkexp d = Exp.mk ~loc:(symbol_rloc()) d -let mkmty ?attrs d = Mty.mk ~loc:(symbol_rloc()) ?attrs d -let mksig d = Sig.mk ~loc:(symbol_rloc()) d -let mkmod ?attrs d = Mod.mk ~loc:(symbol_rloc()) ?attrs d -let mkstr d = Str.mk ~loc:(symbol_rloc()) d -let mkclass ?attrs d = Cl.mk ~loc:(symbol_rloc()) ?attrs d -let mkcty ?attrs d = Cty.mk ~loc:(symbol_rloc()) ?attrs d -let mkctf ?attrs ?docs d = - Ctf.mk ~loc:(symbol_rloc()) ?attrs ?docs d -let mkcf ?attrs ?docs d = - Cf.mk ~loc:(symbol_rloc()) ?attrs ?docs d - -let mkrhs rhs pos = mkloc rhs (rhs_loc pos) - -let reloc_pat x = { x with ppat_loc = symbol_rloc () };; -let reloc_exp x = { x with pexp_loc = symbol_rloc () };; - -let mkoperator name pos = - let loc = rhs_loc pos in - Exp.mk ~loc (Pexp_ident(mkloc (Lident name) loc)) - -let mkpatvar name pos = - Pat.mk ~loc:(rhs_loc pos) (Ppat_var (mkrhs name pos)) +open Docstrings.WithMenhir + +let mkloc = Location.mkloc +let mknoloc = Location.mknoloc + +let make_loc (startpos, endpos) = { + Location.loc_start = startpos; + Location.loc_end = endpos; + Location.loc_ghost = false; +} + +let ghost_loc (startpos, endpos) = { + Location.loc_start = startpos; + Location.loc_end = endpos; + Location.loc_ghost = true; +} + +let mktyp ~loc d = Typ.mk ~loc:(make_loc loc) d +let mkpat ~loc d = Pat.mk ~loc:(make_loc loc) d +let mkexp ~loc d = Exp.mk ~loc:(make_loc loc) d +let mkmty ~loc ?attrs d = Mty.mk ~loc:(make_loc loc) ?attrs d +let mksig ~loc d = Sig.mk ~loc:(make_loc loc) d +let mkmod ~loc ?attrs d = Mod.mk ~loc:(make_loc loc) ?attrs d +let mkstr ~loc d = Str.mk ~loc:(make_loc loc) d +let mkclass ~loc ?attrs d = Cl.mk ~loc:(make_loc loc) ?attrs d +let mkcty ~loc ?attrs d = Cty.mk ~loc:(make_loc loc) ?attrs d + +let pstr_typext (te, ext) = + (Pstr_typext te, ext) +let pstr_primitive (vd, ext) = + (Pstr_primitive vd, ext) +let pstr_type ((nr, ext), tys) = + (Pstr_type (nr, tys), ext) +let pstr_exception (te, ext) = + (Pstr_exception te, ext) +let pstr_include (body, ext) = + (Pstr_include body, ext) +let pstr_recmodule (ext, bindings) = + (Pstr_recmodule bindings, ext) + +let psig_typext (te, ext) = + (Psig_typext te, ext) +let psig_value (vd, ext) = + (Psig_value vd, ext) +let psig_type ((nr, ext), tys) = + (Psig_type (nr, tys), ext) +let psig_typesubst ((nr, ext), tys) = + assert (nr = Recursive); (* see [no_nonrec_flag] *) + (Psig_typesubst tys, ext) +let psig_exception (te, ext) = + (Psig_exception te, ext) +let psig_include (body, ext) = + (Psig_include body, ext) + +let mkctf ~loc ?attrs ?docs d = + Ctf.mk ~loc:(make_loc loc) ?attrs ?docs d +let mkcf ~loc ?attrs ?docs d = + Cf.mk ~loc:(make_loc loc) ?attrs ?docs d + +let mkrhs rhs loc = mkloc rhs (make_loc loc) +let ghrhs rhs loc = mkloc rhs (ghost_loc loc) + +let push_loc x acc = + if x.Location.loc_ghost + then acc + else x :: acc + +let reloc_pat ~loc x = + { x with ppat_loc = make_loc loc; + ppat_loc_stack = push_loc x.ppat_loc x.ppat_loc_stack };; +let reloc_exp ~loc x = + { x with pexp_loc = make_loc loc; + pexp_loc_stack = push_loc x.pexp_loc x.pexp_loc_stack };; +let reloc_typ ~loc x = + { x with ptyp_loc = make_loc loc; + ptyp_loc_stack = push_loc x.ptyp_loc x.ptyp_loc_stack };; + +let mkexpvar ~loc (name : string) = + mkexp ~loc (Pexp_ident(mkrhs (Lident name) loc)) + +let mkoperator = + mkexpvar + +let mkpatvar ~loc name = + mkpat ~loc (Ppat_var (mkrhs name loc)) (* Ghost expressions and patterns: @@ -66,114 +125,153 @@ let mkpatvar name pos = AST node, then the location must be real; in all other cases, it must be ghost. *) -let ghexp d = Exp.mk ~loc:(symbol_gloc ()) d -let ghpat d = Pat.mk ~loc:(symbol_gloc ()) d -let ghtyp d = Typ.mk ~loc:(symbol_gloc ()) d -let ghloc d = { txt = d; loc = symbol_gloc () } -let ghstr d = Str.mk ~loc:(symbol_gloc()) d -let ghsig d = Sig.mk ~loc:(symbol_gloc()) d +let ghexp ~loc d = Exp.mk ~loc:(ghost_loc loc) d +let ghpat ~loc d = Pat.mk ~loc:(ghost_loc loc) d +let ghtyp ~loc d = Typ.mk ~loc:(ghost_loc loc) d +let ghloc ~loc d = { txt = d; loc = ghost_loc loc } +let ghstr ~loc d = Str.mk ~loc:(ghost_loc loc) d +let ghsig ~loc d = Sig.mk ~loc:(ghost_loc loc) d -let mkinfix arg1 name arg2 = - mkexp(Pexp_apply(mkoperator name 2, [Nolabel, arg1; Nolabel, arg2])) +let mkinfix arg1 op arg2 = + Pexp_apply(op, [Nolabel, arg1; Nolabel, arg2]) let neg_string f = if String.length f > 0 && f.[0] = '-' then String.sub f 1 (String.length f - 1) else "-" ^ f -let mkuminus name arg = +let mkuminus ~oploc name arg = match name, arg.pexp_desc with | "-", Pexp_constant(Pconst_integer (n,m)) -> - mkexp(Pexp_constant(Pconst_integer(neg_string n,m))) + Pexp_constant(Pconst_integer(neg_string n,m)) | ("-" | "-."), Pexp_constant(Pconst_float (f, m)) -> - mkexp(Pexp_constant(Pconst_float(neg_string f, m))) + Pexp_constant(Pconst_float(neg_string f, m)) | _ -> - mkexp(Pexp_apply(mkoperator ("~" ^ name) 1, [Nolabel, arg])) + Pexp_apply(mkoperator ~loc:oploc ("~" ^ name), [Nolabel, arg]) -let mkuplus name arg = +let mkuplus ~oploc name arg = let desc = arg.pexp_desc in match name, desc with | "+", Pexp_constant(Pconst_integer _) - | ("+" | "+."), Pexp_constant(Pconst_float _) -> mkexp desc + | ("+" | "+."), Pexp_constant(Pconst_float _) -> desc | _ -> - mkexp(Pexp_apply(mkoperator ("~" ^ name) 1, [Nolabel, arg])) + Pexp_apply(mkoperator ~loc:oploc ("~" ^ name), [Nolabel, arg]) -let mkexp_cons consloc args loc = - Exp.mk ~loc (Pexp_construct(mkloc (Lident "::") consloc, Some args)) +(* TODO define an abstraction boundary between locations-as-pairs + and locations-as-Location.t; it should be clear when we move from + one world to the other *) -let mkpat_cons consloc args loc = - Pat.mk ~loc (Ppat_construct(mkloc (Lident "::") consloc, Some args)) +let mkexp_cons_desc consloc args = + Pexp_construct(mkrhs (Lident "::") consloc, Some args) +let mkexp_cons ~loc consloc args = + mkexp ~loc (mkexp_cons_desc consloc args) -let rec mktailexp nilloc = function +let mkpat_cons_desc consloc args = + Ppat_construct(mkrhs (Lident "::") consloc, Some args) +let mkpat_cons ~loc consloc args = + mkpat ~loc (mkpat_cons_desc consloc args) + +let ghexp_cons_desc consloc args = + Pexp_construct(ghrhs (Lident "::") consloc, Some args) +let ghpat_cons_desc consloc args = + Ppat_construct(ghrhs (Lident "::") consloc, Some args) + +let rec mktailexp nilloc = let open Location in function [] -> - let loc = { nilloc with loc_ghost = true } in - let nil = { txt = Lident "[]"; loc = loc } in - Exp.mk ~loc (Pexp_construct (nil, None)) + let nil = ghloc ~loc:nilloc (Lident "[]") in + Pexp_construct (nil, None), nilloc | e1 :: el -> - let exp_el = mktailexp nilloc el in - let loc = {loc_start = e1.pexp_loc.loc_start; - loc_end = exp_el.pexp_loc.loc_end; - loc_ghost = true} - in - let arg = Exp.mk ~loc (Pexp_tuple [e1; exp_el]) in - mkexp_cons {loc with loc_ghost = true} arg loc + let exp_el, el_loc = mktailexp nilloc el in + let loc = (e1.pexp_loc.loc_start, snd el_loc) in + let arg = ghexp ~loc (Pexp_tuple [e1; ghexp ~loc:el_loc exp_el]) in + ghexp_cons_desc loc arg, loc -let rec mktailpat nilloc = function +let rec mktailpat nilloc = let open Location in function [] -> - let loc = { nilloc with loc_ghost = true } in - let nil = { txt = Lident "[]"; loc = loc } in - Pat.mk ~loc (Ppat_construct (nil, None)) + let nil = ghloc ~loc:nilloc (Lident "[]") in + Ppat_construct (nil, None), nilloc | p1 :: pl -> - let pat_pl = mktailpat nilloc pl in - let loc = {loc_start = p1.ppat_loc.loc_start; - loc_end = pat_pl.ppat_loc.loc_end; - loc_ghost = true} - in - let arg = Pat.mk ~loc (Ppat_tuple [p1; pat_pl]) in - mkpat_cons {loc with loc_ghost = true} arg loc + let pat_pl, el_loc = mktailpat nilloc pl in + let loc = (p1.ppat_loc.loc_start, snd el_loc) in + let arg = ghpat ~loc (Ppat_tuple [p1; ghpat ~loc:el_loc pat_pl]) in + ghpat_cons_desc loc arg, loc let mkstrexp e attrs = { pstr_desc = Pstr_eval (e, attrs); pstr_loc = e.pexp_loc } -let mkexp_constraint e (t1, t2) = +let mkexp_constraint ~loc e (t1, t2) = match t1, t2 with - | Some t, None -> ghexp(Pexp_constraint(e, t)) - | _, Some t -> ghexp(Pexp_coerce(e, t1, t)) + | Some t, None -> ghexp ~loc (Pexp_constraint(e, t)) + | _, Some t -> ghexp ~loc (Pexp_coerce(e, t1, t)) | None, None -> assert false -let mkexp_opt_constraint e = function +let mkexp_opt_constraint ~loc e = function | None -> e - | Some constraint_ -> mkexp_constraint e constraint_ + | Some constraint_ -> mkexp_constraint ~loc e constraint_ -let mkpat_opt_constraint p = function +let mkpat_opt_constraint ~loc p = function | None -> p - | Some typ -> mkpat (Ppat_constraint(p, typ)) - -let array_function str name = - ghloc (Ldot(Lident str, (if !Clflags.fast then "unsafe_" ^ name else name))) + | Some typ -> mkpat ~loc (Ppat_constraint(p, typ)) let syntax_error () = raise Syntaxerr.Escape_error -let unclosed opening_name opening_num closing_name closing_num = - raise(Syntaxerr.Error(Syntaxerr.Unclosed(rhs_loc opening_num, opening_name, - rhs_loc closing_num, closing_name))) +let unclosed opening_name opening_loc closing_name closing_loc = + raise(Syntaxerr.Error(Syntaxerr.Unclosed(make_loc opening_loc, opening_name, + make_loc closing_loc, closing_name))) -let expecting pos nonterm = - raise Syntaxerr.(Error(Expecting(rhs_loc pos, nonterm))) +let expecting loc nonterm = + raise Syntaxerr.(Error(Expecting(make_loc loc, nonterm))) -let not_expecting pos nonterm = - raise Syntaxerr.(Error(Not_expecting(rhs_loc pos, nonterm))) +let not_expecting loc nonterm = + raise Syntaxerr.(Error(Not_expecting(make_loc loc, nonterm))) -let bigarray_function str name = - ghloc (Ldot(Ldot(Lident "Bigarray", str), name)) +let dotop_fun ~loc dotop = + (* We could use ghexp here, but sticking to mkexp for parser.mly + compatibility. TODO improve parser.mly *) + mkexp ~loc (Pexp_ident (ghloc ~loc dotop)) + +let array_function ~loc str name = + ghloc ~loc (Ldot(Lident str, + (if !Clflags.unsafe then "unsafe_" ^ name else name))) + +let array_get_fun ~loc = + ghexp ~loc (Pexp_ident(array_function ~loc "Array" "get")) +let string_get_fun ~loc = + ghexp ~loc (Pexp_ident(array_function ~loc "String" "get")) + +let array_set_fun ~loc = + ghexp ~loc (Pexp_ident(array_function ~loc "Array" "set")) +let string_set_fun ~loc = + ghexp ~loc (Pexp_ident(array_function ~loc "String" "set")) + +let index_get ~loc get_fun array index = + let args = [Nolabel, array; Nolabel, index] in + mkexp ~loc (Pexp_apply(get_fun, args)) + +let index_set ~loc set_fun array index value = + let args = [Nolabel, array; Nolabel, index; Nolabel, value] in + mkexp ~loc (Pexp_apply(set_fun, args)) + +let array_get ~loc = index_get ~loc (array_get_fun ~loc) +let string_get ~loc = index_get ~loc (string_get_fun ~loc) +let dotop_get ~loc dotop = index_get ~loc (dotop_fun ~loc dotop) + +let array_set ~loc = index_set ~loc (array_set_fun ~loc) +let string_set ~loc = index_set ~loc (string_set_fun ~loc) +let dotop_set ~loc dotop = index_set ~loc (dotop_fun ~loc dotop) + +let bigarray_function ~loc str name = + ghloc ~loc (Ldot(Ldot(Lident "Bigarray", str), name)) let bigarray_untuplify = function { pexp_desc = Pexp_tuple explist; pexp_loc = _ } -> explist | exp -> [exp] -let bigarray_get arr arg = - let get = if !Clflags.fast then "unsafe_get" else "get" in +let bigarray_get ~loc arr arg = + let mkexp, ghexp = mkexp ~loc, ghexp ~loc in + let bigarray_function = bigarray_function ~loc in + let get = if !Clflags.unsafe then "unsafe_get" else "get" in match bigarray_untuplify arg with [c1] -> mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array1" get)), @@ -188,8 +286,10 @@ let bigarray_get arr arg = mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Genarray" "get")), [Nolabel, arr; Nolabel, ghexp(Pexp_array coords)])) -let bigarray_set arr arg newval = - let set = if !Clflags.fast then "unsafe_set" else "set" in +let bigarray_set ~loc arr arg newval = + let mkexp, ghexp = mkexp ~loc, ghexp ~loc in + let bigarray_function = bigarray_function ~loc in + let set = if !Clflags.unsafe then "unsafe_set" else "set" in match bigarray_untuplify arg with [c1] -> mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array1" set)), @@ -208,80 +308,93 @@ let bigarray_set arr arg newval = Nolabel, ghexp(Pexp_array coords); Nolabel, newval])) -let lapply p1 p2 = +let lapply ~loc p1 p2 = if !Clflags.applicative_functors then Lapply(p1, p2) - else raise (Syntaxerr.Error(Syntaxerr.Applicative_path (symbol_rloc()))) + else raise (Syntaxerr.Error( + Syntaxerr.Applicative_path (make_loc loc))) + +let exp_of_longident ~loc lid = + mkexp ~loc (Pexp_ident {lid with txt = Lident(Longident.last lid.txt)}) + +(* [loc_map] could be [Location.map]. *) +let loc_map (f : 'a -> 'b) (x : 'a Location.loc) : 'b Location.loc = + { x with txt = f x.txt } + +let loc_last (id : Longident.t Location.loc) : string Location.loc = + loc_map Longident.last id -let exp_of_label lbl pos = - mkexp (Pexp_ident(mkrhs (Lident(Longident.last lbl)) pos)) +let loc_lident (id : string Location.loc) : Longident.t Location.loc = + loc_map (fun x -> Lident x) id -let pat_of_label lbl pos = - mkpat (Ppat_var (mkrhs (Longident.last lbl) pos)) +let exp_of_label ~loc lbl = + mkexp ~loc (Pexp_ident (loc_lident lbl)) -let mk_newtypes newtypes exp = +let pat_of_label ~loc lbl = + mkpat ~loc (Ppat_var (loc_last lbl)) + +let mk_newtypes ~loc newtypes exp = + let mkexp = mkexp ~loc in List.fold_right (fun newtype exp -> mkexp (Pexp_newtype (newtype, exp))) newtypes exp -let wrap_type_annotation newtypes core_type body = +let wrap_type_annotation ~loc newtypes core_type body = + let mkexp, ghtyp = mkexp ~loc, ghtyp ~loc in + let mk_newtypes = mk_newtypes ~loc in let exp = mkexp(Pexp_constraint(body,core_type)) in let exp = mk_newtypes newtypes exp in (exp, ghtyp(Ptyp_poly(newtypes, Typ.varify_constructors newtypes core_type))) -let wrap_exp_attrs body (ext, attrs) = +let wrap_exp_attrs ~loc body (ext, attrs) = + let ghexp = ghexp ~loc in (* todo: keep exact location for the entire attribute *) let body = {body with pexp_attributes = attrs @ body.pexp_attributes} in match ext with | None -> body | Some id -> ghexp(Pexp_extension (id, PStr [mkstrexp body []])) -let mkexp_attrs d attrs = - wrap_exp_attrs (mkexp d) attrs +let mkexp_attrs ~loc d attrs = + wrap_exp_attrs ~loc (mkexp ~loc d) attrs -let wrap_typ_attrs typ (ext, attrs) = +let wrap_typ_attrs ~loc typ (ext, attrs) = (* todo: keep exact location for the entire attribute *) let typ = {typ with ptyp_attributes = attrs @ typ.ptyp_attributes} in match ext with | None -> typ - | Some id -> ghtyp(Ptyp_extension (id, PTyp typ)) - -let mktyp_attrs d attrs = - wrap_typ_attrs (mktyp d) attrs + | Some id -> ghtyp ~loc (Ptyp_extension (id, PTyp typ)) -let wrap_pat_attrs pat (ext, attrs) = +let wrap_pat_attrs ~loc pat (ext, attrs) = (* todo: keep exact location for the entire attribute *) let pat = {pat with ppat_attributes = attrs @ pat.ppat_attributes} in match ext with | None -> pat - | Some id -> ghpat(Ppat_extension (id, PPat (pat, None))) + | Some id -> ghpat ~loc (Ppat_extension (id, PPat (pat, None))) -let mkpat_attrs d attrs = - wrap_pat_attrs (mkpat d) attrs +let mkpat_attrs ~loc d attrs = + wrap_pat_attrs ~loc (mkpat ~loc d) attrs -let wrap_class_attrs body attrs = +let wrap_class_attrs ~loc:_ body attrs = {body with pcl_attributes = attrs @ body.pcl_attributes} -let wrap_class_type_attrs body attrs = - {body with pcty_attributes = attrs @ body.pcty_attributes} -let wrap_mod_attrs body attrs = +let wrap_mod_attrs ~loc:_ attrs body = {body with pmod_attributes = attrs @ body.pmod_attributes} -let wrap_mty_attrs body attrs = +let wrap_mty_attrs ~loc:_ attrs body = {body with pmty_attributes = attrs @ body.pmty_attributes} -let wrap_str_ext body ext = +let wrap_str_ext ~loc body ext = match ext with | None -> body - | Some id -> ghstr(Pstr_extension ((id, PStr [body]), [])) + | Some id -> ghstr ~loc (Pstr_extension ((id, PStr [body]), [])) -let mkstr_ext d ext = - wrap_str_ext (mkstr d) ext +let wrap_mkstr_ext ~loc (item, ext) = + wrap_str_ext ~loc (mkstr ~loc item) ext -let wrap_sig_ext body ext = +let wrap_sig_ext ~loc body ext = match ext with | None -> body - | Some id -> ghsig(Psig_extension ((id, PSig [body]), [])) + | Some id -> ghsig ~loc (Psig_extension ((id, PSig [body]), [])) -let mksig_ext d ext = - wrap_sig_ext (mksig d) ext +let wrap_mksig_ext ~loc (item, ext) = + wrap_sig_ext ~loc (mksig ~loc item) ext let text_str pos = Str.text (rhs_text pos) let text_sig pos = Sig.text (rhs_text pos) @@ -289,23 +402,23 @@ let text_cstr pos = Cf.text (rhs_text pos) let text_csig pos = Ctf.text (rhs_text pos) let text_def pos = [Ptop_def (Str.text (rhs_text pos))] -let extra_text text pos items = +let extra_text startpos endpos text items = match items with | [] -> - let post = rhs_post_text pos in - let post_extras = rhs_post_extra_text pos in + let post = rhs_post_text endpos in + let post_extras = rhs_post_extra_text endpos in text post @ text post_extras | _ :: _ -> - let pre_extras = rhs_pre_extra_text pos in - let post_extras = rhs_post_extra_text pos in + let pre_extras = rhs_pre_extra_text startpos in + let post_extras = rhs_post_extra_text endpos in text pre_extras @ items @ text post_extras -let extra_str pos items = extra_text Str.text pos items -let extra_sig pos items = extra_text Sig.text pos items -let extra_cstr pos items = extra_text Cf.text pos items -let extra_csig pos items = extra_text Ctf.text pos items -let extra_def pos items = - extra_text (fun txt -> [Ptop_def (Str.text txt)]) pos items +let extra_str p1 p2 items = extra_text p1 p2 Str.text items +let extra_sig p1 p2 items = extra_text p1 p2 Sig.text items +let extra_cstr p1 p2 items = extra_text p1 p2 Cf.text items +let extra_csig p1 p2 items = extra_text p1 p2 Ctf.text items +let extra_def p1 p2 items = + extra_text p1 p2 (fun txt -> [Ptop_def (Str.text txt)]) items let extra_rhs_core_type ct ~pos = let docs = rhs_info pos in @@ -325,25 +438,29 @@ type let_bindings = lbs_extension: string Asttypes.loc option; lbs_loc: Location.t } -let mklb first (p, e) attrs = - { lb_pattern = p; +let mklb first ~loc (p, e) attrs = + { + lb_pattern = p; lb_expression = e; lb_attributes = attrs; - lb_docs = symbol_docs_lazy (); - lb_text = if first then empty_text_lazy - else symbol_text_lazy (); - lb_loc = symbol_rloc (); } - -let mklbs ext rf lb = - { lbs_bindings = [lb]; + lb_docs = symbol_docs_lazy loc; + lb_text = (if first then empty_text_lazy + else symbol_text_lazy (fst loc)); + lb_loc = make_loc loc; + } + +let mklbs ~loc ext rf lb = + { + lbs_bindings = [lb]; lbs_rec = rf; lbs_extension = ext ; - lbs_loc = symbol_rloc (); } + lbs_loc = make_loc loc; + } let addlb lbs lb = { lbs with lbs_bindings = lb :: lbs.lbs_bindings } -let val_of_let_bindings lbs = +let val_of_let_bindings ~loc lbs = let bindings = List.map (fun lb -> @@ -353,12 +470,12 @@ let val_of_let_bindings lbs = lb.lb_pattern lb.lb_expression) lbs.lbs_bindings in - let str = mkstr(Pstr_value(lbs.lbs_rec, List.rev bindings)) in + let str = mkstr ~loc (Pstr_value(lbs.lbs_rec, List.rev bindings)) in match lbs.lbs_extension with | None -> str - | Some id -> ghstr (Pstr_extension((id, PStr [str]), [])) + | Some id -> ghstr ~loc (Pstr_extension((id, PStr [str]), [])) -let expr_of_let_bindings lbs body = +let expr_of_let_bindings ~loc lbs body = let bindings = List.map (fun lb -> @@ -366,10 +483,10 @@ let expr_of_let_bindings lbs body = lb.lb_pattern lb.lb_expression) lbs.lbs_bindings in - mkexp_attrs (Pexp_let(lbs.lbs_rec, List.rev bindings, body)) + mkexp_attrs ~loc (Pexp_let(lbs.lbs_rec, List.rev bindings, body)) (lbs.lbs_extension, []) -let class_of_let_bindings lbs body = +let class_of_let_bindings ~loc lbs body = let bindings = List.map (fun lb -> @@ -377,10 +494,9 @@ let class_of_let_bindings lbs body = lb.lb_pattern lb.lb_expression) lbs.lbs_bindings in - if lbs.lbs_extension <> None then - raise Syntaxerr.(Error(Not_expecting(lbs.lbs_loc, "extension"))); - mkclass(Pcl_let (lbs.lbs_rec, List.rev bindings, body)) - + (* Our use of let_bindings(no_ext) guarantees the following: *) + assert (lbs.lbs_extension = None); + mkclass ~loc (Pcl_let (lbs.lbs_rec, List.rev bindings, body)) (* Alternatively, we could keep the generic module type in the Parsetree and extract the package type during type-checking. In that case, @@ -419,6 +535,17 @@ let package_type_of_module_type pmty = err pmty.pmty_loc "only module type identifier and 'with type' constraints are supported" +let mk_directive_arg ~loc k = + { pdira_desc = k; + pdira_loc = make_loc loc; + } + +let mk_directive ~loc name arg = + Ptop_dir { + pdir_name = name; + pdir_arg = arg; + pdir_loc = make_loc loc; + } %} @@ -472,6 +599,8 @@ let package_type_of_module_type pmty = %token INFIXOP3 %token INFIXOP4 %token DOTOP +%token LETOP +%token ANDOP %token INHERIT %token INITIALIZER %token INT @@ -584,7 +713,7 @@ The precedences must be listed from low to high. %left BAR /* pattern (p|p|p) */ %nonassoc below_COMMA %left COMMA /* expr/expr_comma_list (e,e,e) */ -%right MINUSGREATER /* core_type2 (t -> t -> t) */ +%right MINUSGREATER /* function_type (t -> t -> t) */ %right OR BARBAR /* expr (e || e || e) */ %right AMPERSAND AMPERAMPER /* expr (e && e && e) */ %nonassoc below_EQUAL @@ -592,7 +721,6 @@ The precedences must be listed from low to high. %right INFIXOP1 /* expr (e OP e OP e) */ %nonassoc below_LBRACKETAT %nonassoc LBRACKETAT -%nonassoc LBRACKETATAT %right COLONCOLON /* expr (e :: e :: e) */ %left INFIXOP2 PLUS PLUSDOT MINUS MINUSDOT PLUSEQ /* expr (e OP e OP e) */ %left PERCENT INFIXOP3 STAR /* expr (e OP e OP e) */ @@ -609,7 +737,7 @@ The precedences must be listed from low to high. %nonassoc BACKQUOTE BANG BEGIN CHAR FALSE FLOAT INT LBRACE LBRACELESS LBRACKET LBRACKETBAR LIDENT LPAREN NEW PREFIXOP STRING TRUE UIDENT - LBRACKETPERCENT LBRACKETPERCENTPERCENT + LBRACKETPERCENT /* Entry points */ @@ -630,514 +758,1068 @@ The precedences must be listed from low to high. %type parse_pattern %% -/* Entry points */ - +/* macros */ +%inline extra_str(symb): symb { extra_str $startpos $endpos $1 }; +%inline extra_sig(symb): symb { extra_sig $startpos $endpos $1 }; +%inline extra_cstr(symb): symb { extra_cstr $startpos $endpos $1 }; +%inline extra_csig(symb): symb { extra_csig $startpos $endpos $1 }; +%inline extra_def(symb): symb { extra_def $startpos $endpos $1 }; +%inline extra_text(symb): symb { extra_text $startpos $endpos $1 }; +%inline extra_rhs(symb): symb { extra_rhs_core_type $1 ~pos:$endpos($1) }; +%inline mkrhs(symb): symb + { mkrhs $1 $sloc } +; + +%inline text_str(symb): symb + { text_str $startpos @ [$1] } +%inline text_str_SEMISEMI: SEMISEMI + { text_str $startpos } +%inline text_sig(symb): symb + { text_sig $startpos @ [$1] } +%inline text_sig_SEMISEMI: SEMISEMI + { text_sig $startpos } +%inline text_def(symb): symb + { text_def $startpos @ [$1] } +%inline top_def(symb): symb + { Ptop_def [$1] } +%inline text_cstr(symb): symb + { text_cstr $startpos @ [$1] } +%inline text_csig(symb): symb + { text_csig $startpos @ [$1] } + +(* Using this %inline definition means that we do not control precisely + when [mark_rhs_docs] is called, but I don't think this matters. *) +%inline mark_rhs_docs(symb): symb + { mark_rhs_docs $startpos $endpos; + $1 } + +%inline op(symb): symb + { mkoperator ~loc:$sloc $1 } + +%inline mkloc(symb): symb + { mkloc $1 (make_loc $sloc) } + +%inline mkexp(symb): symb + { mkexp ~loc:$sloc $1 } +%inline mkpat(symb): symb + { mkpat ~loc:$sloc $1 } +%inline mktyp(symb): symb + { mktyp ~loc:$sloc $1 } +%inline mkstr(symb): symb + { mkstr ~loc:$sloc $1 } +%inline mksig(symb): symb + { mksig ~loc:$sloc $1 } +%inline mkmod(symb): symb + { mkmod ~loc:$sloc $1 } +%inline mkmty(symb): symb + { mkmty ~loc:$sloc $1 } +%inline mkcty(symb): symb + { mkcty ~loc:$sloc $1 } +%inline mkctf(symb): symb + { mkctf ~loc:$sloc $1 } +%inline mkcf(symb): symb + { mkcf ~loc:$sloc $1 } +%inline mkclass(symb): symb + { mkclass ~loc:$sloc $1 } + +%inline wrap_mkstr_ext(symb): symb + { wrap_mkstr_ext ~loc:$sloc $1 } +%inline wrap_mksig_ext(symb): symb + { wrap_mksig_ext ~loc:$sloc $1 } + +%inline mk_directive_arg(symb): symb + { mk_directive_arg ~loc:$sloc $1 } + +/* Generic definitions */ + +(* [iloption(X)] recognizes either nothing or [X]. Assuming [X] produces + an OCaml list, it produces an OCaml list, too. *) + +%inline iloption(X): + /* nothing */ + { [] } +| x = X + { x } + +(* [llist(X)] recognizes a possibly empty list of [X]s. It is left-recursive. *) + +reversed_llist(X): + /* empty */ + { [] } +| xs = reversed_llist(X) x = X + { x :: xs } + +%inline llist(X): + xs = rev(reversed_llist(X)) + { xs } + +(* [reversed_nonempty_llist(X)] recognizes a nonempty list of [X]s, and produces + an OCaml list in reverse order -- that is, the last element in the input text + appears first in this list. Its definition is left-recursive. *) + +reversed_nonempty_llist(X): + x = X + { [ x ] } +| xs = reversed_nonempty_llist(X) x = X + { x :: xs } + +(* [nonempty_llist(X)] recognizes a nonempty list of [X]s, and produces an OCaml + list in direct order -- that is, the first element in the input text appears + first in this list. *) + +%inline nonempty_llist(X): + xs = rev(reversed_nonempty_llist(X)) + { xs } + +(* [reversed_separated_nonempty_llist(separator, X)] recognizes a nonempty list + of [X]s, separated with [separator]s, and produces an OCaml list in reverse + order -- that is, the last element in the input text appears first in this + list. Its definition is left-recursive. *) + +(* [inline_reversed_separated_nonempty_llist(separator, X)] is semantically + equivalent to [reversed_separated_nonempty_llist(separator, X)], but is + marked %inline, which means that the case of a list of length one and + the case of a list of length more than one will be distinguished at the + use site, and will give rise there to two productions. This can be used + to avoid certain conflicts. *) + +%inline inline_reversed_separated_nonempty_llist(separator, X): + x = X + { [ x ] } +| xs = reversed_separated_nonempty_llist(separator, X) + separator + x = X + { x :: xs } + +reversed_separated_nonempty_llist(separator, X): + xs = inline_reversed_separated_nonempty_llist(separator, X) + { xs } + +(* [separated_nonempty_llist(separator, X)] recognizes a nonempty list of [X]s, + separated with [separator]s, and produces an OCaml list in direct order -- + that is, the first element in the input text appears first in this list. *) + +%inline separated_nonempty_llist(separator, X): + xs = rev(reversed_separated_nonempty_llist(separator, X)) + { xs } + +%inline inline_separated_nonempty_llist(separator, X): + xs = rev(inline_reversed_separated_nonempty_llist(separator, X)) + { xs } + +(* [reversed_separated_nontrivial_llist(separator, X)] recognizes a list of at + least two [X]s, separated with [separator]s, and produces an OCaml list in + reverse order -- that is, the last element in the input text appears first + in this list. Its definition is left-recursive. *) + +reversed_separated_nontrivial_llist(separator, X): + xs = reversed_separated_nontrivial_llist(separator, X) + separator + x = X + { x :: xs } +| x1 = X + separator + x2 = X + { [ x2; x1 ] } + +(* [separated_nontrivial_llist(separator, X)] recognizes a list of at least + two [X]s, separated with [separator]s, and produces an OCaml list in direct + order -- that is, the first element in the input text appears first in this + list. *) + +%inline separated_nontrivial_llist(separator, X): + xs = rev(reversed_separated_nontrivial_llist(separator, X)) + { xs } + +(* [separated_or_terminated_nonempty_list(delimiter, X)] recognizes a nonempty + list of [X]s, separated with [delimiter]s, and optionally terminated with a + final [delimiter]. Its definition is right-recursive. *) + +separated_or_terminated_nonempty_list(delimiter, X): + x = X ioption(delimiter) + { [x] } +| x = X + delimiter + xs = separated_or_terminated_nonempty_list(delimiter, X) + { x :: xs } + +(* [reversed_preceded_or_separated_nonempty_llist(delimiter, X)] recognizes a + nonempty list of [X]s, separated with [delimiter]s, and optionally preceded + with a leading [delimiter]. It produces an OCaml list in reverse order. Its + definition is left-recursive. *) + +reversed_preceded_or_separated_nonempty_llist(delimiter, X): + ioption(delimiter) x = X + { [x] } +| xs = reversed_preceded_or_separated_nonempty_llist(delimiter, X) + delimiter + x = X + { x :: xs } + +(* [preceded_or_separated_nonempty_llist(delimiter, X)] recognizes a nonempty + list of [X]s, separated with [delimiter]s, and optionally preceded with a + leading [delimiter]. It produces an OCaml list in direct order. *) + +%inline preceded_or_separated_nonempty_llist(delimiter, X): + xs = rev(reversed_preceded_or_separated_nonempty_llist(delimiter, X)) + { xs } + +(* [bar_llist(X)] recognizes a nonempty list of [X]'s, separated with BARs, + with an optional leading BAR. We assume that [X] is itself parameterized + with an opening symbol, which can be [epsilon] or [BAR]. *) + +(* This construction may seem needlessly complicated: one might think that + using [preceded_or_separated_nonempty_llist(BAR, X)], where [X] is *not* + itself parameterized, would be sufficient. Indeed, this simpler approach + would recognize the same language. However, the two approaches differ in + the footprint of [X]. We want the start location of [X] to include [BAR] + when present. In the future, we might consider switching to the simpler + definition, at the cost of producing slightly different locations. TODO *) + +reversed_bar_llist(X): + (* An [X] without a leading BAR. *) + x = X(epsilon) + { [x] } + | (* An [X] with a leading BAR. *) + x = X(BAR) + { [x] } + | (* An initial list, followed with a BAR and an [X]. *) + xs = reversed_bar_llist(X) + x = X(BAR) + { x :: xs } + +%inline bar_llist(X): + xs = reversed_bar_llist(X) + { List.rev xs } + +(* [xlist(A, B)] recognizes [AB*]. We assume that the semantic value for [A] + is a pair [x, b], while the semantic value for [B*] is a list [bs]. + We return the pair [x, b :: bs]. *) + +%inline xlist(A, B): + a = A bs = B* + { let (x, b) = a in x, b :: bs } + +(* [listx(delimiter, X, Y)] recognizes a nonempty list of [X]s, optionally + followed with a [Y], separated-or-terminated with [delimiter]s. The + semantic value is a pair of a list of [X]s and an optional [Y]. *) + +listx(delimiter, X, Y): +| x = X ioption(delimiter) + { [x], None } +| x = X delimiter y = Y delimiter? + { [x], Some y } +| x = X + delimiter + tail = listx(delimiter, X, Y) + { let xs, y = tail in + x :: xs, y } + +(* -------------------------------------------------------------------------- *) + +(* Entry points. *) + +(* An .ml file. *) implementation: - structure EOF { extra_str 1 $1 } + structure EOF + { $1 } ; + +(* An .mli file. *) interface: - signature EOF { extra_sig 1 $1 } + signature EOF + { $1 } ; + +(* A toplevel phrase. *) toplevel_phrase: - top_structure SEMISEMI { Ptop_def (extra_str 1 $1) } - | toplevel_directive SEMISEMI { $1 } - | EOF { raise End_of_file } -; -top_structure: - seq_expr post_item_attributes - { (text_str 1) @ [mkstrexp $1 $2] } - | top_structure_tail - { $1 } -; -top_structure_tail: - /* empty */ { [] } - | structure_item top_structure_tail { (text_str 1) @ $1 :: $2 } -; + (* An expression with attributes, ended by a double semicolon. *) + extra_str(text_str(str_exp)) + SEMISEMI + { Ptop_def $1 } +| (* A list of structure items, ended by a double semicolon. *) + extra_str(flatten(text_str(structure_item)*)) + SEMISEMI + { Ptop_def $1 } +| (* A directive, ended by a double semicolon. *) + toplevel_directive + SEMISEMI + { $1 } +| (* End of input. *) + EOF + { raise End_of_file } +; + +(* An .ml file that is read by #use. *) use_file: - use_file_body EOF { extra_def 1 $1 } -; -use_file_body: - use_file_tail { $1 } - | seq_expr post_item_attributes use_file_tail - { (text_def 1) @ Ptop_def[mkstrexp $1 $2] :: $3 } -; -use_file_tail: - /* empty */ - { [] } - | SEMISEMI use_file_body - { $2 } - | structure_item use_file_tail - { (text_def 1) @ Ptop_def[$1] :: $2 } - | toplevel_directive use_file_tail - { mark_rhs_docs 1 1; - (text_def 1) @ $1 :: $2 } + (* An optional standalone expression, + followed with a series of elements, + followed with EOF. *) + extra_def(append( + optional_use_file_standalone_expression, + flatten(use_file_element*) + )) + EOF + { $1 } +; + +(* An optional standalone expression is just an expression with attributes + (str_exp), with extra wrapping. *) +%inline optional_use_file_standalone_expression: + iloption(text_def(top_def(str_exp))) + { $1 } +; + +(* An element in a #used file is one of the following: + - a double semicolon followed with an optional standalone expression; + - a structure item; + - a toplevel directive. + *) +%inline use_file_element: + preceded(SEMISEMI, optional_use_file_standalone_expression) +| text_def(top_def(structure_item)) +| text_def(mark_rhs_docs(toplevel_directive)) + { $1 } ; + parse_core_type: - core_type EOF { $1 } + core_type EOF + { $1 } ; + parse_expression: - seq_expr EOF { $1 } + seq_expr EOF + { $1 } ; + parse_pattern: - pattern EOF { $1 } + pattern EOF + { $1 } ; -/* Module expressions */ +(* -------------------------------------------------------------------------- *) + +(* Functor arguments appear in module expressions and module types. *) + +%inline functor_args: + reversed_nonempty_llist(functor_arg) + { $1 } + (* Produce a reversed list on purpose; + later processed using [fold_left]. *) +; functor_arg: - LPAREN RPAREN - { mkrhs "*" 2, None } - | LPAREN functor_arg_name COLON module_type RPAREN - { mkrhs $2 2, Some $4 } + (* An anonymous and untyped argument. *) + x = mkrhs(LPAREN RPAREN {"*"}) + { x, None } + | (* An argument accompanied with an explicit type. *) + LPAREN x = mkrhs(functor_arg_name) COLON mty = module_type RPAREN + { x, Some mty } ; functor_arg_name: - UIDENT { $1 } - | UNDERSCORE { "_" } + (* A named argument. *) + x = UIDENT + { x } + | (* An anonymous argument. *) + UNDERSCORE + { "_" } ; -functor_args: - functor_args functor_arg - { $2 :: $1 } - | functor_arg - { [ $1 ] } -; +(* -------------------------------------------------------------------------- *) + +(* Module expressions. *) + +(* The syntax of module expressions is not properly stratified. The cases of + functors, functor applications, and attributes interact and cause conflicts, + which are resolved by precedence declarations. This is concise but fragile. + Perhaps in the future an explicit stratification could be used. *) module_expr: - mod_longident - { mkmod(Pmod_ident (mkrhs $1 1)) } - | STRUCT attributes structure END - { mkmod ~attrs:$2 (Pmod_structure(extra_str 3 $3)) } + | STRUCT attrs = attributes s = structure END + { mkmod ~loc:$sloc ~attrs (Pmod_structure s) } | STRUCT attributes structure error - { unclosed "struct" 1 "end" 4 } - | FUNCTOR attributes functor_args MINUSGREATER module_expr - { let modexp = - List.fold_left - (fun acc (n, t) -> mkmod(Pmod_functor(n, t, acc))) - $5 $3 - in wrap_mod_attrs modexp $2 } - | module_expr paren_module_expr - { mkmod(Pmod_apply($1, $2)) } - | module_expr LPAREN RPAREN - { mkmod(Pmod_apply($1, mkmod (Pmod_structure []))) } - | paren_module_expr - { $1 } - | module_expr attribute - { Mod.attr $1 $2 } - | extension - { mkmod(Pmod_extension $1) } -; + { unclosed "struct" $loc($1) "end" $loc($4) } + | FUNCTOR attrs = attributes args = functor_args MINUSGREATER me = module_expr + { wrap_mod_attrs ~loc:$sloc attrs ( + List.fold_left (fun acc (x, mty) -> + mkmod ~loc:$sloc (Pmod_functor (x, mty, acc)) + ) me args + ) } + | me = paren_module_expr + { me } + | me = module_expr attr = attribute + { Mod.attr me attr } + | mkmod( + (* A module identifier. *) + x = mkrhs(mod_longident) + { Pmod_ident x } + | (* In a functor application, the actual argument must be parenthesized. *) + me1 = module_expr me2 = paren_module_expr + { Pmod_apply(me1, me2) } + | (* Application to unit is sugar for application to an empty structure. *) + me1 = module_expr LPAREN RPAREN + { (* TODO review mkmod location *) + Pmod_apply(me1, mkmod ~loc:$sloc (Pmod_structure [])) } + | (* An extension. *) + ex = extension + { Pmod_extension ex } + ) + { $1 } +; + +(* A parenthesized module expression is a module expression that begins + and ends with parentheses. *) paren_module_expr: - LPAREN module_expr COLON module_type RPAREN - { mkmod(Pmod_constraint($2, $4)) } + (* A module expression annotated with a module type. *) + LPAREN me = module_expr COLON mty = module_type RPAREN + { mkmod ~loc:$sloc (Pmod_constraint(me, mty)) } | LPAREN module_expr COLON module_type error - { unclosed "(" 1 ")" 5 } - | LPAREN module_expr RPAREN - { $2 } + { unclosed "(" $loc($1) ")" $loc($5) } + | (* A module expression within parentheses. *) + LPAREN me = module_expr RPAREN + { me (* TODO consider reloc *) } | LPAREN module_expr error - { unclosed "(" 1 ")" 3 } - | LPAREN VAL attributes expr RPAREN - { mkmod ~attrs:$3 (Pmod_unpack $4)} - | LPAREN VAL attributes expr COLON package_type RPAREN - { mkmod ~attrs:$3 - (Pmod_unpack( - ghexp(Pexp_constraint($4, ghtyp(Ptyp_package $6))))) } - | LPAREN VAL attributes expr COLON package_type COLONGREATER package_type - RPAREN - { mkmod ~attrs:$3 - (Pmod_unpack( - ghexp(Pexp_coerce($4, Some(ghtyp(Ptyp_package $6)), - ghtyp(Ptyp_package $8))))) } - | LPAREN VAL attributes expr COLONGREATER package_type RPAREN - { mkmod ~attrs:$3 - (Pmod_unpack( - ghexp(Pexp_coerce($4, None, ghtyp(Ptyp_package $6))))) } + { unclosed "(" $loc($1) ")" $loc($3) } + | (* A core language expression that produces a first-class module. + This expression can be annotated in various ways. *) + LPAREN VAL attrs = attributes e = expr_colon_package_type RPAREN + { mkmod ~loc:$sloc ~attrs (Pmod_unpack e) } | LPAREN VAL attributes expr COLON error - { unclosed "(" 1 ")" 6 } + { unclosed "(" $loc($1) ")" $loc($6) } | LPAREN VAL attributes expr COLONGREATER error - { unclosed "(" 1 ")" 6 } + { unclosed "(" $loc($1) ")" $loc($6) } | LPAREN VAL attributes expr error - { unclosed "(" 1 ")" 5 } + { unclosed "(" $loc($1) ")" $loc($5) } ; -structure: - seq_expr post_item_attributes structure_tail - { mark_rhs_docs 1 2; - (text_str 1) @ mkstrexp $1 $2 :: $3 } - | structure_tail { $1 } +(* The various ways of annotating a core language expression that + produces a first-class module that we wish to unpack. *) +%inline expr_colon_package_type: + e = expr + { e } + | e = expr COLON ty = package_type + { ghexp ~loc:$loc (Pexp_constraint (e, ty)) } + | e = expr COLON ty1 = package_type COLONGREATER ty2 = package_type + { ghexp ~loc:$loc (Pexp_coerce (e, Some ty1, ty2)) } + | e = expr COLONGREATER ty2 = package_type + { ghexp ~loc:$loc (Pexp_coerce (e, None, ty2)) } ; -structure_tail: - /* empty */ { [] } - | SEMISEMI structure { (text_str 1) @ $2 } - | structure_item structure_tail { (text_str 1) @ $1 :: $2 } -; -structure_item: - let_bindings - { val_of_let_bindings $1 } - | primitive_declaration - { let (body, ext) = $1 in mkstr_ext (Pstr_primitive body) ext } - | value_description - { let (body, ext) = $1 in mkstr_ext (Pstr_primitive body) ext } - | type_declarations - { let (nr, l, ext ) = $1 in mkstr_ext (Pstr_type (nr, List.rev l)) ext } - | str_type_extension - { let (l, ext) = $1 in mkstr_ext (Pstr_typext l) ext } - | str_exception_declaration - { let (l, ext) = $1 in mkstr_ext (Pstr_exception l) ext } - | module_binding - { let (body, ext) = $1 in mkstr_ext (Pstr_module body) ext } - | rec_module_bindings - { let (l, ext) = $1 in mkstr_ext (Pstr_recmodule(List.rev l)) ext } - | module_type_declaration - { let (body, ext) = $1 in mkstr_ext (Pstr_modtype body) ext } - | open_statement - { let (body, ext) = $1 in mkstr_ext (Pstr_open body) ext } - | class_declarations - { let (l, ext) = $1 in mkstr_ext (Pstr_class (List.rev l)) ext } - | class_type_declarations - { let (l, ext) = $1 in mkstr_ext (Pstr_class_type (List.rev l)) ext } - | str_include_statement - { let (body, ext) = $1 in mkstr_ext (Pstr_include body) ext } - | item_extension post_item_attributes - { mkstr(Pstr_extension ($1, (add_docs_attrs (symbol_docs ()) $2))) } - | floating_attribute - { mark_symbol_docs (); - mkstr(Pstr_attribute $1) } -; -str_include_statement: - INCLUDE ext_attributes module_expr post_item_attributes - { let (ext, attrs) = $2 in - Incl.mk $3 ~attrs:(attrs@$4) - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) - , ext } -; -module_binding_body: - EQUAL module_expr - { $2 } - | COLON module_type EQUAL module_expr - { mkmod(Pmod_constraint($4, $2)) } - | functor_arg module_binding_body - { mkmod(Pmod_functor(fst $1, snd $1, $2)) } -; -module_binding: - MODULE ext_attributes UIDENT module_binding_body post_item_attributes - { let (ext, attrs) = $2 in - Mb.mk (mkrhs $3 3) $4 ~attrs:(attrs@$5) - ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) - , ext } + +(* A structure, which appears between STRUCT and END (among other places), + begins with an optional standalone expression, and continues with a list + of structure elements. *) +structure: + extra_str(append( + optional_structure_standalone_expression, + flatten(structure_element*) + )) + { $1 } ; -rec_module_bindings: - rec_module_binding { let (b, ext) = $1 in ([b], ext) } - | rec_module_bindings and_module_binding - { let (l, ext) = $1 in ($2 :: l, ext) } + +(* An optional standalone expression is just an expression with attributes + (str_exp), with extra wrapping. *) +%inline optional_structure_standalone_expression: + items = iloption(mark_rhs_docs(text_str(str_exp))) + { items } ; -rec_module_binding: - MODULE ext_attributes REC UIDENT module_binding_body post_item_attributes - { let (ext, attrs) = $2 in - Mb.mk (mkrhs $4 4) $5 ~attrs:(attrs@$6) - ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) - , ext } + +(* An expression with attributes, wrapped as a structure item. *) +%inline str_exp: + e = seq_expr + attrs = post_item_attributes + { mkstrexp e attrs } ; -and_module_binding: - AND attributes UIDENT module_binding_body post_item_attributes - { Mb.mk (mkrhs $3 3) $4 ~attrs:($2@$5) ~loc:(symbol_rloc ()) - ~text:(symbol_text ()) ~docs:(symbol_docs ()) } + +(* A structure element is one of the following: + - a double semicolon followed with an optional standalone expression; + - a structure item. *) +%inline structure_element: + append(text_str_SEMISEMI, optional_structure_standalone_expression) + | text_str(structure_item) + { $1 } ; +(* A structure item. *) +structure_item: + let_bindings(ext) + { val_of_let_bindings ~loc:$sloc $1 } + | mkstr( + item_extension post_item_attributes + { let docs = symbol_docs $sloc in + Pstr_extension ($1, add_docs_attrs docs $2) } + | floating_attribute + { Pstr_attribute $1 } + ) + | wrap_mkstr_ext( + primitive_declaration + { pstr_primitive $1 } + | value_description + { pstr_primitive $1 } + | type_declarations + { pstr_type $1 } + | str_type_extension + { pstr_typext $1 } + | str_exception_declaration + { pstr_exception $1 } + | module_binding + { $1 } + | rec_module_bindings + { pstr_recmodule $1 } + | module_type_declaration + { let (body, ext) = $1 in (Pstr_modtype body, ext) } + | open_declaration + { let (body, ext) = $1 in (Pstr_open body, ext) } + | class_declarations + { let (ext, l) = $1 in (Pstr_class l, ext) } + | class_type_declarations + { let (ext, l) = $1 in (Pstr_class_type l, ext) } + | include_statement(module_expr) + { pstr_include $1 } + ) + { $1 } +; + +(* A single module binding. *) +%inline module_binding: + MODULE + ext = ext attrs1 = attributes + uid = mkrhs(UIDENT) + body = module_binding_body + attrs2 = post_item_attributes + { let docs = symbol_docs $sloc in + let loc = make_loc $sloc in + let attrs = attrs1 @ attrs2 in + let body = Mb.mk uid body ~attrs ~loc ~docs in + Pstr_module body, ext } +; + +(* The body (right-hand side) of a module binding. *) +module_binding_body: + EQUAL me = module_expr + { me } + | mkmod( + COLON mty = module_type EQUAL me = module_expr + { Pmod_constraint(me, mty) } + | arg = functor_arg body = module_binding_body + { let (x, mty) = arg in + Pmod_functor(x, mty, body) } + ) { $1 } +; + +(* A group of recursive module bindings. *) +%inline rec_module_bindings: + xlist(rec_module_binding, and_module_binding) + { $1 } +; + +(* The first binding in a group of recursive module bindings. *) +%inline rec_module_binding: + MODULE + ext = ext + attrs1 = attributes + REC + uid = mkrhs(UIDENT) + body = module_binding_body + attrs2 = post_item_attributes + { + let loc = make_loc $sloc in + let attrs = attrs1 @ attrs2 in + let docs = symbol_docs $sloc in + ext, + Mb.mk uid body ~attrs ~loc ~docs + } +; + +(* The following bindings in a group of recursive module bindings. *) +%inline and_module_binding: + AND + attrs1 = attributes + uid = mkrhs(UIDENT) + body = module_binding_body + attrs2 = post_item_attributes + { + let loc = make_loc $sloc in + let attrs = attrs1 @ attrs2 in + let docs = symbol_docs $sloc in + let text = symbol_text $symbolstartpos in + Mb.mk uid body ~attrs ~loc ~text ~docs + } +; + +(* -------------------------------------------------------------------------- *) + +(* Shared material between structures and signatures. *) + +(* An [include] statement can appear in a structure or in a signature, + which is why this definition is parameterized. *) +%inline include_statement(thing): + INCLUDE + ext = ext + attrs1 = attributes + thing = thing + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + Incl.mk thing ~attrs ~loc ~docs, ext + } +; + +(* A module type declaration. *) +module_type_declaration: + MODULE TYPE + ext = ext + attrs1 = attributes + id = mkrhs(ident) + typ = preceded(EQUAL, module_type)? + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + Mtd.mk id ?typ ~attrs ~loc ~docs, ext + } +; + +(* -------------------------------------------------------------------------- *) + +(* Opens. *) + +open_declaration: + OPEN + override = override_flag + ext = ext + attrs1 = attributes + me = module_expr + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + Opn.mk me ~override ~attrs ~loc ~docs, ext + } +; + +open_description: + OPEN + override = override_flag + ext = ext + attrs1 = attributes + id = mkrhs(mod_ext_longident) + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + Opn.mk id ~override ~attrs ~loc ~docs, ext + } +; + +%inline open_dot_declaration: mkrhs(mod_longident) + { let loc = make_loc $loc($1) in + let me = Mod.ident ~loc $1 in + Opn.mk ~loc me } +; + +(* -------------------------------------------------------------------------- *) + /* Module types */ module_type: - mty_longident - { mkmty(Pmty_ident (mkrhs $1 1)) } - | SIG attributes signature END - { mkmty ~attrs:$2 (Pmty_signature (extra_sig 3 $3)) } + | SIG attrs = attributes s = signature END + { mkmty ~loc:$sloc ~attrs (Pmty_signature s) } | SIG attributes signature error - { unclosed "sig" 1 "end" 4 } - | FUNCTOR attributes functor_args MINUSGREATER module_type - %prec below_WITH - { let mty = - List.fold_left - (fun acc (n, t) -> mkmty(Pmty_functor(n, t, acc))) - $5 $3 - in wrap_mty_attrs mty $2 } - | module_type MINUSGREATER module_type + { unclosed "sig" $loc($1) "end" $loc($4) } + | FUNCTOR attrs = attributes args = functor_args + MINUSGREATER mty = module_type %prec below_WITH - { mkmty(Pmty_functor(mknoloc "_", Some $1, $3)) } - | module_type WITH with_constraints - { mkmty(Pmty_with($1, List.rev $3)) } + { wrap_mty_attrs ~loc:$sloc attrs ( + List.fold_left (fun acc (x, mty) -> + mkmty ~loc:$sloc (Pmty_functor (x, mty, acc)) + ) mty args + ) } | MODULE TYPE OF attributes module_expr %prec below_LBRACKETAT - { mkmty ~attrs:$4 (Pmty_typeof $5) } -/* | LPAREN MODULE mod_longident RPAREN - { mkmty (Pmty_alias (mkrhs $3 3)) } */ + { mkmty ~loc:$sloc ~attrs:$4 (Pmty_typeof $5) } | LPAREN module_type RPAREN { $2 } | LPAREN module_type error - { unclosed "(" 1 ")" 3 } - | extension - { mkmty(Pmty_extension $1) } + { unclosed "(" $loc($1) ")" $loc($3) } | module_type attribute { Mty.attr $1 $2 } -; + | mkmty( + mkrhs(mty_longident) + { Pmty_ident $1 } + | module_type MINUSGREATER module_type + %prec below_WITH + { Pmty_functor(mknoloc "_", Some $1, $3) } + | module_type WITH separated_nonempty_llist(AND, with_constraint) + { Pmty_with($1, $3) } +/* | LPAREN MODULE mkrhs(mod_longident) RPAREN + { Pmty_alias $3 } */ + | extension + { Pmty_extension $1 } + ) + { $1 } +; +(* A signature, which appears between SIG and END (among other places), + is a list of signature elements. *) signature: - /* empty */ { [] } - | SEMISEMI signature { (text_sig 1) @ $2 } - | signature_item signature { (text_sig 1) @ $1 :: $2 } + extra_sig(flatten(signature_element*)) + { $1 } ; + +(* A signature element is one of the following: + - a double semicolon; + - a signature item. *) +%inline signature_element: + text_sig_SEMISEMI + | text_sig(signature_item) + { $1 } +; + +(* A signature item. *) signature_item: - value_description - { let (body, ext) = $1 in mksig_ext (Psig_value body) ext } - | primitive_declaration - { let (body, ext) = $1 in mksig_ext (Psig_value body) ext} - | type_declarations - { let (nr, l, ext) = $1 in mksig_ext (Psig_type (nr, List.rev l)) ext } - | sig_type_extension - { let (l, ext) = $1 in mksig_ext (Psig_typext l) ext } - | sig_exception_declaration - { let (l, ext) = $1 in mksig_ext (Psig_exception l) ext } - | module_declaration - { let (body, ext) = $1 in mksig_ext (Psig_module body) ext } - | module_alias - { let (body, ext) = $1 in mksig_ext (Psig_module body) ext } - | rec_module_declarations - { let (l, ext) = $1 in mksig_ext (Psig_recmodule (List.rev l)) ext } - | module_type_declaration - { let (body, ext) = $1 in mksig_ext (Psig_modtype body) ext } - | open_statement - { let (body, ext) = $1 in mksig_ext (Psig_open body) ext } - | sig_include_statement - { let (body, ext) = $1 in mksig_ext (Psig_include body) ext } - | class_descriptions - { let (l, ext) = $1 in mksig_ext (Psig_class (List.rev l)) ext } - | class_type_declarations - { let (l, ext) = $1 in mksig_ext (Psig_class_type (List.rev l)) ext } | item_extension post_item_attributes - { mksig(Psig_extension ($1, (add_docs_attrs (symbol_docs ()) $2))) } - | floating_attribute - { mark_symbol_docs (); - mksig(Psig_attribute $1) } -; -open_statement: - | OPEN override_flag ext_attributes mod_longident post_item_attributes - { let (ext, attrs) = $3 in - Opn.mk (mkrhs $4 4) ~override:$2 ~attrs:(attrs@$5) - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) - , ext} -; -sig_include_statement: - INCLUDE ext_attributes module_type post_item_attributes %prec below_WITH - { let (ext, attrs) = $2 in - Incl.mk $3 ~attrs:(attrs@$4) - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) - , ext} -; + { let docs = symbol_docs $sloc in + mksig ~loc:$sloc (Psig_extension ($1, (add_docs_attrs docs $2))) } + | mksig( + floating_attribute + { Psig_attribute $1 } + ) + { $1 } + | wrap_mksig_ext( + value_description + { psig_value $1 } + | primitive_declaration + { psig_value $1 } + | type_declarations + { psig_type $1 } + | type_subst_declarations + { psig_typesubst $1 } + | sig_type_extension + { psig_typext $1 } + | sig_exception_declaration + { psig_exception $1 } + | module_declaration + { let (body, ext) = $1 in (Psig_module body, ext) } + | module_alias + { let (body, ext) = $1 in (Psig_module body, ext) } + | module_subst + { let (body, ext) = $1 in (Psig_modsubst body, ext) } + | rec_module_declarations + { let (ext, l) = $1 in (Psig_recmodule l, ext) } + | module_type_declaration + { let (body, ext) = $1 in (Psig_modtype body, ext) } + | open_description + { let (body, ext) = $1 in (Psig_open body, ext) } + | include_statement(module_type) + { psig_include $1 } + | class_descriptions + { let (ext, l) = $1 in (Psig_class l, ext) } + | class_type_declarations + { let (ext, l) = $1 in (Psig_class_type l, ext) } + ) + { $1 } + +(* A module declaration. *) +%inline module_declaration: + MODULE + ext = ext attrs1 = attributes + uid = mkrhs(UIDENT) + body = module_declaration_body + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + Md.mk uid body ~attrs ~loc ~docs, ext + } +; + +(* The body (right-hand side) of a module declaration. *) module_declaration_body: - COLON module_type - { $2 } - | LPAREN UIDENT COLON module_type RPAREN module_declaration_body - { mkmty(Pmty_functor(mkrhs $2 2, Some $4, $6)) } - | LPAREN RPAREN module_declaration_body - { mkmty(Pmty_functor(mkrhs "*" 1, None, $3)) } -; -module_declaration: - MODULE ext_attributes UIDENT module_declaration_body post_item_attributes - { let (ext, attrs) = $2 in - Md.mk (mkrhs $3 3) $4 ~attrs:(attrs@$5) - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) - , ext } -; -module_alias: - MODULE ext_attributes UIDENT EQUAL mod_longident post_item_attributes - { let (ext, attrs) = $2 in - Md.mk (mkrhs $3 3) - (Mty.alias ~loc:(rhs_loc 5) (mkrhs $5 5)) ~attrs:(attrs@$6) - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) - , ext } -; -rec_module_declarations: - rec_module_declaration - { let (body, ext) = $1 in ([body], ext) } - | rec_module_declarations and_module_declaration - { let (l, ext) = $1 in ($2 :: l, ext) } + COLON mty = module_type + { mty } + | mkmty( + arg = functor_arg body = module_declaration_body + { let (x, mty) = arg in + Pmty_functor(x, mty, body) } + ) + { $1 } +; + +(* A module alias declaration (in a signature). *) +%inline module_alias: + MODULE + ext = ext attrs1 = attributes + uid = mkrhs(UIDENT) + EQUAL + body = module_expr_alias + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + Md.mk uid body ~attrs ~loc ~docs, ext + } +; +%inline module_expr_alias: + id = mkrhs(mod_longident) + { Mty.alias ~loc:(make_loc $sloc) id } +; +(* A module substitution (in a signature). *) +module_subst: + MODULE + ext = ext attrs1 = attributes + uid = mkrhs(UIDENT) + COLONEQUAL + body = mkrhs(mod_ext_longident) + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + Ms.mk uid body ~attrs ~loc ~docs, ext + } +| MODULE ext attributes mkrhs(UIDENT) COLONEQUAL error + { expecting $loc($6) "module path" } +; + +(* A group of recursive module declarations. *) +%inline rec_module_declarations: + xlist(rec_module_declaration, and_module_declaration) + { $1 } +; +%inline rec_module_declaration: + MODULE + ext = ext + attrs1 = attributes + REC + uid = mkrhs(UIDENT) + COLON + mty = module_type + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + ext, Md.mk uid mty ~attrs ~loc ~docs + } +; +%inline and_module_declaration: + AND + attrs1 = attributes + uid = mkrhs(UIDENT) + COLON + mty = module_type + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + let docs = symbol_docs $sloc in + let loc = make_loc $sloc in + let text = symbol_text $symbolstartpos in + Md.mk uid mty ~attrs ~loc ~text ~docs + } +; + +(* -------------------------------------------------------------------------- *) + +(* Class declarations. *) + +%inline class_declarations: + xlist(class_declaration, and_class_declaration) + { $1 } +; +%inline class_declaration: + CLASS + ext = ext + attrs1 = attributes + virt = virtual_flag + params = formal_class_parameters + id = mkrhs(LIDENT) + body = class_fun_binding + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + ext, + Ci.mk id body ~virt ~params ~attrs ~loc ~docs + } +; +%inline and_class_declaration: + AND + attrs1 = attributes + virt = virtual_flag + params = formal_class_parameters + id = mkrhs(LIDENT) + body = class_fun_binding + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + let text = symbol_text $symbolstartpos in + Ci.mk id body ~virt ~params ~attrs ~loc ~text ~docs + } ; -rec_module_declaration: - MODULE ext_attributes REC UIDENT COLON module_type post_item_attributes - { let (ext, attrs) = $2 in - Md.mk (mkrhs $4 4) $6 ~attrs:(attrs@$7) - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) - , ext} -; -and_module_declaration: - AND attributes UIDENT COLON module_type post_item_attributes - { Md.mk (mkrhs $3 3) $5 ~attrs:($2@$6) ~loc:(symbol_rloc()) - ~text:(symbol_text()) ~docs:(symbol_docs()) } -; -module_type_declaration_body: - /* empty */ { None } - | EQUAL module_type { Some $2 } -; -module_type_declaration: - MODULE TYPE ext_attributes ident module_type_declaration_body - post_item_attributes - { let (ext, attrs) = $3 in - Mtd.mk (mkrhs $4 4) ?typ:$5 ~attrs:(attrs@$6) - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) - , ext } -; -/* Class expressions */ -class_declarations: - class_declaration - { let (body, ext) = $1 in ([body], ext) } - | class_declarations and_class_declaration - { let (l, ext) = $1 in ($2 :: l, ext) } -; -class_declaration: - CLASS ext_attributes virtual_flag class_type_parameters LIDENT - class_fun_binding post_item_attributes - { let (ext, attrs) = $2 in - Ci.mk (mkrhs $5 5) $6 ~virt:$3 ~params:$4 ~attrs:(attrs@$7) - ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) - , ext } -; -and_class_declaration: - AND attributes virtual_flag class_type_parameters LIDENT class_fun_binding - post_item_attributes - { Ci.mk (mkrhs $5 5) $6 ~virt:$3 ~params:$4 - ~attrs:($2@$7) ~loc:(symbol_rloc ()) - ~text:(symbol_text ()) ~docs:(symbol_docs ()) } -; class_fun_binding: EQUAL class_expr { $2 } - | COLON class_type EQUAL class_expr - { mkclass(Pcl_constraint($4, $2)) } - | labeled_simple_pattern class_fun_binding - { let (l,o,p) = $1 in mkclass(Pcl_fun(l, o, p, $2)) } -; -class_type_parameters: - /*empty*/ { [] } - | LBRACKET type_parameter_list RBRACKET { List.rev $2 } + | mkclass( + COLON class_type EQUAL class_expr + { Pcl_constraint($4, $2) } + | labeled_simple_pattern class_fun_binding + { let (l,o,p) = $1 in Pcl_fun(l, o, p, $2) } + ) { $1 } ; -class_fun_def: - labeled_simple_pattern MINUSGREATER class_expr - { let (l,o,p) = $1 in mkclass(Pcl_fun(l, o, p, $3)) } - | labeled_simple_pattern class_fun_def - { let (l,o,p) = $1 in mkclass(Pcl_fun(l, o, p, $2)) } + +formal_class_parameters: + params = class_parameters(type_parameter) + { params } ; + +(* -------------------------------------------------------------------------- *) + +(* Class expressions. *) + class_expr: class_simple_expr { $1 } | FUN attributes class_fun_def - { wrap_class_attrs $3 $2 } - | class_simple_expr simple_labeled_expr_list - { mkclass(Pcl_apply($1, List.rev $2)) } - | let_bindings IN class_expr - { class_of_let_bindings $1 $3 } - | LET OPEN override_flag attributes mod_longident IN class_expr - { wrap_class_attrs (mkclass(Pcl_open($3, mkrhs $5 5, $7))) $4 } + { wrap_class_attrs ~loc:$sloc $3 $2 } + | let_bindings(no_ext) IN class_expr + { class_of_let_bindings ~loc:$sloc $1 $3 } + | LET OPEN override_flag attributes mkrhs(mod_longident) IN class_expr + { let loc = ($startpos($2), $endpos($4)) in + let od = Opn.mk ~override:$3 ~loc:(make_loc loc) $5 in + mkclass ~loc:$sloc ~attrs:$4 (Pcl_open(od, $7)) } | class_expr attribute { Cl.attr $1 $2 } - | extension - { mkclass(Pcl_extension $1) } + | mkclass( + class_simple_expr nonempty_llist(labeled_simple_expr) + { Pcl_apply($1, $2) } + | extension + { Pcl_extension $1 } + ) { $1 } ; class_simple_expr: - LBRACKET core_type_comma_list RBRACKET class_longident - { mkclass(Pcl_constr(mkloc $4 (rhs_loc 4), List.rev $2)) } - | class_longident - { mkclass(Pcl_constr(mkrhs $1 1, [])) } - | OBJECT attributes class_structure END - { mkclass ~attrs:$2 (Pcl_structure $3) } - | OBJECT attributes class_structure error - { unclosed "object" 1 "end" 4 } - | LPAREN class_expr COLON class_type RPAREN - { mkclass(Pcl_constraint($2, $4)) } - | LPAREN class_expr COLON class_type error - { unclosed "(" 1 ")" 5 } | LPAREN class_expr RPAREN { $2 } | LPAREN class_expr error - { unclosed "(" 1 ")" 3 } + { unclosed "(" $loc($1) ")" $loc($3) } + | mkclass( + tys = actual_class_parameters cid = mkrhs(class_longident) + { Pcl_constr(cid, tys) } + | OBJECT attributes class_structure error + { unclosed "object" $loc($1) "end" $loc($4) } + | LPAREN class_expr COLON class_type RPAREN + { Pcl_constraint($2, $4) } + | LPAREN class_expr COLON class_type error + { unclosed "(" $loc($1) ")" $loc($5) } + ) { $1 } + | OBJECT attributes class_structure END + { mkclass ~loc:$sloc ~attrs:$2 (Pcl_structure $3) } ; -class_structure: - | class_self_pattern class_fields - { Cstr.mk $1 (extra_cstr 2 (List.rev $2)) } + +class_fun_def: + mkclass( + labeled_simple_pattern MINUSGREATER e = class_expr + | labeled_simple_pattern e = class_fun_def + { let (l,o,p) = $1 in Pcl_fun(l, o, p, e) } + ) { $1 } +; +%inline class_structure: + | class_self_pattern extra_cstr(class_fields) + { Cstr.mk $1 $2 } ; class_self_pattern: LPAREN pattern RPAREN - { reloc_pat $2 } - | LPAREN pattern COLON core_type RPAREN - { mkpat(Ppat_constraint($2, $4)) } + { reloc_pat ~loc:$sloc $2 } + | mkpat(LPAREN pattern COLON core_type RPAREN + { Ppat_constraint($2, $4) }) + { $1 } | /* empty */ - { ghpat(Ppat_any) } + { ghpat ~loc:$sloc Ppat_any } ; -class_fields: - /* empty */ - { [] } - | class_fields class_field - { $2 :: (text_cstr 2) @ $1 } +%inline class_fields: + flatten(text_cstr(class_field)*) + { $1 } ; class_field: - | INHERIT override_flag attributes class_expr parent_binder + | INHERIT override_flag attributes class_expr + self = preceded(AS, mkrhs(LIDENT))? post_item_attributes - { mkcf (Pcf_inherit ($2, $4, $5)) ~attrs:($3@$6) ~docs:(symbol_docs ()) } + { let docs = symbol_docs $sloc in + mkcf ~loc:$sloc (Pcf_inherit ($2, $4, self)) ~attrs:($3@$6) ~docs } | VAL value post_item_attributes { let v, attrs = $2 in - mkcf (Pcf_val v) ~attrs:(attrs@$3) ~docs:(symbol_docs ()) } + let docs = symbol_docs $sloc in + mkcf ~loc:$sloc (Pcf_val v) ~attrs:(attrs@$3) ~docs } | METHOD method_ post_item_attributes { let meth, attrs = $2 in - mkcf (Pcf_method meth) ~attrs:(attrs@$3) ~docs:(symbol_docs ()) } + let docs = symbol_docs $sloc in + mkcf ~loc:$sloc (Pcf_method meth) ~attrs:(attrs@$3) ~docs } | CONSTRAINT attributes constrain_field post_item_attributes - { mkcf (Pcf_constraint $3) ~attrs:($2@$4) ~docs:(symbol_docs ()) } + { let docs = symbol_docs $sloc in + mkcf ~loc:$sloc (Pcf_constraint $3) ~attrs:($2@$4) ~docs } | INITIALIZER attributes seq_expr post_item_attributes - { mkcf (Pcf_initializer $3) ~attrs:($2@$4) ~docs:(symbol_docs ()) } + { let docs = symbol_docs $sloc in + mkcf ~loc:$sloc (Pcf_initializer $3) ~attrs:($2@$4) ~docs } | item_extension post_item_attributes - { mkcf (Pcf_extension $1) ~attrs:$2 ~docs:(symbol_docs ()) } - | floating_attribute - { mark_symbol_docs (); - mkcf (Pcf_attribute $1) } -; -parent_binder: - AS LIDENT - { Some (mkrhs $2 2) } - | /* empty */ - { None } + { let docs = symbol_docs $sloc in + mkcf ~loc:$sloc (Pcf_extension $1) ~attrs:$2 ~docs } + | mkcf(floating_attribute + { Pcf_attribute $1 }) + { $1 } ; value: -/* TODO: factorize these rules (also with method): */ - override_flag attributes MUTABLE VIRTUAL label COLON core_type - { if $1 = Override then syntax_error (); - (mkloc $5 (rhs_loc 5), Mutable, Cfk_virtual $7), $2 } - | override_flag attributes VIRTUAL mutable_flag label COLON core_type - { if $1 = Override then syntax_error (); - (mkrhs $5 5, $4, Cfk_virtual $7), $2 } - | override_flag attributes mutable_flag label EQUAL seq_expr - { (mkrhs $4 4, $3, Cfk_concrete ($1, $6)), $2 } - | override_flag attributes mutable_flag label type_constraint EQUAL seq_expr - { - let e = mkexp_constraint $7 $5 in - (mkrhs $4 4, $3, Cfk_concrete ($1, e)), $2 + no_override_flag + attrs = attributes + mutable_ = virtual_with_mutable_flag + label = mkrhs(label) COLON ty = core_type + { (label, mutable_, Cfk_virtual ty), attrs } + | override_flag attributes mutable_flag mkrhs(label) EQUAL seq_expr + { ($4, $3, Cfk_concrete ($1, $6)), $2 } + | override_flag attributes mutable_flag mkrhs(label) type_constraint + EQUAL seq_expr + { let e = mkexp_constraint ~loc:$sloc $7 $5 in + ($4, $3, Cfk_concrete ($1, e)), $2 } ; method_: -/* TODO: factorize those rules... */ - override_flag attributes PRIVATE VIRTUAL label COLON poly_type - { if $1 = Override then syntax_error (); - (mkloc $5 (rhs_loc 5), Private, Cfk_virtual $7), $2 } - | override_flag attributes VIRTUAL private_flag label COLON poly_type - { if $1 = Override then syntax_error (); - (mkloc $5 (rhs_loc 5), $4, Cfk_virtual $7), $2 } - | override_flag attributes private_flag label strict_binding - { (mkloc $4 (rhs_loc 4), $3, - Cfk_concrete ($1, ghexp(Pexp_poly ($5, None)))), $2 } - | override_flag attributes private_flag label COLON poly_type EQUAL seq_expr - { (mkloc $4 (rhs_loc 4), $3, - Cfk_concrete ($1, ghexp(Pexp_poly($8, Some $6)))), $2 } - | override_flag attributes private_flag label COLON TYPE lident_list + no_override_flag + attrs = attributes + private_ = virtual_with_private_flag + label = mkrhs(label) COLON ty = poly_type + { (label, private_, Cfk_virtual ty), attrs } + | override_flag attributes private_flag mkrhs(label) strict_binding + { let e = $5 in + let loc = Location.(e.pexp_loc.loc_start, e.pexp_loc.loc_end) in + ($4, $3, + Cfk_concrete ($1, ghexp ~loc (Pexp_poly (e, None)))), $2 } + | override_flag attributes private_flag mkrhs(label) + COLON poly_type EQUAL seq_expr + { let poly_exp = + let loc = ($startpos($6), $endpos($8)) in + ghexp ~loc (Pexp_poly($8, Some $6)) in + ($4, $3, Cfk_concrete ($1, poly_exp)), $2 } + | override_flag attributes private_flag mkrhs(label) COLON TYPE lident_list DOT core_type EQUAL seq_expr - { let exp, poly = wrap_type_annotation $7 $9 $11 in - (mkloc $4 (rhs_loc 4), $3, - Cfk_concrete ($1, ghexp(Pexp_poly(exp, Some poly)))), $2 } + { let poly_exp_loc = ($startpos($7), $endpos($11)) in + let poly_exp = + let exp, poly = + (* it seems odd to use the global ~loc here while poly_exp_loc + is tighter, but this is what ocamlyacc does; + TODO improve parser.mly *) + wrap_type_annotation ~loc:$sloc $7 $9 $11 in + ghexp ~loc:poly_exp_loc (Pexp_poly(exp, Some poly)) in + ($4, $3, + Cfk_concrete ($1, poly_exp)), $2 } ; /* Class types */ @@ -1145,120 +1827,174 @@ method_: class_type: class_signature { $1 } - | QUESTION LIDENT COLON simple_core_type_or_tuple MINUSGREATER - class_type - { mkcty(Pcty_arrow(Optional $2 , $4, $6)) } - | OPTLABEL simple_core_type_or_tuple MINUSGREATER class_type - { mkcty(Pcty_arrow(Optional $1, $2, $4)) } - | LIDENT COLON simple_core_type_or_tuple MINUSGREATER class_type - { mkcty(Pcty_arrow(Labelled $1, $3, $5)) } - | simple_core_type_or_tuple MINUSGREATER class_type - { mkcty(Pcty_arrow(Nolabel, $1, $3)) } + | mkcty( + label = arg_label + domain = tuple_type + MINUSGREATER + codomain = class_type + { Pcty_arrow(label, domain, codomain) } + ) { $1 } ; class_signature: - LBRACKET core_type_comma_list RBRACKET clty_longident - { mkcty(Pcty_constr (mkloc $4 (rhs_loc 4), List.rev $2)) } - | clty_longident - { mkcty(Pcty_constr (mkrhs $1 1, [])) } + mkcty( + tys = actual_class_parameters cid = mkrhs(clty_longident) + { Pcty_constr (cid, tys) } + | extension + { Pcty_extension $1 } + ) { $1 } | OBJECT attributes class_sig_body END - { mkcty ~attrs:$2 (Pcty_signature $3) } + { mkcty ~loc:$sloc ~attrs:$2 (Pcty_signature $3) } | OBJECT attributes class_sig_body error - { unclosed "object" 1 "end" 4 } + { unclosed "object" $loc($1) "end" $loc($4) } | class_signature attribute { Cty.attr $1 $2 } - | extension - { mkcty(Pcty_extension $1) } - | LET OPEN override_flag attributes mod_longident IN class_signature - { wrap_class_type_attrs (mkcty(Pcty_open($3, mkrhs $5 5, $7))) $4 } + | LET OPEN override_flag attributes mkrhs(mod_longident) IN class_signature + { let loc = ($startpos($2), $endpos($4)) in + let od = Opn.mk ~override:$3 ~loc:(make_loc loc) $5 in + mkcty ~loc:$sloc ~attrs:$4 (Pcty_open(od, $7)) } ; -class_sig_body: - class_self_type class_sig_fields - { Csig.mk $1 (extra_csig 2 (List.rev $2)) } +%inline class_parameters(parameter): + | /* empty */ + { [] } + | LBRACKET params = separated_nonempty_llist(COMMA, parameter) RBRACKET + { params } +; +%inline actual_class_parameters: + tys = class_parameters(core_type) + { tys } +; +%inline class_sig_body: + class_self_type extra_csig(class_sig_fields) + { Csig.mk $1 $2 } ; class_self_type: LPAREN core_type RPAREN { $2 } - | /* empty */ - { mktyp(Ptyp_any) } + | mktyp((* empty *) { Ptyp_any }) + { $1 } ; -class_sig_fields: - /* empty */ { [] } -| class_sig_fields class_sig_field { $2 :: (text_csig 2) @ $1 } +%inline class_sig_fields: + flatten(text_csig(class_sig_field)*) + { $1 } ; class_sig_field: INHERIT attributes class_signature post_item_attributes - { mkctf (Pctf_inherit $3) ~attrs:($2@$4) ~docs:(symbol_docs ()) } + { let docs = symbol_docs $sloc in + mkctf ~loc:$sloc (Pctf_inherit $3) ~attrs:($2@$4) ~docs } | VAL attributes value_type post_item_attributes - { mkctf (Pctf_val $3) ~attrs:($2@$4) ~docs:(symbol_docs ()) } - | METHOD attributes private_virtual_flags label COLON poly_type + { let docs = symbol_docs $sloc in + mkctf ~loc:$sloc (Pctf_val $3) ~attrs:($2@$4) ~docs } + | METHOD attributes private_virtual_flags mkrhs(label) COLON poly_type post_item_attributes - { - let (p, v) = $3 in - mkctf (Pctf_method (mkrhs $4 4, p, v, $6)) ~attrs:($2@$7) ~docs:(symbol_docs ()) - } + { let (p, v) = $3 in + let docs = symbol_docs $sloc in + mkctf ~loc:$sloc (Pctf_method ($4, p, v, $6)) ~attrs:($2@$7) ~docs } | CONSTRAINT attributes constrain_field post_item_attributes - { mkctf (Pctf_constraint $3) ~attrs:($2@$4) ~docs:(symbol_docs ()) } + { let docs = symbol_docs $sloc in + mkctf ~loc:$sloc (Pctf_constraint $3) ~attrs:($2@$4) ~docs } | item_extension post_item_attributes - { mkctf (Pctf_extension $1) ~attrs:$2 ~docs:(symbol_docs ()) } - | floating_attribute - { mark_symbol_docs (); - mkctf(Pctf_attribute $1) } -; -value_type: - VIRTUAL mutable_flag label COLON core_type - { mkrhs $3 3, $2, Virtual, $5 } - | MUTABLE virtual_flag label COLON core_type - { mkrhs $3 3, Mutable, $2, $5 } - | label COLON core_type - { mkrhs $1 1, Immutable, Concrete, $3 } -; -constrain: - core_type EQUAL core_type { $1, $3, symbol_rloc() } + { let docs = symbol_docs $sloc in + mkctf ~loc:$sloc (Pctf_extension $1) ~attrs:$2 ~docs } + | mkctf(floating_attribute + { Pctf_attribute $1 }) + { $1 } ; -constrain_field: - core_type EQUAL core_type { $1, $3 } -; -class_descriptions: - class_description - { let (body, ext) = $1 in ([body],ext) } - | class_descriptions and_class_description - { let (l, ext) = $1 in ($2 :: l, ext) } -; -class_description: - CLASS ext_attributes virtual_flag class_type_parameters LIDENT COLON - class_type post_item_attributes - { let (ext, attrs) = $2 in - Ci.mk (mkrhs $5 5) $7 ~virt:$3 ~params:$4 ~attrs:(attrs @ $8) - ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) - , ext } +%inline value_type: + flags = mutable_virtual_flags + label = mkrhs(label) + COLON + ty = core_type + { + let mut, virt = flags in + label, mut, virt, ty + } ; -and_class_description: - AND attributes virtual_flag class_type_parameters LIDENT COLON class_type - post_item_attributes - { Ci.mk (mkrhs $5 5) $7 ~virt:$3 ~params:$4 - ~attrs:($2@$8) ~loc:(symbol_rloc ()) - ~text:(symbol_text ()) ~docs:(symbol_docs ()) } +%inline constrain: + core_type EQUAL core_type + { $1, $3, make_loc $sloc } +; +constrain_field: + core_type EQUAL core_type + { $1, $3 } +; +(* A group of class descriptions. *) +%inline class_descriptions: + xlist(class_description, and_class_description) + { $1 } +; +%inline class_description: + CLASS + ext = ext + attrs1 = attributes + virt = virtual_flag + params = formal_class_parameters + id = mkrhs(LIDENT) + COLON + cty = class_type + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + ext, + Ci.mk id cty ~virt ~params ~attrs ~loc ~docs + } +; +%inline and_class_description: + AND + attrs1 = attributes + virt = virtual_flag + params = formal_class_parameters + id = mkrhs(LIDENT) + COLON + cty = class_type + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + let text = symbol_text $symbolstartpos in + Ci.mk id cty ~virt ~params ~attrs ~loc ~text ~docs + } ; class_type_declarations: - class_type_declaration - { let (body, ext) = $1 in ([body],ext) } - | class_type_declarations and_class_type_declaration - { let (l, ext) = $1 in ($2 :: l, ext) } -; -class_type_declaration: - CLASS TYPE ext_attributes virtual_flag class_type_parameters LIDENT EQUAL - class_signature post_item_attributes - { let (ext, attrs) = $3 in - Ci.mk (mkrhs $6 6) $8 ~virt:$4 ~params:$5 ~attrs:(attrs@$9) - ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) - , ext} -; -and_class_type_declaration: - AND attributes virtual_flag class_type_parameters LIDENT EQUAL - class_signature post_item_attributes - { Ci.mk (mkrhs $5 5) $7 ~virt:$3 ~params:$4 - ~attrs:($2@$8) ~loc:(symbol_rloc ()) - ~text:(symbol_text ()) ~docs:(symbol_docs ()) } + xlist(class_type_declaration, and_class_type_declaration) + { $1 } +; +%inline class_type_declaration: + CLASS TYPE + ext = ext + attrs1 = attributes + virt = virtual_flag + params = formal_class_parameters + id = mkrhs(LIDENT) + EQUAL + csig = class_signature + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + ext, + Ci.mk id csig ~virt ~params ~attrs ~loc ~docs + } +; +%inline and_class_type_declaration: + AND + attrs1 = attributes + virt = virtual_flag + params = formal_class_parameters + id = mkrhs(LIDENT) + EQUAL + csig = class_signature + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + let text = symbol_text $symbolstartpos in + Ci.mk id csig ~virt ~params ~attrs ~loc ~text ~docs + } ; /* Core expressions */ @@ -1266,11 +2002,13 @@ and_class_type_declaration: seq_expr: | expr %prec below_SEMI { $1 } | expr SEMI { $1 } - | expr SEMI seq_expr { mkexp(Pexp_sequence($1, $3)) } + | mkexp(expr SEMI seq_expr + { Pexp_sequence($1, $3) }) + { $1 } | expr SEMI PERCENT attr_id seq_expr - { let seq = mkexp(Pexp_sequence ($1, $5)) in - let payload = PStr [mkstrexp seq []] in - mkexp (Pexp_extension ($4, payload)) } + { let seq = mkexp ~loc:$sloc (Pexp_sequence ($1, $5)) in + let payload = PStr [mkstrexp seq []] in + mkexp ~loc:$sloc (Pexp_extension ($4, payload)) } ; labeled_simple_pattern: QUESTION LPAREN label_let_pattern opt_default RPAREN @@ -1290,393 +2028,422 @@ labeled_simple_pattern: | simple_pattern { (Nolabel, None, $1) } ; + pattern_var: - LIDENT { mkpat(Ppat_var (mkrhs $1 1)) } - | UNDERSCORE { mkpat Ppat_any } + mkpat( + mkrhs(LIDENT) { Ppat_var $1 } + | UNDERSCORE { Ppat_any } + ) { $1 } ; -opt_default: - /* empty */ { None } - | EQUAL seq_expr { Some $2 } + +%inline opt_default: + preceded(EQUAL, seq_expr)? + { $1 } ; label_let_pattern: - label_var - { $1 } - | label_var COLON core_type - { let (lab, pat) = $1 in (lab, mkpat(Ppat_constraint(pat, $3))) } + x = label_var + { x } + | x = label_var COLON cty = core_type + { let lab, pat = x in + lab, + mkpat ~loc:$sloc (Ppat_constraint (pat, cty)) } ; -label_var: - LIDENT { ($1, mkpat(Ppat_var (mkrhs $1 1))) } +%inline label_var: + mkrhs(LIDENT) + { ($1.Location.txt, mkpat ~loc:$sloc (Ppat_var $1)) } ; let_pattern: pattern { $1 } - | pattern COLON core_type - { mkpat(Ppat_constraint($1, $3)) } + | mkpat(pattern COLON core_type + { Ppat_constraint($1, $3) }) + { $1 } ; + expr: simple_expr %prec below_HASH { $1 } - | simple_expr simple_labeled_expr_list - { mkexp(Pexp_apply($1, List.rev $2)) } - | let_bindings IN seq_expr - { expr_of_let_bindings $1 $3 } - | LET MODULE ext_attributes UIDENT module_binding_body IN seq_expr - { mkexp_attrs (Pexp_letmodule(mkrhs $4 4, $5, $7)) $3 } + | expr_attrs + { let desc, attrs = $1 in + mkexp_attrs ~loc:$sloc desc attrs } + | mkexp(expr_) + { $1 } + | let_bindings(ext) IN seq_expr + { expr_of_let_bindings ~loc:$sloc $1 $3 } + | pbop_op = mkrhs(LETOP) bindings = letop_bindings IN body = seq_expr + { let (pbop_pat, pbop_exp, rev_ands) = bindings in + let ands = List.rev rev_ands in + let pbop_loc = make_loc $sloc in + let let_ = {pbop_op; pbop_pat; pbop_exp; pbop_loc} in + mkexp ~loc:$sloc (Pexp_letop{ let_; ands; body}) } + | expr COLONCOLON expr + { mkexp_cons ~loc:$sloc $loc($2) (ghexp ~loc:$sloc (Pexp_tuple[$1;$3])) } + | mkrhs(label) LESSMINUS expr + { mkexp ~loc:$sloc (Pexp_setinstvar($1, $3)) } + | simple_expr DOT mkrhs(label_longident) LESSMINUS expr + { mkexp ~loc:$sloc (Pexp_setfield($1, $3, $5)) } + | simple_expr DOT LPAREN seq_expr RPAREN LESSMINUS expr + { array_set ~loc:$sloc $1 $4 $7 } + | simple_expr DOT LBRACKET seq_expr RBRACKET LESSMINUS expr + { string_set ~loc:$sloc $1 $4 $7 } + | simple_expr DOT LBRACE expr RBRACE LESSMINUS expr + { bigarray_set ~loc:$sloc $1 $4 $7 } + | simple_expr DOTOP LBRACKET expr RBRACKET LESSMINUS expr + { dotop_set ~loc:$sloc (Lident ("." ^ $2 ^ "[]<-")) $1 $4 $7 } + | simple_expr DOTOP LPAREN expr RPAREN LESSMINUS expr + { dotop_set ~loc:$sloc (Lident ("." ^ $2 ^ "()<-")) $1 $4 $7 } + | simple_expr DOTOP LBRACE expr RBRACE LESSMINUS expr + { dotop_set ~loc:$sloc (Lident ("." ^ $2 ^ "{}<-")) $1 $4 $7 } + | simple_expr DOT mod_longident DOTOP LBRACKET expr RBRACKET LESSMINUS expr + { dotop_set ~loc:$sloc (Ldot($3,"." ^ $4 ^ "[]<-")) $1 $6 $9 } + | simple_expr DOT mod_longident DOTOP LPAREN expr RPAREN LESSMINUS expr + { dotop_set ~loc:$sloc (Ldot($3, "." ^ $4 ^ "()<-")) $1 $6 $9 } + | simple_expr DOT mod_longident DOTOP LBRACE expr RBRACE LESSMINUS expr + { dotop_set ~loc:$sloc (Ldot($3, "." ^ $4 ^ "{}<-")) $1 $6 $9 } + | expr attribute + { Exp.attr $1 $2 } + | UNDERSCORE + { not_expecting $loc($1) "wildcard \"_\"" } +; +%inline expr_attrs: + | LET MODULE ext_attributes mkrhs(UIDENT) module_binding_body IN seq_expr + { Pexp_letmodule($4, $5, $7), $3 } | LET EXCEPTION ext_attributes let_exception_declaration IN seq_expr - { mkexp_attrs (Pexp_letexception($4, $6)) $3 } - | LET OPEN override_flag ext_attributes mod_longident IN seq_expr - { mkexp_attrs (Pexp_open($3, mkrhs $5 5, $7)) $4 } - | FUNCTION ext_attributes opt_bar match_cases - { mkexp_attrs (Pexp_function(List.rev $4)) $2 } + { Pexp_letexception($4, $6), $3 } + | LET OPEN override_flag ext_attributes module_expr IN seq_expr + { let open_loc = make_loc ($startpos($2), $endpos($5)) in + let od = Opn.mk $5 ~override:$3 ~loc:open_loc in + Pexp_open(od, $7), $4 } + | FUNCTION ext_attributes match_cases + { Pexp_function $3, $2 } | FUN ext_attributes labeled_simple_pattern fun_def { let (l,o,p) = $3 in - mkexp_attrs (Pexp_fun(l, o, p, $4)) $2 } + Pexp_fun(l, o, p, $4), $2 } | FUN ext_attributes LPAREN TYPE lident_list RPAREN fun_def - { mkexp_attrs (mk_newtypes $5 $7).pexp_desc $2 } - | MATCH ext_attributes seq_expr WITH opt_bar match_cases - { mkexp_attrs (Pexp_match($3, List.rev $6)) $2 } - | TRY ext_attributes seq_expr WITH opt_bar match_cases - { mkexp_attrs (Pexp_try($3, List.rev $6)) $2 } + { (mk_newtypes ~loc:$sloc $5 $7).pexp_desc, $2 } + | MATCH ext_attributes seq_expr WITH match_cases + { Pexp_match($3, $5), $2 } + | TRY ext_attributes seq_expr WITH match_cases + { Pexp_try($3, $5), $2 } | TRY ext_attributes seq_expr WITH error { syntax_error() } - | expr_comma_list %prec below_COMMA - { mkexp(Pexp_tuple(List.rev $1)) } - | constr_longident simple_expr %prec below_HASH - { mkexp(Pexp_construct(mkrhs $1 1, Some $2)) } - | name_tag simple_expr %prec below_HASH - { mkexp(Pexp_variant($1, Some $2)) } | IF ext_attributes seq_expr THEN expr ELSE expr - { mkexp_attrs(Pexp_ifthenelse($3, $5, Some $7)) $2 } + { Pexp_ifthenelse($3, $5, Some $7), $2 } | IF ext_attributes seq_expr THEN expr - { mkexp_attrs (Pexp_ifthenelse($3, $5, None)) $2 } + { Pexp_ifthenelse($3, $5, None), $2 } | WHILE ext_attributes seq_expr DO seq_expr DONE - { mkexp_attrs (Pexp_while($3, $5)) $2 } + { Pexp_while($3, $5), $2 } | FOR ext_attributes pattern EQUAL seq_expr direction_flag seq_expr DO seq_expr DONE - { mkexp_attrs(Pexp_for($3, $5, $7, $6, $9)) $2 } - | expr COLONCOLON expr - { mkexp_cons (rhs_loc 2) (ghexp(Pexp_tuple[$1;$3])) (symbol_rloc()) } - | expr INFIXOP0 expr - { mkinfix $1 $2 $3 } - | expr INFIXOP1 expr - { mkinfix $1 $2 $3 } - | expr INFIXOP2 expr - { mkinfix $1 $2 $3 } - | expr INFIXOP3 expr - { mkinfix $1 $2 $3 } - | expr INFIXOP4 expr - { mkinfix $1 $2 $3 } - | expr PLUS expr - { mkinfix $1 "+" $3 } - | expr PLUSDOT expr - { mkinfix $1 "+." $3 } - | expr PLUSEQ expr - { mkinfix $1 "+=" $3 } - | expr MINUS expr - { mkinfix $1 "-" $3 } - | expr MINUSDOT expr - { mkinfix $1 "-." $3 } - | expr STAR expr - { mkinfix $1 "*" $3 } - | expr PERCENT expr - { mkinfix $1 "%" $3 } - | expr EQUAL expr - { mkinfix $1 "=" $3 } - | expr LESS expr - { mkinfix $1 "<" $3 } - | expr GREATER expr - { mkinfix $1 ">" $3 } - | expr OR expr - { mkinfix $1 "or" $3 } - | expr BARBAR expr - { mkinfix $1 "||" $3 } - | expr AMPERSAND expr - { mkinfix $1 "&" $3 } - | expr AMPERAMPER expr - { mkinfix $1 "&&" $3 } - | expr COLONEQUAL expr - { mkinfix $1 ":=" $3 } - | subtractive expr %prec prec_unary_minus - { mkuminus $1 $2 } - | additive expr %prec prec_unary_plus - { mkuplus $1 $2 } - | simple_expr DOT label_longident LESSMINUS expr - { mkexp(Pexp_setfield($1, mkrhs $3 3, $5)) } - | simple_expr DOT LPAREN seq_expr RPAREN LESSMINUS expr - { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function "Array" "set")), - [Nolabel,$1; Nolabel,$4; Nolabel,$7])) } - | simple_expr DOT LBRACKET seq_expr RBRACKET LESSMINUS expr - { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function "String" "set")), - [Nolabel,$1; Nolabel,$4; Nolabel,$7])) } - | simple_expr DOT LBRACE expr RBRACE LESSMINUS expr - { bigarray_set $1 $4 $7 } - | simple_expr DOTOP LBRACKET expr RBRACKET LESSMINUS expr - { let id = mkexp @@ Pexp_ident( ghloc @@ Lident ("." ^ $2 ^ "[]<-")) in - mkexp @@ Pexp_apply(id , [Nolabel, $1; Nolabel, $4; Nolabel, $7]) } - | simple_expr DOTOP LPAREN expr RPAREN LESSMINUS expr - { let id = mkexp @@ Pexp_ident( ghloc @@ Lident ("." ^ $2 ^ "()<-")) in - mkexp @@ Pexp_apply(id , [Nolabel, $1; Nolabel, $4; Nolabel, $7]) } - | simple_expr DOTOP LBRACE expr RBRACE LESSMINUS expr - { let id = mkexp @@ Pexp_ident( ghloc @@ Lident ("." ^ $2 ^ "{}<-")) in - mkexp @@ Pexp_apply(id , [Nolabel, $1; Nolabel, $4; Nolabel, $7]) } - | simple_expr DOT mod_longident DOTOP LBRACKET expr RBRACKET LESSMINUS expr - { let id = mkexp @@ Pexp_ident( ghloc @@ Ldot($3,"." ^ $4 ^ "[]<-")) in - mkexp @@ Pexp_apply(id , [Nolabel, $1; Nolabel, $6; Nolabel, $9]) } - | simple_expr DOT mod_longident DOTOP LPAREN expr RPAREN LESSMINUS expr - { let id = mkexp @@ Pexp_ident( ghloc @@ Ldot($3, "." ^ $4 ^ "()<-")) in - mkexp @@ Pexp_apply(id , [Nolabel, $1; Nolabel, $6; Nolabel, $9]) } - | simple_expr DOT mod_longident DOTOP LBRACE expr RBRACE LESSMINUS expr - { let id = mkexp @@ Pexp_ident( ghloc @@ Ldot($3, "." ^ $4 ^ "{}<-")) in - mkexp @@ Pexp_apply(id , [Nolabel, $1; Nolabel, $6; Nolabel, $9]) } - | label LESSMINUS expr - { mkexp(Pexp_setinstvar(mkrhs $1 1, $3)) } + { Pexp_for($3, $5, $7, $6, $9), $2 } | ASSERT ext_attributes simple_expr %prec below_HASH - { mkexp_attrs (Pexp_assert $3) $2 } + { Pexp_assert $3, $2 } | LAZY ext_attributes simple_expr %prec below_HASH - { mkexp_attrs (Pexp_lazy $3) $2 } + { Pexp_lazy $3, $2 } | OBJECT ext_attributes class_structure END - { mkexp_attrs (Pexp_object $3) $2 } + { Pexp_object $3, $2 } | OBJECT ext_attributes class_structure error - { unclosed "object" 1 "end" 4 } - | expr attribute - { Exp.attr $1 $2 } - | UNDERSCORE - { not_expecting 1 "wildcard \"_\"" } + { unclosed "object" $loc($1) "end" $loc($4) } ; +%inline expr_: + | simple_expr nonempty_llist(labeled_simple_expr) + { Pexp_apply($1, $2) } + | expr_comma_list %prec below_COMMA + { Pexp_tuple($1) } + | mkrhs(constr_longident) simple_expr %prec below_HASH + { Pexp_construct($1, Some $2) } + | name_tag simple_expr %prec below_HASH + { Pexp_variant($1, Some $2) } + | e1 = expr op = op(infix_operator) e2 = expr + { mkinfix e1 op e2 } + | subtractive expr %prec prec_unary_minus + { mkuminus ~oploc:$loc($1) $1 $2 } + | additive expr %prec prec_unary_plus + { mkuplus ~oploc:$loc($1) $1 $2 } +; + simple_expr: - val_longident - { mkexp(Pexp_ident (mkrhs $1 1)) } - | constant - { mkexp(Pexp_constant $1) } - | constr_longident %prec prec_constant_constructor - { mkexp(Pexp_construct(mkrhs $1 1, None)) } - | name_tag %prec prec_constant_constructor - { mkexp(Pexp_variant($1, None)) } | LPAREN seq_expr RPAREN - { reloc_exp $2 } + { reloc_exp ~loc:$sloc $2 } | LPAREN seq_expr error - { unclosed "(" 1 ")" 3 } - | BEGIN ext_attributes seq_expr END - { wrap_exp_attrs (reloc_exp $3) $2 (* check location *) } - | BEGIN ext_attributes END - { mkexp_attrs (Pexp_construct (mkloc (Lident "()") (symbol_rloc ()), - None)) $2 } - | BEGIN ext_attributes seq_expr error - { unclosed "begin" 1 "end" 4 } + { unclosed "(" $loc($1) ")" $loc($3) } | LPAREN seq_expr type_constraint RPAREN - { mkexp_constraint $2 $3 } - | simple_expr DOT label_longident - { mkexp(Pexp_field($1, mkrhs $3 3)) } - | mod_longident DOT LPAREN seq_expr RPAREN - { mkexp(Pexp_open(Fresh, mkrhs $1 1, $4)) } - | mod_longident DOT LPAREN RPAREN - { mkexp(Pexp_open(Fresh, mkrhs $1 1, - mkexp(Pexp_construct(mkrhs (Lident "()") 1, None)))) } - | mod_longident DOT LPAREN seq_expr error - { unclosed "(" 3 ")" 5 } + { mkexp_constraint ~loc:$sloc $2 $3 } | simple_expr DOT LPAREN seq_expr RPAREN - { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function "Array" "get")), - [Nolabel,$1; Nolabel,$4])) } + { array_get ~loc:$sloc $1 $4 } | simple_expr DOT LPAREN seq_expr error - { unclosed "(" 3 ")" 5 } + { unclosed "(" $loc($3) ")" $loc($5) } | simple_expr DOT LBRACKET seq_expr RBRACKET - { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function "String" "get")), - [Nolabel,$1; Nolabel,$4])) } + { string_get ~loc:$sloc $1 $4 } | simple_expr DOT LBRACKET seq_expr error - { unclosed "[" 3 "]" 5 } + { unclosed "[" $loc($3) "]" $loc($5) } | simple_expr DOTOP LBRACKET expr RBRACKET - { let id = mkexp @@ Pexp_ident( ghloc @@ Lident ("." ^ $2 ^ "[]")) in - mkexp @@ Pexp_apply(id, [Nolabel, $1; Nolabel, $4]) } + { dotop_get ~loc:$sloc (Lident ("." ^ $2 ^ "[]")) $1 $4 } | simple_expr DOTOP LBRACKET expr error - { unclosed "[" 3 "]" 5 } + { unclosed "[" $loc($3) "]" $loc($5) } | simple_expr DOTOP LPAREN expr RPAREN - { let id = mkexp @@ Pexp_ident( ghloc @@ Lident ("." ^ $2 ^ "()")) in - mkexp @@ Pexp_apply(id, [Nolabel, $1; Nolabel, $4]) } + { dotop_get ~loc:$sloc (Lident ("." ^ $2 ^ "()")) $1 $4 } | simple_expr DOTOP LPAREN expr error - { unclosed "(" 3 ")" 5 } + { unclosed "(" $loc($3) ")" $loc($5) } | simple_expr DOTOP LBRACE expr RBRACE - { let id = mkexp @@ Pexp_ident( ghloc @@ Lident ("." ^ $2 ^ "{}")) in - mkexp @@ Pexp_apply(id, [Nolabel, $1; Nolabel, $4]) } + { dotop_get ~loc:$sloc (Lident ("." ^ $2 ^ "{}")) $1 $4 } | simple_expr DOTOP LBRACE expr error - { unclosed "{" 3 "}" 5 } + { unclosed "{" $loc($3) "}" $loc($5) } | simple_expr DOT mod_longident DOTOP LBRACKET expr RBRACKET - { let id = mkexp @@ Pexp_ident( ghloc @@ Ldot($3, "." ^ $4 ^ "[]")) in - mkexp @@ Pexp_apply(id, [Nolabel, $1; Nolabel, $6]) } - | simple_expr DOT mod_longident DOTOP LBRACKET expr error - { unclosed "[" 5 "]" 7 } + { dotop_get ~loc:$sloc (Ldot($3, "." ^ $4 ^ "[]")) $1 $6 } + | simple_expr DOT + mod_longident DOTOP LBRACKET expr error + { unclosed "[" $loc($5) "]" $loc($7) } | simple_expr DOT mod_longident DOTOP LPAREN expr RPAREN - { let id = mkexp @@ Pexp_ident( ghloc @@ Ldot($3, "." ^ $4 ^ "()")) in - mkexp @@ Pexp_apply(id, [Nolabel, $1; Nolabel, $6]) } - | simple_expr DOT mod_longident DOTOP LPAREN expr error - { unclosed "(" 5 ")" 7 } + { dotop_get ~loc:$sloc (Ldot($3, "." ^ $4 ^ "()")) $1 $6 } + | simple_expr DOT + mod_longident DOTOP LPAREN expr error + { unclosed "(" $loc($5) ")" $loc($7) } | simple_expr DOT mod_longident DOTOP LBRACE expr RBRACE - { let id = mkexp @@ Pexp_ident( ghloc @@ Ldot($3, "." ^ $4 ^ "{}")) in - mkexp @@ Pexp_apply(id, [Nolabel, $1; Nolabel, $6]) } - | simple_expr DOT mod_longident DOTOP LBRACE expr error - { unclosed "{" 5 "}" 7 } + { dotop_get ~loc:$sloc (Ldot($3, "." ^ $4 ^ "{}")) $1 $6 } + | simple_expr DOT + mod_longident DOTOP LBRACE expr error + { unclosed "{" $loc($5) "}" $loc($7) } | simple_expr DOT LBRACE expr RBRACE - { bigarray_get $1 $4 } - | simple_expr DOT LBRACE expr_comma_list error - { unclosed "{" 3 "}" 5 } - | LBRACE record_expr RBRACE - { let (exten, fields) = $2 in mkexp (Pexp_record(fields, exten)) } - | LBRACE record_expr error - { unclosed "{" 1 "}" 3 } - | mod_longident DOT LBRACE record_expr RBRACE - { let (exten, fields) = $4 in - let rec_exp = mkexp(Pexp_record(fields, exten)) in - mkexp(Pexp_open(Fresh, mkrhs $1 1, rec_exp)) } - | mod_longident DOT LBRACE record_expr error - { unclosed "{" 3 "}" 5 } - | LBRACKETBAR expr_semi_list opt_semi BARRBRACKET - { mkexp (Pexp_array(List.rev $2)) } - | LBRACKETBAR expr_semi_list opt_semi error - { unclosed "[|" 1 "|]" 4 } - | LBRACKETBAR BARRBRACKET - { mkexp (Pexp_array []) } - | mod_longident DOT LBRACKETBAR expr_semi_list opt_semi BARRBRACKET - { mkexp(Pexp_open(Fresh, mkrhs $1 1, mkexp(Pexp_array(List.rev $4)))) } - | mod_longident DOT LBRACKETBAR BARRBRACKET - { mkexp(Pexp_open(Fresh, mkrhs $1 1, mkexp(Pexp_array []))) } - | mod_longident DOT LBRACKETBAR expr_semi_list opt_semi error - { unclosed "[|" 3 "|]" 6 } - | LBRACKET expr_semi_list opt_semi RBRACKET - { reloc_exp (mktailexp (rhs_loc 4) (List.rev $2)) } - | LBRACKET expr_semi_list opt_semi error - { unclosed "[" 1 "]" 4 } - | mod_longident DOT LBRACKET expr_semi_list opt_semi RBRACKET - { let list_exp = reloc_exp (mktailexp (rhs_loc 6) (List.rev $4)) in - mkexp(Pexp_open(Fresh, mkrhs $1 1, list_exp)) } - | mod_longident DOT LBRACKET RBRACKET - { mkexp(Pexp_open(Fresh, mkrhs $1 1, - mkexp(Pexp_construct(mkrhs (Lident "[]") 1, None)))) } - | mod_longident DOT LBRACKET expr_semi_list opt_semi error - { unclosed "[" 3 "]" 6 } - | PREFIXOP simple_expr - { mkexp(Pexp_apply(mkoperator $1 1, [Nolabel,$2])) } - | BANG simple_expr - { mkexp(Pexp_apply(mkoperator "!" 1, [Nolabel,$2])) } - | NEW ext_attributes class_longident - { mkexp_attrs (Pexp_new(mkrhs $3 3)) $2 } - | LBRACELESS field_expr_list GREATERRBRACE - { mkexp (Pexp_override $2) } - | LBRACELESS field_expr_list error - { unclosed "{<" 1 ">}" 3 } - | LBRACELESS GREATERRBRACE - { mkexp (Pexp_override [])} - | mod_longident DOT LBRACELESS field_expr_list GREATERRBRACE - { mkexp(Pexp_open(Fresh, mkrhs $1 1, mkexp (Pexp_override $4)))} - | mod_longident DOT LBRACELESS GREATERRBRACE - { mkexp(Pexp_open(Fresh, mkrhs $1 1, mkexp (Pexp_override [])))} - | mod_longident DOT LBRACELESS field_expr_list error - { unclosed "{<" 3 ">}" 5 } - | simple_expr HASH label - { mkexp(Pexp_send($1, mkrhs $3 3)) } - | simple_expr HASHOP simple_expr - { mkinfix $1 $2 $3 } + { bigarray_get ~loc:$sloc $1 $4 } + | simple_expr DOT LBRACE expr error + { unclosed "{" $loc($3) "}" $loc($5) } + | simple_expr_attrs + { let desc, attrs = $1 in + mkexp_attrs ~loc:$sloc desc attrs } + | mkexp(simple_expr_) + { $1 } +; +%inline simple_expr_attrs: + | BEGIN ext = ext attrs = attributes e = seq_expr END + { e.pexp_desc, (ext, attrs @ e.pexp_attributes) } + | BEGIN ext_attributes END + { Pexp_construct (mkloc (Lident "()") (make_loc $sloc), None), $2 } + | BEGIN ext_attributes seq_expr error + { unclosed "begin" $loc($1) "end" $loc($4) } + | NEW ext_attributes mkrhs(class_longident) + { Pexp_new($3), $2 } | LPAREN MODULE ext_attributes module_expr RPAREN - { mkexp_attrs (Pexp_pack $4) $3 } + { Pexp_pack $4, $3 } | LPAREN MODULE ext_attributes module_expr COLON package_type RPAREN - { mkexp_attrs (Pexp_constraint (ghexp (Pexp_pack $4), - ghtyp (Ptyp_package $6))) - $3 } + { Pexp_constraint (ghexp ~loc:$sloc (Pexp_pack $4), $6), $3 } | LPAREN MODULE ext_attributes module_expr COLON error - { unclosed "(" 1 ")" 6 } - | mod_longident DOT LPAREN MODULE ext_attributes module_expr COLON - package_type RPAREN - { mkexp(Pexp_open(Fresh, mkrhs $1 1, - mkexp_attrs (Pexp_constraint (ghexp (Pexp_pack $6), - ghtyp (Ptyp_package $8))) - $5 )) } - | mod_longident DOT LPAREN MODULE ext_attributes module_expr COLON error - { unclosed "(" 3 ")" 8 } - | extension - { mkexp (Pexp_extension $1) } + { unclosed "(" $loc($1) ")" $loc($6) } ; -simple_labeled_expr_list: - labeled_simple_expr - { [$1] } - | simple_labeled_expr_list labeled_simple_expr - { $2 :: $1 } +%inline simple_expr_: + | mkrhs(val_longident) + { Pexp_ident ($1) } + | constant + { Pexp_constant $1 } + | mkrhs(constr_longident) %prec prec_constant_constructor + { Pexp_construct($1, None) } + | name_tag %prec prec_constant_constructor + { Pexp_variant($1, None) } + | op(PREFIXOP) simple_expr + { Pexp_apply($1, [Nolabel,$2]) } + | op(BANG {"!"}) simple_expr + { Pexp_apply($1, [Nolabel,$2]) } + | LBRACELESS object_expr_content GREATERRBRACE + { Pexp_override $2 } + | LBRACELESS object_expr_content error + { unclosed "{<" $loc($1) ">}" $loc($3) } + | LBRACELESS GREATERRBRACE + { Pexp_override [] } + | simple_expr DOT mkrhs(label_longident) + { Pexp_field($1, $3) } + | od=open_dot_declaration DOT LPAREN seq_expr RPAREN + { Pexp_open(od, $4) } + | od=open_dot_declaration DOT LBRACELESS object_expr_content GREATERRBRACE + { (* TODO: review the location of Pexp_override *) + Pexp_open(od, mkexp ~loc:$sloc (Pexp_override $4)) } + | mod_longident DOT LBRACELESS object_expr_content error + { unclosed "{<" $loc($3) ">}" $loc($5) } + | simple_expr HASH mkrhs(label) + { Pexp_send($1, $3) } + | simple_expr op(HASHOP) simple_expr + { mkinfix $1 $2 $3 } + | extension + { Pexp_extension $1 } + | od=open_dot_declaration DOT mkrhs(LPAREN RPAREN {Lident "()"}) + { (* TODO: review the location of Pexp_construct *) + Pexp_open(od, mkexp ~loc:$sloc (Pexp_construct($3, None))) } + | mod_longident DOT LPAREN seq_expr error + { unclosed "(" $loc($3) ")" $loc($5) } + | LBRACE record_expr_content RBRACE + { let (exten, fields) = $2 in + Pexp_record(fields, exten) } + | LBRACE record_expr_content error + { unclosed "{" $loc($1) "}" $loc($3) } + | od=open_dot_declaration DOT LBRACE record_expr_content RBRACE + { let (exten, fields) = $4 in + (* TODO: review the location of Pexp_construct *) + Pexp_open(od, mkexp ~loc:$sloc (Pexp_record(fields, exten))) } + | mod_longident DOT LBRACE record_expr_content error + { unclosed "{" $loc($3) "}" $loc($5) } + | LBRACKETBAR expr_semi_list BARRBRACKET + { Pexp_array($2) } + | LBRACKETBAR expr_semi_list error + { unclosed "[|" $loc($1) "|]" $loc($3) } + | LBRACKETBAR BARRBRACKET + { Pexp_array [] } + | od=open_dot_declaration DOT LBRACKETBAR expr_semi_list BARRBRACKET + { (* TODO: review the location of Pexp_array *) + Pexp_open(od, mkexp ~loc:$sloc (Pexp_array($4))) } + | od=open_dot_declaration DOT LBRACKETBAR BARRBRACKET + { (* TODO: review the location of Pexp_array *) + Pexp_open(od, mkexp ~loc:$sloc (Pexp_array [])) } + | mod_longident DOT + LBRACKETBAR expr_semi_list error + { unclosed "[|" $loc($3) "|]" $loc($5) } + | LBRACKET expr_semi_list RBRACKET + { fst (mktailexp $loc($3) $2) } + | LBRACKET expr_semi_list error + { unclosed "[" $loc($1) "]" $loc($3) } + | od=open_dot_declaration DOT LBRACKET expr_semi_list RBRACKET + { let list_exp = + (* TODO: review the location of list_exp *) + let tail_exp, _tail_loc = mktailexp $loc($5) $4 in + mkexp ~loc:$sloc tail_exp in + Pexp_open(od, list_exp) } + | od=open_dot_declaration DOT mkrhs(LBRACKET RBRACKET {Lident "[]"}) + { (* TODO: review the location of Pexp_construct *) + Pexp_open(od, mkexp ~loc:$sloc (Pexp_construct($3, None))) } + | mod_longident DOT + LBRACKET expr_semi_list error + { unclosed "[" $loc($3) "]" $loc($5) } + | od=open_dot_declaration DOT LPAREN MODULE ext_attributes module_expr COLON + package_type RPAREN + { (* TODO: review the location of Pexp_constraint *) + let modexp = + mkexp_attrs ~loc:$sloc + (Pexp_constraint (ghexp ~loc:$sloc (Pexp_pack $6), $8)) $5 in + Pexp_open(od, modexp) } + | mod_longident DOT + LPAREN MODULE ext_attributes module_expr COLON error + { unclosed "(" $loc($3) ")" $loc($8) } ; labeled_simple_expr: simple_expr %prec below_HASH { (Nolabel, $1) } - | label_expr - { $1 } -; -label_expr: - LABEL simple_expr %prec below_HASH + | LABEL simple_expr %prec below_HASH { (Labelled $1, $2) } - | TILDE label_ident - { (Labelled (fst $2), snd $2) } - | QUESTION label_ident - { (Optional (fst $2), snd $2) } + | TILDE label = LIDENT + { let loc = $loc(label) in + (Labelled label, mkexpvar ~loc label) } + | QUESTION label = LIDENT + { let loc = $loc(label) in + (Optional label, mkexpvar ~loc label) } | OPTLABEL simple_expr %prec below_HASH { (Optional $1, $2) } ; -label_ident: - LIDENT { ($1, mkexp(Pexp_ident(mkrhs (Lident $1) 1))) } +%inline lident_list: + xs = mkrhs(LIDENT)+ + { xs } ; -lident_list: - LIDENT { [mkrhs $1 1] } - | LIDENT lident_list { mkrhs $1 1 :: $2 } +%inline let_ident: + val_ident { mkpatvar ~loc:$sloc $1 } ; let_binding_body: - val_ident strict_binding - { (mkpatvar $1 1, $2) } - | val_ident type_constraint EQUAL seq_expr - { let v = mkpatvar $1 1 in (* PR#7344 *) + let_ident strict_binding + { ($1, $2) } + | let_ident type_constraint EQUAL seq_expr + { let v = $1 in (* PR#7344 *) let t = match $2 with Some t, None -> t | _, Some t -> t | _ -> assert false in - (ghpat(Ppat_constraint(v, ghtyp(Ptyp_poly([],t)))), - mkexp_constraint $4 $2) } - | val_ident COLON typevar_list DOT core_type EQUAL seq_expr - { (ghpat(Ppat_constraint(mkpatvar $1 1, - ghtyp(Ptyp_poly(List.rev $3,$5)))), + let loc = Location.(t.ptyp_loc.loc_start, t.ptyp_loc.loc_end) in + let typ = ghtyp ~loc (Ptyp_poly([],t)) in + let patloc = ($startpos($1), $endpos($2)) in + (ghpat ~loc:patloc (Ppat_constraint(v, typ)), + mkexp_constraint ~loc:$sloc $4 $2) } + | let_ident COLON typevar_list DOT core_type EQUAL seq_expr + (* TODO: could replace [typevar_list DOT core_type] + with [mktyp(poly(core_type))] + and simplify the semantic action? *) + { let typloc = ($startpos($3), $endpos($5)) in + let patloc = ($startpos($1), $endpos($5)) in + (ghpat ~loc:patloc + (Ppat_constraint($1, ghtyp ~loc:typloc (Ptyp_poly($3,$5)))), $7) } - | val_ident COLON TYPE lident_list DOT core_type EQUAL seq_expr - { let exp, poly = wrap_type_annotation $4 $6 $8 in - (ghpat(Ppat_constraint(mkpatvar $1 1, poly)), exp) } + | let_ident COLON TYPE lident_list DOT core_type EQUAL seq_expr + { let exp, poly = + wrap_type_annotation ~loc:$sloc $4 $6 $8 in + let loc = ($startpos($1), $endpos($6)) in + (ghpat ~loc (Ppat_constraint($1, poly)), exp) } | pattern_no_exn EQUAL seq_expr { ($1, $3) } | simple_pattern_not_ident COLON core_type EQUAL seq_expr - { (ghpat(Ppat_constraint($1, $3)), $5) } -; -let_bindings: - let_binding { $1 } - | let_bindings and_let_binding { addlb $1 $2 } -; -let_binding: - LET ext_attributes rec_flag let_binding_body post_item_attributes - { let (ext, attr) = $2 in - mklbs ext $3 (mklb true $4 (attr@$5)) } + { let loc = ($startpos($1), $endpos($3)) in + (ghpat ~loc (Ppat_constraint($1, $3)), $5) } +; +(* The formal parameter EXT can be instantiated with ext or no_ext + so as to indicate whether an extension is allowed or disallowed. *) +let_bindings(EXT): + let_binding(EXT) { $1 } + | let_bindings(EXT) and_let_binding { addlb $1 $2 } +; +%inline let_binding(EXT): + LET + ext = EXT + attrs1 = attributes + rec_flag = rec_flag + body = let_binding_body + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + mklbs ~loc:$sloc ext rec_flag (mklb ~loc:$sloc true body attrs) + } ; and_let_binding: - AND attributes let_binding_body post_item_attributes - { mklb false $3 ($2@$4) } + AND + attrs1 = attributes + body = let_binding_body + attrs2 = post_item_attributes + { + let attrs = attrs1 @ attrs2 in + mklb ~loc:$sloc false body attrs + } +; +letop_binding_body: + pat = let_ident exp = strict_binding + { (pat, exp) } + | pat = simple_pattern COLON typ = core_type EQUAL exp = seq_expr + { let loc = ($startpos(pat), $endpos(typ)) in + (ghpat ~loc (Ppat_constraint(pat, typ)), exp) } + | pat = pattern_no_exn EQUAL exp = seq_expr + { (pat, exp) } +; +letop_bindings: + body = letop_binding_body + { let let_pat, let_exp = body in + let_pat, let_exp, [] } + | bindings = letop_bindings pbop_op = mkrhs(ANDOP) body = let_binding_body + { let let_pat, let_exp, rev_ands = bindings in + let pbop_pat, pbop_exp = body in + let pbop_loc = make_loc $sloc in + let and_ = {pbop_op; pbop_pat; pbop_exp; pbop_loc} in + let_pat, let_exp, and_ :: rev_ands } ; fun_binding: strict_binding { $1 } | type_constraint EQUAL seq_expr - { mkexp_constraint $3 $1 } + { mkexp_constraint ~loc:$sloc $3 $1 } ; strict_binding: EQUAL seq_expr { $2 } | labeled_simple_pattern fun_binding - { let (l, o, p) = $1 in ghexp(Pexp_fun(l, o, p, $2)) } + { let (l, o, p) = $1 in ghexp ~loc:$sloc (Pexp_fun(l, o, p, $2)) } | LPAREN TYPE lident_list RPAREN fun_binding - { mk_newtypes $3 $5 } + { mk_newtypes ~loc:$sloc $3 $5 } ; -match_cases: - match_case { [$1] } - | match_cases BAR match_case { $3 :: $1 } +%inline match_cases: + xs = preceded_or_separated_nonempty_llist(BAR, match_case) + { xs } ; match_case: pattern MINUSGREATER seq_expr @@ -1684,54 +2451,66 @@ match_case: | pattern WHEN seq_expr MINUSGREATER seq_expr { Exp.case $1 ~guard:$3 $5 } | pattern MINUSGREATER DOT - { Exp.case $1 (Exp.unreachable ~loc:(rhs_loc 3) ())} + { Exp.case $1 (Exp.unreachable ~loc:(make_loc $loc($3)) ()) } ; fun_def: MINUSGREATER seq_expr { $2 } - | COLON simple_core_type MINUSGREATER seq_expr - { mkexp (Pexp_constraint ($4, $2)) } + | mkexp(COLON atomic_type MINUSGREATER seq_expr + { Pexp_constraint ($4, $2) }) + { $1 } /* Cf #5939: we used to accept (fun p when e0 -> e) */ | labeled_simple_pattern fun_def { let (l,o,p) = $1 in - ghexp(Pexp_fun(l, o, p, $2)) + ghexp ~loc:$sloc (Pexp_fun(l, o, p, $2)) } | LPAREN TYPE lident_list RPAREN fun_def - { mk_newtypes $3 $5 } -; -expr_comma_list: - expr_comma_list COMMA expr { $3 :: $1 } - | expr COMMA expr { [$3; $1] } -; -record_expr: - simple_expr WITH lbl_expr_list { (Some $1, $3) } - | lbl_expr_list { (None, $1) } -; -lbl_expr_list: - lbl_expr { [$1] } - | lbl_expr SEMI lbl_expr_list { $1 :: $3 } - | lbl_expr SEMI { [$1] } -; -lbl_expr: - label_longident opt_type_constraint EQUAL expr - { (mkrhs $1 1, mkexp_opt_constraint $4 $2) } - | label_longident opt_type_constraint - { (mkrhs $1 1, mkexp_opt_constraint (exp_of_label $1 1) $2) } -; -field_expr_list: - field_expr opt_semi { [$1] } - | field_expr SEMI field_expr_list { $1 :: $3 } -; -field_expr: - label EQUAL expr - { (mkrhs $1 1, $3) } - | label - { (mkrhs $1 1, exp_of_label (Lident $1) 1) } + { mk_newtypes ~loc:$sloc $3 $5 } +; +%inline expr_comma_list: + es = separated_nontrivial_llist(COMMA, expr) + { es } +; +record_expr_content: + eo = ioption(terminated(simple_expr, WITH)) + fields = separated_or_terminated_nonempty_list(SEMI, record_expr_field) + { eo, fields } +; +%inline record_expr_field: + | label = mkrhs(label_longident) + c = type_constraint? + eo = preceded(EQUAL, expr)? + { let e = + match eo with + | None -> + (* No pattern; this is a pun. Desugar it. *) + exp_of_longident ~loc:$sloc label + | Some e -> + e + in + label, mkexp_opt_constraint ~loc:$sloc e c } +; +%inline object_expr_content: + xs = separated_or_terminated_nonempty_list(SEMI, object_expr_field) + { xs } +; +%inline object_expr_field: + label = mkrhs(label) + oe = preceded(EQUAL, expr)? + { let e = + match oe with + | None -> + (* No expression; this is a pun. Desugar it. *) + exp_of_label ~loc:$sloc label + | Some e -> + e + in + label, e } ; -expr_semi_list: - expr { [$1] } - | expr_semi_list SEMI expr { $3 :: $1 } +%inline expr_semi_list: + es = separated_or_terminated_nonempty_list(SEMI, expr) + { es } ; type_constraint: COLON core_type { (Some $2, None) } @@ -1740,340 +2519,448 @@ type_constraint: | COLON error { syntax_error() } | COLONGREATER error { syntax_error() } ; -opt_type_constraint: - type_constraint { Some $1 } - | /* empty */ { None } -; /* Patterns */ +(* Whereas [pattern] is an arbitrary pattern, [pattern_no_exn] is a pattern + that does not begin with the [EXCEPTION] keyword. Thus, [pattern_no_exn] + is the intersection of the context-free language [pattern] with the + regular language [^EXCEPTION .*]. + + Ideally, we would like to use [pattern] everywhere and check in a later + phase that EXCEPTION patterns are used only where they are allowed (there + is code in typing/typecore.ml to this end). Unfortunately, in the + definition of [let_binding_body], we cannot allow [pattern]. That would + create a shift/reduce conflict: upon seeing LET EXCEPTION ..., the parser + wouldn't know whether this is the beginning of a LET EXCEPTION construct or + the beginning of a LET construct whose pattern happens to begin with + EXCEPTION. The conflict is avoided there by using [pattern_no_exn] in the + definition of [let_binding_body]. + + In order to avoid duplication between the definitions of [pattern] and + [pattern_no_exn], we create a parameterized definition [pattern_(self)] + and instantiate it twice. *) + pattern: - | pattern AS val_ident - { mkpat(Ppat_alias($1, mkrhs $3 3)) } - | pattern AS error - { expecting 3 "identifier" } - | pattern_comma_list %prec below_COMMA - { mkpat(Ppat_tuple(List.rev $1)) } - | pattern COLONCOLON pattern - { mkpat_cons (rhs_loc 2) (ghpat(Ppat_tuple[$1;$3])) (symbol_rloc()) } - | pattern COLONCOLON error - { expecting 3 "pattern" } - | pattern BAR pattern - { mkpat(Ppat_or($1, $3)) } - | pattern BAR error - { expecting 3 "pattern" } + pattern_(pattern) + { $1 } | EXCEPTION ext_attributes pattern %prec prec_constr_appl - { mkpat_attrs (Ppat_exception $3) $2} - | pattern attribute - { Pat.attr $1 $2 } - | pattern_gen { $1 } + { mkpat_attrs ~loc:$sloc (Ppat_exception $3) $2} ; + pattern_no_exn: - | pattern_no_exn AS val_ident - { mkpat(Ppat_alias($1, mkrhs $3 3)) } - | pattern_no_exn AS error - { expecting 3 "identifier" } - | pattern_no_exn_comma_list %prec below_COMMA - { mkpat(Ppat_tuple(List.rev $1)) } - | pattern_no_exn COLONCOLON pattern - { mkpat_cons (rhs_loc 2) (ghpat(Ppat_tuple[$1;$3])) (symbol_rloc()) } - | pattern_no_exn COLONCOLON error - { expecting 3 "pattern" } - | pattern_no_exn BAR pattern - { mkpat(Ppat_or($1, $3)) } - | pattern_no_exn BAR error - { expecting 3 "pattern" } - | pattern_no_exn attribute + pattern_(pattern_no_exn) + { $1 } +; + +%inline pattern_(self): + | self COLONCOLON pattern + { mkpat_cons ~loc:$sloc $loc($2) (ghpat ~loc:$sloc (Ppat_tuple[$1;$3])) } + | self attribute { Pat.attr $1 $2 } - | pattern_gen { $1 } + | pattern_gen + { $1 } + | mkpat( + self AS mkrhs(val_ident) + { Ppat_alias($1, $3) } + | self AS error + { expecting $loc($3) "identifier" } + | pattern_comma_list(self) %prec below_COMMA + { Ppat_tuple(List.rev $1) } + | self COLONCOLON error + { expecting $loc($3) "pattern" } + | self BAR pattern + { Ppat_or($1, $3) } + | self BAR error + { expecting $loc($3) "pattern" } + ) { $1 } ; + pattern_gen: simple_pattern { $1 } - | constr_longident pattern %prec prec_constr_appl - { mkpat(Ppat_construct(mkrhs $1 1, Some $2)) } - | name_tag pattern %prec prec_constr_appl - { mkpat(Ppat_variant($1, Some $2)) } + | mkpat( + mkrhs(constr_longident) pattern %prec prec_constr_appl + { Ppat_construct($1, Some $2) } + | name_tag pattern %prec prec_constr_appl + { Ppat_variant($1, Some $2) } + ) { $1 } | LAZY ext_attributes simple_pattern - { mkpat_attrs (Ppat_lazy $3) $2} + { mkpat_attrs ~loc:$sloc (Ppat_lazy $3) $2} ; simple_pattern: - val_ident %prec below_EQUAL - { mkpat(Ppat_var (mkrhs $1 1)) } + mkpat(mkrhs(val_ident) %prec below_EQUAL + { Ppat_var ($1) }) + { $1 } | simple_pattern_not_ident { $1 } ; + simple_pattern_not_ident: + | LPAREN pattern RPAREN + { reloc_pat ~loc:$sloc $2 } + | simple_delimited_pattern + { $1 } + | LPAREN MODULE ext_attributes mkrhs(UIDENT) RPAREN + { mkpat_attrs ~loc:$sloc (Ppat_unpack $4) $3 } + | LPAREN MODULE ext_attributes mkrhs(UIDENT) COLON package_type RPAREN + { mkpat_attrs ~loc:$sloc + (Ppat_constraint(mkpat ~loc:$sloc (Ppat_unpack $4), $6)) + $3 } + | mkpat(simple_pattern_not_ident_) + { $1 } +; +%inline simple_pattern_not_ident_: | UNDERSCORE - { mkpat(Ppat_any) } + { Ppat_any } | signed_constant - { mkpat(Ppat_constant $1) } + { Ppat_constant $1 } | signed_constant DOTDOT signed_constant - { mkpat(Ppat_interval ($1, $3)) } - | constr_longident - { mkpat(Ppat_construct(mkrhs $1 1, None)) } + { Ppat_interval ($1, $3) } + | mkrhs(constr_longident) + { Ppat_construct($1, None) } | name_tag - { mkpat(Ppat_variant($1, None)) } - | HASH type_longident - { mkpat(Ppat_type (mkrhs $2 2)) } - | simple_delimited_pattern - { $1 } - | mod_longident DOT simple_delimited_pattern - { mkpat @@ Ppat_open(mkrhs $1 1, $3) } - | mod_longident DOT LBRACKET RBRACKET - { mkpat @@ Ppat_open(mkrhs $1 1, mkpat @@ - Ppat_construct ( mkrhs (Lident "[]") 4, None)) } - | mod_longident DOT LPAREN RPAREN - { mkpat @@ Ppat_open( mkrhs $1 1, mkpat @@ - Ppat_construct ( mkrhs (Lident "()") 4, None) ) } - | mod_longident DOT LPAREN pattern RPAREN - { mkpat @@ Ppat_open (mkrhs $1 1, $4)} + { Ppat_variant($1, None) } + | HASH mkrhs(type_longident) + { Ppat_type ($2) } + | mkrhs(mod_longident) DOT simple_delimited_pattern + { Ppat_open($1, $3) } + | mkrhs(mod_longident) DOT mkrhs(LBRACKET RBRACKET {Lident "[]"}) + { Ppat_open($1, mkpat ~loc:$sloc (Ppat_construct($3, None))) } + | mkrhs(mod_longident) DOT mkrhs(LPAREN RPAREN {Lident "()"}) + { Ppat_open($1, mkpat ~loc:$sloc (Ppat_construct($3, None))) } + | mkrhs(mod_longident) DOT LPAREN pattern RPAREN + { Ppat_open ($1, $4) } | mod_longident DOT LPAREN pattern error - {unclosed "(" 3 ")" 5 } + { unclosed "(" $loc($3) ")" $loc($5) } | mod_longident DOT LPAREN error - { expecting 4 "pattern" } - | LPAREN pattern RPAREN - { reloc_pat $2 } + { expecting $loc($4) "pattern" } | LPAREN pattern error - { unclosed "(" 1 ")" 3 } + { unclosed "(" $loc($1) ")" $loc($3) } | LPAREN pattern COLON core_type RPAREN - { mkpat(Ppat_constraint($2, $4)) } + { Ppat_constraint($2, $4) } | LPAREN pattern COLON core_type error - { unclosed "(" 1 ")" 5 } + { unclosed "(" $loc($1) ")" $loc($5) } | LPAREN pattern COLON error - { expecting 4 "type" } - | LPAREN MODULE ext_attributes UIDENT RPAREN - { mkpat_attrs (Ppat_unpack (mkrhs $4 4)) $3 } - | LPAREN MODULE ext_attributes UIDENT COLON package_type RPAREN - { mkpat_attrs - (Ppat_constraint(mkpat(Ppat_unpack (mkrhs $4 4)), - ghtyp(Ptyp_package $6))) - $3 } - | LPAREN MODULE ext_attributes UIDENT COLON package_type error - { unclosed "(" 1 ")" 7 } + { expecting $loc($4) "type" } + | LPAREN MODULE ext_attributes UIDENT COLON package_type + error + { unclosed "(" $loc($1) ")" $loc($7) } | extension - { mkpat(Ppat_extension $1) } + { Ppat_extension $1 } ; simple_delimited_pattern: - | LBRACE lbl_pattern_list RBRACE - { let (fields, closed) = $2 in mkpat(Ppat_record(fields, closed)) } - | LBRACE lbl_pattern_list error - { unclosed "{" 1 "}" 3 } - | LBRACKET pattern_semi_list opt_semi RBRACKET - { reloc_pat (mktailpat (rhs_loc 4) (List.rev $2)) } - | LBRACKET pattern_semi_list opt_semi error - { unclosed "[" 1 "]" 4 } - | LBRACKETBAR pattern_semi_list opt_semi BARRBRACKET - { mkpat(Ppat_array(List.rev $2)) } - | LBRACKETBAR BARRBRACKET - { mkpat(Ppat_array []) } - | LBRACKETBAR pattern_semi_list opt_semi error - { unclosed "[|" 1 "|]" 4 } - -pattern_comma_list: - pattern_comma_list COMMA pattern { $3 :: $1 } - | pattern COMMA pattern { [$3; $1] } - | pattern COMMA error { expecting 3 "pattern" } -; -pattern_no_exn_comma_list: - pattern_no_exn_comma_list COMMA pattern { $3 :: $1 } - | pattern_no_exn COMMA pattern { [$3; $1] } - | pattern_no_exn COMMA error { expecting 3 "pattern" } -; -pattern_semi_list: - pattern { [$1] } - | pattern_semi_list SEMI pattern { $3 :: $1 } -; -lbl_pattern_list: - lbl_pattern { [$1], Closed } - | lbl_pattern SEMI { [$1], Closed } - | lbl_pattern SEMI UNDERSCORE opt_semi { [$1], Open } - | lbl_pattern SEMI lbl_pattern_list - { let (fields, closed) = $3 in $1 :: fields, closed } -; -lbl_pattern: - label_longident opt_pattern_type_constraint EQUAL pattern - { (mkrhs $1 1, mkpat_opt_constraint $4 $2) } - | label_longident opt_pattern_type_constraint - { (mkrhs $1 1, mkpat_opt_constraint (pat_of_label $1 1) $2) } -; -opt_pattern_type_constraint: - COLON core_type { Some $2 } - | /* empty */ { None } + mkpat( + LBRACE record_pat_content RBRACE + { let (fields, closed) = $2 in + Ppat_record(fields, closed) } + | LBRACE record_pat_content error + { unclosed "{" $loc($1) "}" $loc($3) } + | LBRACKET pattern_semi_list RBRACKET + { fst (mktailpat $loc($3) $2) } + | LBRACKET pattern_semi_list error + { unclosed "[" $loc($1) "]" $loc($3) } + | LBRACKETBAR pattern_semi_list BARRBRACKET + { Ppat_array $2 } + | LBRACKETBAR BARRBRACKET + { Ppat_array [] } + | LBRACKETBAR pattern_semi_list error + { unclosed "[|" $loc($1) "|]" $loc($3) } + ) { $1 } + +pattern_comma_list(self): + pattern_comma_list(self) COMMA pattern { $3 :: $1 } + | self COMMA pattern { [$3; $1] } + | self COMMA error { expecting $loc($3) "pattern" } +; +%inline pattern_semi_list: + ps = separated_or_terminated_nonempty_list(SEMI, pattern) + { ps } +; +(* A label-pattern list is a nonempty list of label-pattern pairs, optionally + followed with an UNDERSCORE, separated-or-terminated with semicolons. *) +%inline record_pat_content: + listx(SEMI, record_pat_field, UNDERSCORE) + { let fields, closed = $1 in + let closed = match closed with Some () -> Open | None -> Closed in + fields, closed } +; +%inline record_pat_field: + label = mkrhs(label_longident) + octy = preceded(COLON, core_type)? + opat = preceded(EQUAL, pattern)? + { let pat = + match opat with + | None -> + (* No pattern; this is a pun. Desugar it. *) + pat_of_label ~loc:$sloc label + | Some pat -> + pat + in + label, mkpat_opt_constraint ~loc:$sloc pat octy + } ; /* Value descriptions */ value_description: - VAL ext_attributes val_ident COLON core_type post_item_attributes - { let (ext, attrs) = $2 in - Val.mk (mkrhs $3 3) $5 ~attrs:(attrs@$6) - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) - , ext } + VAL + ext = ext + attrs1 = attributes + id = mkrhs(val_ident) + COLON + ty = core_type + attrs2 = post_item_attributes + { let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + Val.mk id ty ~attrs ~loc ~docs, + ext } ; /* Primitive declarations */ -primitive_declaration_body: - STRING { [fst $1] } - | STRING primitive_declaration_body { fst $1 :: $2 } -; primitive_declaration: - EXTERNAL ext_attributes val_ident COLON core_type EQUAL - primitive_declaration_body post_item_attributes - { let (ext, attrs) = $2 in - Val.mk (mkrhs $3 3) $5 ~prim:$7 ~attrs:(attrs@$8) - ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) - , ext } -; - -/* Type declarations */ - -type_declarations: - type_declaration - { let (nonrec_flag, ty, ext) = $1 in (nonrec_flag, [ty], ext) } - | type_declarations and_type_declaration - { let (nonrec_flag, tys, ext) = $1 in (nonrec_flag, $2 :: tys, ext) } -; - -type_declaration: - TYPE ext_attributes nonrec_flag optional_type_parameters LIDENT - type_kind constraints post_item_attributes - { let (kind, priv, manifest) = $6 in - let (ext, attrs) = $2 in - let ty = - Type.mk (mkrhs $5 5) ~params:$4 ~cstrs:(List.rev $7) ~kind - ~priv ?manifest ~attrs:(attrs@$8) - ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) - in - ($3, ty, ext) } -; -and_type_declaration: - AND attributes optional_type_parameters LIDENT type_kind constraints - post_item_attributes - { let (kind, priv, manifest) = $5 in - Type.mk (mkrhs $4 4) ~params:$3 ~cstrs:(List.rev $6) - ~kind ~priv ?manifest ~attrs:($2@$7) ~loc:(symbol_rloc ()) - ~text:(symbol_text ()) ~docs:(symbol_docs ()) } -; -constraints: - constraints CONSTRAINT constrain { $3 :: $1 } - | /* empty */ { [] } + EXTERNAL + ext = ext + attrs1 = attributes + id = mkrhs(val_ident) + COLON + ty = core_type + EQUAL + prim = raw_string+ + attrs2 = post_item_attributes + { let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + Val.mk id ty ~prim ~attrs ~loc ~docs, + ext } +; + +(* Type declarations and type substitutions. *) + +(* Type declarations [type t = u] and type substitutions [type t := u] are very + similar, so we view them as instances of [generic_type_declarations]. In the + case of a type declaration, the use of [nonrec_flag] means that [NONREC] may + be absent or present, whereas in the case of a type substitution, the use of + [no_nonrec_flag] means that [NONREC] must be absent. The use of [type_kind] + versus [type_subst_kind] means that in the first case, we expect an [EQUAL] + sign, whereas in the second case, we expect [COLONEQUAL]. *) + +%inline type_declarations: + generic_type_declarations(nonrec_flag, type_kind) + { $1 } +; + +%inline type_subst_declarations: + generic_type_declarations(no_nonrec_flag, type_subst_kind) + { $1 } +; + +(* A set of type declarations or substitutions begins with a + [generic_type_declaration] and continues with a possibly empty list of + [generic_and_type_declaration]s. *) + +%inline generic_type_declarations(flag, kind): + xlist( + generic_type_declaration(flag, kind), + generic_and_type_declaration(kind) + ) + { $1 } +; + +(* [generic_type_declaration] and [generic_and_type_declaration] look similar, + but are in reality different enough that it is difficult to share anything + between them. *) + +generic_type_declaration(flag, kind): + TYPE + ext = ext + attrs1 = attributes + flag = flag + params = type_parameters + id = mkrhs(LIDENT) + kind_priv_manifest = kind + cstrs = constraints + attrs2 = post_item_attributes + { + let (kind, priv, manifest) = kind_priv_manifest in + let docs = symbol_docs $sloc in + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + (flag, ext), + Type.mk id ~params ~cstrs ~kind ~priv ?manifest ~attrs ~loc ~docs + } +; +%inline generic_and_type_declaration(kind): + AND + attrs1 = attributes + params = type_parameters + id = mkrhs(LIDENT) + kind_priv_manifest = kind + cstrs = constraints + attrs2 = post_item_attributes + { + let (kind, priv, manifest) = kind_priv_manifest in + let docs = symbol_docs $sloc in + let attrs = attrs1 @ attrs2 in + let loc = make_loc $sloc in + let text = symbol_text $symbolstartpos in + Type.mk id ~params ~cstrs ~kind ~priv ?manifest ~attrs ~loc ~docs ~text + } +; +%inline constraints: + llist(preceded(CONSTRAINT, constrain)) + { $1 } +; +(* Lots of %inline expansion are required for [nonempty_type_kind] to be + LR(1). At the cost of some manual expansion, it would be possible to give a + definition that leads to a smaller grammar (after expansion) and therefore + a smaller automaton. *) +nonempty_type_kind: + | priv = inline_private_flag + ty = core_type + { (Ptype_abstract, priv, Some ty) } + | oty = type_synonym + priv = inline_private_flag + cs = constructor_declarations + { (Ptype_variant cs, priv, oty) } + | oty = type_synonym + priv = inline_private_flag + DOTDOT + { (Ptype_open, priv, oty) } + | oty = type_synonym + priv = inline_private_flag + LBRACE ls = label_declarations RBRACE + { (Ptype_record ls, priv, oty) } +; +%inline type_synonym: + ioption(terminated(core_type, EQUAL)) + { $1 } ; type_kind: /*empty*/ { (Ptype_abstract, Public, None) } - | EQUAL core_type - { (Ptype_abstract, Public, Some $2) } - | EQUAL PRIVATE core_type - { (Ptype_abstract, Private, Some $3) } - | EQUAL constructor_declarations - { (Ptype_variant(List.rev $2), Public, None) } - | EQUAL PRIVATE constructor_declarations - { (Ptype_variant(List.rev $3), Private, None) } - | EQUAL DOTDOT - { (Ptype_open, Public, None) } - | EQUAL PRIVATE DOTDOT - { (Ptype_open, Private, None) } - | EQUAL private_flag LBRACE label_declarations RBRACE - { (Ptype_record $4, $2, None) } - | EQUAL core_type EQUAL private_flag constructor_declarations - { (Ptype_variant(List.rev $5), $4, Some $2) } - | EQUAL core_type EQUAL private_flag DOTDOT - { (Ptype_open, $4, Some $2) } - | EQUAL core_type EQUAL private_flag LBRACE label_declarations RBRACE - { (Ptype_record $6, $4, Some $2) } -; -optional_type_parameters: - /*empty*/ { [] } - | optional_type_parameter { [$1] } - | LPAREN optional_type_parameter_list RPAREN { List.rev $2 } -; -optional_type_parameter: - type_variance optional_type_variable { $2, $1 } -; -optional_type_parameter_list: - optional_type_parameter { [$1] } - | optional_type_parameter_list COMMA optional_type_parameter { $3 :: $1 } -; -optional_type_variable: - QUOTE ident { mktyp(Ptyp_var $2) } - | UNDERSCORE { mktyp(Ptyp_any) } + | EQUAL nonempty_type_kind + { $2 } +; +%inline type_subst_kind: + COLONEQUAL nonempty_type_kind + { $2 } +; +type_parameters: + /* empty */ + { [] } + | p = type_parameter + { [p] } + | LPAREN ps = separated_nonempty_llist(COMMA, type_parameter) RPAREN + { ps } ; - - type_parameter: - type_variance type_variable { $2, $1 } + type_variance type_variable { $2, $1 } ; +type_variable: + mktyp( + QUOTE tyvar = ident + { Ptyp_var tyvar } + | UNDERSCORE + { Ptyp_any } + ) { $1 } +; + type_variance: /* empty */ { Invariant } | PLUS { Covariant } | MINUS { Contravariant } ; -type_variable: - QUOTE ident { mktyp(Ptyp_var $2) } -; -type_parameter_list: - type_parameter { [$1] } - | type_parameter_list COMMA type_parameter { $3 :: $1 } -; + +(* A sequence of constructor declarations is either a single BAR, which + means that the list is empty, or a nonempty BAR-separated list of + declarations, with an optional leading BAR. *) constructor_declarations: - | BAR { [ ] } - | constructor_declaration { [$1] } - | bar_constructor_declaration { [$1] } - | constructor_declarations bar_constructor_declaration { $2 :: $1 } -; -constructor_declaration: - | constr_ident generalized_constructor_arguments attributes - { - let args,res = $2 in - Type.constructor (mkrhs $1 1) ~args ?res ~attrs:$3 - ~loc:(symbol_rloc()) ~info:(symbol_info ()) - } -; -bar_constructor_declaration: - | BAR constr_ident generalized_constructor_arguments attributes - { - let args,res = $3 in - Type.constructor (mkrhs $2 2) ~args ?res ~attrs:$4 - ~loc:(symbol_rloc()) ~info:(symbol_info ()) - } + | BAR + { [] } + | cs = bar_llist(constructor_declaration) + { cs } +; +(* A constructor declaration begins with an opening symbol, which can + be either epsilon or BAR. Note that this opening symbol is included + in the footprint $sloc. *) +(* Because [constructor_declaration] and [extension_constructor_declaration] + are identical except for their semantic actions, we introduce the symbol + [generic_constructor_declaration], whose semantic action is neutral -- it + merely returns a tuple. *) +generic_constructor_declaration(opening): + opening + cid = mkrhs(constr_ident) + args_res = generalized_constructor_arguments + attrs = attributes + { + let args, res = args_res in + let info = symbol_info $endpos in + let loc = make_loc $sloc in + cid, args, res, attrs, loc, info + } +; +%inline constructor_declaration(opening): + d = generic_constructor_declaration(opening) + { + let cid, args, res, attrs, loc, info = d in + Type.constructor cid ~args ?res ~attrs ~loc ~info + } ; str_exception_declaration: - | sig_exception_declaration { $1 } - | EXCEPTION ext_attributes constr_ident EQUAL constr_longident attributes - post_item_attributes - { let (ext,attrs) = $2 in - Te.rebind (mkrhs $3 3) (mkrhs $5 5) ~attrs:(attrs @ $6 @ $7) - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) - , ext } + sig_exception_declaration + { $1 } +| EXCEPTION + ext = ext + attrs1 = attributes + id = mkrhs(constr_ident) + EQUAL + lid = mkrhs(constr_longident) + attrs2 = attributes + attrs = post_item_attributes + { let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + Te.mk_exception ~attrs + (Te.rebind id lid ~attrs:(attrs1 @ attrs2) ~loc ~docs) + , ext } ; sig_exception_declaration: - | EXCEPTION ext_attributes constr_ident generalized_constructor_arguments - attributes post_item_attributes - { let args, res = $4 in - let (ext,attrs) = $2 in - Te.decl (mkrhs $3 3) ~args ?res ~attrs:(attrs @ $5 @ $6) - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) - , ext } -; -let_exception_declaration: - constr_ident generalized_constructor_arguments attributes + EXCEPTION + ext = ext + attrs1 = attributes + id = mkrhs(constr_ident) + args_res = generalized_constructor_arguments + attrs2 = attributes + attrs = post_item_attributes + { let args, res = args_res in + let loc = make_loc $sloc in + let docs = symbol_docs $sloc in + Te.mk_exception ~attrs + (Te.decl id ~args ?res ~attrs:(attrs1 @ attrs2) ~loc ~docs) + , ext } +; +%inline let_exception_declaration: + mkrhs(constr_ident) generalized_constructor_arguments attributes { let args, res = $2 in - Te.decl (mkrhs $1 1) ~args ?res ~attrs:$3 ~loc:(symbol_rloc()) } + Te.decl $1 ~args ?res ~attrs:$3 ~loc:(make_loc $sloc) } ; generalized_constructor_arguments: /*empty*/ { (Pcstr_tuple [],None) } | OF constructor_arguments { ($2,None) } - | COLON constructor_arguments MINUSGREATER simple_core_type + | COLON constructor_arguments MINUSGREATER atomic_type %prec below_HASH { ($2,Some $4) } - | COLON simple_core_type + | COLON atomic_type %prec below_HASH { (Pcstr_tuple [],Some $2) } ; constructor_arguments: - | core_type_list { Pcstr_tuple (List.rev $1) } - | LBRACE label_declarations RBRACE { Pcstr_record $2 } + | tys = inline_separated_nonempty_llist(STAR, atomic_type) + %prec below_HASH + { Pcstr_tuple tys } + | LBRACE label_declarations RBRACE + { Pcstr_record $2 } ; label_declarations: label_declaration { [$1] } @@ -2081,114 +2968,98 @@ label_declarations: | label_declaration_semi label_declarations { $1 :: $2 } ; label_declaration: - mutable_flag label COLON poly_type_no_attr attributes - { - Type.field (mkrhs $2 2) $4 ~mut:$1 ~attrs:$5 - ~loc:(symbol_rloc()) ~info:(symbol_info ()) - } + mutable_flag mkrhs(label) COLON poly_type_no_attr attributes + { let info = symbol_info $endpos in + Type.field $2 $4 ~mut:$1 ~attrs:$5 ~loc:(make_loc $sloc) ~info } ; label_declaration_semi: - mutable_flag label COLON poly_type_no_attr attributes SEMI attributes - { - let info = - match rhs_info 5 with - | Some _ as info_before_semi -> info_before_semi - | None -> symbol_info () + mutable_flag mkrhs(label) COLON poly_type_no_attr attributes SEMI attributes + { let info = + match rhs_info $endpos($5) with + | Some _ as info_before_semi -> info_before_semi + | None -> symbol_info $endpos in - Type.field (mkrhs $2 2) $4 ~mut:$1 ~attrs:($5 @ $7) - ~loc:(symbol_rloc()) ~info - } + Type.field $2 $4 ~mut:$1 ~attrs:($5 @ $7) ~loc:(make_loc $sloc) ~info } ; /* Type Extensions */ -str_type_extension: - TYPE ext_attributes nonrec_flag optional_type_parameters type_longident - PLUSEQ private_flag str_extension_constructors post_item_attributes - { let (ext, attrs) = $2 in - if $3 <> Recursive then not_expecting 3 "nonrec flag"; - Te.mk (mkrhs $5 5) (List.rev $8) ~params:$4 ~priv:$7 - ~attrs:(attrs@$9) ~docs:(symbol_docs ()) - , ext } -; -sig_type_extension: - TYPE ext_attributes nonrec_flag optional_type_parameters type_longident - PLUSEQ private_flag sig_extension_constructors post_item_attributes - { let (ext, attrs) = $2 in - if $3 <> Recursive then not_expecting 3 "nonrec flag"; - Te.mk (mkrhs $5 5) (List.rev $8) ~params:$4 ~priv:$7 - ~attrs:(attrs @ $9) ~docs:(symbol_docs ()) - , ext } -; -str_extension_constructors: - extension_constructor_declaration { [$1] } - | bar_extension_constructor_declaration { [$1] } - | extension_constructor_rebind { [$1] } - | bar_extension_constructor_rebind { [$1] } - | str_extension_constructors bar_extension_constructor_declaration - { $2 :: $1 } - | str_extension_constructors bar_extension_constructor_rebind - { $2 :: $1 } -; -sig_extension_constructors: - extension_constructor_declaration { [$1] } - | bar_extension_constructor_declaration { [$1] } - | sig_extension_constructors bar_extension_constructor_declaration - { $2 :: $1 } -; -extension_constructor_declaration: - | constr_ident generalized_constructor_arguments attributes - { let args, res = $2 in - Te.decl (mkrhs $1 1) ~args ?res ~attrs:$3 - ~loc:(symbol_rloc()) ~info:(symbol_info ()) } -; -bar_extension_constructor_declaration: - | BAR constr_ident generalized_constructor_arguments attributes - { let args, res = $3 in - Te.decl (mkrhs $2 2) ~args ?res ~attrs:$4 - ~loc:(symbol_rloc()) ~info:(symbol_info ()) } +%inline str_type_extension: + type_extension(extension_constructor) + { $1 } +; +%inline sig_type_extension: + type_extension(extension_constructor_declaration) + { $1 } +; +%inline type_extension(declaration): + TYPE + ext = ext + attrs1 = attributes + no_nonrec_flag + params = type_parameters + tid = mkrhs(type_longident) + PLUSEQ + priv = private_flag + cs = bar_llist(declaration) + attrs2 = post_item_attributes + { let docs = symbol_docs $sloc in + let attrs = attrs1 @ attrs2 in + Te.mk tid cs ~params ~priv ~attrs ~docs, + ext } +; +%inline extension_constructor(opening): + extension_constructor_declaration(opening) + { $1 } + | extension_constructor_rebind(opening) + { $1 } ; -extension_constructor_rebind: - | constr_ident EQUAL constr_longident attributes - { Te.rebind (mkrhs $1 1) (mkrhs $3 3) ~attrs:$4 - ~loc:(symbol_rloc()) ~info:(symbol_info ()) } +%inline extension_constructor_declaration(opening): + d = generic_constructor_declaration(opening) + { + let cid, args, res, attrs, loc, info = d in + Te.decl cid ~args ?res ~attrs ~loc ~info + } ; -bar_extension_constructor_rebind: - | BAR constr_ident EQUAL constr_longident attributes - { Te.rebind (mkrhs $2 2) (mkrhs $4 4) ~attrs:$5 - ~loc:(symbol_rloc()) ~info:(symbol_info ()) } +extension_constructor_rebind(opening): + opening + cid = mkrhs(constr_ident) + EQUAL + lid = mkrhs(constr_longident) + attrs = attributes + { let info = symbol_info $endpos in + Te.rebind cid lid ~attrs ~loc:(make_loc $sloc) ~info } ; /* "with" constraints (additional type equations over signature components) */ -with_constraints: - with_constraint { [$1] } - | with_constraints AND with_constraint { $3 :: $1 } -; with_constraint: - TYPE optional_type_parameters label_longident with_type_binder + TYPE type_parameters mkrhs(label_longident) with_type_binder core_type_no_attr constraints - { Pwith_type - (mkrhs $3 3, - (Type.mk (mkrhs (Longident.last $3) 3) + { let lident = loc_last $3 in + Pwith_type + ($3, + (Type.mk lident ~params:$2 - ~cstrs:(List.rev $6) + ~cstrs:$6 ~manifest:$5 ~priv:$4 - ~loc:(symbol_rloc()))) } + ~loc:(make_loc $sloc))) } /* used label_longident instead of type_longident to disallow functor applications in type path */ - | TYPE optional_type_parameters label_longident COLONEQUAL core_type_no_attr - { Pwith_typesubst - (mkrhs $3 3, - (Type.mk (mkrhs (Longident.last $3) 3) - ~params:$2 - ~manifest:$5 - ~loc:(symbol_rloc()))) } - | MODULE mod_longident EQUAL mod_ext_longident - { Pwith_module (mkrhs $2 2, mkrhs $4 4) } - | MODULE mod_longident COLONEQUAL mod_ext_longident - { Pwith_modsubst (mkrhs $2 2, mkrhs $4 4) } + | TYPE type_parameters mkrhs(label_longident) + COLONEQUAL core_type_no_attr + { let lident = loc_last $3 in + Pwith_typesubst + ($3, + (Type.mk lident + ~params:$2 + ~manifest:$5 + ~loc:(make_loc $sloc))) } + | MODULE mkrhs(mod_longident) EQUAL mkrhs(mod_ext_longident) + { Pwith_module ($2, $4) } + | MODULE mkrhs(mod_longident) COLONEQUAL mkrhs(mod_ext_longident) + { Pwith_modsubst ($2, $4) } ; with_type_binder: EQUAL { Public } @@ -2197,177 +3068,255 @@ with_type_binder: /* Polymorphic types */ -typevar_list: - QUOTE ident { [mkrhs $2 2] } - | typevar_list QUOTE ident { mkrhs $3 3 :: $1 } +%inline typevar: + QUOTE mkrhs(ident) + { $2 } +; +%inline typevar_list: + nonempty_llist(typevar) + { $1 } +; +%inline poly(X): + typevar_list DOT X + { Ptyp_poly($1, $3) } ; -poly_type: - core_type - { $1 } - | typevar_list DOT core_type - { mktyp(Ptyp_poly(List.rev $1, $3)) } +possibly_poly(X): + X + { $1 } +| mktyp(poly(X)) + { $1 } ; -poly_type_no_attr: - core_type_no_attr - { $1 } - | typevar_list DOT core_type_no_attr - { mktyp(Ptyp_poly(List.rev $1, $3)) } +%inline poly_type: + possibly_poly(core_type) + { $1 } ; +%inline poly_type_no_attr: + possibly_poly(core_type_no_attr) + { $1 } +; + +(* -------------------------------------------------------------------------- *) -/* Core types */ +(* Core language types. *) +(* A core type (core_type) is a core type without attributes (core_type_no_attr) + followed with a list of attributes. *) core_type: core_type_no_attr { $1 } | core_type attribute { Typ.attr $1 $2 } ; -core_type_no_attr: - core_type2 %prec MINUSGREATER - { $1 } - | core_type2 AS QUOTE ident - { mktyp(Ptyp_alias($1, $4)) } -; -core_type2: - simple_core_type_or_tuple - { $1 } - | QUESTION LIDENT COLON core_type2 MINUSGREATER core_type2 - { let param = extra_rhs_core_type $4 ~pos:4 in - mktyp (Ptyp_arrow(Optional $2 , param, $6)) } - | OPTLABEL core_type2 MINUSGREATER core_type2 - { let param = extra_rhs_core_type $2 ~pos:2 in - mktyp(Ptyp_arrow(Optional $1 , param, $4)) - } - | LIDENT COLON core_type2 MINUSGREATER core_type2 - { let param = extra_rhs_core_type $3 ~pos:3 in - mktyp(Ptyp_arrow(Labelled $1, param, $5)) } - | core_type2 MINUSGREATER core_type2 - { let param = extra_rhs_core_type $1 ~pos:1 in - mktyp(Ptyp_arrow(Nolabel, param, $3)) } -; -simple_core_type: - simple_core_type2 %prec below_HASH - { $1 } - | LPAREN core_type_comma_list RPAREN %prec below_HASH - { match $2 with [sty] -> sty | _ -> raise Parse_error } +(* A core type without attributes is currently defined as an alias type, but + this could change in the future if new forms of types are introduced. From + the outside, one should use core_type_no_attr. *) +%inline core_type_no_attr: + alias_type + { $1 } ; -simple_core_type2: - QUOTE ident - { mktyp(Ptyp_var $2) } - | UNDERSCORE - { mktyp(Ptyp_any) } - | type_longident - { mktyp(Ptyp_constr(mkrhs $1 1, [])) } - | simple_core_type2 type_longident - { mktyp(Ptyp_constr(mkrhs $2 2, [$1])) } - | LPAREN core_type_comma_list RPAREN type_longident - { mktyp(Ptyp_constr(mkrhs $4 4, List.rev $2)) } - | LESS meth_list GREATER - { let (f, c) = $2 in mktyp(Ptyp_object (f, c)) } - | LESS GREATER - { mktyp(Ptyp_object ([], Closed)) } - | HASH class_longident - { mktyp(Ptyp_class(mkrhs $2 2, [])) } - | simple_core_type2 HASH class_longident - { mktyp(Ptyp_class(mkrhs $3 3, [$1])) } - | LPAREN core_type_comma_list RPAREN HASH class_longident - { mktyp(Ptyp_class(mkrhs $5 5, List.rev $2)) } - | LBRACKET tag_field RBRACKET - { mktyp(Ptyp_variant([$2], Closed, None)) } -/* PR#3835: this is not LR(1), would need lookahead=2 - | LBRACKET simple_core_type RBRACKET - { mktyp(Ptyp_variant([$2], Closed, None)) } -*/ - | LBRACKET BAR row_field_list RBRACKET - { mktyp(Ptyp_variant(List.rev $3, Closed, None)) } - | LBRACKET row_field BAR row_field_list RBRACKET - { mktyp(Ptyp_variant($2 :: List.rev $4, Closed, None)) } - | LBRACKETGREATER opt_bar row_field_list RBRACKET - { mktyp(Ptyp_variant(List.rev $3, Open, None)) } - | LBRACKETGREATER RBRACKET - { mktyp(Ptyp_variant([], Open, None)) } - | LBRACKETLESS opt_bar row_field_list RBRACKET - { mktyp(Ptyp_variant(List.rev $3, Closed, Some [])) } - | LBRACKETLESS opt_bar row_field_list GREATER name_tag_list RBRACKET - { mktyp(Ptyp_variant(List.rev $3, Closed, Some (List.rev $5))) } +(* Alias types include: + - function types (see below); + - proper alias types: 'a -> int as 'a + *) +alias_type: + function_type + { $1 } + | mktyp( + ty = alias_type AS QUOTE tyvar = ident + { Ptyp_alias(ty, tyvar) } + ) + { $1 } +; + +(* Function types include: + - tuple types (see below); + - proper function types: int -> int + foo: int -> int + ?foo: int -> int + *) +function_type: + | ty = tuple_type + %prec MINUSGREATER + { ty } + | mktyp( + label = arg_label + domain = extra_rhs(tuple_type) + MINUSGREATER + codomain = function_type + { Ptyp_arrow(label, domain, codomain) } + ) + { $1 } +; +%inline arg_label: + | label = optlabel + { Optional label } + | label = LIDENT COLON + { Labelled label } + | /* empty */ + { Nolabel } +; +(* Tuple types include: + - atomic types (see below); + - proper tuple types: int * int * int list + A proper tuple type is a star-separated list of at least two atomic types. + *) +tuple_type: + | ty = atomic_type + %prec below_HASH + { ty } + | mktyp( + tys = separated_nontrivial_llist(STAR, atomic_type) + { Ptyp_tuple tys } + ) + { $1 } +; + +(* Atomic types are the most basic level in the syntax of types. + Atomic types include: + - types between parentheses: (int -> int) + - first-class module types: (module S) + - type variables: 'a + - applications of type constructors: int, int list, int option list + - variant types: [`A] + *) +atomic_type: + | LPAREN core_type RPAREN + { $2 } | LPAREN MODULE ext_attributes package_type RPAREN - { mktyp_attrs (Ptyp_package $4) $3 } - | extension - { mktyp (Ptyp_extension $1) } + { wrap_typ_attrs ~loc:$sloc (reloc_typ ~loc:$sloc $4) $3 } + | mktyp( /* begin mktyp group */ + QUOTE ident + { Ptyp_var $2 } + | UNDERSCORE + { Ptyp_any } + | tys = actual_type_parameters + tid = mkrhs(type_longident) + { Ptyp_constr(tid, tys) } + | LESS meth_list GREATER + { let (f, c) = $2 in Ptyp_object (f, c) } + | LESS GREATER + { Ptyp_object ([], Closed) } + | tys = actual_type_parameters + HASH + cid = mkrhs(class_longident) + { Ptyp_class(cid, tys) } + | LBRACKET tag_field RBRACKET + (* not row_field; see CONFLICTS *) + { Ptyp_variant([$2], Closed, None) } + | LBRACKET BAR row_field_list RBRACKET + { Ptyp_variant($3, Closed, None) } + | LBRACKET row_field BAR row_field_list RBRACKET + { Ptyp_variant($2 :: $4, Closed, None) } + | LBRACKETGREATER BAR? row_field_list RBRACKET + { Ptyp_variant($3, Open, None) } + | LBRACKETGREATER RBRACKET + { Ptyp_variant([], Open, None) } + | LBRACKETLESS BAR? row_field_list RBRACKET + { Ptyp_variant($3, Closed, Some []) } + | LBRACKETLESS BAR? row_field_list GREATER name_tag_list RBRACKET + { Ptyp_variant($3, Closed, Some $5) } + | extension + { Ptyp_extension $1 } + ) + { $1 } /* end mktyp group */ +; + +(* This is the syntax of the actual type parameters in an application of + a type constructor, such as int, int list, or (int, bool) Hashtbl.t. + We allow one of the following: + - zero parameters; + - one parameter: + an atomic type; + among other things, this can be an arbitrary type between parentheses; + - two or more parameters: + arbitrary types, between parentheses, separated with commas. + *) +%inline actual_type_parameters: + | /* empty */ + { [] } + | ty = atomic_type + { [ty] } + | LPAREN tys = separated_nontrivial_llist(COMMA, core_type) RPAREN + { tys } ; -package_type: - module_type { package_type_of_module_type $1 } + +%inline package_type: + mktyp(module_type + { Ptyp_package (package_type_of_module_type $1) }) + { $1 } ; -row_field_list: - row_field { [$1] } - | row_field_list BAR row_field { $3 :: $1 } +%inline row_field_list: + separated_nonempty_llist(BAR, row_field) + { $1 } ; row_field: - tag_field { $1 } - | simple_core_type { Rinherit $1 } + tag_field + { $1 } + | core_type + { Rf.inherit_ ~loc:(make_loc $sloc) $1 } ; tag_field: - name_tag OF opt_ampersand amper_type_list attributes - { Rtag (mkrhs $1 1, add_info_attrs (symbol_info ()) $5, - $3, List.rev $4) } - | name_tag attributes - { Rtag (mkrhs $1 1, add_info_attrs (symbol_info ()) $2, true, []) } + mkrhs(name_tag) OF opt_ampersand amper_type_list attributes + { let info = symbol_info $endpos in + let attrs = add_info_attrs info $5 in + Rf.tag ~loc:(make_loc $sloc) ~attrs $1 $3 $4 } + | mkrhs(name_tag) attributes + { let info = symbol_info $endpos in + let attrs = add_info_attrs info $2 in + Rf.tag ~loc:(make_loc $sloc) ~attrs $1 true [] } ; opt_ampersand: AMPERSAND { true } | /* empty */ { false } ; -amper_type_list: - core_type_no_attr { [$1] } - | amper_type_list AMPERSAND core_type_no_attr { $3 :: $1 } -; -name_tag_list: - name_tag { [$1] } - | name_tag_list name_tag { $2 :: $1 } -; -simple_core_type_or_tuple: - simple_core_type { $1 } - | simple_core_type STAR core_type_list - { mktyp(Ptyp_tuple($1 :: List.rev $3)) } +%inline amper_type_list: + separated_nonempty_llist(AMPERSAND, core_type_no_attr) + { $1 } ; -core_type_comma_list: - core_type { [$1] } - | core_type_comma_list COMMA core_type { $3 :: $1 } -; -core_type_list: - simple_core_type { [$1] } - | core_type_list STAR simple_core_type { $3 :: $1 } +%inline name_tag_list: + nonempty_llist(name_tag) + { $1 } ; +(* A method list (in an object type). *) meth_list: - field_semi meth_list { let (f, c) = $2 in ($1 :: f, c) } - | inherit_field_semi meth_list { let (f, c) = $2 in ($1 :: f, c) } - | field_semi { [$1], Closed } - | field { [$1], Closed } - | inherit_field_semi { [$1], Closed } - | simple_core_type { [Oinherit $1], Closed } - | DOTDOT { [], Open } -; -field: - label COLON poly_type_no_attr attributes - { Otag (mkrhs $1 1, add_info_attrs (symbol_info ()) $4, $3) } -; - -field_semi: - label COLON poly_type_no_attr attributes SEMI attributes + head = field_semi tail = meth_list + | head = inherit_field SEMI tail = meth_list + { let (f, c) = tail in (head :: f, c) } + | head = field_semi + | head = inherit_field SEMI + { [head], Closed } + | head = field + | head = inherit_field + { [head], Closed } + | DOTDOT + { [], Open } +; +%inline field: + mkrhs(label) COLON poly_type_no_attr attributes + { let info = symbol_info $endpos in + let attrs = add_info_attrs info $4 in + Of.tag ~loc:(make_loc $sloc) ~attrs $1 $3 } +; + +%inline field_semi: + mkrhs(label) COLON poly_type_no_attr attributes SEMI attributes { let info = - match rhs_info 4 with + match rhs_info $endpos($4) with | Some _ as info_before_semi -> info_before_semi - | None -> symbol_info () + | None -> symbol_info $endpos in - ( Otag (mkrhs $1 1, add_info_attrs info ($4 @ $6), $3)) } + let attrs = add_info_attrs info ($4 @ $6) in + Of.tag ~loc:(make_loc $sloc) ~attrs $1 $3 } ; -inherit_field_semi: - simple_core_type SEMI { Oinherit $1 } +%inline inherit_field: + ty = atomic_type + { Of.inherit_ ~loc:(make_loc $sloc) ty } +; -label: +%inline label: LIDENT { $1 } ; @@ -2390,23 +3339,20 @@ signed_constant: /* Identifiers and long identifiers */ ident: - UIDENT { $1 } - | LIDENT { $1 } + UIDENT { $1 } + | LIDENT { $1 } ; val_ident: - LIDENT { $1 } - | LPAREN operator RPAREN { $2 } - | LPAREN operator error { unclosed "(" 1 ")" 3 } - | LPAREN error { expecting 2 "operator" } - | LPAREN MODULE error { expecting 3 "module-expr" } + LIDENT { $1 } + | LPAREN operator RPAREN { $2 } + | LPAREN operator error { unclosed "(" $loc($1) ")" $loc($3) } + | LPAREN error { expecting $loc($2) "operator" } + | LPAREN MODULE error { expecting $loc($3) "module-expr" } ; operator: PREFIXOP { $1 } - | INFIXOP0 { $1 } - | INFIXOP1 { $1 } - | INFIXOP2 { $1 } - | INFIXOP3 { $1 } - | INFIXOP4 { $1 } + | LETOP { $1 } + | ANDOP { $1 } | DOTOP LPAREN RPAREN { "."^ $1 ^"()" } | DOTOP LPAREN RPAREN LESSMINUS { "."^ $1 ^ "()<-" } | DOTOP LBRACKET RBRACKET { "."^ $1 ^"[]" } @@ -2415,21 +3361,29 @@ operator: | DOTOP LBRACE RBRACE LESSMINUS { "."^ $1 ^ "{}<-" } | HASHOP { $1 } | BANG { "!" } - | PLUS { "+" } - | PLUSDOT { "+." } - | MINUS { "-" } - | MINUSDOT { "-." } - | STAR { "*" } - | EQUAL { "=" } - | LESS { "<" } - | GREATER { ">" } - | OR { "or" } - | BARBAR { "||" } - | AMPERSAND { "&" } - | AMPERAMPER { "&&" } - | COLONEQUAL { ":=" } - | PLUSEQ { "+=" } - | PERCENT { "%" } + | infix_operator { $1 } +; +%inline infix_operator: + | op = INFIXOP0 { op } + | op = INFIXOP1 { op } + | op = INFIXOP2 { op } + | op = INFIXOP3 { op } + | op = INFIXOP4 { op } + | PLUS {"+"} + | PLUSDOT {"+."} + | PLUSEQ {"+="} + | MINUS {"-"} + | MINUSDOT {"-."} + | STAR {"*"} + | PERCENT {"%"} + | EQUAL {"="} + | LESS {"<"} + | GREATER {">"} + | OR {"or"} + | BARBAR {"||"} + | AMPERSAND {"&"} + | AMPERAMPER {"&&"} + | COLONEQUAL {":="} ; constr_ident: UIDENT { $1 } @@ -2468,7 +3422,10 @@ mod_longident: mod_ext_longident: UIDENT { Lident $1 } | mod_ext_longident DOT UIDENT { Ldot($1, $3) } - | mod_ext_longident LPAREN mod_ext_longident RPAREN { lapply $1 $3 } + | mod_ext_longident LPAREN mod_ext_longident RPAREN + { lapply ~loc:$sloc $1 $3 } + | mod_ext_longident LPAREN error + { expecting $loc($3) "module path" } ; mty_longident: ident { Lident $1 } @@ -2486,18 +3443,33 @@ class_longident: /* Toplevel directives */ toplevel_directive: - HASH ident { Ptop_dir($2, Pdir_none) } - | HASH ident STRING { Ptop_dir($2, Pdir_string (fst $3)) } - | HASH ident INT { let (n, m) = $3 in - Ptop_dir($2, Pdir_int (n ,m)) } - | HASH ident val_longident { Ptop_dir($2, Pdir_ident $3) } - | HASH ident mod_longident { Ptop_dir($2, Pdir_ident $3) } - | HASH ident FALSE { Ptop_dir($2, Pdir_bool false) } - | HASH ident TRUE { Ptop_dir($2, Pdir_bool true) } + HASH dir = mkrhs(ident) + arg = ioption(mk_directive_arg(toplevel_directive_argument)) + { mk_directive ~loc:$sloc dir arg } +; + +%inline toplevel_directive_argument: + | STRING { let (s, _) = $1 in Pdir_string s } + | INT { let (n, m) = $1 in Pdir_int (n ,m) } + | val_longident { Pdir_ident $1 } + | mod_longident { Pdir_ident $1 } + | FALSE { Pdir_bool false } + | TRUE { Pdir_bool true } ; /* Miscellaneous */ +(* The symbol epsilon can be used instead of an /* empty */ comment. *) +%inline epsilon: + /* empty */ + { () } +; + +%inline raw_string: + s = STRING + { fst s } +; + name_tag: BACKQUOTE ident { $2 } ; @@ -2505,15 +3477,23 @@ rec_flag: /* empty */ { Nonrecursive } | REC { Recursive } ; -nonrec_flag: +%inline nonrec_flag: /* empty */ { Recursive } | NONREC { Nonrecursive } ; +%inline no_nonrec_flag: + /* empty */ { Recursive } + | NONREC { not_expecting $loc "nonrec flag" } +; direction_flag: TO { Upto } | DOWNTO { Downto } ; private_flag: + inline_private_flag + { $1 } +; +%inline inline_private_flag: /* empty */ { Public } | PRIVATE { Private } ; @@ -2525,6 +3505,17 @@ virtual_flag: /* empty */ { Concrete } | VIRTUAL { Virtual } ; +mutable_virtual_flags: + /* empty */ + { Immutable, Concrete } + | MUTABLE + { Mutable, Concrete } + | VIRTUAL + { Immutable, Virtual } + | MUTABLE VIRTUAL + | VIRTUAL MUTABLE + { Mutable, Virtual } +; private_virtual_flags: /* empty */ { Public, Concrete } | PRIVATE { Private, Concrete } @@ -2532,17 +3523,26 @@ private_virtual_flags: | PRIVATE VIRTUAL { Private, Virtual } | VIRTUAL PRIVATE { Private, Virtual } ; -override_flag: +(* This nonterminal symbol indicates the definite presence of a VIRTUAL + keyword and the possible presence of a MUTABLE keyword. *) +virtual_with_mutable_flag: + | VIRTUAL { Immutable } + | MUTABLE VIRTUAL { Mutable } + | VIRTUAL MUTABLE { Mutable } +; +(* This nonterminal symbol indicates the definite presence of a VIRTUAL + keyword and the possible presence of a PRIVATE keyword. *) +virtual_with_private_flag: + | VIRTUAL { Public } + | PRIVATE VIRTUAL { Private } + | VIRTUAL PRIVATE { Private } +; +%inline no_override_flag: /* empty */ { Fresh } - | BANG { Override } -; -opt_bar: - /* empty */ { () } - | BAR { () } ; -opt_semi: - | /* empty */ { () } - | SEMI { () } +%inline override_flag: + /* empty */ { Fresh } + | BANG { Override } ; subtractive: | MINUS { "-" } @@ -2552,6 +3552,10 @@ additive: | PLUS { "+" } | PLUSDOT { "+." } ; +optlabel: + | OPTLABEL { $1 } + | QUESTION LIDENT COLON { $2 } +; /* Attributes and extensions */ @@ -2611,30 +3615,42 @@ single_attr_id: ; attr_id: - single_attr_id { mkloc $1 (symbol_rloc()) } - | single_attr_id DOT attr_id { mkloc ($1 ^ "." ^ $3.txt) (symbol_rloc())} + mkloc( + single_attr_id { $1 } + | single_attr_id DOT attr_id { $1 ^ "." ^ $3.txt } + ) { $1 } ; attribute: - LBRACKETAT attr_id payload RBRACKET { ($2, $3) } + LBRACKETAT attr_id payload RBRACKET + { Attr.mk ~loc:(make_loc $sloc) $2 $3 } ; post_item_attribute: - LBRACKETATAT attr_id payload RBRACKET { ($2, $3) } + LBRACKETATAT attr_id payload RBRACKET + { Attr.mk ~loc:(make_loc $sloc) $2 $3 } ; floating_attribute: - LBRACKETATATAT attr_id payload RBRACKET { ($2, $3) } + LBRACKETATATAT attr_id payload RBRACKET + { mark_symbol_docs $sloc; + Attr.mk ~loc:(make_loc $sloc) $2 $3 } +; +%inline post_item_attributes: + post_item_attribute* + { $1 } +; +%inline attributes: + attribute* + { $1 } ; -post_item_attributes: - /* empty */ { [] } - | post_item_attribute post_item_attributes { $1 :: $2 } +ext: + | /* empty */ { None } + | PERCENT attr_id { Some $2 } ; -attributes: - /* empty */{ [] } - | attribute attributes { $1 :: $2 } +%inline no_ext: + | /* empty */ { None } + | PERCENT attr_id { not_expecting $loc "extension" } ; -ext_attributes: - /* empty */ { None, [] } - | attribute attributes { None, $1 :: $2 } - | PERCENT attr_id attributes { Some $2, $3 } +%inline ext_attributes: + ext attributes { $1, $2 } ; extension: LBRACKETPERCENT attr_id payload RBRACKET { ($2, $3) } diff --git a/parsing/parsetree.mli b/parsing/parsetree.mli index 9f5de197..ac5a3f2b 100644 --- a/parsing/parsetree.mli +++ b/parsing/parsetree.mli @@ -13,7 +13,12 @@ (* *) (**************************************************************************) -(** Abstract syntax tree produced by parsing *) +(** Abstract syntax tree produced by parsing + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) open Asttypes @@ -39,7 +44,11 @@ type constant = (** {1 Extension points} *) -type attribute = string loc * payload +type attribute = { + attr_name : string loc; + attr_payload : payload; + attr_loc : Location.t; + } (* [@id ARG] [@@id ARG] @@ -70,6 +79,7 @@ and core_type = { ptyp_desc: core_type_desc; ptyp_loc: Location.t; + ptyp_loc_stack: Location.t list; ptyp_attributes: attributes; (* ... [@id1] [@id2] *) } @@ -141,25 +151,35 @@ and package_type = Longident.t loc * (Longident.t loc * core_type) list (module S with type t1 = T1 and ... and tn = Tn) *) -and row_field = - | Rtag of label loc * attributes * bool * core_type list +and row_field = { + prf_desc : row_field_desc; + prf_loc : Location.t; + prf_attributes : attributes; +} + +and row_field_desc = + | Rtag of label loc * bool * core_type list (* [`A] ( true, [] ) [`A of T] ( false, [T] ) [`A of T1 & .. & Tn] ( false, [T1;...Tn] ) [`A of & T1 & .. & Tn] ( true, [T1;...Tn] ) - - The 2nd field is true if the tag contains a + - The 'bool' field is true if the tag contains a constant (empty) constructor. - '&' occurs when several types are used for the same constructor (see 4.2 in the manual) - - - TODO: switch to a record representation, and keep location *) | Rinherit of core_type (* [ T ] *) -and object_field = - | Otag of label loc * attributes * core_type +and object_field = { + pof_desc : object_field_desc; + pof_loc : Location.t; + pof_attributes : attributes; +} + +and object_field_desc = + | Otag of label loc * core_type | Oinherit of core_type (* Patterns *) @@ -168,6 +188,7 @@ and pattern = { ppat_desc: pattern_desc; ppat_loc: Location.t; + ppat_loc_stack: Location.t list; ppat_attributes: attributes; (* ... [@id1] [@id2] *) } @@ -233,6 +254,7 @@ and expression = { pexp_desc: expression_desc; pexp_loc: Location.t; + pexp_loc_stack: Location.t list; pexp_attributes: attributes; (* ... [@id1] [@id2] *) } @@ -346,10 +368,13 @@ and expression_desc = (module ME : S) is represented as Pexp_constraint(Pexp_pack, Ptyp_package S) *) - | Pexp_open of override_flag * Longident.t loc * expression + | Pexp_open of open_declaration * expression (* M.(E) let open M in E let! open M in E *) + | Pexp_letop of letop + (* let* P = E in E + let* P = E and* P = E in E *) | Pexp_extension of extension (* [%id] *) | Pexp_unreachable @@ -360,7 +385,22 @@ and case = (* (P -> E) or (P when E0 -> E) *) pc_lhs: pattern; pc_guard: expression option; pc_rhs: expression; - } + } + +and letop = + { + let_ : binding_op; + ands : binding_op list; + body : expression; + } + +and binding_op = + { + pbop_op : string loc; + pbop_pat : pattern; + pbop_exp : expression; + pbop_loc : Location.t; + } (* Value descriptions *) @@ -454,6 +494,7 @@ and type_extension = ptyext_params: (core_type * variance) list; ptyext_constructors: extension_constructor list; ptyext_private: private_flag; + ptyext_loc: Location.t; ptyext_attributes: attributes; (* ... [@@id1] [@@id2] *) } (* @@ -466,7 +507,15 @@ and extension_constructor = pext_kind : extension_constructor_kind; pext_loc : Location.t; pext_attributes: attributes; (* C of ... [@id1] [@id2] *) - } + } + +(* exception E *) +and type_exception = + { + ptyexn_constructor: extension_constructor; + ptyexn_loc: Location.t; + ptyexn_attributes: attributes; (* ... [@@id1] [@@id2] *) + } and extension_constructor_kind = Pext_decl of constructor_arguments * core_type option @@ -504,7 +553,7 @@ and class_type_desc = *) | Pcty_extension of extension (* [%id] *) - | Pcty_open of override_flag * Longident.t loc * class_type + | Pcty_open of open_description * class_type (* let open M in CT *) and class_signature = @@ -596,7 +645,7 @@ and class_expr_desc = (* (CE : CT) *) | Pcl_extension of extension (* [%id] *) - | Pcl_open of override_flag * Longident.t loc * class_expr + | Pcl_open of open_description * class_expr (* let open M in CE *) @@ -688,13 +737,18 @@ and signature_item_desc = external x: T = "s1" ... "sn" *) | Psig_type of rec_flag * type_declaration list - (* type t1 = ... and ... and tn = ... *) + (* type t1 = ... and ... and tn = ... *) + | Psig_typesubst of type_declaration list + (* type t1 := ... and ... and tn := ... *) | Psig_typext of type_extension (* type t1 += ... *) - | Psig_exception of extension_constructor + | Psig_exception of type_exception (* exception C of T *) | Psig_module of module_declaration - (* module X : MT *) + (* module X = M + module X : MT *) + | Psig_modsubst of module_substitution + (* module X := M *) | Psig_recmodule of module_declaration list (* module rec X1 : MT1 and ... and Xn : MTn *) | Psig_modtype of module_type_declaration @@ -722,6 +776,14 @@ and module_declaration = } (* S : MT *) +and module_substitution = + { + pms_name: string loc; + pms_manifest: Longident.t loc; + pms_attributes: attributes; (* ... [@@id1] [@@id2] *) + pms_loc: Location.t; + } + and module_type_declaration = { pmtd_name: string loc; @@ -733,9 +795,9 @@ and module_type_declaration = S (abstract module type declaration, pmtd_type = None) *) -and open_description = +and 'a open_infos = { - popen_lid: Longident.t loc; + popen_expr: 'a; popen_override: override_flag; popen_loc: Location.t; popen_attributes: attributes; @@ -745,6 +807,15 @@ and open_description = open X - popen_override = Fresh *) +and open_description = Longident.t loc open_infos +(* open M.N + open M(N).O *) + +and open_declaration = module_expr open_infos +(* open M.N + open M(N).O + open struct ... end *) + and 'a include_infos = { pincl_mod: 'a; @@ -818,7 +889,7 @@ and structure_item_desc = (* type t1 = ... and ... and tn = ... *) | Pstr_typext of type_extension (* type t1 += ... *) - | Pstr_exception of extension_constructor + | Pstr_exception of type_exception (* exception C of T exception C = M.X *) | Pstr_module of module_binding @@ -827,7 +898,7 @@ and structure_item_desc = (* module rec X1 = ME1 and ... and Xn = MEn *) | Pstr_modtype of module_type_declaration (* module type S = MT *) - | Pstr_open of open_description + | Pstr_open of open_declaration (* open X *) | Pstr_class of class_declaration list (* class c1 = ... and ... and cn = ... *) @@ -863,11 +934,23 @@ and module_binding = type toplevel_phrase = | Ptop_def of structure - | Ptop_dir of string * directive_argument + | Ptop_dir of toplevel_directive (* #use, #load ... *) +and toplevel_directive = + { + pdir_name : string loc; + pdir_arg : directive_argument option; + pdir_loc : Location.t; + } + and directive_argument = - | Pdir_none + { + pdira_desc : directive_argument_desc; + pdira_loc : Location.t; + } + +and directive_argument_desc = | Pdir_string of string | Pdir_int of string * char option | Pdir_ident of Longident.t diff --git a/parsing/pprintast.ml b/parsing/pprintast.ml index 30a90644..1590a89d 100644 --- a/parsing/pprintast.ml +++ b/parsing/pprintast.ml @@ -36,16 +36,33 @@ let infix_symbols = [ '='; '<'; '>'; '@'; '^'; '|'; '&'; '+'; '-'; '*'; '/'; let special_infix_strings = ["asr"; "land"; "lor"; "lsl"; "lsr"; "lxor"; "mod"; "or"; ":="; "!="; "::" ] +let letop s = + String.length s > 3 + && s.[0] = 'l' + && s.[1] = 'e' + && s.[2] = 't' + && List.mem s.[3] infix_symbols + +let andop s = + String.length s > 3 + && s.[0] = 'a' + && s.[1] = 'n' + && s.[2] = 'd' + && List.mem s.[3] infix_symbols + (* determines if the string is an infix string. checks backwards, first allowing a renaming postfix ("_102") which may have resulted from Pexp -> Texp -> Pexp translation, then checking if all the characters in the beginning of the string are valid infix characters. *) let fixity_of_string = function + | "" -> `Normal | s when List.mem s special_infix_strings -> `Infix s | s when List.mem s.[0] infix_symbols -> `Infix s | s when List.mem s.[0] prefix_symbols -> `Prefix s | s when s.[0] = '.' -> `Mixfix s + | s when letop s -> `Letop s + | s when andop s -> `Andop s | _ -> `Normal let view_fixity_of_exp = function @@ -53,20 +70,30 @@ let view_fixity_of_exp = function fixity_of_string l | _ -> `Normal -let is_infix = function | `Infix _ -> true | _ -> false +let is_infix = function `Infix _ -> true | _ -> false let is_mixfix = function `Mixfix _ -> true | _ -> false +let is_kwdop = function `Letop _ | `Andop _ -> true | _ -> false + +let first_is c str = + str <> "" && str.[0] = c +let last_is c str = + str <> "" && str.[String.length str - 1] = c + +let first_is_in cs str = + str <> "" && List.mem str.[0] cs (* which identifiers are in fact operators needing parentheses *) let needs_parens txt = let fix = fixity_of_string txt in is_infix fix || is_mixfix fix - || List.mem txt.[0] prefix_symbols + || is_kwdop fix + || first_is_in prefix_symbols txt (* some infixes need spaces around parens to avoid clashes with comment syntax *) let needs_spaces txt = - txt.[0]='*' || txt.[String.length txt - 1] = '*' + first_is '*' txt || last_is '*' txt (* add parentheses to binders when they are in fact infix or prefix operators *) let protect_ident ppf txt = @@ -192,15 +219,20 @@ let rec longident f = function let longident_loc f x = pp f "%a" longident x.txt let constant f = function - | Pconst_char i -> pp f "%C" i - | Pconst_string (i, None) -> pp f "%S" i - | Pconst_string (i, Some delim) -> pp f "{%s|%s|%s}" delim i delim - | Pconst_integer (i, None) -> paren (i.[0]='-') (fun f -> pp f "%s") f i + | Pconst_char i -> + pp f "%C" i + | Pconst_string (i, None) -> + pp f "%S" i + | Pconst_string (i, Some delim) -> + pp f "{%s|%s|%s}" delim i delim + | Pconst_integer (i, None) -> + paren (first_is '-' i) (fun f -> pp f "%s") f i | Pconst_integer (i, Some m) -> - paren (i.[0]='-') (fun f (i, m) -> pp f "%s%c" i m) f (i,m) - | Pconst_float (i, None) -> paren (i.[0]='-') (fun f -> pp f "%s") f i - | Pconst_float (i, Some m) -> paren (i.[0]='-') (fun f (i,m) -> - pp f "%s%c" i m) f (i,m) + paren (first_is '-' i) (fun f (i, m) -> pp f "%s%c" i m) f (i,m) + | Pconst_float (i, None) -> + paren (first_is '-' i) (fun f -> pp f "%s") f i + | Pconst_float (i, Some m) -> + paren (first_is '-' i) (fun f (i,m) -> pp f "%s%c" i m) f (i,m) (* trailing space*) let mutable_flag f = function @@ -226,9 +258,19 @@ let private_flag f = function | Public -> () | Private -> pp f "private@ " +let iter_loc f ctxt {txt; loc = _} = f ctxt txt + let constant_string f s = pp f "%S" s -let tyvar f str = pp f "'%s" str -let tyvar_loc f str = pp f "'%s" str.txt + +let tyvar ppf s = + if String.length s >= 2 && s.[1] = '\'' then + (* without the space, this would be parsed as + a character literal *) + Format.fprintf ppf "' %s" s + else + Format.fprintf ppf "'%s" s + +let tyvar_loc f str = tyvar f str.txt let string_quot f x = pp f "`%s" x (* c ['a,'b] *) @@ -254,7 +296,7 @@ and core_type ctxt f x = pp f "@[<2>%a@;->@;%a@]" (* FIXME remove parens later *) (type_with_label ctxt) (l,ct1) (core_type ctxt) ct2 | Ptyp_alias (ct, s) -> - pp f "@[<2>%a@;as@;'%s@]" (core_type1 ctxt) ct s + pp f "@[<2>%a@;as@;%a@]" (core_type1 ctxt) ct tyvar s | Ptyp_poly ([], ct) -> core_type ctxt f ct | Ptyp_poly (sl, ct) -> @@ -285,14 +327,14 @@ and core_type1 ctxt f x = l longident_loc li | Ptyp_variant (l, closed, low) -> let type_variant_helper f x = - match x with - | Rtag (l, attrs, _, ctl) -> - pp f "@[<2>%a%a@;%a@]" string_quot l.txt + match x.prf_desc with + | Rtag (l, _, ctl) -> + pp f "@[<2>%a%a@;%a@]" (iter_loc string_quot) l (fun f l -> match l with |[] -> () | _ -> pp f "@;of@;%a" (list (core_type ctxt) ~sep:"&") ctl) ctl - (attributes ctxt) attrs + (attributes ctxt) x.prf_attributes | Rinherit ct -> core_type ctxt f ct in pp f "@[<2>[%a%a]@]" (fun f l -> @@ -312,10 +354,11 @@ and core_type1 ctxt f x = pp f ">@ %a" (list string_quot) xs) low | Ptyp_object (l, o) -> - let core_field_type f = function - | Otag (l, attrs, ct) -> + let core_field_type f x = match x.pof_desc with + | Otag (l, ct) -> + (* Cf #7200 *) pp f "@[%s: %a@ %a@ @]" l.txt - (core_type ctxt) ct (attributes ctxt) attrs (* Cf #7200 *) + (core_type ctxt) ct (attributes ctxt) x.pof_attributes | Oinherit ct -> pp f "@[%a@ @]" (core_type ctxt) ct in @@ -326,7 +369,8 @@ and core_type1 ctxt f x = | [] -> pp f ".." | _ -> pp f " ;.." in - pp f "@[<@ %a%a@ > @]" (list core_field_type ~sep:";") l + pp f "@[<@ %a%a@ > @]" + (list core_field_type ~sep:";") l field_var o (* Cf #7200 *) | Ptyp_class (li, l) -> (*FIXME*) pp f "@[%a#%a@]" @@ -511,15 +555,15 @@ and sugar_expr ctxt f e = | _ -> false end | (Lident s | Ldot(_,s)) , a :: i :: rest - when s.[0] = '.' -> - let n = String.length s in + when first_is '.' s -> (* extract operator: assignment operators end with [right_bracket ^ "<-"], access operators end with [right_bracket] directly *) - let assign = s.[n - 1] = '-' in + let assign = last_is '-' s in let kind = (* extract the right end bracket *) + let n = String.length s in if assign then s.[n - 3] else s.[n - 1] in let left, right = match kind with | ')' -> '(', ")" @@ -546,7 +590,8 @@ and expression ctxt f x = paren true (expression reset_ctxt) f x | Pexp_ifthenelse _ | Pexp_sequence _ when ctxt.ifthenelse -> paren true (expression reset_ctxt) f x - | Pexp_let _ | Pexp_letmodule _ | Pexp_open _ | Pexp_letexception _ + | Pexp_let _ | Pexp_letmodule _ | Pexp_open _ + | Pexp_letexception _ | Pexp_letop _ when ctxt.semi -> paren true (expression reset_ctxt) f x | Pexp_fun (l, e0, p, e) -> @@ -666,11 +711,17 @@ and expression ctxt f x = | Pexp_poly (e, Some ct) -> pp f "@[(!poly!@ %a@ : %a)@]" (simple_expr ctxt) e (core_type ctxt) ct - | Pexp_open (ovf, lid, e) -> - pp f "@[<2>let open%s %a in@;%a@]" (override ovf) longident_loc lid + | Pexp_open (o, e) -> + pp f "@[<2>let open%s %a in@;%a@]" + (override o.popen_override) (module_expr ctxt) o.popen_expr (expression ctxt) e | Pexp_variant (l,Some eo) -> pp f "@[<2>`%s@;%a@]" l (simple_expr ctxt) eo + | Pexp_letop {let_; ands; body} -> + pp f "@[<2>@[%a@,%a@] in@;<1 -2>%a@]" + (binding_op ctxt) let_ + (list ~sep:"@," (binding_op ctxt)) ands + (expression ctxt) body | Pexp_extension e -> extension ctxt f e | Pexp_unreachable -> pp f "." | _ -> expression1 ctxt f x @@ -754,14 +805,14 @@ and attributes ctxt f l = and item_attributes ctxt f l = List.iter (item_attribute ctxt f) l -and attribute ctxt f (s, e) = - pp f "@[<2>[@@%s@ %a]@]" s.txt (payload ctxt) e +and attribute ctxt f a = + pp f "@[<2>[@@%s@ %a]@]" a.attr_name.txt (payload ctxt) a.attr_payload -and item_attribute ctxt f (s, e) = - pp f "@[<2>[@@@@%s@ %a]@]" s.txt (payload ctxt) e +and item_attribute ctxt f a = + pp f "@[<2>[@@@@%s@ %a]@]" a.attr_name.txt (payload ctxt) a.attr_payload -and floating_attribute ctxt f (s, e) = - pp f "@[<2>[@@@@@@%s@ %a]@]" s.txt (payload ctxt) e +and floating_attribute ctxt f a = + pp f "@[<2>[@@@@@@%s@ %a]@]" a.attr_name.txt (payload ctxt) a.attr_payload and value_description ctxt f x = (* note: value_description has an attribute field, @@ -778,8 +829,10 @@ and extension ctxt f (s, e) = and item_extension ctxt f (s, e) = pp f "@[<2>[%%%%%s@ %a]@]" s.txt (payload ctxt) e -and exception_declaration ctxt f ext = - pp f "@[exception@ %a@]" (extension_constructor ctxt) ext +and exception_declaration ctxt f x = + pp f "@[exception@ %a@]%a" + (extension_constructor ctxt) x.ptyexn_constructor + (item_attributes ctxt) x.ptyexn_attributes and class_signature ctxt f { pcsig_self = ct; pcsig_fields = l ;_} = let class_type_field f x = @@ -830,8 +883,9 @@ and class_type ctxt f x = | Pcty_extension e -> extension ctxt f e; attributes ctxt f x.pcty_attributes - | Pcty_open (ovf, lid, e) -> - pp f "@[<2>let open%s %a in@;%a@]" (override ovf) longident_loc lid + | Pcty_open (o, e) -> + pp f "@[<2>let open%s %a in@;%a@]" + (override o.popen_override) longident_loc o.popen_expr (class_type ctxt) e (* [class type a = object end] *) @@ -880,7 +934,10 @@ and class_field ctxt f x = let bind e = binding ctxt f {pvb_pat= - {ppat_desc=Ppat_var s;ppat_loc=Location.none;ppat_attributes=[]}; + {ppat_desc=Ppat_var s; + ppat_loc=Location.none; + ppat_loc_stack=[]; + ppat_attributes=[]}; pvb_expr=e; pvb_attributes=[]; pvb_loc=Location.none; @@ -949,8 +1006,9 @@ and class_expr ctxt f x = (class_expr ctxt) ce (class_type ctxt) ct | Pcl_extension e -> extension ctxt f e - | Pcl_open (ovf, lid, e) -> - pp f "@[<2>let open%s %a in@;%a@]" (override ovf) longident_loc lid + | Pcl_open (o, e) -> + pp f "@[<2>let open%s %a in@;%a@]" + (override o.popen_override) longident_loc o.popen_expr (class_expr ctxt) e and module_type ctxt f x = @@ -1010,7 +1068,9 @@ and signature ctxt f x = list ~sep:"@\n" (signature_item ctxt) f x and signature_item ctxt f x : unit = match x.psig_desc with | Psig_type (rf, l) -> - type_def_list ctxt f (rf, l) + type_def_list ctxt f (rf, true, l) + | Psig_typesubst l -> + type_def_list ctxt f (Nonrecursive, false, l) | Psig_value vd -> let intro = if vd.pval_prim = [] then "val" else "external" in pp f "@[<2>%s@ %a@ :@ %a@]%a" intro @@ -1047,10 +1107,14 @@ and signature_item ctxt f x : unit = pmd.pmd_name.txt (module_type ctxt) pmd.pmd_type (item_attributes ctxt) pmd.pmd_attributes + | Psig_modsubst pms -> + pp f "@[module@ %s@ :=@ %a@]%a" pms.pms_name.txt + longident_loc pms.pms_manifest + (item_attributes ctxt) pms.pms_attributes | Psig_open od -> pp f "@[open%s@ %a@]%a" (override od.popen_override) - longident_loc od.popen_lid + longident_loc od.popen_expr (item_attributes ctxt) od.popen_attributes | Psig_include incl -> pp f "@[include@ %a@]%a" @@ -1212,6 +1276,10 @@ and bindings ctxt f (rf,l) = (binding "let" rf) x (list ~sep:"@," (binding "and" Nonrecursive)) xs +and binding_op ctxt f x = + pp f "@[<2>%s %a@;=@;%a@]" + x.pbop_op.txt (pattern ctxt) x.pbop_pat (expression ctxt) x.pbop_exp + and structure_item ctxt f x = match x.pstr_desc with | Pstr_eval (e, attrs) -> @@ -1219,7 +1287,7 @@ and structure_item ctxt f x = (expression ctxt) e (item_attributes ctxt) attrs | Pstr_type (_, []) -> assert false - | Pstr_type (rf, l) -> type_def_list ctxt f (rf, l) + | Pstr_type (rf, l) -> type_def_list ctxt f (rf, true, l) | Pstr_value (rf, l) -> (* pp f "@[let %a%a@]" rec_flag rf bindings l *) pp f "@[<2>%a@]" (bindings ctxt) (rf,l) @@ -1252,7 +1320,7 @@ and structure_item ctxt f x = | Pstr_open od -> pp f "@[<2>open%s@;%a@]%a" (override od.popen_override) - longident_loc od.popen_lid + (module_expr ctxt) od.popen_expr (item_attributes ctxt) od.popen_attributes | Pstr_modtype {pmtd_name=s; pmtd_type=md; pmtd_attributes=attrs} -> pp f "@[module@ type@ %s%a@]%a" @@ -1341,12 +1409,13 @@ and type_params ctxt f = function | [] -> () | l -> pp f "%a " (list (type_param ctxt) ~first:"(" ~last:")" ~sep:",@;") l -and type_def_list ctxt f (rf, l) = +and type_def_list ctxt f (rf, exported, l) = let type_decl kwd rf f x = let eq = if (x.ptype_kind = Ptype_abstract) && (x.ptype_manifest = None) then "" - else " =" + else if exported then " =" + else " :=" in pp f "@[<2>%s %a%a%s%s%a@]%a" kwd nonrec_flag rf @@ -1501,8 +1570,7 @@ and label_x_expression_param ctxt f (l,e) = pp f "~%s:%a" lbl (simple_expr ctxt) e and directive_argument f x = - match x with - | Pdir_none -> () + match x.pdira_desc with | Pdir_string (s) -> pp f "@ %S" s | Pdir_int (n, None) -> pp f "@ %s" n | Pdir_int (n, Some m) -> pp f "@ %s%c" n m @@ -1515,9 +1583,10 @@ let toplevel_phrase f x = (* pp_open_hvbox f 0; *) (* pp_print_list structure_item f s ; *) (* pp_close_box f (); *) - | Ptop_dir (s, da) -> - pp f "@[#%s@ %a@]" s directive_argument da - (* pp f "@[#%s@ %a@]" s directive_argument da *) + | Ptop_dir {pdir_name; pdir_arg = None; _} -> + pp f "@[#%s@]" pdir_name.txt + | Ptop_dir {pdir_name; pdir_arg = Some pdir_arg; _} -> + pp f "@[#%s@ %a@]" pdir_name.txt directive_argument pdir_arg let expression f x = pp f "@[%a@]" (expression reset_ctxt) x diff --git a/parsing/pprintast.mli b/parsing/pprintast.mli index 60f57cf4..454e60e2 100644 --- a/parsing/pprintast.mli +++ b/parsing/pprintast.mli @@ -13,14 +13,32 @@ (* *) (**************************************************************************) + +(** Pretty-printers for {!Parsetree} + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) + type space_formatter = (unit, Format.formatter, unit) format -val toplevel_phrase : Format.formatter -> Parsetree.toplevel_phrase -> unit +val longident : Format.formatter -> Longident.t -> unit val expression : Format.formatter -> Parsetree.expression -> unit val string_of_expression : Parsetree.expression -> string -val top_phrase: Format.formatter -> Parsetree.toplevel_phrase -> unit -val core_type: Format.formatter -> Parsetree.core_type -> unit + val pattern: Format.formatter -> Parsetree.pattern -> unit + +val core_type: Format.formatter -> Parsetree.core_type -> unit + val signature: Format.formatter -> Parsetree.signature -> unit val structure: Format.formatter -> Parsetree.structure -> unit val string_of_structure: Parsetree.structure -> string + +val toplevel_phrase : Format.formatter -> Parsetree.toplevel_phrase -> unit +val top_phrase: Format.formatter -> Parsetree.toplevel_phrase -> unit + + +val tyvar: Format.formatter -> string -> unit + (** Print a type variable name, taking care of the special treatment + required for the single quote character in second position. *) diff --git a/parsing/printast.ml b/parsing/printast.ml index 62ccc04b..fbc0e1ad 100644 --- a/parsing/printast.ml +++ b/parsing/printast.ml @@ -163,11 +163,11 @@ let rec core_type i ppf x = | Ptyp_object (l, c) -> line i ppf "Ptyp_object %a\n" fmt_closed_flag c; let i = i + 1 in - List.iter ( - function - | Otag (l, attrs, t) -> + List.iter (fun field -> + match field.pof_desc with + | Otag (l, t) -> line i ppf "method %s\n" l.txt; - attributes i ppf attrs; + attributes i ppf field.pof_attributes; core_type (i + 1) ppf t | Oinherit ct -> line i ppf "Oinherit\n"; @@ -181,7 +181,10 @@ let rec core_type i ppf x = core_type i ppf ct; | Ptyp_poly (sl, ct) -> line i ppf "Ptyp_poly%a\n" - (fun ppf -> List.iter (fun x -> fprintf ppf " '%s" x.txt)) sl; + (fun ppf -> + List.iter (fun x -> fprintf ppf " %a" Pprintast.tyvar x.txt) + ) + sl; core_type i ppf ct; | Ptyp_package (s, l) -> line i ppf "Ptyp_package %a\n" fmt_longident_loc s; @@ -370,10 +373,15 @@ and expression i ppf x = | Pexp_pack me -> line i ppf "Pexp_pack\n"; module_expr i ppf me - | Pexp_open (ovf, m, e) -> - line i ppf "Pexp_open %a \"%a\"\n" fmt_override_flag ovf - fmt_longident_loc m; + | Pexp_open (o, e) -> + line i ppf "Pexp_open %a\n" fmt_override_flag o.popen_override; + module_expr i ppf o.popen_expr; expression i ppf e + | Pexp_letop {let_; ands; body} -> + line i ppf "Pexp_letop\n"; + binding_op i ppf let_; + list i binding_op ppf ands; + expression i ppf body | Pexp_extension (s, arg) -> line i ppf "Pexp_extension \"%s\"\n" s.txt; payload i ppf arg @@ -404,14 +412,16 @@ and type_declaration i ppf x = line i ppf "ptype_manifest =\n"; option (i+1) core_type ppf x.ptype_manifest +and attribute i ppf k a = + line i ppf "%s \"%s\"\n" k a.attr_name.txt; + payload i ppf a.attr_payload; + and attributes i ppf l = let i = i + 1 in - List.iter - (fun (s, arg) -> - line i ppf "attribute \"%s\"\n" s.txt; - payload (i + 1) ppf arg; - ) - l + List.iter (fun a -> + line i ppf "attribute \"%s\"\n" a.attr_name.txt; + payload (i + 1) ppf a.attr_payload; + ) l; and payload i ppf = function | PStr x -> structure i ppf x @@ -448,6 +458,14 @@ and type_extension i ppf x = list (i+1) extension_constructor ppf x.ptyext_constructors; line i ppf "ptyext_private = %a\n" fmt_private_flag x.ptyext_private; +and type_exception i ppf x = + line i ppf "type_exception\n"; + attributes i ppf x.ptyexn_attributes; + let i = i+1 in + line i ppf "ptyext_constructor =\n"; + let i = i+1 in + extension_constructor i ppf x.ptyexn_constructor + and extension_constructor i ppf x = line i ppf "extension_constructor %a\n" fmt_location x.pext_loc; attributes i ppf x.pext_attributes; @@ -485,9 +503,9 @@ and class_type i ppf x = | Pcty_extension (s, arg) -> line i ppf "Pcty_extension \"%s\"\n" s.txt; payload i ppf arg - | Pcty_open (ovf, m, e) -> - line i ppf "Pcty_open %a \"%a\"\n" fmt_override_flag ovf - fmt_longident_loc m; + | Pcty_open (o, e) -> + line i ppf "Pcty_open %a %a\n" fmt_override_flag o.popen_override + fmt_longident_loc o.popen_expr; class_type i ppf e and class_signature i ppf cs = @@ -515,9 +533,8 @@ and class_type_field i ppf x = line i ppf "Pctf_constraint\n"; core_type (i+1) ppf ct1; core_type (i+1) ppf ct2; - | Pctf_attribute (s, arg) -> - line i ppf "Pctf_attribute \"%s\"\n" s.txt; - payload i ppf arg + | Pctf_attribute a -> + attribute i ppf "Pctf_attribute" a | Pctf_extension (s, arg) -> line i ppf "Pctf_extension \"%s\"\n" s.txt; payload i ppf arg @@ -576,9 +593,9 @@ and class_expr i ppf x = | Pcl_extension (s, arg) -> line i ppf "Pcl_extension \"%s\"\n" s.txt; payload i ppf arg - | Pcl_open (ovf, m, e) -> - line i ppf "Pcl_open %a \"%a\"\n" fmt_override_flag ovf - fmt_longident_loc m; + | Pcl_open (o, e) -> + line i ppf "Pcl_open %a %a\n" fmt_override_flag o.popen_override + fmt_longident_loc o.popen_expr; class_expr i ppf e and class_structure i ppf { pcstr_self = p; pcstr_fields = l } = @@ -610,9 +627,8 @@ and class_field i ppf x = | Pcf_initializer (e) -> line i ppf "Pcf_initializer\n"; expression (i+1) ppf e; - | Pcf_attribute (s, arg) -> - line i ppf "Pcf_attribute \"%s\"\n" s.txt; - payload i ppf arg + | Pcf_attribute a -> + attribute i ppf "Pcf_attribute" a | Pcf_extension (s, arg) -> line i ppf "Pcf_extension \"%s\"\n" s.txt; payload i ppf arg @@ -673,16 +689,24 @@ and signature_item i ppf x = | Psig_type (rf, l) -> line i ppf "Psig_type %a\n" fmt_rec_flag rf; list i type_declaration ppf l; + | Psig_typesubst l -> + line i ppf "Psig_typesubst\n"; + list i type_declaration ppf l; | Psig_typext te -> line i ppf "Psig_typext\n"; type_extension i ppf te - | Psig_exception ext -> + | Psig_exception te -> line i ppf "Psig_exception\n"; - extension_constructor i ppf ext; + type_exception i ppf te | Psig_module pmd -> line i ppf "Psig_module %a\n" fmt_string_loc pmd.pmd_name; attributes i ppf pmd.pmd_attributes; module_type i ppf pmd.pmd_type + | Psig_modsubst pms -> + line i ppf "Psig_modsubst %a = %a\n" + fmt_string_loc pms.pms_name + fmt_longident_loc pms.pms_manifest; + attributes i ppf pms.pms_attributes; | Psig_recmodule decls -> line i ppf "Psig_recmodule\n"; list i module_declaration ppf decls; @@ -691,9 +715,8 @@ and signature_item i ppf x = attributes i ppf x.pmtd_attributes; modtype_declaration i ppf x.pmtd_type | Psig_open od -> - line i ppf "Psig_open %a %a\n" - fmt_override_flag od.popen_override - fmt_longident_loc od.popen_lid; + line i ppf "Psig_open %a %a\n" fmt_override_flag od.popen_override + fmt_longident_loc od.popen_expr; attributes i ppf od.popen_attributes | Psig_include incl -> line i ppf "Psig_include\n"; @@ -709,9 +732,8 @@ and signature_item i ppf x = line i ppf "Psig_extension \"%s\"\n" s.txt; attributes i ppf attrs; payload i ppf arg - | Psig_attribute (s, arg) -> - line i ppf "Psig_attribute \"%s\"\n" s.txt; - payload i ppf arg + | Psig_attribute a -> + attribute i ppf "Psig_attribute" a and modtype_declaration i ppf = function | None -> line i ppf "#abstract" @@ -784,9 +806,9 @@ and structure_item i ppf x = | Pstr_typext te -> line i ppf "Pstr_typext\n"; type_extension i ppf te - | Pstr_exception ext -> + | Pstr_exception te -> line i ppf "Pstr_exception\n"; - extension_constructor i ppf ext; + type_exception i ppf te | Pstr_module x -> line i ppf "Pstr_module\n"; module_binding i ppf x @@ -798,9 +820,8 @@ and structure_item i ppf x = attributes i ppf x.pmtd_attributes; modtype_declaration i ppf x.pmtd_type | Pstr_open od -> - line i ppf "Pstr_open %a %a\n" - fmt_override_flag od.popen_override - fmt_longident_loc od.popen_lid; + line i ppf "Pstr_open %a\n" fmt_override_flag od.popen_override; + module_expr i ppf od.popen_expr; attributes i ppf od.popen_attributes | Pstr_class (l) -> line i ppf "Pstr_class\n"; @@ -816,9 +837,8 @@ and structure_item i ppf x = line i ppf "Pstr_extension \"%s\"\n" s.txt; attributes i ppf attrs; payload i ppf arg - | Pstr_attribute (s, arg) -> - line i ppf "Pstr_attribute \"%s\"\n" s.txt; - payload i ppf arg + | Pstr_attribute a -> + attribute i ppf "Pstr_attribute" a and module_declaration i ppf pmd = string_loc i ppf pmd.pmd_name; @@ -873,6 +893,12 @@ and value_binding i ppf x = pattern (i+1) ppf x.pvb_pat; expression (i+1) ppf x.pvb_expr +and binding_op i ppf x = + line i ppf " %a %a" + fmt_string_loc x.pbop_op fmt_location x.pbop_loc; + pattern (i+1) ppf x.pbop_pat; + expression (i+1) ppf x.pbop_exp; + and string_x_expression i ppf (s, e) = line i ppf " %a\n" fmt_string_loc s; expression (i+1) ppf e; @@ -887,10 +913,10 @@ and label_x_expression i ppf (l,e) = expression (i+1) ppf e; and label_x_bool_x_core_type_list i ppf x = - match x with - Rtag (l, attrs, b, ctl) -> + match x.prf_desc with + Rtag (l, b, ctl) -> line i ppf "Rtag \"%s\" %s\n" l.txt (string_of_bool b); - attributes (i+1) ppf attrs; + attributes (i+1) ppf x.prf_attributes; list (i+1) core_type ppf ctl | Rinherit (ct) -> line i ppf "Rinherit\n"; @@ -902,13 +928,14 @@ let rec toplevel_phrase i ppf x = | Ptop_def (s) -> line i ppf "Ptop_def\n"; structure (i+1) ppf s; - | Ptop_dir (s, da) -> - line i ppf "Ptop_dir \"%s\"\n" s; - directive_argument i ppf da; + | Ptop_dir {pdir_name; pdir_arg; _} -> + line i ppf "Ptop_dir \"%s\"\n" pdir_name.txt; + match pdir_arg with + | None -> () + | Some da -> directive_argument i ppf da; and directive_argument i ppf x = - match x with - | Pdir_none -> line i ppf "Pdir_none\n" + match x.pdira_desc with | Pdir_string (s) -> line i ppf "Pdir_string \"%s\"\n" s; | Pdir_int (n, None) -> line i ppf "Pdir_int %s\n" n; | Pdir_int (n, Some m) -> line i ppf "Pdir_int %s%c\n" n m; diff --git a/parsing/printast.mli b/parsing/printast.mli index b77a2ca5..82156548 100644 --- a/parsing/printast.mli +++ b/parsing/printast.mli @@ -13,6 +13,13 @@ (* *) (**************************************************************************) +(** Raw printer for {!Parsetree} + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) + open Parsetree;; open Format;; diff --git a/parsing/syntaxerr.ml b/parsing/syntaxerr.ml index 0bb55ab6..49372b9e 100644 --- a/parsing/syntaxerr.ml +++ b/parsing/syntaxerr.ml @@ -28,50 +28,6 @@ type error = exception Error of error exception Escape_error -let prepare_error = function - | Unclosed(opening_loc, opening, closing_loc, closing) -> - Location.errorf ~loc:closing_loc - ~sub:[ - Location.errorf ~loc:opening_loc - "This '%s' might be unmatched" opening - ] - ~if_highlight: - (Printf.sprintf "Syntax error: '%s' expected, \ - the highlighted '%s' might be unmatched" - closing opening) - "Syntax error: '%s' expected" closing - - | Expecting (loc, nonterm) -> - Location.errorf ~loc "Syntax error: %s expected." nonterm - | Not_expecting (loc, nonterm) -> - Location.errorf ~loc "Syntax error: %s not expected." nonterm - | Applicative_path loc -> - Location.errorf ~loc - "Syntax error: applicative paths of the form F(X).t \ - are not supported when the option -no-app-func is set." - | Variable_in_scope (loc, var) -> - Location.errorf ~loc - "In this scoped type, variable '%s \ - is reserved for the local type %s." - var var - | Other loc -> - Location.errorf ~loc "Syntax error" - | Ill_formed_ast (loc, s) -> - Location.errorf ~loc "broken invariant in parsetree: %s" s - | Invalid_package_type (loc, s) -> - Location.errorf ~loc "invalid package type: %s" s - -let () = - Location.register_error_of_exn - (function - | Error err -> Some (prepare_error err) - | _ -> None - ) - - -let report_error ppf err = - Location.report_error ppf (prepare_error err) - let location_of_error = function | Unclosed(l,_,_,_) | Applicative_path l diff --git a/parsing/syntaxerr.mli b/parsing/syntaxerr.mli index 319eb579..26ba7126 100644 --- a/parsing/syntaxerr.mli +++ b/parsing/syntaxerr.mli @@ -13,9 +13,12 @@ (* *) (**************************************************************************) -(** Auxiliary type for reporting syntax errors *) +(** Auxiliary type for reporting syntax errors -open Format + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) type error = Unclosed of Location.t * string * Location.t * string @@ -30,8 +33,5 @@ type error = exception Error of error exception Escape_error -val report_error: formatter -> error -> unit - (** @deprecated Use {!Location.error_of_exn}, {!Location.report_error}. *) - val location_of_error: error -> Location.t val ill_formed_ast: Location.t -> string -> 'a diff --git a/runtime/.depend b/runtime/.depend new file mode 100644 index 00000000..2567f409 --- /dev/null +++ b/runtime/.depend @@ -0,0 +1,2178 @@ +afl_b.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +alloc_b.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/stacks.h +array_b.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ + caml/spacetime.h caml/io.h caml/stack.h +backtrace_b.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ + caml/exec.h caml/backtrace_prim.h caml/fail.h +backtrace_byt_b.$(O): backtrace_byt.c caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \ + caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \ + caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h +backtrace_nat_b.$(O): backtrace_nat.c caml/alloc.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/backtrace_prim.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h +bigarray_b.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \ + caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/signals.h +callback_b.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h +clambda_checks_b.$(O): clambda_checks.c caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h +compact_b.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/gc_ctrl.h caml/weak.h caml/compact.h +compare_b.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +custom_b.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc_ctrl.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h +debugger_b.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/fail.h caml/fix_code.h caml/instruct.h \ + caml/intext.h caml/io.h caml/stacks.h caml/sys.h +dynlink_b.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h +dynlink_nat_b.$(O): dynlink_nat.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h \ + caml/callback.h caml/alloc.h caml/intext.h caml/io.h caml/osdeps.h \ + caml/fail.h caml/signals.h caml/hooks.h +extern_b.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h +fail_byt_b.$(O): fail_byt.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stacks.h +fail_nat_b.$(O): fail_nat.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stack.h caml/roots.h \ + caml/callback.h +finalise_b.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h +fix_code_b.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \ + caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +floats_b.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h caml/stacks.h +freelist_b.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \ + caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h +gc_ctrl_b.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ + caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \ + caml/startup_aux.h +globroots_b.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \ + caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h +hash_b.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h +instrtrace_b.$(O): instrtrace.c +intern_b.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \ + caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +interp_b.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ + caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \ + caml/jumptbl.h +ints_b.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +io_b.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h +lexing_b.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +main_b.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +major_gc_b.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \ + caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +md5_b.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/reverse.h +memory_b.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ + caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ + caml/signals.h +meta_b.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ + caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ + caml/stacks.h caml/backtrace_prim.h caml/backtrace.h caml/exec.h +minor_gc_b.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +misc_b.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \ + caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h +obj_b.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \ + caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/spacetime.h caml/io.h caml/stack.h +parsing_b.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \ + caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/alloc.h +prims_b.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/prims.h +printexc_b.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +roots_byt_b.$(O): roots_byt.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stacks.h +roots_nat_b.$(O): roots_nat.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stack.h +signals_b.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/roots.h caml/signals.h \ + caml/signals_machdep.h caml/sys.h +signals_byt_b.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \ + caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/signals_machdep.h +signals_nat_b.$(O): signals_nat.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/signals.h caml/signals_machdep.h signals_osdep.h \ + caml/stack.h caml/spacetime.h caml/io.h +spacetime_byt_b.$(O): spacetime_byt.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h +spacetime_nat_b.$(O): spacetime_nat.c caml/config.h caml/m.h caml/s.h \ + caml/alloc.h caml/misc.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/fail.h caml/gc.h caml/intext.h \ + caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +spacetime_snapshot_b.$(O): spacetime_snapshot.c caml/alloc.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/custom.h caml/fail.h caml/gc.h \ + caml/gc_ctrl.h caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/minor_gc.h caml/address_class.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +stacks_b.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \ + caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +startup_aux_b.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/callback.h caml/dynlink.h caml/osdeps.h \ + caml/startup_aux.h +startup_byt_b.$(O): startup_byt.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \ + caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \ + caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \ + caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \ + caml/startup_aux.h caml/version.h +startup_nat_b.$(O): startup_nat.c caml/callback.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/backtrace.h \ + caml/exec.h caml/custom.h caml/debugger.h caml/fail.h caml/freelist.h \ + caml/gc.h caml/gc_ctrl.h caml/intext.h caml/io.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/printexc.h caml/stack.h caml/startup_aux.h caml/sys.h +str_b.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h +sys_b.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \ + caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h +unix_b.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/sys.h caml/io.h caml/alloc.h +weak_b.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/weak.h caml/signals.h +afl_bd.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +alloc_bd.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/stacks.h +array_bd.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ + caml/spacetime.h caml/io.h caml/stack.h +backtrace_bd.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ + caml/exec.h caml/backtrace_prim.h caml/fail.h +backtrace_byt_bd.$(O): backtrace_byt.c caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \ + caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \ + caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h +backtrace_nat_bd.$(O): backtrace_nat.c caml/alloc.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/backtrace_prim.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h +bigarray_bd.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \ + caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/signals.h +callback_bd.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h +clambda_checks_bd.$(O): clambda_checks.c caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h +compact_bd.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/gc_ctrl.h caml/weak.h caml/compact.h +compare_bd.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +custom_bd.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc_ctrl.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h +debugger_bd.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/fail.h caml/fix_code.h caml/instruct.h \ + caml/intext.h caml/io.h caml/stacks.h caml/sys.h +dynlink_bd.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h +dynlink_nat_bd.$(O): dynlink_nat.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h \ + caml/callback.h caml/alloc.h caml/intext.h caml/io.h caml/osdeps.h \ + caml/fail.h caml/signals.h caml/hooks.h +extern_bd.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h +fail_byt_bd.$(O): fail_byt.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stacks.h +fail_nat_bd.$(O): fail_nat.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stack.h caml/roots.h \ + caml/callback.h +finalise_bd.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h +fix_code_bd.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \ + caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +floats_bd.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h caml/stacks.h +freelist_bd.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \ + caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h +gc_ctrl_bd.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ + caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \ + caml/startup_aux.h +globroots_bd.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \ + caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h +hash_bd.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h +instrtrace_bd.$(O): instrtrace.c caml/instrtrace.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/instruct.h \ + caml/opnames.h caml/prims.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/startup_aux.h +intern_bd.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \ + caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +interp_bd.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ + caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h +ints_bd.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +io_bd.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h +lexing_bd.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +main_bd.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +major_gc_bd.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \ + caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +md5_bd.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/reverse.h +memory_bd.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ + caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ + caml/signals.h +meta_bd.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ + caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ + caml/stacks.h caml/backtrace_prim.h caml/backtrace.h caml/exec.h +minor_gc_bd.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +misc_bd.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \ + caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h +obj_bd.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \ + caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/spacetime.h caml/io.h caml/stack.h +parsing_bd.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \ + caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/alloc.h +prims_bd.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/prims.h +printexc_bd.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +roots_byt_bd.$(O): roots_byt.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stacks.h +roots_nat_bd.$(O): roots_nat.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stack.h +signals_bd.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/roots.h caml/signals.h \ + caml/signals_machdep.h caml/sys.h +signals_byt_bd.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \ + caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/signals_machdep.h +signals_nat_bd.$(O): signals_nat.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/signals.h caml/signals_machdep.h signals_osdep.h \ + caml/stack.h caml/spacetime.h caml/io.h +spacetime_byt_bd.$(O): spacetime_byt.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h +spacetime_nat_bd.$(O): spacetime_nat.c caml/config.h caml/m.h caml/s.h \ + caml/alloc.h caml/misc.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/fail.h caml/gc.h caml/intext.h \ + caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +spacetime_snapshot_bd.$(O): spacetime_snapshot.c caml/alloc.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/custom.h caml/fail.h caml/gc.h \ + caml/gc_ctrl.h caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/minor_gc.h caml/address_class.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +stacks_bd.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \ + caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +startup_aux_bd.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/callback.h caml/dynlink.h caml/osdeps.h \ + caml/startup_aux.h +startup_byt_bd.$(O): startup_byt.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \ + caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \ + caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \ + caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \ + caml/startup_aux.h caml/version.h +startup_nat_bd.$(O): startup_nat.c caml/callback.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/backtrace.h \ + caml/exec.h caml/custom.h caml/debugger.h caml/fail.h caml/freelist.h \ + caml/gc.h caml/gc_ctrl.h caml/intext.h caml/io.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/printexc.h caml/stack.h caml/startup_aux.h caml/sys.h +str_bd.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h +sys_bd.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \ + caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h +unix_bd.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/sys.h caml/io.h caml/alloc.h +weak_bd.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/weak.h caml/signals.h +afl_bi.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +alloc_bi.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/stacks.h +array_bi.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ + caml/spacetime.h caml/io.h caml/stack.h +backtrace_bi.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ + caml/exec.h caml/backtrace_prim.h caml/fail.h +backtrace_byt_bi.$(O): backtrace_byt.c caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \ + caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \ + caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h +backtrace_nat_bi.$(O): backtrace_nat.c caml/alloc.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/backtrace_prim.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h +bigarray_bi.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \ + caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/signals.h +callback_bi.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h +clambda_checks_bi.$(O): clambda_checks.c caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h +compact_bi.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/gc_ctrl.h caml/weak.h caml/compact.h +compare_bi.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +custom_bi.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc_ctrl.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h +debugger_bi.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/fail.h caml/fix_code.h caml/instruct.h \ + caml/intext.h caml/io.h caml/stacks.h caml/sys.h +dynlink_bi.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h +dynlink_nat_bi.$(O): dynlink_nat.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h \ + caml/callback.h caml/alloc.h caml/intext.h caml/io.h caml/osdeps.h \ + caml/fail.h caml/signals.h caml/hooks.h +extern_bi.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h +fail_byt_bi.$(O): fail_byt.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stacks.h +fail_nat_bi.$(O): fail_nat.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stack.h caml/roots.h \ + caml/callback.h +finalise_bi.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h +fix_code_bi.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \ + caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +floats_bi.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h caml/stacks.h +freelist_bi.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \ + caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h +gc_ctrl_bi.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ + caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \ + caml/startup_aux.h +globroots_bi.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \ + caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h +hash_bi.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h +instrtrace_bi.$(O): instrtrace.c +intern_bi.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \ + caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +interp_bi.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ + caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \ + caml/jumptbl.h +ints_bi.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +io_bi.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h +lexing_bi.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +main_bi.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +major_gc_bi.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \ + caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +md5_bi.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/reverse.h +memory_bi.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ + caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ + caml/signals.h +meta_bi.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ + caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ + caml/stacks.h caml/backtrace_prim.h caml/backtrace.h caml/exec.h +minor_gc_bi.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +misc_bi.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \ + caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h +obj_bi.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \ + caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/spacetime.h caml/io.h caml/stack.h +parsing_bi.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \ + caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/alloc.h +prims_bi.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/prims.h +printexc_bi.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +roots_byt_bi.$(O): roots_byt.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stacks.h +roots_nat_bi.$(O): roots_nat.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stack.h +signals_bi.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/roots.h caml/signals.h \ + caml/signals_machdep.h caml/sys.h +signals_byt_bi.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \ + caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/signals_machdep.h +signals_nat_bi.$(O): signals_nat.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/signals.h caml/signals_machdep.h signals_osdep.h \ + caml/stack.h caml/spacetime.h caml/io.h +spacetime_byt_bi.$(O): spacetime_byt.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h +spacetime_nat_bi.$(O): spacetime_nat.c caml/config.h caml/m.h caml/s.h \ + caml/alloc.h caml/misc.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/fail.h caml/gc.h caml/intext.h \ + caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +spacetime_snapshot_bi.$(O): spacetime_snapshot.c caml/alloc.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/custom.h caml/fail.h caml/gc.h \ + caml/gc_ctrl.h caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/minor_gc.h caml/address_class.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +stacks_bi.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \ + caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +startup_aux_bi.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/callback.h caml/dynlink.h caml/osdeps.h \ + caml/startup_aux.h +startup_byt_bi.$(O): startup_byt.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \ + caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \ + caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \ + caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \ + caml/startup_aux.h caml/version.h +startup_nat_bi.$(O): startup_nat.c caml/callback.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/backtrace.h \ + caml/exec.h caml/custom.h caml/debugger.h caml/fail.h caml/freelist.h \ + caml/gc.h caml/gc_ctrl.h caml/intext.h caml/io.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/printexc.h caml/stack.h caml/startup_aux.h caml/sys.h +str_bi.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h +sys_bi.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \ + caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h +unix_bi.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/sys.h caml/io.h caml/alloc.h +weak_bi.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/weak.h caml/signals.h +afl_bpic.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +alloc_bpic.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/stacks.h +array_bpic.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ + caml/spacetime.h caml/io.h caml/stack.h +backtrace_bpic.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ + caml/exec.h caml/backtrace_prim.h caml/fail.h +backtrace_byt_bpic.$(O): backtrace_byt.c caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \ + caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \ + caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h +backtrace_nat_bpic.$(O): backtrace_nat.c caml/alloc.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/backtrace_prim.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h +bigarray_bpic.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \ + caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/signals.h +callback_bpic.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/interp.h caml/instruct.h caml/fix_code.h caml/stacks.h +clambda_checks_bpic.$(O): clambda_checks.c caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h +compact_bpic.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/gc_ctrl.h caml/weak.h caml/compact.h +compare_bpic.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +custom_bpic.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc_ctrl.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h +debugger_bpic.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/fail.h caml/fix_code.h caml/instruct.h \ + caml/intext.h caml/io.h caml/stacks.h caml/sys.h +dynlink_bpic.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h +dynlink_nat_bpic.$(O): dynlink_nat.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h \ + caml/callback.h caml/alloc.h caml/intext.h caml/io.h caml/osdeps.h \ + caml/fail.h caml/signals.h caml/hooks.h +extern_bpic.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h +fail_byt_bpic.$(O): fail_byt.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stacks.h +fail_nat_bpic.$(O): fail_nat.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stack.h caml/roots.h \ + caml/callback.h +finalise_bpic.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h +fix_code_bpic.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \ + caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +floats_bpic.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h caml/stacks.h +freelist_bpic.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \ + caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h +gc_ctrl_bpic.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ + caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stacks.h \ + caml/startup_aux.h +globroots_bpic.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \ + caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h +hash_bpic.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h +instrtrace_bpic.$(O): instrtrace.c +intern_bpic.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \ + caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +interp_bpic.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ + caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \ + caml/jumptbl.h +ints_bpic.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +io_bpic.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h +lexing_bpic.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +main_bpic.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +major_gc_bpic.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \ + caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +md5_bpic.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/reverse.h +memory_bpic.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ + caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ + caml/signals.h +meta_bpic.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ + caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ + caml/stacks.h caml/backtrace_prim.h caml/backtrace.h caml/exec.h +minor_gc_bpic.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +misc_bpic.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \ + caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h +obj_bpic.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \ + caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/spacetime.h caml/io.h caml/stack.h +parsing_bpic.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \ + caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/alloc.h +prims_bpic.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/prims.h +printexc_bpic.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +roots_byt_bpic.$(O): roots_byt.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stacks.h +roots_nat_bpic.$(O): roots_nat.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stack.h +signals_bpic.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/roots.h caml/signals.h \ + caml/signals_machdep.h caml/sys.h +signals_byt_bpic.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \ + caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/signals_machdep.h +signals_nat_bpic.$(O): signals_nat.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/signals.h caml/signals_machdep.h signals_osdep.h \ + caml/stack.h caml/spacetime.h caml/io.h +spacetime_byt_bpic.$(O): spacetime_byt.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h +spacetime_nat_bpic.$(O): spacetime_nat.c caml/config.h caml/m.h caml/s.h \ + caml/alloc.h caml/misc.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/fail.h caml/gc.h caml/intext.h \ + caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +spacetime_snapshot_bpic.$(O): spacetime_snapshot.c caml/alloc.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/custom.h caml/fail.h caml/gc.h \ + caml/gc_ctrl.h caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/minor_gc.h caml/address_class.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +stacks_bpic.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \ + caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +startup_aux_bpic.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/callback.h caml/dynlink.h caml/osdeps.h \ + caml/startup_aux.h +startup_byt_bpic.$(O): startup_byt.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \ + caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \ + caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \ + caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \ + caml/startup_aux.h caml/version.h +startup_nat_bpic.$(O): startup_nat.c caml/callback.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/backtrace.h \ + caml/exec.h caml/custom.h caml/debugger.h caml/fail.h caml/freelist.h \ + caml/gc.h caml/gc_ctrl.h caml/intext.h caml/io.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/printexc.h caml/stack.h caml/startup_aux.h caml/sys.h +str_bpic.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h +sys_bpic.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \ + caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h +unix_bpic.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/sys.h caml/io.h caml/alloc.h +weak_bpic.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/weak.h caml/signals.h +afl_n.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +alloc_n.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/stacks.h +array_n.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ + caml/spacetime.h caml/io.h caml/stack.h +backtrace_n.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ + caml/exec.h caml/backtrace_prim.h caml/fail.h +backtrace_byt_n.$(O): backtrace_byt.c caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \ + caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \ + caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h +backtrace_nat_n.$(O): backtrace_nat.c caml/alloc.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/backtrace_prim.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h +bigarray_n.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \ + caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/signals.h +callback_n.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +clambda_checks_n.$(O): clambda_checks.c caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h +compact_n.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/gc_ctrl.h caml/weak.h caml/compact.h +compare_n.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +custom_n.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc_ctrl.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h +debugger_n.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h +dynlink_n.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h +dynlink_nat_n.$(O): dynlink_nat.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h \ + caml/callback.h caml/alloc.h caml/intext.h caml/io.h caml/osdeps.h \ + caml/fail.h caml/signals.h caml/hooks.h +extern_n.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h +fail_byt_n.$(O): fail_byt.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stacks.h +fail_nat_n.$(O): fail_nat.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stack.h caml/roots.h \ + caml/callback.h +finalise_n.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h +fix_code_n.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \ + caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +floats_n.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h caml/stacks.h +freelist_n.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \ + caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h +gc_ctrl_n.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ + caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stack.h \ + caml/startup_aux.h +globroots_n.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \ + caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h +hash_n.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h +instrtrace_n.$(O): instrtrace.c +intern_n.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \ + caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +interp_n.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ + caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \ + caml/jumptbl.h +ints_n.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +io_n.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h +lexing_n.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +main_n.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +major_gc_n.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \ + caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +md5_n.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/reverse.h +memory_n.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ + caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ + caml/signals.h +meta_n.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ + caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ + caml/stacks.h caml/backtrace_prim.h caml/backtrace.h caml/exec.h +minor_gc_n.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +misc_n.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \ + caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h +obj_n.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \ + caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/spacetime.h caml/io.h caml/stack.h +parsing_n.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \ + caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/alloc.h +prims_n.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/prims.h +printexc_n.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +roots_byt_n.$(O): roots_byt.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stacks.h +roots_nat_n.$(O): roots_nat.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stack.h +signals_n.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/roots.h caml/signals.h \ + caml/signals_machdep.h caml/sys.h +signals_byt_n.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \ + caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/signals_machdep.h +signals_nat_n.$(O): signals_nat.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/signals.h caml/signals_machdep.h signals_osdep.h \ + caml/stack.h caml/spacetime.h caml/io.h +spacetime_byt_n.$(O): spacetime_byt.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h +spacetime_nat_n.$(O): spacetime_nat.c caml/config.h caml/m.h caml/s.h \ + caml/alloc.h caml/misc.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/fail.h caml/gc.h caml/intext.h \ + caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +spacetime_snapshot_n.$(O): spacetime_snapshot.c caml/alloc.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/custom.h caml/fail.h caml/gc.h \ + caml/gc_ctrl.h caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/minor_gc.h caml/address_class.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +stacks_n.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \ + caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +startup_aux_n.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/callback.h caml/osdeps.h caml/startup_aux.h +startup_byt_n.$(O): startup_byt.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \ + caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \ + caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \ + caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \ + caml/startup_aux.h caml/version.h +startup_nat_n.$(O): startup_nat.c caml/callback.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/backtrace.h \ + caml/exec.h caml/custom.h caml/debugger.h caml/fail.h caml/freelist.h \ + caml/gc.h caml/gc_ctrl.h caml/intext.h caml/io.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/printexc.h caml/stack.h caml/startup_aux.h caml/sys.h +str_n.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h +sys_n.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \ + caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h +unix_n.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/sys.h caml/io.h caml/alloc.h +weak_n.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/weak.h caml/signals.h +afl_nd.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +alloc_nd.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/stacks.h +array_nd.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ + caml/spacetime.h caml/io.h caml/stack.h +backtrace_nd.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ + caml/exec.h caml/backtrace_prim.h caml/fail.h +backtrace_byt_nd.$(O): backtrace_byt.c caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \ + caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \ + caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h +backtrace_nat_nd.$(O): backtrace_nat.c caml/alloc.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/backtrace_prim.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h +bigarray_nd.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \ + caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/signals.h +callback_nd.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +clambda_checks_nd.$(O): clambda_checks.c caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h +compact_nd.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/gc_ctrl.h caml/weak.h caml/compact.h +compare_nd.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +custom_nd.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc_ctrl.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h +debugger_nd.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h +dynlink_nd.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h +dynlink_nat_nd.$(O): dynlink_nat.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h \ + caml/callback.h caml/alloc.h caml/intext.h caml/io.h caml/osdeps.h \ + caml/fail.h caml/signals.h caml/hooks.h +extern_nd.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h +fail_byt_nd.$(O): fail_byt.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stacks.h +fail_nat_nd.$(O): fail_nat.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stack.h caml/roots.h \ + caml/callback.h +finalise_nd.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h +fix_code_nd.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \ + caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +floats_nd.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h caml/stacks.h +freelist_nd.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \ + caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h +gc_ctrl_nd.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ + caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stack.h \ + caml/startup_aux.h +globroots_nd.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \ + caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h +hash_nd.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h +instrtrace_nd.$(O): instrtrace.c caml/instrtrace.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/instruct.h \ + caml/opnames.h caml/prims.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/startup_aux.h +intern_nd.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \ + caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +interp_nd.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ + caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h +ints_nd.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +io_nd.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h +lexing_nd.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +main_nd.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +major_gc_nd.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \ + caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +md5_nd.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/reverse.h +memory_nd.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ + caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ + caml/signals.h +meta_nd.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ + caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ + caml/stacks.h caml/backtrace_prim.h caml/backtrace.h caml/exec.h +minor_gc_nd.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +misc_nd.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \ + caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h +obj_nd.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \ + caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/spacetime.h caml/io.h caml/stack.h +parsing_nd.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \ + caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/alloc.h +prims_nd.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/prims.h +printexc_nd.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +roots_byt_nd.$(O): roots_byt.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stacks.h +roots_nat_nd.$(O): roots_nat.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stack.h +signals_nd.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/roots.h caml/signals.h \ + caml/signals_machdep.h caml/sys.h +signals_byt_nd.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \ + caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/signals_machdep.h +signals_nat_nd.$(O): signals_nat.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/signals.h caml/signals_machdep.h signals_osdep.h \ + caml/stack.h caml/spacetime.h caml/io.h +spacetime_byt_nd.$(O): spacetime_byt.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h +spacetime_nat_nd.$(O): spacetime_nat.c caml/config.h caml/m.h caml/s.h \ + caml/alloc.h caml/misc.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/fail.h caml/gc.h caml/intext.h \ + caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +spacetime_snapshot_nd.$(O): spacetime_snapshot.c caml/alloc.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/custom.h caml/fail.h caml/gc.h \ + caml/gc_ctrl.h caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/minor_gc.h caml/address_class.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +stacks_nd.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \ + caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +startup_aux_nd.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/callback.h caml/osdeps.h caml/startup_aux.h +startup_byt_nd.$(O): startup_byt.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \ + caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \ + caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \ + caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \ + caml/startup_aux.h caml/version.h +startup_nat_nd.$(O): startup_nat.c caml/callback.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/backtrace.h \ + caml/exec.h caml/custom.h caml/debugger.h caml/fail.h caml/freelist.h \ + caml/gc.h caml/gc_ctrl.h caml/intext.h caml/io.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/printexc.h caml/stack.h caml/startup_aux.h caml/sys.h +str_nd.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h +sys_nd.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \ + caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h +unix_nd.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/sys.h caml/io.h caml/alloc.h +weak_nd.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/weak.h caml/signals.h +afl_ni.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +alloc_ni.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/stacks.h +array_ni.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ + caml/spacetime.h caml/io.h caml/stack.h +backtrace_ni.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ + caml/exec.h caml/backtrace_prim.h caml/fail.h +backtrace_byt_ni.$(O): backtrace_byt.c caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \ + caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \ + caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h +backtrace_nat_ni.$(O): backtrace_nat.c caml/alloc.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/backtrace_prim.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h +bigarray_ni.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \ + caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/signals.h +callback_ni.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +clambda_checks_ni.$(O): clambda_checks.c caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h +compact_ni.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/gc_ctrl.h caml/weak.h caml/compact.h +compare_ni.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +custom_ni.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc_ctrl.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h +debugger_ni.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h +dynlink_ni.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h +dynlink_nat_ni.$(O): dynlink_nat.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h \ + caml/callback.h caml/alloc.h caml/intext.h caml/io.h caml/osdeps.h \ + caml/fail.h caml/signals.h caml/hooks.h +extern_ni.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h +fail_byt_ni.$(O): fail_byt.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stacks.h +fail_nat_ni.$(O): fail_nat.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stack.h caml/roots.h \ + caml/callback.h +finalise_ni.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h +fix_code_ni.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \ + caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +floats_ni.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h caml/stacks.h +freelist_ni.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \ + caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h +gc_ctrl_ni.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ + caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stack.h \ + caml/startup_aux.h +globroots_ni.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \ + caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h +hash_ni.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h +instrtrace_ni.$(O): instrtrace.c +intern_ni.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \ + caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +interp_ni.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ + caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \ + caml/jumptbl.h +ints_ni.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +io_ni.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h +lexing_ni.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +main_ni.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +major_gc_ni.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \ + caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +md5_ni.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/reverse.h +memory_ni.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ + caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ + caml/signals.h +meta_ni.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ + caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ + caml/stacks.h caml/backtrace_prim.h caml/backtrace.h caml/exec.h +minor_gc_ni.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +misc_ni.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \ + caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h +obj_ni.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \ + caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/spacetime.h caml/io.h caml/stack.h +parsing_ni.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \ + caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/alloc.h +prims_ni.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/prims.h +printexc_ni.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +roots_byt_ni.$(O): roots_byt.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stacks.h +roots_nat_ni.$(O): roots_nat.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stack.h +signals_ni.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/roots.h caml/signals.h \ + caml/signals_machdep.h caml/sys.h +signals_byt_ni.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \ + caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/signals_machdep.h +signals_nat_ni.$(O): signals_nat.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/signals.h caml/signals_machdep.h signals_osdep.h \ + caml/stack.h caml/spacetime.h caml/io.h +spacetime_byt_ni.$(O): spacetime_byt.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h +spacetime_nat_ni.$(O): spacetime_nat.c caml/config.h caml/m.h caml/s.h \ + caml/alloc.h caml/misc.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/fail.h caml/gc.h caml/intext.h \ + caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +spacetime_snapshot_ni.$(O): spacetime_snapshot.c caml/alloc.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/custom.h caml/fail.h caml/gc.h \ + caml/gc_ctrl.h caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/minor_gc.h caml/address_class.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +stacks_ni.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \ + caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +startup_aux_ni.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/callback.h caml/osdeps.h caml/startup_aux.h +startup_byt_ni.$(O): startup_byt.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \ + caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \ + caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \ + caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \ + caml/startup_aux.h caml/version.h +startup_nat_ni.$(O): startup_nat.c caml/callback.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/backtrace.h \ + caml/exec.h caml/custom.h caml/debugger.h caml/fail.h caml/freelist.h \ + caml/gc.h caml/gc_ctrl.h caml/intext.h caml/io.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/printexc.h caml/stack.h caml/startup_aux.h caml/sys.h +str_ni.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h +sys_ni.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \ + caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h +unix_ni.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/sys.h caml/io.h caml/alloc.h +weak_ni.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/weak.h caml/signals.h +afl_np.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +alloc_np.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/stacks.h +array_np.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ + caml/spacetime.h caml/io.h caml/stack.h +backtrace_np.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ + caml/exec.h caml/backtrace_prim.h caml/fail.h +backtrace_byt_np.$(O): backtrace_byt.c caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \ + caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \ + caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h +backtrace_nat_np.$(O): backtrace_nat.c caml/alloc.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/backtrace_prim.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h +bigarray_np.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \ + caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/signals.h +callback_np.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +clambda_checks_np.$(O): clambda_checks.c caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h +compact_np.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/gc_ctrl.h caml/weak.h caml/compact.h +compare_np.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +custom_np.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc_ctrl.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h +debugger_np.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h +dynlink_np.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h +dynlink_nat_np.$(O): dynlink_nat.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h \ + caml/callback.h caml/alloc.h caml/intext.h caml/io.h caml/osdeps.h \ + caml/fail.h caml/signals.h caml/hooks.h +extern_np.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h +fail_byt_np.$(O): fail_byt.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stacks.h +fail_nat_np.$(O): fail_nat.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stack.h caml/roots.h \ + caml/callback.h +finalise_np.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h +fix_code_np.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \ + caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +floats_np.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h caml/stacks.h +freelist_np.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \ + caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h +gc_ctrl_np.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ + caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stack.h \ + caml/startup_aux.h +globroots_np.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \ + caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h +hash_np.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h +instrtrace_np.$(O): instrtrace.c +intern_np.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \ + caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +interp_np.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ + caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \ + caml/jumptbl.h +ints_np.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +io_np.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h +lexing_np.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +main_np.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +major_gc_np.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \ + caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +md5_np.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/reverse.h +memory_np.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ + caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ + caml/signals.h +meta_np.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ + caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ + caml/stacks.h caml/backtrace_prim.h caml/backtrace.h caml/exec.h +minor_gc_np.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +misc_np.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \ + caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h +obj_np.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \ + caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/spacetime.h caml/io.h caml/stack.h +parsing_np.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \ + caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/alloc.h +prims_np.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/prims.h +printexc_np.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +roots_byt_np.$(O): roots_byt.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stacks.h +roots_nat_np.$(O): roots_nat.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stack.h +signals_np.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/roots.h caml/signals.h \ + caml/signals_machdep.h caml/sys.h +signals_byt_np.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \ + caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/signals_machdep.h +signals_nat_np.$(O): signals_nat.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/signals.h caml/signals_machdep.h signals_osdep.h \ + caml/stack.h caml/spacetime.h caml/io.h +spacetime_byt_np.$(O): spacetime_byt.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h +spacetime_nat_np.$(O): spacetime_nat.c caml/config.h caml/m.h caml/s.h \ + caml/alloc.h caml/misc.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/fail.h caml/gc.h caml/intext.h \ + caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +spacetime_snapshot_np.$(O): spacetime_snapshot.c caml/alloc.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/custom.h caml/fail.h caml/gc.h \ + caml/gc_ctrl.h caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/minor_gc.h caml/address_class.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +stacks_np.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \ + caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +startup_aux_np.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/callback.h caml/osdeps.h caml/startup_aux.h +startup_byt_np.$(O): startup_byt.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \ + caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \ + caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \ + caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \ + caml/startup_aux.h caml/version.h +startup_nat_np.$(O): startup_nat.c caml/callback.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/backtrace.h \ + caml/exec.h caml/custom.h caml/debugger.h caml/fail.h caml/freelist.h \ + caml/gc.h caml/gc_ctrl.h caml/intext.h caml/io.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/printexc.h caml/stack.h caml/startup_aux.h caml/sys.h +str_np.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h +sys_np.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \ + caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h +unix_np.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/sys.h caml/io.h caml/alloc.h +weak_np.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/weak.h caml/signals.h +afl_npic.$(O): afl.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/mlvalues.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +alloc_npic.$(O): alloc.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/stacks.h +array_npic.$(O): array.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h \ + caml/spacetime.h caml/io.h caml/stack.h +backtrace_npic.$(O): backtrace.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/backtrace.h \ + caml/exec.h caml/backtrace_prim.h caml/fail.h +backtrace_byt_npic.$(O): backtrace_byt.c caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/misc.h caml/alloc.h caml/custom.h caml/io.h \ + caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/startup.h caml/stacks.h \ + caml/sys.h caml/backtrace.h caml/fail.h caml/backtrace_prim.h +backtrace_nat_npic.$(O): backtrace_nat.c caml/alloc.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/backtrace_prim.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h +bigarray_npic.$(O): bigarray.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/bigarray.h caml/custom.h caml/fail.h \ + caml/intext.h caml/io.h caml/hash.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/signals.h +callback_npic.$(O): callback.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +clambda_checks_npic.$(O): clambda_checks.c caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h +compact_npic.$(O): compact.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/gc_ctrl.h caml/weak.h caml/compact.h +compare_npic.$(O): compare.c caml/custom.h caml/mlvalues.h caml/config.h caml/m.h \ + caml/s.h caml/misc.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +custom_npic.$(O): custom.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc_ctrl.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h +debugger_npic.$(O): debugger.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/debugger.h caml/osdeps.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h +dynlink_npic.$(O): dynlink.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/dynlink.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/prims.h caml/signals.h +dynlink_nat_npic.$(O): dynlink_nat.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/stack.h \ + caml/callback.h caml/alloc.h caml/intext.h caml/io.h caml/osdeps.h \ + caml/fail.h caml/signals.h caml/hooks.h +extern_npic.$(O): extern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/custom.h caml/fail.h caml/gc.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/reverse.h +fail_byt_npic.$(O): fail_byt.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stacks.h +fail_nat_npic.$(O): fail_nat.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/io.h caml/gc.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/printexc.h caml/signals.h caml/stack.h caml/roots.h \ + caml/callback.h +finalise_npic.$(O): finalise.c caml/callback.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/compact.h caml/fail.h \ + caml/finalise.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.h +fix_code_npic.$(O): fix_code.c caml/config.h caml/m.h caml/s.h caml/debugger.h \ + caml/misc.h caml/mlvalues.h caml/fix_code.h caml/instruct.h \ + caml/intext.h caml/io.h caml/md5.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +floats_npic.$(O): floats.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h caml/stacks.h +freelist_npic.$(O): freelist.c caml/config.h caml/m.h caml/s.h caml/freelist.h \ + caml/misc.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h +gc_ctrl_npic.$(O): gc_ctrl.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/compact.h \ + caml/custom.h caml/fail.h caml/finalise.h caml/roots.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/gc_ctrl.h caml/signals.h caml/stack.h \ + caml/startup_aux.h +globroots_npic.$(O): globroots.c caml/memory.h caml/config.h caml/m.h caml/s.h \ + caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/roots.h caml/globroots.h +hash_npic.$(O): hash.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/custom.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/hash.h +instrtrace_npic.$(O): instrtrace.c +intern_npic.$(O): intern.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/custom.h caml/fail.h \ + caml/gc.h caml/intext.h caml/io.h caml/md5.h caml/memory.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/reverse.h +interp_npic.$(O): interp.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/backtrace.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/fix_code.h caml/instrtrace.h \ + caml/instruct.h caml/interp.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/signals.h caml/stacks.h caml/startup_aux.h \ + caml/jumptbl.h +ints_npic.$(O): ints.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/intext.h caml/io.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h +io_npic.$(O): io.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/custom.h caml/fail.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/osdeps.h caml/signals.h caml/sys.h +lexing_npic.$(O): lexing.c caml/fail.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +main_npic.$(O): main.c caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/sys.h caml/osdeps.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +major_gc_npic.$(O): major_gc.c caml/compact.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/custom.h caml/fail.h caml/finalise.h \ + caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +md5_npic.$(O): md5.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/md5.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/reverse.h +memory_npic.$(O): memory.c caml/address_class.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h \ + caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/minor_gc.h \ + caml/signals.h +meta_npic.$(O): meta.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/fix_code.h caml/interp.h \ + caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/gc.h caml/minor_gc.h caml/address_class.h caml/prims.h \ + caml/stacks.h caml/backtrace_prim.h caml/backtrace.h caml/exec.h +minor_gc_npic.$(O): minor_gc.c caml/custom.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/fail.h caml/finalise.h caml/roots.h \ + caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/gc_ctrl.h caml/signals.h \ + caml/weak.h +misc_npic.$(O): misc.c caml/config.h caml/m.h caml/s.h caml/misc.h caml/memory.h \ + caml/gc.h caml/mlvalues.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/version.h +obj_npic.$(O): obj.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h \ + caml/freelist.h caml/memory.h caml/minor_gc.h caml/address_class.h \ + caml/prims.h caml/spacetime.h caml/io.h caml/stack.h +parsing_npic.$(O): parsing.c caml/config.h caml/m.h caml/s.h caml/mlvalues.h \ + caml/misc.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/alloc.h +prims_npic.$(O): prims.c caml/mlvalues.h caml/config.h caml/m.h caml/s.h \ + caml/misc.h caml/prims.h +printexc_npic.$(O): printexc.c caml/backtrace.h caml/mlvalues.h caml/config.h \ + caml/m.h caml/s.h caml/misc.h caml/exec.h caml/callback.h \ + caml/debugger.h caml/fail.h caml/printexc.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +roots_byt_npic.$(O): roots_byt.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stacks.h +roots_nat_npic.$(O): roots_nat.c caml/finalise.h caml/roots.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/memory.h caml/gc.h \ + caml/mlvalues.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/globroots.h caml/stack.h +signals_npic.$(O): signals.c caml/alloc.h caml/misc.h caml/config.h caml/m.h \ + caml/s.h caml/mlvalues.h caml/callback.h caml/fail.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/roots.h caml/signals.h \ + caml/signals_machdep.h caml/sys.h +signals_byt_npic.$(O): signals_byt.c caml/config.h caml/m.h caml/s.h \ + caml/memory.h caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/signals_machdep.h +signals_nat_npic.$(O): signals_nat.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/signals.h caml/signals_machdep.h signals_osdep.h \ + caml/stack.h caml/spacetime.h caml/io.h +spacetime_byt_npic.$(O): spacetime_byt.c caml/fail.h caml/misc.h caml/config.h \ + caml/m.h caml/s.h caml/mlvalues.h +spacetime_nat_npic.$(O): spacetime_nat.c caml/config.h caml/m.h caml/s.h \ + caml/alloc.h caml/misc.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/fail.h caml/gc.h caml/intext.h \ + caml/io.h caml/major_gc.h caml/freelist.h caml/memory.h \ + caml/minor_gc.h caml/address_class.h caml/osdeps.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +spacetime_snapshot_npic.$(O): spacetime_snapshot.c caml/alloc.h caml/misc.h \ + caml/config.h caml/m.h caml/s.h caml/mlvalues.h caml/backtrace_prim.h \ + caml/backtrace.h caml/exec.h caml/custom.h caml/fail.h caml/gc.h \ + caml/gc_ctrl.h caml/intext.h caml/io.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/minor_gc.h caml/address_class.h caml/roots.h \ + caml/signals.h caml/stack.h caml/sys.h caml/spacetime.h +stacks_npic.$(O): stacks.c caml/config.h caml/m.h caml/s.h caml/fail.h \ + caml/misc.h caml/mlvalues.h caml/stacks.h caml/memory.h caml/gc.h \ + caml/major_gc.h caml/freelist.h caml/minor_gc.h caml/address_class.h +startup_aux_npic.$(O): startup_aux.c caml/backtrace.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/exec.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ + caml/address_class.h caml/callback.h caml/osdeps.h caml/startup_aux.h +startup_byt_npic.$(O): startup_byt.c caml/config.h caml/m.h caml/s.h caml/alloc.h \ + caml/misc.h caml/mlvalues.h caml/backtrace.h caml/exec.h \ + caml/callback.h caml/custom.h caml/debugger.h caml/dynlink.h \ + caml/fail.h caml/fix_code.h caml/freelist.h caml/gc_ctrl.h \ + caml/instrtrace.h caml/interp.h caml/intext.h caml/io.h caml/memory.h \ + caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ + caml/osdeps.h caml/prims.h caml/printexc.h caml/reverse.h \ + caml/signals.h caml/stacks.h caml/sys.h caml/startup.h \ + caml/startup_aux.h caml/version.h +startup_nat_npic.$(O): startup_nat.c caml/callback.h caml/mlvalues.h \ + caml/config.h caml/m.h caml/s.h caml/misc.h caml/backtrace.h \ + caml/exec.h caml/custom.h caml/debugger.h caml/fail.h caml/freelist.h \ + caml/gc.h caml/gc_ctrl.h caml/intext.h caml/io.h caml/memory.h \ + caml/major_gc.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/printexc.h caml/stack.h caml/startup_aux.h caml/sys.h +str_npic.$(O): str.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h +sys_npic.$(O): sys.c caml/config.h caml/m.h caml/s.h caml/alloc.h caml/misc.h \ + caml/mlvalues.h caml/debugger.h caml/fail.h caml/gc_ctrl.h caml/io.h \ + caml/osdeps.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/minor_gc.h caml/address_class.h caml/signals.h caml/stacks.h \ + caml/sys.h caml/version.h caml/callback.h caml/startup_aux.h +unix_npic.$(O): unix.c caml/config.h caml/m.h caml/s.h caml/fail.h caml/misc.h \ + caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \ + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/osdeps.h \ + caml/signals.h caml/sys.h caml/io.h caml/alloc.h +weak_npic.$(O): weak.c caml/alloc.h caml/misc.h caml/config.h caml/m.h caml/s.h \ + caml/mlvalues.h caml/fail.h caml/major_gc.h caml/freelist.h \ + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/weak.h caml/signals.h diff --git a/runtime/Makefile b/runtime/Makefile new file mode 100644 index 00000000..9dabe5b2 --- /dev/null +++ b/runtime/Makefile @@ -0,0 +1,418 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 1999 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +ROOTDIR = .. + +include $(ROOTDIR)/Makefile.config +include $(ROOTDIR)/Makefile.common + +# Lists of source files + +PRIMS := $(addsuffix .c, \ + alloc array compare extern floats gc_ctrl hash intern interp ints io \ + lexing md5 meta obj parsing signals str sys callback weak finalise \ + stacks dynlink backtrace_byt backtrace spacetime_byt afl bigarray) + +BYTECODE_C_SOURCES := $(addsuffix .c, \ + interp misc stacks fix_code startup_aux startup_byt freelist major_gc \ + minor_gc memory alloc roots_byt globroots fail_byt signals \ + signals_byt printexc backtrace_byt backtrace compare ints \ + floats str array io extern intern hash sys meta parsing gc_ctrl md5 obj \ + lexing callback debugger weak compact finalise custom dynlink \ + spacetime_byt afl $(UNIX_OR_WIN32) bigarray main) + +NATIVE_C_SOURCES := $(addsuffix .c, \ + startup_aux startup_nat main fail_nat roots_nat signals \ + signals_nat misc freelist major_gc minor_gc memory alloc compare ints \ + floats str array io extern intern hash sys parsing gc_ctrl md5 obj \ + lexing $(UNIX_OR_WIN32) printexc callback weak compact finalise custom \ + globroots backtrace_nat backtrace dynlink_nat debugger meta \ + dynlink clambda_checks spacetime_nat spacetime_snapshot afl bigarray) + +# The other_files variable stores the list of files whose dependencies +# should be computed by `make depend` although they do not need to be +# compiled on the current build system +ifeq "$(UNIX_OR_WIN32)" "win32" +other_files := unix.c +else +other_files := win32.c +endif + +ifeq "$(TOOLCHAIN)" "msvc" +ASM_EXT := asm +ASM_SOURCES := $(ARCH)nt.$(ASM_EXT) +else +ASM_EXT := S +ASM_SOURCES := $(ARCH).$(ASM_EXT) +endif + +# Targets to build and install + +PROGRAMS := ocamlrun$(EXE) +BYTECODE_STATIC_LIBRARIES := ld.conf libcamlrun.$(A) +BYTECODE_SHARED_LIBRARIES := +NATIVE_STATIC_LIBRARIES := libasmrun.$(A) +NATIVE_SHARED_LIBRARIES := + +ifeq "$(RUNTIMED)" "true" +PROGRAMS += ocamlrund$(EXE) +BYTECODE_STATIC_LIBRARIES += libcamlrund.$(A) +NATIVE_STATIC_LIBRARIES += libasmrund.$(A) +endif + +ifeq "$(RUNTIMEI)" "true" +PROGRAMS += ocamlruni$(EXE) +BYTECODE_STATIC_LIBRARIES += libcamlruni.$(A) +NATIVE_STATIC_LIBRARIES += libasmruni.$(A) +endif + +ifeq "$(PROFILING)" "true" +NATIVE_STATIC_LIBRARIES += libasmrunp.$(A) +endif + +ifeq "$(UNIX_OR_WIN32)" "unix" +ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true" +BYTECODE_STATIC_LIBRARIES += libcamlrun_pic.$(A) +BYTECODE_SHARED_LIBRARIES += libcamlrun_shared.$(SO) +NATIVE_STATIC_LIBRARIES += libasmrun_pic.$(A) +NATIVE_SHARED_LIBRARIES += libasmrun_shared.$(SO) +endif +endif + +# List of object files for each target + +ASM_OBJECTS := $(ASM_SOURCES:.$(ASM_EXT)=.$(O)) + +libcamlrun_OBJECTS := $(BYTECODE_C_SOURCES:.c=_b.$(O)) + +libcamlrund_OBJECTS := $(BYTECODE_C_SOURCES:.c=_bd.$(O)) \ + instrtrace_bd.$(O) + +libcamlruni_OBJECTS := $(BYTECODE_C_SOURCES:.c=_bi.$(O)) + +libcamlrunpic_OBJECTS := $(BYTECODE_C_SOURCES:.c=_bpic.$(O)) + +libasmrun_OBJECTS := $(NATIVE_C_SOURCES:.c=_n.$(O)) $(ASM_OBJECTS) + +libasmrund_OBJECTS := $(NATIVE_C_SOURCES:.c=_nd.$(O)) $(ASM_OBJECTS) + +libasmruni_OBJECTS := $(NATIVE_C_SOURCES:.c=_ni.$(O)) $(ASM_OBJECTS) + +libasmrunp_OBJECTS := $(NATIVE_C_SOURCES:.c=_np.$(O)) \ + $(ASM_OBJECTS:.$(O)=_libasmrunp.$(O)) + +libasmrunpic_OBJECTS := $(NATIVE_C_SOURCES:.c=_npic.$(O)) \ + $(ASM_OBJECTS:.$(O)=_libasmrunpic.$(O)) + +# General (non target-specific) assembler and compiler flags + +ifdef BOOTSTRAPPING_FLEXLINK +OC_CPPFLAGS += -DBOOTSTRAPPING_FLEXLINK +endif + +# On Windows, OCAML_STDLIB_DIR needs to be defined dynamically + +ifeq "$(UNIX_OR_WIN32)" "win32" +# OCAML_STDLIB_DIR needs to arrive in dynlink.c as a string which both gcc and +# msvc are willing parse without warning. This means we can't pass UTF-8 +# directly since, as far as I can tell, cl can cope, but the pre-processor +# can't. So the string needs to be directly translated to L"" form. To do this, +# we take advantage of the fact that Cygwin uses GNU libiconv which includes a +# Java pseudo-encoding which translates any UTF-8 sequences to \uXXXX (and, +# unlike the C99 pseudo-encoding, emits two surrogate values when needed, rather +# than \UXXXXXXXX). The \u is then translated to \x in order to accommodate +# pre-Visual Studio 2013 compilers where \x is a non-standard alias for \u. +OCAML_STDLIB_DIR = $(shell echo $(LIBDIR)| iconv -t JAVA | sed -e 's/\\u/\\x/g') +OC_CPPFLAGS += -DOCAML_STDLIB_DIR='L"$(OCAML_STDLIB_DIR)"' +else # Unix +OCAML_STDLIB_DIR = $(LIBDIR) +OC_CPPFLAGS += -DOCAML_STDLIB_DIR='"$(OCAML_STDLIB_DIR)"' +endif + +OC_CPPFLAGS += $(IFLEXDIR) + +ifneq "$(CCOMPTYPE)" "msvc" +OC_CFLAGS += -g +endif + +OC_NATIVE_CPPFLAGS = -DNATIVE_CODE -DTARGET_$(ARCH) + +ifeq "$(UNIX_OR_WIN32)" "unix" +OC_NATIVE_CPPFLAGS += -DMODEL_$(MODEL) +endif + +OC_NATIVE_CPPFLAGS += -DSYS_$(SYSTEM) $(IFLEXDIR) $(LIBUNWIND_INCLUDE_FLAGS) + +OC_DEBUG_CPPFLAGS=-DDEBUG +OC_INSTR_CPPFLAGS=-DCAML_INSTR + +ifeq "$(TOOLCHAIN)" "msvc" +OC_PROF_CFLAGS= +OC_PROF_CPPFLAGS=-DPROFILING +ASMFLAGS= +ifeq ($(WITH_SPACETIME),true) +ASMFLAGS=/DWITH_SPACETIME +endif +else +OC_PROF_CFLAGS=-pg +OC_PROF_CPPFLAGS=-DPROFILING +endif + +ASPPFLAGS = -DSYS_$(SYSTEM) -I$(ROOTDIR)/runtime +ifeq "$(UNIX_OR_WIN32)" "unix" +ASPPFLAGS += -DMODEL_$(MODEL) +endif + +# Commands used to build native libraries + +ifeq "$(UNIX_OR_WIN32)" "win32" +LIBS = $(BYTECCLIBS) $(EXTRALIBS) +ifdef BOOTSTRAPPING_FLEXLINK +MAKE_OCAMLRUN=$(MKEXE_BOOT) +else +MAKE_OCAMLRUN = $(MKEXE) -o $(1) $(2) +endif +else +LIBS = $(BYTECCLIBS) +MAKE_OCAMLRUN = $(MKEXE) -o $(1) $(2) +endif + +# Build, install and clean targets + +.PHONY: all +all: $(BYTECODE_STATIC_LIBRARIES) $(BYTECODE_SHARED_LIBRARIES) $(PROGRAMS) + +.PHONY: allopt +allopt: $(NATIVE_STATIC_LIBRARIES) $(NATIVE_SHARED_LIBRARIES) + +INSTALL_INCDIR=$(INSTALL_LIBDIR)/caml +.PHONY: install +install: + $(INSTALL_PROG) $(PROGRAMS) "$(INSTALL_BINDIR)" + $(INSTALL_DATA) $(BYTECODE_STATIC_LIBRARIES) "$(INSTALL_LIBDIR)" +ifneq "$(BYTECODE_SHARED_LIBRARIES)" "" + $(INSTALL_PROG) $(BYTECODE_SHARED_LIBRARIES) "$(INSTALL_LIBDIR)" +endif + mkdir -p "$(INSTALL_INCDIR)" + $(INSTALL_DATA) caml/*.h "$(INSTALL_INCDIR)" + +.PHONY: installopt +installopt: + $(INSTALL_DATA) $(NATIVE_STATIC_LIBRARIES) "$(INSTALL_LIBDIR)" +ifneq "$(NATIVE_SHARED_LIBRARIES)" "" + $(INSTALL_PROG) $(NATIVE_SHARED_LIBRARIES) "$(INSTALL_LIBDIR)" +endif + +.PHONY: clean +clean: + rm -f $(PROGRAMS) *.$(O) *.$(A) *.$(SO) ld.conf + rm -f primitives prims.c caml/opnames.h caml/jumptbl.h + rm -f caml/version.h + +.PHONY: distclean +distclean: clean + rm -r *~ + +# Generated non-object files + +ld.conf: $(ROOTDIR)/Makefile.config + echo "$(STUBLIBDIR)" > $@ + echo "$(LIBDIR)" >> $@ + +# If primitives contain duplicated lines (e.g. because the code is defined +# like +# #ifdef X +# CAMLprim value caml_foo() ... +# #else +# CAMLprim value caml_foo() ... +# end), horrible things will happen (duplicated entries in Runtimedef -> +# double registration in Symtable -> empty entry in the PRIM table -> +# the bytecode interpreter is confused). +# We sort the primitive file and remove duplicates to avoid this problem. + +# Warning: we use "sort | uniq" instead of "sort -u" because in the MSVC +# port, the "sort" program in the path is Microsoft's and not cygwin's + +# Warning: POSIX sort is locale dependent, that's why we set LC_ALL explicitly. +# Sort is unstable for "is_directory" and "isatty" +# see http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sort.html: +# "using sort to process pathnames, it is recommended that LC_ALL .. set to C" + + +primitives : $(PRIMS) + ./gen_primitives.sh >$@ + +prims.c : primitives + (echo '#define CAML_INTERNALS'; \ + echo '#include "caml/mlvalues.h"'; \ + echo '#include "caml/prims.h"'; \ + sed -e 's/.*/extern value &();/' primitives; \ + echo 'c_primitive caml_builtin_cprim[] = {'; \ + sed -e 's/.*/ &,/' primitives; \ + echo ' 0 };'; \ + echo 'char * caml_names_of_builtin_cprim[] = {'; \ + sed -e 's/.*/ "&",/' primitives; \ + echo ' 0 };') > prims.c + +caml/opnames.h : caml/instruct.h + cat $^ | tr -d '\r' | \ + sed -e '/\/\*/d' \ + -e '/^#/d' \ + -e 's/enum /static char * names_of_/' \ + -e 's/{$$/[] = {/' \ + -e 's/\([[:upper:]][[:upper:]_0-9]*\)/"\1"/g' > $@ + +# caml/jumptbl.h is required only if you have GCC 2.0 or later +caml/jumptbl.h : caml/instruct.h + cat $^ | tr -d '\r' | \ + sed -n -e '/^ /s/ \([A-Z]\)/ \&\&lbl_\1/gp' \ + -e '/^}/q' > $@ + +caml/version.h : $(ROOTDIR)/tools/make-version-header.sh $(ROOTDIR)/VERSION + $^ > $@ + +# Libraries and programs + +ocamlrun$(EXE): prims.$(O) libcamlrun.$(A) + $(call MAKE_OCAMLRUN,$@,$^ $(LIBS)) + +libcamlrun.$(A): $(libcamlrun_OBJECTS) + $(call MKLIB,$@, $^) + +ocamlrund$(EXE): prims.$(O) libcamlrund.$(A) + $(MKEXE) $(MKEXEDEBUGFLAG) -o $@ $^ $(LIBS) + +libcamlrund.$(A): $(libcamlrund_OBJECTS) + $(call MKLIB,$@, $^) + +ocamlruni$(EXE): prims.$(O) libcamlruni.$(A) + $(MKEXE) -o $@ $^ $(LIBS) + +libcamlruni.$(A): $(libcamlruni_OBJECTS) + $(call MKLIB,$@, $^) + +libcamlrun_pic.$(A): $(libcamlrunpic_OBJECTS) + $(call MKLIB,$@, $^) + +libcamlrun_shared.$(SO): $(libcamlrunpic_OBJECTS) + $(MKDLL) -o $@ $^ $(BYTECCLIBS) + +libasmrun.$(A): $(libasmrun_OBJECTS) + $(call MKLIB,$@, $^) + +libasmrund.$(A): $(libasmrund_OBJECTS) + $(call MKLIB,$@, $^) + +libasmruni.$(A): $(libasmruni_OBJECTS) + $(call MKLIB,$@, $^) + +libasmrunp.$(A): $(libasmrunp_OBJECTS) + $(call MKLIB,$@, $^) + +libasmrun_pic.$(A): $(libasmrunpic_OBJECTS) + $(call MKLIB,$@, $^) + +libasmrun_shared.$(SO): $(libasmrunpic_OBJECTS) + $(MKDLL) -o $@ $^ $(NATIVECCLIBS) + +# Target-specific preprocessor and compiler flags + +%_bd.$(O): OC_CPPFLAGS += $(OC_DEBUG_CPPFLAGS) + +%_bi.$(O): OC_CPPFLAGS += $(OC_INSTR_CPPFLAGS) + +%_bpic.$(O): OC_CFLAGS += $(SHAREDLIB_CFLAGS) + +%_n.$(O): OC_CPPFLAGS += $(OC_NATIVE_CPPFLAGS) + +%_nd.$(O): OC_CPPFLAGS += $(OC_NATIVE_CPPFLAGS) $(OC_DEBUG_CPPFLAGS) + +%_ni.$(O): OC_CPPFLAGS += $(OC_NATIVE_CPPFLAGS) $(OC_INSTR_CPPFLAGS) + +%_np.$(O): OC_CFLAGS += $(OC_PROF_CFLAGS) +%_np.$(O): OC_CPPFLAGS += $(OC_NATIVE_CPPFLAGS) $(OC_PROF_CPPFLAGS) + +%_npic.$(O): OC_CFLAGS += $(SHAREDLIB_CFLAGS) +%_npic.$(O): OC_CPPFLAGS += $(OC_NATIVE_CPPFLAGS) + +# Compilation of C files + +# The COMPILE_C_FILE macro below receives as argument the pattern +# that corresponds to the name of the generated object file +# (without the extension, which is added by the macro) +define COMPILE_C_FILE +$(1).$(O): %.c + $$(CC) -c $$(OC_CFLAGS) $$(OC_CPPFLAGS) $$(OUTPUTOBJ)$$@ $$< +endef + +object_types := % %_b %_bd %_bi %_bpic %_n %_nd %_ni %_np %_npic + +$(foreach object_type, $(object_types), \ + $(eval $(call COMPILE_C_FILE,$(object_type)))) + +# Compilation of assembly files + +%.o: %.S + $(ASPP) $(ASPPFLAGS) -o $@ $< || \ + { echo "If your assembler produced syntax errors, it is probably";\ + echo "unhappy with the preprocessor. Check your assembler, or";\ + echo "try producing $*.o by hand.";\ + exit 2; } + +%_libasmrunp.o: %.S + $(ASPP) $(ASPPFLAGS) $(ASPPPROFFLAGS) -o $@ $< + +%_libasmrunpic.o: %.S + $(ASPP) $(ASPPFLAGS) $(SHAREDLIB_CFLAGS) -o $@ $< + +%.obj: %.asm + $(ASM)$@ $(ASMFLAGS) $< + +%_libasmrunpic.obj: %.asm + $(ASM)$@ $(ASMFLAGS) $< + +# Dependencies + +.PHONY: depend +ifeq "$(TOOLCHAIN)" "msvc" +depend: + $(error Dependencies cannot be regenerated using the MSVC ports) +else + +NATIVE_DEP_CPPFLAGS := $(OC_CPPFLAGS) $(OC_NATIVE_CPPFLAGS) +NATIVE_DEP_FILES := $(NATIVE_C_SOURCES) $(other_files) + +depend: *.c caml/opnames.h caml/jumptbl.h caml/version.h + $(CC) -MM $(OC_CPPFLAGS) *.c | \ + sed -e 's/\([^.]*\)\.o/\1_b.$$(O)/' > .depend + $(CC) -MM $(OC_CPPFLAGS) $(OC_DEBUG_CPPFLAGS) *.c | \ + sed -e 's/\([^.]*\)\.o/\1_bd.$$(O)/' >> .depend + $(CC) -MM $(OC_CPPFLAGS) $(OC_INSTR_CPPFLAGS) *.c | \ + sed -e 's/\([^.]*\)\.o/\1_bi.$$(O)/' >> .depend + $(CC) -MM $(OC_CPPFLAGS) *.c | \ + sed -e 's/\([^.]*\)\.o/\1_bpic.$$(O)/' >> .depend + $(CC) -MM $(NATIVE_DEP_CPPFLAGS) *.c | \ + sed -e 's/\([^.]*\)\.o/\1_n.$$(O)/' >> .depend + $(CC) -MM $(NATIVE_DEP_CPPFLAGS) $(OC_DEBUG_CPPFLAGS) *.c | \ + sed -e 's/\([^.]*\)\.o/\1_nd.$$(O)/' >> .depend + $(CC) -MM $(NATIVE_DEP_CPPFLAGS) $(OC_INSTR_CPPFLAGS) *.c | \ + sed -e 's/\([^.]*\)\.o/\1_ni.$$(O)/' >> .depend + $(CC) -MM $(NATIVE_DEP_CPPFLAGS) $(OC_PROF_CPPFLAGS) *.c | \ + sed -e 's/\([^.]*\)\.o/\1_np.$$(O)/' >> .depend + $(CC) -MM $(NATIVE_DEP_CPPFLAGS) *.c | \ + sed -e 's/\([^.]*\)\.o/\1_npic.$$(O)/' >> .depend +endif + +include .depend diff --git a/byterun/afl.c b/runtime/afl.c similarity index 100% rename from byterun/afl.c rename to runtime/afl.c diff --git a/runtime/alloc.c b/runtime/alloc.c new file mode 100644 index 00000000..a3e6fbc2 --- /dev/null +++ b/runtime/alloc.c @@ -0,0 +1,247 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* 1. Allocation functions doing the same work as the macros in the + case where [Setup_for_gc] and [Restore_after_gc] are no-ops. + 2. Convenience functions related to allocation. +*/ + +#include +#include "caml/alloc.h" +#include "caml/custom.h" +#include "caml/major_gc.h" +#include "caml/memory.h" +#include "caml/mlvalues.h" +#include "caml/stacks.h" + +#define Setup_for_gc +#define Restore_after_gc + +CAMLexport value caml_alloc (mlsize_t wosize, tag_t tag) +{ + value result; + mlsize_t i; + + CAMLassert (tag < 256); + CAMLassert (tag != Infix_tag); + if (wosize <= Max_young_wosize){ + if (wosize == 0){ + result = Atom (tag); + }else{ + Alloc_small (result, wosize, tag); + if (tag < No_scan_tag){ + for (i = 0; i < wosize; i++) Field (result, i) = Val_unit; + } + } + }else{ + result = caml_alloc_shr (wosize, tag); + if (tag < No_scan_tag){ + for (i = 0; i < wosize; i++) Field (result, i) = Val_unit; + } + result = caml_check_urgent_gc (result); + } + return result; +} + +CAMLexport value caml_alloc_small (mlsize_t wosize, tag_t tag) +{ + value result; + + CAMLassert (wosize > 0); + CAMLassert (wosize <= Max_young_wosize); + CAMLassert (tag < 256); + Alloc_small (result, wosize, tag); + return result; +} + +CAMLexport value caml_alloc_small_with_my_or_given_profinfo (mlsize_t wosize, + tag_t tag, uintnat profinfo) +{ + if (profinfo == 0) { + return caml_alloc_small(wosize, tag); + } + else { + value result; + + CAMLassert (wosize > 0); + CAMLassert (wosize <= Max_young_wosize); + CAMLassert (tag < 256); + Alloc_small_with_profinfo (result, wosize, tag, profinfo); + return result; + } +} + +/* [n] is a number of words (fields) */ +CAMLexport value caml_alloc_tuple(mlsize_t n) +{ + return caml_alloc(n, 0); +} + +/* [len] is a number of bytes (chars) */ +CAMLexport value caml_alloc_string (mlsize_t len) +{ + value result; + mlsize_t offset_index; + mlsize_t wosize = (len + sizeof (value)) / sizeof (value); + + if (wosize <= Max_young_wosize) { + Alloc_small (result, wosize, String_tag); + }else{ + result = caml_alloc_shr (wosize, String_tag); + result = caml_check_urgent_gc (result); + } + Field (result, wosize - 1) = 0; + offset_index = Bsize_wsize (wosize) - 1; + Byte (result, offset_index) = offset_index - len; + return result; +} + +/* [len] is a number of bytes (chars) */ +CAMLexport value caml_alloc_initialized_string (mlsize_t len, const char *p) +{ + value result = caml_alloc_string (len); + memcpy((char *)String_val(result), p, len); + return result; +} + +/* [len] is a number of words. + [mem] and [max] are relative (without unit). +*/ +CAMLexport value caml_alloc_final (mlsize_t len, final_fun fun, + mlsize_t mem, mlsize_t max) +{ + return caml_alloc_custom(caml_final_custom_operations(fun), + len * sizeof(value), mem, max); +} + +CAMLexport value caml_copy_string(char const *s) +{ + mlsize_t len; + value res; + + len = strlen(s); + res = caml_alloc_initialized_string(len, s); + return res; +} + +CAMLexport value caml_alloc_array(value (*funct)(char const *), + char const ** arr) +{ + CAMLparam0 (); + mlsize_t nbr, n; + CAMLlocal2 (v, result); + + nbr = 0; + while (arr[nbr] != 0) nbr++; + result = caml_alloc (nbr, 0); + for (n = 0; n < nbr; n++) { + /* The two statements below must be separate because of evaluation + order (don't take the address &Field(result, n) before + calling funct, which may cause a GC and move result). */ + v = funct(arr[n]); + caml_modify(&Field(result, n), v); + } + CAMLreturn (result); +} + +/* [len] is a number of floats */ +value caml_alloc_float_array(mlsize_t len) +{ +#ifdef FLAT_FLOAT_ARRAY + mlsize_t wosize = len * Double_wosize; + value result; + /* For consistency with [caml_make_vect], which can't tell whether it should + create a float array or not when the size is zero, the tag is set to + zero when the size is zero. */ + if (wosize <= Max_young_wosize){ + if (wosize == 0) + return Atom(0); + else + Alloc_small (result, wosize, Double_array_tag); + }else { + result = caml_alloc_shr (wosize, Double_array_tag); + result = caml_check_urgent_gc (result); + } + return result; +#else + return caml_alloc (len, 0); +#endif +} + + +CAMLexport value caml_copy_string_array(char const ** arr) +{ + return caml_alloc_array(caml_copy_string, arr); +} + +CAMLexport int caml_convert_flag_list(value list, int *flags) +{ + int res; + res = 0; + while (list != Val_int(0)) { + res |= flags[Int_val(Field(list, 0))]; + list = Field(list, 1); + } + return res; +} + +/* For compiling let rec over values */ + +/* [size] is a [value] representing number of words (fields) */ +CAMLprim value caml_alloc_dummy(value size) +{ + mlsize_t wosize = Long_val(size); + return caml_alloc (wosize, 0); +} + +/* [size] is a [value] representing number of words (fields) */ +CAMLprim value caml_alloc_dummy_function(value size,value arity) +{ + /* the arity argument is used by the js_of_ocaml runtime */ + return caml_alloc_dummy(size); +} + +/* [size] is a [value] representing number of floats. */ +CAMLprim value caml_alloc_dummy_float (value size) +{ + mlsize_t wosize = Long_val(size) * Double_wosize; + return caml_alloc (wosize, 0); +} + +CAMLprim value caml_update_dummy(value dummy, value newval) +{ + mlsize_t size, i; + tag_t tag; + + size = Wosize_val(newval); + tag = Tag_val (newval); + CAMLassert (size == Wosize_val(dummy)); + CAMLassert (tag < No_scan_tag || tag == Double_array_tag); + + Tag_val(dummy) = tag; + if (tag == Double_array_tag){ + size = Wosize_val (newval) / Double_wosize; + for (i = 0; i < size; i++){ + Store_double_flat_field (dummy, i, Double_flat_field (newval, i)); + } + }else{ + for (i = 0; i < size; i++){ + caml_modify (&Field(dummy, i), Field(newval, i)); + } + } + return Val_unit; +} diff --git a/runtime/amd64.S b/runtime/amd64.S new file mode 100644 index 00000000..1a024283 --- /dev/null +++ b/runtime/amd64.S @@ -0,0 +1,741 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2003 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Asm part of the runtime system, AMD64 processor */ +/* Must be preprocessed by cpp */ + +/* PIC mode support based on contribution by Paul Stravers (see PR#4795) */ + +#include "caml/m.h" + +#if defined(SYS_macosx) + +#define LBL(x) L##x +#define G(r) _##r +#define GREL(r) _##r@GOTPCREL +#define GCALL(r) _##r +#define FUNCTION_ALIGN 2 +#define EIGHT_ALIGN 3 +#define SIXTEEN_ALIGN 4 +#define FUNCTION(name) \ + .globl name; \ + .align FUNCTION_ALIGN; \ + name: + +#elif defined(SYS_mingw64) || defined(SYS_cygwin) + +#define LBL(x) .L##x +#define G(r) r +#undef GREL +#define GCALL(r) r +#define FUNCTION_ALIGN 4 +#define EIGHT_ALIGN 8 +#define SIXTEEN_ALIGN 16 +#define FUNCTION(name) \ + .globl name; \ + .align FUNCTION_ALIGN; \ + name: + +#else + +#define LBL(x) .L##x +#define G(r) r +#define GREL(r) r@GOTPCREL +#define GCALL(r) r@PLT +#define FUNCTION_ALIGN 4 +#define EIGHT_ALIGN 8 +#define SIXTEEN_ALIGN 16 +#define FUNCTION(name) \ + .globl name; \ + .type name,@function; \ + .align FUNCTION_ALIGN; \ + name: + +#endif + +#ifdef ASM_CFI_SUPPORTED +#define CFI_STARTPROC .cfi_startproc +#define CFI_ENDPROC .cfi_endproc +#define CFI_ADJUST(n) .cfi_adjust_cfa_offset n +#define CFI_OFFSET(r, n) .cfi_offset r, n +#define CFI_SAME_VALUE(r) .cfi_same_value r +#else +#define CFI_STARTPROC +#define CFI_ENDPROC +#define CFI_ADJUST(n) +#define CFI_OFFSET(r, n) +#define CFI_SAME_VALUE(r) +#endif + +#ifdef WITH_FRAME_POINTERS + +#define ENTER_FUNCTION \ + pushq %rbp; CFI_ADJUST(8); \ + movq %rsp, %rbp +#define LEAVE_FUNCTION \ + popq %rbp; CFI_ADJUST(-8); + +#else + +#define ENTER_FUNCTION \ + subq $8, %rsp; CFI_ADJUST (8); +#define LEAVE_FUNCTION \ + addq $8, %rsp; CFI_ADJUST (-8); + +#endif + +#if defined(__PIC__) && !defined(SYS_mingw64) && !defined(SYS_cygwin) + +/* Position-independent operations on global variables. */ + +/* Store [srcreg] in global [dstlabel]. Clobbers %r11. */ +#define STORE_VAR(srcreg,dstlabel) \ + movq GREL(dstlabel)(%rip), %r11 ; \ + movq srcreg, (%r11) + +#define STORE_VAR32(srcreg,dstlabel) \ + movq GREL(dstlabel)(%rip), %r11 ; \ + movl srcreg, (%r11) + +/* Load global [srclabel] in register [dstreg]. Clobbers %r11. */ +#define LOAD_VAR(srclabel,dstreg) \ + movq GREL(srclabel)(%rip), %r11 ; \ + movq (%r11), dstreg + +/* Compare global [label] with register [reg]. Clobbers %rax. */ +#define CMP_VAR(label,reg) \ + movq GREL(label)(%rip), %rax ; \ + cmpq (%rax), reg + +/* Test 32-bit global [label] against mask [imm]. Clobbers %r11. */ +#define TESTL_VAR(imm,label) \ + movq GREL(label)(%rip), %r11 ; \ + testl imm, (%r11) + +/* Push global [label] on stack. Clobbers %r11. */ +#define PUSH_VAR(srclabel) \ + movq GREL(srclabel)(%rip), %r11 ; \ + pushq (%r11); CFI_ADJUST (8) + +/* Pop global [label] off stack. Clobbers %r11. */ +#define POP_VAR(dstlabel) \ + movq GREL(dstlabel)(%rip), %r11 ; \ + popq (%r11); CFI_ADJUST (-8) + +/* Record lowest stack address and return address. Clobbers %rax. */ +#define RECORD_STACK_FRAME(OFFSET) \ + pushq %r11 ; CFI_ADJUST(8); \ + movq 8+OFFSET(%rsp), %rax ; \ + STORE_VAR(%rax,caml_last_return_address) ; \ + leaq 16+OFFSET(%rsp), %rax ; \ + STORE_VAR(%rax,caml_bottom_of_stack) ; \ + popq %r11; CFI_ADJUST(-8) + +/* Load address of global [label] in register [dst]. */ +#define LEA_VAR(label,dst) \ + movq GREL(label)(%rip), dst + +#else + +/* Non-PIC operations on global variables. Slightly faster. */ + +#define STORE_VAR(srcreg,dstlabel) \ + movq srcreg, G(dstlabel)(%rip) + +#define STORE_VAR32(srcreg,dstlabel) \ + movl srcreg, G(dstlabel)(%rip) + +#define LOAD_VAR(srclabel,dstreg) \ + movq G(srclabel)(%rip), dstreg + +#define CMP_VAR(label,reg) \ + cmpq G(label)(%rip), %r15 + +#define TESTL_VAR(imm,label) \ + testl imm, G(label)(%rip) + +#define PUSH_VAR(srclabel) \ + pushq G(srclabel)(%rip) ; CFI_ADJUST(8) + +#define POP_VAR(dstlabel) \ + popq G(dstlabel)(%rip); CFI_ADJUST(-8) + +#define RECORD_STACK_FRAME(OFFSET) \ + movq OFFSET(%rsp), %rax ; \ + STORE_VAR(%rax,caml_last_return_address) ; \ + leaq 8+OFFSET(%rsp), %rax ; \ + STORE_VAR(%rax,caml_bottom_of_stack) + +#define LEA_VAR(label,dst) \ + leaq G(label)(%rip), dst +#endif + +/* Save and restore all callee-save registers on stack. + Keep the stack 16-aligned. */ + +#if defined(SYS_mingw64) || defined(SYS_cygwin) + +/* Win64 API: callee-save regs are rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15 */ + +#define PUSH_CALLEE_SAVE_REGS \ + pushq %rbx; CFI_ADJUST (8); CFI_OFFSET(rbx, -16); \ + pushq %rbp; CFI_ADJUST (8); CFI_OFFSET(rbp, -24); \ + /* Allows debugger to walk the stack */ \ + pushq %rsi; CFI_ADJUST (8); CFI_OFFSET(rsi, -32); \ + pushq %rdi; CFI_ADJUST (8); CFI_OFFSET(rdi, -40); \ + pushq %r12; CFI_ADJUST (8); CFI_OFFSET(r12, -48); \ + pushq %r13; CFI_ADJUST (8); CFI_OFFSET(r13, -56); \ + pushq %r14; CFI_ADJUST (8); CFI_OFFSET(r14, -64); \ + pushq %r15; CFI_ADJUST (8); CFI_OFFSET(r15, -72); \ + subq $(8+10*16), %rsp; CFI_ADJUST (8+10*16); \ + movupd %xmm6, 0*16(%rsp); \ + movupd %xmm7, 1*16(%rsp); \ + movupd %xmm8, 2*16(%rsp); \ + movupd %xmm9, 3*16(%rsp); \ + movupd %xmm10, 4*16(%rsp); \ + movupd %xmm11, 5*16(%rsp); \ + movupd %xmm12, 6*16(%rsp); \ + movupd %xmm13, 7*16(%rsp); \ + movupd %xmm14, 8*16(%rsp); \ + movupd %xmm15, 9*16(%rsp) + +#define POP_CALLEE_SAVE_REGS \ + movupd 0*16(%rsp), %xmm6; \ + movupd 1*16(%rsp), %xmm7; \ + movupd 2*16(%rsp), %xmm8; \ + movupd 3*16(%rsp), %xmm9; \ + movupd 4*16(%rsp), %xmm10; \ + movupd 5*16(%rsp), %xmm11; \ + movupd 6*16(%rsp), %xmm12; \ + movupd 7*16(%rsp), %xmm13; \ + movupd 8*16(%rsp), %xmm14; \ + movupd 9*16(%rsp), %xmm15; \ + addq $(8+10*16), %rsp; CFI_ADJUST (-8-10*16); \ + popq %r15; CFI_ADJUST(-8); CFI_SAME_VALUE(r15); \ + popq %r14; CFI_ADJUST(-8); CFI_SAME_VALUE(r14); \ + popq %r13; CFI_ADJUST(-8); CFI_SAME_VALUE(r13); \ + popq %r12; CFI_ADJUST(-8); CFI_SAME_VALUE(r12); \ + popq %rdi; CFI_ADJUST(-8); CFI_SAME_VALUE(rdi); \ + popq %rsi; CFI_ADJUST(-8); CFI_SAME_VALUE(rsi); \ + popq %rbp; CFI_ADJUST(-8); CFI_SAME_VALUE(rbp); \ + popq %rbx; CFI_ADJUST(-8); CFI_SAME_VALUE(rbx) + +#else + +/* Unix API: callee-save regs are rbx, rbp, r12-r15 */ + +#define PUSH_CALLEE_SAVE_REGS \ + pushq %rbx; CFI_ADJUST(8); CFI_OFFSET(rbx, -16); \ + pushq %rbp; CFI_ADJUST(8); CFI_OFFSET(rbp, -24); \ + pushq %r12; CFI_ADJUST(8); CFI_OFFSET(r12, -32); \ + pushq %r13; CFI_ADJUST(8); CFI_OFFSET(r13, -40); \ + pushq %r14; CFI_ADJUST(8); CFI_OFFSET(r14, -48); \ + pushq %r15; CFI_ADJUST(8); CFI_OFFSET(r15, -56); \ + subq $8, %rsp; CFI_ADJUST(8) + +#define POP_CALLEE_SAVE_REGS \ + addq $8, %rsp; CFI_ADJUST(-8); \ + popq %r15; CFI_ADJUST(-8); CFI_SAME_VALUE(r15); \ + popq %r14; CFI_ADJUST(-8); CFI_SAME_VALUE(r14); \ + popq %r13; CFI_ADJUST(-8); CFI_SAME_VALUE(r13); \ + popq %r12; CFI_ADJUST(-8); CFI_SAME_VALUE(r12); \ + popq %rbp; CFI_ADJUST(-8); CFI_SAME_VALUE(rbp); \ + popq %rbx; CFI_ADJUST(-8); CFI_SAME_VALUE(rbx) + +#endif + +#if defined(SYS_mingw64) || defined (SYS_cygwin) + /* Calls from OCaml to C must reserve 32 bytes of extra stack space */ +# define PREPARE_FOR_C_CALL subq $32, %rsp; CFI_ADJUST(32) +# define CLEANUP_AFTER_C_CALL addq $32, %rsp; CFI_ADJUST(-32) + /* Stack probing mustn't be larger than the page size */ +# define STACK_PROBE_SIZE $4096 +#else +# define PREPARE_FOR_C_CALL +# define CLEANUP_AFTER_C_CALL +# define STACK_PROBE_SIZE $32768 +#endif + +/* Registers holding arguments of C functions. */ + +#if defined(SYS_mingw64) || defined(SYS_cygwin) +#define C_ARG_1 %rcx +#define C_ARG_2 %rdx +#define C_ARG_3 %r8 +#define C_ARG_4 %r9 +#else +#define C_ARG_1 %rdi +#define C_ARG_2 %rsi +#define C_ARG_3 %rdx +#define C_ARG_4 %rcx +#endif + + .text + + .globl G(caml_system__code_begin) +G(caml_system__code_begin): + ret /* just one instruction, so that debuggers don't display + caml_system__code_begin instead of caml_call_gc */ + +/* Allocation */ + +FUNCTION(G(caml_call_gc)) + CFI_STARTPROC + RECORD_STACK_FRAME(0) +LBL(caml_call_gc): + /* Touch the stack to trigger a recoverable segfault + if insufficient space remains */ + subq STACK_PROBE_SIZE, %rsp + movq %rax, 0(%rsp) + addq STACK_PROBE_SIZE, %rsp + /* Build array of registers, save it into caml_gc_regs */ +#ifdef WITH_FRAME_POINTERS + ENTER_FUNCTION ; +#else + pushq %rbp; CFI_ADJUST(8); +#endif + pushq %r11; CFI_ADJUST (8); + pushq %r10; CFI_ADJUST (8); + pushq %r13; CFI_ADJUST (8); + pushq %r12; CFI_ADJUST (8); + pushq %r9; CFI_ADJUST (8); + pushq %r8; CFI_ADJUST (8); + pushq %rcx; CFI_ADJUST (8); + pushq %rdx; CFI_ADJUST (8); + pushq %rsi; CFI_ADJUST (8); + pushq %rdi; CFI_ADJUST (8); + pushq %rbx; CFI_ADJUST (8); + pushq %rax; CFI_ADJUST (8); + STORE_VAR(%rsp, caml_gc_regs) + /* Save caml_young_ptr, caml_exception_pointer */ + STORE_VAR(%r15, caml_young_ptr) + STORE_VAR(%r14, caml_exception_pointer) +#ifdef WITH_SPACETIME + STORE_VAR(%r13, caml_spacetime_trie_node_ptr) +#endif + /* Save floating-point registers */ + subq $(16*8), %rsp; CFI_ADJUST (16*8); + movsd %xmm0, 0*8(%rsp) + movsd %xmm1, 1*8(%rsp) + movsd %xmm2, 2*8(%rsp) + movsd %xmm3, 3*8(%rsp) + movsd %xmm4, 4*8(%rsp) + movsd %xmm5, 5*8(%rsp) + movsd %xmm6, 6*8(%rsp) + movsd %xmm7, 7*8(%rsp) + movsd %xmm8, 8*8(%rsp) + movsd %xmm9, 9*8(%rsp) + movsd %xmm10, 10*8(%rsp) + movsd %xmm11, 11*8(%rsp) + movsd %xmm12, 12*8(%rsp) + movsd %xmm13, 13*8(%rsp) + movsd %xmm14, 14*8(%rsp) + movsd %xmm15, 15*8(%rsp) + /* Call the garbage collector */ + PREPARE_FOR_C_CALL + call GCALL(caml_garbage_collection) + CLEANUP_AFTER_C_CALL + /* Restore caml_young_ptr, caml_exception_pointer */ + LOAD_VAR(caml_young_ptr, %r15) + LOAD_VAR(caml_exception_pointer, %r14) + /* Restore all regs used by the code generator */ + movsd 0*8(%rsp), %xmm0 + movsd 1*8(%rsp), %xmm1 + movsd 2*8(%rsp), %xmm2 + movsd 3*8(%rsp), %xmm3 + movsd 4*8(%rsp), %xmm4 + movsd 5*8(%rsp), %xmm5 + movsd 6*8(%rsp), %xmm6 + movsd 7*8(%rsp), %xmm7 + movsd 8*8(%rsp), %xmm8 + movsd 9*8(%rsp), %xmm9 + movsd 10*8(%rsp), %xmm10 + movsd 11*8(%rsp), %xmm11 + movsd 12*8(%rsp), %xmm12 + movsd 13*8(%rsp), %xmm13 + movsd 14*8(%rsp), %xmm14 + movsd 15*8(%rsp), %xmm15 + addq $(16*8), %rsp; CFI_ADJUST(-16*8) + popq %rax; CFI_ADJUST(-8) + popq %rbx; CFI_ADJUST(-8) + popq %rdi; CFI_ADJUST(-8) + popq %rsi; CFI_ADJUST(-8) + popq %rdx; CFI_ADJUST(-8) + popq %rcx; CFI_ADJUST(-8) + popq %r8; CFI_ADJUST(-8) + popq %r9; CFI_ADJUST(-8) + popq %r12; CFI_ADJUST(-8) + popq %r13; CFI_ADJUST(-8) + popq %r10; CFI_ADJUST(-8) + popq %r11; CFI_ADJUST(-8) +#ifdef WITH_FRAME_POINTERS + LEAVE_FUNCTION +#else + popq %rbp; CFI_ADJUST(-8); +#endif + /* Return to caller */ + ret +CFI_ENDPROC + +FUNCTION(G(caml_alloc1)) +CFI_STARTPROC +LBL(caml_alloc1): + subq $16, %r15 + CMP_VAR(caml_young_limit, %r15) + jb LBL(100) + ret +LBL(100): + RECORD_STACK_FRAME(0) + ENTER_FUNCTION +/* subq $8, %rsp; CFI_ADJUST (8); */ + call LBL(caml_call_gc) +/* addq $8, %rsp; CFI_ADJUST (-8); */ + LEAVE_FUNCTION + jmp LBL(caml_alloc1) +CFI_ENDPROC + +FUNCTION(G(caml_alloc2)) +CFI_STARTPROC +LBL(caml_alloc2): + subq $24, %r15 + CMP_VAR(caml_young_limit, %r15) + jb LBL(101) + ret +LBL(101): + RECORD_STACK_FRAME(0) + ENTER_FUNCTION +/* subq $8, %rsp; CFI_ADJUST (8); */ + call LBL(caml_call_gc) +/* addq $8, %rsp; CFI_ADJUST (-8); */ + LEAVE_FUNCTION + jmp LBL(caml_alloc2) +CFI_ENDPROC + +FUNCTION(G(caml_alloc3)) +CFI_STARTPROC +LBL(caml_alloc3): + subq $32, %r15 + CMP_VAR(caml_young_limit, %r15) + jb LBL(102) + ret +LBL(102): + RECORD_STACK_FRAME(0) + ENTER_FUNCTION +/* subq $8, %rsp; CFI_ADJUST (8) */ + call LBL(caml_call_gc) +/* addq $8, %rsp; CFI_ADJUST (-8) */ + LEAVE_FUNCTION + jmp LBL(caml_alloc3) +CFI_ENDPROC + +FUNCTION(G(caml_allocN)) +CFI_STARTPROC +LBL(caml_allocN): + pushq %rax; CFI_ADJUST(8) /* save desired size */ + subq %rax, %r15 + CMP_VAR(caml_young_limit, %r15) + jb LBL(103) + addq $8, %rsp; CFI_ADJUST (-8) /* drop desired size */ + ret +LBL(103): + CFI_ADJUST(8) + RECORD_STACK_FRAME(8) +#ifdef WITH_FRAME_POINTERS + /* ensure 16 byte alignment by subq + enter using 16-bytes, PR#7417 */ + subq $8, %rsp; CFI_ADJUST (8) + ENTER_FUNCTION +#endif + call LBL(caml_call_gc) +#ifdef WITH_FRAME_POINTERS + /* ensure 16 byte alignment by leave + addq using 16-bytes PR#7417 */ + LEAVE_FUNCTION + addq $8, %rsp; CFI_ADJUST (-8) +#endif + popq %rax; CFI_ADJUST(-8) /* recover desired size */ + jmp LBL(caml_allocN) +CFI_ENDPROC + +/* Call a C function from OCaml */ + +FUNCTION(G(caml_c_call)) +CFI_STARTPROC +LBL(caml_c_call): + /* Record lowest stack address and return address */ + popq %r12; CFI_ADJUST(-8) + STORE_VAR(%r12, caml_last_return_address) + STORE_VAR(%rsp, caml_bottom_of_stack) +#ifdef WITH_SPACETIME + /* Record the trie node hole pointer that corresponds to + [caml_last_return_address] */ + STORE_VAR(%r13, caml_spacetime_trie_node_ptr) +#endif + subq $8, %rsp; CFI_ADJUST(8) /* equivalent to pushq %r12 */ + /* Touch the stack to trigger a recoverable segfault + if insufficient space remains */ + subq STACK_PROBE_SIZE, %rsp + movq %rax, 0(%rsp) + addq STACK_PROBE_SIZE, %rsp + /* Make the exception handler and alloc ptr available to the C code */ + STORE_VAR(%r15, caml_young_ptr) + STORE_VAR(%r14, caml_exception_pointer) + /* Call the function (address in %rax) */ + /* No need to PREPARE_FOR_C_CALL since the caller already + reserved the stack space if needed (cf. amd64/proc.ml) */ + jmp *%rax +CFI_ENDPROC + +/* Start the OCaml program */ + +FUNCTION(G(caml_start_program)) + CFI_STARTPROC + /* Save callee-save registers */ + PUSH_CALLEE_SAVE_REGS + /* Initial entry point is G(caml_program) */ + LEA_VAR(caml_program, %r12) + /* Common code for caml_start_program and caml_callback* */ +LBL(caml_start_program): + /* Build a callback link */ +#ifdef WITH_SPACETIME + PUSH_VAR(caml_spacetime_trie_node_ptr) +#else + subq $8, %rsp; CFI_ADJUST (8) /* stack 16-aligned */ +#endif + PUSH_VAR(caml_gc_regs) + PUSH_VAR(caml_last_return_address) + PUSH_VAR(caml_bottom_of_stack) +#ifdef WITH_SPACETIME + /* Save arguments to caml_callback* */ + pushq %rax; CFI_ADJUST (8) + pushq %rbx; CFI_ADJUST (8) + pushq %rdi; CFI_ADJUST (8) + pushq %rsi; CFI_ADJUST (8) + /* No need to push %r12: it's callee-save. */ + movq %r12, C_ARG_1 + LEA_VAR(caml_start_program, C_ARG_2) + call GCALL(caml_spacetime_c_to_ocaml) + popq %rsi; CFI_ADJUST (-8) + popq %rdi; CFI_ADJUST (-8) + popq %rbx; CFI_ADJUST (-8) + popq %rax; CFI_ADJUST (-8) +#endif + /* Setup alloc ptr and exception ptr */ + LOAD_VAR(caml_young_ptr, %r15) + LOAD_VAR(caml_exception_pointer, %r14) + /* Build an exception handler */ + lea LBL(108)(%rip), %r13 + pushq %r13; CFI_ADJUST(8) + pushq %r14; CFI_ADJUST(8) + movq %rsp, %r14 +#ifdef WITH_SPACETIME + LOAD_VAR(caml_spacetime_trie_node_ptr, %r13) +#endif + /* Call the OCaml code */ + call *%r12 +LBL(107): + /* Pop the exception handler */ + popq %r14; CFI_ADJUST(-8) + popq %r12; CFI_ADJUST(-8) /* dummy register */ +LBL(109): + /* Update alloc ptr and exception ptr */ + STORE_VAR(%r15,caml_young_ptr) + STORE_VAR(%r14,caml_exception_pointer) + /* Pop the callback link, restoring the global variables */ + POP_VAR(caml_bottom_of_stack) + POP_VAR(caml_last_return_address) + POP_VAR(caml_gc_regs) +#ifdef WITH_SPACETIME + POP_VAR(caml_spacetime_trie_node_ptr) +#else + addq $8, %rsp; CFI_ADJUST (-8); +#endif + /* Restore callee-save registers. */ + POP_CALLEE_SAVE_REGS + /* Return to caller. */ + ret +LBL(108): + /* Exception handler*/ + /* Mark the bucket as an exception result and return it */ + orq $2, %rax + jmp LBL(109) +CFI_ENDPROC + +/* Raise an exception from OCaml */ + +FUNCTION(G(caml_raise_exn)) +CFI_STARTPROC + TESTL_VAR($1, caml_backtrace_active) + jne LBL(110) + movq %r14, %rsp + popq %r14 + ret +LBL(110): + movq %rax, %r12 /* Save exception bucket */ + movq %rax, C_ARG_1 /* arg 1: exception bucket */ +#ifdef WITH_FRAME_POINTERS + ENTER_FUNCTION + movq 8(%rsp), C_ARG_2 /* arg 2: pc of raise */ + leaq 16(%rsp), C_ARG_3 /* arg 3: sp at raise */ +#else + popq C_ARG_2 /* arg 2: pc of raise */ + movq %rsp, C_ARG_3 /* arg 3: sp at raise */ +#endif + movq %r14, C_ARG_4 /* arg 4: sp of handler */ + /* PR#5700: thanks to popq above, stack is now 16-aligned */ + /* Thanks to ENTER_FUNCTION, stack is now 16-aligned */ + PREPARE_FOR_C_CALL /* no need to cleanup after */ + call GCALL(caml_stash_backtrace) + movq %r12, %rax /* Recover exception bucket */ + movq %r14, %rsp + popq %r14 + ret +CFI_ENDPROC + +/* Raise an exception from C */ + +FUNCTION(G(caml_raise_exception)) +CFI_STARTPROC + TESTL_VAR($1, caml_backtrace_active) + jne LBL(112) + movq C_ARG_1, %rax + LOAD_VAR(caml_exception_pointer, %rsp) /* Cut stack */ + popq %r14 /* Recover previous exception handler */ + LOAD_VAR(caml_young_ptr, %r15) /* Reload alloc ptr */ + ret +LBL(112): +#ifdef WITH_FRAME_POINTERS + ENTER_FUNCTION ; +#endif + movq C_ARG_1, %r12 /* Save exception bucket */ + /* arg 1: exception bucket */ + LOAD_VAR(caml_last_return_address,C_ARG_2) /* arg 2: pc of raise */ + LOAD_VAR(caml_bottom_of_stack,C_ARG_3) /* arg 3: sp of raise */ + LOAD_VAR(caml_exception_pointer,C_ARG_4) /* arg 4: sp of handler */ +#ifndef WITH_FRAME_POINTERS + subq $8, %rsp /* PR#5700: maintain stack alignment */ +#endif + PREPARE_FOR_C_CALL /* no need to cleanup after */ + call GCALL(caml_stash_backtrace) + movq %r12, %rax /* Recover exception bucket */ + LOAD_VAR(caml_exception_pointer,%rsp) + popq %r14 /* Recover previous exception handler */ + LOAD_VAR(caml_young_ptr,%r15) /* Reload alloc ptr */ + ret +CFI_ENDPROC + +/* Raise a Stack_overflow exception on return from segv_handler() + (in runtime/signals_nat.c). On entry, the stack is full, so we + cannot record a backtrace. + No CFI information here since this function disrupts the stack + backtrace anyway. */ + +FUNCTION(G(caml_stack_overflow)) + LEA_VAR(caml_exn_Stack_overflow, %rax) + movq %r14, %rsp /* cut the stack */ + popq %r14 /* recover previous exn handler */ + ret /* jump to handler's code */ + +/* Callback from C to OCaml */ + +FUNCTION(G(caml_callback_exn)) +CFI_STARTPROC + /* Save callee-save registers */ + PUSH_CALLEE_SAVE_REGS + /* Initial loading of arguments */ + movq C_ARG_1, %rbx /* closure */ + movq C_ARG_2, %rax /* argument */ + movq 0(%rbx), %r12 /* code pointer */ + jmp LBL(caml_start_program) +CFI_ENDPROC + +FUNCTION(G(caml_callback2_exn)) +CFI_STARTPROC + /* Save callee-save registers */ + PUSH_CALLEE_SAVE_REGS + /* Initial loading of arguments */ + movq C_ARG_1, %rdi /* closure -- no op with Unix conventions */ + movq C_ARG_2, %rax /* first argument */ + movq C_ARG_3, %rbx /* second argument */ + LEA_VAR(caml_apply2, %r12) /* code pointer */ + jmp LBL(caml_start_program) +CFI_ENDPROC + +FUNCTION(G(caml_callback3_exn)) +CFI_STARTPROC + /* Save callee-save registers */ + PUSH_CALLEE_SAVE_REGS + /* Initial loading of arguments */ + movq C_ARG_2, %rax /* first argument */ + movq C_ARG_3, %rbx /* second argument */ + movq C_ARG_1, %rsi /* closure */ + movq C_ARG_4, %rdi /* third argument */ + LEA_VAR(caml_apply3, %r12) /* code pointer */ + jmp LBL(caml_start_program) +CFI_ENDPROC + +FUNCTION(G(caml_ml_array_bound_error)) +CFI_STARTPROC + LEA_VAR(caml_array_bound_error, %rax) + jmp LBL(caml_c_call) +CFI_ENDPROC + + .globl G(caml_system__code_end) +G(caml_system__code_end): + + .data + .globl G(caml_system__frametable) + .align EIGHT_ALIGN +G(caml_system__frametable): + .quad 1 /* one descriptor */ + .quad LBL(107) /* return address into callback */ + .value -1 /* negative frame size => use callback link */ + .value 0 /* no roots here */ + .align EIGHT_ALIGN + .quad 16 + .quad 0 + .string "amd64.S" + +#ifdef WITH_SPACETIME + .data + .globl G(caml_system__spacetime_shapes) + .align EIGHT_ALIGN +G(caml_system__spacetime_shapes): + .quad G(caml_start_program) + .quad 2 /* indirect call point to OCaml code */ + .quad LBL(107) /* in caml_start_program / caml_callback* */ + .quad 0 /* end of shapes for caml_start_program */ + .quad 0 /* end of shape table */ + .align EIGHT_ALIGN +#endif + +#if defined(SYS_macosx) + .literal16 +#elif defined(SYS_mingw64) || defined(SYS_cygwin) + .section .rdata,"dr" +#else + .section .rodata.cst8,"a",@progbits +#endif + .globl G(caml_negf_mask) + .align SIXTEEN_ALIGN +G(caml_negf_mask): + .quad 0x8000000000000000, 0 + .globl G(caml_absf_mask) + .align SIXTEEN_ALIGN +G(caml_absf_mask): + .quad 0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF + +#if defined(SYS_linux) + /* Mark stack as non-executable, PR#4564 */ + .section .note.GNU-stack,"",%progbits +#endif diff --git a/runtime/amd64nt.asm b/runtime/amd64nt.asm new file mode 100644 index 00000000..f7509ce1 --- /dev/null +++ b/runtime/amd64nt.asm @@ -0,0 +1,536 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Xavier Leroy, projet Gallium, INRIA Rocquencourt * +;* * +;* Copyright 2006 Institut National de Recherche en Informatique et * +;* en Automatique. * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +; Asm part of the runtime system, AMD64 processor, Intel syntax + +; Notes on Win64 calling conventions: +; function arguments in RCX, RDX, R8, R9 / XMM0 - XMM3 +; caller must reserve 32 bytes of stack space +; callee must preserve RBX, RBP, RSI, RDI, R12-R15, XMM6-XMM15 + + EXTRN caml_garbage_collection: NEAR + EXTRN caml_apply2: NEAR + EXTRN caml_apply3: NEAR + EXTRN caml_program: NEAR + EXTRN caml_array_bound_error: NEAR + EXTRN caml_young_limit: QWORD + EXTRN caml_young_ptr: QWORD + EXTRN caml_bottom_of_stack: QWORD + EXTRN caml_last_return_address: QWORD + EXTRN caml_gc_regs: QWORD + EXTRN caml_exception_pointer: QWORD + EXTRN caml_backtrace_pos: DWORD + EXTRN caml_backtrace_active: DWORD + EXTRN caml_stash_backtrace: NEAR +IFDEF WITH_SPACETIME + EXTRN caml_spacetime_trie_node_ptr: QWORD + EXTRN caml_spacetime_c_to_ocaml: NEAR +ENDIF + + .CODE + + PUBLIC caml_system__code_begin +caml_system__code_begin: + ret ; just one instruction, so that debuggers don't display + ; caml_system__code_begin instead of caml_call_gc + +; Allocation + + PUBLIC caml_call_gc + ALIGN 16 +caml_call_gc: + ; Record lowest stack address and return address + mov rax, [rsp] + mov caml_last_return_address, rax + lea rax, [rsp+8] + mov caml_bottom_of_stack, rax +L105: + ; Touch the stack to trigger a recoverable segfault + ; if insufficient space remains + sub rsp, 01000h + mov [rsp], rax + add rsp, 01000h + ; Save caml_young_ptr, caml_exception_pointer + mov caml_young_ptr, r15 + mov caml_exception_pointer, r14 +IFDEF WITH_SPACETIME + mov caml_spacetime_trie_node_ptr, r13 +ENDIF + ; Build array of registers, save it into caml_gc_regs + push rbp + push r11 + push r10 + push r13 + push r12 + push r9 + push r8 + push rcx + push rdx + push rsi + push rdi + push rbx + push rax + mov caml_gc_regs, rsp + ; Save floating-point registers + sub rsp, 16*8 + movsd QWORD PTR [rsp + 0*8], xmm0 + movsd QWORD PTR [rsp + 1*8], xmm1 + movsd QWORD PTR [rsp + 2*8], xmm2 + movsd QWORD PTR [rsp + 3*8], xmm3 + movsd QWORD PTR [rsp + 4*8], xmm4 + movsd QWORD PTR [rsp + 5*8], xmm5 + movsd QWORD PTR [rsp + 6*8], xmm6 + movsd QWORD PTR [rsp + 7*8], xmm7 + movsd QWORD PTR [rsp + 8*8], xmm8 + movsd QWORD PTR [rsp + 9*8], xmm9 + movsd QWORD PTR [rsp + 10*8], xmm10 + movsd QWORD PTR [rsp + 11*8], xmm11 + movsd QWORD PTR [rsp + 12*8], xmm12 + movsd QWORD PTR [rsp + 13*8], xmm13 + movsd QWORD PTR [rsp + 14*8], xmm14 + movsd QWORD PTR [rsp + 15*8], xmm15 + ; Call the garbage collector + sub rsp, 32 ; PR#5008: bottom 32 bytes are reserved for callee + call caml_garbage_collection + add rsp, 32 ; PR#5008 + ; Restore all regs used by the code generator + movsd xmm0, QWORD PTR [rsp + 0*8] + movsd xmm1, QWORD PTR [rsp + 1*8] + movsd xmm2, QWORD PTR [rsp + 2*8] + movsd xmm3, QWORD PTR [rsp + 3*8] + movsd xmm4, QWORD PTR [rsp + 4*8] + movsd xmm5, QWORD PTR [rsp + 5*8] + movsd xmm6, QWORD PTR [rsp + 6*8] + movsd xmm7, QWORD PTR [rsp + 7*8] + movsd xmm8, QWORD PTR [rsp + 8*8] + movsd xmm9, QWORD PTR [rsp + 9*8] + movsd xmm10, QWORD PTR [rsp + 10*8] + movsd xmm11, QWORD PTR [rsp + 11*8] + movsd xmm12, QWORD PTR [rsp + 12*8] + movsd xmm13, QWORD PTR [rsp + 13*8] + movsd xmm14, QWORD PTR [rsp + 14*8] + movsd xmm15, QWORD PTR [rsp + 15*8] + add rsp, 16*8 + pop rax + pop rbx + pop rdi + pop rsi + pop rdx + pop rcx + pop r8 + pop r9 + pop r12 + pop r13 + pop r10 + pop r11 + pop rbp + ; Restore caml_young_ptr, caml_exception_pointer + mov r15, caml_young_ptr + mov r14, caml_exception_pointer + ; Return to caller + ret + + PUBLIC caml_alloc1 + ALIGN 16 +caml_alloc1: + sub r15, 16 + cmp r15, caml_young_limit + jb L100 + ret +L100: + mov rax, [rsp + 0] + mov caml_last_return_address, rax + lea rax, [rsp + 8] + mov caml_bottom_of_stack, rax + sub rsp, 8 + call L105 + add rsp, 8 + jmp caml_alloc1 + + PUBLIC caml_alloc2 + ALIGN 16 +caml_alloc2: + sub r15, 24 + cmp r15, caml_young_limit + jb L101 + ret +L101: + mov rax, [rsp + 0] + mov caml_last_return_address, rax + lea rax, [rsp + 8] + mov caml_bottom_of_stack, rax + sub rsp, 8 + call L105 + add rsp, 8 + jmp caml_alloc2 + + PUBLIC caml_alloc3 + ALIGN 16 +caml_alloc3: + sub r15, 32 + cmp r15, caml_young_limit + jb L102 + ret +L102: + mov rax, [rsp + 0] + mov caml_last_return_address, rax + lea rax, [rsp + 8] + mov caml_bottom_of_stack, rax + sub rsp, 8 + call L105 + add rsp, 8 + jmp caml_alloc3 + + PUBLIC caml_allocN + ALIGN 16 +caml_allocN: + sub r15, rax + cmp r15, caml_young_limit + jb L103 + ret +L103: + push rax ; save desired size + mov rax, [rsp + 8] + mov caml_last_return_address, rax + lea rax, [rsp + 16] + mov caml_bottom_of_stack, rax + call L105 + pop rax ; recover desired size + jmp caml_allocN + +; Call a C function from OCaml + + PUBLIC caml_c_call + ALIGN 16 +caml_c_call: + ; Record lowest stack address and return address + pop r12 + mov caml_last_return_address, r12 + mov caml_bottom_of_stack, rsp +IFDEF WITH_SPACETIME + ; Record the trie node hole pointer that corresponds to + ; [caml_last_return_address] + mov caml_spacetime_trie_node_ptr, r13 +ENDIF + ; Touch the stack to trigger a recoverable segfault + ; if insufficient space remains + sub rsp, 01000h + mov [rsp], rax + add rsp, 01000h + ; Make the exception handler and alloc ptr available to the C code + mov caml_young_ptr, r15 + mov caml_exception_pointer, r14 + ; Call the function (address in rax) + call rax + ; Reload alloc ptr + mov r15, caml_young_ptr + ; Return to caller + push r12 + ret + +; Start the OCaml program + + PUBLIC caml_start_program + ALIGN 16 +caml_start_program: + ; Save callee-save registers + push rbx + push rbp + push rsi + push rdi + push r12 + push r13 + push r14 + push r15 + sub rsp, 8+10*16 ; stack 16-aligned + 10 saved xmm regs + movapd OWORD PTR [rsp + 0*16], xmm6 + movapd OWORD PTR [rsp + 1*16], xmm7 + movapd OWORD PTR [rsp + 2*16], xmm8 + movapd OWORD PTR [rsp + 3*16], xmm9 + movapd OWORD PTR [rsp + 4*16], xmm10 + movapd OWORD PTR [rsp + 5*16], xmm11 + movapd OWORD PTR [rsp + 6*16], xmm12 + movapd OWORD PTR [rsp + 7*16], xmm13 + movapd OWORD PTR [rsp + 8*16], xmm14 + movapd OWORD PTR [rsp + 9*16], xmm15 + ; Initial entry point is caml_program + lea r12, caml_program + ; Common code for caml_start_program and caml_callback* +L106: + ; Build a callback link +IFDEF WITH_SPACETIME + push caml_spacetime_trie_node_ptr +ELSE + sub rsp, 8 ; stack 16-aligned +ENDIF + push caml_gc_regs + push caml_last_return_address + push caml_bottom_of_stack +IFDEF WITH_SPACETIME + ; Save arguments to caml_callback + push rax + push rbx + push rdi + push rsi + ; No need to push r12: it is callee-save. + mov rcx, r12 + lea rdx, caml_start_program + call caml_spacetime_c_to_ocaml + pop rsi + pop rdi + pop rbx + pop rax +ENDIF + ; Setup alloc ptr and exception ptr + mov r15, caml_young_ptr + mov r14, caml_exception_pointer + ; Build an exception handler + lea r13, L108 + push r13 + push r14 + mov r14, rsp +IFDEF WITH_SPACETIME + mov r13, caml_spacetime_trie_node_ptr +ENDIF + ; Call the OCaml code + call r12 +L107: + ; Pop the exception handler + pop r14 + pop r12 ; dummy register +L109: + ; Update alloc ptr and exception ptr + mov caml_young_ptr, r15 + mov caml_exception_pointer, r14 + ; Pop the callback restoring, link the global variables + pop caml_bottom_of_stack + pop caml_last_return_address + pop caml_gc_regs +IFDEF WITH_SPACETIME + pop caml_spacetime_trie_node_ptr +ELSE + add rsp, 8 +ENDIF + ; Restore callee-save registers. + movapd xmm6, OWORD PTR [rsp + 0*16] + movapd xmm7, OWORD PTR [rsp + 1*16] + movapd xmm8, OWORD PTR [rsp + 2*16] + movapd xmm9, OWORD PTR [rsp + 3*16] + movapd xmm10, OWORD PTR [rsp + 4*16] + movapd xmm11, OWORD PTR [rsp + 5*16] + movapd xmm12, OWORD PTR [rsp + 6*16] + movapd xmm13, OWORD PTR [rsp + 7*16] + movapd xmm14, OWORD PTR [rsp + 8*16] + movapd xmm15, OWORD PTR [rsp + 9*16] + add rsp, 8+10*16 + pop r15 + pop r14 + pop r13 + pop r12 + pop rdi + pop rsi + pop rbp + pop rbx + ; Return to caller + ret +L108: + ; Exception handler + ; Mark the bucket as an exception result and return it + or rax, 2 + jmp L109 + +; Raise an exception from OCaml + + PUBLIC caml_raise_exn + ALIGN 16 +caml_raise_exn: + test caml_backtrace_active, 1 + jne L110 + mov rsp, r14 ; Cut stack + pop r14 ; Recover previous exception handler + ret ; Branch to handler +L110: + mov r12, rax ; Save exception bucket in r12 + mov rcx, rax ; Arg 1: exception bucket + mov rdx, [rsp] ; Arg 2: PC of raise + lea r8, [rsp+8] ; Arg 3: SP of raise + mov r9, r14 ; Arg 4: SP of handler + sub rsp, 32 ; Reserve 32 bytes on stack + call caml_stash_backtrace + mov rax, r12 ; Recover exception bucket + mov rsp, r14 ; Cut stack + pop r14 ; Recover previous exception handler + ret ; Branch to handler + +; Raise an exception from C + + PUBLIC caml_raise_exception + ALIGN 16 +caml_raise_exception: + test caml_backtrace_active, 1 + jne L112 + mov rax, rcx ; First argument is exn bucket + mov rsp, caml_exception_pointer + pop r14 ; Recover previous exception handler + mov r15, caml_young_ptr ; Reload alloc ptr + ret +L112: + mov r12, rcx ; Save exception bucket in r12 + ; Arg 1: exception bucket + mov rdx, caml_last_return_address ; Arg 2: PC of raise + mov r8, caml_bottom_of_stack ; Arg 3: SP of raise + mov r9, caml_exception_pointer ; Arg 4: SP of handler + sub rsp, 32 ; Reserve 32 bytes on stack + call caml_stash_backtrace + mov rax, r12 ; Recover exception bucket + mov rsp, caml_exception_pointer + pop r14 ; Recover previous exception handler + mov r15, caml_young_ptr ; Reload alloc ptr + ret + +; Callback from C to OCaml + + PUBLIC caml_callback_exn + ALIGN 16 +caml_callback_exn: + ; Save callee-save registers + push rbx + push rbp + push rsi + push rdi + push r12 + push r13 + push r14 + push r15 + sub rsp, 8+10*16 ; stack 16-aligned + 10 saved xmm regs + movapd OWORD PTR [rsp + 0*16], xmm6 + movapd OWORD PTR [rsp + 1*16], xmm7 + movapd OWORD PTR [rsp + 2*16], xmm8 + movapd OWORD PTR [rsp + 3*16], xmm9 + movapd OWORD PTR [rsp + 4*16], xmm10 + movapd OWORD PTR [rsp + 5*16], xmm11 + movapd OWORD PTR [rsp + 6*16], xmm12 + movapd OWORD PTR [rsp + 7*16], xmm13 + movapd OWORD PTR [rsp + 8*16], xmm14 + movapd OWORD PTR [rsp + 9*16], xmm15 + ; Initial loading of arguments + mov rbx, rcx ; closure + mov rax, rdx ; argument + mov r12, [rbx] ; code pointer + jmp L106 + + PUBLIC caml_callback2_exn + ALIGN 16 +caml_callback2_exn: + ; Save callee-save registers + push rbx + push rbp + push rsi + push rdi + push r12 + push r13 + push r14 + push r15 + sub rsp, 8+10*16 ; stack 16-aligned + 10 saved xmm regs + movapd OWORD PTR [rsp + 0*16], xmm6 + movapd OWORD PTR [rsp + 1*16], xmm7 + movapd OWORD PTR [rsp + 2*16], xmm8 + movapd OWORD PTR [rsp + 3*16], xmm9 + movapd OWORD PTR [rsp + 4*16], xmm10 + movapd OWORD PTR [rsp + 5*16], xmm11 + movapd OWORD PTR [rsp + 6*16], xmm12 + movapd OWORD PTR [rsp + 7*16], xmm13 + movapd OWORD PTR [rsp + 8*16], xmm14 + movapd OWORD PTR [rsp + 9*16], xmm15 + ; Initial loading of arguments + mov rdi, rcx ; closure + mov rax, rdx ; first argument + mov rbx, r8 ; second argument + lea r12, caml_apply2 ; code pointer + jmp L106 + + PUBLIC caml_callback3_exn + ALIGN 16 +caml_callback3_exn: + ; Save callee-save registers + push rbx + push rbp + push rsi + push rdi + push r12 + push r13 + push r14 + push r15 + sub rsp, 8+10*16 ; stack 16-aligned + 10 saved xmm regs + movapd OWORD PTR [rsp + 0*16], xmm6 + movapd OWORD PTR [rsp + 1*16], xmm7 + movapd OWORD PTR [rsp + 2*16], xmm8 + movapd OWORD PTR [rsp + 3*16], xmm9 + movapd OWORD PTR [rsp + 4*16], xmm10 + movapd OWORD PTR [rsp + 5*16], xmm11 + movapd OWORD PTR [rsp + 6*16], xmm12 + movapd OWORD PTR [rsp + 7*16], xmm13 + movapd OWORD PTR [rsp + 8*16], xmm14 + movapd OWORD PTR [rsp + 9*16], xmm15 + ; Initial loading of arguments + mov rsi, rcx ; closure + mov rax, rdx ; first argument + mov rbx, r8 ; second argument + mov rdi, r9 ; third argument + lea r12, caml_apply3 ; code pointer + jmp L106 + + PUBLIC caml_ml_array_bound_error + ALIGN 16 +caml_ml_array_bound_error: + lea rax, caml_array_bound_error + jmp caml_c_call + + PUBLIC caml_system__code_end +caml_system__code_end: + + .DATA + PUBLIC caml_system__frametable +caml_system__frametable LABEL QWORD + QWORD 1 ; one descriptor + QWORD L107 ; return address into callback + WORD -1 ; negative frame size => use callback link + WORD 0 ; no roots here + ALIGN 8 + +IFDEF WITH_SPACETIME + .DATA + PUBLIC caml_system__spacetime_shapes + ALIGN 8 +caml_system__spacetime_shapes LABEL QWORD + QWORD caml_start_program + QWORD 2 ; indirect call point to OCaml code + QWORD L107 ; in caml_start_program / caml_callback* + QWORD 0 ; end of shapes in caml_start_program + QWORD 0 ; end of shape table + ALIGN 8 +ENDIF + + PUBLIC caml_negf_mask + ALIGN 16 +caml_negf_mask LABEL QWORD + QWORD 8000000000000000H, 0 + + PUBLIC caml_absf_mask + ALIGN 16 +caml_absf_mask LABEL QWORD + QWORD 7FFFFFFFFFFFFFFFH, 0FFFFFFFFFFFFFFFFH + + END diff --git a/asmrun/arm.S b/runtime/arm.S similarity index 100% rename from asmrun/arm.S rename to runtime/arm.S diff --git a/runtime/arm64.S b/runtime/arm64.S new file mode 100644 index 00000000..bb8e1b5e --- /dev/null +++ b/runtime/arm64.S @@ -0,0 +1,579 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Gallium, INRIA Rocquencourt */ +/* */ +/* Copyright 2013 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Asm part of the runtime system, ARM processor, 64-bit mode */ +/* Must be preprocessed by cpp */ + +#include "caml/m.h" + +/* Special registers */ + +#define TRAP_PTR x26 +#define ALLOC_PTR x27 +#define ALLOC_LIMIT x28 +#define ARG x15 +#define TMP x16 +#define TMP2 x17 + +/* Support for CFI directives */ + +#if defined(ASM_CFI_SUPPORTED) +#define CFI_STARTPROC .cfi_startproc +#define CFI_ENDPROC .cfi_endproc +#define CFI_ADJUST(n) .cfi_adjust_cfa_offset n +#define CFI_REGISTER(r1,r2) .cfi_register r1,r2 +#define CFI_OFFSET(r,n) .cfi_offset r,n +#else +#define CFI_STARTPROC +#define CFI_ENDPROC +#define CFI_ADJUST(n) +#define CFI_REGISTER(r1,r2) +#define CFI_OFFSET(r,n) +#endif + +/* Support for profiling with gprof */ + +#define PROFILE + +/* Macros to load and store global variables. Destroy TMP2 */ + +#if defined(__PIC__) + +#define ADDRGLOBAL(reg,symb) \ + adrp TMP2, :got:symb; \ + ldr reg, [TMP2, #:got_lo12:symb] + +#define LOADGLOBAL(reg,symb) \ + ADDRGLOBAL(TMP2,symb); \ + ldr reg, [TMP2] + +#define STOREGLOBAL(reg,symb) \ + ADDRGLOBAL(TMP2,symb); \ + str reg, [TMP2] + +#define LOADGLOBAL32(reg,symb) \ + ADDRGLOBAL(TMP2,symb); \ + ldrsw reg, [TMP2] + +#else + +#define ADDRGLOBAL(reg,symb) \ + adrp reg, symb; \ + add reg, reg, #:lo12:symb + +#define LOADGLOBAL(reg,symb) \ + adrp TMP2, symb; \ + ldr reg, [TMP2, #:lo12:symb] + +#define STOREGLOBAL(reg,symb) \ + adrp TMP2, symb; \ + str reg, [TMP2, #:lo12:symb] + +#define LOADGLOBAL32(reg,symb) \ + adrp TMP2, symb; \ + ldrsw reg, [TMP2, #:lo12:symb] + +#endif + +/* Allocation functions and GC interface */ + + .globl caml_system__code_begin +caml_system__code_begin: + + .align 2 + .globl caml_call_gc +caml_call_gc: + CFI_STARTPROC + PROFILE + /* Record return address */ + STOREGLOBAL(x30, caml_last_return_address) + /* Record lowest stack address */ + mov TMP, sp + STOREGLOBAL(TMP, caml_bottom_of_stack) +.Lcaml_call_gc: + /* Set up stack space, saving return address and frame pointer */ + /* (2 regs RA/GP, 24 allocatable int regs, 24 caller-save float regs) * 8 */ + CFI_OFFSET(29, -400) + CFI_OFFSET(30, -392) + stp x29, x30, [sp, -400]! + CFI_ADJUST(400) + add x29, sp, #0 + /* Save allocatable integer registers on the stack, in the order + given in proc.ml */ + stp x0, x1, [sp, 16] + stp x2, x3, [sp, 32] + stp x4, x5, [sp, 48] + stp x6, x7, [sp, 64] + stp x8, x9, [sp, 80] + stp x10, x11, [sp, 96] + stp x12, x13, [sp, 112] + stp x14, x15, [sp, 128] + stp x19, x20, [sp, 144] + stp x21, x22, [sp, 160] + stp x23, x24, [sp, 176] + str x25, [sp, 192] + /* Save caller-save floating-point registers on the stack + (callee-saves are preserved by caml_garbage_collection) */ + stp d0, d1, [sp, 208] + stp d2, d3, [sp, 224] + stp d4, d5, [sp, 240] + stp d6, d7, [sp, 256] + stp d16, d17, [sp, 272] + stp d18, d19, [sp, 288] + stp d20, d21, [sp, 304] + stp d22, d23, [sp, 320] + stp d24, d25, [sp, 336] + stp d26, d27, [sp, 352] + stp d28, d29, [sp, 368] + stp d30, d31, [sp, 384] + /* Store pointer to saved integer registers in caml_gc_regs */ + add TMP, sp, #16 + STOREGLOBAL(TMP, caml_gc_regs) + /* Save current allocation pointer for debugging purposes */ + STOREGLOBAL(ALLOC_PTR, caml_young_ptr) + /* Save trap pointer in case an exception is raised during GC */ + STOREGLOBAL(TRAP_PTR, caml_exception_pointer) + /* Call the garbage collector */ + bl caml_garbage_collection + /* Restore registers */ + ldp x0, x1, [sp, 16] + ldp x2, x3, [sp, 32] + ldp x4, x5, [sp, 48] + ldp x6, x7, [sp, 64] + ldp x8, x9, [sp, 80] + ldp x10, x11, [sp, 96] + ldp x12, x13, [sp, 112] + ldp x14, x15, [sp, 128] + ldp x19, x20, [sp, 144] + ldp x21, x22, [sp, 160] + ldp x23, x24, [sp, 176] + ldr x25, [sp, 192] + ldp d0, d1, [sp, 208] + ldp d2, d3, [sp, 224] + ldp d4, d5, [sp, 240] + ldp d6, d7, [sp, 256] + ldp d16, d17, [sp, 272] + ldp d18, d19, [sp, 288] + ldp d20, d21, [sp, 304] + ldp d22, d23, [sp, 320] + ldp d24, d25, [sp, 336] + ldp d26, d27, [sp, 352] + ldp d28, d29, [sp, 368] + ldp d30, d31, [sp, 384] + /* Reload new allocation pointer and allocation limit */ + LOADGLOBAL(ALLOC_PTR, caml_young_ptr) + LOADGLOBAL(ALLOC_LIMIT, caml_young_limit) + /* Free stack space and return to caller */ + ldp x29, x30, [sp], 400 + ret + CFI_ENDPROC + .type caml_call_gc, %function + .size caml_call_gc, .-caml_call_gc + + .align 2 + .globl caml_alloc1 +caml_alloc1: + CFI_STARTPROC + PROFILE +1: sub ALLOC_PTR, ALLOC_PTR, #16 + cmp ALLOC_PTR, ALLOC_LIMIT + b.lo 2f + ret +2: stp x29, x30, [sp, -16]! + CFI_ADJUST(16) + /* Record the lowest address of the caller's stack frame. This is the + address immediately above the pair of words (x29 and x30) we just + pushed. Those must not be included since otherwise the distance from + [caml_bottom_of_stack] to the highest address in the caller's stack + frame won't match the frame size contained in the relevant frame + descriptor. */ + add x29, sp, #16 + STOREGLOBAL(x29, caml_bottom_of_stack) + add x29, sp, #0 + /* Record return address */ + STOREGLOBAL(x30, caml_last_return_address) + /* Call GC */ + bl .Lcaml_call_gc + /* Restore return address */ + ldp x29, x30, [sp], 16 + CFI_ADJUST(-16) + /* Try again */ + b 1b + CFI_ENDPROC + .type caml_alloc1, %function + .size caml_alloc1, .-caml_alloc1 + + .align 2 + .globl caml_alloc2 +caml_alloc2: + CFI_STARTPROC + PROFILE +1: sub ALLOC_PTR, ALLOC_PTR, #24 + cmp ALLOC_PTR, ALLOC_LIMIT + b.lo 2f + ret +2: stp x29, x30, [sp, -16]! + CFI_ADJUST(16) + /* Record the lowest address of the caller's stack frame. + See comment above. */ + add x29, sp, #16 + STOREGLOBAL(x29, caml_bottom_of_stack) + add x29, sp, #0 + /* Record return address */ + STOREGLOBAL(x30, caml_last_return_address) + /* Call GC */ + bl .Lcaml_call_gc + /* Restore return address */ + ldp x29, x30, [sp], 16 + CFI_ADJUST(-16) + /* Try again */ + b 1b + CFI_ENDPROC + .type caml_alloc2, %function + .size caml_alloc2, .-caml_alloc2 + + .align 2 + .globl caml_alloc3 +caml_alloc3: + CFI_STARTPROC + PROFILE +1: sub ALLOC_PTR, ALLOC_PTR, #32 + cmp ALLOC_PTR, ALLOC_LIMIT + b.lo 2f + ret +2: stp x29, x30, [sp, -16]! + CFI_ADJUST(16) + /* Record the lowest address of the caller's stack frame. + See comment above. */ + add x29, sp, #16 + STOREGLOBAL(x29, caml_bottom_of_stack) + add x29, sp, #0 + /* Record return address */ + STOREGLOBAL(x30, caml_last_return_address) + /* Call GC */ + bl .Lcaml_call_gc + /* Restore return address */ + ldp x29, x30, [sp], 16 + CFI_ADJUST(-16) + /* Try again */ + b 1b + CFI_ENDPROC + .type caml_alloc3, %function + .size caml_alloc3, .-caml_alloc3 + + .align 2 + .globl caml_allocN +caml_allocN: + CFI_STARTPROC + PROFILE +1: sub ALLOC_PTR, ALLOC_PTR, ARG + cmp ALLOC_PTR, ALLOC_LIMIT + b.lo 2f + ret +2: stp x29, x30, [sp, -16]! + CFI_ADJUST(16) + /* Record the lowest address of the caller's stack frame. + See comment above. */ + add x29, sp, #16 + STOREGLOBAL(x29, caml_bottom_of_stack) + add x29, sp, #0 + /* Record return address */ + STOREGLOBAL(x30, caml_last_return_address) + /* Call GC. This preserves ARG */ + bl .Lcaml_call_gc + /* Restore return address */ + ldp x29, x30, [sp], 16 + CFI_ADJUST(-16) + /* Try again */ + b 1b + CFI_ENDPROC + .type caml_allocN, %function + .size caml_allocN, .-caml_allocN + +/* Call a C function from OCaml */ +/* Function to call is in ARG */ + + .align 2 + .globl caml_c_call +caml_c_call: + CFI_STARTPROC + PROFILE + /* Preserve return address in callee-save register x19 */ + mov x19, x30 + CFI_REGISTER(30, 19) + /* Record lowest stack address and return address */ + STOREGLOBAL(x30, caml_last_return_address) + add TMP, sp, #0 + STOREGLOBAL(TMP, caml_bottom_of_stack) + /* Make the exception handler alloc ptr available to the C code */ + STOREGLOBAL(ALLOC_PTR, caml_young_ptr) + STOREGLOBAL(TRAP_PTR, caml_exception_pointer) + /* Call the function */ + blr ARG + /* Reload alloc ptr and alloc limit */ + LOADGLOBAL(ALLOC_PTR, caml_young_ptr) + LOADGLOBAL(ALLOC_LIMIT, caml_young_limit) + /* Return */ + ret x19 + CFI_ENDPROC + .type caml_c_call, %function + .size caml_c_call, .-caml_c_call + +/* Start the OCaml program */ + + .align 2 + .globl caml_start_program +caml_start_program: + CFI_STARTPROC + PROFILE + ADDRGLOBAL(ARG, caml_program) + +/* Code shared with caml_callback* */ +/* Address of OCaml code to call is in ARG */ +/* Arguments to the OCaml code are in x0...x7 */ + +.Ljump_to_caml: + /* Set up stack frame and save callee-save registers */ + CFI_OFFSET(29, -160) + CFI_OFFSET(30, -152) + stp x29, x30, [sp, -160]! + CFI_ADJUST(160) + add x29, sp, #0 + stp x19, x20, [sp, 16] + stp x21, x22, [sp, 32] + stp x23, x24, [sp, 48] + stp x25, x26, [sp, 64] + stp x27, x28, [sp, 80] + stp d8, d9, [sp, 96] + stp d10, d11, [sp, 112] + stp d12, d13, [sp, 128] + stp d14, d15, [sp, 144] + /* Setup a callback link on the stack */ + LOADGLOBAL(x8, caml_bottom_of_stack) + LOADGLOBAL(x9, caml_last_return_address) + LOADGLOBAL(x10, caml_gc_regs) + stp x8, x9, [sp, -32]! /* 16-byte alignment */ + CFI_ADJUST(32) + str x10, [sp, 16] + /* Setup a trap frame to catch exceptions escaping the OCaml code */ + LOADGLOBAL(x8, caml_exception_pointer) + adr x9, .Ltrap_handler + stp x8, x9, [sp, -16]! + CFI_ADJUST(16) + add TRAP_PTR, sp, #0 + /* Reload allocation pointers */ + LOADGLOBAL(ALLOC_PTR, caml_young_ptr) + LOADGLOBAL(ALLOC_LIMIT, caml_young_limit) + /* Call the OCaml code */ + blr ARG +.Lcaml_retaddr: + /* Pop the trap frame, restoring caml_exception_pointer */ + ldr x8, [sp], 16 + CFI_ADJUST(-16) + STOREGLOBAL(x8, caml_exception_pointer) + /* Pop the callback link, restoring the global variables */ +.Lreturn_result: + ldr x10, [sp, 16] + ldp x8, x9, [sp], 32 + CFI_ADJUST(-32) + STOREGLOBAL(x8, caml_bottom_of_stack) + STOREGLOBAL(x9, caml_last_return_address) + STOREGLOBAL(x10, caml_gc_regs) + /* Update allocation pointer */ + STOREGLOBAL(ALLOC_PTR, caml_young_ptr) + /* Reload callee-save registers and return address */ + ldp x19, x20, [sp, 16] + ldp x21, x22, [sp, 32] + ldp x23, x24, [sp, 48] + ldp x25, x26, [sp, 64] + ldp x27, x28, [sp, 80] + ldp d8, d9, [sp, 96] + ldp d10, d11, [sp, 112] + ldp d12, d13, [sp, 128] + ldp d14, d15, [sp, 144] + ldp x29, x30, [sp], 160 + CFI_ADJUST(-160) + /* Return to C caller */ + ret + CFI_ENDPROC + .type .Lcaml_retaddr, %function + .size .Lcaml_retaddr, .-.Lcaml_retaddr + .type caml_start_program, %function + .size caml_start_program, .-caml_start_program + +/* The trap handler */ + + .align 2 +.Ltrap_handler: + CFI_STARTPROC + /* Save exception pointer */ + STOREGLOBAL(TRAP_PTR, caml_exception_pointer) + /* Encode exception bucket as an exception result */ + orr x0, x0, #2 + /* Return it */ + b .Lreturn_result + CFI_ENDPROC + .type .Ltrap_handler, %function + .size .Ltrap_handler, .-.Ltrap_handler + +/* Raise an exception from OCaml */ + + .align 2 + .globl caml_raise_exn +caml_raise_exn: + CFI_STARTPROC + PROFILE + /* Test if backtrace is active */ + LOADGLOBAL32(TMP, caml_backtrace_active) + cbnz TMP, 2f +1: /* Cut stack at current trap handler */ + mov sp, TRAP_PTR + /* Pop previous handler and jump to it */ + ldr TMP, [sp, 8] + ldr TRAP_PTR, [sp], 16 + br TMP +2: /* Preserve exception bucket in callee-save register x19 */ + mov x19, x0 + /* Stash the backtrace */ + /* arg1: exn bucket, already in x0 */ + mov x1, x30 /* arg2: pc of raise */ + add x2, sp, #0 /* arg3: sp of raise */ + mov x3, TRAP_PTR /* arg4: sp of handler */ + bl caml_stash_backtrace + /* Restore exception bucket and raise */ + mov x0, x19 + b 1b + CFI_ENDPROC + .type caml_raise_exn, %function + .size caml_raise_exn, .-caml_raise_exn + +/* Raise an exception from C */ + + .align 2 + .globl caml_raise_exception +caml_raise_exception: + CFI_STARTPROC + PROFILE + /* Reload trap ptr, alloc ptr and alloc limit */ + LOADGLOBAL(TRAP_PTR, caml_exception_pointer) + LOADGLOBAL(ALLOC_PTR, caml_young_ptr) + LOADGLOBAL(ALLOC_LIMIT, caml_young_limit) + /* Test if backtrace is active */ + LOADGLOBAL32(TMP, caml_backtrace_active) + cbnz TMP, 2f +1: /* Cut stack at current trap handler */ + mov sp, TRAP_PTR + /* Pop previous handler and jump to it */ + ldr TMP, [sp, 8] + ldr TRAP_PTR, [sp], 16 + br TMP +2: /* Preserve exception bucket in callee-save register x19 */ + mov x19, x0 + /* Stash the backtrace */ + /* arg1: exn bucket, already in x0 */ + LOADGLOBAL(x1, caml_last_return_address) /* arg2: pc of raise */ + LOADGLOBAL(x2, caml_bottom_of_stack) /* arg3: sp of raise */ + mov x3, TRAP_PTR /* arg4: sp of handler */ + bl caml_stash_backtrace + /* Restore exception bucket and raise */ + mov x0, x19 + b 1b + CFI_ENDPROC + .type caml_raise_exception, %function + .size caml_raise_exception, .-caml_raise_exception + +/* Callback from C to OCaml */ + + .align 2 + .globl caml_callback_exn +caml_callback_exn: + CFI_STARTPROC + PROFILE + /* Initial shuffling of arguments (x0 = closure, x1 = first arg) */ + mov TMP, x0 + mov x0, x1 /* x0 = first arg */ + mov x1, TMP /* x1 = closure environment */ + ldr ARG, [TMP] /* code pointer */ + b .Ljump_to_caml + CFI_ENDPROC + .type caml_callback_exn, %function + .size caml_callback_exn, .-caml_callback_exn + + .align 2 + .globl caml_callback2_exn +caml_callback2_exn: + CFI_STARTPROC + PROFILE + /* Initial shuffling of arguments (x0 = closure, x1 = arg1, x2 = arg2) */ + mov TMP, x0 + mov x0, x1 /* x0 = first arg */ + mov x1, x2 /* x1 = second arg */ + mov x2, TMP /* x2 = closure environment */ + ADDRGLOBAL(ARG, caml_apply2) + b .Ljump_to_caml + CFI_ENDPROC + .type caml_callback2_exn, %function + .size caml_callback2_exn, .-caml_callback2_exn + + .align 2 + .globl caml_callback3_exn +caml_callback3_exn: + CFI_STARTPROC + PROFILE + /* Initial shuffling of arguments */ + /* (x0 = closure, x1 = arg1, x2 = arg2, x3 = arg3) */ + mov TMP, x0 + mov x0, x1 /* x0 = first arg */ + mov x1, x2 /* x1 = second arg */ + mov x2, x3 /* x2 = third arg */ + mov x3, TMP /* x3 = closure environment */ + ADDRGLOBAL(ARG, caml_apply3) + b .Ljump_to_caml + CFI_ENDPROC + .type caml_callback3_exn, %function + .size caml_callback3_exn, .-caml_callback3_exn + + .align 2 + .globl caml_ml_array_bound_error +caml_ml_array_bound_error: + CFI_STARTPROC + PROFILE + /* Load address of [caml_array_bound_error] in ARG */ + ADDRGLOBAL(ARG, caml_array_bound_error) + /* Call that function */ + b caml_c_call + CFI_ENDPROC + .type caml_ml_array_bound_error, %function + .size caml_ml_array_bound_error, .-caml_ml_array_bound_error + + .globl caml_system__code_end +caml_system__code_end: + +/* GC roots for callback */ + + .data + .align 3 + .globl caml_system__frametable +caml_system__frametable: + .quad 1 /* one descriptor */ + .quad .Lcaml_retaddr /* return address into callback */ + .short -1 /* negative frame size => use callback link */ + .short 0 /* no roots */ + .align 3 + .type caml_system__frametable, %object + .size caml_system__frametable, .-caml_system__frametable + +/* Mark stack as non-executable */ + .section .note.GNU-stack,"",%progbits diff --git a/runtime/array.c b/runtime/array.c new file mode 100644 index 00000000..e4da1db8 --- /dev/null +++ b/runtime/array.c @@ -0,0 +1,591 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Operations on arrays */ +#include +#include "caml/alloc.h" +#include "caml/fail.h" +#include "caml/memory.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/signals.h" +/* Why is caml/spacetime.h included conditionnally sometimes and not here ? */ +#include "caml/spacetime.h" + +static const mlsize_t mlsize_t_max = -1; + +/* returns number of elements (either fields or floats) */ +/* [ 'a array -> int ] */ +CAMLexport mlsize_t caml_array_length(value array) +{ +#ifdef FLAT_FLOAT_ARRAY + if (Tag_val(array) == Double_array_tag) + return Wosize_val(array) / Double_wosize; + else +#endif + return Wosize_val(array); +} + +CAMLexport int caml_is_double_array(value array) +{ + return (Tag_val(array) == Double_array_tag); +} + +/* Note: the OCaml types on the following primitives will work both with + and without the -no-flat-float-array configure-time option. If you + respect them, your C code should work in both configurations. +*/ + +/* [ 'a array -> int -> 'a ] where 'a != float */ +CAMLprim value caml_array_get_addr(value array, value index) +{ + intnat idx = Long_val(index); + if (idx < 0 || idx >= Wosize_val(array)) caml_array_bound_error(); + return Field(array, idx); +} + +/* [ float array -> int -> float ] */ +CAMLprim value caml_array_get_float(value array, value index) +{ + intnat idx = Long_val(index); +#ifdef FLAT_FLOAT_ARRAY + double d; + value res; + + if (idx < 0 || idx >= Wosize_val(array) / Double_wosize) + caml_array_bound_error(); + d = Double_flat_field(array, idx); +#define Setup_for_gc +#define Restore_after_gc + Alloc_small(res, Double_wosize, Double_tag); +#undef Setup_for_gc +#undef Restore_after_gc + Store_double_val(res, d); + return res; +#else + CAMLassert (Tag_val (array) != Double_array_tag); + if (idx < 0 || idx >= Wosize_val(array)) caml_array_bound_error(); + return Field(array, idx); +#endif /* FLAT_FLOAT_ARRAY */ +} + +/* [ 'a array -> int -> 'a ] */ +CAMLprim value caml_array_get(value array, value index) +{ +#ifdef FLAT_FLOAT_ARRAY + if (Tag_val(array) == Double_array_tag) + return caml_array_get_float(array, index); +#else + CAMLassert (Tag_val(array) != Double_array_tag); +#endif + return caml_array_get_addr(array, index); +} + +/* [ floatarray -> int -> float ] */ +CAMLprim value caml_floatarray_get(value array, value index) +{ + intnat idx = Long_val(index); + double d; + value res; + + CAMLassert (Tag_val(array) == Double_array_tag); + if (idx < 0 || idx >= Wosize_val(array) / Double_wosize) + caml_array_bound_error(); + d = Double_flat_field(array, idx); +#define Setup_for_gc +#define Restore_after_gc + Alloc_small(res, Double_wosize, Double_tag); +#undef Setup_for_gc +#undef Restore_after_gc + Store_double_val(res, d); + return res; +} + +/* [ 'a array -> int -> 'a -> unit ] where 'a != float */ +CAMLprim value caml_array_set_addr(value array, value index, value newval) +{ + intnat idx = Long_val(index); + if (idx < 0 || idx >= Wosize_val(array)) caml_array_bound_error(); + Modify(&Field(array, idx), newval); + return Val_unit; +} + +/* [ float array -> int -> float -> unit ] */ +CAMLprim value caml_array_set_float(value array, value index, value newval) +{ + intnat idx = Long_val(index); +#ifdef FLAT_FLOAT_ARRAY + double d = Double_val (newval); + if (idx < 0 || idx >= Wosize_val(array) / Double_wosize) + caml_array_bound_error(); + Store_double_flat_field(array, idx, d); +#else + CAMLassert (Tag_val (array) != Double_array_tag); + if (idx < 0 || idx >= Wosize_val(array)) caml_array_bound_error(); + Modify(&Field(array, idx), newval); +#endif + return Val_unit; +} + +/* [ 'a array -> int -> 'a -> unit ] */ +CAMLprim value caml_array_set(value array, value index, value newval) +{ +#ifdef FLAT_FLOAT_ARRAY + if (Tag_val(array) == Double_array_tag) + return caml_array_set_float(array, index, newval); +#else + CAMLassert (Tag_val(array) != Double_array_tag); +#endif + return caml_array_set_addr(array, index, newval); +} + +/* [ floatarray -> int -> float -> unit ] */ +CAMLprim value caml_floatarray_set(value array, value index, value newval) +{ + intnat idx = Long_val(index); + double d = Double_val (newval); + CAMLassert (Tag_val(array) == Double_array_tag); + if (idx < 0 || idx >= Wosize_val(array) / Double_wosize) + caml_array_bound_error(); + Store_double_flat_field(array, idx, d); + return Val_unit; +} + +/* [ float array -> int -> float ] */ +CAMLprim value caml_array_unsafe_get_float(value array, value index) +{ + intnat idx = Long_val (index); +#ifdef FLAT_FLOAT_ARRAY + double d; + value res; + + d = Double_flat_field(array, idx); +#define Setup_for_gc +#define Restore_after_gc + Alloc_small(res, Double_wosize, Double_tag); +#undef Setup_for_gc +#undef Restore_after_gc + Store_double_val(res, d); + return res; +#else /* FLAT_FLOAT_ARRAY */ + CAMLassert (Tag_val(array) != Double_array_tag); + return Field(array, idx); +#endif /* FLAT_FLOAT_ARRAY */ +} + +/* [ 'a array -> int -> 'a ] */ +CAMLprim value caml_array_unsafe_get(value array, value index) +{ +#ifdef FLAT_FLOAT_ARRAY + if (Tag_val(array) == Double_array_tag) + return caml_array_unsafe_get_float(array, index); +#else + CAMLassert (Tag_val(array) != Double_array_tag); +#endif + return Field(array, Long_val(index)); +} + +/* [ floatarray -> int -> float ] */ +CAMLprim value caml_floatarray_unsafe_get(value array, value index) +{ + intnat idx = Long_val(index); + double d; + value res; + + CAMLassert (Tag_val(array) == Double_array_tag); + d = Double_flat_field(array, idx); +#define Setup_for_gc +#define Restore_after_gc + Alloc_small(res, Double_wosize, Double_tag); +#undef Setup_for_gc +#undef Restore_after_gc + Store_double_val(res, d); + return res; +} + +/* [ 'a array -> int -> 'a -> unit ] where 'a != float */ +CAMLprim value caml_array_unsafe_set_addr(value array, value index,value newval) +{ + intnat idx = Long_val(index); + Modify(&Field(array, idx), newval); + return Val_unit; +} + +/* [ float array -> int -> float -> unit ] */ +CAMLprim value caml_array_unsafe_set_float(value array,value index,value newval) +{ + intnat idx = Long_val(index); +#ifdef FLAT_FLOAT_ARRAY + double d = Double_val (newval); + Store_double_flat_field(array, idx, d); +#else + Modify(&Field(array, idx), newval); +#endif + return Val_unit; +} + +/* [ 'a array -> int -> 'a -> unit ] */ +CAMLprim value caml_array_unsafe_set(value array, value index, value newval) +{ +#ifdef FLAT_FLOAT_ARRAY + if (Tag_val(array) == Double_array_tag) + return caml_array_unsafe_set_float(array, index, newval); +#else + CAMLassert (Tag_val(array) != Double_array_tag); +#endif + return caml_array_unsafe_set_addr(array, index, newval); +} + +/* [ floatarray -> int -> float -> unit ] */ +CAMLprim value caml_floatarray_unsafe_set(value array, value index,value newval) +{ + intnat idx = Long_val(index); + double d = Double_val (newval); + Store_double_flat_field(array, idx, d); + return Val_unit; +} + +/* [len] is a [value] representing number of floats. */ +/* [ int -> floatarray ] */ +CAMLprim value caml_floatarray_create(value len) +{ + mlsize_t wosize = Long_val(len) * Double_wosize; + value result; + if (wosize <= Max_young_wosize){ + if (wosize == 0) + return Atom(0); + else +#define Setup_for_gc +#define Restore_after_gc + Alloc_small (result, wosize, Double_array_tag); +#undef Setup_for_gc +#undef Restore_after_gc + }else if (wosize > Max_wosize) + caml_invalid_argument("Float.Array.create"); + else { + result = caml_alloc_shr (wosize, Double_array_tag); + result = caml_check_urgent_gc (result); + } + return result; +} + +/* [len] is a [value] representing number of words or floats */ +/* Spacetime profiling assumes that this function is only called from OCaml. */ +CAMLprim value caml_make_vect(value len, value init) +{ + CAMLparam2 (len, init); + CAMLlocal1 (res); + mlsize_t size, i; + + size = Long_val(len); + if (size == 0) { + res = Atom(0); +#ifdef FLAT_FLOAT_ARRAY + } else if (Is_block(init) + && Is_in_value_area(init) + && Tag_val(init) == Double_tag) { + mlsize_t wsize; + double d; + d = Double_val(init); + wsize = size * Double_wosize; + if (wsize > Max_wosize) caml_invalid_argument("Array.make"); + res = caml_alloc(wsize, Double_array_tag); + for (i = 0; i < size; i++) { + Store_double_flat_field(res, i, d); + } +#endif + } else { + if (size <= Max_young_wosize) { + uintnat profinfo; + Get_my_profinfo_with_cached_backtrace(profinfo, size); + res = caml_alloc_small_with_my_or_given_profinfo(size, 0, profinfo); + for (i = 0; i < size; i++) Field(res, i) = init; + } + else if (size > Max_wosize) caml_invalid_argument("Array.make"); + else if (Is_block(init) && Is_young(init)) { + /* We don't want to create so many major-to-minor references, + so [init] is moved to the major heap by doing a minor GC. */ + CAML_INSTR_INT ("force_minor/make_vect@", 1); + caml_request_minor_gc (); + caml_gc_dispatch (); + res = caml_alloc_shr(size, 0); + for (i = 0; i < size; i++) Field(res, i) = init; + res = caml_check_urgent_gc (res); + } + else { + res = caml_alloc_shr(size, 0); + for (i = 0; i < size; i++) caml_initialize(&Field(res, i), init); + res = caml_check_urgent_gc (res); + } + } + CAMLreturn (res); +} + +/* [len] is a [value] representing number of floats */ +/* [ int -> float array ] */ +CAMLprim value caml_make_float_vect(value len) +{ +#ifdef FLAT_FLOAT_ARRAY + return caml_floatarray_create (len); +#else + static value uninitialized_float = Val_unit; + if (uninitialized_float == Val_unit){ + uninitialized_float = caml_alloc_shr (Double_wosize, Double_tag); + caml_register_generational_global_root (&uninitialized_float); + } + return caml_make_vect (len, uninitialized_float); +#endif +} + +/* This primitive is used internally by the compiler to compile + explicit array expressions. + For float arrays when FLAT_FLOAT_ARRAY is true, it takes an array of + boxed floats and returns the corresponding flat-allocated [float array]. + In all other cases, it just returns its argument unchanged. +*/ +CAMLprim value caml_make_array(value init) +{ +#ifdef FLAT_FLOAT_ARRAY + CAMLparam1 (init); + mlsize_t wsize, size, i; + CAMLlocal2 (v, res); + + size = Wosize_val(init); + if (size == 0) { + CAMLreturn (init); + } else { + v = Field(init, 0); + if (Is_long(v) + || ! Is_in_value_area(v) + || Tag_val(v) != Double_tag) { + CAMLreturn (init); + } else { + wsize = size * Double_wosize; + if (wsize <= Max_young_wosize) { + res = caml_alloc_small(wsize, Double_array_tag); + } else { + res = caml_alloc_shr(wsize, Double_array_tag); + res = caml_check_urgent_gc(res); + } + for (i = 0; i < size; i++) { + double d = Double_val(Field(init, i)); + Store_double_flat_field(res, i, d); + } + CAMLreturn (res); + } + } +#else + return init; +#endif +} + +/* Blitting */ + +CAMLprim value caml_array_blit(value a1, value ofs1, value a2, value ofs2, + value n) +{ + value * src, * dst; + intnat count; + +#ifdef FLAT_FLOAT_ARRAY + if (Tag_val(a2) == Double_array_tag) { + /* Arrays of floats. The values being copied are floats, not + pointer, so we can do a direct copy. memmove takes care of + potential overlap between the copied areas. */ + memmove((double *)a2 + Long_val(ofs2), + (double *)a1 + Long_val(ofs1), + Long_val(n) * sizeof(double)); + return Val_unit; + } +#endif + CAMLassert (Tag_val(a2) != Double_array_tag); + if (Is_young(a2)) { + /* Arrays of values, destination is in young generation. + Here too we can do a direct copy since this cannot create + old-to-young pointers, nor mess up with the incremental major GC. + Again, memmove takes care of overlap. */ + memmove(&Field(a2, Long_val(ofs2)), + &Field(a1, Long_val(ofs1)), + Long_val(n) * sizeof(value)); + return Val_unit; + } + /* Array of values, destination is in old generation. + We must use caml_modify. */ + count = Long_val(n); + if (a1 == a2 && Long_val(ofs1) < Long_val(ofs2)) { + /* Copy in descending order */ + for (dst = &Field(a2, Long_val(ofs2) + count - 1), + src = &Field(a1, Long_val(ofs1) + count - 1); + count > 0; + count--, src--, dst--) { + caml_modify(dst, *src); + } + } else { + /* Copy in ascending order */ + for (dst = &Field(a2, Long_val(ofs2)), src = &Field(a1, Long_val(ofs1)); + count > 0; + count--, src++, dst++) { + caml_modify(dst, *src); + } + } + /* Many caml_modify in a row can create a lot of old-to-young refs. + Give the minor GC a chance to run if it needs to. */ + caml_check_urgent_gc(Val_unit); + return Val_unit; +} + +/* A generic function for extraction and concatenation of sub-arrays */ + +static value caml_array_gather(intnat num_arrays, + value arrays[/*num_arrays*/], + intnat offsets[/*num_arrays*/], + intnat lengths[/*num_arrays*/]) +{ + CAMLparamN(arrays, num_arrays); + value res; /* no need to register it as a root */ +#ifdef FLAT_FLOAT_ARRAY + int isfloat = 0; + mlsize_t wsize; +#endif + mlsize_t i, size, count, pos; + value * src; + + /* Determine total size and whether result array is an array of floats */ + size = 0; + for (i = 0; i < num_arrays; i++) { + if (mlsize_t_max - lengths[i] < size) caml_invalid_argument("Array.concat"); + size += lengths[i]; +#ifdef FLAT_FLOAT_ARRAY + if (Tag_val(arrays[i]) == Double_array_tag) isfloat = 1; +#endif + } + if (size == 0) { + /* If total size = 0, just return empty array */ + res = Atom(0); + } +#ifdef FLAT_FLOAT_ARRAY + else if (isfloat) { + /* This is an array of floats. We can use memcpy directly. */ + if (size > Max_wosize/Double_wosize) caml_invalid_argument("Array.concat"); + wsize = size * Double_wosize; + res = caml_alloc(wsize, Double_array_tag); + for (i = 0, pos = 0; i < num_arrays; i++) { + memcpy((double *)res + pos, + (double *)arrays[i] + offsets[i], + lengths[i] * sizeof(double)); + pos += lengths[i]; + } + CAMLassert(pos == size); + } +#endif + else if (size <= Max_young_wosize) { + /* Array of values, small enough to fit in young generation. + We can use memcpy directly. */ + res = caml_alloc_small(size, 0); + for (i = 0, pos = 0; i < num_arrays; i++) { + memcpy(&Field(res, pos), + &Field(arrays[i], offsets[i]), + lengths[i] * sizeof(value)); + pos += lengths[i]; + } + CAMLassert(pos == size); + } + else if (size > Max_wosize) { + /* Array of values, too big. */ + caml_invalid_argument("Array.concat"); + } else { + /* Array of values, must be allocated in old generation and filled + using caml_initialize. */ + res = caml_alloc_shr(size, 0); + for (i = 0, pos = 0; i < num_arrays; i++) { + for (src = &Field(arrays[i], offsets[i]), count = lengths[i]; + count > 0; + count--, src++, pos++) { + caml_initialize(&Field(res, pos), *src); + } + } + CAMLassert(pos == size); + + /* Many caml_initialize in a row can create a lot of old-to-young + refs. Give the minor GC a chance to run if it needs to. */ + res = caml_check_urgent_gc(res); + } + CAMLreturn (res); +} + +CAMLprim value caml_array_sub(value a, value ofs, value len) +{ + value arrays[1] = { a }; + intnat offsets[1] = { Long_val(ofs) }; + intnat lengths[1] = { Long_val(len) }; + return caml_array_gather(1, arrays, offsets, lengths); +} + +CAMLprim value caml_array_append(value a1, value a2) +{ + value arrays[2] = { a1, a2 }; + intnat offsets[2] = { 0, 0 }; + intnat lengths[2] = { caml_array_length(a1), caml_array_length(a2) }; + return caml_array_gather(2, arrays, offsets, lengths); +} + +CAMLprim value caml_array_concat(value al) +{ +#define STATIC_SIZE 16 + value static_arrays[STATIC_SIZE], * arrays; + intnat static_offsets[STATIC_SIZE], * offsets; + intnat static_lengths[STATIC_SIZE], * lengths; + intnat n, i; + value l, res; + + /* Length of list = number of arrays */ + for (n = 0, l = al; l != Val_int(0); l = Field(l, 1)) n++; + /* Allocate extra storage if too many arrays */ + if (n <= STATIC_SIZE) { + arrays = static_arrays; + offsets = static_offsets; + lengths = static_lengths; + } else { + arrays = caml_stat_alloc(n * sizeof(value)); + offsets = caml_stat_alloc_noexc(n * sizeof(intnat)); + if (offsets == NULL) { + caml_stat_free(arrays); + caml_raise_out_of_memory(); + } + lengths = caml_stat_alloc_noexc(n * sizeof(value)); + if (lengths == NULL) { + caml_stat_free(offsets); + caml_stat_free(arrays); + caml_raise_out_of_memory(); + } + } + /* Build the parameters to caml_array_gather */ + for (i = 0, l = al; l != Val_int(0); l = Field(l, 1), i++) { + arrays[i] = Field(l, 0); + offsets[i] = 0; + lengths[i] = caml_array_length(Field(l, 0)); + } + /* Do the concatenation */ + res = caml_array_gather(n, arrays, offsets, lengths); + /* Free the extra storage if needed */ + if (n > STATIC_SIZE) { + caml_stat_free(arrays); + caml_stat_free(offsets); + caml_stat_free(lengths); + } + return res; +} diff --git a/runtime/backtrace.c b/runtime/backtrace.c new file mode 100644 index 00000000..a3c2c08f --- /dev/null +++ b/runtime/backtrace.c @@ -0,0 +1,349 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Stack backtrace for uncaught exceptions */ + +#include +#include +#include + +#include "caml/alloc.h" +#include "caml/memory.h" +#include "caml/backtrace.h" +#include "caml/backtrace_prim.h" +#include "caml/fail.h" + +/* The table of debug information fragments */ +struct ext_table caml_debug_info; + +CAMLexport int32_t caml_backtrace_active = 0; +CAMLexport int32_t caml_backtrace_pos = 0; +CAMLexport backtrace_slot * caml_backtrace_buffer = NULL; +CAMLexport value caml_backtrace_last_exn = Val_unit; + +void caml_init_backtrace(void) +{ + caml_register_global_root(&caml_backtrace_last_exn); +} + +/* Start or stop the backtrace machinery */ +CAMLprim value caml_record_backtrace(value vflag) +{ + int flag = Int_val(vflag); + + if (flag != caml_backtrace_active) { + caml_backtrace_active = flag; + caml_backtrace_pos = 0; + caml_backtrace_last_exn = Val_unit; + /* Note: We do lazy initialization of caml_backtrace_buffer when + needed in order to simplify the interface with the thread + library (thread creation doesn't need to allocate + caml_backtrace_buffer). So we don't have to allocate it here. + */ + } + return Val_unit; +} + +/* Return the status of the backtrace machinery */ +CAMLprim value caml_backtrace_status(value vunit) +{ + return Val_bool(caml_backtrace_active); +} + +/* Print location information -- same behavior as in Printexc + + note that the test for compiler-inserted raises is slightly redundant: + (!li->loc_valid && li->loc_is_raise) + caml_debuginfo_location guarantees that when li->loc_valid is + 0, then li->loc_is_raise is always 1, so the latter test is + useless. We kept it to keep code identical to the runtime/ + implementation. */ +static void print_location(struct caml_loc_info * li, int index) +{ + char * info; + char * inlined; + + /* Ignore compiler-inserted raise */ + if (!li->loc_valid && li->loc_is_raise) return; + + if (li->loc_is_raise) { + /* Initial raise if index == 0, re-raise otherwise */ + if (index == 0) + info = "Raised at"; + else + info = "Re-raised at"; + } else { + if (index == 0) + info = "Raised by primitive operation at"; + else + info = "Called from"; + } + if (li->loc_is_inlined) { + inlined = " (inlined)"; + } else { + inlined = ""; + } + if (! li->loc_valid) { + fprintf(stderr, "%s unknown location%s\n", info, inlined); + } else { + fprintf (stderr, "%s file \"%s\"%s, line %d, characters %d-%d\n", + info, li->loc_filename, inlined, li->loc_lnum, + li->loc_startchr, li->loc_endchr); + } +} + +/* Print a backtrace */ +CAMLexport void caml_print_exception_backtrace(void) +{ + int i; + struct caml_loc_info li; + debuginfo dbg; + + if (!caml_debug_info_available()) { + fprintf(stderr, "(Cannot print stack backtrace: " + "no debug information available)\n"); + return; + } + + for (i = 0; i < caml_backtrace_pos; i++) { + for (dbg = caml_debuginfo_extract(caml_backtrace_buffer[i]); + dbg != NULL; + dbg = caml_debuginfo_next(dbg)) + { + caml_debuginfo_location(dbg, &li); + print_location(&li, i); + } + } +} + +/* Get a copy of the latest backtrace */ +CAMLprim value caml_get_exception_raw_backtrace(value unit) +{ + CAMLparam0(); + CAMLlocal1(res); + + /* Beware: the allocations below may cause finalizers to be run, and another + backtrace---possibly of a different length---to be stashed (for example + if the finalizer raises then catches an exception). We choose to ignore + any such finalizer backtraces and return the original one. */ + + if (!caml_backtrace_active || + caml_backtrace_buffer == NULL || + caml_backtrace_pos == 0) { + res = caml_alloc(0, 0); + } + else { + backtrace_slot saved_caml_backtrace_buffer[BACKTRACE_BUFFER_SIZE]; + int saved_caml_backtrace_pos; + intnat i; + + saved_caml_backtrace_pos = caml_backtrace_pos; + + if (saved_caml_backtrace_pos > BACKTRACE_BUFFER_SIZE) { + saved_caml_backtrace_pos = BACKTRACE_BUFFER_SIZE; + } + + memcpy(saved_caml_backtrace_buffer, caml_backtrace_buffer, + saved_caml_backtrace_pos * sizeof(backtrace_slot)); + + res = caml_alloc(saved_caml_backtrace_pos, 0); + for (i = 0; i < saved_caml_backtrace_pos; i++) { + Field(res, i) = Val_backtrace_slot(saved_caml_backtrace_buffer[i]); + } + } + + CAMLreturn(res); +} + +/* Copy back a backtrace and exception to the global state. + This function should be used only with Printexc.raw_backtrace */ +/* noalloc (caml value): so no CAMLparam* CAMLreturn* */ +CAMLprim value caml_restore_raw_backtrace(value exn, value backtrace) +{ + intnat i; + mlsize_t bt_size; + + caml_backtrace_last_exn = exn; + + bt_size = Wosize_val(backtrace); + if(bt_size > BACKTRACE_BUFFER_SIZE){ + bt_size = BACKTRACE_BUFFER_SIZE; + } + + /* We don't allocate if the backtrace is empty (no -g or backtrace + not activated) */ + if(bt_size == 0){ + caml_backtrace_pos = 0; + return Val_unit; + } + + /* Allocate if needed and copy the backtrace buffer */ + if (caml_backtrace_buffer == NULL && caml_alloc_backtrace_buffer() == -1){ + return Val_unit; + } + + caml_backtrace_pos = bt_size; + for(i=0; i < caml_backtrace_pos; i++){ + caml_backtrace_buffer[i] = Backtrace_slot_val(Field(backtrace, i)); + } + + return Val_unit; +} + +#define Val_debuginfo(bslot) (Val_long((uintnat)(bslot)>>1)) +#define Debuginfo_val(vslot) ((debuginfo)(Long_val(vslot) << 1)) + +/* Convert the raw backtrace to a data structure usable from OCaml */ +static value caml_convert_debuginfo(debuginfo dbg) +{ + CAMLparam0(); + CAMLlocal2(p, fname); + struct caml_loc_info li; + + caml_debuginfo_location(dbg, &li); + + if (li.loc_valid) { + fname = caml_copy_string(li.loc_filename); + p = caml_alloc_small(6, 0); + Field(p, 0) = Val_bool(li.loc_is_raise); + Field(p, 1) = fname; + Field(p, 2) = Val_int(li.loc_lnum); + Field(p, 3) = Val_int(li.loc_startchr); + Field(p, 4) = Val_int(li.loc_endchr); + Field(p, 5) = Val_bool(li.loc_is_inlined); + } else { + p = caml_alloc_small(1, 1); + Field(p, 0) = Val_bool(li.loc_is_raise); + } + + CAMLreturn(p); +} + +CAMLprim value caml_convert_raw_backtrace_slot(value slot) +{ + if (!caml_debug_info_available()) + caml_failwith("No debug information available"); + + return (caml_convert_debuginfo(Debuginfo_val(slot))); +} + +/* Convert the raw backtrace to a data structure usable from OCaml */ +CAMLprim value caml_convert_raw_backtrace(value bt) +{ + CAMLparam1(bt); + CAMLlocal1(array); + intnat i, index; + + if (!caml_debug_info_available()) + caml_failwith("No debug information available"); + + for (i = 0, index = 0; i < Wosize_val(bt); ++i) + { + debuginfo dbg; + for (dbg = caml_debuginfo_extract(Backtrace_slot_val(Field(bt, i))); + dbg != NULL; + dbg = caml_debuginfo_next(dbg)) + index++; + } + + array = caml_alloc(index, 0); + + for (i = 0, index = 0; i < Wosize_val(bt); ++i) + { + debuginfo dbg; + for (dbg = caml_debuginfo_extract(Backtrace_slot_val(Field(bt, i))); + dbg != NULL; + dbg = caml_debuginfo_next(dbg)) + { + Store_field(array, index, caml_convert_debuginfo(dbg)); + index++; + } + } + + CAMLreturn(array); +} + +CAMLprim value caml_raw_backtrace_length(value bt) +{ + return Val_int(Wosize_val(bt)); +} + +CAMLprim value caml_raw_backtrace_slot(value bt, value index) +{ + uintnat i; + debuginfo dbg; + + i = Long_val(index); + if (i >= Wosize_val(bt)) + caml_invalid_argument("Printexc.get_raw_backtrace_slot: " + "index out of bounds"); + dbg = caml_debuginfo_extract(Backtrace_slot_val(Field(bt, i))); + return Val_debuginfo(dbg); +} + +CAMLprim value caml_raw_backtrace_next_slot(value slot) +{ + debuginfo dbg; + + CAMLparam1(slot); + CAMLlocal1(v); + + dbg = Debuginfo_val(slot); + dbg = caml_debuginfo_next(dbg); + + if (dbg == NULL) + v = Val_int(0); /* None */ + else + { + v = caml_alloc(1, 0); + Field(v, 0) = Val_debuginfo(dbg); + } + + CAMLreturn(v); +} + +/* the function below is deprecated: we previously returned directly + the OCaml-usable representation, instead of the raw backtrace as an + abstract type, but this has a large performance overhead if you + store a lot of backtraces and print only some of them. + + It is not used by the Printexc library anymore, or anywhere else in + the compiler, but we have kept it in case some user still depends + on it as an external. */ +CAMLprim value caml_get_exception_backtrace(value unit) +{ + CAMLparam0(); + CAMLlocal3(arr, res, backtrace); + intnat i; + + if (!caml_debug_info_available()) { + res = Val_int(0); /* None */ + } else { + backtrace = caml_get_exception_raw_backtrace(Val_unit); + + arr = caml_alloc(Wosize_val(backtrace), 0); + for (i = 0; i < Wosize_val(backtrace); i++) { + backtrace_slot slot = Backtrace_slot_val(Field(backtrace, i)); + debuginfo dbg = caml_debuginfo_extract(slot); + Store_field(arr, i, caml_convert_debuginfo(dbg)); + } + + res = caml_alloc_small(1, 0); Field(res, 0) = arr; /* Some */ + } + + CAMLreturn(res); +} diff --git a/runtime/backtrace_byt.c b/runtime/backtrace_byt.c new file mode 100644 index 00000000..8ea94eed --- /dev/null +++ b/runtime/backtrace_byt.c @@ -0,0 +1,454 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Stack backtrace for uncaught exceptions */ + +#include +#include +#include +#include + +#include "caml/config.h" +#ifdef HAS_UNISTD +#include +#endif + +#include "caml/mlvalues.h" +#include "caml/alloc.h" +#include "caml/custom.h" +#include "caml/io.h" +#include "caml/instruct.h" +#include "caml/intext.h" +#include "caml/exec.h" +#include "caml/fix_code.h" +#include "caml/memory.h" +#include "caml/startup.h" +#include "caml/stacks.h" +#include "caml/sys.h" +#include "caml/backtrace.h" +#include "caml/fail.h" +#include "caml/backtrace_prim.h" + +/* The table of debug information fragments */ +struct ext_table caml_debug_info; + +CAMLexport char_os * caml_cds_file = NULL; + +/* Location of fields in the Instruct.debug_event record */ +enum { + EV_POS = 0, + EV_MODULE = 1, + EV_LOC = 2, + EV_KIND = 3 +}; + +/* Location of fields in the Location.t record. */ +enum { + LOC_START = 0, + LOC_END = 1, + LOC_GHOST = 2 +}; + +/* Location of fields in the Lexing.position record. */ +enum { + POS_FNAME = 0, + POS_LNUM = 1, + POS_BOL = 2, + POS_CNUM = 3 +}; + +/* Runtime representation of the debug information, optimized + for quick lookup */ +struct ev_info { + code_t ev_pc; + char *ev_filename; + int ev_lnum; + int ev_startchr; + int ev_endchr; +}; + +struct debug_info { + code_t start; + code_t end; + mlsize_t num_events; + struct ev_info *events; + int already_read; +}; + +static struct debug_info *find_debug_info(code_t pc) +{ + int i; + for (i = 0; i < caml_debug_info.size; i++) { + struct debug_info *di = caml_debug_info.contents[i]; + if (pc >= di->start && pc < di->end) + return di; + } + return NULL; +} + +static int cmp_ev_info(const void *a, const void *b) +{ + code_t pc_a = ((const struct ev_info*)a)->ev_pc; + code_t pc_b = ((const struct ev_info*)b)->ev_pc; + if (pc_a > pc_b) return 1; + if (pc_a < pc_b) return -1; + return 0; +} + +static struct ev_info *process_debug_events(code_t code_start, + value events_heap, + mlsize_t *num_events) +{ + CAMLparam1(events_heap); + CAMLlocal3(l, ev, ev_start); + mlsize_t i, j; + struct ev_info *events; + + /* Compute the size of the required event buffer. */ + *num_events = 0; + for (i = 0; i < caml_array_length(events_heap); i++) + for (l = Field(events_heap, i); l != Val_int(0); l = Field(l, 1)) + (*num_events)++; + + if (*num_events == 0) + CAMLreturnT(struct ev_info *, NULL); + + events = caml_stat_alloc_noexc(*num_events * sizeof(struct ev_info)); + if(events == NULL) + caml_fatal_error ("caml_add_debug_info: out of memory"); + + j = 0; + for (i = 0; i < caml_array_length(events_heap); i++) { + for (l = Field(events_heap, i); l != Val_int(0); l = Field(l, 1)) { + ev = Field(l, 0); + + events[j].ev_pc = (code_t)((char*)code_start + + Long_val(Field(ev, EV_POS))); + + ev_start = Field(Field(ev, EV_LOC), LOC_START); + + { + uintnat fnsz = caml_string_length(Field(ev_start, POS_FNAME)) + 1; + events[j].ev_filename = (char*)caml_stat_alloc_noexc(fnsz); + if(events[j].ev_filename == NULL) + caml_fatal_error ("caml_add_debug_info: out of memory"); + memcpy(events[j].ev_filename, + String_val(Field(ev_start, POS_FNAME)), + fnsz); + } + + events[j].ev_lnum = Int_val(Field(ev_start, POS_LNUM)); + events[j].ev_startchr = + Int_val(Field(ev_start, POS_CNUM)) + - Int_val(Field(ev_start, POS_BOL)); + events[j].ev_endchr = + Int_val(Field(Field(Field(ev, EV_LOC), LOC_END), POS_CNUM)) + - Int_val(Field(ev_start, POS_BOL)); + + j++; + } + } + + CAMLassert(j == *num_events); + + qsort(events, *num_events, sizeof(struct ev_info), cmp_ev_info); + + CAMLreturnT(struct ev_info *, events); +} + +/* Processes a (Instruct.debug_event list array) into a form suitable + for quick lookup and registers it for the (code_start,code_size) pc range. */ +CAMLprim value caml_add_debug_info(code_t code_start, value code_size, + value events_heap) +{ + CAMLparam1(events_heap); + struct debug_info *debug_info; + + /* build the OCaml-side debug_info value */ + debug_info = caml_stat_alloc(sizeof(struct debug_info)); + + debug_info->start = code_start; + debug_info->end = (code_t)((char*) code_start + Long_val(code_size)); + if (events_heap == Val_unit) { + debug_info->events = NULL; + debug_info->num_events = 0; + debug_info->already_read = 0; + } else { + debug_info->events = + process_debug_events(code_start, events_heap, &debug_info->num_events); + debug_info->already_read = 1; + } + + caml_ext_table_add(&caml_debug_info, debug_info); + + CAMLreturn(Val_unit); +} + +CAMLprim value caml_remove_debug_info(code_t start) +{ + CAMLparam0(); + CAMLlocal2(dis, prev); + + int i; + for (i = 0; i < caml_debug_info.size; i++) { + struct debug_info *di = caml_debug_info.contents[i]; + if (di->start == start) { + /* note that caml_ext_table_remove calls caml_stat_free on the + removed resource, bracketing the caml_stat_alloc call in + caml_add_debug_info. */ + caml_ext_table_remove(&caml_debug_info, di); + break; + } + } + + CAMLreturn(Val_unit); +} + +int caml_alloc_backtrace_buffer(void){ + CAMLassert(caml_backtrace_pos == 0); + caml_backtrace_buffer = + caml_stat_alloc_noexc(BACKTRACE_BUFFER_SIZE * sizeof(code_t)); + if (caml_backtrace_buffer == NULL) return -1; + return 0; +} + +/* Store the return addresses contained in the given stack fragment + into the backtrace array */ + +void caml_stash_backtrace(value exn, code_t pc, value * sp, int reraise) +{ + if (pc != NULL) pc = pc - 1; + if (exn != caml_backtrace_last_exn || !reraise) { + caml_backtrace_pos = 0; + caml_backtrace_last_exn = exn; + } + + if (caml_backtrace_buffer == NULL && caml_alloc_backtrace_buffer() == -1) + return; + + if (caml_backtrace_pos >= BACKTRACE_BUFFER_SIZE) return; + /* testing the code region is needed: PR#1554 */ + if (find_debug_info(pc) != NULL) + caml_backtrace_buffer[caml_backtrace_pos++] = pc; + + /* Traverse the stack and put all values pointing into bytecode + into the backtrace buffer. */ + for (/*nothing*/; sp < caml_trapsp; sp++) { + code_t p = (code_t) *sp; + if (caml_backtrace_pos >= BACKTRACE_BUFFER_SIZE) break; + if (find_debug_info(p) != NULL) + caml_backtrace_buffer[caml_backtrace_pos++] = p; + } +} + +/* returns the next frame pointer (or NULL if none is available); + updates *sp to point to the following one, and *trsp to the next + trap frame, which we will skip when we reach it */ + +code_t caml_next_frame_pointer(value ** sp, value ** trsp) +{ + while (*sp < caml_stack_high) { + code_t *p = (code_t*) (*sp)++; + if(&Trap_pc(*trsp) == p) { + *trsp = Trap_link(*trsp); + continue; + } + + if (find_debug_info(*p) != NULL) + return *p; + } + return NULL; +} + +/* Stores upto [max_frames_value] frames of the current call stack to + return to the user. This is used not in an exception-raising + context, but only when the user requests to save the trace + (hopefully less often). Instead of using a bounded buffer as + [caml_stash_backtrace], we first traverse the stack to compute the + right size, then allocate space for the trace. */ + +CAMLprim value caml_get_current_callstack(value max_frames_value) +{ + CAMLparam1(max_frames_value); + CAMLlocal1(trace); + + /* we use `intnat` here because, were it only `int`, passing `max_int` + from the OCaml side would overflow on 64bits machines. */ + intnat max_frames = Long_val(max_frames_value); + intnat trace_size; + + /* first compute the size of the trace */ + { + value * sp = caml_extern_sp; + value * trsp = caml_trapsp; + + for (trace_size = 0; trace_size < max_frames; trace_size++) { + code_t p = caml_next_frame_pointer(&sp, &trsp); + if (p == NULL) break; + } + } + + trace = caml_alloc(trace_size, 0); + + /* then collect the trace */ + { + value * sp = caml_extern_sp; + value * trsp = caml_trapsp; + uintnat trace_pos; + + for (trace_pos = 0; trace_pos < trace_size; trace_pos++) { + code_t p = caml_next_frame_pointer(&sp, &trsp); + CAMLassert(p != NULL); + Field(trace, trace_pos) = Val_backtrace_slot(p); + } + } + + CAMLreturn(trace); +} + +/* Read the debugging info contained in the current bytecode executable. */ + +static void read_main_debug_info(struct debug_info *di) +{ + CAMLparam0(); + CAMLlocal3(events, evl, l); + char_os *exec_name; + int fd, num_events, orig, i; + struct channel *chan; + struct exec_trailer trail; + + CAMLassert(di->already_read == 0); + di->already_read = 1; + + if (caml_cds_file != NULL) { + exec_name = caml_cds_file; + } else { + exec_name = caml_exe_name; + } + + fd = caml_attempt_open(&exec_name, &trail, 1); + if (fd < 0){ + caml_fatal_error ("executable program file not found"); + CAMLreturn0; + } + + caml_read_section_descriptors(fd, &trail); + if (caml_seek_optional_section(fd, &trail, "DBUG") != -1) { + chan = caml_open_descriptor_in(fd); + + num_events = caml_getword(chan); + events = caml_alloc(num_events, 0); + + for (i = 0; i < num_events; i++) { + orig = caml_getword(chan); + evl = caml_input_val(chan); + caml_input_val(chan); /* Skip the list of absolute directory names */ + /* Relocate events in event list */ + for (l = evl; l != Val_int(0); l = Field(l, 1)) { + value ev = Field(l, 0); + Field(ev, EV_POS) = Val_long(Long_val(Field(ev, EV_POS)) + orig); + } + /* Record event list */ + Store_field(events, i, evl); + } + + caml_close_channel(chan); + + di->events = process_debug_events(caml_start_code, events, &di->num_events); + } + + CAMLreturn0; +} + +CAMLexport void caml_init_debug_info(void) +{ + caml_ext_table_init(&caml_debug_info, 1); + caml_add_debug_info(caml_start_code, Val_long(caml_code_size), Val_unit); +} + +int caml_debug_info_available(void) +{ + return (caml_debug_info.size != 0); +} + +/* Search the event index for the given PC. Return -1 if not found. */ + +static struct ev_info *event_for_location(code_t pc) +{ + uintnat low, high; + struct debug_info *di = find_debug_info(pc); + + if (di == NULL) + return NULL; + + if (!di->already_read) + read_main_debug_info(di); + + if (di->num_events == 0) + return NULL; + + low = 0; + high = di->num_events; + while (low+1 < high) { + uintnat m = (low+high)/2; + if(pc < di->events[m].ev_pc) high = m; + else low = m; + } + if (di->events[low].ev_pc == pc) + return &di->events[low]; + /* ocamlc sometimes moves an event past a following PUSH instruction; + allow mismatch by 1 instruction. */ + if (di->events[low].ev_pc == pc + 1) + return &di->events[low]; + if (low+1 < di->num_events && di->events[low+1].ev_pc == pc + 1) + return &di->events[low+1]; + + return NULL; +} + +/* Extract location information for the given PC */ + +void caml_debuginfo_location(debuginfo dbg, + /*out*/ struct caml_loc_info * li) +{ + code_t pc = dbg; + struct ev_info *event = event_for_location(pc); + li->loc_is_raise = + caml_is_instruction(*pc, RAISE) || + caml_is_instruction(*pc, RERAISE); + if (event == NULL) { + li->loc_valid = 0; + return; + } + li->loc_valid = 1; + li->loc_is_inlined = 0; + li->loc_filename = event->ev_filename; + li->loc_lnum = event->ev_lnum; + li->loc_startchr = event->ev_startchr; + li->loc_endchr = event->ev_endchr; +} + +debuginfo caml_debuginfo_extract(backtrace_slot slot) +{ + return (debuginfo)slot; +} + +debuginfo caml_debuginfo_next(debuginfo dbg) +{ + /* No inlining in bytecode */ + return NULL; +} diff --git a/runtime/backtrace_nat.c b/runtime/backtrace_nat.c new file mode 100644 index 00000000..0d1a3e58 --- /dev/null +++ b/runtime/backtrace_nat.c @@ -0,0 +1,235 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Gallium, INRIA Rocquencourt */ +/* */ +/* Copyright 2006 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Stack backtrace for uncaught exceptions */ + +#include +#include +#include + +#include "caml/alloc.h" +#include "caml/backtrace.h" +#include "caml/backtrace_prim.h" +#include "caml/memory.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/stack.h" + +/* Returns the next frame descriptor (or NULL if none is available), + and updates *pc and *sp to point to the following one. */ +frame_descr * caml_next_frame_descriptor(uintnat * pc, char ** sp) +{ + frame_descr * d; + uintnat h; + + while (1) { + h = Hash_retaddr(*pc); + while (1) { + d = caml_frame_descriptors[h]; + if (d == NULL) return NULL; /* happens if some code compiled without -g */ + if (d->retaddr == *pc) break; + h = (h+1) & caml_frame_descriptors_mask; + } + /* Skip to next frame */ + if (d->frame_size != 0xFFFF) { + /* Regular frame, update sp/pc and return the frame descriptor */ + *sp += (d->frame_size & 0xFFFC); + *pc = Saved_return_address(*sp); +#ifdef Mask_already_scanned + *pc = Mask_already_scanned(*pc); +#endif + return d; + } else { + /* Special frame marking the top of a stack chunk for an ML callback. + Skip C portion of stack and continue with next ML stack chunk. */ + struct caml_context * next_context = Callback_link(*sp); + *sp = next_context->bottom_of_stack; + *pc = next_context->last_retaddr; + /* A null sp means no more ML stack chunks; stop here. */ + if (*sp == NULL) return NULL; + } + } +} + +int caml_alloc_backtrace_buffer(void){ + CAMLassert(caml_backtrace_pos == 0); + caml_backtrace_buffer = + caml_stat_alloc_noexc(BACKTRACE_BUFFER_SIZE * sizeof(backtrace_slot)); + if (caml_backtrace_buffer == NULL) return -1; + return 0; +} + +/* Stores the return addresses contained in the given stack fragment + into the backtrace array ; this version is performance-sensitive as + it is called at each [raise] in a program compiled with [-g], so we + preserved the global, statically bounded buffer of the old + implementation -- before the more flexible + [caml_get_current_callstack] was implemented. */ +void caml_stash_backtrace(value exn, uintnat pc, char * sp, char * trapsp) +{ + if (exn != caml_backtrace_last_exn) { + caml_backtrace_pos = 0; + caml_backtrace_last_exn = exn; + } + + if (caml_backtrace_buffer == NULL && caml_alloc_backtrace_buffer() == -1) + return; + + /* iterate on each frame */ + while (1) { + frame_descr * descr = caml_next_frame_descriptor(&pc, &sp); + if (descr == NULL) return; + /* store its descriptor in the backtrace buffer */ + if (caml_backtrace_pos >= BACKTRACE_BUFFER_SIZE) return; + caml_backtrace_buffer[caml_backtrace_pos++] = (backtrace_slot) descr; + + /* Stop when we reach the current exception handler */ + if (sp > trapsp) return; + } +} + +/* Stores upto [max_frames_value] frames of the current call stack to + return to the user. This is used not in an exception-raising + context, but only when the user requests to save the trace + (hopefully less often). Instead of using a bounded buffer as + [caml_stash_backtrace], we first traverse the stack to compute the + right size, then allocate space for the trace. */ +CAMLprim value caml_get_current_callstack(value max_frames_value) +{ + CAMLparam1(max_frames_value); + CAMLlocal1(trace); + + /* we use `intnat` here because, were it only `int`, passing `max_int` + from the OCaml side would overflow on 64bits machines. */ + intnat max_frames = Long_val(max_frames_value); + intnat trace_size; + + /* first compute the size of the trace */ + { + uintnat pc = caml_last_return_address; + char * sp = caml_bottom_of_stack; + char * limitsp = caml_top_of_stack; + + trace_size = 0; + while (1) { + frame_descr * descr = caml_next_frame_descriptor(&pc, &sp); + if (descr == NULL) break; + if (trace_size >= max_frames) break; + ++trace_size; + + if (sp > limitsp) break; + } + } + + trace = caml_alloc((mlsize_t) trace_size, 0); + + /* then collect the trace */ + { + uintnat pc = caml_last_return_address; + char * sp = caml_bottom_of_stack; + intnat trace_pos; + + for (trace_pos = 0; trace_pos < trace_size; trace_pos++) { + frame_descr * descr = caml_next_frame_descriptor(&pc, &sp); + CAMLassert(descr != NULL); + Field(trace, trace_pos) = Val_backtrace_slot((backtrace_slot) descr); + } + } + + CAMLreturn(trace); +} + + +debuginfo caml_debuginfo_extract(backtrace_slot slot) +{ + uintnat infoptr; + frame_descr * d = (frame_descr *)slot; + + if ((d->frame_size & 1) == 0) { + return NULL; + } + /* Recover debugging info */ + infoptr = ((uintnat) d + + sizeof(char *) + sizeof(short) + sizeof(short) + + sizeof(short) * d->num_live + sizeof(frame_descr *) - 1) + & -sizeof(frame_descr *); + return *((debuginfo*)infoptr); +} + +debuginfo caml_debuginfo_next(debuginfo dbg) +{ + uint32_t * infoptr; + + if (dbg == NULL) + return NULL; + + infoptr = dbg; + infoptr += 2; /* Two packed info fields */ + return *((debuginfo*)infoptr); +} + +/* Extract location information for the given frame descriptor */ +void caml_debuginfo_location(debuginfo dbg, /*out*/ struct caml_loc_info * li) +{ + uint32_t info1, info2; + + /* If no debugging information available, print nothing. + When everything is compiled with -g, this corresponds to + compiler-inserted re-raise operations. */ + if (dbg == NULL) { + li->loc_valid = 0; + li->loc_is_raise = 1; + li->loc_is_inlined = 0; + return; + } + /* Recover debugging info */ + info1 = ((uint32_t *)dbg)[0]; + info2 = ((uint32_t *)dbg)[1]; + /* Format of the two info words: + llllllllllllllllllll aaaaaaaa bbbbbbbbbb nnnnnnnnnnnnnnnnnnnnnnnn kk + 44 36 26 2 0 + (32+12) (32+4) + k ( 2 bits): 0 if it's a call + 1 if it's a raise + n (24 bits): offset (in 4-byte words) of file name relative to dbg + l (20 bits): line number + a ( 8 bits): beginning of character range + b (10 bits): end of character range */ + li->loc_valid = 1; + li->loc_is_raise = (info1 & 3) == 1; + li->loc_is_inlined = caml_debuginfo_next(dbg) != NULL; + li->loc_filename = (char *) dbg + (info1 & 0x3FFFFFC); + li->loc_lnum = info2 >> 12; + li->loc_startchr = (info2 >> 4) & 0xFF; + li->loc_endchr = ((info2 & 0xF) << 6) | (info1 >> 26); +} + +CAMLprim value caml_add_debug_info(backtrace_slot start, value size, + value events) +{ + return Val_unit; +} + +CAMLprim value caml_remove_debug_info(backtrace_slot start) +{ + return Val_unit; +} + +int caml_debug_info_available(void) +{ + return 1; +} diff --git a/runtime/bigarray.c b/runtime/bigarray.c new file mode 100644 index 00000000..62d3d3de --- /dev/null +++ b/runtime/bigarray.c @@ -0,0 +1,1229 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +#include +#include +#include +#include "caml/alloc.h" +#include "caml/bigarray.h" +#include "caml/custom.h" +#include "caml/fail.h" +#include "caml/intext.h" +#include "caml/hash.h" +#include "caml/memory.h" +#include "caml/mlvalues.h" +#include "caml/signals.h" + +#define int8 caml_ba_int8 +#define uint8 caml_ba_uint8 +#define int16 caml_ba_int16 +#define uint16 caml_ba_uint16 + +/* Compute the number of elements of a big array */ + +CAMLexport uintnat caml_ba_num_elts(struct caml_ba_array * b) +{ + uintnat num_elts; + int i; + num_elts = 1; + for (i = 0; i < b->num_dims; i++) num_elts = num_elts * b->dim[i]; + return num_elts; +} + +/* Size in bytes of a bigarray element, indexed by bigarray kind */ + +CAMLexport int caml_ba_element_size[] = +{ 4 /*FLOAT32*/, 8 /*FLOAT64*/, + 1 /*SINT8*/, 1 /*UINT8*/, + 2 /*SINT16*/, 2 /*UINT16*/, + 4 /*INT32*/, 8 /*INT64*/, + sizeof(value) /*CAML_INT*/, sizeof(value) /*NATIVE_INT*/, + 8 /*COMPLEX32*/, 16 /*COMPLEX64*/, + 1 /*CHAR*/ +}; + +/* Compute the number of bytes for the elements of a big array */ + +CAMLexport uintnat caml_ba_byte_size(struct caml_ba_array * b) +{ + return caml_ba_num_elts(b) + * caml_ba_element_size[b->flags & CAML_BA_KIND_MASK]; +} + +/* Operation table for bigarrays */ + +CAMLexport struct custom_operations caml_ba_ops = { + "_bigarray", + caml_ba_finalize, + caml_ba_compare, + caml_ba_hash, + caml_ba_serialize, + caml_ba_deserialize, + custom_compare_ext_default, + custom_fixed_length_default +}; + +/* Allocation of a big array */ + +/* [caml_ba_alloc] will allocate a new bigarray object in the heap. + If [data] is NULL, the memory for the contents is also allocated + (with [malloc]) by [caml_ba_alloc]. + [data] cannot point into the OCaml heap. + [dim] may point into an object in the OCaml heap. +*/ +CAMLexport value +caml_ba_alloc(int flags, int num_dims, void * data, intnat * dim) +{ + uintnat num_elts, asize, size; + int i; + value res; + struct caml_ba_array * b; + intnat dimcopy[CAML_BA_MAX_NUM_DIMS]; + + CAMLassert(num_dims >= 0 && num_dims <= CAML_BA_MAX_NUM_DIMS); + CAMLassert((flags & CAML_BA_KIND_MASK) <= CAML_BA_CHAR); + for (i = 0; i < num_dims; i++) dimcopy[i] = dim[i]; + size = 0; + if (data == NULL) { + num_elts = 1; + for (i = 0; i < num_dims; i++) { + if (caml_umul_overflow(num_elts, dimcopy[i], &num_elts)) + caml_raise_out_of_memory(); + } + if (caml_umul_overflow(num_elts, + caml_ba_element_size[flags & CAML_BA_KIND_MASK], + &size)) + caml_raise_out_of_memory(); + data = malloc(size); + if (data == NULL && size != 0) caml_raise_out_of_memory(); + flags |= CAML_BA_MANAGED; + } + asize = SIZEOF_BA_ARRAY + num_dims * sizeof(intnat); + res = caml_alloc_custom_mem(&caml_ba_ops, asize, size); + b = Caml_ba_array_val(res); + b->data = data; + b->num_dims = num_dims; + b->flags = flags; + b->proxy = NULL; + for (i = 0; i < num_dims; i++) b->dim[i] = dimcopy[i]; + return res; +} + +/* Same as caml_ba_alloc, but dimensions are passed as a list of + arguments */ + +CAMLexport value caml_ba_alloc_dims(int flags, int num_dims, void * data, ...) +{ + va_list ap; + intnat dim[CAML_BA_MAX_NUM_DIMS]; + int i; + value res; + + CAMLassert(num_dims <= CAML_BA_MAX_NUM_DIMS); + va_start(ap, data); + for (i = 0; i < num_dims; i++) dim[i] = va_arg(ap, intnat); + va_end(ap); + res = caml_ba_alloc(flags, num_dims, data, dim); + return res; +} + +/* Finalization of a big array */ + +CAMLexport void caml_ba_finalize(value v) +{ + struct caml_ba_array * b = Caml_ba_array_val(v); + + switch (b->flags & CAML_BA_MANAGED_MASK) { + case CAML_BA_EXTERNAL: + break; + case CAML_BA_MANAGED: + if (b->proxy == NULL) { + free(b->data); + } else { + if (-- b->proxy->refcount == 0) { + free(b->proxy->data); + free(b->proxy); + } + } + break; + case CAML_BA_MAPPED_FILE: + /* Bigarrays for mapped files use a different finalization method */ + /* fallthrough */ + default: + CAMLassert(0); + } +} + +/* Comparison of two big arrays */ + +CAMLexport int caml_ba_compare(value v1, value v2) +{ + struct caml_ba_array * b1 = Caml_ba_array_val(v1); + struct caml_ba_array * b2 = Caml_ba_array_val(v2); + uintnat n, num_elts; + intnat flags1, flags2; + int i; + + /* Compare kind & layout in case the arguments are of different types */ + flags1 = b1->flags & (CAML_BA_KIND_MASK | CAML_BA_LAYOUT_MASK); + flags2 = b2->flags & (CAML_BA_KIND_MASK | CAML_BA_LAYOUT_MASK); + if (flags1 != flags2) return flags2 - flags1; + /* Compare number of dimensions */ + if (b1->num_dims != b2->num_dims) return b2->num_dims - b1->num_dims; + /* Same number of dimensions: compare dimensions lexicographically */ + for (i = 0; i < b1->num_dims; i++) { + intnat d1 = b1->dim[i]; + intnat d2 = b2->dim[i]; + if (d1 != d2) return d1 < d2 ? -1 : 1; + } + /* Same dimensions: compare contents lexicographically */ + num_elts = caml_ba_num_elts(b1); + +#define DO_INTEGER_COMPARISON(type) \ + { type * p1 = b1->data; type * p2 = b2->data; \ + for (n = 0; n < num_elts; n++) { \ + type e1 = *p1++; type e2 = *p2++; \ + if (e1 < e2) return -1; \ + if (e1 > e2) return 1; \ + } \ + return 0; \ + } +#define DO_FLOAT_COMPARISON(type) \ + { type * p1 = b1->data; type * p2 = b2->data; \ + for (n = 0; n < num_elts; n++) { \ + type e1 = *p1++; type e2 = *p2++; \ + if (e1 < e2) return -1; \ + if (e1 > e2) return 1; \ + if (e1 != e2) { \ + caml_compare_unordered = 1; \ + if (e1 == e1) return 1; \ + if (e2 == e2) return -1; \ + } \ + } \ + return 0; \ + } + + switch (b1->flags & CAML_BA_KIND_MASK) { + case CAML_BA_COMPLEX32: + num_elts *= 2; /*fallthrough*/ + case CAML_BA_FLOAT32: + DO_FLOAT_COMPARISON(float); + case CAML_BA_COMPLEX64: + num_elts *= 2; /*fallthrough*/ + case CAML_BA_FLOAT64: + DO_FLOAT_COMPARISON(double); + case CAML_BA_CHAR: + DO_INTEGER_COMPARISON(caml_ba_uint8); + case CAML_BA_SINT8: + DO_INTEGER_COMPARISON(caml_ba_int8); + case CAML_BA_UINT8: + DO_INTEGER_COMPARISON(caml_ba_uint8); + case CAML_BA_SINT16: + DO_INTEGER_COMPARISON(caml_ba_int16); + case CAML_BA_UINT16: + DO_INTEGER_COMPARISON(caml_ba_uint16); + case CAML_BA_INT32: + DO_INTEGER_COMPARISON(int32_t); + case CAML_BA_INT64: + DO_INTEGER_COMPARISON(int64_t); + case CAML_BA_CAML_INT: + case CAML_BA_NATIVE_INT: + DO_INTEGER_COMPARISON(intnat); + default: + CAMLassert(0); + return 0; /* should not happen */ + } +#undef DO_INTEGER_COMPARISON +#undef DO_FLOAT_COMPARISON +} + +/* Hashing of a bigarray */ + +CAMLexport intnat caml_ba_hash(value v) +{ + struct caml_ba_array * b = Caml_ba_array_val(v); + intnat num_elts, n; + uint32_t h, w; + int i; + + num_elts = 1; + for (i = 0; i < b->num_dims; i++) num_elts = num_elts * b->dim[i]; + h = 0; + + switch (b->flags & CAML_BA_KIND_MASK) { + case CAML_BA_CHAR: + case CAML_BA_SINT8: + case CAML_BA_UINT8: { + caml_ba_uint8 * p = b->data; + if (num_elts > 256) num_elts = 256; + for (n = 0; n + 4 <= num_elts; n += 4, p += 4) { + w = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); + h = caml_hash_mix_uint32(h, w); + } + w = 0; + switch (num_elts & 3) { + case 3: w = p[2] << 16; /* fallthrough */ + case 2: w |= p[1] << 8; /* fallthrough */ + case 1: w |= p[0]; + h = caml_hash_mix_uint32(h, w); + } + break; + } + case CAML_BA_SINT16: + case CAML_BA_UINT16: { + caml_ba_uint16 * p = b->data; + if (num_elts > 128) num_elts = 128; + for (n = 0; n + 2 <= num_elts; n += 2, p += 2) { + w = p[0] | (p[1] << 16); + h = caml_hash_mix_uint32(h, w); + } + if ((num_elts & 1) != 0) + h = caml_hash_mix_uint32(h, p[0]); + break; + } + case CAML_BA_INT32: + { + uint32_t * p = b->data; + if (num_elts > 64) num_elts = 64; + for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_uint32(h, *p); + break; + } + case CAML_BA_CAML_INT: + case CAML_BA_NATIVE_INT: + { + intnat * p = b->data; + if (num_elts > 64) num_elts = 64; + for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_intnat(h, *p); + break; + } + case CAML_BA_INT64: + { + int64_t * p = b->data; + if (num_elts > 32) num_elts = 32; + for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_int64(h, *p); + break; + } + case CAML_BA_COMPLEX32: + num_elts *= 2; /* fallthrough */ + case CAML_BA_FLOAT32: + { + float * p = b->data; + if (num_elts > 64) num_elts = 64; + for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_float(h, *p); + break; + } + case CAML_BA_COMPLEX64: + num_elts *= 2; /* fallthrough */ + case CAML_BA_FLOAT64: + { + double * p = b->data; + if (num_elts > 32) num_elts = 32; + for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_double(h, *p); + break; + } + } + return h; +} + +static void caml_ba_serialize_longarray(void * data, + intnat num_elts, + intnat min_val, intnat max_val) +{ +#ifdef ARCH_SIXTYFOUR + int overflow_32 = 0; + intnat * p, n; + for (n = 0, p = data; n < num_elts; n++, p++) { + if (*p < min_val || *p > max_val) { overflow_32 = 1; break; } + } + if (overflow_32) { + caml_serialize_int_1(1); + caml_serialize_block_8(data, num_elts); + } else { + caml_serialize_int_1(0); + for (n = 0, p = data; n < num_elts; n++, p++) + caml_serialize_int_4((int32_t) *p); + } +#else + caml_serialize_int_1(0); + caml_serialize_block_4(data, num_elts); +#endif +} + +CAMLexport void caml_ba_serialize(value v, + uintnat * wsize_32, + uintnat * wsize_64) +{ + struct caml_ba_array * b = Caml_ba_array_val(v); + intnat num_elts; + int i; + + /* Serialize header information */ + caml_serialize_int_4(b->num_dims); + caml_serialize_int_4(b->flags & (CAML_BA_KIND_MASK | CAML_BA_LAYOUT_MASK)); + /* On a 64-bit machine, if any of the dimensions is >= 2^32, + the size of the marshaled data will be >= 2^32 and + extern_value() will fail. So, it is safe to write the dimensions + as 32-bit unsigned integers. */ + for (i = 0; i < b->num_dims; i++) caml_serialize_int_4(b->dim[i]); + /* Compute total number of elements */ + num_elts = 1; + for (i = 0; i < b->num_dims; i++) num_elts = num_elts * b->dim[i]; + /* Serialize elements */ + switch (b->flags & CAML_BA_KIND_MASK) { + case CAML_BA_CHAR: + case CAML_BA_SINT8: + case CAML_BA_UINT8: + caml_serialize_block_1(b->data, num_elts); break; + case CAML_BA_SINT16: + case CAML_BA_UINT16: + caml_serialize_block_2(b->data, num_elts); break; + case CAML_BA_FLOAT32: + case CAML_BA_INT32: + caml_serialize_block_4(b->data, num_elts); break; + case CAML_BA_COMPLEX32: + caml_serialize_block_4(b->data, num_elts * 2); break; + case CAML_BA_FLOAT64: + case CAML_BA_INT64: + caml_serialize_block_8(b->data, num_elts); break; + case CAML_BA_COMPLEX64: + caml_serialize_block_8(b->data, num_elts * 2); break; + case CAML_BA_CAML_INT: + caml_ba_serialize_longarray(b->data, num_elts, -0x40000000, 0x3FFFFFFF); + break; + case CAML_BA_NATIVE_INT: + caml_ba_serialize_longarray(b->data, num_elts, -0x80000000, 0x7FFFFFFF); + break; + } + /* Compute required size in OCaml heap. Assumes struct caml_ba_array + is exactly 4 + num_dims words */ + CAMLassert(SIZEOF_BA_ARRAY == 4 * sizeof(value)); + *wsize_32 = (4 + b->num_dims) * 4; + *wsize_64 = (4 + b->num_dims) * 8; +} + +static void caml_ba_deserialize_longarray(void * dest, intnat num_elts) +{ + int sixty = caml_deserialize_uint_1(); +#ifdef ARCH_SIXTYFOUR + if (sixty) { + caml_deserialize_block_8(dest, num_elts); + } else { + intnat * p, n; + for (n = 0, p = dest; n < num_elts; n++, p++) + *p = caml_deserialize_sint_4(); + } +#else + if (sixty) + caml_deserialize_error("input_value: cannot read bigarray " + "with 64-bit OCaml ints"); + caml_deserialize_block_4(dest, num_elts); +#endif +} + +CAMLexport uintnat caml_ba_deserialize(void * dst) +{ + struct caml_ba_array * b = dst; + int i; + uintnat num_elts, size; + + /* Read back header information */ + b->num_dims = caml_deserialize_uint_4(); + if (b->num_dims < 0 || b->num_dims > CAML_BA_MAX_NUM_DIMS) + caml_deserialize_error("input_value: wrong number of bigarray dimensions"); + b->flags = caml_deserialize_uint_4() | CAML_BA_MANAGED; + b->proxy = NULL; + for (i = 0; i < b->num_dims; i++) b->dim[i] = caml_deserialize_uint_4(); + /* Compute total number of elements. Watch out for overflows (MPR#7765). */ + num_elts = 1; + for (i = 0; i < b->num_dims; i++) { + if (caml_umul_overflow(num_elts, b->dim[i], &num_elts)) + caml_deserialize_error("input_value: size overflow for bigarray"); + } + /* Determine array size in bytes. Watch out for overflows (MPR#7765). */ + if ((b->flags & CAML_BA_KIND_MASK) > CAML_BA_CHAR) + caml_deserialize_error("input_value: bad bigarray kind"); + if (caml_umul_overflow(num_elts, + caml_ba_element_size[b->flags & CAML_BA_KIND_MASK], + &size)) + caml_deserialize_error("input_value: size overflow for bigarray"); + /* Allocate room for data */ + b->data = malloc(size); + if (b->data == NULL) + caml_deserialize_error("input_value: out of memory for bigarray"); + /* Read data */ + switch (b->flags & CAML_BA_KIND_MASK) { + case CAML_BA_CHAR: + case CAML_BA_SINT8: + case CAML_BA_UINT8: + caml_deserialize_block_1(b->data, num_elts); break; + case CAML_BA_SINT16: + case CAML_BA_UINT16: + caml_deserialize_block_2(b->data, num_elts); break; + case CAML_BA_FLOAT32: + case CAML_BA_INT32: + caml_deserialize_block_4(b->data, num_elts); break; + case CAML_BA_COMPLEX32: + caml_deserialize_block_4(b->data, num_elts * 2); break; + case CAML_BA_FLOAT64: + case CAML_BA_INT64: + caml_deserialize_block_8(b->data, num_elts); break; + case CAML_BA_COMPLEX64: + caml_deserialize_block_8(b->data, num_elts * 2); break; + case CAML_BA_CAML_INT: + case CAML_BA_NATIVE_INT: + caml_ba_deserialize_longarray(b->data, num_elts); break; + } + /* PR#5516: use C99's flexible array types if possible */ + return SIZEOF_BA_ARRAY + b->num_dims * sizeof(intnat); +} + +/* Allocate a bigarray from OCaml */ + +CAMLprim value caml_ba_create(value vkind, value vlayout, value vdim) +{ + intnat dim[CAML_BA_MAX_NUM_DIMS]; + mlsize_t num_dims; + int i, flags; + + num_dims = Wosize_val(vdim); + /* here num_dims is unsigned (mlsize_t) so no need to check (num_dims >= 0) */ + if (num_dims > CAML_BA_MAX_NUM_DIMS) + caml_invalid_argument("Bigarray.create: bad number of dimensions"); + for (i = 0; i < num_dims; i++) { + dim[i] = Long_val(Field(vdim, i)); + if (dim[i] < 0) + caml_invalid_argument("Bigarray.create: negative dimension"); + } + flags = Caml_ba_kind_val(vkind) | Caml_ba_layout_val(vlayout); + return caml_ba_alloc(flags, num_dims, NULL, dim); +} + +/* Given a big array and a vector of indices, check that the indices + are within the bounds and return the offset of the corresponding + array element in the data part of the array. */ + +static long caml_ba_offset(struct caml_ba_array * b, intnat * index) +{ + intnat offset; + int i; + + offset = 0; + if ((b->flags & CAML_BA_LAYOUT_MASK) == CAML_BA_C_LAYOUT) { + /* C-style layout: row major, indices start at 0 */ + for (i = 0; i < b->num_dims; i++) { + if ((uintnat) index[i] >= (uintnat) b->dim[i]) + caml_array_bound_error(); + offset = offset * b->dim[i] + index[i]; + } + } else { + /* Fortran-style layout: column major, indices start at 1 */ + for (i = b->num_dims - 1; i >= 0; i--) { + if ((uintnat) (index[i] - 1) >= (uintnat) b->dim[i]) + caml_array_bound_error(); + offset = offset * b->dim[i] + (index[i] - 1); + } + } + return offset; +} + +/* Helper function to allocate a record of two double floats */ + +static value copy_two_doubles(double d0, double d1) +{ + value res = caml_alloc_small(2 * Double_wosize, Double_array_tag); + Store_double_field(res, 0, d0); + Store_double_field(res, 1, d1); + return res; +} + +/* Generic code to read from a big array */ + +value caml_ba_get_N(value vb, value * vind, int nind) +{ + struct caml_ba_array * b = Caml_ba_array_val(vb); + intnat index[CAML_BA_MAX_NUM_DIMS]; + int i; + intnat offset; + + /* Check number of indices = number of dimensions of array + (maybe not necessary if ML typing guarantees this) */ + if (nind != b->num_dims) + caml_invalid_argument("Bigarray.get: wrong number of indices"); + /* Compute offset and check bounds */ + for (i = 0; i < b->num_dims; i++) index[i] = Long_val(vind[i]); + offset = caml_ba_offset(b, index); + /* Perform read */ + switch ((b->flags) & CAML_BA_KIND_MASK) { + default: + CAMLassert(0); + case CAML_BA_FLOAT32: + return caml_copy_double((double) ((float *) b->data)[offset]); + case CAML_BA_FLOAT64: + return caml_copy_double(((double *) b->data)[offset]); + case CAML_BA_SINT8: + return Val_int(((int8 *) b->data)[offset]); + case CAML_BA_UINT8: + return Val_int(((uint8 *) b->data)[offset]); + case CAML_BA_SINT16: + return Val_int(((int16 *) b->data)[offset]); + case CAML_BA_UINT16: + return Val_int(((uint16 *) b->data)[offset]); + case CAML_BA_INT32: + return caml_copy_int32(((int32_t *) b->data)[offset]); + case CAML_BA_INT64: + return caml_copy_int64(((int64_t *) b->data)[offset]); + case CAML_BA_NATIVE_INT: + return caml_copy_nativeint(((intnat *) b->data)[offset]); + case CAML_BA_CAML_INT: + return Val_long(((intnat *) b->data)[offset]); + case CAML_BA_COMPLEX32: + { float * p = ((float *) b->data) + offset * 2; + return copy_two_doubles((double) p[0], (double) p[1]); } + case CAML_BA_COMPLEX64: + { double * p = ((double *) b->data) + offset * 2; + return copy_two_doubles(p[0], p[1]); } + case CAML_BA_CHAR: + return Val_int(((unsigned char *) b->data)[offset]); + } +} + +CAMLprim value caml_ba_get_1(value vb, value vind1) +{ + return caml_ba_get_N(vb, &vind1, 1); +} + +CAMLprim value caml_ba_get_2(value vb, value vind1, value vind2) +{ + value vind[2]; + vind[0] = vind1; vind[1] = vind2; + return caml_ba_get_N(vb, vind, 2); +} + +CAMLprim value caml_ba_get_3(value vb, value vind1, value vind2, value vind3) +{ + value vind[3]; + vind[0] = vind1; vind[1] = vind2; vind[2] = vind3; + return caml_ba_get_N(vb, vind, 3); +} + +CAMLprim value caml_ba_get_generic(value vb, value vind) +{ + return caml_ba_get_N(vb, &Field(vind, 0), Wosize_val(vind)); +} + + +CAMLprim value caml_ba_uint8_get16(value vb, value vind) +{ + intnat res; + unsigned char b1, b2; + intnat idx = Long_val(vind); + struct caml_ba_array * b = Caml_ba_array_val(vb); + if (idx < 0 || idx >= b->dim[0] - 1) caml_array_bound_error(); + b1 = ((unsigned char*) b->data)[idx]; + b2 = ((unsigned char*) b->data)[idx+1]; +#ifdef ARCH_BIG_ENDIAN + res = b1 << 8 | b2; +#else + res = b2 << 8 | b1; +#endif + return Val_int(res); +} + +CAMLprim value caml_ba_uint8_get32(value vb, value vind) +{ + uint32_t res; + unsigned char b1, b2, b3, b4; + intnat idx = Long_val(vind); + struct caml_ba_array * b = Caml_ba_array_val(vb); + if (idx < 0 || idx >= b->dim[0] - 3) caml_array_bound_error(); + b1 = ((unsigned char*) b->data)[idx]; + b2 = ((unsigned char*) b->data)[idx+1]; + b3 = ((unsigned char*) b->data)[idx+2]; + b4 = ((unsigned char*) b->data)[idx+3]; +#ifdef ARCH_BIG_ENDIAN + res = b1 << 24 | b2 << 16 | b3 << 8 | b4; +#else + res = b4 << 24 | b3 << 16 | b2 << 8 | b1; +#endif + return caml_copy_int32(res); +} + +CAMLprim value caml_ba_uint8_get64(value vb, value vind) +{ + uint64_t res; + unsigned char b1, b2, b3, b4, b5, b6, b7, b8; + intnat idx = Long_val(vind); + struct caml_ba_array * b = Caml_ba_array_val(vb); + if (idx < 0 || idx >= b->dim[0] - 7) caml_array_bound_error(); + b1 = ((unsigned char*) b->data)[idx]; + b2 = ((unsigned char*) b->data)[idx+1]; + b3 = ((unsigned char*) b->data)[idx+2]; + b4 = ((unsigned char*) b->data)[idx+3]; + b5 = ((unsigned char*) b->data)[idx+4]; + b6 = ((unsigned char*) b->data)[idx+5]; + b7 = ((unsigned char*) b->data)[idx+6]; + b8 = ((unsigned char*) b->data)[idx+7]; +#ifdef ARCH_BIG_ENDIAN + res = (uint64_t) b1 << 56 | (uint64_t) b2 << 48 + | (uint64_t) b3 << 40 | (uint64_t) b4 << 32 + | (uint64_t) b5 << 24 | (uint64_t) b6 << 16 + | (uint64_t) b7 << 8 | (uint64_t) b8; +#else + res = (uint64_t) b8 << 56 | (uint64_t) b7 << 48 + | (uint64_t) b6 << 40 | (uint64_t) b5 << 32 + | (uint64_t) b4 << 24 | (uint64_t) b3 << 16 + | (uint64_t) b2 << 8 | (uint64_t) b1; +#endif + return caml_copy_int64(res); +} + +/* Generic write to a big array */ + +static value caml_ba_set_aux(value vb, value * vind, intnat nind, value newval) +{ + struct caml_ba_array * b = Caml_ba_array_val(vb); + intnat index[CAML_BA_MAX_NUM_DIMS]; + int i; + intnat offset; + + /* Check number of indices = number of dimensions of array + (maybe not necessary if ML typing guarantees this) */ + if (nind != b->num_dims) + caml_invalid_argument("Bigarray.set: wrong number of indices"); + /* Compute offset and check bounds */ + for (i = 0; i < b->num_dims; i++) index[i] = Long_val(vind[i]); + offset = caml_ba_offset(b, index); + /* Perform write */ + switch (b->flags & CAML_BA_KIND_MASK) { + default: + CAMLassert(0); + case CAML_BA_FLOAT32: + ((float *) b->data)[offset] = Double_val(newval); break; + case CAML_BA_FLOAT64: + ((double *) b->data)[offset] = Double_val(newval); break; + case CAML_BA_CHAR: + case CAML_BA_SINT8: + case CAML_BA_UINT8: + ((int8 *) b->data)[offset] = Int_val(newval); break; + case CAML_BA_SINT16: + case CAML_BA_UINT16: + ((int16 *) b->data)[offset] = Int_val(newval); break; + case CAML_BA_INT32: + ((int32_t *) b->data)[offset] = Int32_val(newval); break; + case CAML_BA_INT64: + ((int64_t *) b->data)[offset] = Int64_val(newval); break; + case CAML_BA_NATIVE_INT: + ((intnat *) b->data)[offset] = Nativeint_val(newval); break; + case CAML_BA_CAML_INT: + ((intnat *) b->data)[offset] = Long_val(newval); break; + case CAML_BA_COMPLEX32: + { float * p = ((float *) b->data) + offset * 2; + p[0] = Double_field(newval, 0); + p[1] = Double_field(newval, 1); + break; } + case CAML_BA_COMPLEX64: + { double * p = ((double *) b->data) + offset * 2; + p[0] = Double_field(newval, 0); + p[1] = Double_field(newval, 1); + break; } + } + return Val_unit; +} + +CAMLprim value caml_ba_set_1(value vb, value vind1, value newval) +{ + return caml_ba_set_aux(vb, &vind1, 1, newval); +} + +CAMLprim value caml_ba_set_2(value vb, value vind1, value vind2, value newval) +{ + value vind[2]; + vind[0] = vind1; vind[1] = vind2; + return caml_ba_set_aux(vb, vind, 2, newval); +} + +CAMLprim value caml_ba_set_3(value vb, value vind1, value vind2, value vind3, + value newval) +{ + value vind[3]; + vind[0] = vind1; vind[1] = vind2; vind[2] = vind3; + return caml_ba_set_aux(vb, vind, 3, newval); +} + +value caml_ba_set_N(value vb, value * vind, int nargs) +{ + return caml_ba_set_aux(vb, vind, nargs - 1, vind[nargs - 1]); +} + +CAMLprim value caml_ba_set_generic(value vb, value vind, value newval) +{ + return caml_ba_set_aux(vb, &Field(vind, 0), Wosize_val(vind), newval); +} + +CAMLprim value caml_ba_uint8_set16(value vb, value vind, value newval) +{ + unsigned char b1, b2; + intnat val; + intnat idx = Long_val(vind); + struct caml_ba_array * b = Caml_ba_array_val(vb); + if (idx < 0 || idx >= b->dim[0] - 1) caml_array_bound_error(); + val = Long_val(newval); +#ifdef ARCH_BIG_ENDIAN + b1 = 0xFF & val >> 8; + b2 = 0xFF & val; +#else + b2 = 0xFF & val >> 8; + b1 = 0xFF & val; +#endif + ((unsigned char*) b->data)[idx] = b1; + ((unsigned char*) b->data)[idx+1] = b2; + return Val_unit; +} + +CAMLprim value caml_ba_uint8_set32(value vb, value vind, value newval) +{ + unsigned char b1, b2, b3, b4; + intnat idx = Long_val(vind); + intnat val; + struct caml_ba_array * b = Caml_ba_array_val(vb); + if (idx < 0 || idx >= b->dim[0] - 3) caml_array_bound_error(); + val = Int32_val(newval); +#ifdef ARCH_BIG_ENDIAN + b1 = 0xFF & val >> 24; + b2 = 0xFF & val >> 16; + b3 = 0xFF & val >> 8; + b4 = 0xFF & val; +#else + b4 = 0xFF & val >> 24; + b3 = 0xFF & val >> 16; + b2 = 0xFF & val >> 8; + b1 = 0xFF & val; +#endif + ((unsigned char*) b->data)[idx] = b1; + ((unsigned char*) b->data)[idx+1] = b2; + ((unsigned char*) b->data)[idx+2] = b3; + ((unsigned char*) b->data)[idx+3] = b4; + return Val_unit; +} + +CAMLprim value caml_ba_uint8_set64(value vb, value vind, value newval) +{ + unsigned char b1, b2, b3, b4, b5, b6, b7, b8; + intnat idx = Long_val(vind); + int64_t val; + struct caml_ba_array * b = Caml_ba_array_val(vb); + if (idx < 0 || idx >= b->dim[0] - 7) caml_array_bound_error(); + val = Int64_val(newval); +#ifdef ARCH_BIG_ENDIAN + b1 = 0xFF & val >> 56; + b2 = 0xFF & val >> 48; + b3 = 0xFF & val >> 40; + b4 = 0xFF & val >> 32; + b5 = 0xFF & val >> 24; + b6 = 0xFF & val >> 16; + b7 = 0xFF & val >> 8; + b8 = 0xFF & val; +#else + b8 = 0xFF & val >> 56; + b7 = 0xFF & val >> 48; + b6 = 0xFF & val >> 40; + b5 = 0xFF & val >> 32; + b4 = 0xFF & val >> 24; + b3 = 0xFF & val >> 16; + b2 = 0xFF & val >> 8; + b1 = 0xFF & val; +#endif + ((unsigned char*) b->data)[idx] = b1; + ((unsigned char*) b->data)[idx+1] = b2; + ((unsigned char*) b->data)[idx+2] = b3; + ((unsigned char*) b->data)[idx+3] = b4; + ((unsigned char*) b->data)[idx+4] = b5; + ((unsigned char*) b->data)[idx+5] = b6; + ((unsigned char*) b->data)[idx+6] = b7; + ((unsigned char*) b->data)[idx+7] = b8; + return Val_unit; +} + +/* Return the number of dimensions of a big array */ + +CAMLprim value caml_ba_num_dims(value vb) +{ + struct caml_ba_array * b = Caml_ba_array_val(vb); + return Val_long(b->num_dims); +} + +/* Return the n-th dimension of a big array */ + +CAMLprim value caml_ba_dim(value vb, value vn) +{ + struct caml_ba_array * b = Caml_ba_array_val(vb); + intnat n = Long_val(vn); + if (n < 0 || n >= b->num_dims) caml_invalid_argument("Bigarray.dim"); + return Val_long(b->dim[n]); +} + +CAMLprim value caml_ba_dim_1(value vb) +{ + return caml_ba_dim(vb, Val_int(0)); +} + +CAMLprim value caml_ba_dim_2(value vb) +{ + return caml_ba_dim(vb, Val_int(1)); +} + +CAMLprim value caml_ba_dim_3(value vb) +{ + return caml_ba_dim(vb, Val_int(2)); +} + +/* Return the kind of a big array */ + +CAMLprim value caml_ba_kind(value vb) +{ + return Val_caml_ba_kind(Caml_ba_array_val(vb)->flags & CAML_BA_KIND_MASK); +} + +/* Return the layout of a big array */ + +CAMLprim value caml_ba_layout(value vb) +{ + int layout = Caml_ba_array_val(vb)->flags & CAML_BA_LAYOUT_MASK; + return Val_caml_ba_layout(layout); +} + +/* Create / update proxy to indicate that b2 is a sub-array of b1 */ + +static void caml_ba_update_proxy(struct caml_ba_array * b1, + struct caml_ba_array * b2) +{ + struct caml_ba_proxy * proxy; + /* Nothing to do for un-managed arrays */ + if ((b1->flags & CAML_BA_MANAGED_MASK) == CAML_BA_EXTERNAL) return; + if (b1->proxy != NULL) { + /* If b1 is already a proxy for a larger array, increment refcount of + proxy */ + b2->proxy = b1->proxy; + ++ b1->proxy->refcount; + } else { + /* Otherwise, create proxy and attach it to both b1 and b2 */ + proxy = malloc(sizeof(struct caml_ba_proxy)); + if (proxy == NULL) caml_raise_out_of_memory(); + proxy->refcount = 2; /* original array + sub array */ + proxy->data = b1->data; + proxy->size = + b1->flags & CAML_BA_MAPPED_FILE ? caml_ba_byte_size(b1) : 0; + b1->proxy = proxy; + b2->proxy = proxy; + } +} + +/* Slicing */ + +CAMLprim value caml_ba_slice(value vb, value vind) +{ + CAMLparam2 (vb, vind); + #define b (Caml_ba_array_val(vb)) + CAMLlocal1 (res); + intnat index[CAML_BA_MAX_NUM_DIMS]; + int num_inds, i; + intnat offset; + intnat * sub_dims; + char * sub_data; + + /* Check number of indices <= number of dimensions of array */ + num_inds = Wosize_val(vind); + if (num_inds > b->num_dims) + caml_invalid_argument("Bigarray.slice: too many indices"); + /* Compute offset and check bounds */ + if ((b->flags & CAML_BA_LAYOUT_MASK) == CAML_BA_C_LAYOUT) { + /* We slice from the left */ + for (i = 0; i < num_inds; i++) index[i] = Long_val(Field(vind, i)); + for (/*nothing*/; i < b->num_dims; i++) index[i] = 0; + offset = caml_ba_offset(b, index); + sub_dims = b->dim + num_inds; + } else { + /* We slice from the right */ + for (i = 0; i < num_inds; i++) + index[b->num_dims - num_inds + i] = Long_val(Field(vind, i)); + for (i = 0; i < b->num_dims - num_inds; i++) index[i] = 1; + offset = caml_ba_offset(b, index); + sub_dims = b->dim; + } + sub_data = + (char *) b->data + + offset * caml_ba_element_size[b->flags & CAML_BA_KIND_MASK]; + /* Allocate an OCaml bigarray to hold the result */ + res = caml_ba_alloc(b->flags, b->num_dims - num_inds, sub_data, sub_dims); + /* Copy the finalization function from the original array (PR#8568) */ + Custom_ops_val(res) = Custom_ops_val(vb); + /* Create or update proxy in case of managed bigarray */ + caml_ba_update_proxy(b, Caml_ba_array_val(res)); + /* Return result */ + CAMLreturn (res); + + #undef b +} + +/* Changing the layout of an array (memory is shared) */ + +CAMLprim value caml_ba_change_layout(value vb, value vlayout) +{ + CAMLparam2 (vb, vlayout); + CAMLlocal1 (res); + #define b (Caml_ba_array_val(vb)) + /* if the layout is different, change the flags and reverse the dimensions */ + if (Caml_ba_layout_val(vlayout) != (b->flags & CAML_BA_LAYOUT_MASK)) { + /* change the flags to reflect the new layout */ + int flags = (b->flags & (CAML_BA_KIND_MASK | CAML_BA_MANAGED_MASK)) + | Caml_ba_layout_val(vlayout); + /* reverse the dimensions */ + intnat new_dim[CAML_BA_MAX_NUM_DIMS]; + unsigned int i; + for(i = 0; i < b->num_dims; i++) new_dim[i] = b->dim[b->num_dims - i - 1]; + res = caml_ba_alloc(flags, b->num_dims, b->data, new_dim); + /* Copy the finalization function from the original array (PR#8568) */ + Custom_ops_val(res) = Custom_ops_val(vb); + caml_ba_update_proxy(b, Caml_ba_array_val(res)); + CAMLreturn(res); + } else { + /* otherwise, do nothing */ + CAMLreturn(vb); + } + #undef b +} + + +/* Extracting a sub-array of same number of dimensions */ + +CAMLprim value caml_ba_sub(value vb, value vofs, value vlen) +{ + CAMLparam3 (vb, vofs, vlen); + CAMLlocal1 (res); + #define b (Caml_ba_array_val(vb)) + intnat ofs = Long_val(vofs); + intnat len = Long_val(vlen); + int i, changed_dim; + intnat mul; + char * sub_data; + + /* Compute offset and check bounds */ + if ((b->flags & CAML_BA_LAYOUT_MASK) == CAML_BA_C_LAYOUT) { + /* We reduce the first dimension */ + mul = 1; + for (i = 1; i < b->num_dims; i++) mul *= b->dim[i]; + changed_dim = 0; + } else { + /* We reduce the last dimension */ + mul = 1; + for (i = 0; i < b->num_dims - 1; i++) mul *= b->dim[i]; + changed_dim = b->num_dims - 1; + ofs--; /* Fortran arrays start at 1 */ + } + if (ofs < 0 || len < 0 || ofs + len > b->dim[changed_dim]) + caml_invalid_argument("Bigarray.sub: bad sub-array"); + sub_data = + (char *) b->data + + ofs * mul * caml_ba_element_size[b->flags & CAML_BA_KIND_MASK]; + /* Allocate an OCaml bigarray to hold the result */ + res = caml_ba_alloc(b->flags, b->num_dims, sub_data, b->dim); + /* Copy the finalization function from the original array (PR#8568) */ + Custom_ops_val(res) = Custom_ops_val(vb); + /* Doctor the changed dimension */ + Caml_ba_array_val(res)->dim[changed_dim] = len; + /* Create or update proxy in case of managed bigarray */ + caml_ba_update_proxy(b, Caml_ba_array_val(res)); + /* Return result */ + CAMLreturn (res); + + #undef b +} + +/* Copying a big array into another one */ + +#define LEAVE_RUNTIME_OP_CUTOFF 4096 +#define is_mmapped(ba) ((ba)->flags & CAML_BA_MAPPED_FILE) + +CAMLprim value caml_ba_blit(value vsrc, value vdst) +{ + CAMLparam2(vsrc, vdst); + struct caml_ba_array * src = Caml_ba_array_val(vsrc); + struct caml_ba_array * dst = Caml_ba_array_val(vdst); + void *src_data = src->data; + void *dst_data = dst->data; + int i; + intnat num_bytes; + int leave_runtime; + + /* Check same numbers of dimensions and same dimensions */ + if (src->num_dims != dst->num_dims) goto blit_error; + for (i = 0; i < src->num_dims; i++) + if (src->dim[i] != dst->dim[i]) goto blit_error; + /* Compute number of bytes in array data */ + num_bytes = + caml_ba_num_elts(src) + * caml_ba_element_size[src->flags & CAML_BA_KIND_MASK]; + leave_runtime = + ( + (num_bytes >= LEAVE_RUNTIME_OP_CUTOFF*sizeof(long)) + || is_mmapped(src) + || is_mmapped(dst) + ); + /* Do the copying */ + if (leave_runtime) caml_enter_blocking_section(); + memmove (dst_data, src_data, num_bytes); + if (leave_runtime) caml_leave_blocking_section(); + CAMLreturn (Val_unit); + blit_error: + caml_invalid_argument("Bigarray.blit: dimension mismatch"); + CAMLreturn (Val_unit); /* not reached */ +} + +/* Filling a big array with a given value */ + +#define FILL_GEN_LOOP(n_ops, loop) do{ \ + int leave_runtime = ((n_ops >= LEAVE_RUNTIME_OP_CUTOFF) || is_mmapped(b)); \ + if (leave_runtime) caml_enter_blocking_section(); \ + loop; \ + if (leave_runtime) caml_leave_blocking_section(); \ +}while(0) + +#define FILL_SCALAR_LOOP \ + FILL_GEN_LOOP(num_elts, \ + for (p = data; num_elts > 0; p++, num_elts--) *p = init) + +#define FILL_COMPLEX_LOOP \ + FILL_GEN_LOOP(num_elts + num_elts, \ + for (p = data; num_elts > 0; num_elts--) { *p++ = init0; *p++ = init1; }) + +CAMLprim value caml_ba_fill(value vb, value vinit) +{ + CAMLparam1(vb); + struct caml_ba_array * b = Caml_ba_array_val(vb); + void *data = b->data; + intnat num_elts = caml_ba_num_elts(b); + + switch (b->flags & CAML_BA_KIND_MASK) { + default: + CAMLassert(0); + case CAML_BA_FLOAT32: { + float init = Double_val(vinit); + float * p; + FILL_SCALAR_LOOP; + break; + } + case CAML_BA_FLOAT64: { + double init = Double_val(vinit); + double * p; + FILL_SCALAR_LOOP; + break; + } + case CAML_BA_CHAR: + case CAML_BA_SINT8: + case CAML_BA_UINT8: { + int init = Int_val(vinit); + unsigned char * p; + FILL_SCALAR_LOOP; + break; + } + case CAML_BA_SINT16: + case CAML_BA_UINT16: { + int init = Int_val(vinit); + int16 * p; + FILL_SCALAR_LOOP; + break; + } + case CAML_BA_INT32: { + int32_t init = Int32_val(vinit); + int32_t * p; + FILL_SCALAR_LOOP; + break; + } + case CAML_BA_INT64: { + int64_t init = Int64_val(vinit); + int64_t * p; + FILL_SCALAR_LOOP; + break; + } + case CAML_BA_NATIVE_INT: { + intnat init = Nativeint_val(vinit); + intnat * p; + FILL_SCALAR_LOOP; + break; + } + case CAML_BA_CAML_INT: { + intnat init = Long_val(vinit); + intnat * p; + FILL_SCALAR_LOOP; + break; + } + case CAML_BA_COMPLEX32: { + float init0 = Double_field(vinit, 0); + float init1 = Double_field(vinit, 1); + float * p; + FILL_COMPLEX_LOOP; + break; + } + case CAML_BA_COMPLEX64: { + double init0 = Double_field(vinit, 0); + double init1 = Double_field(vinit, 1); + double * p; + FILL_COMPLEX_LOOP; + break; + } + } + CAMLreturn (Val_unit); +} + +/* Reshape an array: change dimensions and number of dimensions, preserving + array contents */ + +CAMLprim value caml_ba_reshape(value vb, value vdim) +{ + CAMLparam2 (vb, vdim); + CAMLlocal1 (res); +#define b (Caml_ba_array_val(vb)) + intnat dim[CAML_BA_MAX_NUM_DIMS]; + mlsize_t num_dims; + uintnat num_elts; + int i; + + num_dims = Wosize_val(vdim); + /* here num_dims is unsigned (mlsize_t) so no need to check (num_dims >= 0) */ + if (num_dims > CAML_BA_MAX_NUM_DIMS) + caml_invalid_argument("Bigarray.reshape: bad number of dimensions"); + num_elts = 1; + for (i = 0; i < num_dims; i++) { + dim[i] = Long_val(Field(vdim, i)); + if (dim[i] < 0) + caml_invalid_argument("Bigarray.reshape: negative dimension"); + num_elts *= dim[i]; + } + /* Check that sizes agree */ + if (num_elts != caml_ba_num_elts(b)) + caml_invalid_argument("Bigarray.reshape: size mismatch"); + /* Create bigarray with same data and new dimensions */ + res = caml_ba_alloc(b->flags, num_dims, b->data, dim); + /* Copy the finalization function from the original array (PR#8568) */ + Custom_ops_val(res) = Custom_ops_val(vb); + /* Create or update proxy in case of managed bigarray */ + caml_ba_update_proxy(b, Caml_ba_array_val(res)); + /* Return result */ + CAMLreturn (res); + +#undef b +} diff --git a/byterun/callback.c b/runtime/callback.c similarity index 100% rename from byterun/callback.c rename to runtime/callback.c diff --git a/byterun/caml/address_class.h b/runtime/caml/address_class.h similarity index 100% rename from byterun/caml/address_class.h rename to runtime/caml/address_class.h diff --git a/byterun/caml/alloc.h b/runtime/caml/alloc.h similarity index 100% rename from byterun/caml/alloc.h rename to runtime/caml/alloc.h diff --git a/runtime/caml/backtrace.h b/runtime/caml/backtrace.h new file mode 100644 index 00000000..fcc13312 --- /dev/null +++ b/runtime/caml/backtrace.h @@ -0,0 +1,137 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2001 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#ifndef CAML_BACKTRACE_H +#define CAML_BACKTRACE_H + +#ifdef CAML_INTERNALS + +#include "mlvalues.h" +#include "exec.h" + +/* Runtime support for backtrace generation. + * + * It has two kind of users: + * - high-level API to capture and decode backtraces; + * - low-level runtime routines, to introspect machine state and determine + * whether a backtrace should be generated when using "raise". + * + * Backtrace generation is split in multiple steps. + * The lowest-level one, done by [backtrace_byt.c] and + * [backtrace_nat.c] just fills the [caml_backtrace_buffer] + * variable each time a frame is unwinded. + * At that point, we don't know whether the backtrace will be useful or not so + * this code should be as fast as possible. + * + * If the backtrace happens to be useful, later passes will read + * [caml_backtrace_buffer] and turn it into a [raw_backtrace] and then a + * [backtrace]. + * This is done in [backtrace.c] and [stdlib/printexc.ml]. + * + * Content of buffers + * ------------------ + * + * [caml_backtrace_buffer] (really cheap) + * Backend and process image dependent, abstracted by C-type backtrace_slot. + * [raw_backtrace] (cheap) + * OCaml values of abstract type [Printexc.raw_backtrace_slot], + * still backend and process image dependent (unsafe to marshal). + * [backtrace] (more expensive) + * OCaml values of algebraic data-type [Printexc.backtrace_slot] + */ + +/* Non zero iff backtraces are recorded. + * One should use to change this variable [caml_record_backtrace]. + */ +CAMLextern int caml_backtrace_active; + +/* The [backtrace_slot] type represents values stored in the + * [caml_backtrace_buffer]. In bytecode, it is the same as a + * [code_t], in native code it as a [frame_descr *]. The difference + * doesn't matter for code outside [backtrace_{byt,nat}.c], + * so it is just exposed as a [backtrace_slot]. + */ +typedef void * backtrace_slot; + +/* The [caml_backtrace_buffer] and [caml_backtrace_last_exn] + * variables are valid only if [caml_backtrace_active != 0]. + * + * They are part of the state specific to each thread, and threading libraries + * are responsible for copying them on context switch. + * See [otherlibs/systhreads/st_stubs.c] and [otherlibs/threads/scheduler.c]. + */ + +/* [caml_backtrace_buffer] is filled by runtime when unwinding stack. + * It is an array ranging from [0] to [caml_backtrace_pos - 1]. + * [caml_backtrace_pos] is always zero if [!caml_backtrace_active]. + * + * Its maximum size is determined by [BACKTRACE_BUFFER_SIZE] from + * [backtrace_prim.h], but this shouldn't affect users. + */ +CAMLextern backtrace_slot * caml_backtrace_buffer; +CAMLextern int caml_backtrace_pos; + +/* [caml_backtrace_last_exn] stores the last exception value that was raised, + * iff [caml_backtrace_active != 0]. + * It is tested for equality to determine whether a raise is a re-raise of the + * same exception. + * + * FIXME: this shouldn't matter anymore. Since OCaml 4.02, non-parameterized + * exceptions are constant, so physical equality is no longer appropriate. + * raise and re-raise are distinguished by: + * - passing reraise = 1 to [caml_stash_backtrace] (see below) in the bytecode + * interpreter; + * - directly resetting [caml_backtrace_pos] to 0 in native runtimes for raise. + */ +CAMLextern value caml_backtrace_last_exn; + +/* [caml_record_backtrace] toggle backtrace recording on and off. + * This function can be called at runtime by user-code, or during + * initialization if backtraces were requested. + * + * It might be called before GC initialization, so it shouldn't do OCaml + * allocation. + */ +CAMLprim value caml_record_backtrace(value vflag); + + +#ifndef NATIVE_CODE + +/* Path to the file containing debug information, if any, or NULL. */ +CAMLextern char_os * caml_cds_file; + +/* Primitive called _only_ by runtime to record unwinded frames to + * backtrace. A similar primitive exists for native code, but with a + * different prototype. */ +extern void caml_stash_backtrace(value exn, code_t pc, value * sp, int reraise); + +#endif + + +/* Default (C-level) printer for backtraces. It is called if an + * exception causes a termination of the program or of a thread. + * + * [Printexc] provide a higher-level printer mimicking its output but making + * use of registered exception printers, and is used when possible in place of + * this function after [Printexc] initialization. + */ +CAMLextern void caml_print_exception_backtrace(void); + +void caml_init_backtrace(void); +CAMLexport void caml_init_debug_info(void); + +#endif /* CAML_INTERNALS */ + +#endif /* CAML_BACKTRACE_H */ diff --git a/runtime/caml/backtrace_prim.h b/runtime/caml/backtrace_prim.h new file mode 100644 index 00000000..b6673218 --- /dev/null +++ b/runtime/caml/backtrace_prim.h @@ -0,0 +1,100 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2001 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#ifndef CAML_BACKTRACE_PRIM_H +#define CAML_BACKTRACE_PRIM_H + +#ifdef CAML_INTERNALS + +#include "backtrace.h" + +/* Backtrace generation is split in [backtrace.c] and [backtrace_prim]. + * + * [backtrace_prim] contains all backend-specific + * code, and has two different + * implementations in [runtime/backtrace_byt.c] and [runtime/backtrace_nat.c]. + * + * [backtrace.c] has a unique implementation, and exposes a uniform + * higher level API above [backtrace_{byt,nat}.c]. + */ + +/* Extract location information for the given raw_backtrace_slot */ + +struct caml_loc_info { + int loc_valid; + int loc_is_raise; + char * loc_filename; + int loc_lnum; + int loc_startchr; + int loc_endchr; + int loc_is_inlined; +}; + +/* When compiling with -g, backtrace slots have debug info associated. + * When a call is inlined in native mode, debuginfos form a linked list. + */ +typedef void * debuginfo; + +/* Check availability of debug information before extracting a trace. + * Relevant for bytecode, always true for native code. */ +int caml_debug_info_available(void); + +/* Return debuginfo associated to a slot or NULL. */ +debuginfo caml_debuginfo_extract(backtrace_slot slot); + +/* In case of an inlined call return next debuginfo or NULL otherwise. */ +debuginfo caml_debuginfo_next(debuginfo dbg); + +/* Extract locations from backtrace_slot */ +void caml_debuginfo_location(debuginfo dbg, /*out*/ struct caml_loc_info * li); + +/* In order to prevent the GC from walking through the debug + information (which have no headers), we transform slots to 31/63 bits + ocaml integers by shifting them by 1 to the right. We do not lose + information as slots are aligned. + + In particular, we do not need to use [caml_modify] when setting + an array element with such a value. + */ +#define Val_backtrace_slot(bslot) (Val_long(((uintnat)(bslot))>>1)) +#define Backtrace_slot_val(vslot) ((backtrace_slot)(Long_val(vslot) << 1)) + +/* Allocate the caml_backtrace_buffer. Returns 0 on success, -1 otherwise */ +int caml_alloc_backtrace_buffer(void); + +#ifndef NATIVE_CODE +/* These two functions are used by the bytecode runtime when loading + and unloading bytecode */ +value caml_add_debug_info(code_t code_start, value code_size, + value events_heap); +value caml_remove_debug_info(code_t start); +#endif + +#define BACKTRACE_BUFFER_SIZE 1024 + +/* Besides decoding backtrace info, [backtrace_prim] has two other + * responsibilities: + * + * It defines the [caml_stash_backtrace] function, which is called to quickly + * fill the backtrace buffer by walking the stack when an exception is raised. + * + * It also defines the [caml_get_current_callstack] OCaml primitive, which also + * walks the stack but directly turns it into a [raw_backtrace] and is called + * explicitly. + */ + +#endif /* CAML_INTERNALS */ + +#endif /* CAML_BACKTRACE_PRIM_H */ diff --git a/byterun/caml/bigarray.h b/runtime/caml/bigarray.h similarity index 100% rename from byterun/caml/bigarray.h rename to runtime/caml/bigarray.h diff --git a/byterun/caml/callback.h b/runtime/caml/callback.h similarity index 100% rename from byterun/caml/callback.h rename to runtime/caml/callback.h diff --git a/byterun/caml/compact.h b/runtime/caml/compact.h similarity index 100% rename from byterun/caml/compact.h rename to runtime/caml/compact.h diff --git a/byterun/caml/compare.h b/runtime/caml/compare.h similarity index 100% rename from byterun/caml/compare.h rename to runtime/caml/compare.h diff --git a/runtime/caml/compatibility.h b/runtime/caml/compatibility.h new file mode 100644 index 00000000..c2e1881c --- /dev/null +++ b/runtime/caml/compatibility.h @@ -0,0 +1,375 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Moscova, INRIA Rocquencourt */ +/* */ +/* Copyright 2003 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* definitions for compatibility with old identifiers */ + +#ifndef CAML_COMPATIBILITY_H +#define CAML_COMPATIBILITY_H + +/* internal global variables renamed between 4.02.1 and 4.03.0 */ +#define caml_stat_top_heap_size Bsize_wsize(caml_stat_top_heap_wsz) +#define caml_stat_heap_size Bsize_wsize(caml_stat_heap_wsz) + +#ifndef CAML_NAME_SPACE + +/* + #define --> CAMLextern (defined with CAMLexport or CAMLprim) + (rien) --> CAMLprim + g --> global C identifier + x --> special case + + SP* signals the special cases: + - when the identifier was not simply prefixed with [caml_] + - when the [caml_] version was already used for something else, and + was renamed out of the way (watch out for [caml_alloc] and + [caml_array_bound_error] in *.s) +*/ + +/* a faire: + - ui_* (reverifier que win32.c n'en depend pas) +*/ + + +/* **** alloc.c */ +#define alloc caml_alloc /*SP*/ +#define alloc_small caml_alloc_small +#define alloc_tuple caml_alloc_tuple +#define alloc_string caml_alloc_string +#define alloc_final caml_alloc_final +#define copy_string caml_copy_string +#define alloc_array caml_alloc_array +#define copy_string_array caml_copy_string_array +#define convert_flag_list caml_convert_flag_list + +/* **** array.c */ + +/* **** backtrace.c */ +#define backtrace_active caml_backtrace_active +#define backtrace_pos caml_backtrace_pos +#define backtrace_buffer caml_backtrace_buffer +#define backtrace_last_exn caml_backtrace_last_exn +#define print_exception_backtrace caml_print_exception_backtrace + +/* **** callback.c */ +#define callback_depth caml_callback_depth +#define callbackN_exn caml_callbackN_exn +#define callback_exn caml_callback_exn +#define callback2_exn caml_callback2_exn +#define callback3_exn caml_callback3_exn +#define callback caml_callback +#define callback2 caml_callback2 +#define callback3 caml_callback3 +#define callbackN caml_callbackN + +/* **** compact.c */ + +/* **** compare.c */ +#define compare_unordered caml_compare_unordered + +/* **** custom.c */ +#define alloc_custom caml_alloc_custom +#define register_custom_operations caml_register_custom_operations + +/* **** debugger.c */ + +/* **** dynlink.c */ + +/* **** extern.c */ +#define output_val caml_output_val +#define output_value_to_malloc caml_output_value_to_malloc +#define output_value_to_block caml_output_value_to_block +#define serialize_int_1 caml_serialize_int_1 +#define serialize_int_2 caml_serialize_int_2 +#define serialize_int_4 caml_serialize_int_4 +#define serialize_int_8 caml_serialize_int_8 +#define serialize_float_4 caml_serialize_float_4 +#define serialize_float_8 caml_serialize_float_8 +#define serialize_block_1 caml_serialize_block_1 +#define serialize_block_2 caml_serialize_block_2 +#define serialize_block_4 caml_serialize_block_4 +#define serialize_block_8 caml_serialize_block_8 +#define serialize_block_float_8 caml_serialize_block_float_8 + +/* **** fail.c */ +#define external_raise caml_external_raise +#define mlraise caml_raise /*SP*/ +#define raise_constant caml_raise_constant +#define raise_with_arg caml_raise_with_arg +#define raise_with_string caml_raise_with_string +#define failwith caml_failwith +#define invalid_argument caml_invalid_argument +#define array_bound_error caml_array_bound_error /*SP*/ +#define raise_out_of_memory caml_raise_out_of_memory +#define raise_stack_overflow caml_raise_stack_overflow +#define raise_sys_error caml_raise_sys_error +#define raise_end_of_file caml_raise_end_of_file +#define raise_zero_divide caml_raise_zero_divide +#define raise_not_found caml_raise_not_found +#define raise_sys_blocked_io caml_raise_sys_blocked_io +/* **** runtime/fail_nat.c */ +/* **** runtime/.s */ + +/* **** finalise.c */ + +/* **** fix_code.c */ + +/* **** floats.c */ +/*#define Double_val caml_Double_val done in mlvalues.h as needed */ +/*#define Store_double_val caml_Store_double_val done in mlvalues.h as needed */ +#define copy_double caml_copy_double + +/* **** freelist.c */ + +/* **** gc_ctrl.c */ + +/* **** globroots.c */ +#define register_global_root caml_register_global_root +#define remove_global_root caml_remove_global_root + +/* **** hash.c */ +#define hash_variant caml_hash_variant + +/* **** instrtrace.c */ + +/* **** intern.c */ +#define input_val caml_input_val +#define input_val_from_string caml_input_val_from_string +#define input_value_from_malloc caml_input_value_from_malloc +#define input_value_from_block caml_input_value_from_block +#define deserialize_uint_1 caml_deserialize_uint_1 +#define deserialize_sint_1 caml_deserialize_sint_1 +#define deserialize_uint_2 caml_deserialize_uint_2 +#define deserialize_sint_2 caml_deserialize_sint_2 +#define deserialize_uint_4 caml_deserialize_uint_4 +#define deserialize_sint_4 caml_deserialize_sint_4 +#define deserialize_uint_8 caml_deserialize_uint_8 +#define deserialize_sint_8 caml_deserialize_sint_8 +#define deserialize_float_4 caml_deserialize_float_4 +#define deserialize_float_8 caml_deserialize_float_8 +#define deserialize_block_1 caml_deserialize_block_1 +#define deserialize_block_2 caml_deserialize_block_2 +#define deserialize_block_4 caml_deserialize_block_4 +#define deserialize_block_8 caml_deserialize_block_8 +#define deserialize_block_float_8 caml_deserialize_block_float_8 +#define deserialize_error caml_deserialize_error + +/* **** interp.c */ + +/* **** ints.c */ +#define int32_ops caml_int32_ops +#define copy_int32 caml_copy_int32 +/*#define Int64_val caml_Int64_val *** done in mlvalues.h as needed */ +#define int64_ops caml_int64_ops +#define copy_int64 caml_copy_int64 +#define nativeint_ops caml_nativeint_ops +#define copy_nativeint caml_copy_nativeint + +/* **** io.c */ +#define channel_mutex_free caml_channel_mutex_free +#define channel_mutex_lock caml_channel_mutex_lock +#define channel_mutex_unlock caml_channel_mutex_unlock +#define channel_mutex_unlock_exn caml_channel_mutex_unlock_exn +#define all_opened_channels caml_all_opened_channels +#define open_descriptor_in caml_open_descriptor_in /*SP*/ +#define open_descriptor_out caml_open_descriptor_out /*SP*/ +#define close_channel caml_close_channel /*SP*/ +#define channel_size caml_channel_size /*SP*/ +#define channel_binary_mode caml_channel_binary_mode +#define flush_partial caml_flush_partial /*SP*/ +#define flush caml_flush /*SP*/ +#define putword caml_putword +#define putblock caml_putblock +#define really_putblock caml_really_putblock +#define seek_out caml_seek_out /*SP*/ +#define pos_out caml_pos_out /*SP*/ +#define do_read caml_do_read +#define refill caml_refill +#define getword caml_getword +#define getblock caml_getblock +#define really_getblock caml_really_getblock +#define seek_in caml_seek_in /*SP*/ +#define pos_in caml_pos_in /*SP*/ +#define input_scan_line caml_input_scan_line /*SP*/ +#define finalize_channel caml_finalize_channel +#define alloc_channel caml_alloc_channel +/*#define Val_file_offset caml_Val_file_offset *** done in io.h as needed */ +/*#define File_offset_val caml_File_offset_val *** done in io.h as needed */ + +/* **** lexing.c */ + +/* **** main.c */ +/* *** no change */ + +/* **** major_gc.c */ +#define heap_start caml_heap_start +#define page_table caml_page_table + +/* **** md5.c */ +#define md5_string caml_md5_string +#define md5_chan caml_md5_chan +#define MD5Init caml_MD5Init +#define MD5Update caml_MD5Update +#define MD5Final caml_MD5Final +#define MD5Transform caml_MD5Transform + +/* **** memory.c */ +#define alloc_shr caml_alloc_shr +#define initialize caml_initialize +#define modify caml_modify +#define stat_alloc caml_stat_alloc +#define stat_free caml_stat_free +#define stat_resize caml_stat_resize + +/* **** meta.c */ + +/* **** minor_gc.c */ +#define young_start caml_young_start +#define young_end caml_young_end +#define young_ptr caml_young_ptr +#define young_limit caml_young_limit +#define ref_table caml_ref_table +#define minor_collection caml_minor_collection +#define check_urgent_gc caml_check_urgent_gc + +/* **** misc.c */ + +/* **** obj.c */ + +/* **** parsing.c */ + +/* **** prims.c */ + +/* **** printexc.c */ +#define format_caml_exception caml_format_exception /*SP*/ + +/* **** roots.c */ +#define local_roots caml_local_roots +#define scan_roots_hook caml_scan_roots_hook +#define do_local_roots caml_do_local_roots + +/* **** signals.c */ +#define pending_signals caml_pending_signals +#define something_to_do caml_something_to_do +#define enter_blocking_section_hook caml_enter_blocking_section_hook +#define leave_blocking_section_hook caml_leave_blocking_section_hook +#define try_leave_blocking_section_hook caml_try_leave_blocking_section_hook +#define async_action_hook caml_async_action_hook +#define enter_blocking_section caml_enter_blocking_section +#define leave_blocking_section caml_leave_blocking_section +#define convert_signal_number caml_convert_signal_number +/* **** runtime/signals.c */ +#define garbage_collection caml_garbage_collection + +/* **** stacks.c */ +#define stack_low caml_stack_low +#define stack_high caml_stack_high +#define stack_threshold caml_stack_threshold +#define extern_sp caml_extern_sp +#define trapsp caml_trapsp +#define trap_barrier caml_trap_barrier + +/* **** startup.c */ +#define atom_table caml_atom_table +/* **** runtime/startup_nat.c */ +#define static_data_start caml_static_data_start +#define static_data_end caml_static_data_end + +/* **** str.c */ +#define string_length caml_string_length + +/* **** sys.c */ +#define sys_error caml_sys_error +#define sys_exit caml_sys_exit + +/* **** terminfo.c */ + +/* **** unix.c & win32.c */ +#define search_exe_in_path caml_search_exe_in_path + +/* **** weak.c */ + +/* **** asmcomp/asmlink.ml */ + +/* **** asmcomp/cmmgen.ml */ + +/* **** asmcomp/asmlink.ml, asmcomp/cmmgen.ml, asmcomp/compilenv.ml */ + +/* ************************************************************* */ + +/* **** otherlibs/bigarray */ +#define int8 caml_ba_int8 +#define uint8 caml_ba_uint8 +#define int16 caml_ba_int16 +#define uint16 caml_ba_uint16 +#define MAX_NUM_DIMS CAML_BA_MAX_NUM_DIMS +#define caml_bigarray_kind caml_ba_kind +#define BIGARRAY_FLOAT32 CAML_BA_FLOAT32 +#define BIGARRAY_FLOAT64 CAML_BA_FLOAT64 +#define BIGARRAY_SINT8 CAML_BA_SINT8 +#define BIGARRAY_UINT8 CAML_BA_UINT8 +#define BIGARRAY_SINT16 CAML_BA_SINT16 +#define BIGARRAY_UINT16 CAML_BA_UINT16 +#define BIGARRAY_INT32 CAML_BA_INT32 +#define BIGARRAY_INT64 CAML_BA_INT64 +#define BIGARRAY_CAML_INT CAML_BA_CAML_INT +#define BIGARRAY_NATIVE_INT CAML_BA_NATIVE_INT +#define BIGARRAY_COMPLEX32 CAML_BA_COMPLEX32 +#define BIGARRAY_COMPLEX64 CAML_BA_COMPLEX64 +#define BIGARRAY_KIND_MASK CAML_BA_KIND_MASK +#define caml_bigarray_layout caml_ba_layout +#define BIGARRAY_C_LAYOUT CAML_BA_C_LAYOUT +#define BIGARRAY_FORTRAN_LAYOUT CAML_BA_FORTRAN_LAYOUT +#define BIGARRAY_LAYOUT_MASK CAML_BA_LAYOUT_MASK +#define caml_bigarray_managed caml_ba_managed +#define BIGARRAY_EXTERNAL CAML_BA_EXTERNAL +#define BIGARRAY_MANAGED CAML_BA_MANAGED +#define BIGARRAY_MAPPED_FILE CAML_BA_MAPPED_FILE +#define BIGARRAY_MANAGED_MASK CAML_BA_MANAGED_MASK +#define caml_bigarray_proxy caml_ba_proxy +#define caml_bigarray caml_ba_array +#define Bigarray_val Caml_ba_array_val +#define Data_bigarray_val Caml_ba_data_val +#define alloc_bigarray caml_ba_alloc +#define alloc_bigarray_dims caml_ba_alloc_dims +#define bigarray_map_file caml_ba_map_file +#define bigarray_unmap_file caml_ba_unmap_file +#define bigarray_element_size caml_ba_element_size +#define bigarray_byte_size caml_ba_byte_size +#define bigarray_deserialize caml_ba_deserialize +#define MAX_BIGARRAY_MEMORY CAML_BA_MAX_MEMORY +#define bigarray_create caml_ba_create +#define bigarray_get_N caml_ba_get_N +#define bigarray_get_1 caml_ba_get_1 +#define bigarray_get_2 caml_ba_get_2 +#define bigarray_get_3 caml_ba_get_3 +#define bigarray_get_generic caml_ba_get_generic +#define bigarray_set_1 caml_ba_set_1 +#define bigarray_set_2 caml_ba_set_2 +#define bigarray_set_3 caml_ba_set_3 +#define bigarray_set_N caml_ba_set_N +#define bigarray_set_generic caml_ba_set_generic +#define bigarray_num_dims caml_ba_num_dims +#define bigarray_dim caml_ba_dim +#define bigarray_kind caml_ba_kind +#define bigarray_layout caml_ba_layout +#define bigarray_slice caml_ba_slice +#define bigarray_sub caml_ba_sub +#define bigarray_blit caml_ba_blit +#define bigarray_fill caml_ba_fill +#define bigarray_reshape caml_ba_reshape +#define bigarray_init caml_ba_init + +#endif /* CAML_NAME_SPACE */ +#endif /* CAML_COMPATIBILITY_H */ diff --git a/runtime/caml/config.h b/runtime/caml/config.h new file mode 100644 index 00000000..584d2682 --- /dev/null +++ b/runtime/caml/config.h @@ -0,0 +1,258 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#ifndef CAML_CONFIG_H +#define CAML_CONFIG_H + +#include "m.h" + +/* If supported, tell gcc that we can use 32-bit code addresses for + * threaded code, unless we are compiled for a shared library (-fPIC option) */ +#ifdef HAS_ARCH_CODE32 +#ifndef __PIC__ +# define ARCH_CODE32 +#endif /* __PIC__ */ +#endif /* HAS_ARCH_CODE32 */ + +/* Microsoft introduced the LL integer literal suffix in Visual C++ .NET 2003 */ +#if defined(_MSC_VER) && _MSC_VER < 1400 +#define INT64_LITERAL(s) s ## i64 +#else +#define INT64_LITERAL(s) s ## LL +#endif + +#if defined(_MSC_VER) && !defined(__cplusplus) +#define inline __inline +#endif + +#include "s.h" + +#if defined(_MSC_VER) && _MSC_VER < 1300 +#define LACKS_SANE_NAN +#define LACKS_VSCPRINTF +#endif + +#ifdef BOOTSTRAPPING_FLEXLINK +#undef SUPPORT_DYNAMIC_LINKING +#endif + +#ifndef CAML_NAME_SPACE +#include "compatibility.h" +#endif + +#include + +#if defined(HAS_LOCALE_H) || defined(HAS_XLOCALE_H) +#define HAS_LOCALE +#endif + +#ifdef HAS_STDINT_H +#include +#endif + +#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1800) +#define ARCH_SIZET_PRINTF_FORMAT "I" +#else +#define ARCH_SIZET_PRINTF_FORMAT "z" +#endif + +/* Types for 32-bit integers, 64-bit integers, and + native integers (as wide as a pointer type) */ + +#ifndef ARCH_INT32_TYPE +#if SIZEOF_INT == 4 +#define ARCH_INT32_TYPE int +#define ARCH_UINT32_TYPE unsigned int +#define ARCH_INT32_PRINTF_FORMAT "" +#elif SIZEOF_LONG == 4 +#define ARCH_INT32_TYPE long +#define ARCH_UINT32_TYPE unsigned long +#define ARCH_INT32_PRINTF_FORMAT "l" +#elif SIZEOF_SHORT == 4 +#define ARCH_INT32_TYPE short +#define ARCH_UINT32_TYPE unsigned short +#define ARCH_INT32_PRINTF_FORMAT "" +#else +#error "No 32-bit integer type available" +#endif +#endif + +#ifdef __MINGW32__ + #define ARCH_INT64_TYPE long long + #define ARCH_UINT64_TYPE unsigned long long + #define ARCH_INT64_PRINTF_FORMAT "I64" +#elif defined(_MSC_VER) + #define ARCH_INT64_TYPE __int64 + #define ARCH_UINT64_TYPE unsigned __int64 + #define ARCH_INT64_PRINTF_FORMAT "I64" +#else + #if SIZEOF_LONG == 8 + #define ARCH_INT64_TYPE long + #define ARCH_UINT64_TYPE unsigned long + #define ARCH_INT64_PRINTF_FORMAT "l" + #elif SIZEOF_LONGLONG == 8 + #define ARCH_INT64_TYPE long long + #define ARCH_UINT64_TYPE unsigned long long + #define ARCH_INT64_PRINTF_FORMAT "ll" + #else + #error "No 64-bit integer type available" + #endif +#endif + +#ifndef HAS_STDINT_H +/* Not a C99 compiler, typically MSVC. Define the C99 types we use. */ +typedef ARCH_INT32_TYPE int32_t; +typedef ARCH_UINT32_TYPE uint32_t; +typedef ARCH_INT64_TYPE int64_t; +typedef ARCH_UINT64_TYPE uint64_t; +#if SIZEOF_SHORT == 2 +typedef short int16_t; +typedef unsigned short uint16_t; +#else +#error "No 16-bit integer type available" +#endif +#endif + +#if SIZEOF_PTR == SIZEOF_LONG +/* Standard models: ILP32 or I32LP64 */ +typedef long intnat; +typedef unsigned long uintnat; +#define ARCH_INTNAT_PRINTF_FORMAT "l" +#elif SIZEOF_PTR == SIZEOF_INT +/* Hypothetical IP32L64 model */ +typedef int intnat; +typedef unsigned int uintnat; +#define ARCH_INTNAT_PRINTF_FORMAT "" +#elif SIZEOF_PTR == 8 +/* Win64 model: IL32P64 */ +typedef int64_t intnat; +typedef uint64_t uintnat; +#define ARCH_INTNAT_PRINTF_FORMAT ARCH_INT64_PRINTF_FORMAT +#else +#error "No integer type available to represent pointers" +#endif + +/* Endianness of floats */ + +/* ARCH_FLOAT_ENDIANNESS encodes the byte order of doubles as follows: + the value [0xabcdefgh] means that the least significant byte of the + float is at byte offset [a], the next lsb at [b], ..., and the + most significant byte at [h]. */ + +#if defined(__arm__) && !defined(__ARM_EABI__) +#define ARCH_FLOAT_ENDIANNESS 0x45670123 +#elif defined(ARCH_BIG_ENDIAN) +#define ARCH_FLOAT_ENDIANNESS 0x76543210 +#else +#define ARCH_FLOAT_ENDIANNESS 0x01234567 +#endif + + +/* We use threaded code interpretation if the compiler provides labels + as first-class values (GCC 2.x). */ + +#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(DEBUG) \ + && !defined (SHRINKED_GNUC) && !defined(CAML_JIT) +#define THREADED_CODE +#endif + + +/* Memory model parameters */ + +/* The size of a page for memory management (in bytes) is [1 << Page_log]. + [Page_size] must be a multiple of [sizeof (value)]. + [Page_log] must be be >= 8 and <= 20. + Do not change the definition of [Page_size]. */ +#define Page_log 12 /* A page is 4 kilobytes. */ +#define Page_size (1 << Page_log) + +/* Initial size of stack (bytes). */ +#define Stack_size (4096 * sizeof(value)) + +/* Minimum free size of stack (bytes); below that, it is reallocated. */ +#define Stack_threshold (256 * sizeof(value)) + +/* Default maximum size of the stack (words). */ +#define Max_stack_def (1024 * 1024) + + +/* Maximum size of a block allocated in the young generation (words). */ +/* Must be > 4 */ +#define Max_young_wosize 256 +#define Max_young_whsize (Whsize_wosize (Max_young_wosize)) + + +/* Minimum size of the minor zone (words). + This must be at least [2 * Max_young_whsize]. */ +#define Minor_heap_min 4096 + +/* Maximum size of the minor zone (words). + Must be greater than or equal to [Minor_heap_min]. +*/ +#define Minor_heap_max (1 << 28) + +/* Default size of the minor zone. (words) */ +#define Minor_heap_def 262144 + + +/* Minimum size increment when growing the heap (words). + Must be a multiple of [Page_size / sizeof (value)]. */ +#define Heap_chunk_min (15 * Page_size) + +/* Default size increment when growing the heap. + If this is <= 1000, it's a percentage of the current heap size. + If it is > 1000, it's a number of words. */ +#define Heap_chunk_def 15 + +/* Default initial size of the major heap (words); + Must be a multiple of [Page_size / sizeof (value)]. */ +#define Init_heap_def (31 * Page_size) +/* (about 512 kB for a 32-bit platform, 1 MB for a 64-bit platform.) */ + + +/* Default speed setting for the major GC. The heap will grow until + the dead objects and the free list represent this percentage of the + total size of live objects. */ +#define Percent_free_def 80 + +/* Default setting for the compacter: 500% + (i.e. trigger the compacter when 5/6 of the heap is free or garbage) + This can be set quite high because the overhead is over-estimated + when fragmentation occurs. + */ +#define Max_percent_free_def 500 + +/* Default setting for the major GC slice smoothing window: 1 + (i.e. no smoothing) +*/ +#define Major_window_def 1 + +/* Maximum size of the major GC slice smoothing window. */ +#define Max_major_window 50 + +/* Default setting for the ratio of custom garbage to major heap size. + Documented in gc.mli */ +#define Custom_major_ratio_def 44 + +/* Default setting for the ratio of custom garbage to minor heap size. + Documented in gc.mli */ +#define Custom_minor_ratio_def 100 + +/* Default setting for maximum size of custom objects counted as garbage + in the minor heap. + Documented in gc.mli */ +#define Custom_minor_max_bsz_def 8192 + +#endif /* CAML_CONFIG_H */ diff --git a/runtime/caml/custom.h b/runtime/caml/custom.h new file mode 100644 index 00000000..4e70edb1 --- /dev/null +++ b/runtime/caml/custom.h @@ -0,0 +1,84 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#ifndef CAML_CUSTOM_H +#define CAML_CUSTOM_H + + +#ifndef CAML_NAME_SPACE +#include "compatibility.h" +#endif +#include "mlvalues.h" + +struct custom_fixed_length { + intnat bsize_32; + intnat bsize_64; +}; + +struct custom_operations { + char *identifier; + void (*finalize)(value v); + int (*compare)(value v1, value v2); + intnat (*hash)(value v); + void (*serialize)(value v, + /*out*/ uintnat * bsize_32 /*size in bytes*/, + /*out*/ uintnat * bsize_64 /*size in bytes*/); + uintnat (*deserialize)(void * dst); + int (*compare_ext)(value v1, value v2); + const struct custom_fixed_length* fixed_length; +}; + +#define custom_finalize_default NULL +#define custom_compare_default NULL +#define custom_hash_default NULL +#define custom_serialize_default NULL +#define custom_deserialize_default NULL +#define custom_compare_ext_default NULL +#define custom_fixed_length_default NULL + +#define Custom_ops_val(v) (*((struct custom_operations **) (v))) + +#ifdef __cplusplus +extern "C" { +#endif + + +CAMLextern value caml_alloc_custom(struct custom_operations * ops, + uintnat size, /*size in bytes*/ + mlsize_t mem, /*resources consumed*/ + mlsize_t max /*max resources*/); + +CAMLextern value caml_alloc_custom_mem(struct custom_operations * ops, + uintnat size, /*size in bytes*/ + mlsize_t mem /*memory consumed*/); + +CAMLextern void caml_register_custom_operations(struct custom_operations * ops); + +CAMLextern int caml_compare_unordered; + /* Used by custom comparison to report unordered NaN-like cases. */ + +#ifdef CAML_INTERNALS +extern struct custom_operations * caml_find_custom_operations(char * ident); +extern struct custom_operations * + caml_final_custom_operations(void (*fn)(value)); + +extern void caml_init_custom_operations(void); +#endif /* CAML_INTERNALS */ + +#ifdef __cplusplus +} +#endif + +#endif /* CAML_CUSTOM_H */ diff --git a/byterun/caml/debugger.h b/runtime/caml/debugger.h similarity index 100% rename from byterun/caml/debugger.h rename to runtime/caml/debugger.h diff --git a/runtime/caml/dune b/runtime/caml/dune new file mode 100644 index 00000000..5b6c7cb2 --- /dev/null +++ b/runtime/caml/dune @@ -0,0 +1,29 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +(rule + (targets jumptbl.h) + (mode fallback) + (deps (:h instruct.h)) + (action + (with-stdout-to %{targets} + (bash "cat %{h} | tr -d '\\r' | \ + sed -n -e '/^ /s/ \\([A-Z]\\)/ \\&\\&lbl_\\1/gp' -e '/^}/q'")))) + +(rule + (targets version.h) + (mode fallback) + (action + (with-stdout-to %{targets} + (run %{dep:../../tools/make-version-header.sh} %{dep:../../VERSION})))) diff --git a/byterun/caml/dynlink.h b/runtime/caml/dynlink.h similarity index 100% rename from byterun/caml/dynlink.h rename to runtime/caml/dynlink.h diff --git a/runtime/caml/exec.h b/runtime/caml/exec.h new file mode 100644 index 00000000..07c5310d --- /dev/null +++ b/runtime/caml/exec.h @@ -0,0 +1,67 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* exec.h : format of executable bytecode files */ + +#ifndef CAML_EXEC_H +#define CAML_EXEC_H + +#ifdef CAML_INTERNALS + +/* Executable bytecode files are composed of a number of sections, + identified by 4-character names. A table of contents at the + end of the file lists the section names along with their sizes, + in the order in which they appear in the file: + + offset 0 ---> initial junk + data for section 1 + data for section 2 + ... + data for section N + table of contents: + descriptor for section 1 + ... + descriptor for section N + trailer + end of file ---> +*/ + +/* Structure of t.o.c. entries + Numerical quantities are 32-bit unsigned integers, big endian */ + +struct section_descriptor { + char name[4]; /* Section name */ + uint32_t len; /* Length of data in bytes */ +}; + +#define EXEC_MAGIC_LENGTH 12 + +/* Structure of the trailer. */ + +struct exec_trailer { + uint32_t num_sections; /* Number of sections */ + char magic[EXEC_MAGIC_LENGTH]; /* The magic number */ + struct section_descriptor * section; /* Not part of file */ +}; + +#define TRAILER_SIZE (4+EXEC_MAGIC_LENGTH) + +/* Magic number for this release */ + +#define EXEC_MAGIC "Caml1999X025" + +#endif /* CAML_INTERNALS */ + +#endif /* CAML_EXEC_H */ diff --git a/byterun/caml/fail.h b/runtime/caml/fail.h similarity index 100% rename from byterun/caml/fail.h rename to runtime/caml/fail.h diff --git a/runtime/caml/finalise.h b/runtime/caml/finalise.h new file mode 100644 index 00000000..5c8ea24c --- /dev/null +++ b/runtime/caml/finalise.h @@ -0,0 +1,36 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Moscova, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#ifndef CAML_FINALISE_H +#define CAML_FINALISE_H + +#ifdef CAML_INTERNALS + +#include "roots.h" + +void caml_final_update_mark_phase (void); +void caml_final_update_clean_phase (void); +void caml_final_do_calls (void); +void caml_final_do_roots (scanning_action f); +void caml_final_invert_finalisable_values (void); +void caml_final_oldify_young_roots (void); +void caml_final_empty_young (void); +void caml_final_update_minor_roots(void); +value caml_final_register (value f, value v); +void caml_final_invariant_check(void); + +#endif /* CAML_INTERNALS */ + +#endif /* CAML_FINALISE_H */ diff --git a/byterun/caml/fix_code.h b/runtime/caml/fix_code.h similarity index 100% rename from byterun/caml/fix_code.h rename to runtime/caml/fix_code.h diff --git a/byterun/caml/freelist.h b/runtime/caml/freelist.h similarity index 100% rename from byterun/caml/freelist.h rename to runtime/caml/freelist.h diff --git a/runtime/caml/gc.h b/runtime/caml/gc.h new file mode 100644 index 00000000..5276087e --- /dev/null +++ b/runtime/caml/gc.h @@ -0,0 +1,79 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#ifndef CAML_GC_H +#define CAML_GC_H + + +#include "mlvalues.h" + +#define Caml_white (0 << 8) +#define Caml_gray (1 << 8) +#define Caml_blue (2 << 8) +#define Caml_black (3 << 8) + +#define Color_hd(hd) ((color_t) ((hd) & Caml_black)) +#define Color_hp(hp) (Color_hd (Hd_hp (hp))) +#define Color_val(val) (Color_hd (Hd_val (val))) + +#define Is_white_hd(hd) (Color_hd (hd) == Caml_white) +#define Is_gray_hd(hd) (Color_hd (hd) == Caml_gray) +#define Is_blue_hd(hd) (Color_hd (hd) == Caml_blue) +#define Is_black_hd(hd) (Color_hd (hd) == Caml_black) + +#define Whitehd_hd(hd) (((hd) & ~Caml_black)/*| Caml_white*/) +#define Grayhd_hd(hd) (((hd) & ~Caml_black) | Caml_gray) +#define Blackhd_hd(hd) (((hd)/*& ~Caml_black*/)| Caml_black) +#define Bluehd_hd(hd) (((hd) & ~Caml_black) | Caml_blue) + +/* This depends on the layout of the header. See [mlvalues.h]. */ +#define Make_header(wosize, tag, color) \ + (/*CAMLassert ((wosize) <= Max_wosize),*/ \ + ((header_t) (((header_t) (wosize) << 10) \ + + (color) \ + + (tag_t) (tag))) \ + ) + +#ifdef WITH_PROFINFO +#define Make_header_with_profinfo(wosize, tag, color, profinfo) \ + (Make_header(wosize, tag, color) \ + | ((((intnat) profinfo) & PROFINFO_MASK) << PROFINFO_SHIFT) \ + ) +#else +#define Make_header_with_profinfo(wosize, tag, color, profinfo) \ + Make_header(wosize, tag, color) +#endif + +#ifdef WITH_SPACETIME +struct ext_table; +extern uintnat caml_spacetime_my_profinfo(struct ext_table**, uintnat); +#define Make_header_allocated_here(wosize, tag, color) \ + (Make_header_with_profinfo(wosize, tag, color, \ + caml_spacetime_my_profinfo(NULL, wosize)) \ + ) +#else +#define Make_header_allocated_here Make_header +#endif + +#define Is_white_val(val) (Color_val(val) == Caml_white) +#define Is_gray_val(val) (Color_val(val) == Caml_gray) +#define Is_blue_val(val) (Color_val(val) == Caml_blue) +#define Is_black_val(val) (Color_val(val) == Caml_black) + +/* For extern.c */ +#define Colornum_hd(hd) ((color_t) (((hd) >> 8) & 3)) +#define Coloredhd_hd(hd,colnum) (((hd) & ~Caml_black) | ((colnum) << 8)) + +#endif /* CAML_GC_H */ diff --git a/runtime/caml/gc_ctrl.h b/runtime/caml/gc_ctrl.h new file mode 100644 index 00000000..aeff1ec8 --- /dev/null +++ b/runtime/caml/gc_ctrl.h @@ -0,0 +1,62 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#ifndef CAML_GC_CTRL_H +#define CAML_GC_CTRL_H + +#ifdef CAML_INTERNALS + +#include "misc.h" + +extern double + caml_stat_minor_words, + caml_stat_promoted_words, + caml_stat_major_words; + +extern intnat + caml_stat_minor_collections, + caml_stat_major_collections, + caml_stat_heap_wsz, + caml_stat_top_heap_wsz, + caml_stat_compactions, + caml_stat_heap_chunks; + +uintnat caml_normalize_heap_increment (uintnat); + +/* + minor_size: cf. minor_heap_size in gc.mli + major_size: Size in words of the initial major heap + major_incr: cf. major_heap_increment in gc.mli + percent_fr: cf. space_overhead in gc.mli + percent_m : cf. max_overhead in gc.mli + window : cf. window_size in gc.mli + custom_maj: cf. custom_major_ratio in gc.mli + custom_min: cf. custom_minor_ratio in gc.mli + custom_sz : cf. custom_minor_max_size in gc.mli +*/ +void caml_init_gc (uintnat minor_size, uintnat major_size, uintnat major_incr, + uintnat percent_fr, uintnat percent_m, uintnat window, + uintnat custom_maj, uintnat custom_min, uintnat custom_bsz); + + +CAMLextern value caml_gc_stat(value v); + +#ifdef DEBUG +void caml_heap_check (void); +#endif + +#endif /* CAML_INTERNALS */ + +#endif /* CAML_GC_CTRL_H */ diff --git a/byterun/caml/globroots.h b/runtime/caml/globroots.h similarity index 100% rename from byterun/caml/globroots.h rename to runtime/caml/globroots.h diff --git a/byterun/caml/hash.h b/runtime/caml/hash.h similarity index 100% rename from byterun/caml/hash.h rename to runtime/caml/hash.h diff --git a/byterun/caml/hooks.h b/runtime/caml/hooks.h similarity index 100% rename from byterun/caml/hooks.h rename to runtime/caml/hooks.h diff --git a/runtime/caml/instrtrace.h b/runtime/caml/instrtrace.h new file mode 100644 index 00000000..17ee3ce0 --- /dev/null +++ b/runtime/caml/instrtrace.h @@ -0,0 +1,35 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Trace the instructions executed */ + +#ifndef _instrtrace_ +#define _instrtrace_ + +#ifdef CAML_INTERNALS + +#include "mlvalues.h" +#include "misc.h" + +extern intnat caml_icount; +void caml_stop_here (void); +void caml_disasm_instr (code_t pc); +void caml_trace_value_file (value v, code_t prog, asize_t proglen, FILE * f); +void caml_trace_accu_sp_file(value accu, value * sp, code_t prog, + asize_t proglen, FILE * f); + +#endif /* CAML_INTERNALS */ + +#endif diff --git a/byterun/caml/instruct.h b/runtime/caml/instruct.h similarity index 100% rename from byterun/caml/instruct.h rename to runtime/caml/instruct.h diff --git a/byterun/caml/int64_emul.h b/runtime/caml/int64_emul.h similarity index 100% rename from byterun/caml/int64_emul.h rename to runtime/caml/int64_emul.h diff --git a/byterun/caml/int64_format.h b/runtime/caml/int64_format.h similarity index 100% rename from byterun/caml/int64_format.h rename to runtime/caml/int64_format.h diff --git a/byterun/caml/int64_native.h b/runtime/caml/int64_native.h similarity index 100% rename from byterun/caml/int64_native.h rename to runtime/caml/int64_native.h diff --git a/byterun/caml/interp.h b/runtime/caml/interp.h similarity index 100% rename from byterun/caml/interp.h rename to runtime/caml/interp.h diff --git a/runtime/caml/intext.h b/runtime/caml/intext.h new file mode 100644 index 00000000..927e2497 --- /dev/null +++ b/runtime/caml/intext.h @@ -0,0 +1,213 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Structured input/output */ + +#ifndef CAML_INTEXT_H +#define CAML_INTEXT_H + +#ifndef CAML_NAME_SPACE +#include "compatibility.h" +#endif +#include "misc.h" +#include "mlvalues.h" + +#ifdef CAML_INTERNALS +#include "io.h" + +/* Magic number */ + +#define Intext_magic_number_small 0x8495A6BE +#define Intext_magic_number_big 0x8495A6BF + +/* Header format for the "small" model: 20 bytes + 0 "small" magic number + 4 length of marshaled data, in bytes + 8 number of shared blocks + 12 size in words when read on a 32-bit platform + 16 size in words when read on a 64-bit platform + The 4 numbers are 32 bits each, in big endian. + + Header format for the "big" model: 32 bytes + 0 "big" magic number + 4 four reserved bytes, currently set to 0 + 8 length of marshaled data, in bytes + 16 number of shared blocks + 24 size in words when read on a 64-bit platform + The 3 numbers are 64 bits each, in big endian. +*/ + +/* Codes for the compact format */ + +#define PREFIX_SMALL_BLOCK 0x80 +#define PREFIX_SMALL_INT 0x40 +#define PREFIX_SMALL_STRING 0x20 +#define CODE_INT8 0x0 +#define CODE_INT16 0x1 +#define CODE_INT32 0x2 +#define CODE_INT64 0x3 +#define CODE_SHARED8 0x4 +#define CODE_SHARED16 0x5 +#define CODE_SHARED32 0x6 +#define CODE_SHARED64 0x14 +#define CODE_BLOCK32 0x8 +#define CODE_BLOCK64 0x13 +#define CODE_STRING8 0x9 +#define CODE_STRING32 0xA +#define CODE_STRING64 0x15 +#define CODE_DOUBLE_BIG 0xB +#define CODE_DOUBLE_LITTLE 0xC +#define CODE_DOUBLE_ARRAY8_BIG 0xD +#define CODE_DOUBLE_ARRAY8_LITTLE 0xE +#define CODE_DOUBLE_ARRAY32_BIG 0xF +#define CODE_DOUBLE_ARRAY32_LITTLE 0x7 +#define CODE_DOUBLE_ARRAY64_BIG 0x16 +#define CODE_DOUBLE_ARRAY64_LITTLE 0x17 +#define CODE_CODEPOINTER 0x10 +#define CODE_INFIXPOINTER 0x11 +#define CODE_CUSTOM 0x12 /* deprecated */ +#define CODE_CUSTOM_LEN 0x18 +#define CODE_CUSTOM_FIXED 0x19 + +#if ARCH_FLOAT_ENDIANNESS == 0x76543210 +#define CODE_DOUBLE_NATIVE CODE_DOUBLE_BIG +#define CODE_DOUBLE_ARRAY8_NATIVE CODE_DOUBLE_ARRAY8_BIG +#define CODE_DOUBLE_ARRAY32_NATIVE CODE_DOUBLE_ARRAY32_BIG +#define CODE_DOUBLE_ARRAY64_NATIVE CODE_DOUBLE_ARRAY64_BIG +#else +#define CODE_DOUBLE_NATIVE CODE_DOUBLE_LITTLE +#define CODE_DOUBLE_ARRAY8_NATIVE CODE_DOUBLE_ARRAY8_LITTLE +#define CODE_DOUBLE_ARRAY32_NATIVE CODE_DOUBLE_ARRAY32_LITTLE +#define CODE_DOUBLE_ARRAY64_NATIVE CODE_DOUBLE_ARRAY64_LITTLE +#endif + +/* Size-ing data structures for extern. Chosen so that + sizeof(struct trail_block) and sizeof(struct output_block) + are slightly below 8Kb. */ + +#define ENTRIES_PER_TRAIL_BLOCK 1025 +#define SIZE_EXTERN_OUTPUT_BLOCK 8100 + +/* The entry points */ + +void caml_output_val (struct channel * chan, value v, value flags); + /* Output [v] with flags [flags] on the channel [chan]. */ + +#endif /* CAML_INTERNALS */ + +#ifdef __cplusplus +extern "C" { +#endif + +CAMLextern void caml_output_value_to_malloc(value v, value flags, + /*out*/ char ** buf, + /*out*/ intnat * len); + /* Output [v] with flags [flags] to a memory buffer allocated with + malloc. On return, [*buf] points to the buffer and [*len] + contains the number of bytes in buffer. */ +CAMLextern intnat caml_output_value_to_block(value v, value flags, + char * data, intnat len); + /* Output [v] with flags [flags] to a user-provided memory buffer. + [data] points to the start of this buffer, and [len] is its size + in bytes. Return the number of bytes actually written in buffer. + Raise [Failure] if buffer is too short. */ + +#ifdef CAML_INTERNALS +value caml_input_val (struct channel * chan); + /* Read a structured value from the channel [chan]. */ + +extern value caml_input_value_to_outside_heap (value channel); + /* As for [caml_input_value], but the value is unmarshalled into + malloc blocks that are not added to the heap. Not for the + casual user. */ + +extern int caml_extern_allow_out_of_heap; + /* Permit the marshaller to traverse structures that look like OCaml + values but do not live in the OCaml heap. */ + +extern value caml_output_value(value vchan, value v, value flags); +#endif /* CAML_INTERNALS */ + +CAMLextern value caml_input_val_from_string (value str, intnat ofs); + /* Read a structured value from the OCaml string [str], starting + at offset [ofs]. */ +CAMLextern value caml_input_value_from_malloc(char * data, intnat ofs); + /* Read a structured value from a malloced buffer. [data] points + to the beginning of the buffer, and [ofs] is the offset of the + beginning of the externed data in this buffer. The buffer is + deallocated with [free] on return, or if an exception is raised. */ +CAMLextern value caml_input_value_from_block(char * data, intnat len); + /* Read a structured value from a user-provided buffer. [data] points + to the beginning of the externed data in this buffer, + and [len] is the length in bytes of valid data in this buffer. + The buffer is never deallocated by this routine. */ + +/* Functions for writing user-defined marshallers */ + +CAMLextern void caml_serialize_int_1(int i); +CAMLextern void caml_serialize_int_2(int i); +CAMLextern void caml_serialize_int_4(int32_t i); +CAMLextern void caml_serialize_int_8(int64_t i); +CAMLextern void caml_serialize_float_4(float f); +CAMLextern void caml_serialize_float_8(double f); +CAMLextern void caml_serialize_block_1(void * data, intnat len); +CAMLextern void caml_serialize_block_2(void * data, intnat len); +CAMLextern void caml_serialize_block_4(void * data, intnat len); +CAMLextern void caml_serialize_block_8(void * data, intnat len); +CAMLextern void caml_serialize_block_float_8(void * data, intnat len); + +CAMLextern int caml_deserialize_uint_1(void); +CAMLextern int caml_deserialize_sint_1(void); +CAMLextern int caml_deserialize_uint_2(void); +CAMLextern int caml_deserialize_sint_2(void); +CAMLextern uint32_t caml_deserialize_uint_4(void); +CAMLextern int32_t caml_deserialize_sint_4(void); +CAMLextern uint64_t caml_deserialize_uint_8(void); +CAMLextern int64_t caml_deserialize_sint_8(void); +CAMLextern float caml_deserialize_float_4(void); +CAMLextern double caml_deserialize_float_8(void); +CAMLextern void caml_deserialize_block_1(void * data, intnat len); +CAMLextern void caml_deserialize_block_2(void * data, intnat len); +CAMLextern void caml_deserialize_block_4(void * data, intnat len); +CAMLextern void caml_deserialize_block_8(void * data, intnat len); +CAMLextern void caml_deserialize_block_float_8(void * data, intnat len); + +CAMLnoreturn_start +CAMLextern void caml_deserialize_error(char * msg) +CAMLnoreturn_end; + + +#ifdef CAML_INTERNALS + +/* Auxiliary stuff for sending code pointers */ + +struct code_fragment { + char * code_start; + char * code_end; + unsigned char digest[16]; + char digest_computed; +}; + +CAMLextern struct code_fragment * caml_extern_find_code(char *addr); + +extern struct ext_table caml_code_fragments_table; + +#endif /* CAML_INTERNALS */ + +#ifdef __cplusplus +} +#endif + +#endif /* CAML_INTEXT_H */ diff --git a/byterun/caml/io.h b/runtime/caml/io.h similarity index 100% rename from byterun/caml/io.h rename to runtime/caml/io.h diff --git a/runtime/caml/m.h.in b/runtime/caml/m.h.in new file mode 100644 index 00000000..d8e535e0 --- /dev/null +++ b/runtime/caml/m.h.in @@ -0,0 +1,104 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Machine-related configuration */ + +#undef ARCH_SIXTYFOUR + +/* Define ARCH_SIXTYFOUR if the processor has a natural word size of 64 bits. + That is, sizeof(char *) = 8. + Otherwise, leave ARCH_SIXTYFOUR undefined. + This assumes sizeof(char *) = 4. */ + +#undef ARCH_BIG_ENDIAN + +/* Define ARCH_BIG_ENDIAN if the processor is big endian (the most + significant byte of an integer stored in memory comes first). + Leave ARCH_BIG_ENDIAN undefined if the processor is little-endian + (the least significant byte comes first). +*/ + +#undef ARCH_ALIGN_DOUBLE + +/* Define ARCH_ALIGN_DOUBLE if the processor requires doubles to be + doubleword-aligned. Leave ARCH_ALIGN_DOUBLE undefined if the processor + supports word-aligned doubles. */ + +#undef HAS_ARCH_CODE32 + +/* Define HAS_ARCH_CODE32 if, on a 64-bit machine, code pointers fit + in 32 bits, i.e. the code segment resides in the low 4G of the + addressing space. + HAS_ARCH_CODE32 is ignored on 32-bit machines. */ + +#undef SIZEOF_INT +#undef SIZEOF_LONG +#undef SIZEOF_PTR +#undef SIZEOF_SHORT +#undef SIZEOF_LONGLONG + +/* Define SIZEOF_INT, SIZEOF_LONG, SIZEOF_PTR, SIZEOF_SHORT and + SIZEOF_LONGLONG to the sizes in bytes of the C types "int", "long", + "char *", "short" and "long long" respectively. */ + +#undef ARCH_INT64_TYPE +#undef ARCH_UINT64_TYPE + +/* Define ARCH_INT64_TYPE and ARCH_UINT64_TYPE to 64-bit integer types, + typically "long long" and "unsigned long long" on 32-bit platforms, + and "long" and "unsigned long" on 64-bit platforms. + If the C compiler doesn't support any 64-bit integer type, + leave both ARCH_INT64_TYPE and ARCH_UINT64_TYPE undefined. */ + +#undef ARCH_INT64_PRINTF_FORMAT + +/* Define ARCH_INT64_PRINTF_FORMAT to the printf format used for formatting + values of type ARCH_INT64_TYPE. This is usually "ll" on 32-bit + platforms and "l" on 64-bit platforms. + Leave undefined if ARCH_INT64_TYPE is undefined. */ + +#undef ARCH_ALIGN_INT64 + +/* Define ARCH_ALIGN_INT64 if the processor requires 64-bit integers to be + doubleword-aligned. Leave ARCH_ALIGN_INT64 undefined if the processor + supports word-aligned 64-bit integers. Leave undefined if + 64-bit integers are not supported. */ + +#undef PROFINFO_WIDTH + +#undef WITH_SPACETIME +#undef ENABLE_CALL_COUNTS + +#undef NONSTANDARD_DIV_MOD + +/* Leave NONSTANDARD_DIV_MOD undefined if the C operators / and % implement + round-towards-zero semantics, as specified by ISO C 9x and implemented + by most contemporary processors. Otherwise, or if you don't know, + define NONSTANDARD_DIV_MOD: this will select a slower but correct + software emulation of division and modulus. */ + +#undef ASM_CFI_SUPPORTED + +#undef WITH_FRAME_POINTERS + +#undef NO_NAKED_POINTERS + +#undef WITH_PROFINFO + +#undef CAML_WITH_FPIC + +#undef CAML_SAFE_STRING + +#undef FLAT_FLOAT_ARRAY diff --git a/byterun/caml/major_gc.h b/runtime/caml/major_gc.h similarity index 100% rename from byterun/caml/major_gc.h rename to runtime/caml/major_gc.h diff --git a/byterun/caml/md5.h b/runtime/caml/md5.h similarity index 100% rename from byterun/caml/md5.h rename to runtime/caml/md5.h diff --git a/runtime/caml/memory.h b/runtime/caml/memory.h new file mode 100644 index 00000000..5075cd0a --- /dev/null +++ b/runtime/caml/memory.h @@ -0,0 +1,596 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Allocation macros and functions */ + +#ifndef CAML_MEMORY_H +#define CAML_MEMORY_H + +#ifndef CAML_NAME_SPACE +#include "compatibility.h" +#endif +#include "config.h" +#ifdef CAML_INTERNALS +#include "gc.h" +#include "major_gc.h" +#include "minor_gc.h" +#endif /* CAML_INTERNALS */ +#include "misc.h" +#include "mlvalues.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +CAMLextern value caml_alloc_shr (mlsize_t wosize, tag_t); +#ifdef WITH_PROFINFO +CAMLextern value caml_alloc_shr_with_profinfo (mlsize_t, tag_t, intnat); +CAMLextern value caml_alloc_shr_preserving_profinfo (mlsize_t, tag_t, + header_t); +#else +#define caml_alloc_shr_with_profinfo(size, tag, profinfo) \ + caml_alloc_shr(size, tag) +#define caml_alloc_shr_preserving_profinfo(size, tag, header) \ + caml_alloc_shr(size, tag) +#endif /* WITH_PROFINFO */ +CAMLextern value caml_alloc_shr_no_raise (mlsize_t wosize, tag_t); +CAMLextern void caml_adjust_gc_speed (mlsize_t, mlsize_t); +CAMLextern void caml_alloc_dependent_memory (mlsize_t bsz); +CAMLextern void caml_free_dependent_memory (mlsize_t bsz); +CAMLextern void caml_modify (value *, value); +CAMLextern void caml_initialize (value *, value); +CAMLextern value caml_check_urgent_gc (value); +CAMLextern int caml_init_alloc_for_heap (void); +CAMLextern char *caml_alloc_for_heap (asize_t request); /* Size in bytes. */ +CAMLextern void caml_free_for_heap (char *mem); +CAMLextern void caml_disown_for_heap (char *mem); +CAMLextern int caml_add_to_heap (char *mem); +CAMLextern color_t caml_allocation_color (void *hp); + +CAMLextern int caml_huge_fallback_count; + + +/* [caml_stat_*] functions below provide an interface to the static memory + manager built into the runtime, which can be used for managing static + (that is, non-moving) blocks of heap memory. + + Function arguments that have type [caml_stat_block] must always be pointers + to blocks returned by the [caml_stat_*] functions below. Attempting to use + these functions on memory blocks allocated by a different memory manager + (e.g. the one from the C runtime) will cause undefined behaviour. +*/ +typedef void* caml_stat_block; + +#ifdef CAML_INTERNALS + +/* The pool must be initialized with a call to [caml_stat_create_pool] + before it is possible to use any of the [caml_stat_*] functions below. + + If the pool is not initialized, [caml_stat_*] functions will still work in + backward compatibility mode, becoming thin wrappers around [malloc] family + of functions. In this case, calling [caml_stat_destroy_pool] will not free + the claimed heap memory, resulting in leaks. +*/ +CAMLextern void caml_stat_create_pool(void); + +/* [caml_stat_destroy_pool] frees all the heap memory claimed by the pool. + + Once the pool is destroyed, [caml_stat_*] functions will continue to work + in backward compatibility mode, becoming thin wrappers around [malloc] + family of functions. +*/ +CAMLextern void caml_stat_destroy_pool(void); + +#endif /* CAML_INTERNALS */ + +/* [caml_stat_alloc(size)] allocates a memory block of the requested [size] + (in bytes) and returns a pointer to it. It throws an OCaml exception in case + the request fails, and so requires the runtime lock to be held. +*/ +CAMLextern caml_stat_block caml_stat_alloc(asize_t); + +/* [caml_stat_alloc_noexc(size)] allocates a memory block of the requested + [size] (in bytes) and returns a pointer to it, or NULL in case the request + fails. +*/ +CAMLextern caml_stat_block caml_stat_alloc_noexc(asize_t); + +/* [caml_stat_alloc_aligned(size, modulo, block*)] allocates a memory block of + the requested [size] (in bytes), the starting address of which is aligned to + the provided [modulo] value. The function returns the aligned address, as + well as the unaligned [block] (as an output parameter). It throws an OCaml + exception in case the request fails, and so requires the runtime lock. +*/ +CAMLextern void* caml_stat_alloc_aligned(asize_t, int modulo, caml_stat_block*); + +/* [caml_stat_alloc_aligned_noexc] is a variant of [caml_stat_alloc_aligned] + that returns NULL in case the request fails, and doesn't require the runtime + lock to be held. +*/ +CAMLextern void* caml_stat_alloc_aligned_noexc(asize_t, int modulo, + caml_stat_block*); + +/* [caml_stat_calloc_noexc(num, size)] allocates a block of memory for an array + of [num] elements, each of them [size] bytes long, and initializes all its + bits to zero, effectively allocating a zero-initialized memory block of + [num * size] bytes. It returns NULL in case the request fails. +*/ +CAMLextern caml_stat_block caml_stat_calloc_noexc(asize_t, asize_t); + +/* [caml_stat_free(block)] deallocates the provided [block]. */ +CAMLextern void caml_stat_free(caml_stat_block); + +/* [caml_stat_resize(block, size)] changes the size of the provided [block] to + [size] bytes. The function may move the memory block to a new location (whose + address is returned by the function). The content of the [block] is preserved + up to the smaller of the new and old sizes, even if the block is moved to a + new location. If the new size is larger, the value of the newly allocated + portion is indeterminate. The function throws an OCaml exception in case the + request fails, and so requires the runtime lock to be held. +*/ +CAMLextern caml_stat_block caml_stat_resize(caml_stat_block, asize_t); + +/* [caml_stat_resize_noexc] is a variant of [caml_stat_resize] that returns NULL + in case the request fails, and doesn't require the runtime lock. +*/ +CAMLextern caml_stat_block caml_stat_resize_noexc(caml_stat_block, asize_t); + + +/* A [caml_stat_block] containing a NULL-terminated string */ +typedef char* caml_stat_string; + +/* [caml_stat_strdup(s)] returns a pointer to a heap-allocated string which is a + copy of the NULL-terminated string [s]. It throws an OCaml exception in case + the request fails, and so requires the runtime lock to be held. +*/ +CAMLextern caml_stat_string caml_stat_strdup(const char *s); +#ifdef _WIN32 +CAMLextern wchar_t* caml_stat_wcsdup(const wchar_t *s); +#endif + +/* [caml_stat_strdup_noexc] is a variant of [caml_stat_strdup] that returns NULL + in case the request fails, and doesn't require the runtime lock. +*/ +CAMLextern caml_stat_string caml_stat_strdup_noexc(const char *s); + +/* [caml_stat_strconcat(nargs, strings)] concatenates NULL-terminated [strings] + (an array of [char*] of size [nargs]) into a new string, dropping all NULLs, + except for the very last one. It throws an OCaml exception in case the + request fails, and so requires the runtime lock to be held. +*/ +CAMLextern caml_stat_string caml_stat_strconcat(int n, ...); +#ifdef _WIN32 +CAMLextern wchar_t* caml_stat_wcsconcat(int n, ...); +#endif + + +/* void caml_shrink_heap (char *); Only used in compact.c */ + +#ifdef CAML_INTERNALS + +extern uintnat caml_use_huge_pages; + +#ifdef HAS_HUGE_PAGES +#include +#define Heap_page_size HUGE_PAGE_SIZE +#define Round_mmap_size(x) \ + (((x) + (Heap_page_size - 1)) & ~ (Heap_page_size - 1)) +#endif + + +int caml_page_table_add(int kind, void * start, void * end); +int caml_page_table_remove(int kind, void * start, void * end); +int caml_page_table_initialize(mlsize_t bytesize); + +#ifdef DEBUG +#define DEBUG_clear(result, wosize) do{ \ + uintnat caml__DEBUG_i; \ + for (caml__DEBUG_i = 0; caml__DEBUG_i < (wosize); ++ caml__DEBUG_i){ \ + Field ((result), caml__DEBUG_i) = Debug_uninit_minor; \ + } \ +}while(0) +#else +#define DEBUG_clear(result, wosize) +#endif + +#define Alloc_small_with_profinfo(result, wosize, tag, profinfo) do { \ + CAMLassert ((wosize) >= 1); \ + CAMLassert ((tag_t) (tag) < 256); \ + CAMLassert ((wosize) <= Max_young_wosize); \ + caml_young_ptr -= Whsize_wosize (wosize); \ + if (caml_young_ptr < caml_young_trigger){ \ + caml_young_ptr += Whsize_wosize (wosize); \ + CAML_INSTR_INT ("force_minor/alloc_small@", 1); \ + Setup_for_gc; \ + caml_gc_dispatch (); \ + Restore_after_gc; \ + caml_young_ptr -= Whsize_wosize (wosize); \ + } \ + Hd_hp (caml_young_ptr) = \ + Make_header_with_profinfo ((wosize), (tag), Caml_black, profinfo); \ + (result) = Val_hp (caml_young_ptr); \ + DEBUG_clear ((result), (wosize)); \ +}while(0) + +#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) +extern uintnat caml_spacetime_my_profinfo(struct ext_table**, uintnat); +#define Alloc_small(result, wosize, tag) \ + Alloc_small_with_profinfo(result, wosize, tag, \ + caml_spacetime_my_profinfo(NULL, wosize)) +#else +#define Alloc_small(result, wosize, tag) \ + Alloc_small_with_profinfo(result, wosize, tag, (uintnat) 0) +#endif + +/* Deprecated alias for [caml_modify] */ + +#define Modify(fp,val) caml_modify((fp), (val)) + +#endif /* CAML_INTERNALS */ + +struct caml__roots_block { + struct caml__roots_block *next; + intnat ntables; + intnat nitems; + value *tables [5]; +}; + +CAMLextern struct caml__roots_block *caml_local_roots; /* defined in roots.c */ + +/* The following macros are used to declare C local variables and + function parameters of type [value]. + + The function body must start with one of the [CAMLparam] macros. + If the function has no parameter of type [value], use [CAMLparam0]. + If the function has 1 to 5 [value] parameters, use the corresponding + [CAMLparam] with the parameters as arguments. + If the function has more than 5 [value] parameters, use [CAMLparam5] + for the first 5 parameters, and one or more calls to the [CAMLxparam] + macros for the others. + If the function takes an array of [value]s as argument, use + [CAMLparamN] to declare it (or [CAMLxparamN] if you already have a + call to [CAMLparam] for some other arguments). + + If you need local variables of type [value], declare them with one + or more calls to the [CAMLlocal] macros at the beginning of the + function, after the call to CAMLparam. Use [CAMLlocalN] (at the + beginning of the function) to declare an array of [value]s. + + Your function may raise an exception or return a [value] with the + [CAMLreturn] macro. Its argument is simply the [value] returned by + your function. Do NOT directly return a [value] with the [return] + keyword. If your function returns void, use [CAMLreturn0]. If you + un-register the local roots (i.e. undo the effects of the [CAMLparam*] + and [CAMLlocal] macros) without returning immediately, use [CAMLdrop]. + + All the identifiers beginning with "caml__" are reserved by OCaml. + Do not use them for anything (local or global variables, struct or + union tags, macros, etc.) +*/ + +#define CAMLparam0() \ + struct caml__roots_block *caml__frame = caml_local_roots + +#define CAMLparam1(x) \ + CAMLparam0 (); \ + CAMLxparam1 (x) + +#define CAMLparam2(x, y) \ + CAMLparam0 (); \ + CAMLxparam2 (x, y) + +#define CAMLparam3(x, y, z) \ + CAMLparam0 (); \ + CAMLxparam3 (x, y, z) + +#define CAMLparam4(x, y, z, t) \ + CAMLparam0 (); \ + CAMLxparam4 (x, y, z, t) + +#define CAMLparam5(x, y, z, t, u) \ + CAMLparam0 (); \ + CAMLxparam5 (x, y, z, t, u) + +#define CAMLparamN(x, size) \ + CAMLparam0 (); \ + CAMLxparamN (x, (size)) + +/* CAMLunused is preserved for compatibility reasons. + Instead of the legacy GCC/Clang-only + CAMLunused foo; + you should prefer + CAMLunused_start foo CAMLunused_end; + which supports both GCC/Clang and MSVC. +*/ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 7)) + #define CAMLunused_start __attribute__ ((unused)) + #define CAMLunused_end + #define CAMLunused __attribute__ ((unused)) +#elif _MSC_VER >= 1500 + #define CAMLunused_start __pragma( warning (push) ) \ + __pragma( warning (disable:4189 ) ) + #define CAMLunused_end __pragma( warning (pop)) + #define CAMLunused +#else + #define CAMLunused_start + #define CAMLunused_end + #define CAMLunused +#endif + +#define CAMLxparam1(x) \ + struct caml__roots_block caml__roots_##x; \ + CAMLunused_start int caml__dummy_##x = ( \ + (void) caml__frame, \ + (caml__roots_##x.next = caml_local_roots), \ + (caml_local_roots = &caml__roots_##x), \ + (caml__roots_##x.nitems = 1), \ + (caml__roots_##x.ntables = 1), \ + (caml__roots_##x.tables [0] = &x), \ + 0) \ + CAMLunused_end + +#define CAMLxparam2(x, y) \ + struct caml__roots_block caml__roots_##x; \ + CAMLunused_start int caml__dummy_##x = ( \ + (void) caml__frame, \ + (caml__roots_##x.next = caml_local_roots), \ + (caml_local_roots = &caml__roots_##x), \ + (caml__roots_##x.nitems = 1), \ + (caml__roots_##x.ntables = 2), \ + (caml__roots_##x.tables [0] = &x), \ + (caml__roots_##x.tables [1] = &y), \ + 0) \ + CAMLunused_end + +#define CAMLxparam3(x, y, z) \ + struct caml__roots_block caml__roots_##x; \ + CAMLunused_start int caml__dummy_##x = ( \ + (void) caml__frame, \ + (caml__roots_##x.next = caml_local_roots), \ + (caml_local_roots = &caml__roots_##x), \ + (caml__roots_##x.nitems = 1), \ + (caml__roots_##x.ntables = 3), \ + (caml__roots_##x.tables [0] = &x), \ + (caml__roots_##x.tables [1] = &y), \ + (caml__roots_##x.tables [2] = &z), \ + 0) \ + CAMLunused_end + +#define CAMLxparam4(x, y, z, t) \ + struct caml__roots_block caml__roots_##x; \ + CAMLunused_start int caml__dummy_##x = ( \ + (void) caml__frame, \ + (caml__roots_##x.next = caml_local_roots), \ + (caml_local_roots = &caml__roots_##x), \ + (caml__roots_##x.nitems = 1), \ + (caml__roots_##x.ntables = 4), \ + (caml__roots_##x.tables [0] = &x), \ + (caml__roots_##x.tables [1] = &y), \ + (caml__roots_##x.tables [2] = &z), \ + (caml__roots_##x.tables [3] = &t), \ + 0) \ + CAMLunused_end + +#define CAMLxparam5(x, y, z, t, u) \ + struct caml__roots_block caml__roots_##x; \ + CAMLunused_start int caml__dummy_##x = ( \ + (void) caml__frame, \ + (caml__roots_##x.next = caml_local_roots), \ + (caml_local_roots = &caml__roots_##x), \ + (caml__roots_##x.nitems = 1), \ + (caml__roots_##x.ntables = 5), \ + (caml__roots_##x.tables [0] = &x), \ + (caml__roots_##x.tables [1] = &y), \ + (caml__roots_##x.tables [2] = &z), \ + (caml__roots_##x.tables [3] = &t), \ + (caml__roots_##x.tables [4] = &u), \ + 0) \ + CAMLunused_end + +#define CAMLxparamN(x, size) \ + struct caml__roots_block caml__roots_##x; \ + CAMLunused_start int caml__dummy_##x = ( \ + (void) caml__frame, \ + (caml__roots_##x.next = caml_local_roots), \ + (caml_local_roots = &caml__roots_##x), \ + (caml__roots_##x.nitems = (size)), \ + (caml__roots_##x.ntables = 1), \ + (caml__roots_##x.tables[0] = &(x[0])), \ + 0) \ + CAMLunused_end + +#define CAMLlocal1(x) \ + value x = Val_unit; \ + CAMLxparam1 (x) + +#define CAMLlocal2(x, y) \ + value x = Val_unit, y = Val_unit; \ + CAMLxparam2 (x, y) + +#define CAMLlocal3(x, y, z) \ + value x = Val_unit, y = Val_unit, z = Val_unit; \ + CAMLxparam3 (x, y, z) + +#define CAMLlocal4(x, y, z, t) \ + value x = Val_unit, y = Val_unit, z = Val_unit, t = Val_unit; \ + CAMLxparam4 (x, y, z, t) + +#define CAMLlocal5(x, y, z, t, u) \ + value x = Val_unit, y = Val_unit, z = Val_unit, t = Val_unit, u = Val_unit; \ + CAMLxparam5 (x, y, z, t, u) + +#define CAMLlocalN(x, size) \ + value x [(size)]; \ + int caml__i_##x; \ + for (caml__i_##x = 0; caml__i_##x < size; caml__i_##x ++) { \ + x[caml__i_##x] = Val_unit; \ + } \ + CAMLxparamN (x, (size)) + + +#define CAMLdrop caml_local_roots = caml__frame + +#define CAMLreturn0 do{ \ + CAMLdrop; \ + return; \ +}while (0) + +#define CAMLreturnT(type, result) do{ \ + type caml__temp_result = (result); \ + CAMLdrop; \ + return caml__temp_result; \ +}while(0) + +#define CAMLreturn(result) CAMLreturnT(value, result) + +#define CAMLnoreturn ((void) caml__frame) + + +/* convenience macro */ +#define Store_field(block, offset, val) do{ \ + mlsize_t caml__temp_offset = (offset); \ + value caml__temp_val = (val); \ + caml_modify (&Field ((block), caml__temp_offset), caml__temp_val); \ +}while(0) + +/* + NOTE: [Begin_roots] and [End_roots] are superseded by [CAMLparam]*, + [CAMLxparam]*, [CAMLlocal]*, [CAMLreturn]. + + [Begin_roots] and [End_roots] are used for C variables that are GC roots. + It must contain all values in C local variables and function parameters + at the time the minor GC is called. + Usage: + After initialising your local variables to legal OCaml values, but before + calling allocation functions, insert [Begin_roots_n(v1, ... vn)], where + v1 ... vn are your variables of type [value] that you want to be updated + across allocations. + At the end, insert [End_roots()]. + + Note that [Begin_roots] opens a new block, and [End_roots] closes it. + Thus they must occur in matching pairs at the same brace nesting level. + + You can use [Val_unit] as a dummy initial value for your variables. +*/ + +#define Begin_root Begin_roots1 + +#define Begin_roots1(r0) { \ + struct caml__roots_block caml__roots_block; \ + caml__roots_block.next = caml_local_roots; \ + caml_local_roots = &caml__roots_block; \ + caml__roots_block.nitems = 1; \ + caml__roots_block.ntables = 1; \ + caml__roots_block.tables[0] = &(r0); + +#define Begin_roots2(r0, r1) { \ + struct caml__roots_block caml__roots_block; \ + caml__roots_block.next = caml_local_roots; \ + caml_local_roots = &caml__roots_block; \ + caml__roots_block.nitems = 1; \ + caml__roots_block.ntables = 2; \ + caml__roots_block.tables[0] = &(r0); \ + caml__roots_block.tables[1] = &(r1); + +#define Begin_roots3(r0, r1, r2) { \ + struct caml__roots_block caml__roots_block; \ + caml__roots_block.next = caml_local_roots; \ + caml_local_roots = &caml__roots_block; \ + caml__roots_block.nitems = 1; \ + caml__roots_block.ntables = 3; \ + caml__roots_block.tables[0] = &(r0); \ + caml__roots_block.tables[1] = &(r1); \ + caml__roots_block.tables[2] = &(r2); + +#define Begin_roots4(r0, r1, r2, r3) { \ + struct caml__roots_block caml__roots_block; \ + caml__roots_block.next = caml_local_roots; \ + caml_local_roots = &caml__roots_block; \ + caml__roots_block.nitems = 1; \ + caml__roots_block.ntables = 4; \ + caml__roots_block.tables[0] = &(r0); \ + caml__roots_block.tables[1] = &(r1); \ + caml__roots_block.tables[2] = &(r2); \ + caml__roots_block.tables[3] = &(r3); + +#define Begin_roots5(r0, r1, r2, r3, r4) { \ + struct caml__roots_block caml__roots_block; \ + caml__roots_block.next = caml_local_roots; \ + caml_local_roots = &caml__roots_block; \ + caml__roots_block.nitems = 1; \ + caml__roots_block.ntables = 5; \ + caml__roots_block.tables[0] = &(r0); \ + caml__roots_block.tables[1] = &(r1); \ + caml__roots_block.tables[2] = &(r2); \ + caml__roots_block.tables[3] = &(r3); \ + caml__roots_block.tables[4] = &(r4); + +#define Begin_roots_block(table, size) { \ + struct caml__roots_block caml__roots_block; \ + caml__roots_block.next = caml_local_roots; \ + caml_local_roots = &caml__roots_block; \ + caml__roots_block.nitems = (size); \ + caml__roots_block.ntables = 1; \ + caml__roots_block.tables[0] = (table); + +#define End_roots() caml_local_roots = caml__roots_block.next; } + + +/* [caml_register_global_root] registers a global C variable as a memory root + for the duration of the program, or until [caml_remove_global_root] is + called. */ + +CAMLextern void caml_register_global_root (value *); + +/* [caml_remove_global_root] removes a memory root registered on a global C + variable with [caml_register_global_root]. */ + +CAMLextern void caml_remove_global_root (value *); + +/* [caml_register_generational_global_root] registers a global C + variable as a memory root for the duration of the program, or until + [caml_remove_generational_global_root] is called. + The program guarantees that the value contained in this variable + will not be assigned directly. If the program needs to change + the value of this variable, it must do so by calling + [caml_modify_generational_global_root]. The [value *] pointer + passed to [caml_register_generational_global_root] must contain + a valid OCaml value before the call. + In return for these constraints, scanning of memory roots during + minor collection is made more efficient. */ + +CAMLextern void caml_register_generational_global_root (value *); + +/* [caml_remove_generational_global_root] removes a memory root + registered on a global C variable with + [caml_register_generational_global_root]. */ + +CAMLextern void caml_remove_generational_global_root (value *); + +/* [caml_modify_generational_global_root(r, newval)] + modifies the value contained in [r], storing [newval] inside. + In other words, the assignment [*r = newval] is performed, + but in a way that is compatible with the optimized scanning of + generational global roots. [r] must be a global memory root + previously registered with [caml_register_generational_global_root]. */ + +CAMLextern void caml_modify_generational_global_root(value *r, value newval); + +#ifdef __cplusplus +} +#endif + +#endif /* CAML_MEMORY_H */ diff --git a/runtime/caml/minor_gc.h b/runtime/caml/minor_gc.h new file mode 100644 index 00000000..92793e2d --- /dev/null +++ b/runtime/caml/minor_gc.h @@ -0,0 +1,120 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#ifndef CAML_MINOR_GC_H +#define CAML_MINOR_GC_H + + +#include "address_class.h" +#include "config.h" + +CAMLextern value *caml_young_start, *caml_young_end; +CAMLextern value *caml_young_alloc_start, *caml_young_alloc_end; +CAMLextern value *caml_young_ptr, *caml_young_limit; +CAMLextern value *caml_young_trigger; +extern asize_t caml_minor_heap_wsz; +extern int caml_in_minor_collection; +extern double caml_extra_heap_resources_minor; + +#define CAML_TABLE_STRUCT(t) { \ + t *base; \ + t *end; \ + t *threshold; \ + t *ptr; \ + t *limit; \ + asize_t size; \ + asize_t reserve; \ +} + +struct caml_ref_table CAML_TABLE_STRUCT(value *); +CAMLextern struct caml_ref_table caml_ref_table; + +struct caml_ephe_ref_elt { + value ephe; /* an ephemeron in major heap */ + mlsize_t offset; /* the offset that points in the minor heap */ +}; + +struct caml_ephe_ref_table CAML_TABLE_STRUCT(struct caml_ephe_ref_elt); +CAMLextern struct caml_ephe_ref_table caml_ephe_ref_table; + +struct caml_custom_elt { + value block; /* The finalized block in the minor heap. */ + mlsize_t mem; /* The parameters for adjusting GC speed. */ + mlsize_t max; +}; + +struct caml_custom_table CAML_TABLE_STRUCT(struct caml_custom_elt); +CAMLextern struct caml_custom_table caml_custom_table; + +extern void caml_set_minor_heap_size (asize_t); /* size in bytes */ +extern void caml_empty_minor_heap (void); +CAMLextern void caml_gc_dispatch (void); +CAMLextern void garbage_collection (void); /* runtime/signals_nat.c */ +extern void caml_realloc_ref_table (struct caml_ref_table *); +extern void caml_alloc_table (struct caml_ref_table *, asize_t, asize_t); +extern void caml_realloc_ephe_ref_table (struct caml_ephe_ref_table *); +extern void caml_alloc_ephe_table (struct caml_ephe_ref_table *, + asize_t, asize_t); +extern void caml_realloc_custom_table (struct caml_custom_table *); +extern void caml_alloc_custom_table (struct caml_custom_table *, + asize_t, asize_t); +extern void caml_oldify_one (value, value *); +extern void caml_oldify_mopup (void); + +#define Oldify(p) do{ \ + value __oldify__v__ = *p; \ + if (Is_block (__oldify__v__) && Is_young (__oldify__v__)){ \ + caml_oldify_one (__oldify__v__, (p)); \ + } \ + }while(0) + +static inline void add_to_ref_table (struct caml_ref_table *tbl, value *p) +{ + if (tbl->ptr >= tbl->limit){ + CAMLassert (tbl->ptr == tbl->limit); + caml_realloc_ref_table (tbl); + } + *tbl->ptr++ = p; +} + +static inline void add_to_ephe_ref_table (struct caml_ephe_ref_table *tbl, + value ar, mlsize_t offset) +{ + struct caml_ephe_ref_elt *ephe_ref; + if (tbl->ptr >= tbl->limit){ + CAMLassert (tbl->ptr == tbl->limit); + caml_realloc_ephe_ref_table (tbl); + } + ephe_ref = tbl->ptr++; + ephe_ref->ephe = ar; + ephe_ref->offset = offset; + CAMLassert(ephe_ref->offset < Wosize_val(ephe_ref->ephe)); +} + +static inline void add_to_custom_table (struct caml_custom_table *tbl, value v, + mlsize_t mem, mlsize_t max) +{ + struct caml_custom_elt *elt; + if (tbl->ptr >= tbl->limit){ + CAMLassert (tbl->ptr == tbl->limit); + caml_realloc_custom_table (tbl); + } + elt = tbl->ptr++; + elt->block = v; + elt->mem = mem; + elt->max = max; +} + +#endif /* CAML_MINOR_GC_H */ diff --git a/runtime/caml/misc.h b/runtime/caml/misc.h new file mode 100644 index 00000000..6aa98516 --- /dev/null +++ b/runtime/caml/misc.h @@ -0,0 +1,437 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Miscellaneous macros and variables. */ + +#ifndef CAML_MISC_H +#define CAML_MISC_H + +#ifndef CAML_NAME_SPACE +#include "compatibility.h" +#endif +#include "config.h" + +/* Standard definitions */ + +#include +#include + +/* Basic types and constants */ + +typedef size_t asize_t; + +#ifndef NULL +#define NULL 0 +#endif + +#ifdef CAML_INTERNALS +typedef char * addr; +#endif /* CAML_INTERNALS */ + +/* Noreturn is preserved for compatibility reasons. + Instead of the legacy GCC/Clang-only + foo Noreturn; + you should prefer + CAMLnoreturn_start foo CAMLnoreturn_end; + which supports both GCC/Clang and MSVC. + + Note: CAMLnoreturn is a different macro defined in memory.h, + to be used in function bodies rather than as a prototype attribute. +*/ +#ifdef __GNUC__ + /* Works only in GCC 2.5 and later */ + #define CAMLnoreturn_start + #define CAMLnoreturn_end __attribute__ ((noreturn)) + #define Noreturn __attribute__ ((noreturn)) +#elif _MSC_VER >= 1500 + #define CAMLnoreturn_start __declspec(noreturn) + #define CAMLnoreturn_end + #define Noreturn +#else + #define CAMLnoreturn_start + #define CAMLnoreturn_end + #define Noreturn +#endif + + + +/* Export control (to mark primitives and to handle Windows DLL) */ + +#define CAMLexport +#define CAMLprim +#define CAMLextern extern + +/* Weak function definitions that can be overridden by external libs */ +/* Conservatively restricted to ELF and MacOSX platforms */ +#if defined(__GNUC__) && (defined (__ELF__) || defined(__APPLE__)) +#define CAMLweakdef __attribute__((weak)) +#else +#define CAMLweakdef +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* GC timing hooks. These can be assigned by the user. + [caml_minor_gc_begin_hook] must not allocate nor change any heap value. + The others can allocate and even call back to OCaml code. +*/ +typedef void (*caml_timing_hook) (void); +extern caml_timing_hook caml_major_slice_begin_hook, caml_major_slice_end_hook; +extern caml_timing_hook caml_minor_gc_begin_hook, caml_minor_gc_end_hook; +extern caml_timing_hook caml_finalise_begin_hook, caml_finalise_end_hook; + +/* Windows Unicode support (rest below - char_os is needed earlier) */ + +#ifdef _WIN32 +typedef wchar_t char_os; +#else +typedef char char_os; +#endif + +/* Assertions */ + +#ifdef DEBUG + +#ifdef UNICODE +/* See https://msdn.microsoft.com/ja-jp/library/b0084kay(v=vs.71).aspx + It's not clear why this isn't so obviously documented, as it doesn't + seem to have been superseded by a more sensible mechanism! */ +#define CAML_WIDEN_STRING_LITERAL2(x) L##x +#define CAML_WIDEN_STRING_LITERAL(x) CAML_WIDEN_STRING_LITERAL2(x) +#define __OSFILE__ CAML_WIDEN_STRING_LITERAL(__FILE__) +#else +#define __OSFILE__ __FILE__ +#endif + +#define CAMLassert(x) \ + ((x) ? (void) 0 : caml_failed_assert ( #x , __OSFILE__, __LINE__)) +CAMLnoreturn_start +CAMLextern void caml_failed_assert (char *, char_os *, int) +CAMLnoreturn_end; +#else +#define CAMLassert(x) ((void) 0) +#endif + +CAMLnoreturn_start +CAMLextern void caml_fatal_error (char *, ...) +#ifdef __GNUC__ + __attribute__ ((format (printf, 1, 2))) +#endif +CAMLnoreturn_end; + +/* Detection of available C built-in functions, the Clang way. */ + +#ifdef __has_builtin +#define Caml_has_builtin(x) __has_builtin(x) +#else +#define Caml_has_builtin(x) 0 +#endif + +/* Integer arithmetic with overflow detection. + The functions return 0 if no overflow, 1 if overflow. + The result of the operation is always stored at [*res]. + If no overflow is reported, this is the exact result. + If overflow is reported, this is the exact result modulo 2 to the word size. +*/ + +static inline int caml_uadd_overflow(uintnat a, uintnat b, uintnat * res) +{ +#if __GNUC__ >= 5 || Caml_has_builtin(__builtin_add_overflow) + return __builtin_add_overflow(a, b, res); +#else + uintnat c = a + b; + *res = c; + return c < a; +#endif +} + +static inline int caml_usub_overflow(uintnat a, uintnat b, uintnat * res) +{ +#if __GNUC__ >= 5 || Caml_has_builtin(__builtin_sub_overflow) + return __builtin_sub_overflow(a, b, res); +#else + uintnat c = a - b; + *res = c; + return a < b; +#endif +} + +#if __GNUC__ >= 5 || Caml_has_builtin(__builtin_mul_overflow) +static inline int caml_umul_overflow(uintnat a, uintnat b, uintnat * res) +{ + return __builtin_mul_overflow(a, b, res); +} +#else +extern int caml_umul_overflow(uintnat a, uintnat b, uintnat * res); +#endif + +/* Windows Unicode support */ + +#ifdef _WIN32 + +#define _T(x) L ## x + +#define access_os _waccess +#define open_os _wopen +#define stat_os _wstati64 +#define unlink_os _wunlink +#define rename_os caml_win32_rename +#define chdir_os _wchdir +#define getcwd_os _wgetcwd +#define system_os _wsystem +#define rmdir_os _wrmdir +#define putenv_os _wputenv +#define chmod_os _wchmod +#define execv_os _wexecv +#define execve_os _wexecve +#define execvp_os _wexecvp +#define execvpe_os _wexecvpe +#define strcmp_os wcscmp +#define strlen_os wcslen +#define sscanf_os swscanf + +#define caml_stat_strdup_os caml_stat_wcsdup +#define caml_stat_strconcat_os caml_stat_wcsconcat + +#define caml_stat_strdup_to_os caml_stat_strdup_to_utf16 +#define caml_stat_strdup_of_os caml_stat_strdup_of_utf16 +#define caml_copy_string_of_os caml_copy_string_of_utf16 + +#else /* _WIN32 */ + +#define _T(x) x + +#define access_os access +#define open_os open +#define stat_os stat +#define unlink_os unlink +#define rename_os rename +#define chdir_os chdir +#define getcwd_os getcwd +#define system_os system +#define rmdir_os rmdir +#define putenv_os putenv +#define chmod_os chmod +#define execv_os execv +#define execve_os execve +#define execvp_os execvp +#define execvpe_os execvpe +#define strcmp_os strcmp +#define strlen_os strlen +#define sscanf_os sscanf + +#define caml_stat_strdup_os caml_stat_strdup +#define caml_stat_strconcat_os caml_stat_strconcat + +#define caml_stat_strdup_to_os caml_stat_strdup +#define caml_stat_strdup_of_os caml_stat_strdup +#define caml_copy_string_of_os caml_copy_string + +#endif /* _WIN32 */ + + +/* Data structures */ + +struct ext_table { + int size; + int capacity; + void ** contents; +}; + +extern void caml_ext_table_init(struct ext_table * tbl, int init_capa); +extern int caml_ext_table_add(struct ext_table * tbl, void * data); +extern void caml_ext_table_remove(struct ext_table * tbl, void * data); +extern void caml_ext_table_free(struct ext_table * tbl, int free_entries); +extern void caml_ext_table_clear(struct ext_table * tbl, int free_entries); + +CAMLextern int caml_read_directory(char_os * dirname, + struct ext_table * contents); + +/* Deprecated aliases */ +#define caml_aligned_malloc caml_stat_alloc_aligned_noexc +#define caml_strdup caml_stat_strdup +#define caml_strconcat caml_stat_strconcat + +#ifdef CAML_INTERNALS + +/* GC flags and messages */ + +extern uintnat caml_verb_gc; +void caml_gc_message (int, char *, ...) +#ifdef __GNUC__ + __attribute__ ((format (printf, 2, 3))) +#endif +; + +/* Runtime warnings */ +extern uintnat caml_runtime_warnings; +int caml_runtime_warnings_active(void); + +#ifdef DEBUG +#ifdef ARCH_SIXTYFOUR +#define Debug_tag(x) (INT64_LITERAL(0xD700D7D7D700D6D7u) \ + | ((uintnat) (x) << 16) \ + | ((uintnat) (x) << 48)) +#else +#define Debug_tag(x) (0xD700D6D7ul | ((uintnat) (x) << 16)) +#endif /* ARCH_SIXTYFOUR */ + +/* + 00 -> free words in minor heap + 01 -> fields of free list blocks in major heap + 03 -> heap chunks deallocated by heap shrinking + 04 -> fields deallocated by [caml_obj_truncate] + 10 -> uninitialised fields of minor objects + 11 -> uninitialised fields of major objects + 15 -> uninitialised words of [caml_stat_alloc_aligned] blocks + 85 -> filler bytes of [caml_stat_alloc_aligned] + 99 -> the magic prefix of a memory block allocated by [caml_stat_alloc] + + special case (byte by byte): + D7 -> uninitialised words of [caml_stat_alloc] blocks +*/ +#define Debug_free_minor Debug_tag (0x00) +#define Debug_free_major Debug_tag (0x01) +#define Debug_free_shrink Debug_tag (0x03) +#define Debug_free_truncate Debug_tag (0x04) +#define Debug_uninit_minor Debug_tag (0x10) +#define Debug_uninit_major Debug_tag (0x11) +#define Debug_uninit_align Debug_tag (0x15) +#define Debug_filler_align Debug_tag (0x85) +#define Debug_pool_magic Debug_tag (0x99) + +#define Debug_uninit_stat 0xD7 + +/* Note: the first argument is in fact a [value] but we don't have this + type available yet because we can't include [mlvalues.h] in this file. +*/ +extern void caml_set_fields (intnat v, uintnat, uintnat); +#endif /* DEBUG */ + + +/* snprintf emulation for Win32 */ + +#if defined(_WIN32) && !defined(_UCRT) +extern int caml_snprintf(char * buf, size_t size, const char * format, ...); +#define snprintf caml_snprintf +#endif + +#ifdef CAML_INSTR +/* Timers and counters for GC latency profiling (Linux-only) */ + +#include +#include + +extern intnat caml_stat_minor_collections; +extern intnat caml_instr_starttime, caml_instr_stoptime; + +struct caml_instr_block { + struct timespec ts[10]; + char *tag[10]; + int index; + struct caml_instr_block *next; +}; + +extern struct caml_instr_block *caml_instr_log; + +/* Declare a timer/counter name. [t] must be a new variable name. */ +#define CAML_INSTR_DECLARE(t) \ + struct caml_instr_block *t = NULL + +/* Allocate the data block for a given name. + [t] must have been declared with [CAML_INSTR_DECLARE]. */ +#define CAML_INSTR_ALLOC(t) do{ \ + if (caml_stat_minor_collections >= caml_instr_starttime \ + && caml_stat_minor_collections < caml_instr_stoptime){ \ + t = caml_stat_alloc_noexc (sizeof (struct caml_instr_block)); \ + t->index = 0; \ + t->tag[0] = ""; \ + t->next = caml_instr_log; \ + caml_instr_log = t; \ + } \ + }while(0) + +/* Allocate the data block and start the timer. + [t] must have been declared with [CAML_INSTR_DECLARE] + and allocated with [CAML_INSTR_ALLOC]. */ +#define CAML_INSTR_START(t, msg) do{ \ + if (t != NULL){ \ + t->tag[0] = msg; \ + clock_gettime (CLOCK_REALTIME, &(t->ts[0])); \ + } \ + }while(0) + +/* Declare a timer, allocate its data, and start it. + [t] must be a new variable name. */ +#define CAML_INSTR_SETUP(t, msg) \ + CAML_INSTR_DECLARE (t); \ + CAML_INSTR_ALLOC (t); \ + CAML_INSTR_START (t, msg) + +/* Record an intermediate time within a given timer. + [t] must have been declared, allocated, and started. */ +#define CAML_INSTR_TIME(t, msg) do{ \ + if (t != NULL){ \ + ++ t->index; \ + t->tag[t->index] = (msg); \ + clock_gettime (CLOCK_REALTIME, &(t->ts[t->index])); \ + } \ + }while(0) + +/* Record an integer data point. + If [msg] ends with # it will be interpreted as an integer-valued event. + If it ends with @ it will be interpreted as an event counter. +*/ +#define CAML_INSTR_INT(msg, data) do{ \ + CAML_INSTR_SETUP (__caml_tmp, ""); \ + if (__caml_tmp != NULL){ \ + __caml_tmp->index = 1; \ + __caml_tmp->tag[1] = msg; \ + __caml_tmp->ts[1].tv_sec = 0; \ + __caml_tmp->ts[1].tv_nsec = (data); \ + } \ + }while(0) + +/* This function is called at the start of the program to set up + the data for the above macros. +*/ +extern void caml_instr_init (void); + +/* This function is automatically called by the runtime to output + the collected data to the dump file. */ +extern void caml_instr_atexit (void); + +#else /* CAML_INSTR */ + +#define CAML_INSTR_DECLARE(t) /**/ +#define CAML_INSTR_ALLOC(t) /**/ +#define CAML_INSTR_START(t, name) /**/ +#define CAML_INSTR_SETUP(t, name) /**/ +#define CAML_INSTR_TIME(t, msg) /**/ +#define CAML_INSTR_INT(msg, c) /**/ +#define caml_instr_init() /**/ +#define caml_instr_atexit() /**/ + +#endif /* CAML_INSTR */ + +#endif /* CAML_INTERNALS */ + +#ifdef __cplusplus +} +#endif + +#endif /* CAML_MISC_H */ diff --git a/byterun/caml/mlvalues.h b/runtime/caml/mlvalues.h similarity index 100% rename from byterun/caml/mlvalues.h rename to runtime/caml/mlvalues.h diff --git a/runtime/caml/osdeps.h b/runtime/caml/osdeps.h new file mode 100644 index 00000000..d41779d3 --- /dev/null +++ b/runtime/caml/osdeps.h @@ -0,0 +1,160 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2001 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Operating system - specific stuff */ + +#ifndef CAML_OSDEPS_H +#define CAML_OSDEPS_H + +#ifdef _WIN32 +extern unsigned short caml_win32_major; +extern unsigned short caml_win32_minor; +extern unsigned short caml_win32_build; +extern unsigned short caml_win32_revision; +#endif + +#ifdef CAML_INTERNALS + +#include "misc.h" +#include "memory.h" + +/* Read at most [n] bytes from file descriptor [fd] into buffer [buf]. + [flags] indicates whether [fd] is a socket + (bit [CHANNEL_FLAG_FROM_SOCKET] is set in this case, see [io.h]). + (This distinction matters for Win32, but not for Unix.) + Return number of bytes read. + In case of error, raises [Sys_error] or [Sys_blocked_io]. */ +extern int caml_read_fd(int fd, int flags, void * buf, int n); + +/* Write at most [n] bytes from buffer [buf] onto file descriptor [fd]. + [flags] indicates whether [fd] is a socket + (bit [CHANNEL_FLAG_FROM_SOCKET] is set in this case, see [io.h]). + (This distinction matters for Win32, but not for Unix.) + Return number of bytes written. + In case of error, raises [Sys_error] or [Sys_blocked_io]. */ +extern int caml_write_fd(int fd, int flags, void * buf, int n); + +/* Decompose the given path into a list of directories, and add them + to the given table. */ +extern char_os * caml_decompose_path(struct ext_table * tbl, char_os * path); + +/* Search the given file in the given list of directories. + If not found, return a copy of [name]. */ +extern char_os * caml_search_in_path(struct ext_table * path, + const char_os * name); + +/* Same, but search an executable name in the system path for executables. */ +CAMLextern char_os * caml_search_exe_in_path(const char_os * name); + +/* Same, but search a shared library in the given path. */ +extern char_os * caml_search_dll_in_path(struct ext_table * path, + const char_os * name); + +/* Open a shared library and return a handle on it. + If [for_execution] is true, perform full symbol resolution and + execute initialization code so that functions from the shared library + can be called. If [for_execution] is false, functions from this + shared library will not be called, but just checked for presence, + so symbol resolution can be skipped. + If [global] is true, symbols from the shared library can be used + to resolve for other libraries to be opened later on. + Return [NULL] on error. */ +extern void * caml_dlopen(char_os * libname, int for_execution, int global); + +/* Close a shared library handle */ +extern void caml_dlclose(void * handle); + +/* Look up the given symbol in the given shared library. + Return [NULL] if not found, or symbol value if found. */ +extern void * caml_dlsym(void * handle, const char * name); + +extern void * caml_globalsym(const char * name); + +/* Return an error message describing the most recent dynlink failure. */ +extern char * caml_dlerror(void); + +/* Add to [contents] the (short) names of the files contained in + the directory named [dirname]. No entries are added for [.] and [..]. + Return 0 on success, -1 on error; set errno in the case of error. */ +extern int caml_read_directory(char_os * dirname, struct ext_table * contents); + +/* Recover executable name if possible (/proc/sef/exe under Linux, + GetModuleFileName under Windows). Return NULL on error, + string allocated with [caml_stat_alloc] on success. */ +extern char_os * caml_executable_name(void); + +/* Secure version of [getenv]: returns NULL if the process has special + privileges (setuid bit, setgid bit, capabilities). +*/ +extern char_os *caml_secure_getenv(char_os const *var); + +/* If [fd] refers to a terminal or console, return the number of rows + (lines) that it displays. Otherwise, or if the number of rows + cannot be determined, return -1. */ +extern int caml_num_rows_fd(int fd); + +#ifdef _WIN32 + +extern int caml_win32_rename(const wchar_t *, const wchar_t *); + +extern void caml_probe_win32_version(void); +extern void caml_setup_win32_terminal(void); +extern void caml_restore_win32_terminal(void); + +extern wchar_t *caml_win32_getenv(wchar_t const *); + +/* Windows Unicode support */ + +extern int win_multi_byte_to_wide_char(const char* s, + int slen, + wchar_t *out, + int outlen); +extern int win_wide_char_to_multi_byte(const wchar_t* s, + int slen, + char *out, + int outlen); + +/* [caml_stat_strdup_to_utf16(s)] returns a NULL-terminated copy of [s], + re-encoded in UTF-16. The encoding of [s] is assumed to be UTF-8 if + [caml_windows_unicode_runtime_enabled] is non-zero **and** [s] is valid + UTF-8, or the current Windows code page otherwise. + + The returned string is allocated with [caml_stat_alloc], so it should be free + using [caml_stat_free]. +*/ +extern wchar_t* caml_stat_strdup_to_utf16(const char *s); + +/* [caml_stat_strdup_of_utf16(s)] returns a NULL-terminated copy of [s], + re-encoded in UTF-8 if [caml_windows_unicode_runtime_enabled] is non-zero or + the current Windows code page otherwise. + + The returned string is allocated with [caml_stat_alloc], so it should be free + using [caml_stat_free]. +*/ +extern char* caml_stat_strdup_of_utf16(const wchar_t *s); + +/* [caml_copy_string_of_utf16(s)] returns an OCaml string containing a copy of + [s] re-encoded in UTF-8 if [caml_windows_unicode_runtime_enabled] is non-zero + or in the current code page otherwise. +*/ +extern value caml_copy_string_of_utf16(const wchar_t *s); + +extern int caml_win32_isatty(int fd); + +#endif /* _WIN32 */ + +#endif /* CAML_INTERNALS */ + +#endif /* CAML_OSDEPS_H */ diff --git a/byterun/caml/prims.h b/runtime/caml/prims.h similarity index 100% rename from byterun/caml/prims.h rename to runtime/caml/prims.h diff --git a/byterun/caml/printexc.h b/runtime/caml/printexc.h similarity index 100% rename from byterun/caml/printexc.h rename to runtime/caml/printexc.h diff --git a/byterun/caml/reverse.h b/runtime/caml/reverse.h similarity index 100% rename from byterun/caml/reverse.h rename to runtime/caml/reverse.h diff --git a/byterun/caml/roots.h b/runtime/caml/roots.h similarity index 100% rename from byterun/caml/roots.h rename to runtime/caml/roots.h diff --git a/runtime/caml/s.h.in b/runtime/caml/s.h.in new file mode 100644 index 00000000..70bd891f --- /dev/null +++ b/runtime/caml/s.h.in @@ -0,0 +1,279 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Operating system and standard library configuration. */ + +/* 0. Operating system type string. */ + +#undef OCAML_OS_TYPE +/* #define OCAML_OS_TYPE "Unix" */ +/* #define OCAML_OS_TYPE "Win32" */ +/* #define OCAML_OS_TYPE "MacOS" */ + +/* 1. For the runtime system. */ + +#undef POSIX_SIGNALS + +/* Define POSIX_SIGNALS if signal handling is POSIX-compliant. + In particular, sigaction(), sigprocmask() and the operations on + sigset_t are provided. */ + +#undef BSD_SIGNALS + +/* Define BSD_SIGNALS if signal handlers have the BSD semantics: the handler + remains attached to the signal when the signal is received. Leave it + undefined if signal handlers have the System V semantics: the signal + resets the behavior to default. */ + +#undef HAS_SIGSETMASK + +/* Define HAS_SIGSETMASK if you have sigsetmask(), as in BSD. */ + +#undef SUPPORT_DYNAMIC_LINKING + +/* Define SUPPORT_DYNAMIC_LINKING if dynamic loading of C stub code + via dlopen() is available. */ + +#undef HAS_C99_FLOAT_OPS + +/* Define HAS_C99_FLOAT_OPS if conforms to ISO C99. + In particular, it should provide expm1(), log1p(), hypot(), copysign(). */ + +#undef HAS_WORKING_FMA + +/* Define HAS_WORKING_FMA if the fma function is correctly implemented. The + newlib library (intentionally) just has return x * y + z. */ + +#undef HAS_GETRUSAGE + +#undef HAS_TIMES + +#undef HAS_SECURE_GETENV + +#undef HAS___SECURE_GETENV + +#undef HAS_ISSETUGID + +/* 2. For the Unix library. */ + +#undef HAS_SOCKETS + +/* Define HAS_SOCKETS if you have BSD sockets. */ + +#undef HAS_SOCKLEN_T + +/* Define HAS_SOCKLEN_T if the type socklen_t is defined in + /usr/include/sys/socket.h. */ + +#undef HAS_INET_ATON + +#undef HAS_IPV6 + +#undef HAS_STDINT_H + +#undef HAS_UNISTD + +/* Define HAS_UNISTD if you have /usr/include/unistd.h. */ + +#undef HAS_DIRENT + +/* Define HAS_DIRENT if you have /usr/include/dirent.h and the result of + readdir() is of type struct dirent *. + Otherwise, we'll load /usr/include/sys/dir.h, and readdir() is expected to + return a struct direct *. */ + +#undef HAS_REWINDDIR + +/* Define HAS_REWINDDIR if you have rewinddir(). */ + +#undef HAS_LOCKF + +/* Define HAS_LOCKF if the library provides the lockf() function. */ + +#undef HAS_MKFIFO + +/* Define HAS_MKFIFO if the library provides the mkfifo() function. */ + +#undef HAS_GETCWD + +/* Define HAS_GETCWD if the library provides the getcwd() function. */ + +#undef HAS_GETPRIORITY + +/* Define HAS_GETPRIORITY if the library provides getpriority() and + setpriority(). Otherwise, we'll use nice(). */ + +#undef HAS_UTIME +#undef HAS_UTIMES + +/* Define HAS_UTIME if you have /usr/include/utime.h and the library + provides utime(). Define HAS_UTIMES if the library provides utimes(). */ + +#undef HAS_DUP2 + +/* Define HAS_DUP2 if you have dup2(). */ + +#undef HAS_FCHMOD + +/* Define HAS_FCHMOD if you have fchmod() and fchown(). */ + +#undef HAS_TRUNCATE + +/* Define HAS_TRUNCATE if you have truncate() and + ftruncate(). */ + +#undef HAS_SELECT + +/* Define HAS_SELECT if you have select(). */ + +#undef HAS_SYS_SELECT_H + +/* Define HAS_SYS_SELECT_H if /usr/include/sys/select.h exists + and should be included before using select(). */ + +#undef HAS_NANOSLEEP +/* Define HAS_NANOSLEEP if you have nanosleep(). */ + +#undef HAS_SYMLINK + +/* Define HAS_SYMLINK if you have symlink() and readlink() and lstat(). */ + +#undef HAS_WAIT4 +#undef HAS_WAITPID + +/* Define HAS_WAIT4 if you have wait4(). + Define HAS_WAITPID if you have waitpid(). */ + +#undef HAS_GETGROUPS + +/* Define HAS_GETGROUPS if you have getgroups(). */ + +#undef HAS_SETGROUPS + +/* Define HAS_SETGROUPS if you have setgroups(). */ + +#undef HAS_INITGROUPS + +/* Define HAS_INITGROUPS if you have initgroups(). */ + +#undef HAS_TERMIOS + +/* Define HAS_TERMIOS if you have /usr/include/termios.h and it is + Posix-compliant. */ + +#undef HAS_ASYNC_IO + +/* Define HAS_ASYNC_IO if BSD-style asynchronous I/O are supported + (the process can request to be sent a SIGIO signal when a descriptor + is ready for reading). */ + +#undef HAS_SETITIMER + +/* Define HAS_SETITIMER if you have setitimer(). */ + +#undef HAS_GETHOSTNAME + +/* Define HAS_GETHOSTNAME if you have gethostname(). */ + +#undef HAS_UNAME + +/* Define HAS_UNAME if you have uname(). */ + +#undef HAS_GETTIMEOFDAY + +/* Define HAS_GETTIMEOFDAY if you have gettimeofday(). */ + +#undef HAS_MKTIME + +/* Define HAS_MKTIME if you have mktime(). */ + +#undef HAS_SETSID + +/* Define HAS_SETSID if you have setsid(). */ + +#undef HAS_PUTENV + +/* Define HAS_PUTENV if you have putenv(). */ + +#undef HAS_LOCALE_H + +/* Define HAS_LOCALE_H if you have the include file and the + uselocale() function. */ + +#undef HAS_XLOCALE_H + +/* Define HAS_XLOCALE_H if you have the include file and the + uselocale() function. */ + +#undef HAS_STRTOD_L + +/* Define HAS_STRTOD_L if you have strtod_l */ + +#undef HAS_MMAP + +/* Define HAS_MMAP if you have the include file and the + functions mmap() and munmap(). */ + +#undef HAS_PWRITE + +#undef HAS_NANOSECOND_STAT + +#undef HAS_GETHOSTBYNAME_R + +/* Define HAS_GETHOSTBYNAME_R if gethostbyname_r() is available. + The value of this symbol is the number of arguments of + gethostbyname_r(): either 5 or 6 depending on prototype. + (5 is the Solaris version, 6 is the Linux version). */ + +#undef HAS_GETHOSTBYADDR_R 8 + +/* Define HAS_GETHOSTBYADDR_R if gethostbyname_r() is available. + The value of this symbol is the number of arguments of + gethostbyaddr_r(): either 7 or 8 depending on prototype. + (7 is the Solaris version, 8 is the Linux version). */ + +#undef HAS_MKSTEMP + +#undef HAS_NICE + +/* Define HAS_NICE if you have nice(). */ + +#undef HAS_DUP3 + +#undef HAS_PIPE2 + +#undef HAS_ACCEPT4 + +#undef HAS_GETAUXVAL + +#undef HAS_SYS_SHM_H + +#undef HAS_EXECVPE + +#undef HAS_STACK_OVERFLOW_DETECTION + +#undef HAS_SIGWAIT + +#undef HAS_LIBBFD + +#undef HAS_HUGE_PAGES + +#undef HUGE_PAGE_SIZE + +#undef HAS_LIBUNWIND + +#undef HAS_BROKEN_PRINTF + +#undef HAS_STRERROR diff --git a/runtime/caml/signals.h b/runtime/caml/signals.h new file mode 100644 index 00000000..46e65dd2 --- /dev/null +++ b/runtime/caml/signals.h @@ -0,0 +1,66 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#ifndef CAML_SIGNALS_H +#define CAML_SIGNALS_H + +#if defined(CAML_INTERNALS) && defined(POSIX_SIGNALS) +#include +#endif + +#ifndef CAML_NAME_SPACE +#include "compatibility.h" +#endif +#include "misc.h" +#include "mlvalues.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CAML_INTERNALS +CAMLextern intnat volatile caml_signals_are_pending; +CAMLextern intnat volatile caml_pending_signals[]; +CAMLextern int volatile caml_something_to_do; +extern int volatile caml_requested_major_slice; +extern int volatile caml_requested_minor_gc; + +void caml_request_major_slice (void); +void caml_request_minor_gc (void); +CAMLextern int caml_convert_signal_number (int); +CAMLextern int caml_rev_convert_signal_number (int); +void caml_execute_signal(int signal_number, int in_signal_handler); +void caml_record_signal(int signal_number); +void caml_process_pending_signals(void); +void caml_process_event(void); +int caml_set_signal_action(int signo, int action); + +CAMLextern void (*caml_enter_blocking_section_hook)(void); +CAMLextern void (*caml_leave_blocking_section_hook)(void); +CAMLextern int (*caml_try_leave_blocking_section_hook)(void); +CAMLextern void (* volatile caml_async_action_hook)(void); +#ifdef POSIX_SIGNALS +CAMLextern int (*caml_sigmask_hook)(int, const sigset_t *, sigset_t *); +#endif +#endif /* CAML_INTERNALS */ + +CAMLextern void caml_enter_blocking_section (void); +CAMLextern void caml_leave_blocking_section (void); + +#ifdef __cplusplus +} +#endif + +#endif /* CAML_SIGNALS_H */ diff --git a/byterun/caml/signals_machdep.h b/runtime/caml/signals_machdep.h similarity index 100% rename from byterun/caml/signals_machdep.h rename to runtime/caml/signals_machdep.h diff --git a/byterun/caml/spacetime.h b/runtime/caml/spacetime.h similarity index 100% rename from byterun/caml/spacetime.h rename to runtime/caml/spacetime.h diff --git a/runtime/caml/stack.h b/runtime/caml/stack.h new file mode 100644 index 00000000..0c4aab15 --- /dev/null +++ b/runtime/caml/stack.h @@ -0,0 +1,124 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Machine-dependent interface with the asm code */ + +#ifndef CAML_STACK_H +#define CAML_STACK_H + +#ifdef CAML_INTERNALS + +/* Macros to access the stack frame */ + +#ifdef TARGET_i386 +#define Saved_return_address(sp) *((intnat *)((sp) - 4)) +#ifndef SYS_win32 +#define Callback_link(sp) ((struct caml_context *)((sp) + 16)) +#else +#define Callback_link(sp) ((struct caml_context *)((sp) + 8)) +#endif +#endif + +#ifdef TARGET_power +#if defined(MODEL_ppc) +#define Saved_return_address(sp) *((intnat *)((sp) - 4)) +#define Callback_link(sp) ((struct caml_context *)((sp) + 16)) +#elif defined(MODEL_ppc64) +#define Saved_return_address(sp) *((intnat *)((sp) + 16)) +#define Callback_link(sp) ((struct caml_context *)((sp) + (48 + 32))) +#elif defined(MODEL_ppc64le) +#define Saved_return_address(sp) *((intnat *)((sp) + 16)) +#define Callback_link(sp) ((struct caml_context *)((sp) + (32 + 32))) +#else +#error "TARGET_power: wrong MODEL" +#endif +#define Already_scanned(sp, retaddr) ((retaddr) & 1) +#define Mask_already_scanned(retaddr) ((retaddr) & ~1) +#define Mark_scanned(sp, retaddr) Saved_return_address(sp) = (retaddr) | 1 +#endif + +#ifdef TARGET_s390x +#define Saved_return_address(sp) *((intnat *)((sp) - SIZEOF_PTR)) +#define Trap_frame_size 16 +#define Callback_link(sp) ((struct caml_context *)((sp) + Trap_frame_size)) +#endif + +#ifdef TARGET_arm +#define Saved_return_address(sp) *((intnat *)((sp) - 4)) +#define Callback_link(sp) ((struct caml_context *)((sp) + 8)) +#endif + +#ifdef TARGET_amd64 +#define Saved_return_address(sp) *((intnat *)((sp) - 8)) +#define Callback_link(sp) ((struct caml_context *)((sp) + 16)) +#endif + +#ifdef TARGET_arm64 +#define Saved_return_address(sp) *((intnat *)((sp) - 8)) +#define Callback_link(sp) ((struct caml_context *)((sp) + 16)) +#endif + +/* Structure of OCaml callback contexts */ + +struct caml_context { + char * bottom_of_stack; /* beginning of OCaml stack chunk */ + uintnat last_retaddr; /* last return address in OCaml code */ + value * gc_regs; /* pointer to register block */ +#ifdef WITH_SPACETIME + void* trie_node; +#endif +}; + +/* Structure of frame descriptors */ + +typedef struct { + uintnat retaddr; + unsigned short frame_size; + unsigned short num_live; + unsigned short live_ofs[1]; +} frame_descr; + +/* Hash table of frame descriptors */ + +extern frame_descr ** caml_frame_descriptors; +extern uintnat caml_frame_descriptors_mask; + +#define Hash_retaddr(addr) \ + (((uintnat)(addr) >> 3) & caml_frame_descriptors_mask) + +extern void caml_init_frame_descriptors(void); +extern void caml_register_frametable(intnat *); +extern void caml_unregister_frametable(intnat *); +extern void caml_register_dyn_global(void *); + +extern uintnat caml_stack_usage (void); +extern uintnat (*caml_stack_usage_hook)(void); + +/* Declaration of variables used in the asm code */ +extern char * caml_top_of_stack; +extern char * caml_bottom_of_stack; +extern uintnat caml_last_return_address; +extern value * caml_gc_regs; +extern char * caml_exception_pointer; +extern value * caml_globals[]; +extern char caml_globals_map[]; +extern intnat caml_globals_inited; +extern intnat * caml_frametable[]; + +CAMLextern frame_descr * caml_next_frame_descriptor(uintnat * pc, char ** sp); + +#endif /* CAML_INTERNALS */ + +#endif /* CAML_STACK_H */ diff --git a/byterun/caml/stacks.h b/runtime/caml/stacks.h similarity index 100% rename from byterun/caml/stacks.h rename to runtime/caml/stacks.h diff --git a/runtime/caml/startup.h b/runtime/caml/startup.h new file mode 100644 index 00000000..a069a457 --- /dev/null +++ b/runtime/caml/startup.h @@ -0,0 +1,52 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2001 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#ifndef CAML_STARTUP_H +#define CAML_STARTUP_H + +#ifdef CAML_INTERNALS + +#include "mlvalues.h" +#include "exec.h" + +CAMLextern void caml_main(char_os **argv); + +CAMLextern void caml_startup_code( + code_t code, asize_t code_size, + char *data, asize_t data_size, + char *section_table, asize_t section_table_size, + int pooling, + char_os **argv); + +CAMLextern value caml_startup_code_exn( + code_t code, asize_t code_size, + char *data, asize_t data_size, + char *section_table, asize_t section_table_size, + int pooling, + char_os **argv); + +enum { FILE_NOT_FOUND = -1, BAD_BYTECODE = -2, WRONG_MAGIC = -3 }; + +extern int caml_attempt_open(char_os **name, struct exec_trailer *trail, + int do_open_script); +extern void caml_read_section_descriptors(int fd, struct exec_trailer *trail); +extern int32_t caml_seek_optional_section(int fd, struct exec_trailer *trail, + char *name); +extern int32_t caml_seek_section(int fd, struct exec_trailer *trail, + char *name); + +#endif /* CAML_INTERNALS */ + +#endif /* CAML_STARTUP_H */ diff --git a/runtime/caml/startup_aux.h b/runtime/caml/startup_aux.h new file mode 100644 index 00000000..77ced69f --- /dev/null +++ b/runtime/caml/startup_aux.h @@ -0,0 +1,50 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, Jane Street Group, LLC */ +/* */ +/* Copyright 2015 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#ifndef CAML_STARTUP_AUX_H +#define CAML_STARTUP_AUX_H + +#ifdef CAML_INTERNALS + +#include "config.h" + +extern void caml_init_locale(void); +extern void caml_free_locale(void); + +extern void caml_init_atom_table (void); + +extern uintnat caml_init_percent_free; +extern uintnat caml_init_max_percent_free; +extern uintnat caml_init_minor_heap_wsz; +extern uintnat caml_init_heap_chunk_sz; +extern uintnat caml_init_heap_wsz; +extern uintnat caml_init_max_stack_wsz; +extern uintnat caml_init_major_window; +extern uintnat caml_init_custom_major_ratio; +extern uintnat caml_init_custom_minor_ratio; +extern uintnat caml_init_custom_minor_max_bsz; +extern uintnat caml_trace_level; +extern int caml_cleanup_on_exit; + +extern void caml_parse_ocamlrunparam (void); + +/* Common entry point to caml_startup. + Returns 0 if the runtime is already initialized. + If [pooling] is 0, [caml_stat_*] functions will not be backed by a pool. */ +extern int caml_startup_aux (int pooling); + +#endif /* CAML_INTERNALS */ + +#endif /* CAML_STARTUP_AUX_H */ diff --git a/runtime/caml/sys.h b/runtime/caml/sys.h new file mode 100644 index 00000000..39e24c57 --- /dev/null +++ b/runtime/caml/sys.h @@ -0,0 +1,55 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#ifndef CAML_SYS_H +#define CAML_SYS_H + +#ifdef CAML_INTERNALS + +#include "misc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NO_ARG Val_int(0) + +CAMLnoreturn_start +CAMLextern void caml_sys_error (value) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_sys_io_error (value) +CAMLnoreturn_end; + +CAMLextern double caml_sys_time_unboxed(value); +CAMLextern void caml_sys_init (char_os * exe_name, char_os ** argv); + +CAMLnoreturn_start +CAMLextern value caml_sys_exit (value) +CAMLnoreturn_end; + +extern double caml_sys_time_unboxed(value); +CAMLextern value caml_sys_get_argv(value unit); + +extern char_os * caml_exe_name; + +#ifdef __cplusplus +} +#endif + +#endif /* CAML_INTERNALS */ + +#endif /* CAML_SYS_H */ diff --git a/byterun/caml/ui.h b/runtime/caml/ui.h similarity index 100% rename from byterun/caml/ui.h rename to runtime/caml/ui.h diff --git a/runtime/caml/weak.h b/runtime/caml/weak.h new file mode 100644 index 00000000..ab514fdb --- /dev/null +++ b/runtime/caml/weak.h @@ -0,0 +1,216 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1997 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Operations on weak arrays */ + +#ifndef CAML_WEAK_H +#define CAML_WEAK_H + +#include "mlvalues.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** The requirements of the functions must be satisfied, it is + unspecified what happens if they are not. The debugging runtime + could check some of them. */ + +CAMLextern value caml_ephemeron_create(mlsize_t len); +/** Create an ephemeron with the given number of keys. + This function allocates. + */ + +CAMLextern mlsize_t caml_ephemeron_num_keys(value eph); +/** Return the number of key in the ephemeron. The valid key offset goes + from [0] to the predecessor of the returned value. */ + +CAMLextern int caml_ephemeron_key_is_set(value eph, mlsize_t offset); +/** Return 1 if the key in the ephemeron at the given offset is set. + Otherwise 0. The value [eph] must be an ephemeron and [offset] a + valid key offset. +*/ + +CAMLextern void caml_ephemeron_set_key(value eph, mlsize_t offset, value k); +/** Set the key of the given ephemeron [eph] at the given offset + [offset] to the given value [k]. The value [eph] must be an + ephemeron, [offset] a valid key offset and [k] a block. +*/ + +CAMLextern void caml_ephemeron_unset_key(value eph, mlsize_t offset); +/** Unset the key of the given ephemeron at the given offset. The + value [eph] must be an ephemeron and [offset] a valid key offset. +*/ + +CAMLextern int caml_ephemeron_get_key(value eph, mlsize_t offset, value *key); +/** Return 1 if the key in the ephemeron at the given offset is set. + Otherwise 0. When returning 1, set [*key] to the pointed value. + + The value [eph] must be an ephemeron and [offset] a valid key + offset. +*/ + +CAMLextern int caml_ephemeron_get_key_copy(value eph, mlsize_t offset, + value *key); +/** Return 1 if the key in the ephemeron at the given offset is set. + Otherwise 0. When returning 1, set [*key] to a shallow copy of the + key. This function allocates. + + The value [eph] must be an ephemeron and [offset] a valid key + offset. +*/ + +CAMLextern void caml_ephemeron_blit_key(value eph1, mlsize_t off1, + value eph2, mlsize_t off2, + mlsize_t len); +/** Fill the given range of keys of [eph2] with the given range of + keys of [eph1]. Contrary to using caml_ephemeron_get_key followed + by caml_ephemeron_set_key or caml_ephemeron_unset_key, this + function does not prevent the incremental GC from erasing the + value in its current cycle. The value [eph1] (resp. [eph2]) must + be an ephemeron and the offsets between [off1] and [off1+len] + (resp. between [off2] and [off2+offset]) must be valid keys of + [eph1] (resp. [eph2]). +*/ + +CAMLextern int caml_ephemeron_data_is_set(value eph); +/** Return 1 if the data in the ephemeron is set. + Otherwise 0. The value [eph] must be an ephemeron. +*/ + +CAMLextern void caml_ephemeron_set_data(value eph, value k); +/** Set the data of the given ephemeron [eph] to the given value + [k]. The value [eph] must be an ephemeron and [k] a block. +*/ + +CAMLextern void caml_ephemeron_unset_data(value eph); +/** Unset the data of the given ephemeron. The value [eph] must be an + ephemeron. +*/ + +CAMLextern int caml_ephemeron_get_data(value eph, value *data); +/** Return 1 if the data in the ephemeron at the given offset is set. + Otherwise 0. When returning 1, set [*data] to the pointed value. + + The value [eph] must be an ephemeron and [offset] a valid key + offset. +*/ + +CAMLextern int caml_ephemeron_get_data_copy(value eph, value *data); +/** Return 1 if the data in the ephemeron at the given offset is set. + Otherwise 0. When returning 1, set [*data] to a shallow copy of + the data. This function allocates. + + The value [eph] must be an ephemeron and [offset] a valid key + offset. +*/ + +CAMLextern void caml_ephemeron_blit_data(value eph1, value eph2); +/** Sets the data of [eph2] to be the same as the data of [eph1]. + Contrary to using caml_ephemeron_get_data followed by + caml_ephemeron_set_data or caml_ephemeron_unset_data, this + function does not prevent the incremental GC from erasing the + value in its current cycle. The values [eph1] and [eph2] must be + ephemerons. +*/ + + +#define caml_weak_array_length caml_ephemeron_num_keys +#define caml_weak_array_create caml_ephemeron_create +#define caml_weak_array_check caml_ephemeron_key_is_set +#define caml_weak_array_unset caml_ephemeron_unset_key +#define caml_weak_array_set caml_ephemeron_set_key +#define caml_weak_array_get caml_ephemeron_get_key +#define caml_weak_array_get_copy caml_ephemeron_get_key_copy +#define caml_weak_array_blit caml_ephemeron_blit_key + +#ifdef CAML_INTERNALS + +extern value caml_ephe_list_head; +extern value caml_ephe_none; + + +/** The first field 0: weak list; + second field 1: data; + others 2..: keys; + + A weak pointer is an ephemeron with the data at caml_ephe_none + If fields are added, don't forget to update weak.ml, [additional_values], + and obj.ml, [Ephemeron.additional_values]. + + + */ + +#define CAML_EPHE_LINK_OFFSET 0 +#define CAML_EPHE_DATA_OFFSET 1 +#define CAML_EPHE_FIRST_KEY 2 +#define CAML_EPHE_MAX_WOSIZE (Max_wosize - CAML_EPHE_FIRST_KEY) + +/* In the header, in order to let major_gc.c + and weak.c see the body of the function */ +static inline void caml_ephe_clean (value v){ + value child; + int release_data = 0; + mlsize_t size, i; + header_t hd; + CAMLassert(caml_gc_phase == Phase_clean); + + hd = Hd_val (v); + size = Wosize_hd (hd); + for (i = 2; i < size; i++){ + child = Field (v, i); + ephemeron_again: + if (child != caml_ephe_none + && Is_block (child) && Is_in_heap_or_young (child)){ + if (Tag_val (child) == Forward_tag){ + value f = Forward_val (child); + if (Is_block (f)) { + if (!Is_in_value_area(f) || Tag_val (f) == Forward_tag + || Tag_val (f) == Lazy_tag || Tag_val (f) == Double_tag){ + /* Do not short-circuit the pointer. */ + }else{ + Field (v, i) = child = f; + if (Is_block (f) && Is_young (f)) + add_to_ephe_ref_table(&caml_ephe_ref_table, v, i); + goto ephemeron_again; + } + } + } + if (Is_white_val (child) && !Is_young (child)){ + release_data = 1; + Field (v, i) = caml_ephe_none; + } + } + } + + child = Field (v, 1); + if(child != caml_ephe_none){ + if (release_data){ + Field (v, 1) = caml_ephe_none; + } else { + /* The mark phase must have marked it */ + CAMLassert( !(Is_block (child) && Is_in_heap (child) + && Is_white_val (child)) ); + } + } +} + +#endif /* CAML_INTERNALS */ + +#ifdef __cplusplus +} +#endif + +#endif /* CAML_WEAK_H */ diff --git a/runtime/clambda_checks.c b/runtime/clambda_checks.c new file mode 100644 index 00000000..b2b33d14 --- /dev/null +++ b/runtime/clambda_checks.c @@ -0,0 +1,88 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Pierre Chambart, OCamlPro */ +/* Mark Shinwell, Jane Street Europe */ +/* */ +/* Copyright 2013--2016 OCamlPro SAS */ +/* Copyright 2014--2016 Jane Street Group LLC */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Runtime checks to try to catch errors in code generation. + See flambda_to_clambda.ml for more information. */ + +#include + +#include "caml/mlvalues.h" + +value caml_check_value_is_closure(value v, value v_descr) +{ + const char* descr = String_val(v_descr); + value orig_v = v; + + if (v == (value) 0) { + fprintf(stderr, "NULL is not a closure: %s\n", + descr); + abort(); + } + if (!Is_block(v)) { + fprintf(stderr, + "Expecting a closure, got a non-boxed value %p: %s\n", + (void*) v, descr); + abort(); + } + if (!(Tag_val(v) == Closure_tag || Tag_val(v) == Infix_tag)) { + fprintf(stderr, + "Expecting a closure, got a boxed value with tag %i: %s\n", + Tag_val(v), descr); + abort(); + } + if (Tag_val(v) == Infix_tag) { + v -= Infix_offset_val(v); + CAMLassert(Tag_val(v) == Closure_tag); + } + CAMLassert(Wosize_val(v) >= 2); + + return orig_v; +} + +value caml_check_field_access(value v, value pos, value v_descr) +{ + const char* descr = String_val(v_descr); + value orig_v = v; + if (v == (value) 0) { + fprintf(stderr, + "Access to field %" ARCH_INT64_PRINTF_FORMAT + "u of NULL: %s\n", (ARCH_UINT64_TYPE) Long_val(pos), descr); + abort(); + } + if (!Is_block(v)) { + fprintf(stderr, + "Access to field %" ARCH_INT64_PRINTF_FORMAT + "u of non-boxed value %p is illegal: %s\n", + (ARCH_UINT64_TYPE) Long_val(pos), (void*) v, descr); + abort(); + } + if (Tag_val(v) == Infix_tag) { + uintnat offset = Infix_offset_val(v); + v -= offset; + pos += offset / sizeof(value); + } + CAMLassert(Long_val(pos) >= 0); + if (Long_val(pos) >= Wosize_val(v)) { + fprintf(stderr, + "Access to field %" ARCH_INT64_PRINTF_FORMAT + "u of value %p of size %" ARCH_INT64_PRINTF_FORMAT "u is illegal: %s\n", + (ARCH_UINT64_TYPE) Long_val(pos), (void*) v, + (ARCH_UINT64_TYPE) Wosize_val(v), + descr); + abort(); + } + return orig_v; +} diff --git a/runtime/compact.c b/runtime/compact.c new file mode 100644 index 00000000..0f40035a --- /dev/null +++ b/runtime/compact.c @@ -0,0 +1,564 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +#include + +#include "caml/address_class.h" +#include "caml/config.h" +#include "caml/finalise.h" +#include "caml/freelist.h" +#include "caml/gc.h" +#include "caml/gc_ctrl.h" +#include "caml/major_gc.h" +#include "caml/memory.h" +#include "caml/mlvalues.h" +#include "caml/roots.h" +#include "caml/weak.h" +#include "caml/compact.h" + +extern uintnat caml_percent_free; /* major_gc.c */ +extern void caml_shrink_heap (char *); /* memory.c */ + +/* Encoded headers: the color is stored in the 2 least significant bits. + (For pointer inversion, we need to distinguish headers from pointers.) + s is a Wosize, t is a tag, and c is a color (a two-bit number) + + For the purpose of compaction, "colors" are: + 0: pointers (direct or inverted) + 1: integer or (unencoded) infix header + 2: inverted pointer for infix header + 3: integer or encoded (noninfix) header + + XXX Should be fixed: + XXX The above assumes that all roots are aligned on a 4-byte boundary, + XXX which is not always guaranteed by C. + XXX (see [caml_register_global_roots]) + XXX Should be able to fix it to only assume 2-byte alignment. +*/ +#ifdef WITH_PROFINFO +#define Make_ehd(s,t,c,p) \ + (((s) << 10) | (t) << 2 | (c) | ((p) << PROFINFO_SHIFT)) +#else +#define Make_ehd(s,t,c,p) (((s) << 10) | (t) << 2 | (c)) +#endif +#define Whsize_ehd(h) Whsize_hd (h) +#define Wosize_ehd(h) Wosize_hd (h) +#define Tag_ehd(h) (((h) >> 2) & 0xFF) +#ifdef WITH_PROFINFO +#define Profinfo_ehd(hd) Profinfo_hd(hd) +#endif +#define Ecolor(w) ((w) & 3) + +typedef uintnat word; + +static void invert_pointer_at (word *p) +{ + word q = *p; + CAMLassert (Ecolor ((intnat) p) == 0); + + /* Use Ecolor (q) == 0 instead of Is_block (q) because q could be an + inverted pointer for an infix header (with Ecolor == 2). */ + if (Ecolor (q) == 0 && Is_in_heap (q)){ + switch (Ecolor (Hd_val (q))){ + case 0: + case 3: /* Pointer or header: insert in inverted list. */ + *p = Hd_val (q); + Hd_val (q) = (header_t) p; + break; + case 1: /* Infix header: make inverted infix list. */ + /* Double inversion: the last of the inverted infix list points to + the next infix header in this block. The last of the last list + contains the original block header. */ + { + /* This block as a value. */ + value val = (value) q - Infix_offset_val (q); + /* Get the block header. */ + word *hp = (word *) Hp_val (val); + + while (Ecolor (*hp) == 0) hp = (word *) *hp; + CAMLassert (Ecolor (*hp) == 3); + if (Tag_ehd (*hp) == Closure_tag){ + /* This is the first infix found in this block. */ + /* Save original header. */ + *p = *hp; + /* Link inverted infix list. */ + Hd_val (q) = (header_t) ((word) p | 2); + /* Change block header's tag to Infix_tag, and change its size + to point to the infix list. */ + *hp = Make_ehd (Wosize_bhsize (q - val), Infix_tag, 3, (uintnat) 0); + }else{ + CAMLassert (Tag_ehd (*hp) == Infix_tag); + /* Point the last of this infix list to the current first infix + list of the block. */ + *p = (word) &Field (val, Wosize_ehd (*hp)) | 1; + /* Point the head of this infix list to the above. */ + Hd_val (q) = (header_t) ((word) p | 2); + /* Change block header's size to point to this infix list. */ + *hp = Make_ehd (Wosize_bhsize (q - val), Infix_tag, 3, (uintnat) 0); + } + } + break; + case 2: /* Inverted infix list: insert. */ + *p = Hd_val (q); + Hd_val (q) = (header_t) ((word) p | 2); + break; + } + } +} + +void caml_invert_root (value v, value *p) +{ + invert_pointer_at ((word *) p); +} + +static char *compact_fl; + +static void init_compact_allocate (void) +{ + char *ch = caml_heap_start; + while (ch != NULL){ + Chunk_alloc (ch) = 0; + ch = Chunk_next (ch); + } + compact_fl = caml_heap_start; +} + +/* [size] is a number of bytes and includes the header size */ +static char *compact_allocate (mlsize_t size) +{ + char *chunk, *adr; + + while (Chunk_size (compact_fl) - Chunk_alloc (compact_fl) <= Bhsize_wosize (3) + && Chunk_size (Chunk_next (compact_fl)) + - Chunk_alloc (Chunk_next (compact_fl)) + <= Bhsize_wosize (3)){ + compact_fl = Chunk_next (compact_fl); + } + chunk = compact_fl; + while (Chunk_size (chunk) - Chunk_alloc (chunk) < size){ + chunk = Chunk_next (chunk); + CAMLassert (chunk != NULL); + } + adr = chunk + Chunk_alloc (chunk); + Chunk_alloc (chunk) += size; + return adr; +} + +static void do_compaction (void) +{ + char *ch, *chend; + CAMLassert (caml_gc_phase == Phase_idle); + caml_gc_message (0x10, "Compacting heap...\n"); + +#ifdef DEBUG + caml_heap_check (); +#endif + + /* First pass: encode all noninfix headers. */ + { + ch = caml_heap_start; + while (ch != NULL){ + header_t *p = (header_t *) ch; + + chend = ch + Chunk_size (ch); + while ((char *) p < chend){ + header_t hd = Hd_hp (p); + mlsize_t sz = Wosize_hd (hd); + + if (Is_blue_hd (hd)){ + /* Free object. Give it a string tag. */ + Hd_hp (p) = Make_ehd (sz, String_tag, 3, (uintnat) 0); + }else{ + CAMLassert (Is_white_hd (hd)); + /* Live object. Keep its tag. */ + Hd_hp (p) = Make_ehd (sz, Tag_hd (hd), 3, Profinfo_hd (hd)); + } + p += Whsize_wosize (sz); + } + ch = Chunk_next (ch); + } + } + + + /* Second pass: invert pointers. + Link infix headers in each block in an inverted list of inverted lists. + Don't forget roots and weak pointers. */ + { + /* Invert roots first because the threads library needs some heap + data structures to find its roots. Fortunately, it doesn't need + the headers (see above). */ + caml_do_roots (caml_invert_root, 1); + /* The values to be finalised are not roots but should still be inverted */ + caml_final_invert_finalisable_values (); + + ch = caml_heap_start; + while (ch != NULL){ + word *p = (word *) ch; + chend = ch + Chunk_size (ch); + + while ((char *) p < chend){ + word q = *p; + size_t sz, i; + tag_t t; + word *infixes; + + while (Ecolor (q) == 0) q = * (word *) q; + sz = Whsize_ehd (q); + t = Tag_ehd (q); + + if (t == Infix_tag){ + /* Get the original header of this block. */ + infixes = p + sz; + q = *infixes; + while (Ecolor (q) != 3) q = * (word *) (q & ~(uintnat)3); + sz = Whsize_ehd (q); + t = Tag_ehd (q); + } + + if (t < No_scan_tag){ + for (i = 1; i < sz; i++) invert_pointer_at (&(p[i])); + } + p += sz; + } + ch = Chunk_next (ch); + } + /* Invert weak pointers. */ + { + value *pp = &caml_ephe_list_head; + value p; + word q; + size_t sz, i; + + while (1){ + p = *pp; + if (p == (value) NULL) break; + q = Hd_val (p); + while (Ecolor (q) == 0) q = * (word *) q; + sz = Wosize_ehd (q); + for (i = 1; i < sz; i++){ + if (Field (p,i) != caml_ephe_none){ + invert_pointer_at ((word *) &(Field (p,i))); + } + } + invert_pointer_at ((word *) pp); + pp = &Field (p, 0); + } + } + } + + + /* Third pass: reallocate virtually; revert pointers; decode headers. + Rebuild infix headers. */ + { + init_compact_allocate (); + ch = caml_heap_start; + while (ch != NULL){ + word *p = (word *) ch; + + chend = ch + Chunk_size (ch); + while ((char *) p < chend){ + word q = *p; + + if (Ecolor (q) == 0 || Tag_ehd (q) == Infix_tag){ + /* There were (normal or infix) pointers to this block. */ + size_t sz; + tag_t t; + char *newadr; +#ifdef WITH_PROFINFO + uintnat profinfo; +#endif + word *infixes = NULL; + + while (Ecolor (q) == 0) q = * (word *) q; + sz = Whsize_ehd (q); + t = Tag_ehd (q); +#ifdef WITH_PROFINFO + profinfo = Profinfo_ehd (q); +#endif + if (t == Infix_tag){ + /* Get the original header of this block. */ + infixes = p + sz; + q = *infixes; + CAMLassert (Ecolor (q) == 2); + while (Ecolor (q) != 3) q = * (word *) (q & ~(uintnat)3); + sz = Whsize_ehd (q); + t = Tag_ehd (q); + } + + newadr = compact_allocate (Bsize_wsize (sz)); + q = *p; + while (Ecolor (q) == 0){ + word next = * (word *) q; + * (word *) q = (word) Val_hp (newadr); + q = next; + } + *p = Make_header_with_profinfo (Wosize_whsize (sz), t, Caml_white, + profinfo); + + if (infixes != NULL){ + /* Rebuild the infix headers and revert the infix pointers. */ + while (Ecolor ((word) infixes) != 3){ + infixes = (word *) ((word) infixes & ~(uintnat) 3); + q = *infixes; + while (Ecolor (q) == 2){ + word next; + q = (word) q & ~(uintnat) 3; + next = * (word *) q; + * (word *) q = (word) Val_hp ((word *) newadr + (infixes - p)); + q = next; + } + CAMLassert (Ecolor (q) == 1 || Ecolor (q) == 3); + /* No need to preserve any profinfo value on the [Infix_tag] + headers; the Spacetime profiling heap snapshot code doesn't + look at them. */ + *infixes = Make_header (infixes - p, Infix_tag, Caml_white); + infixes = (word *) q; + } + } + p += sz; + }else{ + CAMLassert (Ecolor (q) == 3); + /* This is guaranteed only if caml_compact_heap was called after a + nonincremental major GC: CAMLassert (Tag_ehd (q) == String_tag); + */ + /* No pointers to the header and no infix header: + the object was free. */ + *p = Make_header (Wosize_ehd (q), Tag_ehd (q), Caml_blue); + p += Whsize_ehd (q); + } + } + ch = Chunk_next (ch); + } + } + + + /* Fourth pass: reallocate and move objects. + Use the exact same allocation algorithm as pass 3. */ + { + init_compact_allocate (); + ch = caml_heap_start; + while (ch != NULL){ + word *p = (word *) ch; + + chend = ch + Chunk_size (ch); + while ((char *) p < chend){ + word q = *p; + if (Color_hd (q) == Caml_white){ + size_t sz = Bhsize_hd (q); + char *newadr = compact_allocate (sz); + memmove (newadr, p, sz); + p += Wsize_bsize (sz); + }else{ + CAMLassert (Color_hd (q) == Caml_blue); + p += Whsize_hd (q); + } + } + ch = Chunk_next (ch); + } + } + + /* Shrink the heap if needed. */ + { + /* Find the amount of live data and the unshrinkable free space. */ + asize_t live = 0; + asize_t free = 0; + asize_t wanted; + + ch = caml_heap_start; + while (ch != NULL){ + if (Chunk_alloc (ch) != 0){ + live += Wsize_bsize (Chunk_alloc (ch)); + free += Wsize_bsize (Chunk_size (ch) - Chunk_alloc (ch)); + } + ch = Chunk_next (ch); + } + + /* Add up the empty chunks until there are enough, then remove the + other empty chunks. */ + wanted = caml_percent_free * (live / 100 + 1); + ch = caml_heap_start; + while (ch != NULL){ + char *next_chunk = Chunk_next (ch); /* Chunk_next (ch) will be erased */ + + if (Chunk_alloc (ch) == 0){ + if (free < wanted){ + free += Wsize_bsize (Chunk_size (ch)); + }else{ + caml_shrink_heap (ch); + } + } + ch = next_chunk; + } + } + + /* Rebuild the free list. */ + { + ch = caml_heap_start; + caml_fl_reset (); + while (ch != NULL){ + if (Chunk_size (ch) > Chunk_alloc (ch)){ + caml_make_free_blocks ((value *) (ch + Chunk_alloc (ch)), + Wsize_bsize (Chunk_size(ch)-Chunk_alloc(ch)), 1, + Caml_white); + } + ch = Chunk_next (ch); + } + } + ++ caml_stat_compactions; + caml_gc_message (0x10, "done.\n"); +} + +uintnat caml_percent_max; /* used in gc_ctrl.c and memory.c */ + +void caml_compact_heap (void) +{ + uintnat target_wsz, live; + CAML_INSTR_SETUP(tmr, "compact"); + + CAMLassert (caml_young_ptr == caml_young_alloc_end); + CAMLassert (caml_ref_table.ptr == caml_ref_table.base); + CAMLassert (caml_ephe_ref_table.ptr == caml_ephe_ref_table.base); + CAMLassert (caml_custom_table.ptr == caml_custom_table.base); + + do_compaction (); + CAML_INSTR_TIME (tmr, "compact/main"); + /* Compaction may fail to shrink the heap to a reasonable size + because it deals in complete chunks: if a very large chunk + is at the beginning of the heap, everything gets moved to + it and it is not freed. + + In that case, we allocate a new chunk of the desired heap + size, chain it at the beginning of the heap (thus pretending + its address is smaller), and launch a second compaction. + This will move all data to this new chunk and free the + very large chunk. + + See PR#5389 + */ + /* We compute: + freewords = caml_fl_cur_wsz (exact) + heapwords = Wsize_bsize (caml_heap_size) (exact) + live = heapwords - freewords + wanted = caml_percent_free * (live / 100 + 1) (same as in do_compaction) + target_wsz = live + wanted + We add one page to make sure a small difference in counting sizes + won't make [do_compaction] keep the second block (and break all sorts + of invariants). + + We recompact if target_wsz < heap_size / 2 + */ + live = caml_stat_heap_wsz - caml_fl_cur_wsz; + target_wsz = live + caml_percent_free * (live / 100 + 1) + + Wsize_bsize (Page_size); + target_wsz = caml_clip_heap_chunk_wsz (target_wsz); + +#ifdef HAS_HUGE_PAGES + if (caml_use_huge_pages + && Bsize_wsize (caml_stat_heap_wsz) <= HUGE_PAGE_SIZE) + return; +#endif + + if (target_wsz < caml_stat_heap_wsz / 2){ + /* Recompact. */ + char *chunk; + + caml_gc_message (0x10, "Recompacting heap (target=%" + ARCH_INTNAT_PRINTF_FORMAT "uk words)\n", + target_wsz / 1024); + + chunk = caml_alloc_for_heap (Bsize_wsize (target_wsz)); + if (chunk == NULL) return; + /* PR#5757: we need to make the new blocks blue, or they won't be + recognized as free by the recompaction. */ + caml_make_free_blocks ((value *) chunk, + Wsize_bsize (Chunk_size (chunk)), 0, Caml_blue); + if (caml_page_table_add (In_heap, chunk, chunk + Chunk_size (chunk)) != 0){ + caml_free_for_heap (chunk); + return; + } + Chunk_next (chunk) = caml_heap_start; + caml_heap_start = chunk; + ++ caml_stat_heap_chunks; + caml_stat_heap_wsz += Wsize_bsize (Chunk_size (chunk)); + if (caml_stat_heap_wsz > caml_stat_top_heap_wsz){ + caml_stat_top_heap_wsz = caml_stat_heap_wsz; + } + do_compaction (); + CAMLassert (caml_stat_heap_chunks == 1); + CAMLassert (Chunk_next (caml_heap_start) == NULL); + CAMLassert (caml_stat_heap_wsz == Wsize_bsize (Chunk_size (chunk))); + CAML_INSTR_TIME (tmr, "compact/recompact"); + } +} + +void caml_compact_heap_maybe (void) +{ + /* Estimated free+garbage words in the heap: + FW = fl_size_at_phase_change + 3 * (caml_fl_cur_wsz + - caml_fl_wsz_at_phase_change) + FW = 3 * caml_fl_cur_wsz - 2 * caml_fl_wsz_at_phase_change + Estimated live words: LW = caml_stat_heap_wsz - FW + Estimated free percentage: FP = 100 * FW / LW + We compact the heap if FP > caml_percent_max + */ + double fw, fp; + CAMLassert (caml_gc_phase == Phase_idle); + if (caml_percent_max >= 1000000) return; + if (caml_stat_major_collections < 3) return; + if (caml_stat_heap_wsz <= 2 * caml_clip_heap_chunk_wsz (0)) return; + +#ifdef HAS_HUGE_PAGES + if (caml_use_huge_pages + && Bsize_wsize (caml_stat_heap_wsz) <= HUGE_PAGE_SIZE) + return; +#endif + + fw = 3.0 * caml_fl_cur_wsz - 2.0 * caml_fl_wsz_at_phase_change; + if (fw < 0) fw = caml_fl_cur_wsz; + + if (fw >= caml_stat_heap_wsz){ + fp = 1000000.0; + }else{ + fp = 100.0 * fw / (caml_stat_heap_wsz - fw); + if (fp > 1000000.0) fp = 1000000.0; + } + caml_gc_message (0x200, "FL size at phase change = %" + ARCH_INTNAT_PRINTF_FORMAT "u words\n", + (uintnat) caml_fl_wsz_at_phase_change); + caml_gc_message (0x200, "FL current size = %" + ARCH_INTNAT_PRINTF_FORMAT "u words\n", + (uintnat) caml_fl_cur_wsz); + caml_gc_message (0x200, "Estimated overhead = %" + ARCH_INTNAT_PRINTF_FORMAT "u%%\n", + (uintnat) fp); + if (fp >= caml_percent_max){ + caml_gc_message (0x200, "Automatic compaction triggered.\n"); + caml_empty_minor_heap (); /* minor heap must be empty for compaction */ + caml_finish_major_cycle (); + + fw = caml_fl_cur_wsz; + fp = 100.0 * fw / (caml_stat_heap_wsz - fw); + caml_gc_message (0x200, "Measured overhead: %" + ARCH_INTNAT_PRINTF_FORMAT "u%%\n", + (uintnat) fp); + if (fp >= caml_percent_max) + caml_compact_heap (); + else + caml_gc_message (0x200, "Automatic compaction aborted.\n"); + + } +} diff --git a/runtime/compare.c b/runtime/compare.c new file mode 100644 index 00000000..5de2e0e8 --- /dev/null +++ b/runtime/compare.c @@ -0,0 +1,373 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +#include +#include +#include "caml/custom.h" +#include "caml/fail.h" +#include "caml/memory.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" + +#if defined(LACKS_SANE_NAN) && !defined(isnan) +#define isnan _isnan +#endif + +/* Structural comparison on trees. */ + +struct compare_item { value * v1, * v2; mlsize_t count; }; + +#define COMPARE_STACK_INIT_SIZE 8 +#define COMPARE_STACK_MIN_ALLOC_SIZE 32 +#define COMPARE_STACK_MAX_SIZE (1024*1024) +CAMLexport int caml_compare_unordered; + +struct compare_stack { + struct compare_item init_stack[COMPARE_STACK_INIT_SIZE]; + struct compare_item* stack; + struct compare_item* limit; +}; + +/* Free the compare stack if needed */ +static void compare_free_stack(struct compare_stack* stk) +{ + if (stk->stack != stk->init_stack) { + caml_stat_free(stk->stack); + stk->stack = NULL; + } +} + +/* Same, then raise Out_of_memory */ +CAMLnoreturn_start +static void compare_stack_overflow(struct compare_stack* stk) +CAMLnoreturn_end; + +static void compare_stack_overflow(struct compare_stack* stk) +{ + caml_gc_message (0x04, "Stack overflow in structural comparison\n"); + compare_free_stack(stk); + caml_raise_out_of_memory(); +} + +/* Grow the compare stack */ +static struct compare_item * compare_resize_stack(struct compare_stack* stk, + struct compare_item * sp) +{ + asize_t newsize; + asize_t sp_offset = sp - stk->stack; + struct compare_item * newstack; + + if (stk->stack == stk->init_stack) { + newsize = COMPARE_STACK_MIN_ALLOC_SIZE; + newstack = caml_stat_alloc_noexc(sizeof(struct compare_item) * newsize); + if (newstack == NULL) compare_stack_overflow(stk); + memcpy(newstack, stk->init_stack, + sizeof(struct compare_item) * COMPARE_STACK_INIT_SIZE); + } else { + newsize = 2 * (stk->limit - stk->stack); + if (newsize >= COMPARE_STACK_MAX_SIZE) compare_stack_overflow(stk); + newstack = caml_stat_resize_noexc(stk->stack, + sizeof(struct compare_item) * newsize); + if (newstack == NULL) compare_stack_overflow(stk); + } + stk->stack = newstack; + stk->limit = newstack + newsize; + return newstack + sp_offset; +} + + +static intnat do_compare_val(struct compare_stack* stk, + value v1, value v2, int total); + +static intnat compare_val(value v1, value v2, int total) +{ + struct compare_stack stk; + intnat res; + stk.stack = stk.init_stack; + stk.limit = stk.stack + COMPARE_STACK_INIT_SIZE; + res = do_compare_val(&stk, v1, v2, total); + compare_free_stack(&stk); + return res; +} + +/* Structural comparison */ + + +#define LESS -1 +#define EQUAL 0 +#define GREATER 1 +#define UNORDERED ((intnat)1 << (8 * sizeof(value) - 1)) + +/* The return value of compare_val is as follows: + > 0 v1 is greater than v2 + 0 v1 is equal to v2 + < 0 and > UNORDERED v1 is less than v2 + UNORDERED v1 and v2 cannot be compared */ + +static intnat do_compare_val(struct compare_stack* stk, + value v1, value v2, int total) +{ + struct compare_item * sp; + tag_t t1, t2; + + sp = stk->stack; + while (1) { + if (v1 == v2 && total) goto next_item; + if (Is_long(v1)) { + if (v1 == v2) goto next_item; + if (Is_long(v2)) + return Long_val(v1) - Long_val(v2); + /* Subtraction above cannot overflow and cannot result in UNORDERED */ +#ifndef NO_NAKED_POINTERS + if (!Is_in_value_area(v2)) + return LESS; +#endif + switch (Tag_val(v2)) { + case Forward_tag: + v2 = Forward_val(v2); + continue; + case Custom_tag: { + int res; + int (*compare)(value v1, value v2) = Custom_ops_val(v2)->compare_ext; + if (compare == NULL) break; /* for backward compatibility */ + caml_compare_unordered = 0; + res = compare(v1, v2); + if (caml_compare_unordered && !total) return UNORDERED; + if (res != 0) return res; + goto next_item; + } + default: /*fallthrough*/; + } + return LESS; /* v1 long < v2 block */ + } + if (Is_long(v2)) { +#ifndef NO_NAKED_POINTERS + if (!Is_in_value_area(v1)) + return GREATER; +#endif + switch (Tag_val(v1)) { + case Forward_tag: + v1 = Forward_val(v1); + continue; + case Custom_tag: { + int res; + int (*compare)(value v1, value v2) = Custom_ops_val(v1)->compare_ext; + if (compare == NULL) break; /* for backward compatibility */ + caml_compare_unordered = 0; + res = compare(v1, v2); + if (caml_compare_unordered && !total) return UNORDERED; + if (res != 0) return res; + goto next_item; + } + default: /*fallthrough*/; + } + return GREATER; /* v1 block > v2 long */ + } +#ifndef NO_NAKED_POINTERS + /* If one of the objects is outside the heap (but is not an atom), + use address comparison. Since both addresses are 2-aligned, + shift lsb off to avoid overflow in subtraction. */ + if (! Is_in_value_area(v1) || ! Is_in_value_area(v2)) { + if (v1 == v2) goto next_item; + return (v1 >> 1) - (v2 >> 1); + /* Subtraction above cannot result in UNORDERED */ + } +#endif + t1 = Tag_val(v1); + t2 = Tag_val(v2); + if (t1 == Forward_tag) { v1 = Forward_val (v1); continue; } + if (t2 == Forward_tag) { v2 = Forward_val (v2); continue; } + if (t1 != t2) return (intnat)t1 - (intnat)t2; + switch(t1) { + case String_tag: { + mlsize_t len1, len2; + int res; + if (v1 == v2) break; + len1 = caml_string_length(v1); + len2 = caml_string_length(v2); + res = memcmp(String_val(v1), String_val(v2), len1 <= len2 ? len1 : len2); + if (res < 0) return LESS; + if (res > 0) return GREATER; + if (len1 != len2) return len1 - len2; + break; + } + case Double_tag: { + double d1 = Double_val(v1); + double d2 = Double_val(v2); +#ifdef LACKS_SANE_NAN + if (isnan(d2)) { + if (! total) return UNORDERED; + if (isnan(d1)) break; + return GREATER; + } else if (isnan(d1)) { + if (! total) return UNORDERED; + return LESS; + } +#endif + if (d1 < d2) return LESS; + if (d1 > d2) return GREATER; +#ifndef LACKS_SANE_NAN + if (d1 != d2) { + if (! total) return UNORDERED; + /* One or both of d1 and d2 is NaN. Order according to the + convention NaN = NaN and NaN < f for all other floats f. */ + if (d1 == d1) return GREATER; /* d1 is not NaN, d2 is NaN */ + if (d2 == d2) return LESS; /* d2 is not NaN, d1 is NaN */ + /* d1 and d2 are both NaN, thus equal: continue comparison */ + } +#endif + break; + } + case Double_array_tag: { + mlsize_t sz1 = Wosize_val(v1) / Double_wosize; + mlsize_t sz2 = Wosize_val(v2) / Double_wosize; + mlsize_t i; + if (sz1 != sz2) return sz1 - sz2; + for (i = 0; i < sz1; i++) { + double d1 = Double_flat_field(v1, i); + double d2 = Double_flat_field(v2, i); + #ifdef LACKS_SANE_NAN + if (isnan(d2)) { + if (! total) return UNORDERED; + if (isnan(d1)) break; + return GREATER; + } else if (isnan(d1)) { + if (! total) return UNORDERED; + return LESS; + } + #endif + if (d1 < d2) return LESS; + if (d1 > d2) return GREATER; + #ifndef LACKS_SANE_NAN + if (d1 != d2) { + if (! total) return UNORDERED; + /* See comment for Double_tag case */ + if (d1 == d1) return GREATER; + if (d2 == d2) return LESS; + } + #endif + } + break; + } + case Abstract_tag: + compare_free_stack(stk); + caml_invalid_argument("compare: abstract value"); + case Closure_tag: + case Infix_tag: + compare_free_stack(stk); + caml_invalid_argument("compare: functional value"); + case Object_tag: { + intnat oid1 = Oid_val(v1); + intnat oid2 = Oid_val(v2); + if (oid1 != oid2) return oid1 - oid2; + break; + } + case Custom_tag: { + int res; + int (*compare)(value v1, value v2) = Custom_ops_val(v1)->compare; + /* Hardening against comparisons between different types */ + if (compare != Custom_ops_val(v2)->compare) { + return strcmp(Custom_ops_val(v1)->identifier, + Custom_ops_val(v2)->identifier) < 0 + ? LESS : GREATER; + } + if (compare == NULL) { + compare_free_stack(stk); + caml_invalid_argument("compare: abstract value"); + } + caml_compare_unordered = 0; + res = compare(v1, v2); + if (caml_compare_unordered && !total) return UNORDERED; + if (res != 0) return res; + break; + } + default: { + mlsize_t sz1 = Wosize_val(v1); + mlsize_t sz2 = Wosize_val(v2); + /* Compare sizes first for speed */ + if (sz1 != sz2) return sz1 - sz2; + if (sz1 == 0) break; + /* Remember that we still have to compare fields 1 ... sz - 1 */ + if (sz1 > 1) { + sp++; + if (sp >= stk->limit) sp = compare_resize_stack(stk, sp); + sp->v1 = &Field(v1, 1); + sp->v2 = &Field(v2, 1); + sp->count = sz1 - 1; + } + /* Continue comparison with first field */ + v1 = Field(v1, 0); + v2 = Field(v2, 0); + continue; + } + } + next_item: + /* Pop one more item to compare, if any */ + if (sp == stk->stack) return EQUAL; /* we're done */ + v1 = *((sp->v1)++); + v2 = *((sp->v2)++); + if (--(sp->count) == 0) sp--; + } +} + +CAMLprim value caml_compare(value v1, value v2) +{ + intnat res = compare_val(v1, v2, 1); + /* Free stack if needed */ + if (res < 0) + return Val_int(LESS); + else if (res > 0) + return Val_int(GREATER); + else + return Val_int(EQUAL); +} + +CAMLprim value caml_equal(value v1, value v2) +{ + intnat res = compare_val(v1, v2, 0); + return Val_int(res == 0); +} + +CAMLprim value caml_notequal(value v1, value v2) +{ + intnat res = compare_val(v1, v2, 0); + return Val_int(res != 0); +} + +CAMLprim value caml_lessthan(value v1, value v2) +{ + intnat res = compare_val(v1, v2, 0); + return Val_int(res < 0 && res != UNORDERED); +} + +CAMLprim value caml_lessequal(value v1, value v2) +{ + intnat res = compare_val(v1, v2, 0); + return Val_int(res <= 0 && res != UNORDERED); +} + +CAMLprim value caml_greaterthan(value v1, value v2) +{ + intnat res = compare_val(v1, v2, 0); + return Val_int(res > 0); +} + +CAMLprim value caml_greaterequal(value v1, value v2) +{ + intnat res = compare_val(v1, v2, 0); + return Val_int(res >= 0); +} diff --git a/runtime/custom.c b/runtime/custom.c new file mode 100644 index 00000000..9ec3b222 --- /dev/null +++ b/runtime/custom.c @@ -0,0 +1,162 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +#include + +#include "caml/alloc.h" +#include "caml/custom.h" +#include "caml/fail.h" +#include "caml/gc_ctrl.h" +#include "caml/memory.h" +#include "caml/mlvalues.h" +#include "caml/signals.h" + +uintnat caml_custom_major_ratio = Custom_major_ratio_def; +uintnat caml_custom_minor_ratio = Custom_minor_ratio_def; +uintnat caml_custom_minor_max_bsz = Custom_minor_max_bsz_def; + +static value alloc_custom_gen (struct custom_operations * ops, + uintnat bsz, + mlsize_t mem, + mlsize_t max_major, + mlsize_t mem_minor, + mlsize_t max_minor) +{ + mlsize_t wosize; + CAMLparam0(); + CAMLlocal1(result); + + /* [mem] is the total amount of out-of-heap memory, [mem_minor] is how much + of it should be counted against [max_minor]. */ + CAMLassert (mem_minor <= mem); + + wosize = 1 + (bsz + sizeof(value) - 1) / sizeof(value); + if (wosize <= Max_young_wosize) { + result = caml_alloc_small(wosize, Custom_tag); + Custom_ops_val(result) = ops; + if (ops->finalize != NULL || mem != 0) { + if (mem > mem_minor) { + caml_adjust_gc_speed (mem - mem_minor, max_major); + } + /* The remaining [mem_minor] will be counted if the block survives a + minor GC */ + add_to_custom_table (&caml_custom_table, result, mem_minor, max_major); + /* Keep track of extra resources held by custom block in + minor heap. */ + if (mem_minor != 0) { + if (max_minor == 0) max_minor = 1; + caml_extra_heap_resources_minor += + (double) mem_minor / (double) max_minor; + if (caml_extra_heap_resources_minor > 1.0) { + caml_request_minor_gc (); + caml_gc_dispatch (); + } + } + } + } else { + result = caml_alloc_shr(wosize, Custom_tag); + Custom_ops_val(result) = ops; + caml_adjust_gc_speed(mem, max_major); + result = caml_check_urgent_gc(result); + } + CAMLreturn(result); +} + +CAMLexport value caml_alloc_custom(struct custom_operations * ops, + uintnat bsz, + mlsize_t mem, + mlsize_t max) +{ + return alloc_custom_gen (ops, bsz, mem, max, mem, max); +} + +CAMLexport value caml_alloc_custom_mem(struct custom_operations * ops, + uintnat bsz, + mlsize_t mem) +{ + mlsize_t mem_minor = + mem < caml_custom_minor_max_bsz ? mem : caml_custom_minor_max_bsz; + return alloc_custom_gen (ops, bsz, mem, + Bsize_wsize (caml_stat_heap_wsz) / 150 + * caml_custom_major_ratio, + mem_minor, + Bsize_wsize (caml_minor_heap_wsz) / 100 + * caml_custom_major_ratio); +} + +struct custom_operations_list { + struct custom_operations * ops; + struct custom_operations_list * next; +}; + +static struct custom_operations_list * custom_ops_table = NULL; + +CAMLexport void caml_register_custom_operations(struct custom_operations * ops) +{ + struct custom_operations_list * l = + caml_stat_alloc(sizeof(struct custom_operations_list)); + CAMLassert(ops->identifier != NULL); + CAMLassert(ops->deserialize != NULL); + l->ops = ops; + l->next = custom_ops_table; + custom_ops_table = l; +} + +struct custom_operations * caml_find_custom_operations(char * ident) +{ + struct custom_operations_list * l; + for (l = custom_ops_table; l != NULL; l = l->next) + if (strcmp(l->ops->identifier, ident) == 0) return l->ops; + return NULL; +} + +static struct custom_operations_list * custom_ops_final_table = NULL; + +struct custom_operations * caml_final_custom_operations(final_fun fn) +{ + struct custom_operations_list * l; + struct custom_operations * ops; + for (l = custom_ops_final_table; l != NULL; l = l->next) + if (l->ops->finalize == fn) return l->ops; + ops = caml_stat_alloc(sizeof(struct custom_operations)); + ops->identifier = "_final"; + ops->finalize = fn; + ops->compare = custom_compare_default; + ops->hash = custom_hash_default; + ops->serialize = custom_serialize_default; + ops->deserialize = custom_deserialize_default; + ops->compare_ext = custom_compare_ext_default; + ops->fixed_length = custom_fixed_length_default; + l = caml_stat_alloc(sizeof(struct custom_operations_list)); + l->ops = ops; + l->next = custom_ops_final_table; + custom_ops_final_table = l; + return ops; +} + +extern struct custom_operations caml_int32_ops, + caml_nativeint_ops, + caml_int64_ops, + caml_ba_ops; + +void caml_init_custom_operations(void) +{ + caml_register_custom_operations(&caml_int32_ops); + caml_register_custom_operations(&caml_nativeint_ops); + caml_register_custom_operations(&caml_int64_ops); + caml_register_custom_operations(&caml_ba_ops); +} diff --git a/runtime/debugger.c b/runtime/debugger.c new file mode 100644 index 00000000..a7c20278 --- /dev/null +++ b/runtime/debugger.c @@ -0,0 +1,462 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Interface with the byte-code debugger */ + +#ifdef _WIN32 +#include +#endif /* _WIN32 */ + +#include + +#include "caml/alloc.h" +#include "caml/config.h" +#include "caml/debugger.h" +#include "caml/misc.h" +#include "caml/osdeps.h" + +int caml_debugger_in_use = 0; +uintnat caml_event_count; +int caml_debugger_fork_mode = 1; /* parent by default */ + +#if !defined(HAS_SOCKETS) || defined(NATIVE_CODE) + +void caml_debugger_init(void) +{ +} + +void caml_debugger(enum event_kind event) +{ +} + +void caml_debugger_cleanup_fork(void) +{ +} + +#else + +#ifdef HAS_UNISTD +#include +#endif +#include +#include +#ifndef _WIN32 +#include +#include +#include +#include +#include +#include +#else +#define ATOM ATOM_WS +#include +#undef ATOM +#include +#endif + +#include "caml/fail.h" +#include "caml/fix_code.h" +#include "caml/instruct.h" +#include "caml/intext.h" +#include "caml/io.h" +#include "caml/mlvalues.h" +#include "caml/stacks.h" +#include "caml/sys.h" + +static value marshal_flags = Val_emptylist; + +static int sock_domain; /* Socket domain for the debugger */ +static union { /* Socket address for the debugger */ + struct sockaddr s_gen; +#ifndef _WIN32 + struct sockaddr_un s_unix; +#endif + struct sockaddr_in s_inet; +} sock_addr; +static int sock_addr_len; /* Length of sock_addr */ + +static int dbg_socket = -1; /* The socket connected to the debugger */ +static struct channel * dbg_in; /* Input channel on the socket */ +static struct channel * dbg_out;/* Output channel on the socket */ + +static char *dbg_addr = NULL; + +static void open_connection(void) +{ +#ifdef _WIN32 + /* Set socket to synchronous mode so that file descriptor-oriented + functions (read()/write() etc.) can be used */ + + int oldvalue, oldvaluelen, newvalue, retcode; + oldvaluelen = sizeof(oldvalue); + retcode = getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, + (char *) &oldvalue, &oldvaluelen); + if (retcode == 0) { + newvalue = SO_SYNCHRONOUS_NONALERT; + setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, + (char *) &newvalue, sizeof(newvalue)); + } +#endif + dbg_socket = socket(sock_domain, SOCK_STREAM, 0); +#ifdef _WIN32 + if (retcode == 0) { + /* Restore initial mode */ + setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, + (char *) &oldvalue, oldvaluelen); + } +#endif + if (dbg_socket == -1 || + connect(dbg_socket, &sock_addr.s_gen, sock_addr_len) == -1){ + caml_fatal_error + ( + "cannot connect to debugger at %s\n" + "error: %s", + (dbg_addr ? dbg_addr : "(none)"), + strerror (errno) + ); + } +#ifdef _WIN32 + dbg_socket = _open_osfhandle(dbg_socket, 0); + if (dbg_socket == -1) + caml_fatal_error("_open_osfhandle failed"); +#endif + dbg_in = caml_open_descriptor_in(dbg_socket); + dbg_out = caml_open_descriptor_out(dbg_socket); + if (!caml_debugger_in_use) caml_putword(dbg_out, -1); /* first connection */ +#ifdef _WIN32 + caml_putword(dbg_out, _getpid()); +#else + caml_putword(dbg_out, getpid()); +#endif + caml_flush(dbg_out); +} + +static void close_connection(void) +{ + caml_close_channel(dbg_in); + caml_close_channel(dbg_out); + dbg_socket = -1; /* was closed by caml_close_channel */ +} + +#ifdef _WIN32 +static void winsock_startup(void) +{ + WSADATA wsaData; + int err = WSAStartup(MAKEWORD(2, 0), &wsaData); + if (err) caml_fatal_error("WSAStartup failed"); +} + +static void winsock_cleanup(void) +{ + WSACleanup(); +} +#endif + +void caml_debugger_init(void) +{ + char * address; + char_os * a; + size_t a_len; + char * port, * p; + struct hostent * host; + int n; + + caml_register_global_root(&marshal_flags); + marshal_flags = caml_alloc(2, Tag_cons); + Store_field(marshal_flags, 0, Val_int(1)); /* Marshal.Closures */ + Store_field(marshal_flags, 1, Val_emptylist); + + a = caml_secure_getenv(_T("CAML_DEBUG_SOCKET")); + address = a ? caml_stat_strdup_of_os(a) : NULL; + if (address == NULL) return; + if (dbg_addr != NULL) caml_stat_free(dbg_addr); + dbg_addr = address; + +#ifdef _WIN32 + winsock_startup(); + (void)atexit(winsock_cleanup); +#endif + /* Parse the address */ + port = NULL; + for (p = address; *p != 0; p++) { + if (*p == ':') { *p = 0; port = p+1; break; } + } + if (port == NULL) { +#ifndef _WIN32 + /* Unix domain */ + sock_domain = PF_UNIX; + sock_addr.s_unix.sun_family = AF_UNIX; + a_len = strlen(address); + if (a_len >= sizeof(sock_addr.s_unix.sun_path)) { + caml_fatal_error + ( + "debug socket path length exceeds maximum permitted length" + ); + } + strncpy(sock_addr.s_unix.sun_path, address, + sizeof(sock_addr.s_unix.sun_path) - 1); + sock_addr.s_unix.sun_path[sizeof(sock_addr.s_unix.sun_path) - 1] = '\0'; + sock_addr_len = + ((char *)&(sock_addr.s_unix.sun_path) - (char *)&(sock_addr.s_unix)) + + a_len; +#else + caml_fatal_error("unix sockets not supported"); +#endif + } else { + /* Internet domain */ + sock_domain = PF_INET; + for (p = (char *) &sock_addr.s_inet, n = sizeof(sock_addr.s_inet); + n > 0; n--) *p++ = 0; + sock_addr.s_inet.sin_family = AF_INET; + sock_addr.s_inet.sin_addr.s_addr = inet_addr(address); + if (sock_addr.s_inet.sin_addr.s_addr == -1) { + host = gethostbyname(address); + if (host == NULL) + caml_fatal_error("unknown debugging host %s", address); + memmove(&sock_addr.s_inet.sin_addr, host->h_addr, host->h_length); + } + sock_addr.s_inet.sin_port = htons(atoi(port)); + sock_addr_len = sizeof(sock_addr.s_inet); + } + open_connection(); + caml_debugger_in_use = 1; + caml_trap_barrier = caml_stack_high; +} + +static value getval(struct channel *chan) +{ + value res; + if (caml_really_getblock(chan, (char *) &res, sizeof(res)) < sizeof(res)) + caml_raise_end_of_file(); /* Bad, but consistent with caml_getword */ + return res; +} + +static void putval(struct channel *chan, value val) +{ + caml_really_putblock(chan, (char *) &val, sizeof(val)); +} + +static void safe_output_value(struct channel *chan, value val) +{ + struct longjmp_buffer raise_buf, * saved_external_raise; + + /* Catch exceptions raised by [caml_output_val] */ + saved_external_raise = caml_external_raise; + if (sigsetjmp(raise_buf.buf, 0) == 0) { + caml_external_raise = &raise_buf; + caml_output_val(chan, val, marshal_flags); + } else { + /* Send wrong magic number, will cause [caml_input_value] to fail */ + caml_really_putblock(chan, "\000\000\000\000", 4); + } + caml_external_raise = saved_external_raise; +} + +#define Pc(sp) ((code_t)((sp)[0])) +#define Env(sp) ((sp)[1]) +#define Extra_args(sp) (Long_val(((sp)[2]))) +#define Locals(sp) ((sp) + 3) + +void caml_debugger(enum event_kind event) +{ + value * frame; + intnat i, pos; + value val; + + if (dbg_socket == -1) return; /* Not connected to a debugger. */ + + /* Reset current frame */ + frame = caml_extern_sp + 1; + + /* Report the event to the debugger */ + switch(event) { + case PROGRAM_START: /* Nothing to report */ + goto command_loop; + case EVENT_COUNT: + caml_putch(dbg_out, REP_EVENT); + break; + case BREAKPOINT: + caml_putch(dbg_out, REP_BREAKPOINT); + break; + case PROGRAM_EXIT: + caml_putch(dbg_out, REP_EXITED); + break; + case TRAP_BARRIER: + caml_putch(dbg_out, REP_TRAP); + break; + case UNCAUGHT_EXC: + caml_putch(dbg_out, REP_UNCAUGHT_EXC); + break; + } + caml_putword(dbg_out, caml_event_count); + if (event == EVENT_COUNT || event == BREAKPOINT) { + caml_putword(dbg_out, caml_stack_high - frame); + caml_putword(dbg_out, (Pc(frame) - caml_start_code) * sizeof(opcode_t)); + } else { + /* No PC and no stack frame associated with other events */ + caml_putword(dbg_out, 0); + caml_putword(dbg_out, 0); + } + caml_flush(dbg_out); + + command_loop: + + /* Read and execute the commands sent by the debugger */ + while(1) { + switch(caml_getch(dbg_in)) { + case REQ_SET_EVENT: + pos = caml_getword(dbg_in); + CAMLassert (pos >= 0); + CAMLassert (pos < caml_code_size); + caml_set_instruction(caml_start_code + pos / sizeof(opcode_t), EVENT); + break; + case REQ_SET_BREAKPOINT: + pos = caml_getword(dbg_in); + CAMLassert (pos >= 0); + CAMLassert (pos < caml_code_size); + caml_set_instruction(caml_start_code + pos / sizeof(opcode_t), BREAK); + break; + case REQ_RESET_INSTR: + pos = caml_getword(dbg_in); + CAMLassert (pos >= 0); + CAMLassert (pos < caml_code_size); + pos = pos / sizeof(opcode_t); + caml_set_instruction(caml_start_code + pos, caml_saved_code[pos]); + break; + case REQ_CHECKPOINT: +#ifndef _WIN32 + i = fork(); + if (i == 0) { + close_connection(); /* Close parent connection. */ + open_connection(); /* Open new connection with debugger */ + } else { + caml_putword(dbg_out, i); + caml_flush(dbg_out); + } +#else + caml_fatal_error("REQ_CHECKPOINT command"); + exit(-1); +#endif + break; + case REQ_GO: + caml_event_count = caml_getword(dbg_in); + return; + case REQ_STOP: + exit(0); + break; + case REQ_WAIT: +#ifndef _WIN32 + wait(NULL); +#else + caml_fatal_error("REQ_WAIT command"); + exit(-1); +#endif + break; + case REQ_INITIAL_FRAME: + frame = caml_extern_sp + 1; + /* Fall through */ + case REQ_GET_FRAME: + caml_putword(dbg_out, caml_stack_high - frame); + if (frame < caml_stack_high){ + caml_putword(dbg_out, (Pc(frame) - caml_start_code) * sizeof(opcode_t)); + }else{ + caml_putword (dbg_out, 0); + } + caml_flush(dbg_out); + break; + case REQ_SET_FRAME: + i = caml_getword(dbg_in); + frame = caml_stack_high - i; + break; + case REQ_UP_FRAME: + i = caml_getword(dbg_in); + if (frame + Extra_args(frame) + i + 3 >= caml_stack_high) { + caml_putword(dbg_out, -1); + } else { + frame += Extra_args(frame) + i + 3; + caml_putword(dbg_out, caml_stack_high - frame); + caml_putword(dbg_out, (Pc(frame) - caml_start_code) * sizeof(opcode_t)); + } + caml_flush(dbg_out); + break; + case REQ_SET_TRAP_BARRIER: + i = caml_getword(dbg_in); + caml_trap_barrier = caml_stack_high - i; + break; + case REQ_GET_LOCAL: + i = caml_getword(dbg_in); + putval(dbg_out, Locals(frame)[i]); + caml_flush(dbg_out); + break; + case REQ_GET_ENVIRONMENT: + i = caml_getword(dbg_in); + putval(dbg_out, Field(Env(frame), i)); + caml_flush(dbg_out); + break; + case REQ_GET_GLOBAL: + i = caml_getword(dbg_in); + putval(dbg_out, Field(caml_global_data, i)); + caml_flush(dbg_out); + break; + case REQ_GET_ACCU: + putval(dbg_out, *caml_extern_sp); + caml_flush(dbg_out); + break; + case REQ_GET_HEADER: + val = getval(dbg_in); + caml_putword(dbg_out, Hd_val(val)); + caml_flush(dbg_out); + break; + case REQ_GET_FIELD: + val = getval(dbg_in); + i = caml_getword(dbg_in); + if (Tag_val(val) != Double_array_tag) { + caml_putch(dbg_out, 0); + putval(dbg_out, Field(val, i)); + } else { + double d = Double_flat_field(val, i); + caml_putch(dbg_out, 1); + caml_really_putblock(dbg_out, (char *) &d, 8); + } + caml_flush(dbg_out); + break; + case REQ_MARSHAL_OBJ: + val = getval(dbg_in); + safe_output_value(dbg_out, val); + caml_flush(dbg_out); + break; + case REQ_GET_CLOSURE_CODE: + val = getval(dbg_in); + caml_putword(dbg_out, (Code_val(val)-caml_start_code) * sizeof(opcode_t)); + caml_flush(dbg_out); + break; + case REQ_SET_FORK_MODE: + caml_debugger_fork_mode = caml_getword(dbg_in); + break; + } + } +} + +void caml_debugger_cleanup_fork(void) +{ + /* We could remove all of the breakpoints, but closing the connection + * means that they'll just be skipped anyway. */ + close_connection(); + caml_debugger_in_use = 0; +} + +#endif diff --git a/runtime/dune b/runtime/dune new file mode 100644 index 00000000..8e8a116b --- /dev/null +++ b/runtime/dune @@ -0,0 +1,58 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +(rule + (targets primitives) + (mode fallback) + (deps alloc.c array.c compare.c extern.c floats.c gc_ctrl.c hash.c intern.c + interp.c ints.c io.c lexing.c md5.c meta.c obj.c parsing.c signals.c + str.c sys.c callback.c weak.c finalise.c stacks.c dynlink.c + backtrace_byt.c backtrace.c spacetime_byt.c afl.c bigarray.c) + (action (with-stdout-to %{targets} (run %{dep:gen_primitives.sh})))) + +(rule + (targets libcamlrun.a) + (mode fallback) + (deps ../Makefile.config ../Makefile.common Makefile + (glob_files caml/*.h) + interp.c misc.c stacks.c fix_code.c startup_aux.c startup_byt.c + freelist.c major_gc.c minor_gc.c memory.c alloc.c roots_byt.c + globroots.c fail_byt.c signals.c signals_byt.c printexc.c + backtrace_byt.c backtrace.c compare.c ints.c floats.c str.c array.c + io.c extern.c intern.c hash.c sys.c meta.c parsing.c gc_ctrl.c md5.c + obj.c lexing.c callback.c debugger.c weak.c compact.c finalise.c + custom.c dynlink.c spacetime_byt.c afl.c unix.c win32.c bigarray.c + main.c) + (action + (progn + (bash "touch .depend") ; hack. + (run make %{targets}) + (bash "rm .depend")))) + +;; HACK +(library + (name runtime) + (modes byte) + (wrapped false) + (modules runtime) + (flags (-nostdlib -nopervasives)) + (self_build_stubs_archive (runtime))) + +(rule + (targets libruntime_stubs.a) + (action (copy libcamlrun.a %{targets}))) + +(rule + (targets runtime.ml) + (action (write-file %{targets} "let linkme = ()"))) diff --git a/runtime/dynlink.c b/runtime/dynlink.c new file mode 100644 index 00000000..cf728b0e --- /dev/null +++ b/runtime/dynlink.c @@ -0,0 +1,304 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Dynamic loading of C primitives. */ + +#include +#include +#include +#include +#include +#include "caml/config.h" +#ifdef HAS_UNISTD +#include +#endif +#include "caml/alloc.h" +#include "caml/dynlink.h" +#include "caml/fail.h" +#include "caml/mlvalues.h" +#include "caml/memory.h" +#include "caml/misc.h" +#include "caml/osdeps.h" +#include "caml/prims.h" +#include "caml/signals.h" + +#ifndef NATIVE_CODE + +/* The table of primitives */ +struct ext_table caml_prim_table; + +#ifdef DEBUG +/* The names of primitives (for instrtrace.c) */ +struct ext_table caml_prim_name_table; +#endif + +/* The table of shared libraries currently opened */ +static struct ext_table shared_libs; + +/* The search path for shared libraries */ +struct ext_table caml_shared_libs_path; + +/* Look up the given primitive name in the built-in primitive table, + then in the opened shared libraries (shared_libs) */ +static c_primitive lookup_primitive(char * name) +{ + int i; + void * res; + + for (i = 0; caml_names_of_builtin_cprim[i] != NULL; i++) { + if (strcmp(name, caml_names_of_builtin_cprim[i]) == 0) + return caml_builtin_cprim[i]; + } + for (i = 0; i < shared_libs.size; i++) { + res = caml_dlsym(shared_libs.contents[i], name); + if (res != NULL) return (c_primitive) res; + } + return NULL; +} + +/* Parse the OCAML_STDLIB_DIR/ld.conf file and add the directories + listed there to the search path */ + +#define LD_CONF_NAME _T("ld.conf") + +static char_os * parse_ld_conf(void) +{ + char_os * stdlib, * ldconfname, * wconfig, * p, * q; + char * config; +#ifdef _WIN32 + struct _stati64 st; +#else + struct stat st; +#endif + int ldconf, nread; + + stdlib = caml_secure_getenv(_T("OCAMLLIB")); + if (stdlib == NULL) stdlib = caml_secure_getenv(_T("CAMLLIB")); + if (stdlib == NULL) stdlib = OCAML_STDLIB_DIR; + ldconfname = caml_stat_strconcat_os(3, stdlib, _T("/"), LD_CONF_NAME); + if (stat_os(ldconfname, &st) == -1) { + caml_stat_free(ldconfname); + return NULL; + } + ldconf = open_os(ldconfname, O_RDONLY, 0); + if (ldconf == -1) + caml_fatal_error("cannot read loader config file %s", + caml_stat_strdup_of_os(ldconfname)); + config = caml_stat_alloc(st.st_size + 1); + nread = read(ldconf, config, st.st_size); + if (nread == -1) + caml_fatal_error + ("error while reading loader config file %s", + caml_stat_strdup_of_os(ldconfname)); + config[nread] = 0; + wconfig = caml_stat_strdup_to_os(config); + caml_stat_free(config); + q = wconfig; + for (p = wconfig; *p != 0; p++) { + if (*p == _T('\n')) { + *p = 0; + caml_ext_table_add(&caml_shared_libs_path, q); + q = p + 1; + } + } + if (q < p) caml_ext_table_add(&caml_shared_libs_path, q); + close(ldconf); + caml_stat_free(ldconfname); + return wconfig; +} + +/* Open the given shared library and add it to shared_libs. + Abort on error. */ +static void open_shared_lib(char_os * name) +{ + char_os * realname; + char * u8; + void * handle; + + realname = caml_search_dll_in_path(&caml_shared_libs_path, name); + u8 = caml_stat_strdup_of_os(realname); + caml_gc_message(0x100, "Loading shared library %s\n", u8); + caml_stat_free(u8); + caml_enter_blocking_section(); + handle = caml_dlopen(realname, 1, 1); + caml_leave_blocking_section(); + if (handle == NULL) + caml_fatal_error + ( + "cannot load shared library %s\n" + "Reason: %s", + caml_stat_strdup_of_os(name), + caml_dlerror() + ); + caml_ext_table_add(&shared_libs, handle); + caml_stat_free(realname); +} + +/* Build the table of primitives, given a search path and a list + of shared libraries (both 0-separated in a char array). + Abort the runtime system on error. */ +void caml_build_primitive_table(char_os * lib_path, + char_os * libs, + char * req_prims) +{ + char_os * tofree1, * tofree2; + char_os * p; + char * q; + + /* Initialize the search path for dynamic libraries: + - directories specified on the command line with the -I option + - directories specified in the CAML_LD_LIBRARY_PATH + - directories specified in the executable + - directories specified in the file /ld.conf */ + tofree1 = caml_decompose_path(&caml_shared_libs_path, + caml_secure_getenv(_T("CAML_LD_LIBRARY_PATH"))); + if (lib_path != NULL) + for (p = lib_path; *p != 0; p += strlen_os(p) + 1) + caml_ext_table_add(&caml_shared_libs_path, p); + tofree2 = parse_ld_conf(); + /* Open the shared libraries */ + caml_ext_table_init(&shared_libs, 8); + if (libs != NULL) + for (p = libs; *p != 0; p += strlen_os(p) + 1) + open_shared_lib(p); + /* Build the primitive table */ + caml_ext_table_init(&caml_prim_table, 0x180); +#ifdef DEBUG + caml_ext_table_init(&caml_prim_name_table, 0x180); +#endif + for (q = req_prims; *q != 0; q += strlen(q) + 1) { + c_primitive prim = lookup_primitive(q); + if (prim == NULL) + caml_fatal_error("unknown C primitive `%s'", q); + caml_ext_table_add(&caml_prim_table, (void *) prim); +#ifdef DEBUG + caml_ext_table_add(&caml_prim_name_table, caml_stat_strdup(q)); +#endif + } + /* Clean up */ + caml_stat_free(tofree1); + caml_stat_free(tofree2); + caml_ext_table_free(&caml_shared_libs_path, 0); +} + +/* Build the table of primitives as a copy of the builtin primitive table. + Used for executables generated by ocamlc -output-obj. */ + +void caml_build_primitive_table_builtin(void) +{ + int i; + caml_ext_table_init(&caml_prim_table, 0x180); +#ifdef DEBUG + caml_ext_table_init(&caml_prim_name_table, 0x180); +#endif + for (i = 0; caml_builtin_cprim[i] != 0; i++) { + caml_ext_table_add(&caml_prim_table, (void *) caml_builtin_cprim[i]); +#ifdef DEBUG + caml_ext_table_add(&caml_prim_name_table, + caml_stat_strdup(caml_names_of_builtin_cprim[i])); +#endif + } +} + +void caml_free_shared_libs(void) +{ + while (shared_libs.size > 0) + caml_dlclose(shared_libs.contents[--shared_libs.size]); +} + +#endif /* NATIVE_CODE */ + +/** dlopen interface for the bytecode linker **/ + +#define Handle_val(v) (*((void **) (v))) + +CAMLprim value caml_dynlink_open_lib(value mode, value filename) +{ + void * handle; + value result; + char_os * p; + + caml_gc_message(0x100, "Opening shared library %s\n", + String_val(filename)); + p = caml_stat_strdup_to_os(String_val(filename)); + caml_enter_blocking_section(); + handle = caml_dlopen(p, Int_val(mode), 1); + caml_leave_blocking_section(); + caml_stat_free(p); + if (handle == NULL) caml_failwith(caml_dlerror()); + result = caml_alloc_small(1, Abstract_tag); + Handle_val(result) = handle; + return result; +} + +CAMLprim value caml_dynlink_close_lib(value handle) +{ + caml_dlclose(Handle_val(handle)); + return Val_unit; +} + +/*#include */ +CAMLprim value caml_dynlink_lookup_symbol(value handle, value symbolname) +{ + void * symb; + value result; + symb = caml_dlsym(Handle_val(handle), String_val(symbolname)); + /* printf("%s = 0x%lx\n", String_val(symbolname), symb); + fflush(stdout); */ + if (symb == NULL) return Val_unit /*caml_failwith(caml_dlerror())*/; + result = caml_alloc_small(1, Abstract_tag); + Handle_val(result) = symb; + return result; +} + +#ifndef NATIVE_CODE + +CAMLprim value caml_dynlink_add_primitive(value handle) +{ + return Val_int(caml_ext_table_add(&caml_prim_table, Handle_val(handle))); +} + +CAMLprim value caml_dynlink_get_current_libs(value unit) +{ + CAMLparam0(); + CAMLlocal1(res); + int i; + + res = caml_alloc_tuple(shared_libs.size); + for (i = 0; i < shared_libs.size; i++) { + value v = caml_alloc_small(1, Abstract_tag); + Handle_val(v) = shared_libs.contents[i]; + Store_field(res, i, v); + } + CAMLreturn(res); +} + +#else + +value caml_dynlink_add_primitive(value handle) +{ + caml_invalid_argument("dynlink_add_primitive"); + return Val_unit; /* not reached */ +} + +value caml_dynlink_get_current_libs(value unit) +{ + caml_invalid_argument("dynlink_get_current_libs"); + return Val_unit; /* not reached */ +} + +#endif /* NATIVE_CODE */ diff --git a/asmrun/natdynlink.c b/runtime/dynlink_nat.c similarity index 100% rename from asmrun/natdynlink.c rename to runtime/dynlink_nat.c diff --git a/runtime/extern.c b/runtime/extern.c new file mode 100644 index 00000000..248b61a6 --- /dev/null +++ b/runtime/extern.c @@ -0,0 +1,947 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Structured output */ + +/* The interface of this file is "caml/intext.h" */ + +#include +#include "caml/alloc.h" +#include "caml/config.h" +#include "caml/custom.h" +#include "caml/fail.h" +#include "caml/gc.h" +#include "caml/intext.h" +#include "caml/io.h" +#include "caml/md5.h" +#include "caml/memory.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/reverse.h" + +static uintnat obj_counter; /* Number of objects emitted so far */ +static uintnat size_32; /* Size in words of 32-bit block for struct. */ +static uintnat size_64; /* Size in words of 64-bit block for struct. */ + +/* Flags affecting marshaling */ + +enum { + NO_SHARING = 1, /* Flag to ignore sharing */ + CLOSURES = 2, /* Flag to allow marshaling code pointers */ + COMPAT_32 = 4 /* Flag to ensure that output can safely + be read back on a 32-bit platform */ +}; + +static int extern_flags; /* logical or of some of the flags above */ + +/* Trail mechanism to undo forwarding pointers put inside objects */ + +struct trail_entry { + value obj; /* address of object + initial color in low 2 bits */ + value field0; /* initial contents of field 0 */ +}; + +struct trail_block { + struct trail_block * previous; + struct trail_entry entries[ENTRIES_PER_TRAIL_BLOCK]; +}; + +static struct trail_block extern_trail_first; +static struct trail_block * extern_trail_block; +static struct trail_entry * extern_trail_cur, * extern_trail_limit; + + +/* Stack for pending values to marshal */ + +struct extern_item { value * v; mlsize_t count; }; + +#define EXTERN_STACK_INIT_SIZE 256 +#define EXTERN_STACK_MAX_SIZE (1024*1024*100) + +static struct extern_item extern_stack_init[EXTERN_STACK_INIT_SIZE]; + +static struct extern_item * extern_stack = extern_stack_init; +static struct extern_item * extern_stack_limit = extern_stack_init + + EXTERN_STACK_INIT_SIZE; + +/* Forward declarations */ + +CAMLnoreturn_start +static void extern_out_of_memory(void) +CAMLnoreturn_end; + +CAMLnoreturn_start +static void extern_invalid_argument(char *msg) +CAMLnoreturn_end; + +CAMLnoreturn_start +static void extern_failwith(char *msg) +CAMLnoreturn_end; + +CAMLnoreturn_start +static void extern_stack_overflow(void) +CAMLnoreturn_end; + +static void extern_replay_trail(void); +static void free_extern_output(void); + +/* Free the extern stack if needed */ +static void extern_free_stack(void) +{ + if (extern_stack != extern_stack_init) { + caml_stat_free(extern_stack); + /* Reinitialize the globals for next time around */ + extern_stack = extern_stack_init; + extern_stack_limit = extern_stack + EXTERN_STACK_INIT_SIZE; + } +} + +static struct extern_item * extern_resize_stack(struct extern_item * sp) +{ + asize_t newsize = 2 * (extern_stack_limit - extern_stack); + asize_t sp_offset = sp - extern_stack; + struct extern_item * newstack; + + if (newsize >= EXTERN_STACK_MAX_SIZE) extern_stack_overflow(); + if (extern_stack == extern_stack_init) { + newstack = caml_stat_alloc_noexc(sizeof(struct extern_item) * newsize); + if (newstack == NULL) extern_stack_overflow(); + memcpy(newstack, extern_stack_init, + sizeof(struct extern_item) * EXTERN_STACK_INIT_SIZE); + } else { + newstack = caml_stat_resize_noexc(extern_stack, + sizeof(struct extern_item) * newsize); + if (newstack == NULL) extern_stack_overflow(); + } + extern_stack = newstack; + extern_stack_limit = newstack + newsize; + return newstack + sp_offset; +} + +/* Initialize the trail */ + +static void init_extern_trail(void) +{ + extern_trail_block = &extern_trail_first; + extern_trail_cur = extern_trail_block->entries; + extern_trail_limit = extern_trail_block->entries + ENTRIES_PER_TRAIL_BLOCK; +} + +/* Replay the trail, undoing the in-place modifications + performed on objects */ + +static void extern_replay_trail(void) +{ + struct trail_block * blk, * prevblk; + struct trail_entry * ent, * lim; + + blk = extern_trail_block; + lim = extern_trail_cur; + while (1) { + for (ent = &(blk->entries[0]); ent < lim; ent++) { + value obj = ent->obj; + color_t colornum = obj & 3; + obj = obj & ~3; + Hd_val(obj) = Coloredhd_hd(Hd_val(obj), colornum); + Field(obj, 0) = ent->field0; + } + if (blk == &extern_trail_first) break; + prevblk = blk->previous; + caml_stat_free(blk); + blk = prevblk; + lim = &(blk->entries[ENTRIES_PER_TRAIL_BLOCK]); + } + /* Protect against a second call to extern_replay_trail */ + extern_trail_block = &extern_trail_first; + extern_trail_cur = extern_trail_block->entries; +} + +/* Set forwarding pointer on an object and add corresponding entry + to the trail. */ + +static void extern_record_location(value obj) +{ + header_t hdr; + + if (extern_flags & NO_SHARING) return; + if (extern_trail_cur == extern_trail_limit) { + struct trail_block * new_block = + caml_stat_alloc_noexc(sizeof(struct trail_block)); + if (new_block == NULL) extern_out_of_memory(); + new_block->previous = extern_trail_block; + extern_trail_block = new_block; + extern_trail_cur = extern_trail_block->entries; + extern_trail_limit = extern_trail_block->entries + ENTRIES_PER_TRAIL_BLOCK; + } + hdr = Hd_val(obj); + extern_trail_cur->obj = obj | Colornum_hd(hdr); + extern_trail_cur->field0 = Field(obj, 0); + extern_trail_cur++; + Hd_val(obj) = Bluehd_hd(hdr); + Field(obj, 0) = (value) obj_counter; + obj_counter++; +} + +/* To buffer the output */ + +static char * extern_userprovided_output; +static char * extern_ptr, * extern_limit; + +struct output_block { + struct output_block * next; + char * end; + char data[SIZE_EXTERN_OUTPUT_BLOCK]; +}; + +static struct output_block * extern_output_first, * extern_output_block; + +static void init_extern_output(void) +{ + extern_userprovided_output = NULL; + extern_output_first = caml_stat_alloc_noexc(sizeof(struct output_block)); + if (extern_output_first == NULL) caml_raise_out_of_memory(); + extern_output_block = extern_output_first; + extern_output_block->next = NULL; + extern_ptr = extern_output_block->data; + extern_limit = extern_output_block->data + SIZE_EXTERN_OUTPUT_BLOCK; +} + +static void close_extern_output(void) +{ + if (extern_userprovided_output == NULL){ + extern_output_block->end = extern_ptr; + } +} + +static void free_extern_output(void) +{ + struct output_block * blk, * nextblk; + + if (extern_userprovided_output != NULL) return; + for (blk = extern_output_first; blk != NULL; blk = nextblk) { + nextblk = blk->next; + caml_stat_free(blk); + } + extern_output_first = NULL; + extern_free_stack(); +} + +static void grow_extern_output(intnat required) +{ + struct output_block * blk; + intnat extra; + + if (extern_userprovided_output != NULL) { + extern_failwith("Marshal.to_buffer: buffer overflow"); + } + extern_output_block->end = extern_ptr; + if (required <= SIZE_EXTERN_OUTPUT_BLOCK / 2) + extra = 0; + else + extra = required; + blk = caml_stat_alloc_noexc(sizeof(struct output_block) + extra); + if (blk == NULL) extern_out_of_memory(); + extern_output_block->next = blk; + extern_output_block = blk; + extern_output_block->next = NULL; + extern_ptr = extern_output_block->data; + extern_limit = extern_output_block->data + SIZE_EXTERN_OUTPUT_BLOCK + extra; +} + +static intnat extern_output_length(void) +{ + struct output_block * blk; + intnat len; + + if (extern_userprovided_output != NULL) { + return extern_ptr - extern_userprovided_output; + } else { + for (len = 0, blk = extern_output_first; blk != NULL; blk = blk->next) + len += blk->end - blk->data; + return len; + } +} + +/* Exception raising, with cleanup */ + +static void extern_out_of_memory(void) +{ + extern_replay_trail(); + free_extern_output(); + caml_raise_out_of_memory(); +} + +static void extern_invalid_argument(char *msg) +{ + extern_replay_trail(); + free_extern_output(); + caml_invalid_argument(msg); +} + +static void extern_failwith(char *msg) +{ + extern_replay_trail(); + free_extern_output(); + caml_failwith(msg); +} + +static void extern_stack_overflow(void) +{ + caml_gc_message (0x04, "Stack overflow in marshaling value\n"); + extern_replay_trail(); + free_extern_output(); + caml_raise_out_of_memory(); +} + +/* Conversion to big-endian */ + +static inline void store16(char * dst, int n) +{ + dst[0] = n >> 8; dst[1] = n; +} + +static inline void store32(char * dst, intnat n) +{ + dst[0] = n >> 24; dst[1] = n >> 16; dst[2] = n >> 8; dst[3] = n; +} + +static inline void store64(char * dst, int64_t n) +{ + dst[0] = n >> 56; dst[1] = n >> 48; dst[2] = n >> 40; dst[3] = n >> 32; + dst[4] = n >> 24; dst[5] = n >> 16; dst[6] = n >> 8; dst[7] = n; +} + +/* Write characters, integers, and blocks in the output buffer */ + +static inline void write(int c) +{ + if (extern_ptr >= extern_limit) grow_extern_output(1); + *extern_ptr++ = c; +} + +static void writeblock(const char * data, intnat len) +{ + if (extern_ptr + len > extern_limit) grow_extern_output(len); + memcpy(extern_ptr, data, len); + extern_ptr += len; +} + +static inline void writeblock_float8(const double * data, intnat ndoubles) +{ +#if ARCH_FLOAT_ENDIANNESS == 0x01234567 || ARCH_FLOAT_ENDIANNESS == 0x76543210 + writeblock((const char *) data, ndoubles * 8); +#else + caml_serialize_block_float_8(data, ndoubles); +#endif +} + +static void writecode8(int code, intnat val) +{ + if (extern_ptr + 2 > extern_limit) grow_extern_output(2); + extern_ptr[0] = code; + extern_ptr[1] = val; + extern_ptr += 2; +} + +static void writecode16(int code, intnat val) +{ + if (extern_ptr + 3 > extern_limit) grow_extern_output(3); + extern_ptr[0] = code; + store16(extern_ptr + 1, (int) val); + extern_ptr += 3; +} + +static void writecode32(int code, intnat val) +{ + if (extern_ptr + 5 > extern_limit) grow_extern_output(5); + extern_ptr[0] = code; + store32(extern_ptr + 1, val); + extern_ptr += 5; +} + +#ifdef ARCH_SIXTYFOUR +static void writecode64(int code, intnat val) +{ + if (extern_ptr + 9 > extern_limit) grow_extern_output(9); + extern_ptr[0] = code; + store64(extern_ptr + 1, val); + extern_ptr += 9; +} +#endif + +/* Marshal the given value in the output buffer */ + +int caml_extern_allow_out_of_heap = 0; + +static void extern_rec(value v) +{ + struct code_fragment * cf; + struct extern_item * sp; + sp = extern_stack; + + while(1) { + if (Is_long(v)) { + intnat n = Long_val(v); + if (n >= 0 && n < 0x40) { + write(PREFIX_SMALL_INT + n); + } else if (n >= -(1 << 7) && n < (1 << 7)) { + writecode8(CODE_INT8, n); + } else if (n >= -(1 << 15) && n < (1 << 15)) { + writecode16(CODE_INT16, n); +#ifdef ARCH_SIXTYFOUR + } else if (n < -((intnat)1 << 30) || n >= ((intnat)1 << 30)) { + if (extern_flags & COMPAT_32) + extern_failwith("output_value: integer cannot be read back on " + "32-bit platform"); + writecode64(CODE_INT64, n); +#endif + } else + writecode32(CODE_INT32, n); + goto next_item; + } + if (Is_in_value_area(v) || caml_extern_allow_out_of_heap) { + header_t hd = Hd_val(v); + tag_t tag = Tag_hd(hd); + mlsize_t sz = Wosize_hd(hd); + + if (tag == Forward_tag) { + value f = Forward_val (v); + if (Is_block (f) + && (!Is_in_value_area(f) || Tag_val (f) == Forward_tag + || Tag_val (f) == Lazy_tag +#ifdef FLAT_FLOAT_ARRAY + || Tag_val (f) == Double_tag +#endif + )){ + /* Do not short-circuit the pointer. */ + }else{ + v = f; + continue; + } + } + /* Atoms are treated specially for two reasons: they are not allocated + in the externed block, and they are automatically shared. */ + if (sz == 0) { + if (tag < 16) { + write(PREFIX_SMALL_BLOCK + tag); + } else { +#ifdef WITH_PROFINFO + writecode32(CODE_BLOCK32, Hd_no_profinfo(hd)); +#else + writecode32(CODE_BLOCK32, hd); +#endif + } + goto next_item; + } + /* Check if already seen */ + if (Color_hd(hd) == Caml_blue) { + uintnat d = obj_counter - (uintnat) Field(v, 0); + if (d < 0x100) { + writecode8(CODE_SHARED8, d); + } else if (d < 0x10000) { + writecode16(CODE_SHARED16, d); +#ifdef ARCH_SIXTYFOUR + } else if (d >= (uintnat)1 << 32) { + writecode64(CODE_SHARED64, d); +#endif + } else { + writecode32(CODE_SHARED32, d); + } + goto next_item; + } + + /* Output the contents of the object */ + switch(tag) { + case String_tag: { + mlsize_t len = caml_string_length(v); + if (len < 0x20) { + write(PREFIX_SMALL_STRING + len); + } else if (len < 0x100) { + writecode8(CODE_STRING8, len); + } else { +#ifdef ARCH_SIXTYFOUR + if (len > 0xFFFFFB && (extern_flags & COMPAT_32)) + extern_failwith("output_value: string cannot be read back on " + "32-bit platform"); + if (len < (uintnat)1 << 32) + writecode32(CODE_STRING32, len); + else + writecode64(CODE_STRING64, len); +#else + writecode32(CODE_STRING32, len); +#endif + } + writeblock(String_val(v), len); + size_32 += 1 + (len + 4) / 4; + size_64 += 1 + (len + 8) / 8; + extern_record_location(v); + break; + } + case Double_tag: { + if (sizeof(double) != 8) + extern_invalid_argument("output_value: non-standard floats"); + write(CODE_DOUBLE_NATIVE); + writeblock_float8((double *) v, 1); + size_32 += 1 + 2; + size_64 += 1 + 1; + extern_record_location(v); + break; + } + case Double_array_tag: { + mlsize_t nfloats; + if (sizeof(double) != 8) + extern_invalid_argument("output_value: non-standard floats"); + nfloats = Wosize_val(v) / Double_wosize; + if (nfloats < 0x100) { + writecode8(CODE_DOUBLE_ARRAY8_NATIVE, nfloats); + } else { +#ifdef ARCH_SIXTYFOUR + if (nfloats > 0x1FFFFF && (extern_flags & COMPAT_32)) + extern_failwith("output_value: float array cannot be read back on " + "32-bit platform"); + if (nfloats < (uintnat) 1 << 32) + writecode32(CODE_DOUBLE_ARRAY32_NATIVE, nfloats); + else + writecode64(CODE_DOUBLE_ARRAY64_NATIVE, nfloats); +#else + writecode32(CODE_DOUBLE_ARRAY32_NATIVE, nfloats); +#endif + } + writeblock_float8((double *) v, nfloats); + size_32 += 1 + nfloats * 2; + size_64 += 1 + nfloats; + extern_record_location(v); + break; + } + case Abstract_tag: + extern_invalid_argument("output_value: abstract value (Abstract)"); + break; + case Infix_tag: + writecode32(CODE_INFIXPOINTER, Infix_offset_hd(hd)); + v = v - Infix_offset_hd(hd); /* PR#5772 */ + continue; + case Custom_tag: { + uintnat sz_32, sz_64; + char * size_header; + char * ident = Custom_ops_val(v)->identifier; + void (*serialize)(value v, uintnat * bsize_32, + uintnat * bsize_64) + = Custom_ops_val(v)->serialize; + const struct custom_fixed_length* fixed_length + = Custom_ops_val(v)->fixed_length; + if (serialize == NULL) + extern_invalid_argument("output_value: abstract value (Custom)"); + if (fixed_length == NULL) { + write(CODE_CUSTOM_LEN); + writeblock(ident, strlen(ident) + 1); + /* Reserve 12 bytes for the lengths (sz_32 and sz_64). */ + if (extern_ptr + 12 >= extern_limit) grow_extern_output(12); + size_header = extern_ptr; + extern_ptr += 12; + serialize(v, &sz_32, &sz_64); + /* Store length before serialized block */ + store32(size_header, sz_32); + store64(size_header + 4, sz_64); + } else { + write(CODE_CUSTOM_FIXED); + writeblock(ident, strlen(ident) + 1); + serialize(v, &sz_32, &sz_64); + if (sz_32 != fixed_length->bsize_32 || + sz_64 != fixed_length->bsize_64) + caml_fatal_error( + "output_value: incorrect fixed sizes specified by %s", + ident); + } + size_32 += 2 + ((sz_32 + 3) >> 2); /* header + ops + data */ + size_64 += 2 + ((sz_64 + 7) >> 3); + extern_record_location(v); + break; + } + default: { + value field0; + if (tag < 16 && sz < 8) { + write(PREFIX_SMALL_BLOCK + tag + (sz << 4)); + } else { +#ifdef ARCH_SIXTYFOUR +#ifdef WITH_PROFINFO + header_t hd_erased = Hd_no_profinfo(hd); +#else + header_t hd_erased = hd; +#endif + if (sz > 0x3FFFFF && (extern_flags & COMPAT_32)) + extern_failwith("output_value: array cannot be read back on " + "32-bit platform"); + if (hd_erased < (uintnat)1 << 32) + writecode32(CODE_BLOCK32, Whitehd_hd (hd_erased)); + else + writecode64(CODE_BLOCK64, Whitehd_hd (hd_erased)); +#else + writecode32(CODE_BLOCK32, Whitehd_hd (hd)); +#endif + } + size_32 += 1 + sz; + size_64 += 1 + sz; + field0 = Field(v, 0); + extern_record_location(v); + /* Remember that we still have to serialize fields 1 ... sz - 1 */ + if (sz > 1) { + sp++; + if (sp >= extern_stack_limit) sp = extern_resize_stack(sp); + sp->v = &Field(v,1); + sp->count = sz-1; + } + /* Continue serialization with the first field */ + v = field0; + continue; + } + } + } + else if ((cf = caml_extern_find_code((char *) v)) != NULL) { + if ((extern_flags & CLOSURES) == 0) + extern_invalid_argument("output_value: functional value"); + writecode32(CODE_CODEPOINTER, (char *) v - cf->code_start); + writeblock((const char *)cf->digest, 16); + } else { + extern_invalid_argument("output_value: abstract value (outside heap)"); + } + next_item: + /* Pop one more item to marshal, if any */ + if (sp == extern_stack) { + /* We are done. Cleanup the stack and leave the function */ + extern_free_stack(); + return; + } + v = *((sp->v)++); + if (--(sp->count) == 0) sp--; + } + /* Never reached as function leaves with return */ +} + +static int extern_flag_values[] = { NO_SHARING, CLOSURES, COMPAT_32 }; + +static intnat extern_value(value v, value flags, + /*out*/ char header[32], + /*out*/ int * header_len) +{ + intnat res_len; + /* Parse flag list */ + extern_flags = caml_convert_flag_list(flags, extern_flag_values); + /* Initializations */ + init_extern_trail(); + obj_counter = 0; + size_32 = 0; + size_64 = 0; + /* Marshal the object */ + extern_rec(v); + /* Record end of output */ + close_extern_output(); + /* Undo the modifications done on externed blocks */ + extern_replay_trail(); + /* Write the header */ + res_len = extern_output_length(); +#ifdef ARCH_SIXTYFOUR + if (res_len >= ((intnat)1 << 32) || + size_32 >= ((intnat)1 << 32) || size_64 >= ((intnat)1 << 32)) { + /* The object is too big for the small header format. + Fail if we are in compat32 mode, or use big header. */ + if (extern_flags & COMPAT_32) { + free_extern_output(); + caml_failwith("output_value: object too big to be read back on " + "32-bit platform"); + } + store32(header, Intext_magic_number_big); + store32(header + 4, 0); + store64(header + 8, res_len); + store64(header + 16, obj_counter); + store64(header + 24, size_64); + *header_len = 32; + return res_len; + } +#endif + /* Use the small header format */ + store32(header, Intext_magic_number_small); + store32(header + 4, res_len); + store32(header + 8, obj_counter); + store32(header + 12, size_32); + store32(header + 16, size_64); + *header_len = 20; + return res_len; +} + +void caml_output_val(struct channel *chan, value v, value flags) +{ + char header[32]; + int header_len; + struct output_block * blk, * nextblk; + + if (! caml_channel_binary_mode(chan)) + caml_failwith("output_value: not a binary channel"); + init_extern_output(); + extern_value(v, flags, header, &header_len); + /* During [caml_really_putblock], concurrent [caml_output_val] operations + can take place (via signal handlers or context switching in systhreads), + and [extern_output_first] may change. So, save it in a local variable. */ + blk = extern_output_first; + caml_really_putblock(chan, header, header_len); + while (blk != NULL) { + caml_really_putblock(chan, blk->data, blk->end - blk->data); + nextblk = blk->next; + caml_stat_free(blk); + blk = nextblk; + } +} + +CAMLprim value caml_output_value(value vchan, value v, value flags) +{ + CAMLparam3 (vchan, v, flags); + struct channel * channel = Channel(vchan); + + Lock(channel); + caml_output_val(channel, v, flags); + Unlock(channel); + CAMLreturn (Val_unit); +} + +CAMLprim value caml_output_value_to_bytes(value v, value flags) +{ + char header[32]; + int header_len; + intnat data_len, ofs; + value res; + struct output_block * blk, * nextblk; + + init_extern_output(); + data_len = extern_value(v, flags, header, &header_len); + /* PR#4030: it is prudent to save extern_output_first before allocating + the result, as in caml_output_val */ + blk = extern_output_first; + res = caml_alloc_string(header_len + data_len); + ofs = 0; + memcpy(&Byte(res, ofs), header, header_len); + ofs += header_len; + while (blk != NULL) { + int n = blk->end - blk->data; + memcpy(&Byte(res, ofs), blk->data, n); + ofs += n; + nextblk = blk->next; + caml_stat_free(blk); + blk = nextblk; + } + return res; +} + +CAMLprim value caml_output_value_to_string(value v, value flags) +{ + return caml_output_value_to_bytes(v,flags); +} + +CAMLexport intnat caml_output_value_to_block(value v, value flags, + char * buf, intnat len) +{ + char header[32]; + int header_len; + intnat data_len; + /* At this point we don't know the size of the header. + Guess that it is small, and fix up later if not. */ + extern_userprovided_output = buf + 20; + extern_ptr = extern_userprovided_output; + extern_limit = buf + len; + data_len = extern_value(v, flags, header, &header_len); + if (header_len != 20) { + /* Bad guess! Need to shift the output to make room for big header. + Make sure there is room. */ + if (header_len + data_len > len) + caml_failwith("Marshal.to_buffer: buffer overflow"); + memmove(buf + header_len, buf + 20, data_len); + } + memcpy(buf, header, header_len); + return header_len + data_len; +} + +CAMLprim value caml_output_value_to_buffer(value buf, value ofs, value len, + value v, value flags) +{ + intnat l = + caml_output_value_to_block(v, flags, + &Byte(buf, Long_val(ofs)), Long_val(len)); + return Val_long(l); +} + +CAMLexport void caml_output_value_to_malloc(value v, value flags, + /*out*/ char ** buf, + /*out*/ intnat * len) +{ + char header[32]; + int header_len; + intnat data_len; + char * res; + struct output_block * blk; + + init_extern_output(); + data_len = extern_value(v, flags, header, &header_len); + res = caml_stat_alloc_noexc(header_len + data_len); + if (res == NULL) extern_out_of_memory(); + *buf = res; + *len = header_len + data_len; + memcpy(res, header, header_len); + res += header_len; + for (blk = extern_output_first; blk != NULL; blk = blk->next) { + int n = blk->end - blk->data; + memcpy(res, blk->data, n); + res += n; + } + free_extern_output(); +} + +/* Functions for writing user-defined marshallers */ + +CAMLexport void caml_serialize_int_1(int i) +{ + if (extern_ptr + 1 > extern_limit) grow_extern_output(1); + extern_ptr[0] = i; + extern_ptr += 1; +} + +CAMLexport void caml_serialize_int_2(int i) +{ + if (extern_ptr + 2 > extern_limit) grow_extern_output(2); + store16(extern_ptr, i); + extern_ptr += 2; +} + +CAMLexport void caml_serialize_int_4(int32_t i) +{ + if (extern_ptr + 4 > extern_limit) grow_extern_output(4); + store32(extern_ptr, i); + extern_ptr += 4; +} + +CAMLexport void caml_serialize_int_8(int64_t i) +{ + if (extern_ptr + 8 > extern_limit) grow_extern_output(8); + store64(extern_ptr, i); + extern_ptr += 8; +} + +CAMLexport void caml_serialize_float_4(float f) +{ + caml_serialize_block_4(&f, 1); +} + +CAMLexport void caml_serialize_float_8(double f) +{ + caml_serialize_block_float_8(&f, 1); +} + +CAMLexport void caml_serialize_block_1(void * data, intnat len) +{ + if (extern_ptr + len > extern_limit) grow_extern_output(len); + memcpy(extern_ptr, data, len); + extern_ptr += len; +} + +CAMLexport void caml_serialize_block_2(void * data, intnat len) +{ + if (extern_ptr + 2 * len > extern_limit) grow_extern_output(2 * len); +#ifndef ARCH_BIG_ENDIAN + { + unsigned char * p; + char * q; + for (p = data, q = extern_ptr; len > 0; len--, p += 2, q += 2) + Reverse_16(q, p); + extern_ptr = q; + } +#else + memcpy(extern_ptr, data, len * 2); + extern_ptr += len * 2; +#endif +} + +CAMLexport void caml_serialize_block_4(void * data, intnat len) +{ + if (extern_ptr + 4 * len > extern_limit) grow_extern_output(4 * len); +#ifndef ARCH_BIG_ENDIAN + { + unsigned char * p; + char * q; + for (p = data, q = extern_ptr; len > 0; len--, p += 4, q += 4) + Reverse_32(q, p); + extern_ptr = q; + } +#else + memcpy(extern_ptr, data, len * 4); + extern_ptr += len * 4; +#endif +} + +CAMLexport void caml_serialize_block_8(void * data, intnat len) +{ + if (extern_ptr + 8 * len > extern_limit) grow_extern_output(8 * len); +#ifndef ARCH_BIG_ENDIAN + { + unsigned char * p; + char * q; + for (p = data, q = extern_ptr; len > 0; len--, p += 8, q += 8) + Reverse_64(q, p); + extern_ptr = q; + } +#else + memcpy(extern_ptr, data, len * 8); + extern_ptr += len * 8; +#endif +} + +CAMLexport void caml_serialize_block_float_8(void * data, intnat len) +{ + if (extern_ptr + 8 * len > extern_limit) grow_extern_output(8 * len); +#if ARCH_FLOAT_ENDIANNESS == 0x01234567 + memcpy(extern_ptr, data, len * 8); + extern_ptr += len * 8; +#elif ARCH_FLOAT_ENDIANNESS == 0x76543210 + { + unsigned char * p; + char * q; + for (p = data, q = extern_ptr; len > 0; len--, p += 8, q += 8) + Reverse_64(q, p); + extern_ptr = q; + } +#else + { + unsigned char * p; + char * q; + for (p = data, q = extern_ptr; len > 0; len--, p += 8, q += 8) + Permute_64(q, 0x01234567, p, ARCH_FLOAT_ENDIANNESS); + extern_ptr = q; + } +#endif +} + +/* Find where a code pointer comes from */ + +CAMLexport struct code_fragment * caml_extern_find_code(char *addr) +{ + int i; + for (i = caml_code_fragments_table.size - 1; i >= 0; i--) { + struct code_fragment * cf = caml_code_fragments_table.contents[i]; + if (! cf->digest_computed) { + caml_md5_block(cf->digest, cf->code_start, cf->code_end - cf->code_start); + cf->digest_computed = 1; + } + if (cf->code_start <= addr && addr < cf->code_end) return cf; + } + return NULL; +} diff --git a/runtime/fail_byt.c b/runtime/fail_byt.c new file mode 100644 index 00000000..9c8d6a45 --- /dev/null +++ b/runtime/fail_byt.c @@ -0,0 +1,204 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Raising exceptions from C. */ + +#include +#include +#include "caml/alloc.h" +#include "caml/fail.h" +#include "caml/io.h" +#include "caml/gc.h" +#include "caml/memory.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/printexc.h" +#include "caml/signals.h" +#include "caml/stacks.h" + +CAMLexport struct longjmp_buffer * caml_external_raise = NULL; +value caml_exn_bucket; + +CAMLexport void caml_raise(value v) +{ + Unlock_exn(); + caml_exn_bucket = v; + if (caml_external_raise == NULL) caml_fatal_uncaught_exception(v); + siglongjmp(caml_external_raise->buf, 1); +} + +CAMLexport void caml_raise_constant(value tag) +{ + caml_raise(tag); +} + +CAMLexport void caml_raise_with_arg(value tag, value arg) +{ + CAMLparam2 (tag, arg); + CAMLlocal1 (bucket); + + bucket = caml_alloc_small (2, 0); + Field(bucket, 0) = tag; + Field(bucket, 1) = arg; + caml_raise(bucket); + CAMLnoreturn; +} + +CAMLexport void caml_raise_with_args(value tag, int nargs, value args[]) +{ + CAMLparam1 (tag); + CAMLxparamN (args, nargs); + value bucket; + int i; + + CAMLassert(1 + nargs <= Max_young_wosize); + bucket = caml_alloc_small (1 + nargs, 0); + Field(bucket, 0) = tag; + for (i = 0; i < nargs; i++) Field(bucket, 1 + i) = args[i]; + caml_raise(bucket); + CAMLnoreturn; +} + +CAMLexport void caml_raise_with_string(value tag, char const *msg) +{ + CAMLparam1(tag); + value v_msg = caml_copy_string(msg); + caml_raise_with_arg(tag, v_msg); + CAMLnoreturn; +} + +/* PR#5115: Built-in exceptions can be triggered by input_value + while reading the initial value of [caml_global_data]. + + We check against this issue here in runtime/fail_byt.c instead of + runtime/intern.c. Having the check here means that these calls will + be slightly slower for all bytecode programs (not just the calls + coming from intern). Because intern.c is shared between the bytecode and + the native runtimes, putting checks there would slow do input_value for + natively-compiled programs that do not need these checks. +*/ +static void check_global_data(char const *exception_name) +{ + if (caml_global_data == 0) { + fprintf(stderr, "Fatal error: exception %s\n", exception_name); + exit(2); + } +} + +static void check_global_data_param(char const *exception_name, char const *msg) +{ + if (caml_global_data == 0) { + fprintf(stderr, "Fatal error: exception %s(\"%s\")\n", exception_name, msg); + exit(2); + } +} + +static inline value caml_get_failwith_tag (char const *msg) +{ + check_global_data_param("Failure", msg); + return Field(caml_global_data, FAILURE_EXN); +} + +CAMLexport void caml_failwith (char const *msg) +{ + caml_raise_with_string(caml_get_failwith_tag(msg), msg); +} + +CAMLexport void caml_failwith_value (value msg) +{ + CAMLparam1(msg); + value tag = caml_get_failwith_tag(String_val(msg)); + caml_raise_with_arg(tag, msg); + CAMLnoreturn; +} + +static inline value caml_get_invalid_argument_tag (char const *msg) +{ + check_global_data_param("Invalid_argument", msg); + return Field(caml_global_data, INVALID_EXN); +} + +CAMLexport void caml_invalid_argument (char const *msg) +{ + caml_raise_with_string(caml_get_invalid_argument_tag(msg), msg); +} + +CAMLexport void caml_invalid_argument_value (value msg) +{ + CAMLparam1(msg); + value tag = caml_get_invalid_argument_tag(String_val(msg)); + caml_raise_with_arg(tag, msg); + CAMLnoreturn; +} + +CAMLexport void caml_array_bound_error(void) +{ + caml_invalid_argument("index out of bounds"); +} + +CAMLexport void caml_raise_out_of_memory(void) +{ + check_global_data("Out_of_memory"); + caml_raise_constant(Field(caml_global_data, OUT_OF_MEMORY_EXN)); +} + +CAMLexport void caml_raise_stack_overflow(void) +{ + check_global_data("Stack_overflow"); + caml_raise_constant(Field(caml_global_data, STACK_OVERFLOW_EXN)); +} + +CAMLexport void caml_raise_sys_error(value msg) +{ + check_global_data_param("Sys_error", String_val(msg)); + caml_raise_with_arg(Field(caml_global_data, SYS_ERROR_EXN), msg); +} + +CAMLexport void caml_raise_end_of_file(void) +{ + check_global_data("End_of_file"); + caml_raise_constant(Field(caml_global_data, END_OF_FILE_EXN)); +} + +CAMLexport void caml_raise_zero_divide(void) +{ + check_global_data("Division_by_zero"); + caml_raise_constant(Field(caml_global_data, ZERO_DIVIDE_EXN)); +} + +CAMLexport void caml_raise_not_found(void) +{ + check_global_data("Not_found"); + caml_raise_constant(Field(caml_global_data, NOT_FOUND_EXN)); +} + +CAMLexport void caml_raise_sys_blocked_io(void) +{ + check_global_data("Sys_blocked_io"); + caml_raise_constant(Field(caml_global_data, SYS_BLOCKED_IO)); +} + +int caml_is_special_exception(value exn) { + /* this function is only used in caml_format_exception to produce + a more readable textual representation of some exceptions. It is + better to fall back to the general, less readable representation + than to abort with a fatal error as above. */ + if (caml_global_data == 0) return 0; + return exn == Field(caml_global_data, MATCH_FAILURE_EXN) + || exn == Field(caml_global_data, ASSERT_FAILURE_EXN) + || exn == Field(caml_global_data, UNDEFINED_RECURSIVE_MODULE_EXN); +} diff --git a/runtime/fail_nat.c b/runtime/fail_nat.c new file mode 100644 index 00000000..ec5bfebc --- /dev/null +++ b/runtime/fail_nat.c @@ -0,0 +1,192 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Raising exceptions from C. */ + +#include +#include +#include "caml/alloc.h" +#include "caml/fail.h" +#include "caml/io.h" +#include "caml/gc.h" +#include "caml/memory.h" +#include "caml/mlvalues.h" +#include "caml/printexc.h" +#include "caml/signals.h" +#include "caml/stack.h" +#include "caml/roots.h" +#include "caml/callback.h" + +/* The globals holding predefined exceptions */ + +typedef value caml_generated_constant[1]; + +extern caml_generated_constant + caml_exn_Out_of_memory, + caml_exn_Sys_error, + caml_exn_Failure, + caml_exn_Invalid_argument, + caml_exn_End_of_file, + caml_exn_Division_by_zero, + caml_exn_Not_found, + caml_exn_Match_failure, + caml_exn_Sys_blocked_io, + caml_exn_Stack_overflow, + caml_exn_Assert_failure, + caml_exn_Undefined_recursive_module; + +/* Exception raising */ + +CAMLnoreturn_start + extern void caml_raise_exception (value bucket) +CAMLnoreturn_end; + +char * caml_exception_pointer = NULL; + +void caml_raise(value v) +{ + Unlock_exn(); + if (caml_exception_pointer == NULL) caml_fatal_uncaught_exception(v); + + while (caml_local_roots != NULL && + (char *) caml_local_roots < caml_exception_pointer) { + caml_local_roots = caml_local_roots->next; + } + + caml_raise_exception(v); +} + +void caml_raise_constant(value tag) +{ + caml_raise(tag); +} + +void caml_raise_with_arg(value tag, value arg) +{ + CAMLparam2 (tag, arg); + CAMLlocal1 (bucket); + + bucket = caml_alloc_small (2, 0); + Field(bucket, 0) = tag; + Field(bucket, 1) = arg; + caml_raise(bucket); + CAMLnoreturn; +} + +void caml_raise_with_args(value tag, int nargs, value args[]) +{ + CAMLparam1 (tag); + CAMLxparamN (args, nargs); + value bucket; + int i; + + CAMLassert(1 + nargs <= Max_young_wosize); + bucket = caml_alloc_small (1 + nargs, 0); + Field(bucket, 0) = tag; + for (i = 0; i < nargs; i++) Field(bucket, 1 + i) = args[i]; + caml_raise(bucket); + CAMLnoreturn; +} + +void caml_raise_with_string(value tag, char const *msg) +{ + CAMLparam1(tag); + value v_msg = caml_copy_string(msg); + caml_raise_with_arg(tag, v_msg); + CAMLnoreturn; +} + +void caml_failwith (char const *msg) +{ + caml_raise_with_string((value) caml_exn_Failure, msg); +} + +void caml_failwith_value (value msg) +{ + caml_raise_with_arg((value) caml_exn_Failure, msg); +} + +void caml_invalid_argument (char const *msg) +{ + caml_raise_with_string((value) caml_exn_Invalid_argument, msg); +} + +void caml_invalid_argument_value (value msg) +{ + caml_raise_with_arg((value) caml_exn_Invalid_argument, msg); +} + +void caml_raise_out_of_memory(void) +{ + caml_raise_constant((value) caml_exn_Out_of_memory); +} + +void caml_raise_stack_overflow(void) +{ + caml_raise_constant((value) caml_exn_Stack_overflow); +} + +void caml_raise_sys_error(value msg) +{ + caml_raise_with_arg((value) caml_exn_Sys_error, msg); +} + +void caml_raise_end_of_file(void) +{ + caml_raise_constant((value) caml_exn_End_of_file); +} + +void caml_raise_zero_divide(void) +{ + caml_raise_constant((value) caml_exn_Division_by_zero); +} + +void caml_raise_not_found(void) +{ + caml_raise_constant((value) caml_exn_Not_found); +} + +void caml_raise_sys_blocked_io(void) +{ + caml_raise_constant((value) caml_exn_Sys_blocked_io); +} + +/* We use a pre-allocated exception because we can't + do a GC before the exception is raised (lack of stack descriptors + for the ccall to [caml_array_bound_error]). */ + +static value * caml_array_bound_error_exn = NULL; + +void caml_array_bound_error(void) +{ + if (caml_array_bound_error_exn == NULL) { + caml_array_bound_error_exn = + caml_named_value("Pervasives.array_bound_error"); + if (caml_array_bound_error_exn == NULL) { + fprintf(stderr, "Fatal error: exception " + "Invalid_argument(\"index out of bounds\")\n"); + exit(2); + } + } + caml_raise(*caml_array_bound_error_exn); +} + +int caml_is_special_exception(value exn) { + return exn == (value) caml_exn_Match_failure + || exn == (value) caml_exn_Assert_failure + || exn == (value) caml_exn_Undefined_recursive_module; +} diff --git a/byterun/finalise.c b/runtime/finalise.c similarity index 100% rename from byterun/finalise.c rename to runtime/finalise.c diff --git a/runtime/fix_code.c b/runtime/fix_code.c new file mode 100644 index 00000000..e55ac5c5 --- /dev/null +++ b/runtime/fix_code.c @@ -0,0 +1,195 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Handling of blocks of bytecode (endianness switch, threading). */ + +#include "caml/config.h" + +#ifdef HAS_UNISTD +#include +#else +#include +#endif + +#include "caml/debugger.h" +#include "caml/fix_code.h" +#include "caml/instruct.h" +#include "caml/intext.h" +#include "caml/md5.h" +#include "caml/memory.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/reverse.h" + +code_t caml_start_code; +asize_t caml_code_size; +unsigned char * caml_saved_code; +struct ext_table caml_code_fragments_table; + +/* Read the main bytecode block from a file */ + +void caml_init_code_fragments(void) { + struct code_fragment * cf; + /* Register the code in the table of code fragments */ + cf = caml_stat_alloc(sizeof(struct code_fragment)); + cf->code_start = (char *) caml_start_code; + cf->code_end = (char *) caml_start_code + caml_code_size; + caml_md5_block(cf->digest, caml_start_code, caml_code_size); + cf->digest_computed = 1; + caml_ext_table_init(&caml_code_fragments_table, 8); + caml_ext_table_add(&caml_code_fragments_table, cf); +} + +void caml_load_code(int fd, asize_t len) +{ + int i; + + caml_code_size = len; + caml_start_code = (code_t) caml_stat_alloc(caml_code_size); + if (read(fd, (char *) caml_start_code, caml_code_size) != caml_code_size) + caml_fatal_error("truncated bytecode file"); + caml_init_code_fragments(); + /* Prepare the code for execution */ +#ifdef ARCH_BIG_ENDIAN + caml_fixup_endianness(caml_start_code, caml_code_size); +#endif + if (caml_debugger_in_use) { + len /= sizeof(opcode_t); + caml_saved_code = (unsigned char *) caml_stat_alloc(len); + for (i = 0; i < len; i++) caml_saved_code[i] = caml_start_code[i]; + } +#ifdef THREADED_CODE + /* Better to thread now than at the beginning of [caml_interprete], + since the debugger interface needs to perform SET_EVENT requests + on the code. */ + caml_thread_code(caml_start_code, caml_code_size); +#endif +} + +/* This code is needed only if the processor is big endian */ + +#ifdef ARCH_BIG_ENDIAN + +void caml_fixup_endianness(code_t code, asize_t len) +{ + code_t p; + len /= sizeof(opcode_t); + for (p = code; p < code + len; p++) { + Reverse_32(p, p); + } +} + +#endif + +/* This code is needed only if we're using threaded code */ + +#ifdef THREADED_CODE + +char ** caml_instr_table; +char * caml_instr_base; + +static int* opcode_nargs = NULL; +int* caml_init_opcode_nargs(void) +{ + if( opcode_nargs == NULL ){ + int* l = (int*)caml_stat_alloc(sizeof(int) * FIRST_UNIMPLEMENTED_OP); + int i; + + for (i = 0; i < FIRST_UNIMPLEMENTED_OP; i++) { + l [i] = 0; + } + /* Instructions with one operand */ + l[PUSHACC] = l[ACC] = l[POP] = l[ASSIGN] = + l[PUSHENVACC] = l[ENVACC] = l[PUSH_RETADDR] = l[APPLY] = + l[APPTERM1] = l[APPTERM2] = l[APPTERM3] = l[RETURN] = + l[GRAB] = l[PUSHGETGLOBAL] = l[GETGLOBAL] = l[SETGLOBAL] = + l[PUSHATOM] = l[ATOM] = l[MAKEBLOCK1] = l[MAKEBLOCK2] = + l[MAKEBLOCK3] = l[MAKEFLOATBLOCK] = l[GETFIELD] = + l[GETFLOATFIELD] = l[SETFIELD] = l[SETFLOATFIELD] = + l[BRANCH] = l[BRANCHIF] = l[BRANCHIFNOT] = l[PUSHTRAP] = + l[C_CALL1] = l[C_CALL2] = l[C_CALL3] = l[C_CALL4] = l[C_CALL5] = + l[CONSTINT] = l[PUSHCONSTINT] = l[OFFSETINT] = + l[OFFSETREF] = l[OFFSETCLOSURE] = l[PUSHOFFSETCLOSURE] = 1; + + /* Instructions with two operands */ + l[APPTERM] = l[CLOSURE] = l[PUSHGETGLOBALFIELD] = + l[GETGLOBALFIELD] = l[MAKEBLOCK] = l[C_CALLN] = + l[BEQ] = l[BNEQ] = l[BLTINT] = l[BLEINT] = l[BGTINT] = l[BGEINT] = + l[BULTINT] = l[BUGEINT] = l[GETPUBMET] = 2; + + opcode_nargs = l; + } + return opcode_nargs; +} + +void caml_thread_code (code_t code, asize_t len) +{ + code_t p; + int* l = caml_init_opcode_nargs(); + len /= sizeof(opcode_t); + for (p = code; p < code + len; /*nothing*/) { + opcode_t instr = *p; + if (instr < 0 || instr >= FIRST_UNIMPLEMENTED_OP){ + /* FIXME -- should Assert(false) ? + caml_fatal_error ("in fix_code: bad opcode (%lx)", + (char *)(long)instr); + */ + instr = STOP; + } + *p++ = (opcode_t)(caml_instr_table[instr] - caml_instr_base); + if (instr == SWITCH) { + uint32_t sizes = *p++; + uint32_t const_size = sizes & 0xFFFF; + uint32_t block_size = sizes >> 16; + p += const_size + block_size; + } else if (instr == CLOSUREREC) { + uint32_t nfuncs = *p++; + p++; /* skip nvars */ + p += nfuncs; + } else { + p += l[instr]; + } + } + CAMLassert(p == code + len); +} + +#else + +int* caml_init_opcode_nargs() +{ + return NULL; +} + +#endif /* THREADED_CODE */ + +void caml_set_instruction(code_t pos, opcode_t instr) +{ +#ifdef THREADED_CODE + *pos = (opcode_t)(caml_instr_table[instr] - caml_instr_base); +#else + *pos = instr; +#endif +} + +int caml_is_instruction(opcode_t instr1, opcode_t instr2) +{ +#ifdef THREADED_CODE + return instr1 == (opcode_t)(caml_instr_table[instr2] - caml_instr_base); +#else + return instr1 == instr2; +#endif +} diff --git a/runtime/floats.c b/runtime/floats.c new file mode 100644 index 00000000..33bf14e8 --- /dev/null +++ b/runtime/floats.c @@ -0,0 +1,1094 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* The interface of this file is in "caml/mlvalues.h" and "caml/alloc.h" */ + +/* Needed for uselocale */ +#define _XOPEN_SOURCE 700 + +/* Needed for strtod_l */ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +#include "caml/alloc.h" +#include "caml/fail.h" +#include "caml/memory.h" +#include "caml/mlvalues.h" +#include "caml/misc.h" +#include "caml/reverse.h" +#include "caml/stacks.h" + +#if defined(HAS_LOCALE) || defined(__MINGW32__) + +#if defined(HAS_LOCALE_H) || defined(__MINGW32__) +#include +#endif + +#if defined(HAS_XLOCALE_H) +#include +#endif + +#if defined(_MSC_VER) +#ifndef locale_t +#define locale_t _locale_t +#endif +#ifndef freelocale +#define freelocale _free_locale +#endif +#ifndef strtod_l +#define strtod_l _strtod_l +#endif +#endif + +#endif /* defined(HAS_LOCALE) */ + +#ifdef _MSC_VER +#include +#ifndef isnan +#define isnan _isnan +#endif +#ifndef isfinite +#define isfinite _finite +#endif +#ifndef nextafter +#define nextafter _nextafter +#endif +#endif + +#ifdef ARCH_ALIGN_DOUBLE + +CAMLexport double caml_Double_val(value val) +{ + union { value v[2]; double d; } buffer; + + CAMLassert(sizeof(double) == 2 * sizeof(value)); + buffer.v[0] = Field(val, 0); + buffer.v[1] = Field(val, 1); + return buffer.d; +} + +CAMLexport void caml_Store_double_val(value val, double dbl) +{ + union { value v[2]; double d; } buffer; + + CAMLassert(sizeof(double) == 2 * sizeof(value)); + buffer.d = dbl; + Field(val, 0) = buffer.v[0]; + Field(val, 1) = buffer.v[1]; +} + +#endif + +/* + OCaml runtime itself doesn't call setlocale, i.e. it is using + standard "C" locale by default, but it is possible that + third-party code loaded into process does. +*/ +#ifdef HAS_LOCALE +locale_t caml_locale = (locale_t)0; +#endif + +#if defined(_MSC_VER) || defined(__MINGW32__) +/* there is no analogue to uselocale in MSVC so just set locale for thread */ +#define USE_LOCALE setlocale(LC_NUMERIC,"C") +#define RESTORE_LOCALE do {} while(0) +#elif defined(HAS_LOCALE) +#define USE_LOCALE locale_t saved_locale = uselocale(caml_locale) +#define RESTORE_LOCALE uselocale(saved_locale) +#else +#define USE_LOCALE do {} while(0) +#define RESTORE_LOCALE do {} while(0) +#endif + +void caml_init_locale(void) +{ +#if defined(_MSC_VER) || defined(__MINGW32__) + _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); +#endif +#ifdef HAS_LOCALE + if ((locale_t)0 == caml_locale) + { +#if defined(_MSC_VER) + caml_locale = _create_locale(LC_NUMERIC, "C"); +#else + caml_locale = newlocale(LC_NUMERIC_MASK,"C",(locale_t)0); +#endif + } +#endif +} + +void caml_free_locale(void) +{ +#ifdef HAS_LOCALE + if ((locale_t)0 != caml_locale) freelocale(caml_locale); + caml_locale = (locale_t)0; +#endif +} + +CAMLexport value caml_copy_double(double d) +{ + value res; + +#define Setup_for_gc +#define Restore_after_gc + Alloc_small(res, Double_wosize, Double_tag); +#undef Setup_for_gc +#undef Restore_after_gc + Store_double_val(res, d); + return res; +} + +#ifndef FLAT_FLOAT_ARRAY +CAMLexport void caml_Store_double_array_field(value val, mlsize_t i, double dbl) +{ + CAMLparam1 (val); + value d = caml_copy_double (dbl); + + CAMLassert (Tag_val (val) != Double_array_tag); + caml_modify (&Field(val, i), d); + CAMLreturn0; +} +#endif /* ! FLAT_FLOAT_ARRAY */ + +CAMLprim value caml_format_float(value fmt, value arg) +{ + value res; + double d = Double_val(arg); + +#ifdef HAS_BROKEN_PRINTF + if (isfinite(d)) { +#endif + USE_LOCALE; + res = caml_alloc_sprintf(String_val(fmt), d); + RESTORE_LOCALE; +#ifdef HAS_BROKEN_PRINTF + } else { + if (isnan(d)) { + res = caml_copy_string("nan"); + } else { + if (d > 0) + res = caml_copy_string("inf"); + else + res = caml_copy_string("-inf"); + } + } +#endif + return res; +} + +CAMLprim value caml_hexstring_of_float(value arg, value vprec, value vstyle) +{ + union { uint64_t i; double d; } u; + int sign, exp; + uint64_t m; + char buffer[64]; + char * buf, * p; + intnat prec; + int d; + value res; + + /* Allocate output buffer */ + prec = Long_val(vprec); + /* 12 chars for sign, 0x, decimal point, exponent */ + buf = (prec + 12 <= 64 ? buffer : caml_stat_alloc(prec + 12)); + /* Extract sign, mantissa, and exponent */ + u.d = Double_val(arg); + sign = u.i >> 63; + exp = (u.i >> 52) & 0x7FF; + m = u.i & (((uint64_t) 1 << 52) - 1); + /* Put sign */ + p = buf; + if (sign) { + *p++ = '-'; + } else { + switch (Int_val(vstyle)) { + case '+': *p++ = '+'; break; + case ' ': *p++ = ' '; break; + } + } + /* Treat special cases */ + if (exp == 0x7FF) { + char * txt; + if (m == 0) txt = "infinity"; else txt = "nan"; + memcpy(p, txt, strlen(txt)); + p[strlen(txt)] = 0; + res = caml_copy_string(buf); + } else { + /* Output "0x" prefix */ + *p++ = '0'; *p++ = 'x'; + /* Normalize exponent and mantissa */ + if (exp == 0) { + if (m != 0) exp = -1022; /* denormal */ + } else { + exp = exp - 1023; + m = m | ((uint64_t) 1 << 52); + } + /* If a precision is given, and is small, round mantissa accordingly */ + prec = Long_val(vprec); + if (prec >= 0 && prec < 13) { + int i = 52 - prec * 4; + uint64_t unit = (uint64_t) 1 << i; + uint64_t half = unit >> 1; + uint64_t mask = unit - 1; + uint64_t frac = m & mask; + m = m & ~mask; + /* Round to nearest, ties to even */ + if (frac > half || (frac == half && (m & unit) != 0)) { + m += unit; + } + } + /* Leading digit */ + d = m >> 52; + *p++ = (d < 10 ? d + '0' : d - 10 + 'a'); + m = (m << 4) & (((uint64_t) 1 << 56) - 1); + /* Fractional digits. If a precision is given, print that number of + digits. Otherwise, print as many digits as needed to represent + the mantissa exactly. */ + if (prec >= 0 ? prec > 0 : m != 0) { + *p++ = '.'; + while (prec >= 0 ? prec > 0 : m != 0) { + d = m >> 52; + *p++ = (d < 10 ? d + '0' : d - 10 + 'a'); + m = (m << 4) & (((uint64_t) 1 << 56) - 1); + prec--; + } + } + *p = 0; + /* Add exponent */ + res = caml_alloc_sprintf("%sp%+d", buf, exp); + } + if (buf != buffer) caml_stat_free(buf); + return res; +} + +static int caml_float_of_hex(const char * s, double * res) +{ + int64_t m = 0; /* the mantissa - top 60 bits at most */ + int n_bits = 0; /* total number of bits read */ + int m_bits = 0; /* number of bits in mantissa */ + int x_bits = 0; /* number of bits after mantissa */ + int dec_point = -1; /* bit count corresponding to decimal point */ + /* -1 if no decimal point seen */ + int exp = 0; /* exponent */ + char * p; /* for converting the exponent */ + double f; + + while (*s != 0) { + char c = *s++; + switch (c) { + case '_': + break; + case '.': + if (dec_point >= 0) return -1; /* multiple decimal points */ + dec_point = n_bits; + break; + case 'p': case 'P': { + long e; + if (*s == 0) return -1; /* nothing after exponent mark */ + e = strtol(s, &p, 10); + if (*p != 0) return -1; /* ill-formed exponent */ + /* Handle exponents larger than int by returning 0/infinity directly. + Mind that INT_MIN/INT_MAX are included in the test so as to capture + the overflow case of strtol on Win64 -- long and int have the same + size there. */ + if (e <= INT_MIN) { + *res = 0.; + return 0; + } + else if (e >= INT_MAX) { + *res = m == 0 ? 0. : HUGE_VAL; + return 0; + } + /* regular exponent value */ + exp = e; + s = p; /* stop at next loop iteration */ + break; + } + default: { /* Nonzero digit */ + int d; + if (c >= '0' && c <= '9') d = c - '0'; + else if (c >= 'A' && c <= 'F') d = c - 'A' + 10; + else if (c >= 'a' && c <= 'f') d = c - 'a' + 10; + else return -1; /* bad digit */ + n_bits += 4; + if (d == 0 && m == 0) break; /* leading zeros are skipped */ + if (m_bits < 60) { + /* There is still room in m. Add this digit to the mantissa. */ + m = (m << 4) + d; + m_bits += 4; + } else { + /* We've already collected 60 significant bits in m. + Now all we care about is whether there is a nonzero bit + after. In this case, round m to odd so that the later + rounding of m to FP produces the correct result. */ + if (d != 0) m |= 1; /* round to odd */ + x_bits += 4; + } + break; + } + } + } + if (n_bits == 0) return -1; + /* Convert mantissa to FP. We use a signed conversion because we can + (m has 60 bits at most) and because it is faster + on several architectures. */ + f = (double) (int64_t) m; + /* Adjust exponent to take decimal point and extra digits into account */ + { + int adj = x_bits; + if (dec_point >= 0) adj = adj + (dec_point - n_bits); + /* saturated addition exp + adj */ + if (adj > 0 && exp > INT_MAX - adj) + exp = INT_MAX; + else if (adj < 0 && exp < INT_MIN - adj) + exp = INT_MIN; + else + exp = exp + adj; + } + /* Apply exponent if needed */ + if (exp != 0) f = ldexp(f, exp); + /* Done! */ + *res = f; + return 0; +} + +CAMLprim value caml_float_of_string(value vs) +{ + char parse_buffer[64]; + char * buf, * dst, * end; + const char *src; + mlsize_t len; + int sign; + double d; + + /* Check for hexadecimal FP constant */ + src = String_val(vs); + sign = 1; + if (*src == '-') { sign = -1; src++; } + else if (*src == '+') { src++; }; + if (src[0] == '0' && (src[1] == 'x' || src[1] == 'X')) { + if (caml_float_of_hex(src + 2, &d) == -1) + caml_failwith("float_of_string"); + return caml_copy_double(sign < 0 ? -d : d); + } + /* Remove '_' characters before calling strtod () */ + len = caml_string_length(vs); + buf = len < sizeof(parse_buffer) ? parse_buffer : caml_stat_alloc(len + 1); + src = String_val(vs); + dst = buf; + while (len--) { + char c = *src++; + if (c != '_') *dst++ = c; + } + *dst = 0; + if (dst == buf) goto error; +#if defined(HAS_STRTOD_L) && defined(HAS_LOCALE) + d = strtod_l((const char *) buf, &end, caml_locale); +#else + USE_LOCALE; + /* Convert using strtod */ + d = strtod((const char *) buf, &end); + RESTORE_LOCALE; +#endif /* HAS_STRTOD_L */ + if (end != dst) goto error; + if (buf != parse_buffer) caml_stat_free(buf); + return caml_copy_double(d); + error: + if (buf != parse_buffer) caml_stat_free(buf); + caml_failwith("float_of_string"); + return Val_unit; /* not reached */ +} + +CAMLprim value caml_int_of_float(value f) +{ + return Val_long((intnat) Double_val(f)); +} + +CAMLprim value caml_float_of_int(value n) +{ + return caml_copy_double((double) Long_val(n)); +} + +CAMLprim value caml_neg_float(value f) +{ + return caml_copy_double(- Double_val(f)); +} + +CAMLprim value caml_abs_float(value f) +{ + return caml_copy_double(fabs(Double_val(f))); +} + +CAMLprim value caml_add_float(value f, value g) +{ + return caml_copy_double(Double_val(f) + Double_val(g)); +} + +CAMLprim value caml_sub_float(value f, value g) +{ + return caml_copy_double(Double_val(f) - Double_val(g)); +} + +CAMLprim value caml_mul_float(value f, value g) +{ + return caml_copy_double(Double_val(f) * Double_val(g)); +} + +CAMLprim value caml_div_float(value f, value g) +{ + return caml_copy_double(Double_val(f) / Double_val(g)); +} + +CAMLprim value caml_exp_float(value f) +{ + return caml_copy_double(exp(Double_val(f))); +} + +CAMLexport double caml_trunc(double x) +{ +#ifdef HAS_C99_FLOAT_OPS + return trunc(x); +#else + return (x >= 0.0)? floor(x) : ceil(x); +#endif +} + +CAMLprim value caml_trunc_float(value f) +{ + return caml_copy_double(caml_trunc(Double_val(f))); +} + +CAMLexport double caml_round(double f) +{ +#ifdef HAS_C99_FLOAT_OPS + return round(f); +#else + union { uint64_t i; double d; } u, pred_one_half; /* predecessor of 0.5 */ + int e; /* exponent */ + u.d = f; + e = (u.i >> 52) & 0x7ff; /* - 0x3ff for the actual exponent */ + pred_one_half.i = 0x3FDFFFFFFFFFFFFF; /* 0x1.FFFFFFFFFFFFFp-2 */ + + if (isfinite(f) && f != 0.) { + if (e >= 52 + 0x3ff) return f; /* f is an integer already */ + if (f > 0.0) + /* If we added 0.5 instead of its predecessor, then the + predecessor of 0.5 would be rounded to 1. instead of 0. */ + return floor(f + pred_one_half.d); + else + return ceil(f - pred_one_half.d); + } + else + return f; +#endif +} + +CAMLprim value caml_round_float(value f) +{ + return caml_copy_double(caml_round(Double_val(f))); +} + +CAMLprim value caml_floor_float(value f) +{ + return caml_copy_double(floor(Double_val(f))); +} + +CAMLexport double caml_nextafter(double x, double y) +{ + return nextafter(x, y); +} + +CAMLprim value caml_nextafter_float(value x, value y) +{ + return caml_copy_double(caml_nextafter(Double_val(x), Double_val(y))); +} + +#ifndef HAS_WORKING_FMA +union double_as_int64 { double d; uint64_t i; }; +#define IEEE754_DOUBLE_BIAS 0x3ff +#define IEEE_EXPONENT(N) (((N) >> 52) & 0x7ff) +#define IEEE_NEGATIVE(N) ((N) >> 63) +//C99 hexa float literals cannot be used, use pow() instead. +#define FL53 (pow(2,53)) //0x1p53 +#define FLM53 (pow(2,-53)) //0x1p-53 +#define FL54 (pow(2,54)) //0x1p54 +#define FLM54 (pow(2,-54)) //0x1p-54 +#define FL108 (pow(2,108)) //0x1p108 +#define FLM108 (pow(2,-108)) //0x1p-108 +#define FLM1074 (pow(2,-1074)) //0x1p-1074 +#endif + +CAMLexport double caml_fma(double x, double y, double z) +{ +#ifdef HAS_WORKING_FMA + return fma(x, y, z); +#else // Emulation of FMA, from S. Boldo and G. Melquiond, "Emulation + // of a FMA and Correctly Rounded Sums: Proved Algorithms Using + // Rounding to Odd," in IEEE Transactions on Computers, vol. 57, + // no. 4, pp. 462-471, April 2008. Special cases implementation + // comes from glibc's IEEE754 FMA emulation. + // Only valid for double precision and round-to-nearest mode. + + union double_as_int64 u, v, w; + union double_as_int64 ora; + double mh, ml, xh, xl, yh, yl, t; + double ah, al; + double orah, oral; + double t1, t2; + double tiny; + int neg, adjust = 0; + u.d = x; + v.d = y; + w.d = z; + + if ( IEEE_EXPONENT(u.i) + IEEE_EXPONENT(v.i) >= 0x7FF + + IEEE754_DOUBLE_BIAS - DBL_MANT_DIG + || IEEE_EXPONENT(u.i) >= 0x7ff - DBL_MANT_DIG + || IEEE_EXPONENT(v.i) >= 0x7ff - DBL_MANT_DIG + || IEEE_EXPONENT(w.i) >= 0x7ff - DBL_MANT_DIG + || IEEE_EXPONENT(u.i) + IEEE_EXPONENT(v.i) <= + IEEE754_DOUBLE_BIAS + DBL_MANT_DIG ) + { + /* If z is Inf, but x and y are finite, the result should be z + * rather than NaN. */ + if (IEEE_EXPONENT(w.i) == 0x7ff && + IEEE_EXPONENT(u.i) != 0x7ff && + IEEE_EXPONENT(v.i) != 0x7ff) + return (z + x) + y; + /* If z is zero and x and y are nonzero, compute the result as + x * y to avoid the wrong sign of a zero result if x * y + underflows to 0. */ + if (z == 0 && x != 0 && y != 0) + return x * y; + /* If x or y or z is Inf/NaN, or if x * y is zero, compute as + x * y + z. */ + if (IEEE_EXPONENT(u.i) == 0x7ff + || IEEE_EXPONENT(v.i) == 0x7ff + || IEEE_EXPONENT(w.i) == 0x7ff + || x == 0 + || y == 0) + return x * y + z; + /* If fma will certainly overflow, compute as x * y. */ + if ((IEEE_EXPONENT(u.i) + IEEE_EXPONENT(v.i)) + > 0x7ff + IEEE754_DOUBLE_BIAS) + return x * y; + /* If x * y is less than 1/4 of DBL_TRUE_MIN, neither the result + nor whether there is underflow depends on its exact value, + only on its sign. */ + if (IEEE_EXPONENT(u.i) + IEEE_EXPONENT(v.i) + < IEEE754_DOUBLE_BIAS - DBL_MANT_DIG - 2) + { + neg = IEEE_NEGATIVE(u.i) ^ IEEE_NEGATIVE(v.i) ; + tiny = neg ? -FLM1074 : FLM1074; + if (IEEE_EXPONENT(w.i) >= 3) + return tiny + z; + /* Scaling up, adding TINY and scaling down produces the + correct result, because in round-to-nearest mode adding + TINY has no effect and in other modes double rounding is + harmless. But it may not produce required underflow + exceptions. */ + v.d = z * FL54 + tiny; + return v.d * FLM54; + } + if (IEEE_EXPONENT(u.i) + IEEE_EXPONENT(v.i) + >= 0x7ff + IEEE754_DOUBLE_BIAS - DBL_MANT_DIG) + { + /* Compute 1p-53 times smaller result and multiply at the + end. */ + if (IEEE_EXPONENT(u.i) > IEEE_EXPONENT(v.i)) + x *= FLM53; + else + y *= FLM53; + /* If x + y exponent is very large and z exponent is very small, + it doesn't matter if we don't adjust it. */ + if (IEEE_EXPONENT(w.i) > DBL_MANT_DIG) + z *= FLM53; + adjust = 1; + } + else if (IEEE_EXPONENT(w.i) >= 0x7ff - DBL_MANT_DIG) + { + /* Similarly. If z exponent is very large and x and y + exponents are very small, adjust them up to avoid + spurious underflows, rather than down. */ + if (IEEE_EXPONENT(u.i) + IEEE_EXPONENT(v.i) + <= IEEE754_DOUBLE_BIAS + 2 * DBL_MANT_DIG) + { + if (IEEE_EXPONENT(u.i) > IEEE_EXPONENT(v.i)) + x *= FL108; + else + y *= FL108; + } + else if (IEEE_EXPONENT(u.i) > IEEE_EXPONENT(v.i)) + { + if (IEEE_EXPONENT(u.i) > DBL_MANT_DIG) + x *= FLM53; + } + else if (IEEE_EXPONENT(v.i) > DBL_MANT_DIG) + y *= FLM53; + z *= FLM53; + adjust = 1; + } + else if (IEEE_EXPONENT(u.i) >= 0x7ff - DBL_MANT_DIG) + { + x *= FLM53; + y *= FL53; + } + else if (IEEE_EXPONENT(v.i) >= 0x7ff - DBL_MANT_DIG) + { + y *= FLM53; + x *= FL53; + } + else /* if (IEEE_EXPONENT(u.i) + IEEE_EXPONENT(v.i) <= + IEEE754_DOUBLE_BIAS + DBL_MANT_DIG) */ + { + if (IEEE_EXPONENT(u.i) > IEEE_EXPONENT(v.i)) + x *= FL108; + else + y *= FL108; + if (IEEE_EXPONENT(w.i) <= 4 * DBL_MANT_DIG + 6) + { + z *= FL108; + adjust = -1; + } + } + } + + /* Ensure correct sign of exact 0 + 0. */ + if ((x == 0 || y == 0) && z == 0) + return x * y + z; + + // Error-free multiplication: mh + ml = x * y + mh = x * y; + t = x * 134217729.0; + xh = t - (t - x); + xl = x - xh; + t = y * 134217729.0; + yh = t - (t - y); + yl = y - yh; + ml = xl * yl - (((mh - xh * yh) - xl * yh) - xh * yl); + // Error-free addition: ah + al = z + mh + ah = z + mh; + t = ah - z; + al = (z - (ah - t)) + (mh - t); + + /* If the result is an exact zero, ensure it has the correct sign. */ + if (ah == 0 && ml == 0) + return z + mh; + + // Normalize ah, al, ml. + t1 = al + ml; + t = t1 - al; + t2 = (al - (t1 - t)) + (ml - t); + al = t1; + ml = t2; + t1 = ah + al; + t = t1 - ah; + t2 = (ah - (t1 - t)) + (al - t); + ah = t1; + al = t2; + + // Odd-rounded addition: ora = al + ml. + orah = al + ml; + oral = (al - orah) + ml; + + if ( oral != 0.0 ) + { + ora.d = orah; + if ( !(ora.i & 1) ) + { + if ( (oral > 0.0) ^ (orah < 0.0) ) + ora.i++; + else + ora.i--; + orah = ora.d; + } + } + + // Rounded addition: ra = ah + orah. + if ( adjust > 0 ) + return (ah + orah) * FL53; + else if ( adjust < 0 ) + return (ah + orah) * FLM108; + else + return ah + orah; +#endif +} + +CAMLprim value caml_fma_float(value f1, value f2, value f3) +{ + return caml_copy_double(caml_fma(Double_val(f1), + Double_val(f2), Double_val(f3))); +} + +CAMLprim value caml_fmod_float(value f1, value f2) +{ + return caml_copy_double(fmod(Double_val(f1), Double_val(f2))); +} + +CAMLprim value caml_frexp_float(value f) +{ + CAMLparam1 (f); + CAMLlocal2 (res, mantissa); + int exponent; + + mantissa = caml_copy_double(frexp (Double_val(f), &exponent)); + res = caml_alloc_tuple(2); + Field(res, 0) = mantissa; + Field(res, 1) = Val_int(exponent); + CAMLreturn (res); +} + +// Seems dumb but intnat could not correspond to int type. +double caml_ldexp_float_unboxed(double f, intnat i) +{ + return ldexp(f, (int) i); +} + + +CAMLprim value caml_ldexp_float(value f, value i) +{ + return caml_copy_double(ldexp(Double_val(f), Int_val(i))); +} + +CAMLprim value caml_log_float(value f) +{ + return caml_copy_double(log(Double_val(f))); +} + +CAMLprim value caml_log10_float(value f) +{ + return caml_copy_double(log10(Double_val(f))); +} + +CAMLprim value caml_modf_float(value f) +{ + double frem; + + CAMLparam1 (f); + CAMLlocal3 (res, quo, rem); + + quo = caml_copy_double(modf (Double_val(f), &frem)); + rem = caml_copy_double(frem); + res = caml_alloc_tuple(2); + Field(res, 0) = quo; + Field(res, 1) = rem; + CAMLreturn (res); +} + +CAMLprim value caml_sqrt_float(value f) +{ + return caml_copy_double(sqrt(Double_val(f))); +} + +CAMLprim value caml_power_float(value f, value g) +{ + return caml_copy_double(pow(Double_val(f), Double_val(g))); +} + +CAMLprim value caml_sin_float(value f) +{ + return caml_copy_double(sin(Double_val(f))); +} + +CAMLprim value caml_sinh_float(value f) +{ + return caml_copy_double(sinh(Double_val(f))); +} + +CAMLprim value caml_cos_float(value f) +{ + return caml_copy_double(cos(Double_val(f))); +} + +CAMLprim value caml_cosh_float(value f) +{ + return caml_copy_double(cosh(Double_val(f))); +} + +CAMLprim value caml_tan_float(value f) +{ + return caml_copy_double(tan(Double_val(f))); +} + +CAMLprim value caml_tanh_float(value f) +{ + return caml_copy_double(tanh(Double_val(f))); +} + +CAMLprim value caml_asin_float(value f) +{ + return caml_copy_double(asin(Double_val(f))); +} + +CAMLprim value caml_acos_float(value f) +{ + return caml_copy_double(acos(Double_val(f))); +} + +CAMLprim value caml_atan_float(value f) +{ + return caml_copy_double(atan(Double_val(f))); +} + +CAMLprim value caml_atan2_float(value f, value g) +{ + return caml_copy_double(atan2(Double_val(f), Double_val(g))); +} + +CAMLprim value caml_ceil_float(value f) +{ + return caml_copy_double(ceil(Double_val(f))); +} + +CAMLexport double caml_hypot(double x, double y) +{ +#ifdef HAS_C99_FLOAT_OPS + return hypot(x, y); +#else + double tmp, ratio; + x = fabs(x); y = fabs(y); + if (x != x) /* x is NaN */ + return y > DBL_MAX ? y : x; /* PR#6321 */ + if (y != y) /* y is NaN */ + return x > DBL_MAX ? x : y; /* PR#6321 */ + if (x < y) { tmp = x; x = y; y = tmp; } + if (x == 0.0) return 0.0; + ratio = y / x; + return x * sqrt(1.0 + ratio * ratio); +#endif +} + +CAMLprim value caml_hypot_float(value f, value g) +{ + return caml_copy_double(caml_hypot(Double_val(f), Double_val(g))); +} + +/* These emulations of expm1() and log1p() are due to William Kahan. + See http://www.plunk.org/~hatch/rightway.php */ +CAMLexport double caml_expm1(double x) +{ +#ifdef HAS_C99_FLOAT_OPS + return expm1(x); +#else + double u = exp(x); + if (u == 1.) + return x; + if (u - 1. == -1.) + return -1.; + return (u - 1.) * x / log(u); +#endif +} + +CAMLexport double caml_log1p(double x) +{ +#ifdef HAS_C99_FLOAT_OPS + return log1p(x); +#else + double u = 1. + x; + if (u == 1.) + return x; + else + return log(u) * x / (u - 1.); +#endif +} + +CAMLprim value caml_expm1_float(value f) +{ + return caml_copy_double(caml_expm1(Double_val(f))); +} + +CAMLprim value caml_log1p_float(value f) +{ + return caml_copy_double(caml_log1p(Double_val(f))); +} + +union double_as_two_int32 { + double d; +#if defined(ARCH_BIG_ENDIAN) || (defined(__arm__) && !defined(__ARM_EABI__)) + struct { uint32_t h; uint32_t l; } i; +#else + struct { uint32_t l; uint32_t h; } i; +#endif +}; + +CAMLexport double caml_copysign(double x, double y) +{ +#ifdef HAS_C99_FLOAT_OPS + return copysign(x, y); +#else + union double_as_two_int32 ux, uy; + ux.d = x; + uy.d = y; + ux.i.h &= 0x7FFFFFFFU; + ux.i.h |= (uy.i.h & 0x80000000U); + return ux.d; +#endif +} + +CAMLprim value caml_copysign_float(value f, value g) +{ + return caml_copy_double(caml_copysign(Double_val(f), Double_val(g))); +} + +CAMLprim value caml_signbit(double x) +{ +#ifdef HAS_C99_FLOAT_OPS + return Val_bool(signbit(x)); +#else + union double_as_two_int32 ux; + ux.d = x; + return Val_bool(ux.i.h >> 31); +#endif +} + +CAMLprim value caml_signbit_float(value f) +{ + return caml_signbit(Double_val(f)); +} + +#ifdef LACKS_SANE_NAN + +CAMLprim value caml_neq_float(value vf, value vg) +{ + double f = Double_val(vf); + double g = Double_val(vg); + return Val_bool(isnan(f) || isnan(g) || f != g); +} + +#define DEFINE_NAN_CMP(op) (value vf, value vg) \ +{ \ + double f = Double_val(vf); \ + double g = Double_val(vg); \ + return Val_bool(!isnan(f) && !isnan(g) && f op g); \ +} + +intnat caml_float_compare_unboxed(double f, double g) +{ + /* Insane => nan == everything && nan < everything && nan > everything */ + if (isnan(f) && isnan(g)) return 0; + if (!isnan(g) && f < g) return -1; + if (f != g) return 1; + return 0; +} + +#else + +CAMLprim value caml_neq_float(value f, value g) +{ + return Val_bool(Double_val(f) != Double_val(g)); +} + +#define DEFINE_NAN_CMP(op) (value f, value g) \ +{ \ + return Val_bool(Double_val(f) op Double_val(g)); \ +} + +intnat caml_float_compare_unboxed(double f, double g) +{ + /* If one or both of f and g is NaN, order according to the convention + NaN = NaN and NaN < x for all other floats x. */ + /* This branchless implementation is from GPR#164. + Note that [f == f] if and only if f is not NaN. */ + return (f > g) - (f < g) + (f == f) - (g == g); +} + +#endif + +CAMLprim value caml_eq_float DEFINE_NAN_CMP(==) +CAMLprim value caml_le_float DEFINE_NAN_CMP(<=) +CAMLprim value caml_lt_float DEFINE_NAN_CMP(<) +CAMLprim value caml_ge_float DEFINE_NAN_CMP(>=) +CAMLprim value caml_gt_float DEFINE_NAN_CMP(>) + +CAMLprim value caml_float_compare(value vf, value vg) +{ + return Val_int(caml_float_compare_unboxed(Double_val(vf),Double_val(vg))); +} + +enum { FP_normal, FP_subnormal, FP_zero, FP_infinite, FP_nan }; + +value caml_classify_float_unboxed(double vd) +{ +#ifdef ARCH_SIXTYFOUR + union { double d; uint64_t i; } u; + uint64_t n; + uint32_t e; + + u.d = vd; + n = u.i << 1; /* shift sign bit off */ + if (n == 0) return Val_int(FP_zero); + e = n >> 53; /* extract exponent */ + if (e == 0) return Val_int(FP_subnormal); + if (e == 0x7FF) { + if (n << 11 == 0) /* shift exponent off */ + return Val_int(FP_infinite); + else + return Val_int(FP_nan); + } + return Val_int(FP_normal); +#else + union double_as_two_int32 u; + uint32_t h, l; + + u.d = vd; + h = u.i.h; l = u.i.l; + l = l | (h & 0xFFFFF); + h = h & 0x7FF00000; + if ((h | l) == 0) + return Val_int(FP_zero); + if (h == 0) + return Val_int(FP_subnormal); + if (h == 0x7FF00000) { + if (l == 0) + return Val_int(FP_infinite); + else + return Val_int(FP_nan); + } + return Val_int(FP_normal); +#endif +} + +CAMLprim value caml_classify_float(value vd) +{ + return caml_classify_float_unboxed(Double_val(vd)); +} + +/* The [caml_init_ieee_float] function should initialize floating-point hardware + so that it behaves as much as possible like the IEEE standard. + In particular, return special numbers like Infinity and NaN instead + of signalling exceptions. Currently, everyone is in IEEE mode + at program startup, except FreeBSD prior to 4.0R. */ + +#ifdef __FreeBSD__ +#include +#if (__FreeBSD_version < 400017) +#include +#endif +#endif + +void caml_init_ieee_floats(void) +{ +#if defined(__FreeBSD__) && (__FreeBSD_version < 400017) + fpsetmask(0); +#endif +} diff --git a/runtime/freelist.c b/runtime/freelist.c new file mode 100644 index 00000000..fbd23324 --- /dev/null +++ b/runtime/freelist.c @@ -0,0 +1,623 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +#define FREELIST_DEBUG 0 +#if FREELIST_DEBUG +#include +#endif + +#include + +#include "caml/config.h" +#include "caml/freelist.h" +#include "caml/gc.h" +#include "caml/gc_ctrl.h" +#include "caml/memory.h" +#include "caml/major_gc.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" + +/* The free-list is kept sorted by increasing addresses. + This makes the merging of adjacent free blocks possible. + (See [caml_fl_merge_block].) +*/ + +/* A free list block is a [value] (integer representing a pointer to the + first word after the block's header). The end of the list is NULL. */ +#define Val_NULL ((value) NULL) + +/* The sentinel can be located anywhere in memory, but it must not be + adjacent to any heap object. */ +static struct { + value filler1; /* Make sure the sentinel is never adjacent to any block. */ + header_t h; + value first_field; + value filler2; /* Make sure the sentinel is never adjacent to any block. */ +} sentinel = {0, Make_header (0, 0, Caml_blue), Val_NULL, 0}; + +#define Fl_head (Val_bp (&(sentinel.first_field))) +static value fl_prev = Fl_head; /* Current allocation pointer. */ +static value fl_last = Val_NULL; /* Last block in the list. Only valid + just after [caml_fl_allocate] returns NULL. */ +value caml_fl_merge = Fl_head; /* Current insertion pointer. Managed + jointly with [sweep_slice]. */ +asize_t caml_fl_cur_wsz = 0; /* Number of words in the free list, + including headers but not fragments. */ + +#define FLP_MAX 1000 +static value flp [FLP_MAX]; +static int flp_size = 0; +static value beyond = Val_NULL; + +#define Next(b) (Field (b, 0)) + +#define Policy_next_fit 0 +#define Policy_first_fit 1 +uintnat caml_allocation_policy = Policy_next_fit; +#define policy caml_allocation_policy + +#ifdef DEBUG +static void fl_check (void) +{ + value cur, prev; + int prev_found = 0, flp_found = 0, merge_found = 0; + uintnat size_found = 0; + int sz = 0; + + prev = Fl_head; + cur = Next (prev); + while (cur != Val_NULL){ + size_found += Whsize_bp (cur); + CAMLassert (Is_in_heap (cur)); + if (cur == fl_prev) prev_found = 1; + if (policy == Policy_first_fit && Wosize_bp (cur) > sz){ + sz = Wosize_bp (cur); + if (flp_found < flp_size){ + CAMLassert (Next (flp[flp_found]) == cur); + ++ flp_found; + }else{ + CAMLassert (beyond == Val_NULL + || Bp_val (cur) >= Bp_val (Next (beyond))); + } + } + if (cur == caml_fl_merge) merge_found = 1; + prev = cur; + cur = Next (prev); + } + if (policy == Policy_next_fit) CAMLassert (prev_found || fl_prev == Fl_head); + if (policy == Policy_first_fit) CAMLassert (flp_found == flp_size); + CAMLassert (merge_found || caml_fl_merge == Fl_head); + CAMLassert (size_found == caml_fl_cur_wsz); +} + +#endif + +/* [allocate_block] is called by [caml_fl_allocate]. Given a suitable free + block and the requested size, it allocates a new block from the free + block. There are three cases: + 0. The free block has the requested size. Detach the block from the + free-list and return it. + 1. The free block is 1 word longer than the requested size. Detach + the block from the free list. The remaining word cannot be linked: + turn it into an empty block (header only), and return the rest. + 2. The free block is large enough. Split it in two and return the right + block. + In all cases, the allocated block is right-justified in the free block: + it is located in the high-address words of the free block, so that + the linking of the free-list does not change in case 2. +*/ +static header_t *allocate_block (mlsize_t wh_sz, int flpi, value prev, + value cur) +{ + header_t h = Hd_bp (cur); + CAMLassert (Whsize_hd (h) >= wh_sz); + if (Wosize_hd (h) < wh_sz + 1){ /* Cases 0 and 1. */ + caml_fl_cur_wsz -= Whsize_hd (h); + Next (prev) = Next (cur); + CAMLassert (Is_in_heap (Next (prev)) || Next (prev) == Val_NULL); + if (caml_fl_merge == cur) caml_fl_merge = prev; +#ifdef DEBUG + fl_last = Val_NULL; +#endif + /* In case 1, the following creates the empty block correctly. + In case 0, it gives an invalid header to the block. The function + calling [caml_fl_allocate] will overwrite it. */ + Hd_op (cur) = Make_header (0, 0, Caml_white); + if (policy == Policy_first_fit){ + if (flpi + 1 < flp_size && flp[flpi + 1] == cur){ + flp[flpi + 1] = prev; + }else if (flpi == flp_size - 1){ + beyond = (prev == Fl_head) ? Val_NULL : prev; + -- flp_size; + } + } + }else{ /* Case 2. */ + caml_fl_cur_wsz -= wh_sz; + Hd_op (cur) = Make_header (Wosize_hd (h) - wh_sz, 0, Caml_blue); + } + if (policy == Policy_next_fit) fl_prev = prev; + return (header_t *) &Field (cur, Wosize_hd (h) - wh_sz); +} + +#ifdef CAML_INSTR +static uintnat instr_size [20] = + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +static char *instr_name [20] = { + NULL, + "alloc01@", + "alloc02@", + "alloc03@", + "alloc04@", + "alloc05@", + "alloc06@", + "alloc07@", + "alloc08@", + "alloc09@", + "alloc10-19@", + "alloc20-29@", + "alloc30-39@", + "alloc40-49@", + "alloc50-59@", + "alloc60-69@", + "alloc70-79@", + "alloc80-89@", + "alloc90-99@", + "alloc_large@", +}; +uintnat caml_instr_alloc_jump = 0; +/* number of pointers followed to allocate from the free list */ +#endif /*CAML_INSTR*/ + +/* [caml_fl_allocate] does not set the header of the newly allocated block. + The calling function must do it before any GC function gets called. + [caml_fl_allocate] returns a head pointer. +*/ +header_t *caml_fl_allocate (mlsize_t wo_sz) +{ + value cur = Val_NULL, prev; + header_t *result; + int i; + mlsize_t sz, prevsz; + CAMLassert (sizeof (char *) == sizeof (value)); + CAMLassert (wo_sz >= 1); +#ifdef CAML_INSTR + if (wo_sz < 10){ + ++instr_size[wo_sz]; + }else if (wo_sz < 100){ + ++instr_size[wo_sz/10 + 9]; + }else{ + ++instr_size[19]; + } +#endif /* CAML_INSTR */ + + switch (policy){ + case Policy_next_fit: + CAMLassert (fl_prev != Val_NULL); + /* Search from [fl_prev] to the end of the list. */ + prev = fl_prev; + cur = Next (prev); + while (cur != Val_NULL){ + CAMLassert (Is_in_heap (cur)); + if (Wosize_bp (cur) >= wo_sz){ + return allocate_block (Whsize_wosize (wo_sz), 0, prev, cur); + } + prev = cur; + cur = Next (prev); +#ifdef CAML_INSTR + ++ caml_instr_alloc_jump; +#endif + } + fl_last = prev; + /* Search from the start of the list to [fl_prev]. */ + prev = Fl_head; + cur = Next (prev); + while (prev != fl_prev){ + if (Wosize_bp (cur) >= wo_sz){ + return allocate_block (Whsize_wosize (wo_sz), 0, prev, cur); + } + prev = cur; + cur = Next (prev); +#ifdef CAML_INSTR + ++ caml_instr_alloc_jump; +#endif + } + /* No suitable block was found. */ + return NULL; + break; + + case Policy_first_fit: { + /* Search in the flp array. */ + for (i = 0; i < flp_size; i++){ + sz = Wosize_bp (Next (flp[i])); + if (sz >= wo_sz){ +#if FREELIST_DEBUG + if (i > 5) fprintf (stderr, "FLP: found at %d size=%d\n", i, wo_sz); +#endif + result = allocate_block (Whsize_wosize (wo_sz), i, flp[i], + Next (flp[i])); + goto update_flp; + } + } + /* Extend the flp array. */ + if (flp_size == 0){ + prev = Fl_head; + prevsz = 0; + }else{ + prev = Next (flp[flp_size - 1]); + prevsz = Wosize_bp (prev); + if (beyond != Val_NULL) prev = beyond; + } + while (flp_size < FLP_MAX){ + cur = Next (prev); + if (cur == Val_NULL){ + fl_last = prev; + beyond = (prev == Fl_head) ? Val_NULL : prev; + return NULL; + }else{ + sz = Wosize_bp (cur); + if (sz > prevsz){ + flp[flp_size] = prev; + ++ flp_size; + if (sz >= wo_sz){ + beyond = cur; + i = flp_size - 1; +#if FREELIST_DEBUG + if (flp_size > 5){ + fprintf (stderr, "FLP: extended to %d\n", flp_size); + } +#endif + result = allocate_block (Whsize_wosize (wo_sz), flp_size - 1, prev, + cur); + goto update_flp; + } + prevsz = sz; + } + } + prev = cur; + } + beyond = cur; + + /* The flp table is full. Do a slow first-fit search. */ +#if FREELIST_DEBUG + fprintf (stderr, "FLP: table is full -- slow first-fit\n"); +#endif + if (beyond != Val_NULL){ + prev = beyond; + }else{ + prev = flp[flp_size - 1]; + } + prevsz = Wosize_bp (Next (flp[FLP_MAX-1])); + CAMLassert (prevsz < wo_sz); + cur = Next (prev); + while (cur != Val_NULL){ + CAMLassert (Is_in_heap (cur)); + sz = Wosize_bp (cur); + if (sz < prevsz){ + beyond = cur; + }else if (sz >= wo_sz){ + return allocate_block (Whsize_wosize (wo_sz), flp_size, prev, cur); + } + prev = cur; + cur = Next (prev); + } + fl_last = prev; + return NULL; + + update_flp: /* (i, sz) */ + /* The block at [i] was removed or reduced. Update the table. */ + CAMLassert (0 <= i && i < flp_size + 1); + if (i < flp_size){ + if (i > 0){ + prevsz = Wosize_bp (Next (flp[i-1])); + }else{ + prevsz = 0; + } + if (i == flp_size - 1){ + if (Wosize_bp (Next (flp[i])) <= prevsz){ + beyond = Next (flp[i]); + -- flp_size; + }else{ + beyond = Val_NULL; + } + }else{ + value buf [FLP_MAX]; + int j = 0; + mlsize_t oldsz = sz; + + prev = flp[i]; + while (prev != flp[i+1] && j < FLP_MAX - i){ + cur = Next (prev); + sz = Wosize_bp (cur); + if (sz > prevsz){ + buf[j++] = prev; + prevsz = sz; + if (sz >= oldsz){ + CAMLassert (sz == oldsz); + break; + } + } + prev = cur; + } +#if FREELIST_DEBUG + if (j > 2) fprintf (stderr, "FLP: update; buf size = %d\n", j); +#endif + if (FLP_MAX >= flp_size + j - 1){ + if (j != 1){ + memmove (&flp[i+j], &flp[i+1], sizeof (value) * (flp_size-i-1)); + } + if (j > 0) memmove (&flp[i], &buf[0], sizeof (value) * j); + flp_size += j - 1; + }else{ + if (FLP_MAX > i + j){ + if (j != 1){ + memmove (&flp[i+j], &flp[i+1], sizeof (value) * (FLP_MAX-i-j)); + } + if (j > 0) memmove (&flp[i], &buf[0], sizeof (value) * j); + }else{ + if (i != FLP_MAX){ + memmove (&flp[i], &buf[0], sizeof (value) * (FLP_MAX - i)); + } + } + flp_size = FLP_MAX - 1; + beyond = Next (flp[FLP_MAX - 1]); + } + } + } + return result; + } + break; + + default: + CAMLassert (0); /* unknown policy */ + break; + } + return NULL; /* NOT REACHED */ +} + +/* Location of the last fragment seen by the sweeping code. + This is a pointer to the first word after the fragment, which is + the header of the next block. + Note that [last_fragment] doesn't point to the fragment itself, + but to the block after it. +*/ +static header_t *last_fragment; + +void caml_fl_init_merge (void) +{ +#ifdef CAML_INSTR + int i; + for (i = 1; i < 20; i++){ + CAML_INSTR_INT (instr_name[i], instr_size[i]); + instr_size[i] = 0; + } +#endif /* CAML_INSTR */ + last_fragment = NULL; + caml_fl_merge = Fl_head; +#ifdef DEBUG + fl_check (); +#endif +} + +static void truncate_flp (value changed) +{ + if (changed == Fl_head){ + flp_size = 0; + beyond = Val_NULL; + }else{ + while (flp_size > 0 + && Bp_val (Next (flp[flp_size - 1])) >= Bp_val (changed)) + -- flp_size; + if (Bp_val (beyond) >= Bp_val (changed)) beyond = Val_NULL; + } +} + +/* This is called by caml_compact_heap. */ +void caml_fl_reset (void) +{ + Next (Fl_head) = Val_NULL; + switch (policy){ + case Policy_next_fit: + fl_prev = Fl_head; + break; + case Policy_first_fit: + truncate_flp (Fl_head); + break; + default: + CAMLassert (0); + break; + } + caml_fl_cur_wsz = 0; + caml_fl_init_merge (); +} + +/* [caml_fl_merge_block] returns the head pointer of the next block after [bp], + because merging blocks may change the size of [bp]. */ +header_t *caml_fl_merge_block (value bp) +{ + value prev, cur; + header_t *adj; + header_t hd = Hd_val (bp); + mlsize_t prev_wosz; + + caml_fl_cur_wsz += Whsize_hd (hd); + +#ifdef DEBUG + caml_set_fields (bp, 0, Debug_free_major); +#endif + prev = caml_fl_merge; + cur = Next (prev); + /* The sweep code makes sure that this is the right place to insert + this block: */ + CAMLassert (Bp_val (prev) < Bp_val (bp) || prev == Fl_head); + CAMLassert (Bp_val (cur) > Bp_val (bp) || cur == Val_NULL); + + if (policy == Policy_first_fit) truncate_flp (prev); + + /* If [last_fragment] and [bp] are adjacent, merge them. */ + if (last_fragment == Hp_val (bp)){ + mlsize_t bp_whsz = Whsize_val (bp); + if (bp_whsz <= Max_wosize){ + hd = Make_header (bp_whsz, 0, Caml_white); + bp = (value) last_fragment; + Hd_val (bp) = hd; + caml_fl_cur_wsz += Whsize_wosize (0); + } + } + + /* If [bp] and [cur] are adjacent, remove [cur] from the free-list + and merge them. */ + adj = (header_t *) &Field (bp, Wosize_hd (hd)); + if (adj == Hp_val (cur)){ + value next_cur = Next (cur); + mlsize_t cur_whsz = Whsize_val (cur); + + if (Wosize_hd (hd) + cur_whsz <= Max_wosize){ + Next (prev) = next_cur; + if (policy == Policy_next_fit && fl_prev == cur) fl_prev = prev; + hd = Make_header (Wosize_hd (hd) + cur_whsz, 0, Caml_blue); + Hd_val (bp) = hd; + adj = (header_t *) &Field (bp, Wosize_hd (hd)); +#ifdef DEBUG + fl_last = Val_NULL; + Next (cur) = (value) Debug_free_major; + Hd_val (cur) = Debug_free_major; +#endif + cur = next_cur; + } + } + /* If [prev] and [bp] are adjacent merge them, else insert [bp] into + the free-list if it is big enough. */ + prev_wosz = Wosize_val (prev); + if ((header_t *) &Field (prev, prev_wosz) == Hp_val (bp) + && prev_wosz + Whsize_hd (hd) < Max_wosize){ + Hd_val (prev) = Make_header (prev_wosz + Whsize_hd (hd), 0,Caml_blue); +#ifdef DEBUG + Hd_val (bp) = Debug_free_major; +#endif + CAMLassert (caml_fl_merge == prev); + }else if (Wosize_hd (hd) != 0){ + Hd_val (bp) = Bluehd_hd (hd); + Next (bp) = cur; + Next (prev) = bp; + caml_fl_merge = bp; + }else{ + /* This is a fragment. Leave it in white but remember it for eventual + merging with the next block. */ + last_fragment = (header_t *) bp; + caml_fl_cur_wsz -= Whsize_wosize (0); + } + return adj; +} + +/* This is a heap extension. We have to insert it in the right place + in the free-list. + [caml_fl_add_blocks] can only be called right after a call to + [caml_fl_allocate] that returned Val_NULL. + Most of the heap extensions are expected to be at the end of the + free list. (This depends on the implementation of [malloc].) + + [bp] must point to a list of blocks chained by their field 0, + terminated by Val_NULL, and field 1 of the first block must point to + the last block. +*/ +void caml_fl_add_blocks (value bp) +{ + value cur = bp; + CAMLassert (fl_last != Val_NULL); + CAMLassert (Next (fl_last) == Val_NULL); + do { + caml_fl_cur_wsz += Whsize_bp (cur); + cur = Field(cur, 0); + } while (cur != Val_NULL); + + if (Bp_val (bp) > Bp_val (fl_last)){ + Next (fl_last) = bp; + if (fl_last == caml_fl_merge && (char *) bp < caml_gc_sweep_hp){ + caml_fl_merge = Field (bp, 1); + } + if (policy == Policy_first_fit && flp_size < FLP_MAX){ + flp [flp_size++] = fl_last; + } + }else{ + value prev; + + prev = Fl_head; + cur = Next (prev); + while (cur != Val_NULL && Bp_val (cur) < Bp_val (bp)){ + CAMLassert (Bp_val (prev) < Bp_val (bp) || prev == Fl_head); + /* XXX TODO: extend flp on the fly */ + prev = cur; + cur = Next (prev); + } + CAMLassert (Bp_val (prev) < Bp_val (bp) || prev == Fl_head); + CAMLassert (Bp_val (cur) > Bp_val (bp) || cur == Val_NULL); + Next (Field (bp, 1)) = cur; + Next (prev) = bp; + /* When inserting blocks between [caml_fl_merge] and [caml_gc_sweep_hp], + we must advance [caml_fl_merge] to the new block, so that [caml_fl_merge] + is always the last free-list block before [caml_gc_sweep_hp]. */ + if (prev == caml_fl_merge && (char *) bp < caml_gc_sweep_hp){ + caml_fl_merge = Field (bp, 1); + } + if (policy == Policy_first_fit) truncate_flp (bp); + } +} + +/* Cut a block of memory into Max_wosize pieces, give them headers, + and optionally merge them into the free list. + arguments: + p: pointer to the first word of the block + size: size of the block (in words) + do_merge: 1 -> do merge; 0 -> do not merge + color: which color to give to the pieces; if [do_merge] is 1, this + is overridden by the merge code, but we have historically used + [Caml_white]. +*/ +void caml_make_free_blocks (value *p, mlsize_t size, int do_merge, int color) +{ + mlsize_t sz; + + while (size > 0){ + if (size > Whsize_wosize (Max_wosize)){ + sz = Whsize_wosize (Max_wosize); + }else{ + sz = size; + } + *(header_t *)p = + Make_header (Wosize_whsize (sz), 0, color); + if (do_merge) caml_fl_merge_block (Val_hp (p)); + size -= sz; + p += sz; + } +} + +void caml_set_allocation_policy (uintnat p) +{ + switch (p){ + case Policy_next_fit: + fl_prev = Fl_head; + policy = p; + break; + case Policy_first_fit: + flp_size = 0; + beyond = Val_NULL; + policy = p; + break; + default: + break; + } +} diff --git a/runtime/gc_ctrl.c b/runtime/gc_ctrl.c new file mode 100644 index 00000000..4b2efa1a --- /dev/null +++ b/runtime/gc_ctrl.c @@ -0,0 +1,739 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +#include "caml/alloc.h" +#include "caml/backtrace.h" +#include "caml/compact.h" +#include "caml/custom.h" +#include "caml/fail.h" +#include "caml/finalise.h" +#include "caml/freelist.h" +#include "caml/gc.h" +#include "caml/gc_ctrl.h" +#include "caml/major_gc.h" +#include "caml/memory.h" +#include "caml/minor_gc.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/signals.h" +#ifdef NATIVE_CODE +#include "caml/stack.h" +#else +#include "caml/stacks.h" +#endif +#include "caml/startup_aux.h" + +#ifndef NATIVE_CODE +extern uintnat caml_max_stack_size; /* defined in stacks.c */ +#endif + +double caml_stat_minor_words = 0.0, + caml_stat_promoted_words = 0.0, + caml_stat_major_words = 0.0; + +intnat caml_stat_minor_collections = 0, + caml_stat_major_collections = 0, + caml_stat_heap_wsz = 0, + caml_stat_top_heap_wsz = 0, + caml_stat_compactions = 0, + caml_stat_heap_chunks = 0; + +extern uintnat caml_major_heap_increment; /* percent or words; see major_gc.c */ +extern uintnat caml_percent_free; /* see major_gc.c */ +extern uintnat caml_percent_max; /* see compact.c */ +extern uintnat caml_allocation_policy; /* see freelist.c */ +extern uintnat caml_custom_major_ratio; /* see custom.c */ +extern uintnat caml_custom_minor_ratio; /* see custom.c */ +extern uintnat caml_custom_minor_max_bsz; /* see custom.c */ + +#define Next(hp) ((header_t *)(hp) + Whsize_hp (hp)) + +#ifdef DEBUG + +/* Check that [v]'s header looks good. [v] must be a block in the heap. */ +static void check_head (value v) +{ + CAMLassert (Is_block (v)); + CAMLassert (Is_in_heap (v)); + + CAMLassert (Wosize_val (v) != 0); + CAMLassert (Color_hd (Hd_val (v)) != Caml_blue); + CAMLassert (Is_in_heap (v)); + if (Tag_val (v) == Infix_tag){ + int offset = Wsize_bsize (Infix_offset_val (v)); + value trueval = Val_op (&Field (v, -offset)); + CAMLassert (Tag_val (trueval) == Closure_tag); + CAMLassert (Wosize_val (trueval) > offset); + CAMLassert (Is_in_heap (&Field (trueval, Wosize_val (trueval) - 1))); + }else{ + CAMLassert (Is_in_heap (&Field (v, Wosize_val (v) - 1))); + } + if (Tag_val (v) == Double_tag){ + CAMLassert (Wosize_val (v) == Double_wosize); + }else if (Tag_val (v) == Double_array_tag){ + CAMLassert (Wosize_val (v) % Double_wosize == 0); + } +} + +static void check_block (header_t *hp) +{ + mlsize_t i; + value v = Val_hp (hp); + value f; + + check_head (v); + switch (Tag_hp (hp)){ + case Abstract_tag: break; + case String_tag: + break; + case Double_tag: + CAMLassert (Wosize_val (v) == Double_wosize); + break; + case Double_array_tag: + CAMLassert (Wosize_val (v) % Double_wosize == 0); + break; + case Custom_tag: + CAMLassert (!Is_in_heap (Custom_ops_val (v))); + break; + + case Infix_tag: + CAMLassert (0); + break; + + default: + CAMLassert (Tag_hp (hp) < No_scan_tag); + for (i = 0; i < Wosize_hp (hp); i++){ + f = Field (v, i); + if (Is_block (f) && Is_in_heap (f)){ + check_head (f); + CAMLassert (Color_val (f) != Caml_blue); + } + } + } +} + +#endif /* DEBUG */ + +/* Check the heap structure (if compiled in debug mode) and + gather statistics; return the stats if [returnstats] is true, + otherwise return [Val_unit]. +*/ +static value heap_stats (int returnstats) +{ + CAMLparam0 (); + intnat live_words = 0, live_blocks = 0, + free_words = 0, free_blocks = 0, largest_free = 0, + fragments = 0, heap_chunks = 0; + char *chunk = caml_heap_start, *chunk_end; + header_t *cur_hp; +#ifdef DEBUG + header_t *prev_hp; +#endif + header_t cur_hd; + +#ifdef DEBUG + caml_gc_message (-1, "### OCaml runtime: heap check ###\n"); +#endif + + while (chunk != NULL){ + ++ heap_chunks; + chunk_end = chunk + Chunk_size (chunk); +#ifdef DEBUG + prev_hp = NULL; +#endif + cur_hp = (header_t *) chunk; + while (cur_hp < (header_t *) chunk_end){ + cur_hd = Hd_hp (cur_hp); + CAMLassert (Next (cur_hp) <= (header_t *) chunk_end); + switch (Color_hd (cur_hd)){ + case Caml_white: + if (Wosize_hd (cur_hd) == 0){ + ++ fragments; + CAMLassert (prev_hp == NULL + || Color_hp (prev_hp) != Caml_blue + || cur_hp == (header_t *) caml_gc_sweep_hp); + }else{ + if (caml_gc_phase == Phase_sweep + && cur_hp >= (header_t *) caml_gc_sweep_hp){ + ++ free_blocks; + free_words += Whsize_hd (cur_hd); + if (Whsize_hd (cur_hd) > largest_free){ + largest_free = Whsize_hd (cur_hd); + } + }else{ + ++ live_blocks; + live_words += Whsize_hd (cur_hd); +#ifdef DEBUG + check_block (cur_hp); +#endif + } + } + break; + case Caml_gray: case Caml_black: + CAMLassert (Wosize_hd (cur_hd) > 0); + ++ live_blocks; + live_words += Whsize_hd (cur_hd); +#ifdef DEBUG + check_block (cur_hp); +#endif + break; + case Caml_blue: + CAMLassert (Wosize_hd (cur_hd) > 0); + ++ free_blocks; + free_words += Whsize_hd (cur_hd); + if (Whsize_hd (cur_hd) > largest_free){ + largest_free = Whsize_hd (cur_hd); + } + /* not true any more with big heap chunks + CAMLassert (prev_hp == NULL + || (Color_hp (prev_hp) != Caml_blue + && Wosize_hp (prev_hp) > 0) + || cur_hp == caml_gc_sweep_hp); + CAMLassert (Next (cur_hp) == chunk_end + || (Color_hp (Next (cur_hp)) != Caml_blue + && Wosize_hp (Next (cur_hp)) > 0) + || (Whsize_hd (cur_hd) + Wosize_hp (Next (cur_hp)) + > Max_wosize) + || Next (cur_hp) == caml_gc_sweep_hp); + */ + break; + } +#ifdef DEBUG + prev_hp = cur_hp; +#endif + cur_hp = Next (cur_hp); + } + CAMLassert (cur_hp == (header_t *) chunk_end); + chunk = Chunk_next (chunk); + } + +#ifdef DEBUG + caml_final_invariant_check(); +#endif + + CAMLassert (heap_chunks == caml_stat_heap_chunks); + CAMLassert (live_words + free_words + fragments == caml_stat_heap_wsz); + + if (returnstats){ + CAMLlocal1 (res); + + /* get a copy of these before allocating anything... */ + double minwords = caml_stat_minor_words + + (double) (caml_young_alloc_end - caml_young_ptr); + double prowords = caml_stat_promoted_words; + double majwords = caml_stat_major_words + (double) caml_allocated_words; + intnat mincoll = caml_stat_minor_collections; + intnat majcoll = caml_stat_major_collections; + intnat heap_words = caml_stat_heap_wsz; + intnat cpct = caml_stat_compactions; + intnat top_heap_words = caml_stat_top_heap_wsz; + + res = caml_alloc_tuple (16); + Store_field (res, 0, caml_copy_double (minwords)); + Store_field (res, 1, caml_copy_double (prowords)); + Store_field (res, 2, caml_copy_double (majwords)); + Store_field (res, 3, Val_long (mincoll)); + Store_field (res, 4, Val_long (majcoll)); + Store_field (res, 5, Val_long (heap_words)); + Store_field (res, 6, Val_long (heap_chunks)); + Store_field (res, 7, Val_long (live_words)); + Store_field (res, 8, Val_long (live_blocks)); + Store_field (res, 9, Val_long (free_words)); + Store_field (res, 10, Val_long (free_blocks)); + Store_field (res, 11, Val_long (largest_free)); + Store_field (res, 12, Val_long (fragments)); + Store_field (res, 13, Val_long (cpct)); + Store_field (res, 14, Val_long (top_heap_words)); + Store_field (res, 15, Val_long (caml_stack_usage())); + CAMLreturn (res); + }else{ + CAMLreturn (Val_unit); + } +} + +#ifdef DEBUG +void caml_heap_check (void) +{ + heap_stats (0); +} +#endif + +CAMLprim value caml_gc_stat(value v) +{ + value result; + CAML_INSTR_SETUP (tmr, ""); + CAMLassert (v == Val_unit); + result = heap_stats (1); + CAML_INSTR_TIME (tmr, "explicit/gc_stat"); + return result; +} + +CAMLprim value caml_gc_quick_stat(value v) +{ + CAMLparam0 (); + CAMLlocal1 (res); + + /* get a copy of these before allocating anything... */ + double minwords = caml_stat_minor_words + + (double) (caml_young_alloc_end - caml_young_ptr); + double prowords = caml_stat_promoted_words; + double majwords = caml_stat_major_words + (double) caml_allocated_words; + intnat mincoll = caml_stat_minor_collections; + intnat majcoll = caml_stat_major_collections; + intnat heap_words = caml_stat_heap_wsz; + intnat top_heap_words = caml_stat_top_heap_wsz; + intnat cpct = caml_stat_compactions; + intnat heap_chunks = caml_stat_heap_chunks; + + res = caml_alloc_tuple (16); + Store_field (res, 0, caml_copy_double (minwords)); + Store_field (res, 1, caml_copy_double (prowords)); + Store_field (res, 2, caml_copy_double (majwords)); + Store_field (res, 3, Val_long (mincoll)); + Store_field (res, 4, Val_long (majcoll)); + Store_field (res, 5, Val_long (heap_words)); + Store_field (res, 6, Val_long (heap_chunks)); + Store_field (res, 7, Val_long (0)); + Store_field (res, 8, Val_long (0)); + Store_field (res, 9, Val_long (0)); + Store_field (res, 10, Val_long (0)); + Store_field (res, 11, Val_long (0)); + Store_field (res, 12, Val_long (0)); + Store_field (res, 13, Val_long (cpct)); + Store_field (res, 14, Val_long (top_heap_words)); + Store_field (res, 15, Val_long (caml_stack_usage())); + CAMLreturn (res); +} + +double caml_gc_minor_words_unboxed() +{ + return (caml_stat_minor_words + + (double) (caml_young_alloc_end - caml_young_ptr)); +} + +CAMLprim value caml_gc_minor_words(value v) +{ + CAMLparam0 (); /* v is ignored */ + CAMLreturn(caml_copy_double(caml_gc_minor_words_unboxed())); +} + +CAMLprim value caml_gc_counters(value v) +{ + CAMLparam0 (); /* v is ignored */ + CAMLlocal1 (res); + + /* get a copy of these before allocating anything... */ + double minwords = caml_stat_minor_words + + (double) (caml_young_alloc_end - caml_young_ptr); + double prowords = caml_stat_promoted_words; + double majwords = caml_stat_major_words + (double) caml_allocated_words; + + res = caml_alloc_tuple (3); + Store_field (res, 0, caml_copy_double (minwords)); + Store_field (res, 1, caml_copy_double (prowords)); + Store_field (res, 2, caml_copy_double (majwords)); + CAMLreturn (res); +} + +CAMLprim value caml_gc_huge_fallback_count (value v) +{ + return Val_long (caml_huge_fallback_count); +} + +CAMLprim value caml_gc_get(value v) +{ + CAMLparam0 (); /* v is ignored */ + CAMLlocal1 (res); + + res = caml_alloc_tuple (11); + Store_field (res, 0, Val_long (caml_minor_heap_wsz)); /* s */ + Store_field (res, 1, Val_long (caml_major_heap_increment)); /* i */ + Store_field (res, 2, Val_long (caml_percent_free)); /* o */ + Store_field (res, 3, Val_long (caml_verb_gc)); /* v */ + Store_field (res, 4, Val_long (caml_percent_max)); /* O */ +#ifndef NATIVE_CODE + Store_field (res, 5, Val_long (caml_max_stack_size)); /* l */ +#else + Store_field (res, 5, Val_long (0)); +#endif + Store_field (res, 6, Val_long (caml_allocation_policy)); /* a */ + Store_field (res, 7, Val_long (caml_major_window)); /* w */ + Store_field (res, 8, Val_long (caml_custom_major_ratio)); /* M */ + Store_field (res, 9, Val_long (caml_custom_minor_ratio)); /* m */ + Store_field (res, 10, Val_long (caml_custom_minor_max_bsz)); /* n */ + CAMLreturn (res); +} + +#define Max(x,y) ((x) < (y) ? (y) : (x)) + +static uintnat norm_pfree (uintnat p) +{ + return Max (p, 1); +} + +static uintnat norm_pmax (uintnat p) +{ + return p; +} + +static intnat norm_minsize (intnat s) +{ + if (s < Minor_heap_min) s = Minor_heap_min; + if (s > Minor_heap_max) s = Minor_heap_max; + return s; +} + +static uintnat norm_window (intnat w) +{ + if (w < 1) w = 1; + if (w > Max_major_window) w = Max_major_window; + return w; +} + +static uintnat norm_custom_maj (uintnat p) +{ + return Max (p, 1); +} + +static uintnat norm_custom_min (uintnat p) +{ + return Max (p, 1); +} + +CAMLprim value caml_gc_set(value v) +{ + uintnat newpf, newpm; + asize_t newheapincr; + asize_t newminwsz; + uintnat oldpolicy; + uintnat new_custom_maj, new_custom_min, new_custom_sz; + CAML_INSTR_SETUP (tmr, ""); + + caml_verb_gc = Long_val (Field (v, 3)); + +#ifndef NATIVE_CODE + caml_change_max_stack_size (Long_val (Field (v, 5))); +#endif + + newpf = norm_pfree (Long_val (Field (v, 2))); + if (newpf != caml_percent_free){ + caml_percent_free = newpf; + caml_gc_message (0x20, "New space overhead: %" + ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_percent_free); + } + + newpm = norm_pmax (Long_val (Field (v, 4))); + if (newpm != caml_percent_max){ + caml_percent_max = newpm; + caml_gc_message (0x20, "New max overhead: %" + ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_percent_max); + } + + newheapincr = Long_val (Field (v, 1)); + if (newheapincr != caml_major_heap_increment){ + caml_major_heap_increment = newheapincr; + if (newheapincr > 1000){ + caml_gc_message (0x20, "New heap increment size: %" + ARCH_INTNAT_PRINTF_FORMAT "uk words\n", + caml_major_heap_increment/1024); + }else{ + caml_gc_message (0x20, "New heap increment size: %" + ARCH_INTNAT_PRINTF_FORMAT "u%%\n", + caml_major_heap_increment); + } + } + oldpolicy = caml_allocation_policy; + caml_set_allocation_policy (Long_val (Field (v, 6))); + if (oldpolicy != caml_allocation_policy){ + caml_gc_message (0x20, "New allocation policy: %" + ARCH_INTNAT_PRINTF_FORMAT "u\n", caml_allocation_policy); + } + + /* This field was added in 4.03.0. */ + if (Wosize_val (v) >= 8){ + int old_window = caml_major_window; + caml_set_major_window (norm_window (Long_val (Field (v, 7)))); + if (old_window != caml_major_window){ + caml_gc_message (0x20, "New smoothing window size: %d\n", + caml_major_window); + } + } + + /* These fields were added in 4.08.0. */ + if (Wosize_val (v) >= 11){ + new_custom_maj = norm_custom_maj (Field (v, 8)); + if (new_custom_maj != caml_custom_major_ratio){ + caml_custom_major_ratio = new_custom_maj; + caml_gc_message (0x20, "New custom major ratio: %" + ARCH_INTNAT_PRINTF_FORMAT "u%%\n", + caml_custom_major_ratio); + } + new_custom_min = norm_custom_min (Field (v, 9)); + if (new_custom_min != caml_custom_minor_ratio){ + caml_custom_minor_ratio = new_custom_min; + caml_gc_message (0x20, "New custom minor ratio: %" + ARCH_INTNAT_PRINTF_FORMAT "u%%\n", + caml_custom_minor_ratio); + } + new_custom_sz = Field (v, 10); + if (new_custom_sz != caml_custom_minor_max_bsz){ + caml_custom_minor_max_bsz = new_custom_sz; + caml_gc_message (0x20, "New custom minor size limit: %" + ARCH_INTNAT_PRINTF_FORMAT "u%%\n", + caml_custom_minor_max_bsz); + } + } + + /* Minor heap size comes last because it will trigger a minor collection + (thus invalidating [v]) and it can raise [Out_of_memory]. */ + newminwsz = norm_minsize (Long_val (Field (v, 0))); + if (newminwsz != caml_minor_heap_wsz){ + caml_gc_message (0x20, "New minor heap size: %" + ARCH_SIZET_PRINTF_FORMAT "uk words\n", newminwsz / 1024); + caml_set_minor_heap_size (Bsize_wsize (newminwsz)); + } + CAML_INSTR_TIME (tmr, "explicit/gc_set"); + return Val_unit; +} + +CAMLprim value caml_gc_minor(value v) +{ + CAML_INSTR_SETUP (tmr, ""); + CAMLassert (v == Val_unit); + caml_request_minor_gc (); + caml_gc_dispatch (); + CAML_INSTR_TIME (tmr, "explicit/gc_minor"); + return Val_unit; +} + +static void test_and_compact (void) +{ + double fp; + + fp = 100.0 * caml_fl_cur_wsz / (caml_stat_heap_wsz - caml_fl_cur_wsz); + if (fp > 999999.0) fp = 999999.0; + caml_gc_message (0x200, "Estimated overhead (lower bound) = %" + ARCH_INTNAT_PRINTF_FORMAT "u%%\n", + (uintnat) fp); + if (fp >= caml_percent_max){ + caml_gc_message (0x200, "Automatic compaction triggered.\n"); + caml_compact_heap (); + } +} + +CAMLprim value caml_gc_major(value v) +{ + CAML_INSTR_SETUP (tmr, ""); + CAMLassert (v == Val_unit); + caml_gc_message (0x1, "Major GC cycle requested\n"); + caml_empty_minor_heap (); + caml_finish_major_cycle (); + test_and_compact (); + caml_final_do_calls (); + CAML_INSTR_TIME (tmr, "explicit/gc_major"); + return Val_unit; +} + +CAMLprim value caml_gc_full_major(value v) +{ + CAML_INSTR_SETUP (tmr, ""); + CAMLassert (v == Val_unit); + caml_gc_message (0x1, "Full major GC cycle requested\n"); + caml_empty_minor_heap (); + caml_finish_major_cycle (); + caml_final_do_calls (); + caml_empty_minor_heap (); + caml_finish_major_cycle (); + test_and_compact (); + caml_final_do_calls (); + CAML_INSTR_TIME (tmr, "explicit/gc_full_major"); + return Val_unit; +} + +CAMLprim value caml_gc_major_slice (value v) +{ + CAML_INSTR_SETUP (tmr, ""); + CAMLassert (Is_long (v)); + caml_major_collection_slice (Long_val (v)); + CAML_INSTR_TIME (tmr, "explicit/gc_major_slice"); + return Val_long (0); +} + +CAMLprim value caml_gc_compaction(value v) +{ + CAML_INSTR_SETUP (tmr, ""); + CAMLassert (v == Val_unit); + caml_gc_message (0x10, "Heap compaction requested\n"); + caml_empty_minor_heap (); + caml_finish_major_cycle (); + caml_final_do_calls (); + caml_empty_minor_heap (); + caml_finish_major_cycle (); + caml_compact_heap (); + caml_final_do_calls (); + CAML_INSTR_TIME (tmr, "explicit/gc_compact"); + return Val_unit; +} + +CAMLprim value caml_get_minor_free (value v) +{ + return Val_int (caml_young_ptr - caml_young_alloc_start); +} + +CAMLprim value caml_get_major_bucket (value v) +{ + long i = Long_val (v); + if (i < 0) caml_invalid_argument ("Gc.get_bucket"); + if (i < caml_major_window){ + i += caml_major_ring_index; + if (i >= caml_major_window) i -= caml_major_window; + CAMLassert (0 <= i && i < caml_major_window); + return Val_long ((long) (caml_major_ring[i] * 1e6)); + }else{ + return Val_long (0); + } +} + +CAMLprim value caml_get_major_credit (value v) +{ + CAMLassert (v == Val_unit); + return Val_long ((long) (caml_major_work_credit * 1e6)); +} + +uintnat caml_normalize_heap_increment (uintnat i) +{ + if (i < Bsize_wsize (Heap_chunk_min)){ + i = Bsize_wsize (Heap_chunk_min); + } + return ((i + Page_size - 1) >> Page_log) << Page_log; +} + +/* [minor_size] and [major_size] are numbers of words + [major_incr] is either a percentage or a number of words */ +void caml_init_gc (uintnat minor_size, uintnat major_size, + uintnat major_incr, uintnat percent_fr, + uintnat percent_m, uintnat window, + uintnat custom_maj, uintnat custom_min, + uintnat custom_bsz) +{ + uintnat major_heap_size = + Bsize_wsize (caml_normalize_heap_increment (major_size)); + + caml_instr_init (); + if (caml_init_alloc_for_heap () != 0){ + caml_fatal_error ("cannot initialize heap: mmap failed"); + } + if (caml_page_table_initialize(Bsize_wsize(minor_size) + major_heap_size)){ + caml_fatal_error ("cannot initialize page table"); + } + caml_set_minor_heap_size (Bsize_wsize (norm_minsize (minor_size))); + caml_major_heap_increment = major_incr; + caml_percent_free = norm_pfree (percent_fr); + caml_percent_max = norm_pmax (percent_m); + caml_init_major_heap (major_heap_size); + caml_major_window = norm_window (window); + caml_custom_major_ratio = norm_custom_maj (custom_maj); + caml_custom_minor_ratio = norm_custom_min (custom_min); + caml_custom_minor_max_bsz = custom_bsz; + caml_gc_message (0x20, "Initial minor heap size: %" + ARCH_SIZET_PRINTF_FORMAT "uk words\n", + caml_minor_heap_wsz / 1024); + caml_gc_message (0x20, "Initial major heap size: %" + ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n", + major_heap_size / 1024); + caml_gc_message (0x20, "Initial space overhead: %" + ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_percent_free); + caml_gc_message (0x20, "Initial max overhead: %" + ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_percent_max); + if (caml_major_heap_increment > 1000){ + caml_gc_message (0x20, "Initial heap increment: %" + ARCH_INTNAT_PRINTF_FORMAT "uk words\n", + caml_major_heap_increment / 1024); + }else{ + caml_gc_message (0x20, "Initial heap increment: %" + ARCH_INTNAT_PRINTF_FORMAT "u%%\n", + caml_major_heap_increment); + } + caml_gc_message (0x20, "Initial allocation policy: %" + ARCH_INTNAT_PRINTF_FORMAT "u\n", caml_allocation_policy); + caml_gc_message (0x20, "Initial smoothing window: %d\n", + caml_major_window); +} + + +/* FIXME After the startup_aux.c unification, move these functions there. */ + +CAMLprim value caml_runtime_variant (value unit) +{ + CAMLassert (unit == Val_unit); +#if defined (DEBUG) + return caml_copy_string ("d"); +#elif defined (CAML_INSTR) + return caml_copy_string ("i"); +#else + return caml_copy_string (""); +#endif +} + +extern int caml_parser_trace; + +CAMLprim value caml_runtime_parameters (value unit) +{ +#define F_Z ARCH_INTNAT_PRINTF_FORMAT +#define F_S ARCH_SIZET_PRINTF_FORMAT + + CAMLassert (unit == Val_unit); + return caml_alloc_sprintf + ("a=%d,b=%d,H=%"F_Z"u,i=%"F_Z"u,l=%"F_Z"u,o=%"F_Z"u,O=%"F_Z"u,p=%d," + "s=%"F_S"u,t=%"F_Z"u,v=%"F_Z"u,w=%d,W=%"F_Z"u", + /* a */ (int) caml_allocation_policy, + /* b */ caml_backtrace_active, + /* h */ /* missing */ /* FIXME add when changed to min_heap_size */ + /* H */ caml_use_huge_pages, + /* i */ caml_major_heap_increment, +#ifdef NATIVE_CODE + /* l */ (uintnat) 0, +#else + /* l */ caml_max_stack_size, +#endif + /* o */ caml_percent_free, + /* O */ caml_percent_max, + /* p */ caml_parser_trace, + /* R */ /* missing */ + /* s */ caml_minor_heap_wsz, + /* t */ caml_trace_level, + /* v */ caml_verb_gc, + /* w */ caml_major_window, + /* W */ caml_runtime_warnings + ); +#undef F_Z +#undef F_S +} + +/* Control runtime warnings */ + +CAMLprim value caml_ml_enable_runtime_warnings(value vbool) +{ + caml_runtime_warnings = Bool_val(vbool); + return Val_unit; +} + +CAMLprim value caml_ml_runtime_warnings_enabled(value unit) +{ + CAMLassert (unit == Val_unit); + return Val_bool(caml_runtime_warnings); +} diff --git a/runtime/gen_primitives.sh b/runtime/gen_primitives.sh new file mode 100755 index 00000000..e3ca2779 --- /dev/null +++ b/runtime/gen_primitives.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 1999 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +# duplicated from $(ROOTDIR)/runtime/Makefile + +( + for prim in \ + alloc array compare extern floats gc_ctrl hash intern interp ints io \ + lexing md5 meta obj parsing signals str sys callback weak finalise \ + stacks dynlink backtrace_byt backtrace spacetime_byt afl bigarray + do + sed -n -e "s/^CAMLprim value \([a-z0-9_][a-z0-9_]*\).*/\1/p" "$prim.c" + done + sed -n -e 's/^CAMLprim_int64_[0-9](\([a-z0-9_][a-z0-9_]*\)).*/caml_int64_\1\ +caml_int64_\1_native/p' ints.c +) | LC_ALL=C sort | uniq diff --git a/byterun/globroots.c b/runtime/globroots.c similarity index 100% rename from byterun/globroots.c rename to runtime/globroots.c diff --git a/byterun/hash.c b/runtime/hash.c similarity index 100% rename from byterun/hash.c rename to runtime/hash.c diff --git a/asmrun/i386.S b/runtime/i386.S similarity index 100% rename from asmrun/i386.S rename to runtime/i386.S diff --git a/asmrun/i386nt.asm b/runtime/i386nt.asm similarity index 100% rename from asmrun/i386nt.asm rename to runtime/i386nt.asm diff --git a/runtime/instrtrace.c b/runtime/instrtrace.c new file mode 100644 index 00000000..3aa99448 --- /dev/null +++ b/runtime/instrtrace.c @@ -0,0 +1,269 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Trace the instructions executed */ + +#ifdef DEBUG + +#include +#include +#include + +#include "caml/instrtrace.h" +#include "caml/instruct.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/opnames.h" +#include "caml/prims.h" +#include "caml/stacks.h" +#include "caml/startup_aux.h" + +extern code_t caml_start_code; + +intnat caml_icount = 0; + +void caml_stop_here () {} + +void caml_disasm_instr(pc) + code_t pc; +{ + int instr = *pc; + printf("%6ld %s", (long) (pc - caml_start_code), + instr < 0 || instr > STOP ? "???" : names_of_instructions[instr]); + pc++; + switch(instr) { + /* Instructions with one integer operand */ + case PUSHACC: case ACC: case POP: case ASSIGN: + case PUSHENVACC: case ENVACC: case PUSH_RETADDR: case APPLY: + case APPTERM1: case APPTERM2: case APPTERM3: case RETURN: + case GRAB: case PUSHGETGLOBAL: case GETGLOBAL: case SETGLOBAL: + case PUSHATOM: case ATOM: case MAKEBLOCK1: case MAKEBLOCK2: + case MAKEBLOCK3: case MAKEFLOATBLOCK: + case GETFIELD: case SETFIELD: case GETFLOATFIELD: case SETFLOATFIELD: + case BRANCH: case BRANCHIF: case BRANCHIFNOT: case PUSHTRAP: + case CONSTINT: case PUSHCONSTINT: case OFFSETINT: case OFFSETREF: + case OFFSETCLOSURE: case PUSHOFFSETCLOSURE: + printf(" %d\n", pc[0]); break; + /* Instructions with two operands */ + case APPTERM: case CLOSURE: case CLOSUREREC: case PUSHGETGLOBALFIELD: + case GETGLOBALFIELD: case MAKEBLOCK: + case BEQ: case BNEQ: case BLTINT: case BLEINT: case BGTINT: case BGEINT: + case BULTINT: case BUGEINT: + printf(" %d, %d\n", pc[0], pc[1]); break; + /* Instructions with a C primitive as operand */ + case C_CALLN: + printf(" %d,", pc[0]); pc++; + /* fallthrough */ + case C_CALL1: case C_CALL2: case C_CALL3: case C_CALL4: case C_CALL5: + if (pc[0] < 0 || pc[0] >= caml_prim_name_table.size) + printf(" unknown primitive %d\n", pc[0]); + else + printf(" %s\n", (char *) caml_prim_name_table.contents[pc[0]]); + break; + default: + printf("\n"); + } + fflush (stdout); +} + +char * caml_instr_string (code_t pc) +{ + static char buf[256]; + char nambuf[128]; + int instr = *pc; + char *nam; + + nam = (instr < 0 || instr > STOP) + ? (snprintf (nambuf, sizeof(nambuf), "???%d", instr), nambuf) + : names_of_instructions[instr]; + pc++; + switch (instr) { + /* Instructions with one integer operand */ + case PUSHACC: + case ACC: + case POP: + case ASSIGN: + case PUSHENVACC: + case ENVACC: + case PUSH_RETADDR: + case APPLY: + case APPTERM1: + case APPTERM2: + case APPTERM3: + case RETURN: + case GRAB: + case PUSHGETGLOBAL: + case GETGLOBAL: + case SETGLOBAL: + case PUSHATOM: + case ATOM: + case MAKEBLOCK1: + case MAKEBLOCK2: + case MAKEBLOCK3: + case MAKEFLOATBLOCK: + case GETFIELD: + case SETFIELD: + case GETFLOATFIELD: + case SETFLOATFIELD: + case BRANCH: + case BRANCHIF: + case BRANCHIFNOT: + case PUSHTRAP: + case CONSTINT: + case PUSHCONSTINT: + case OFFSETINT: + case OFFSETREF: + case OFFSETCLOSURE: + case PUSHOFFSETCLOSURE: + snprintf(buf, sizeof(buf), "%s %d", nam, pc[0]); + break; + /* Instructions with two operands */ + case APPTERM: + case CLOSURE: + case CLOSUREREC: + case PUSHGETGLOBALFIELD: + case GETGLOBALFIELD: + case MAKEBLOCK: + case BEQ: + case BNEQ: + case BLTINT: + case BLEINT: + case BGTINT: + case BGEINT: + case BULTINT: + case BUGEINT: + snprintf(buf, sizeof(buf), "%s %d, %d", nam, pc[0], pc[1]); + break; + case SWITCH: + snprintf(buf, sizeof(buf), "SWITCH sz%#lx=%ld::ntag%ld nint%ld", + (long) pc[0], (long) pc[0], (unsigned long) pc[0] >> 16, + (unsigned long) pc[0] & 0xffff); + break; + /* Instructions with a C primitive as operand */ + case C_CALLN: + snprintf(buf, sizeof(buf), "%s %d,", nam, pc[0]); + pc++; + /* fallthrough */ + case C_CALL1: + case C_CALL2: + case C_CALL3: + case C_CALL4: + case C_CALL5: + if (pc[0] < 0 || pc[0] >= caml_prim_name_table.size) + snprintf(buf, sizeof(buf), "%s unknown primitive %d", nam, pc[0]); + else + snprintf(buf, sizeof(buf), "%s %s", + nam, (char *) caml_prim_name_table.contents[pc[0]]); + break; + default: + snprintf(buf, sizeof(buf), "%s", nam); + break; + }; + return buf; +} + + +void +caml_trace_value_file (value v, code_t prog, asize_t proglen, FILE * f) +{ + int i; + fprintf (f, "%#" ARCH_INTNAT_PRINTF_FORMAT "x", v); + if (!v) + return; + if (prog && v % sizeof (int) == 0 + && (code_t) v >= prog + && (code_t) v < (code_t) ((char *) prog + proglen)) + fprintf (f, "=code@%ld", (long) ((code_t) v - prog)); + else if (Is_long (v)) + fprintf (f, "=long%" ARCH_INTNAT_PRINTF_FORMAT "d", Long_val (v)); + else if ((void*)v >= (void*)caml_stack_low + && (void*)v < (void*)caml_stack_high) + fprintf (f, "=stack_%ld", (long) ((intnat*)caml_stack_high - (intnat*)v)); + else if (Is_block (v)) { + int s = Wosize_val (v); + int tg = Tag_val (v); + int l = 0; + switch (tg) { + case Closure_tag: + fprintf (f, "=closure[s%d,cod%ld]", + s, (long) ((code_t) (Code_val (v)) - prog)); + goto displayfields; + case String_tag: + l = caml_string_length (v); + fprintf (f, "=string[s%dL%d]'", s, l); + for (i = 0; i < ((l>0x1f)?0x1f:l) ; i++) { + if (isprint ((int) Byte (v, i))) + putc (Byte (v, i), f); + else + putc ('?', f); + }; + fprintf (f, "'"); + goto displayfields; + case Double_tag: + fprintf (f, "=float[s%d]=%g", s, Double_val (v)); + goto displayfields; + case Double_array_tag: + fprintf (f, "=floatarray[s%d]", s); + for (i = 0; i < ((s>0xf)?0xf:s); i++) + fprintf (f, " %g", Double_flat_field (v, i)); + goto displayfields; + case Abstract_tag: + fprintf (f, "=abstract[s%d]", s); + goto displayfields; + case Custom_tag: + fprintf (f, "=custom[s%d]", s); + goto displayfields; + default: + fprintf (f, "=block", tg, s); + displayfields: + if (s > 0) + fputs ("=(", f); + for (i = 0; i < s; i++) { + if (i > 20) { + fputs ("....", f); + break; + }; + if (i > 0) + putc (' ', f); + fprintf (f, "%#" ARCH_INTNAT_PRINTF_FORMAT "x", Field (v, i)); + }; + if (s > 0) + putc (')', f); + }; + } +} + +void +caml_trace_accu_sp_file (value accu, value * sp, code_t prog, asize_t proglen, + FILE * f) +{ + int i; + value *p; + fprintf (f, "accu="); + caml_trace_value_file (accu, prog, proglen, f); + fprintf (f, "\n sp=%#" ARCH_INTNAT_PRINTF_FORMAT "x @%ld:", + (intnat) sp, (long) (caml_stack_high - sp)); + for (p = sp, i = 0; i < 12 + (1 << caml_trace_level) && p < caml_stack_high; + p++, i++) { + fprintf (f, "\n[%ld] ", (long) (caml_stack_high - p)); + caml_trace_value_file (*p, prog, proglen, f); + }; + putc ('\n', f); + fflush (f); +} + +#endif /* DEBUG */ diff --git a/runtime/intern.c b/runtime/intern.c new file mode 100644 index 00000000..9932d80b --- /dev/null +++ b/runtime/intern.c @@ -0,0 +1,1086 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Structured input, compact format */ + +/* The interface of this file is "caml/intext.h" */ + +#include +#include +#include "caml/alloc.h" +#include "caml/callback.h" +#include "caml/config.h" +#include "caml/custom.h" +#include "caml/fail.h" +#include "caml/gc.h" +#include "caml/intext.h" +#include "caml/io.h" +#include "caml/md5.h" +#include "caml/memory.h" +#include "caml/mlvalues.h" +#include "caml/misc.h" +#include "caml/reverse.h" + +static unsigned char * intern_src; +/* Reading pointer in block holding input data. */ + +static unsigned char * intern_input = NULL; +/* Pointer to beginning of block holding input data, + if non-NULL this pointer will be freed by the cleanup function. */ + +static header_t * intern_dest; +/* Writing pointer in destination block */ + +static char * intern_extra_block = NULL; +/* If non-NULL, point to new heap chunk allocated with caml_alloc_for_heap. */ + +static asize_t obj_counter; +/* Count how many objects seen so far */ + +static value * intern_obj_table = NULL; +/* The pointers to objects already seen */ + +static color_t intern_color; +/* Color to assign to newly created headers */ + +static header_t intern_header; +/* Original header of the destination block. + Meaningful only if intern_extra_block is NULL. */ + +static value intern_block = 0; +/* Point to the heap block allocated as destination block. + Meaningful only if intern_extra_block is NULL. */ + +static char * intern_resolve_code_pointer(unsigned char digest[16], + asize_t offset); + +CAMLnoreturn_start +static void intern_bad_code_pointer(unsigned char digest[16]) +CAMLnoreturn_end; + +static void intern_free_stack(void); + +static inline unsigned char read8u(void) +{ return *intern_src++; } + +static inline signed char read8s(void) +{ return *intern_src++; } + +static inline uint16_t read16u(void) +{ + uint16_t res = (intern_src[0] << 8) + intern_src[1]; + intern_src += 2; + return res; +} + +static inline int16_t read16s(void) +{ + int16_t res = (intern_src[0] << 8) + intern_src[1]; + intern_src += 2; + return res; +} + +static inline uint32_t read32u(void) +{ + uint32_t res = + ((uint32_t)(intern_src[0]) << 24) + (intern_src[1] << 16) + + (intern_src[2] << 8) + intern_src[3]; + intern_src += 4; + return res; +} + +static inline int32_t read32s(void) +{ + int32_t res = + ((uint32_t)(intern_src[0]) << 24) + (intern_src[1] << 16) + + (intern_src[2] << 8) + intern_src[3]; + intern_src += 4; + return res; +} + +#ifdef ARCH_SIXTYFOUR +static uintnat read64u(void) +{ + uintnat res = + ((uintnat) (intern_src[0]) << 56) + + ((uintnat) (intern_src[1]) << 48) + + ((uintnat) (intern_src[2]) << 40) + + ((uintnat) (intern_src[3]) << 32) + + ((uintnat) (intern_src[4]) << 24) + + ((uintnat) (intern_src[5]) << 16) + + ((uintnat) (intern_src[6]) << 8) + + (uintnat) (intern_src[7]); + intern_src += 8; + return res; +} +#endif + +static inline void readblock(void * dest, intnat len) +{ + memcpy(dest, intern_src, len); + intern_src += len; +} + +static void intern_init(void * src, void * input) +{ + /* This is asserted at the beginning of demarshaling primitives. + If it fails, it probably means that an exception was raised + without calling intern_cleanup() during the previous demarshaling. */ + CAMLassert (intern_input == NULL && intern_obj_table == NULL \ + && intern_extra_block == NULL && intern_block == 0); + intern_src = src; + intern_input = input; +} + +static void intern_cleanup(void) +{ + if (intern_input != NULL) { + caml_stat_free(intern_input); + intern_input = NULL; + } + if (intern_obj_table != NULL) { + caml_stat_free(intern_obj_table); + intern_obj_table = NULL; + } + if (intern_extra_block != NULL) { + /* free newly allocated heap chunk */ + caml_free_for_heap(intern_extra_block); + intern_extra_block = NULL; + } else if (intern_block != 0) { + /* restore original header for heap block, otherwise GC is confused */ + Hd_val(intern_block) = intern_header; + intern_block = 0; + } + /* free the recursion stack */ + intern_free_stack(); +} + +static void readfloat(double * dest, unsigned int code) +{ + if (sizeof(double) != 8) { + intern_cleanup(); + caml_invalid_argument("input_value: non-standard floats"); + } + readblock((char *) dest, 8); + /* Fix up endianness, if needed */ +#if ARCH_FLOAT_ENDIANNESS == 0x76543210 + /* Host is big-endian; fix up if data read is little-endian */ + if (code != CODE_DOUBLE_BIG) Reverse_64(dest, dest); +#elif ARCH_FLOAT_ENDIANNESS == 0x01234567 + /* Host is little-endian; fix up if data read is big-endian */ + if (code != CODE_DOUBLE_LITTLE) Reverse_64(dest, dest); +#else + /* Host is neither big nor little; permute as appropriate */ + if (code == CODE_DOUBLE_LITTLE) + Permute_64(dest, ARCH_FLOAT_ENDIANNESS, dest, 0x01234567) + else + Permute_64(dest, ARCH_FLOAT_ENDIANNESS, dest, 0x76543210); +#endif +} + +/* [len] is a number of floats */ +static void readfloats(double * dest, mlsize_t len, unsigned int code) +{ + mlsize_t i; + if (sizeof(double) != 8) { + intern_cleanup(); + caml_invalid_argument("input_value: non-standard floats"); + } + readblock((char *) dest, len * 8); + /* Fix up endianness, if needed */ +#if ARCH_FLOAT_ENDIANNESS == 0x76543210 + /* Host is big-endian; fix up if data read is little-endian */ + if (code != CODE_DOUBLE_ARRAY8_BIG && + code != CODE_DOUBLE_ARRAY32_BIG) { + for (i = 0; i < len; i++) Reverse_64(dest + i, dest + i); + } +#elif ARCH_FLOAT_ENDIANNESS == 0x01234567 + /* Host is little-endian; fix up if data read is big-endian */ + if (code != CODE_DOUBLE_ARRAY8_LITTLE && + code != CODE_DOUBLE_ARRAY32_LITTLE) { + for (i = 0; i < len; i++) Reverse_64(dest + i, dest + i); + } +#else + /* Host is neither big nor little; permute as appropriate */ + if (code == CODE_DOUBLE_ARRAY8_LITTLE || + code == CODE_DOUBLE_ARRAY32_LITTLE) { + for (i = 0; i < len; i++) + Permute_64(dest + i, ARCH_FLOAT_ENDIANNESS, dest + i, 0x01234567); + } else { + for (i = 0; i < len; i++) + Permute_64(dest + i, ARCH_FLOAT_ENDIANNESS, dest + i, 0x76543210); + } +#endif +} + +/* Item on the stack with defined operation */ +struct intern_item { + value * dest; + intnat arg; + enum { + OReadItems, /* read arg items and store them in dest[0], dest[1], ... */ + OFreshOID, /* generate a fresh OID and store it in *dest */ + OShift /* offset *dest by arg */ + } op; +}; + +/* FIXME: This is duplicated in two other places, with the only difference of + the type of elements stored in the stack. Possible solution in C would + be to instantiate stack these function via. C preprocessor macro. + */ + +#define INTERN_STACK_INIT_SIZE 256 +#define INTERN_STACK_MAX_SIZE (1024*1024*100) + +static struct intern_item intern_stack_init[INTERN_STACK_INIT_SIZE]; + +static struct intern_item * intern_stack = intern_stack_init; +static struct intern_item * intern_stack_limit = intern_stack_init + + INTERN_STACK_INIT_SIZE; + +/* Free the recursion stack if needed */ +static void intern_free_stack(void) +{ + if (intern_stack != intern_stack_init) { + caml_stat_free(intern_stack); + /* Reinitialize the globals for next time around */ + intern_stack = intern_stack_init; + intern_stack_limit = intern_stack + INTERN_STACK_INIT_SIZE; + } +} + +/* Same, then raise Out_of_memory */ +CAMLnoreturn_start +static void intern_stack_overflow(void) +CAMLnoreturn_end; + +static void intern_stack_overflow(void) +{ + caml_gc_message (0x04, "Stack overflow in un-marshaling value\n"); + intern_free_stack(); + caml_raise_out_of_memory(); +} + +static struct intern_item * intern_resize_stack(struct intern_item * sp) +{ + asize_t newsize = 2 * (intern_stack_limit - intern_stack); + asize_t sp_offset = sp - intern_stack; + struct intern_item * newstack; + + if (newsize >= INTERN_STACK_MAX_SIZE) intern_stack_overflow(); + if (intern_stack == intern_stack_init) { + newstack = caml_stat_alloc_noexc(sizeof(struct intern_item) * newsize); + if (newstack == NULL) intern_stack_overflow(); + memcpy(newstack, intern_stack_init, + sizeof(struct intern_item) * INTERN_STACK_INIT_SIZE); + } else { + newstack = caml_stat_resize_noexc(intern_stack, + sizeof(struct intern_item) * newsize); + if (newstack == NULL) intern_stack_overflow(); + } + intern_stack = newstack; + intern_stack_limit = newstack + newsize; + return newstack + sp_offset; +} + +/* Convenience macros for requesting operation on the stack */ +#define PushItem() \ + do { \ + sp++; \ + if (sp >= intern_stack_limit) sp = intern_resize_stack(sp); \ + } while(0) + +#define ReadItems(_dest,_n) \ + do { \ + if (_n > 0) { \ + PushItem(); \ + sp->op = OReadItems; \ + sp->dest = _dest; \ + sp->arg = _n; \ + } \ + } while(0) + +static void intern_rec(value *dest) +{ + unsigned int code; + tag_t tag; + mlsize_t size, len, ofs_ind; + value v; + asize_t ofs; + header_t header; + unsigned char digest[16]; + struct custom_operations * ops; + char * codeptr; + struct intern_item * sp; + + sp = intern_stack; + + /* Initially let's try to read the first object from the stream */ + ReadItems(dest, 1); + + /* The un-marshaler loop, the recursion is unrolled */ + while(sp != intern_stack) { + + /* Interpret next item on the stack */ + dest = sp->dest; + switch (sp->op) { + case OFreshOID: + /* Refresh the object ID */ + /* but do not do it for predefined exception slots */ + if (Long_val(Field((value)dest, 1)) >= 0) + caml_set_oo_id((value)dest); + /* Pop item and iterate */ + sp--; + break; + case OShift: + /* Shift value by an offset */ + *dest += sp->arg; + /* Pop item and iterate */ + sp--; + break; + case OReadItems: + /* Pop item */ + sp->dest++; + if (--(sp->arg) == 0) sp--; + /* Read a value and set v to this value */ + code = read8u(); + if (code >= PREFIX_SMALL_INT) { + if (code >= PREFIX_SMALL_BLOCK) { + /* Small block */ + tag = code & 0xF; + size = (code >> 4) & 0x7; + read_block: + if (size == 0) { + v = Atom(tag); + } else { + v = Val_hp(intern_dest); + if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; + *intern_dest = Make_header_allocated_here(size, tag, intern_color); + intern_dest += 1 + size; + /* For objects, we need to freshen the oid */ + if (tag == Object_tag) { + CAMLassert(size >= 2); + /* Request to read rest of the elements of the block */ + ReadItems(&Field(v, 2), size - 2); + /* Request freshing OID */ + PushItem(); + sp->op = OFreshOID; + sp->dest = (value*) v; + sp->arg = 1; + /* Finally read first two block elements: method table and old OID */ + ReadItems(&Field(v, 0), 2); + } else + /* If it's not an object then read the contents of the block */ + ReadItems(&Field(v, 0), size); + } + } else { + /* Small integer */ + v = Val_int(code & 0x3F); + } + } else { + if (code >= PREFIX_SMALL_STRING) { + /* Small string */ + len = (code & 0x1F); + read_string: + size = (len + sizeof(value)) / sizeof(value); + v = Val_hp(intern_dest); + if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; + *intern_dest = Make_header_allocated_here(size, String_tag, intern_color); + intern_dest += 1 + size; + Field(v, size - 1) = 0; + ofs_ind = Bsize_wsize(size) - 1; + Byte(v, ofs_ind) = ofs_ind - len; + readblock((char *)String_val(v), len); + } else { + switch(code) { + case CODE_INT8: + v = Val_long(read8s()); + break; + case CODE_INT16: + v = Val_long(read16s()); + break; + case CODE_INT32: + v = Val_long(read32s()); + break; + case CODE_INT64: +#ifdef ARCH_SIXTYFOUR + v = Val_long((intnat) (read64u())); + break; +#else + intern_cleanup(); + caml_failwith("input_value: integer too large"); + break; +#endif + case CODE_SHARED8: + ofs = read8u(); + read_shared: + CAMLassert (ofs > 0); + CAMLassert (ofs <= obj_counter); + CAMLassert (intern_obj_table != NULL); + v = intern_obj_table[obj_counter - ofs]; + break; + case CODE_SHARED16: + ofs = read16u(); + goto read_shared; + case CODE_SHARED32: + ofs = read32u(); + goto read_shared; +#ifdef ARCH_SIXTYFOUR + case CODE_SHARED64: + ofs = read64u(); + goto read_shared; +#endif + case CODE_BLOCK32: + header = (header_t) read32u(); + tag = Tag_hd(header); + size = Wosize_hd(header); + goto read_block; +#ifdef ARCH_SIXTYFOUR + case CODE_BLOCK64: + header = (header_t) read64u(); + tag = Tag_hd(header); + size = Wosize_hd(header); + goto read_block; +#endif + case CODE_STRING8: + len = read8u(); + goto read_string; + case CODE_STRING32: + len = read32u(); + goto read_string; +#ifdef ARCH_SIXTYFOUR + case CODE_STRING64: + len = read64u(); + goto read_string; +#endif + case CODE_DOUBLE_LITTLE: + case CODE_DOUBLE_BIG: + v = Val_hp(intern_dest); + if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; + *intern_dest = Make_header_allocated_here(Double_wosize, Double_tag, + intern_color); + intern_dest += 1 + Double_wosize; + readfloat((double *) v, code); + break; + case CODE_DOUBLE_ARRAY8_LITTLE: + case CODE_DOUBLE_ARRAY8_BIG: + len = read8u(); + read_double_array: + size = len * Double_wosize; + v = Val_hp(intern_dest); + if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; + *intern_dest = Make_header_allocated_here(size, Double_array_tag, + intern_color); + intern_dest += 1 + size; + readfloats((double *) v, len, code); + break; + case CODE_DOUBLE_ARRAY32_LITTLE: + case CODE_DOUBLE_ARRAY32_BIG: + len = read32u(); + goto read_double_array; +#ifdef ARCH_SIXTYFOUR + case CODE_DOUBLE_ARRAY64_LITTLE: + case CODE_DOUBLE_ARRAY64_BIG: + len = read64u(); + goto read_double_array; +#endif + case CODE_CODEPOINTER: + ofs = read32u(); + readblock(digest, 16); + codeptr = intern_resolve_code_pointer(digest, ofs); + if (codeptr != NULL) { + v = (value) codeptr; + } else { + value * function_placeholder = + caml_named_value ("Debugger.function_placeholder"); + if (function_placeholder != NULL) { + v = *function_placeholder; + } else { + intern_cleanup(); + intern_bad_code_pointer(digest); + } + } + break; + case CODE_INFIXPOINTER: + ofs = read32u(); + /* Read a value to *dest, then offset *dest by ofs */ + PushItem(); + sp->dest = dest; + sp->op = OShift; + sp->arg = ofs; + ReadItems(dest, 1); + continue; /* with next iteration of main loop, skipping *dest = v */ + case CODE_CUSTOM: + case CODE_CUSTOM_LEN: + case CODE_CUSTOM_FIXED: { + ops = caml_find_custom_operations((char *) intern_src); + if (ops == NULL) { + intern_cleanup(); + caml_failwith("input_value: unknown custom block identifier"); + } + if (code == CODE_CUSTOM_FIXED && ops->fixed_length == NULL) { + intern_cleanup(); + caml_failwith("input_value: expected a fixed-size custom block"); + } + while (*intern_src++ != 0) /*nothing*/; /*skip identifier*/ + if (code == CODE_CUSTOM) { + /* deprecated */ + size = ops->deserialize((void *) (intern_dest + 2)); + } else { + uintnat expected_size; +#ifdef ARCH_SIXTYFOUR + if (code == CODE_CUSTOM_FIXED) { + expected_size = ops->fixed_length->bsize_64; + } else { + intern_src += 4; + expected_size = read64u(); + } +#else + if (code == CODE_CUSTOM_FIXED) { + expected_size = ops->fixed_length->bsize_32; + } else { + expected_size = read32u(); + intern_src += 8; + } +#endif + size = ops->deserialize((void *) (intern_dest + 2)); + if (size != expected_size) { + intern_cleanup(); + caml_failwith( + "input_value: incorrect length of serialized custom block"); + } + } + size = 1 + (size + sizeof(value) - 1) / sizeof(value); + v = Val_hp(intern_dest); + if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; + *intern_dest = Make_header_allocated_here(size, Custom_tag, + intern_color); + Custom_ops_val(v) = ops; + + if (ops->finalize != NULL && Is_young(v)) { + /* Remember that the block has a finalizer. */ + add_to_custom_table (&caml_custom_table, v, 0, 1); + } + + intern_dest += 1 + size; + break; + } + default: + intern_cleanup(); + caml_failwith("input_value: ill-formed message"); + } + } + } + /* end of case OReadItems */ + *dest = v; + break; + default: + CAMLassert(0); + } + } + /* We are done. Cleanup the stack and leave the function */ + intern_free_stack(); +} + +static void intern_alloc(mlsize_t whsize, mlsize_t num_objects, + int outside_heap) +{ + mlsize_t wosize; + + if (whsize == 0) { + CAMLassert (intern_extra_block == NULL && intern_block == 0 + && intern_obj_table == NULL); + return; + } + wosize = Wosize_whsize(whsize); + if (outside_heap || wosize > Max_wosize) { + /* Round desired size up to next page */ + asize_t request = + ((Bsize_wsize(whsize) + Page_size - 1) >> Page_log) << Page_log; + intern_extra_block = caml_alloc_for_heap(request); + if (intern_extra_block == NULL) { + intern_cleanup(); + caml_raise_out_of_memory(); + } + intern_color = + outside_heap ? Caml_black : caml_allocation_color(intern_extra_block); + intern_dest = (header_t *) intern_extra_block; + CAMLassert (intern_block == 0); + } else { + /* this is a specialised version of caml_alloc from alloc.c */ + if (wosize <= Max_young_wosize){ + if (wosize == 0){ + intern_block = Atom (String_tag); + } else { + intern_block = caml_alloc_small (wosize, String_tag); + } + }else{ + intern_block = caml_alloc_shr_no_raise (wosize, String_tag); + /* do not do the urgent_gc check here because it might darken + intern_block into gray and break the intern_color assertion below */ + if (intern_block == 0) { + intern_cleanup(); + caml_raise_out_of_memory(); + } + } + intern_header = Hd_val(intern_block); + intern_color = Color_hd(intern_header); + CAMLassert (intern_color == Caml_white || intern_color == Caml_black); + intern_dest = (header_t *) Hp_val(intern_block); + CAMLassert (intern_extra_block == NULL); + } + obj_counter = 0; + if (num_objects > 0) { + intern_obj_table = + (value *) caml_stat_alloc_noexc(num_objects * sizeof(value)); + if (intern_obj_table == NULL) { + intern_cleanup(); + caml_raise_out_of_memory(); + } + } else + CAMLassert(intern_obj_table == NULL); +} + +static void intern_add_to_heap(mlsize_t whsize) +{ + /* Add new heap chunk to heap if needed */ + if (intern_extra_block != NULL) { + /* If heap chunk not filled totally, build free block at end */ + asize_t request = Chunk_size (intern_extra_block); + header_t * end_extra_block = + (header_t *) intern_extra_block + Wsize_bsize(request); + CAMLassert(intern_block == 0); + CAMLassert(intern_dest <= end_extra_block); + if (intern_dest < end_extra_block){ + caml_make_free_blocks ((value *) intern_dest, + end_extra_block - intern_dest, 0, Caml_white); + } + caml_allocated_words += + Wsize_bsize ((char *) intern_dest - intern_extra_block); + caml_add_to_heap(intern_extra_block); + intern_extra_block = NULL; // To prevent intern_cleanup freeing it + } else { + intern_block = 0; // To prevent intern_cleanup rewriting its header + } +} + +/* Parsing the header */ + +struct marshal_header { + uint32_t magic; + int header_len; + uintnat data_len; + uintnat num_objects; + uintnat whsize; +}; + +static void caml_parse_header(char * fun_name, + /*out*/ struct marshal_header * h) +{ + char errmsg[100]; + + h->magic = read32u(); + switch(h->magic) { + case Intext_magic_number_small: + h->header_len = 20; + h->data_len = read32u(); + h->num_objects = read32u(); +#ifdef ARCH_SIXTYFOUR + read32u(); + h->whsize = read32u(); +#else + h->whsize = read32u(); + read32u(); +#endif + break; + case Intext_magic_number_big: +#ifdef ARCH_SIXTYFOUR + h->header_len = 32; + read32u(); + h->data_len = read64u(); + h->num_objects = read64u(); + h->whsize = read64u(); +#else + errmsg[sizeof(errmsg) - 1] = 0; + snprintf(errmsg, sizeof(errmsg) - 1, + "%s: object too large to be read back on a 32-bit platform", + fun_name); + caml_failwith(errmsg); +#endif + break; + default: + errmsg[sizeof(errmsg) - 1] = 0; + snprintf(errmsg, sizeof(errmsg) - 1, + "%s: bad object", + fun_name); + caml_failwith(errmsg); + } +} + +/* Reading from a channel */ + +static value caml_input_val_core(struct channel *chan, int outside_heap) +{ + intnat r; + char header[32]; + struct marshal_header h; + char * block; + value res; + + if (! caml_channel_binary_mode(chan)) + caml_failwith("input_value: not a binary channel"); + /* Read and parse the header */ + r = caml_really_getblock(chan, header, 20); + if (r == 0) + caml_raise_end_of_file(); + else if (r < 20) + caml_failwith("input_value: truncated object"); + intern_src = (unsigned char *) header; + if (read32u() == Intext_magic_number_big) { + /* Finish reading the header */ + if (caml_really_getblock(chan, header + 20, 32 - 20) < 32 - 20) + caml_failwith("input_value: truncated object"); + } + intern_src = (unsigned char *) header; + caml_parse_header("input_value", &h); + /* Read block from channel */ + block = caml_stat_alloc(h.data_len); + /* During [caml_really_getblock], concurrent [caml_input_val] operations + can take place (via signal handlers or context switching in systhreads), + and [intern_input] may change. So, wait until [caml_really_getblock] + is over before using [intern_input] and the other global vars. */ + if (caml_really_getblock(chan, block, h.data_len) < h.data_len) { + caml_stat_free(block); + caml_failwith("input_value: truncated object"); + } + /* Initialize global state */ + intern_init(block, block); + intern_alloc(h.whsize, h.num_objects, outside_heap); + /* Fill it in */ + intern_rec(&res); + if (!outside_heap) { + intern_add_to_heap(h.whsize); + } else { + caml_disown_for_heap(intern_extra_block); + intern_extra_block = NULL; + intern_block = 0; + } + /* Free everything */ + intern_cleanup(); + return caml_check_urgent_gc(res); +} + +value caml_input_val(struct channel* chan) +{ + return caml_input_val_core(chan, 0); +} + +CAMLprim value caml_input_value(value vchan) +{ + CAMLparam1 (vchan); + struct channel * chan = Channel(vchan); + CAMLlocal1 (res); + + Lock(chan); + res = caml_input_val(chan); + Unlock(chan); + CAMLreturn (res); +} + +/* Reading from memory-resident blocks */ + +CAMLprim value caml_input_value_to_outside_heap(value vchan) +{ + CAMLparam1 (vchan); + struct channel * chan = Channel(vchan); + CAMLlocal1 (res); + + Lock(chan); + res = caml_input_val_core(chan, 1); + Unlock(chan); + CAMLreturn (res); +} + +CAMLexport value caml_input_val_from_bytes(value str, intnat ofs) +{ + CAMLparam1 (str); + CAMLlocal1 (obj); + struct marshal_header h; + + /* Initialize global state */ + intern_init(&Byte_u(str, ofs), NULL); + caml_parse_header("input_val_from_string", &h); + if (ofs + h.header_len + h.data_len > caml_string_length(str)) + caml_failwith("input_val_from_string: bad length"); + /* Allocate result */ + intern_alloc(h.whsize, h.num_objects, 0); + intern_src = &Byte_u(str, ofs + h.header_len); /* If a GC occurred */ + /* Fill it in */ + intern_rec(&obj); + intern_add_to_heap(h.whsize); + /* Free everything */ + intern_cleanup(); + CAMLreturn (caml_check_urgent_gc(obj)); +} + +CAMLprim value caml_input_value_from_string(value str, value ofs) +{ + return caml_input_val_from_bytes(str, Long_val(ofs)); +} + +CAMLprim value caml_input_value_from_bytes(value str, value ofs) +{ + return caml_input_val_from_bytes(str, Long_val(ofs)); +} + +static value input_val_from_block(struct marshal_header * h) +{ + value obj; + /* Allocate result */ + intern_alloc(h->whsize, h->num_objects, 0); + /* Fill it in */ + intern_rec(&obj); + intern_add_to_heap(h->whsize); + /* Free internal data structures */ + intern_cleanup(); + return caml_check_urgent_gc(obj); +} + +CAMLexport value caml_input_value_from_malloc(char * data, intnat ofs) +{ + struct marshal_header h; + + intern_init(data + ofs, data); + + caml_parse_header("input_value_from_malloc", &h); + + return input_val_from_block(&h); +} + +/* [len] is a number of bytes */ +CAMLexport value caml_input_value_from_block(char * data, intnat len) +{ + struct marshal_header h; + + /* Initialize global state */ + intern_init(data, NULL); + caml_parse_header("input_value_from_block", &h); + if (h.header_len + h.data_len > len) + caml_failwith("input_val_from_block: bad length"); + return input_val_from_block(&h); +} + +/* [ofs] is a [value] that represents a number of bytes + result is a [value] that represents a number of bytes + To handle both the small and the big format, + we assume 20 bytes are available at [buff + ofs], + and we return the data size + the length of the part of the header + that remains to be read. */ + +CAMLprim value caml_marshal_data_size(value buff, value ofs) +{ + uint32_t magic; + int header_len; + uintnat data_len; + + intern_src = &Byte_u(buff, Long_val(ofs)); + magic = read32u(); + switch(magic) { + case Intext_magic_number_small: + header_len = 20; + data_len = read32u(); + break; + case Intext_magic_number_big: +#ifdef ARCH_SIXTYFOUR + header_len = 32; + read32u(); + data_len = read64u(); +#else + caml_failwith("Marshal.data_size: " + "object too large to be read back on a 32-bit platform"); +#endif + break; + default: + caml_failwith("Marshal.data_size: bad object"); + } + return Val_long((header_len - 20) + data_len); +} + +/* Resolution of code pointers */ + +static char * intern_resolve_code_pointer(unsigned char digest[16], + asize_t offset) +{ + int i; + for (i = caml_code_fragments_table.size - 1; i >= 0; i--) { + struct code_fragment * cf = caml_code_fragments_table.contents[i]; + if (! cf->digest_computed) { + caml_md5_block(cf->digest, cf->code_start, cf->code_end - cf->code_start); + cf->digest_computed = 1; + } + if (memcmp(digest, cf->digest, 16) == 0) { + if (cf->code_start + offset < cf->code_end) + return cf->code_start + offset; + else + return NULL; + } + } + return NULL; +} + +static void intern_bad_code_pointer(unsigned char digest[16]) +{ + char msg[256]; + snprintf(msg, sizeof(msg), + "input_value: unknown code module " + "%02X%02X%02X%02X%02X%02X%02X%02X" + "%02X%02X%02X%02X%02X%02X%02X%02X", + digest[0], digest[1], digest[2], digest[3], + digest[4], digest[5], digest[6], digest[7], + digest[8], digest[9], digest[10], digest[11], + digest[12], digest[13], digest[14], digest[15]); + caml_failwith(msg); +} + +/* Functions for writing user-defined marshallers */ + +CAMLexport int caml_deserialize_uint_1(void) +{ + return read8u(); +} + +CAMLexport int caml_deserialize_sint_1(void) +{ + return read8s(); +} + +CAMLexport int caml_deserialize_uint_2(void) +{ + return read16u(); +} + +CAMLexport int caml_deserialize_sint_2(void) +{ + return read16s(); +} + +CAMLexport uint32_t caml_deserialize_uint_4(void) +{ + return read32u(); +} + +CAMLexport int32_t caml_deserialize_sint_4(void) +{ + return read32s(); +} + +CAMLexport uint64_t caml_deserialize_uint_8(void) +{ + uint64_t i; + caml_deserialize_block_8(&i, 1); + return i; +} + +CAMLexport int64_t caml_deserialize_sint_8(void) +{ + int64_t i; + caml_deserialize_block_8(&i, 1); + return i; +} + +CAMLexport float caml_deserialize_float_4(void) +{ + float f; + caml_deserialize_block_4(&f, 1); + return f; +} + +CAMLexport double caml_deserialize_float_8(void) +{ + double f; + caml_deserialize_block_float_8(&f, 1); + return f; +} + +CAMLexport void caml_deserialize_block_1(void * data, intnat len) +{ + memcpy(data, intern_src, len); + intern_src += len; +} + +CAMLexport void caml_deserialize_block_2(void * data, intnat len) +{ +#ifndef ARCH_BIG_ENDIAN + unsigned char * p, * q; + for (p = intern_src, q = data; len > 0; len--, p += 2, q += 2) + Reverse_16(q, p); + intern_src = p; +#else + memcpy(data, intern_src, len * 2); + intern_src += len * 2; +#endif +} + +CAMLexport void caml_deserialize_block_4(void * data, intnat len) +{ +#ifndef ARCH_BIG_ENDIAN + unsigned char * p, * q; + for (p = intern_src, q = data; len > 0; len--, p += 4, q += 4) + Reverse_32(q, p); + intern_src = p; +#else + memcpy(data, intern_src, len * 4); + intern_src += len * 4; +#endif +} + +CAMLexport void caml_deserialize_block_8(void * data, intnat len) +{ +#ifndef ARCH_BIG_ENDIAN + unsigned char * p, * q; + for (p = intern_src, q = data; len > 0; len--, p += 8, q += 8) + Reverse_64(q, p); + intern_src = p; +#else + memcpy(data, intern_src, len * 8); + intern_src += len * 8; +#endif +} + +CAMLexport void caml_deserialize_block_float_8(void * data, intnat len) +{ +#if ARCH_FLOAT_ENDIANNESS == 0x01234567 + memcpy(data, intern_src, len * 8); + intern_src += len * 8; +#elif ARCH_FLOAT_ENDIANNESS == 0x76543210 + unsigned char * p, * q; + for (p = intern_src, q = data; len > 0; len--, p += 8, q += 8) + Reverse_64(q, p); + intern_src = p; +#else + unsigned char * p, * q; + for (p = intern_src, q = data; len > 0; len--, p += 8, q += 8) + Permute_64(q, ARCH_FLOAT_ENDIANNESS, p, 0x01234567); + intern_src = p; +#endif +} + +CAMLexport void caml_deserialize_error(char * msg) +{ + intern_cleanup(); + caml_failwith(msg); +} diff --git a/runtime/interp.c b/runtime/interp.c new file mode 100644 index 00000000..137e28d6 --- /dev/null +++ b/runtime/interp.c @@ -0,0 +1,1172 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* The bytecode interpreter */ +#include +#include "caml/alloc.h" +#include "caml/backtrace.h" +#include "caml/callback.h" +#include "caml/debugger.h" +#include "caml/fail.h" +#include "caml/fix_code.h" +#include "caml/instrtrace.h" +#include "caml/instruct.h" +#include "caml/interp.h" +#include "caml/major_gc.h" +#include "caml/memory.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/prims.h" +#include "caml/signals.h" +#include "caml/stacks.h" +#include "caml/startup_aux.h" + +/* Registers for the abstract machine: + pc the code pointer + sp the stack pointer (grows downward) + accu the accumulator + env heap-allocated environment + caml_trapsp pointer to the current trap frame + extra_args number of extra arguments provided by the caller + +sp is a local copy of the global variable caml_extern_sp. */ + +/* Instruction decoding */ + +#ifdef THREADED_CODE +# define Instruct(name) lbl_##name +# if defined(ARCH_SIXTYFOUR) && !defined(ARCH_CODE32) +# define Jumptbl_base ((char *) &&lbl_ACC0) +# else +# define Jumptbl_base ((char *) 0) +# define jumptbl_base ((char *) 0) +# endif +# ifdef DEBUG +# define Next goto next_instr +# else +# define Next goto *(void *)(jumptbl_base + *pc++) +# endif +#else +# define Instruct(name) case name +# define Next break +#endif + +/* GC interface */ + +#define Setup_for_gc \ + { sp -= 2; sp[0] = accu; sp[1] = env; caml_extern_sp = sp; } +#define Restore_after_gc \ + { accu = sp[0]; env = sp[1]; sp += 2; } +#define Setup_for_c_call \ + { saved_pc = pc; *--sp = env; caml_extern_sp = sp; } +#define Restore_after_c_call \ + { sp = caml_extern_sp; env = *sp++; saved_pc = NULL; } + +/* An event frame must look like accu + a C_CALL frame + a RETURN 1 frame */ +#define Setup_for_event \ + { sp -= 6; \ + sp[0] = accu; /* accu */ \ + sp[1] = Val_unit; /* C_CALL frame: dummy environment */ \ + sp[2] = Val_unit; /* RETURN frame: dummy local 0 */ \ + sp[3] = (value) pc; /* RETURN frame: saved return address */ \ + sp[4] = env; /* RETURN frame: saved environment */ \ + sp[5] = Val_long(extra_args); /* RETURN frame: saved extra args */ \ + caml_extern_sp = sp; } +#define Restore_after_event \ + { sp = caml_extern_sp; accu = sp[0]; \ + pc = (code_t) sp[3]; env = sp[4]; extra_args = Long_val(sp[5]); \ + sp += 6; } + +/* Debugger interface */ + +#define Setup_for_debugger \ + { sp -= 4; \ + sp[0] = accu; sp[1] = (value)(pc - 1); \ + sp[2] = env; sp[3] = Val_long(extra_args); \ + caml_extern_sp = sp; } +#define Restore_after_debugger { sp += 4; } + +#ifdef THREADED_CODE +#define Restart_curr_instr \ + goto *(jumptable[caml_saved_code[pc - 1 - caml_start_code]]) +#else +#define Restart_curr_instr \ + curr_instr = caml_saved_code[pc - 1 - caml_start_code]; \ + goto dispatch_instr +#endif + +/* Register optimization. + Some compilers underestimate the use of the local variables representing + the abstract machine registers, and don't put them in hardware registers, + which slows down the interpreter considerably. + For GCC, I have hand-assigned hardware registers for several architectures. +*/ + +#if defined(__GNUC__) && !defined(DEBUG) && !defined(__INTEL_COMPILER) \ + && !defined(__llvm__) +#ifdef __mips__ +#define PC_REG asm("$16") +#define SP_REG asm("$17") +#define ACCU_REG asm("$18") +#endif +#ifdef __sparc__ +#define PC_REG asm("%l0") +#define SP_REG asm("%l1") +#define ACCU_REG asm("%l2") +#endif +#ifdef __alpha__ +#ifdef __CRAY__ +#define PC_REG asm("r9") +#define SP_REG asm("r10") +#define ACCU_REG asm("r11") +#define JUMPTBL_BASE_REG asm("r12") +#else +#define PC_REG asm("$9") +#define SP_REG asm("$10") +#define ACCU_REG asm("$11") +#define JUMPTBL_BASE_REG asm("$12") +#endif +#endif +#ifdef __i386__ +#define PC_REG asm("%esi") +#define SP_REG asm("%edi") +#define ACCU_REG +#endif +#if defined(__ppc__) || defined(__ppc64__) +#define PC_REG asm("26") +#define SP_REG asm("27") +#define ACCU_REG asm("28") +#endif +#ifdef __hppa__ +#define PC_REG asm("%r18") +#define SP_REG asm("%r17") +#define ACCU_REG asm("%r16") +#endif +#ifdef __mc68000__ +#define PC_REG asm("a5") +#define SP_REG asm("a4") +#define ACCU_REG asm("d7") +#endif +/* PR#4953: these specific registers not available in Thumb mode */ +#if defined (__arm__) && !defined(__thumb__) +#define PC_REG asm("r6") +#define SP_REG asm("r8") +#define ACCU_REG asm("r7") +#endif +#ifdef __ia64__ +#define PC_REG asm("36") +#define SP_REG asm("37") +#define ACCU_REG asm("38") +#define JUMPTBL_BASE_REG asm("39") +#endif +#ifdef __x86_64__ +#define PC_REG asm("%r15") +#define SP_REG asm("%r14") +#define ACCU_REG asm("%r13") +#endif +#ifdef __aarch64__ +#define PC_REG asm("%x19") +#define SP_REG asm("%x20") +#define ACCU_REG asm("%x21") +#define JUMPTBL_BASE_REG asm("%x22") +#endif +#endif + +#ifdef DEBUG +static intnat caml_bcodcount; +#endif + +/* The interpreter itself */ + +value caml_interprete(code_t prog, asize_t prog_size) +{ +#ifdef PC_REG + register code_t pc PC_REG; + register value * sp SP_REG; + register value accu ACCU_REG; +#else + register code_t pc; + register value * sp; + register value accu; +#endif +#if defined(THREADED_CODE) && defined(ARCH_SIXTYFOUR) && !defined(ARCH_CODE32) +#ifdef JUMPTBL_BASE_REG + register char * jumptbl_base JUMPTBL_BASE_REG; +#else + register char * jumptbl_base; +#endif +#endif + value env; + intnat extra_args; + struct longjmp_buffer * initial_external_raise; + intnat initial_sp_offset; + /* volatile ensures that initial_local_roots and saved_pc + will keep correct value across longjmp */ + struct caml__roots_block * volatile initial_local_roots; + volatile code_t saved_pc = NULL; + struct longjmp_buffer raise_buf; +#ifndef THREADED_CODE + opcode_t curr_instr; +#endif + +#ifdef THREADED_CODE + static void * jumptable[] = { +# include "caml/jumptbl.h" + }; +#endif + + if (prog == NULL) { /* Interpreter is initializing */ +#ifdef THREADED_CODE + caml_instr_table = (char **) jumptable; + caml_instr_base = Jumptbl_base; +#endif + return Val_unit; + } + +#if defined(THREADED_CODE) && defined(ARCH_SIXTYFOUR) && !defined(ARCH_CODE32) + jumptbl_base = Jumptbl_base; +#endif + initial_local_roots = caml_local_roots; + initial_sp_offset = (char *) caml_stack_high - (char *) caml_extern_sp; + initial_external_raise = caml_external_raise; + caml_callback_depth++; + saved_pc = NULL; + + if (sigsetjmp(raise_buf.buf, 0)) { + caml_local_roots = initial_local_roots; + sp = caml_extern_sp; + accu = caml_exn_bucket; + pc = saved_pc; saved_pc = NULL; + if (pc != NULL) pc += 2; + /* +2 adjustment for the sole purpose of backtraces */ + goto raise_exception; + } + caml_external_raise = &raise_buf; + + sp = caml_extern_sp; + pc = prog; + extra_args = 0; + env = Atom(0); + accu = Val_int(0); + +#ifdef THREADED_CODE +#ifdef DEBUG + next_instr: + if (caml_icount-- == 0) caml_stop_here (); + CAMLassert(sp >= caml_stack_low); + CAMLassert(sp <= caml_stack_high); +#endif + goto *(void *)(jumptbl_base + *pc++); /* Jump to the first instruction */ +#else + while(1) { +#ifdef DEBUG + caml_bcodcount++; + if (caml_icount-- == 0) caml_stop_here (); + if (caml_trace_level>1) printf("\n##%" ARCH_INTNAT_PRINTF_FORMAT "d\n", + caml_bcodcount); + if (caml_trace_level>0) caml_disasm_instr(pc); + if (caml_trace_level>1) { + printf("env="); + caml_trace_value_file(env,prog,prog_size,stdout); + putchar('\n'); + caml_trace_accu_sp_file(accu,sp,prog,prog_size,stdout); + fflush(stdout); + }; + CAMLassert(sp >= caml_stack_low); + CAMLassert(sp <= caml_stack_high); +#endif + curr_instr = *pc++; + + dispatch_instr: + switch(curr_instr) { +#endif + +/* Basic stack operations */ + + Instruct(ACC0): + accu = sp[0]; Next; + Instruct(ACC1): + accu = sp[1]; Next; + Instruct(ACC2): + accu = sp[2]; Next; + Instruct(ACC3): + accu = sp[3]; Next; + Instruct(ACC4): + accu = sp[4]; Next; + Instruct(ACC5): + accu = sp[5]; Next; + Instruct(ACC6): + accu = sp[6]; Next; + Instruct(ACC7): + accu = sp[7]; Next; + + Instruct(PUSH): Instruct(PUSHACC0): + *--sp = accu; Next; + Instruct(PUSHACC1): + *--sp = accu; accu = sp[1]; Next; + Instruct(PUSHACC2): + *--sp = accu; accu = sp[2]; Next; + Instruct(PUSHACC3): + *--sp = accu; accu = sp[3]; Next; + Instruct(PUSHACC4): + *--sp = accu; accu = sp[4]; Next; + Instruct(PUSHACC5): + *--sp = accu; accu = sp[5]; Next; + Instruct(PUSHACC6): + *--sp = accu; accu = sp[6]; Next; + Instruct(PUSHACC7): + *--sp = accu; accu = sp[7]; Next; + + Instruct(PUSHACC): + *--sp = accu; + /* Fallthrough */ + Instruct(ACC): + accu = sp[*pc++]; + Next; + + Instruct(POP): + sp += *pc++; + Next; + Instruct(ASSIGN): + sp[*pc++] = accu; + accu = Val_unit; + Next; + +/* Access in heap-allocated environment */ + + Instruct(ENVACC1): + accu = Field(env, 1); Next; + Instruct(ENVACC2): + accu = Field(env, 2); Next; + Instruct(ENVACC3): + accu = Field(env, 3); Next; + Instruct(ENVACC4): + accu = Field(env, 4); Next; + + Instruct(PUSHENVACC1): + *--sp = accu; accu = Field(env, 1); Next; + Instruct(PUSHENVACC2): + *--sp = accu; accu = Field(env, 2); Next; + Instruct(PUSHENVACC3): + *--sp = accu; accu = Field(env, 3); Next; + Instruct(PUSHENVACC4): + *--sp = accu; accu = Field(env, 4); Next; + + Instruct(PUSHENVACC): + *--sp = accu; + /* Fallthrough */ + Instruct(ENVACC): + accu = Field(env, *pc++); + Next; + +/* Function application */ + + Instruct(PUSH_RETADDR): { + sp -= 3; + sp[0] = (value) (pc + *pc); + sp[1] = env; + sp[2] = Val_long(extra_args); + pc++; + Next; + } + Instruct(APPLY): { + extra_args = *pc - 1; + pc = Code_val(accu); + env = accu; + goto check_stacks; + } + Instruct(APPLY1): { + value arg1 = sp[0]; + sp -= 3; + sp[0] = arg1; + sp[1] = (value)pc; + sp[2] = env; + sp[3] = Val_long(extra_args); + pc = Code_val(accu); + env = accu; + extra_args = 0; + goto check_stacks; + } + Instruct(APPLY2): { + value arg1 = sp[0]; + value arg2 = sp[1]; + sp -= 3; + sp[0] = arg1; + sp[1] = arg2; + sp[2] = (value)pc; + sp[3] = env; + sp[4] = Val_long(extra_args); + pc = Code_val(accu); + env = accu; + extra_args = 1; + goto check_stacks; + } + Instruct(APPLY3): { + value arg1 = sp[0]; + value arg2 = sp[1]; + value arg3 = sp[2]; + sp -= 3; + sp[0] = arg1; + sp[1] = arg2; + sp[2] = arg3; + sp[3] = (value)pc; + sp[4] = env; + sp[5] = Val_long(extra_args); + pc = Code_val(accu); + env = accu; + extra_args = 2; + goto check_stacks; + } + + Instruct(APPTERM): { + int nargs = *pc++; + int slotsize = *pc; + value * newsp; + int i; + /* Slide the nargs bottom words of the current frame to the top + of the frame, and discard the remainder of the frame */ + newsp = sp + slotsize - nargs; + for (i = nargs - 1; i >= 0; i--) newsp[i] = sp[i]; + sp = newsp; + pc = Code_val(accu); + env = accu; + extra_args += nargs - 1; + goto check_stacks; + } + Instruct(APPTERM1): { + value arg1 = sp[0]; + sp = sp + *pc - 1; + sp[0] = arg1; + pc = Code_val(accu); + env = accu; + goto check_stacks; + } + Instruct(APPTERM2): { + value arg1 = sp[0]; + value arg2 = sp[1]; + sp = sp + *pc - 2; + sp[0] = arg1; + sp[1] = arg2; + pc = Code_val(accu); + env = accu; + extra_args += 1; + goto check_stacks; + } + Instruct(APPTERM3): { + value arg1 = sp[0]; + value arg2 = sp[1]; + value arg3 = sp[2]; + sp = sp + *pc - 3; + sp[0] = arg1; + sp[1] = arg2; + sp[2] = arg3; + pc = Code_val(accu); + env = accu; + extra_args += 2; + goto check_stacks; + } + + Instruct(RETURN): { + sp += *pc++; + if (extra_args > 0) { + extra_args--; + pc = Code_val(accu); + env = accu; + } else { + pc = (code_t)(sp[0]); + env = sp[1]; + extra_args = Long_val(sp[2]); + sp += 3; + } + Next; + } + + Instruct(RESTART): { + int num_args = Wosize_val(env) - 2; + int i; + sp -= num_args; + for (i = 0; i < num_args; i++) sp[i] = Field(env, i + 2); + env = Field(env, 1); + extra_args += num_args; + Next; + } + + Instruct(GRAB): { + int required = *pc++; + if (extra_args >= required) { + extra_args -= required; + } else { + mlsize_t num_args, i; + num_args = 1 + extra_args; /* arg1 + extra args */ + Alloc_small(accu, num_args + 2, Closure_tag); + Field(accu, 1) = env; + for (i = 0; i < num_args; i++) Field(accu, i + 2) = sp[i]; + Code_val(accu) = pc - 3; /* Point to the preceding RESTART instr. */ + sp += num_args; + pc = (code_t)(sp[0]); + env = sp[1]; + extra_args = Long_val(sp[2]); + sp += 3; + } + Next; + } + + Instruct(CLOSURE): { + int nvars = *pc++; + int i; + if (nvars > 0) *--sp = accu; + if (nvars < Max_young_wosize) { + /* nvars + 1 <= Max_young_wosize, can allocate in minor heap */ + Alloc_small(accu, 1 + nvars, Closure_tag); + for (i = 0; i < nvars; i++) Field(accu, i + 1) = sp[i]; + } else { + /* PR#6385: must allocate in major heap */ + /* caml_alloc_shr and caml_initialize never trigger a GC, + so no need to Setup_for_gc */ + accu = caml_alloc_shr(1 + nvars, Closure_tag); + for (i = 0; i < nvars; i++) caml_initialize(&Field(accu, i + 1), sp[i]); + } + /* The code pointer is not in the heap, so no need to go through + caml_initialize. */ + Code_val(accu) = pc + *pc; + pc++; + sp += nvars; + Next; + } + + Instruct(CLOSUREREC): { + int nfuncs = *pc++; + int nvars = *pc++; + mlsize_t blksize = nfuncs * 2 - 1 + nvars; + int i; + value * p; + if (nvars > 0) *--sp = accu; + if (blksize <= Max_young_wosize) { + Alloc_small(accu, blksize, Closure_tag); + p = &Field(accu, nfuncs * 2 - 1); + for (i = 0; i < nvars; i++, p++) *p = sp[i]; + } else { + /* PR#6385: must allocate in major heap */ + /* caml_alloc_shr and caml_initialize never trigger a GC, + so no need to Setup_for_gc */ + accu = caml_alloc_shr(blksize, Closure_tag); + p = &Field(accu, nfuncs * 2 - 1); + for (i = 0; i < nvars; i++, p++) caml_initialize(p, sp[i]); + } + sp += nvars; + /* The code pointers and infix headers are not in the heap, + so no need to go through caml_initialize. */ + p = &Field(accu, 0); + *p = (value) (pc + pc[0]); + *--sp = accu; + p++; + for (i = 1; i < nfuncs; i++) { + *p = Make_header(i * 2, Infix_tag, Caml_white); /* color irrelevant. */ + p++; + *p = (value) (pc + pc[i]); + *--sp = (value) p; + p++; + } + pc += nfuncs; + Next; + } + + Instruct(PUSHOFFSETCLOSURE): + *--sp = accu; /* fallthrough */ + Instruct(OFFSETCLOSURE): + accu = env + *pc++ * sizeof(value); Next; + + Instruct(PUSHOFFSETCLOSUREM2): + *--sp = accu; /* fallthrough */ + Instruct(OFFSETCLOSUREM2): + accu = env - 2 * sizeof(value); Next; + Instruct(PUSHOFFSETCLOSURE0): + *--sp = accu; /* fallthrough */ + Instruct(OFFSETCLOSURE0): + accu = env; Next; + Instruct(PUSHOFFSETCLOSURE2): + *--sp = accu; /* fallthrough */ + Instruct(OFFSETCLOSURE2): + accu = env + 2 * sizeof(value); Next; + + +/* Access to global variables */ + + Instruct(PUSHGETGLOBAL): + *--sp = accu; + /* Fallthrough */ + Instruct(GETGLOBAL): + accu = Field(caml_global_data, *pc); + pc++; + Next; + + Instruct(PUSHGETGLOBALFIELD): + *--sp = accu; + /* Fallthrough */ + Instruct(GETGLOBALFIELD): { + accu = Field(caml_global_data, *pc); + pc++; + accu = Field(accu, *pc); + pc++; + Next; + } + + Instruct(SETGLOBAL): + caml_modify(&Field(caml_global_data, *pc), accu); + accu = Val_unit; + pc++; + Next; + +/* Allocation of blocks */ + + Instruct(PUSHATOM0): + *--sp = accu; + /* Fallthrough */ + Instruct(ATOM0): + accu = Atom(0); Next; + + Instruct(PUSHATOM): + *--sp = accu; + /* Fallthrough */ + Instruct(ATOM): + accu = Atom(*pc++); Next; + + Instruct(MAKEBLOCK): { + mlsize_t wosize = *pc++; + tag_t tag = *pc++; + mlsize_t i; + value block; + if (wosize <= Max_young_wosize) { + Alloc_small(block, wosize, tag); + Field(block, 0) = accu; + for (i = 1; i < wosize; i++) Field(block, i) = *sp++; + } else { + block = caml_alloc_shr(wosize, tag); + caml_initialize(&Field(block, 0), accu); + for (i = 1; i < wosize; i++) caml_initialize(&Field(block, i), *sp++); + } + accu = block; + Next; + } + Instruct(MAKEBLOCK1): { + tag_t tag = *pc++; + value block; + Alloc_small(block, 1, tag); + Field(block, 0) = accu; + accu = block; + Next; + } + Instruct(MAKEBLOCK2): { + tag_t tag = *pc++; + value block; + Alloc_small(block, 2, tag); + Field(block, 0) = accu; + Field(block, 1) = sp[0]; + sp += 1; + accu = block; + Next; + } + Instruct(MAKEBLOCK3): { + tag_t tag = *pc++; + value block; + Alloc_small(block, 3, tag); + Field(block, 0) = accu; + Field(block, 1) = sp[0]; + Field(block, 2) = sp[1]; + sp += 2; + accu = block; + Next; + } + Instruct(MAKEFLOATBLOCK): { + mlsize_t size = *pc++; + mlsize_t i; + value block; + if (size <= Max_young_wosize / Double_wosize) { + Alloc_small(block, size * Double_wosize, Double_array_tag); + } else { + block = caml_alloc_shr(size * Double_wosize, Double_array_tag); + } + Store_double_flat_field(block, 0, Double_val(accu)); + for (i = 1; i < size; i++){ + Store_double_flat_field(block, i, Double_val(*sp)); + ++ sp; + } + accu = block; + Next; + } + +/* Access to components of blocks */ + + Instruct(GETFIELD0): + accu = Field(accu, 0); Next; + Instruct(GETFIELD1): + accu = Field(accu, 1); Next; + Instruct(GETFIELD2): + accu = Field(accu, 2); Next; + Instruct(GETFIELD3): + accu = Field(accu, 3); Next; + Instruct(GETFIELD): + accu = Field(accu, *pc); pc++; Next; + Instruct(GETFLOATFIELD): { + double d = Double_flat_field(accu, *pc); + Alloc_small(accu, Double_wosize, Double_tag); + Store_double_val(accu, d); + pc++; + Next; + } + + Instruct(SETFIELD0): + caml_modify(&Field(accu, 0), *sp++); + accu = Val_unit; + Next; + Instruct(SETFIELD1): + caml_modify(&Field(accu, 1), *sp++); + accu = Val_unit; + Next; + Instruct(SETFIELD2): + caml_modify(&Field(accu, 2), *sp++); + accu = Val_unit; + Next; + Instruct(SETFIELD3): + caml_modify(&Field(accu, 3), *sp++); + accu = Val_unit; + Next; + Instruct(SETFIELD): + caml_modify(&Field(accu, *pc), *sp++); + accu = Val_unit; + pc++; + Next; + Instruct(SETFLOATFIELD): + Store_double_flat_field(accu, *pc, Double_val(*sp)); + accu = Val_unit; + sp++; + pc++; + Next; + +/* Array operations */ + + Instruct(VECTLENGTH): { + /* Todo: when FLAT_FLOAT_ARRAY is false, this instruction should + be split into VECTLENGTH and FLOATVECTLENGTH because we know + statically which one it is. */ + mlsize_t size = Wosize_val(accu); + if (Tag_val(accu) == Double_array_tag) size = size / Double_wosize; + accu = Val_long(size); + Next; + } + Instruct(GETVECTITEM): + accu = Field(accu, Long_val(sp[0])); + sp += 1; + Next; + Instruct(SETVECTITEM): + caml_modify(&Field(accu, Long_val(sp[0])), sp[1]); + accu = Val_unit; + sp += 2; + Next; + +/* Bytes/String operations */ + Instruct(GETSTRINGCHAR): + Instruct(GETBYTESCHAR): + accu = Val_int(Byte_u(accu, Long_val(sp[0]))); + sp += 1; + Next; + Instruct(SETBYTESCHAR): + Byte_u(accu, Long_val(sp[0])) = Int_val(sp[1]); + sp += 2; + accu = Val_unit; + Next; + +/* Branches and conditional branches */ + + Instruct(BRANCH): + pc += *pc; + Next; + Instruct(BRANCHIF): + if (accu != Val_false) pc += *pc; else pc++; + Next; + Instruct(BRANCHIFNOT): + if (accu == Val_false) pc += *pc; else pc++; + Next; + Instruct(SWITCH): { + uint32_t sizes = *pc++; + if (Is_block(accu)) { + intnat index = Tag_val(accu); + CAMLassert ((uintnat) index < (sizes >> 16)); + pc += pc[(sizes & 0xFFFF) + index]; + } else { + intnat index = Long_val(accu); + CAMLassert ((uintnat) index < (sizes & 0xFFFF)) ; + pc += pc[index]; + } + Next; + } + Instruct(BOOLNOT): + accu = Val_not(accu); + Next; + +/* Exceptions */ + + Instruct(PUSHTRAP): + sp -= 4; + Trap_pc(sp) = pc + *pc; + Trap_link(sp) = caml_trapsp; + sp[2] = env; + sp[3] = Val_long(extra_args); + caml_trapsp = sp; + pc++; + Next; + + Instruct(POPTRAP): + if (caml_something_to_do) { + /* We must check here so that if a signal is pending and its + handler triggers an exception, the exception is trapped + by the current try...with, not the enclosing one. */ + pc--; /* restart the POPTRAP after processing the signal */ + goto process_signal; + } + caml_trapsp = Trap_link(sp); + sp += 4; + Next; + + Instruct(RAISE_NOTRACE): + if (caml_trapsp >= caml_trap_barrier) caml_debugger(TRAP_BARRIER); + goto raise_notrace; + + Instruct(RERAISE): + if (caml_trapsp >= caml_trap_barrier) caml_debugger(TRAP_BARRIER); + if (caml_backtrace_active) caml_stash_backtrace(accu, pc, sp, 1); + goto raise_notrace; + + Instruct(RAISE): + raise_exception: + if (caml_trapsp >= caml_trap_barrier) caml_debugger(TRAP_BARRIER); + if (caml_backtrace_active) caml_stash_backtrace(accu, pc, sp, 0); + raise_notrace: + if ((char *) caml_trapsp + >= (char *) caml_stack_high - initial_sp_offset) { + caml_external_raise = initial_external_raise; + caml_extern_sp = (value *) ((char *) caml_stack_high + - initial_sp_offset); + caml_callback_depth--; + return Make_exception_result(accu); + } + sp = caml_trapsp; + pc = Trap_pc(sp); + caml_trapsp = Trap_link(sp); + env = sp[2]; + extra_args = Long_val(sp[3]); + sp += 4; + Next; + +/* Stack checks */ + + check_stacks: + if (sp < caml_stack_threshold) { + caml_extern_sp = sp; + caml_realloc_stack(Stack_threshold / sizeof(value)); + sp = caml_extern_sp; + } + /* Fall through CHECK_SIGNALS */ + +/* Signal handling */ + + Instruct(CHECK_SIGNALS): /* accu not preserved */ + if (caml_something_to_do) goto process_signal; + Next; + + process_signal: + caml_something_to_do = 0; + Setup_for_event; + caml_process_event(); + Restore_after_event; + Next; + +/* Calling C functions */ + + Instruct(C_CALL1): + Setup_for_c_call; + accu = Primitive(*pc)(accu); + Restore_after_c_call; + pc++; + Next; + Instruct(C_CALL2): + Setup_for_c_call; + accu = Primitive(*pc)(accu, sp[1]); + Restore_after_c_call; + sp += 1; + pc++; + Next; + Instruct(C_CALL3): + Setup_for_c_call; + accu = Primitive(*pc)(accu, sp[1], sp[2]); + Restore_after_c_call; + sp += 2; + pc++; + Next; + Instruct(C_CALL4): + Setup_for_c_call; + accu = Primitive(*pc)(accu, sp[1], sp[2], sp[3]); + Restore_after_c_call; + sp += 3; + pc++; + Next; + Instruct(C_CALL5): + Setup_for_c_call; + accu = Primitive(*pc)(accu, sp[1], sp[2], sp[3], sp[4]); + Restore_after_c_call; + sp += 4; + pc++; + Next; + Instruct(C_CALLN): { + int nargs = *pc++; + *--sp = accu; + Setup_for_c_call; + accu = Primitive(*pc)(sp + 1, nargs); + Restore_after_c_call; + sp += nargs; + pc++; + Next; + } + +/* Integer constants */ + + Instruct(CONST0): + accu = Val_int(0); Next; + Instruct(CONST1): + accu = Val_int(1); Next; + Instruct(CONST2): + accu = Val_int(2); Next; + Instruct(CONST3): + accu = Val_int(3); Next; + + Instruct(PUSHCONST0): + *--sp = accu; accu = Val_int(0); Next; + Instruct(PUSHCONST1): + *--sp = accu; accu = Val_int(1); Next; + Instruct(PUSHCONST2): + *--sp = accu; accu = Val_int(2); Next; + Instruct(PUSHCONST3): + *--sp = accu; accu = Val_int(3); Next; + + Instruct(PUSHCONSTINT): + *--sp = accu; + /* Fallthrough */ + Instruct(CONSTINT): + accu = Val_int(*pc); + pc++; + Next; + +/* Integer arithmetic */ + + Instruct(NEGINT): + accu = (value)(2 - (intnat)accu); Next; + Instruct(ADDINT): + accu = (value)((intnat) accu + (intnat) *sp++ - 1); Next; + Instruct(SUBINT): + accu = (value)((intnat) accu - (intnat) *sp++ + 1); Next; + Instruct(MULINT): + accu = Val_long(Long_val(accu) * Long_val(*sp++)); Next; + + Instruct(DIVINT): { + intnat divisor = Long_val(*sp++); + if (divisor == 0) { Setup_for_c_call; caml_raise_zero_divide(); } + accu = Val_long(Long_val(accu) / divisor); + Next; + } + Instruct(MODINT): { + intnat divisor = Long_val(*sp++); + if (divisor == 0) { Setup_for_c_call; caml_raise_zero_divide(); } + accu = Val_long(Long_val(accu) % divisor); + Next; + } + Instruct(ANDINT): + accu = (value)((intnat) accu & (intnat) *sp++); Next; + Instruct(ORINT): + accu = (value)((intnat) accu | (intnat) *sp++); Next; + Instruct(XORINT): + accu = (value)(((intnat) accu ^ (intnat) *sp++) | 1); Next; + Instruct(LSLINT): + accu = (value)((((intnat) accu - 1) << Long_val(*sp++)) + 1); Next; + Instruct(LSRINT): + accu = (value)((((uintnat) accu) >> Long_val(*sp++)) | 1); Next; + Instruct(ASRINT): + accu = (value)((((intnat) accu) >> Long_val(*sp++)) | 1); Next; + +#define Integer_comparison(typ,opname,tst) \ + Instruct(opname): \ + accu = Val_int((typ) accu tst (typ) *sp++); Next; + + Integer_comparison(intnat,EQ, ==) + Integer_comparison(intnat,NEQ, !=) + Integer_comparison(intnat,LTINT, <) + Integer_comparison(intnat,LEINT, <=) + Integer_comparison(intnat,GTINT, >) + Integer_comparison(intnat,GEINT, >=) + Integer_comparison(uintnat,ULTINT, <) + Integer_comparison(uintnat,UGEINT, >=) + +#define Integer_branch_comparison(typ,opname,tst,debug) \ + Instruct(opname): \ + if ( *pc++ tst (typ) Long_val(accu)) { \ + pc += *pc ; \ + } else { \ + pc++ ; \ + } ; Next; + + Integer_branch_comparison(intnat,BEQ, ==, "==") + Integer_branch_comparison(intnat,BNEQ, !=, "!=") + Integer_branch_comparison(intnat,BLTINT, <, "<") + Integer_branch_comparison(intnat,BLEINT, <=, "<=") + Integer_branch_comparison(intnat,BGTINT, >, ">") + Integer_branch_comparison(intnat,BGEINT, >=, ">=") + Integer_branch_comparison(uintnat,BULTINT, <, "<") + Integer_branch_comparison(uintnat,BUGEINT, >=, ">=") + + Instruct(OFFSETINT): + accu += *pc << 1; + pc++; + Next; + Instruct(OFFSETREF): + Field(accu, 0) += *pc << 1; + accu = Val_unit; + pc++; + Next; + Instruct(ISINT): + accu = Val_long(accu & 1); + Next; + +/* Object-oriented operations */ + +#define Lookup(obj, lab) Field (Field (obj, 0), Int_val(lab)) + + /* please don't forget to keep below code in sync with the + functions caml_cache_public_method and + caml_cache_public_method2 in obj.c */ + + Instruct(GETMETHOD): + accu = Lookup(sp[0], accu); + Next; + +#define CAML_METHOD_CACHE +#ifdef CAML_METHOD_CACHE + Instruct(GETPUBMET): { + /* accu == object, pc[0] == tag, pc[1] == cache */ + value meths = Field (accu, 0); + value ofs; +#ifdef CAML_TEST_CACHE + static int calls = 0, hits = 0; + if (calls >= 10000000) { + fprintf(stderr, "cache hit = %d%%\n", hits / 100000); + calls = 0; hits = 0; + } + calls++; +#endif + *--sp = accu; + accu = Val_int(*pc++); + ofs = *pc & Field(meths,1); + if (*(value*)(((char*)&Field(meths,3)) + ofs) == accu) { +#ifdef CAML_TEST_CACHE + hits++; +#endif + accu = *(value*)(((char*)&Field(meths,2)) + ofs); + } + else + { + int li = 3, hi = Field(meths,0), mi; + while (li < hi) { + mi = ((li+hi) >> 1) | 1; + if (accu < Field(meths,mi)) hi = mi-2; + else li = mi; + } + *pc = (li-3)*sizeof(value); + accu = Field (meths, li-1); + } + pc++; + Next; + } +#else + Instruct(GETPUBMET): + *--sp = accu; + accu = Val_int(*pc); + pc += 2; + /* Fallthrough */ +#endif + Instruct(GETDYNMET): { + /* accu == tag, sp[0] == object, *pc == cache */ + value meths = Field (sp[0], 0); + int li = 3, hi = Field(meths,0), mi; + while (li < hi) { + mi = ((li+hi) >> 1) | 1; + if (accu < Field(meths,mi)) hi = mi-2; + else li = mi; + } + accu = Field (meths, li-1); + Next; + } + +/* Debugging and machine control */ + + Instruct(STOP): + caml_external_raise = initial_external_raise; + caml_extern_sp = sp; + caml_callback_depth--; + return accu; + + Instruct(EVENT): + if (--caml_event_count == 0) { + Setup_for_debugger; + caml_debugger(EVENT_COUNT); + Restore_after_debugger; + } + Restart_curr_instr; + + Instruct(BREAK): + Setup_for_debugger; + caml_debugger(BREAKPOINT); + Restore_after_debugger; + Restart_curr_instr; + +#ifndef THREADED_CODE + default: +#if _MSC_VER >= 1200 + __assume(0); +#else + caml_fatal_error("bad opcode (%" + ARCH_INTNAT_PRINTF_FORMAT "x)", + (intnat) *(pc-1)); +#endif + } + } +#endif +} + +void caml_prepare_bytecode(code_t prog, asize_t prog_size) { + /* other implementations of the interpreter (such as an hypothetical + JIT translator) might want to do something with a bytecode before + running it */ + CAMLassert(prog); + CAMLassert(prog_size>0); + /* actually, the threading of the bytecode might be done here */ +} + +void caml_release_bytecode(code_t prog, asize_t prog_size) { + /* other implementations of the interpreter (such as an hypothetical + JIT translator) might want to know when a bytecode is removed */ + /* check that we have a program */ + CAMLassert(prog); + CAMLassert(prog_size>0); +} diff --git a/runtime/ints.c b/runtime/ints.c new file mode 100644 index 00000000..df6c65a4 --- /dev/null +++ b/runtime/ints.c @@ -0,0 +1,847 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +#include +#include +#include "caml/alloc.h" +#include "caml/custom.h" +#include "caml/fail.h" +#include "caml/intext.h" +#include "caml/memory.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" + +static const char * parse_sign_and_base(const char * p, + /*out*/ int * base, + /*out*/ int * signedness, + /*out*/ int * sign) +{ + *sign = 1; + if (*p == '-') { + *sign = -1; + p++; + } else if (*p == '+') + p++; + *base = 10; *signedness = 1; + if (*p == '0') { + switch (p[1]) { + case 'x': case 'X': + *base = 16; *signedness = 0; p += 2; break; + case 'o': case 'O': + *base = 8; *signedness = 0; p += 2; break; + case 'b': case 'B': + *base = 2; *signedness = 0; p += 2; break; + case 'u': case 'U': + *signedness = 0; p += 2; break; + } + } + return p; +} + +static int parse_digit(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + else + return -1; +} + +#define INT_ERRMSG "int_of_string" +#define INT32_ERRMSG "Int32.of_string" +#define INT64_ERRMSG "Int64.of_string" +#define INTNAT_ERRMSG "Nativeint.of_string" + +static intnat parse_intnat(value s, int nbits, const char *errmsg) +{ + const char * p; + uintnat res, threshold; + int sign, base, signedness, d; + + p = parse_sign_and_base(String_val(s), &base, &signedness, &sign); + threshold = ((uintnat) -1) / base; + d = parse_digit(*p); + if (d < 0 || d >= base) caml_failwith(errmsg); + for (p++, res = d; /*nothing*/; p++) { + char c = *p; + if (c == '_') continue; + d = parse_digit(c); + if (d < 0 || d >= base) break; + /* Detect overflow in multiplication base * res */ + if (res > threshold) caml_failwith(errmsg); + res = base * res + d; + /* Detect overflow in addition (base * res) + d */ + if (res < (uintnat) d) caml_failwith(errmsg); + } + if (p != String_val(s) + caml_string_length(s)){ + caml_failwith(errmsg); + } + if (signedness) { + /* Signed representation expected, allow -2^(nbits-1) to 2^(nbits-1) - 1 */ + if (sign >= 0) { + if (res >= (uintnat)1 << (nbits - 1)) caml_failwith(errmsg); + } else { + if (res > (uintnat)1 << (nbits - 1)) caml_failwith(errmsg); + } + } else { + /* Unsigned representation expected, allow 0 to 2^nbits - 1 + and tolerate -(2^nbits - 1) to 0 */ + if (nbits < sizeof(uintnat) * 8 && res >= (uintnat)1 << nbits) + caml_failwith(errmsg); + } + return sign < 0 ? -((intnat) res) : (intnat) res; +} + +value caml_bswap16_direct(value x) +{ + return ((((x & 0x00FF) << 8) | + ((x & 0xFF00) >> 8))); +} + +CAMLprim value caml_bswap16(value v) +{ + intnat x = Int_val(v); + return (Val_int ((((x & 0x00FF) << 8) | + ((x & 0xFF00) >> 8)))); +} + +/* Tagged integers */ + +CAMLprim value caml_int_compare(value v1, value v2) +{ + int res = (v1 > v2) - (v1 < v2); + return Val_int(res); +} + +CAMLprim value caml_int_of_string(value s) +{ + return Val_long(parse_intnat(s, 8 * sizeof(value) - 1, INT_ERRMSG)); +} + +#define FORMAT_BUFFER_SIZE 32 + +static char parse_format(value fmt, + char * suffix, + char format_string[FORMAT_BUFFER_SIZE]) +{ + char * p; + char lastletter; + mlsize_t len, len_suffix; + + /* Copy OCaml format fmt to format_string, + adding the suffix before the last letter of the format */ + len = caml_string_length(fmt); + len_suffix = strlen(suffix); + if (len + len_suffix + 1 >= FORMAT_BUFFER_SIZE) + caml_invalid_argument("format_int: format too long"); + memmove(format_string, String_val(fmt), len); + p = format_string + len - 1; + lastletter = *p; + /* Compress two-letter formats, ignoring the [lnL] annotation */ + if (p[-1] == 'l' || p[-1] == 'n' || p[-1] == 'L') p--; + memmove(p, suffix, len_suffix); p += len_suffix; + *p++ = lastletter; + *p = 0; + /* Return the conversion type (last letter) */ + return lastletter; +} + +CAMLprim value caml_format_int(value fmt, value arg) +{ + char format_string[FORMAT_BUFFER_SIZE]; + char conv; + value res; + + conv = parse_format(fmt, ARCH_INTNAT_PRINTF_FORMAT, format_string); + switch (conv) { + case 'u': case 'x': case 'X': case 'o': + res = caml_alloc_sprintf(format_string, Unsigned_long_val(arg)); + break; + default: + res = caml_alloc_sprintf(format_string, Long_val(arg)); + break; + } + return res; +} + +/* 32-bit integers */ + +static int int32_cmp(value v1, value v2) +{ + int32_t i1 = Int32_val(v1); + int32_t i2 = Int32_val(v2); + return (i1 > i2) - (i1 < i2); +} + +static intnat int32_hash(value v) +{ + return Int32_val(v); +} + +static void int32_serialize(value v, uintnat * bsize_32, + uintnat * bsize_64) +{ + caml_serialize_int_4(Int32_val(v)); + *bsize_32 = *bsize_64 = 4; +} + +static uintnat int32_deserialize(void * dst) +{ + *((int32_t *) dst) = caml_deserialize_sint_4(); + return 4; +} + +static const struct custom_fixed_length int32_length = { 4, 4 }; + +CAMLexport struct custom_operations caml_int32_ops = { + "_i", + custom_finalize_default, + int32_cmp, + int32_hash, + int32_serialize, + int32_deserialize, + custom_compare_ext_default, + &int32_length +}; + +CAMLexport value caml_copy_int32(int32_t i) +{ + value res = caml_alloc_custom(&caml_int32_ops, 4, 0, 1); + Int32_val(res) = i; + return res; +} + +CAMLprim value caml_int32_neg(value v) +{ return caml_copy_int32(- Int32_val(v)); } + +CAMLprim value caml_int32_add(value v1, value v2) +{ return caml_copy_int32(Int32_val(v1) + Int32_val(v2)); } + +CAMLprim value caml_int32_sub(value v1, value v2) +{ return caml_copy_int32(Int32_val(v1) - Int32_val(v2)); } + +CAMLprim value caml_int32_mul(value v1, value v2) +{ return caml_copy_int32(Int32_val(v1) * Int32_val(v2)); } + +CAMLprim value caml_int32_div(value v1, value v2) +{ + int32_t dividend = Int32_val(v1); + int32_t divisor = Int32_val(v2); + if (divisor == 0) caml_raise_zero_divide(); + /* PR#4740: on some processors, division crashes on overflow. + Implement the same behavior as for type "int". */ + if (dividend == (1<<31) && divisor == -1) return v1; + return caml_copy_int32(dividend / divisor); +} + +CAMLprim value caml_int32_mod(value v1, value v2) +{ + int32_t dividend = Int32_val(v1); + int32_t divisor = Int32_val(v2); + if (divisor == 0) caml_raise_zero_divide(); + /* PR#4740: on some processors, modulus crashes if division overflows. + Implement the same behavior as for type "int". */ + if (dividend == (1<<31) && divisor == -1) return caml_copy_int32(0); + return caml_copy_int32(dividend % divisor); +} + +CAMLprim value caml_int32_and(value v1, value v2) +{ return caml_copy_int32(Int32_val(v1) & Int32_val(v2)); } + +CAMLprim value caml_int32_or(value v1, value v2) +{ return caml_copy_int32(Int32_val(v1) | Int32_val(v2)); } + +CAMLprim value caml_int32_xor(value v1, value v2) +{ return caml_copy_int32(Int32_val(v1) ^ Int32_val(v2)); } + +CAMLprim value caml_int32_shift_left(value v1, value v2) +{ return caml_copy_int32(Int32_val(v1) << Int_val(v2)); } + +CAMLprim value caml_int32_shift_right(value v1, value v2) +{ return caml_copy_int32(Int32_val(v1) >> Int_val(v2)); } + +CAMLprim value caml_int32_shift_right_unsigned(value v1, value v2) +{ return caml_copy_int32((uint32_t)Int32_val(v1) >> Int_val(v2)); } + +static int32_t caml_swap32(int32_t x) +{ + return (((x & 0x000000FF) << 24) | + ((x & 0x0000FF00) << 8) | + ((x & 0x00FF0000) >> 8) | + ((x & 0xFF000000) >> 24)); +} + +value caml_int32_direct_bswap(value v) +{ return caml_swap32((int32_t) v); } + +CAMLprim value caml_int32_bswap(value v) +{ return caml_copy_int32(caml_swap32(Int32_val(v))); } + +CAMLprim value caml_int32_of_int(value v) +{ return caml_copy_int32((int32_t) Long_val(v)); } + +CAMLprim value caml_int32_to_int(value v) +{ return Val_long(Int32_val(v)); } + +int32_t caml_int32_of_float_unboxed(double x) +{ return (int32_t) x; } + +CAMLprim value caml_int32_of_float(value v) +{ return caml_copy_int32((int32_t)(Double_val(v))); } + +double caml_int32_to_float_unboxed(int32_t x) +{ return (double) x; } + +CAMLprim value caml_int32_to_float(value v) +{ return caml_copy_double((double)(Int32_val(v))); } + +intnat caml_int32_compare_unboxed(int32_t i1, int32_t i2) +{ + return (i1 > i2) - (i1 < i2); +} + +CAMLprim value caml_int32_compare(value v1, value v2) +{ + return Val_int(caml_int32_compare_unboxed(Int32_val(v1),Int32_val(v2))); +} + +CAMLprim value caml_int32_format(value fmt, value arg) +{ + char format_string[FORMAT_BUFFER_SIZE]; + + parse_format(fmt, ARCH_INT32_PRINTF_FORMAT, format_string); + return caml_alloc_sprintf(format_string, Int32_val(arg)); +} + +CAMLprim value caml_int32_of_string(value s) +{ + return caml_copy_int32((int32_t) parse_intnat(s, 32, INT32_ERRMSG)); +} + +int32_t caml_int32_bits_of_float_unboxed(double d) +{ + union { float f; int32_t i; } u; + u.f = (float) d; + return u.i; +} + +double caml_int32_float_of_bits_unboxed(int32_t i) +{ + union { float f; int32_t i; } u; + u.i = i; + return (double) u.f; +} + +CAMLprim value caml_int32_bits_of_float(value vd) +{ + return caml_copy_int32(caml_int32_bits_of_float_unboxed(Double_val(vd))); +} + +CAMLprim value caml_int32_float_of_bits(value vi) +{ + return caml_copy_double(caml_int32_float_of_bits_unboxed(Int32_val(vi))); +} + +/* 64-bit integers */ + +#ifdef ARCH_ALIGN_INT64 + +CAMLexport int64_t caml_Int64_val(value v) +{ + union { int32_t i[2]; int64_t j; } buffer; + buffer.i[0] = ((int32_t *) Data_custom_val(v))[0]; + buffer.i[1] = ((int32_t *) Data_custom_val(v))[1]; + return buffer.j; +} + +#endif + +static int int64_cmp(value v1, value v2) +{ + int64_t i1 = Int64_val(v1); + int64_t i2 = Int64_val(v2); + return (i1 > i2) - (i1 < i2); +} + +static intnat int64_hash(value v) +{ + int64_t x = Int64_val(v); + uint32_t lo = (uint32_t) x, hi = (uint32_t) (x >> 32); + return hi ^ lo; +} + +static void int64_serialize(value v, uintnat * bsize_32, + uintnat * bsize_64) +{ + caml_serialize_int_8(Int64_val(v)); + *bsize_32 = *bsize_64 = 8; +} + +static uintnat int64_deserialize(void * dst) +{ +#ifndef ARCH_ALIGN_INT64 + *((int64_t *) dst) = caml_deserialize_sint_8(); +#else + union { int32_t i[2]; int64_t j; } buffer; + buffer.j = caml_deserialize_sint_8(); + ((int32_t *) dst)[0] = buffer.i[0]; + ((int32_t *) dst)[1] = buffer.i[1]; +#endif + return 8; +} + +static const struct custom_fixed_length int64_length = { 8, 8 }; + +CAMLexport struct custom_operations caml_int64_ops = { + "_j", + custom_finalize_default, + int64_cmp, + int64_hash, + int64_serialize, + int64_deserialize, + custom_compare_ext_default, + &int64_length +}; + +CAMLexport value caml_copy_int64(int64_t i) +{ + value res = caml_alloc_custom(&caml_int64_ops, 8, 0, 1); +#ifndef ARCH_ALIGN_INT64 + Int64_val(res) = i; +#else + union { int32_t i[2]; int64_t j; } buffer; + buffer.j = i; + ((int32_t *) Data_custom_val(res))[0] = buffer.i[0]; + ((int32_t *) Data_custom_val(res))[1] = buffer.i[1]; +#endif + return res; +} + +#define CAMLprim_int64_1(name) \ + CAMLprim int64_t caml_int64_##name##_native(int64_t); \ + \ + CAMLprim value caml_int64_##name(value v) \ + { return caml_copy_int64(caml_int64_##name##_native(Int64_val(v))); } \ + \ + CAMLprim int64_t caml_int64_##name##_native + +#define CAMLprim_int64_2(name) \ + CAMLprim int64_t caml_int64_##name##_native(int64_t, int64_t); \ + \ + CAMLprim value caml_int64_##name(value v1, value v2) \ + { return caml_copy_int64(caml_int64_##name##_native(Int64_val(v1), \ + Int64_val(v2))); } \ + \ + CAMLprim int64_t caml_int64_##name##_native + +CAMLprim_int64_1(neg)(int64_t i) +{ return -i; } + +CAMLprim_int64_2(add)(int64_t i1, int64_t i2) +{ return i1 + i2; } + +CAMLprim_int64_2(sub)(int64_t i1, int64_t i2) +{ return i1 - i2; } + +CAMLprim_int64_2(mul)(int64_t i1, int64_t i2) +{ return i1 * i2; } + +CAMLprim_int64_2(div)(int64_t dividend, int64_t divisor) +{ + if (divisor == 0) caml_raise_zero_divide(); + /* PR#4740: on some processors, division crashes on overflow. + Implement the same behavior as for type "int". */ + if (dividend == ((int64_t)1 << 63) && divisor == -1) return dividend; + return dividend / divisor; +} + +CAMLprim_int64_2(mod)(int64_t dividend, int64_t divisor) +{ + if (divisor == 0) caml_raise_zero_divide(); + /* PR#4740: on some processors, division crashes on overflow. + Implement the same behavior as for type "int". */ + if (dividend == ((int64_t)1 << 63) && divisor == -1) return 0; + return dividend % divisor; +} + +CAMLprim_int64_2(and)(int64_t i1, int64_t i2) +{ return i1 & i2; } + +CAMLprim_int64_2(or)(int64_t i1, int64_t i2) +{ return i1 | i2; } + +CAMLprim_int64_2(xor)(int64_t i1, int64_t i2) +{ return i1 ^ i2; } + +CAMLprim value caml_int64_shift_left(value v1, value v2) +{ return caml_copy_int64(Int64_val(v1) << Int_val(v2)); } + +CAMLprim value caml_int64_shift_right(value v1, value v2) +{ return caml_copy_int64(Int64_val(v1) >> Int_val(v2)); } + +CAMLprim value caml_int64_shift_right_unsigned(value v1, value v2) +{ return caml_copy_int64((uint64_t) (Int64_val(v1)) >> Int_val(v2)); } + +#ifdef ARCH_SIXTYFOUR +static value caml_swap64(value x) +{ + return (((((x) & 0x00000000000000FF) << 56) | + (((x) & 0x000000000000FF00) << 40) | + (((x) & 0x0000000000FF0000) << 24) | + (((x) & 0x00000000FF000000) << 8) | + (((x) & 0x000000FF00000000) >> 8) | + (((x) & 0x0000FF0000000000) >> 24) | + (((x) & 0x00FF000000000000) >> 40) | + (((x) & 0xFF00000000000000) >> 56))); +} + +value caml_int64_direct_bswap(value v) +{ return caml_swap64(v); } +#endif + +CAMLprim value caml_int64_bswap(value v) +{ + int64_t x = Int64_val(v); + return caml_copy_int64 + (((x & INT64_LITERAL(0x00000000000000FFU)) << 56) | + ((x & INT64_LITERAL(0x000000000000FF00U)) << 40) | + ((x & INT64_LITERAL(0x0000000000FF0000U)) << 24) | + ((x & INT64_LITERAL(0x00000000FF000000U)) << 8) | + ((x & INT64_LITERAL(0x000000FF00000000U)) >> 8) | + ((x & INT64_LITERAL(0x0000FF0000000000U)) >> 24) | + ((x & INT64_LITERAL(0x00FF000000000000U)) >> 40) | + ((x & INT64_LITERAL(0xFF00000000000000U)) >> 56)); +} + +CAMLprim value caml_int64_of_int(value v) +{ return caml_copy_int64((int64_t) (Long_val(v))); } + +CAMLprim value caml_int64_to_int(value v) +{ return Val_long((intnat) (Int64_val(v))); } + +int64_t caml_int64_of_float_unboxed(double x) +{ return (int64_t) x; } + +CAMLprim value caml_int64_of_float(value v) +{ return caml_copy_int64((int64_t) (Double_val(v))); } + +double caml_int64_to_float_unboxed(int64_t x) +{ return (double) x; } + +CAMLprim value caml_int64_to_float(value v) +{ return caml_copy_double((double) (Int64_val(v))); } + +CAMLprim value caml_int64_of_int32(value v) +{ return caml_copy_int64((int64_t) (Int32_val(v))); } + +CAMLprim value caml_int64_to_int32(value v) +{ return caml_copy_int32((int32_t) (Int64_val(v))); } + +CAMLprim value caml_int64_of_nativeint(value v) +{ return caml_copy_int64((int64_t) (Nativeint_val(v))); } + +CAMLprim value caml_int64_to_nativeint(value v) +{ return caml_copy_nativeint((intnat) (Int64_val(v))); } + +intnat caml_int64_compare_unboxed(int64_t i1, int64_t i2) +{ + return (i1 > i2) - (i1 < i2); +} + +CAMLprim value caml_int64_compare(value v1, value v2) +{ + return Val_int(caml_int64_compare_unboxed(Int64_val(v1),Int64_val(v2))); +} + +CAMLprim value caml_int64_format(value fmt, value arg) +{ + char format_string[FORMAT_BUFFER_SIZE]; + + parse_format(fmt, ARCH_INT64_PRINTF_FORMAT, format_string); + return caml_alloc_sprintf(format_string, Int64_val(arg)); +} + +CAMLprim value caml_int64_of_string(value s) +{ + const char * p; + uint64_t res, threshold; + int sign, base, signedness, d; + + p = parse_sign_and_base(String_val(s), &base, &signedness, &sign); + threshold = ((uint64_t) -1) / base; + d = parse_digit(*p); + if (d < 0 || d >= base) caml_failwith(INT64_ERRMSG); + res = d; + for (p++; /*nothing*/; p++) { + char c = *p; + if (c == '_') continue; + d = parse_digit(c); + if (d < 0 || d >= base) break; + /* Detect overflow in multiplication base * res */ + if (res > threshold) caml_failwith(INT64_ERRMSG); + res = base * res + d; + /* Detect overflow in addition (base * res) + d */ + if (res < (uint64_t) d) caml_failwith(INT64_ERRMSG); + } + if (p != String_val(s) + caml_string_length(s)){ + caml_failwith(INT64_ERRMSG); + } + if (signedness) { + /* Signed representation expected, allow -2^63 to 2^63 - 1 only */ + if (sign >= 0) { + if (res >= (uint64_t)1 << 63) caml_failwith(INT64_ERRMSG); + } else { + if (res > (uint64_t)1 << 63) caml_failwith(INT64_ERRMSG); + } + } + if (sign < 0) res = - res; + return caml_copy_int64(res); +} + +int64_t caml_int64_bits_of_float_unboxed(double d) +{ + union { double d; int64_t i; int32_t h[2]; } u; + u.d = d; +#if defined(__arm__) && !defined(__ARM_EABI__) + { int32_t t = u.h[0]; u.h[0] = u.h[1]; u.h[1] = t; } +#endif + return u.i; +} + +double caml_int64_float_of_bits_unboxed(int64_t i) +{ + union { double d; int64_t i; int32_t h[2]; } u; + u.i = i; +#if defined(__arm__) && !defined(__ARM_EABI__) + { int32_t t = u.h[0]; u.h[0] = u.h[1]; u.h[1] = t; } +#endif + return u.d; +} + +CAMLprim value caml_int64_bits_of_float(value vd) +{ + return caml_copy_int64(caml_int64_bits_of_float_unboxed(Double_val(vd))); +} + +CAMLprim value caml_int64_float_of_bits(value vi) +{ + return caml_copy_double(caml_int64_float_of_bits_unboxed(Int64_val(vi))); +} + +/* Native integers */ + +static int nativeint_cmp(value v1, value v2) +{ + intnat i1 = Nativeint_val(v1); + intnat i2 = Nativeint_val(v2); + return (i1 > i2) - (i1 < i2); +} + +static intnat nativeint_hash(value v) +{ + intnat n = Nativeint_val(v); +#ifdef ARCH_SIXTYFOUR + /* 32/64 bits compatibility trick. See explanations in file "hash.c", + function caml_hash_mix_intnat. */ + return (n >> 32) ^ (n >> 63) ^ n; +#else + return n; +#endif +} + +static void nativeint_serialize(value v, uintnat * bsize_32, + uintnat * bsize_64) +{ + intnat l = Nativeint_val(v); +#ifdef ARCH_SIXTYFOUR + if (l >= -((intnat)1 << 31) && l < ((intnat)1 << 31)) { + caml_serialize_int_1(1); + caml_serialize_int_4((int32_t) l); + } else { + caml_serialize_int_1(2); + caml_serialize_int_8(l); + } +#else + caml_serialize_int_1(1); + caml_serialize_int_4(l); +#endif + *bsize_32 = 4; + *bsize_64 = 8; +} + +static uintnat nativeint_deserialize(void * dst) +{ + switch (caml_deserialize_uint_1()) { + case 1: + *((intnat *) dst) = caml_deserialize_sint_4(); + break; + case 2: +#ifdef ARCH_SIXTYFOUR + *((intnat *) dst) = caml_deserialize_sint_8(); +#else + caml_deserialize_error("input_value: native integer value too large"); +#endif + break; + default: + caml_deserialize_error("input_value: ill-formed native integer"); + } + return sizeof(intnat); +} + +static const struct custom_fixed_length nativeint_length = { 4, 8 }; +CAMLexport struct custom_operations caml_nativeint_ops = { + "_n", + custom_finalize_default, + nativeint_cmp, + nativeint_hash, + nativeint_serialize, + nativeint_deserialize, + custom_compare_ext_default, + &nativeint_length +}; + +CAMLexport value caml_copy_nativeint(intnat i) +{ + value res = caml_alloc_custom(&caml_nativeint_ops, sizeof(intnat), 0, 1); + Nativeint_val(res) = i; + return res; +} + +CAMLprim value caml_nativeint_neg(value v) +{ return caml_copy_nativeint(- Nativeint_val(v)); } + +CAMLprim value caml_nativeint_add(value v1, value v2) +{ return caml_copy_nativeint(Nativeint_val(v1) + Nativeint_val(v2)); } + +CAMLprim value caml_nativeint_sub(value v1, value v2) +{ return caml_copy_nativeint(Nativeint_val(v1) - Nativeint_val(v2)); } + +CAMLprim value caml_nativeint_mul(value v1, value v2) +{ return caml_copy_nativeint(Nativeint_val(v1) * Nativeint_val(v2)); } + +#define Nativeint_min_int ((intnat) 1 << (sizeof(intnat) * 8 - 1)) + +CAMLprim value caml_nativeint_div(value v1, value v2) +{ + intnat dividend = Nativeint_val(v1); + intnat divisor = Nativeint_val(v2); + if (divisor == 0) caml_raise_zero_divide(); + /* PR#4740: on some processors, modulus crashes if division overflows. + Implement the same behavior as for type "int". */ + if (dividend == Nativeint_min_int && divisor == -1) return v1; + return caml_copy_nativeint(dividend / divisor); +} + +CAMLprim value caml_nativeint_mod(value v1, value v2) +{ + intnat dividend = Nativeint_val(v1); + intnat divisor = Nativeint_val(v2); + if (divisor == 0) caml_raise_zero_divide(); + /* PR#4740: on some processors, modulus crashes if division overflows. + Implement the same behavior as for type "int". */ + if (dividend == Nativeint_min_int && divisor == -1){ + return caml_copy_nativeint(0); + } + return caml_copy_nativeint(dividend % divisor); +} + +CAMLprim value caml_nativeint_and(value v1, value v2) +{ return caml_copy_nativeint(Nativeint_val(v1) & Nativeint_val(v2)); } + +CAMLprim value caml_nativeint_or(value v1, value v2) +{ return caml_copy_nativeint(Nativeint_val(v1) | Nativeint_val(v2)); } + +CAMLprim value caml_nativeint_xor(value v1, value v2) +{ return caml_copy_nativeint(Nativeint_val(v1) ^ Nativeint_val(v2)); } + +CAMLprim value caml_nativeint_shift_left(value v1, value v2) +{ return caml_copy_nativeint(Nativeint_val(v1) << Int_val(v2)); } + +CAMLprim value caml_nativeint_shift_right(value v1, value v2) +{ return caml_copy_nativeint(Nativeint_val(v1) >> Int_val(v2)); } + +CAMLprim value caml_nativeint_shift_right_unsigned(value v1, value v2) +{ return caml_copy_nativeint((uintnat)Nativeint_val(v1) >> Int_val(v2)); } + +value caml_nativeint_direct_bswap(value v) +{ +#ifdef ARCH_SIXTYFOUR + return caml_swap64(v); +#else + return caml_swap32(v); +#endif +} + +CAMLprim value caml_nativeint_bswap(value v) +{ +#ifdef ARCH_SIXTYFOUR + return caml_copy_nativeint(caml_swap64(Nativeint_val(v))); +#else + return caml_copy_nativeint(caml_swap32(Nativeint_val(v))); +#endif +} + +CAMLprim value caml_nativeint_of_int(value v) +{ return caml_copy_nativeint(Long_val(v)); } + +CAMLprim value caml_nativeint_to_int(value v) +{ return Val_long(Nativeint_val(v)); } + +intnat caml_nativeint_of_float_unboxed(double x) +{ return (intnat) x; } + +CAMLprim value caml_nativeint_of_float(value v) +{ return caml_copy_nativeint((intnat)(Double_val(v))); } + +double caml_nativeint_to_float_unboxed(intnat x) +{ return (double) x; } + +CAMLprim value caml_nativeint_to_float(value v) +{ return caml_copy_double((double)(Nativeint_val(v))); } + +CAMLprim value caml_nativeint_of_int32(value v) +{ return caml_copy_nativeint(Int32_val(v)); } + +CAMLprim value caml_nativeint_to_int32(value v) +{ return caml_copy_int32((int32_t) Nativeint_val(v)); } + +intnat caml_nativeint_compare_unboxed(intnat i1, intnat i2) +{ + return (i1 > i2) - (i1 < i2); +} + +CAMLprim value caml_nativeint_compare(value v1, value v2) +{ + return Val_int(caml_nativeint_compare_unboxed(Nativeint_val(v1), + Nativeint_val(v2))); +} + +CAMLprim value caml_nativeint_format(value fmt, value arg) +{ + char format_string[FORMAT_BUFFER_SIZE]; + + parse_format(fmt, ARCH_INTNAT_PRINTF_FORMAT, format_string); + return caml_alloc_sprintf(format_string, Nativeint_val(arg)); +} + +CAMLprim value caml_nativeint_of_string(value s) +{ + return caml_copy_nativeint(parse_intnat(s, 8 * sizeof(value), INTNAT_ERRMSG)); +} diff --git a/runtime/io.c b/runtime/io.c new file mode 100644 index 00000000..90a1aa64 --- /dev/null +++ b/runtime/io.c @@ -0,0 +1,835 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Buffered input/output. */ + +#include +#include +#include +#include +#include +#include +#include "caml/config.h" +#ifdef HAS_UNISTD +#include +#endif +#ifdef __CYGWIN__ +#include +#endif +#include "caml/alloc.h" +#include "caml/custom.h" +#include "caml/fail.h" +#include "caml/io.h" +#include "caml/memory.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/osdeps.h" +#include "caml/signals.h" +#include "caml/sys.h" + +#ifndef SEEK_SET +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif + +#if defined(_WIN32) +#include +#define lseek _lseeki64 +#endif + + +/* Hooks for locking channels */ + +CAMLexport void (*caml_channel_mutex_free) (struct channel *) = NULL; +CAMLexport void (*caml_channel_mutex_lock) (struct channel *) = NULL; +CAMLexport void (*caml_channel_mutex_unlock) (struct channel *) = NULL; +CAMLexport void (*caml_channel_mutex_unlock_exn) (void) = NULL; + +/* List of opened channels */ +CAMLexport struct channel * caml_all_opened_channels = NULL; + +/* Basic functions over type struct channel *. + These functions can be called directly from C. + No locking is performed. */ + +/* Functions shared between input and output */ + +CAMLexport struct channel * caml_open_descriptor_in(int fd) +{ + struct channel * channel; + + channel = (struct channel *) caml_stat_alloc(sizeof(struct channel)); + channel->fd = fd; + caml_enter_blocking_section(); + channel->offset = lseek(fd, 0, SEEK_CUR); + caml_leave_blocking_section(); + channel->curr = channel->max = channel->buff; + channel->end = channel->buff + IO_BUFFER_SIZE; + channel->mutex = NULL; + channel->revealed = 0; + channel->old_revealed = 0; + channel->refcount = 0; + channel->flags = 0; + channel->next = caml_all_opened_channels; + channel->prev = NULL; + channel->name = NULL; + if (caml_all_opened_channels != NULL) + caml_all_opened_channels->prev = channel; + caml_all_opened_channels = channel; + return channel; +} + +CAMLexport struct channel * caml_open_descriptor_out(int fd) +{ + struct channel * channel; + + channel = caml_open_descriptor_in(fd); + channel->max = NULL; + return channel; +} + +static void unlink_channel(struct channel *channel) +{ + if (channel->prev == NULL) { + CAMLassert (channel == caml_all_opened_channels); + caml_all_opened_channels = caml_all_opened_channels->next; + if (caml_all_opened_channels != NULL) + caml_all_opened_channels->prev = NULL; + } else { + channel->prev->next = channel->next; + if (channel->next != NULL) channel->next->prev = channel->prev; + } +} + +CAMLexport void caml_close_channel(struct channel *channel) +{ + close(channel->fd); + if (channel->refcount > 0) return; + if (caml_channel_mutex_free != NULL) (*caml_channel_mutex_free)(channel); + unlink_channel(channel); + caml_stat_free(channel->name); + caml_stat_free(channel); +} + +CAMLexport file_offset caml_channel_size(struct channel *channel) +{ + file_offset offset; + file_offset end; + int fd; + + /* We extract data from [channel] before dropping the OCaml lock, in case + someone else touches the block. */ + fd = channel->fd; + offset = channel->offset; + caml_enter_blocking_section(); + end = lseek(fd, 0, SEEK_END); + if (end == -1 || lseek(fd, offset, SEEK_SET) != offset) { + caml_leave_blocking_section(); + caml_sys_error(NO_ARG); + } + caml_leave_blocking_section(); + return end; +} + +CAMLexport int caml_channel_binary_mode(struct channel *channel) +{ +#if defined(_WIN32) || defined(__CYGWIN__) + int oldmode = setmode(channel->fd, O_BINARY); + if (oldmode == O_TEXT) setmode(channel->fd, O_TEXT); + return oldmode == O_BINARY; +#else + return 1; +#endif +} + +/* Output */ + +/* Attempt to flush the buffer. This will make room in the buffer for + at least one character. Returns true if the buffer is empty at the + end of the flush, or false if some data remains in the buffer. + */ + +CAMLexport int caml_flush_partial(struct channel *channel) +{ + int towrite, written; + + towrite = channel->curr - channel->buff; + CAMLassert (towrite >= 0); + if (towrite > 0) { + written = caml_write_fd(channel->fd, channel->flags, + channel->buff, towrite); + channel->offset += written; + if (written < towrite) + memmove(channel->buff, channel->buff + written, towrite - written); + channel->curr -= written; + } + return (channel->curr == channel->buff); +} + +/* Flush completely the buffer. */ + +CAMLexport void caml_flush(struct channel *channel) +{ + while (! caml_flush_partial(channel)) /*nothing*/; +} + +/* Output data */ + +CAMLexport void caml_putword(struct channel *channel, uint32_t w) +{ + if (! caml_channel_binary_mode(channel)) + caml_failwith("output_binary_int: not a binary channel"); + caml_putch(channel, w >> 24); + caml_putch(channel, w >> 16); + caml_putch(channel, w >> 8); + caml_putch(channel, w); +} + +CAMLexport int caml_putblock(struct channel *channel, char *p, intnat len) +{ + int n, free, towrite, written; + + n = len >= INT_MAX ? INT_MAX : (int) len; + free = channel->end - channel->curr; + if (n < free) { + /* Write request small enough to fit in buffer: transfer to buffer. */ + memmove(channel->curr, p, n); + channel->curr += n; + return n; + } else { + /* Write request overflows buffer (or just fills it up): transfer whatever + fits to buffer and write the buffer */ + memmove(channel->curr, p, free); + towrite = channel->end - channel->buff; + written = caml_write_fd(channel->fd, channel->flags, + channel->buff, towrite); + if (written < towrite) + memmove(channel->buff, channel->buff + written, towrite - written); + channel->offset += written; + channel->curr = channel->end - written; + return free; + } +} + +CAMLexport void caml_really_putblock(struct channel *channel, + char *p, intnat len) +{ + int written; + while (len > 0) { + written = caml_putblock(channel, p, len); + p += written; + len -= written; + } +} + +CAMLexport void caml_seek_out(struct channel *channel, file_offset dest) +{ + caml_flush(channel); + caml_enter_blocking_section(); + if (lseek(channel->fd, dest, SEEK_SET) != dest) { + caml_leave_blocking_section(); + caml_sys_error(NO_ARG); + } + caml_leave_blocking_section(); + channel->offset = dest; +} + +CAMLexport file_offset caml_pos_out(struct channel *channel) +{ + return channel->offset + (file_offset)(channel->curr - channel->buff); +} + +/* Input */ + +/* caml_do_read is exported for Cash */ +CAMLexport int caml_do_read(int fd, char *p, unsigned int n) +{ + return caml_read_fd(fd, 0, p, n); +} + +CAMLexport unsigned char caml_refill(struct channel *channel) +{ + int n; + + n = caml_read_fd(channel->fd, channel->flags, + channel->buff, channel->end - channel->buff); + if (n == 0) caml_raise_end_of_file(); + channel->offset += n; + channel->max = channel->buff + n; + channel->curr = channel->buff + 1; + return (unsigned char)(channel->buff[0]); +} + +CAMLexport uint32_t caml_getword(struct channel *channel) +{ + int i; + uint32_t res; + + if (! caml_channel_binary_mode(channel)) + caml_failwith("input_binary_int: not a binary channel"); + res = 0; + for(i = 0; i < 4; i++) { + res = (res << 8) + caml_getch(channel); + } + return res; +} + +CAMLexport int caml_getblock(struct channel *channel, char *p, intnat len) +{ + int n, avail, nread; + + n = len >= INT_MAX ? INT_MAX : (int) len; + avail = channel->max - channel->curr; + if (n <= avail) { + memmove(p, channel->curr, n); + channel->curr += n; + return n; + } else if (avail > 0) { + memmove(p, channel->curr, avail); + channel->curr += avail; + return avail; + } else { + nread = caml_read_fd(channel->fd, channel->flags, channel->buff, + channel->end - channel->buff); + channel->offset += nread; + channel->max = channel->buff + nread; + if (n > nread) n = nread; + memmove(p, channel->buff, n); + channel->curr = channel->buff + n; + return n; + } +} + +/* Returns the number of bytes read. */ +CAMLexport intnat caml_really_getblock(struct channel *chan, char *p, intnat n) +{ + intnat k = n; + int r; + while (k > 0) { + r = caml_getblock(chan, p, k); + if (r == 0) break; + p += r; + k -= r; + } + return n - k; +} + +CAMLexport void caml_seek_in(struct channel *channel, file_offset dest) +{ + if (dest >= channel->offset - (channel->max - channel->buff) && + dest <= channel->offset) { + channel->curr = channel->max - (channel->offset - dest); + } else { + caml_enter_blocking_section(); + if (lseek(channel->fd, dest, SEEK_SET) != dest) { + caml_leave_blocking_section(); + caml_sys_error(NO_ARG); + } + caml_leave_blocking_section(); + channel->offset = dest; + channel->curr = channel->max = channel->buff; + } +} + +CAMLexport file_offset caml_pos_in(struct channel *channel) +{ + return channel->offset - (file_offset)(channel->max - channel->curr); +} + +CAMLexport intnat caml_input_scan_line(struct channel *channel) +{ + char * p; + int n; + + p = channel->curr; + do { + if (p >= channel->max) { + /* No more characters available in the buffer */ + if (channel->curr > channel->buff) { + /* Try to make some room in the buffer by shifting the unread + portion at the beginning */ + memmove(channel->buff, channel->curr, channel->max - channel->curr); + n = channel->curr - channel->buff; + channel->curr -= n; + channel->max -= n; + p -= n; + } + if (channel->max >= channel->end) { + /* Buffer is full, no room to read more characters from the input. + Return the number of characters in the buffer, with negative + sign to indicate that no newline was encountered. */ + return -(channel->max - channel->curr); + } + /* Fill the buffer as much as possible */ + n = caml_read_fd(channel->fd, channel->flags, + channel->max, channel->end - channel->max); + if (n == 0) { + /* End-of-file encountered. Return the number of characters in the + buffer, with negative sign since we haven't encountered + a newline. */ + return -(channel->max - channel->curr); + } + channel->offset += n; + channel->max += n; + } + } while (*p++ != '\n'); + /* Found a newline. Return the length of the line, newline included. */ + return (p - channel->curr); +} + +/* OCaml entry points for the I/O functions. Wrap struct channel * + objects into a heap-allocated object. Perform locking + and unlocking around the I/O operations. */ + +/* FIXME CAMLexport, but not in io.h exported for Cash ? */ +CAMLexport void caml_finalize_channel(value vchan) +{ + struct channel * chan = Channel(vchan); + if ((chan->flags & CHANNEL_FLAG_MANAGED_BY_GC) == 0) return; + if (--chan->refcount > 0) return; + if (caml_channel_mutex_free != NULL) (*caml_channel_mutex_free)(chan); + + if (chan->fd != -1 && chan->name && caml_runtime_warnings_active()) + fprintf(stderr, + "[ocaml] channel opened on file '%s' dies without being closed\n", + chan->name + ); + + if (chan->max == NULL && chan->curr != chan->buff){ + /* + This is an unclosed out channel (chan->max == NULL) with a + non-empty buffer: keep it around so the OCaml [at_exit] function + gets a chance to flush it. We would want to simply flush the + channel now, but (i) flushing can raise exceptions, and (ii) it + is potentially a blocking operation. Both are forbidden in a + finalization function. + + Refs: + http://caml.inria.fr/mantis/view.php?id=6902 + https://github.com/ocaml/ocaml/pull/210 + */ + if (chan->name && caml_runtime_warnings_active()) + fprintf(stderr, + "[ocaml] (moreover, it has unflushed data)\n" + ); + } else { + unlink_channel(chan); + caml_stat_free(chan->name); + caml_stat_free(chan); + } +} + +static int compare_channel(value vchan1, value vchan2) +{ + struct channel * chan1 = Channel(vchan1); + struct channel * chan2 = Channel(vchan2); + return (chan1 == chan2) ? 0 : (chan1 < chan2) ? -1 : 1; +} + +static intnat hash_channel(value vchan) +{ + return (intnat) (Channel(vchan)); +} + +static struct custom_operations channel_operations = { + "_chan", + caml_finalize_channel, + compare_channel, + hash_channel, + custom_serialize_default, + custom_deserialize_default, + custom_compare_ext_default, + custom_fixed_length_default +}; + +CAMLexport value caml_alloc_channel(struct channel *chan) +{ + value res; + chan->refcount++; /* prevent finalization during next alloc */ + res = caml_alloc_custom_mem(&channel_operations, sizeof(struct channel *), + sizeof(struct channel)); + Channel(res) = chan; + return res; +} + +CAMLprim value caml_ml_open_descriptor_in(value fd) +{ + struct channel * chan = caml_open_descriptor_in(Int_val(fd)); + chan->flags |= CHANNEL_FLAG_MANAGED_BY_GC; + return caml_alloc_channel(chan); +} + +CAMLprim value caml_ml_open_descriptor_out(value fd) +{ + struct channel * chan = caml_open_descriptor_out(Int_val(fd)); + chan->flags |= CHANNEL_FLAG_MANAGED_BY_GC; + return caml_alloc_channel(chan); +} + +CAMLprim value caml_ml_set_channel_name(value vchannel, value vname) +{ + struct channel * channel = Channel(vchannel); + caml_stat_free(channel->name); + if (caml_string_length(vname) > 0) + channel->name = caml_stat_strdup(String_val(vname)); + else + channel->name = NULL; + return Val_unit; +} + +#define Pair_tag 0 + +CAMLprim value caml_ml_out_channels_list (value unit) +{ + CAMLparam0 (); + CAMLlocal3 (res, tail, chan); + struct channel * channel; + + res = Val_emptylist; + for (channel = caml_all_opened_channels; + channel != NULL; + channel = channel->next) + /* Testing channel->fd >= 0 looks unnecessary, as + caml_ml_close_channel changes max when setting fd to -1. */ + if (channel->max == NULL) { + chan = caml_alloc_channel (channel); + tail = res; + res = caml_alloc_small (2, Pair_tag); + Field (res, 0) = chan; + Field (res, 1) = tail; + } + CAMLreturn (res); +} + +CAMLprim value caml_channel_descriptor(value vchannel) +{ + int fd = Channel(vchannel)->fd; + if (fd == -1) { errno = EBADF; caml_sys_error(NO_ARG); } + return Val_int(fd); +} + +CAMLprim value caml_ml_close_channel(value vchannel) +{ + int result; + int do_syscall; + int fd; + + /* For output channels, must have flushed before */ + struct channel * channel = Channel(vchannel); + if (channel->fd != -1){ + fd = channel->fd; + channel->fd = -1; + do_syscall = 1; + }else{ + do_syscall = 0; + result = 0; + } + /* Ensure that every read or write on the channel will cause an + immediate caml_flush_partial or caml_refill, thus raising a Sys_error + exception */ + channel->curr = channel->max = channel->end; + + if (do_syscall) { + caml_enter_blocking_section(); + result = close(fd); + caml_leave_blocking_section(); + } + + if (result == -1) caml_sys_error (NO_ARG); + return Val_unit; +} + +/* EOVERFLOW is the Unix98 error indicating that a file position or file + size is not representable. + ERANGE is the ANSI C error indicating that some argument to some + function is out of range. This is less precise than EOVERFLOW, + but guaranteed to be defined on all ANSI C environments. */ +#ifndef EOVERFLOW +#define EOVERFLOW ERANGE +#endif + +CAMLprim value caml_ml_channel_size(value vchannel) +{ + file_offset size = caml_channel_size(Channel(vchannel)); + if (size > Max_long) { errno = EOVERFLOW; caml_sys_error(NO_ARG); } + return Val_long(size); +} + +CAMLprim value caml_ml_channel_size_64(value vchannel) +{ + return Val_file_offset(caml_channel_size(Channel(vchannel))); +} + +CAMLprim value caml_ml_set_binary_mode(value vchannel, value mode) +{ +#if defined(_WIN32) || defined(__CYGWIN__) + struct channel * channel = Channel(vchannel); +#if defined(_WIN32) + /* The implementation of [caml_read_fd] and [caml_write_fd] in win32.c + doesn't support socket I/O with CRLF conversion. */ + if ((channel->flags & CHANNEL_FLAG_FROM_SOCKET) != 0 + && ! Bool_val(mode)) { + errno = EINVAL; + caml_sys_error(NO_ARG); + } +#endif + if (setmode(channel->fd, Bool_val(mode) ? O_BINARY : O_TEXT) == -1) + caml_sys_error(NO_ARG); +#endif + return Val_unit; +} + +/* + If the channel is closed, DO NOT raise a "bad file descriptor" + exception, but do nothing (the buffer is already empty). + This is because some libraries will flush at exit, even on + file descriptors that may be closed. +*/ + +CAMLprim value caml_ml_flush_partial(value vchannel) +{ + CAMLparam1 (vchannel); + struct channel * channel = Channel(vchannel); + int res; + + if (channel->fd == -1) CAMLreturn(Val_true); + Lock(channel); + res = caml_flush_partial(channel); + Unlock(channel); + CAMLreturn (Val_bool(res)); +} + +CAMLprim value caml_ml_flush(value vchannel) +{ + CAMLparam1 (vchannel); + struct channel * channel = Channel(vchannel); + + if (channel->fd == -1) CAMLreturn(Val_unit); + Lock(channel); + caml_flush(channel); + Unlock(channel); + CAMLreturn (Val_unit); +} + +CAMLprim value caml_ml_output_char(value vchannel, value ch) +{ + CAMLparam2 (vchannel, ch); + struct channel * channel = Channel(vchannel); + + Lock(channel); + caml_putch(channel, Long_val(ch)); + Unlock(channel); + CAMLreturn (Val_unit); +} + +CAMLprim value caml_ml_output_int(value vchannel, value w) +{ + CAMLparam2 (vchannel, w); + struct channel * channel = Channel(vchannel); + + Lock(channel); + caml_putword(channel, (uint32_t) Long_val(w)); + Unlock(channel); + CAMLreturn (Val_unit); +} + +CAMLprim value caml_ml_output_partial(value vchannel, value buff, value start, + value length) +{ + CAMLparam4 (vchannel, buff, start, length); + struct channel * channel = Channel(vchannel); + int res; + + Lock(channel); + res = caml_putblock(channel, &Byte(buff, Long_val(start)), Long_val(length)); + Unlock(channel); + CAMLreturn (Val_int(res)); +} + +CAMLprim value caml_ml_output_bytes(value vchannel, value buff, value start, + value length) +{ + CAMLparam4 (vchannel, buff, start, length); + struct channel * channel = Channel(vchannel); + intnat pos = Long_val(start); + intnat len = Long_val(length); + + Lock(channel); + /* We cannot call caml_really_putblock here because buff may move + during caml_write_fd */ + while (len > 0) { + int written = caml_putblock(channel, &Byte(buff, pos), len); + pos += written; + len -= written; + } + Unlock(channel); + CAMLreturn (Val_unit); +} + +CAMLprim value caml_ml_output(value vchannel, value buff, value start, + value length) +{ + return caml_ml_output_bytes (vchannel, buff, start, length); +} + +CAMLprim value caml_ml_seek_out(value vchannel, value pos) +{ + CAMLparam2 (vchannel, pos); + struct channel * channel = Channel(vchannel); + + Lock(channel); + caml_seek_out(channel, Long_val(pos)); + Unlock(channel); + CAMLreturn (Val_unit); +} + +CAMLprim value caml_ml_seek_out_64(value vchannel, value pos) +{ + CAMLparam2 (vchannel, pos); + struct channel * channel = Channel(vchannel); + + Lock(channel); + caml_seek_out(channel, File_offset_val(pos)); + Unlock(channel); + CAMLreturn (Val_unit); +} + +CAMLprim value caml_ml_pos_out(value vchannel) +{ + file_offset pos = caml_pos_out(Channel(vchannel)); + if (pos > Max_long) { errno = EOVERFLOW; caml_sys_error(NO_ARG); } + return Val_long(pos); +} + +CAMLprim value caml_ml_pos_out_64(value vchannel) +{ + return Val_file_offset(caml_pos_out(Channel(vchannel))); +} + +CAMLprim value caml_ml_input_char(value vchannel) +{ + CAMLparam1 (vchannel); + struct channel * channel = Channel(vchannel); + unsigned char c; + + Lock(channel); + c = caml_getch(channel); + Unlock(channel); + CAMLreturn (Val_long(c)); +} + +CAMLprim value caml_ml_input_int(value vchannel) +{ + CAMLparam1 (vchannel); + struct channel * channel = Channel(vchannel); + intnat i; + + Lock(channel); + i = caml_getword(channel); + Unlock(channel); +#ifdef ARCH_SIXTYFOUR + i = (i << 32) >> 32; /* Force sign extension */ +#endif + CAMLreturn (Val_long(i)); +} + +CAMLprim value caml_ml_input(value vchannel, value buff, value vstart, + value vlength) +{ + CAMLparam4 (vchannel, buff, vstart, vlength); + struct channel * channel = Channel(vchannel); + intnat start, len; + int n, avail, nread; + + Lock(channel); + /* We cannot call caml_getblock here because buff may move during + caml_read_fd */ + start = Long_val(vstart); + len = Long_val(vlength); + n = len >= INT_MAX ? INT_MAX : (int) len; + avail = channel->max - channel->curr; + if (n <= avail) { + memmove(&Byte(buff, start), channel->curr, n); + channel->curr += n; + } else if (avail > 0) { + memmove(&Byte(buff, start), channel->curr, avail); + channel->curr += avail; + n = avail; + } else { + nread = caml_read_fd(channel->fd, channel->flags, channel->buff, + channel->end - channel->buff); + channel->offset += nread; + channel->max = channel->buff + nread; + if (n > nread) n = nread; + memmove(&Byte(buff, start), channel->buff, n); + channel->curr = channel->buff + n; + } + Unlock(channel); + CAMLreturn (Val_long(n)); +} + +CAMLprim value caml_ml_seek_in(value vchannel, value pos) +{ + CAMLparam2 (vchannel, pos); + struct channel * channel = Channel(vchannel); + + Lock(channel); + caml_seek_in(channel, Long_val(pos)); + Unlock(channel); + CAMLreturn (Val_unit); +} + +CAMLprim value caml_ml_seek_in_64(value vchannel, value pos) +{ + CAMLparam2 (vchannel, pos); + struct channel * channel = Channel(vchannel); + + Lock(channel); + caml_seek_in(channel, File_offset_val(pos)); + Unlock(channel); + CAMLreturn (Val_unit); +} + +CAMLprim value caml_ml_pos_in(value vchannel) +{ + file_offset pos = caml_pos_in(Channel(vchannel)); + if (pos > Max_long) { errno = EOVERFLOW; caml_sys_error(NO_ARG); } + return Val_long(pos); +} + +CAMLprim value caml_ml_pos_in_64(value vchannel) +{ + return Val_file_offset(caml_pos_in(Channel(vchannel))); +} + +CAMLprim value caml_ml_input_scan_line(value vchannel) +{ + CAMLparam1 (vchannel); + struct channel * channel = Channel(vchannel); + intnat res; + + Lock(channel); + res = caml_input_scan_line(channel); + Unlock(channel); + CAMLreturn (Val_long(res)); +} + +CAMLprim value caml_terminfo_rows(value vchannel) +{ + return Val_int(caml_num_rows_fd(Channel(vchannel)->fd)); +} diff --git a/byterun/lexing.c b/runtime/lexing.c similarity index 100% rename from byterun/lexing.c rename to runtime/lexing.c diff --git a/byterun/main.c b/runtime/main.c similarity index 100% rename from byterun/main.c rename to runtime/main.c diff --git a/runtime/major_gc.c b/runtime/major_gc.c new file mode 100644 index 00000000..2fde9e84 --- /dev/null +++ b/runtime/major_gc.c @@ -0,0 +1,948 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +#include +#include + +#include "caml/compact.h" +#include "caml/custom.h" +#include "caml/config.h" +#include "caml/fail.h" +#include "caml/finalise.h" +#include "caml/freelist.h" +#include "caml/gc.h" +#include "caml/gc_ctrl.h" +#include "caml/major_gc.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/roots.h" +#include "caml/signals.h" +#include "caml/weak.h" + +#if defined (NATIVE_CODE) && defined (NO_NAKED_POINTERS) +#define NATIVE_CODE_AND_NO_NAKED_POINTERS +#else +#undef NATIVE_CODE_AND_NO_NAKED_POINTERS +#endif + +#ifdef _MSC_VER +static inline double fmin(double a, double b) { + return (a < b) ? a : b; +} +#endif + +uintnat caml_percent_free; +uintnat caml_major_heap_increment; +CAMLexport char *caml_heap_start; +char *caml_gc_sweep_hp; +int caml_gc_phase; /* always Phase_mark, Pase_clean, + Phase_sweep, or Phase_idle */ +static value *gray_vals; +static value *gray_vals_cur, *gray_vals_end; +static asize_t gray_vals_size; +static int heap_is_pure; /* The heap is pure if the only gray objects + below [markhp] are also in [gray_vals]. */ +uintnat caml_allocated_words; +uintnat caml_dependent_size, caml_dependent_allocated; +double caml_extra_heap_resources; +uintnat caml_fl_wsz_at_phase_change = 0; + +extern char *caml_fl_merge; /* Defined in freelist.c. */ + +static char *markhp, *chunk, *limit; +static double p_backlog = 0.0; /* backlog for the gc speedup parameter */ + +int caml_gc_subphase; /* Subphase_{mark_roots,mark_main,mark_final} */ + +/** + Ephemerons: + During mark phase the list caml_ephe_list_head of ephemerons + is iterated by different pointers that follow the invariants: + caml_ephe_list_head ->* ephes_checked_if_pure ->* ephes_to_check ->* null + | | | + (1) (2) (3) + + At the start of mark phase, (1) and (2) are empty. + + In mark phase: + - the ephemerons in (1) have a data alive or none + (nb: new ephemerons are added in this part by weak.c) + - the ephemerons in (2) have at least a white key or are white + if ephe_list_pure is true, otherwise they are in an unknown state and + must be checked again. + - the ephemerons in (3) are in an unknown state and must be checked + + At the end of mark phase, (3) is empty and ephe_list_pure is true. + The ephemeron in (1) and (2) will be cleaned (white keys and datas + replaced by none or the ephemeron is removed from the list if it is white) + in clean phase. + + In clean phase: + caml_ephe_list_head ->* ephes_to_check ->* null + | | + (1) (3) + + In clean phase, (2) is not used, ephes_to_check is initialized at + caml_ephe_list_head: + - the ephemerons in (1) are clean. + - the ephemerons in (3) should be cleaned or removed if white. + + */ +static int ephe_list_pure; +/** The ephemerons is pure if since the start of its iteration + no value have been darken. */ +static value *ephes_checked_if_pure; +static value *ephes_to_check; + +int caml_major_window = 1; +double caml_major_ring[Max_major_window] = { 0. }; +int caml_major_ring_index = 0; +double caml_major_work_credit = 0.0; +double caml_gc_clock = 0.0; + +#ifdef DEBUG +static unsigned long major_gc_counter = 0; +#endif + +void (*caml_major_gc_hook)(void) = NULL; + +static void realloc_gray_vals (void) +{ + value *new; + + CAMLassert (gray_vals_cur == gray_vals_end); + if (gray_vals_size < caml_stat_heap_wsz / 32){ + caml_gc_message (0x08, "Growing gray_vals to %" + ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n", + (intnat) gray_vals_size * sizeof (value) / 512); + new = (value *) caml_stat_resize_noexc ((char *) gray_vals, + 2 * gray_vals_size * + sizeof (value)); + if (new == NULL){ + caml_gc_message (0x08, "No room for growing gray_vals\n"); + gray_vals_cur = gray_vals; + heap_is_pure = 0; + }else{ + gray_vals = new; + gray_vals_cur = gray_vals + gray_vals_size; + gray_vals_size *= 2; + gray_vals_end = gray_vals + gray_vals_size; + } + }else{ + gray_vals_cur = gray_vals + gray_vals_size / 2; + heap_is_pure = 0; + } +} + +void caml_darken (value v, value *p /* not used */) +{ +#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS + if (Is_block (v) && !Is_young (v) && Wosize_val (v) > 0) { +#else + if (Is_block (v) && Is_in_heap (v)) { +#endif + header_t h = Hd_val (v); + tag_t t = Tag_hd (h); + if (t == Infix_tag){ + v -= Infix_offset_val(v); + h = Hd_val (v); + t = Tag_hd (h); + } +#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS + /* We insist that naked pointers to outside the heap point to things that + look like values with headers coloured black. This isn't always + strictly necessary but is essential in certain cases---in particular + when the value is allocated in a read-only section. (For the values + where it would be safe it is a performance improvement since we avoid + putting them on the grey list.) */ + CAMLassert (Is_in_heap (v) || Is_black_hd (h)); +#endif + CAMLassert (!Is_blue_hd (h)); + if (Is_white_hd (h)){ + ephe_list_pure = 0; + if (t < No_scan_tag){ + Hd_val (v) = Grayhd_hd (h); + *gray_vals_cur++ = v; + if (gray_vals_cur >= gray_vals_end) realloc_gray_vals (); + }else{ + Hd_val (v) = Blackhd_hd (h); + } + } + } +} + +static void start_cycle (void) +{ + CAMLassert (caml_gc_phase == Phase_idle); + CAMLassert (gray_vals_cur == gray_vals); + caml_gc_message (0x01, "Starting new major GC cycle\n"); + caml_darken_all_roots_start (); + caml_gc_phase = Phase_mark; + caml_gc_subphase = Subphase_mark_roots; + markhp = NULL; + ephe_list_pure = 1; + ephes_checked_if_pure = &caml_ephe_list_head; + ephes_to_check = &caml_ephe_list_head; +#ifdef DEBUG + ++ major_gc_counter; + caml_heap_check (); +#endif +} + +/* We may stop the slice inside values, in order to avoid large latencies + on large arrays. In this case, [current_value] is the partially-marked + value and [current_index] is the index of the next field to be marked. +*/ +static value current_value = 0; +static mlsize_t current_index = 0; + +/* For instrumentation */ +#ifdef CAML_INSTR +#define INSTR(x) x +#else +#define INSTR(x) /**/ +#endif + +static void init_sweep_phase(void) +{ + /* Phase_clean is done. */ + /* Initialise the sweep phase. */ + caml_gc_sweep_hp = caml_heap_start; + caml_fl_init_merge (); + caml_gc_phase = Phase_sweep; + chunk = caml_heap_start; + caml_gc_sweep_hp = chunk; + limit = chunk + Chunk_size (chunk); + caml_fl_wsz_at_phase_change = caml_fl_cur_wsz; + if (caml_major_gc_hook) (*caml_major_gc_hook)(); +} + +/* auxiliary function of mark_slice */ +static inline value* mark_slice_darken(value *gray_vals_ptr, + value v, mlsize_t i, + int in_ephemeron, int *slice_pointers) +{ + value child; + header_t chd; + + child = Field (v, i); + +#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS + if (Is_block (child) + && ! Is_young (child) + && Wosize_val (child) > 0 /* Atoms never need to be marked. */ + /* Closure blocks contain code pointers at offsets that cannot + be reliably determined, so we always use the page table when + marking such values. */ + && (!(Tag_val (v) == Closure_tag || Tag_val (v) == Infix_tag) || + Is_in_heap (child))) { +#else + if (Is_block (child) && Is_in_heap (child)) { +#endif + INSTR (++ *slice_pointers;) + chd = Hd_val (child); + if (Tag_hd (chd) == Forward_tag){ + value f = Forward_val (child); + if ((in_ephemeron && Is_long(f)) || + (Is_block (f) + && (!Is_in_value_area(f) || Tag_val (f) == Forward_tag + || Tag_val (f) == Lazy_tag +#ifdef FLAT_FLOAT_ARRAY + || Tag_val (f) == Double_tag +#endif + ))){ + /* Do not short-circuit the pointer. */ + }else{ + /* The variable child is not changed because it must be mark alive */ + Field (v, i) = f; + if (Is_block (f) && Is_young (f) && !Is_young (child)){ + if(in_ephemeron){ + add_to_ephe_ref_table (&caml_ephe_ref_table, v, i); + }else{ + add_to_ref_table (&caml_ref_table, &Field (v, i)); + } + } + } + } + else if (Tag_hd(chd) == Infix_tag) { + child -= Infix_offset_val(child); + chd = Hd_val(child); + } +#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS + /* See [caml_darken] for a description of this assertion. */ + CAMLassert (Is_in_heap (child) || Is_black_hd (chd)); +#endif + if (Is_white_hd (chd)){ + ephe_list_pure = 0; + Hd_val (child) = Grayhd_hd (chd); + *gray_vals_ptr++ = child; + if (gray_vals_ptr >= gray_vals_end) { + gray_vals_cur = gray_vals_ptr; + realloc_gray_vals (); + gray_vals_ptr = gray_vals_cur; + } + } + } + + return gray_vals_ptr; +} + +static value* mark_ephe_aux (value *gray_vals_ptr, intnat *work, + int *slice_pointers) +{ + value v, data, key; + header_t hd; + mlsize_t size, i; + + v = *ephes_to_check; + hd = Hd_val(v); + CAMLassert(Tag_val (v) == Abstract_tag); + data = Field(v,CAML_EPHE_DATA_OFFSET); + if ( data != caml_ephe_none && + Is_block (data) && Is_in_heap (data) && Is_white_val (data)){ + + int alive_data = 1; + + /* The liveness of the ephemeron is one of the condition */ + if (Is_white_hd (hd)) alive_data = 0; + + /* The liveness of the keys not caml_ephe_none is the other condition */ + size = Wosize_hd (hd); + for (i = CAML_EPHE_FIRST_KEY; alive_data && i < size; i++){ + key = Field (v, i); + ephemeron_again: + if (key != caml_ephe_none && + Is_block (key) && Is_in_heap (key)){ + if (Tag_val (key) == Forward_tag){ + value f = Forward_val (key); + if (Is_long (f) || + (Is_block (f) && + (!Is_in_value_area(f) || Tag_val (f) == Forward_tag + || Tag_val (f) == Lazy_tag +#ifdef FLAT_FLOAT_ARRAY + || Tag_val (f) == Double_tag +#endif + ))){ + /* Do not short-circuit the pointer. */ + }else{ + Field (v, i) = key = f; + goto ephemeron_again; + } + } + if (Is_white_val (key)){ + alive_data = 0; + } + } + } + *work -= Whsize_wosize(i); + + if (alive_data){ + gray_vals_ptr = mark_slice_darken(gray_vals_ptr,v, + CAML_EPHE_DATA_OFFSET, + /*in_ephemeron=*/1, + slice_pointers); + } else { /* not triggered move to the next one */ + ephes_to_check = &Field(v,CAML_EPHE_LINK_OFFSET); + return gray_vals_ptr; + } + } else { /* a simily weak pointer or an already alive data */ + *work -= 1; + } + + /* all keys black or data none or black + move the ephemerons from (3) to the end of (1) */ + if ( ephes_checked_if_pure == ephes_to_check ) { + /* corner case and optim */ + ephes_checked_if_pure = &Field(v,CAML_EPHE_LINK_OFFSET); + ephes_to_check = ephes_checked_if_pure; + } else { + /* - remove v from the list (3) */ + *ephes_to_check = Field(v,CAML_EPHE_LINK_OFFSET); + /* - insert it at the end of (1) */ + Field(v,CAML_EPHE_LINK_OFFSET) = *ephes_checked_if_pure; + *ephes_checked_if_pure = v; + ephes_checked_if_pure = &Field(v,CAML_EPHE_LINK_OFFSET); + } + return gray_vals_ptr; +} + + + +static void mark_slice (intnat work) +{ + value *gray_vals_ptr; /* Local copy of [gray_vals_cur] */ + value v; + header_t hd; + mlsize_t size, i, start, end; /* [start] is a local copy of [current_index] */ +#ifdef CAML_INSTR + int slice_fields = 0; +#endif + int slice_pointers = 0; /** gcc removes it when not in CAML_INSTR */ + + caml_gc_message (0x40, "Marking %"ARCH_INTNAT_PRINTF_FORMAT"d words\n", work); + caml_gc_message (0x40, "Subphase = %d\n", caml_gc_subphase); + gray_vals_ptr = gray_vals_cur; + v = current_value; + start = current_index; + while (work > 0){ + if (v == 0 && gray_vals_ptr > gray_vals){ + CAMLassert (start == 0); + v = *--gray_vals_ptr; + CAMLassert (Is_gray_val (v)); + } + if (v != 0){ + hd = Hd_val(v); + CAMLassert (Is_gray_hd (hd)); + size = Wosize_hd (hd); + end = start + work; + if (Tag_hd (hd) < No_scan_tag){ + start = size < start ? size : start; + end = size < end ? size : end; + CAMLassert (end >= start); + INSTR (slice_fields += end - start;) + INSTR (if (size > end) + CAML_INSTR_INT ("major/mark/slice/remain", size - end);) + for (i = start; i < end; i++){ + gray_vals_ptr = mark_slice_darken(gray_vals_ptr,v,i, + /*in_ephemeron=*/ 0, + &slice_pointers); + } + if (end < size){ + work = 0; + start = end; + /* [v] doesn't change. */ + CAMLassert (Is_gray_val (v)); + }else{ + CAMLassert (end == size); + Hd_val (v) = Blackhd_hd (hd); + work -= Whsize_wosize(end - start); + start = 0; + v = 0; + } + }else{ + /* The block doesn't contain any pointers. */ + CAMLassert (start == 0); + Hd_val (v) = Blackhd_hd (hd); + work -= Whsize_wosize(size); + v = 0; + } + }else if (markhp != NULL){ + if (markhp == limit){ + chunk = Chunk_next (chunk); + if (chunk == NULL){ + markhp = NULL; + }else{ + markhp = chunk; + limit = chunk + Chunk_size (chunk); + } + }else{ + if (Is_gray_val (Val_hp (markhp))){ + CAMLassert (gray_vals_ptr == gray_vals); + CAMLassert (v == 0 && start == 0); + v = Val_hp (markhp); + } + markhp += Bhsize_hp (markhp); + } + }else if (!heap_is_pure){ + heap_is_pure = 1; + chunk = caml_heap_start; + markhp = chunk; + limit = chunk + Chunk_size (chunk); + } else if (caml_gc_subphase == Subphase_mark_roots) { + gray_vals_cur = gray_vals_ptr; + work = caml_darken_all_roots_slice (work); + gray_vals_ptr = gray_vals_cur; + if (work > 0){ + caml_gc_subphase = Subphase_mark_main; + } + } else if (*ephes_to_check != (value) NULL) { + /* Continue to scan the list of ephe */ + gray_vals_ptr = mark_ephe_aux(gray_vals_ptr,&work,&slice_pointers); + } else if (!ephe_list_pure){ + /* We must scan again the list because some value have been darken */ + ephe_list_pure = 1; + ephes_to_check = ephes_checked_if_pure; + }else{ + switch (caml_gc_subphase){ + case Subphase_mark_main: { + /* Subphase_mark_main is done. + Mark finalised values. */ + gray_vals_cur = gray_vals_ptr; + caml_final_update_mark_phase (); + gray_vals_ptr = gray_vals_cur; + if (gray_vals_ptr > gray_vals){ + v = *--gray_vals_ptr; + CAMLassert (start == 0); + } + /* Complete the marking */ + ephes_to_check = ephes_checked_if_pure; + caml_gc_subphase = Subphase_mark_final; + } + break; + case Subphase_mark_final: { + /** The set of unreachable value will not change anymore for + this cycle. Start clean phase. */ + caml_gc_phase = Phase_clean; + caml_final_update_clean_phase (); + if (caml_ephe_list_head != (value) NULL){ + /* Initialise the clean phase. */ + ephes_to_check = &caml_ephe_list_head; + } else { + /* Initialise the sweep phase. */ + init_sweep_phase(); + } + work = 0; + } + break; + default: CAMLassert (0); + } + } + } + gray_vals_cur = gray_vals_ptr; + current_value = v; + current_index = start; + INSTR (CAML_INSTR_INT ("major/mark/slice/fields#", slice_fields);) + INSTR (CAML_INSTR_INT ("major/mark/slice/pointers#", slice_pointers);) +} + +/* Clean ephemerons */ +static void clean_slice (intnat work) +{ + value v; + + caml_gc_message (0x40, "Cleaning %" + ARCH_INTNAT_PRINTF_FORMAT "d words\n", work); + while (work > 0){ + v = *ephes_to_check; + if (v != (value) NULL){ + if (Is_white_val (v)){ + /* The whole array is dead, remove it from the list. */ + *ephes_to_check = Field (v, CAML_EPHE_LINK_OFFSET); + work -= 1; + }else{ + caml_ephe_clean(v); + ephes_to_check = &Field (v, CAML_EPHE_LINK_OFFSET); + work -= Whsize_val (v); + } + }else{ /* End of list reached */ + /* Phase_clean is done. */ + /* Initialise the sweep phase. */ + init_sweep_phase(); + work = 0; + } + } +} + +static void sweep_slice (intnat work) +{ + char *hp; + header_t hd; + + caml_gc_message (0x40, "Sweeping %" + ARCH_INTNAT_PRINTF_FORMAT "d words\n", work); + while (work > 0){ + if (caml_gc_sweep_hp < limit){ + hp = caml_gc_sweep_hp; + hd = Hd_hp (hp); + work -= Whsize_hd (hd); + caml_gc_sweep_hp += Bhsize_hd (hd); + switch (Color_hd (hd)){ + case Caml_white: + if (Tag_hd (hd) == Custom_tag){ + void (*final_fun)(value) = Custom_ops_val(Val_hp(hp))->finalize; + if (final_fun != NULL) final_fun(Val_hp(hp)); + } + caml_gc_sweep_hp = (char *) caml_fl_merge_block (Val_hp (hp)); + break; + case Caml_blue: + /* Only the blocks of the free-list are blue. See [freelist.c]. */ + caml_fl_merge = Bp_hp (hp); + break; + default: /* gray or black */ + CAMLassert (Color_hd (hd) == Caml_black); + Hd_hp (hp) = Whitehd_hd (hd); + break; + } + CAMLassert (caml_gc_sweep_hp <= limit); + }else{ + chunk = Chunk_next (chunk); + if (chunk == NULL){ + /* Sweeping is done. */ + ++ caml_stat_major_collections; + work = 0; + caml_gc_phase = Phase_idle; + caml_request_minor_gc (); + }else{ + caml_gc_sweep_hp = chunk; + limit = chunk + Chunk_size (chunk); + } + } + } +} + +#ifdef CAML_INSTR +static char *mark_slice_name[] = { + /* 0 */ NULL, + /* 1 */ NULL, + /* 2 */ NULL, + /* 3 */ NULL, + /* 4 */ NULL, + /* 5 */ NULL, + /* 6 */ NULL, + /* 7 */ NULL, + /* 8 */ NULL, + /* 9 */ NULL, + /* 10 */ "major/mark_roots", + /* 11 */ "major/mark_main", + /* 12 */ "major/mark_weak1", + /* 13 */ "major/mark_weak2", + /* 14 */ "major/mark_final", +}; +#endif + +/* The main entry point for the major GC. Called about once for each + minor GC. [howmuch] is the amount of work to do: + -1 if the GC is triggered automatically + 0 to let the GC compute the amount of work + [n] to make the GC do enough work to (on average) free [n] words + */ +void caml_major_collection_slice (intnat howmuch) +{ + double p, dp, filt_p, spend; + intnat computed_work; + int i; + /* + Free memory at the start of the GC cycle (garbage + free list) (assumed): + FM = caml_stat_heap_wsz * caml_percent_free + / (100 + caml_percent_free) + + Assuming steady state and enforcing a constant allocation rate, then + FM is divided in 2/3 for garbage and 1/3 for free list. + G = 2 * FM / 3 + G is also the amount of memory that will be used during this cycle + (still assuming steady state). + + Proportion of G consumed since the previous slice: + PH = caml_allocated_words / G + = caml_allocated_words * 3 * (100 + caml_percent_free) + / (2 * caml_stat_heap_wsz * caml_percent_free) + Proportion of extra-heap resources consumed since the previous slice: + PE = caml_extra_heap_resources + Proportion of total work to do in this slice: + P = max (PH, PE) + + Here, we insert a time-based filter on the P variable to avoid large + latency spikes in the GC, so the P below is a smoothed-out version of + the P above. + + Amount of marking work for the GC cycle: + MW = caml_stat_heap_wsz * 100 / (100 + caml_percent_free) + + caml_incremental_roots_count + Amount of sweeping work for the GC cycle: + SW = caml_stat_heap_wsz + + In order to finish marking with a non-empty free list, we will + use 40% of the time for marking, and 60% for sweeping. + + Let MT be the time spent marking, ST the time spent sweeping, and TT + the total time for this cycle. We have: + MT = 40/100 * TT + ST = 60/100 * TT + + Amount of time to spend on this slice: + T = P * TT = P * MT / (40/100) = P * ST / (60/100) + + Since we must do MW work in MT time or SW work in ST time, the amount + of work for this slice is: + MS = P * MW / (40/100) if marking + SS = P * SW / (60/100) if sweeping + + Amount of marking work for a marking slice: + MS = P * MW / (40/100) + MS = P * (caml_stat_heap_wsz * 250 / (100 + caml_percent_free) + + 2.5 * caml_incremental_roots_count) + Amount of sweeping work for a sweeping slice: + SS = P * SW / (60/100) + SS = P * caml_stat_heap_wsz * 5 / 3 + + This slice will either mark MS words or sweep SS words. + */ + + if (caml_major_slice_begin_hook != NULL) (*caml_major_slice_begin_hook) (); + CAML_INSTR_SETUP (tmr, "major"); + + p = (double) caml_allocated_words * 3.0 * (100 + caml_percent_free) + / caml_stat_heap_wsz / caml_percent_free / 2.0; + if (caml_dependent_size > 0){ + dp = (double) caml_dependent_allocated * (100 + caml_percent_free) + / caml_dependent_size / caml_percent_free; + }else{ + dp = 0.0; + } + if (p < dp) p = dp; + if (p < caml_extra_heap_resources) p = caml_extra_heap_resources; + p += p_backlog; + p_backlog = 0.0; + if (p > 0.3){ + p_backlog = p - 0.3; + p = 0.3; + } + CAML_INSTR_INT ("major/work/extra#", + (uintnat) (caml_extra_heap_resources * 1000000)); + + caml_gc_message (0x40, "ordered work = %" + ARCH_INTNAT_PRINTF_FORMAT "d words\n", howmuch); + caml_gc_message (0x40, "allocated_words = %" + ARCH_INTNAT_PRINTF_FORMAT "u\n", + caml_allocated_words); + caml_gc_message (0x40, "extra_heap_resources = %" + ARCH_INTNAT_PRINTF_FORMAT "uu\n", + (uintnat) (caml_extra_heap_resources * 1000000)); + caml_gc_message (0x40, "raw work-to-do = %" + ARCH_INTNAT_PRINTF_FORMAT "du\n", + (intnat) (p * 1000000)); + caml_gc_message (0x40, "work backlog = %" + ARCH_INTNAT_PRINTF_FORMAT "du\n", + (intnat) (p_backlog * 1000000)); + + for (i = 0; i < caml_major_window; i++){ + caml_major_ring[i] += p / caml_major_window; + } + + if (caml_gc_clock >= 1.0){ + caml_gc_clock -= 1.0; + ++caml_major_ring_index; + if (caml_major_ring_index >= caml_major_window){ + caml_major_ring_index = 0; + } + } + if (howmuch == -1){ + /* auto-triggered GC slice: spend work credit on the current bucket, + then do the remaining work, if any */ + /* Note that the minor GC guarantees that the major slice is called in + automatic mode (with [howmuch] = -1) at least once per clock tick. + This means we never leave a non-empty bucket behind. */ + spend = fmin (caml_major_work_credit, + caml_major_ring[caml_major_ring_index]); + caml_major_work_credit -= spend; + filt_p = caml_major_ring[caml_major_ring_index] - spend; + caml_major_ring[caml_major_ring_index] = 0.0; + }else{ + /* forced GC slice: do work and add it to the credit */ + if (howmuch == 0){ + /* automatic setting: size of next bucket + we do not use the current bucket, as it may be empty */ + int i = caml_major_ring_index + 1; + if (i >= caml_major_window) i = 0; + filt_p = caml_major_ring[i]; + }else{ + /* manual setting */ + filt_p = (double) howmuch * 3.0 * (100 + caml_percent_free) + / caml_stat_heap_wsz / caml_percent_free / 2.0; + } + caml_major_work_credit += filt_p; + } + + p = filt_p; + + caml_gc_message (0x40, "filtered work-to-do = %" + ARCH_INTNAT_PRINTF_FORMAT "du\n", + (intnat) (p * 1000000)); + + if (caml_gc_phase == Phase_idle){ + if (caml_young_ptr == caml_young_alloc_end){ + /* We can only start a major GC cycle if the minor allocation arena + is empty, otherwise we'd have to treat it as a set of roots. */ + start_cycle (); + CAML_INSTR_TIME (tmr, "major/roots"); + } + p = 0; + goto finished; + } + + if (p < 0){ + p = 0; + goto finished; + } + + if (caml_gc_phase == Phase_mark || caml_gc_phase == Phase_clean){ + computed_work = (intnat) (p * ((double) caml_stat_heap_wsz * 250 + / (100 + caml_percent_free) + + caml_incremental_roots_count)); + }else{ + computed_work = (intnat) (p * caml_stat_heap_wsz * 5 / 3); + } + caml_gc_message (0x40, "computed work = %" + ARCH_INTNAT_PRINTF_FORMAT "d words\n", computed_work); + if (caml_gc_phase == Phase_mark){ + CAML_INSTR_INT ("major/work/mark#", computed_work); + mark_slice (computed_work); + CAML_INSTR_TIME (tmr, mark_slice_name[caml_gc_subphase]); + caml_gc_message (0x02, "!"); + }else if (caml_gc_phase == Phase_clean){ + clean_slice (computed_work); + caml_gc_message (0x02, "%%"); + }else{ + CAMLassert (caml_gc_phase == Phase_sweep); + CAML_INSTR_INT ("major/work/sweep#", computed_work); + sweep_slice (computed_work); + CAML_INSTR_TIME (tmr, "major/sweep"); + caml_gc_message (0x02, "$"); + } + + if (caml_gc_phase == Phase_idle){ + caml_compact_heap_maybe (); + CAML_INSTR_TIME (tmr, "major/check_and_compact"); + } + + finished: + caml_gc_message (0x40, "work-done = %" + ARCH_INTNAT_PRINTF_FORMAT "du\n", + (intnat) (p * 1000000)); + + /* if some of the work was not done, take it back from the credit + or spread it over the buckets. */ + p = filt_p - p; + spend = fmin (p, caml_major_work_credit); + caml_major_work_credit -= spend; + if (p > spend){ + p -= spend; + p /= caml_major_window; + for (i = 0; i < caml_major_window; i++) caml_major_ring[i] += p; + } + + caml_stat_major_words += caml_allocated_words; + caml_allocated_words = 0; + caml_dependent_allocated = 0; + caml_extra_heap_resources = 0.0; + if (caml_major_slice_end_hook != NULL) (*caml_major_slice_end_hook) (); +} + +/* This does not call [caml_compact_heap_maybe] because the estimates of + free and live memory are only valid for a cycle done incrementally. + Besides, this function itself is called by [caml_compact_heap_maybe]. +*/ +void caml_finish_major_cycle (void) +{ + if (caml_gc_phase == Phase_idle){ + p_backlog = 0.0; /* full major GC cycle, the backlog becomes irrelevant */ + start_cycle (); + } + while (caml_gc_phase == Phase_mark) mark_slice (LONG_MAX); + while (caml_gc_phase == Phase_clean) clean_slice (LONG_MAX); + CAMLassert (caml_gc_phase == Phase_sweep); + while (caml_gc_phase == Phase_sweep) sweep_slice (LONG_MAX); + CAMLassert (caml_gc_phase == Phase_idle); + caml_stat_major_words += caml_allocated_words; + caml_allocated_words = 0; +} + +/* Call this function to make sure [bsz] is greater than or equal + to both [Heap_chunk_min] and the current heap increment. +*/ +asize_t caml_clip_heap_chunk_wsz (asize_t wsz) +{ + asize_t result = wsz; + uintnat incr; + + /* Compute the heap increment as a word size. */ + if (caml_major_heap_increment > 1000){ + incr = caml_major_heap_increment; + }else{ + incr = caml_stat_heap_wsz / 100 * caml_major_heap_increment; + } + + if (result < incr){ + result = incr; + } + if (result < Heap_chunk_min){ + result = Heap_chunk_min; + } + return result; +} + +/* [heap_size] is a number of bytes */ +void caml_init_major_heap (asize_t heap_size) +{ + int i; + + caml_stat_heap_wsz = caml_clip_heap_chunk_wsz (Wsize_bsize (heap_size)); + caml_stat_top_heap_wsz = caml_stat_heap_wsz; + CAMLassert (Bsize_wsize (caml_stat_heap_wsz) % Page_size == 0); + caml_heap_start = + (char *) caml_alloc_for_heap (Bsize_wsize (caml_stat_heap_wsz)); + if (caml_heap_start == NULL) + caml_fatal_error ("cannot allocate initial major heap"); + Chunk_next (caml_heap_start) = NULL; + caml_stat_heap_wsz = Wsize_bsize (Chunk_size (caml_heap_start)); + caml_stat_heap_chunks = 1; + caml_stat_top_heap_wsz = caml_stat_heap_wsz; + + if (caml_page_table_add(In_heap, caml_heap_start, + caml_heap_start + Bsize_wsize (caml_stat_heap_wsz)) + != 0) { + caml_fatal_error ("cannot allocate initial page table"); + } + + caml_fl_init_merge (); + caml_make_free_blocks ((value *) caml_heap_start, + caml_stat_heap_wsz, 1, Caml_white); + caml_gc_phase = Phase_idle; + gray_vals_size = 2048; + gray_vals = (value *) caml_stat_alloc_noexc (gray_vals_size * sizeof (value)); + if (gray_vals == NULL) + caml_fatal_error ("not enough memory for the gray cache"); + gray_vals_cur = gray_vals; + gray_vals_end = gray_vals + gray_vals_size; + heap_is_pure = 1; + caml_allocated_words = 0; + caml_extra_heap_resources = 0.0; + for (i = 0; i < Max_major_window; i++) caml_major_ring[i] = 0.0; +} + +void caml_set_major_window (int w){ + uintnat total = 0; + int i; + if (w == caml_major_window) return; + CAMLassert (w <= Max_major_window); + /* Collect the current work-to-do from the buckets. */ + for (i = 0; i < caml_major_window; i++){ + total += caml_major_ring[i]; + } + /* Redistribute to the new buckets. */ + for (i = 0; i < w; i++){ + caml_major_ring[i] = total / w; + } + caml_major_window = w; +} + +void caml_finalise_heap (void) +{ + /* Finishing major cycle (all values become white) */ + caml_empty_minor_heap (); + caml_finish_major_cycle (); + CAMLassert (caml_gc_phase == Phase_idle); + + /* Finalising all values (by means of forced sweeping) */ + caml_fl_init_merge (); + caml_gc_phase = Phase_sweep; + chunk = caml_heap_start; + caml_gc_sweep_hp = chunk; + limit = chunk + Chunk_size (chunk); + while (caml_gc_phase == Phase_sweep) + sweep_slice (LONG_MAX); +} diff --git a/byterun/md5.c b/runtime/md5.c similarity index 100% rename from byterun/md5.c rename to runtime/md5.c diff --git a/runtime/memory.c b/runtime/memory.c new file mode 100644 index 00000000..c13503f8 --- /dev/null +++ b/runtime/memory.c @@ -0,0 +1,1010 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +#include +#include +#include +#include +#include "caml/address_class.h" +#include "caml/config.h" +#include "caml/fail.h" +#include "caml/freelist.h" +#include "caml/gc.h" +#include "caml/gc_ctrl.h" +#include "caml/major_gc.h" +#include "caml/memory.h" +#include "caml/major_gc.h" +#include "caml/minor_gc.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/signals.h" + +int caml_huge_fallback_count = 0; +/* Number of times that mmapping big pages fails and we fell back to small + pages. This counter is available to the program through + [Gc.huge_fallback_count]. +*/ + +uintnat caml_use_huge_pages = 0; +/* True iff the program allocates heap chunks by mmapping huge pages. + This is set when parsing [OCAMLRUNPARAM] and must stay constant + after that. +*/ + +extern uintnat caml_percent_free; /* major_gc.c */ + +/* Page table management */ + +#define Page(p) ((uintnat) (p) >> Page_log) +#define Page_mask ((uintnat) -1 << Page_log) + +#ifdef ARCH_SIXTYFOUR + +/* 64-bit implementation: + The page table is represented sparsely as a hash table + with linear probing */ + +struct page_table { + mlsize_t size; /* size == 1 << (wordsize - shift) */ + int shift; + mlsize_t mask; /* mask == size - 1 */ + mlsize_t occupancy; + uintnat * entries; /* [size] */ +}; + +static struct page_table caml_page_table; + +/* Page table entries are the logical 'or' of + - the key: address of a page (low Page_log bits = 0) + - the data: a 8-bit integer */ + +#define Page_entry_matches(entry,addr) \ + ((((entry) ^ (addr)) & Page_mask) == 0) + +/* Multiplicative Fibonacci hashing + (Knuth, TAOCP vol 3, section 6.4, page 518). + HASH_FACTOR is (sqrt(5) - 1) / 2 * 2^wordsize. */ +#ifdef ARCH_SIXTYFOUR +#define HASH_FACTOR 11400714819323198486UL +#else +#define HASH_FACTOR 2654435769UL +#endif +#define Hash(v) (((v) * HASH_FACTOR) >> caml_page_table.shift) + +int caml_page_table_lookup(void * addr) +{ + uintnat h, e; + + h = Hash(Page(addr)); + /* The first hit is almost always successful, so optimize for this case */ + e = caml_page_table.entries[h]; + if (Page_entry_matches(e, (uintnat)addr)) return e & 0xFF; + while(1) { + if (e == 0) return 0; + h = (h + 1) & caml_page_table.mask; + e = caml_page_table.entries[h]; + if (Page_entry_matches(e, (uintnat)addr)) return e & 0xFF; + } +} + +int caml_page_table_initialize(mlsize_t bytesize) +{ + uintnat pagesize = Page(bytesize); + + caml_page_table.size = 1; + caml_page_table.shift = 8 * sizeof(uintnat); + /* Aim for initial load factor between 1/4 and 1/2 */ + while (caml_page_table.size < 2 * pagesize) { + caml_page_table.size <<= 1; + caml_page_table.shift -= 1; + } + caml_page_table.mask = caml_page_table.size - 1; + caml_page_table.occupancy = 0; + caml_page_table.entries = + caml_stat_calloc_noexc(caml_page_table.size, sizeof(uintnat)); + if (caml_page_table.entries == NULL) + return -1; + else + return 0; +} + +static int caml_page_table_resize(void) +{ + struct page_table old = caml_page_table; + uintnat * new_entries; + uintnat i, h; + + caml_gc_message (0x08, "Growing page table to %" + ARCH_INTNAT_PRINTF_FORMAT "u entries\n", + caml_page_table.size); + + new_entries = caml_stat_calloc_noexc(2 * old.size, sizeof(uintnat)); + if (new_entries == NULL) { + caml_gc_message (0x08, "No room for growing page table\n"); + return -1; + } + + caml_page_table.size = 2 * old.size; + caml_page_table.shift = old.shift - 1; + caml_page_table.mask = caml_page_table.size - 1; + caml_page_table.occupancy = old.occupancy; + caml_page_table.entries = new_entries; + + for (i = 0; i < old.size; i++) { + uintnat e = old.entries[i]; + if (e == 0) continue; + h = Hash(Page(e)); + while (caml_page_table.entries[h] != 0) + h = (h + 1) & caml_page_table.mask; + caml_page_table.entries[h] = e; + } + + caml_stat_free(old.entries); + return 0; +} + +static int caml_page_table_modify(uintnat page, int toclear, int toset) +{ + uintnat h; + + CAMLassert ((page & ~Page_mask) == 0); + + /* Resize to keep load factor below 1/2 */ + if (caml_page_table.occupancy * 2 >= caml_page_table.size) { + if (caml_page_table_resize() != 0) return -1; + } + h = Hash(Page(page)); + while (1) { + if (caml_page_table.entries[h] == 0) { + caml_page_table.entries[h] = page | toset; + caml_page_table.occupancy++; + break; + } + if (Page_entry_matches(caml_page_table.entries[h], page)) { + caml_page_table.entries[h] = + (caml_page_table.entries[h] & ~toclear) | toset; + break; + } + h = (h + 1) & caml_page_table.mask; + } + return 0; +} + +#else + +/* 32-bit implementation: + The page table is represented as a 2-level array of unsigned char */ + +CAMLexport unsigned char * caml_page_table[Pagetable1_size]; +static unsigned char caml_page_table_empty[Pagetable2_size] = { 0, }; + +int caml_page_table_initialize(mlsize_t bytesize) +{ + int i; + for (i = 0; i < Pagetable1_size; i++) + caml_page_table[i] = caml_page_table_empty; + return 0; +} + +static int caml_page_table_modify(uintnat page, int toclear, int toset) +{ + uintnat i = Pagetable_index1(page); + uintnat j = Pagetable_index2(page); + + if (caml_page_table[i] == caml_page_table_empty) { + unsigned char * new_tbl = caml_stat_calloc_noexc(Pagetable2_size, 1); + if (new_tbl == 0) return -1; + caml_page_table[i] = new_tbl; + } + caml_page_table[i][j] = (caml_page_table[i][j] & ~toclear) | toset; + return 0; +} + +#endif + +int caml_page_table_add(int kind, void * start, void * end) +{ + uintnat pstart = (uintnat) start & Page_mask; + uintnat pend = ((uintnat) end - 1) & Page_mask; + uintnat p; + + for (p = pstart; p <= pend; p += Page_size) + if (caml_page_table_modify(p, 0, kind) != 0) return -1; + return 0; +} + +int caml_page_table_remove(int kind, void * start, void * end) +{ + uintnat pstart = (uintnat) start & Page_mask; + uintnat pend = ((uintnat) end - 1) & Page_mask; + uintnat p; + + for (p = pstart; p <= pend; p += Page_size) + if (caml_page_table_modify(p, kind, 0) != 0) return -1; + return 0; +} + + +/* Initialize the [alloc_for_heap] system. + This function must be called exactly once, and it must be called + before the first call to [alloc_for_heap]. + It returns 0 on success and -1 on failure. +*/ +int caml_init_alloc_for_heap (void) +{ + return 0; +} + +/* Allocate a block of the requested size, to be passed to + [caml_add_to_heap] later. + [request] will be rounded up to some implementation-dependent size. + The caller must use [Chunk_size] on the result to recover the actual + size. + Return NULL if the request cannot be satisfied. The returned pointer + is a hp, but the header (and the contents) must be initialized by the + caller. +*/ +char *caml_alloc_for_heap (asize_t request) +{ + if (caml_use_huge_pages){ +#ifdef HAS_HUGE_PAGES + uintnat size = Round_mmap_size (sizeof (heap_chunk_head) + request); + void *block; + char *mem; + block = mmap (NULL, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0); + if (block == MAP_FAILED) return NULL; + mem = (char *) block + sizeof (heap_chunk_head); + Chunk_size (mem) = size - sizeof (heap_chunk_head); + Chunk_block (mem) = block; + return mem; +#else + return NULL; +#endif + }else{ + char *mem; + void *block; + + request = ((request + Page_size - 1) >> Page_log) << Page_log; + mem = caml_stat_alloc_aligned_noexc (request + sizeof (heap_chunk_head), + sizeof (heap_chunk_head), &block); + if (mem == NULL) return NULL; + mem += sizeof (heap_chunk_head); + Chunk_size (mem) = request; + Chunk_block (mem) = block; + return mem; + } +} + +/* Use this function if a block allocated with [caml_alloc_for_heap] is + not actually going to be added to the heap. The caller is responsible + for freeing it. */ +void caml_disown_for_heap (char* mem) +{ + /* Currently a no-op. */ + (void)mem; /* can CAMLunused_{start,end} be used here? */ +} + +/* Use this function to free a block allocated with [caml_alloc_for_heap] + if you don't add it with [caml_add_to_heap]. +*/ +void caml_free_for_heap (char *mem) +{ + if (caml_use_huge_pages){ +#ifdef HAS_HUGE_PAGES + munmap (Chunk_block (mem), Chunk_size (mem) + sizeof (heap_chunk_head)); +#else + CAMLassert (0); +#endif + }else{ + caml_stat_free (Chunk_block (mem)); + } +} + +/* Take a chunk of memory as argument, which must be the result of a + call to [caml_alloc_for_heap], and insert it into the heap chaining. + The contents of the chunk must be a sequence of valid blocks and + fragments: no space between blocks and no trailing garbage. If + some blocks are blue, they must be added to the free list by the + caller. All other blocks must have the color [caml_allocation_color(m)]. + The caller must update [caml_allocated_words] if applicable. + Return value: 0 if no error; -1 in case of error. + + See also: caml_compact_heap, which duplicates most of this function. +*/ +int caml_add_to_heap (char *m) +{ +#ifdef DEBUG + /* Should check the contents of the block. */ +#endif /* DEBUG */ + + caml_gc_message (0x04, "Growing heap to %" + ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n", + (Bsize_wsize (caml_stat_heap_wsz) + Chunk_size (m)) / 1024); + + /* Register block in page table */ + if (caml_page_table_add(In_heap, m, m + Chunk_size(m)) != 0) + return -1; + + /* Chain this heap chunk. */ + { + char **last = &caml_heap_start; + char *cur = *last; + + while (cur != NULL && cur < m){ + last = &(Chunk_next (cur)); + cur = *last; + } + Chunk_next (m) = cur; + *last = m; + + ++ caml_stat_heap_chunks; + } + + caml_stat_heap_wsz += Wsize_bsize (Chunk_size (m)); + if (caml_stat_heap_wsz > caml_stat_top_heap_wsz){ + caml_stat_top_heap_wsz = caml_stat_heap_wsz; + } + return 0; +} + +/* Allocate more memory from malloc for the heap. + Return a blue block of at least the requested size. + The blue block is chained to a sequence of blue blocks (through their + field 0); the last block of the chain is pointed by field 1 of the + first. There may be a fragment after the last block. + The caller must insert the blocks into the free list. + [request] is a number of words and must be less than or equal + to [Max_wosize]. + Return NULL when out of memory. +*/ +static value *expand_heap (mlsize_t request) +{ + /* these point to headers, but we do arithmetic on them, hence [value *]. */ + value *mem, *hp, *prev; + asize_t over_request, malloc_request, remain; + + CAMLassert (request <= Max_wosize); + over_request = request + request / 100 * caml_percent_free; + malloc_request = caml_clip_heap_chunk_wsz (over_request); + mem = (value *) caml_alloc_for_heap (Bsize_wsize (malloc_request)); + if (mem == NULL){ + caml_gc_message (0x04, "No room for growing heap\n"); + return NULL; + } + remain = Wsize_bsize (Chunk_size (mem)); + prev = hp = mem; + /* FIXME find a way to do this with a call to caml_make_free_blocks */ + while (Wosize_whsize (remain) > Max_wosize){ + Hd_hp (hp) = Make_header (Max_wosize, 0, Caml_blue); +#ifdef DEBUG + caml_set_fields (Val_hp (hp), 0, Debug_free_major); +#endif + hp += Whsize_wosize (Max_wosize); + remain -= Whsize_wosize (Max_wosize); + Field (Val_hp (mem), 1) = Field (Val_hp (prev), 0) = Val_hp (hp); + prev = hp; + } + if (remain > 1){ + Hd_hp (hp) = Make_header (Wosize_whsize (remain), 0, Caml_blue); +#ifdef DEBUG + caml_set_fields (Val_hp (hp), 0, Debug_free_major); +#endif + Field (Val_hp (mem), 1) = Field (Val_hp (prev), 0) = Val_hp (hp); + Field (Val_hp (hp), 0) = (value) NULL; + }else{ + Field (Val_hp (prev), 0) = (value) NULL; + if (remain == 1) { + Hd_hp (hp) = Make_header_allocated_here (0, 0, Caml_white); + } + } + CAMLassert (Wosize_hp (mem) >= request); + if (caml_add_to_heap ((char *) mem) != 0){ + caml_free_for_heap ((char *) mem); + return NULL; + } + return Op_hp (mem); +} + +/* Remove the heap chunk [chunk] from the heap and give the memory back + to [free]. +*/ +void caml_shrink_heap (char *chunk) +{ + char **cp; + + /* Never deallocate the first chunk, because caml_heap_start is both the + first block and the base address for page numbers, and we don't + want to shift the page table, it's too messy (see above). + It will never happen anyway, because of the way compaction works. + (see compact.c) + XXX FIXME this has become false with the fix to PR#5389 (see compact.c) + */ + if (chunk == caml_heap_start) return; + + caml_stat_heap_wsz -= Wsize_bsize (Chunk_size (chunk)); + caml_gc_message (0x04, "Shrinking heap to %" + ARCH_INTNAT_PRINTF_FORMAT "uk words\n", + caml_stat_heap_wsz / 1024); + +#ifdef DEBUG + { + mlsize_t i; + for (i = 0; i < Wsize_bsize (Chunk_size (chunk)); i++){ + ((value *) chunk) [i] = Debug_free_shrink; + } + } +#endif + + -- caml_stat_heap_chunks; + + /* Remove [chunk] from the list of chunks. */ + cp = &caml_heap_start; + while (*cp != chunk) cp = &(Chunk_next (*cp)); + *cp = Chunk_next (chunk); + + /* Remove the pages of [chunk] from the page table. */ + caml_page_table_remove(In_heap, chunk, chunk + Chunk_size (chunk)); + + /* Free the [malloc] block that contains [chunk]. */ + caml_free_for_heap (chunk); +} + +color_t caml_allocation_color (void *hp) +{ + if (caml_gc_phase == Phase_mark || caml_gc_phase == Phase_clean + || (caml_gc_phase == Phase_sweep && (addr)hp >= (addr)caml_gc_sweep_hp)){ + return Caml_black; + }else{ + CAMLassert (caml_gc_phase == Phase_idle + || (caml_gc_phase == Phase_sweep + && (addr)hp < (addr)caml_gc_sweep_hp)); + return Caml_white; + } +} + +static inline value caml_alloc_shr_aux (mlsize_t wosize, tag_t tag, + int raise_oom, uintnat profinfo) +{ + header_t *hp; + value *new_block; + + if (wosize > Max_wosize) { + if (raise_oom) + caml_raise_out_of_memory (); + else + return 0; + } + hp = caml_fl_allocate (wosize); + if (hp == NULL){ + new_block = expand_heap (wosize); + if (new_block == NULL) { + if (!raise_oom) + return 0; + else if (caml_in_minor_collection) + caml_fatal_error ("out of memory"); + else + caml_raise_out_of_memory (); + } + caml_fl_add_blocks ((value) new_block); + hp = caml_fl_allocate (wosize); + } + + CAMLassert (Is_in_heap (Val_hp (hp))); + + /* Inline expansion of caml_allocation_color. */ + if (caml_gc_phase == Phase_mark || caml_gc_phase == Phase_clean + || (caml_gc_phase == Phase_sweep && (addr)hp >= (addr)caml_gc_sweep_hp)){ + Hd_hp (hp) = Make_header_with_profinfo (wosize, tag, Caml_black, profinfo); + }else{ + CAMLassert (caml_gc_phase == Phase_idle + || (caml_gc_phase == Phase_sweep + && (addr)hp < (addr)caml_gc_sweep_hp)); + Hd_hp (hp) = Make_header_with_profinfo (wosize, tag, Caml_white, profinfo); + } + CAMLassert (Hd_hp (hp) + == Make_header_with_profinfo (wosize, tag, caml_allocation_color (hp), + profinfo)); + caml_allocated_words += Whsize_wosize (wosize); + if (caml_allocated_words > caml_minor_heap_wsz){ + CAML_INSTR_INT ("request_major/alloc_shr@", 1); + caml_request_major_slice (); + } +#ifdef DEBUG + { + uintnat i; + for (i = 0; i < wosize; i++){ + Field (Val_hp (hp), i) = Debug_uninit_major; + } + } +#endif + return Val_hp (hp); +} + +CAMLexport value caml_alloc_shr_no_raise (mlsize_t wosize, tag_t tag) +{ + return caml_alloc_shr_aux(wosize, tag, 0, 0); +} + +#ifdef WITH_PROFINFO + +/* Use this to debug problems with macros... */ +#define NO_PROFINFO 0xff + +CAMLexport value caml_alloc_shr_with_profinfo (mlsize_t wosize, tag_t tag, + intnat profinfo) +{ + return caml_alloc_shr_aux(wosize, tag, 1, profinfo); +} + +CAMLexport value caml_alloc_shr_preserving_profinfo (mlsize_t wosize, + tag_t tag, header_t old_header) +{ + return caml_alloc_shr_with_profinfo (wosize, tag, Profinfo_hd(old_header)); +} + +#else +#define NO_PROFINFO 0 +#endif /* WITH_PROFINFO */ + +#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) +#include "caml/spacetime.h" + +CAMLexport value caml_alloc_shr (mlsize_t wosize, tag_t tag) +{ + return caml_alloc_shr_with_profinfo (wosize, tag, + caml_spacetime_my_profinfo (NULL, wosize)); +} +#else +CAMLexport value caml_alloc_shr (mlsize_t wosize, tag_t tag) +{ + return caml_alloc_shr_aux (wosize, tag, 1, NO_PROFINFO); +} +#endif + +/* Dependent memory is all memory blocks allocated out of the heap + that depend on the GC (and finalizers) for deallocation. + For the GC to take dependent memory into account when computing + its automatic speed setting, + you must call [caml_alloc_dependent_memory] when you allocate some + dependent memory, and [caml_free_dependent_memory] when you + free it. In both cases, you pass as argument the size (in bytes) + of the block being allocated or freed. +*/ +CAMLexport void caml_alloc_dependent_memory (mlsize_t nbytes) +{ + caml_dependent_size += nbytes / sizeof (value); + caml_dependent_allocated += nbytes / sizeof (value); +} + +CAMLexport void caml_free_dependent_memory (mlsize_t nbytes) +{ + if (caml_dependent_size < nbytes / sizeof (value)){ + caml_dependent_size = 0; + }else{ + caml_dependent_size -= nbytes / sizeof (value); + } +} + +/* Use this function to tell the major GC to speed up when you use + finalized blocks to automatically deallocate resources (other + than memory). The GC will do at least one cycle every [max] + allocated resources; [res] is the number of resources allocated + this time. + Note that only [res/max] is relevant. The units (and kind of + resource) can change between calls to [caml_adjust_gc_speed]. +*/ +CAMLexport void caml_adjust_gc_speed (mlsize_t res, mlsize_t max) +{ + if (max == 0) max = 1; + if (res > max) res = max; + caml_extra_heap_resources += (double) res / (double) max; + if (caml_extra_heap_resources > 1.0){ + CAML_INSTR_INT ("request_major/adjust_gc_speed_1@", 1); + caml_extra_heap_resources = 1.0; + caml_request_major_slice (); + } +} + +/* You must use [caml_initialize] to store the initial value in a field of + a shared block, unless you are sure the value is not a young block. + A block value [v] is a shared block if and only if [Is_in_heap (v)] + is true. +*/ +/* [caml_initialize] never calls the GC, so you may call it while a block is + unfinished (i.e. just after a call to [caml_alloc_shr].) */ +/* PR#6084 workaround: define it as a weak symbol */ +CAMLexport CAMLweakdef void caml_initialize (value *fp, value val) +{ + CAMLassert(Is_in_heap_or_young(fp)); + *fp = val; + if (!Is_young((value)fp) && Is_block (val) && Is_young (val)) { + add_to_ref_table (&caml_ref_table, fp); + } +} + +/* You must use [caml_modify] to change a field of an existing shared block, + unless you are sure the value being overwritten is not a shared block and + the value being written is not a young block. */ +/* [caml_modify] never calls the GC. */ +/* [caml_modify] can also be used to do assignment on data structures that are + in the minor heap instead of in the major heap. In this case, it + is a bit slower than simple assignment. + In particular, you can use [caml_modify] when you don't know whether the + block being changed is in the minor heap or the major heap. */ +/* PR#6084 workaround: define it as a weak symbol */ + +CAMLexport CAMLweakdef void caml_modify (value *fp, value val) +{ + /* The write barrier implemented by [caml_modify] checks for the + following two conditions and takes appropriate action: + 1- a pointer from the major heap to the minor heap is created + --> add [fp] to the remembered set + 2- a pointer from the major heap to the major heap is overwritten, + while the GC is in the marking phase + --> call [caml_darken] on the overwritten pointer so that the + major GC treats it as an additional root. + */ + value old; + + if (Is_young((value)fp)) { + /* The modified object resides in the minor heap. + Conditions 1 and 2 cannot occur. */ + *fp = val; + } else { + /* The modified object resides in the major heap. */ + CAMLassert(Is_in_heap(fp)); + old = *fp; + *fp = val; + if (Is_block(old)) { + /* If [old] is a pointer within the minor heap, we already + have a major->minor pointer and [fp] is already in the + remembered set. Conditions 1 and 2 cannot occur. */ + if (Is_young(old)) return; + /* Here, [old] can be a pointer within the major heap. + Check for condition 2. */ + if (caml_gc_phase == Phase_mark) caml_darken(old, NULL); + } + /* Check for condition 1. */ + if (Is_block(val) && Is_young(val)) { + add_to_ref_table (&caml_ref_table, fp); + } + } +} + + +/* Global memory pool. + + The pool is structured as a ring of blocks, where each block's header + contains two links: to the previous and to the next block. The data + structure allows for insertions and removals of blocks in constant time, + given that a pointer to the operated block is provided. + + Initially, the pool contains a single block -- a pivot with no data, the + guaranteed existence of which makes for a more concise implementation. + + The API functions that operate on the pool receive not pointers to the + block's header, but rather pointers to the block's "data" field. This + behaviour is required to maintain compatibility with the interfaces of + [malloc], [realloc], and [free] family of functions, as well as to hide + the implementation from the user. +*/ + +/* A type with the most strict alignment requirements */ +union max_align { + char c; + short s; + long l; + int i; + float f; + double d; + void *v; + void (*q)(void); +}; + +struct pool_block { +#ifdef DEBUG + intnat magic; +#endif + struct pool_block *next; + struct pool_block *prev; + /* Use C99's flexible array types if possible */ +#if (__STDC_VERSION__ >= 199901L) + union max_align data[]; /* not allocated, used for alignment purposes */ +#else + union max_align data[1]; +#endif +}; + +#if (__STDC_VERSION__ >= 199901L) +#define SIZEOF_POOL_BLOCK sizeof(struct pool_block) +#else +#define SIZEOF_POOL_BLOCK offsetof(struct pool_block, data) +#endif + +static struct pool_block *pool = NULL; + + +/* Returns a pointer to the block header, given a pointer to "data" */ +static struct pool_block* get_pool_block(caml_stat_block b) +{ + if (b == NULL) + return NULL; + + else { + struct pool_block *pb = + (struct pool_block*)(((char*)b) - SIZEOF_POOL_BLOCK); +#ifdef DEBUG + CAMLassert(pb->magic == Debug_pool_magic); +#endif + return pb; + } +} + +CAMLexport void caml_stat_create_pool(void) +{ + if (pool == NULL) { + pool = malloc(SIZEOF_POOL_BLOCK); + if (pool == NULL) + caml_fatal_error("out of memory"); +#ifdef DEBUG + pool->magic = Debug_pool_magic; +#endif + pool->next = pool; + pool->prev = pool; + } +} + +CAMLexport void caml_stat_destroy_pool(void) +{ + if (pool != NULL) { + pool->prev->next = NULL; + while (pool != NULL) { + struct pool_block *next = pool->next; + free(pool); + pool = next; + } + pool = NULL; + } +} + +/* [sz] and [modulo] are numbers of bytes */ +CAMLexport void* caml_stat_alloc_aligned_noexc(asize_t sz, int modulo, + caml_stat_block *b) +{ + char *raw_mem; + uintnat aligned_mem; + CAMLassert (0 <= modulo && modulo < Page_size); + raw_mem = (char *) caml_stat_alloc_noexc(sz + Page_size); + if (raw_mem == NULL) return NULL; + *b = raw_mem; + raw_mem += modulo; /* Address to be aligned */ + aligned_mem = (((uintnat) raw_mem / Page_size + 1) * Page_size); +#ifdef DEBUG + { + uintnat *p; + uintnat *p0 = (void *) *b; + uintnat *p1 = (void *) (aligned_mem - modulo); + uintnat *p2 = (void *) (aligned_mem - modulo + sz); + uintnat *p3 = (void *) ((char *) *b + sz + Page_size); + for (p = p0; p < p1; p++) *p = Debug_filler_align; + for (p = p1; p < p2; p++) *p = Debug_uninit_align; + for (p = p2; p < p3; p++) *p = Debug_filler_align; + } +#endif + return (char *) (aligned_mem - modulo); +} + +/* [sz] and [modulo] are numbers of bytes */ +CAMLexport void* caml_stat_alloc_aligned(asize_t sz, int modulo, + caml_stat_block *b) +{ + void *result = caml_stat_alloc_aligned_noexc(sz, modulo, b); + /* malloc() may return NULL if size is 0 */ + if ((result == NULL) && (sz != 0)) + caml_raise_out_of_memory(); + return result; +} + +/* [sz] is a number of bytes */ +CAMLexport caml_stat_block caml_stat_alloc_noexc(asize_t sz) +{ + /* Backward compatibility mode */ + if (pool == NULL) + return malloc(sz); + else { + struct pool_block *pb = malloc(sz + SIZEOF_POOL_BLOCK); + if (pb == NULL) return NULL; +#ifdef DEBUG + memset(&(pb->data), Debug_uninit_stat, sz); + pb->magic = Debug_pool_magic; +#endif + + /* Linking the block into the ring */ + pb->next = pool->next; + pb->prev = pool; + pool->next->prev = pb; + pool->next = pb; + + return &(pb->data); + } +} + +/* [sz] is a number of bytes */ +CAMLexport caml_stat_block caml_stat_alloc(asize_t sz) +{ + void *result = caml_stat_alloc_noexc(sz); + /* malloc() may return NULL if size is 0 */ + if ((result == NULL) && (sz != 0)) + caml_raise_out_of_memory(); + return result; +} + +CAMLexport void caml_stat_free(caml_stat_block b) +{ + /* Backward compatibility mode */ + if (pool == NULL) + free(b); + else { + struct pool_block *pb = get_pool_block(b); + if (pb == NULL) return; + + /* Unlinking the block from the ring */ + pb->prev->next = pb->next; + pb->next->prev = pb->prev; + + free(pb); + } +} + +/* [sz] is a number of bytes */ +CAMLexport caml_stat_block caml_stat_resize_noexc(caml_stat_block b, asize_t sz) +{ + /* Backward compatibility mode */ + if (pool == NULL) + return realloc(b, sz); + else { + struct pool_block *pb = get_pool_block(b); + struct pool_block *pb_new = realloc(pb, sz + SIZEOF_POOL_BLOCK); + if (pb_new == NULL) return NULL; + + /* Relinking the new block into the ring in place of the old one */ + pb_new->prev->next = pb_new; + pb_new->next->prev = pb_new; + + return &(pb_new->data); + } +} + +/* [sz] is a number of bytes */ +CAMLexport caml_stat_block caml_stat_resize(caml_stat_block b, asize_t sz) +{ + void *result = caml_stat_resize_noexc(b, sz); + if (result == NULL) + caml_raise_out_of_memory(); + return result; +} + +/* [sz] is a number of bytes */ +CAMLexport caml_stat_block caml_stat_calloc_noexc(asize_t num, asize_t sz) +{ + uintnat total; + if (caml_umul_overflow(sz, num, &total)) + return NULL; + else { + caml_stat_block result = caml_stat_alloc_noexc(total); + if (result != NULL) + memset(result, 0, total); + return result; + } +} + +CAMLexport caml_stat_string caml_stat_strdup_noexc(const char *s) +{ + size_t slen = strlen(s); + caml_stat_block result = caml_stat_alloc_noexc(slen + 1); + if (result == NULL) + return NULL; + memcpy(result, s, slen + 1); + return result; +} + +CAMLexport caml_stat_string caml_stat_strdup(const char *s) +{ + caml_stat_string result = caml_stat_strdup_noexc(s); + if (result == NULL) + caml_raise_out_of_memory(); + return result; +} + +#ifdef _WIN32 + +CAMLexport wchar_t * caml_stat_wcsdup(const wchar_t *s) +{ + int slen = wcslen(s); + wchar_t* result = caml_stat_alloc((slen + 1)*sizeof(wchar_t)); + if (result == NULL) + caml_raise_out_of_memory(); + memcpy(result, s, (slen + 1)*sizeof(wchar_t)); + return result; +} + +#endif + +CAMLexport caml_stat_string caml_stat_strconcat(int n, ...) +{ + va_list args; + char *result, *p; + size_t len = 0; + int i; + + va_start(args, n); + for (i = 0; i < n; i++) { + const char *s = va_arg(args, const char*); + len += strlen(s); + } + va_end(args); + + result = caml_stat_alloc(len + 1); + + va_start(args, n); + p = result; + for (i = 0; i < n; i++) { + const char *s = va_arg(args, const char*); + size_t l = strlen(s); + memcpy(p, s, l); + p += l; + } + va_end(args); + + *p = 0; + return result; +} + +#ifdef _WIN32 + +CAMLexport wchar_t* caml_stat_wcsconcat(int n, ...) +{ + va_list args; + wchar_t *result, *p; + size_t len = 0; + int i; + + va_start(args, n); + for (i = 0; i < n; i++) { + const wchar_t *s = va_arg(args, const wchar_t*); + len += wcslen(s); + } + va_end(args); + + result = caml_stat_alloc((len + 1)*sizeof(wchar_t)); + + va_start(args, n); + p = result; + for (i = 0; i < n; i++) { + const wchar_t *s = va_arg(args, const wchar_t*); + size_t l = wcslen(s); + memcpy(p, s, l*sizeof(wchar_t)); + p += l; + } + va_end(args); + + *p = 0; + return result; +} + +#endif diff --git a/runtime/meta.c b/runtime/meta.c new file mode 100644 index 00000000..613da124 --- /dev/null +++ b/runtime/meta.c @@ -0,0 +1,297 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Primitives for the toplevel */ + +#include +#include "caml/alloc.h" +#include "caml/config.h" +#include "caml/fail.h" +#include "caml/fix_code.h" +#include "caml/interp.h" +#include "caml/intext.h" +#include "caml/major_gc.h" +#include "caml/memory.h" +#include "caml/minor_gc.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/prims.h" +#include "caml/stacks.h" +#include "caml/backtrace_prim.h" + +#ifndef NATIVE_CODE + +CAMLprim value caml_get_global_data(value unit) +{ + return caml_global_data; +} + +char * caml_section_table = NULL; +asize_t caml_section_table_size; + +CAMLprim value caml_get_section_table(value unit) +{ + if (caml_section_table == NULL) caml_raise_not_found(); + return caml_input_value_from_block(caml_section_table, + caml_section_table_size); +} + +struct bytecode { + code_t prog; + asize_t len; +}; +#define Bytecode_val(p) ((struct bytecode*)Data_abstract_val(p)) + +/* Convert a bytes array (= LongString.t) to a contiguous buffer. + The result is allocated with caml_stat_alloc */ +static char* buffer_of_bytes_array(value ls, asize_t *len) +{ + CAMLparam1(ls); + CAMLlocal1(s); + asize_t off; + char *ret; + int i; + + *len = 0; + for (i = 0; i < Wosize_val(ls); i++) { + s = Field(ls, i); + *len += caml_string_length(s); + } + + ret = caml_stat_alloc(*len); + off = 0; + for (i = 0; i < Wosize_val(ls); i++) { + size_t s_len; + s = Field(ls, i); + s_len = caml_string_length(s); + memcpy(ret + off, Bytes_val(s), s_len); + off += s_len; + } + + CAMLreturnT (char*, ret); +} + +CAMLprim value caml_reify_bytecode(value ls_prog, + value debuginfo, + value digest_opt) +{ + CAMLparam3(ls_prog, debuginfo, digest_opt); + CAMLlocal3(clos, bytecode, retval); + struct code_fragment * cf = caml_stat_alloc(sizeof(struct code_fragment)); + code_t prog; + asize_t len; + + prog = (code_t)buffer_of_bytes_array(ls_prog, &len); + caml_add_debug_info(prog, Val_long(len), debuginfo); + cf->code_start = (char *) prog; + cf->code_end = (char *) prog + len; + /* match (digest_opt : string option) with */ + if (Is_block(digest_opt)) { + /* | Some digest -> */ + memcpy(cf->digest, String_val(Field(digest_opt, 0)), 16); + cf->digest_computed = 1; + } else { + /* | None -> */ + cf->digest_computed = 0; + } + caml_ext_table_add(&caml_code_fragments_table, cf); + +#ifdef ARCH_BIG_ENDIAN + caml_fixup_endianness((code_t) prog, len); +#endif +#ifdef THREADED_CODE + caml_thread_code((code_t) prog, len); +#endif + caml_prepare_bytecode((code_t) prog, len); + clos = caml_alloc_small (1, Closure_tag); + Code_val(clos) = (code_t) prog; + bytecode = caml_alloc_small (2, Abstract_tag); + Bytecode_val(bytecode)->prog = prog; + Bytecode_val(bytecode)->len = len; + retval = caml_alloc_small (2, 0); + Field(retval, 0) = bytecode; + Field(retval, 1) = clos; + CAMLreturn (retval); +} + +/* signal to the interpreter machinery that a bytecode is no more + needed (before freeing it) - this might be useful for a JIT + implementation */ + +CAMLprim value caml_static_release_bytecode(value bc) +{ + code_t prog; + asize_t len; + struct code_fragment * cf = NULL, * cfi; + int i; + prog = Bytecode_val(bc)->prog; + len = Bytecode_val(bc)->len; + caml_remove_debug_info(prog); + for (i = 0; i < caml_code_fragments_table.size; i++) { + cfi = (struct code_fragment *) caml_code_fragments_table.contents[i]; + if (cfi->code_start == (char *) prog && + cfi->code_end == (char *) prog + len) { + cf = cfi; + break; + } + } + + if (!cf) { + /* [cf] Not matched with a caml_reify_bytecode call; impossible. */ + CAMLassert (0); + } else { + caml_ext_table_remove(&caml_code_fragments_table, cf); + } + +#ifndef NATIVE_CODE + caml_release_bytecode(prog, len); +#else + caml_failwith("Meta.static_release_bytecode impossible with native code"); +#endif + caml_stat_free(prog); + return Val_unit; +} + +CAMLprim value caml_register_code_fragment(value prog, value len, value digest) +{ + struct code_fragment * cf = caml_stat_alloc(sizeof(struct code_fragment)); + cf->code_start = (char *) prog; + cf->code_end = (char *) prog + Long_val(len); + memcpy(cf->digest, String_val(digest), 16); + cf->digest_computed = 1; + caml_ext_table_add(&caml_code_fragments_table, cf); + return Val_unit; +} + +CAMLprim value caml_realloc_global(value size) +{ + mlsize_t requested_size, actual_size, i; + value new_global_data; + + requested_size = Long_val(size); + actual_size = Wosize_val(caml_global_data); + if (requested_size >= actual_size) { + requested_size = (requested_size + 0x100) & 0xFFFFFF00; + caml_gc_message (0x08, "Growing global data to %" + ARCH_INTNAT_PRINTF_FORMAT "u entries\n", + requested_size); + new_global_data = caml_alloc_shr(requested_size, 0); + for (i = 0; i < actual_size; i++) + caml_initialize(&Field(new_global_data, i), Field(caml_global_data, i)); + for (i = actual_size; i < requested_size; i++){ + Field (new_global_data, i) = Val_long (0); + } + caml_global_data = new_global_data; + } + return Val_unit; +} + +CAMLprim value caml_get_current_environment(value unit) +{ + return *caml_extern_sp; +} + +CAMLprim value caml_invoke_traced_function(value codeptr, value env, value arg) +{ + /* Stack layout on entry: + return frame into instrument_closure function + arg3 to call_original_code (arg) + arg2 to call_original_code (env) + arg1 to call_original_code (codeptr) + arg3 to call_original_code (arg) + arg2 to call_original_code (env) + saved env */ + + /* Stack layout on exit: + return frame into instrument_closure function + actual arg to code (arg) + pseudo return frame into codeptr: + extra_args = 0 + environment = env + PC = codeptr + arg3 to call_original_code (arg) same 6 bottom words as + arg2 to call_original_code (env) on entrance, but + arg1 to call_original_code (codeptr) shifted down 4 words + arg3 to call_original_code (arg) + arg2 to call_original_code (env) + saved env */ + + value * osp, * nsp; + int i; + + osp = caml_extern_sp; + caml_extern_sp -= 4; + nsp = caml_extern_sp; + for (i = 0; i < 6; i++) nsp[i] = osp[i]; + nsp[6] = codeptr; + nsp[7] = env; + nsp[8] = Val_int(0); + nsp[9] = arg; + return Val_unit; +} + +#else + +/* Dummy definitions to support compilation of ocamlc.opt */ + +value caml_get_global_data(value unit) +{ + caml_invalid_argument("Meta.get_global_data"); + return Val_unit; /* not reached */ +} + +value caml_get_section_table(value unit) +{ + caml_invalid_argument("Meta.get_section_table"); + return Val_unit; /* not reached */ +} + +value caml_realloc_global(value size) +{ + caml_invalid_argument("Meta.realloc_global"); + return Val_unit; /* not reached */ +} + +value caml_invoke_traced_function(value codeptr, value env, value arg) +{ + caml_invalid_argument("Meta.invoke_traced_function"); + return Val_unit; /* not reached */ +} + +value caml_reify_bytecode(value prog, value len) +{ + caml_invalid_argument("Meta.reify_bytecode"); + return Val_unit; /* not reached */ +} + +value caml_static_release_bytecode(value prog, value len) +{ + caml_invalid_argument("Meta.static_release_bytecode"); + return Val_unit; /* not reached */ +} + +value * caml_stack_low; +value * caml_stack_high; +value * caml_stack_threshold; +value * caml_extern_sp; +value * caml_trapsp; +int caml_callback_depth; +int volatile caml_something_to_do; +void (* volatile caml_async_action_hook)(void); +struct longjmp_buffer * caml_external_raise; + +#endif diff --git a/runtime/minor_gc.c b/runtime/minor_gc.c new file mode 100644 index 00000000..fce3ae06 --- /dev/null +++ b/runtime/minor_gc.c @@ -0,0 +1,558 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +#include +#include "caml/custom.h" +#include "caml/config.h" +#include "caml/fail.h" +#include "caml/finalise.h" +#include "caml/gc.h" +#include "caml/gc_ctrl.h" +#include "caml/major_gc.h" +#include "caml/memory.h" +#include "caml/minor_gc.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/roots.h" +#include "caml/signals.h" +#include "caml/weak.h" + +/* Pointers into the minor heap. + [caml_young_base] + The [malloc] block that contains the heap. + [caml_young_start] ... [caml_young_end] + The whole range of the minor heap: all young blocks are inside + this interval. + [caml_young_alloc_start]...[caml_young_alloc_end] + The allocation arena: newly-allocated blocks are carved from + this interval, starting at [caml_young_alloc_end]. + [caml_young_alloc_mid] is the mid-point of this interval. + [caml_young_ptr], [caml_young_trigger], [caml_young_limit] + These pointers are all inside the allocation arena. + - [caml_young_ptr] is where the next allocation will take place. + - [caml_young_trigger] is how far we can allocate before triggering + [caml_gc_dispatch]. Currently, it is either [caml_young_alloc_start] + or the mid-point of the allocation arena. + - [caml_young_limit] is the pointer that is compared to + [caml_young_ptr] for allocation. It is either + [caml_young_alloc_end] if a signal is pending and we are in + native code, or [caml_young_trigger]. +*/ + +struct generic_table CAML_TABLE_STRUCT(char); + +asize_t caml_minor_heap_wsz; +static void *caml_young_base = NULL; +CAMLexport value *caml_young_start = NULL, *caml_young_end = NULL; +CAMLexport value *caml_young_alloc_start = NULL, + *caml_young_alloc_mid = NULL, + *caml_young_alloc_end = NULL; +CAMLexport value *caml_young_ptr = NULL, *caml_young_limit = NULL; +CAMLexport value *caml_young_trigger = NULL; + +CAMLexport struct caml_ref_table + caml_ref_table = { NULL, NULL, NULL, NULL, NULL, 0, 0}; + +CAMLexport struct caml_ephe_ref_table + caml_ephe_ref_table = { NULL, NULL, NULL, NULL, NULL, 0, 0}; + +CAMLexport struct caml_custom_table + caml_custom_table = { NULL, NULL, NULL, NULL, NULL, 0, 0}; +/* Table of custom blocks in the minor heap that contain finalizers + or GC speed parameters. */ + +int caml_in_minor_collection = 0; + +double caml_extra_heap_resources_minor = 0; + +/* [sz] and [rsv] are numbers of entries */ +static void alloc_generic_table (struct generic_table *tbl, asize_t sz, + asize_t rsv, asize_t element_size) +{ + void *new_table; + + tbl->size = sz; + tbl->reserve = rsv; + new_table = (void *) caml_stat_alloc_noexc((tbl->size + tbl->reserve) * + element_size); + if (new_table == NULL) caml_fatal_error ("not enough memory"); + if (tbl->base != NULL) caml_stat_free (tbl->base); + tbl->base = new_table; + tbl->ptr = tbl->base; + tbl->threshold = tbl->base + tbl->size * element_size; + tbl->limit = tbl->threshold; + tbl->end = tbl->base + (tbl->size + tbl->reserve) * element_size; +} + +void caml_alloc_table (struct caml_ref_table *tbl, asize_t sz, asize_t rsv) +{ + alloc_generic_table ((struct generic_table *) tbl, sz, rsv, sizeof (value *)); +} + +void caml_alloc_ephe_table (struct caml_ephe_ref_table *tbl, asize_t sz, + asize_t rsv) +{ + alloc_generic_table ((struct generic_table *) tbl, sz, rsv, + sizeof (struct caml_ephe_ref_elt)); +} + +void caml_alloc_custom_table (struct caml_custom_table *tbl, asize_t sz, + asize_t rsv) +{ + alloc_generic_table ((struct generic_table *) tbl, sz, rsv, + sizeof (struct caml_custom_elt)); +} + +static void reset_table (struct generic_table *tbl) +{ + tbl->size = 0; + tbl->reserve = 0; + if (tbl->base != NULL) caml_stat_free (tbl->base); + tbl->base = tbl->ptr = tbl->threshold = tbl->limit = tbl->end = NULL; +} + +static void clear_table (struct generic_table *tbl) +{ + tbl->ptr = tbl->base; + tbl->limit = tbl->threshold; +} + +void caml_set_minor_heap_size (asize_t bsz) +{ + char *new_heap; + void *new_heap_base; + + CAMLassert (bsz >= Bsize_wsize(Minor_heap_min)); + CAMLassert (bsz <= Bsize_wsize(Minor_heap_max)); + CAMLassert (bsz % sizeof (value) == 0); + if (caml_young_ptr != caml_young_alloc_end){ + CAML_INSTR_INT ("force_minor/set_minor_heap_size@", 1); + caml_requested_minor_gc = 0; + caml_young_trigger = caml_young_alloc_mid; + caml_young_limit = caml_young_trigger; + caml_empty_minor_heap (); + } + CAMLassert (caml_young_ptr == caml_young_alloc_end); + new_heap = caml_stat_alloc_aligned_noexc(bsz, 0, &new_heap_base); + if (new_heap == NULL) caml_raise_out_of_memory(); + if (caml_page_table_add(In_young, new_heap, new_heap + bsz) != 0) + caml_raise_out_of_memory(); + + if (caml_young_start != NULL){ + caml_page_table_remove(In_young, caml_young_start, caml_young_end); + caml_stat_free (caml_young_base); + } + caml_young_base = new_heap_base; + caml_young_start = (value *) new_heap; + caml_young_end = (value *) (new_heap + bsz); + caml_young_alloc_start = caml_young_start; + caml_young_alloc_mid = caml_young_alloc_start + Wsize_bsize (bsz) / 2; + caml_young_alloc_end = caml_young_end; + caml_young_trigger = caml_young_alloc_start; + caml_young_limit = caml_young_trigger; + caml_young_ptr = caml_young_alloc_end; + caml_minor_heap_wsz = Wsize_bsize (bsz); + + reset_table ((struct generic_table *) &caml_ref_table); + reset_table ((struct generic_table *) &caml_ephe_ref_table); + reset_table ((struct generic_table *) &caml_custom_table); +} + +static value oldify_todo_list = 0; + +/* Note that the tests on the tag depend on the fact that Infix_tag, + Forward_tag, and No_scan_tag are contiguous. */ + +void caml_oldify_one (value v, value *p) +{ + value result; + header_t hd; + mlsize_t sz, i; + tag_t tag; + + tail_call: + if (Is_block (v) && Is_young (v)){ + CAMLassert ((value *) Hp_val (v) >= caml_young_ptr); + hd = Hd_val (v); + if (hd == 0){ /* If already forwarded */ + *p = Field (v, 0); /* then forward pointer is first field. */ + }else{ + tag = Tag_hd (hd); + if (tag < Infix_tag){ + value field0; + + sz = Wosize_hd (hd); + result = caml_alloc_shr_preserving_profinfo (sz, tag, hd); + *p = result; + field0 = Field (v, 0); + Hd_val (v) = 0; /* Set forward flag */ + Field (v, 0) = result; /* and forward pointer. */ + if (sz > 1){ + Field (result, 0) = field0; + Field (result, 1) = oldify_todo_list; /* Add this block */ + oldify_todo_list = v; /* to the "to do" list. */ + }else{ + CAMLassert (sz == 1); + p = &Field (result, 0); + v = field0; + goto tail_call; + } + }else if (tag >= No_scan_tag){ + sz = Wosize_hd (hd); + result = caml_alloc_shr_preserving_profinfo (sz, tag, hd); + for (i = 0; i < sz; i++) Field (result, i) = Field (v, i); + Hd_val (v) = 0; /* Set forward flag */ + Field (v, 0) = result; /* and forward pointer. */ + *p = result; + }else if (tag == Infix_tag){ + mlsize_t offset = Infix_offset_hd (hd); + caml_oldify_one (v - offset, p); /* Cannot recurse deeper than 1. */ + *p += offset; + }else{ + value f = Forward_val (v); + tag_t ft = 0; + int vv = 1; + + CAMLassert (tag == Forward_tag); + if (Is_block (f)){ + if (Is_young (f)){ + vv = 1; + ft = Tag_val (Hd_val (f) == 0 ? Field (f, 0) : f); + }else{ + vv = Is_in_value_area(f); + if (vv){ + ft = Tag_val (f); + } + } + } + if (!vv || ft == Forward_tag || ft == Lazy_tag +#ifdef FLAT_FLOAT_ARRAY + || ft == Double_tag +#endif + ){ + /* Do not short-circuit the pointer. Copy as a normal block. */ + CAMLassert (Wosize_hd (hd) == 1); + result = caml_alloc_shr_preserving_profinfo (1, Forward_tag, hd); + *p = result; + Hd_val (v) = 0; /* Set (GC) forward flag */ + Field (v, 0) = result; /* and forward pointer. */ + p = &Field (result, 0); + v = f; + goto tail_call; + }else{ + v = f; /* Follow the forwarding */ + goto tail_call; /* then oldify. */ + } + } + } + }else{ + *p = v; + } +} + +/* Test if the ephemeron is alive, everything outside minor heap is alive */ +static inline int ephe_check_alive_data(struct caml_ephe_ref_elt *re){ + mlsize_t i; + value child; + for (i = CAML_EPHE_FIRST_KEY; i < Wosize_val(re->ephe); i++){ + child = Field (re->ephe, i); + if(child != caml_ephe_none + && Is_block (child) && Is_young (child) + && Hd_val (child) != 0){ /* Value not copied to major heap */ + return 0; + } + } + return 1; +} + +/* Finish the work that was put off by [caml_oldify_one]. + Note that [caml_oldify_one] itself is called by oldify_mopup, so we + have to be careful to remove the first entry from the list before + oldifying its fields. */ +void caml_oldify_mopup (void) +{ + value v, new_v, f; + mlsize_t i; + struct caml_ephe_ref_elt *re; + int redo = 0; + + while (oldify_todo_list != 0){ + v = oldify_todo_list; /* Get the head. */ + CAMLassert (Hd_val (v) == 0); /* It must be forwarded. */ + new_v = Field (v, 0); /* Follow forward pointer. */ + oldify_todo_list = Field (new_v, 1); /* Remove from list. */ + + f = Field (new_v, 0); + if (Is_block (f) && Is_young (f)){ + caml_oldify_one (f, &Field (new_v, 0)); + } + for (i = 1; i < Wosize_val (new_v); i++){ + f = Field (v, i); + if (Is_block (f) && Is_young (f)){ + caml_oldify_one (f, &Field (new_v, i)); + }else{ + Field (new_v, i) = f; + } + } + } + + /* Oldify the data in the minor heap of alive ephemeron + During minor collection keys outside the minor heap are considered alive */ + for (re = caml_ephe_ref_table.base; + re < caml_ephe_ref_table.ptr; re++){ + /* look only at ephemeron with data in the minor heap */ + if (re->offset == 1){ + value *data = &Field(re->ephe,1); + if (*data != caml_ephe_none && Is_block (*data) && Is_young (*data)){ + if (Hd_val (*data) == 0){ /* Value copied to major heap */ + *data = Field (*data, 0); + } else { + if (ephe_check_alive_data(re)){ + caml_oldify_one(*data,data); + redo = 1; /* oldify_todo_list can still be 0 */ + } + } + } + } + } + + if (redo) caml_oldify_mopup (); +} + +/* Make sure the minor heap is empty by performing a minor collection + if needed. +*/ +void caml_empty_minor_heap (void) +{ + value **r; + struct caml_custom_elt *elt; + uintnat prev_alloc_words; + struct caml_ephe_ref_elt *re; + + if (caml_young_ptr != caml_young_alloc_end){ + if (caml_minor_gc_begin_hook != NULL) (*caml_minor_gc_begin_hook) (); + CAML_INSTR_SETUP (tmr, "minor"); + prev_alloc_words = caml_allocated_words; + caml_in_minor_collection = 1; + caml_gc_message (0x02, "<"); + caml_oldify_local_roots(); + CAML_INSTR_TIME (tmr, "minor/local_roots"); + for (r = caml_ref_table.base; r < caml_ref_table.ptr; r++){ + caml_oldify_one (**r, *r); + } + CAML_INSTR_TIME (tmr, "minor/ref_table"); + caml_oldify_mopup (); + CAML_INSTR_TIME (tmr, "minor/copy"); + /* Update the ephemerons */ + for (re = caml_ephe_ref_table.base; + re < caml_ephe_ref_table.ptr; re++){ + if(re->offset < Wosize_val(re->ephe)){ + /* If it is not the case, the ephemeron has been truncated */ + value *key = &Field(re->ephe,re->offset); + if (*key != caml_ephe_none && Is_block (*key) && Is_young (*key)){ + if (Hd_val (*key) == 0){ /* Value copied to major heap */ + *key = Field (*key, 0); + }else{ /* Value not copied so it's dead */ + CAMLassert(!ephe_check_alive_data(re)); + *key = caml_ephe_none; + Field(re->ephe,1) = caml_ephe_none; + } + } + } + } + /* Update the OCaml finalise_last values */ + caml_final_update_minor_roots(); + /* Run custom block finalisation of dead minor values */ + for (elt = caml_custom_table.base; elt < caml_custom_table.ptr; elt++){ + value v = elt->block; + if (Hd_val (v) == 0){ + /* Block was copied to the major heap: adjust GC speed numbers. */ + caml_adjust_gc_speed(elt->mem, elt->max); + }else{ + /* Block will be freed: call finalization function, if any. */ + void (*final_fun)(value) = Custom_ops_val(v)->finalize; + if (final_fun != NULL) final_fun(v); + } + } + CAML_INSTR_TIME (tmr, "minor/update_weak"); + caml_stat_minor_words += caml_young_alloc_end - caml_young_ptr; + caml_gc_clock += (double) (caml_young_alloc_end - caml_young_ptr) + / caml_minor_heap_wsz; + caml_young_ptr = caml_young_alloc_end; + clear_table ((struct generic_table *) &caml_ref_table); + clear_table ((struct generic_table *) &caml_ephe_ref_table); + clear_table ((struct generic_table *) &caml_custom_table); + caml_extra_heap_resources_minor = 0; + caml_gc_message (0x02, ">"); + caml_in_minor_collection = 0; + caml_final_empty_young (); + CAML_INSTR_TIME (tmr, "minor/finalized"); + caml_stat_promoted_words += caml_allocated_words - prev_alloc_words; + CAML_INSTR_INT ("minor/promoted#", caml_allocated_words - prev_alloc_words); + ++ caml_stat_minor_collections; + if (caml_minor_gc_end_hook != NULL) (*caml_minor_gc_end_hook) (); + }else{ + /* The minor heap is empty nothing to do. */ + caml_final_empty_young (); + } +#ifdef DEBUG + { + value *p; + for (p = caml_young_alloc_start; p < caml_young_alloc_end; ++p){ + *p = Debug_free_minor; + } + } +#endif +} + +#ifdef CAML_INSTR +extern uintnat caml_instr_alloc_jump; +#endif + +/* Do a minor collection or a slice of major collection, call finalisation + functions, etc. + Leave enough room in the minor heap to allocate at least one object. +*/ +CAMLexport void caml_gc_dispatch (void) +{ + value *trigger = caml_young_trigger; /* save old value of trigger */ +#ifdef CAML_INSTR + CAML_INSTR_SETUP(tmr, "dispatch"); + CAML_INSTR_TIME (tmr, "overhead"); + CAML_INSTR_INT ("alloc/jump#", caml_instr_alloc_jump); + caml_instr_alloc_jump = 0; +#endif + + if (trigger == caml_young_alloc_start || caml_requested_minor_gc){ + /* The minor heap is full, we must do a minor collection. */ + /* reset the pointers first because the end hooks might allocate */ + caml_requested_minor_gc = 0; + caml_young_trigger = caml_young_alloc_mid; + caml_young_limit = caml_young_trigger; + caml_empty_minor_heap (); + /* The minor heap is empty, we can start a major collection. */ + if (caml_gc_phase == Phase_idle) caml_major_collection_slice (-1); + CAML_INSTR_TIME (tmr, "dispatch/minor"); + + caml_final_do_calls (); + CAML_INSTR_TIME (tmr, "dispatch/finalizers"); + + while (caml_young_ptr - caml_young_alloc_start < Max_young_whsize){ + /* The finalizers or the hooks have filled up the minor heap, we must + repeat the minor collection. */ + caml_requested_minor_gc = 0; + caml_young_trigger = caml_young_alloc_mid; + caml_young_limit = caml_young_trigger; + caml_empty_minor_heap (); + /* The minor heap is empty, we can start a major collection. */ + if (caml_gc_phase == Phase_idle) caml_major_collection_slice (-1); + CAML_INSTR_TIME (tmr, "dispatch/finalizers_minor"); + } + } + if (trigger != caml_young_alloc_start || caml_requested_major_slice){ + /* The minor heap is half-full, do a major GC slice. */ + caml_requested_major_slice = 0; + caml_young_trigger = caml_young_alloc_start; + caml_young_limit = caml_young_trigger; + caml_major_collection_slice (-1); + CAML_INSTR_TIME (tmr, "dispatch/major"); + } +} + +/* For backward compatibility with Lablgtk: do a minor collection to + ensure that the minor heap is empty. +*/ +CAMLexport void caml_minor_collection (void) +{ + caml_requested_minor_gc = 1; + caml_gc_dispatch (); +} + +CAMLexport value caml_check_urgent_gc (value extra_root) +{ + CAMLparam1 (extra_root); + if (caml_requested_major_slice || caml_requested_minor_gc){ + CAML_INSTR_INT ("force_minor/check_urgent_gc@", 1); + caml_gc_dispatch(); + } + CAMLreturn (extra_root); +} + +static void realloc_generic_table +(struct generic_table *tbl, asize_t element_size, + char * msg_intr_int, char *msg_threshold, char *msg_growing, char *msg_error) +{ + CAMLassert (tbl->ptr == tbl->limit); + CAMLassert (tbl->limit <= tbl->end); + CAMLassert (tbl->limit >= tbl->threshold); + + if (tbl->base == NULL){ + alloc_generic_table (tbl, caml_minor_heap_wsz / 8, 256, + element_size); + }else if (tbl->limit == tbl->threshold){ + CAML_INSTR_INT (msg_intr_int, 1); + caml_gc_message (0x08, msg_threshold, 0); + tbl->limit = tbl->end; + caml_request_minor_gc (); + }else{ + asize_t sz; + asize_t cur_ptr = tbl->ptr - tbl->base; + CAMLassert (caml_requested_minor_gc); + + tbl->size *= 2; + sz = (tbl->size + tbl->reserve) * element_size; + caml_gc_message (0x08, msg_growing, (intnat) sz/1024); + tbl->base = caml_stat_resize_noexc (tbl->base, sz); + if (tbl->base == NULL){ + caml_fatal_error ("%s", msg_error); + } + tbl->end = tbl->base + (tbl->size + tbl->reserve) * element_size; + tbl->threshold = tbl->base + tbl->size * element_size; + tbl->ptr = tbl->base + cur_ptr; + tbl->limit = tbl->end; + } +} + +void caml_realloc_ref_table (struct caml_ref_table *tbl) +{ + realloc_generic_table + ((struct generic_table *) tbl, sizeof (value *), + "request_minor/realloc_ref_table@", + "ref_table threshold crossed\n", + "Growing ref_table to %" ARCH_INTNAT_PRINTF_FORMAT "dk bytes\n", + "ref_table overflow"); +} + +void caml_realloc_ephe_ref_table (struct caml_ephe_ref_table *tbl) +{ + realloc_generic_table + ((struct generic_table *) tbl, sizeof (struct caml_ephe_ref_elt), + "request_minor/realloc_ephe_ref_table@", + "ephe_ref_table threshold crossed\n", + "Growing ephe_ref_table to %" ARCH_INTNAT_PRINTF_FORMAT "dk bytes\n", + "ephe_ref_table overflow"); +} + +void caml_realloc_custom_table (struct caml_custom_table *tbl) +{ + realloc_generic_table + ((struct generic_table *) tbl, sizeof (struct caml_custom_elt), + "request_minor/realloc_custom_table@", + "custom_table threshold crossed\n", + "Growing custom_table to %" ARCH_INTNAT_PRINTF_FORMAT "dk bytes\n", + "custom_table overflow"); +} diff --git a/runtime/misc.c b/runtime/misc.c new file mode 100644 index 00000000..576f982a --- /dev/null +++ b/runtime/misc.c @@ -0,0 +1,283 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +#if _MSC_VER >= 1400 && _MSC_VER < 1700 +/* Microsoft introduced a regression in Visual Studio 2005 (technically it's + not present in the Windows Server 2003 SDK which has a pre-release version) + and the abort function ceased to be declared __declspec(noreturn). This was + fixed in Visual Studio 2012. Trick stdlib.h into not defining abort (this + means exit and _exit are not defined either, but they aren't required). */ +#define _CRT_TERMINATE_DEFINED +__declspec(noreturn) void __cdecl abort(void); +#endif + +#include +#include +#include +#include "caml/config.h" +#include "caml/misc.h" +#include "caml/memory.h" +#include "caml/osdeps.h" +#include "caml/version.h" + +caml_timing_hook caml_major_slice_begin_hook = NULL; +caml_timing_hook caml_major_slice_end_hook = NULL; +caml_timing_hook caml_minor_gc_begin_hook = NULL; +caml_timing_hook caml_minor_gc_end_hook = NULL; +caml_timing_hook caml_finalise_begin_hook = NULL; +caml_timing_hook caml_finalise_end_hook = NULL; + +#ifdef DEBUG + +void caml_failed_assert (char * expr, char_os * file_os, int line) +{ + char* file = caml_stat_strdup_of_os(file_os); + fprintf (stderr, "file %s; line %d ### Assertion failed: %s\n", + file, line, expr); + fflush (stderr); + caml_stat_free(file); + abort(); +} + +void caml_set_fields (value v, uintnat start, uintnat filler) +{ + mlsize_t i; + for (i = start; i < Wosize_val (v); i++){ + Field (v, i) = (value) filler; + } +} + +#endif /* DEBUG */ + +uintnat caml_verb_gc = 0; + +void caml_gc_message (int level, char *msg, ...) +{ + if ((caml_verb_gc & level) != 0){ + va_list ap; + va_start(ap, msg); + vfprintf (stderr, msg, ap); + va_end(ap); + fflush (stderr); + } +} + +CAMLexport void caml_fatal_error (char *msg, ...) +{ + va_list ap; + va_start(ap, msg); + fprintf (stderr, "Fatal error: "); + vfprintf (stderr, msg, ap); + va_end(ap); + fprintf (stderr, "\n"); + exit(2); +} + +/* If you change the caml_ext_table* functions, also update + runtime/spacetime_nat.c:find_trie_node_from_libunwind. */ + +void caml_ext_table_init(struct ext_table * tbl, int init_capa) +{ + tbl->size = 0; + tbl->capacity = init_capa; + tbl->contents = caml_stat_alloc(sizeof(void *) * init_capa); +} + +int caml_ext_table_add(struct ext_table * tbl, caml_stat_block data) +{ + int res; + if (tbl->size >= tbl->capacity) { + tbl->capacity *= 2; + tbl->contents = + caml_stat_resize(tbl->contents, sizeof(void *) * tbl->capacity); + } + res = tbl->size; + tbl->contents[res] = data; + tbl->size++; + return res; +} + +void caml_ext_table_remove(struct ext_table * tbl, caml_stat_block data) +{ + int i; + for (i = 0; i < tbl->size; i++) { + if (tbl->contents[i] == data) { + caml_stat_free(tbl->contents[i]); + memmove(&tbl->contents[i], &tbl->contents[i + 1], + (tbl->size - i - 1) * sizeof(void *)); + tbl->size--; + } + } +} + +void caml_ext_table_clear(struct ext_table * tbl, int free_entries) +{ + int i; + if (free_entries) { + for (i = 0; i < tbl->size; i++) caml_stat_free(tbl->contents[i]); + } + tbl->size = 0; +} + +void caml_ext_table_free(struct ext_table * tbl, int free_entries) +{ + caml_ext_table_clear(tbl, free_entries); + caml_stat_free(tbl->contents); +} + +/* Integer arithmetic with overflow detection */ + +#if ! (__GNUC__ >= 5 || Caml_has_builtin(__builtin_mul_overflow)) +CAMLexport int caml_umul_overflow(uintnat a, uintnat b, uintnat * res) +{ +#define HALF_SIZE (sizeof(uintnat) * 4) +#define HALF_MASK (((uintnat)1 << HALF_SIZE) - 1) +#define LOW_HALF(x) ((x) & HALF_MASK) +#define HIGH_HALF(x) ((x) >> HALF_SIZE) + /* Cut in half words */ + uintnat al = LOW_HALF(a); + uintnat ah = HIGH_HALF(a); + uintnat bl = LOW_HALF(b); + uintnat bh = HIGH_HALF(b); + /* Exact product is: + al * bl + + ah * bl << HALF_SIZE + + al * bh << HALF_SIZE + + ah * bh << 2*HALF_SIZE + Overflow occurs if: + ah * bh is not 0, i.e. ah != 0 and bh != 0 + OR ah * bl has high half != 0 + OR al * bh has high half != 0 + OR the sum al * bl + LOW_HALF(ah * bl) << HALF_SIZE + + LOW_HALF(al * bh) << HALF_SIZE overflows. + This sum is equal to p = (a * b) modulo word size. */ + uintnat p = a * b; + uintnat p1 = al * bh; + uintnat p2 = ah * bl; + *res = p; + if (ah == 0 && bh == 0) return 0; + if (ah != 0 && bh != 0) return 1; + if (HIGH_HALF(p1) != 0 || HIGH_HALF(p2) != 0) return 1; + p1 <<= HALF_SIZE; + p2 <<= HALF_SIZE; + p1 += p2; + if (p < p1 || p1 < p2) return 1; /* overflow in sums */ + return 0; +#undef HALF_SIZE +#undef HALF_MASK +#undef LOW_HALF +#undef HIGH_HALF +} +#endif + +/* Runtime warnings */ + +uintnat caml_runtime_warnings = 0; +static int caml_runtime_warnings_first = 1; + +int caml_runtime_warnings_active(void) +{ + if (!caml_runtime_warnings) return 0; + if (caml_runtime_warnings_first) { + fprintf(stderr, "[ocaml] (use Sys.enable_runtime_warnings to control " + "these warnings)\n"); + caml_runtime_warnings_first = 0; + } + return 1; +} + +#ifdef CAML_INSTR +/* Timers for profiling GC and allocation (experimental, Linux-only) */ + +#include +#include +#include + +struct caml_instr_block *caml_instr_log = NULL; +intnat caml_instr_starttime, caml_instr_stoptime; + +#define Get_time(p,i) ((p)->ts[(i)].tv_nsec + 1000000000 * (p)->ts[(i)].tv_sec) + +void caml_instr_init (void) +{ + char *s; + + caml_instr_starttime = 0; + s = caml_secure_getenv ("OCAML_INSTR_START"); + if (s != NULL) caml_instr_starttime = atol (s); + caml_instr_stoptime = LONG_MAX; + s = caml_secure_getenv ("OCAML_INSTR_STOP"); + if (s != NULL) caml_instr_stoptime = atol (s); +} + +void caml_instr_atexit (void) +{ + int i; + struct caml_instr_block *p, *prev, *next; + FILE *f = NULL; + char *fname; + + fname = caml_secure_getenv ("OCAML_INSTR_FILE"); + if (fname != NULL){ + char *mode = "a"; + char buf [1000]; + char *name = fname; + + if (name[0] == '@'){ + snprintf (buf, sizeof(buf), "%s.%d", name + 1, getpid ()); + name = buf; + } + if (name[0] == '+'){ + mode = "a"; + name = name + 1; + }else if (name [0] == '>' || name[0] == '-'){ + mode = "w"; + name = name + 1; + } + f = fopen (name, mode); + } + + if (f != NULL){ + /* reverse the list */ + prev = NULL; + p = caml_instr_log; + while (p != NULL){ + next = p->next; + p->next = prev; + prev = p; + p = next; + } + caml_instr_log = prev; + fprintf (f, "==== OCAML INSTRUMENTATION DATA %s\n", OCAML_VERSION_STRING); + for (p = caml_instr_log; p != NULL; p = p->next){ + for (i = 0; i < p->index; i++){ + fprintf (f, "@@ %19ld %19ld %s\n", + (long) Get_time (p, i), + (long) Get_time(p, i+1), + p->tag[i+1]); + } + if (p->tag[0][0] != '\000'){ + fprintf (f, "@@ %19ld %19ld %s\n", + (long) Get_time (p, 0), + (long) Get_time(p, p->index), + p->tag[0]); + } + } + fclose (f); + } +} +#endif /* CAML_INSTR */ diff --git a/byterun/obj.c b/runtime/obj.c similarity index 100% rename from byterun/obj.c rename to runtime/obj.c diff --git a/byterun/parsing.c b/runtime/parsing.c similarity index 100% rename from byterun/parsing.c rename to runtime/parsing.c diff --git a/asmrun/power.S b/runtime/power.S similarity index 100% rename from asmrun/power.S rename to runtime/power.S diff --git a/runtime/printexc.c b/runtime/printexc.c new file mode 100644 index 00000000..83176500 --- /dev/null +++ b/runtime/printexc.c @@ -0,0 +1,154 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Print an uncaught exception and abort */ + +#include +#include +#include +#include "caml/backtrace.h" +#include "caml/callback.h" +#include "caml/debugger.h" +#include "caml/fail.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/printexc.h" +#include "caml/memory.h" + +struct stringbuf { + char * ptr; + char * end; + char data[256]; +}; + +static void add_char(struct stringbuf *buf, char c) +{ + if (buf->ptr < buf->end) *(buf->ptr++) = c; +} + +static void add_string(struct stringbuf *buf, const char *s) +{ + size_t len = strlen(s); + if (buf->ptr + len > buf->end) len = buf->end - buf->ptr; + if (len > 0) memmove(buf->ptr, s, len); + buf->ptr += len; +} + +CAMLexport char * caml_format_exception(value exn) +{ + mlsize_t start, i; + value bucket, v; + struct stringbuf buf; + char intbuf[64]; + char * res; + + buf.ptr = buf.data; + buf.end = buf.data + sizeof(buf.data) - 1; + if (Tag_val(exn) == 0) { + add_string(&buf, String_val(Field(Field(exn, 0), 0))); + /* Check for exceptions in the style of Match_failure and Assert_failure */ + if (Wosize_val(exn) == 2 && + Is_block(Field(exn, 1)) && + Tag_val(Field(exn, 1)) == 0 && + caml_is_special_exception(Field(exn, 0))) { + bucket = Field(exn, 1); + start = 0; + } else { + bucket = exn; + start = 1; + } + add_char(&buf, '('); + for (i = start; i < Wosize_val(bucket); i++) { + if (i > start) add_string(&buf, ", "); + v = Field(bucket, i); + if (Is_long(v)) { + snprintf(intbuf, sizeof(intbuf), + "%" ARCH_INTNAT_PRINTF_FORMAT "d", Long_val(v)); + add_string(&buf, intbuf); + } else if (Tag_val(v) == String_tag) { + add_char(&buf, '"'); + add_string(&buf, String_val(v)); + add_char(&buf, '"'); + } else { + add_char(&buf, '_'); + } + } + add_char(&buf, ')'); + } else + add_string(&buf, String_val(Field(exn, 0))); + + *buf.ptr = 0; /* Terminate string */ + i = buf.ptr - buf.data + 1; + res = caml_stat_alloc_noexc(i); + if (res == NULL) return NULL; + memmove(res, buf.data, i); + return res; +} + + +#ifdef NATIVE_CODE +# define DEBUGGER_IN_USE 0 +#else +# define DEBUGGER_IN_USE caml_debugger_in_use +#endif + +/* Default C implementation in case the OCaml one is not registered. */ +static void default_fatal_uncaught_exception(value exn) +{ + char * msg; + value * at_exit; + int saved_backtrace_active, saved_backtrace_pos; + + /* Build a string representation of the exception */ + msg = caml_format_exception(exn); + /* Perform "at_exit" processing, ignoring all exceptions that may + be triggered by this */ + saved_backtrace_active = caml_backtrace_active; + saved_backtrace_pos = caml_backtrace_pos; + caml_backtrace_active = 0; + at_exit = caml_named_value("Pervasives.do_at_exit"); + if (at_exit != NULL) caml_callback_exn(*at_exit, Val_unit); + caml_backtrace_active = saved_backtrace_active; + caml_backtrace_pos = saved_backtrace_pos; + /* Display the uncaught exception */ + fprintf(stderr, "Fatal error: exception %s\n", msg); + caml_stat_free(msg); + /* Display the backtrace if available */ + if (caml_backtrace_active && !DEBUGGER_IN_USE) + caml_print_exception_backtrace(); +} + +int caml_abort_on_uncaught_exn = 0; /* see afl.c */ + +void caml_fatal_uncaught_exception(value exn) +{ + value *handle_uncaught_exception; + + handle_uncaught_exception = + caml_named_value("Printexc.handle_uncaught_exception"); + if (handle_uncaught_exception != NULL) + /* [Printexc.handle_uncaught_exception] does not raise exception. */ + caml_callback2(*handle_uncaught_exception, exn, Val_bool(DEBUGGER_IN_USE)); + else + default_fatal_uncaught_exception(exn); + /* Terminate the process */ + if (caml_abort_on_uncaught_exn) { + abort(); + } else { + exit(2); + } +} diff --git a/runtime/roots_byt.c b/runtime/roots_byt.c new file mode 100644 index 00000000..6536ceea --- /dev/null +++ b/runtime/roots_byt.c @@ -0,0 +1,120 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* To walk the memory roots for garbage collection */ + +#include "caml/finalise.h" +#include "caml/globroots.h" +#include "caml/major_gc.h" +#include "caml/memory.h" +#include "caml/minor_gc.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/roots.h" +#include "caml/stacks.h" + +CAMLexport struct caml__roots_block *caml_local_roots = NULL; + +CAMLexport void (*caml_scan_roots_hook) (scanning_action f) = NULL; + +/* FIXME should rename to [caml_oldify_minor_roots] and synchronise with + roots_nat.c */ +/* Call [caml_oldify_one] on (at least) all the roots that point to the minor + heap. */ +void caml_oldify_local_roots (void) +{ + register value * sp; + struct caml__roots_block *lr; + intnat i, j; + + /* The stack */ + for (sp = caml_extern_sp; sp < caml_stack_high; sp++) { + caml_oldify_one (*sp, sp); + } + /* Local C roots */ /* FIXME do the old-frame trick ? */ + for (lr = caml_local_roots; lr != NULL; lr = lr->next) { + for (i = 0; i < lr->ntables; i++){ + for (j = 0; j < lr->nitems; j++){ + sp = &(lr->tables[i][j]); + caml_oldify_one (*sp, sp); + } + } + } + /* Global C roots */ + caml_scan_global_young_roots(&caml_oldify_one); + /* Finalised values */ + caml_final_oldify_young_roots (); + /* Hook */ + if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(&caml_oldify_one); +} + +/* Call [caml_darken] on all roots */ + +void caml_darken_all_roots_start (void) +{ + caml_do_roots (caml_darken, 1); +} + +uintnat caml_incremental_roots_count = 1; + +intnat caml_darken_all_roots_slice (intnat work) +{ + return work; +} + +/* Note, in byte-code there is only one global root, so [do_globals] is + ignored and [caml_darken_all_roots_slice] does nothing. */ +void caml_do_roots (scanning_action f, int do_globals) +{ + CAML_INSTR_SETUP (tmr, "major_roots"); + /* Global variables */ + f(caml_global_data, &caml_global_data); + CAML_INSTR_TIME (tmr, "major_roots/global"); + /* The stack and the local C roots */ + caml_do_local_roots(f, caml_extern_sp, caml_stack_high, caml_local_roots); + CAML_INSTR_TIME (tmr, "major_roots/local"); + /* Global C roots */ + caml_scan_global_roots(f); + CAML_INSTR_TIME (tmr, "major_roots/C"); + /* Finalised values */ + caml_final_do_roots (f); + CAML_INSTR_TIME (tmr, "major_roots/finalised"); + /* Hook */ + if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(f); + CAML_INSTR_TIME (tmr, "major_roots/hook"); +} + +CAMLexport void caml_do_local_roots (scanning_action f, value *stack_low, + value *stack_high, + struct caml__roots_block *local_roots) +{ + register value * sp; + struct caml__roots_block *lr; + int i, j; + + for (sp = stack_low; sp < stack_high; sp++) { + f (*sp, sp); + } + for (lr = local_roots; lr != NULL; lr = lr->next) { + for (i = 0; i < lr->ntables; i++){ + for (j = 0; j < lr->nitems; j++){ + sp = &(lr->tables[i][j]); + f (*sp, sp); + } + } + } +} diff --git a/runtime/roots_nat.c b/runtime/roots_nat.c new file mode 100644 index 00000000..38483b41 --- /dev/null +++ b/runtime/roots_nat.c @@ -0,0 +1,506 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* To walk the memory roots for garbage collection */ + +#include "caml/finalise.h" +#include "caml/globroots.h" +#include "caml/memory.h" +#include "caml/major_gc.h" +#include "caml/minor_gc.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/stack.h" +#include "caml/roots.h" +#include +#include + +/* Roots registered from C functions */ + +struct caml__roots_block *caml_local_roots = NULL; + +void (*caml_scan_roots_hook) (scanning_action) = NULL; + +/* The hashtable of frame descriptors */ +frame_descr ** caml_frame_descriptors = NULL; +uintnat caml_frame_descriptors_mask = 0; + +/* Linked-list */ + +typedef struct link { + void *data; + struct link *next; +} link; + +static link *cons(void *data, link *tl) { + link *lnk = caml_stat_alloc(sizeof(link)); + lnk->data = data; + lnk->next = tl; + return lnk; +} + +#define iter_list(list,lnk) \ + for (lnk = list; lnk != NULL; lnk = lnk->next) + +/* Linked-list of frametables */ + +static link *frametables = NULL; +static intnat num_descr = 0; + +static intnat count_descriptors(link *list) { + intnat num_descr = 0; + link *lnk; + iter_list(list,lnk) { + num_descr += *((intnat*) lnk->data); + } + return num_descr; +} + +static link* frametables_list_tail(link *list) { + link *lnk, *tail = NULL; + iter_list(list,lnk) { + tail = lnk; + } + return tail; +} + +static frame_descr * next_frame_descr(frame_descr * d) { + uintnat nextd; + nextd = + ((uintnat)d + + sizeof(char *) + sizeof(short) + sizeof(short) + + sizeof(short) * d->num_live + sizeof(frame_descr *) - 1) + & -sizeof(frame_descr *); + if (d->frame_size & 1) nextd += sizeof(void *); /* pointer to debuginfo */ + return((frame_descr *) nextd); +} + +static void fill_hashtable(link *frametables) { + intnat len, j; + intnat * tbl; + frame_descr * d; + uintnat h; + link *lnk = NULL; + + iter_list(frametables,lnk) { + tbl = (intnat*) lnk->data; + len = *tbl; + d = (frame_descr *)(tbl + 1); + for (j = 0; j < len; j++) { + h = Hash_retaddr(d->retaddr); + while (caml_frame_descriptors[h] != NULL) { + h = (h+1) & caml_frame_descriptors_mask; + } + caml_frame_descriptors[h] = d; + d = next_frame_descr(d); + } + } +} + +static void init_frame_descriptors(link *new_frametables) +{ + intnat tblsize, increase, i; + link *tail = NULL; + + CAMLassert(new_frametables); + + tail = frametables_list_tail(new_frametables); + increase = count_descriptors(new_frametables); + tblsize = caml_frame_descriptors_mask + 1; + + /* Reallocate the caml_frame_descriptor table if it is too small */ + if(tblsize < (num_descr + increase) * 2) { + + /* Merge both lists */ + tail->next = frametables; + frametables = NULL; + + /* [num_descr] can be less than [num_descr + increase] if frame + tables where unregistered */ + num_descr = count_descriptors(new_frametables); + + tblsize = 4; + while (tblsize < 2 * num_descr) tblsize *= 2; + + caml_frame_descriptors_mask = tblsize - 1; + if(caml_frame_descriptors) caml_stat_free(caml_frame_descriptors); + caml_frame_descriptors = + (frame_descr **) caml_stat_alloc(tblsize * sizeof(frame_descr *)); + for (i = 0; i < tblsize; i++) caml_frame_descriptors[i] = NULL; + + fill_hashtable(new_frametables); + } else { + num_descr += increase; + fill_hashtable(new_frametables); + tail->next = frametables; + } + + frametables = new_frametables; +} + +void caml_init_frame_descriptors(void) { + intnat i; + link *new_frametables = NULL; + for (i = 0; caml_frametable[i] != 0; i++) + new_frametables = cons(caml_frametable[i],new_frametables); + init_frame_descriptors(new_frametables); +} + +void caml_register_frametable(intnat *table) { + link *new_frametables = cons(table,NULL); + init_frame_descriptors(new_frametables); +} + +static void remove_entry(frame_descr * d) { + uintnat i; + uintnat r; + uintnat j; + + i = Hash_retaddr(d->retaddr); + while (caml_frame_descriptors[i] != d) { + i = (i+1) & caml_frame_descriptors_mask; + } + + r1: + j = i; + caml_frame_descriptors[i] = NULL; + r2: + i = (i+1) & caml_frame_descriptors_mask; + // r3 + if(caml_frame_descriptors[i] == NULL) return; + r = Hash_retaddr(caml_frame_descriptors[i]->retaddr); + /* If r is between i and j (cyclically), i.e. if + caml_frame_descriptors[i]->retaddr don't need to be moved */ + if(( ( j < r ) && ( r <= i ) ) || + ( ( i < j ) && ( j < r ) ) || /* i cycled, r not */ + ( ( r <= i ) && ( i < j ) ) ) { /* i and r cycled */ + goto r2; + } + // r4 + caml_frame_descriptors[j] = caml_frame_descriptors[i]; + goto r1; +} + +void caml_unregister_frametable(intnat *table) { + intnat len, j; + link *lnk; + link *previous = frametables; + frame_descr * d; + + len = *table; + d = (frame_descr *)(table + 1); + for (j = 0; j < len; j++) { + remove_entry(d); + d = next_frame_descr(d); + } + + iter_list(frametables,lnk) { + if(lnk->data == table) { + previous->next = lnk->next; + caml_stat_free(lnk); + break; + } + previous = lnk; + } +} + +/* Communication with [caml_start_program] and [caml_call_gc]. */ + +char * caml_top_of_stack; +char * caml_bottom_of_stack = NULL; /* no stack initially */ +uintnat caml_last_return_address = 1; /* not in OCaml code initially */ +value * caml_gc_regs; +intnat caml_globals_inited = 0; +static intnat caml_globals_scanned = 0; +static link * caml_dyn_globals = NULL; + +void caml_register_dyn_global(void *v) { + caml_dyn_globals = cons((void*) v,caml_dyn_globals); +} + +/* Call [caml_oldify_one] on (at least) all the roots that point to the minor + heap. */ +void caml_oldify_local_roots (void) +{ + char * sp; + uintnat retaddr; + value * regs; + frame_descr * d; + uintnat h; + intnat i, j; + int n, ofs; + unsigned short * p; + value * glob; + value * root; + struct caml__roots_block *lr; + link *lnk; + + /* The global roots */ + for (i = caml_globals_scanned; + i <= caml_globals_inited && caml_globals[i] != 0; + i++) { + for(glob = caml_globals[i]; *glob != 0; glob++) { + for (j = 0; j < Wosize_val(*glob); j++){ + Oldify (&Field (*glob, j)); + } + } + } + caml_globals_scanned = caml_globals_inited; + + /* Dynamic global roots */ + iter_list(caml_dyn_globals, lnk) { + for(glob = (value *) lnk->data; *glob != 0; glob++) { + for (j = 0; j < Wosize_val(*glob); j++){ + Oldify (&Field (*glob, j)); + } + } + } + + /* The stack and local roots */ + sp = caml_bottom_of_stack; + retaddr = caml_last_return_address; + regs = caml_gc_regs; + if (sp != NULL) { + while (1) { + /* Find the descriptor corresponding to the return address */ + h = Hash_retaddr(retaddr); + while(1) { + d = caml_frame_descriptors[h]; + if (d->retaddr == retaddr) break; + h = (h+1) & caml_frame_descriptors_mask; + } + if (d->frame_size != 0xFFFF) { + /* Scan the roots in this frame */ + for (p = d->live_ofs, n = d->num_live; n > 0; n--, p++) { + ofs = *p; + if (ofs & 1) { + root = regs + (ofs >> 1); + } else { + root = (value *)(sp + ofs); + } + Oldify (root); + } + /* Move to next frame */ + sp += (d->frame_size & 0xFFFC); + retaddr = Saved_return_address(sp); +#ifdef Already_scanned + /* Stop here if the frame has been scanned during earlier GCs */ + if (Already_scanned(sp, retaddr)) break; + /* Mark frame as already scanned */ + Mark_scanned(sp, retaddr); +#endif + } else { + /* This marks the top of a stack chunk for an ML callback. + Skip C portion of stack and continue with next ML stack chunk. */ + struct caml_context * next_context = Callback_link(sp); + sp = next_context->bottom_of_stack; + retaddr = next_context->last_retaddr; + regs = next_context->gc_regs; + /* A null sp means no more ML stack chunks; stop here. */ + if (sp == NULL) break; + } + } + } + /* Local C roots */ + for (lr = caml_local_roots; lr != NULL; lr = lr->next) { + for (i = 0; i < lr->ntables; i++){ + for (j = 0; j < lr->nitems; j++){ + root = &(lr->tables[i][j]); + Oldify (root); + } + } + } + /* Global C roots */ + caml_scan_global_young_roots(&caml_oldify_one); + /* Finalised values */ + caml_final_oldify_young_roots (); + /* Hook */ + if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(&caml_oldify_one); +} + +uintnat caml_incremental_roots_count = 0; + +/* Call [caml_darken] on all roots, incrementally: + [caml_darken_all_roots_start] does the non-incremental part and + sets things up for [caml_darken_all_roots_slice]. +*/ +void caml_darken_all_roots_start (void) +{ + caml_do_roots (caml_darken, 0); +} + +/* Call [caml_darken] on at most [work] global roots. Return the + amount of work not done, if any. If this is strictly positive, + the darkening is done. + */ +intnat caml_darken_all_roots_slice (intnat work) +{ + static int i, j; + static value *glob; + static int do_resume = 0; + static mlsize_t roots_count = 0; + intnat remaining_work = work; + CAML_INSTR_SETUP (tmr, ""); + + /* If the loop was started in a previous call, resume it. */ + if (do_resume) goto resume; + + /* This is the same loop as in [caml_do_roots], but we make it + suspend itself when [work] reaches 0. */ + for (i = 0; caml_globals[i] != 0; i++) { + for(glob = caml_globals[i]; *glob != 0; glob++) { + for (j = 0; j < Wosize_val(*glob); j++){ + caml_darken (Field (*glob, j), &Field (*glob, j)); + -- remaining_work; + if (remaining_work == 0){ + roots_count += work; + do_resume = 1; + goto suspend; + } + resume: ; + } + } + } + + /* The loop finished normally, so all roots are now darkened. */ + caml_incremental_roots_count = roots_count + work - remaining_work; + /* Prepare for the next run. */ + do_resume = 0; + roots_count = 0; + + suspend: + /* Do this in both cases. */ + CAML_INSTR_TIME (tmr, "major/mark/global_roots_slice"); + return remaining_work; +} + +void caml_do_roots (scanning_action f, int do_globals) +{ + int i, j; + value * glob; + link *lnk; + CAML_INSTR_SETUP (tmr, "major_roots"); + + if (do_globals){ + /* The global roots */ + for (i = 0; caml_globals[i] != 0; i++) { + for(glob = caml_globals[i]; *glob != 0; glob++) { + for (j = 0; j < Wosize_val(*glob); j++) + f (Field (*glob, j), &Field (*glob, j)); + } + } + } + /* Dynamic global roots */ + iter_list(caml_dyn_globals, lnk) { + for(glob = (value *) lnk->data; *glob != 0; glob++) { + for (j = 0; j < Wosize_val(*glob); j++){ + f (Field (*glob, j), &Field (*glob, j)); + } + } + } + CAML_INSTR_TIME (tmr, "major_roots/dynamic_global"); + /* The stack and local roots */ + caml_do_local_roots(f, caml_bottom_of_stack, caml_last_return_address, + caml_gc_regs, caml_local_roots); + CAML_INSTR_TIME (tmr, "major_roots/local"); + /* Global C roots */ + caml_scan_global_roots(f); + CAML_INSTR_TIME (tmr, "major_roots/C"); + /* Finalised values */ + caml_final_do_roots (f); + CAML_INSTR_TIME (tmr, "major_roots/finalised"); + /* Hook */ + if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(f); + CAML_INSTR_TIME (tmr, "major_roots/hook"); +} + +void caml_do_local_roots(scanning_action f, char * bottom_of_stack, + uintnat last_retaddr, value * gc_regs, + struct caml__roots_block * local_roots) +{ + char * sp; + uintnat retaddr; + value * regs; + frame_descr * d; + uintnat h; + int i, j, n, ofs; + unsigned short * p; + value * root; + struct caml__roots_block *lr; + + sp = bottom_of_stack; + retaddr = last_retaddr; + regs = gc_regs; + if (sp != NULL) { + while (1) { + /* Find the descriptor corresponding to the return address */ + h = Hash_retaddr(retaddr); + while(1) { + d = caml_frame_descriptors[h]; + if (d->retaddr == retaddr) break; + h = (h+1) & caml_frame_descriptors_mask; + } + if (d->frame_size != 0xFFFF) { + /* Scan the roots in this frame */ + for (p = d->live_ofs, n = d->num_live; n > 0; n--, p++) { + ofs = *p; + if (ofs & 1) { + root = regs + (ofs >> 1); + } else { + root = (value *)(sp + ofs); + } + f (*root, root); + } + /* Move to next frame */ + sp += (d->frame_size & 0xFFFC); + retaddr = Saved_return_address(sp); +#ifdef Mask_already_scanned + retaddr = Mask_already_scanned(retaddr); +#endif + } else { + /* This marks the top of a stack chunk for an ML callback. + Skip C portion of stack and continue with next ML stack chunk. */ + struct caml_context * next_context = Callback_link(sp); + sp = next_context->bottom_of_stack; + retaddr = next_context->last_retaddr; + regs = next_context->gc_regs; + /* A null sp means no more ML stack chunks; stop here. */ + if (sp == NULL) break; + } + } + } + /* Local C roots */ + for (lr = local_roots; lr != NULL; lr = lr->next) { + for (i = 0; i < lr->ntables; i++){ + for (j = 0; j < lr->nitems; j++){ + root = &(lr->tables[i][j]); + f (*root, root); + } + } + } +} + +uintnat (*caml_stack_usage_hook)(void) = NULL; + +uintnat caml_stack_usage (void) +{ + uintnat sz; + sz = (value *) caml_top_of_stack - (value *) caml_bottom_of_stack; + if (caml_stack_usage_hook != NULL) + sz += (*caml_stack_usage_hook)(); + return sz; +} diff --git a/asmrun/s390x.S b/runtime/s390x.S similarity index 100% rename from asmrun/s390x.S rename to runtime/s390x.S diff --git a/runtime/signals.c b/runtime/signals.c new file mode 100644 index 00000000..743d10a3 --- /dev/null +++ b/runtime/signals.c @@ -0,0 +1,450 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Signal handling, code common to the bytecode and native systems */ + +#include +#include +#include "caml/alloc.h" +#include "caml/callback.h" +#include "caml/config.h" +#include "caml/fail.h" +#include "caml/memory.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/roots.h" +#include "caml/signals.h" +#include "caml/signals_machdep.h" +#include "caml/sys.h" + +#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) +#include "caml/spacetime.h" +#endif + +#ifndef NSIG +#define NSIG 64 +#endif + +/* The set of pending signals (received but not yet processed) */ + +CAMLexport intnat volatile caml_signals_are_pending = 0; +CAMLexport intnat volatile caml_pending_signals[NSIG]; + +#ifdef POSIX_SIGNALS +/* This wrapper makes [sigprocmask] compatible with + [pthread_sigmask]. Indeed, the latter returns the error code while + the former sets [errno]. + */ +static int sigprocmask_wrapper(int how, const sigset_t *set, sigset_t *oldset) { + if(sigprocmask(how, set, oldset) != 0) return errno; + else return 0; +} + +CAMLexport int (*caml_sigmask_hook)(int, const sigset_t *, sigset_t *) + = sigprocmask_wrapper; +#endif + +/* Execute all pending signals */ + +void caml_process_pending_signals(void) +{ + int i; + int really_pending; +#ifdef POSIX_SIGNALS + sigset_t set; +#endif + + if(!caml_signals_are_pending) + return; + caml_signals_are_pending = 0; + + /* Check that there is indeed a pending signal before issuing the + syscall in [caml_sigmask_hook]. */ + really_pending = 0; + for (i = 0; i < NSIG; i++) + if (caml_pending_signals[i]) { + really_pending = 1; + break; + } + if(!really_pending) + return; + +#ifdef POSIX_SIGNALS + caml_sigmask_hook(/* dummy */ SIG_BLOCK, NULL, &set); +#endif + for (i = 0; i < NSIG; i++) { + if (!caml_pending_signals[i]) + continue; +#ifdef POSIX_SIGNALS + if(sigismember(&set, i)) + continue; +#endif + caml_pending_signals[i] = 0; + caml_execute_signal(i, 0); + } +} + +/* Record the delivery of a signal, and arrange for it to be processed + as soon as possible: + - in bytecode: via caml_something_to_do, processed in caml_process_event + - in native-code: by playing with the allocation limit, processed + in caml_garbage_collection +*/ + +void caml_record_signal(int signal_number) +{ + caml_pending_signals[signal_number] = 1; + caml_signals_are_pending = 1; +#ifndef NATIVE_CODE + caml_something_to_do = 1; +#else + caml_young_limit = caml_young_alloc_end; +#endif +} + +/* Management of blocking sections. */ + +static intnat volatile caml_async_signal_mode = 0; + +static void caml_enter_blocking_section_default(void) +{ + CAMLassert (caml_async_signal_mode == 0); + caml_async_signal_mode = 1; +} + +static void caml_leave_blocking_section_default(void) +{ + CAMLassert (caml_async_signal_mode == 1); + caml_async_signal_mode = 0; +} + +static int caml_try_leave_blocking_section_default(void) +{ + intnat res; + Read_and_clear(res, caml_async_signal_mode); + return res; +} + +CAMLexport void (*caml_enter_blocking_section_hook)(void) = + caml_enter_blocking_section_default; +CAMLexport void (*caml_leave_blocking_section_hook)(void) = + caml_leave_blocking_section_default; +CAMLexport int (*caml_try_leave_blocking_section_hook)(void) = + caml_try_leave_blocking_section_default; + +CAMLexport void caml_enter_blocking_section(void) +{ + while (1){ + /* Process all pending signals now */ + caml_process_pending_signals(); + caml_enter_blocking_section_hook (); + /* Check again for pending signals. + If none, done; otherwise, try again */ + if (! caml_signals_are_pending) break; + caml_leave_blocking_section_hook (); + } +} + +CAMLexport void caml_leave_blocking_section(void) +{ + int saved_errno; + /* Save the value of errno (PR#5982). */ + saved_errno = errno; + caml_leave_blocking_section_hook (); + + /* Some other thread may have switched + [caml_signals_are_pending] to 0 even though there are still + pending signals (masked in the other thread). To handle this + case, we force re-examination of all signals by setting it back + to 1. + + Another case where this is necessary (even in a single threaded + setting) is when the blocking section unmasks a pending signal: + If the signal is pending and masked but has already been + examinated by [caml_process_pending_signals], then + [caml_signals_are_pending] is 0 but the signal needs to be + handled at this point. */ + caml_signals_are_pending = 1; + caml_process_pending_signals(); + + errno = saved_errno; +} + +/* Execute a signal handler immediately */ + +static value caml_signal_handlers = 0; + +void caml_execute_signal(int signal_number, int in_signal_handler) +{ + value res; + value handler; +#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) + void* saved_spacetime_trie_node_ptr; +#endif +#ifdef POSIX_SIGNALS + sigset_t nsigs, sigs; + /* Block the signal before executing the handler, and record in sigs + the original signal mask */ + sigemptyset(&nsigs); + sigaddset(&nsigs, signal_number); + caml_sigmask_hook(SIG_BLOCK, &nsigs, &sigs); +#endif +#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) + /* We record the signal handler's execution separately, in the same + trie used for finalisers. */ + saved_spacetime_trie_node_ptr + = caml_spacetime_trie_node_ptr; + caml_spacetime_trie_node_ptr + = caml_spacetime_finaliser_trie_root; +#endif +#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) + /* Handled action may have no associated handler, which we interpret + as meaning the signal should be handled by a call to exit. This is + is used to allow spacetime profiles to be completed on interrupt */ + if (caml_signal_handlers == 0) { + res = caml_sys_exit(Val_int(2)); + } else { + handler = Field(caml_signal_handlers, signal_number); + if (!Is_block(handler)) { + res = caml_sys_exit(Val_int(2)); + } else { +#else + handler = Field(caml_signal_handlers, signal_number); +#endif + res = caml_callback_exn( + handler, + Val_int(caml_rev_convert_signal_number(signal_number))); +#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) + } + } + caml_spacetime_trie_node_ptr = saved_spacetime_trie_node_ptr; +#endif +#ifdef POSIX_SIGNALS + if (! in_signal_handler) { + /* Restore the original signal mask */ + caml_sigmask_hook(SIG_SETMASK, &sigs, NULL); + } else if (Is_exception_result(res)) { + /* Restore the original signal mask and unblock the signal itself */ + sigdelset(&sigs, signal_number); + caml_sigmask_hook(SIG_SETMASK, &sigs, NULL); + } +#endif + if (Is_exception_result(res)) caml_raise(Extract_exception(res)); +} + +/* Arrange for a garbage collection to be performed as soon as possible */ + +int volatile caml_requested_major_slice = 0; +int volatile caml_requested_minor_gc = 0; + +void caml_request_major_slice (void) +{ + caml_requested_major_slice = 1; +#ifndef NATIVE_CODE + caml_something_to_do = 1; +#else + caml_young_limit = caml_young_alloc_end; + /* This is only moderately effective on ports that cache [caml_young_limit] + in a register, since [caml_modify] is called directly, not through + [caml_c_call], so it may take a while before the register is reloaded + from [caml_young_limit]. */ +#endif +} + +void caml_request_minor_gc (void) +{ + caml_requested_minor_gc = 1; +#ifndef NATIVE_CODE + caml_something_to_do = 1; +#else + caml_young_limit = caml_young_alloc_end; + /* Same remark as above in [caml_request_major_slice]. */ +#endif +} + +/* OS-independent numbering of signals */ + +#ifndef SIGABRT +#define SIGABRT -1 +#endif +#ifndef SIGALRM +#define SIGALRM -1 +#endif +#ifndef SIGFPE +#define SIGFPE -1 +#endif +#ifndef SIGHUP +#define SIGHUP -1 +#endif +#ifndef SIGILL +#define SIGILL -1 +#endif +#ifndef SIGINT +#define SIGINT -1 +#endif +#ifndef SIGKILL +#define SIGKILL -1 +#endif +#ifndef SIGPIPE +#define SIGPIPE -1 +#endif +#ifndef SIGQUIT +#define SIGQUIT -1 +#endif +#ifndef SIGSEGV +#define SIGSEGV -1 +#endif +#ifndef SIGTERM +#define SIGTERM -1 +#endif +#ifndef SIGUSR1 +#define SIGUSR1 -1 +#endif +#ifndef SIGUSR2 +#define SIGUSR2 -1 +#endif +#ifndef SIGCHLD +#define SIGCHLD -1 +#endif +#ifndef SIGCONT +#define SIGCONT -1 +#endif +#ifndef SIGSTOP +#define SIGSTOP -1 +#endif +#ifndef SIGTSTP +#define SIGTSTP -1 +#endif +#ifndef SIGTTIN +#define SIGTTIN -1 +#endif +#ifndef SIGTTOU +#define SIGTTOU -1 +#endif +#ifndef SIGVTALRM +#define SIGVTALRM -1 +#endif +#ifndef SIGPROF +#define SIGPROF -1 +#endif +#ifndef SIGBUS +#define SIGBUS -1 +#endif +#ifndef SIGPOLL +#define SIGPOLL -1 +#endif +#ifndef SIGSYS +#define SIGSYS -1 +#endif +#ifndef SIGTRAP +#define SIGTRAP -1 +#endif +#ifndef SIGURG +#define SIGURG -1 +#endif +#ifndef SIGXCPU +#define SIGXCPU -1 +#endif +#ifndef SIGXFSZ +#define SIGXFSZ -1 +#endif + +static int posix_signals[] = { + SIGABRT, SIGALRM, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGKILL, SIGPIPE, + SIGQUIT, SIGSEGV, SIGTERM, SIGUSR1, SIGUSR2, SIGCHLD, SIGCONT, + SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGVTALRM, SIGPROF, SIGBUS, + SIGPOLL, SIGSYS, SIGTRAP, SIGURG, SIGXCPU, SIGXFSZ +}; + +CAMLexport int caml_convert_signal_number(int signo) +{ + if (signo < 0 && signo >= -(sizeof(posix_signals) / sizeof(int))) + return posix_signals[-signo-1]; + else + return signo; +} + +CAMLexport int caml_rev_convert_signal_number(int signo) +{ + int i; + for (i = 0; i < sizeof(posix_signals) / sizeof(int); i++) + if (signo == posix_signals[i]) return -i - 1; + return signo; +} + +/* Installation of a signal handler (as per [Sys.signal]) */ + +CAMLprim value caml_install_signal_handler(value signal_number, value action) +{ + CAMLparam2 (signal_number, action); + CAMLlocal1 (res); + int sig, act, oldact; + + sig = caml_convert_signal_number(Int_val(signal_number)); + if (sig < 0 || sig >= NSIG) + caml_invalid_argument("Sys.signal: unavailable signal"); + switch(action) { + case Val_int(0): /* Signal_default */ + act = 0; + break; + case Val_int(1): /* Signal_ignore */ + act = 1; + break; + default: /* Signal_handle */ + act = 2; + break; + } + oldact = caml_set_signal_action(sig, act); + switch (oldact) { + case 0: /* was Signal_default */ + res = Val_int(0); + break; + case 1: /* was Signal_ignore */ + res = Val_int(1); + break; + case 2: /* was Signal_handle */ + #if defined(NATIVE_CODE) && defined(WITH_SPACETIME) + /* Handled action may have no associated handler + which we treat as Signal_default */ + if (caml_signal_handlers == 0) { + res = Val_int(0); + } else { + if (!Is_block(Field(caml_signal_handlers, sig))) { + res = Val_int(0); + } else { + res = caml_alloc_small (1, 0); + Field(res, 0) = Field(caml_signal_handlers, sig); + } + } + #else + res = caml_alloc_small (1, 0); + Field(res, 0) = Field(caml_signal_handlers, sig); + #endif + break; + default: /* error in caml_set_signal_action */ + caml_sys_error(NO_ARG); + } + if (Is_block(action)) { + if (caml_signal_handlers == 0) { + caml_signal_handlers = caml_alloc(NSIG, 0); + caml_register_global_root(&caml_signal_handlers); + } + caml_modify(&Field(caml_signal_handlers, sig), Field(action, 0)); + } + caml_process_pending_signals(); + CAMLreturn (res); +} diff --git a/byterun/signals_byt.c b/runtime/signals_byt.c similarity index 100% rename from byterun/signals_byt.c rename to runtime/signals_byt.c diff --git a/runtime/signals_nat.c b/runtime/signals_nat.c new file mode 100644 index 00000000..29a5f49e --- /dev/null +++ b/runtime/signals_nat.c @@ -0,0 +1,288 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Gallium, INRIA Rocquencourt */ +/* */ +/* Copyright 2007 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Signal handling, code specific to the native-code compiler */ + +#if defined(TARGET_amd64) && defined (SYS_linux) +#define _GNU_SOURCE +#endif +#include +#include +#include +#include "caml/fail.h" +#include "caml/memory.h" +#include "caml/osdeps.h" +#include "caml/signals.h" +#include "caml/signals_machdep.h" +#include "signals_osdep.h" +#include "caml/stack.h" +#include "caml/spacetime.h" + +#ifdef HAS_STACK_OVERFLOW_DETECTION +#include +#include +#endif + +#ifndef NSIG +#define NSIG 64 +#endif + +typedef void (*signal_handler)(int signo); + +#ifdef _WIN32 +extern signal_handler caml_win32_signal(int sig, signal_handler action); +#define signal(sig,act) caml_win32_signal(sig,act) +extern void caml_win32_overflow_detection(); +#endif + +extern char * caml_code_area_start, * caml_code_area_end; +extern char caml_system__code_begin, caml_system__code_end; + +/* Do not use the macro from address_class.h here. */ +#undef Is_in_code_area +#define Is_in_code_area(pc) \ + ( ((char *)(pc) >= caml_code_area_start && \ + (char *)(pc) <= caml_code_area_end) \ +|| ((char *)(pc) >= &caml_system__code_begin && \ + (char *)(pc) <= &caml_system__code_end) \ +|| (Classify_addr(pc) & In_code_area) ) + +/* This routine is the common entry point for garbage collection + and signal handling. It can trigger a callback to OCaml code. + With system threads, this callback can cause a context switch. + Hence [caml_garbage_collection] must not be called from regular C code + (e.g. the [caml_alloc] function) because the context of the call + (e.g. [intern_val]) may not allow context switching. + Only generated assembly code can call [caml_garbage_collection], + via the caml_call_gc assembly stubs. */ + +void caml_garbage_collection(void) +{ + caml_young_limit = caml_young_trigger; + if (caml_requested_major_slice || caml_requested_minor_gc || + caml_young_ptr - caml_young_trigger < Max_young_whsize){ + caml_gc_dispatch (); + } + +#ifdef WITH_SPACETIME + if (caml_young_ptr == caml_young_alloc_end) { + caml_spacetime_automatic_snapshot(); + } +#endif + + caml_process_pending_signals(); +} + +DECLARE_SIGNAL_HANDLER(handle_signal) +{ + int saved_errno; + /* Save the value of errno (PR#5982). */ + saved_errno = errno; +#if !defined(POSIX_SIGNALS) && !defined(BSD_SIGNALS) + signal(sig, handle_signal); +#endif + if (sig < 0 || sig >= NSIG) return; + if (caml_try_leave_blocking_section_hook ()) { + caml_execute_signal(sig, 1); + caml_enter_blocking_section_hook(); + } else { + caml_record_signal(sig); + /* Some ports cache [caml_young_limit] in a register. + Use the signal context to modify that register too, but only if + we are inside OCaml code (not inside C code). */ +#if defined(CONTEXT_PC) && defined(CONTEXT_YOUNG_LIMIT) + if (Is_in_code_area(CONTEXT_PC)) + CONTEXT_YOUNG_LIMIT = (context_reg) caml_young_limit; +#endif + } + errno = saved_errno; +} + +int caml_set_signal_action(int signo, int action) +{ + signal_handler oldact; +#ifdef POSIX_SIGNALS + struct sigaction sigact, oldsigact; +#else + signal_handler act; +#endif + +#ifdef POSIX_SIGNALS + switch(action) { + case 0: + sigact.sa_handler = SIG_DFL; + sigact.sa_flags = 0; + break; + case 1: + sigact.sa_handler = SIG_IGN; + sigact.sa_flags = 0; + break; + default: + SET_SIGACT(sigact, handle_signal); + break; + } + sigemptyset(&sigact.sa_mask); + if (sigaction(signo, &sigact, &oldsigact) == -1) return -1; + oldact = oldsigact.sa_handler; +#else + switch(action) { + case 0: act = SIG_DFL; break; + case 1: act = SIG_IGN; break; + default: act = handle_signal; break; + } + oldact = signal(signo, act); + if (oldact == SIG_ERR) return -1; +#endif + if (oldact == (signal_handler) handle_signal) + return 2; + else if (oldact == SIG_IGN) + return 1; + else + return 0; +} + +/* Machine- and OS-dependent handling of bound check trap */ + +#if defined(TARGET_power) \ + || defined(TARGET_s390x) +DECLARE_SIGNAL_HANDLER(trap_handler) +{ +#if defined(SYS_rhapsody) + /* Unblock SIGTRAP */ + { sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGTRAP); + caml_sigmask_hook(SIG_UNBLOCK, &mask, NULL); + } +#endif + caml_exception_pointer = (char *) CONTEXT_EXCEPTION_POINTER; + caml_young_ptr = (value *) CONTEXT_YOUNG_PTR; + caml_bottom_of_stack = (char *) CONTEXT_SP; + caml_last_return_address = (uintnat) CONTEXT_PC; + caml_array_bound_error(); +} +#endif + +/* Machine- and OS-dependent handling of stack overflow */ + +#ifdef HAS_STACK_OVERFLOW_DETECTION + +static char * system_stack_top; +static char sig_alt_stack[SIGSTKSZ]; + +#if defined(SYS_linux) +/* PR#4746: recent Linux kernels with support for stack randomization + silently add 2 Mb of stack space on top of RLIMIT_STACK. + 2 Mb = 0x200000, to which we add 8 kB (=0x2000) for overshoot. */ +#define EXTRA_STACK 0x202000 +#else +#define EXTRA_STACK 0x2000 +#endif + +#ifdef RETURN_AFTER_STACK_OVERFLOW +extern void caml_stack_overflow(void); +#endif + +DECLARE_SIGNAL_HANDLER(segv_handler) +{ + struct rlimit limit; + struct sigaction act; + char * fault_addr; + + /* Sanity checks: + - faulting address is word-aligned + - faulting address is within the stack + - we are in OCaml code */ + fault_addr = CONTEXT_FAULTING_ADDRESS; + if (((uintnat) fault_addr & (sizeof(intnat) - 1)) == 0 + && getrlimit(RLIMIT_STACK, &limit) == 0 + && fault_addr < system_stack_top + && fault_addr >= system_stack_top - limit.rlim_cur - EXTRA_STACK +#ifdef CONTEXT_PC + && Is_in_code_area(CONTEXT_PC) +#endif + ) { +#ifdef RETURN_AFTER_STACK_OVERFLOW + /* Tweak the PC part of the context so that on return from this + handler, we jump to the asm function [caml_stack_overflow] + (from $ARCH.S). */ +#ifdef CONTEXT_PC + CONTEXT_PC = (context_reg) &caml_stack_overflow; +#else +#error "CONTEXT_PC must be defined if RETURN_AFTER_STACK_OVERFLOW is" +#endif +#else + /* Raise a Stack_overflow exception straight from this signal handler */ +#if defined(CONTEXT_YOUNG_PTR) && defined(CONTEXT_EXCEPTION_POINTER) + caml_exception_pointer = (char *) CONTEXT_EXCEPTION_POINTER; + caml_young_ptr = (value *) CONTEXT_YOUNG_PTR; +#endif + caml_raise_stack_overflow(); +#endif + } else { + /* Otherwise, deactivate our exception handler and return, + causing fatal signal to be generated at point of error. */ + act.sa_handler = SIG_DFL; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + sigaction(SIGSEGV, &act, NULL); + } +} + +#endif + +/* Initialization of signal stuff */ + +void caml_init_signals(void) +{ + /* Bound-check trap handling */ + +#if defined(TARGET_power) + { struct sigaction act; + sigemptyset(&act.sa_mask); + SET_SIGACT(act, trap_handler); +#if !defined(SYS_rhapsody) + act.sa_flags |= SA_NODEFER; +#endif + sigaction(SIGTRAP, &act, NULL); + } +#endif + +#if defined(TARGET_s390x) + { struct sigaction act; + sigemptyset(&act.sa_mask); + SET_SIGACT(act, trap_handler); + sigaction(SIGFPE, &act, NULL); + } +#endif + + /* Stack overflow handling */ +#ifdef HAS_STACK_OVERFLOW_DETECTION + { + stack_t stk; + struct sigaction act; + stk.ss_sp = sig_alt_stack; + stk.ss_size = SIGSTKSZ; + stk.ss_flags = 0; + SET_SIGACT(act, segv_handler); + act.sa_flags |= SA_ONSTACK | SA_NODEFER; + sigemptyset(&act.sa_mask); + system_stack_top = (char *) &act; + if (sigaltstack(&stk, NULL) == 0) { sigaction(SIGSEGV, &act, NULL); } + } +#endif +} diff --git a/asmrun/signals_osdep.h b/runtime/signals_osdep.h similarity index 100% rename from asmrun/signals_osdep.h rename to runtime/signals_osdep.h diff --git a/byterun/spacetime.c b/runtime/spacetime_byt.c similarity index 100% rename from byterun/spacetime.c rename to runtime/spacetime_byt.c diff --git a/runtime/spacetime_nat.c b/runtime/spacetime_nat.c new file mode 100644 index 00000000..b479f3e2 --- /dev/null +++ b/runtime/spacetime_nat.c @@ -0,0 +1,1161 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Mark Shinwell and Leo White, Jane Street Europe */ +/* */ +/* Copyright 2013--2016, Jane Street Group, LLC */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "caml/config.h" +#ifdef HAS_UNISTD +#include +#endif +#ifdef _WIN32 +#include /* for _getpid */ +#include /* for _wgetcwd */ +#endif + +#include "caml/alloc.h" +#include "caml/backtrace_prim.h" +#include "caml/fail.h" +#include "caml/gc.h" +#include "caml/intext.h" +#include "caml/major_gc.h" +#include "caml/memory.h" +#include "caml/minor_gc.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/osdeps.h" +#include "caml/roots.h" +#include "caml/signals.h" +#include "caml/stack.h" +#include "caml/sys.h" +#include "caml/spacetime.h" + +#ifdef WITH_SPACETIME + +/* We force "noinline" in certain places to be sure we know how many + frames there will be on the stack. */ +#ifdef _MSC_VER +#define NOINLINE __declspec(noinline) +#else +#define NOINLINE __attribute__((noinline)) +#endif + +#ifdef HAS_LIBUNWIND +#define UNW_LOCAL_ONLY +#include "libunwind.h" +#endif + +static int automatic_snapshots = 0; +static double snapshot_interval = 0.0; +static double next_snapshot_time = 0.0; +static struct channel *snapshot_channel; +static int pid_when_snapshot_channel_opened; + +extern value caml_spacetime_debug(value); + +static char* start_of_free_node_block; +static char* end_of_free_node_block; + +typedef struct per_thread { + value* trie_node_root; + value* finaliser_trie_node_root; + struct per_thread* next; +} per_thread; + +/* List of tries corresponding to threads that have been created. */ +/* CR-soon mshinwell: just include the main trie in this list. */ +static per_thread* per_threads = NULL; +static int num_per_threads = 0; + +/* [caml_spacetime_shapes] is defined in the startup file. */ +extern uint64_t* caml_spacetime_shapes; + +uint64_t** caml_spacetime_static_shape_tables = NULL; +shape_table* caml_spacetime_dynamic_shape_tables = NULL; + +static uintnat caml_spacetime_profinfo = (uintnat) 0; + +value caml_spacetime_trie_root = Val_unit; +value* caml_spacetime_trie_node_ptr = &caml_spacetime_trie_root; + +static value caml_spacetime_finaliser_trie_root_main_thread = Val_unit; +value* caml_spacetime_finaliser_trie_root + = &caml_spacetime_finaliser_trie_root_main_thread; + +/* CR-someday mshinwell: think about thread safety of the manipulation of + this list for multicore */ +allocation_point* caml_all_allocation_points = NULL; + +static const uintnat chunk_size = 1024 * 1024; + +#ifdef _WIN32 +#define strdup_os wcsdup +#define snprintf_os _snwprintf +#else +#define strdup_os strdup +#define snprintf_os snprintf +#endif + +static void reinitialise_free_node_block(void) +{ + size_t index; + + start_of_free_node_block = (char*) caml_stat_alloc_noexc(chunk_size); + end_of_free_node_block = start_of_free_node_block + chunk_size; + + for (index = 0; index < chunk_size / sizeof(value); index++) { + ((value*) start_of_free_node_block)[index] = Val_unit; + } +} + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +enum { + FEATURE_CALL_COUNTS = 1, +} features; + +static uint16_t version_number = 0; +static uint32_t magic_number_base = 0xace00ace; + +static void caml_spacetime_write_magic_number_internal(struct channel* chan) +{ + value magic_number; + uint16_t features = 0; + +#ifdef ENABLE_CALL_COUNTS + features |= FEATURE_CALL_COUNTS; +#endif + + magic_number = + Val_long(((uint64_t) magic_number_base) + | (((uint64_t) version_number) << 32) + | (((uint64_t) features) << 48)); + + Lock(chan); + caml_output_val(chan, magic_number, Val_long(0)); + Unlock(chan); +} + +CAMLprim value caml_spacetime_write_magic_number(value v_channel) +{ + caml_spacetime_write_magic_number_internal(Channel(v_channel)); + return Val_unit; +} + +static char_os* automatic_snapshot_dir; + +static void open_snapshot_channel(void) +{ + int fd; + char_os filename[8192]; + int pid; + int filename_len = sizeof(filename)/sizeof(char_os); +#ifdef _WIN32 + pid = _getpid(); +#else + pid = getpid(); +#endif + snprintf_os(filename, filename_len, _T("%s/spacetime-%d"), + automatic_snapshot_dir, pid); + filename[filename_len-1] = _T('\0'); + fd = open_os(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + if (fd == -1) { + automatic_snapshots = 0; + } + else { + snapshot_channel = caml_open_descriptor_out(fd); + snapshot_channel->flags |= CHANNEL_FLAG_BLOCKING_WRITE; + pid_when_snapshot_channel_opened = pid; + caml_spacetime_write_magic_number_internal(snapshot_channel); + } +} + +static void maybe_reopen_snapshot_channel(void) +{ + /* This function should be used before writing to the automatic snapshot + channel. It detects whether we have forked since the channel was opened. + If so, we close the old channel (ignoring any errors just in case the + old fd has been closed, e.g. in a double-fork situation where the middle + process has a loop to manually close all fds and no Spacetime snapshot + was written during that time) and then open a new one. */ + + int pid; +#ifdef _WIN32 + pid = _getpid(); +#else + pid = getpid(); +#endif + + if (pid != pid_when_snapshot_channel_opened) { + caml_close_channel(snapshot_channel); + open_snapshot_channel(); + } +} + +extern void caml_spacetime_automatic_save(void); + +void caml_spacetime_initialize(void) +{ + /* Note that this is called very early (even prior to GC initialisation). */ + + char_os *ap_interval; + + reinitialise_free_node_block(); + + caml_spacetime_static_shape_tables = &caml_spacetime_shapes; + + ap_interval = caml_secure_getenv (_T("OCAML_SPACETIME_INTERVAL")); + if (ap_interval != NULL) { + unsigned int interval = 0; + sscanf_os(ap_interval, _T("%u"), &interval); + if (interval != 0) { + double time; + char_os cwd[4096]; + char_os* user_specified_automatic_snapshot_dir; + int dir_ok = 1; + + user_specified_automatic_snapshot_dir = + caml_secure_getenv(_T("OCAML_SPACETIME_SNAPSHOT_DIR")); + + if (user_specified_automatic_snapshot_dir == NULL) { +#if defined(HAS_GETCWD) + if (getcwd_os(cwd, sizeof(cwd)/sizeof(char_os)) == NULL) { + dir_ok = 0; + } +#else + dir_ok = 0; +#endif + if (dir_ok) { + automatic_snapshot_dir = strdup_os(cwd); + } + } + else { + automatic_snapshot_dir = + strdup_os(user_specified_automatic_snapshot_dir); + } + + if (dir_ok) { + automatic_snapshots = 1; + open_snapshot_channel(); + if (automatic_snapshots) { +#ifdef SIGINT + /* Catch interrupt so that the profile can be completed. + We do this by marking the signal as handled without + specifying an actual handler. This causes the signal + to be handled by a call to exit. */ + caml_set_signal_action(SIGINT, 2); +#endif + snapshot_interval = interval / 1e3; + time = caml_sys_time_unboxed(Val_unit); + next_snapshot_time = time + snapshot_interval; + atexit(&caml_spacetime_automatic_save); + } + } + } + } +} + +void caml_spacetime_register_shapes(void* dynlinked_table) +{ + shape_table* table; + table = (shape_table*) caml_stat_alloc_noexc(sizeof(shape_table)); + if (table == NULL) { + fprintf(stderr, "Out of memory whilst registering shape table"); + abort(); + } + table->table = (uint64_t*) dynlinked_table; + table->next = caml_spacetime_dynamic_shape_tables; + caml_spacetime_dynamic_shape_tables = table; +} + +CAMLprim value caml_spacetime_trie_is_initialized (value v_unit) +{ + return (caml_spacetime_trie_root == Val_unit) ? Val_false : Val_true; +} + +CAMLprim value caml_spacetime_get_trie_root (value v_unit) +{ + return caml_spacetime_trie_root; +} + +void caml_spacetime_register_thread( + value* trie_node_root, value* finaliser_trie_node_root) +{ + per_thread* thr; + + thr = (per_thread*) caml_stat_alloc_noexc(sizeof(per_thread)); + if (thr == NULL) { + fprintf(stderr, "Out of memory while registering thread for profiling\n"); + abort(); + } + thr->next = per_threads; + per_threads = thr; + + thr->trie_node_root = trie_node_root; + thr->finaliser_trie_node_root = finaliser_trie_node_root; + + /* CR-soon mshinwell: record thread ID (and for the main thread too) */ + + num_per_threads++; +} + +static void caml_spacetime_save_event_internal (value v_time_opt, + struct channel* chan, + value v_event_name) +{ + value v_time; + double time_override = 0.0; + int use_time_override = 0; + + if (Is_block(v_time_opt)) { + time_override = Double_field(Field(v_time_opt, 0), 0); + use_time_override = 1; + } + v_time = caml_spacetime_timestamp(time_override, use_time_override); + + Lock(chan); + caml_output_val(chan, Val_long(2), Val_long(0)); + caml_output_val(chan, v_event_name, Val_long(0)); + caml_extern_allow_out_of_heap = 1; + caml_output_val(chan, v_time, Val_long(0)); + caml_extern_allow_out_of_heap = 0; + Unlock(chan); + + caml_stat_free(Hp_val(v_time)); +} + +CAMLprim value caml_spacetime_save_event (value v_time_opt, + value v_channel, + value v_event_name) +{ + struct channel* chan = Channel(v_channel); + + caml_spacetime_save_event_internal(v_time_opt, chan, v_event_name); + + return Val_unit; +} + + +void save_trie (struct channel *chan, double time_override, + int use_time_override) +{ + value v_time, v_frames, v_shapes; + /* CR-someday mshinwell: The commented-out changes here are for multicore, + where we think we should have one trie per domain. */ + /* int num_marshalled = 0; + per_thread* thr = per_threads; */ + + Lock(chan); + + caml_output_val(chan, Val_long(1), Val_long(0)); + + v_time = caml_spacetime_timestamp(time_override, use_time_override); + v_frames = caml_spacetime_frame_table(); + v_shapes = caml_spacetime_shape_table(); + + caml_extern_allow_out_of_heap = 1; + caml_output_val(chan, v_time, Val_long(0)); + caml_output_val(chan, v_frames, Val_long(0)); + caml_output_val(chan, v_shapes, Val_long(0)); + caml_extern_allow_out_of_heap = 0; + + caml_output_val(chan, Val_long(1) /* Val_long(num_per_threads + 1) */, + Val_long(0)); + + /* Marshal both the main and finaliser tries, for all threads that have + been created, to an [out_channel]. This can be done by using the + extern.c code as usual, since the trie looks like standard OCaml values; + but we must allow it to traverse outside the heap. */ + + caml_extern_allow_out_of_heap = 1; + caml_output_val(chan, caml_spacetime_trie_root, Val_long(0)); + caml_output_val(chan, + caml_spacetime_finaliser_trie_root_main_thread, Val_long(0)); + /* while (thr != NULL) { + caml_output_val(chan, *(thr->trie_node_root), Val_long(0)); + caml_output_val(chan, *(thr->finaliser_trie_node_root), + Val_long(0)); + thr = thr->next; + num_marshalled++; + } + CAMLassert(num_marshalled == num_per_threads); */ + caml_extern_allow_out_of_heap = 0; + + Unlock(chan); +} + +CAMLprim value caml_spacetime_save_trie (value v_time_opt, value v_channel) +{ + struct channel* channel = Channel(v_channel); + double time_override = 0.0; + int use_time_override = 0; + + if (Is_block(v_time_opt)) { + time_override = Double_field(Field(v_time_opt, 0), 0); + use_time_override = 1; + } + + save_trie(channel, time_override, use_time_override); + + return Val_unit; +} + +c_node_type caml_spacetime_classify_c_node(c_node* node) +{ + return (node->pc & 2) ? CALL : ALLOCATION; +} + +c_node* caml_spacetime_c_node_of_stored_pointer(value node_stored) +{ + CAMLassert(node_stored == Val_unit || Is_c_node(node_stored)); + return (node_stored == Val_unit) ? NULL : (c_node*) Hp_val(node_stored); +} + +c_node* caml_spacetime_c_node_of_stored_pointer_not_null( + value node_stored) +{ + CAMLassert(Is_c_node(node_stored)); + return (c_node*) Hp_val(node_stored); +} + +value caml_spacetime_stored_pointer_of_c_node(c_node* c_node) +{ + value node; + CAMLassert(c_node != NULL); + node = Val_hp(c_node); + CAMLassert(Is_c_node(node)); + return node; +} + +#ifdef HAS_LIBUNWIND +static int pc_inside_c_node_matches(c_node* node, void* pc) +{ + return Decode_c_node_pc(node->pc) == pc; +} +#endif + +static value allocate_uninitialized_ocaml_node(int size_including_header) +{ + void* node; + uintnat size; + + CAMLassert(size_including_header >= 3); + node = caml_stat_alloc(sizeof(uintnat) * size_including_header); + + size = size_including_header * sizeof(value); + + node = (void*) start_of_free_node_block; + if (end_of_free_node_block - start_of_free_node_block < size) { + reinitialise_free_node_block(); + node = (void*) start_of_free_node_block; + CAMLassert(end_of_free_node_block - start_of_free_node_block >= size); + } + + start_of_free_node_block += size; + + /* We don't currently rely on [uintnat] alignment, but we do need some + alignment, so just be sure. */ + CAMLassert (((uintnat) node) % sizeof(uintnat) == 0); + return Val_hp(node); +} + +static value find_tail_node(value node, void* callee) +{ + /* Search the tail chain within [node] (which corresponds to an invocation + of a caller of [callee]) to determine whether it contains a tail node + corresponding to [callee]. Returns any such node, or [Val_unit] if no + such node exists. */ + + value starting_node; + value pc; + value found = Val_unit; + + starting_node = node; + pc = Encode_node_pc(callee); + + do { + CAMLassert(Is_ocaml_node(node)); + if (Node_pc(node) == pc) { + found = node; + } + else { + node = Tail_link(node); + } + } while (found == Val_unit && starting_node != node); + + return found; +} + +CAMLprim value caml_spacetime_allocate_node( + int size_including_header, void* pc, value* node_hole) +{ + value node; + value caller_node = Val_unit; + + node = *node_hole; + /* The node hole should either contain [Val_unit], indicating that this + function was not tail called and we have not been to this point in the + trie before; or it should contain a value encoded using + [Encoded_tail_caller_node] that points at the node of a caller + that tail called the current function. (Such a value is necessary to + be able to find the start of the caller's node, and hence its tail + chain, so we as a tail-called callee can link ourselves in.) */ + CAMLassert(Is_tail_caller_node_encoded(node)); + + if (node != Val_unit) { + value tail_node; + /* The callee was tail called. Find whether there already exists a node + for it in the tail call chain within the caller's node. The caller's + node must always be an OCaml node. */ + caller_node = Decode_tail_caller_node(node); + tail_node = find_tail_node(caller_node, pc); + if (tail_node != Val_unit) { + /* This tail calling sequence has happened before; just fill the hole + with the existing node and return. */ + *node_hole = tail_node; + return 0; /* indicates an existing node was returned */ + } + } + + node = allocate_uninitialized_ocaml_node(size_including_header); + Hd_val(node) = + Make_header(size_including_header - 1, OCaml_node_tag, Caml_black); + CAMLassert((((uintnat) pc) % 1) == 0); + Node_pc(node) = Encode_node_pc(pc); + /* If the callee was tail called, then the tail link field will link this + new node into an existing tail chain. Otherwise, it is initialized with + the empty tail chain, i.e. the one pointing directly at [node]. */ + if (caller_node == Val_unit) { + Tail_link(node) = node; + } + else { + Tail_link(node) = Tail_link(caller_node); + Tail_link(caller_node) = node; + } + + /* The callee node pointers for direct tail call points are + initialized from code emitted by the OCaml compiler. This is done to + avoid having to pass this function a description of which nodes are + direct tail call points. (We cannot just count them and put them at the + beginning of the node because we need the indexes of elements within the + node during instruction selection before we have found all call points.) + + All other fields have already been initialised by + [reinitialise_free_node_block]. + */ + + *node_hole = node; + + return 1; /* indicates a new node was created */ +} + +static c_node* allocate_c_node(void) +{ + c_node* node; + size_t index; + + node = (c_node*) start_of_free_node_block; + if (end_of_free_node_block - start_of_free_node_block < sizeof(c_node)) { + reinitialise_free_node_block(); + node = (c_node*) start_of_free_node_block; + CAMLassert(end_of_free_node_block - start_of_free_node_block + >= sizeof(c_node)); + } + start_of_free_node_block += sizeof(c_node); + + CAMLassert((sizeof(c_node) % sizeof(uintnat)) == 0); + + /* CR-soon mshinwell: remove this and pad the structure properly */ + for (index = 0; index < sizeof(c_node) / sizeof(value); index++) { + ((value*) node)[index] = Val_unit; + } + + node->gc_header = + Make_header(sizeof(c_node)/sizeof(uintnat) - 1, C_node_tag, Caml_black); + node->data.call.callee_node = Val_unit; + node->data.call.call_count = Val_long(0); + node->next = Val_unit; + + return node; +} + +/* Since a given indirect call site either always yields tail calls or + always yields non-tail calls, the output of + [caml_spacetime_indirect_node_hole_ptr] is uniquely determined by its + first two arguments (the callee and the node hole). We cache these + to increase performance of recursive functions containing an indirect + call (e.g. [List.map] when not inlined). */ +static void* last_indirect_node_hole_ptr_callee; +static value* last_indirect_node_hole_ptr_node_hole; +static call_point* last_indirect_node_hole_ptr_result; + +CAMLprim value* caml_spacetime_indirect_node_hole_ptr + (void* callee, value* node_hole, value caller_node) +{ + /* Find the address of the node hole for an indirect call to [callee]. + If [caller_node] is not [Val_unit], it is a pointer to the caller's + node, and indicates that this is a tail call site. */ + + c_node* c_node; + value encoded_callee; + + if (callee == last_indirect_node_hole_ptr_callee + && node_hole == last_indirect_node_hole_ptr_node_hole) { +#ifdef ENABLE_CALL_COUNTS + last_indirect_node_hole_ptr_result->call_count = + Val_long (Long_val (last_indirect_node_hole_ptr_result->call_count) + 1); +#endif + return &(last_indirect_node_hole_ptr_result->callee_node); + } + + last_indirect_node_hole_ptr_callee = callee; + last_indirect_node_hole_ptr_node_hole = node_hole; + + encoded_callee = Encode_c_node_pc_for_call(callee); + + while (*node_hole != Val_unit) { + CAMLassert(((uintnat) *node_hole) % sizeof(value) == 0); + + c_node = caml_spacetime_c_node_of_stored_pointer_not_null(*node_hole); + + CAMLassert(c_node != NULL); + CAMLassert(caml_spacetime_classify_c_node(c_node) == CALL); + + if (c_node->pc == encoded_callee) { +#ifdef ENABLE_CALL_COUNTS + c_node->data.call.call_count = + Val_long (Long_val(c_node->data.call.call_count) + 1); +#endif + last_indirect_node_hole_ptr_result = &(c_node->data.call); + return &(last_indirect_node_hole_ptr_result->callee_node); + } + else { + node_hole = &c_node->next; + } + } + + c_node = allocate_c_node(); + c_node->pc = encoded_callee; + + if (caller_node != Val_unit) { + /* This is a tail call site. + Perform the initialization equivalent to that emitted by + [Spacetime.code_for_function_prologue] for direct tail call + sites. */ + c_node->data.call.callee_node = Encode_tail_caller_node(caller_node); + } + + *node_hole = caml_spacetime_stored_pointer_of_c_node(c_node); + + CAMLassert(((uintnat) *node_hole) % sizeof(value) == 0); + CAMLassert(*node_hole != Val_unit); + +#ifdef ENABLE_CALL_COUNTS + c_node->data.call.call_count = + Val_long (Long_val(c_node->data.call.call_count) + 1); +#endif + last_indirect_node_hole_ptr_result = &(c_node->data.call); + + return &(last_indirect_node_hole_ptr_result->callee_node); +} + +/* Some notes on why caml_call_gc doesn't need a distinguished node. + (Remember that thread switches are irrelevant here because each thread + has its own trie.) + + caml_call_gc only invokes OCaml functions in the following circumstances: + 1. running an OCaml finaliser; + 2. executing an OCaml signal handler. + Both of these are done on the finaliser trie. Furthermore, both of + these invocations start via caml_callback; the code in this file for + handling that (caml_spacetime_c_to_ocaml) correctly copes with that by + attaching a single "caml_start_program" node that can cope with any + number of indirect OCaml calls from that point. + + caml_call_gc may also invoke C functions that cause allocation. All of + these (assuming libunwind support is present) will cause a chain of + c_node structures to be attached to the trie, starting at the node hole + passed to caml_call_gc from OCaml code. These structures are extensible + and can thus accommodate any number of C backtraces leading from + caml_call_gc. +*/ +/* CR-soon mshinwell: it might in fact be the case now that nothing called + from caml_call_gc will do any allocation that ends up on the trie. We + can revisit this after the first release. */ + +static NOINLINE void* find_trie_node_from_libunwind(int for_allocation, + uintnat wosize, struct ext_table** cached_frames) +{ +#ifdef HAS_LIBUNWIND + /* Given that [caml_last_return_address] is the most recent call site in + OCaml code, and that we are now in C (or other) code called from that + site, obtain a backtrace using libunwind and graft the most recent + portion (everything back to but not including [caml_last_return_address]) + onto the trie. See the important comment below regarding the fact that + call site, and not callee, addresses are recorded during this process. + + If [for_allocation] is non-zero, the final node recorded will be for + an allocation, and the returned pointer is to the allocation node. + Otherwise, no node is recorded for the innermost frame, and the + returned pointer is a pointer to the *node hole* where a node for that + frame should be attached. + + If [for_allocation] is non-zero then [wosize] must give the size in + words, excluding the header, of the value being allocated. + + If [cached_frames != NULL] then: + 1. If [*cached_frames] is NULL then save the captured backtrace in a + newly-allocated table and store the pointer to that table in + [*cached_frames]; + 2. Otherwise use [*cached_frames] as the unwinding information. + The intention is that when the context is known (e.g. a function such + as [caml_make_vect] known to have been directly invoked from OCaml), + we can avoid expensive calls to libunwind. + */ + + unw_cursor_t cur; + unw_context_t ctx; + int ret; + int innermost_frame; + int frame; + static struct ext_table frames_local; + struct ext_table* frames; + static int ext_table_initialised = 0; + int have_frames_already = 0; + value* node_hole; + c_node* node = NULL; + int initial_table_size = 1000; + int must_initialise_node_for_allocation = 0; + + if (!cached_frames) { + if (!ext_table_initialised) { + caml_ext_table_init(&frames_local, initial_table_size); + ext_table_initialised = 1; + } + else { + caml_ext_table_clear(&frames_local, 0); + } + frames = &frames_local; + } else { + if (*cached_frames) { + frames = *cached_frames; + have_frames_already = 1; + } + else { + frames = + (struct ext_table*) caml_stat_alloc_noexc(sizeof(struct ext_table)); + if (!frames) { + caml_fatal_error("not enough memory for ext_table allocation"); + } + caml_ext_table_init(frames, initial_table_size); + *cached_frames = frames; + } + } + + if (!have_frames_already) { + /* Get the stack backtrace as far as [caml_last_return_address]. */ + + ret = unw_getcontext(&ctx); + if (ret != UNW_ESUCCESS) { + return NULL; + } + + ret = unw_init_local(&cur, &ctx); + if (ret != UNW_ESUCCESS) { + return NULL; + } + + while ((ret = unw_step(&cur)) > 0) { + unw_word_t ip; + unw_get_reg(&cur, UNW_REG_IP, &ip); + if (caml_last_return_address == (uintnat) ip) { + break; + } + else { + /* Inlined some of [caml_ext_table_add] for speed. */ + if (frames->size < frames->capacity) { + frames->contents[frames->size++] = (void*) ip; + } else { + caml_ext_table_add(frames, (void*) ip); + } + } + } + } + + /* We always need to ignore the frames for: + #0 find_trie_node_from_libunwind + #1 caml_spacetime_c_to_ocaml + Further, if this is not an allocation point, we should not create the + node for the current C function that triggered us (i.e. frame #2). */ + innermost_frame = for_allocation ? 1 : 2; + + if (frames->size - 1 < innermost_frame) { + /* Insufficiently many frames (maybe no frames) returned from + libunwind; just don't do anything. */ + return NULL; + } + + node_hole = caml_spacetime_trie_node_ptr; + /* Note that if [node_hole] is filled, then it must point to a C node, + since it is not possible for there to be a call point in an OCaml + function that sometimes calls C and sometimes calls OCaml. */ + + for (frame = frames->size - 1; frame >= innermost_frame; frame--) { + c_node_type expected_type; + void* pc = frames->contents[frame]; + CAMLassert (pc != (void*) caml_last_return_address); + + if (!for_allocation) { + expected_type = CALL; + } + else { + expected_type = (frame > innermost_frame ? CALL : ALLOCATION); + } + + if (*node_hole == Val_unit) { + node = allocate_c_node(); + /* Note: for CALL nodes, the PC is the program counter at each call + site. We do not store program counter addresses of the start of + callees, unlike for OCaml nodes. This means that some trie nodes + will become conflated. These can be split during post-processing by + working out which function each call site was in. */ + node->pc = (expected_type == CALL ? Encode_c_node_pc_for_call(pc) + : Encode_c_node_pc_for_alloc_point(pc)); + *node_hole = caml_spacetime_stored_pointer_of_c_node(node); + if (expected_type == ALLOCATION) { + must_initialise_node_for_allocation = 1; + } + } + else { + c_node* prev; + int found = 0; + + node = caml_spacetime_c_node_of_stored_pointer_not_null(*node_hole); + CAMLassert(node != NULL); + CAMLassert(node->next == Val_unit + || (((uintnat) (node->next)) % sizeof(value) == 0)); + + prev = NULL; + + while (!found && node != NULL) { + if (caml_spacetime_classify_c_node(node) == expected_type + && pc_inside_c_node_matches(node, pc)) { + found = 1; + } + else { + prev = node; + node = caml_spacetime_c_node_of_stored_pointer(node->next); + } + } + if (!found) { + CAMLassert(prev != NULL); + node = allocate_c_node(); + node->pc = (expected_type == CALL ? Encode_c_node_pc_for_call(pc) + : Encode_c_node_pc_for_alloc_point(pc)); + if (expected_type == ALLOCATION) { + must_initialise_node_for_allocation = 1; + } + prev->next = caml_spacetime_stored_pointer_of_c_node(node); + } + } + + CAMLassert(node != NULL); + + CAMLassert(caml_spacetime_classify_c_node(node) == expected_type); + CAMLassert(pc_inside_c_node_matches(node, pc)); + node_hole = &node->data.call.callee_node; + } + + if (must_initialise_node_for_allocation) { + caml_spacetime_profinfo++; + if (caml_spacetime_profinfo > PROFINFO_MASK) { + /* Profiling counter overflow. */ + caml_spacetime_profinfo = PROFINFO_MASK; + } + node->data.allocation.profinfo = + Make_header_with_profinfo( + /* "-1" because [c_node] has the GC header as its first + element. */ + offsetof(c_node, data.allocation.count)/sizeof(value) - 1, + Infix_tag, + Caml_black, + caml_spacetime_profinfo); + node->data.allocation.count = Val_long(0); + + /* Add the new allocation point into the linked list of all allocation + points. */ + if (caml_all_allocation_points != NULL) { + node->data.allocation.next = + (value) &caml_all_allocation_points->count; + } else { + node->data.allocation.next = Val_unit; + } + caml_all_allocation_points = &node->data.allocation; + } + + if (for_allocation) { + CAMLassert(caml_spacetime_classify_c_node(node) == ALLOCATION); + CAMLassert(caml_spacetime_c_node_of_stored_pointer(node->next) != node); + CAMLassert(Profinfo_hd(node->data.allocation.profinfo) > 0); + node->data.allocation.count = + Val_long(Long_val(node->data.allocation.count) + (1 + wosize)); + } + + CAMLassert(node->next != (value) NULL); + + return for_allocation ? (void*) node : (void*) node_hole; +#else + return NULL; +#endif +} + +void caml_spacetime_c_to_ocaml(void* ocaml_entry_point, + void* identifying_pc_for_caml_start_program) +{ + /* Called in [caml_start_program] and [caml_callback*] when we are about + to cross from C into OCaml. [ocaml_entry_point] is the branch target. + This situation is handled by ensuring the presence of a new OCaml node + for the callback veneer; the node contains a single indirect call point + which accumulates the [ocaml_entry_point]s. + + The layout of the node is described in the "system shape table"; see + amd64.S. + */ + + value node; + + /* Update the trie with the current backtrace, as far back as + [caml_last_return_address], and leave the node hole pointer at + the correct place for attachment of a [caml_start_program] node. */ + +#ifdef HAS_LIBUNWIND + value* node_temp; + node_temp = (value*) find_trie_node_from_libunwind(0, 0, NULL); + if (node_temp != NULL) { + caml_spacetime_trie_node_ptr = node_temp; + } +#endif + + if (*caml_spacetime_trie_node_ptr == Val_unit) { + uintnat size_including_header; + + size_including_header = + 1 /* GC header */ + Node_num_header_words + Indirect_num_fields; + + node = allocate_uninitialized_ocaml_node(size_including_header); + Hd_val(node) = + Make_header(size_including_header - 1, OCaml_node_tag, Caml_black); + CAMLassert((((uintnat) identifying_pc_for_caml_start_program) % 1) == 0); + Node_pc(node) = Encode_node_pc(identifying_pc_for_caml_start_program); + Tail_link(node) = node; + Indirect_pc_linked_list(node, Node_num_header_words) = Val_unit; + *caml_spacetime_trie_node_ptr = node; + } + else { + node = *caml_spacetime_trie_node_ptr; + /* If there is a node here already, it should never be an initialized + (but as yet unused) tail call point, since calls from OCaml into C + are never tail calls (and no C -> C call is marked as tail). */ + CAMLassert(!Is_tail_caller_node_encoded(node)); + } + + CAMLassert(Is_ocaml_node(node)); + CAMLassert(Decode_node_pc(Node_pc(node)) + == identifying_pc_for_caml_start_program); + CAMLassert(Tail_link(node) == node); + CAMLassert(Wosize_val(node) == Node_num_header_words + Indirect_num_fields); + + /* Search the node to find the node hole corresponding to the indirect + call to the OCaml function. */ + caml_spacetime_trie_node_ptr = + caml_spacetime_indirect_node_hole_ptr( + ocaml_entry_point, + &Indirect_pc_linked_list(node, Node_num_header_words), + Val_unit); + CAMLassert(*caml_spacetime_trie_node_ptr == Val_unit + || Is_ocaml_node(*caml_spacetime_trie_node_ptr)); +} + +extern void caml_garbage_collection(void); /* signals_nat.c */ +extern void caml_array_bound_error(void); /* fail.c */ + +CAMLprim uintnat caml_spacetime_generate_profinfo (void* profinfo_words, + uintnat index_within_node) +{ + /* Called from code that creates a value's header inside an OCaml + function. */ + + value node; + uintnat profinfo; + + caml_spacetime_profinfo++; + if (caml_spacetime_profinfo > PROFINFO_MASK) { + /* Profiling counter overflow. */ + caml_spacetime_profinfo = PROFINFO_MASK; + } + profinfo = caml_spacetime_profinfo; + + /* CR-someday mshinwell: we could always use the [struct allocation_point] + overlay instead of the macros now. */ + + /* [node] isn't really a node; it points into the middle of + one---specifically to the "profinfo" word of an allocation point. + It's done like this to avoid re-calculating the place in the node + (which already has to be done in the OCaml-generated code run before + this function). */ + node = (value) profinfo_words; + CAMLassert(Alloc_point_profinfo(node, 0) == Val_unit); + + /* The profinfo value is stored shifted to reduce the number of + instructions required on the OCaml side. It also enables us to use + [Infix_tag] to obtain valid value pointers into the middle of nodes, + which is used for the linked list of all allocation points. */ + profinfo = Make_header_with_profinfo( + index_within_node, Infix_tag, Caml_black, profinfo); + + CAMLassert(!Is_block(profinfo)); + Alloc_point_profinfo(node, 0) = profinfo; + /* The count is set to zero by the initialisation when the node was + created (see above). */ + CAMLassert(Alloc_point_count(node, 0) == Val_long(0)); + + /* Add the new allocation point into the linked list of all allocation + points. */ + if (caml_all_allocation_points != NULL) { + Alloc_point_next_ptr(node, 0) = (value) &caml_all_allocation_points->count; + } + else { + CAMLassert(Alloc_point_next_ptr(node, 0) == Val_unit); + } + caml_all_allocation_points = (allocation_point*) node; + + return profinfo; +} + +uintnat caml_spacetime_my_profinfo (struct ext_table** cached_frames, + uintnat wosize) +{ + /* Return the profinfo value that should be written into a value's header + during an allocation from C. This may necessitate extending the trie + with information obtained from libunwind. */ + + c_node* node; + uintnat profinfo = 0; + + node = find_trie_node_from_libunwind(1, wosize, cached_frames); + if (node != NULL) { + profinfo = ((uintnat) (node->data.allocation.profinfo)) >> PROFINFO_SHIFT; + } + + return profinfo; /* N.B. not shifted by PROFINFO_SHIFT */ +} + +void caml_spacetime_automatic_snapshot (void) +{ + if (automatic_snapshots) { + double start_time, end_time; + start_time = caml_sys_time_unboxed(Val_unit); + if (start_time >= next_snapshot_time) { + maybe_reopen_snapshot_channel(); + caml_spacetime_save_snapshot(snapshot_channel, 0.0, 0); + end_time = caml_sys_time_unboxed(Val_unit); + next_snapshot_time = end_time + snapshot_interval; + } + } +} + +CAMLprim value caml_spacetime_save_event_for_automatic_snapshots + (value v_event_name) +{ + if (automatic_snapshots) { + maybe_reopen_snapshot_channel(); + caml_spacetime_save_event_internal (Val_unit, snapshot_channel, + v_event_name); + } + return Val_unit; +} + +void caml_spacetime_automatic_save (void) +{ + /* Called from [atexit]. */ + + if (automatic_snapshots) { + automatic_snapshots = 0; + maybe_reopen_snapshot_channel(); + save_trie(snapshot_channel, 0.0, 0); + caml_flush(snapshot_channel); + caml_close_channel(snapshot_channel); + } +} + +CAMLprim value caml_spacetime_enabled (value v_unit) +{ + return Val_true; +} + +CAMLprim value caml_register_channel_for_spacetime (value v_channel) +{ + struct channel* channel = Channel(v_channel); + channel->flags |= CHANNEL_FLAG_BLOCKING_WRITE; + return Val_unit; +} + +#else + +/* Functions for when the compiler was not configured with "-spacetime". */ + +CAMLprim value caml_spacetime_write_magic_number(value v_channel) +{ + return Val_unit; +} + +CAMLprim value caml_spacetime_enabled (value v_unit) +{ + return Val_false; +} + +CAMLprim value caml_spacetime_save_event (value v_time_opt, + value v_channel, + value v_event_name) +{ + return Val_unit; +} + +CAMLprim value caml_spacetime_save_event_for_automatic_snapshots + (value v_event_name) +{ + return Val_unit; +} + +CAMLprim value caml_spacetime_save_trie (value ignored) +{ + return Val_unit; +} + +CAMLprim value caml_register_channel_for_spacetime (value v_channel) +{ + return Val_unit; +} + +#endif diff --git a/asmrun/spacetime_snapshot.c b/runtime/spacetime_snapshot.c similarity index 100% rename from asmrun/spacetime_snapshot.c rename to runtime/spacetime_snapshot.c diff --git a/byterun/stacks.c b/runtime/stacks.c similarity index 100% rename from byterun/stacks.c rename to runtime/stacks.c diff --git a/runtime/startup_aux.c b/runtime/startup_aux.c new file mode 100644 index 00000000..9ab22e2a --- /dev/null +++ b/runtime/startup_aux.c @@ -0,0 +1,176 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Some runtime initialization functions that are common to bytecode + and native code. */ + +#include +#include "caml/backtrace.h" +#include "caml/memory.h" +#include "caml/callback.h" +#include "caml/major_gc.h" +#ifndef NATIVE_CODE +#include "caml/dynlink.h" +#endif +#include "caml/osdeps.h" +#include "caml/startup_aux.h" + + +/* Initialize the atom table */ + +CAMLexport header_t caml_atom_table[256]; +void caml_init_atom_table(void) +{ + int i; + for(i = 0; i < 256; i++) { +#ifdef NATIVE_CODE + caml_atom_table[i] = Make_header_allocated_here(0, i, Caml_white); +#else + caml_atom_table[i] = Make_header(0, i, Caml_white); +#endif + } + if (caml_page_table_add(In_static_data, + caml_atom_table, caml_atom_table + 256) != 0) { + caml_fatal_error("not enough memory for initial page table"); + } +} + + +/* Parse the OCAMLRUNPARAM environment variable. */ + +uintnat caml_init_percent_free = Percent_free_def; +uintnat caml_init_max_percent_free = Max_percent_free_def; +uintnat caml_init_minor_heap_wsz = Minor_heap_def; +uintnat caml_init_heap_chunk_sz = Heap_chunk_def; +uintnat caml_init_heap_wsz = Init_heap_def; +uintnat caml_init_max_stack_wsz = Max_stack_def; +uintnat caml_init_major_window = Major_window_def; +uintnat caml_init_custom_major_ratio = Custom_major_ratio_def; +uintnat caml_init_custom_minor_ratio = Custom_minor_ratio_def; +uintnat caml_init_custom_minor_max_bsz = Custom_minor_max_bsz_def; +extern int caml_parser_trace; +uintnat caml_trace_level = 0; +int caml_cleanup_on_exit = 0; + + +static void scanmult (char_os *opt, uintnat *var) +{ + char_os mult = _T(' '); + unsigned int val = 1; + sscanf_os (opt, _T("=%u%c"), &val, &mult); + sscanf_os (opt, _T("=0x%x%c"), &val, &mult); + switch (mult) { + case _T('k'): *var = (uintnat) val * 1024; break; + case _T('M'): *var = (uintnat) val * (1024 * 1024); break; + case _T('G'): *var = (uintnat) val * (1024 * 1024 * 1024); break; + default: *var = (uintnat) val; break; + } +} + +void caml_parse_ocamlrunparam(void) +{ + char_os *opt = caml_secure_getenv (_T("OCAMLRUNPARAM")); + uintnat p; + + if (opt == NULL) opt = caml_secure_getenv (_T("CAMLRUNPARAM")); + + if (opt != NULL){ + while (*opt != _T('\0')){ + switch (*opt++){ + case _T('a'): scanmult (opt, &p); caml_set_allocation_policy (p); break; + case _T('b'): scanmult (opt, &p); caml_record_backtrace(Val_bool (p)); + break; + case _T('c'): scanmult (opt, &p); caml_cleanup_on_exit = (p != 0); break; + case _T('h'): scanmult (opt, &caml_init_heap_wsz); break; + case _T('H'): scanmult (opt, &caml_use_huge_pages); break; + case _T('i'): scanmult (opt, &caml_init_heap_chunk_sz); break; + case _T('l'): scanmult (opt, &caml_init_max_stack_wsz); break; + case _T('M'): scanmult (opt, &caml_init_custom_major_ratio); break; + case _T('m'): scanmult (opt, &caml_init_custom_minor_ratio); break; + case _T('n'): scanmult (opt, &caml_init_custom_minor_max_bsz); break; + case _T('o'): scanmult (opt, &caml_init_percent_free); break; + case _T('O'): scanmult (opt, &caml_init_max_percent_free); break; + case _T('p'): scanmult (opt, &p); caml_parser_trace = (p != 0); break; + case _T('R'): break; /* see stdlib/hashtbl.mli */ + case _T('s'): scanmult (opt, &caml_init_minor_heap_wsz); break; + case _T('t'): scanmult (opt, &caml_trace_level); break; + case _T('v'): scanmult (opt, &caml_verb_gc); break; + case _T('w'): scanmult (opt, &caml_init_major_window); break; + case _T('W'): scanmult (opt, &caml_runtime_warnings); break; + } + while (*opt != _T('\0')){ + if (*opt++ == ',') break; + } + } + } +} + + +/* The number of outstanding calls to caml_startup */ +static int startup_count = 0; + +/* Has the runtime been shut down already? */ +static int shutdown_happened = 0; + + +int caml_startup_aux(int pooling) +{ + if (shutdown_happened == 1) + caml_fatal_error("caml_startup was called after the runtime " + "was shut down with caml_shutdown"); + + /* Second and subsequent calls are ignored, + since the runtime has already started */ + startup_count++; + if (startup_count > 1) + return 0; + + if (pooling) + caml_stat_create_pool(); + + return 1; +} + +static void call_registered_value(char* name) +{ + value *f = caml_named_value(name); + if (f != NULL) + caml_callback_exn(*f, Val_unit); +} + +CAMLexport void caml_shutdown(void) +{ + if (startup_count <= 0) + caml_fatal_error("a call to caml_shutdown has no " + "corresponding call to caml_startup"); + + /* Do nothing unless it's the last call remaining */ + startup_count--; + if (startup_count > 0) + return; + + call_registered_value("Pervasives.do_at_exit"); + call_registered_value("Thread.at_shutdown"); + caml_finalise_heap(); + caml_free_locale(); +#ifndef NATIVE_CODE + caml_free_shared_libs(); +#endif + caml_stat_destroy_pool(); + + shutdown_happened = 1; +} diff --git a/runtime/startup_byt.c b/runtime/startup_byt.c new file mode 100644 index 00000000..1f648956 --- /dev/null +++ b/runtime/startup_byt.c @@ -0,0 +1,563 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Start-up code */ + +#include +#include +#include +#include +#include "caml/config.h" +#ifdef HAS_UNISTD +#include +#endif +#ifdef _WIN32 +#include +#endif +#include "caml/alloc.h" +#include "caml/backtrace.h" +#include "caml/callback.h" +#include "caml/custom.h" +#include "caml/debugger.h" +#include "caml/dynlink.h" +#include "caml/exec.h" +#include "caml/fail.h" +#include "caml/fix_code.h" +#include "caml/freelist.h" +#include "caml/gc_ctrl.h" +#include "caml/instrtrace.h" +#include "caml/interp.h" +#include "caml/intext.h" +#include "caml/io.h" +#include "caml/memory.h" +#include "caml/minor_gc.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/osdeps.h" +#include "caml/prims.h" +#include "caml/printexc.h" +#include "caml/reverse.h" +#include "caml/signals.h" +#include "caml/stacks.h" +#include "caml/sys.h" +#include "caml/startup.h" +#include "caml/startup_aux.h" +#include "caml/version.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +static char magicstr[EXEC_MAGIC_LENGTH+1]; +static int print_magic = 0; + +/* Read the trailer of a bytecode file */ + +static void fixup_endianness_trailer(uint32_t * p) +{ +#ifndef ARCH_BIG_ENDIAN + Reverse_32(p, p); +#endif +} + +static int read_trailer(int fd, struct exec_trailer *trail) +{ + if (lseek(fd, (long) -TRAILER_SIZE, SEEK_END) == -1) + return BAD_BYTECODE; + if (read(fd, (char *) trail, TRAILER_SIZE) < TRAILER_SIZE) + return BAD_BYTECODE; + fixup_endianness_trailer(&trail->num_sections); + memcpy(magicstr, trail->magic, EXEC_MAGIC_LENGTH); + magicstr[EXEC_MAGIC_LENGTH] = 0; + + if (print_magic) { + printf("%s\n", magicstr); + exit(0); + } + return + (strncmp(trail->magic, EXEC_MAGIC, sizeof(trail->magic)) == 0) + ? 0 : WRONG_MAGIC; +} + +int caml_attempt_open(char_os **name, struct exec_trailer *trail, + int do_open_script) +{ + char_os * truename; + int fd; + int err; + char buf [2], * u8; + + truename = caml_search_exe_in_path(*name); + u8 = caml_stat_strdup_of_os(truename); + caml_gc_message(0x100, "Opening bytecode executable %s\n", u8); + caml_stat_free(u8); + fd = open_os(truename, O_RDONLY | O_BINARY); + if (fd == -1) { + caml_stat_free(truename); + caml_gc_message(0x100, "Cannot open file\n"); + return FILE_NOT_FOUND; + } + if (!do_open_script) { + err = read (fd, buf, 2); + if (err < 2 || (buf [0] == '#' && buf [1] == '!')) { + close(fd); + caml_stat_free(truename); + caml_gc_message(0x100, "Rejected #! script\n"); + return BAD_BYTECODE; + } + } + err = read_trailer(fd, trail); + if (err != 0) { + close(fd); + caml_stat_free(truename); + caml_gc_message(0x100, "Not a bytecode executable\n"); + return err; + } + *name = truename; + return fd; +} + +/* Read the section descriptors */ + +void caml_read_section_descriptors(int fd, struct exec_trailer *trail) +{ + int toc_size, i; + + toc_size = trail->num_sections * 8; + trail->section = caml_stat_alloc(toc_size); + lseek(fd, - (long) (TRAILER_SIZE + toc_size), SEEK_END); + if (read(fd, (char *) trail->section, toc_size) != toc_size) + caml_fatal_error("cannot read section table"); + /* Fixup endianness of lengths */ + for (i = 0; i < trail->num_sections; i++) + fixup_endianness_trailer(&(trail->section[i].len)); +} + +/* Position fd at the beginning of the section having the given name. + Return the length of the section data in bytes, or -1 if no section + found with that name. */ + +int32_t caml_seek_optional_section(int fd, struct exec_trailer *trail, + char *name) +{ + long ofs; + int i; + + ofs = TRAILER_SIZE + trail->num_sections * 8; + for (i = trail->num_sections - 1; i >= 0; i--) { + ofs += trail->section[i].len; + if (strncmp(trail->section[i].name, name, 4) == 0) { + lseek(fd, -ofs, SEEK_END); + return trail->section[i].len; + } + } + return -1; +} + +/* Position fd at the beginning of the section having the given name. + Return the length of the section data in bytes. */ + +int32_t caml_seek_section(int fd, struct exec_trailer *trail, char *name) +{ + int32_t len = caml_seek_optional_section(fd, trail, name); + if (len == -1) + caml_fatal_error("section `%s' is missing", name); + return len; +} + +/* Read and return the contents of the section having the given name. + Add a terminating 0. Return NULL if no such section. */ + +static char * read_section(int fd, struct exec_trailer *trail, char *name) +{ + int32_t len; + char * data; + + len = caml_seek_optional_section(fd, trail, name); + if (len == -1) return NULL; + data = caml_stat_alloc(len + 1); + if (read(fd, data, len) != len) + caml_fatal_error("error reading section %s", name); + data[len] = 0; + return data; +} + +#ifdef _WIN32 + +static char_os * read_section_to_os(int fd, struct exec_trailer *trail, + char *name) +{ + int32_t len, wlen; + char * data; + wchar_t * wdata; + + len = caml_seek_optional_section(fd, trail, name); + if (len == -1) return NULL; + data = caml_stat_alloc(len + 1); + if (read(fd, data, len) != len) + caml_fatal_error("error reading section %s", name); + data[len] = 0; + wlen = win_multi_byte_to_wide_char(data, len, NULL, 0); + wdata = caml_stat_alloc((wlen + 1)*sizeof(wchar_t)); + win_multi_byte_to_wide_char(data, len, wdata, wlen); + wdata[wlen] = 0; + caml_stat_free(data); + return wdata; +} + +#else + +#define read_section_to_os read_section + +#endif + +/* Invocation of ocamlrun: 4 cases. + + 1. runtime + bytecode + user types: ocamlrun [options] bytecode args... + arguments: ocamlrun [options] bytecode args... + + 2. bytecode script + user types: bytecode args... + 2a (kernel 1) arguments: ocamlrun ./bytecode args... + 2b (kernel 2) arguments: bytecode bytecode args... + + 3. concatenated runtime and bytecode + user types: composite args... + arguments: composite args... + +Algorithm: + 1- If argument 0 is a valid byte-code file that does not start with #!, + then we are in case 3 and we pass the same command line to the + OCaml program. + 2- In all other cases, we parse the command line as: + (whatever) [options] bytecode args... + and we strip "(whatever) [options]" from the command line. + +*/ + +/* Parse options on the command line */ + +static int parse_command_line(char_os **argv) +{ + int i, j; + + for(i = 1; argv[i] != NULL && argv[i][0] == _T('-'); i++) { + switch(argv[i][1]) { + case _T('t'): + ++ caml_trace_level; /* ignored unless DEBUG mode */ + break; + case _T('v'): + if (!strcmp_os (argv[i], _T("-version"))){ + printf ("%s\n", "The OCaml runtime, version " OCAML_VERSION_STRING); + exit (0); + }else if (!strcmp_os (argv[i], _T("-vnum"))){ + printf ("%s\n", OCAML_VERSION_STRING); + exit (0); + }else{ + caml_verb_gc = 0x001+0x004+0x008+0x010+0x020; + } + break; + case _T('p'): + for (j = 0; caml_names_of_builtin_cprim[j] != NULL; j++) + printf("%s\n", caml_names_of_builtin_cprim[j]); + exit(0); + break; + case _T('b'): + caml_record_backtrace(Val_true); + break; + case _T('I'): + if (argv[i + 1] != NULL) { + caml_ext_table_add(&caml_shared_libs_path, argv[i + 1]); + i++; + } + break; + case _T('m'): + print_magic = 1; + break; + case _T('M'): + printf ( "%s\n", EXEC_MAGIC); + exit(0); + break; + default: + caml_fatal_error("unknown option %s", caml_stat_strdup_of_os(argv[i])); + } + } + return i; +} + +extern void caml_init_ieee_floats (void); + +#ifdef _WIN32 +extern void caml_signal_thread(void * lpParam); +#endif + +#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L + +/* PR 4887: avoid crash box of windows runtime on some system calls */ +extern void caml_install_invalid_parameter_handler(); + +#endif + +extern int caml_ensure_spacetime_dot_o_is_included; + +/* Main entry point when loading code from a file */ + +CAMLexport void caml_main(char_os **argv) +{ + int fd, pos; + struct exec_trailer trail; + struct channel * chan; + value res; + char * req_prims; + char_os * shared_lib_path, * shared_libs; + char_os * exe_name, * proc_self_exe; + + caml_ensure_spacetime_dot_o_is_included++; + + /* Determine options */ +#ifdef DEBUG + caml_verb_gc = 0x3F; +#endif + caml_parse_ocamlrunparam(); +#ifdef DEBUG + caml_gc_message (-1, "### OCaml runtime: debug mode ###\n"); +#endif + if (!caml_startup_aux(/* pooling */ caml_cleanup_on_exit)) + return; + + /* Machine-dependent initialization of the floating-point hardware + so that it behaves as much as possible as specified in IEEE */ + caml_init_ieee_floats(); + caml_init_locale(); +#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L + caml_install_invalid_parameter_handler(); +#endif + caml_init_custom_operations(); + caml_ext_table_init(&caml_shared_libs_path, 8); + caml_external_raise = NULL; + + /* Determine position of bytecode file */ + pos = 0; + + /* First, try argv[0] (when ocamlrun is called by a bytecode program) */ + exe_name = argv[0]; + fd = caml_attempt_open(&exe_name, &trail, 0); + + /* Little grasshopper wonders why we do that at all, since + "The current executable is ocamlrun itself, it's never a bytecode + program". Little grasshopper "ocamlc -custom" in mind should keep. + With -custom, we have an executable that is ocamlrun itself + concatenated with the bytecode. So, if the attempt with argv[0] + failed, it is worth trying again with executable_name. */ + if (fd < 0 && (proc_self_exe = caml_executable_name()) != NULL) { + exe_name = proc_self_exe; + fd = caml_attempt_open(&exe_name, &trail, 0); + } + + if (fd < 0) { + pos = parse_command_line(argv); + if (argv[pos] == 0) + caml_fatal_error("no bytecode file specified"); + exe_name = argv[pos]; + fd = caml_attempt_open(&exe_name, &trail, 1); + switch(fd) { + case FILE_NOT_FOUND: + caml_fatal_error("cannot find file '%s'", + caml_stat_strdup_of_os(argv[pos])); + break; + case BAD_BYTECODE: + caml_fatal_error( + "the file '%s' is not a bytecode executable file", + caml_stat_strdup_of_os(exe_name)); + break; + case WRONG_MAGIC: + caml_fatal_error( + "the file '%s' has not the right magic number: "\ + "expected %s, got %s", + caml_stat_strdup_of_os(exe_name), + EXEC_MAGIC, + magicstr); + break; + } + } + /* Read the table of contents (section descriptors) */ + caml_read_section_descriptors(fd, &trail); + /* Initialize the abstract machine */ + caml_init_gc (caml_init_minor_heap_wsz, caml_init_heap_wsz, + caml_init_heap_chunk_sz, caml_init_percent_free, + caml_init_max_percent_free, caml_init_major_window, + caml_init_custom_major_ratio, caml_init_custom_minor_ratio, + caml_init_custom_minor_max_bsz); + caml_init_stack (caml_init_max_stack_wsz); + caml_init_atom_table(); + caml_init_backtrace(); + /* Initialize the interpreter */ + caml_interprete(NULL, 0); + /* Initialize the debugger, if needed */ + caml_debugger_init(); + /* Load the code */ + caml_code_size = caml_seek_section(fd, &trail, "CODE"); + caml_load_code(fd, caml_code_size); + caml_init_debug_info(); + /* Build the table of primitives */ + shared_lib_path = read_section_to_os(fd, &trail, "DLPT"); + shared_libs = read_section_to_os(fd, &trail, "DLLS"); + req_prims = read_section(fd, &trail, "PRIM"); + if (req_prims == NULL) caml_fatal_error("no PRIM section"); + caml_build_primitive_table(shared_lib_path, shared_libs, req_prims); + caml_stat_free(shared_lib_path); + caml_stat_free(shared_libs); + caml_stat_free(req_prims); + /* Load the globals */ + caml_seek_section(fd, &trail, "DATA"); + chan = caml_open_descriptor_in(fd); + caml_global_data = caml_input_val(chan); + caml_close_channel(chan); /* this also closes fd */ + caml_stat_free(trail.section); + /* Ensure that the globals are in the major heap. */ + caml_oldify_one (caml_global_data, &caml_global_data); + caml_oldify_mopup (); + /* Initialize system libraries */ + caml_sys_init(exe_name, argv + pos); +#ifdef _WIN32 + /* Start a thread to handle signals */ + if (caml_secure_getenv(_T("CAMLSIGPIPE"))) + _beginthread(caml_signal_thread, 4096, NULL); +#endif + /* Execute the program */ + caml_debugger(PROGRAM_START); + res = caml_interprete(caml_start_code, caml_code_size); + if (Is_exception_result(res)) { + caml_exn_bucket = Extract_exception(res); + if (caml_debugger_in_use) { + caml_extern_sp = &caml_exn_bucket; /* The debugger needs the + exception value.*/ + caml_debugger(UNCAUGHT_EXC); + } + caml_fatal_uncaught_exception(caml_exn_bucket); + } +} + +/* Main entry point when code is linked in as initialized data */ + +CAMLexport value caml_startup_code_exn( + code_t code, asize_t code_size, + char *data, asize_t data_size, + char *section_table, asize_t section_table_size, + int pooling, + char_os **argv) +{ + char_os * cds_file; + char_os * exe_name; + + /* Determine options */ +#ifdef DEBUG + caml_verb_gc = 0x3F; +#endif + caml_parse_ocamlrunparam(); +#ifdef DEBUG + caml_gc_message (-1, "### OCaml runtime: debug mode ###\n"); +#endif + if (caml_cleanup_on_exit) + pooling = 1; + if (!caml_startup_aux(pooling)) + return Val_unit; + + caml_init_ieee_floats(); + caml_init_locale(); +#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L + caml_install_invalid_parameter_handler(); +#endif + caml_init_custom_operations(); + cds_file = caml_secure_getenv(_T("CAML_DEBUG_FILE")); + if (cds_file != NULL) { + caml_cds_file = caml_stat_strdup_os(cds_file); + } + exe_name = caml_executable_name(); + if (exe_name == NULL) exe_name = caml_search_exe_in_path(argv[0]); + caml_external_raise = NULL; + /* Initialize the abstract machine */ + caml_init_gc (caml_init_minor_heap_wsz, caml_init_heap_wsz, + caml_init_heap_chunk_sz, caml_init_percent_free, + caml_init_max_percent_free, caml_init_major_window, + caml_init_custom_major_ratio, caml_init_custom_minor_ratio, + caml_init_custom_minor_max_bsz); + caml_init_stack (caml_init_max_stack_wsz); + caml_init_atom_table(); + caml_init_backtrace(); + /* Initialize the interpreter */ + caml_interprete(NULL, 0); + /* Initialize the debugger, if needed */ + caml_debugger_init(); + /* Load the code */ + caml_start_code = code; + caml_code_size = code_size; + caml_init_code_fragments(); + caml_init_debug_info(); + if (caml_debugger_in_use) { + uintnat len, i; + len = code_size / sizeof(opcode_t); + caml_saved_code = (unsigned char *) caml_stat_alloc(len); + for (i = 0; i < len; i++) caml_saved_code[i] = caml_start_code[i]; + } +#ifdef THREADED_CODE + caml_thread_code(caml_start_code, code_size); +#endif + /* Use the builtin table of primitives */ + caml_build_primitive_table_builtin(); + /* Load the globals */ + caml_global_data = caml_input_value_from_block(data, data_size); + /* Ensure that the globals are in the major heap. */ + caml_oldify_one (caml_global_data, &caml_global_data); + caml_oldify_mopup (); + /* Record the sections (for caml_get_section_table in meta.c) */ + caml_section_table = section_table; + caml_section_table_size = section_table_size; + /* Initialize system libraries */ + caml_sys_init(exe_name, argv); + /* Execute the program */ + caml_debugger(PROGRAM_START); + return caml_interprete(caml_start_code, caml_code_size); +} + +CAMLexport void caml_startup_code( + code_t code, asize_t code_size, + char *data, asize_t data_size, + char *section_table, asize_t section_table_size, + int pooling, + char_os **argv) +{ + value res; + + res = caml_startup_code_exn(code, code_size, data, data_size, + section_table, section_table_size, + pooling, argv); + if (Is_exception_result(res)) { + caml_exn_bucket = Extract_exception(res); + if (caml_debugger_in_use) { + caml_extern_sp = &caml_exn_bucket; /* The debugger needs the + exception value.*/ + caml_debugger(UNCAUGHT_EXC); + } + caml_fatal_uncaught_exception(caml_exn_bucket); + } +} diff --git a/runtime/startup_nat.c b/runtime/startup_nat.c new file mode 100644 index 00000000..43b85e31 --- /dev/null +++ b/runtime/startup_nat.c @@ -0,0 +1,190 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Start-up code */ + +#include +#include +#include "caml/callback.h" +#include "caml/backtrace.h" +#include "caml/custom.h" +#include "caml/debugger.h" +#include "caml/fail.h" +#include "caml/freelist.h" +#include "caml/gc.h" +#include "caml/gc_ctrl.h" +#include "caml/intext.h" +#include "caml/memory.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/osdeps.h" +#include "caml/printexc.h" +#include "caml/stack.h" +#include "caml/startup_aux.h" +#include "caml/sys.h" +#ifdef WITH_SPACETIME +#include "caml/spacetime.h" +#endif +#ifdef HAS_UI +#include "caml/ui.h" +#endif + +extern int caml_parser_trace; +CAMLexport header_t caml_atom_table[256]; +char * caml_code_area_start, * caml_code_area_end; +struct ext_table caml_code_fragments_table; + +/* Initialize the atom table and the static data and code area limits. */ + +struct segment { char * begin; char * end; }; + +static void init_static(void) +{ + extern struct segment caml_data_segments[], caml_code_segments[]; + int i; + struct code_fragment * cf; + + caml_init_atom_table (); + + for (i = 0; caml_data_segments[i].begin != 0; i++) { + /* PR#5509: we must include the zero word at end of data segment, + because pointers equal to caml_data_segments[i].end are static data. */ + if (caml_page_table_add(In_static_data, + caml_data_segments[i].begin, + caml_data_segments[i].end + sizeof(value)) != 0) + caml_fatal_error("not enough memory for initial page table"); + } + + caml_code_area_start = caml_code_segments[0].begin; + caml_code_area_end = caml_code_segments[0].end; + for (i = 1; caml_code_segments[i].begin != 0; i++) { + if (caml_code_segments[i].begin < caml_code_area_start) + caml_code_area_start = caml_code_segments[i].begin; + if (caml_code_segments[i].end > caml_code_area_end) + caml_code_area_end = caml_code_segments[i].end; + } + /* Register the code in the table of code fragments */ + cf = caml_stat_alloc(sizeof(struct code_fragment)); + cf->code_start = caml_code_area_start; + cf->code_end = caml_code_area_end; + cf->digest_computed = 0; + caml_ext_table_init(&caml_code_fragments_table, 8); + caml_ext_table_add(&caml_code_fragments_table, cf); +} + +/* These are termination hooks used by the systhreads library */ +struct longjmp_buffer caml_termination_jmpbuf; +void (*caml_termination_hook)(void *) = NULL; + +extern value caml_start_program (void); +extern void caml_init_ieee_floats (void); +extern void caml_init_signals (void); +#ifdef _WIN32 +extern void caml_win32_overflow_detection (void); +#endif + +#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L + +/* PR 4887: avoid crash box of windows runtime on some system calls */ +extern void caml_install_invalid_parameter_handler(); + +#endif + +value caml_startup_common(char_os **argv, int pooling) +{ + char_os * exe_name, * proc_self_exe; + char tos; + + /* Determine options */ +#ifdef DEBUG + caml_verb_gc = 0x3F; +#endif + caml_parse_ocamlrunparam(); +#ifdef DEBUG + caml_gc_message (-1, "### OCaml runtime: debug mode ###\n"); +#endif + if (caml_cleanup_on_exit) + pooling = 1; + if (!caml_startup_aux(pooling)) + return Val_unit; + +#ifdef WITH_SPACETIME + caml_spacetime_initialize(); +#endif + caml_init_frame_descriptors(); + caml_init_ieee_floats(); + caml_init_locale(); +#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L + caml_install_invalid_parameter_handler(); +#endif + caml_init_custom_operations(); + caml_top_of_stack = &tos; + caml_init_gc (caml_init_minor_heap_wsz, caml_init_heap_wsz, + caml_init_heap_chunk_sz, caml_init_percent_free, + caml_init_max_percent_free, caml_init_major_window, + caml_init_custom_major_ratio, caml_init_custom_minor_ratio, + caml_init_custom_minor_max_bsz); + init_static(); + caml_init_signals(); +#ifdef _WIN32 + caml_win32_overflow_detection(); +#endif + caml_init_backtrace(); + caml_debugger_init (); /* force debugger.o stub to be linked */ + exe_name = argv[0]; + if (exe_name == NULL) exe_name = _T(""); + proc_self_exe = caml_executable_name(); + if (proc_self_exe != NULL) + exe_name = proc_self_exe; + else + exe_name = caml_search_exe_in_path(exe_name); + caml_sys_init(exe_name, argv); + if (sigsetjmp(caml_termination_jmpbuf.buf, 0)) { + if (caml_termination_hook != NULL) caml_termination_hook(NULL); + return Val_unit; + } + return caml_start_program(); +} + +value caml_startup_exn(char_os **argv) +{ + return caml_startup_common(argv, /* pooling */ 0); +} + +void caml_startup(char_os **argv) +{ + value res = caml_startup_exn(argv); + if (Is_exception_result(res)) + caml_fatal_uncaught_exception(Extract_exception(res)); +} + +void caml_main(char_os **argv) +{ + caml_startup(argv); +} + +value caml_startup_pooled_exn(char_os **argv) +{ + return caml_startup_common(argv, /* pooling */ 1); +} + +void caml_startup_pooled(char_os **argv) +{ + value res = caml_startup_pooled_exn(argv); + if (Is_exception_result(res)) + caml_fatal_uncaught_exception(Extract_exception(res)); +} diff --git a/runtime/str.c b/runtime/str.c new file mode 100644 index 00000000..80efcc8a --- /dev/null +++ b/runtime/str.c @@ -0,0 +1,474 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Operations on strings */ + +#include +#include +#include +#include +#include "caml/alloc.h" +#include "caml/fail.h" +#include "caml/memory.h" +#include "caml/mlvalues.h" +#include "caml/misc.h" + +/* returns a number of bytes (chars) */ +CAMLexport mlsize_t caml_string_length(value s) +{ + mlsize_t temp; + temp = Bosize_val(s) - 1; + CAMLassert (Byte (s, temp - Byte (s, temp)) == 0); + return temp - Byte (s, temp); +} + +/* returns a value that represents a number of bytes (chars) */ +CAMLprim value caml_ml_string_length(value s) +{ + mlsize_t temp; + temp = Bosize_val(s) - 1; + CAMLassert (Byte (s, temp - Byte (s, temp)) == 0); + return Val_long(temp - Byte (s, temp)); +} + +CAMLprim value caml_ml_bytes_length(value s) +{ + return caml_ml_string_length(s); +} + +CAMLexport int caml_string_is_c_safe (value s) +{ + return strlen(String_val(s)) == caml_string_length(s); +} + +/** + * [caml_create_string] is deprecated, + * use [caml_create_bytes] instead + */ +CAMLprim value caml_create_string(value len) +{ + mlsize_t size = Long_val(len); + if (size > Bsize_wsize (Max_wosize) - 1){ + caml_invalid_argument("String.create"); + } + return caml_alloc_string(size); +} + +/* [len] is a value that represents a number of bytes (chars) */ +CAMLprim value caml_create_bytes(value len) +{ + mlsize_t size = Long_val(len); + if (size > Bsize_wsize (Max_wosize) - 1){ + caml_invalid_argument("Bytes.create"); + } + return caml_alloc_string(size); +} + + + +CAMLprim value caml_string_get(value str, value index) +{ + intnat idx = Long_val(index); + if (idx < 0 || idx >= caml_string_length(str)) caml_array_bound_error(); + return Val_int(Byte_u(str, idx)); +} + +CAMLprim value caml_bytes_get(value str, value index) +{ + return caml_string_get(str, index); +} + +CAMLprim value caml_bytes_set(value str, value index, value newval) +{ + intnat idx = Long_val(index); + if (idx < 0 || idx >= caml_string_length(str)) caml_array_bound_error(); + Byte_u(str, idx) = Int_val(newval); + return Val_unit; +} + +/** + * [caml_string_set] is deprecated, + * use [caml_bytes_set] instead + */ +CAMLprim value caml_string_set(value str, value index, value newval) +{ + return caml_bytes_set(str,index,newval); +} + + +CAMLprim value caml_string_get16(value str, value index) +{ + intnat res; + unsigned char b1, b2; + intnat idx = Long_val(index); + if (idx < 0 || idx + 1 >= caml_string_length(str)) caml_array_bound_error(); + b1 = Byte_u(str, idx); + b2 = Byte_u(str, idx + 1); +#ifdef ARCH_BIG_ENDIAN + res = b1 << 8 | b2; +#else + res = b2 << 8 | b1; +#endif + return Val_int(res); +} + +CAMLprim value caml_bytes_get16(value str, value index) +{ + return caml_string_get16(str,index); +} + +CAMLprim value caml_string_get32(value str, value index) +{ + int32_t res; + unsigned char b1, b2, b3, b4; + intnat idx = Long_val(index); + if (idx < 0 || idx + 3 >= caml_string_length(str)) caml_array_bound_error(); + b1 = Byte_u(str, idx); + b2 = Byte_u(str, idx + 1); + b3 = Byte_u(str, idx + 2); + b4 = Byte_u(str, idx + 3); +#ifdef ARCH_BIG_ENDIAN + res = b1 << 24 | b2 << 16 | b3 << 8 | b4; +#else + res = b4 << 24 | b3 << 16 | b2 << 8 | b1; +#endif + return caml_copy_int32(res); +} + +CAMLprim value caml_bytes_get32(value str, value index) +{ + return caml_string_get32(str,index); +} + +CAMLprim value caml_string_get64(value str, value index) +{ + uint64_t res; + unsigned char b1, b2, b3, b4, b5, b6, b7, b8; + intnat idx = Long_val(index); + if (idx < 0 || idx + 7 >= caml_string_length(str)) caml_array_bound_error(); + b1 = Byte_u(str, idx); + b2 = Byte_u(str, idx + 1); + b3 = Byte_u(str, idx + 2); + b4 = Byte_u(str, idx + 3); + b5 = Byte_u(str, idx + 4); + b6 = Byte_u(str, idx + 5); + b7 = Byte_u(str, idx + 6); + b8 = Byte_u(str, idx + 7); +#ifdef ARCH_BIG_ENDIAN + res = (uint64_t) b1 << 56 | (uint64_t) b2 << 48 + | (uint64_t) b3 << 40 | (uint64_t) b4 << 32 + | (uint64_t) b5 << 24 | (uint64_t) b6 << 16 + | (uint64_t) b7 << 8 | (uint64_t) b8; +#else + res = (uint64_t) b8 << 56 | (uint64_t) b7 << 48 + | (uint64_t) b6 << 40 | (uint64_t) b5 << 32 + | (uint64_t) b4 << 24 | (uint64_t) b3 << 16 + | (uint64_t) b2 << 8 | (uint64_t) b1; +#endif + return caml_copy_int64(res); +} + +CAMLprim value caml_bytes_get64(value str, value index) +{ + return caml_string_get64(str,index); +} + +CAMLprim value caml_bytes_set16(value str, value index, value newval) +{ + unsigned char b1, b2; + intnat val; + intnat idx = Long_val(index); + if (idx < 0 || idx + 1 >= caml_string_length(str)) caml_array_bound_error(); + val = Long_val(newval); +#ifdef ARCH_BIG_ENDIAN + b1 = 0xFF & val >> 8; + b2 = 0xFF & val; +#else + b2 = 0xFF & val >> 8; + b1 = 0xFF & val; +#endif + Byte_u(str, idx) = b1; + Byte_u(str, idx + 1) = b2; + return Val_unit; +} + +CAMLprim value caml_bytes_set32(value str, value index, value newval) +{ + unsigned char b1, b2, b3, b4; + intnat val; + intnat idx = Long_val(index); + if (idx < 0 || idx + 3 >= caml_string_length(str)) caml_array_bound_error(); + val = Int32_val(newval); +#ifdef ARCH_BIG_ENDIAN + b1 = 0xFF & val >> 24; + b2 = 0xFF & val >> 16; + b3 = 0xFF & val >> 8; + b4 = 0xFF & val; +#else + b4 = 0xFF & val >> 24; + b3 = 0xFF & val >> 16; + b2 = 0xFF & val >> 8; + b1 = 0xFF & val; +#endif + Byte_u(str, idx) = b1; + Byte_u(str, idx + 1) = b2; + Byte_u(str, idx + 2) = b3; + Byte_u(str, idx + 3) = b4; + return Val_unit; +} + +CAMLprim value caml_bytes_set64(value str, value index, value newval) +{ + unsigned char b1, b2, b3, b4, b5, b6, b7, b8; + int64_t val; + intnat idx = Long_val(index); + if (idx < 0 || idx + 7 >= caml_string_length(str)) caml_array_bound_error(); + val = Int64_val(newval); +#ifdef ARCH_BIG_ENDIAN + b1 = 0xFF & val >> 56; + b2 = 0xFF & val >> 48; + b3 = 0xFF & val >> 40; + b4 = 0xFF & val >> 32; + b5 = 0xFF & val >> 24; + b6 = 0xFF & val >> 16; + b7 = 0xFF & val >> 8; + b8 = 0xFF & val; +#else + b8 = 0xFF & val >> 56; + b7 = 0xFF & val >> 48; + b6 = 0xFF & val >> 40; + b5 = 0xFF & val >> 32; + b4 = 0xFF & val >> 24; + b3 = 0xFF & val >> 16; + b2 = 0xFF & val >> 8; + b1 = 0xFF & val; +#endif + Byte_u(str, idx) = b1; + Byte_u(str, idx + 1) = b2; + Byte_u(str, idx + 2) = b3; + Byte_u(str, idx + 3) = b4; + Byte_u(str, idx + 4) = b5; + Byte_u(str, idx + 5) = b6; + Byte_u(str, idx + 6) = b7; + Byte_u(str, idx + 7) = b8; + return Val_unit; +} + +CAMLprim value caml_string_equal(value s1, value s2) +{ + mlsize_t sz1, sz2; + value * p1, * p2; + + if (s1 == s2) return Val_true; + sz1 = Wosize_val(s1); + sz2 = Wosize_val(s2); + if (sz1 != sz2) return Val_false; + for(p1 = Op_val(s1), p2 = Op_val(s2); sz1 > 0; sz1--, p1++, p2++) + if (*p1 != *p2) return Val_false; + return Val_true; +} + +CAMLprim value caml_bytes_equal(value s1, value s2) +{ + return caml_string_equal(s1,s2); +} + +CAMLprim value caml_string_notequal(value s1, value s2) +{ + return Val_not(caml_string_equal(s1, s2)); +} + +CAMLprim value caml_bytes_notequal(value s1, value s2) +{ + return caml_string_notequal(s1,s2); +} + +CAMLprim value caml_string_compare(value s1, value s2) +{ + mlsize_t len1, len2; + int res; + + if (s1 == s2) return Val_int(0); + len1 = caml_string_length(s1); + len2 = caml_string_length(s2); + res = memcmp(String_val(s1), String_val(s2), len1 <= len2 ? len1 : len2); + if (res < 0) return Val_int(-1); + if (res > 0) return Val_int(1); + if (len1 < len2) return Val_int(-1); + if (len1 > len2) return Val_int(1); + return Val_int(0); +} + +CAMLprim value caml_bytes_compare(value s1, value s2) +{ + return caml_string_compare(s1,s2); +} + +CAMLprim value caml_string_lessthan(value s1, value s2) +{ + return caml_string_compare(s1, s2) < Val_int(0) ? Val_true : Val_false; +} + +CAMLprim value caml_bytes_lessthan(value s1, value s2) +{ + return caml_string_lessthan(s1,s2); +} + + +CAMLprim value caml_string_lessequal(value s1, value s2) +{ + return caml_string_compare(s1, s2) <= Val_int(0) ? Val_true : Val_false; +} + +CAMLprim value caml_bytes_lessequal(value s1, value s2) +{ + return caml_string_lessequal(s1,s2); +} + + +CAMLprim value caml_string_greaterthan(value s1, value s2) +{ + return caml_string_compare(s1, s2) > Val_int(0) ? Val_true : Val_false; +} + +CAMLprim value caml_bytes_greaterthan(value s1, value s2) +{ + return caml_string_greaterthan(s1,s2); +} + +CAMLprim value caml_string_greaterequal(value s1, value s2) +{ + return caml_string_compare(s1, s2) >= Val_int(0) ? Val_true : Val_false; +} + +CAMLprim value caml_bytes_greaterequal(value s1, value s2) +{ + return caml_string_greaterequal(s1,s2); +} + +CAMLprim value caml_blit_bytes(value s1, value ofs1, value s2, value ofs2, + value n) +{ + memmove(&Byte(s2, Long_val(ofs2)), &Byte(s1, Long_val(ofs1)), Long_val(n)); + return Val_unit; +} + +CAMLprim value caml_blit_string(value s1, value ofs1, value s2, value ofs2, + value n) +{ + return caml_blit_bytes (s1, ofs1, s2, ofs2, n); +} + +CAMLprim value caml_fill_bytes(value s, value offset, value len, value init) +{ + memset(&Byte(s, Long_val(offset)), Int_val(init), Long_val(len)); + return Val_unit; +} + +/** + * [caml_fill_string] is deprecated, use [caml_fill_bytes] instead + */ +CAMLprim value caml_fill_string(value s, value offset, value len, value init) +{ + return caml_fill_bytes (s, offset, len, init); +} + +CAMLexport value caml_alloc_sprintf(const char * format, ...) +{ + va_list args; + char buf[128]; + int n; + value res; + +#if !defined(_WIN32) || defined(_UCRT) + /* C99-compliant implementation */ + va_start(args, format); + /* "vsnprintf(dest, sz, format, args)" writes at most "sz" characters + into "dest", including the terminating '\0'. + It returns the number of characters of the formatted string, + excluding the terminating '\0'. */ + n = vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + if (n < sizeof(buf)) { + /* All output characters were written to buf, including the + terminating '\0'. Allocate a Caml string with length "n" + as computed by vsnprintf, and copy the output of vsnprintf into it. */ + res = caml_alloc_initialized_string(n, buf); + } else { + /* PR#7568: if the format is in the Caml heap, the following + caml_alloc_string could move or free the format. To prevent + this, take a copy of the format outside the Caml heap. */ + char * saved_format = caml_stat_strdup(format); + /* Allocate a Caml string with length "n" as computed by vsnprintf. */ + res = caml_alloc_string(n); + /* Re-do the formatting, outputting directly in the Caml string. + Note that caml_alloc_string left room for a '\0' at position n, + so the size passed to vsnprintf is n+1. */ + va_start(args, format); + vsnprintf((char *)String_val(res), n + 1, saved_format, args); + va_end(args); + caml_stat_free(saved_format); + } + return res; +#else + /* Implementation specific to the Microsoft CRT library */ + va_start(args, format); + /* "_vsnprintf(dest, sz, format, args)" writes at most "sz" characters + into "dest". Let "len" be the number of characters of the formatted + string. + If "len" < "sz", a null terminator was appended, and "len" is returned. + If "len" == "sz", no null termination, and "len" is returned. + If "len" > "sz", a negative value is returned. */ + n = _vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + if (n >= 0 && n <= sizeof(buf)) { + /* All output characters were written to buf. + "n" is the actual length of the output. + Allocate a Caml string of length "n" and copy the characters into it. */ + res = caml_alloc_string(n); + memcpy(String_val(res), buf, n); + } else { + /* PR#7568: if the format is in the Caml heap, the following + caml_alloc_string could move or free the format. To prevent + this, take a copy of the format outside the Caml heap. */ + char * saved_format = caml_stat_strdup(format); + /* Determine actual length of output, excluding final '\0' */ + va_start(args, format); + n = _vscprintf(format, args); + va_end(args); + res = caml_alloc_string(n); + /* Re-do the formatting, outputting directly in the Caml string. + Note that caml_alloc_string left room for a '\0' at position n, + so the size passed to _vsnprintf is n+1. */ + va_start(args, format); + _vsnprintf(String_val(res), n + 1, saved_format, args); + va_end(args); + caml_stat_free(saved_format); + } + return res; +#endif +} + +CAMLprim value caml_string_of_bytes(value bv) +{ + return bv; +} + +CAMLprim value caml_bytes_of_string(value bv) +{ + return bv; +} diff --git a/runtime/sys.c b/runtime/sys.c new file mode 100644 index 00000000..c019ee9f --- /dev/null +++ b/runtime/sys.c @@ -0,0 +1,644 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Basic system calls */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +#include /* for _wchdir and _wgetcwd */ +#else +#include +#endif +#include "caml/config.h" +#ifdef HAS_UNISTD +#include +#endif +#ifdef HAS_TIMES +#include +#endif +#ifdef HAS_GETRUSAGE +#include +#include +#endif +#ifdef HAS_GETTIMEOFDAY +#include +#endif +#include "caml/alloc.h" +#include "caml/debugger.h" +#include "caml/fail.h" +#include "caml/gc_ctrl.h" +#include "caml/io.h" +#include "caml/misc.h" +#include "caml/mlvalues.h" +#include "caml/osdeps.h" +#include "caml/signals.h" +#include "caml/stacks.h" +#include "caml/sys.h" +#include "caml/version.h" +#include "caml/callback.h" +#include "caml/startup_aux.h" + +static char * error_message(void) +{ + return strerror(errno); +} + +#ifndef EAGAIN +#define EAGAIN (-1) +#endif +#ifndef EWOULDBLOCK +#define EWOULDBLOCK (-1) +#endif + +CAMLexport void caml_sys_error(value arg) +{ + CAMLparam1 (arg); + char * err; + CAMLlocal1 (str); + + err = error_message(); + if (arg == NO_ARG) { + str = caml_copy_string(err); + } else { + mlsize_t err_len = strlen(err); + mlsize_t arg_len = caml_string_length(arg); + str = caml_alloc_string(arg_len + 2 + err_len); + memmove(&Byte(str, 0), String_val(arg), arg_len); + memmove(&Byte(str, arg_len), ": ", 2); + memmove(&Byte(str, arg_len + 2), err, err_len); + } + caml_raise_sys_error(str); + CAMLnoreturn; +} + +CAMLexport void caml_sys_io_error(value arg) +{ + if (errno == EAGAIN || errno == EWOULDBLOCK) { + caml_raise_sys_blocked_io(); + } else { + caml_sys_error(arg); + } +} + +/* Check that [name] can safely be used as a file path */ + +static void caml_sys_check_path(value name) +{ + if (! caml_string_is_c_safe(name)) { + errno = ENOENT; + caml_sys_error(name); + } +} + +CAMLprim value caml_sys_exit(value retcode_v) +{ + int retcode = Int_val(retcode_v); + + if ((caml_verb_gc & 0x400) != 0) { + /* cf caml_gc_counters */ + double minwords = caml_stat_minor_words + + (double) (caml_young_end - caml_young_ptr); + double prowords = caml_stat_promoted_words; + double majwords = caml_stat_major_words + (double) caml_allocated_words; + double allocated_words = minwords + majwords - prowords; + intnat mincoll = caml_stat_minor_collections; + intnat majcoll = caml_stat_major_collections; + intnat heap_words = caml_stat_heap_wsz; + intnat heap_chunks = caml_stat_heap_chunks; + intnat top_heap_words = caml_stat_top_heap_wsz; + intnat cpct = caml_stat_compactions; + caml_gc_message(0x400, "allocated_words: %.0f\n", allocated_words); + caml_gc_message(0x400, "minor_words: %.0f\n", minwords); + caml_gc_message(0x400, "promoted_words: %.0f\n", prowords); + caml_gc_message(0x400, "major_words: %.0f\n", majwords); + caml_gc_message(0x400, "minor_collections: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", + mincoll); + caml_gc_message(0x400, "major_collections: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", + majcoll); + caml_gc_message(0x400, "heap_words: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", + heap_words); + caml_gc_message(0x400, "heap_chunks: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", + heap_chunks); + caml_gc_message(0x400, "top_heap_words: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", + top_heap_words); + caml_gc_message(0x400, "compactions: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", + cpct); + } + +#ifndef NATIVE_CODE + caml_debugger(PROGRAM_EXIT); +#endif + caml_instr_atexit (); + if (caml_cleanup_on_exit) + caml_shutdown(); +#ifdef _WIN32 + caml_restore_win32_terminal(); +#endif + exit(retcode); +} + +#ifndef O_BINARY +#define O_BINARY 0 +#endif +#ifndef O_TEXT +#define O_TEXT 0 +#endif +#ifndef O_NONBLOCK +#ifdef O_NDELAY +#define O_NONBLOCK O_NDELAY +#else +#define O_NONBLOCK 0 +#endif +#endif + +static int sys_open_flags[] = { + O_RDONLY, O_WRONLY, O_APPEND | O_WRONLY, O_CREAT, O_TRUNC, O_EXCL, + O_BINARY, O_TEXT, O_NONBLOCK +}; + +CAMLprim value caml_sys_open(value path, value vflags, value vperm) +{ + CAMLparam3(path, vflags, vperm); + int fd, flags, perm; + char_os * p; + +#if defined(O_CLOEXEC) + flags = O_CLOEXEC; +#elif defined(_WIN32) + flags = _O_NOINHERIT; +#else + flags = 0; +#endif + + caml_sys_check_path(path); + p = caml_stat_strdup_to_os(String_val(path)); + flags |= caml_convert_flag_list(vflags, sys_open_flags); + perm = Int_val(vperm); + /* open on a named FIFO can block (PR#1533) */ + caml_enter_blocking_section(); + fd = open_os(p, flags, perm); + /* fcntl on a fd can block (PR#5069)*/ +#if defined(F_SETFD) && defined(FD_CLOEXEC) && !defined(_WIN32) \ + && !defined(O_CLOEXEC) + if (fd != -1) + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif + caml_leave_blocking_section(); + caml_stat_free(p); + if (fd == -1) caml_sys_error(path); + CAMLreturn(Val_long(fd)); +} + +CAMLprim value caml_sys_close(value fd_v) +{ + int fd = Int_val(fd_v); + caml_enter_blocking_section(); + close(fd); + caml_leave_blocking_section(); + return Val_unit; +} + +CAMLprim value caml_sys_file_exists(value name) +{ +#ifdef _WIN32 + struct _stati64 st; +#else + struct stat st; +#endif + char_os * p; + int ret; + + if (! caml_string_is_c_safe(name)) return Val_false; + p = caml_stat_strdup_to_os(String_val(name)); + caml_enter_blocking_section(); + ret = stat_os(p, &st); + caml_leave_blocking_section(); + caml_stat_free(p); + + return Val_bool(ret == 0); +} + +CAMLprim value caml_sys_is_directory(value name) +{ + CAMLparam1(name); +#ifdef _WIN32 + struct _stati64 st; +#else + struct stat st; +#endif + char_os * p; + int ret; + + caml_sys_check_path(name); + p = caml_stat_strdup_to_os(String_val(name)); + caml_enter_blocking_section(); + ret = stat_os(p, &st); + caml_leave_blocking_section(); + caml_stat_free(p); + + if (ret == -1) caml_sys_error(name); +#ifdef S_ISDIR + CAMLreturn(Val_bool(S_ISDIR(st.st_mode))); +#else + CAMLreturn(Val_bool(st.st_mode & S_IFDIR)); +#endif +} + +CAMLprim value caml_sys_remove(value name) +{ + CAMLparam1(name); + char_os * p; + int ret; + caml_sys_check_path(name); + p = caml_stat_strdup_to_os(String_val(name)); + caml_enter_blocking_section(); + ret = unlink_os(p); + caml_leave_blocking_section(); + caml_stat_free(p); + if (ret != 0) caml_sys_error(name); + CAMLreturn(Val_unit); +} + +CAMLprim value caml_sys_rename(value oldname, value newname) +{ + char_os * p_old; + char_os * p_new; + int ret; + caml_sys_check_path(oldname); + caml_sys_check_path(newname); + p_old = caml_stat_strdup_to_os(String_val(oldname)); + p_new = caml_stat_strdup_to_os(String_val(newname)); + caml_enter_blocking_section(); + ret = rename_os(p_old, p_new); + caml_leave_blocking_section(); + caml_stat_free(p_new); + caml_stat_free(p_old); + if (ret != 0) + caml_sys_error(NO_ARG); + return Val_unit; +} + +CAMLprim value caml_sys_chdir(value dirname) +{ + CAMLparam1(dirname); + char_os * p; + int ret; + caml_sys_check_path(dirname); + p = caml_stat_strdup_to_os(String_val(dirname)); + caml_enter_blocking_section(); + ret = chdir_os(p); + caml_leave_blocking_section(); + caml_stat_free(p); + if (ret != 0) caml_sys_error(dirname); + CAMLreturn(Val_unit); +} + +CAMLprim value caml_sys_getcwd(value unit) +{ + char_os buff[4096]; + char_os * ret; +#ifdef HAS_GETCWD + ret = getcwd_os(buff, sizeof(buff)/sizeof(*buff)); +#else + caml_invalid_argument("Sys.getcwd not implemented"); +#endif /* HAS_GETCWD */ + if (ret == 0) caml_sys_error(NO_ARG); + return caml_copy_string_of_os(buff); +} + +CAMLprim value caml_sys_unsafe_getenv(value var) +{ + char_os * res, * p; + value val; + + if (! caml_string_is_c_safe(var)) caml_raise_not_found(); + p = caml_stat_strdup_to_os(String_val(var)); +#ifdef _WIN32 + res = caml_win32_getenv(p); +#else + res = getenv(p); +#endif + caml_stat_free(p); + if (res == 0) caml_raise_not_found(); + val = caml_copy_string_of_os(res); +#ifdef _WIN32 + caml_stat_free(res); +#endif + return val; +} + +CAMLprim value caml_sys_getenv(value var) +{ + char_os * res, * p; + value val; + + if (! caml_string_is_c_safe(var)) caml_raise_not_found(); + p = caml_stat_strdup_to_os(String_val(var)); +#ifdef _WIN32 + res = caml_win32_getenv(p); +#else + res = caml_secure_getenv(p); +#endif + caml_stat_free(p); + if (res == 0) caml_raise_not_found(); + val = caml_copy_string_of_os(res); +#ifdef _WIN32 + caml_stat_free(res); +#endif + return val; +} + +char_os * caml_exe_name; +char_os ** caml_main_argv; + +CAMLprim value caml_sys_get_argv(value unit) +{ + CAMLparam0 (); /* unit is unused */ + CAMLlocal3 (exe_name, argv, res); + exe_name = caml_copy_string_of_os(caml_exe_name); + argv = + caml_alloc_array((void *)caml_copy_string_of_os, + (char const **) caml_main_argv); + res = caml_alloc_small(2, 0); + Field(res, 0) = exe_name; + Field(res, 1) = argv; + CAMLreturn(res); +} + +void caml_sys_init(char_os * exe_name, char_os **argv) +{ +#ifdef _WIN32 + /* Initialises the caml_win32_* globals on Windows with the version of + Windows which is running */ + caml_probe_win32_version(); +#if WINDOWS_UNICODE + caml_setup_win32_terminal(); +#endif +#endif + caml_exe_name = exe_name; + caml_main_argv = argv; +} + +#ifdef _WIN32 +#define WIFEXITED(status) 1 +#define WEXITSTATUS(status) (status) +#else +#if !(defined(WIFEXITED) && defined(WEXITSTATUS)) +/* Assume old-style V7 status word */ +#define WIFEXITED(status) (((status) & 0xFF) == 0) +#define WEXITSTATUS(status) (((status) >> 8) & 0xFF) +#endif +#endif + +CAMLprim value caml_sys_system_command(value command) +{ + CAMLparam1 (command); + int status, retcode; + char_os *buf; + + if (! caml_string_is_c_safe (command)) { + errno = EINVAL; + caml_sys_error(command); + } + buf = caml_stat_strdup_to_os(String_val(command)); + caml_enter_blocking_section (); + status = system_os(buf); + caml_leave_blocking_section (); + caml_stat_free(buf); + if (status == -1) caml_sys_error(command); + if (WIFEXITED(status)) + retcode = WEXITSTATUS(status); + else + retcode = 255; + CAMLreturn (Val_int(retcode)); +} + +double caml_sys_time_include_children_unboxed(value include_children) +{ +#ifdef HAS_GETRUSAGE + struct rusage ru; + double acc = 0.; + + getrusage (RUSAGE_SELF, &ru); + acc += ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1e6 + + ru.ru_stime.tv_sec + ru.ru_stime.tv_usec / 1e6; + + if (Bool_val(include_children)) { + getrusage (RUSAGE_CHILDREN, &ru); + acc += ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1e6 + + ru.ru_stime.tv_sec + ru.ru_stime.tv_usec / 1e6; + } + + return acc; +#else + #ifdef HAS_TIMES + #ifndef CLK_TCK + #ifdef HZ + #define CLK_TCK HZ + #else + #define CLK_TCK 60 + #endif + #endif + struct tms t; + clock_t acc = 0; + times(&t); + acc += t.tms_utime + t.tms_stime; + if (Bool_val(include_children)) { + acc += t.tms_cutime + t.tms_cstime; + } + return (double)acc / CLK_TCK; + #else + /* clock() is standard ANSI C. We have no way of getting + subprocess times in this branch. */ + return (double)clock() / CLOCKS_PER_SEC; + #endif +#endif +} + +CAMLprim value caml_sys_time_include_children(value include_children) +{ + return caml_copy_double( + caml_sys_time_include_children_unboxed(include_children)); +} + +double caml_sys_time_unboxed(value unit) { + return caml_sys_time_include_children_unboxed(Val_false); +} + +CAMLprim value caml_sys_time(value unit) +{ + return caml_copy_double(caml_sys_time_unboxed(unit)); +} + +#ifdef _WIN32 +extern int caml_win32_random_seed (intnat data[16]); +#endif + +CAMLprim value caml_sys_random_seed (value unit) +{ + intnat data[16]; + int n, i; + value res; +#ifdef _WIN32 + n = caml_win32_random_seed(data); +#else + int fd; + n = 0; + /* Try /dev/urandom first */ + fd = open("/dev/urandom", O_RDONLY, 0); + if (fd != -1) { + unsigned char buffer[12]; + int nread = read(fd, buffer, 12); + close(fd); + while (nread > 0) data[n++] = buffer[--nread]; + } + /* If the read from /dev/urandom fully succeeded, we now have 96 bits + of good random data and can stop here. Otherwise, complement + whatever we got (probably nothing) with some not-very-random data. */ + if (n < 12) { +#ifdef HAS_GETTIMEOFDAY + struct timeval tv; + gettimeofday(&tv, NULL); + data[n++] = tv.tv_usec; + data[n++] = tv.tv_sec; +#else + data[n++] = time(NULL); +#endif +#ifdef HAS_UNISTD + data[n++] = getpid(); + data[n++] = getppid(); +#endif + } +#endif + /* Convert to an OCaml array of ints */ + res = caml_alloc_small(n, 0); + for (i = 0; i < n; i++) Field(res, i) = Val_long(data[i]); + return res; +} + +CAMLprim value caml_sys_const_big_endian(value unit) +{ +#ifdef ARCH_BIG_ENDIAN + return Val_true; +#else + return Val_false; +#endif +} + +/* returns a value that represents a number of bits */ +CAMLprim value caml_sys_const_word_size(value unit) +{ + return Val_long(8 * sizeof(value)); +} + +/* returns a value that represents a number of bits */ +CAMLprim value caml_sys_const_int_size(value unit) +{ + return Val_long(8 * sizeof(value) - 1) ; +} + +/* returns a value that represents a number of words */ +CAMLprim value caml_sys_const_max_wosize(value unit) +{ + return Val_long(Max_wosize) ; +} + +CAMLprim value caml_sys_const_ostype_unix(value unit) +{ + return Val_bool(0 == strcmp(OCAML_OS_TYPE,"Unix")); +} + +CAMLprim value caml_sys_const_ostype_win32(value unit) +{ + return Val_bool(0 == strcmp(OCAML_OS_TYPE,"Win32")); +} + +CAMLprim value caml_sys_const_ostype_cygwin(value unit) +{ + return Val_bool(0 == strcmp(OCAML_OS_TYPE,"Cygwin")); +} + +CAMLprim value caml_sys_const_backend_type(value unit) +{ + return Val_int(1); /* Bytecode backed */ +} +CAMLprim value caml_sys_get_config(value unit) +{ + CAMLparam0 (); /* unit is unused */ + CAMLlocal2 (result, ostype); + + ostype = caml_copy_string(OCAML_OS_TYPE); + result = caml_alloc_small (3, 0); + Field(result, 0) = ostype; + Field(result, 1) = Val_long (8 * sizeof(value)); +#ifdef ARCH_BIG_ENDIAN + Field(result, 2) = Val_true; +#else + Field(result, 2) = Val_false; +#endif + CAMLreturn (result); +} + +CAMLprim value caml_sys_read_directory(value path) +{ + CAMLparam1(path); + CAMLlocal1(result); + struct ext_table tbl; + char_os * p; + int ret; + + caml_sys_check_path(path); + caml_ext_table_init(&tbl, 50); + p = caml_stat_strdup_to_os(String_val(path)); + caml_enter_blocking_section(); + ret = caml_read_directory(p, &tbl); + caml_leave_blocking_section(); + caml_stat_free(p); + if (ret == -1){ + caml_ext_table_free(&tbl, 1); + caml_sys_error(path); + } + caml_ext_table_add(&tbl, NULL); + result = caml_copy_string_array((char const **) tbl.contents); + caml_ext_table_free(&tbl, 1); + CAMLreturn(result); +} + +/* Return true if the value is a filedescriptor (int) that is + * (presumably) open on an interactive terminal */ +CAMLprim value caml_sys_isatty(value chan) +{ + int fd; + value ret; + + fd = (Channel(chan))->fd; +#ifdef _WIN32 + ret = Val_bool(caml_win32_isatty(fd)); +#else + ret = Val_bool(isatty(fd)); +#endif + + return ret; +} diff --git a/runtime/unix.c b/runtime/unix.c new file mode 100644 index 00000000..c0ddbaaa --- /dev/null +++ b/runtime/unix.c @@ -0,0 +1,442 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2001 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Unix-specific stuff */ + +#define _GNU_SOURCE + /* Helps finding RTLD_DEFAULT in glibc */ + /* also secure_getenv */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "caml/config.h" +#ifdef SUPPORT_DYNAMIC_LINKING +#ifdef __CYGWIN__ +#include "flexdll.h" +#else +#include +#endif +#endif +#ifdef HAS_UNISTD +#include +#endif +#ifdef HAS_DIRENT +#include +#else +#include +#endif +#ifdef __APPLE__ +#include +#endif +#include "caml/fail.h" +#include "caml/memory.h" +#include "caml/misc.h" +#include "caml/osdeps.h" +#include "caml/signals.h" +#include "caml/sys.h" +#include "caml/io.h" +#include "caml/alloc.h" + +#ifndef S_ISREG +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif + +#ifndef EINTR +#define EINTR (-1) +#endif +#ifndef EAGAIN +#define EAGAIN (-1) +#endif +#ifndef EWOULDBLOCK +#define EWOULDBLOCK (-1) +#endif + +int caml_read_fd(int fd, int flags, void * buf, int n) +{ + int retcode; + do { + caml_enter_blocking_section(); + retcode = read(fd, buf, n); + caml_leave_blocking_section(); + } while (retcode == -1 && errno == EINTR); + if (retcode == -1) caml_sys_io_error(NO_ARG); + return retcode; +} + +int caml_write_fd(int fd, int flags, void * buf, int n) +{ + int retcode; + again: +#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) + if (flags & CHANNEL_FLAG_BLOCKING_WRITE) { + retcode = write(fd, buf, n); + } else { +#endif + caml_enter_blocking_section(); + retcode = write(fd, buf, n); + caml_leave_blocking_section(); +#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) + } +#endif + if (retcode == -1) { + if (errno == EINTR) goto again; + if ((errno == EAGAIN || errno == EWOULDBLOCK) && n > 1) { + /* We couldn't do a partial write here, probably because + n <= PIPE_BUF and POSIX says that writes of less than + PIPE_BUF characters must be atomic. + We first try again with a partial write of 1 character. + If that fails too, we'll return an error code. */ + n = 1; goto again; + } + } + if (retcode == -1) caml_sys_io_error(NO_ARG); + CAMLassert (retcode > 0); + return retcode; +} + +caml_stat_string caml_decompose_path(struct ext_table * tbl, char * path) +{ + char * p, * q; + size_t n; + + if (path == NULL) return NULL; + p = caml_stat_strdup(path); + q = p; + while (1) { + for (n = 0; q[n] != 0 && q[n] != ':'; n++) /*nothing*/; + caml_ext_table_add(tbl, q); + q = q + n; + if (*q == 0) break; + *q = 0; + q += 1; + } + return p; +} + +caml_stat_string caml_search_in_path(struct ext_table * path, const char * name) +{ + const char * p; + char * dir, * fullname; + int i; + struct stat st; + + for (p = name; *p != 0; p++) { + if (*p == '/') goto not_found; + } + for (i = 0; i < path->size; i++) { + dir = path->contents[i]; + if (dir[0] == 0) dir = "."; /* empty path component = current dir */ + fullname = caml_stat_strconcat(3, dir, "/", name); + if (stat(fullname, &st) == 0 && S_ISREG(st.st_mode)) + return fullname; + caml_stat_free(fullname); + } + not_found: + return caml_stat_strdup(name); +} + +#ifdef __CYGWIN__ + +/* Cygwin needs special treatment because of the implicit ".exe" at the + end of executable file names */ + +static int cygwin_file_exists(const char * name) +{ + int fd, ret; + struct stat st; + /* Cannot use stat() here because it adds ".exe" implicitly */ + fd = open(name, O_RDONLY); + if (fd == -1) return 0; + ret = fstat(fd, &st); + close(fd); + return ret == 0 && S_ISREG(st.st_mode); +} + +static caml_stat_string cygwin_search_exe_in_path(struct ext_table * path, + const char * name) +{ + const char * p; + char * dir, * fullname; + int i; + + for (p = name; *p != 0; p++) { + if (*p == '/' || *p == '\\') goto not_found; + } + for (i = 0; i < path->size; i++) { + dir = path->contents[i]; + if (dir[0] == 0) dir = "."; /* empty path component = current dir */ + fullname = caml_stat_strconcat(3, dir, "/", name); + if (cygwin_file_exists(fullname)) return fullname; + caml_stat_free(fullname); + fullname = caml_stat_strconcat(4, dir, "/", name, ".exe"); + if (cygwin_file_exists(fullname)) return fullname; + caml_stat_free(fullname); + } + not_found: + if (cygwin_file_exists(name)) return caml_stat_strdup(name); + fullname = caml_stat_strconcat(2, name, ".exe"); + if (cygwin_file_exists(fullname)) return fullname; + caml_stat_free(fullname); + return caml_stat_strdup(name); +} + +#endif + +caml_stat_string caml_search_exe_in_path(const char * name) +{ + struct ext_table path; + char * tofree; + caml_stat_string res; + + caml_ext_table_init(&path, 8); + tofree = caml_decompose_path(&path, getenv("PATH")); +#ifndef __CYGWIN__ + res = caml_search_in_path(&path, name); +#else + res = cygwin_search_exe_in_path(&path, name); +#endif + caml_stat_free(tofree); + caml_ext_table_free(&path, 0); + return res; +} + +caml_stat_string caml_search_dll_in_path(struct ext_table * path, + const char * name) +{ + caml_stat_string dllname; + caml_stat_string res; + + dllname = caml_stat_strconcat(2, name, ".so"); + res = caml_search_in_path(path, dllname); + caml_stat_free(dllname); + return res; +} + +#ifdef SUPPORT_DYNAMIC_LINKING +#ifdef __CYGWIN__ +/* Use flexdll */ + +void * caml_dlopen(char * libname, int for_execution, int global) +{ + int flags = (global ? FLEXDLL_RTLD_GLOBAL : 0); + if (!for_execution) flags |= FLEXDLL_RTLD_NOEXEC; + return flexdll_dlopen(libname, flags); +} + +void caml_dlclose(void * handle) +{ + flexdll_dlclose(handle); +} + +void * caml_dlsym(void * handle, const char * name) +{ + return flexdll_dlsym(handle, name); +} + +void * caml_globalsym(const char * name) +{ + return flexdll_dlsym(flexdll_dlopen(NULL,0), name); +} + +char * caml_dlerror(void) +{ + return flexdll_dlerror(); +} + +#else +/* Use normal dlopen */ + +#ifndef RTLD_GLOBAL +#define RTLD_GLOBAL 0 +#endif +#ifndef RTLD_LOCAL +#define RTLD_LOCAL 0 +#endif + +void * caml_dlopen(char * libname, int for_execution, int global) +{ + return dlopen(libname, RTLD_NOW | (global ? RTLD_GLOBAL : RTLD_LOCAL)); + /* Could use RTLD_LAZY if for_execution == 0, but needs testing */ +} + +void caml_dlclose(void * handle) +{ + dlclose(handle); +} + +void * caml_dlsym(void * handle, const char * name) +{ + return dlsym(handle, name); +} + +void * caml_globalsym(const char * name) +{ +#ifdef RTLD_DEFAULT + return caml_dlsym(RTLD_DEFAULT, name); +#else + return NULL; +#endif +} + +char * caml_dlerror(void) +{ + return (char*) dlerror(); +} + +#endif +#else + +void * caml_dlopen(char * libname, int for_execution, int global) +{ + return NULL; +} + +void caml_dlclose(void * handle) +{ +} + +void * caml_dlsym(void * handle, const char * name) +{ + return NULL; +} + +void * caml_globalsym(const char * name) +{ + return NULL; +} + +char * caml_dlerror(void) +{ + return "dynamic loading not supported on this platform"; +} + +#endif + +/* Add to [contents] the (short) names of the files contained in + the directory named [dirname]. No entries are added for [.] and [..]. + Return 0 on success, -1 on error; set errno in the case of error. */ + +CAMLexport int caml_read_directory(char * dirname, struct ext_table * contents) +{ + DIR * d; +#ifdef HAS_DIRENT + struct dirent * e; +#else + struct direct * e; +#endif + + d = opendir(dirname); + if (d == NULL) return -1; + while (1) { + e = readdir(d); + if (e == NULL) break; + if (strcmp(e->d_name, ".") == 0 || strcmp(e->d_name, "..") == 0) continue; + caml_ext_table_add(contents, caml_stat_strdup(e->d_name)); + } + closedir(d); + return 0; +} + +/* Recover executable name from /proc/self/exe if possible */ + +char * caml_executable_name(void) +{ +#if defined(__linux__) + int namelen, retcode; + char * name; + struct stat st; + + /* lstat("/proc/self/exe") returns st_size == 0 so we cannot use it + to determine the size of the buffer. Instead, we guess and adjust. */ + namelen = 256; + while (1) { + name = caml_stat_alloc(namelen); + retcode = readlink("/proc/self/exe", name, namelen); + if (retcode == -1) { caml_stat_free(name); return NULL; } + if (retcode < namelen) break; + caml_stat_free(name); + if (namelen >= 1024*1024) return NULL; /* avoid runaway and overflow */ + namelen *= 2; + } + /* readlink() does not zero-terminate its result. + There is room for a final zero since retcode < namelen. */ + name[retcode] = 0; + /* Make sure that the contents of /proc/self/exe is a regular file. + (Old Linux kernels return an inode number instead.) */ + if (stat(name, &st) == -1 || ! S_ISREG(st.st_mode)) { + caml_stat_free(name); return NULL; + } + return name; + +#elif defined(__APPLE__) + unsigned int namelen; + char * name; + + namelen = 256; + name = caml_stat_alloc(namelen); + if (_NSGetExecutablePath(name, &namelen) == 0) return name; + caml_stat_free(name); + /* Buffer is too small, but namelen now contains the size needed */ + name = caml_stat_alloc(namelen); + if (_NSGetExecutablePath(name, &namelen) == 0) return name; + caml_stat_free(name); + return NULL; + +#else + return NULL; + +#endif +} + +char *caml_secure_getenv (char const *var) +{ +#ifdef HAS_SECURE_GETENV + return secure_getenv (var); +#elif defined (HAS___SECURE_GETENV) + return __secure_getenv (var); +#elif defined(HAS_ISSETUGID) + if (!issetugid ()) + return getenv(var); + else + return NULL; +#else + if (geteuid () == getuid () && getegid () == getgid ()) + return getenv(var); + else + return NULL; +#endif +} + +int caml_num_rows_fd(int fd) +{ +#ifdef TIOCGWINSZ + struct winsize w; + w.ws_row = -1; + if (ioctl(fd, TIOCGWINSZ, &w) == 0) + return w.ws_row; + else + return -1; +#else + return -1; +#endif +} diff --git a/runtime/weak.c b/runtime/weak.c new file mode 100644 index 00000000..a2df1c86 --- /dev/null +++ b/runtime/weak.c @@ -0,0 +1,574 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1997 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Operations on weak arrays and ephemerons (named ephe here)*/ + +#include + +#include "caml/alloc.h" +#include "caml/fail.h" +#include "caml/major_gc.h" +#include "caml/memory.h" +#include "caml/mlvalues.h" +#include "caml/weak.h" +#include "caml/minor_gc.h" +#include "caml/signals.h" + +value caml_ephe_list_head = 0; + +static value ephe_dummy = 0; +value caml_ephe_none = (value) &ephe_dummy; + +#define CAMLassert_valid_ephemeron(eph) do{ \ + CAMLassert (Is_in_heap (eph)); \ + CAMLassert (Tag_val(eph) == Abstract_tag); \ + CAMLassert (CAML_EPHE_FIRST_KEY <= Wosize_val (eph)); \ +}while(0) + +#define CAMLassert_valid_offset(eph, offset) do{ \ + CAMLassert_valid_ephemeron(eph); \ + CAMLassert (0 <= offset); \ + CAMLassert (offset < Wosize_val (eph) - CAML_EPHE_FIRST_KEY); \ +}while(0) + +#define CAMLassert_not_dead_value(v) do{ \ + CAMLassert ( caml_gc_phase != Phase_clean \ + || !Is_block(v) \ + || !Is_in_heap (v) \ + || !Is_white_val(v) ); \ +}while(0) + +CAMLexport mlsize_t caml_ephemeron_num_keys(value eph) +{ + CAMLassert_valid_ephemeron(eph); + return Wosize_val (eph) - CAML_EPHE_FIRST_KEY; +} + +/** The minor heap is considered alive. */ +#if defined (NATIVE_CODE) && defined (NO_NAKED_POINTERS) +/** Outside minor and major heap, x must be black. */ +static inline int Is_Dead_during_clean(value x) +{ + CAMLassert (x != caml_ephe_none); + CAMLassert (caml_gc_phase == Phase_clean); + return Is_block (x) && !Is_young (x) && Is_white_val(x); +} +/** The minor heap doesn't have to be marked, outside they should + already be black +*/ +static inline int Must_be_Marked_during_mark(value x) +{ + CAMLassert (x != caml_ephe_none); + CAMLassert (caml_gc_phase == Phase_mark); + return Is_block (x) && !Is_young (x); +} +#else +static inline int Is_Dead_during_clean(value x) +{ + CAMLassert (x != caml_ephe_none); + CAMLassert (caml_gc_phase == Phase_clean); + return Is_block (x) && Is_in_heap (x) && Is_white_val(x); +} +static inline int Must_be_Marked_during_mark(value x) +{ + CAMLassert (x != caml_ephe_none); + CAMLassert (caml_gc_phase == Phase_mark); + return Is_block (x) && Is_in_heap (x); +} +#endif + +/* [len] is a number of words (fields) */ +CAMLexport value caml_ephemeron_create (mlsize_t len) +{ + mlsize_t size, i; + value res; + + CAMLassert(len <= CAML_EPHE_MAX_WOSIZE); + size = len + CAML_EPHE_FIRST_KEY; + if (size < CAML_EPHE_FIRST_KEY || size > Max_wosize) + caml_invalid_argument ("Weak.create"); + res = caml_alloc_shr (size, Abstract_tag); + for (i = 1; i < size; i++) Field (res, i) = caml_ephe_none; + Field (res, CAML_EPHE_LINK_OFFSET) = caml_ephe_list_head; + caml_ephe_list_head = res; + return res; +} + +CAMLprim value caml_ephe_create (value len) +{ + return caml_ephemeron_create(Long_val(len)); +} + +CAMLprim value caml_weak_create (value len) +{ + return caml_ephe_create(len); +} + +/** + Specificity of the cleaning phase (Phase_clean): + + The dead keys must be removed from the ephemerons and data removed + when one the keys is dead. Here we call it cleaning the ephemerons. + A specific phase of the GC is dedicated to this, Phase_clean. This + phase is just after the mark phase, so the white values are dead + values. It iterates the function caml_ephe_clean through all the + ephemerons. + + However the GC is incremental and ocaml code can run on the middle + of this cleaning phase. In order to respect the semantic of the + ephemerons concerning dead values, the getter and setter must work + as if the cleaning of all the ephemerons have been done at once. + + - key getter: Even if a dead key have not yet been replaced by + caml_ephe_none, getting it should return none. + - key setter: If we replace a dead key we need to set the data to + caml_ephe_none and clean the ephemeron. + + This two cases are dealt by a call to do_check_key_clean that + trigger the cleaning of the ephemerons when the accessed key is + dead. This test is fast. + + In the case of value getter and value setter, there is no fast + test because the removing of the data depend of the deadliness of the keys. + We must always try to clean the ephemerons. + + */ + +#define None_val (Val_int(0)) +#define Some_tag 0 + +/* If we are in Phase_clean we need to check if the key + that is going to disappear is dead and so should trigger a cleaning + */ +static void do_check_key_clean(value ar, mlsize_t offset) +{ + CAMLassert (offset >= CAML_EPHE_FIRST_KEY); + if (caml_gc_phase == Phase_clean){ + value elt = Field (ar, offset); + if (elt != caml_ephe_none && Is_Dead_during_clean(elt)){ + Field(ar, offset) = caml_ephe_none; + Field(ar, CAML_EPHE_DATA_OFFSET) = caml_ephe_none; + }; + }; +} + +/* If we are in Phase_clean we need to do as if the key is empty when + it will be cleaned during this phase */ +static inline int is_ephe_key_none(value ar, mlsize_t offset) +{ + value elt = Field (ar, offset); + if (elt == caml_ephe_none){ + return 1; + }else if (caml_gc_phase == Phase_clean && Is_Dead_during_clean(elt)){ + Field(ar, offset) = caml_ephe_none; + Field(ar, CAML_EPHE_DATA_OFFSET) = caml_ephe_none; + return 1; + } else { + return 0; + } +} + +static void do_set (value ar, mlsize_t offset, value v) +{ + if (Is_block (v) && Is_young (v)){ + /* modified version of caml_modify */ + value old = Field (ar, offset); + Field (ar, offset) = v; + if (!(Is_block (old) && Is_young (old))){ + add_to_ephe_ref_table (&caml_ephe_ref_table, ar, offset); + } + }else{ + Field (ar, offset) = v; + } +} + +CAMLexport void caml_ephemeron_set_key(value ar, mlsize_t offset, value k) +{ + CAMLassert_valid_offset(ar, offset); + CAMLassert (Is_in_heap (ar)); + + offset += CAML_EPHE_FIRST_KEY; + do_check_key_clean(ar, offset); + do_set (ar, offset, k); +} + +CAMLprim value caml_ephe_set_key (value ar, value n, value el) +{ + caml_ephemeron_set_key(ar, Long_val(n), el); + return Val_unit; +} + +CAMLexport void caml_ephemeron_unset_key(value ar, mlsize_t offset) +{ + CAMLassert_valid_offset(ar, offset); + CAMLassert (Is_in_heap (ar)); + + offset += CAML_EPHE_FIRST_KEY; + + do_check_key_clean(ar, offset); + Field (ar, offset) = caml_ephe_none; +} + +CAMLprim value caml_ephe_unset_key (value ar, value n) +{ + caml_ephemeron_unset_key(ar, Long_val(n)); + return Val_unit; +} + +/* deprecated (03/2016) */ +value caml_ephe_set_key_option (value ar, value n, value el) +{ + if (Is_block (el)){ + CAMLassert (Wosize_val (el) == 1); + caml_ephe_set_key(ar, n, Field (el, 0)); + }else{ + CAMLassert (el == None_val); + caml_ephe_unset_key(ar, n); + } + return Val_unit; +} + +/* deprecated (03/2016) */ +CAMLprim value caml_weak_set (value ar, value n, value el) +{ + return caml_ephe_set_key_option(ar, n, el); +} + +CAMLexport void caml_ephemeron_set_data (value ar, value el) +{ + CAMLassert_valid_ephemeron(ar); + + if (caml_gc_phase == Phase_clean){ + /* During this phase since we don't know which ephemerons have been + cleaned we always need to check it. */ + caml_ephe_clean(ar); + }; + do_set (ar, CAML_EPHE_DATA_OFFSET, el); +} + +CAMLprim value caml_ephe_set_data (value ar, value el) +{ + caml_ephemeron_set_data (ar, el); + return Val_unit; +} + +CAMLexport void caml_ephemeron_unset_data (value ar) +{ + CAMLassert_valid_ephemeron(ar); + + Field (ar, CAML_EPHE_DATA_OFFSET) = caml_ephe_none; +} + +CAMLprim value caml_ephe_unset_data (value ar) +{ + caml_ephemeron_unset_data (ar); + return Val_unit; +} + +static value optionalize(int status, value *x) +{ + CAMLparam0(); + CAMLlocal2(res, v); + if(status) { + v = *x; + res = caml_alloc_small (1, Some_tag); + Field (res, 0) = v; + } else { + res = None_val; + } + CAMLreturn(res); +} + +CAMLexport int caml_ephemeron_get_key (value ar, mlsize_t offset, value *key) +{ + value elt; + CAMLassert_valid_offset(ar, offset); + + offset += CAML_EPHE_FIRST_KEY; + + if (is_ephe_key_none(ar, offset)){ + return 0; + }else{ + elt = Field (ar, offset); + if (caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(elt)){ + caml_darken (elt, NULL); + } + *key = elt; + CAMLassert_not_dead_value(elt); + return 1; + } +} + +CAMLprim value caml_ephe_get_key (value ar, value n) +{ + value data; + return optionalize(caml_ephemeron_get_key(ar, Long_val(n), &data), &data); +} + +CAMLprim value caml_weak_get (value ar, value n) +{ + return caml_ephe_get_key(ar, n); +} + +CAMLexport int caml_ephemeron_get_data (value ar, value *data) +{ + value elt; + CAMLassert_valid_ephemeron(ar); + + if(caml_gc_phase == Phase_clean) caml_ephe_clean(ar); + elt = Field (ar, CAML_EPHE_DATA_OFFSET); + if (elt == caml_ephe_none){ + return 0; + }else{ + if (caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(elt)){ + caml_darken (elt, NULL); + } + *data = elt; + CAMLassert_not_dead_value(elt); + return 1; + } +} + +CAMLprim value caml_ephe_get_data (value ar) +{ + value data; + return optionalize(caml_ephemeron_get_data(ar, &data), &data); +} + + +static inline void copy_value(value src, value dst) +{ + if (Tag_val (src) < No_scan_tag){ + mlsize_t i; + for (i = 0; i < Wosize_val (src); i++){ + value f = Field (src, i); + if (caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(f)){ + caml_darken (f, NULL); + } + caml_modify (&Field (dst, i), f); + } + }else{ + memmove (Bp_val (dst), Bp_val (src), Bosize_val (src)); + } +} + +CAMLexport int caml_ephemeron_get_key_copy(value ar, mlsize_t offset, + value *key) +{ + mlsize_t loop = 0; + CAMLparam1(ar); + value elt = Val_unit, v; /* Caution: they are NOT local roots. */ + CAMLassert_valid_offset(ar, offset); + + offset += CAML_EPHE_FIRST_KEY; + + while(1) { + if(is_ephe_key_none(ar, offset)) CAMLreturn(0); + v = Field (ar, offset); + /** Don't copy custom_block #7279 */ + if(!(Is_block (v) && Is_in_heap_or_young(v) && Tag_val(v) != Custom_tag)) { + if ( caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(v) ){ + caml_darken (v, NULL); + }; + *key = v; + CAMLreturn(1); + } + if (elt != Val_unit && + Wosize_val(v) == Wosize_val(elt) && Tag_val(v) == Tag_val(elt)) { + /* The allocation may trigger a finaliser that change the tag + and size of the block. Therefore, in addition to checking + that the pointer is still alive, we have to check that it + still has the same tag and size. + */ + CAMLassert_not_dead_value(v); + copy_value(v, elt); + *key = elt; + CAMLreturn(1); + } + + CAMLassert(loop < 10); + if(8 == loop){ /** One minor gc must be enough */ + elt = Val_unit; + CAML_INSTR_INT ("force_minor/weak@", 1); + caml_request_minor_gc (); + caml_gc_dispatch (); + } else { + /* cases where loop is between 0 to 7 and where loop is equal to 9 */ + elt = caml_alloc (Wosize_val (v), Tag_val (v)); + /* The GC may erase, move or even change v during this call to + caml_alloc. */ + } + ++loop; + } +} + +CAMLprim value caml_ephe_get_key_copy (value ar, value n) +{ + value key; + return optionalize(caml_ephemeron_get_key_copy(ar, Long_val(n), &key), + &key); +} + +CAMLprim value caml_weak_get_copy (value ar, value n) +{ + return caml_ephe_get_key_copy(ar, n); +} + +CAMLexport int caml_ephemeron_get_data_copy (value ar, value *data) +{ + mlsize_t loop = 0; + CAMLparam1 (ar); + value elt = Val_unit, v; /* Caution: they are NOT local roots. */ + CAMLassert_valid_ephemeron(ar); + + while(1) { + if (caml_gc_phase == Phase_clean) caml_ephe_clean(ar); + v = Field (ar, CAML_EPHE_DATA_OFFSET); + if (v == caml_ephe_none) CAMLreturn(0); + /** Don't copy custom_block #7279 */ + if (!(Is_block (v) && Is_in_heap_or_young(v) && Tag_val(v) != Custom_tag)) { + if ( caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(v) ){ + caml_darken (v, NULL); + }; + *data = v; + CAMLreturn(1); + } + if (elt != Val_unit && + Wosize_val(v) == Wosize_val(elt) && Tag_val(v) == Tag_val(elt)) { + /** cf caml_ephemeron_get_key_copy */ + CAMLassert_not_dead_value(v); + copy_value(v, elt); + *data = elt; + CAMLreturn(1); + } + + CAMLassert(loop < 10); + if(8 == loop){ /** One minor gc must be enough */ + elt = Val_unit; + CAML_INSTR_INT ("force_minor/weak@", 1); + caml_request_minor_gc (); + caml_gc_dispatch (); + } else { + /* cases where loop is between 0 to 7 and where loop is equal to 9 */ + elt = caml_alloc (Wosize_val (v), Tag_val (v)); + /** cf caml_ephemeron_get_key_copy */ + } + ++loop; + } +} + + +CAMLprim value caml_ephe_get_data_copy (value ar) +{ + value data; + return optionalize(caml_ephemeron_get_data_copy(ar, &data), &data); +} + +CAMLexport int caml_ephemeron_key_is_set(value ar, mlsize_t offset) +{ + CAMLassert_valid_offset(ar, offset); + + offset += CAML_EPHE_FIRST_KEY; + return !is_ephe_key_none(ar, offset); +} + +CAMLprim value caml_ephe_check_key (value ar, value n) +{ + return Val_bool (caml_ephemeron_key_is_set(ar, Long_val(n))); +} + +CAMLprim value caml_weak_check (value ar, value n) +{ + return caml_ephe_check_key(ar, n); +} + +CAMLexport int caml_ephemeron_data_is_set (value ar) +{ + CAMLassert_valid_ephemeron(ar); + + if(caml_gc_phase == Phase_clean) caml_ephe_clean(ar); + return Field (ar, CAML_EPHE_DATA_OFFSET) != caml_ephe_none; +} + +CAMLprim value caml_ephe_check_data (value ar) +{ + return Val_bool (caml_ephemeron_data_is_set(ar)); +} + +CAMLexport void caml_ephemeron_blit_key(value ars, mlsize_t offset_s, + value ard, mlsize_t offset_d, + mlsize_t length) +{ + intnat i; /** intnat because the second for-loop stops with i == -1 */ + if (length == 0) return; + CAMLassert_valid_offset(ars, offset_s); + CAMLassert_valid_offset(ard, offset_d); + CAMLassert(length <= Wosize_val(ars) - CAML_EPHE_FIRST_KEY); + CAMLassert(length <= Wosize_val(ard) - CAML_EPHE_FIRST_KEY); + CAMLassert(offset_s <= Wosize_val(ars) - CAML_EPHE_FIRST_KEY - length); + CAMLassert(offset_d <= Wosize_val(ard) - CAML_EPHE_FIRST_KEY - length); + + offset_s += CAML_EPHE_FIRST_KEY; + offset_d += CAML_EPHE_FIRST_KEY; + + if (caml_gc_phase == Phase_clean){ + caml_ephe_clean(ars); + caml_ephe_clean(ard); + } + if (offset_d < offset_s){ + for (i = 0; i < length; i++){ + do_set (ard, offset_d + i, Field (ars, offset_s + i)); + } + }else{ + for (i = length - 1; i >= 0; i--){ + do_set (ard, offset_d + i, Field (ars, offset_s + i)); + } + } +} + +CAMLprim value caml_ephe_blit_key (value ars, value ofs, + value ard, value ofd, value len) +{ + if (Long_val(len) == 0) return Val_unit; + + caml_ephemeron_blit_key(ars,Long_val(ofs),ard,Long_val(ofd),Long_val(len)); + return Val_unit; +} + +CAMLprim value caml_weak_blit (value ars, value ofs, + value ard, value ofd, value len) +{ + return caml_ephe_blit_key (ars, ofs, ard, ofd, len); +} + +CAMLexport void caml_ephemeron_blit_data (value ars, value ard) +{ + CAMLassert_valid_ephemeron(ars); + CAMLassert_valid_ephemeron(ard); + + if(caml_gc_phase == Phase_clean) { + caml_ephe_clean(ars); + caml_ephe_clean(ard); + }; + do_set (ard, CAML_EPHE_DATA_OFFSET, Field (ars, CAML_EPHE_DATA_OFFSET)); +} + +CAMLprim value caml_ephe_blit_data (value ars, value ard) +{ + caml_ephemeron_blit_data(ars, ard); + return Val_unit; +} diff --git a/runtime/win32.c b/runtime/win32.c new file mode 100644 index 00000000..f6ae5a0a --- /dev/null +++ b/runtime/win32.c @@ -0,0 +1,1037 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* Win32-specific stuff */ + +/* FILE_INFO_BY_HANDLE_CLASS and FILE_NAME_INFO are only available from Windows + Vista onwards */ +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "caml/alloc.h" +#include "caml/address_class.h" +#include "caml/fail.h" +#include "caml/io.h" +#include "caml/memory.h" +#include "caml/misc.h" +#include "caml/osdeps.h" +#include "caml/signals.h" +#include "caml/sys.h" + +#include "caml/config.h" +#ifdef SUPPORT_DYNAMIC_LINKING +#include +#endif + +#ifndef S_ISREG +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif + +unsigned short caml_win32_major = 0; +unsigned short caml_win32_minor = 0; +unsigned short caml_win32_build = 0; +unsigned short caml_win32_revision = 0; + +CAMLnoreturn_start +static void caml_win32_sys_error (int errnum) +CAMLnoreturn_end; + +static void caml_win32_sys_error(int errnum) +{ + wchar_t buffer[512]; + value msg; + if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + errnum, + 0, + buffer, + sizeof(buffer)/sizeof(wchar_t), + NULL)) { + msg = caml_copy_string_of_utf16(buffer); + } else { + msg = caml_alloc_sprintf("unknown error #%d", errnum); + } + caml_raise_sys_error(msg); +} + +int caml_read_fd(int fd, int flags, void * buf, int n) +{ + int retcode; + if ((flags & CHANNEL_FLAG_FROM_SOCKET) == 0) { + caml_enter_blocking_section(); + retcode = read(fd, buf, n); + /* Large reads from console can fail with ENOMEM. Reduce requested size + and try again. */ + if (retcode == -1 && errno == ENOMEM && n > 16384) { + retcode = read(fd, buf, 16384); + } + caml_leave_blocking_section(); + if (retcode == -1) caml_sys_io_error(NO_ARG); + } else { + caml_enter_blocking_section(); + retcode = recv((SOCKET) _get_osfhandle(fd), buf, n, 0); + caml_leave_blocking_section(); + if (retcode == -1) caml_win32_sys_error(WSAGetLastError()); + } + return retcode; +} + +int caml_write_fd(int fd, int flags, void * buf, int n) +{ + int retcode; + if ((flags & CHANNEL_FLAG_FROM_SOCKET) == 0) { +#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) + if (flags & CHANNEL_FLAG_BLOCKING_WRITE) { + retcode = write(fd, buf, n); + } else { +#endif + caml_enter_blocking_section(); + retcode = write(fd, buf, n); + caml_leave_blocking_section(); +#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) + } +#endif + if (retcode == -1) caml_sys_io_error(NO_ARG); + } else { + caml_enter_blocking_section(); + retcode = send((SOCKET) _get_osfhandle(fd), buf, n, 0); + caml_leave_blocking_section(); + if (retcode == -1) caml_win32_sys_error(WSAGetLastError()); + } + CAMLassert (retcode > 0); + return retcode; +} + +wchar_t * caml_decompose_path(struct ext_table * tbl, wchar_t * path) +{ + wchar_t * p, * q; + int n; + + if (path == NULL) return NULL; + p = caml_stat_wcsdup(path); + q = p; + while (1) { + for (n = 0; q[n] != 0 && q[n] != L';'; n++) /*nothing*/; + caml_ext_table_add(tbl, q); + q = q + n; + if (*q == 0) break; + *q = 0; + q += 1; + } + return p; +} + +wchar_t * caml_search_in_path(struct ext_table * path, const wchar_t * name) +{ + wchar_t * dir, * fullname; + char * u8; + const wchar_t * p; + int i; + struct _stati64 st; + + for (p = name; *p != 0; p++) { + if (*p == '/' || *p == '\\') goto not_found; + } + for (i = 0; i < path->size; i++) { + dir = path->contents[i]; + if (dir[0] == 0) continue; + /* not sure what empty path components mean under Windows */ + fullname = caml_stat_wcsconcat(3, dir, L"\\", name); + u8 = caml_stat_strdup_of_utf16(fullname); + caml_gc_message(0x100, "Searching %s\n", u8); + caml_stat_free(u8); + if (_wstati64(fullname, &st) == 0 && S_ISREG(st.st_mode)) + return fullname; + caml_stat_free(fullname); + } + not_found: + u8 = caml_stat_strdup_of_utf16(name); + caml_gc_message(0x100, "%s not found in search path\n", u8); + caml_stat_free(u8); + return caml_stat_wcsdup(name); +} + +CAMLexport wchar_t * caml_search_exe_in_path(const wchar_t * name) +{ + wchar_t * fullname, * filepart; + char * u8; + size_t fullnamelen; + DWORD retcode; + + fullnamelen = wcslen(name) + 1; + if (fullnamelen < 256) fullnamelen = 256; + while (1) { + fullname = caml_stat_alloc(fullnamelen*sizeof(wchar_t)); + retcode = SearchPath(NULL, /* use system search path */ + name, + L".exe", /* add .exe extension if needed */ + fullnamelen, + fullname, + &filepart); + if (retcode == 0) { + u8 = caml_stat_strdup_of_utf16(name); + caml_gc_message(0x100, "%s not found in search path\n", u8); + caml_stat_free(u8); + caml_stat_free(fullname); + return caml_stat_strdup_os(name); + } + if (retcode < fullnamelen) + return fullname; + caml_stat_free(fullname); + fullnamelen = retcode + 1; + } +} + +wchar_t * caml_search_dll_in_path(struct ext_table * path, const wchar_t * name) +{ + wchar_t * dllname; + wchar_t * res; + + dllname = caml_stat_wcsconcat(2, name, L".dll"); + res = caml_search_in_path(path, dllname); + caml_stat_free(dllname); + return res; +} + +#ifdef SUPPORT_DYNAMIC_LINKING + +void * caml_dlopen(wchar_t * libname, int for_execution, int global) +{ + void *handle; + int flags = (global ? FLEXDLL_RTLD_GLOBAL : 0); + if (!for_execution) flags |= FLEXDLL_RTLD_NOEXEC; + handle = flexdll_wdlopen(libname, flags); + if ((handle != NULL) && ((caml_verb_gc & 0x100) != 0)) { + flexdll_dump_exports(handle); + fflush(stdout); + } + return handle; +} + +void caml_dlclose(void * handle) +{ + flexdll_dlclose(handle); +} + +void * caml_dlsym(void * handle, const char * name) +{ + return flexdll_dlsym(handle, name); +} + +void * caml_globalsym(const char * name) +{ + return flexdll_dlsym(flexdll_dlopen(NULL,0), name); +} + +char * caml_dlerror(void) +{ + return flexdll_dlerror(); +} + +#else + +void * caml_dlopen(wchar_t * libname, int for_execution, int global) +{ + return NULL; +} + +void caml_dlclose(void * handle) +{ +} + +void * caml_dlsym(void * handle, const char * name) +{ + return NULL; +} + +void * caml_globalsym(const char * name) +{ + return NULL; +} + +char * caml_dlerror(void) +{ + return "dynamic loading not supported on this platform"; +} + +#endif + +/* Proper emulation of signal(), including ctrl-C and ctrl-break */ + +typedef void (*sighandler)(int sig); +static int ctrl_handler_installed = 0; +static volatile sighandler ctrl_handler_action = SIG_DFL; + +static BOOL WINAPI ctrl_handler(DWORD event) +{ + /* Only ctrl-C and ctrl-Break are handled */ + if (event != CTRL_C_EVENT && event != CTRL_BREAK_EVENT) return FALSE; + /* Default behavior is to exit, which we get by not handling the event */ + if (ctrl_handler_action == SIG_DFL) return FALSE; + /* Ignore behavior is to do nothing, which we get by claiming that we + have handled the event */ + if (ctrl_handler_action == SIG_IGN) return TRUE; + /* Win32 doesn't like it when we do a longjmp() at this point + (it looks like we're running in a different thread than + the main program!). So, just record the signal. */ + caml_record_signal(SIGINT); + /* We have handled the event */ + return TRUE; +} + +sighandler caml_win32_signal(int sig, sighandler action) +{ + sighandler oldaction; + + if (sig != SIGINT) return signal(sig, action); + if (! ctrl_handler_installed) { + SetConsoleCtrlHandler(ctrl_handler, TRUE); + ctrl_handler_installed = 1; + } + oldaction = ctrl_handler_action; + ctrl_handler_action = action; + return oldaction; +} + +/* Expansion of @responsefile and *? file patterns in the command line */ + +static int argc; +static wchar_t ** argv; +static int argvsize; + +static void store_argument(wchar_t * arg); +static void expand_argument(wchar_t * arg); +static void expand_pattern(wchar_t * arg); + +static void out_of_memory(void) +{ + fprintf(stderr, "Out of memory while expanding command line\n"); + exit(2); +} + +static void store_argument(wchar_t * arg) +{ + if (argc + 1 >= argvsize) { + argvsize *= 2; + argv = + (wchar_t **) caml_stat_resize_noexc(argv, argvsize * sizeof(wchar_t *)); + if (argv == NULL) out_of_memory(); + } + argv[argc++] = arg; +} + +static void expand_argument(wchar_t * arg) +{ + wchar_t * p; + + for (p = arg; *p != 0; p++) { + if (*p == L'*' || *p == L'?') { + expand_pattern(arg); + return; + } + } + store_argument(arg); +} + +static void expand_pattern(wchar_t * pat) +{ + wchar_t * prefix, * p, * name; + intptr_t handle; + struct _wfinddata_t ffblk; + size_t i; + + handle = _wfindfirst(pat, &ffblk); + if (handle == -1) { + store_argument(pat); /* a la Bourne shell */ + return; + } + prefix = caml_stat_wcsdup(pat); + /* We need to stop at the first directory or drive boundary, because the + * _findata_t structure contains the filename, not the leading directory. */ + for (i = wcslen(prefix); i > 0; i--) { + wchar_t c = prefix[i - 1]; + if (c == L'\\' || c == L'/' || c == L':') { prefix[i] = 0; break; } + } + /* No separator was found, it's a filename pattern without a leading + directory. */ + if (i == 0) + prefix[0] = 0; + do { + name = caml_stat_wcsconcat(2, prefix, ffblk.name); + store_argument(name); + } while (_wfindnext(handle, &ffblk) != -1); + _findclose(handle); + caml_stat_free(prefix); +} + + +CAMLexport void caml_expand_command_line(int * argcp, wchar_t *** argvp) +{ + int i; + argc = 0; + argvsize = 16; + argv = (wchar_t **) caml_stat_alloc_noexc(argvsize * sizeof(wchar_t *)); + if (argv == NULL) out_of_memory(); + for (i = 0; i < *argcp; i++) expand_argument((*argvp)[i]); + argv[argc] = NULL; + *argcp = argc; + *argvp = argv; +} + +/* Add to [contents] the (short) names of the files contained in + the directory named [dirname]. No entries are added for [.] and [..]. + Return 0 on success, -1 on error; set errno in the case of error. */ + +int caml_read_directory(wchar_t * dirname, struct ext_table * contents) +{ + size_t dirnamelen; + wchar_t * template; + intptr_t h; + struct _wfinddata_t fileinfo; + + dirnamelen = wcslen(dirname); + if (dirnamelen > 0 && + (dirname[dirnamelen - 1] == L'/' + || dirname[dirnamelen - 1] == L'\\' + || dirname[dirnamelen - 1] == L':')) + template = caml_stat_wcsconcat(2, dirname, L"*.*"); + else + template = caml_stat_wcsconcat(2, dirname, L"\\*.*"); + h = _wfindfirst(template, &fileinfo); + if (h == -1) { + caml_stat_free(template); + return errno == ENOENT ? 0 : -1; + } + do { + if (wcscmp(fileinfo.name, L".") != 0 && wcscmp(fileinfo.name, L"..") != 0) { + caml_ext_table_add(contents, caml_stat_strdup_of_utf16(fileinfo.name)); + } + } while (_wfindnext(h, &fileinfo) == 0); + _findclose(h); + caml_stat_free(template); + return 0; +} + +#ifndef NATIVE_CODE + +/* Set up a new thread for control-C emulation and termination */ + +void caml_signal_thread(void * lpParam) +{ + wchar_t *endptr; + HANDLE h; + /* Get an hexa-code raw handle through the environment */ + h = (HANDLE) (uintptr_t) + wcstol(caml_secure_getenv(_T("CAMLSIGPIPE")), &endptr, 16); + while (1) { + DWORD numread; + BOOL ret; + char iobuf[2]; + /* This shall always return a single character */ + ret = ReadFile(h, iobuf, 1, &numread, NULL); + if (!ret || numread != 1) caml_sys_exit(Val_int(2)); + switch (iobuf[0]) { + case 'C': + caml_record_signal(SIGINT); + break; + case 'T': + raise(SIGTERM); + return; + } + } +} + +#endif /* NATIVE_CODE */ + +#if defined(NATIVE_CODE) + +/* Handling of system stack overflow. + * Based on code provided by Olivier Andrieu. + + * An EXCEPTION_STACK_OVERFLOW is signaled when the guard page at the + * end of the stack has been accessed. Windows clears the PAGE_GUARD + * protection (making it a regular PAGE_READWRITE) and then calls our + * exception handler. This means that although we're handling an "out + * of stack" condition, there is a bit of stack available to call + * functions and allocate temporaries. + * + * PAGE_GUARD is a one-shot access protection mechanism: we need to + * restore the PAGE_GUARD protection on this page otherwise the next + * stack overflow won't be detected and the program will abruptly exit + * with STATUS_ACCESS_VIOLATION. + * + * Visual Studio 2003 and later (_MSC_VER >= 1300) have a + * _resetstkoflw() function that resets this protection. + * Unfortunately, it cannot work when called directly from the + * exception handler because at this point we are using the page that + * is to be protected. + * + * A solution is to use an alternate stack when restoring the + * protection. However it's not possible to use _resetstkoflw() then + * since it determines the stack pointer by calling alloca(): it would + * try to protect the alternate stack. + * + * Finally, we call caml_raise_stack_overflow; it will either call + * caml_raise_exception which switches back to the normal stack, or + * call caml_fatal_uncaught_exception which terminates the program + * quickly. + */ + +static uintnat win32_alt_stack[0x100]; + +static void caml_reset_stack (void *faulting_address) +{ + SYSTEM_INFO si; + DWORD page_size; + MEMORY_BASIC_INFORMATION mbi; + DWORD oldprot; + + /* get the system's page size. */ + GetSystemInfo (&si); + page_size = si.dwPageSize; + + /* get some information on the page the fault occurred */ + if (! VirtualQuery (faulting_address, &mbi, sizeof mbi)) + goto failed; + + VirtualProtect (mbi.BaseAddress, page_size, + mbi.Protect | PAGE_GUARD, &oldprot); + + failed: + caml_raise_stack_overflow(); +} + + +#ifndef _WIN64 +static LONG CALLBACK + caml_stack_overflow_VEH (EXCEPTION_POINTERS* exn_info) +{ + DWORD code = exn_info->ExceptionRecord->ExceptionCode; + CONTEXT *ctx = exn_info->ContextRecord; + DWORD *ctx_ip = &(ctx->Eip); + DWORD *ctx_sp = &(ctx->Esp); + + if (code == EXCEPTION_STACK_OVERFLOW && Is_in_code_area (*ctx_ip)) + { + uintnat faulting_address; + uintnat * alt_esp; + + /* grab the address that caused the fault */ + faulting_address = exn_info->ExceptionRecord->ExceptionInformation[1]; + + /* call caml_reset_stack(faulting_address) using the alternate stack */ + alt_esp = win32_alt_stack + sizeof(win32_alt_stack) / sizeof(uintnat); + *--alt_esp = faulting_address; + *ctx_sp = (uintnat) (alt_esp - 1); + *ctx_ip = (uintnat) &caml_reset_stack; + + return EXCEPTION_CONTINUE_EXECUTION; + } + + return EXCEPTION_CONTINUE_SEARCH; +} + +#else +extern char *caml_exception_pointer; +extern value *caml_young_ptr; + +/* Do not use the macro from address_class.h here. */ +#undef Is_in_code_area +#define Is_in_code_area(pc) \ + ( ((char *)(pc) >= caml_code_area_start && \ + (char *)(pc) <= caml_code_area_end) \ +|| ((char *)(pc) >= &caml_system__code_begin && \ + (char *)(pc) <= &caml_system__code_end) \ +|| (Classify_addr(pc) & In_code_area) ) +extern char caml_system__code_begin, caml_system__code_end; + + +static LONG CALLBACK + caml_stack_overflow_VEH (EXCEPTION_POINTERS* exn_info) +{ + DWORD code = exn_info->ExceptionRecord->ExceptionCode; + CONTEXT *ctx = exn_info->ContextRecord; + + if (code == EXCEPTION_STACK_OVERFLOW && Is_in_code_area (ctx->Rip)) + { + uintnat faulting_address; + uintnat * alt_rsp; + + /* grab the address that caused the fault */ + faulting_address = exn_info->ExceptionRecord->ExceptionInformation[1]; + + /* refresh runtime parameters from registers */ + caml_exception_pointer = (char *) ctx->R14; + caml_young_ptr = (value *) ctx->R15; + + /* call caml_reset_stack(faulting_address) using the alternate stack */ + alt_rsp = win32_alt_stack + sizeof(win32_alt_stack) / sizeof(uintnat); + ctx->Rcx = faulting_address; + ctx->Rsp = (uintnat) (alt_rsp - 4 - 1); + ctx->Rip = (uintnat) &caml_reset_stack; + + return EXCEPTION_CONTINUE_EXECUTION; + } + + return EXCEPTION_CONTINUE_SEARCH; +} +#endif /* _WIN64 */ + +void caml_win32_overflow_detection(void) +{ + AddVectoredExceptionHandler(1, caml_stack_overflow_VEH); +} + +#endif /* NATIVE_CODE */ + +/* Seeding of pseudo-random number generators */ + +int caml_win32_random_seed (intnat data[16]) +{ + /* For better randomness, consider: + http://msdn.microsoft.com/library/en-us/seccrypto/security/rtlgenrandom.asp + http://blogs.msdn.com/b/michael_howard/archive/2005/01/14/353379.aspx + */ + FILETIME t; + LARGE_INTEGER pc; + GetSystemTimeAsFileTime(&t); + QueryPerformanceCounter(&pc); /* PR#6032 */ + data[0] = t.dwLowDateTime; + data[1] = t.dwHighDateTime; + data[2] = GetCurrentProcessId(); + data[3] = pc.LowPart; + data[4] = pc.HighPart; + return 5; +} + + +#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L + +static void invalid_parameter_handler(const wchar_t* expression, + const wchar_t* function, + const wchar_t* file, + unsigned int line, + uintptr_t pReserved) +{ + /* no crash box */ +} + + +void caml_install_invalid_parameter_handler() +{ + _set_invalid_parameter_handler(invalid_parameter_handler); +} + +#endif + + +/* Recover executable name */ + +wchar_t * caml_executable_name(void) +{ + wchar_t * name; + DWORD namelen, ret; + + namelen = 256; + while (1) { + name = caml_stat_alloc(namelen*sizeof(wchar_t)); + ret = GetModuleFileName(NULL, name, namelen); + if (ret == 0) { caml_stat_free(name); return NULL; } + if (ret < namelen) break; + caml_stat_free(name); + if (namelen >= 1024*1024) return NULL; /* avoid runaway and overflow */ + namelen *= 2; + } + return name; +} + +/* snprintf emulation */ + +#ifdef LACKS_VSCPRINTF +/* No _vscprintf until Visual Studio .NET 2002 and sadly no version number + in the CRT headers until Visual Studio 2005 so forced to predicate this + on the compiler version instead */ +int _vscprintf(const char * format, va_list args) +{ + int n; + int sz = 5; + char* buf = (char*)malloc(sz); + n = _vsnprintf(buf, sz, format, args); + while (n < 0 || n > sz) { + sz += 512; + buf = (char*)realloc(buf, sz); + n = _vsnprintf(buf, sz, format, args); + } + free(buf); + return n; +} +#endif + +#if defined(_WIN32) && !defined(_UCRT) +int caml_snprintf(char * buf, size_t size, const char * format, ...) +{ + int len; + va_list args; + + if (size > 0) { + va_start(args, format); + len = _vsnprintf(buf, size, format, args); + va_end(args); + if (len >= 0 && len < size) { + /* [len] characters were stored in [buf], + a null-terminator was appended. */ + return len; + } + /* [size] characters were stored in [buf], without null termination. + Put a null terminator, truncating the output. */ + buf[size - 1] = 0; + } + /* Compute the actual length of output, excluding null terminator */ + va_start(args, format); + len = _vscprintf(format, args); + va_end(args); + return len; +} +#endif + +wchar_t *caml_secure_getenv (wchar_t const *var) +{ + /* Win32 doesn't have a notion of setuid bit, so getenv is safe. */ + return _wgetenv(var); +} + +/* caml_win32_getenv is used to implement Sys.getenv and Unix.getenv in such a + way that they get direct access to the Win32 environment rather than to the + copy that is cached by the C runtime system. The result of caml_win32_getenv + is dynamically allocated and must be explicitly deallocated. + + In contrast, the OCaml runtime system still calls _wgetenv from the C runtime + system, via caml_secure_getenv. The result is statically allocated and needs + no deallocation. */ +CAMLexport wchar_t *caml_win32_getenv(wchar_t const *lpName) +{ + wchar_t * lpBuffer; + DWORD nSize = 256, res; + + lpBuffer = caml_stat_alloc_noexc(nSize * sizeof(wchar_t)); + + if (lpBuffer == NULL) + return NULL; + + res = GetEnvironmentVariable(lpName, lpBuffer, nSize); + + if (res == 0) { + caml_stat_free(lpBuffer); + return NULL; + } + + if (res < nSize) + return lpBuffer; + + nSize = res; + lpBuffer = caml_stat_resize_noexc(lpBuffer, nSize * sizeof(wchar_t)); + + if (lpBuffer == NULL) + return NULL; + + res = GetEnvironmentVariable(lpName, lpBuffer, nSize); + + if (res == 0 || res >= nSize) { + caml_stat_free(lpBuffer); + return NULL; + } + + return lpBuffer; +} + +/* The rename() implementation in MSVC's CRT is based on MoveFile() + and therefore fails if the new name exists. This is inconsistent + with POSIX and a problem in practice. Here we reimplement + rename() using MoveFileEx() to make it more POSIX-like. + There are no official guarantee that the rename operation is atomic, + but it is widely believed to be atomic on NTFS. */ + +int caml_win32_rename(const wchar_t * oldpath, const wchar_t * newpath) +{ + /* MOVEFILE_REPLACE_EXISTING: to be closer to POSIX + MOVEFILE_COPY_ALLOWED: MoveFile performs a copy if old and new + paths are on different devices, so we do the same here for + compatibility with the old rename()-based implementation. + MOVEFILE_WRITE_THROUGH: not sure it's useful; affects only + the case where a copy is done. */ + if (MoveFileEx(oldpath, newpath, + MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH | + MOVEFILE_COPY_ALLOWED)) { + return 0; + } + /* Modest attempt at mapping Win32 error codes to POSIX error codes. + The __dosmaperr() function from the CRT does a better job but is + generally not accessible. */ + switch (GetLastError()) { + case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: + errno = ENOENT; break; + case ERROR_ACCESS_DENIED: case ERROR_WRITE_PROTECT: case ERROR_CANNOT_MAKE: + errno = EACCES; break; + case ERROR_CURRENT_DIRECTORY: case ERROR_BUSY: + errno = EBUSY; break; + case ERROR_NOT_SAME_DEVICE: + errno = EXDEV; break; + case ERROR_ALREADY_EXISTS: + errno = EEXIST; break; + default: + errno = EINVAL; + } + return -1; +} + +/* Windows Unicode support */ +static uintnat windows_unicode_enabled = WINDOWS_UNICODE; + +/* If [windows_unicode_strict] is non-zero, then illegal UTF-8 characters (on + the OCaml side) or illegal UTF-16 characters (on the Windows side) cause an + error to be signaled. What happens then depends on the variable + [windows_unicode_fallback]. + + If [windows_unicode_strict] is zero, then illegal characters are silently + dropped. */ +static uintnat windows_unicode_strict = 1; + +/* If [windows_unicode_fallback] is non-zero, then if an error is signaled when + translating to UTF-16, the translation is re-done under the assumption that + the argument string is encoded in the local codepage. */ +static uintnat windows_unicode_fallback = 1; + +CAMLexport int win_multi_byte_to_wide_char(const char *s, int slen, + wchar_t *out, int outlen) +{ + int retcode; + + CAMLassert (s != NULL); + + if (slen == 0) + return 0; + + if (windows_unicode_enabled != 0) { + retcode = + MultiByteToWideChar(CP_UTF8, + windows_unicode_strict ? MB_ERR_INVALID_CHARS : 0, + s, slen, out, outlen); + if (retcode == 0 && windows_unicode_fallback != 0) + retcode = MultiByteToWideChar(CP_ACP, 0, s, slen, out, outlen); + } else { + retcode = MultiByteToWideChar(CP_ACP, 0, s, slen, out, outlen); + } + + if (retcode == 0) + caml_win32_sys_error(GetLastError()); + + return retcode; +} + +/* For old versions of Windows we simply ignore the flag */ +#ifndef WC_ERR_INVALID_CHARS +#define WC_ERR_INVALID_CHARS 0 +#endif + +CAMLexport int win_wide_char_to_multi_byte(const wchar_t *s, int slen, + char *out, int outlen) +{ + int retcode; + + CAMLassert(s != NULL); + + if (slen == 0) + return 0; + + if (windows_unicode_enabled != 0) + retcode = + WideCharToMultiByte(CP_UTF8, + windows_unicode_strict ? WC_ERR_INVALID_CHARS : 0, + s, slen, out, outlen, NULL, NULL); + else + retcode = + WideCharToMultiByte(CP_ACP, 0, s, slen, out, outlen, NULL, NULL); + + if (retcode == 0) + caml_win32_sys_error(GetLastError()); + + return retcode; +} + +CAMLexport value caml_copy_string_of_utf16(const wchar_t *s) +{ + int retcode, slen; + value v; + + slen = wcslen(s); + /* Do not include final NULL */ + retcode = win_wide_char_to_multi_byte(s, slen, NULL, 0); + v = caml_alloc_string(retcode); + win_wide_char_to_multi_byte(s, slen, String_val(v), retcode); + + return v; +} + +CAMLexport inline wchar_t* caml_stat_strdup_to_utf16(const char *s) +{ + wchar_t * ws; + int retcode; + + retcode = win_multi_byte_to_wide_char(s, -1, NULL, 0); + ws = caml_stat_alloc_noexc(retcode * sizeof(*ws)); + win_multi_byte_to_wide_char(s, -1, ws, retcode); + + return ws; +} + +CAMLexport caml_stat_string caml_stat_strdup_of_utf16(const wchar_t *s) +{ + caml_stat_string out; + int retcode; + + retcode = win_wide_char_to_multi_byte(s, -1, NULL, 0); + out = caml_stat_alloc(retcode); + win_wide_char_to_multi_byte(s, -1, out, retcode); + + return out; +} + +void caml_probe_win32_version(void) +{ + /* Determine the version of Windows we're running, and cache it */ + WCHAR fileName[MAX_PATH]; + DWORD size = + GetModuleFileName(GetModuleHandle(L"kernel32"), fileName, MAX_PATH); + DWORD dwHandle = 0; + BYTE* versionInfo; + fileName[size] = 0; + size = GetFileVersionInfoSize(fileName, &dwHandle); + versionInfo = (BYTE*)malloc(size * sizeof(BYTE)); + if (GetFileVersionInfo(fileName, 0, size, versionInfo)) { + UINT len = 0; + VS_FIXEDFILEINFO* vsfi = NULL; + VerQueryValue(versionInfo, L"\\", (void**)&vsfi, &len); + caml_win32_major = HIWORD(vsfi->dwProductVersionMS); + caml_win32_minor = LOWORD(vsfi->dwProductVersionMS); + caml_win32_build = HIWORD(vsfi->dwProductVersionLS); + caml_win32_revision = LOWORD(vsfi->dwProductVersionLS); + } + free(versionInfo); +} + +static UINT startup_codepage = 0; + +void caml_setup_win32_terminal(void) +{ + if (caml_win32_major >= 10) { + startup_codepage = GetConsoleOutputCP(); + if (startup_codepage != CP_UTF8) + SetConsoleOutputCP(CP_UTF8); + } +} + +void caml_restore_win32_terminal(void) +{ + if (startup_codepage != 0) + SetConsoleOutputCP(startup_codepage); +} + +/* Detect if a named pipe corresponds to a Cygwin/MSYS pty: see + https://github.com/mirror/newlib-cygwin/blob/00e9bf2/winsup/cygwin/dtable.cc#L932 +*/ +typedef +BOOL (WINAPI *tGetFileInformationByHandleEx)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, + LPVOID, DWORD); + +static int caml_win32_is_cygwin_pty(HANDLE hFile) +{ + char buffer[1024]; + FILE_NAME_INFO * nameinfo = (FILE_NAME_INFO *) buffer; + static tGetFileInformationByHandleEx pGetFileInformationByHandleEx = + INVALID_HANDLE_VALUE; + + if (pGetFileInformationByHandleEx == INVALID_HANDLE_VALUE) + pGetFileInformationByHandleEx = + (tGetFileInformationByHandleEx)GetProcAddress( + GetModuleHandle(L"KERNEL32.DLL"), "GetFileInformationByHandleEx"); + + if (pGetFileInformationByHandleEx == NULL) + return 0; + + /* Get pipe name. GetFileInformationByHandleEx does not NULL-terminate the + string, so reduce the buffer size to allow for adding one. */ + if (! pGetFileInformationByHandleEx(hFile, + FileNameInfo, + buffer, + sizeof(buffer) - sizeof(WCHAR))) + return 0; + + nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0'; + + /* check if this could be a msys pty pipe ('msys-XXXX-ptyN-XX') + or a cygwin pty pipe ('cygwin-XXXX-ptyN-XX') */ + if ((wcsstr(nameinfo->FileName, L"msys-") || + wcsstr(nameinfo->FileName, L"cygwin-")) && + wcsstr(nameinfo->FileName, L"-pty")) + return 1; + + return 0; +} + +CAMLexport int caml_win32_isatty(int fd) +{ + DWORD lpMode; + HANDLE hFile = (HANDLE)_get_osfhandle(fd); + + if (hFile == INVALID_HANDLE_VALUE) + return 0; + + switch (GetFileType(hFile)) { + case FILE_TYPE_CHAR: + /* Both console handles and the NUL device are FILE_TYPE_CHAR. The NUL + device returns FALSE for a GetConsoleMode call. _isatty incorrectly + only uses GetFileType (see GPR#1321). */ + return GetConsoleMode(hFile, &lpMode); + case FILE_TYPE_PIPE: + /* Cygwin PTYs are implemented using named pipes */ + return caml_win32_is_cygwin_pty(hFile); + default: + break; + } + + return 0; +} + +int caml_num_rows_fd(int fd) +{ + return -1; +} diff --git a/stdlib/.depend b/stdlib/.depend index 2e53ef70..8929413f 100644 --- a/stdlib/.depend +++ b/stdlib/.depend @@ -1,331 +1,1255 @@ -stdlib__arg.cmo : stdlib__sys.cmi stdlib__string.cmi stdlib__printf.cmi stdlib__list.cmi stdlib__buffer.cmi stdlib__array.cmi \ +stdlib__arg.cmo : \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__printf.cmi \ + stdlib__list.cmi \ + stdlib__buffer.cmi \ + stdlib__array.cmi \ stdlib__arg.cmi -stdlib__arg.cmx : stdlib__sys.cmx stdlib__string.cmx stdlib__printf.cmx stdlib__list.cmx stdlib__buffer.cmx stdlib__array.cmx \ +stdlib__arg.cmx : \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__printf.cmx \ + stdlib__list.cmx \ + stdlib__buffer.cmx \ + stdlib__array.cmx \ stdlib__arg.cmi stdlib__arg.cmi : -stdlib__array.cmo : stdlib__seq.cmi stdlib__array.cmi -stdlib__array.cmx : stdlib__seq.cmx stdlib__array.cmi -stdlib__array.cmi : stdlib__seq.cmi -stdlib__arrayLabels.cmo : stdlib__array.cmi stdlib__arrayLabels.cmi -stdlib__arrayLabels.cmx : stdlib__array.cmx stdlib__arrayLabels.cmi -stdlib__arrayLabels.cmi : stdlib__seq.cmi -stdlib__bigarray.cmo : stdlib__sys.cmi stdlib__complex.cmi stdlib__array.cmi stdlib__bigarray.cmi -stdlib__bigarray.cmx : stdlib__sys.cmx stdlib__complex.cmx stdlib__array.cmx stdlib__bigarray.cmi -stdlib__bigarray.cmi : stdlib__complex.cmi -stdlib__buffer.cmo : stdlib__uchar.cmi stdlib__sys.cmi stdlib__string.cmi stdlib__seq.cmi stdlib__char.cmi stdlib__bytes.cmi \ +stdlib__array.cmo : \ + stdlib__seq.cmi \ + stdlib__array.cmi +stdlib__array.cmx : \ + stdlib__seq.cmx \ + stdlib__array.cmi +stdlib__array.cmi : \ + stdlib__seq.cmi +stdlib__arrayLabels.cmo : \ + stdlib__array.cmi \ + stdlib__arrayLabels.cmi +stdlib__arrayLabels.cmx : \ + stdlib__array.cmx \ + stdlib__arrayLabels.cmi +stdlib__arrayLabels.cmi : \ + stdlib__seq.cmi +stdlib__bigarray.cmo : \ + stdlib__sys.cmi \ + stdlib__complex.cmi \ + stdlib__array.cmi \ + stdlib__bigarray.cmi +stdlib__bigarray.cmx : \ + stdlib__sys.cmx \ + stdlib__complex.cmx \ + stdlib__array.cmx \ + stdlib__bigarray.cmi +stdlib__bigarray.cmi : \ + stdlib__complex.cmi +stdlib__bool.cmo : \ + stdlib.cmi \ + stdlib__bool.cmi +stdlib__bool.cmx : \ + stdlib.cmx \ + stdlib__bool.cmi +stdlib__bool.cmi : +stdlib__buffer.cmo : \ + stdlib__uchar.cmi \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__seq.cmi \ + stdlib__char.cmi \ + stdlib__bytes.cmi \ stdlib__buffer.cmi -stdlib__buffer.cmx : stdlib__uchar.cmx stdlib__sys.cmx stdlib__string.cmx stdlib__seq.cmx stdlib__char.cmx stdlib__bytes.cmx \ +stdlib__buffer.cmx : \ + stdlib__uchar.cmx \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__seq.cmx \ + stdlib__char.cmx \ + stdlib__bytes.cmx \ stdlib__buffer.cmi -stdlib__buffer.cmi : stdlib__uchar.cmi stdlib__seq.cmi -stdlib__bytes.cmo : stdlib__sys.cmi stdlib__seq.cmi stdlib__char.cmi stdlib__bytes.cmi -stdlib__bytes.cmx : stdlib__sys.cmx stdlib__seq.cmx stdlib__char.cmx stdlib__bytes.cmi -stdlib__bytes.cmi : stdlib__seq.cmi -stdlib__bytesLabels.cmo : stdlib__bytes.cmi stdlib__bytesLabels.cmi -stdlib__bytesLabels.cmx : stdlib__bytes.cmx stdlib__bytesLabels.cmi -stdlib__bytesLabels.cmi : stdlib__seq.cmi -stdlib__callback.cmo : stdlib__obj.cmi stdlib__callback.cmi -stdlib__callback.cmx : stdlib__obj.cmx stdlib__callback.cmi +stdlib__buffer.cmi : \ + stdlib__uchar.cmi \ + stdlib__seq.cmi +stdlib__bytes.cmo : \ + stdlib__sys.cmi \ + stdlib.cmi \ + stdlib__seq.cmi \ + stdlib__char.cmi \ + stdlib__bytes.cmi +stdlib__bytes.cmx : \ + stdlib__sys.cmx \ + stdlib.cmx \ + stdlib__seq.cmx \ + stdlib__char.cmx \ + stdlib__bytes.cmi +stdlib__bytes.cmi : \ + stdlib__seq.cmi +stdlib__bytesLabels.cmo : \ + stdlib__bytes.cmi \ + stdlib__bytesLabels.cmi +stdlib__bytesLabels.cmx : \ + stdlib__bytes.cmx \ + stdlib__bytesLabels.cmi +stdlib__bytesLabels.cmi : \ + stdlib__seq.cmi +stdlib__callback.cmo : \ + stdlib__obj.cmi \ + stdlib__callback.cmi +stdlib__callback.cmx : \ + stdlib__obj.cmx \ + stdlib__callback.cmi stdlib__callback.cmi : -camlinternalFormat.cmo : stdlib__sys.cmi stdlib__string.cmi stdlib__char.cmi \ - camlinternalFormatBasics.cmi stdlib__bytes.cmi stdlib__buffer.cmi camlinternalFormat.cmi -camlinternalFormat.cmx : stdlib__sys.cmx stdlib__string.cmx stdlib__char.cmx \ - camlinternalFormatBasics.cmx stdlib__bytes.cmx stdlib__buffer.cmx camlinternalFormat.cmi -camlinternalFormat.cmi : camlinternalFormatBasics.cmi stdlib__buffer.cmi -camlinternalFormatBasics.cmo : camlinternalFormatBasics.cmi -camlinternalFormatBasics.cmx : camlinternalFormatBasics.cmi +camlinternalFormat.cmo : \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__int.cmi \ + stdlib__char.cmi \ + camlinternalFormatBasics.cmi \ + stdlib__bytes.cmi \ + stdlib__buffer.cmi \ + camlinternalFormat.cmi +camlinternalFormat.cmx : \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__int.cmx \ + stdlib__char.cmx \ + camlinternalFormatBasics.cmx \ + stdlib__bytes.cmx \ + stdlib__buffer.cmx \ + camlinternalFormat.cmi +camlinternalFormat.cmi : \ + camlinternalFormatBasics.cmi \ + stdlib__buffer.cmi +camlinternalFormatBasics.cmo : \ + camlinternalFormatBasics.cmi +camlinternalFormatBasics.cmx : \ + camlinternalFormatBasics.cmi camlinternalFormatBasics.cmi : -camlinternalLazy.cmo : stdlib__obj.cmi camlinternalLazy.cmi -camlinternalLazy.cmx : stdlib__obj.cmx camlinternalLazy.cmi +camlinternalLazy.cmo : \ + stdlib__obj.cmi \ + camlinternalLazy.cmi +camlinternalLazy.cmx : \ + stdlib__obj.cmx \ + camlinternalLazy.cmi camlinternalLazy.cmi : -camlinternalMod.cmo : stdlib__obj.cmi camlinternalOO.cmi stdlib__array.cmi \ +camlinternalMod.cmo : \ + stdlib__obj.cmi \ + camlinternalOO.cmi \ + stdlib__array.cmi \ camlinternalMod.cmi -camlinternalMod.cmx : stdlib__obj.cmx camlinternalOO.cmx stdlib__array.cmx \ +camlinternalMod.cmx : \ + stdlib__obj.cmx \ + camlinternalOO.cmx \ + stdlib__array.cmx \ camlinternalMod.cmi -camlinternalMod.cmi : stdlib__obj.cmi -camlinternalOO.cmo : stdlib__sys.cmi stdlib__string.cmi stdlib__obj.cmi stdlib__map.cmi stdlib__list.cmi stdlib__char.cmi \ - stdlib__array.cmi camlinternalOO.cmi -camlinternalOO.cmx : stdlib__sys.cmx stdlib__string.cmx stdlib__obj.cmx stdlib__map.cmx stdlib__list.cmx stdlib__char.cmx \ - stdlib__array.cmx camlinternalOO.cmi -camlinternalOO.cmi : stdlib__obj.cmi -stdlib__char.cmo : stdlib__char.cmi -stdlib__char.cmx : stdlib__char.cmi +camlinternalMod.cmi : \ + stdlib__obj.cmi +camlinternalOO.cmo : \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__obj.cmi \ + stdlib__map.cmi \ + stdlib__list.cmi \ + stdlib__char.cmi \ + stdlib__array.cmi \ + camlinternalOO.cmi +camlinternalOO.cmx : \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__obj.cmx \ + stdlib__map.cmx \ + stdlib__list.cmx \ + stdlib__char.cmx \ + stdlib__array.cmx \ + camlinternalOO.cmi +camlinternalOO.cmi : \ + stdlib__obj.cmi +stdlib__char.cmo : \ + stdlib__char.cmi +stdlib__char.cmx : \ + stdlib__char.cmi stdlib__char.cmi : -stdlib__complex.cmo : stdlib__complex.cmi -stdlib__complex.cmx : stdlib__complex.cmi +stdlib__complex.cmo : \ + stdlib__complex.cmi +stdlib__complex.cmx : \ + stdlib__complex.cmi stdlib__complex.cmi : -stdlib__digest.cmo : stdlib__string.cmi stdlib__char.cmi stdlib__bytes.cmi stdlib__digest.cmi -stdlib__digest.cmx : stdlib__string.cmx stdlib__char.cmx stdlib__bytes.cmx stdlib__digest.cmi +stdlib__digest.cmo : \ + stdlib__string.cmi \ + stdlib__char.cmi \ + stdlib__bytes.cmi \ + stdlib__digest.cmi +stdlib__digest.cmx : \ + stdlib__string.cmx \ + stdlib__char.cmx \ + stdlib__bytes.cmx \ + stdlib__digest.cmi stdlib__digest.cmi : -stdlib__ephemeron.cmo : stdlib__sys.cmi stdlib__seq.cmi stdlib__random.cmi stdlib__obj.cmi stdlib__lazy.cmi stdlib__hashtbl.cmi \ - stdlib__array.cmi stdlib__ephemeron.cmi -stdlib__ephemeron.cmx : stdlib__sys.cmx stdlib__seq.cmx stdlib__random.cmx stdlib__obj.cmx stdlib__lazy.cmx stdlib__hashtbl.cmx \ - stdlib__array.cmx stdlib__ephemeron.cmi -stdlib__ephemeron.cmi : stdlib__hashtbl.cmi -stdlib__filename.cmo : stdlib__sys.cmi stdlib__string.cmi stdlib__random.cmi stdlib__printf.cmi stdlib__lazy.cmi stdlib__buffer.cmi \ +stdlib__ephemeron.cmo : \ + stdlib__sys.cmi \ + stdlib__seq.cmi \ + stdlib__random.cmi \ + stdlib__obj.cmi \ + stdlib__lazy.cmi \ + stdlib__hashtbl.cmi \ + stdlib__array.cmi \ + stdlib__ephemeron.cmi +stdlib__ephemeron.cmx : \ + stdlib__sys.cmx \ + stdlib__seq.cmx \ + stdlib__random.cmx \ + stdlib__obj.cmx \ + stdlib__lazy.cmx \ + stdlib__hashtbl.cmx \ + stdlib__array.cmx \ + stdlib__ephemeron.cmi +stdlib__ephemeron.cmi : \ + stdlib__hashtbl.cmi +stdlib__filename.cmo : \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__random.cmi \ + stdlib__printf.cmi \ + stdlib__lazy.cmi \ + stdlib__buffer.cmi \ stdlib__filename.cmi -stdlib__filename.cmx : stdlib__sys.cmx stdlib__string.cmx stdlib__random.cmx stdlib__printf.cmx stdlib__lazy.cmx stdlib__buffer.cmx \ +stdlib__filename.cmx : \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__random.cmx \ + stdlib__printf.cmx \ + stdlib__lazy.cmx \ + stdlib__buffer.cmx \ stdlib__filename.cmi stdlib__filename.cmi : -stdlib__float.cmo : stdlib__float.cmi -stdlib__float.cmx : stdlib__float.cmi -stdlib__float.cmi : -stdlib__format.cmo : stdlib__string.cmi stdlib__list.cmi camlinternalFormatBasics.cmi \ - camlinternalFormat.cmi stdlib__buffer.cmi stdlib__format.cmi -stdlib__format.cmx : stdlib__string.cmx stdlib__list.cmx camlinternalFormatBasics.cmx \ - camlinternalFormat.cmx stdlib__buffer.cmx stdlib__format.cmi -stdlib__format.cmi : stdlib__buffer.cmi -stdlib__gc.cmo : stdlib__sys.cmi stdlib__string.cmi stdlib__printf.cmi stdlib__gc.cmi -stdlib__gc.cmx : stdlib__sys.cmx stdlib__string.cmx stdlib__printf.cmx stdlib__gc.cmi +stdlib__float.cmo : \ + stdlib.cmi \ + stdlib__seq.cmi \ + stdlib__list.cmi \ + stdlib__array.cmi \ + stdlib__float.cmi +stdlib__float.cmx : \ + stdlib.cmx \ + stdlib__seq.cmx \ + stdlib__list.cmx \ + stdlib__array.cmx \ + stdlib__float.cmi +stdlib__float.cmi : \ + stdlib.cmi \ + stdlib__seq.cmi +stdlib__format.cmo : \ + stdlib__string.cmi \ + stdlib.cmi \ + stdlib__stack.cmi \ + stdlib__queue.cmi \ + stdlib__list.cmi \ + stdlib__int.cmi \ + camlinternalFormatBasics.cmi \ + camlinternalFormat.cmi \ + stdlib__buffer.cmi \ + stdlib__format.cmi +stdlib__format.cmx : \ + stdlib__string.cmx \ + stdlib.cmx \ + stdlib__stack.cmx \ + stdlib__queue.cmx \ + stdlib__list.cmx \ + stdlib__int.cmx \ + camlinternalFormatBasics.cmx \ + camlinternalFormat.cmx \ + stdlib__buffer.cmx \ + stdlib__format.cmi +stdlib__format.cmi : \ + stdlib.cmi \ + stdlib__buffer.cmi +stdlib__fun.cmo : \ + stdlib__printexc.cmi \ + stdlib__fun.cmi +stdlib__fun.cmx : \ + stdlib__printexc.cmx \ + stdlib__fun.cmi +stdlib__fun.cmi : +stdlib__gc.cmo : \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__printf.cmi \ + stdlib__gc.cmi +stdlib__gc.cmx : \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__printf.cmx \ + stdlib__gc.cmi stdlib__gc.cmi : -stdlib__genlex.cmo : stdlib__string.cmi stdlib__stream.cmi stdlib__list.cmi stdlib__hashtbl.cmi stdlib__char.cmi stdlib__bytes.cmi \ +stdlib__genlex.cmo : \ + stdlib__string.cmi \ + stdlib__stream.cmi \ + stdlib__list.cmi \ + stdlib__hashtbl.cmi \ + stdlib__char.cmi \ + stdlib__bytes.cmi \ stdlib__genlex.cmi -stdlib__genlex.cmx : stdlib__string.cmx stdlib__stream.cmx stdlib__list.cmx stdlib__hashtbl.cmx stdlib__char.cmx stdlib__bytes.cmx \ +stdlib__genlex.cmx : \ + stdlib__string.cmx \ + stdlib__stream.cmx \ + stdlib__list.cmx \ + stdlib__hashtbl.cmx \ + stdlib__char.cmx \ + stdlib__bytes.cmx \ stdlib__genlex.cmi -stdlib__genlex.cmi : stdlib__stream.cmi -stdlib__hashtbl.cmo : stdlib__sys.cmi stdlib__string.cmi stdlib__seq.cmi stdlib__random.cmi stdlib__obj.cmi stdlib__lazy.cmi \ - stdlib__array.cmi stdlib__hashtbl.cmi -stdlib__hashtbl.cmx : stdlib__sys.cmx stdlib__string.cmx stdlib__seq.cmx stdlib__random.cmx stdlib__obj.cmx stdlib__lazy.cmx \ - stdlib__array.cmx stdlib__hashtbl.cmi -stdlib__hashtbl.cmi : stdlib__seq.cmi -stdlib__int32.cmo : stdlib__int32.cmi -stdlib__int32.cmx : stdlib__int32.cmi +stdlib__genlex.cmi : \ + stdlib__stream.cmi +stdlib__hashtbl.cmo : \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__seq.cmi \ + stdlib__random.cmi \ + stdlib__obj.cmi \ + stdlib__lazy.cmi \ + stdlib__array.cmi \ + stdlib__hashtbl.cmi +stdlib__hashtbl.cmx : \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__seq.cmx \ + stdlib__random.cmx \ + stdlib__obj.cmx \ + stdlib__lazy.cmx \ + stdlib__array.cmx \ + stdlib__hashtbl.cmi +stdlib__hashtbl.cmi : \ + stdlib__seq.cmi +stdlib__int.cmo : \ + stdlib.cmi \ + stdlib__int.cmi +stdlib__int.cmx : \ + stdlib.cmx \ + stdlib__int.cmi +stdlib__int.cmi : +stdlib__int32.cmo : \ + stdlib__sys.cmi \ + stdlib.cmi \ + stdlib__int32.cmi +stdlib__int32.cmx : \ + stdlib__sys.cmx \ + stdlib.cmx \ + stdlib__int32.cmi stdlib__int32.cmi : -stdlib__int64.cmo : stdlib__int64.cmi -stdlib__int64.cmx : stdlib__int64.cmi +stdlib__int64.cmo : \ + stdlib.cmi \ + stdlib__int64.cmi +stdlib__int64.cmx : \ + stdlib.cmx \ + stdlib__int64.cmi stdlib__int64.cmi : -stdlib__lazy.cmo : stdlib__obj.cmi camlinternalLazy.cmi stdlib__lazy.cmi -stdlib__lazy.cmx : stdlib__obj.cmx camlinternalLazy.cmx stdlib__lazy.cmi -stdlib__lazy.cmi : -stdlib__lexing.cmo : stdlib__sys.cmi stdlib__string.cmi stdlib__bytes.cmi stdlib__array.cmi stdlib__lexing.cmi -stdlib__lexing.cmx : stdlib__sys.cmx stdlib__string.cmx stdlib__bytes.cmx stdlib__array.cmx stdlib__lexing.cmi +stdlib__lazy.cmo : \ + stdlib__obj.cmi \ + camlinternalLazy.cmi \ + stdlib__lazy.cmi +stdlib__lazy.cmx : \ + stdlib__obj.cmx \ + camlinternalLazy.cmx \ + stdlib__lazy.cmi +stdlib__lazy.cmi : \ + camlinternalLazy.cmi +stdlib__lexing.cmo : \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__bytes.cmi \ + stdlib__array.cmi \ + stdlib__lexing.cmi +stdlib__lexing.cmx : \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__bytes.cmx \ + stdlib__array.cmx \ + stdlib__lexing.cmi stdlib__lexing.cmi : -stdlib__list.cmo : stdlib__sys.cmi stdlib__seq.cmi stdlib__list.cmi -stdlib__list.cmx : stdlib__sys.cmx stdlib__seq.cmx stdlib__list.cmi -stdlib__list.cmi : stdlib__seq.cmi -stdlib__listLabels.cmo : stdlib__list.cmi stdlib__listLabels.cmi -stdlib__listLabels.cmx : stdlib__list.cmx stdlib__listLabels.cmi -stdlib__listLabels.cmi : stdlib__seq.cmi -stdlib__map.cmo : stdlib__seq.cmi stdlib__map.cmi -stdlib__map.cmx : stdlib__seq.cmx stdlib__map.cmi -stdlib__map.cmi : stdlib__seq.cmi -stdlib__marshal.cmo : stdlib__bytes.cmi stdlib__marshal.cmi -stdlib__marshal.cmx : stdlib__bytes.cmx stdlib__marshal.cmi +stdlib__list.cmo : \ + stdlib__sys.cmi \ + stdlib__seq.cmi \ + stdlib__list.cmi +stdlib__list.cmx : \ + stdlib__sys.cmx \ + stdlib__seq.cmx \ + stdlib__list.cmi +stdlib__list.cmi : \ + stdlib__seq.cmi +stdlib__listLabels.cmo : \ + stdlib__list.cmi \ + stdlib__listLabels.cmi +stdlib__listLabels.cmx : \ + stdlib__list.cmx \ + stdlib__listLabels.cmi +stdlib__listLabels.cmi : \ + stdlib__seq.cmi +stdlib__map.cmo : \ + stdlib__seq.cmi \ + stdlib__map.cmi +stdlib__map.cmx : \ + stdlib__seq.cmx \ + stdlib__map.cmi +stdlib__map.cmi : \ + stdlib__seq.cmi +stdlib__marshal.cmo : \ + stdlib__bytes.cmi \ + stdlib__marshal.cmi +stdlib__marshal.cmx : \ + stdlib__bytes.cmx \ + stdlib__marshal.cmi stdlib__marshal.cmi : -stdlib__moreLabels.cmo : stdlib__set.cmi stdlib__map.cmi stdlib__hashtbl.cmi stdlib__moreLabels.cmi -stdlib__moreLabels.cmx : stdlib__set.cmx stdlib__map.cmx stdlib__hashtbl.cmx stdlib__moreLabels.cmi -stdlib__moreLabels.cmi : stdlib__set.cmi stdlib__seq.cmi stdlib__map.cmi stdlib__hashtbl.cmi -stdlib__nativeint.cmo : stdlib__sys.cmi stdlib__nativeint.cmi -stdlib__nativeint.cmx : stdlib__sys.cmx stdlib__nativeint.cmi +stdlib__moreLabels.cmo : \ + stdlib__set.cmi \ + stdlib__map.cmi \ + stdlib__hashtbl.cmi \ + stdlib__moreLabels.cmi +stdlib__moreLabels.cmx : \ + stdlib__set.cmx \ + stdlib__map.cmx \ + stdlib__hashtbl.cmx \ + stdlib__moreLabels.cmi +stdlib__moreLabels.cmi : \ + stdlib__set.cmi \ + stdlib__seq.cmi \ + stdlib__map.cmi \ + stdlib__hashtbl.cmi +stdlib__nativeint.cmo : \ + stdlib__sys.cmi \ + stdlib.cmi \ + stdlib__nativeint.cmi +stdlib__nativeint.cmx : \ + stdlib__sys.cmx \ + stdlib.cmx \ + stdlib__nativeint.cmi stdlib__nativeint.cmi : -stdlib__obj.cmo : stdlib__marshal.cmi stdlib__int32.cmi stdlib__obj.cmi -stdlib__obj.cmx : stdlib__marshal.cmx stdlib__int32.cmx stdlib__obj.cmi -stdlib__obj.cmi : stdlib__int32.cmi -stdlib__oo.cmo : camlinternalOO.cmi stdlib__oo.cmi -stdlib__oo.cmx : camlinternalOO.cmx stdlib__oo.cmi -stdlib__oo.cmi : camlinternalOO.cmi -stdlib__parsing.cmo : stdlib__obj.cmi stdlib__lexing.cmi stdlib__array.cmi stdlib__parsing.cmi -stdlib__parsing.cmx : stdlib__obj.cmx stdlib__lexing.cmx stdlib__array.cmx stdlib__parsing.cmi -stdlib__parsing.cmi : stdlib__obj.cmi stdlib__lexing.cmi -stdlib__printexc.cmo : stdlib__printf.cmi stdlib__obj.cmi stdlib__buffer.cmi stdlib__array.cmi stdlib__printexc.cmi -stdlib__printexc.cmx : stdlib__printf.cmx stdlib__obj.cmx stdlib__buffer.cmx stdlib__array.cmx stdlib__printexc.cmi +stdlib__obj.cmo : \ + stdlib__sys.cmi \ + stdlib__marshal.cmi \ + stdlib__int32.cmi \ + stdlib__obj.cmi +stdlib__obj.cmx : \ + stdlib__sys.cmx \ + stdlib__marshal.cmx \ + stdlib__int32.cmx \ + stdlib__obj.cmi +stdlib__obj.cmi : \ + stdlib__int32.cmi +stdlib__oo.cmo : \ + camlinternalOO.cmi \ + stdlib__oo.cmi +stdlib__oo.cmx : \ + camlinternalOO.cmx \ + stdlib__oo.cmi +stdlib__oo.cmi : \ + camlinternalOO.cmi +stdlib__option.cmo : \ + stdlib__seq.cmi \ + stdlib__option.cmi +stdlib__option.cmx : \ + stdlib__seq.cmx \ + stdlib__option.cmi +stdlib__option.cmi : \ + stdlib__seq.cmi +stdlib__parsing.cmo : \ + stdlib__obj.cmi \ + stdlib__lexing.cmi \ + stdlib__array.cmi \ + stdlib__parsing.cmi +stdlib__parsing.cmx : \ + stdlib__obj.cmx \ + stdlib__lexing.cmx \ + stdlib__array.cmx \ + stdlib__parsing.cmi +stdlib__parsing.cmi : \ + stdlib__obj.cmi \ + stdlib__lexing.cmi +stdlib__pervasives.cmo : \ + camlinternalFormatBasics.cmi +stdlib__pervasives.cmx : \ + camlinternalFormatBasics.cmx +stdlib__printexc.cmo : \ + stdlib.cmi \ + stdlib__printf.cmi \ + stdlib__obj.cmi \ + stdlib__buffer.cmi \ + stdlib__array.cmi \ + stdlib__printexc.cmi +stdlib__printexc.cmx : \ + stdlib.cmx \ + stdlib__printf.cmx \ + stdlib__obj.cmx \ + stdlib__buffer.cmx \ + stdlib__array.cmx \ + stdlib__printexc.cmi stdlib__printexc.cmi : -stdlib__printf.cmo : camlinternalFormatBasics.cmi camlinternalFormat.cmi stdlib__buffer.cmi \ +stdlib__printf.cmo : \ + camlinternalFormatBasics.cmi \ + camlinternalFormat.cmi \ + stdlib__buffer.cmi \ stdlib__printf.cmi -stdlib__printf.cmx : camlinternalFormatBasics.cmx camlinternalFormat.cmx stdlib__buffer.cmx \ +stdlib__printf.cmx : \ + camlinternalFormatBasics.cmx \ + camlinternalFormat.cmx \ + stdlib__buffer.cmx \ stdlib__printf.cmi -stdlib__printf.cmi : stdlib__buffer.cmi -stdlib__queue.cmo : stdlib__seq.cmi stdlib__queue.cmi -stdlib__queue.cmx : stdlib__seq.cmx stdlib__queue.cmi -stdlib__queue.cmi : stdlib__seq.cmi -stdlib__random.cmo : stdlib__string.cmi stdlib__nativeint.cmi stdlib__int64.cmi stdlib__int32.cmi stdlib__digest.cmi \ - stdlib__char.cmi stdlib__array.cmi stdlib__random.cmi -stdlib__random.cmx : stdlib__string.cmx stdlib__nativeint.cmx stdlib__int64.cmx stdlib__int32.cmx stdlib__digest.cmx \ - stdlib__char.cmx stdlib__array.cmx stdlib__random.cmi -stdlib__random.cmi : stdlib__nativeint.cmi stdlib__int64.cmi stdlib__int32.cmi -stdlib__scanf.cmo : stdlib__string.cmi stdlib__printf.cmi stdlib__list.cmi camlinternalFormatBasics.cmi \ - camlinternalFormat.cmi stdlib__bytes.cmi stdlib__buffer.cmi stdlib__scanf.cmi -stdlib__scanf.cmx : stdlib__string.cmx stdlib__printf.cmx stdlib__list.cmx camlinternalFormatBasics.cmx \ - camlinternalFormat.cmx stdlib__bytes.cmx stdlib__buffer.cmx stdlib__scanf.cmi -stdlib__scanf.cmi : -stdlib__seq.cmo : stdlib__seq.cmi -stdlib__seq.cmx : stdlib__seq.cmi +stdlib__printf.cmi : \ + stdlib__buffer.cmi +stdlib__queue.cmo : \ + stdlib__seq.cmi \ + stdlib__queue.cmi +stdlib__queue.cmx : \ + stdlib__seq.cmx \ + stdlib__queue.cmi +stdlib__queue.cmi : \ + stdlib__seq.cmi +stdlib__random.cmo : \ + stdlib__string.cmi \ + stdlib.cmi \ + stdlib__nativeint.cmi \ + stdlib__int64.cmi \ + stdlib__int32.cmi \ + stdlib__int.cmi \ + stdlib__digest.cmi \ + stdlib__char.cmi \ + stdlib__array.cmi \ + stdlib__random.cmi +stdlib__random.cmx : \ + stdlib__string.cmx \ + stdlib.cmx \ + stdlib__nativeint.cmx \ + stdlib__int64.cmx \ + stdlib__int32.cmx \ + stdlib__int.cmx \ + stdlib__digest.cmx \ + stdlib__char.cmx \ + stdlib__array.cmx \ + stdlib__random.cmi +stdlib__random.cmi : \ + stdlib__nativeint.cmi \ + stdlib__int64.cmi \ + stdlib__int32.cmi +stdlib__result.cmo : \ + stdlib__seq.cmi \ + stdlib__result.cmi +stdlib__result.cmx : \ + stdlib__seq.cmx \ + stdlib__result.cmi +stdlib__result.cmi : \ + stdlib__seq.cmi +stdlib__scanf.cmo : \ + stdlib__string.cmi \ + stdlib.cmi \ + stdlib__printf.cmi \ + stdlib__list.cmi \ + camlinternalFormatBasics.cmi \ + camlinternalFormat.cmi \ + stdlib__bytes.cmi \ + stdlib__buffer.cmi \ + stdlib__scanf.cmi +stdlib__scanf.cmx : \ + stdlib__string.cmx \ + stdlib.cmx \ + stdlib__printf.cmx \ + stdlib__list.cmx \ + camlinternalFormatBasics.cmx \ + camlinternalFormat.cmx \ + stdlib__bytes.cmx \ + stdlib__buffer.cmx \ + stdlib__scanf.cmi +stdlib__scanf.cmi : \ + stdlib.cmi +stdlib__seq.cmo : \ + stdlib__seq.cmi +stdlib__seq.cmx : \ + stdlib__seq.cmi stdlib__seq.cmi : -stdlib__set.cmo : stdlib__seq.cmi stdlib__list.cmi stdlib__set.cmi -stdlib__set.cmx : stdlib__seq.cmx stdlib__list.cmx stdlib__set.cmi -stdlib__set.cmi : stdlib__seq.cmi -stdlib__sort.cmo : stdlib__array.cmi stdlib__sort.cmi -stdlib__sort.cmx : stdlib__array.cmx stdlib__sort.cmi -stdlib__sort.cmi : -stdlib__spacetime.cmo : stdlib__gc.cmi stdlib__spacetime.cmi -stdlib__spacetime.cmx : stdlib__gc.cmx stdlib__spacetime.cmi +stdlib__set.cmo : \ + stdlib__seq.cmi \ + stdlib__list.cmi \ + stdlib__set.cmi +stdlib__set.cmx : \ + stdlib__seq.cmx \ + stdlib__list.cmx \ + stdlib__set.cmi +stdlib__set.cmi : \ + stdlib__seq.cmi +stdlib__spacetime.cmo : \ + stdlib__gc.cmi \ + stdlib__spacetime.cmi +stdlib__spacetime.cmx : \ + stdlib__gc.cmx \ + stdlib__spacetime.cmi stdlib__spacetime.cmi : -stdlib__stack.cmo : stdlib__seq.cmi stdlib__list.cmi stdlib__stack.cmi -stdlib__stack.cmx : stdlib__seq.cmx stdlib__list.cmx stdlib__stack.cmi -stdlib__stack.cmi : stdlib__seq.cmi -stdlib__stdLabels.cmo : stdlib__stringLabels.cmi stdlib__listLabels.cmi stdlib__bytesLabels.cmi \ - stdlib__arrayLabels.cmi stdlib__stdLabels.cmi -stdlib__stdLabels.cmx : stdlib__stringLabels.cmx stdlib__listLabels.cmx stdlib__bytesLabels.cmx \ - stdlib__arrayLabels.cmx stdlib__stdLabels.cmi -stdlib__stdLabels.cmi : stdlib__stringLabels.cmi stdlib__listLabels.cmi stdlib__bytesLabels.cmi \ +stdlib__stack.cmo : \ + stdlib__seq.cmi \ + stdlib__list.cmi \ + stdlib__stack.cmi +stdlib__stack.cmx : \ + stdlib__seq.cmx \ + stdlib__list.cmx \ + stdlib__stack.cmi +stdlib__stack.cmi : \ + stdlib__seq.cmi +stdlib__stdLabels.cmo : \ + stdlib__stringLabels.cmi \ + stdlib__listLabels.cmi \ + stdlib__bytesLabels.cmi \ + stdlib__arrayLabels.cmi \ + stdlib__stdLabels.cmi +stdlib__stdLabels.cmx : \ + stdlib__stringLabels.cmx \ + stdlib__listLabels.cmx \ + stdlib__bytesLabels.cmx \ + stdlib__arrayLabels.cmx \ + stdlib__stdLabels.cmi +stdlib__stdLabels.cmi : \ + stdlib__stringLabels.cmi \ + stdlib__listLabels.cmi \ + stdlib__bytesLabels.cmi \ stdlib__arrayLabels.cmi std_exit.cmo : std_exit.cmx : -stdlib__stream.cmo : stdlib__string.cmi stdlib__list.cmi stdlib__lazy.cmi stdlib__bytes.cmi stdlib__stream.cmi -stdlib__stream.cmx : stdlib__string.cmx stdlib__list.cmx stdlib__lazy.cmx stdlib__bytes.cmx stdlib__stream.cmi +stdlib__stream.cmo : \ + stdlib__string.cmi \ + stdlib__list.cmi \ + stdlib__lazy.cmi \ + stdlib__bytes.cmi \ + stdlib__stream.cmi +stdlib__stream.cmx : \ + stdlib__string.cmx \ + stdlib__list.cmx \ + stdlib__lazy.cmx \ + stdlib__bytes.cmx \ + stdlib__stream.cmi stdlib__stream.cmi : -stdlib__string.cmo : stdlib__bytes.cmi stdlib__string.cmi -stdlib__string.cmx : stdlib__bytes.cmx stdlib__string.cmi -stdlib__string.cmi : stdlib__seq.cmi -stdlib__stringLabels.cmo : stdlib__string.cmi stdlib__stringLabels.cmi -stdlib__stringLabels.cmx : stdlib__string.cmx stdlib__stringLabels.cmi -stdlib__stringLabels.cmi : stdlib__seq.cmi -stdlib__sys.cmo : stdlib__sys.cmi -stdlib__sys.cmx : stdlib__sys.cmi +stdlib__string.cmo : \ + stdlib.cmi \ + stdlib__bytes.cmi \ + stdlib__string.cmi +stdlib__string.cmx : \ + stdlib.cmx \ + stdlib__bytes.cmx \ + stdlib__string.cmi +stdlib__string.cmi : \ + stdlib__seq.cmi +stdlib__stringLabels.cmo : \ + stdlib__string.cmi \ + stdlib__stringLabels.cmi +stdlib__stringLabels.cmx : \ + stdlib__string.cmx \ + stdlib__stringLabels.cmi +stdlib__stringLabels.cmi : \ + stdlib__seq.cmi +stdlib__sys.cmo : \ + stdlib__sys.cmi +stdlib__sys.cmx : \ + stdlib__sys.cmi stdlib__sys.cmi : -stdlib__uchar.cmo : stdlib__char.cmi stdlib__uchar.cmi -stdlib__uchar.cmx : stdlib__char.cmx stdlib__uchar.cmi +stdlib__uchar.cmo : \ + stdlib.cmi \ + stdlib__char.cmi \ + stdlib__uchar.cmi +stdlib__uchar.cmx : \ + stdlib.cmx \ + stdlib__char.cmx \ + stdlib__uchar.cmi stdlib__uchar.cmi : -stdlib__weak.cmo : stdlib__sys.cmi stdlib__obj.cmi stdlib__hashtbl.cmi stdlib__array.cmi stdlib__weak.cmi -stdlib__weak.cmx : stdlib__sys.cmx stdlib__obj.cmx stdlib__hashtbl.cmx stdlib__array.cmx stdlib__weak.cmi -stdlib__weak.cmi : stdlib__hashtbl.cmi -stdlib.cmo : camlinternalFormatBasics.cmi stdlib.cmi -stdlib.cmx : camlinternalFormatBasics.cmx stdlib.cmi -stdlib.cmi : camlinternalFormatBasics.cmi -stdlib__arg.cmo : stdlib__sys.cmi stdlib__string.cmi stdlib__printf.cmi stdlib__list.cmi stdlib__buffer.cmi stdlib__array.cmi \ +stdlib__unit.cmo : \ + stdlib__unit.cmi +stdlib__unit.cmx : \ + stdlib__unit.cmi +stdlib__unit.cmi : +stdlib__weak.cmo : \ + stdlib__sys.cmi \ + stdlib__obj.cmi \ + stdlib__hashtbl.cmi \ + stdlib__array.cmi \ + stdlib__weak.cmi +stdlib__weak.cmx : \ + stdlib__sys.cmx \ + stdlib__obj.cmx \ + stdlib__hashtbl.cmx \ + stdlib__array.cmx \ + stdlib__weak.cmi +stdlib__weak.cmi : \ + stdlib__hashtbl.cmi +stdlib.cmo : \ + camlinternalFormatBasics.cmi \ + stdlib.cmi +stdlib.cmx : \ + camlinternalFormatBasics.cmx \ + stdlib.cmi +stdlib.cmi : \ + camlinternalFormatBasics.cmi +stdlib__arg.cmo : \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__printf.cmi \ + stdlib__list.cmi \ + stdlib__buffer.cmi \ + stdlib__array.cmi \ stdlib__arg.cmi -stdlib__arg.p.cmx : stdlib__sys.cmx stdlib__string.cmx stdlib__printf.cmx stdlib__list.cmx stdlib__buffer.cmx stdlib__array.cmx \ +stdlib__arg.p.cmx : \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__printf.cmx \ + stdlib__list.cmx \ + stdlib__buffer.cmx \ + stdlib__array.cmx \ stdlib__arg.cmi -stdlib__array.cmo : stdlib__seq.cmi stdlib__array.cmi -stdlib__array.p.cmx : stdlib__seq.cmx stdlib__array.cmi -stdlib__arrayLabels.cmo : stdlib__array.cmi stdlib__arrayLabels.cmi -stdlib__arrayLabels.p.cmx : stdlib__array.cmx stdlib__arrayLabels.cmi -stdlib__bigarray.cmo : stdlib__sys.cmi stdlib__complex.cmi stdlib__array.cmi stdlib__bigarray.cmi -stdlib__bigarray.p.cmx : stdlib__sys.cmx stdlib__complex.cmx stdlib__array.cmx stdlib__bigarray.cmi -stdlib__buffer.cmo : stdlib__uchar.cmi stdlib__sys.cmi stdlib__string.cmi stdlib__seq.cmi stdlib__char.cmi stdlib__bytes.cmi \ +stdlib__array.cmo : \ + stdlib__seq.cmi \ + stdlib__array.cmi +stdlib__array.p.cmx : \ + stdlib__seq.cmx \ + stdlib__array.cmi +stdlib__arrayLabels.cmo : \ + stdlib__array.cmi \ + stdlib__arrayLabels.cmi +stdlib__arrayLabels.p.cmx : \ + stdlib__array.cmx \ + stdlib__arrayLabels.cmi +stdlib__bigarray.cmo : \ + stdlib__sys.cmi \ + stdlib__complex.cmi \ + stdlib__array.cmi \ + stdlib__bigarray.cmi +stdlib__bigarray.p.cmx : \ + stdlib__sys.cmx \ + stdlib__complex.cmx \ + stdlib__array.cmx \ + stdlib__bigarray.cmi +stdlib__bool.cmo : \ + stdlib.cmi \ + stdlib__bool.cmi +stdlib__bool.p.cmx : \ + stdlib.cmx \ + stdlib__bool.cmi +stdlib__buffer.cmo : \ + stdlib__uchar.cmi \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__seq.cmi \ + stdlib__char.cmi \ + stdlib__bytes.cmi \ stdlib__buffer.cmi -stdlib__buffer.p.cmx : stdlib__uchar.cmx stdlib__sys.cmx stdlib__string.cmx stdlib__seq.cmx stdlib__char.cmx stdlib__bytes.cmx \ +stdlib__buffer.p.cmx : \ + stdlib__uchar.cmx \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__seq.cmx \ + stdlib__char.cmx \ + stdlib__bytes.cmx \ stdlib__buffer.cmi -stdlib__bytes.cmo : stdlib__sys.cmi stdlib__seq.cmi stdlib__char.cmi stdlib__bytes.cmi -stdlib__bytes.p.cmx : stdlib__sys.cmx stdlib__seq.cmx stdlib__char.cmx stdlib__bytes.cmi -stdlib__bytesLabels.cmo : stdlib__bytes.cmi stdlib__bytesLabels.cmi -stdlib__bytesLabels.p.cmx : stdlib__bytes.cmx stdlib__bytesLabels.cmi -stdlib__callback.cmo : stdlib__obj.cmi stdlib__callback.cmi -stdlib__callback.p.cmx : stdlib__obj.cmx stdlib__callback.cmi -camlinternalFormat.cmo : stdlib__sys.cmi stdlib__string.cmi stdlib__char.cmi \ - camlinternalFormatBasics.cmi stdlib__bytes.cmi stdlib__buffer.cmi camlinternalFormat.cmi -camlinternalFormat.p.cmx : stdlib__sys.cmx stdlib__string.cmx stdlib__char.cmx \ - camlinternalFormatBasics.cmx stdlib__bytes.cmx stdlib__buffer.cmx camlinternalFormat.cmi -camlinternalFormatBasics.cmo : camlinternalFormatBasics.cmi -camlinternalFormatBasics.p.cmx : camlinternalFormatBasics.cmi -camlinternalLazy.cmo : stdlib__obj.cmi camlinternalLazy.cmi -camlinternalLazy.p.cmx : stdlib__obj.cmx camlinternalLazy.cmi -camlinternalMod.cmo : stdlib__obj.cmi camlinternalOO.cmi stdlib__array.cmi \ +stdlib__bytes.cmo : \ + stdlib__sys.cmi \ + stdlib.cmi \ + stdlib__seq.cmi \ + stdlib__char.cmi \ + stdlib__bytes.cmi +stdlib__bytes.p.cmx : \ + stdlib__sys.cmx \ + stdlib.cmx \ + stdlib__seq.cmx \ + stdlib__char.cmx \ + stdlib__bytes.cmi +stdlib__bytesLabels.cmo : \ + stdlib__bytes.cmi \ + stdlib__bytesLabels.cmi +stdlib__bytesLabels.p.cmx : \ + stdlib__bytes.cmx \ + stdlib__bytesLabels.cmi +stdlib__callback.cmo : \ + stdlib__obj.cmi \ + stdlib__callback.cmi +stdlib__callback.p.cmx : \ + stdlib__obj.cmx \ + stdlib__callback.cmi +camlinternalFormat.cmo : \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__int.cmi \ + stdlib__char.cmi \ + camlinternalFormatBasics.cmi \ + stdlib__bytes.cmi \ + stdlib__buffer.cmi \ + camlinternalFormat.cmi +camlinternalFormat.p.cmx : \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__int.cmx \ + stdlib__char.cmx \ + camlinternalFormatBasics.cmx \ + stdlib__bytes.cmx \ + stdlib__buffer.cmx \ + camlinternalFormat.cmi +camlinternalFormatBasics.cmo : \ + camlinternalFormatBasics.cmi +camlinternalFormatBasics.p.cmx : \ + camlinternalFormatBasics.cmi +camlinternalLazy.cmo : \ + stdlib__obj.cmi \ + camlinternalLazy.cmi +camlinternalLazy.p.cmx : \ + stdlib__obj.cmx \ + camlinternalLazy.cmi +camlinternalMod.cmo : \ + stdlib__obj.cmi \ + camlinternalOO.cmi \ + stdlib__array.cmi \ camlinternalMod.cmi -camlinternalMod.p.cmx : stdlib__obj.cmx camlinternalOO.cmx stdlib__array.cmx \ +camlinternalMod.p.cmx : \ + stdlib__obj.cmx \ + camlinternalOO.cmx \ + stdlib__array.cmx \ camlinternalMod.cmi -camlinternalOO.cmo : stdlib__sys.cmi stdlib__string.cmi stdlib__obj.cmi stdlib__map.cmi stdlib__list.cmi stdlib__char.cmi \ - stdlib__array.cmi camlinternalOO.cmi -camlinternalOO.p.cmx : stdlib__sys.cmx stdlib__string.cmx stdlib__obj.cmx stdlib__map.cmx stdlib__list.cmx stdlib__char.cmx \ - stdlib__array.cmx camlinternalOO.cmi -stdlib__char.cmo : stdlib__char.cmi -stdlib__char.p.cmx : stdlib__char.cmi -stdlib__complex.cmo : stdlib__complex.cmi -stdlib__complex.p.cmx : stdlib__complex.cmi -stdlib__digest.cmo : stdlib__string.cmi stdlib__char.cmi stdlib__bytes.cmi stdlib__digest.cmi -stdlib__digest.p.cmx : stdlib__string.cmx stdlib__char.cmx stdlib__bytes.cmx stdlib__digest.cmi -stdlib__ephemeron.cmo : stdlib__sys.cmi stdlib__seq.cmi stdlib__random.cmi stdlib__obj.cmi stdlib__lazy.cmi stdlib__hashtbl.cmi \ - stdlib__array.cmi stdlib__ephemeron.cmi -stdlib__ephemeron.p.cmx : stdlib__sys.cmx stdlib__seq.cmx stdlib__random.cmx stdlib__obj.cmx stdlib__lazy.cmx stdlib__hashtbl.cmx \ - stdlib__array.cmx stdlib__ephemeron.cmi -stdlib__filename.cmo : stdlib__sys.cmi stdlib__string.cmi stdlib__random.cmi stdlib__printf.cmi stdlib__lazy.cmi stdlib__buffer.cmi \ +camlinternalOO.cmo : \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__obj.cmi \ + stdlib__map.cmi \ + stdlib__list.cmi \ + stdlib__char.cmi \ + stdlib__array.cmi \ + camlinternalOO.cmi +camlinternalOO.p.cmx : \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__obj.cmx \ + stdlib__map.cmx \ + stdlib__list.cmx \ + stdlib__char.cmx \ + stdlib__array.cmx \ + camlinternalOO.cmi +stdlib__char.cmo : \ + stdlib__char.cmi +stdlib__char.p.cmx : \ + stdlib__char.cmi +stdlib__complex.cmo : \ + stdlib__complex.cmi +stdlib__complex.p.cmx : \ + stdlib__complex.cmi +stdlib__digest.cmo : \ + stdlib__string.cmi \ + stdlib__char.cmi \ + stdlib__bytes.cmi \ + stdlib__digest.cmi +stdlib__digest.p.cmx : \ + stdlib__string.cmx \ + stdlib__char.cmx \ + stdlib__bytes.cmx \ + stdlib__digest.cmi +stdlib__ephemeron.cmo : \ + stdlib__sys.cmi \ + stdlib__seq.cmi \ + stdlib__random.cmi \ + stdlib__obj.cmi \ + stdlib__lazy.cmi \ + stdlib__hashtbl.cmi \ + stdlib__array.cmi \ + stdlib__ephemeron.cmi +stdlib__ephemeron.p.cmx : \ + stdlib__sys.cmx \ + stdlib__seq.cmx \ + stdlib__random.cmx \ + stdlib__obj.cmx \ + stdlib__lazy.cmx \ + stdlib__hashtbl.cmx \ + stdlib__array.cmx \ + stdlib__ephemeron.cmi +stdlib__filename.cmo : \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__random.cmi \ + stdlib__printf.cmi \ + stdlib__lazy.cmi \ + stdlib__buffer.cmi \ stdlib__filename.cmi -stdlib__filename.p.cmx : stdlib__sys.cmx stdlib__string.cmx stdlib__random.cmx stdlib__printf.cmx stdlib__lazy.cmx stdlib__buffer.cmx \ +stdlib__filename.p.cmx : \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__random.cmx \ + stdlib__printf.cmx \ + stdlib__lazy.cmx \ + stdlib__buffer.cmx \ stdlib__filename.cmi -stdlib__float.cmo : stdlib__float.cmi -stdlib__float.p.cmx : stdlib__float.cmi -stdlib__format.cmo : stdlib__string.cmi stdlib__list.cmi camlinternalFormatBasics.cmi \ - camlinternalFormat.cmi stdlib__buffer.cmi stdlib__format.cmi -stdlib__format.p.cmx : stdlib__string.cmx stdlib__list.cmx camlinternalFormatBasics.cmx \ - camlinternalFormat.cmx stdlib__buffer.cmx stdlib__format.cmi -stdlib__gc.cmo : stdlib__sys.cmi stdlib__string.cmi stdlib__printf.cmi stdlib__gc.cmi -stdlib__gc.p.cmx : stdlib__sys.cmx stdlib__string.cmx stdlib__printf.cmx stdlib__gc.cmi -stdlib__genlex.cmo : stdlib__string.cmi stdlib__stream.cmi stdlib__list.cmi stdlib__hashtbl.cmi stdlib__char.cmi stdlib__bytes.cmi \ +stdlib__float.cmo : \ + stdlib.cmi \ + stdlib__seq.cmi \ + stdlib__list.cmi \ + stdlib__array.cmi \ + stdlib__float.cmi +stdlib__float.p.cmx : \ + stdlib.cmx \ + stdlib__seq.cmx \ + stdlib__list.cmx \ + stdlib__array.cmx \ + stdlib__float.cmi +stdlib__format.cmo : \ + stdlib__string.cmi \ + stdlib.cmi \ + stdlib__stack.cmi \ + stdlib__queue.cmi \ + stdlib__list.cmi \ + stdlib__int.cmi \ + camlinternalFormatBasics.cmi \ + camlinternalFormat.cmi \ + stdlib__buffer.cmi \ + stdlib__format.cmi +stdlib__format.p.cmx : \ + stdlib__string.cmx \ + stdlib.cmx \ + stdlib__stack.cmx \ + stdlib__queue.cmx \ + stdlib__list.cmx \ + stdlib__int.cmx \ + camlinternalFormatBasics.cmx \ + camlinternalFormat.cmx \ + stdlib__buffer.cmx \ + stdlib__format.cmi +stdlib__fun.cmo : \ + stdlib__printexc.cmi \ + stdlib__fun.cmi +stdlib__fun.p.cmx : \ + stdlib__printexc.cmx \ + stdlib__fun.cmi +stdlib__gc.cmo : \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__printf.cmi \ + stdlib__gc.cmi +stdlib__gc.p.cmx : \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__printf.cmx \ + stdlib__gc.cmi +stdlib__genlex.cmo : \ + stdlib__string.cmi \ + stdlib__stream.cmi \ + stdlib__list.cmi \ + stdlib__hashtbl.cmi \ + stdlib__char.cmi \ + stdlib__bytes.cmi \ stdlib__genlex.cmi -stdlib__genlex.p.cmx : stdlib__string.cmx stdlib__stream.cmx stdlib__list.cmx stdlib__hashtbl.cmx stdlib__char.cmx stdlib__bytes.cmx \ +stdlib__genlex.p.cmx : \ + stdlib__string.cmx \ + stdlib__stream.cmx \ + stdlib__list.cmx \ + stdlib__hashtbl.cmx \ + stdlib__char.cmx \ + stdlib__bytes.cmx \ stdlib__genlex.cmi -stdlib__hashtbl.cmo : stdlib__sys.cmi stdlib__string.cmi stdlib__seq.cmi stdlib__random.cmi stdlib__obj.cmi stdlib__lazy.cmi \ - stdlib__array.cmi stdlib__hashtbl.cmi -stdlib__hashtbl.p.cmx : stdlib__sys.cmx stdlib__string.cmx stdlib__seq.cmx stdlib__random.cmx stdlib__obj.cmx stdlib__lazy.cmx \ - stdlib__array.cmx stdlib__hashtbl.cmi -stdlib__int32.cmo : stdlib__int32.cmi -stdlib__int32.p.cmx : stdlib__int32.cmi -stdlib__int64.cmo : stdlib__int64.cmi -stdlib__int64.p.cmx : stdlib__int64.cmi -stdlib__lazy.cmo : stdlib__obj.cmi camlinternalLazy.cmi stdlib__lazy.cmi -stdlib__lazy.p.cmx : stdlib__obj.cmx camlinternalLazy.cmx stdlib__lazy.cmi -stdlib__lexing.cmo : stdlib__sys.cmi stdlib__string.cmi stdlib__bytes.cmi stdlib__array.cmi stdlib__lexing.cmi -stdlib__lexing.p.cmx : stdlib__sys.cmx stdlib__string.cmx stdlib__bytes.cmx stdlib__array.cmx stdlib__lexing.cmi -stdlib__list.cmo : stdlib__sys.cmi stdlib__seq.cmi stdlib__list.cmi -stdlib__list.p.cmx : stdlib__sys.cmx stdlib__seq.cmx stdlib__list.cmi -stdlib__listLabels.cmo : stdlib__list.cmi stdlib__listLabels.cmi -stdlib__listLabels.p.cmx : stdlib__list.cmx stdlib__listLabels.cmi -stdlib__map.cmo : stdlib__seq.cmi stdlib__map.cmi -stdlib__map.p.cmx : stdlib__seq.cmx stdlib__map.cmi -stdlib__marshal.cmo : stdlib__bytes.cmi stdlib__marshal.cmi -stdlib__marshal.p.cmx : stdlib__bytes.cmx stdlib__marshal.cmi -stdlib__moreLabels.cmo : stdlib__set.cmi stdlib__map.cmi stdlib__hashtbl.cmi stdlib__moreLabels.cmi -stdlib__moreLabels.p.cmx : stdlib__set.cmx stdlib__map.cmx stdlib__hashtbl.cmx stdlib__moreLabels.cmi -stdlib__nativeint.cmo : stdlib__sys.cmi stdlib__nativeint.cmi -stdlib__nativeint.p.cmx : stdlib__sys.cmx stdlib__nativeint.cmi -stdlib__obj.cmo : stdlib__marshal.cmi stdlib__int32.cmi stdlib__obj.cmi -stdlib__obj.p.cmx : stdlib__marshal.cmx stdlib__int32.cmx stdlib__obj.cmi -stdlib__oo.cmo : camlinternalOO.cmi stdlib__oo.cmi -stdlib__oo.p.cmx : camlinternalOO.cmx stdlib__oo.cmi -stdlib__parsing.cmo : stdlib__obj.cmi stdlib__lexing.cmi stdlib__array.cmi stdlib__parsing.cmi -stdlib__parsing.p.cmx : stdlib__obj.cmx stdlib__lexing.cmx stdlib__array.cmx stdlib__parsing.cmi -stdlib__printexc.cmo : stdlib__printf.cmi stdlib__obj.cmi stdlib__buffer.cmi stdlib__array.cmi stdlib__printexc.cmi -stdlib__printexc.p.cmx : stdlib__printf.cmx stdlib__obj.cmx stdlib__buffer.cmx stdlib__array.cmx stdlib__printexc.cmi -stdlib__printf.cmo : camlinternalFormatBasics.cmi camlinternalFormat.cmi stdlib__buffer.cmi \ +stdlib__hashtbl.cmo : \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__seq.cmi \ + stdlib__random.cmi \ + stdlib__obj.cmi \ + stdlib__lazy.cmi \ + stdlib__array.cmi \ + stdlib__hashtbl.cmi +stdlib__hashtbl.p.cmx : \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__seq.cmx \ + stdlib__random.cmx \ + stdlib__obj.cmx \ + stdlib__lazy.cmx \ + stdlib__array.cmx \ + stdlib__hashtbl.cmi +stdlib__int.cmo : \ + stdlib.cmi \ + stdlib__int.cmi +stdlib__int.p.cmx : \ + stdlib.cmx \ + stdlib__int.cmi +stdlib__int32.cmo : \ + stdlib__sys.cmi \ + stdlib.cmi \ + stdlib__int32.cmi +stdlib__int32.p.cmx : \ + stdlib__sys.cmx \ + stdlib.cmx \ + stdlib__int32.cmi +stdlib__int64.cmo : \ + stdlib.cmi \ + stdlib__int64.cmi +stdlib__int64.p.cmx : \ + stdlib.cmx \ + stdlib__int64.cmi +stdlib__lazy.cmo : \ + stdlib__obj.cmi \ + camlinternalLazy.cmi \ + stdlib__lazy.cmi +stdlib__lazy.p.cmx : \ + stdlib__obj.cmx \ + camlinternalLazy.cmx \ + stdlib__lazy.cmi +stdlib__lexing.cmo : \ + stdlib__sys.cmi \ + stdlib__string.cmi \ + stdlib__bytes.cmi \ + stdlib__array.cmi \ + stdlib__lexing.cmi +stdlib__lexing.p.cmx : \ + stdlib__sys.cmx \ + stdlib__string.cmx \ + stdlib__bytes.cmx \ + stdlib__array.cmx \ + stdlib__lexing.cmi +stdlib__list.cmo : \ + stdlib__sys.cmi \ + stdlib__seq.cmi \ + stdlib__list.cmi +stdlib__list.p.cmx : \ + stdlib__sys.cmx \ + stdlib__seq.cmx \ + stdlib__list.cmi +stdlib__listLabels.cmo : \ + stdlib__list.cmi \ + stdlib__listLabels.cmi +stdlib__listLabels.p.cmx : \ + stdlib__list.cmx \ + stdlib__listLabels.cmi +stdlib__map.cmo : \ + stdlib__seq.cmi \ + stdlib__map.cmi +stdlib__map.p.cmx : \ + stdlib__seq.cmx \ + stdlib__map.cmi +stdlib__marshal.cmo : \ + stdlib__bytes.cmi \ + stdlib__marshal.cmi +stdlib__marshal.p.cmx : \ + stdlib__bytes.cmx \ + stdlib__marshal.cmi +stdlib__moreLabels.cmo : \ + stdlib__set.cmi \ + stdlib__map.cmi \ + stdlib__hashtbl.cmi \ + stdlib__moreLabels.cmi +stdlib__moreLabels.p.cmx : \ + stdlib__set.cmx \ + stdlib__map.cmx \ + stdlib__hashtbl.cmx \ + stdlib__moreLabels.cmi +stdlib__nativeint.cmo : \ + stdlib__sys.cmi \ + stdlib.cmi \ + stdlib__nativeint.cmi +stdlib__nativeint.p.cmx : \ + stdlib__sys.cmx \ + stdlib.cmx \ + stdlib__nativeint.cmi +stdlib__obj.cmo : \ + stdlib__sys.cmi \ + stdlib__marshal.cmi \ + stdlib__int32.cmi \ + stdlib__obj.cmi +stdlib__obj.p.cmx : \ + stdlib__sys.cmx \ + stdlib__marshal.cmx \ + stdlib__int32.cmx \ + stdlib__obj.cmi +stdlib__oo.cmo : \ + camlinternalOO.cmi \ + stdlib__oo.cmi +stdlib__oo.p.cmx : \ + camlinternalOO.cmx \ + stdlib__oo.cmi +stdlib__option.cmo : \ + stdlib__seq.cmi \ + stdlib__option.cmi +stdlib__option.p.cmx : \ + stdlib__seq.cmx \ + stdlib__option.cmi +stdlib__parsing.cmo : \ + stdlib__obj.cmi \ + stdlib__lexing.cmi \ + stdlib__array.cmi \ + stdlib__parsing.cmi +stdlib__parsing.p.cmx : \ + stdlib__obj.cmx \ + stdlib__lexing.cmx \ + stdlib__array.cmx \ + stdlib__parsing.cmi +stdlib__pervasives.cmo : \ + camlinternalFormatBasics.cmi +stdlib__pervasives.p.cmx : \ + camlinternalFormatBasics.cmx +stdlib__printexc.cmo : \ + stdlib.cmi \ + stdlib__printf.cmi \ + stdlib__obj.cmi \ + stdlib__buffer.cmi \ + stdlib__array.cmi \ + stdlib__printexc.cmi +stdlib__printexc.p.cmx : \ + stdlib.cmx \ + stdlib__printf.cmx \ + stdlib__obj.cmx \ + stdlib__buffer.cmx \ + stdlib__array.cmx \ + stdlib__printexc.cmi +stdlib__printf.cmo : \ + camlinternalFormatBasics.cmi \ + camlinternalFormat.cmi \ + stdlib__buffer.cmi \ stdlib__printf.cmi -stdlib__printf.p.cmx : camlinternalFormatBasics.cmx camlinternalFormat.cmx stdlib__buffer.cmx \ +stdlib__printf.p.cmx : \ + camlinternalFormatBasics.cmx \ + camlinternalFormat.cmx \ + stdlib__buffer.cmx \ stdlib__printf.cmi -stdlib__queue.cmo : stdlib__seq.cmi stdlib__queue.cmi -stdlib__queue.p.cmx : stdlib__seq.cmx stdlib__queue.cmi -stdlib__random.cmo : stdlib__string.cmi stdlib__nativeint.cmi stdlib__int64.cmi stdlib__int32.cmi stdlib__digest.cmi \ - stdlib__char.cmi stdlib__array.cmi stdlib__random.cmi -stdlib__random.p.cmx : stdlib__string.cmx stdlib__nativeint.cmx stdlib__int64.cmx stdlib__int32.cmx stdlib__digest.cmx \ - stdlib__char.cmx stdlib__array.cmx stdlib__random.cmi -stdlib__scanf.cmo : stdlib__string.cmi stdlib__printf.cmi stdlib__list.cmi camlinternalFormatBasics.cmi \ - camlinternalFormat.cmi stdlib__bytes.cmi stdlib__buffer.cmi stdlib__scanf.cmi -stdlib__scanf.p.cmx : stdlib__string.cmx stdlib__printf.cmx stdlib__list.cmx camlinternalFormatBasics.cmx \ - camlinternalFormat.cmx stdlib__bytes.cmx stdlib__buffer.cmx stdlib__scanf.cmi -stdlib__seq.cmo : stdlib__seq.cmi -stdlib__seq.p.cmx : stdlib__seq.cmi -stdlib__set.cmo : stdlib__seq.cmi stdlib__list.cmi stdlib__set.cmi -stdlib__set.p.cmx : stdlib__seq.cmx stdlib__list.cmx stdlib__set.cmi -stdlib__sort.cmo : stdlib__array.cmi stdlib__sort.cmi -stdlib__sort.p.cmx : stdlib__array.cmx stdlib__sort.cmi -stdlib__spacetime.cmo : stdlib__gc.cmi stdlib__spacetime.cmi -stdlib__spacetime.p.cmx : stdlib__gc.cmx stdlib__spacetime.cmi -stdlib__stack.cmo : stdlib__seq.cmi stdlib__list.cmi stdlib__stack.cmi -stdlib__stack.p.cmx : stdlib__seq.cmx stdlib__list.cmx stdlib__stack.cmi -stdlib__stdLabels.cmo : stdlib__stringLabels.cmi stdlib__listLabels.cmi stdlib__bytesLabels.cmi \ - stdlib__arrayLabels.cmi stdlib__stdLabels.cmi -stdlib__stdLabels.p.cmx : stdlib__stringLabels.cmx stdlib__listLabels.cmx stdlib__bytesLabels.cmx \ - stdlib__arrayLabels.cmx stdlib__stdLabels.cmi +stdlib__queue.cmo : \ + stdlib__seq.cmi \ + stdlib__queue.cmi +stdlib__queue.p.cmx : \ + stdlib__seq.cmx \ + stdlib__queue.cmi +stdlib__random.cmo : \ + stdlib__string.cmi \ + stdlib.cmi \ + stdlib__nativeint.cmi \ + stdlib__int64.cmi \ + stdlib__int32.cmi \ + stdlib__int.cmi \ + stdlib__digest.cmi \ + stdlib__char.cmi \ + stdlib__array.cmi \ + stdlib__random.cmi +stdlib__random.p.cmx : \ + stdlib__string.cmx \ + stdlib.cmx \ + stdlib__nativeint.cmx \ + stdlib__int64.cmx \ + stdlib__int32.cmx \ + stdlib__int.cmx \ + stdlib__digest.cmx \ + stdlib__char.cmx \ + stdlib__array.cmx \ + stdlib__random.cmi +stdlib__result.cmo : \ + stdlib__seq.cmi \ + stdlib__result.cmi +stdlib__result.p.cmx : \ + stdlib__seq.cmx \ + stdlib__result.cmi +stdlib__scanf.cmo : \ + stdlib__string.cmi \ + stdlib.cmi \ + stdlib__printf.cmi \ + stdlib__list.cmi \ + camlinternalFormatBasics.cmi \ + camlinternalFormat.cmi \ + stdlib__bytes.cmi \ + stdlib__buffer.cmi \ + stdlib__scanf.cmi +stdlib__scanf.p.cmx : \ + stdlib__string.cmx \ + stdlib.cmx \ + stdlib__printf.cmx \ + stdlib__list.cmx \ + camlinternalFormatBasics.cmx \ + camlinternalFormat.cmx \ + stdlib__bytes.cmx \ + stdlib__buffer.cmx \ + stdlib__scanf.cmi +stdlib__seq.cmo : \ + stdlib__seq.cmi +stdlib__seq.p.cmx : \ + stdlib__seq.cmi +stdlib__set.cmo : \ + stdlib__seq.cmi \ + stdlib__list.cmi \ + stdlib__set.cmi +stdlib__set.p.cmx : \ + stdlib__seq.cmx \ + stdlib__list.cmx \ + stdlib__set.cmi +stdlib__spacetime.cmo : \ + stdlib__gc.cmi \ + stdlib__spacetime.cmi +stdlib__spacetime.p.cmx : \ + stdlib__gc.cmx \ + stdlib__spacetime.cmi +stdlib__stack.cmo : \ + stdlib__seq.cmi \ + stdlib__list.cmi \ + stdlib__stack.cmi +stdlib__stack.p.cmx : \ + stdlib__seq.cmx \ + stdlib__list.cmx \ + stdlib__stack.cmi +stdlib__stdLabels.cmo : \ + stdlib__stringLabels.cmi \ + stdlib__listLabels.cmi \ + stdlib__bytesLabels.cmi \ + stdlib__arrayLabels.cmi \ + stdlib__stdLabels.cmi +stdlib__stdLabels.p.cmx : \ + stdlib__stringLabels.cmx \ + stdlib__listLabels.cmx \ + stdlib__bytesLabels.cmx \ + stdlib__arrayLabels.cmx \ + stdlib__stdLabels.cmi std_exit.cmo : std_exit.cmx : -stdlib__stream.cmo : stdlib__string.cmi stdlib__list.cmi stdlib__lazy.cmi stdlib__bytes.cmi stdlib__stream.cmi -stdlib__stream.p.cmx : stdlib__string.cmx stdlib__list.cmx stdlib__lazy.cmx stdlib__bytes.cmx stdlib__stream.cmi -stdlib__string.cmo : stdlib__bytes.cmi stdlib__string.cmi -stdlib__string.p.cmx : stdlib__bytes.cmx stdlib__string.cmi -stdlib__stringLabels.cmo : stdlib__string.cmi stdlib__stringLabels.cmi -stdlib__stringLabels.p.cmx : stdlib__string.cmx stdlib__stringLabels.cmi -stdlib__sys.cmo : stdlib__sys.cmi -stdlib__sys.p.cmx : stdlib__sys.cmi -stdlib__uchar.cmo : stdlib__char.cmi stdlib__uchar.cmi -stdlib__uchar.p.cmx : stdlib__char.cmx stdlib__uchar.cmi -stdlib__weak.cmo : stdlib__sys.cmi stdlib__obj.cmi stdlib__hashtbl.cmi stdlib__array.cmi stdlib__weak.cmi -stdlib__weak.p.cmx : stdlib__sys.cmx stdlib__obj.cmx stdlib__hashtbl.cmx stdlib__array.cmx stdlib__weak.cmi -stdlib.cmo : camlinternalFormatBasics.cmi stdlib.cmi -stdlib.p.cmx : camlinternalFormatBasics.cmx stdlib.cmi +stdlib__stream.cmo : \ + stdlib__string.cmi \ + stdlib__list.cmi \ + stdlib__lazy.cmi \ + stdlib__bytes.cmi \ + stdlib__stream.cmi +stdlib__stream.p.cmx : \ + stdlib__string.cmx \ + stdlib__list.cmx \ + stdlib__lazy.cmx \ + stdlib__bytes.cmx \ + stdlib__stream.cmi +stdlib__string.cmo : \ + stdlib.cmi \ + stdlib__bytes.cmi \ + stdlib__string.cmi +stdlib__string.p.cmx : \ + stdlib.cmx \ + stdlib__bytes.cmx \ + stdlib__string.cmi +stdlib__stringLabels.cmo : \ + stdlib__string.cmi \ + stdlib__stringLabels.cmi +stdlib__stringLabels.p.cmx : \ + stdlib__string.cmx \ + stdlib__stringLabels.cmi +stdlib__sys.cmo : \ + stdlib__sys.cmi +stdlib__sys.p.cmx : \ + stdlib__sys.cmi +stdlib__uchar.cmo : \ + stdlib.cmi \ + stdlib__char.cmi \ + stdlib__uchar.cmi +stdlib__uchar.p.cmx : \ + stdlib.cmx \ + stdlib__char.cmx \ + stdlib__uchar.cmi +stdlib__unit.cmo : \ + stdlib__unit.cmi +stdlib__unit.p.cmx : \ + stdlib__unit.cmi +stdlib__weak.cmo : \ + stdlib__sys.cmi \ + stdlib__obj.cmi \ + stdlib__hashtbl.cmi \ + stdlib__array.cmi \ + stdlib__weak.cmi +stdlib__weak.p.cmx : \ + stdlib__sys.cmx \ + stdlib__obj.cmx \ + stdlib__hashtbl.cmx \ + stdlib__array.cmx \ + stdlib__weak.cmi +stdlib.cmo : \ + camlinternalFormatBasics.cmi \ + stdlib.cmi +stdlib.p.cmx : \ + camlinternalFormatBasics.cmx \ + stdlib.cmi diff --git a/stdlib/Compflags b/stdlib/Compflags index 0bffcebe..0f3138cd 100755 --- a/stdlib/Compflags +++ b/stdlib/Compflags @@ -18,8 +18,9 @@ case $1 in stdlib.cm[iox]|stdlib.p.cmx) echo ' -nopervasives -no-alias-deps -w -49' \ ' -pp "$AWK -f expand_module_aliases.awk"';; - stdlib__pervasives.cm[iox]|stdlib__pervasives.p.cmx) echo ' -nopervasives';; - camlinternalOO.cmx|camlinternalOO.p.cmx) echo ' -inline 0';; + camlinternalOO.cmx|camlinternalOO.p.cmx) echo ' -inline 0 -afl-inst-ratio 0';; + camlinternalLazy.cmx|camlinternalLazy.p.cmx) echo ' -afl-inst-ratio 0';; + # never instrument camlinternalOO or camlinternalLazy (PR#7725) stdlib__buffer.cmx|stdlib__buffer.p.cmx) echo ' -inline 3';; # make sure add_char is inlined (PR#5872) stdlib__buffer.cm[io]) echo ' -w A';; @@ -29,6 +30,6 @@ case $1 in echo ' -w Ae';; stdlib__scanf.cmx|stdlib__scanf.p.cmx) echo ' -inline 9';; *Labels.cm[ox]|*Labels.p.cmx) echo ' -nolabels -no-alias-deps';; - pervasives.cm[iox]|pervasives.p.cmx) echo ' -nopervasives -no-alias-deps -w -49';; + stdlib__float.cm[ox]|stdlib__float.p.cmx) echo ' -nolabels -no-alias-deps';; *) echo ' ';; esac diff --git a/stdlib/HACKING.adoc b/stdlib/HACKING.adoc new file mode 100644 index 00000000..407d079e --- /dev/null +++ b/stdlib/HACKING.adoc @@ -0,0 +1,37 @@ += Contributing to the standard library + +For guidelines about standard library content, see +link:../CONTRIBUTING.md#contributing-to-the-standard-library[]. + +Note: All paths are given relative to the root of the repository. + +First, build the compiler. Run `./configure`, then `make world.opt`. See +link:../HACKING.adoc[]. + +To add a new module, you must: + +* Create new `.mli` and `.ml` files for the modules, obviously. + +* Define the module in `stdlib/stdlib.mli`, `stdlib/stdlib.ml`, and + `otherlibs/threads/stdlib.ml` in the section of the code commented, + "MODULE ALIASES". Please maintain the same style as the rest of the code, in + particular the alphabetical ordering and whitespace alignment of module + aliases. Note that `otherlibs/threads/stdlib.mli` is a symbolic link to + `stdlib/stdlib.mli`. + +* Add `$(P)module_name.cmo` to the definition of `OTHERS` in `stdlib/Makefile`. + +* Add `$(LIB)/$(P)module_name.cmo` to the definition of `LIB_OBJS` in + `otherlibs/threads/Makefile`. + +* Add `$(P)module_name` to the definition of `STDLIB_MODULES` in + `stdlib/StdlibModules`. Please maintain the alphabetical order. + +* Run `make alldepend` to update all the `.depend` files. These files are not + edited by hand. + +* Run `make clean` or `make partialclean`, then `make world.opt`. + +If you are adding multiple modules, follow the steps above and rebuild the +compiler after adding each module. If you add multiple modules before +rebuilding, the build may fail. diff --git a/stdlib/Makefile b/stdlib/Makefile index 4b044914..67dc8bc4 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -13,14 +13,15 @@ #* * #************************************************************************** -include ../config/Makefile -include ../Makefile.common +ROOTDIR = .. -CAMLRUN ?= ../boot/ocamlrun -CAMLYACC ?= ../boot/ocamlyacc +include $(ROOTDIR)/Makefile.config +include $(ROOTDIR)/Makefile.common + +CAMLRUN ?= $(ROOTDIR)/boot/ocamlrun TARGET_BINDIR ?= $(BINDIR) -COMPILER=../ocamlc +COMPILER=$(ROOTDIR)/ocamlc CAMLC=$(CAMLRUN) $(COMPILER) COMPFLAGS=-strict-sequence -absname -w +a-4-9-41-42-44-45-48 \ -g -warn-error A -bin-annot -nostdlib \ @@ -30,23 +31,27 @@ OPTCOMPFLAGS=-O3 else OPTCOMPFLAGS= endif -OPTCOMPILER=../ocamlopt +OPTCOMPILER=$(ROOTDIR)/ocamlopt CAMLOPT=$(CAMLRUN) $(OPTCOMPILER) -CAMLDEP=$(CAMLRUN) ../tools/ocamldep +CAMLDEP=$(CAMLRUN) $(ROOTDIR)/boot/ocamlc -depend +DEPFLAGS=-slash + +OC_CPPFLAGS += -I$(ROOTDIR)/runtime # Object file prefix P=stdlib__ OBJS=camlinternalFormatBasics.cmo stdlib.cmo $(OTHERS) -OTHERS=$(P)seq.cmo $(P)char.cmo $(P)uchar.cmo $(P)sys.cmo $(P)list.cmo \ - $(P)bytes.cmo $(P)string.cmo \ - $(P)sort.cmo $(P)marshal.cmo $(P)obj.cmo $(P)float.cmo $(P)array.cmo \ - $(P)int32.cmo $(P)int64.cmo $(P)nativeint.cmo \ +OTHERS= $(P)pervasives.cmo $(P)seq.cmo $(P)option.cmo $(P)result.cmo \ + $(P)bool.cmo $(P)char.cmo $(P)uchar.cmo $(P)sys.cmo $(P)list.cmo \ + $(P)bytes.cmo $(P)string.cmo $(P)unit.cmo \ + $(P)marshal.cmo $(P)obj.cmo $(P)array.cmo $(P)float.cmo \ + $(P)int.cmo $(P)int32.cmo $(P)int64.cmo $(P)nativeint.cmo \ $(P)lexing.cmo $(P)parsing.cmo \ $(P)set.cmo $(P)map.cmo $(P)stack.cmo $(P)queue.cmo \ camlinternalLazy.cmo $(P)lazy.cmo $(P)stream.cmo \ $(P)buffer.cmo camlinternalFormat.cmo $(P)printf.cmo \ - $(P)arg.cmo $(P)printexc.cmo $(P)gc.cmo \ + $(P)arg.cmo $(P)printexc.cmo $(P)fun.cmo $(P)gc.cmo \ $(P)digest.cmo $(P)random.cmo $(P)hashtbl.cmo $(P)weak.cmo \ $(P)format.cmo $(P)scanf.cmo $(P)callback.cmo \ camlinternalOO.cmo $(P)oo.cmo camlinternalMod.cmo \ @@ -57,6 +62,7 @@ OTHERS=$(P)seq.cmo $(P)char.cmo $(P)uchar.cmo $(P)sys.cmo $(P)list.cmo \ $(P)spacetime.cmo $(P)bigarray.cmo PREFIXED_OBJS=$(filter stdlib__%.cmo,$(OBJS)) +UNPREFIXED_OBJS=$(PREFIXED_OBJS:stdlib__%.cmo=%) .PHONY: all all: stdlib.cma std_exit.cmo camlheader target_camlheader camlheader_ur @@ -75,8 +81,9 @@ else PROFILINGTARGET = noprof endif -.PHONY: allopt +.PHONY: allopt opt.opt # allopt and opt.opt are synonyms allopt: stdlib.cmxa std_exit.cmx allopt-$(PROFILINGTARGET) +opt.opt: allopt .PHONY: allopt-noprof allopt-noprof: @@ -85,28 +92,35 @@ allopt-noprof: allopt-prof: stdlib.p.cmxa std_exit.p.cmx rm -f std_exit.p.cmi +LEGACY_OBJS=$(patsubst stdlib__%,"$(INSTALL_LIBDIR)/%", \ + $(filter stdlib__%,$(OBJS))) .PHONY: install install:: # Transitional: when upgrading from 4.06 -> 4.07, module M is in stdlib__m.cm*, # while previously it was in m.cm*, which confuses the compiler. - rm -f $(patsubst stdlib__%,"$(INSTALL_LIBDIR)/%", $(filter stdlib__%,$(OBJS))) + rm -f $(LEGACY_OBJS) # Remove "old" pervasives.* and bigarray.* to avoid getting confused with the # Stdlib versions. rm -f "$(INSTALL_LIBDIR)/pervasives.*" "$(INSTALL_LIBDIR)/bigarray.*" # End transitional $(INSTALL_DATA) \ - stdlib.cma std_exit.cmo *.cmi *.cmt *.cmti *.mli *.ml camlheader_ur \ + stdlib.cma std_exit.cmo *.cmi camlheader_ur \ + "$(INSTALL_LIBDIR)" +ifeq "$(INSTALL_SOURCE_ARTIFACTS)" "true" + $(INSTALL_DATA) \ + *.cmt *.cmti *.mli *.ml \ "$(INSTALL_LIBDIR)" +endif $(INSTALL_DATA) target_camlheader "$(INSTALL_LIBDIR)/camlheader" ifeq "$(RUNTIMED)" "true" install:: - $(INSTALL_DATA) target_camlheaderd $(INSTALL_LIBDIR) + $(INSTALL_DATA) target_camlheaderd "$(INSTALL_LIBDIR)" endif ifeq "$(RUNTIMEI)" "true" install:: - $(INSTALL_DATA) target_camlheaderi $(INSTALL_LIBDIR) + $(INSTALL_DATA) target_camlheaderi "$(INSTALL_LIBDIR)" endif .PHONY: installopt @@ -141,7 +155,7 @@ CAMLHEADERS =\ camlheaderi target_camlheaderi ifeq "$(HASHBANGSCRIPTS)" "true" -$(CAMLHEADERS): ../config/Makefile +$(CAMLHEADERS): $(ROOTDIR)/Makefile.config for suff in '' d i; do \ echo '#!$(BINDIR)/ocamlrun'$$suff > camlheader$$suff && \ echo '#!$(TARGET_BINDIR)/ocamlrun'$$suff >target_camlheader$$suff; \ @@ -149,17 +163,17 @@ $(CAMLHEADERS): ../config/Makefile echo '#!' | tr -d '\012' > camlheader_ur; else # Hashbang scripts not supported -$(CAMLHEADERS): $(HEADERPROGRAM) ../config/Makefile +$(CAMLHEADERS): $(HEADERPROGRAM) $(ROOTDIR)/Makefile.config ifeq "$(UNIX_OR_WIN32)" "unix" $(CAMLHEADERS): for suff in '' d i; do \ - $(CC) $(CFLAGS) $(CPPFLAGS) -I../byterun $(LDFLAGS) \ + $(CC) $(OC_CFLAGS) $(OC_CPPFLAGS) $(OC_LDFLAGS) \ -DRUNTIME_NAME='"$(BINDIR)/ocamlrun'$$suff'"' \ header.c $(OUTPUTEXE)tmpheader$(EXE) && \ strip tmpheader$(EXE) && \ mv tmpheader$(EXE) camlheader$$suff && \ - $(CC) $(CFLAGS) $(CPPFLAGS) -I../byterun $(LDFLAGS) \ + $(CC) $(OC_CFLAGS) $(OC_CPPFLAGS) $(OC_LDFLAGS) \ -DRUNTIME_NAME='"$(TARGET_BINDIR)/ocamlrun'$$suff'"' \ header.c $(OUTPUTEXE)tmpheader$(EXE) && \ strip tmpheader$(EXE) && \ @@ -173,7 +187,7 @@ else # Windows # with those above camlheader: headernt.c - $(CC) -c $(CFLAGS) $(CPPFLAGS) -I../byterun \ + $(CC) -c $(OC_CFLAGS) $(OC_CPPFLAGS) \ -DRUNTIME_NAME='"ocamlrun"' $(OUTPUTOBJ)headernt.$(O) $< $(MKEXE) -o tmpheader.exe headernt.$(O) $(EXTRALIBS) rm -f camlheader.exe @@ -186,7 +200,7 @@ camlheader_ur: camlheader cp camlheader camlheader_ur camlheaderd: headernt.c - $(CC) -c $(CFLAGS) $(CPPFLAGS) -I../byterun \ + $(CC) -c $(OC_CFLAGS) $(OC_CPPFLAGS) \ -DRUNTIME_NAME='"ocamlrund"' $(OUTPUTOBJ)headerntd.$(O) $< $(MKEXE) -o tmpheaderd.exe headerntd.$(O) $(EXTRALIBS) mv tmpheaderd.exe camlheaderd @@ -195,7 +209,7 @@ target_camlheaderd: camlheaderd cp camlheaderd target_camlheaderd camlheaderi: headernt.c - $(CC) -c $(CFLAGS) $(CPPFLAGS) -I../byterun \ + $(CC) -c $(OC_CFLAGS) $(OC_CPPFLAGS) \ -DRUNTIME_NAME='"ocamlruni"' $(OUTPUTOBJ)headernti.$(O) $< $(MKEXE) -o tmpheaderi.exe headernti.$(O) $(EXTRALIBS) mv tmpheaderi.exe camlheaderi @@ -219,8 +233,8 @@ stdlib.cmxa: $(OBJS:.cmo=.cmx) stdlib.p.cmxa: $(OBJS:.cmo=.p.cmx) $(CAMLOPT) -a -o $@ $^ -sys.ml: sys.mlp ../VERSION - sed -e "s|%%VERSION%%|`sed -e 1q ../VERSION | tr -d '\r'`|" sys.mlp > $@ +sys.ml: $(ROOTDIR)/VERSION sys.mlp + sed -e "s|%%VERSION%%|`sed -e 1q $< | tr -d '\r'`|" sys.mlp > $@ .PHONY: clean clean:: @@ -267,7 +281,8 @@ $(OBJS:.cmo=.cmi) std_exit.cmi: $(COMPILER_DEPS) $(OBJS:.cmo=.cmx) std_exit.cmx: $(OPTCOMPILER) $(OBJS:.cmo=.p.cmx) std_exit.p.cmx: $(OPTCOMPILER) -# Dependencies on Stdlib (not tracked by ocamldep) +# Dependencies on Stdlib (not tracked by ocamlc -depend) + $(OTHERS) std_exit.cmo: stdlib.cmi $(OTHERS:.cmo=.cmi) std_exit.cmi: stdlib.cmi $(OBJS:.cmo=.cmx) std_exit.cmx: stdlib.cmi @@ -290,15 +305,16 @@ SPACE := $(EMPTY) $(EMPTY) # it looks for the .cmx file (not .p.cmx). .PHONY: depend depend: - $(CAMLDEP) -slash $(filter-out stdlib.%,$(wildcard *.mli *.ml)) \ + $(CAMLDEP) $(DEPFLAGS) $(filter-out stdlib.%,$(wildcard *.mli *.ml)) \ > .depend.tmp - $(CAMLDEP) -slash -pp "$(AWK) -f remove_module_aliases.awk" \ + $(CAMLDEP) $(DEPFLAGS) -pp "$(AWK) -f remove_module_aliases.awk" \ stdlib.ml stdlib.mli >> .depend.tmp - $(CAMLDEP) -slash $(filter-out stdlib.%,$(wildcard *.ml)) \ + $(CAMLDEP) $(DEPFLAGS) $(filter-out stdlib.%,$(wildcard *.ml)) \ | sed -e 's/\.cmx : /.p.cmx : /g' >>.depend.tmp - $(CAMLDEP) -slash -pp "$(AWK) -f remove_module_aliases.awk" stdlib.ml \ + $(CAMLDEP) $(DEPFLAGS) -pp "$(AWK) -f remove_module_aliases.awk" \ + stdlib.ml \ | sed -e 's/\.cmx : /.p.cmx : /g' >> .depend.tmp sed -Ee \ - 's#(^| )(${subst ${SPACE},|,${PREFIXED_OBJS:stdlib__%.cmo=%}})[.]#\1stdlib__\2.#g' \ + 's#(^| )(${subst ${SPACE},|,${UNPREFIXED_OBJS}})[.]#\1stdlib__\2.#g' \ .depend.tmp > .depend rm -f .depend.tmp diff --git a/stdlib/Makefile.nt b/stdlib/Makefile.nt deleted file mode 100644 index ed9900bb..00000000 --- a/stdlib/Makefile.nt +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include Makefile diff --git a/stdlib/StdlibModules b/stdlib/StdlibModules index 490c78cd..a8ee625a 100644 --- a/stdlib/StdlibModules +++ b/stdlib/StdlibModules @@ -26,6 +26,7 @@ STDLIB_MODULES=\ $(P)array \ $(P)arrayLabels \ $(P)bigarray \ + $(P)bool \ $(P)buffer \ $(P)bytes \ $(P)bytesLabels \ @@ -42,9 +43,11 @@ STDLIB_MODULES=\ $(P)filename \ $(P)float \ $(P)format \ + $(P)fun \ $(P)gc \ $(P)genlex \ $(P)hashtbl \ + $(P)int \ $(P)int32 \ $(P)int64 \ $(P)lazy \ @@ -57,15 +60,17 @@ STDLIB_MODULES=\ $(P)nativeint \ $(P)obj \ $(P)oo \ + $(P)option \ $(P)parsing \ + $(P)pervasives \ $(P)printexc \ $(P)printf \ $(P)queue \ $(P)random \ + $(P)result \ $(P)scanf \ $(P)seq \ $(P)set \ - $(P)sort \ $(P)stack \ $(P)stdLabels \ stdlib \ @@ -74,4 +79,5 @@ STDLIB_MODULES=\ $(P)stringLabels \ $(P)sys \ $(P)uchar \ + $(P)unit \ $(P)weak diff --git a/stdlib/arg.ml b/stdlib/arg.ml index eb06f795..64e63d77 100644 --- a/stdlib/arg.ml +++ b/stdlib/arg.ml @@ -38,8 +38,8 @@ type spec = function with each remaining argument *) | Expand of (string -> string array) (* If the remaining arguments to process are of the form - [["-foo"; "arg"] @ rest] where "foo" is - registered as [Expand f], then the + [["-foo"; "arg"] @ rest] where "foo" + is registered as [Expand f], then the arguments [f "arg" @ rest] are processed. Only allowed in [parse_and_expand_argv_dynamic]. *) @@ -129,7 +129,8 @@ let float_of_string_opt x = try Some (float_of_string x) with Failure _ -> None -let parse_and_expand_argv_dynamic_aux allow_expand current argv speclist anonfun errmsg = +let parse_and_expand_argv_dynamic_aux allow_expand current argv speclist anonfun + errmsg = let initpos = !current in let convert_error error = (* convert an internal error to a Bad/Help exception @@ -137,7 +138,8 @@ let parse_and_expand_argv_dynamic_aux allow_expand current argv speclist anonfun to an user-raised Bad exception. *) let b = Buffer.create 200 in - let progname = if initpos < (Array.length !argv) then !argv.(initpos) else "(?)" in + let progname = + if initpos < (Array.length !argv) then !argv.(initpos) else "(?)" in begin match error with | Unknown "-help" -> () | Unknown "--help" -> () @@ -186,7 +188,7 @@ let parse_and_expand_argv_dynamic_aux allow_expand current argv speclist anonfun | Some _ -> () in let rec treat_action = function - | Unit f -> f (); + | Unit f -> no_arg (); f (); | Bool f -> let arg = get_arg () in begin match bool_of_string_opt arg with @@ -241,20 +243,25 @@ let parse_and_expand_argv_dynamic_aux allow_expand current argv speclist anonfun end; consume_arg (); | Tuple specs -> + no_arg (); List.iter treat_action specs; | Rest f -> + no_arg (); while !current < (Array.length !argv) - 1 do f !argv.(!current + 1); consume_arg (); done; | Expand f -> if not allow_expand then - raise (Invalid_argument "Arg.Expand is is only allowed with Arg.parse_and_expand_argv_dynamic"); + raise (Invalid_argument "Arg.Expand is is only allowed with \ + Arg.parse_and_expand_argv_dynamic"); let arg = get_arg () in let newarg = f arg in consume_arg (); let before = Array.sub !argv 0 (!current + 1) - and after = Array.sub !argv (!current + 1) ((Array.length !argv) - !current - 1) in + and after = + Array.sub !argv (!current + 1) + ((Array.length !argv) - !current - 1) in argv:= Array.concat [before;newarg;after]; in treat_action action end @@ -269,7 +276,8 @@ let parse_and_expand_argv_dynamic current argv speclist anonfun errmsg = parse_and_expand_argv_dynamic_aux true current argv speclist anonfun errmsg let parse_argv_dynamic ?(current=current) argv speclist anonfun errmsg = - parse_and_expand_argv_dynamic_aux false current (ref argv) speclist anonfun errmsg + parse_and_expand_argv_dynamic_aux false current (ref argv) speclist anonfun + errmsg let parse_argv ?(current=current) argv speclist anonfun errmsg = diff --git a/stdlib/arg.mli b/stdlib/arg.mli index 6b6ee9e4..3f3116c5 100644 --- a/stdlib/arg.mli +++ b/stdlib/arg.mli @@ -61,8 +61,8 @@ type spec = function with each remaining argument *) | Expand of (string -> string array) (** If the remaining arguments to process are of the form - [["-foo"; "arg"] @ rest] where "foo" is - registered as [Expand f], then the + [["-foo"; "arg"] @ rest] where "foo" + is registered as [Expand f], then the arguments [f "arg" @ rest] are processed. Only allowed in [parse_and_expand_argv_dynamic]. *) @@ -189,8 +189,8 @@ val read_arg: string -> string array @since 4.05.0 *) val read_arg0: string -> string array -(** Identical to {!Arg.read_arg} but assumes null character terminated command line - arguments. +(** Identical to {!Arg.read_arg} but assumes null character terminated command + line arguments. @since 4.05.0 *) diff --git a/stdlib/array.ml b/stdlib/array.ml index a693f4a7..a1b9663f 100644 --- a/stdlib/array.ml +++ b/stdlib/array.ml @@ -13,6 +13,9 @@ (* *) (**************************************************************************) +(* An alias for the type of arrays. *) +type 'a t = 'a array + (* Array operations *) external length : 'a array -> int = "%array_length" @@ -303,7 +306,7 @@ let stable_sort cmp a = let fast_sort = stable_sort -(** {6 Iterators} *) +(** {1 Iterators} *) let to_seq a = let rec aux i () = diff --git a/stdlib/array.mli b/stdlib/array.mli index 0a9e7f3f..6e3d4053 100644 --- a/stdlib/array.mli +++ b/stdlib/array.mli @@ -13,6 +13,9 @@ (* *) (**************************************************************************) +type 'a t = 'a array +(** An alias for the type of arrays. *) + (** Array operations. *) external length : 'a array -> int = "%array_length" @@ -24,7 +27,7 @@ external get : 'a array -> int -> 'a = "%array_safe_get" The last element has number [Array.length a - 1]. You can also write [a.(n)] instead of [Array.get a n]. - Raise [Invalid_argument "index out of bounds"] + Raise [Invalid_argument] if [n] is outside the range 0 to [(Array.length a - 1)]. *) external set : 'a array -> int -> 'a -> unit = "%array_safe_set" @@ -32,7 +35,7 @@ external set : 'a array -> int -> 'a -> unit = "%array_safe_set" element number [n] with [x]. You can also write [a.(n) <- x] instead of [Array.set a n x]. - Raise [Invalid_argument "index out of bounds"] + Raise [Invalid_argument] if [n] is outside the range 0 to [Array.length a - 1]. *) external make : int -> 'a -> 'a array = "caml_make_vect" @@ -90,7 +93,10 @@ val create_matrix : int -> int -> 'a -> 'a array array val append : 'a array -> 'a array -> 'a array (** [Array.append v1 v2] returns a fresh array containing the - concatenation of the arrays [v1] and [v2]. *) + concatenation of the arrays [v1] and [v2]. + + Raise [Invalid_argument] if + [Array.length v1 + Array.length v2 > Sys.max_array_length]. *) val concat : 'a array list -> 'a array (** Same as {!Array.append}, but concatenates a list of arrays. *) @@ -100,7 +106,7 @@ val sub : 'a array -> int -> int -> 'a array containing the elements number [start] to [start + len - 1] of array [a]. - Raise [Invalid_argument "Array.sub"] if [start] and [len] do not + Raise [Invalid_argument] if [start] and [len] do not designate a valid subarray of [a]; that is, if [start < 0], or [len < 0], or [start + len > Array.length a]. *) @@ -112,7 +118,7 @@ val fill : 'a array -> int -> int -> 'a -> unit (** [Array.fill a ofs len x] modifies the array [a] in place, storing [x] in elements number [ofs] to [ofs + len - 1]. - Raise [Invalid_argument "Array.fill"] if [ofs] and [len] do not + Raise [Invalid_argument] if [ofs] and [len] do not designate a valid subarray of [a]. *) val blit : 'a array -> int -> 'a array -> int -> int -> unit @@ -122,7 +128,7 @@ val blit : 'a array -> int -> 'a array -> int -> int -> unit [v1] and [v2] are the same array, and the source and destination chunks overlap. - Raise [Invalid_argument "Array.blit"] if [o1] and [len] do not + Raise [Invalid_argument] if [o1] and [len] do not designate a valid subarray of [v1], or if [o2] and [len] do not designate a valid subarray of [v2]. *) @@ -131,7 +137,10 @@ val to_list : 'a array -> 'a list val of_list : 'a list -> 'a array (** [Array.of_list l] returns a fresh array containing the elements - of [l]. *) + of [l]. + + Raise [Invalid_argument] if the length of [l] is greater than + [Sys.max_array_length].*) (** {1 Iterators} *) @@ -201,13 +210,14 @@ val exists : ('a -> bool) -> 'a array -> bool @since 4.03.0 *) val mem : 'a -> 'a array -> bool -(** [mem a l] is true if and only if [a] is equal - to an element of [l]. - @since 4.03.0 *) +(** [mem a l] is true if and only if [a] is structurally equal + to an element of [l] (i.e. there is an [x] in [l] such that + [compare a x = 0]). + @since 4.03.0 *) val memq : 'a -> 'a array -> bool (** Same as {!Array.mem}, but uses physical equality instead of structural - equality to compare array elements. + equality to compare elements. @since 4.03.0 *) @@ -219,9 +229,8 @@ val sort : ('a -> 'a -> int) -> 'a array -> unit function. The comparison function must return 0 if its arguments compare as equal, a positive integer if the first is greater, and a negative integer if the first is smaller (see below for a - complete specification). For example, {!Pervasives.compare} is - a suitable comparison function, provided there are no floating-point - NaN values in the data. After calling [Array.sort], the + complete specification). For example, {!Stdlib.compare} is + a suitable comparison function. After calling [Array.sort], the array is sorted in place in increasing order. [Array.sort] is guaranteed to run in constant heap space and (at most) logarithmic stack space. @@ -231,7 +240,7 @@ val sort : ('a -> 'a -> int) -> 'a array -> unit Specification of the comparison function: Let [a] be the array and [cmp] the comparison function. The following - must be true for all x, y, z in a : + must be true for all [x], [y], [z] in [a] : - [cmp x y] > 0 if and only if [cmp y x] < 0 - if [cmp x y] >= 0 and [cmp y z] >= 0 then [cmp x z] >= 0 @@ -245,8 +254,8 @@ val stable_sort : ('a -> 'a -> int) -> 'a array -> unit elements that compare equal are kept in their original order) and not guaranteed to run in constant heap space. - The current implementation uses Merge Sort. It uses [n/2] - words of heap space, where [n] is the length of the array. + The current implementation uses Merge Sort. It uses a temporary + array of length [n/2], where [n] is the length of the array. It is usually faster than the current implementation of {!Array.sort}. *) @@ -256,7 +265,7 @@ val fast_sort : ('a -> 'a -> int) -> 'a array -> unit *) -(** {6 Iterators} *) +(** {1 Iterators} *) val to_seq : 'a array -> 'a Seq.t (** Iterate on the array, in increasing order. Modifications of the diff --git a/stdlib/arrayLabels.mli b/stdlib/arrayLabels.mli index 2ecf4dd2..df84a7d3 100644 --- a/stdlib/arrayLabels.mli +++ b/stdlib/arrayLabels.mli @@ -13,6 +13,9 @@ (* *) (**************************************************************************) +type 'a t = 'a array +(** An alias for the type of arrays. *) + (** Array operations. *) external length : 'a array -> int = "%array_length" @@ -158,7 +161,7 @@ val fold_right : f:('b -> 'a -> 'a) -> 'b array -> init:'a -> 'a where [n] is the length of the array [a]. *) -(** {6 Iterators on two arrays} *) +(** {1 Iterators on two arrays} *) val iter2 : f:('a -> 'b -> unit) -> 'a array -> 'b array -> unit @@ -175,7 +178,7 @@ val map2 : f:('a -> 'b -> 'c) -> 'a array -> 'b array -> 'c array @since 4.05.0 *) -(** {6 Array scanning} *) +(** {1 Array scanning} *) val exists : f:('a -> bool) -> 'a array -> bool @@ -219,7 +222,7 @@ val sort : cmp:('a -> 'a -> int) -> 'a array -> unit function. The comparison function must return 0 if its arguments compare as equal, a positive integer if the first is greater, and a negative integer if the first is smaller (see below for a - complete specification). For example, {!Pervasives.compare} is + complete specification). For example, {!Stdlib.compare} is a suitable comparison function, provided there are no floating-point NaN values in the data. After calling [Array.sort], the array is sorted in place in increasing order. @@ -256,7 +259,7 @@ val fast_sort : cmp:('a -> 'a -> int) -> 'a array -> unit *) -(** {6 Iterators} *) +(** {1 Iterators} *) val to_seq : 'a array -> 'a Seq.t (** Iterate on the array, in increasing order diff --git a/stdlib/bigarray.mli b/stdlib/bigarray.mli index 39433dde..2c126121 100644 --- a/stdlib/bigarray.mli +++ b/stdlib/bigarray.mli @@ -16,35 +16,35 @@ (** Large, multi-dimensional, numerical arrays. This module implements multi-dimensional arrays of integers and - floating-point numbers, thereafter referred to as 'big arrays', + floating-point numbers, thereafter referred to as 'Bigarrays', to distinguish them from the standard OCaml arrays described in {!module:Array}. The implementation allows efficient sharing of large numerical arrays between OCaml code and C or Fortran numerical libraries. - The main differences between 'big arrays' and standard OCaml + The main differences between 'Bigarrays' and standard OCaml arrays are as follows: - - Big arrays are not limited in size, unlike OCaml arrays. + - Bigarrays are not limited in size, unlike OCaml arrays. (Normal float arrays are limited to 2,097,151 elements on a 32-bit platform, and normal arrays of other types to 4,194,303 elements.) - - Big arrays are multi-dimensional. Any number of dimensions + - Bigarrays are multi-dimensional. Any number of dimensions between 0 and 16 is supported. In contrast, OCaml arrays are mono-dimensional and require encoding multi-dimensional arrays as arrays of arrays. - - Big arrays can only contain integers and floating-point numbers, + - Bigarrays can only contain integers and floating-point numbers, while OCaml arrays can contain arbitrary OCaml data types. - - Big arrays provide more space-efficient storage of + - Bigarrays provide more space-efficient storage of integer and floating-point elements than normal OCaml arrays, in particular because they support 'small' types such as single-precision floats and 8 and 16-bit integers, in addition to the standard OCaml types of double-precision floats and 32 and 64-bit integers. - - The memory layout of big arrays is entirely compatible with that + - The memory layout of Bigarrays is entirely compatible with that of arrays in C and Fortran, allowing large arrays to be passed back and forth between OCaml code and C / Fortran code with no data copying at all. - - Big arrays support interesting high-level operations that normal + - Bigarrays support interesting high-level operations that normal arrays do not provide efficiently, such as extracting sub-arrays and 'slicing' a multi-dimensional array along certain dimensions, all without any copying. @@ -53,17 +53,17 @@ source, then refer to array types and operations via short dot notation, e.g. [Array1.t] or [Array2.sub]. - Big arrays support all the OCaml ad-hoc polymorphic operations: - - comparisons ([=], [<>], [<=], etc, as well as {!Pervasives.compare}); + Bigarrays support all the OCaml ad-hoc polymorphic operations: + - comparisons ([=], [<>], [<=], etc, as well as {!Stdlib.compare}); - hashing (module [Hash]); - and structured input-output (the functions from the - {!Marshal} module, as well as {!Pervasives.output_value} - and {!Pervasives.input_value}). + {!Marshal} module, as well as {!Stdlib.output_value} + and {!Stdlib.input_value}). *) (** {1 Element kinds} *) -(** Big arrays can contain elements of the following kinds: +(** Bigarrays can contain elements of the following kinds: - IEEE single precision (32 bits) floating-point numbers ({!Bigarray.float32_elt}), - IEEE double precision (64 bits) floating-point numbers @@ -118,18 +118,18 @@ type ('a, 'b) kind = | Complex64 : (Complex.t, complex64_elt) kind | Char : (char, int8_unsigned_elt) kind (**) (** To each element kind is associated an OCaml type, which is - the type of OCaml values that can be stored in the big array + the type of OCaml values that can be stored in the Bigarray or read back from it. This type is not necessarily the same as the type of the array elements proper: for instance, - a big array whose elements are of kind [float32_elt] contains + a Bigarray whose elements are of kind [float32_elt] contains 32-bit single precision floats, but reading or writing one of its elements from OCaml uses the OCaml type [float], which is 64-bit double precision floats. The GADT type [('a, 'b) kind] captures this association - of an OCaml type ['a] for values read or written in the big array, + of an OCaml type ['a] for values read or written in the Bigarray, and of an element kind ['b] which represents the actual contents - of the big array. Its constructors list all possible associations + of the Bigarray. Its constructors list all possible associations of OCaml types with element kinds, and are re-exported below for backward-compatibility reasons. @@ -187,16 +187,16 @@ val nativeint : (nativeint, nativeint_elt) kind val char : (char, int8_unsigned_elt) kind (** As shown by the types of the values above, - big arrays of kind [float32_elt] and [float64_elt] are - accessed using the OCaml type [float]. Big arrays of complex kinds + Bigarrays of kind [float32_elt] and [float64_elt] are + accessed using the OCaml type [float]. Bigarrays of complex kinds [complex32_elt], [complex64_elt] are accessed with the OCaml type - {!Complex.t}. Big arrays of + {!Complex.t}. Bigarrays of integer kinds are accessed using the smallest OCaml integer type large enough to represent the array elements: - [int] for 8- and 16-bit integer bigarrays, as well as OCaml-integer - bigarrays; [int32] for 32-bit integer bigarrays; [int64] - for 64-bit integer bigarrays; and [nativeint] for - platform-native integer bigarrays. Finally, big arrays of + [int] for 8- and 16-bit integer Bigarrays, as well as OCaml-integer + Bigarrays; [int32] for 32-bit integer Bigarrays; [int64] + for 64-bit integer Bigarrays; and [nativeint] for + platform-native integer Bigarrays. Finally, Bigarrays of kind [int8_unsigned_elt] can also be accessed as arrays of characters instead of arrays of small integers, by using the kind value [char] instead of [int8_unsigned]. *) @@ -214,7 +214,7 @@ type c_layout = C_layout_typ (**) type fortran_layout = Fortran_layout_typ (**) (** To facilitate interoperability with existing C and Fortran code, - this library supports two different memory layouts for big arrays, + this library supports two different memory layouts for Bigarrays, one compatible with the C conventions, the other compatible with the Fortran conventions. @@ -256,7 +256,7 @@ val fortran_layout : fortran_layout layout module Genarray : sig type ('a, 'b, 'c) t - (** The type [Genarray.t] is the type of big arrays with variable + (** The type [Genarray.t] is the type of Bigarrays with variable numbers of dimensions. Any number of dimensions between 0 and 16 is supported. @@ -271,27 +271,27 @@ module Genarray : ([c_layout] or [fortran_layout]). For instance, [(float, float32_elt, fortran_layout) Genarray.t] - is the type of generic big arrays containing 32-bit floats + is the type of generic Bigarrays containing 32-bit floats in Fortran layout; reads and writes in this array use the OCaml type [float]. *) external create: ('a, 'b) kind -> 'c layout -> int array -> ('a, 'b, 'c) t = "caml_ba_create" - (** [Genarray.create kind layout dimensions] returns a new big array + (** [Genarray.create kind layout dimensions] returns a new Bigarray whose element kind is determined by the parameter [kind] (one of [float32], [float64], [int8_signed], etc) and whose layout is determined by the parameter [layout] (one of [c_layout] or [fortran_layout]). The [dimensions] parameter is an array of - integers that indicate the size of the big array in each dimension. + integers that indicate the size of the Bigarray in each dimension. The length of [dimensions] determines the number of dimensions - of the bigarray. + of the Bigarray. For instance, [Genarray.create int32 c_layout [|4;6;8|]] - returns a fresh big array of 32-bit integers, in C layout, + returns a fresh Bigarray of 32-bit integers, in C layout, having three dimensions, the three dimensions being 4, 6 and 8 respectively. - Big arrays returned by [Genarray.create] are not initialized: + Bigarrays returned by [Genarray.create] are not initialized: the initial values of array elements is unspecified. [Genarray.create] raises [Invalid_argument] if the number of dimensions @@ -299,29 +299,29 @@ module Genarray : is negative. *) external num_dims: ('a, 'b, 'c) t -> int = "caml_ba_num_dims" - (** Return the number of dimensions of the given big array. *) + (** Return the number of dimensions of the given Bigarray. *) val dims : ('a, 'b, 'c) t -> int array - (** [Genarray.dims a] returns all dimensions of the big array [a], + (** [Genarray.dims a] returns all dimensions of the Bigarray [a], as an array of integers of length [Genarray.num_dims a]. *) external nth_dim: ('a, 'b, 'c) t -> int -> int = "caml_ba_dim" (** [Genarray.nth_dim a n] returns the [n]-th dimension of the - big array [a]. The first dimension corresponds to [n = 0]; + Bigarray [a]. The first dimension corresponds to [n = 0]; the second dimension corresponds to [n = 1]; the last dimension, to [n = Genarray.num_dims a - 1]. Raise [Invalid_argument] if [n] is less than 0 or greater or equal than [Genarray.num_dims a]. *) external kind: ('a, 'b, 'c) t -> ('a, 'b) kind = "caml_ba_kind" - (** Return the kind of the given big array. *) + (** Return the kind of the given Bigarray. *) external layout: ('a, 'b, 'c) t -> 'c layout = "caml_ba_layout" - (** Return the layout of the given big array. *) + (** Return the layout of the given Bigarray. *) external change_layout: ('a, 'b, 'c) t -> 'd layout -> ('a, 'b, 'd) t = "caml_ba_change_layout" - (** [Genarray.change_layout a layout] returns a bigarray with the + (** [Genarray.change_layout a layout] returns a Bigarray with the specified [layout], sharing the data with [a] (and hence having the same dimensions as [a]). No copying of elements is involved: the new array and the original array share the same storage space. @@ -338,7 +338,7 @@ module Genarray : @since 4.03.0 *) external get: ('a, 'b, 'c) t -> int array -> 'a = "caml_ba_get_generic" - (** Read an element of a generic big array. + (** Read an element of a generic Bigarray. [Genarray.get a [|i1; ...; iN|]] returns the element of [a] whose coordinates are [i1] in the first dimension, [i2] in the second dimension, ..., [iN] in the [N]-th dimension. @@ -358,7 +358,7 @@ module Genarray : external set: ('a, 'b, 'c) t -> int array -> 'a -> unit = "caml_ba_set_generic" - (** Assign an element of a generic big array. + (** Assign an element of a generic Bigarray. [Genarray.set a [|i1; ...; iN|] v] stores the value [v] in the element of [a] whose coordinates are [i1] in the first dimension, [i2] in the second dimension, ..., [iN] in the [N]-th dimension. @@ -376,9 +376,9 @@ module Genarray : external sub_left: ('a, 'b, c_layout) t -> int -> int -> ('a, 'b, c_layout) t = "caml_ba_sub" - (** Extract a sub-array of the given big array by restricting the + (** Extract a sub-array of the given Bigarray by restricting the first (left-most) dimension. [Genarray.sub_left a ofs len] - returns a big array with the same number of dimensions as [a], + returns a Bigarray with the same number of dimensions as [a], and the same dimensions as [a], except the first dimension, which corresponds to the interval [[ofs ... ofs + len - 1]] of the first dimension of [a]. No copying of elements is @@ -388,7 +388,7 @@ module Genarray : element at coordinates [[|i1+ofs; ...; iN|]] of the original array [a]. - [Genarray.sub_left] applies only to big arrays in C layout. + [Genarray.sub_left] applies only to Bigarrays in C layout. Raise [Invalid_argument] if [ofs] and [len] do not designate a valid sub-array of [a], that is, if [ofs < 0], or [len < 0], or [ofs + len > Genarray.nth_dim a 0]. *) @@ -396,9 +396,9 @@ module Genarray : external sub_right: ('a, 'b, fortran_layout) t -> int -> int -> ('a, 'b, fortran_layout) t = "caml_ba_sub" - (** Extract a sub-array of the given big array by restricting the + (** Extract a sub-array of the given Bigarray by restricting the last (right-most) dimension. [Genarray.sub_right a ofs len] - returns a big array with the same number of dimensions as [a], + returns a Bigarray with the same number of dimensions as [a], and the same dimensions as [a], except the last dimension, which corresponds to the interval [[ofs ... ofs + len - 1]] of the last dimension of [a]. No copying of elements is @@ -408,7 +408,7 @@ module Genarray : element at coordinates [[|i1; ...; iN+ofs|]] of the original array [a]. - [Genarray.sub_right] applies only to big arrays in Fortran layout. + [Genarray.sub_right] applies only to Bigarrays in Fortran layout. Raise [Invalid_argument] if [ofs] and [len] do not designate a valid sub-array of [a], that is, if [ofs < 1], or [len < 0], or [ofs + len > Genarray.nth_dim a (Genarray.num_dims a - 1)]. *) @@ -416,7 +416,7 @@ module Genarray : external slice_left: ('a, 'b, c_layout) t -> int array -> ('a, 'b, c_layout) t = "caml_ba_slice" - (** Extract a sub-array of lower dimension from the given big array + (** Extract a sub-array of lower dimension from the given Bigarray by fixing one or several of the first (left-most) coordinates. [Genarray.slice_left a [|i1; ... ; iM|]] returns the 'slice' of [a] obtained by setting the first [M] coordinates to @@ -427,14 +427,14 @@ module Genarray : array [a]. No copying of elements is involved: the slice and the original array share the same storage space. - [Genarray.slice_left] applies only to big arrays in C layout. + [Genarray.slice_left] applies only to Bigarrays in C layout. Raise [Invalid_argument] if [M >= N], or if [[|i1; ... ; iM|]] is outside the bounds of [a]. *) external slice_right: ('a, 'b, fortran_layout) t -> int array -> ('a, 'b, fortran_layout) t = "caml_ba_slice" - (** Extract a sub-array of lower dimension from the given big array + (** Extract a sub-array of lower dimension from the given Bigarray by fixing one or several of the last (right-most) coordinates. [Genarray.slice_right a [|i1; ... ; iM|]] returns the 'slice' of [a] obtained by setting the last [M] coordinates to @@ -445,13 +445,13 @@ module Genarray : array [a]. No copying of elements is involved: the slice and the original array share the same storage space. - [Genarray.slice_right] applies only to big arrays in Fortran layout. + [Genarray.slice_right] applies only to Bigarrays in Fortran layout. Raise [Invalid_argument] if [M >= N], or if [[|i1; ... ; iM|]] is outside the bounds of [a]. *) external blit: ('a, 'b, 'c) t -> ('a, 'b, 'c) t -> unit = "caml_ba_blit" - (** Copy all elements of a big array in another big array. + (** Copy all elements of a Bigarray in another Bigarray. [Genarray.blit src dst] copies all elements of [src] into [dst]. Both arrays [src] and [dst] must have the same number of dimensions and equal dimensions. Copying a sub-array of [src] @@ -459,9 +459,9 @@ module Genarray : to sub-array or slices of [src] and [dst]. *) external fill: ('a, 'b, 'c) t -> 'a -> unit = "caml_ba_fill" - (** Set all elements of a big array to a given value. + (** Set all elements of a Bigarray to a given value. [Genarray.fill a v] stores the value [v] in all elements of - the big array [a]. Setting only some elements of [a] to [v] + the Bigarray [a]. Setting only some elements of [a] to [v] can be achieved by applying [Genarray.fill] to a sub-array or a slice of [a]. *) end @@ -476,22 +476,22 @@ module Genarray : @since 4.05.0 *) module Array0 : sig type ('a, 'b, 'c) t - (** The type of zero-dimensional big arrays whose elements have + (** The type of zero-dimensional Bigarrays whose elements have OCaml type ['a], representation kind ['b], and memory layout ['c]. *) val create: ('a, 'b) kind -> 'c layout -> ('a, 'b, 'c) t - (** [Array0.create kind layout] returns a new bigarray of zero dimension. + (** [Array0.create kind layout] returns a new Bigarray of zero dimension. [kind] and [layout] determine the array element kind and the array layout as described for {!Genarray.create}. *) external kind: ('a, 'b, 'c) t -> ('a, 'b) kind = "caml_ba_kind" - (** Return the kind of the given big array. *) + (** Return the kind of the given Bigarray. *) external layout: ('a, 'b, 'c) t -> 'c layout = "caml_ba_layout" - (** Return the layout of the given big array. *) + (** Return the layout of the given Bigarray. *) val change_layout: ('a, 'b, 'c) t -> 'd layout -> ('a, 'b, 'd) t - (** [Array0.change_layout a layout] returns a big array with the + (** [Array0.change_layout a layout] returns a Bigarray with the specified [layout], sharing the data with [a]. No copying of elements is involved: the new array and the original array share the same storage space. @@ -509,15 +509,15 @@ module Array0 : sig (** [Array0.set a x v] stores the value [v] in [a]. *) external blit: ('a, 'b, 'c) t -> ('a, 'b, 'c) t -> unit = "caml_ba_blit" - (** Copy the first big array to the second big array. + (** Copy the first Bigarray to the second Bigarray. See {!Genarray.blit} for more details. *) external fill: ('a, 'b, 'c) t -> 'a -> unit = "caml_ba_fill" - (** Fill the given big array with the given value. + (** Fill the given Bigarray with the given value. See {!Genarray.fill} for more details. *) val of_value: ('a, 'b) kind -> 'c layout -> 'a -> ('a, 'b, 'c) t - (** Build a zero-dimensional big array initialized from the + (** Build a zero-dimensional Bigarray initialized from the given value. *) end @@ -534,27 +534,27 @@ end faster operations, and more precise static type-checking. *) module Array1 : sig type ('a, 'b, 'c) t - (** The type of one-dimensional big arrays whose elements have + (** The type of one-dimensional Bigarrays whose elements have OCaml type ['a], representation kind ['b], and memory layout ['c]. *) val create: ('a, 'b) kind -> 'c layout -> int -> ('a, 'b, 'c) t - (** [Array1.create kind layout dim] returns a new bigarray of + (** [Array1.create kind layout dim] returns a new Bigarray of one dimension, whose size is [dim]. [kind] and [layout] determine the array element kind and the array layout as described for {!Genarray.create}. *) external dim: ('a, 'b, 'c) t -> int = "%caml_ba_dim_1" (** Return the size (dimension) of the given one-dimensional - big array. *) + Bigarray. *) external kind: ('a, 'b, 'c) t -> ('a, 'b) kind = "caml_ba_kind" - (** Return the kind of the given big array. *) + (** Return the kind of the given Bigarray. *) external layout: ('a, 'b, 'c) t -> 'c layout = "caml_ba_layout" - (** Return the layout of the given big array. *) + (** Return the layout of the given Bigarray. *) val change_layout: ('a, 'b, 'c) t -> 'd layout -> ('a, 'b, 'd) t - (** [Array1.change_layout a layout] returns a bigarray with the + (** [Array1.change_layout a layout] returns a Bigarray with the specified [layout], sharing the data with [a] (and hence having the same dimension as [a]). No copying of elements is involved: the new array and the original array share the same storage space. @@ -586,27 +586,27 @@ module Array1 : sig external sub: ('a, 'b, 'c) t -> int -> int -> ('a, 'b, 'c) t = "caml_ba_sub" - (** Extract a sub-array of the given one-dimensional big array. + (** Extract a sub-array of the given one-dimensional Bigarray. See {!Genarray.sub_left} for more details. *) val slice: ('a, 'b, 'c) t -> int -> ('a, 'b, 'c) Array0.t (** Extract a scalar (zero-dimensional slice) of the given one-dimensional - big array. The integer parameter is the index of the scalar to + Bigarray. The integer parameter is the index of the scalar to extract. See {!Bigarray.Genarray.slice_left} and {!Bigarray.Genarray.slice_right} for more details. @since 4.05.0 *) external blit: ('a, 'b, 'c) t -> ('a, 'b, 'c) t -> unit = "caml_ba_blit" - (** Copy the first big array to the second big array. + (** Copy the first Bigarray to the second Bigarray. See {!Genarray.blit} for more details. *) external fill: ('a, 'b, 'c) t -> 'a -> unit = "caml_ba_fill" - (** Fill the given big array with the given value. + (** Fill the given Bigarray with the given value. See {!Genarray.fill} for more details. *) val of_array: ('a, 'b) kind -> 'c layout -> 'a array -> ('a, 'b, 'c) t - (** Build a one-dimensional big array initialized from the + (** Build a one-dimensional Bigarray initialized from the given array. *) external unsafe_get: ('a, 'b, 'c) t -> int -> 'a = "%caml_ba_unsafe_ref_1" @@ -631,30 +631,30 @@ end module Array2 : sig type ('a, 'b, 'c) t - (** The type of two-dimensional big arrays whose elements have + (** The type of two-dimensional Bigarrays whose elements have OCaml type ['a], representation kind ['b], and memory layout ['c]. *) val create: ('a, 'b) kind -> 'c layout -> int -> int -> ('a, 'b, 'c) t - (** [Array2.create kind layout dim1 dim2] returns a new bigarray of + (** [Array2.create kind layout dim1 dim2] returns a new Bigarray of two dimension, whose size is [dim1] in the first dimension and [dim2] in the second dimension. [kind] and [layout] determine the array element kind and the array layout as described for {!Bigarray.Genarray.create}. *) external dim1: ('a, 'b, 'c) t -> int = "%caml_ba_dim_1" - (** Return the first dimension of the given two-dimensional big array. *) + (** Return the first dimension of the given two-dimensional Bigarray. *) external dim2: ('a, 'b, 'c) t -> int = "%caml_ba_dim_2" - (** Return the second dimension of the given two-dimensional big array. *) + (** Return the second dimension of the given two-dimensional Bigarray. *) external kind: ('a, 'b, 'c) t -> ('a, 'b) kind = "caml_ba_kind" - (** Return the kind of the given big array. *) + (** Return the kind of the given Bigarray. *) external layout: ('a, 'b, 'c) t -> 'c layout = "caml_ba_layout" - (** Return the layout of the given big array. *) + (** Return the layout of the given Bigarray. *) val change_layout: ('a, 'b, 'c) t -> 'd layout -> ('a, 'b, 'd) t - (** [Array2.change_layout a layout] returns a bigarray with the + (** [Array2.change_layout a layout] returns a Bigarray with the specified [layout], sharing the data with [a] (and hence having the same dimensions as [a]). No copying of elements is involved: the new array and the original array share the same storage space. @@ -688,7 +688,7 @@ module Array2 : external sub_left: ('a, 'b, c_layout) t -> int -> int -> ('a, 'b, c_layout) t = "caml_ba_sub" (** Extract a two-dimensional sub-array of the given two-dimensional - big array by restricting the first dimension. + Bigarray by restricting the first dimension. See {!Bigarray.Genarray.sub_left} for more details. [Array2.sub_left] applies only to arrays with C layout. *) @@ -696,35 +696,35 @@ module Array2 : ('a, 'b, fortran_layout) t -> int -> int -> ('a, 'b, fortran_layout) t = "caml_ba_sub" (** Extract a two-dimensional sub-array of the given two-dimensional - big array by restricting the second dimension. + Bigarray by restricting the second dimension. See {!Bigarray.Genarray.sub_right} for more details. [Array2.sub_right] applies only to arrays with Fortran layout. *) val slice_left: ('a, 'b, c_layout) t -> int -> ('a, 'b, c_layout) Array1.t (** Extract a row (one-dimensional slice) of the given two-dimensional - big array. The integer parameter is the index of the row to + Bigarray. The integer parameter is the index of the row to extract. See {!Bigarray.Genarray.slice_left} for more details. [Array2.slice_left] applies only to arrays with C layout. *) val slice_right: ('a, 'b, fortran_layout) t -> int -> ('a, 'b, fortran_layout) Array1.t (** Extract a column (one-dimensional slice) of the given - two-dimensional big array. The integer parameter is the + two-dimensional Bigarray. The integer parameter is the index of the column to extract. See {!Bigarray.Genarray.slice_right} for more details. [Array2.slice_right] applies only to arrays with Fortran layout. *) external blit: ('a, 'b, 'c) t -> ('a, 'b, 'c) t -> unit = "caml_ba_blit" - (** Copy the first big array to the second big array. + (** Copy the first Bigarray to the second Bigarray. See {!Bigarray.Genarray.blit} for more details. *) external fill: ('a, 'b, 'c) t -> 'a -> unit = "caml_ba_fill" - (** Fill the given big array with the given value. + (** Fill the given Bigarray with the given value. See {!Bigarray.Genarray.fill} for more details. *) val of_array: ('a, 'b) kind -> 'c layout -> 'a array array -> ('a, 'b, 'c) t - (** Build a two-dimensional big array initialized from the + (** Build a two-dimensional Bigarray initialized from the given array of arrays. *) external unsafe_get: ('a, 'b, 'c) t -> int -> int -> 'a @@ -747,34 +747,34 @@ end module Array3 : sig type ('a, 'b, 'c) t - (** The type of three-dimensional big arrays whose elements have + (** The type of three-dimensional Bigarrays whose elements have OCaml type ['a], representation kind ['b], and memory layout ['c]. *) val create: ('a, 'b) kind -> 'c layout -> int -> int -> int -> ('a, 'b, 'c) t - (** [Array3.create kind layout dim1 dim2 dim3] returns a new bigarray of + (** [Array3.create kind layout dim1 dim2 dim3] returns a new Bigarray of three dimension, whose size is [dim1] in the first dimension, [dim2] in the second dimension, and [dim3] in the third. [kind] and [layout] determine the array element kind and the array layout as described for {!Bigarray.Genarray.create}. *) external dim1: ('a, 'b, 'c) t -> int = "%caml_ba_dim_1" - (** Return the first dimension of the given three-dimensional big array. *) + (** Return the first dimension of the given three-dimensional Bigarray. *) external dim2: ('a, 'b, 'c) t -> int = "%caml_ba_dim_2" - (** Return the second dimension of the given three-dimensional big array. *) + (** Return the second dimension of the given three-dimensional Bigarray. *) external dim3: ('a, 'b, 'c) t -> int = "%caml_ba_dim_3" - (** Return the third dimension of the given three-dimensional big array. *) + (** Return the third dimension of the given three-dimensional Bigarray. *) external kind: ('a, 'b, 'c) t -> ('a, 'b) kind = "caml_ba_kind" - (** Return the kind of the given big array. *) + (** Return the kind of the given Bigarray. *) external layout: ('a, 'b, 'c) t -> 'c layout = "caml_ba_layout" - (** Return the layout of the given big array. *) + (** Return the layout of the given Bigarray. *) val change_layout: ('a, 'b, 'c) t -> 'd layout -> ('a, 'b, 'd) t - (** [Array3.change_layout a layout] returns a bigarray with the + (** [Array3.change_layout a layout] returns a Bigarray with the specified [layout], sharing the data with [a] (and hence having the same dimensions as [a]). No copying of elements is involved: the new array and the original array share the same storage space. @@ -808,7 +808,7 @@ module Array3 : external sub_left: ('a, 'b, c_layout) t -> int -> int -> ('a, 'b, c_layout) t = "caml_ba_sub" (** Extract a three-dimensional sub-array of the given - three-dimensional big array by restricting the first dimension. + three-dimensional Bigarray by restricting the first dimension. See {!Bigarray.Genarray.sub_left} for more details. [Array3.sub_left] applies only to arrays with C layout. *) @@ -816,14 +816,14 @@ module Array3 : ('a, 'b, fortran_layout) t -> int -> int -> ('a, 'b, fortran_layout) t = "caml_ba_sub" (** Extract a three-dimensional sub-array of the given - three-dimensional big array by restricting the second dimension. + three-dimensional Bigarray by restricting the second dimension. See {!Bigarray.Genarray.sub_right} for more details. [Array3.sub_right] applies only to arrays with Fortran layout. *) val slice_left_1: ('a, 'b, c_layout) t -> int -> int -> ('a, 'b, c_layout) Array1.t (** Extract a one-dimensional slice of the given three-dimensional - big array by fixing the first two coordinates. + Bigarray by fixing the first two coordinates. The integer parameters are the coordinates of the slice to extract. See {!Bigarray.Genarray.slice_left} for more details. [Array3.slice_left_1] applies only to arrays with C layout. *) @@ -832,7 +832,7 @@ module Array3 : ('a, 'b, fortran_layout) t -> int -> int -> ('a, 'b, fortran_layout) Array1.t (** Extract a one-dimensional slice of the given three-dimensional - big array by fixing the last two coordinates. + Bigarray by fixing the last two coordinates. The integer parameters are the coordinates of the slice to extract. See {!Bigarray.Genarray.slice_right} for more details. [Array3.slice_right_1] applies only to arrays with Fortran @@ -840,7 +840,7 @@ module Array3 : val slice_left_2: ('a, 'b, c_layout) t -> int -> ('a, 'b, c_layout) Array2.t (** Extract a two-dimensional slice of the given three-dimensional - big array by fixing the first coordinate. + Bigarray by fixing the first coordinate. The integer parameter is the first coordinate of the slice to extract. See {!Bigarray.Genarray.slice_left} for more details. [Array3.slice_left_2] applies only to arrays with C layout. *) @@ -848,7 +848,7 @@ module Array3 : val slice_right_2: ('a, 'b, fortran_layout) t -> int -> ('a, 'b, fortran_layout) Array2.t (** Extract a two-dimensional slice of the given - three-dimensional big array by fixing the last coordinate. + three-dimensional Bigarray by fixing the last coordinate. The integer parameter is the coordinate of the slice to extract. See {!Bigarray.Genarray.slice_right} for more details. [Array3.slice_right_2] applies only to arrays with Fortran @@ -856,16 +856,16 @@ module Array3 : external blit: ('a, 'b, 'c) t -> ('a, 'b, 'c) t -> unit = "caml_ba_blit" - (** Copy the first big array to the second big array. + (** Copy the first Bigarray to the second Bigarray. See {!Bigarray.Genarray.blit} for more details. *) external fill: ('a, 'b, 'c) t -> 'a -> unit = "caml_ba_fill" - (** Fill the given big array with the given value. + (** Fill the given Bigarray with the given value. See {!Bigarray.Genarray.fill} for more details. *) val of_array: ('a, 'b) kind -> 'c layout -> 'a array array array -> ('a, 'b, 'c) t - (** Build a three-dimensional big array initialized from the + (** Build a three-dimensional Bigarray initialized from the given array of arrays of arrays. *) external unsafe_get: ('a, 'b, 'c) t -> int -> int -> int -> 'a @@ -880,54 +880,54 @@ module Array3 : end -(** {1 Coercions between generic big arrays and fixed-dimension big arrays} *) +(** {1 Coercions between generic Bigarrays and fixed-dimension Bigarrays} *) external genarray_of_array0 : ('a, 'b, 'c) Array0.t -> ('a, 'b, 'c) Genarray.t = "%identity" -(** Return the generic big array corresponding to the given zero-dimensional - big array. @since 4.05.0 *) +(** Return the generic Bigarray corresponding to the given zero-dimensional + Bigarray. @since 4.05.0 *) external genarray_of_array1 : ('a, 'b, 'c) Array1.t -> ('a, 'b, 'c) Genarray.t = "%identity" -(** Return the generic big array corresponding to the given one-dimensional - big array. *) +(** Return the generic Bigarray corresponding to the given one-dimensional + Bigarray. *) external genarray_of_array2 : ('a, 'b, 'c) Array2.t -> ('a, 'b, 'c) Genarray.t = "%identity" -(** Return the generic big array corresponding to the given two-dimensional - big array. *) +(** Return the generic Bigarray corresponding to the given two-dimensional + Bigarray. *) external genarray_of_array3 : ('a, 'b, 'c) Array3.t -> ('a, 'b, 'c) Genarray.t = "%identity" -(** Return the generic big array corresponding to the given three-dimensional - big array. *) +(** Return the generic Bigarray corresponding to the given three-dimensional + Bigarray. *) val array0_of_genarray : ('a, 'b, 'c) Genarray.t -> ('a, 'b, 'c) Array0.t -(** Return the zero-dimensional big array corresponding to the given - generic big array. Raise [Invalid_argument] if the generic big array +(** Return the zero-dimensional Bigarray corresponding to the given + generic Bigarray. Raise [Invalid_argument] if the generic Bigarray does not have exactly zero dimension. @since 4.05.0 *) val array1_of_genarray : ('a, 'b, 'c) Genarray.t -> ('a, 'b, 'c) Array1.t -(** Return the one-dimensional big array corresponding to the given - generic big array. Raise [Invalid_argument] if the generic big array +(** Return the one-dimensional Bigarray corresponding to the given + generic Bigarray. Raise [Invalid_argument] if the generic Bigarray does not have exactly one dimension. *) val array2_of_genarray : ('a, 'b, 'c) Genarray.t -> ('a, 'b, 'c) Array2.t -(** Return the two-dimensional big array corresponding to the given - generic big array. Raise [Invalid_argument] if the generic big array +(** Return the two-dimensional Bigarray corresponding to the given + generic Bigarray. Raise [Invalid_argument] if the generic Bigarray does not have exactly two dimensions. *) val array3_of_genarray : ('a, 'b, 'c) Genarray.t -> ('a, 'b, 'c) Array3.t -(** Return the three-dimensional big array corresponding to the given - generic big array. Raise [Invalid_argument] if the generic big array +(** Return the three-dimensional Bigarray corresponding to the given + generic Bigarray. Raise [Invalid_argument] if the generic Bigarray does not have exactly three dimensions. *) -(** {1 Re-shaping big arrays} *) +(** {1 Re-shaping Bigarrays} *) val reshape : ('a, 'b, 'c) Genarray.t -> int array -> ('a, 'b, 'c) Genarray.t -(** [reshape b [|d1;...;dN|]] converts the big array [b] to a +(** [reshape b [|d1;...;dN|]] converts the Bigarray [b] to a [N]-dimensional array of dimensions [d1]...[dN]. The returned array and the original array [b] share their data and have the same layout. For instance, assuming that [b] @@ -937,8 +937,8 @@ val reshape : ('a, 'b, 'c) Genarray.t -> int array -> ('a, 'b, 'c) Genarray.t to the element [x * 3 + y] of [b]. If [b] has Fortran layout, the element [(x,y)] of [b'] corresponds to the element [x + (y - 1) * 4] of [b]. - The returned big array must have exactly the same number of - elements as the original big array [b]. That is, the product + The returned Bigarray must have exactly the same number of + elements as the original Bigarray [b]. That is, the product of the dimensions of [b] must be equal to [i1 * ... * iN]. Otherwise, [Invalid_argument] is raised. *) diff --git a/stdlib/bool.ml b/stdlib/bool.ml new file mode 100644 index 00000000..8ce03004 --- /dev/null +++ b/stdlib/bool.ml @@ -0,0 +1,33 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* The OCaml programmers *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +type t = bool = false | true + +external not : bool -> bool = "%boolnot" +external ( && ) : bool -> bool -> bool = "%sequand" +external ( || ) : bool -> bool -> bool = "%sequor" +let equal : bool -> bool -> bool = ( = ) +let compare : bool -> bool -> int = Stdlib.compare +let to_int = function false -> 0 | true -> 1 +let to_float = function false -> 0. | true -> 1. + +(* +let of_string = function +| "false" -> Some false +| "true" -> Some true +| _ -> None +*) + +let to_string = function false -> "false" | true -> "true" diff --git a/stdlib/bool.mli b/stdlib/bool.mli new file mode 100644 index 00000000..975afe3f --- /dev/null +++ b/stdlib/bool.mli @@ -0,0 +1,68 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* The OCaml programmers *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** Boolean values. + + @since 4.08 *) + +(** {1:bools Booleans} *) + +type t = bool = false | true +(** The type of booleans (truth values). + + The constructors [false] and [true] are included here so that they have + paths, but they are not intended to be used in user-defined data types. + *) + +val not : bool -> bool +(** [not b] is the boolean negation of [b]. *) + +external ( && ) : bool -> bool -> bool = "%sequand" +(** [e0 && e1] is the lazy boolean conjunction of expressions [e0] and [e1]. + If [e0] evaluates to [false], [e1] is not evaluated. Right-associative + operator at precedence level 3/11. *) + +external ( || ) : bool -> bool -> bool = "%sequor" +(** [e0 || e1] is the lazy boolean disjunction of expressions [e0] and [e1]. + If [e0] evaluates to [true], [e1] is not evaluated. Right-associative + operator at precedence level 2/11. *) + +(** {1:preds Predicates and comparisons} *) + +val equal : bool -> bool -> bool +(** [equal b0 b1] is [true] iff [b0] and [b1] are both either [true] + or [false]. *) + +val compare : bool -> bool -> int +(** [compare b0 b1] is a total order on boolean values. [false] is smaller + than [true]. *) + +(** {1:convert Converting} *) + +val to_int : bool -> int +(** [to_int b] is [0] if [b] is [false] and [1] if [b] is [true]. *) + +val to_float : bool -> float +(** [to_float b] is [0.] if [b] is [false] and [1.] if [b] is [true]. *) + +(* +val of_string : string -> bool option +(** [of_string s] is [Some true] if [s] is ["true"], [Some false] if [s] + is ["false"] and [None] otherwise. *) +*) + +val to_string : bool -> string +(** [to_string b] is ["true"] if [b] is [true] and ["false"] if [b] is + [false]. *) diff --git a/stdlib/buffer.ml b/stdlib/buffer.ml index 387b51a5..e8d83c1c 100644 --- a/stdlib/buffer.ml +++ b/stdlib/buffer.ml @@ -273,7 +273,7 @@ let truncate b len = else b.position <- len -(** {6 Iterators} *) +(** {1 Iterators} *) let to_seq b = let rec aux i () = @@ -300,3 +300,60 @@ let of_seq i = add_seq b i; b +(** {6 Binary encoding of integers} *) + +external unsafe_set_int8 : bytes -> int -> int -> unit = "%bytes_unsafe_set" +external unsafe_set_int16 : bytes -> int -> int -> unit = "%caml_bytes_set16u" +external unsafe_set_int32 : bytes -> int -> int32 -> unit = "%caml_bytes_set32u" +external unsafe_set_int64 : bytes -> int -> int64 -> unit = "%caml_bytes_set64u" +external swap16 : int -> int = "%bswap16" +external swap32 : int32 -> int32 = "%bswap_int32" +external swap64 : int64 -> int64 = "%bswap_int64" + + +let add_int8 b x = + let new_position = b.position + 1 in + if new_position > b.length then resize b 1; + unsafe_set_int8 b.buffer b.position x; + b.position <- new_position + +let add_int16_ne b x = + let new_position = b.position + 2 in + if new_position > b.length then resize b 2; + unsafe_set_int16 b.buffer b.position x; + b.position <- new_position + +let add_int32_ne b x = + let new_position = b.position + 4 in + if new_position > b.length then resize b 4; + unsafe_set_int32 b.buffer b.position x; + b.position <- new_position + +let add_int64_ne b x = + let new_position = b.position + 8 in + if new_position > b.length then resize b 8; + unsafe_set_int64 b.buffer b.position x; + b.position <- new_position + +let add_int16_le b x = + add_int16_ne b (if Sys.big_endian then swap16 x else x) + +let add_int16_be b x = + add_int16_ne b (if Sys.big_endian then x else swap16 x) + +let add_int32_le b x = + add_int32_ne b (if Sys.big_endian then swap32 x else x) + +let add_int32_be b x = + add_int32_ne b (if Sys.big_endian then x else swap32 x) + +let add_int64_le b x = + add_int64_ne b (if Sys.big_endian then swap64 x else x) + +let add_int64_be b x = + add_int64_ne b (if Sys.big_endian then x else swap64 x) + +let add_uint8 = add_int8 +let add_uint16_ne = add_int16_ne +let add_uint16_le = add_int16_le +let add_uint16_be = add_int16_be diff --git a/stdlib/buffer.mli b/stdlib/buffer.mli index 884973a2..83b96c71 100644 --- a/stdlib/buffer.mli +++ b/stdlib/buffer.mli @@ -158,7 +158,7 @@ val truncate : t -> int -> unit Raise [Invalid_argument] if [len < 0] or [len > length b]. @since 4.05.0 *) -(** {6 Iterators} *) +(** {1 Iterators} *) val to_seq : t -> char Seq.t (** Iterate on the buffer, in increasing order. @@ -178,3 +178,106 @@ val of_seq : char Seq.t -> t (** Create a buffer from the generator @since 4.07 *) +(** {1 Binary encoding of integers} *) + +(** The functions in this section append binary encodings of integers + to buffers. + + Little-endian (resp. big-endian) encoding means that least + (resp. most) significant bytes are stored first. Big-endian is + also known as network byte order. Native-endian encoding is + either little-endian or big-endian depending on {!Sys.big_endian}. + + 32-bit and 64-bit integers are represented by the [int32] and + [int64] types, which can be interpreted either as signed or + unsigned numbers. + + 8-bit and 16-bit integers are represented by the [int] type, + which has more bits than the binary encoding. Functions that + encode these values truncate their inputs to their least + significant bytes. +*) + +val add_uint8 : t -> int -> unit +(** [add_uint8 b i] appends a binary unsigned 8-bit integer [i] to + [b]. + @since 4.08 +*) + +val add_int8 : t -> int -> unit +(** [add_int8 b i] appends a binary signed 8-bit integer [i] to + [b]. + @since 4.08 +*) + +val add_uint16_ne : t -> int -> unit +(** [add_uint16_ne b i] appends a binary native-endian unsigned 16-bit + integer [i] to [b]. + @since 4.08 +*) + +val add_uint16_be : t -> int -> unit +(** [add_uint16_be b i] appends a binary big-endian unsigned 16-bit + integer [i] to [b]. + @since 4.08 +*) + +val add_uint16_le : t -> int -> unit +(** [add_uint16_le b i] appends a binary little-endian unsigned 16-bit + integer [i] to [b]. + @since 4.08 +*) + +val add_int16_ne : t -> int -> unit +(** [add_int16_ne b i] appends a binary native-endian signed 16-bit + integer [i] to [b]. + @since 4.08 +*) + +val add_int16_be : t -> int -> unit +(** [add_int16_be b i] appends a binary big-endian signed 16-bit + integer [i] to [b]. + @since 4.08 +*) + +val add_int16_le : t -> int -> unit +(** [add_int16_le b i] appends a binary little-endian signed 16-bit + integer [i] to [b]. + @since 4.08 +*) + +val add_int32_ne : t -> int32 -> unit +(** [add_int32_ne b i] appends a binary native-endian 32-bit integer + [i] to [b]. + @since 4.08 +*) + +val add_int32_be : t -> int32 -> unit +(** [add_int32_be b i] appends a binary big-endian 32-bit integer + [i] to [b]. + @since 4.08 +*) + +val add_int32_le : t -> int32 -> unit +(** [add_int32_le b i] appends a binary little-endian 32-bit integer + [i] to [b]. + @since 4.08 +*) + +val add_int64_ne : t -> int64 -> unit +(** [add_int64_ne b i] appends a binary native-endian 64-bit integer + [i] to [b]. + @since 4.08 +*) + +val add_int64_be : t -> int64 -> unit +(** [add_int64_be b i] appends a binary big-endian 64-bit integer + [i] to [b]. + @since 4.08 +*) + +val add_int64_le : t -> int64 -> unit +(** [add_int64_ne b i] appends a binary little-endian 64-bit integer + [i] to [b]. + @since 4.08 +*) diff --git a/stdlib/bytes.ml b/stdlib/bytes.ml index 3532bc4b..d89297e7 100644 --- a/stdlib/bytes.ml +++ b/stdlib/bytes.ml @@ -261,8 +261,10 @@ let index_from s i c = (* duplicated in string.ml *) let index_from_opt s i c = let l = length s in - if i < 0 || i > l then invalid_arg "String.index_from_opt / Bytes.index_from_opt" else - index_rec_opt s l i c + if i < 0 || i > l then + invalid_arg "String.index_from_opt / Bytes.index_from_opt" + else + index_rec_opt s l i c (* duplicated in string.ml *) let rec rindex_rec s i c = @@ -317,8 +319,8 @@ let rcontains_from s i c = type t = bytes -let compare (x: t) (y: t) = Pervasives.compare x y -external equal : t -> t -> bool = "caml_bytes_equal" +let compare (x: t) (y: t) = Stdlib.compare x y +external equal : t -> t -> bool = "caml_bytes_equal" [@@noalloc] (* Deprecated functions implemented via other deprecated functions *) [@@@ocaml.warning "-3"] @@ -328,7 +330,7 @@ let lowercase s = map Char.lowercase s let capitalize s = apply1 Char.uppercase s let uncapitalize s = apply1 Char.lowercase s -(** {6 Iterators} *) +(** {1 Iterators} *) let to_seq s = let rec aux i () = @@ -367,3 +369,81 @@ let of_seq i = i; sub !buf 0 !n +(** {6 Binary encoding/decoding of integers} *) + +external get_uint8 : bytes -> int -> int = "%bytes_safe_get" +external get_uint16_ne : bytes -> int -> int = "%caml_bytes_get16" +external get_int32_ne : bytes -> int -> int32 = "%caml_bytes_get32" +external get_int64_ne : bytes -> int -> int64 = "%caml_bytes_get64" +external set_int8 : bytes -> int -> int -> unit = "%bytes_safe_set" +external set_int16_ne : bytes -> int -> int -> unit = "%caml_bytes_set16" +external set_int32_ne : bytes -> int -> int32 -> unit = "%caml_bytes_set32" +external set_int64_ne : bytes -> int -> int64 -> unit = "%caml_bytes_set64" +external swap16 : int -> int = "%bswap16" +external swap32 : int32 -> int32 = "%bswap_int32" +external swap64 : int64 -> int64 = "%bswap_int64" + +let get_int8 b i = + ((get_uint8 b i) lsl (Sys.int_size - 8)) asr (Sys.int_size - 8) + +let get_uint16_le b i = + if Sys.big_endian then swap16 (get_uint16_ne b i) + else get_uint16_ne b i + +let get_uint16_be b i = + if not Sys.big_endian then swap16 (get_uint16_ne b i) + else get_uint16_ne b i + +let get_int16_ne b i = + ((get_uint16_ne b i) lsl (Sys.int_size - 16)) asr (Sys.int_size - 16) + +let get_int16_le b i = + ((get_uint16_le b i) lsl (Sys.int_size - 16)) asr (Sys.int_size - 16) + +let get_int16_be b i = + ((get_uint16_be b i) lsl (Sys.int_size - 16)) asr (Sys.int_size - 16) + +let get_int32_le b i = + if Sys.big_endian then swap32 (get_int32_ne b i) + else get_int32_ne b i + +let get_int32_be b i = + if not Sys.big_endian then swap32 (get_int32_ne b i) + else get_int32_ne b i + +let get_int64_le b i = + if Sys.big_endian then swap64 (get_int64_ne b i) + else get_int64_ne b i + +let get_int64_be b i = + if not Sys.big_endian then swap64 (get_int64_ne b i) + else get_int64_ne b i + +let set_int16_le b i x = + if Sys.big_endian then set_int16_ne b i (swap16 x) + else set_int16_ne b i x + +let set_int16_be b i x = + if not Sys.big_endian then set_int16_ne b i (swap16 x) + else set_int16_ne b i x + +let set_int32_le b i x = + if Sys.big_endian then set_int32_ne b i (swap32 x) + else set_int32_ne b i x + +let set_int32_be b i x = + if not Sys.big_endian then set_int32_ne b i (swap32 x) + else set_int32_ne b i x + +let set_int64_le b i x = + if Sys.big_endian then set_int64_ne b i (swap64 x) + else set_int64_ne b i x + +let set_int64_be b i x = + if not Sys.big_endian then set_int64_ne b i (swap64 x) + else set_int64_ne b i x + +let set_uint8 = set_int8 +let set_uint16_ne = set_int16_ne +let set_uint16_be = set_int16_be +let set_uint16_le = set_int16_le diff --git a/stdlib/bytes.mli b/stdlib/bytes.mli index 6a889eca..d449f82d 100644 --- a/stdlib/bytes.mli +++ b/stdlib/bytes.mli @@ -219,7 +219,8 @@ val index_from : bytes -> int -> char -> int val index_from_opt: bytes -> int -> char -> int option (** [index_from _opts i c] returns the index of the first occurrence of - byte [c] in [s] after position [i] or [None] if [c] does not occur in [s] after position [i]. + byte [c] in [s] after position [i] or [None] if [c] does not occur in [s] + after position [i]. [Bytes.index_opt s c] is equivalent to [Bytes.index_from_opt s 0 c]. Raise [Invalid_argument] if [i] is not a valid position in [s]. @@ -310,7 +311,7 @@ type t = bytes val compare: t -> t -> int (** The comparison function for byte sequences, with the same - specification as {!Pervasives.compare}. Along with the type [t], + specification as {!Stdlib.compare}. Along with the type [t], this function [compare] allows the module [Bytes] to be passed as argument to the functors {!Set.Make} and {!Map.Make}. *) @@ -318,7 +319,7 @@ val equal: t -> t -> bool (** The equality function for byte sequences. @since 4.03.0 *) -(** {3 Unsafe conversions (for advanced users)} +(** {1:unsafe Unsafe conversions (for advanced users)} This section describes unsafe, low-level conversion functions between [bytes] and [string]. They do not copy the internal data; @@ -447,7 +448,7 @@ let s = Bytes.of_string "hello" [string] type for this purpose. *) -(** {6 Iterators} *) +(** {1 Iterators} *) val to_seq : t -> char Seq.t (** Iterate on the string, in increasing index order. Modifications of the @@ -462,6 +463,203 @@ val of_seq : char Seq.t -> t (** Create a string from the generator @since 4.07 *) +(** {1 Binary encoding/decoding of integers} *) + +(** The functions in this section binary encode and decode integers to + and from byte sequences. + + All following functions raise [Invalid_argument] if the space + needed at index [i] to decode or encode the integer is not + available. + + Little-endian (resp. big-endian) encoding means that least + (resp. most) significant bytes are stored first. Big-endian is + also known as network byte order. Native-endian encoding is + either little-endian or big-endian depending on {!Sys.big_endian}. + + 32-bit and 64-bit integers are represented by the [int32] and + [int64] types, which can be interpreted either as signed or + unsigned numbers. + + 8-bit and 16-bit integers are represented by the [int] type, + which has more bits than the binary encoding. These extra bits + are handled as follows: {ul + {- Functions that decode signed (resp. unsigned) 8-bit or 16-bit + integers represented by [int] values sign-extend + (resp. zero-extend) their result.} + {- Functions that encode 8-bit or 16-bit integers represented by + [int] values truncate their input to their least significant + bytes.}} +*) + +val get_uint8 : bytes -> int -> int +(** [get_uint8 b i] is [b]'s unsigned 8-bit integer starting at byte index [i]. + @since 4.08 +*) + +val get_int8 : bytes -> int -> int +(** [get_int8 b i] is [b]'s signed 8-bit integer starting at byte index [i]. + @since 4.08 +*) + +val get_uint16_ne : bytes -> int -> int +(** [get_uint16_ne b i] is [b]'s native-endian unsigned 16-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_uint16_be : bytes -> int -> int +(** [get_uint16_be b i] is [b]'s big-endian unsigned 16-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_uint16_le : bytes -> int -> int +(** [get_uint16_le b i] is [b]'s little-endian unsigned 16-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int16_ne : bytes -> int -> int +(** [get_int16_ne b i] is [b]'s native-endian signed 16-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int16_be : bytes -> int -> int +(** [get_int16_be b i] is [b]'s big-endian signed 16-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int16_le : bytes -> int -> int +(** [get_int16_le b i] is [b]'s little-endian signed 16-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int32_ne : bytes -> int -> int32 +(** [get_int32_ne b i] is [b]'s native-endian 32-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int32_be : bytes -> int -> int32 +(** [get_int32_be b i] is [b]'s big-endian 32-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int32_le : bytes -> int -> int32 +(** [get_int32_le b i] is [b]'s little-endian 32-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int64_ne : bytes -> int -> int64 +(** [get_int64_ne b i] is [b]'s native-endian 64-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int64_be : bytes -> int -> int64 +(** [get_int64_be b i] is [b]'s big-endian 64-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int64_le : bytes -> int -> int64 +(** [get_int64_le b i] is [b]'s little-endian 64-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val set_uint8 : bytes -> int -> int -> unit +(** [set_uint8 b i v] sets [b]'s unsigned 8-bit integer starting at byte index + [i] to [v]. + @since 4.08 +*) + +val set_int8 : bytes -> int -> int -> unit +(** [set_int8 b i v] sets [b]'s signed 8-bit integer starting at byte index + [i] to [v]. + @since 4.08 +*) + +val set_uint16_ne : bytes -> int -> int -> unit +(** [set_uint16_ne b i v] sets [b]'s native-endian unsigned 16-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_uint16_be : bytes -> int -> int -> unit +(** [set_uint16_be b i v] sets [b]'s big-endian unsigned 16-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_uint16_le : bytes -> int -> int -> unit +(** [set_uint16_le b i v] sets [b]'s little-endian unsigned 16-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int16_ne : bytes -> int -> int -> unit +(** [set_int16_ne b i v] sets [b]'s native-endian signed 16-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int16_be : bytes -> int -> int -> unit +(** [set_int16_be b i v] sets [b]'s big-endian signed 16-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int16_le : bytes -> int -> int -> unit +(** [set_int16_le b i v] sets [b]'s little-endian signed 16-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int32_ne : bytes -> int -> int32 -> unit +(** [set_int32_ne b i v] sets [b]'s native-endian 32-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int32_be : bytes -> int -> int32 -> unit +(** [set_int32_be b i v] sets [b]'s big-endian 32-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int32_le : bytes -> int -> int32 -> unit +(** [set_int32_le b i v] sets [b]'s little-endian 32-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int64_ne : bytes -> int -> int64 -> unit +(** [set_int64_ne b i v] sets [b]'s native-endian 64-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int64_be : bytes -> int -> int64 -> unit +(** [set_int64_be b i v] sets [b]'s big-endian 64-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int64_le : bytes -> int -> int64 -> unit +(** [set_int64_le b i v] sets [b]'s little-endian 64-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + + + (**/**) (* The following is for system use only. Do not call directly. *) diff --git a/stdlib/bytesLabels.mli b/stdlib/bytesLabels.mli index dc710a9f..2cc700a5 100644 --- a/stdlib/bytesLabels.mli +++ b/stdlib/bytesLabels.mli @@ -193,7 +193,8 @@ val index_from : bytes -> int -> char -> int val index_from_opt: bytes -> int -> char -> int option (** [index_from _opts i c] returns the index of the first occurrence of - byte [c] in [s] after position [i] or [None] if [c] does not occur in [s] after position [i]. + byte [c] in [s] after position [i] or [None] if [c] does not occur in [s] + after position [i]. [Bytes.index_opt s c] is equivalent to [Bytes.index_from_opt s 0 c]. Raise [Invalid_argument] if [i] is not a valid position in [s]. @@ -284,7 +285,7 @@ type t = bytes val compare: t -> t -> int (** The comparison function for byte sequences, with the same - specification as {!Pervasives.compare}. Along with the type [t], + specification as {!Stdlib.compare}. Along with the type [t], this function [compare] allows the module [Bytes] to be passed as argument to the functors {!Set.Make} and {!Map.Make}. *) @@ -292,7 +293,7 @@ val equal: t -> t -> bool (** The equality function for byte sequences. @since 4.05.0 *) -(** {6 Iterators} *) +(** {1 Iterators} *) val to_seq : t -> char Seq.t (** Iterate on the string, in increasing index order. Modifications of the @@ -307,6 +308,202 @@ val of_seq : char Seq.t -> t (** Create a string from the generator @since 4.07 *) +(** {1 Binary encoding/decoding of integers} *) + +(** The functions in this section binary encode and decode integers to + and from byte sequences. + + All following functions raise [Invalid_argument] if the space + needed at index [i] to decode or encode the integer is not + available. + + Little-endian (resp. big-endian) encoding means that least + (resp. most) significant bytes are stored first. Big-endian is + also known as network byte order. Native-endian encoding is + either little-endian or big-endian depending on {!Sys.big_endian}. + + 32-bit and 64-bit integers are represented by the [int32] and + [int64] types, which can be interpreted either as signed or + unsigned numbers. + + 8-bit and 16-bit integers are represented by the [int] type, + which has more bits than the binary encoding. These extra bits + are handled as follows: {ul + {- Functions that decode signed (resp. unsigned) 8-bit or 16-bit + integers represented by [int] values sign-extend + (resp. zero-extend) their result.} + {- Functions that encode 8-bit or 16-bit integers represented by + [int] values truncate their input to their least significant + bytes.}} +*) + +val get_uint8 : bytes -> int -> int +(** [get_uint8 b i] is [b]'s unsigned 8-bit integer starting at byte index [i]. + @since 4.08 +*) + +val get_int8 : bytes -> int -> int +(** [get_int8 b i] is [b]'s signed 8-bit integer starting at byte index [i]. + @since 4.08 +*) + +val get_uint16_ne : bytes -> int -> int +(** [get_uint16_ne b i] is [b]'s native-endian unsigned 16-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_uint16_be : bytes -> int -> int +(** [get_uint16_be b i] is [b]'s big-endian unsigned 16-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_uint16_le : bytes -> int -> int +(** [get_uint16_le b i] is [b]'s little-endian unsigned 16-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int16_ne : bytes -> int -> int +(** [get_int16_ne b i] is [b]'s native-endian signed 16-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int16_be : bytes -> int -> int +(** [get_int16_be b i] is [b]'s big-endian signed 16-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int16_le : bytes -> int -> int +(** [get_int16_le b i] is [b]'s little-endian signed 16-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int32_ne : bytes -> int -> int32 +(** [get_int32_ne b i] is [b]'s native-endian 32-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int32_be : bytes -> int -> int32 +(** [get_int32_be b i] is [b]'s big-endian 32-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int32_le : bytes -> int -> int32 +(** [get_int32_le b i] is [b]'s little-endian 32-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int64_ne : bytes -> int -> int64 +(** [get_int64_ne b i] is [b]'s native-endian 64-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int64_be : bytes -> int -> int64 +(** [get_int64_be b i] is [b]'s big-endian 64-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val get_int64_le : bytes -> int -> int64 +(** [get_int64_le b i] is [b]'s little-endian 64-bit integer + starting at byte index [i]. + @since 4.08 +*) + +val set_uint8 : bytes -> int -> int -> unit +(** [set_uint8 b i v] sets [b]'s unsigned 8-bit integer starting at byte index + [i] to [v]. + @since 4.08 +*) + +val set_int8 : bytes -> int -> int -> unit +(** [set_int8 b i v] sets [b]'s signed 8-bit integer starting at byte index + [i] to [v]. + @since 4.08 +*) + +val set_uint16_ne : bytes -> int -> int -> unit +(** [set_uint16_ne b i v] sets [b]'s native-endian unsigned 16-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_uint16_be : bytes -> int -> int -> unit +(** [set_uint16_be b i v] sets [b]'s big-endian unsigned 16-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_uint16_le : bytes -> int -> int -> unit +(** [set_uint16_le b i v] sets [b]'s little-endian unsigned 16-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int16_ne : bytes -> int -> int -> unit +(** [set_int16_ne b i v] sets [b]'s native-endian signed 16-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int16_be : bytes -> int -> int -> unit +(** [set_int16_be b i v] sets [b]'s big-endian signed 16-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int16_le : bytes -> int -> int -> unit +(** [set_int16_le b i v] sets [b]'s little-endian signed 16-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int32_ne : bytes -> int -> int32 -> unit +(** [set_int32_ne b i v] sets [b]'s native-endian 32-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int32_be : bytes -> int -> int32 -> unit +(** [set_int32_be b i v] sets [b]'s big-endian 32-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int32_le : bytes -> int -> int32 -> unit +(** [set_int32_le b i v] sets [b]'s little-endian 32-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int64_ne : bytes -> int -> int64 -> unit +(** [set_int64_ne b i v] sets [b]'s native-endian 64-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int64_be : bytes -> int -> int64 -> unit +(** [set_int64_be b i v] sets [b]'s big-endian 64-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + +val set_int64_le : bytes -> int -> int64 -> unit +(** [set_int64_le b i v] sets [b]'s little-endian 64-bit integer + starting at byte index [i] to [v]. + @since 4.08 +*) + + (**/**) (* The following is for system use only. Do not call directly. *) diff --git a/stdlib/camlinternalFormat.ml b/stdlib/camlinternalFormat.ml index 3d8369aa..7c36e22a 100644 --- a/stdlib/camlinternalFormat.ml +++ b/stdlib/camlinternalFormat.ml @@ -281,9 +281,9 @@ let buffer_contents buf = (* Convert an integer conversion to char. *) let char_of_iconv iconv = match iconv with - | Int_d | Int_pd | Int_sd -> 'd' | Int_i | Int_pi | Int_si -> 'i' - | Int_x | Int_Cx -> 'x' | Int_X | Int_CX -> 'X' | Int_o | Int_Co -> 'o' - | Int_u -> 'u' + | Int_d | Int_pd | Int_sd | Int_Cd -> 'd' | Int_i | Int_pi | Int_si + | Int_Ci -> 'i' | Int_x | Int_Cx -> 'x' | Int_X | Int_CX -> 'X' | Int_o + | Int_Co -> 'o' | Int_u | Int_Cu -> 'u' (* Convert a float conversion to char. *) let char_of_fconv fconv = match fconv with @@ -376,7 +376,7 @@ let bprint_ignored_flag buf ign_flag = let bprint_pad_opt buf pad_opt = match pad_opt with | None -> () - | Some width -> buffer_add_string buf (string_of_int width) + | Some width -> buffer_add_string buf (Int.to_string width) (***) @@ -386,7 +386,7 @@ fun buf pad -> match pad with | No_padding -> () | Lit_padding (padty, n) -> bprint_padty buf padty; - buffer_add_string buf (string_of_int n); + buffer_add_string buf (Int.to_string n); | Arg_padding padty -> bprint_padty buf padty; buffer_add_char buf '*' @@ -397,7 +397,7 @@ let bprint_precision : type a b . buffer -> (a, b) precision -> unit = | No_precision -> () | Lit_precision n -> buffer_add_char buf '.'; - buffer_add_string buf (string_of_int n); + buffer_add_string buf (Int.to_string n); | Arg_precision -> buffer_add_string buf ".*" @@ -407,7 +407,8 @@ let bprint_precision : type a b . buffer -> (a, b) precision -> unit = let bprint_iconv_flag buf iconv = match iconv with | Int_pd | Int_pi -> buffer_add_char buf '+' | Int_sd | Int_si -> buffer_add_char buf ' ' - | Int_Cx | Int_CX | Int_Co -> buffer_add_char buf '#' + | Int_Cx | Int_CX | Int_Co | Int_Cd | Int_Ci | Int_Cu -> + buffer_add_char buf '#' | Int_d | Int_i | Int_x | Int_X | Int_o | Int_u -> () (* Print an complete int format in a buffer (ex: "%3.*d"). *) @@ -885,7 +886,8 @@ fun fmtty -> match fmtty with | Char rest -> Char_ty (fmtty_of_fmt rest) | Caml_char rest -> Char_ty (fmtty_of_fmt rest) - | Bool (pad, rest) -> fmtty_of_padding_fmtty pad (Bool_ty (fmtty_of_fmt rest)) + | Bool (pad, rest) -> + fmtty_of_padding_fmtty pad (Bool_ty (fmtty_of_fmt rest)) | Alpha rest -> Alpha_ty (fmtty_of_fmt rest) | Theta rest -> Theta_ty (fmtty_of_fmt rest) | Custom (arity, _, rest) -> fmtty_of_custom arity (fmtty_of_fmt rest) @@ -1373,36 +1375,36 @@ let string_to_caml_string str = (* Generate the format_int/int32/nativeint/int64 first argument from an int_conv. *) let format_of_iconv = function - | Int_d -> "%d" | Int_pd -> "%+d" | Int_sd -> "% d" - | Int_i -> "%i" | Int_pi -> "%+i" | Int_si -> "% i" + | Int_d | Int_Cd -> "%d" | Int_pd -> "%+d" | Int_sd -> "% d" + | Int_i | Int_Ci -> "%i" | Int_pi -> "%+i" | Int_si -> "% i" | Int_x -> "%x" | Int_Cx -> "%#x" | Int_X -> "%X" | Int_CX -> "%#X" | Int_o -> "%o" | Int_Co -> "%#o" - | Int_u -> "%u" + | Int_u | Int_Cu -> "%u" let format_of_iconvL = function - | Int_d -> "%Ld" | Int_pd -> "%+Ld" | Int_sd -> "% Ld" - | Int_i -> "%Li" | Int_pi -> "%+Li" | Int_si -> "% Li" + | Int_d | Int_Cd -> "%Ld" | Int_pd -> "%+Ld" | Int_sd -> "% Ld" + | Int_i | Int_Ci -> "%Li" | Int_pi -> "%+Li" | Int_si -> "% Li" | Int_x -> "%Lx" | Int_Cx -> "%#Lx" | Int_X -> "%LX" | Int_CX -> "%#LX" | Int_o -> "%Lo" | Int_Co -> "%#Lo" - | Int_u -> "%Lu" + | Int_u | Int_Cu -> "%Lu" let format_of_iconvl = function - | Int_d -> "%ld" | Int_pd -> "%+ld" | Int_sd -> "% ld" - | Int_i -> "%li" | Int_pi -> "%+li" | Int_si -> "% li" + | Int_d | Int_Cd -> "%ld" | Int_pd -> "%+ld" | Int_sd -> "% ld" + | Int_i | Int_Ci -> "%li" | Int_pi -> "%+li" | Int_si -> "% li" | Int_x -> "%lx" | Int_Cx -> "%#lx" | Int_X -> "%lX" | Int_CX -> "%#lX" | Int_o -> "%lo" | Int_Co -> "%#lo" - | Int_u -> "%lu" + | Int_u | Int_Cu -> "%lu" let format_of_iconvn = function - | Int_d -> "%nd" | Int_pd -> "%+nd" | Int_sd -> "% nd" - | Int_i -> "%ni" | Int_pi -> "%+ni" | Int_si -> "% ni" + | Int_d | Int_Cd -> "%nd" | Int_pd -> "%+nd" | Int_sd -> "% nd" + | Int_i | Int_Ci -> "%ni" | Int_pi -> "%+ni" | Int_si -> "% ni" | Int_x -> "%nx" | Int_Cx -> "%#nx" | Int_X -> "%nX" | Int_CX -> "%#nX" | Int_o -> "%no" | Int_Co -> "%#no" - | Int_u -> "%nu" + | Int_u | Int_Cu -> "%nu" (* Generate the format_float first argument form a float_conv. *) let format_of_fconv fconv prec = @@ -1413,15 +1415,44 @@ let format_of_fconv fconv prec = buffer_add_char buf '%'; bprint_fconv_flag buf fconv; buffer_add_char buf '.'; - buffer_add_string buf (string_of_int prec); + buffer_add_string buf (Int.to_string prec); buffer_add_char buf symb; buffer_contents buf +let transform_int_alt iconv s = + match iconv with + | Int_Cd | Int_Ci | Int_Cu -> + let digits = + let n = ref 0 in + for i = 0 to String.length s - 1 do + match String.unsafe_get s i with + | '0'..'9' -> incr n + | _ -> () + done; + !n + in + let buf = Bytes.create (String.length s + (digits - 1) / 3) in + let pos = ref 0 in + let put c = Bytes.set buf !pos c; incr pos in + let left = ref ((digits - 1) mod 3 + 1) in + for i = 0 to String.length s - 1 do + match String.unsafe_get s i with + | '0'..'9' as c -> + if !left = 0 then (put '_'; left := 3); decr left; put c + | c -> put c + done; + Bytes.unsafe_to_string buf + | _ -> s + (* Convert an integer to a string according to a conversion. *) -let convert_int iconv n = format_int (format_of_iconv iconv) n -let convert_int32 iconv n = format_int32 (format_of_iconvl iconv) n -let convert_nativeint iconv n = format_nativeint (format_of_iconvn iconv) n -let convert_int64 iconv n = format_int64 (format_of_iconvL iconv) n +let convert_int iconv n = + transform_int_alt iconv (format_int (format_of_iconv iconv) n) +let convert_int32 iconv n = + transform_int_alt iconv (format_int32 (format_of_iconvl iconv) n) +let convert_nativeint iconv n = + transform_int_alt iconv (format_nativeint (format_of_iconvn iconv) n) +let convert_int64 iconv n = + transform_int_alt iconv (format_int64 (format_of_iconvL iconv) n) (* Convert a float to string. *) (* Fix special case of "OCaml float format". *) @@ -1480,39 +1511,39 @@ let string_of_fmtty fmtty = acc: rev list of printing entities (string, char, flush, formatting, ...). fmt: the format. *) let rec make_printf : type a b c d e f . - (b -> (b, c) acc -> f) -> b -> (b, c) acc -> + ((b, c) acc -> f) -> (b, c) acc -> (a, b, c, d, e, f) fmt -> a = -fun k o acc fmt -> match fmt with +fun k acc fmt -> match fmt with | Char rest -> fun c -> let new_acc = Acc_data_char (acc, c) in - make_printf k o new_acc rest + make_printf k new_acc rest | Caml_char rest -> fun c -> let new_acc = Acc_data_string (acc, format_caml_char c) in - make_printf k o new_acc rest + make_printf k new_acc rest | String (pad, rest) -> - make_padding k o acc rest pad (fun str -> str) + make_padding k acc rest pad (fun str -> str) | Caml_string (pad, rest) -> - make_padding k o acc rest pad string_to_caml_string + make_padding k acc rest pad string_to_caml_string | Int (iconv, pad, prec, rest) -> - make_int_padding_precision k o acc rest pad prec convert_int iconv + make_int_padding_precision k acc rest pad prec convert_int iconv | Int32 (iconv, pad, prec, rest) -> - make_int_padding_precision k o acc rest pad prec convert_int32 iconv + make_int_padding_precision k acc rest pad prec convert_int32 iconv | Nativeint (iconv, pad, prec, rest) -> - make_int_padding_precision k o acc rest pad prec convert_nativeint iconv + make_int_padding_precision k acc rest pad prec convert_nativeint iconv | Int64 (iconv, pad, prec, rest) -> - make_int_padding_precision k o acc rest pad prec convert_int64 iconv + make_int_padding_precision k acc rest pad prec convert_int64 iconv | Float (fconv, pad, prec, rest) -> - make_float_padding_precision k o acc rest pad prec fconv + make_float_padding_precision k acc rest pad prec fconv | Bool (pad, rest) -> - make_padding k o acc rest pad string_of_bool + make_padding k acc rest pad string_of_bool | Alpha rest -> - fun f x -> make_printf k o (Acc_delay (acc, fun o -> f o x)) rest + fun f x -> make_printf k (Acc_delay (acc, fun o -> f o x)) rest | Theta rest -> - fun f -> make_printf k o (Acc_delay (acc, f)) rest + fun f -> make_printf k (Acc_delay (acc, f)) rest | Custom (arity, f, rest) -> - make_custom k o acc rest arity (f ()) + make_custom k acc rest arity (f ()) | Reader _ -> (* This case is impossible, by typing of formats. *) (* Indeed, since printf and co. take a format4 as argument, the 'd and 'e @@ -1524,234 +1555,234 @@ fun k o acc fmt -> match fmt with itself recursively on the sub-format associated to %{...%}. *) assert false | Flush rest -> - make_printf k o (Acc_flush acc) rest + make_printf k (Acc_flush acc) rest | String_literal (str, rest) -> - make_printf k o (Acc_string_literal (acc, str)) rest + make_printf k (Acc_string_literal (acc, str)) rest | Char_literal (chr, rest) -> - make_printf k o (Acc_char_literal (acc, chr)) rest + make_printf k (Acc_char_literal (acc, chr)) rest | Format_arg (_, sub_fmtty, rest) -> let ty = string_of_fmtty sub_fmtty in (fun str -> ignore str; - make_printf k o (Acc_data_string (acc, ty)) rest) + make_printf k (Acc_data_string (acc, ty)) rest) | Format_subst (_, fmtty, rest) -> - fun (Format (fmt, _)) -> make_printf k o acc + fun (Format (fmt, _)) -> make_printf k acc (concat_fmt (recast fmt fmtty) rest) | Scan_char_set (_, _, rest) -> let new_acc = Acc_invalid_arg (acc, "Printf: bad conversion %[") in - fun _ -> make_printf k o new_acc rest + fun _ -> make_printf k new_acc rest | Scan_get_counter (_, rest) -> (* This case should be refused for Printf. *) (* Accepted for backward compatibility. *) (* Interpret %l, %n and %L as %u. *) fun n -> let new_acc = Acc_data_string (acc, format_int "%u" n) in - make_printf k o new_acc rest + make_printf k new_acc rest | Scan_next_char rest -> fun c -> let new_acc = Acc_data_char (acc, c) in - make_printf k o new_acc rest + make_printf k new_acc rest | Ignored_param (ign, rest) -> - make_ignored_param k o acc ign rest + make_ignored_param k acc ign rest | Formatting_lit (fmting_lit, rest) -> - make_printf k o (Acc_formatting_lit (acc, fmting_lit)) rest + make_printf k (Acc_formatting_lit (acc, fmting_lit)) rest | Formatting_gen (Open_tag (Format (fmt', _)), rest) -> - let k' koc kacc = - make_printf k koc (Acc_formatting_gen (acc, Acc_open_tag kacc)) rest in - make_printf k' o End_of_acc fmt' + let k' kacc = + make_printf k (Acc_formatting_gen (acc, Acc_open_tag kacc)) rest in + make_printf k' End_of_acc fmt' | Formatting_gen (Open_box (Format (fmt', _)), rest) -> - let k' koc kacc = - make_printf k koc (Acc_formatting_gen (acc, Acc_open_box kacc)) rest in - make_printf k' o End_of_acc fmt' + let k' kacc = + make_printf k (Acc_formatting_gen (acc, Acc_open_box kacc)) rest in + make_printf k' End_of_acc fmt' | End_of_format -> - k o acc + k acc (* Delay the error (Invalid_argument "Printf: bad conversion %_"). *) (* Generate functions to take remaining arguments (after the "%_"). *) and make_ignored_param : type x y a b c d e f . - (b -> (b, c) acc -> f) -> b -> (b, c) acc -> + ((b, c) acc -> f) -> (b, c) acc -> (a, b, c, d, y, x) ignored -> (x, b, c, y, e, f) fmt -> a = -fun k o acc ign fmt -> match ign with - | Ignored_char -> make_invalid_arg k o acc fmt - | Ignored_caml_char -> make_invalid_arg k o acc fmt - | Ignored_string _ -> make_invalid_arg k o acc fmt - | Ignored_caml_string _ -> make_invalid_arg k o acc fmt - | Ignored_int (_, _) -> make_invalid_arg k o acc fmt - | Ignored_int32 (_, _) -> make_invalid_arg k o acc fmt - | Ignored_nativeint (_, _) -> make_invalid_arg k o acc fmt - | Ignored_int64 (_, _) -> make_invalid_arg k o acc fmt - | Ignored_float (_, _) -> make_invalid_arg k o acc fmt - | Ignored_bool _ -> make_invalid_arg k o acc fmt - | Ignored_format_arg _ -> make_invalid_arg k o acc fmt - | Ignored_format_subst (_, fmtty) -> make_from_fmtty k o acc fmtty fmt +fun k acc ign fmt -> match ign with + | Ignored_char -> make_invalid_arg k acc fmt + | Ignored_caml_char -> make_invalid_arg k acc fmt + | Ignored_string _ -> make_invalid_arg k acc fmt + | Ignored_caml_string _ -> make_invalid_arg k acc fmt + | Ignored_int (_, _) -> make_invalid_arg k acc fmt + | Ignored_int32 (_, _) -> make_invalid_arg k acc fmt + | Ignored_nativeint (_, _) -> make_invalid_arg k acc fmt + | Ignored_int64 (_, _) -> make_invalid_arg k acc fmt + | Ignored_float (_, _) -> make_invalid_arg k acc fmt + | Ignored_bool _ -> make_invalid_arg k acc fmt + | Ignored_format_arg _ -> make_invalid_arg k acc fmt + | Ignored_format_subst (_, fmtty) -> make_from_fmtty k acc fmtty fmt | Ignored_reader -> assert false - | Ignored_scan_char_set _ -> make_invalid_arg k o acc fmt - | Ignored_scan_get_counter _ -> make_invalid_arg k o acc fmt - | Ignored_scan_next_char -> make_invalid_arg k o acc fmt + | Ignored_scan_char_set _ -> make_invalid_arg k acc fmt + | Ignored_scan_get_counter _ -> make_invalid_arg k acc fmt + | Ignored_scan_next_char -> make_invalid_arg k acc fmt (* Special case of printf "%_(". *) and make_from_fmtty : type x y a b c d e f . - (b -> (b, c) acc -> f) -> b -> (b, c) acc -> + ((b, c) acc -> f) -> (b, c) acc -> (a, b, c, d, y, x) fmtty -> (x, b, c, y, e, f) fmt -> a = -fun k o acc fmtty fmt -> match fmtty with - | Char_ty rest -> fun _ -> make_from_fmtty k o acc rest fmt - | String_ty rest -> fun _ -> make_from_fmtty k o acc rest fmt - | Int_ty rest -> fun _ -> make_from_fmtty k o acc rest fmt - | Int32_ty rest -> fun _ -> make_from_fmtty k o acc rest fmt - | Nativeint_ty rest -> fun _ -> make_from_fmtty k o acc rest fmt - | Int64_ty rest -> fun _ -> make_from_fmtty k o acc rest fmt - | Float_ty rest -> fun _ -> make_from_fmtty k o acc rest fmt - | Bool_ty rest -> fun _ -> make_from_fmtty k o acc rest fmt - | Alpha_ty rest -> fun _ _ -> make_from_fmtty k o acc rest fmt - | Theta_ty rest -> fun _ -> make_from_fmtty k o acc rest fmt - | Any_ty rest -> fun _ -> make_from_fmtty k o acc rest fmt +fun k acc fmtty fmt -> match fmtty with + | Char_ty rest -> fun _ -> make_from_fmtty k acc rest fmt + | String_ty rest -> fun _ -> make_from_fmtty k acc rest fmt + | Int_ty rest -> fun _ -> make_from_fmtty k acc rest fmt + | Int32_ty rest -> fun _ -> make_from_fmtty k acc rest fmt + | Nativeint_ty rest -> fun _ -> make_from_fmtty k acc rest fmt + | Int64_ty rest -> fun _ -> make_from_fmtty k acc rest fmt + | Float_ty rest -> fun _ -> make_from_fmtty k acc rest fmt + | Bool_ty rest -> fun _ -> make_from_fmtty k acc rest fmt + | Alpha_ty rest -> fun _ _ -> make_from_fmtty k acc rest fmt + | Theta_ty rest -> fun _ -> make_from_fmtty k acc rest fmt + | Any_ty rest -> fun _ -> make_from_fmtty k acc rest fmt | Reader_ty _ -> assert false | Ignored_reader_ty _ -> assert false - | Format_arg_ty (_, rest) -> fun _ -> make_from_fmtty k o acc rest fmt - | End_of_fmtty -> make_invalid_arg k o acc fmt + | Format_arg_ty (_, rest) -> fun _ -> make_from_fmtty k acc rest fmt + | End_of_fmtty -> make_invalid_arg k acc fmt | Format_subst_ty (ty1, ty2, rest) -> let ty = trans (symm ty1) ty2 in - fun _ -> make_from_fmtty k o acc (concat_fmtty ty rest) fmt + fun _ -> make_from_fmtty k acc (concat_fmtty ty rest) fmt (* Insert an Acc_invalid_arg in the accumulator and continue to generate closures to get the remaining arguments. *) and make_invalid_arg : type a b c d e f . - (b -> (b, c) acc -> f) -> b -> (b, c) acc -> + ((b, c) acc -> f) -> (b, c) acc -> (a, b, c, d, e, f) fmt -> a = -fun k o acc fmt -> - make_printf k o (Acc_invalid_arg (acc, "Printf: bad conversion %_")) fmt +fun k acc fmt -> + make_printf k (Acc_invalid_arg (acc, "Printf: bad conversion %_")) fmt (* Fix padding, take it as an extra integer argument if needed. *) and make_padding : type x z a b c d e f . - (b -> (b, c) acc -> f) -> b -> (b, c) acc -> + ((b, c) acc -> f) -> (b, c) acc -> (a, b, c, d, e, f) fmt -> (x, z -> a) padding -> (z -> string) -> x = - fun k o acc fmt pad trans -> match pad with + fun k acc fmt pad trans -> match pad with | No_padding -> fun x -> let new_acc = Acc_data_string (acc, trans x) in - make_printf k o new_acc fmt + make_printf k new_acc fmt | Lit_padding (padty, width) -> fun x -> let new_acc = Acc_data_string (acc, fix_padding padty width (trans x)) in - make_printf k o new_acc fmt + make_printf k new_acc fmt | Arg_padding padty -> fun w x -> let new_acc = Acc_data_string (acc, fix_padding padty w (trans x)) in - make_printf k o new_acc fmt + make_printf k new_acc fmt (* Fix padding and precision for int, int32, nativeint or int64. *) (* Take one or two extra integer arguments if needed. *) and make_int_padding_precision : type x y z a b c d e f . - (b -> (b, c) acc -> f) -> b -> (b, c) acc -> + ((b, c) acc -> f) -> (b, c) acc -> (a, b, c, d, e, f) fmt -> (x, y) padding -> (y, z -> a) precision -> (int_conv -> z -> string) -> int_conv -> x = - fun k o acc fmt pad prec trans iconv -> match pad, prec with + fun k acc fmt pad prec trans iconv -> match pad, prec with | No_padding, No_precision -> fun x -> let str = trans iconv x in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt | No_padding, Lit_precision p -> fun x -> let str = fix_int_precision p (trans iconv x) in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt | No_padding, Arg_precision -> fun p x -> let str = fix_int_precision p (trans iconv x) in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt | Lit_padding (padty, w), No_precision -> fun x -> let str = fix_padding padty w (trans iconv x) in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt | Lit_padding (padty, w), Lit_precision p -> fun x -> let str = fix_padding padty w (fix_int_precision p (trans iconv x)) in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt | Lit_padding (padty, w), Arg_precision -> fun p x -> let str = fix_padding padty w (fix_int_precision p (trans iconv x)) in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt | Arg_padding padty, No_precision -> fun w x -> let str = fix_padding padty w (trans iconv x) in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt | Arg_padding padty, Lit_precision p -> fun w x -> let str = fix_padding padty w (fix_int_precision p (trans iconv x)) in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt | Arg_padding padty, Arg_precision -> fun w p x -> let str = fix_padding padty w (fix_int_precision p (trans iconv x)) in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt (* Convert a float, fix padding and precision if needed. *) (* Take the float argument and one or two extra integer arguments if needed. *) and make_float_padding_precision : type x y a b c d e f . - (b -> (b, c) acc -> f) -> b -> (b, c) acc -> + ((b, c) acc -> f) -> (b, c) acc -> (a, b, c, d, e, f) fmt -> (x, y) padding -> (y, float -> a) precision -> float_conv -> x = - fun k o acc fmt pad prec fconv -> match pad, prec with + fun k acc fmt pad prec fconv -> match pad, prec with | No_padding, No_precision -> fun x -> let str = convert_float fconv default_float_precision x in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt | No_padding, Lit_precision p -> fun x -> let str = convert_float fconv p x in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt | No_padding, Arg_precision -> fun p x -> let str = convert_float fconv p x in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt | Lit_padding (padty, w), No_precision -> fun x -> let str = convert_float fconv default_float_precision x in let str' = fix_padding padty w str in - make_printf k o (Acc_data_string (acc, str')) fmt + make_printf k (Acc_data_string (acc, str')) fmt | Lit_padding (padty, w), Lit_precision p -> fun x -> let str = fix_padding padty w (convert_float fconv p x) in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt | Lit_padding (padty, w), Arg_precision -> fun p x -> let str = fix_padding padty w (convert_float fconv p x) in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt | Arg_padding padty, No_precision -> fun w x -> let str = convert_float fconv default_float_precision x in let str' = fix_padding padty w str in - make_printf k o (Acc_data_string (acc, str')) fmt + make_printf k (Acc_data_string (acc, str')) fmt | Arg_padding padty, Lit_precision p -> fun w x -> let str = fix_padding padty w (convert_float fconv p x) in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt | Arg_padding padty, Arg_precision -> fun w p x -> let str = fix_padding padty w (convert_float fconv p x) in - make_printf k o (Acc_data_string (acc, str)) fmt + make_printf k (Acc_data_string (acc, str)) fmt and make_custom : type x y a b c d e f . - (b -> (b, c) acc -> f) -> b -> (b, c) acc -> + ((b, c) acc -> f) -> (b, c) acc -> (a, b, c, d, e, f) fmt -> (a, x, y) custom_arity -> x -> y = - fun k o acc rest arity f -> match arity with - | Custom_zero -> make_printf k o (Acc_data_string (acc, f)) rest + fun k acc rest arity f -> match arity with + | Custom_zero -> make_printf k (Acc_data_string (acc, f)) rest | Custom_succ arity -> fun x -> - make_custom k o acc rest arity (f x) + make_custom k acc rest arity (f x) let const x _ = x -let rec make_iprintf : type a b c d e f. - (b -> f) -> b -> (a, b, c, d, e, f) fmt -> a = +let rec make_iprintf : type a b c d e f state. + (state -> f) -> state -> (a, b, c, d, e, f) fmt -> a = fun k o fmt -> match fmt with | Char rest -> const (make_iprintf k o rest) @@ -1814,7 +1845,7 @@ let rec make_iprintf : type a b c d e f. | Scan_next_char rest -> const (make_iprintf k o rest) | Ignored_param (ign, rest) -> - make_ignored_param (fun x _ -> k x) o (End_of_acc) ign rest + make_ignored_param (fun _ -> k o) (End_of_acc) ign rest | Formatting_lit (_, rest) -> make_iprintf k o rest | Formatting_gen (Open_tag (Format (fmt', _)), rest) -> @@ -1824,8 +1855,8 @@ let rec make_iprintf : type a b c d e f. | End_of_format -> k o and fn_of_padding_precision : - type x y z a b c d e f. - (b -> f) -> b -> (a, b, c, d, e, f) fmt -> + type x y z a b c d e f state. + (state -> f) -> state -> (a, b, c, d, e, f) fmt -> (x, y) padding -> (y, z -> a) precision -> x = fun k o fmt pad prec -> match pad, prec with | No_padding , No_precision -> @@ -1846,8 +1877,9 @@ and fn_of_padding_precision : const (const (make_iprintf k o fmt)) | Arg_padding _, Arg_precision -> const (const (const (make_iprintf k o fmt))) -and fn_of_custom_arity : type x y a b c d e f . - (b -> f) -> b -> (a, b, c, d, e, f) fmt -> (a, x, y) custom_arity -> y = +and fn_of_custom_arity : type x y a b c d e f state. + (state -> f) -> + state -> (a, b, c, d, e, f) fmt -> (a, x, y) custom_arity -> y = fun k o fmt -> function | Custom_zero -> make_iprintf k o fmt @@ -1924,8 +1956,8 @@ let rec strput_acc b acc = match acc with (* Raise [Failure] with a pretty-printed error message. *) let failwith_message (Format (fmt, _)) = let buf = Buffer.create 256 in - let k () acc = strput_acc buf acc; failwith (Buffer.contents buf) in - make_printf k () End_of_acc fmt + let k acc = strput_acc buf acc; failwith (Buffer.contents buf) in + make_printf k End_of_acc fmt (******************************************************************************) (* Formatting tools *) @@ -2550,7 +2582,7 @@ let fmt_ebb_of_string ?legacy_behavior str = end; fmt_result - (* Parse formatting informations (after '@'). *) + (* Parse formatting information (after '@'). *) and parse_after_at : type e f . int -> int -> (_, _, e, f) fmt_ebb = fun str_ind end_ind -> if str_ind = end_ind then Fmt_EBB (Char_literal ('@', End_of_format)) @@ -2883,6 +2915,9 @@ let fmt_ebb_of_string ?legacy_behavior str = | false, false, false, 'o' -> Int_o | false, true, false, 'o' -> Int_Co | false, false, false, 'u' -> Int_u + | false, true, false, 'd' -> Int_Cd + | false, true, false, 'i' -> Int_Ci + | false, true, false, 'u' -> Int_Cu | _, true, _, 'x' when legacy_behavior -> Int_Cx | _, true, _, 'X' when legacy_behavior -> Int_CX | _, true, _, 'o' when legacy_behavior -> Int_Co diff --git a/stdlib/camlinternalFormat.mli b/stdlib/camlinternalFormat.mli index ccb4076c..94d77729 100644 --- a/stdlib/camlinternalFormat.mli +++ b/stdlib/camlinternalFormat.mli @@ -58,10 +58,10 @@ type ('b, 'c, 'e, 'f) fmt_ebb = Fmt_EBB : ('b, 'c, 'e, 'f) fmt_ebb val make_printf : - ('b -> ('b, 'c) acc -> 'd) -> 'b -> ('b, 'c) acc -> + (('b, 'c) acc -> 'd) -> ('b, 'c) acc -> ('a, 'b, 'c, 'c, 'c, 'd) CamlinternalFormatBasics.fmt -> 'a -val make_iprintf : ('b -> 'f) -> 'b -> ('a, 'b, 'c, 'd, 'e, 'f) fmt -> 'a +val make_iprintf : ('s -> 'f) -> 's -> ('a, 'b, 'c, 'd, 'e, 'f) fmt -> 'a val output_acc : out_channel -> (out_channel, unit) acc -> unit val bufput_acc : Buffer.t -> (Buffer.t, unit) acc -> unit diff --git a/stdlib/camlinternalFormatBasics.ml b/stdlib/camlinternalFormatBasics.ml index 04743426..03e973ce 100644 --- a/stdlib/camlinternalFormatBasics.ml +++ b/stdlib/camlinternalFormatBasics.ml @@ -29,6 +29,7 @@ type int_conv = | Int_X | Int_CX (* %X | %#X *) | Int_o | Int_Co (* %o | %#o *) | Int_u (* %u *) + | Int_Cd | Int_Ci | Int_Cu (* %#d | %#i | %#u *) (* Float conversion. *) type float_conv = diff --git a/stdlib/camlinternalFormatBasics.mli b/stdlib/camlinternalFormatBasics.mli index 3c351ef7..4b7f4389 100644 --- a/stdlib/camlinternalFormatBasics.mli +++ b/stdlib/camlinternalFormatBasics.mli @@ -20,6 +20,7 @@ type padty = Left | Right | Zeros type int_conv = | Int_d | Int_pd | Int_sd | Int_i | Int_pi | Int_si | Int_x | Int_Cx | Int_X | Int_CX | Int_o | Int_Co | Int_u + | Int_Cd | Int_Ci | Int_Cu type float_conv = | Float_f | Float_pf | Float_sf | Float_e | Float_pe | Float_se diff --git a/stdlib/camlinternalLazy.ml b/stdlib/camlinternalLazy.ml index f64be62e..bc727b73 100644 --- a/stdlib/camlinternalLazy.ml +++ b/stdlib/camlinternalLazy.ml @@ -15,6 +15,8 @@ (* Internals of forcing lazy values. *) +type 'a t = 'a lazy_t + exception Undefined let raise_undefined = Obj.repr (fun () -> raise Undefined) diff --git a/stdlib/camlinternalLazy.mli b/stdlib/camlinternalLazy.mli index 101535cd..7d04087f 100644 --- a/stdlib/camlinternalLazy.mli +++ b/stdlib/camlinternalLazy.mli @@ -19,6 +19,8 @@ exception Undefined +type 'a t = 'a lazy_t + val force_lazy_block : 'a lazy_t -> 'a val force_val_lazy_block : 'a lazy_t -> 'a diff --git a/stdlib/char.mli b/stdlib/char.mli index 5d5fc033..aaa627e4 100644 --- a/stdlib/char.mli +++ b/stdlib/char.mli @@ -57,7 +57,7 @@ type t = char val compare: t -> t -> int (** The comparison function for characters, with the same specification as - {!Pervasives.compare}. Along with the type [t], this function [compare] + {!Stdlib.compare}. Along with the type [t], this function [compare] allows the module [Char] to be passed as argument to the functors {!Set.Make} and {!Map.Make}. *) diff --git a/stdlib/digest.mli b/stdlib/digest.mli index 2c9bebc5..9f9fd534 100644 --- a/stdlib/digest.mli +++ b/stdlib/digest.mli @@ -29,7 +29,7 @@ type t = string val compare : t -> t -> int (** The comparison function for 16-character digest, with the same - specification as {!Pervasives.compare} and the implementation + specification as {!Stdlib.compare} and the implementation shared with {!String.compare}. Along with the type [t], this function [compare] allows the module [Digest] to be passed as argument to the functors {!Set.Make} and {!Map.Make}. diff --git a/stdlib/dune b/stdlib/dune new file mode 100644 index 00000000..ee66f6e7 --- /dev/null +++ b/stdlib/dune @@ -0,0 +1,36 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +(library + (name stdlib) + (stdlib + (exit_module std_exit) + (internal_modules Camlinternal*) + (modules_before_stdlib + camlinternalFormatBasics)) + (flags (:standard -w -9 -nolabels)) + (preprocess + (per_module + ((action + (run awk -v dune_wrapped=true + -f %{dep:expand_module_aliases.awk} %{input-file})) + stdlib)))) + +(rule + (targets sys.ml) + (deps (:version ../VERSION) (:p sys.mlp)) + (action + (with-stdout-to %{targets} + (bash + "sed -e \"s|%%VERSION%%|`sed -e 1q %{version} | tr -d '\r'`|\" %{p}")))) diff --git a/stdlib/ephemeron.ml b/stdlib/ephemeron.ml index 24bd1e70..b630c15b 100644 --- a/stdlib/ephemeron.ml +++ b/stdlib/ephemeron.ml @@ -482,6 +482,10 @@ module K1 = struct let hash (_seed: int) x = H.hash x end) let create sz = create ~random:false sz + let of_seq i = + let tbl = create 16 in + replace_seq tbl i; + tbl end end @@ -570,6 +574,10 @@ module K2 = struct let hash (_seed: int) x = H2.hash x end) let create sz = create ~random:false sz + let of_seq i = + let tbl = create 16 in + replace_seq tbl i; + tbl end end @@ -670,5 +678,9 @@ module Kn = struct let hash (_seed: int) x = H.hash x end) let create sz = create ~random:false sz + let of_seq i = + let tbl = create 16 in + replace_seq tbl i; + tbl end end diff --git a/stdlib/ephemeron.mli b/stdlib/ephemeron.mli index efa5f661..66a3e9ac 100644 --- a/stdlib/ephemeron.mli +++ b/stdlib/ephemeron.mli @@ -56,7 +56,7 @@ Notes: - All the types defined in this module cannot be marshaled - using {!Pervasives.output_value} or the functions of the + using {!Stdlib.output_value} or the functions of the {!Marshal} module. Ephemerons are defined in a language agnostic way in this paper: diff --git a/stdlib/expand_module_aliases.awk b/stdlib/expand_module_aliases.awk index c373b351..7f1e49ba 100644 --- a/stdlib/expand_module_aliases.awk +++ b/stdlib/expand_module_aliases.awk @@ -22,6 +22,12 @@ NR == 1 { printf ("# 1 \"%s\"\n", FILENAME) } else if (state==1) state=2; else if ($1 == "module") - printf ("\n(** @canonical %s *)\nmodule %s = Stdlib__%s%s\n", - $2, $2, tolower(substr($4,1,1)), substr($4,2)); + { if (ocamldoc!="true") printf("\n(** @canonical %s *)", $2); + first_letter=substr($4,1,1); + if (dune_wrapped!="true") + first_letter=tolower(first_letter); + printf("\nmodule %s = Stdlib__%s%s\n", $2, first_letter, substr($4,2)); + } + else + print } diff --git a/stdlib/filename.ml b/stdlib/filename.ml index f9b0bc6c..18827aa2 100644 --- a/stdlib/filename.ml +++ b/stdlib/filename.ml @@ -83,6 +83,18 @@ module Unix = struct String.length name >= String.length suff && String.sub name (String.length name - String.length suff) (String.length suff) = suff + + let chop_suffix_opt ~suffix filename = + let len_s = String.length suffix and len_f = String.length filename in + if len_f >= len_s then + let r = String.sub filename (len_f - len_s) len_s in + if r = suffix then + Some (String.sub filename 0 (len_f - len_s)) + else + None + else + None + let temp_dir_name = try Sys.getenv "TMPDIR" with Not_found -> "/tmp" let quote = generic_quote "'\\''" @@ -110,6 +122,19 @@ module Win32 = struct (let s = String.sub name (String.length name - String.length suff) (String.length suff) in String.lowercase_ascii s = String.lowercase_ascii suff) + + let chop_suffix_opt ~suffix filename = + let len_s = String.length suffix and len_f = String.length filename in + if len_f >= len_s then + let r = String.sub filename (len_f - len_s) len_s in + if String.lowercase_ascii r = String.lowercase_ascii suffix then + Some (String.sub filename 0 (len_f - len_s)) + else + None + else + None + + let temp_dir_name = try Sys.getenv "TEMP" with Not_found -> "." let quote s = @@ -163,6 +188,7 @@ module Cygwin = struct let is_relative = Win32.is_relative let is_implicit = Win32.is_implicit let check_suffix = Win32.check_suffix + let chop_suffix_opt = Win32.chop_suffix_opt let temp_dir_name = Unix.temp_dir_name let quote = Unix.quote let basename = generic_basename is_dir_sep current_dir_name @@ -170,23 +196,27 @@ module Cygwin = struct end let (current_dir_name, parent_dir_name, dir_sep, is_dir_sep, - is_relative, is_implicit, check_suffix, temp_dir_name, quote, basename, + is_relative, is_implicit, check_suffix, chop_suffix_opt, + temp_dir_name, quote, basename, dirname) = match Sys.os_type with | "Win32" -> (Win32.current_dir_name, Win32.parent_dir_name, Win32.dir_sep, Win32.is_dir_sep, Win32.is_relative, Win32.is_implicit, Win32.check_suffix, + Win32.chop_suffix_opt, Win32.temp_dir_name, Win32.quote, Win32.basename, Win32.dirname) | "Cygwin" -> (Cygwin.current_dir_name, Cygwin.parent_dir_name, Cygwin.dir_sep, Cygwin.is_dir_sep, Cygwin.is_relative, Cygwin.is_implicit, Cygwin.check_suffix, + Cygwin.chop_suffix_opt, Cygwin.temp_dir_name, Cygwin.quote, Cygwin.basename, Cygwin.dirname) | _ -> (* normally "Unix" *) (Unix.current_dir_name, Unix.parent_dir_name, Unix.dir_sep, Unix.is_dir_sep, Unix.is_relative, Unix.is_implicit, Unix.check_suffix, + Unix.chop_suffix_opt, Unix.temp_dir_name, Unix.quote, Unix.basename, Unix.dirname) let concat dirname filename = diff --git a/stdlib/filename.mli b/stdlib/filename.mli index fa6f0369..b05ad0d2 100644 --- a/stdlib/filename.mli +++ b/stdlib/filename.mli @@ -42,12 +42,33 @@ val is_implicit : string -> bool val check_suffix : string -> string -> bool (** [check_suffix name suff] returns [true] if the filename [name] - ends with the suffix [suff]. *) + ends with the suffix [suff]. + + Under Windows ports (including Cygwin), comparison is + case-insensitive, relying on [String.lowercase_ascii]. Note that + this does not match exactly the interpretation of case-insensitive + filename equivalence from Windows. *) val chop_suffix : string -> string -> string (** [chop_suffix name suff] removes the suffix [suff] from the filename [name]. The behavior is undefined if [name] does not - end with the suffix [suff]. *) + end with the suffix [suff]. It is thus recommmended to use + [chop_suffix_opt] instead. +*) + +val chop_suffix_opt: suffix:string -> string -> string option +(** [chop_suffix_opt ~suffix filename] removes the suffix from + the [filename] if possible, or returns [None] if the + filename does not end with the suffix. + + Under Windows ports (including Cygwin), comparison is + case-insensitive, relying on [String.lowercase_ascii]. Note that + this does not match exactly the interpretation of case-insensitive + filename equivalence from Windows. + + @since 4.08 +*) + val extension : string -> string (** [extension name] is the shortest suffix [ext] of [name0] where: diff --git a/stdlib/float.ml b/stdlib/float.ml index 3cd01006..3145f1c6 100644 --- a/stdlib/float.ml +++ b/stdlib/float.ml @@ -21,20 +21,30 @@ external mul : float -> float -> float = "%mulfloat" external div : float -> float -> float = "%divfloat" external rem : float -> float -> float = "caml_fmod_float" "fmod" [@@unboxed] [@@noalloc] +external fma : float -> float -> float -> float = "caml_fma_float" "caml_fma" + [@@unboxed] [@@noalloc] external abs : float -> float = "%absfloat" -let infinity = Pervasives.infinity -let neg_infinity = Pervasives.neg_infinity -let nan = Pervasives.nan + +let zero = 0. +let one = 1. +let minus_one = -1. +let infinity = Stdlib.infinity +let neg_infinity = Stdlib.neg_infinity +let nan = Stdlib.nan +let is_finite (x: float) = x -. x = 0. +let is_infinite (x: float) = 1. /. x = 0. +let is_nan (x: float) = x <> x + let pi = 0x1.921fb54442d18p+1 -let max_float = Pervasives.max_float -let min_float = Pervasives.min_float -let epsilon = Pervasives.epsilon_float +let max_float = Stdlib.max_float +let min_float = Stdlib.min_float +let epsilon = Stdlib.epsilon_float external of_int : int -> float = "%floatofint" external to_int : float -> int = "%intoffloat" external of_string : string -> float = "caml_float_of_string" -let of_string_opt = Pervasives.float_of_string_opt -let to_string = Pervasives.string_of_float -type fpclass = Pervasives.fpclass = +let of_string_opt = Stdlib.float_of_string_opt +let to_string = Stdlib.string_of_float +type fpclass = Stdlib.fpclass = FP_normal | FP_subnormal | FP_zero @@ -73,13 +83,29 @@ external sinh : float -> float = "caml_sinh_float" "sinh" [@@unboxed] [@@noalloc] external tanh : float -> float = "caml_tanh_float" "tanh" [@@unboxed] [@@noalloc] +external trunc : float -> float = "caml_trunc_float" "caml_trunc" + [@@unboxed] [@@noalloc] +external round : float -> float = "caml_round_float" "caml_round" + [@@unboxed] [@@noalloc] external ceil : float -> float = "caml_ceil_float" "ceil" [@@unboxed] [@@noalloc] external floor : float -> float = "caml_floor_float" "floor" [@@unboxed] [@@noalloc] -external copysign : float -> float -> float + +let is_integer x = x = trunc x && is_finite x + +external next_after : float -> float -> float + = "caml_nextafter_float" "caml_nextafter" [@@unboxed] [@@noalloc] + +let succ x = next_after x infinity +let pred x = next_after x neg_infinity + +external copy_sign : float -> float -> float = "caml_copysign_float" "caml_copysign" [@@unboxed] [@@noalloc] +external sign_bit : (float [@unboxed]) -> bool + = "caml_signbit_float" "caml_signbit" [@@noalloc] + external frexp : float -> float * int = "caml_frexp_float" external ldexp : (float [@unboxed]) -> (int [@untagged]) -> (float [@unboxed]) = "caml_ldexp_float" "caml_ldexp_float_unboxed" [@@noalloc] @@ -87,15 +113,399 @@ external modf : float -> float * float = "caml_modf_float" type t = float external compare : float -> float -> int = "%compare" let equal x y = compare x y = 0 -external seeded_hash_param : int -> int -> int -> float -> int = "caml_hash" [@@noalloc] + +let[@inline] min (x: float) (y: float) = + if y > x || (not(sign_bit y) && sign_bit x) then + if is_nan y then y else x + else if is_nan x then x else y + +let[@inline] max (x: float) (y: float) = + if y > x || (not(sign_bit y) && sign_bit x) then + if is_nan x then x else y + else if is_nan y then y else x + +let[@inline] min_max (x: float) (y: float) = + if is_nan x || is_nan y then (nan, nan) + else if y > x || (not(sign_bit y) && sign_bit x) then (x, y) else (y, x) + +let[@inline] min_num (x: float) (y: float) = + if y > x || (not(sign_bit y) && sign_bit x) then + if is_nan x then y else x + else if is_nan y then x else y + +let[@inline] max_num (x: float) (y: float) = + if y > x || (not(sign_bit y) && sign_bit x) then + if is_nan y then x else y + else if is_nan x then y else x + +let[@inline] min_max_num (x: float) (y: float) = + if is_nan x then (y,y) + else if is_nan y then (x,x) + else if y > x || (not(sign_bit y) && sign_bit x) then (x,y) else (y,x) + +external seeded_hash_param : int -> int -> int -> float -> int + = "caml_hash" [@@noalloc] let hash x = seeded_hash_param 10 100 0 x module Array = struct + type t = floatarray - external create : int -> t = "caml_floatarray_create" + external length : t -> int = "%floatarray_length" external get : t -> int -> float = "%floatarray_safe_get" external set : t -> int -> float -> unit = "%floatarray_safe_set" + external create : int -> t = "caml_floatarray_create" external unsafe_get : t -> int -> float = "%floatarray_unsafe_get" external unsafe_set : t -> int -> float -> unit = "%floatarray_unsafe_set" + + let unsafe_fill a ofs len v = + for i = ofs to ofs + len - 1 do unsafe_set a i v done + + let unsafe_blit src sofs dst dofs len = + for i = 0 to len - 1 do + unsafe_set dst (dofs + i) (unsafe_get src (sofs + i)) + done + + let check a ofs len msg = + if ofs < 0 || len < 0 || ofs + len < 0 || ofs + len > length a then + invalid_arg msg + + let make n v = + let result = create n in + unsafe_fill result 0 n v; + result + + let init l f = + if l < 0 then invalid_arg "Float.Array.init" + else + let res = create l in + for i = 0 to l - 1 do + unsafe_set res i (f i) + done; + res + + let append a1 a2 = + let l1 = length a1 in + let l2 = length a2 in + let result = create (l1 + l2) in + unsafe_blit a1 0 result 0 l1; + unsafe_blit a2 0 result l1 l2; + result + + (* next 3 functions: modified copy of code from string.ml *) + let ensure_ge (x:int) y = + if x >= y then x else invalid_arg "Float.Array.concat" + + let rec sum_lengths acc = function + | [] -> acc + | hd :: tl -> sum_lengths (ensure_ge (length hd + acc) acc) tl + + let concat l = + let len = sum_lengths 0 l in + let result = create len in + let rec loop l i = + match l with + | [] -> assert (i = len) + | hd :: tl -> + let hlen = length hd in + unsafe_blit hd 0 result i hlen; + loop tl (i + hlen) + in + loop l 0; + result + + let sub a ofs len = + check a ofs len "Float.Array.sub"; + let result = create len in + unsafe_blit a ofs result 0 len; + result + + let copy a = + let l = length a in + let result = create l in + unsafe_blit a 0 result 0 l; + result + + let fill a ofs len v = + check a ofs len "Float.Array.fill"; + unsafe_fill a ofs len v + + let blit src sofs dst dofs len = + check src sofs len "Float.array.blit"; + check dst dofs len "Float.array.blit"; + unsafe_blit src sofs dst dofs len + + let to_list a = + List.init (length a) (unsafe_get a) + + let of_list l = + let result = create (List.length l) in + let rec fill i l = + match l with + | [] -> result + | h :: t -> unsafe_set result i h; fill (i + 1) t + in + fill 0 l + + (* duplicated from array.ml *) + let iter f a = + for i = 0 to length a - 1 do f (unsafe_get a i) done + + (* duplicated from array.ml *) + let iter2 f a b = + if length a <> length b then + invalid_arg "Float.Array.iter2: arrays must have the same length" + else + for i = 0 to length a - 1 do f (unsafe_get a i) (unsafe_get b i) done + + let map f a = + let l = length a in + let r = create l in + for i = 0 to l - 1 do + unsafe_set r i (f (unsafe_get a i)) + done; + r + + let map2 f a b = + let la = length a in + let lb = length b in + if la <> lb then + invalid_arg "Float.Array.map2: arrays must have the same length" + else begin + let r = create la in + for i = 0 to la - 1 do + unsafe_set r i (f (unsafe_get a i) (unsafe_get b i)) + done; + r + end + + (* duplicated from array.ml *) + let iteri f a = + for i = 0 to length a - 1 do f i (unsafe_get a i) done + + let mapi f a = + let l = length a in + let r = create l in + for i = 0 to l - 1 do + unsafe_set r i (f i (unsafe_get a i)) + done; + r + + (* duplicated from array.ml *) + let fold_left f x a = + let r = ref x in + for i = 0 to length a - 1 do + r := f !r (unsafe_get a i) + done; + !r + + (* duplicated from array.ml *) + let fold_right f a x = + let r = ref x in + for i = length a - 1 downto 0 do + r := f (unsafe_get a i) !r + done; + !r + + (* duplicated from array.ml *) + let exists p a = + let n = length a in + let rec loop i = + if i = n then false + else if p (unsafe_get a i) then true + else loop (i + 1) in + loop 0 + + (* duplicated from array.ml *) + let for_all p a = + let n = length a in + let rec loop i = + if i = n then true + else if p (unsafe_get a i) then loop (i + 1) + else false in + loop 0 + + (* duplicated from array.ml *) + let mem x a = + let n = length a in + let rec loop i = + if i = n then false + else if compare (unsafe_get a i) x = 0 then true + else loop (i + 1) + in + loop 0 + + (* mostly duplicated from array.ml, but slightly different *) + let mem_ieee x a = + let n = length a in + let rec loop i = + if i = n then false + else if x = (unsafe_get a i) then true + else loop (i + 1) + in + loop 0 + + (* duplicated from array.ml *) + exception Bottom of int + let sort cmp a = + let maxson l i = + let i31 = i+i+i+1 in + let x = ref i31 in + if i31+2 < l then begin + if cmp (get a i31) (get a (i31+1)) < 0 then x := i31+1; + if cmp (get a !x) (get a (i31+2)) < 0 then x := i31+2; + !x + end else + if i31+1 < l && cmp (get a i31) (get a (i31+1)) < 0 + then i31+1 + else if i31 < l then i31 else raise (Bottom i) + in + let rec trickledown l i e = + let j = maxson l i in + if cmp (get a j) e > 0 then begin + set a i (get a j); + trickledown l j e; + end else begin + set a i e; + end; + in + let trickle l i e = try trickledown l i e with Bottom i -> set a i e in + let rec bubbledown l i = + let j = maxson l i in + set a i (get a j); + bubbledown l j + in + let bubble l i = try bubbledown l i with Bottom i -> i in + let rec trickleup i e = + let father = (i - 1) / 3 in + assert (i <> father); + if cmp (get a father) e < 0 then begin + set a i (get a father); + if father > 0 then trickleup father e else set a 0 e; + end else begin + set a i e; + end; + in + let l = length a in + for i = (l + 1) / 3 - 1 downto 0 do trickle l i (get a i); done; + for i = l - 1 downto 2 do + let e = (get a i) in + set a i (get a 0); + trickleup (bubble i 0) e; + done; + if l > 1 then (let e = (get a 1) in set a 1 (get a 0); set a 0 e) + + (* duplicated from array.ml, except for the call to [create] *) + let cutoff = 5 + let stable_sort cmp a = + let merge src1ofs src1len src2 src2ofs src2len dst dstofs = + let src1r = src1ofs + src1len and src2r = src2ofs + src2len in + let rec loop i1 s1 i2 s2 d = + if cmp s1 s2 <= 0 then begin + set dst d s1; + let i1 = i1 + 1 in + if i1 < src1r then + loop i1 (get a i1) i2 s2 (d + 1) + else + blit src2 i2 dst (d + 1) (src2r - i2) + end else begin + set dst d s2; + let i2 = i2 + 1 in + if i2 < src2r then + loop i1 s1 i2 (get src2 i2) (d + 1) + else + blit a i1 dst (d + 1) (src1r - i1) + end + in loop src1ofs (get a src1ofs) src2ofs (get src2 src2ofs) dstofs; + in + let isortto srcofs dst dstofs len = + for i = 0 to len - 1 do + let e = (get a (srcofs + i)) in + let j = ref (dstofs + i - 1) in + while (!j >= dstofs && cmp (get dst !j) e > 0) do + set dst (!j + 1) (get dst !j); + decr j; + done; + set dst (!j + 1) e; + done; + in + let rec sortto srcofs dst dstofs len = + if len <= cutoff then isortto srcofs dst dstofs len else begin + let l1 = len / 2 in + let l2 = len - l1 in + sortto (srcofs + l1) dst (dstofs + l1) l2; + sortto srcofs a (srcofs + l2) l1; + merge (srcofs + l2) l1 dst (dstofs + l1) l2 dst dstofs; + end; + in + let l = length a in + if l <= cutoff then isortto 0 a 0 l else begin + let l1 = l / 2 in + let l2 = l - l1 in + let t = create l2 in + sortto l1 t 0 l2; + sortto 0 a l2 l1; + merge l2 l1 t 0 l2 a 0; + end + + let fast_sort = stable_sort + + (* duplicated from array.ml *) + let to_seq a = + let rec aux i () = + if i < length a + then + let x = unsafe_get a i in + Seq.Cons (x, aux (i+1)) + else Seq.Nil + in + aux 0 + + (* duplicated from array.ml *) + let to_seqi a = + let rec aux i () = + if i < length a + then + let x = unsafe_get a i in + Seq.Cons ((i,x), aux (i+1)) + else Seq.Nil + in + aux 0 + + (* mostly duplicated from array.ml *) + let of_rev_list l = + let len = List.length l in + let a = create len in + let rec fill i = function + [] -> a + | hd::tl -> unsafe_set a i hd; fill (i-1) tl + in + fill (len-1) l + + (* duplicated from array.ml *) + let of_seq i = + let l = Seq.fold_left (fun acc x -> x::acc) [] i in + of_rev_list l + + + let map_to_array f a = + let l = length a in + if l = 0 then [| |] else begin + let r = Array.make l (f (unsafe_get a 0)) in + for i = 1 to l - 1 do + Array.unsafe_set r i (f (unsafe_get a i)) + done; + r + end + + let map_from_array f a = + let l = Array.length a in + let r = create l in + for i = 0 to l - 1 do + unsafe_set r i (f (Array.unsafe_get a i)) + done; + r + end + +module ArrayLabels = Array diff --git a/stdlib/float.mli b/stdlib/float.mli index f7b4cd8d..70d6ab8a 100644 --- a/stdlib/float.mli +++ b/stdlib/float.mli @@ -30,6 +30,18 @@ @since 4.07.0 *) +val zero : float +(** The floating point 0. + @since 4.08.0 *) + +val one : float +(** The floating-point 1. + @since 4.08.0 *) + +val minus_one : float +(** The floating-point -1. + @since 4.08.0 *) + external neg : float -> float = "%negfloat" (** Unary negation. *) @@ -45,12 +57,33 @@ external mul : float -> float -> float = "%mulfloat" external div : float -> float -> float = "%divfloat" (** Floating-point division. *) +external fma : float -> float -> float -> float = + "caml_fma_float" "caml_fma" [@@unboxed] [@@noalloc] +(** [fma x y z] returns [x * y + z], with a best effort for computing + this expression with a single rounding, using either hardware + instructions (providing full IEEE compliance) or a software + emulation. Note: since software emulation of the fma is costly, + make sure that you are using hardware fma support if performance + matters. @since 4.08.0 *) + external rem : float -> float -> float = "caml_fmod_float" "fmod" [@@unboxed] [@@noalloc] (** [rem a b] returns the remainder of [a] with respect to [b]. The returned value is [a -. n *. b], where [n] is the quotient [a /. b] rounded towards zero to an integer. *) +val succ : float -> float +(** [succ x] returns the floating point number right after [x] i.e., + the smallest floating-point number greater than [x]. See also + {!next_after}. + @since 4.08.0 *) + +val pred : float -> float +(** [pred x] returns the floating-point number right before [x] i.e., + the greatest floating-point number smaller than [x]. See also + {!next_after}. + @since 4.08.0 *) + external abs : float -> float = "%absfloat" (** [abs f] returns the absolute value of [f]. *) @@ -81,6 +114,27 @@ val epsilon : float (** The difference between [1.0] and the smallest exactly representable floating-point number greater than [1.0]. *) +val is_finite : float -> bool +(** [is_finite x] is [true] iff [x] is finite i.e., not infinite and + not {!nan}. + + @since 4.08.0 *) + +val is_infinite : float -> bool +(** [is_infinite x] is [true] iff [x] is {!infinity} or {!neg_infinity}. + + @since 4.08.0 *) + +val is_nan : float -> bool +(** [is_nan x] is [true] iff [x] is not a number (see {!nan}). + + @since 4.08.0 *) + +val is_integer : float -> bool +(** [is_integer x] is [true] iff [x] is an integer. + + @since 4.08.0 *) + external of_int : int -> float = "%floatofint" (** Convert an integer to floating-point. *) @@ -112,7 +166,7 @@ val of_string_opt: string -> float option val to_string : float -> string (** Return the string representation of a floating-point number. *) -type fpclass = Pervasives.fpclass = +type fpclass = Stdlib.fpclass = FP_normal (** Normal number, none of the below *) | FP_subnormal (** Number very close to 0.0, has reduced precision *) | FP_zero (** Number is 0.0 or -0.0 *) @@ -204,6 +258,22 @@ external tanh : float -> float = "caml_tanh_float" "tanh" [@@unboxed] [@@noalloc] (** Hyperbolic tangent. Argument is in radians. *) +external trunc : float -> float = "caml_trunc_float" "caml_trunc" + [@@unboxed] [@@noalloc] +(** [trunc x] rounds [x] to the nearest integer whose absolute value is + less than or equal to [x]. + + @since 4.08.0 *) + +external round : float -> float = "caml_round_float" "caml_round" + [@@unboxed] [@@noalloc] +(** [round x] rounds [x] to the nearest integer with ties (fractional + values of 0.5) rounded away from zero, regardless of the current + rounding direction. If [x] is an integer, [+0.], [-0.], [nan], or + infinite, [x] itself is returned. + + @since 4.08.0 *) + external ceil : float -> float = "caml_ceil_float" "ceil" [@@unboxed] [@@noalloc] (** Round above to an integer value. @@ -217,14 +287,37 @@ external floor : float -> float = "caml_floor_float" "floor" equal to [f]. The result is returned as a float. *) -external copysign : float -> float -> float +external next_after : float -> float -> float + = "caml_nextafter_float" "caml_nextafter" [@@unboxed] [@@noalloc] +(** [next_after x y] returns the next representable floating-point + value following [x] in the direction of [y]. More precisely, if + [y] is greater (resp. less) than [x], it returns the smallest + (resp. largest) representable number greater (resp. less) than [x]. + If [x] equals [y], the function returns [y]. If [x] or [y] is + [nan], a [nan] is returned. + Note that [next_after max_float infinity = infinity] and that + [next_after 0. infinity] is the smallest denormalized positive number. + If [x] is the smallest denormalized positive number, + [next_after x 0. = 0.] + + @since 4.08.0 *) + +external copy_sign : float -> float -> float = "caml_copysign_float" "caml_copysign" [@@unboxed] [@@noalloc] -(** [copysign x y] returns a float whose absolute value is that of [x] +(** [copy_sign x y] returns a float whose absolute value is that of [x] and whose sign is that of [y]. If [x] is [nan], returns [nan]. If [y] is [nan], returns either [x] or [-. x], but it is not specified which. *) +external sign_bit : (float [@unboxed]) -> bool + = "caml_signbit_float" "caml_signbit" [@@noalloc] +(** [sign_bit x] is [true] iff the sign bit of [x] is set. + For example [sign_bit 1.] and [signbit 0.] are [false] while + [sign_bit (-1.)] and [sign_bit (-0.)] are [true]. + + @since 4.08.0 *) + external frexp : float -> float * int = "caml_frexp_float" (** [frexp f] returns the pair of the significant and the exponent of [f]. When [f] is zero, the @@ -253,15 +346,313 @@ val compare: t -> t -> int val equal: t -> t -> bool (** The equal function for floating-point numbers, compared using {!compare}. *) +val min : t -> t -> t +(** [min x y] returns the minimum of [x] and [y]. It returns [nan] + when [x] or [y] is [nan]. Moreover [min (-0.) (+0.) = -0.] + + @since 4.08.0 *) + +val max : float -> float -> float +(** [max x y] returns the maximum of [x] and [y]. It returns [nan] + when [x] or [y] is [nan]. Moreover [max (-0.) (+0.) = +0.] + + @since 4.08.0 *) + +val min_max : float -> float -> float * float +(** [min_max x y] is [(min x y, max x y)], just more efficient. + + @since 4.08.0 *) + +val min_num : t -> t -> t +(** [min_num x y] returns the minimum of [x] and [y] treating [nan] as + missing values. If both [x] and [y] are [nan], [nan] is returned. + Moreover [min_num (-0.) (+0.) = -0.] + + @since 4.08.0 *) + +val max_num : t -> t -> t +(** [max_num x y] returns the maximum of [x] and [y] treating [nan] as + missing values. If both [x] and [y] are [nan] [nan] is returned. + Moreover [max_num (-0.) (+0.) = +0.] + + @since 4.08.0 *) + +val min_max_num : float -> float -> float * float +(** [min_max_num x y] is [(min_num x y, max_num x y)], just more + efficient. Note that in particular [min_max_num x nan = (x, x)] + and [min_max_num nan y = (y, y)]. + + @since 4.08.0 *) + + val hash: t -> int (** The hash function for floating-point numbers. *) module Array : sig + + type t = floatarray + (** The type of float arrays with packed representation. @since 4.08.0 *) + + val length : t -> int + (** Return the length (number of elements) of the given floatarray. *) + + val get : t -> int -> float + (** [get a n] returns the element number [n] of floatarray [a]. + + Raise [Invalid_argument] if [n] is outside the range 0 to + [(length a - 1)]. *) + + val set : t -> int -> float -> unit + (** [set a n x] modifies floatarray [a] in place, replacing element + number [n] with [x]. + + Raise [Invalid_argument] if [n] is outside the range 0 to + [(length a - 1)]. *) + + val make : int -> float -> t + (** [make n x] returns a fresh floatarray of length [n], initialized with [x]. + + Raise [Invalid_argument] if [n < 0] or [n > Sys.max_floatarray_length]. *) + + val create : int -> t + (** [create n] returns a fresh floatarray of length [n], + with uninitialized data. + + Raise [Invalid_argument] if [n < 0] or [n > Sys.max_floatarray_length]. *) + + val init : int -> (int -> float) -> t + (** [init n f] returns a fresh floatarray of length [n], + with element number [i] initialized to the result of [f i]. + In other terms, [init n f] tabulates the results of [f] + applied to the integers [0] to [n-1]. + + Raise [Invalid_argument] if [n < 0] or [n > Sys.max_floatarray_length]. *) + + val append : t -> t -> t + (** [append v1 v2] returns a fresh floatarray containing the + concatenation of the floatarrays [v1] and [v2]. + + Raise [Invalid_argument] if + [length v1 + length v2 > Sys.max_floatarray_length]. *) + + val concat : t list -> t + (** Same as {!append}, but concatenates a list of floatarrays. *) + + val sub : t -> int -> int -> t + (** [sub a start len] returns a fresh floatarray of length [len], + containing the elements number [start] to [start + len - 1] + of floatarray [a]. + + Raise [Invalid_argument] if [start] and [len] do not + designate a valid subarray of [a]; that is, if + [start < 0], or [len < 0], or [start + len > length a]. *) + + val copy : t -> t + (** [copy a] returns a copy of [a], that is, a fresh floatarray + containing the same elements as [a]. *) + + val fill : t -> int -> int -> float -> unit + (** [fill a ofs len x] modifies the floatarray [a] in place, + storing [x] in elements number [ofs] to [ofs + len - 1]. + + Raise [Invalid_argument] if [ofs] and [len] do not + designate a valid subarray of [a]. *) + + val blit : t -> int -> t -> int -> int -> unit + (** [blit v1 o1 v2 o2 len] copies [len] elements + from floatarray [v1], starting at element number [o1], to floatarray [v2], + starting at element number [o2]. It works correctly even if + [v1] and [v2] are the same floatarray, and the source and + destination chunks overlap. + + Raise [Invalid_argument] if [o1] and [len] do not + designate a valid subarray of [v1], or if [o2] and [len] do not + designate a valid subarray of [v2]. *) + + val to_list : t -> float list + (** [to_list a] returns the list of all the elements of [a]. *) + + val of_list : float list -> t + (** [of_list l] returns a fresh floatarray containing the elements + of [l]. + + Raise [Invalid_argument] if the length of [l] is greater than + [Sys.max_floatarray_length].*) + + (** {2 Iterators} *) + + val iter : (float -> unit) -> t -> unit + (** [iter f a] applies function [f] in turn to all + the elements of [a]. It is equivalent to + [f a.(0); f a.(1); ...; f a.(length a - 1); ()]. *) + + val iteri : (int -> float -> unit) -> t -> unit + (** Same as {!iter}, but the + function is applied with the index of the element as first argument, + and the element itself as second argument. *) + + val map : (float -> float) -> t -> t + (** [map f a] applies function [f] to all the elements of [a], + and builds a floatarray with the results returned by [f]. *) + + val mapi : (int -> float -> float) -> t -> t + (** Same as {!map}, but the + function is applied to the index of the element as first argument, + and the element itself as second argument. *) + + val fold_left : ('a -> float -> 'a) -> 'a -> t -> 'a + (** [fold_left f x a] computes + [f (... (f (f x a.(0)) a.(1)) ...) a.(n-1)], + where [n] is the length of the floatarray [a]. *) + + val fold_right : (float -> 'a -> 'a) -> t -> 'a -> 'a + (** [fold_right f a x] computes + [f a.(0) (f a.(1) ( ... (f a.(n-1) x) ...))], + where [n] is the length of the floatarray [a]. *) + + (** {2 Iterators on two arrays} *) + + val iter2 : (float -> float -> unit) -> t -> t -> unit + (** [Array.iter2 f a b] applies function [f] to all the elements of [a] + and [b]. + Raise [Invalid_argument] if the floatarrays are not the same size. *) + + val map2 : (float -> float -> float) -> t -> t -> t + (** [map2 f a b] applies function [f] to all the elements of [a] + and [b], and builds a floatarray with the results returned by [f]: + [[| f a.(0) b.(0); ...; f a.(length a - 1) b.(length b - 1)|]]. + Raise [Invalid_argument] if the floatarrays are not the same size. *) + + (** {2 Array scanning} *) + + val for_all : (float -> bool) -> t -> bool + (** [for_all p [|a1; ...; an|]] checks if all elements of the floatarray + satisfy the predicate [p]. That is, it returns + [(p a1) && (p a2) && ... && (p an)]. *) + + val exists : (float -> bool) -> t -> bool + (** [exists p [|a1; ...; an|]] checks if at least one element of + the floatarray satisfies the predicate [p]. That is, it returns + [(p a1) || (p a2) || ... || (p an)]. *) + + val mem : float -> t -> bool + (** [mem a l] is true if and only if there is an element of [l] that is + structurally equal to [a], i.e. there is an [x] in [l] such + that [compare a x = 0]. *) + + val mem_ieee : float -> t -> bool + (** Same as {!mem}, but uses IEEE equality instead of structural equality. *) + + (** {2 Sorting} *) + + val sort : (float -> float -> int) -> t -> unit + (** Sort a floatarray in increasing order according to a comparison + function. The comparison function must return 0 if its arguments + compare as equal, a positive integer if the first is greater, + and a negative integer if the first is smaller (see below for a + complete specification). For example, {!Pervasives.compare} is + a suitable comparison function. After calling [sort], the + array is sorted in place in increasing order. + [sort] is guaranteed to run in constant heap space + and (at most) logarithmic stack space. + + The current implementation uses Heap Sort. It runs in constant + stack space. + + Specification of the comparison function: + Let [a] be the floatarray and [cmp] the comparison function. The following + must be true for all [x], [y], [z] in [a] : +- [cmp x y] > 0 if and only if [cmp y x] < 0 +- if [cmp x y] >= 0 and [cmp y z] >= 0 then [cmp x z] >= 0 + + When [sort] returns, [a] contains the same elements as before, + reordered in such a way that for all i and j valid indices of [a] : +- [cmp a.(i) a.(j)] >= 0 if and only if i >= j + *) + + val stable_sort : (float -> float -> int) -> t -> unit + (** Same as {!sort}, but the sorting algorithm is stable (i.e. + elements that compare equal are kept in their original order) and + not guaranteed to run in constant heap space. + + The current implementation uses Merge Sort. It uses a temporary + floatarray of length [n/2], where [n] is the length of the floatarray. + It is usually faster than the current implementation of {!sort}. *) + + val fast_sort : (float -> float -> int) -> t -> unit + (** Same as {!sort} or {!stable_sort}, whichever is faster + on typical input. *) + + (** {2 Iterators} *) + + val to_seq : t -> float Seq.t + (** Iterate on the floatarray, in increasing order. Modifications of the + floatarray during iteration will be reflected in the iterator. *) + + val to_seqi : t -> (int * float) Seq.t + (** Iterate on the floatarray, in increasing order, yielding indices along + elements. Modifications of the floatarray during iteration will be + reflected in the iterator. *) + + val of_seq : float Seq.t -> t + (** Create an array from the generator. *) + + + val map_to_array : (float -> 'a) -> t -> 'a array + (** [map_to_array f a] applies function [f] to all the elements of [a], + and builds an array with the results returned by [f]: + [[| f a.(0); f a.(1); ...; f a.(length a - 1) |]]. *) + + val map_from_array : ('a -> float) -> 'a array -> t + (** [map_from_array f a] applies function [f] to all the elements of [a], + and builds a floatarray with the results returned by [f]. *) + + (** {2 Undocumented functions} *) + + (* These functions are for system use only. Do not call directly. *) + external unsafe_get : t -> int -> float = "%floatarray_unsafe_get" + external unsafe_set : t -> int -> float -> unit = "%floatarray_unsafe_set" +end + +module ArrayLabels : sig + type t = floatarray - external create : int -> t = "caml_floatarray_create" - external length : t -> int = "%floatarray_length" - external get : t -> int -> float = "%floatarray_safe_get" - external set : t -> int -> float -> unit = "%floatarray_safe_set" + val length : t -> int + val get : t -> int -> float + val set : t -> int -> float -> unit + val make : int -> float -> t + val create : int -> t + val init : int -> f:(int -> float) -> t + val append : t -> t -> t + val concat : t list -> t + val sub : t -> pos:int -> len:int -> t + val copy : t -> t + val fill : t -> pos:int -> len:int -> float -> unit + val blit : src:t -> src_pos:int -> dst:t -> dst_pos:int -> len:int -> unit + val to_list : t -> float list + val of_list : float list -> t + val iter : f:(float -> unit) -> t -> unit + val iteri : f:(int -> float -> unit) -> t -> unit + val map : f:(float -> float) -> t -> t + val mapi : f:(int -> float -> float) -> t -> t + val fold_left : f:('a -> float -> 'a) -> init:'a -> t -> 'a + val fold_right : f:(float -> 'a -> 'a) -> t -> init:'a -> 'a + val iter2 : f:(float -> float -> unit) -> t -> t -> unit + val map2 : f:(float -> float -> float) -> t -> t -> t + val for_all : f:(float -> bool) -> t -> bool + val exists : f:(float -> bool) -> t -> bool + val mem : float -> set:t -> bool + val mem_ieee : float -> set:t -> bool + val sort : cmp:(float -> float -> int) -> t -> unit + val stable_sort : cmp:(float -> float -> int) -> t -> unit + val fast_sort : cmp:(float -> float -> int) -> t -> unit + val to_seq : t -> float Seq.t + val to_seqi : t -> (int * float) Seq.t + val of_seq : float Seq.t -> t + val map_to_array : f:(float -> 'a) -> t -> 'a array + val map_from_array : f:('a -> float) -> 'a array -> t + + (* These functions are for system use only. Do not call directly. *) external unsafe_get : t -> int -> float = "%floatarray_unsafe_get" external unsafe_set : t -> int -> float -> unit = "%floatarray_unsafe_set" end diff --git a/stdlib/format.ml b/stdlib/format.ml index e02ffae1..ae1f3c64 100644 --- a/stdlib/format.ml +++ b/stdlib/format.ml @@ -20,13 +20,28 @@ The pretty-printing engine internal data structures. *) +let id x = x + (* A devoted type for sizes to avoid confusion between sizes and mere integers. *) -type size +module Size : sig + type t + + val to_int : t -> int + val of_int : int -> t + val zero : t + val unknown : t + val is_known : t -> bool +end = struct + type t = int -external size_of_int : int -> size = "%identity" + let to_int = id + let of_int = id + let zero = 0 + let unknown = -1 + let is_known n = n >= 0 +end -external int_of_size : size -> int = "%identity" (* The pretty-printing boxes definition: @@ -52,7 +67,10 @@ type box_type = CamlinternalFormatBasics.block_type = elements that drive indentation and line splitting. *) type pp_token = | Pp_text of string (* normal text *) - | Pp_break of int * int (* complete break *) + | Pp_break of { (* complete break *) + fits: string * int * string; (* line is not split *) + breaks: string * int * string; (* line is split *) + } | Pp_tbreak of int * int (* go to next tabulation *) | Pp_stab (* set a tabulation *) | Pp_begin of int * box_type (* beginning of a box *) @@ -62,40 +80,23 @@ type pp_token = | Pp_newline (* to force a newline inside a box *) | Pp_if_newline (* to do something only if this very line has been broken *) - | Pp_open_tag of tag (* opening a tag name *) + | Pp_open_tag of stag (* opening a tag name *) | Pp_close_tag (* closing the most recently open tag *) -and tag = string +and stag = .. and tbox = Pp_tbox of int list ref (* Tabulation box *) +type tag = string +type stag += String_tag of tag -(* The pretty-printer queue definition: + +(* The pretty-printer queue: pretty-printing material is not written in the output as soon as emitted; instead, the material is simply recorded in the pretty-printer queue, until the enclosing box has a known computed size and proper splitting decisions can be made. - To define the pretty-printer queue, we first define polymorphic queues, - then pretty-printer queue elements. -*) - -(* The pretty-printer queue: polymorphic queue definition. *) -type 'a queue_elem = - | Nil - | Cons of { - head : 'a; - mutable tail : 'a queue_elem; - } - - -type 'a queue = { - mutable insert : 'a queue_elem; - mutable body : 'a queue_elem; -} - - -(* The pretty-printer queue: queue element definition. The pretty-printer queue contains formatting elements to be printed. Each formatting element is a tuple (size, token, length), where - length is the declared length of the token, @@ -103,24 +104,22 @@ type 'a queue = { (size is set when the size of the box is known, so that size of break hints are definitive). *) type pp_queue_elem = { - mutable elem_size : size; + mutable size : Size.t; token : pp_token; length : int; } (* The pretty-printer queue definition. *) -type pp_queue = pp_queue_elem queue +type pp_queue = pp_queue_elem Queue.t (* The pretty-printer scanning stack. *) -(* The pretty-printer scanning stack: scanning element definition. - Each element is (left_total, queue element) where left_total - is the value of pp_left_total when the element has been enqueued. *) -type pp_scan_elem = Scan_elem of int * pp_queue_elem - -(* The pretty-printer scanning stack definition. *) -type pp_scan_stack = pp_scan_elem list +(* The pretty-printer scanning stack: scanning element definition. *) +type pp_scan_elem = { + left_total : int; (* Value of pp_left_total when the element was enqueued. *) + queue_elem : pp_queue_elem +} (* The pretty-printer formatting stack: the formatting stack contains the description of all the currently active @@ -129,24 +128,20 @@ type pp_scan_stack = pp_scan_elem list (* The pretty-printer formatting stack: formatting stack element definition. Each stack element describes a pretty-printing box. *) -type pp_format_elem = Format_elem of box_type * int - -(* The pretty-printer formatting stack definition. *) -type pp_format_stack = pp_format_elem list - -(* The pretty-printer semantics tag stack definition. *) -type pp_tag_stack = tag list +type pp_format_elem = { box_type : box_type; width : int } (* The formatter definition. Each formatter value is a pretty-printer instance with all its machinery. *) type formatter = { - (* The various stacks. *) - mutable pp_scan_stack : pp_scan_stack; - mutable pp_format_stack : pp_format_stack; - mutable pp_tbox_stack : tbox list; - mutable pp_tag_stack : pp_tag_stack; - mutable pp_mark_stack : pp_tag_stack; + (* The pretty-printer scanning stack. *) + pp_scan_stack : pp_scan_elem Stack.t; + (* The pretty-printer formatting stack. *) + pp_format_stack : pp_format_elem Stack.t; + pp_tbox_stack : tbox Stack.t; + (* The pretty-printer semantics tag stack. *) + pp_tag_stack : stag Stack.t; + pp_mark_stack : stag Stack.t; (* Value of right margin. *) mutable pp_margin : int; (* Minimal space left before margin, when opening a box. *) @@ -185,21 +180,21 @@ type formatter = { (* Are tags marked ? *) mutable pp_mark_tags : bool; (* Find opening and closing markers of tags. *) - mutable pp_mark_open_tag : tag -> string; - mutable pp_mark_close_tag : tag -> string; - mutable pp_print_open_tag : tag -> unit; - mutable pp_print_close_tag : tag -> unit; + mutable pp_mark_open_tag : stag -> string; + mutable pp_mark_close_tag : stag -> string; + mutable pp_print_open_tag : stag -> unit; + mutable pp_print_close_tag : stag -> unit; (* The pretty-printer queue. *) - mutable pp_queue : pp_queue; + pp_queue : pp_queue; } (* The formatter specific tag handling functions. *) -type formatter_tag_functions = { - mark_open_tag : tag -> string; - mark_close_tag : tag -> string; - print_open_tag : tag -> unit; - print_close_tag : tag -> unit; +type formatter_stag_functions = { + mark_open_stag : stag -> string; + mark_close_stag : stag -> string; + print_open_stag : stag -> unit; + print_close_stag : stag -> unit; } @@ -219,46 +214,15 @@ type formatter_out_functions = { *) -(* Queues auxiliaries. *) - -let make_queue () = { insert = Nil; body = Nil; } - -let clear_queue q = q.insert <- Nil; q.body <- Nil - -let add_queue x q = - let c = Cons { head = x; tail = Nil; } in - match q with - | { insert = Cons cell; body = _; } -> - q.insert <- c; cell.tail <- c - (* Invariant: when insert is Nil body should be Nil. *) - | { insert = Nil; body = _; } -> - q.insert <- c; q.body <- c - - -exception Empty_queue - -let peek_queue = function - | { body = Cons { head = x; tail = _; }; _ } -> x - | { body = Nil; insert = _; } -> raise Empty_queue - - -let take_queue = function - | { body = Cons { head = x; tail = tl; }; _ } as q -> - q.body <- tl; - if tl = Nil then q.insert <- Nil; (* Maintain the invariant. *) - x - | { body = Nil; insert = _; } -> raise Empty_queue - - (* Enter a token in the pretty-printer queue. *) -let pp_enqueue state ({ length = len; _} as token) = - state.pp_right_total <- state.pp_right_total + len; - add_queue token state.pp_queue +let pp_enqueue state token = + state.pp_right_total <- state.pp_right_total + token.length; + Queue.add token state.pp_queue let pp_clear_queue state = state.pp_left_total <- 1; state.pp_right_total <- 1; - clear_queue state.pp_queue + Queue.clear state.pp_queue (* Pp_infinity: large value for default tokens size. @@ -289,8 +253,19 @@ and pp_output_newline state = state.pp_out_newline () and pp_output_spaces state n = state.pp_out_spaces n and pp_output_indent state n = state.pp_out_indent n +(* Format a textual token *) +let format_pp_text state size text = + state.pp_space_left <- state.pp_space_left - size; + pp_output_string state text; + state.pp_is_new_line <- false + +(* Format a string by its length, if not empty *) +let format_string state s = + if s <> "" then format_pp_text state (String.length s) s + (* To format a break, indenting a new line. *) -let break_new_line state offset width = +let break_new_line state (before, offset, after) width = + format_string state before; pp_output_newline state; state.pp_is_new_line <- true; let indent = state.pp_margin - width + offset in @@ -298,39 +273,41 @@ let break_new_line state offset width = let real_indent = min state.pp_max_indent indent in state.pp_current_indent <- real_indent; state.pp_space_left <- state.pp_margin - state.pp_current_indent; - pp_output_indent state state.pp_current_indent + pp_output_indent state state.pp_current_indent; + format_string state after (* To force a line break inside a box: no offset is added. *) -let break_line state width = break_new_line state 0 width +let break_line state width = break_new_line state ("", 0, "") width (* To format a break that fits on the current line. *) -let break_same_line state width = +let break_same_line state (before, width, after) = + format_string state before; state.pp_space_left <- state.pp_space_left - width; - pp_output_spaces state width + pp_output_spaces state width; + format_string state after (* To indent no more than pp_max_indent, if one tries to open a box beyond pp_max_indent, then the box is rejected on the left by simulating a break. *) let pp_force_break_line state = - match state.pp_format_stack with - | Format_elem (bl_ty, width) :: _ -> + match Stack.top_opt state.pp_format_stack with + | None -> pp_output_newline state + | Some { box_type; width } -> if width > state.pp_space_left then - (match bl_ty with - | Pp_fits -> () | Pp_hbox -> () - | Pp_vbox | Pp_hvbox | Pp_hovbox | Pp_box -> - break_line state width) - | [] -> pp_output_newline state + match box_type with + | Pp_fits | Pp_hbox -> () + | Pp_vbox | Pp_hvbox | Pp_hovbox | Pp_box -> break_line state width (* To skip a token, if the previous line has been broken. *) let pp_skip_token state = - (* When calling pp_skip_token the queue cannot be empty. *) - match take_queue state.pp_queue with - | { elem_size = size; length = len; token = _; } -> - state.pp_left_total <- state.pp_left_total - len; - state.pp_space_left <- state.pp_space_left + int_of_size size + match Queue.take_opt state.pp_queue with + | None -> () (* print_if_newline must have been the last printing command *) + | Some { size; length; _ } -> + state.pp_left_total <- state.pp_left_total - length; + state.pp_space_left <- state.pp_space_left + Size.to_int size (* @@ -343,178 +320,148 @@ let pp_skip_token state = let format_pp_token state size = function | Pp_text s -> - state.pp_space_left <- state.pp_space_left - size; - pp_output_string state s; - state.pp_is_new_line <- false + format_pp_text state size s | Pp_begin (off, ty) -> let insertion_point = state.pp_margin - state.pp_space_left in if insertion_point > state.pp_max_indent then (* can not open a box right there. *) begin pp_force_break_line state end; - let offset = state.pp_space_left - off in - let bl_type = - begin match ty with + let width = state.pp_space_left - off in + let box_type = + match ty with | Pp_vbox -> Pp_vbox | Pp_hbox | Pp_hvbox | Pp_hovbox | Pp_box | Pp_fits -> - if size > state.pp_space_left then ty else Pp_fits - end in - state.pp_format_stack <- - Format_elem (bl_type, offset) :: state.pp_format_stack + if size > state.pp_space_left then ty else Pp_fits in + Stack.push { box_type; width } state.pp_format_stack | Pp_end -> - begin match state.pp_format_stack with - | _ :: ls -> state.pp_format_stack <- ls - | [] -> () (* No more box to close. *) - end + Stack.pop_opt state.pp_format_stack |> ignore | Pp_tbegin (Pp_tbox _ as tbox) -> - state.pp_tbox_stack <- tbox :: state.pp_tbox_stack + Stack.push tbox state.pp_tbox_stack | Pp_tend -> - begin match state.pp_tbox_stack with - | _ :: ls -> state.pp_tbox_stack <- ls - | [] -> () (* No more tabulation box to close. *) - end + Stack.pop_opt state.pp_tbox_stack |> ignore | Pp_stab -> - begin match state.pp_tbox_stack with - | Pp_tbox tabs :: _ -> + begin match Stack.top_opt state.pp_tbox_stack with + | None -> () (* No open tabulation box. *) + | Some (Pp_tbox tabs) -> let rec add_tab n = function | [] -> [n] | x :: l as ls -> if n < x then n :: ls else x :: add_tab n l in tabs := add_tab (state.pp_margin - state.pp_space_left) !tabs - | [] -> () (* No open tabulation box. *) end | Pp_tbreak (n, off) -> let insertion_point = state.pp_margin - state.pp_space_left in - begin match state.pp_tbox_stack with - | Pp_tbox tabs :: _ -> - let rec find n = function - | x :: l -> if x >= n then x else find n l - | [] -> raise Not_found in + begin match Stack.top_opt state.pp_tbox_stack with + | None -> () (* No open tabulation box. *) + | Some (Pp_tbox tabs) -> let tab = match !tabs with - | x :: _ -> - begin - try find insertion_point !tabs with - | Not_found -> x - end - | _ -> insertion_point in + | [] -> insertion_point + | first :: _ -> + let rec find = function + | head :: tail -> + if head >= insertion_point then head else find tail + | [] -> first in + find !tabs in let offset = tab - insertion_point in if offset >= 0 - then break_same_line state (offset + n) - else break_new_line state (tab + off) state.pp_margin - | [] -> () (* No open tabulation box. *) + then break_same_line state ("", offset + n, "") + else break_new_line state ("", tab + off, "") state.pp_margin end | Pp_newline -> - begin match state.pp_format_stack with - | Format_elem (_, width) :: _ -> break_line state width - | [] -> pp_output_newline state (* No open box. *) + begin match Stack.top_opt state.pp_format_stack with + | None -> pp_output_newline state (* No open box. *) + | Some { width; _} -> break_line state width end | Pp_if_newline -> if state.pp_current_indent != state.pp_margin - state.pp_space_left then pp_skip_token state - | Pp_break (n, off) -> - begin match state.pp_format_stack with - | Format_elem (ty, width) :: _ -> - begin match ty with + | Pp_break { fits; breaks } -> + let before, off, _ = breaks in + begin match Stack.top_opt state.pp_format_stack with + | None -> () (* No open box. *) + | Some { box_type; width } -> + begin match box_type with | Pp_hovbox -> - if size > state.pp_space_left - then break_new_line state off width - else break_same_line state n + if size + String.length before > state.pp_space_left + then break_new_line state breaks width + else break_same_line state fits | Pp_box -> (* Have the line just been broken here ? *) - if state.pp_is_new_line then break_same_line state n else - if size > state.pp_space_left - then break_new_line state off width else + if state.pp_is_new_line then break_same_line state fits else + if size + String.length before > state.pp_space_left + then break_new_line state breaks width else (* break the line here leads to new indentation ? *) if state.pp_current_indent > state.pp_margin - width + off - then break_new_line state off width - else break_same_line state n - | Pp_hvbox -> break_new_line state off width - | Pp_fits -> break_same_line state n - | Pp_vbox -> break_new_line state off width - | Pp_hbox -> break_same_line state n + then break_new_line state breaks width + else break_same_line state fits + | Pp_hvbox -> break_new_line state breaks width + | Pp_fits -> break_same_line state fits + | Pp_vbox -> break_new_line state breaks width + | Pp_hbox -> break_same_line state fits end - | [] -> () (* No open box. *) end | Pp_open_tag tag_name -> let marker = state.pp_mark_open_tag tag_name in pp_output_string state marker; - state.pp_mark_stack <- tag_name :: state.pp_mark_stack + Stack.push tag_name state.pp_mark_stack | Pp_close_tag -> - begin match state.pp_mark_stack with - | tag_name :: tags -> + begin match Stack.pop_opt state.pp_mark_stack with + | None -> () (* No more tag to close. *) + | Some tag_name -> let marker = state.pp_mark_close_tag tag_name in - pp_output_string state marker; - state.pp_mark_stack <- tags - | [] -> () (* No more tag to close. *) + pp_output_string state marker end (* Print if token size is known else printing is delayed. - Size is known when not negative. Printing is delayed when the text waiting in the queue requires - more room to format than exists on the current line. - - Note: [advance_loop] must be tail recursive to prevent stack overflows. *) -let rec advance_loop state = - match peek_queue state.pp_queue with - | {elem_size = size; token = tok; length = len} -> - let size = int_of_size size in - if not - (size < 0 && - (state.pp_right_total - state.pp_left_total < state.pp_space_left)) - then begin - ignore (take_queue state.pp_queue); - format_pp_token state (if size < 0 then pp_infinity else size) tok; - state.pp_left_total <- len + state.pp_left_total; - advance_loop state + more room to format than exists on the current line. *) +let rec advance_left state = + match Queue.peek_opt state.pp_queue with + | None -> () (* No tokens to print *) + | Some { size; token; length } -> + let pending_count = state.pp_right_total - state.pp_left_total in + if Size.is_known size || pending_count >= state.pp_space_left then begin + Queue.take state.pp_queue |> ignore; (* Not empty: we peek into it *) + let size = if Size.is_known size then Size.to_int size else pp_infinity in + format_pp_token state size token; + state.pp_left_total <- length + state.pp_left_total; + (advance_left [@tailcall]) state end -let advance_left state = - try advance_loop state with - | Empty_queue -> () - - (* To enqueue a token : try to advance. *) let enqueue_advance state tok = pp_enqueue state tok; advance_left state -(* Building pretty-printer queue elements. *) -let make_queue_elem size tok len = - { elem_size = size; token = tok; length = len; } - (* To enqueue strings. *) let enqueue_string_as state size s = - let len = int_of_size size in - enqueue_advance state (make_queue_elem size (Pp_text s) len) + enqueue_advance state { size; token = Pp_text s; length = Size.to_int size } let enqueue_string state s = - let len = String.length s in - enqueue_string_as state (size_of_int len) s + enqueue_string_as state (Size.of_int (String.length s)) s (* Routines for scan stack determine size of boxes. *) (* The scan_stack is never empty. *) -let scan_stack_bottom = - let q_elem = make_queue_elem (size_of_int (-1)) (Pp_text "") 0 in - [Scan_elem (-1, q_elem)] - - -(* Clearing the pretty-printer scanning stack. *) -let clear_scan_stack state = state.pp_scan_stack <- scan_stack_bottom +let initialize_scan_stack stack = + Stack.clear stack; + let queue_elem = { size = Size.unknown; token = Pp_text ""; length = 0 } in + Stack.push { left_total = -1; queue_elem } stack (* Setting the size of boxes on scan stack: if ty = true then size of break is set else size of box is set; @@ -526,41 +473,37 @@ let clear_scan_stack state = state.pp_scan_stack <- scan_stack_bottom Pattern matching on token in scan stack is also exhaustive, since scan_push is used on breaks and opening of boxes. *) let set_size state ty = - match state.pp_scan_stack with - | Scan_elem - (left_tot, - ({ elem_size = size; token = tok; length = _; } as queue_elem)) :: t -> - let size = int_of_size size in + match Stack.top_opt state.pp_scan_stack with + | None -> () (* scan_stack is never empty. *) + | Some { left_total; queue_elem } -> + let size = Size.to_int queue_elem.size in (* test if scan stack contains any data that is not obsolete. *) - if left_tot < state.pp_left_total then clear_scan_stack state else - begin match tok with - | Pp_break (_, _) | Pp_tbreak (_, _) -> - if ty then - begin - queue_elem.elem_size <- size_of_int (state.pp_right_total + size); - state.pp_scan_stack <- t + if left_total < state.pp_left_total then + initialize_scan_stack state.pp_scan_stack + else + match queue_elem.token with + | Pp_break _ | Pp_tbreak (_, _) -> + if ty then begin + queue_elem.size <- Size.of_int (state.pp_right_total + size); + Stack.pop_opt state.pp_scan_stack |> ignore end | Pp_begin (_, _) -> - if not ty then - begin - queue_elem.elem_size <- size_of_int (state.pp_right_total + size); - state.pp_scan_stack <- t + if not ty then begin + queue_elem.size <- Size.of_int (state.pp_right_total + size); + Stack.pop_opt state.pp_scan_stack |> ignore end | Pp_text _ | Pp_stab | Pp_tbegin _ | Pp_tend | Pp_end - | Pp_newline | Pp_if_newline - | Pp_open_tag _ | Pp_close_tag -> + | Pp_newline | Pp_if_newline | Pp_open_tag _ | Pp_close_tag -> () (* scan_push is only used for breaks and boxes. *) - end - | [] -> () (* scan_stack is never empty. *) (* Push a token on pretty-printer scanning stack. If b is true set_size is called. *) -let scan_push state b tok = - pp_enqueue state tok; +let scan_push state b token = + pp_enqueue state token; if b then set_size state true; - state.pp_scan_stack <- - Scan_elem (state.pp_right_total, tok) :: state.pp_scan_stack + let elem = { left_total = state.pp_right_total; queue_elem = token } in + Stack.push elem state.pp_scan_stack (* To open a new box : @@ -569,11 +512,8 @@ let scan_push state b tok = let pp_open_box_gen state indent br_ty = state.pp_curr_depth <- state.pp_curr_depth + 1; if state.pp_curr_depth < state.pp_max_boxes then - let elem = - make_queue_elem - (size_of_int (- state.pp_right_total)) - (Pp_begin (indent, br_ty)) - 0 in + let size = Size.of_int (- state.pp_right_total) in + let elem = { size; token = Pp_begin (indent, br_ty); length = 0 } in scan_push state false elem else if state.pp_curr_depth = state.pp_max_boxes then enqueue_string state state.pp_ellipsis @@ -588,8 +528,7 @@ let pp_close_box state () = begin if state.pp_curr_depth < state.pp_max_boxes then begin - pp_enqueue state - { elem_size = size_of_int 0; token = Pp_end; length = 0; }; + pp_enqueue state { size = Size.zero; token = Pp_end; length = 0 }; set_size state true; set_size state false end; state.pp_curr_depth <- state.pp_curr_depth - 1; @@ -597,37 +536,29 @@ let pp_close_box state () = (* Open a tag, pushing it on the tag stack. *) -let pp_open_tag state tag_name = +let pp_open_stag state tag_name = if state.pp_print_tags then begin - state.pp_tag_stack <- tag_name :: state.pp_tag_stack; + Stack.push tag_name state.pp_tag_stack; state.pp_print_open_tag tag_name end; if state.pp_mark_tags then - pp_enqueue state { - elem_size = size_of_int 0; - token = Pp_open_tag tag_name; - length = 0; - } + let token = Pp_open_tag tag_name in + pp_enqueue state { size = Size.zero; token; length = 0 } (* Close a tag, popping it from the tag stack. *) -let pp_close_tag state () = +let pp_close_stag state () = if state.pp_mark_tags then - pp_enqueue state { - elem_size = size_of_int 0; - token = Pp_close_tag; - length = 0; - }; + pp_enqueue state { size = Size.zero; token = Pp_close_tag; length = 0 }; if state.pp_print_tags then - begin - match state.pp_tag_stack with - | tag_name :: tags -> - state.pp_print_close_tag tag_name; - state.pp_tag_stack <- tags - | _ -> () (* No more tag to close. *) - end + match Stack.pop_opt state.pp_tag_stack with + | None -> () (* No more tag to close. *) + | Some tag_name -> + state.pp_print_close_tag tag_name +let pp_open_tag state s = pp_open_stag state (String_tag s) +let pp_close_tag state () = pp_close_stag state () let pp_set_print_tags state b = state.pp_print_tags <- b let pp_set_mark_tags state b = state.pp_mark_tags <- b @@ -638,19 +569,19 @@ let pp_set_tags state b = (* Handling tag handling functions: get/set functions. *) -let pp_get_formatter_tag_functions state () = { - mark_open_tag = state.pp_mark_open_tag; - mark_close_tag = state.pp_mark_close_tag; - print_open_tag = state.pp_print_open_tag; - print_close_tag = state.pp_print_close_tag; +let pp_get_formatter_stag_functions state () = { + mark_open_stag = state.pp_mark_open_tag; + mark_close_stag = state.pp_mark_close_tag; + print_open_stag = state.pp_print_open_tag; + print_close_stag = state.pp_print_close_tag; } -let pp_set_formatter_tag_functions state { - mark_open_tag = mot; - mark_close_tag = mct; - print_open_tag = pot; - print_close_tag = pct; +let pp_set_formatter_stag_functions state { + mark_open_stag = mot; + mark_close_stag = mct; + print_open_stag = pot; + print_close_stag = pct; } = state.pp_mark_open_tag <- mot; state.pp_mark_close_tag <- mct; @@ -661,20 +592,18 @@ let pp_set_formatter_tag_functions state { (* Initialize pretty-printer. *) let pp_rinit state = pp_clear_queue state; - clear_scan_stack state; - state.pp_format_stack <- []; - state.pp_tbox_stack <- []; - state.pp_tag_stack <- []; - state.pp_mark_stack <- []; + initialize_scan_stack state.pp_scan_stack; + Stack.clear state.pp_format_stack; + Stack.clear state.pp_tbox_stack; + Stack.clear state.pp_tag_stack; + Stack.clear state.pp_mark_stack; state.pp_current_indent <- 0; state.pp_curr_depth <- 0; state.pp_space_left <- state.pp_margin; pp_open_sys_box state let clear_tag_stack state = - List.iter - (fun _ -> pp_close_tag state ()) - state.pp_tag_stack + Stack.iter (fun _ -> pp_close_tag state ()) state.pp_tag_stack (* Flushing pretty-printer queue. *) @@ -701,7 +630,7 @@ let pp_print_as_size state size s = let pp_print_as state isize s = - pp_print_as_size state (size_of_int isize) s + pp_print_as_size state (Size.of_int isize) s let pp_print_string state s = @@ -709,7 +638,7 @@ let pp_print_string state s = (* To format an integer. *) -let pp_print_int state i = pp_print_string state (string_of_int i) +let pp_print_int state i = pp_print_string state (Int.to_string i) (* To format a float. *) let pp_print_float state f = pp_print_string state (string_of_float f) @@ -748,27 +677,34 @@ and pp_print_flush state () = (* To get a newline when one does not want to close the current box. *) let pp_force_newline state () = if state.pp_curr_depth < state.pp_max_boxes then - enqueue_advance state (make_queue_elem (size_of_int 0) Pp_newline 0) + enqueue_advance state { size = Size.zero; token = Pp_newline; length = 0 } (* To format something, only in case the line has just been broken. *) let pp_print_if_newline state () = if state.pp_curr_depth < state.pp_max_boxes then - enqueue_advance state (make_queue_elem (size_of_int 0) Pp_if_newline 0) + enqueue_advance state + { size = Size.zero; token = Pp_if_newline; length = 0 } + +(* Generalized break hint that allows to print strings before/after + same-line offset (width) or new-line offset *) +let pp_print_custom_break state ~fits ~breaks = + let before, width, after = fits in + if state.pp_curr_depth < state.pp_max_boxes then + let size = Size.of_int (- state.pp_right_total) in + let token = Pp_break { fits; breaks } in + let length = String.length before + width + String.length after in + let elem = { size; token; length } in + scan_push state true elem (* Printing break hints: A break hint indicates where a box may be broken. If line is broken then offset is added to the indentation of the current box else (the value of) width blanks are printed. *) let pp_print_break state width offset = - if state.pp_curr_depth < state.pp_max_boxes then - let elem = - make_queue_elem - (size_of_int (- state.pp_right_total)) - (Pp_break (width, offset)) - width in - scan_push state true elem + pp_print_custom_break state + ~fits:("", width, "") ~breaks:("", offset, "") (* Print a space : @@ -784,8 +720,8 @@ and pp_print_cut state () = pp_print_break state 0 0 let pp_open_tbox state () = state.pp_curr_depth <- state.pp_curr_depth + 1; if state.pp_curr_depth < state.pp_max_boxes then - let elem = - make_queue_elem (size_of_int 0) (Pp_tbegin (Pp_tbox (ref []))) 0 in + let size = Size.zero in + let elem = { size; token = Pp_tbegin (Pp_tbox (ref [])); length = 0 } in enqueue_advance state elem @@ -794,7 +730,7 @@ let pp_close_tbox state () = if state.pp_curr_depth > 1 then begin if state.pp_curr_depth < state.pp_max_boxes then - let elem = make_queue_elem (size_of_int 0) Pp_tend 0 in + let elem = { size = Size.zero; token = Pp_tend; length = 0 } in enqueue_advance state elem; state.pp_curr_depth <- state.pp_curr_depth - 1 end @@ -803,11 +739,8 @@ let pp_close_tbox state () = (* Print a tabulation break. *) let pp_print_tbreak state width offset = if state.pp_curr_depth < state.pp_max_boxes then - let elem = - make_queue_elem - (size_of_int (- state.pp_right_total)) - (Pp_tbreak (width, offset)) - width in + let size = Size.of_int (- state.pp_right_total) in + let elem = { size; token = Pp_tbreak (width, offset); length = width } in scan_push state true elem @@ -815,8 +748,7 @@ let pp_print_tab state () = pp_print_tbreak state 0 0 let pp_set_tab state () = if state.pp_curr_depth < state.pp_max_boxes then - let elem = - make_queue_elem (size_of_int 0) Pp_stab 0 in + let elem = { size = Size.zero; token = Pp_stab; length = 0 } in enqueue_advance state elem @@ -857,7 +789,8 @@ let pp_set_min_space_left state n = pp_max_indent = pp_margin - pp_min_space_left, and pp_space_left = pp_margin. *) let pp_set_max_indent state n = - pp_set_min_space_left state (state.pp_margin - n) + if n > 1 then + pp_set_min_space_left state (state.pp_margin - n) let pp_get_max_indent state () = state.pp_max_indent @@ -879,8 +812,32 @@ let pp_set_margin state n = pp_set_max_indent state new_max_indent +(** Geometry functions and types *) +type geometry = { max_indent:int; margin: int} + +let check_geometry geometry = + geometry.max_indent > 1 + && geometry.margin > geometry.max_indent + let pp_get_margin state () = state.pp_margin +let pp_set_geometry state ~max_indent ~margin = + if max_indent < 2 then + raise (Invalid_argument "Format.pp_set_geometry: max_indent < 2") + else if margin <= max_indent then + raise (Invalid_argument "Format.pp_set_geometry: margin <= max_indent") + else + pp_set_margin state margin; pp_set_max_indent state max_indent + +let pp_safe_set_geometry state ~max_indent ~margin = + if check_geometry {max_indent;margin} then + pp_set_geometry state ~max_indent ~margin + else + () + +let pp_get_geometry state () = + { margin = pp_get_margin state (); max_indent = pp_get_max_indent state () } + (* Setting a formatter basic output functions. *) let pp_set_formatter_out_functions state { out_string = f; @@ -944,8 +901,12 @@ let pp_set_formatter_out_channel state oc = *) -let default_pp_mark_open_tag s = "<" ^ s ^ ">" -let default_pp_mark_close_tag s = "" +let default_pp_mark_open_tag = function + | String_tag s -> "<" ^ s ^ ">" + | _ -> "" +let default_pp_mark_close_tag = function + | String_tag s -> "" + | _ -> "" let default_pp_print_open_tag = ignore let default_pp_print_close_tag = ignore @@ -954,20 +915,21 @@ let default_pp_print_close_tag = ignore Other fields get reasonable default values. *) let pp_make_formatter f g h i j = (* The initial state of the formatter contains a dummy box. *) - let pp_queue = make_queue () in + let pp_queue = Queue.create () in let sys_tok = - make_queue_elem (size_of_int (-1)) (Pp_begin (0, Pp_hovbox)) 0 in - add_queue sys_tok pp_queue; - let sys_scan_stack = - Scan_elem (1, sys_tok) :: scan_stack_bottom in + { size = Size.unknown; token = Pp_begin (0, Pp_hovbox); length = 0 } in + Queue.add sys_tok pp_queue; + let scan_stack = Stack.create () in + initialize_scan_stack scan_stack; + Stack.push { left_total = 1; queue_elem = sys_tok } scan_stack; let pp_margin = 78 and pp_min_space_left = 10 in { - pp_scan_stack = sys_scan_stack; - pp_format_stack = []; - pp_tbox_stack = []; - pp_tag_stack = []; - pp_mark_stack = []; + pp_scan_stack = scan_stack; + pp_format_stack = Stack.create (); + pp_tbox_stack = Stack.create (); + pp_tag_stack = Stack.create (); + pp_mark_stack = Stack.create (); pp_margin = pp_margin; pp_min_space_left = pp_min_space_left; pp_max_indent = pp_margin - pp_min_space_left; @@ -1034,9 +996,9 @@ let pp_make_buffer () = Buffer.create pp_buffer_size let stdbuf = pp_make_buffer () (* Predefined formatters standard formatter to print - to [Pervasives.stdout], [Pervasives.stderr], and {!stdbuf}. *) -let std_formatter = formatter_of_out_channel Pervasives.stdout -and err_formatter = formatter_of_out_channel Pervasives.stderr + to [Stdlib.stdout], [Stdlib.stderr], and {!stdbuf}. *) +let std_formatter = formatter_of_out_channel Stdlib.stdout +and err_formatter = formatter_of_out_channel Stdlib.stderr and str_formatter = formatter_of_buffer stdbuf @@ -1117,7 +1079,7 @@ let formatter_of_symbolic_output_buffer sob = (* Basic functions on the 'standard' formatter - (the formatter that prints to [Pervasives.stdout]). + (the formatter that prints to [Stdlib.stdout]). *) @@ -1129,6 +1091,8 @@ and open_box = pp_open_box std_formatter and close_box = pp_close_box std_formatter and open_tag = pp_open_tag std_formatter and close_tag = pp_close_tag std_formatter +and open_stag = pp_open_stag std_formatter +and close_stag = pp_close_stag std_formatter and print_as = pp_print_as std_formatter and print_string = pp_print_string std_formatter and print_int = pp_print_int std_formatter @@ -1156,6 +1120,10 @@ and get_margin = pp_get_margin std_formatter and set_max_indent = pp_set_max_indent std_formatter and get_max_indent = pp_get_max_indent std_formatter +and set_geometry = pp_set_geometry std_formatter +and safe_set_geometry = pp_safe_set_geometry std_formatter +and get_geometry = pp_get_geometry std_formatter + and set_max_boxes = pp_set_max_boxes std_formatter and get_max_boxes = pp_get_max_boxes std_formatter and over_max_boxes = pp_over_max_boxes std_formatter @@ -1176,10 +1144,10 @@ and set_formatter_output_functions = and get_formatter_output_functions = pp_get_formatter_output_functions std_formatter -and set_formatter_tag_functions = - pp_set_formatter_tag_functions std_formatter -and get_formatter_tag_functions = - pp_get_formatter_tag_functions std_formatter +and set_formatter_stag_functions = + pp_set_formatter_stag_functions std_formatter +and get_formatter_stag_functions = + pp_get_formatter_stag_functions std_formatter and set_print_tags = pp_set_print_tags std_formatter and get_print_tags = @@ -1225,6 +1193,14 @@ let pp_print_text ppf s = done; if !left <> len then flush () +let pp_print_option ?(none = fun _ () -> ()) pp_v ppf = function +| None -> none ppf () +| Some v -> pp_v ppf v + +let pp_print_result ~ok ~error ppf = function +| Ok v -> ok ppf v +| Error e -> error ppf e + (**************************************************************) let compute_tag output tag_acc = @@ -1267,17 +1243,17 @@ let rec output_acc ppf acc = match acc with | Acc_string_literal (Acc_formatting_lit (p, Magic_size (_, size)), s) | Acc_data_string (Acc_formatting_lit (p, Magic_size (_, size)), s) -> output_acc ppf p; - pp_print_as_size ppf (size_of_int size) s; + pp_print_as_size ppf (Size.of_int size) s; | Acc_char_literal (Acc_formatting_lit (p, Magic_size (_, size)), c) | Acc_data_char (Acc_formatting_lit (p, Magic_size (_, size)), c) -> output_acc ppf p; - pp_print_as_size ppf (size_of_int size) (String.make 1 c); + pp_print_as_size ppf (Size.of_int size) (String.make 1 c); | Acc_formatting_lit (p, f) -> output_acc ppf p; output_formatting_lit ppf f; | Acc_formatting_gen (p, Acc_open_tag acc') -> output_acc ppf p; - pp_open_tag ppf (compute_tag output_acc acc') + pp_open_stag ppf (String_tag (compute_tag output_acc acc')) | Acc_formatting_gen (p, Acc_open_box acc') -> output_acc ppf p; let (indent, bty) = open_box_of_string (compute_tag output_acc acc') in @@ -1299,20 +1275,20 @@ let rec strput_acc ppf acc = match acc with | Acc_string_literal (Acc_formatting_lit (p, Magic_size (_, size)), s) | Acc_data_string (Acc_formatting_lit (p, Magic_size (_, size)), s) -> strput_acc ppf p; - pp_print_as_size ppf (size_of_int size) s; + pp_print_as_size ppf (Size.of_int size) s; | Acc_char_literal (Acc_formatting_lit (p, Magic_size (_, size)), c) | Acc_data_char (Acc_formatting_lit (p, Magic_size (_, size)), c) -> strput_acc ppf p; - pp_print_as_size ppf (size_of_int size) (String.make 1 c); + pp_print_as_size ppf (Size.of_int size) (String.make 1 c); | Acc_delay (Acc_formatting_lit (p, Magic_size (_, size)), f) -> strput_acc ppf p; - pp_print_as_size ppf (size_of_int size) (f ()); + pp_print_as_size ppf (Size.of_int size) (f ()); | Acc_formatting_lit (p, f) -> strput_acc ppf p; output_formatting_lit ppf f; | Acc_formatting_gen (p, Acc_open_tag acc') -> strput_acc ppf p; - pp_open_tag ppf (compute_tag strput_acc acc') + pp_open_stag ppf (String_tag (compute_tag strput_acc acc')) | Acc_formatting_gen (p, Acc_open_box acc') -> strput_acc ppf p; let (indent, bty) = open_box_of_string (compute_tag strput_acc acc') in @@ -1334,42 +1310,55 @@ let rec strput_acc ppf acc = match acc with let kfprintf k ppf (Format (fmt, _)) = make_printf - (fun ppf acc -> output_acc ppf acc; k ppf) - ppf End_of_acc fmt + (fun acc -> output_acc ppf acc; k ppf) + End_of_acc fmt and ikfprintf k ppf (Format (fmt, _)) = make_iprintf k ppf fmt +let ifprintf _ppf (Format (fmt, _)) = + make_iprintf ignore () fmt + let fprintf ppf = kfprintf ignore ppf -let ifprintf ppf = ikfprintf ignore ppf let printf fmt = fprintf std_formatter fmt let eprintf fmt = fprintf err_formatter fmt +let kdprintf k (Format (fmt, _)) = + make_printf + (fun acc -> k (fun ppf -> output_acc ppf acc)) + End_of_acc fmt + +let dprintf fmt = kdprintf (fun i -> i) fmt + let ksprintf k (Format (fmt, _)) = let b = pp_make_buffer () in let ppf = formatter_of_buffer b in - let k () acc = + let k acc = strput_acc ppf acc; k (flush_buffer_formatter b ppf) in - make_printf k () End_of_acc fmt + make_printf k End_of_acc fmt -let sprintf fmt = ksprintf (fun s -> s) fmt +let sprintf fmt = ksprintf id fmt let kasprintf k (Format (fmt, _)) = let b = pp_make_buffer () in let ppf = formatter_of_buffer b in - let k ppf acc = + let k acc = output_acc ppf acc; k (flush_buffer_formatter b ppf) in - make_printf k ppf End_of_acc fmt + make_printf k End_of_acc fmt + +let asprintf fmt = kasprintf id fmt -let asprintf fmt = kasprintf (fun s -> s) fmt +(* Flushing standard formatters at end of execution. *) -(* Output everything left in the pretty printer queue at end of execution. *) -let () = at_exit print_flush +let flush_standard_formatters () = + pp_print_flush std_formatter (); + pp_print_flush err_formatter () +let () = at_exit flush_standard_formatters (* @@ -1408,9 +1397,47 @@ let get_all_formatter_output_functions = let ppf = formatter_of_buffer b then use {!fprintf ppf} as usual. *) let bprintf b (Format (fmt, _) : ('a, formatter, unit) format) = - let k ppf acc = output_acc ppf acc; pp_flush_queue ppf false in - make_printf k (formatter_of_buffer b) End_of_acc fmt + let ppf = formatter_of_buffer b in + let k acc = output_acc ppf acc; pp_flush_queue ppf false in + make_printf k End_of_acc fmt (* Deprecated : alias for ksprintf. *) let kprintf = ksprintf + + + +(* Deprecated tag functions *) + +type formatter_tag_functions = { + mark_open_tag : tag -> string; + mark_close_tag : tag -> string; + print_open_tag : tag -> unit; + print_close_tag : tag -> unit; +} + + +let pp_set_formatter_tag_functions state { + mark_open_tag = mot; + mark_close_tag = mct; + print_open_tag = pot; + print_close_tag = pct; + } = + let stringify f e = function String_tag s -> f s | _ -> e in + state.pp_mark_open_tag <- stringify mot ""; + state.pp_mark_close_tag <- stringify mct ""; + state.pp_print_open_tag <- stringify pot (); + state.pp_print_close_tag <- stringify pct () + +let pp_get_formatter_tag_functions fmt () = + let funs = pp_get_formatter_stag_functions fmt () in + let mark_open_tag s = funs.mark_open_stag (String_tag s) in + let mark_close_tag s = funs.mark_close_stag (String_tag s) in + let print_open_tag s = funs.print_open_stag (String_tag s) in + let print_close_tag s = funs.print_close_stag (String_tag s) in + {mark_open_tag; mark_close_tag; print_open_tag; print_close_tag} + +let set_formatter_tag_functions = + pp_set_formatter_tag_functions std_formatter +and get_formatter_tag_functions = + pp_get_formatter_tag_functions std_formatter diff --git a/stdlib/format.mli b/stdlib/format.mli index 404118b6..44ae07cd 100644 --- a/stdlib/format.mli +++ b/stdlib/format.mli @@ -27,8 +27,8 @@ abstract {{!section:formatter}formatters} which provide basic output functions. Some formatters are predefined, notably: - - {!std_formatter} outputs to {{!Pervasives.stdout}stdout} - - {!err_formatter} outputs to {{!Pervasives.stderr}stderr} + - {!std_formatter} outputs to {{!Stdlib.stdout}stdout} + - {!err_formatter} outputs to {{!Stdlib.stderr}stderr} Most functions in the {!Format} module come in two variants: a short version that operates on {!std_formatter} and the @@ -89,7 +89,7 @@ pending text, and resets the standard pretty-printer. Warning: mixing calls to pretty-printing functions of this module with - calls to {!Pervasives} low level output functions is error prone. + calls to {!Stdlib} low level output functions is error prone. The pretty-printing functions output material that is delayed in the pretty-printer queue and stacks in order to compute proper line @@ -98,9 +98,9 @@ may appear before the output of a pretty-printing function that has been called before. For instance, [ - Pervasives.print_string "<"; + Stdlib.print_string "<"; Format.print_string "PRETTY"; - Pervasives.print_string ">"; + Stdlib.print_string ">"; Format.print_string "TEXT"; ] leads to output [<>PRETTYTEXT]. @@ -288,6 +288,48 @@ val print_break : int -> int -> unit the current indentation. *) +val pp_print_custom_break : + formatter -> + fits:(string * int * string) -> + breaks:(string * int * string) -> + unit +(** [pp_print_custom_break ppf ~fits:(s1, n, s2) ~breaks:(s3, m, s4)] emits a + custom break hint: the pretty-printer may split the line at this point. + + If it does not split the line, then the [s1] is emitted, then [n] spaces, + then [s2]. + + If it splits the line, then it emits the [s3] string, then an indent + (according to the box rules), then an offset of [m] spaces, then the [s4] + string. + + While [n] and [m] are handled by [formatter_out_functions.out_indent], the + strings will be handled by [formatter_out_functions.out_string]. This allows + for a custom formatter that handles indentation distinctly, for example, + outputs [
    ] tags or [ ] entities. + + The custom break is useful if you want to change which visible + (non-whitespace) characters are printed in case of break or no break. For + example, when printing a list {[ [a; b; c] ]}, you might want to add a + trailing semicolon when it is printed vertically: + + {[ +[ + a; + b; + c; +] + ]} + + You can do this as follows: + {[ +printf "@[[@;<0 2>@[a;@,b;@,c@]%t]@]@\n" + (pp_print_custom_break ~fits:("", 0, "") ~breaks:(";", 0, "")) + ]} + + @since 4.08.0 +*) + val pp_force_newline : formatter -> unit -> unit val force_newline : unit -> unit (** Force a new line in the current pretty-printing box. @@ -329,7 +371,7 @@ val print_flush : unit -> unit disturb further pretty-printing. Warning: If the output device of the pretty-printer is an output channel, - repeated calls to [print_flush] means repeated calls to {!Pervasives.flush} + repeated calls to [print_flush] means repeated calls to {!Stdlib.flush} to flush the out channel; these explicit flush calls could foil the buffering strategy of output channels and could dramatically impact efficiency. @@ -363,6 +405,8 @@ val set_margin : int -> unit maximum indentation limit is decreased while trying to preserve a minimal ratio [max_indent/margin>=50%] and if possible the current difference [margin - max_indent]. + + See also {!pp_set_geometry}. *) val pp_get_margin : formatter -> unit -> int @@ -376,20 +420,83 @@ val set_max_indent : int -> unit (** [pp_set_max_indent ppf d] sets the maximum indentation limit of lines to [d] (in characters): once this limit is reached, new pretty-printing boxes are rejected to the - left, if they do not fit on the current line. + left, unless the enclosing box fully fits on the current line. + As an illustration, + {[ set_margin 10; set_max_indent 5; printf "@[123456@[7@]89A@]@." ]} + yields + {[ + 123456 + 789A + ]} + because the nested box ["@[7@]"] is opened after the maximum indentation + limit ([7>5]) and its parent box does not fit on the current line. + Either decreasing the length of the parent box to make it fit on a line: + {[ printf "@[123456@[7@]89@]@." ]} + or opening an intermediary box before the maximum indentation limit which + fits on the current line + {[ printf "@[123@[456@[7@]89@]A@]@." ]} + avoids the rejection to the left of the inner boxes and print respectively + ["123456789"] and ["123456789A"] . + Note also that vertical boxes never fit on a line whereas horizontal boxes + always fully fit on the current line. Nothing happens if [d] is smaller than 2. + If [d] is too large, the limit is set to the maximum admissible value (which is greater than [10 ^ 9]). If [d] is greater or equal than the current margin, it is ignored, and the current maximum indentation limit is kept. + + See also {!pp_set_geometry}. *) val pp_get_max_indent : formatter -> unit -> int val get_max_indent : unit -> int (** Return the maximum indentation limit (in characters). *) +(** {1 Geometry } + +Geometric functions can be used to manipulate simultaneously the +coupled variables, margin and maxixum indentation limit. + +*) + +type geometry = { max_indent:int; margin: int} + +val check_geometry: geometry -> bool +(** Check if the formatter geometry is valid: [1 < max_indent < margin] *) + +val pp_set_geometry : formatter -> max_indent:int -> margin:int -> unit +val set_geometry : max_indent:int -> margin:int -> unit +val pp_safe_set_geometry : formatter -> max_indent:int -> margin:int -> unit +val safe_set_geometry : max_indent:int -> margin:int -> unit +(** + [pp_set_geometry ppf ~max_indent ~margin] sets both the margin + and maximum indentation limit for [ppf]. + + When [1 < max_indent < margin], + [pp_set_geometry ppf ~max_indent ~margin] + is equivalent to + [pp_set_margin ppf margin; pp_set_max_indent ppf max_indent]; + and avoids the subtly incorrect + [pp_set_max_indent ppf max_indent; pp_set_margin ppf margin]; + + Outside of this domain, [pp_set_geometry] raises an invalid argument + exception whereas [pp_safe_set_geometry] does nothing. + + @since 4.08.0 +*) + +val pp_get_geometry: formatter -> unit -> geometry +val get_geometry: unit -> geometry +(** Return the current geometry of the formatter + + @since 4.08.0 +*) + + + (** {1 Maximum formatting depth} *) (** The maximum formatting depth is the maximum number of pretty-printing @@ -502,9 +609,8 @@ val get_ellipsis_text : unit -> string (** {1:tags Semantic tags} *) -type tag = string - -(** {i Semantic tags} (or simply {e tags}) are user's defined delimiters +type stag = .. +(** {i Semantic tags} (or simply {e tags}) are user's defined annotations to associate user's specific operations to printed entities. Common usage of semantic tags is text decoration to get specific font or @@ -513,10 +619,14 @@ type tag = string More sophisticated usage of semantic tags could handle dynamic modification of the pretty-printer behavior to properly print the material within some specific tags. + For instance, we can define an RGB tag like so: +{[ +type stag += RGB of {r:int;g:int;b:int} +]} In order to properly delimit printed entities, a semantic tag must be opened before and closed after the entity. Semantic tags must be properly - nested like parentheses. + nested like parentheses using {!pp_open_stag} and {!pp_close_stag}. Tag specific operations occur any time a tag is opened or closed, At each occurrence, two kinds of operations are performed {e tag-marking} and @@ -537,12 +647,12 @@ type tag = string More precisely: when a semantic tag is opened or closed then both and successive 'tag-printing' and 'tag-marking' operations occur: - Tag-printing a semantic tag means calling the formatter specific function - [print_open_tag] (resp. [print_close_tag]) with the name of the tag as + [print_open_stag] (resp. [print_close_stag]) with the name of the tag as argument: that tag-printing function can then print any regular material to the formatter (so that this material is enqueued as usual in the formatter queue for further line splitting computation). - Tag-marking a semantic tag means calling the formatter specific function - [mark_open_tag] (resp. [mark_close_tag]) with the name of the tag as + [mark_open_stag] (resp. [mark_close_stag]) with the name of the tag as argument: that tag-marking function can then return the 'tag-opening marker' (resp. `tag-closing marker') for direct output into the output device of the formatter. @@ -560,35 +670,43 @@ type tag = string information. Once [set_tags] is set to [true], the pretty-printer engine honors tags and decorates the output accordingly. - Default tag-marking functions behave the HTML way: tags are enclosed in "<" - and ">"; hence, opening marker for tag [t] is [""] and closing marker is - [""]. + Default tag-marking functions behave the HTML way: {{!tag}string tags} are + enclosed in "<" and ">" while other tags are ignored; + hence, opening marker for tag string ["t"] is [""] and closing marker + is [""]. Default tag-printing functions just do nothing. Tag-marking and tag-printing functions are user definable and can - be set by calling {!set_formatter_tag_functions}. + be set by calling {!set_formatter_stag_functions}. Semantic tag operations may be set on or off with {!set_tags}. Tag-marking operations may be set on or off with {!set_mark_tags}. Tag-printing operations may be set on or off with {!set_print_tags}. *) -val pp_open_tag : formatter -> string -> unit -val open_tag : tag -> unit -(** [pp_open_tag ppf t] opens the semantic tag named [t]. +type tag = string +type stag += String_tag of tag +(** [String_tag s] is a string tag [s]. String tags can be inserted either + by explicitly using the constructor [String_tag] or by using the dedicated + format syntax ["@{ ... @}"]. +*) + +val pp_open_stag : formatter -> stag -> unit +val open_stag : stag -> unit +(** [pp_open_stag ppf t] opens the semantic tag named [t]. - The [print_open_tag] tag-printing function of the formatter is called with + The [print_open_stag] tag-printing function of the formatter is called with [t] as argument; then the opening tag marker for [t], as given by - [mark_open_tag t], is written into the output device of the formatter. + [mark_open_stag t], is written into the output device of the formatter. *) -val pp_close_tag : formatter -> unit -> unit -val close_tag : unit -> unit -(** [pp_close_tag ppf ()] closes the most recently opened semantic tag [t]. +val pp_close_stag : formatter -> unit -> unit +val close_stag : unit -> unit +(** [pp_close_stag ppf ()] closes the most recently opened semantic tag [t]. - The closing tag marker, as given by [mark_close_tag t], is written into the - output device of the formatter; then the [print_close_tag] tag-printing + The closing tag marker, as given by [mark_close_stag t], is written into the + output device of the formatter; then the [print_close_stag] tag-printing function of the formatter is called with [t] as argument. *) @@ -616,8 +734,8 @@ val get_mark_tags : unit -> bool (** {1 Redirecting the standard formatter output} *) val pp_set_formatter_out_channel : - formatter -> Pervasives.out_channel -> unit -val set_formatter_out_channel : Pervasives.out_channel -> unit + formatter -> Stdlib.out_channel -> unit +val set_formatter_out_channel : Stdlib.out_channel -> unit (** Redirect the standard pretty-printer output to the given channel. (All the output functions of the standard formatter are set to the default output functions printing to the given channel.) @@ -683,9 +801,9 @@ type formatter_out_functions = { By default: - fields [out_string] and [out_flush] are output device specific; - (e.g. {!Pervasives.output_string} and {!Pervasives.flush} for a - {!Pervasives.out_channel} device, or [Buffer.add_substring] and - {!Pervasives.ignore} for a [Buffer.t] output device), + (e.g. {!Stdlib.output_string} and {!Stdlib.flush} for a + {!Stdlib.out_channel} device, or [Buffer.add_substring] and + {!Stdlib.ignore} for a [Buffer.t] output device), - field [out_newline] is equivalent to [out_string "\n" 0 1]; - fields [out_spaces] and [out_indent] are equivalent to [out_string (String.make n ' ') 0 n]. @@ -721,11 +839,11 @@ val get_formatter_out_functions : unit -> formatter_out_functions (** {1:tagsmeaning Redefining semantic tag operations} *) -type formatter_tag_functions = { - mark_open_tag : tag -> string; - mark_close_tag : tag -> string; - print_open_tag : tag -> unit; - print_close_tag : tag -> unit; +type formatter_stag_functions = { + mark_open_stag : stag -> string; + mark_close_stag : stag -> string; + print_open_stag : stag -> unit; + print_close_stag : stag -> unit; } (** The semantic tag handling functions specific to a formatter: [mark] versions are the 'tag-marking' functions that associate a string @@ -735,19 +853,19 @@ type formatter_tag_functions = { regular printing when a tag is closed or opened. *) -val pp_set_formatter_tag_functions : - formatter -> formatter_tag_functions -> unit -val set_formatter_tag_functions : formatter_tag_functions -> unit -(** [pp_set_formatter_tag_functions ppf tag_funs] changes the meaning of +val pp_set_formatter_stag_functions : + formatter -> formatter_stag_functions -> unit +val set_formatter_stag_functions : formatter_stag_functions -> unit +(** [pp_set_formatter_stag_functions ppf tag_funs] changes the meaning of opening and closing semantic tag operations to use the functions in [tag_funs] when printing on [ppf]. When opening a semantic tag with name [t], the string [t] is passed to the - opening tag-marking function (the [mark_open_tag] field of the + opening tag-marking function (the [mark_open_stag] field of the record [tag_funs]), that must return the opening tag marker for - that name. When the next call to [close_tag ()] happens, the semantic tag + that name. When the next call to [close_stag ()] happens, the semantic tag name [t] is sent back to the closing tag-marking function (the - [mark_close_tag] field of record [tag_funs]), that must return a + [mark_close_stag] field of record [tag_funs]), that must return a closing tag marker for that name. The [print_] field of the record contains the tag-printing functions that @@ -755,9 +873,9 @@ val set_formatter_tag_functions : formatter_tag_functions -> unit in the pretty-printer queue. *) -val pp_get_formatter_tag_functions : - formatter -> unit -> formatter_tag_functions -val get_formatter_tag_functions : unit -> formatter_tag_functions +val pp_get_formatter_stag_functions : + formatter -> unit -> formatter_stag_functions +val get_formatter_stag_functions : unit -> formatter_stag_functions (** Return the current semantic tag operation functions of the standard pretty-printer. *) @@ -772,7 +890,7 @@ val get_formatter_tag_functions : unit -> formatter_tag_functions For instance, given a {!Buffer.t} buffer [b], {!formatter_of_buffer} [b] returns a new formatter using buffer [b] as its output device. - Similarly, given a {!Pervasives.out_channel} output channel [oc], + Similarly, given a {!Stdlib.out_channel} output channel [oc], {!formatter_of_out_channel} [oc] returns a new formatter using channel [oc] as its output device. @@ -789,13 +907,13 @@ val formatter_of_out_channel : out_channel -> formatter val std_formatter : formatter (** The standard formatter to write to standard output. - It is defined as {!formatter_of_out_channel} {!Pervasives.stdout}. + It is defined as {!formatter_of_out_channel} {!Stdlib.stdout}. *) val err_formatter : formatter (** A formatter to write to standard error. - It is defined as {!formatter_of_out_channel} {!Pervasives.stderr}. + It is defined as {!formatter_of_out_channel} {!Stdlib.stderr}. *) val formatter_of_buffer : Buffer.t -> formatter @@ -826,9 +944,9 @@ val make_formatter : For instance, {[ make_formatter - (Pervasives.output oc) - (fun () -> Pervasives.flush oc) ]} - returns a formatter to the {!Pervasives.out_channel} [oc]. + (Stdlib.output oc) + (fun () -> Stdlib.flush oc) ]} + returns a formatter to the {!Stdlib.out_channel} [oc]. *) val formatter_of_out_functions : @@ -949,6 +1067,23 @@ val pp_print_text : formatter -> string -> unit @since 4.02.0 *) +val pp_print_option : + ?none:(formatter -> unit -> unit) -> + (formatter -> 'a -> unit) -> (formatter -> 'a option -> unit) +(** [pp_print_option ?none pp_v ppf o] prints [o] on [ppf] + using [pp_v] if [o] is [Some v] and [none] if it is [None]. [none] + prints nothing by default. + + @since 4.08 *) + +val pp_print_result : + ok:(formatter -> 'a -> unit) -> error:(formatter -> 'e -> unit) -> + formatter -> ('a, 'e) result -> unit +(** [pp_print_result ~ok ~error ppf r] prints [r] on [ppf] using + [ok] if [r] is [Ok _] and [error] if [r] is [Error _]. + + @since 4.08 *) + (** {1:fpp Formatted pretty-printing} *) (** @@ -1016,8 +1151,8 @@ val fprintf : formatter -> ('a, formatter, unit) format -> 'a specification is any character string that does not contain the closing character ['>']. If omitted, the tag name defaults to the empty string. - For more details about semantic tags, see the functions {!open_tag} and - {!close_tag}. + For more details about semantic tags, see the functions {!open_stag} and + {!close_stag}. - [@\}]: close the most recently opened semantic tag. - [@?]: flush the pretty-printer as with [print_flush ()]. This is equivalent to the conversion [%!]. @@ -1068,6 +1203,29 @@ val asprintf : ('a, formatter, unit, string) format4 -> 'a @since 4.01.0 *) +val dprintf : + ('a, formatter, unit, formatter -> unit) format4 -> 'a +(** Same as {!fprintf}, except the formatter is the last argument. + [dprintf "..." a b c] is a function of type + [formatter -> unit] which can be given to a format specifier [%t]. + + This can be used as a replacement for {!asprintf} to delay + formatting decisions. Using the string returned by {!asprintf} in a + formatting context forces formatting decisions to be taken in + isolation, and the final string may be created + prematurely. {!dprintf} allows delay of formatting decisions until + the final formatting context is known. + For example: +{[ + let t = Format.dprintf "%i@ %i@ %i" 1 2 3 in + ... + Format.printf "@[%t@]" t +]} + + @since 4.08.0 +*) + + val ifprintf : formatter -> ('a, formatter, unit) format -> 'a (** Same as [fprintf] above, but does not print anything. Useful to ignore some material when conditionally printing. @@ -1083,6 +1241,15 @@ val kfprintf : (** Same as [fprintf] above, but instead of returning immediately, passes the formatter to its first argument at the end of printing. *) +val kdprintf : + ((formatter -> unit) -> 'a) -> + ('b, formatter, unit, 'a) format4 -> 'b +(** Same as {!dprintf} above, but instead of returning immediately, + passes the suspended printer to its first argument at the end of printing. + + @since 4.08.0 +*) + val ikfprintf : (formatter -> 'a) -> formatter -> ('b, formatter, unit, 'a) format4 -> 'b @@ -1150,3 +1317,55 @@ val pp_get_all_formatter_output_functions : (int -> unit) [@@ocaml.deprecated "Use Format.pp_get_formatter_out_functions instead."] (** @deprecated Subsumed by [pp_get_formatter_out_functions]. *) + +(** {2 String tags} *) + +val pp_open_tag : formatter -> tag -> unit +[@@ocaml.deprecated "Use Format.pp_open_stag."] +(** @deprecated Subsumed by {!pp_open_stag}. *) + +val open_tag : tag -> unit +[@@ocaml.deprecated "Use Format.open_stag."] +(** @deprecated Subsumed by {!open_stag}. *) + +val pp_close_tag : formatter -> unit -> unit +[@@ocaml.deprecated "Use Format.pp_close_stag."] +(** @deprecated Subsumed by {!pp_close_stag}. *) + +val close_tag : unit -> unit +[@@ocaml.deprecated "Use Format.close_stag."] +(** @deprecated Subsumed by {!close_stag}. *) + +type formatter_tag_functions = { + mark_open_tag : tag -> string; + mark_close_tag : tag -> string; + print_open_tag : tag -> unit; + print_close_tag : tag -> unit; +} +[@@ocaml.deprecated "Use formatter_stag_functions."] +(** @deprecated Subsumed by {!formatter_stag_functions}. *) + +val pp_set_formatter_tag_functions : + formatter -> formatter_tag_functions -> unit +[@@ocaml.deprecated + "This function will erase non-string tag formatting functions. \ + Use Format.pp_set_formatter_stag_functions."] +[@@warning "-3"] +(** This function will erase non-string tag formatting functions. + @deprecated Subsumed by {!pp_set_formatter_stag_functions}. *) + +val set_formatter_tag_functions : formatter_tag_functions -> unit +[@@ocaml.deprecated "Use Format.set_formatter_stag_functions."] +[@@warning "-3"] +(** @deprecated Subsumed by {!set_formatter_stag_functions}. *) + +val pp_get_formatter_tag_functions : + formatter -> unit -> formatter_tag_functions +[@@ocaml.deprecated "Use Format.pp_get_formatter_stag_functions."] +[@@warning "-3"] +(** @deprecated Subsumed by {!pp_get_formatter_stag_functions}. *) + +val get_formatter_tag_functions : unit -> formatter_tag_functions +[@@ocaml.deprecated "Use Format.get_formatter_stag_functions."] +[@@warning "-3"] +(** @deprecated Subsumed by {!get_formatter_stag_functions}. *) diff --git a/stdlib/fun.ml b/stdlib/fun.ml new file mode 100644 index 00000000..247f107e --- /dev/null +++ b/stdlib/fun.ml @@ -0,0 +1,34 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* The OCaml programmers *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +external id : 'a -> 'a = "%identity" +let const c _ = c +let flip f x y = f y x +let negate p v = not (p v) + +exception Finally_raised of exn + +let protect ~(finally : unit -> unit) work = + let finally_no_exn () = + try finally () with e -> + let bt = Printexc.get_raw_backtrace () in + Printexc.raise_with_backtrace (Finally_raised e) bt + in + match work () with + | result -> finally_no_exn () ; result + | exception work_exn -> + let work_bt = Printexc.get_raw_backtrace () in + finally_no_exn () ; + Printexc.raise_with_backtrace work_exn work_bt diff --git a/stdlib/fun.mli b/stdlib/fun.mli new file mode 100644 index 00000000..202e4c23 --- /dev/null +++ b/stdlib/fun.mli @@ -0,0 +1,63 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* The OCaml programmers *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** Function manipulation. + + @since 4.08 *) + +(** {1 Combinators} *) + +external id : 'a -> 'a = "%identity" +(** [id] is the identity function. For any argument [x], [id x] is [x]. *) + +val const : 'a -> (_ -> 'a) +(** [const c] is a function that always returns the value [c]. For any + argument [x], [(const c) x] is [c]. *) + +val flip : ('a -> 'b -> 'c) -> ('b -> 'a -> 'c) +(** [flip f] reverses the argument order of the binary function + [f]. For any arguments [x] and [y], [(flip f) x y] is [f y x]. *) + +val negate : ('a -> bool) -> ('a -> bool) +(** [negate p] is the negation of the predicate function [p]. For any + argument [x], [(negate p) x] is [not (p x)]. *) + +(** {1 Exception handling} *) + +val protect : finally:(unit -> unit) -> (unit -> 'a) -> 'a +(** [protect ~finally work] invokes [work ()] and then [finally ()] + before [work ()] returns with its value or an exception. In the + latter case the exception is re-raised after [finally ()]. If + [finally ()] raises an exception, then the exception + {!Finally_raised} is raised instead. + + [protect] can be used to enforce local invariants whether [work + ()] returns normally or raises an exception. However, it does not + protect against unexpected exceptions raised inside [finally ()] + such as {!Stdlib.Out_of_memory}, {!Stdlib.Stack_overflow}, or + asynchronous exceptions raised by signal handlers + (e.g. {!Sys.Break}). + + Note: It is a {e programming error} if other kinds of exceptions + are raised by [finally], as any exception raised in [work ()] will + be lost in the event of a {!Finally_raised} exception. Therefore, + one should make sure to handle those inside the finally. *) + +exception Finally_raised of exn +(** [Finally_raised exn] is raised by [protect ~finally work] when + [finally] raises an exception [exn]. This exception denotes either + an unexpected exception or a programming error. As a general rule, + one should not catch a [Finally_raised] exception except as part of + a catch-all handler. *) diff --git a/stdlib/gc.ml b/stdlib/gc.ml index d3dd069b..41a8f8c8 100644 --- a/stdlib/gc.ml +++ b/stdlib/gc.ml @@ -41,6 +41,9 @@ type control = { mutable stack_limit : int; mutable allocation_policy : int; window_size : int; + custom_major_ratio : int; + custom_minor_ratio : int; + custom_minor_max_size : int; } external stat : unit -> stat = "caml_gc_stat" diff --git a/stdlib/gc.mli b/stdlib/gc.mli index bae8c8bc..47e7dedf 100644 --- a/stdlib/gc.mli +++ b/stdlib/gc.mli @@ -84,10 +84,13 @@ type stat = type control = { mutable minor_heap_size : int; + [@ocaml.deprecated_mutable "Use {(Gc.get()) with Gc.minor_heap_size = ...}"] (** The size (in words) of the minor heap. Changing this parameter will trigger a minor collection. Default: 256k. *) mutable major_heap_increment : int; + [@ocaml.deprecated_mutable + "Use {(Gc.get()) with Gc.major_heap_increment = ...}"] (** How much to add to the major heap when increasing it. If this number is less than or equal to 1000, it is a percentage of the current heap size (i.e. setting it to 100 will double the heap @@ -95,6 +98,7 @@ type control = number of words that will be added to the heap. Default: 15. *) mutable space_overhead : int; + [@ocaml.deprecated_mutable "Use {(Gc.get()) with Gc.space_overhead = ...}"] (** The major GC speed is computed from this parameter. This is the memory that will be "wasted" because the GC does not immediately collect unreachable blocks. It is expressed as a @@ -104,6 +108,7 @@ type control = Default: 80. *) mutable verbose : int; + [@ocaml.deprecated_mutable "Use {(Gc.get()) with Gc.verbose = ...}"] (** This value controls the GC messages on standard error output. It is a sum of some of the following flags, to print messages on the corresponding events: @@ -121,6 +126,7 @@ type control = Default: 0. *) mutable max_overhead : int; + [@ocaml.deprecated_mutable "Use {(Gc.get()) with Gc.max_overhead = ...}"] (** Heap compaction is triggered when the estimated amount of "wasted" memory is more than [max_overhead] percent of the amount of live data. If [max_overhead] is set to 0, heap @@ -132,11 +138,14 @@ type control = Default: 500. *) mutable stack_limit : int; + [@ocaml.deprecated_mutable "Use {(Gc.get()) with Gc.stack_limit = ...}"] (** The maximum size of the stack (in words). This is only relevant to the byte-code runtime, as the native code runtime uses the operating system's stack. Default: 1024k. *) mutable allocation_policy : int; + [@ocaml.deprecated_mutable + "Use {(Gc.get()) with Gc.allocation_policy = ...}"] (** The policy used for allocating in the heap. Possible values are 0 and 1. 0 is the next-fit policy, which is quite fast but can result in fragmentation. 1 is the @@ -149,7 +158,41 @@ type control = out variations in its workload. This is an integer between 1 and 50. Default: 1. @since 4.03.0 *) -} + + custom_major_ratio : int; + (** Target ratio of floating garbage to major heap size for + out-of-heap memory held by custom values located in the major + heap. The GC speed is adjusted to try to use this much memory + for dead values that are not yet collected. Expressed as a + percentage of major heap size. The default value keeps the + out-of-heap floating garbage about the same size as the + in-heap overhead. + Note: this only applies to values allocated with + [caml_alloc_custom_mem] (e.g. bigarrays). + Default: 44. + @since 4.08.0 *) + + custom_minor_ratio : int; + (** Bound on floating garbage for out-of-heap memory held by + custom values in the minor heap. A minor GC is triggered when + this much memory is held by custom values located in the minor + heap. Expressed as a percentage of minor heap size. + Note: this only applies to values allocated with + [caml_alloc_custom_mem] (e.g. bigarrays). + Default: 100. + @since 4.08.0 *) + + custom_minor_max_size : int; + (** Maximum amount of out-of-heap memory for each custom value + allocated in the minor heap. When a custom value is allocated + on the minor heap and holds more than this many bytes, only + this value is counted against [custom_minor_ratio] and the + rest is directly counted against [custom_major_ratio]. + Note: this only applies to values allocated with + [caml_alloc_custom_mem] (e.g. bigarrays). + Default: 8192 bytes. + @since 4.08.0 *) + } (** The GC parameters are given as a [control] record. Note that these parameters can also be initialised by setting the OCAMLRUNPARAM environment variable. See the documentation of @@ -306,7 +349,7 @@ val finalise : ('a -> unit) -> 'a -> unit The results of calling {!String.make}, {!Bytes.make}, {!Bytes.create}, - {!Array.make}, and {!Pervasives.ref} are guaranteed to be + {!Array.make}, and {!Stdlib.ref} are guaranteed to be heap-allocated and non-constant except when the length argument is [0]. *) @@ -318,9 +361,9 @@ val finalise_last : (unit -> unit) -> 'a -> unit first time. So contrary to {!finalise} the value will never be reachable again or used again. In particular every weak pointer and ephemeron that contained this value as key or data is unset - before running the finalisation function. Moreover the - finalisation function attached with `GC.finalise` are always - called before the finalisation function attached with `GC.finalise_last`. + before running the finalisation function. Moreover the finalisation + functions attached with {!finalise} are always called before the + finalisation functions attached with {!finalise_last}. @since 4.04 *) diff --git a/stdlib/hashtbl.ml b/stdlib/hashtbl.ml index 99726341..82ee9db7 100644 --- a/stdlib/hashtbl.ml +++ b/stdlib/hashtbl.ml @@ -354,7 +354,7 @@ let stats h = max_bucket_length = mbl; bucket_histogram = histo } -(** {6 Iterators} *) +(** {1 Iterators} *) let to_seq tbl = (* capture current array, so that even if the table is resized we @@ -570,6 +570,17 @@ module MakeSeeded(H: SeededHashedType): (SeededS with type key = H.t) = H.equal k key || mem_in_bucket next in mem_in_bucket h.data.(key_index h key) + let add_seq tbl i = + Seq.iter (fun (k,v) -> add tbl k v) i + + let replace_seq tbl i = + Seq.iter (fun (k,v) -> replace tbl k v) i + + let of_seq i = + let tbl = create 16 in + replace_seq tbl i; + tbl + let iter = iter let filter_map_inplace = filter_map_inplace let fold = fold @@ -578,9 +589,6 @@ module MakeSeeded(H: SeededHashedType): (SeededS with type key = H.t) = let to_seq = to_seq let to_seq_keys = to_seq_keys let to_seq_values = to_seq_values - let add_seq = add_seq - let replace_seq = replace_seq - let of_seq = of_seq end module Make(H: HashedType): (S with type key = H.t) = @@ -591,4 +599,8 @@ module Make(H: HashedType): (S with type key = H.t) = let hash (_seed: int) x = H.hash x end) let create sz = create ~random:false sz + let of_seq i = + let tbl = create 16 in + replace_seq tbl i; + tbl end diff --git a/stdlib/hashtbl.mli b/stdlib/hashtbl.mli index a96c99c3..5a9d825a 100644 --- a/stdlib/hashtbl.mli +++ b/stdlib/hashtbl.mli @@ -216,10 +216,13 @@ val stats : ('a, 'b) t -> statistics buckets by size. @since 4.00.0 *) -(** {6 Iterators} *) +(** {1 Iterators} *) val to_seq : ('a,'b) t -> ('a * 'b) Seq.t -(** Iterate on the whole table, in unspecified order. +(** Iterate on the whole table. The order in which the bindings + appear in the sequence is unspecified. However, if the table contains + several bindings for the same key, they appear in reversed order of + introduction, that is, the most recent binding appears first. The behavior is not defined if the hash table is modified during the iteration. @@ -227,11 +230,11 @@ val to_seq : ('a,'b) t -> ('a * 'b) Seq.t @since 4.07 *) val to_seq_keys : ('a,_) t -> 'a Seq.t -(** Iterate on 'as, in ascending order +(** Same as [Seq.map fst (to_seq m)] @since 4.07 *) val to_seq_values : (_,'b) t -> 'b Seq.t -(** Iterate on values, in ascending order of their corresponding 'a +(** Same as [Seq.map snd (to_seq m)] @since 4.07 *) val add_seq : ('a,'b) t -> ('a * 'b) Seq.t -> unit @@ -298,7 +301,7 @@ module type HashedType = (provided objects do not contain floats) - ([(fun x y -> compare x y = 0)], {!Hashtbl.hash}) for comparing objects by structure - and handling {!Pervasives.nan} correctly + and handling {!Stdlib.nan} correctly - ([(==)], {!Hashtbl.hash}) for comparing objects by physical equality (e.g. for mutable or cyclic objects). *) end @@ -446,7 +449,7 @@ module MakeSeeded (H : SeededHashedType) : SeededS with type key = H.t val hash : 'a -> int (** [Hashtbl.hash x] associates a nonnegative integer to any value of any type. It is guaranteed that - if [x = y] or [Pervasives.compare x y = 0], then [hash x = hash y]. + if [x = y] or [Stdlib.compare x y = 0], then [hash x = hash y]. Moreover, [hash] always terminates, even on cyclic structures. *) val seeded_hash : int -> 'a -> int diff --git a/stdlib/headernt.c b/stdlib/headernt.c index be71e946..43109c86 100644 --- a/stdlib/headernt.c +++ b/stdlib/headernt.c @@ -90,7 +90,7 @@ static BOOL WINAPI ctrl_handler(DWORD event) #if WINDOWS_UNICODE #define CP CP_UTF8 #else -#define CP CP_THREAD_ACP +#define CP CP_ACP #endif static void write_console(HANDLE hOut, WCHAR *wstr) @@ -98,10 +98,13 @@ static void write_console(HANDLE hOut, WCHAR *wstr) DWORD consoleMode, numwritten, len; static char str[MAX_PATH]; - if (GetConsoleMode(hOut, &consoleMode) != 0) { /* The output stream is a Console */ + if (GetConsoleMode(hOut, &consoleMode) != 0) { + /* The output stream is a Console */ WriteConsole(hOut, wstr, wcslen(wstr), &numwritten, NULL); } else { /* The output stream is redirected */ - len = WideCharToMultiByte(CP, 0, wstr, wcslen(wstr), str, sizeof(str), NULL, NULL); + len = + WideCharToMultiByte(CP, 0, wstr, wcslen(wstr), str, sizeof(str), + NULL, NULL); WriteFile(hOut, str, len, &numwritten, NULL); } } @@ -113,7 +116,8 @@ static __inline void __declspec(noreturn) run_runtime(wchar_t * runtime, STARTUPINFO stinfo; PROCESS_INFORMATION procinfo; DWORD retcode; - if (SearchPath(NULL, runtime, L".exe", sizeof(path)/sizeof(wchar_t), path, &runtime) == 0) { + if (SearchPath(NULL, runtime, L".exe", sizeof(path)/sizeof(wchar_t), + path, &runtime) == 0) { HANDLE errh; errh = GetStdHandle(STD_ERROR_HANDLE); write_console(errh, L"Cannot exec "); @@ -180,7 +184,8 @@ int wmain(void) #endif } CloseHandle(h); - MultiByteToWideChar(CP, 0, runtime_path, -1, wruntime_path, sizeof(wruntime_path)/sizeof(wchar_t)); + MultiByteToWideChar(CP, 0, runtime_path, -1, wruntime_path, + sizeof(wruntime_path)/sizeof(wchar_t)); run_runtime(wruntime_path , cmdline); #if _MSC_VER >= 1200 __assume(0); /* Not reached */ diff --git a/stdlib/int.ml b/stdlib/int.ml new file mode 100644 index 00000000..b8f32cc0 --- /dev/null +++ b/stdlib/int.ml @@ -0,0 +1,50 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* The OCaml programmers *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +type t = int + +let zero = 0 +let one = 1 +let minus_one = -1 +external neg : int -> int = "%negint" +external add : int -> int -> int = "%addint" +external sub : int -> int -> int = "%subint" +external mul : int -> int -> int = "%mulint" +external div : int -> int -> int = "%divint" +external rem : int -> int -> int = "%modint" +external succ : int -> int = "%succint" +external pred : int -> int = "%predint" +let abs x = if x >= 0 then x else -x +let max_int = (-1) lsr 1 +let min_int = max_int + 1 +external logand : int -> int -> int = "%andint" +external logor : int -> int -> int = "%orint" +external logxor : int -> int -> int = "%xorint" +let lognot x = logxor x (-1) +external shift_left : int -> int -> int = "%lslint" +external shift_right : int -> int -> int = "%asrint" +external shift_right_logical : int -> int -> int = "%lsrint" +let equal : int -> int -> bool = ( = ) +let compare : int -> int -> int = Stdlib.compare +external to_float : int -> float = "%floatofint" +external of_float : float -> int = "%intoffloat" + +(* +external int_of_string : string -> int = "caml_int_of_string" +let of_string s = try Some (int_of_string s) with Failure _ -> None +*) + +external format_int : string -> int -> string = "caml_format_int" +let to_string x = format_int "%d" x diff --git a/stdlib/int.mli b/stdlib/int.mli new file mode 100644 index 00000000..12a0167d --- /dev/null +++ b/stdlib/int.mli @@ -0,0 +1,144 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* The OCaml programmers *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** Integer values. + + Integers are {!Sys.int_size} bits wide and use two's complement + representation. All operations are taken modulo + 2{^[Sys.int_size]}. They do not fail on overflow. + + @since 4.08 *) + +(** {1:ints Integers} *) + +type t = int +(** The type for integer values. *) + +val zero : int +(** [zero] is the integer [0]. *) + +val one : int +(** [one] is the integer [1]. *) + +val minus_one : int +(** [minus_one] is the integer [-1]. *) + +external neg : int -> int = "%negint" +(** [neg x] is [~-x]. *) + +external add : int -> int -> int = "%addint" +(** [add x y] is the addition [x + y]. *) + +external sub : int -> int -> int = "%subint" +(** [sub x y] is the subtraction [x - y]. *) + +external mul : int -> int -> int = "%mulint" +(** [mul x y] is the multiplication [x * y]. *) + +external div : int -> int -> int = "%divint" +(** [div x y] is the division [x / y]. See {!Stdlib.( / )} for details. *) + +external rem : int -> int -> int = "%modint" +(** [rem x y] is the remainder [x mod y]. See {!Stdlib.( mod )} for details. *) + +external succ : int -> int = "%succint" +(** [succ x] is [add x 1]. *) + +external pred : int -> int = "%predint" +(** [pred x] is [sub x 1]. *) + +val abs : int -> int +(** [abs x] is the absolute value of [x]. That is [x] if [x] is positive + and [neg x] if [x] is negative. {b Warning.} This may be negative if + the argument is {!min_int}. *) + +val max_int : int +(** [max_int] is the greatest representable integer, + [2{^[Sys.int_size - 1]} - 1]. *) + +val min_int : int +(** [min_int] is the smallest representable integer, + [-2{^[Sys.int_size - 1]}]. *) + +external logand : int -> int -> int = "%andint" +(** [logand x y] is the bitwise logical and of [x] and [y]. *) + +external logor : int -> int -> int = "%orint" +(** [logor x y] is the bitwise logical or of [x] and [y]. *) + +external logxor : int -> int -> int = "%xorint" +(** [logxor x y] is the bitwise logical exclusive or of [x] and [y]. *) + +val lognot : int -> int +(** [lognot x] is the bitwise logical negation of [x]. *) + +external shift_left : int -> int -> int = "%lslint" +(** [shift_left x n] shifts [x] to the left by [n] bits. The result + is unspecified if [n < 0] or [n > ]{!Sys.int_size}. *) + +external shift_right : int -> int -> int = "%asrint" +(** [shift_right x n] shifts [x] to the right by [n] bits. This is an + arithmetic shift: the sign bit of [x] is replicated and inserted + in the vacated bits. The result is unspecified if [n < 0] or + [n > ]{!Sys.int_size}. *) + +external shift_right_logical : int -> int -> int = "%lsrint" +(** [shift_right x n] shifts [x] to the right by [n] bits. This is a + logical shift: zeroes are inserted in the vacated bits regardless + of the sign of [x]. The result is unspecified if [n < 0] or + [n > ]{!Sys.int_size}. *) + +(** {1:preds Predicates and comparisons} *) + +val equal : int -> int -> bool +(** [equal x y] is [true] iff [x = y]. *) + +val compare : int -> int -> int +(** [compare x y] is {!Stdlib.compare}[ x y] but more efficient. *) + +(** {1:convert Converting} *) + +external to_float : int -> float = "%floatofint" +(** [to_float x] is [x] as a floating point number. *) + +external of_float : float -> int = "%intoffloat" +(** [of_float x] truncates [x] to an integer. The result is + unspecified if the argument is [nan] or falls outside the range of + representable integers. *) + +(* +val of_string : string -> int option +(** [of_string s] is [Some s] if [s] can be parsed to an integer + in the range representable by the type [int] (note that this + depends on {!Sys.int_size}) and [None] otherwise. + + The string may start with an optional ['-'] or ['+'] sign, and may + be followed by an optional prefix that specifies the base in which + the number is expressed. If there is not prefix or if the prefix + is [0u] or [0U] it is expressed in decimal. If the prefix is [0x] + or [0X] it is expressed in hexadecimal. If the prefix is [0o] or + [0O] it is expressed in octal. If the prefix is [0b] or [0B] it is + expressed in binary. + + When the [0u] or [0U] prefix is used, the represented number may + exceed {!max_int} or {!min_int} in which case it wraps around + modulo 2{^[Sys.int_size]} like arithmetic operations do. + + The ['_'] (underscore) character can appear anywhere between two + digits of the number. *) +*) + +val to_string : int -> string +(** [to_string x] is the written representation of [x] in decimal. *) diff --git a/stdlib/int32.ml b/stdlib/int32.ml index 959c0424..e159851e 100644 --- a/stdlib/int32.ml +++ b/stdlib/int32.ml @@ -52,6 +52,22 @@ let min_int = 0x80000000l let max_int = 0x7FFFFFFFl let lognot n = logxor n (-1l) +let unsigned_to_int = + match Sys.word_size with + | 32 -> + let max_int = of_int Stdlib.max_int in + fun n -> + if compare zero n <= 0 && compare n max_int <= 0 then + Some (to_int n) + else + None + | 64 -> + (* So that it compiles in 32-bit *) + let move = int_of_string "0x1_0000_0000" in + fun n -> let i = to_int n in Some (if i < 0 then i + move else i) + | _ -> + assert false + external format : string -> int32 -> string = "caml_int32_format" let to_string n = format "%d" n @@ -64,5 +80,22 @@ let of_string_opt s = type t = int32 -let compare (x: t) (y: t) = Pervasives.compare x y +let compare (x: t) (y: t) = Stdlib.compare x y let equal (x: t) (y: t) = compare x y = 0 + +let unsigned_compare n m = + compare (sub n min_int) (sub m min_int) + +(* Unsigned division from signed division of the same + bitness. See Warren Jr., Henry S. (2013). Hacker's Delight (2 ed.), Sec 9-3. +*) +let unsigned_div n d = + if d < zero then + if unsigned_compare n d < 0 then zero else one + else + let q = shift_left (div (shift_right_logical n 1) d) 1 in + let r = sub n (mul q d) in + if unsigned_compare r d >= 0 then succ q else q + +let unsigned_rem n d = + sub n (mul (unsigned_div n d) d) diff --git a/stdlib/int32.mli b/stdlib/int32.mli index 199d86f2..a6bdb572 100644 --- a/stdlib/int32.mli +++ b/stdlib/int32.mli @@ -24,7 +24,15 @@ Performance notice: values of type [int32] occupy more memory space than values of type [int], and arithmetic operations on [int32] are generally slower than those on [int]. Use [int32] - only when the application requires exact 32-bit arithmetic. *) + only when the application requires exact 32-bit arithmetic. + + Literals for 32-bit integers are suffixed by l: + {[ + let zero: int32 = 0l + let one: int32 = 1l + let m_one: int32 = -1l + ]} +*) val zero : int32 (** The 32-bit integer 0. *) @@ -50,7 +58,13 @@ external mul : int32 -> int32 -> int32 = "%int32_mul" external div : int32 -> int32 -> int32 = "%int32_div" (** Integer division. Raise [Division_by_zero] if the second argument is zero. This division rounds the real quotient of - its arguments towards zero, as specified for {!Pervasives.(/)}. *) + its arguments towards zero, as specified for {!Stdlib.(/)}. *) + +val unsigned_div : int32 -> int32 -> int32 +(** Same as {!div}, except that arguments and result are interpreted as {e + unsigned} 32-bit integers. + + @since 4.08.0 *) external rem : int32 -> int32 -> int32 = "%int32_mod" (** Integer remainder. If [y] is not zero, the result @@ -58,6 +72,12 @@ external rem : int32 -> int32 -> int32 = "%int32_mod" [x = Int32.add (Int32.mul (Int32.div x y) y) (Int32.rem x y)]. If [y = 0], [Int32.rem x y] raises [Division_by_zero]. *) +val unsigned_rem : int32 -> int32 -> int32 +(** Same as {!rem}, except that arguments and result are interpreted as {e + unsigned} 32-bit integers. + + @since 4.08.0 *) + val succ : int32 -> int32 (** Successor. [Int32.succ x] is [Int32.add x Int32.one]. *) @@ -104,7 +124,8 @@ external shift_right_logical : int32 -> int -> int32 = "%int32_lsr" external of_int : int -> int32 = "%int32_of_int" (** Convert the given integer (type [int]) to a 32-bit integer - (type [int32]). *) + (type [int32]). On 64-bit platforms, the argument is taken + modulo 2{^32}. *) external to_int : int32 -> int = "%int32_to_int" (** Convert the given 32-bit integer (type [int32]) to an @@ -113,6 +134,13 @@ external to_int : int32 -> int = "%int32_to_int" during the conversion. On 64-bit platforms, the conversion is exact. *) +val unsigned_to_int : int32 -> int option +(** Same as {!to_int}, but interprets the argument as an {e unsigned} integer. + Returns [None] if the unsigned value of the argument cannot fit into an + [int]. + + @since 4.08.0 *) + external of_float : float -> int32 = "caml_int32_of_float" "caml_int32_of_float_unboxed" [@@unboxed] [@@noalloc] @@ -128,7 +156,7 @@ external to_float : int32 -> float external of_string : string -> int32 = "caml_int32_of_string" (** Convert the given string to a 32-bit integer. - The string is read in decimal (by default, or if the string + The string is read in decimal (by default, or if the string begins with [0u]) or in hexadecimal, octal or binary if the string begins with [0x], [0o] or [0b] respectively. @@ -172,10 +200,16 @@ type t = int32 val compare: t -> t -> int (** The comparison function for 32-bit integers, with the same specification as - {!Pervasives.compare}. Along with the type [t], this function [compare] + {!Stdlib.compare}. Along with the type [t], this function [compare] allows the module [Int32] to be passed as argument to the functors {!Set.Make} and {!Map.Make}. *) +val unsigned_compare: t -> t -> int +(** Same as {!compare}, except that arguments are interpreted as {e unsigned} + 32-bit integers. + + @since 4.08.0 *) + val equal: t -> t -> bool (** The equal function for int32s. @since 4.03.0 *) diff --git a/stdlib/int64.ml b/stdlib/int64.ml index 8bc95a03..1640368d 100644 --- a/stdlib/int64.ml +++ b/stdlib/int64.ml @@ -50,6 +50,14 @@ let min_int = 0x8000000000000000L let max_int = 0x7FFFFFFFFFFFFFFFL let lognot n = logxor n (-1L) +let unsigned_to_int = + let max_int = of_int Stdlib.max_int in + fun n -> + if compare zero n <= 0 && compare n max_int <= 0 then + Some (to_int n) + else + None + external format : string -> int64 -> string = "caml_int64_format" let to_string n = format "%d" n @@ -71,5 +79,22 @@ external float_of_bits : int64 -> float type t = int64 -let compare (x: t) (y: t) = Pervasives.compare x y +let compare (x: t) (y: t) = Stdlib.compare x y let equal (x: t) (y: t) = compare x y = 0 + +let unsigned_compare n m = + compare (sub n min_int) (sub m min_int) + +(* Unsigned division from signed division of the same + bitness. See Warren Jr., Henry S. (2013). Hacker's Delight (2 ed.), Sec 9-3. +*) +let unsigned_div n d = + if d < zero then + if unsigned_compare n d < 0 then zero else one + else + let q = shift_left (div (shift_right_logical n 1) d) 1 in + let r = sub n (mul q d) in + if unsigned_compare r d >= 0 then succ q else q + +let unsigned_rem n d = + sub n (mul (unsigned_div n d) d) diff --git a/stdlib/int64.mli b/stdlib/int64.mli index 96f48a60..732cc008 100644 --- a/stdlib/int64.mli +++ b/stdlib/int64.mli @@ -25,6 +25,13 @@ space than values of type [int], and arithmetic operations on [int64] are generally slower than those on [int]. Use [int64] only when the application requires exact 64-bit arithmetic. + + Literals for 64-bit integers are suffixed by L: + {[ + let zero: int64 = 0L + let one: int64 = 1L + let m_one: int64 = -1L + ]} *) val zero : int64 @@ -51,7 +58,13 @@ external mul : int64 -> int64 -> int64 = "%int64_mul" external div : int64 -> int64 -> int64 = "%int64_div" (** Integer division. Raise [Division_by_zero] if the second argument is zero. This division rounds the real quotient of - its arguments towards zero, as specified for {!Pervasives.(/)}. *) + its arguments towards zero, as specified for {!Stdlib.(/)}. *) + +val unsigned_div : int64 -> int64 -> int64 +(** Same as {!div}, except that arguments and result are interpreted as {e + unsigned} 64-bit integers. + + @since 4.08.0 *) external rem : int64 -> int64 -> int64 = "%int64_mod" (** Integer remainder. If [y] is not zero, the result @@ -59,6 +72,12 @@ external rem : int64 -> int64 -> int64 = "%int64_mod" [x = Int64.add (Int64.mul (Int64.div x y) y) (Int64.rem x y)]. If [y = 0], [Int64.rem x y] raises [Division_by_zero]. *) +val unsigned_rem : int64 -> int64 -> int64 +(** Same as {!rem}, except that arguments and result are interpreted as {e + unsigned} 64-bit integers. + + @since 4.08.0 *) + val succ : int64 -> int64 (** Successor. [Int64.succ x] is [Int64.add x Int64.one]. *) @@ -114,6 +133,13 @@ external to_int : int64 -> int = "%int64_to_int" is taken modulo 2{^31}, i.e. the top 33 bits are lost during the conversion. *) +val unsigned_to_int : int64 -> int option +(** Same as {!to_int}, but interprets the argument as an {e unsigned} integer. + Returns [None] if the unsigned value of the argument cannot fit into an + [int]. + + @since 4.08.0 *) + external of_float : float -> int64 = "caml_int64_of_float" "caml_int64_of_float_unboxed" [@@unboxed] [@@noalloc] @@ -150,7 +176,7 @@ external to_nativeint : int64 -> nativeint = "%int64_to_nativeint" external of_string : string -> int64 = "caml_int64_of_string" (** Convert the given string to a 64-bit integer. - The string is read in decimal (by default, or if the string + The string is read in decimal (by default, or if the string begins with [0u]) or in hexadecimal, octal or binary if the string begins with [0x], [0o] or [0b] respectively. @@ -193,10 +219,16 @@ type t = int64 val compare: t -> t -> int (** The comparison function for 64-bit integers, with the same specification as - {!Pervasives.compare}. Along with the type [t], this function [compare] + {!Stdlib.compare}. Along with the type [t], this function [compare] allows the module [Int64] to be passed as argument to the functors {!Set.Make} and {!Map.Make}. *) +val unsigned_compare: t -> t -> int +(** Same as {!compare}, except that arguments are interpreted as {e unsigned} + 64-bit integers. + + @since 4.08.0 *) + val equal: t -> t -> bool (** The equal function for int64s. @since 4.03.0 *) diff --git a/stdlib/lazy.ml b/stdlib/lazy.ml index 7dc1e9dd..317f925c 100644 --- a/stdlib/lazy.ml +++ b/stdlib/lazy.ml @@ -47,7 +47,7 @@ rules for the [lazy] keyword. *) -type 'a t = 'a lazy_t +type 'a t = 'a CamlinternalLazy.t exception Undefined = CamlinternalLazy.Undefined diff --git a/stdlib/lazy.mli b/stdlib/lazy.mli index ee10366e..93b890e2 100644 --- a/stdlib/lazy.mli +++ b/stdlib/lazy.mli @@ -15,13 +15,28 @@ (** Deferred computations. *) -type 'a t = 'a lazy_t +type 'a t = 'a CamlinternalLazy.t (** A value of type ['a Lazy.t] is a deferred computation, called a suspension, that has a result of type ['a]. The special expression syntax [lazy (expr)] makes a suspension of the computation of [expr], without computing [expr] itself yet. "Forcing" the suspension will then compute [expr] and return its - result. + result. Matching a suspension with the special pattern syntax + [lazy(pattern)] also computes the underlying expression and + tries to bind it to [pattern]: + + {[ + let lazy_option_map f x = + match x with + | lazy (Some x) -> Some (Lazy.force f x) + | _ -> None + ]} + + Note: If lazy patterns appear in multiple cases in a pattern-matching, + lazy expressions may be forced even outside of the case ultimately selected + by the pattern matching. In the example above, the suspension [x] is always + computed. + Note: [lazy_t] is the built-in type constructor used by the compiler for the [lazy] keyword. You should not use it directly. Always use diff --git a/stdlib/lexing.ml b/stdlib/lexing.ml index 2c2633d4..ccca743c 100644 --- a/stdlib/lexing.ml +++ b/stdlib/lexing.ml @@ -63,7 +63,7 @@ external c_new_engine : lex_tables -> int -> lexbuf -> int let engine tbl state buf = let result = c_engine tbl state buf in - if result >= 0 then begin + if result >= 0 && buf.lex_curr_p != dummy_pos then begin buf.lex_start_p <- buf.lex_curr_p; buf.lex_curr_p <- {buf.lex_curr_p with pos_cnum = buf.lex_abs_pos + buf.lex_curr_pos}; @@ -73,7 +73,7 @@ let engine tbl state buf = let new_engine tbl state buf = let result = c_new_engine tbl state buf in - if result >= 0 then begin + if result >= 0 && buf.lex_curr_p != dummy_pos then begin buf.lex_start_p <- buf.lex_curr_p; buf.lex_curr_p <- {buf.lex_curr_p with pos_cnum = buf.lex_abs_pos + buf.lex_curr_pos}; @@ -145,7 +145,7 @@ let zero_pos = { pos_cnum = 0; } -let from_function f = +let from_function ?(with_positions = true) f = { refill_buff = lex_refill f (Bytes.create 512); lex_buffer = Bytes.create 1024; lex_buffer_len = 0; @@ -156,14 +156,14 @@ let from_function f = lex_last_action = 0; lex_mem = [||]; lex_eof_reached = false; - lex_start_p = zero_pos; - lex_curr_p = zero_pos; + lex_start_p = if with_positions then zero_pos else dummy_pos; + lex_curr_p = if with_positions then zero_pos else dummy_pos; } -let from_channel ic = - from_function (fun buf n -> input ic buf 0 n) +let from_channel ?with_positions ic = + from_function ?with_positions (fun buf n -> input ic buf 0 n) -let from_string s = +let from_string ?(with_positions = true) s = { refill_buff = (fun lexbuf -> lexbuf.lex_eof_reached <- true); lex_buffer = Bytes.of_string s; (* have to make a copy for compatibility with unsafe-string mode *) @@ -175,10 +175,12 @@ let from_string s = lex_last_action = 0; lex_mem = [||]; lex_eof_reached = true; - lex_start_p = zero_pos; - lex_curr_p = zero_pos; + lex_start_p = if with_positions then zero_pos else dummy_pos; + lex_curr_p = if with_positions then zero_pos else dummy_pos; } +let with_positions lexbuf = lexbuf.lex_curr_p != dummy_pos + let lexeme lexbuf = let len = lexbuf.lex_curr_pos - lexbuf.lex_start_pos in Bytes.sub_string lexbuf.lex_buffer lexbuf.lex_start_pos len @@ -215,10 +217,12 @@ let lexeme_end_p lexbuf = lexbuf.lex_curr_p let new_line lexbuf = let lcp = lexbuf.lex_curr_p in - lexbuf.lex_curr_p <- { lcp with - pos_lnum = lcp.pos_lnum + 1; - pos_bol = lcp.pos_cnum; - } + if lcp != dummy_pos then + lexbuf.lex_curr_p <- + { lcp with + pos_lnum = lcp.pos_lnum + 1; + pos_bol = lcp.pos_cnum; + } @@ -227,5 +231,7 @@ let new_line lexbuf = let flush_input lb = lb.lex_curr_pos <- 0; lb.lex_abs_pos <- 0; - lb.lex_curr_p <- {lb.lex_curr_p with pos_cnum = 0}; + let lcp = lb.lex_curr_p in + if lcp != dummy_pos then + lb.lex_curr_p <- {zero_pos with pos_fname = lcp.pos_fname}; lb.lex_buffer_len <- 0; diff --git a/stdlib/lexing.mli b/stdlib/lexing.mli index 397d20cb..0a511535 100644 --- a/stdlib/lexing.mli +++ b/stdlib/lexing.mli @@ -65,28 +65,42 @@ type lexbuf = The lexer buffer holds the current state of the scanner, plus a function to refill the buffer from the input. - At each token, the lexing engine will copy [lex_curr_p] to - [lex_start_p], then change the [pos_cnum] field - of [lex_curr_p] by updating it with the number of characters read - since the start of the [lexbuf]. The other fields are left - unchanged by the lexing engine. In order to keep them + Lexers can optionally maintain the [lex_curr_p] and [lex_start_p] + position fields. This "position tracking" mode is the default, and + it corresponds to passing [~with_position:true] to functions that + create lexer buffers. In this mode, the lexing engine and lexer + actions are co-responsible for properly updating the position + fields, as described in the next paragraph. When the mode is + explicitly disabled (with [~with_position:false]), the lexing + engine will not touch the position fields and the lexer actions + should be careful not to do it either; the [lex_curr_p] and + [lex_start_p] field will then always hold the [dummy_pos] invalid + position. Not tracking positions avoids allocations and memory + writes and can significantly improve the performance of the lexer + in contexts where [lex_start_p] and [lex_curr_p] are not needed. + + Position tracking mode works as follows. At each token, the lexing + engine will copy [lex_curr_p] to [lex_start_p], then change the + [pos_cnum] field of [lex_curr_p] by updating it with the number of + characters read since the start of the [lexbuf]. The other fields + are left unchanged by the lexing engine. In order to keep them accurate, they must be initialised before the first use of the - lexbuf, and updated by the relevant lexer actions (i.e. at each - end of line -- see also [new_line]). - *) + lexbuf, and updated by the relevant lexer actions (i.e. at each end + of line -- see also [new_line]). +*) -val from_channel : in_channel -> lexbuf +val from_channel : ?with_positions:bool -> in_channel -> lexbuf (** Create a lexer buffer on the given input channel. [Lexing.from_channel inchan] returns a lexer buffer which reads from the input channel [inchan], at the current reading position. *) -val from_string : string -> lexbuf +val from_string : ?with_positions:bool -> string -> lexbuf (** Create a lexer buffer which reads from the given string. Reading starts from the first character in the string. An end-of-input condition is generated when the end of the string is reached. *) -val from_function : (bytes -> int -> int) -> lexbuf +val from_function : ?with_positions:bool -> (bytes -> int -> int) -> lexbuf (** Create a lexer buffer with the given function as its reading method. When the scanner needs more characters, it will call the given function, giving it a byte sequence [s] and a byte @@ -94,6 +108,17 @@ val from_function : (bytes -> int -> int) -> lexbuf starting at index 0, and return the number of bytes provided. A return value of 0 means end of input. *) +val with_positions : lexbuf -> bool +(** Tell whether the lexer buffer keeps track of position fields + [lex_curr_p] / [lex_start_p], as determined by the corresponding + optional argument for functions that create lexer buffers + (whose default value is [true]). + + When [with_positions] is [false], lexer actions should not + modify position fields. Doing it nevertheless could + re-enable the [with_position] mode and degrade performances. +*) + (** {1 Functions for lexer semantic actions} *) @@ -127,16 +152,19 @@ val lexeme_end : lexbuf -> int val lexeme_start_p : lexbuf -> position (** Like [lexeme_start], but return a complete [position] instead - of an offset. *) + of an offset. When position tracking is disabled, the function + returns [dummy_pos]. *) val lexeme_end_p : lexbuf -> position (** Like [lexeme_end], but return a complete [position] instead - of an offset. *) + of an offset. When position tracking is disabled, the function + returns [dummy_pos]. *) val new_line : lexbuf -> unit (** Update the [lex_curr_p] field of the lexbuf to reflect the start of a new line. You can call this function in the semantic action - of the rule that matches the end-of-line character. + of the rule that matches the end-of-line character. The function + does nothing when position tracking is disabled. @since 3.11.0 *) diff --git a/stdlib/list.ml b/stdlib/list.ml index 7cee6094..3980ddd6 100644 --- a/stdlib/list.ml +++ b/stdlib/list.ml @@ -13,6 +13,9 @@ (* *) (**************************************************************************) +(* An alias for the type of lists. *) +type 'a t = 'a list = [] | (::) of 'a * 'a list + (* List operations *) let rec length_aux len = function @@ -69,7 +72,8 @@ let rec init_aux i n f = let rev_init_threshold = match Sys.backend_type with | Sys.Native | Sys.Bytecode -> 10_000 - (* We don't known the size of the stack, better be safe and assume it's small. *) + (* We don't know the size of the stack, better be safe and assume it's + small. *) | Sys.Other _ -> 50 let init len f = @@ -232,6 +236,16 @@ let find_all p = let filter = find_all +let filter_map f = + let rec aux accu = function + | [] -> rev accu + | x :: l -> + match f x with + | None -> aux accu l + | Some v -> aux (v :: accu) l + in + aux [] + let partition p l = let rec part yes no = function | [] -> (rev yes, rev no) @@ -490,7 +504,7 @@ let rec compare_length_with l n = compare_length_with l (n-1) ;; -(** {6 Iterators} *) +(** {1 Iterators} *) let to_seq l = let rec aux l () = match l with diff --git a/stdlib/list.mli b/stdlib/list.mli index e7a339b5..ad58b7d6 100644 --- a/stdlib/list.mli +++ b/stdlib/list.mli @@ -26,6 +26,9 @@ longer than about 10000 elements. *) +type 'a t = 'a list = [] | (::) of 'a * 'a list +(** An alias for the type of lists. *) + val length : 'a list -> int (** Return the length (number of elements) of the given list. *) @@ -74,7 +77,7 @@ val rev : 'a list -> 'a list (** List reversal. *) val init : int -> (int -> 'a) -> 'a list -(** [List.init len f] is [f 0; f 1; ...; f (len-1)], evaluated left to right. +(** [List.init len f] is [[f 0; f 1; ...; f (len-1)]], evaluated left to right. @raise Invalid_argument if len < 0. @since 4.06.0 @@ -131,6 +134,13 @@ val rev_map : ('a -> 'b) -> 'a list -> 'b list {!List.rev}[ (]{!List.map}[ f l)], but is tail-recursive and more efficient. *) +val filter_map : ('a -> 'b option) -> 'a list -> 'b list +(** [filter_map f l] applies [f] to every element of [l], filters + out the [None] elements and returns the list of the arguments of + the [Some] elements. + @since 4.08.0 +*) + val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a (** [List.fold_left f a [b1; ...; bn]] is [f (... (f (f a b1) b2) ...) bn]. *) @@ -309,7 +319,7 @@ val sort : ('a -> 'a -> int) -> 'a list -> 'a list compare as equal, a positive integer if the first is greater, and a negative integer if the first is smaller (see Array.sort for a complete specification). For example, - {!Pervasives.compare} is a suitable comparison function. + {!Stdlib.compare} is a suitable comparison function. The resulting list is sorted in increasing order. [List.sort] is guaranteed to run in constant heap space (in addition to the size of the result list) and logarithmic @@ -346,7 +356,7 @@ val merge : ('a -> 'a -> int) -> 'a list -> 'a list -> 'a list Not tail-recursive (sum of the lengths of the arguments). *) -(** {6 Iterators} *) +(** {1 Iterators} *) val to_seq : 'a list -> 'a Seq.t (** Iterate on the list diff --git a/stdlib/listLabels.mli b/stdlib/listLabels.mli index ab6980c2..7ea911b6 100644 --- a/stdlib/listLabels.mli +++ b/stdlib/listLabels.mli @@ -13,6 +13,9 @@ (* *) (**************************************************************************) +type 'a t = 'a list = [] | (::) of 'a * 'a list +(** An alias for the type of lists. *) + (** List operations. Some functions are flagged as not tail-recursive. A tail-recursive @@ -133,6 +136,13 @@ val rev_map : f:('a -> 'b) -> 'a list -> 'b list {!List.rev}[ (]{!List.map}[ f l)], but is tail-recursive and more efficient. *) +val filter_map : f:('a -> 'b option) -> 'a list -> 'b list +(** [filter_map f l] applies [f] to every element of [l], filters + out the [None] elements and returns the list of the arguments of + the [Some] elements. + @since 4.08.0 +*) + val fold_left : f:('a -> 'b -> 'a) -> init:'a -> 'b list -> 'a (** [List.fold_left f a [b1; ...; bn]] is [f (... (f (f a b1) b2) ...) bn]. *) @@ -315,7 +325,7 @@ val sort : cmp:('a -> 'a -> int) -> 'a list -> 'a list compare as equal, a positive integer if the first is greater, and a negative integer if the first is smaller (see Array.sort for a complete specification). For example, - {!Pervasives.compare} is a suitable comparison function. + {!Stdlib.compare} is a suitable comparison function. The resulting list is sorted in increasing order. [List.sort] is guaranteed to run in constant heap space (in addition to the size of the result list) and logarithmic @@ -352,7 +362,7 @@ val merge : cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list Not tail-recursive (sum of the lengths of the arguments). *) -(** {6 Iterators} *) +(** {1 Iterators} *) val to_seq : 'a list -> 'a Seq.t (** Iterate on the list diff --git a/stdlib/map.ml b/stdlib/map.ml index 28bb5bd0..0883ba10 100644 --- a/stdlib/map.ml +++ b/stdlib/map.ml @@ -351,7 +351,8 @@ module Make(Ord: OrderedType) = struct match (l, r) with (Empty, _) -> add_min_binding v d r | (_, Empty) -> add_max_binding v d l - | (Node{l=ll; v=lv; d=ld; r=lr; h=lh}, Node{l=rl; v=rv; d=rd; r=rr; h=rh}) -> + | (Node{l=ll; v=lv; d=ld; r=lr; h=lh}, + Node{l=rl; v=rv; d=rd; r=rr; h=rh}) -> if lh > rh + 2 then bal ll lv ld (join lr v d r) else if rh > lh + 2 then bal (join l v d rl) rv rd rr else create l v d r @@ -399,7 +400,8 @@ module Make(Ord: OrderedType) = struct let rec union f s1 s2 = match (s1, s2) with | (Empty, s) | (s, Empty) -> s - | (Node {l=l1; v=v1; d=d1; r=r1; h=h1}, Node {l=l2; v=v2; d=d2; r=r2; h=h2}) -> + | (Node {l=l1; v=v1; d=d1; r=r1; h=h1}, + Node {l=l2; v=v2; d=d2; r=r2; h=h2}) -> if h1 >= h2 then let (l2, d2, r2) = split v1 s2 in let l = union f l1 l2 and r = union f r1 r2 in diff --git a/stdlib/map.mli b/stdlib/map.mli index 531fb8fe..2dc955ab 100644 --- a/stdlib/map.mli +++ b/stdlib/map.mli @@ -28,8 +28,8 @@ struct type t = int * int let compare (x0,y0) (x1,y1) = - match Pervasives.compare x0 x1 with - 0 -> Pervasives.compare y0 y1 + match Stdlib.compare x0 x1 with + 0 -> Stdlib.compare y0 y1 | c -> c end @@ -55,7 +55,7 @@ module type OrderedType = [f e1 e2] is strictly negative if [e1] is smaller than [e2], and [f e1 e2] is strictly positive if [e1] is greater than [e2]. Example: a suitable ordering function is the generic structural - comparison function {!Pervasives.compare}. *) + comparison function {!Stdlib.compare}. *) end (** Input signature of the functor {!Map.Make}. *) @@ -129,10 +129,10 @@ module type S = arguments, the function [f] is used to combine them. This is a special case of [merge]: [union f m1 m2] is equivalent to [merge f' m1 m2], where - - [f' None None = None] - - [f' (Some v) None = Some v] - - [f' None (Some v) = Some v] - - [f' (Some v1) (Some v2) = f v1 v2] + - [f' _key None None = None] + - [f' _key (Some v) None = Some v] + - [f' _key None (Some v) = Some v] + - [f' key (Some v1) (Some v2) = f key v1 v2] @since 4.03.0 *) @@ -194,35 +194,35 @@ module type S = val bindings: 'a t -> (key * 'a) list (** Return the list of all bindings of the given map. - The returned list is sorted in increasing order with respect + The returned list is sorted in increasing order of keys with respect to the ordering [Ord.compare], where [Ord] is the argument given to {!Map.Make}. @since 3.12.0 *) val min_binding: 'a t -> (key * 'a) - (** Return the smallest binding of the given map + (** Return the binding with the smallest key in a given map (with respect to the [Ord.compare] ordering), or raise [Not_found] if the map is empty. @since 3.12.0 *) val min_binding_opt: 'a t -> (key * 'a) option - (** Return the smallest binding of the given map + (** Return the binding with the smallest key in the given map (with respect to the [Ord.compare] ordering), or [None] if the map is empty. @since 4.05 *) val max_binding: 'a t -> (key * 'a) - (** Same as {!Map.S.min_binding}, but returns the largest binding - of the given map. + (** Same as {!Map.S.min_binding}, but returns the binding with + the largest key in the given map. @since 3.12.0 *) val max_binding_opt: 'a t -> (key * 'a) option - (** Same as {!Map.S.min_binding_opt}, but returns the largest binding - of the given map. + (** Same as {!Map.S.min_binding_opt}, but returns the binding with + the largest key in the given map. @since 4.05 *) @@ -306,15 +306,15 @@ module type S = (** Same as {!Map.S.map}, but the function receives as arguments both the key and the associated value for each binding of the map. *) - (** {6 Iterators} *) + (** {1 Iterators} *) val to_seq : 'a t -> (key * 'a) Seq.t - (** Iterate on the whole map, in ascending order + (** Iterate on the whole map, in ascending order of keys @since 4.07 *) val to_seq_from : key -> 'a t -> (key * 'a) Seq.t (** [to_seq_from k m] iterates on a subset of the bindings of [m], - in ascending order, from key [k] or above. + in ascending order of keys, from key [k] or above. @since 4.07 *) val add_seq : (key * 'a) Seq.t -> 'a t -> 'a t diff --git a/stdlib/marshal.ml b/stdlib/marshal.ml index 63133d7f..d9f158a4 100644 --- a/stdlib/marshal.ml +++ b/stdlib/marshal.ml @@ -17,7 +17,7 @@ type extern_flags = No_sharing | Closures | Compat_32 -(* note: this type definition is used in 'byterun/debugger.c' *) +(* note: this type definition is used in 'runtime/debugger.c' *) external to_channel: out_channel -> 'a -> extern_flags list -> unit = "caml_output_value" diff --git a/stdlib/moreLabels.mli b/stdlib/moreLabels.mli index 7a57d5eb..08bc0f4d 100644 --- a/stdlib/moreLabels.mli +++ b/stdlib/moreLabels.mli @@ -194,6 +194,7 @@ module Set : sig val remove : elt -> t -> t val union : t -> t -> t val inter : t -> t -> t + val disjoint : t -> t -> bool val diff : t -> t -> t val compare : t -> t -> int val equal : t -> t -> bool diff --git a/stdlib/nativeint.ml b/stdlib/nativeint.ml index 2f6fe780..5d8b4e61 100644 --- a/stdlib/nativeint.ml +++ b/stdlib/nativeint.ml @@ -49,6 +49,14 @@ let min_int = shift_left 1n (size - 1) let max_int = sub min_int 1n let lognot n = logxor n (-1n) +let unsigned_to_int = + let max_int = of_int Stdlib.max_int in + fun n -> + if compare zero n <= 0 && compare n max_int <= 0 then + Some (to_int n) + else + None + external format : string -> nativeint -> string = "caml_nativeint_format" let to_string n = format "%d" n @@ -61,5 +69,22 @@ let of_string_opt s = type t = nativeint -let compare (x: t) (y: t) = Pervasives.compare x y +let compare (x: t) (y: t) = Stdlib.compare x y let equal (x: t) (y: t) = compare x y = 0 + +let unsigned_compare n m = + compare (sub n min_int) (sub m min_int) + +(* Unsigned division from signed division of the same + bitness. See Warren Jr., Henry S. (2013). Hacker's Delight (2 ed.), Sec 9-3. +*) +let unsigned_div n d = + if d < zero then + if unsigned_compare n d < 0 then zero else one + else + let q = shift_left (div (shift_right_logical n 1) d) 1 in + let r = sub n (mul q d) in + if unsigned_compare r d >= 0 then succ q else q + +let unsigned_rem n d = + sub n (mul (unsigned_div n d) d) diff --git a/stdlib/nativeint.mli b/stdlib/nativeint.mli index a047ced5..c338142a 100644 --- a/stdlib/nativeint.mli +++ b/stdlib/nativeint.mli @@ -28,6 +28,13 @@ [nativeint] are generally slower than those on [int]. Use [nativeint] only when the application requires the extra bit of precision over the [int] type. + + Literals for native integers are suffixed by n: + {[ + let zero: nativeint = 0n + let one: nativeint = 1n + let m_one: nativeint = -1n + ]} *) val zero : nativeint @@ -54,7 +61,13 @@ external mul : nativeint -> nativeint -> nativeint = "%nativeint_mul" external div : nativeint -> nativeint -> nativeint = "%nativeint_div" (** Integer division. Raise [Division_by_zero] if the second argument is zero. This division rounds the real quotient of - its arguments towards zero, as specified for {!Pervasives.(/)}. *) + its arguments towards zero, as specified for {!Stdlib.(/)}. *) + +val unsigned_div : nativeint -> nativeint -> nativeint +(** Same as {!div}, except that arguments and result are interpreted as {e + unsigned} native integers. + + @since 4.08.0 *) external rem : nativeint -> nativeint -> nativeint = "%nativeint_mod" (** Integer remainder. If [y] is not zero, the result @@ -64,6 +77,12 @@ external rem : nativeint -> nativeint -> nativeint = "%nativeint_mod" (Nativeint.rem x y)]. If [y = 0], [Nativeint.rem x y] raises [Division_by_zero]. *) +val unsigned_rem : nativeint -> nativeint -> nativeint +(** Same as {!rem}, except that arguments and result are interpreted as {e + unsigned} native integers. + + @since 4.08.0 *) + val succ : nativeint -> nativeint (** Successor. [Nativeint.succ x] is [Nativeint.add x Nativeint.one]. *) @@ -131,6 +150,13 @@ external to_int : nativeint -> int = "%nativeint_to_int" integer (type [int]). The high-order bit is lost during the conversion. *) +val unsigned_to_int : nativeint -> int option +(** Same as {!to_int}, but interprets the argument as an {e unsigned} integer. + Returns [None] if the unsigned value of the argument cannot fit into an + [int]. + + @since 4.08.0 *) + external of_float : float -> nativeint = "caml_nativeint_of_float" "caml_nativeint_of_float_unboxed" [@@unboxed] [@@noalloc] @@ -158,7 +184,7 @@ external to_int32 : nativeint -> int32 = "%nativeint_to_int32" external of_string : string -> nativeint = "caml_nativeint_of_string" (** Convert the given string to a native integer. - The string is read in decimal (by default, or if the string + The string is read in decimal (by default, or if the string begins with [0u]) or in hexadecimal, octal or binary if the string begins with [0x], [0o] or [0b] respectively. @@ -183,10 +209,16 @@ type t = nativeint val compare: t -> t -> int (** The comparison function for native integers, with the same specification as - {!Pervasives.compare}. Along with the type [t], this function [compare] + {!Stdlib.compare}. Along with the type [t], this function [compare] allows the module [Nativeint] to be passed as argument to the functors {!Set.Make} and {!Map.Make}. *) +val unsigned_compare: t -> t -> int +(** Same as {!compare}, except that arguments are interpreted as {e unsigned} + native integers. + + @since 4.08.0 *) + val equal: t -> t -> bool (** The equal function for native ints. @since 4.03.0 *) diff --git a/stdlib/obj.ml b/stdlib/obj.ml index 6c5f4f9e..b2269a95 100644 --- a/stdlib/obj.ml +++ b/stdlib/obj.ml @@ -67,42 +67,88 @@ let int_tag = 1000 let out_of_heap_tag = 1001 let unaligned_tag = 1002 -let extension_constructor x = - let x = repr x in - let slot = - if (is_block x) && (tag x) <> object_tag && (size x) >= 1 then field x 0 - else x - in - let name = - if (is_block slot) && (tag slot) = object_tag then field slot 0 - else invalid_arg "Obj.extension_constructor" - in - if (tag name) = string_tag then (obj slot : extension_constructor) - else invalid_arg "Obj.extension_constructor" - -let [@inline always] extension_name (slot : extension_constructor) = - (obj (field (repr slot) 0) : string) - -let [@inline always] extension_id (slot : extension_constructor) = - (obj (field (repr slot) 1) : int) +module Extension_constructor = +struct + type t = extension_constructor + let of_val x = + let x = repr x in + let slot = + if (is_block x) && (tag x) <> object_tag && (size x) >= 1 then field x 0 + else x + in + let name = + if (is_block slot) && (tag slot) = object_tag then field slot 0 + else invalid_arg "Obj.extension_constructor" + in + if (tag name) = string_tag then (obj slot : t) + else invalid_arg "Obj.extension_constructor" + + let [@inline always] name (slot : t) = + (obj (field (repr slot) 0) : string) + + let [@inline always] id (slot : t) = + (obj (field (repr slot) 1) : int) +end + +let extension_constructor = Extension_constructor.of_val +let extension_name = Extension_constructor.name +let extension_id = Extension_constructor.id module Ephemeron = struct type obj_t = t type t (** ephemeron *) - external create: int -> t = "caml_ephe_create" + (** To change in sync with weak.h *) + let additional_values = 2 + let max_ephe_length = Sys.max_array_length - additional_values + + external create : int -> t = "caml_ephe_create";; + let create l = + if not (0 <= l && l <= max_ephe_length) then + invalid_arg "Obj.Ephemeron.create"; + create l - let length x = size(repr x) - 2 + let length x = size(repr x) - additional_values + + let raise_if_invalid_offset e o msg = + if not (0 <= o && o < length e) then + invalid_arg msg external get_key: t -> int -> obj_t option = "caml_ephe_get_key" + let get_key e o = + raise_if_invalid_offset e o "Obj.Ephemeron.get_key"; + get_key e o + external get_key_copy: t -> int -> obj_t option = "caml_ephe_get_key_copy" + let get_key_copy e o = + raise_if_invalid_offset e o "Obj.Ephemeron.get_key_copy"; + get_key_copy e o + external set_key: t -> int -> obj_t -> unit = "caml_ephe_set_key" + let set_key e o x = + raise_if_invalid_offset e o "Obj.Ephemeron.set_key"; + set_key e o x + external unset_key: t -> int -> unit = "caml_ephe_unset_key" + let unset_key e o = + raise_if_invalid_offset e o "Obj.Ephemeron.unset_key"; + unset_key e o + external check_key: t -> int -> bool = "caml_ephe_check_key" + let check_key e o = + raise_if_invalid_offset e o "Obj.Ephemeron.check_key"; + check_key e o + external blit_key : t -> int -> t -> int -> int -> unit = "caml_ephe_blit_key" + let blit_key e1 o1 e2 o2 l = + if l < 0 || o1 < 0 || o1 > length e1 - l + || o2 < 0 || o2 > length e2 - l + then invalid_arg "Obj.Ephemeron.blit_key" + else if l <> 0 then blit_key e1 o1 e2 o2 l + external get_data: t -> obj_t option = "caml_ephe_get_data" external get_data_copy: t -> obj_t option = "caml_ephe_get_data_copy" external set_data: t -> obj_t -> unit = "caml_ephe_set_data" @@ -110,5 +156,4 @@ module Ephemeron = struct external check_data: t -> bool = "caml_ephe_check_data" external blit_data : t -> t -> unit = "caml_ephe_blit_data" - end diff --git a/stdlib/obj.mli b/stdlib/obj.mli index e76c7df9..bac04d56 100644 --- a/stdlib/obj.mli +++ b/stdlib/obj.mli @@ -86,9 +86,19 @@ val int_tag : int val out_of_heap_tag : int val unaligned_tag : int (* should never happen @since 3.11.0 *) +module Extension_constructor : +sig + type t = extension_constructor + val of_val : 'a -> t + val [@inline always] name : t -> string + val [@inline always] id : t -> int +end val extension_constructor : 'a -> extension_constructor + [@@ocaml.deprecated "use Obj.Extension_constructor.of_val"] val [@inline always] extension_name : extension_constructor -> string + [@@ocaml.deprecated "use Obj.Extension_constructor.name"] val [@inline always] extension_id : extension_constructor -> int + [@@ocaml.deprecated "use Obj.Extension_constructor.id"] (** The following two functions are deprecated. Use module {!Marshal} instead. *) @@ -109,7 +119,10 @@ module Ephemeron: sig val create: int -> t (** [create n] returns an ephemeron with [n] keys. - All the keys and the data are initially empty *) + All the keys and the data are initially empty. + The argument [n] must be between zero + and {!max_ephe_length} (limits included). + *) val length: t -> int (** return the number of keys *) @@ -149,4 +162,8 @@ module Ephemeron: sig val blit_data : t -> t -> unit (** Same as {!Ephemeron.K1.blit_data} *) + + val max_ephe_length: int + (** Maximum length of an ephemeron, ie the maximum number of keys an + ephemeron could contain *) end diff --git a/stdlib/ocaml_operators.mld b/stdlib/ocaml_operators.mld new file mode 100644 index 00000000..de7f30ef --- /dev/null +++ b/stdlib/ocaml_operators.mld @@ -0,0 +1,100 @@ +Precedence level and associativity of operators + +The following table lists the precedence level of all operator classes +from the highest to the lowest precedence. A few other syntactic constructions +are also listed as references. + +{%latex: +% +% Note: the tables below should be kept in sync with the one in +% manual/manual/refman/expr.etex . +% +\begin{tabular}{cc} +\hline +Operator class & Associativity \\ +\hline +$!\ldots$ $\tilde{}\ldots$ & -- \\ +$.\cdots()$ $.\cdots[]$ $.\cdots\\{\\}$ & -- \\ +\#\ldots & left \\ +function application & left \\ +- -. & -- \\ +$**\ldots$ lsl lsr asr & right \\ +$*\ldots$ /\ldots \%\ldots mod land lor lxor & left \\ ++\ldots -\ldots & left \\ +:: & right \\ +@\ldots \textasciicircum\ldots & right \\ +=\ldots <\ldots >\ldots |\ldots \&\ldots \$\ldots != & left \\ +\& \&\& & right \\ +or || & right \\ +, & -- \\ +<- := & right \\ +if & -- \\ +; & right \\ +\hline +\end{tabular} +%} + +{%html: + + + + + + + + + + + + + + + + + + + +
    Operator classAssociativity
    !… ~…
    .…() .…[] .…{} +
    #… left
    function application left
    - -.
    **… lsl lsr asr right
    *… /… %… mod land lor lxor + left
    +… -… left
    :: right
    @… ^… right
    =… <… +>… |… &… $… != left
    & && right
    or || right
    ,
    <- := right
    if
    ; right
    +%} + +{%man: +.IP Associativity +Operator class +.IP - +!.. ~.. +.IP - +\&.() .[] .{} +.IP left +#.. +.IP left +function application +.IP - +- -. +.IP right +**.. lsl lsr asr +.IP left +*.. /.. %.. mod land lor lxor +.IP left ++.. -.. +.IP right +:: +.IP right +@.. ^.. +.IP left +=.. <.. >.. |.. &.. $.. != +.IP right +& && +.IP right +or || +.IP - +, +.IP right +<- := +.IP - +if +.IP right +; +%} diff --git a/stdlib/option.ml b/stdlib/option.ml new file mode 100644 index 00000000..97fa0b4e --- /dev/null +++ b/stdlib/option.ml @@ -0,0 +1,43 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* The OCaml programmers *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +type 'a t = 'a option = None | Some of 'a + +let none = None +let some v = Some v +let value o ~default = match o with Some v -> v | None -> default +let get = function Some v -> v | None -> invalid_arg "option is None" +let bind o f = match o with None -> None | Some v -> f v +let join = function Some (Some _ as o) -> o | _ -> None +let map f o = match o with None -> None | Some v -> Some (f v) +let fold ~none ~some = function Some v -> some v | None -> none +let iter f = function Some v -> f v | None -> () +let is_none = function None -> true | Some _ -> false +let is_some = function None -> false | Some _ -> true + +let equal eq o0 o1 = match o0, o1 with +| Some v0, Some v1 -> eq v0 v1 +| None, None -> true +| _ -> false + +let compare cmp o0 o1 = match o0, o1 with +| Some v0, Some v1 -> cmp v0 v1 +| None, None -> 0 +| None, Some _ -> -1 +| Some _, None -> 1 + +let to_result ~none = function None -> Error none | Some v -> Ok v +let to_list = function None -> [] | Some v -> [v] +let to_seq = function None -> Seq.empty | Some v -> Seq.return v diff --git a/stdlib/option.mli b/stdlib/option.mli new file mode 100644 index 00000000..7659dbc2 --- /dev/null +++ b/stdlib/option.mli @@ -0,0 +1,83 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* The OCaml programmers *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** Option values. + + Option values explicitly indicate the presence or absence of a value. + + @since 4.08 *) + +(** {1:options Options} *) + +type 'a t = 'a option = None | Some of 'a +(** The type for option values. Either [None] or a value [Some v]. *) + +val none : 'a option +(** [none] is [None]. *) + +val some : 'a -> 'a option +(** [some v] is [Some v]. *) + +val value : 'a option -> default:'a -> 'a +(** [value o ~default] is [v] if [o] is [Some v] and [default] otherwise. *) + +val get : 'a option -> 'a +(** [get o] is [v] if [o] is [Some v] and @raise Invalid_argument otherwise. *) + +val bind : 'a option -> ('a -> 'b option) -> 'b option +(** [bind o f] is [Some (f v)] if [o] is [Some v] and [None] if [o] is + [None]. *) + +val join : 'a option option -> 'a option +(** [join oo] is [Some v] if [oo] is [Some (Some v)] and [None] otherwise. *) + +val map : ('a -> 'b) -> 'a option -> 'b option +(** [map f o] is [None] if [o] is [None] and [Some (f v)] is [o] is [Some v]. *) + +val fold : none:'a -> some:('b -> 'a) -> 'b option -> 'a +(** [fold ~none ~some o] is [none] if [o] is [None] and [some v] if [o] is + [Some v]. *) + +val iter : ('a -> unit) -> 'a option -> unit +(** [iter f o] is [f v] if [o] is [Some v] and [()] otherwise. *) + +(** {1:preds Predicates and comparisons} *) + +val is_none : 'a option -> bool +(** [is_none o] is [true] iff [o] is [None]. *) + +val is_some : 'a option -> bool +(** [is_some o] is [true] iff [o] is [Some o]. *) + +val equal : ('a -> 'a -> bool) -> 'a option -> 'a option -> bool +(** [equal eq o0 o1] is [true] iff [o0] and [o1] are both [None] or if + they are [Some v0] and [Some v1] and [eq v0 v1] is [true]. *) + +val compare : ('a -> 'a -> int) -> 'a option -> 'a option -> int +(** [compare cmp o0 o1] is a total order on options using [cmp] to compare + values wrapped by [Some _]. [None] is smaller than [Some _] values. *) + +(** {1:convert Converting} *) + +val to_result : none:'e -> 'a option -> ('a, 'e) result +(** [to_result ~none o] is [Ok v] if [o] is [Some v] and [Error none] + otherwise. *) + +val to_list : 'a option -> 'a list +(** [to_list o] is [[]] if [o] is [None] and [[v]] if [o] is [Some v]. *) + +val to_seq : 'a option -> 'a Seq.t +(** [to_seq o] is [o] as a sequence. [None] is the empty sequence and + [Some v] is the singleton sequence containing [v]. *) diff --git a/stdlib/pervasives.ml b/stdlib/pervasives.ml new file mode 100644 index 00000000..e9b2e5cd --- /dev/null +++ b/stdlib/pervasives.ml @@ -0,0 +1,244 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jeremie Dimino, Jane Street Europe *) +(* *) +(* Copyright 2017 Jane Street Group LLC *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** @deprecated Use {!Stdlib} *) + +external raise : exn -> 'a = "%raise" +external raise_notrace : exn -> 'a = "%raise_notrace" +let invalid_arg = invalid_arg +let failwith = failwith +exception Exit +external ( = ) : 'a -> 'a -> bool = "%equal" +external ( <> ) : 'a -> 'a -> bool = "%notequal" +external ( < ) : 'a -> 'a -> bool = "%lessthan" +external ( > ) : 'a -> 'a -> bool = "%greaterthan" +external ( <= ) : 'a -> 'a -> bool = "%lessequal" +external ( >= ) : 'a -> 'a -> bool = "%greaterequal" +external compare : 'a -> 'a -> int = "%compare" +let min = min +let max = max +external ( == ) : 'a -> 'a -> bool = "%eq" +external ( != ) : 'a -> 'a -> bool = "%noteq" +external not : bool -> bool = "%boolnot" +external ( && ) : bool -> bool -> bool = "%sequand" +external ( & ) : bool -> bool -> bool = "%sequand" + [@@ocaml.deprecated "Use (&&) instead."] +external ( || ) : bool -> bool -> bool = "%sequor" +external ( or ) : bool -> bool -> bool = "%sequor" + [@@ocaml.deprecated "Use (||) instead."] +external __LOC__ : string = "%loc_LOC" +external __FILE__ : string = "%loc_FILE" +external __LINE__ : int = "%loc_LINE" +external __MODULE__ : string = "%loc_MODULE" +external __POS__ : string * int * int * int = "%loc_POS" +external __LOC_OF__ : 'a -> string * 'a = "%loc_LOC" +external __LINE_OF__ : 'a -> int * 'a = "%loc_LINE" +external __POS_OF__ : 'a -> (string * int * int * int) * 'a = "%loc_POS" +external ( |> ) : 'a -> ('a -> 'b) -> 'b = "%revapply" +external ( @@ ) : ('a -> 'b) -> 'a -> 'b = "%apply" +external ( ~- ) : int -> int = "%negint" +external ( ~+ ) : int -> int = "%identity" +external succ : int -> int = "%succint" +external pred : int -> int = "%predint" +external ( + ) : int -> int -> int = "%addint" +external ( - ) : int -> int -> int = "%subint" +external ( * ) : int -> int -> int = "%mulint" +external ( / ) : int -> int -> int = "%divint" +external ( mod ) : int -> int -> int = "%modint" +let abs = abs +let max_int = max_int +let min_int = min_int +external ( land ) : int -> int -> int = "%andint" +external ( lor ) : int -> int -> int = "%orint" +external ( lxor ) : int -> int -> int = "%xorint" +let lnot = lnot +external ( lsl ) : int -> int -> int = "%lslint" +external ( lsr ) : int -> int -> int = "%lsrint" +external ( asr ) : int -> int -> int = "%asrint" +external ( ~-. ) : float -> float = "%negfloat" +external ( ~+. ) : float -> float = "%identity" +external ( +. ) : float -> float -> float = "%addfloat" +external ( -. ) : float -> float -> float = "%subfloat" +external ( *. ) : float -> float -> float = "%mulfloat" +external ( /. ) : float -> float -> float = "%divfloat" +external ( ** ) : float -> float -> float = "caml_power_float" "pow" + [@@unboxed] [@@noalloc] +external sqrt : float -> float = "caml_sqrt_float" "sqrt" + [@@unboxed] [@@noalloc] +external exp : float -> float = "caml_exp_float" "exp" [@@unboxed] [@@noalloc] +external log : float -> float = "caml_log_float" "log" [@@unboxed] [@@noalloc] +external log10 : float -> float = "caml_log10_float" "log10" + [@@unboxed] [@@noalloc] +external expm1 : float -> float = "caml_expm1_float" "caml_expm1" + [@@unboxed] [@@noalloc] +external log1p : float -> float = "caml_log1p_float" "caml_log1p" + [@@unboxed] [@@noalloc] +external cos : float -> float = "caml_cos_float" "cos" [@@unboxed] [@@noalloc] +external sin : float -> float = "caml_sin_float" "sin" [@@unboxed] [@@noalloc] +external tan : float -> float = "caml_tan_float" "tan" [@@unboxed] [@@noalloc] +external acos : float -> float = "caml_acos_float" "acos" + [@@unboxed] [@@noalloc] +external asin : float -> float = "caml_asin_float" "asin" + [@@unboxed] [@@noalloc] +external atan : float -> float = "caml_atan_float" "atan" + [@@unboxed] [@@noalloc] +external atan2 : float -> float -> float = "caml_atan2_float" "atan2" + [@@unboxed] [@@noalloc] +external hypot : float -> float -> float = "caml_hypot_float" "caml_hypot" + [@@unboxed] [@@noalloc] +external cosh : float -> float = "caml_cosh_float" "cosh" + [@@unboxed] [@@noalloc] +external sinh : float -> float = "caml_sinh_float" "sinh" + [@@unboxed] [@@noalloc] +external tanh : float -> float = "caml_tanh_float" "tanh" + [@@unboxed] [@@noalloc] +external ceil : float -> float = "caml_ceil_float" "ceil" + [@@unboxed] [@@noalloc] +external floor : float -> float = "caml_floor_float" "floor" + [@@unboxed] [@@noalloc] +external abs_float : float -> float = "%absfloat" +external copysign : float -> float -> float + = "caml_copysign_float" "caml_copysign" + [@@unboxed] [@@noalloc] +external mod_float : float -> float -> float = "caml_fmod_float" "fmod" + [@@unboxed] [@@noalloc] +external frexp : float -> float * int = "caml_frexp_float" +external ldexp : (float [@unboxed]) -> (int [@untagged]) -> (float [@unboxed]) = + "caml_ldexp_float" "caml_ldexp_float_unboxed" [@@noalloc] +external modf : float -> float * float = "caml_modf_float" +external float : int -> float = "%floatofint" +external float_of_int : int -> float = "%floatofint" +external truncate : float -> int = "%intoffloat" +external int_of_float : float -> int = "%intoffloat" +let infinity = infinity +let neg_infinity = neg_infinity +let nan = nan +let max_float = max_float +let min_float = min_float +let epsilon_float = epsilon_float +type nonrec fpclass = fpclass = + FP_normal + | FP_subnormal + | FP_zero + | FP_infinite + | FP_nan +external classify_float : (float [@unboxed]) -> fpclass = + "caml_classify_float" "caml_classify_float_unboxed" [@@noalloc] +let ( ^ ) = ( ^ ) +external int_of_char : char -> int = "%identity" +let char_of_int = char_of_int +external ignore : 'a -> unit = "%ignore" +let string_of_bool = string_of_bool +let bool_of_string = bool_of_string +let bool_of_string_opt = bool_of_string_opt +let string_of_int = string_of_int +external int_of_string : string -> int = "caml_int_of_string" +let int_of_string_opt = int_of_string_opt +let string_of_float = string_of_float +external float_of_string : string -> float = "caml_float_of_string" +let float_of_string_opt = float_of_string_opt +external fst : 'a * 'b -> 'a = "%field0" +external snd : 'a * 'b -> 'b = "%field1" +let ( @ ) = ( @ ) +type nonrec in_channel = in_channel +type nonrec out_channel = out_channel +let stdin = stdin +let stdout = stdout +let stderr = stderr +let print_char = print_char +let print_string = print_string +let print_bytes = print_bytes +let print_int = print_int +let print_float = print_float +let print_endline = print_endline +let print_newline = print_newline +let prerr_char = prerr_char +let prerr_string = prerr_string +let prerr_bytes = prerr_bytes +let prerr_int = prerr_int +let prerr_float = prerr_float +let prerr_endline = prerr_endline +let prerr_newline = prerr_newline +let read_line = read_line +let read_int = read_int +let read_int_opt = read_int_opt +let read_float = read_float +let read_float_opt = read_float_opt +type nonrec open_flag = open_flag = + Open_rdonly + | Open_wronly + | Open_append + | Open_creat + | Open_trunc + | Open_excl + | Open_binary + | Open_text + | Open_nonblock +let open_out = open_out +let open_out_bin = open_out_bin +let open_out_gen = open_out_gen +let flush = flush +let flush_all = flush_all +let output_char = output_char +let output_string = output_string +let output_bytes = output_bytes +let output = output +let output_substring = output_substring +let output_byte = output_byte +let output_binary_int = output_binary_int +let output_value = output_value +let seek_out = seek_out +let pos_out = pos_out +let out_channel_length = out_channel_length +let close_out = close_out +let close_out_noerr = close_out_noerr +let set_binary_mode_out = set_binary_mode_out +let open_in = open_in +let open_in_bin = open_in_bin +let open_in_gen = open_in_gen +let input_char = input_char +let input_line = input_line +let input = input +let really_input = really_input +let really_input_string = really_input_string +let input_byte = input_byte +let input_binary_int = input_binary_int +let input_value = input_value +let seek_in = seek_in +let pos_in = pos_in +let in_channel_length = in_channel_length +let close_in = close_in +let close_in_noerr = close_in_noerr +let set_binary_mode_in = set_binary_mode_in +module LargeFile = LargeFile +type nonrec 'a ref = 'a ref = { mutable contents : 'a } +external ref : 'a -> 'a ref = "%makemutable" +external ( ! ) : 'a ref -> 'a = "%field0" +external ( := ) : 'a ref -> 'a -> unit = "%setfield0" +external incr : int ref -> unit = "%incr" +external decr : int ref -> unit = "%decr" +type nonrec ('a,'b) result = ('a,'b) result = Ok of 'a | Error of 'b +type ('a, 'b, 'c, 'd, 'e, 'f) format6 = + ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.format6 +type ('a, 'b, 'c, 'd) format4 = ('a, 'b, 'c, 'c, 'c, 'd) format6 +type ('a, 'b, 'c) format = ('a, 'b, 'c, 'c) format4 +let string_of_format = string_of_format +external format_of_string : + ('a, 'b, 'c, 'd, 'e, 'f) format6 -> + ('a, 'b, 'c, 'd, 'e, 'f) format6 = "%identity" +let ( ^^ ) = ( ^^ ) +let exit = exit +let at_exit = at_exit +let valid_float_lexem = valid_float_lexem +let do_at_exit = do_at_exit diff --git a/stdlib/printexc.ml b/stdlib/printexc.ml index 90214d9f..28f4fe06 100644 --- a/stdlib/printexc.ml +++ b/stdlib/printexc.ml @@ -15,6 +15,8 @@ open Printf +type t = exn = .. + let printers = ref [] let locfmt = format_of_string "File \"%s\", line %d, characters %d-%d: %s" @@ -280,12 +282,12 @@ let handle_uncaught_exception' exn debugger_in_use = (* Get the backtrace now, in case one of the [at_exit] function destroys it. *) let raw_backtrace = - if debugger_in_use (* Same test as in [byterun/printexc.c] *) then + if debugger_in_use (* Same test as in [runtime/printexc.c] *) then empty_backtrace else try_get_raw_backtrace () in - (try Pervasives.do_at_exit () with _ -> ()); + (try Stdlib.do_at_exit () with _ -> ()); match !uncaught_exception_handler with | None -> eprintf "Fatal error: exception %s\n" (to_string exn); @@ -308,7 +310,7 @@ let handle_uncaught_exception' exn debugger_in_use = "Fatal error: out of memory in uncaught exception handler" (* This function is called by [caml_fatal_uncaught_exception] in - [byterun/printexc.c] which expects no exception is raised. *) + [runtime/printexc.c] which expects no exception is raised. *) let handle_uncaught_exception exn debugger_in_use = try handle_uncaught_exception' exn debugger_in_use diff --git a/stdlib/printexc.mli b/stdlib/printexc.mli index 873e385f..da22a523 100644 --- a/stdlib/printexc.mli +++ b/stdlib/printexc.mli @@ -15,6 +15,9 @@ (** Facilities for printing exceptions and inspecting current call stack. *) +type t = exn = .. +(** The type of exception values. *) + val to_string: exn -> string (** [Printexc.to_string e] returns a string representation of the exception [e]. *) @@ -159,7 +162,7 @@ val set_uncaught_exception_handler: (exn -> raw_backtrace -> unit) -> unit backtrace on standard error output. Note that when [fn] is called all the functions registered with - {!Pervasives.at_exit} have already been called. Because of this you must + {!Stdlib.at_exit} have already been called. Because of this you must make sure any output channel [fn] writes on is flushed. Also note that exceptions raised by user code in the interactive toplevel diff --git a/stdlib/printf.ml b/stdlib/printf.ml index 136cbe56..814e82d1 100644 --- a/stdlib/printf.ml +++ b/stdlib/printf.ml @@ -17,9 +17,9 @@ open CamlinternalFormatBasics open CamlinternalFormat let kfprintf k o (Format (fmt, _)) = - make_printf (fun o acc -> output_acc o acc; k o) o End_of_acc fmt + make_printf (fun acc -> output_acc o acc; k o) End_of_acc fmt let kbprintf k b (Format (fmt, _)) = - make_printf (fun b acc -> bufput_acc b acc; k b) b End_of_acc fmt + make_printf (fun acc -> bufput_acc b acc; k b) End_of_acc fmt let ikfprintf k oc (Format (fmt, _)) = make_iprintf k oc fmt @@ -30,11 +30,11 @@ let printf fmt = fprintf stdout fmt let eprintf fmt = fprintf stderr fmt let ksprintf k (Format (fmt, _)) = - let k' () acc = + let k' acc = let buf = Buffer.create 64 in strput_acc buf acc; k (Buffer.contents buf) in - make_printf k' () End_of_acc fmt + make_printf k' End_of_acc fmt let sprintf fmt = ksprintf (fun s -> s) fmt diff --git a/stdlib/printf.mli b/stdlib/printf.mli index 39f7d4f3..a80aa045 100644 --- a/stdlib/printf.mli +++ b/stdlib/printf.mli @@ -100,9 +100,9 @@ val fprintf : out_channel -> ('a, out_channel, unit) format -> 'a sign if positive. - space: for signed numerical conversions, prefix number with a space if positive. - - [#]: request an alternate formatting style for the hexadecimal - and octal integer types ([x], [X], [o], [lx], [lX], [lo], [Lx], - [LX], [Lo]). + - [#]: request an alternate formatting style for the integer types + ([x], [X], [o], [lx], [lX], [lo], [Lx], [LX], [Lo], [d], [i], [u], + [ld], [li], [lu], [Ld], [Li], [Lu], [nd], [ni], [nu]). The optional [width] is an integer indicating the minimal width of the result. For instance, [%6d] prints an integer, diff --git a/stdlib/queue.ml b/stdlib/queue.ml index 72c134b3..f8d8b251 100644 --- a/stdlib/queue.ml +++ b/stdlib/queue.ml @@ -60,6 +60,11 @@ let peek q = | Nil -> raise Empty | Cons { content } -> content +let peek_opt q = + match q.first with + | Nil -> None + | Cons { content } -> Some content + let top = peek @@ -74,6 +79,17 @@ let take q = q.first <- next; content +let take_opt q = + match q.first with + | Nil -> None + | Cons { content; next = Nil } -> + clear q; + Some content + | Cons { content; next } -> + q.length <- q.length - 1; + q.first <- next; + Some content + let pop = take @@ -131,7 +147,7 @@ let transfer q1 q2 = q2.last <- q1.last; clear q1 -(** {6 Iterators} *) +(** {1 Iterators} *) let to_seq q = let rec aux c () = match c with @@ -146,4 +162,3 @@ let of_seq g = let q = create() in add_seq q g; q - diff --git a/stdlib/queue.mli b/stdlib/queue.mli index afff9209..12c99f3f 100644 --- a/stdlib/queue.mli +++ b/stdlib/queue.mli @@ -43,6 +43,11 @@ val take : 'a t -> 'a (** [take q] removes and returns the first element in queue [q], or raises {!Empty} if the queue is empty. *) +val take_opt : 'a t -> 'a option +(** [take_opt q] removes and returns the first element in queue [q], + or returns [None] if the queue is empty. + @since 4.08 *) + val pop : 'a t -> 'a (** [pop] is a synonym for [take]. *) @@ -50,6 +55,11 @@ val peek : 'a t -> 'a (** [peek q] returns the first element in queue [q], without removing it from the queue, or raises {!Empty} if the queue is empty. *) +val peek_opt : 'a t -> 'a option +(** [peek_opt q] returns the first element in queue [q], without removing + it from the queue, or returns [None] if the queue is empty. + @since 4.08 *) + val top : 'a t -> 'a (** [top] is a synonym for [peek]. *) @@ -81,7 +91,7 @@ val transfer : 'a t -> 'a t -> unit sequence [iter (fun x -> add x q2) q1; clear q1], but runs in constant time. *) -(** {6 Iterators} *) +(** {1 Iterators} *) val to_seq : 'a t -> 'a Seq.t (** Iterate on the queue, in front-to-back order. @@ -94,6 +104,5 @@ val add_seq : 'a t -> 'a Seq.t -> unit @since 4.07 *) val of_seq : 'a Seq.t -> 'a t -(** Create an array from the generator +(** Create a queue from the generator @since 4.07 *) - diff --git a/stdlib/random.ml b/stdlib/random.ml index 76e9fa17..a88a5f87 100644 --- a/stdlib/random.ml +++ b/stdlib/random.ml @@ -38,7 +38,7 @@ module State = struct let full_init s seed = - let combine accu x = Digest.string (accu ^ string_of_int x) in + let combine accu x = Digest.string (accu ^ Int.to_string x) in let extract d = Char.code d.[0] + (Char.code d.[1] lsl 8) + (Char.code d.[2] lsl 16) + (Char.code d.[3] lsl 24) @@ -134,8 +134,8 @@ module State = struct (* Returns a float 0 <= x <= 1 with at most 60 bits of precision. *) let rawfloat s = let scale = 1073741824.0 (* 2^30 *) - and r1 = Pervasives.float (bits s) - and r2 = Pervasives.float (bits s) + and r1 = Stdlib.float (bits s) + and r2 = Stdlib.float (bits s) in (r1 /. scale +. r2) /. scale @@ -223,7 +223,7 @@ init 299792643; init_diff2 100; chisquare diff2 100000 100 (* Return the sum of the squares of v[i0,i1[ *) let rec sumsq v i0 i1 = if i0 >= i1 then 0.0 - else if i1 = i0 + 1 then Pervasives.float v.(i0) *. Pervasives.float v.(i0) + else if i1 = i0 + 1 then Stdlib.float v.(i0) *. Stdlib.float v.(i0) else sumsq v i0 ((i0+i1)/2) +. sumsq v ((i0+i1)/2) i1 @@ -235,8 +235,8 @@ let chisquare g n r = f.(t) <- f.(t) + 1 done; let t = sumsq f 0 r - and r = Pervasives.float r - and n = Pervasives.float n in + and r = Stdlib.float r + and n = Stdlib.float n in let sr = 2.0 *. sqrt r in (r -. sr, (r *. t /. n) -. n, r +. sr) diff --git a/stdlib/result.ml b/stdlib/result.ml new file mode 100644 index 00000000..6d172702 --- /dev/null +++ b/stdlib/result.ml @@ -0,0 +1,46 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* The OCaml programmers *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +type ('a, 'e) t = ('a, 'e) result = Ok of 'a | Error of 'e + +let ok v = Ok v +let error e = Error e +let value r ~default = match r with Ok v -> v | Error _ -> default +let get_ok = function Ok v -> v | Error _ -> invalid_arg "result is Error _" +let get_error = function Error e -> e | Ok _ -> invalid_arg "result is Ok _" +let bind r f = match r with Ok v -> f v | Error _ as e -> e +let join = function Ok r -> r | Error _ as e -> e +let map f = function Ok v -> Ok (f v) | Error _ as e -> e +let map_error f = function Error e -> Error (f e) | Ok _ as v -> v +let fold ~ok ~error = function Ok v -> ok v | Error e -> error e +let iter f = function Ok v -> f v | Error _ -> () +let iter_error f = function Error e -> f e | Ok _ -> () +let is_ok = function Ok _ -> true | Error _ -> false +let is_error = function Error _ -> true | Ok _ -> false + +let equal ~ok ~error r0 r1 = match r0, r1 with +| Ok v0, Ok v1 -> ok v0 v1 +| Error e0, Error e1 -> error e0 e1 +| _, _ -> false + +let compare ~ok ~error r0 r1 = match r0, r1 with +| Ok v0, Ok v1 -> ok v0 v1 +| Error e0, Error e1 -> error e0 e1 +| Ok _, Error _ -> -1 +| Error _, Ok _ -> 1 + +let to_option = function Ok v -> Some v | Error _ -> None +let to_list = function Ok v -> [v] | Error _ -> [] +let to_seq = function Ok v -> Seq.return v | Error _ -> Seq.empty diff --git a/stdlib/result.mli b/stdlib/result.mli new file mode 100644 index 00000000..c05d25c6 --- /dev/null +++ b/stdlib/result.mli @@ -0,0 +1,101 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* The OCaml programmers *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** Result values. + + Result values handle computation results and errors in an explicit + and declarative manner without resorting to exceptions. + + @since 4.08 *) + +(** {1:results Results} *) + +type ('a, 'e) t = ('a, 'e) result = Ok of 'a | Error of 'e +(** The type for result values. Either a value [Ok v] or an error [Error e]. *) + +val ok : 'a -> ('a, 'e) result +(** [ok v] is [Ok v]. *) + +val error : 'e -> ('a, 'e) result +(** [error e] is [Error e]. *) + +val value : ('a, 'e) result -> default:'a -> 'a +(** [value r ~default] is [v] if [r] is [Ok v] and [default] otherwise. *) + +val get_ok : ('a, 'e) result -> 'a +(** [get_ok r] is [v] if [r] is [Ok v] and @raise Invalid_argument + otherwise. *) + +val get_error : ('a, 'e) result -> 'e +(** [get_error r] is [e] if [r] is [Error e] and @raise Invalid_argument + otherwise. *) + +val bind : ('a, 'e) result -> ('a -> ('b, 'e) result) -> ('b, 'e) result +(** [bind r f] is [f v] if [r] is [Ok v] and [r] if [r] is [Error _]. *) + +val join : (('a, 'e) result, 'e) result -> ('a, 'e) result +(** [join rr] is [r] if [rr] is [Ok r] and [rr] if [rr] is [Error _]. *) + +val map : ('a -> 'b) -> ('a, 'e) result -> ('b, 'e) result +(** [map f r] is [Ok (f v)] if [r] is [Ok v] and [r] if [r] is [Error _]. *) + +val map_error : ('e -> 'f) -> ('a, 'e) result -> ('a, 'f) result +(** [map_error f r] is [Error (f e)] if [r] is [Error e] and [r] if + [r] is [Ok _]. *) + +val fold : ok:('a -> 'c) -> error:('e -> 'c) -> ('a, 'e) result -> 'c +(** [fold ~ok ~error r] is [ok v] if [r] is [Ok v] and [error e] if [r] + is [Error e]. *) + +val iter : ('a -> unit) -> ('a, 'e) result -> unit +(** [iter f r] is [f v] if [r] is [Ok v] and [()] otherwise. *) + +val iter_error : ('e -> unit) -> ('a, 'e) result -> unit +(** [iter_error f r] is [f e] if [r] is [Error e] and [()] otherwise. *) + +(** {1:preds Predicates and comparisons} *) + +val is_ok : ('a, 'e) result -> bool +(** [is_ok r] is [true] iff [r] is [Ok _]. *) + +val is_error : ('a, 'e) result -> bool +(** [is_error r] is [true] iff [r] is [Error _]. *) + +val equal : + ok:('a -> 'a -> bool) -> error:('e -> 'e -> bool) -> ('a, 'e) result -> + ('a, 'e) result -> bool +(** [equal ~ok ~error r0 r1] tests equality of [r0] and [r1] using [ok] + and [error] to respectively compare values wrapped by [Ok _] and + [Error _]. *) + +val compare : + ok:('a -> 'a -> int) -> error:('e -> 'e -> int) -> ('a, 'e) result -> + ('a, 'e) result -> int +(** [compare ~ok ~error r0 r1] totally orders [r0] and [r1] using [ok] and + [error] to respectively compare values wrapped by [Ok _ ] and [Error _]. + [Ok _] values are smaller than [Error _] values. *) + +(** {1:convert Converting} *) + +val to_option : ('a, 'e) result -> 'a option +(** [to_option r] is [r] as an option, mapping [Ok v] to [Some v] and + [Error _] to [None]. *) + +val to_list : ('a, 'e) result -> 'a list +(** [to_list r] is [[v]] if [r] is [Ok v] and [[]] otherwise. *) + +val to_seq : ('a, 'e) result -> 'a Seq.t +(** [to_seq r] is [r] as a sequence. [Ok v] is the singleton sequence + containing [v] and [Error _] is the empty sequence. *) diff --git a/stdlib/scanf.ml b/stdlib/scanf.ml index 7f12d9a4..b4d62a81 100644 --- a/stdlib/scanf.ml +++ b/stdlib/scanf.ml @@ -17,14 +17,14 @@ open CamlinternalFormatBasics open CamlinternalFormat (* alias to avoid warning for ambiguity between - Pervasives.format6 + Stdlib.format6 and CamlinternalFormatBasics.format6 (the former is in fact an alias for the latter, but the ambiguity warning doesn't care) *) type ('a, 'b, 'c, 'd, 'e, 'f) format6 = - ('a, 'b, 'c, 'd, 'e, 'f) Pervasives.format6 + ('a, 'b, 'c, 'd, 'e, 'f) Stdlib.format6 (* The run-time library for scanners. *) @@ -39,12 +39,12 @@ module type SCANNING = sig type file_name = string val stdin : in_channel - (* The scanning buffer reading from [Pervasives.stdin]. - [stdib] is equivalent to [Scanning.from_channel Pervasives.stdin]. *) + (* The scanning buffer reading from [Stdlib.stdin]. + [stdib] is equivalent to [Scanning.from_channel Stdlib.stdin]. *) val stdib : in_channel (* An alias for [Scanf.stdin], the scanning buffer reading from - [Pervasives.stdin]. *) + [Stdlib.stdin]. *) val next_char : scanbuf -> char (* [Scanning.next_char ib] advance the scanning buffer for @@ -126,11 +126,11 @@ module type SCANNING = sig val from_file_bin : file_name -> in_channel val from_string : string -> in_channel val from_function : (unit -> char) -> in_channel - val from_channel : Pervasives.in_channel -> in_channel + val from_channel : Stdlib.in_channel -> in_channel val close_in : in_channel -> unit - val memo_from_channel : Pervasives.in_channel -> in_channel + val memo_from_channel : Stdlib.in_channel -> in_channel (* Obsolete. *) end @@ -143,8 +143,8 @@ module Scanning : SCANNING = struct type file_name = string type in_channel_name = - | From_channel of Pervasives.in_channel - | From_file of file_name * Pervasives.in_channel + | From_channel of Stdlib.in_channel + | From_file of file_name * Stdlib.in_channel | From_function | From_string @@ -213,7 +213,7 @@ module Scanning : SCANNING = struct let name_of_input ib = match ib.ic_input_name with - | From_channel _ic -> "unnamed Pervasives input channel" + | From_channel _ic -> "unnamed Stdlib input channel" | From_file (fname, _ic) -> fname | From_function -> "unnamed function" | From_string -> "unnamed character string" @@ -325,7 +325,7 @@ module Scanning : SCANNING = struct let file_buffer_size = ref 1024 (* The scanner closes the input channel at end of input. *) - let scan_close_at_end ic = Pervasives.close_in ic; raise End_of_file + let scan_close_at_end ic = Stdlib.close_in ic; raise End_of_file (* The scanner does not close the input channel at end of input: it just raises [End_of_file]. *) @@ -352,13 +352,13 @@ module Scanning : SCANNING = struct let from_ic_close_at_end = from_ic scan_close_at_end let from_ic_raise_at_end = from_ic scan_raise_at_end - (* The scanning buffer reading from [Pervasives.stdin]. + (* The scanning buffer reading from [Stdlib.stdin]. One could try to define [stdib] as a scanning buffer reading a character at a time (no bufferization at all), but unfortunately the top-level interaction would be wrong. This is due to some kind of - 'race condition' when reading from [Pervasives.stdin], + 'race condition' when reading from [Stdlib.stdin], since the interactive compiler and [Scanf.scanf] will simultaneously - read the material they need from [Pervasives.stdin]; then, confusion + read the material they need from [Stdlib.stdin]; then, confusion will result from what should be read by the top-level and what should be read by [Scanf.scanf]. This is even more complicated by the one character lookahead that @@ -369,7 +369,7 @@ module Scanning : SCANNING = struct characters have been read, we simply ask to read more. *) let stdin = from_ic scan_raise_at_end - (From_file ("-", Pervasives.stdin)) Pervasives.stdin + (From_file ("-", Stdlib.stdin)) Stdlib.stdin let stdib = stdin @@ -382,8 +382,8 @@ module Scanning : SCANNING = struct from_ic_close_at_end (From_file (fname, ic)) ic - let open_in = open_in_file Pervasives.open_in - let open_in_bin = open_in_file Pervasives.open_in_bin + let open_in = open_in_file Stdlib.open_in + let open_in_bin = open_in_file Stdlib.open_in_bin let from_file = open_in let from_file_bin = open_in_bin @@ -395,14 +395,14 @@ module Scanning : SCANNING = struct let close_in ib = match ib.ic_input_name with | From_channel ic -> - Pervasives.close_in ic - | From_file (_fname, ic) -> Pervasives.close_in ic + Stdlib.close_in ic + | From_file (_fname, ic) -> Stdlib.close_in ic | From_function | From_string -> () (* Obsolete: a memo [from_channel] version to build a [Scanning.in_channel] - scanning buffer out of a [Pervasives.in_channel]. + scanning buffer out of a [Stdlib.in_channel]. This function was used to try to preserve the scanning semantics for the (now obsolete) function [fscanf]. Given that all scanner must read from a [Scanning.in_channel] scanning @@ -411,7 +411,7 @@ module Scanning : SCANNING = struct from the same scanning buffer. This obliged this library to allocated scanning buffers that were not properly garbage collectable, hence leading to memory leaks. - If you need to read from a [Pervasives.in_channel] input channel + If you need to read from a [Stdlib.in_channel] input channel [ic], simply define a [Scanning.in_channel] formatted input channel as in [let ib = Scanning.from_channel ic], then use [Scanf.bscanf ib] as usual. *) @@ -556,7 +556,7 @@ let integer_conversion_of_char = function (* Extract an integer literal token. - Since the functions Pervasives.*int*_of_string do not accept a leading +, + Since the functions Stdlib.*int*_of_string do not accept a leading +, we skip it if necessary. *) let token_int_literal conv ib = let tok = @@ -1547,21 +1547,8 @@ let sscanf_format : fun s format f -> bscanf_format (Scanning.from_string s) format f -let string_to_String s = - let l = String.length s in - let b = Buffer.create (l + 2) in - Buffer.add_char b '\"'; - for i = 0 to l - 1 do - let c = s.[i] in - if c = '\"' then Buffer.add_char b '\\'; - Buffer.add_char b c; - done; - Buffer.add_char b '\"'; - Buffer.contents b - - let format_from_string s fmt = - sscanf_format (string_to_String s) fmt (fun x -> x) + sscanf_format ("\"" ^ String.escaped s ^ "\"") fmt (fun x -> x) let unescaped s = diff --git a/stdlib/scanf.mli b/stdlib/scanf.mli index c3d2a6a8..5f48632e 100644 --- a/stdlib/scanf.mli +++ b/stdlib/scanf.mli @@ -88,7 +88,7 @@ module Scanning : sig type in_channel (** The notion of input channel for the {!Scanf} module: those channels provide all the machinery necessary to read from any source - of characters, including a {!Pervasives.in_channel} value. + of characters, including a {!Stdlib.in_channel} value. A Scanf.Scanning.in_channel value is also called a {i formatted input channel} or equivalently a {i scanning buffer}. The type {!Scanning.scanbuf} below is an alias for [Scanning.in_channel]. @@ -110,10 +110,10 @@ type scanbuf = in_channel val stdin : in_channel (** The standard input notion for the {!Scanf} module. [Scanning.stdin] is the {!Scanning.in_channel} formatted input channel - attached to {!Pervasives.stdin}. + attached to {!Stdlib.stdin}. Note: in the interactive system, when input is read from - {!Pervasives.stdin}, the newline character that triggers evaluation is + {!Stdlib.stdin}, the newline character that triggers evaluation is part of the input; thus, the scanning specifications must properly skip this additional newline character (for instance, simply add a ['\n'] as the last character of the format string). @@ -144,7 +144,7 @@ val open_in_bin : file_name -> in_channel *) val close_in : in_channel -> unit -(** Closes the {!Pervasives.in_channel} associated with the given +(** Closes the {!Stdlib.in_channel} associated with the given {!Scanning.in_channel} formatted input channel. @since 3.12.0 *) @@ -172,9 +172,9 @@ val from_function : (unit -> char) -> in_channel end-of-input condition by raising the exception [End_of_file]. *) -val from_channel : Pervasives.in_channel -> in_channel +val from_channel : Stdlib.in_channel -> in_channel (** [Scanning.from_channel ic] returns a {!Scanning.in_channel} formatted - input channel which reads from the regular {!Pervasives.in_channel} input + input channel which reads from the regular {!Stdlib.in_channel} input channel [ic] argument. Reading starts at current reading position of [ic]. *) @@ -198,7 +198,7 @@ val name_of_input : in_channel -> string val stdib : in_channel [@@ocaml.deprecated "Use Scanf.Scanning.stdin instead."] (** A deprecated alias for {!Scanning.stdin}, the scanning buffer reading from - {!Pervasives.stdin}. + {!Stdlib.stdin}. *) end @@ -218,7 +218,7 @@ type ('a, 'b, 'c, 'd) scanner = For instance, the {!Scanf.scanf} function below has type [('a, 'b, 'c, 'd) scanner], since it is a formatted input function that reads from {!Scanning.stdin}: [scanf fmt f] applies [f] to the arguments - specified by [fmt], reading those arguments from {!Pervasives.stdin} as + specified by [fmt], reading those arguments from {!Stdlib.stdin} as expected. If the format [fmt] has some [%r] indications, the corresponding @@ -471,7 +471,7 @@ val sscanf : string -> ('a, 'b, 'c, 'd) scanner val scanf : ('a, 'b, 'c, 'd) scanner (** Same as {!Scanf.bscanf}, but reads from the predefined formatted input - channel {!Scanf.Scanning.stdin} that is connected to {!Pervasives.stdin}. + channel {!Scanf.Scanning.stdin} that is connected to {!Stdlib.stdin}. *) val kscanf : @@ -531,13 +531,13 @@ val unescaped : string -> string in the argument. Raise {!Scan_failure} if [s] is not properly escaped (i.e. [s] has invalid escape sequences or special characters that are not properly escaped). - For instance, [String.unescaped "\""] will fail. + For instance, [Scanf.unescaped "\""] will fail. @since 4.00.0 *) (** {1 Deprecated} *) -val fscanf : Pervasives.in_channel -> ('a, 'b, 'c, 'd) scanner +val fscanf : Stdlib.in_channel -> ('a, 'b, 'c, 'd) scanner [@@ocaml.deprecated "Use Scanning.from_channel then Scanf.bscanf."] (** @deprecated [Scanf.fscanf] is error prone and deprecated since 4.03.0. @@ -546,14 +546,14 @@ val fscanf : Pervasives.in_channel -> ('a, 'b, 'c, 'd) scanner must read from a user defined {!Scanning.in_channel} formatted input channel. - If you need to read from a {!Pervasives.in_channel} input channel + If you need to read from a {!Stdlib.in_channel} input channel [ic], simply define a {!Scanning.in_channel} formatted input channel as in [let ib = Scanning.from_channel ic], then use [Scanf.bscanf ib] as usual. *) val kfscanf : - Pervasives.in_channel -> (Scanning.in_channel -> exn -> 'd) -> + Stdlib.in_channel -> (Scanning.in_channel -> exn -> 'd) -> ('a, 'b, 'c, 'd) scanner [@@ocaml.deprecated "Use Scanning.from_channel then Scanf.kscanf."] (** @deprecated [Scanf.kfscanf] is error prone and deprecated since 4.03.0. *) diff --git a/stdlib/seq.mli b/stdlib/seq.mli index f33c19ac..e1b04779 100644 --- a/stdlib/seq.mli +++ b/stdlib/seq.mli @@ -53,25 +53,30 @@ val map : ('a -> 'b) -> 'a t -> 'b t val filter : ('a -> bool) -> 'a t -> 'a t (** Remove from the sequence the elements that do not satisfy the given predicate. - This transformation is lazy, it only applies when the result is traversed. *) + This transformation is lazy, it only applies when the result is + traversed. *) val filter_map : ('a -> 'b option) -> 'a t -> 'b t (** Apply the function to every element; if [f x = None] then [x] is dropped; if [f x = Some y] then [y] is returned. - This transformation is lazy, it only applies when the result is traversed. *) + This transformation is lazy, it only applies when the result is + traversed. *) val flat_map : ('a -> 'b t) -> 'a t -> 'b t (** Map each element to a subsequence, then return each element of this sub-sequence in turn. - This transformation is lazy, it only applies when the result is traversed. *) + This transformation is lazy, it only applies when the result is + traversed. *) val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a (** Traverse the sequence from left to right, combining each element with the accumulator using the given function. - The traversal happens immediately and will not terminate on infinite sequences. + The traversal happens immediately and will not terminate on infinite + sequences. Also see {!List.fold_left} *) val iter : ('a -> unit) -> 'a t -> unit (** Iterate on the sequence, calling the (imperative) function on every element. - The traversal happens immediately and will not terminate on infinite sequences. *) + The traversal happens immediately and will not terminate on infinite + sequences. *) diff --git a/stdlib/set.ml b/stdlib/set.ml index 2793de0f..6c8fdce8 100644 --- a/stdlib/set.ml +++ b/stdlib/set.ml @@ -33,6 +33,7 @@ module type S = val remove: elt -> t -> t val union: t -> t -> t val inter: t -> t -> t + val disjoint: t -> t -> bool val diff: t -> t -> t val compare: t -> t -> int val equal: t -> t -> bool @@ -288,6 +289,38 @@ module Make(Ord: OrderedType) = | (l2, true, r2) -> join (inter l1 l2) v1 (inter r1 r2) + (* Same as split, but compute the left and right subtrees + only if the pivot element is not in the set. The right subtree + is computed on demand. *) + + type split_bis = + | Found + | NotFound of t * (unit -> t) + + let rec split_bis x = function + Empty -> + NotFound (Empty, (fun () -> Empty)) + | Node{l; v; r; _} -> + let c = Ord.compare x v in + if c = 0 then Found + else if c < 0 then + match split_bis x l with + | Found -> Found + | NotFound (ll, rl) -> NotFound (ll, (fun () -> join (rl ()) v r)) + else + match split_bis x r with + | Found -> Found + | NotFound (lr, rr) -> NotFound (join l v lr, rr) + + let rec disjoint s1 s2 = + match (s1, s2) with + (Empty, _) | (_, Empty) -> true + | (Node{l=l1; v=v1; r=r1}, t2) -> + if s1 == s2 then false + else match split_bis v1 t2 with + NotFound(l2, r2) -> disjoint l1 l2 && disjoint r1 (r2 ()) + | Found -> false + let rec diff s1 s2 = match (s1, s2) with (Empty, _) -> Empty diff --git a/stdlib/set.mli b/stdlib/set.mli index ba8343c9..dd712809 100644 --- a/stdlib/set.mli +++ b/stdlib/set.mli @@ -30,8 +30,8 @@ struct type t = int * int let compare (x0,y0) (x1,y1) = - match Pervasives.compare x0 x1 with - 0 -> Pervasives.compare y0 y1 + match Stdlib.compare x0 x1 with + 0 -> Stdlib.compare y0 y1 | c -> c end @@ -56,7 +56,7 @@ module type OrderedType = [f e1 e2] is strictly negative if [e1] is smaller than [e2], and [f e1 e2] is strictly positive if [e1] is greater than [e2]. Example: a suitable ordering function is the generic structural - comparison function {!Pervasives.compare}. *) + comparison function {!Stdlib.compare}. *) end (** Input signature of the functor {!Set.Make}. *) @@ -98,8 +98,13 @@ module type S = val inter: t -> t -> t (** Set intersection. *) + val disjoint: t -> t -> bool + (** Test if two sets are disjoint. + @since 4.08.0 *) + val diff: t -> t -> t - (** Set difference. *) + (** Set difference: [diff s1 s2] contains the elements of [s1] + that are not in [s2]. *) val compare: t -> t -> int (** Total ordering between sets. Can be used as the ordering function @@ -259,7 +264,7 @@ module type S = except perhaps for lists with many duplicated elements. @since 4.02.0 *) - (** {6 Iterators} *) + (** {1 Iterators} *) val to_seq_from : elt -> t -> elt Seq.t (** [to_seq_from x s] iterates on a subset of the elements of [s] diff --git a/stdlib/sort.ml b/stdlib/sort.ml deleted file mode 100644 index 3e3b12e0..00000000 --- a/stdlib/sort.ml +++ /dev/null @@ -1,99 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -(* Merging and sorting *) - -open Array - -let rec merge order l1 l2 = - match l1 with - [] -> l2 - | h1 :: t1 -> - match l2 with - [] -> l1 - | h2 :: t2 -> - if order h1 h2 - then h1 :: merge order t1 l2 - else h2 :: merge order l1 t2 - -let list order l = - let rec initlist = function - [] -> [] - | [e] -> [[e]] - | e1::e2::rest -> - (if order e1 e2 then [e1;e2] else [e2;e1]) :: initlist rest in - let rec merge2 = function - l1::l2::rest -> merge order l1 l2 :: merge2 rest - | x -> x in - let rec mergeall = function - [] -> [] - | [l] -> l - | llist -> mergeall (merge2 llist) in - mergeall(initlist l) - -let swap arr i j = - let tmp = unsafe_get arr i in - unsafe_set arr i (unsafe_get arr j); - unsafe_set arr j tmp - -(* There is a known performance bug in the code below. If you find - it, don't bother reporting it. You're not supposed to use this - module anyway. *) -let array cmp arr = - let rec qsort lo hi = - if hi - lo >= 6 then begin - let mid = (lo + hi) lsr 1 in - (* Select median value from among LO, MID, and HI. Rearrange - LO and HI so the three values are sorted. This lowers the - probability of picking a pathological pivot. It also - avoids extra comparisons on i and j in the two tight "while" - loops below. *) - if cmp (unsafe_get arr mid) (unsafe_get arr lo) then swap arr mid lo; - if cmp (unsafe_get arr hi) (unsafe_get arr mid) then begin - swap arr mid hi; - if cmp (unsafe_get arr mid) (unsafe_get arr lo) then swap arr mid lo - end; - let pivot = unsafe_get arr mid in - let i = ref (lo + 1) and j = ref (hi - 1) in - if not (cmp pivot (unsafe_get arr hi)) - || not (cmp (unsafe_get arr lo) pivot) - then raise (Invalid_argument "Sort.array"); - while !i < !j do - while not (cmp pivot (unsafe_get arr !i)) do incr i done; - while not (cmp (unsafe_get arr !j) pivot) do decr j done; - if !i < !j then swap arr !i !j; - incr i; decr j - done; - (* Recursion on smaller half, tail-call on larger half *) - if !j - lo <= hi - !i then begin - qsort lo !j; qsort !i hi - end else begin - qsort !i hi; qsort lo !j - end - end in - qsort 0 (Array.length arr - 1); - (* Finish sorting by insertion sort *) - for i = 1 to Array.length arr - 1 do - let val_i = (unsafe_get arr i) in - if not (cmp (unsafe_get arr (i - 1)) val_i) then begin - unsafe_set arr i (unsafe_get arr (i - 1)); - let j = ref (i - 1) in - while !j >= 1 && not (cmp (unsafe_get arr (!j - 1)) val_i) do - unsafe_set arr !j (unsafe_get arr (!j - 1)); - decr j - done; - unsafe_set arr !j val_i - end - done diff --git a/stdlib/sort.mli b/stdlib/sort.mli deleted file mode 100644 index 80ebad26..00000000 --- a/stdlib/sort.mli +++ /dev/null @@ -1,44 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -(** Sorting and merging lists. - - @deprecated This module is obsolete and exists only for backward - compatibility. - The sorting functions in {!Array} and {!List} should be used instead. - The new functions are faster and use less memory. -*) - -val list : ('a -> 'a -> bool) -> 'a list -> 'a list - [@@ocaml.deprecated "Use List.sort instead."] -(** Sort a list in increasing order according to an ordering predicate. - The predicate should return [true] if its first argument is - less than or equal to its second argument. *) - -val array : ('a -> 'a -> bool) -> 'a array -> unit - [@@ocaml.deprecated "Use Array.sort instead."] -(** Sort an array in increasing order according to an - ordering predicate. - The predicate should return [true] if its first argument is - less than or equal to its second argument. - The array is sorted in place. *) - -val merge : ('a -> 'a -> bool) -> 'a list -> 'a list -> 'a list - [@@ocaml.deprecated "Use List.merge instead."] -(** Merge two lists according to the given predicate. - Assuming the two argument lists are sorted according to the - predicate, [merge] returns a sorted list containing the elements - from the two lists. The behavior is undefined if the two - argument lists were not sorted. *) diff --git a/stdlib/stack.ml b/stdlib/stack.ml index 1b48c0e0..c46161f0 100644 --- a/stdlib/stack.ml +++ b/stdlib/stack.ml @@ -30,10 +30,20 @@ let pop s = | hd::tl -> s.c <- tl; s.len <- s.len - 1; hd | [] -> raise Empty +let pop_opt s = + match s.c with + | hd::tl -> s.c <- tl; s.len <- s.len - 1; Some hd + | [] -> None + let top s = match s.c with | hd::_ -> hd - | [] -> raise Empty + | [] -> raise Empty + +let top_opt s = + match s.c with + | hd::_ -> Some hd + | [] -> None let is_empty s = (s.c = []) @@ -43,7 +53,7 @@ let iter f s = List.iter f s.c let fold f acc s = List.fold_left f acc s.c -(** {6 Iterators} *) +(** {1 Iterators} *) let to_seq s = List.to_seq s.c @@ -53,4 +63,3 @@ let of_seq g = let s = create() in add_seq s g; s - diff --git a/stdlib/stack.mli b/stdlib/stack.mli index 9fa6ed07..26ea3cc6 100644 --- a/stdlib/stack.mli +++ b/stdlib/stack.mli @@ -35,10 +35,20 @@ val pop : 'a t -> 'a (** [pop s] removes and returns the topmost element in stack [s], or raises {!Empty} if the stack is empty. *) +val pop_opt : 'a t -> 'a option +(** [pop_opt s] removes and returns the topmost element in stack [s], + or returns [None] if the stack is empty. + @since 4.08 *) + val top : 'a t -> 'a (** [top s] returns the topmost element in stack [s], or raises {!Empty} if the stack is empty. *) +val top_opt : 'a t -> 'a option +(** [top_opt s] returns the topmost element in stack [s], + or [None] if the stack is empty. + @since 4.08 *) + val clear : 'a t -> unit (** Discard all elements from a stack. *) @@ -62,7 +72,7 @@ val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b and [xn] the bottom element. The stack is unchanged. @since 4.03 *) -(** {6 Iterators} *) +(** {1 Iterators} *) val to_seq : 'a t -> 'a Seq.t (** Iterate on the stack, top to bottom. @@ -76,4 +86,3 @@ val add_seq : 'a t -> 'a Seq.t -> unit val of_seq : 'a Seq.t -> 'a t (** Create a stack from the iterator @since 4.07 *) - diff --git a/stdlib/stdlib.ml b/stdlib/stdlib.ml index 05dfe9e8..5cef512c 100644 --- a/stdlib/stdlib.ml +++ b/stdlib/stdlib.ml @@ -13,20 +13,16 @@ (* *) (**************************************************************************) -module Pervasives = struct -(* type 'a option = None | Some of 'a *) - (* Exceptions *) external register_named_value : string -> 'a -> unit = "caml_register_named_value" let () = - (* for asmrun/fail.c *) + (* for runtime/fail_nat.c *) register_named_value "Pervasives.array_bound_error" (Invalid_argument "index out of bounds") - external raise : exn -> 'a = "%raise" external raise_notrace : exn -> 'a = "%raise_notrace" @@ -34,6 +30,18 @@ let failwith s = raise(Failure s) let invalid_arg s = raise(Invalid_argument s) exception Exit +exception Match_failure = Match_failure +exception Assert_failure = Assert_failure +exception Invalid_argument = Invalid_argument +exception Failure = Failure +exception Not_found = Not_found +exception Out_of_memory = Out_of_memory +exception Stack_overflow = Stack_overflow +exception Sys_error = Sys_error +exception End_of_file = End_of_file +exception Division_by_zero = Division_by_zero +exception Sys_blocked_io = Sys_blocked_io +exception Undefined_recursive_module = Undefined_recursive_module (* Composition operators *) @@ -541,7 +549,7 @@ let at_exit f = (* MPR#7253, MPR#7796: make sure "f" is executed only once *) let f_already_ran = ref false in exit_function := - (fun () -> + (fun () -> if not !f_already_ran then begin f_already_ran := true; f() end; g()) @@ -552,15 +560,13 @@ let exit retcode = sys_exit retcode let _ = register_named_value "Pervasives.do_at_exit" do_at_exit -end - -include Pervasives (*MODULE_ALIASES*) module Arg = Arg module Array = Array module ArrayLabels = ArrayLabels module Bigarray = Bigarray +module Bool = Bool module Buffer = Buffer module Bytes = Bytes module BytesLabels = BytesLabels @@ -572,9 +578,11 @@ module Ephemeron = Ephemeron module Filename = Filename module Float = Float module Format = Format +module Fun = Fun module Gc = Gc module Genlex = Genlex module Hashtbl = Hashtbl +module Int = Int module Int32 = Int32 module Int64 = Int64 module Lazy = Lazy @@ -587,15 +595,17 @@ module MoreLabels = MoreLabels module Nativeint = Nativeint module Obj = Obj module Oo = Oo +module Option = Option module Parsing = Parsing +module Pervasives = Pervasives module Printexc = Printexc module Printf = Printf module Queue = Queue module Random = Random +module Result = Result module Scanf = Scanf module Seq = Seq module Set = Set -module Sort = Sort module Spacetime = Spacetime module Stack = Stack module StdLabels = StdLabels @@ -604,4 +614,5 @@ module String = String module StringLabels = StringLabels module Sys = Sys module Uchar = Uchar +module Unit = Unit module Weak = Weak diff --git a/stdlib/stdlib.mli b/stdlib/stdlib.mli index 99eca4b8..7087901a 100644 --- a/stdlib/stdlib.mli +++ b/stdlib/stdlib.mli @@ -18,19 +18,13 @@ This module is automatically opened at the beginning of each compilation. All components of this module can therefore be referred by their short name, without prefixing them by [Stdlib]. -*) - -module Pervasives : sig -(** Pervasive operations. - - This module provides the basic operations over the built-in types - (numbers, booleans, byte sequences, strings, exceptions, references, - lists, arrays, input-output channels, ...). - This module is included in the toplevel [Stdlib] module. + It particular, it provides the basic operations over the built-in + types (numbers, booleans, byte sequences, strings, exceptions, + references, lists, arrays, input-output channels, ...) and the + {{!modules}standard library modules}. *) - (** {1 Exceptions} *) external raise : exn -> 'a = "%raise" @@ -51,6 +45,73 @@ exception Exit (** The [Exit] exception is not raised by any library function. It is provided for use in your programs. *) +exception Match_failure of (string * int * int) + [@ocaml.warn_on_literal_pattern] +(** Exception raised when none of the cases of a pattern-matching + apply. The arguments are the location of the match keyword in the + source code (file name, line number, column number). *) + +exception Assert_failure of (string * int * int) + [@ocaml.warn_on_literal_pattern] +(** Exception raised when an assertion fails. The arguments are the + location of the assert keyword in the source code (file name, line + number, column number). *) + +exception Invalid_argument of string + [@ocaml.warn_on_literal_pattern] +(** Exception raised by library functions to signal that the given + arguments do not make sense. The string gives some information to + the programmer. As a general rule, this exception should not be + caught, it denotes a programming error and the code should be + modified not to trigger it. *) + +exception Failure of string + [@ocaml.warn_on_literal_pattern] +(** Exception raised by library functions to signal that they are + undefined on the given arguments. The string is meant to give some + information to the programmer; you must not pattern match on the + string literal because it may change in future versions (use + Failure _ instead). *) + +exception Not_found +(** Exception raised by search functions when the desired object could + not be found. *) + +exception Out_of_memory +(** Exception raised by the garbage collector when there is + insufficient memory to complete the computation. *) + +exception Stack_overflow +(** Exception raised by the bytecode interpreter when the evaluation + stack reaches its maximal size. This often indicates infinite or + excessively deep recursion in the user's program. (Not fully + implemented by the native-code compiler.) *) + +exception Sys_error of string + [@ocaml.warn_on_literal_pattern] +(** Exception raised by the input/output functions to report an + operating system error. The string is meant to give some + information to the programmer; you must not pattern match on the + string literal because it may change in future versions (use + Sys_error _ instead). *) + +exception End_of_file +(** Exception raised by input functions to signal that the end of file + has been reached. *) + +exception Division_by_zero +(** Exception raised by integer division and remainder operations when + their second argument is zero. *) + +exception Sys_blocked_io +(** A special case of Sys_error raised when no I/O is possible on a + non-blocking I/O channel. *) + +exception Undefined_recursive_module of (string * int * int) + [@ocaml.warn_on_literal_pattern] +(** Exception raised when an ill-founded recursive module definition + is evaluated. The arguments are the location of the definition in + the source code (file name, line number, column number). *) (** {1 Comparisons} *) @@ -61,23 +122,27 @@ external ( = ) : 'a -> 'a -> bool = "%equal" even if the two mutable objects are not the same physical object. Equality between functional values raises [Invalid_argument]. Equality between cyclic data structures may not terminate. - Left-associative operator at precedence level 4/11. *) + Left-associative operator, see {!Ocaml_operators} for more information. *) external ( <> ) : 'a -> 'a -> bool = "%notequal" -(** Negation of {!Pervasives.( = )}. - Left-associative operator at precedence level 4/11. *) +(** Negation of {!Stdlib.( = )}. + Left-associative operator, see {!Ocaml_operators} for more information. +*) external ( < ) : 'a -> 'a -> bool = "%lessthan" -(** See {!Pervasives.( >= )}. - Left-associative operator at precedence level 4/11. *) +(** See {!Stdlib.( >= )}. + Left-associative operator, see {!Ocaml_operators} for more information. +*) external ( > ) : 'a -> 'a -> bool = "%greaterthan" -(** See {!Pervasives.( >= )}. - Left-associative operator at precedence level 4/11. *) +(** See {!Stdlib.( >= )}. + Left-associative operator, see {!Ocaml_operators} for more information. +*) external ( <= ) : 'a -> 'a -> bool = "%lessequal" -(** See {!Pervasives.( >= )}. - Left-associative operator at precedence level 4/11. *) +(** See {!Stdlib.( >= )}. + Left-associative operator, see {!Ocaml_operators} for more information. +*) external ( >= ) : 'a -> 'a -> bool = "%greaterequal" (** Structural ordering functions. These functions coincide with @@ -88,7 +153,8 @@ external ( >= ) : 'a -> 'a -> bool = "%greaterequal" of [( = )], mutable structures are compared by contents. Comparison between functional values raises [Invalid_argument]. Comparison between cyclic structures may not terminate. - Left-associative operator at precedence level 4/11. *) + Left-associative operator, see {!Ocaml_operators} for more information. +*) external compare : 'a -> 'a -> int = "%compare" (** [compare x y] returns [0] if [x] is equal to [y], @@ -96,7 +162,7 @@ external compare : 'a -> 'a -> int = "%compare" if [x] is greater than [y]. The ordering implemented by [compare] is compatible with the comparison predicates [=], [<] and [>] defined above, with one difference on the treatment of the float value - {!Pervasives.nan}. Namely, the comparison predicates treat [nan] + {!Stdlib.nan}. Namely, the comparison predicates treat [nan] as different from any other float value, including itself; while [compare] treats [nan] as equal to itself and less than any other float value. This treatment of [nan] ensures that [compare] @@ -128,11 +194,13 @@ external ( == ) : 'a -> 'a -> bool = "%eq" On non-mutable types, the behavior of [( == )] is implementation-dependent; however, it is guaranteed that [e1 == e2] implies [compare e1 e2 = 0]. - Left-associative operator at precedence level 4/11. *) + Left-associative operator, see {!Ocaml_operators} for more information. +*) external ( != ) : 'a -> 'a -> bool = "%noteq" -(** Negation of {!Pervasives.( == )}. - Left-associative operator at precedence level 4/11. *) +(** Negation of {!Stdlib.( == )}. + Left-associative operator, see {!Ocaml_operators} for more information. +*) (** {1 Boolean operations} *) @@ -144,24 +212,27 @@ external ( && ) : bool -> bool -> bool = "%sequand" (** The boolean 'and'. Evaluation is sequential, left-to-right: in [e1 && e2], [e1] is evaluated first, and if it returns [false], [e2] is not evaluated at all. - Right-associative operator at precedence level 3/11. *) + Right-associative operator, see {!Ocaml_operators} for more information. +*) external ( & ) : bool -> bool -> bool = "%sequand" [@@ocaml.deprecated "Use (&&) instead."] -(** @deprecated {!Pervasives.( && )} should be used instead. - Right-associative operator at precedence level 3/11. *) +(** @deprecated {!Stdlib.( && )} should be used instead. + Right-associative operator, see {!Ocaml_operators} for more information. +*) external ( || ) : bool -> bool -> bool = "%sequor" (** The boolean 'or'. Evaluation is sequential, left-to-right: in [e1 || e2], [e1] is evaluated first, and if it returns [true], [e2] is not evaluated at all. - Right-associative operator at precedence level 2/11. + Right-associative operator, see {!Ocaml_operators} for more information. *) external ( or ) : bool -> bool -> bool = "%sequor" [@@ocaml.deprecated "Use (||) instead."] -(** @deprecated {!Pervasives.( || )} should be used instead. - Right-associative operator at precedence level 2/11. *) +(** @deprecated {!Stdlib.( || )} should be used instead. + Right-associative operator, see {!Ocaml_operators} for more information. +*) (** {1 Debugging} *) @@ -229,15 +300,15 @@ external __POS_OF__ : 'a -> (string * int * int * int) * 'a = "%loc_POS" external ( |> ) : 'a -> ('a -> 'b) -> 'b = "%revapply" (** Reverse-application operator: [x |> f |> g] is exactly equivalent to [g (f (x))]. - Left-associative operator at precedence level 4/11. - @since 4.01 - *) + Left-associative operator, see {!Ocaml_operators} for more information. + @since 4.01 +*) external ( @@ ) : ('a -> 'b) -> 'a -> 'b = "%apply" (** Application operator: [g @@ f @@ x] is exactly equivalent to [g (f (x))]. - Right-associative operator at precedence level 5/11. - @since 4.01 + Right-associative operator, see {!Ocaml_operators} for more information. + @since 4.01 *) (** {1 Integer arithmetic} *) @@ -248,13 +319,13 @@ external ( @@ ) : ('a -> 'b) -> 'a -> 'b = "%apply" external ( ~- ) : int -> int = "%negint" (** Unary negation. You can also write [- e] instead of [~- e]. - Unary operator at precedence level 9/11 for [- e] - and 11/11 for [~- e]. *) + Unary operator, see {!Ocaml_operators} for more information. +*) + external ( ~+ ) : int -> int = "%identity" (** Unary addition. You can also write [+ e] instead of [~+ e]. - Unary operator at precedence level 9/11 for [+ e] - and 11/11 for [~+ e]. + Unary operator, see {!Ocaml_operators} for more information. @since 3.12.0 *) @@ -266,15 +337,18 @@ external pred : int -> int = "%predint" external ( + ) : int -> int -> int = "%addint" (** Integer addition. - Left-associative operator at precedence level 6/11. *) + Left-associative operator, see {!Ocaml_operators} for more information. +*) external ( - ) : int -> int -> int = "%subint" (** Integer subtraction. - Left-associative operator at precedence level 6/11. *) + Left-associative operator, , see {!Ocaml_operators} for more information. +*) external ( * ) : int -> int -> int = "%mulint" (** Integer multiplication. - Left-associative operator at precedence level 7/11. *) + Left-associative operator, see {!Ocaml_operators} for more information. +*) external ( / ) : int -> int -> int = "%divint" (** Integer division. @@ -283,7 +357,8 @@ external ( / ) : int -> int -> int = "%divint" More precisely, if [x >= 0] and [y > 0], [x / y] is the greatest integer less than or equal to the real quotient of [x] by [y]. Moreover, [(- x) / y = x / (- y) = - (x / y)]. - Left-associative operator at precedence level 7/11. *) + Left-associative operator, see {!Ocaml_operators} for more information. +*) external ( mod ) : int -> int -> int = "%modint" (** Integer remainder. If [y] is not zero, the result @@ -293,7 +368,8 @@ external ( mod ) : int -> int -> int = "%modint" If [y = 0], [x mod y] raises [Division_by_zero]. Note that [x mod y] is negative only if [x < 0]. Raise [Division_by_zero] if [y] is zero. - Left-associative operator at precedence level 7/11. *) + Left-associative operator, see {!Ocaml_operators} for more information. +*) val abs : int -> int (** Return the absolute value of the argument. Note that this may be @@ -310,15 +386,18 @@ val min_int : int external ( land ) : int -> int -> int = "%andint" (** Bitwise logical and. - Left-associative operator at precedence level 7/11. *) + Left-associative operator, see {!Ocaml_operators} for more information. +*) external ( lor ) : int -> int -> int = "%orint" (** Bitwise logical or. - Left-associative operator at precedence level 7/11. *) + Left-associative operator, see {!Ocaml_operators} for more information. +*) external ( lxor ) : int -> int -> int = "%xorint" (** Bitwise logical exclusive or. - Left-associative operator at precedence level 7/11. *) + Left-associative operator, see {!Ocaml_operators} for more information. +*) val lnot : int -> int (** Bitwise logical negation. *) @@ -326,21 +405,23 @@ val lnot : int -> int external ( lsl ) : int -> int -> int = "%lslint" (** [n lsl m] shifts [n] to the left by [m] bits. The result is unspecified if [m < 0] or [m > Sys.int_size]. - Right-associative operator at precedence level 8/11. *) + Right-associative operator, see {!Ocaml_operators} for more information. +*) external ( lsr ) : int -> int -> int = "%lsrint" (** [n lsr m] shifts [n] to the right by [m] bits. This is a logical shift: zeroes are inserted regardless of the sign of [n]. The result is unspecified if [m < 0] or [m > Sys.int_size]. - Right-associative operator at precedence level 8/11. *) + Right-associative operator, see {!Ocaml_operators} for more information. +*) external ( asr ) : int -> int -> int = "%asrint" (** [n asr m] shifts [n] to the right by [m] bits. This is an arithmetic shift: the sign bit of [n] is replicated. The result is unspecified if [m < 0] or [m > Sys.int_size]. - Right-associative operator at precedence level 8/11. *) - + Right-associative operator, see {!Ocaml_operators} for more information. +*) (** {1 Floating-point arithmetic} @@ -358,36 +439,40 @@ external ( asr ) : int -> int -> int = "%asrint" external ( ~-. ) : float -> float = "%negfloat" (** Unary negation. You can also write [-. e] instead of [~-. e]. - Unary operator at precedence level 9/11 for [-. e] - and 11/11 for [~-. e]. *) + Unary operator, see {!Ocaml_operators} for more information. +*) external ( ~+. ) : float -> float = "%identity" (** Unary addition. You can also write [+. e] instead of [~+. e]. - Unary operator at precedence level 9/11 for [+. e] - and 11/11 for [~+. e]. + Unary operator, see {!Ocaml_operators} for more information. @since 3.12.0 *) external ( +. ) : float -> float -> float = "%addfloat" (** Floating-point addition. - Left-associative operator at precedence level 6/11. *) + Left-associative operator, see {!Ocaml_operators} for more information. +*) external ( -. ) : float -> float -> float = "%subfloat" (** Floating-point subtraction. - Left-associative operator at precedence level 6/11. *) + Left-associative operator, see {!Ocaml_operators} for more information. +*) external ( *. ) : float -> float -> float = "%mulfloat" (** Floating-point multiplication. - Left-associative operator at precedence level 7/11. *) + Left-associative operator, see {!Ocaml_operators} for more information. +*) external ( /. ) : float -> float -> float = "%divfloat" (** Floating-point division. - Left-associative operator at precedence level 7/11. *) + Left-associative operator, see {!Ocaml_operators} for more information. +*) external ( ** ) : float -> float -> float = "caml_power_float" "pow" [@@unboxed] [@@noalloc] (** Exponentiation. - Right-associative operator at precedence level 8/11. *) + Right-associative operator, see {!Ocaml_operators} for more information. +*) external sqrt : float -> float = "caml_sqrt_float" "sqrt" [@@unboxed] [@@noalloc] @@ -516,13 +601,13 @@ external modf : float -> float * float = "caml_modf_float" part of [f]. *) external float : int -> float = "%floatofint" -(** Same as {!Pervasives.float_of_int}. *) +(** Same as {!Stdlib.float_of_int}. *) external float_of_int : int -> float = "%floatofint" (** Convert an integer to floating-point. *) external truncate : float -> int = "%intoffloat" -(** Same as {!Pervasives.int_of_float}. *) +(** Same as {!Stdlib.int_of_float}. *) external int_of_float : float -> int = "%intoffloat" (** Truncate the given floating-point number to an integer. @@ -560,7 +645,7 @@ type fpclass = | FP_infinite (** Number is positive or negative infinity *) | FP_nan (** Not a number: result of an undefined operation *) (** The five classes of floating-point numbers, as determined by - the {!Pervasives.classify_float} function. *) + the {!Stdlib.classify_float} function. *) external classify_float : (float [@unboxed]) -> fpclass = "caml_classify_float" "caml_classify_float_unboxed" [@@noalloc] @@ -575,8 +660,8 @@ external classify_float : (float [@unboxed]) -> fpclass = val ( ^ ) : string -> string -> string (** String concatenation. - Right-associative operator at precedence level 5/11. *) - + Right-associative operator, see {!Ocaml_operators} for more information. +*) (** {1 Character operations} @@ -610,22 +695,21 @@ val string_of_bool : bool -> string may be shared, the user should not modify them directly. *) -val bool_of_string : string -> bool -(** Convert the given string to a boolean. - Raise [Invalid_argument "bool_of_string"] if the string is not - ["true"] or ["false"]. *) - val bool_of_string_opt: string -> bool option (** Convert the given string to a boolean. - Return [None] if the string is not - ["true"] or ["false"]. - @since 4.05 + + Return [None] if the string is not ["true"] or ["false"]. + @since 4.05 *) +val bool_of_string : string -> bool +(** Same as {!Stdlib.bool_of_string_opt}, but raise + [Invalid_argument "bool_of_string"] instead of returning [None]. *) + val string_of_int : int -> string (** Return the string representation of an integer, in decimal. *) -external int_of_string : string -> int = "caml_int_of_string" +val int_of_string_opt: string -> int option (** Convert the given string to an integer. The string is read in decimal (by default, or if the string begins with [0u]), in hexadecimal (if it begins with [0x] or @@ -639,41 +723,48 @@ external int_of_string : string -> int = "caml_int_of_string" The [_] (underscore) character can appear anywhere in the string and is ignored. - Raise [Failure "int_of_string"] if the given string is not - a valid representation of an integer, or if the integer represented - exceeds the range of integers representable in type [int]. *) - -val int_of_string_opt: string -> int option -(** Same as [int_of_string], but returns [None] instead of raising. - @since 4.05 + Return [None] if the given string is not a valid representation of an + integer, or if the integer represented exceeds the range of integers + representable in type [int]. + @since 4.05 *) +external int_of_string : string -> int = "caml_int_of_string" +(** Same as {!Stdlib.int_of_string_opt}, but raise + [Failure "int_of_string"] instead of returning [None]. *) + val string_of_float : float -> string (** Return the string representation of a floating-point number. *) -external float_of_string : string -> float = "caml_float_of_string" +val float_of_string_opt: string -> float option (** Convert the given string to a float. The string is read in decimal (by default) or in hexadecimal (marked by [0x] or [0X]). + The format of decimal floating-point numbers is [ [-] dd.ddd (e|E) [+|-] dd ], where [d] stands for a decimal digit. + The format of hexadecimal floating-point numbers is [ [-] 0(x|X) hh.hhh (p|P) [+|-] dd ], where [h] stands for an hexadecimal digit and [d] for a decimal digit. + In both cases, at least one of the integer and fractional parts must be given; the exponent part is optional. + The [_] (underscore) character can appear anywhere in the string and is ignored. + Depending on the execution platforms, other representations of floating-point numbers can be accepted, but should not be relied upon. - Raise [Failure "float_of_string"] if the given string is not a valid - representation of a float. *) -val float_of_string_opt: string -> float option -(** Same as [float_of_string], but returns [None] instead of raising. - @since 4.05 + Return [None] if the given string is not a valid representation of a float. + @since 4.05 *) +external float_of_string : string -> float = "caml_float_of_string" +(** Same as {!Stdlib.float_of_string_opt}, but raise + [Failure "float_of_string"] instead of returning [None]. *) + (** {1 Pair operations} *) external fst : 'a * 'b -> 'a = "%field0" @@ -690,8 +781,8 @@ external snd : 'a * 'b -> 'b = "%field1" val ( @ ) : 'a list -> 'a list -> 'a list (** List concatenation. Not tail-recursive (length of the first argument). - Right-associative operator at precedence level 5/11. *) - + Right-associative operator, see {!Ocaml_operators} for more information. +*) (** {1 Input/output} Note: all input/output functions can raise [Sys_error] when the system @@ -775,28 +866,30 @@ val read_line : unit -> string until a newline character is encountered. Return the string of all characters read, without the newline character at the end. *) -val read_int : unit -> int +val read_int_opt: unit -> int option (** Flush standard output, then read one line from standard input - and convert it to an integer. Raise [Failure "int_of_string"] - if the line read is not a valid representation of an integer. *) + and convert it to an integer. -val read_int_opt: unit -> int option -(** Same as [read_int_opt], but returns [None] instead of raising. - @since 4.05 + Return [None] if the line read is not a valid representation of an integer. + @since 4.05 *) -val read_float : unit -> float -(** Flush standard output, then read one line from standard input - and convert it to a floating-point number. - The result is unspecified if the line read is not a valid - representation of a floating-point number. *) +val read_int : unit -> int +(** Same as {!Stdlib.read_int_opt}, but raise [Failure "int_of_string"] + instead of returning [None]. *) val read_float_opt: unit -> float option (** Flush standard output, then read one line from standard input - and convert it to a floating-point number. - Returns [None] if the line read is not a valid - representation of a floating-point number. - @since 4.05.0 *) + and convert it to a floating-point number. + + Return [None] if the line read is not a valid representation of a + floating-point number. + @since 4.05.0 +*) + +val read_float : unit -> float +(** Same as {!Stdlib.read_float_opt}, but raise [Failure "float_of_string"] + instead of returning [None]. *) (** {2 General output functions} *) @@ -811,8 +904,8 @@ type open_flag = | Open_binary (** open in binary mode (no conversion). *) | Open_text (** open in text mode (may perform conversions). *) | Open_nonblock (** open in non-blocking mode. *) -(** Opening modes for {!Pervasives.open_out_gen} and - {!Pervasives.open_in_gen}. *) +(** Opening modes for {!Stdlib.open_out_gen} and + {!Stdlib.open_in_gen}. *) val open_out : string -> out_channel (** Open the named file for writing, and return a new output channel @@ -821,17 +914,17 @@ val open_out : string -> out_channel is created if it does not already exists. *) val open_out_bin : string -> out_channel -(** Same as {!Pervasives.open_out}, but the file is opened in binary mode, +(** Same as {!Stdlib.open_out}, but the file is opened in binary mode, so that no translation takes place during writes. On operating systems that do not distinguish between text mode and binary - mode, this function behaves like {!Pervasives.open_out}. *) + mode, this function behaves like {!Stdlib.open_out}. *) val open_out_gen : open_flag list -> int -> string -> out_channel (** [open_out_gen mode perm filename] opens the named file for writing, as described above. The extra argument [mode] specifies the opening mode. The extra argument [perm] specifies the file permissions, in case the file must be created. - {!Pervasives.open_out} and {!Pervasives.open_out_bin} are special + {!Stdlib.open_out} and {!Stdlib.open_out_bin} are special cases of this function. *) val flush : out_channel -> unit @@ -874,15 +967,15 @@ val output_binary_int : out_channel -> int -> unit on the given output channel. The given integer is taken modulo 2{^32}. The only reliable way to read it back is through the - {!Pervasives.input_binary_int} function. The format is compatible across + {!Stdlib.input_binary_int} function. The format is compatible across all machines for a given version of OCaml. *) val output_value : out_channel -> 'a -> unit (** Write the representation of a structured value of any type to a channel. Circularities and sharing inside the value are detected and preserved. The object can be read back, - by the function {!Pervasives.input_value}. See the description of module - {!Marshal} for more information. {!Pervasives.output_value} is equivalent + by the function {!Stdlib.input_value}. See the description of module + {!Marshal} for more information. {!Stdlib.output_value} is equivalent to {!Marshal.to_channel} with an empty list of flags. *) val seek_out : out_channel -> int -> unit @@ -930,16 +1023,16 @@ val open_in : string -> in_channel on that file, positioned at the beginning of the file. *) val open_in_bin : string -> in_channel -(** Same as {!Pervasives.open_in}, but the file is opened in binary mode, +(** Same as {!Stdlib.open_in}, but the file is opened in binary mode, so that no translation takes place during reads. On operating systems that do not distinguish between text mode and binary - mode, this function behaves like {!Pervasives.open_in}. *) + mode, this function behaves like {!Stdlib.open_in}. *) val open_in_gen : open_flag list -> int -> string -> in_channel (** [open_in_gen mode perm filename] opens the named file for reading, as described above. The extra arguments [mode] and [perm] specify the opening mode and file permissions. - {!Pervasives.open_in} and {!Pervasives.open_in_bin} are special + {!Stdlib.open_in} and {!Stdlib.open_in_bin} are special cases of this function. *) val input_char : in_channel -> char @@ -965,7 +1058,7 @@ val input : in_channel -> bytes -> int -> int -> int no more characters were available at that time, or because the implementation found it convenient to do a partial read; [input] must be called again to read the remaining characters, - if desired. (See also {!Pervasives.really_input} for reading + if desired. (See also {!Stdlib.really_input} for reading exactly [len] characters.) Exception [Invalid_argument "input"] is raised if [pos] and [len] do not designate a valid range of [buf]. *) @@ -986,19 +1079,19 @@ val really_input_string : in_channel -> int -> string @since 4.02.0 *) val input_byte : in_channel -> int -(** Same as {!Pervasives.input_char}, but return the 8-bit integer representing +(** Same as {!Stdlib.input_char}, but return the 8-bit integer representing the character. Raise [End_of_file] if an end of file was reached. *) val input_binary_int : in_channel -> int (** Read an integer encoded in binary format (4 bytes, big-endian) - from the given input channel. See {!Pervasives.output_binary_int}. + from the given input channel. See {!Stdlib.output_binary_int}. Raise [End_of_file] if an end of file was reached while reading the integer. *) val input_value : in_channel -> 'a (** Read the representation of a structured value, as produced - by {!Pervasives.output_value}, and return the corresponding value. + by {!Stdlib.output_value}, and return the corresponding value. This function is identical to {!Marshal.from_channel}; see the description of module {!Marshal} for more information, in particular concerning the lack of type safety. *) @@ -1057,7 +1150,6 @@ module LargeFile : regular integers (type [int]), these alternate functions allow operating on files whose sizes are greater than [max_int]. *) - (** {1 References} *) type 'a ref = { mutable contents : 'a } @@ -1070,12 +1162,14 @@ external ref : 'a -> 'a ref = "%makemutable" external ( ! ) : 'a ref -> 'a = "%field0" (** [!r] returns the current contents of reference [r]. Equivalent to [fun r -> r.contents]. - Unary operator at precedence level 11/11.*) + Unary operator, see {!Ocaml_operators} for more information. +*) external ( := ) : 'a ref -> 'a -> unit = "%setfield0" (** [r := a] stores the value of [a] in reference [r]. Equivalent to [fun r v -> r.contents <- v]. - Right-associative operator at precedence level 1/11. *) + Right-associative operator, see {!Ocaml_operators} for more information. +*) external incr : int ref -> unit = "%incr" (** Increment the integer contained in the given reference. @@ -1189,8 +1283,8 @@ val ( ^^ ) : [f2]: in case of formatted output, it accepts arguments from [f1], then arguments from [f2]; in case of formatted input, it returns results from [f1], then results from [f2]. - Right-associative operator at precedence level 5/11. *) - + Right-associative operator, see {!Ocaml_operators} for more information. +*) (** {1 Program termination} *) @@ -1207,7 +1301,7 @@ val at_exit : (unit -> unit) -> unit (** Register the given function to be called at program termination time. The functions registered with [at_exit] will be called when the program does any of the following: - - executes {!Pervasives.exit} + - executes {!Stdlib.exit} - terminates, either normally or because of an uncaught exception - executes the C function [caml_shutdown]. @@ -1223,15 +1317,17 @@ val valid_float_lexem : string -> string val unsafe_really_input : in_channel -> bytes -> int -> int -> unit val do_at_exit : unit -> unit -end -include module type of struct include Pervasives end +(**/**) + +(** {1:modules Standard library modules } *) (*MODULE_ALIASES*) module Arg = Arg module Array = Array module ArrayLabels = ArrayLabels module Bigarray = Bigarray +module Bool = Bool module Buffer = Buffer module Bytes = Bytes module BytesLabels = BytesLabels @@ -1243,9 +1339,11 @@ module Ephemeron = Ephemeron module Filename = Filename module Float = Float module Format = Format +module Fun = Fun module Gc = Gc module Genlex = Genlex module Hashtbl = Hashtbl +module Int = Int module Int32 = Int32 module Int64 = Int64 module Lazy = Lazy @@ -1258,15 +1356,21 @@ module MoreLabels = MoreLabels module Nativeint = Nativeint module Obj = Obj module Oo = Oo +module Option = Option module Parsing = Parsing +module Pervasives = Pervasives +[@@deprecated "Use Stdlib instead.\n\ +\n\ +If you need to stay compatible with OCaml < 4.07, you can use the \n\ +stdlib-shims library: https://github.com/ocaml/stdlib-shims"] module Printexc = Printexc module Printf = Printf module Queue = Queue module Random = Random +module Result = Result module Scanf = Scanf module Seq = Seq module Set = Set -module Sort = Sort module Spacetime = Spacetime module Stack = Stack module StdLabels = StdLabels @@ -1275,4 +1379,5 @@ module String = String module StringLabels = StringLabels module Sys = Sys module Uchar = Uchar +module Unit = Unit module Weak = Weak diff --git a/stdlib/string.ml b/stdlib/string.ml index 82c4af36..12a627f3 100644 --- a/stdlib/string.ml +++ b/stdlib/string.ml @@ -104,7 +104,8 @@ let escaped s = let rec escape_if_needed s n i = if i >= n then s else match unsafe_get s i with - | '\"' | '\\' | '\000'..'\031' | '\127'.. '\255' -> bts (B.escaped (bos s)) + | '\"' | '\\' | '\000'..'\031' | '\127'.. '\255' -> + bts (B.escaped (bos s)) | _ -> escape_if_needed s n (i+1) in escape_if_needed s (length s) 0 @@ -134,8 +135,10 @@ let index_from s i c = (* duplicated in bytes.ml *) let index_from_opt s i c = let l = length s in - if i < 0 || i > l then invalid_arg "String.index_from_opt / Bytes.index_from_opt" else - index_rec_opt s l i c + if i < 0 || i > l then + invalid_arg "String.index_from_opt / Bytes.index_from_opt" + else + index_rec_opt s l i c (* duplicated in bytes.ml *) let rec rindex_rec s i c = @@ -196,8 +199,8 @@ let uncapitalize_ascii s = type t = string -let compare (x: t) (y: t) = Pervasives.compare x y -external equal : string -> string -> bool = "caml_string_equal" +let compare (x: t) (y: t) = Stdlib.compare x y +external equal : string -> string -> bool = "caml_string_equal" [@@noalloc] let split_on_char sep s = let r = ref [] in @@ -221,11 +224,10 @@ let capitalize s = let uncapitalize s = B.uncapitalize (bos s) |> bts -(** {6 Iterators} *) +(** {1 Iterators} *) let to_seq s = bos s |> B.to_seq let to_seqi s = bos s |> B.to_seqi let of_seq g = B.of_seq g |> bts - diff --git a/stdlib/string.mli b/stdlib/string.mli index 8ec3fff8..a38c8123 100644 --- a/stdlib/string.mli +++ b/stdlib/string.mli @@ -32,21 +32,19 @@ substring of [s] if [len >= 0] and [start] and [start+len] are valid positions in [s]. - OCaml strings used to be modifiable in place, for instance via the - {!String.set} and {!String.blit} functions described below. This - usage is deprecated and only possible when the compiler is put in - "unsafe-string" mode by giving the [-unsafe-string] command-line - option (which is currently the default for reasons of backward - compatibility). This is done by making the types [string] and - [bytes] (see module {!Bytes}) interchangeable so that functions - expecting byte sequences can also accept strings as arguments and - modify them. - - All new code should avoid this feature and be compiled with the - [-safe-string] command-line option to enforce the separation between - the types [string] and [bytes]. - - *) + Note: OCaml strings used to be modifiable in place, for instance via + the {!String.set} and {!String.blit} functions described below. This + usage is only possible when the compiler is put in "unsafe-string" + mode by giving the [-unsafe-string] command-line option. This + compatibility mode makes the types [string] and [bytes] (see module + {!Bytes}) interchangeable so that functions expecting byte sequences + can also accept strings as arguments and modify them. + + The distinction between [bytes] and [string] was introduced in OCaml + 4.02, and the "unsafe-string" compatibility mode was the default + until OCaml 4.05. Starting with 4.06, the compatibility mode is + opt-in; we intend to remove the option in the future. +*) external length : string -> int = "%string_length" (** Return the length (number of characters) of the given string. *) @@ -310,7 +308,7 @@ type t = string val compare: t -> t -> int (** The comparison function for strings, with the same specification as - {!Pervasives.compare}. Along with the type [t], this function [compare] + {!Stdlib.compare}. Along with the type [t], this function [compare] allows the module [String] to be passed as argument to the functors {!Set.Make} and {!Map.Make}. *) @@ -333,7 +331,7 @@ val split_on_char: char -> string -> string list @since 4.04.0 *) -(** {6 Iterators} *) +(** {1 Iterators} *) val to_seq : t -> char Seq.t (** Iterate on the string, in increasing index order. Modifications of the diff --git a/stdlib/stringLabels.mli b/stdlib/stringLabels.mli index dac714cb..d136a169 100644 --- a/stdlib/stringLabels.mli +++ b/stdlib/stringLabels.mli @@ -265,7 +265,7 @@ type t = string val compare: t -> t -> int (** The comparison function for strings, with the same specification as - {!Pervasives.compare}. Along with the type [t], this function [compare] + {!Stdlib.compare}. Along with the type [t], this function [compare] allows the module [String] to be passed as argument to the functors {!Set.Make} and {!Map.Make}. *) @@ -288,7 +288,7 @@ val split_on_char: sep:char -> string -> string list @since 4.05.0 *) -(** {6 Iterators} *) +(** {1 Iterators} *) val to_seq : t -> char Seq.t (** Iterate on the string, in increasing index order. Modifications of the diff --git a/stdlib/sys.mli b/stdlib/sys.mli index 22884950..370449ec 100644 --- a/stdlib/sys.mli +++ b/stdlib/sys.mli @@ -145,9 +145,16 @@ val max_string_length : int (** Maximum length of strings and byte sequences. *) val max_array_length : int -(** Maximum length of a normal array. The maximum length of a float - array is [max_array_length/2] on 32-bit machines and - [max_array_length] on 64-bit machines. *) +(** Maximum length of a normal array (i.e. any array whose elements are + not of type [float]). The maximum length of a [float array] + is [max_floatarray_length] if OCaml was configured with + [--enable-flat-float-array] and [max_array_length] if configured + with [--disable-flat-float-array]. *) + +val max_floatarray_length : int +(** Maximum length of a floatarray. This is also the maximum length of + a [float array] when OCaml is configured with + [--enable-flat-float-array]. *) external runtime_variant : unit -> string = "caml_runtime_variant" (** Return the name of the runtime variant the program is running on. diff --git a/stdlib/sys.mlp b/stdlib/sys.mlp index 62c84fb1..5d997e8a 100644 --- a/stdlib/sys.mlp +++ b/stdlib/sys.mlp @@ -45,6 +45,7 @@ let unix = unix () let win32 = win32 () let cygwin = cygwin () let max_array_length = max_wosize () +let max_floatarray_length = max_array_length / (64 / word_size) let max_string_length = word_size / 8 * max_array_length - 1 external runtime_variant : unit -> string = "caml_runtime_variant" external runtime_parameters : unit -> string = "caml_runtime_parameters" diff --git a/stdlib/uchar.ml b/stdlib/uchar.ml index e4a40f65..f48e1b10 100644 --- a/stdlib/uchar.ml +++ b/stdlib/uchar.ml @@ -54,5 +54,5 @@ let to_char u = let unsafe_to_char = Char.unsafe_chr let equal : int -> int -> bool = ( = ) -let compare : int -> int -> int = Pervasives.compare +let compare : int -> int -> int = Stdlib.compare let hash = to_int diff --git a/stdlib/uchar.mli b/stdlib/uchar.mli index afab670f..8ce7a35a 100644 --- a/stdlib/uchar.mli +++ b/stdlib/uchar.mli @@ -92,7 +92,7 @@ val equal : t -> t -> bool (** [equal u u'] is [u = u']. *) val compare : t -> t -> int -(** [compare u u'] is [Pervasives.compare u u']. *) +(** [compare u u'] is [Stdlib.compare u u']. *) val hash : t -> int (** [hash u] associates a non-negative integer to [u]. *) diff --git a/stdlib/unit.ml b/stdlib/unit.ml new file mode 100644 index 00000000..402c2593 --- /dev/null +++ b/stdlib/unit.ml @@ -0,0 +1,20 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* The OCaml programmers *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +type t = unit = () + +let equal () () = true +let compare () () = 0 +let to_string () = "()" diff --git a/stdlib/unit.mli b/stdlib/unit.mli new file mode 100644 index 00000000..8c7cb211 --- /dev/null +++ b/stdlib/unit.mli @@ -0,0 +1,36 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* The OCaml programmers *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** Unit values. + + @since 4.08 *) + +(** {1:unit The unit type} *) + +type t = unit = () +(** The unit type. + + The constructor [()] is included here so that it has a path, + but it is not intended to be used in user-defined data types. + *) + +val equal : t -> t -> bool +(** [equal u1 u2] is [true]. *) + +val compare : t -> t -> int +(** [compare u1 u2] is [0]. *) + +val to_string : t -> string +(** [to_string b] is ["()"]. *) diff --git a/stdlib/weak.ml b/stdlib/weak.ml index 4ade095a..5368ff80 100644 --- a/stdlib/weak.ml +++ b/stdlib/weak.ml @@ -19,20 +19,54 @@ type 'a t external create : int -> 'a t = "caml_weak_create" +let create l = + if not (0 <= l && l <= Obj.Ephemeron.max_ephe_length) then + invalid_arg("Weak.create"); + create l + (** number of additional values in a weak pointer *) let additional_values = 2 let length x = Obj.size(Obj.repr x) - additional_values -external set : 'a t -> int -> 'a option -> unit = "caml_weak_set" +let raise_if_invalid_offset e o msg = + if not (0 <= o && o < length e) then + invalid_arg(msg) + +external set' : 'a t -> int -> 'a -> unit = "caml_ephe_set_key" +external unset : 'a t -> int -> unit = "caml_ephe_unset_key" +let set e o x = + raise_if_invalid_offset e o "Weak.set"; + match x with + | None -> unset e o + | Some x -> set' e o x + external get : 'a t -> int -> 'a option = "caml_weak_get" +let get e o = + raise_if_invalid_offset e o "Weak.get"; + get e o + external get_copy : 'a t -> int -> 'a option = "caml_weak_get_copy" +let get_copy e o = + raise_if_invalid_offset e o "Weak.get_copy"; + get_copy e o + external check : 'a t -> int -> bool = "caml_weak_check" +let check e o = + raise_if_invalid_offset e o "Weak.check"; + check e o + external blit : 'a t -> int -> 'a t -> int -> int -> unit = "caml_weak_blit" + (* blit: src srcoff dst dstoff len *) +let blit e1 o1 e2 o2 l = + if l < 0 || o1 < 0 || o1 > length e1 - l + || o2 < 0 || o2 > length e2 - l + then invalid_arg "Weak.blit" + else if l <> 0 then blit e1 o1 e2 o2 l let fill ar ofs len x = - if ofs < 0 || len < 0 || ofs + len > length ar + if ofs < 0 || len < 0 || ofs > length ar - len then raise (Invalid_argument "Weak.fill") else begin for i = ofs to (ofs + len - 1) do diff --git a/stdlib/weak.mli b/stdlib/weak.mli index 842520aa..a1f304c4 100644 --- a/stdlib/weak.mli +++ b/stdlib/weak.mli @@ -22,15 +22,17 @@ type 'a t (** The type of arrays of weak pointers (weak arrays). A weak pointer is a value that the garbage collector may erase whenever the value is not used any more (through normal pointers) by the - program. Note that finalisation functions are run after the - weak pointers are erased. + program. Note that finalisation functions are run before the + weak pointers are erased, because the finalisation functions + can make values alive again (before 4.03 the finalisation + functions were run after). A weak pointer is said to be full if it points to a value, empty if the value was erased by the GC. Notes: - Integers are not allocated and cannot be stored in weak arrays. - - Weak arrays cannot be marshaled using {!Pervasives.output_value} + - Weak arrays cannot be marshaled using {!Stdlib.output_value} nor the functions of the {!Marshal} module. *) @@ -38,7 +40,8 @@ type 'a t val create : int -> 'a t (** [Weak.create n] returns a new weak array of length [n]. All the pointers are initially empty. Raise [Invalid_argument] - if [n] is negative or greater than {!Sys.max_array_length}[-1].*) + if [n] is not comprised between zero and + {!Obj.Ephemeron.max_ephe_length} (limits included).*) val length : 'a t -> int (** [Weak.length ar] returns the length (number of elements) of @@ -114,7 +117,7 @@ module type S = sig type t (** The type of tables that contain elements of type [data]. Note that weak hash sets cannot be marshaled using - {!Pervasives.output_value} or the functions of the {!Marshal} + {!Stdlib.output_value} or the functions of the {!Marshal} module. *) val create : int -> t diff --git a/testsuite/HACKING.adoc b/testsuite/HACKING.adoc index f634cda7..3d010e54 100644 --- a/testsuite/HACKING.adoc +++ b/testsuite/HACKING.adoc @@ -4,10 +4,29 @@ == Useful Makefile targets -`make parallel`:: runs the tests in parallel using the link:https://www.gnu.org/software/parallel/[GNU parallel] tool: tests run twice as fast with no difference in output order. +`make parallel`:: + runs the tests in parallel using the + link:https://www.gnu.org/software/parallel/[GNU parallel] tool: tests run + twice as fast with no difference in output order. -`make all-foo`, `make parallel-foo`:: runs only the tests in the directories whose name starts with `foo`: `parallel-typing`, `all-lib`, etc. +`make all-foo`, `make parallel-foo`:: + runs only the tests in the directories whose name starts with `foo`: + `parallel-typing`, `all-lib`, etc. -`make one DIR=tests/foo`:: runs only the tests in the directory `tests/foo`. This is often equivalent to `cd tests/foo && make`, but sometimes the latter breaks the test makefile if it contains fragile relative filesystem paths. Such errors should be fixed if you find them, but `make one DIR=...` is the more reliable option as it runs exactly as `make all` which is heavily tested. +`make one DIR=tests/foo`:: + runs only the tests in the directory `tests/foo`. This is often equivalent to + `cd tests/foo && make`, but sometimes the latter breaks the test makefile if + it contains fragile relative filesystem paths. Such errors should be fixed if + you find them, but `make one DIR=...` is the more reliable option as it runs + exactly as `make all` which is heavily tested. -`make promote DIR=tests/foo`:: most test run a program and compare the result of the program, store in a file `foo.result`, with a reference output stored in `foo.reference` -- the test fails if the two output differ. Sometimes a change in result is innocuous, it comes from an intended change in output instead of a regression. `make promote` copies the new result file into the reference file, making the test pass again. Whenever you use this rule please check carefully, using `git diff`, that the change really corresponds to an intended output difference, and not to a regression. You then need to commit the change to reference file, and your commit message should explain why the output changed. +`make promote DIR=tests/foo`:: + Most tests run a program and compare the result of the program, store in a file + `foo.result`, with a reference output stored in `foo.reference` -- the test + fails if the two output differ. Sometimes a change in result is innocuous, it + comes from an intended change in output instead of a regression. + `make promote` copies the new result file into the reference file, making the + test pass again. Whenever you use this rule please check carefully, using + `git diff`, that the change really corresponds to an intended output + difference, and not to a regression. You then need to commit the change to + reference file, and your commit message should explain why the output changed. diff --git a/testsuite/Makefile b/testsuite/Makefile index 7375c467..b383ec23 100644 --- a/testsuite/Makefile +++ b/testsuite/Makefile @@ -21,6 +21,18 @@ FIND=find TOPDIR := .. include $(TOPDIR)/Makefile.tools +OCAMLTESTDIR_CYGPATH=$(shell $(CYGPATH) $(BASEDIR)/$(DIR)/_ocamltest) + +failstamp := failure.stamp + +TESTLOG ?= _log + +ocamltest_directory := ../ocamltest + +ocamltest_program := $(or \ + $(wildcard $(ocamltest_directory)/ocamltest.opt$(EXE)),\ + $(wildcard $(ocamltest_directory)/ocamltest$(EXE))) + ifeq "$(UNIX_OR_WIN32)" "unix" ifeq "$(SYSTEM)" "cygwin" find := /usr/bin/find @@ -31,26 +43,23 @@ else # Windows find := /usr/bin/find FLEXDLL_SUBMODULE_PRESENT := $(wildcard ../flexdll/Makefile) ifeq "$(FLEXDLL_SUBMODULE_PRESENT)" "" - FLEXLINK_PREFIX= + FLEXLINK_ENV = else - ROOT:=$(shell cd .. && pwd| cygpath -m -f -) - EMPTY= - FLEXLINK_PREFIX:=OCAML_FLEXLINK="$(ROOT)/boot/ocamlrun \ - $(ROOT)/flexdll/flexlink.exe" $(EMPTY) + ROOT := $(shell cd .. && pwd| cygpath -m -f -) + FLEXLINK_ENV = \ + OCAML_FLEXLINK="$(ROOT)/boot/ocamlrun $(ROOT)/flexdll/flexlink.exe" endif endif -failstamp := failure.stamp - -TESTLOG ?= _log - -ocamltest_directory := ../ocamltest - -ocamltest_program := $(or \ - $(wildcard $(ocamltest_directory)/ocamltest.opt$(EXE)),\ - $(wildcard $(ocamltest_directory)/ocamltest$(EXE))) +ifeq "$(FLEXLINK_ENV)" "" + ocamltest := MKDLL="$(MKDLL)" SORT=$(SORT) MAKE=$(MAKE) $(ocamltest_program) +else + MKDLL=$(WINTOPDIR)/boot/ocamlrun $(WINTOPDIR)/flexdll/flexlink.exe \ + $(FLEXLINK_FLAGS) -ocamltest := $(FLEXLINK_PREFIX) SORT=$(SORT) $(ocamltest_program) + ocamltest := $(FLEXLINK_ENV) MKDLL="$(MKDLL)" SORT=$(SORT) MAKE=$(MAKE) \ + $(ocamltest_program) +endif .PHONY: default default: @@ -108,8 +117,17 @@ new-without-report: lib tools echo Running tests from \'$$dir\' ... ; \ $(MAKE) exec-ocamltest DIR=$$dir \ OCAMLTESTENV="" OCAMLTESTFLAGS=""; \ - done || touch $(failstamp)) 2>&1 | tee -a $(TESTLOG) - @if [ -f $(failstamp) ]; then rm $(failstamp); exit 1; fi + done || echo outer loop >> $(failstamp)) 2>&1 | tee -a $(TESTLOG) + @$(MAKE) check-failstamp + +.PHONY: check-failstamp +check-failstamp: + @if [ -f $(failstamp) ]; then \ + echo 'Unexpected error in the test infrastructure:'; \ + cat $(failstamp); \ + rm $(failstamp); \ + exit 1; \ + fi .PHONY: all-% all-%: lib tools @@ -119,7 +137,7 @@ all-%: lib tools @$(MAKE) $(NO_PRINT) retries @$(MAKE) report -# The targets below use GNU parallel to paralellize tests +# The targets below use GNU parallel to parallelize tests # 'make all' and 'make parallel' should be equivalent # # parallel uses specific logic to make sure the output of the commands @@ -186,7 +204,7 @@ one: lib tools exit 1; \ fi @$(MAKE) $(NO_PRINT) exec-one DIR=$(DIR) - @if [ -f $(failstamp) ]; then rm $(failstamp); exit 1; fi + @$(MAKE) check-failstamp .PHONY: exec-one exec-one: @@ -203,7 +221,7 @@ exec-one: elif [ -f $(DIR)/ocamltests ] && [ -z $(LEGACY) ] ; then \ echo "Running tests from '$$DIR' ..."; \ $(MAKE) exec-ocamltest DIR=$(DIR) \ - OCAMLTESTENV="OCAMLTESTDIR=$(shell $(CYGPATH) $(BASEDIR)/$(DIR)/_ocamltest)" \ + OCAMLTESTENV="OCAMLTESTDIR=$(OCAMLTESTDIR_CYGPATH)" \ OCAMLTESTFLAGS=""; \ fi @@ -215,8 +233,8 @@ exec-ocamltest: (IFS=$$(printf "\r\n"); while read testfile; do \ TERM=dumb $(OCAMLTESTENV) \ $(ocamltest) $(OCAMLTESTFLAGS) $(DIR)/$$testfile || \ - touch $(failstamp); \ - done < $$file) || touch $(failstamp) + echo " ... testing '$$testfile' => unexpected error"; \ + done < $$file) || echo directory "$(DIR)" >>$(failstamp) .PHONY: clean-one clean-one: @@ -242,7 +260,7 @@ promote: fi @if [ -f $(DIR)/ocamltests ]; then \ $(MAKE) exec-ocamltest DIR=$(DIR) \ - OCAMLTESTENV="OCAMLTESTDIR=$(shell $(CYGPATH) $(BASEDIR)/$(DIR)/_ocamltest)" \ + OCAMLTESTENV="OCAMLTESTDIR=$(OCAMLTESTDIR_CYGPATH)" \ OCAMLTESTFLAGS="-promote"; \ else \ cd $(DIR) && $(MAKE) TERM=dumb BASEDIR=$(BASEDIR) promote; \ diff --git a/testsuite/lib/lib.ml b/testsuite/lib/lib.ml index 9ab74271..59b8549d 100644 --- a/testsuite/lib/lib.ml +++ b/testsuite/lib/lib.ml @@ -1,3 +1,18 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Para, INRIA Rocquencourt *) +(* *) +(* Copyright 1999 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + external raise : exn -> 'a = "%raise" external not : bool -> bool = "%boolnot" diff --git a/testsuite/lib/testing.ml b/testsuite/lib/testing.ml index 662719af..4111ca51 100644 --- a/testsuite/lib/testing.ml +++ b/testsuite/lib/testing.ml @@ -13,7 +13,7 @@ (* *) (**************************************************************************) -(* Testing auxilliaries. *) +(* Testing auxiliaries. *) open Scanf;; diff --git a/testsuite/lib/testing.mli b/testsuite/lib/testing.mli index f13bb358..ce054156 100644 --- a/testsuite/lib/testing.mli +++ b/testsuite/lib/testing.mli @@ -13,7 +13,7 @@ (* *) (**************************************************************************) -(* Testing auxilliaries. *) +(* Testing auxiliaries. *) val test : bool -> unit;; (** [test e] tests that [e] evaluates to [true]. *) diff --git a/testsuite/makefiles/Makefile.common b/testsuite/makefiles/Makefile.common index 76063f7c..34500493 100644 --- a/testsuite/makefiles/Makefile.common +++ b/testsuite/makefiles/Makefile.common @@ -16,6 +16,8 @@ TOPDIR=$(BASEDIR)/.. include $(TOPDIR)/Makefile.tools +codegen := $(OTOPDIR)/testsuite/tools/codegen + .PHONY: defaultpromote defaultpromote: @for file in *.reference; do \ @@ -61,12 +63,10 @@ defaultclean: @$(OCAMLLEX) -q $< > /dev/null .cmm.s: - @$(OCAMLRUN) ./codegen -S $*.cmm + @$(OCAMLRUN) $(codegen) -S $*.cmm .cmm.obj: - @$(OCAMLRUN) ./codegen $*.cmm \ - | grep -v "_caml_\(young_ptr\|young_limit\|extra_params\ - \|allocN\|raise_exn\|reraise_exn\)" > $*.s + @$(OCAMLRUN) $(codegen) $*.cmm > $*.s @set -o pipefail ; \ $(ASM) $*.obj $*.s | tail -n +2 @@ -78,7 +78,7 @@ defaultclean: @$(ASPP) $(ASPPFLAGS) -DSYS_$(SYSTEM) -o $*.o $*.s .c.o: - @$(CC) $(CFLAGS) -c -I$(CTOPDIR)/byterun $*.c -o $*.$(O) + @$(CC) $(OC_CFLAGS) -c -I$(CTOPDIR)/runtime $*.c -o $*.$(O) .f.o: - @$(FORTRAN_COMPILER) -c -I$(CTOPDIR)/byterun $*.f -o $*.$(O) + @$(FORTRAN_COMPILER) -c -I$(CTOPDIR)/runtime $*.f -o $*.$(O) diff --git a/testsuite/makefiles/Makefile.dlambda b/testsuite/makefiles/Makefile.dlambda deleted file mode 100644 index eebd2436..00000000 --- a/testsuite/makefiles/Makefile.dlambda +++ /dev/null @@ -1,38 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Clerc, SED, INRIA Rocquencourt * -#* * -#* Copyright 2010 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -# To avoid tests breaking each time the internal name generation -# changes, we strip -dlambda-produced identifiers of their unique -# identifier: "x/1234" becomes simply "x". - -.PHONY: default -default: - @for file in *.ml; do \ - $(OCAMLC) -dlambda -c $$file 2>&1 | \ - sed -e "s|\\([A-Za-z_][A-Za-z_']*\)/[0-9][0-9]*|\\1|g" \ - > $$file.result; \ - done - @for file in *.reference; do \ - printf " ... testing '$$file':"; \ - $(DIFF) $$file `basename $$file reference`result >/dev/null \ - && echo " => passed" || echo " => failed"; \ - done - -.PHONY: promote -promote: defaultpromote - -.PHONY: clean -clean: defaultclean - @rm -f *.result diff --git a/testsuite/makefiles/Makefile.dparsetree b/testsuite/makefiles/Makefile.dparsetree deleted file mode 100644 index 7d1fcd0e..00000000 --- a/testsuite/makefiles/Makefile.dparsetree +++ /dev/null @@ -1,33 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Clerc, SED, INRIA Rocquencourt * -#* Jeremie Dimino, Jane Street Europe * -#* * -#* Copyright 2010 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -.PHONY: default -default: - @for file in *.ml; do \ - $(OCAMLC) -dparsetree -c $$file 2>$$file.result >/dev/null || true; \ - done - @for file in *.reference; do \ - printf " ... testing '$$file':"; \ - $(DIFF) $$file `basename $$file reference`result >/dev/null \ - && echo " => passed" || echo " => failed"; \ - done - -.PHONY: promote -promote: defaultpromote - -.PHONY: clean -clean: defaultclean - @rm -f *.result diff --git a/testsuite/makefiles/Makefile.expect b/testsuite/makefiles/Makefile.expect deleted file mode 100644 index 99e24014..00000000 --- a/testsuite/makefiles/Makefile.expect +++ /dev/null @@ -1,41 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Jeremie Dimino, Jane Street Europe * -#* * -#* Copyright 2016 Jane Street Group LLC * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -.PHONY: default -default: - @for file in *.ml; do \ - printf " ... testing '$$file':"; \ - TERM=dumb $(EXPECT_TEST) $(EXPECT_FLAGS) -repo-root $(OTOPDIR) $$file && \ - TERM=dumb $(EXPECT_TEST) $(EXPECT_FLAGS) -repo-root $(OTOPDIR) -principal \ - $$file.corrected && \ - mv $$file.corrected.corrected $$file.corrected && \ - $(DIFF) $$file $$file.corrected && \ - echo " => passed" || echo " => failed"; \ - done - -# Builds everything needed to run an expect test -.PHONY: deps -deps: - @$(MAKE) -C $(OTOPDIR) coldstart ocaml ocamlc - @$(MAKE) -C $(OTOPDIR)/testsuite/tools expect_test$(EXE) - -.PHONY: promote -promote: - @for file in *.corrected; do \ - cp $$file `basename $$file .corrected`; \ - done - -.PHONY: clean -clean: defaultclean - @rm -f *.corrected diff --git a/testsuite/makefiles/Makefile.okbad b/testsuite/makefiles/Makefile.okbad deleted file mode 100644 index d463181e..00000000 --- a/testsuite/makefiles/Makefile.okbad +++ /dev/null @@ -1,54 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Clerc, SED, INRIA Rocquencourt * -#* * -#* Copyright 2010 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -.PHONY: default -default: compile - -# See run-file in Makefile.several for the use of mktemp -.PHONY: compile -compile: - @for file in *.ml; do \ - printf " ... testing '$$file'"; \ - if [ `echo $$file | grep principal` ]; \ - then PRIN="-principal -w +18+19 -warn-error A"; \ - else PRIN=""; fi; \ - if [ `echo $$file | grep bad` ]; then \ - $(OCAMLC) -c -w a $$PRIN $$file 2>/dev/null \ - && echo " => failed" || echo " => passed"; \ - else \ - F="`basename $$file .ml`"; \ - test -f $$F.mli && $(OCAMLC) -c -w a $$PRIN $$F.mli; \ - $(OCAMLC) -c -w a $$PRIN $$file 2>/dev/null \ - && if [ -f $$F.reference ]; then \ - test -e program.byte.exe && { \ - T="`mktemp -p .`"; \ - mv -f program.byte.exe "$$T"; \ - rm -f "$$T"; \ - } ; \ - rm -f program.byte program.byte.exe; \ - $(OCAMLC) $$F.cmo -o program.byte$(EXE) \ - && $(OCAMLRUN) program.byte$(EXE) >$$F.result \ - && $(DIFF) $$F.reference $$F.result >/dev/null; \ - fi \ - && echo " => passed" || echo " => failed"; \ - fi; \ - done - -.PHONY: promote -promote: defaultpromote - -.PHONY: clean -clean: defaultclean - @rm -f program.byte program.byte.exe *.cm* *.result diff --git a/testsuite/makefiles/Makefile.one b/testsuite/makefiles/Makefile.one index c98fbb59..c6b797f1 100644 --- a/testsuite/makefiles/Makefile.one +++ b/testsuite/makefiles/Makefile.one @@ -32,7 +32,7 @@ CUSTOM_FLAG=`if [ -n "$(C_FILES)" ]; then echo '-custom'; fi` ADD_CFLAGS+=$(CUSTOM_FLAG) MYRUNTIME=`if [ -z "$(C_FILES)$(CUSTOM)" ]; then echo '$(OCAMLRUN)'; fi` -C_INCLUDES+=-I $(CTOPDIR)/byterun +C_INCLUDES+=-I $(CTOPDIR)/runtime .PHONY: default default: diff --git a/testsuite/makefiles/Makefile.several b/testsuite/makefiles/Makefile.several deleted file mode 100644 index 18604b24..00000000 --- a/testsuite/makefiles/Makefile.several +++ /dev/null @@ -1,154 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Clerc, SED, INRIA Rocquencourt * -#* * -#* Copyright 2010 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -FC=$(FORTAN_COMPILER) -CMO_FILES=$(MODULES:=.cmo) -CMX_FILES=$(MODULES:=.cmx) -CMA_FILES=$(LIBRARIES:=.cma) -CMXA_FILES=$(LIBRARIES:=.cmxa) -O_FILES=$(F_FILES:=.$(O)) $(C_FILES:=.$(O)) - -CUSTOM_FLAG=`if [ -n "$(C_FILES)" ]; then echo '-custom'; fi` -ADD_CFLAGS+=$(CUSTOM_FLAG) -MYRUNTIME=`if [ -z "$(C_FILES)$(CUSTOM)" ]; then echo '$(OCAMLRUN)'; echo '$(ADD_BYTERUN_FLAGS)'; fi` -FORTRAN_LIB=`if [ -n "$(F_FILES)" ]; then echo $(FORTRAN_LIBRARY); fi` -ADD_CFLAGS+=$(FORTRAN_LIB) -ADD_OPTFLAGS+=$(FORTRAN_LIB) - -C_INCLUDES+=-I $(CTOPDIR)/byterun -I $(CTOPDIR)/otherlibs/bigarray - -GENERATED_SOURCES= - -SKIP=false - -.PHONY: check -check: - @if [ -n "$(FORTRAN_COMPILER)" -o -z "$(F_FILES)" ]; then \ - $(SET_LD_PATH) $(MAKE) run-all; \ - else \ - $(MAKE) C_FILES= F_FILES= SKIP=true run-all; \ - fi - -.PHONY: run-all -run-all: - @for file in $(C_FILES); do \ - $(OCAMLC) -c $(C_INCLUDES) -c $$file.c; \ - done; - @for file in $(F_FILES); do \ - $(FORTRAN_COMPILER) -c $$file.f; \ - done; - @for file in *.ml; do \ - printf " ... testing '$$file':"; \ - if $(SKIP) ; then \ - echo " => skipped"; continue; \ - fi; \ - if [ -f `basename $$file ml`precheck ]; then \ - if ! TOOLCHAIN=$(TOOLCHAIN) sh `basename $$file ml`precheck ; then \ - echo " => skipped"; \ - continue; \ - fi; \ - fi; \ - if $(NATIVECODE_ONLY); then : ; else \ - $(MAKE) run-file DESC=ocamlc COMP='$(OCAMLC)' \ - RUNTIME='$(MYRUNTIME)' \ - COMPFLAGS='$(ADD_COMPFLAGS) $(ADD_CFLAGS) $(O_FILES) \ - $(CMA_FILES) -I $(OTOPDIR)/testsuite/lib \ - $(CMO_FILES)' \ - FILE=$$file PROGRAM_ARGS='$(PROGRAM_ARGS)'; \ - fi \ - && \ - if $(BYTECODE_ONLY); then : ; else \ - $(MAKE) run-file DESC=ocamlopt COMP='$(OCAMLOPT)' \ - RUNTIME= \ - COMPFLAGS='$(ADD_COMPFLAGS) $(ADD_OPTFLAGS) \ - $(O_FILES) $(CMXA_FILES) \ - -I $(OTOPDIR)/testsuite/lib $(CMX_FILES)' \ - FILE=$$file PROGRAM_ARGS='$(PROGRAM_ARGS)'; \ - fi \ - && \ - if [ -n "$(UNSAFE)" ]; then \ - $(MAKE) run-file DESC=ocamlc-unsafe COMP='$(OCAMLC)' \ - RUNTIME='$(MYRUNTIME)' \ - COMPFLAGS='-unsafe $(ADD_COMPFLAGS) $(ADD_CFLAGS) \ - $(O_FILES) $(CMA_FILES) \ - -I $(OTOPDIR)/testsuite/lib $(CMO_FILES)' \ - FILE=$$file \ - && \ - if $(BYTECODE_ONLY); then : ; else \ - $(MAKE) run-file DESC=ocamlopt-unsafe COMP='$(OCAMLOPT)' \ - RUNTIME= \ - COMPFLAGS='-unsafe $(ADD_COMPFLAGS) $(ADD_OPTFLAGS)\ - $(O_FILES) $(CMXA_FILES) \ - -I $(OTOPDIR)/testsuite/lib $(CMX_FILES)' \ - FILE=$$file; \ - fi; \ - fi \ - && echo " => passed" || echo " => failed"; \ - done - -# On Windows, nefarious software (specifically Windows Defender) can prevent -# executable files being deleted while it scans them. Unfortunately, it does -# this by allowing the delete system call (either via rm -f or cmd /c del) to -# complete with success but the file can linger for seconds or even minutes -# until it suddenly disappears. During this time, the file cannot be overwritten -# but it can be renamed, hence the odd use of mktemp. Some tests compiled with -# flambda seem to be consistently "interesting" to Windows Defender. Note that -# the interference doesn't appear to affect the execution of the tests. -.PHONY: run-file -run-file: - @printf " $(DESC)" - @test -e program.exe && { \ - T="`mktemp -p .`"; \ - mv -f program.exe "$$T"; \ - rm -f "$$T"; \ - } || true - @rm -f program program$(EXE) - @if [ -f "$(FILE).silent-compilation" ]; then \ - temp="$$(mktemp "$${TMPDIR:-/tmp}/ocaml-test-XXXXXXXX")"; \ - $(COMP) $(COMPFLAGS) $(FILE) -o program$(EXE) >$$temp 2>&1 ; \ - if [ -s "$$temp" ]; then \ - rm -f $$temp; \ - printf " Error: compilation wrote to stdout/stderr!\n"; \ - exit 1; \ - fi; \ - rm -f $$temp; \ - else \ - $(COMP) $(COMPFLAGS) $(FILE) -o program$(EXE); \ - fi - @F="`basename $(FILE) .ml`"; \ - if [ -f $$F.runner ]; then \ - RUNTIME="$(RUNTIME)" sh $$F.runner; \ - else \ - $(SET_LD_PATH) $(RUNTIME) ./program$(EXE) $(PROGRAM_ARGS) >$$F.result; \ - fi \ - && \ - if [ -f $$F.checker ]; then \ - DIFF="$(DIFF)" SORT="$(SORT)" sh $$F.checker || { \ - printf " Error: output checker failed!\n"; \ - exit 1; \ - }; \ - else \ - $(DIFF) $$F.reference $$F.result >/dev/null || { \ - printf " Error: results don't match reference output!\n"; \ - exit 1; \ - }; \ - fi - -.PHONY: promote -promote: defaultpromote - -.PHONY: clean -clean: defaultclean - @rm -f *.result program program.exe $(GENERATED_SOURCES) diff --git a/testsuite/makefiles/Makefile.toplevel b/testsuite/makefiles/Makefile.toplevel deleted file mode 100644 index ad5a4b37..00000000 --- a/testsuite/makefiles/Makefile.toplevel +++ /dev/null @@ -1,37 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Clerc, SED, INRIA Rocquencourt * -#* * -#* Copyright 2010 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -.PHONY: default -default: - @for file in *.ml; do \ - TERM=dumb $(OCAML) $(TOPFLAGS) <$$file 2>&1 \ - | grep -v '^ OCaml version' > $$file.result; \ - if [ -f $$file.principal.reference ]; then \ - TERM=dumb $(OCAML) $(TOPFLAGS) -principal <$$file 2>&1 \ - | grep -v '^ OCaml version' > $$file.principal.result; \ - fi; \ - done - @for file in *.reference; do \ - printf " ... testing '$$file':"; \ - $(DIFF) $$file `basename $$file reference`result >/dev/null \ - && echo " => passed" || echo " => failed"; \ - done - -.PHONY: promote -promote: defaultpromote - -.PHONY: clean -clean: defaultclean - @rm -f *.result diff --git a/testsuite/makefiles/summarize.awk b/testsuite/makefiles/summarize.awk index 97f214b6..b185c672 100644 --- a/testsuite/makefiles/summarize.awk +++ b/testsuite/makefiles/summarize.awk @@ -41,6 +41,14 @@ function record_skip() { clear(); } +function record_na() { + check(); + if (!(key in RESULTS)) ++nresults; + RESULTS[key] = "n"; + if (curdir in SKIPPED) SKIPPED[curdir] = 1; + clear(); +} + # The output cares only if the test passes at least once so if a test passes, # but then fails in a re-run triggered by a different test, ignore it. function record_fail() { @@ -105,6 +113,10 @@ function record_unexp() { record_skip(); } +/=> n\/a/ { + record_na(); +} + /=> failed/ { record_fail(); } @@ -157,22 +169,18 @@ END { }else{ skips[skipidx++] = key; } + }else if (r == "n"){ + ++ ignored; } } printf("\n"); - printf("Summary:\n"); - printf(" %3d tests passed\n", passed); - printf(" %3d tests skipped\n", skipped); - printf(" %3d tests failed\n", failed); - printf(" %3d unexpected errors\n", unexped); - printf(" %3d tests considered", nresults); - if (nresults == passed + skipped + failed + unexped){ - printf ("\n"); - }else{ - printf (" (totals don't add up??)"); + if (skipped != 0){ + printf("\nList of skipped tests:\n"); + for (i=0; i < skipidx; i++) printf(" %s\n", skips[i]); } - if (reran != 0){ - printf(" %3d test dir re-runs\n", reran); + if (empty != 0){ + printf("\nList of directories returning no results:\n"); + for (i=0; i < empty; i++) printf(" %s\n", blanks[i]); } if (failed != 0){ printf("\nList of failed tests:\n"); @@ -182,15 +190,22 @@ END { printf("\nList of unexpected errors:\n"); for (i=0; i < unexped; i++) printf(" %s\n", unexp[i]); } - if (skipped != 0){ - printf("\nList of skipped tests:\n"); - for (i=0; i < skipidx; i++) printf(" %s\n", skips[i]); + printf("\n"); + printf("Summary:\n"); + printf(" %3d tests passed\n", passed); + printf(" %3d tests skipped\n", skipped); + printf(" %3d tests failed\n", failed); + printf(" %3d tests not started (parent test skipped or failed)\n", + ignored); + printf(" %3d unexpected errors\n", unexped); + printf(" %3d tests considered", nresults); + if (nresults != passed + skipped + ignored + failed + unexped){ + printf (" (totals don't add up??)"); } - if (empty != 0){ - printf("\nList of directories returning no results:\n"); - for (i=0; i < empty; i++) printf(" %s\n", blanks[i]); + printf ("\n"); + if (reran != 0){ + printf(" %3d test dir re-runs\n", reran); } - printf("\n"); if (failed || unexped){ printf("#### Something failed. Exiting with error status.\n\n"); exit 4; diff --git a/testsuite/tests/afl-instrumentation/afltest.ml b/testsuite/tests/afl-instrumentation/afltest.ml index b8a67b34..630990a3 100644 --- a/testsuite/tests/afl-instrumentation/afltest.ml +++ b/testsuite/tests/afl-instrumentation/afltest.ml @@ -1,17 +1,16 @@ (* TEST (* Just a test-driver *) * native-compiler - ** no-afl-instrument - *** script + ** script script = "sh ${test_source_directory}/has-afl-showmap.sh" files = "harness.ml test.ml" - **** setup-ocamlopt.byte-build-env - ***** ocamlopt.byte + *** setup-ocamlopt.byte-build-env + **** ocamlopt.byte module = "test.ml" flags = "-afl-instrument" - ****** ocamlopt.byte - module = "" + ***** ocamlopt.byte + module = "" program = "${test_build_directory}/test" flags = "-afl-inst-ratio 0" all_modules = "test.cmx harness.ml" - ******* run + ****** run *) diff --git a/testsuite/tests/afl-instrumentation/afltest.run b/testsuite/tests/afl-instrumentation/afltest.run index eb495145..6e84cdbe 100755 --- a/testsuite/tests/afl-instrumentation/afltest.run +++ b/testsuite/tests/afl-instrumentation/afltest.run @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e @@ -29,7 +29,7 @@ for t in `seq 1 $NTESTS`; do done if [ -z "$failures" ]; then - echo "all tests passed"; + echo "all tests passed"; exit ${TEST_PASS} else exit ${TEST_FAIL}; diff --git a/testsuite/tests/afl-instrumentation/harness.ml b/testsuite/tests/afl-instrumentation/harness.ml index dbcbebf0..dddbec36 100644 --- a/testsuite/tests/afl-instrumentation/harness.ml +++ b/testsuite/tests/afl-instrumentation/harness.ml @@ -13,10 +13,15 @@ let () = reset_instrumentation true; begin match Sys.argv with - | [| _; "len" |] -> print_int (Array.length Test.tests); print_newline (); flush stdout + | [| _; "len" |] -> + print_int (Array.length Test.tests); print_newline (); flush stdout | [| _; "name"; n |] -> print_string (name n); flush stdout | [| _; "1"; n |] -> run n - | [| _; "2"; n |] -> run n; (* Random.set_state orig_random; *)reset_instrumentation false; run n + | [| _; "2"; n |] -> + run n; + (* Random.set_state orig_random; *) + reset_instrumentation false; + run n | _ -> failwith "error" end; sys_exit 0 diff --git a/testsuite/tests/afl-instrumentation/test.ml b/testsuite/tests/afl-instrumentation/test.ml index 83c1fc00..63f0a205 100644 --- a/testsuite/tests/afl-instrumentation/test.ml +++ b/testsuite/tests/afl-instrumentation/test.ml @@ -60,6 +60,13 @@ let random () = opaque @@ if Random.int 100 < 50 then print_string "a" else print_string "b"; if Random.int 100 < 50 then print_string "a" else print_string "b" +let already_forced = lazy (ref 42) +let _ = Lazy.force already_forced + +let laziness () = opaque @@ + let _ = Lazy.force already_forced in + Gc.major () + let tests = [| ("lists", fun () -> lists 42); ("manylists", fun () -> for i = 1 to 10 do lists 42 done); @@ -69,5 +76,5 @@ let tests = ("classes", fun () -> classes 42); ("obj_ordering", obj_ordering); (* ("random", random); *) + ("laziness", laziness); |] - diff --git a/testsuite/tests/asmcomp/is_static_flambda.ml b/testsuite/tests/asmcomp/is_static_flambda.ml index de395c69..7ddf7e92 100644 --- a/testsuite/tests/asmcomp/is_static_flambda.ml +++ b/testsuite/tests/asmcomp/is_static_flambda.ml @@ -67,9 +67,9 @@ let i () = let () = (i [@inlined never]) () -module type P = module type of Pervasives +module type P = module type of Stdlib (* Top-level modules should be static *) -let () = assert(is_in_static_data (module Pervasives:P)) +let () = assert(is_in_static_data (module Stdlib:P)) (* Not constant let rec to test extraction to initialize_symbol *) let r = ref 0 diff --git a/testsuite/tests/asmcomp/register_typing.ml b/testsuite/tests/asmcomp/register_typing.ml index af8501c1..3bf3104f 100644 --- a/testsuite/tests/asmcomp/register_typing.ml +++ b/testsuite/tests/asmcomp/register_typing.ml @@ -19,6 +19,6 @@ let g (t : int list typ) x = let x = f t ([x; x; x; x; x]) in Gc.minor (); allocate_garbage (); - ignore (String.length (String.concat " " (List.map string_of_int x))) + ignore (String.length (String.concat " " (List.map Int.to_string x))) let () = g Ptr 5 diff --git a/testsuite/tests/asmcomp/register_typing_switch.ml b/testsuite/tests/asmcomp/register_typing_switch.ml index a5cfe3f8..73960c4b 100644 --- a/testsuite/tests/asmcomp/register_typing_switch.ml +++ b/testsuite/tests/asmcomp/register_typing_switch.ml @@ -20,6 +20,6 @@ let g (t : int list typ) x = let x = f t ([x; x; x; x; x]) in Gc.minor (); allocate_garbage (); - ignore (String.length (String.concat " " (List.map string_of_int x))) + ignore (String.length (String.concat " " (List.map Int.to_string x))) let () = g Ptr 5 diff --git a/testsuite/tests/asmcomp/staticalloc.ml b/testsuite/tests/asmcomp/staticalloc.ml index 2092ecc6..16eae1d4 100644 --- a/testsuite/tests/asmcomp/staticalloc.ml +++ b/testsuite/tests/asmcomp/staticalloc.ml @@ -16,10 +16,11 @@ let () = let pair x y = (x, y) in let a = pair 1 2 in let b = pair a ["x";"y"] in - let g () = (a, fst b) in + let[@local never] g () = (a, fst b) in assert (g () == ((1,2), (1,2))); assert (fst (pair a a) == (1, 2)); - assert (snd b != ["x"; "y"] || Config.safe_string); (* mutable "constant", cannot be shared *) + assert (snd b != ["x"; "y"] || Config.safe_string); (* mutable "constant", + cannot be shared *) let x2 = Gc.allocated_bytes () in assert(x1 -. x0 = x2 -. x1) (* check that we did not allocated anything between x1 and x2 *) diff --git a/testsuite/tests/asmgen/Makefile b/testsuite/tests/asmgen/Makefile deleted file mode 100644 index f6d0c238..00000000 --- a/testsuite/tests/asmgen/Makefile +++ /dev/null @@ -1,122 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Clerc, SED, INRIA Rocquencourt * -#* * -#* Copyright 2010 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -BASEDIR=../.. - -include $(BASEDIR)/../config/Makefile - -INCLUDES=\ - -I $(OTOPDIR)/parsing \ - -I $(OTOPDIR)/utils \ - -I $(OTOPDIR)/typing \ - -I $(OTOPDIR)/middle_end \ - -I $(OTOPDIR)/bytecomp \ - -I $(OTOPDIR)/asmcomp - -OTHEROBJS=\ - $(OTOPDIR)/compilerlibs/ocamlcommon.cma \ - $(OTOPDIR)/compilerlibs/ocamloptcomp.cma - -OBJS=parsecmmaux.cmo parsecmm.cmo lexcmm.cmo - -ADD_COMPFLAGS=$(INCLUDES) -w -40 -g - -default: - @if $(BYTECODE_ONLY) || $(SKIP) ; then $(MAKE) skips ; else \ - $(MAKE) all; \ - fi - -all: - @$(MAKE) arch codegen - @$(MAKE) tests - -main.cmo: parsecmm.cmo - -codegen: parsecmm.ml lexcmm.ml $(OBJS:.cmo=.cmi) $(OBJS) main.cmo - @$(OCAMLC) $(LINKFLAGS) -o codegen $(OTHEROBJS) $(OBJS) main.cmo - -parsecmm.mli parsecmm.ml: parsecmm.mly - @$(OCAMLYACC) -q parsecmm.mly - -lexcmm.ml: lexcmm.mll - @$(OCAMLLEX) -q lexcmm.mll - -CASES=fib tak quicksort quicksort2 soli \ - arith checkbound tagged-fib tagged-integr tagged-quicksort tagged-tak \ - catch-try catch-rec even-odd even-odd-spill pgcd -ARGS_fib=-DINT_INT -DFUN=fib main.c -ARGS_tak=-DUNIT_INT -DFUN=takmain main.c -ARGS_quicksort=-DSORT -DFUN=quicksort main.c -ARGS_quicksort2=-DSORT -DFUN=quicksort main.c -ARGS_soli=-DUNIT_INT -DFUN=solitaire main.c -ARGS_integr=-DINT_FLOAT -DFUN=test main.c -ARGS_arith=mainarith.c -ARGS_checkbound=-DCHECKBOUND main.c -ARGS_tagged-fib=-DINT_INT -DFUN=fib main.c -ARGS_tagged-integr=-DINT_FLOAT -DFUN=test main.c -ARGS_tagged-quicksort=-DSORT -DFUN=quicksort main.c -ARGS_tagged-tak=-DUNIT_INT -DFUN=takmain main.c -ARGS_catch-try=-DINT_INT -DFUN=catch_exit main.c -ARGS_catch-rec=-DINT_INT -DFUN=catch_fact main.c -ARGS_even-odd=-DINT_INT -DFUN=is_even main.c -ARGS_even-odd-spill=-DINT_INT -DFUN=is_even main.c -ARGS_pgcd=-DINT_INT -DFUN=pgcd_30030 main.c - -skips: - @for c in $(CASES); do \ - echo " ... testing '$$c': => skipped"; \ - done - -one: - @$(call CCOMP,$(NAME).out $(ARGS_$(NAME)) $(NAME).$(O) $(ARCH).$(O)) \ - && echo " => passed" || echo " => failed" - -clean: defaultclean - @rm -f ./codegen *.out *.out.manifest *.$(O) *.exe - @rm -f parsecmm.ml parsecmm.mli lexcmm.ml - @rm -f $(CASES:=.s) - -include $(BASEDIR)/makefiles/Makefile.common - -ifeq "$(CCOMPTYPE)-$(ARCH)" "msvc-amd64" -# these tests are not ported to MSVC64 yet -SKIP=true -else -SKIP=false -endif - -ifeq "$(WITH_SPACETIME)" "true" -# These tests have not been ported for Spacetime -SKIP=true -endif - -ifeq ($(CCOMPTYPE),msvc) -CCOMP=set -o pipefail ; $(CC) $(CFLAGS) /Fe$(1) | tail -n +2 -else -CCOMP=$(CC) $(CFLAGS) -o $(1) -endif -tests: $(CASES:=.$(O)) - @for c in $(CASES); do \ - printf " ... testing '$$c':"; \ - $(MAKE) one NAME=$$c; \ - done - -promote: - -arch: $(ARCH).$(O) - -i386.obj: i386nt.asm - @set -o pipefail ; \ - $(ASM) $@ $^ | tail -n +2 diff --git a/testsuite/tests/asmgen/arith.cmm b/testsuite/tests/asmgen/arith.cmm index 09156568..fad3f29f 100644 --- a/testsuite/tests/asmgen/arith.cmm +++ b/testsuite/tests/asmgen/arith.cmm @@ -1,3 +1,9 @@ +(* TEST +files = "mainarith.c" +arguments = "mainarith.c" +* asmgen +*) + (**************************************************************************) (* *) (* OCaml *) diff --git a/testsuite/tests/asmgen/catch-float.cmm b/testsuite/tests/asmgen/catch-float.cmm new file mode 100644 index 00000000..9d1d1683 --- /dev/null +++ b/testsuite/tests/asmgen/catch-float.cmm @@ -0,0 +1,11 @@ +(* TEST +files = "main.c" +arguments = "-DFLOAT_CATCH -DFUN=catch_float main.c" +* asmgen +*) + +(function "catch_float" (b:int) + (+f 10.0 + (catch + (exit lbl 100.0) + with (lbl x:float) (+f x 1000.0)))) diff --git a/testsuite/tests/asmgen/catch-rec.cmm b/testsuite/tests/asmgen/catch-rec.cmm index 69208f5f..17f9884a 100644 --- a/testsuite/tests/asmgen/catch-rec.cmm +++ b/testsuite/tests/asmgen/catch-rec.cmm @@ -1,5 +1,11 @@ +(* TEST +files = "main.c" +arguments = "-DINT_INT -DFUN=catch_fact main.c" +* asmgen +*) + (function "catch_fact" (b:int) (catch (exit fact b 1) - with (fact c acc) + with (fact c:val acc:val) (if (== c 0) acc (exit fact (- c 1) ( * c acc))))) diff --git a/testsuite/tests/asmgen/catch-try-float.cmm b/testsuite/tests/asmgen/catch-try-float.cmm new file mode 100644 index 00000000..23287298 --- /dev/null +++ b/testsuite/tests/asmgen/catch-try-float.cmm @@ -0,0 +1,12 @@ +(* TEST +files = "main.c" +arguments = "-DFLOAT_CATCH -DFUN=catch_try_float main.c" +* asmgen +*) + +(function "catch_try_float" (b:float) + (+f 10.0 + (catch + (try (exit lbl 100.0) + with var 456.0) + with (lbl x:float) (+f x 1000.0)))) diff --git a/testsuite/tests/asmgen/catch-try.cmm b/testsuite/tests/asmgen/catch-try.cmm index bbbdc387..7537c656 100644 --- a/testsuite/tests/asmgen/catch-try.cmm +++ b/testsuite/tests/asmgen/catch-try.cmm @@ -1,7 +1,12 @@ +(* TEST +files = "main.c" +arguments = "-DINT_INT -DFUN=catch_exit main.c" +* asmgen +*) (function "catch_exit" (b:int) (+ 33 (catch (try (exit lbl 12) with var 456) - with (lbl x) (+ x 789)))) + with (lbl x:val) (+ x 789)))) diff --git a/testsuite/tests/asmgen/checkbound.cmm b/testsuite/tests/asmgen/checkbound.cmm index 35206f25..0b864d5b 100644 --- a/testsuite/tests/asmgen/checkbound.cmm +++ b/testsuite/tests/asmgen/checkbound.cmm @@ -1,3 +1,9 @@ +(* TEST +files = "main.c" +arguments = "-DCHECKBOUND main.c" +* asmgen +*) + (**************************************************************************) (* *) (* OCaml *) diff --git a/testsuite/tests/asmgen/even-odd-spill-float.cmm b/testsuite/tests/asmgen/even-odd-spill-float.cmm new file mode 100644 index 00000000..1603aa80 --- /dev/null +++ b/testsuite/tests/asmgen/even-odd-spill-float.cmm @@ -0,0 +1,27 @@ +(* TEST +files = "main.c" +arguments = "-DINT_FLOAT -DFUN=is_even main.c" +* asmgen +*) + +("format_odd": string "odd %d\n\000") +("format_even": string "even %d\n\000") + +(function "force_spill" (a:int) 0) +(function "force_spill_float" (f:float) 0.0) + +(function "is_even" (b:int) + (catch (exit even b 0.0) + with (odd v:val f:float) + (if (== v 0) f + (seq + (extcall "printf_int" "format_odd" v unit) + (let v2 (- v 1) + (app "force_spill" 0 int) + (app "force_spill_float" 0.0 float) + (exit even v2 (+f 1.0 f))))) + and (even v:val f:float) + (if (== v 0) f + (seq + (extcall "printf_int" "format_even" v unit) + (exit odd (- v 1) (+f 1.0 f)))))) diff --git a/testsuite/tests/asmgen/even-odd-spill.cmm b/testsuite/tests/asmgen/even-odd-spill.cmm index 0c5f0558..f0b9a70f 100644 --- a/testsuite/tests/asmgen/even-odd-spill.cmm +++ b/testsuite/tests/asmgen/even-odd-spill.cmm @@ -1,3 +1,9 @@ +(* TEST +files = "main.c" +arguments = "-DINT_INT -DFUN=is_even main.c" +* asmgen +*) + ("format_odd": string "odd %d\n\000") ("format_even": string "even %d\n\000") @@ -5,14 +11,14 @@ (function "is_even" (b:int) (catch (exit even b) - with (odd v) + with (odd v:val) (if (== v 0) 0 (seq (extcall "printf_int" "format_odd" v unit) (let v2 (- v 1) (app "force_spill" 0 int) (exit even v2)))) - and (even v) + and (even v:val) (if (== v 0) 1 (seq (extcall "printf_int" "format_even" v unit) diff --git a/testsuite/tests/asmgen/even-odd.cmm b/testsuite/tests/asmgen/even-odd.cmm index db79f1ca..adf0d0b8 100644 --- a/testsuite/tests/asmgen/even-odd.cmm +++ b/testsuite/tests/asmgen/even-odd.cmm @@ -1,8 +1,14 @@ +(* TEST +files= "main.c" +arguments = "-DINT_INT -DFUN=is_even main.c" +* asmgen +*) + (function "is_even" (b:int) (catch (exit even b) - with (odd v) + with (odd v:val) (if (== v 0) 0 (exit even (- v 1))) - and (even v) + and (even v:val) (if (== v 0) 1 - (exit odd (- v 1))))) \ No newline at end of file + (exit odd (- v 1))))) diff --git a/testsuite/tests/asmgen/fib.cmm b/testsuite/tests/asmgen/fib.cmm index 49de4ba1..c1a82de2 100644 --- a/testsuite/tests/asmgen/fib.cmm +++ b/testsuite/tests/asmgen/fib.cmm @@ -1,3 +1,9 @@ +(* TEST +files = "main.c" +arguments = "-DINT_INT -DFUN=fib main.c" +* asmgen +*) + (**************************************************************************) (* *) (* OCaml *) diff --git a/testsuite/tests/asmgen/i386.S b/testsuite/tests/asmgen/i386.S deleted file mode 100644 index 26dc83fc..00000000 --- a/testsuite/tests/asmgen/i386.S +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* Linux with ELF binaries does not prefix identifiers with _. - Linux with a.out binaries, FreeBSD, and NextStep do. */ - -#if defined(SYS_linux_elf) || defined(SYS_bsd_elf) \ - || defined(SYS_solaris) || defined(SYS_beos) || defined(SYS_gnu) -#define G(x) x -#define FUNCTION_ALIGN 16 -#else -#define G(x) _##x -#define FUNCTION_ALIGN 4 -#endif - - .globl G(call_gen_code) - .align FUNCTION_ALIGN -G(call_gen_code): - pushl %ebp - movl %esp,%ebp - pushl %ebx - pushl %esi - pushl %edi - movl 12(%ebp),%eax - movl 16(%ebp),%ebx - movl 20(%ebp),%ecx - movl 24(%ebp),%edx - call *8(%ebp) - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - - .globl G(caml_c_call) - .align FUNCTION_ALIGN -G(caml_c_call): - jmp *%eax - - .comm G(caml_exception_pointer), 4 - .comm G(young_ptr), 4 - .comm G(young_start), 4 - -#if defined(SYS_linux_elf) - /* Mark stack as non-executable */ - .section .note.GNU-stack,"",%progbits -#endif diff --git a/testsuite/tests/asmgen/i386nt.asm b/testsuite/tests/asmgen/i386nt.asm deleted file mode 100644 index 618d41c9..00000000 --- a/testsuite/tests/asmgen/i386nt.asm +++ /dev/null @@ -1,65 +0,0 @@ -;*********************************************************************; -; ; -; OCaml ; -; ; -; Xavier Leroy, projet Cristal, INRIA Rocquencourt ; -; ; -; Copyright 1996 Institut National de Recherche en Informatique et ; -; en Automatique. All rights reserved. This file is distributed ; -; under the terms of the Q Public License version 1.0. ; -; ; -;*********************************************************************; - - .386 - .MODEL FLAT - - .CODE - PUBLIC _call_gen_code - ALIGN 4 -_call_gen_code: - push ebp - mov ebp, esp - push ebx - push esi - push edi - mov eax, [ebp+12] - mov ebx, [ebp+16] - mov ecx, [ebp+20] - mov edx, [ebp+24] - call DWORD PTR [ebp+8] - pop edi - pop esi - pop ebx - pop ebp - ret - - PUBLIC _caml_c_call - ALIGN 4 -_caml_c_call: - ffree st(0) - ffree st(1) - ffree st(2) - ffree st(3) - jmp eax - - PUBLIC _caml_call_gc - PUBLIC _caml_alloc - PUBLIC _caml_alloc1 - PUBLIC _caml_alloc2 - PUBLIC _caml_alloc3 -_caml_call_gc: -_caml_alloc: -_caml_alloc1: -_caml_alloc2: -_caml_alloc3: - int 3 - - .DATA - PUBLIC _caml_exception_pointer -_caml_exception_pointer dword 0 - PUBLIC _young_ptr -_young_ptr dword 0 - PUBLIC _young_limit -_young_limit dword 0 - - END diff --git a/testsuite/tests/asmgen/integr.cmm b/testsuite/tests/asmgen/integr.cmm index c82d60b2..84a3895c 100644 --- a/testsuite/tests/asmgen/integr.cmm +++ b/testsuite/tests/asmgen/integr.cmm @@ -1,3 +1,11 @@ +(* TEST +files = "main.c" +arguments = "-DINT_FLOAT -DFUN=test main.c" +* skip +reason = "This test is currently broken" +** asmgen +*) + (**************************************************************************) (* *) (* OCaml *) diff --git a/testsuite/tests/asmgen/lexcmm.mli b/testsuite/tests/asmgen/lexcmm.mli deleted file mode 100644 index f9fe6afa..00000000 --- a/testsuite/tests/asmgen/lexcmm.mli +++ /dev/null @@ -1,10 +0,0 @@ -val token: Lexing.lexbuf -> Parsecmm.token - -type error = - Illegal_character - | Unterminated_comment - | Unterminated_string - -exception Error of error - -val report_error: Lexing.lexbuf -> error -> unit diff --git a/testsuite/tests/asmgen/lexcmm.mll b/testsuite/tests/asmgen/lexcmm.mll deleted file mode 100644 index 81eab9d0..00000000 --- a/testsuite/tests/asmgen/lexcmm.mll +++ /dev/null @@ -1,245 +0,0 @@ -{ -open Parsecmm - -type error = - Illegal_character - | Unterminated_comment - | Unterminated_string - -exception Error of error - -(* For nested comments *) - -let comment_depth = ref 0 - -(* The table of keywords *) - -let keyword_table = - Misc.create_hashtable 149 [ - "absf", ABSF; - "addr", ADDR; - "align", ALIGN; - "alloc", ALLOC; - "and", AND; - "app", APPLY; - "assign", ASSIGN; - "byte", BYTE; - "case", CASE; - "catch", CATCH; - "checkbound", CHECKBOUND; - "data", DATA; - "exit", EXIT; - "extcall", EXTCALL; - "float", FLOAT; - "float32", FLOAT32; - "float64", FLOAT64; - "floatofint", FLOATOFINT; - "function", FUNCTION; - "global", GLOBAL; - "half", HALF; - "if", IF; - "int", INT; - "int32", INT32; - "intoffloat", INTOFFLOAT; - "string", KSTRING; - "let", LET; - "load", LOAD; - "mod", MODI; - "mulh", MULH; - "or", OR; - "proj", PROJ; - "raise_withtrace", RAISE Cmm.Raise_withtrace; - "raise_notrace", RAISE Cmm.Raise_notrace; - "seq", SEQ; - "signed", SIGNED; - "skip", SKIP; - "store", STORE; - "switch", SWITCH; - "try", TRY; - "unit", UNIT; - "unsigned", UNSIGNED; - "val", VAL; - "while", WHILE; - "with", WITH; - "xor", XOR; - "addraref", ADDRAREF; - "intaref", INTAREF; - "floataref", FLOATAREF; - "addraset", ADDRASET; - "intaset", INTASET; - "floataset", FLOATASET -] - -(* To buffer string literals *) - -let initial_string_buffer = Bytes.create 256 -let string_buff = ref initial_string_buffer -let string_index = ref 0 - -let reset_string_buffer () = - string_buff := initial_string_buffer; - string_index := 0 - -let store_string_char c = - if !string_index >= Bytes.length (!string_buff) then begin - let new_buff = Bytes.create (Bytes.length (!string_buff) * 2) in - Bytes.blit (!string_buff) 0 new_buff 0 (Bytes.length (!string_buff)); - string_buff := new_buff - end; - Bytes.unsafe_set (!string_buff) (!string_index) c; - incr string_index - -let get_stored_string () = - let s = Bytes.sub_string (!string_buff) 0 (!string_index) in - string_buff := initial_string_buffer; - s - -(* To translate escape sequences *) - -let char_for_backslash = function - 'n' -> '\010' - | 'r' -> '\013' - | 'b' -> '\008' - | 't' -> '\009' - | c -> c - -let char_for_decimal_code lexbuf i = - Char.chr(100 * (Char.code(Lexing.lexeme_char lexbuf i) - 48) + - 10 * (Char.code(Lexing.lexeme_char lexbuf (i+1)) - 48) + - (Char.code(Lexing.lexeme_char lexbuf (i+2)) - 48)) - -(* Error report *) - -let report_error lexbuf msg = - prerr_string "Lexical error around character "; - prerr_int (Lexing.lexeme_start lexbuf); - match msg with - Illegal_character -> - prerr_string ": illegal character" - | Unterminated_comment -> - prerr_string ": unterminated comment" - | Unterminated_string -> - prerr_string ": unterminated string" - -} - -let newline = ('\013'* '\010') - -rule token = parse - newline - { Lexing.new_line lexbuf; token lexbuf } - | [' ' '\009' '\012'] + - { token lexbuf } - | "+a" { ADDA } - | "+v" { ADDV } - | "+f" { ADDF } - | "+" { ADDI } - | ">>s" { ASR } - | ":" { COLON } - | "/f" { DIVF } - | "/" { DIVI } - | eof { EOF } - | "==a" { EQA } - | "==f" { EQF } - | "==" { EQI } - | ">=a" { GEA } - | ">=f" { GEF } - | ">=" { GEI } - | ">a" { GTA } - | ">f" { GTF } - | ">" { GTI } - | "[" { LBRACKET } - | "<=a" { LEA } - | "<=f" { LEF } - | "<=" { LEI } - | "(" { LPAREN } - | "<<" { LSL } - | ">>u" { LSR } - | "=f" { NGEF } - | "!>f" { NGTF } - | "!<=f" { NLEF } - | "! - IDENT s } - | "\"" - { reset_string_buffer(); - string lexbuf; - STRING (get_stored_string()) } - | "(*" - { comment_depth := 1; - comment lexbuf; - token lexbuf } - | '{' ['A' - 'Z' 'a'-'z' '/' ',' '.' '-' '_' ' ''0'-'9']+ - ':' [ '0'-'9' ]+ ',' ['0'-'9' ]+ '-' ['0'-'9' ]+ '}' - { - let loc_s = Lexing.lexeme lexbuf in - let pos_fname, pos_lnum, start, end_ = - Scanf.sscanf loc_s "{%s@:%i,%i-%i}" (fun file line start end_ -> - (file, line, start, end_)) - in - let loc_start = - Lexing.{ pos_fname; pos_lnum; pos_bol = 0; pos_cnum = start } - in - let loc_end = - Lexing.{ pos_fname; pos_lnum; pos_bol = 0; pos_cnum = end_ } - in - let location = Location.{ loc_start; loc_end; loc_ghost = false } in - LOCATION location } - | _ { raise(Error(Illegal_character)) } - -and comment = parse - "(*" - { comment_depth := succ !comment_depth; comment lexbuf } - | "*)" - { comment_depth := pred !comment_depth; - if !comment_depth > 0 then comment lexbuf } - | eof - { raise (Error(Unterminated_comment)) } - | newline - { Lexing.new_line lexbuf; comment lexbuf } - | _ - { comment lexbuf } - -and string = parse - '"' - { () } - | '\\' [' ' '\010' '\013' '\009' '\026' '\012'] + - { string lexbuf } - | '\\' ['\\' '"' 'n' 't' 'b' 'r'] - { store_string_char(char_for_backslash(Lexing.lexeme_char lexbuf 1)); - string lexbuf } - | '\\' ['0'-'9'] ['0'-'9'] ['0'-'9'] - { store_string_char(char_for_decimal_code lexbuf 1); - string lexbuf } - | eof - { raise (Error(Unterminated_string)) } - | _ - { store_string_char(Lexing.lexeme_char lexbuf 0); - string lexbuf } - diff --git a/testsuite/tests/asmgen/main.c b/testsuite/tests/asmgen/main.c index 5f305731..103e022b 100644 --- a/testsuite/tests/asmgen/main.c +++ b/testsuite/tests/asmgen/main.c @@ -34,6 +34,16 @@ void printf_int(char * fmt, int arg) printf(fmt, arg); } +#define FLOATTEST(arg,res) \ + { double result = (res); \ + if (arg < result || arg > result) { \ + printf("Failed test \"%s == %s\": " \ + "result %.15g, expected %.15g\n", \ + #arg, #res, arg, result); \ + return(2); \ + } \ + } + #ifdef SORT int cmpint(const void * i, const void * j) @@ -71,6 +81,14 @@ int main(int argc, char **argv) printf("%f\n", call_gen_code(FUN, atoi(argv[1]))); } #endif +#ifdef FLOAT_CATCH + { extern double FUN(long); + extern double call_gen_code(double (*)(long), long); + double result = call_gen_code(FUN, 1); + FLOATTEST(result, 1110.0) + printf("%f\n", result); + } +#endif #ifdef SORT { extern void FUN(long, long, long *); extern void call_gen_code(void (*)(long, long, long *), long, long, long *); diff --git a/testsuite/tests/asmgen/main.ml b/testsuite/tests/asmgen/main.ml deleted file mode 100644 index 6970f99a..00000000 --- a/testsuite/tests/asmgen/main.ml +++ /dev/null @@ -1,66 +0,0 @@ -open Clflags -let write_asm_file = ref false - -let compile_file filename = - if !write_asm_file then begin - let out_name = Filename.chop_extension filename ^ ".s" in - Emitaux.output_channel := open_out out_name - end; (* otherwise, stdout *) - Compilenv.reset "test"; - Emit.begin_assembly(); - let ic = open_in filename in - let lb = Lexing.from_channel ic in - lb.Lexing.lex_curr_p <- { lb.Lexing.lex_curr_p with pos_fname = filename }; - try - while true do - Asmgen.compile_phrase Format.std_formatter - (Parsecmm.phrase Lexcmm.token lb) - done - with - End_of_file -> - close_in ic; Emit.end_assembly(); - if !write_asm_file then close_out !Emitaux.output_channel - | Lexcmm.Error msg -> - close_in ic; Lexcmm.report_error lb msg - | Parsing.Parse_error -> - close_in ic; - let start_p = Lexing.lexeme_start_p lb in - let end_p = Lexing.lexeme_end_p lb in - Printf.eprintf "File \"%s\", line %i, characters %i-%i:\n\ - Syntax error.\n%!" - filename - start_p.Lexing.pos_lnum - (start_p.Lexing.pos_cnum - start_p.Lexing.pos_bol) - (end_p.Lexing.pos_cnum - start_p.Lexing.pos_bol) - | Parsecmmaux.Error msg -> - close_in ic; Parsecmmaux.report_error msg - | x -> - close_in ic; raise x - -let usage = "Usage: codegen \noptions are:" - -let main() = - Arg.parse [ - "-S", Arg.Set write_asm_file, - " Output file to filename.s (default is stdout)"; - "-g", Arg.Set Clflags.debug, ""; - "-dcmm", Arg.Set dump_cmm, ""; - "-dcse", Arg.Set dump_cse, ""; - "-dsel", Arg.Set dump_selection, ""; - "-dlive", Arg.Unit(fun () -> dump_live := true; - Printmach.print_live := true), ""; - "-dspill", Arg.Set dump_spill, ""; - "-dsplit", Arg.Set dump_split, ""; - "-dinterf", Arg.Set dump_interf, ""; - "-dprefer", Arg.Set dump_prefer, ""; - "-dalloc", Arg.Set dump_regalloc, ""; - "-dreload", Arg.Set dump_reload, ""; - "-dscheduling", Arg.Set dump_scheduling, ""; - "-dlinear", Arg.Set dump_linear, ""; - "-dtimings", Arg.Unit (fun () -> profile_columns := [ `Time ]), ""; - ] compile_file usage - -let () = - main (); - Profile.print Format.std_formatter !Clflags.profile_columns; - exit 0 diff --git a/testsuite/tests/asmgen/mainarith.c b/testsuite/tests/asmgen/mainarith.c index de876bfe..cdba6a9d 100644 --- a/testsuite/tests/asmgen/mainarith.c +++ b/testsuite/tests/asmgen/mainarith.c @@ -19,7 +19,7 @@ #include #include -#include "../../../byterun/caml/config.h" +#include #define FMT ARCH_INTNAT_PRINTF_FORMAT void caml_ml_array_bound_error(void) diff --git a/testsuite/tests/asmgen/ocamltests b/testsuite/tests/asmgen/ocamltests new file mode 100644 index 00000000..e0edd3ae --- /dev/null +++ b/testsuite/tests/asmgen/ocamltests @@ -0,0 +1,20 @@ +arith.cmm +catch-rec.cmm +catch-try.cmm +catch-float.cmm +catch-try-float.cmm +checkbound.cmm +even-odd-spill.cmm +even-odd-spill-float.cmm +even-odd.cmm +fib.cmm +integr.cmm +pgcd.cmm +quicksort.cmm +quicksort2.cmm +soli.cmm +tagged-fib.cmm +tagged-integr.cmm +tagged-quicksort.cmm +tagged-tak.cmm +tak.cmm diff --git a/testsuite/tests/asmgen/parsecmm.mly b/testsuite/tests/asmgen/parsecmm.mly deleted file mode 100644 index b597a015..00000000 --- a/testsuite/tests/asmgen/parsecmm.mly +++ /dev/null @@ -1,373 +0,0 @@ -/* A simple parser for C-- */ - -%{ -open Cmm -open Parsecmmaux - -let rec make_letdef def body = - match def with - [] -> body - | (id, def) :: rem -> - unbind_ident id; - Clet(id, def, make_letdef rem body) - -let make_switch n selector caselist = - let index = Array.make n 0 in - let casev = Array.of_list caselist in - let actv = Array.make (Array.length casev) (Cexit(0,[])) in - for i = 0 to Array.length casev - 1 do - let (posl, e) = casev.(i) in - List.iter (fun pos -> index.(pos) <- i) posl; - actv.(i) <- e - done; - Cswitch(selector, index, actv, Debuginfo.none) - -let access_array base numelt size = - match numelt with - Cconst_int 0 -> base - | Cconst_int n -> Cop(Cadda, [base; Cconst_int(n * size)], Debuginfo.none) - | _ -> Cop(Cadda, [base; - Cop(Clsl, [numelt; Cconst_int(Misc.log2 size)], - Debuginfo.none)], - Debuginfo.none) - -%} - -%token ABSF -%token ADDA -%token ADDF -%token ADDI -%token ADDV -%token ADDR -%token ALIGN -%token ALLOC -%token AND -%token APPLY -%token ASR -%token ASSIGN -%token BYTE -%token CASE -%token CATCH -%token CHECKBOUND -%token COLON -%token DATA -%token DIVF -%token DIVI -%token EOF -%token EQA -%token EQF -%token EQI -%token EXIT -%token EXTCALL -%token FLOAT -%token FLOAT32 -%token FLOAT64 -%token FLOATCONST -%token FLOATOFINT -%token FUNCTION -%token GEA -%token GEF -%token GEI -%token GLOBAL -%token GTA -%token GTF -%token GTI -%token HALF -%token IDENT -%token IF -%token INT -%token INT32 -%token INTCONST -%token INTOFFLOAT -%token KSTRING -%token LBRACKET -%token LEA -%token LEF -%token LEI -%token LET -%token LOAD -%token LOCATION -%token LPAREN -%token LSL -%token LSR -%token LTA -%token LTF -%token LTI -%token MODI -%token MULF -%token MULH -%token MULI -%token NEA -%token NEF -%token NEI -%token NGEF -%token NGTF -%token NLEF -%token NLTF -%token OR -%token POINTER -%token PROJ -%token RAISE -%token RBRACKET -%token RPAREN -%token SEQ -%token SIGNED -%token SKIP -%token STAR -%token STORE -%token STRING -%token SUBF -%token SUBI -%token SWITCH -%token TRY -%token UNIT -%token UNSIGNED -%token VAL -%token WHILE -%token WITH -%token XOR -%token ADDRAREF -%token INTAREF -%token FLOATAREF -%token ADDRASET -%token INTASET -%token FLOATASET - -%start phrase -%type phrase - -%% - -phrase: - fundecl { Cfunction $1 } - | datadecl { Cdata $1 } - | EOF { raise End_of_file } -; -fundecl: - LPAREN FUNCTION fun_name LPAREN params RPAREN sequence RPAREN - { List.iter (fun (id, ty) -> unbind_ident id) $5; - {fun_name = $3; fun_args = $5; fun_body = $7; - fun_codegen_options = - if Config.flambda then [ - Reduce_code_size; - No_CSE; - ] - else [ Reduce_code_size ]; - fun_dbg = debuginfo ()} } -; -fun_name: - STRING { $1 } - | IDENT { $1 } -params: - oneparam params { $1 :: $2 } - | /**/ { [] } -; -oneparam: - IDENT COLON machtype { (bind_ident $1, $3) } -; -machtype: - UNIT { [||] } - | componentlist { Array.of_list(List.rev $1) } -; -component: - VAL { Val } - | ADDR { Addr } - | INT { Int } - | FLOAT { Float } -; -componentlist: - component { [$1] } - | componentlist STAR component { $3 :: $1 } -; -expr: - INTCONST { Cconst_int $1 } - | FLOATCONST { Cconst_float (float_of_string $1) } - | STRING { Cconst_symbol $1 } - | POINTER { Cconst_pointer $1 } - | IDENT { Cvar(find_ident $1) } - | LBRACKET RBRACKET { Ctuple [] } - | LPAREN LET letdef sequence RPAREN { make_letdef $3 $4 } - | LPAREN ASSIGN IDENT expr RPAREN { Cassign(find_ident $3, $4) } - | LPAREN APPLY location expr exprlist machtype RPAREN - { Cop(Capply $6, $4 :: List.rev $5, debuginfo ?loc:$3 ()) } - | LPAREN EXTCALL STRING exprlist machtype RPAREN - {Cop(Cextcall($3, $5, false, None), List.rev $4, debuginfo ())} - | LPAREN ALLOC exprlist RPAREN { Cop(Calloc, List.rev $3, debuginfo ()) } - | LPAREN SUBF expr RPAREN { Cop(Cnegf, [$3], debuginfo ()) } - | LPAREN SUBF expr expr RPAREN { Cop(Csubf, [$3; $4], debuginfo ()) } - | LPAREN unaryop expr RPAREN { Cop($2, [$3], debuginfo ()) } - | LPAREN binaryop expr expr RPAREN { Cop($2, [$3; $4], debuginfo ()) } - | LPAREN SEQ sequence RPAREN { $3 } - | LPAREN IF expr expr expr RPAREN { Cifthenelse($3, $4, $5) } - | LPAREN SWITCH INTCONST expr caselist RPAREN { make_switch $3 $4 $5 } - | LPAREN WHILE expr sequence RPAREN - { let body = - match $3 with - Cconst_int x when x <> 0 -> $4 - | _ -> Cifthenelse($3, $4, (Cexit(0,[]))) in - Ccatch(Recursive, [0, [], Cloop body], Ctuple []) } - | LPAREN EXIT IDENT exprlist RPAREN - { Cexit(find_label $3, List.rev $4) } - | LPAREN CATCH sequence WITH catch_handlers RPAREN - { let handlers = $5 in - List.iter (fun (_, l, _) -> List.iter unbind_ident l) handlers; - Ccatch(Recursive, handlers, $3) } - | EXIT { Cexit(0,[]) } - | LPAREN TRY sequence WITH bind_ident sequence RPAREN - { unbind_ident $5; Ctrywith($3, $5, $6) } - | LPAREN VAL expr expr RPAREN - { Cop(Cload (Word_val, Mutable), [access_array $3 $4 Arch.size_addr], - debuginfo ()) } - | LPAREN ADDRAREF expr expr RPAREN - { Cop(Cload (Word_val, Mutable), [access_array $3 $4 Arch.size_addr], - Debuginfo.none) } - | LPAREN INTAREF expr expr RPAREN - { Cop(Cload (Word_int, Mutable), [access_array $3 $4 Arch.size_int], - Debuginfo.none) } - | LPAREN FLOATAREF expr expr RPAREN - { Cop(Cload (Double_u, Mutable), [access_array $3 $4 Arch.size_float], - Debuginfo.none) } - | LPAREN ADDRASET expr expr expr RPAREN - { Cop(Cstore (Word_val, Assignment), - [access_array $3 $4 Arch.size_addr; $5], Debuginfo.none) } - | LPAREN INTASET expr expr expr RPAREN - { Cop(Cstore (Word_int, Assignment), - [access_array $3 $4 Arch.size_int; $5], Debuginfo.none) } - | LPAREN FLOATASET expr expr expr RPAREN - { Cop(Cstore (Double_u, Assignment), - [access_array $3 $4 Arch.size_float; $5], Debuginfo.none) } -; -exprlist: - exprlist expr { $2 :: $1 } - | /**/ { [] } -; -letdef: - oneletdef { [$1] } - | LPAREN letdefmult RPAREN { $2 } -; -letdefmult: - /**/ { [] } - | oneletdef letdefmult { $1 :: $2 } -; -oneletdef: - IDENT expr { (bind_ident $1, $2) } -; -chunk: - UNSIGNED BYTE { Byte_unsigned } - | SIGNED BYTE { Byte_signed } - | UNSIGNED HALF { Sixteen_unsigned } - | SIGNED HALF { Sixteen_signed } - | UNSIGNED INT32 { Thirtytwo_unsigned } - | SIGNED INT32 { Thirtytwo_signed } - | INT { Word_int } - | ADDR { Word_val } - | FLOAT32 { Single } - | FLOAT64 { Double } - | FLOAT { Double_u } - | VAL { Word_val } -; -unaryop: - LOAD chunk { Cload ($2, Mutable) } - | FLOATOFINT { Cfloatofint } - | INTOFFLOAT { Cintoffloat } - | RAISE { Craise $1 } - | ABSF { Cabsf } -; -binaryop: - STORE chunk { Cstore ($2, Assignment) } - | ADDI { Caddi } - | SUBI { Csubi } - | STAR { Cmuli } - | DIVI { Cdivi } - | MODI { Cmodi } - | AND { Cand } - | OR { Cor } - | XOR { Cxor } - | LSL { Clsl } - | LSR { Clsr } - | ASR { Casr } - | EQI { Ccmpi Ceq } - | NEI { Ccmpi Cne } - | LTI { Ccmpi Clt } - | LEI { Ccmpi Cle } - | GTI { Ccmpi Cgt } - | GEI { Ccmpi Cge } - | ADDA { Cadda } - | ADDV { Caddv } - | EQA { Ccmpa Ceq } - | NEA { Ccmpa Cne } - | LTA { Ccmpa Clt } - | LEA { Ccmpa Cle } - | GTA { Ccmpa Cgt } - | GEA { Ccmpa Cge } - | ADDF { Caddf } - | MULF { Cmulf } - | DIVF { Cdivf } - | EQF { Ccmpf CFeq } - | NEF { Ccmpf CFneq } - | LTF { Ccmpf CFlt } - | NLTF { Ccmpf CFnlt } - | LEF { Ccmpf CFle } - | NLEF { Ccmpf CFnle } - | GTF { Ccmpf CFgt } - | NGTF { Ccmpf CFngt } - | GEF { Ccmpf CFge } - | NGEF { Ccmpf CFnge } - | CHECKBOUND { Ccheckbound } - | MULH { Cmulhi } -; -sequence: - expr sequence { Csequence($1, $2) } - | expr { $1 } -; -caselist: - onecase sequence caselist { ($1, $2) :: $3 } - | /**/ { [] } -; -onecase: - CASE INTCONST COLON onecase { $2 :: $4 } - | CASE INTCONST COLON { [$2] } -; -bind_ident: - IDENT { bind_ident $1 } -; -datadecl: - LPAREN datalist RPAREN { List.rev $2 } - | LPAREN DATA datalist RPAREN { List.rev $3 } -; -datalist: - datalist dataitem { $2 :: $1 } - | /**/ { [] } -; -dataitem: - STRING COLON { Cdefine_symbol $1 } - | BYTE INTCONST { Cint8 $2 } - | HALF INTCONST { Cint16 $2 } - | INT INTCONST { Cint(Nativeint.of_int $2) } - | FLOAT FLOATCONST { Cdouble (float_of_string $2) } - | ADDR STRING { Csymbol_address $2 } - | VAL STRING { Csymbol_address $2 } - | KSTRING STRING { Cstring $2 } - | SKIP INTCONST { Cskip $2 } - | ALIGN INTCONST { Calign $2 } - | GLOBAL STRING { Cglobal_symbol $2 } -; -catch_handlers: - | catch_handler - { [$1] } - | catch_handler AND catch_handlers - { $1 :: $3 } - -catch_handler: - | sequence - { 0, [], $1 } - | LPAREN IDENT bind_identlist RPAREN sequence - { find_label $2, $3, $5 } - -bind_identlist: - /**/ { [] } - | bind_ident bind_identlist { $1 :: $2 } - -location: - /**/ { None } - | LOCATION { Some $1 } diff --git a/testsuite/tests/asmgen/parsecmmaux.ml b/testsuite/tests/asmgen/parsecmmaux.ml deleted file mode 100644 index db555273..00000000 --- a/testsuite/tests/asmgen/parsecmmaux.ml +++ /dev/null @@ -1,43 +0,0 @@ -(* Auxiliary functions for parsing *) - -type error = - Unbound of string - -exception Error of error - -let tbl_ident = (Hashtbl.create 57 : (string, Ident.t) Hashtbl.t) -let tbl_label = (Hashtbl.create 57 : (string, int) Hashtbl.t) - -let ident_name s = - match String.index s '/' with - | exception Not_found -> s - | n -> String.sub s 0 n - -let bind_ident s = - let id = Ident.create (ident_name s) in - Hashtbl.add tbl_ident s id; - id - -let find_ident s = - try - Hashtbl.find tbl_ident s - with Not_found -> - raise(Error(Unbound s)) - -let unbind_ident id = - Hashtbl.remove tbl_ident (Ident.name id) - -let find_label s = - try - Hashtbl.find tbl_label s - with Not_found -> - let lbl = Lambda.next_raise_count () in - Hashtbl.add tbl_label s lbl; - lbl - -let report_error = function - Unbound s -> - prerr_string "Unbound identifier "; prerr_string s; prerr_endline "." - -let debuginfo ?(loc=Location.symbol_rloc ()) () = - Debuginfo.(from_location loc) diff --git a/testsuite/tests/asmgen/parsecmmaux.mli b/testsuite/tests/asmgen/parsecmmaux.mli deleted file mode 100644 index f5478579..00000000 --- a/testsuite/tests/asmgen/parsecmmaux.mli +++ /dev/null @@ -1,16 +0,0 @@ -(* Auxiliary functions for parsing *) - -val bind_ident: string -> Ident.t -val find_ident: string -> Ident.t -val unbind_ident: Ident.t -> unit - -val find_label: string -> int - -val debuginfo: ?loc:Location.t -> unit -> Debuginfo.t - -type error = - Unbound of string - -exception Error of error - -val report_error: error -> unit diff --git a/testsuite/tests/asmgen/pgcd.cmm b/testsuite/tests/asmgen/pgcd.cmm index e75a149a..3bd067c8 100644 --- a/testsuite/tests/asmgen/pgcd.cmm +++ b/testsuite/tests/asmgen/pgcd.cmm @@ -1,9 +1,15 @@ +(* TEST +files = "main.c" +arguments = "-DINT_INT -DFUN=pgcd_30030 main.c" +* asmgen +*) + (function "pgcd_30030" (a:int) (catch (exit pgcd a 30030) - with (pgcd n m) + with (pgcd n:val m:val) (if (> n m) (exit pgcd m n) (if (== n 0) m (let (r (mod m n)) - (exit pgcd r n)))))) \ No newline at end of file + (exit pgcd r n)))))) diff --git a/testsuite/tests/asmgen/quicksort.cmm b/testsuite/tests/asmgen/quicksort.cmm index b0859415..7779780f 100644 --- a/testsuite/tests/asmgen/quicksort.cmm +++ b/testsuite/tests/asmgen/quicksort.cmm @@ -1,3 +1,9 @@ +(* TEST +files = "main.c" +arguments = "-DSORT -DFUN=quicksort main.c" +* asmgen +*) + (**************************************************************************) (* *) (* OCaml *) diff --git a/testsuite/tests/asmgen/quicksort2.cmm b/testsuite/tests/asmgen/quicksort2.cmm index 96c1fc12..2c6b278e 100644 --- a/testsuite/tests/asmgen/quicksort2.cmm +++ b/testsuite/tests/asmgen/quicksort2.cmm @@ -1,3 +1,9 @@ +(* TEST +files = "main.c" +arguments = "-DSORT -DFUN=quicksort main.c" +* asmgen +*) + (**************************************************************************) (* *) (* OCaml *) diff --git a/testsuite/tests/asmgen/soli.cmm b/testsuite/tests/asmgen/soli.cmm index c8ffc5d6..cd0822b1 100644 --- a/testsuite/tests/asmgen/soli.cmm +++ b/testsuite/tests/asmgen/soli.cmm @@ -1,3 +1,9 @@ +(* TEST +files = "main.c" +arguments = "-DUNIT_INT -DFUN=solitaire main.c" +* asmgen +*) + (**************************************************************************) (* *) (* OCaml *) diff --git a/testsuite/tests/asmgen/tagged-fib.cmm b/testsuite/tests/asmgen/tagged-fib.cmm index d83afaa4..b9b96152 100644 --- a/testsuite/tests/asmgen/tagged-fib.cmm +++ b/testsuite/tests/asmgen/tagged-fib.cmm @@ -1,3 +1,9 @@ +(* TEST +files = "main.c" +arguments = "-DINT_INT -DFUN=fib main.c" +* asmgen +*) + (**************************************************************************) (* *) (* OCaml *) diff --git a/testsuite/tests/asmgen/tagged-integr.cmm b/testsuite/tests/asmgen/tagged-integr.cmm index b89bd508..c2781efe 100644 --- a/testsuite/tests/asmgen/tagged-integr.cmm +++ b/testsuite/tests/asmgen/tagged-integr.cmm @@ -1,3 +1,9 @@ +(* TEST +files = "main.c" +arguments = "-DINT_FLOAT -DFUN=test main.c" +* asmgen +*) + (**************************************************************************) (* *) (* OCaml *) diff --git a/testsuite/tests/asmgen/tagged-quicksort.cmm b/testsuite/tests/asmgen/tagged-quicksort.cmm index 59293aa2..7c2ce6ef 100644 --- a/testsuite/tests/asmgen/tagged-quicksort.cmm +++ b/testsuite/tests/asmgen/tagged-quicksort.cmm @@ -1,3 +1,9 @@ +(* TEST +files = "main.c" +arguments = "-DSORT -DFUN=quicksort main.c" +* asmgen +*) + (**************************************************************************) (* *) (* OCaml *) diff --git a/testsuite/tests/asmgen/tagged-tak.cmm b/testsuite/tests/asmgen/tagged-tak.cmm index 30c98a00..3ff6ea4f 100644 --- a/testsuite/tests/asmgen/tagged-tak.cmm +++ b/testsuite/tests/asmgen/tagged-tak.cmm @@ -1,3 +1,9 @@ +(* TEST +files = "main.c" +arguments = "-DUNIT_INT -DFUN=takmain main.c" +* asmgen +*) + (**************************************************************************) (* *) (* OCaml *) diff --git a/testsuite/tests/asmgen/tak.cmm b/testsuite/tests/asmgen/tak.cmm index 2750fff3..1835ef66 100644 --- a/testsuite/tests/asmgen/tak.cmm +++ b/testsuite/tests/asmgen/tak.cmm @@ -1,3 +1,9 @@ +(* TEST +files = "main.c" +arguments = "-DUNIT_INT -DFUN=takmain main.c" +* asmgen +*) + (**************************************************************************) (* *) (* OCaml *) diff --git a/testsuite/tests/ast-invariants/test.ml b/testsuite/tests/ast-invariants/test.ml index 1e0074b1..314c668b 100644 --- a/testsuite/tests/ast-invariants/test.ml +++ b/testsuite/tests/ast-invariants/test.ml @@ -1,8 +1,9 @@ (* TEST include ocamlcommon + * hasunix include unix arguments = "${ocamlsrcdir}" - * native + ** native *) (* This test checks all ml files in the ocaml repository that are accepted diff --git a/testsuite/tests/backtrace/backtrace2.byte.reference b/testsuite/tests/backtrace/backtrace2.byte.reference index 231e7e60..36465dc0 100644 --- a/testsuite/tests/backtrace/backtrace2.byte.reference +++ b/testsuite/tests/backtrace/backtrace2.byte.reference @@ -46,13 +46,13 @@ Called from file "backtrace2.ml", line 52, characters 43-52 Called from file "backtrace2.ml", line 52, characters 43-52 Called from file "backtrace2.ml", line 52, characters 43-52 Called from file "backtrace2.ml", line 52, characters 43-52 -Called from file "camlinternalLazy.ml", line 27, characters 17-27 -Re-raised at file "camlinternalLazy.ml", line 34, characters 10-11 +Called from file "camlinternalLazy.ml", line 29, characters 17-27 +Re-raised at file "camlinternalLazy.ml", line 36, characters 10-11 Called from file "backtrace2.ml", line 67, characters 11-23 Uncaught exception Not_found Raised at file "hashtbl.ml", line 194, characters 19-28 Called from file "backtrace2.ml", line 55, characters 8-41 -Re-raised at file "camlinternalLazy.ml", line 33, characters 62-63 -Called from file "camlinternalLazy.ml", line 27, characters 17-27 -Re-raised at file "camlinternalLazy.ml", line 34, characters 10-11 +Re-raised at file "camlinternalLazy.ml", line 35, characters 62-63 +Called from file "camlinternalLazy.ml", line 29, characters 17-27 +Re-raised at file "camlinternalLazy.ml", line 36, characters 10-11 Called from file "backtrace2.ml", line 67, characters 11-23 diff --git a/testsuite/tests/backtrace/backtrace2.opt.reference b/testsuite/tests/backtrace/backtrace2.opt.reference index cc110b6d..c0b9816b 100644 --- a/testsuite/tests/backtrace/backtrace2.opt.reference +++ b/testsuite/tests/backtrace/backtrace2.opt.reference @@ -46,13 +46,13 @@ Called from file "backtrace2.ml", line 52, characters 43-52 Called from file "backtrace2.ml", line 52, characters 43-52 Called from file "backtrace2.ml", line 52, characters 43-52 Called from file "backtrace2.ml", line 52, characters 43-52 -Called from file "camlinternalLazy.ml", line 27, characters 17-27 -Re-raised at file "camlinternalLazy.ml", line 34, characters 4-11 +Called from file "camlinternalLazy.ml", line 29, characters 17-27 +Re-raised at file "camlinternalLazy.ml", line 36, characters 4-11 Called from file "backtrace2.ml", line 67, characters 11-23 Uncaught exception Not_found Raised at file "hashtbl.ml", line 194, characters 13-28 Called from file "backtrace2.ml", line 55, characters 8-41 -Re-raised at file "camlinternalLazy.ml", line 33, characters 56-63 -Called from file "camlinternalLazy.ml", line 27, characters 17-27 -Re-raised at file "camlinternalLazy.ml", line 34, characters 4-11 +Re-raised at file "camlinternalLazy.ml", line 35, characters 56-63 +Called from file "camlinternalLazy.ml", line 29, characters 17-27 +Re-raised at file "camlinternalLazy.ml", line 36, characters 4-11 Called from file "backtrace2.ml", line 67, characters 11-23 diff --git a/testsuite/tests/backtrace/backtrace_or_exception.byte.reference b/testsuite/tests/backtrace/backtrace_or_exception.byte.reference new file mode 100644 index 00000000..81ff030c --- /dev/null +++ b/testsuite/tests/backtrace/backtrace_or_exception.byte.reference @@ -0,0 +1,14 @@ +exception Backtrace_or_exception.Exn +Raised at file "backtrace_or_exception.ml", line 24, characters 10-13 +Called from file "backtrace_or_exception.ml", line 44, characters 6-10 +--------------------------- +exception Backtrace_or_exception.Exn +Raised at file "backtrace_or_exception.ml", line 15, characters 10-13 +Called from file "backtrace_or_exception.ml", line 28, characters 8-44 +Re-raised at file "backtrace_or_exception.ml", line 31, characters 10-13 +Called from file "backtrace_or_exception.ml", line 44, characters 6-10 +--------------------------- +exception Backtrace_or_exception.Exn +Raised at file "backtrace_or_exception.ml", line 40, characters 12-15 +Called from file "backtrace_or_exception.ml", line 44, characters 6-10 +--------------------------- diff --git a/testsuite/tests/backtrace/backtrace_or_exception.ml b/testsuite/tests/backtrace/backtrace_or_exception.ml new file mode 100644 index 00000000..8b6fb0f1 --- /dev/null +++ b/testsuite/tests/backtrace/backtrace_or_exception.ml @@ -0,0 +1,54 @@ +(* TEST + flags = "-g" + ocamlrunparam += ",b=1" + * bytecode + reference="${test_source_directory}/backtrace_or_exception.byte.reference" + * native + reference = "${test_source_directory}/backtrace_or_exception.opt.reference" + compare_programs = "false" +*) + +exception Exn + +let return_exn ?(raise_it_instead=false) () = + if raise_it_instead then + raise Exn + else + Exn +[@@inline never] + +let without_reraise () = + match return_exn () with + | Exn as exn + | exception (Exn as exn) -> + raise exn + | _ -> assert false + +let with_reraise () = + match return_exn ~raise_it_instead:true () with + | Exn as exn + | exception (Exn as exn) -> + raise exn + | _ -> assert false + +let trickier () = + try raise Not_found + with e -> + match return_exn () with + | Exn as exn + | exception (Exn as exn) -> + raise exn + | _ -> assert false + +let run f = + try f () + with exn -> + Printf.printf "exception %s\n" (Printexc.to_string exn); + Printexc.print_backtrace stdout; + Printf.printf "---------------------------\n%!" + +let _ = + Printexc.record_backtrace true; + run without_reraise; + run with_reraise; + run trickier diff --git a/testsuite/tests/backtrace/backtrace_or_exception.opt.reference b/testsuite/tests/backtrace/backtrace_or_exception.opt.reference new file mode 100644 index 00000000..d3f8b666 --- /dev/null +++ b/testsuite/tests/backtrace/backtrace_or_exception.opt.reference @@ -0,0 +1,14 @@ +exception Backtrace_or_exception.Exn +Raised at file "backtrace_or_exception.ml", line 24, characters 4-13 +Called from file "backtrace_or_exception.ml", line 44, characters 6-10 +--------------------------- +exception Backtrace_or_exception.Exn +Raised at file "backtrace_or_exception.ml", line 15, characters 4-13 +Called from file "backtrace_or_exception.ml", line 28, characters 8-44 +Re-raised at file "backtrace_or_exception.ml", line 31, characters 4-13 +Called from file "backtrace_or_exception.ml", line 44, characters 6-10 +--------------------------- +exception Backtrace_or_exception.Exn +Raised at file "backtrace_or_exception.ml", line 40, characters 6-15 +Called from file "backtrace_or_exception.ml", line 44, characters 6-10 +--------------------------- diff --git a/testsuite/tests/backtrace/backtrace_slots.ml b/testsuite/tests/backtrace/backtrace_slots.ml index ef68b3fd..15bbb1ef 100644 --- a/testsuite/tests/backtrace/backtrace_slots.ml +++ b/testsuite/tests/backtrace/backtrace_slots.ml @@ -25,7 +25,7 @@ let get_backtrace () = Array.iteri (fun i slot -> Hashtbl.add table slot i) raw_slots; let module S = Set.Make(struct type t = Printexc.raw_backtrace_slot - let compare = Pervasives.compare + let compare = Stdlib.compare end) in let slots = Array.fold_right S.add raw_slots S.empty in Array.iteri (fun i slot -> diff --git a/testsuite/tests/backtrace/callstack.ml b/testsuite/tests/backtrace/callstack.ml new file mode 100644 index 00000000..76bf9f96 --- /dev/null +++ b/testsuite/tests/backtrace/callstack.ml @@ -0,0 +1,19 @@ +(* TEST + flags = "-g" + * hassysthreads + include systhreads + compare_programs = "false" + ** no-flambda + reference = "${test_source_directory}/callstack.reference" + *** native + *** bytecode +*) +let[@inline never] f0 () = + Printexc.print_raw_backtrace stdout (Printexc.get_callstack 100); () +let[@inline never] f1 () = f0 (); () +let[@inline never] f2 () = f1 (); () +let[@inline never] f3 () = f2 (); () +let () = Printf.printf "main thread:\n" +let () = f3 () +let () = Printf.printf "new thread:\n" +let () = Thread.join (Thread.create f3 ()) diff --git a/testsuite/tests/backtrace/callstack.reference b/testsuite/tests/backtrace/callstack.reference new file mode 100644 index 00000000..33fa9a81 --- /dev/null +++ b/testsuite/tests/backtrace/callstack.reference @@ -0,0 +1,12 @@ +main thread: +Raised by primitive operation at file "callstack.ml", line 12, characters 38-66 +Called from file "callstack.ml", line 13, characters 27-32 +Called from file "callstack.ml", line 14, characters 27-32 +Called from file "callstack.ml", line 15, characters 27-32 +Called from file "callstack.ml", line 17, characters 9-14 +new thread: +Raised by primitive operation at file "callstack.ml", line 12, characters 38-66 +Called from file "callstack.ml", line 13, characters 27-32 +Called from file "callstack.ml", line 14, characters 27-32 +Called from file "callstack.ml", line 15, characters 27-32 +Called from file "thread.ml", line 39, characters 8-14 diff --git a/testsuite/tests/backtrace/inline_traversal_test.ml b/testsuite/tests/backtrace/inline_traversal_test.ml index 1bbcb357..c28e849f 100644 --- a/testsuite/tests/backtrace/inline_traversal_test.ml +++ b/testsuite/tests/backtrace/inline_traversal_test.ml @@ -40,7 +40,7 @@ let () = let location = match Slot.location x with | None -> "" | Some {filename; line_number; _} -> - filename ^ ":" ^ string_of_int line_number + filename ^ ":" ^ Int.to_string line_number in Printf.printf "- %s%s%s\n" location diff --git a/testsuite/tests/backtrace/ocamltests b/testsuite/tests/backtrace/ocamltests index 166dcd7c..6d70aec2 100644 --- a/testsuite/tests/backtrace/ocamltests +++ b/testsuite/tests/backtrace/ocamltests @@ -2,8 +2,10 @@ backtrace.ml backtrace2.ml backtrace3.ml backtrace_deprecated.ml +backtrace_or_exception.ml backtrace_slots.ml backtraces_and_finalizers.ml +callstack.ml inline_test.ml inline_traversal_test.ml pr6920_why_at.ml diff --git a/testsuite/tests/backtrace/pr6920_why_at.byte.reference b/testsuite/tests/backtrace/pr6920_why_at.byte.reference index 44285955..5fdde076 100644 --- a/testsuite/tests/backtrace/pr6920_why_at.byte.reference +++ b/testsuite/tests/backtrace/pr6920_why_at.byte.reference @@ -1,4 +1,4 @@ -Fatal error: exception Stdlib.Pervasives.Exit +Fatal error: exception Stdlib.Exit Raised at file "pr6920_why_at.ml", line 13, characters 41-45 Called from file "pr6920_why_at.ml", line 15, characters 2-11 Called from file "pr6920_why_at.ml", line 21, characters 2-6 diff --git a/testsuite/tests/letrec/backreferences.reference b/testsuite/tests/backtrace/pr6920_why_at.native.reference similarity index 100% rename from testsuite/tests/letrec/backreferences.reference rename to testsuite/tests/backtrace/pr6920_why_at.native.reference diff --git a/testsuite/tests/backtrace/pr6920_why_at.opt.reference b/testsuite/tests/backtrace/pr6920_why_at.opt.reference index 62a0ef96..076f29ae 100644 --- a/testsuite/tests/backtrace/pr6920_why_at.opt.reference +++ b/testsuite/tests/backtrace/pr6920_why_at.opt.reference @@ -1,4 +1,4 @@ -Fatal error: exception Stdlib.Pervasives.Exit +Fatal error: exception Stdlib.Exit Raised at file "pr6920_why_at.ml", line 13, characters 35-45 Called from file "pr6920_why_at.ml", line 15, characters 2-11 Called from file "pr6920_why_at.ml", line 21, characters 2-6 diff --git a/testsuite/tests/backtrace/pr6920_why_swallow.byte.reference b/testsuite/tests/backtrace/pr6920_why_swallow.byte.reference index c262211d..f967fa7a 100644 --- a/testsuite/tests/backtrace/pr6920_why_swallow.byte.reference +++ b/testsuite/tests/backtrace/pr6920_why_swallow.byte.reference @@ -1,4 +1,4 @@ -Fatal error: exception Stdlib.Pervasives.Exit +Fatal error: exception Stdlib.Exit Raised at file "pr6920_why_swallow.ml", line 13, characters 41-45 Called from file "pr6920_why_swallow.ml", line 16, characters 4-13 Called from file "pr6920_why_swallow.ml", line 23, characters 2-6 diff --git a/testsuite/tests/letrec/class_1.reference b/testsuite/tests/backtrace/pr6920_why_swallow.native.reference similarity index 100% rename from testsuite/tests/letrec/class_1.reference rename to testsuite/tests/backtrace/pr6920_why_swallow.native.reference diff --git a/testsuite/tests/backtrace/pr6920_why_swallow.opt.reference b/testsuite/tests/backtrace/pr6920_why_swallow.opt.reference index b842cee0..48b4b05a 100644 --- a/testsuite/tests/backtrace/pr6920_why_swallow.opt.reference +++ b/testsuite/tests/backtrace/pr6920_why_swallow.opt.reference @@ -1,4 +1,4 @@ -Fatal error: exception Stdlib.Pervasives.Exit +Fatal error: exception Stdlib.Exit Raised at file "pr6920_why_swallow.ml", line 13, characters 35-45 Called from file "pr6920_why_swallow.ml", line 16, characters 4-13 Called from file "pr6920_why_swallow.ml", line 23, characters 2-6 diff --git a/testsuite/tests/basic-float/zero_sized_float_arrays.ml b/testsuite/tests/basic-float/zero_sized_float_arrays.ml index b207b828..51657d3e 100644 --- a/testsuite/tests/basic-float/zero_sized_float_arrays.ml +++ b/testsuite/tests/basic-float/zero_sized_float_arrays.ml @@ -11,7 +11,7 @@ let float_array_from_runtime : float array = Array.make 0 0.0 let () = - assert (Pervasives.compare non_float_array non_float_array_from_runtime = 0); - assert (Pervasives.compare non_float_array non_float_array_from_runtime = 0); - assert (Pervasives.compare float_array float_array_from_runtime = 0); - assert (Pervasives.compare float_array float_array_from_runtime = 0) + assert (Stdlib.compare non_float_array non_float_array_from_runtime = 0); + assert (Stdlib.compare non_float_array non_float_array_from_runtime = 0); + assert (Stdlib.compare float_array float_array_from_runtime = 0); + assert (Stdlib.compare float_array float_array_from_runtime = 0) diff --git a/testsuite/tests/basic-modules/recursive_module_evaluation_errors.ml b/testsuite/tests/basic-modules/recursive_module_evaluation_errors.ml index b937563f..316f49c9 100644 --- a/testsuite/tests/basic-modules/recursive_module_evaluation_errors.ml +++ b/testsuite/tests/basic-modules/recursive_module_evaluation_errors.ml @@ -8,17 +8,112 @@ and C:sig val x: int end = struct let x = B.x end and D:sig val x: int end = struct let x = C.x end and E:sig val x: int val y:int end = struct let x = D.x let y = 0 end [%%expect {| -Line _, characters 27-49: - and B:sig val x: int end = struct let x = E.y end - ^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 27-49: +2 | and B:sig val x: int end = struct let x = E.y end + ^^^^^^^^^^^^^^^^^^^^^^ Error: Cannot safely evaluate the definition of the following cycle of recursively-defined modules: B -> E -> D -> C -> B. - There are no safe modules in this cycle (see manual section 8.4) + There are no safe modules in this cycle (see manual section 8.2). +Line 2, characters 10-20: +2 | and B:sig val x: int end = struct let x = E.y end + ^^^^^^^^^^ + Module B defines an unsafe value, x . +Line 5, characters 10-20: +5 | and E:sig val x: int val y:int end = struct let x = D.x let y = 0 end + ^^^^^^^^^^ + Module E defines an unsafe value, x . +Line 4, characters 10-20: +4 | and D:sig val x: int end = struct let x = C.x end + ^^^^^^^^^^ + Module D defines an unsafe value, x . +Line 3, characters 10-20: +3 | and C:sig val x: int end = struct let x = B.x end + ^^^^^^^^^^ + Module C defines an unsafe value, x . |}] +type t = .. +module rec A: sig type t += A end = struct type t += A = B.A end +and B:sig type t += A end = struct type t += A = A.A end +[%%expect {| +type t = .. +Line 2, characters 36-64: +2 | module rec A: sig type t += A end = struct type t += A = B.A end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Cannot safely evaluate the definition of the following cycle + of recursively-defined modules: A -> B -> A. + There are no safe modules in this cycle (see manual section 8.2). +Line 2, characters 28-29: +2 | module rec A: sig type t += A end = struct type t += A = B.A end + ^ + Module A defines an unsafe extension constructor, A . +Line 3, characters 20-21: +3 | and B:sig type t += A end = struct type t += A = A.A end + ^ + Module B defines an unsafe extension constructor, A . +|}] + + +module rec A: sig + module F: functor(X:sig end) -> sig end + val f: unit -> unit +end = struct + module F(X:sig end) = struct end + let f () = B.value +end +and B: sig val value: unit end = struct let value = A.f () end +[%%expect {| +Line 4, characters 6-72: +4 | ......struct +5 | module F(X:sig end) = struct end +6 | let f () = B.value +7 | end +Error: Cannot safely evaluate the definition of the following cycle + of recursively-defined modules: A -> B -> A. + There are no safe modules in this cycle (see manual section 8.2). +Line 2, characters 2-41: +2 | module F: functor(X:sig end) -> sig end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Module A defines an unsafe functor, F . +Line 8, characters 11-26: +8 | and B: sig val value: unit end = struct let value = A.f () end + ^^^^^^^^^^^^^^^ + Module B defines an unsafe value, value . +|}] + + +module F(X: sig module type t module M: t end) = struct + module rec A: sig + module M: X.t + val f: unit -> unit + end = struct + module M = X.M + let f () = B.value + end + and B: sig val value: unit end = struct let value = A.f () end +end +[%%expect {| +Line 5, characters 8-62: +5 | ........struct +6 | module M = X.M +7 | let f () = B.value +8 | end +Error: Cannot safely evaluate the definition of the following cycle + of recursively-defined modules: A -> B -> A. + There are no safe modules in this cycle (see manual section 8.2). +Line 3, characters 4-17: +3 | module M: X.t + ^^^^^^^^^^^^^ + Module A defines an unsafe module, M . +Line 9, characters 13-28: +9 | and B: sig val value: unit end = struct let value = A.f () end + ^^^^^^^^^^^^^^^ + Module B defines an unsafe value, value . +|}] + + module rec M: sig val f: unit -> int end = struct let f () = N.x end and N:sig val x: int end = struct let x = M.f () end;; [%%expect {| Exception: Undefined_recursive_module ("", 1, 43). |}] - diff --git a/testsuite/tests/basic-more/morematch.compilers.reference b/testsuite/tests/basic-more/morematch.compilers.reference index 7f077dd6..f8857caa 100644 --- a/testsuite/tests/basic-more/morematch.compilers.reference +++ b/testsuite/tests/basic-more/morematch.compilers.reference @@ -1,30 +1,60 @@ -File "morematch.ml", line 1050, characters 8-65: -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -(A `D|B (`B, (`A|`C))) File "morematch.ml", line 67, characters 2-5: +67 | | 4|5|7 -> 100 + ^^^ Warning 12: this sub-pattern is unused. File "morematch.ml", line 68, characters 2-3: +68 | | 7 | 8 -> 6 + ^ Warning 12: this sub-pattern is unused. File "morematch.ml", line 219, characters 33-47: +219 | let f = function (([]|[_]) as x)|(_::([] as x))|(_::_::x) -> x + ^^^^^^^^^^^^^^ Warning 12: this sub-pattern is unused. File "morematch.ml", line 388, characters 2-15: +388 | | A,_,(100|103) -> 5 + ^^^^^^^^^^^^^ Warning 11: this match case is unused. File "morematch.ml", line 401, characters 2-20: +401 | | [],_,(100|103|104) -> 5 + ^^^^^^^^^^^^^^^^^^ Warning 11: this match case is unused. File "morematch.ml", line 402, characters 2-16: +402 | | [],_,(100|103) -> 6 + ^^^^^^^^^^^^^^ Warning 11: this match case is unused. File "morematch.ml", line 403, characters 2-29: +403 | | [],_,(1000|1001|1002|20000) -> 7 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 11: this match case is unused. File "morematch.ml", line 413, characters 5-12: +413 | | (100|103|101) -> 2 + ^^^^^^^ Warning 12: this sub-pattern is unused. File "morematch.ml", line 432, characters 43-44: +432 | | (J,J,((C|D) as x |E x|F (_,x))) | (J,_,((C|J) as x)) -> autre (x,x,x) + ^ Warning 12: this sub-pattern is unused. File "morematch.ml", line 455, characters 7-8: +455 | | _,_,(X|U _) -> 8 + ^ Warning 12: this sub-pattern is unused. File "morematch.ml", line 456, characters 2-7: +456 | | _,_,Y -> 5 + ^^^^^ Warning 11: this match case is unused. +File "morematch.ml", line 1050, characters 8-65: +1050 | ........function +1051 | | A (`A|`C) -> 0 +1052 | | B (`B,`D) -> 1 +1053 | | C -> 2 +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +(A `D|B (`B, (`A|`C))) File "morematch.ml", line 1084, characters 5-51: +1084 | | _, _, _, _, _, A, _, _, _, _, B, _, _, _, _, _ -> "11" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 11: this match case is unused. File "morematch.ml", line 1086, characters 5-51: +1086 | | _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ -> "13" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 11: this match case is unused. diff --git a/testsuite/tests/basic-more/morematch.ml b/testsuite/tests/basic-more/morematch.ml index 99d0d61d..e9a83ff6 100644 --- a/testsuite/tests/basic-more/morematch.ml +++ b/testsuite/tests/basic-more/morematch.ml @@ -1132,7 +1132,7 @@ exception Error of string let lucexn e = try try raise e with Error msg -> msg - with Found (s,r) -> s^string_of_int r + with Found (s,r) -> s^Int.to_string r let () = test "lucexn1" lucexn (Error "coucou") "coucou" ; diff --git a/testsuite/tests/basic-more/robustmatch.compilers.reference b/testsuite/tests/basic-more/robustmatch.compilers.reference index 2ccfe59b..333a214d 100644 --- a/testsuite/tests/basic-more/robustmatch.compilers.reference +++ b/testsuite/tests/basic-more/robustmatch.compilers.reference @@ -1,107 +1,196 @@ File "robustmatch.ml", line 33, characters 6-122: +33 | ......match t1, t2, x with +34 | | AB, AB, A -> () +35 | | MAB, _, A -> () +36 | | _, AB, B -> () +37 | | _, MAB, B -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (AB, MAB, A) File "robustmatch.ml", line 54, characters 4-73: +54 | ....match r1, r2, a with +55 | | R1, _, 0 -> () +56 | | _, R2, "coucou" -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R1, R1, 1) File "robustmatch.ml", line 64, characters 4-73: +64 | ....match r1, r2, a with +65 | | R1, _, A -> () +66 | | _, R2, "coucou" -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R1, R1, (B|C)) File "robustmatch.ml", line 69, characters 4-73: +69 | ....match r1, r2, a with +70 | | _, R2, "coucou" -> () +71 | | R1, _, A -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R1, R1, (B|C)) File "robustmatch.ml", line 74, characters 4-73: +74 | ....match r1, r2, a with +75 | | _, R2, "coucou" -> () +76 | | R1, _, _ -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R2, R2, "") File "robustmatch.ml", line 85, characters 4-66: +85 | ....match r1, r2, a with +86 | | R1, _, A -> () +87 | | _, R2, X -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R1, R1, (B|C)) File "robustmatch.ml", line 90, characters 4-87: +90 | ....match r1, r2, a with +91 | | R1, _, A -> () +92 | | _, R2, X -> () +93 | | R1, _, _ -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R2, R2, (Y|Z)) File "robustmatch.ml", line 96, characters 4-66: +96 | ....match r1, r2, a with +97 | | R1, _, _ -> () +98 | | _, R2, X -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R2, R2, (Y|Z)) File "robustmatch.ml", line 107, characters 4-66: +107 | ....match r1, r2, a with +108 | | R1, _, A -> () +109 | | _, R2, X -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R1, R1, (B|C)) File "robustmatch.ml", line 129, characters 4-66: +129 | ....match r1, r2, a with +130 | | R1, _, A -> () +131 | | _, R2, X -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R1, R1, B) File "robustmatch.ml", line 151, characters 4-66: +151 | ....match r1, r2, a with +152 | | R1, _, A -> () +153 | | _, R2, X -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R1, R1, B) File "robustmatch.ml", line 156, characters 4-87: +156 | ....match r1, r2, a with +157 | | R1, _, A -> () +158 | | _, R2, X -> () +159 | | R1, _, _ -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R2, R2, Y) File "robustmatch.ml", line 162, characters 4-66: +162 | ....match r1, r2, a with +163 | | R1, _, _ -> () +164 | | _, R2, X -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R2, R2, Y) File "robustmatch.ml", line 167, characters 4-66: +167 | ....match r1, r2, a with +168 | | R1, _, C -> () +169 | | _, R2, Y -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R1, R1, A) File "robustmatch.ml", line 176, characters 4-90: +176 | ....match r1, r2, a with +177 | | _, R1, 0 -> () +178 | | R2, _, [||] -> () +179 | | _, R1, 1 -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R2, R2, [| _ |]) File "robustmatch.ml", line 182, characters 4-69: +182 | ....match r1, r2, a with +183 | | R1, _, _ -> () +184 | | _, R2, [||] -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R2, R2, [| _ |]) File "robustmatch.ml", line 187, characters 4-90: +187 | ....match r1, r2, a with +188 | | _, R2, [||] -> () +189 | | R1, _, 0 -> () +190 | | R1, _, _ -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R2, R2, [| _ |]) File "robustmatch.ml", line 200, characters 4-89: +200 | ....match r1, r2, a with +201 | | _, R2, [||] -> () +202 | | R1, _, 0 -> () +203 | | _, _, _ -> () Warning 4: this pattern-matching is fragile. It will remain exhaustive when constructors are added to type repr. File "robustmatch.ml", line 210, characters 4-75: +210 | ....match r1, r2, a with +211 | | R1, _, 'c' -> () +212 | | _, R2, "coucou" -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R1, R1, 'a') File "robustmatch.ml", line 219, characters 4-74: +219 | ....match r1, r2, a with +220 | | R1, _, `A -> () +221 | | _, R2, "coucou" -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R1, R1, `B) File "robustmatch.ml", line 228, characters 4-89: +228 | ....match r1, r2, a with +229 | | R1, _, (3, "") -> () +230 | | _, R2, (1, "coucou", 'a') -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R1, R1, (3, "*")) File "robustmatch.ml", line 239, characters 4-113: +239 | ....match r1, r2, a with +240 | | R1, _, { x = 3; y = "" } -> () +241 | | _, R2, { a = 1; b = "coucou"; c = 'a' } -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R1, R1, {x=3; y="*"}) File "robustmatch.ml", line 244, characters 4-113: +244 | ....match r1, r2, a with +245 | | R2, _, { a = 1; b = "coucou"; c = 'a' } -> () +246 | | _, R1, { x = 3; y = "" } -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R2, R2, {a=1; b="coucou"; c='b'}) File "robustmatch.ml", line 253, characters 4-72: +253 | ....match r1, r2, a with +254 | | R1, _, (3, "") -> () +255 | | _, R2, 1 -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R1, R1, (3, "*")) File "robustmatch.ml", line 263, characters 4-82: +263 | ....match r1, r2, a with +264 | | R1, _, { x = 3; y = "" } -> () +265 | | _, R2, 1 -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R1, R1, {x=3; y="*"}) File "robustmatch.ml", line 272, characters 4-71: +272 | ....match r1, r2, a with +273 | | R1, _, lazy 1 -> () +274 | | _, R2, 1 -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R1, R1, lazy 0) File "robustmatch.ml", line 281, characters 4-99: +281 | ....match r1, r2, a with +282 | | R1, _, () -> () +283 | | _, R2, "coucou" -> () +284 | | _, R2, "foo" -> () Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (R2, R2, "") diff --git a/testsuite/tests/basic-more/structural_constants.ml b/testsuite/tests/basic-more/structural_constants.ml index 21bb5b2f..66cff92b 100644 --- a/testsuite/tests/basic-more/structural_constants.ml +++ b/testsuite/tests/basic-more/structural_constants.ml @@ -127,90 +127,97 @@ let long_array = 962; 963; 964; 965; 966; 967; 968; 969; 970; 971; 972; 973; 974; 975; 976; 977; 978; 979; 980; 981; 982; 983; 984; 985; 986; 987; 988; 989; 990; 991; 992; 993; 994; 995; 996; 997; 998; 999; 1000; - 1001; 1002; 1003; 1004; 1005; 1006; 1007; 1008; 1009; 1010; 1011; 1012; 1013; - 1014; 1015; 1016; 1017; 1018; 1019; 1020; 1021; 1022; 1023; 1024; 1025; 1026; - 1027; 1028; 1029; 1030; 1031; 1032; 1033; 1034; 1035; 1036; 1037; 1038; 1039; - 1040; 1041; 1042; 1043; 1044; 1045; 1046; 1047; 1048; 1049; 1050; 1051; 1052; - 1053; 1054; 1055; 1056; 1057; 1058; 1059; 1060; 1061; 1062; 1063; 1064; 1065; - 1066; 1067; 1068; 1069; 1070; 1071; 1072; 1073; 1074; 1075; 1076; 1077; 1078; - 1079; 1080; 1081; 1082; 1083; 1084; 1085; 1086; 1087; 1088; 1089; 1090; 1091; - 1092; 1093; 1094; 1095; 1096; 1097; 1098; 1099; 1100; 1101; 1102; 1103; 1104; - 1105; 1106; 1107; 1108; 1109; 1110; 1111; 1112; 1113; 1114; 1115; 1116; 1117; - 1118; 1119; 1120; 1121; 1122; 1123; 1124; 1125; 1126; 1127; 1128; 1129; 1130; - 1131; 1132; 1133; 1134; 1135; 1136; 1137; 1138; 1139; 1140; 1141; 1142; 1143; - 1144; 1145; 1146; 1147; 1148; 1149; 1150; 1151; 1152; 1153; 1154; 1155; 1156; - 1157; 1158; 1159; 1160; 1161; 1162; 1163; 1164; 1165; 1166; 1167; 1168; 1169; - 1170; 1171; 1172; 1173; 1174; 1175; 1176; 1177; 1178; 1179; 1180; 1181; 1182; - 1183; 1184; 1185; 1186; 1187; 1188; 1189; 1190; 1191; 1192; 1193; 1194; 1195; - 1196; 1197; 1198; 1199; 1200; 1201; 1202; 1203; 1204; 1205; 1206; 1207; 1208; - 1209; 1210; 1211; 1212; 1213; 1214; 1215; 1216; 1217; 1218; 1219; 1220; 1221; - 1222; 1223; 1224; 1225; 1226; 1227; 1228; 1229; 1230; 1231; 1232; 1233; 1234; - 1235; 1236; 1237; 1238; 1239; 1240; 1241; 1242; 1243; 1244; 1245; 1246; 1247; - 1248; 1249; 1250; 1251; 1252; 1253; 1254; 1255; 1256; 1257; 1258; 1259; 1260; - 1261; 1262; 1263; 1264; 1265; 1266; 1267; 1268; 1269; 1270; 1271; 1272; 1273; - 1274; 1275; 1276; 1277; 1278; 1279; 1280; 1281; 1282; 1283; 1284; 1285; 1286; - 1287; 1288; 1289; 1290; 1291; 1292; 1293; 1294; 1295; 1296; 1297; 1298; 1299; - 1300; 1301; 1302; 1303; 1304; 1305; 1306; 1307; 1308; 1309; 1310; 1311; 1312; - 1313; 1314; 1315; 1316; 1317; 1318; 1319; 1320; 1321; 1322; 1323; 1324; 1325; - 1326; 1327; 1328; 1329; 1330; 1331; 1332; 1333; 1334; 1335; 1336; 1337; 1338; - 1339; 1340; 1341; 1342; 1343; 1344; 1345; 1346; 1347; 1348; 1349; 1350; 1351; - 1352; 1353; 1354; 1355; 1356; 1357; 1358; 1359; 1360; 1361; 1362; 1363; 1364; - 1365; 1366; 1367; 1368; 1369; 1370; 1371; 1372; 1373; 1374; 1375; 1376; 1377; - 1378; 1379; 1380; 1381; 1382; 1383; 1384; 1385; 1386; 1387; 1388; 1389; 1390; - 1391; 1392; 1393; 1394; 1395; 1396; 1397; 1398; 1399; 1400; 1401; 1402; 1403; - 1404; 1405; 1406; 1407; 1408; 1409; 1410; 1411; 1412; 1413; 1414; 1415; 1416; - 1417; 1418; 1419; 1420; 1421; 1422; 1423; 1424; 1425; 1426; 1427; 1428; 1429; - 1430; 1431; 1432; 1433; 1434; 1435; 1436; 1437; 1438; 1439; 1440; 1441; 1442; - 1443; 1444; 1445; 1446; 1447; 1448; 1449; 1450; 1451; 1452; 1453; 1454; 1455; - 1456; 1457; 1458; 1459; 1460; 1461; 1462; 1463; 1464; 1465; 1466; 1467; 1468; - 1469; 1470; 1471; 1472; 1473; 1474; 1475; 1476; 1477; 1478; 1479; 1480; 1481; - 1482; 1483; 1484; 1485; 1486; 1487; 1488; 1489; 1490; 1491; 1492; 1493; 1494; - 1495; 1496; 1497; 1498; 1499; 1500; 1501; 1502; 1503; 1504; 1505; 1506; 1507; - 1508; 1509; 1510; 1511; 1512; 1513; 1514; 1515; 1516; 1517; 1518; 1519; 1520; - 1521; 1522; 1523; 1524; 1525; 1526; 1527; 1528; 1529; 1530; 1531; 1532; 1533; - 1534; 1535; 1536; 1537; 1538; 1539; 1540; 1541; 1542; 1543; 1544; 1545; 1546; - 1547; 1548; 1549; 1550; 1551; 1552; 1553; 1554; 1555; 1556; 1557; 1558; 1559; - 1560; 1561; 1562; 1563; 1564; 1565; 1566; 1567; 1568; 1569; 1570; 1571; 1572; - 1573; 1574; 1575; 1576; 1577; 1578; 1579; 1580; 1581; 1582; 1583; 1584; 1585; - 1586; 1587; 1588; 1589; 1590; 1591; 1592; 1593; 1594; 1595; 1596; 1597; 1598; - 1599; 1600; 1601; 1602; 1603; 1604; 1605; 1606; 1607; 1608; 1609; 1610; 1611; - 1612; 1613; 1614; 1615; 1616; 1617; 1618; 1619; 1620; 1621; 1622; 1623; 1624; - 1625; 1626; 1627; 1628; 1629; 1630; 1631; 1632; 1633; 1634; 1635; 1636; 1637; - 1638; 1639; 1640; 1641; 1642; 1643; 1644; 1645; 1646; 1647; 1648; 1649; 1650; - 1651; 1652; 1653; 1654; 1655; 1656; 1657; 1658; 1659; 1660; 1661; 1662; 1663; - 1664; 1665; 1666; 1667; 1668; 1669; 1670; 1671; 1672; 1673; 1674; 1675; 1676; - 1677; 1678; 1679; 1680; 1681; 1682; 1683; 1684; 1685; 1686; 1687; 1688; 1689; - 1690; 1691; 1692; 1693; 1694; 1695; 1696; 1697; 1698; 1699; 1700; 1701; 1702; - 1703; 1704; 1705; 1706; 1707; 1708; 1709; 1710; 1711; 1712; 1713; 1714; 1715; - 1716; 1717; 1718; 1719; 1720; 1721; 1722; 1723; 1724; 1725; 1726; 1727; 1728; - 1729; 1730; 1731; 1732; 1733; 1734; 1735; 1736; 1737; 1738; 1739; 1740; 1741; - 1742; 1743; 1744; 1745; 1746; 1747; 1748; 1749; 1750; 1751; 1752; 1753; 1754; - 1755; 1756; 1757; 1758; 1759; 1760; 1761; 1762; 1763; 1764; 1765; 1766; 1767; - 1768; 1769; 1770; 1771; 1772; 1773; 1774; 1775; 1776; 1777; 1778; 1779; 1780; - 1781; 1782; 1783; 1784; 1785; 1786; 1787; 1788; 1789; 1790; 1791; 1792; 1793; - 1794; 1795; 1796; 1797; 1798; 1799; 1800; 1801; 1802; 1803; 1804; 1805; 1806; - 1807; 1808; 1809; 1810; 1811; 1812; 1813; 1814; 1815; 1816; 1817; 1818; 1819; - 1820; 1821; 1822; 1823; 1824; 1825; 1826; 1827; 1828; 1829; 1830; 1831; 1832; - 1833; 1834; 1835; 1836; 1837; 1838; 1839; 1840; 1841; 1842; 1843; 1844; 1845; - 1846; 1847; 1848; 1849; 1850; 1851; 1852; 1853; 1854; 1855; 1856; 1857; 1858; - 1859; 1860; 1861; 1862; 1863; 1864; 1865; 1866; 1867; 1868; 1869; 1870; 1871; - 1872; 1873; 1874; 1875; 1876; 1877; 1878; 1879; 1880; 1881; 1882; 1883; 1884; - 1885; 1886; 1887; 1888; 1889; 1890; 1891; 1892; 1893; 1894; 1895; 1896; 1897; - 1898; 1899; 1900; 1901; 1902; 1903; 1904; 1905; 1906; 1907; 1908; 1909; 1910; - 1911; 1912; 1913; 1914; 1915; 1916; 1917; 1918; 1919; 1920; 1921; 1922; 1923; - 1924; 1925; 1926; 1927; 1928; 1929; 1930; 1931; 1932; 1933; 1934; 1935; 1936; - 1937; 1938; 1939; 1940; 1941; 1942; 1943; 1944; 1945; 1946; 1947; 1948; 1949; - 1950; 1951; 1952; 1953; 1954; 1955; 1956; 1957; 1958; 1959; 1960; 1961; 1962; - 1963; 1964; 1965; 1966; 1967; 1968; 1969; 1970; 1971; 1972; 1973; 1974; 1975; - 1976; 1977; 1978; 1979; 1980; 1981; 1982; 1983; 1984; 1985; 1986; 1987; 1988; - 1989; 1990; 1991; 1992; 1993; 1994; 1995; 1996; 1997; 1998; 1999; 2000; 2001; - 2002; 2003; 2004; 2005; 2006; 2007; 2008; 2009; 2010; 2011; 2012; 2013; 2014; - 2015; 2016; 2017; 2018; 2019; 2020; 2021; 2022; 2023; 2024; 2025; 2026; 2027; - 2028; 2029; 2030; 2031; 2032; 2033; 2034; 2035; 2036; 2037; 2038; 2039; 2040; - 2041; 2042; 2043; 2044; 2045; 2046; 2047; 2048; 2049; 2050; 2051; 2052; 2053; - 2054; 2055; 2056; 2057; 2058; 2059; 2060; 2061; 2062; 2063; 2064; 2065; 2066; - 2067; 2068; 2069; 2070; 2071; 2072; 2073; 2074; 2075; 2076; 2077; 2078; 2079; - 2080; 2081; 2082; 2083; 2084; 2085; 2086; 2087; 2088; 2089; 2090; 2091; 2092; + 1001; 1002; 1003; 1004; 1005; 1006; 1007; 1008; 1009; 1010; 1011; 1012; + 1013; 1014; 1015; 1016; 1017; 1018; 1019; 1020; 1021; 1022; 1023; 1024; + 1025; 1026; 1027; 1028; 1029; 1030; 1031; 1032; 1033; 1034; 1035; 1036; + 1037; 1038; 1039; 1040; 1041; 1042; 1043; 1044; 1045; 1046; 1047; 1048; + 1049; 1050; 1051; 1052; 1053; 1054; 1055; 1056; 1057; 1058; 1059; 1060; + 1061; 1062; 1063; 1064; 1065; 1066; 1067; 1068; 1069; 1070; 1071; 1072; + 1073; 1074; 1075; 1076; 1077; 1078; 1079; 1080; 1081; 1082; 1083; 1084; + 1085; 1086; 1087; 1088; 1089; 1090; 1091; 1092; 1093; 1094; 1095; 1096; + 1097; 1098; 1099; 1100; 1101; 1102; 1103; 1104; 1105; 1106; 1107; 1108; + 1109; 1110; 1111; 1112; 1113; 1114; 1115; 1116; 1117; 1118; 1119; 1120; + 1121; 1122; 1123; 1124; 1125; 1126; 1127; 1128; 1129; 1130; 1131; 1132; + 1133; 1134; 1135; 1136; 1137; 1138; 1139; 1140; 1141; 1142; 1143; 1144; + 1145; 1146; 1147; 1148; 1149; 1150; 1151; 1152; 1153; 1154; 1155; 1156; + 1157; 1158; 1159; 1160; 1161; 1162; 1163; 1164; 1165; 1166; 1167; 1168; + 1169; 1170; 1171; 1172; 1173; 1174; 1175; 1176; 1177; 1178; 1179; 1180; + 1181; 1182; 1183; 1184; 1185; 1186; 1187; 1188; 1189; 1190; 1191; 1192; + 1193; 1194; 1195; 1196; 1197; 1198; 1199; 1200; 1201; 1202; 1203; 1204; + 1205; 1206; 1207; 1208; 1209; 1210; 1211; 1212; 1213; 1214; 1215; 1216; + 1217; 1218; 1219; 1220; 1221; 1222; 1223; 1224; 1225; 1226; 1227; 1228; + 1229; 1230; 1231; 1232; 1233; 1234; 1235; 1236; 1237; 1238; 1239; 1240; + 1241; 1242; 1243; 1244; 1245; 1246; 1247; 1248; 1249; 1250; 1251; 1252; + 1253; 1254; 1255; 1256; 1257; 1258; 1259; 1260; 1261; 1262; 1263; 1264; + 1265; 1266; 1267; 1268; 1269; 1270; 1271; 1272; 1273; 1274; 1275; 1276; + 1277; 1278; 1279; 1280; 1281; 1282; 1283; 1284; 1285; 1286; 1287; 1288; + 1289; 1290; 1291; 1292; 1293; 1294; 1295; 1296; 1297; 1298; 1299; 1300; + 1301; 1302; 1303; 1304; 1305; 1306; 1307; 1308; 1309; 1310; 1311; 1312; + 1313; 1314; 1315; 1316; 1317; 1318; 1319; 1320; 1321; 1322; 1323; 1324; + 1325; 1326; 1327; 1328; 1329; 1330; 1331; 1332; 1333; 1334; 1335; 1336; + 1337; 1338; 1339; 1340; 1341; 1342; 1343; 1344; 1345; 1346; 1347; 1348; + 1349; 1350; 1351; 1352; 1353; 1354; 1355; 1356; 1357; 1358; 1359; 1360; + 1361; 1362; 1363; 1364; 1365; 1366; 1367; 1368; 1369; 1370; 1371; 1372; + 1373; 1374; 1375; 1376; 1377; 1378; 1379; 1380; 1381; 1382; 1383; 1384; + 1385; 1386; 1387; 1388; 1389; 1390; 1391; 1392; 1393; 1394; 1395; 1396; + 1397; 1398; 1399; 1400; 1401; 1402; 1403; 1404; 1405; 1406; 1407; 1408; + 1409; 1410; 1411; 1412; 1413; 1414; 1415; 1416; 1417; 1418; 1419; 1420; + 1421; 1422; 1423; 1424; 1425; 1426; 1427; 1428; 1429; 1430; 1431; 1432; + 1433; 1434; 1435; 1436; 1437; 1438; 1439; 1440; 1441; 1442; 1443; 1444; + 1445; 1446; 1447; 1448; 1449; 1450; 1451; 1452; 1453; 1454; 1455; 1456; + 1457; 1458; 1459; 1460; 1461; 1462; 1463; 1464; 1465; 1466; 1467; 1468; + 1469; 1470; 1471; 1472; 1473; 1474; 1475; 1476; 1477; 1478; 1479; 1480; + 1481; 1482; 1483; 1484; 1485; 1486; 1487; 1488; 1489; 1490; 1491; 1492; + 1493; 1494; 1495; 1496; 1497; 1498; 1499; 1500; 1501; 1502; 1503; 1504; + 1505; 1506; 1507; 1508; 1509; 1510; 1511; 1512; 1513; 1514; 1515; 1516; + 1517; 1518; 1519; 1520; 1521; 1522; 1523; 1524; 1525; 1526; 1527; 1528; + 1529; 1530; 1531; 1532; 1533; 1534; 1535; 1536; 1537; 1538; 1539; 1540; + 1541; 1542; 1543; 1544; 1545; 1546; 1547; 1548; 1549; 1550; 1551; 1552; + 1553; 1554; 1555; 1556; 1557; 1558; 1559; 1560; 1561; 1562; 1563; 1564; + 1565; 1566; 1567; 1568; 1569; 1570; 1571; 1572; 1573; 1574; 1575; 1576; + 1577; 1578; 1579; 1580; 1581; 1582; 1583; 1584; 1585; 1586; 1587; 1588; + 1589; 1590; 1591; 1592; 1593; 1594; 1595; 1596; 1597; 1598; 1599; 1600; + 1601; 1602; 1603; 1604; 1605; 1606; 1607; 1608; 1609; 1610; 1611; 1612; + 1613; 1614; 1615; 1616; 1617; 1618; 1619; 1620; 1621; 1622; 1623; 1624; + 1625; 1626; 1627; 1628; 1629; 1630; 1631; 1632; 1633; 1634; 1635; 1636; + 1637; 1638; 1639; 1640; 1641; 1642; 1643; 1644; 1645; 1646; 1647; 1648; + 1649; 1650; 1651; 1652; 1653; 1654; 1655; 1656; 1657; 1658; 1659; 1660; + 1661; 1662; 1663; 1664; 1665; 1666; 1667; 1668; 1669; 1670; 1671; 1672; + 1673; 1674; 1675; 1676; 1677; 1678; 1679; 1680; 1681; 1682; 1683; 1684; + 1685; 1686; 1687; 1688; 1689; 1690; 1691; 1692; 1693; 1694; 1695; 1696; + 1697; 1698; 1699; 1700; 1701; 1702; 1703; 1704; 1705; 1706; 1707; 1708; + 1709; 1710; 1711; 1712; 1713; 1714; 1715; 1716; 1717; 1718; 1719; 1720; + 1721; 1722; 1723; 1724; 1725; 1726; 1727; 1728; 1729; 1730; 1731; 1732; + 1733; 1734; 1735; 1736; 1737; 1738; 1739; 1740; 1741; 1742; 1743; 1744; + 1745; 1746; 1747; 1748; 1749; 1750; 1751; 1752; 1753; 1754; 1755; 1756; + 1757; 1758; 1759; 1760; 1761; 1762; 1763; 1764; 1765; 1766; 1767; 1768; + 1769; 1770; 1771; 1772; 1773; 1774; 1775; 1776; 1777; 1778; 1779; 1780; + 1781; 1782; 1783; 1784; 1785; 1786; 1787; 1788; 1789; 1790; 1791; 1792; + 1793; 1794; 1795; 1796; 1797; 1798; 1799; 1800; 1801; 1802; 1803; 1804; + 1805; 1806; 1807; 1808; 1809; 1810; 1811; 1812; 1813; 1814; 1815; 1816; + 1817; 1818; 1819; 1820; 1821; 1822; 1823; 1824; 1825; 1826; 1827; 1828; + 1829; 1830; 1831; 1832; 1833; 1834; 1835; 1836; 1837; 1838; 1839; 1840; + 1841; 1842; 1843; 1844; 1845; 1846; 1847; 1848; 1849; 1850; 1851; 1852; + 1853; 1854; 1855; 1856; 1857; 1858; 1859; 1860; 1861; 1862; 1863; 1864; + 1865; 1866; 1867; 1868; 1869; 1870; 1871; 1872; 1873; 1874; 1875; 1876; + 1877; 1878; 1879; 1880; 1881; 1882; 1883; 1884; 1885; 1886; 1887; 1888; + 1889; 1890; 1891; 1892; 1893; 1894; 1895; 1896; 1897; 1898; 1899; 1900; + 1901; 1902; 1903; 1904; 1905; 1906; 1907; 1908; 1909; 1910; 1911; 1912; + 1913; 1914; 1915; 1916; 1917; 1918; 1919; 1920; 1921; 1922; 1923; 1924; + 1925; 1926; 1927; 1928; 1929; 1930; 1931; 1932; 1933; 1934; 1935; 1936; + 1937; 1938; 1939; 1940; 1941; 1942; 1943; 1944; 1945; 1946; 1947; 1948; + 1949; 1950; 1951; 1952; 1953; 1954; 1955; 1956; 1957; 1958; 1959; 1960; + 1961; 1962; 1963; 1964; 1965; 1966; 1967; 1968; 1969; 1970; 1971; 1972; + 1973; 1974; 1975; 1976; 1977; 1978; 1979; 1980; 1981; 1982; 1983; 1984; + 1985; 1986; 1987; 1988; 1989; 1990; 1991; 1992; 1993; 1994; 1995; 1996; + 1997; 1998; 1999; 2000; 2001; 2002; 2003; 2004; 2005; 2006; 2007; 2008; + 2009; 2010; 2011; 2012; 2013; 2014; 2015; 2016; 2017; 2018; 2019; 2020; + 2021; 2022; 2023; 2024; 2025; 2026; 2027; 2028; 2029; 2030; 2031; 2032; + 2033; 2034; 2035; 2036; 2037; 2038; 2039; 2040; 2041; 2042; 2043; 2044; + 2045; 2046; 2047; 2048; 2049; 2050; 2051; 2052; 2053; 2054; 2055; 2056; + 2057; 2058; 2059; 2060; 2061; 2062; 2063; 2064; 2065; 2066; 2067; 2068; + 2069; 2070; 2071; 2072; 2073; 2074; 2075; 2076; 2077; 2078; 2079; 2080; + 2081; 2082; 2083; 2084; 2085; 2086; 2087; 2088; 2089; 2090; 2091; 2092; 2093; 2094; |] let () = diff --git a/testsuite/tests/basic/boxedints.ml b/testsuite/tests/basic/boxedints.ml index e3ff7000..8705dbb8 100644 --- a/testsuite/tests/basic/boxedints.ml +++ b/testsuite/tests/basic/boxedints.ml @@ -35,6 +35,7 @@ module type TESTSIG = sig val sub: t -> t -> t val mul: t -> t -> t val div: t -> t -> t + val unsigned_div: t -> t -> t val rem: t -> t -> t val logand: t -> t -> t val logor: t -> t -> t @@ -44,6 +45,7 @@ module type TESTSIG = sig val shift_right_logical: t -> int -> t val of_int: int -> t val to_int: t -> int + val unsigned_to_int: t -> int option val of_float: float -> t val to_float: t -> float val zero: t @@ -55,7 +57,7 @@ module type TESTSIG = sig val to_string: t -> string val of_string: string -> t end - val testcomp: t -> t -> bool*bool*bool*bool*bool*bool*int + val testcomp: t -> t -> bool*bool*bool*bool*bool*bool*int*int val skip_float_tests: bool end @@ -72,6 +74,30 @@ struct test 4 (to_int (of_int 0x3FFFFFFF)) 0x3FFFFFFF; test 5 (to_int (of_int (-0x40000000))) (-0x40000000); + testing_function "unsigned_to_int"; + test 1 (unsigned_to_int (of_int 0)) (Some 0); + test 2 (unsigned_to_int (of_int 123)) (Some 123); + test 3 (unsigned_to_int minus_one) + (match Sys.word_size with + | 32 -> None + | 64 -> Some (int_of_string "0xFFFFFFFF") + | _ -> assert false); + test 4 (unsigned_to_int max_int) + (match Sys.word_size with + | 32 -> None + | 64 -> Some (to_int max_int) + | _ -> assert false); + test 5 (unsigned_to_int min_int) + (match Sys.word_size with + | 32 -> None + | 64 -> Some (int_of_string "0x80000000") + | _ -> assert false); + test 6 (unsigned_to_int (of_int Stdlib.max_int)) + (match Sys.word_size with + | 32 -> Some Stdlib.max_int + | 64 -> Some (int_of_string "0xFFFFFFFF") + | _ -> assert false); + testing_function "of_string"; test 1 (of_string "0") (of_int 0); test 2 (of_string "123") (of_int 123); @@ -170,6 +196,21 @@ struct 11, 1234567, -12345678]; test 12 (div min_int (of_int (-1))) min_int; + testing_function "unsigned_div"; + List.iter + (fun (n, a, b, c) -> test n (unsigned_div a b) c) + [1, of_int 0, of_int 2, of_int 0; + 2, of_int 123, of_int 1, of_int 123; + 3, of_int (-123), of_int 1, of_int (-123); + 4, of_int (123), of_int (-1), of_int 0; + 5, of_int (-123), of_int (-1), of_int 0; + 6, of_int 127531236, of_int 365, of_int (127531236/365); + 7, of_int 16384, of_int 256, of_int (16384/256); + 8, of_int (-1), of_int 2, max_int; + 9, of_int (-1), max_int, of_int 2; + 10, min_int, of_int 2, shift_left (of_int 1) 30; + 11, of_int (-1), of_int 8, shift_right_logical (of_int (-1)) 3]; + testing_function "mod"; List.iter (fun (n, a, b) -> test n (rem (of_int a) (of_int b)) (of_int (a mod b))) @@ -271,19 +312,19 @@ struct testing_function "Comparisons"; test 1 (testcomp (of_int 0) (of_int 0)) - (true,false,false,false,true,true,0); + (true,false,false,false,true,true,0,0); test 2 (testcomp (of_int 1234567) (of_int 1234567)) - (true,false,false,false,true,true,0); + (true,false,false,false,true,true,0, 0); test 3 (testcomp (of_int 0) (of_int 1)) - (false,true,true,false,true,false,-1); + (false,true,true,false,true,false,-1,-1); test 4 (testcomp (of_int (-1)) (of_int 0)) - (false,true,true,false,true,false,-1); + (false,true,true,false,true,false,-1,1); test 5 (testcomp (of_int 1) (of_int 0)) - (false,true,false,true,false,true,1); + (false,true,false,true,false,true,1,1); test 6 (testcomp (of_int 0) (of_int (-1))) - (false,true,false,true,false,true,1); + (false,true,false,true,false,true,1,-1); test 7 (testcomp max_int min_int) - (false,true,false,true,false,true,1); + (false,true,false,true,false,true,1,-1); () end @@ -303,6 +344,15 @@ struct test 4 (to_int (of_int 0x3FFFFFFF)) 0x3FFFFFFF; test 5 (to_int (of_int (-0x40000000))) (-0x40000000); + testing_function "unsigned_to_int"; + test 1 (unsigned_to_int (of_int 0)) (Some 0); + test 2 (unsigned_to_int (of_int 123)) (Some 123); + test 3 (unsigned_to_int minus_one) None; + test 4 (unsigned_to_int max_int) None; + test 5 (unsigned_to_int min_int) None; + test 6 (unsigned_to_int (of_int Stdlib.max_int)) + (Some Stdlib.max_int); + testing_function "of_string"; test 1 (of_string "0") (of_int 0); test 2 (of_string "123") (of_int 123); @@ -406,6 +456,21 @@ struct 11, 1234567, -12345678]; test 12 (div min_int (of_int (-1))) min_int; + testing_function "unsigned_div"; + List.iter + (fun (n, a, b, c) -> test n (unsigned_div a b) c) + [1, of_int 0, of_int 2, of_int 0; + 2, of_int 123, of_int 1, of_int 123; + 3, of_int (-123), of_int 1, of_int (-123); + 4, of_int (123), of_int (-1), of_int 0; + 5, of_int (-123), of_int (-1), of_int 0; + 6, of_int 127531236, of_int 365, of_int (127531236/365); + 7, of_int 16384, of_int 256, of_int (16384/256); + 8, of_int (-1), of_int 2, max_int; + 9, of_int (-1), max_int, of_int 2; + 10, min_int, of_int 2, shift_left (of_int 1) 62; + 11, of_int (-1), of_int 8, shift_right_logical (of_int (-1)) 3]; + testing_function "mod"; List.iter (fun (n, a, b) -> test n (rem (of_int a) (of_int b)) (of_int (a mod b))) @@ -489,19 +554,19 @@ struct testing_function "Comparisons"; test 1 (testcomp (of_int 0) (of_int 0)) - (true,false,false,false,true,true,0); + (true,false,false,false,true,true,0,0); test 2 (testcomp (of_int 1234567) (of_int 1234567)) - (true,false,false,false,true,true,0); + (true,false,false,false,true,true,0,0); test 3 (testcomp (of_int 0) (of_int 1)) - (false,true,true,false,true,false,-1); + (false,true,true,false,true,false,-1,-1); test 4 (testcomp (of_int (-1)) (of_int 0)) - (false,true,true,false,true,false,-1); + (false,true,true,false,true,false,-1,1); test 5 (testcomp (of_int 1) (of_int 0)) - (false,true,false,true,false,true,1); + (false,true,false,true,false,true,1,1); test 6 (testcomp (of_int 0) (of_int (-1))) - (false,true,false,true,false,true,1); + (false,true,false,true,false,true,1,-1); test 7 (testcomp max_int min_int) - (false,true,false,true,false,true,1); + (false,true,false,true,false,true,1,-1); () end @@ -509,11 +574,14 @@ end (******** The test proper **********) let testcomp_int32 (a : int32) (b : int32) = - (a = b, a <> b, a < b, a > b, a <= b, a >= b, compare a b) + (a = b, a <> b, a < b, a > b, a <= b, a >= b, compare a b, + Int32.unsigned_compare a b) let testcomp_int64 (a : int64) (b : int64) = - (a = b, a <> b, a < b, a > b, a <= b, a >= b, compare a b) + (a = b, a <> b, a < b, a > b, a <= b, a >= b, compare a b, + Int64.unsigned_compare a b) let testcomp_nativeint (a : nativeint) (b : nativeint) = - (a = b, a <> b, a < b, a > b, a <= b, a >= b, compare a b) + (a = b, a <> b, a < b, a > b, a <= b, a >= b, compare a b, + Nativeint.unsigned_compare a b) let _ = testing_function "-------- Int32 --------"; diff --git a/testsuite/tests/basic/boxedints.reference b/testsuite/tests/basic/boxedints.reference index 009390fa..8aa45802 100644 --- a/testsuite/tests/basic/boxedints.reference +++ b/testsuite/tests/basic/boxedints.reference @@ -3,6 +3,8 @@ of_int, to_int 1... 2... 3... 4... 5... +unsigned_to_int + 1... 2... 3... 4... 5... 6... of_string 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... to_string, format @@ -17,6 +19,8 @@ mul 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13... div 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... +unsigned_div + 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... mod 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... and @@ -42,6 +46,8 @@ Comparisons of_int, to_int 1... 2... 3... 4... 5... +unsigned_to_int + 1... 2... 3... 4... 5... 6... of_string 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... to_string, format @@ -56,6 +62,8 @@ mul 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13... div 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... +unsigned_div + 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... mod 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... and @@ -77,6 +85,8 @@ Comparisons of_int, to_int 1... 2... 3... 4... 5... +unsigned_to_int + 1... 2... 3... 4... 5... 6... of_string 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... to_string, format @@ -91,6 +101,8 @@ mul 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... 13... div 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... +unsigned_div + 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... mod 1... 2... 3... 4... 5... 6... 7... 8... 9... 10... 11... 12... and diff --git a/testsuite/tests/basic/camlCase.ml b/testsuite/tests/basic/camlCase.ml new file mode 100644 index 00000000..cd298427 --- /dev/null +++ b/testsuite/tests/basic/camlCase.ml @@ -0,0 +1 @@ +let answer = 42 diff --git a/testsuite/tests/basic/constprop.ml b/testsuite/tests/basic/constprop.ml deleted file mode 100644 index c89b1824..00000000 --- a/testsuite/tests/basic/constprop.ml +++ /dev/null @@ -1,124 +0,0 @@ -(* TEST - flags = "-pp '${c_preprocessor}'" - * bytecode - compare_programs = "false" - * native -*) - -(* Test constant propagation through inlining *) - -(* constprop.ml is generated from constprop.mlp using - cpp constprop.mlp > constprop.ml -*) - -#define tbool(x,y) \ - (x && y, x || y, not x) - -#define tint(x,y,s) \ - (-x, x + y, x - y, x * y, x / y, x mod y, \ - x land y, x lor y, x lxor y, \ - x lsl s, x lsr s, x asr s, \ - x = y, x <> y, x < y, x <= y, x > y, x >= y, \ - succ x, pred y) - -#define tfloat(x,y) \ - (int_of_float x, \ - x +. y, x -. y, x *. y, x /. y, \ - x = y, x <> y, x < y, x <= y, x > y, x >= y) - -#define tconvint(i) \ - (float_of_int i, \ - Int32.of_int i, \ - Nativeint.of_int i, \ - Int64.of_int i) - -#define tconvint32(i) \ - (Int32.to_int i, \ - Nativeint.of_int32 i, \ - Int64.of_int32 i) - -#define tconvnativeint(i) \ - (Nativeint.to_int i, \ - Nativeint.to_int32 i, \ - Int64.of_nativeint i) - -#define tconvint64(i) \ - (Int64.to_int i, \ - Int64.to_int32 i, \ - Int64.to_nativeint i) \ - -#define tint32(x,y,s) \ - Int32.(neg x, add x y, sub x y, mul x y, div x y, rem x y, \ - logand x y, logor x y, logxor x y, \ - shift_left x s, shift_right x s, shift_right_logical x s, \ - x = y, x <> y, x < y, x <= y, x > y, x >= y) - -#define tnativeint(x,y,s) \ - Nativeint.(neg x, add x y, sub x y, mul x y, div x y, rem x y, \ - logand x y, logor x y, logxor x y, \ - shift_left x s, shift_right x s, shift_right_logical x s, \ - x = y, x <> y, x < y, x <= y, x > y, x >= y) - -#define tint64(x,y,s) \ - Int64.(neg x, add x y, sub x y, mul x y, div x y, rem x y, \ - logand x y, logor x y, logxor x y, \ - shift_left x s, shift_right x s, shift_right_logical x s, \ - x = y, x <> y, x < y, x <= y, x > y, x >= y) - -let do_test msg res1 res2 = - Printf.printf "%s: %s\n" msg (if res1 = res2 then "passed" else "FAILED") - -(* Hide a constant from the optimizer, preventing constant propagation *) -let hide x = List.nth [x] 0 - -let _ = - begin - let x = true and y = false in - let xh = hide x and yh = hide y in - do_test "booleans" (tbool(x, y)) (tbool(xh,yh)) - end; - begin - let x = 89809344 and y = 457455773 and s = 7 in - let xh = hide x and yh = hide y and sh = hide s in - do_test "integers" (tint(x, y, s)) (tint(xh,yh,sh)) - end; - begin - let x = 3.141592654 and y = 0.341638588598232096 in - let xh = hide x and yh = hide y in - do_test "floats" (tfloat(x, y)) (tfloat(xh, yh)) - end; - begin - let x = 781944104l and y = 308219921l and s = 3 in - let xh = hide x and yh = hide y and sh = hide s in - do_test "32-bit integers" (tint32(x, y, s)) (tint32(xh, yh, sh)) - end; - begin - let x = 1828697041n and y = -521695949n and s = 8 in - let xh = hide x and yh = hide y and sh = hide s in - do_test "native integers" (tnativeint(x, y, s)) (tnativeint(xh, yh, sh)) - end; - begin - let x = 1511491586921138079L and y = 6677538715441746158L and s = 17 in - let xh = hide x and yh = hide y and sh = hide s in - do_test "64-bit integers" (tint64(x, y, s)) (tint64(xh, yh, sh)) - end; - begin - let x = 1000807289 in - let xh = hide x in - do_test "integer conversions" (tconvint(x)) (tconvint(xh)) - end; - begin - let x = 10486393l in - let xh = hide x in - do_test "32-bit integer conversions" (tconvint32(x)) (tconvint32(xh)) - end; - begin - let x = -131134014n in - let xh = hide x in - do_test "native integer conversions" (tconvnativeint(x))(tconvnativeint(xh)) - end; - begin - let x = 531871273453404175L in - let xh = hide x in - do_test "64-bit integer conversions" (tconvint64(x)) (tconvint64(xh)) - end diff --git a/testsuite/tests/basic/constprop.ml.c b/testsuite/tests/basic/constprop.ml.c new file mode 100644 index 00000000..ee23d489 --- /dev/null +++ b/testsuite/tests/basic/constprop.ml.c @@ -0,0 +1,130 @@ +(* TEST + flags = "-pp '${c_preprocessor}'" + ocaml_filetype_flag = "-impl" + * bytecode + compare_programs = "false" + * native +*) + +(* This file has extension .ml.c because it needs to be preprocessed + by the C preprocessor, which requires a .c extension when called + through the C compiler +*) + +(* Test constant propagation through inlining *) + +(* constprop.ml is generated from constprop.mlp using + cpp constprop.mlp > constprop.ml +*) + +#define tbool(x,y) \ + (x && y, x || y, not x) + +#define tint(x,y,s) \ + (-x, x + y, x - y, x * y, x / y, x mod y, \ + x land y, x lor y, x lxor y, \ + x lsl s, x lsr s, x asr s, \ + x = y, x <> y, x < y, x <= y, x > y, x >= y, \ + succ x, pred y) + +#define tfloat(x,y) \ + (int_of_float x, \ + x +. y, x -. y, x *. y, x /. y, \ + x = y, x <> y, x < y, x <= y, x > y, x >= y) + +#define tconvint(i) \ + (float_of_int i, \ + Int32.of_int i, \ + Nativeint.of_int i, \ + Int64.of_int i) + +#define tconvint32(i) \ + (Int32.to_int i, \ + Nativeint.of_int32 i, \ + Int64.of_int32 i) + +#define tconvnativeint(i) \ + (Nativeint.to_int i, \ + Nativeint.to_int32 i, \ + Int64.of_nativeint i) + +#define tconvint64(i) \ + (Int64.to_int i, \ + Int64.to_int32 i, \ + Int64.to_nativeint i) \ + +#define tint32(x,y,s) \ + Int32.(neg x, add x y, sub x y, mul x y, div x y, rem x y, \ + logand x y, logor x y, logxor x y, \ + shift_left x s, shift_right x s, shift_right_logical x s, \ + x = y, x <> y, x < y, x <= y, x > y, x >= y) + +#define tnativeint(x,y,s) \ + Nativeint.(neg x, add x y, sub x y, mul x y, div x y, rem x y, \ + logand x y, logor x y, logxor x y, \ + shift_left x s, shift_right x s, shift_right_logical x s, \ + x = y, x <> y, x < y, x <= y, x > y, x >= y) + +#define tint64(x,y,s) \ + Int64.(neg x, add x y, sub x y, mul x y, div x y, rem x y, \ + logand x y, logor x y, logxor x y, \ + shift_left x s, shift_right x s, shift_right_logical x s, \ + x = y, x <> y, x < y, x <= y, x > y, x >= y) + +let do_test msg res1 res2 = + Printf.printf "%s: %s\n" msg (if res1 = res2 then "passed" else "FAILED") + +(* Hide a constant from the optimizer, preventing constant propagation *) +let hide x = List.nth [x] 0 + +let _ = + begin + let x = true and y = false in + let xh = hide x and yh = hide y in + do_test "booleans" (tbool(x, y)) (tbool(xh,yh)) + end; + begin + let x = 89809344 and y = 457455773 and s = 7 in + let xh = hide x and yh = hide y and sh = hide s in + do_test "integers" (tint(x, y, s)) (tint(xh,yh,sh)) + end; + begin + let x = 3.141592654 and y = 0.341638588598232096 in + let xh = hide x and yh = hide y in + do_test "floats" (tfloat(x, y)) (tfloat(xh, yh)) + end; + begin + let x = 781944104l and y = 308219921l and s = 3 in + let xh = hide x and yh = hide y and sh = hide s in + do_test "32-bit integers" (tint32(x, y, s)) (tint32(xh, yh, sh)) + end; + begin + let x = 1828697041n and y = -521695949n and s = 8 in + let xh = hide x and yh = hide y and sh = hide s in + do_test "native integers" (tnativeint(x, y, s)) (tnativeint(xh, yh, sh)) + end; + begin + let x = 1511491586921138079L and y = 6677538715441746158L and s = 17 in + let xh = hide x and yh = hide y and sh = hide s in + do_test "64-bit integers" (tint64(x, y, s)) (tint64(xh, yh, sh)) + end; + begin + let x = 1000807289 in + let xh = hide x in + do_test "integer conversions" (tconvint(x)) (tconvint(xh)) + end; + begin + let x = 10486393l in + let xh = hide x in + do_test "32-bit integer conversions" (tconvint32(x)) (tconvint32(xh)) + end; + begin + let x = -131134014n in + let xh = hide x in + do_test "native integer conversions" (tconvnativeint(x))(tconvnativeint(xh)) + end; + begin + let x = 531871273453404175L in + let xh = hide x in + do_test "64-bit integer conversions" (tconvint64(x)) (tconvint64(xh)) + end diff --git a/testsuite/tests/basic/constprop.reference b/testsuite/tests/basic/constprop.ml.reference similarity index 100% rename from testsuite/tests/basic/constprop.reference rename to testsuite/tests/basic/constprop.ml.reference diff --git a/testsuite/tests/basic/eval_order_4.ml b/testsuite/tests/basic/eval_order_4.ml index 0e7130a9..98de05fb 100644 --- a/testsuite/tests/basic/eval_order_4.ml +++ b/testsuite/tests/basic/eval_order_4.ml @@ -7,9 +7,9 @@ let f = in fun q -> fun i -> "") (print_endline "x") let _ = - let k = - (let _i = print_int 1 - in fun q -> fun i -> "") () + let k = + (let _i = print_int 1 + in fun q -> fun i -> "") () in k (print_int 0) let () = diff --git a/testsuite/tests/basic/eval_order_6.ml b/testsuite/tests/basic/eval_order_6.ml index bec1f7ed..b9ecf42f 100644 --- a/testsuite/tests/basic/eval_order_6.ml +++ b/testsuite/tests/basic/eval_order_6.ml @@ -11,9 +11,8 @@ let r = { x = 10; y = 20 };; let h = f r;; -print_endline (string_of_int (h ()));; +print_endline (Int.to_string (h ()));; r.x <- 20;; -print_endline (string_of_int (h ()));; - +print_endline (Int.to_string (h ()));; diff --git a/testsuite/tests/basic/localfunction.ml b/testsuite/tests/basic/localfunction.ml new file mode 100755 index 00000000..6ea7b5d7 --- /dev/null +++ b/testsuite/tests/basic/localfunction.ml @@ -0,0 +1,32 @@ +(* TEST *) + +let f x = + let r = ref 0 in + let ret x = r := x in + let[@local] g y = ret (x * y) in + begin match x with + | 0 -> ret 0 + | 1 -> g 10 + | _ -> + if x < 10 then g 20 else g 30 + end; + !r + +let () = + let x0 = Gc.allocated_bytes () in + let x1 = Gc.allocated_bytes () in + let r = ref 0 in + for i = 0 to 20 do r := !r + f i done; + let x2 = Gc.allocated_bytes () in + Printf.printf "%i\n%!" !r; + assert(x1 -. x0 = x2 -. x1) + (* check that we did not allocated anything between x1 and x2 *) + + +let () = + (* #8558 *) + let f () = () in + let r = ref 0 in + let g () = f (incr r) in + g (); + assert (!r = 1) diff --git a/testsuite/tests/basic/localfunction.reference b/testsuite/tests/basic/localfunction.reference new file mode 100755 index 00000000..e44974eb --- /dev/null +++ b/testsuite/tests/basic/localfunction.reference @@ -0,0 +1 @@ +5840 diff --git a/testsuite/tests/basic/maps.ml b/testsuite/tests/basic/maps.ml index 9ed19c0f..52504d06 100644 --- a/testsuite/tests/basic/maps.ml +++ b/testsuite/tests/basic/maps.ml @@ -54,7 +54,8 @@ let () = List.iter (function (k, f) -> let m1 = update i f m in let m2 = IntMap.update i f m in - if not (IntMap.equal ( = ) m1 m2 && ((m1 == m) = (m2 == m))) then begin + if not (IntMap.equal ( = ) m1 m2 && ((m1 == m) = (m2 == m))) then + begin Printf.printf "ERROR: %s: %d -> %d\n" k i j; print_endline "expected result:"; show m1; @@ -63,10 +64,11 @@ let () = end ) [ - "replace", (function None -> None | Some _ -> Some j); - "delete if exists, bind otherwise", (function None -> Some j | Some _ -> None); - "delete", (function None -> None | Some _ -> None); - "insert", (function None -> Some j | Some _ -> Some j); + "replace", (function None -> None | Some _ -> Some j); + "delete if exists, bind otherwise", + (function None -> Some j | Some _ -> None); + "delete", (function None -> None | Some _ -> None); + "insert", (function None -> Some j | Some _ -> Some j); ] done; done; diff --git a/testsuite/tests/basic/min_int.ml b/testsuite/tests/basic/min_int.ml index 0b85db47..bfb2ff4a 100644 --- a/testsuite/tests/basic/min_int.ml +++ b/testsuite/tests/basic/min_int.ml @@ -7,6 +7,6 @@ let min_int = -1073741824 let () = match min_int with | -1073741824 as i -> - assert (string_of_int i = "-1073741824"); + assert (Int.to_string i = "-1073741824"); print_endline "OK" | _ -> assert false diff --git a/testsuite/tests/basic/ocamltests b/testsuite/tests/basic/ocamltests index 593fa408..8142a2b3 100644 --- a/testsuite/tests/basic/ocamltests +++ b/testsuite/tests/basic/ocamltests @@ -1,7 +1,7 @@ arrays.ml bigints.ml boxedints.ml -constprop.ml +constprop.ml.c divint.ml equality.ml eval_order_1.ml @@ -13,10 +13,12 @@ float.ml float_physical_equality.ml includestruct.ml localexn.ml +localfunction.ml maps.ml min_int.ml opt_variants.ml patmatch.ml +patmatch_incoherence.ml pr7253.ml pr7533.ml pr7657.ml @@ -26,4 +28,5 @@ stringmatch.ml switch_opts.ml tailcalls.ml trigraph.ml +unit_naming.ml zero_divided_by_n.ml diff --git a/testsuite/tests/basic/opt_variants.ml b/testsuite/tests/basic/opt_variants.ml index 6cc954ef..a75ca355 100755 --- a/testsuite/tests/basic/opt_variants.ml +++ b/testsuite/tests/basic/opt_variants.ml @@ -113,4 +113,22 @@ let () = W.add w r; assert (W.find_opt w r = Some r); + let stack = Stack.create () in + Stack.push 41 stack; + Stack.push 42 stack; + assert(Stack.top_opt stack = Some 42); + assert(Stack.pop_opt stack = Some 42); + assert(Stack.pop_opt stack = Some 41); + assert(Stack.pop_opt stack = None); + assert(Stack.top_opt stack = None); + + let queue = Queue.create () in + Queue.add 41 queue; + Queue.add 42 queue; + assert(Queue.peek_opt queue = Some 41); + assert(Queue.take_opt queue = Some 41); + assert(Queue.take_opt queue = Some 42); + assert(Queue.take_opt queue = None); + assert(Queue.peek_opt queue = None); + () diff --git a/testsuite/tests/basic/patmatch_incoherence.ml b/testsuite/tests/basic/patmatch_incoherence.ml new file mode 100644 index 00000000..10d38dbb --- /dev/null +++ b/testsuite/tests/basic/patmatch_incoherence.ml @@ -0,0 +1,138 @@ +(* TEST + * expect +*) + +type tlist = { x: 'a. 'a list };; +[%%expect{| +type tlist = { x : 'a. 'a list; } +|}];; + +match { x = [] } with +| { x = [] } -> () +| { x = 3 :: _ } -> () +| { x = "" :: _ } -> () +;; +[%%expect{| +- : unit = () +|}];; + + +type t = { x: 'a. 'a };; +[%%expect{| +type t = { x : 'a. 'a; } +|}];; + +match { x = assert false } with +| { x = 3 } -> () +| { x = "" } -> () +;; +[%%expect{| +Exception: Assert_failure ("", 1, 12). +|}];; + +match { x = assert false } with +| { x = 3 } -> () +| { x = None } -> () +;; +[%%expect{| +Line 1, characters 0-70: +1 | match { x = assert false } with +2 | | { x = 3 } -> () +3 | | { x = None } -> () +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +{x=Some _} +Exception: Assert_failure ("", 1, 12). +|}];; + +match { x = assert false } with +| { x = None } -> () +| { x = "" } -> () +;; +[%%expect{| +Line 1, characters 0-71: +1 | match { x = assert false } with +2 | | { x = None } -> () +3 | | { x = "" } -> () +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +{x="*"} +Exception: Assert_failure ("", 1, 12). +|}];; + +match { x = assert false } with +| { x = None } -> () +| { x = `X } -> () +;; +[%%expect{| +Line 1, characters 0-71: +1 | match { x = assert false } with +2 | | { x = None } -> () +3 | | { x = `X } -> () +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +{x=`AnyOtherTag} +Exception: Assert_failure ("", 1, 12). +|}];; + +match { x = assert false } with +| { x = [||] } -> () +| { x = 3 } -> () +;; +[%%expect{| +Line 1, characters 0-70: +1 | match { x = assert false } with +2 | | { x = [||] } -> () +3 | | { x = 3 } -> () +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +{x=0} +Exception: Assert_failure ("", 1, 12). +|}];; + +match { x = assert false } with +| { x = `X } -> () +| { x = 3 } -> () +;; +[%%expect{| +Line 1, characters 0-68: +1 | match { x = assert false } with +2 | | { x = `X } -> () +3 | | { x = 3 } -> () +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +{x=0} +Exception: Assert_failure ("", 1, 12). +|}];; + +match { x = assert false } with +| { x = `X "lol" } -> () +| { x = 3 } -> () +;; +[%%expect{| +Line 1, characters 0-74: +1 | match { x = assert false } with +2 | | { x = `X "lol" } -> () +3 | | { x = 3 } -> () +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +{x=0} +Exception: Assert_failure ("", 1, 12). +|}];; + +match { x = assert false } with +| { x = (2., "") } -> () +| { x = None } -> () +| { x = 3 } -> () +;; +[%%expect{| +Line 1, characters 0-95: +1 | match { x = assert false } with +2 | | { x = (2., "") } -> () +3 | | { x = None } -> () +4 | | { x = 3 } -> () +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +{x=0} +Exception: Assert_failure ("", 1, 12). +|}];; diff --git a/testsuite/tests/basic/pr7253.ml b/testsuite/tests/basic/pr7253.ml index 149488d0..23c51f21 100644 --- a/testsuite/tests/basic/pr7253.ml +++ b/testsuite/tests/basic/pr7253.ml @@ -13,4 +13,3 @@ let () = at_exit (fun () -> print_endline "Last"); at_exit (fun () -> print_endline "Raise"; raise My_exception); at_exit (fun () -> print_endline "First") - diff --git a/testsuite/tests/basic/switch_opts.ml b/testsuite/tests/basic/switch_opts.ml index 1a6dfb86..a32772e5 100644 --- a/testsuite/tests/basic/switch_opts.ml +++ b/testsuite/tests/basic/switch_opts.ml @@ -20,7 +20,8 @@ let testcases = [ Test (3, 3., function 1 -> 1. | 2 -> 2. | 3 -> 3. | _ -> 0.); Test (3, Sys.opaque_identity "c" ^ Sys.opaque_identity "c", function 1 -> "a" | 2 -> "b" | 3 -> "cc" | _ -> ""); - Test (3, List.rev [3;2;1], function 1 -> [] | 2 -> [42] | 3 -> [1;2;3] | _ -> [415]); + Test (3, List.rev [3;2;1], + function 1 -> [] | 2 -> [42] | 3 -> [1;2;3] | _ -> [415]); Test (C, 3, function A -> 1 | B -> 2 | C -> 3); Test (C, -3, function A -> 1 | B -> 2 | C -> -3); @@ -62,4 +63,3 @@ let run_test (Test (a, b, f)) = let () = List.iter run_test testcases; Printf.printf "%d tests passed\n" !passes - diff --git a/testsuite/tests/basic/unit_naming.compilers.reference b/testsuite/tests/basic/unit_naming.compilers.reference new file mode 100644 index 00000000..7a7a0898 --- /dev/null +++ b/testsuite/tests/basic/unit_naming.compilers.reference @@ -0,0 +1,4 @@ +File "unit_naming.ml", line 9, characters 10-25: +9 | print_int Camlcase.answer + ^^^^^^^^^^^^^^^ +Error: Unbound module Camlcase diff --git a/testsuite/tests/basic/unit_naming.ml b/testsuite/tests/basic/unit_naming.ml new file mode 100644 index 00000000..6b7a65c2 --- /dev/null +++ b/testsuite/tests/basic/unit_naming.ml @@ -0,0 +1,9 @@ +(* TEST + modules = "camlCase.ml" + * setup-ocamlc.byte-build-env + ** ocamlc.byte + ocamlc_byte_exit_status = "2" + *** check-ocamlc.byte-output +*) + +print_int Camlcase.answer diff --git a/testsuite/tests/compiler-libs/ocamltests b/testsuite/tests/compiler-libs/ocamltests new file mode 100644 index 00000000..c2778632 --- /dev/null +++ b/testsuite/tests/compiler-libs/ocamltests @@ -0,0 +1 @@ +test_longident.ml diff --git a/testsuite/tests/compiler-libs/test_longident.ml b/testsuite/tests/compiler-libs/test_longident.ml new file mode 100644 index 00000000..917a4805 --- /dev/null +++ b/testsuite/tests/compiler-libs/test_longident.ml @@ -0,0 +1,112 @@ +(* TEST + flags = "-I ${ocamlsrcdir}/parsing" + include ocamlcommon + * expect +*) + +module L = Longident +[%%expect {| +module L = Longident +|}] + +let flatten_ident = L.flatten (L.Lident "foo") +[%%expect {| +val flatten_ident : string list = ["foo"] +|}] +let flatten_dot = L.flatten (L.Ldot (L.Lident "M", "foo")) +[%%expect {| +val flatten_dot : string list = ["M"; "foo"] +|}] +let flatten_apply = L.flatten (L.Lapply (L.Lident "F", L.Lident "X")) +[%%expect {| +>> Fatal error: Longident.flat +Exception: Misc.Fatal_error. +|}] + +let unflatten_empty = L.unflatten [] +[%%expect {| +val unflatten_empty : L.t option = None +|}] +let unflatten_sing = L.unflatten ["foo"] +[%%expect {| +val unflatten_sing : L.t option = Some (L.Lident "foo") +|}] +let unflatten_dot = L.unflatten ["M"; "N"; "foo"] +[%%expect {| +val unflatten_dot : L.t option = + Some (L.Ldot (L.Ldot (L.Lident "M", "N"), "foo")) +|}] + +let last_ident = L.last (L.Lident "foo") +[%%expect {| +val last_ident : string = "foo" +|}] +let last_dot = L.last (L.Ldot (L.Lident "M", "foo")) +[%%expect {| +val last_dot : string = "foo" +|}] +let last_apply = L.last (L.Lapply (L.Lident "F", L.Lident "X")) +[%%expect {| +>> Fatal error: Longident.last +Exception: Misc.Fatal_error. +|}] +let last_dot_apply = L.last + (L.Ldot (L.Lapply (L.Lident "F", L.Lident "X"), "foo")) +[%%expect {| +val last_dot_apply : string = "foo" +|}];; + +let parse_empty = L.parse "" +[%%expect {| +val parse_empty : L.t = L.Lident "" +|}] +let parse_ident = L.parse "foo" +[%%expect {| +val parse_ident : L.t = L.Lident "foo" +|}] +let parse_dot = L.parse "M.foo" +[%%expect {| +val parse_dot : L.t = L.Ldot (L.Lident "M", "foo") +|}] +let parse_path = L.parse "M.N.foo" +[%%expect {| +val parse_path : L.t = L.Ldot (L.Ldot (L.Lident "M", "N"), "foo") +|}] +let parse_complex = L.parse "M.F(M.N).N.foo" +(* the result below is a known misbehavior of Longident.parse + which does not handle applications properly. Fixing it + would be nice, but we soo no convenient way to do it without + introducing unpleasant dependencies. *) +[%%expect {| +val parse_complex : L.t = + L.Ldot (L.Ldot (L.Ldot (L.Ldot (L.Lident "M", "F(M"), "N)"), "N"), "foo") +|}] + +let string_of_longident lid = Format.asprintf "%a" Pprintast.longident lid +[%%expect{| +val string_of_longident : Longident.t -> string = +|}] +let str_empty = string_of_longident parse_empty +[%%expect {| +val str_empty : string = "" +|}] +let str_ident = string_of_longident parse_ident +[%%expect {| +val str_ident : string = "foo" +|}] +let str_dot = string_of_longident parse_dot +[%%expect {| +val str_dot : string = "M.foo" +|}] +let str_path = string_of_longident parse_path +[%%expect {| +val str_path : string = "M.N.foo" +|}] + + +let str_complex = string_of_longident + (let (&.) p word = L.Ldot(p, word) in + L.Lapply(L.Lident "M" &. "F", L.Lident "M" &. "N") &. "N" &. "foo") +[%%expect{| +val str_complex : string = "M.F(M.N).N.foo" +|}] diff --git a/testsuite/tests/embedded/cmcaml.ml b/testsuite/tests/embedded/cmcaml.ml index 37d1794e..005b489c 100644 --- a/testsuite/tests/embedded/cmcaml.ml +++ b/testsuite/tests/embedded/cmcaml.ml @@ -8,7 +8,7 @@ let rec fib n = if n < 2 then 1 else fib(n-1) + fib(n-2) let format_result n = - let r = "Result = " ^ string_of_int n in + let r = "Result = " ^ Int.to_string n in (* Allocate gratuitously to test GC *) for i = 1 to 1500 do ignore (Bytes.create 256) done; r diff --git a/testsuite/tests/ephe-c-api/ocamltests b/testsuite/tests/ephe-c-api/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/ephe-c-api/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/ephe-c-api/stubs.c b/testsuite/tests/ephe-c-api/stubs.c new file mode 100644 index 00000000..2ea819f3 --- /dev/null +++ b/testsuite/tests/ephe-c-api/stubs.c @@ -0,0 +1,325 @@ +#include +#include "caml/alloc.h" +#include "caml/memory.h" +#include "caml/weak.h" + +/* C version of ephetest.ml */ + +void is_true(const char* test, const char* s, int b) { + if(b) printf("%s %s: OK\n", test, s); + else printf("%s %s: FAIL\n", test, s); +} + +void is_false(const char* test, const char* s, int b) { + is_true(test, s, !b); +} + +void is_data_value(const char* test, value eph, intnat v) { + CAMLparam1(eph); + CAMLlocal1(x); + + if(caml_ephemeron_get_data_copy(eph, &x)) + if(Long_val(Field(x, 0)) == v) printf("%s data set: OK\n", test); + else printf("%s data set: FAIL(bad value %li)\n", test, + (long int)Long_val(Field(x, 0))); + else + printf("%s data set: FAIL\n", test); + + CAMLreturn0; +} + +void is_key_value(const char* test, value eph, intnat v) { + CAMLparam1(eph); + CAMLlocal1(x); + + if(caml_ephemeron_get_key_copy(eph, 0, &x)) + if(Long_val(Field(x, 0)) == v) printf("%s key set: OK\n", test); + else printf("%s key set: FAIL(bad value %li)\n", test, + (long int)Long_val(Field(x, 0))); + else + printf("%s key unset: FAIL\n", test); + + CAMLreturn0; +} + +void is_key_unset(const char* test, value eph) { + is_false(test, "key unset", caml_ephemeron_key_is_set(eph, 0)); +} + +void is_data_unset(const char* test, value eph) { + is_false(test, "data unset", caml_ephemeron_data_is_set(eph)); +} + +extern value caml_gc_minor(value); +extern value caml_gc_full_major(value); + +CAMLprim value test1(value ra, value rb) { + CAMLparam2(ra, rb); + CAMLlocal1(eph); + value x; + + const char* test = "test1"; + caml_gc_minor(Val_unit); + caml_gc_full_major(Val_unit); + eph = caml_ephemeron_create(1); + caml_ephemeron_set_key(eph, 0, Field(ra, 0)); + x = caml_alloc_small(1, 0); + Field(x, 0) = Val_long(42); + caml_ephemeron_set_data(eph, x); + is_key_value(test, eph, 1); + is_data_value(test, eph, 42); + caml_gc_minor(Val_unit); + is_key_value(test, eph, 1); + is_data_value(test, eph, 42); + caml_gc_full_major(Val_unit); + is_key_value(test, eph, 1); + is_data_value(test, eph, 42); + x = caml_alloc_small(1, 0); + Field(x, 0) = Val_long(12); + caml_modify(&Field(ra, 0), x); + caml_gc_full_major(Val_unit); + is_key_unset(test, eph); + is_data_unset(test, eph); + + CAMLreturn(Val_unit); +} + +CAMLprim value test2(value ra, value rb) { + CAMLparam2(ra, rb); + CAMLlocal1(eph); + value x; + + const char* test = "test2"; + caml_gc_minor(Val_unit); + caml_gc_full_major(Val_unit); + eph = caml_ephemeron_create(1); + x = caml_alloc_small(1, 0); + Field(x, 0) = Val_long(125); + caml_ephemeron_set_key(eph, 0, x); + x = caml_alloc_small(1, 0); + Field(x, 0) = Val_long(42); + caml_ephemeron_set_data(eph, x); + is_key_value(test, eph, 125); + is_data_value(test, eph, 42); + x = caml_alloc_small(1, 0); + Field(x, 0) = Val_long(13); + caml_modify(&Field(ra, 0), x); + caml_gc_minor(Val_unit); + is_key_unset(test, eph); + is_data_unset(test, eph); + + CAMLreturn(Val_unit); +} + +CAMLprim value test3(value ra, value rb) { + CAMLparam2(ra, rb); + CAMLlocal1(eph); + value x; + + const char* test = "test3"; + caml_gc_minor(Val_unit); + caml_gc_full_major(Val_unit); + eph = caml_ephemeron_create(1); + x = caml_alloc_small(1, 0); + Field(x, 0) = Val_long(125); + caml_ephemeron_set_key(eph, 0, x); + caml_ephemeron_set_data(eph, Field(ra, 0)); + is_key_value(test, eph, 125); + is_data_value(test, eph, 13); + x = caml_alloc_small(1, 0); + Field(x, 0) = Val_long(14); + caml_modify(&Field(ra, 0), x); + caml_gc_minor(Val_unit); + is_key_unset(test, eph); + is_data_unset(test, eph); + + CAMLreturn(Val_unit); +} + +CAMLprim value test4(value ra, value rb) { + CAMLparam2(ra, rb); + CAMLlocal2(eph, y); + value x; + + const char* test = "test4"; + caml_gc_minor(Val_unit); + caml_gc_full_major(Val_unit); + eph = caml_ephemeron_create(1); + y = caml_alloc(1, 0); + x = caml_alloc_small(1, 0); + Field(x, 0) = y; + caml_modify(&Field(y, 0), Val_long(3)); + caml_modify(&Field(rb, 0), x); + y = Val_unit; + caml_ephemeron_set_key(eph, 0, Field(Field(rb, 0), 0)); + x = caml_alloc_small(1, 0); + Field(x, 0) = Val_long(43); + caml_ephemeron_set_data(eph, x); + is_key_value(test, eph, 3); + is_data_value(test, eph, 43); + caml_gc_minor(Val_unit); + caml_gc_minor(Val_unit); + is_key_value(test, eph, 3); + is_data_value(test, eph, 43); + + CAMLreturn(Val_unit); +} + +CAMLprim value test5(value ra, value rb) { + CAMLparam2(ra, rb); + CAMLlocal2(eph, y); + value x; + + const char* test = "test5"; + caml_gc_minor(Val_unit); + caml_gc_full_major(Val_unit); + eph = caml_ephemeron_create(1); + y = caml_alloc(1, 0); + x = caml_alloc_small(1, 0); + Field(x, 0) = y; + caml_modify(&Field(y, 0), Val_long(3)); + caml_modify(&Field(rb, 0), x); + y = Val_unit; + caml_ephemeron_set_key(eph, 0, Field(Field(rb, 0), 0)); + x = caml_alloc_small(1, 0); + Field(x, 0) = Val_long(43); + caml_ephemeron_set_data(eph, x); + is_key_value(test, eph, 3); + is_data_value(test, eph, 43); + x = caml_alloc_small(1, 0); + Field(x, 0) = Val_long(4); + caml_modify(&Field(rb, 0), x); + caml_gc_minor(Val_unit); + caml_gc_minor(Val_unit); + is_key_unset(test, eph); + is_data_unset(test, eph); + + CAMLreturn(Val_unit); +} + +CAMLprim value test6(value ra, value rb) { + CAMLparam2(ra, rb); + CAMLlocal2(eph, y); + value x; + + const char* test = "test6"; + caml_gc_minor(Val_unit); + caml_gc_full_major(Val_unit); + eph = caml_ephemeron_create(1); + y = caml_alloc(1, 0); + x = caml_alloc_small(1, 0); + Field(x, 0) = y; + caml_modify(&Field(y, 0), Val_long(3)); + caml_modify(&Field(rb, 0), x); + y = Val_unit; + caml_ephemeron_set_key(eph, 0, Field(Field(rb, 0), 0)); + x = caml_alloc_small(1, 0); + Field(x, 0) = Field(Field(rb, 0), 0); + caml_ephemeron_set_data(eph, x); + caml_gc_minor(Val_unit); + is_key_value(test, eph, 3); + x = caml_alloc_small(1, 0); + Field(x, 0) = Val_long(4); + caml_modify(&Field(rb, 0), x); + caml_gc_full_major(Val_unit); + is_key_unset(test, eph); + is_data_unset(test, eph); + + CAMLreturn(Val_unit); +} + +CAMLprim value test7(value ra, value rb) { + CAMLparam2(ra, rb); + CAMLlocal4(eph, weak, y, rc); + value x; + + const char* test = "test7"; + caml_gc_minor(Val_unit); + caml_gc_full_major(Val_unit); + x = caml_alloc_small(1, 0); + Field(x, 0) = Val_long(42); + caml_modify(&Field(ra, 0), x); + weak = caml_weak_array_create(1); + y = caml_ephemeron_create(1); + eph = caml_alloc_small(1, 0); + Field(eph, 0) = y; + y = Val_unit; + rc = caml_alloc_small(1, 0); + Field(rc, 0) = Field(eph, 0); + caml_weak_array_set(weak, 0, Field(rc, 0)); + caml_ephemeron_set_key(Field(eph, 0), 0, Field(ra, 0)); + caml_ephemeron_set_data(Field(eph, 0), Field(rc, 0)); + caml_gc_minor(Val_unit); + is_true(test, "before", caml_weak_array_check(weak, 0)); + caml_modify(&Field(eph, 0), caml_ephemeron_create(1)); + caml_modify(&Field(rc, 0), Val_unit); + caml_gc_full_major(Val_unit); + caml_gc_full_major(Val_unit); + caml_gc_full_major(Val_unit); + is_false(test, "after", caml_weak_array_check(weak, 0)); + + CAMLreturn(Val_unit); +} + +CAMLprim value test8(value ra, value rb) { + CAMLparam2(ra, rb); + CAMLlocal3(x, y, z); + + const char* test = "test8"; + + x = caml_ephemeron_create(15); + z = caml_ephemeron_create(3); + is_true(test, "eph length=15", caml_ephemeron_num_keys(x) == 15); + is_true(test, "eph length=3", caml_ephemeron_num_keys(z) == 3); + + is_false(test, "eph get empty nonull", caml_ephemeron_get_key(x, 5, &y)); + is_false(test, "eph get copy empty nonnull", caml_ephemeron_get_key_copy(x, 5, &y)); + caml_ephemeron_set_key(x, 5, ra); + is_true(test, "eph get nonull", caml_ephemeron_get_key(x, 5, &y)); + is_true(test, "eph get eq", y == ra); + is_true(test, "eph get copy nonnull", caml_ephemeron_get_key_copy(x, 5, &y)); + is_true(test, "eph get copy eq", y != ra); + caml_ephemeron_blit_key(x, 4, z, 0, 3); + caml_ephemeron_unset_key(x, 5); + is_false(test, "eph get unset nonull", caml_ephemeron_get_key(x, 5, &y)); + is_false(test, "eph get copy unset nonnull", caml_ephemeron_get_key_copy(x, 5, &y)); + is_true(test, "eph get nonull z", caml_ephemeron_get_key(z, 1, &y)); + is_true(test, "eph get eq z", y == ra); + is_false(test, "eph get empty z", caml_ephemeron_get_key(z, 0, &y)); + + is_false(test, "eph get data empty nonull", caml_ephemeron_get_data(x, &y)); + is_false(test, "eph get data copy empty nonnull", caml_ephemeron_get_data_copy(x, &y)); + caml_ephemeron_set_data(x, ra); + is_true(test, "eph get data nonull", caml_ephemeron_get_data(x, &y)); + is_true(test, "eph get data eq", y == ra); + is_true(test, "eph get data copy nonnull", caml_ephemeron_get_data_copy(x, &y)); + is_true(test, "eph get data copy eq", y != ra); + caml_ephemeron_blit_data(x, z); + caml_ephemeron_unset_data(x); + is_false(test, "eph get data unset nonull", caml_ephemeron_get_data(x, &y)); + is_false(test, "eph get data copy unset nonnull", caml_ephemeron_get_data_copy(x, &y)); + is_true(test, "eph get nonull z", caml_ephemeron_get_data(z, &y)); + is_true(test, "eph get eq z", y == ra); + + x = caml_weak_array_create(15); + z = caml_weak_array_create(3); + is_true(test, "eph length=15", caml_weak_array_length(x) == 15); + is_true(test, "eph length=3", caml_weak_array_length(z) == 3); + + is_false(test, "eph get empty nonull", caml_weak_array_get(x, 5, &y)); + is_false(test, "eph get copy empty nonnull", caml_weak_array_get_copy(x, 5, &y)); + caml_weak_array_set(x, 5, ra); + is_true(test, "eph get nonull", caml_weak_array_get(x, 5, &y)); + is_true(test, "eph get eq", y == ra); + is_true(test, "eph get copy nonnull", caml_weak_array_get_copy(x, 5, &y)); + is_true(test, "eph get copy eq", y != ra); + caml_weak_array_blit(x, 4, z, 0, 3); + caml_weak_array_unset(x, 5); + is_false(test, "eph get unset nonull", caml_weak_array_get(x, 5, &y)); + is_false(test, "eph get copy unset nonnull", caml_weak_array_get_copy(x, 5, &y)); + is_true(test, "eph get nonull z", caml_weak_array_get(z, 1, &y)); + is_true(test, "eph get eq z", y == ra); + is_false(test, "eph get empty z", caml_weak_array_get(z, 0, &y)); + + CAMLreturn(Val_unit); +} diff --git a/testsuite/tests/ephe-c-api/test.ml b/testsuite/tests/ephe-c-api/test.ml new file mode 100644 index 00000000..a29cd851 --- /dev/null +++ b/testsuite/tests/ephe-c-api/test.ml @@ -0,0 +1,24 @@ +(* TEST + modules = "stubs.c" +*) + +(* C version of ephetest.ml *) + +let make_ra () = ref (ref 1) [@@inline never] +let make_rb () = ref (ref (ref 2)) [@@inline never] + +let ra = make_ra () +let rb = make_rb () + +external test1 : int ref ref -> int ref ref ref -> unit = "test1" +external test2 : int ref ref -> int ref ref ref -> unit = "test2" +external test3 : int ref ref -> int ref ref ref -> unit = "test3" +external test4 : int ref ref -> int ref ref ref -> unit = "test4" +external test5 : int ref ref -> int ref ref ref -> unit = "test5" +external test6 : int ref ref -> int ref ref ref -> unit = "test6" +external test7 : int ref ref -> int ref ref ref -> unit = "test7" +external test8 : int ref ref -> int ref ref ref -> unit = "test8" + +let () = + test1 ra rb; test2 ra rb; test3 ra rb; test4 ra rb; test5 ra rb; + test6 ra rb; test7 ra rb; test8 ra rb diff --git a/testsuite/tests/ephe-c-api/test.reference b/testsuite/tests/ephe-c-api/test.reference new file mode 100644 index 00000000..6afb35a6 --- /dev/null +++ b/testsuite/tests/ephe-c-api/test.reference @@ -0,0 +1,65 @@ +test1 key set: OK +test1 data set: OK +test1 key set: OK +test1 data set: OK +test1 key set: OK +test1 data set: OK +test1 key unset: OK +test1 data unset: OK +test2 key set: OK +test2 data set: OK +test2 key unset: OK +test2 data unset: OK +test3 key set: OK +test3 data set: OK +test3 key unset: OK +test3 data unset: OK +test4 key set: OK +test4 data set: OK +test4 key set: OK +test4 data set: OK +test5 key set: OK +test5 data set: OK +test5 key unset: OK +test5 data unset: OK +test6 key set: OK +test6 key unset: OK +test6 data unset: OK +test7 before: OK +test7 after: OK +test8 eph length=15: OK +test8 eph length=3: OK +test8 eph get empty nonull: OK +test8 eph get copy empty nonnull: OK +test8 eph get nonull: OK +test8 eph get eq: OK +test8 eph get copy nonnull: OK +test8 eph get copy eq: OK +test8 eph get unset nonull: OK +test8 eph get copy unset nonnull: OK +test8 eph get nonull z: OK +test8 eph get eq z: OK +test8 eph get empty z: OK +test8 eph get data empty nonull: OK +test8 eph get data copy empty nonnull: OK +test8 eph get data nonull: OK +test8 eph get data eq: OK +test8 eph get data copy nonnull: OK +test8 eph get data copy eq: OK +test8 eph get data unset nonull: OK +test8 eph get data copy unset nonnull: OK +test8 eph get nonull z: OK +test8 eph get eq z: OK +test8 eph length=15: OK +test8 eph length=3: OK +test8 eph get empty nonull: OK +test8 eph get copy empty nonnull: OK +test8 eph get nonull: OK +test8 eph get eq: OK +test8 eph get copy nonnull: OK +test8 eph get copy eq: OK +test8 eph get unset nonull: OK +test8 eph get copy unset nonnull: OK +test8 eph get nonull z: OK +test8 eph get eq z: OK +test8 eph get empty z: OK diff --git a/testsuite/tests/extension-constructor/test.ml b/testsuite/tests/extension-constructor/test.ml index f738642a..227f420a 100644 --- a/testsuite/tests/extension-constructor/test.ml +++ b/testsuite/tests/extension-constructor/test.ml @@ -12,13 +12,13 @@ type t += C type t += D of int * string let () = - assert (Obj.extension_constructor M.A + assert (Obj.Extension_constructor.of_val M.A == [%extension_constructor M.A]); - assert (Obj.extension_constructor (M.B 42) + assert (Obj.Extension_constructor.of_val (M.B 42) == [%extension_constructor M.B]); - assert (Obj.extension_constructor C + assert (Obj.Extension_constructor.of_val C == [%extension_constructor C]); - assert (Obj.extension_constructor (D (42, "")) + assert (Obj.Extension_constructor.of_val (D (42, "")) == [%extension_constructor D]) let () = print_endline "OK" diff --git a/testsuite/tests/flambda/gpr2239.ml b/testsuite/tests/flambda/gpr2239.ml new file mode 100644 index 00000000..22c6555e --- /dev/null +++ b/testsuite/tests/flambda/gpr2239.ml @@ -0,0 +1,16 @@ +(* TEST + * flambda + * native +*) + +let do_something () = + Printf.printf "Hello world\n%!"; Ok () +[@@inline never] + +let f x = + match do_something () with + | Ok () -> x + | Error r -> let _ = !r in x +[@@inline never] + +let () = f () diff --git a/testsuite/tests/flambda/gpr2239.reference b/testsuite/tests/flambda/gpr2239.reference new file mode 100644 index 00000000..802992c4 --- /dev/null +++ b/testsuite/tests/flambda/gpr2239.reference @@ -0,0 +1 @@ +Hello world diff --git a/testsuite/tests/flambda/ocamltests b/testsuite/tests/flambda/ocamltests index 77176ff6..03b4913f 100644 --- a/testsuite/tests/flambda/ocamltests +++ b/testsuite/tests/flambda/ocamltests @@ -1,3 +1,4 @@ approx_meet.ml gpr998.ml specialise.ml +gpr2239.ml diff --git a/testsuite/tests/flambda/specialise.ml b/testsuite/tests/flambda/specialise.ml index a85d0cab..b5e80c7b 100644 --- a/testsuite/tests/flambda/specialise.ml +++ b/testsuite/tests/flambda/specialise.ml @@ -44,11 +44,16 @@ let foo bar init a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 = let a12 = a11 + 1 in let a13 = a12 + 1 in match x_in_g with - | Some _ -> f_inner x_in_g (y_in_g - baz) a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 - | None -> f_inner x_in_g (y_in_g - baz) a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 + | Some _ -> + f_inner x_in_g (y_in_g - baz) + a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 + | None -> + f_inner x_in_g (y_in_g - baz) + a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 in f_inner in let s = Some init in let f_through_hide = hide_until_round_2 init f_outer in - (f_through_hide [@specialised]) s 10 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 + (f_through_hide [@specialised]) + s 10 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 diff --git a/testsuite/tests/float-unboxing/float_subst_boxed_number.ml b/testsuite/tests/float-unboxing/float_subst_boxed_number.ml index 8d3ad834..c8c07273 100644 --- a/testsuite/tests/float-unboxing/float_subst_boxed_number.ml +++ b/testsuite/tests/float-unboxing/float_subst_boxed_number.ml @@ -10,10 +10,10 @@ let eliminate_intermediate_float_record () = for n = 1 to 1000 do let open Complex in let c = { re = float n; im = 0. } in - (* The following line triggers warning 55 twice when compiled without flambda *) - (* It would be better to disable this warning just here but since *) - (* this is a backend-warning, this is not currently possible *) - (* Hence the use of the -w-55 command-line flag for this test *) + (* The following line triggers warning 55 twice when compiled without + flambda. It would be better to disable this warning just here but since + this is a backend-warning, this is not currently possible. Hence the use + of the -w-55 command-line flag for this test *) r := !r +. (norm [@inlined]) ((add [@inlined]) c i); done; ignore (Sys.opaque_identity !r) @@ -122,7 +122,7 @@ let unbox_record_1 record = let block = { record with int32 = record.int32 } in for i = 1 to 1000 do let y_float = - if i mod 2 = 0 then nan else Pervasives.float i + if i mod 2 = 0 then nan else Stdlib.float i in block.float <- block.float +. (y_float *. 2.); let y_int32 = diff --git a/testsuite/tests/float-unboxing/ocamltests b/testsuite/tests/float-unboxing/ocamltests index a430a13e..6ef80d51 100644 --- a/testsuite/tests/float-unboxing/ocamltests +++ b/testsuite/tests/float-unboxing/ocamltests @@ -1 +1,2 @@ float_subst_boxed_number.ml +unbox_under_assign.ml diff --git a/testsuite/tests/float-unboxing/unbox_under_assign.ml b/testsuite/tests/float-unboxing/unbox_under_assign.ml new file mode 100644 index 00000000..46a6a18c --- /dev/null +++ b/testsuite/tests/float-unboxing/unbox_under_assign.ml @@ -0,0 +1,75 @@ +(* TEST +*) + +module Float = struct + type _ t = + | IO : int option t + | F : float t + + let bar : type a. a t -> float -> int -> a = + fun t f i -> + match t with + | IO -> Some i + | F -> f + [@@inline always] + + let foo (t : float t) f i = + let r = ref 0. in + r := bar t f i +end + +(* These boxed integer cases were also fixed by GPR#2083, although + current compiler code would not actually cause a failure even + before that fix. The tests here are given in case register + typing is tightened up in future (e.g. GPR#1192). *) + +module Int32 = struct + type _ t = + | IO : int option t + | F : int32 t + + let bar : type a. a t -> int32 -> int -> a = + fun t f i -> + match t with + | IO -> Some i + | F -> f + [@@inline always] + + let foo (t : int32 t) f i = + let r = ref 0l in + r := bar t f i +end + +module Int64 = struct + type _ t = + | IO : int option t + | F : int64 t + + let bar : type a. a t -> int64 -> int -> a = + fun t f i -> + match t with + | IO -> Some i + | F -> f + [@@inline always] + + let foo (t : int64 t) f i = + let r = ref 0L in + r := bar t f i +end + +module Nativeint = struct + type _ t = + | IO : int option t + | F : nativeint t + + let bar : type a. a t -> nativeint -> int -> a = + fun t f i -> + match t with + | IO -> Some i + | F -> f + [@@inline always] + + let foo (t : nativeint t) f i = + let r = ref 0n in + r := bar t f i +end diff --git a/testsuite/tests/fma/fma.ml b/testsuite/tests/fma/fma.ml new file mode 100644 index 00000000..2a274405 --- /dev/null +++ b/testsuite/tests/fma/fma.ml @@ -0,0 +1,496 @@ +(* TEST *) + +(* modified glibc's fma() tests *) + +let error l x y z r c = + Printf.fprintf stdout + "%s FAIL!\tfma (%h, %h, %h) returned %h instead of %h.\n" + l x y z c (List.hd r) + +let success l = + Printf.fprintf stdout "%s OK!\n" l + +let fma_test l x y z r = + let c = Float.fma x y z in + if List.exists (fun i -> i = c) r + then success l + else error l x y z r c + +(* test case description: + + (string * float * float * float * float list) + | | | | | + id | | | IEEE compliant result in head, + | | | or, accepted fma emulation approximation + | | | results in tail (if any) + | | | + x y z -> operands as in fma x y z + *) +let _ = + let cases = [ + ("001", 0x1p+0, 0x2p+0, 0x3p+0, [0x5p+0]); + ("002", 0x1.4p+0, 0xcp-4, 0x1p-4, [0x1p+0]); + ("003", 0x0p+0, 0x0p+0, 0x0p+0, [0x0p+0]); + ("004", 0x0p+0, 0x0p+0, ~-.0x0p+0, [0x0p+0]); + ("005", 0x0p+0, ~-.0x0p+0, 0x0p+0, [0x0p+0]); + ("006", 0x0p+0, ~-.0x0p+0, ~-.0x0p+0, [~-.0x0p+0]); + ("007", ~-.0x0p+0, 0x0p+0, 0x0p+0, [0x0p+0]); + ("008", ~-.0x0p+0, 0x0p+0, ~-.0x0p+0, [~-.0x0p+0]); + ("009", ~-.0x0p+0, ~-.0x0p+0, 0x0p+0, [0x0p+0]); + ("010", ~-.0x0p+0, ~-.0x0p+0, ~-.0x0p+0, [0x0p+0]); + ("011", 0x1p+0, 0x0p+0, 0x0p+0, [0x0p+0]); + ("012", 0x1p+0, 0x0p+0, ~-.0x0p+0, [0x0p+0]); + ("013", 0x1p+0, ~-.0x0p+0, 0x0p+0, [0x0p+0]); + ("014", 0x1p+0, ~-.0x0p+0, ~-.0x0p+0, [~-.0x0p+0]); + ("015", ~-.0x1p+0, 0x0p+0, 0x0p+0, [0x0p+0]); + ("016", ~-.0x1p+0, 0x0p+0, ~-.0x0p+0, [~-.0x0p+0]); + ("017", ~-.0x1p+0, ~-.0x0p+0, 0x0p+0, [0x0p+0]); + ("018", ~-.0x1p+0, ~-.0x0p+0, ~-.0x0p+0, [0x0p+0]); + ("019", 0x0p+0, 0x1p+0, 0x0p+0, [0x0p+0]); + ("020", 0x0p+0, 0x1p+0, ~-.0x0p+0, [0x0p+0]); + ("021", 0x0p+0, ~-.0x1p+0, 0x0p+0, [0x0p+0]); + ("022", 0x0p+0, ~-.0x1p+0, ~-.0x0p+0, [~-.0x0p+0]); + ("023", ~-.0x0p+0, 0x1p+0, 0x0p+0, [0x0p+0]); + ("024", ~-.0x0p+0, 0x1p+0, ~-.0x0p+0, [~-.0x0p+0]); + ("025", ~-.0x0p+0, ~-.0x1p+0, 0x0p+0, [0x0p+0]); + ("026", ~-.0x0p+0, ~-.0x1p+0, ~-.0x0p+0, [0x0p+0]); + ("027", 0x1p+0, 0x1p+0, ~-.0x1p+0, [0x0p+0]); + ("028", 0x1p+0, ~-.0x1p+0, 0x1p+0, [0x0p+0]); + ("029", ~-.0x1p+0, 0x1p+0, 0x1p+0, [0x0p+0]); + ("030", ~-.0x1p+0, ~-.0x1p+0, ~-.0x1p+0, [0x0p+0]); + ("031", 0x0p+0, 0x0p+0, 0x1p+0, [0x1p+0]); + ("032", 0x0p+0, 0x0p+0, 0x2p+0, [0x2p+0]); + ("033", 0x0p+0, 0x0p+0, 0xf.fffffp+124, [0xf.fffffp+124]); + ("034", 0x0p+0, 0x0p+0, 0xf.ffffffffffff8p+1020, + [0xf.ffffffffffff8p+1020]); + ("035", 0x0p+0, 0x1p+0, 0x1p+0, [0x1p+0]); + ("036", 0x1p+0, 0x0p+0, 0x1p+0, [0x1p+0]); + ("037", 0x0p+0, 0x1p+0, 0x2p+0, [0x2p+0]); + ("038", 0x1p+0, 0x0p+0, 0x2p+0, [0x2p+0]); + ("039", 0x0p+0, 0x1p+0, 0xf.fffffp+124, [0xf.fffffp+124]); + ("040", 0x0p+0, 0x1p+0, 0xf.ffffffffffff8p+1020, + [0xf.ffffffffffff8p+1020]); + ("041", 0x1p+0, 0x0p+0, 0xf.fffffp+124, [0xf.fffffp+124]); + ("042", 0x1p+0, 0x0p+0, 0xf.ffffffffffff8p+1020, + [0xf.ffffffffffff8p+1020]); + ("043", 0x4p-128, 0x4p-128, 0x0p+0, [0x1p-252]); + ("044", 0x4p-128, 0x4p-1024, 0x0p+0, [0x0p+0]); + ("045", 0x4p-128, 0x8p-972, 0x0p+0, [0x0p+0]); + ("046", 0x4p-1024, 0x4p-128, 0x0p+0, [0x0p+0]); + ("047", 0x4p-1024, 0x4p-1024, 0x0p+0, [0x0p+0]); + ("048", 0x4p-1024, 0x8p-972, 0x0p+0, [0x0p+0]); + ("049", 0x8p-972, 0x4p-128, 0x0p+0, [0x0p+0]); + ("050", 0x8p-972, 0x4p-1024, 0x0p+0, [0x0p+0]); + ("051", 0x8p-972, 0x8p-972, 0x0p+0, [0x0p+0]); + ("052", 0x4p-128, 0x4p-128, ~-.0x0p+0, [0x1p-252]); + ("053", 0x4p-128, 0x4p-1024, ~-.0x0p+0, [0x0p+0]); + ("054", 0x4p-128, 0x8p-972, ~-.0x0p+0, [0x0p+0]); + ("055", 0x4p-1024, 0x4p-128, ~-.0x0p+0, [0x0p+0]); + ("056", 0x4p-1024, 0x4p-1024, ~-.0x0p+0, [0x0p+0]); + ("057", 0x4p-1024, 0x8p-972, ~-.0x0p+0, [0x0p+0]); + ("058", 0x8p-972, 0x4p-128, ~-.0x0p+0, [0x0p+0]); + ("059", 0x8p-972, 0x4p-1024, ~-.0x0p+0, [0x0p+0]); + ("060", 0x8p-972, 0x8p-972, ~-.0x0p+0, [0x0p+0]); + ("061", 0x4p-128, ~-.0x4p-128, 0x0p+0, [~-.0x1p-252]); + ("062", 0x4p-128, ~-.0x4p-1024, 0x0p+0, [~-.0x0p+0]); + ("063", 0x4p-128, ~-.0x8p-972, 0x0p+0, [~-.0x0p+0]); + ("064", 0x4p-1024, ~-.0x4p-128, 0x0p+0, [~-.0x0p+0]); + ("065", 0x4p-1024, ~-.0x4p-1024, 0x0p+0, [~-.0x0p+0]); + ("066", 0x4p-1024, ~-.0x8p-972, 0x0p+0, [~-.0x0p+0]); + ("067", 0x8p-972, ~-.0x4p-128, 0x0p+0, [~-.0x0p+0]); + ("068", 0x8p-972, ~-.0x4p-1024, 0x0p+0, [~-.0x0p+0]); + ("069", 0x8p-972, ~-.0x8p-972, 0x0p+0, [~-.0x0p+0]); + ("070", 0x4p-128, ~-.0x4p-128, ~-.0x0p+0, [~-.0x1p-252]); + ("071", 0x4p-128, ~-.0x4p-1024, ~-.0x0p+0, [~-.0x0p+0]); + ("072", 0x4p-128, ~-.0x8p-972, ~-.0x0p+0, [~-.0x0p+0]); + ("073", 0x4p-1024, ~-.0x4p-128, ~-.0x0p+0, [~-.0x0p+0]); + ("074", 0x4p-1024, ~-.0x4p-1024, ~-.0x0p+0, [~-.0x0p+0]); + ("075", 0x4p-1024, ~-.0x8p-972, ~-.0x0p+0, [~-.0x0p+0]); + ("076", 0x8p-972, ~-.0x4p-128, ~-.0x0p+0, [~-.0x0p+0]); + ("077", 0x8p-972, ~-.0x4p-1024, ~-.0x0p+0, [~-.0x0p+0]); + ("078", 0x8p-972, ~-.0x8p-972, ~-.0x0p+0, [~-.0x0p+0]); + ("079", ~-.0x4p-128, 0x4p-128, 0x0p+0, [~-.0x1p-252]); + ("080", ~-.0x4p-128, 0x4p-1024, 0x0p+0, [~-.0x0p+0]); + ("081", ~-.0x4p-128, 0x8p-972, 0x0p+0, [~-.0x0p+0]); + ("082", ~-.0x4p-1024, 0x4p-128, 0x0p+0, [~-.0x0p+0]); + ("083", ~-.0x4p-1024, 0x4p-1024, 0x0p+0, [~-.0x0p+0]); + ("084", ~-.0x4p-1024, 0x8p-972, 0x0p+0, [~-.0x0p+0]); + ("085", ~-.0x8p-972, 0x4p-128, 0x0p+0, [~-.0x0p+0]); + ("086", ~-.0x8p-972, 0x4p-1024, 0x0p+0, [~-.0x0p+0]); + ("087", ~-.0x8p-972, 0x8p-972, 0x0p+0, [~-.0x0p+0]); + ("088", ~-.0x4p-128, 0x4p-128, ~-.0x0p+0, [~-.0x1p-252]); + ("089", ~-.0x4p-128, 0x4p-1024, ~-.0x0p+0, [~-.0x0p+0]); + ("090", ~-.0x4p-128, 0x8p-972, ~-.0x0p+0, [~-.0x0p+0]); + ("091", ~-.0x4p-1024, 0x4p-128, ~-.0x0p+0, [~-.0x0p+0]); + ("092", ~-.0x4p-1024, 0x4p-1024, ~-.0x0p+0, [~-.0x0p+0]); + ("093", ~-.0x4p-1024, 0x8p-972, ~-.0x0p+0, [~-.0x0p+0]); + ("094", ~-.0x8p-972, 0x4p-128, ~-.0x0p+0, [~-.0x0p+0]); + ("095", ~-.0x8p-972, 0x4p-1024, ~-.0x0p+0, [~-.0x0p+0]); + ("096", ~-.0x8p-972, 0x8p-972, ~-.0x0p+0, [~-.0x0p+0]); + ("097", ~-.0x4p-128, ~-.0x4p-128, 0x0p+0, [0x1p-252]); + ("098", ~-.0x4p-128, ~-.0x4p-1024, 0x0p+0, [0x0p+0]); + ("099", ~-.0x4p-128, ~-.0x8p-972, 0x0p+0, [0x0p+0]); + ("100", ~-.0x4p-1024, ~-.0x4p-128, 0x0p+0, [0x0p+0]); + ("101", ~-.0x4p-1024, ~-.0x4p-1024, 0x0p+0, [0x0p+0]); + ("102", ~-.0x4p-1024, ~-.0x8p-972, 0x0p+0, [0x0p+0]); + ("103", ~-.0x8p-972, ~-.0x4p-128, 0x0p+0, [0x0p+0]); + ("104", ~-.0x8p-972, ~-.0x4p-1024, 0x0p+0, [0x0p+0]); + ("105", ~-.0x8p-972, ~-.0x8p-972, 0x0p+0, [0x0p+0]); + ("106", ~-.0x4p-128, ~-.0x4p-128, ~-.0x0p+0, [0x1p-252]); + ("107", ~-.0x4p-128, ~-.0x4p-1024, ~-.0x0p+0, [0x0p+0]); + ("108", ~-.0x4p-128, ~-.0x8p-972, ~-.0x0p+0, [0x0p+0]); + ("109", ~-.0x4p-1024, ~-.0x4p-128, ~-.0x0p+0, [0x0p+0]); + ("110", ~-.0x4p-1024, ~-.0x4p-1024, ~-.0x0p+0, [0x0p+0]); + ("111", ~-.0x4p-1024, ~-.0x8p-972, ~-.0x0p+0, [0x0p+0]); + ("112", ~-.0x8p-972, ~-.0x4p-128, ~-.0x0p+0, [0x0p+0]); + ("113", ~-.0x8p-972, ~-.0x4p-1024, ~-.0x0p+0, [0x0p+0]); + ("114", ~-.0x8p-972, ~-.0x8p-972, ~-.0x0p+0, [0x0p+0]); + ("115", 0xf.fffffp+124, 0xf.fffffp+124, 0x4p-128, [0xf.ffffe000001p+252]); + ("116", 0xf.fffffp+124, 0xf.fffffp+124, 0x4p-1024, + [0xf.ffffe000001p+252]); + ("117", 0xf.fffffp+124, 0xf.fffffp+124, 0x8p-972, [0xf.ffffe000001p+252]); + ("118", 0xf.fffffp+124, 0xf.ffffffffffff8p+1020, 0x4p-128, [infinity]); + ("119", 0xf.fffffp+124, 0xf.ffffffffffff8p+1020, 0x4p-1024, [infinity]); + ("120", 0xf.fffffp+124, 0xf.ffffffffffff8p+1020, 0x8p-972, [infinity]); + ("121", 0xf.ffffffffffff8p+1020, 0xf.fffffp+124, 0x4p-128, [infinity]); + ("122", 0xf.ffffffffffff8p+1020, 0xf.fffffp+124, 0x4p-1024, [infinity]); + ("123", 0xf.ffffffffffff8p+1020, 0xf.fffffp+124, 0x8p-972, [infinity]); + ("124", 0xf.ffffffffffff8p+1020, 0xf.ffffffffffff8p+1020, 0x4p-128, + [infinity]); + ("125", 0xf.ffffffffffff8p+1020, 0xf.ffffffffffff8p+1020, 0x4p-1024, + [infinity]); + ("126", 0xf.ffffffffffff8p+1020, 0xf.ffffffffffff8p+1020, 0x8p-972, + [infinity]); + ("127", 0xf.fffffp+124, 0xf.fffffp+124, ~-.0x4p-128, + [0xf.ffffe000001p+252]); + ("128", 0xf.fffffp+124, 0xf.fffffp+124, ~-.0x4p-1024, + [0xf.ffffe000001p+252]); + ("129", 0xf.fffffp+124, 0xf.fffffp+124, ~-.0x8p-972, + [0xf.ffffe000001p+252]); + ("130", 0xf.fffffp+124, 0xf.ffffffffffff8p+1020, ~-.0x4p-128, [infinity]); + ("131", 0xf.fffffp+124, 0xf.ffffffffffff8p+1020, ~-.0x4p-1024, + [infinity]); + ("132", 0xf.fffffp+124, 0xf.ffffffffffff8p+1020, ~-.0x8p-972, [infinity]); + ("133", 0xf.ffffffffffff8p+1020, 0xf.fffffp+124, ~-.0x4p-128, [infinity]); + ("134", 0xf.ffffffffffff8p+1020, 0xf.fffffp+124, ~-.0x4p-1024, + [infinity]); + ("135", 0xf.ffffffffffff8p+1020, 0xf.fffffp+124, ~-.0x8p-972, [infinity]); + ("136", 0xf.ffffffffffff8p+1020, 0xf.ffffffffffff8p+1020, ~-.0x4p-128, + [infinity]); + ("137", 0xf.ffffffffffff8p+1020, 0xf.ffffffffffff8p+1020, ~-.0x4p-1024, + [infinity]); + ("138", 0xf.ffffffffffff8p+1020, 0xf.ffffffffffff8p+1020, ~-.0x8p-972, + [infinity]); + ("139", 0xf.fffffp+124, ~-.0xf.fffffp+124, 0x4p-128, + [~-.0xf.ffffe000001p+252]); + ("140", 0xf.fffffp+124, ~-.0xf.fffffp+124, 0x4p-1024, + [~-.0xf.ffffe000001p+252]); + ("141", 0xf.fffffp+124, ~-.0xf.fffffp+124, 0x8p-972, + [~-.0xf.ffffe000001p+252]); + ("142", 0xf.fffffp+124, ~-.0xf.ffffffffffff8p+1020, 0x4p-128, + [~-.infinity]); + ("143", 0xf.fffffp+124, ~-.0xf.ffffffffffff8p+1020, 0x4p-1024, + [~-.infinity]); + ("144", 0xf.fffffp+124, ~-.0xf.ffffffffffff8p+1020, 0x8p-972, + [~-.infinity]); + ("145", 0xf.ffffffffffff8p+1020, ~-.0xf.fffffp+124, 0x4p-128, + [~-.infinity]); + ("146", 0xf.ffffffffffff8p+1020, ~-.0xf.fffffp+124, 0x4p-1024, + [~-.infinity]); + ("147", 0xf.ffffffffffff8p+1020, ~-.0xf.fffffp+124, 0x8p-972, + [~-.infinity]); + ("148", 0xf.ffffffffffff8p+1020, ~-.0xf.ffffffffffff8p+1020, 0x4p-128, + [~-.infinity]); + ("149", 0xf.ffffffffffff8p+1020, ~-.0xf.ffffffffffff8p+1020, 0x4p-1024, + [~-.infinity]); + ("150", 0xf.ffffffffffff8p+1020, ~-.0xf.ffffffffffff8p+1020, 0x8p-972, + [~-.infinity]); + ("151", 0xf.fffffp+124, ~-.0xf.fffffp+124, ~-.0x4p-128, + [~-.0xf.ffffe000001p+252]); + ("152", 0xf.fffffp+124, ~-.0xf.fffffp+124, ~-.0x4p-1024, + [~-.0xf.ffffe000001p+252]); + ("153", 0xf.fffffp+124, ~-.0xf.fffffp+124, ~-.0x8p-972, + [~-.0xf.ffffe000001p+252]); + ("154", 0xf.fffffp+124, ~-.0xf.ffffffffffff8p+1020, ~-.0x4p-128, + [~-.infinity]); + ("155", 0xf.fffffp+124, ~-.0xf.ffffffffffff8p+1020, ~-.0x4p-1024, + [~-.infinity]); + ("156", 0xf.fffffp+124, ~-.0xf.ffffffffffff8p+1020, ~-.0x8p-972, + [~-.infinity]); + ("157", 0xf.ffffffffffff8p+1020, ~-.0xf.fffffp+124, ~-.0x4p-128, + [~-.infinity]); + ("158", 0xf.ffffffffffff8p+1020, ~-.0xf.fffffp+124, ~-.0x4p-1024, + [~-.infinity]); + ("159", 0xf.ffffffffffff8p+1020, ~-.0xf.fffffp+124, ~-.0x8p-972, + [~-.infinity]); + ("160", 0xf.ffffffffffff8p+1020, ~-.0xf.ffffffffffff8p+1020, ~-.0x4p-128, + [~-.infinity]); + ("161", 0xf.ffffffffffff8p+1020, ~-.0xf.ffffffffffff8p+1020, ~-.0x4p-1024, + [~-.infinity]); + ("162", 0xf.ffffffffffff8p+1020, ~-.0xf.ffffffffffff8p+1020, ~-.0x8p-972, + [~-.infinity]); + ("163", ~-.0xf.fffffp+124, 0xf.fffffp+124, 0x4p-128, + [~-.0xf.ffffe000001p+252]); + ("164", ~-.0xf.fffffp+124, 0xf.fffffp+124, 0x4p-1024, + [~-.0xf.ffffe000001p+252]); + ("165", ~-.0xf.fffffp+124, 0xf.fffffp+124, 0x8p-972, + [~-.0xf.ffffe000001p+252]); + ("166", ~-.0xf.fffffp+124, 0xf.ffffffffffff8p+1020, 0x4p-128, + [~-.infinity]); + ("167", ~-.0xf.fffffp+124, 0xf.ffffffffffff8p+1020, 0x4p-1024, + [~-.infinity]); + ("168", ~-.0xf.fffffp+124, 0xf.ffffffffffff8p+1020, 0x8p-972, + [~-.infinity]); + ("169", ~-.0xf.ffffffffffff8p+1020, 0xf.fffffp+124, 0x4p-128, + [~-.infinity]); + ("170", ~-.0xf.ffffffffffff8p+1020, 0xf.fffffp+124, 0x4p-1024, + [~-.infinity]); + ("171", ~-.0xf.ffffffffffff8p+1020, 0xf.fffffp+124, 0x8p-972, + [~-.infinity]); + ("172", ~-.0xf.ffffffffffff8p+1020, 0xf.ffffffffffff8p+1020, 0x4p-128, + [~-.infinity]); + ("173", ~-.0xf.ffffffffffff8p+1020, 0xf.ffffffffffff8p+1020, 0x4p-1024, + [~-.infinity]); + ("174", ~-.0xf.ffffffffffff8p+1020, 0xf.ffffffffffff8p+1020, 0x8p-972, + [~-.infinity]); + ("175", ~-.0xf.fffffp+124, 0xf.fffffp+124, ~-.0x4p-128, + [~-.0xf.ffffe000001p+252]); + ("176", ~-.0xf.fffffp+124, 0xf.fffffp+124, ~-.0x4p-1024, + [~-.0xf.ffffe000001p+252]); + ("177", ~-.0xf.fffffp+124, 0xf.fffffp+124, ~-.0x8p-972, + [~-.0xf.ffffe000001p+252]); + ("178", ~-.0xf.fffffp+124, 0xf.ffffffffffff8p+1020, ~-.0x4p-128, + [~-.infinity]); + ("179", ~-.0xf.fffffp+124, 0xf.ffffffffffff8p+1020, ~-.0x4p-1024, + [~-.infinity]); + ("180", ~-.0xf.fffffp+124, 0xf.ffffffffffff8p+1020, ~-.0x8p-972, + [~-.infinity]); + ("181", ~-.0xf.ffffffffffff8p+1020, 0xf.fffffp+124, ~-.0x4p-128, + [~-.infinity]); + ("182", ~-.0xf.ffffffffffff8p+1020, 0xf.fffffp+124, ~-.0x4p-1024, + [~-.infinity]); + ("183", ~-.0xf.ffffffffffff8p+1020, 0xf.fffffp+124, ~-.0x8p-972, + [~-.infinity]); + ("184", ~-.0xf.ffffffffffff8p+1020, 0xf.ffffffffffff8p+1020, ~-.0x4p-128, + [~-.infinity]); + ("185", ~-.0xf.ffffffffffff8p+1020, 0xf.ffffffffffff8p+1020, ~-.0x4p-1024, + [~-.infinity]); + ("186", ~-.0xf.ffffffffffff8p+1020, 0xf.ffffffffffff8p+1020, ~-.0x8p-972, + [~-.infinity]); + ("187", ~-.0xf.fffffp+124, ~-.0xf.fffffp+124, 0x4p-128, + [0xf.ffffe000001p+252]); + ("188", ~-.0xf.fffffp+124, ~-.0xf.fffffp+124, 0x4p-1024, + [0xf.ffffe000001p+252]); + ("189", ~-.0xf.fffffp+124, ~-.0xf.fffffp+124, 0x8p-972, + [0xf.ffffe000001p+252]); + ("190", ~-.0xf.fffffp+124, ~-.0xf.ffffffffffff8p+1020, 0x4p-128, + [infinity]); + ("191", ~-.0xf.fffffp+124, ~-.0xf.ffffffffffff8p+1020, 0x4p-1024, + [infinity]); + ("192", ~-.0xf.fffffp+124, ~-.0xf.ffffffffffff8p+1020, 0x8p-972, + [infinity]); + ("193", ~-.0xf.ffffffffffff8p+1020, ~-.0xf.fffffp+124, 0x4p-128, + [infinity]); + ("194", ~-.0xf.ffffffffffff8p+1020, ~-.0xf.fffffp+124, 0x4p-1024, + [infinity]); + ("195", ~-.0xf.ffffffffffff8p+1020, ~-.0xf.fffffp+124, 0x8p-972, + [infinity]); + ("196", ~-.0xf.ffffffffffff8p+1020, ~-.0xf.ffffffffffff8p+1020, 0x4p-128, + [infinity]); + ("197", ~-.0xf.ffffffffffff8p+1020, ~-.0xf.ffffffffffff8p+1020, 0x4p-1024, + [infinity]); + ("198", ~-.0xf.ffffffffffff8p+1020, ~-.0xf.ffffffffffff8p+1020, 0x8p-972, + [infinity]); + ("199", ~-.0xf.fffffp+124, ~-.0xf.fffffp+124, ~-.0x4p-128, + [0xf.ffffe000001p+252]); + ("200", ~-.0xf.fffffp+124, ~-.0xf.fffffp+124, ~-.0x4p-1024, + [0xf.ffffe000001p+252]); + ("201", ~-.0xf.fffffp+124, ~-.0xf.fffffp+124, ~-.0x8p-972, + [0xf.ffffe000001p+252]); + ("202", ~-.0xf.fffffp+124, ~-.0xf.ffffffffffff8p+1020, ~-.0x4p-128, + [infinity]); + ("203", ~-.0xf.fffffp+124, ~-.0xf.ffffffffffff8p+1020, ~-.0x4p-1024, + [infinity]); + ("204", ~-.0xf.fffffp+124, ~-.0xf.ffffffffffff8p+1020, ~-.0x8p-972, + [infinity]); + ("205", ~-.0xf.ffffffffffff8p+1020, ~-.0xf.fffffp+124, ~-.0x4p-128, + [infinity]); + ("206", ~-.0xf.ffffffffffff8p+1020, ~-.0xf.fffffp+124, ~-.0x4p-1024, + [infinity]); + ("207", ~-.0xf.ffffffffffff8p+1020, ~-.0xf.fffffp+124, ~-.0x8p-972, + [infinity]); + ("208", ~-.0xf.ffffffffffff8p+1020, ~-.0xf.ffffffffffff8p+1020, + ~-.0x4p-128, [infinity]); + ("209", ~-.0xf.ffffffffffff8p+1020, ~-.0xf.ffffffffffff8p+1020, + ~-.0x4p-1024, [infinity]); + ("210", ~-.0xf.ffffffffffff8p+1020, ~-.0xf.ffffffffffff8p+1020, + ~-.0x8p-972, [infinity]); + ("211", 0x2.fffp+12, 0x1.000002p+0, 0x1.ffffp-24, [0x2.fff006p+12]); + ("212", 0x1.fffp+0, 0x1.00001p+0, ~-.0x1.fffp+0, [0x1.fffp-20]); + ("213", 0xc.d5e6fp+124, 0x2.6af378p-128, ~-.0x1.f08948p+0, + [0xd.da108p-28]); + ("214", 0x1.9abcdep+100, 0x2.6af378p-128, ~-.0x3.e1129p-28, + [0x1.bb421p-52]); + ("215", 0xf.fffffp+124, 0x1.001p+0, ~-.0xf.fffffp+124, [0xf.fffffp+112]); + ("216", ~-.0xf.fffffp+124, 0x1.fffffep+0, 0xf.fffffp+124, + [~-.0xf.ffffd000002p+124]); + ("217", 0xf.fffffp+124, 0x2p+0, ~-.0xf.fffffp+124, [0xf.fffffp+124]); + ("218", 0x5p-128, 0x8.00002p-4, 0x1p-128, [0x3.80000ap-128]); + ("219", ~-.0x5p-128, 0x8.00002p-4, ~-.0x1p-128, [~-.0x3.80000ap-128]); + ("220", 0x7.ffffep-128, 0x8.00001p-4, 0x8p-152, [0x3.ffffffffffep-128]); + ("221", ~-.0x7.ffffep-128, 0x8.00001p-4, ~-.0x8p-152, + [~-.0x3.ffffffffffep-128]); + ("222", 0x8p-152, 0x8p-4, 0x3.fffff8p-128, [0x3.fffffcp-128]); + ("223", ~-.0x8p-152, 0x8p-4, ~-.0x3.fffff8p-128, [~-.0x3.fffffcp-128]); + ("224", 0x8p-152, 0x8.8p-4, 0x3.fffff8p-128, [0x3.fffffc4p-128]); + ("225", ~-.0x8p-152, 0x8.8p-4, ~-.0x3.fffff8p-128, [~-.0x3.fffffc4p-128]); + ("226", 0x8p-152, 0x8p-152, 0x8p+124, [0x8p+124]); + ("227", 0x8p-152, ~-.0x8p-152, 0x8p+124, [0x8p+124]); + ("228", 0x8p-152, 0x8p-152, ~-.0x8p+124, [~-.0x8p+124]); + ("229", 0x8p-152, ~-.0x8p-152, ~-.0x8p+124, [~-.0x8p+124]); + ("230", 0x8p-152, 0x8p-152, 0x4p-128, [0x4p-128]); + ("231", 0x8p-152, ~-.0x8p-152, 0x4p-128, [0x4p-128]); + ("232", 0x8p-152, 0x8p-152, ~-.0x4p-128, [~-.0x4p-128]); + ("233", 0x8p-152, ~-.0x8p-152, ~-.0x4p-128, [~-.0x4p-128]); + ("234", 0x8p-152, 0x8p-152, 0x3.fffff8p-128, [0x3.fffff8p-128]); + ("235", 0x8p-152, ~-.0x8p-152, 0x3.fffff8p-128, [0x3.fffff8p-128]); + ("236", 0x8p-152, 0x8p-152, ~-.0x3.fffff8p-128, [~-.0x3.fffff8p-128]); + ("237", 0x8p-152, ~-.0x8p-152, ~-.0x3.fffff8p-128, [~-.0x3.fffff8p-128]); + ("238", 0x8p-152, 0x8p-152, 0x8p-152, [0x8p-152]); + ("239", 0x8p-152, ~-.0x8p-152, 0x8p-152, [0x8p-152]); + ("240", 0x8p-152, 0x8p-152, ~-.0x8p-152, [~-.0x8p-152]); + ("241", 0x8p-152, ~-.0x8p-152, ~-.0x8p-152, [~-.0x8p-152]); + ("242", 0xf.ffp-4, 0xf.ffp-4, ~-.0xf.fep-4, [0x1p-24]); + ("243", 0xf.ffp-4, ~-.0xf.ffp-4, 0xf.fep-4, [~-.0x1p-24]); + ("244", ~-.0xf.ffp-4, 0xf.ffp-4, 0xf.fep-4, [~-.0x1p-24]); + ("245", ~-.0xf.ffp-4, ~-.0xf.ffp-4, ~-.0xf.fep-4, [0x1p-24]); + ("246", 0x4.000008p-128, 0x4.000008p-28, 0x8p+124, [0x8p+124]); + ("247", 0x4.000008p-128, ~-.0x4.000008p-28, 0x8p+124, [0x8p+124]); + ("248", 0x4.000008p-128, 0x4.000008p-28, ~-.0x8p+124, [~-.0x8p+124]); + ("249", 0x4.000008p-128, ~-.0x4.000008p-28, ~-.0x8p+124, [~-.0x8p+124]); + ("250", 0x4.000008p-128, 0x4.000008p-28, 0x8p+100, [0x8p+100]); + ("251", 0x4.000008p-128, ~-.0x4.000008p-28, 0x8p+100, [0x8p+100]); + ("252", 0x4.000008p-128, 0x4.000008p-28, ~-.0x8p+100, [~-.0x8p+100]); + ("253", 0x4.000008p-128, ~-.0x4.000008p-28, ~-.0x8p+100, [~-.0x8p+100]); + ("254", 0x2.fep+12, 0x1.0000000000001p+0, 0x1.ffep-48, + [0x2.fe00000000002p+12; 0x1.7f00000000002p+13]); + ("255", 0x1.fffp+0, 0x1.0000000000001p+0, ~-.0x1.fffp+0, + [0x1.fffp-52; 0x1p-51]); + ("256", 0x1.0000002p+0, 0xf.fffffep-4, 0x1p-300, [0x1p+0]); + ("257", 0x1.0000002p+0, 0xf.fffffep-4, ~-.0x1p-300, + [0xf.ffffffffffff8p-4; 0x1p+0]); + ("258", 0xe.f56df7797f768p+1020, 0x3.7ab6fbbcbfbb4p-1024, + ~-.0x3.40bf1803497f6p+0, + [0x8.4c4b43de4ed2p-56; 0x1.095f287bc9da4p-53; 0x1.098p-53]); + ("259", 0x1.deadbeef2feedp+900, 0x3.7ab6fbbcbfbb4p-1024, + ~-.0x6.817e300692fecp-124, + [0x1.0989687bc9da4p-176; 0x1.095f287bc9da4p-176; 0x1.098p-176]); + ("260", 0xf.ffffffffffff8p+1020, 0x1.001p+0, + ~-.0xf.ffffffffffff8p+1020, [0xf.ffffffffffff8p+1008; 0x1p+1012]); + ("261", ~-.0xf.ffffffffffff8p+1020, 0x1.fffffffffffffp+0, + 0xf.ffffffffffff8p+1020, [~-.0xf.fffffffffffe8p+1020]); + ("262", 0xf.ffffffffffff8p+1020, 0x2p+0, ~-.0xf.ffffffffffff8p+1020, + [0xf.ffffffffffff8p+1020]); + ("263", 0x5.a827999fcef3p-540, 0x5.a827999fcef3p-540, 0x0p+0, [0x0p+0]); + ("264", 0x3.bd5b7dde5fddap-496, 0x3.bd5b7dde5fddap-496, + ~-.0xd.fc352bc352bap-992, + [0x1.0989687cp-1044; 0x0.000004277ca1fp-1022; 0x0.00000428p-1022]); + ("265", 0x3.bd5b7dde5fddap-504, 0x3.bd5b7dde5fddap-504, + ~-.0xd.fc352bc352bap-1008, + [0x1.0988p-1060; 0x0.0000000004278p-1022; 0x0.000000000428p-1022]); + ("266", 0x8p-540, 0x4p-540, 0x4p-1076, [0x8p-1076]); + ("267", 0x1.7fffff8p-968, 0x4p-108, 0x4p-1048, + [0x4.0000004p-1048; 0x0.0000010000002p-1022]); + ("268", 0x2.8000008p-968, 0x4p-108, 0x4p-1048, + [0x4.000000cp-1048; 0x0.0000010000002p-1022]); + ("269", 0x2.8p-968, ~-.0x4p-108, ~-.0x4p-1048, [~-.0x4.0000008p-1048]); + ("270", ~-.0x2.33956cdae7c2ep-960, 0x3.8e211518bfea2p-108, + ~-.0x2.02c2b59766d9p-1024, [~-.0x2.02c2b59767564p-1024]); + ("271", ~-.0x3.a5d5dadd1d3a6p-980, ~-.0x2.9c0cd8c5593bap-64, + ~-.0x2.49179ac00d15p-1024, [~-.0x2.491702717ed74p-1024]); + ("272", 0x2.2a7aca1773e0cp-908, 0x9.6809186a42038p-128, + ~-.0x2.c9e356b3f0fp-1024, + [~-.0x2.c89d5c48eefa4p-1024; ~-.0x0.b22757123bbe8p-1022]); + ("273", ~-.0x3.ffffffffffffep-712, 0x3.ffffffffffffep-276, + 0x3.fffffc0000ffep-984, [0x2.fffffc0000ffep-984; 0x1.7ffffe00008p-983]); + ("274", 0x5p-1024, 0x8.000000000001p-4, 0x1p-1024, + [0x3.8000000000004p-1024]); + ("275", ~-.0x5p-1024, 0x8.000000000001p-4, ~-.0x1p-1024, + [~-.0x3.8000000000004p-1024]); + ("276", 0x7.ffffffffffffp-1024, 0x8.0000000000008p-4, 0x4p-1076, + [0x4p-1024]); + ("277", ~-.0x7.ffffffffffffp-1024, 0x8.0000000000008p-4, ~-.0x4p-1076, + [~-.0x4p-1024]); + ("278", 0x4p-1076, 0x8p-4, 0x3.ffffffffffffcp-1024, [0x4p-1024]); + ("279", ~-.0x4p-1076, 0x8p-4, ~-.0x3.ffffffffffffcp-1024, [~-.0x4p-1024]); + ("280", 0x4p-1076, 0x8.8p-4, 0x3.ffffffffffffcp-1024, [0x4p-1024]); + ("281", ~-.0x4p-1076, 0x8.8p-4, ~-.0x3.ffffffffffffcp-1024, + [~-.0x4p-1024]); + ("282", 0x4p-1076, 0x4p-1076, 0x8p+1020, [0x8p+1020]); + ("283", 0x4p-1076, ~-.0x4p-1076, 0x8p+1020, [0x8p+1020]); + ("284", 0x4p-1076, 0x4p-1076, ~-.0x8p+1020, [~-.0x8p+1020]); + ("285", 0x4p-1076, ~-.0x4p-1076, ~-.0x8p+1020, [~-.0x8p+1020]); + ("286", 0x4p-1076, 0x4p-1076, 0x4p-1024, [0x4p-1024]); + ("287", 0x4p-1076, ~-.0x4p-1076, 0x4p-1024, [0x4p-1024]); + ("288", 0x4p-1076, 0x4p-1076, ~-.0x4p-1024, [~-.0x4p-1024]); + ("289", 0x4p-1076, ~-.0x4p-1076, ~-.0x4p-1024, [~-.0x4p-1024]); + ("290", 0x4p-1076, 0x4p-1076, 0x3.ffffffffffffcp-1024, + [0x3.ffffffffffffcp-1024]); + ("291", 0x4p-1076, ~-.0x4p-1076, 0x3.ffffffffffffcp-1024, + [0x3.ffffffffffffcp-1024]); + ("292", 0x4p-1076, 0x4p-1076, ~-.0x3.ffffffffffffcp-1024, + [~-.0x3.ffffffffffffcp-1024]); + ("293", 0x4p-1076, ~-.0x4p-1076, ~-.0x3.ffffffffffffcp-1024, + [~-.0x3.ffffffffffffcp-1024]); + ("294", 0x4p-1076, 0x4p-1076, 0x4p-1076, [0x4p-1076]); + ("295", 0x4p-1076, ~-.0x4p-1076, 0x4p-1076, [0x4p-1076]); + ("296", 0x4p-1076, 0x4p-1076, ~-.0x4p-1076, [~-.0x4p-1076]); + ("297", 0x4p-1076, ~-.0x4p-1076, ~-.0x4p-1076, [~-.0x4p-1076]); + ("298", 0xf.ffffffffffff8p-4, 0xf.ffffffffffff8p-4, + ~-.0xf.ffffffffffffp-4, [0x4p-108; 0x0p+0]); + ("299", 0xf.ffffffffffff8p-4, ~-.0xf.ffffffffffff8p-4, + 0xf.ffffffffffffp-4, [~-.0x4p-108; 0x0p+0]); + ("300", ~-.0xf.ffffffffffff8p-4, 0xf.ffffffffffff8p-4, + 0xf.ffffffffffffp-4, [~-.0x4p-108; 0x0p+0]); + ("301", ~-.0xf.ffffffffffff8p-4, ~-.0xf.ffffffffffff8p-4, + ~-.0xf.ffffffffffffp-4, [0x4p-108; 0x0p+0]); + ("302", 0x4.0000000000004p-1024, 0x2.0000000000002p-56, 0x8p+1020, + [0x8p+1020]); + ("303", 0x4.0000000000004p-1024, ~-.0x2.0000000000002p-56, 0x8p+1020, + [0x8p+1020]); + ("304", 0x4.0000000000004p-1024, 0x2.0000000000002p-56, ~-.0x8p+1020, + [~-.0x8p+1020]); + ("305", 0x4.0000000000004p-1024, ~-.0x2.0000000000002p-56, ~-.0x8p+1020, + [~-.0x8p+1020]); + ("306", 0x4.0000000000004p-1024, 0x2.0000000000002p-56, 0x4p+968, + [0x4p+968]); + ("307", 0x4.0000000000004p-1024, ~-.0x2.0000000000002p-56, 0x4p+968, + [0x4p+968]); + ("308", 0x4.0000000000004p-1024, 0x2.0000000000002p-56, ~-.0x4p+968, + [~-.0x4p+968]); + ("309", 0x4.0000000000004p-1024, ~-.0x2.0000000000002p-56, ~-.0x4p+968, + [~-.0x4p+968]); + ("310", 0x7.fffff8p-128, 0x3.fffffcp+24, 0xf.fffffp+124, + [0xf.fffffp+124]); + ("311", 0x7.fffff8p-128, ~-.0x3.fffffcp+24, 0xf.fffffp+124, + [0xf.fffffp+124]); + ("312", 0x7.fffff8p-128, 0x3.fffffcp+24, ~-.0xf.fffffp+124, + [~-.0xf.fffffp+124]); + ("313", 0x7.fffff8p-128, ~-.0x3.fffffcp+24, ~-.0xf.fffffp+124, + [~-.0xf.fffffp+124]); + ("314", 0x7.ffffffffffffcp-1024, 0x7.ffffffffffffcp+52, + 0xf.ffffffffffff8p+1020, [0xf.ffffffffffff8p+1020]); + ("315", 0x7.ffffffffffffcp-1024, ~-.0x7.ffffffffffffcp+52, + 0xf.ffffffffffff8p+1020, [0xf.ffffffffffff8p+1020]); + ("316", 0x7.ffffffffffffcp-1024, 0x7.ffffffffffffcp+52, + ~-.0xf.ffffffffffff8p+1020, [~-.0xf.ffffffffffff8p+1020]); + ("317", 0x7.ffffffffffffcp-1024, ~-.0x7.ffffffffffffcp+52, + ~-.0xf.ffffffffffff8p+1020, [~-.0xf.ffffffffffff8p+1020]) + ] in + let rec do_cases c = + match c with + (l, x, y, z, r)::t -> fma_test l x y z r; + do_cases t + | [] -> () + in + do_cases cases diff --git a/testsuite/tests/fma/fma.reference b/testsuite/tests/fma/fma.reference new file mode 100644 index 00000000..44d04b38 --- /dev/null +++ b/testsuite/tests/fma/fma.reference @@ -0,0 +1,317 @@ +001 OK! +002 OK! +003 OK! +004 OK! +005 OK! +006 OK! +007 OK! +008 OK! +009 OK! +010 OK! +011 OK! +012 OK! +013 OK! +014 OK! +015 OK! +016 OK! +017 OK! +018 OK! +019 OK! +020 OK! +021 OK! +022 OK! +023 OK! +024 OK! +025 OK! +026 OK! +027 OK! +028 OK! +029 OK! +030 OK! +031 OK! +032 OK! +033 OK! +034 OK! +035 OK! +036 OK! +037 OK! +038 OK! +039 OK! +040 OK! +041 OK! +042 OK! +043 OK! +044 OK! +045 OK! +046 OK! +047 OK! +048 OK! +049 OK! +050 OK! +051 OK! +052 OK! +053 OK! +054 OK! +055 OK! +056 OK! +057 OK! +058 OK! +059 OK! +060 OK! +061 OK! +062 OK! +063 OK! +064 OK! +065 OK! +066 OK! +067 OK! +068 OK! +069 OK! +070 OK! +071 OK! +072 OK! +073 OK! +074 OK! +075 OK! +076 OK! +077 OK! +078 OK! +079 OK! +080 OK! +081 OK! +082 OK! +083 OK! +084 OK! +085 OK! +086 OK! +087 OK! +088 OK! +089 OK! +090 OK! +091 OK! +092 OK! +093 OK! +094 OK! +095 OK! +096 OK! +097 OK! +098 OK! +099 OK! +100 OK! +101 OK! +102 OK! +103 OK! +104 OK! +105 OK! +106 OK! +107 OK! +108 OK! +109 OK! +110 OK! +111 OK! +112 OK! +113 OK! +114 OK! +115 OK! +116 OK! +117 OK! +118 OK! +119 OK! +120 OK! +121 OK! +122 OK! +123 OK! +124 OK! +125 OK! +126 OK! +127 OK! +128 OK! +129 OK! +130 OK! +131 OK! +132 OK! +133 OK! +134 OK! +135 OK! +136 OK! +137 OK! +138 OK! +139 OK! +140 OK! +141 OK! +142 OK! +143 OK! +144 OK! +145 OK! +146 OK! +147 OK! +148 OK! +149 OK! +150 OK! +151 OK! +152 OK! +153 OK! +154 OK! +155 OK! +156 OK! +157 OK! +158 OK! +159 OK! +160 OK! +161 OK! +162 OK! +163 OK! +164 OK! +165 OK! +166 OK! +167 OK! +168 OK! +169 OK! +170 OK! +171 OK! +172 OK! +173 OK! +174 OK! +175 OK! +176 OK! +177 OK! +178 OK! +179 OK! +180 OK! +181 OK! +182 OK! +183 OK! +184 OK! +185 OK! +186 OK! +187 OK! +188 OK! +189 OK! +190 OK! +191 OK! +192 OK! +193 OK! +194 OK! +195 OK! +196 OK! +197 OK! +198 OK! +199 OK! +200 OK! +201 OK! +202 OK! +203 OK! +204 OK! +205 OK! +206 OK! +207 OK! +208 OK! +209 OK! +210 OK! +211 OK! +212 OK! +213 OK! +214 OK! +215 OK! +216 OK! +217 OK! +218 OK! +219 OK! +220 OK! +221 OK! +222 OK! +223 OK! +224 OK! +225 OK! +226 OK! +227 OK! +228 OK! +229 OK! +230 OK! +231 OK! +232 OK! +233 OK! +234 OK! +235 OK! +236 OK! +237 OK! +238 OK! +239 OK! +240 OK! +241 OK! +242 OK! +243 OK! +244 OK! +245 OK! +246 OK! +247 OK! +248 OK! +249 OK! +250 OK! +251 OK! +252 OK! +253 OK! +254 OK! +255 OK! +256 OK! +257 OK! +258 OK! +259 OK! +260 OK! +261 OK! +262 OK! +263 OK! +264 OK! +265 OK! +266 OK! +267 OK! +268 OK! +269 OK! +270 OK! +271 OK! +272 OK! +273 OK! +274 OK! +275 OK! +276 OK! +277 OK! +278 OK! +279 OK! +280 OK! +281 OK! +282 OK! +283 OK! +284 OK! +285 OK! +286 OK! +287 OK! +288 OK! +289 OK! +290 OK! +291 OK! +292 OK! +293 OK! +294 OK! +295 OK! +296 OK! +297 OK! +298 OK! +299 OK! +300 OK! +301 OK! +302 OK! +303 OK! +304 OK! +305 OK! +306 OK! +307 OK! +308 OK! +309 OK! +310 OK! +311 OK! +312 OK! +313 OK! +314 OK! +315 OK! +316 OK! +317 OK! diff --git a/testsuite/tests/fma/ocamltests b/testsuite/tests/fma/ocamltests new file mode 100644 index 00000000..d51821f0 --- /dev/null +++ b/testsuite/tests/fma/ocamltests @@ -0,0 +1 @@ +fma.ml diff --git a/testsuite/tests/formatting/errors_batch.ml b/testsuite/tests/formatting/errors_batch.ml new file mode 100644 index 00000000..abf4513d --- /dev/null +++ b/testsuite/tests/formatting/errors_batch.ml @@ -0,0 +1,43 @@ +(* TEST + include ocamlcommon +*) + +let () = + let open Location in + (* Some dummy locations for demo purposes *) + let pos = Lexing.{ + pos_fname = "hello.ml"; + pos_lnum = 18; + pos_bol = 15; + pos_cnum = 35; + } in + let loc1 = { + loc_start = pos; loc_end = { pos with pos_cnum = 42 }; + loc_ghost = false + } in + let loc2 = { + loc_start = { pos with pos_lnum = 20; pos_bol = 0; pos_cnum = 4 }; + loc_end = { pos with pos_lnum = 20; pos_bol = 0; pos_cnum = 8 }; + loc_ghost = false + } in + let loc3 = { + loc_start = { pos with pos_lnum = 20; pos_bol = 0; pos_cnum = 6 }; + loc_end = { pos with pos_lnum = 20; pos_bol = 0; pos_cnum = 8 }; + loc_ghost = false + } in + let report = { + kind = Report_error; + main = msg ~loc:loc1 "%a" Format.pp_print_text + "These are the contents of the main error message. \ + It is very long and should wrap across several lines."; + sub = [ + msg ~loc:loc2 "A located first sub-message."; + msg ~loc:loc3 "%a" Format.pp_print_text + "Longer sub-messages that do not fit on the \ + same line as the location get indented."; + msg "@[This second sub-message does not have \ + a location;@,ghost locations of submessages are \ + not printed.@]"; + ] + } in + print_report Format.std_formatter report diff --git a/testsuite/tests/formatting/errors_batch.reference b/testsuite/tests/formatting/errors_batch.reference new file mode 100644 index 00000000..450693d8 --- /dev/null +++ b/testsuite/tests/formatting/errors_batch.reference @@ -0,0 +1,10 @@ +File "hello.ml", line 18, characters 20-27: +Error: These are the contents of the main error message. It is very long and + should wrap across several lines. +File "hello.ml", line 20, characters 4-8: + A located first sub-message. +File "hello.ml", line 20, characters 6-8: + Longer sub-messages that do not fit on the same line as the location get + indented. + This second sub-message does not have a location; + ghost locations of submessages are not printed. diff --git a/testsuite/tests/formatting/margins.ml b/testsuite/tests/formatting/margins.ml index 7ae3f7cf..03628889 100644 --- a/testsuite/tests/formatting/margins.ml +++ b/testsuite/tests/formatting/margins.ml @@ -7,5 +7,6 @@ let () = Format.pp_set_margin Format.std_formatter 20;; 1 + "foo";; let () = Format.pp_set_margin Format.std_formatter 80;; +let () = Format.pp_set_max_indent Format.std_formatter 70;; 1 + "foo";; diff --git a/testsuite/tests/formatting/margins.ocaml.reference b/testsuite/tests/formatting/margins.ocaml.reference index 13606fe5..0650bbcb 100644 --- a/testsuite/tests/formatting/margins.ocaml.reference +++ b/testsuite/tests/formatting/margins.ocaml.reference @@ -1,13 +1,13 @@ -Characters 5-10: - 1 + "foo";; - ^^^^^ +Line 2, characters 4-9: +2 | 1 + "foo";; + ^^^^^ Error: This expression has type string but an expression was expected of type int -Characters 5-10: - 1 + "foo";; - ^^^^^ +Line 2, characters 4-9: +2 | 1 + "foo";; + ^^^^^ Error: This expression has type string but an expression was expected of type int diff --git a/testsuite/tests/formatting/ocamltests b/testsuite/tests/formatting/ocamltests index f780baa3..6315a066 100644 --- a/testsuite/tests/formatting/ocamltests +++ b/testsuite/tests/formatting/ocamltests @@ -1 +1,2 @@ margins.ml +errors_batch.ml diff --git a/testsuite/tests/functors/functors.compilers.reference b/testsuite/tests/functors/functors.compilers.reference index 929d8849..ef88efdb 100644 --- a/testsuite/tests/functors/functors.compilers.reference +++ b/testsuite/tests/functors/functors.compilers.reference @@ -4,22 +4,25 @@ (module-defn(O) functors.ml(12):184-279 (function X is_a_functor always_inline (let - (cow = (function x (apply (field 0 X) x)) - sheep = (function x (+ 1 (apply cow x)))) + (cow = (function x[int] : int (apply (field 0 X) x)) + sheep = (function x[int] : int (+ 1 (apply cow x)))) (makeblock 0 cow sheep)))) F = (module-defn(F) functors.ml(17):281-392 (function X Y is_a_functor always_inline (let - (cow = (function x (apply (field 0 Y) (apply (field 0 X) x))) - sheep = (function x (+ 1 (apply cow x)))) + (cow = + (function x[int] : int + (apply (field 0 Y) (apply (field 0 X) x))) + sheep = (function x[int] : int (+ 1 (apply cow x)))) (makeblock 0 cow sheep)))) F1 = (module-defn(F1) functors.ml(31):516-632 (function X Y is_a_functor always_inline (let - (cow = (function x (apply (field 0 Y) (apply (field 0 X) x))) - sheep = (function x (+ 1 (apply cow x)))) + (sheep = + (function x[int] : int + (+ 1 (apply (field 0 Y) (apply (field 0 X) x))))) (makeblock 0 sheep)))) F2 = (module-defn(F2) functors.ml(36):634-784 @@ -27,8 +30,9 @@ (let (X =a (makeblock 0 (field 1 X)) Y =a (makeblock 0 (field 1 Y)) - cow = (function x (apply (field 0 Y) (apply (field 0 X) x))) - sheep = (function x (+ 1 (apply cow x)))) + sheep = + (function x[int] : int + (+ 1 (apply (field 0 Y) (apply (field 0 X) x))))) (makeblock 0 sheep)))) M = (module-defn(M) functors.ml(41):786-970 @@ -38,8 +42,9 @@ (function X Y is_a_functor always_inline (let (cow = - (function x (apply (field 0 Y) (apply (field 0 X) x))) - sheep = (function x (+ 1 (apply cow x)))) + (function x[int] : int + (apply (field 0 Y) (apply (field 0 X) x))) + sheep = (function x[int] : int (+ 1 (apply cow x)))) (makeblock 0 cow sheep))))) (makeblock 0 (function funarg funarg is_a_functor stub diff --git a/testsuite/tests/gc-roots/globroots.ml b/testsuite/tests/gc-roots/globroots.ml index 8245e85f..df438bc4 100644 --- a/testsuite/tests/gc-roots/globroots.ml +++ b/testsuite/tests/gc-roots/globroots.ml @@ -31,9 +31,9 @@ module Test(G: GLOBREF) = struct let size = 1024 - let vals = Array.init size string_of_int + let vals = Array.init size Int.to_string - let a = Array.init size (fun i -> G.register (string_of_int i)) + let a = Array.init size (fun i -> G.register (Int.to_string i)) let check () = for i = 0 to size - 1 do @@ -51,14 +51,14 @@ module Test(G: GLOBREF) = struct Gc.minor() | 5|6|7|8|9|10|11|12 -> (* update with young value *) let i = Random.int size in - G.set a.(i) (string_of_int i) + G.set a.(i) (Int.to_string i) | 13|14|15|16|17|18|19|20 -> (* update with old value *) let i = Random.int size in G.set a.(i) vals.(i) | 21|22|23|24|25|26|27|28 -> (* re-register young value *) let i = Random.int size in G.remove a.(i); - a.(i) <- G.register (string_of_int i) + a.(i) <- G.register (Int.to_string i) | (*29|30|31|32|33|34|35|36*) _ -> (* re-register old value *) let i = Random.int size in G.remove a.(i); diff --git a/testsuite/tests/generalized-open/accepted_batch.ml b/testsuite/tests/generalized-open/accepted_batch.ml new file mode 100644 index 00000000..7c82a76c --- /dev/null +++ b/testsuite/tests/generalized-open/accepted_batch.ml @@ -0,0 +1,34 @@ +(* TEST *) + +open Set.Make(String) + +let e = empty + +open struct + let x = singleton "hidden" +end + +let () = iter print_endline (union x (of_list ["a"; "b"])) + +let f = + let open Set.Make(Int32) in + let e2 = empty in + let open struct + let y = 3 + end in + (e, e2, y) + +module type S = sig + open Set.Make(Bool) + + type nonrec t = t +end + +let hd _ = () + +open (List : sig val map : ('a -> 'b) -> 'a list -> 'b list end) + +let l = + hd (map succ [0; 1; 2; 3]) + +let y = map succ [] diff --git a/testsuite/tests/generalized-open/accepted_batch.reference b/testsuite/tests/generalized-open/accepted_batch.reference new file mode 100644 index 00000000..9c224025 --- /dev/null +++ b/testsuite/tests/generalized-open/accepted_batch.reference @@ -0,0 +1,3 @@ +a +b +hidden diff --git a/testsuite/tests/generalized-open/accepted_expect.ml b/testsuite/tests/generalized-open/accepted_expect.ml new file mode 100644 index 00000000..ba526cb8 --- /dev/null +++ b/testsuite/tests/generalized-open/accepted_expect.ml @@ -0,0 +1,63 @@ +(* TEST + * expect +*) + +open Set.Make(String);; +[%%expect{| +|}] + +let e = empty;; +[%%expect{| +val e : t = +|}] + +open struct + let x = singleton "hidden" +end;; +[%%expect{| +|}];; + +elements (union x (of_list ["a"; "b"]));; +[%%expect{| +- : elt list = ["a"; "b"; "hidden"] +|}] + +let f = + let open Set.Make(Int32) in + let e2 = empty in + let open struct + let y = 3 + end in + (e, e2, y);; +[%%expect{| +val f : t * Set.Make(Int32).t * int = (, , 3) +|}] + +module type S = sig + open Set.Make(Bool) + + type nonrec t = t +end;; +[%%expect{| +module type S = sig type nonrec t = Set.Make(Bool).t end +|}] + +let hd _ = ();; +[%%expect{| +val hd : 'a -> unit = +|}] + +open (List : sig val map : ('a -> 'b) -> 'a list -> 'b list end);; +[%%expect{| +|}] + +let l = map succ [0;1;2;3] +let () = hd l;; +[%%expect{| +val l : int list = [1; 2; 3; 4] +|}] + +let y = map succ [];; +[%%expect{| +val y : int list = [] +|}] diff --git a/testsuite/tests/generalized-open/expansiveness.ml b/testsuite/tests/generalized-open/expansiveness.ml new file mode 100644 index 00000000..b2a55012 --- /dev/null +++ b/testsuite/tests/generalized-open/expansiveness.ml @@ -0,0 +1,93 @@ +(* TEST + * expect +*) + +module Fn = struct + let id x = x +end +;; +[%%expect{| +module Fn : sig val id : 'a -> 'a end +|}] + +let f = fun x -> Fn.id x +;; +[%%expect{| +val f : 'a -> 'a = +|}] + +let g = Fn.(fun x -> id x) +let h = let open Fn in fun x -> id x +;; +[%%expect{| +val g : 'a -> 'a = +val h : 'a -> 'a = +|}] + +let i = + let open struct + let id x = x + end in + fun x -> id x + +let iM = + let module M = struct + let id x = x + end in + fun x -> M.id x +;; +[%%expect{| +val i : 'a -> 'a = +val iM : 'a -> 'a = +|}] + +let j = + let open struct + exception E + let id x = x + end in + fun x -> id x + +let jM = + let module M = struct + exception E + let id x = x + end in + fun x -> M.id x +;; +[%%expect{| +val j : '_weak1 -> '_weak1 = +val jM : '_weak2 -> '_weak2 = +|}] + +module Square(X : sig val x : int end) = struct + let result = X.x * X.x +end +;; +[%%expect{| +module Square : functor (X : sig val x : int end) -> sig val result : int end +|}] + +let k = + let open Square(struct let x = 3 end) in + fun x -> x + +let kM = + let module M = Square(struct let x = 3 end) in + fun x -> x +;; +[%%expect{| +val k : '_weak3 -> '_weak3 = +val kM : '_weak4 -> '_weak4 = +|}] + +let op = + let module M = struct + open struct let r = ref [] end + let s = r + end in + M.s +;; +[%%expect{| +val op : '_weak5 list ref = {contents = []} +|}] diff --git a/testsuite/tests/generalized-open/funct_body.compilers.reference b/testsuite/tests/generalized-open/funct_body.compilers.reference new file mode 100644 index 00000000..316b98a6 --- /dev/null +++ b/testsuite/tests/generalized-open/funct_body.compilers.reference @@ -0,0 +1,5 @@ +File "funct_body.ml", line 30, characters 12-20: +30 | include (val !r) + ^^^^^^^^ +Error: This expression creates fresh types. + It is not allowed inside applicative functors. diff --git a/testsuite/tests/generalized-open/funct_body.ml b/testsuite/tests/generalized-open/funct_body.ml new file mode 100644 index 00000000..4490f773 --- /dev/null +++ b/testsuite/tests/generalized-open/funct_body.ml @@ -0,0 +1,47 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "2" +** check-ocamlc.byte-output +*) + +module type T = sig + type t + val x : t + val f : t -> unit +end + +module Int = struct + type t = int + let x = 42 + let f = print_int +end + +module String = struct + type t = string + let x = "Forty Two" + let f = print_endline +end + +let r = ref (module Int : T) + +module F (X : sig end) = struct + open struct + include (val !r) + end + type s = t + let x : s = x + let f : s -> unit = f +end + +module M = struct end + +module N = F(M) + +let () = + r := (module String : T) + +module O = F(M) + +let () = + O.f N.x diff --git a/testsuite/tests/generalized-open/gpr1506.ml b/testsuite/tests/generalized-open/gpr1506.ml new file mode 100644 index 00000000..f8c8d7e9 --- /dev/null +++ b/testsuite/tests/generalized-open/gpr1506.ml @@ -0,0 +1,389 @@ +(* TEST + * expect +*) + +type t = A +[%%expect{| +type t = A +|}] + +module M = struct + open struct type t' = t end + type t = B of t * t' | C +end +[%%expect{| +module M : sig type t = B of t/1 * t/2 | C end +|}] + +(* test *) +include struct + open M + let test = B (B (C, A), A) +end +[%%expect{| +val test : M.t = M.B (M.B (M.C, A), A) +|}] + +include struct + open struct let aux x y = x / y end + let f x = aux x 2 + let g y = aux 3 y +end +[%%expect{| +val f : int -> int = +val g : int -> int = +|}];; + +include struct + open struct exception Interrupt end + let run () = + raise Interrupt + let () = + match run() with exception Interrupt -> () | _ -> assert false +end +[%%expect{| +val run : unit -> 'a = +|}];; + +(* It was decided to not allow this anymore. *) +(* +module type S = sig + open struct + open struct + type t' = char + end + type t = t' -> int + end + val x : t +end +[%%expect{| +module type S = sig val x : char -> int end +|}];; + +module M : S = struct + let x = Char.code +end +[%%expect{| +module M : S +|}];; +*) + +module M = struct + module M (F: sig end) (X: sig end) = struct end + open M(struct end) +end +[%%expect{| +Line 3, characters 7-20: +3 | open M(struct end) + ^^^^^^^^^^^^^ +Error: This module is not a structure; it has type + functor (X : sig end) -> sig end +|}] + +open struct + open struct let counter = ref 0 end + let inc () = incr counter + let dec () = decr counter + let current () = !counter +end +[%%expect{| +|}] + +let () = + inc(); inc(); dec (); + assert (current () = 1) +[%%expect{| +|}];; + +include struct open struct type t = T end let x = T end +[%%expect{| +Line 1, characters 15-41: +1 | include struct open struct type t = T end let x = T end + ^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: The type t/143 introduced by this open appears in the signature + Line 1, characters 46-47: + The value x has no valid type if t/143 is hidden +|}];; + +module A = struct + open struct + open struct + type t = T + let x = T + end + let y = x + end +end +[%%expect{| +Line 3, characters 4-56: +3 | ....open struct +4 | type t = T +5 | let x = T +6 | end +Error: The type t/149 introduced by this open appears in the signature + Line 7, characters 8-9: + The value y has no valid type if t/149 is hidden +|}];; + +module A = struct + open struct + open struct + type t = T + end + let y = T + end + let g = y +end +[%%expect{| +Line 3, characters 4-40: +3 | ....open struct +4 | type t = T +5 | end +Error: The type t/155 introduced by this open appears in the signature + Line 6, characters 8-9: + The value y has no valid type if t/155 is hidden +|}] + +(* It was decided to not allow this anymore. *) +(* +module type S = sig open struct type t = T end val x : t end +[%%expect{| +Line _, characters 20-46: + module type S = sig open struct type t = T end val x : t end + ^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: The module identifier M#13 cannot be eliminated from val x : M#13.t +|}];; +*) + + +(* It was decided to not allow this anymore. *) +(* +module type S = sig + open struct + type t = int + open struct + type s = T | A of t + end + val x : char + end + val y : t +end +[%%expect{| +module type S = sig val y : int end +|}] +*) + +(* It was decided to not allow this anymore. *) +(* +module type S = sig open struct assert false end end;; +[%%expect{| +module type S = sig end +|}];; +*) + +(* It was decided to not allow this anymore. *) +(* +module type S = sig open struct type t = int end val x : t end;; +[%%expect{| +module type S = sig val x : int end +|}];; +*) + +module type S = sig + (* It was decided to not allow this anymore. *) + (* + open struct type t = int end + type s = t + *) + type s = int +end +[%%expect{| +module type S = sig type s = int end +|}] + +module type T = sig type s = int end +module F(X:S) : T = X +module G(X:T) : S = X +[%%expect{| +module type T = sig type s = int end +module F : functor (X : S) -> T +module G : functor (X : T) -> S +|}] + +module Counter : sig val inc : unit -> unit val current : unit -> int val z : int val zz : int end = struct + open struct let counter = ref 0 end + let x = 1 + let y = 2 + let dec () = decr counter + + open struct + module A : sig val z : int end = struct + open struct + let n = 3 + module A = struct + open struct + let x = 1 + end + let y = x + end + let h = A.y + let g = A.y + n + end + let z = h + g + end + + let z = 12 + + module B : sig val z : int end = struct + open struct + module A = struct + open struct let x = 1 end + let y = x + open struct let x = 1 end + let z = y + x + end + let h = A.y + let g = A.z + 1 + end + let z = h + g + end + + let h = A.z + B.z + end + + let z = z + h + let g = 1 + let ggg = 2 + let inc () = incr counter + let zz = 5 + let current () = !counter +end +[%%expect{| +module Counter : + sig + val inc : unit -> unit + val current : unit -> int + val z : int + val zz : int + end +|}] + +let () = begin + assert (Counter.z = 21) +end +[%%expect{| +|}] + +(* It was decided to not allow parts of this example anymore, see below for a + slightly simpler version. *) +(* +module N = struct + open (functor + (N: sig open struct type t = int end val x : t end) -> + (struct let y = N.x end))(struct let x = 1 end) + + let () = + assert(y = 1) +end +[%%expect{| +module N : sig end +|}] +*) +module N = struct + open (functor + (N: sig val x : int end) -> + (struct let y = N.x end))(struct let x = 1 end) + + let () = + assert(y = 1) +end +[%%expect{| +module N : sig end +|}] + +module M = struct + open struct + open struct + module type S = sig + (* It was decided to not allow this anymore *) + (* open struct type t = int end val x : t *) + val x : int + end + module M : S = struct let x = 1 end + end + end +end +[%%expect{| +module M : sig end +|}] + +(* It was decided to not allow this anymore *) +(* +module N = struct + open struct + module type S = sig open struct type t = T end val x : t end + end +end +[%%expect{| +Line _, characters 24-50: + module type S = sig open struct type t = T end val x : t end + ^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: The module identifier M#32 cannot be eliminated from val x : M#32.t +|}] +*) + +let x = let open struct open struct let y = 1 end let x = y + 1 end in x +[%%expect{| +val x : int = 2 +|}] + +let y = + let + open ((functor (X: sig val x : int end) -> struct X.x end)(struct let x = 1 end)) + in x + +[%%expect{| +val y : int = 2 +|}] + +let x = let open struct type t = T end in T + +[%%expect{| +Line 1, characters 42-43: +1 | let x = let open struct type t = T end in T + ^ +Error: This expression has type t but an expression was expected of type 'a + The type constructor t would escape its scope +|}] + +module type Print = sig + type t + val print: t -> unit +end + +module Print_int: Print with type t = int = struct + type t = int let print = print_int +end +module Print_list(P: Print): Print with type t = P.t list = struct + type t = P.t list + let print = List.iter P.print +end +let print_list_of_int = let open Print_list(Print_int) in print + +[%%expect{| +module type Print = sig type t val print : t -> unit end +module Print_int : sig type t = int val print : t -> unit end +module Print_list : + functor (P : Print) -> sig type t = P.t list val print : t -> unit end +val print_list_of_int : Print_int.t list -> unit = +|}] + +let f () = let open functor(X: sig end) -> struct end in ();; + +[%%expect{| +Line 1, characters 20-53: +1 | let f () = let open functor(X: sig end) -> struct end in ();; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This module is not a structure; it has type + functor (X : sig end) -> sig end +|}] diff --git a/testsuite/tests/generalized-open/ocamltests b/testsuite/tests/generalized-open/ocamltests new file mode 100644 index 00000000..897bd052 --- /dev/null +++ b/testsuite/tests/generalized-open/ocamltests @@ -0,0 +1,6 @@ +accepted_batch.ml +accepted_expect.ml +expansiveness.ml +funct_body.ml +gpr1506.ml +shadowing.ml diff --git a/testsuite/tests/generalized-open/shadowing.ml b/testsuite/tests/generalized-open/shadowing.ml new file mode 100644 index 00000000..589807d3 --- /dev/null +++ b/testsuite/tests/generalized-open/shadowing.ml @@ -0,0 +1,59 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "0" +** check-ocamlc.byte-output +*) + +module Make_sure_val : sig + val x : int +end = struct + let x = 3 + + open struct + let x = 'c' + end +end + +type t = A + +open struct + type t = B +end + +type ext = .. + +module Make_sure_ec : sig + type ext += C of int +end = struct + type ext += C of int + + open struct + type ext += D of char + end +end + + +module M = struct type t = int end + +open struct + module M = struct type u = char end +end + +module type S = sig type t = int end + +open struct + module type S = sig type u = char end +end + +class c = object method x = 3 end + +open struct + class c = object method y = 'c' end +end + +class type ct = object method x : int end + +open struct + class type ct = object method y : int end +end diff --git a/testsuite/tests/let-syntax/let_syntax.ml b/testsuite/tests/let-syntax/let_syntax.ml new file mode 100644 index 00000000..3837d57a --- /dev/null +++ b/testsuite/tests/let-syntax/let_syntax.ml @@ -0,0 +1,723 @@ +(* TEST + * expect +*) + +let id x = x + +let apply x f = f x + +let pair x y = x, y + +module Id = struct + + let (let+) = apply + + let (and+) = pair + +end;; +[%%expect{| +val id : 'a -> 'a = +val apply : 'a -> ('a -> 'b) -> 'b = +val pair : 'a -> 'b -> 'a * 'b = +module Id : + sig + val ( let+ ) : 'a -> ('a -> 'b) -> 'b + val ( and+ ) : 'a -> 'b -> 'a * 'b + end +|}];; + +let res = + Id.( + let+ x = 1 + and+ y = 2 + and+ z = 3 in + [x; y; z] + );; +[%%expect{| +val res : int list = [1; 2; 3] +|}];; + +let res2 = + Id.( + let+ x = 1 in + x + 2 + );; +[%%expect{| +val res2 : int = 3 +|}];; + + +module List = struct + + let map l f = List.map f l + + let concat_map l f = + let l = List.map f l in + List.concat l + + let product xs ys = + List.fold_right + (fun x acc -> (List.map (fun y -> (x, y)) ys) @ acc) + xs [] + + let (let+) = map + + let (and+) = product + + let ( let* ) = concat_map + + let ( and* ) = product + +end;; +[%%expect{| +module List : + sig + val map : 'a list -> ('a -> 'b) -> 'b list + val concat_map : 'a list -> ('a -> 'b list) -> 'b list + val product : 'a list -> 'b list -> ('a * 'b) list + val ( let+ ) : 'a list -> ('a -> 'b) -> 'b list + val ( and+ ) : 'a list -> 'b list -> ('a * 'b) list + val ( let* ) : 'a list -> ('a -> 'b list) -> 'b list + val ( and* ) : 'a list -> 'b list -> ('a * 'b) list + end +|}];; + +let map = + List.( + let+ x = [1; 2; 3] in + x + 1 + );; +[%%expect{| +val map : int list = [2; 3; 4] +|}];; + +let map_and = + List.( + let+ x = [1; 2; 3] + and+ y = [7; 8; 9] in + x + y + );; +[%%expect{| +val map_and : int list = [8; 9; 10; 9; 10; 11; 10; 11; 12] +|}];; + +let bind = + List.( + let* x = [1; 2; 3] in + let* y = [7; 8; 9] in + [x + y] + );; +[%%expect{| +val bind : int list = [8; 9; 10; 9; 10; 11; 10; 11; 12] +|}];; + +let bind_and = + List.( + let* x = [1; 2; 3] + and* y = [7; 8; 9] in + [x + y] + );; +[%%expect{| +val bind_and : int list = [8; 9; 10; 9; 10; 11; 10; 11; 12] +|}];; + +let bind_map = + List.( + let* x = [1; 2; 3] in + let+ y = [7; 8; 9] in + x + y + );; +[%%expect{| +val bind_map : int list = [8; 9; 10; 9; 10; 11; 10; 11; 12] +|}];; + +module Let_unbound = struct +end;; +[%%expect{| +module Let_unbound : sig end +|}];; + +let let_unbound = + Let_unbound.( + let+ x = 1 in + x + y + );; +[%%expect{| +Line 3, characters 4-8: +3 | let+ x = 1 in + ^^^^ +Error: Unbound value let+ +|}];; + +module And_unbound = struct + let (let+) = Id.(let+) +end;; +[%%expect{| +module And_unbound : sig val ( let+ ) : 'a -> ('a -> 'b) -> 'b end +|}];; + +let and_unbound = + And_unbound.( + let+ x = 1 + and+ y = 2 in + x + y + );; +[%%expect{| +Line 4, characters 4-8: +4 | and+ y = 2 in + ^^^^ +Error: Unbound value and+ +|}];; + +module Ill_typed_1 = struct + + let (let+) = fun x f -> f (not x) + +end;; +[%%expect{| +module Ill_typed_1 : sig val ( let+ ) : bool -> (bool -> 'a) -> 'a end +|}];; + +let ill_typed_1 = + Ill_typed_1.( + let+ x = 1 in + x + y + );; +[%%expect{| +Line 3, characters 13-14: +3 | let+ x = 1 in + ^ +Error: This expression has type int but an expression was expected of type + bool +|}];; + +module Ill_typed_2 = struct + + let (let+) = apply + let (and+) = fun x y -> x +. y, x -. y + +end;; +[%%expect{| +module Ill_typed_2 : + sig + val ( let+ ) : 'a -> ('a -> 'b) -> 'b + val ( and+ ) : float -> float -> float * float + end +|}];; + +let ill_typed_2 = + Ill_typed_2.( + let+ x = 1 + and+ y = 2 in + x + y + );; +[%%expect{| +Line 3, characters 13-14: +3 | let+ x = 1 + ^ +Error: This expression has type int but an expression was expected of type + float +|}];; + +module Ill_typed_3 = struct + + let (let+) = 7 + +end;; +[%%expect{| +module Ill_typed_3 : sig val ( let+ ) : int end +|}];; + +let ill_typed_3 = + Ill_typed_3.( + let+ x = 1 in + x + y + );; +[%%expect{| +Line 3, characters 4-8: +3 | let+ x = 1 in + ^^^^ +Error: The operator let+ has type int but it was expected to have type + 'a -> ('b -> 'c) -> 'd +|}];; + +module Ill_typed_4 = struct + + let (let+) = apply + let (and+) = not + +end;; +[%%expect{| +module Ill_typed_4 : + sig val ( let+ ) : 'a -> ('a -> 'b) -> 'b val ( and+ ) : bool -> bool end +|}];; + +let ill_typed_4 = + Ill_typed_4.( + let+ x = 1 + and+ y = 2 in + x + y + );; +[%%expect{| +Line 4, characters 4-8: +4 | and+ y = 2 in + ^^^^ +Error: The operator and+ has type bool -> bool + but it was expected to have type bool -> 'a -> 'b + Type bool is not compatible with type 'a -> 'b +|}];; + +module Ill_typed_5 = struct + + let (let+) = (fun x f -> not x) + let (and+) = pair + +end;; +[%%expect{| +module Ill_typed_5 : + sig + val ( let+ ) : bool -> 'a -> bool + val ( and+ ) : 'a -> 'b -> 'a * 'b + end +|}];; + +let ill_typed_5 = + Ill_typed_5.( + let+ x = 1 + and+ y = 2 + and+ z = 3 in + x + y + z + );; +[%%expect{| +Line 3, characters 9-44: +3 | .........x = 1 +4 | and+ y = 2 +5 | and+ z = 3... +Error: These bindings have type (int * int) * int + but bindings were expected of type bool +|}];; + +module Ill_typed_6 = struct + + let (let+) = apply + let (and+) = fun x y -> x + 1, y + +end;; +[%%expect{| +module Ill_typed_6 : + sig + val ( let+ ) : 'a -> ('a -> 'b) -> 'b + val ( and+ ) : int -> 'a -> int * 'a + end +|}];; + +let ill_typed_6 = + Ill_typed_6.( + let+ x = 1 + and+ y = 2 + and+ z = 3 in + x + y + z + );; +[%%expect{| +Line 3, characters 9-29: +3 | .........x = 1 +4 | and+ y = 2 +Error: These bindings have type int * int but bindings were expected of type + int +|}];; + + +module Ill_typed_7 = struct + + let (let+) f x = f (x + 1) + let (and+) = pair + +end;; +[%%expect{| +module Ill_typed_7 : + sig + val ( let+ ) : (int -> 'a) -> int -> 'a + val ( and+ ) : 'a -> 'b -> 'a * 'b + end +|}];; + +let ill_typed_7 = + Ill_typed_7.( + let+ x = 1 + and+ y = 2 in + x + y + );; +[%%expect{| +Line 3, characters 4-8: +3 | let+ x = 1 + ^^^^ +Error: The operator let+ has type (int -> 'a) -> int -> 'a + but it was expected to have type (int -> 'a) -> ('b * 'c -> 'd) -> 'e + Type int is not compatible with type 'b * 'c -> 'd +|}];; + +module Indexed_monad = struct + + type opened = private Opened + type closed = private Closed + + type (_, _, _) t = + | Return : 'a -> ('s, 's, 'a) t + | Map : ('s1, 's2, 'a) t * ('a -> 'b) -> ('s1, 's2, 'b) t + | Both : ('s1, 's2, 'a) t * ('s2, 's3, 'b) t -> ('s1, 's3, 'a * 'b) t + | Bind : ('s1, 's2, 'a) t * ('a -> ('s2, 's3, 'b) t) -> ('s1, 's3, 'b) t + | Open : string -> (closed, opened, unit) t + | Read : (opened, opened, string) t + | Close : (opened, closed, unit) t + + let return x = Return x + let map m f = Map(m, f) + let both m1 m2 = Both(m1, m2) + let bind m f = Bind(m, f) + let open_ s = Open s + let read = Read + let close = Close + + type 'a state = + | Opened : in_channel -> opened state + | Closed : closed state + + let run (type a) (m : (closed, closed, a) t) : a = + let rec loop : type a s1 s2. s1 state -> (s1, s2, a) t -> s2 state * a = + fun state m -> + match m, state with + | Return x, _ -> state, x + | Map(m, f), _ -> + let state2, x = loop state m in + state2, f x + | Both(m1, m2), _ -> + let state2, x = loop state m1 in + let state3, y = loop state2 m2 in + state3, (x, y) + | Bind(m, f), _ -> + let state2, x = loop state m in + loop state2 (f x) + | Open filename, Closed -> + let ic = open_in filename in + Opened ic, () + | Read, Opened ic -> + let c = input_line ic in + state, c + | Close, Opened ic -> + close_in ic; + Closed, () + in + let Closed, result = loop Closed m in + result + + let ( let+ ) = map + let ( and+ ) = both + let ( let* ) = bind + let ( and* ) = both + +end;; +[%%expect {| +module Indexed_monad : + sig + type opened = private Opened + type closed = private Closed + type (_, _, _) t = + Return : 'a -> ('s, 's, 'a) t + | Map : ('s1, 's2, 'a) t * ('a -> 'b) -> ('s1, 's2, 'b) t + | Both : ('s1, 's2, 'a) t * ('s2, 's3, 'b) t -> ('s1, 's3, 'a * 'b) t + | Bind : ('s1, 's2, 'a) t * + ('a -> ('s2, 's3, 'b) t) -> ('s1, 's3, 'b) t + | Open : string -> (closed, opened, unit) t + | Read : (opened, opened, string) t + | Close : (opened, closed, unit) t + val return : 'a -> ('b, 'b, 'a) t + val map : ('a, 'b, 'c) t -> ('c -> 'd) -> ('a, 'b, 'd) t + val both : ('a, 'b, 'c) t -> ('b, 'd, 'e) t -> ('a, 'd, 'c * 'e) t + val bind : ('a, 'b, 'c) t -> ('c -> ('b, 'd, 'e) t) -> ('a, 'd, 'e) t + val open_ : string -> (closed, opened, unit) t + val read : (opened, opened, string) t + val close : (opened, closed, unit) t + type 'a state = + Opened : in_channel -> opened state + | Closed : closed state + val run : (closed, closed, 'a) t -> 'a + val ( let+ ) : ('a, 'b, 'c) t -> ('c -> 'd) -> ('a, 'b, 'd) t + val ( and+ ) : ('a, 'b, 'c) t -> ('b, 'd, 'e) t -> ('a, 'd, 'c * 'e) t + val ( let* ) : ('a, 'b, 'c) t -> ('c -> ('b, 'd, 'e) t) -> ('a, 'd, 'e) t + val ( and* ) : ('a, 'b, 'c) t -> ('b, 'd, 'e) t -> ('a, 'd, 'c * 'e) t + end +|}];; + +let indexed_monad1 = + Indexed_monad.( + let+ () = open_ "foo" + and+ first = read + and+ second = read + and+ () = close in + first ^ second + );; +[%%expect{| +val indexed_monad1 : + (Indexed_monad.closed, Indexed_monad.closed, string) Indexed_monad.t = + Indexed_monad.Map + (Indexed_monad.Both + (Indexed_monad.Both + (Indexed_monad.Both (Indexed_monad.Open "foo", Indexed_monad.Read), + Indexed_monad.Read), + Indexed_monad.Close), + ) +|}];; + +let indexed_monad2 = + Indexed_monad.( + let* () = open_ "foo" in + let* first = read in + let* second = read in + let* () = close in + return (first ^ second) + );; +[%%expect{| +val indexed_monad2 : + (Indexed_monad.closed, Indexed_monad.closed, string) Indexed_monad.t = + Indexed_monad.Bind (Indexed_monad.Open "foo", ) +|}];; + +let indexed_monad3 = + Indexed_monad.( + let+ first = read + and+ () = open_ "foo" + and+ second = read + and+ () = close in + first ^ second + );; +[%%expect{| +Line 4, characters 14-25: +4 | and+ () = open_ "foo" + ^^^^^^^^^^^ +Error: This expression has type + (Indexed_monad.closed, Indexed_monad.opened, unit) Indexed_monad.t + but an expression was expected of type + (Indexed_monad.opened, 'a, 'b) Indexed_monad.t + Type Indexed_monad.closed is not compatible with type + Indexed_monad.opened +|}];; + +let indexed_monad4 = + Indexed_monad.( + let* () = open_ "foo" in + let* first = read in + let* () = close in + let* second = read in + return (first ^ second) + );; +[%%expect{| +Line 6, characters 4-55: +6 | ....let* second = read in +7 | return (first ^ second) +Error: This expression has type + (Indexed_monad.opened, Indexed_monad.opened, string) Indexed_monad.t + but an expression was expected of type + (Indexed_monad.closed, 'a, 'b) Indexed_monad.t + Type Indexed_monad.opened is not compatible with type + Indexed_monad.closed +|}];; + +(* Test principality using constructor disambiguation *) + +module A = struct + type t = A +end + +module Let_principal = struct + let ( let+ ) (x : A.t) f = f x +end;; +[%%expect{| +module A : sig type t = A end +module Let_principal : sig val ( let+ ) : A.t -> (A.t -> 'a) -> 'a end +|}];; + +let let_principal = + Let_principal.( + let+ A = A in + () + );; +[%%expect{| +val let_principal : unit = () +|}];; + + +module And_principal = struct + let ( let+ ) = apply + let ( and+ ) (x : A.t) y = x, y +end;; +[%%expect{| +module And_principal : + sig + val ( let+ ) : 'a -> ('a -> 'b) -> 'b + val ( and+ ) : A.t -> 'a -> A.t * 'a + end +|}];; + +let and_principal = + And_principal.( + let+ _ = A + and+ () = () in + () + );; +[%%expect{| +val and_principal : unit = () +|}];; + +module Let_not_principal = struct + let ( let+ ) = apply +end;; +[%%expect{| +module Let_not_principal : sig val ( let+ ) : 'a -> ('a -> 'b) -> 'b end +|}];; + +let let_not_principal = + Let_not_principal.( + let+ A = A.A in + () + );; +[%%expect{| +val let_not_principal : unit = () +|}, Principal{| +Line 3, characters 9-10: +3 | let+ A = A.A in + ^ +Error: Unbound constructor A +|}];; + +module And_not_principal = struct + let ( let+ ) = apply + let ( and+ ) x y = if true then x,y else y,x +end;; +[%%expect{| +module And_not_principal : + sig + val ( let+ ) : 'a -> ('a -> 'b) -> 'b + val ( and+ ) : 'a -> 'a -> 'a * 'a + end +|}];; + +let and_not_principal = + And_not_principal.( + fun x y -> + let+ A.A = x + and+ A = y in + () + );; +[%%expect{| +val and_not_principal : A.t -> A.t -> unit = +|}, Principal{| +Line 5, characters 11-12: +5 | and+ A = y in + ^ +Error: Unbound constructor A +|}];; + +module Let_not_propagated = struct + let ( let+ ) = apply +end;; +[%%expect{| +module Let_not_propagated : sig val ( let+ ) : 'a -> ('a -> 'b) -> 'b end +|}];; + +let let_not_propagated : A.t = + Let_not_propagated.( + let+ x = 3 in + A + );; +[%%expect{| +Line 4, characters 4-5: +4 | A + ^ +Error: Unbound constructor A +|}];; + +module Side_effects_ordering = struct + let r = ref [] + let msg s = + r := !r @ [s] + let output () = !r + let ( let+ ) x f = msg "Let operator"; f x + let ( and+ ) a b = msg "First and operator"; a, b + let ( and++ ) a b = msg "Second and operator"; a, b +end;; +[%%expect{| +module Side_effects_ordering : + sig + val r : string list ref + val msg : string -> unit + val output : unit -> string list + val ( let+ ) : 'a -> ('a -> 'b) -> 'b + val ( and+ ) : 'a -> 'b -> 'a * 'b + val ( and++ ) : 'a -> 'b -> 'a * 'b + end +|}];; + +let side_effects_ordering = + Side_effects_ordering.( + let+ () = msg "First argument" + and+ () = msg "Second argument" + and++ () = msg "Third argument" in + output () + );; +[%%expect{| +val side_effects_ordering : string list = + ["First argument"; "Second argument"; "First and operator"; + "Third argument"; "Second and operator"; "Let operator"] +|}];; + +module GADT_ordering = struct + type point = { x : int; y : int } + type _ is_point = + | Is_point : point is_point + let (let+) = apply + let (and+) = pair +end;; +[%%expect{| +module GADT_ordering : + sig + type point = { x : int; y : int; } + type _ is_point = Is_point : point is_point + val ( let+ ) : 'a -> ('a -> 'b) -> 'b + val ( and+ ) : 'a -> 'b -> 'a * 'b + end +|}];; + +let gadt_ordering = + GADT_ordering.( + fun (type a) (is_point : a is_point) (a : a) -> + let+ Is_point : a is_point = is_point + and+ { x; y } : a = a in + x + y + );; +[%%expect{| +val gadt_ordering : 'a GADT_ordering.is_point -> 'a -> int = +|}];; + +(* This example doesn't produce a good error location. To fix this we need to handle the + patterns directly rather than elaborating them to tuples. We'd like to do this in + future but it is quite a bit of work, so for now we leave the location as it is. It + should only appear in principal mode when using GADTs anyway. *) +let bad_location = + GADT_ordering.( + fun (type a) (is_point : a is_point) (a : a) -> + let+ Is_point = is_point + and+ { x; y } = a in + x + y + );; +[%%expect{| +val bad_location : 'a GADT_ordering.is_point -> 'a -> int = +|}, Principal{| +Line 4, characters 6-10: +4 | let+ Is_point = is_point + ^^^^ +Error: This pattern matches values of type + GADT_ordering.point GADT_ordering.is_point * GADT_ordering.point + but a pattern was expected which matches values of type + a GADT_ordering.is_point * a + Type GADT_ordering.point is not compatible with type a +|}];; diff --git a/testsuite/tests/let-syntax/ocamltests b/testsuite/tests/let-syntax/ocamltests new file mode 100644 index 00000000..da15f631 --- /dev/null +++ b/testsuite/tests/let-syntax/ocamltests @@ -0,0 +1 @@ +let_syntax.ml diff --git a/testsuite/tests/letrec-check/basic.ml b/testsuite/tests/letrec-check/basic.ml new file mode 100644 index 00000000..fea13c48 --- /dev/null +++ b/testsuite/tests/letrec-check/basic.ml @@ -0,0 +1,363 @@ +(* TEST + * expect +*) + +let rec x = (x; ());; +[%%expect{| +val x : unit = () +|}];; + +let rec x = "x";; +[%%expect{| +val x : string = "x" +|}];; + +let rec x = let x = () in x;; +[%%expect{| +val x : unit = () +|}];; + +let rec x = let y = (x; ()) in y;; +[%%expect{| +val x : unit = () +|}];; + +let rec x = let y = () in x;; +[%%expect{| +Line 1, characters 12-27: +1 | let rec x = let y = () in x;; + ^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = [y] +and y = let x = () in x;; +[%%expect{| +val x : unit list = [()] +val y : unit = () +|}];; + +let rec x = [y] +and y = let rec x = () in x;; +[%%expect{| +val x : unit list = [()] +val y : unit = () +|}];; + +let rec x = + let a = x in + fun () -> a () +and y = + [x];; +[%%expect{| +val x : unit -> 'a = +val y : (unit -> 'a) list = [] +|}];; + +let rec x = [|y|] and y = 0;; +[%%expect{| +val x : int array = [|0|] +val y : int = 0 +|}];; + + +let rec x = (y, y) +and y = fun () -> ignore x;; +[%%expect{| +val x : (unit -> unit) * (unit -> unit) = (, ) +val y : unit -> unit = +|}];; + +let rec x = Some y +and y = fun () -> ignore x +;; +[%%expect{| +val x : (unit -> unit) option = Some +val y : unit -> unit = +|}];; + +let rec x = ignore x;; +[%%expect{| +Line 1, characters 12-20: +1 | let rec x = ignore x;; + ^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = y 0 and y _ = ();; +[%%expect{| +Line 1, characters 12-15: +1 | let rec x = y 0 and y _ = ();; + ^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec b = if b then true else false;; +[%%expect{| +Line 1, characters 12-37: +1 | let rec b = if b then true else false;; + ^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = function + Some _ -> ignore (y []) + | None -> ignore (y []) +and y = function + [] -> ignore (x None) + | _ :: _ -> ignore (x None) + ;; +[%%expect{| +val x : 'a option -> unit = +val y : 'a list -> unit = +|}];; + +(* this is accepted as all fields are overridden *) +let rec x = { x with contents = 3 } [@ocaml.warning "-23"];; +[%%expect{| +val x : int ref = {contents = 3} +|}];; + +(* this is rejected as `c` will be dereferenced during the copy, + and is not yet fully defined *) +let rec c = { c with Complex.re = 1.0 };; +[%%expect{| +Line 1, characters 12-39: +1 | let rec c = { c with Complex.re = 1.0 };; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = `A y +and y = fun () -> ignore x +;; +[%%expect{| +val x : [> `A of unit -> unit ] = `A +val y : unit -> unit = +|}];; + +let rec x = { contents = y } +and y = fun () -> ignore x;; +[%%expect{| +val x : (unit -> unit) ref = {contents = } +val y : unit -> unit = +|}];; + +let r = ref (fun () -> ()) +let rec x = fun () -> r := x;; +[%%expect{| +val r : (unit -> unit) ref = {contents = } +val x : unit -> unit = +|}];; + +let rec x = fun () -> y.contents and y = { contents = 3 };; +[%%expect{| +val x : unit -> int = +val y : int ref = {contents = 3} +|}];; + +let r = ref () +let rec x = r := x;; +[%%expect{| +val r : unit ref = {contents = ()} +Line 2, characters 12-18: +2 | let rec x = r := x;; + ^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = + for i = 0 to 1 do + let z = y in ignore z + done +and y = x; ();; +[%%expect{| +Line 2, characters 2-52: +2 | ..for i = 0 to 1 do +3 | let z = y in ignore z +4 | done +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = + for i = 0 to y do + () + done +and y = 10;; +[%%expect{| +Line 2, characters 2-33: +2 | ..for i = 0 to y do +3 | () +4 | done +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = + for i = y to 10 do + () + done +and y = 0;; +[%%expect{| +Line 2, characters 2-34: +2 | ..for i = y to 10 do +3 | () +4 | done +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = + while false do + let y = x in ignore y + done +and y = x; ();; +[%%expect{| +Line 2, characters 2-49: +2 | ..while false do +3 | let y = x in ignore y +4 | done +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = + while y do + () + done +and y = false;; +[%%expect{| +Line 2, characters 2-26: +2 | ..while y do +3 | () +4 | done +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = + while y do + let y = x in ignore y + done +and y = false;; +[%%expect{| +Line 2, characters 2-45: +2 | ..while y do +3 | let y = x in ignore y +4 | done +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + + + +let rec x = y.contents and y = { contents = 3 };; +[%%expect{| +Line 1, characters 12-22: +1 | let rec x = y.contents and y = { contents = 3 };; + ^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = assert y and y = true;; +[%%expect{| +Line 1, characters 12-20: +1 | let rec x = assert y and y = true;; + ^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +(* Recursively constructing arrays of known non-float type is permitted *) +let rec deep_cycle : [`Tuple of [`Shared of 'a] array] as 'a + = `Tuple [| `Shared deep_cycle |];; +[%%expect{| +val deep_cycle : [ `Tuple of [ `Shared of 'a ] array ] as 'a = + `Tuple [|`Shared |] +|}];; + +(* Constructing float arrays was disallowed altogether at one point + by an overzealous check. Constructing float arrays in recursive + bindings is fine when they don't partake in the recursion. *) +let rec _x = let _ = [| 1.0 |] in 1. in ();; +[%%expect{| +- : unit = () +|}];; + +(* The builtin Stdlib.ref is currently treated as a constructor. + Other functions of the same name should not be so treated. *) +let _ = + let module Stdlib = + struct + let ref _ = assert false + end in + let rec x = Stdlib.ref y + and y = fun () -> ignore x + in (x, y) +;; +[%%expect{| +Line 6, characters 14-26: +6 | let rec x = Stdlib.ref y + ^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +(* An example, from Leo White, of let rec bindings that allocate + values of unknown size *) +let foo p x = + let rec f = + if p then (fun y -> x + g y) else (fun y -> g y) + and g = + if not p then (fun y -> x - f y) else (fun y -> f y) + in + (f, g) +;; +[%%expect{| +Line 3, characters 4-52: +3 | if p then (fun y -> x + g y) else (fun y -> g y) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = + match let _ = y in raise Not_found with + _ -> "x" + | exception Not_found -> "z" +and y = match x with + z -> ("y", z);; +[%%expect{| +Line 2, characters 2-85: +2 | ..match let _ = y in raise Not_found with +3 | _ -> "x" +4 | | exception Not_found -> "z" +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + + +(* To compute the dependencies of mutually-recursive bindings, + transitive dependencies must be taken into account. + + The example below was causing a segfault in 4.08+dev. +*) +let rec wrong = + (* x depends on y, + and y depends on wrong, + so it is important to notice that x transitively depends on wrong; + + an earlier version of our letrec analysis would only report that + y depends on wrong, which seems safe as y is not used in the + body. + *) + let rec x = ref y + and y = ref wrong + in ref ("foo" ^ ! ! !x);; +[%%expect{| +Line 10, characters 2-65: +10 | ..let rec x = ref y +11 | and y = ref wrong +12 | in ref ("foo" ^ ! ! !x).. +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}] + +(* in this case, x does not depend on y, so everything is fine *) +let rec okay = + let rec x = ref "bar" + and _y = ref okay in + ref ("foo" ^ ! x);; +[%%expect{| +val okay : string ref = {contents = "foobar"} +|}] diff --git a/testsuite/tests/letrec-check/extension_constructor.ml b/testsuite/tests/letrec-check/extension_constructor.ml new file mode 100644 index 00000000..e581a0ac --- /dev/null +++ b/testsuite/tests/letrec-check/extension_constructor.ml @@ -0,0 +1,25 @@ +(* TEST + * expect +*) + +(* Example from Stephen Dolan. + Accessing an extension constructor involves accessing the module + in which it's defined. + *) +module type T = + sig exception A of int end;; +[%%expect{| +module type T = sig exception A of int end +|}];; + +let rec x = + let module M = (val m) in + M.A 42 +and (m : (module T)) = + (module (struct exception A of int end) : T);; +[%%expect{| +Line 2, characters 2-36: +2 | ..let module M = (val m) in +3 | M.A 42 +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; diff --git a/testsuite/tests/letrec-check/flat_float_array.ml b/testsuite/tests/letrec-check/flat_float_array.ml new file mode 100644 index 00000000..e49064cc --- /dev/null +++ b/testsuite/tests/letrec-check/flat_float_array.ml @@ -0,0 +1,52 @@ +(* TEST + * flat-float-array + ** expect +*) + +(* When the -flat-float-array optimization is active (standard in + OCaml versions up to at least 4.07), creating an array may perform + a dynamic check, inspecing its first element to decide whether it + is a float or not. The check is elided when the type-checker can + determine statically that the type of the elements is float, or + that it will never be float. + + In the dynamic check case, it is unsound to define in + a mutually-recursive way a value and an array containing that + value. + + In the case where an array is statically known to be an array of float, + this dynamic check does not happen, but the elements are unboxed to + be put in the flat float array, so they are dereferenced anyway. +*) + +(* In these tests, `z` is known to be a non-float, + so no unboxing or dynamic check happens, the definition is valid. *) +let f (z: int) = let rec x = [| y; z |] and y = z in x;; +let f (z: bytes) = let rec x = [| y; z |] and y = z in x;; +[%%expect {| +val f : int -> int array = +val f : bytes -> bytes array = +|}];; + +(* In this test, `z` has a generic/polymorphic type, + so it could be instantiated with either float or non-float. + A dynamic check will occur, so the definition must be rejected. *) +let f z = let rec x = [| y; z |] and y = z in x;; +[%%expect {| +Line 1, characters 22-32: +1 | let f z = let rec x = [| y; z |] and y = z in x;; + ^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}] + +(* In this test, `z` is known to be a float, so a float array will be + created. When the flat-float-array optimization is active, the + array elements will be unboxed, thus evaluated. This definition + must be rejected. *) +let f (z: float) = let rec x = [| y; z |] and y = z in x;; +[%%expect {| +Line 1, characters 31-41: +1 | let f (z: float) = let rec x = [| y; z |] and y = z in x;; + ^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}] diff --git a/testsuite/tests/letrec-check/float_unboxing.ml b/testsuite/tests/letrec-check/float_unboxing.ml new file mode 100644 index 00000000..6ef268f8 --- /dev/null +++ b/testsuite/tests/letrec-check/float_unboxing.ml @@ -0,0 +1,37 @@ +(* TEST + * expect +*) + +(* This program is a minimal example which segfault if + (e1.x <- e2) considers that (e2) is in Return mode, + rather than Dereference -- here a write to a + field in a statically-known all-float record is + unboxed on the flight, so accepting this example + would dereference (when running `g.f <- y` with y + uninitialized) an arbitrary address. *) +type t = { mutable f: float } +let g = { f = 0.0 } +let rec x = (g.f <- y; ()) and y = 2.0;; +[%%expect{| +type t = { mutable f : float; } +val g : t = {f = 0.} +Line 3, characters 12-26: +3 | let rec x = (g.f <- y; ()) and y = 2.0;; + ^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +(* same example, with object instance variables + instead of record fields *) +class c = object + val mutable f = 0.0 + method m = + let rec x = (f <- y; ()) and y = 2.0 in f +end;; +let _ = print_float (new c)#m;; +[%%expect{| +Line 4, characters 16-28: +4 | let rec x = (f <- y; ()) and y = 2.0 in f + ^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; diff --git a/testsuite/tests/letrec-check/labels.ml b/testsuite/tests/letrec-check/labels.ml new file mode 100644 index 00000000..e8b28342 --- /dev/null +++ b/testsuite/tests/letrec-check/labels.ml @@ -0,0 +1,33 @@ +(* TEST + * expect +*) + +let f ~x () = x ();; +[%%expect{| +val f : x:(unit -> 'a) -> unit -> 'a = +|}];; + +let rec x = f ~x;; +[%%expect{| +Line 1, characters 12-16: +1 | let rec x = f ~x;; + ^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let f x ~y = x + y +(* this function creates "abstracted arguments" in the sense of + Rec_check.is_abstracted_arg. Those should be treated as + returned/unguarded, and not delayed, otherwise the code below + segfaults. *) +let rec g = f ~y:(print_endline !y; 0) +and y = + let _ = g in (* ignore g to have a real dependency *) + ref "foo";; +[%%expect {| +val f : int -> y:int -> int = +Line 6, characters 12-38: +6 | let rec g = f ~y:(print_endline !y; 0) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}] diff --git a/testsuite/tests/letrec-check/lazy_.ml b/testsuite/tests/letrec-check/lazy_.ml new file mode 100644 index 00000000..3bec9ec7 --- /dev/null +++ b/testsuite/tests/letrec-check/lazy_.ml @@ -0,0 +1,23 @@ +(* TEST + * expect +*) + +let rec a = lazy b and b = 3;; +[%%expect{| +Line 1, characters 12-18: +1 | let rec a = lazy b and b = 3;; + ^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec e = lazy (fun _ -> f) and f = ();; +[%%expect{| +val e : ('a -> unit) lazy_t = lazy +val f : unit = () +|}];; + +let rec x = lazy (Lazy.force x + Lazy.force x) + ;; +[%%expect{| +val x : int Lazy.t = +|}];; diff --git a/testsuite/tests/letrec-check/modules.ml b/testsuite/tests/letrec-check/modules.ml new file mode 100644 index 00000000..883c49d9 --- /dev/null +++ b/testsuite/tests/letrec-check/modules.ml @@ -0,0 +1,97 @@ +(* TEST + * expect +*) + +let rec x = let module M = struct let f = x end in ();; +[%%expect{| +val x : unit = () +|}];; + +let rec x = let module M = struct let f = x let g = x () end in fun () -> ();; +[%%expect{| +Line 1, characters 12-76: +1 | let rec x = let module M = struct let f = x let g = x () end in fun () -> ();; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = let module M = struct let f = x () let g = x end in fun () -> ();; +[%%expect{| +Line 1, characters 12-76: +1 | let rec x = let module M = struct let f = x () let g = x end in fun () -> ();; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = (let module M = struct let f = y 0 let g = () end in fun () -> ()) + and y = succ;; +[%%expect{| +Line 1, characters 12-78: +1 | let rec x = (let module M = struct let f = y 0 let g = () end in fun () -> ()) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = + let module M = struct + module N = struct let y = x end + end in M.N.y;; +[%%expect{| +Line 2, characters 2-74: +2 | ..let module M = struct +3 | module N = struct let y = x end +4 | end in M.N.y.. +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +module type T = sig val y: int end + +let rec x = let module M = + struct + module N = + struct + let y = x + end + end + in fun () -> ignore (M.N.y ());; +[%%expect{| +module type T = sig val y : int end +val x : unit -> unit = +|}];; + +let rec x = let module M = struct let f = x () and g = x end in fun () -> ();; +[%%expect{| +Line 1, characters 12-76: +1 | let rec x = let module M = struct let f = x () and g = x end in fun () -> ();; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +module type T = sig end +let rec x = (module (val y : T) : T) +and y = let module M = struct let x = x end in (module M : T) +;; +[%%expect{| +module type T = sig end +Line 2, characters 12-36: +2 | let rec x = (module (val y : T) : T) + ^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +(* module constraints *) +module type S = sig val y : float end;; +module type T = sig val x : float val y : float end;; +type t = T : (module S) -> t;; + +let rec x = let module M = (val m) in T (module M) +and (m : (module T)) = (module (struct let x = 10.0 and y = 20.0 end) : T);; +[%%expect{| +module type S = sig val y : float end +module type T = sig val x : float val y : float end +type t = T : (module S) -> t +Line 5, characters 12-50: +5 | let rec x = let module M = (val m) in T (module M) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; diff --git a/testsuite/tests/letrec-check/no_flat_float_array.ml b/testsuite/tests/letrec-check/no_flat_float_array.ml new file mode 100644 index 00000000..394669bf --- /dev/null +++ b/testsuite/tests/letrec-check/no_flat_float_array.ml @@ -0,0 +1,32 @@ +(* TEST + * no-flat-float-array + ** expect +*) + +(* See float_block_disallowed.ml for explanations. + + When the -flat-float-array optimization is *not* set, float arrays + are not unboxed, and no dynamic check is performed on generc array + creation, so array literals behave just like other constructors + and can be defined mutually recursively with their elements. +*) + +(* Case of elements known not to be float. *) +let f (z: int) = let rec x = [| y; z |] and y = z in x;; +let f (z: bytes) = let rec x = [| y; z |] and y = z in x;; +[%%expect {| +val f : int -> int array = +val f : bytes -> bytes array = +|}];; + +(* Generic case (element may or may not be float), no dynamic test. *) +let f z = let rec x = [| y; z |] and y = z in x;; +[%%expect {| +val f : 'a -> 'a array = +|}] + +(* Float case, no unboxing. *) +let f (z: float) = let rec x = [| y; z |] and y = z in x;; +[%%expect {| +val f : float -> float array = +|}] diff --git a/testsuite/tests/letrec-check/objects.ml b/testsuite/tests/letrec-check/objects.ml new file mode 100644 index 00000000..a223450e --- /dev/null +++ b/testsuite/tests/letrec-check/objects.ml @@ -0,0 +1,60 @@ +(* TEST + * expect +*) + +class c = object end +let rec x = fun () -> new c;; +[%%expect{| +class c : object end +val x : unit -> c = +|}];; + +class c _ = object end +let rec x = new c x;; +[%%expect{| +class c : 'a -> object end +Line 2, characters 12-19: +2 | let rec x = new c x;; + ^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = y#m and y = object method m = () end;; +[%%expect{| +Line 1, characters 12-15: +1 | let rec x = y#m and y = object method m = () end;; + ^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = (object method m _ = () end)#m x;; +[%%expect{| +Line 1, characters 12-44: +1 | let rec x = (object method m _ = () end)#m x;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = object val mutable v = 0 method m = v <- y end and y = 1;; +[%%expect{| +Line 1, characters 12-58: +1 | let rec x = object val mutable v = 0 method m = v <- y end and y = 1;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = object method m = x end;; +[%%expect{| +Line 1, characters 12-35: +1 | let rec x = object method m = x end;; + ^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +let rec x = object method m = ignore x end;; +[%%expect{| +Line 1, characters 12-42: +1 | let rec x = object method m = ignore x end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; diff --git a/testsuite/tests/letrec-check/ocamltests b/testsuite/tests/letrec-check/ocamltests new file mode 100644 index 00000000..3cae2e71 --- /dev/null +++ b/testsuite/tests/letrec-check/ocamltests @@ -0,0 +1,14 @@ +basic.ml +extension_constructor.ml +flat_float_array.ml +no_flat_float_array.ml +float_unboxing.ml +records.ml +labels.ml +lazy_.ml +modules.ml +objects.ml +pr7215.ml +pr7231.ml +pr7706.ml +unboxed.ml diff --git a/testsuite/tests/letrec-disallowed/pr7215.ml b/testsuite/tests/letrec-check/pr7215.ml similarity index 100% rename from testsuite/tests/letrec-disallowed/pr7215.ml rename to testsuite/tests/letrec-check/pr7215.ml diff --git a/testsuite/tests/letrec-check/pr7215.ocaml.reference b/testsuite/tests/letrec-check/pr7215.ocaml.reference new file mode 100644 index 00000000..197a1009 --- /dev/null +++ b/testsuite/tests/letrec-check/pr7215.ocaml.reference @@ -0,0 +1,7 @@ +type (_, _) eq = Refl : ('a, 'a) eq +val cast : ('a, 'b) eq -> 'a -> 'b = +Line 3, characters 30-55: +3 | let rec (p : (int, a) eq) = match p with Refl -> Refl in + ^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' + diff --git a/testsuite/tests/letrec-check/pr7231.ml b/testsuite/tests/letrec-check/pr7231.ml new file mode 100644 index 00000000..b2ddf3c2 --- /dev/null +++ b/testsuite/tests/letrec-check/pr7231.ml @@ -0,0 +1,5 @@ +(* TEST + * toplevel +*) + +let rec r = let rec x () = r and y () = x () in y () in r "oops";; diff --git a/testsuite/tests/letrec-check/pr7231.ocaml.reference b/testsuite/tests/letrec-check/pr7231.ocaml.reference new file mode 100644 index 00000000..9b1a5a13 --- /dev/null +++ b/testsuite/tests/letrec-check/pr7231.ocaml.reference @@ -0,0 +1,9 @@ +Line 5, characters 58-64: +5 | let rec r = let rec x () = r and y () = x () in y () in r "oops";; + ^^^^^^ +Warning 20: this argument will not be used by the function. +Line 5, characters 12-52: +5 | let rec r = let rec x () = r and y () = x () in y () in r "oops";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' + diff --git a/testsuite/tests/letrec-disallowed/pr7706.ml b/testsuite/tests/letrec-check/pr7706.ml similarity index 100% rename from testsuite/tests/letrec-disallowed/pr7706.ml rename to testsuite/tests/letrec-check/pr7706.ml diff --git a/testsuite/tests/letrec-check/pr7706.ocaml.reference b/testsuite/tests/letrec-check/pr7706.ocaml.reference new file mode 100644 index 00000000..3303026b --- /dev/null +++ b/testsuite/tests/letrec-check/pr7706.ocaml.reference @@ -0,0 +1,9 @@ +Line 5, characters 2-67: +5 | ..let y = if false then (fun z -> 1) else (fun z -> x 4 + 1) in +6 | y.. +Error: This kind of expression is not allowed as right-hand side of `let rec' +Line 2, characters 17-18: +2 | let () = ignore (x 42);; + ^ +Error: Unbound value x + diff --git a/testsuite/tests/letrec-check/records.ml b/testsuite/tests/letrec-check/records.ml new file mode 100644 index 00000000..db11d41e --- /dev/null +++ b/testsuite/tests/letrec-check/records.ml @@ -0,0 +1,31 @@ +(* TEST + * expect +*) +type t = { x : int; self : t };; +[%%expect {| +type t = { x : int; self : t; } +|}];; + +let rec x = 1 +and u = Some { t with x = 2 } +and t = { x; self = t } +(* We have carefully placed `u` before `t` here, + so that the copy { t with .. }, if accepted, + is evaluated before 't' is initialized -- making + the assertion below fail, typically aborting + with a segmentation fault. + + If you exchange the declaration orders of `u` and `t`, + and the static check accepts this example, then `t` + is initialized first and the assertion succeeds. *) + + +let () = match u with + | None -> assert false + | Some {x = _; self} -> assert (self.x = t.x) +[%%expect {| +Line 2, characters 8-29: +2 | and u = Some { t with x = 2 } + ^^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; diff --git a/testsuite/tests/letrec-check/unboxed.ml b/testsuite/tests/letrec-check/unboxed.ml new file mode 100644 index 00000000..78284722 --- /dev/null +++ b/testsuite/tests/letrec-check/unboxed.ml @@ -0,0 +1,109 @@ +(* TEST + * expect +*) + +type r = R of r list [@@unboxed] +let rec a = R [a];; +[%%expect{| +type r = R of r list [@@unboxed] +val a : r = R [] +|}];; + + +type t = {x: int64} [@@unboxed] +let rec x = {x = y} and y = 3L;; +[%%expect{| +type t = { x : int64; } [@@unboxed] +Line 2, characters 12-19: +2 | let rec x = {x = y} and y = 3L;; + ^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +type r = A of r [@@unboxed] +let rec y = A y;; +[%%expect{| +type r = A of r [@@unboxed] +Line 2, characters 12-15: +2 | let rec y = A y;; + ^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +(* This test is not allowed if 'a' is unboxed, but should be accepted + as written *) +type a = {a: b} +and b = X of a | Y + +let rec a = + {a= + (if Sys.opaque_identity true then + X a + else + Y)};; +[%%expect{| +type a = { a : b; } +and b = X of a | Y +val a : a = {a = X } +|}];; + +type a = {a: b }[@@unboxed] +and b = X of a | Y + +let rec a = + {a= + (if Sys.opaque_identity true then + X a + else + Y)};; +[%%expect{| +type a = { a : b; } [@@unboxed] +and b = X of a | Y +Line 5, characters 2-75: +5 | ..{a= +6 | (if Sys.opaque_identity true then +7 | X a +8 | else +9 | Y)}.. +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; + +(* This test is not allowed if 'c' is unboxed, but should be accepted + as written *) +type d = D of e +and e = V of d | W;; +[%%expect{| +type d = D of e +and e = V of d | W +|}];; + +let rec d = + D + (if Sys.opaque_identity true then + V d + else + W);; +[%%expect{| +val d : d = D (V ) +|}];; + +type d = D of e [@@unboxed] +and e = V of d | W;; + +let rec d = + D + (if Sys.opaque_identity true then + V d + else + W);; +[%%expect{| +type d = D of e [@@unboxed] +and e = V of d | W +Line 5, characters 2-72: +5 | ..D +6 | (if Sys.opaque_identity true then +7 | V d +8 | else +9 | W).. +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; diff --git a/testsuite/tests/letrec/backreferences.ml b/testsuite/tests/letrec-compilation/backreferences.ml similarity index 100% rename from testsuite/tests/letrec/backreferences.ml rename to testsuite/tests/letrec-compilation/backreferences.ml diff --git a/testsuite/tests/letrec/generic_array.reference b/testsuite/tests/letrec-compilation/backreferences.reference similarity index 100% rename from testsuite/tests/letrec/generic_array.reference rename to testsuite/tests/letrec-compilation/backreferences.reference diff --git a/testsuite/tests/letrec/class_1.ml b/testsuite/tests/letrec-compilation/class_1.ml similarity index 100% rename from testsuite/tests/letrec/class_1.ml rename to testsuite/tests/letrec-compilation/class_1.ml diff --git a/testsuite/tests/letrec/labels.reference b/testsuite/tests/letrec-compilation/class_1.reference similarity index 100% rename from testsuite/tests/letrec/labels.reference rename to testsuite/tests/letrec-compilation/class_1.reference diff --git a/testsuite/tests/letrec/class_2.ml b/testsuite/tests/letrec-compilation/class_2.ml similarity index 100% rename from testsuite/tests/letrec/class_2.ml rename to testsuite/tests/letrec-compilation/class_2.ml diff --git a/testsuite/tests/letrec/class_2.reference b/testsuite/tests/letrec-compilation/class_2.reference similarity index 100% rename from testsuite/tests/letrec/class_2.reference rename to testsuite/tests/letrec-compilation/class_2.reference diff --git a/testsuite/tests/letrec/evaluation_order_1.ml b/testsuite/tests/letrec-compilation/evaluation_order_1.ml similarity index 100% rename from testsuite/tests/letrec/evaluation_order_1.ml rename to testsuite/tests/letrec-compilation/evaluation_order_1.ml diff --git a/testsuite/tests/letrec/evaluation_order_1.reference b/testsuite/tests/letrec-compilation/evaluation_order_1.reference similarity index 100% rename from testsuite/tests/letrec/evaluation_order_1.reference rename to testsuite/tests/letrec-compilation/evaluation_order_1.reference diff --git a/testsuite/tests/letrec/evaluation_order_2.ml b/testsuite/tests/letrec-compilation/evaluation_order_2.ml similarity index 100% rename from testsuite/tests/letrec/evaluation_order_2.ml rename to testsuite/tests/letrec-compilation/evaluation_order_2.ml diff --git a/testsuite/tests/letrec/evaluation_order_2.reference b/testsuite/tests/letrec-compilation/evaluation_order_2.reference similarity index 100% rename from testsuite/tests/letrec/evaluation_order_2.reference rename to testsuite/tests/letrec-compilation/evaluation_order_2.reference diff --git a/testsuite/tests/letrec/evaluation_order_3.ml b/testsuite/tests/letrec-compilation/evaluation_order_3.ml similarity index 100% rename from testsuite/tests/letrec/evaluation_order_3.ml rename to testsuite/tests/letrec-compilation/evaluation_order_3.ml diff --git a/testsuite/tests/letrec/evaluation_order_3.reference b/testsuite/tests/letrec-compilation/evaluation_order_3.reference similarity index 100% rename from testsuite/tests/letrec/evaluation_order_3.reference rename to testsuite/tests/letrec-compilation/evaluation_order_3.reference diff --git a/testsuite/tests/letrec/float_block_1.ml b/testsuite/tests/letrec-compilation/float_block_1.ml similarity index 100% rename from testsuite/tests/letrec/float_block_1.ml rename to testsuite/tests/letrec-compilation/float_block_1.ml diff --git a/testsuite/tests/letrec/float_block_1.reference b/testsuite/tests/letrec-compilation/float_block_1.reference similarity index 100% rename from testsuite/tests/letrec/float_block_1.reference rename to testsuite/tests/letrec-compilation/float_block_1.reference diff --git a/testsuite/tests/letrec/generic_array.ml b/testsuite/tests/letrec-compilation/generic_array.ml similarity index 100% rename from testsuite/tests/letrec/generic_array.ml rename to testsuite/tests/letrec-compilation/generic_array.ml diff --git a/testsuite/tests/letrec/lists.reference b/testsuite/tests/letrec-compilation/generic_array.reference similarity index 100% rename from testsuite/tests/letrec/lists.reference rename to testsuite/tests/letrec-compilation/generic_array.reference diff --git a/testsuite/tests/letrec/labels.ml b/testsuite/tests/letrec-compilation/labels.ml similarity index 100% rename from testsuite/tests/letrec/labels.ml rename to testsuite/tests/letrec-compilation/labels.ml diff --git a/testsuite/tests/letrec/mixing_value_closures_1.reference b/testsuite/tests/letrec-compilation/labels.reference similarity index 100% rename from testsuite/tests/letrec/mixing_value_closures_1.reference rename to testsuite/tests/letrec-compilation/labels.reference diff --git a/testsuite/tests/letrec/lazy_.ml b/testsuite/tests/letrec-compilation/lazy_.ml similarity index 100% rename from testsuite/tests/letrec/lazy_.ml rename to testsuite/tests/letrec-compilation/lazy_.ml diff --git a/testsuite/tests/letrec/lazy_.reference b/testsuite/tests/letrec-compilation/lazy_.reference similarity index 100% rename from testsuite/tests/letrec/lazy_.reference rename to testsuite/tests/letrec-compilation/lazy_.reference diff --git a/testsuite/tests/letrec/lists.ml b/testsuite/tests/letrec-compilation/lists.ml similarity index 100% rename from testsuite/tests/letrec/lists.ml rename to testsuite/tests/letrec-compilation/lists.ml diff --git a/testsuite/tests/letrec/mixing_value_closures_2.reference b/testsuite/tests/letrec-compilation/lists.reference similarity index 100% rename from testsuite/tests/letrec/mixing_value_closures_2.reference rename to testsuite/tests/letrec-compilation/lists.reference diff --git a/testsuite/tests/letrec/mixing_value_closures_1.ml b/testsuite/tests/letrec-compilation/mixing_value_closures_1.ml similarity index 100% rename from testsuite/tests/letrec/mixing_value_closures_1.ml rename to testsuite/tests/letrec-compilation/mixing_value_closures_1.ml diff --git a/testsuite/tests/letrec/mutual_functions.reference b/testsuite/tests/letrec-compilation/mixing_value_closures_1.reference similarity index 100% rename from testsuite/tests/letrec/mutual_functions.reference rename to testsuite/tests/letrec-compilation/mixing_value_closures_1.reference diff --git a/testsuite/tests/letrec/mixing_value_closures_2.ml b/testsuite/tests/letrec-compilation/mixing_value_closures_2.ml similarity index 100% rename from testsuite/tests/letrec/mixing_value_closures_2.ml rename to testsuite/tests/letrec-compilation/mixing_value_closures_2.ml diff --git a/testsuite/tests/letrec/nested.reference b/testsuite/tests/letrec-compilation/mixing_value_closures_2.reference similarity index 100% rename from testsuite/tests/letrec/nested.reference rename to testsuite/tests/letrec-compilation/mixing_value_closures_2.reference diff --git a/testsuite/tests/letrec/mutual_functions.ml b/testsuite/tests/letrec-compilation/mutual_functions.ml similarity index 100% rename from testsuite/tests/letrec/mutual_functions.ml rename to testsuite/tests/letrec-compilation/mutual_functions.ml diff --git a/testsuite/tests/letrec/pr4989.reference b/testsuite/tests/letrec-compilation/mutual_functions.reference similarity index 100% rename from testsuite/tests/letrec/pr4989.reference rename to testsuite/tests/letrec-compilation/mutual_functions.reference diff --git a/testsuite/tests/letrec/nested.ml b/testsuite/tests/letrec-compilation/nested.ml similarity index 100% rename from testsuite/tests/letrec/nested.ml rename to testsuite/tests/letrec-compilation/nested.ml diff --git a/testsuite/tests/letrec/ref.reference b/testsuite/tests/letrec-compilation/nested.reference similarity index 100% rename from testsuite/tests/letrec/ref.reference rename to testsuite/tests/letrec-compilation/nested.reference diff --git a/testsuite/tests/letrec-compilation/ocamltests b/testsuite/tests/letrec-compilation/ocamltests new file mode 100644 index 00000000..6fb1f819 --- /dev/null +++ b/testsuite/tests/letrec-compilation/ocamltests @@ -0,0 +1,18 @@ +backreferences.ml +class_1.ml +class_2.ml +evaluation_order_1.ml +evaluation_order_2.ml +evaluation_order_3.ml +float_block_1.ml +generic_array.ml +labels.ml +lazy_.ml +lists.ml +mixing_value_closures_1.ml +mixing_value_closures_2.ml +mutual_functions.ml +nested.ml +pr4989.ml +record_with.ml +ref.ml diff --git a/testsuite/tests/letrec/pr4989.ml b/testsuite/tests/letrec-compilation/pr4989.ml similarity index 100% rename from testsuite/tests/letrec/pr4989.ml rename to testsuite/tests/letrec-compilation/pr4989.ml diff --git a/testsuite/tests/unboxed-primitive-args/main.reference b/testsuite/tests/letrec-compilation/pr4989.reference similarity index 100% rename from testsuite/tests/unboxed-primitive-args/main.reference rename to testsuite/tests/letrec-compilation/pr4989.reference diff --git a/testsuite/tests/letrec/record_with.ml b/testsuite/tests/letrec-compilation/record_with.ml similarity index 100% rename from testsuite/tests/letrec/record_with.ml rename to testsuite/tests/letrec-compilation/record_with.ml diff --git a/testsuite/tests/letrec/record_with.reference b/testsuite/tests/letrec-compilation/record_with.reference similarity index 100% rename from testsuite/tests/letrec/record_with.reference rename to testsuite/tests/letrec-compilation/record_with.reference diff --git a/testsuite/tests/letrec-compilation/ref.ml b/testsuite/tests/letrec-compilation/ref.ml new file mode 100644 index 00000000..990191c4 --- /dev/null +++ b/testsuite/tests/letrec-compilation/ref.ml @@ -0,0 +1,15 @@ +(* TEST *) + +(* Test construction of cyclic values where the cycles pass through + references *) + +type t = { mutable next : t; mutable inst : n ref } +and n = T of t + +let rec d = { next = d; inst = ref (T d) } + +let f t1 t2 = + let rec self = ref init + and init () = t1 (function () -> self := t2; t2 ()) + in fun () -> !self () +;; diff --git a/testsuite/tests/letrec-compilation/ref.reference b/testsuite/tests/letrec-compilation/ref.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/letrec-disallowed/disallowed.ml b/testsuite/tests/letrec-disallowed/disallowed.ml deleted file mode 100644 index ae156843..00000000 --- a/testsuite/tests/letrec-disallowed/disallowed.ml +++ /dev/null @@ -1,116 +0,0 @@ -(* TEST - * toplevel -*) - -let rec x = let y = () in x;; - -let rec x = let module M = struct let f = x let g = x () end in fun () -> ();; - -let rec x = let module M = struct let f = x () let g = x end in fun () -> ();; - -let rec x = (let module M = struct let f = y 0 let g = () end in fun () -> ()) - and y = succ;; - -let rec x = let module M = struct module N = struct let y = x end end in M.N.y;; - -let rec x = let module M = struct let f = x () and g = x end in fun () -> ();; - -class c _ = object end;; -let rec x = new c x;; - -let rec x = ignore x;; - -let rec x = y 0 and y _ = ();; - -let rec c = { c with Complex.re = 1.0 };; - -let rec b = if b then true else false;; - -let r = ref () -let rec x = r := x;; - -let rec x = - for i = 0 to 1 do - let z = y in ignore z - done -and y = x; ();; - -let rec x = - for i = 0 to y do - () - done -and y = 10;; - -let rec x = - for i = y to 10 do - () - done -and y = 0;; - -let rec x = - while false do - let y = x in ignore y - done -and y = x; ();; - -let rec x = - while y do - () - done -and y = false;; - -let rec x = - while y do - let y = x in ignore y - done -and y = false;; - -let rec x = y#m and y = object method m = () end;; - -let rec x = (object method m _ = () end)#m x;; - -let rec x = y.contents and y = { contents = 3 };; - -let rec x = object val mutable v = 0 method m = v <- y end and y = 1;; - -let rec x = assert y and y = true;; - -let rec x = object method m = x end;; - -let rec x = object method m = ignore x end;; - -(* The builtin Pervasives.ref is currently treated as a constructor. - Other functions of the same name should not be so treated. *) -let _ = - let module Pervasives = - struct - let ref _ = assert false - end in - let rec x = Pervasives.ref y - and y = fun () -> ignore x - in (x, y) -;; - -(* An example, from Leo White, of let rec bindings that allocate - values of unknown size *) -let foo p x = - let rec f = - if p then (fun y -> x + g y) else (fun y -> g y) - and g = - if not p then (fun y -> x - f y) else (fun y -> f y) - in - (f, g) -;; - -module type T = sig end -let rec x = (module (val y : T) : T) -and y = let module M = struct let x = x end in (module M : T) -;; - -let rec x = - match let _ = y in raise Not_found with - _ -> "x" - | exception Not_found -> "z" -and y = match x with - z -> ("y", z);; - diff --git a/testsuite/tests/letrec-disallowed/disallowed.ocaml.reference b/testsuite/tests/letrec-disallowed/disallowed.ocaml.reference deleted file mode 100644 index 7effceb8..00000000 --- a/testsuite/tests/letrec-disallowed/disallowed.ocaml.reference +++ /dev/null @@ -1,125 +0,0 @@ -Characters 38-53: - let rec x = let y = () in x;; - ^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-77: - let rec x = let module M = struct let f = x let g = x () end in fun () -> ();; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-77: - let rec x = let module M = struct let f = x () let g = x end in fun () -> ();; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-79: - let rec x = (let module M = struct let f = y 0 let g = () end in fun () -> ()) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-79: - let rec x = let module M = struct module N = struct let y = x end end in M.N.y;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-77: - let rec x = let module M = struct let f = x () and g = x end in fun () -> ();; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -class c : 'a -> object end -Characters 12-19: - let rec x = new c x;; - ^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-21: - let rec x = ignore x;; - ^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-16: - let rec x = y 0 and y _ = ();; - ^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-40: - let rec c = { c with Complex.re = 1.0 };; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-38: - let rec b = if b then true else false;; - ^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 28-34: - let rec x = r := x;; - ^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 15-65: - ..for i = 0 to 1 do - let z = y in ignore z - done -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 15-46: - ..for i = 0 to y do - () - done -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 15-47: - ..for i = y to 10 do - () - done -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 15-62: - ..while false do - let y = x in ignore y - done -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 15-39: - ..while y do - () - done -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 15-58: - ..while y do - let y = x in ignore y - done -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-16: - let rec x = y#m and y = object method m = () end;; - ^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-45: - let rec x = (object method m _ = () end)#m x;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-23: - let rec x = y.contents and y = { contents = 3 };; - ^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-59: - let rec x = object val mutable v = 0 method m = v <- y end and y = 1;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-21: - let rec x = assert y and y = true;; - ^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-36: - let rec x = object method m = x end;; - ^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 13-43: - let rec x = object method m = ignore x end;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 230-246: - let rec x = Pervasives.ref y - ^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 127-175: - if p then (fun y -> x + g y) else (fun y -> g y) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 37-61: - let rec x = (module (val y : T) : T) - ^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 15-98: - ..match let _ = y in raise Not_found with - _ -> "x" - | exception Not_found -> "z". -Error: This kind of expression is not allowed as right-hand side of `let rec' - diff --git a/testsuite/tests/letrec-disallowed/extension_constructor.ml b/testsuite/tests/letrec-disallowed/extension_constructor.ml deleted file mode 100644 index a49fcbd0..00000000 --- a/testsuite/tests/letrec-disallowed/extension_constructor.ml +++ /dev/null @@ -1,16 +0,0 @@ -(* TEST - * toplevel -*) - -(* Example from Stephen Dolan. - Accessing an extension constructor involves accessing the module - in which it's defined. - *) -module type T = - sig exception A of int end;; - -let rec x = - let module M = (val m) in - M.A 42 -and (m : (module T)) = - (module (struct exception A of int end));; diff --git a/testsuite/tests/letrec-disallowed/extension_constructor.ocaml.reference b/testsuite/tests/letrec-disallowed/extension_constructor.ocaml.reference deleted file mode 100644 index fcd714e1..00000000 --- a/testsuite/tests/letrec-disallowed/extension_constructor.ocaml.reference +++ /dev/null @@ -1,6 +0,0 @@ -module type T = sig exception A of int end -Characters 15-49: - ..let module M = (val m) in - M.A 42 -Error: This kind of expression is not allowed as right-hand side of `let rec' - diff --git a/testsuite/tests/letrec-disallowed/float_block_allowed.ml b/testsuite/tests/letrec-disallowed/float_block_allowed.ml deleted file mode 100644 index 1b9ad983..00000000 --- a/testsuite/tests/letrec-disallowed/float_block_allowed.ml +++ /dev/null @@ -1,14 +0,0 @@ -(* TEST - * no-flat-float-array - ** toplevel -*) - -(* these recursive float arrays are allowed when -no-flat-float-array - is set -- the first array element is not forced on array creation - anymore *) -let test = - let rec x = [| y; y |] and y = 1. in - assert (x = [| 1.; 1. |]); - assert (y = 1.); - () -;; diff --git a/testsuite/tests/letrec-disallowed/float_block_allowed.ocaml.reference b/testsuite/tests/letrec-disallowed/float_block_allowed.ocaml.reference deleted file mode 100644 index 422a95ec..00000000 --- a/testsuite/tests/letrec-disallowed/float_block_allowed.ocaml.reference +++ /dev/null @@ -1,2 +0,0 @@ -val test : unit = () - diff --git a/testsuite/tests/letrec-disallowed/float_block_disallowed.ml b/testsuite/tests/letrec-disallowed/float_block_disallowed.ml deleted file mode 100644 index ca9e6dc8..00000000 --- a/testsuite/tests/letrec-disallowed/float_block_disallowed.ml +++ /dev/null @@ -1,18 +0,0 @@ -(* TEST - * flat-float-array - ** toplevel -*) - -(* when the -flat-float-array optimization is active (standard in - OCaml versions up to at least 4.07), creating an array inspects its - first element to decide whether it is a float or not; it would thus - be unsound to allow to recursively define a float value and an - array starting with that element (in general we disallow using a - recursively-defined value in an array literal). -*) -let test = - let rec x = [| y; y |] and y = 1. in - assert (x = [| 1.; 1. |]); - assert (y = 1.); - () -;; diff --git a/testsuite/tests/letrec-disallowed/float_block_disallowed.ocaml.reference b/testsuite/tests/letrec-disallowed/float_block_disallowed.ocaml.reference deleted file mode 100644 index f3139c32..00000000 --- a/testsuite/tests/letrec-disallowed/float_block_disallowed.ocaml.reference +++ /dev/null @@ -1,5 +0,0 @@ -Characters 470-480: - let rec x = [| y; y |] and y = 1. in - ^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' - diff --git a/testsuite/tests/letrec-disallowed/generic_arrays.ml b/testsuite/tests/letrec-disallowed/generic_arrays.ml deleted file mode 100644 index a4735051..00000000 --- a/testsuite/tests/letrec-disallowed/generic_arrays.ml +++ /dev/null @@ -1,7 +0,0 @@ -(* TEST - * toplevel -*) - -(* This is not allowed because constructing the generic array 'x' involves - inspecting 'y', which is bound in the same recursive group *) -let f z = let rec x = [| y; z |] and y = z in x;; diff --git a/testsuite/tests/letrec-disallowed/generic_arrays.ocaml.reference b/testsuite/tests/letrec-disallowed/generic_arrays.ocaml.reference deleted file mode 100644 index cfac91cc..00000000 --- a/testsuite/tests/letrec-disallowed/generic_arrays.ocaml.reference +++ /dev/null @@ -1,5 +0,0 @@ -Characters 188-198: - let f z = let rec x = [| y; z |] and y = z in x;; - ^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' - diff --git a/testsuite/tests/letrec-disallowed/labels.ml b/testsuite/tests/letrec-disallowed/labels.ml deleted file mode 100644 index ff94719a..00000000 --- a/testsuite/tests/letrec-disallowed/labels.ml +++ /dev/null @@ -1,6 +0,0 @@ -(* TEST - * toplevel -*) - -let f ~x () = x ();; -let rec x = f ~x;; diff --git a/testsuite/tests/letrec-disallowed/labels.ocaml.reference b/testsuite/tests/letrec-disallowed/labels.ocaml.reference deleted file mode 100644 index 2e778e55..00000000 --- a/testsuite/tests/letrec-disallowed/labels.ocaml.reference +++ /dev/null @@ -1,6 +0,0 @@ -val f : x:(unit -> 'a) -> unit -> 'a = -Characters 12-16: - let rec x = f ~x;; - ^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' - diff --git a/testsuite/tests/letrec-disallowed/lazy_.ml b/testsuite/tests/letrec-disallowed/lazy_.ml deleted file mode 100644 index 38a964ed..00000000 --- a/testsuite/tests/letrec-disallowed/lazy_.ml +++ /dev/null @@ -1,7 +0,0 @@ -(* TEST - * toplevel -*) - -let rec a = lazy b and b = 3;; - -let rec e = lazy (fun _ -> f) and f = ();; diff --git a/testsuite/tests/letrec-disallowed/lazy_.ocaml.reference b/testsuite/tests/letrec-disallowed/lazy_.ocaml.reference deleted file mode 100644 index 0c6ebd21..00000000 --- a/testsuite/tests/letrec-disallowed/lazy_.ocaml.reference +++ /dev/null @@ -1,7 +0,0 @@ -Characters 39-45: - let rec a = lazy b and b = 3;; - ^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -val e : ('a -> unit) lazy_t = lazy -val f : unit = () - diff --git a/testsuite/tests/letrec-disallowed/module_constraints.ml b/testsuite/tests/letrec-disallowed/module_constraints.ml deleted file mode 100644 index 29114fea..00000000 --- a/testsuite/tests/letrec-disallowed/module_constraints.ml +++ /dev/null @@ -1,10 +0,0 @@ -(* TEST - * toplevel -*) - -module type S = sig val y : float end;; -module type T = sig val x : float val y : float end;; -type t = T : (module S) -> t;; - -let rec x = let module M = (val m) in T (module M) -and (m : (module T)) = (module (struct let x = 10.0 and y = 20.0 end));; diff --git a/testsuite/tests/letrec-disallowed/module_constraints.ocaml.reference b/testsuite/tests/letrec-disallowed/module_constraints.ocaml.reference deleted file mode 100644 index b94a8779..00000000 --- a/testsuite/tests/letrec-disallowed/module_constraints.ocaml.reference +++ /dev/null @@ -1,8 +0,0 @@ -module type S = sig val y : float end -module type T = sig val x : float val y : float end -type t = T : (module S) -> t -Characters 13-51: - let rec x = let module M = (val m) in T (module M) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' - diff --git a/testsuite/tests/letrec-disallowed/ocamltests b/testsuite/tests/letrec-disallowed/ocamltests deleted file mode 100644 index f7eed7e3..00000000 --- a/testsuite/tests/letrec-disallowed/ocamltests +++ /dev/null @@ -1,12 +0,0 @@ -disallowed.ml -extension_constructor.ml -float_block_allowed.ml -float_block_disallowed.ml -generic_arrays.ml -labels.ml -lazy_.ml -module_constraints.ml -pr7215.ml -pr7231.ml -pr7706.ml -unboxed.ml diff --git a/testsuite/tests/letrec-disallowed/pr7215.ocaml.reference b/testsuite/tests/letrec-disallowed/pr7215.ocaml.reference deleted file mode 100644 index 0c16042e..00000000 --- a/testsuite/tests/letrec-disallowed/pr7215.ocaml.reference +++ /dev/null @@ -1,7 +0,0 @@ -type (_, _) eq = Refl : ('a, 'a) eq -val cast : ('a, 'b) eq -> 'a -> 'b = -Characters 53-78: - let rec (p : (int, a) eq) = match p with Refl -> Refl in - ^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' - diff --git a/testsuite/tests/letrec-disallowed/pr7231.ml b/testsuite/tests/letrec-disallowed/pr7231.ml deleted file mode 100644 index 22234b3d..00000000 --- a/testsuite/tests/letrec-disallowed/pr7231.ml +++ /dev/null @@ -1,5 +0,0 @@ -(* TEST - * toplevel -*) - -let rec r = let rec x () = r and y () = x () in y () in r "oops";; diff --git a/testsuite/tests/letrec-disallowed/pr7231.ocaml.reference b/testsuite/tests/letrec-disallowed/pr7231.ocaml.reference deleted file mode 100644 index fb6be21e..00000000 --- a/testsuite/tests/letrec-disallowed/pr7231.ocaml.reference +++ /dev/null @@ -1,9 +0,0 @@ -Characters 84-90: - let rec r = let rec x () = r and y () = x () in y () in r "oops";; - ^^^^^^ -Warning 20: this argument will not be used by the function. -Characters 38-78: - let rec r = let rec x () = r and y () = x () in y () in r "oops";; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' - diff --git a/testsuite/tests/letrec-disallowed/pr7706.ocaml.reference b/testsuite/tests/letrec-disallowed/pr7706.ocaml.reference deleted file mode 100644 index e0bc36ea..00000000 --- a/testsuite/tests/letrec-disallowed/pr7706.ocaml.reference +++ /dev/null @@ -1,9 +0,0 @@ -Characters 39-104: - ..let y = if false then (fun z -> 1) else (fun z -> x 4 + 1) in - y.. -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 18-19: - let () = ignore (x 42);; - ^ -Error: Unbound value x - diff --git a/testsuite/tests/letrec-disallowed/unboxed.ml b/testsuite/tests/letrec-disallowed/unboxed.ml deleted file mode 100644 index eaab1c3b..00000000 --- a/testsuite/tests/letrec-disallowed/unboxed.ml +++ /dev/null @@ -1,29 +0,0 @@ -(* TEST - * toplevel -*) - -type t = {x: int64} [@@unboxed];; -let rec x = {x = y} and y = 3L;; - -type r = A of r [@@unboxed];; -let rec y = A y;; - -type a = {a: b }[@@unboxed] -and b = X of a | Y - -let rec a = - {a= - (if Sys.opaque_identity true then - X a - else - Y)};; - -type d = D of e [@@unboxed] -and e = V of d | W;; - -let rec d = - D - (if Sys.opaque_identity true then - V d - else - W);; diff --git a/testsuite/tests/letrec-disallowed/unboxed.ocaml.reference b/testsuite/tests/letrec-disallowed/unboxed.ocaml.reference deleted file mode 100644 index 41962dce..00000000 --- a/testsuite/tests/letrec-disallowed/unboxed.ocaml.reference +++ /dev/null @@ -1,27 +0,0 @@ -type t = { x : int64; } [@@unboxed] -Characters 12-19: - let rec x = {x = y} and y = 3L;; - ^^^^^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -type r = A of r [@@unboxed] -Characters 12-15: - let rec y = A y;; - ^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 77-150: - ..{a= - (if Sys.opaque_identity true then - X a - else - Y)}.. -Error: This kind of expression is not allowed as right-hand side of `let rec' -type d = D of e [@@unboxed] -and e = V of d | W -Characters 15-85: - ..D - (if Sys.opaque_identity true then - V d - else - W).. -Error: This kind of expression is not allowed as right-hand side of `let rec' - diff --git a/testsuite/tests/letrec/allowed.ml b/testsuite/tests/letrec/allowed.ml deleted file mode 100644 index 8c6910a7..00000000 --- a/testsuite/tests/letrec/allowed.ml +++ /dev/null @@ -1,108 +0,0 @@ -(* TEST -*) - -let rec x = (x; ());; - -let rec x = let x = () in x;; - -let rec x = [y] -and y = let x = () in x;; - -let rec x = [y] -and y = let rec x = () in x;; - -let rec x = - let a = x in - fun () -> a () -and y = - [x];; - -let rec x = let module M = struct let f = x end in ();; - -module type T = sig val y: int end - -let rec x = let module M = - struct - module N = - struct - let y = x - end - end - in fun () -> ignore (M.N.y ());; - -let rec x = "x";; - -class c = object end -let rec x = fun () -> new c;; - -let rec x = (y, y) -and y = fun () -> ignore x;; - -let rec x = Some y -and y = fun () -> ignore x -;; - -let rec x = `A y -and y = fun () -> ignore x -;; - -let rec x = { contents = y } -and y = fun () -> ignore x;; - -let r = ref (fun () -> ()) -let rec x = fun () -> r := x;; - -let rec x = fun () -> y.contents and y = { contents = 3 };; - -let rec x = function - Some _ -> ignore (y []) - | None -> ignore (y []) -and y = function - [] -> ignore (x None) - | _ :: _ -> ignore (x None) - ;; - -let rec x = lazy (Lazy.force x + Lazy.force x) - ;; - -let rec x = { x with contents = 3 } [@ocaml.warning "-23"];; - -let rec x = let y = (x; ()) in y;; - -let rec x = [|y|] and y = 0;; - -(* Recursively constructing arrays of known non-float type is permitted *) -let rec deep_cycle : [`Tuple of [`Shared of 'a] array] as 'a - = `Tuple [| `Shared deep_cycle |];; - -(* Constructing float arrays was disallowed altogether at one point - by an overzealous check. Constructing float arrays in recursive - bindings is fine when they don't partake in the recursion. *) -let rec _x = let _ = [| 1.0 |] in 1. in ();; - -(* This test is not allowed if 'a' is unboxed, but should be accepted - as written *) -type a = {a: b} -and b = X of a | Y - -let rec a = - {a= - (if Sys.opaque_identity true then - X a - else - Y)};; - -(* This test is not allowed if 'c' is unboxed, but should be accepted - as written *) -type d = D of e -and e = V of d | W;; - -let rec d = - D - (if Sys.opaque_identity true then - V d - else - W);; - -type r = R of r list [@@unboxed];; -let rec a = R [a];; diff --git a/testsuite/tests/letrec/ocamltests b/testsuite/tests/letrec/ocamltests deleted file mode 100644 index a92895e6..00000000 --- a/testsuite/tests/letrec/ocamltests +++ /dev/null @@ -1,19 +0,0 @@ -allowed.ml -backreferences.ml -class_1.ml -class_2.ml -evaluation_order_1.ml -evaluation_order_2.ml -evaluation_order_3.ml -float_block_1.ml -generic_array.ml -labels.ml -lazy_.ml -lists.ml -mixing_value_closures_1.ml -mixing_value_closures_2.ml -mutual_functions.ml -nested.ml -pr4989.ml -record_with.ml -ref.ml diff --git a/testsuite/tests/letrec/ref.ml b/testsuite/tests/letrec/ref.ml deleted file mode 100644 index 0f31b0a3..00000000 --- a/testsuite/tests/letrec/ref.ml +++ /dev/null @@ -1,14 +0,0 @@ -(* TEST *) - -(* Test construction of cyclic values where the cycles pass through references *) - -type t = { mutable next : t; mutable inst : n ref } -and n = T of t - -let rec d = { next = d; inst = ref (T d) } - -let f t1 t2 = - let rec self = ref init - and init () = t1 (function () -> self := t2; t2 ()) - in fun () -> !self () -;; diff --git a/testsuite/tests/lexing/escape.ml b/testsuite/tests/lexing/escape.ml new file mode 100644 index 00000000..bcb75313 --- /dev/null +++ b/testsuite/tests/lexing/escape.ml @@ -0,0 +1,11 @@ +(* TEST + * toplevel +*) + +(* Errors *) + +let invalid = "\99" ;; +let invalid = "\999" ;; +let invalid = "\o777" ;; +let invalid = "\o77" ;; +let invalid = "\o99" ;; diff --git a/testsuite/tests/lexing/escape.ocaml.reference b/testsuite/tests/lexing/escape.ocaml.reference new file mode 100644 index 00000000..2e9d9fd5 --- /dev/null +++ b/testsuite/tests/lexing/escape.ocaml.reference @@ -0,0 +1,24 @@ +Line 7, characters 15-17: +7 | let invalid = "\99" ;; + ^^ +Warning 14: illegal backslash escape in string. +val invalid : string = "\\99" +Line 1, characters 15-19: +1 | let invalid = "\999" ;; + ^^^^ +Error: Illegal backslash escape in string or character (\999): 999 is outside the range of legal characters (0-255). +Line 1, characters 15-20: +1 | let invalid = "\o777" ;; + ^^^^^ +Error: Illegal backslash escape in string or character (\o777): o777 (=511) is outside the range of legal characters (0-255). +Line 1, characters 15-17: +1 | let invalid = "\o77" ;; + ^^ +Warning 14: illegal backslash escape in string. +val invalid : string = "\\o77" +Line 1, characters 15-17: +1 | let invalid = "\o99" ;; + ^^ +Warning 14: illegal backslash escape in string. +val invalid : string = "\\o99" + diff --git a/testsuite/tests/lexing/ocamltests b/testsuite/tests/lexing/ocamltests index c08e182c..4b21c4a7 100644 --- a/testsuite/tests/lexing/ocamltests +++ b/testsuite/tests/lexing/ocamltests @@ -1 +1,2 @@ +escape.ml uchar_esc.ml diff --git a/testsuite/tests/lexing/uchar_esc.ocaml.reference b/testsuite/tests/lexing/uchar_esc.ocaml.reference index e29a1305..953104ae 100644 --- a/testsuite/tests/lexing/uchar_esc.ocaml.reference +++ b/testsuite/tests/lexing/uchar_esc.ocaml.reference @@ -1,35 +1,35 @@ -Characters 34-43: - let invalid_sv = "\u{0D800}" ;; - ^^^^^^^^^ -Error: Illegal backslash escape in string or character (\u{0D800}, D800 is not a Unicode scalar value) -Characters 18-26: - let invalid_sv = "\u{D800}" ;; - ^^^^^^^^ -Error: Illegal backslash escape in string or character (\u{D800}, D800 is not a Unicode scalar value) -Characters 18-26: - let invalid_sv = "\u{D900}" ;; - ^^^^^^^^ -Error: Illegal backslash escape in string or character (\u{D900}, D900 is not a Unicode scalar value) -Characters 18-26: - let invalid_sv = "\u{DFFF}" ;; - ^^^^^^^^ -Error: Illegal backslash escape in string or character (\u{DFFF}, DFFF is not a Unicode scalar value) -Characters 18-28: - let invalid_sv = "\u{110000} ;; - ^^^^^^^^^^ -Error: Illegal backslash escape in string or character (\u{110000}, 110000 is not a Unicode scalar value) -Characters 24-36: - let too_many_digits = "\u{01234567}" ;; - ^^^^^^^^^^^^ -Error: Illegal backslash escape in string or character (\u{01234567}, too many digits, expected 1 to 6 hexadecimal digits) -Characters 21-23: - let no_hex_digits = "\u{}" ;; - ^^ +Line 5, characters 18-27: +5 | let invalid_sv = "\u{0D800}" ;; + ^^^^^^^^^ +Error: Illegal backslash escape in string or character (\u{0D800}): D800 is not a Unicode scalar value +Line 1, characters 18-26: +1 | let invalid_sv = "\u{D800}" ;; + ^^^^^^^^ +Error: Illegal backslash escape in string or character (\u{D800}): D800 is not a Unicode scalar value +Line 1, characters 18-26: +1 | let invalid_sv = "\u{D900}" ;; + ^^^^^^^^ +Error: Illegal backslash escape in string or character (\u{D900}): D900 is not a Unicode scalar value +Line 1, characters 18-26: +1 | let invalid_sv = "\u{DFFF}" ;; + ^^^^^^^^ +Error: Illegal backslash escape in string or character (\u{DFFF}): DFFF is not a Unicode scalar value +Line 1, characters 18-28: +1 | let invalid_sv = "\u{110000} ;; + ^^^^^^^^^^ +Error: Illegal backslash escape in string or character (\u{110000}): 110000 is not a Unicode scalar value +Line 2, characters 23-35: +2 | let too_many_digits = "\u{01234567}" ;; + ^^^^^^^^^^^^ +Error: Illegal backslash escape in string or character (\u{01234567}): too many digits, expected 1 to 6 hexadecimal digits +Line 1, characters 21-23: +1 | let no_hex_digits = "\u{}" ;; + ^^ Warning 14: illegal backslash escape in string. val no_hex_digits : string = "\\u{}" -Characters 25-27: - let illegal_hex_digit = "\u{u}" ;; - ^^ +Line 1, characters 25-27: +1 | let illegal_hex_digit = "\u{u}" ;; + ^^ Warning 14: illegal backslash escape in string. val illegal_hex_digit : string = "\\u{u}" diff --git a/testsuite/tests/lib-arg/testarg.ml b/testsuite/tests/lib-arg/testarg.ml index 0241bc61..6458ce8d 100644 --- a/testsuite/tests/lib-arg/testarg.ml +++ b/testsuite/tests/lib-arg/testarg.ml @@ -195,7 +195,8 @@ let test_align () = let spec = [ "-foo", Arg.String ignore, "FOO Do foo with FOO"; - "-bar", Arg.Tuple [Arg.String ignore; Arg.String ignore], "FOO BAR\tDo bar with FOO and BAR"; + "-bar", Arg.Tuple [Arg.String ignore; Arg.String ignore], + "FOO BAR\tDo bar with FOO and BAR"; "-cha", Arg.Unit ignore, " Another option"; "-sym", Arg.Symbol (["a"; "b"], ignore), "\ty\tfoo"; "-sym2", Arg.Symbol (["a"; "b"], ignore), "x bar"; diff --git a/testsuite/tests/lib-arg/testerror.ml b/testsuite/tests/lib-arg/testerror.ml index 8786cfb6..94409452 100644 --- a/testsuite/tests/lib-arg/testerror.ml +++ b/testsuite/tests/lib-arg/testerror.ml @@ -24,7 +24,8 @@ let tests = [ ; [], ignore, ["-help" ] (** wrong argument type *) -; ["-int", Arg.Int ignore, "wrong argument type" ], ignore, ["-int"; "not_an_int" ] +; ["-int", Arg.Int ignore, "wrong argument type" ], ignore, + ["-int"; "not_an_int" ] (** unknown option *) ; [], ignore, [ "-an-unknown-option" ] @@ -37,6 +38,12 @@ let tests = [ Arg.Unit (fun () -> raise @@ Arg.Bad("User-raised error bis")), "user raised error"] , ignore, [ "-error" ] + +(* bad keyword in various places*) +; [ "-rest", Arg.Rest ignore, "help"], ignore, [ "-rest=1" ] +; [ "-tuple", Arg.Tuple [Arg.Int print_int; Arg.Int print_int ], "help" ] + , ignore, [ "-tuple=1" ] +; [ "-unit", Arg.Unit ignore, "" ], ignore, [ "-unit=1" ] ] let () = diff --git a/testsuite/tests/lib-arg/testerror.reference b/testsuite/tests/lib-arg/testerror.reference index 3608e11c..c061b32f 100644 --- a/testsuite/tests/lib-arg/testerror.reference +++ b/testsuite/tests/lib-arg/testerror.reference @@ -1,45 +1,65 @@ -(1/7) Bad: +(1/10) Bad: testerror: option '-s' needs an argument. Arg module testing -s missing arg -help Display this list of options --help Display this list of options -(2/7) Bad: +(2/10) Bad: testerror: wrong argument 'true'; option '-set=true' expects no argument. Arg module testing -set no argument expected -help Display this list of options --help Display this list of options -(3/7) Help: +(3/10) Help: Arg module testing -help Display this list of options --help Display this list of options -(4/7) Bad: +(4/10) Bad: testerror: wrong argument 'not_an_int'; option '-int' expects an integer. Arg module testing -int wrong argument type -help Display this list of options --help Display this list of options -(5/7) Bad: +(5/10) Bad: testerror: unknown option '-an-unknown-option'. Arg module testing -help Display this list of options --help Display this list of options -(6/7) Bad: +(6/10) Bad: testerror: User-raised error. Arg module testing -help Display this list of options --help Display this list of options -(7/7) Bad: +(7/10) Bad: testerror: User-raised error bis. Arg module testing -error user raised error -help Display this list of options --help Display this list of options +(8/10) Bad: +testerror: wrong argument '1'; option '-rest=1' expects no argument. +Arg module testing + -rest help + -help Display this list of options + --help Display this list of options + +(9/10) Bad: +testerror: wrong argument '1'; option '-tuple=1' expects no argument. +Arg module testing + -tuple help + -help Display this list of options + --help Display this list of options + +(10/10) Bad: +testerror: wrong argument '1'; option '-unit=1' expects no argument. +Arg module testing + -help Display this list of options + --help Display this list of options + diff --git a/testsuite/tests/lib-bigarray-2/Makefile b/testsuite/tests/lib-bigarray-2/Makefile deleted file mode 100644 index f36a3f00..00000000 --- a/testsuite/tests/lib-bigarray-2/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Clerc, SED, INRIA Rocquencourt * -#* * -#* Copyright 2010 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -BASEDIR=../.. -LIBRARIES=unix bigarray -C_FILES=bigarrfstub -F_FILES=bigarrf -ADD_COMPFLAGS=-I $(OTOPDIR)/otherlibs/bigarray \ - -I $(OTOPDIR)/otherlibs/$(UNIXLIB) - -include $(BASEDIR)/makefiles/Makefile.several -include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/lib-bigarray-2/bigarrfml.ml b/testsuite/tests/lib-bigarray-2/bigarrfml.ml index d33862ed..40020b23 100644 --- a/testsuite/tests/lib-bigarray-2/bigarrfml.ml +++ b/testsuite/tests/lib-bigarray-2/bigarrfml.ml @@ -1,3 +1,33 @@ +(* TEST + +files = "bigarrf.f bigarrfstub.c" +last_flags = "-cclib -lgfortran" + +* script +script = "sh ${test_source_directory}/has-gfortran.sh" + +** setup-ocamlc.byte-build-env +*** script +script = "gfortran -c bigarrf.f" +**** ocamlc.byte +all_modules = "bigarrf.o bigarrfstub.c bigarrfml.ml" +***** run +output = "${test_build_directory}/program-output" +stdout = "${output}" +****** check-program-output + +** setup-ocamlopt.byte-build-env +*** script +script = "gfortran -c bigarrf.f" +**** ocamlopt.byte +all_modules = "bigarrf.o bigarrfstub.c bigarrfml.ml" +***** run +output = "${test_build_directory}/program-output" +stdout = "${output}" +****** check-program-output + +*) + open Bigarray open Printf diff --git a/testsuite/tests/lib-bigarray-2/bigarrfstub.c b/testsuite/tests/lib-bigarray-2/bigarrfstub.c index efec26aa..1f9a2dce 100644 --- a/testsuite/tests/lib-bigarray-2/bigarrfstub.c +++ b/testsuite/tests/lib-bigarray-2/bigarrfstub.c @@ -15,7 +15,7 @@ #include #include -#include +#include extern void filltab_(void); extern void printtab_(float * data, int * dimx, int * dimy); diff --git a/testsuite/tests/lib-bigarray-2/has-gfortran.sh b/testsuite/tests/lib-bigarray-2/has-gfortran.sh new file mode 100644 index 00000000..82f7ae8a --- /dev/null +++ b/testsuite/tests/lib-bigarray-2/has-gfortran.sh @@ -0,0 +1,12 @@ +#!/bin/sh +if ! which gfortran > /dev/null 2>&1; then + echo "gfortran not available" > ${ocamltest_response} + test_result=${TEST_SKIP} +elif ! grep -q '^CC=gcc' ${ocamlsrcdir}/Makefile.config; then + echo "OCaml was not compiled with gcc" > ${ocamltest_response} + test_result=${TEST_SKIP} +else + test_result=${TEST_PASS} +fi + +exit ${test_result} diff --git a/testsuite/tests/lib-bigarray-2/ocamltests b/testsuite/tests/lib-bigarray-2/ocamltests new file mode 100644 index 00000000..133f99d6 --- /dev/null +++ b/testsuite/tests/lib-bigarray-2/ocamltests @@ -0,0 +1 @@ +bigarrfml.ml diff --git a/testsuite/tests/lib-bigarray-file/mapfile.ml b/testsuite/tests/lib-bigarray-file/mapfile.ml index bf4bc120..a28d5486 100644 --- a/testsuite/tests/lib-bigarray-file/mapfile.ml +++ b/testsuite/tests/lib-bigarray-file/mapfile.ml @@ -1,4 +1,5 @@ (* TEST + * hasunix include unix *) diff --git a/testsuite/tests/lib-bigarray/change_layout.ml b/testsuite/tests/lib-bigarray/change_layout.ml index 5e481065..fcc0d1fb 100644 --- a/testsuite/tests/lib-bigarray/change_layout.ml +++ b/testsuite/tests/lib-bigarray/change_layout.ml @@ -64,7 +64,8 @@ let testG n = Genarray.set gen pos (-1.); let different = Genarray.get gen pos <> initial in let gen' = Genarray.change_layout gen fortran in - Genarray.set gen' ( Array.init rank @@ fun n -> 1 + pos.( rank - 1 - n ) ) initial; + Genarray.set gen' ( Array.init rank @@ fun n -> 1 + pos.( rank - 1 - n ) ) + initial; if not (different && initial = Genarray.get gen pos) then Some pos else None diff --git a/testsuite/tests/lib-bool/ocamltests b/testsuite/tests/lib-bool/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/lib-bool/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/lib-bool/test.ml b/testsuite/tests/lib-bool/test.ml new file mode 100644 index 00000000..a59fd7c5 --- /dev/null +++ b/testsuite/tests/lib-bool/test.ml @@ -0,0 +1,86 @@ +(* TEST +*) + +let test_not () = + assert (Bool.not false = true); + assert (Bool.not true = false); + () + +let test_and () = + let wit = ref 0 in + assert (Bool.( && ) (incr wit; false) (incr wit; false) = false); + assert (!wit = 1); wit := 0; + assert (Bool.( && ) (incr wit; false) (incr wit; true) = false); + assert (!wit = 1); wit := 0; + assert (Bool.( && ) (incr wit; true) (incr wit; false) = false); + assert (!wit = 2); wit := 0; + assert (Bool.( && ) (incr wit; true) (incr wit; true) = true); + assert (!wit = 2); wit := 0; + () + +let test_or () = + let wit = ref 0 in + assert (Bool.( || ) (incr wit; false) (incr wit; false) = false); + assert (!wit = 2); wit := 0; + assert (Bool.( || ) (incr wit; false) (incr wit; true) = true); + assert (!wit = 2); wit := 0; + assert (Bool.( || ) (incr wit; true) (incr wit; false) = true); + assert (!wit = 1); wit := 0; + assert (Bool.( || ) (incr wit; true) (incr wit; true) = true); + assert (!wit = 1); wit := 0; + () + +let test_equal () = + assert (Bool.equal false false = true); + assert (Bool.equal false true = false); + assert (Bool.equal true false = false); + assert (Bool.equal true true = true); + () + +let test_compare () = + assert (Bool.compare false false = 0); + assert (Bool.compare false true = -1); + assert (Bool.compare true false = 1); + assert (Bool.compare true true = 0); + () + +let test_to_int () = + assert (Bool.to_int false = 0); + assert (Bool.to_int true = 1); + () + +let test_to_float () = + assert (Bool.to_float false = 0.); + assert (Bool.to_float true = 1.); + () + +let test_of_string () = + (* + assert (Bool.of_string "false" = Some false); + assert (Bool.of_string "true" = Some true); + assert (Bool.of_string "heyho" = None); + assert (Bool.of_string "1" = None); + assert (Bool.of_string "0" = None); +*) + () + +let test_to_string () = + assert (Bool.to_string false = "false"); + assert (Bool.to_string true = "true"); + () + +let tests () = + test_not (); + test_and (); + test_or (); + test_equal (); + test_compare (); + test_to_int (); + test_to_float (); + test_of_string (); + test_to_string (); + () + +let () = + tests (); + print_endline "OK" diff --git a/testsuite/tests/lib-bool/test.reference b/testsuite/tests/lib-bool/test.reference new file mode 100644 index 00000000..d86bac9d --- /dev/null +++ b/testsuite/tests/lib-bool/test.reference @@ -0,0 +1 @@ +OK diff --git a/testsuite/tests/lib-buffer/test.ml b/testsuite/tests/lib-buffer/test.ml index a63735df..7b1ab9a4 100644 --- a/testsuite/tests/lib-buffer/test.ml +++ b/testsuite/tests/lib-buffer/test.ml @@ -195,3 +195,64 @@ let add_utf_16le_uchar : unit = test_spec_map "add_utf_16le_uchar: test against spec" map Buffer.add_utf_16le_uchar ;; + + + + +let () = + let b = Buffer.create 64 in + Buffer.add_int8 b 0xff; + Buffer.add_int8 b 0x01; + Buffer.add_int16_be b 0x0123; + Buffer.add_int16_le b 0x0123; + Buffer.add_int32_be b 0x01234567l; + Buffer.add_int32_le b 0x01234567l; + Buffer.add_int64_be b 0x0123456789abcdefL; + Buffer.add_int64_le b 0x0123456789abcdefL; + assert (Buffer.contents b = + "\xff\x01" ^ + "\x01\x23\x23\x01" ^ + "\x01\x23\x45\x67" ^ + "\x67\x45\x23\x01" ^ + "\x01\x23\x45\x67\x89\xab\xcd\xef" ^ + "\xef\xcd\xab\x89\x67\x45\x23\x01" + ); + Buffer.clear b; + Buffer.add_int16_ne b 0x0123; + Buffer.add_int32_ne b 0x01234567l; + Buffer.add_int64_ne b 0x0123456789abcdefL; + let s = Buffer.contents b in + if Sys.big_endian then + assert (s = "\x01\x23\x01\x23\x45\x67\x01\x23\x45\x67\x89\xab\xcd\xef") + else + assert (s = "\x23\x01\x67\x45\x23\x01\xef\xcd\xab\x89\x67\x45\x23\x01"); + + for i = 1 to 20 do + let b = Buffer.create i in + for j = 1 to 100 do + Buffer.add_int8 b 1 + done; + assert(Buffer.length b = 100); + done; + for i = 1 to 20 do + let b = Buffer.create i in + for j = 1 to 100 do + Buffer.add_int16_ne b 1 + done; + assert(Buffer.length b = 200); + done; + for i = 1 to 20 do + let b = Buffer.create i in + for j = 1 to 100 do + Buffer.add_int32_ne b 1l + done; + assert(Buffer.length b = 400); + done; + for i = 1 to 20 do + let b = Buffer.create i in + for j = 1 to 100 do + Buffer.add_int64_ne b 1L + done; + assert(Buffer.length b = 800); + done +;; diff --git a/testsuite/tests/lib-bytes/binary.ml b/testsuite/tests/lib-bytes/binary.ml new file mode 100755 index 00000000..899cdfe0 --- /dev/null +++ b/testsuite/tests/lib-bytes/binary.ml @@ -0,0 +1,172 @@ +(* TEST +*) + +let err x = + match Lazy.force x with + | exception Invalid_argument _ -> () + | _ -> assert false + +let () = + let b = Bytes.make 5 (Char.chr 0) in + Bytes.set_int8 b 3 260; + Bytes.set_int8 b 2 1; + Bytes.set_int8 b 1 2; + Bytes.set_int8 b 0 3; + Bytes.set_int8 b 4 (-1); + assert (Bytes.to_string b = "\003\002\001\004\255"); + lazy (Bytes.set_int8 b 5 0) |> err; + lazy (Bytes.get_int8 b 5) |> err; + lazy (Bytes.set_uint8 b 5 0) |> err; + lazy (Bytes.get_uint8 b 5) |> err; + assert(Bytes.get_int8 b 0 = 3); + assert(Bytes.get_int8 b 1 = 2); + assert(Bytes.get_int8 b 2 = 1); + assert(Bytes.get_int8 b 3 = 4); + assert(Bytes.get_int8 b 4 = -1); + assert(Bytes.get_uint8 b 0 = 3); + assert(Bytes.get_uint8 b 1 = 2); + assert(Bytes.get_uint8 b 2 = 1); + assert(Bytes.get_uint8 b 3 = 4); + assert(Bytes.get_uint8 b 4 = 255); + for i = 0 to 255 do + Bytes.set_uint8 b 0 i; + assert (Bytes.get_uint8 b 0 = i); + done; + for i = -128 to 127 do + Bytes.set_int8 b 0 i; + assert (Bytes.get_int8 b 0 = i); + done + +let () = + let b = Bytes.make 3 (Char.chr 0) in + Bytes.set_int16_le b 1 0x1234; + Bytes.set_int16_le b 0 0xabcd; + assert (Bytes.to_string b = "\xcd\xab\x12"); + assert(Bytes.get_uint16_le b 0 = 0xabcd); + assert(Bytes.get_uint16_le b 1 = 0x12ab); + assert(Bytes.get_int16_le b 0 = 0xabcd - 0x10000); + assert(Bytes.get_int16_le b 1 = 0x12ab); + assert(Bytes.get_uint16_be b 1 = 0xab12); + assert(Bytes.get_int16_be b 1 = 0xab12 - 0x10000); + for i = 0 to Bytes.length b - 2 do + let x = Bytes.get_int16_ne b i in + let f = if Sys.big_endian then Bytes.get_int16_be else Bytes.get_int16_le in + assert (x = f b i); + + let x = Bytes.get_uint16_ne b i in + let f = if Sys.big_endian then Bytes.get_uint16_be else Bytes.get_uint16_le in + assert (x = f b i) + done; + lazy (Bytes.set_int16_le b 2 0) |> err; + lazy (Bytes.set_int16_ne b 2 0) |> err; + lazy (Bytes.set_int16_be b 2 0) |> err; + lazy (Bytes.get_int16_le b 2) |> err; + lazy (Bytes.get_int16_ne b 2) |> err; + lazy (Bytes.get_int16_be b 2) |> err; + lazy (Bytes.set_uint16_le b 2 0) |> err; + lazy (Bytes.set_uint16_ne b 2 0) |> err; + lazy (Bytes.set_uint16_be b 2 0) |> err; + lazy (Bytes.get_uint16_le b 2) |> err; + lazy (Bytes.get_uint16_ne b 2) |> err; + lazy (Bytes.get_uint16_be b 2) |> err; + for i = 0 to 0xffff do + Bytes.set_uint16_le b 0 i; + assert (Bytes.get_uint16_le b 0 = i); + Bytes.set_uint16_be b 0 i; + assert (Bytes.get_uint16_be b 0 = i); + Bytes.set_uint16_ne b 0 i; + assert (Bytes.get_uint16_ne b 0 = i); + assert ( + (if Sys.big_endian then Bytes.get_uint16_be else Bytes.get_uint16_le) + b 0 = i); + done; + for i = -0x8000 to 0x7fff do + Bytes.set_int16_le b 0 i; + assert (Bytes.get_int16_le b 0 = i); + Bytes.set_int16_be b 0 i; + assert (Bytes.get_int16_be b 0 = i); + Bytes.set_int16_ne b 0 i; + assert (Bytes.get_int16_ne b 0 = i); + assert ( + (if Sys.big_endian then Bytes.get_int16_be else Bytes.get_int16_le) + b 0 = i); + done + +let () = + let b = Bytes.make 6 (Char.chr 0) in + Bytes.set_int32_le b 1 0x01234567l; + Bytes.set_int32_le b 0 0x89abcdefl; + assert (Bytes.to_string b = "\xef\xcd\xab\x89\x01\x00"); + assert (Bytes.get_int32_le b 0 = 0x89abcdefl); + assert (Bytes.get_int32_be b 0 = 0xefcdab89l); + assert (Bytes.get_int32_le b 1 = 0x0189abcdl); + assert (Bytes.get_int32_be b 1 = 0xcdab8901l); + + Bytes.set_int32_be b 1 0x01234567l; + Bytes.set_int32_be b 0 0x89abcdefl; + assert (Bytes.to_string b = "\x89\xab\xcd\xef\x67\x00"); + + Bytes.set_int32_ne b 0 0x01234567l; + assert(Bytes.get_int32_ne b 0 = 0x01234567l); + if Sys.big_endian then + assert (Bytes.to_string b = "\x01\x23\x45\x67\x67\x00") + else + assert (Bytes.to_string b = "\x67\x45\x23\x01\x67\x00"); + Bytes.set_int32_ne b 0 0xffffffffl; + assert(Bytes.get_int32_ne b 0 = 0xffffffffl); + + + for i = 0 to Bytes.length b - 4 do + let x = Bytes.get_int32_ne b i in + let f = + if Sys.big_endian then Bytes.get_int32_be else Bytes.get_int32_le + in + assert (x = f b i); + done; + lazy (Bytes.set_int32_le b 3 0l) |> err; + lazy (Bytes.set_int32_ne b 3 0l) |> err; + lazy (Bytes.set_int32_be b 3 0l) |> err; + lazy (Bytes.get_int32_le b 3) |> err; + lazy (Bytes.get_int32_ne b 3) |> err; + lazy (Bytes.get_int32_be b 3) |> err; + () + + +let () = + let b = Bytes.make 10 (Char.chr 0) in + Bytes.set_int64_le b 1 0x0123456789abcdefL; + Bytes.set_int64_le b 0 0x1032547698badcfeL; + assert (Bytes.to_string b = "\xfe\xdc\xba\x98\x76\x54\x32\x10\x01\x00"); + assert (Bytes.get_int64_le b 0 = 0x1032547698badcfeL); + assert (Bytes.get_int64_be b 0 = 0xfedcba9876543210L); + assert (Bytes.get_int64_le b 1 = 0x011032547698badcL); + assert (Bytes.get_int64_be b 1 = 0xdcba987654321001L); + + Bytes.set_int64_be b 1 0x0123456789abcdefL; + Bytes.set_int64_be b 0 0x1032547698badcfeL; + assert (Bytes.to_string b = "\x10\x32\x54\x76\x98\xba\xdc\xfe\xef\x00"); + + Bytes.set_int64_ne b 0 0x0123456789abcdefL; + assert(Bytes.get_int64_ne b 0 = 0x0123456789abcdefL); + if Sys.big_endian then + assert (Bytes.to_string b = "\x01\x23\x45\x67\x89\xab\xcd\xef\xef\x00") + else + assert (Bytes.to_string b = "\xef\xcd\xab\x89\x67\x45\x23\x01\xef\x00"); + Bytes.set_int64_ne b 0 0xffffffffffffffffL; + assert(Bytes.get_int64_ne b 0 = 0xffffffffffffffffL); + + for i = 0 to Bytes.length b - 8 do + let x = Bytes.get_int64_ne b i in + let f = + if Sys.big_endian then Bytes.get_int64_be else Bytes.get_int64_le + in + assert (x = f b i); + done; + + lazy (Bytes.set_int64_le b 3 0L) |> err; + lazy (Bytes.set_int64_ne b 3 0L) |> err; + lazy (Bytes.set_int64_be b 3 0L) |> err; + lazy (Bytes.get_int64_le b 3) |> err; + lazy (Bytes.get_int64_ne b 3) |> err; + lazy (Bytes.get_int64_be b 3) |> err; + () diff --git a/testsuite/tests/lib-bytes/ocamltests b/testsuite/tests/lib-bytes/ocamltests index a139cdac..5f976f97 100644 --- a/testsuite/tests/lib-bytes/ocamltests +++ b/testsuite/tests/lib-bytes/ocamltests @@ -1 +1,2 @@ +binary.ml test_bytes.ml diff --git a/testsuite/tests/lib-bytes/test_bytes.ml b/testsuite/tests/lib-bytes/test_bytes.ml index 2e1d9b6a..33a285d8 100644 --- a/testsuite/tests/lib-bytes/test_bytes.ml +++ b/testsuite/tests/lib-bytes/test_bytes.ml @@ -4,8 +4,8 @@ let test_raises_invalid_argument f x = ignore - (Testing.test_raises_exc_p (function Invalid_argument _ -> true | _ -> false) - f x) + (Testing.test_raises_exc_p + (function Invalid_argument _ -> true | _ -> false) f x) let check b offset s = let rec loop i = diff --git a/testsuite/tests/lib-digest/md5.ml b/testsuite/tests/lib-digest/md5.ml index edfe85c4..4c686df6 100644 --- a/testsuite/tests/lib-digest/md5.ml +++ b/testsuite/tests/lib-digest/md5.ml @@ -134,10 +134,14 @@ let string_to_data s = data let int32_to_string n s i = - Bytes.set s (i+3) (Char.chr (Int32.to_int (Int32.shift_right n 24) land 0xFF)); - Bytes.set s (i+2) (Char.chr (Int32.to_int (Int32.shift_right n 16) land 0xFF)); - Bytes.set s (i+1) (Char.chr (Int32.to_int (Int32.shift_right n 8) land 0xFF)); - Bytes.set s i (Char.chr (Int32.to_int n land 0xFF)) + Bytes.set s (i+3) + (Char.chr (Int32.to_int (Int32.shift_right n 24) land 0xFF)); + Bytes.set s (i+2) + (Char.chr (Int32.to_int (Int32.shift_right n 16) land 0xFF)); + Bytes.set s (i+1) + (Char.chr (Int32.to_int (Int32.shift_right n 8) land 0xFF)); + Bytes.set s i + (Char.chr (Int32.to_int n land 0xFF)) let init () = { buf = Bytes.create 64; diff --git a/testsuite/tests/lib-dynlink-bytecode/Makefile b/testsuite/tests/lib-dynlink-bytecode/Makefile deleted file mode 100644 index 1e56b168..00000000 --- a/testsuite/tests/lib-dynlink-bytecode/Makefile +++ /dev/null @@ -1,73 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Clerc, SED, INRIA Rocquencourt * -#* * -#* Copyright 2010 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -BASEDIR=../.. - -COMPFLAGS=-I $(OTOPDIR)/otherlibs/dynlink -LD_PATH=.:$(TOPDIR)/otherlibs/dynlink - -.PHONY: default -default: - @if ! $(SUPPORTS_SHARED_LIBRARIES); then \ - echo 'skipped (shared libraries not available)'; \ - else \ - $(SET_LD_PATH) $(MAKE) compile run; \ - fi - -.PHONY: compile -compile: - @$(OCAMLC) -c registry.ml - @for file in stub*.c; do \ - $(OCAMLC) -ccopt -I -ccopt $(CTOPDIR)/byterun -c $$file; \ - $(OCAMLMKLIB) -o `echo $$file | sed -e 's/stub/plug/' -e 's/\.c//'` \ - `basename $$file c`$(O); \ - done - @for file in plug*.ml; do \ - $(OCAMLC) -c $$file; \ - $(OCAMLMKLIB) -o `basename $$file .ml` `basename $$file ml`cmo; \ - done - @$(OCAMLC) -c main.ml - @rm -f main static custom custom.exe - @$(OCAMLC) -o main dynlink.cma registry.cmo main.cmo - @$(OCAMLC) -o static -linkall registry.cmo plug1.cma plug2.cma \ - -use-runtime $(OTOPDIR)/byterun/ocamlrun$(USE_RUNTIME)$(EXE) - @$(OCAMLC) -o custom$(EXE) -custom -linkall registry.cmo plug2.cma \ - plug1.cma -I . - -.PHONY: run -run: - @printf " ... testing 'main'" - @$(OCAMLRUN) ./main plug1.cma plug2.cma >main.result - @$(DIFF) main.reference main.result >/dev/null \ - && echo " => passed" || echo " => failed" - - @printf " ... testing 'static'" - @$(OCAMLRUN) ./static >static.result - @$(DIFF) static.reference static.result >/dev/null \ - && echo " => passed" || echo " => failed" - - @printf " ... testing 'custom'" - @./custom$(EXE) >custom.result - @$(DIFF) custom.reference custom.result >/dev/null \ - && echo " => passed" || echo " => failed" - -.PHONY: promote -promote: defaultpromote - -.PHONY: clean -clean: defaultclean - @rm -f main static custom custom.exe *.result marshal.data dllplug*.dll - -include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/lib-dynlink-bytecode/main.ml b/testsuite/tests/lib-dynlink-bytecode/main.ml index 725ee80c..558dc69a 100644 --- a/testsuite/tests/lib-dynlink-bytecode/main.ml +++ b/testsuite/tests/lib-dynlink-bytecode/main.ml @@ -1,9 +1,65 @@ +(* TEST + +include dynlink + +ld_library_path += "${test_build_directory}" + +files = "plug1.ml plug2.ml registry.ml stub1.c stub2.c" + +* shared-libraries +** setup-ocamlc.byte-build-env +*** ocamlc.byte +compile_only = "true" +all_modules = "registry.ml stub1.c stub2.c plug1.ml plug2.ml main.ml" +**** ocamlmklib +program = "plug1" +modules = "stub1.${objext}" +***** ocamlmklib +program = "plug2" +modules = "stub2.${objext}" +****** ocamlmklib +program = "plug1" +modules = "plug1.cmo" +******* ocamlmklib +program = "plug2" +modules = "plug2.cmo" + +compile_only = "false" + +******** ocamlc.byte +program = "${test_build_directory}/main.exe" +all_modules = "registry.cmo main.cmo" +********* run +arguments = "plug1.cma plug2.cma" +output = "main.output" +********** check-program-output + +******** ocamlc.byte +program = "${test_build_directory}/static.exe" +flags = "-linkall" +all_modules = "registry.cmo plug1.cma plug2.cma" +********* run +output = "static.output" +********** check-program-output +reference = "${test_source_directory}/static.reference" + +******** ocamlc.byte +program = "${test_build_directory}/custom.exe" +flags = "-custom -linkall -I ." +all_modules = "registry.cmo plug2.cma plug1.cma" +use_runtime = "false" +********* run +output = "custom.output" +********** check-program-output +reference = "${test_source_directory}/custom.reference" + +*) + let f x = print_string "This is Main.f\n"; x let () = Registry.register f let _ = - Dynlink.init (); Dynlink.allow_unsafe_modules true; for i = 1 to Array.length Sys.argv - 1 do let name = Sys.argv.(i) in diff --git a/testsuite/tests/lib-dynlink-bytecode/ocamltests b/testsuite/tests/lib-dynlink-bytecode/ocamltests new file mode 100644 index 00000000..d389d156 --- /dev/null +++ b/testsuite/tests/lib-dynlink-bytecode/ocamltests @@ -0,0 +1 @@ +main.ml diff --git a/testsuite/tests/lib-dynlink-csharp/Makefile b/testsuite/tests/lib-dynlink-csharp/Makefile deleted file mode 100644 index a385d1ca..00000000 --- a/testsuite/tests/lib-dynlink-csharp/Makefile +++ /dev/null @@ -1,122 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Clerc, SED, INRIA Rocquencourt * -#* * -#* Copyright 2010 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -BASEDIR=../.. -# Only run this test for TOOLCHAIN=msvc -CSC_COMMAND=$(filter csc,$(subst msvc,csc,$(TOOLCHAIN))) -CSC=$(CSC_COMMAND) $(CSC_FLAGS) - -COMPFLAGS=-I $(OTOPDIR)/otherlibs/bigarray -I $(OTOPDIR)/otherlibs/dynlink \ - -I $(OTOPDIR)/byterun -LD_PATH=$(TOPDIR)/otherlibs/win32unix:$(TOPDIR)/otherlibs/bigarray:$(TOPDIR)/otherlibs/dynlink - -default: - @$(SET_LD_PATH) $(MAKE) all - -.PHONY: all -all: prepare bytecode bytecode-dll native native-dll - -.PHONY: prepare -prepare: - @if $(SUPPORTS_SHARED_LIBRARIES); then \ - $(OCAMLC) -c plugin.ml && \ - if $(BYTECODE_ONLY) ; then : ; else \ - $(OCAMLOPT) -o plugin.cmxs -shared plugin.ml; \ - fi; \ - fi - -.PHONY: bytecode -bytecode: - @printf " ... testing 'bytecode':" - @if ! $(SUPPORTS_SHARED_LIBRARIES) || ! which $(CSC_COMMAND) >/dev/null 2>&1; \ - then \ - echo " => skipped"; \ - else \ - rm -f main.exe main.dll; \ - $(OCAMLC) -output-obj -o main.dll dynlink.cma main.ml entry.c; \ - $(CSC) /nologo /nowarn:1668 /out:main.exe main.cs; \ - ./main.exe > bytecode.result; \ - $(DIFF) bytecode.reference bytecode.result >/dev/null \ - && echo " => passed" || echo " => failed"; \ - fi - -.PHONY: bytecode-dll -bytecode-dll: - @printf " ... testing 'bytecode-dll':" - @if ! $(SUPPORTS_SHARED_LIBRARIES) || ! which $(CSC_COMMAND) > /dev/null 2>&1; \ - then \ - echo " => skipped"; \ - else \ - rm -f main.exe main_obj.$(O) main.dll; \ - $(OCAMLC) -output-obj -o main_obj.$(O) dynlink.cma entry.c main.ml; \ - $(MKDLL) -maindll -o main.dll main_obj.$(O) entry.$(O) \ - $(CTOPDIR)/byterun/libcamlrun.$(A) $(BYTECCLIBS); \ - $(CSC) /nologo /nowarn:1668 /out:main.exe main.cs; \ - ./main.exe >bytecode-dll.result; \ - $(DIFF) bytecode.reference bytecode-dll.result >/dev/null \ - && echo " => passed" || echo " => failed"; \ - fi - -.PHONY: native -native: - @printf " ... testing 'native':" - @if ! $(SUPPORTS_SHARED_LIBRARIES) || $(BYTECODE_ONLY) \ - || ! which $(CSC_COMMAND) > /dev/null 2>&1; then \ - echo " => skipped"; \ - else \ - rm -f main.exe main.dll; \ - $(OCAMLOPT) -output-obj -o main.dll dynlink.cmxa entry.c main.ml; \ - $(CSC) /nologo /nowarn:1668 /out:main.exe main.cs; \ - ./main.exe > native.result; \ - $(DIFF) native.reference native.result > /dev/null \ - && echo " => passed" || echo " => failed"; \ - fi - -.PHONY: native-dll -native-dll: - @printf " ... testing 'native-dll':" - @if ! $(SUPPORTS_SHARED_LIBRARIES) || $(BYTECODE_ONLY) \ - || ! which $(CSC_COMMAND) > /dev/null 2>&1; then \ - echo " => skipped"; \ - else \ - rm -f main.exe main_obj.$(O) main.dll; \ - $(OCAMLOPT) -output-obj -o main_obj.$(O) dynlink.cmxa entry.c \ - main.ml; \ - $(MKDLL) -maindll -o main.dll main_obj.$(O) entry.$(O) \ - $(CTOPDIR)/asmrun/libasmrun.lib $(NATIVECCLIBS); \ - $(CSC) /nologo /nowarn:1668 /out:main.exe main.cs; \ - ./main.exe > native-dll.result; \ - $(DIFF) native.reference native-dll.result >/dev/null \ - && echo " => passed" || echo " => failed"; \ - fi - -.PHONY: promote -promote: defaultpromote - -.PHONY: clean -clean: defaultclean - @rm -f *.result *.exe *.dll *.so *.obj *.o - -include $(BASEDIR)/makefiles/Makefile.common - -ifneq ($(FLEXLINK_PREFIX),) -MKDLL=$(WINTOPDIR)/boot/ocamlrun $(WINTOPDIR)/flexdll/flexlink.exe $(FLEXLINK_FLAGS) -endif - -ifeq ($(HOST),msvc) -CSC_FLAGS=/platform:x86 -else -CSC_FLAGS= -endif diff --git a/testsuite/tests/lib-dynlink-csharp/bytecode.reference b/testsuite/tests/lib-dynlink-csharp/bytecode.reference deleted file mode 100644 index 1c61c156..00000000 --- a/testsuite/tests/lib-dynlink-csharp/bytecode.reference +++ /dev/null @@ -1,7 +0,0 @@ -Now starting the OCaml engine. -Main is running. -Loading ../../../otherlibs/win32unix/unix.cma -Loading ../../../otherlibs/bigarray/bigarray.cma -Loading plugin.cmo -I'm the plugin. -OK. diff --git a/testsuite/tests/lib-dynlink-csharp/entry.c b/testsuite/tests/lib-dynlink-csharp/entry.c old mode 100755 new mode 100644 diff --git a/testsuite/tests/lib-dynlink-csharp/main.bytecode.reference b/testsuite/tests/lib-dynlink-csharp/main.bytecode.reference new file mode 100644 index 00000000..c162cac0 --- /dev/null +++ b/testsuite/tests/lib-dynlink-csharp/main.bytecode.reference @@ -0,0 +1,5 @@ +Now starting the OCaml engine. +Main is running. +Loading plugin.cmo +I'm the plugin. +OK. diff --git a/testsuite/tests/lib-dynlink-csharp/main.cs b/testsuite/tests/lib-dynlink-csharp/main.cs old mode 100755 new mode 100644 diff --git a/testsuite/tests/lib-dynlink-csharp/main.ml b/testsuite/tests/lib-dynlink-csharp/main.ml old mode 100755 new mode 100644 index 93fe830c..35f0ca4c --- a/testsuite/tests/lib-dynlink-csharp/main.ml +++ b/testsuite/tests/lib-dynlink-csharp/main.ml @@ -1,3 +1,85 @@ +(* TEST + +include dynlink + +files = "entry.c main.cs plugin.ml" + +* csharp-compiler +** shared-libraries +set csharp_cmd = "${csc} ${csc_flags} /out:main.exe main.cs" + +*** setup-ocamlc.byte-build-env +**** ocamlc.byte +module = "plugin.ml" +***** ocamlc.byte +module = "" +flags = "-output-obj" +program = "main.dll" +all_modules = "dynlink.cma main.ml entry.c" +****** script +script = "${csharp_cmd}" +******* run +program = "./main.exe" +******** check-program-output +reference = "${test_source_directory}/main.bytecode.reference" + +*** setup-ocamlc.byte-build-env +compiler_directory_suffix = "-dll" +**** ocamlc.byte +module = "plugin.ml" +***** ocamlc.byte +module = "" +flags = "-output-obj" +program = "main_obj.${objext}" +all_modules = "dynlink.cma entry.c main.ml" +****** script +script = "${mkdll} -maindll -o main.dll main_obj.${objext} entry.${objext} \ + ${ocamlsrcdir}/runtime/libcamlrun.lib ${bytecc_libs}" +******* script +script = "${csharp_cmd}" +******** run +program = "./main.exe" +********* check-program-output +reference = "${test_source_directory}/main.bytecode.reference" + +*** setup-ocamlopt.byte-build-env +**** ocamlopt.byte +program = "plugin.cmxs" +flags = "-shared" +all_modules = "plugin.ml" +***** ocamlopt.byte +flags = "-output-obj" +program= "main.dll" +all_modules = "dynlink.cmxa entry.c main.ml" +****** script +script = "${csharp_cmd}" +******* run +program = "./main.exe" +******** check-program-output +reference = "${test_source_directory}/main.native.reference" + +*** setup-ocamlopt.byte-build-env +compiler_directory_suffix = "-dll" +**** ocamlopt.byte +program = "plugin.cmxs" +flags = "-shared" +all_modules = "plugin.ml" +***** ocamlopt.byte +flags = "-output-obj" +program = "main_obj.${objext}" +all_modules = "dynlink.cmxa entry.c main.ml" +****** script +script = "${mkdll} -maindll -o main.dll main_obj.${objext} entry.${objext} \ + ${ocamlsrcdir}/runtime/libasmrun.lib ${nativecc_libs}" +******* script +script = "${csharp_cmd}" +******** run +program = "./main.exe" +********* check-program-output +reference = "${test_source_directory}/main.native.reference" + +*) + let load s = Printf.printf "Loading %s\n%!" s; try @@ -12,14 +94,7 @@ let _ = Stdlib.Bigarray.float32 let () = ignore (Hashtbl.hash 42.0); print_endline "Main is running."; - Dynlink.init (); Dynlink.allow_unsafe_modules true; - let s1,s2,s3 = - Dynlink.adapt_filename "../../../otherlibs/win32unix/unix.cma", - Dynlink.adapt_filename "../../../otherlibs/bigarray/bigarray.cma", - Dynlink.adapt_filename "plugin.cmo" - in - load s1; - load s2; - load s3; + let plugin_name = Dynlink.adapt_filename "plugin.cmo" in + load plugin_name; print_endline "OK." diff --git a/testsuite/tests/lib-dynlink-csharp/main.native.reference b/testsuite/tests/lib-dynlink-csharp/main.native.reference new file mode 100644 index 00000000..a26525ee --- /dev/null +++ b/testsuite/tests/lib-dynlink-csharp/main.native.reference @@ -0,0 +1,5 @@ +Now starting the OCaml engine. +Main is running. +Loading plugin.cmxs +I'm the plugin. +OK. diff --git a/testsuite/tests/lib-dynlink-csharp/native.reference b/testsuite/tests/lib-dynlink-csharp/native.reference deleted file mode 100644 index cfb612da..00000000 --- a/testsuite/tests/lib-dynlink-csharp/native.reference +++ /dev/null @@ -1,7 +0,0 @@ -Now starting the OCaml engine. -Main is running. -Loading ../../../otherlibs/win32unix/unix.cmxs -Loading ../../../otherlibs/bigarray/bigarray.cmxs -Loading plugin.cmxs -I'm the plugin. -OK. diff --git a/testsuite/tests/lib-dynlink-csharp/ocamltests b/testsuite/tests/lib-dynlink-csharp/ocamltests new file mode 100644 index 00000000..d389d156 --- /dev/null +++ b/testsuite/tests/lib-dynlink-csharp/ocamltests @@ -0,0 +1 @@ +main.ml diff --git a/testsuite/tests/lib-dynlink-csharp/plugin.ml b/testsuite/tests/lib-dynlink-csharp/plugin.ml old mode 100755 new mode 100644 diff --git a/testsuite/tests/lib-dynlink-initializers/ocamltests b/testsuite/tests/lib-dynlink-initializers/ocamltests new file mode 100644 index 00000000..548f6b3c --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/ocamltests @@ -0,0 +1,9 @@ +test1_main.ml +test2_main.ml +test3_main.ml +test4_main.ml +test5_main.ml +test6_main.ml +test7_main.ml +test8_main.ml +test9_main.ml diff --git a/testsuite/tests/lib-dynlink-initializers/test1_inited_second.ml b/testsuite/tests/lib-dynlink-initializers/test1_inited_second.ml new file mode 100644 index 00000000..bbee32a7 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test1_inited_second.ml @@ -0,0 +1 @@ +let g x = Test1_main.f x diff --git a/testsuite/tests/lib-dynlink-initializers/test1_main.ml b/testsuite/tests/lib-dynlink-initializers/test1_main.ml new file mode 100644 index 00000000..69725e91 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test1_main.ml @@ -0,0 +1,57 @@ +(* TEST + +include dynlink + +files = "test1_inited_second.ml test1_plugin.ml" + +libraries = "" + +* shared-libraries +** setup-ocamlc.byte-build-env +*** ocamlc.byte +module = "test1_main.ml" +*** ocamlc.byte +module = "test1_inited_second.ml" +*** ocamlc.byte +module = "test1_plugin.ml" +*** ocamlc.byte +program = "${test_build_directory}/test1.byte" +libraries = "dynlink" +all_modules = "test1_main.cmo test1_inited_second.cmo" +**** run + +** native-dynlink +*** setup-ocamlopt.byte-build-env +**** ocamlopt.byte +module = "test1_main.ml" +**** ocamlopt.byte +module = "test1_inited_second.ml" +**** ocamlopt.byte +program = "test1_plugin.cmxs" +flags = "-shared" +all_modules = "test1_plugin.ml" +**** ocamlopt.byte +program = "${test_build_directory}/test1.exe" +libraries = "dynlink" +all_modules = "test1_main.cmx test1_inited_second.cmx" +***** run +*) + +(* Check that a module in the main program whose initializer has not + executed completely cannot be depended upon by a shared library being + loaded. *) + +let f x = x + 1 [@@inline never] + +let () = + try + if Dynlink.is_native then begin + Dynlink.loadfile "test1_plugin.cmxs" + end else begin + Dynlink.loadfile "test1_plugin.cmo" + end; + assert false + with + | Dynlink.Error ( + Dynlink.Linking_error (_, + Dynlink.Uninitialized_global "Test1_inited_second")) -> () diff --git a/testsuite/tests/lib-dynlink-initializers/test1_plugin.ml b/testsuite/tests/lib-dynlink-initializers/test1_plugin.ml new file mode 100644 index 00000000..6df90f17 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test1_plugin.ml @@ -0,0 +1,2 @@ +let () = + print_int ((Test1_inited_second.g [@inlined never]) 42) diff --git a/testsuite/tests/lib-dynlink-initializers/test2_inited_first.ml b/testsuite/tests/lib-dynlink-initializers/test2_inited_first.ml new file mode 100644 index 00000000..1c235048 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test2_inited_first.ml @@ -0,0 +1 @@ +let f x = x + 1 [@@inline never] diff --git a/testsuite/tests/lib-dynlink-initializers/test2_main.ml b/testsuite/tests/lib-dynlink-initializers/test2_main.ml new file mode 100644 index 00000000..06bf8d91 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test2_main.ml @@ -0,0 +1,50 @@ +(* TEST + +include dynlink + +files = "test2_inited_first.ml test2_plugin.ml" + +libraries = "" + +* shared-libraries +** setup-ocamlc.byte-build-env +*** ocamlc.byte +module = "test2_inited_first.ml" +*** ocamlc.byte +module = "test2_main.ml" +*** ocamlc.byte +module = "test2_plugin.ml" +*** ocamlc.byte +program = "${test_build_directory}/test2.byte" +libraries = "dynlink" +all_modules = "test2_inited_first.cmo test2_main.cmo" +**** run + +** native-dynlink +*** setup-ocamlopt.byte-build-env +**** ocamlopt.byte +module = "test2_inited_first.ml" +**** ocamlopt.byte +module = "test2_main.ml" +**** ocamlopt.byte +program = "test2_plugin.cmxs" +flags = "-shared" +all_modules = "test2_plugin.ml" +**** ocamlopt.byte +program = "${test_build_directory}/test2.exe" +libraries = "dynlink" +all_modules = "test2_inited_first.cmx test2_main.cmx" +***** run +*) + +(* Check that a shared library can refer to a module in the main program + as long as that module has already been loaded. *) + +let g x = Test2_inited_first.f x + +let () = + if Dynlink.is_native then begin + Dynlink.loadfile "test2_plugin.cmxs" + end else begin + Dynlink.loadfile "test2_plugin.cmo" + end diff --git a/testsuite/tests/lib-dynlink-initializers/test2_plugin.ml b/testsuite/tests/lib-dynlink-initializers/test2_plugin.ml new file mode 100644 index 00000000..696cc168 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test2_plugin.ml @@ -0,0 +1,2 @@ +let () = + print_int (Test2_inited_first.f 42) diff --git a/testsuite/tests/lib-dynlink-initializers/test3_main.ml b/testsuite/tests/lib-dynlink-initializers/test3_main.ml new file mode 100644 index 00000000..2de898cc --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test3_main.ml @@ -0,0 +1,55 @@ +(* TEST + +include dynlink + +files = "test3_plugin_a.ml test3_plugin_b.ml" + +libraries = "" + +* shared-libraries +** setup-ocamlc.byte-build-env +*** ocamlc.byte +module = "test3_main.ml" +*** ocamlc.byte +module = "test3_plugin_a.ml" +*** ocamlc.byte +module = "test3_plugin_b.ml" +*** ocamlc.byte +program = "test3_plugin.cma" +flags = "-a" +all_modules = "test3_plugin_a.cmo test3_plugin_b.cmo" +*** ocamlc.byte +program = "${test_build_directory}/test3.byte" +libraries = "dynlink" +all_modules = "test3_main.cmo" +**** run + +** native-dynlink +*** setup-ocamlopt.byte-build-env +**** ocamlopt.byte +module = "test3_main.ml" +**** ocamlopt.byte +module = "test3_plugin_a.ml" +**** ocamlopt.byte +module = "test3_plugin_b.ml" +**** ocamlopt.byte +program = "test3_plugin.cmxs" +flags = "-shared" +all_modules = "test3_plugin_a.cmx test3_plugin_b.cmx" +**** ocamlopt.byte +program = "${test_build_directory}/test3.exe" +libraries = "dynlink" +all_modules = "test3_main.cmx" +***** run +*) + +(* Check that one module in a shared library can refer to another module + in the same shared library as long as the second module has already + been loaded. *) + +let () = + if Dynlink.is_native then begin + Dynlink.loadfile "test3_plugin.cmxs" + end else begin + Dynlink.loadfile "test3_plugin.cma" + end diff --git a/testsuite/tests/lib-dynlink-initializers/test3_plugin_a.ml b/testsuite/tests/lib-dynlink-initializers/test3_plugin_a.ml new file mode 100644 index 00000000..2f1eb893 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test3_plugin_a.ml @@ -0,0 +1 @@ +let f x = x + 3 [@@inline never] diff --git a/testsuite/tests/lib-dynlink-initializers/test3_plugin_b.ml b/testsuite/tests/lib-dynlink-initializers/test3_plugin_b.ml new file mode 100644 index 00000000..07d83fb9 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test3_plugin_b.ml @@ -0,0 +1,2 @@ +let () = + print_int (Test3_plugin_a.f 42) diff --git a/testsuite/tests/lib-dynlink-initializers/test4_main.ml b/testsuite/tests/lib-dynlink-initializers/test4_main.ml new file mode 100644 index 00000000..e3b369b7 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test4_main.ml @@ -0,0 +1,60 @@ +(* TEST + +include dynlink + +files = "test4_plugin_a.ml test4_plugin_b.ml" + +libraries = "" + +* shared-libraries +** setup-ocamlc.byte-build-env +*** ocamlc.byte +module = "test4_main.ml" +*** ocamlc.byte +module = "test4_plugin_b.ml" +*** ocamlc.byte +module = "test4_plugin_a.ml" +*** ocamlc.byte +program = "test4_plugin.cma" +flags = "-a" +all_modules = "test4_plugin_a.cmo test4_plugin_b.cmo" +*** ocamlc.byte +program = "${test_build_directory}/test4.byte" +libraries = "dynlink" +all_modules = "test4_main.cmo" +**** run + +** native-dynlink +*** setup-ocamlopt.byte-build-env +**** ocamlopt.byte +module = "test4_main.ml" +**** ocamlopt.byte +module = "test4_plugin_b.ml" +**** ocamlopt.byte +module = "test4_plugin_a.ml" +**** ocamlopt.byte +program = "test4_plugin.cmxs" +flags = "-shared" +all_modules = "test4_plugin_a.cmx test4_plugin_b.cmx" +**** ocamlopt.byte +program = "${test_build_directory}/test4.exe" +libraries = "dynlink" +all_modules = "test4_main.cmx" +***** run +*) + +(* Check that a module in a shared library cannot refer to another + module in the same shared library if it has not yet been loaded. *) + +let () = + try + if Dynlink.is_native then begin + Dynlink.loadfile "test4_plugin.cmxs" + end else begin + Dynlink.loadfile "test4_plugin.cma" + end; + assert false + with + | Dynlink.Error ( + Dynlink.Linking_error (_, + Dynlink.Uninitialized_global "Test4_plugin_b")) -> () diff --git a/testsuite/tests/lib-dynlink-initializers/test4_plugin_a.ml b/testsuite/tests/lib-dynlink-initializers/test4_plugin_a.ml new file mode 100644 index 00000000..0341c3bb --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test4_plugin_a.ml @@ -0,0 +1,2 @@ +let () = + print_int (Test4_plugin_b.f 42) diff --git a/testsuite/tests/lib-dynlink-initializers/test4_plugin_b.ml b/testsuite/tests/lib-dynlink-initializers/test4_plugin_b.ml new file mode 100644 index 00000000..2f1eb893 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test4_plugin_b.ml @@ -0,0 +1 @@ +let f x = x + 3 [@@inline never] diff --git a/testsuite/tests/lib-dynlink-initializers/test5_main.ml b/testsuite/tests/lib-dynlink-initializers/test5_main.ml new file mode 100644 index 00000000..545729ed --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test5_main.ml @@ -0,0 +1,60 @@ +(* TEST + +include dynlink + +files = "test5_plugin_a.ml test5_plugin_b.ml test5_second_plugin.ml" + +libraries = "" + +* shared-libraries +** setup-ocamlc.byte-build-env +*** ocamlc.byte +module = "test5_main.ml" +*** ocamlc.byte +module = "test5_plugin_a.ml" +*** ocamlc.byte +module = "test5_plugin_b.ml" +*** ocamlc.byte +module = "test5_second_plugin.ml" +*** ocamlc.byte +program = "test5_plugin.cma" +flags = "-a" +all_modules = "test5_plugin_a.cmo test5_plugin_b.cmo" +*** ocamlc.byte +program = "${test_build_directory}/test5.byte" +libraries = "dynlink" +all_modules = "test5_main.cmo" +**** run + +** native-dynlink +*** setup-ocamlopt.byte-build-env +**** ocamlopt.byte +module = "test5_main.ml" +**** ocamlopt.byte +module = "test5_plugin_a.ml" +**** ocamlopt.byte +module = "test5_plugin_b.ml" +**** ocamlopt.byte +program = "test5_plugin.cmxs" +flags = "-shared" +all_modules = "test5_plugin_a.cmx test5_plugin_b.cmx" +**** ocamlopt.byte +program = "test5_second_plugin.cmxs" +flags = "-shared" +all_modules = "test5_second_plugin.ml" +**** ocamlopt.byte +program = "${test_build_directory}/test5.exe" +libraries = "dynlink" +all_modules = "test5_main.cmx" +***** run +*) + +(* Check that when one shared library loads another shared library then + modules of the second shared library can refer to modules of the + first shared library, as long as they have already been loaded. *) + +let () = + if Dynlink.is_native then + Dynlink.loadfile "test5_plugin.cmxs" + else + Dynlink.loadfile "test5_plugin.cma" diff --git a/testsuite/tests/lib-dynlink-initializers/test5_plugin_a.ml b/testsuite/tests/lib-dynlink-initializers/test5_plugin_a.ml new file mode 100644 index 00000000..5f65b9e4 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test5_plugin_a.ml @@ -0,0 +1,4 @@ +let x = ref 0 + +let () = + x := 1 diff --git a/testsuite/tests/lib-dynlink-initializers/test5_plugin_b.ml b/testsuite/tests/lib-dynlink-initializers/test5_plugin_b.ml new file mode 100644 index 00000000..0813c559 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test5_plugin_b.ml @@ -0,0 +1,6 @@ +let () = + if Dynlink.is_native then begin + Dynlink.loadfile "test5_second_plugin.cmxs" + end else begin + Dynlink.loadfile "test5_second_plugin.cmo" + end diff --git a/testsuite/tests/lib-dynlink-initializers/test5_second_plugin.ml b/testsuite/tests/lib-dynlink-initializers/test5_second_plugin.ml new file mode 100644 index 00000000..9f1f53f6 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test5_second_plugin.ml @@ -0,0 +1,2 @@ +let () = + assert (!Test5_plugin_a.x = 1) diff --git a/testsuite/tests/lib-dynlink-initializers/test6_main.ml b/testsuite/tests/lib-dynlink-initializers/test6_main.ml new file mode 100644 index 00000000..b3c764db --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test6_main.ml @@ -0,0 +1,50 @@ +(* TEST + +include dynlink + +files = "test6_plugin.ml test6_second_plugin.ml" + +libraries = "" + +* shared-libraries +** setup-ocamlc.byte-build-env +*** ocamlc.byte +module = "test6_main.ml" +*** ocamlc.byte +module = "test6_plugin.ml" +*** ocamlc.byte +module = "test6_second_plugin.ml" +*** ocamlc.byte +program = "${test_build_directory}/test6.byte" +libraries = "dynlink" +all_modules = "test6_main.cmo" +**** run + +** native-dynlink +*** setup-ocamlopt.byte-build-env +**** ocamlopt.byte +module = "test6_main.ml" +**** ocamlopt.byte +program = "test6_plugin.cmxs" +flags = "-shared" +all_modules = "test6_plugin.ml" +**** ocamlopt.byte +program = "test6_second_plugin.cmxs" +flags = "-shared" +all_modules = "test6_second_plugin.ml" +**** ocamlopt.byte +program = "${test_build_directory}/test6.exe" +libraries = "dynlink" +all_modules = "test6_main.cmx" +***** run +*) + +(* Check that a module in a loaded shared library whose initializer has not + executed completely cannot be depended upon by another shared library being + loaded. *) + +let () = + if Dynlink.is_native then + Dynlink.loadfile "test6_plugin.cmxs" + else + Dynlink.loadfile "test6_plugin.cmo" diff --git a/testsuite/tests/lib-dynlink-initializers/test6_plugin.ml b/testsuite/tests/lib-dynlink-initializers/test6_plugin.ml new file mode 100644 index 00000000..da785fce --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test6_plugin.ml @@ -0,0 +1,17 @@ +let x = ref 0 + +let () = + try + if Dynlink.is_native then begin + Dynlink.loadfile "test6_second_plugin.cmxs" + end else begin + Dynlink.loadfile "test6_second_plugin.cmo" + end; + assert false + with + | Dynlink.Error ( + Dynlink.Linking_error (_, + Dynlink.Uninitialized_global "Test6_plugin")) -> () + +let () = + x := 1 diff --git a/testsuite/tests/lib-dynlink-initializers/test6_second_plugin.ml b/testsuite/tests/lib-dynlink-initializers/test6_second_plugin.ml new file mode 100644 index 00000000..d0104a80 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test6_second_plugin.ml @@ -0,0 +1,2 @@ +let () = + assert (!Test6_plugin.x = 1) diff --git a/testsuite/tests/lib-dynlink-initializers/test7_interface_only.mli b/testsuite/tests/lib-dynlink-initializers/test7_interface_only.mli new file mode 100644 index 00000000..23267003 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test7_interface_only.mli @@ -0,0 +1,2 @@ + +type t = int diff --git a/testsuite/tests/lib-dynlink-initializers/test7_main.ml b/testsuite/tests/lib-dynlink-initializers/test7_main.ml new file mode 100644 index 00000000..d64f8de7 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test7_main.ml @@ -0,0 +1,49 @@ +(* TEST + +include dynlink + +files = "test7_interface_only.mli test7_plugin.ml" + +libraries = "" + +* shared-libraries +** setup-ocamlc.byte-build-env +*** ocamlc.byte +module = "test7_interface_only.mli" +*** ocamlc.byte +module = "test7_main.ml" +*** ocamlc.byte +module = "test7_plugin.ml" +*** ocamlc.byte +program = "${test_build_directory}/test7.byte" +libraries = "dynlink" +all_modules = "test7_main.cmo" +**** run + +** native-dynlink +*** setup-ocamlopt.byte-build-env +**** ocamlopt.byte +module = "test7_interface_only.mli" +**** ocamlopt.byte +module = "test7_main.ml" +**** ocamlopt.byte +program = "test7_plugin.cmxs" +flags = "-shared" +all_modules = "test7_plugin.ml" +**** ocamlopt.byte +program = "${test_build_directory}/test7.exe" +libraries = "dynlink" +all_modules = "test7_main.cmx" +***** run +*) + +(* Check that a shared library can depend on an interface-only module + that is also depended on by modules in the main program *) + +let f (x : Test7_interface_only.t) = x + 1 [@@inline never] + +let () = + if Dynlink.is_native then + Dynlink.loadfile "test7_plugin.cmxs" + else + Dynlink.loadfile "test7_plugin.cmo" diff --git a/testsuite/tests/lib-dynlink-initializers/test7_plugin.ml b/testsuite/tests/lib-dynlink-initializers/test7_plugin.ml new file mode 100644 index 00000000..8b95a7e4 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test7_plugin.ml @@ -0,0 +1,2 @@ +let () = + print_int (42 : Test7_interface_only.t) diff --git a/testsuite/tests/lib-dynlink-initializers/test8_main.ml b/testsuite/tests/lib-dynlink-initializers/test8_main.ml new file mode 100644 index 00000000..7c556867 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test8_main.ml @@ -0,0 +1,58 @@ +(* TEST + +include dynlink + +files = "test8_plugin_a.ml test8_plugin_b.ml test8_plugin_b.mli" + +libraries = "" + +* shared-libraries +** setup-ocamlc.byte-build-env +*** ocamlc.byte +module = "test8_main.ml" +*** ocamlc.byte +module = "test8_plugin_b.mli" +*** ocamlc.byte +module = "test8_plugin_a.ml" +*** ocamlc.byte +module = "test8_plugin_b.ml" +*** ocamlc.byte +program = "test8_plugin.cma" +flags = "-a" +all_modules = "test8_plugin_a.cmo test8_plugin_b.cmo" +*** ocamlc.byte +program = "${test_build_directory}/test8.byte" +libraries = "dynlink" +all_modules = "test8_main.cmo" +**** run + +** native-dynlink +*** setup-ocamlopt.byte-build-env +**** ocamlopt.byte +module = "test8_main.ml" +**** ocamlopt.byte +module = "test8_plugin_b.mli" +**** ocamlopt.byte +module = "test8_plugin_a.ml" +**** ocamlopt.byte +module = "test8_plugin_b.ml" +**** ocamlopt.byte +program = "test8_plugin.cmxs" +flags = "-shared" +all_modules = "test8_plugin_a.cmx test8_plugin_b.cmx" +**** ocamlopt.byte +program = "${test_build_directory}/test8.exe" +libraries = "dynlink" +all_modules = "test8_main.cmx" +***** run +*) + +(* Check that modules of a shared library can have interface-only + dependencies to later modules in the same shared library. *) + +let () = + if Dynlink.is_native then begin + Dynlink.loadfile "test8_plugin.cmxs" + end else begin + Dynlink.loadfile "test8_plugin.cma" + end diff --git a/testsuite/tests/lib-dynlink-initializers/test8_plugin_a.ml b/testsuite/tests/lib-dynlink-initializers/test8_plugin_a.ml new file mode 100644 index 00000000..e11f804d --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test8_plugin_a.ml @@ -0,0 +1,4 @@ +let () = + print_int (42 : Test8_plugin_b.t) + +let f x = x + 3 diff --git a/testsuite/tests/lib-dynlink-initializers/test8_plugin_b.ml b/testsuite/tests/lib-dynlink-initializers/test8_plugin_b.ml new file mode 100644 index 00000000..2df7d3d1 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test8_plugin_b.ml @@ -0,0 +1,4 @@ +type t = int + +let () = + print_int (Test8_plugin_a.f 42) diff --git a/testsuite/tests/lib-dynlink-initializers/test8_plugin_b.mli b/testsuite/tests/lib-dynlink-initializers/test8_plugin_b.mli new file mode 100644 index 00000000..23267003 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test8_plugin_b.mli @@ -0,0 +1,2 @@ + +type t = int diff --git a/testsuite/tests/lib-dynlink-initializers/test9_main.ml b/testsuite/tests/lib-dynlink-initializers/test9_main.ml new file mode 100644 index 00000000..110e2fc4 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test9_main.ml @@ -0,0 +1,57 @@ +(* TEST + +include dynlink + +files = "test9_plugin.ml test9_second_plugin.ml test9_second_plugin.mli" + +libraries = "" + +* shared-libraries +** setup-ocamlc.byte-build-env +*** ocamlc.byte +module = "test9_second_plugin.mli" +*** ocamlc.byte +module = "test9_main.ml" +*** ocamlc.byte +module = "test9_plugin.ml" +*** ocamlc.byte +module = "test9_second_plugin.ml" +*** ocamlc.byte +program = "${test_build_directory}/test9.byte" +libraries = "dynlink" +all_modules = "test9_main.cmo" +**** run + +** native-dynlink +*** setup-ocamlopt.byte-build-env +**** ocamlopt.byte +module = "test9_second_plugin.mli" +**** ocamlopt.byte +module = "test9_main.ml" +**** ocamlopt.byte +program = "test9_plugin.cmxs" +flags = "-shared" +all_modules = "test9_plugin.ml" +**** ocamlopt.byte +program = "test9_second_plugin.cmxs" +flags = "-shared" +all_modules = "test9_second_plugin.ml" +**** ocamlopt.byte +program = "${test_build_directory}/test9.exe" +libraries = "dynlink" +all_modules = "test9_main.cmx" +***** run +*) + +(* Check that a shared library can depend on an interface-only module + that is implemented by another shared library that is loaded + later. *) + +let () = + if Dynlink.is_native then begin + Dynlink.loadfile "test9_plugin.cmxs"; + Dynlink.loadfile "test9_second_plugin.cmxs" + end else begin + Dynlink.loadfile "test9_plugin.cmo"; + Dynlink.loadfile "test9_second_plugin.cmo" + end diff --git a/testsuite/tests/lib-dynlink-initializers/test9_plugin.ml b/testsuite/tests/lib-dynlink-initializers/test9_plugin.ml new file mode 100644 index 00000000..08d86cb2 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test9_plugin.ml @@ -0,0 +1,2 @@ +let () = + print_int (42 : Test9_second_plugin.t) diff --git a/testsuite/tests/lib-dynlink-initializers/test9_second_plugin.ml b/testsuite/tests/lib-dynlink-initializers/test9_second_plugin.ml new file mode 100644 index 00000000..c3fee3c8 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test9_second_plugin.ml @@ -0,0 +1,4 @@ + +type t = int + +let () = print_endline "Second" diff --git a/testsuite/tests/lib-dynlink-initializers/test9_second_plugin.mli b/testsuite/tests/lib-dynlink-initializers/test9_second_plugin.mli new file mode 100644 index 00000000..23267003 --- /dev/null +++ b/testsuite/tests/lib-dynlink-initializers/test9_second_plugin.mli @@ -0,0 +1,2 @@ + +type t = int diff --git a/testsuite/tests/lib-dynlink-native/Makefile b/testsuite/tests/lib-dynlink-native/Makefile deleted file mode 100644 index 50ed0e8b..00000000 --- a/testsuite/tests/lib-dynlink-native/Makefile +++ /dev/null @@ -1,126 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Clerc, SED, INRIA Rocquencourt * -#* * -#* Copyright 2010 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -BASEDIR=$(shell pwd)/../.. - -COMPFLAGS=-I $(OTOPDIR)/otherlibs/$(UNIXLIBVAR)unix \ - -I $(OTOPDIR)/otherlibs/systhreads \ - -I $(OTOPDIR)/otherlibs/dynlink -LD_PATH = $(TOPDIR)/otherlibs/$(UNIXLIBVAR)unix:$(TOPDIR)/otherlibs/systhreads\ -:$(TOPDIR)/otherlibs/dynlink - -.PHONY: default -default: - @if ! $(NATDYNLINK) || $(BYTECODE_ONLY) ; then \ - echo " ... testing 'main' => skipped"; \ - else \ - $(SET_LD_PATH) $(MAKE) all; \ - fi - -.PHONY: all -all: compile run - -PLUGINS=plugin.so plugin2.so sub/plugin.so sub/plugin3.so plugin4.so \ - mypack.so packed1.so packed1_client.so pack_client.so plugin_ref.so \ - plugin_high_arity.so plugin_ext.so plugin_simple.so bug.so \ - plugin_thread.so plugin4_unix.so a.so b.so c.so - -.PHONY: compile -compile: $(PLUGINS) main$(EXE) mylib.so - -.PHONY: run -run: - @printf " ... testing 'main'" - @./main$(EXE) plugin.so plugin2.so plugin_thread.so > result - @$(DIFF) reference result >/dev/null \ - && echo " => passed" || echo " => failed" - -main$(EXE): api.cmx main.cmx - @$(OCAMLOPT) -I +threads -o main$(EXE) -linkall unix.cmxa threads.cmxa \ - dynlink.cmxa api.cmx main.cmx - -main_ext$(EXE): api.cmx main.cmx factorial.$(O) - @$(OCAMLOPT) -o main_ext$(EXE) dynlink.cmxa api.cmx main.cmx \ - factorial.$(O) - -sub/plugin3.cmx: sub/api.cmi sub/api.cmx sub/plugin3.ml - @cd sub; \ - mv api.cmx api.cmx.bak; \ - $(OCAMLOPT) -c plugin3.ml; \ - mv api.cmx.bak api.cmx - -plugin2.cmx: api.cmx plugin.cmi plugin.cmx - @mv plugin.cmx plugin.cmx.bak; - @$(OCAMLOPT) -c plugin2.ml - @mv plugin.cmx.bak plugin.cmx - -sub/api.so: sub/api.cmi sub/api.ml - @cd sub; $(OCAMLOPT) -c $(SUPPORTS_SHARED_LIBRARIES) api.ml - -sub/api.cmi: sub/api.mli - @cd sub; $(OCAMLOPT) -c -opaque api.mli - -sub/api.cmx: sub/api.cmi sub/api.ml - @cd sub; $(OCAMLOPT) -c api.ml - -plugin.cmi: plugin.mli - @$(OCAMLOPT) -c -opaque plugin.mli - -plugin.cmx: api.cmx plugin.cmi -sub/plugin.cmx: api.cmx -plugin4.cmx: api.cmx -main.cmx: api.cmx -plugin_ext.cmx: api.cmx plugin_ext.ml - @$(OCAMLOPT) -c plugin_ext.ml - -plugin_ext.so: factorial.$(O) plugin_ext.cmx - @$(OCAMLOPT) -shared -o plugin_ext.so factorial.$(O) \ - plugin_ext.cmx - -plugin4_unix.so: plugin4.cmx - @$(OCAMLOPT) -shared -o plugin4_unix.so unix.cmxa plugin4.cmx - -packed1_client.cmx: packed1.cmx - -pack_client.cmx: mypack.cmx - -packed1.cmx: api.cmx packed1.ml - @$(OCAMLOPT) -c $(COMPFLAGS) -for-pack Mypack packed1.ml - -mypack.cmx: packed1.cmx - @$(OCAMLOPT) $(COMPFLAGS) -S -pack -o mypack.cmx packed1.cmx - -mylib.cmxa: plugin.cmx plugin2.cmx - @$(OCAMLOPT) $(COMPFLAGS) -a -o mylib.cmxa plugin.cmx plugin2.cmx - -factorial.$(O): factorial.c - @$(OCAMLOPT) -c -ccopt "$(SHAREDCCCOMPOPTS)" -ccopt -I \ - -ccopt $(CTOPDIR)/byterun \ - factorial.c - -.PHONY: promote -promote: - @cp result reference - -.PRECIOUS: %.cmx - -.PHONY: clean -clean: defaultclean - @rm -f result *.so *.o *.cm* main main_ext *.exe *.s *.asm *.obj - @rm -f *.a *.lib - @rm -f sub/*.so sub/*.o sub/*.cm* sub/*.s sub/*.asm sub/*.obj - @rm -f marshal.data - -include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/lib-dynlink-native/a.ml b/testsuite/tests/lib-dynlink-native/a.ml old mode 100755 new mode 100644 diff --git a/testsuite/tests/lib-dynlink-native/b.ml b/testsuite/tests/lib-dynlink-native/b.ml old mode 100755 new mode 100644 diff --git a/testsuite/tests/lib-dynlink-native/c.ml b/testsuite/tests/lib-dynlink-native/c.ml old mode 100755 new mode 100644 diff --git a/testsuite/tests/lib-dynlink-native/main.ml b/testsuite/tests/lib-dynlink-native/main.ml index 8c738aeb..bba07704 100644 --- a/testsuite/tests/lib-dynlink-native/main.ml +++ b/testsuite/tests/lib-dynlink-native/main.ml @@ -1,8 +1,221 @@ +(* TEST + +files = "a.ml api.ml b.ml bug.ml c.ml factorial.c pack_client.ml \ + packed1_client.ml packed1.ml plugin2.ml plugin4.ml plugin_ext.ml \ + plugin_high_arity.ml plugin.ml plugin.mli plugin_ref.ml \ + plugin_simple.ml plugin_thread.ml" + +* hassysthreads +include systhreads +include dynlink + +set subdir = "${test_source_directory}/sub" + +** native-dynlink +libraries = "" (* We will add them manually where appropriated *) +*** setup-ocamlopt.byte-build-env +ocamlopt_default_flags = "" (* Removes the -ccopt -no-pie on ised on OpenBSD *) +**** script +script = "mkdir sub" +***** script +script = "cp ${subdir}/api.mli ${subdir}/api.ml ${subdir}/plugin3.ml \ + ${subdir}/plugin.ml sub" +****** ocamlopt.byte +module = "api.ml" +******* ocamlopt.byte +flags = "-opaque" +module = "plugin.mli" +******** ocamlopt.byte +flags = "" +module = "plugin.ml" +********* ocamlopt.byte +module= "" +flags = "-shared" +program = "plugin.so" +all_modules = "plugin.cmx" +********** script +script = "mv plugin.cmx plugin.cmx.bak" +*********** ocamlopt.byte +flags = "" +module = "plugin2.ml" +************ script +script = "mv plugin.cmx.bak plugin.cmx" +************* ocamlopt.byte +module= "" +flags = "-shared" +program = "plugin2.so" +all_modules = "plugin2.cmx" +************** ocamlopt.byte +flags = "" +module = "sub/plugin.ml" +*************** ocamlopt.byte +module = "" +flags = "-shared" +program = "sub/plugin.so" +all_modules = "sub/plugin.cmx" +**************** cd +cwd = "sub" +***************** ocamlopt.byte +module = "api.mli" +flags = "-opaque" +****************** ocamlopt.byte +flags = "" +module = "api.ml" +******************* script +script = "mv api.cmx api.cmx.bak" +******************** ocamlopt.byte +module = "plugin3.ml" +********************* script +script = "mv api.cmx.bak api.cmx" +********************** cd +cwd = ".." +*********************** ocamlopt.byte +module = "" +flags = "-shared" +program = "sub/plugin3.so" +all_modules = "sub/plugin3.cmx" +************************ ocamlopt.byte +flags = "" +module = "plugin4.ml" +************************* ocamlopt.byte +module = "" +flags = "-shared" +program = "plugin4.so" +all_modules = "plugin4.cmx" +************************** ocamlopt.byte +module = "packed1.ml" +flags = "-for-pack Mypack" +*************************** ocamlopt.byte +flags = "-S -pack" +module = "" +program = "mypack.cmx" +all_modules = "packed1.cmx" +**************************** ocamlopt.byte +program = "mypack.so" +flags = "-shared" +all_modules = "mypack.cmx" +***************************** ocamlopt.byte +program = "packed1.so" +flags = "-shared" +all_modules = "packed1.cmx" +****************************** ocamlopt.byte +flags = "" +module = "packed1_client.ml" +******************************* ocamlopt.byte +module = "" +program = "packed1_client.so" +flags = "-shared" +all_modules = "packed1_client.cmx" +******************************** ocamlopt.byte +flags = "" +module = "pack_client.ml" +********************************* ocamlopt.byte +module = "" +program = "pack_client.so" +flags = "-shared" +all_modules = "pack_client.cmx" +********************************** ocamlopt.byte +flags = "" +module = "plugin_ref.ml" +*********************************** ocamlopt.byte +module = "" +program = "plugin_ref.so" +flags = "-shared" +all_modules = "plugin_ref.cmx" +************************************ ocamlopt.byte +flags = "" +module = "plugin_high_arity.ml" +************************************* ocamlopt.byte +module = "" +program = "plugin_high_arity.so" +flags = "-shared" +all_modules = "plugin_high_arity.cmx" +************************************** ocamlopt.byte +flags = "-ccopt ${shared_library_cflags}" +module = "factorial.c" +*************************************** ocamlopt.byte +flags = "" +module = "plugin_ext.ml" +**************************************** ocamlopt.byte +module = "" +program = "plugin_ext.so" +flags = "-shared" +all_modules = "factorial.${objext} plugin_ext.cmx" +***************************************** ocamlopt.byte +module = "plugin_simple.ml" +flags = "" +****************************************** ocamlopt.byte +module = "" +program = "plugin_simple.so" +flags = "-shared" +all_modules = "plugin_simple.cmx" +****************************************** ocamlopt.byte +module = "bug.ml" +flags = "" +******************************************* ocamlopt.byte +module = "" +program = "bug.so" +flags = "-shared" +all_modules = "bug.cmx" +******************************************* ocamlopt.byte +module = "plugin_thread.ml" +flags = "" +******************************************** ocamlopt.byte +module = "" +program = "plugin_thread.so" +flags = "-shared" +all_modules = "plugin_thread.cmx" +********************************************* ocamlopt.byte +program = "plugin4_unix.so" +all_modules = "unix.cmxa plugin4.cmx" +********************************************** ocamlopt.byte +flags = "" +compile_only = "true" +all_modules = "a.ml b.ml c.ml main.ml" +*********************************************** ocamlopt.byte +module = "" +compile_only = "false" +flags = "-shared" +program = "a.so" +all_modules = "a.cmx" +************************************************ ocamlopt.byte +program = "b.so" +all_modules = "b.cmx" +************************************************* ocamlopt.byte +program = "c.so" +all_modules = "c.cmx" +************************************************** ocamlopt.byte +program = "mylib.cmxa" +flags = "-a" +all_modules = "plugin.cmx plugin2.cmx" +*************************************************** ocamlopt.byte +program = "mylib.so" +flags = "-shared -linkall" +all_modules = "mylib.cmxa" +**************************************************** ocamlopt.byte +program = "${test_build_directory}/main.exe" +libraries = "unix threads dynlink" +flags = "-linkall" +all_modules = "api.cmx main.cmx" +(* +On OpenBSD, the compiler produces warnings like +/usr/bin/ld: warning: creating a DT_TEXTREL in a shared object. +So the compiler output is not empty on OpenBSD so an emptiness check +would fail on this platform. + +We thus do not check compiler output. This was not done either before the +test was ported to ocamltest. +*) + +***************************************************** run +arguments = "plugin.so plugin2.so plugin_thread.so" +****************************************************** check-program-output +*) + let () = Api.add_cb (fun () -> print_endline "Callback from main") let () = - Dynlink.init (); Dynlink.allow_unsafe_modules true; for i = 1 to Array.length Sys.argv - 1 do let name = Sys.argv.(i) in diff --git a/testsuite/tests/lib-dynlink-native/reference b/testsuite/tests/lib-dynlink-native/main.reference similarity index 100% rename from testsuite/tests/lib-dynlink-native/reference rename to testsuite/tests/lib-dynlink-native/main.reference diff --git a/testsuite/tests/lib-dynlink-native/ocamltests b/testsuite/tests/lib-dynlink-native/ocamltests new file mode 100644 index 00000000..d389d156 --- /dev/null +++ b/testsuite/tests/lib-dynlink-native/ocamltests @@ -0,0 +1 @@ +main.ml diff --git a/testsuite/tests/lib-dynlink-pr4229/abstract.ml b/testsuite/tests/lib-dynlink-pr4229/abstract.ml new file mode 100644 index 00000000..167565c8 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4229/abstract.ml @@ -0,0 +1,3 @@ +type t = int +let print i = Printf.printf "Abstract %i\n" i +let x = 10 diff --git a/testsuite/tests/lib-dynlink-pr4229/abstract.mli b/testsuite/tests/lib-dynlink-pr4229/abstract.mli new file mode 100644 index 00000000..d31df8a5 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4229/abstract.mli @@ -0,0 +1,3 @@ +type t +val print: t -> unit +val x: t diff --git a/testsuite/tests/lib-dynlink-pr4229/client.ml b/testsuite/tests/lib-dynlink-pr4229/client.ml new file mode 100644 index 00000000..cc0ac86f --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4229/client.ml @@ -0,0 +1 @@ +let () = Static.f Abstract.x diff --git a/testsuite/tests/lib-dynlink-pr4229/main.ml b/testsuite/tests/lib-dynlink-pr4229/main.ml new file mode 100644 index 00000000..3c3c9779 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4229/main.ml @@ -0,0 +1,94 @@ +(* TEST + +include dynlink + +files = "abstract.mli abstract.ml static.ml client.ml main.ml" + +set sub = "${test_source_directory}/sub" + +libraries = "" + +* shared-libraries +** setup-ocamlc.byte-build-env +*** script +script = "mkdir sub" +**** script +script = "cp ${sub}/abstract.mli ${sub}/abstract.ml sub" +***** cd +cwd = "${sub}" +****** ocamlc.byte +module = "abstract.mli" +******* ocamlc.byte +module = "abstract.ml" +******** cd +cwd = ".." +********* ocamlc.byte +module = "abstract.mli" +********** ocamlc.byte +module = "abstract.ml" +*********** ocamlc.byte +module = "static.ml" +************ ocamlc.byte +module = "client.ml" +************* ocamlc.byte +module = "main.ml" +************** ocamlc.byte +program = "${test_build_directory}/main" +libraries = "dynlink" +module = "" +all_modules = "abstract.cmo static.cmo main.cmo" +*************** run +exit_status = "2" +**************** check-program-output + +** native-dynlink +*** setup-ocamlopt.byte-build-env +**** script +script = "mkdir sub" +***** script +script = "cp ${sub}/abstract.mli ${sub}/abstract.ml sub" +****** cd +cwd = "${sub}" +******* ocamlopt.byte +module = "abstract.mli" +******** ocamlopt.byte +program = "abstract.cmxs" +flags = "-shared" +module = "" +all_modules = "abstract.ml" +********* cd +cwd = ".." +********** ocamlopt.byte +flags = "" +module = "abstract.mli" +*********** ocamlopt.byte +module = "abstract.ml" +************ ocamlopt.byte +module = "static.ml" +************* ocamlopt.byte +program = "client.cmxs" +flags = "-shared" +module = "" +all_modules = "client.ml" +************* ocamlopt.byte +module = "main_native.ml" +************** ocamlopt.byte +program = "${test_build_directory}/main_native" +libraries = "dynlink" +module = "" +all_modules = "abstract.cmx static.cmx main_native.cmx" +*************** run +exit_status = "2" +**************** check-program-output +*) + +(* PR#4229 *) + +let () = + try + (* Dynlink.init (); *) (* this function has been removed from the API *) + Dynlink.loadfile "client.cmo"; (* utilise abstract.cmo *) + Dynlink.loadfile "sub/abstract.cmo"; + Dynlink.loadfile "client.cmo" (* utilise sub/abstract.cmo *) + with + | Dynlink.Error (Dynlink.Module_already_loaded "Abstract") -> exit 2 diff --git a/testsuite/tests/lib-dynlink-pr4229/main.reference b/testsuite/tests/lib-dynlink-pr4229/main.reference new file mode 100644 index 00000000..c2cc066e --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4229/main.reference @@ -0,0 +1 @@ +Abstract 10 \ No newline at end of file diff --git a/testsuite/tests/lib-dynlink-pr4229/main_native.ml b/testsuite/tests/lib-dynlink-pr4229/main_native.ml new file mode 100644 index 00000000..532858e0 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4229/main_native.ml @@ -0,0 +1,10 @@ +(* PR#4229 *) + +let () = + try + (* Dynlink.init (); *) (* this function has been removed from the API *) + Dynlink.loadfile "client.cmxs"; (* utilise abstract.cmx *) + Dynlink.loadfile "sub/abstract.cmxs"; + Dynlink.loadfile "client.cmxs" (* utilise sub/abstract.cmx *) + with + | Dynlink.Error (Dynlink.Module_already_loaded "Abstract") -> exit 2 diff --git a/testsuite/tests/lib-dynlink-pr4229/ocamltests b/testsuite/tests/lib-dynlink-pr4229/ocamltests new file mode 100644 index 00000000..d389d156 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4229/ocamltests @@ -0,0 +1 @@ +main.ml diff --git a/testsuite/tests/lib-dynlink-pr4229/static.ml b/testsuite/tests/lib-dynlink-pr4229/static.ml new file mode 100644 index 00000000..a30eb133 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4229/static.ml @@ -0,0 +1 @@ +let f = Abstract.print diff --git a/testsuite/tests/lib-dynlink-pr4229/sub/abstract.ml b/testsuite/tests/lib-dynlink-pr4229/sub/abstract.ml new file mode 100644 index 00000000..60e8cbb2 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4229/sub/abstract.ml @@ -0,0 +1,3 @@ +type t = string +let print i = Printf.printf "Abstract %s\n" i +let x = "foo" diff --git a/testsuite/tests/lib-dynlink-pr4229/sub/abstract.mli b/testsuite/tests/lib-dynlink-pr4229/sub/abstract.mli new file mode 100644 index 00000000..d31df8a5 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4229/sub/abstract.mli @@ -0,0 +1,3 @@ +type t +val print: t -> unit +val x: t diff --git a/testsuite/tests/lib-dynlink-pr4839/byte.plugin1.reference b/testsuite/tests/lib-dynlink-pr4839/byte.plugin1.reference new file mode 100644 index 00000000..2a9b87db --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/byte.plugin1.reference @@ -0,0 +1,3 @@ +API +zero=0 +fact (zero+5) = 120 diff --git a/testsuite/tests/lib-dynlink-pr4839/byte.plugin2.reference b/testsuite/tests/lib-dynlink-pr4839/byte.plugin2.reference new file mode 100644 index 00000000..bd488fc2 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/byte.plugin2.reference @@ -0,0 +1,2 @@ +API +ERROR: interface mismatch on Packed diff --git a/testsuite/tests/lib-dynlink-pr4839/byte.plugin3.reference b/testsuite/tests/lib-dynlink-pr4839/byte.plugin3.reference new file mode 100644 index 00000000..c79c0cf2 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/byte.plugin3.reference @@ -0,0 +1,2 @@ +API +ERROR: The module `Packed' is already loaded (either by the main program or a previously-dynlinked library) diff --git a/testsuite/tests/lib-dynlink-pr4839/byte.plugin4.reference b/testsuite/tests/lib-dynlink-pr4839/byte.plugin4.reference new file mode 100644 index 00000000..c79c0cf2 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/byte.plugin4.reference @@ -0,0 +1,2 @@ +API +ERROR: The module `Packed' is already loaded (either by the main program or a previously-dynlinked library) diff --git a/testsuite/tests/lib-dynlink-pr4839/host/api.ml b/testsuite/tests/lib-dynlink-pr4839/host/api.ml new file mode 100644 index 00000000..cc6ddaa6 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/host/api.ml @@ -0,0 +1,3 @@ +let fact = ref (fun _ -> assert false) +let zero = ref (-1) +let _ = prerr_endline "API" diff --git a/testsuite/tests/lib-dynlink-pr4839/host/api.mli b/testsuite/tests/lib-dynlink-pr4839/host/api.mli new file mode 100644 index 00000000..0f9e19b3 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/host/api.mli @@ -0,0 +1,2 @@ +val fact : (int -> int) ref +val zero : int ref diff --git a/testsuite/tests/lib-dynlink-pr4839/host/host.ml b/testsuite/tests/lib-dynlink-pr4839/host/host.ml new file mode 100644 index 00000000..2dbfb34b --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/host/host.ml @@ -0,0 +1,8 @@ +let _ = + try + Dynlink.loadfile Sys.argv.(1); + Format.eprintf "zero=%d@." !Packed.Api.zero; + Format.eprintf "fact (zero+5) = %d@." (!Packed.Api.fact (!Packed.Api.zero + 5)) + with + | Dynlink.Error e -> + Format.eprintf "ERROR: %s@." (Dynlink.error_message e) diff --git a/testsuite/tests/lib-dynlink-pr4839/native.plugin1.reference b/testsuite/tests/lib-dynlink-pr4839/native.plugin1.reference new file mode 100644 index 00000000..2a9b87db --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/native.plugin1.reference @@ -0,0 +1,3 @@ +API +zero=0 +fact (zero+5) = 120 diff --git a/testsuite/tests/lib-dynlink-pr4839/native.plugin2.reference b/testsuite/tests/lib-dynlink-pr4839/native.plugin2.reference new file mode 100644 index 00000000..bd488fc2 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/native.plugin2.reference @@ -0,0 +1,2 @@ +API +ERROR: interface mismatch on Packed diff --git a/testsuite/tests/lib-dynlink-pr4839/native.plugin3.reference b/testsuite/tests/lib-dynlink-pr4839/native.plugin3.reference new file mode 100644 index 00000000..c79c0cf2 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/native.plugin3.reference @@ -0,0 +1,2 @@ +API +ERROR: The module `Packed' is already loaded (either by the main program or a previously-dynlinked library) diff --git a/testsuite/tests/lib-dynlink-pr4839/native.plugin4.reference b/testsuite/tests/lib-dynlink-pr4839/native.plugin4.reference new file mode 100644 index 00000000..c79c0cf2 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/native.plugin4.reference @@ -0,0 +1,2 @@ +API +ERROR: The module `Packed' is already loaded (either by the main program or a previously-dynlinked library) diff --git a/testsuite/tests/lib-dynlink-pr4839/ocamltests b/testsuite/tests/lib-dynlink-pr4839/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/lib-dynlink-pr4839/plugin1/api.ml b/testsuite/tests/lib-dynlink-pr4839/plugin1/api.ml new file mode 100644 index 00000000..cc6ddaa6 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/plugin1/api.ml @@ -0,0 +1,3 @@ +let fact = ref (fun _ -> assert false) +let zero = ref (-1) +let _ = prerr_endline "API" diff --git a/testsuite/tests/lib-dynlink-pr4839/plugin1/api.mli b/testsuite/tests/lib-dynlink-pr4839/plugin1/api.mli new file mode 100644 index 00000000..0f9e19b3 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/plugin1/api.mli @@ -0,0 +1,2 @@ +val fact : (int -> int) ref +val zero : int ref diff --git a/testsuite/tests/lib-dynlink-pr4839/plugin1/plugin.ml b/testsuite/tests/lib-dynlink-pr4839/plugin1/plugin.ml new file mode 100644 index 00000000..30eedc2e --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/plugin1/plugin.ml @@ -0,0 +1,7 @@ +let rec fact = function + | 0 -> 1 + | n -> n * fact (n - 1) + +let _ = + Packed.Api.zero := 0; + Packed.Api.fact := fact diff --git a/testsuite/tests/lib-dynlink-pr4839/plugin2/api.ml b/testsuite/tests/lib-dynlink-pr4839/plugin2/api.ml new file mode 100644 index 00000000..576ed895 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/plugin2/api.ml @@ -0,0 +1,3 @@ +let fact = ref None +let zero = ref (-1) +let _ = prerr_endline "API" diff --git a/testsuite/tests/lib-dynlink-pr4839/plugin2/api.mli b/testsuite/tests/lib-dynlink-pr4839/plugin2/api.mli new file mode 100644 index 00000000..fe30c8e9 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/plugin2/api.mli @@ -0,0 +1,2 @@ +val fact : (int -> int) option ref +val zero : int ref diff --git a/testsuite/tests/lib-dynlink-pr4839/plugin2/plugin.ml b/testsuite/tests/lib-dynlink-pr4839/plugin2/plugin.ml new file mode 100644 index 00000000..53771da3 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/plugin2/plugin.ml @@ -0,0 +1,7 @@ +let rec fact = function + | 0 -> 1 + | n -> n * fact (n - 1) + +let _ = + Packed.Api.zero := 0; + Packed.Api.fact := Some fact diff --git a/testsuite/tests/lib-dynlink-pr4839/plugin3/api.ml b/testsuite/tests/lib-dynlink-pr4839/plugin3/api.ml new file mode 100644 index 00000000..576ed895 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/plugin3/api.ml @@ -0,0 +1,3 @@ +let fact = ref None +let zero = ref (-1) +let _ = prerr_endline "API" diff --git a/testsuite/tests/lib-dynlink-pr4839/plugin3/api.mli b/testsuite/tests/lib-dynlink-pr4839/plugin3/api.mli new file mode 100644 index 00000000..fe30c8e9 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/plugin3/api.mli @@ -0,0 +1,2 @@ +val fact : (int -> int) option ref +val zero : int ref diff --git a/testsuite/tests/lib-dynlink-pr4839/plugin3/plugin.ml b/testsuite/tests/lib-dynlink-pr4839/plugin3/plugin.ml new file mode 100644 index 00000000..53771da3 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/plugin3/plugin.ml @@ -0,0 +1,7 @@ +let rec fact = function + | 0 -> 1 + | n -> n * fact (n - 1) + +let _ = + Packed.Api.zero := 0; + Packed.Api.fact := Some fact diff --git a/testsuite/tests/lib-dynlink-pr4839/plugin4/api.ml b/testsuite/tests/lib-dynlink-pr4839/plugin4/api.ml new file mode 100644 index 00000000..0138901e --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/plugin4/api.ml @@ -0,0 +1,3 @@ +let fact = ref (fun _ -> assert false) +let zero = ref 42 +let _ = prerr_endline "API" diff --git a/testsuite/tests/lib-dynlink-pr4839/plugin4/api.mli b/testsuite/tests/lib-dynlink-pr4839/plugin4/api.mli new file mode 100644 index 00000000..0f9e19b3 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/plugin4/api.mli @@ -0,0 +1,2 @@ +val fact : (int -> int) ref +val zero : int ref diff --git a/testsuite/tests/lib-dynlink-pr4839/plugin4/plugin.ml b/testsuite/tests/lib-dynlink-pr4839/plugin4/plugin.ml new file mode 100644 index 00000000..93682b7a --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/plugin4/plugin.ml @@ -0,0 +1,7 @@ +let rec fact = function + | 0 -> 1 + | n -> n * fact (n - 1) + +let _ = + (* Packed.Api.zero := 0; *) + Packed.Api.fact := fact diff --git a/testsuite/tests/lib-dynlink-pr4839/test.ml b/testsuite/tests/lib-dynlink-pr4839/test.ml new file mode 100644 index 00000000..44522534 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr4839/test.ml @@ -0,0 +1,261 @@ +(* TEST + +include dynlink +libraries = "" +set host = "${test_source_directory}/host" +set plugin1 = "${test_source_directory}/plugin1" +set plugin2 = "${test_source_directory}/plugin2" +set plugin3 = "${test_source_directory}/plugin3" +set plugin4 = "${test_source_directory}/plugin4" + +* shared-libraries +** setup-ocamlc.byte-build-env +*** script +script = "mkdir host plugin1 plugin2 plugin3 plugin4" +*** script +script = "cp ${host}/host.ml ${host}/api.mli ${host}/api.ml host" +*** script +script = "cp ${plugin1}/plugin.ml ${plugin1}/api.mli ${plugin1}/api.ml plugin1" +*** script +script = "cp ${plugin2}/plugin.ml ${plugin2}/api.mli ${plugin2}/api.ml plugin2" +*** script +script = "cp ${plugin3}/plugin.ml ${plugin3}/api.mli ${plugin3}/api.ml plugin3" +*** script +script = "cp ${plugin4}/plugin.ml ${plugin4}/api.mli ${plugin4}/api.ml plugin4" + +*** cd +cwd = "plugin1" +*** ocamlc.byte +module = "api.mli" +*** ocamlc.byte +flags = "-for-pack Packed" +module = "api.ml" +*** ocamlc.byte +program = "packed.cmo" +flags = "-pack" +all_modules = "api.cmo" +*** ocamlc.byte +program = "plugin.cma" +flags = "-a" +all_modules = "plugin.ml" +*** cd +cwd = ".." + +*** cd +cwd = "plugin2" +*** ocamlc.byte +module = "api.mli" +*** ocamlc.byte +flags = "-for-pack Packed" +module = "api.ml" +*** ocamlc.byte +program = "packed.cmo" +flags = "-pack" +all_modules = "api.cmo" +*** ocamlc.byte +program = "plugin.cma" +flags = "-a" +all_modules = "plugin.ml" +*** cd +cwd = ".." + +*** cd +cwd = "plugin3" +*** ocamlc.byte +module = "api.mli" +*** ocamlc.byte +flags = "-for-pack Packed" +module = "api.ml" +*** ocamlc.byte +program = "packed.cmo" +flags = "-pack" +all_modules = "api.cmo" +*** ocamlc.byte +program = "plugin.cma" +flags = "-a" +all_modules = "packed.cmo plugin.ml" +*** cd +cwd = ".." + +*** cd +cwd = "plugin4" +*** ocamlc.byte +module = "api.mli" +*** ocamlc.byte +flags = "-for-pack Packed" +module = "api.ml" +*** ocamlc.byte +program = "packed.cmo" +flags = "-pack" +all_modules = "api.cmo" +*** ocamlc.byte +program = "plugin.cma" +flags = "-a" +all_modules = "packed.cmo plugin.ml" +*** cd +cwd = ".." + +*** cd +cwd = "host" +*** ocamlc.byte +module = "api.mli" +*** ocamlc.byte +flags = "-for-pack Packed" +module = "api.ml" +*** ocamlc.byte +program = "packed.cmo" +flags = "-pack" +all_modules = "api.cmo" +*** ocamlc.byte +program = "./host.byt" +libraries = "dynlink" +all_modules = "packed.cmo host.ml" +**** run +arguments = "../plugin1/plugin.cma" +output = "byte.plugin1.result" +***** check-program-output +reference = "${test_source_directory}/byte.plugin1.reference" +**** run +arguments = "../plugin2/plugin.cma" +output = "byte.plugin2.result" +***** check-program-output +reference = "${test_source_directory}/byte.plugin2.reference" +**** run +arguments = "../plugin3/plugin.cma" +output = "byte.plugin3.result" +***** check-program-output +reference = "${test_source_directory}/byte.plugin3.reference" +**** run +arguments = "../plugin4/plugin.cma" +output = "byte.plugin4.result" +***** check-program-output +reference = "${test_source_directory}/byte.plugin4.reference" +*** cd +cwd = ".." + +** native-dynlink +*** setup-ocamlopt.byte-build-env + +**** script +script = "mkdir host plugin1 plugin2 plugin3 plugin4" +**** script +script = "cp ${host}/host.ml ${host}/api.mli ${host}/api.ml host" +**** script +script = "cp ${plugin1}/plugin.ml ${plugin1}/api.mli ${plugin1}/api.ml plugin1" +**** script +script = "cp ${plugin2}/plugin.ml ${plugin2}/api.mli ${plugin2}/api.ml plugin2" +**** script +script = "cp ${plugin3}/plugin.ml ${plugin3}/api.mli ${plugin3}/api.ml plugin3" +**** script +script = "cp ${plugin4}/plugin.ml ${plugin4}/api.mli ${plugin4}/api.ml plugin4" + +**** cd +cwd = "plugin1" +**** ocamlopt.byte +module = "api.mli" +**** ocamlopt.byte +flags = "-for-pack Packed" +module = "api.ml" +**** ocamlopt.byte +program = "packed.cmx" +flags = "-pack" +all_modules = "api.cmx" +**** ocamlopt.byte +program = "plugin.cmxs" +flags = "-shared" +all_modules = "plugin.ml" +**** cd +cwd = ".." + +**** cd +cwd = "plugin2" +**** ocamlopt.byte +module = "api.mli" +**** ocamlopt.byte +flags = "-for-pack Packed" +module = "api.ml" +**** ocamlopt.byte +program = "packed.cmx" +flags = "-pack" +all_modules = "api.cmx" +**** ocamlopt.byte +program = "plugin.cmxs" +flags = "-shared" +all_modules = "plugin.ml" +*** cd +cwd = ".." + +**** cd +cwd = "plugin3" +**** ocamlopt.byte +module = "api.mli" +**** ocamlopt.byte +flags = "-for-pack Packed" +module = "api.ml" +**** ocamlopt.byte +program = "packed.cmx" +flags = "-pack" +all_modules = "api.cmx" +**** ocamlopt.byte +program = "plugin.cmxs" +flags = "-shared" +all_modules = "packed.cmx plugin.ml" +**** cd +cwd = ".." + +**** cd +cwd = "plugin4" +**** ocamlopt.byte +module = "api.mli" +**** ocamlopt.byte +flags = "-for-pack Packed" +module = "api.ml" +**** ocamlopt.byte +program = "packed.cmx" +flags = "-pack" +all_modules = "api.cmx" +**** ocamlopt.byte +program = "plugin.cmxs" +flags = "-shared" +all_modules = "packed.cmx plugin.ml" +**** cd +cwd = ".." + +**** cd +cwd = "host" +**** ocamlopt.byte +module = "api.mli" +**** ocamlopt.byte +flags = "-for-pack Packed" +module = "api.ml" +**** ocamlopt.byte +program = "packed.cmx" +flags = "-pack" +all_modules = "api.cmx" +**** ocamlopt.byte +program = "./host.exe" +libraries = "dynlink" +all_modules = "packed.cmx host.ml" +***** run +arguments = "../plugin1/plugin.cmxs" +output = "native.plugin1.result" +****** check-program-output +reference = "${test_source_directory}/native.plugin1.reference" +***** run +arguments = "../plugin2/plugin.cmxs" +output = "native.plugin2.result" +****** check-program-output +reference = "${test_source_directory}/native.plugin2.reference" +***** run +arguments = "../plugin3/plugin.cmxs" +output = "native.plugin3.result" +****** check-program-output +reference = "${test_source_directory}/native.plugin3.reference" +***** run +arguments = "../plugin4/plugin.cmxs" +output = "native.plugin4.result" +****** check-program-output +reference = "${test_source_directory}/native.plugin4.reference" +**** cd +cwd = ".." +*) diff --git a/testsuite/tests/lib-dynlink-pr6950/b.ml b/testsuite/tests/lib-dynlink-pr6950/b.ml new file mode 100644 index 00000000..86b4fbf6 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr6950/b.ml @@ -0,0 +1 @@ +let () = Printf.printf "%s\n%s\n" Config.foo Config.bar diff --git a/testsuite/tests/lib-dynlink-pr6950/byte.reference b/testsuite/tests/lib-dynlink-pr6950/byte.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/lib-dynlink-pr6950/config.ml b/testsuite/tests/lib-dynlink-pr6950/config.ml new file mode 100644 index 00000000..251a3b43 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr6950/config.ml @@ -0,0 +1,2 @@ +let foo = "foo" +let bar = "bar" diff --git a/testsuite/tests/lib-dynlink-pr6950/loader.ml b/testsuite/tests/lib-dynlink-pr6950/loader.ml new file mode 100644 index 00000000..ed5c0c25 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr6950/loader.ml @@ -0,0 +1,48 @@ +(* TEST + +include dynlink +libraries = "" +files = "config.ml b.ml" + +* shared-libraries +** setup-ocamlc.byte-build-env +*** ocamlc.byte +program = "plugin.cma" +flags = "-a" +all_modules = "config.ml b.ml" +*** ocamlc.byte +program = "${test_build_directory}/loader.byte" +flags = "-linkall" +include ocamlcommon +libraries += "dynlink" +all_modules = "loader.ml" +**** run +arguments = "plugin.cma" +exit_status = "2" +***** check-program-output +reference = "${test_source_directory}/byte.reference" + +** native-dynlink +*** setup-ocamlopt.byte-build-env +**** ocamlopt.byte +program = "plugin.cmxs" +flags = "-shared" +all_modules = "config.ml b.ml" +**** ocamlopt.byte +program = "${test_build_directory}/loader.exe" +flags = "-linkall" +include ocamlcommon +libraries += "dynlink" +all_modules = "loader.ml" +***** run +arguments = "plugin.cmxs" +exit_status = "2" +****** check-program-output +reference = "${test_source_directory}/native.reference" +*) +let () = + try + Dynlink.loadfile Sys.argv.(1) + with + | Dynlink.Error (Dynlink.Module_already_loaded "Config") -> exit 2 + | _ -> exit 1 diff --git a/testsuite/tests/lib-dynlink-pr6950/native.reference b/testsuite/tests/lib-dynlink-pr6950/native.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/lib-dynlink-pr6950/ocamltests b/testsuite/tests/lib-dynlink-pr6950/ocamltests new file mode 100644 index 00000000..0fe19df0 --- /dev/null +++ b/testsuite/tests/lib-dynlink-pr6950/ocamltests @@ -0,0 +1 @@ +loader.ml diff --git a/testsuite/tests/lib-dynlink-private/ocamltests b/testsuite/tests/lib-dynlink-private/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/lib-dynlink-private/pig.mli b/testsuite/tests/lib-dynlink-private/pig.mli new file mode 100644 index 00000000..795aef97 --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/pig.mli @@ -0,0 +1,4 @@ +type t + +val p : t +val oink : t -> unit diff --git a/testsuite/tests/lib-dynlink-private/plugin1/sheep.ml b/testsuite/tests/lib-dynlink-private/plugin1/sheep.ml new file mode 100644 index 00000000..85296894 --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin1/sheep.ml @@ -0,0 +1,4 @@ +type t = int + +let s = 42 +let baa _t = () [@@inline never] diff --git a/testsuite/tests/lib-dynlink-private/plugin1/sheep.mli b/testsuite/tests/lib-dynlink-private/plugin1/sheep.mli new file mode 100644 index 00000000..faf8d641 --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin1/sheep.mli @@ -0,0 +1,4 @@ +type t + +val s : t +val baa : t -> unit diff --git a/testsuite/tests/lib-dynlink-private/plugin2/cow.ml b/testsuite/tests/lib-dynlink-private/plugin2/cow.ml new file mode 100644 index 00000000..a738a303 --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin2/cow.ml @@ -0,0 +1,4 @@ +type t = int + +let c = 42 +let moo _t = () [@@inline never] diff --git a/testsuite/tests/lib-dynlink-private/plugin2/cow.mli b/testsuite/tests/lib-dynlink-private/plugin2/cow.mli new file mode 100644 index 00000000..11faf4c3 --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin2/cow.mli @@ -0,0 +1,4 @@ +type t + +val c : t +val moo : t -> unit diff --git a/testsuite/tests/lib-dynlink-private/plugin2b/cow.ml b/testsuite/tests/lib-dynlink-private/plugin2b/cow.ml new file mode 100644 index 00000000..185ed568 --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin2b/cow.ml @@ -0,0 +1,4 @@ +type t = int + +let c = 1 +let moo _t = () [@@inline never] diff --git a/testsuite/tests/lib-dynlink-private/plugin2b/cow.mli b/testsuite/tests/lib-dynlink-private/plugin2b/cow.mli new file mode 100644 index 00000000..11faf4c3 --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin2b/cow.mli @@ -0,0 +1,4 @@ +type t + +val c : t +val moo : t -> unit diff --git a/testsuite/tests/lib-dynlink-private/plugin2c/cow.ml b/testsuite/tests/lib-dynlink-private/plugin2c/cow.ml new file mode 100644 index 00000000..f6c10d10 --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin2c/cow.ml @@ -0,0 +1,4 @@ +type t = int + +let d = 4 +let moo _t = () [@@inline never] diff --git a/testsuite/tests/lib-dynlink-private/plugin2c/cow.mli b/testsuite/tests/lib-dynlink-private/plugin2c/cow.mli new file mode 100644 index 00000000..4afb5adc --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin2c/cow.mli @@ -0,0 +1,4 @@ +type t + +val d : t +val moo : t -> unit diff --git a/testsuite/tests/lib-dynlink-private/plugin3/pig.ml b/testsuite/tests/lib-dynlink-private/plugin3/pig.ml new file mode 100644 index 00000000..899a04c6 --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin3/pig.ml @@ -0,0 +1,4 @@ +type t = string + +let p = "oink" +let oink _t = () [@@inline never] diff --git a/testsuite/tests/lib-dynlink-private/plugin3/pig.mli b/testsuite/tests/lib-dynlink-private/plugin3/pig.mli new file mode 100644 index 00000000..795aef97 --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin3/pig.mli @@ -0,0 +1,4 @@ +type t + +val p : t +val oink : t -> unit diff --git a/testsuite/tests/lib-dynlink-private/plugin4/chicken.ml b/testsuite/tests/lib-dynlink-private/plugin4/chicken.ml new file mode 100644 index 00000000..9b06bdad --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin4/chicken.ml @@ -0,0 +1,11 @@ + +(* Test that a privately loaded module can recursively load a module of + the same name *) +let test_chicken () = + if Dynlink.is_native then + Dynlink.loadfile_private "plugin5/chicken.cmxs" + else + Dynlink.loadfile_private "plugin5/chicken.cmo" + +let () = + test_chicken () diff --git a/testsuite/tests/lib-dynlink-private/plugin4/chicken.mli b/testsuite/tests/lib-dynlink-private/plugin4/chicken.mli new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/lib-dynlink-private/plugin5/chicken.ml b/testsuite/tests/lib-dynlink-private/plugin5/chicken.ml new file mode 100644 index 00000000..766e2eb1 --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin5/chicken.ml @@ -0,0 +1,2 @@ + +let x = 5 diff --git a/testsuite/tests/lib-dynlink-private/plugin5/chicken.mli b/testsuite/tests/lib-dynlink-private/plugin5/chicken.mli new file mode 100644 index 00000000..b356381d --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin5/chicken.mli @@ -0,0 +1,2 @@ + +val x : int diff --git a/testsuite/tests/lib-dynlink-private/plugin6/partridge.ml b/testsuite/tests/lib-dynlink-private/plugin6/partridge.ml new file mode 100644 index 00000000..0469149d --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin6/partridge.ml @@ -0,0 +1 @@ +let wings = 2 diff --git a/testsuite/tests/lib-dynlink-private/plugin6/partridge.mli b/testsuite/tests/lib-dynlink-private/plugin6/partridge.mli new file mode 100644 index 00000000..62407164 --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin6/partridge.mli @@ -0,0 +1 @@ +val wings : int diff --git a/testsuite/tests/lib-dynlink-private/plugin6/pheasant.ml b/testsuite/tests/lib-dynlink-private/plugin6/pheasant.ml new file mode 100644 index 00000000..2adb24dd --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/plugin6/pheasant.ml @@ -0,0 +1,10 @@ +(* See comment in the main "test.ml" file. *) + +let test_pheasant () = + if Dynlink.is_native then + Dynlink.loadfile "plugin6/partridge.cmxs" + else + Dynlink.loadfile "plugin6/partridge.cmo" + +let () = + test_pheasant () diff --git a/testsuite/tests/lib-dynlink-private/plugin6/pheasant.mli b/testsuite/tests/lib-dynlink-private/plugin6/pheasant.mli new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/lib-dynlink-private/sheep.ml b/testsuite/tests/lib-dynlink-private/sheep.ml new file mode 100644 index 00000000..98d0b7ba --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/sheep.ml @@ -0,0 +1,4 @@ +type t = string + +let s = "baa" +let baa _t = () [@@inline never] diff --git a/testsuite/tests/lib-dynlink-private/sheep.mli b/testsuite/tests/lib-dynlink-private/sheep.mli new file mode 100644 index 00000000..faf8d641 --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/sheep.mli @@ -0,0 +1,4 @@ +type t + +val s : t +val baa : t -> unit diff --git a/testsuite/tests/lib-dynlink-private/test.ml b/testsuite/tests/lib-dynlink-private/test.ml new file mode 100644 index 00000000..7181c5d1 --- /dev/null +++ b/testsuite/tests/lib-dynlink-private/test.ml @@ -0,0 +1,272 @@ +(* TEST + +include dynlink +libraries = "" +files = "sheep.mli sheep.ml pig.mli" +set plugin1 = "${test_source_directory}/plugin1" +set plugin2 = "${test_source_directory}/plugin2" +set plugin2b = "${test_source_directory}/plugin2b" +set plugin2c = "${test_source_directory}/plugin2c" +set plugin3 = "${test_source_directory}/plugin3" +set plugin4 = "${test_source_directory}/plugin4" +set plugin5 = "${test_source_directory}/plugin5" +set plugin6 = "${test_source_directory}/plugin6" + +* shared-libraries +** setup-ocamlc.byte-build-env +*** ocamlc.byte +module = "sheep.mli" +**** ocamlc.byte +module = "sheep.ml" +***** ocamlc.byte +module = "pig.mli" +****** ocamlc.byte +module = "test.ml" +*** script +script = "mkdir plugin1 plugin2 plugin2b plugin2c plugin3 plugin4 plugin5 plugin6" +**** script +script = "cp ${plugin1}/sheep.mli ${plugin1}/sheep.ml plugin1" +**** script +script = "cp ${plugin2}/cow.mli ${plugin2}/cow.ml plugin2" +**** script +script = "cp ${plugin2b}/cow.mli ${plugin2b}/cow.ml plugin2b" +**** script +script = "cp ${plugin2c}/cow.mli ${plugin2c}/cow.ml plugin2c" +**** script +script = "cp ${plugin3}/pig.mli ${plugin3}/pig.ml plugin3" +**** script +script = "cp ${plugin4}/chicken.mli ${plugin4}/chicken.ml plugin4" +**** script +script = "cp ${plugin5}/chicken.mli ${plugin5}/chicken.ml plugin5" +**** script +script = "cp ${plugin6}/pheasant.mli ${plugin6}/pheasant.ml ${plugin6}/partridge.mli ${plugin6}/partridge.ml plugin6" +***** ocamlc.byte +module = "plugin1/sheep.mli" +***** ocamlc.byte +flags = "-I plugin1" +module = "plugin1/sheep.ml" +***** ocamlc.byte +module = "plugin2/cow.mli" +***** ocamlc.byte +flags = "-I plugin2" +module = "plugin2/cow.ml" +***** ocamlc.byte +module = "plugin2b/cow.mli" +***** ocamlc.byte +flags = "-I plugin2b" +module = "plugin2b/cow.ml" +***** ocamlc.byte +module = "plugin2c/cow.mli" +***** ocamlc.byte +flags = "-I plugin2c" +module = "plugin2c/cow.ml" +***** ocamlc.byte +module = "plugin3/pig.mli" +***** ocamlc.byte +flags = "-I plugin3" +module = "plugin3/pig.ml" +***** ocamlc.byte +module = "plugin4/chicken.mli" +***** ocamlc.byte +flags = "-I plugin4" +module = "plugin4/chicken.ml" +***** ocamlc.byte +module = "plugin5/chicken.mli" +***** ocamlc.byte +flags = "-I plugin5" +module = "plugin5/chicken.ml" +***** ocamlc.byte +module = "plugin6/pheasant.mli" +***** ocamlc.byte +flags = "-I plugin6" +module = "plugin6/pheasant.ml" +***** ocamlc.byte +module = "plugin6/partridge.mli" +***** ocamlc.byte +flags = "-I plugin6" +module = "plugin6/partridge.ml" +***** ocamlc.byte +program = "${test_build_directory}/test.byte" +libraries = "dynlink" +all_modules = "sheep.cmo test.cmo" +****** run + +** native-dynlink +*** setup-ocamlopt.byte-build-env +**** ocamlopt.byte +module = "sheep.mli" +***** ocamlopt.byte +module = "sheep.ml" +****** ocamlopt.byte +module = "pig.mli" +******* ocamlopt.byte +module = "test.ml" +**** script +script = "mkdir plugin1 plugin2 plugin2b plugin2c plugin3 plugin4 plugin5 plugin6" +***** script +script = "cp ${plugin1}/sheep.mli ${plugin1}/sheep.ml plugin1" +***** script +script = "cp ${plugin2}/cow.mli ${plugin2}/cow.ml plugin2" +***** script +script = "cp ${plugin2b}/cow.mli ${plugin2b}/cow.ml plugin2b" +***** script +script = "cp ${plugin2c}/cow.mli ${plugin2c}/cow.ml plugin2c" +***** script +script = "cp ${plugin3}/pig.mli ${plugin3}/pig.ml plugin3" +***** script +script = "cp ${plugin4}/chicken.mli ${plugin4}/chicken.ml plugin4" +***** script +script = "cp ${plugin5}/chicken.mli ${plugin5}/chicken.ml plugin5" +***** script +script = "cp ${plugin6}/pheasant.mli ${plugin6}/pheasant.ml ${plugin6}/partridge.mli ${plugin6}/partridge.ml plugin6" +****** ocamlopt.byte +module = "plugin1/sheep.mli" +****** ocamlopt.byte +program = "plugin1/sheep.cmxs" +flags = "-I plugin1 -shared" +all_modules = "plugin1/sheep.ml" +****** ocamlopt.byte +module = "plugin2/cow.mli" +****** ocamlopt.byte +program = "plugin2/cow.cmxs" +flags = "-I plugin2 -shared" +all_modules = "plugin2/cow.ml" +****** ocamlopt.byte +module = "plugin2b/cow.mli" +****** ocamlopt.byte +program = "plugin2b/cow.cmxs" +flags = "-I plugin2b -shared" +all_modules = "plugin2b/cow.ml" +****** ocamlopt.byte +module = "plugin2c/cow.mli" +****** ocamlopt.byte +program = "plugin2c/cow.cmxs" +flags = "-I plugin2c -shared" +all_modules = "plugin2c/cow.ml" +****** ocamlopt.byte +module = "plugin3/pig.mli" +****** ocamlopt.byte +program = "plugin3/pig.cmxs" +flags = "-I plugin3 -shared" +all_modules = "plugin3/pig.ml" +****** ocamlopt.byte +module = "plugin4/chicken.mli" +****** ocamlopt.byte +program = "plugin4/chicken.cmxs" +flags = "-I plugin4 -shared" +all_modules = "plugin4/chicken.ml" +****** ocamlopt.byte +module = "plugin5/chicken.mli" +****** ocamlopt.byte +program = "plugin5/chicken.cmxs" +flags = "-I plugin5 -shared" +all_modules = "plugin5/chicken.ml" +****** ocamlopt.byte +module = "plugin6/pheasant.mli" +****** ocamlopt.byte +program = "plugin6/pheasant.cmxs" +flags = "-I plugin6 -shared" +all_modules = "plugin6/pheasant.ml" +****** ocamlopt.byte +module = "plugin6/partridge.mli" +****** ocamlopt.byte +program = "plugin6/partridge.cmxs" +flags = "-I plugin6 -shared" +all_modules = "plugin6/partridge.ml" +****** ocamlopt.byte +program = "${test_build_directory}/test.exe" +libraries = "dynlink" +all_modules = "sheep.cmx test.cmx" +******* run +*) + +let () = Sheep.baa Sheep.s (* Use Sheep module *) +let _ = fun (x : Pig.t) -> x (* Reference Pig module *) + +(* Test that a privately loaded module cannot have the same name as a + module in the program. *) +let test_sheep () = + match + if Dynlink.is_native then + Dynlink.loadfile_private "plugin1/sheep.cmxs" + else + Dynlink.loadfile_private "plugin1/sheep.cmo" + with + | () -> assert false + | exception Dynlink.Error ( + Dynlink.Module_already_loaded "Sheep") -> () + +(* Test repeated loading of a privately-loaded module. *) +let test_cow_repeated () = + if Dynlink.is_native then + Dynlink.loadfile_private "plugin2/cow.cmxs" + else + Dynlink.loadfile_private "plugin2/cow.cmo" + +(* Test that a privately loaded module can have the same name as a + previous privately loaded module, in the case where the interfaces are + the same, but the implementations differ. *) +let test_cow_same_name_same_mli () = + if Dynlink.is_native then + Dynlink.loadfile_private "plugin2b/cow.cmxs" + else + Dynlink.loadfile_private "plugin2b/cow.cmo" + +(* Test that a privately loaded module can have the same name as a + previous privately loaded module, in the case where neither the interfaces + nor the implementations are the same. *) +let test_cow_same_name_different_mli () = + if Dynlink.is_native then + Dynlink.loadfile_private "plugin2c/cow.cmxs" + else + Dynlink.loadfile_private "plugin2c/cow.cmo" + +(* Test that a privately loaded module cannot have the same name as an + interface depended on by modules the program. *) +let test_pig () = + match + if Dynlink.is_native then + Dynlink.loadfile_private "plugin3/pig.cmxs" + else + Dynlink.loadfile_private "plugin3/pig.cmo" + with + | () -> assert false + | exception Dynlink.Error ( + Dynlink.Private_library_cannot_implement_interface "Pig") -> () + +(* Test that a privately loaded module can recursively load a module of + the same name. *) +let test_chicken () = + if Dynlink.is_native then + Dynlink.loadfile_private "plugin4/chicken.cmxs" + else + Dynlink.loadfile_private "plugin4/chicken.cmo" + +(* Test that a public load of a module M inside a privately-loaded module, + followed by a public load of M, causes an error. *) +let test_pheasant () = + begin + if Dynlink.is_native then + Dynlink.loadfile_private "plugin6/pheasant.cmxs" + else + Dynlink.loadfile_private "plugin6/pheasant.cmo" + end; + match + if Dynlink.is_native then + Dynlink.loadfile "plugin6/partridge.cmxs" + else + Dynlink.loadfile "plugin6/partridge.cmo" + with + | () -> assert false + | exception Dynlink.Error ( + Dynlink.Module_already_loaded "Partridge") -> () + +let () = + test_sheep (); + test_cow_repeated (); + test_cow_repeated (); + test_cow_same_name_same_mli (); + test_cow_same_name_different_mli (); + test_pig (); + test_chicken (); + test_pheasant () diff --git a/testsuite/tests/lib-filename/ocamltests b/testsuite/tests/lib-filename/ocamltests index 8615801f..ed4fe5cb 100644 --- a/testsuite/tests/lib-filename/ocamltests +++ b/testsuite/tests/lib-filename/ocamltests @@ -1 +1,2 @@ extension.ml +suffix.ml diff --git a/testsuite/tests/lib-filename/suffix.ml b/testsuite/tests/lib-filename/suffix.ml new file mode 100755 index 00000000..3faa5c94 --- /dev/null +++ b/testsuite/tests/lib-filename/suffix.ml @@ -0,0 +1,27 @@ +(* TEST +*) + +let () = + let test ~suffix name exp = + let r1 = Filename.chop_suffix_opt ~suffix name <> None in + let r2 = Filename.check_suffix name suffix in + assert (r1 = r2); + assert (r1 = exp) + in + let full_test ~suffix name = + test ~suffix name true; + match Filename.chop_suffix_opt ~suffix name with + | None -> assert false + | Some base -> assert (base ^ suffix = name) + in + let win32 = Sys.os_type = "Win32" || Sys.os_type = "Cygwin" in + full_test ~suffix:".txt" "foo.txt"; + full_test ~suffix:"txt" "foo.txt"; + full_test ~suffix:"" "foo.txt"; + full_test ~suffix:"" ""; + test ~suffix:".txt" "f" false; + test ~suffix:".txt" "" false; + test ~suffix:".txt" "foo.txt.bak" false; + test ~suffix:".txt" "foo.TXT" win32; + if win32 then + assert (Filename.chop_suffix_opt ~suffix:".txt" "foo.TXT" = Some "foo") diff --git a/testsuite/tests/lib-filename/suffix.reference b/testsuite/tests/lib-filename/suffix.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/lib-float/ocamltests b/testsuite/tests/lib-float/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/lib-float/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/lib-float/test.ml b/testsuite/tests/lib-float/test.ml new file mode 100644 index 00000000..10734a49 --- /dev/null +++ b/testsuite/tests/lib-float/test.ml @@ -0,0 +1,119 @@ +(* TEST +*) + +let () = + assert(Float.is_finite 1.); + assert(Float.is_finite Float.pi); + assert(not(Float.is_finite Float.infinity)); + assert(not(Float.is_finite Float.nan)); + assert(Float.is_infinite Float.infinity); + assert(not(Float.is_infinite 1.)); + assert(not(Float.is_infinite Float.nan)); + assert(Float.is_nan Float.nan); + assert(not(Float.is_nan 1.)); + assert(not(Float.is_nan neg_infinity)); + assert(Float.is_integer 1.); + assert(Float.is_integer (-1e10)); + assert(not(Float.is_integer 1.5)); + assert(not(Float.is_integer Float.infinity)); + assert(not(Float.is_integer Float.nan)); + + assert(Float.trunc 1.5 = 1.); + assert(Float.trunc (-1.5) = -1.); + assert(Float.(trunc infinity = infinity)); + assert(Float.(trunc neg_infinity = neg_infinity)); + assert(Float.(is_nan(trunc nan))); + + assert(Float.round 0.5 = 1.); + assert(Float.round (-0.5) = -1.); + assert(Float.round 1.5 = 2.); + assert(Float.round (-1.5) = -2.); + assert(let x = 0x1.0000000000001p52 in (* x + 0.5 rounds to x +. 1. *) + Float.round x = x); + assert(Float.round (Float.next_after 0.5 0.) = 0.); + + assert(Float.(round infinity = infinity)); + assert(Float.(round neg_infinity = neg_infinity)); + assert(Float.(is_nan(round nan))); + + assert(Float.next_after 0x1.FFFFFFFFFFFFFp-2 1. = 0.5); + assert(Float.next_after 0x1.FFFFFFFFFFFFFp-2 0. = 0x1.FFFFFFFFFFFFEp-2); + assert(Float.(next_after 0x1.FFFFFFFFFFFFFp-2 infinity = 0.5)); + assert(Float.(next_after 0x1.FFFFFFFFFFFFFp-2 neg_infinity + = 0x1.FFFFFFFFFFFFEp-2)); + assert(Float.next_after 1. 1. = 1.); + assert(Float.(is_nan(next_after nan 1.))); + assert(Float.(is_nan(next_after 3. nan))); + + assert(Float.(succ 0x1.FFFFFFFFFFFFFp-2 = 0.5)); + assert(Float.(pred 0.5 = 0x1.FFFFFFFFFFFFFp-2)); + assert(Float.(succ 0. > 0.)); + assert(Float.(pred 0. < 0.)); + assert(Float.(succ max_float = infinity)); + assert(Float.(pred (-. max_float) = neg_infinity)); + assert(Float.(succ 0. < min_float)); + assert(Float.(succ infinity = infinity)); + assert(Float.(pred neg_infinity = neg_infinity)); + assert(Float.(is_nan(succ nan))); + assert(Float.(is_nan(pred nan))); + + assert(not(Float.sign_bit 1.)); + assert(Float.sign_bit (-1.)); + assert(not(Float.sign_bit 0.)); + assert(Float.sign_bit (-0.)); + assert(not(Float.sign_bit infinity)); + assert(Float.sign_bit neg_infinity); + + assert(Float.min 1. 2. = 1.); + assert(Float.min 2. 1. = 1.); + assert(Float.(is_nan(min 1. nan))); + assert(Float.(is_nan(min nan 2.))); + assert(Float.(is_nan(min nan nan))); + assert(1. /. Float.min (-0.) (+0.) = neg_infinity); + assert(1. /. Float.min (+0.) (-0.) = neg_infinity); + + assert(Float.max 1. 2. = 2.); + assert(Float.max 2. 1. = 2.); + assert(Float.(is_nan(max 1. nan))); + assert(Float.(is_nan(max nan 2.))); + assert(Float.(is_nan(max nan nan))); + assert(1. /. Float.max (-0.) (+0.) = infinity); + assert(1. /. Float.max (+0.) (-0.) = infinity); + + assert(Float.min_max 1. 2. = (1., 2.)); + assert(Float.min_max 2. 1. = (1., 2.)); + let is_nan2 (x, y) = Float.is_nan x && Float.is_nan y in + assert(Float.(is_nan2(min_max 1. nan))); + assert(Float.(is_nan2(min_max nan 2.))); + assert(Float.(is_nan2(min_max nan nan))); + assert(let x, y = Float.min_max (-0.) (+0.) in + 1. /. x = neg_infinity && 1. /. y = infinity); + assert(let x, y = Float.min_max (+0.) (-0.) in + 1. /. x = neg_infinity && 1. /. y = infinity); + + assert(Float.min_num 1. 2. = 1.); + assert(Float.(min_num 1. nan = 1.)); + assert(Float.(min_num nan 2. = 2.)); + assert(Float.(is_nan(min_num nan nan))); + assert(1. /. Float.min_num (-0.) (+0.) = neg_infinity); + assert(1. /. Float.min_num (+0.) (-0.) = neg_infinity); + + assert(Float.max_num 1. 2. = 2.); + assert(Float.(max_num 1. nan = 1.)); + assert(Float.(max_num nan 2. = 2.)); + assert(Float.(is_nan(max_num nan nan))); + assert(1. /. Float.max_num (-0.) (+0.) = infinity); + assert(1. /. Float.max_num (+0.) (-0.) = infinity); + + assert(Float.min_max_num 1. 2. = (1., 2.)); + assert(Float.min_max_num 2. 1. = (1., 2.)); + assert(Float.min_max_num 1. nan = (1., 1.)); + assert(Float.min_max_num nan 1. = (1., 1.)); + assert(Float.(is_nan2(min_max_num nan nan))); + assert(let x, y = Float.min_max_num (-0.) (+0.) in + 1. /. x = neg_infinity && 1. /. y = infinity); + assert(let x, y = Float.min_max_num (+0.) (-0.) in + 1. /. x = neg_infinity && 1. /. y = infinity); +;; + +let () = print_endline "OK" diff --git a/testsuite/tests/lib-float/test.reference b/testsuite/tests/lib-float/test.reference new file mode 100644 index 00000000..d86bac9d --- /dev/null +++ b/testsuite/tests/lib-float/test.reference @@ -0,0 +1 @@ +OK diff --git a/testsuite/tests/lib-floatarray/floatarray.ml b/testsuite/tests/lib-floatarray/floatarray.ml new file mode 100644 index 00000000..7c0434f7 --- /dev/null +++ b/testsuite/tests/lib-floatarray/floatarray.ml @@ -0,0 +1,528 @@ +(* TEST +*) + +open Printf + +(* This is the module type of [Float.Array] except type [t] is abstract. *) +module type S = sig + type t + val length : t -> int + val get : t -> int -> float + val set : t -> int -> float -> unit + val make : int -> float -> t + val create : int -> t + val init : int -> (int -> float) -> t + val append : t -> t -> t + val concat : t list -> t + val sub : t -> int -> int -> t + val copy : t -> t + val fill : t -> int -> int -> float -> unit + val blit : t -> int -> t -> int -> int -> unit + val to_list : t -> float list + val of_list : float list -> t + val iter : (float -> unit) -> t -> unit + val iteri : (int -> float -> unit) -> t -> unit + val map : (float -> float) -> t -> t + val mapi : (int -> float -> float) -> t -> t + val fold_left : ('a -> float -> 'a) -> 'a -> t -> 'a + val fold_right : (float -> 'a -> 'a) -> t -> 'a -> 'a + val iter2 : (float -> float -> unit) -> t -> t -> unit + val map2 : (float -> float -> float) -> t -> t -> t + val for_all : (float -> bool) -> t -> bool + val exists : (float -> bool) -> t -> bool + val mem : float -> t -> bool + val mem_ieee : float -> t -> bool + val sort : (float -> float -> int) -> t -> unit + val stable_sort : (float -> float -> int) -> t -> unit + val fast_sort : (float -> float -> int) -> t -> unit + val to_seq : t -> float Seq.t + val to_seqi : t -> (int * float) Seq.t + val of_seq : float Seq.t -> t + val map_to_array : (float -> 'a) -> t -> 'a array + val map_from_array : ('a -> float) -> 'a array -> t + val unsafe_get : t -> int -> float + val unsafe_set : t -> int -> float -> unit +end + +(* module [Array] specialized to [float] and with a few changes, + satisfies signature S *) +module Float_array : S = struct + include Stdlib.Array + let create = create_float + let map_to_array f a = map f a + let map_from_array f a = map f a + let mem_ieee x a = exists ((=) x) a + type t = float array +end + +module Test (A : S) : sig end = struct + + (* auxiliary functions *) + + let neg_zero = 1.0 /. neg_infinity in + + let rec check_i_upto a i = + if i >= 0 then begin + assert (A.get a i = Float.of_int i); + check_i_upto a (i - 1); + end + in + + let check_i a = check_i_upto a (A.length a - 1) in + + let check_inval f arg = + match f arg with + | _ -> assert false + | exception (Invalid_argument _) -> () + | exception _ -> assert false + in + + (* [make] [set] [get] *) + let a = A.make 1000 1.0 in + for i = 0 to 499 do A.set a i (Float.of_int i) done; + let rec loop i = + if i >= 0 then begin + assert (A.get a i = (if i < 500 then Float.of_int i else 1.0)); + loop (i - 1); + end + in loop 999; + check_inval (A.get a) (-1); + check_inval (A.get a) (1000); + check_inval (fun i -> A.set a i 1.0) (-1); + check_inval (fun i -> A.set a i 1.0) 1000; + check_inval A.create (-1); + check_inval A.create (Sys.max_floatarray_length + 1); + check_inval (fun i -> A.make i 1.0) (-1); + check_inval (fun i -> A.make i 1.0) (Sys.max_floatarray_length + 1); + + (* [length] *) + let test_length l = assert (l = (A.length (A.create l))) in + test_length 0; + test_length 10; + test_length 25; + test_length 255; + test_length 256; + test_length 1000; + test_length 123456; + + (* [init] *) + let a = A.init 1000 Float.of_int in + check_i a; + check_inval (fun i -> A.init i Float.of_int) (-1); + check_inval (fun i -> A.init i Float.of_int) (Sys.max_floatarray_length + 1); + + (* [append] *) + let check m n = + let a = A.init m Float.of_int in + let b = A.init n (fun x -> Float.of_int (x + m)) in + let c = A.append a b in + assert (A.length c = (m + n)); + check_i c; + in + check 0 0; + check 0 100; + check 1 100; + check 100 0; + check 100 1; + check 100 100; + check 1000 1000; + (* check_inval omitted *) + + (* [concat] *) + let check l = + let f (len, acc) n = + (len + n, A.init n (fun i -> Float.of_int (len + i)) :: acc) + in + let (total, ll) = List.fold_left f (0, []) l in + let b = A.concat (List.rev ll) in + assert (A.length b = total); + check_i b; + in + check [0; 0; 0]; + check [1; 10; 100]; + check [10; 0]; + check [0]; + check [1000; 1000; 1000]; + check []; + (* check_inval omitted *) + + (* [sub] *) + let a = A.init 1000 (fun i -> Float.of_int (i - 100)) in + let b = A.sub a 100 200 in + check_i b; + assert (A.length b = 200); + let b = A.sub a 1000 0 in + check_i (A.sub a 1000 0); + assert (A.length b = 0); + check_inval (A.sub a (-1)) 0; + check_inval (A.sub a 0) (-1); + check_inval (A.sub a 0) 1001; + check_inval (A.sub a 1000) 1; + + (* [copy] *) + let check len = + let a = A.init len Float.of_int in + let b = A.copy a in + check_i b; + assert (A.length b = len); + in + check 0; + check 1; + check 128; + check 1023; + + (* [blit] [fill] *) + let test_blit_fill data initval ofs len = + let a = A.of_list data in + let b = A.create (List.length data) in + A.blit a 0 b 0 (A.length b); + assert (a = b); + A.fill b ofs len initval; + let rec check i = function + | [] -> () + | hd :: tl -> + assert (A.get b i = (if i >= ofs && i < ofs + len + then initval else hd)); + check (i + 1) tl; + in + check 0 data + in + test_blit_fill [1.0;2.0;5.0;8.123;-100.456;212e19] 3.1415 3 2; + let a = A.create 100 in + check_inval (A.fill a (-1) 0) 1.0; + check_inval (A.fill a 0 (-1)) 1.0; + check_inval (A.fill a 0 101) 1.0; + check_inval (A.fill a 100 1) 1.0; + check_inval (A.fill a 101 0) 1.0; + check_inval (A.blit a (-1) a 0) 0; + check_inval (A.blit a 0 a 0) (-1); + check_inval (A.blit a 0 a 0) 101; + check_inval (A.blit a 100 a 0) 1; + check_inval (A.blit a 101 a 0) 0; + check_inval (A.blit a 0 a (-1)) 0; + check_inval (A.blit a 0 a 100) 1; + check_inval (A.blit a 0 a 101) 0; + + (* [to_list] [of_list] *) + let a = A.init 1000 Float.of_int in + assert (compare a (A.of_list (A.to_list a)) = 0); + let a = A.init 0 Float.of_int in + assert (compare a (A.of_list (A.to_list a)) = 0); + (* check_inval omitted *) + + (* [iter] *) + let a = A.init 300 (Float.of_int) in + let r = ref 0.0 in + A.iter (fun x -> assert (x = !r); r := x +. 1.0) a; + A.iter (fun _ -> assert false) (A.create 0); + assert (!r = 300.0); + + (* [iteri] *) + let a = A.init 300 Float.of_int in + let r = ref 0 in + let f i x = + assert (i = !r); + assert (x = Float.of_int i); + r := i + 1 + in + A.iteri f a; + A.iteri (fun _ _ -> assert false) (A.create 0); + assert (!r = 300); + + (* [map], test result and order of evaluation *) + let a = A.init 500 Float.of_int in + let r = ref 0.0 in + let f x = + assert (x = !r); + r := !r +. 1.0; + x -. 1.0 + in + let b = A.map f a in + check_i (A.sub b 1 499); + + (* [mapi], test result and order of evaluation *) + let a = A.init 500 Float.of_int in + let r = ref 0.0 in + let f i x = + assert (x = Float.of_int i); + assert (x = !r); + r := !r +. 1.0; + x -. 1.0 + in + let b = A.mapi f a in + check_i (A.sub b 1 499); + + (* [fold_left], test result and order of evaluation *) + let a = A.init 500 Float.of_int in + let f acc x = + assert (acc = x); + x +. 1.0 + in + let acc = A.fold_left f 0.0 a in + assert (acc = 500.0); + + (* [fold_right], test result and order of evaluation *) + let a = A.init 500 Float.of_int in + let f x acc = + assert (x = acc -. 1.0); + x + in + let acc = A.fold_right f a 500.0 in + assert (acc = 0.0); + + (* [iter2], test result and order of evaluation *) + let a = A.init 123 Float.of_int in + let b = A.init 123 Float.of_int in + let r = ref 0.0 in + let f x y = + assert (x = !r); + assert (y = !r); + r := !r +. 1.0; + in + A.iter2 f a b; + let c = A.create 456 in + check_inval (A.iter2 (fun _ _ -> assert false) a) c; + check_inval (A.iter2 (fun _ _ -> assert false) c) a; + + (* [map2], test result and order of evaluation *) + let a = A.init 456 Float.of_int in + let b = A.init 456 (fun i -> Float.of_int i /. 2.0) in + let r = ref 0.0 in + let f x y = + assert (x = !r); + assert (y = !r /. 2.0); + r := !r +. 1.0; + 2.0 *. (x -. y) + in + let c = A.map2 f a b in + check_i c; + let d = A.create 455 in + check_inval (A.map2 (fun _ _ -> assert false) a) d; + check_inval (A.map2 (fun _ _ -> assert false) d) a; + + (* [for_all], test result and order of evaluation *) + let a = A.init 777 Float.of_int in + let r = ref 0.0 in + let f x = + assert (x = !r); + r := x +. 1.0; + true + in + assert (A.for_all f a); + let f x = assert (x = 0.0); false in + assert (not (A.for_all f a)); + + (* [exists], test result and order of evaluation *) + let a = A.init 777 Float.of_int in + let r = ref 0.0 in + let f x = + assert (x = !r); + r := x +. 1.0; + false + in + assert (not (A.exists f a)); + let f x = assert (x = 0.0); true in + assert (A.exists f a); + + (* [mem] *) + let a = A.init 7777 Float.of_int in + assert (A.mem 0.0 a); + assert (A.mem 7776.0 a); + assert (not (A.mem (-1.0) a)); + assert (not (A.mem 7777.0 a)); + let check v = + A.set a 1000 v; + assert (A.mem v a); + in + List.iter check [infinity; neg_infinity; neg_zero; nan]; + + (* [mem_ieee] *) + let a = A.init 7777 Float.of_int in + assert (A.mem_ieee 0.0 a); + assert (A.mem_ieee 7776.0 a); + assert (not (A.mem_ieee (-1.0) a)); + assert (not (A.mem_ieee 7777.0 a)); + let check v = + A.set a 1000 v; + assert (A.mem_ieee v a); + in + List.iter check [infinity; neg_infinity; neg_zero]; + A.set a 0 nan; + assert (not (A.mem_ieee nan a)); + + (* [sort] [fast_sort] [stable_sort] *) + let check_sort sort cmp a = + let rec check_sorted a i = + if i + 1 < A.length a then begin + assert (cmp (A.get a i) (A.get a (i + 1)) <= 0); + check_sorted a (i + 1); + end + in + let rec check_permutation a b i = + let p = Array.make (A.length a) true in + let rec find lo hi x = + assert (lo < hi); + if hi = lo + 1 then begin + assert (cmp (A.get a lo) x = 0); + assert (p.(lo)); + p.(lo) <- false; + end else begin + let mid = (lo + hi) / 2 in + assert (lo < mid && mid < hi); + match cmp (A.get a (mid - 1)) x with + | 0 when p.(mid - 1) -> find lo mid x + | 0 -> find mid hi x + | c when c < 0 -> find mid hi x + | c when c > 0 -> find lo mid x + | _ -> assert false + end + in + A.iter (find 0 (A.length a)) b + in + let b = A.copy a in + sort cmp a; + check_sorted a 0; + check_permutation a b 0; + in + Random.init 123; + let rand_float _ = + match Random.int 1004 with + | 1000 -> nan + | 1001 -> infinity + | 1002 -> neg_infinity + | 1003 -> neg_zero + | n when n < 500 -> Random.float 1.0 + | _ -> -. Random.float 1.0 + in + let check s = + let a = A.init 5 Float.of_int in + check_sort s Stdlib.compare a; (* already sorted *) + check_sort s (fun x y -> Stdlib.compare y x) a; (* reverse-sorted *) + + let a = A.of_list [nan; neg_infinity; neg_zero; 0.; infinity] in + check_sort s Stdlib.compare a; (* already sorted *) + check_sort s (fun x y -> Stdlib.compare y x) a; (* reverse-sorted *) + + let a = A.init 50000 rand_float in + check_sort s Stdlib.compare a; + let a = A.make 1000 1.0 in + check_sort s Stdlib.compare a; + let a = A.append (A.make 1000 1.0) (A.make 1000 2.0) in + check_sort s Stdlib.compare a; + in + check A.sort; + check A.stable_sort; + check A.fast_sort; + + (* [to_seq] *) + let check_seq a = + let r = ref 0 in + let f x = + assert (A.get a !r = x); + r := !r + 1; + in + let s = A.to_seq a in + Seq.iter f s; + in + check_seq (A.init 999 Float.of_int); + check_seq (A.create 0); + + (* [to_seqi] *) + let check_seqi a = + let r = ref 0 in + let f (i, x) = + assert (i = !r); + assert (A.get a !r = x); + r := !r + 1; + in + let s = A.to_seqi a in + Seq.iter f s; + in + check_seqi (A.init 999 Float.of_int); + check_seqi (A.create 0); + + (* [of_seq] *) + let r = ref 0 in + let rec f () = + if !r = 100 then Seq.Nil else begin + let res = Seq.Cons (Float.of_int !r, f) in + r := !r + 1; + res + end + in + let a = A.of_seq f in + assert (a = A.init 100 Float.of_int); + assert (A.of_seq Seq.empty = A.create 0); + + (* [map_to_array] *) + let r = ref 0 in + let f x = + assert (x = Float.of_int !r); + r := !r + 1; + x *. 2.0 + in + let a = A.init 876 Float.of_int in + let ar1 = A.map_to_array f a in + let ar2 = Array.init 876 (fun x -> Float.of_int (2 * x)) in + assert (ar1 = ar2); + let ar = A.map_to_array (fun _ -> assert false) (A.create 0) in + assert (ar = [| |]); + + (* [map_from_array] *) + let r = ref 0 in + let f x = + assert (x = Float.of_int !r); + r := !r + 1; + x *. 2.0 + in + let ar = Array.init 876 Float.of_int in + let a1 = A.map_from_array f ar in + let a2 = A.init 876 (fun x -> Float.of_int (2 * x)) in + assert (a1 = a2); + let a = A.map_from_array (fun _ -> assert false) [| |] in + assert (a = A.create 0); + + (* comparisons *) + let normalize_comparison n = + if n = 0 then 0 else if n < 0 then -1 else 1 + in + let check c l1 l2 = + assert (c = (normalize_comparison (compare (A.of_list l1) (A.of_list l2)))) + in + check 0 [0.0; 0.25; -4.0; 3.141592654; nan] + [0.0; 0.25; -4.0; 3.141592654; nan]; + check (-1) [0.0; 0.25; nan] + [0.0; 0.25; 3.14]; + check (-1) [0.0; 0.25; -4.0] + [0.0; 0.25; 3.14159]; + check 1 [0.0; 2.718; -4.0] + [0.0; 0.25; 3.14159]; + check 1 [0.0; 2.718; -4.0] + [nan; 0.25; 3.14159]; + + (* [unsafe_get] [unsafe_set] *) + let a = A.create 3 in + for i = 0 to 2 do A.unsafe_set a i (float i) done; + for i = 0 to 2 do assert (A.unsafe_get a i = float i) done; + + (* I/O *) + let test_structured_io value = + let (tmp, oc) = + Filename.open_temp_file ~mode:[Open_binary] "floatarray" ".data" + in + Marshal.to_channel oc value []; + close_out oc; + let ic = open_in_bin tmp in + let value' = Marshal.from_channel ic in + close_in ic; + Sys.remove tmp; + assert (compare value value' = 0) + in + let l = [0.; 0.25; -4.; 3.14159265; nan; infinity; neg_infinity; neg_zero] in + test_structured_io (A.of_list l); + +end + +(* We run the same tests on [Float.Array] and [Array]. *) +module T1 = Test (Stdlib.Float.Array) +module T2 = Test (Float_array) diff --git a/testsuite/tests/lib-floatarray/ocamltests b/testsuite/tests/lib-floatarray/ocamltests new file mode 100644 index 00000000..abf19023 --- /dev/null +++ b/testsuite/tests/lib-floatarray/ocamltests @@ -0,0 +1 @@ +floatarray.ml diff --git a/testsuite/tests/lib-format/ocamltests b/testsuite/tests/lib-format/ocamltests index 9e3d6f21..414bc603 100644 --- a/testsuite/tests/lib-format/ocamltests +++ b/testsuite/tests/lib-format/ocamltests @@ -1,2 +1,4 @@ pr6824.ml tformat.ml +print_if_newline.ml +pp_print_custom_break.ml diff --git a/testsuite/tests/lib-format/pp_print_custom_break.ml b/testsuite/tests/lib-format/pp_print_custom_break.ml new file mode 100644 index 00000000..82065a5a --- /dev/null +++ b/testsuite/tests/lib-format/pp_print_custom_break.ml @@ -0,0 +1,64 @@ +(* TEST *) + +(* + +A test file for Format.pp_print_custom_break. + +*) +let fprintf, printf, list = Format.(fprintf, printf, pp_print_list) +let string, custom_break = Format.(pp_print_string, pp_print_custom_break) + +let () = Format.set_margin 30 + +let example = [ + "Foo"; "Baz"; "Bar"; "Qux"; "Quux"; "Quuz"; "Corge"; "Grault"; "Garply"; +] + +let boxes = ["v"; "b"; "h"; "hv"; "hov"] + +let test format data = + boxes |> List.iter (fun box -> + printf "## The %S box@\n```@\n@[<%s 0>%a@]@\n```@\n@\n" box box + (format box) data); + +module Format_list = struct + let pp_sep ppf () = fprintf ppf ";@ " + + let format box_type ppf items = + fprintf ppf "[@;<0 2>@[<%s>%a@]%t]" box_type + (list ~pp_sep string) items + (custom_break ~fits:("", 0, "") ~breaks:(";", 0, "")) + + let () = + printf "# Printing arrays: last trailing semicolon is optional@\n@\n"; + test format example +end + + +module Format_statements = struct + let pp_sep ppf () = + custom_break ppf ~fits:(";", 1, "") ~breaks:("", 0, "") + + let rec format box_type ppf items = + fprintf ppf "{@;<0 2>@[<%s>%a@]@,}" box_type + (list ~pp_sep string) items + + let () = + printf "# Printing statements: terminator is optional after newline@\n@\n"; + test format example +end + + +module Format_function = struct + let pp_sep ppf () = fprintf ppf "@ | " + let format_case ppf = fprintf ppf "%s -> ()" + + let rec format box_type ppf items = + fprintf ppf "@[<%s>function%t%a@]" box_type + (custom_break ~fits:("", 1, "") ~breaks:("", 0, "| ")) + (list ~pp_sep format_case) items + + let () = + printf "# Printing function: first pipe character is optional@\n@\n"; + test format example +end diff --git a/testsuite/tests/lib-format/pp_print_custom_break.reference b/testsuite/tests/lib-format/pp_print_custom_break.reference new file mode 100644 index 00000000..f90f7673 --- /dev/null +++ b/testsuite/tests/lib-format/pp_print_custom_break.reference @@ -0,0 +1,159 @@ +# Printing arrays: last trailing semicolon is optional + +## The "v" box +``` +[ + Foo; + Baz; + Bar; + Qux; + Quux; + Quuz; + Corge; + Grault; + Garply; +] +``` + +## The "b" box +``` +[ + Foo; Baz; Bar; Qux; Quux; + Quuz; Corge; Grault; Garply; +] +``` + +## The "h" box +``` +[Foo; Baz; Bar; Qux; Quux; Quuz; Corge; Grault; Garply] +``` + +## The "hv" box +``` +[ + Foo; + Baz; + Bar; + Qux; + Quux; + Quuz; + Corge; + Grault; + Garply; +] +``` + +## The "hov" box +``` +[ + Foo; Baz; Bar; Qux; Quux; + Quuz; Corge; Grault; Garply; +] +``` + +# Printing statements: terminator is optional after newline + +## The "v" box +``` +{ + Foo + Baz + Bar + Qux + Quux + Quuz + Corge + Grault + Garply +} +``` + +## The "b" box +``` +{ + Foo; Baz; Bar; Qux; Quux + Quuz; Corge; Grault; Garply +} +``` + +## The "h" box +``` +{Foo; Baz; Bar; Qux; Quux; Quuz; Corge; Grault; Garply} +``` + +## The "hv" box +``` +{ + Foo + Baz + Bar + Qux + Quux + Quuz + Corge + Grault + Garply +} +``` + +## The "hov" box +``` +{ + Foo; Baz; Bar; Qux; Quux + Quuz; Corge; Grault; Garply +} +``` + +# Printing function: first pipe character is optional + +## The "v" box +``` +function +| Foo -> () +| Baz -> () +| Bar -> () +| Qux -> () +| Quux -> () +| Quuz -> () +| Corge -> () +| Grault -> () +| Garply -> () +``` + +## The "b" box +``` +function Foo -> () +| Baz -> () | Bar -> () +| Qux -> () | Quux -> () +| Quuz -> () | Corge -> () +| Grault -> () | Garply -> () +``` + +## The "h" box +``` +function Foo -> () | Baz -> () | Bar -> () | Qux -> () | Quux -> () | Quuz -> () | Corge -> () | Grault -> () | Garply -> () +``` + +## The "hv" box +``` +function +| Foo -> () +| Baz -> () +| Bar -> () +| Qux -> () +| Quux -> () +| Quuz -> () +| Corge -> () +| Grault -> () +| Garply -> () +``` + +## The "hov" box +``` +function Foo -> () +| Baz -> () | Bar -> () +| Qux -> () | Quux -> () +| Quuz -> () | Corge -> () +| Grault -> () | Garply -> () +``` + diff --git a/testsuite/tests/lib-format/print_if_newline.ml b/testsuite/tests/lib-format/print_if_newline.ml new file mode 100644 index 00000000..31c42b02 --- /dev/null +++ b/testsuite/tests/lib-format/print_if_newline.ml @@ -0,0 +1,26 @@ +(* TEST *) + +(* + +A test file for Format.print_if_newline. + +*) + +open Format;; + +printf "\ntest print_if_newline\n%!"; +printf " newline here\n%!"; +print_if_newline (); +printf " this gets printed"; +print_if_newline (); +printf " this doesn't get printed"; + +printf "\nprint_if_newline doesn't crash when last statement\n%!"; +printf " newline here\n"; +(* Important that the following is the last statement in the file. + + [print_if_newline] sets up the Format module to skip printing + the next printing command. However, it should not crash if there + is no next printing statement. *) +print_if_newline (); +;; diff --git a/testsuite/tests/lib-format/print_if_newline.reference b/testsuite/tests/lib-format/print_if_newline.reference new file mode 100644 index 00000000..df810718 --- /dev/null +++ b/testsuite/tests/lib-format/print_if_newline.reference @@ -0,0 +1,6 @@ + +test print_if_newline + newline here + this gets printed +print_if_newline doesn't crash when last statement + newline here diff --git a/testsuite/tests/lib-format/tformat.ml b/testsuite/tests/lib-format/tformat.ml index 325d9277..83250aa5 100644 --- a/testsuite/tests/lib-format/tformat.ml +++ b/testsuite/tests/lib-format/tformat.ml @@ -525,6 +525,14 @@ try test (sprintf "@@" = "@"); test (sprintf "@@@@" = "@@"); test (sprintf "@@%%" = "@%"); + + say "\nDelayed printf\n%!"; + let t1 = dprintf "%i - %s" 1 "bar" in + test (asprintf "foo %t" t1 = "foo 1 - bar"); + let t2 = dprintf "%a@]" (pp_print_list pp_print_int) [1 ; 2 ; 3] in + test (asprintf "foo @[%t@,%s" t2 "bar" = "foo 1\n 2\n 3\nbar"); + test (asprintf "%t @[%t" t1 t2 = "1 - bar 123"); + say "\nend of tests\n%!"; with e -> diff --git a/testsuite/tests/lib-format/tformat.reference b/testsuite/tests/lib-format/tformat.reference index 461fe9da..4496e98c 100644 --- a/testsuite/tests/lib-format/tformat.reference +++ b/testsuite/tests/lib-format/tformat.reference @@ -90,6 +90,8 @@ t 309 ! % @ , and constants 310 311 312 313 314 315 316 +Delayed printf + 317 318 319 end of tests All tests succeeded. diff --git a/testsuite/tests/lib-fun/ocamltests b/testsuite/tests/lib-fun/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/lib-fun/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/lib-fun/test.ml b/testsuite/tests/lib-fun/test.ml new file mode 100644 index 00000000..ba534db2 --- /dev/null +++ b/testsuite/tests/lib-fun/test.ml @@ -0,0 +1,52 @@ +(* TEST +*) + +let test_id () = + assert (Fun.id true = true); + assert (Fun.id 1 = 1); + assert (not (Fun.id nan = nan)); + () + +let test_const () = + assert (Fun.const true false = true); + assert (Fun.const 0 false = 0); + assert (Fun.const 0 4 = 0); + () + +let test_flip () = + assert (Fun.flip ( ^ ) "of order" "out " = "out of order"); + assert (Fun.flip List.append [2] [1] = [1;2]); + assert (Fun.flip List.cons [2] 1 = [1;2]); + () + +let test_negate () = + assert (Fun.negate (Bool.equal true) true = false); + assert (Fun.negate (Bool.equal true) false = true); + () + +let test_protect () = + let does_raise f x = + try f x ; false + with _ -> true + in + let double_raise () = + let f () = raise Exit in + try + Fun.protect ~finally:f f () + with + | Exit -> () + in + assert (does_raise double_raise ()) + +let tests () = + test_id (); + test_const (); + test_flip (); + test_negate (); + test_protect (); + () + +let () = + tests (); + print_endline "OK"; + () diff --git a/testsuite/tests/lib-fun/test.reference b/testsuite/tests/lib-fun/test.reference new file mode 100644 index 00000000..d86bac9d --- /dev/null +++ b/testsuite/tests/lib-fun/test.reference @@ -0,0 +1 @@ +OK diff --git a/testsuite/tests/lib-hashtbl/htbl.ml b/testsuite/tests/lib-hashtbl/htbl.ml index 46f5e210..7dd6f287 100644 --- a/testsuite/tests/lib-hashtbl/htbl.ml +++ b/testsuite/tests/lib-hashtbl/htbl.ml @@ -35,17 +35,18 @@ module Test(H: Hashtbl.S) (M: Map.S with type key = H.key) = struct let to_list_ h : _ list = H.fold (fun k v acc -> (k,v) :: acc) h [] - |> List.sort Pervasives.compare + |> List.sort Stdlib.compare let check_to_seq h = let l = to_list_ h in let l2 = List.of_seq (H.to_seq h) in - assert (l = List.sort Pervasives.compare l2) + assert (l = List.sort Stdlib.compare l2) let check_to_seq_of_seq h = let h' = H.create (H.length h) in H.add_seq h' (H.to_seq h); - (*printf "h.len=%d, h'.len=%d\n" (List.length @@ to_list_ h) (List.length @@ to_list_ h');*) + (*printf "h.len=%d, h'.len=%d\n" (List.length @@ to_list_ h) + (List.length @@ to_list_ h');*) assert (to_list_ h = to_list_ h') let test data = @@ -82,31 +83,31 @@ end module SS = struct type t = string - let compare (x:t) (y:t) = Pervasives.compare x y + let compare (x:t) (y:t) = Stdlib.compare x y let equal (x:t) (y:t) = x=y let hash = Hashtbl.hash end module SI = struct type t = int - let compare (x:t) (y:t) = Pervasives.compare x y + let compare (x:t) (y:t) = Stdlib.compare x y let equal (x:t) (y:t) = x=y let hash = Hashtbl.hash end module SSP = struct type t = string*string - let compare (x:t) (y:t) = Pervasives.compare x y + let compare (x:t) (y:t) = Stdlib.compare x y let equal (x:t) (y:t) = x=y let hash = Hashtbl.hash end module SSL = struct type t = string list - let compare (x:t) (y:t) = Pervasives.compare x y + let compare (x:t) (y:t) = Stdlib.compare x y let equal (x:t) (y:t) = x=y let hash = Hashtbl.hash end module SSA = struct type t = string array - let compare (x:t) (y:t) = Pervasives.compare x y + let compare (x:t) (y:t) = Stdlib.compare x y let equal (x:t) (y:t) = x=y let hash = Hashtbl.hash end @@ -233,7 +234,7 @@ let list_data data = hd :: tl end in for i = 0 to Array.length d - 1 do - d.(i) <- (mklist (Random.int 16), string_of_int i) + d.(i) <- (mklist (Random.int 16), Int.to_string i) done; d diff --git a/testsuite/tests/lib-int/ocamltests b/testsuite/tests/lib-int/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/lib-int/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/lib-int/test.ml b/testsuite/tests/lib-int/test.ml new file mode 100644 index 00000000..322ae97c --- /dev/null +++ b/testsuite/tests/lib-int/test.ml @@ -0,0 +1,71 @@ +(* TEST +*) + +let test_consts () = + assert (Int.zero = 0); + assert (Int.one = 1); + assert (Int.minus_one = -1); + () + +let test_arith () = + assert (Int.add 2 4 = 6); + assert (Int.sub 6 2 = 4); + assert (Int.mul 6 2 = 12); + assert (Int.div 12 2 = 6); + assert (Int.rem 5 2 = 1); + assert (Int.succ 5 = 6); + assert (Int.pred 5 = 4); + assert (Int.abs (-5) = 5); + assert (Int.abs 5 = 5); + () + +let test_logops () = + assert (Int.logand 0xF0F0 0xFFFF = 0xF0F0); + assert (Int.logor 0xF0FF 0x0F0F = 0xFFFF); + assert (Int.logxor 0xF0FF 0x0F0F = 0xFFF0); + assert (Int.lognot Int.max_int = Int.min_int); + assert (Int.shift_left 1 4 = 16); + assert (Int.shift_right 16 4 = 1); + assert (Int.shift_right (-16) 4 = (-1)); + assert (Int.shift_right (-16) 4 = (-1)); + assert (Int.shift_right_logical Int.min_int (Sys.int_size - 1) = 1); + () + +let test_equal () = + assert (Int.equal 1 1 = true); + assert (Int.equal 1 0 = false); + () + +let test_compare () = + assert (Int.compare 3 3 = 0); + assert (Int.compare 3 4 = (-1)); + assert (Int.compare 4 3 = 1); + assert (Int.compare (-4) 3 = -1); + assert (Int.compare 3 (-4) = 1); + () + +let test_float_conv () = + assert (Int.to_float 5 = 5.0); + assert (Int.of_float 5. = 5); + assert (Int.of_float 5.9 = 5); + () + +let test_string_conv () = + assert (Int.to_string 50 = "50"); +(* assert (Int.of_string "50" = Some 50); + assert (Int.of_string "" = None); *) + () + +let tests () = + test_consts (); + test_arith (); + test_logops (); + test_equal (); + test_compare (); + test_float_conv (); + test_string_conv (); + () + +let () = + tests (); + print_endline "OK" diff --git a/testsuite/tests/lib-int/test.reference b/testsuite/tests/lib-int/test.reference new file mode 100644 index 00000000..d86bac9d --- /dev/null +++ b/testsuite/tests/lib-int/test.reference @@ -0,0 +1 @@ +OK diff --git a/testsuite/tests/lib-int64/ocamltests b/testsuite/tests/lib-int64/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/lib-int64/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/lib-int64/test.ml b/testsuite/tests/lib-int64/test.ml new file mode 100644 index 00000000..82e2b4f8 --- /dev/null +++ b/testsuite/tests/lib-int64/test.ml @@ -0,0 +1,71 @@ +(* TEST +*) + +let test_consts () = + assert (Int64.zero = 0L); + assert (Int64.one = 1L); + assert (Int64.minus_one = -1L); + () + +let test_arith () = + assert (Int64.add 2L 4L = 6L); + assert (Int64.sub 6L 2L = 4L); + assert (Int64.mul 6L 2L = 12L); + assert (Int64.div 12L 2L = 6L); + assert (Int64.rem 5L 2L = 1L); + assert (Int64.succ 5L = 6L); + assert (Int64.pred 5L = 4L); + assert (Int64.abs (-5L) = 5L); + assert (Int64.abs 5L = 5L); + () + +let test_logops () = + assert (Int64.logand 0xF0F0L 0xFFFFL = 0xF0F0L); + assert (Int64.logor 0xF0FFL 0x0F0FL = 0xFFFFL); + assert (Int64.logxor 0xF0FFL 0x0F0FL = 0xFFF0L); + assert (Int64.lognot Int64.max_int = Int64.min_int); + assert (Int64.shift_left 1L 4 = 16L); + assert (Int64.shift_right 16L 4 = 1L); + assert (Int64.shift_right (-16L) 4 = (-1L)); + assert (Int64.shift_right (-16L) 4 = (-1L)); + assert (Int64.shift_right_logical Int64.min_int 63 = 1L); + () + +let test_equal () = + assert (Int64.equal 1L 1L = true); + assert (Int64.equal 1L 0L = false); + () + +let test_compare () = + assert (Int64.compare 3L 3L = 0); + assert (Int64.compare 3L 4L = (-1)); + assert (Int64.compare 4L 3L = 1); + assert (Int64.compare (-4L) 3L = -1); + assert (Int64.compare 3L (-4L) = 1); + () + +let test_float_conv () = + assert (Int64.to_float 5L = 5.0); + assert (Int64.of_float 5. = 5L); + assert (Int64.of_float 5.9 = 5L); + () + +let test_string_conv () = + assert (Int64.to_string 50L = "50"); +(* assert (Int64.of_string "50" = Some 50); + assert (Int64.of_string "" = None); *) + () + +let tests () = + test_consts (); + test_arith (); + test_logops (); + test_equal (); + test_compare (); + test_float_conv (); + test_string_conv (); + () + +let () = + tests (); + print_endline "OK" diff --git a/testsuite/tests/lib-int64/test.reference b/testsuite/tests/lib-int64/test.reference new file mode 100644 index 00000000..d86bac9d --- /dev/null +++ b/testsuite/tests/lib-int64/test.reference @@ -0,0 +1 @@ +OK diff --git a/testsuite/tests/lib-list/test.ml b/testsuite/tests/lib-list/test.ml index 68fdd1ac..88b0a5be 100644 --- a/testsuite/tests/lib-list/test.ml +++ b/testsuite/tests/lib-list/test.ml @@ -1,6 +1,12 @@ (* TEST *) +let string_of_even_opt x = + if x mod 2 = 0 then + Some (string_of_int x) + else + None + (* Standard test case *) let () = let l = List.init 10 (fun x -> x) in @@ -35,6 +41,7 @@ let () = assert (List.compare_length_with [1] 0 > 0); assert (List.compare_length_with ['1'] 1 = 0); assert (List.compare_length_with ['1'] 2 < 0); + assert (List.filter_map string_of_even_opt l = ["0";"2";"4";"6";"8"]); () ;; @@ -59,7 +66,8 @@ let () = let _ = List.init n (fun x -> result := (x = n - 1)) in assert !result in - let threshold = 10_000 in (* Threshold must equal the value in stdlib/list.ml *) + (* Threshold must equal the value in stdlib/list.ml *) + let threshold = 10_000 in test threshold; (* Non tail-recursive case *) test (threshold + 1) (* Tail-recursive case *) ;; diff --git a/testsuite/tests/lib-marshal/intext.ml b/testsuite/tests/lib-marshal/intext.ml index 66cc714f..5ed2bbc5 100644 --- a/testsuite/tests/lib-marshal/intext.ml +++ b/testsuite/tests/lib-marshal/intext.ml @@ -578,6 +578,19 @@ let test_end_of_file_regression () = with _ -> false ) +external init_buggy_custom_ops : unit -> unit = + "init_buggy_custom_ops" +let () = init_buggy_custom_ops () +type buggy +external value_with_buggy_serialiser : unit -> buggy = + "value_with_buggy_serialiser" +let test_buggy_serialisers () = + let x = value_with_buggy_serialiser () in + let s = Marshal.to_string x [] in + match Marshal.from_string s 0 with + | exception (Failure _) -> () + | _ -> + failwith "Marshalling should not have succeeded with a bad serialiser!" let main() = if Array.length Sys.argv <= 2 then begin @@ -592,6 +605,7 @@ let main() = test_infix (); test_mutual_rec_regression (); test_end_of_file_regression (); + test_buggy_serialisers (); Sys.remove "intext.data"; end else if Sys.argv.(1) = "make" then begin diff --git a/testsuite/tests/lib-marshal/intextaux.c b/testsuite/tests/lib-marshal/intextaux.c index 183343d6..d8ea180a 100644 --- a/testsuite/tests/lib-marshal/intextaux.c +++ b/testsuite/tests/lib-marshal/intextaux.c @@ -15,6 +15,7 @@ #include #include +#include #define CAML_INTERNALS @@ -28,3 +29,36 @@ value marshal_from_block(value vbuf, value vlen) { return caml_input_value_from_block((char *) vbuf, Long_val(vlen)); } + +static void bad_serialize(value v, uintnat* sz_32, uintnat* sz_64) +{ + caml_serialize_int_4(42); + *sz_32 = *sz_64 = 100; +} + +static uintnat bad_deserialize(void* dst) +{ + return 10; +} + +static struct custom_operations buggy_ops = { + "foo", + custom_finalize_default, + custom_compare_default, + custom_hash_default, + bad_serialize, + bad_deserialize, + custom_compare_ext_default, + custom_fixed_length_default +}; + +value init_buggy_custom_ops() +{ + caml_register_custom_operations(&buggy_ops); + return Val_unit; +} + +value value_with_buggy_serialiser() +{ + return caml_alloc_custom(&buggy_ops, 20, 0, 1); +} diff --git a/testsuite/tests/lib-option/ocamltests b/testsuite/tests/lib-option/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/lib-option/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/lib-option/test.ml b/testsuite/tests/lib-option/test.ml new file mode 100644 index 00000000..316e3eae --- /dev/null +++ b/testsuite/tests/lib-option/test.ml @@ -0,0 +1,117 @@ +(* TEST +*) + +let strf = Printf.sprintf +let assert_raise_invalid_argument f v = + assert (try ignore (f v); false with Invalid_argument _ -> true); + () + +let test_none_some () = + assert (Option.none = None); + assert (Option.some 2 = Some 2); + () + +let test_value () = + assert (Option.value None ~default:5 = 5); + assert (Option.value (Some 3) ~default:5 = 3); + () + +let test_get () = + assert_raise_invalid_argument Option.get None; + assert (Option.get (Some 2) = 2); + () + +let test_bind () = + assert (Option.bind (Some 3) (fun x -> Some (succ x)) = Some 4); + assert (Option.bind (Some 3) (fun _ -> None) = None); + assert (Option.bind None (fun x -> Some (succ x)) = None); + assert (Option.bind None (fun _ -> None) = None); + () + +let test_join () = + assert (Option.join (Some (Some 3)) = Some 3); + assert (Option.join (Some None) = None); + assert (Option.join None = None); + () + +let test_map () = + assert (Option.map succ (Some 3) = Some 4); + assert (Option.map succ None = None); + () + +let test_fold () = + assert (Option.fold ~none:3 ~some:succ (Some 1) = 2); + assert (Option.fold ~none:3 ~some:succ None = 3); + assert (Option.(fold ~none ~some) (Some 1) = (Some 1)); + assert (Option.(fold ~none ~some) None = None); + () + +let test_iter () = + let count = ref 0 in + let set_count x = count := x in + assert (!count = 0); + Option.iter set_count (Some 2); assert (!count = 2); + Option.iter set_count None; assert (!count = 2); + () + +let test_is_none_some () = + assert (Option.is_none None = true); + assert (Option.is_some None = false); + assert (Option.is_none (Some 2) = false); + assert (Option.is_some (Some 2) = true); + () + +let test_equal () = + let eq v0 v1 = (v0 mod 2) = (v1 mod 2) in + let equal = Option.equal eq in + assert (not @@ equal (Some 2) (Some 3)); + assert ( equal (Some 2) (Some 4)); + assert (not @@ equal (Some 2) None); + assert (not @@ equal None (Some 3)); + assert (not @@ equal None (Some 4)); + assert ( equal None None); + () + +let test_compare () = + let compare v0 v1 = - (compare v0 v1) in + let compare = Option.compare compare in + assert (compare (Some 2) (Some 1) = -1); + assert (compare (Some 2) (Some 2) = 0); + assert (compare (Some 2) (Some 3) = 1); + assert (compare (Some 2) None = 1); + assert (compare None (Some 1) = -1); + assert (compare None (Some 2) = -1); + assert (compare None (Some 3) = -1); + assert (compare None None = 0); + () + +let test_to_option_list_seq () = + assert (Option.to_result ~none:6 (Some 3) = Ok 3); + assert (Option.to_result ~none:6 None = Error 6); + assert (Option.to_list (Some 3) = [3]); + assert (Option.to_list None = []); + begin match (Option.to_seq (Some 3)) () with + | Seq.Cons (3, f) -> assert (f () = Seq.Nil) + | _ -> assert false + end; + assert ((Option.to_seq None) () = Seq.Nil); + () + +let tests () = + test_none_some (); + test_value (); + test_get (); + test_bind (); + test_join (); + test_map (); + test_fold (); + test_iter (); + test_is_none_some (); + test_equal (); + test_compare (); + test_to_option_list_seq (); + () + +let () = + tests (); + print_endline "OK" diff --git a/testsuite/tests/lib-option/test.reference b/testsuite/tests/lib-option/test.reference new file mode 100644 index 00000000..d86bac9d --- /dev/null +++ b/testsuite/tests/lib-option/test.reference @@ -0,0 +1 @@ +OK diff --git a/testsuite/tests/lib-printf/tprintf.ml b/testsuite/tests/lib-printf/tprintf.ml index bf7236a7..8036dfb7 100644 --- a/testsuite/tests/lib-printf/tprintf.ml +++ b/testsuite/tests/lib-printf/tprintf.ml @@ -19,8 +19,13 @@ try test (sprintf "%04d/%05i" 42 43 = "0042/00043"); test (sprintf "%+d/%+i" 42 43 = "+42/+43"); test (sprintf "% d/% i" 42 43 = " 42/ 43"); - (*test (sprintf "%#d/%#i" 42 43 = "42/43");*) - (* >> '#' is incompatible with 'd' *) + test (sprintf "%#d/%#i" 42 43 = "42/43"); + test (sprintf "%#d/%#i" 123 123 = "123/123"); + test (sprintf "%#d/%#i" 1234 1234 = "1_234/1_234"); + test (sprintf "%#d/%#i" 12345 12345 = "12_345/12_345"); + test (sprintf "%#d/%#i" 123456 123456 = "123_456/123_456"); + test (sprintf "%#4d/%#5i" 1234 1234 = "1_234/1_234"); + test (sprintf "%#-6d/%#-7i" 1234 1234 = "1_234 /1_234 "); test (sprintf "%4d/%5i" 42 43 = " 42/ 43"); test (sprintf "%*d" (-4) 42 = "42 "); test (sprintf "%*d/%*i" 4 42 5 43 = " 42/ 43"); @@ -33,8 +38,13 @@ try test (sprintf "%04d/%05i" (-42) (-43) = "-042/-0043"); test (sprintf "%+d/%+i" (-42) (-43) = "-42/-43"); test (sprintf "% d/% i" (-42) (-43) = "-42/-43"); - (*test (sprintf "%#d/%#i" (-42) (-43) = "-42/-43");*) - (* >> '#' is incompatible with 'd' *) + test (sprintf "%#d/%#i" (-42) (-43) = "-42/-43"); + test (sprintf "%#d/%#i" (-123) (-123) = "-123/-123"); + test (sprintf "%#d/%#i" (-1234) (-1234) = "-1_234/-1_234"); + test (sprintf "%#d/%#i" (-12345) (-12345) = "-12_345/-12_345"); + test (sprintf "%#d/%#i" (-123456) (-123456) = "-123_456/-123_456"); + test (sprintf "%#4d/%#5i" (-1234) (-1234) = "-1_234/-1_234"); + test (sprintf "%#-6d/%#-7i" (-1234) (-1234) = "-1_234/-1_234 "); test (sprintf "%4d/%5i" (-42) (-43) = " -42/ -43"); test (sprintf "%*d" (-4) (-42) = "-42 "); test (sprintf "%*d/%*i" 4 (-42) 5 (-43) = " -42/ -43"); @@ -49,8 +59,13 @@ try (* >> '+' is incompatible with 'u' *) (*test (sprintf "% u" 42 = "42");*) (* >> ' ' is incompatible with 'u' *) - (*test (sprintf "%#u" 42 = "42");*) - (* >> '#' is incompatible with 'u' *) + test (sprintf "%#u" 42 = "42"); + test (sprintf "%#u" 123 = "123"); + test (sprintf "%#u" 1234 = "1_234"); + test (sprintf "%#u" 12345 = "12_345"); + test (sprintf "%#u" 123456 = "123_456"); + test (sprintf "%#4u" 1234 = "1_234"); + test (sprintf "%#6u" 1234 = " 1_234"); test (sprintf "%4u" 42 = " 42"); test (sprintf "%*u" 4 42 = " 42"); test (sprintf "%*u" (-4) 42 = "42 "); @@ -59,8 +74,10 @@ try begin match Sys.word_size with | 32 -> test (sprintf "%u" (-1) = "2147483647"); + test (sprintf "%#u" (-1) = "2_147_483_647"); | 64 -> test (sprintf "%u" (-1) = "9223372036854775807"); + test (sprintf "%#u" (-1) = "9_223_372_036_854_775_807"); | _ -> test false end; diff --git a/testsuite/tests/lib-printf/tprintf.reference b/testsuite/tests/lib-printf/tprintf.reference index 9098a48d..af593cd4 100644 --- a/testsuite/tests/lib-printf/tprintf.reference +++ b/testsuite/tests/lib-printf/tprintf.reference @@ -1,95 +1,95 @@ d/i positive - 0 1 2 3 4 5 6 7 + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 d/i negative - 8 9 10 11 12 13 14 15 + 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 u positive - 16 17 18 19 20 21 + 30 31 32 33 34 35 36 37 38 39 40 41 42 u negative - 22 + 43 44 x positive - 23 24 25 26 27 28 29 30 31 32 33 + 45 46 47 48 49 50 51 52 53 54 55 x negative - 34 + 56 X positive - 35 36 37 38 39 40 + 57 58 59 60 61 62 x negative - 41 + 63 o positive - 42 43 44 45 46 47 + 64 65 66 67 68 69 o negative - 48 + 70 s - 49 50 51 52 53 54 55 56 57 58 + 71 72 73 74 75 76 77 78 79 80 S - 59 60 61 62 63 64 65 66 + 81 82 83 84 85 86 87 88 c - 67 + 89 C - 68 69 + 90 91 f - 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 + 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 F - 85 86 87 88 89 90 91 + 107 108 109 110 111 112 113 h - 92 93 94 95 96 97 98 99 100 101 102 103 104 + 114 115 116 117 118 119 120 121 122 123 124 125 126 H - 105 106 107 108 109 110 111 112 113 114 115 116 117 + 127 128 129 130 131 132 133 134 135 136 137 138 139 e - 118 119 120 121 122 123 124 125 126 127 128 129 130 131 + 140 141 142 143 144 145 146 147 148 149 150 151 152 153 E - 132 133 134 135 136 137 138 139 140 141 142 143 144 145 + 154 155 156 157 158 159 160 161 162 163 164 165 166 167 B - 146 147 148 149 + 168 169 170 171 ld/li positive - 150 151 152 153 154 155 156 + 172 173 174 175 176 177 178 ld/li negative - 157 158 159 160 161 162 163 + 179 180 181 182 183 184 185 lu positive - 164 165 166 167 168 + 186 187 188 189 190 lu negative - 169 + 191 lx positive - 170 171 172 173 174 175 + 192 193 194 195 196 197 lx negative - 176 + 198 lX positive - 177 178 179 180 181 182 + 199 200 201 202 203 204 lx negative - 183 + 205 lo positive - 184 185 186 187 188 189 + 206 207 208 209 210 211 lo negative - 190 + 212 Ld/Li positive - 191 192 193 194 195 + 213 214 215 216 217 Ld/Li negative - 196 197 198 199 200 + 218 219 220 221 222 Lu positive - 201 202 203 204 205 + 223 224 225 226 227 Lu negative - 206 + 228 Lx positive - 207 208 209 210 211 212 + 229 230 231 232 233 234 Lx negative - 213 + 235 LX positive - 214 215 216 217 218 219 + 236 237 238 239 240 241 Lx negative - 220 + 242 Lo positive - 221 222 223 224 225 226 + 243 244 245 246 247 248 Lo negative - 227 + 249 a - 228 + 250 t - 229 + 251 {...%} - 230 + 252 (...%) - 231 + 253 ! % @ , and constants - 232 233 234 235 236 237 238 + 254 255 256 257 258 259 260 end of tests All tests succeeded. diff --git a/testsuite/tests/lib-result/ocamltests b/testsuite/tests/lib-result/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/lib-result/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/lib-result/test.ml b/testsuite/tests/lib-result/test.ml new file mode 100644 index 00000000..6e7a5cc8 --- /dev/null +++ b/testsuite/tests/lib-result/test.ml @@ -0,0 +1,131 @@ +(* TEST +*) + +let strf = Printf.sprintf +let assert_raise_invalid_argument f v = + assert (try ignore (f v); false with Invalid_argument _ -> true); + () + +let test_ok_error () = + assert (Result.ok 3 = Ok 3); + assert (Result.error "ha!" = Error "ha!"); + () + +let test_value () = + assert (Result.value (Ok 3) ~default:5 = 3); + assert (Result.value (Error "ha!") ~default:5 = 5); + () + +let test_get_ok_error () = + assert (Result.get_ok (Ok 3) = 3); + assert_raise_invalid_argument Result.get_ok (Error "ha!"); + assert (Result.get_error (Error "ha!") = "ha!"); + assert_raise_invalid_argument Result.get_error (Ok 2); + () + +let test_bind () = + assert (Result.bind (Ok 3) (fun x -> Ok (succ x)) = Ok 4); + assert (Result.bind (Ok 3) (fun x -> Error (strf "hu%d!" x)) = Error "hu3!"); + assert (Result.bind (Error "ha!") (fun x -> Ok (succ x)) = Error "ha!"); + assert (Result.bind (Error "ha!") (fun _ -> Error "hu!") = Error "ha!"); + () + +let test_join () = + assert (Result.join (Ok (Ok 3)) = Ok 3); + assert (Result.join (Ok (Error "ha!")) = Error "ha!"); + assert (Result.join (Error "ha!") = Error "ha!"); + () + +let test_maps () = + assert (Result.map succ (Ok 3) = Ok 4); + assert (Result.map succ (Error "ha!") = Error "ha!"); + assert (Result.map_error succ (Error 3) = Error 4); + assert (Result.map_error succ (Ok 2) = Ok 2); + () + +let test_fold () = + assert (Result.fold ~ok:succ ~error:succ (Ok 1) = 2); + assert (Result.fold ~ok:succ ~error:succ (Error 1) = 2); + assert (Result.(fold ~ok ~error) (Ok 1) = (Ok 1)); + assert (Result.(fold ~ok ~error) (Error "ha!") = (Error "ha!")); + () + +let test_iters () = + let count = ref 0 in + let set_count x = count := x in + assert (!count = 0); + Result.iter set_count (Ok 2); assert (!count = 2); + Result.iter set_count (Error "ha!"); assert (!count = 2); + Result.iter_error set_count (Error 3); assert (!count = 3); + Result.iter_error set_count (Ok "ha!"); assert (!count = 3); + () + +let test_is_ok_error () = + assert (Result.is_ok (Ok 2) = true); + assert (Result.is_error (Ok 2) = false); + assert (Result.is_ok (Error "ha!") = false); + assert (Result.is_error (Error "ha!") = true); + () + +let test_equal () = + let ok v0 v1 = (v0 mod 2) = (v1 mod 2) in + let error = ok in + let equal = Result.equal ~ok ~error in + assert (not @@ equal (Ok 2) (Ok 3)); + assert ( equal (Ok 2) (Ok 4)); + assert (not @@ equal (Ok 2) (Error 3)); + assert (not @@ equal (Ok 2) (Error 4)); + assert (not @@ equal (Error 2) (Ok 3)); + assert (not @@ equal (Error 2) (Ok 4)); + assert (not @@ equal (Error 2) (Error 3)); + assert ( equal (Error 2) (Error 4)); + () + +let test_compare () = + let ok v0 v1 = - (compare v0 v1) in + let error = ok in + let compare = Result.compare ~ok ~error in + assert (compare (Ok 2) (Ok 1) = -1); + assert (compare (Ok 2) (Ok 2) = 0); + assert (compare (Ok 2) (Ok 3) = 1); + assert (compare (Ok 2) (Error 1) = -1); + assert (compare (Ok 2) (Error 2) = -1); + assert (compare (Ok 2) (Error 3) = -1); + assert (compare (Error 2) (Ok 1) = 1); + assert (compare (Error 2) (Ok 2) = 1); + assert (compare (Error 2) (Ok 3) = 1); + assert (compare (Error 2) (Error 1) = -1); + assert (compare (Error 2) (Error 2) = 0); + assert (compare (Error 2) (Error 3) = 1); + () + +let test_to_option_list_seq () = + assert (Result.to_option (Ok 3) = Some 3); + assert (Result.to_option (Error "ha!") = None); + assert (Result.to_list (Ok 3) = [3]); + assert (Result.to_list (Error "ha!") = []); + begin match (Result.to_seq (Ok 3)) () with + | Seq.Cons (3, f) -> assert (f () = Seq.Nil) + | _ -> assert false + end; + assert ((Result.to_seq (Error "ha!")) () = Seq.Nil); + () + +let tests () = + test_ok_error (); + test_value (); + test_get_ok_error (); + test_bind (); + test_join (); + test_maps (); + test_fold (); + test_iters (); + test_is_ok_error (); + test_equal (); + test_compare (); + test_to_option_list_seq (); + () + +let () = + tests (); + print_endline "OK" diff --git a/testsuite/tests/lib-result/test.reference b/testsuite/tests/lib-result/test.reference new file mode 100644 index 00000000..d86bac9d --- /dev/null +++ b/testsuite/tests/lib-result/test.reference @@ -0,0 +1 @@ +OK diff --git a/testsuite/tests/lib-scanf-2/reference b/testsuite/tests/lib-scanf-2/tscanf2.reference similarity index 100% rename from testsuite/tests/lib-scanf-2/reference rename to testsuite/tests/lib-scanf-2/tscanf2.reference diff --git a/testsuite/tests/lib-scanf-2/tscanf2_master.ml b/testsuite/tests/lib-scanf-2/tscanf2_master.ml index 988c8a52..a596b3ae 100644 --- a/testsuite/tests/lib-scanf-2/tscanf2_master.ml +++ b/testsuite/tests/lib-scanf-2/tscanf2_master.ml @@ -1,78 +1,79 @@ (* TEST -include unix modules = "tscanf2_io.ml" -files = "tscanf2_slave.ml" -reference = "${test_source_directory}/reference" +* hasunix +include unix +files = "tscanf2_worker.ml" +reference = "${test_source_directory}/tscanf2.reference" (* The bytcode test *) -* setup-ocamlc.byte-build-env +** setup-ocamlc.byte-build-env program = "${test_build_directory}/master.byte" -** ocamlc.byte (* Compiles the master *) +*** ocamlc.byte (* Compiles the master *) -*** ocamlc.byte (* Compiles the slave *) +**** ocamlc.byte (* Compiles the worker *) -all_modules = "tscanf2_io.cmo tscanf2_slave.ml" +all_modules = "tscanf2_io.cmo tscanf2_worker.ml" -program = "${test_build_directory}/slave.byte" +program = "${test_build_directory}/worker.byte" -**** check-ocamlc.byte-output +***** check-ocamlc.byte-output -***** run +****** run program = "${test_build_directory}/master.byte" -arguments = "${test_build_directory}/slave.byte" +arguments = "${test_build_directory}/worker.byte" -****** check-program-output +******* check-program-output (* The native test *) -* setup-ocamlopt.byte-build-env +** setup-ocamlopt.byte-build-env program = "${test_build_directory}/master.opt" -** ocamlopt.byte (* Compiles the master *) +*** ocamlopt.byte (* Compiles the master *) -*** ocamlopt.byte (* Compiles the slave *) +**** ocamlopt.byte (* Compiles the worker *) -all_modules = "tscanf2_io.cmx tscanf2_slave.ml" +all_modules = "tscanf2_io.cmx tscanf2_worker.ml" -program = "${test_build_directory}/slave.opt" +program = "${test_build_directory}/worker.opt" -**** check-ocamlopt.byte-output +***** check-ocamlopt.byte-output -***** run +****** run program = "${test_build_directory}/master.opt" -arguments = "${test_build_directory}/slave.opt" +arguments = "${test_build_directory}/worker.opt" -****** check-program-output +******* check-program-output *) (* A very simple master: - - first launch a slave process, + - first launch a worker process, - then repeat a random number of times: + print the string " Ping" on stderr, - + send it to the slave, + + send it to the worker, + and wait for its answer "-pong", - - finally send the string "stop" to the slave + - finally send the string "stop" to the worker and wait for its answer "OK, bye!" and die. Use the communication module Tscanf2_io. - Usage: test_master *) + Usage: test_master *) open Tscanf2_io;; -let slave = Sys.argv.(1);; -let ic, oc = Unix.open_process slave;; +let worker = Sys.argv.(1);; +let ic, oc = Unix.open_process worker;; let ib = Scanf.Scanning.from_channel ic;; let ob = Buffer.create 1024;; diff --git a/testsuite/tests/lib-scanf-2/tscanf2_slave.ml b/testsuite/tests/lib-scanf-2/tscanf2_slave.ml deleted file mode 100644 index e06a81f8..00000000 --- a/testsuite/tests/lib-scanf-2/tscanf2_slave.ml +++ /dev/null @@ -1,28 +0,0 @@ -(* A very simple slave: - - read the string " Ping" on stdin, - - then print the string "-pong" on stderr, - - and send it back on stdout - - until reading the string "stop" on stdin, - - then print the string "!\n" on stderr, - - send back the string "OK, bye!" on stdout, - - and die. - - Use the communication module Test_scanf2_io. *) - -open Tscanf2_io;; - -let ib = Scanf.Scanning.from_channel stdin;; -let ob = Buffer.create 1024 -and oc = stdout;; - -let send_string_pong ob = send_string ob oc "-pong";; -let send_string_okbye ob = send_string ob oc "OK, bye!";; - -while true do - let s = receive_string ib in - match s with - | " Ping" -> Printf.eprintf "-pong"; flush stderr; send_string_pong ob - | "stop" -> Printf.eprintf "!\n"; flush stderr; send_string_okbye ob; exit 0 - | s -> failwith ("Slave: unbound string " ^ s) -done -;; diff --git a/testsuite/tests/lib-scanf-2/tscanf2_worker.ml b/testsuite/tests/lib-scanf-2/tscanf2_worker.ml new file mode 100644 index 00000000..87345edc --- /dev/null +++ b/testsuite/tests/lib-scanf-2/tscanf2_worker.ml @@ -0,0 +1,28 @@ +(* A very simple worker: + - read the string " Ping" on stdin, + - then print the string "-pong" on stderr, + - and send it back on stdout + - until reading the string "stop" on stdin, + - then print the string "!\n" on stderr, + - send back the string "OK, bye!" on stdout, + - and die. + + Use the communication module Test_scanf2_io. *) + +open Tscanf2_io;; + +let ib = Scanf.Scanning.from_channel stdin;; +let ob = Buffer.create 1024 +and oc = stdout;; + +let send_string_pong ob = send_string ob oc "-pong";; +let send_string_okbye ob = send_string ob oc "OK, bye!";; + +while true do + let s = receive_string ib in + match s with + | " Ping" -> Printf.eprintf "-pong"; flush stderr; send_string_pong ob + | "stop" -> Printf.eprintf "!\n"; flush stderr; send_string_okbye ob; exit 0 + | s -> failwith ("Slave: unbound string " ^ s) +done +;; diff --git a/testsuite/tests/lib-scanf/tscanf.ml b/testsuite/tests/lib-scanf/tscanf.ml index 4a48653a..e932f960 100644 --- a/testsuite/tests/lib-scanf/tscanf.ml +++ b/testsuite/tests/lib-scanf/tscanf.ml @@ -454,7 +454,7 @@ let rec scan_elems ib accu = bscanf ib " %c " (fun c -> match c with | '[' when accu = [] -> - (* begginning of list: could find either + (* beginning of list: could find either - an int, if the list is not empty, - the char ], if the list is empty. *) bscanf ib "%[]]" @@ -931,7 +931,7 @@ let scan_string_list = scan_list (fun ib -> Scanf.bscanf ib "%S");; let scan_bool_list = scan_list (fun ib -> Scanf.bscanf ib "%B");; let scan_char_list = scan_list (fun ib -> Scanf.bscanf ib "%C");; -(* [scan_list] is truely polymorphic: scanning a list of lists of items +(* [scan_list] is truly polymorphic: scanning a list of lists of items is a one liner! Here we scan list of lists of floats. *) @@ -983,7 +983,7 @@ let test35 () = test (test340 () && test35 ()) ;; -(* The prefered reader functionnals. *) +(* The preferred reader functionnals. *) (* To read a list as in OCaml (elements are ``blank + semicolon + blank'' separated, and the list is enclosed in brackets). *) @@ -1235,7 +1235,7 @@ let next_char ob () = let send_string ob s = Buffer.add_string ob s; Buffer.add_char ob '\n';; -let send_int ob i = send_string ob (string_of_int i);; +let send_int ob i = send_string ob (Int.to_string i);; let rec reader = let count = ref 0 in @@ -1538,4 +1538,20 @@ let test60 () = sscanf "abc" "%1s%s" (fun s1 s2 -> s1 = "a" && s2 = "bc") ;; -test (test60 ()); +test (test60 ()) +;; + +let test61 () = + let test fmt = + format_from_string (string_of_format fmt) fmt = fmt + in + test "%s/%a" && + test "\\ " && + test "\\x" && + test "\\x25s" && + test "\\\"%s" && + test "\\" +;; + +test (test61 ()) +;; diff --git a/testsuite/tests/lib-scanf/tscanf.reference b/testsuite/tests/lib-scanf/tscanf.reference index 5b2859cb..a06a17ed 100644 --- a/testsuite/tests/lib-scanf/tscanf.reference +++ b/testsuite/tests/lib-scanf/tscanf.reference @@ -1,2 +1,2 @@ - 0 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 + 0 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 All tests succeeded. diff --git a/testsuite/tests/lib-seq/test.ml b/testsuite/tests/lib-seq/test.ml index ca38d466..1392b0d1 100644 --- a/testsuite/tests/lib-seq/test.ml +++ b/testsuite/tests/lib-seq/test.ml @@ -11,7 +11,7 @@ let () = |> Seq.filter (fun x -> x mod 2 = 0) |> List.of_seq)); () -;; +;; (* MPR 7820 *) let () = @@ -23,5 +23,3 @@ let () = ;; let () = print_endline "OK";; - - diff --git a/testsuite/tests/lib-set/testset.ml b/testsuite/tests/lib-set/testset.ml index 378dbfe6..b998875e 100644 --- a/testsuite/tests/lib-set/testset.ml +++ b/testsuite/tests/lib-set/testset.ml @@ -41,6 +41,9 @@ let test x s1 s2 = (let s = S.inter s1 s2 in fun i -> S.mem i s = (S.mem i s1 && S.mem i s2)); + checkbool "disjoint" + (S.is_empty (S.inter s1 s2) = S.disjoint s1 s2); + check "diff" (let s = S.diff s1 s2 in fun i -> S.mem i s = (S.mem i s1 && not (S.mem i s2))); diff --git a/testsuite/tests/lib-stdlib/ocamltests b/testsuite/tests/lib-stdlib/ocamltests new file mode 100644 index 00000000..a1f50ef4 --- /dev/null +++ b/testsuite/tests/lib-stdlib/ocamltests @@ -0,0 +1 @@ +pervasives_deprecated.ml diff --git a/testsuite/tests/lib-stdlib/pervasives_deprecated.ml b/testsuite/tests/lib-stdlib/pervasives_deprecated.ml new file mode 100644 index 00000000..86df5542 --- /dev/null +++ b/testsuite/tests/lib-stdlib/pervasives_deprecated.ml @@ -0,0 +1,41 @@ +(* TEST + * expect +*) + +[@@@warning "@A"];; + +Pervasives.(+) 1 1;; +[%%expect{| +Line 3, characters 0-14: +3 | Pervasives.(+) 1 1;; + ^^^^^^^^^^^^^^ +Error (alert deprecated): module Stdlib.Pervasives +Use Stdlib instead. + +If you need to stay compatible with OCaml < 4.07, you can use the +stdlib-shims library: https://github.com/ocaml/stdlib-shims +|}] + +module X = Pervasives;; +[%%expect{| +Line 1, characters 11-21: +1 | module X = Pervasives;; + ^^^^^^^^^^ +Error (alert deprecated): module Stdlib.Pervasives +Use Stdlib instead. + +If you need to stay compatible with OCaml < 4.07, you can use the +stdlib-shims library: https://github.com/ocaml/stdlib-shims +|}] + +open Pervasives;; +[%%expect{| +Line 1, characters 5-15: +1 | open Pervasives;; + ^^^^^^^^^^ +Error (alert deprecated): module Stdlib.Pervasives +Use Stdlib instead. + +If you need to stay compatible with OCaml < 4.07, you can use the +stdlib-shims library: https://github.com/ocaml/stdlib-shims +|}] diff --git a/testsuite/tests/lib-str/t01.ml b/testsuite/tests/lib-str/t01.ml index 1fb7805a..87621c15 100644 --- a/testsuite/tests/lib-str/t01.ml +++ b/testsuite/tests/lib-str/t01.ml @@ -1,4 +1,5 @@ (* TEST + * hasstr include str *) diff --git a/testsuite/tests/lib-systhreads/ocamltests b/testsuite/tests/lib-systhreads/ocamltests index e818e548..4723c9f1 100644 --- a/testsuite/tests/lib-systhreads/ocamltests +++ b/testsuite/tests/lib-systhreads/ocamltests @@ -1,2 +1,3 @@ testfork.ml testpreempt.ml +threadsigmask.ml diff --git a/testsuite/tests/lib-systhreads/testfork.ml b/testsuite/tests/lib-systhreads/testfork.ml index dbd456ca..3fdf3860 100644 --- a/testsuite/tests/lib-systhreads/testfork.ml +++ b/testsuite/tests/lib-systhreads/testfork.ml @@ -1,9 +1,10 @@ (* TEST + * hassysthreads include systhreads - * not-bsd - ** libunix - *** bytecode - *** native + ** not-bsd + *** libunix + **** bytecode + **** native *) (* POSIX threads and fork() *) diff --git a/testsuite/tests/lib-systhreads/testpreempt.ml b/testsuite/tests/lib-systhreads/testpreempt.ml index 820e3cd0..11d69152 100644 --- a/testsuite/tests/lib-systhreads/testpreempt.ml +++ b/testsuite/tests/lib-systhreads/testpreempt.ml @@ -1,13 +1,14 @@ (* TEST + * hassysthreads (* On Windows, we use Sleep(0) for triggering preemption of threads. However, this does not seem very reliable, so that this test fails on some Windows configurations. See GPR #1533. *) include systhreads - * not-windows - ** bytecode - ** native + ** not-windows + *** bytecode + *** native *) let rec generate_list n = diff --git a/testsuite/tests/lib-systhreads/threadsigmask.ml b/testsuite/tests/lib-systhreads/threadsigmask.ml new file mode 100644 index 00000000..acfaaf93 --- /dev/null +++ b/testsuite/tests/lib-systhreads/threadsigmask.ml @@ -0,0 +1,80 @@ +(* TEST + +* hassysthreads +include systhreads +** not-windows +*** bytecode +*** native +*) + +let stopped = ref false + +(* This function is purposed to do some computations which allocate, + so that the corresponding thread is likely to handle signals if it + is allowed to. *) +let rec loop () = + let rec generate_list n = + let rec aux acc = function + | 0 -> acc + | n -> aux (float n :: acc) (n-1) + in + aux [] n + in + let long_list = generate_list 100000 in + let res = List.length (List.rev_map sin long_list) in + ignore (Sys.opaque_identity res) + +let thread s = + ignore (Thread.sigmask Unix.SIG_UNBLOCK [s]); + while not !stopped do loop () done + +let handler tid_exp cnt signal = + incr cnt; + if Thread.id (Thread.self ()) != !tid_exp then + Printf.printf "Signal received in an unexpected thread !\n" + +let _ = + ignore (Thread.sigmask Unix.SIG_BLOCK [Sys.sigusr1; Sys.sigusr2]); + + (* Install the signal handlers *) + let (tid1, tid2) = (ref 0, ref 0) in + let (cnt1, cnt2) = (ref 0, ref 0) in + Sys.set_signal Sys.sigusr1 (Sys.Signal_handle (handler tid1 cnt1)); + Sys.set_signal Sys.sigusr2 (Sys.Signal_handle (handler tid2 cnt2)); + + (* Spawn the other thread and unblock sigusr2 in the main thread *) + let t1 = Thread.create thread Sys.sigusr1 in + let t2 = Thread.self () in + ignore (Thread.sigmask Unix.SIG_UNBLOCK [Sys.sigusr2]); + tid1 := Thread.id t1; + tid2 := Thread.id t2; + + (* Send signals to the current process. They should be received by the + correct respective threads. *) + let pid = Unix.getpid () in + let cntsent = ref 0 in + (* We loop until each thread has received at least 5 signals and we + have sent more than 100 signals in total. We do not check that all + signals get handled, because they could be missed because of the + lack of fairness of the scheduler. *) + while !cntsent < 100 || !cnt1 < 5 || !cnt2 < 5 do + Unix.kill pid Sys.sigusr1; + Unix.kill pid Sys.sigusr2; + incr cntsent; + Thread.delay 0.07; + + (* Still, if too many signals have been sent, we interrupt the + test to avoid a timeout. *) + if !cntsent > 2000 then begin + stopped := true; + Thread.join t1; + Printf.printf "A thread does not receive signals. %d %d %d\n" !cnt1 !cnt2 !cntsent; + exit 0 + end + done; + + (* Join worker thread *) + stopped := true; + Thread.join t1; + + Printf.printf "OK\n" diff --git a/testsuite/tests/lib-systhreads/threadsigmask.reference b/testsuite/tests/lib-systhreads/threadsigmask.reference new file mode 100644 index 00000000..d86bac9d --- /dev/null +++ b/testsuite/tests/lib-systhreads/threadsigmask.reference @@ -0,0 +1 @@ +OK diff --git a/testsuite/tests/lib-threads/backtrace_threads.ml b/testsuite/tests/lib-threads/backtrace_threads.ml index 8044af3b..96b99e14 100644 --- a/testsuite/tests/lib-threads/backtrace_threads.ml +++ b/testsuite/tests/lib-threads/backtrace_threads.ml @@ -1,5 +1,6 @@ (* TEST +* hassysthreads include systhreads *) diff --git a/testsuite/tests/lib-threads/bank.ml b/testsuite/tests/lib-threads/bank.ml index cf00a717..09e9a70b 100644 --- a/testsuite/tests/lib-threads/bank.ml +++ b/testsuite/tests/lib-threads/bank.ml @@ -1,5 +1,6 @@ (* TEST +* hassysthreads include systhreads *) diff --git a/testsuite/tests/lib-threads/beat.ml b/testsuite/tests/lib-threads/beat.ml index a09980be..e77c0a86 100644 --- a/testsuite/tests/lib-threads/beat.ml +++ b/testsuite/tests/lib-threads/beat.ml @@ -1,5 +1,6 @@ (* TEST +* hassysthreads include systhreads *) diff --git a/testsuite/tests/lib-threads/bufchan.ml b/testsuite/tests/lib-threads/bufchan.ml index 4c243c6c..eadc61bf 100644 --- a/testsuite/tests/lib-threads/bufchan.ml +++ b/testsuite/tests/lib-threads/bufchan.ml @@ -1,5 +1,6 @@ (* TEST +* hassysthreads include systhreads *) diff --git a/testsuite/tests/lib-threads/close.ml b/testsuite/tests/lib-threads/close.ml index 5f8918a3..63e3a178 100644 --- a/testsuite/tests/lib-threads/close.ml +++ b/testsuite/tests/lib-threads/close.ml @@ -1,5 +1,6 @@ (* TEST +* hassysthreads include systhreads *) diff --git a/testsuite/tests/lib-threads/fileio.ml b/testsuite/tests/lib-threads/fileio.ml index d380917a..6bf90b99 100644 --- a/testsuite/tests/lib-threads/fileio.ml +++ b/testsuite/tests/lib-threads/fileio.ml @@ -1,5 +1,6 @@ (* TEST +* hassysthreads include systhreads *) diff --git a/testsuite/tests/lib-threads/pr4466.ml b/testsuite/tests/lib-threads/pr4466.ml index 5d214a6f..e09fee1b 100644 --- a/testsuite/tests/lib-threads/pr4466.ml +++ b/testsuite/tests/lib-threads/pr4466.ml @@ -1,11 +1,8 @@ (* TEST +* hassysthreads include systhreads -* libunix (* Broken on Windows (missing join?), needs to be fixed *) -** bytecode -** native - *) open Printf @@ -21,9 +18,10 @@ open Printf (the one connected to the echo server) *) -let serve_connection s = +let server sock = + let (s, _) = Unix.accept sock in let buf = Bytes.make 1024 '>' in - while true do + for i = 1 to 3 do let n = Unix.recv s buf 2 (Bytes.length buf - 2) [] in if n = 0 then begin Unix.close s; Thread.exit () @@ -32,12 +30,6 @@ let serve_connection s = end done -let server sock = - while true do - let (s, _) = Unix.accept sock in - ignore(Thread.create serve_connection s) - done - let reader s = let buf = Bytes.make 16 ' ' in match Unix.select [s] [] [] 10.0 with @@ -59,7 +51,7 @@ let _ = Unix.bind serv addr; let addr = Unix.getsockname serv in Unix.listen serv 5; - ignore (Thread.create server serv); + let tserv = Thread.create server serv in Thread.delay 0.2; let client = Unix.socket (Unix.domain_of_sockaddr addr) Unix.SOCK_STREAM 0 in @@ -78,4 +70,6 @@ let _ = let a = Thread.create reader client in Thread.delay 0.1; writer client "3333"; - Thread.join a + Thread.join a; + (* Cleanup before exiting *) + Thread.join tserv diff --git a/testsuite/tests/lib-threads/pr5325.ml b/testsuite/tests/lib-threads/pr5325.ml index 27a83098..69f15774 100644 --- a/testsuite/tests/lib-threads/pr5325.ml +++ b/testsuite/tests/lib-threads/pr5325.ml @@ -1,11 +1,8 @@ (* TEST +* hassysthreads include systhreads -* libunix (* Broken on Windows (missing join?), needs to be fixed *) -** bytecode -** native - *) open Printf @@ -19,26 +16,15 @@ open Printf and copies to standard output - main program executes [writer], which writes to the same socket (the one connected to the echo server) - - thread [timeout] causes a failure if nothing happens in 10 seconds. *) -let serve_connection s = +let server sock = + let (s, _) = Unix.accept sock in let buf = Bytes.make 1024 '>' in let n = Unix.read s buf 2 (Bytes.length buf - 2) in ignore (Unix.write s buf 0 (n + 2)); Unix.close s -let server sock = - while true do - let (s, _) = Unix.accept sock in - ignore(Thread.create serve_connection s) - done - -let timeout () = - Thread.delay 10.0; - printf "Time out, exiting...\n%!"; - exit 2 - let reader s = let buf = Bytes.make 1024 ' ' in let n = Unix.read s buf 0 (Bytes.length buf) in @@ -56,8 +42,7 @@ let _ = Unix.bind serv addr; let addr = Unix.getsockname serv in Unix.listen serv 5; - ignore (Thread.create server serv); - ignore (Thread.create timeout ()); + let tserv = Thread.create server serv in Thread.delay 0.5; let client = Unix.socket (Unix.domain_of_sockaddr addr) Unix.SOCK_STREAM 0 in @@ -65,4 +50,5 @@ let _ = let rd = Thread.create reader client in Thread.delay 0.5; writer client "Client data\n"; - Thread.join rd + Thread.join rd; + Thread.join tserv diff --git a/testsuite/tests/lib-threads/pr7638.ml b/testsuite/tests/lib-threads/pr7638.ml index 07e1a81c..3003d93d 100644 --- a/testsuite/tests/lib-threads/pr7638.ml +++ b/testsuite/tests/lib-threads/pr7638.ml @@ -1,5 +1,6 @@ (* TEST +* hassysthreads include systhreads *) diff --git a/testsuite/tests/lib-threads/prodcons.ml b/testsuite/tests/lib-threads/prodcons.ml index 808da43a..93b99ce2 100644 --- a/testsuite/tests/lib-threads/prodcons.ml +++ b/testsuite/tests/lib-threads/prodcons.ml @@ -1,5 +1,6 @@ (* TEST +* hassysthreads include systhreads *) diff --git a/testsuite/tests/lib-threads/prodcons2.ml b/testsuite/tests/lib-threads/prodcons2.ml index 8f3c5b25..58eb8210 100644 --- a/testsuite/tests/lib-threads/prodcons2.ml +++ b/testsuite/tests/lib-threads/prodcons2.ml @@ -1,5 +1,6 @@ (* TEST +* hassysthreads include systhreads *) diff --git a/testsuite/tests/lib-threads/sieve.ml b/testsuite/tests/lib-threads/sieve.ml index 9c6414b8..b44b0902 100644 --- a/testsuite/tests/lib-threads/sieve.ml +++ b/testsuite/tests/lib-threads/sieve.ml @@ -1,5 +1,6 @@ (* TEST +* hassysthreads include systhreads *) diff --git a/testsuite/tests/lib-threads/signal.ml b/testsuite/tests/lib-threads/signal.ml index 2db8fe44..868427c5 100644 --- a/testsuite/tests/lib-threads/signal.ml +++ b/testsuite/tests/lib-threads/signal.ml @@ -1,46 +1,47 @@ (* TEST +* hassysthreads include systhreads files = "sigint.c" -* libunix (* excludes mingw32/64 and msvc32/64 *) +** libunix (* excludes mingw32/64 and msvc32/64 *) -** setup-ocamlc.byte-build-env +*** setup-ocamlc.byte-build-env program = "${test_build_directory}/signal.byte" -*** ocamlc.byte +**** ocamlc.byte program = "sigint" all_modules = "sigint.c" -**** ocamlc.byte +***** ocamlc.byte program = "${test_build_directory}/signal.byte" all_modules = "signal.ml" -***** check-ocamlc.byte-output -****** run -******* check-program-output +****** check-ocamlc.byte-output +******* run +******** check-program-output -** setup-ocamlopt.byte-build-env +*** setup-ocamlopt.byte-build-env program = "${test_build_directory}/signal.opt" -*** ocamlopt.byte +**** ocamlopt.byte program = "sigint" all_modules = "sigint.c" -**** ocamlc.byte +***** ocamlopt.byte program = "${test_build_directory}/signal.opt" all_modules = "signal.ml" -***** check-ocamlopt.byte-output -****** run -******* check-program-output +****** check-ocamlopt.byte-output +******* run +******** check-program-output *) diff --git a/testsuite/tests/lib-threads/sockets.ml b/testsuite/tests/lib-threads/sockets.ml index 9f767077..c7299c42 100644 --- a/testsuite/tests/lib-threads/sockets.ml +++ b/testsuite/tests/lib-threads/sockets.ml @@ -1,10 +1,11 @@ (* TEST +* hassysthreads include systhreads -* libunix (* Broken on Windows (missing join?), needs to be fixed *) -** bytecode -** native +** libunix (* Broken on Windows (missing join?), needs to be fixed *) +*** bytecode +*** native *) diff --git a/testsuite/tests/lib-threads/swapchan.ml b/testsuite/tests/lib-threads/swapchan.ml index 8d7f7522..853b1a20 100644 --- a/testsuite/tests/lib-threads/swapchan.ml +++ b/testsuite/tests/lib-threads/swapchan.ml @@ -1,5 +1,6 @@ (* TEST +* hassysthreads include systhreads *) diff --git a/testsuite/tests/lib-threads/tls.ml b/testsuite/tests/lib-threads/tls.ml index c69db388..ef4fc516 100644 --- a/testsuite/tests/lib-threads/tls.ml +++ b/testsuite/tests/lib-threads/tls.ml @@ -1,5 +1,6 @@ (* TEST +* hassysthreads include systhreads *) diff --git a/testsuite/tests/lib-threads/torture.ml b/testsuite/tests/lib-threads/torture.ml index 9c4a8475..a96314f9 100644 --- a/testsuite/tests/lib-threads/torture.ml +++ b/testsuite/tests/lib-threads/torture.ml @@ -1,5 +1,6 @@ (* TEST +* hassysthreads include systhreads *) @@ -32,7 +33,8 @@ let reader_thread (ic, size) = (* print_string "reader "; print_int n; print_newline(); *) for i = 0 to n-1 do if Bytes.get buff i = 'b' then Thread.exit() - else if Bytes.get buff i <> 'a' then print_string "error in reader_thread\n" + else if Bytes.get buff i <> 'a' then + print_string "error in reader_thread\n" done done diff --git a/testsuite/tests/lib-unix/common/channel_of.ml b/testsuite/tests/lib-unix/common/channel_of.ml new file mode 100644 index 00000000..f61dd949 --- /dev/null +++ b/testsuite/tests/lib-unix/common/channel_of.ml @@ -0,0 +1,66 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +open Printf + +let shouldpass msg fn arg = + try + ignore (fn arg); printf "%s: passed (no error)\n" msg + with Unix.Unix_error(err, _, _) -> + printf "%s: FAILED (error %s)\n" msg (Unix.error_message err) + +let shouldfail msg fn arg = + try + ignore (fn arg); printf "%s: FAILED (no error raised)\n" msg + with Unix.Unix_error(err, _, _) -> + printf "%s: passed (error raised)\n" msg + +let _ = + (* Files *) + begin + let fd = Unix.(openfile "file.tmp" [O_WRONLY;O_CREAT;O_TRUNC] 0o666) in + shouldpass "File 1" Unix.in_channel_of_descr fd; + shouldpass "File 2" Unix.out_channel_of_descr fd; + Unix.close fd + end; + (* Pipes *) + begin + let out, inp = Unix.pipe () in + shouldpass "Pipe 1" Unix.in_channel_of_descr out; + shouldpass "Pipe 2" Unix.out_channel_of_descr inp; + Unix.close out; Unix.close inp + end; + (* Sockets *) + let addr = Unix.ADDR_INET(Unix.inet_addr_loopback, 0) in + begin + let sock = + Unix.socket (Unix.domain_of_sockaddr addr) Unix.SOCK_STREAM 0 in + shouldpass "Stream socket 1" Unix.in_channel_of_descr sock; + shouldpass "Stream socket 2" Unix.out_channel_of_descr sock; + Unix.close sock + end; + begin + let sock = + Unix.socket (Unix.domain_of_sockaddr addr) Unix.SOCK_DGRAM 0 in + shouldfail "Stream socket 1" Unix.in_channel_of_descr sock; + shouldfail "Stream socket 2" Unix.out_channel_of_descr sock; + Unix.close sock + end; + (* Whatever is connected to standard descriptors; hopefully a terminal *) + begin + shouldpass "stdin" Unix.in_channel_of_descr Unix.stdin; + shouldpass "stderr" Unix.out_channel_of_descr Unix.stderr + end; + (* A closed file descriptor should now fail *) + begin + let fd = Unix.(openfile "file.tmp" [O_WRONLY;O_CREAT;O_TRUNC] 0o666) in + Unix.close fd; + shouldfail "Closed file 1" Unix.in_channel_of_descr fd; + shouldfail "Closed file 2" Unix.out_channel_of_descr fd + end; + (* End of test *) + Sys.remove "file.tmp" diff --git a/testsuite/tests/lib-unix/common/channel_of.reference b/testsuite/tests/lib-unix/common/channel_of.reference new file mode 100644 index 00000000..c9cf71da --- /dev/null +++ b/testsuite/tests/lib-unix/common/channel_of.reference @@ -0,0 +1,12 @@ +File 1: passed (no error) +File 2: passed (no error) +Pipe 1: passed (no error) +Pipe 2: passed (no error) +Stream socket 1: passed (no error) +Stream socket 2: passed (no error) +Stream socket 1: passed (error raised) +Stream socket 2: passed (error raised) +stdin: passed (no error) +stderr: passed (no error) +Closed file 1: passed (error raised) +Closed file 2: passed (error raised) diff --git a/testsuite/tests/lib-unix/common/cloexec.ml b/testsuite/tests/lib-unix/common/cloexec.ml index 9b528674..5b5f5693 100644 --- a/testsuite/tests/lib-unix/common/cloexec.ml +++ b/testsuite/tests/lib-unix/common/cloexec.ml @@ -7,40 +7,41 @@ Presumably this is because the OCaml runtime opens files, so that handles that have actually been closed at execution look open and make the test fail. - + One possible fix for this would be to make it possible for ocamltest to compile C-only programs, which will be a bit of work to handle the - output of msvc and will also duplicate what the ocaml compiler itslef + output of msvc and will also duplicate what the OCaml compiler itself already does. *) +* hasunix include unix files = "fdstatus_aux.c fdstatus_main.ml" -*libunix -** setup-ocamlc.byte-build-env +**libunix +*** setup-ocamlc.byte-build-env program = "${test_build_directory}/cloexec.byte" -*** ocamlc.byte +**** ocamlc.byte program = "${test_build_directory}/fdstatus.exe" all_modules = "fdstatus_aux.c fdstatus_main.ml" -**** ocamlc.byte +***** ocamlc.byte program = "${test_build_directory}/cloexec.byte" all_modules= "cloexec.ml" -***** check-ocamlc.byte-output -****** run -******* check-program-output +****** check-ocamlc.byte-output +******* run +******** check-program-output -** setup-ocamlopt.byte-build-env +*** setup-ocamlopt.byte-build-env program = "${test_build_directory}/cloexec.opt" -*** ocamlopt.byte +**** ocamlopt.byte program = "${test_build_directory}/fdstatus.exe" all_modules = "fdstatus_aux.c fdstatus_main.ml" -**** ocamlopt.byte +***** ocamlopt.byte program = "${test_build_directory}/cloexec.opt" all_modules= "cloexec.ml" -***** check-ocamlopt.byte-output -****** run -******* check-program-output +****** check-ocamlopt.byte-output +******* run +******** check-program-output *) @@ -54,7 +55,7 @@ all_modules= "cloexec.ml" let string_of_fd (fd: Unix.file_descr) : string = match Sys.os_type with - | "Unix" | "Cygwin" -> string_of_int (Obj.magic fd : int) + | "Unix" | "Cygwin" -> Int.to_string (Obj.magic fd : int) | "Win32" -> if Sys.word_size = 32 then Int32.to_string (Obj.magic fd : int32) @@ -97,7 +98,7 @@ let _ = p0;p0';p1;p1';p2;p2'; s0;s1;s2; x0;x0';x1;x1';x2;x2' |] in - let untested = + let untested = [untested1; untested2; untested3; untested4; untested5] in let pid = diff --git a/testsuite/tests/lib-unix/common/dup.ml b/testsuite/tests/lib-unix/common/dup.ml index 2cb8c975..b689137c 100644 --- a/testsuite/tests/lib-unix/common/dup.ml +++ b/testsuite/tests/lib-unix/common/dup.ml @@ -1,5 +1,8 @@ (* TEST +* hasunix include unix +** bytecode +** native *) let _ = diff --git a/testsuite/tests/lib-unix/common/dup2.ml b/testsuite/tests/lib-unix/common/dup2.ml index a3dcc120..c3a7facc 100644 --- a/testsuite/tests/lib-unix/common/dup2.ml +++ b/testsuite/tests/lib-unix/common/dup2.ml @@ -1,6 +1,9 @@ (* TEST +* hasunix include unix stderr = "/dev/null" +** bytecode +** native *) let cat file = @@ -18,12 +21,10 @@ let _ = let fd = Unix.(openfile "./tmp.txt" [O_WRONLY;O_TRUNC;O_CREAT;O_SHARE_DELETE] - 0o600) in + 0o600) in out fd "---\n"; Unix.dup2 ~cloexec:true fd Unix.stderr; Unix.close fd; out Unix.stderr "Some output\n"; cat "./tmp.txt"; Sys.remove "./tmp.txt" - - diff --git a/testsuite/tests/lib-unix/common/getaddrinfo.ml b/testsuite/tests/lib-unix/common/getaddrinfo.ml new file mode 100644 index 00000000..b140ef91 --- /dev/null +++ b/testsuite/tests/lib-unix/common/getaddrinfo.ml @@ -0,0 +1,16 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +let () = + let x = Unix.getaddrinfo "\000" "" [] in + Gc.full_major (); + assert (x = []);; + +let () = + let x = Unix.getaddrinfo "" "\000" [] in + Gc.full_major (); + assert (x = []);; diff --git a/testsuite/tests/lib-unix/common/ocamltests b/testsuite/tests/lib-unix/common/ocamltests index 12da8014..2e07ad64 100644 --- a/testsuite/tests/lib-unix/common/ocamltests +++ b/testsuite/tests/lib-unix/common/ocamltests @@ -1,3 +1,4 @@ +channel_of.ml cloexec.ml dup2.ml dup.ml @@ -7,3 +8,5 @@ rename.ml test_unix_cmdline.ml utimes.ml wait_nohang.ml +getaddrinfo.ml +process_pid.ml diff --git a/testsuite/tests/lib-unix/common/pipe_eof.ml b/testsuite/tests/lib-unix/common/pipe_eof.ml index a4c71d7e..3bd6ae5f 100644 --- a/testsuite/tests/lib-unix/common/pipe_eof.ml +++ b/testsuite/tests/lib-unix/common/pipe_eof.ml @@ -1,5 +1,8 @@ (* TEST +* hasunix include unix +** bytecode +** native *) let drain pipe = diff --git a/testsuite/tests/lib-unix/common/process_pid.ml b/testsuite/tests/lib-unix/common/process_pid.ml new file mode 100644 index 00000000..6df536bf --- /dev/null +++ b/testsuite/tests/lib-unix/common/process_pid.ml @@ -0,0 +1,24 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +let null = + if Sys.win32 then + "NUL" + else + "/dev/null" + +let () = + let ic, _ as process = + (* Redirect to null to avoid + "The process tried to write to a nonexistent pipe." on Windows *) + Printf.ksprintf Unix.open_process "echo toto > %s" null + in + assert + (Unix.process_pid process = Unix.process_pid process); + + ignore (Unix.close_process process); + print_endline "OK" diff --git a/testsuite/tests/lib-unix/common/process_pid.reference b/testsuite/tests/lib-unix/common/process_pid.reference new file mode 100644 index 00000000..d86bac9d --- /dev/null +++ b/testsuite/tests/lib-unix/common/process_pid.reference @@ -0,0 +1 @@ +OK diff --git a/testsuite/tests/lib-unix/common/redirections.ml b/testsuite/tests/lib-unix/common/redirections.ml index 409ec365..65fbd60c 100644 --- a/testsuite/tests/lib-unix/common/redirections.ml +++ b/testsuite/tests/lib-unix/common/redirections.ml @@ -2,31 +2,32 @@ files = "reflector.ml" -* setup-ocamlc.byte-build-env +* hasunix +** setup-ocamlc.byte-build-env program = "${test_build_directory}/redirections.byte" -** ocamlc.byte +*** ocamlc.byte program = "${test_build_directory}/reflector.exe" all_modules = "reflector.ml" -*** ocamlc.byte +**** ocamlc.byte include unix program = "${test_build_directory}/redirections.byte" all_modules= "redirections.ml" -**** check-ocamlc.byte-output -***** run -****** check-program-output +***** check-ocamlc.byte-output +****** run +******* check-program-output -* setup-ocamlopt.byte-build-env +** setup-ocamlopt.byte-build-env program = "${test_build_directory}/redirections.opt" -** ocamlopt.byte +*** ocamlopt.byte program = "${test_build_directory}/reflector.exe" all_modules = "reflector.ml" -*** ocamlopt.byte +**** ocamlopt.byte include unix program = "${test_build_directory}/redirections.opt" all_modules= "redirections.ml" -**** check-ocamlopt.byte-output -***** run -****** check-program-output +***** check-ocamlopt.byte-output +****** run +******* check-program-output *) @@ -55,7 +56,8 @@ let test_createprocess systemenv = let pid = Unix.create_process_env refl - [| refl; "-i2o"; "-i2e"; "-o"; "123"; "-e"; "456"; "-i2o"; "-v"; "XVAR" |] + [| refl; "-i2o"; "-i2e"; "-o"; "123"; "-e"; "456"; "-i2o"; "-v"; "XVAR" + |] (Array.append [| "XVAR=xvar" |] systemenv) p_exit f_out f_err in out p_entrance "aaaa\n"; @@ -115,7 +117,7 @@ let test_open_process_full systemenv = (refl ^ " -o 123 -i2o -e 456 -i2e -v XVAR") (Array.append [|"XVAR=xvar"|] systemenv) in output_string i "aa\nbbbb\n"; close_out i; - for _i = 1 to 3 do + for _i = 1 to 3 do out Unix.stdout (input_line o ^ "\n") done; for _i = 1 to 2 do @@ -126,17 +128,13 @@ let test_open_process_full systemenv = out Unix.stdout "!!! reflector exited with an error\n" let _ = - let ocamlrunparam = - match Sys.getenv_opt "OCAMLRUNPARAM" with - | None -> [||] - | Some v -> [|"OCAMLRUNPARAM=" ^ v|] - in + let env = Unix.environment() in (* The following 'close' makes things more difficult. - Under Unix it works fine, but under Win32 create_process + Under Unix it works fine, but under Win32 create_process gives an error if one of the standard handles is closed. *) (* Unix.close Unix.stdin; *) out Unix.stdout "** create_process\n"; - test_createprocess ocamlrunparam; + test_createprocess env; out Unix.stdout "** create_process 2>&1 redirection\n"; test_2ampsup1(); out Unix.stdout "** create_process swap 1-2\n"; @@ -146,4 +144,4 @@ let _ = out Unix.stdout "** open_process_out\n"; test_open_process_out(); out Unix.stdout "** open_process_full\n"; - test_open_process_full ocamlrunparam + test_open_process_full env diff --git a/testsuite/tests/lib-unix/common/reflector.ml b/testsuite/tests/lib-unix/common/reflector.ml index 9188019a..be242c80 100644 --- a/testsuite/tests/lib-unix/common/reflector.ml +++ b/testsuite/tests/lib-unix/common/reflector.ml @@ -1,10 +1,10 @@ -let copyline input output = +let copyline input output = let rec copy() = match input_char input with | exception End_of_file -> output_string output "\n" | char -> output_char output char; - if char='\n' then () else copy() + if char='\n' then () else copy() in copy(); flush output @@ -16,7 +16,7 @@ let output_endline output str = let output_env_var output env_var = let value = match Sys.getenv_opt env_var with - | None -> "" + | None -> "" | Some v -> v in output_endline stdout value @@ -44,8 +44,7 @@ let report_bad_argument _arg = output_endline stderr "" let () = - set_binary_mode_in stdin true; + set_binary_mode_in stdin true; set_binary_mode_out stdout true; set_binary_mode_out stderr true; Arg.parse options report_bad_argument "" - \ No newline at end of file diff --git a/testsuite/tests/lib-unix/common/rename.ml b/testsuite/tests/lib-unix/common/rename.ml index 46000bb3..402ddf0b 100644 --- a/testsuite/tests/lib-unix/common/rename.ml +++ b/testsuite/tests/lib-unix/common/rename.ml @@ -1,5 +1,8 @@ (* TEST +* hasunix include unix +** bytecode +** native *) (* Test the Unix.rename function *) diff --git a/testsuite/tests/lib-unix/common/test_unix_cmdline.ml b/testsuite/tests/lib-unix/common/test_unix_cmdline.ml index 4c782a32..3dffec3b 100644 --- a/testsuite/tests/lib-unix/common/test_unix_cmdline.ml +++ b/testsuite/tests/lib-unix/common/test_unix_cmdline.ml @@ -2,31 +2,32 @@ files = "cmdline_prog.ml" -* setup-ocamlc.byte-build-env +* hasunix +** setup-ocamlc.byte-build-env program = "${test_build_directory}/test_unix_cmdline.byte" -** ocamlc.byte +*** ocamlc.byte program = "${test_build_directory}/cmdline_prog.exe" all_modules = "cmdline_prog.ml" -*** ocamlc.byte +**** ocamlc.byte include unix program = "${test_build_directory}/test_unix_cmdline.byte" all_modules= "test_unix_cmdline.ml" -**** check-ocamlc.byte-output -***** run -****** check-program-output +***** check-ocamlc.byte-output +****** run +******* check-program-output -* setup-ocamlopt.byte-build-env +** setup-ocamlopt.byte-build-env program = "${test_build_directory}/test_unix_cmdline.opt" -** ocamlc.byte +*** ocamlc.byte program = "${test_build_directory}/cmdline_prog.exe" all_modules = "cmdline_prog.ml" -*** ocamlopt.byte +**** ocamlopt.byte include unix program = "${test_build_directory}/test_unix_cmdline.opt" all_modules= "test_unix_cmdline.ml" -**** check-ocamlopt.byte-output -***** run -****** check-program-output +***** check-ocamlopt.byte-output +****** run +******* check-program-output *) @@ -38,7 +39,9 @@ let run args = let out, inp = pipe () in let in_chan = in_channel_of_descr out in set_binary_mode_in in_chan false; - let pid = create_process ("./" ^ prog_name) (Array.of_list (prog_name :: args)) Unix.stdin inp Unix.stderr in + let pid = + create_process ("./" ^ prog_name) (Array.of_list (prog_name :: args)) + Unix.stdin inp Unix.stderr in List.iter (fun arg -> let s = input_line in_chan in Printf.printf "%S -> %S [%s]\n" arg s (if s = arg then "OK" else "FAIL") diff --git a/testsuite/tests/lib-unix/common/utimes.ml b/testsuite/tests/lib-unix/common/utimes.ml index c353544a..0bc32570 100644 --- a/testsuite/tests/lib-unix/common/utimes.ml +++ b/testsuite/tests/lib-unix/common/utimes.ml @@ -1,6 +1,9 @@ (* TEST +* hasunix include unix files = "utimes.txt" +** bytecode +** native *) (* We do not check setting the "last access time" because it is hard to do so on diff --git a/testsuite/tests/lib-unix/common/wait_nohang.ml b/testsuite/tests/lib-unix/common/wait_nohang.ml index a9d6c5d1..fb4cacb9 100644 --- a/testsuite/tests/lib-unix/common/wait_nohang.ml +++ b/testsuite/tests/lib-unix/common/wait_nohang.ml @@ -1,4 +1,5 @@ (* TEST +* hasunix include unix *) diff --git a/testsuite/tests/lib-unix/isatty/isatty_std.ml b/testsuite/tests/lib-unix/isatty/isatty_std.ml index 9e410f5e..1dcff453 100644 --- a/testsuite/tests/lib-unix/isatty/isatty_std.ml +++ b/testsuite/tests/lib-unix/isatty/isatty_std.ml @@ -1,7 +1,10 @@ (* TEST +* hasunix include unix stdin = "/dev/null" stderr = "/dev/null" +** bytecode +** native *) Printf.printf diff --git a/testsuite/tests/lib-unix/unix-execvpe/exec.ml b/testsuite/tests/lib-unix/unix-execvpe/exec.ml index 1c36643e..f4826a99 100644 --- a/testsuite/tests/lib-unix/unix-execvpe/exec.ml +++ b/testsuite/tests/lib-unix/unix-execvpe/exec.ml @@ -1,9 +1,10 @@ (* TEST + * hasunix include unix script = "sh ${test_source_directory}/has-execvpe.sh" - * script - ** bytecode - ** native + ** script + *** bytecode + *** native *) open Printf diff --git a/testsuite/tests/lib-unix/unix-execvpe/has-execvpe.sh b/testsuite/tests/lib-unix/unix-execvpe/has-execvpe.sh index 18f3311f..51707f10 100755 --- a/testsuite/tests/lib-unix/unix-execvpe/has-execvpe.sh +++ b/testsuite/tests/lib-unix/unix-execvpe/has-execvpe.sh @@ -5,7 +5,7 @@ # It makes sense to run the tests only if execvpe is nt implemented. # If it is implemented, the test is skipped. -if grep -q HAS_EXECVPE ${ocamlsrcdir}/byterun/caml/s.h; then +if grep -q "#define HAS_EXECVPE" ${ocamlsrcdir}/runtime/caml/s.h; then exit ${TEST_SKIP}; fi exit ${TEST_PASS} diff --git a/testsuite/tests/lib-unix/unix-execvpe/script3 b/testsuite/tests/lib-unix/unix-execvpe/script3 index 931aac38..93b66113 100755 --- a/testsuite/tests/lib-unix/unix-execvpe/script3 +++ b/testsuite/tests/lib-unix/unix-execvpe/script3 @@ -2,4 +2,3 @@ echo "--- ./script3" echo "FOO is $FOO, BAR is $BAR, BUZ is $BUZ" echo "$# arguments: $*" - diff --git a/testsuite/tests/lib-unix/unix-execvpe/subdir/nonexec b/testsuite/tests/lib-unix/unix-execvpe/subdir/nonexec index b76ada7b..d8534975 100644 --- a/testsuite/tests/lib-unix/unix-execvpe/subdir/nonexec +++ b/testsuite/tests/lib-unix/unix-execvpe/subdir/nonexec @@ -1,2 +1 @@ echo "This script lacks the x bit and should not run!" - diff --git a/testsuite/tests/lib-unix/win-env/test_env.ml b/testsuite/tests/lib-unix/win-env/test_env.ml index 3a12eb91..45a96b82 100644 --- a/testsuite/tests/lib-unix/win-env/test_env.ml +++ b/testsuite/tests/lib-unix/win-env/test_env.ml @@ -7,7 +7,8 @@ modules = "stubs.c" ** native *) -external set_environment_variable: string -> string -> unit = "stub_SetEnvironmentVariable" +external set_environment_variable: string -> string -> unit + = "stub_SetEnvironmentVariable" let find_env s = let env = Unix.environment () in diff --git a/testsuite/tests/lib-unix/win-stat/test.ml b/testsuite/tests/lib-unix/win-stat/test.ml index d83d4add..63ea178a 100644 --- a/testsuite/tests/lib-unix/win-stat/test.ml +++ b/testsuite/tests/lib-unix/win-stat/test.ml @@ -1,7 +1,7 @@ (* TEST -include unix modules = "fakeclock.c" -* windows +* libwin32unix +include unix ** bytecode ** native *) diff --git a/testsuite/tests/lib-unix/win-symlink/ocamltests b/testsuite/tests/lib-unix/win-symlink/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/lib-unix/win-symlink/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/lib-unix/win-symlink/test.ml b/testsuite/tests/lib-unix/win-symlink/test.ml index f47abbde..64b8ae91 100644 --- a/testsuite/tests/lib-unix/win-symlink/test.ml +++ b/testsuite/tests/lib-unix/win-symlink/test.ml @@ -1,7 +1,7 @@ (* TEST +* libwin32unix include unix -* windows ** has_symlink *** bytecode *** native diff --git a/testsuite/tests/link-test/test.ml b/testsuite/tests/link-test/test.ml index bf4f6013..7b618baa 100644 --- a/testsuite/tests/link-test/test.ml +++ b/testsuite/tests/link-test/test.ml @@ -1,6 +1,7 @@ (* TEST -modules = "aliases.ml external_for_pack.ml external.ml submodule.ml test.ml use_in_pack.ml" +modules = "aliases.ml external_for_pack.ml external.ml submodule.ml test.ml \ + use_in_pack.ml" * setup-ocamlc.byte-build-env program = "${test_build_directory}/test.byte" diff --git a/testsuite/tests/local-functions/ocamltests b/testsuite/tests/local-functions/ocamltests new file mode 100644 index 00000000..65f80369 --- /dev/null +++ b/testsuite/tests/local-functions/ocamltests @@ -0,0 +1,2 @@ +tupled.ml +tupled2.ml diff --git a/testsuite/tests/local-functions/tupled.ml b/testsuite/tests/local-functions/tupled.ml new file mode 100644 index 00000000..aef5aacb --- /dev/null +++ b/testsuite/tests/local-functions/tupled.ml @@ -0,0 +1,11 @@ +(* TEST +*) + +(* PR#8705 *) +let () = + let tupled (x, y) = + print_string ""; + fun z -> x, y, z + in + let a, b, c = tupled (0, 1) 2 in + assert (a = 0 && b = 1 && c = 2) diff --git a/testsuite/tests/local-functions/tupled2.ml b/testsuite/tests/local-functions/tupled2.ml new file mode 100644 index 00000000..e1564980 --- /dev/null +++ b/testsuite/tests/local-functions/tupled2.ml @@ -0,0 +1,16 @@ +(* TEST +*) + +(* PR#8705 *) + +let test x = + let tupled (x, y) = (); fun () -> [|x; y|] in + match x with + | None -> [| |] + | Some (x, y) -> tupled (x, y) () + +let expected = "Hello " + +let result = (test (Some (expected, "World!"))).(0) + +let () = assert (String.equal expected result) diff --git a/testsuite/tests/locale/ocamltests b/testsuite/tests/locale/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/locale/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/locale/stubs.c b/testsuite/tests/locale/stubs.c new file mode 100644 index 00000000..1eec8ab1 --- /dev/null +++ b/testsuite/tests/locale/stubs.c @@ -0,0 +1,8 @@ +#include +#include + +value ml_setlocale(value v_locale) +{ + setlocale(LC_ALL,String_val(v_locale)); + return Val_unit; +} diff --git a/testsuite/tests/locale/test.ml b/testsuite/tests/locale/test.ml new file mode 100644 index 00000000..dbd4f449 --- /dev/null +++ b/testsuite/tests/locale/test.ml @@ -0,0 +1,31 @@ +(* TEST +modules = "stubs.c" +*) + +external setlocale : string -> unit = "ml_setlocale" + +let show f = + try + string_of_float @@ f () + with exn -> Printf.sprintf "exn %s" (Printexc.to_string exn) +let pr fmt = Printf.ksprintf print_endline fmt + +let () = + let s = "12345.6789" in + let f = 1.23 in + let test () = + pr " print 1.23 : %s" (show @@ fun () -> f); + pr " parse %S : %s" s (show @@ fun () -> float_of_string s); + pr " roundtrip 1.23 : %s" + (show @@ fun () -> float_of_string @@ string_of_float f); + in + pr "locale from environment"; + setlocale ""; + test (); + pr "locale nl_NL"; + setlocale "nl_NL"; + test (); + pr "locale POSIX"; + setlocale "C"; + test (); + () diff --git a/testsuite/tests/locale/test.reference b/testsuite/tests/locale/test.reference new file mode 100644 index 00000000..9aceecc7 --- /dev/null +++ b/testsuite/tests/locale/test.reference @@ -0,0 +1,12 @@ +locale from environment + print 1.23 : 1.23 + parse "12345.6789" : 12345.6789 + roundtrip 1.23 : 1.23 +locale nl_NL + print 1.23 : 1.23 + parse "12345.6789" : 12345.6789 + roundtrip 1.23 : 1.23 +locale POSIX + print 1.23 : 1.23 + parse "12345.6789" : 12345.6789 + roundtrip 1.23 : 1.23 diff --git a/testsuite/tests/manual-intf-c/curses_stubs.c b/testsuite/tests/manual-intf-c/curses_stubs.c index 33c74a87..dd390e89 100644 --- a/testsuite/tests/manual-intf-c/curses_stubs.c +++ b/testsuite/tests/manual-intf-c/curses_stubs.c @@ -15,7 +15,8 @@ static struct custom_operations curses_window_ops = { custom_hash_default, custom_serialize_default, custom_deserialize_default, - custom_compare_ext_default + custom_compare_ext_default, + custom_fixed_length_default }; /* Accessing the WINDOW * part of an OCaml custom block */ diff --git a/testsuite/tests/manual-intf-c/prog.ml b/testsuite/tests/manual-intf-c/prog.ml index 82eaeac8..9a9e6845 100644 --- a/testsuite/tests/manual-intf-c/prog.ml +++ b/testsuite/tests/manual-intf-c/prog.ml @@ -2,7 +2,7 @@ (* Tests from manual, section intf-c *) (* This test is currently skipped because there is no proper way to - figure out whether Curses is avaiblable or not. If it becomes possible + figure out whether Curses is available or not. If it becomes possible to figure that out, it would be nice to be able to check that the test compiles. Executing seems lessrelevant. *) diff --git a/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml b/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml index 11661d05..8b6bb3fd 100644 --- a/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml +++ b/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml @@ -1,5 +1,5 @@ (* TEST - * toplevel + * expect *) (** Test exhaustiveness. @@ -14,3 +14,80 @@ let test_match_exhaustiveness () = | Some false -> () | None -> () ;; + +[%%expect{| +Line 8, characters 4-83: + 8 | ....match None with + 9 | | exception e -> () +10 | | Some false -> () +11 | | None -> () +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +Some true +val test_match_exhaustiveness : unit -> unit = +|}] +;; + +let test_match_exhaustiveness_nest1 () = + match None with + | Some false -> () + | None | exception _ -> () +;; + +[%%expect{| +Line 2, characters 4-73: +2 | ....match None with +3 | | Some false -> () +4 | | None | exception _ -> () +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +Some true +val test_match_exhaustiveness_nest1 : unit -> unit = +|}] +;; + +let test_match_exhaustiveness_nest2 () = + match None with + | Some false | exception _ -> () + | None -> () +;; + +[%%expect{| +Line 2, characters 4-73: +2 | ....match None with +3 | | Some false | exception _ -> () +4 | | None -> () +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +Some true +val test_match_exhaustiveness_nest2 : unit -> unit = +|}] +;; + +let test_match_exhaustiveness_full () = + match None with + | exception e -> () + | Some false | exception _ -> () + | None | exception _ -> () +;; + +[%%expect{| +Line 2, characters 4-111: +2 | ....match None with +3 | | exception e -> () +4 | | Some false | exception _ -> () +5 | | None | exception _ -> () +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +Some true +Line 4, characters 29-30: +4 | | Some false | exception _ -> () + ^ +Warning 11: this match case is unused. +Line 5, characters 23-24: +5 | | None | exception _ -> () + ^ +Warning 11: this match case is unused. +val test_match_exhaustiveness_full : unit -> unit = +|}] +;; diff --git a/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml.reference b/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml.reference deleted file mode 100644 index 69ba3a45..00000000 --- a/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml.reference +++ /dev/null @@ -1,11 +0,0 @@ - -# * * * * Characters 210-289: - ....match None with - | exception e -> () - | Some false -> () - | None -> () -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -Some true -val test_match_exhaustiveness : unit -> unit = -# diff --git a/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ocaml.reference b/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ocaml.reference deleted file mode 100644 index 20f6afbb..00000000 --- a/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ocaml.reference +++ /dev/null @@ -1,10 +0,0 @@ -Characters 236-315: - ....match None with - | exception e -> () - | Some false -> () - | None -> () -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -Some true -val test_match_exhaustiveness : unit -> unit = - diff --git a/testsuite/tests/match-exception-warnings/no_mixing_under_guard.ml b/testsuite/tests/match-exception-warnings/no_mixing_under_guard.ml new file mode 100644 index 00000000..199f4758 --- /dev/null +++ b/testsuite/tests/match-exception-warnings/no_mixing_under_guard.ml @@ -0,0 +1,21 @@ +(* TEST + * expect +*) +exception Exit + +let r = ref "" + +let guarded f = + match f () with + | true | exception Exit when r := "hello"; true -> !r + | _ -> "other" +;; + +[%%expect{| +exception Exit +val r : string ref = {contents = ""} +Line _, characters 4-25: + | true | exception Exit when r := "hello"; true -> !r + ^^^^^^^^^^^^^^^^^^^^^ +Error: Mixing value and exception patterns under when-guards is not supported. +|}] diff --git a/testsuite/tests/match-exception-warnings/no_value_clauses.ml b/testsuite/tests/match-exception-warnings/no_value_clauses.ml new file mode 100644 index 00000000..f301105b --- /dev/null +++ b/testsuite/tests/match-exception-warnings/no_value_clauses.ml @@ -0,0 +1,15 @@ +(* TEST + * expect +*) + +let test f = + match f () with exception Not_found -> () +;; + +[%%expect{| +Line _, characters 2-43: + match f () with exception Not_found -> () + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: None of the patterns in this 'match' expression match values. +|}] +;; diff --git a/testsuite/tests/match-exception-warnings/placement.ml b/testsuite/tests/match-exception-warnings/placement.ml new file mode 100644 index 00000000..a8423f16 --- /dev/null +++ b/testsuite/tests/match-exception-warnings/placement.ml @@ -0,0 +1,172 @@ +(* TEST + * expect +*) + +(*****************************************************) +(* Restrict where "exception P" patterns can appear. *) +(*****************************************************) + +(* should be accepted *) + +let f x = + match x () with + | _ -> () + | exception _ -> () +;; + +[%%expect{| +val f : (unit -> 'a) -> unit = +|}] +;; + +let f x = + match x () with + | _ | exception _ -> () +;; + +[%%expect{| +val f : (unit -> 'a) -> unit = +|}] +;; + +let f x = + match x () with + | Arg.(Set _ | exception Bad _) -> () + | _ -> () +;; + +[%%expect{| +val f : (unit -> Arg.spec) -> unit = +|}] +;; + +let f x = + match x () with + | _ -> () + | (exception (_ : exn) : int) -> () +;; + +[%%expect{| +val f : (unit -> int) -> unit = +|}] +;; + +(* should be rejected *) + +let f x = + try x (); () + with exception _ -> () +;; + +[%%expect{| +Line _, characters 7-18: + with exception _ -> () + ^^^^^^^^^^^ +Error: Exception patterns are not allowed in this position. +|}] +;; + +let f x = + match x () with + | (exception _) as _pat -> () + | _ -> () +;; + +[%%expect{| +Line _, characters 4-17: + | (exception _) as _pat -> () + ^^^^^^^^^^^^^ +Error: Exception patterns are not allowed in this position. +|}] +;; + +let f x = + match x () with + | (_, exception _, _) -> () +;; + +[%%expect{| +Line _, characters 8-19: + | (_, exception _, _) -> () + ^^^^^^^^^^^ +Error: Exception patterns are not allowed in this position. +|}] +;; + +let f x = + match x () with + | lazy (exception _) -> () + | _ -> () +;; + +[%%expect{| +Line _, characters 9-22: + | lazy (exception _) -> () + ^^^^^^^^^^^^^ +Error: Exception patterns are not allowed in this position. +|}] +;; + +let f x = + match x () with + | { contents = exception _ } -> () +;; + +[%%expect{| +Line _, characters 17-28: + | { contents = exception _ } -> () + ^^^^^^^^^^^ +Error: Exception patterns are not allowed in this position. +|}] +;; + +let f x = + match x () with + | [| exception _ |] -> () +;; + +[%%expect{| +Line _, characters 7-18: + | [| exception _ |] -> () + ^^^^^^^^^^^ +Error: Exception patterns are not allowed in this position. +|}] +;; + +let f x = + match x () with + | Some (exception _) -> () +;; + +[%%expect{| +Line _, characters 9-22: + | Some (exception _) -> () + ^^^^^^^^^^^^^ +Error: Exception patterns are not allowed in this position. +|}] +;; + +let f x = + match x () with + | `A (exception _) -> () +;; + +[%%expect{| +Line _, characters 7-20: + | `A (exception _) -> () + ^^^^^^^^^^^^^ +Error: Exception patterns are not allowed in this position. +|}] +;; + +let f = function + | exception _ -> () + | _ -> () +;; + +[%%expect{| +Line _, characters 4-15: + | exception _ -> () + ^^^^^^^^^^^ +Error: Exception patterns are not allowed in this position. +|}] diff --git a/testsuite/tests/match-exception-warnings/pr7083.ml b/testsuite/tests/match-exception-warnings/pr7083.ml new file mode 100644 index 00000000..cf8ddd64 --- /dev/null +++ b/testsuite/tests/match-exception-warnings/pr7083.ml @@ -0,0 +1,13 @@ +(* TEST + * expect +*) + +let f x = + match x with + | `A -> () + | exception Not_found -> () +;; + +[%%expect{| +val f : [< `A ] -> unit = +|}] diff --git a/testsuite/tests/match-exception-warnings/reachability.ml b/testsuite/tests/match-exception-warnings/reachability.ml new file mode 100644 index 00000000..4a36dc55 --- /dev/null +++ b/testsuite/tests/match-exception-warnings/reachability.ml @@ -0,0 +1,61 @@ +(* TEST + * expect +*) + +let f x = + match x with + | _ -> () + | exception _ -> . +;; + +[%%expect{| +Line _, characters 14-15: + | exception _ -> . + ^ +Error: This match case could not be refuted. + Here is an example of a value that would reach it: _ +|}] +;; + +let f x = + match x with + | _ -> () + | None | exception _ -> . +;; + +[%%expect{| +Line _, characters 21-22: + | None | exception _ -> . + ^ +Error: This match case could not be refuted. + Here is an example of a value that would reach it: _ +|}] +;; + + +let f x = + match x with + | _ -> () + | exception Not_found | None -> . +;; + + +[%%expect{| +Line _, characters 14-23: + | exception Not_found | None -> . + ^^^^^^^^^ +Error: This match case could not be refuted. + Here is an example of a value that would reach it: Not_found +|}] +;; + +let f x = + match x with + | _ | exception _ -> () + | exception Not_found -> . +;; + +[%%expect{| +val f : 'a -> unit = +|}] +;; diff --git a/testsuite/tests/match-exception/identifier_sharing.ml b/testsuite/tests/match-exception/identifier_sharing.ml new file mode 100644 index 00000000..e0bb3890 --- /dev/null +++ b/testsuite/tests/match-exception/identifier_sharing.ml @@ -0,0 +1,9 @@ +(* TEST +*) + +exception String of string + +let _ = + match "foo" with + | str | exception (String str) -> print_endline str + | exception _ -> print_endline "unexpected exception!" diff --git a/testsuite/tests/match-exception/identifier_sharing.reference b/testsuite/tests/match-exception/identifier_sharing.reference new file mode 100644 index 00000000..257cc564 --- /dev/null +++ b/testsuite/tests/match-exception/identifier_sharing.reference @@ -0,0 +1 @@ +foo diff --git a/testsuite/tests/match-exception/ocamltests b/testsuite/tests/match-exception/ocamltests index 1ea017da..8494eb24 100644 --- a/testsuite/tests/match-exception/ocamltests +++ b/testsuite/tests/match-exception/ocamltests @@ -1,5 +1,6 @@ allocation.ml exception_propagation.ml +identifier_sharing.ml match_failure.ml nested_handlers.ml raise_from_success_continuation.ml diff --git a/testsuite/tests/messages/precise_locations.ml b/testsuite/tests/messages/precise_locations.ml index c204d461..3b5612a3 100644 --- a/testsuite/tests/messages/precise_locations.ml +++ b/testsuite/tests/messages/precise_locations.ml @@ -6,9 +6,9 @@ type t = (unit, unit, unit, unit) bar ;; (* PR#7315: we expect the error location on "bar" instead of "(...) bar" *) [%%expect{| -Line _, characters 34-37: - type t = (unit, unit, unit, unit) bar - ^^^ +Line 1, characters 34-37: +1 | type t = (unit, unit, unit, unit) bar + ^^^ Error: Unbound type constructor bar |}];; @@ -16,9 +16,9 @@ function (x : #bar) -> ();; (* we expect the location on "bar" instead of "#bar" *) [%%expect{| -Line _, characters 1-4: - #bar) -> ();; - ^^^ +Line 2, characters 1-4: +2 | #bar) -> ();; + ^^^ Error: Unbound class bar |}];; @@ -27,18 +27,18 @@ function ;; (* we expect the location on "bar" instead of "#bar" *) [%%expect{| -Line _, characters 1-4: - #bar -> () - ^^^ +Line 2, characters 1-4: +2 | #bar -> () + ^^^ Error: Unbound type constructor bar |}];; new bar;; (* we expect the location on "bar" instead of "new bar" *) [%%expect{| -Line _, characters 4-7: - new bar;; - ^^^ +Line 1, characters 4-7: +1 | new bar;; + ^^^ Error: Unbound class bar |}];; @@ -51,28 +51,28 @@ Foo ();; (* "Foo ()": the whole construct, with arguments, is deprecated *) [%%expect{| type t = Foo of unit | Bar -Line _, characters 0-6: - Foo ();; - ^^^^^^ -Error (warning 3): deprecated: Foo +Line 6, characters 0-6: +6 | Foo ();; + ^^^^^^ +Error (alert deprecated): Foo |}];; function Foo _ -> () | Bar -> ();; (* "Foo _", the whole construct is deprecated *) [%%expect{| -Line _, characters 0-5: - Foo _ -> () | Bar -> ();; - ^^^^^ -Error (warning 3): deprecated: Foo +Line 2, characters 0-5: +2 | Foo _ -> () | Bar -> ();; + ^^^^^ +Error (alert deprecated): Foo |}];; open Foo;; (* the error location should be on "Foo" *) [%%expect{| -Line _, characters 5-8: - open Foo;; - ^^^ +Line 1, characters 5-8: +1 | open Foo;; + ^^^ Error: Unbound module Foo |}];; @@ -83,18 +83,18 @@ end);; (* here we expect the error location to be on "open List" as whole rather than "List" *) [%%expect{| -Line _, characters 0-9: - open List - ^^^^^^^^^ +Line 2, characters 0-9: +2 | open List + ^^^^^^^^^ Error (warning 33): unused open Stdlib.List. |}];; type unknown += Foo;; (* unknown, not the whole line *) [%%expect{| -Line _, characters 5-12: - type unknown += Foo;; - ^^^^^^^ +Line 1, characters 5-12: +1 | type unknown += Foo;; + ^^^^^^^ Error: Unbound type constructor unknown |}];; @@ -104,8 +104,8 @@ Foo = Foobar;; (* Foobar, not the whole line *) [%%expect{| type t = .. -Line _, characters 6-12: - Foo = Foobar;; - ^^^^^^ +Line 3, characters 6-12: +3 | Foo = Foobar;; + ^^^^^^ Error: Unbound constructor Foobar |}];; diff --git a/testsuite/tests/misc/ephetest2.ml b/testsuite/tests/misc/ephetest2.ml index 6d9a87c9..1b92172b 100644 --- a/testsuite/tests/misc/ephetest2.ml +++ b/testsuite/tests/misc/ephetest2.ml @@ -57,7 +57,7 @@ and pp_var fmt v = pp_form v.form type env = { - (** resizeable array for cheap *) + (** resizable array for cheap *) vars : (int,var) Hashtbl.t; (** the ephemerons must be alive *) ephes : ephe Stack.t; @@ -144,9 +144,10 @@ let run test init = Stack.clear env.varephe_false; Gc.full_major (); let res = Hashtbl.fold (fun _ v acc -> acc && check_var v) env.vars true in - is_true test "check" res + is_true test "check" res; + env (* Keep env.varephe_true alive. *) let () = for i = 0 to nb_test do - run ("test"^(string_of_int i)) i; + ignore (run ("test"^(Int.to_string i)) i); done diff --git a/testsuite/tests/no-alias-deps/a2235.ml b/testsuite/tests/no-alias-deps/a2235.ml new file mode 100644 index 00000000..7fecab12 --- /dev/null +++ b/testsuite/tests/no-alias-deps/a2235.ml @@ -0,0 +1 @@ +let x = 42 diff --git a/testsuite/tests/no-alias-deps/aliases.compilers.reference b/testsuite/tests/no-alias-deps/aliases.compilers.reference index 4e611b8c..16b8ef98 100644 --- a/testsuite/tests/no-alias-deps/aliases.compilers.reference +++ b/testsuite/tests/no-alias-deps/aliases.compilers.reference @@ -1,5 +1,9 @@ -File "aliases.ml", line 16, characters 12-13: -Warning 49: no cmi file was found in path for module A File "aliases.ml", line 17, characters 12-13: +17 | module A' = A (* missing a.cmi *) + ^ +Warning 49: no cmi file was found in path for module A +File "aliases.ml", line 18, characters 12-13: +18 | module B' = B (* broken b.cmi *) + ^ Warning 49: no valid cmi file was found in path for module B. b.cmi is not a compiled interface diff --git a/testsuite/tests/no-alias-deps/aliases.ml b/testsuite/tests/no-alias-deps/aliases.ml index c0c48056..3b7eca74 100644 --- a/testsuite/tests/no-alias-deps/aliases.ml +++ b/testsuite/tests/no-alias-deps/aliases.ml @@ -4,7 +4,8 @@ compile_only = "true" files = "c.mli d.mli" * setup-ocamlc.byte-build-env ** script -script = "cp ${test_source_directory}/b.cmi.invalid ${test_build_directory}/b.cmi" +script = + "cp ${test_source_directory}/b.cmi.invalid ${test_build_directory}/b.cmi" *** ocamlc.byte all_modules = "c.mli d.mli aliases.ml" **** check-ocamlc.byte-output diff --git a/testsuite/tests/no-alias-deps/gpr2235.ml b/testsuite/tests/no-alias-deps/gpr2235.ml new file mode 100644 index 00000000..d517770e --- /dev/null +++ b/testsuite/tests/no-alias-deps/gpr2235.ml @@ -0,0 +1,21 @@ +(* TEST +flags = "-no-alias-deps -w -49" +compile_only = "true" +files = "a2235.ml lib__2235.ml lib2235.ml user_of_lib2235.ml" +* setup-ocamlc.byte-build-env +** ocamlc.byte +module = "lib__2235.ml" +*** check-ocamlc.byte-output +**** ocamlc.byte +flags = "-no-alias-deps -w -49 -open Lib__2235 -o lib__A2235.cmo" +module = "a2235.ml" +***** check-ocamlc.byte-output +****** ocamlc.byte +flags = "-no-alias-deps -w -49 -open Lib__2235" +module = "lib2235.ml" +******* check-ocamlc.byte-output +******** ocamlc.byte +flags = "-no-alias-deps -w -49" +module = "user_of_lib2235.ml" +********* check-ocamlc.byte-output +*) diff --git a/testsuite/tests/no-alias-deps/lib2235.ml b/testsuite/tests/no-alias-deps/lib2235.ml new file mode 100644 index 00000000..33cb7330 --- /dev/null +++ b/testsuite/tests/no-alias-deps/lib2235.ml @@ -0,0 +1 @@ +module A2235 = A2235 diff --git a/testsuite/tests/no-alias-deps/lib__2235.ml b/testsuite/tests/no-alias-deps/lib__2235.ml new file mode 100644 index 00000000..438d81d8 --- /dev/null +++ b/testsuite/tests/no-alias-deps/lib__2235.ml @@ -0,0 +1 @@ +module A2235 = Lib__A2235 diff --git a/testsuite/tests/no-alias-deps/ocamltests b/testsuite/tests/no-alias-deps/ocamltests index b42a42fd..d107063d 100644 --- a/testsuite/tests/no-alias-deps/ocamltests +++ b/testsuite/tests/no-alias-deps/ocamltests @@ -1 +1,2 @@ aliases.ml +gpr2235.ml diff --git a/testsuite/tests/no-alias-deps/user_of_lib2235.ml b/testsuite/tests/no-alias-deps/user_of_lib2235.ml new file mode 100644 index 00000000..dfc04742 --- /dev/null +++ b/testsuite/tests/no-alias-deps/user_of_lib2235.ml @@ -0,0 +1,3 @@ +open Lib2235 + +let x = A2235.x diff --git a/testsuite/tests/opaque/test.ml b/testsuite/tests/opaque/test.ml index e597f36e..eae9bf20 100644 --- a/testsuite/tests/opaque/test.ml +++ b/testsuite/tests/opaque/test.ml @@ -4,7 +4,8 @@ compile_only = "true" * setup-ocamlopt.byte-build-env ** script -script = "cp -r ${test_source_directory}/fst ${test_source_directory}/intf ${test_source_directory}/snd ${test_build_directory}" +script = "cp -r ${test_source_directory}/fst ${test_source_directory}/intf \ + ${test_source_directory}/snd ${test_build_directory}" *** ocamlopt.byte flags = "-I intf -opaque" all_modules = "intf/opaque_intf.mli" @@ -12,9 +13,11 @@ all_modules = "intf/opaque_intf.mli" flags = "-I intf" all_modules = "intf/opaque_impl.mli intf/regular.mli" ***** script -script = "cp intf/opaque_intf.cmi intf/opaque_impl.cmi intf/regular.cmi intf/opaque_intf.mli intf/opaque_impl.mli intf/regular.mli fst" +script = "cp intf/opaque_intf.cmi intf/opaque_impl.cmi intf/regular.cmi \ + intf/opaque_intf.mli intf/opaque_impl.mli intf/regular.mli fst" ****** script -script = "cp intf/opaque_intf.cmi intf/opaque_impl.cmi intf/regular.cmi intf/opaque_intf.mli intf/opaque_impl.mli intf/regular.mli snd" +script = "cp intf/opaque_intf.cmi intf/opaque_impl.cmi intf/regular.cmi \ + intf/opaque_intf.mli intf/opaque_impl.mli intf/regular.mli snd" ******* ocamlopt.byte flags = "-I fst -opaque" all_modules = "fst/opaque_impl.ml" diff --git a/testsuite/tests/output-complete-obj/ocamltests b/testsuite/tests/output-complete-obj/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/output-complete-obj/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/output-complete-obj/test.ml b/testsuite/tests/output-complete-obj/test.ml new file mode 100644 index 00000000..4dd31355 --- /dev/null +++ b/testsuite/tests/output-complete-obj/test.ml @@ -0,0 +1,33 @@ +(* TEST + +files = "test.ml_stub.c" + +* libunix +** setup-ocamlc.byte-build-env +*** ocamlc.byte +flags = "-w a -output-complete-obj" +program = "test.ml.bc.${objext}" +**** script +script = "${mkexe} -I${ocamlsrcdir}/runtime -o test.ml_bc_stub.exe \ + test.ml.bc.${objext} ${nativecc_libs} test.ml_stub.c" +output = "${compiler_output}" +***** run +program = "./test.ml_bc_stub.exe" +stdout = "program-output" +stderr = "program-output" +** setup-ocamlopt.byte-build-env +*** ocamlopt.byte +flags = "-w a -output-complete-obj" +program = "test.ml.exe.${objext}" +**** script +script = "${mkexe} -I${ocamlsrcdir}/runtime -o test.ml_stub.exe \ + test.ml.exe.${objext} ${bytecc_libs} test.ml_stub.c" +output = "${compiler_output}" +***** run +program = "./test.ml_stub.exe" +stdout = "program-output" +stderr = "program-output" + +*) + +let () = Printf.printf "Test!!\n%!" diff --git a/testsuite/tests/output_obj/test.ml_stub.c b/testsuite/tests/output-complete-obj/test.ml_stub.c similarity index 100% rename from testsuite/tests/output_obj/test.ml_stub.c rename to testsuite/tests/output-complete-obj/test.ml_stub.c diff --git a/testsuite/tests/output_obj/Makefile.disabled b/testsuite/tests/output_obj/Makefile.disabled deleted file mode 100644 index 17fb689f..00000000 --- a/testsuite/tests/output_obj/Makefile.disabled +++ /dev/null @@ -1,58 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Clerc, SED, INRIA Rocquencourt * -#* * -#* Copyright 2010 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -BASEDIR=../.. -SHOULD_FAIL= - - -compile: - @for file in *.ml; do \ - printf " ... testing '$$file' with native"; \ - if $(BYTECODE_ONLY); then \ - echo " => skipped"; \ - else \ - rm -f log $${file}.exe.$(O) $${file}_stub$(EXE); \ - ( set -x; \ - $(OCAMLOPT) -w a -output-complete-obj -o $${file}.exe.$(O) \ - $${file} && \ - $(MKEXE) -I$(CTOPDIR)/byterun -o $${file}_stub$(EXE) \ - $${file}.exe.$(O) $(NATIVECCLIBS) $${file}_stub.c && \ - ./$${file}_stub$(EXE) ) > log 2>&1 \ - && echo " => passed" || (echo " => failed" && cat log); \ - fi \ - done - @for file in *.ml; do \ - printf " ... testing '$$file' with byte"; \ - if [ $(TOOLCHAIN) = msvc ]; then \ - echo " => skipped"; \ - else \ - rm -f log $${file}.bc.$(O) $${file}_bc_stub$(EXE); \ - ( set -x; \ - $(OCAMLC) -ccopt "-I$(CTOPDIR)/byterun" -w a -output-complete-obj\ - -o $${file}.bc.$(O) $${file} && \ - $(MKEXE) -I$(CTOPDIR)/byterun -o $${file}_bc_stub$(EXE) \ - $${file}.bc.$(O) $(BYTECCLIBS) $${file}_stub.c && \ - ./$${file}_bc_stub$(EXE) ) > log 2>&1 \ - && echo " => passed" || (echo " => failed" && cat log); \ - fi; \ - done - @rm -f log - -promote: - -clean: defaultclean - @rm -f ./a.out - -include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/output_obj/test.ml b/testsuite/tests/output_obj/test.ml deleted file mode 100644 index 2cdc201d..00000000 --- a/testsuite/tests/output_obj/test.ml +++ /dev/null @@ -1 +0,0 @@ -let () = Printf.printf "Test!!\n%!" diff --git a/testsuite/tests/parse-errors/escape_error.compilers.reference b/testsuite/tests/parse-errors/escape_error.compilers.reference new file mode 100644 index 00000000..5610c044 --- /dev/null +++ b/testsuite/tests/parse-errors/escape_error.compilers.reference @@ -0,0 +1,13 @@ +Line 8, characters 16-18: +8 | try foo () with ;; + ^^ +Error: Syntax error +Line 2, characters 5-6: +2 | (3 : );; + ^ +Error: Syntax error +Line 2, characters 6-7: +2 | (3 :> );; + ^ +Error: Syntax error + diff --git a/testsuite/tests/parse-errors/escape_error.ml b/testsuite/tests/parse-errors/escape_error.ml new file mode 100644 index 00000000..2a8e99b6 --- /dev/null +++ b/testsuite/tests/parse-errors/escape_error.ml @@ -0,0 +1,12 @@ +(* TEST + * toplevel +*) + +(* Nothing to see here, parse.ml dictates that these be printed as regular + "Syntax error". *) + +try foo () with ;; + +(3 : );; + +(3 :> );; diff --git a/testsuite/tests/parse-errors/expecting.compilers.reference b/testsuite/tests/parse-errors/expecting.compilers.reference new file mode 100644 index 00000000..55e7b7fa --- /dev/null +++ b/testsuite/tests/parse-errors/expecting.compilers.reference @@ -0,0 +1,33 @@ +Line 6, characters 9-10: +6 | | 3 as 3 -> () + ^ +Error: Syntax error: identifier expected. +Line 3, characters 9-11: +3 | | 3 :: -> () + ^^ +Error: Syntax error: pattern expected. +Line 3, characters 8-10: +3 | | 3 | -> () + ^^ +Error: Syntax error: pattern expected. +Line 3, characters 11-13: +3 | | List.( -> () + ^^ +Error: Syntax error: pattern expected. +Line 3, characters 9-10: +3 | | (3 : 3) -> () + ^ +Error: Syntax error: type expected. +Line 3, characters 7-8: +3 | | (3,) -> () + ^ +Error: Syntax error: pattern expected. +Line 3, characters 6-8: +3 | | ( -> () + ^^ +Error: Syntax error: operator expected. +Line 3, characters 12-14: +3 | | (module -> () + ^^ +Error: Syntax error: module-expr expected. + diff --git a/testsuite/tests/parse-errors/expecting.ml b/testsuite/tests/parse-errors/expecting.ml new file mode 100644 index 00000000..4298b818 --- /dev/null +++ b/testsuite/tests/parse-errors/expecting.ml @@ -0,0 +1,35 @@ +(* TEST + * toplevel +*) + +let f = function + | 3 as 3 -> () +;; + +let f = function + | 3 :: -> () +;; + +let f = function + | 3 | -> () +;; + +let f = function + | List.( -> () +;; + +let f = function + | (3 : 3) -> () +;; + +let f = function + | (3,) -> () +;; + +let f = function + | ( -> () +;; + +let f = function + | (module -> () +;; diff --git a/testsuite/tests/parse-errors/ocamltests b/testsuite/tests/parse-errors/ocamltests new file mode 100644 index 00000000..314733ee --- /dev/null +++ b/testsuite/tests/parse-errors/ocamltests @@ -0,0 +1,18 @@ +escape_error.ml +expecting.ml +pr7847.ml +unclosed_class_signature.mli +unclosed_class_simpl_expr1.ml +unclosed_class_simpl_expr2.ml +unclosed_class_simpl_expr3.ml +unclosed_object.ml +unclosed_paren_module_expr1.ml +unclosed_paren_module_expr2.ml +unclosed_paren_module_expr3.ml +unclosed_paren_module_expr4.ml +unclosed_paren_module_expr5.ml +unclosed_paren_module_type.mli +unclosed_sig.mli +unclosed_simple_expr.ml +unclosed_simple_pattern.ml +unclosed_struct.ml diff --git a/testsuite/tests/parse-errors/pr7847.compilers.reference b/testsuite/tests/parse-errors/pr7847.compilers.reference new file mode 100644 index 00000000..8a3c7cbe --- /dev/null +++ b/testsuite/tests/parse-errors/pr7847.compilers.reference @@ -0,0 +1,4 @@ +File "pr7847.ml", line 10, characters 30-31: +10 | external x : unit -> (int,int)`A.t = "x" + ^ +Error: Syntax error diff --git a/testsuite/tests/parse-errors/pr7847.ml b/testsuite/tests/parse-errors/pr7847.ml new file mode 100644 index 00000000..8018109b --- /dev/null +++ b/testsuite/tests/parse-errors/pr7847.ml @@ -0,0 +1,10 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "2" +*** check-ocamlc.byte-output +*) + +(* https://caml.inria.fr/mantis/view.php?id=7847 + The backquote causes a syntax error; this file should be rejected. *) +external x : unit -> (int,int)`A.t = "x" diff --git a/testsuite/tests/parse-errors/unclosed_class_signature.compilers.reference b/testsuite/tests/parse-errors/unclosed_class_signature.compilers.reference new file mode 100644 index 00000000..8c93b930 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_class_signature.compilers.reference @@ -0,0 +1,6 @@ +File "unclosed_class_signature.mli", line 11, characters 0-0: +Error: Syntax error: 'end' expected +File "unclosed_class_signature.mli", line 10, characters 10-16: +10 | class c : object + ^^^^^^ + This 'object' might be unmatched diff --git a/testsuite/tests/parse-errors/unclosed_class_signature.mli b/testsuite/tests/parse-errors/unclosed_class_signature.mli new file mode 100644 index 00000000..0aa6bf49 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_class_signature.mli @@ -0,0 +1,10 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "2" +*** check-ocamlc.byte-output +*) + +(* It is apparently impossible to get the "unclosed object" message. *) + +class c : object diff --git a/testsuite/tests/parse-errors/unclosed_class_simpl_expr1.compilers.reference b/testsuite/tests/parse-errors/unclosed_class_simpl_expr1.compilers.reference new file mode 100644 index 00000000..7cedc39c --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_class_simpl_expr1.compilers.reference @@ -0,0 +1,6 @@ +File "unclosed_class_simpl_expr1.ml", line 10, characters 0-0: +Error: Syntax error: 'end' expected +File "unclosed_class_simpl_expr1.ml", line 8, characters 10-16: +8 | class c = object + ^^^^^^ + This 'object' might be unmatched diff --git a/testsuite/tests/parse-errors/unclosed_class_simpl_expr1.ml b/testsuite/tests/parse-errors/unclosed_class_simpl_expr1.ml new file mode 100644 index 00000000..86466d81 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_class_simpl_expr1.ml @@ -0,0 +1,9 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "2" +*** check-ocamlc.byte-output +*) + +class c = object + method x = 1 diff --git a/testsuite/tests/parse-errors/unclosed_class_simpl_expr2.compilers.reference b/testsuite/tests/parse-errors/unclosed_class_simpl_expr2.compilers.reference new file mode 100644 index 00000000..832b9419 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_class_simpl_expr2.compilers.reference @@ -0,0 +1,6 @@ +File "unclosed_class_simpl_expr2.ml", line 9, characters 0-0: +Error: Syntax error: ')' expected +File "unclosed_class_simpl_expr2.ml", line 8, characters 10-11: +8 | class c = (object end : object end + ^ + This '(' might be unmatched diff --git a/testsuite/tests/parse-errors/unclosed_class_simpl_expr2.ml b/testsuite/tests/parse-errors/unclosed_class_simpl_expr2.ml new file mode 100644 index 00000000..dc762fd2 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_class_simpl_expr2.ml @@ -0,0 +1,8 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "2" +*** check-ocamlc.byte-output +*) + +class c = (object end : object end diff --git a/testsuite/tests/parse-errors/unclosed_class_simpl_expr3.compilers.reference b/testsuite/tests/parse-errors/unclosed_class_simpl_expr3.compilers.reference new file mode 100644 index 00000000..94e1743e --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_class_simpl_expr3.compilers.reference @@ -0,0 +1,6 @@ +File "unclosed_class_simpl_expr3.ml", line 9, characters 0-0: +Error: Syntax error: ')' expected +File "unclosed_class_simpl_expr3.ml", line 8, characters 10-11: +8 | class c = (object end + ^ + This '(' might be unmatched diff --git a/testsuite/tests/parse-errors/unclosed_class_simpl_expr3.ml b/testsuite/tests/parse-errors/unclosed_class_simpl_expr3.ml new file mode 100644 index 00000000..142d3b09 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_class_simpl_expr3.ml @@ -0,0 +1,8 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "2" +*** check-ocamlc.byte-output +*) + +class c = (object end diff --git a/testsuite/tests/parse-errors/unclosed_object.compilers.reference b/testsuite/tests/parse-errors/unclosed_object.compilers.reference new file mode 100644 index 00000000..296e478d --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_object.compilers.reference @@ -0,0 +1,6 @@ +File "unclosed_object.ml", line 11, characters 0-0: +Error: Syntax error: 'end' expected +File "unclosed_object.ml", line 10, characters 8-14: +10 | let o = object + ^^^^^^ + This 'object' might be unmatched diff --git a/testsuite/tests/parse-errors/unclosed_object.ml b/testsuite/tests/parse-errors/unclosed_object.ml new file mode 100644 index 00000000..c74a7135 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_object.ml @@ -0,0 +1,10 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "2" +*** check-ocamlc.byte-output +*) + +(* Failed to get the unclosed object error message. *) + +let o = object diff --git a/testsuite/tests/parse-errors/unclosed_paren_module_expr1.compilers.reference b/testsuite/tests/parse-errors/unclosed_paren_module_expr1.compilers.reference new file mode 100644 index 00000000..73f2b644 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_paren_module_expr1.compilers.reference @@ -0,0 +1,6 @@ +File "unclosed_paren_module_expr1.ml", line 9, characters 0-0: +Error: Syntax error: ')' expected +File "unclosed_paren_module_expr1.ml", line 8, characters 11-12: +8 | module M = (struct end : sig end + ^ + This '(' might be unmatched diff --git a/testsuite/tests/parse-errors/unclosed_paren_module_expr1.ml b/testsuite/tests/parse-errors/unclosed_paren_module_expr1.ml new file mode 100644 index 00000000..b22a3fb4 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_paren_module_expr1.ml @@ -0,0 +1,8 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "2" +*** check-ocamlc.byte-output +*) + +module M = (struct end : sig end diff --git a/testsuite/tests/parse-errors/unclosed_paren_module_expr2.compilers.reference b/testsuite/tests/parse-errors/unclosed_paren_module_expr2.compilers.reference new file mode 100644 index 00000000..802d2a14 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_paren_module_expr2.compilers.reference @@ -0,0 +1,6 @@ +File "unclosed_paren_module_expr2.ml", line 9, characters 0-0: +Error: Syntax error: ')' expected +File "unclosed_paren_module_expr2.ml", line 8, characters 11-12: +8 | module M = (struct end + ^ + This '(' might be unmatched diff --git a/testsuite/tests/parse-errors/unclosed_paren_module_expr2.ml b/testsuite/tests/parse-errors/unclosed_paren_module_expr2.ml new file mode 100644 index 00000000..a786f351 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_paren_module_expr2.ml @@ -0,0 +1,8 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "2" +*** check-ocamlc.byte-output +*) + +module M = (struct end diff --git a/testsuite/tests/parse-errors/unclosed_paren_module_expr3.compilers.reference b/testsuite/tests/parse-errors/unclosed_paren_module_expr3.compilers.reference new file mode 100644 index 00000000..12668431 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_paren_module_expr3.compilers.reference @@ -0,0 +1,6 @@ +File "unclosed_paren_module_expr3.ml", line 9, characters 0-0: +Error: Syntax error: ')' expected +File "unclosed_paren_module_expr3.ml", line 8, characters 11-12: +8 | module M = (val 3 : + ^ + This '(' might be unmatched diff --git a/testsuite/tests/parse-errors/unclosed_paren_module_expr3.ml b/testsuite/tests/parse-errors/unclosed_paren_module_expr3.ml new file mode 100644 index 00000000..4c5c7858 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_paren_module_expr3.ml @@ -0,0 +1,8 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "2" +*** check-ocamlc.byte-output +*) + +module M = (val 3 : diff --git a/testsuite/tests/parse-errors/unclosed_paren_module_expr4.compilers.reference b/testsuite/tests/parse-errors/unclosed_paren_module_expr4.compilers.reference new file mode 100644 index 00000000..0af7a414 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_paren_module_expr4.compilers.reference @@ -0,0 +1,6 @@ +File "unclosed_paren_module_expr4.ml", line 9, characters 0-0: +Error: Syntax error: ')' expected +File "unclosed_paren_module_expr4.ml", line 8, characters 11-12: +8 | module M = (val 3 :> + ^ + This '(' might be unmatched diff --git a/testsuite/tests/parse-errors/unclosed_paren_module_expr4.ml b/testsuite/tests/parse-errors/unclosed_paren_module_expr4.ml new file mode 100644 index 00000000..fc3daefc --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_paren_module_expr4.ml @@ -0,0 +1,8 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "2" +*** check-ocamlc.byte-output +*) + +module M = (val 3 :> diff --git a/testsuite/tests/parse-errors/unclosed_paren_module_expr5.compilers.reference b/testsuite/tests/parse-errors/unclosed_paren_module_expr5.compilers.reference new file mode 100644 index 00000000..e7e8dad1 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_paren_module_expr5.compilers.reference @@ -0,0 +1,6 @@ +File "unclosed_paren_module_expr5.ml", line 9, characters 0-0: +Error: Syntax error: ')' expected +File "unclosed_paren_module_expr5.ml", line 8, characters 11-12: +8 | module M = (val 3 + ^ + This '(' might be unmatched diff --git a/testsuite/tests/parse-errors/unclosed_paren_module_expr5.ml b/testsuite/tests/parse-errors/unclosed_paren_module_expr5.ml new file mode 100644 index 00000000..8ce6c0b2 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_paren_module_expr5.ml @@ -0,0 +1,8 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "2" +*** check-ocamlc.byte-output +*) + +module M = (val 3 diff --git a/testsuite/tests/parse-errors/unclosed_paren_module_type.compilers.reference b/testsuite/tests/parse-errors/unclosed_paren_module_type.compilers.reference new file mode 100644 index 00000000..a1fc808a --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_paren_module_type.compilers.reference @@ -0,0 +1,6 @@ +File "unclosed_paren_module_type.mli", line 9, characters 0-0: +Error: Syntax error: ')' expected +File "unclosed_paren_module_type.mli", line 8, characters 11-12: +8 | module M : (sig end + ^ + This '(' might be unmatched diff --git a/testsuite/tests/parse-errors/unclosed_paren_module_type.mli b/testsuite/tests/parse-errors/unclosed_paren_module_type.mli new file mode 100644 index 00000000..436ce5dc --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_paren_module_type.mli @@ -0,0 +1,8 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "2" +*** check-ocamlc.byte-output +*) + +module M : (sig end diff --git a/testsuite/tests/parse-errors/unclosed_sig.compilers.reference b/testsuite/tests/parse-errors/unclosed_sig.compilers.reference new file mode 100644 index 00000000..ad20205f --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_sig.compilers.reference @@ -0,0 +1,6 @@ +File "unclosed_sig.mli", line 10, characters 0-0: +Error: Syntax error: 'end' expected +File "unclosed_sig.mli", line 8, characters 11-14: +8 | module M : sig + ^^^ + This 'sig' might be unmatched diff --git a/testsuite/tests/parse-errors/unclosed_sig.mli b/testsuite/tests/parse-errors/unclosed_sig.mli new file mode 100644 index 00000000..af49ea40 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_sig.mli @@ -0,0 +1,9 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "2" +*** check-ocamlc.byte-output +*) + +module M : sig + type t = T diff --git a/testsuite/tests/parse-errors/unclosed_simple_expr.compilers.reference b/testsuite/tests/parse-errors/unclosed_simple_expr.compilers.reference new file mode 100644 index 00000000..3aec8f72 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_simple_expr.compilers.reference @@ -0,0 +1,186 @@ +Line 5, characters 5-7: +5 | (3; 2;; + ^^ +Error: Syntax error: ')' expected +Line 5, characters 0-1: +5 | (3; 2;; + ^ + This '(' might be unmatched +Line 2, characters 10-12: +2 | begin 3; 2;; + ^^ +Error: Syntax error: 'end' expected +Line 2, characters 0-5: +2 | begin 3; 2;; + ^^^^^ + This 'begin' might be unmatched +Line 2, characters 10-12: +2 | List.(3; 2;; + ^^ +Error: Syntax error: ')' expected +Line 2, characters 5-6: +2 | List.(3; 2;; + ^ + This '(' might be unmatched +Line 2, characters 17-19: +2 | simple_expr.(3; 2;; + ^^ +Error: Syntax error: ')' expected +Line 2, characters 12-13: +2 | simple_expr.(3; 2;; + ^ + This '(' might be unmatched +Line 2, characters 17-19: +2 | simple_expr.[3; 2;; + ^^ +Error: Syntax error: ']' expected +Line 2, characters 12-13: +2 | simple_expr.[3; 2;; + ^ + This '[' might be unmatched +Line 2, characters 15-17: +2 | simple_expr.%[3;; + ^^ +Error: Syntax error: ']' expected +Line 2, characters 13-14: +2 | simple_expr.%[3;; + ^ + This '[' might be unmatched +Line 2, characters 15-17: +2 | simple_expr.%(3;; + ^^ +Error: Syntax error: ')' expected +Line 2, characters 13-14: +2 | simple_expr.%(3;; + ^ + This '(' might be unmatched +Line 2, characters 15-17: +2 | simple_expr.%{3;; + ^^ +Error: Syntax error: '}' expected +Line 2, characters 13-14: +2 | simple_expr.%{3;; + ^ + This '{' might be unmatched +Line 2, characters 11-13: +2 | foo.Bar.%[3;; + ^^ +Error: Syntax error: ']' expected +Line 2, characters 9-10: +2 | foo.Bar.%[3;; + ^ + This '[' might be unmatched +Line 2, characters 11-13: +2 | foo.Bar.%(3;; + ^^ +Error: Syntax error: ')' expected +Line 2, characters 9-10: +2 | foo.Bar.%(3;; + ^ + This '(' might be unmatched +Line 2, characters 11-13: +2 | foo.Bar.%{3;; + ^^ +Error: Syntax error: '}' expected +Line 2, characters 9-10: +2 | foo.Bar.%{3;; + ^ + This '{' might be unmatched +Line 2, characters 17-19: +2 | simple_expr.{3, 2;; + ^^ +Error: Syntax error: '}' expected +Line 2, characters 12-13: +2 | simple_expr.{3, 2;; + ^ + This '{' might be unmatched +Line 2, characters 10-12: +2 | { x = 3; y;; + ^^ +Error: Syntax error: '}' expected +Line 2, characters 0-1: +2 | { x = 3; y;; + ^ + This '{' might be unmatched +Line 2, characters 16-18: +2 | List.{ x = 3; y ;; + ^^ +Error: Syntax error: '}' expected +Line 2, characters 5-6: +2 | List.{ x = 3; y ;; + ^ + This '{' might be unmatched +Line 2, characters 7-9: +2 | [| 3; 2;; + ^^ +Error: Syntax error: '|]' expected +Line 2, characters 0-2: +2 | [| 3; 2;; + ^^ + This '[|' might be unmatched +Line 2, characters 11-13: +2 | List.[|3; 2;; + ^^ +Error: Syntax error: '|]' expected +Line 2, characters 5-7: +2 | List.[|3; 2;; + ^^ + This '[|' might be unmatched +Line 2, characters 5-7: +2 | [3; 2;; + ^^ +Error: Syntax error: ']' expected +Line 2, characters 0-1: +2 | [3; 2;; + ^ + This '[' might be unmatched +Line 2, characters 10-12: +2 | List.[3; 2;; + ^^ +Error: Syntax error: ']' expected +Line 2, characters 5-6: +2 | List.[3; 2;; + ^ + This '[' might be unmatched +Line 2, characters 13-15: +2 | {< x = 3; y; ;; + ^^ +Error: Syntax error: '>}' expected +Line 2, characters 0-2: +2 | {< x = 3; y; ;; + ^^ + This '{<' might be unmatched +Line 2, characters 17-19: +2 | List.{< x = 3; y ;; + ^^ +Error: Syntax error: '>}' expected +Line 2, characters 5-7: +2 | List.{< x = 3; y ;; + ^^ + This '{<' might be unmatched +Line 2, characters 20-22: +2 | (module struct end :;; + ^^ +Error: Syntax error: ')' expected +Line 2, characters 0-1: +2 | (module struct end :;; + ^ + This '(' might be unmatched +Line 2, characters 25-27: +2 | List.(module struct end :;; + ^^ +Error: Syntax error: ')' expected +Line 2, characters 5-6: +2 | List.(module struct end :;; + ^ + This '(' might be unmatched + +Line 2, characters 2-3: +2 | (=; + ^ +Error: Syntax error: ')' expected +Line 2, characters 0-1: +2 | (=; + ^ + This '(' might be unmatched + diff --git a/testsuite/tests/parse-errors/unclosed_simple_expr.ml b/testsuite/tests/parse-errors/unclosed_simple_expr.ml new file mode 100644 index 00000000..ceeb77ff --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_simple_expr.ml @@ -0,0 +1,49 @@ +(* TEST + * toplevel +*) + +(3; 2;; + +begin 3; 2;; + +List.(3; 2;; + +simple_expr.(3; 2;; + +simple_expr.[3; 2;; + +simple_expr.%[3;; + +simple_expr.%(3;; + +simple_expr.%{3;; + +foo.Bar.%[3;; + +foo.Bar.%(3;; + +foo.Bar.%{3;; + +simple_expr.{3, 2;; + +{ x = 3; y;; + +List.{ x = 3; y ;; + +[| 3; 2;; + +List.[|3; 2;; + +[3; 2;; + +List.[3; 2;; + +{< x = 3; y; ;; + +List.{< x = 3; y ;; + +(module struct end :;; + +List.(module struct end :;; + +(=; diff --git a/testsuite/tests/parse-errors/unclosed_simple_pattern.compilers.reference b/testsuite/tests/parse-errors/unclosed_simple_pattern.compilers.reference new file mode 100644 index 00000000..825979ab --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_simple_pattern.compilers.reference @@ -0,0 +1,53 @@ +Line 7, characters 0-2: +7 | ;; + ^^ +Error: Syntax error: ')' expected +Line 6, characters 9-10: +6 | | List.(_ + ^ + This '(' might be unmatched +Line 4, characters 0-2: +4 | ;; + ^^ +Error: Syntax error: ')' expected +Line 3, characters 4-5: +3 | | (_ + ^ + This '(' might be unmatched +Line 4, characters 0-2: +4 | ;; + ^^ +Error: Syntax error: ')' expected +Line 3, characters 4-5: +3 | | (_ : int + ^ + This '(' might be unmatched +Line 6, characters 18-25: +6 | | (module Foo : sig end + ^^^^^^^ +Error: invalid package type: only module type identifier and 'with type' constraints are supported +Line 7, characters 0-2: +7 | ;; + ^^ +Error: Syntax error: '}' expected +Line 6, characters 4-5: +6 | | { foo; bar; + ^ + This '{' might be unmatched +Line 4, characters 0-2: +4 | ;; + ^^ +Error: Syntax error: ']' expected +Line 3, characters 4-5: +3 | | [ 1; 2; + ^ + This '[' might be unmatched +Line 4, characters 0-2: +4 | ;; + ^^ +Error: Syntax error: '|]' expected +Line 3, characters 4-6: +3 | | [| 3; 4; + ^^ + This '[|' might be unmatched + diff --git a/testsuite/tests/parse-errors/unclosed_simple_pattern.ml b/testsuite/tests/parse-errors/unclosed_simple_pattern.ml new file mode 100644 index 00000000..f0878848 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_simple_pattern.ml @@ -0,0 +1,37 @@ +(* TEST + * toplevel +*) + +let f = function + | List.(_ +;; + +let f = function + | (_ +;; + +let f = function + | (_ : int +;; + +(* Impossible to get the "unclosed (" message here. This case gets absorbed by + val_ident... *) + +let f = function + | (module Foo : sig end +;; + +(* As with expressions, impossible to get the unclosed message for the following + cases. *) + +let f = function + | { foo; bar; +;; + +let f = function + | [ 1; 2; +;; + +let f = function + | [| 3; 4; +;; diff --git a/testsuite/tests/parse-errors/unclosed_struct.compilers.reference b/testsuite/tests/parse-errors/unclosed_struct.compilers.reference new file mode 100644 index 00000000..59bc1c60 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_struct.compilers.reference @@ -0,0 +1,6 @@ +File "unclosed_struct.ml", line 10, characters 0-0: +Error: Syntax error: 'end' expected +File "unclosed_struct.ml", line 8, characters 11-17: +8 | module M = struct + ^^^^^^ + This 'struct' might be unmatched diff --git a/testsuite/tests/parse-errors/unclosed_struct.ml b/testsuite/tests/parse-errors/unclosed_struct.ml new file mode 100644 index 00000000..6066f1e8 --- /dev/null +++ b/testsuite/tests/parse-errors/unclosed_struct.ml @@ -0,0 +1,9 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte +ocamlc_byte_exit_status = "2" +*** check-ocamlc.byte-output +*) + +module M = struct + type t = T diff --git a/testsuite/tests/parsetree/source.ml b/testsuite/tests/parsetree/source.ml index 37590863..c67012e1 100644 --- a/testsuite/tests/parsetree/source.ml +++ b/testsuite/tests/parsetree/source.ml @@ -304,7 +304,7 @@ let pop_castable () = | [] -> raise Not_found ;; -(* We can add foos and bars to this list, and retrive them *) +(* We can add foos and bars to this list, and retrieve them *) push_castable (new foo);; push_castable (new bar);; @@ -720,7 +720,7 @@ end = struct let ik = { tag = Int; label = "int"; - write = string_of_int; + write = Int.to_string; read = int_of_string } let () = Hashtbl.add readTbl "int" (K ik) @@ -838,7 +838,7 @@ let apply x = (module N : S) let () = - let int = forget (create string_of_int succ 0) in + let int = forget (create Int.to_string succ 0) in let str = forget (create (fun s -> s) (fun s -> s ^ s) "X") in List.iter print (List.map apply [int; apply int; apply (apply str)]) @@ -911,7 +911,7 @@ module rec Print : sig end = struct let to_string (type s) t x = match t with - | Int eq -> string_of_int (TypEq.apply eq x) + | Int eq -> Int.to_string (TypEq.apply eq x) | String eq -> Printf.sprintf "%S" (TypEq.apply eq x) | Pair p -> let module P = (val p : PAIR with type t = s) in @@ -946,7 +946,7 @@ let f = function | Some _ [@foooo]-> 2 | None -> 3 ;; -print_endline (string_of_int (f (Some (module struct let x = false end))));; +print_endline (Int.to_string (f (Some (module struct let x = false end))));; type 'a ty = | Int : int ty | Bool : bool ty @@ -3182,7 +3182,7 @@ open Typ let rec to_string: 'a. 'a Typ.typ -> 'a -> string = fun (type s) t x -> match (t : s typ) with - | Int eq -> string_of_int (TypEq.apply eq x) + | Int eq -> Int.to_string (TypEq.apply eq x) | String eq -> Printf.sprintf "%S" (TypEq.apply eq x) | Pair (module P) -> let (x1, x2) = TypEq.apply P.eq x in @@ -3288,7 +3288,7 @@ let subst_lambda ~subst_rec ~free ~subst : _ lambda -> _ = function ~f:(fun ~key ~data acc -> if Names.mem s used then data::acc else acc) in if List.exists used_expr ~f:(fun t -> Names.mem s (free t)) then - let name = s ^ string_of_int (next_id ()) in + let name = s ^ Int.to_string (next_id ()) in `Abs(name, subst_rec ~subst:(Subst.add ~key:s ~data:(`Var name) subst) t) else @@ -3469,7 +3469,7 @@ class ['a] lambda_ops (ops : ('a,'a) #ops Lazy.t) = ~f:(fun ~key ~data acc -> if Names.mem s used then data::acc else acc) in if List.exists used_expr ~f:(fun t -> Names.mem s (!!free t)) then - let name = s ^ string_of_int (next_id ()) in + let name = s ^ Int.to_string (next_id ()) in `Abs(name, !!subst ~sub:(Subst.add ~key:s ~data:(`Var name) sub) t) else @@ -3656,7 +3656,7 @@ let lambda_ops (ops : ('a,'a) #ops Lazy.t) = ~f:(fun ~key ~data acc -> if Names.mem s used then data::acc else acc) in if List.exists used_expr ~f:(fun t -> Names.mem s (!!free t)) then - let name = s ^ string_of_int (next_id ()) in + let name = s ^ Int.to_string (next_id ()) in `Abs(name, !!subst ~sub:(Subst.add ~key:s ~data:(`Var name) sub) t) else @@ -4161,7 +4161,7 @@ module Make(O : Set.OrderedType) : S with type elt = O.t = module rec A : Set.OrderedType = struct type t = int - let compare = Pervasives.compare + let compare = Stdlib.compare end and B : S = struct module C = Make(A) @@ -4746,7 +4746,7 @@ module C : sig module L : module type of List end = A include D' (* let () = - print_endline (string_of_int D'.M.y) + print_endline (Int.to_string D'.M.y) *) open A let f = @@ -4820,6 +4820,7 @@ module Z = functor (_: sig end) (_:sig end) (_: sig end) -> struct end;; module GZ : functor (X: sig end) () (Z: sig end) -> sig end = functor (X: sig end) () (Z: sig end) -> struct end;; module F (X : sig end) = struct type t = int end;; +module F (_ : sig end) = struct type t = int end;; type t = F(Does_not_exist).t;; type expr = [ `Abs of string * expr @@ -5762,7 +5763,7 @@ module rec A type t = Leaf of int | Node of ASet.t let compare x y = match (x,y) with - (Leaf i, Leaf j) -> Pervasives.compare i j + (Leaf i, Leaf j) -> Stdlib.compare i j | (Leaf i, Node t) -> -1 | (Node s, Leaf j) -> 1 | (Node s, Node t) -> ASet.compare s t @@ -6761,7 +6762,7 @@ module PR7135 = struct f (x :> int) (y :> int) end;; -(* exemple of non-ground coercion *) +(* example of non-ground coercion *) module Test1 = struct type t = private int @@ -7354,3 +7355,12 @@ module Indexop = struct end type t = | + + +(* GPR#2034 *) + +let x = ` Foo +let x = ` (* wait for it *) Bar +type (+' a, -' a', ' a'b', 'ab', ' abcd', ' (* ! *) x) t = + ' a * ' a' * ' a'b' * 'ab' * ' abcd' * ' (* !! *) x + as ' a' diff --git a/testsuite/tests/parsetree/test.ml b/testsuite/tests/parsetree/test.ml index 02533bd4..ed635483 100644 --- a/testsuite/tests/parsetree/test.ml +++ b/testsuite/tests/parsetree/test.ml @@ -21,8 +21,9 @@ let remove_locs = attributes = (fun mapper attrs -> let attrs = default_mapper.attributes mapper attrs in - List.filter (fun (s, _) -> s.Location.txt <> "#punning#") - attrs (* this is to accomodate a LexiFi custom extension *) + List.filter (fun a -> + a.Parsetree.attr_name.Location.txt <> "#punning#") + attrs (* this is to accommodate a LexiFi custom extension *) ) } diff --git a/testsuite/tests/parsing/anonymous_class_parameter.compilers.reference b/testsuite/tests/parsing/anonymous_class_parameter.compilers.reference new file mode 100644 index 00000000..bc335501 --- /dev/null +++ b/testsuite/tests/parsing/anonymous_class_parameter.compilers.reference @@ -0,0 +1 @@ +class ['a, _] foo : object method bar : 'a -> 'a end diff --git a/testsuite/tests/parsing/anonymous_class_parameter.ml b/testsuite/tests/parsing/anonymous_class_parameter.ml new file mode 100644 index 00000000..bbecc127 --- /dev/null +++ b/testsuite/tests/parsing/anonymous_class_parameter.ml @@ -0,0 +1,15 @@ +(* TEST + flags = "-i" + * setup-ocamlc.byte-build-env + ** ocamlc.byte + *** check-ocamlc.byte-output +*) + +(* This test is valid OCaml code. + It uses an anonymous type variable as a formal parameter in a class + declaration. This used to be rejected by the parser, even though the + printer (ocamlc -i) could in fact produce it. *) + +class ['a, _] foo = object + method bar: 'a -> 'a = fun x -> x +end diff --git a/testsuite/tests/parsing/arrow_ambiguity.compilers.reference b/testsuite/tests/parsing/arrow_ambiguity.compilers.reference new file mode 100644 index 00000000..3f7b120c --- /dev/null +++ b/testsuite/tests/parsing/arrow_ambiguity.compilers.reference @@ -0,0 +1,2 @@ +File "arrow_ambiguity.ml", line 29, characters 0-0: +Error: Syntax error diff --git a/testsuite/tests/parsing/arrow_ambiguity.ml b/testsuite/tests/parsing/arrow_ambiguity.ml new file mode 100644 index 00000000..5af88afe --- /dev/null +++ b/testsuite/tests/parsing/arrow_ambiguity.ml @@ -0,0 +1,28 @@ +(* TEST + ocamlc_byte_exit_status = "2" + * setup-ocamlc.byte-build-env + ** ocamlc.byte + *** check-ocamlc.byte-output +*) + +(* A potential ambiguity arises because the arrow -> is used + both in the syntax of core types and module types, and + (furthermore) the construction "T with type t = ..." means + that a module type can end with a core type. *) + +module type T = sig type t end + +(* This is OK *) +module type Foo = + (T with type t = int) -> T + +(* This is OK *) +module type Bar = + T with type t = int -> int + +(* This is not OK. + Therefore the shift/reduce conflict on MINUSGREATER + must be solved in favor of shifting. This is why + MINUSGREATER is declared right-associative. *) +module type Bar = + T with type t = int -> T diff --git a/testsuite/tests/parsing/attributes.compilers.reference b/testsuite/tests/parsing/attributes.compilers.reference index bc3967be..30f1620e 100644 --- a/testsuite/tests/parsing/attributes.compilers.reference +++ b/testsuite/tests/parsing/attributes.compilers.reference @@ -1,34 +1,68 @@ [ - structure_item (attributes.ml[8,120+0]..[8,120+8]) + structure_item (attributes.ml[8,120+0]..[8,120+28]) + Pstr_exception + type_exception + attribute "foo" + [] + ptyext_constructor = + extension_constructor (attributes.ml[8,120+0]..[8,120+28]) + attribute "foo" + [] + pext_name = "Foo" + pext_kind = + Pext_decl + [] + None + structure_item (attributes.ml[10,150+0]..[10,150+44]) + Pstr_exception + type_exception + attribute "foo" + [] + ptyext_constructor = + extension_constructor (attributes.ml[10,150+0]..[10,150+44]) + attribute "foo" + [] + pext_name = "Bar" + pext_kind = + Pext_decl + [ + core_type (attributes.ml[10,150+18]..[10,150+21]) + attribute "foo" + [] + Ptyp_constr "int" (attributes.ml[10,150+18]..[10,150+21]) + [] + ] + None + structure_item (attributes.ml[12,196+0]..[12,196+8]) Pstr_attribute "foo" [] - structure_item (attributes.ml[10,130+0]..[11,169+9]) + structure_item (attributes.ml[14,206+0]..[15,245+9]) Pstr_value Nonrec [ attribute "foo" [] - pattern (attributes.ml[10,130+4]..[10,130+38]) ghost + pattern (attributes.ml[14,206+4]..[14,206+27]) ghost Ppat_constraint - pattern (attributes.ml[10,130+4]..[10,130+13]) + pattern (attributes.ml[14,206+4]..[14,206+13]) attribute "foo" [] - Ppat_var "x" (attributes.ml[10,130+5]..[10,130+6]) - core_type (attributes.ml[10,130+16]..[10,130+20]) + Ppat_var "x" (attributes.ml[14,206+5]..[14,206+6]) + core_type (attributes.ml[14,206+16]..[14,206+20]) attribute "foo" [] - Ptyp_constr "unit" (attributes.ml[10,130+16]..[10,130+20]) + Ptyp_constr "unit" (attributes.ml[14,206+16]..[14,206+20]) [] - expression (attributes.ml[10,130+30]..[10,130+32]) + expression (attributes.ml[14,206+30]..[14,206+32]) attribute "foo" [] - Pexp_construct "()" (attributes.ml[10,130+30]..[10,130+32]) + Pexp_construct "()" (attributes.ml[14,206+30]..[14,206+32]) None ] - structure_item (attributes.ml[13,180+0]..[15,217+7]) + structure_item (attributes.ml[17,256+0]..[19,293+7]) Pstr_type Rec [ - type_declaration "t" (attributes.ml[13,180+5]..[13,180+6]) (attributes.ml[13,180+0]..[15,217+7]) + type_declaration "t" (attributes.ml[17,256+5]..[17,256+6]) (attributes.ml[17,256+0]..[19,293+7]) attribute "foo" [] ptype_params = @@ -38,15 +72,15 @@ ptype_kind = Ptype_variant [ - (attributes.ml[14,189+2]..[14,189+27]) - "Foo" (attributes.ml[14,189+4]..[14,189+7]) + (attributes.ml[18,265+2]..[18,265+27]) + "Foo" (attributes.ml[18,265+4]..[18,265+7]) attribute "foo" [] [ - core_type (attributes.ml[14,189+12]..[14,189+13]) + core_type (attributes.ml[18,265+12]..[18,265+13]) attribute "foo" [] - Ptyp_constr "t" (attributes.ml[14,189+12]..[14,189+13]) + Ptyp_constr "t" (attributes.ml[18,265+12]..[18,265+13]) [] ] None @@ -55,23 +89,23 @@ ptype_manifest = None ] - structure_item (attributes.ml[17,226+0]..[17,226+8]) + structure_item (attributes.ml[21,302+0]..[21,302+8]) Pstr_attribute "foo" [] - structure_item (attributes.ml[20,237+0]..[29,344+7]) + structure_item (attributes.ml[24,313+0]..[33,420+7]) Pstr_module - "M" (attributes.ml[20,237+7]..[20,237+8]) + "M" (attributes.ml[24,313+7]..[24,313+8]) attribute "foo" [] - module_expr (attributes.ml[20,237+11]..[28,334+3]) + module_expr (attributes.ml[24,313+11]..[32,410+3]) attribute "foo" [] Pmod_structure [ - structure_item (attributes.ml[21,255+2]..[25,310+11]) + structure_item (attributes.ml[25,331+2]..[29,386+11]) Pstr_type Rec [ - type_declaration "t" (attributes.ml[21,255+7]..[21,255+8]) (attributes.ml[21,255+2]..[25,310+11]) + type_declaration "t" (attributes.ml[25,331+7]..[25,331+8]) (attributes.ml[25,331+2]..[29,386+11]) attribute "foo" [] attribute "foo" @@ -83,50 +117,70 @@ ptype_kind = Ptype_record [ - (attributes.ml[22,268+4]..[22,268+25]) + (attributes.ml[26,344+4]..[26,344+25]) attribute "foo" [] Immutable - "l" (attributes.ml[22,268+4]..[22,268+5]) core_type (attributes.ml[22,268+9]..[22,268+10]) + "l" (attributes.ml[26,344+4]..[26,344+5]) core_type (attributes.ml[26,344+9]..[26,344+10]) attribute "foo" [] - Ptyp_constr "t" (attributes.ml[22,268+9]..[22,268+10]) + Ptyp_constr "t" (attributes.ml[26,344+9]..[26,344+10]) [] ] ptype_private = Public ptype_manifest = None ] - structure_item (attributes.ml[27,323+2]..[27,323+10]) + structure_item (attributes.ml[31,399+2]..[31,399+10]) Pstr_attribute "foo" [] ] - structure_item (attributes.ml[31,353+0]..[39,477+7]) - Pstr_modtype "S" (attributes.ml[31,353+12]..[31,353+13]) + structure_item (attributes.ml[35,429+0]..[45,601+7]) + Pstr_modtype "S" (attributes.ml[35,429+12]..[35,429+13]) attribute "foo" [] - module_type (attributes.ml[31,353+16]..[38,467+3]) + module_type (attributes.ml[35,429+16]..[44,591+3]) attribute "foo" [] Pmty_signature [ - signature_item (attributes.ml[33,374+2]..[34,442+11]) + signature_item (attributes.ml[37,450+2]..[37,450+46]) + Psig_exception + type_exception + attribute "foo" + [] + ptyext_constructor = + extension_constructor (attributes.ml[37,450+2]..[37,450+46]) + attribute "foo" + [] + pext_name = "Bar" + pext_kind = + Pext_decl + [ + core_type (attributes.ml[37,450+20]..[37,450+23]) + attribute "foo" + [] + Ptyp_constr "int" (attributes.ml[37,450+20]..[37,450+23]) + [] + ] + None + signature_item (attributes.ml[39,498+2]..[40,566+11]) Psig_include - module_type (attributes.ml[33,374+10]..[33,374+61]) + module_type (attributes.ml[39,498+10]..[39,498+61]) attribute "foo" [] Pmty_with - module_type (attributes.ml[33,374+11]..[33,374+35]) + module_type (attributes.ml[39,498+11]..[39,498+35]) attribute "foo" [] Pmty_typeof - module_expr (attributes.ml[33,374+27]..[33,374+28]) + module_expr (attributes.ml[39,498+27]..[39,498+28]) attribute "foo" [] - Pmod_ident "M" (attributes.ml[33,374+27]..[33,374+28]) + Pmod_ident "M" (attributes.ml[39,498+27]..[39,498+28]) [ - Pwith_typesubst "t" (attributes.ml[33,374+53]..[33,374+54]) - type_declaration "t" (attributes.ml[33,374+53]..[33,374+54]) (attributes.ml[33,374+48]..[33,374+61]) + Pwith_typesubst "t" (attributes.ml[39,498+53]..[39,498+54]) + type_declaration "t" (attributes.ml[39,498+53]..[39,498+54]) (attributes.ml[39,498+48]..[39,498+61]) ptype_params = [] ptype_cstrs = @@ -136,17 +190,17 @@ ptype_private = Public ptype_manifest = Some - core_type (attributes.ml[33,374+58]..[33,374+61]) - Ptyp_constr "M.t" (attributes.ml[33,374+58]..[33,374+61]) + core_type (attributes.ml[39,498+58]..[39,498+61]) + Ptyp_constr "M.t" (attributes.ml[39,498+58]..[39,498+61]) [] ] attribute "foo" [] - signature_item (attributes.ml[36,455+2]..[36,455+10]) + signature_item (attributes.ml[42,579+2]..[42,579+10]) Psig_attribute "foo" [] ] - structure_item (attributes.ml[41,486+0]..[41,486+8]) + structure_item (attributes.ml[47,610+0]..[47,610+8]) Pstr_attribute "foo" [] ] diff --git a/testsuite/tests/parsing/attributes.ml b/testsuite/tests/parsing/attributes.ml index 8bee64d6..b89df9ca 100644 --- a/testsuite/tests/parsing/attributes.ml +++ b/testsuite/tests/parsing/attributes.ml @@ -5,6 +5,10 @@ *** check-ocamlc.byte-output *) +exception Foo [@foo] [@@foo] + +exception Bar of (int [@foo]) [@foo] [@@foo] + [@@@foo] let (x[@foo]) : unit [@foo] = ()[@foo] @@ -30,6 +34,8 @@ end[@foo] module type S = sig + exception Bar of (int [@foo]) [@foo] [@@foo] + include (module type of (M[@foo]))[@foo] with type t := M.t[@foo] [@@foo] diff --git a/testsuite/tests/parsing/broken_invariants.compilers.reference b/testsuite/tests/parsing/broken_invariants.compilers.reference new file mode 100644 index 00000000..36926ef9 --- /dev/null +++ b/testsuite/tests/parsing/broken_invariants.compilers.reference @@ -0,0 +1,25 @@ +Line 12, characters 20-25: +12 | let empty_tuple = [%tuple];; + ^^^^^ +Error: broken invariant in parsetree: Tuples must have at least 2 components. +Line 1, characters 21-27: +1 | let empty_record = [%record];; + ^^^^^^ +Error: broken invariant in parsetree: Records cannot be empty. +Line 1, characters 20-27: +1 | let empty_apply = [%no_args f];; + ^^^^^^^ +Error: broken invariant in parsetree: Function application with no argument. +Line 1, characters 19-45: +1 | let f = function [%record_with_functor_fields] -> ();; + ^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: broken invariant in parsetree: Functor application not allowed here. +Line 1, characters 3-12: +1 | [%%empty_let];; + ^^^^^^^^^ +Error: broken invariant in parsetree: Let with no bindings. +Line 1, characters 3-13: +1 | [%%empty_type];; + ^^^^^^^^^^ +Error: broken invariant in parsetree: Type declarations cannot be empty. + diff --git a/testsuite/tests/parsing/broken_invariants.ml b/testsuite/tests/parsing/broken_invariants.ml new file mode 100644 index 00000000..4ab9ff99 --- /dev/null +++ b/testsuite/tests/parsing/broken_invariants.ml @@ -0,0 +1,17 @@ +(* TEST + files="illegal_ppx.ml" + * setup-ocamlc.byte-build-env + ** ocamlc.byte with ocamlcommon + all_modules="illegal_ppx.ml" + program="ppx.exe" + *** toplevel + all_modules="broken_invariants.ml" + flags="-ppx '${ocamlrun} ${test_build_directory_prefix}/ocamlc.byte/ppx.exe'" +*) + +let empty_tuple = [%tuple];; +let empty_record = [%record];; +let empty_apply = [%no_args f];; +let f = function [%record_with_functor_fields] -> ();; +[%%empty_let];; +[%%empty_type];; diff --git a/testsuite/tests/parsing/constructor_declarations.compilers.reference b/testsuite/tests/parsing/constructor_declarations.compilers.reference new file mode 100644 index 00000000..eb21ae03 --- /dev/null +++ b/testsuite/tests/parsing/constructor_declarations.compilers.reference @@ -0,0 +1,4 @@ +File "constructor_declarations.ml", line 24, characters 2-3: +24 | | A of int + ^ +Error: Syntax error diff --git a/testsuite/tests/parsing/constructor_declarations.ml b/testsuite/tests/parsing/constructor_declarations.ml new file mode 100644 index 00000000..cac1f1b0 --- /dev/null +++ b/testsuite/tests/parsing/constructor_declarations.ml @@ -0,0 +1,25 @@ +(* TEST + ocamlc_byte_exit_status = "2" + * setup-ocamlc.byte-build-env + ** ocamlc.byte + *** check-ocamlc.byte-output +*) + +(* Allowed. *) +type t = + A of int + | B of bool + +(* Allowed. *) +type u = + | A of int + | B of bool + +(* Allowed. *) +type v = | + +(* Disallowed, but was allowed in 4.07. *) +type w = + | + | A of int + | B of bool diff --git a/testsuite/tests/parsing/docstrings.ml b/testsuite/tests/parsing/docstrings.ml index 199c876d..3cae459d 100644 --- a/testsuite/tests/parsing/docstrings.ml +++ b/testsuite/tests/parsing/docstrings.ml @@ -78,11 +78,24 @@ module Manual : sig (** The comment for the class type my_class_type *) class type my_class_type = object + (** This is a docstring that OCaml <= 4.07.1 drops. + For some reason, when a class type begins with two docstrings, + it keeps only the second one. + This is fixed by GPR#2151. *) + (** The comment for variable x. *) val mutable x : int - (** The commend for method m. *) + (** The comment for method m. *) method m : int -> int + + (** This is a docstring that OCaml <= 4.07.1 misplaces. + For some reason, when a class type ends with two docstrings, + it keeps both of them, but exchanges their order. + This is again fixed by GPR#2151. *) + + (** Another docstring that OCaml <= 4.07.1 misplaces. *) + end (** The comment for module Foo *) @@ -146,6 +159,10 @@ end = struct (** Ambiguous comment on both titi and toto *) method toto = tutu ^ "!" + (** floating 1 *) + + (** floating 2 *) + (** The comment for method m *) method m (f : float) = 1 end @@ -155,6 +172,10 @@ end = struct (** The comment for the instance variable x. *) val mutable x : int + (** floating 1 *) + + (** floating 2 *) + (** The comment for method m. *) method m : int -> int end @@ -222,8 +243,13 @@ module Manual : end[@@ocaml.doc " The comment for class my_class "] class type my_class_type = object + [@@@ocaml.text + " This is a docstring that OCaml <= 4.07.1 drops.\n For some reason, when a class type begins with two docstrings,\n it keeps only the second one.\n This is fixed by GPR#2151. "] val mutable x : int[@@ocaml.doc " The comment for variable x. "] - method m : int -> int[@@ocaml.doc " The commend for method m. "] + method m : int -> int[@@ocaml.doc " The comment for method m. "] + [@@@ocaml.text + " This is a docstring that OCaml <= 4.07.1 misplaces.\n For some reason, when a class type ends with two docstrings,\n it keeps both of them, but exchanges their order.\n This is again fixed by GPR#2151. "] + [@@@ocaml.text " Another docstring that OCaml <= 4.07.1 misplaces. "] end[@@ocaml.doc " The comment for the class type my_class_type "] module Foo : sig @@ -266,12 +292,16 @@ module Manual : " Ambiguous comment on both titi and toto "] method toto = tutu ^ "!"[@@ocaml.doc " Ambiguous comment on both titi and toto "] + [@@@ocaml.text " floating 1 "] + [@@@ocaml.text " floating 2 "] method m (f : float) = 1[@@ocaml.doc " The comment for method m "] end[@@ocaml.doc " The comment for class my_class "] class type my_class_type = object val mutable x : int[@@ocaml.doc " The comment for the instance variable x. "] + [@@@ocaml.text " floating 1 "] + [@@@ocaml.text " floating 2 "] method m : int -> int[@@ocaml.doc " The comment for method m. "] end[@@ocaml.doc " The comment for class type my_class_type "] module Foo = @@ -282,9 +312,9 @@ module Manual : module type my_module_type = sig val x : int end[@@ocaml.doc " The comment for module type my_module_type. "] end ;; -Line _, characters 12-14: - inherit cl - ^^ +Line 141, characters 12-14: +141 | inherit cl + ^^ Error: Unbound class cl |}] diff --git a/testsuite/tests/parsing/extensions.compilers.reference b/testsuite/tests/parsing/extensions.compilers.reference index dfad2ad7..7b5f952c 100644 --- a/testsuite/tests/parsing/extensions.compilers.reference +++ b/testsuite/tests/parsing/extensions.compilers.reference @@ -20,7 +20,7 @@ Pstr_value Nonrec [ - pattern (extensions.ml[10,176+4]..[10,176+46]) ghost + pattern (extensions.ml[10,176+4]..[10,176+31]) ghost Ppat_constraint pattern (extensions.ml[10,176+4]..[10,176+14]) Ppat_extension "foo" @@ -76,7 +76,7 @@ Pstr_value Nonrec [ - pattern (extensions.ml[13,251+4]..[13,251+74]) ghost + pattern (extensions.ml[13,251+4]..[13,251+44]) ghost Ppat_constraint pattern (extensions.ml[13,251+4]..[13,251+23]) Ppat_extension "foo" @@ -147,7 +147,7 @@ Pstr_value Nonrec [ - pattern (extensions.ml[16,344+4]..[16,344+60]) ghost + pattern (extensions.ml[16,344+4]..[16,344+37]) ghost Ppat_constraint pattern (extensions.ml[16,344+4]..[16,344+19]) Ppat_extension "foo" @@ -208,7 +208,7 @@ Pstr_value Nonrec [ - pattern (extensions.ml[20,445+4]..[20,445+60]) ghost + pattern (extensions.ml[20,445+4]..[20,445+44]) ghost Ppat_constraint pattern (extensions.ml[20,445+4]..[20,445+28]) Ppat_extension "foo" @@ -252,7 +252,7 @@ Pstr_value Nonrec [ - pattern (extensions.ml[23,534+4]..[25,606+23]) ghost + pattern (extensions.ml[23,534+4]..[24,573+32]) ghost Ppat_constraint pattern (extensions.ml[23,534+4]..[23,534+38]) Ppat_extension "foo" @@ -323,4 +323,6 @@ ] File "extensions.ml", line 9, characters 3-6: +9 | [%%foo let x = 1 in x] + ^^^ Error: Uninterpreted extension 'foo'. diff --git a/testsuite/tests/parsing/hash_ambiguity.compilers.reference b/testsuite/tests/parsing/hash_ambiguity.compilers.reference new file mode 100644 index 00000000..6caf2013 --- /dev/null +++ b/testsuite/tests/parsing/hash_ambiguity.compilers.reference @@ -0,0 +1,113 @@ +[ + structure_item (hash_ambiguity.ml[8,140+0]..[8,140+28]) + Pstr_class + [ + class_declaration (hash_ambiguity.ml[8,140+0]..[8,140+28]) + pci_virt = Concrete + pci_params = + [ + core_type (hash_ambiguity.ml[8,140+7]..[8,140+9]) + Ptyp_var a + ] + pci_name = "list" (hash_ambiguity.ml[8,140+11]..[8,140+15]) + pci_expr = + class_expr (hash_ambiguity.ml[8,140+18]..[8,140+28]) + Pcl_structure + class_structure + pattern (hash_ambiguity.ml[8,140+24]..[8,140+24]) ghost + Ppat_any + [] + ] + structure_item (hash_ambiguity.ml[9,169+0]..[9,169+27]) + Pstr_type Rec + [ + type_declaration "t" (hash_ambiguity.ml[9,169+8]..[9,169+9]) (hash_ambiguity.ml[9,169+0]..[9,169+27]) + ptype_params = + [ + core_type (hash_ambiguity.ml[9,169+5]..[9,169+7]) + Ptyp_var a + ] + ptype_cstrs = + [] + ptype_kind = + Ptype_abstract + ptype_private = Public + ptype_manifest = + Some + core_type (hash_ambiguity.ml[9,169+12]..[9,169+27]) + Ptyp_alias "a" + core_type (hash_ambiguity.ml[9,169+12]..[9,169+21]) + Ptyp_class "list" (hash_ambiguity.ml[9,169+17]..[9,169+21]) + [ + core_type (hash_ambiguity.ml[9,169+12]..[9,169+15]) + Ptyp_constr "int" (hash_ambiguity.ml[9,169+12]..[9,169+15]) + [] + ] + ] + structure_item (hash_ambiguity.ml[15,425+0]..[15,425+26]) + Pstr_type Rec + [ + type_declaration "u" (hash_ambiguity.ml[15,425+8]..[15,425+9]) (hash_ambiguity.ml[15,425+0]..[15,425+26]) + ptype_params = + [ + core_type (hash_ambiguity.ml[15,425+5]..[15,425+7]) + Ptyp_var a + ] + ptype_cstrs = + [] + ptype_kind = + Ptype_variant + [ + (hash_ambiguity.ml[15,425+12]..[15,425+26]) + "A" (hash_ambiguity.ml[15,425+12]..[15,425+13]) + [ + core_type (hash_ambiguity.ml[15,425+17]..[15,425+26]) + Ptyp_class "list" (hash_ambiguity.ml[15,425+22]..[15,425+26]) + [ + core_type (hash_ambiguity.ml[15,425+17]..[15,425+20]) + Ptyp_constr "int" (hash_ambiguity.ml[15,425+17]..[15,425+20]) + [] + ] + ] + None + ] + ptype_private = Public + ptype_manifest = + None + ] + structure_item (hash_ambiguity.ml[17,453+0]..[17,453+32]) + Pstr_type Rec + [ + type_declaration "v" (hash_ambiguity.ml[17,453+8]..[17,453+9]) (hash_ambiguity.ml[17,453+0]..[17,453+32]) + ptype_params = + [ + core_type (hash_ambiguity.ml[17,453+5]..[17,453+7]) + Ptyp_var a + ] + ptype_cstrs = + [] + ptype_kind = + Ptype_variant + [ + (hash_ambiguity.ml[17,453+12]..[17,453+32]) + "A" (hash_ambiguity.ml[17,453+12]..[17,453+13]) + [ + core_type (hash_ambiguity.ml[17,453+17]..[17,453+20]) + Ptyp_constr "int" (hash_ambiguity.ml[17,453+17]..[17,453+20]) + [] + core_type (hash_ambiguity.ml[17,453+23]..[17,453+32]) + Ptyp_class "list" (hash_ambiguity.ml[17,453+28]..[17,453+32]) + [ + core_type (hash_ambiguity.ml[17,453+23]..[17,453+26]) + Ptyp_constr "int" (hash_ambiguity.ml[17,453+23]..[17,453+26]) + [] + ] + ] + None + ] + ptype_private = Public + ptype_manifest = + None + ] +] + diff --git a/testsuite/tests/parsing/hash_ambiguity.ml b/testsuite/tests/parsing/hash_ambiguity.ml new file mode 100644 index 00000000..32f8297f --- /dev/null +++ b/testsuite/tests/parsing/hash_ambiguity.ml @@ -0,0 +1,17 @@ +(* TEST + flags = "-stop-after parsing -dparsetree" + * setup-ocamlc.byte-build-env + ** ocamlc.byte + *** check-ocamlc.byte-output +*) + +class ['a] list = object end +type 'a t = int #list as 'a + (* Here, "int #list" must be understood as a type. + Another interpretation would be to understand just "int" + as a type and view "#list" as a toplevel directive. + A syntax error would then be reported at "as". *) + +type 'a u = A of int #list + +type 'a v = A of int * int #list diff --git a/testsuite/tests/parsing/illegal_ppx.ml b/testsuite/tests/parsing/illegal_ppx.ml new file mode 100644 index 00000000..b8280904 --- /dev/null +++ b/testsuite/tests/parsing/illegal_ppx.ml @@ -0,0 +1,38 @@ +module H = Ast_helper +module M = Ast_mapper +open Parsetree +let empty_tuple loc = H.Exp.tuple ~loc [] +let empty_record loc = H.Exp.record ~loc [] None +let empty_apply loc f = + H.Exp.apply ~loc f [] + +let empty_let loc = H.Str.value ~loc Asttypes.Nonrecursive [] +let empty_type loc = H.Str.type_ ~loc Asttypes.Nonrecursive [] +let functor_id loc = Location.mkloc + (Longident.( Lapply (Lident "F", Lident "X"))) loc +let complex_record loc = + H.Pat.record ~loc [functor_id loc, H.Pat.any ~loc () ] Asttypes.Closed + +let super = M.default_mapper +let expr mapper e = + match e.pexp_desc with + | Pexp_extension ({txt="tuple";loc},_) -> empty_tuple loc + | Pexp_extension({txt="record";loc},_) -> empty_record loc + | Pexp_extension({txt="no_args";loc},PStr[{pstr_desc= Pstr_eval (e,_);_}]) + -> empty_apply loc e + | _ -> super.M.expr mapper e + +let pat mapper p = + match p.ppat_desc with + | Ppat_extension ({txt="record_with_functor_fields";loc},_) -> + complex_record loc + | _ -> super.M.pat mapper p + +let structure_item mapper stri = match stri.pstr_desc with + | Pstr_extension (({Location.txt="empty_let";loc},_),_) -> empty_let loc + | Pstr_extension (({Location.txt="empty_type";loc},_),_) -> empty_type loc + | _ -> super.structure_item mapper stri + +let () = M.register "illegal ppx" (fun _ -> + { super with expr; pat; structure_item } + ) diff --git a/testsuite/tests/parsing/int_and_float_with_modifier.compilers.reference b/testsuite/tests/parsing/int_and_float_with_modifier.compilers.reference index 84eddc7c..3b3ed7e1 100644 --- a/testsuite/tests/parsing/int_and_float_with_modifier.compilers.reference +++ b/testsuite/tests/parsing/int_and_float_with_modifier.compilers.reference @@ -83,4 +83,6 @@ ] File "int_and_float_with_modifier.ml", line 10, characters 2-57: +10 | 1234567890_1234567890_1234567890_1234567890_1234567890z + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Unknown modifier 'z' for literal 1234567890_1234567890_1234567890_1234567890_1234567890z diff --git a/testsuite/tests/parsing/ocamltests b/testsuite/tests/parsing/ocamltests index b509fdb8..8879838c 100644 --- a/testsuite/tests/parsing/ocamltests +++ b/testsuite/tests/parsing/ocamltests @@ -1,11 +1,17 @@ +anonymous_class_parameter.ml +arrow_ambiguity.ml attributes.ml +broken_invariants.ml +constructor_declarations.ml docstrings.ml extended_indexoperators.ml extensions.ml +hash_ambiguity.ml int_and_float_with_modifier.ml pr6604_2.ml pr6604_3.ml pr6604.ml pr6865.ml pr7165.ml +reloc.ml shortcut_ext_attr.ml diff --git a/testsuite/tests/parsing/pr6604.compilers.reference b/testsuite/tests/parsing/pr6604.compilers.reference index 634351de..1be03a31 100644 --- a/testsuite/tests/parsing/pr6604.compilers.reference +++ b/testsuite/tests/parsing/pr6604.compilers.reference @@ -1,2 +1,4 @@ File "pr6604.ml", line 9, characters 0-1: +9 | #1 + ^ Error: Syntax error diff --git a/testsuite/tests/parsing/pr6604_2.compilers.reference b/testsuite/tests/parsing/pr6604_2.compilers.reference index 3d5c60ef..2de5677c 100644 --- a/testsuite/tests/parsing/pr6604_2.compilers.reference +++ b/testsuite/tests/parsing/pr6604_2.compilers.reference @@ -1,2 +1,4 @@ File "pr6604_2.ml", line 9, characters 1-2: +9 | #1 "pr6604.ml" + ^ Error: Syntax error diff --git a/testsuite/tests/parsing/pr6865.compilers.reference b/testsuite/tests/parsing/pr6865.compilers.reference index fb417c36..97017f96 100644 --- a/testsuite/tests/parsing/pr6865.compilers.reference +++ b/testsuite/tests/parsing/pr6865.compilers.reference @@ -49,4 +49,6 @@ ] File "pr6865.ml", line 9, characters 4-7: +9 | let%foo x = 42 + ^^^ Error: Uninterpreted extension 'foo'. diff --git a/testsuite/tests/parsing/pr7165.compilers.reference b/testsuite/tests/parsing/pr7165.compilers.reference index 55fe3c49..de62d810 100644 --- a/testsuite/tests/parsing/pr7165.compilers.reference +++ b/testsuite/tests/parsing/pr7165.compilers.reference @@ -1,2 +1,4 @@ File "pr7165.ml", line 12, characters 1-23: +12 | #9342101923012312312 "" + ^^^^^^^^^^^^^^^^^^^^^^ Error: Invalid lexer directive "#9342101923012312312 \"\"": line number out of range diff --git a/testsuite/tests/parsing/reloc.ml b/testsuite/tests/parsing/reloc.ml new file mode 100644 index 00000000..0948d171 --- /dev/null +++ b/testsuite/tests/parsing/reloc.ml @@ -0,0 +1,25 @@ +(* TEST + flags = "-I ${ocamlsrcdir}/parsing -I ${ocamlsrcdir}/toplevel" + include ocamlcommon + * expect +*) + +(* Check that [e.pexp_loc :: e.pexp_loc_stack] includes all + intermediate locations of an expression. *) + +let blocks = + let s = {| ( (* comment *) (( "contant" [@attr] ) (* comment *))) |} in + let e = Parse.expression (Lexing.from_string s) in + let extract (loc : Location.t) = + let a = loc.loc_start.pos_cnum in + let b = loc.loc_end.pos_cnum in + String.sub s a (b - a) + in + List.map extract (e.pexp_loc :: e.pexp_loc_stack) +;; +[%%expect {| +val blocks : string list = + ["( (* comment *) (( \"contant\" [@attr] ) (* comment *)))"; + "(( \"contant\" [@attr] ) (* comment *))"; "( \"contant\" [@attr] )"; + "\"contant\""] +|}];; diff --git a/testsuite/tests/parsing/shortcut_ext_attr.compilers.reference b/testsuite/tests/parsing/shortcut_ext_attr.compilers.reference index d8ceb058..414aa824 100644 --- a/testsuite/tests/parsing/shortcut_ext_attr.compilers.reference +++ b/testsuite/tests/parsing/shortcut_ext_attr.compilers.reference @@ -56,7 +56,9 @@ expression (shortcut_ext_attr.ml[13,261+3]..[13,261+29]) attribute "foo" [] - Pexp_open Fresh ""M" (shortcut_ext_attr.ml[13,261+22]..[13,261+23])" + Pexp_open Fresh + module_expr (shortcut_ext_attr.ml[13,261+22]..[13,261+23]) + Pmod_ident "M" (shortcut_ext_attr.ml[13,261+22]..[13,261+23]) expression (shortcut_ext_attr.ml[13,261+27]..[13,261+29]) Pexp_construct "()" (shortcut_ext_attr.ml[13,261+27]..[13,261+29]) None @@ -387,7 +389,7 @@ Pcf_method Public "x" (shortcut_ext_attr.ml[42,939+17]..[42,939+18]) Concrete Fresh - expression (shortcut_ext_attr.ml[42,939+10]..[42,939+22]) ghost + expression (shortcut_ext_attr.ml[42,939+21]..[42,939+22]) ghost Pexp_poly expression (shortcut_ext_attr.ml[42,939+21]..[42,939+22]) Pexp_constant PConst_int (3,None) @@ -407,7 +409,7 @@ Pcf_method Private "x" (shortcut_ext_attr.ml[44,993+26]..[44,993+27]) Concrete Override - expression (shortcut_ext_attr.ml[44,993+10]..[44,993+31]) ghost + expression (shortcut_ext_attr.ml[44,993+30]..[44,993+31]) ghost Pexp_poly expression (shortcut_ext_attr.ml[44,993+30]..[44,993+31]) Pexp_constant PConst_int (3,None) @@ -536,7 +538,7 @@ module_type (shortcut_ext_attr.ml[71,1478+19]..[71,1478+20]) Pmty_ident "S" (shortcut_ext_attr.ml[71,1478+19]..[71,1478+20]) module_type (shortcut_ext_attr.ml[72,1503+4]..[73,1535+19]) - Pmty_functor "_" (_none_[1,0+-1]..[1,0+-1]) ghost + Pmty_functor "_" (_none_[0,0+-1]..[0,0+-1]) ghost module_type (shortcut_ext_attr.ml[72,1503+5]..[72,1503+27]) attribute "foo" [] @@ -687,14 +689,16 @@ [ structure_item (shortcut_ext_attr.ml[86,1759+0]..[86,1759+21]) Pstr_exception - extension_constructor (shortcut_ext_attr.ml[86,1759+0]..[86,1759+21]) - attribute "foo" - [] - pext_name = "X" - pext_kind = - Pext_decl - [] - None + type_exception + ptyext_constructor = + extension_constructor (shortcut_ext_attr.ml[86,1759+0]..[86,1759+21]) + attribute "foo" + [] + pext_name = "X" + pext_kind = + Pext_decl + [] + None ] structure_item (shortcut_ext_attr.ml[88,1782+0]..[88,1782+22]) ghost Pstr_extension "foo" @@ -756,7 +760,9 @@ Pstr_extension "foo" [ structure_item (shortcut_ext_attr.ml[94,1905+0]..[94,1905+16]) - Pstr_open Fresh "M" (shortcut_ext_attr.ml[94,1905+15]..[94,1905+16]) + Pstr_open Fresh + module_expr (shortcut_ext_attr.ml[94,1905+15]..[94,1905+16]) + Pmod_ident "M" (shortcut_ext_attr.ml[94,1905+15]..[94,1905+16]) attribute "foo" [] ] @@ -858,14 +864,16 @@ [ signature_item (shortcut_ext_attr.ml[105,2091+2]..[105,2091+23]) Psig_exception - extension_constructor (shortcut_ext_attr.ml[105,2091+2]..[105,2091+23]) - attribute "foo" - [] - pext_name = "X" - pext_kind = - Pext_decl - [] - None + type_exception + ptyext_constructor = + extension_constructor (shortcut_ext_attr.ml[105,2091+2]..[105,2091+23]) + attribute "foo" + [] + pext_name = "X" + pext_kind = + Pext_decl + [] + None ] signature_item (shortcut_ext_attr.ml[107,2116+2]..[107,2116+24]) ghost Psig_extension "foo" @@ -975,4 +983,6 @@ ] File "shortcut_ext_attr.ml", line 10, characters 6-9: +10 | let%foo[@foo] x = 3 + ^^^ Error: Uninterpreted extension 'foo'. diff --git a/testsuite/tests/ppx-attributes/warning.ml b/testsuite/tests/ppx-attributes/warning.ml index 0c74ae7a..0ae66674 100644 --- a/testsuite/tests/ppx-attributes/warning.ml +++ b/testsuite/tests/ppx-attributes/warning.ml @@ -2,6 +2,7 @@ *) [@@@ocaml.warning "@A"] +[@@@ocaml.alert "++all"] (* Fixture *) @@ -25,26 +26,26 @@ module A = struct let _ = let x = 1 in () end [@@ocaml.warning "-26"] module rec B : sig type t end = struct type t = T.deprecated end -[@@ocaml.warning "-3"] +[@@ocaml.alert "-deprecated"] module type T = sig type t = T.deprecated end -[@@ocaml.warning "-3"] +[@@ocaml.alert "-deprecated"] (* Signature items *) module type S = sig val x : T.deprecated - [@@ocaml.warning "-3"] + [@@ocaml.alert "-deprecated"] module AA : sig type t = T.deprecated end - [@@ocaml.warning "-3"] + [@@ocaml.alert "-deprecated"] module rec BB : sig type t = T.deprecated end - [@@ocaml.warning "-3"] + [@@ocaml.alert "-deprecated"] module type T = sig type t = T.deprecated end - [@@ocaml.warning "-3"] + [@@ocaml.alert "-deprecated"] include DEPRECATED - [@@ocaml.warning "-3"] + [@@ocaml.alert "-deprecated"] end diff --git a/testsuite/tests/ppx-contexts/myppx.ml b/testsuite/tests/ppx-contexts/myppx.ml index 738fd9a4..a42f0721 100644 --- a/testsuite/tests/ppx-contexts/myppx.ml +++ b/testsuite/tests/ppx-contexts/myppx.ml @@ -3,8 +3,43 @@ open Ast_mapper let () = + let quote_strings li = + List.map (Printf.sprintf "%S") li |> String.concat " " in + let quote_option = function + | None -> "None" + | Some s -> Printf.sprintf "Some(%S)" s in register "test" (fun _ -> - Printf.eprintf "use_threads=%b\n" !Clflags.use_threads; - Printf.eprintf "use_vmthreads=%b\n" !Clflags.use_vmthreads; + Printf.eprintf "\n"; + Printf.eprintf "tool_name: %S\n" + (tool_name ()); + (* + (* Note: we do not test include_dirs, load_path + as they produce non-portable paths *) + Printf.eprintf "include_dirs: [%s]\n" + (quote_strings !Clflags.include_dirs); + Printf.eprintf "load_path: [%s]\n" + (quote_strings !Config.load_path); + *) + Printf.eprintf "open_modules: [%s]\n" + (quote_strings !Clflags.open_modules); + Printf.eprintf "for_package: %S\n" + (quote_option !Clflags.for_package); + Printf.eprintf "use_debug: %B\n" + !Clflags.debug; + Printf.eprintf "use_threads: %B\n" + !Clflags.use_threads; + Printf.eprintf "use_vmthreads: %B\n" + !Clflags.use_vmthreads; + Printf.eprintf "recursive_types: %B\n" + !Clflags.recursive_types; + Printf.eprintf "principal: %B\n" + !Clflags.principal; + Printf.eprintf "transparent_modules: %B\n" + !Clflags.transparent_modules; + Printf.eprintf "unboxed_types: %B\n" + !Clflags.unboxed_types; + Printf.eprintf "unsafe_string: %B\n" + !Clflags.unsafe_string; + Printf.eprintf "\n"; + flush stderr; default_mapper); - diff --git a/testsuite/tests/ppx-contexts/test.compilers.reference b/testsuite/tests/ppx-contexts/test.compilers.reference index ac117c7a..c6f393f8 100644 --- a/testsuite/tests/ppx-contexts/test.compilers.reference +++ b/testsuite/tests/ppx-contexts/test.compilers.reference @@ -1,4 +1,31 @@ -use_threads=true -use_vmthreads=false -use_threads=false -use_vmthreads=true + +tool_name: "ocamlc" +open_modules: ["List"] +for_package: "None" +use_debug: false +use_threads: true +use_vmthreads: false +recursive_types: true +principal: true +transparent_modules: false +unboxed_types: true +unsafe_string: false + +File "_none_", line 1: +Alert deprecated: The -vmthread argument of ocamlc is deprecated +since OCaml 4.08.0. Please switch to system threads, which have the +same API. Lightweight threads with VM-level scheduling are provided by +third-party libraries such as Lwt, but with a different API. + +tool_name: "ocamlc" +open_modules: [] +for_package: "None" +use_debug: true +use_threads: false +use_vmthreads: true +recursive_types: false +principal: false +transparent_modules: true +unboxed_types: false +unsafe_string: true + diff --git a/testsuite/tests/ppx-contexts/test.ml b/testsuite/tests/ppx-contexts/test.ml index 4ad226e9..3a9719e9 100644 --- a/testsuite/tests/ppx-contexts/test.ml +++ b/testsuite/tests/ppx-contexts/test.ml @@ -7,10 +7,23 @@ program = "${test_build_directory}/myppx.exe" all_modules = "myppx.ml" *** ocamlc.byte module = "test.ml" -flags = "-thread -ppx ${program}" +flags = "-thread \ + -I ${test_build_directory} \ + -open List \ + -rectypes \ + -principal \ + -alias-deps \ + -unboxed-types \ + -safe-string \ + -ppx ${program}" **** ocamlc.byte module = "test.ml" -flags = "-vmthread -ppx ${program}" +flags = "-vmthread \ + -g \ + -no-alias-deps \ + -no-unboxed-types \ + -unsafe-string \ + -ppx ${program}" ***** check-ocamlc.byte-output *) diff --git a/testsuite/tests/regression/gpr1623/gpr1623.ml b/testsuite/tests/regression/gpr1623/gpr1623.ml index 556fe1c4..80f84452 100644 --- a/testsuite/tests/regression/gpr1623/gpr1623.ml +++ b/testsuite/tests/regression/gpr1623/gpr1623.ml @@ -1,14 +1,14 @@ (* TEST - arguments = "???" + arguments = "???" *) (* On Windows the runtime expand windows wildcards (asterisks and * question marks). * - * This file is a non-regression test for github's PR#1623. + * This file is a non-regression test for github's PR#1623. * - * On Windows 64bits, a segfault was triggered when one argument consists - * only of wildcards. + * On Windows 64bits, a segfault was triggered when one argument consists + * only of wildcards. * * The source code of this test is empty: we just check the arguments * expansion. diff --git a/testsuite/tests/regression/missing_set_of_closures/missing_set_of_closures.ml b/testsuite/tests/regression/missing_set_of_closures/missing_set_of_closures.ml index 70f37e6a..3d3f9916 100644 --- a/testsuite/tests/regression/missing_set_of_closures/missing_set_of_closures.ml +++ b/testsuite/tests/regression/missing_set_of_closures/missing_set_of_closures.ml @@ -1,7 +1,7 @@ (* TEST files = "a.ml b.ml b2.ml" * setup-ocamlopt.byte-build-env -** script +** script script = "mkdir -p dir" *** script script = "cp ${test_source_directory}/dir/c.ml dir/" diff --git a/testsuite/tests/regression/pr3612/custom_finalize.c b/testsuite/tests/regression/pr3612/custom_finalize.c index d09fc6d9..5b9dc3d8 100644 --- a/testsuite/tests/regression/pr3612/custom_finalize.c +++ b/testsuite/tests/regression/pr3612/custom_finalize.c @@ -45,7 +45,8 @@ static struct custom_operations caml_test_ops = { custom_hash_default, caml_test_serialize, caml_test_deserialize, - custom_compare_ext_default + custom_compare_ext_default, + custom_fixed_length_default }; value caml_test_pr3612_alloc(value unit) diff --git a/testsuite/tests/regression/pr7920/ocamltests b/testsuite/tests/regression/pr7920/ocamltests new file mode 100644 index 00000000..2272069c --- /dev/null +++ b/testsuite/tests/regression/pr7920/ocamltests @@ -0,0 +1 @@ +pr7920.ml diff --git a/testsuite/tests/regression/pr7920/pr7920.ml b/testsuite/tests/regression/pr7920/pr7920.ml new file mode 100644 index 00000000..4644b9fa --- /dev/null +++ b/testsuite/tests/regression/pr7920/pr7920.ml @@ -0,0 +1,11 @@ +(* TEST *) + +module Z = struct end + +module type QSig = sig + module Z : sig end +end + +module Q : QSig with module Z = Z = struct + module Z = Z +end diff --git a/testsuite/tests/regression/pr7920/pr7920.reference b/testsuite/tests/regression/pr7920/pr7920.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/runtime-errors/Makefile b/testsuite/tests/runtime-errors/Makefile deleted file mode 100644 index 04ce0695..00000000 --- a/testsuite/tests/runtime-errors/Makefile +++ /dev/null @@ -1,80 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Clerc, SED, INRIA Rocquencourt * -#* * -#* Copyright 2010 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -BASEDIR=../.. - -.PHONY: default -default: - @$(MAKE) compile - @$(MAKE) run - -.PHONY: compile -compile: - @for f in *.ml; do \ - F=`basename $$f .ml`; \ - rm -f $$F.bytecode $$F.native $$F.native.exe; \ - $(OCAMLC) -w a -o $$F.bytecode $$f; \ - if $(BYTECODE_ONLY); then : ; else \ - $(OCAMLOPT) -w a -o $$F.native$(EXE) $$f; \ - fi; \ - done - @$(if $(findstring win32,$(UNIX_OR_WIN32)),:, \ - grep -q HAS_STACK_OVERFLOW_DETECTION $(TOPDIR)/byterun/caml/s.h \ - || rm -f stackoverflow.native$(EXE)) - -# Cygwin doesn't allow the stack limit to be changed - the 4096 is -# intended to be larger than the its default stack size. The logic -# causes the test to be skipped if the stacksize cannot be brought -# below this value (uname -s value exits with an error status in Cygwin) -.PHONY: run -run: - @ul=`ulimit -s`; \ - if ( [ "$$ul" = "unlimited" ] || [ $$ul -gt 4096 ] ) ; then \ - ulimit -s 1024 && ul=1 || ul=0 ; \ - else \ - ul=1; \ - fi; \ - for f in *.bytecode; do \ - printf " ... testing '$$f':"; \ - if [ $$ul -eq 1 ] ; then \ - $(OCAMLRUN) ./$$f >$$f.result 2>&1 || true; \ - DIFF="$(DIFF)" sh $$f.checker \ - && echo " => passed" || echo " => failed"; \ - else \ - echo " => unexpected error"; \ - fi; \ - fn=`basename $$f bytecode`native; \ - if $(BYTECODE_ONLY) || [ ! -f "$${fn}$(EXE)" ] ; then \ - echo " ... testing '$$fn': => skipped" ; \ - else \ - printf " ... testing '$$fn':"; \ - if [ $$ul -eq 1 ] ; then \ - ./$${fn}$(EXE) >$$fn.result 2>&1 || true; \ - DIFF="$(DIFF)" sh $$fn.checker \ - && echo " => passed" || echo " => failed"; \ - else \ - echo " => unexpected error"; \ - fi; \ - fi; \ - done - -.PHONY: promote -promote: defaultpromote - -.PHONY: clean -clean: defaultclean - @rm -f *.bytecode *.native *.native.exe *.result - -include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/runtime-errors/has-stackoverflow-detection.sh b/testsuite/tests/runtime-errors/has-stackoverflow-detection.sh new file mode 100644 index 00000000..a71c9762 --- /dev/null +++ b/testsuite/tests/runtime-errors/has-stackoverflow-detection.sh @@ -0,0 +1,8 @@ +#!/bin/sh +if grep -q "#define HAS_STACK_OVERFLOW_DETECTION" ${ocamlsrcdir}/runtime/caml/s.h; then + test_result=${TEST_PASS}; +else + test_result=${TEST_SKIP}; +fi + +exit ${test_result} diff --git a/testsuite/tests/runtime-errors/ocamltests b/testsuite/tests/runtime-errors/ocamltests new file mode 100644 index 00000000..c4a51b5c --- /dev/null +++ b/testsuite/tests/runtime-errors/ocamltests @@ -0,0 +1,2 @@ +stackoverflow.ml +syserror.ml diff --git a/testsuite/tests/runtime-errors/stackoverflow.bytecode.checker b/testsuite/tests/runtime-errors/stackoverflow.bytecode.checker deleted file mode 100644 index c850ba05..00000000 --- a/testsuite/tests/runtime-errors/stackoverflow.bytecode.checker +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Damien Doligez, projet Gallium, INRIA Rocquencourt * -#* * -#* Copyright 2013 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -$DIFF stackoverflow.bytecode.reference stackoverflow.bytecode.result diff --git a/testsuite/tests/runtime-errors/stackoverflow.ml b/testsuite/tests/runtime-errors/stackoverflow.ml index ad70d0ca..82c1c25a 100644 --- a/testsuite/tests/runtime-errors/stackoverflow.ml +++ b/testsuite/tests/runtime-errors/stackoverflow.ml @@ -1,3 +1,28 @@ +(* TEST + +flags = "-w a" + +* setup-ocamlc.byte-build-env +** ocamlc.byte +*** run +**** check-program-output + +* libwin32unix +** setup-ocamlopt.byte-build-env +*** ocamlopt.byte +**** run +***** check-program-output + +* libunix +** script +script = "sh ${test_source_directory}/has-stackoverflow-detection.sh" +*** setup-ocamlopt.byte-build-env +**** ocamlopt.byte +***** run +****** check-program-output + +*) + let rec f x = if not (x = 0 || x = 10000 || x = 20000) then 1 + f (x + 1) diff --git a/testsuite/tests/runtime-errors/stackoverflow.native.checker b/testsuite/tests/runtime-errors/stackoverflow.native.checker deleted file mode 100644 index f640718a..00000000 --- a/testsuite/tests/runtime-errors/stackoverflow.native.checker +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Damien Doligez, projet Gallium, INRIA Rocquencourt * -#* * -#* Copyright 2013 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -$DIFF stackoverflow.native.reference stackoverflow.native.result diff --git a/testsuite/tests/runtime-errors/stackoverflow.bytecode.reference b/testsuite/tests/runtime-errors/stackoverflow.reference similarity index 100% rename from testsuite/tests/runtime-errors/stackoverflow.bytecode.reference rename to testsuite/tests/runtime-errors/stackoverflow.reference diff --git a/testsuite/tests/runtime-errors/stackoverflow.run b/testsuite/tests/runtime-errors/stackoverflow.run new file mode 100644 index 00000000..acd7368b --- /dev/null +++ b/testsuite/tests/runtime-errors/stackoverflow.run @@ -0,0 +1,16 @@ +#!/bin/sh +ul=`ulimit -s` +if ( [ "$ul" = "unlimited" ] || [ $ul -gt 4096 ] ) ; then + ulimit -s 1024 && ul=true || ul=false ; +else + ul=true; +fi + +if $ul; then + ${program} > ${output} 2>&1; +else + # The test is not actually run + # We thus tell ocamltest the test output is equal to the reference file + # so that the comparison between reference and output will still succeed + echo output="${reference}" > ${ocamltest_response} +fi diff --git a/testsuite/tests/runtime-errors/syserror.bytecode.checker b/testsuite/tests/runtime-errors/syserror.bytecode.checker deleted file mode 100644 index 6433b148..00000000 --- a/testsuite/tests/runtime-errors/syserror.bytecode.checker +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Damien Doligez, projet Gallium, INRIA Rocquencourt * -#* * -#* Copyright 2013 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -grep 'Fatal error: exception Sys_error' syserror.bytecode.result >/dev/null diff --git a/testsuite/tests/runtime-errors/syserror.ml b/testsuite/tests/runtime-errors/syserror.ml index 46f62ead..39818a21 100644 --- a/testsuite/tests/runtime-errors/syserror.ml +++ b/testsuite/tests/runtime-errors/syserror.ml @@ -1 +1,31 @@ +(* TEST + +flags = "-w a" + +* setup-ocamlc.byte-build-env +** ocamlc.byte +*** run +exit_status = "2" +**** libunix +***** check-program-output +reference = "${test_source_directory}/syserror.unix.reference" +**** libwin32unix +***** check-program-output +reference = "${test_source_directory}/syserror.win32.reference" + +* setup-ocamlopt.byte-build-env +** ocamlopt.byte +*** run +exit_status = "2" +**** libunix +***** check-program-output +reference = "${test_source_directory}/syserror.unix.reference" +**** libwin32unix +***** check-program-output +reference = "${test_source_directory}/syserror.win32.reference" + +*) + +let _ = Printexc.record_backtrace false + let channel = open_out "titi:/toto" diff --git a/testsuite/tests/runtime-errors/syserror.native.checker b/testsuite/tests/runtime-errors/syserror.native.checker deleted file mode 100644 index 41448fff..00000000 --- a/testsuite/tests/runtime-errors/syserror.native.checker +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Damien Doligez, projet Gallium, INRIA Rocquencourt * -#* * -#* Copyright 2013 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -grep 'Fatal error: exception Sys_error' syserror.native.result >/dev/null diff --git a/testsuite/tests/runtime-errors/syserror.native.reference b/testsuite/tests/runtime-errors/syserror.native.reference deleted file mode 100644 index 3f6219a2..00000000 --- a/testsuite/tests/runtime-errors/syserror.native.reference +++ /dev/null @@ -1 +0,0 @@ -Fatal error: exception Sys_error("titi:/toto: No such file or directory") diff --git a/testsuite/tests/runtime-errors/syserror.bytecode.reference b/testsuite/tests/runtime-errors/syserror.unix.reference similarity index 100% rename from testsuite/tests/runtime-errors/syserror.bytecode.reference rename to testsuite/tests/runtime-errors/syserror.unix.reference diff --git a/testsuite/tests/runtime-errors/syserror.win32.reference b/testsuite/tests/runtime-errors/syserror.win32.reference new file mode 100644 index 00000000..4030c3ad --- /dev/null +++ b/testsuite/tests/runtime-errors/syserror.win32.reference @@ -0,0 +1 @@ +Fatal error: exception Sys_error("titi:/toto: Invalid argument") diff --git a/testsuite/tests/self-contained-toplevel/main.ml b/testsuite/tests/self-contained-toplevel/main.ml index 7dd7b5cf..5bd6b61f 100644 --- a/testsuite/tests/self-contained-toplevel/main.ml +++ b/testsuite/tests/self-contained-toplevel/main.ml @@ -30,4 +30,10 @@ let () = ; cmi = Marshal.from_string Cached_cmi.foo 0 } | _ -> old_loader unit_name); + Toploop.add_hook (function + | Toploop.After_setup -> + Toploop.toplevel_env := + Env.add_persistent_structure (Ident.create_persistent "Foo") + !Toploop.toplevel_env + | _ -> ()); Topmain.main () diff --git a/testsuite/tests/shadow_include/artificial.ml b/testsuite/tests/shadow_include/artificial.ml new file mode 100644 index 00000000..f881c999 --- /dev/null +++ b/testsuite/tests/shadow_include/artificial.ml @@ -0,0 +1,70 @@ +(* TEST + * expect + flags = "-nostdlib -nopervasives" +*) + +module Foo : sig + type t + + module Bar : sig + type t + end + + val to_ : t -> Bar.t + val from: Bar.t -> t +end = struct + type t + + module Bar = struct + type nonrec t = t + end + + let to_ x = x + let from x = x +end +;; +[%%expect{| +module Foo : + sig + type t + module Bar : sig type t end + val to_ : t -> Bar.t + val from : Bar.t -> t + end +|}] + +module Extended = struct + include Foo + module Bar = struct + include Bar + let int = 42 + end +end +;; +[%%expect{| +module Extended : + sig + type t = Foo.t + val to_ : t -> Foo.Bar.t + val from : Foo.Bar.t -> t + module Bar : sig type t = Foo.Bar.t val int : int end + end +|}] + +module type Extended = sig + include module type of struct include Foo end + module Bar : sig + include module type of struct include Bar end + val int : int + end +end +;; +[%%expect{| +module type Extended = + sig + type t = Foo.t + val to_ : t -> Foo.Bar.t + val from : Foo.Bar.t -> t + module Bar : sig type t = Foo.Bar.t val int : int end + end +|}] diff --git a/testsuite/tests/shadow_include/cannot_shadow_error.compilers.reference b/testsuite/tests/shadow_include/cannot_shadow_error.compilers.reference new file mode 100644 index 00000000..7d1b19e6 --- /dev/null +++ b/testsuite/tests/shadow_include/cannot_shadow_error.compilers.reference @@ -0,0 +1,8 @@ +File "cannot_shadow_error.ml", line 24, characters 2-36: +24 | include Comparable with type t = t + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Illegal shadowing of included type t/9 by t/13 + File "cannot_shadow_error.ml", line 23, characters 2-19: + Type t/9 came from this include + File "cannot_shadow_error.ml", line 14, characters 2-23: + The value print has no valid type if t/9 is shadowed diff --git a/testsuite/tests/shadow_include/cannot_shadow_error.ml b/testsuite/tests/shadow_include/cannot_shadow_error.ml new file mode 100644 index 00000000..11619ca8 --- /dev/null +++ b/testsuite/tests/shadow_include/cannot_shadow_error.ml @@ -0,0 +1,25 @@ +(* TEST +* setup-ocamlc.byte-build-env +flags = "-nostdlib -nopervasives" +** ocamlc.byte +ocamlc_byte_exit_status = "2" +*** check-ocamlc.byte-output +*) + +(* Same example as in tests/typing-sigsubst/sigsubst.ml, but not as an + expect_test so we get the full error. *) + +module type Printable = sig + type t + val print : t -> unit +end + +module type Comparable = sig + type t + val compare : t -> t -> int +end + +module type PrintableComparable = sig + include Printable + include Comparable with type t = t +end diff --git a/testsuite/tests/shadow_include/ocamltests b/testsuite/tests/shadow_include/ocamltests new file mode 100644 index 00000000..d972079f --- /dev/null +++ b/testsuite/tests/shadow_include/ocamltests @@ -0,0 +1,3 @@ +artificial.ml +cannot_shadow_error.ml +shadow_all.ml diff --git a/testsuite/tests/shadow_include/shadow_all.ml b/testsuite/tests/shadow_include/shadow_all.ml new file mode 100644 index 00000000..7e31cad2 --- /dev/null +++ b/testsuite/tests/shadow_include/shadow_all.ml @@ -0,0 +1,477 @@ +(* TEST + * expect + flags = "-nopervasives" (* can't pass -nostdlib because of objects. *) +*) + +(* Signatures *) + +(* Tests that everything can be shadowed. *) + +module type S = sig + type t + + val unit : unit + + external e : unit -> unit = "%identity" + + module M : sig type t end + + module type T + + exception E + + type ext = .. + type ext += C + + class c : object end + + class type ct = object end +end +;; +[%%expect{| +module type S = + sig + type t + val unit : unit + external e : unit -> unit = "%identity" + module M : sig type t end + module type T + exception E + type ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] + +module type SS = sig + include S + include S +end +;; +[%%expect{| +module type SS = + sig + type t + val unit : unit + external e : unit -> unit = "%identity" + module M : sig type t end + module type T + exception E + type ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] + +(* Test that the call to nondep works properly. *) + +module type Type = sig + include S + type u = t + include S +end +;; +[%%expect{| +module type Type = + sig + type u + type t + val unit : unit + external e : unit -> unit = "%identity" + module M : sig type t end + module type T + exception E + type ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] + +module type Type_fail = sig + include S + val ignore : t -> unit + include S +end +;; +[%%expect{| +Line 4, characters 2-11: +4 | include S + ^^^^^^^^^ +Error: Illegal shadowing of included type t/144 by t/161 + Line 2, characters 2-11: + Type t/144 came from this include + Line 3, characters 2-24: + The value ignore has no valid type if t/144 is shadowed +|}] + +module type Module = sig + include S + module N = M + include S +end +;; +[%%expect{| +module type Module = + sig + module N : sig type t end + type t + val unit : unit + external e : unit -> unit = "%identity" + module M : sig type t end + module type T + exception E + type ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] + +module type Module_fail = sig + include S + val ignore : M.t -> unit + include S +end +;; +[%%expect{| +Line 4, characters 2-11: +4 | include S + ^^^^^^^^^ +Error: Illegal shadowing of included module M/232 by M/249 + Line 2, characters 2-11: + Module M/232 came from this include + Line 3, characters 2-26: + The value ignore has no valid type if M/232 is shadowed +|}] + + +module type Module_type = sig + include S + module type U = T + include S +end +;; +[%%expect{| +module type Module_type = + sig + module type U + type t + val unit : unit + external e : unit -> unit = "%identity" + module M : sig type t end + module type T + exception E + type ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] + +module type Module_type_fail = sig + include S + module F : functor (_ : T) -> sig end + include S +end +;; +[%%expect{| +Line 4, characters 2-11: +4 | include S + ^^^^^^^^^ +Error: Illegal shadowing of included module type T/317 by T/335 + Line 2, characters 2-11: + Module type T/317 came from this include + Line 3, characters 2-39: + The module F has no valid type if T/317 is shadowed +|}] + +module type Extension = sig + include S + type ext += C2 + include S +end +;; +[%%expect{| +Line 4, characters 2-11: +4 | include S + ^^^^^^^^^ +Error: Illegal shadowing of included type ext/353 by ext/370 + Line 2, characters 2-11: + Type ext/353 came from this include + Line 3, characters 14-16: + The extension constructor C2 has no valid type if ext/353 is shadowed +|}] + +module type Class = sig + include S + class parametrized : int -> c + include S +end +;; +[%%expect{| +module type Class = + sig + class parametrized : int -> object end + type t + val unit : unit + external e : unit -> unit = "%identity" + module M : sig type t end + module type T + exception E + type ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] + +module type Class_type = sig + include S + class type parametrized = ct + include S +end +;; +[%%expect{| +module type Class_type = + sig + class type parametrized = object end + type t + val unit : unit + external e : unit -> unit = "%identity" + module M : sig type t end + module type T + exception E + type ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] + +(* Structures *) + +(* Tests that everything can be shadowed. *) + +module N = struct + type t + + let unit = () + + external e : unit -> unit = "%identity" + + module M = struct end + + module type T = sig end + + exception E + + type ext = .. + type ext += C + + class c = object end + + class type ct = object end +end +;; +[%%expect{| +module N : + sig + type t + val unit : unit + external e : unit -> unit = "%identity" + module M : sig end + module type T = sig end + exception E + type ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] + +module NN = struct + include N + include N +end +;; +[%%expect{| +module NN : + sig + type t = N.t + val unit : unit + external e : unit -> unit = "%identity" + module M = N.M + module type T = sig end + exception E + type ext = N.ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] + +(* Test that the call to nondep works properly *) + +module Type = struct + include N + type u = t + include N +end +;; +[%%expect{| +module Type : + sig + type u = N.t + type t = N.t + val unit : unit + external e : unit -> unit = "%identity" + module M = N.M + module type T = sig end + exception E + type ext = N.ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] + +module Module = struct + include N + module O = M + include N +end +;; +[%%expect{| +module Module : + sig + module O = N.M + type t = N.t + val unit : unit + external e : unit -> unit = "%identity" + module M = N.M + module type T = sig end + exception E + type ext = N.ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] + +module Module_type = struct + include N + module type U = T + include N +end +;; +[%%expect{| +module Module_type : + sig + module type U = sig end + type t = N.t + val unit : unit + external e : unit -> unit = "%identity" + module M = N.M + module type T = sig end + exception E + type ext = N.ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] + +module Exception = struct + include N + exception Exn = E + include N +end +;; +[%%expect{| +module Exception : + sig + exception Exn + type t = N.t + val unit : unit + external e : unit -> unit = "%identity" + module M = N.M + module type T = sig end + exception E + type ext = N.ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] + +module Extension = struct + include N + type ext += C2 + include N +end +;; +[%%expect{| +module Extension : + sig + type N.ext += C2 + type t = N.t + val unit : unit + external e : unit -> unit = "%identity" + module M = N.M + module type T = sig end + exception E + type ext = N.ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] + +module Class = struct + include N + class parametrized _ = c + include N +end +;; +[%%expect{| +module Class : + sig + class parametrized : 'a -> object end + type t = N.t + val unit : unit + external e : unit -> unit = "%identity" + module M = N.M + module type T = sig end + exception E + type ext = N.ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] + +module Class_type = struct + include N + class type parametrized = ct + include N +end +;; +[%%expect{| +module Class_type : + sig + class type parametrized = object end + type t = N.t + val unit : unit + external e : unit -> unit = "%identity" + module M = N.M + module type T = sig end + exception E + type ext = N.ext = .. + type ext += C + class c : object end + class type ct = object end + end +|}] diff --git a/testsuite/tests/tool-caml-tex/ellipses.ml b/testsuite/tests/tool-caml-tex/ellipses.ml new file mode 100644 index 00000000..474873a0 --- /dev/null +++ b/testsuite/tests/tool-caml-tex/ellipses.ml @@ -0,0 +1,60 @@ +(* TEST + reference="${test_source_directory}/ellipses.reference" + output="ellipses.output" + script = "${ocamlrun} ${ocamlsrcdir}/tools/caml-tex \ + -repo-root ${ocamlsrcdir} ${test_source_directory}/${test_file} -o ${output}" + * hasstr + ** native-compiler + *** shared-libraries + **** script with unix,str + ***** check-program-output +*) + +\begin{caml_example*}{verbatim} +let start = 0 +[@@@ellipsis.start] +let hidden = succ start +[@@@ellipsis.stop] +let mid = succ hidden +let[@ellipsis] statement = succ mid + +module E = struct end +include E[@@ellipsis] + +let expr = succ statement[@ellipsis] + +let pat = match start with + | 0[@ellipsis] | 1 -> succ expr + | _ -> succ expr + +let case = match start with + | 0 -> succ pat + | _[@ellipsis.start] -> succ pat[@ellipsis.stop] + + +let annot: int[@ellipsis] = succ case + +let subexpr = succ annot + (2[@ellipsis.stop] - 1[@ellipsis.start] * 2) - 2 + +class[@ellipsis] c = object val x = succ subexpr end + +class c2 = object + val[@ellipsis] x = 0 + val y = 1 + method[@ellipsis] m = 2 + method n = 3 + [@@@ellipsis.start] + method l = 4 + [@@@ellipsis.stop] +end + +type t = A[@ellipsis] | B |C[@ellipsis.start] | D | E [@ellipsis.stop] | F +type arrow = int -> (int -> int[@ellipsis]) +type record = { a:int; b:int[@ellipsis]; c:int; + d:int[@ellipsis.start]; e:int; f:int[@ellipsis.stop]; + g:int } +type polyvar = [`A|`B[@ellipsis] |`C + |`D[@ellipsis.start] | `E | `F [@ellipsis.stop] + | `G ] +type exn += A[@ellipsis] | B |C[@ellipsis.start] | D | E [@ellipsis.stop] | F +\end{caml_example*} diff --git a/testsuite/tests/tool-caml-tex/ellipses.reference b/testsuite/tests/tool-caml-tex/ellipses.reference new file mode 100644 index 00000000..b4c4ccb0 --- /dev/null +++ b/testsuite/tests/tool-caml-tex/ellipses.reference @@ -0,0 +1,58 @@ +(* TEST + reference="${test_source_directory}/ellipses.reference" + output="ellipses.output" + script = "${ocamlrun} ${ocamlsrcdir}/tools/caml-tex \ + -repo-root ${ocamlsrcdir} ${test_source_directory}/${test_file} -o ${output}" + * hasstr + ** native-compiler + *** shared-libraries + **** script with unix,str + ***** check-program-output +*) + +\camlexample{verbatim} +\caml\camlinput\?let start = 0 +\?\ldots +\?let mid = succ hidden +\?\ldots + +\?module E = struct end +\?\ldots + +\?let expr = \ldots + +\?let pat = match start with +\? | \ldots | 1 -> succ expr +\? | _ -> succ expr + +\?let case = match start with +\? | 0 -> succ pat +\? | \ldots + + +\?let annot: \ldots = succ case + +\?let subexpr = succ annot + (\ldots * 2) - 2 + +\?\ldots + +\?class c2 = object +\? \ldots +\? val y = 1 +\? \ldots +\? method n = 3 +\? \ldots +\?end + +\?type t = \ldots | B \ldots | F +\?type arrow = int -> (\ldots) +\?type record = { a:int; \ldots c:int; +\? \ldots +\? g:int } +\?type polyvar = [\textasciigrave\-A|\ldots |\textasciigrave\-C +\? |\ldots +\? | \textasciigrave\-G ] +\?type exn += \ldots | B \ldots | F +\endcamlinput +\endcaml +\endcamlexample diff --git a/testsuite/tests/tool-caml-tex/ocamltests b/testsuite/tests/tool-caml-tex/ocamltests new file mode 100644 index 00000000..e543110f --- /dev/null +++ b/testsuite/tests/tool-caml-tex/ocamltests @@ -0,0 +1,2 @@ +ellipses.ml +redirections.ml diff --git a/testsuite/tests/tool-caml-tex/redirections.ml b/testsuite/tests/tool-caml-tex/redirections.ml new file mode 100644 index 00000000..1e2fe992 --- /dev/null +++ b/testsuite/tests/tool-caml-tex/redirections.ml @@ -0,0 +1,27 @@ +(* TEST + reference="${test_source_directory}/redirections.reference" + output="redirections.output" + script = "${ocamlrun} ${ocamlsrcdir}/tools/caml-tex \ + -repo-root ${ocamlsrcdir} ${test_source_directory}/${test_file} -o ${output}" + * hasstr + ** native-compiler + *** shared-libraries + **** script with unix,str + ***** check-program-output + *** no-shared-libraries + **** script with unix,str + script = "${ocamlsrcdir}/tools/caml-tex \ + -repo-root ${ocamlsrcdir} ${test_source_directory}/${test_file} -o ${output}" + ***** check-program-output +*) + +\begin{caml_example}{toplevel} +[@@@warning "+A"];; +1 + 2. [@@expect error];; +let f x = () [@@expect warning 27];; +\end{caml_example} + +\begin{caml_example}{toplevel} +Format.printf "Hello@."; +print_endline "world";; +\end{caml_example} diff --git a/testsuite/tests/tool-caml-tex/redirections.reference b/testsuite/tests/tool-caml-tex/redirections.reference new file mode 100644 index 00000000..242209c7 --- /dev/null +++ b/testsuite/tests/tool-caml-tex/redirections.reference @@ -0,0 +1,38 @@ +(* TEST + reference="${test_source_directory}/redirections.reference" + output="redirections.output" + script = "${ocamlrun} ${ocamlsrcdir}/tools/caml-tex \ + -repo-root ${ocamlsrcdir} ${test_source_directory}/${test_file} -o ${output}" + * hasstr + ** native-compiler + *** shared-libraries + **** script with unix,str + ***** check-program-output + *** no-shared-libraries + **** script with unix,str + script = "${ocamlsrcdir}/tools/caml-tex \ + -repo-root ${ocamlsrcdir} ${test_source_directory}/${test_file} -o ${output}" + ***** check-program-output +*) + +\camlexample{toplevel} +\caml\camlinput\?[@@@warning "+A"];; +\endcamlinput\endcaml +\caml\camlinput\?1 + \<2.\> ;; +\endcamlinput\camlerror\:Error: This expression has type float but an expression was expected of type +\: int +\endcamlerror\endcaml +\caml\camlinput\?let f \ = () ;; +\endcamlinput\camlwarn\:Warning 27: unused variable x. +\:val f : \textquotesingle\-a -> unit = +\endcamlwarn\endcaml +\endcamlexample + +\camlexample{toplevel} +\caml\camlinput\?Format.printf "Hello@."; +\?print_endline "world";; +\endcamlinput\camloutput\:Hello +\:world +\:- : unit = () +\endcamloutput\endcaml +\endcamlexample diff --git a/testsuite/tests/tool-command-line/test.compilers.reference b/testsuite/tests/tool-command-line/test.compilers.reference new file mode 100644 index 00000000..9182c8a7 --- /dev/null +++ b/testsuite/tests/tool-command-line/test.compilers.reference @@ -0,0 +1 @@ +don't know what to do with unknown-file diff --git a/testsuite/tests/tool-command-line/test.ml b/testsuite/tests/tool-command-line/test.ml index e7b7893e..61dc8b0e 100644 --- a/testsuite/tests/tool-command-line/test.ml +++ b/testsuite/tests/tool-command-line/test.ml @@ -2,25 +2,30 @@ files = "unknown-file" -* skip (* setup-ocamlc.byte-build-env *) +* setup-ocamlc.byte-build-env +compiler_output = "compiler-output.raw" ** ocamlc.byte all_modules = "" flags = "unknown-file" ocamlc_byte_exit_status = "2" -*** check-ocamlc.byte-output +*** script +script = "grep 'know what to do with unknown-file' compiler-output.raw" +output = "compiler-output" +**** check-ocamlc.byte-output +compiler_output = "compiler-output" -* skip (* setup-ocamlopt.byte-build-env *) +* setup-ocamlopt.byte-build-env +compiler_output = "compiler-output.raw" ** ocamlopt.byte all_modules = "" flags = "unknown-file" ocamlopt_byte_exit_status = "2" -*** no-flambda +*** script +script = "grep 'know what to do with unknown-file' compiler-output.raw" +output = "compiler-output" **** check-ocamlopt.byte-output -*** flambda -**** check-ocamlopt.byte-output -compiler_reference = "${test_source_directory}/test.ocamlopt.byte.flambda.reference" +compiler_output = "compiler-output" *) (* this file is just a test driver, the test does not contain real OCamlcode *) - diff --git a/testsuite/tests/tool-command-line/test.ocamlc.byte.reference b/testsuite/tests/tool-command-line/test.ocamlc.byte.reference deleted file mode 100644 index 2bcd4b39..00000000 --- a/testsuite/tests/tool-command-line/test.ocamlc.byte.reference +++ /dev/null @@ -1,130 +0,0 @@ -don't know what to do with unknown-file -Usage: ocamlc -Options are: - -a Build a library - -absname Show absolute filenames in error messages - -annot Save information in .annot - -bin-annot Save typedtree in .cmt - -c Compile only (do not link) - -cc Use as the C compiler and linker - -cclib Pass option to the C linker - -ccopt Pass option to the C compiler and linker - -color {auto|always|never} Enable or disable colors in compiler messages - The following settings are supported: - auto use heuristics to enable colors only if supported - always enable colors - never disable colors - The default setting is 'auto', and the current heuristic - checks that the TERM environment variable exists and is - not empty or "dumb", and that isatty(stderr) holds. - -compat-32 Check that generated bytecode can run on 32-bit platforms - -config Print configuration values and exit - -custom Link in custom mode - -dllib Use the dynamically-loaded library - -dllpath Add to the run-time search path for shared libraries - -dtypes (deprecated) same as -annot - -for-pack Generate code that can later be `packed' with - ocamlc -pack -o .cmo - -g Save debugging information - -i Print inferred interface - -I Add to the list of include directories - -impl Compile as a .ml file - -intf Compile as a .mli file - -intf-suffix Suffix for interface files (default: .mli) - -intf_suffix (deprecated) same as -intf-suffix - -keep-docs Keep documentation strings in .cmi files - -no-keep-docs Do not keep documentation strings in .cmi files (default) - -keep-locs Keep locations in .cmi files (default) - -no-keep-locs Do not keep locations in .cmi files - -labels Use commuting label mode - -linkall Link all modules, even unused ones - -make-runtime Build a runtime system with given C objects and libraries - -make_runtime (deprecated) same as -make-runtime - -modern (deprecated) same as -labels - -alias-deps Do record dependencies for module aliases - -no-alias-deps Do not record dependencies for module aliases - -app-funct Activate applicative functors - -no-app-funct Deactivate applicative functors - -no-check-prims Do not check runtime for primitives - -noassert Do not compile assertion checks - -noautolink Do not automatically link C libraries specified in .cma files - -nolabels Ignore non-optional labels in types - -nostdlib Do not add default directory to the list of include directories - -o Set output file name to - -opaque Does not generate cross-module optimization information - (reduces necessary recompilation on module change) - -open Opens the module before typing - -output-obj Output an object file instead of an executable - -output-complete-obj Output an object file, including runtime, instead of an executable - -pack Package the given .cmo files into one .cmo - -pp Pipe sources through preprocessor - -ppx Pipe abstract syntax trees through preprocessor - -plugin Load dynamic plugin - -principal Check principality of type inference - -no-principal Do not check principality of type inference (default) - -rectypes Allow arbitrary recursive types - -no-rectypes Do not allow arbitrary recursive types (default) - -runtime-variant Use the variant of the run-time system - -safe-string Make strings immutable (default) - -short-paths Shorten paths in types - -strict-sequence Left-hand part of a sequence must have type unit - -no-strict-sequence Left-hand part of a sequence need not have type unit (default) - -strict-formats Reject invalid formats accepted by legacy implementations - (Warning: Invalid formats may behave differently from - previous OCaml versions, and will become always-rejected - in future OCaml versions. You should always use this flag - to detect invalid formats so you can fix them.) - -no-strict-formats Accept invalid formats accepted by legacy implementations (default) - (Warning: Invalid formats may behave differently from - previous OCaml versions, and will become always-rejected - in future OCaml versions. You should never use this flag - and instead fix invalid formats.) - -thread (deprecated) same as -I +threads - -unboxed-types unannotated unboxable types will be unboxed - -no-unboxed-types unannotated unboxable types will not be unboxed (default) - -unsafe Do not compile bounds checking on array and string access - -unsafe-string Make strings mutable - -use-runtime Generate bytecode for the given runtime system - -use_runtime (deprecated) same as -use-runtime - -v Print compiler version and location of standard library and exit - -verbose Print calls to external commands - -version Print version and exit - --version Print version and exit - -vmthread Generate code that supports the threads library with VM-level - scheduling - -vnum Print version number and exit - -w Enable or disable warnings according to : - + enable warnings in - - disable warnings in - @ enable warnings in and treat them as errors - can be: - a single warning number - .. a range of consecutive warning numbers - a predefined set - default setting is "+a-4-6-7-9-27-29-32..42-44-45-48-50-60" - -warn-error Enable or disable error status for warnings according - to . See option -w for the syntax of . - Default setting is "-a+31" - -warn-help Show description of warning numbers - -where Print location of standard library and exit - - Treat as a file name (even if it starts with `-') - -nopervasives (undocumented) - -use-prims (undocumented) - -dno-unique-ids (undocumented) - -dunique-ids (undocumented) - -dsource (undocumented) - -dparsetree (undocumented) - -dtypedtree (undocumented) - -drawlambda (undocumented) - -dlambda (undocumented) - -dinstr (undocumented) - -dtimings Print timings information for each pass - -dprofile Print performance information for each pass - The columns are: time alloc top-heap absolute-top-heap. - -args Read additional newline-terminated command line arguments - from - -args0 Read additional null character terminated command line arguments -from - -depend Compute dependencies (use 'ocamlc -depend -help' for details) - -help Display this list of options - --help Display this list of options diff --git a/testsuite/tests/tool-command-line/test.ocamlopt.byte.flambda.reference b/testsuite/tests/tool-command-line/test.ocamlopt.byte.flambda.reference deleted file mode 100644 index b2b25085..00000000 --- a/testsuite/tests/tool-command-line/test.ocamlopt.byte.flambda.reference +++ /dev/null @@ -1,178 +0,0 @@ -don't know what to do with unknown-file -Usage: ocamlopt -Options are: - -fPIC Generate position-independent machine code (default) - -fno-PIC Generate position-dependent machine code - -a Build a library - -absname Show absolute filenames in error messages - -afl-instrument Enable instrumentation for afl-fuzz - -afl-inst-ratio Configure percentage of branches instrumented - (advanced, see afl-fuzz docs for AFL_INST_RATIO) - -annot Save information in .annot - -bin-annot Save typedtree in .cmt - -inline-branch-factor |=[,...] Estimate the probability of a branch being cold as 1/(1+n) (used for inlining) (default 0.10) - -c Compile only (do not link) - -cc Use as the C compiler and linker - -cclib Pass option to the C linker - -ccopt Pass option to the C compiler and linker - -clambda-checks Instrument clambda code with closure and field access checks (for debugging the compiler) - -Oclassic Make inlining decisions at function definition time rather than at the call site (replicates previous behaviour of the compiler) - -color {auto|always|never} Enable or disable colors in compiler messages - The following settings are supported: - auto use heuristics to enable colors only if supported - always enable colors - never disable colors - The default setting is 'auto', and the current heuristic - checks that the TERM environment variable exists and is - not empty or "dumb", and that isatty(stderr) holds. - -compact Optimize code size rather than speed - -config Print configuration values and exit - -dtypes (deprecated) same as -annot - -for-pack Generate code that can later be `packed' with - ocamlopt -pack -o .cmx - -g Record debugging information for exception backtrace - -i Print inferred interface - -I Add to the list of include directories - -impl Compile as a .ml file - -inline |=[,...] Aggressiveness of inlining (default 10.00, higher numbers mean more aggressive) - -inline-toplevel |=[,...] Aggressiveness of inlining at toplevel (higher numbers mean more aggressive) - -inline-alloc-cost |=[,...] The cost of not removing an allocation during inlining (default 7, higher numbers more costly) - -inline-branch-cost |=[,...] The cost of not removing a conditional during inlining (default 5, higher numbers more costly) - -inline-call-cost |=[,...] The cost of not removing a call during inlining (default 5, higher numbers more costly) - -inline-prim-cost |=[,...] The cost of not removing a primitive during inlining (default 3, higher numbers more costly) - -inline-indirect-cost |=[,...] The cost of not removing an indirect call during inlining (default 4, higher numbers more costly) - -inline-lifting-benefit |=[,...] The benefit of lifting definitions to toplevel during inlining (default 1300, higher numbers more beneficial) - -inlining-report Emit `..inlining' file(s) (one per round) showing the inliner's decisions - -intf Compile as a .mli file - -intf-suffix Suffix for interface files (default: .mli) - -keep-docs Keep documentation strings in .cmi files - -no-keep-docs Do not keep documentation strings in .cmi files (default) - -keep-locs Keep locations in .cmi files (default) - -no-keep-locs Do not keep locations in .cmi files - -labels Use commuting label mode - -linkall Link all modules, even unused ones - -inline-max-depth |=[,...] Maximum depth of search for inlining opportunities inside inlined functions (default 1) - -alias-deps Do record dependencies for module aliases - -no-alias-deps Do not record dependencies for module aliases - -linscan Use the linear scan register allocator - -app-funct Activate applicative functors - -no-app-funct Deactivate applicative functors - -no-float-const-prop Deactivate constant propagation for floating-point operations - -noassert Do not compile assertion checks - -noautolink Do not automatically link C libraries specified in .cmxa files - -nodynlink Enable optimizations for code that will not be dynlinked - -nolabels Ignore non-optional labels in types - -nostdlib Do not add default directory to the list of include directories - -no-unbox-free-vars-of-closures Do not unbox variables that will appear inside function closures - -no-unbox-specialised-args Do not unbox arguments to which functions have been specialised - -o Set output file name to - -O2 Apply increased optimization for speed - -O3 Apply aggressive optimization for speed (may significantly increase code size and compilation time) - -opaque Does not generate cross-module optimization information - (reduces necessary recompilation on module change) - -open Opens the module before typing - -output-obj Output an object file instead of an executable - -output-complete-obj Output an object file, including runtime, instead of an executable - -p Compile and link with profiling support for "gprof" - (not supported on all platforms) - -pack Package the given .cmx files into one .cmx - -plugin Load dynamic plugin - -pp Pipe sources through preprocessor - -ppx Pipe abstract syntax trees through preprocessor - -principal Check principality of type inference - -no-principal Do not check principality of type inference (default) - -rectypes Allow arbitrary recursive types - -no-rectypes Do not allow arbitrary recursive types (default) - -remove-unused-arguments Remove unused function arguments - -rounds Repeat tree optimization and inlining phases this many times (default 1). Rounds are numbered starting from zero. - -runtime-variant Use the variant of the run-time system - -S Keep intermediate assembly file - -safe-string Make strings immutable (default) - -shared Produce a dynlinkable plugin - -short-paths Shorten paths in types - -strict-sequence Left-hand part of a sequence must have type unit - -no-strict-sequence Left-hand part of a sequence need not have type unit (default) - -strict-formats Reject invalid formats accepted by legacy implementations - (Warning: Invalid formats may behave differently from - previous OCaml versions, and will become always-rejected - in future OCaml versions. You should always use this flag - to detect invalid formats so you can fix them.) - -no-strict-formats Accept invalid formats accepted by legacy implementations (default) - (Warning: Invalid formats may behave differently from - previous OCaml versions, and will become always-rejected - in future OCaml versions. You should never use this flag - and instead fix invalid formats.) - -thread (deprecated) same as -I +threads - -unbox-closures Pass free variables via specialised arguments rather than closures - -unbox-closures-factor 0> Scale the size threshold above which unbox-closures will slow down indirect calls rather than duplicating a function (default 10) - -inline-max-unroll |=[,...] Unroll recursive functions at most this many times (default 0) - -unboxed-types unannotated unboxable types will be unboxed - -no-unboxed-types unannotated unboxable types will not be unboxed (default) - -unsafe Do not compile bounds checking on array and string access - -unsafe-string Make strings mutable - -v Print compiler version and location of standard library and exit - -verbose Print calls to external commands - -version Print version and exit - --version Print version and exit - -vnum Print version number and exit - -w Enable or disable warnings according to : - + enable warnings in - - disable warnings in - @ enable warnings in and treat them as errors - can be: - a single warning number - .. a range of consecutive warning numbers - a predefined set - default setting is "+a-4-6-7-9-27-29-32..42-44-45-48-50-60" - -warn-error Enable or disable error status for warnings according - to . See option -w for the syntax of . - Default setting is "-a+31" - -warn-help Show description of warning numbers - -where Print location of standard library and exit - - Treat as a file name (even if it starts with `-') - -nopervasives (undocumented) - -dno-unique-ids (undocumented) - -dunique-ids (undocumented) - -dsource (undocumented) - -dparsetree (undocumented) - -dtypedtree (undocumented) - -drawlambda (undocumented) - -dlambda (undocumented) - -drawclambda (undocumented) - -dclambda (undocumented) - -dflambda Print Flambda terms - -drawflambda Print Flambda terms after closure conversion - -dflambda-invariants Check Flambda invariants around each pass - -dflambda-no-invariants Do not Check Flambda invariants around each pass - -dflambda-let Print when the given Flambda [Let] is created - -dflambda-verbose Print Flambda terms including around each pass - -dcmm (undocumented) - -dsel (undocumented) - -dcombine (undocumented) - -dcse (undocumented) - -dlive (undocumented) - -davail Print register availability info when printing liveness - -drunavail Run register availability pass (for testing only; needs -g) - -dspill (undocumented) - -dsplit (undocumented) - -dinterf (undocumented) - -dprefer (undocumented) - -dalloc (undocumented) - -dreload (undocumented) - -dscheduling (undocumented) - -dlinear (undocumented) - -dinterval (undocumented) - -dstartup (undocumented) - -dtimings Print timings information for each pass - -dprofile Print performance information for each pass - The columns are: time alloc top-heap absolute-top-heap. - -dump-pass Record transformations performed by these passes: - unbox-closures unbox-specialised-args unbox-free-vars-of-closures - remove-free-vars-equal-to-args remove-unused-arguments unused-arguments - -args Read additional newline-terminated command line arguments - from - -args0 Read additional null character terminated command line arguments -from - -depend Compute dependencies (use 'ocamlopt -depend -help' for details) - -help Display this list of options - --help Display this list of options diff --git a/testsuite/tests/tool-command-line/test.ocamlopt.byte.reference b/testsuite/tests/tool-command-line/test.ocamlopt.byte.reference deleted file mode 100644 index 829f44c3..00000000 --- a/testsuite/tests/tool-command-line/test.ocamlopt.byte.reference +++ /dev/null @@ -1,178 +0,0 @@ -don't know what to do with unknown-file -Usage: ocamlopt -Options are: - -fPIC Generate position-independent machine code (default) - -fno-PIC Generate position-dependent machine code - -a Build a library - -absname Show absolute filenames in error messages - -afl-instrument Enable instrumentation for afl-fuzz - -afl-inst-ratio Configure percentage of branches instrumented - (advanced, see afl-fuzz docs for AFL_INST_RATIO) - -annot Save information in .annot - -bin-annot Save typedtree in .cmt - -inline-branch-factor |=[,...] Estimate the probability of a branch being cold as 1/(1+n) (used for inlining) (default 0.10) - -c Compile only (do not link) - -cc Use as the C compiler and linker - -cclib Pass option to the C linker - -ccopt Pass option to the C compiler and linker - -clambda-checks Instrument clambda code with closure and field access checks (for debugging the compiler) - -Oclassic Make inlining decisions at function definition time rather than at the call site (replicates previous behaviour of the compiler) - -color {auto|always|never} Enable or disable colors in compiler messages - The following settings are supported: - auto use heuristics to enable colors only if supported - always enable colors - never disable colors - The default setting is 'auto', and the current heuristic - checks that the TERM environment variable exists and is - not empty or "dumb", and that isatty(stderr) holds. - -compact Optimize code size rather than speed - -config Print configuration values and exit - -dtypes (deprecated) same as -annot - -for-pack Generate code that can later be `packed' with - ocamlopt -pack -o .cmx - -g Record debugging information for exception backtrace - -i Print inferred interface - -I Add to the list of include directories - -impl Compile as a .ml file - -inline |=[,...] Aggressiveness of inlining (default 1.25, higher numbers mean more aggressive) - -inline-toplevel |=[,...] Aggressiveness of inlining at toplevel (higher numbers mean more aggressive) - -inline-alloc-cost |=[,...] The cost of not removing an allocation during inlining (default 7, higher numbers more costly) - -inline-branch-cost |=[,...] The cost of not removing a conditional during inlining (default 5, higher numbers more costly) - -inline-call-cost |=[,...] The cost of not removing a call during inlining (default 5, higher numbers more costly) - -inline-prim-cost |=[,...] The cost of not removing a primitive during inlining (default 3, higher numbers more costly) - -inline-indirect-cost |=[,...] The cost of not removing an indirect call during inlining (default 4, higher numbers more costly) - -inline-lifting-benefit |=[,...] The benefit of lifting definitions to toplevel during inlining (default 1300, higher numbers more beneficial) - -inlining-report Emit `..inlining' file(s) (one per round) showing the inliner's decisions - -intf Compile as a .mli file - -intf-suffix Suffix for interface files (default: .mli) - -keep-docs Keep documentation strings in .cmi files - -no-keep-docs Do not keep documentation strings in .cmi files (default) - -keep-locs Keep locations in .cmi files (default) - -no-keep-locs Do not keep locations in .cmi files - -labels Use commuting label mode - -linkall Link all modules, even unused ones - -inline-max-depth |=[,...] Maximum depth of search for inlining opportunities inside inlined functions (default 1) - -alias-deps Do record dependencies for module aliases - -no-alias-deps Do not record dependencies for module aliases - -linscan Use the linear scan register allocator - -app-funct Activate applicative functors - -no-app-funct Deactivate applicative functors - -no-float-const-prop Deactivate constant propagation for floating-point operations - -noassert Do not compile assertion checks - -noautolink Do not automatically link C libraries specified in .cmxa files - -nodynlink Enable optimizations for code that will not be dynlinked - -nolabels Ignore non-optional labels in types - -nostdlib Do not add default directory to the list of include directories - -no-unbox-free-vars-of-closures Do not unbox variables that will appear inside function closures - -no-unbox-specialised-args Do not unbox arguments to which functions have been specialised - -o Set output file name to - -O2 Apply increased optimization for speed - -O3 Apply aggressive optimization for speed (may significantly increase code size and compilation time) - -opaque Does not generate cross-module optimization information - (reduces necessary recompilation on module change) - -open Opens the module before typing - -output-obj Output an object file instead of an executable - -output-complete-obj Output an object file, including runtime, instead of an executable - -p Compile and link with profiling support for "gprof" - (not supported on all platforms) - -pack Package the given .cmx files into one .cmx - -plugin Load dynamic plugin - -pp Pipe sources through preprocessor - -ppx Pipe abstract syntax trees through preprocessor - -principal Check principality of type inference - -no-principal Do not check principality of type inference (default) - -rectypes Allow arbitrary recursive types - -no-rectypes Do not allow arbitrary recursive types (default) - -remove-unused-arguments Remove unused function arguments - -rounds Repeat tree optimization and inlining phases this many times (default 1). Rounds are numbered starting from zero. - -runtime-variant Use the variant of the run-time system - -S Keep intermediate assembly file - -safe-string Make strings immutable (default) - -shared Produce a dynlinkable plugin - -short-paths Shorten paths in types - -strict-sequence Left-hand part of a sequence must have type unit - -no-strict-sequence Left-hand part of a sequence need not have type unit (default) - -strict-formats Reject invalid formats accepted by legacy implementations - (Warning: Invalid formats may behave differently from - previous OCaml versions, and will become always-rejected - in future OCaml versions. You should always use this flag - to detect invalid formats so you can fix them.) - -no-strict-formats Accept invalid formats accepted by legacy implementations (default) - (Warning: Invalid formats may behave differently from - previous OCaml versions, and will become always-rejected - in future OCaml versions. You should never use this flag - and instead fix invalid formats.) - -thread (deprecated) same as -I +threads - -unbox-closures Pass free variables via specialised arguments rather than closures - -unbox-closures-factor 0> Scale the size threshold above which unbox-closures will slow down indirect calls rather than duplicating a function (default 10) - -inline-max-unroll |=[,...] Unroll recursive functions at most this many times (default 0) - -unboxed-types unannotated unboxable types will be unboxed - -no-unboxed-types unannotated unboxable types will not be unboxed (default) - -unsafe Do not compile bounds checking on array and string access - -unsafe-string Make strings mutable - -v Print compiler version and location of standard library and exit - -verbose Print calls to external commands - -version Print version and exit - --version Print version and exit - -vnum Print version number and exit - -w Enable or disable warnings according to : - + enable warnings in - - disable warnings in - @ enable warnings in and treat them as errors - can be: - a single warning number - .. a range of consecutive warning numbers - a predefined set - default setting is "+a-4-6-7-9-27-29-32..42-44-45-48-50-60" - -warn-error Enable or disable error status for warnings according - to . See option -w for the syntax of . - Default setting is "-a+31" - -warn-help Show description of warning numbers - -where Print location of standard library and exit - - Treat as a file name (even if it starts with `-') - -nopervasives (undocumented) - -dno-unique-ids (undocumented) - -dunique-ids (undocumented) - -dsource (undocumented) - -dparsetree (undocumented) - -dtypedtree (undocumented) - -drawlambda (undocumented) - -dlambda (undocumented) - -drawclambda (undocumented) - -dclambda (undocumented) - -dflambda Print Flambda terms - -drawflambda Print Flambda terms after closure conversion - -dflambda-invariants Check Flambda invariants around each pass - -dflambda-no-invariants Do not Check Flambda invariants around each pass - -dflambda-let Print when the given Flambda [Let] is created - -dflambda-verbose Print Flambda terms including around each pass - -dcmm (undocumented) - -dsel (undocumented) - -dcombine (undocumented) - -dcse (undocumented) - -dlive (undocumented) - -davail Print register availability info when printing liveness - -drunavail Run register availability pass (for testing only; needs -g) - -dspill (undocumented) - -dsplit (undocumented) - -dinterf (undocumented) - -dprefer (undocumented) - -dalloc (undocumented) - -dreload (undocumented) - -dscheduling (undocumented) - -dlinear (undocumented) - -dinterval (undocumented) - -dstartup (undocumented) - -dtimings Print timings information for each pass - -dprofile Print performance information for each pass - The columns are: time alloc top-heap absolute-top-heap. - -dump-pass Record transformations performed by these passes: - unbox-closures unbox-specialised-args unbox-free-vars-of-closures - remove-free-vars-equal-to-args remove-unused-arguments unused-arguments - -args Read additional newline-terminated command line arguments - from - -args0 Read additional null character terminated command line arguments -from - -depend Compute dependencies (use 'ocamlopt -depend -help' for details) - -help Display this list of options - --help Display this list of options diff --git a/testsuite/tests/tool-debugger/basic/debuggee.ml b/testsuite/tests/tool-debugger/basic/debuggee.ml index 6bdac7e7..91ad3c21 100644 --- a/testsuite/tests/tool-debugger/basic/debuggee.ml +++ b/testsuite/tests/tool-debugger/basic/debuggee.ml @@ -2,12 +2,13 @@ set foo = "bar" flags += " -g " ocamldebug_script = "${test_source_directory}/input_script" -* shared-libraries -** setup-ocamlc.byte-build-env -*** ocamlc.byte -**** check-ocamlc.byte-output -***** ocamldebug -****** check-program-output +* debugger +** shared-libraries +*** setup-ocamlc.byte-build-env +**** ocamlc.byte +***** check-ocamlc.byte-output +****** ocamldebug +******* check-program-output *) print_endline Sys.argv.(1);; diff --git a/testsuite/tests/tool-debugger/find-artifacts/debuggee.ml b/testsuite/tests/tool-debugger/find-artifacts/debuggee.ml index c06350ed..70aee3ff 100644 --- a/testsuite/tests/tool-debugger/find-artifacts/debuggee.ml +++ b/testsuite/tests/tool-debugger/find-artifacts/debuggee.ml @@ -1,24 +1,25 @@ (* TEST ocamldebug_script = "${test_source_directory}/input_script" -* shared-libraries -** setup-ocamlc.byte-build-env -*** script +* debugger +** shared-libraries +*** setup-ocamlc.byte-build-env +**** script script = "mkdir out" -**** ocamlc.byte +***** ocamlc.byte flags = "-g -c" all_modules = "${test_source_directory}/in/blah.ml" program = "out/blah.cmo" -***** ocamlc.byte +****** ocamlc.byte program = "out/foo.cmo" flags = "-I out -g -c" all_modules = "${test_source_directory}/in/foo.ml" -****** ocamlc.byte +******* ocamlc.byte all_modules = "out/blah.cmo out/foo.cmo" flags = " -g " program = "debuggee.exe" -******* check-ocamlc.byte-output -******** ocamldebug -********* check-program-output +******** check-ocamlc.byte-output +********* ocamldebug +********** check-program-output *) (* This file only contains the specification of how to run the test *) diff --git a/testsuite/tests/tool-debugger/no_debug_event/noev.ml b/testsuite/tests/tool-debugger/no_debug_event/noev.ml index 92f5b09f..2cf9866b 100644 --- a/testsuite/tests/tool-debugger/no_debug_event/noev.ml +++ b/testsuite/tests/tool-debugger/no_debug_event/noev.ml @@ -1,27 +1,28 @@ (* TEST files = "a.ml b.ml" ocamldebug_script = "${test_source_directory}/input_script" -* shared-libraries -** setup-ocamlc.byte-build-env -*** ocamlc.byte +* debugger +** shared-libraries +*** setup-ocamlc.byte-build-env +**** ocamlc.byte module = "a.ml" flags = "-g -for-pack foo" -**** ocamlc.byte +***** ocamlc.byte module = "" all_modules = "a.cmo" program = "foo.cmo" flags = "-g -pack" -***** ocamlc.byte +****** ocamlc.byte module = "b.ml" flags = " -g " -****** ocamlc.byte +******* ocamlc.byte module = "" flags = " -g " all_modules = "foo.cmo b.cmo" program = "${test_build_directory}/noev.exe" -******* check-ocamlc.byte-output -******** ocamldebug -********* check-program-output +******** check-ocamlc.byte-output +********* ocamldebug +********** check-program-output *) (* This file only contains the specification of how to run the test *) diff --git a/testsuite/tests/tool-expect-test/clean_typer.ml b/testsuite/tests/tool-expect-test/clean_typer.ml new file mode 100644 index 00000000..535ce8d8 --- /dev/null +++ b/testsuite/tests/tool-expect-test/clean_typer.ml @@ -0,0 +1,82 @@ +(* TEST + * expect +*) + +module Variants = struct + type bar = [ `Bar ] + type foo = private [< `Foo | `Bar ] +end + +open Variants + +module M : sig + type +'a t + + val foo : unit -> foo t + val bar : unit -> bar t +end = struct + type 'a t = 'a list + + let foo () = [] + let bar () = [] +end + +module type Foo = sig + val x : foo M.t -> unit +end + +let ffoo t (module F : Foo) = + F.x t + +module type Bar = sig + val x : bar M.t -> unit +end + +let fbar t (module B : Bar) = + B.x t + +let (foo : foo M.t) = M.foo () +let (bar : bar M.t) = M.bar () +[%%expect {| +module Variants : + sig type bar = [ `Bar ] type foo = private [< `Bar | `Foo ] end +module M : + sig + type +'a t + val foo : unit -> Variants.foo t + val bar : unit -> Variants.bar t + end +module type Foo = sig val x : Variants.foo M.t -> unit end +val ffoo : Variants.foo M.t -> (module Foo) -> unit = +module type Bar = sig val x : Variants.bar M.t -> unit end +val fbar : Variants.bar M.t -> (module Bar) -> unit = +val foo : Variants.foo M.t = +val bar : Variants.bar M.t = +|}] + +let f1 = ffoo foo;; +[%%expect {| +val f1 : (module Foo) -> unit = +|}] + +let f2 = ffoo bar;; +[%%expect {| +Line 1, characters 14-17: +1 | let f2 = ffoo bar;; + ^^^ +Error: This expression has type Variants.bar M.t + but an expression was expected of type Variants.foo M.t + Type Variants.bar = [ `Bar ] is not compatible with type Variants.foo + The first variant type does not allow tag(s) `Foo +|}] + +let f3 = fbar foo;; +[%%expect {| +Line 1, characters 14-17: +1 | let f3 = fbar foo;; + ^^^ +Error: This expression has type Variants.foo M.t + but an expression was expected of type Variants.bar M.t + Type Variants.foo is not compatible with type Variants.bar = [ `Bar ] + The second variant type does not allow tag(s) `Foo +|}] diff --git a/testsuite/tests/tool-expect-test/ocamltests b/testsuite/tests/tool-expect-test/ocamltests new file mode 100644 index 00000000..c7e19b87 --- /dev/null +++ b/testsuite/tests/tool-expect-test/ocamltests @@ -0,0 +1 @@ +clean_typer.ml diff --git a/testsuite/tests/tool-lexyacc/chars.mll b/testsuite/tests/tool-lexyacc/chars.mll new file mode 100644 index 00000000..119a0f7e --- /dev/null +++ b/testsuite/tests/tool-lexyacc/chars.mll @@ -0,0 +1,16 @@ +(* TEST + ocamllex_flags = " -q " +*) + +{ +let f' _ = () +let f1 _ = () +let f2 _ _ = () +} + +rule token = parse + | 'a' { f' '"' } + | 'b' { f2 '\o170' '"' } + | 'c' { f1 "\u{1F42B}" } + | 'd' { f1 {|}|} } + | 'e' { (* " *) } (* " *) } diff --git a/testsuite/tests/tool-lexyacc/main.ml b/testsuite/tests/tool-lexyacc/main.ml index 4f58b93e..511a7769 100644 --- a/testsuite/tests/tool-lexyacc/main.ml +++ b/testsuite/tests/tool-lexyacc/main.ml @@ -1,5 +1,6 @@ (* TEST - modules = "syntax.ml gram_aux.ml grammar.mly scan_aux.ml scanner.mll lexgen.ml output.ml" + modules = "syntax.ml gram_aux.ml grammar.mly scan_aux.ml scanner.mll \ + lexgen.ml output.ml" files = "input" arguments = "input" ocamllex_flags = " -q " diff --git a/testsuite/tests/tool-lexyacc/mpr7760.mll b/testsuite/tests/tool-lexyacc/mpr7760.mll new file mode 100644 index 00000000..bffca2d5 --- /dev/null +++ b/testsuite/tests/tool-lexyacc/mpr7760.mll @@ -0,0 +1,13 @@ +(* TEST + ocamllex_flags = " -q " +*) + +rule read = shortest + | ("aa" | "bbb") (_ as x) _? { x } + | _ as y { y } + +{ + let r = read (Lexing.from_string "aasdf") in + Printf.printf "<%c>\n" r ; + () +} diff --git a/testsuite/tests/tool-lexyacc/mpr7760.reference b/testsuite/tests/tool-lexyacc/mpr7760.reference new file mode 100644 index 00000000..ece61086 --- /dev/null +++ b/testsuite/tests/tool-lexyacc/mpr7760.reference @@ -0,0 +1 @@ + diff --git a/testsuite/tests/tool-lexyacc/ocamltests b/testsuite/tests/tool-lexyacc/ocamltests index d389d156..69c655f2 100644 --- a/testsuite/tests/tool-lexyacc/ocamltests +++ b/testsuite/tests/tool-lexyacc/ocamltests @@ -1 +1,3 @@ main.ml +mpr7760.mll +chars.mll diff --git a/testsuite/tests/tool-lexyacc/output.ml b/testsuite/tests/tool-lexyacc/output.ml index 973aa5e4..957c82a7 100644 --- a/testsuite/tests/tool-lexyacc/output.ml +++ b/testsuite/tests/tool-lexyacc/output.ml @@ -21,7 +21,7 @@ let copy_chunk (Location(start,stop)) = let output_action (i,act) = - output_string !oc ("action_" ^ string_of_int i ^ " lexbuf = (\n"); + output_string !oc ("action_" ^ Int.to_string i ^ " lexbuf = (\n"); copy_chunk act; output_string !oc ")\nand " @@ -44,7 +44,7 @@ let enumerate_vect v = with Not_found -> env := (v.(pos), {pos = [pos]; freq = 1 }) :: !env done; - Sort.list (fun (e1, occ1) (e2, occ2) -> occ1.freq >= occ2.freq) !env + List.sort (fun (e1, occ1) (e2, occ2) -> compare occ2.freq occ1.freq) !env let output_move = function @@ -53,9 +53,9 @@ let output_move = function | Goto dest -> match !states.(dest) with Perform act_num -> - output_string !oc ("action_" ^ string_of_int act_num ^ " lexbuf") + output_string !oc ("action_" ^ Int.to_string act_num ^ " lexbuf") | _ -> - output_string !oc ("state_" ^ string_of_int dest ^ " lexbuf") + output_string !oc ("state_" ^ Int.to_string dest ^ " lexbuf") (* Cannot use standard char_for_read because the characters to escape @@ -111,13 +111,13 @@ let output_state state_num = function () | Shift(what_to_do, moves) -> output_string !oc - ("state_" ^ string_of_int state_num ^ " lexbuf =\n"); + ("state_" ^ Int.to_string state_num ^ " lexbuf =\n"); begin match what_to_do with No_remember -> () | Remember i -> output_string !oc (" Lexing.set_backtrack lexbuf action_" ^ - string_of_int i ^ ";\n") + Int.to_string i ^ ";\n") end; output_all_trans moves @@ -129,7 +129,7 @@ let rec output_entries = function | (name,state_num) :: rest -> output_string !oc (name ^ " lexbuf =\n"); output_string !oc " Lexing.init lexbuf;\n"; - output_string !oc (" state_" ^ string_of_int state_num ^ + output_string !oc (" state_" ^ Int.to_string state_num ^ " lexbuf\n"); match rest with [] -> () diff --git a/testsuite/tests/tool-ocaml-annot/check-annot.sh b/testsuite/tests/tool-ocaml-annot/check-annot.sh new file mode 100755 index 00000000..f8b0e635 --- /dev/null +++ b/testsuite/tests/tool-ocaml-annot/check-annot.sh @@ -0,0 +1,7 @@ +#!/bin/sh +MODULENAME=$1 +if [ -f ${test_build_directory}/${MODULENAME}.annot ]; then +exit ${TEST_PASS} +else +exit ${TEST_FAIL} +fi diff --git a/testsuite/tests/tool-ocaml-annot/failure.ml b/testsuite/tests/tool-ocaml-annot/failure.ml new file mode 100644 index 00000000..fd9ad0fb --- /dev/null +++ b/testsuite/tests/tool-ocaml-annot/failure.ml @@ -0,0 +1,19 @@ +(* TEST + +flags = "-annot" +script = "sh ${test_source_directory}/check-annot.sh failure" +ocamlc_byte_exit_status = "2" +ocamlopt_byte_exit_status = "2" + +* setup-ocamlc.byte-build-env +** ocamlc.byte +*** script + +* setup-ocamlopt.byte-build-env +** ocamlopt.byte +*** script +*) + +(* Check that .annot files are emitted in case of failed compilation. *) +let a = 3 +let b = a +. 1 diff --git a/testsuite/tests/tool-ocaml-annot/ocamltests b/testsuite/tests/tool-ocaml-annot/ocamltests new file mode 100644 index 00000000..156c866d --- /dev/null +++ b/testsuite/tests/tool-ocaml-annot/ocamltests @@ -0,0 +1,3 @@ +success.ml +failure.ml +typeonly.ml diff --git a/testsuite/tests/tool-ocaml-annot/success.ml b/testsuite/tests/tool-ocaml-annot/success.ml new file mode 100644 index 00000000..126799c9 --- /dev/null +++ b/testsuite/tests/tool-ocaml-annot/success.ml @@ -0,0 +1,18 @@ +(* TEST + +flags = "-annot" +script = "sh ${test_source_directory}/check-annot.sh success" + +* setup-ocamlc.byte-build-env +** ocamlc.byte +*** script + +* setup-ocamlopt.byte-build-env +** ocamlopt.byte +*** script +*) + +(* Check that .annot files are emitted in case of regular successful + compilation. *) +let a = 3 +let b = float a diff --git a/testsuite/tests/tool-ocaml-annot/typeonly.ml b/testsuite/tests/tool-ocaml-annot/typeonly.ml new file mode 100644 index 00000000..db8d1eae --- /dev/null +++ b/testsuite/tests/tool-ocaml-annot/typeonly.ml @@ -0,0 +1,18 @@ +(* TEST + +flags = "-i -annot" +compile_only = "true" +script = "sh ${test_source_directory}/check-annot.sh typeonly" + +* setup-ocamlc.byte-build-env +** ocamlc.byte +*** script + +* setup-ocamlopt.byte-build-env +** ocamlopt.byte +*** script +*) + +(* Check that .annot files are emitted in case of type-only compilation. *) +let a = 3 +let b = float a diff --git a/testsuite/tests/tool-ocaml/t240-c_call1.ml b/testsuite/tests/tool-ocaml/t240-c_call1.ml index 0b0bfd41..b1be841f 100644 --- a/testsuite/tests/tool-ocaml/t240-c_call1.ml +++ b/testsuite/tests/tool-ocaml/t240-c_call1.ml @@ -7,9 +7,9 @@ ocaml_script_as_argument = "true" *) open Lib;; -if Pervasives.int_of_string "123" <> 123 then raise Not_found;; +if Stdlib.int_of_string "123" <> 123 then raise Not_found;; (** test for fix of bug 6649: http://caml.inria.fr/mantis/view.php?id=6649 *) -if Pervasives.int_of_string "+123" <> 123 then raise Not_found;; +if Stdlib.int_of_string "+123" <> 123 then raise Not_found;; if Int32.of_string "+123" <> Int32.of_int 123 then raise Not_found;; if Int64.of_string "+123" <> Int64.of_int 123 then raise Not_found;; diff --git a/testsuite/tests/tool-ocamlc-error-cleanup/check-error-cleanup.sh b/testsuite/tests/tool-ocamlc-error-cleanup/check-error-cleanup.sh new file mode 100644 index 00000000..c70bee7b --- /dev/null +++ b/testsuite/tests/tool-ocamlc-error-cleanup/check-error-cleanup.sh @@ -0,0 +1,6 @@ +if [ -f test.cmo ] +then + exit ${TEST_FAIL} +else + exit ${TEST_PASS} +fi diff --git a/testsuite/tests/tool-ocamlc-error-cleanup/ocamltests b/testsuite/tests/tool-ocamlc-error-cleanup/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/tool-ocamlc-error-cleanup/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/tool-ocamlc-error-cleanup/test.ml b/testsuite/tests/tool-ocamlc-error-cleanup/test.ml new file mode 100644 index 00000000..b0013bd8 --- /dev/null +++ b/testsuite/tests/tool-ocamlc-error-cleanup/test.ml @@ -0,0 +1,16 @@ +(* TEST +* setup-ocamlc.byte-build-env +compiler_output = "compiler-output.raw" +** ocamlc.byte +all_modules = "test.ml" +flags = "-warn-error A" +ocamlc_byte_exit_status = "2" +*** script +script = "sh ${test_source_directory}/check-error-cleanup.sh" +*) + +(* Regression test for MPR#7918 *) +let f () = + (* -warn-error A will error with unused x below *) + let x = 12 in + 1 diff --git a/testsuite/tests/tool-ocamlc-stop-after/ocamltests b/testsuite/tests/tool-ocamlc-stop-after/ocamltests new file mode 100644 index 00000000..ebd7d56f --- /dev/null +++ b/testsuite/tests/tool-ocamlc-stop-after/ocamltests @@ -0,0 +1,3 @@ +stop_after_parsing_impl.ml +stop_after_parsing_intf.mli +stop_after_typing_impl.ml diff --git a/testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_impl.compilers.reference b/testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_impl.compilers.reference new file mode 100644 index 00000000..8cac2daa --- /dev/null +++ b/testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_impl.compilers.reference @@ -0,0 +1,36 @@ +[ + structure_item (stop_after_parsing_impl.ml[12,306+0]..[12,306+24]) + Pstr_value Nonrec + [ + + pattern (stop_after_parsing_impl.ml[12,306+4]..[12,306+5]) + Ppat_any + expression (stop_after_parsing_impl.ml[12,306+8]..[12,306+24]) + Pexp_apply + expression (stop_after_parsing_impl.ml[12,306+21]..[12,306+22]) + Pexp_ident "+" (stop_after_parsing_impl.ml[12,306+21]..[12,306+22]) + [ + + Nolabel + expression (stop_after_parsing_impl.ml[12,306+8]..[12,306+20]) + Pexp_apply + expression (stop_after_parsing_impl.ml[12,306+11]..[12,306+12]) + Pexp_ident "+" (stop_after_parsing_impl.ml[12,306+11]..[12,306+12]) + [ + + Nolabel + expression (stop_after_parsing_impl.ml[12,306+9]..[12,306+10]) + Pexp_constant PConst_int (1,None) + + Nolabel + expression (stop_after_parsing_impl.ml[12,306+13]..[12,306+19]) + Pexp_constant PConst_string("true",None) + ] + + Nolabel + expression (stop_after_parsing_impl.ml[12,306+23]..[12,306+24]) + Pexp_ident "x" (stop_after_parsing_impl.ml[12,306+23]..[12,306+24]) + ] + ] +] + diff --git a/testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_impl.ml b/testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_impl.ml new file mode 100644 index 00000000..3276733c --- /dev/null +++ b/testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_impl.ml @@ -0,0 +1,12 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte + flags = "-stop-after parsing -dparsetree" + ocamlc_byte_exit_status = "0" +*** check-ocamlc.byte-output +*) + +(* we intentionally write ill-typed output; + if `-stop-after parsing` was not supported properly, + the test would fail with an error *) +let _ = (1 + "true") + x diff --git a/testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_intf.compilers.reference b/testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_intf.compilers.reference new file mode 100644 index 00000000..f5cb47d1 --- /dev/null +++ b/testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_intf.compilers.reference @@ -0,0 +1,10 @@ +[ + signature_item (stop_after_parsing_intf.mli[12,306+0]..[12,306+61]) + Psig_value + value_description "x" (stop_after_parsing_intf.mli[12,306+4]..[12,306+5]) (stop_after_parsing_intf.mli[12,306+0]..[12,306+61]) + core_type (stop_after_parsing_intf.mli[12,306+8]..[12,306+61]) + Ptyp_constr "Module_that_does_not_exists.type_that_does_not_exists" (stop_after_parsing_intf.mli[12,306+8]..[12,306+61]) + [] + [] +] + diff --git a/testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_intf.mli b/testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_intf.mli new file mode 100644 index 00000000..328a78d4 --- /dev/null +++ b/testsuite/tests/tool-ocamlc-stop-after/stop_after_parsing_intf.mli @@ -0,0 +1,12 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte + flags = "-stop-after parsing -dparsetree" + ocamlc_byte_exit_status = "0" +*** check-ocamlc.byte-output +*) + +(* we intentionally write ill-typed output; + if `-stop-after parsing` was not supported properly, + the test would fail with an error *) +val x : Module_that_does_not_exists.type_that_does_not_exists diff --git a/testsuite/tests/tool-ocamlc-stop-after/stop_after_typing_impl.compilers.reference b/testsuite/tests/tool-ocamlc-stop-after/stop_after_typing_impl.compilers.reference new file mode 100644 index 00000000..257eeb74 --- /dev/null +++ b/testsuite/tests/tool-ocamlc-stop-after/stop_after_typing_impl.compilers.reference @@ -0,0 +1,18 @@ +[ + structure_item (stop_after_typing_impl.ml[13,349+0]..stop_after_typing_impl.ml[13,349+37]) + Tstr_primitive + value_description apply/80 (stop_after_typing_impl.ml[13,349+0]..stop_after_typing_impl.ml[13,349+37]) + core_type (stop_after_typing_impl.ml[13,349+16]..stop_after_typing_impl.ml[13,349+26]) + Ttyp_arrow + Nolabel + core_type (stop_after_typing_impl.ml[13,349+16]..stop_after_typing_impl.ml[13,349+19]) + Ttyp_constr "int/1!" + [] + core_type (stop_after_typing_impl.ml[13,349+23]..stop_after_typing_impl.ml[13,349+26]) + Ttyp_constr "int/1!" + [] + [ + "%apply" + ] +] + diff --git a/testsuite/tests/tool-ocamlc-stop-after/stop_after_typing_impl.ml b/testsuite/tests/tool-ocamlc-stop-after/stop_after_typing_impl.ml new file mode 100644 index 00000000..e7e9d089 --- /dev/null +++ b/testsuite/tests/tool-ocamlc-stop-after/stop_after_typing_impl.ml @@ -0,0 +1,13 @@ +(* TEST +* setup-ocamlc.byte-build-env +** ocamlc.byte + flags = "-stop-after typing -dtypedtree" + ocamlc_byte_exit_status = "0" +*** check-ocamlc.byte-output +*) + +(* we intentionally write an output that is type-correct + but will be rejected before bytecode compilation + due to the incorrect type given to the %apply + compiler primitive. *) +external apply: int -> int = "%apply" diff --git a/testsuite/tests/tool-ocamldep-modalias/Makefile b/testsuite/tests/tool-ocamldep-modalias/Makefile deleted file mode 100644 index 476a8ace..00000000 --- a/testsuite/tests/tool-ocamldep-modalias/Makefile +++ /dev/null @@ -1,73 +0,0 @@ -# Test for ocamldep and -no-alias-deps -# There are two versions: -# Makefile.build uses -no-alias-deps only for lib.ml/mli -# Makefile.build2 has no lib.ml, and uses -no-alias-deps for components too - -OCAMLDEP=$(OCAMLRUN) $(OTOPDIR)/tools/ocamldep -SOURCES = A.ml B.ml C.ml D.ml -LINKS = $(SOURCES:%=Lib%) -DEPENDS = depend.mk depend.mk2 depend.mod depend.mod2 depend.mod3 - -all: clean - @$(MAKE) build > /dev/null - @$(MAKE) $(DEPENDS) > /dev/null - @$(MAKE) compare - -build: depend.mk depend.mk2 - rm -f $(LINKS) - if $(NATIVECODE_ONLY); then : ; else \ - $(MAKE) -f Makefile.build byte; \ - rm -f *.cm* lib.ml; \ - $(MAKE) -f Makefile.build2 byte; fi - if $(BYTECODE_ONLY); then :; else \ - $(MAKE) -f Makefile.build opt; \ - rm -f *.cm* lib.ml; \ - $(MAKE) -f Makefile.build2 opt; fi - -# Create links for prefixed versions of the components -Lib%.ml: %.ml - cp $< $@ - -# Dependencies for Makefile.build, compiling and linking lib.cmo -depend.mk: $(LINKS) - cp lib_impl.ml lib.ml - $(OCAMLDEP) -as-map lib.ml lib.mli > $@ - $(OCAMLDEP) -map lib.ml -open Lib $(LINKS) >> $@ - -# Dependencies for Makefile.build2, not compiling lib.cmo -depend.mk2: $(LINKS) - rm -f lib.ml - $(OCAMLDEP) -map lib.mli -open Lib \ - $(LINKS) > $@ - -# Others tests for ocamldep -depend.mod: $(LINKS) - cp lib_impl.ml lib.ml - $(OCAMLDEP) -as-map -modules lib.ml lib.mli > $@ - $(OCAMLDEP) -modules -map lib.ml -open Lib $(LINKS) >> $@ - -depend.mod2: $(LINKS) - rm -f lib.ml - $(OCAMLDEP) -modules -map lib.mli $(LINKS) > $@ - -depend.mod3: $(LINKS) - rm -f lib.ml - $(OCAMLDEP) -modules -as-map -map lib.mli -open Lib \ - $(LINKS) > $@ - -promote: - for i in $(DEPENDS); do cp $$i $$i.reference; done - -compare: $(DEPENDS) - @rm -f $(LINKS) lib.ml - @for i in $(DEPENDS); do \ - printf " ... testing '$$i':"; \ - $(DIFF) $$i.reference $$i > /dev/null \ - && echo " => passed" || echo " => failed"; \ - done - -clean: - @rm -f *.cm* *.$(O) *.$(A) $(DEPENDS) $(LINKS) lib.ml *~ *.byt* *.opt* - -BASEDIR=../.. -include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/tool-ocamldep-modalias/Makefile.build b/testsuite/tests/tool-ocamldep-modalias/Makefile.build index 17c61dfb..a28f99d4 100644 --- a/testsuite/tests/tool-ocamldep-modalias/Makefile.build +++ b/testsuite/tests/tool-ocamldep-modalias/Makefile.build @@ -1,29 +1,43 @@ # Makefile using -no-alias-deps only for lib.ml/mli +# Note: not using pattern rules here is intended. +# This is to be as portable as possible since this Makefile +# will not necessarily be ran by GNU make +# The same holds for $< and $@ + SOURCES = A.ml B.ml C.ml D.ml OBJECTS = lib.cmo $(SOURCES:%.ml=Lib%.cmo) NOBJECTS = $(OBJECTS:%.cmo=%.cmx) byte: main.byt -opt: main.opt +opt: clean main.opt main.byt: lib.cma main.cmo $(OCAMLC) lib.cma main.cmo -o $@ lib.ml: lib_impl.ml - cp $< $@ + cp lib_impl.ml lib.ml lib.cma: $(OBJECTS) $(OCAMLC) -a -o $@ $(OBJECTS) lib.cmi: lib.mli - $(OCAMLC) -c -no-alias-deps -w -49 $< + $(OCAMLC) -c -no-alias-deps -w -49 lib.mli lib.cmo: lib.ml - $(OCAMLC) -c -no-alias-deps -w -49 $< + $(OCAMLC) -c -no-alias-deps -w -49 lib.ml + +LibA.cmo: A.ml + $(OCAMLC) -c -open Lib -o LibA.cmo A.ml + +LibB.cmo: B.ml + $(OCAMLC) -c -open Lib -o LibB.cmo B.ml -Lib%.cmo: %.ml - $(OCAMLC) -c -open Lib -o $@ $< +LibC.cmo: C.ml + $(OCAMLC) -c -open Lib -o LibC.cmo C.ml + +LibD.cmo: D.ml + $(OCAMLC) -c -open Lib -o LibD.cmo D.ml main.opt: lib.cmxa main.cmx $(OCAMLOPT) lib.cmxa main.cmx -o $@ @@ -34,10 +48,28 @@ lib.cmxa: $(NOBJECTS) lib.cmx: lib.ml $(OCAMLOPT) -c -no-alias-deps -w -49 $< -Lib%.cmx: %.ml - $(OCAMLOPT) -c -open Lib -o $@ $< +LibA.cmx: A.ml + $(OCAMLOPT) -c -open Lib -o LibA.cmx A.ml + +LibB.cmx: B.ml + $(OCAMLOPT) -c -open Lib -o LibB.cmx B.ml + +LibC.cmx: C.ml + $(OCAMLOPT) -c -open Lib -o LibC.cmx C.ml + +LibD.cmx: D.ml + $(OCAMLOPT) -c -open Lib -o LibD.cmx D.ml include depend.mk -BASEDIR=../.. -include $(BASEDIR)/makefiles/Makefile.common +.PHONY: clean +clean: + rm -f *.cm* lib.ml + +.SUFFIXES: .ml .cmo .cmx + +.ml.cmo: + $(OCAMLC) -c $< + +.ml.cmx: + $(OCAMLOPT) -c $< diff --git a/testsuite/tests/tool-ocamldep-modalias/Makefile.build2 b/testsuite/tests/tool-ocamldep-modalias/Makefile.build2 index a75477b9..e9b1d690 100644 --- a/testsuite/tests/tool-ocamldep-modalias/Makefile.build2 +++ b/testsuite/tests/tool-ocamldep-modalias/Makefile.build2 @@ -1,38 +1,63 @@ # Makefile using -no-alias-deps for all files, no need to link lib.cmo +# Note: not using pattern rules here is intended. +# This is to be as portable as possible since this Makefile +# will not necessarily be ran by GNU make +# The same holds for $< and $@ + SOURCES = A.ml B.ml C.ml OBJECTS = $(SOURCES:%.ml=Lib%.cmo) NOBJECTS = $(OBJECTS:%.cmo=%.cmx) byte: main.byt2 -opt: main.opt2 +opt: clean main.opt2 main.byt2: lib2.cma main.cmo - $(OCAMLC) lib2.cma main.cmo -o $@ + $(OCAMLC) -no-alias-deps lib2.cma main.cmo -o main.byt2 lib2.cma: $(OBJECTS) - $(OCAMLC) -a -o $@ $(OBJECTS) + $(OCAMLC) -no-alias-deps -a -o lib2.cma $(OBJECTS) lib.cmi: lib.mli - $(OCAMLC) -c -w -49 $< + $(OCAMLC) -no-alias-deps -c -w -49 lib.mli + +LibA.cmo: A.ml + $(OCAMLC) -no-alias-deps -c -open Lib -o LibA.cmo A.ml -Lib%.cmo: %.ml - $(OCAMLC) -c -open Lib -o $@ $< +LibB.cmo: B.ml + $(OCAMLC) -no-alias-deps -c -open Lib -o LibB.cmo B.ml + +LibC.cmo: C.ml + $(OCAMLC) -no-alias-deps -c -open Lib -o LibC.cmo C.ml main.opt2: lib.cmxa main.cmx - $(OCAMLOPT) lib.cmxa main.cmx -o $@ + $(OCAMLOPT) -no-alias-deps lib.cmxa main.cmx -o main.opt2 lib.cmxa: $(NOBJECTS) - $(OCAMLOPT) -a -o $@ $(NOBJECTS) + $(OCAMLOPT) -no-alias-deps -a -o lib.cmxa $(NOBJECTS) lib.cmx: lib.ml - $(OCAMLOPT) -c -no-alias-deps -w -49 $< + $(OCAMLOPT) -no-alias-deps -c -w -49 lib.ml + +LibA.cmx: A.ml + $(OCAMLOPT) -no-alias-deps -c -open Lib -o LibA.cmx A.ml -Lib%.cmx: %.ml - $(OCAMLOPT) -c -open Lib -o $@ $< +LibB.cmx: B.ml + $(OCAMLOPT) -no-alias-deps -c -open Lib -o LibB.cmx B.ml + +LibC.cmx: C.ml + $(OCAMLOPT) -no-alias-deps -c -open Lib -o LibC.cmx C.ml include depend.mk2 -BASEDIR=../.. -include $(BASEDIR)/makefiles/Makefile.common -COMPFLAGS = -no-alias-deps # Used by $(OCAMLC) +.PHONY: clean +clean: + rm -f *.cm* lib.ml + +.SUFFIXES: .ml .cmo .cmx + +.ml.cmo: + $(OCAMLC) -no-alias-deps -c $< + +.ml.cmx: + $(OCAMLOPT) -no-alias-deps -c $< diff --git a/testsuite/tests/tool-ocamldep-modalias/depend.mk.reference b/testsuite/tests/tool-ocamldep-modalias/depend.mk.reference index 951b5d26..cbec4e4c 100644 --- a/testsuite/tests/tool-ocamldep-modalias/depend.mk.reference +++ b/testsuite/tests/tool-ocamldep-modalias/depend.mk.reference @@ -1,11 +1,27 @@ -lib.cmo : lib.cmi -lib.cmx : lib.cmi +lib.cmo : \ + lib.cmi +lib.cmx : \ + lib.cmi lib.cmi : -LibA.cmo : lib.cmi -LibA.cmx : lib.cmx -LibB.cmo : LibA.cmo lib.cmi -LibB.cmx : LibA.cmx lib.cmx -LibC.cmo : LibB.cmo LibA.cmo lib.cmi -LibC.cmx : LibB.cmx LibA.cmx lib.cmx -LibD.cmo : lib.cmi -LibD.cmx : lib.cmx +LibA.cmo : \ + lib.cmi +LibA.cmx : \ + lib.cmx +LibB.cmo : \ + LibA.cmo \ + lib.cmi +LibB.cmx : \ + LibA.cmx \ + lib.cmx +LibC.cmo : \ + LibB.cmo \ + LibA.cmo \ + lib.cmi +LibC.cmx : \ + LibB.cmx \ + LibA.cmx \ + lib.cmx +LibD.cmo : \ + lib.cmi +LibD.cmx : \ + lib.cmx diff --git a/testsuite/tests/tool-ocamldep-modalias/depend.mk2.reference b/testsuite/tests/tool-ocamldep-modalias/depend.mk2.reference index a3f73b5e..05d501f5 100644 --- a/testsuite/tests/tool-ocamldep-modalias/depend.mk2.reference +++ b/testsuite/tests/tool-ocamldep-modalias/depend.mk2.reference @@ -1,8 +1,22 @@ -LibA.cmo : lib.cmi -LibA.cmx : lib.cmi -LibB.cmo : LibA.cmo lib.cmi -LibB.cmx : LibA.cmx lib.cmi -LibC.cmo : LibB.cmo LibA.cmo lib.cmi -LibC.cmx : LibB.cmx LibA.cmx lib.cmi -LibD.cmo : lib.cmi -LibD.cmx : lib.cmi +LibA.cmo : \ + lib.cmi +LibA.cmx : \ + lib.cmi +LibB.cmo : \ + LibA.cmo \ + lib.cmi +LibB.cmx : \ + LibA.cmx \ + lib.cmi +LibC.cmo : \ + LibB.cmo \ + LibA.cmo \ + lib.cmi +LibC.cmx : \ + LibB.cmx \ + LibA.cmx \ + lib.cmi +LibD.cmo : \ + lib.cmi +LibD.cmx : \ + lib.cmi diff --git a/testsuite/tests/tool-ocamldep-modalias/main.ml b/testsuite/tests/tool-ocamldep-modalias/main.ml index 94668912..18be061d 100644 --- a/testsuite/tests/tool-ocamldep-modalias/main.ml +++ b/testsuite/tests/tool-ocamldep-modalias/main.ml @@ -1,3 +1,86 @@ +(* TEST + +files = "A.ml B.ml C.ml D.ml lib_impl.ml lib.mli" + +script = "sh ${test_source_directory}/setup-links.sh" +set sources = "A.ml B.ml C.ml D.ml" +set links = "LibA.ml LibB.ml LibC.ml LibD.ml" +set stdlib = "-nostdlib -I ${ocamlsrcdir}/stdlib" +set OCAMLC = "${ocamlrun} ${ocamlc_byte} ${stdlib}" +set OCAMLOPT = "${ocamlrun} ${ocamlopt_byte} ${stdlib}" + +* setup-ocamlc.byte-build-env +compiler_directory_suffix = ".depend.mk" +compiler_output = "${test_build_directory}/depend.mk" +** script +*** script +script = "cp lib_impl.ml lib.ml" +**** ocamlc.byte +commandline = "-depend -as-map lib.ml lib.mli" +***** ocamlc.byte +commandline = "-depend -map lib.ml -open Lib ${links}" +****** check-ocamlc.byte-output +compiler_reference = "${test_source_directory}/depend.mk.reference" +******* hasunix +******** script +script = "cp ${test_source_directory}/Makefile.build Makefile" +********* script +script = "rm -f ${links}" +********** script +script = "${MAKE} byte" +*********** native-compiler +************ script +script = "${MAKE} opt" + +* setup-ocamlc.byte-build-env +compiler_directory_suffix = ".depend.mk2" +compiler_output = "${test_build_directory}/depend.mk2" +** script +*** ocamlc.byte +commandline = "-depend -map lib.mli -open Lib ${links}" +**** check-ocamlc.byte-output +compiler_reference = "${test_source_directory}/depend.mk2.reference" +***** hasunix +****** script +script = "rm -f ${links}" +******* script +script = "cp ${test_source_directory}/Makefile.build2 Makefile" +******** script +script = "${MAKE} byte" +********* native-compiler +********** script +script = "${MAKE} opt" + +* setup-ocamlc.byte-build-env +compiler_directory_suffix = ".depend.mod" +** script +*** script +script = "cp lib_impl.ml lib.ml" +**** ocamlc.byte +commandline = "-depend -as-map -modules lib.ml lib.mli" +***** ocamlc.byte +commandline = "-depend -modules -map lib.ml -open Lib ${links}" +****** check-ocamlc.byte-output +compiler_reference = "${test_source_directory}/depend.mod.reference" + +* setup-ocamlc.byte-build-env +compiler_directory_suffix = ".depend.mod2" +** script +*** ocamlc.byte +commandline = "-depend -modules -map lib.mli ${links}" +**** check-ocamlc.byte-output +compiler_reference = "${test_source_directory}/depend.mod2.reference" + +* setup-ocamlc.byte-build-env +compiler_directory_suffix = ".depend.mod3" +** script +*** ocamlc.byte +commandline = "-depend -modules -as-map -map lib.mli -open Lib ${links}" +**** check-ocamlc.byte-output +compiler_reference = "${test_source_directory}/depend.mod3.reference" + +*) + open Lib let () = Printf.printf "B.g 3 = %d\n%!" (B.g 3) diff --git a/testsuite/tests/tool-ocamldep-modalias/ocamltests b/testsuite/tests/tool-ocamldep-modalias/ocamltests new file mode 100644 index 00000000..d389d156 --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/ocamltests @@ -0,0 +1 @@ +main.ml diff --git a/testsuite/tests/tool-ocamldep-modalias/setup-links.sh b/testsuite/tests/tool-ocamldep-modalias/setup-links.sh new file mode 100644 index 00000000..1197fff1 --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/setup-links.sh @@ -0,0 +1,2 @@ +#!/bin/sh +for i in A B C D; do cp $i.ml Lib$i.ml; done diff --git a/testsuite/tests/tool-ocamldoc/Documentation_tags.mli b/testsuite/tests/tool-ocamldoc/Documentation_tags.mli index 413a4ca0..0dadce66 100644 --- a/testsuite/tests/tool-ocamldoc/Documentation_tags.mli +++ b/testsuite/tests/tool-ocamldoc/Documentation_tags.mli @@ -5,10 +5,10 @@ (** Test the html rendering of ocamldoc documentation tags *) val heterological: unit -(** +(** @author yes @param no No description - @param neither see no description + @param neither see no description @deprecated since the start of time @return () @see "Documentation_tags.mli" Self reference diff --git a/testsuite/tests/tool-ocamldoc/Include_module_type_of.html.reference b/testsuite/tests/tool-ocamldoc/Include_module_type_of.html.reference new file mode 100644 index 00000000..1619e218 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc/Include_module_type_of.html.reference @@ -0,0 +1,29 @@ + + + + + + + + + + +Include_module_type_of + + + +

    Module Include_module_type_of

    + +
    module Include_module_type_of: sig .. end
    +
    +

    Test include module type of... variants

    +
    +
    +
    + +
    module A: sig .. end
    +
    module M: sig .. end
    +
    module B: sig .. end
    +
    include Include_module_type_of.M
    + diff --git a/testsuite/tests/tool-ocamldoc/Include_module_type_of.latex.reference b/testsuite/tests/tool-ocamldoc/Include_module_type_of.latex.reference new file mode 100644 index 00000000..67edcaed --- /dev/null +++ b/testsuite/tests/tool-ocamldoc/Include_module_type_of.latex.reference @@ -0,0 +1,96 @@ +\documentclass[11pt]{article} +\usepackage[latin1]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{textcomp} +\usepackage{fullpage} +\usepackage{url} +\usepackage{ocamldoc} +\begin{document} +\tableofcontents +\section{Module {\tt{Include\_module\_type\_of}} : Test {\tt{include module type of...}} variants} +\label{Include-underscoremodule-underscoretype-underscoreof}\index{Include-underscoremodule-underscoretype-underscoreof@\verb`Include_module_type_of`} + + + + +\ocamldocvspace{0.5cm} + + + +\begin{ocamldoccode} +{\tt{module }}{\tt{A}}{\tt{ : }}\end{ocamldoccode} +\label{Include-underscoremodule-underscoretype-underscoreof.A}\index{A@\verb`A`} + +\begin{ocamldocsigend} + + +\label{TYPInclude-underscoremodule-underscoretype-underscoreof.A.t}\begin{ocamldoccode} +type t +\end{ocamldoccode} +\index{t@\verb`t`} +\end{ocamldocsigend} + + + + + + +\begin{ocamldoccode} +{\tt{module }}{\tt{M}}{\tt{ : }}\end{ocamldoccode} +\label{Include-underscoremodule-underscoretype-underscoreof.M}\index{M@\verb`M`} + +\begin{ocamldocsigend} + + +A module M + +\begin{ocamldoccode} +{\tt{module }}{\tt{Inner}}{\tt{ : }}\end{ocamldoccode} +\label{Include-underscoremodule-underscoretype-underscoreof.M.Inner}\index{Inner@\verb`Inner`} +\begin{ocamldocsigend} + + +\label{TYPInclude-underscoremodule-underscoretype-underscoreof.M.Inner.t}\begin{ocamldoccode} +type t +\end{ocamldoccode} +\index{t@\verb`t`} +\end{ocamldocsigend} + + + + +\begin{ocamldoccode} +{\tt{module }}{\tt{Alias}}{\tt{ : }}\end{ocamldoccode} +\label{Include-underscoremodule-underscoretype-underscoreof.M.Alias}\index{Alias@\verb`Alias`} +{\tt{Include\_module\_type\_of.A}} + + + +\label{TYPInclude-underscoremodule-underscoretype-underscoreof.M.t}\begin{ocamldoccode} +type t +\end{ocamldoccode} +\index{t@\verb`t`} +\end{ocamldocsigend} + + + + + + +\begin{ocamldoccode} +{\tt{module }}{\tt{B}}{\tt{ : }}\end{ocamldoccode} +\label{Include-underscoremodule-underscoretype-underscoreof.B}\index{B@\verb`B`} + +\begin{ocamldocsigend} + + +{\tt{include }}{\tt{Include\_module\_type\_of.M}}\end{ocamldocsigend} + + + + + + +{\tt{include }}{\tt{Include\_module\_type\_of.M}} + +\end{document} diff --git a/testsuite/tests/tool-ocamldoc/Include_module_type_of.mli b/testsuite/tests/tool-ocamldoc/Include_module_type_of.mli new file mode 100644 index 00000000..c30432d4 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc/Include_module_type_of.mli @@ -0,0 +1,21 @@ +(* TEST + * ocamldoc with html + * ocamldoc with latex +*) + +(** Test [include module type of...] variants *) + +module A: sig type t end +module M: sig + (** A module M *) + + module Inner: sig type t end + module Alias = A + type t +end + +module B: sig + include module type of M +end + +include module type of struct include M end diff --git a/testsuite/tests/tool-ocamldoc/Level_0.latex.reference b/testsuite/tests/tool-ocamldoc/Level_0.latex.reference index 331512ff..f6fdba54 100644 --- a/testsuite/tests/tool-ocamldoc/Level_0.latex.reference +++ b/testsuite/tests/tool-ocamldoc/Level_0.latex.reference @@ -7,13 +7,13 @@ \usepackage{ocamldoc} \begin{document} \tableofcontents -\section{Module {\tt{Level\_0}} : Test for level 0 headings } +\section{Module {\tt{Level\_0}} : Test for level 0 headings} \label{Level-underscore0}\index{Level-underscore0@\verb`Level_0`} \subsection*{Level 1} - + Standard heading levels start at 1. @@ -21,12 +21,12 @@ \section{Level 0} - A level 0 heading is guaranted to be at the same level that + A level 0 heading is guaranteed to be at the same level that the main heading of the module. - This setup allows users to start their standard heading at level 1 rather - than 2, without losing the ability to add global level heading, + This setup allows users to start their standard heading at level 1 rather + than 2, without losing the ability to add global level heading, when, if ever, such heading is warranted diff --git a/testsuite/tests/tool-ocamldoc/Level_0.mli b/testsuite/tests/tool-ocamldoc/Level_0.mli index d9458572..f7ac2a88 100644 --- a/testsuite/tests/tool-ocamldoc/Level_0.mli +++ b/testsuite/tests/tool-ocamldoc/Level_0.mli @@ -2,18 +2,18 @@ * ocamldoc with latex *) -(** Test for level 0 headings - - {1 Level 1} - +(** Test for level 0 headings + + {1 Level 1} + Standard heading levels start at 1. {0 Level 0} - A level 0 heading is guaranted to be at the same level that + A level 0 heading is guaranteed to be at the same level that the main heading of the module. - This setup allows users to start their standard heading at level 1 rather - than 2, without losing the ability to add global level heading, + This setup allows users to start their standard heading at level 1 rather + than 2, without losing the ability to add global level heading, when, if ever, such heading is warranted *) diff --git a/testsuite/tests/tool-ocamldoc/Paragraph.html.reference b/testsuite/tests/tool-ocamldoc/Paragraph.html.reference index 2672a5f6..7cc2bc1f 100644 --- a/testsuite/tests/tool-ocamldoc/Paragraph.html.reference +++ b/testsuite/tests/tool-ocamldoc/Paragraph.html.reference @@ -41,7 +41,7 @@
  • An enumerated list first element
  • second element
  • -
    Alignement test: left
    Right
    Center
    +
    Alignment test: left
    Right
    Center

    Other complex textin subscript and superscript

    There is also html specific elements.

    diff --git a/testsuite/tests/tool-ocamldoc/Paragraph.mli b/testsuite/tests/tool-ocamldoc/Paragraph.mli index 5e94589c..8073c7cd 100644 --- a/testsuite/tests/tool-ocamldoc/Paragraph.mli +++ b/testsuite/tests/tool-ocamldoc/Paragraph.mli @@ -30,7 +30,7 @@ + An enumerated list first element + second element - {L Alignement test: left} + {L Alignment test: left} {R Right} {C Center} diff --git a/testsuite/tests/tool-ocamldoc/latex_ref.latex.reference b/testsuite/tests/tool-ocamldoc/latex_ref.latex.reference new file mode 100644 index 00000000..5daabbc2 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc/latex_ref.latex.reference @@ -0,0 +1,27 @@ +\documentclass[11pt]{article} +\usepackage[latin1]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{textcomp} +\usepackage{fullpage} +\usepackage{url} +\usepackage{ocamldoc} +\begin{document} +\tableofcontents +\section{Module {\tt{Latex\_ref}} : Latex-only test} +\label{Latex-underscoreref}\index{Latex-underscoreref@\verb`Latex_ref`} + + + + +\ocamldocvspace{0.5cm} + + + +\subsection*{Title } +\label{lbl} + + + Check that this text[\ref{lbl}] is present in the generated latex + with a reference to [\ref{lbl}]. + +\end{document} diff --git a/testsuite/tests/tool-ocamldoc/latex_ref.mli b/testsuite/tests/tool-ocamldoc/latex_ref.mli new file mode 100644 index 00000000..8424aa89 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc/latex_ref.mli @@ -0,0 +1,11 @@ +(* TEST + * ocamldoc with latex +*) + +(** Latex-only test *) + +(** {1:lbl Title } + + Check that {{!lbl}this text} is present in the generated latex + with a reference to {!lbl}. +*) diff --git a/testsuite/tests/tool-ocamldoc/ocamltests b/testsuite/tests/tool-ocamldoc/ocamltests index 0d05eb3d..b9fbde78 100644 --- a/testsuite/tests/tool-ocamldoc/ocamltests +++ b/testsuite/tests/tool-ocamldoc/ocamltests @@ -1,11 +1,13 @@ Documentation_tags.mli Extensible_variant.ml +Include_module_type_of.mli Inline_records.mli Inline_records_bis.ml Item_ids.mli Paragraph.mli Module_whitespace.ml No_preamble.mli +latex_ref.mli Level_0.mli Linebreaks.mli Loop.ml diff --git a/testsuite/tests/tool-ocamlobjinfo/has-lib-bfd.sh b/testsuite/tests/tool-ocamlobjinfo/has-lib-bfd.sh index 4074d6da..1b268740 100644 --- a/testsuite/tests/tool-ocamlobjinfo/has-lib-bfd.sh +++ b/testsuite/tests/tool-ocamlobjinfo/has-lib-bfd.sh @@ -1,6 +1,6 @@ #!/bin/sh -if grep -q HAS_LIBBFD ${ocamlsrcdir}/byterun/caml/s.h; then +if grep -q "#define HAS_LIBBFD" ${ocamlsrcdir}/runtime/caml/s.h; then exit ${TEST_PASS}; fi echo libbfd not available > ${ocamltest_response} diff --git a/testsuite/tests/tool-toplevel-invocation/test.ml b/testsuite/tests/tool-toplevel-invocation/test.ml index 3932035c..1229e5db 100644 --- a/testsuite/tests/tool-toplevel-invocation/test.ml +++ b/testsuite/tests/tool-toplevel-invocation/test.ml @@ -13,14 +13,16 @@ ocaml_exit_status = "2" ** ocaml flags = "-args ${test_source_directory}/indirect_first_arg_fail.txt" -compiler_reference = "${test_source_directory}/indirect_first_arg_fail.txt.reference" +compiler_reference = + "${test_source_directory}/indirect_first_arg_fail.txt.reference" compiler_output = "${test_build_directory}/indirect_first_arg_fail.output" ocaml_exit_status = "2" *** check-ocaml-output ** ocaml flags = "-args ${test_source_directory}/indirect_last_arg_fail.txt" -compiler_reference = "${test_source_directory}/indirect_last_arg_fail.txt.reference" +compiler_reference = + "${test_source_directory}/indirect_last_arg_fail.txt.reference" compiler_output = "${test_build_directory}/indirect_last_arg_fail.output" ocaml_exit_status = "2" *** check-ocaml-output diff --git a/testsuite/tests/tool-toplevel/error_highlighting.compilers.reference b/testsuite/tests/tool-toplevel/error_highlighting.compilers.reference new file mode 100644 index 00000000..d1e221ec --- /dev/null +++ b/testsuite/tests/tool-toplevel/error_highlighting.compilers.reference @@ -0,0 +1,68 @@ +Line 9, characters 8-15: +9 | let x = (1 + 2) +. 3. in ();; + ^^^^^^^ +Error: This expression has type int but an expression was expected of type + float +Line 2, characters 15-17: +2 | let x = (1 + 2 in ();; + ^^ +Error: Syntax error: ')' expected +Line 2, characters 8-9: +2 | let x = (1 + 2 in ();; + ^ + This '(' might be unmatched +Line 2, characters 14-16: +2 | let x = (1 + 2;; + ^^ +Error: Syntax error: ')' expected +Line 2, characters 8-9: +2 | let x = (1 + 2;; + ^ + This '(' might be unmatched +Line 3, characters 8-9: +3 | let y = 1 +. 2. in + ^ +Error: This expression has type int but an expression was expected of type + float +Line 4, characters 2-4: +4 | 2 in + ^^ +Error: Syntax error: ')' expected +Line 2, characters 8-9: +2 | let x = (1 + ^ + This '(' might be unmatched +Line 2, characters 8-17: +2 | ........(1 +3 | + +4 | 2)... +Error: This expression has type int but an expression was expected of type + float +File "error_highlighting_use1.ml", line 1, characters 8-15: +1 | let x = (1 + 2) +. 3. in ();; + ^^^^^^^ +Error: This expression has type int but an expression was expected of type + float +File "error_highlighting_use2.ml", line 1, characters 15-17: +1 | let x = (1 + 2 in ();; + ^^ +Error: Syntax error: ')' expected +File "error_highlighting_use2.ml", line 1, characters 8-9: +1 | let x = (1 + 2 in ();; + ^ + This '(' might be unmatched +File "error_highlighting_use3.ml", line 3, characters 2-4: +3 | 2 in + ^^ +Error: Syntax error: ')' expected +File "error_highlighting_use3.ml", line 1, characters 8-9: +1 | let x = (1 + ^ + This '(' might be unmatched +File "error_highlighting_use4.ml", line 1, characters 8-17: +1 | ........(1 +2 | + +3 | 2)... +Error: This expression has type int but an expression was expected of type + float + diff --git a/testsuite/tests/tool-toplevel/error_highlighting.ml b/testsuite/tests/tool-toplevel/error_highlighting.ml new file mode 100644 index 00000000..832b55da --- /dev/null +++ b/testsuite/tests/tool-toplevel/error_highlighting.ml @@ -0,0 +1,32 @@ +(* TEST + files = "error_highlighting_use1.ml \ + error_highlighting_use2.ml \ + error_highlighting_use3.ml \ + error_highlighting_use4.ml" + * toplevel +*) + +let x = (1 + 2) +. 3. in ();; + +let x = (1 + 2 in ();; + +let x = (1 + 2;; + +let x = 1 in +let y = 1 +. 2. in +();; + +let x = (1 + + +2 in +();; + +let x = (1 + + +2) +. +3. in ();; + +#use "error_highlighting_use1.ml";; +#use "error_highlighting_use2.ml";; +#use "error_highlighting_use3.ml";; +#use "error_highlighting_use4.ml";; diff --git a/testsuite/tests/tool-toplevel/error_highlighting_use1.ml b/testsuite/tests/tool-toplevel/error_highlighting_use1.ml new file mode 100644 index 00000000..87ac4416 --- /dev/null +++ b/testsuite/tests/tool-toplevel/error_highlighting_use1.ml @@ -0,0 +1 @@ +let x = (1 + 2) +. 3. in ();; diff --git a/testsuite/tests/tool-toplevel/error_highlighting_use2.ml b/testsuite/tests/tool-toplevel/error_highlighting_use2.ml new file mode 100644 index 00000000..295584f6 --- /dev/null +++ b/testsuite/tests/tool-toplevel/error_highlighting_use2.ml @@ -0,0 +1 @@ +let x = (1 + 2 in ();; diff --git a/testsuite/tests/tool-toplevel/error_highlighting_use3.ml b/testsuite/tests/tool-toplevel/error_highlighting_use3.ml new file mode 100644 index 00000000..04cb9a85 --- /dev/null +++ b/testsuite/tests/tool-toplevel/error_highlighting_use3.ml @@ -0,0 +1,4 @@ +let x = (1 + + +2 in +();; diff --git a/testsuite/tests/tool-toplevel/error_highlighting_use4.ml b/testsuite/tests/tool-toplevel/error_highlighting_use4.ml new file mode 100644 index 00000000..252dc7ee --- /dev/null +++ b/testsuite/tests/tool-toplevel/error_highlighting_use4.ml @@ -0,0 +1,4 @@ +let x = (1 + + +2) +. +3. in ();; diff --git a/testsuite/tests/tool-toplevel/exotic_lists.ml b/testsuite/tests/tool-toplevel/exotic_lists.ml index 1f068cd2..bb09823b 100644 --- a/testsuite/tests/tool-toplevel/exotic_lists.ml +++ b/testsuite/tests/tool-toplevel/exotic_lists.ml @@ -15,5 +15,3 @@ end;; L.[[1];[2];[3];[4];[5]];; open L;; [1;2;3;4;5];; - - diff --git a/testsuite/tests/tool-toplevel/ocamltests b/testsuite/tests/tool-toplevel/ocamltests index 81e8f0f0..28d1ff56 100644 --- a/testsuite/tests/tool-toplevel/ocamltests +++ b/testsuite/tests/tool-toplevel/ocamltests @@ -1,5 +1,7 @@ exotic_lists.ml +pr6468.ml pr7060.ml pr7751.ml strings.ml tracing.ml +error_highlighting.ml diff --git a/testsuite/tests/tool-toplevel/pr6468.compilers.reference b/testsuite/tests/tool-toplevel/pr6468.compilers.reference new file mode 100644 index 00000000..a63d008d --- /dev/null +++ b/testsuite/tests/tool-toplevel/pr6468.compilers.reference @@ -0,0 +1,12 @@ +- : unit = () +val f : unit -> 'a = +Line 1, characters 11-15: +1 | let g () = f (); 1;; + ^^^^ +Warning 21: this statement never returns (or has an unsound type.) +val g : unit -> int = +Exception: Not_found. +Raised at file "//toplevel//", line 2, characters 17-26 +Called from file "//toplevel//", line 1, characters 11-15 +Called from file "toplevel/toploop.ml", line 208, characters 17-27 + diff --git a/testsuite/tests/tool-toplevel/pr6468.ml b/testsuite/tests/tool-toplevel/pr6468.ml new file mode 100644 index 00000000..69680ccf --- /dev/null +++ b/testsuite/tests/tool-toplevel/pr6468.ml @@ -0,0 +1,10 @@ +(* TEST + * toplevel +*) + +(* Make the test reproducible regardless of whether OCAMLRUNPARAM=b or not *) +Printexc.record_backtrace true;; + +let f () = raise Not_found;; +let g () = f (); 1;; +g ();; diff --git a/testsuite/tests/tool-toplevel/pr7060.compilers.reference b/testsuite/tests/tool-toplevel/pr7060.compilers.reference index 6b142def..3538e007 100644 --- a/testsuite/tests/tool-toplevel/pr7060.compilers.reference +++ b/testsuite/tests/tool-toplevel/pr7060.compilers.reference @@ -1,15 +1,15 @@ type t = A | B type u = C of t -Characters 18-54: - let print_t out = function A -> Format.fprintf out "A";; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 18-54: +1 | let print_t out = function A -> Format.fprintf out "A";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: B val print_t : Format.formatter -> t -> unit = - : t = - + - : u = C - + diff --git a/testsuite/tests/tool-toplevel/pr7751.compilers.reference b/testsuite/tests/tool-toplevel/pr7751.compilers.reference index ec948bdc..5cdf1246 100644 --- a/testsuite/tests/tool-toplevel/pr7751.compilers.reference +++ b/testsuite/tests/tool-toplevel/pr7751.compilers.reference @@ -6,5 +6,5 @@ {Lexing.pos_fname = ""; pos_lnum = 1; pos_bol = 0; pos_cnum = 0}; loc_end = {Lexing.pos_fname = ""; pos_lnum = 1; pos_bol = 0; pos_cnum = 1}; loc_ghost = false}; - pexp_attributes = []} + pexp_loc_stack = []; pexp_attributes = []} diff --git a/testsuite/tests/tool-toplevel/strings.ml b/testsuite/tests/tool-toplevel/strings.ml index 07e86f42..baf29871 100644 --- a/testsuite/tests/tool-toplevel/strings.ml +++ b/testsuite/tests/tool-toplevel/strings.ml @@ -7,7 +7,8 @@ {|"\'|};; -" !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~";; +" !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`\ +abcdefghijklmnopqrstuvwxyz{|}~";; "\x00\x01\x02\x03\x04\x05\x06\x07\x0B\x0C\x0E\x0F\ \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\ diff --git a/testsuite/tests/translprim/array_spec.compilers.flat.reference b/testsuite/tests/translprim/array_spec.compilers.flat.reference new file mode 100644 index 00000000..5e5c558e --- /dev/null +++ b/testsuite/tests/translprim/array_spec.compilers.flat.reference @@ -0,0 +1,65 @@ +(setglobal Array_spec! + (let + (int_a = (makearray[int] 1 2 3) + float_a = (makearray[float] 1. 2. 3.) + addr_a = (makearray[addr] "a" "b" "c")) + (seq (array.length[int] int_a) (array.length[float] float_a) + (array.length[addr] addr_a) (function a : int (array.length[gen] a)) + (array.get[int] int_a 0) (array.get[float] float_a 0) + (array.get[addr] addr_a 0) (function a (array.get[gen] a 0)) + (array.unsafe_get[int] int_a 0) (array.unsafe_get[float] float_a 0) + (array.unsafe_get[addr] addr_a 0) + (function a (array.unsafe_get[gen] a 0)) (array.set[int] int_a 0 1) + (array.set[float] float_a 0 1.) (array.set[addr] addr_a 0 "a") + (function a x (array.set[gen] a 0 x)) (array.unsafe_set[int] int_a 0 1) + (array.unsafe_set[float] float_a 0 1.) + (array.unsafe_set[addr] addr_a 0 "a") + (function a x (array.unsafe_set[gen] a 0 x)) + (let + (eta_gen_len = (function prim stub (array.length[gen] prim)) + eta_gen_safe_get = + (function prim prim stub (array.get[gen] prim prim)) + eta_gen_unsafe_get = + (function prim prim stub (array.unsafe_get[gen] prim prim)) + eta_gen_safe_set = + (function prim prim prim stub (array.set[gen] prim prim prim)) + eta_gen_unsafe_set = + (function prim prim prim stub + (array.unsafe_set[gen] prim prim prim)) + eta_int_len = (function prim stub (array.length[int] prim)) + eta_int_safe_get = + (function prim prim stub (array.get[int] prim prim)) + eta_int_unsafe_get = + (function prim prim stub (array.unsafe_get[int] prim prim)) + eta_int_safe_set = + (function prim prim prim stub (array.set[int] prim prim prim)) + eta_int_unsafe_set = + (function prim prim prim stub + (array.unsafe_set[int] prim prim prim)) + eta_float_len = (function prim stub (array.length[float] prim)) + eta_float_safe_get = + (function prim prim stub (array.get[float] prim prim)) + eta_float_unsafe_get = + (function prim prim stub (array.unsafe_get[float] prim prim)) + eta_float_safe_set = + (function prim prim prim stub (array.set[float] prim prim prim)) + eta_float_unsafe_set = + (function prim prim prim stub + (array.unsafe_set[float] prim prim prim)) + eta_addr_len = (function prim stub (array.length[addr] prim)) + eta_addr_safe_get = + (function prim prim stub (array.get[addr] prim prim)) + eta_addr_unsafe_get = + (function prim prim stub (array.unsafe_get[addr] prim prim)) + eta_addr_safe_set = + (function prim prim prim stub (array.set[addr] prim prim prim)) + eta_addr_unsafe_set = + (function prim prim prim stub + (array.unsafe_set[addr] prim prim prim))) + (makeblock 0 int_a float_a addr_a eta_gen_len eta_gen_safe_get + eta_gen_unsafe_get eta_gen_safe_set eta_gen_unsafe_set eta_int_len + eta_int_safe_get eta_int_unsafe_get eta_int_safe_set + eta_int_unsafe_set eta_float_len eta_float_safe_get + eta_float_unsafe_get eta_float_safe_set eta_float_unsafe_set + eta_addr_len eta_addr_safe_get eta_addr_unsafe_get + eta_addr_safe_set eta_addr_unsafe_set))))) diff --git a/testsuite/tests/translprim/array_spec.compilers.no-flat.reference b/testsuite/tests/translprim/array_spec.compilers.no-flat.reference new file mode 100644 index 00000000..e839bbdb --- /dev/null +++ b/testsuite/tests/translprim/array_spec.compilers.no-flat.reference @@ -0,0 +1,65 @@ +(setglobal Array_spec! + (let + (int_a = (makearray[int] 1 2 3) + float_a = (makearray[addr] 1. 2. 3.) + addr_a = (makearray[addr] "a" "b" "c")) + (seq (array.length[int] int_a) (array.length[addr] float_a) + (array.length[addr] addr_a) (function a : int (array.length[addr] a)) + (array.get[int] int_a 0) (array.get[addr] float_a 0) + (array.get[addr] addr_a 0) (function a (array.get[addr] a 0)) + (array.unsafe_get[int] int_a 0) (array.unsafe_get[addr] float_a 0) + (array.unsafe_get[addr] addr_a 0) + (function a (array.unsafe_get[addr] a 0)) (array.set[int] int_a 0 1) + (array.set[addr] float_a 0 1.) (array.set[addr] addr_a 0 "a") + (function a x (array.set[addr] a 0 x)) + (array.unsafe_set[int] int_a 0 1) (array.unsafe_set[addr] float_a 0 1.) + (array.unsafe_set[addr] addr_a 0 "a") + (function a x (array.unsafe_set[addr] a 0 x)) + (let + (eta_gen_len = (function prim stub (array.length[addr] prim)) + eta_gen_safe_get = + (function prim prim stub (array.get[addr] prim prim)) + eta_gen_unsafe_get = + (function prim prim stub (array.unsafe_get[addr] prim prim)) + eta_gen_safe_set = + (function prim prim prim stub (array.set[addr] prim prim prim)) + eta_gen_unsafe_set = + (function prim prim prim stub + (array.unsafe_set[addr] prim prim prim)) + eta_int_len = (function prim stub (array.length[int] prim)) + eta_int_safe_get = + (function prim prim stub (array.get[int] prim prim)) + eta_int_unsafe_get = + (function prim prim stub (array.unsafe_get[int] prim prim)) + eta_int_safe_set = + (function prim prim prim stub (array.set[int] prim prim prim)) + eta_int_unsafe_set = + (function prim prim prim stub + (array.unsafe_set[int] prim prim prim)) + eta_float_len = (function prim stub (array.length[addr] prim)) + eta_float_safe_get = + (function prim prim stub (array.get[addr] prim prim)) + eta_float_unsafe_get = + (function prim prim stub (array.unsafe_get[addr] prim prim)) + eta_float_safe_set = + (function prim prim prim stub (array.set[addr] prim prim prim)) + eta_float_unsafe_set = + (function prim prim prim stub + (array.unsafe_set[addr] prim prim prim)) + eta_addr_len = (function prim stub (array.length[addr] prim)) + eta_addr_safe_get = + (function prim prim stub (array.get[addr] prim prim)) + eta_addr_unsafe_get = + (function prim prim stub (array.unsafe_get[addr] prim prim)) + eta_addr_safe_set = + (function prim prim prim stub (array.set[addr] prim prim prim)) + eta_addr_unsafe_set = + (function prim prim prim stub + (array.unsafe_set[addr] prim prim prim))) + (makeblock 0 int_a float_a addr_a eta_gen_len eta_gen_safe_get + eta_gen_unsafe_get eta_gen_safe_set eta_gen_unsafe_set eta_int_len + eta_int_safe_get eta_int_unsafe_get eta_int_safe_set + eta_int_unsafe_set eta_float_len eta_float_safe_get + eta_float_unsafe_get eta_float_safe_set eta_float_unsafe_set + eta_addr_len eta_addr_safe_get eta_addr_unsafe_get + eta_addr_safe_set eta_addr_unsafe_set))))) diff --git a/testsuite/tests/translprim/array_spec.compilers.reference.flat b/testsuite/tests/translprim/array_spec.compilers.reference.flat deleted file mode 100644 index c692c8a9..00000000 --- a/testsuite/tests/translprim/array_spec.compilers.reference.flat +++ /dev/null @@ -1,65 +0,0 @@ -(setglobal Array_spec! - (let - (int_a = (makearray[int] 1 2 3) - float_a = (makearray[float] 1. 2. 3.) - addr_a = (makearray[addr] "a" "b" "c")) - (seq (array.length[int] int_a) (array.length[float] float_a) - (array.length[addr] addr_a) (function a (array.length[gen] a)) - (array.get[int] int_a 0) (array.get[float] float_a 0) - (array.get[addr] addr_a 0) (function a (array.get[gen] a 0)) - (array.unsafe_get[int] int_a 0) (array.unsafe_get[float] float_a 0) - (array.unsafe_get[addr] addr_a 0) - (function a (array.unsafe_get[gen] a 0)) (array.set[int] int_a 0 1) - (array.set[float] float_a 0 1.) (array.set[addr] addr_a 0 "a") - (function a x (array.set[gen] a 0 x)) (array.unsafe_set[int] int_a 0 1) - (array.unsafe_set[float] float_a 0 1.) - (array.unsafe_set[addr] addr_a 0 "a") - (function a x (array.unsafe_set[gen] a 0 x)) - (let - (eta_gen_len = (function prim stub (array.length[gen] prim)) - eta_gen_safe_get = - (function prim prim stub (array.get[gen] prim prim)) - eta_gen_unsafe_get = - (function prim prim stub (array.unsafe_get[gen] prim prim)) - eta_gen_safe_set = - (function prim prim prim stub (array.set[gen] prim prim prim)) - eta_gen_unsafe_set = - (function prim prim prim stub - (array.unsafe_set[gen] prim prim prim)) - eta_int_len = (function prim stub (array.length[int] prim)) - eta_int_safe_get = - (function prim prim stub (array.get[int] prim prim)) - eta_int_unsafe_get = - (function prim prim stub (array.unsafe_get[int] prim prim)) - eta_int_safe_set = - (function prim prim prim stub (array.set[int] prim prim prim)) - eta_int_unsafe_set = - (function prim prim prim stub - (array.unsafe_set[int] prim prim prim)) - eta_float_len = (function prim stub (array.length[float] prim)) - eta_float_safe_get = - (function prim prim stub (array.get[float] prim prim)) - eta_float_unsafe_get = - (function prim prim stub (array.unsafe_get[float] prim prim)) - eta_float_safe_set = - (function prim prim prim stub (array.set[float] prim prim prim)) - eta_float_unsafe_set = - (function prim prim prim stub - (array.unsafe_set[float] prim prim prim)) - eta_addr_len = (function prim stub (array.length[addr] prim)) - eta_addr_safe_get = - (function prim prim stub (array.get[addr] prim prim)) - eta_addr_unsafe_get = - (function prim prim stub (array.unsafe_get[addr] prim prim)) - eta_addr_safe_set = - (function prim prim prim stub (array.set[addr] prim prim prim)) - eta_addr_unsafe_set = - (function prim prim prim stub - (array.unsafe_set[addr] prim prim prim))) - (makeblock 0 int_a float_a addr_a eta_gen_len eta_gen_safe_get - eta_gen_unsafe_get eta_gen_safe_set eta_gen_unsafe_set eta_int_len - eta_int_safe_get eta_int_unsafe_get eta_int_safe_set - eta_int_unsafe_set eta_float_len eta_float_safe_get - eta_float_unsafe_get eta_float_safe_set eta_float_unsafe_set - eta_addr_len eta_addr_safe_get eta_addr_unsafe_get - eta_addr_safe_set eta_addr_unsafe_set))))) diff --git a/testsuite/tests/translprim/array_spec.compilers.reference.no-flat b/testsuite/tests/translprim/array_spec.compilers.reference.no-flat deleted file mode 100644 index b6538050..00000000 --- a/testsuite/tests/translprim/array_spec.compilers.reference.no-flat +++ /dev/null @@ -1,65 +0,0 @@ -(setglobal Array_spec! - (let - (int_a = (makearray[int] 1 2 3) - float_a = (makearray[addr] 1. 2. 3.) - addr_a = (makearray[addr] "a" "b" "c")) - (seq (array.length[int] int_a) (array.length[addr] float_a) - (array.length[addr] addr_a) (function a (array.length[addr] a)) - (array.get[int] int_a 0) (array.get[addr] float_a 0) - (array.get[addr] addr_a 0) (function a (array.get[addr] a 0)) - (array.unsafe_get[int] int_a 0) (array.unsafe_get[addr] float_a 0) - (array.unsafe_get[addr] addr_a 0) - (function a (array.unsafe_get[addr] a 0)) (array.set[int] int_a 0 1) - (array.set[addr] float_a 0 1.) (array.set[addr] addr_a 0 "a") - (function a x (array.set[addr] a 0 x)) - (array.unsafe_set[int] int_a 0 1) (array.unsafe_set[addr] float_a 0 1.) - (array.unsafe_set[addr] addr_a 0 "a") - (function a x (array.unsafe_set[addr] a 0 x)) - (let - (eta_gen_len = (function prim stub (array.length[addr] prim)) - eta_gen_safe_get = - (function prim prim stub (array.get[addr] prim prim)) - eta_gen_unsafe_get = - (function prim prim stub (array.unsafe_get[addr] prim prim)) - eta_gen_safe_set = - (function prim prim prim stub (array.set[addr] prim prim prim)) - eta_gen_unsafe_set = - (function prim prim prim stub - (array.unsafe_set[addr] prim prim prim)) - eta_int_len = (function prim stub (array.length[int] prim)) - eta_int_safe_get = - (function prim prim stub (array.get[int] prim prim)) - eta_int_unsafe_get = - (function prim prim stub (array.unsafe_get[int] prim prim)) - eta_int_safe_set = - (function prim prim prim stub (array.set[int] prim prim prim)) - eta_int_unsafe_set = - (function prim prim prim stub - (array.unsafe_set[int] prim prim prim)) - eta_float_len = (function prim stub (array.length[addr] prim)) - eta_float_safe_get = - (function prim prim stub (array.get[addr] prim prim)) - eta_float_unsafe_get = - (function prim prim stub (array.unsafe_get[addr] prim prim)) - eta_float_safe_set = - (function prim prim prim stub (array.set[addr] prim prim prim)) - eta_float_unsafe_set = - (function prim prim prim stub - (array.unsafe_set[addr] prim prim prim)) - eta_addr_len = (function prim stub (array.length[addr] prim)) - eta_addr_safe_get = - (function prim prim stub (array.get[addr] prim prim)) - eta_addr_unsafe_get = - (function prim prim stub (array.unsafe_get[addr] prim prim)) - eta_addr_safe_set = - (function prim prim prim stub (array.set[addr] prim prim prim)) - eta_addr_unsafe_set = - (function prim prim prim stub - (array.unsafe_set[addr] prim prim prim))) - (makeblock 0 int_a float_a addr_a eta_gen_len eta_gen_safe_get - eta_gen_unsafe_get eta_gen_safe_set eta_gen_unsafe_set eta_int_len - eta_int_safe_get eta_int_unsafe_get eta_int_safe_set - eta_int_unsafe_set eta_float_len eta_float_safe_get - eta_float_unsafe_get eta_float_safe_set eta_float_unsafe_set - eta_addr_len eta_addr_safe_get eta_addr_unsafe_get - eta_addr_safe_set eta_addr_unsafe_set))))) diff --git a/testsuite/tests/translprim/array_spec.ml b/testsuite/tests/translprim/array_spec.ml index d84979d4..6d0c1e49 100644 --- a/testsuite/tests/translprim/array_spec.ml +++ b/testsuite/tests/translprim/array_spec.ml @@ -4,10 +4,12 @@ flags = "-dlambda -dno-unique-ids" *** flat-float-array **** check-ocamlc.byte-output - compiler_reference = "${test_source_directory}/array_spec.compilers.reference.flat" + compiler_reference = + "${test_source_directory}/array_spec.compilers.flat.reference" *** no-flat-float-array **** check-ocamlc.byte-output - compiler_reference = "${test_source_directory}/array_spec.compilers.reference.no-flat" + compiler_reference = + "${test_source_directory}/array_spec.compilers.no-flat.reference" *) external len : 'a array -> int = "%array_length" diff --git a/testsuite/tests/translprim/comparison_table.compilers.reference b/testsuite/tests/translprim/comparison_table.compilers.reference index b3c439fe..fdee1671 100644 --- a/testsuite/tests/translprim/comparison_table.compilers.reference +++ b/testsuite/tests/translprim/comparison_table.compilers.reference @@ -1,68 +1,70 @@ (setglobal Comparison_table! (let - (gen_cmp = (function x y (caml_compare x y)) - int_cmp = (function x y (caml_int_compare x y)) - bool_cmp = (function x y (caml_int_compare x y)) - intlike_cmp = (function x y (caml_int_compare x y)) - float_cmp = (function x y (caml_float_compare x y)) - string_cmp = (function x y (caml_string_compare x y)) - int32_cmp = (function x y (caml_int32_compare x y)) - int64_cmp = (function x y (caml_int64_compare x y)) - nativeint_cmp = (function x y (caml_nativeint_compare x y)) + (gen_cmp = (function x y : int (caml_compare x y)) + int_cmp = (function x[int] y[int] : int (caml_int_compare x y)) + bool_cmp = (function x y : int (caml_int_compare x y)) + intlike_cmp = (function x y : int (caml_int_compare x y)) + float_cmp = (function x[float] y[float] : int (caml_float_compare x y)) + string_cmp = (function x y : int (caml_string_compare x y)) + int32_cmp = (function x[int32] y[int32] : int (caml_int32_compare x y)) + int64_cmp = (function x[int64] y[int64] : int (caml_int64_compare x y)) + nativeint_cmp = + (function x[nativeint] y[nativeint] : int + (caml_nativeint_compare x y)) gen_eq = (function x y (caml_equal x y)) - int_eq = (function x y (== x y)) + int_eq = (function x[int] y[int] (== x y)) bool_eq = (function x y (== x y)) intlike_eq = (function x y (== x y)) - float_eq = (function x y (==. x y)) + float_eq = (function x[float] y[float] (==. x y)) string_eq = (function x y (caml_string_equal x y)) - int32_eq = (function x y (Int32.== x y)) - int64_eq = (function x y (Int64.== x y)) - nativeint_eq = (function x y (Nativeint.== x y)) + int32_eq = (function x[int32] y[int32] (Int32.== x y)) + int64_eq = (function x[int64] y[int64] (Int64.== x y)) + nativeint_eq = (function x[nativeint] y[nativeint] (Nativeint.== x y)) gen_ne = (function x y (caml_notequal x y)) - int_ne = (function x y (!= x y)) + int_ne = (function x[int] y[int] (!= x y)) bool_ne = (function x y (!= x y)) intlike_ne = (function x y (!= x y)) - float_ne = (function x y (!=. x y)) + float_ne = (function x[float] y[float] (!=. x y)) string_ne = (function x y (caml_string_notequal x y)) - int32_ne = (function x y (Int32.!= x y)) - int64_ne = (function x y (Int64.!= x y)) - nativeint_ne = (function x y (Nativeint.!= x y)) + int32_ne = (function x[int32] y[int32] (Int32.!= x y)) + int64_ne = (function x[int64] y[int64] (Int64.!= x y)) + nativeint_ne = (function x[nativeint] y[nativeint] (Nativeint.!= x y)) gen_lt = (function x y (caml_lessthan x y)) - int_lt = (function x y (< x y)) + int_lt = (function x[int] y[int] (< x y)) bool_lt = (function x y (< x y)) intlike_lt = (function x y (< x y)) - float_lt = (function x y (<. x y)) + float_lt = (function x[float] y[float] (<. x y)) string_lt = (function x y (caml_string_lessthan x y)) - int32_lt = (function x y (Int32.< x y)) - int64_lt = (function x y (Int64.< x y)) - nativeint_lt = (function x y (Nativeint.< x y)) + int32_lt = (function x[int32] y[int32] (Int32.< x y)) + int64_lt = (function x[int64] y[int64] (Int64.< x y)) + nativeint_lt = (function x[nativeint] y[nativeint] (Nativeint.< x y)) gen_gt = (function x y (caml_greaterthan x y)) - int_gt = (function x y (> x y)) + int_gt = (function x[int] y[int] (> x y)) bool_gt = (function x y (> x y)) intlike_gt = (function x y (> x y)) - float_gt = (function x y (>. x y)) + float_gt = (function x[float] y[float] (>. x y)) string_gt = (function x y (caml_string_greaterthan x y)) - int32_gt = (function x y (Int32.> x y)) - int64_gt = (function x y (Int64.> x y)) - nativeint_gt = (function x y (Nativeint.> x y)) + int32_gt = (function x[int32] y[int32] (Int32.> x y)) + int64_gt = (function x[int64] y[int64] (Int64.> x y)) + nativeint_gt = (function x[nativeint] y[nativeint] (Nativeint.> x y)) gen_le = (function x y (caml_lessequal x y)) - int_le = (function x y (<= x y)) + int_le = (function x[int] y[int] (<= x y)) bool_le = (function x y (<= x y)) intlike_le = (function x y (<= x y)) - float_le = (function x y (<=. x y)) + float_le = (function x[float] y[float] (<=. x y)) string_le = (function x y (caml_string_lessequal x y)) - int32_le = (function x y (Int32.<= x y)) - int64_le = (function x y (Int64.<= x y)) - nativeint_le = (function x y (Nativeint.<= x y)) + int32_le = (function x[int32] y[int32] (Int32.<= x y)) + int64_le = (function x[int64] y[int64] (Int64.<= x y)) + nativeint_le = (function x[nativeint] y[nativeint] (Nativeint.<= x y)) gen_ge = (function x y (caml_greaterequal x y)) - int_ge = (function x y (>= x y)) + int_ge = (function x[int] y[int] (>= x y)) bool_ge = (function x y (>= x y)) intlike_ge = (function x y (>= x y)) - float_ge = (function x y (>=. x y)) + float_ge = (function x[float] y[float] (>=. x y)) string_ge = (function x y (caml_string_greaterequal x y)) - int32_ge = (function x y (Int32.>= x y)) - int64_ge = (function x y (Int64.>= x y)) - nativeint_ge = (function x y (Nativeint.>= x y)) + int32_ge = (function x[int32] y[int32] (Int32.>= x y)) + int64_ge = (function x[int64] y[int64] (Int64.>= x y)) + nativeint_ge = (function x[nativeint] y[nativeint] (Nativeint.>= x y)) eta_gen_cmp = (function prim prim stub (caml_compare prim prim)) eta_int_cmp = (function prim prim stub (caml_int_compare prim prim)) eta_bool_cmp = (function prim prim stub (caml_int_compare prim prim)) diff --git a/testsuite/tests/translprim/locs.ml b/testsuite/tests/translprim/locs.ml index dbdcb733..78343cda 100644 --- a/testsuite/tests/translprim/locs.ml +++ b/testsuite/tests/translprim/locs.ml @@ -7,7 +7,7 @@ let print_file file = print_endline file let print_line line = - print_endline (string_of_int line) + print_endline (Int.to_string line) let print_module md = print_endline md diff --git a/testsuite/tests/translprim/module_coercion.compilers.flat.reference b/testsuite/tests/translprim/module_coercion.compilers.flat.reference new file mode 100644 index 00000000..3327f360 --- /dev/null +++ b/testsuite/tests/translprim/module_coercion.compilers.flat.reference @@ -0,0 +1,87 @@ +(setglobal Module_coercion! + (let (M = (module-defn(M) module_coercion.ml(15):436-1135 (makeblock 0))) + (makeblock 0 M + (module-defn(M_int) module_coercion.ml(46):1552-1591 + (makeblock 0 (function prim stub (array.length[int] prim)) + (function prim prim stub (array.get[int] prim prim)) + (function prim prim stub (array.unsafe_get[int] prim prim)) + (function prim prim prim stub (array.set[int] prim prim prim)) + (function prim prim prim stub + (array.unsafe_set[int] prim prim prim)) + (function prim prim stub (caml_int_compare prim prim)) + (function prim prim stub (== prim prim)) + (function prim prim stub (!= prim prim)) + (function prim prim stub (< prim prim)) + (function prim prim stub (> prim prim)) + (function prim prim stub (<= prim prim)) + (function prim prim stub (>= prim prim)))) + (module-defn(M_float) module_coercion.ml(47):1594-1637 + (makeblock 0 (function prim stub (array.length[float] prim)) + (function prim prim stub (array.get[float] prim prim)) + (function prim prim stub (array.unsafe_get[float] prim prim)) + (function prim prim prim stub (array.set[float] prim prim prim)) + (function prim prim prim stub + (array.unsafe_set[float] prim prim prim)) + (function prim prim stub (caml_float_compare prim prim)) + (function prim prim stub (==. prim prim)) + (function prim prim stub (!=. prim prim)) + (function prim prim stub (<. prim prim)) + (function prim prim stub (>. prim prim)) + (function prim prim stub (<=. prim prim)) + (function prim prim stub (>=. prim prim)))) + (module-defn(M_string) module_coercion.ml(48):1640-1685 + (makeblock 0 (function prim stub (array.length[addr] prim)) + (function prim prim stub (array.get[addr] prim prim)) + (function prim prim stub (array.unsafe_get[addr] prim prim)) + (function prim prim prim stub (array.set[addr] prim prim prim)) + (function prim prim prim stub + (array.unsafe_set[addr] prim prim prim)) + (function prim prim stub (caml_string_compare prim prim)) + (function prim prim stub (caml_string_equal prim prim)) + (function prim prim stub (caml_string_notequal prim prim)) + (function prim prim stub (caml_string_lessthan prim prim)) + (function prim prim stub (caml_string_greaterthan prim prim)) + (function prim prim stub (caml_string_lessequal prim prim)) + (function prim prim stub (caml_string_greaterequal prim prim)))) + (module-defn(M_int32) module_coercion.ml(49):1688-1731 + (makeblock 0 (function prim stub (array.length[addr] prim)) + (function prim prim stub (array.get[addr] prim prim)) + (function prim prim stub (array.unsafe_get[addr] prim prim)) + (function prim prim prim stub (array.set[addr] prim prim prim)) + (function prim prim prim stub + (array.unsafe_set[addr] prim prim prim)) + (function prim prim stub (caml_int32_compare prim prim)) + (function prim prim stub (Int32.== prim prim)) + (function prim prim stub (Int32.!= prim prim)) + (function prim prim stub (Int32.< prim prim)) + (function prim prim stub (Int32.> prim prim)) + (function prim prim stub (Int32.<= prim prim)) + (function prim prim stub (Int32.>= prim prim)))) + (module-defn(M_int64) module_coercion.ml(50):1734-1777 + (makeblock 0 (function prim stub (array.length[addr] prim)) + (function prim prim stub (array.get[addr] prim prim)) + (function prim prim stub (array.unsafe_get[addr] prim prim)) + (function prim prim prim stub (array.set[addr] prim prim prim)) + (function prim prim prim stub + (array.unsafe_set[addr] prim prim prim)) + (function prim prim stub (caml_int64_compare prim prim)) + (function prim prim stub (Int64.== prim prim)) + (function prim prim stub (Int64.!= prim prim)) + (function prim prim stub (Int64.< prim prim)) + (function prim prim stub (Int64.> prim prim)) + (function prim prim stub (Int64.<= prim prim)) + (function prim prim stub (Int64.>= prim prim)))) + (module-defn(M_nativeint) module_coercion.ml(51):1780-1831 + (makeblock 0 (function prim stub (array.length[addr] prim)) + (function prim prim stub (array.get[addr] prim prim)) + (function prim prim stub (array.unsafe_get[addr] prim prim)) + (function prim prim prim stub (array.set[addr] prim prim prim)) + (function prim prim prim stub + (array.unsafe_set[addr] prim prim prim)) + (function prim prim stub (caml_nativeint_compare prim prim)) + (function prim prim stub (Nativeint.== prim prim)) + (function prim prim stub (Nativeint.!= prim prim)) + (function prim prim stub (Nativeint.< prim prim)) + (function prim prim stub (Nativeint.> prim prim)) + (function prim prim stub (Nativeint.<= prim prim)) + (function prim prim stub (Nativeint.>= prim prim))))))) diff --git a/testsuite/tests/translprim/module_coercion.compilers.no-flat.reference b/testsuite/tests/translprim/module_coercion.compilers.no-flat.reference new file mode 100644 index 00000000..877e9df5 --- /dev/null +++ b/testsuite/tests/translprim/module_coercion.compilers.no-flat.reference @@ -0,0 +1,87 @@ +(setglobal Module_coercion! + (let (M = (module-defn(M) module_coercion.ml(15):436-1135 (makeblock 0))) + (makeblock 0 M + (module-defn(M_int) module_coercion.ml(46):1552-1591 + (makeblock 0 (function prim stub (array.length[int] prim)) + (function prim prim stub (array.get[int] prim prim)) + (function prim prim stub (array.unsafe_get[int] prim prim)) + (function prim prim prim stub (array.set[int] prim prim prim)) + (function prim prim prim stub + (array.unsafe_set[int] prim prim prim)) + (function prim prim stub (caml_int_compare prim prim)) + (function prim prim stub (== prim prim)) + (function prim prim stub (!= prim prim)) + (function prim prim stub (< prim prim)) + (function prim prim stub (> prim prim)) + (function prim prim stub (<= prim prim)) + (function prim prim stub (>= prim prim)))) + (module-defn(M_float) module_coercion.ml(47):1594-1637 + (makeblock 0 (function prim stub (array.length[addr] prim)) + (function prim prim stub (array.get[addr] prim prim)) + (function prim prim stub (array.unsafe_get[addr] prim prim)) + (function prim prim prim stub (array.set[addr] prim prim prim)) + (function prim prim prim stub + (array.unsafe_set[addr] prim prim prim)) + (function prim prim stub (caml_float_compare prim prim)) + (function prim prim stub (==. prim prim)) + (function prim prim stub (!=. prim prim)) + (function prim prim stub (<. prim prim)) + (function prim prim stub (>. prim prim)) + (function prim prim stub (<=. prim prim)) + (function prim prim stub (>=. prim prim)))) + (module-defn(M_string) module_coercion.ml(48):1640-1685 + (makeblock 0 (function prim stub (array.length[addr] prim)) + (function prim prim stub (array.get[addr] prim prim)) + (function prim prim stub (array.unsafe_get[addr] prim prim)) + (function prim prim prim stub (array.set[addr] prim prim prim)) + (function prim prim prim stub + (array.unsafe_set[addr] prim prim prim)) + (function prim prim stub (caml_string_compare prim prim)) + (function prim prim stub (caml_string_equal prim prim)) + (function prim prim stub (caml_string_notequal prim prim)) + (function prim prim stub (caml_string_lessthan prim prim)) + (function prim prim stub (caml_string_greaterthan prim prim)) + (function prim prim stub (caml_string_lessequal prim prim)) + (function prim prim stub (caml_string_greaterequal prim prim)))) + (module-defn(M_int32) module_coercion.ml(49):1688-1731 + (makeblock 0 (function prim stub (array.length[addr] prim)) + (function prim prim stub (array.get[addr] prim prim)) + (function prim prim stub (array.unsafe_get[addr] prim prim)) + (function prim prim prim stub (array.set[addr] prim prim prim)) + (function prim prim prim stub + (array.unsafe_set[addr] prim prim prim)) + (function prim prim stub (caml_int32_compare prim prim)) + (function prim prim stub (Int32.== prim prim)) + (function prim prim stub (Int32.!= prim prim)) + (function prim prim stub (Int32.< prim prim)) + (function prim prim stub (Int32.> prim prim)) + (function prim prim stub (Int32.<= prim prim)) + (function prim prim stub (Int32.>= prim prim)))) + (module-defn(M_int64) module_coercion.ml(50):1734-1777 + (makeblock 0 (function prim stub (array.length[addr] prim)) + (function prim prim stub (array.get[addr] prim prim)) + (function prim prim stub (array.unsafe_get[addr] prim prim)) + (function prim prim prim stub (array.set[addr] prim prim prim)) + (function prim prim prim stub + (array.unsafe_set[addr] prim prim prim)) + (function prim prim stub (caml_int64_compare prim prim)) + (function prim prim stub (Int64.== prim prim)) + (function prim prim stub (Int64.!= prim prim)) + (function prim prim stub (Int64.< prim prim)) + (function prim prim stub (Int64.> prim prim)) + (function prim prim stub (Int64.<= prim prim)) + (function prim prim stub (Int64.>= prim prim)))) + (module-defn(M_nativeint) module_coercion.ml(51):1780-1831 + (makeblock 0 (function prim stub (array.length[addr] prim)) + (function prim prim stub (array.get[addr] prim prim)) + (function prim prim stub (array.unsafe_get[addr] prim prim)) + (function prim prim prim stub (array.set[addr] prim prim prim)) + (function prim prim prim stub + (array.unsafe_set[addr] prim prim prim)) + (function prim prim stub (caml_nativeint_compare prim prim)) + (function prim prim stub (Nativeint.== prim prim)) + (function prim prim stub (Nativeint.!= prim prim)) + (function prim prim stub (Nativeint.< prim prim)) + (function prim prim stub (Nativeint.> prim prim)) + (function prim prim stub (Nativeint.<= prim prim)) + (function prim prim stub (Nativeint.>= prim prim))))))) diff --git a/testsuite/tests/translprim/module_coercion.compilers.reference.flat b/testsuite/tests/translprim/module_coercion.compilers.reference.flat deleted file mode 100644 index b70909ee..00000000 --- a/testsuite/tests/translprim/module_coercion.compilers.reference.flat +++ /dev/null @@ -1,87 +0,0 @@ -(setglobal Module_coercion! - (let (M = (module-defn(M) module_coercion.ml(13):417-1116 (makeblock 0))) - (makeblock 0 M - (module-defn(M_int) module_coercion.ml(44):1533-1572 - (makeblock 0 (function prim stub (array.length[int] prim)) - (function prim prim stub (array.get[int] prim prim)) - (function prim prim stub (array.unsafe_get[int] prim prim)) - (function prim prim prim stub (array.set[int] prim prim prim)) - (function prim prim prim stub - (array.unsafe_set[int] prim prim prim)) - (function prim prim stub (caml_int_compare prim prim)) - (function prim prim stub (== prim prim)) - (function prim prim stub (!= prim prim)) - (function prim prim stub (< prim prim)) - (function prim prim stub (> prim prim)) - (function prim prim stub (<= prim prim)) - (function prim prim stub (>= prim prim)))) - (module-defn(M_float) module_coercion.ml(45):1575-1618 - (makeblock 0 (function prim stub (array.length[float] prim)) - (function prim prim stub (array.get[float] prim prim)) - (function prim prim stub (array.unsafe_get[float] prim prim)) - (function prim prim prim stub (array.set[float] prim prim prim)) - (function prim prim prim stub - (array.unsafe_set[float] prim prim prim)) - (function prim prim stub (caml_float_compare prim prim)) - (function prim prim stub (==. prim prim)) - (function prim prim stub (!=. prim prim)) - (function prim prim stub (<. prim prim)) - (function prim prim stub (>. prim prim)) - (function prim prim stub (<=. prim prim)) - (function prim prim stub (>=. prim prim)))) - (module-defn(M_string) module_coercion.ml(46):1621-1666 - (makeblock 0 (function prim stub (array.length[addr] prim)) - (function prim prim stub (array.get[addr] prim prim)) - (function prim prim stub (array.unsafe_get[addr] prim prim)) - (function prim prim prim stub (array.set[addr] prim prim prim)) - (function prim prim prim stub - (array.unsafe_set[addr] prim prim prim)) - (function prim prim stub (caml_string_compare prim prim)) - (function prim prim stub (caml_string_equal prim prim)) - (function prim prim stub (caml_string_notequal prim prim)) - (function prim prim stub (caml_string_lessthan prim prim)) - (function prim prim stub (caml_string_greaterthan prim prim)) - (function prim prim stub (caml_string_lessequal prim prim)) - (function prim prim stub (caml_string_greaterequal prim prim)))) - (module-defn(M_int32) module_coercion.ml(47):1669-1712 - (makeblock 0 (function prim stub (array.length[addr] prim)) - (function prim prim stub (array.get[addr] prim prim)) - (function prim prim stub (array.unsafe_get[addr] prim prim)) - (function prim prim prim stub (array.set[addr] prim prim prim)) - (function prim prim prim stub - (array.unsafe_set[addr] prim prim prim)) - (function prim prim stub (caml_int32_compare prim prim)) - (function prim prim stub (Int32.== prim prim)) - (function prim prim stub (Int32.!= prim prim)) - (function prim prim stub (Int32.< prim prim)) - (function prim prim stub (Int32.> prim prim)) - (function prim prim stub (Int32.<= prim prim)) - (function prim prim stub (Int32.>= prim prim)))) - (module-defn(M_int64) module_coercion.ml(48):1715-1758 - (makeblock 0 (function prim stub (array.length[addr] prim)) - (function prim prim stub (array.get[addr] prim prim)) - (function prim prim stub (array.unsafe_get[addr] prim prim)) - (function prim prim prim stub (array.set[addr] prim prim prim)) - (function prim prim prim stub - (array.unsafe_set[addr] prim prim prim)) - (function prim prim stub (caml_int64_compare prim prim)) - (function prim prim stub (Int64.== prim prim)) - (function prim prim stub (Int64.!= prim prim)) - (function prim prim stub (Int64.< prim prim)) - (function prim prim stub (Int64.> prim prim)) - (function prim prim stub (Int64.<= prim prim)) - (function prim prim stub (Int64.>= prim prim)))) - (module-defn(M_nativeint) module_coercion.ml(49):1761-1812 - (makeblock 0 (function prim stub (array.length[addr] prim)) - (function prim prim stub (array.get[addr] prim prim)) - (function prim prim stub (array.unsafe_get[addr] prim prim)) - (function prim prim prim stub (array.set[addr] prim prim prim)) - (function prim prim prim stub - (array.unsafe_set[addr] prim prim prim)) - (function prim prim stub (caml_nativeint_compare prim prim)) - (function prim prim stub (Nativeint.== prim prim)) - (function prim prim stub (Nativeint.!= prim prim)) - (function prim prim stub (Nativeint.< prim prim)) - (function prim prim stub (Nativeint.> prim prim)) - (function prim prim stub (Nativeint.<= prim prim)) - (function prim prim stub (Nativeint.>= prim prim))))))) diff --git a/testsuite/tests/translprim/module_coercion.compilers.reference.no-flat b/testsuite/tests/translprim/module_coercion.compilers.reference.no-flat deleted file mode 100644 index 3a9503ee..00000000 --- a/testsuite/tests/translprim/module_coercion.compilers.reference.no-flat +++ /dev/null @@ -1,87 +0,0 @@ -(setglobal Module_coercion! - (let (M = (module-defn(M) module_coercion.ml(13):417-1116 (makeblock 0))) - (makeblock 0 M - (module-defn(M_int) module_coercion.ml(44):1533-1572 - (makeblock 0 (function prim stub (array.length[int] prim)) - (function prim prim stub (array.get[int] prim prim)) - (function prim prim stub (array.unsafe_get[int] prim prim)) - (function prim prim prim stub (array.set[int] prim prim prim)) - (function prim prim prim stub - (array.unsafe_set[int] prim prim prim)) - (function prim prim stub (caml_int_compare prim prim)) - (function prim prim stub (== prim prim)) - (function prim prim stub (!= prim prim)) - (function prim prim stub (< prim prim)) - (function prim prim stub (> prim prim)) - (function prim prim stub (<= prim prim)) - (function prim prim stub (>= prim prim)))) - (module-defn(M_float) module_coercion.ml(45):1575-1618 - (makeblock 0 (function prim stub (array.length[addr] prim)) - (function prim prim stub (array.get[addr] prim prim)) - (function prim prim stub (array.unsafe_get[addr] prim prim)) - (function prim prim prim stub (array.set[addr] prim prim prim)) - (function prim prim prim stub - (array.unsafe_set[addr] prim prim prim)) - (function prim prim stub (caml_float_compare prim prim)) - (function prim prim stub (==. prim prim)) - (function prim prim stub (!=. prim prim)) - (function prim prim stub (<. prim prim)) - (function prim prim stub (>. prim prim)) - (function prim prim stub (<=. prim prim)) - (function prim prim stub (>=. prim prim)))) - (module-defn(M_string) module_coercion.ml(46):1621-1666 - (makeblock 0 (function prim stub (array.length[addr] prim)) - (function prim prim stub (array.get[addr] prim prim)) - (function prim prim stub (array.unsafe_get[addr] prim prim)) - (function prim prim prim stub (array.set[addr] prim prim prim)) - (function prim prim prim stub - (array.unsafe_set[addr] prim prim prim)) - (function prim prim stub (caml_string_compare prim prim)) - (function prim prim stub (caml_string_equal prim prim)) - (function prim prim stub (caml_string_notequal prim prim)) - (function prim prim stub (caml_string_lessthan prim prim)) - (function prim prim stub (caml_string_greaterthan prim prim)) - (function prim prim stub (caml_string_lessequal prim prim)) - (function prim prim stub (caml_string_greaterequal prim prim)))) - (module-defn(M_int32) module_coercion.ml(47):1669-1712 - (makeblock 0 (function prim stub (array.length[addr] prim)) - (function prim prim stub (array.get[addr] prim prim)) - (function prim prim stub (array.unsafe_get[addr] prim prim)) - (function prim prim prim stub (array.set[addr] prim prim prim)) - (function prim prim prim stub - (array.unsafe_set[addr] prim prim prim)) - (function prim prim stub (caml_int32_compare prim prim)) - (function prim prim stub (Int32.== prim prim)) - (function prim prim stub (Int32.!= prim prim)) - (function prim prim stub (Int32.< prim prim)) - (function prim prim stub (Int32.> prim prim)) - (function prim prim stub (Int32.<= prim prim)) - (function prim prim stub (Int32.>= prim prim)))) - (module-defn(M_int64) module_coercion.ml(48):1715-1758 - (makeblock 0 (function prim stub (array.length[addr] prim)) - (function prim prim stub (array.get[addr] prim prim)) - (function prim prim stub (array.unsafe_get[addr] prim prim)) - (function prim prim prim stub (array.set[addr] prim prim prim)) - (function prim prim prim stub - (array.unsafe_set[addr] prim prim prim)) - (function prim prim stub (caml_int64_compare prim prim)) - (function prim prim stub (Int64.== prim prim)) - (function prim prim stub (Int64.!= prim prim)) - (function prim prim stub (Int64.< prim prim)) - (function prim prim stub (Int64.> prim prim)) - (function prim prim stub (Int64.<= prim prim)) - (function prim prim stub (Int64.>= prim prim)))) - (module-defn(M_nativeint) module_coercion.ml(49):1761-1812 - (makeblock 0 (function prim stub (array.length[addr] prim)) - (function prim prim stub (array.get[addr] prim prim)) - (function prim prim stub (array.unsafe_get[addr] prim prim)) - (function prim prim prim stub (array.set[addr] prim prim prim)) - (function prim prim prim stub - (array.unsafe_set[addr] prim prim prim)) - (function prim prim stub (caml_nativeint_compare prim prim)) - (function prim prim stub (Nativeint.== prim prim)) - (function prim prim stub (Nativeint.!= prim prim)) - (function prim prim stub (Nativeint.< prim prim)) - (function prim prim stub (Nativeint.> prim prim)) - (function prim prim stub (Nativeint.<= prim prim)) - (function prim prim stub (Nativeint.>= prim prim))))))) diff --git a/testsuite/tests/translprim/module_coercion.ml b/testsuite/tests/translprim/module_coercion.ml index 86f2ae95..a6d334c8 100644 --- a/testsuite/tests/translprim/module_coercion.ml +++ b/testsuite/tests/translprim/module_coercion.ml @@ -4,10 +4,12 @@ flags = "-dlambda -dno-unique-ids" *** flat-float-array **** check-ocamlc.byte-output - compiler_reference = "${test_source_directory}/module_coercion.compilers.reference.flat" + compiler_reference = + "${test_source_directory}/module_coercion.compilers.flat.reference" *** no-flat-float-array **** check-ocamlc.byte-output - compiler_reference = "${test_source_directory}/module_coercion.compilers.reference.no-flat" + compiler_reference = + "${test_source_directory}/module_coercion.compilers.no-flat.reference" *) module M = struct diff --git a/testsuite/tests/typing-core-bugs/missing_rec_hint.ml b/testsuite/tests/typing-core-bugs/missing_rec_hint.ml new file mode 100644 index 00000000..f3e62e2b --- /dev/null +++ b/testsuite/tests/typing-core-bugs/missing_rec_hint.ml @@ -0,0 +1,67 @@ +(* TEST + * expect +*) + +let facto n = (* missing [rec] *) + if n = 0 then 1 else n * facto (n-1) + +[%%expect{| +Line 2, characters 28-33: +2 | if n = 0 then 1 else n * facto (n-1) + ^^^^^ +Error: Unbound value facto +Hint: If this is a recursive definition, +you should add the 'rec' keyword on line 1 +|}];; + +let x = 3 in +let f x = f x in +() + +[%%expect{| +Line 2, characters 10-11: +2 | let f x = f x in + ^ +Error: Unbound value f +Hint: If this is a recursive definition, +you should add the 'rec' keyword on line 2 +|}];; + +let f x = if x < 0 then x else h (x-1) +and g x = if x < 0 then x else f (x-1) +and h x = if x < 0 then x else g (x-1) + +[%%expect{| +Line 1, characters 31-32: +1 | let f x = if x < 0 then x else h (x-1) + ^ +Error: Unbound value h +Hint: If this is a recursive definition, +you should add the 'rec' keyword on line 1 +|}];; + +let value1 = 3 in +let value2 = value2 (* typo: should be value1 *) + 1 in +() + +[%%expect{| +Line 2, characters 13-19: +2 | let value2 = value2 (* typo: should be value1 *) + 1 in + ^^^^^^ +Error: Unbound value value2 +Hint: Did you mean value1? +|}];; + +let foobar1 () = () in +let foobar2 () = foobar2 () (* typo? or missing "rec"? *) in +() + +[%%expect{| +Line 2, characters 17-24: +2 | let foobar2 () = foobar2 () (* typo? or missing "rec"? *) in + ^^^^^^^ +Error: Unbound value foobar2 +Hint: Did you mean foobar1? +Hint: If this is a recursive definition, +you should add the 'rec' keyword on line 2 +|}];; diff --git a/testsuite/tests/typing-core-bugs/ocamltests b/testsuite/tests/typing-core-bugs/ocamltests index 498d4c3d..089ea717 100644 --- a/testsuite/tests/typing-core-bugs/ocamltests +++ b/testsuite/tests/typing-core-bugs/ocamltests @@ -1,2 +1,4 @@ +missing_rec_hint.ml unit_fun_hints.ml type_expected_explanation.ml +repeated_did_you_mean.ml diff --git a/testsuite/tests/typing-core-bugs/repeated_did_you_mean.ml b/testsuite/tests/typing-core-bugs/repeated_did_you_mean.ml new file mode 100755 index 00000000..3c187fa4 --- /dev/null +++ b/testsuite/tests/typing-core-bugs/repeated_did_you_mean.ml @@ -0,0 +1,22 @@ +(* TEST + * expect +*) + +(* MPR 7864 *) + +let foo = 12 +module M = struct + let foo = 13 +end +open M + +let _ = fox;; +[%%expect{| +val foo : int = 12 +module M : sig val foo : int end +Line 7, characters 8-11: +7 | let _ = fox;; + ^^^ +Error: Unbound value fox +Hint: Did you mean foo? +|}] diff --git a/testsuite/tests/typing-core-bugs/type_expected_explanation.ml b/testsuite/tests/typing-core-bugs/type_expected_explanation.ml index 97143f90..e01aa267 100644 --- a/testsuite/tests/typing-core-bugs/type_expected_explanation.ml +++ b/testsuite/tests/typing-core-bugs/type_expected_explanation.ml @@ -6,9 +6,9 @@ if 3 then ();; [%%expect{| -Line _, characters 3-4: - if 3 then ();; - ^ +Line 1, characters 3-4: +1 | if 3 then ();; + ^ Error: This expression has type int but an expression was expected of type bool because it is in the condition of an if-statement @@ -17,9 +17,9 @@ Error: This expression has type int but an expression was expected of type fun b -> if true then (print_int b) else (if b then ());; [%%expect{| -Line _, characters 45-46: - fun b -> if true then (print_int b) else (if b then ());; - ^ +Line 1, characters 45-46: +1 | fun b -> if true then (print_int b) else (if b then ());; + ^ Error: This expression has type int but an expression was expected of type bool because it is in the condition of an if-statement @@ -30,9 +30,9 @@ Error: This expression has type int but an expression was expected of type fun b -> if true then (if b then ()) else (print_int b);; [%%expect{| -Line _, characters 53-54: - fun b -> if true then (if b then ()) else (print_int b);; - ^ +Line 1, characters 53-54: +1 | fun b -> if true then (if b then ()) else (print_int b);; + ^ Error: This expression has type bool but an expression was expected of type int |}];; @@ -40,9 +40,9 @@ Error: This expression has type bool but an expression was expected of type if (let x = 3 in x) then ();; [%%expect{| -Line _, characters 17-18: - if (let x = 3 in x) then ();; - ^ +Line 1, characters 17-18: +1 | if (let x = 3 in x) then ();; + ^ Error: This expression has type int but an expression was expected of type bool because it is in the condition of an if-statement @@ -51,9 +51,9 @@ Error: This expression has type int but an expression was expected of type if (if true then 3 else 4) then ();; [%%expect{| -Line _, characters 17-18: - if (if true then 3 else 4) then ();; - ^ +Line 1, characters 17-18: +1 | if (if true then 3 else 4) then ();; + ^ Error: This expression has type int but an expression was expected of type bool because it is in the condition of an if-statement @@ -62,9 +62,9 @@ Error: This expression has type int but an expression was expected of type if true then 3;; [%%expect{| -Line _, characters 13-14: - if true then 3;; - ^ +Line 1, characters 13-14: +1 | if true then 3;; + ^ Error: This expression has type int but an expression was expected of type unit because it is in the result of a conditional with no else branch @@ -73,20 +73,19 @@ Error: This expression has type int but an expression was expected of type if (fun x -> x) then ();; [%%expect{| -Line _, characters 3-15: - if (fun x -> x) then ();; - ^^^^^^^^^^^^ +Line 1, characters 3-15: +1 | if (fun x -> x) then ();; + ^^^^^^^^^^^^ Error: This expression should not be a function, the expected type is -bool -because it is in the condition of an if-statement + bool because it is in the condition of an if-statement |}];; while 42 do () done;; [%%expect{| -Line _, characters 6-8: - while 42 do () done;; - ^^ +Line 1, characters 6-8: +1 | while 42 do () done;; + ^^ Error: This expression has type int but an expression was expected of type bool because it is in the condition of a while-loop @@ -97,9 +96,9 @@ Error: This expression has type int but an expression was expected of type while true do (if true then 3 else 4) done;; [%%expect{| -Line _, characters 14-37: - while true do (if true then 3 else 4) done;; - ^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 14-37: +1 | while true do (if true then 3 else 4) done;; + ^^^^^^^^^^^^^^^^^^^^^^^ Error: This expression has type int but an expression was expected of type unit because it is in the body of a while-loop @@ -108,9 +107,9 @@ Error: This expression has type int but an expression was expected of type for i = 3. to 4 do () done;; [%%expect{| -Line _, characters 8-10: - for i = 3. to 4 do () done;; - ^^ +Line 1, characters 8-10: +1 | for i = 3. to 4 do () done;; + ^^ Error: This expression has type float but an expression was expected of type int because it is in a for-loop start index @@ -119,9 +118,9 @@ Error: This expression has type float but an expression was expected of type for i = 3 to 4. do () done;; [%%expect{| -Line _, characters 13-15: - for i = 3 to 4. do () done;; - ^^ +Line 1, characters 13-15: +1 | for i = 3 to 4. do () done;; + ^^ Error: This expression has type float but an expression was expected of type int because it is in a for-loop stop index @@ -132,9 +131,9 @@ Error: This expression has type float but an expression was expected of type for i = 0 to 0 do (if true then 3 else 4) done;; [%%expect{| -Line _, characters 18-41: - for i = 0 to 0 do (if true then 3 else 4) done;; - ^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 18-41: +1 | for i = 0 to 0 do (if true then 3 else 4) done;; + ^^^^^^^^^^^^^^^^^^^^^^^ Error: This expression has type int but an expression was expected of type unit because it is in the body of a for-loop @@ -143,9 +142,9 @@ Error: This expression has type int but an expression was expected of type assert 12;; [%%expect{| -Line _, characters 7-9: - assert 12;; - ^^ +Line 1, characters 7-9: +1 | assert 12;; + ^^ Error: This expression has type int but an expression was expected of type bool because it is in the condition of an assertion @@ -155,9 +154,9 @@ Error: This expression has type int but an expression was expected of type (let x = 3 in x+1); ();; [%%expect{| -Line _, characters 0-18: - (let x = 3 in x+1); ();; - ^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-18: +1 | (let x = 3 in x+1); ();; + ^^^^^^^^^^^^^^^^^^ Error: This expression has type int but an expression was expected of type unit because it is in the left-hand side of a sequence @@ -168,10 +167,23 @@ let ordered_list_with x y = else if x > y then [y;x] [%%expect{| -Line _, characters 22-26: - else if x > y then [y;x] - ^^^^ +Line 3, characters 22-26: +3 | else if x > y then [y;x] + ^^^^ Error: This variant expression is expected to have type unit because it is in the result of a conditional with no else branch The constructor :: does not belong to type unit |}];; + +(function + | y when y + 1 -> () + | _ -> ());; + +[%%expect{| +Line 2, characters 11-16: +2 | | y when y + 1 -> () + ^^^^^ +Error: This expression has type int but an expression was expected of type + bool + because it is in a when-guard +|}];; diff --git a/testsuite/tests/typing-core-bugs/unit_fun_hints.ml b/testsuite/tests/typing-core-bugs/unit_fun_hints.ml index ae7135d3..73b4ad22 100644 --- a/testsuite/tests/typing-core-bugs/unit_fun_hints.ml +++ b/testsuite/tests/typing-core-bugs/unit_fun_hints.ml @@ -8,9 +8,9 @@ let _ = g 3;; (* missing `fun () ->' *) [%%expect{| val g : (unit -> 'a) -> 'a = -Line _, characters 10-11: - let _ = g 3;; (* missing `fun () ->' *) - ^ +Line 2, characters 10-11: +2 | let _ = g 3;; (* missing `fun () ->' *) + ^ Error: This expression has type int but an expression was expected of type unit -> 'a Hint: Did you forget to wrap the expression using `fun () ->'? @@ -25,9 +25,9 @@ let _ = (* We use -strict-sequence for this test: otherwise only a warning is produced about print_newline not being of type unit *) [%%expect{| -Line _, characters 3-16: - print_newline; (* missing unit argument *) - ^^^^^^^^^^^^^ +Line 3, characters 3-16: +3 | print_newline; (* missing unit argument *) + ^^^^^^^^^^^^^ Error: This expression has type unit -> unit but an expression was expected of type unit because it is in the left-hand side of a sequence @@ -38,9 +38,9 @@ let x = read_int in (* missing unit argument *) print_int x;; [%%expect{| -Line _, characters 10-11: - print_int x;; - ^ +Line 2, characters 10-11: +2 | print_int x;; + ^ Error: This expression has type unit -> int but an expression was expected of type int Hint: Did you forget to provide `()' as argument? @@ -51,9 +51,9 @@ let g f = f = 3;; [%%expect{| -Line _, characters 6-7: - f = 3;; - ^ +Line 3, characters 6-7: +3 | f = 3;; + ^ Error: This expression has type int but an expression was expected of type unit -> 'a Hint: Did you forget to wrap the expression using `fun () ->'? @@ -64,9 +64,9 @@ let g f = 3 = f;; [%%expect{| -Line _, characters 6-7: - 3 = f;; - ^ +Line 3, characters 6-7: +3 | 3 = f;; + ^ Error: This expression has type unit -> 'a but an expression was expected of type int Hint: Did you forget to provide `()' as argument? diff --git a/testsuite/tests/typing-deprecated/alerts.ml b/testsuite/tests/typing-deprecated/alerts.ml new file mode 100755 index 00000000..016ccf55 --- /dev/null +++ b/testsuite/tests/typing-deprecated/alerts.ml @@ -0,0 +1,273 @@ +(* TEST + * expect +*) + + +(* Enable all alerts as errors, except foo (soft) and bar (disabled) *) +[@@@ocaml.alert "@all--foo-bar"];; + +module X : sig + val x: int [@@alert foo "Foo!"] + val y: int [@@alert bar "Bar!"] + val z: int [@@alert baz "Baz!"] + val t: int [@@alert foo "FOO"] [@@alert bar "BAR"] [@@alert baz "BAZ"] +end = struct + let x, y, z, t = 0, 0, 0, 0 +end +[%%expect{| +module X : sig val x : int val y : int val z : int val t : int end +|}] + +let _ = X.x;; +[%%expect{| +Line 1, characters 8-11: +1 | let _ = X.x;; + ^^^ +Alert foo: X.x +Foo! +- : int = 0 +|}] + +let _ = X.y;; +[%%expect{| +- : int = 0 +|}] + +let _ = X.z;; +[%%expect{| +Line 1, characters 8-11: +1 | let _ = X.z;; + ^^^ +Error (alert baz): X.z +Baz! +|}] + +let _ = X.t;; +[%%expect{| +Line 1, characters 8-11: +1 | let _ = X.t;; + ^^^ +Error (alert baz): X.t +BAZ +Line 1, characters 8-11: +1 | let _ = X.t;; + ^^^ +Alert foo: X.t +FOO +|}] + + +module Z1 : sig + val x: int [@@alert foo "Foo!"] [@@alert foo2 "Foo2"] + val y: int [@@alert bar "Bar!"] + val z: int [@@alert baz "Baz!"] + val t: int [@@alert foo "FOO"] [@@alert bar "BAR"] [@@alert baz "BAZ"] +end = X;; +[%%expect{| +module Z1 : sig val x : int val y : int val z : int val t : int end +|}] + +module Z2 : sig + val x: int + val y: int + val z: int + val t: int +end = X;; +[%%expect{| +Line 6, characters 6-7: +6 | end = X;; + ^ +Alert foo: x +Foo! +Line 4, characters 2-33: +4 | val x: int [@@alert foo "Foo!"] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Definition +Line 2, characters 2-12: +2 | val x: int + ^^^^^^^^^^ + Expected signature +Line 6, characters 6-7: +6 | end = X;; + ^ +Error (alert baz): z +Baz! +Line 6, characters 2-33: +6 | val z: int [@@alert baz "Baz!"] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Definition +Line 4, characters 2-12: +4 | val z: int + ^^^^^^^^^^ + Expected signature +Line 6, characters 6-7: +6 | end = X;; + ^ +Error (alert baz): t +BAZ +Line 7, characters 2-72: +7 | val t: int [@@alert foo "FOO"] [@@alert bar "BAR"] [@@alert baz "BAZ"] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Definition +Line 5, characters 2-12: +5 | val t: int + ^^^^^^^^^^ + Expected signature +Line 6, characters 6-7: +6 | end = X;; + ^ +Alert foo: t +FOO +Line 7, characters 2-72: +7 | val t: int [@@alert foo "FOO"] [@@alert bar "BAR"] [@@alert baz "BAZ"] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Definition +Line 5, characters 2-12: +5 | val t: int + ^^^^^^^^^^ + Expected signature +|}] + +(* Turn all alerts into soft mode *) +[@@@ocaml.alert "--all"];; + +module Z3 : sig + val x: int + val y: int + val z: int + val t: int +end = X;; +[%%expect{| +Line 8, characters 6-7: +8 | end = X;; + ^ +Alert foo: x +Foo! +Line 4, characters 2-33: +4 | val x: int [@@alert foo "Foo!"] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Definition +Line 4, characters 2-12: +4 | val x: int + ^^^^^^^^^^ + Expected signature +Line 8, characters 6-7: +8 | end = X;; + ^ +Alert baz: z +Baz! +Line 6, characters 2-33: +6 | val z: int [@@alert baz "Baz!"] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Definition +Line 6, characters 2-12: +6 | val z: int + ^^^^^^^^^^ + Expected signature +Line 8, characters 6-7: +8 | end = X;; + ^ +Alert baz: t +BAZ +Line 7, characters 2-72: +7 | val t: int [@@alert foo "FOO"] [@@alert bar "BAR"] [@@alert baz "BAZ"] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Definition +Line 7, characters 2-12: +7 | val t: int + ^^^^^^^^^^ + Expected signature +Line 8, characters 6-7: +8 | end = X;; + ^ +Alert foo: t +FOO +Line 7, characters 2-72: +7 | val t: int [@@alert foo "FOO"] [@@alert bar "BAR"] [@@alert baz "BAZ"] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Definition +Line 7, characters 2-12: +7 | val t: int + ^^^^^^^^^^ + Expected signature +module Z3 : sig val x : int val y : int val z : int val t : int end +|}] + + +(* Disable all alerts *) +[@@@ocaml.alert "-all"];; + +module Z4 : sig + val x: int + val y: int + val z: int + val t: int +end = X;; +[%%expect{| +module Z4 : sig val x : int val y : int val z : int val t : int end +|}] + + +(* Multiple alert messages of the same kind *) +[@@@ocaml.alert "+all--all"] +module X : sig + val x: int [@@alert bla "X1"] [@@alert bla "X2"] [@@alert bla "X3"] + val y: int [@@alert bla "X1"] [@@alert bla] [@@alert bla "X3"] + val z: int [@@alert bla] [@@alert bla] [@@alert bla] +end = struct + let x, y, z = 0, 0, 0 +end;; +let _ = X.x +let _ = X.y +let _ = X.z +[%%expect{| +module X : sig val x : int val y : int val z : int end +Line 9, characters 8-11: +9 | let _ = X.x + ^^^ +Alert bla: X.x +X1 +X2 +X3 +- : int = 0 +Line 10, characters 8-11: +10 | let _ = X.y + ^^^ +Alert bla: X.y +X1 +X3 +- : int = 0 +Line 11, characters 8-11: +11 | let _ = X.z + ^^^ +Alert bla: X.z +- : int = 0 +|}] + + +(* Invalid paylods *) +module X : sig + val x: int [@@alert 42] + val y: int [@@alert bla 42] + val z: int [@@alert "bla"] +end = struct + let x, y, z = 0, 0, 0 +end +[%%expect{| +Line 2, characters 13-25: +2 | val x: int [@@alert 42] + ^^^^^^^^^^^^ +Warning 47: illegal payload for attribute 'alert'. +Invalid payload +Line 3, characters 13-29: +3 | val y: int [@@alert bla 42] + ^^^^^^^^^^^^^^^^ +Warning 47: illegal payload for attribute 'alert'. +Invalid payload +Line 4, characters 13-28: +4 | val z: int [@@alert "bla"] + ^^^^^^^^^^^^^^^ +Warning 47: illegal payload for attribute 'alert'. +Ill-formed list of alert settings +module X : sig val x : int val y : int val z : int end +|}] diff --git a/testsuite/tests/typing-deprecated/deprecated.ml b/testsuite/tests/typing-deprecated/deprecated.ml index 902483d7..18adcb99 100644 --- a/testsuite/tests/typing-deprecated/deprecated.ml +++ b/testsuite/tests/typing-deprecated/deprecated.ml @@ -16,46 +16,93 @@ end = struct let x = 0 end;; [%%expect{| -Line _, characters 9-10: - val x: t [@@ocaml.deprecated] - ^ -Warning 3: deprecated: t +Line 7, characters 9-10: +7 | val x: t [@@ocaml.deprecated] + ^ +Alert deprecated: t module X : sig type t type s type u val x : t end |}] type t = X.t ;; [%%expect{| -Line _, characters 9-12: - type t = X.t - ^^^ -Warning 3: deprecated: X.t +Line 1, characters 9-12: +1 | type t = X.t + ^^^ +Alert deprecated: X.t type t = X.t |}] let x = X.x ;; [%%expect{| -Line _, characters 8-11: - let x = X.x - ^^^ -Warning 3: deprecated: X.x +Line 1, characters 8-11: +1 | let x = X.x + ^^^ +Alert deprecated: X.x val x : X.t = |}] +(* Patterns *) + +let (_, foo [@deprecated], _) = 1, (), 3 +;; +foo;; +[%%expect{| +val foo : unit = () +Line 3, characters 0-3: +3 | foo;; + ^^^ +Alert deprecated: foo +- : unit = () +|}] + +let (_, foo, bar) [@deprecated] = 1, (), 3 +;; +foo;; +[%%expect{| +val foo : unit = () +val bar : int = 3 +- : unit = () +|}] + +let f = function + | bar, cho [@deprecated], _ -> cho + 1 +;; +[%%expect{| +Line 2, characters 33-36: +2 | | bar, cho [@deprecated], _ -> cho + 1 + ^^^ +Alert deprecated: cho +val f : 'a * int * 'b -> int = +|}] + +class c (_, (foo [@deprecated] : int)) = + object + val h = foo + end +;; +[%%expect{| +Line 3, characters 12-15: +3 | val h = foo + ^^^ +Alert deprecated: foo +class c : 'a * int -> object val h : int end +|}] + (* Type declarations *) type t = X.t * X.s ;; [%%expect{| -Line _, characters 9-12: - type t = X.t * X.s - ^^^ -Warning 3: deprecated: X.t -Line _, characters 15-18: - type t = X.t * X.s - ^^^ -Warning 3: deprecated: X.s +Line 1, characters 9-12: +1 | type t = X.t * X.s + ^^^ +Alert deprecated: X.t +Line 1, characters 15-18: +1 | type t = X.t * X.s + ^^^ +Alert deprecated: X.s type t = X.t * X.s |}] @@ -69,10 +116,10 @@ type t1 = X.t [@@ocaml.warning "-3"] and t2 = X.s ;; [%%expect{| -Line _, characters 9-12: - and t2 = X.s - ^^^ -Warning 3: deprecated: X.s +Line 2, characters 9-12: +2 | and t2 = X.s + ^^^ +Alert deprecated: X.s type t1 = X.t and t2 = X.s |}] @@ -80,10 +127,10 @@ and t2 = X.s type t = A of t [@@ocaml.deprecated] ;; [%%expect{| -Line _, characters 14-15: - type t = A of t [@@ocaml.deprecated] - ^ -Warning 3: deprecated: t +Line 1, characters 14-15: +1 | type t = A of t [@@ocaml.deprecated] + ^ +Alert deprecated: t type t = A of t |}] @@ -106,10 +153,10 @@ type t = X.t * X.s type t = (X.t [@ocaml.warning "-3"]) * X.s ;; [%%expect{| -Line _, characters 39-42: - type t = (X.t [@ocaml.warning "-3"]) * X.s - ^^^ -Warning 3: deprecated: X.s +Line 1, characters 39-42: +1 | type t = (X.t [@ocaml.warning "-3"]) * X.s + ^^^ +Alert deprecated: X.s type t = X.t * X.s |}] @@ -126,10 +173,10 @@ type t = A of t let _ = function (_ : X.t) -> () ;; [%%expect{| -Line _, characters 22-25: - let _ = function (_ : X.t) -> () - ^^^ -Warning 3: deprecated: X.t +Line 1, characters 22-25: +1 | let _ = function (_ : X.t) -> () + ^^^ +Alert deprecated: X.t - : X.t -> unit = |}] @@ -145,10 +192,10 @@ let _ = function (_ : X.t)[@ocaml.warning "-3"] -> () module M = struct let x = X.x end ;; [%%expect{| -Line _, characters 26-29: - module M = struct let x = X.x end - ^^^ -Warning 3: deprecated: X.x +Line 1, characters 26-29: +1 | module M = struct let x = X.x end + ^^^ +Alert deprecated: X.x module M : sig val x : X.t end |}] @@ -167,18 +214,21 @@ module M : sig val x : X.t end module rec M : sig val x: X.t end = struct let x = X.x end [%%expect{| -Line _, characters 26-29: - module rec M : sig val x: X.t end = struct let x = X.x end - ^^^ -Warning 3: deprecated: X.t -Line _, characters 51-54: - module rec M : sig val x: X.t end = struct let x = X.x end - ^^^ -Warning 3: deprecated: X.x +Line 1, characters 26-29: +1 | module rec M : sig val x: X.t end = struct let x = X.x end + ^^^ +Alert deprecated: X.t +Line 1, characters 51-54: +1 | module rec M : sig val x: X.t end = struct let x = X.x end + ^^^ +Alert deprecated: X.x module rec M : sig val x : X.t end |}] -module rec M : sig val x: X.t end = struct let x = X.x end [@@ocaml.warning "-3"] +module rec M : sig val x: X.t end = + struct + let x = X.x + end [@@ocaml.warning "-3"] [%%expect{| module rec M : sig val x : X.t end |}] @@ -194,10 +244,10 @@ module rec M : (sig val x: X.t end)[@ocaml.warning "-3"] = struct let x = X.x end [%%expect{| -Line _, characters 17-20: - struct let x = X.x end - ^^^ -Warning 3: deprecated: X.x +Line 3, characters 17-20: +3 | struct let x = X.x end + ^^^ +Alert deprecated: X.x module rec M : sig val x : X.t end |}] @@ -206,10 +256,10 @@ module rec M : sig val x : X.t end module type S = sig type t = X.t end ;; [%%expect{| -Line _, characters 29-32: - module type S = sig type t = X.t end - ^^^ -Warning 3: deprecated: X.t +Line 1, characters 29-32: +1 | module type S = sig type t = X.t end + ^^^ +Alert deprecated: X.t module type S = sig type t = X.t end |}] @@ -231,10 +281,10 @@ module type S = sig type t = X.t end class c = object method x = X.x end ;; [%%expect{| -Line _, characters 28-31: - class c = object method x = X.x end - ^^^ -Warning 3: deprecated: X.x +Line 1, characters 28-31: +1 | class c = object method x = X.x end + ^^^ +Alert deprecated: X.x class c : object method x : X.t end |}] @@ -262,10 +312,10 @@ class c : object method x : X.t end class type c = object method x : X.t end ;; [%%expect{| -Line _, characters 33-36: - class type c = object method x : X.t end - ^^^ -Warning 3: deprecated: X.t +Line 1, characters 33-36: +1 | class type c = object method x : X.t end + ^^^ +Alert deprecated: X.t class type c = object method x : X.t end |}] @@ -294,10 +344,10 @@ class type c = object method x : X.t end external foo: unit -> X.t = "foo" ;; [%%expect{| -Line _, characters 22-25: - external foo: unit -> X.t = "foo" - ^^^ -Warning 3: deprecated: X.t +Line 1, characters 22-25: +1 | external foo: unit -> X.t = "foo" + ^^^ +Alert deprecated: X.t external foo : unit -> X.t = "foo" |}] @@ -313,10 +363,10 @@ external foo : unit -> X.t = "foo" X.x ;; [%%expect{| -Line _, characters 0-3: - X.x - ^^^ -Warning 3: deprecated: X.x +Line 1, characters 0-3: +1 | X.x + ^^^ +Alert deprecated: X.x - : X.t = |}] @@ -335,10 +385,10 @@ open D ;; [%%expect{| module D : sig end -Line _, characters 5-6: - open D - ^ -Warning 3: deprecated: module D +Line 3, characters 5-6: +3 | open D + ^ +Alert deprecated: module D |}] open D [@@ocaml.warning "-3"] @@ -349,10 +399,10 @@ open D [@@ocaml.warning "-3"] include D ;; [%%expect{| -Line _, characters 8-9: - include D - ^ -Warning 3: deprecated: module D +Line 1, characters 8-9: +1 | include D + ^ +Alert deprecated: module D |}] include D [@@ocaml.warning "-3"] @@ -375,10 +425,10 @@ type ext += | C of X.u [@ocaml.warning "-3"] ;; [%%expect{| -Line _, characters 9-12: - | A of X.t - ^^^ -Warning 3: deprecated: X.t +Line 2, characters 9-12: +2 | | A of X.t + ^^^ +Alert deprecated: X.t type ext += A of X.t | B of X.s | C of X.u |}] @@ -394,10 +444,10 @@ type ext += C of X.t exception Foo of X.t ;; [%%expect{| -Line _, characters 17-20: - exception Foo of X.t - ^^^ -Warning 3: deprecated: X.t +Line 1, characters 17-20: +1 | exception Foo of X.t + ^^^ +Alert deprecated: X.t exception Foo of X.t |}] @@ -416,10 +466,10 @@ type t = | C of (X.u [@ocaml.warning "-3"]) ;; [%%expect{| -Line _, characters 9-12: - | A of X.t - ^^^ -Warning 3: deprecated: X.t +Line 2, characters 9-12: +2 | | A of X.t + ^^^ +Alert deprecated: X.t type t = A of X.t | B of X.s | C of X.u |}] @@ -431,10 +481,10 @@ type t = } ;; [%%expect{| -Line _, characters 7-10: - a: X.t; - ^^^ -Warning 3: deprecated: X.t +Line 3, characters 7-10: +3 | a: X.t; + ^^^ +Alert deprecated: X.t type t = { a : X.t; b : X.s; c : X.u; } |}] @@ -447,10 +497,10 @@ type t = > ;; [%%expect{| -Line _, characters 7-10: - a: X.t; - ^^^ -Warning 3: deprecated: X.t +Line 3, characters 7-10: +3 | a: X.t; + ^^^ +Alert deprecated: X.t type t = < a : X.t; b : X.s; c : X.u > |}] @@ -463,10 +513,10 @@ type t = ] ;; [%%expect{| -Line _, characters 10-13: - | `A of X.t - ^^^ -Warning 3: deprecated: X.t +Line 3, characters 10-13: +3 | | `A of X.t + ^^^ +Alert deprecated: X.t type t = [ `A of X.t | `B of X.s | `C of X.u ] |}] @@ -477,9 +527,9 @@ type t = [ `A of X.t | `B of X.s | `C of X.u ] [@@@ocaml.ppwarning "Pp warning!"] ;; [%%expect{| -Line _, characters 20-33: - [@@@ocaml.ppwarning "Pp warning!"] - ^^^^^^^^^^^^^ +Line 1, characters 20-33: +1 | [@@@ocaml.ppwarning "Pp warning!"] + ^^^^^^^^^^^^^ Warning 22: Pp warning! |}] @@ -488,13 +538,13 @@ let x = () [@ocaml.ppwarning "Pp warning 1!"] [@@ocaml.ppwarning "Pp warning 2!"] ;; [%%expect{| -Line _, characters 24-39: - [@@ocaml.ppwarning "Pp warning 2!"] - ^^^^^^^^^^^^^^^ +Line 2, characters 24-39: +2 | [@@ocaml.ppwarning "Pp warning 2!"] + ^^^^^^^^^^^^^^^ Warning 22: Pp warning 2! -Line _, characters 29-44: - let x = () [@ocaml.ppwarning "Pp warning 1!"] - ^^^^^^^^^^^^^^^ +Line 1, characters 29-44: +1 | let x = () [@ocaml.ppwarning "Pp warning 1!"] + ^^^^^^^^^^^^^^^ Warning 22: Pp warning 1! val x : unit = () |}] @@ -503,9 +553,9 @@ type t = unit [@ocaml.ppwarning "Pp warning!"] ;; [%%expect{| -Line _, characters 22-35: - [@ocaml.ppwarning "Pp warning!"] - ^^^^^^^^^^^^^ +Line 2, characters 22-35: +2 | [@ocaml.ppwarning "Pp warning!"] + ^^^^^^^^^^^^^ Warning 22: Pp warning! type t = unit |}] @@ -521,34 +571,38 @@ module X = struct end ;; [%%expect{| -Line _, characters 22-36: - [@@@ocaml.ppwarning "Pp warning2!"] - ^^^^^^^^^^^^^^ +Line 8, characters 22-36: +8 | [@@@ocaml.ppwarning "Pp warning2!"] + ^^^^^^^^^^^^^^ Warning 22: Pp warning2! module X : sig end |}] -let x = ((() [@ocaml.ppwarning "Pp warning 1!"]) [@ocaml.warning "-22"]) [@ocaml.ppwarning "Pp warning 2!"] +let x = + ((() [@ocaml.ppwarning "Pp warning 1!"]) [@ocaml.warning "-22"]) + [@ocaml.ppwarning "Pp warning 2!"] ;; [%%expect{| -Line _, characters 93-108: - let x = ((() [@ocaml.ppwarning "Pp warning 1!"]) [@ocaml.warning "-22"]) [@ocaml.ppwarning "Pp warning 2!"] - ^^^^^^^^^^^^^^^ +Line 3, characters 23-38: +3 | [@ocaml.ppwarning "Pp warning 2!"] + ^^^^^^^^^^^^^^^ Warning 22: Pp warning 2! val x : unit = () |}] -type t = ((unit [@ocaml.ppwarning "Pp warning 1!"]) [@ocaml.warning "-22"]) [@ocaml.ppwarning "Pp warning 2!"] +type t = + ((unit [@ocaml.ppwarning "Pp warning 1!"]) [@ocaml.warning "-22"]) + [@ocaml.ppwarning "Pp warning 2!"] [@@ocaml.ppwarning "Pp warning 3!"] ;; [%%expect{| -Line _, characters 21-36: - [@@ocaml.ppwarning "Pp warning 3!"] - ^^^^^^^^^^^^^^^ +Line 4, characters 21-36: +4 | [@@ocaml.ppwarning "Pp warning 3!"] + ^^^^^^^^^^^^^^^ Warning 22: Pp warning 3! -Line _, characters 96-111: - type t = ((unit [@ocaml.ppwarning "Pp warning 1!"]) [@ocaml.warning "-22"]) [@ocaml.ppwarning "Pp warning 2!"] - ^^^^^^^^^^^^^^^ +Line 3, characters 21-36: +3 | [@ocaml.ppwarning "Pp warning 2!"] + ^^^^^^^^^^^^^^^ Warning 22: Pp warning 2! type t = unit |}] @@ -556,13 +610,13 @@ type t = unit let ([][@ocaml.ppwarning "XX"]) = [] ;; [%%expect{| -Line _, characters 25-29: - let ([][@ocaml.ppwarning "XX"]) = [] - ^^^^ +Line 1, characters 25-29: +1 | let ([][@ocaml.ppwarning "XX"]) = [] + ^^^^ Warning 22: XX -Line _, characters 4-31: - let ([][@ocaml.ppwarning "XX"]) = [] - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 4-31: +1 | let ([][@ocaml.ppwarning "XX"]) = [] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: _::_ diff --git a/testsuite/tests/typing-deprecated/ocamltests b/testsuite/tests/typing-deprecated/ocamltests index b8c7cb45..c38985ee 100644 --- a/testsuite/tests/typing-deprecated/ocamltests +++ b/testsuite/tests/typing-deprecated/ocamltests @@ -1 +1,2 @@ deprecated.ml +alerts.ml diff --git a/testsuite/tests/typing-extension-constructor/test.ocaml.reference b/testsuite/tests/typing-extension-constructor/test.ocaml.reference index f116fd3c..0fa7595b 100644 --- a/testsuite/tests/typing-extension-constructor/test.ocaml.reference +++ b/testsuite/tests/typing-extension-constructor/test.ocaml.reference @@ -3,9 +3,9 @@ type t += A - : extension_constructor = - : extension_constructor = module M : sig type extension_constructor = int end -Characters 2-28: - ([%extension_constructor A] : extension_constructor);; - ^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 1-27: +2 | ([%extension_constructor A] : extension_constructor);; + ^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This expression has type extension_constructor but an expression was expected of type M.extension_constructor = int diff --git a/testsuite/tests/typing-extensions/cast.ml b/testsuite/tests/typing-extensions/cast.ml index 713d86d8..7e155f53 100644 --- a/testsuite/tests/typing-extensions/cast.ml +++ b/testsuite/tests/typing-extensions/cast.ml @@ -82,7 +82,7 @@ let pop_castable () = | [] -> raise Not_found ;; -(* We can add foos and bars to this list, and retrive them *) +(* We can add foos and bars to this list, and retrieve them *) push_castable (new foo);; push_castable (new bar);; diff --git a/testsuite/tests/typing-extensions/extensions.ml b/testsuite/tests/typing-extensions/extensions.ml index 59ea0305..f4867449 100644 --- a/testsuite/tests/typing-extensions/extensions.ml +++ b/testsuite/tests/typing-extensions/extensions.ml @@ -310,8 +310,10 @@ type foo += | Bar of int ;; -let extension_name e = Obj.extension_name (Obj.extension_constructor e);; -let extension_id e = Obj.extension_id (Obj.extension_constructor e);; +let extension_name e = Obj.Extension_constructor.name + (Obj.Extension_constructor.of_val e);; +let extension_id e = Obj.Extension_constructor.id + (Obj.Extension_constructor.of_val e);; let n1 = extension_name Foo ;; @@ -333,8 +335,8 @@ type foo += Foo let f = is_foo Foo ;; -let _ = Obj.extension_constructor 7 (* Invald_arg *) +let _ = Obj.Extension_constructor.of_val 7 (* Invalid_arg *) ;; -let _ = Obj.extension_constructor (object method m = 3 end) (* Invald_arg *) +let _ = Obj.Extension_constructor.of_val (object method m = 3 end) (* Invalid_arg *) ;; diff --git a/testsuite/tests/typing-extensions/extensions.ocaml.reference b/testsuite/tests/typing-extensions/extensions.ocaml.reference index 6d55712e..53e30600 100644 --- a/testsuite/tests/typing-extensions/extensions.ocaml.reference +++ b/testsuite/tests/typing-extensions/extensions.ocaml.reference @@ -3,25 +3,25 @@ type foo = .. type foo += A | B of int val is_a : foo -> bool = type foo -Characters 1-21: - type foo += A of int (* Error type is not open *) - ^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 0-20: +2 | type foo += A of int (* Error type is not open *) + ^^^^^^^^^^^^^^^^^^^^ Error: Type definition foo is not extensible type foo = private .. -Characters 13-21: - type foo += A of int (* Error type is private *) - ^^^^^^^^ +Line 2, characters 12-20: +2 | type foo += A of int (* Error type is private *) + ^^^^^^^^ Error: Cannot extend private type definition foo type 'a foo = .. -Characters 1-30: - type ('a, 'b) foo += A of int (* Error: type parameter mismatch *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 0-29: +2 | type ('a, 'b) foo += A of int (* Error: type parameter mismatch *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This extension does not match the definition of type foo They have different arities. module type S = sig type foo = private .. type foo += A of float end -Characters 73-95: - type foo += B of float (* Error: foo does not have an extensible type *) - ^^^^^^^^^^^^^^^^^^^^^^ +Line 7, characters 2-24: +7 | type foo += B of float (* Error: foo does not have an extensible type *) + ^^^^^^^^^^^^^^^^^^^^^^ Error: Type definition foo is not extensible type foo = .. module M : @@ -42,14 +42,14 @@ type _ foo += A : int -> int foo | B : int foo val get_num : 'a foo -> 'a -> 'a option = type 'a foo = .. constraint 'a = [> `Var ] type 'a foo += A of 'a -Characters 11-12: - let a = A 9 (* ERROR: Constraints not met *) - ^ +Line 2, characters 10-11: +2 | let a = A 9 (* ERROR: Constraints not met *) + ^ Error: This expression has type int but an expression was expected of type [> `Var ] -Characters 20-23: - type 'a foo += B : int foo (* ERROR: Constraints not met *) - ^^^ +Line 2, characters 19-22: +2 | type 'a foo += B : int foo (* ERROR: Constraints not met *) + ^^^ Error: This type int should be an instance of type [> `Var ] type foo = .. module M : sig type foo += A of int end @@ -57,27 +57,27 @@ val a1 : foo = M.A 10 module type S = sig type foo += private A of int end module M_S : S val is_s : foo -> bool = -Characters 10-18: - let a2 = M_S.A 20 (* ERROR: Cannot create a value using a private constructor *) - ^^^^^^^^ +Line 2, characters 9-17: +2 | let a2 = M_S.A 20 (* ERROR: Cannot create a value using a private constructor *) + ^^^^^^^^ Error: Cannot create values of the private type foo type foo = .. module M : sig type foo += A1 of int end type foo += A2 of int type bar = .. -Characters 18-22: - type bar += A3 = M.A1 (* Error: rebind wrong type *) - ^^^^ +Line 2, characters 17-21: +2 | type bar += A3 = M.A1 (* Error: rebind wrong type *) + ^^^^ Error: The constructor M.A1 has type foo but was expected to be of type bar module M : sig type foo += private B1 of int end type foo += private B2 of int -Characters 18-22: - type foo += B3 = M.B1 (* Error: rebind private extension *) - ^^^^ +Line 2, characters 17-21: +2 | type foo += B3 = M.B1 (* Error: rebind private extension *) + ^^^^ Error: The constructor M.B1 is private -Characters 17-24: - type foo += C = Unknown (* Error: unbound extension *) - ^^^^^^^ +Line 2, characters 16-23: +2 | type foo += C = Unknown (* Error: unbound extension *) + ^^^^^^^ Error: Unbound constructor Unknown module M : sig type foo = private .. type foo += A1 of int end type M.foo += A2 of int @@ -88,22 +88,22 @@ type 'a foo1 += A of int | B of 'a | C : int foo1 type 'a foo2 += D of int | E of 'a | F : int foo2 type +'a foo = .. type 'a foo += A of (int -> 'a) -Characters 1-32: - type 'a foo += B of ('a -> int) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 0-31: +2 | type 'a foo += B of ('a -> int) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In this definition, expected parameter variances are not satisfied. The 1st type parameter was expected to be covariant, but it is injective contravariant. -Characters 1-40: - type _ foo += C : ('a -> int) -> 'a foo - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 0-39: +2 | type _ foo += C : ('a -> int) -> 'a foo + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In this definition, expected parameter variances are not satisfied. The 1st type parameter was expected to be covariant, but it is injective contravariant. type 'a bar = .. -Characters 1-33: - type +'a bar += D of (int -> 'a) (* ERROR: type variances do not match *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 0-32: +2 | type +'a bar += D of (int -> 'a) (* ERROR: type variances do not match *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This extension does not match the definition of type bar Their variances do not agree. module M : sig type exn += Foo of int * float | Bar : 'a list -> exn end diff --git a/testsuite/tests/typing-extensions/msg.ml b/testsuite/tests/typing-extensions/msg.ml index da50613c..07cdba65 100644 --- a/testsuite/tests/typing-extensions/msg.ml +++ b/testsuite/tests/typing-extensions/msg.ml @@ -73,7 +73,7 @@ end = struct let ik = { tag = Int; label = "int"; - write = string_of_int; + write = Int.to_string; read = int_of_string } let () = Hashtbl.add readTbl "int" (K ik) diff --git a/testsuite/tests/typing-extensions/open_types.ocaml.reference b/testsuite/tests/typing-extensions/open_types.ocaml.reference index fc44f884..2dddce7b 100644 --- a/testsuite/tests/typing-extensions/open_types.ocaml.reference +++ b/testsuite/tests/typing-extensions/open_types.ocaml.reference @@ -8,40 +8,40 @@ module type S = sig type baz += Foo of float end module M_S : S type foo = .. type bar = foo -Characters 1-23: - type bar += Bar of int (* Error: type is not open *) - ^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 0-22: +2 | type bar += Bar of int (* Error: type is not open *) + ^^^^^^^^^^^^^^^^^^^^^^ Error: Type definition bar is not extensible -Characters 1-20: - type baz = bar = .. (* Error: type kinds don't match *) - ^^^^^^^^^^^^^^^^^^^ +Line 2, characters 0-19: +2 | type baz = bar = .. (* Error: type kinds don't match *) + ^^^^^^^^^^^^^^^^^^^ Error: This variant or record definition does not match that of type bar Their kinds differ. type 'a foo = .. -Characters 1-32: - type ('a, 'b) bar = 'a foo = .. (* Error: arrities do not match *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 0-31: +2 | type ('a, 'b) bar = 'a foo = .. (* Error: arrities do not match *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This variant or record definition does not match that of type 'a foo They have different arities. type ('a, 'b) foo = .. -Characters 1-38: - type ('a, 'b) bar = ('a, 'a) foo = .. (* Error: constraints do not match *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 0-37: +2 | type ('a, 'b) bar = ('a, 'a) foo = .. (* Error: constraints do not match *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This variant or record definition does not match that of type ('a, 'a) foo Their constraints differ. module M : sig type foo = .. end module type S = sig type foo end module M_S : S -Characters 1-20: - type M_S.foo += Foo (* ERROR: Cannot extend a type that isn't "open" *) - ^^^^^^^^^^^^^^^^^^^ +Line 2, characters 0-19: +2 | type M_S.foo += Foo (* ERROR: Cannot extend a type that isn't "open" *) + ^^^^^^^^^^^^^^^^^^^ Error: Type definition M_S.foo is not extensible module M : sig type foo end module type S = sig type foo = .. end -Characters 15-16: - module M_S = (M : S) (* ERROR: Signatures are not compatible *) - ^ +Line 2, characters 14-15: +2 | module M_S = (M : S) (* ERROR: Signatures are not compatible *) + ^ Error: Signature mismatch: Modules do not match: sig type foo = M.foo end is not included in S Type declarations do not match: @@ -52,15 +52,15 @@ Error: Signature mismatch: module M : sig type foo = .. end module type S = sig type foo = private .. end module M_S : S -Characters 17-20: - type M_S.foo += Foo (* ERROR: Cannot extend a private extensible type *) - ^^^ +Line 2, characters 16-19: +2 | type M_S.foo += Foo (* ERROR: Cannot extend a private extensible type *) + ^^^ Error: Cannot extend private type definition M_S.foo module M : sig type foo = private .. end module type S = sig type foo = .. end -Characters 15-16: - module M_S = (M : S) (* ERROR: Signatures are not compatible *) - ^ +Line 2, characters 14-15: +2 | module M_S = (M : S) (* ERROR: Signatures are not compatible *) + ^ Error: Signature mismatch: Modules do not match: sig type foo = M.foo = private .. end @@ -73,9 +73,9 @@ Error: Signature mismatch: A private type would be revealed. module M : sig type +'a foo = .. type 'a bar = 'a foo = .. end module type S = sig type 'a foo = .. type 'a bar = 'a foo = .. end -Characters 15-16: - module M_S = (M : S) (* ERROR: Signatures are not compatible *) - ^ +Line 2, characters 14-15: +2 | module M_S = (M : S) (* ERROR: Signatures are not compatible *) + ^ Error: Signature mismatch: Modules do not match: sig type 'a foo = 'a M.foo = .. type 'a bar = 'a foo = .. end @@ -87,9 +87,9 @@ Error: Signature mismatch: type 'a foo = .. Their variances do not agree. type exn2 = exn = .. -Characters 61-79: - let f = function Foo -> () - ^^^^^^^^^^^^^^^^^^ +Line 6, characters 8-26: +6 | let f = function Foo -> () + ^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: *extension* @@ -98,11 +98,11 @@ must include a wild card pattern in order to be exhaustive. type foo = .. type foo += Foo val f : foo -> unit = -Characters 44-96: - ........function - | [Foo] -> 1 - | _::_::_ -> 3 - | [] -> 2 +Line 4, characters 8-60: +4 | ........function +5 | | [Foo] -> 1 +6 | | _::_::_ -> 3 +7 | | [] -> 2 Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: *extension*::[] @@ -111,9 +111,9 @@ must include a wild card pattern in order to be exhaustive. val f : foo list -> int = type t = .. type t += IPair : (int * int) -> t -Characters 9-63: - let f = function IPair (i, j) -> Format.sprintf "(%d, %d)" i j ;; (* warn *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 8-62: +2 | let f = function IPair (i, j) -> Format.sprintf "(%d, %d)" i j ;; (* warn *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: *extension* diff --git a/testsuite/tests/typing-fstclassmod/fstclassmod.ml b/testsuite/tests/typing-fstclassmod/fstclassmod.ml index 1e5c531c..9be53992 100644 --- a/testsuite/tests/typing-fstclassmod/fstclassmod.ml +++ b/testsuite/tests/typing-fstclassmod/fstclassmod.ml @@ -60,7 +60,7 @@ let apply x = (module N : S) let () = - let int = forget (create string_of_int succ 0) in + let int = forget (create Int.to_string succ 0) in let str = forget (create (fun s -> s) (fun s -> s ^ s) "X") in List.iter print (List.map apply [int; apply int; apply (apply str)]) @@ -133,7 +133,7 @@ module rec Print : sig end = struct let to_string (type s) t x = match t with - | Int eq -> string_of_int (TypEq.apply eq x) + | Int eq -> Int.to_string (TypEq.apply eq x) | String eq -> Printf.sprintf "%S" (TypEq.apply eq x) | Pair p -> let module P = (val p : PAIR with type t = s) in @@ -168,4 +168,4 @@ let f = function | Some _ -> 2 | None -> 3 ;; -print_endline (string_of_int (f (Some (module struct let x = false end))));; +print_endline (Int.to_string (f (Some (module struct let x = false end))));; diff --git a/testsuite/tests/typing-gadts/ambiguity.ml b/testsuite/tests/typing-gadts/ambiguity.ml index 20e923a0..ab6c97ac 100644 --- a/testsuite/tests/typing-gadts/ambiguity.ml +++ b/testsuite/tests/typing-gadts/ambiguity.ml @@ -15,9 +15,9 @@ let ret_e1 (type a b) (b : bool) (wit : (a, b) eq) (x : a) (y : b) = | _ -> x ;; [%%expect{| -Line _, characters 29-30: - | Refl -> if b then x else y - ^ +Line 3, characters 29-30: +3 | | Refl -> if b then x else y + ^ Error: This expression has type b = a but an expression was expected of type a This instance of a is ambiguous: @@ -30,9 +30,9 @@ let ret_e2 (type a b) (b : bool) (wit : (a, b) eq) (x : a) (y : b) = | _ -> y ;; [%%expect{| -Line _, characters 29-30: - | Refl -> if b then x else y - ^ +Line 3, characters 29-30: +3 | | Refl -> if b then x else y + ^ Error: This expression has type b = a but an expression was expected of type a This instance of a is ambiguous: @@ -45,9 +45,9 @@ let ret_ei1 (type a) (b : bool) (wit : (a, int) eq) (x : a) = | _ -> x ;; [%%expect{| -Line _, characters 29-30: - | Refl -> if b then x else 0 - ^ +Line 3, characters 29-30: +3 | | Refl -> if b then x else 0 + ^ Error: This expression has type int but an expression was expected of type a = int This instance of int is ambiguous: @@ -60,9 +60,9 @@ let ret_ei2 (type a) (b : bool) (wit : (a, int) eq) (x : a) = | _ -> x ;; [%%expect{| -Line _, characters 29-30: - | Refl -> if b then x else 0 - ^ +Line 3, characters 29-30: +3 | | Refl -> if b then x else 0 + ^ Error: This expression has type int but an expression was expected of type a = int This instance of int is ambiguous: @@ -76,9 +76,9 @@ let ret_f (type a b) (wit : (a, b) eq) (x : a) (y : b) = | _ -> [x] ;; [%%expect{| -Line _, characters 16-17: - | Refl -> [x; y] - ^ +Line 3, characters 16-17: +3 | | Refl -> [x; y] + ^ Error: This expression has type b = a but an expression was expected of type a This instance of a is ambiguous: @@ -91,9 +91,9 @@ let ret_g1 (type a b) (wit : (a, b) eq) (x : a) (y : b) = | _ -> [y] ;; [%%expect{| -Line _, characters 16-17: - | Refl -> [x; y] - ^ +Line 3, characters 16-17: +3 | | Refl -> [x; y] + ^ Error: This expression has type b = a but an expression was expected of type a This instance of a is ambiguous: @@ -113,11 +113,10 @@ let f (type a b) (x : (a, b) eq) = | _, [(_ : a)] -> [] ;; [%%expect{| -Line _, characters 4-29: - | Refl, [(_ : a) | (_ : b)] -> [] - ^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 4-29: +3 | | Refl, [(_ : a) | (_ : b)] -> [] + ^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This pattern matches values of type (a, b) eq * b list - but a pattern was expected which matches values of type 'a This instance of b is ambiguous: it would escape the scope of its equation |}] @@ -128,11 +127,10 @@ let g1 (type a b) (x : (a, b) eq) = | _, [(_ : b)] -> [] ;; [%%expect{| -Line _, characters 4-29: - | Refl, [(_ : a) | (_ : b)] -> [] - ^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 4-29: +3 | | Refl, [(_ : a) | (_ : b)] -> [] + ^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This pattern matches values of type (a, b) eq * b list - but a pattern was expected which matches values of type 'a This instance of b is ambiguous: it would escape the scope of its equation |}] @@ -143,11 +141,10 @@ let g2 (type a b) (x : (a, b) eq) = | _, [(_ : a)] -> [] ;; [%%expect{| -Line _, characters 4-29: - | Refl, [(_ : b) | (_ : a)] -> [] - ^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 4-29: +3 | | Refl, [(_ : b) | (_ : a)] -> [] + ^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This pattern matches values of type (a, b) eq * b list - but a pattern was expected which matches values of type 'a This instance of b is ambiguous: it would escape the scope of its equation |}] @@ -158,11 +155,10 @@ let h1 (type a b) (x : (a, b) eq) = | Refl, [(_ : a) | (_ : b)] -> [] ;; [%%expect{| -Line _, characters 4-29: - | Refl, [(_ : a) | (_ : b)] -> [] - ^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 4, characters 4-29: +4 | | Refl, [(_ : a) | (_ : b)] -> [] + ^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This pattern matches values of type (a, b) eq * b list - but a pattern was expected which matches values of type 'a This instance of b is ambiguous: it would escape the scope of its equation |}] @@ -173,11 +169,10 @@ let h2 (type a b) (x : (a, b) eq) = | Refl, [(_ : a) | (_ : b)] -> [] ;; [%%expect{| -Line _, characters 4-29: - | Refl, [(_ : a) | (_ : b)] -> [] - ^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 4, characters 4-29: +4 | | Refl, [(_ : a) | (_ : b)] -> [] + ^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This pattern matches values of type (a, b) eq * b list - but a pattern was expected which matches values of type 'a This instance of b is ambiguous: it would escape the scope of its equation |}] @@ -188,11 +183,10 @@ let h3 (type a b) (x : (a, b) eq) = | Refl, [(_ : b) | (_ : a)] -> [] ;; [%%expect{| -Line _, characters 4-29: - | Refl, [(_ : b) | (_ : a)] -> [] - ^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 4, characters 4-29: +4 | | Refl, [(_ : b) | (_ : a)] -> [] + ^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This pattern matches values of type (a, b) eq * b list - but a pattern was expected which matches values of type 'a This instance of b is ambiguous: it would escape the scope of its equation |}] diff --git a/testsuite/tests/typing-gadts/didier.ml b/testsuite/tests/typing-gadts/didier.ml index 749ae667..717fb945 100644 --- a/testsuite/tests/typing-gadts/didier.ml +++ b/testsuite/tests/typing-gadts/didier.ml @@ -12,9 +12,9 @@ let fbool (type t) (x : t) (tag : t ty) = ;; [%%expect{| type 'a ty = Int : int ty | Bool : bool ty -Line _, characters 2-30: - ..match tag with - | Bool -> x +Line 6, characters 2-30: +6 | ..match tag with +7 | | Bool -> x Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Int @@ -28,9 +28,9 @@ let fint (type t) (x : t) (tag : t ty) = | Int -> x > 0 ;; [%%expect{| -Line _, characters 2-33: - ..match tag with - | Int -> x > 0 +Line 2, characters 2-33: +2 | ..match tag with +3 | | Int -> x > 0 Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Bool @@ -49,9 +49,9 @@ let f (type t) (x : t) (tag : t ty) = [%%expect{| val f : 'a -> 'a ty -> bool = |}, Principal{| -Line _, characters 12-13: - | Bool -> x - ^ +Line 4, characters 12-13: +4 | | Bool -> x + ^ Error: This expression has type t but an expression was expected of type bool |}];; (* val f : 'a -> 'a ty -> bool = *) @@ -63,15 +63,15 @@ let g (type t) (x : t) (tag : t ty) = | Int -> x > 0 ;; [%%expect{| -Line _, characters 11-16: - | Int -> x > 0 - ^^^^^ +Line 4, characters 11-16: +4 | | Int -> x > 0 + ^^^^^ Error: This expression has type bool but an expression was expected of type t = int |}, Principal{| -Line _, characters 11-16: - | Int -> x > 0 - ^^^^^ +Line 4, characters 11-16: +4 | | Int -> x > 0 + ^^^^^ Error: This expression has type bool but an expression was expected of type t |}];; (* Error: This expression has type bool but an expression was expected of type diff --git a/testsuite/tests/typing-gadts/dynamic_frisch.ml b/testsuite/tests/typing-gadts/dynamic_frisch.ml index 7af47672..8bef4074 100644 --- a/testsuite/tests/typing-gadts/dynamic_frisch.ml +++ b/testsuite/tests/typing-gadts/dynamic_frisch.ml @@ -601,9 +601,9 @@ let ty_list : type a e. (a,e) ty -> (a vlist,e) ty = fun t -> | "Cons", Some (Tdyn (Pair (_, Var), (p : a * a vlist))) -> `Cons p))) ;; [%%expect{| -Line _, characters 41-58: - | "Cons", Some (Tdyn (Pair (_, Var), (p : a * a vlist))) -> `Cons p))) - ^^^^^^^^^^^^^^^^^ +Line 7, characters 41-58: +7 | | "Cons", Some (Tdyn (Pair (_, Var), (p : a * a vlist))) -> `Cons p))) + ^^^^^^^^^^^^^^^^^ Error: This pattern matches values of type a * a vlist but a pattern was expected which matches values of type $Tdyn_'a = $0 * $1 diff --git a/testsuite/tests/typing-gadts/gpr1997.ml b/testsuite/tests/typing-gadts/gpr1997.ml deleted file mode 100644 index 8a9b6c95..00000000 --- a/testsuite/tests/typing-gadts/gpr1997.ml +++ /dev/null @@ -1,53 +0,0 @@ -(* TEST - * expect -*) - -module M : sig - type 'a t - - type _ typ = - | Foo : 'a -> [`Foo of 'a] typ - | Bar : string -> [`Bar] typ - - val use_bar : [`Bar] t -> int - - val foo : [`Foo of int] t - -end = struct - type 'a t = string - - type _ typ = - | Foo : 'a -> [`Foo of 'a] typ - | Bar : string -> [`Bar] typ - - let foo = "foo" - - let use_bar _ = 0 -end;; -[%%expect {| -module M : - sig - type 'a t - type _ typ = - Foo : 'a -> [ `Foo of 'a ] typ - | Bar : string -> [ `Bar ] typ - val use_bar : [ `Bar ] t -> int - val foo : [ `Foo of int ] t - end -|}];; - -let go (type a) (typ : a M.typ) (msg : a M.t) = - match typ with - | Bar s -> - (match M.use_bar msg with _ -> ()) -;; -[%%expect {| -Line _, characters 2-68: - ..match typ with - | Bar s -> - (match M.use_bar msg with _ -> ()) -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -Foo _ -val go : 'a M.typ -> 'a M.t -> unit = -|}];; diff --git a/testsuite/tests/typing-gadts/nested_equations.ml b/testsuite/tests/typing-gadts/nested_equations.ml index ffb7084c..b1719bfb 100644 --- a/testsuite/tests/typing-gadts/nested_equations.ml +++ b/testsuite/tests/typing-gadts/nested_equations.ml @@ -16,9 +16,9 @@ let w_bool : bool t = Obj.magic 0;; let f_bool (x : bool) : int = let Int = w_bool in x;; (* fail *) [%%expect{| val w_bool : bool t = Int -Line _, characters 34-37: - let f_bool (x : bool) : int = let Int = w_bool in x;; (* fail *) - ^^^ +Line 2, characters 34-37: +2 | let f_bool (x : bool) : int = let Int = w_bool in x;; (* fail *) + ^^^ Error: This pattern matches values of type int t but a pattern was expected which matches values of type bool t Type int is not compatible with type bool @@ -35,9 +35,9 @@ let w_spec : Arg.spec t = Obj.magic 0;; let f_spec (x : Arg.spec) : int = let Int = w_spec in x;; (* fail *) [%%expect{| val w_spec : Arg.spec t = Int -Line _, characters 38-41: - let f_spec (x : Arg.spec) : int = let Int = w_spec in x;; (* fail *) - ^^^ +Line 2, characters 38-41: +2 | let f_spec (x : Arg.spec) : int = let Int = w_spec in x;; (* fail *) + ^^^ Error: This pattern matches values of type int t but a pattern was expected which matches values of type Arg.spec t Type int is not compatible with type Arg.spec diff --git a/testsuite/tests/typing-gadts/ocamltests b/testsuite/tests/typing-gadts/ocamltests index 908c01f5..83d75ab1 100644 --- a/testsuite/tests/typing-gadts/ocamltests +++ b/testsuite/tests/typing-gadts/ocamltests @@ -3,6 +3,7 @@ didier.ml dynamic_frisch.ml nested_equations.ml omega07.ml +or_patterns.ml pr5332.ml pr5689.ml pr5785.ml @@ -43,7 +44,7 @@ pr7618.ml pr7747.ml term-conv.ml test.ml +unexpected_existentials.ml unify_mb.ml variables_in_mcomp.ml yallop_bugs.ml -gpr1997.ml diff --git a/testsuite/tests/typing-gadts/or_patterns.ml b/testsuite/tests/typing-gadts/or_patterns.ml new file mode 100644 index 00000000..c7e0b18d --- /dev/null +++ b/testsuite/tests/typing-gadts/or_patterns.ml @@ -0,0 +1,763 @@ +(* TEST + * expect +*) + +type _ t = + | IntLit : int t + | BoolLit : bool t +;; + +[%%expect{| +type _ t = IntLit : int t | BoolLit : bool t +|}] + +let trivial t = + match t with + | IntLit -> () + | BoolLit -> () +;; + +[%%expect{| +Line 4, characters 4-11: +4 | | BoolLit -> () + ^^^^^^^ +Error: This pattern matches values of type bool t + but a pattern was expected which matches values of type int t + Type bool is not compatible with type int +|}] + +let trivial_annotated (type a) (t : a t) = + match t with + | IntLit -> () + | BoolLit -> () +;; + +[%%expect{| +val trivial_annotated : 'a t -> unit = +|}] + +let trivial_merged t = + match t with + | IntLit + | BoolLit -> () +;; + +[%%expect{| +Line 4, characters 4-11: +4 | | BoolLit -> () + ^^^^^^^ +Error: This pattern matches values of type bool t + but a pattern was expected which matches values of type int t + Type bool is not compatible with type int +|}] + +let trivial_merged_annotated (type a) (t : a t) = + match t with + | IntLit + | BoolLit -> () +;; + +[%%expect{| +val trivial_merged_annotated : 'a t -> unit = +|}] + +let trivial_merged_annotated_under_tuple1 (type a) (t : a t) = + match (3, t) with + | _, (IntLit + | BoolLit) -> () +;; + +[%%expect{| +val trivial_merged_annotated_under_tuple1 : 'a t -> unit = +|}] + +let trivial_merged_annotated_under_tuple2 (type a) (tt : a t * a t) = + match tt with + | IntLit, (IntLit | BoolLit) -> () + | _ -> () +;; + +[%%expect{| +Line 3, characters 22-29: +3 | | IntLit, (IntLit | BoolLit) -> () + ^^^^^^^ +Error: This pattern matches values of type bool t + but a pattern was expected which matches values of type a t + Type bool is not compatible with type a = int +|}] + +let trivial_merged_annotated_under_tuple2 (type a) (tt : a t * a t) = + match tt with + | (IntLit | BoolLit), IntLit -> () + | _ -> () +;; + +[%%expect{| +val trivial_merged_annotated_under_tuple2 : 'a t * 'a t -> unit = +|}] + + +let trivial_merged_annotated_under_array (type a) (t : a t array) = + match t with + | [| (IntLit | BoolLit); _ |] -> () + | [| _; _; (BoolLit | IntLit) |] -> () + | [| _; _; _; (BoolLit | IntLit) |] + | [| _; _; _; (BoolLit | IntLit); _ |] -> () + | _ -> () +;; + +[%%expect{| +val trivial_merged_annotated_under_array : 'a t array -> unit = +|}] + +let simple t a = + match t, a with + | IntLit, 3 -> () + | BoolLit, true -> () + | _, _ -> () +;; + +[%%expect{| +Line 4, characters 4-11: +4 | | BoolLit, true -> () + ^^^^^^^ +Error: This pattern matches values of type bool t + but a pattern was expected which matches values of type int t + Type bool is not compatible with type int +|}, Principal{| +Line 4, characters 4-17: +4 | | BoolLit, true -> () + ^^^^^^^^^^^^^ +Error: This pattern matches values of type bool t * bool + but a pattern was expected which matches values of type int t * int + Type bool is not compatible with type int +|}] + +let simple_annotated (type a) (t : a t) (a : a) = + match t, a with + | IntLit, 3 -> () + | BoolLit, true -> () + | _, _ -> () +;; + +[%%expect{| +val simple_annotated : 'a t -> 'a -> unit = +|}] + +let simple_merged t a = + match t, a with + | IntLit, 3 + | BoolLit, true -> () + | _, _ -> () +;; + +[%%expect{| +Line 4, characters 4-11: +4 | | BoolLit, true -> () + ^^^^^^^ +Error: This pattern matches values of type bool t + but a pattern was expected which matches values of type int t + Type bool is not compatible with type int +|}] + +let simple_merged_ambi (type a) (t : a t) a = + match t, a with + | IntLit, (3 : a) + | BoolLit, true -> () + | _, _ -> () +;; + +[%%expect{| +Line 4, characters 13-17: +4 | | BoolLit, true -> () + ^^^^ +Error: This pattern matches values of type bool + but a pattern was expected which matches values of type a = bool + This instance of bool is ambiguous: + it would escape the scope of its equation +|}] + + +let simple_merged_not_annotated_enough (type a) (t : a t) a = + match t, a with + | IntLit, 3 + | BoolLit, true -> () + | _, _ -> () +;; + +[%%expect{| +Line 4, characters 13-17: +4 | | BoolLit, true -> () + ^^^^ +Error: This pattern matches values of type bool + but a pattern was expected which matches values of type int +|}] + + +let simple_merged_annotated (type a) (t : a t) (a : a) = + match t, a with + | IntLit, 3 + | BoolLit, true -> () + | _, _ -> () +;; + +[%%expect{| +val simple_merged_annotated : 'a t -> 'a -> unit = +|}] + +let simple_mega_merged_annotated (type a) (t : a t) (a : a) = + match t, a with + | IntLit, 3 + | BoolLit, true + | _, _ -> () +;; + +[%%expect{| +val simple_mega_merged_annotated : 'a t -> 'a -> unit = +|}] + +let simple_merged_annotated_return (type a) (t : a t) (a : a) = + match t, a with + | IntLit, (3 as x) + | BoolLit, (true as x) -> ignore x + | _, _ -> () +;; + +[%%expect{| +Line 3, characters 12-20: +3 | | IntLit, (3 as x) + ^^^^^^^^ +Error: This pattern matches values of type a + This instance of a is ambiguous: + it would escape the scope of its equation +|}] + +let simple_merged_annotated_return_annotated (type a) (t : a t) (a : a) = + match t, a with + | IntLit, ((3 : a) as x) + | BoolLit, ((true : a) as x) -> ignore x + | _, _ -> () +;; + +[%%expect{| +Line 3, characters 4-57: +3 | ....IntLit, ((3 : a) as x) +4 | | BoolLit, ((true : a) as x)............ +Error: The variable x on the left-hand side of this or-pattern has type + a but on the right-hand side it has type bool +|}] + +(* test more scenarios: when the or-pattern itself is not at toplevel but under + other patterns. *) + +let simple_merged_annotated_under_tuple (type a) (pair : a t * a) = + match (), pair with + | (), ( IntLit, 3 + | BoolLit, true) -> () + | _, _ -> () +;; + +[%%expect{| +val simple_merged_annotated_under_tuple : 'a t * 'a -> unit = +|}] + +let simple_merged_annotated_under_arrays (type a) (pair : a t * a) = + match [| [| pair |] |] with + | [| _ ; [| ( IntLit, 3 + | BoolLit, true) |] |] -> () + | _ -> () +;; + +[%%expect{| +val simple_merged_annotated_under_arrays : 'a t * 'a -> unit = +|}] + + +let simple_merged_annotated_under_poly_variant (type a) (pair : a t * a) = + match `Foo pair with + | `Foo ( IntLit, 3 + | BoolLit, true ) -> () + | _ -> () +;; + +[%%expect{| +Line 3, characters 19-20: +3 | | `Foo ( IntLit, 3 + ^ +Error: This pattern matches values of type int + but a pattern was expected which matches values of type a = int + This instance of int is ambiguous: + it would escape the scope of its equation +|}] + +let simple_merged_annotated_under_poly_variant_annotated (type a) pair = + match (`Foo pair : [ `Foo of (a t * a) ]) with + | `Foo ( IntLit, 3 + | BoolLit, true ) -> () + | _ -> () +;; + +[%%expect{| +val simple_merged_annotated_under_poly_variant_annotated : 'a t * 'a -> unit = + +|}] + +type 'a iref = { content : 'a; };; +[%%expect{| +type 'a iref = { content : 'a; } +|}] + +let simple_merged_annotated_under_record (type a) (pair : a t * a) = + match { content = pair } with + | { content = ( IntLit, 3 + | BoolLit, true ) } -> () + | _ -> () +;; +[%%expect{| +val simple_merged_annotated_under_record : 'a t * 'a -> unit = +|}] + +let simple_merged_annotated_under_mutable_record (type a) (pair : a t * a) = + match { contents = pair } with + | { contents = ( IntLit, 3 + | BoolLit, true ) } -> () + | _ -> () +;; +[%%expect{| +val simple_merged_annotated_under_mutable_record : 'a t * 'a -> unit = +|}] + +type 'a piref = { pcontent : 'b. 'a * 'b; };; +[%%expect{| +type 'a piref = { pcontent : 'b. 'a * 'b; } +|}] + +let simple_merged_annotated_under_poly_record1 (type a) (r : (a t * a) piref) = + match r with + | { pcontent = ( IntLit, 3 + | BoolLit, true ), _ } -> () + | _ -> () +;; +[%%expect{| +val simple_merged_annotated_under_poly_record1 : ('a t * 'a) piref -> unit = + +|}] + +let simple_merged_annotated_under_poly_record2 (type a) (r : (a t * a) piref) = + match r with + | { pcontent = ( (IntLit, 3), _ + | (BoolLit, true), _ ) } -> () + | _ -> () +;; +[%%expect{| +val simple_merged_annotated_under_poly_record2 : ('a t * 'a) piref -> unit = + +|}] + +let simple_merged_annotated_under_constructor (type a) (pair : a t * a) = + match Some pair with + | Some ( IntLit, 3 + | BoolLit, true ) -> () + | _ -> () +;; +[%%expect{| +val simple_merged_annotated_under_constructor : 'a t * 'a -> unit = +|}] + +type _ gadt_opt = + | GNone : 'a gadt_opt + | GSome : 'a -> 'a gadt_opt +;; +[%%expect{| +type _ gadt_opt = GNone : 'a gadt_opt | GSome : 'a -> 'a gadt_opt +|}] + +let simple_merged_annotated_under_gadt_constructor (type a) (pair : a t * a) = + match GSome pair with + | GSome ( IntLit, 3 + | BoolLit, true ) -> () + | _ -> () +;; +[%%expect{| +val simple_merged_annotated_under_gadt_constructor : 'a t * 'a -> unit = + +|}] + +(* back to simpler tests. *) + +let noop t a = + match t, a with + | IntLit, x -> x + | BoolLit, x -> x +;; + +[%%expect{| +Line 4, characters 4-11: +4 | | BoolLit, x -> x + ^^^^^^^ +Error: This pattern matches values of type bool t + but a pattern was expected which matches values of type int t + Type bool is not compatible with type int +|}, Principal{| +Line 4, characters 4-14: +4 | | BoolLit, x -> x + ^^^^^^^^^^ +Error: This pattern matches values of type bool t * 'a + but a pattern was expected which matches values of type int t * 'b + Type bool is not compatible with type int +|}] + +let noop_annotated (type a) (t : a t) (a : a) : a = + match t, a with + | IntLit, x -> x + | BoolLit, x -> x +;; + +[%%expect{| +val noop_annotated : 'a t -> 'a -> 'a = +|}] + +let noop_merged t a = + match t, a with + | IntLit, x + | BoolLit, x -> x +;; + +[%%expect{| +Line 4, characters 4-11: +4 | | BoolLit, x -> x + ^^^^^^^ +Error: This pattern matches values of type bool t + but a pattern was expected which matches values of type int t + Type bool is not compatible with type int +|}] + +let noop_merged_annotated (type a) (t : a t) (a : a) : a = + match t, a with + | IntLit, x + | BoolLit, x -> x +;; + +[%%expect{| +val noop_merged_annotated : 'a t -> 'a -> 'a = +|}] + +(***) + +type _ t2 = + | Int : int -> int t2 + | Bool : bool -> bool t2 + +[%%expect{| +type _ t2 = Int : int -> int t2 | Bool : bool -> bool t2 +|}] + +let trivial2 t2 = + match t2 with + | Int _ -> () + | Bool _ -> () +;; + +[%%expect{| +Line 4, characters 4-10: +4 | | Bool _ -> () + ^^^^^^ +Error: This pattern matches values of type bool t2 + but a pattern was expected which matches values of type int t2 + Type bool is not compatible with type int +|}] + +let trivial2_annotated (type a) (t2 : a t2) = + match t2 with + | Int _ -> () + | Bool _ -> () +;; + +[%%expect{| +val trivial2_annotated : 'a t2 -> unit = +|}] + +let trivial2_merged t2 = + match t2 with + | Int _ + | Bool _ -> () +;; + +[%%expect{| +Line 4, characters 4-10: +4 | | Bool _ -> () + ^^^^^^ +Error: This pattern matches values of type bool t2 + but a pattern was expected which matches values of type int t2 + Type bool is not compatible with type int +|}] + +let trivial2_merged_annotated (type a) (t2 : a t2) = + match t2 with + | Int _ + | Bool _ -> () +;; + +[%%expect{| +val trivial2_merged_annotated : 'a t2 -> unit = +|}] + + +let extract t2 = + match t2 with + | Int _ -> x + | Bool _ -> x +;; + +[%%expect{| +Line 4, characters 4-10: +4 | | Bool _ -> x + ^^^^^^ +Error: This pattern matches values of type bool t2 + but a pattern was expected which matches values of type int t2 + Type bool is not compatible with type int +|}] + +let extract_annotated (type a) (t2 : a t2) : a = + match t2 with + | Int x -> x + | Bool x -> x +;; + +[%%expect{| +val extract_annotated : 'a t2 -> 'a = +|}] + +let extract_merged t2 = + match t2 with + | Int x + | Bool x -> x +;; + +[%%expect{| +Line 4, characters 4-10: +4 | | Bool x -> x + ^^^^^^ +Error: This pattern matches values of type bool t2 + but a pattern was expected which matches values of type int t2 + Type bool is not compatible with type int +|}] + +let extract_merged_annotated (type a) (t2 : a t2) : a = + match t2 with + | Int x + | Bool x -> x +;; + + +[%%expect{| +Line 3, characters 4-20: +3 | ....Int x +4 | | Bool x..... +Error: The variable x on the left-hand side of this or-pattern has type + int but on the right-hand side it has type bool +|}] + +let extract_merged_super_annotated (type a) (t2 : a t2) : a = + match t2 with + | Int (x : a) + | Bool (x : a) -> x +;; + +[%%expect{| +val extract_merged_super_annotated : 'a t2 -> 'a = +|}] + +let extract_merged_too_lightly_annotated (type a) (t2 : a t2) : a = + match t2 with + | Int (x : a) + | Bool x -> x +;; + +[%%expect{| +Line 3, characters 4-26: +3 | ....Int (x : a) +4 | | Bool x..... +Error: The variable x on the left-hand side of this or-pattern has type + a but on the right-hand side it has type bool +|}] + +let extract_merged_super_lightly_annotated (type a) (t2 : a t2) = + match t2 with + | Int (x : a) + | Bool (x : a) -> x +;; + +[%%expect{| +val extract_merged_super_lightly_annotated : 'a t2 -> 'a = +|}] + +let lambiguity (type a) (t2 : a t2) = + match t2 with + | Int ((_ : a) as x) + | Bool (x : a) -> x +;; + +[%%expect{| +Line 3, characters 8-22: +3 | | Int ((_ : a) as x) + ^^^^^^^^^^^^^^ +Error: This pattern matches values of type a + This instance of a is ambiguous: + it would escape the scope of its equation +|}] + +let rambiguity (type a) (t2 : a t2) = + match t2 with + | Int (_ as x) + | Bool ((_ : a) as x) -> x +;; + +[%%expect{| +Line 4, characters 9-23: +4 | | Bool ((_ : a) as x) -> x + ^^^^^^^^^^^^^^ +Error: This pattern matches values of type a + This instance of a is ambiguous: + it would escape the scope of its equation +|}] + + +(***) + +type _ t3 = + | A : int t3 + | B : int t3 + +[%%expect{| +type _ t3 = A : int t3 | B : int t3 +|}] + +(* This was always allowed as the branches can unify. *) +let not_annotated x = + match x with + | A | B -> 3 +;; + +[%%expect{| +val not_annotated : int t3 -> int = +|}] + +let return_int (type a) (x : a t3) = + match x with + | A | B -> 3 +;; + +[%%expect{| +val return_int : 'a t3 -> int = +|}] + +let return_a (type a) (x : a t3) : a = + match x with + | A | B -> 3 (* fails because the equation [a = int] doesn't escape any of + the branches of this or-pattern. *) +;; + +[%%expect{| +Line 3, characters 13-14: +3 | | A | B -> 3 (* fails because the equation [a = int] doesn't escape any of + ^ +Error: This expression has type int but an expression was expected of type a +|}] + +(* Making sure we don't break a frequent pattern of GADTs indexed by polymorphic + variants, where or-patterns were already accepted under or-patterns. *) + +type any = [ `A | `B | `C | `D | `E | `F ] + +type voyel = [ `A | `E ] + +type _ letter = + | A : [< any > `A ] letter + | B : [< any > `B ] letter + | C : [< any > `C ] letter + | D : [< any > `D ] letter + | E : [< any > `E ] letter + | F : [< any > `F ] letter + +type _ cased = + | Up : 'a letter -> ([< any ] as 'a) cased + | Lo : 'a letter -> ([< any ] as 'a) cased + +type gvoyel = voyel cased +type a = [ `A ] cased +;; +[%%expect{| +type any = [ `A | `B | `C | `D | `E | `F ] +type voyel = [ `A | `E ] +type _ letter = + A : [< any > `A ] letter + | B : [< any > `B ] letter + | C : [< any > `C ] letter + | D : [< any > `D ] letter + | E : [< any > `E ] letter + | F : [< any > `F ] letter +type _ cased = + Up : 'a letter -> ([< any ] as 'a) cased + | Lo : 'a letter -> ([< any ] as 'a) cased +type gvoyel = voyel cased +type a = [ `A ] cased +|}] + +let gvoyel_of_a : a -> gvoyel = function + | Up A | Lo A as a -> a +;; +[%%expect{| +val gvoyel_of_a : a -> gvoyel = +|}] + +(* Some other illustrations of the issues with as-patterns. *) + +let f_ok (type a) (t : a t) (a : bool iref) (b : a iref) = + match t, a, b with + | IntLit, ({ content = true } as x), _ + | BoolLit, _, ({ content = true} as x) -> ignore x + | _, _, _ -> () +;; +[%%expect{| +val f_ok : 'a t -> bool iref -> 'a iref -> unit = +|}] + + +let f_amb (type a) (t : a t) (a : bool ref) (b : a ref) = + match t, a, b with + | IntLit, ({ contents = true } as x), _ + | BoolLit, _, ({ contents = true} as x) -> ignore x + | _, _, _ -> () +;; +[%%expect{| +Line 3, characters 4-108: +3 | ....IntLit, ({ contents = true } as x), _ +4 | | BoolLit, _, ({ contents = true} as x)............ +Error: The variable x on the left-hand side of this or-pattern has type + bool ref + but on the right-hand side it has type a ref + Type bool is not compatible with type a +|}] + +(********************************************) + +type t = + | A : 'a -> t + | B : 'a -> t +;; +[%%expect{| +type t = A : 'a -> t | B : 'a -> t +|}] + +let f = function + | A x + | B x -> ignore x +;; +[%%expect{| +Line 2, characters 6-7: +2 | | A x + ^ +Error: This pattern matches values of type $A_'a + The type constructor $A_'a would escape its scope +|}] diff --git a/testsuite/tests/typing-gadts/pr5332.ml b/testsuite/tests/typing-gadts/pr5332.ml index 9747cb9b..f81fff49 100644 --- a/testsuite/tests/typing-gadts/pr5332.ml +++ b/testsuite/tests/typing-gadts/pr5332.ml @@ -26,9 +26,9 @@ type ('env, 'a) typ = Tint : ('env, int) typ | Tbool : ('env, bool) typ | Tvar : ('env, 'a) var -> ('env, 'a) typ -Line _, characters 5-6: - | _ -> . (* error *) - ^ +Line 15, characters 5-6: +15 | | _ -> . (* error *) + ^ Error: This match case could not be refuted. Here is an example of a value that would reach it: (Tint, Tvar Zero) |}];; diff --git a/testsuite/tests/typing-gadts/pr5689.ml b/testsuite/tests/typing-gadts/pr5689.ml index 49375c0f..172ea5b2 100644 --- a/testsuite/tests/typing-gadts/pr5689.ml +++ b/testsuite/tests/typing-gadts/pr5689.ml @@ -100,9 +100,9 @@ let rec process : type a. a linkp2 -> ast_t -> a inline_t = ;; [%%expect{| type _ linkp2 = Kind : 'a linkp -> ([< inkind ] as 'a) linkp2 -Line _, characters 35-43: - | (Kind _, Ast_Text txt) -> Text txt - ^^^^^^^^ +Line 7, characters 35-43: +7 | | (Kind _, Ast_Text txt) -> Text txt + ^^^^^^^^ Error: This expression has type ([< inkind > `Nonlink ] as 'a) inline_t but an expression was expected of type a inline_t Type 'a = [< `Link | `Nonlink > `Nonlink ] is not compatible with type diff --git a/testsuite/tests/typing-gadts/pr5785.ml b/testsuite/tests/typing-gadts/pr5785.ml index 671f88cc..96eed8fd 100644 --- a/testsuite/tests/typing-gadts/pr5785.ml +++ b/testsuite/tests/typing-gadts/pr5785.ml @@ -13,10 +13,10 @@ struct | Two, Two -> "four" end;; [%%expect{| -Line _, characters 43-100: - ...........................................function - | One, One -> "two" - | Two, Two -> "four" +Line 7, characters 43-100: +7 | ...........................................function +8 | | One, One -> "two" +9 | | Two, Two -> "four" Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (Two, One) diff --git a/testsuite/tests/typing-gadts/pr5906.ml b/testsuite/tests/typing-gadts/pr5906.ml index b3c19827..ad62ef09 100644 --- a/testsuite/tests/typing-gadts/pr5906.ml +++ b/testsuite/tests/typing-gadts/pr5906.ml @@ -27,12 +27,12 @@ type (_, _, _) binop = Eq : ('a, 'a, bool) binop | Leq : ('a, 'a, bool) binop | Add : (int, int, int) binop -Line _, characters 2-195: - ..match bop, x, y with - | Eq, Bool x, Bool y -> Bool (if x then y else not y) - | Leq, Int x, Int y -> Bool (x <= y) - | Leq, Bool x, Bool y -> Bool (x <= y) - | Add, Int x, Int y -> Int (x + y) +Line 12, characters 2-195: +12 | ..match bop, x, y with +13 | | Eq, Bool x, Bool y -> Bool (if x then y else not y) +14 | | Leq, Int x, Int y -> Bool (x <= y) +15 | | Leq, Bool x, Bool y -> Bool (x <= y) +16 | | Add, Int x, Int y -> Int (x + y) Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (Eq, Int _, _) diff --git a/testsuite/tests/typing-gadts/pr5948.ml b/testsuite/tests/typing-gadts/pr5948.ml index 59852564..29547ea6 100644 --- a/testsuite/tests/typing-gadts/pr5948.ml +++ b/testsuite/tests/typing-gadts/pr5948.ml @@ -39,9 +39,9 @@ val intB : [< `TagB ] -> int = val intAorB : [< `TagA of int | `TagB ] -> int = type _ wrapPoly = WrapPoly : 'a poly -> ([< `TagA of int | `TagB ] as 'a) wrapPoly -Line _, characters 23-27: - | WrapPoly ATag -> intA - ^^^^ +Line 25, characters 23-27: +25 | | WrapPoly ATag -> intA + ^^^^ Error: This expression has type ([< `TagA of 'b ] as 'a) -> 'b but an expression was expected of type a -> int Type [< `TagA of 'b ] as 'a is not compatible with type @@ -52,8 +52,8 @@ Error: This expression has type ([< `TagA of 'b ] as 'a) -> 'b let _ = example6 (WrapPoly AandBTags) `TagB (* This causes a seg fault *) ;; [%%expect{| -Line _, characters 9-17: - let _ = example6 (WrapPoly AandBTags) `TagB (* This causes a seg fault *) - ^^^^^^^^ +Line 1, characters 9-17: +1 | let _ = example6 (WrapPoly AandBTags) `TagB (* This causes a seg fault *) + ^^^^^^^^ Error: Unbound value example6 |}];; diff --git a/testsuite/tests/typing-gadts/pr5981.ml b/testsuite/tests/typing-gadts/pr5981.ml index 4d6d69e9..ba8c7e42 100644 --- a/testsuite/tests/typing-gadts/pr5981.ml +++ b/testsuite/tests/typing-gadts/pr5981.ml @@ -12,9 +12,9 @@ module F(S : sig type 'a t end) = struct | A, B -> "f A B" end;; [%%expect{| -Line _, characters 47-84: - ...............................................match l, r with - | A, B -> "f A B" +Line 7, characters 47-84: +7 | ...............................................match l, r with +8 | | A, B -> "f A B" Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (A, A) @@ -39,9 +39,9 @@ module F(S : sig type 'a t end) = struct | A, B -> "f A B" end;; [%%expect{| -Line _, characters 15-52: - ...............match l, r with - | A, B -> "f A B" +Line 10, characters 15-52: +10 | ...............match l, r with +11 | | A, B -> "f A B" Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (A, A) diff --git a/testsuite/tests/typing-gadts/pr5985.ml b/testsuite/tests/typing-gadts/pr5985.ml index 06c5125b..72bbd278 100644 --- a/testsuite/tests/typing-gadts/pr5985.ml +++ b/testsuite/tests/typing-gadts/pr5985.ml @@ -8,9 +8,9 @@ module F (S : sig type 'a s end) = struct type _ t = T : 'a -> 'a s t end;; (* fail *) [%%expect{| -Line _, characters 2-29: - type _ t = T : 'a -> 'a s t - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 2-29: +3 | type _ t = T : 'a -> 'a s t + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In this definition, a type variable cannot be deduced from the type parameters. |}];; @@ -37,9 +37,9 @@ module F(T:sig type 'a t end) = struct object constraint 'a = 'b T.t val x' : 'b = x method x = x' end end;; (* fail *) [%%expect{| -Line _, characters 2-86: - ..class ['a] c x = - object constraint 'a = 'b T.t val x' : 'b = x method x = x' end +Line 2, characters 2-86: +2 | ..class ['a] c x = +3 | object constraint 'a = 'b T.t val x' : 'b = x method x = x' end Error: In this definition, a type variable cannot be deduced from the type parameters. |}];; @@ -51,18 +51,18 @@ let magic (x : int) : bool = let A x = A x in x;; (* fail *) [%%expect{| -Line _, characters 0-49: - type 'x t = A of 'a constraint 'x = [< `X of 'a ] ;; (* fail *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-49: +1 | type 'x t = A of 'a constraint 'x = [< `X of 'a ] ;; (* fail *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In this definition, a type variable cannot be deduced from the type parameters. |}];; type 'a t = A : 'a -> [< `X of 'a ] t;; (* fail *) [%%expect{| -Line _, characters 0-37: - type 'a t = A : 'a -> [< `X of 'a ] t;; (* fail *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-37: +1 | type 'a t = A : 'a -> [< `X of 'a ] t;; (* fail *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In this definition, a type variable cannot be deduced from the type parameters. |}];; @@ -77,9 +77,9 @@ type _ t = T : 'a -> 'a Queue.t t;; (* fail *) type (_, _) eq = Eq : ('a, 'a) eq val eq : 'a = val eq : ('a Queue.t, 'b Queue.t) eq = Eq -Line _, characters 0-33: - type _ t = T : 'a -> 'a Queue.t t;; (* fail *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 5, characters 0-33: +5 | type _ t = T : 'a -> 'a Queue.t t;; (* fail *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In this definition, a type variable cannot be deduced from the type parameters. |}];; @@ -95,18 +95,18 @@ module type S = sig type _ t = T : 'a -> 'a s t end;; (* fail *) [%%expect{| -Line _, characters 2-29: - type _ t = T : 'a -> 'a s t - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 2-29: +3 | type _ t = T : 'a -> 'a s t + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In this definition, a type variable cannot be deduced from the type parameters. |}];; (* Otherwise we can write the following *) module rec M : (S with type 'a s = unit) = M;; [%%expect{| -Line _, characters 16-17: - module rec M : (S with type 'a s = unit) = M;; - ^ +Line 1, characters 16-17: +1 | module rec M : (S with type 'a s = unit) = M;; + ^ Error: Unbound module type S |}];; (* For the above reason, we cannot allow the abstract declaration @@ -129,14 +129,14 @@ type 'a q = Q;; type +'a t = 'b constraint 'a = 'b q;; [%%expect{| type 'a q = Q -Line _, characters 0-36: - type +'a t = 'b constraint 'a = 'b q;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 0-36: +2 | type +'a t = 'b constraint 'a = 'b q;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In this definition, a type variable has a variance that cannot be deduced from the type parameters. It was expected to be unrestricted, but it is covariant. |}];; -(* shoud fail: we do not know for sure the variance of Queue.t *) +(* should fail: we do not know for sure the variance of Queue.t *) type +'a t = T of 'a;; type +'a s = 'b constraint 'a = 'b t;; (* ok *) @@ -146,9 +146,9 @@ type +'a s = 'b constraint 'a = 'b t |}];; type -'a s = 'b constraint 'a = 'b t;; (* fail *) [%%expect{| -Line _, characters 0-36: - type -'a s = 'b constraint 'a = 'b t;; (* fail *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-36: +1 | type -'a s = 'b constraint 'a = 'b t;; (* fail *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In this definition, a type variable has a variance that is not reflected by its occurrence in type parameters. It was expected to be contravariant, but it is covariant. @@ -167,9 +167,9 @@ type +'a s = 'b constraint 'a = 'b q t |}];; type +'a s = 'b constraint 'a = 'b t q;; (* fail *) [%%expect{| -Line _, characters 0-38: - type +'a s = 'b constraint 'a = 'b t q;; (* fail *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-38: +1 | type +'a s = 'b constraint 'a = 'b t q;; (* fail *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In this definition, a type variable has a variance that cannot be deduced from the type parameters. It was expected to be unrestricted, but it is covariant. @@ -195,9 +195,9 @@ type +'a t = unit constraint 'a = 'b list;; type _ g = G : 'a -> 'a t g;; (* fail *) [%%expect{| type +'a t = unit constraint 'a = 'b list -Line _, characters 0-27: - type _ g = G : 'a -> 'a t g;; (* fail *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 0-27: +2 | type _ g = G : 'a -> 'a t g;; (* fail *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In this definition, a type variable cannot be deduced from the type parameters. |}];; diff --git a/testsuite/tests/typing-gadts/pr5989.ml b/testsuite/tests/typing-gadts/pr5989.ml index 3b51c9cd..2c4fdc31 100644 --- a/testsuite/tests/typing-gadts/pr5989.ml +++ b/testsuite/tests/typing-gadts/pr5989.ml @@ -25,9 +25,9 @@ let () = print_endline (f M.eq) ;; [%%expect{| type (_, _) t = Any : ('a, 'b) t | Eq : ('a, 'a) t module M : sig type s = private [> `A ] val eq : (s, [ `A | `B ]) t end -Line _, characters 39-64: - .......................................function - | Any -> "Any" +Line 16, characters 39-64: +16 | .......................................function +17 | | Any -> "Any" Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Eq @@ -55,9 +55,9 @@ module N : type s = private < a : int; .. > val eq : (s, < a : int; b : bool >) t end -Line _, characters 49-74: - .................................................function - | Any -> "Any" +Line 12, characters 49-74: +12 | .................................................function +13 | | Any -> "Any" Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Eq diff --git a/testsuite/tests/typing-gadts/pr5997.ml b/testsuite/tests/typing-gadts/pr5997.ml index f9ca2cf8..27e35b35 100644 --- a/testsuite/tests/typing-gadts/pr5997.ml +++ b/testsuite/tests/typing-gadts/pr5997.ml @@ -22,9 +22,9 @@ match M.comp with | Diff -> false;; type (_, _) comp = Eq : ('a, 'a) comp | Diff : ('a, 'b) comp module U : sig type t = T end module M : sig type t = T val comp : (U.t, t) comp end -Line _, characters 0-33: - match M.comp with | Diff -> false;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 16, characters 0-33: +16 | match M.comp with | Diff -> false;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Eq @@ -45,9 +45,9 @@ match M.comp with | Diff -> false;; [%%expect{| module U : sig type t = { x : int; } end module M : sig type t = { x : int; } val comp : (U.t, t) comp end -Line _, characters 0-33: - match M.comp with | Diff -> false;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 11, characters 0-33: +11 | match M.comp with | Diff -> false;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Eq diff --git a/testsuite/tests/typing-gadts/pr6158.ml b/testsuite/tests/typing-gadts/pr6158.ml index c52fa026..711304bb 100644 --- a/testsuite/tests/typing-gadts/pr6158.ml +++ b/testsuite/tests/typing-gadts/pr6158.ml @@ -15,9 +15,9 @@ struct let f : ('a S.s, 'a S.t) eq -> unit = function Refl -> () end;; type 'a t = T of 'a type 'a s = S of 'a type (_, _) eq = Refl : ('a, 'a) eq -Line _, characters 45-49: - let f : (int s, int t) eq -> unit = function Refl -> ();; - ^^^^ +Line 6, characters 45-49: +6 | let f : (int s, int t) eq -> unit = function Refl -> ();; + ^^^^ Error: This pattern matches values of type (int s, int s) eq but a pattern was expected which matches values of type (int s, int t) eq diff --git a/testsuite/tests/typing-gadts/pr6163.ml b/testsuite/tests/typing-gadts/pr6163.ml index 38642f32..cf06eaf5 100644 --- a/testsuite/tests/typing-gadts/pr6163.ml +++ b/testsuite/tests/typing-gadts/pr6163.ml @@ -24,9 +24,9 @@ type aux = Aux : [ `Succ of [< [< [< [ `Zero ] pre_nat ] pre_nat ] pre_nat ] ] nat -> aux -Line _, characters 4-5: - | _ -> . (* error *) - ^ +Line 14, characters 4-5: +14 | | _ -> . (* error *) + ^ Error: This match case could not be refuted. Here is an example of a value that would reach it: Succ (Succ (Succ (Succ (Succ Zero)))) diff --git a/testsuite/tests/typing-gadts/pr6174.ml b/testsuite/tests/typing-gadts/pr6174.ml index fbf799a6..9f672c4f 100644 --- a/testsuite/tests/typing-gadts/pr6174.ml +++ b/testsuite/tests/typing-gadts/pr6174.ml @@ -7,9 +7,9 @@ let f : type a o. ((a -> o) -> o) t -> (a -> o) -> o = fun C k -> k (fun x -> x);; [%%expect{| type _ t = C : ((('a -> 'o) -> 'o) -> ('b -> 'o) -> 'o) t -Line _, characters 24-25: - fun C k -> k (fun x -> x);; - ^ +Line 3, characters 24-25: +3 | fun C k -> k (fun x -> x);; + ^ Error: This expression has type $0 but an expression was expected of type $1 = ($2 -> $1) -> $1 |}];; diff --git a/testsuite/tests/typing-gadts/pr6241.ml b/testsuite/tests/typing-gadts/pr6241.ml index 77f0bdff..aec74eb0 100644 --- a/testsuite/tests/typing-gadts/pr6241.ml +++ b/testsuite/tests/typing-gadts/pr6241.ml @@ -21,9 +21,9 @@ let x = N.f A;; [%%expect{| type (_, _) t = A : ('a, 'a) t | B : string -> ('a, 'b) t -Line _, characters 52-74: - ....................................................function - | B s -> s +Line 8, characters 52-74: +8 | ....................................................function +9 | | B s -> s Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: A diff --git a/testsuite/tests/typing-gadts/pr6690.ml b/testsuite/tests/typing-gadts/pr6690.ml index bfe6a353..d50e3707 100644 --- a/testsuite/tests/typing-gadts/pr6690.ml +++ b/testsuite/tests/typing-gadts/pr6690.ml @@ -26,9 +26,9 @@ type 'a local_visit_action type ('a, 'result, 'visit_action) context = Local : ('a, 'a * insert, 'a local_visit_action) context | Global : ('a, 'a, 'a visit_action) context -Line _, characters 4-9: - | Local -> fun _ -> raise Exit - ^^^^^ +Line 15, characters 4-9: +15 | | Local -> fun _ -> raise Exit + ^^^^^ Error: This pattern matches values of type ($0, $0 * insert, $0 local_visit_action) context but a pattern was expected which matches values of type @@ -41,13 +41,12 @@ type 'a local_visit_action type ('a, 'result, 'visit_action) context = Local : ('a, 'a * insert, 'a local_visit_action) context | Global : ('a, 'a, 'a visit_action) context -Line _, characters 4-10: - | Global -> fun _ -> raise Exit - ^^^^^^ -Error: This pattern matches values of type ($1, $1, visit_action) context - but a pattern was expected which matches values of type +Line 15, characters 4-9: +15 | | Local -> fun _ -> raise Exit + ^^^^^ +Error: This pattern matches values of type ($0, $0 * insert, visit_action) context - Type $1 is not compatible with type $0 + The type constructor $0 would escape its scope |}];; let vexpr (type visit_action) @@ -57,22 +56,21 @@ let vexpr (type visit_action) | Global -> fun _ -> raise Exit ;; [%%expect{| -Line _, characters 4-9: - | Local -> fun _ -> raise Exit - ^^^^^ +Line 4, characters 4-9: +4 | | Local -> fun _ -> raise Exit + ^^^^^ Error: This pattern matches values of type ($'a, $'a * insert, $'a local_visit_action) context but a pattern was expected which matches values of type ($'a, $'a * insert, visit_action) context The type constructor $'a would escape its scope |}, Principal{| -Line _, characters 4-10: - | Global -> fun _ -> raise Exit - ^^^^^^ -Error: This pattern matches values of type ($1, $1, visit_action) context - but a pattern was expected which matches values of type +Line 4, characters 4-9: +4 | | Local -> fun _ -> raise Exit + ^^^^^ +Error: This pattern matches values of type ($0, $0 * insert, visit_action) context - Type $1 is not compatible with type $0 + The type constructor $0 would escape its scope |}];; let vexpr (type result) (type visit_action) diff --git a/testsuite/tests/typing-gadts/pr6934.ml b/testsuite/tests/typing-gadts/pr6934.ml index 789a0ebc..76cb0563 100644 --- a/testsuite/tests/typing-gadts/pr6934.ml +++ b/testsuite/tests/typing-gadts/pr6934.ml @@ -4,9 +4,8 @@ type nonrec t = A : t;; [%%expect{| -Line _, characters 16-21: - type nonrec t = A : t;; - ^^^^^ +Line 1, characters 16-21: +1 | type nonrec t = A : t;; + ^^^^^ Error: GADT case syntax cannot be used in a 'nonrec' block. |}] - diff --git a/testsuite/tests/typing-gadts/pr6980.ml b/testsuite/tests/typing-gadts/pr6980.ml index b2321edf..f4d53bfe 100644 --- a/testsuite/tests/typing-gadts/pr6980.ml +++ b/testsuite/tests/typing-gadts/pr6980.ml @@ -21,9 +21,9 @@ type 'a first = First : 'b t second -> ([< `Bar | `Foo ] as 'b) t first and 'a second = Second : [< `Bar | `Baz | `Foo > `Bar ] s second type aux = Aux : ([< `Bar | `Foo ] as 'a) t second * ('a -> int) -> aux val it : [< `Bar | `Foo > `Bar ] = `Bar -Line _, characters 27-29: - let g (Aux(Second, f)) = f it;; - ^^ +Line 11, characters 27-29: +11 | let g (Aux(Second, f)) = f it;; + ^^ Error: This expression has type [< `Bar | `Foo > `Bar ] but an expression was expected of type [< `Bar | `Foo ] Types for tag `Bar are incompatible diff --git a/testsuite/tests/typing-gadts/pr6993_bad.ml b/testsuite/tests/typing-gadts/pr6993_bad.ml index d480ee89..e33808a7 100644 --- a/testsuite/tests/typing-gadts/pr6993_bad.ml +++ b/testsuite/tests/typing-gadts/pr6993_bad.ml @@ -17,9 +17,9 @@ f B.eq;; [%%expect{| type (_, _) eqp = Y : ('a, 'a) eqp | N : string -> ('a, 'b) eqp -Line _, characters 36-66: - let f : ('a list, 'a) eqp -> unit = function N s -> print_string s;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 36-66: +2 | let f : ('a list, 'a) eqp -> unit = function N s -> print_string s;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Y diff --git a/testsuite/tests/typing-gadts/pr7016.ml b/testsuite/tests/typing-gadts/pr7016.ml index cb618cc7..be4f1a87 100644 --- a/testsuite/tests/typing-gadts/pr7016.ml +++ b/testsuite/tests/typing-gadts/pr7016.ml @@ -11,9 +11,9 @@ let get1 (Cons (x, _) : (_ * 'a, 'a) t) = x ;; (* warn, cf PR#6993 *) type (_, _) t = Nil : ('tl, 'tl) t | Cons : 'a * ('b, 'tl) t -> ('a * 'b, 'tl) t -Line _, characters 9-43: - let get1 (Cons (x, _) : (_ * 'a, 'a) t) = x ;; (* warn, cf PR#6993 *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 5, characters 9-43: +5 | let get1 (Cons (x, _) : (_ * 'a, 'a) t) = x ;; (* warn, cf PR#6993 *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Nil @@ -26,9 +26,9 @@ let get1' = function [%%expect{| val get1' : ('b * 'a as 'a, 'a) t -> 'b = |}, Principal{| -Line _, characters 4-7: - | Nil -> assert false ;; (* ok *) - ^^^ +Line 3, characters 4-7: +3 | | Nil -> assert false ;; (* ok *) + ^^^ Error: This pattern matches values of type ('b * 'a, 'b * 'a) t but a pattern was expected which matches values of type ('b * 'a, 'a) t diff --git a/testsuite/tests/typing-gadts/pr7160.ml b/testsuite/tests/typing-gadts/pr7160.ml index 1c7633ba..f7b94431 100644 --- a/testsuite/tests/typing-gadts/pr7160.ml +++ b/testsuite/tests/typing-gadts/pr7160.ml @@ -14,9 +14,9 @@ type _ t = | String : string -> string t | Same : 'l t -> 'l t val f : int t -> int = -Line _, characters 0-97: - type 'a tt = 'a t = - Int : int -> int tt | String : string -> string tt | Same : 'l1 t -> 'l2 tt.. +Line 4, characters 0-97: +4 | type 'a tt = 'a t = +5 | Int : int -> int tt | String : string -> string tt | Same : 'l1 t -> 'l2 tt.. Error: This variant or record definition does not match that of type 'a t The types for field Same are not equal. |}];; diff --git a/testsuite/tests/typing-gadts/pr7214.ml b/testsuite/tests/typing-gadts/pr7214.ml index 8a589ee8..a14616d7 100644 --- a/testsuite/tests/typing-gadts/pr7214.ml +++ b/testsuite/tests/typing-gadts/pr7214.ml @@ -12,9 +12,9 @@ let f (type a) (x : a t) = () ;; [%%expect{| type _ t = I : int t -Line _, characters 9-10: - let (I : a t) = x (* fail because of toplevel let *) - ^ +Line 5, characters 9-10: +5 | let (I : a t) = x (* fail because of toplevel let *) + ^ Error: This pattern matches values of type int t but a pattern was expected which matches values of type a t Type int is not compatible with type a @@ -36,9 +36,9 @@ let bad (type a) = ;; [%%expect{| type (_, _) eq = Refl : ('a, 'a) eq -Line _, characters 10-14: - let (Refl : (int, a) eq) = M.e (* must fail for soundness *) - ^^^^ +Line 8, characters 10-14: +8 | let (Refl : (int, a) eq) = M.e (* must fail for soundness *) + ^^^^ Error: This pattern matches values of type (int, int) eq but a pattern was expected which matches values of type (int, a) eq Type int is not compatible with type a diff --git a/testsuite/tests/typing-gadts/pr7222.ml b/testsuite/tests/typing-gadts/pr7222.ml index 4316e10e..683458b4 100644 --- a/testsuite/tests/typing-gadts/pr7222.ml +++ b/testsuite/tests/typing-gadts/pr7222.ml @@ -20,9 +20,9 @@ type (_, _) elt = Elt_fine : 'nat n -> ('l, 'nat * 'l) elt | Elt : 'nat n -> ('l, 'nat -> 'l) elt type _ t = Nil : nil t | Cons : ('x, 'fx) elt * 'x t -> 'fx t -Line _, characters 11-18: - let Cons(Elt dim, _) = sh in () - ^^^^^^^ +Line 9, characters 11-18: +9 | let Cons(Elt dim, _) = sh in () + ^^^^^^^ Error: This pattern matches values of type ($Cons_'x, 'a -> $Cons_'x) elt but a pattern was expected which matches values of type ($Cons_'x, 'a -> $'b -> nil) elt @@ -34,10 +34,9 @@ type (_, _) elt = Elt_fine : 'nat n -> ('l, 'nat * 'l) elt | Elt : 'nat n -> ('l, 'nat -> 'l) elt type _ t = Nil : nil t | Cons : ('x, 'fx) elt * 'x t -> 'fx t -Line _, characters 6-22: - let Cons(Elt dim, _) = sh in () - ^^^^^^^^^^^^^^^^ +Line 9, characters 6-22: +9 | let Cons(Elt dim, _) = sh in () + ^^^^^^^^^^^^^^^^ Error: This pattern matches values of type ('a -> $0 -> nil) t - but a pattern was expected which matches values of type 'b The type constructor $0 would escape its scope |}];; diff --git a/testsuite/tests/typing-gadts/pr7234.ml b/testsuite/tests/typing-gadts/pr7234.ml index 49c040ed..ae98e02c 100644 --- a/testsuite/tests/typing-gadts/pr7234.ml +++ b/testsuite/tests/typing-gadts/pr7234.ml @@ -8,9 +8,9 @@ let f (type a) (Neq n : (a, a t) eq) = n;; (* warn! *) [%%expect{| type (_, _) eq = Eq : ('a, 'a) eq | Neq : int -> ('a, 'b) eq type 'a t -Line _, characters 15-40: - let f (type a) (Neq n : (a, a t) eq) = n;; (* warn! *) - ^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 15-40: +3 | let f (type a) (Neq n : (a, a t) eq) = n;; (* warn! *) + ^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Eq @@ -21,9 +21,9 @@ module F (T : sig type _ t end) = struct let f (type a) (Neq n : (a, a T.t) eq) = n (* warn! *) end;; [%%expect{| -Line _, characters 16-43: - let f (type a) (Neq n : (a, a T.t) eq) = n (* warn! *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 16-43: +2 | let f (type a) (Neq n : (a, a T.t) eq) = n (* warn! *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Eq diff --git a/testsuite/tests/typing-gadts/pr7260.ml b/testsuite/tests/typing-gadts/pr7260.ml index d5a15673..c6f160f4 100644 --- a/testsuite/tests/typing-gadts/pr7260.ml +++ b/testsuite/tests/typing-gadts/pr7260.ml @@ -19,13 +19,13 @@ class foo = type bar = < bar : unit > type _ ty = Int : int ty type dyn = Dyn : 'a ty -> dyn -Line _, characters 0-108: - class foo = - object (this) - method foo (Dyn ty) = - match ty with - | Int -> (this :> bar) - end................................. +Line 7, characters 0-108: + 7 | class foo = + 8 | object (this) + 9 | method foo (Dyn ty) = +10 | match ty with +11 | | Int -> (this :> bar) +12 | end................................. Error: This class should be virtual. The following methods are undefined : bar |}];; diff --git a/testsuite/tests/typing-gadts/pr7269.ml b/testsuite/tests/typing-gadts/pr7269.ml index 2a07e8b5..9293eb3b 100644 --- a/testsuite/tests/typing-gadts/pr7269.ml +++ b/testsuite/tests/typing-gadts/pr7269.ml @@ -11,9 +11,9 @@ let _ = f (T (`Conj `B) :> s t);; (* warn *) type s = [ `A | `B ] and sub = [ `B ] type +'a t = T : [< `Conj of 'a & sub | `Other of string ] -> 'a t -Line _, characters 6-47: - let f (T (`Other msg) : s t) = print_string msg;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 4, characters 6-47: +4 | let f (T (`Other msg) : s t) = print_string msg;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: T (`Conj _) @@ -39,9 +39,9 @@ module M : type t = T : [< `Conj of int & s | `Other of string ] -> t val x : t end -Line _, characters 12-59: - let () = M.(match x with T (`Other msg) -> print_string msg);; (* warn *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 11, characters 12-59: +11 | let () = M.(match x with T (`Other msg) -> print_string msg);; (* warn *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: T (`Conj _) @@ -71,9 +71,9 @@ module M : } val e : elim -> unit end -Line _, characters 21-57: - let () = M.(e { ex = fun (`Other msg) -> print_string msg });; (* warn *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 13, characters 21-57: +13 | let () = M.(e { ex = fun (`Other msg) -> print_string msg });; (* warn *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: `Conj _ diff --git a/testsuite/tests/typing-gadts/pr7374.ml b/testsuite/tests/typing-gadts/pr7374.ml index f682807b..1eb4166c 100644 --- a/testsuite/tests/typing-gadts/pr7374.ml +++ b/testsuite/tests/typing-gadts/pr7374.ml @@ -21,9 +21,9 @@ end = struct fun Refl -> Refl end;; (* should fail *) [%%expect{| -Line _, characters 16-20: - fun Refl -> Refl - ^^^^ +Line 7, characters 16-20: +7 | fun Refl -> Refl + ^^^^ Error: This expression has type (a, a) eq but an expression was expected of type (a, t) eq Type a is not compatible with type t = [ `Rec of 'a ] X.t as 'a @@ -47,9 +47,9 @@ module F (X : sig type 'a t end) = struct fun Refl Refl -> Refl;; end;; (* should fail *) [%%expect{| -Line _, characters 21-25: - fun Refl Refl -> Refl;; - ^^^^ +Line 4, characters 21-25: +4 | fun Refl Refl -> Refl;; + ^^^^ Error: This expression has type (a, a) eq but an expression was expected of type (a, a X.t X.t) eq Type a = b X.t is not compatible with type a X.t X.t diff --git a/testsuite/tests/typing-gadts/pr7378.ml b/testsuite/tests/typing-gadts/pr7378.ml index 190fbfdc..d7767033 100644 --- a/testsuite/tests/typing-gadts/pr7378.ml +++ b/testsuite/tests/typing-gadts/pr7378.ml @@ -15,9 +15,9 @@ module Y = struct | A : 'a * 'b * ('b -> unit) -> t end;; (* should fail *) [%%expect{| -Line _, characters 2-54: - ..type t = X.t = - | A : 'a * 'b * ('b -> unit) -> t +Line 2, characters 2-54: +2 | ..type t = X.t = +3 | | A : 'a * 'b * ('b -> unit) -> t Error: This variant or record definition does not match that of type X.t The types for field A are not equal. |}] diff --git a/testsuite/tests/typing-gadts/pr7390.ml b/testsuite/tests/typing-gadts/pr7390.ml index 29e23ae7..2a988e1c 100644 --- a/testsuite/tests/typing-gadts/pr7390.ml +++ b/testsuite/tests/typing-gadts/pr7390.ml @@ -21,9 +21,9 @@ type 'fill either = let f (* : filled either -> string *) = fun (Either (Y a, N)) -> a;; [%%expect{| -Line _, characters 2-28: - fun (Either (Y a, N)) -> a;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 2-28: +2 | fun (Either (Y a, N)) -> a;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Either (N, Y _) diff --git a/testsuite/tests/typing-gadts/pr7421.ml b/testsuite/tests/typing-gadts/pr7421.ml index a17a774e..79acaceb 100644 --- a/testsuite/tests/typing-gadts/pr7421.ml +++ b/testsuite/tests/typing-gadts/pr7421.ml @@ -13,9 +13,9 @@ let f (x : ('a, empty Lazy.t) result) = | Ok x -> x | Error (lazy _) -> .;; [%%expect{| -Line _, characters 4-18: - | Error (lazy _) -> .;; - ^^^^^^^^^^^^^^ +Line 4, characters 4-18: +4 | | Error (lazy _) -> .;; + ^^^^^^^^^^^^^^ Error: This match case could not be refuted. Here is an example of a value that would reach it: Error lazy _ |}] @@ -24,9 +24,9 @@ let f (x : ('a, empty Lazy.t) result) = | Ok x -> x | Error (lazy Refl) -> .;; [%%expect{| -Line _, characters 16-20: - | Error (lazy Refl) -> .;; - ^^^^ +Line 4, characters 16-20: +4 | | Error (lazy Refl) -> .;; + ^^^^ Error: This pattern matches values of type (int, int) eq but a pattern was expected which matches values of type empty = (int, unit) eq diff --git a/testsuite/tests/typing-gadts/pr7432.ml b/testsuite/tests/typing-gadts/pr7432.ml index 0eb9b601..014fd7e4 100644 --- a/testsuite/tests/typing-gadts/pr7432.ml +++ b/testsuite/tests/typing-gadts/pr7432.ml @@ -21,9 +21,9 @@ let f : [`L of (s, t) eql | `R of silly] -> 'a = function `R {silly} -> silly ;; [%%expect{| -Line _, characters 2-30: - function `R {silly} -> silly - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 2-30: +2 | function `R {silly} -> silly + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: `L Refl diff --git a/testsuite/tests/typing-gadts/pr7618.ml b/testsuite/tests/typing-gadts/pr7618.ml index 5227bd65..ce98c531 100644 --- a/testsuite/tests/typing-gadts/pr7618.ml +++ b/testsuite/tests/typing-gadts/pr7618.ml @@ -19,11 +19,10 @@ let ok (type a b) (x : (a, b) eq) = ;; [%%expect{| type ('a, 'b) eq = Refl : ('a, 'a) eq -Line _, characters 4-29: - | Refl, [(_ : a) | (_ : b)] -> [] - ^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 4, characters 4-29: +4 | | Refl, [(_ : a) | (_ : b)] -> [] + ^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This pattern matches values of type (a, b) eq * b list - but a pattern was expected which matches values of type 'a This instance of b is ambiguous: it would escape the scope of its equation |}] @@ -33,11 +32,10 @@ let fails (type a b) (x : (a, b) eq) = | Refl, [(_ : b) | (_ : a)] -> [] ;; [%%expect{| -Line _, characters 4-29: - | Refl, [(_ : a) | (_ : b)] -> [] - ^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 4-29: +3 | | Refl, [(_ : a) | (_ : b)] -> [] + ^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This pattern matches values of type (a, b) eq * b list - but a pattern was expected which matches values of type 'a This instance of b is ambiguous: it would escape the scope of its equation |}] @@ -45,9 +43,9 @@ Error: This pattern matches values of type (a, b) eq * b list (* branches must be unified! *) let x = match [] with ["1"] -> 1 | [1.0] -> 2 | [1] -> 3 | _ -> 4;; [%%expect{| -Line _, characters 35-40: - let x = match [] with ["1"] -> 1 | [1.0] -> 2 | [1] -> 3 | _ -> 4;; - ^^^^^ +Line 1, characters 35-40: +1 | let x = match [] with ["1"] -> 1 | [1.0] -> 2 | [1] -> 3 | _ -> 4;; + ^^^^^ Error: This pattern matches values of type float list but a pattern was expected which matches values of type string list Type float is not compatible with type string diff --git a/testsuite/tests/typing-gadts/pr7747.ml b/testsuite/tests/typing-gadts/pr7747.ml index c3620e8a..97b89061 100644 --- a/testsuite/tests/typing-gadts/pr7747.ml +++ b/testsuite/tests/typing-gadts/pr7747.ml @@ -22,9 +22,9 @@ val f : N.t -> M.t = |}] let f x = match N.eq with Refl -> (x : M.t :> N.t);; [%%expect{| -Line _, characters 34-50: - let f x = match N.eq with Refl -> (x : M.t :> N.t);; - ^^^^^^^^^^^^^^^^ +Line 1, characters 34-50: +1 | let f x = match N.eq with Refl -> (x : M.t :> N.t);; + ^^^^^^^^^^^^^^^^ Error: Type M.t is not a subtype of N.t |}] diff --git a/testsuite/tests/typing-gadts/term-conv.ml b/testsuite/tests/typing-gadts/term-conv.ml index 993b460e..436100ba 100644 --- a/testsuite/tests/typing-gadts/term-conv.ml +++ b/testsuite/tests/typing-gadts/term-conv.ml @@ -41,8 +41,8 @@ module Typeable : | Fun : ('a ty * 'b ty) -> ('a -> 'b) ty type (_, _) eq = Eq : ('a, 'a) eq exception CastFailure - val check_eq : 't ty -> 't' ty -> ('t, 't') eq - val gcast : 't ty -> 't' ty -> 't -> 't' + val check_eq : 't ty -> ' t' ty -> ('t, ' t') eq + val gcast : 't ty -> ' t' ty -> 't -> ' t' end |}];; diff --git a/testsuite/tests/typing-gadts/test.ml b/testsuite/tests/typing-gadts/test.ml index 579dece8..61061872 100644 --- a/testsuite/tests/typing-gadts/test.ml +++ b/testsuite/tests/typing-gadts/test.ml @@ -103,16 +103,16 @@ module Nonexhaustive = end ;; [%%expect{| -Line _, characters 6-34: - ......function - | C2 x -> x +Line 11, characters 6-34: +11 | ......function +12 | | C2 x -> x Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: C1 _ -Line _, characters 6-77: - ......function - | Foo _ , Foo _ -> true - | Bar _, Bar _ -> true +Line 24, characters 6-77: +24 | ......function +25 | | Foo _ , Foo _ -> true +26 | | Bar _, Bar _ -> true Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (Bar _, Foo _) @@ -157,15 +157,15 @@ module PR6862 = struct class d (Just x) = object method x : int = x end end;; [%%expect{| -Line _, characters 10-18: - class c (Some x) = object method x : int = x end - ^^^^^^^^ +Line 2, characters 10-18: +2 | class c (Some x) = object method x : int = x end + ^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: None -Line _, characters 10-18: - class d (Just x) = object method x : int = x end - ^^^^^^^^ +Line 4, characters 10-18: +4 | class d (Just x) = object method x : int = x end + ^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Nothing @@ -192,9 +192,9 @@ module PR6220 = struct let g : int t -> int = function I -> 1 | _ -> 2 (* warn *) end;; [%%expect{| -Line _, characters 43-44: - let g : int t -> int = function I -> 1 | _ -> 2 (* warn *) - ^ +Line 4, characters 43-44: +4 | let g : int t -> int = function I -> 1 | _ -> 2 (* warn *) + ^ Warning 56: this match case is unreachable. Consider replacing it with a refutation case ' -> .' module PR6220 : @@ -260,9 +260,9 @@ module PR6801 = struct | String s -> print_endline s (* warn : Any *) end;; [%%expect{| -Line _, characters 4-50: - ....match x with - | String s -> print_endline s................. +Line 8, characters 4-50: +8 | ....match x with +9 | | String s -> print_endline s................. Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Any @@ -284,9 +284,9 @@ module Existential_escape = end ;; [%%expect{| -Line _, characters 21-22: - let eval (D x) = x - ^ +Line 5, characters 21-22: +5 | let eval (D x) = x + ^ Error: This expression has type $D_'a t but an expression was expected of type 'a The type constructor $D_'a would escape its scope @@ -317,12 +317,11 @@ module Or_patterns = end ;; [%%expect{| -Line _, characters 11-19: - | (IntLit _ | BoolLit _) -> () - ^^^^^^^^ -Error: This pattern matches values of type int t - but a pattern was expected which matches values of type s t - Type int is not compatible with type s +module Or_patterns : + sig + type _ t = IntLit : int -> int t | BoolLit : bool -> bool t + val eval : 's t -> unit + end |}];; module Polymorphic_variants = @@ -368,9 +367,9 @@ module Propagation : val check : 's t -> 's end |}, Principal{| -Line _, characters 19-20: - | BoolLit b -> b - ^ +Line 13, characters 19-20: +13 | | BoolLit b -> b + ^ Error: This expression has type bool but an expression was expected of type s |}];; @@ -381,15 +380,15 @@ module Normal_constrs = struct let f = function A -> 1 | B -> 2 end;; [%%expect{| -Line _, characters 28-29: - let f = function A -> 1 | B -> 2 - ^ +Line 5, characters 28-29: +5 | let f = function A -> 1 | B -> 2 + ^ Error: This variant pattern is expected to have type a The constructor B does not belong to type a |}, Principal{| -Line _, characters 28-29: - let f = function A -> 1 | B -> 2 - ^ +Line 5, characters 28-29: +5 | let f = function A -> 1 | B -> 2 + ^ Error: This pattern matches values of type b but a pattern was expected which matches values of type a |}];; @@ -401,9 +400,9 @@ module PR6849 = struct Foo -> 5 end;; [%%expect{| -Line _, characters 6-9: - Foo -> 5 - ^^^ +Line 5, characters 6-9: +5 | Foo -> 5 + ^^^ Error: This pattern matches values of type 'a t but a pattern was expected which matches values of type int |}];; @@ -432,9 +431,9 @@ let test : type a. a t -> _ = function Int -> ky (1 : a) 1 (* fails *) ;; [%%expect{| -Line _, characters 18-30: - function Int -> ky (1 : a) 1 (* fails *) - ^^^^^^^^^^^^ +Line 2, characters 18-30: +2 | function Int -> ky (1 : a) 1 (* fails *) + ^^^^^^^^^^^^ Error: This expression has type a = int but an expression was expected of type 'a This instance of int is ambiguous: @@ -446,9 +445,9 @@ let test : type a. a t -> a = fun x -> in r ;; [%%expect{| -Line _, characters 30-42: - let r = match x with Int -> ky (1 : a) 1 (* fails *) - ^^^^^^^^^^^^ +Line 2, characters 30-42: +2 | let r = match x with Int -> ky (1 : a) 1 (* fails *) + ^^^^^^^^^^^^ Error: This expression has type a = int but an expression was expected of type 'a This instance of int is ambiguous: @@ -460,9 +459,9 @@ let test : type a. a t -> a = fun x -> in r ;; [%%expect{| -Line _, characters 30-42: - let r = match x with Int -> ky 1 (1 : a) (* fails *) - ^^^^^^^^^^^^ +Line 2, characters 30-42: +2 | let r = match x with Int -> ky 1 (1 : a) (* fails *) + ^^^^^^^^^^^^ Error: This expression has type a = int but an expression was expected of type 'a This instance of int is ambiguous: @@ -536,9 +535,9 @@ let test2 : type a. a t -> a option = fun x -> !u ;; (* fails because u : (int | a) option ref *) [%%expect{| -Line _, characters 46-48: - begin match x with Int -> u := Some 1; r := !u end; - ^^ +Line 4, characters 46-48: +4 | begin match x with Int -> u := Some 1; r := !u end; + ^^ Error: This expression has type int option but an expression was expected of type a option Type int is not compatible with type a = int @@ -574,9 +573,9 @@ let we_y1x (type a) (x : a) (v : a t) = ;; (* fail *) [%%expect{| val either : 'a -> 'a -> 'a = -Line _, characters 44-45: - match v with Int -> let y = either 1 x in y - ^ +Line 3, characters 44-45: +3 | match v with Int -> let y = either 1 x in y + ^ Error: This expression has type a = int but an expression was expected of type 'a This instance of int is ambiguous: @@ -635,9 +634,9 @@ let f (type a) (x : a t) y = in M.z ;; (* fails because of aliasing... *) [%%expect{| -Line _, characters 46-47: - let module M = struct type b = a let z = (y : b) end - ^ +Line 3, characters 46-47: +3 | let module M = struct type b = a let z = (y : b) end + ^ Error: This expression has type a = int but an expression was expected of type b = int This instance of int is ambiguous: @@ -688,9 +687,9 @@ let f : type a b. (a,b) eq -> ( as 'c) -> ( as 'c) = ;; (* fail *) [%%expect{| type (_, _) eq = Eq : ('a, 'a) eq -Line _, characters 4-90: - ....f : type a b. (a,b) eq -> ( as 'c) -> ( as 'c) = - fun Eq o -> o +Line 3, characters 4-90: +3 | ....f : type a b. (a,b) eq -> ( as 'c) -> ( as 'c) = +4 | fun Eq o -> o Error: The universal type variable 'b cannot be generalized: it is already bound to another variable. |}];; @@ -699,9 +698,9 @@ let f : type a b. (a,b) eq -> -> = fun Eq o -> o ;; (* fail *) [%%expect{| -Line _, characters 14-15: - fun Eq o -> o - ^ +Line 2, characters 14-15: +2 | fun Eq o -> o + ^ Error: This expression has type < m : a; .. > but an expression was expected of type < m : b; .. > Type a is not compatible with type b = a @@ -712,9 +711,9 @@ Error: This expression has type < m : a; .. > let f (type a) (type b) (eq : (a,b) eq) (o : ) : = match eq with Eq -> o ;; (* should fail *) [%%expect{| -Line _, characters 22-23: - match eq with Eq -> o ;; (* should fail *) - ^ +Line 2, characters 22-23: +2 | match eq with Eq -> o ;; (* should fail *) + ^ Error: This expression has type < m : a; .. > but an expression was expected of type < m : b; .. > Type a is not compatible with type b = a @@ -752,9 +751,9 @@ let f : type a b. (a,b) eq -> < m : a; .. > -> < m : b > = [%%expect{| val f : ('a, 'b) eq -> < m : 'a > -> < m : 'b > = |}, Principal{| -Line _, characters 44-45: - let r : < m : b > = match eq with Eq -> o in (* fail with principal *) - ^ +Line 4, characters 44-45: +4 | let r : < m : b > = match eq with Eq -> o in (* fail with principal *) + ^ Error: This expression has type < m : a > but an expression was expected of type < m : b > Type a is not compatible with type b = a @@ -768,9 +767,9 @@ let f : type a b. (a,b) eq -> < m : a; .. > -> < m : b > = ignore (o : < m : a >); r;; [%%expect{| -Line _, characters 44-45: - let r : < m : b > = match eq with Eq -> o in (* fail *) - ^ +Line 3, characters 44-45: +3 | let r : < m : b > = match eq with Eq -> o in (* fail *) + ^ Error: This expression has type < m : a; .. > but an expression was expected of type < m : b > Type a is not compatible with type b = a @@ -781,18 +780,18 @@ Error: This expression has type < m : a; .. > let f : type a b. (a,b) eq -> [> `A of a] -> [> `A of b] = fun Eq o -> o ;; (* fail *) [%%expect{| -Line _, characters 14-15: - fun Eq o -> o ;; (* fail *) - ^ +Line 2, characters 14-15: +2 | fun Eq o -> o ;; (* fail *) + ^ Error: This expression has type [> `A of a ] but an expression was expected of type [> `A of b ] Type a is not compatible with type b = a This instance of a is ambiguous: it would escape the scope of its equation |}, Principal{| -Line _, characters 9-15: - fun Eq o -> o ;; (* fail *) - ^^^^^^ +Line 2, characters 9-15: +2 | fun Eq o -> o ;; (* fail *) + ^^^^^^ Error: This expression has type ([> `A of b ] as 'a) -> 'a but an expression was expected of type [> `A of a ] -> [> `A of b ] Types for tag `A are incompatible @@ -801,9 +800,9 @@ Error: This expression has type ([> `A of b ] as 'a) -> 'a let f (type a b) (eq : (a,b) eq) (v : [> `A of a]) : [> `A of b] = match eq with Eq -> v ;; (* should fail *) [%%expect{| -Line _, characters 22-23: - match eq with Eq -> v ;; (* should fail *) - ^ +Line 2, characters 22-23: +2 | match eq with Eq -> v ;; (* should fail *) + ^ Error: This expression has type [> `A of a ] but an expression was expected of type [> `A of b ] Type a is not compatible with type b = a @@ -814,9 +813,9 @@ Error: This expression has type [> `A of a ] let f : type a b. (a,b) eq -> [< `A of a | `B] -> [< `A of b | `B] = fun Eq o -> o ;; (* fail *) [%%expect{| -Line _, characters 4-84: - ....f : type a b. (a,b) eq -> [< `A of a | `B] -> [< `A of b | `B] = - fun Eq o -> o.............. +Line 1, characters 4-84: +1 | ....f : type a b. (a,b) eq -> [< `A of a | `B] -> [< `A of b | `B] = +2 | fun Eq o -> o.............. Error: This definition has type ('a, 'b) eq -> ([< `A of 'b & 'a | `B ] as 'c) -> 'c which is less general than 'a0 'b0. ('a0, 'b0) eq -> 'c -> 'c @@ -843,9 +842,9 @@ let f : type a b. (a,b) eq -> [> `A of a | `B] -> [`A of b | `B] = [%%expect{| val f : ('a, 'b) eq -> [ `A of 'a | `B ] -> [ `A of 'b | `B ] = |}, Principal{| -Line _, characters 49-50: - let r : [`A of b | `B] = match eq with Eq -> o in (* fail with principal *) - ^ +Line 4, characters 49-50: +4 | let r : [`A of b | `B] = match eq with Eq -> o in (* fail with principal *) + ^ Error: This expression has type [ `A of a | `B ] but an expression was expected of type [ `A of b | `B ] Type a is not compatible with type b = a @@ -859,9 +858,9 @@ let f : type a b. (a,b) eq -> [> `A of a | `B] -> [`A of b | `B] = ignore (o : [< `A of a | `B]); r;; [%%expect{| -Line _, characters 49-50: - let r : [`A of b | `B] = match eq with Eq -> o in (* fail *) - ^ +Line 3, characters 49-50: +3 | let r : [`A of b | `B] = match eq with Eq -> o in (* fail *) + ^ Error: This expression has type [> `A of a | `B ] but an expression was expected of type [ `A of b | `B ] Type a is not compatible with type b = a @@ -916,14 +915,14 @@ let f : type a. a ty -> a t -> int = fun x y -> | TA, D z -> z ;; (* warn *) [%%expect{| -Line _, characters 2-153: - ..match x, y with - | _, A z -> z - | _, B z -> if z then 1 else 2 - | _, C z -> truncate z - | TE TC, D [|1.0|] -> 14 - | TA, D 0 -> -1 - | TA, D z -> z +Line 2, characters 2-153: +2 | ..match x, y with +3 | | _, A z -> z +4 | | _, B z -> if z then 1 else 2 +5 | | _, C z -> truncate z +6 | | TE TC, D [|1.0|] -> 14 +7 | | TA, D 0 -> -1 +8 | | TA, D z -> z Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (TE TC, D [| 0. |]) @@ -940,9 +939,9 @@ let f : type a. a ty -> a t -> int = fun x y -> | D z, TA -> z ;; (* fail *) [%%expect{| -Line _, characters 6-13: - | D [|1.0|], TE TC -> 14 - ^^^^^^^ +Line 6, characters 6-13: +6 | | D [|1.0|], TE TC -> 14 + ^^^^^^^ Error: This pattern matches values of type 'a array but a pattern was expected which matches values of type a |}];; @@ -960,9 +959,9 @@ let f : type a. a ty -> a t -> int = fun x y -> ;; (* fail *) [%%expect{| type ('a, 'b) pair = { right : 'a; left : 'b; } -Line _, characters 25-32: - | {left=TE TC; right=D [|1.0|]} -> 14 - ^^^^^^^ +Line 8, characters 25-32: +8 | | {left=TE TC; right=D [|1.0|]} -> 14 + ^^^^^^^ Error: This pattern matches values of type 'a array but a pattern was expected which matches values of type a |}];; @@ -980,14 +979,14 @@ let f : type a. a ty -> a t -> int = fun x y -> ;; (* ok *) [%%expect{| type ('a, 'b) pair = { left : 'a; right : 'b; } -Line _, characters 2-244: - ..match {left=x; right=y} with - | {left=_; right=A z} -> z - | {left=_; right=B z} -> if z then 1 else 2 - | {left=_; right=C z} -> truncate z - | {left=TE TC; right=D [|1.0|]} -> 14 - | {left=TA; right=D 0} -> -1 - | {left=TA; right=D z} -> z +Line 4, characters 2-244: + 4 | ..match {left=x; right=y} with + 5 | | {left=_; right=A z} -> z + 6 | | {left=_; right=B z} -> if z then 1 else 2 + 7 | | {left=_; right=C z} -> truncate z + 8 | | {left=TE TC; right=D [|1.0|]} -> 14 + 9 | | {left=TA; right=D 0} -> -1 +10 | | {left=TA; right=D z} -> z Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: {left=TE TC; right=D [| 0. |]} @@ -1005,9 +1004,9 @@ let f : type a b. (a M.t, b M.t) eq -> (a, b) eq = ;; [%%expect{| module M : sig type 'a t val eq : ('a t, 'b t) eq end -Line _, characters 17-19: - function Eq -> Eq (* fail *) - ^^ +Line 6, characters 17-19: +6 | function Eq -> Eq (* fail *) + ^^ Error: This expression has type (a, a) eq but an expression was expected of type (a, b) eq Type a is not compatible with type b @@ -1061,9 +1060,9 @@ let g (type t) (x:t) (e : t int_foo) (e' : t int_bar) = [%%expect{| type _ int_foo = IF_constr : < foo : int; .. > int_foo type _ int_bar = IB_constr : < bar : int; .. > int_bar -Line _, characters 3-4: - (x:) - ^ +Line 10, characters 3-4: +10 | (x:) + ^ Error: This expression has type t = < foo : int; .. > but an expression was expected of type < foo : int > Type $0 = < bar : int; .. > is not compatible with type < > @@ -1075,9 +1074,9 @@ let g (type t) (x:t) (e : t int_foo) (e' : t int_bar) = (x:) ;; [%%expect{| -Line _, characters 3-4: - (x:) - ^ +Line 3, characters 3-4: +3 | (x:) + ^ Error: This expression has type t = < foo : int; .. > but an expression was expected of type < bar : int; foo : int > Type $0 = < bar : int; .. > is not compatible with type < bar : int > @@ -1089,9 +1088,9 @@ let g (type t) (x:t) (e : t int_foo) (e' : t int_bar) = (x:) ;; [%%expect{| -Line _, characters 2-26: - (x:) - ^^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 2-26: +3 | (x:) + ^^^^^^^^^^^^^^^^^^^^^^^^ Error: This expression has type < bar : int; foo : int; .. > but an expression was expected of type 'a The type constructor $1 would escape its scope @@ -1173,9 +1172,9 @@ let f : type a b. (a,b) eq -> (a,int) eq -> a -> b -> _ = fun ab aint a b -> in ignore x ;; (* ok *) [%%expect{| -Line _, characters 24-25: - if true then a else b - ^ +Line 5, characters 24-25: +5 | if true then a else b + ^ Error: This expression has type b = int but an expression was expected of type a = int Type b = int is not compatible with type int @@ -1191,9 +1190,9 @@ let f : type a b. (a,b) eq -> (b,int) eq -> a -> b -> _ = fun ab bint a b -> in ignore x ;; (* ok *) [%%expect{| -Line _, characters 24-25: - if true then a else b - ^ +Line 5, characters 24-25: +5 | if true then a else b + ^ Error: This expression has type b = int but an expression was expected of type a = int Type int is not compatible with type a = int @@ -1207,9 +1206,9 @@ let f (type a b c) (b : bool) (w1 : (a,b) eq) (w2 : (a,int) eq) (x : a) (y : b) if b then x else y ;; [%%expect{| -Line _, characters 19-20: - if b then x else y - ^ +Line 4, characters 19-20: +4 | if b then x else y + ^ Error: This expression has type b = int but an expression was expected of type a = int Type a = int is not compatible with type a = int @@ -1222,9 +1221,9 @@ let f (type a b c) (b : bool) (w1 : (a,b) eq) (w2 : (a,int) eq) (x : a) (y : b) let Eq = w2 in if b then y else x [%%expect{| -Line _, characters 19-20: - if b then y else x - ^ +Line 4, characters 19-20: +4 | if b then y else x + ^ Error: This expression has type a = int but an expression was expected of type b = int This instance of int is ambiguous: diff --git a/testsuite/tests/typing-gadts/unexpected_existentials.ml b/testsuite/tests/typing-gadts/unexpected_existentials.ml new file mode 100644 index 00000000..5216dc50 --- /dev/null +++ b/testsuite/tests/typing-gadts/unexpected_existentials.ml @@ -0,0 +1,158 @@ +(* TEST + * expect +*) +(** Test the error message for existential types apparearing + in unexpected position *) +type any = Any: 'a -> any +[%%expect {| +type any = Any : 'a -> any +|}] + +let Any x = Any () +[%%expect {| +Line 1, characters 4-9: +1 | let Any x = Any () + ^^^^^ +Error: Existential types are not allowed in toplevel bindings, + but this pattern introduces the existential type $Any_'a. +|}] + +let () = + let Any x = Any () and () = () in + () +[%%expect {| +Line 2, characters 6-11: +2 | let Any x = Any () and () = () in + ^^^^^ +Error: Existential types are not allowed in "let ... and ..." bindings, + but this pattern introduces the existential type $Any_'a. +|}] + + +let () = + let rec Any x = Any () in + () +[%%expect {| +Line 2, characters 10-15: +2 | let rec Any x = Any () in + ^^^^^ +Error: Existential types are not allowed in recursive bindings, + but this pattern introduces the existential type $Any_'a. +|}] + + +let () = + let[@attribute] Any x = Any () in + () +[%%expect {| +Line 2, characters 18-23: +2 | let[@attribute] Any x = Any () in + ^^^^^ +Error: Existential types are not allowed in presence of attributes, + but this pattern introduces the existential type $Any_'a. +|}] + + +class c (Any x) = object end +[%%expect {| +Line 1, characters 8-15: +1 | class c (Any x) = object end + ^^^^^^^ +Error: Existential types are not allowed in class arguments, + but this pattern introduces the existential type $Any_'a. +|}] + +class c = object(Any x)end +[%%expect {| +Line 1, characters 16-23: +1 | class c = object(Any x)end + ^^^^^^^ +Error: Existential types are not allowed in self patterns, + but this pattern introduces the existential type $Any_'a. +|}] + +type other = Any: _ -> other +[%%expect {| +type other = Any : 'a -> other +|}] + +let Any x = Any () +[%%expect {| +Line 1, characters 4-9: +1 | let Any x = Any () + ^^^^^ +Error: Existential types are not allowed in toplevel bindings, + but the constructor Any introduces existential types. +|}] + + +class c = let Any _x = () in object end +[%%expect {| +Line 1, characters 14-20: +1 | class c = let Any _x = () in object end + ^^^^^^ +Error: Existential types are not allowed in bindings inside class definition, + but the constructor Any introduces existential types. +|}] + +let () = + let Any x = Any () and () = () in + () +[%%expect {| +Line 2, characters 6-11: +2 | let Any x = Any () and () = () in + ^^^^^ +Error: Existential types are not allowed in "let ... and ..." bindings, + but the constructor Any introduces existential types. +|}] + + +let () = + let rec Any x = Any () in + () +[%%expect {| +Line 2, characters 10-15: +2 | let rec Any x = Any () in + ^^^^^ +Error: Existential types are not allowed in recursive bindings, + but the constructor Any introduces existential types. +|}] + + +let () = + let[@attribute] Any x = Any () in + () +[%%expect {| +Line 2, characters 18-23: +2 | let[@attribute] Any x = Any () in + ^^^^^ +Error: Existential types are not allowed in presence of attributes, + but the constructor Any introduces existential types. +|}] + +class c (Any x) = object end +[%%expect {| +Line 1, characters 8-15: +1 | class c (Any x) = object end + ^^^^^^^ +Error: Existential types are not allowed in class arguments, + but the constructor Any introduces existential types. +|}] + +class c = object(Any x) end +[%%expect {| +Line 1, characters 16-23: +1 | class c = object(Any x) end + ^^^^^^^ +Error: Existential types are not allowed in self patterns, + but the constructor Any introduces existential types. +|}] + +class c = let Any _x = () in object end +[%%expect {| +Line 1, characters 14-20: +1 | class c = let Any _x = () in object end + ^^^^^^ +Error: Existential types are not allowed in bindings inside class definition, + but the constructor Any introduces existential types. +|}] diff --git a/testsuite/tests/typing-gadts/yallop_bugs.ml b/testsuite/tests/typing-gadts/yallop_bugs.ml index 5e86e911..443a6526 100644 --- a/testsuite/tests/typing-gadts/yallop_bugs.ml +++ b/testsuite/tests/typing-gadts/yallop_bugs.ml @@ -18,9 +18,9 @@ let magic : 'a 'b. 'a -> 'b = ;; [%%expect{| type (_, _) eq = Refl : ('a, 'a) eq -Line _, characters 44-52: - let f (Refl : (a T.t, b T.t) eq) = (x :> b) - ^^^^^^^^ +Line 8, characters 44-52: +8 | let f (Refl : (a T.t, b T.t) eq) = (x :> b) + ^^^^^^^^ Error: Type a is not a subtype of b |}];; @@ -37,9 +37,9 @@ let magic : 'a 'b. 'a -> 'b = (downcast bad_proof ((object method m = x end) :> < >)) # m ;; [%%expect{| -Line _, characters 0-36: - type (_, +_) eq = Refl : ('a, 'a) eq - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-36: +1 | type (_, +_) eq = Refl : ('a, 'a) eq + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In this GADT definition, the variance of some parameter cannot be checked |}];; @@ -56,10 +56,10 @@ let check : type s . s t * s -> bool = function ;; [%%expect{| type _ t = IntLit : int t | BoolLit : bool t -Line _, characters 39-99: - .......................................function - | BoolLit, false -> false - | IntLit , 6 -> false +Line 5, characters 39-99: +5 | .......................................function +6 | | BoolLit, false -> false +7 | | IntLit , 6 -> false Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (IntLit, 0) @@ -74,10 +74,10 @@ let check : type s . (s t, s) pair -> bool = function ;; [%%expect{| type ('a, 'b) pair = { fst : 'a; snd : 'b; } -Line _, characters 45-134: - .............................................function - | {fst = BoolLit; snd = false} -> false - | {fst = IntLit ; snd = 6} -> false +Line 3, characters 45-134: +3 | .............................................function +4 | | {fst = BoolLit; snd = false} -> false +5 | | {fst = IntLit ; snd = 6} -> false Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: {fst=IntLit; snd=0} diff --git a/testsuite/tests/typing-immediate/immediate.ml b/testsuite/tests/typing-immediate/immediate.ml index caa6ee60..285d1128 100644 --- a/testsuite/tests/typing-immediate/immediate.ml +++ b/testsuite/tests/typing-immediate/immediate.ml @@ -106,9 +106,9 @@ module B = struct type t = string [@@immediate] end;; [%%expect{| -Line _, characters 2-31: - type t = string [@@immediate] - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 2-31: +2 | type t = string [@@immediate] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Types marked with the immediate attribute must be non-pointer types like int or bool |}];; @@ -119,9 +119,9 @@ module C = struct type s = t [@@immediate] end;; [%%expect{| -Line _, characters 2-26: - type s = t [@@immediate] - ^^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 2-26: +3 | type s = t [@@immediate] + ^^^^^^^^^^^^^^^^^^^^^^^^ Error: Types marked with the immediate attribute must be non-pointer types like int or bool |}];; @@ -131,10 +131,10 @@ module D : sig type t [@@immediate] end = struct type t = string end;; [%%expect{| -Line _, characters 42-70: - ..........................................struct - type t = string - end.. +Line 1, characters 42-70: +1 | ..........................................struct +2 | type t = string +3 | end.. Error: Signature mismatch: Modules do not match: sig type t = string end @@ -151,9 +151,9 @@ Error: Signature mismatch: module M_invalid : S = struct type t = string end;; module FM_invalid = F (struct type t = string end);; [%%expect{| -Line _, characters 23-49: - module M_invalid : S = struct type t = string end;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 23-49: +1 | module M_invalid : S = struct type t = string end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Signature mismatch: Modules do not match: sig type t = string end is not included in S Type declarations do not match: @@ -169,9 +169,9 @@ module E = struct and s = string end;; [%%expect{| -Line _, characters 2-26: - type t = s [@@immediate] - ^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 2-26: +2 | type t = s [@@immediate] + ^^^^^^^^^^^^^^^^^^^^^^^^ Error: Types marked with the immediate attribute must be non-pointer types like int or bool |}];; diff --git a/testsuite/tests/typing-implicit_unpack/implicit_unpack.ml b/testsuite/tests/typing-implicit_unpack/implicit_unpack.ml index 89cebf85..a6b4d697 100644 --- a/testsuite/tests/typing-implicit_unpack/implicit_unpack.ml +++ b/testsuite/tests/typing-implicit_unpack/implicit_unpack.ml @@ -113,7 +113,7 @@ open Typ let rec to_string: 'a. 'a Typ.typ -> 'a -> string = fun (type s) t x -> match (t : s typ) with - | Int eq -> string_of_int (TypEq.apply eq x) + | Int eq -> Int.to_string (TypEq.apply eq x) | String eq -> Printf.sprintf "%S" (TypEq.apply eq x) | Pair (module P) -> let (x1, x2) = TypEq.apply P.eq x in diff --git a/testsuite/tests/typing-implicit_unpack/implicit_unpack.ocaml.reference b/testsuite/tests/typing-implicit_unpack/implicit_unpack.ocaml.reference index db613370..94f9fff8 100644 --- a/testsuite/tests/typing-implicit_unpack/implicit_unpack.ocaml.reference +++ b/testsuite/tests/typing-implicit_unpack/implicit_unpack.ocaml.reference @@ -1,45 +1,43 @@ -val sort : (module Stdlib.Set.S with type elt = 'a) -> 'a list -> 'a list = - -val make_set : ('a -> 'a -> int) -> (module Stdlib.Set.S with type elt = 'a) = - +val sort : (module Set.S with type elt = 'a) -> 'a list -> 'a list = +val make_set : ('a -> 'a -> int) -> (module Set.S with type elt = 'a) = val sort_cmp : ('a -> 'a -> int) -> 'a list -> 'a list = module type S = sig type t val x : t end val f : (module S with type t = int) -> int = -Characters 6-37: - let f (module M : S with type t = 'a) = M.x;; (* Error *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 6-37: +1 | let f (module M : S with type t = 'a) = M.x;; (* Error *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The type of this packed module contains variables: -(module S with type t = 'a) + (module S with type t = 'a) val f : (module S with type t = 'a) -> 'a = - : int = 1 type 'a s = { s : (module S with type t = 'a); } - : int s = {s = } -Characters 9-19: - let f {s=(module M)} = M.x;; (* Error *) - ^^^^^^^^^^ +Line 1, characters 9-19: +1 | let f {s=(module M)} = M.x;; (* Error *) + ^^^^^^^^^^ Error: The type of this packed module contains variables: -(module S with type t = 'a) + (module S with type t = 'a) val f : 'a s -> 'a = type s = { s : (module S with type t = int); } val f : s -> int = val f : s -> s -> int = module type S = sig val x : int end val f : (module S) -> int -> (module S) -> int = -Characters 8-37: - let m = (module struct let x = 3 end);; (* Error *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 8-37: +1 | let m = (module struct let x = 3 end);; (* Error *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The signature for this packaged module couldn't be inferred. val m : (module S) = - : int = 7 - : int = 6 - : int = 3 -Characters 4-14: - let (module M) = m;; (* Error: only allowed in [let .. in] *) - ^^^^^^^^^^ +Line 1, characters 4-14: +1 | let (module M) = m;; (* Error: only allowed in [let .. in] *) + ^^^^^^^^^^ Error: Modules are not allowed in this pattern. -Characters 14-24: - class c = let (module M) = m in object end;; (* Error again *) - ^^^^^^^^^^ +Line 1, characters 14-24: +1 | class c = let (module M) = m in object end;; (* Error again *) + ^^^^^^^^^^ Error: Modules are not allowed in this pattern. module M : S module type S' = sig val f : int -> int end @@ -71,8 +69,8 @@ module rec Typ : | String of ('a, string) TypEq.t | Pair of (module PAIR with type t = 'a) end -val int : int Typ.typ = Int -val str : string Typ.typ = String +val int : int Typ.typ = Typ.Int +val str : string Typ.typ = Typ.String val pair : 'a Typ.typ -> 'b Typ.typ -> ('a * 'b) Typ.typ = val to_string : 'a Typ.typ -> 'a -> string = module type MapT = diff --git a/testsuite/tests/typing-labels/mixin.ml b/testsuite/tests/typing-labels/mixin.ml index 6df06748..ed5848c9 100644 --- a/testsuite/tests/typing-labels/mixin.ml +++ b/testsuite/tests/typing-labels/mixin.ml @@ -52,7 +52,7 @@ let subst_lambda ~subst_rec ~free ~subst : _ lambda -> _ = function ~f:(fun ~key ~data acc -> if Names.mem s used then data::acc else acc) in if List.exists used_expr ~f:(fun t -> Names.mem s (free t)) then - let name = s ^ string_of_int (next_id ()) in + let name = s ^ Int.to_string (next_id ()) in `Abs(name, subst_rec ~subst:(Subst.add ~key:s ~data:(`Var name) subst) t) else diff --git a/testsuite/tests/typing-labels/mixin2.ml b/testsuite/tests/typing-labels/mixin2.ml index 637a677a..0beebf49 100644 --- a/testsuite/tests/typing-labels/mixin2.ml +++ b/testsuite/tests/typing-labels/mixin2.ml @@ -78,7 +78,7 @@ class ['a] lambda_ops (ops : ('a,'a) #ops Lazy.t) = ~f:(fun ~key ~data acc -> if Names.mem s used then data::acc else acc) in if List.exists used_expr ~f:(fun t -> Names.mem s (!!free t)) then - let name = s ^ string_of_int (next_id ()) in + let name = s ^ Int.to_string (next_id ()) in `Abs(name, !!subst ~sub:(Subst.add ~key:s ~data:(`Var name) sub) t) else diff --git a/testsuite/tests/typing-labels/mixin3.ml b/testsuite/tests/typing-labels/mixin3.ml index d5f8c922..92975a8b 100644 --- a/testsuite/tests/typing-labels/mixin3.ml +++ b/testsuite/tests/typing-labels/mixin3.ml @@ -75,7 +75,7 @@ let lambda_ops (ops : ('a,'a) #ops Lazy.t) = ~f:(fun ~key ~data acc -> if Names.mem s used then data::acc else acc) in if List.exists used_expr ~f:(fun t -> Names.mem s (!!free t)) then - let name = s ^ string_of_int (next_id ()) in + let name = s ^ Int.to_string (next_id ()) in `Abs(name, !!subst ~sub:(Subst.add ~key:s ~data:(`Var name) sub) t) else diff --git a/testsuite/tests/typing-misc-bugs/pr6303_bad.compilers.reference b/testsuite/tests/typing-misc-bugs/pr6303_bad.compilers.reference index 0ad8bb9a..39da9708 100644 --- a/testsuite/tests/typing-misc-bugs/pr6303_bad.compilers.reference +++ b/testsuite/tests/typing-misc-bugs/pr6303_bad.compilers.reference @@ -1,4 +1,6 @@ File "pr6303_bad.ml", line 11, characters 22-23: +11 | let r' : string foo = r + ^ Error: This expression has type int foo but an expression was expected of type string foo Type int is not compatible with type string diff --git a/testsuite/tests/typing-misc-bugs/pr6946_bad.compilers.reference b/testsuite/tests/typing-misc-bugs/pr6946_bad.compilers.reference index c5a8859b..608d9a23 100644 --- a/testsuite/tests/typing-misc-bugs/pr6946_bad.compilers.reference +++ b/testsuite/tests/typing-misc-bugs/pr6946_bad.compilers.reference @@ -1,3 +1,5 @@ File "pr6946_bad.ml", line 10, characters 8-11: +10 | let _ = foo ();; + ^^^ Error: This expression has type int This is not a function; it cannot be applied. diff --git a/testsuite/tests/typing-misc/constraints.ml b/testsuite/tests/typing-misc/constraints.ml index a47cf964..213de4e7 100644 --- a/testsuite/tests/typing-misc/constraints.ml +++ b/testsuite/tests/typing-misc/constraints.ml @@ -4,37 +4,37 @@ type 'a t = [`A of 'a t t] as 'a;; (* fails *) [%%expect{| -Line _, characters 0-32: - type 'a t = [`A of 'a t t] as 'a;; (* fails *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-32: +1 | type 'a t = [`A of 'a t t] as 'a;; (* fails *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The definition of t contains a cycle: 'a t t as 'a |}, Principal{| -Line _, characters 0-32: - type 'a t = [`A of 'a t t] as 'a;; (* fails *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-32: +1 | type 'a t = [`A of 'a t t] as 'a;; (* fails *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The definition of t contains a cycle: [ `A of 'a t t ] as 'a |}];; type 'a t = [`A of 'a t t];; (* fails *) [%%expect{| -Line _, characters 0-26: - type 'a t = [`A of 'a t t];; (* fails *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-26: +1 | type 'a t = [`A of 'a t t];; (* fails *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In the definition of t, type 'a t t should be 'a t |}];; type 'a t = [`A of 'a t t] constraint 'a = 'a t;; (* fails since 4.04 *) [%%expect{| -Line _, characters 0-47: - type 'a t = [`A of 'a t t] constraint 'a = 'a t;; (* fails since 4.04 *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-47: +1 | type 'a t = [`A of 'a t t] constraint 'a = 'a t;; (* fails since 4.04 *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The type abbreviation t is cyclic |}];; type 'a t = [`A of 'a t] constraint 'a = 'a t;; (* fails since 4.04 *) [%%expect{| -Line _, characters 0-45: - type 'a t = [`A of 'a t] constraint 'a = 'a t;; (* fails since 4.04 *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-45: +1 | type 'a t = [`A of 'a t] constraint 'a = 'a t;; (* fails since 4.04 *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The type abbreviation t is cyclic |}];; type 'a t = [`A of 'a] as 'a;; @@ -45,9 +45,9 @@ type 'a t = [ `A of 'b ] as 'b constraint 'a = [ `A of 'a ] |}];; type 'a v = [`A of u v] constraint 'a = t and t = u and u = t;; (* fails *) [%%expect{| -Line _, characters 0-41: - type 'a v = [`A of u v] constraint 'a = t and t = u and u = t;; (* fails *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-41: +1 | type 'a v = [`A of u v] constraint 'a = t and t = u and u = t;; (* fails *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The definition of v contains a cycle: t |}];; @@ -73,9 +73,9 @@ module type PR6505 = sig end ;; (* fails *) [%%expect{| -Line _, characters 2-44: - and 'o abs constraint 'o = 'o is_an_object - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 2-44: +3 | and 'o abs constraint 'o = 'o is_an_object + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The definition of abs contains a cycle: 'a is_an_object as 'a |}];; @@ -93,9 +93,9 @@ module PR6505a : and ('a, 'l) abs = 'l constraint 'a = 'l is_an_object val y : (< > is_an_object, < > is_an_object) abs end -Line _, characters 8-17: - let _ = PR6505a.y#bang;; (* fails *) - ^^^^^^^^^ +Line 6, characters 8-17: +6 | let _ = PR6505a.y#bang;; (* fails *) + ^^^^^^^^^ Error: This expression has type (< > PR6505a.is_an_object, < > PR6505a.is_an_object) PR6505a.abs It has no method bang @@ -106,9 +106,9 @@ module PR6505a : and ('a, 'l) abs = 'l constraint 'a = 'l is_an_object val y : (< >, < >) abs end -Line _, characters 8-17: - let _ = PR6505a.y#bang;; (* fails *) - ^^^^^^^^^ +Line 6, characters 8-17: +6 | let _ = PR6505a.y#bang;; (* fails *) + ^^^^^^^^^ Error: This expression has type (< >, < >) PR6505a.abs It has no method bang |}] @@ -126,9 +126,9 @@ module PR6505b : and ('a, 'l) abs = 'l constraint 'a = 'l is_an_object val x : (([> `Foo of int ] as 'a) is_an_object, 'a is_an_object) abs end -Line _, characters 23-57: - let () = print_endline (match PR6505b.x with `Bar s -> s);; (* fails *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 6, characters 23-57: +6 | let () = print_endline (match PR6505b.x with `Bar s -> s);; (* fails *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: `Foo _ diff --git a/testsuite/tests/typing-misc/disambiguate_principality.ml b/testsuite/tests/typing-misc/disambiguate_principality.ml index f9908a49..ed49ecbf 100644 --- a/testsuite/tests/typing-misc/disambiguate_principality.ml +++ b/testsuite/tests/typing-misc/disambiguate_principality.ml @@ -34,9 +34,9 @@ let after_a = { x with lbl = 4 } ;; [%%expect{| -Line _, characters 2-20: - { x with lbl = 4 } - ^^^^^^^^^^^^^^^^^^ +Line 3, characters 2-20: +3 | { x with lbl = 4 } + ^^^^^^^^^^^^^^^^^^ Warning 23: all the fields are explicitly listed in this record: the 'with' clause is useless. val after_a : M.r = {M.lbl = 4} @@ -49,9 +49,9 @@ let b = [%%expect{| val b : unit = () |}, Principal{| -Line _, characters 7-18: - x := { lbl = 4 } - ^^^^^^^^^^^ +Line 3, characters 7-18: +3 | x := { lbl = 4 } + ^^^^^^^^^^^ Warning 18: this type-based record disambiguation is not principal. val b : unit = () |}] @@ -77,9 +77,9 @@ let e = { x with contents = { lbl = 4 } } ;; [%%expect{| -Line _, characters 24-27: - { x with contents = { lbl = 4 } } - ^^^ +Line 3, characters 24-27: +3 | { x with contents = { lbl = 4 } } + ^^^ Error: Unbound record field lbl |}] @@ -107,15 +107,15 @@ let h x = | { lbl = _ } -> () ;; [%%expect{| -Line _, characters 4-15: - | { lbl = _ } -> () - ^^^^^^^^^^^ +Line 4, characters 4-15: +4 | | { lbl = _ } -> () + ^^^^^^^^^^^ Warning 11: this match case is unused. val h : M.r -> unit = |}, Principal{| -Line _, characters 6-9: - | { lbl = _ } -> () - ^^^ +Line 4, characters 6-9: +4 | | { lbl = _ } -> () + ^^^ Error: Unbound record field lbl |}] @@ -125,9 +125,9 @@ let i x = | (_ : M.r) -> () ;; [%%expect{| -Line _, characters 6-9: - | { lbl = _ } -> () - ^^^ +Line 3, characters 6-9: +3 | | { lbl = _ } -> () + ^^^ Error: Unbound record field lbl |}] @@ -137,9 +137,9 @@ let j x = | { lbl = _ } -> () ;; [%%expect{| -Line _, characters 4-15: - | { lbl = _ } -> () - ^^^^^^^^^^^ +Line 4, characters 4-15: +4 | | { lbl = _ } -> () + ^^^^^^^^^^^ Warning 12: this sub-pattern is unused. val j : M.r -> unit = |}] @@ -150,9 +150,9 @@ let k x = | (_ : M.r) -> () ;; [%%expect{| -Line _, characters 6-9: - | { lbl = _ } - ^^^ +Line 3, characters 6-9: +3 | | { lbl = _ } + ^^^ Error: Unbound record field lbl |}] @@ -169,9 +169,9 @@ let m x = | { contents = { lbl = _ } } -> () ;; [%%expect{| -Line _, characters 19-22: - | { contents = { lbl = _ } } -> () - ^^^ +Line 3, characters 19-22: +3 | | { contents = { lbl = _ } } -> () + ^^^ Error: Unbound record field lbl |}] @@ -181,15 +181,15 @@ let n x = | { contents = { lbl = _ } } -> () ;; [%%expect{| -Line _, characters 4-30: - | { contents = { lbl = _ } } -> () - ^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 4, characters 4-30: +4 | | { contents = { lbl = _ } } -> () + ^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 11: this match case is unused. val n : M.r ref -> unit = |}, Principal{| -Line _, characters 19-22: - | { contents = { lbl = _ } } -> () - ^^^ +Line 4, characters 19-22: +4 | | { contents = { lbl = _ } } -> () + ^^^ Error: Unbound record field lbl |}] @@ -199,9 +199,9 @@ let o x = | (_ : M.r ref) -> () ;; [%%expect{| -Line _, characters 19-22: - | { contents = { lbl = _ } } -> () - ^^^ +Line 3, characters 19-22: +3 | | { contents = { lbl = _ } } -> () + ^^^ Error: Unbound record field lbl |}] @@ -211,9 +211,9 @@ let p x = | { contents = { lbl = _ } } -> () ;; [%%expect{| -Line _, characters 4-30: - | { contents = { lbl = _ } } -> () - ^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 4, characters 4-30: +4 | | { contents = { lbl = _ } } -> () + ^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 12: this sub-pattern is unused. val p : M.r ref -> unit = |}] @@ -224,9 +224,9 @@ let q x = | (_ : M.r ref) -> () ;; [%%expect{| -Line _, characters 19-22: - | { contents = { lbl = _ } } - ^^^ +Line 3, characters 19-22: +3 | | { contents = { lbl = _ } } + ^^^ Error: Unbound record field lbl |}] @@ -247,9 +247,9 @@ let s arg = [%%expect{| val s : M.r ref -> unit = |}, Principal{| -Line _, characters 9-20: - x := { lbl = 4 } - ^^^^^^^^^^^ +Line 4, characters 9-20: +4 | x := { lbl = 4 } + ^^^^^^^^^^^ Warning 18: this type-based record disambiguation is not principal. val s : M.r ref -> unit = |}] @@ -261,9 +261,9 @@ let t = function [%%expect{| val t : M.r ref -> unit = |}, Principal{| -Line _, characters 9-20: - x := { lbl = 4 } - ^^^^^^^^^^^ +Line 3, characters 9-20: +3 | x := { lbl = 4 } + ^^^^^^^^^^^ Warning 18: this type-based record disambiguation is not principal. val t : M.r ref -> unit = |}] @@ -275,9 +275,244 @@ let u = function [%%expect{| val u : M.r ref -> int = |}, Principal{| -Line _, characters 7-10: - !x.lbl - ^^^ +Line 3, characters 7-10: +3 | !x.lbl + ^^^ Warning 18: this type-based field disambiguation is not principal. val u : M.r ref -> int = |}] + + +(*** Constructors ***) + +(* Expressions *) + +module M = struct + type t = A | B +end +;; +[%%expect{| +module M : sig type t = A | B end +|}] + +let before_a : M.t = + A +;; +[%%expect{| +val before_a : M.t = M.A +|}] + +let a = + let x = (A : M.t) in + x +;; +[%%expect{| +val a : M.t = M.A +|}] + +let b = + let x = ({ contents = A } : M.t ref) in + x := B +;; +[%%expect{| +val b : unit = () +|}, Principal{| +Line 3, characters 7-8: +3 | x := B + ^ +Warning 18: this type-based constructor disambiguation is not principal. +val b : unit = () +|}] + +let d = + let x = ({ contents = A } : M.t ref) in + x.contents <- B +;; +[%%expect{| +val d : unit = () +|}] + +let e = + let x = ({ contents = A } : M.t ref) in + { x with contents = B } +;; +[%%expect{| +Line 3, characters 22-23: +3 | { x with contents = B } + ^ +Error: Unbound constructor B +|}] + +(* Patterns *) + +let g (x : M.t) = + match x with + | A | B -> () +;; +[%%expect{| +val g : M.t -> unit = +|}] + +let h x = + match x with + | (A : M.t) -> () + | B -> () +;; +[%%expect{| +val h : M.t -> unit = +|}, Principal{| +Line 4, characters 4-5: +4 | | B -> () + ^ +Error: Unbound constructor B +|}] + +let i x = + match x with + | A -> () + | (B : M.t) -> () +;; +[%%expect{| +Line 3, characters 4-5: +3 | | A -> () + ^ +Error: Unbound constructor A +|}] + +let j x = + match x with + | (A : M.t) + | B -> () +;; +[%%expect{| +val j : M.t -> unit = +|}] + +let k x = + match x with + | A + | (B : M.t) -> () +;; +[%%expect{| +Line 3, characters 4-5: +3 | | A + ^ +Error: Unbound constructor A +|}] + +let l (x : M.t ref) = + match x with + | { contents = (A | B) } -> () +;; +[%%expect{| +val l : M.t ref -> unit = +|}] + +let m x = + match x with + | { contents = (A | B) } -> () +;; +[%%expect{| +Line 3, characters 18-19: +3 | | { contents = (A | B) } -> () + ^ +Error: Unbound constructor A +|}] + +let n x = + match x with + | (_ : M.t ref) -> () + | { contents = A } -> () +;; +[%%expect{| +Line 4, characters 4-20: +4 | | { contents = A } -> () + ^^^^^^^^^^^^^^^^ +Warning 11: this match case is unused. +val n : M.t ref -> unit = +|}, Principal{| +Line 4, characters 17-18: +4 | | { contents = A } -> () + ^ +Error: Unbound constructor A +|}] + +let o x = + match x with + | { contents = A } -> () + | (_ : M.t ref) -> () +;; +[%%expect{| +Line 3, characters 17-18: +3 | | { contents = A } -> () + ^ +Error: Unbound constructor A +|}] + +let p x = + match x with + | (_ : M.t ref) + | { contents = A } -> () +;; +[%%expect{| +Line 4, characters 4-20: +4 | | { contents = A } -> () + ^^^^^^^^^^^^^^^^ +Warning 12: this sub-pattern is unused. +val p : M.t ref -> unit = +|}] + +let q x = + match x with + | { contents = A } + | (_ : M.t ref) -> () +;; +[%%expect{| +Line 3, characters 17-18: +3 | | { contents = A } + ^ +Error: Unbound constructor A +|}] + +let s arg = + match arg with + | (x : M.t ref) -> + x := A +;; +[%%expect{| +val s : M.t ref -> unit = +|}, Principal{| +Line 4, characters 9-10: +4 | x := A + ^ +Warning 18: this type-based constructor disambiguation is not principal. +val s : M.t ref -> unit = +|}] + +let t = function + | ({ contents = M.A } : M.t ref) as x -> + x := B +;; +[%%expect{| +Line 1, characters 8-70: +1 | ........function +2 | | ({ contents = M.A } : M.t ref) as x -> +3 | x := B +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +{contents=B} +val t : M.t ref -> unit = +|}, Principal{| +Line 3, characters 9-10: +3 | x := B + ^ +Warning 18: this type-based constructor disambiguation is not principal. +Line 1, characters 8-70: +1 | ........function +2 | | ({ contents = M.A } : M.t ref) as x -> +3 | x := B +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +{contents=B} +val t : M.t ref -> unit = +|}] diff --git a/testsuite/tests/typing-misc/empty_ppx.ml b/testsuite/tests/typing-misc/empty_ppx.ml new file mode 100644 index 00000000..431ba868 --- /dev/null +++ b/testsuite/tests/typing-misc/empty_ppx.ml @@ -0,0 +1,14 @@ +module H = Ast_helper +module M = Ast_mapper +open Parsetree +let empty_polyvar loc = H.Typ.variant ~loc [] Asttypes.Closed None + +let super = M.default_mapper +let typ mapper e = + match e.ptyp_desc with + | Ptyp_extension ({txt="empty_polyvar";loc},_) -> empty_polyvar loc + | _ -> super.M.typ mapper e + +let () = M.register "empty ppx" (fun _ -> + { super with typ } + ) diff --git a/testsuite/tests/typing-misc/empty_variant.ml b/testsuite/tests/typing-misc/empty_variant.ml index 88342711..74a0713c 100644 --- a/testsuite/tests/typing-misc/empty_variant.ml +++ b/testsuite/tests/typing-misc/empty_variant.ml @@ -25,7 +25,7 @@ let g (x:m) = val g : m -> 'a = |}] -let f : t option -> int = function None -> 3 +let f : t option -> int = function None -> 3 [%%expect{| val f : t option -> int = |}] diff --git a/testsuite/tests/typing-misc/exotic_unifications.ml b/testsuite/tests/typing-misc/exotic_unifications.ml new file mode 100644 index 00000000..9f27b561 --- /dev/null +++ b/testsuite/tests/typing-misc/exotic_unifications.ml @@ -0,0 +1,29 @@ +(* TEST + * expect +*) + +class virtual t = object method virtual x: float end + +class x = object(self: ) + inherit t +end +[%%expect {| +class virtual t : object method virtual x : float end +Line 4, characters 16-17: +4 | inherit t + ^ +Error: The method x has type int but is expected to have type float + Type int is not compatible with type float +|}] + +let x = + let module M = struct module type t = sig end end in + (module struct end: M.t) +[%%expect {| +Line 3, characters 2-26: +3 | (module struct end: M.t) + ^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This expression has type (module M.t) + but an expression was expected of type 'a + The module type M.t would escape its scope +|}] diff --git a/testsuite/tests/typing-misc/external_arity.ml b/testsuite/tests/typing-misc/external_arity.ml new file mode 100644 index 00000000..bad0fb17 --- /dev/null +++ b/testsuite/tests/typing-misc/external_arity.ml @@ -0,0 +1,33 @@ +(* TEST + * expect +*) + +let f a b c = a + b + c + +let _ : int = Obj.magic f None None None + +[%%expect +{| +val f : int -> int -> int -> int = +- : int = 0 +|}] + +external cmp : 'a -> 'b = "%compare" + +[%%expect +{| +Line 1, characters 0-36: +1 | external cmp : 'a -> 'b = "%compare" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Wrong arity for builtin primitive "%compare" +|}] + +external apply : 'a -> 'b = "%apply" + +[%%expect +{| +Line 1, characters 0-36: +1 | external apply : 'a -> 'b = "%apply" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Wrong arity for builtin primitive "%apply" +|}] diff --git a/testsuite/tests/typing-misc/labels.ml b/testsuite/tests/typing-misc/labels.ml index a2b5c364..3289ea39 100644 --- a/testsuite/tests/typing-misc/labels.ml +++ b/testsuite/tests/typing-misc/labels.ml @@ -7,9 +7,9 @@ let f ~x = x + 1;; f ?x:0;; [%%expect{| val f : x:int -> int = -Line _, characters 5-6: - f ?x:0;; - ^ +Line 2, characters 5-6: +2 | f ?x:0;; + ^ Warning 43: the label x is not optional. - : int = 1 |}];; @@ -27,9 +27,9 @@ val g : ?x:'a -> unit -> unit = (* PR#5748 *) foo (fun ?opt () -> ()) ;; (* fails *) [%%expect{| -Line _, characters 4-23: - foo (fun ?opt () -> ()) ;; (* fails *) - ^^^^^^^^^^^^^^^^^^^ +Line 1, characters 4-23: +1 | foo (fun ?opt () -> ()) ;; (* fails *) + ^^^^^^^^^^^^^^^^^^^ Error: This function should have type unit -> unit but its first argument is labelled ?opt |}];; diff --git a/testsuite/tests/typing-misc/mapping.ml b/testsuite/tests/typing-misc/mapping.ml new file mode 100644 index 00000000..79eaaab7 --- /dev/null +++ b/testsuite/tests/typing-misc/mapping.ml @@ -0,0 +1,4 @@ +module Range_intf = Pr8548__Range_intf +module Range = Pr8548__Range +module Ranged_intf = Pr8548__Ranged_intf +module Ranged = Pr8548__Ranged diff --git a/testsuite/tests/typing-misc/ocamltests b/testsuite/tests/typing-misc/ocamltests index 2f80cc48..1053da91 100644 --- a/testsuite/tests/typing-misc/ocamltests +++ b/testsuite/tests/typing-misc/ocamltests @@ -1,16 +1,30 @@ constraints.ml disambiguate_principality.ml +exotic_unifications.ml inside_out.ml labels.ml occur_check.ml +pat_type_sharing.ml +pattern_open.ml polyvars.ml +pr6416.ml +pr6634.ml pr6939-flat-float-array.ml pr6939-no-flat-float-array.ml pr7103.ml pr7228.ml pr7668_bad.ml +pr8548.ml +pr8548_split.ml printing.ml records.ml +scope_escape.ml +unique_names_in_unification.ml variant.ml wellfounded.ml empty_variant.ml +typecore_errors.ml +typecore_nolabel_errors.ml +typecore_empty_polyvariant_error.ml +typetexp_errors.ml +external_arity.ml diff --git a/testsuite/tests/typing-misc/occur_check.ml b/testsuite/tests/typing-misc/occur_check.ml index 90c5224e..9d681c88 100644 --- a/testsuite/tests/typing-misc/occur_check.ml +++ b/testsuite/tests/typing-misc/occur_check.ml @@ -8,18 +8,18 @@ type 'a t = 'a;; let f (g : 'a list -> 'a t -> 'a) s = g s s;; [%%expect{| type 'a t = 'a -Line _, characters 42-43: - let f (g : 'a list -> 'a t -> 'a) s = g s s;; - ^ +Line 2, characters 42-43: +2 | let f (g : 'a list -> 'a t -> 'a) s = g s s;; + ^ Error: This expression has type 'a list but an expression was expected of type 'a t = 'a The type variable 'a occurs inside 'a list |}];; let f (g : 'a * 'b -> 'a t -> 'a) s = g s s;; [%%expect{| -Line _, characters 42-43: - let f (g : 'a * 'b -> 'a t -> 'a) s = g s s;; - ^ +Line 1, characters 42-43: +1 | let f (g : 'a * 'b -> 'a t -> 'a) s = g s s;; + ^ Error: This expression has type 'a * 'b but an expression was expected of type 'a t = 'a The type variable 'a occurs inside 'a * 'b diff --git a/testsuite/tests/typing-misc/pat_type_sharing.ml b/testsuite/tests/typing-misc/pat_type_sharing.ml new file mode 100644 index 00000000..1cbf6964 --- /dev/null +++ b/testsuite/tests/typing-misc/pat_type_sharing.ml @@ -0,0 +1,17 @@ +(* TEST + * expect +*) +type 'a r = { a : 'a; b : 'a; } +type 'a ty = Int : int ty | Float : float ty;; +[%%expect{| +type 'a r = { a : 'a; b : 'a; } +type 'a ty = Int : int ty | Float : float ty +|}] + +let foo (type a) (ty : a ty) (x : a r) = + match ty, x with + | Int, { a = 3; b } -> b + | _ -> assert false;; +[%%expect{| +val foo : 'a ty -> 'a r -> 'a = +|}] diff --git a/testsuite/tests/typing-misc/pattern_open.ml b/testsuite/tests/typing-misc/pattern_open.ml new file mode 100644 index 00000000..16572b6e --- /dev/null +++ b/testsuite/tests/typing-misc/pattern_open.ml @@ -0,0 +1,249 @@ +(* TEST + * expect +*) + +let pp fmt = Format.printf (fmt^^"@.") + +type 'a box = B of 'a +(* Basic tests *) +module M = struct + type c = C + type t = {x : c box } +end + +module N = struct + type d = D + let d = D + type t = {x: d box} +end +open N;; +[%%expect {| +val pp : ('a, Format.formatter, unit, unit, unit, unit) format6 -> 'a = +type 'a box = B of 'a +module M : sig type c = C type t = { x : c box; } end +module N : sig type d = D val d : d type t = { x : d box; } end +|}] + +let f M.{ x=B C } y = M.C,y;; +let g M.(x) M.(w) = x * w +;; +let g = function + | M.[] -> [] + | M.[C] -> M.[C] + | _ -> [] +;; +let h = function + | M.[||] -> None + | M.[| C |] -> Some M.C + | _ -> None +;; +let f2 = function + | M.( B (B C) ) -> M.C +;; +(* () constructor *) +let M.() = () +;; +[%%expect {| +val f : M.t -> 'a -> M.c * 'a = +val g : int -> int -> int = +val g : M.c list -> M.c list = +val h : M.c array -> M.c option = +val f2 : M.c box box -> M.c = +|}] + +(* Pattern open separation*) +module L = struct + type _ c = C : unit c + type t = { t : unit c } + type r = { r : unit c } + let x ()= pp "Wrong value L.x" +end +;; +module K = struct + type _ c = C : unit c + type t = { t : unit c } + type r = { r : unit c } + let x ()= pp "Right value K.x" +end;; +[%%expect {| +module L : + sig + type _ c = C : unit c + type t = { t : unit c; } + type r = { r : unit c; } + val x : unit -> unit + end +module K : + sig + type _ c = C : unit c + type t = { t : unit c; } + type r = { r : unit c; } + val x : unit -> unit + end +|}] + +let () = + let test = + let open K in + function + | L.{t}, ({r=C} : K.r) -> x () + in + test (L.{t=C}, K.{r=C});; +[%%expect {| +Right value K.x +|}] + +module Exterior = struct + module Gadt = struct + module Boolean = struct + type t = { b : bool } + type wrong = false | true + let print () = pp "Wrong function: Exterior.Gadt.Boolean.print" + end + + type _ t = + | Bool : Boolean.t -> bool t + | Int : int -> int t + | Eq : 'a t * 'a t -> bool t + + let print () = pp "Wrong function: Exterior.Gadt.print" + end + let print () = pp "Wrong function: Exterior.print" +end;; +[%%expect {| +module Exterior : + sig + module Gadt : + sig + module Boolean : + sig + type t = { b : bool; } + type wrong = false | true + val print : unit -> unit + end + type _ t = + Bool : Boolean.t -> bool t + | Int : int -> int t + | Eq : 'a t * 'a t -> bool t + val print : unit -> unit + end + val print : unit -> unit + end +|}] +let rec eval: type t. t Exterior.Gadt.t -> t = function + | Exterior.( Gadt.( Eq (a,b) ) ) -> (eval a) = (eval b) + | Exterior.( Gadt.( Bool Boolean.{b} ) ) -> b + | Exterior.Gadt.( Int n ) -> n +let () = + let print () = pp "Right function print" in + let choose (type a):a Exterior.Gadt.t * a Exterior.Gadt.t -> a -> a = + fun (a,b) c -> + match a, b, c with + | Exterior.( Gadt.( Bool Boolean.{b} ), Gadt.Bool _ , _ ) -> print(); true + | Exterior.(Gadt.Bool Gadt.Boolean.{b}), _ , true -> print(); true + | Exterior.(Gadt.Bool Gadt.Boolean.{b}), _ , false -> print(); b + | Exterior.Gadt.( Int n, Int k, 0 ) -> print(); 0 + | Exterior.( Gadt.(Int n, Gadt.Int k, l) ) -> print(); k+n+l + | Exterior.Gadt.( Eq (a,b) ), _, true -> print(); true + | Exterior.(Gadt.( Eq (a,b), _ , false )) -> print(); eval a = eval b in + let _ = + choose Exterior.Gadt.(Bool Boolean.{b=true}, Bool Boolean.{b=false}) false + in + print () +;; +[%%expect {| +val eval : 't Exterior.Gadt.t -> 't = +Right function print +Right function print +|} +] +(* existential type *) +module Existential = struct + type printable = E : 'a * ('a -> unit) -> printable +end + +let rec print: Existential.printable -> unit = function + | Existential.( E(x, print) ) -> print x +;; +[%%expect {| +module Existential : + sig type printable = E : 'a * ('a -> unit) -> printable end +val print : Existential.printable -> unit = +|}] + +(* Test that constructors and variables introduced in scope inside + M.(..) are not propagated outside of M.(..) *) +module S = struct + type 'a t = Sep : unit t + type ex = Ex: 'a * 'a -> ex + let s = Sep +end +;; +[%%expect {| +module S : + sig + type 'a t = Sep : unit t + type ex = Ex : 'a * 'a -> ex + val s : unit t + end +|}] +let test_separation = function + | S.(Sep), (S.(Sep,Sep), Sep) -> ();; +[%%expect {| +Line 2, characters 27-30: +2 | | S.(Sep), (S.(Sep,Sep), Sep) -> ();; + ^^^ +Error: Unbound constructor Sep +|}] +let test_separation_2 = function + | S.(Ex(a,b)), Ex(c,d) -> ();; +[%%expect {| +Line 2, characters 17-19: +2 | | S.(Ex(a,b)), Ex(c,d) -> ();; + ^^ +Error: Unbound constructor Ex +|}] +let test_separation_3 = function + | S.(Sep) -> s;; +[%%expect {| +Line 2, characters 15-16: +2 | | S.(Sep) -> s;; + ^ +Error: Unbound value s +|}] + +(* Testing interaction of local open in pattern and backtracking *) +module PR6437 = struct + module Ctx = struct + type ('a, 'b) t = + | Nil : (unit, unit) t + | Cons : ('a, 'b) t -> ('a * unit, 'b * unit) t + end + + module Var = struct + type 'a t = + | O : ('a * unit) t + | S : 'a t -> ('a * unit) t + end +end + +let rec f : type g1 g2. (g1, g2) PR6437.Ctx.t * g1 PR6437.Var.t + -> g2 PR6437.Var.t = function + | PR6437.( Ctx.(Cons g), Var.(O) ) -> PR6437.Var.O + | PR6437.( Ctx.(Cons g), Var.(S n) ) -> PR6437.Var.S (f (g, n)) + | _ -> . ;; +[%%expect {| +module PR6437 : + sig + module Ctx : + sig + type ('a, 'b) t = + Nil : (unit, unit) t + | Cons : ('a, 'b) t -> ('a * unit, 'b * unit) t + end + module Var : + sig type 'a t = O : ('a * unit) t | S : 'a t -> ('a * unit) t end + end +val f : ('g1, 'g2) PR6437.Ctx.t * 'g1 PR6437.Var.t -> 'g2 PR6437.Var.t = + +|}] diff --git a/testsuite/tests/typing-misc/polyvars.ml b/testsuite/tests/typing-misc/polyvars.ml index f14a9950..e6c88dd6 100644 --- a/testsuite/tests/typing-misc/polyvars.ml +++ b/testsuite/tests/typing-misc/polyvars.ml @@ -6,27 +6,27 @@ type ab = [ `A | `B ];; let f (x : [`A]) = match x with #ab -> 1;; [%%expect{| type ab = [ `A | `B ] -Line _, characters 32-35: - let f (x : [`A]) = match x with #ab -> 1;; - ^^^ +Line 2, characters 32-35: +2 | let f (x : [`A]) = match x with #ab -> 1;; + ^^^ Error: This pattern matches values of type [? `A | `B ] but a pattern was expected which matches values of type [ `A ] The second variant type does not allow tag(s) `B |}];; let f x = ignore (match x with #ab -> 1); ignore (x : [`A]);; [%%expect{| -Line _, characters 31-34: - let f x = ignore (match x with #ab -> 1); ignore (x : [`A]);; - ^^^ +Line 1, characters 31-34: +1 | let f x = ignore (match x with #ab -> 1); ignore (x : [`A]);; + ^^^ Error: This pattern matches values of type [? `B ] but a pattern was expected which matches values of type [ `A ] The second variant type does not allow tag(s) `B |}];; let f x = ignore (match x with `A|`B -> 1); ignore (x : [`A]);; [%%expect{| -Line _, characters 34-36: - let f x = ignore (match x with `A|`B -> 1); ignore (x : [`A]);; - ^^ +Line 1, characters 34-36: +1 | let f x = ignore (match x with `A|`B -> 1); ignore (x : [`A]);; + ^^ Error: This pattern matches values of type [? `B ] but a pattern was expected which matches values of type [ `A ] The second variant type does not allow tag(s) `B @@ -34,17 +34,17 @@ Error: This pattern matches values of type [? `B ] let f (x : [< `A | `B]) = match x with `A | `B | `C -> 0;; (* warn *) [%%expect{| -Line _, characters 49-51: - let f (x : [< `A | `B]) = match x with `A | `B | `C -> 0;; (* warn *) - ^^ +Line 1, characters 49-51: +1 | let f (x : [< `A | `B]) = match x with `A | `B | `C -> 0;; (* warn *) + ^^ Warning 12: this sub-pattern is unused. val f : [< `A | `B ] -> int = |}];; let f (x : [`A | `B]) = match x with `A | `B | `C -> 0;; (* fail *) [%%expect{| -Line _, characters 47-49: - let f (x : [`A | `B]) = match x with `A | `B | `C -> 0;; (* fail *) - ^^ +Line 1, characters 47-49: +1 | let f (x : [`A | `B]) = match x with `A | `B | `C -> 0;; (* fail *) + ^^ Error: This pattern matches values of type [? `C ] but a pattern was expected which matches values of type [ `A | `B ] The second variant type does not allow tag(s) `C @@ -70,33 +70,33 @@ type t = A | B - : [> `A ] option * t -> int = - : t * [< `A | `B ] -> int = - : [< `A | `B ] * t -> int = -Line _, characters 0-41: - function (`A|`B), _ -> 0 | _,(`A|`B) -> 1;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 9, characters 0-41: +9 | function (`A|`B), _ -> 0 | _,(`A|`B) -> 1;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (`AnyOtherTag, `AnyOtherTag) - : [> `A | `B ] * [> `A | `B ] -> int = -Line _, characters 0-29: - function `B,1 -> 1 | _,1 -> 2;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 10, characters 0-29: +10 | function `B,1 -> 1 | _,1 -> 2;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (_, 0) -Line _, characters 21-24: - function `B,1 -> 1 | _,1 -> 2;; - ^^^ +Line 10, characters 21-24: +10 | function `B,1 -> 1 | _,1 -> 2;; + ^^^ Warning 11: this match case is unused. - : [< `B ] * int -> int = -Line _, characters 0-29: - function 1,`B -> 1 | 1,_ -> 2;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 11, characters 0-29: +11 | function 1,`B -> 1 | 1,_ -> 2;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (0, _) -Line _, characters 21-24: - function 1,`B -> 1 | 1,_ -> 2;; - ^^^ +Line 11, characters 21-24: +11 | function 1,`B -> 1 | 1,_ -> 2;; + ^^^ Warning 11: this match case is unused. - : int * [< `B ] -> int = |}];; @@ -117,9 +117,9 @@ val f : 'a -> [< `Foo ] -> 'a = let f : ([`A | `B ] as 'a) -> [> 'a] -> unit = fun x (y : [> 'a]) -> ();; let f (x : [`A | `B] as 'a) (y : [> 'a]) = ();; [%%expect{| -Line _, characters 61-63: - let f : ([`A | `B ] as 'a) -> [> 'a] -> unit = fun x (y : [> 'a]) -> ();; - ^^ +Line 1, characters 61-63: +1 | let f : ([`A | `B ] as 'a) -> [> 'a] -> unit = fun x (y : [> 'a]) -> ();; + ^^ Error: The type 'a does not expand to a polymorphic variant type Hint: Did you mean `a? |}] @@ -135,9 +135,9 @@ type t = private [> `A of string ];; function (`A x : t) -> x;; [%%expect{| type t = private [> `A of string ] -Line _, characters 0-24: - function (`A x : t) -> x;; - ^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 0-24: +2 | function (`A x : t) -> x;; + ^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: ` @@ -146,9 +146,9 @@ Here is an example of a case that is not matched: let f = function `AnyOtherTag, _ -> 1 | _, (`AnyOtherTag|`AnyOtherTag') -> 2;; [%%expect{| -Line _, characters 8-76: - let f = function `AnyOtherTag, _ -> 1 | _, (`AnyOtherTag|`AnyOtherTag') -> 2;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 8-76: +1 | let f = function `AnyOtherTag, _ -> 1 | _, (`AnyOtherTag|`AnyOtherTag') -> 2;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (`AnyOtherTag', `AnyOtherTag'') diff --git a/testsuite/tests/typing-misc/pr6416.ml b/testsuite/tests/typing-misc/pr6416.ml new file mode 100644 index 00000000..a3fa4eeb --- /dev/null +++ b/testsuite/tests/typing-misc/pr6416.ml @@ -0,0 +1,406 @@ +(* TEST + flags="-no-alias-deps -w +40" + * expect +*) +module M = struct + type t = A + module M : sig + val f : t -> unit + end = struct + type t = B + let f B = () + end +end;; +[%%expect{| +Line 5, characters 8-52: +5 | ........struct +6 | type t = B +7 | let f B = () +8 | end +Error: Signature mismatch: + Modules do not match: + sig type t = B val f : t -> unit end + is not included in + sig val f : t -> unit end + Values do not match: + val f : t/1 -> unit + is not included in + val f : t/2 -> unit + Line 6, characters 4-14: + Definition of type t/1 + Line 2, characters 2-12: + Definition of type t/2 +|}] + +module N = struct + type t= A + module M: sig type u = A of t end = + struct type t = B type u = A of t end +end;; +[%%expect{| +Line 4, characters 2-39: +4 | struct type t = B type u = A of t end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Signature mismatch: + Modules do not match: + sig type t = B type u = A of t end + is not included in + sig type u = A of t end + Type declarations do not match: + type u = A of t/1 + is not included in + type u = A of t/2 + The types for field A are not equal. + Line 4, characters 9-19: + Definition of type t/1 + Line 2, characters 2-11: + Definition of type t/2 +|}] + +module K = struct + module type s + module M: sig module A:functor(X:s) -> sig end end = + struct + module type s + module A(X:s) =struct end + end +end;; + +[%%expect{| +Line 4, characters 4-70: +4 | ....struct +5 | module type s +6 | module A(X:s) =struct end +7 | end +Error: Signature mismatch: + Modules do not match: + sig module type s module A : functor (X : s) -> sig end end + is not included in + sig module A : functor (X : s) -> sig end end + In module A: + Modules do not match: + functor (X : s/1) -> sig end + is not included in + functor (X : s/2) -> sig end + At position module A(X : ) : ... + Modules do not match: s/2 is not included in s/1 + Line 5, characters 6-19: + Definition of module type s/1 + Line 2, characters 2-15: + Definition of module type s/2 +|}] + +module L = struct + module T = struct type t end + module M: sig type t = A of T.t end = + struct + module T = struct type t end + type t = A of T.t + end +end;; + [%%expect {| +Line 4, characters 4-77: +4 | ....struct +5 | module T = struct type t end +6 | type t = A of T.t +7 | end +Error: Signature mismatch: + Modules do not match: + sig module T : sig type t end type t = A of T.t end + is not included in + sig type t = A of T.t end + Type declarations do not match: + type t = A of T/1.t + is not included in + type t = A of T/2.t + The types for field A are not equal. + Line 5, characters 6-34: + Definition of module T/1 + Line 2, characters 2-30: + Definition of module T/2 +|}] + +module O = struct + module type s + type t = A + module M: sig val f: (module s) -> t -> t end = + struct module type s type t = B let f (module X:s) A = B end +end;; + +[%%expect{| +Line 5, characters 2-62: +5 | struct module type s type t = B let f (module X:s) A = B end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Signature mismatch: + Modules do not match: + sig module type s type t = B val f : (module s) -> t/2 -> t/1 end + is not included in + sig val f : (module s) -> t -> t end + Values do not match: + val f : (module s/1) -> t/2 -> t/1 + is not included in + val f : (module s/2) -> t/2 -> t/2 + Line 5, characters 23-33: + Definition of type t/1 + Line 3, characters 2-12: + Definition of type t/2 + Line 5, characters 9-22: + Definition of module type s/1 + Line 2, characters 2-15: + Definition of module type s/2 +|}] + +module P = struct + module type a + type a = A + module M : sig val f: a -> (module a) -> a end + = struct type a = B let f A _ = B end +end;; + +[%%expect{| +Line 5, characters 5-41: +5 | = struct type a = B let f A _ = B end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Signature mismatch: + Modules do not match: + sig type a = B val f : a/2 -> 'a -> a/1 end + is not included in + sig val f : a -> (module a) -> a end + Values do not match: + val f : a/2 -> 'a -> a/1 + is not included in + val f : a/2 -> (module a) -> a/2 + Line 5, characters 12-22: + Definition of type a/1 + Line 3, characters 2-12: + Definition of type a/2 +|}] + +module Q = struct + class a = object method m = () end + module M: sig class b: a end = + struct + class a = object method c = let module X = struct type t end in () end + class b = a + end +end;; + + +[%%expect{| +Line 4, characters 2-105: +4 | ..struct +5 | class a = object method c = let module X = struct type t end in () end +6 | class b = a +7 | end +Error: Signature mismatch: + Modules do not match: + sig class a : object method c : unit end class b : a end + is not included in + sig class b : a end + Class declarations do not match: + class b : a + does not match + class b : a/2 + The first class type has no method m + The public method c cannot be hidden + Line 5, characters 4-74: + Definition of class type a/1 + Line 2, characters 2-36: + Definition of class type a/2 +|}] + +module R = struct + class type a = object method m: unit end + module M: sig class type b= a end = + struct + class type a = object end + class type b = a + end +end;; + +[%%expect{| +Line 4, characters 2-65: +4 | ..struct +5 | class type a = object end +6 | class type b = a +7 | end +Error: Signature mismatch: + Modules do not match: + sig class type a = object end class type b = a end + is not included in + sig class type b = a end + Class type declarations do not match: + class type b = a/1 + does not match + class type b = a/2 + The first class type has no method m + Line 5, characters 4-29: + Definition of class type a/1 + Line 2, characters 2-42: + Definition of class type a/2 +|}] + +module S = struct + class a= object end + class b = a +end;; + +[%%expect{| +module S : sig class a : object end class b : a end +|}] + +module X: sig + type t + class type a = object method m:t end + module K: sig + type t + class type c = object method m: t end + end +end = struct + type t + class type a = object method m:t end + module K = struct + type t + class type c = object inherit a end + end +end;; + +[%%expect{| +Line 8, characters 6-141: + 8 | ......struct + 9 | type t +10 | class type a = object method m:t end +11 | module K = struct +12 | type t +13 | class type c = object inherit a end +14 | end +15 | end.. +Error: Signature mismatch: + Modules do not match: + sig + type t + class type a = object method m : t end + module K : sig type t class type c = object method m : t/2 end end + end + is not included in + sig + type t + class type a = object method m : t end + module K : sig type t class type c = object method m : t end end + end + In module K: + Modules do not match: + sig type t = K.t class type c = object method m : t/2 end end + is not included in + sig type t class type c = object method m : t end end + In module K: + Class type declarations do not match: + class type c = object method m : t/2 end + does not match + class type c = object method m : t/1 end + The method m has type t/2 but is expected to have type t/1 + Type t/2 is not compatible with type t/1 = K.t + Line 12, characters 4-10: + Definition of type t/1 + Line 9, characters 2-8: + Definition of type t/2 +|}] +;; + +module rec M: sig type t type a = M.t end = +struct type t module M = struct type t end type a = M.t end;; + +[%%expect{| +Line 2, characters 0-59: +2 | struct type t module M = struct type t end type a = M.t end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Signature mismatch: + Modules do not match: + sig type t = M.t module M : sig type t = M.M.t end type a = M.t end + is not included in + sig type t type a = M.t end + Type declarations do not match: + type a = M/1.t + is not included in + type a = M/2.t + Line 2, characters 14-42: + Definition of module M/1 + File "_none_", line 1: + Definition of module M/2 +|}] + + +(** Multiple redefinition of t *) +type t = A;; +type t = B;; +type t = C;; +type t = D;; +module M: sig val f: t -> t -> t -> t end = struct + let f A B C = D +end;; +[%%expect {| +type t = A +type t = B +type t = C +type t = D +Line 5, characters 44-72: +5 | ............................................struct +6 | let f A B C = D +7 | end.. +Error: Signature mismatch: + Modules do not match: + sig val f : t/2 -> t/3 -> t/4 -> t/1 end + is not included in + sig val f : t -> t -> t -> t end + Values do not match: + val f : t/2 -> t/3 -> t/4 -> t/1 + is not included in + val f : t/1 -> t/1 -> t/1 -> t/1 + Line 4, characters 0-10: + Definition of type t/1 + Line 1, characters 0-10: + Definition of type t/2 + Line 2, characters 0-10: + Definition of type t/3 + Line 3, characters 0-10: + Definition of type t/4 +|}] + +(** Check interaction with no-alias-deps *) +module Foo = struct + type info = { doc : unit } + type t = { info : info } +end +let add_extra_info arg = arg.Foo.info.doc +[%%expect {| +module Foo : sig type info = { doc : unit; } type t = { info : info; } end +Line 5, characters 38-41: +5 | let add_extra_info arg = arg.Foo.info.doc + ^^^ +Warning 40: doc was selected from type Foo.info. +It is not visible in the current scope, and will not +be selected if the type becomes unknown. +val add_extra_info : Foo.t -> unit = +|}] + +(** Check type-directed disambiguation *) +module Bar = struct + type info = { doc : unit } +end;; +module Foo = struct + type t = { info : Bar.info } +end;; +module Bar = struct end;; +let add_extra_info arg = arg.Foo.info.doc +[%%expect{| +module Bar : sig type info = { doc : unit; } end +module Foo : sig type t = { info : Bar.info; } end +module Bar : sig end +Line 8, characters 38-41: +8 | let add_extra_info arg = arg.Foo.info.doc + ^^^ +Warning 40: doc was selected from type Bar/2.info. +It is not visible in the current scope, and will not +be selected if the type becomes unknown. +val add_extra_info : Foo.t -> unit = +|}] diff --git a/testsuite/tests/typing-misc/pr6634.ml b/testsuite/tests/typing-misc/pr6634.ml new file mode 100644 index 00000000..2faf7c98 --- /dev/null +++ b/testsuite/tests/typing-misc/pr6634.ml @@ -0,0 +1,30 @@ +(* TEST + * expect + *) + +type t = int +module M : sig type t end with type t = [`T of t] = +struct + type t = [`T of t] +end;; + +[%%expect{| +type t = int +Line 3, characters 0-31: +3 | struct +4 | type t = [`T of t] +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig type t = [ `T of t ] end + is not included in + sig type t = [ `T of t ] end + Type declarations do not match: + type t = [ `T of t/2 ] + is not included in + type t = [ `T of t/1 ] + Line 1, characters 0-12: + Definition of type t/1 + Line 4, characters 2-20: + Definition of type t/2 +|}] diff --git a/testsuite/tests/typing-misc/pr6939-flat-float-array.ml b/testsuite/tests/typing-misc/pr6939-flat-float-array.ml index 63e59441..2fe2fcd5 100644 --- a/testsuite/tests/typing-misc/pr6939-flat-float-array.ml +++ b/testsuite/tests/typing-misc/pr6939-flat-float-array.ml @@ -5,20 +5,20 @@ let rec x = [| x |]; 1.;; [%%expect{| -Line _, characters 12-19: - let rec x = [| x |]; 1.;; - ^^^^^^^ +Line 1, characters 12-19: +1 | let rec x = [| x |]; 1.;; + ^^^^^^^ Warning 10: this expression should have type unit. -Line _, characters 12-23: - let rec x = [| x |]; 1.;; - ^^^^^^^^^^^ +Line 1, characters 12-23: +1 | let rec x = [| x |]; 1.;; + ^^^^^^^^^^^ Error: This kind of expression is not allowed as right-hand side of `let rec' |}];; let rec x = let u = [|y|] in 10. and y = 1.;; [%%expect{| -Line _, characters 12-32: - let rec x = let u = [|y|] in 10. and y = 1.;; - ^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 12-32: +1 | let rec x = let u = [|y|] in 10. and y = 1.;; + ^^^^^^^^^^^^^^^^^^^^ Error: This kind of expression is not allowed as right-hand side of `let rec' |}];; diff --git a/testsuite/tests/typing-misc/pr6939-no-flat-float-array.ml b/testsuite/tests/typing-misc/pr6939-no-flat-float-array.ml index 84409761..a08bb57a 100644 --- a/testsuite/tests/typing-misc/pr6939-no-flat-float-array.ml +++ b/testsuite/tests/typing-misc/pr6939-no-flat-float-array.ml @@ -5,18 +5,18 @@ let rec x = [| x |]; 1.;; [%%expect{| -Line _, characters 12-19: - let rec x = [| x |]; 1.;; - ^^^^^^^ +Line 1, characters 12-19: +1 | let rec x = [| x |]; 1.;; + ^^^^^^^ Warning 10: this expression should have type unit. val x : float = 1. |}];; let rec x = let u = [|y|] in 10. and y = 1.;; [%%expect{| -Line _, characters 16-17: - let rec x = let u = [|y|] in 10. and y = 1.;; - ^ +Line 1, characters 16-17: +1 | let rec x = let u = [|y|] in 10. and y = 1.;; + ^ Warning 26: unused variable u. val x : float = 10. val y : float = 1. diff --git a/testsuite/tests/typing-misc/pr7103.ml b/testsuite/tests/typing-misc/pr7103.ml index 706e3731..524ca3f7 100644 --- a/testsuite/tests/typing-misc/pr7103.ml +++ b/testsuite/tests/typing-misc/pr7103.ml @@ -20,9 +20,9 @@ val h : [> `b ] t -> unit = let _ = fun (x : a t) -> f x;; [%%expect{| -Line _, characters 27-28: - let _ = fun (x : a t) -> f x;; - ^ +Line 1, characters 27-28: +1 | let _ = fun (x : a t) -> f x;; + ^ Error: This expression has type a t but an expression was expected of type (< .. > as 'a) t Type a is not compatible with type < .. > as 'a @@ -30,9 +30,9 @@ Error: This expression has type a t but an expression was expected of type let _ = fun (x : a t) -> g x;; [%%expect{| -Line _, characters 27-28: - let _ = fun (x : a t) -> g x;; - ^ +Line 1, characters 27-28: +1 | let _ = fun (x : a t) -> g x;; + ^ Error: This expression has type a t but an expression was expected of type ([< `b ] as 'a) t Type a is not compatible with type [< `b ] as 'a @@ -40,9 +40,9 @@ Error: This expression has type a t but an expression was expected of type let _ = fun (x : a t) -> h x;; [%%expect{| -Line _, characters 27-28: - let _ = fun (x : a t) -> h x;; - ^ +Line 1, characters 27-28: +1 | let _ = fun (x : a t) -> h x;; + ^ Error: This expression has type a t but an expression was expected of type ([> `b ] as 'a) t Type a is not compatible with type [> `b ] as 'a diff --git a/testsuite/tests/typing-misc/pr7228.ml b/testsuite/tests/typing-misc/pr7228.ml index ff48b073..1e98cca5 100644 --- a/testsuite/tests/typing-misc/pr7228.ml +++ b/testsuite/tests/typing-misc/pr7228.ml @@ -14,8 +14,8 @@ type t = private A of {mutable x: int};; fun (A r) -> r.x <- 42;; [%%expect{| type t = private A of { mutable x : int; } -Line _, characters 15-16: - fun (A r) -> r.x <- 42;; - ^ +Line 2, characters 15-16: +2 | fun (A r) -> r.x <- 42;; + ^ Error: Cannot assign field x of the private type t.A |}];; diff --git a/testsuite/tests/typing-misc/pr7668_bad.ml b/testsuite/tests/typing-misc/pr7668_bad.ml index 8eca88d2..5dccf5ac 100644 --- a/testsuite/tests/typing-misc/pr7668_bad.ml +++ b/testsuite/tests/typing-misc/pr7668_bad.ml @@ -20,10 +20,73 @@ else `Right ()) xs val partition_map : ('a -> [< `Left of 'b | `Right of 'c ]) -> 'a list -> 'b list * 'c list = -Line _, characters 35-96: - ...................................partition_map (fun x -> if x then `Left () - else `Right ()) xs +Line 12, characters 35-96: +12 | ...................................partition_map (fun x -> if x then `Left () +13 | else `Right ()) xs Error: This expression has type unit list * unit list but an expression was expected of type int list * int list Type unit is not compatible with type int |}] + +module M : sig + type t = [ + | `A of int + | `B of [ `BA | `BB of unit list ] + | `C of unit ] + + val a : t -> t +end = struct + type t = [ + | `A of int + | `B of [ `BA | `BB of unit list ] + | `C of unit ] + +let a b = + let f = function + | Ok x -> x + | Error _ -> `C () + in + f (match b with + | `A pc -> + begin match pc with + | 1 -> Ok (`B `BA) + | _ -> Ok (`B (`BB [1;2;3])) + end + | _ -> assert false) + +end +;; +[%%expect{| +Line 8, characters 6-348: + 8 | ......struct + 9 | type t = [ +10 | | `A of int +11 | | `B of [ `BA | `BB of unit list ] +12 | | `C of unit ] +... +24 | end +25 | | _ -> assert false) +26 | +27 | end +Error: Signature mismatch: + Modules do not match: + sig + type t = + [ `A of int | `B of [ `BA | `BB of unit list ] | `C of unit ] + val a : + [> `A of int ] -> + [> `B of [> `BA | `BB of int list ] | `C of unit ] + end + is not included in + sig + type t = + [ `A of int | `B of [ `BA | `BB of unit list ] | `C of unit ] + val a : t -> t + end + Values do not match: + val a : + [> `A of int ] -> + [> `B of [> `BA | `BB of int list ] | `C of unit ] + is not included in + val a : t -> t +|}] diff --git a/testsuite/tests/typing-misc/pr8548.ml b/testsuite/tests/typing-misc/pr8548.ml new file mode 100644 index 00000000..c50809af --- /dev/null +++ b/testsuite/tests/typing-misc/pr8548.ml @@ -0,0 +1,146 @@ +(* TEST + * expect *) + +module type Endpoint_intf = sig + type t +end +;; +[%%expect{| +module type Endpoint_intf = sig type t end +|}] + +module type S = sig + module Endpoint : Endpoint_intf + + type finite = [ `Before of Endpoint.t ] + type infinite = [ `Until_infinity ] + + type +'a range = private { until : 'a } constraint 'a = [< finite | infinite ] + + val until : 'a range -> 'a +end +;; +[%%expect{| +module type S = + sig + module Endpoint : Endpoint_intf + type finite = [ `Before of Endpoint.t ] + type infinite = [ `Until_infinity ] + type +'a range = private { until : 'a; } + constraint 'a = [< `Before of Endpoint.t | `Until_infinity ] + val until : + ([< `Before of Endpoint.t | `Until_infinity ] as 'a) range -> 'a + end +|}] + +module type Ranged = sig + module Endpoint : Endpoint_intf + module Range : S with type Endpoint.t = Endpoint.t +end +;; +[%%expect{| +module type Ranged = + sig + module Endpoint : Endpoint_intf + module Range : + sig + module Endpoint : sig type t = Endpoint.t end + type finite = [ `Before of Endpoint.t ] + type infinite = [ `Until_infinity ] + type +'a range = private { until : 'a; } + constraint 'a = [< `Before of Endpoint.t | `Until_infinity ] + val until : + ([< `Before of Endpoint.t | `Until_infinity ] as 'a) range -> 'a + end + end +|}] + +module Assume (Given : sig + module Make_range (Endpoint : Endpoint_intf) : + S with module Endpoint = Endpoint + + module Make_ranged (Range : S) : + Ranged with module Endpoint = Range.Endpoint + and module Range = Range + end) = +struct + module Point = struct + type t + end + + open Given + + module Test_range = Make_range(Point) + module Test_ranged = Make_ranged(Test_range) +end +;; +[%%expect{| +module Assume : + functor + (Given : sig + module Make_range : + functor (Endpoint : Endpoint_intf) -> + sig + module Endpoint : sig type t = Endpoint.t end + type finite = [ `Before of Endpoint.t ] + type infinite = [ `Until_infinity ] + type +'a range = private { until : 'a; } + constraint 'a = + [< `Before of Endpoint.t | `Until_infinity ] + val until : + ([< `Before of Endpoint.t | `Until_infinity ] as 'a) + range -> 'a + end + module Make_ranged : + functor (Range : S) -> + sig + module Endpoint : sig type t = Range.Endpoint.t end + module Range : + sig + module Endpoint : sig type t = Range.Endpoint.t end + type finite = [ `Before of Endpoint.t ] + type infinite = [ `Until_infinity ] + type +'a range = + 'a Range.range = private { + until : 'a; + } + constraint 'a = + [< `Before of Endpoint.t | `Until_infinity ] + val until : + ([< `Before of Endpoint.t | `Until_infinity ] + as 'a) + range -> 'a + end + end + end) -> + sig + module Point : sig type t end + module Test_range : + sig + module Endpoint : sig type t = Point.t end + type finite = [ `Before of Endpoint.t ] + type infinite = [ `Until_infinity ] + type +'a range = + 'a Given.Make_range(Point).range = private { + until : 'a; + } constraint 'a = [< `Before of Endpoint.t | `Until_infinity ] + val until : + ([< `Before of Endpoint.t | `Until_infinity ] as 'a) range -> 'a + end + module Test_ranged : + sig + module Endpoint : sig type t = Test_range.Endpoint.t end + module Range : + sig + module Endpoint : sig type t = Test_range.Endpoint.t end + type finite = [ `Before of Endpoint.t ] + type infinite = [ `Until_infinity ] + type +'a range = 'a Test_range.range = private { until : 'a; } + constraint 'a = [< `Before of Endpoint.t | `Until_infinity ] + val until : + ([< `Before of Endpoint.t | `Until_infinity ] as 'a) range -> + 'a + end + end + end +|}] diff --git a/testsuite/tests/typing-misc/pr8548_split.ml b/testsuite/tests/typing-misc/pr8548_split.ml new file mode 100644 index 00000000..65f9a00c --- /dev/null +++ b/testsuite/tests/typing-misc/pr8548_split.ml @@ -0,0 +1,20 @@ +(* TEST +files = "mapping.ml range_intf.ml ranged_intf.ml range.ml ranged.ml" +* setup-ocamlc.byte-build-env +** ocamlc.byte +flags = "-no-alias-deps -w -49 -o Pr8548__Mapping" +module = "mapping.ml" +** ocamlc.byte +flags = "-no-alias-deps -open Pr8548__Mapping -o pr8548__Range_intf.cmo" +module = "range_intf.ml" +*** ocamlc.byte +flags = "-no-alias-deps -open Pr8548__Mapping -o pr8548__Range.cmo" +module = "range.ml" +*** ocamlc.byte +flags = "-no-alias-deps -open Pr8548__Mapping -o pr8548__Ranged_intf.cmo" +module = "ranged_intf.ml" +**** ocamlc.byte +flags = "-no-alias-deps -open Pr8548__Mapping -o pr8548__Ranged.cmo" +module = "ranged.ml" +ocamlc_byte_exit_status = "0" +*) diff --git a/testsuite/tests/typing-misc/printing.ml b/testsuite/tests/typing-misc/printing.ml index 48a8c7ed..9108b55a 100644 --- a/testsuite/tests/typing-misc/printing.ml +++ b/testsuite/tests/typing-misc/printing.ml @@ -6,9 +6,9 @@ type t = [ 'A_name | `Hi ];; [%%expect{| -Line _, characters 11-18: - type t = [ 'A_name | `Hi ];; - ^^^^^^^ +Line 1, characters 11-18: +1 | type t = [ 'A_name | `Hi ];; + ^^^^^^^ Error: The type 'A_name does not expand to a polymorphic variant type Hint: Did you mean `A_name? |}];; @@ -43,3 +43,11 @@ let f x = (x :> G.t);; module G = M.N val f : [< G.t ] -> G.t = |}] + + +(* GPR#2034 *) + +type (+' a', -' a'b, 'cd') t = ' a'b -> ' a' * 'cd';; +[%%expect{| +type (' a', ' a'b, 'cd') t = ' a'b -> ' a' * 'cd' +|}];; diff --git a/testsuite/tests/typing-misc/range.ml b/testsuite/tests/typing-misc/range.ml new file mode 100644 index 00000000..fd83af95 --- /dev/null +++ b/testsuite/tests/typing-misc/range.ml @@ -0,0 +1,16 @@ +module Make (Endpoint : Range_intf.Endpoint_intf) : + Range_intf.S with module Endpoint = Endpoint += struct + module Endpoint = Endpoint + + type finite = [ `Before of Endpoint.t ] + type infinite = [ `Until_infinity ] + + type +'a range = { until : 'a } constraint 'a = [< finite | infinite ] + + let until r = r.until + + type t = [finite | infinite] range + + let compare_range _ _ _ = 0 +end diff --git a/testsuite/tests/typing-misc/range_intf.ml b/testsuite/tests/typing-misc/range_intf.ml new file mode 100644 index 00000000..4a620a9b --- /dev/null +++ b/testsuite/tests/typing-misc/range_intf.ml @@ -0,0 +1,16 @@ +module type Endpoint_intf = sig + type t +end + +module type S = sig + module Endpoint : Endpoint_intf + + type finite = [ `Before of Endpoint.t ] + type infinite = [ `Until_infinity ] + + type +'a range = private { until : 'a } constraint 'a = [< finite | infinite ] + + val compare_range : ('a -> 'a -> int) -> 'a range -> 'a range -> int + + type t = [finite | infinite] range +end diff --git a/testsuite/tests/typing-misc/ranged.ml b/testsuite/tests/typing-misc/ranged.ml new file mode 100644 index 00000000..3aadcc52 --- /dev/null +++ b/testsuite/tests/typing-misc/ranged.ml @@ -0,0 +1,14 @@ +module Make (Range : Range_intf.S) : + Ranged_intf.S with module Endpoint = Range.Endpoint + and module Range = Range += struct + module Endpoint = Range.Endpoint + module Range = Range +end + +module Test = struct + type t = T +end + +module Test_range = Range.Make(Test) +module Test_ranged = Make(Test_range) diff --git a/testsuite/tests/typing-misc/ranged_intf.ml b/testsuite/tests/typing-misc/ranged_intf.ml new file mode 100644 index 00000000..1672d6e7 --- /dev/null +++ b/testsuite/tests/typing-misc/ranged_intf.ml @@ -0,0 +1,4 @@ +module type S = sig + module Endpoint : Range_intf.Endpoint_intf + module Range : Range_intf.S with type Endpoint.t = Endpoint.t +end diff --git a/testsuite/tests/typing-misc/records.ml b/testsuite/tests/typing-misc/records.ml index 190b0b18..1d26860b 100644 --- a/testsuite/tests/typing-misc/records.ml +++ b/testsuite/tests/typing-misc/records.ml @@ -7,25 +7,25 @@ type t = {x:int;y:int};; {x=3;z=2};; [%%expect{| type t = { x : int; y : int; } -Line _, characters 5-6: - {x=3;z=2};; - ^ +Line 2, characters 5-6: +2 | {x=3;z=2};; + ^ Error: Unbound record field z |}];; fun {x=3;z=2} -> ();; [%%expect{| -Line _, characters 9-10: - fun {x=3;z=2} -> ();; - ^ +Line 1, characters 9-10: +1 | fun {x=3;z=2} -> ();; + ^ Error: Unbound record field z |}];; (* mixed labels *) {x=3; contents=2};; [%%expect{| -Line _, characters 6-14: - {x=3; contents=2};; - ^^^^^^^^ +Line 1, characters 6-14: +1 | {x=3; contents=2};; + ^^^^^^^^ Error: The record field contents belongs to the type 'a ref but is mixed here with fields of type t |}];; @@ -35,16 +35,16 @@ type u = private {mutable u:int};; {u=3};; [%%expect{| type u = private { mutable u : int; } -Line _, characters 0-5: - {u=3};; - ^^^^^ +Line 2, characters 0-5: +2 | {u=3};; + ^^^^^ Error: Cannot create values of the private type u |}];; fun x -> x.u <- 3;; [%%expect{| -Line _, characters 11-12: - fun x -> x.u <- 3;; - ^ +Line 1, characters 11-12: +1 | fun x -> x.u <- 3;; + ^ Error: Cannot assign field u of the private type u |}];; @@ -70,13 +70,26 @@ type foo = { mutable y:int };; let f (r: int) = r.y <- 3;; [%%expect{| type foo = { mutable y : int; } -Line _, characters 17-18: - let f (r: int) = r.y <- 3;; - ^ +Line 2, characters 17-18: +2 | let f (r: int) = r.y <- 3;; + ^ Error: This expression has type int but an expression was expected of type foo |}];; +let f (r: int) = + match r with + | { contents = 3 } -> () +[%%expect{| +Line 3, characters 4-20: +3 | | { contents = 3 } -> () + ^^^^^^^^^^^^^^^^ +Error: This pattern matches values of type int ref + but a pattern was expected which matches values of type int +|}];; + + + (* bugs *) type foo = { y: int; z: int };; type bar = { x: int };; @@ -84,9 +97,9 @@ let f (r: bar) = ({ r with z = 3 } : foo) [%%expect{| type foo = { y : int; z : int; } type bar = { x : int; } -Line _, characters 20-21: - let f (r: bar) = ({ r with z = 3 } : foo) - ^ +Line 3, characters 20-21: +3 | let f (r: bar) = ({ r with z = 3 } : foo) + ^ Error: This expression has type bar but an expression was expected of type foo |}];; @@ -95,35 +108,35 @@ type foo = { x: int };; let r : foo = { ZZZ.x = 2 };; [%%expect{| type foo = { x : int; } -Line _, characters 16-21: - let r : foo = { ZZZ.x = 2 };; - ^^^^^ +Line 2, characters 16-21: +2 | let r : foo = { ZZZ.x = 2 };; + ^^^^^ Error: Unbound module ZZZ |}];; (ZZZ.X : int option);; [%%expect{| -Line _, characters 1-6: - (ZZZ.X : int option);; - ^^^^^ +Line 1, characters 1-6: +1 | (ZZZ.X : int option);; + ^^^^^ Error: Unbound module ZZZ |}];; (* PR#5865 *) let f (x : Complex.t) = x.Complex.z;; [%%expect{| -Line _, characters 26-35: - let f (x : Complex.t) = x.Complex.z;; - ^^^^^^^^^ +Line 1, characters 26-35: +1 | let f (x : Complex.t) = x.Complex.z;; + ^^^^^^^^^ Error: Unbound record field Complex.z |}];; (* PR#6608 *) { true with contents = 0 };; [%%expect{| -Line _, characters 2-6: - { true with contents = 0 };; - ^^^^ +Line 1, characters 2-6: +1 | { true with contents = 0 };; + ^^^^ Error: This expression has type bool but an expression was expected of type 'a ref |}];; @@ -144,9 +157,9 @@ let x = { f = 12; g = 43 };; [%%expect{| type 'a t = { f : 'a; g : 'a; } val x : int t = {f = 12; g = 43} -Line _, characters 0-19: - {x with f = "hola"};; - ^^^^^^^^^^^^^^^^^^^ +Line 3, characters 0-19: +3 | {x with f = "hola"};; + ^^^^^^^^^^^^^^^^^^^ Error: This expression has type string t but an expression was expected of type int t Type string is not compatible with type int diff --git a/testsuite/tests/typing-misc/scope_escape.ml b/testsuite/tests/typing-misc/scope_escape.ml new file mode 100644 index 00000000..94a47d23 --- /dev/null +++ b/testsuite/tests/typing-misc/scope_escape.ml @@ -0,0 +1,15 @@ +(* TEST + * expect +*) + +let x = ref [] +module M = struct type t let _ = (x : t list ref) end;; +[%%expect{| +val x : '_weak1 list ref = {contents = []} +Line 2, characters 34-35: +2 | module M = struct type t let _ = (x : t list ref) end;; + ^ +Error: This expression has type 'weak1 list ref + but an expression was expected of type t list ref + The type constructor t would escape its scope +|}] diff --git a/testsuite/tests/typing-misc/typecore_empty_polyvariant_error.compilers.reference b/testsuite/tests/typing-misc/typecore_empty_polyvariant_error.compilers.reference new file mode 100644 index 00000000..39673507 --- /dev/null +++ b/testsuite/tests/typing-misc/typecore_empty_polyvariant_error.compilers.reference @@ -0,0 +1,6 @@ +type t = [ ] +Line 1, characters 31-32: +1 | let f: 'a. t -> 'a = function #t -> . ;; + ^ +Error: The type t is not a variant type + diff --git a/testsuite/tests/typing-misc/typecore_empty_polyvariant_error.ml b/testsuite/tests/typing-misc/typecore_empty_polyvariant_error.ml new file mode 100644 index 00000000..11c23d9b --- /dev/null +++ b/testsuite/tests/typing-misc/typecore_empty_polyvariant_error.ml @@ -0,0 +1,13 @@ +(* TEST + files="empty_ppx.ml" + * setup-ocamlc.byte-build-env + ** ocamlc.byte with ocamlcommon + all_modules="empty_ppx.ml" + program="ppx.exe" + *** toplevel + all_modules="${test_file}" + flags="-ppx '${ocamlrun} ${test_build_directory_prefix}/ocamlc.byte/ppx.exe'" +*) + +type t = [%empty_polyvar];; +let f: 'a. t -> 'a = function #t -> . ;; diff --git a/testsuite/tests/typing-misc/typecore_errors.ml b/testsuite/tests/typing-misc/typecore_errors.ml new file mode 100644 index 00000000..3d62f3f6 --- /dev/null +++ b/testsuite/tests/typing-misc/typecore_errors.ml @@ -0,0 +1,475 @@ +(* TEST + * expect +*) + + +(** Gives an example for every [raise(Error(_,_,_)] in typing/typecore.ml + that is no covered by another test in the testsuite and does not + require special flags or ppx. +*) + +(** Illegal interval *) + +let x = function 0. .. 1. -> () +[%%expect {| +Line 8, characters 17-25: +8 | let x = function 0. .. 1. -> () + ^^^^^^^^ +Error: Only character intervals are supported in patterns. +|}] + +(** Constructor arity mismatch *) +let f = function None None -> 0 + +[%%expect{| +Line 1, characters 17-26: +1 | let f = function None None -> 0 + ^^^^^^^^^ +Error: The constructor None expects 0 argument(s), + but is applied here to 1 argument(s) +|}] + +let x = None None +[%%expect{| +Line 1, characters 8-17: +1 | let x = None None + ^^^^^^^^^ +Error: The constructor None expects 0 argument(s), + but is applied here to 1 argument(s) +|}] + +(** Inline record escape *) +type t = A of {x:int} +let f = function (A (x:_)) -> 0 + +[%%expect{| +type t = A of { x : int; } +Line 2, characters 20-25: +2 | let f = function (A (x:_)) -> 0 + ^^^^^ +Error: This form is not allowed as the type of the inlined record could escape. +|}] + + +(** Exception below toplevel *) +let f = function Some(exception Not_found) -> 0 +[%%expect{| +Line 1, characters 21-42: +1 | let f = function Some(exception Not_found) -> 0 + ^^^^^^^^^^^^^^^^^^^^^ +Error: Exception patterns are not allowed in this position. +|}] + +(** Extension *) +let f = function [%ext] -> 0 +[%%expect{| +Line 1, characters 19-22: +1 | let f = function [%ext] -> 0 + ^^^ +Error: Uninterpreted extension 'ext'. +|}] + + +(** Unification error in type approx *) + +let rec f x = ( (), () : _ -> _ -> _ ) +[%%expect{| +Line 3, characters 14-38: +3 | let rec f x = ( (), () : _ -> _ -> _ ) + ^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This expression has type 'a * 'b + but an expression was expected of type 'c -> 'd -> 'e +|}] + +let rec g x = ( ((), ()) : _ -> _ :> _ ) +[%%expect{| +Line 1, characters 14-40: +1 | let rec g x = ( ((), ()) : _ -> _ :> _ ) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This expression has type 'a * 'b + but an expression was expected of type 'c -> 'd +|}] + + +(** Masked instance variable *) +let c = object val x= 0 val y = x end +[%%expect{| +Line 1, characters 32-33: +1 | let c = object val x= 0 val y = x end + ^ +Error: The instance variable x + cannot be accessed from the definition of another instance variable +|}] + + +(** No value clause *) + +let f x = match x with exception Not_found -> ();; +[%%expect{| +Line 3, characters 10-48: +3 | let f x = match x with exception Not_found -> ();; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: None of the patterns in this 'match' expression match values. +|}] + +(** Check duplicate *) +type r = { x : int } +let r = { x= 1; x= 1} + +[%%expect{| +type r = { x : int; } +Line 2, characters 8-21: +2 | let r = { x= 1; x= 1} + ^^^^^^^^^^^^^ +Error: The record field label x is defined several times +|}] + +(** Non-mutable is non mutable *) +let () = { x = 1 }.x <- 2 + +[%%expect{| +Line 1, characters 9-25: +1 | let () = { x = 1 }.x <- 2 + ^^^^^^^^^^^^^^^^ +Error: The record field x is not mutable +|}] + + +(** Invalid for loop *) + +let () = for Some i = 3 to 4 do () done; +[%%expect{| +Line 3, characters 13-19: +3 | let () = for Some i = 3 to 4 do () done; + ^^^^^^ +Error: Invalid for-loop index: only variables and _ are allowed. +|}] + + +(** Inherited methods not defined *) + +class virtual v = object method virtual m: int end;; +class c = object(self) + inherit v as super + method m = 0 + method x: int = super#m +end;; + +[%%expect{| +class virtual v : object method virtual m : int end +Line 7, characters 18-23: +7 | method x: int = super#m + ^^^^^ +Error: This expression has no method m +|}] + +(** New virtual class *) + +let x = new v + +[%%expect{| +Line 3, characters 8-13: +3 | let x = new v + ^^^^^ +Error: Cannot instantiate the virtual class v +|}] + + +(* Immutable instance variable cannot be mutated *) +let x = object val x = 1 method m = x<-0 end + +[%%expect{| +Line 1, characters 36-40: +1 | let x = object val x = 1 method m = x<-0 end + ^^^^ +Error: The instance variable x is not mutable +|}] + +(** Self variables cannot be mutated *) +let x = object(self) method m = self <-0 end + +[%%expect{| +Line 1, characters 32-40: +1 | let x = object(self) method m = self <-0 end + ^^^^^^^^ +Error: The value self is not an instance variable +|}] + +(** Multiply override *) + +class c = object val x = 0 method m: c = {< x=0; x=1 >} end + +[%%expect{| +Line 3, characters 41-55: +3 | class c = object val x = 0 method m: c = {< x=0; x=1 >} end + ^^^^^^^^^^^^^^ +Error: The instance variable x is overridden several times +|}] + +(** Override outside of classes *) + +let f x = {< y = x >} + +[%%expect{| +Line 3, characters 10-21: +3 | let f x = {< y = x >} + ^^^^^^^^^^^ +Error: This object duplication occurs outside a method definition +|}] + + +(** Unbound instance variable in object duplication *) + +class c = object val x = 0 method m: c = {< y=1 >} end + +[%%expect{| +Line 3, characters 41-50: +3 | class c = object val x = 0 method m: c = {< y=1 >} end + ^^^^^^^^^ +Error: Unbound instance variable y +|}] + + +(** Not a packed type *) +module type empty = sig end +let f (x:int) = () +let x = f (module struct end) +[%%expect {| +module type empty = sig end +val f : int -> unit = +Line 3, characters 10-29: +3 | let x = f (module struct end) + ^^^^^^^^^^^^^^^^^^^ +Error: This expression is packed module, but the expected type is int +|}] + + +(** Builtin [%extension_constructor *) +type t = A +let x = [%extension_constructor A] +[%%expect {| +type t = A +Line 2, characters 32-33: +2 | let x = [%extension_constructor A] + ^ +Error: This constructor is not an extension constructor. +|}] + +let x = [%extension_constructor] +[%%expect {| +Line 1, characters 8-32: +1 | let x = [%extension_constructor] + ^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Invalid [%extension_constructor] payload, a constructor is expected. +|}] + +(** Invalid format *) +let x = format_of_string "%z" +[%%expect {| +Line 1, characters 25-29: +1 | let x = format_of_string "%z" + ^^^^ +Error: invalid format "%z": at character number 1, invalid conversion "%z" +|}] + +(** Apply wrong label *) + +let f ~x = x + 2 +let y = f ~y:1 +[%%expect {| +val f : x:int -> int = +Line 4, characters 13-14: +4 | let y = f ~y:1 + ^ +Error: The function applied to this argument has type x:int -> int +This argument cannot be applied with label ~y +|}] + +let g f = f ~x:0 ~y:0; f ~y:0 ~x:0 +[%%expect {| +Line 1, characters 23-24: +1 | let g f = f ~x:0 ~y:0; f ~y:0 ~x:0 + ^ +Error: This function is applied to arguments + in an order different from other calls. + This is only allowed when the real type is known. +|}] + +(** Inlined record *) +type t = A of { x: int } +let x = A 1 +[%%expect {| +type t = A of { x : int; } +Line 2, characters 8-11: +2 | let x = A 1 + ^^^ +Error: This constructor expects an inlined record argument. +|}] + +(** Illegal let rec *) +type 'a t = A of 'a +let rec A x = A (A ()) + +[%%expect {| +type 'a t = A of 'a +Line 2, characters 8-11: +2 | let rec A x = A (A ()) + ^^^ +Error: Only variables are allowed as left-hand side of `let rec' +|}] + +(** Non-linear pattern *) + +let quadratic (x,x) = x * x +[%%expect {| +Line 3, characters 17-18: +3 | let quadratic (x,x) = x * x + ^ +Error: Variable x is bound several times in this matching +|}] + +(** Or-patter clash *) +type t = A of int | B of float|C +let f (A x|B x) = 0 +[%%expect {| +type t = A of int | B of float | C +Line 2, characters 6-15: +2 | let f (A x|B x) = 0 + ^^^^^^^^^ +Error: The variable x on the left-hand side of this or-pattern has type + int but on the right-hand side it has type float +|}] + +(** Orphan pattern variable *) + +let f (A x|C) = 0 +[%%expect {| +Line 3, characters 6-13: +3 | let f (A x|C) = 0 + ^^^^^^^ +Error: Variable x must occur on both sides of this | pattern +|}] + + +let f (A x|B y) = 0 +[%%expect {| +Line 1, characters 6-15: +1 | let f (A x|B y) = 0 + ^^^^^^^^^ +Error: Variable x must occur on both sides of this | pattern +|}] + +(** #t *) +type t = [] +let f = function #t -> () +[%%expect {| +type t = [] +Line 2, characters 18-19: +2 | let f = function #t -> () + ^ +Error: The type t is not a variant type +|}] + +let f {x;x=y;x=z} = x +[%%expect {| +Line 1, characters 6-17: +1 | let f {x;x=y;x=z} = x + ^^^^^^^^^^^ +Error: The record field label x is defined several times +|}] + +(** Coercion failure *) + +let x = ([`B]:>[`A]) +[%%expect {| +Line 3, characters 9-13: +3 | let x = ([`B]:>[`A]) + ^^^^ +Error: This expression cannot be coerced to type [ `A ]; it has type + [> `B ] list + but is here used with type [< `A ] +|}] + +(** Unbound instance variable *) + +let o = object method m = instance <- 0 end + +[%%expect{| +Line 3, characters 26-39: +3 | let o = object method m = instance <- 0 end + ^^^^^^^^^^^^^ +Error: Unbound instance variable instance +|}] + + +(** Hash collision *) +let x = function + | `azdwbie -> () + | `c7diagq -> () +[%%expect{| +Line 3, characters 4-12: +3 | | `c7diagq -> () + ^^^^^^^^ +Error: Variant tags `azdwbie and `c7diagq have the same hash value. + Change one of them. +|}] + + +let x = `azdwbie = `c7diagq +[%%expect{| +Line 1, characters 20-28: +1 | let x = `azdwbie = `c7diagq + ^^^^^^^^ +Error: Variant tags `azdwbie and `c7diagq have the same hash value. + Change one of them. +|}] + +type 'a x = + | X: [>`azdwbie] x + | Y: [>`c7diagq] x + +let x = function + | X -> () + | Y -> () + +[%%expect{| +type 'a x = X : [> `azdwbie ] x | Y : [> `c7diagq ] x +Line 7, characters 4-5: +7 | | Y -> () + ^ +Error: Variant tags `azdwbie and `c7diagq have the same hash value. + Change one of them. +|}] + + +type t = {x:unit} +type s = {y:unit} +let f = function {x; y} -> x +[%%expect {| +type t = { x : unit; } +type s = { y : unit; } +Line 3, characters 21-22: +3 | let f = function {x; y} -> x + ^ +Error: The record field y belongs to the type s + but is mixed here with fields of type t +|}] + + +(** Error extension node *) + +let x = [%ocaml.error "Expression error"] +[%%expect {| +Line 3, characters 10-21: +3 | let x = [%ocaml.error "Expression error"] + ^^^^^^^^^^^ +Error: Expression error +|}] + +let f [%ocaml.error "Pattern error"] = () +[%%expect {| +Line 1, characters 8-19: +1 | let f [%ocaml.error "Pattern error"] = () + ^^^^^^^^^^^ +Error: Pattern error +|}] diff --git a/testsuite/tests/typing-misc/typecore_nolabel_errors.ml b/testsuite/tests/typing-misc/typecore_nolabel_errors.ml new file mode 100644 index 00000000..0efcd8d0 --- /dev/null +++ b/testsuite/tests/typing-misc/typecore_nolabel_errors.ml @@ -0,0 +1,50 @@ +(* TEST + flags="-nolabels" + * expect +*) + + +(** Gives an example for every [raise(Error(_,_,_)] in typing/typecore.ml + which both requires the "-nolabel" flags and is no covered by another test + in the testsuite. +*) + +let check f = f () + +let f ~x = () +let () = check f;; +[%%expect {| +val check : (unit -> 'a) -> 'a = +val f : x:'a -> unit = +|}] + +let () = f ~y:1 +[%%expect {| +Line 1, characters 14-15: +1 | let () = f ~y:1 + ^ +Error: The function applied to this argument has type x:'a -> unit +This argument cannot be applied with label ~y +|}] + +let f ?x ~a ?y ~z = () +let g = f ?y:None ?x:None ~a:() +[%%expect {| +val f : ?x:'a -> a:'b -> ?y:'c -> z:'d -> unit = +Line 2, characters 13-17: +2 | let g = f ?y:None ?x:None ~a:() + ^^^^ +Error: The function applied to this argument has type + ?x:'a -> a:'b -> ?y:'c -> z:'d -> unit +This argument cannot be applied with label ?y +|}] + +let f (g: ?x:_ -> _) = g ~y:None ?x:None; g ?x:None () + +[%%expect{| +Line 1, characters 28-32: +1 | let f (g: ?x:_ -> _) = g ~y:None ?x:None; g ?x:None () + ^^^^ +Error: The function applied to this argument has type ?x:'a -> 'b +This argument cannot be applied with label ~y +|}] diff --git a/testsuite/tests/typing-misc/typetexp_errors.ml b/testsuite/tests/typing-misc/typetexp_errors.ml new file mode 100644 index 00000000..8bbd9cbb --- /dev/null +++ b/testsuite/tests/typing-misc/typetexp_errors.ml @@ -0,0 +1,25 @@ +(* TEST + * expect +*) + +type ('a,'at,'any,'en) t = A of 'an +[%%expect {| +Line 1, characters 32-35: +1 | type ('a,'at,'any,'en) t = A of 'an + ^^^ +Error: The type variable 'an is unbound in this type declaration. +Hint: Did you mean 'a, 'any, 'at or 'en? +|} +] + +type mismatched = [< `A of int | `B of float > `B `C] +[%%expect {| +Line 1, characters 18-53: +1 | type mismatched = [< `A of int | `B of float > `B `C] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: The constructor C is missing from the upper bound (between '<' + and '>') of this polymorphic variant but is present in + its lower bound (after '>'). + Hint: Either add `C in the upper bound, or remove it + from the lower bound. +|}] diff --git a/testsuite/tests/typing-misc/unique_names_in_unification.ml b/testsuite/tests/typing-misc/unique_names_in_unification.ml new file mode 100644 index 00000000..0c2d2650 --- /dev/null +++ b/testsuite/tests/typing-misc/unique_names_in_unification.ml @@ -0,0 +1,87 @@ +(* TEST + * expect + *) +type t = A +let x = A +module M = struct + type t = B + let f: t -> t = fun B -> x +end;; + +[%%expect{| +type t = A +val x : t = A +Line 5, characters 27-28: +5 | let f: t -> t = fun B -> x + ^ +Error: This expression has type t/2 but an expression was expected of type + t/1 + Line 4, characters 2-12: + Definition of type t/1 + Line 1, characters 0-10: + Definition of type t/2 +|}] + +module M = struct type t = B end +let y = M.B +module N = struct + module M = struct + type t = C + end + let f : M.t -> M.t = fun M.C -> y +end;; + +[%%expect{| +module M : sig type t = B end +val y : M.t = M.B +Line 7, characters 34-35: +7 | let f : M.t -> M.t = fun M.C -> y + ^ +Error: This expression has type M/2.t but an expression was expected of type + M/1.t + Line 4, characters 2-41: + Definition of module M/1 + Line 1, characters 0-32: + Definition of module M/2 +|}] + +type t = D +let f: t -> t = fun D -> x;; + + +[%%expect{| +type t = D +Line 2, characters 25-26: +2 | let f: t -> t = fun D -> x;; + ^ +Error: This expression has type t/1 but an expression was expected of type + t/2 + Line 1, characters 0-10: + Definition of type t/1 + Line 1, characters 0-10: + Definition of type t/2 +|}] + +type ttt +type ttt = A of ttt | B of uuu +and uuu = C of uuu | D of ttt;; +[%%expect{| +type ttt +type ttt = A of ttt | B of uuu +and uuu = C of uuu | D of ttt +|}] + +type nonrec ttt = X of ttt +let x: ttt = let rec y = A y in y;; +[%%expect{| +type nonrec ttt = X of ttt +Line 2, characters 32-33: +2 | let x: ttt = let rec y = A y in y;; + ^ +Error: This expression has type ttt/2 but an expression was expected of type + ttt/1 + Line 1, characters 0-26: + Definition of type ttt/1 + Line 2, characters 0-30: + Definition of type ttt/2 +|}] diff --git a/testsuite/tests/typing-misc/variant.ml b/testsuite/tests/typing-misc/variant.ml index 9564f36a..b1dfd1c0 100644 --- a/testsuite/tests/typing-misc/variant.ml +++ b/testsuite/tests/typing-misc/variant.ml @@ -11,11 +11,11 @@ end = struct let f = function A | B -> 0 end;; [%%expect{| -Line _, characters 6-61: - ......struct - type t = A | B - let f = function A | B -> 0 - end.. +Line 3, characters 6-61: +3 | ......struct +4 | type t = A | B +5 | let f = function A | B -> 0 +6 | end.. Error: Signature mismatch: Modules do not match: sig type t = X.t = A | B val f : t -> int end diff --git a/testsuite/tests/typing-misc/wellfounded.ml b/testsuite/tests/typing-misc/wellfounded.ml index 17214048..f6043128 100644 --- a/testsuite/tests/typing-misc/wellfounded.ml +++ b/testsuite/tests/typing-misc/wellfounded.ml @@ -15,8 +15,8 @@ let f : type t. t prod -> _ = function Prod -> ;; [%%expect{| type _ prod = Prod : ('a * 'y) prod -Line _, characters 6-20: - type d = d * d - ^^^^^^^^^^^^^^ +Line 6, characters 6-20: +6 | type d = d * d + ^^^^^^^^^^^^^^ Error: The type abbreviation d is cyclic |}];; diff --git a/testsuite/tests/typing-missing-cmi-2/bar.mli b/testsuite/tests/typing-missing-cmi-2/bar.mli new file mode 100644 index 00000000..752ac028 --- /dev/null +++ b/testsuite/tests/typing-missing-cmi-2/bar.mli @@ -0,0 +1 @@ +val foo : unit -> 'a Foo.t diff --git a/testsuite/tests/typing-missing-cmi-2/baz.ml b/testsuite/tests/typing-missing-cmi-2/baz.ml new file mode 100644 index 00000000..2dd4482a --- /dev/null +++ b/testsuite/tests/typing-missing-cmi-2/baz.ml @@ -0,0 +1 @@ +let x = Bar.foo () diff --git a/testsuite/tests/typing-missing-cmi-2/foo.mli b/testsuite/tests/typing-missing-cmi-2/foo.mli new file mode 100644 index 00000000..cbc4635f --- /dev/null +++ b/testsuite/tests/typing-missing-cmi-2/foo.mli @@ -0,0 +1 @@ +type 'a t diff --git a/testsuite/tests/typing-missing-cmi-2/ocamltests b/testsuite/tests/typing-missing-cmi-2/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/typing-missing-cmi-2/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/typing-missing-cmi-2/test.compilers.reference b/testsuite/tests/typing-missing-cmi-2/test.compilers.reference new file mode 100644 index 00000000..0927ee4b --- /dev/null +++ b/testsuite/tests/typing-missing-cmi-2/test.compilers.reference @@ -0,0 +1 @@ +val x : '_weak1 Foo.t diff --git a/testsuite/tests/typing-missing-cmi-2/test.ml b/testsuite/tests/typing-missing-cmi-2/test.ml new file mode 100644 index 00000000..2ef1c6d3 --- /dev/null +++ b/testsuite/tests/typing-missing-cmi-2/test.ml @@ -0,0 +1,15 @@ +(* TEST +files = "foo.mli bar.mli baz.ml" +* setup-ocamlc.byte-build-env +** ocamlc.byte +module = "foo.mli" +*** ocamlc.byte +module = "bar.mli" +**** script +script = "rm foo.cmi" +***** ocamlc.byte +flags = "-c -i" +module = "baz.ml" +ocamlc_byte_exit_status = "0" +****** check-ocamlc.byte-output +*) diff --git a/testsuite/tests/typing-missing-cmi/test.compilers.reference b/testsuite/tests/typing-missing-cmi/test.compilers.reference index dfcfd020..92bfbe7e 100644 --- a/testsuite/tests/typing-missing-cmi/test.compilers.reference +++ b/testsuite/tests/typing-missing-cmi/test.compilers.reference @@ -1,5 +1,7 @@ File "main.ml", line 1, characters 14-17: +1 | let _ = A.a = B.b + ^^^ Error: This expression has type M.b but an expression was expected of type M.a -M.b is abstract because no corresponding cmi file was found in path. -M.a is abstract because no corresponding cmi file was found in path. + M.b is abstract because no corresponding cmi file was found in path. + M.a is abstract because no corresponding cmi file was found in path. diff --git a/testsuite/tests/typing-modules-bugs/pr6293_bad.compilers.reference b/testsuite/tests/typing-modules-bugs/pr6293_bad.compilers.reference index 199c1cf7..580fa93e 100644 --- a/testsuite/tests/typing-modules-bugs/pr6293_bad.compilers.reference +++ b/testsuite/tests/typing-modules-bugs/pr6293_bad.compilers.reference @@ -1,4 +1,6 @@ -File "pr6293_bad.ml", line 10, characters 6-38: +File "pr6293_bad.ml", line 10, characters 18-37: +10 | let f (module M : S with type t = int) = { M.a = 0 };; + ^^^^^^^^^^^^^^^^^^^ Error: In this `with' constraint, the new definition of t does not match its original definition in the constrained signature: Type declarations do not match: @@ -6,5 +8,5 @@ Error: In this `with' constraint, the new definition of t is not included in type t = { a : int; b : int; } File "pr6293_bad.ml", line 9, characters 20-50: Expected declaration - File "pr6293_bad.ml", line 10, characters 6-38: Actual declaration + File "pr6293_bad.ml", line 10, characters 18-37: Actual declaration Their kinds differ. diff --git a/testsuite/tests/typing-modules-bugs/pr6427_bad.compilers.reference b/testsuite/tests/typing-modules-bugs/pr6427_bad.compilers.reference index 3c3c036c..8dd13d5a 100644 --- a/testsuite/tests/typing-modules-bugs/pr6427_bad.compilers.reference +++ b/testsuite/tests/typing-modules-bugs/pr6427_bad.compilers.reference @@ -1,3 +1,5 @@ File "pr6427_bad.ml", line 12, characters 13-65: +12 | module X = (val if !flag then (module A) else (module B) : S.T) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This expression creates fresh types. It is not allowed inside applicative functors. diff --git a/testsuite/tests/typing-modules-bugs/pr6485_ok.ml b/testsuite/tests/typing-modules-bugs/pr6485_ok.ml index ee90544e..641a3552 100644 --- a/testsuite/tests/typing-modules-bugs/pr6485_ok.ml +++ b/testsuite/tests/typing-modules-bugs/pr6485_ok.ml @@ -51,4 +51,3 @@ let () = let module Baz = String_id2.Make(struct let module_name="Baz" end) in let baz = Baz.of_string "baz" in Printf.printf "baz = %s\n" (baz :> string) - diff --git a/testsuite/tests/typing-modules-bugs/pr6572_ok.ml b/testsuite/tests/typing-modules-bugs/pr6572_ok.ml index 8f9647bc..94cd21c5 100644 --- a/testsuite/tests/typing-modules-bugs/pr6572_ok.ml +++ b/testsuite/tests/typing-modules-bugs/pr6572_ok.ml @@ -18,7 +18,7 @@ module Make(O : Set.OrderedType) : S with type elt = O.t = module rec A : Set.OrderedType = struct type t = int - let compare = Pervasives.compare + let compare = Stdlib.compare end and B : S = struct module C = Make(A) diff --git a/testsuite/tests/typing-modules-bugs/pr6752_bad.compilers.reference b/testsuite/tests/typing-modules-bugs/pr6752_bad.compilers.reference index 87fff51c..c14ca406 100644 --- a/testsuite/tests/typing-modules-bugs/pr6752_bad.compilers.reference +++ b/testsuite/tests/typing-modules-bugs/pr6752_bad.compilers.reference @@ -1,4 +1,6 @@ File "pr6752_bad.ml", line 26, characters 31-40: +26 | let q' : Common0.msg Queue.t = Common0.q + ^^^^^^^^^ Error: This expression has type 'a Queue.t but an expression was expected of type Common0.msg Queue.t The type constructor Common0.msg would escape its scope diff --git a/testsuite/tests/typing-modules-bugs/pr6899_first_bad.compilers.reference b/testsuite/tests/typing-modules-bugs/pr6899_first_bad.compilers.reference index fb4d3461..82c11aa3 100644 --- a/testsuite/tests/typing-modules-bugs/pr6899_first_bad.compilers.reference +++ b/testsuite/tests/typing-modules-bugs/pr6899_first_bad.compilers.reference @@ -1,3 +1,5 @@ File "pr6899_first_bad.ml", line 9, characters 4-17: +9 | let should_reject = + ^^^^^^^^^^^^^ Error: The type of this expression, '_weak1 -> '_weak2 -> unit, contains type variables that cannot be generalized diff --git a/testsuite/tests/typing-modules-bugs/pr6899_second_bad.compilers.reference b/testsuite/tests/typing-modules-bugs/pr6899_second_bad.compilers.reference index 58b44ba7..66950a17 100644 --- a/testsuite/tests/typing-modules-bugs/pr6899_second_bad.compilers.reference +++ b/testsuite/tests/typing-modules-bugs/pr6899_second_bad.compilers.reference @@ -1,3 +1,5 @@ File "pr6899_second_bad.ml", line 12, characters 6-9: +12 | let bar = wrap () + ^^^ Error: The type of this expression, _[< `Test ] -> unit, contains type variables that cannot be generalized diff --git a/testsuite/tests/typing-modules-bugs/pr6992_bad.compilers.reference b/testsuite/tests/typing-modules-bugs/pr6992_bad.compilers.reference index c6882a1c..0054f28d 100644 --- a/testsuite/tests/typing-modules-bugs/pr6992_bad.compilers.reference +++ b/testsuite/tests/typing-modules-bugs/pr6992_bad.compilers.reference @@ -1,4 +1,6 @@ File "pr6992_bad.ml", line 16, characters 69-71: +16 | let uniq (type a) (type b) (Eq : a fix) (Eq : b fix) : (a, b) eq = Eq + ^^ Error: This expression has type (a, a) eq but an expression was expected of type (a, b) eq Type a is not compatible with type b diff --git a/testsuite/tests/typing-modules-bugs/pr7112_bad.compilers.reference b/testsuite/tests/typing-modules-bugs/pr7112_bad.compilers.reference index 5e5de80a..7d1ade32 100644 --- a/testsuite/tests/typing-modules-bugs/pr7112_bad.compilers.reference +++ b/testsuite/tests/typing-modules-bugs/pr7112_bad.compilers.reference @@ -1,3 +1,5 @@ File "pr7112_bad.ml", line 13, characters 30-31: +13 | module G (X : F(N).S) : A.S = X + ^ Error: Signature mismatch: Modules do not match: F(N).S is not included in A.S diff --git a/testsuite/tests/typing-modules-bugs/pr7414_2_bad.compilers.reference b/testsuite/tests/typing-modules-bugs/pr7414_2_bad.compilers.reference index fd43b069..e606767e 100644 --- a/testsuite/tests/typing-modules-bugs/pr7414_2_bad.compilers.reference +++ b/testsuite/tests/typing-modules-bugs/pr7414_2_bad.compilers.reference @@ -1,4 +1,6 @@ File "pr7414_2_bad.ml", line 46, characters 28-34: +46 | let module Ignore = Force(Choose) in + ^^^^^^ Error: Signature mismatch: Modules do not match: functor () -> sig module Choice : T val r : '_weak1 list ref ref end diff --git a/testsuite/tests/typing-modules-bugs/pr7414_2_bad.ml b/testsuite/tests/typing-modules-bugs/pr7414_2_bad.ml index 0c2df938..e3cfca5f 100644 --- a/testsuite/tests/typing-modules-bugs/pr7414_2_bad.ml +++ b/testsuite/tests/typing-modules-bugs/pr7414_2_bad.ml @@ -15,7 +15,7 @@ end module Int = struct type t = int let x = 0 - let show x = string_of_int x + let show x = Int.to_string x end module String = struct diff --git a/testsuite/tests/typing-modules-bugs/pr7414_bad.compilers.reference b/testsuite/tests/typing-modules-bugs/pr7414_bad.compilers.reference index 16894165..5bdae1de 100644 --- a/testsuite/tests/typing-modules-bugs/pr7414_bad.compilers.reference +++ b/testsuite/tests/typing-modules-bugs/pr7414_bad.compilers.reference @@ -1,4 +1,6 @@ File "pr7414_bad.ml", line 52, characters 22-28: +52 | module Ignore = Force(Choose) + ^^^^^^ Error: Signature mismatch: Modules do not match: functor () -> sig module Choice : T val r : '_weak1 list ref ref end diff --git a/testsuite/tests/typing-modules-bugs/pr7414_bad.ml b/testsuite/tests/typing-modules-bugs/pr7414_bad.ml index 979e511c..c95e0ac1 100644 --- a/testsuite/tests/typing-modules-bugs/pr7414_bad.ml +++ b/testsuite/tests/typing-modules-bugs/pr7414_bad.ml @@ -15,7 +15,7 @@ end module Int = struct type t = int let x = 0 - let show x = string_of_int x + let show x = Int.to_string x end module String = struct diff --git a/testsuite/tests/typing-modules-bugs/pr7601_ok.ml b/testsuite/tests/typing-modules-bugs/pr7601_ok.ml index 4d1b8cdb..9b3cf39b 100644 --- a/testsuite/tests/typing-modules-bugs/pr7601_ok.ml +++ b/testsuite/tests/typing-modules-bugs/pr7601_ok.ml @@ -19,11 +19,12 @@ module type Analysis = sig [< `Location of t | `Value of t | `None ] as 'a - val of_var : ?f:string -> string -> [ `Location of _ | `Value of _ | `None ] maybe_region + val of_var : + ?f:string -> string -> + [ `Location of _ | `Value of _ | `None ] maybe_region end module Make (Analysis : Analysis) = struct include Analysis let of_var = of_var ~f:"" end - diff --git a/testsuite/tests/typing-modules-bugs/pr7601a_ok.ml b/testsuite/tests/typing-modules-bugs/pr7601a_ok.ml index 58fcf4eb..fd046d8a 100644 --- a/testsuite/tests/typing-modules-bugs/pr7601a_ok.ml +++ b/testsuite/tests/typing-modules-bugs/pr7601a_ok.ml @@ -25,4 +25,3 @@ module Make2 (M : Param2) = struct include M let f = f ~a:"" end - diff --git a/testsuite/tests/typing-modules/.gitattributes b/testsuite/tests/typing-modules/.gitattributes new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/typing-modules/Test.ml b/testsuite/tests/typing-modules/Test.ml index 610c8fca..ad10f664 100644 --- a/testsuite/tests/typing-modules/Test.ml +++ b/testsuite/tests/typing-modules/Test.ml @@ -68,9 +68,9 @@ module M : sig type -'a t = private int end = struct type +'a t = private int end ;; [%%expect{| -Line _, characters 2-37: - struct type +'a t = private int end - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 2-37: +2 | struct type +'a t = private int end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Signature mismatch: Modules do not match: sig type +'a t = private int end @@ -91,9 +91,9 @@ module type B = A with type t = u;; (* fail *) [%%expect{| module type A = sig type t = X of int end type u = X of bool -Line _, characters 23-33: - module type B = A with type t = u;; (* fail *) - ^^^^^^^^^^ +Line 3, characters 23-33: +3 | module type B = A with type t = u;; (* fail *) + ^^^^^^^^^^ Error: This variant or record definition does not match that of type u The types for field X are not equal. |}];; @@ -103,9 +103,9 @@ Error: This variant or record definition does not match that of type u module type S = sig exception Foo of int exception Foo of bool end;; [%%expect{| -Line _, characters 52-55: - module type S = sig exception Foo of int exception Foo of bool end;; - ^^^ +Line 1, characters 42-63: +1 | module type S = sig exception Foo of int exception Foo of bool end;; + ^^^^^^^^^^^^^^^^^^^^^ Error: Multiple definition of the extension constructor name Foo. Names must be unique in a given structure or signature. |}];; @@ -116,8 +116,82 @@ module F(X : sig end) = struct let x = 3 end;; F.x;; (* fail *) [%%expect{| module F : functor (X : sig end) -> sig val x : int end -Line _, characters 0-3: - F.x;; (* fail *) - ^^^ +Line 2, characters 0-3: +2 | F.x;; (* fail *) + ^^^ Error: The module F is a functor, it cannot have any components |}];; + +type t = ..;; +[%%expect{| +type t = .. +|}];; + +module M : sig type t += E end = struct type t += E of int end;; +[%%expect{| +Line 1, characters 33-62: +1 | module M : sig type t += E end = struct type t += E of int end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Signature mismatch: + Modules do not match: + sig type t += E of int end + is not included in + sig type t += E end + Extension declarations do not match: + type t += E of int + is not included in + type t += E + The arities for field E differ. +|}];; + +module M : sig type t += E of char end = struct type t += E of int end;; +[%%expect{| +Line 1, characters 41-70: +1 | module M : sig type t += E of char end = struct type t += E of int end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Signature mismatch: + Modules do not match: + sig type t += E of int end + is not included in + sig type t += E of char end + Extension declarations do not match: + type t += E of int + is not included in + type t += E of char + The types for field E are not equal. +|}];; + +module M : sig type t += C of int end = struct type t += E of int end;; +[%%expect{| +Line 1, characters 40-69: +1 | module M : sig type t += C of int end = struct type t += E of int end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Signature mismatch: + Modules do not match: + sig type t += E of int end + is not included in + sig type t += C of int end + The extension constructor `C' is required but not provided +|}];; + +module M : sig + type t += E of { x : int } +end = struct + type t += E of int +end;; +[%%expect{| +Line 3, characters 6-37: +3 | ......struct +4 | type t += E of int +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig type t += E of int end + is not included in + sig type t += E of { x : int; } end + Extension declarations do not match: + type t += E of int + is not included in + type t += E of { x : int; } + The types for field E are not equal. +|}];; diff --git a/testsuite/tests/typing-modules/aliases.ml b/testsuite/tests/typing-modules/aliases.ml index 1bdfa6fd..40727eb7 100644 --- a/testsuite/tests/typing-modules/aliases.ml +++ b/testsuite/tests/typing-modules/aliases.ml @@ -287,6 +287,7 @@ module StringSet : val remove : elt -> t -> t val union : t -> t -> t val inter : t -> t -> t + val disjoint : t -> t -> bool val diff : t -> t -> t val compare : t -> t -> int val equal : t -> t -> bool @@ -331,6 +332,7 @@ module SSet : val remove : elt -> t -> t val union : t -> t -> t val inter : t -> t -> t + val disjoint : t -> t -> bool val diff : t -> t -> t val compare : t -> t -> int val equal : t -> t -> bool @@ -407,6 +409,7 @@ module A : val remove : elt -> t -> t val union : t -> t -> t val inter : t -> t -> t + val disjoint : t -> t -> bool val diff : t -> t -> t val compare : t -> t -> int val equal : t -> t -> bool @@ -523,6 +526,7 @@ module SInt : val remove : elt -> t -> t val union : t -> t -> t val inter : t -> t -> t + val disjoint : t -> t -> bool val diff : t -> t -> t val compare : t -> t -> int val equal : t -> t -> bool @@ -568,9 +572,9 @@ module type S = type wrap' = wrap = W of (Set.Make(Int).t, Set.Make(I).t) eq end module Int2 : sig type t = int val compare : 'a -> 'a -> int end -Line _, characters 10-30: - include S with module I := I - ^^^^^^^^^^^^^^^^^^^^ +Line 15, characters 10-30: +15 | include S with module I := I + ^^^^^^^^^^^^^^^^^^^^ Error: In this `with' constraint, the new definition of I does not match its original definition in the constrained signature: Modules do not match: (module Int2) is not included in (module Int) @@ -661,7 +665,7 @@ module rec Bad : A = Bad;; [%%expect{| module type Alias = sig module N : sig end module M = N end module F : functor (X : sig end) -> sig type t end -Line _: +Line 1: Error: Module type declarations do not match: module type A = sig module M = F(List) end does not match @@ -795,3 +799,65 @@ end;; module X : sig module N : sig end end module Y : sig module type S = sig module N = X.N end end |}];; + +module type S = sig + module M : sig + module A : sig end + module B : sig end + end + module N = M.A +end + +module Foo = struct + module B = struct let x = 0 end + module A = struct let x = "hello" end +end + +module Bar : S with module M := Foo = struct module N = Foo.A end + +let s : string = Bar.N.x +[%%expect {| +module type S = + sig + module M : sig module A : sig end module B : sig end end + module N = M.A + end +module Foo : + sig module B : sig val x : int end module A : sig val x : string end end +module Bar : sig module N = Foo.A end +val s : string = "hello" +|}] + + +module M : sig + module N : sig + module A : sig val x : string end + module B : sig val x : int end + end + module F (X : sig module A = N.A end) : sig val s : string end +end = struct + module N = struct + module B = struct let x = 0 end + module A = struct let x = "hello" end + end + module F (X : sig module A : sig val x : string end end) = struct + let s = X.A.x + end +end + +module N = M.F(struct module A = M.N.A end) + +let s : string = N.s +[%%expect {| +module M : + sig + module N : + sig + module A : sig val x : string end + module B : sig val x : int end + end + module F : functor (X : sig module A = N.A end) -> sig val s : string end + end +module N : sig val s : string end +val s : string = "hello" +|}] diff --git a/testsuite/tests/typing-modules/applicative_functor_type.ml b/testsuite/tests/typing-modules/applicative_functor_type.ml index b02a882d..e62b7e63 100644 --- a/testsuite/tests/typing-modules/applicative_functor_type.ml +++ b/testsuite/tests/typing-modules/applicative_functor_type.ml @@ -16,9 +16,9 @@ module M : sig type t val equal : 'a -> 'a -> bool end type t = Set.Make(M).t [%%expect{| -Line _, characters 9-22: - type t = Set.Make(M).t - ^^^^^^^^^^^^^ +Line 1, characters 9-22: +1 | type t = Set.Make(M).t + ^^^^^^^^^^^^^ Error: The type of M does not match Set.Make's parameter Modules do not match: sig type t = M.t val equal : 'a -> 'a -> bool end @@ -40,9 +40,9 @@ module F : type t = F(M).t [%%expect{| -Line _, characters 9-15: - type t = F(M).t - ^^^^^^ +Line 1, characters 9-15: +1 | type t = F(M).t + ^^^^^^ Error: The type of M does not match F's parameter Modules do not match: sig type t = M.t val equal : 'a -> 'a -> bool end @@ -63,9 +63,9 @@ module Generative : functor () -> sig type t end type t = Generative(M).t [%%expect{| -Line _, characters 9-24: - type t = Generative(M).t - ^^^^^^^^^^^^^^^ +Line 1, characters 9-24: +1 | type t = Generative(M).t + ^^^^^^^^^^^^^^^ Error: The functor Generative is generative, it cannot be applied in type expressions |}] @@ -76,8 +76,8 @@ module F(X : sig module type S module F : S end) = struct type t = X.F(Parsing).t end [%%expect{| -Line _, characters 11-25: - type t = X.F(Parsing).t - ^^^^^^^^^^^^^^ +Line 2, characters 11-25: +2 | type t = X.F(Parsing).t + ^^^^^^^^^^^^^^ Error: The module X.F is abstract, it cannot be applied |}] diff --git a/testsuite/tests/typing-modules/firstclass.ml b/testsuite/tests/typing-modules/firstclass.ml index 18679d1b..a79d01d9 100644 --- a/testsuite/tests/typing-modules/firstclass.ml +++ b/testsuite/tests/typing-modules/firstclass.ml @@ -29,9 +29,9 @@ module type S2 = sig type u type t type w end val g2 : (module S2 with type t = int and type u = bool) -> (module S') = val h : (module S2 with type t = 'a) -> (module S with type t = 'a) = -Line _, characters 3-4: - (x : (module S'));; (* fail *) - ^ +Line 5, characters 3-4: +5 | (x : (module S'));; (* fail *) + ^ Error: This expression has type (module S2 with type t = int and type u = bool) but an expression was expected of type (module S') @@ -43,9 +43,9 @@ let g3 x = (x : (module S3 with type t = 'a and type u = 'b) :> (module S'));; (* fail *) [%%expect{| module type S3 = sig type u type t val x : int end -Line _, characters 2-67: - (x : (module S3 with type t = 'a and type u = 'b) :> (module S'));; (* fail *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 2-67: +3 | (x : (module S3 with type t = 'a and type u = 'b) :> (module S'));; (* fail *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Type (module S3 with type t = int and type u = bool) is not a subtype of (module S') |}];; diff --git a/testsuite/tests/typing-modules/generative.ml b/testsuite/tests/typing-modules/generative.ml index 75cc7ae7..f490f075 100644 --- a/testsuite/tests/typing-modules/generative.ml +++ b/testsuite/tests/typing-modules/generative.ml @@ -29,9 +29,9 @@ module F : functor () -> S |}];; module G (X : sig end) : S = F ();; (* fail *) [%%expect{| -Line _, characters 29-33: - module G (X : sig end) : S = F ();; (* fail *) - ^^^^ +Line 1, characters 29-33: +1 | module G (X : sig end) : S = F ();; (* fail *) + ^^^^ Error: This expression creates fresh types. It is not allowed inside applicative functors. |}];; @@ -49,9 +49,9 @@ module M : S |}];; module M = F(U);; (* fail *) [%%expect{| -Line _, characters 11-12: - module M = F(U);; (* fail *) - ^ +Line 1, characters 11-12: +1 | module M = F(U);; (* fail *) + ^ Error: This is a generative functor. It can only be applied to () |}];; @@ -60,9 +60,9 @@ module F1 (X : sig end) = struct end;; module F2 : functor () -> sig end = F1;; (* fail *) [%%expect{| module F1 : functor (X : sig end) -> sig end -Line _, characters 36-38: - module F2 : functor () -> sig end = F1;; (* fail *) - ^^ +Line 2, characters 36-38: +2 | module F2 : functor () -> sig end = F1;; (* fail *) + ^^ Error: Signature mismatch: Modules do not match: functor (X : sig end) -> sig end @@ -73,9 +73,9 @@ module F3 () = struct end;; module F4 : functor (X : sig end) -> sig end = F3;; (* fail *) [%%expect{| module F3 : functor () -> sig end -Line _, characters 47-49: - module F4 : functor (X : sig end) -> sig end = F3;; (* fail *) - ^^ +Line 2, characters 47-49: +2 | module F4 : functor (X : sig end) -> sig end = F3;; (* fail *) + ^^ Error: Signature mismatch: Modules do not match: functor () -> sig end diff --git a/testsuite/tests/typing-modules/nondep.ml b/testsuite/tests/typing-modules/nondep.ml new file mode 100644 index 00000000..6662dc5b --- /dev/null +++ b/testsuite/tests/typing-modules/nondep.ml @@ -0,0 +1,21 @@ +(* TEST + * expect +*) + +module F(X : sig type t end) = struct + let f (_ : X.t) = () +end;; +[%%expect{| +module F : functor (X : sig type t end) -> sig val f : X.t -> unit end +|}] + +module M = F(struct type t = T end);; +[%%expect{| +Line 1, characters 11-35: +1 | module M = F(struct type t = T end);; + ^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This functor has type + functor (X : sig type t end) -> sig val f : X.t -> unit end + The parameter cannot be eliminated in the result type. + Please bind the argument to a module identifier. +|}] diff --git a/testsuite/tests/typing-modules/nondep_private_abbrev.ml b/testsuite/tests/typing-modules/nondep_private_abbrev.ml new file mode 100644 index 00000000..f0b0ec57 --- /dev/null +++ b/testsuite/tests/typing-modules/nondep_private_abbrev.ml @@ -0,0 +1,137 @@ +(* TEST + * expect +*) + +module F(_ : sig end) : sig + type t = private int +end = struct + type t = int +end;; +[%%expect{| +module F : sig end -> sig type t = private int end +|}] + +module Direct = F(struct end);; +[%%expect{| +module Direct : sig type t = private int end +|}] + +module G(X : sig end) : sig + type t = F(X).t +end = F(X);; +[%%expect{| +module G : functor (X : sig end) -> sig type t = F(X).t end +|}] + +module Indirect = G(struct end);; +[%%expect{| +module Indirect : sig type t = private int end +|}] + +(* unroll_abbrev *) + +module Pub(_ : sig end) = struct + type t = [ `Foo of t ] +end;; +[%%expect{| +module Pub : sig end -> sig type t = [ `Foo of t ] end +|}] + +module Priv(_ : sig end) = struct + type t = private [ `Foo of t ] +end;; +[%%expect{| +module Priv : sig end -> sig type t = private [ `Foo of t ] end +|}] + +module DirectPub = Pub(struct end);; +[%%expect{| +module DirectPub : sig type t = [ `Foo of t ] end +|}] + +module DirectPriv = Priv(struct end);; +[%%expect{| +module DirectPriv : sig type t = private [ `Foo of t ] end +|}] + +module H(X : sig end) : sig + type t = Pub(X).t +end = Pub(X);; +[%%expect{| +module H : functor (X : sig end) -> sig type t = Pub(X).t end +|}] + +module I(X : sig end) : sig + type t = Priv(X).t +end = Priv(X);; +[%%expect{| +module I : functor (X : sig end) -> sig type t = Priv(X).t end +|}] + +module IndirectPub = H(struct end);; +[%%expect{| +module IndirectPub : sig type t = [ `Foo of 'a ] as 'a end +|}] + +(* The result would be + {[ + type t = private [ `Foo of t ] + ]} + if we were unrolling the abbrev. *) +module IndirectPriv = I(struct end);; +[%%expect{| +module IndirectPriv : sig type t end +|}] + +(*** Test proposed by Jacques in + https://github.com/ocaml/ocaml/pull/1826#discussion_r194290729 ***) + +(* Baseline *) + +type t = private [ `Bar of int | `Foo of t -> int ];; +[%%expect{| +type t = private [ `Bar of int | `Foo of t -> int ] +|}] + +module M : sig + type s = private [ `Bar of int | `Foo of 'a -> int ] as 'a +end = struct + type s = t +end;; +[%%expect{| +Line 3, characters 6-29: +3 | ......struct +4 | type s = t +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig type s = t end + is not included in + sig type s = private [ `Bar of int | `Foo of 'a -> int ] as 'a end + Type declarations do not match: + type s = t + is not included in + type s = private [ `Bar of int | `Foo of 'a -> int ] as 'a +|}] + +(* nondep_type_decl + nondep_type_rec *) + +module Priv(_ : sig end) = struct + type t = private [ `Foo of t -> int | `Bar of int ] +end;; +[%%expect{| +module Priv : + sig end -> sig type t = private [ `Bar of int | `Foo of t -> int ] end +|}] + +module I(X : sig end) : sig + type t = Priv(X).t +end = Priv(X);; +[%%expect{| +module I : functor (X : sig end) -> sig type t = Priv(X).t end +|}] + +module IndirectPriv = I(struct end);; +[%%expect{| +module IndirectPriv : sig type t end +|}] diff --git a/testsuite/tests/typing-modules/normalize_path.ml b/testsuite/tests/typing-modules/normalize_path.ml new file mode 100755 index 00000000..44f45ef4 --- /dev/null +++ b/testsuite/tests/typing-modules/normalize_path.ml @@ -0,0 +1,17 @@ +(* TEST + * expect +*) + +module X = struct + + module B = List + + exception B of {x:int} +end + +let _ = X.B {x=2} +;; +[%%expect{| +module X : sig module B = List exception B of { x : int; } end +- : exn = X.B {x = 2} +|}] diff --git a/testsuite/tests/typing-modules/ocamltests b/testsuite/tests/typing-modules/ocamltests index 1b548b20..34d5fbaa 100644 --- a/testsuite/tests/typing-modules/ocamltests +++ b/testsuite/tests/typing-modules/ocamltests @@ -2,12 +2,18 @@ aliases.ml applicative_functor_type.ml firstclass.ml generative.ml +nondep.ml +nondep_private_abbrev.ml +normalize_path.ml pr5911.ml pr6394.ml pr7207.ml pr7348.ml +pr7726.ml pr7787.ml pr7818.ml +pr7851.ml printing.ml recursive.ml Test.ml +unroll_private_abbrev.ml diff --git a/testsuite/tests/typing-modules/pr6394.ml b/testsuite/tests/typing-modules/pr6394.ml index 82f4cb77..3fa04735 100644 --- a/testsuite/tests/typing-modules/pr6394.ml +++ b/testsuite/tests/typing-modules/pr6394.ml @@ -10,11 +10,11 @@ end = struct let f = function A | B -> 0 end;; [%%expect{| -Line _, characters 6-63: - ......struct - type t = A | B - let f = function A | B -> 0 - end.. +Line 4, characters 6-63: +4 | ......struct +5 | type t = A | B +6 | let f = function A | B -> 0 +7 | end.. Error: Signature mismatch: Modules do not match: sig type t = X.t = A | B val f : t -> int end diff --git a/testsuite/tests/typing-modules/pr7207.ml b/testsuite/tests/typing-modules/pr7207.ml index c18176fc..81000648 100644 --- a/testsuite/tests/typing-modules/pr7207.ml +++ b/testsuite/tests/typing-modules/pr7207.ml @@ -6,8 +6,8 @@ module F (X : sig end) = struct type t = int end;; type t = F(Does_not_exist).t;; [%%expect{| module F : functor (X : sig end) -> sig type t = int end -Line _, characters 9-28: - type t = F(Does_not_exist).t;; - ^^^^^^^^^^^^^^^^^^^ +Line 2, characters 9-28: +2 | type t = F(Does_not_exist).t;; + ^^^^^^^^^^^^^^^^^^^ Error: Unbound module Does_not_exist |}];; diff --git a/testsuite/tests/typing-modules/pr7348.ml b/testsuite/tests/typing-modules/pr7348.ml index 5cce4e2c..e24d529f 100644 --- a/testsuite/tests/typing-modules/pr7348.ml +++ b/testsuite/tests/typing-modules/pr7348.ml @@ -33,7 +33,7 @@ module A : sig end = struct let x : < foo: int; ..> = X.x end - module N = F(M) + module N = F(M) let _ = (N.x = M.x) end;; [%%expect{| diff --git a/testsuite/tests/typing-modules/pr7726.ml b/testsuite/tests/typing-modules/pr7726.ml new file mode 100644 index 00000000..edc64080 --- /dev/null +++ b/testsuite/tests/typing-modules/pr7726.ml @@ -0,0 +1,150 @@ +(* TEST + * expect +*) + +module type T = sig type t end +module Fix(F:(T -> T)) = struct + module rec Fixed : T with type t = F(Fixed).t = F(Fixed) +end;; +[%%expect{| +module type T = sig type t end +module Fix : + functor (F : T -> T) -> + sig module rec Fixed : sig type t = F(Fixed).t end end +|}] + +module T1 = Fix(functor (X:sig type t end) -> struct type t = X.t option end);; +[%%expect{| +Line 1, characters 12-77: +1 | module T1 = Fix(functor (X:sig type t end) -> struct type t = X.t option end);; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: In the signature of this functor application: + The type abbreviation Fixed.t is cyclic +|}] +module T2 = Fix(functor (X:sig type t end) -> struct type t = X.t end);; +[%%expect{| +Line 1, characters 12-70: +1 | module T2 = Fix(functor (X:sig type t end) -> struct type t = X.t end);; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: In the signature of this functor application: + The definition of Fixed.t contains a cycle: + F(Fixed).t +|}] + +(* Positive example *) +module F3(X:T) = struct type t = Z | S of X.t end;; +module T3 = Fix(F3);; +let x : T3.Fixed.t = S Z;; +[%%expect{| +module F3 : functor (X : T) -> sig type t = Z | S of X.t end +module T3 : sig module rec Fixed : sig type t = F3(Fixed).t end end +val x : T3.Fixed.t = F3(T3.Fixed).S F3(T3.Fixed).Z +|}] + +(* Torture the type checker more *) +module M = struct + module F (X : T) : T = X + module rec Fixed : sig type t = F(Fixed).t end = Fixed +end +module type S = module type of M +module Id (X : T) = X;; +[%%expect{| +module M : + sig + module F : functor (X : T) -> T + module rec Fixed : sig type t = F(Fixed).t end + end +module type S = + sig + module F : functor (X : T) -> T + module rec Fixed : sig type t = F(Fixed).t end + end +module Id : functor (X : T) -> sig type t = X.t end +|}] + +module type Bad = S with module F = Id;; +[%%expect{| +Line 1, characters 18-38: +1 | module type Bad = S with module F = Id;; + ^^^^^^^^^^^^^^^^^^^^ +Error: In this instantiated signature: + The definition of Fixed.t contains a cycle: + F(Fixed).t +|}] + +(* More examples by lpw25 *) +module M = Fix(Id);; +[%%expect{| +Line 1, characters 11-18: +1 | module M = Fix(Id);; + ^^^^^^^ +Error: In the signature of this functor application: + The definition of Fixed.t contains a cycle: + Id(Fixed).t +|}] +type t = Fix(Id).Fixed.t;; +[%%expect{| +Line 1, characters 9-24: +1 | type t = Fix(Id).Fixed.t;; + ^^^^^^^^^^^^^^^ +Error: In the signature of Fix(Id): + The definition of Fixed.t contains a cycle: + Id(Fixed).t +|}] +let f (x : Fix(Id).Fixed.t) = x;; +[%%expect{| +Line 1, characters 11-26: +1 | let f (x : Fix(Id).Fixed.t) = x;; + ^^^^^^^^^^^^^^^ +Error: In the signature of Fix(Id): + The definition of Fixed.t contains a cycle: + Id(Fixed).t +|}] + +module Foo (F : T -> T) = struct + let f (x : Fix(F).Fixed.t) = x + end +module M = Foo(Id);; +M.f 5;; +[%%expect{| +module Foo : + functor (F : T -> T) -> sig val f : Fix(F).Fixed.t -> Fix(F).Fixed.t end +module M : sig val f : Fix(Id).Fixed.t -> Fix(Id).Fixed.t end +Line 1: +Error: In the signature of Fix(Id): + The definition of Fixed.t contains a cycle: + Id(Fixed).t +|}] + +(* Extra tests for GPR#1676 *) +module F() = struct type t end +module M = struct end;; +type t = F(M).t;; +[%%expect{| +module F : functor () -> sig type t end +module M : sig end +Line 3, characters 9-15: +3 | type t = F(M).t;; + ^^^^^^ +Error: The functor F is generative, it cannot be applied in type expressions +|}] + +module Fix2(F:(T -> T)) = struct + module rec Fixed : T with type t = F(Fixed).t = F(Fixed) + module R(X:sig end) = struct type t = Fixed.t end +end;; +let f (x : Fix2(Id).R(M).t) = x;; +[%%expect{| +module Fix2 : + functor (F : T -> T) -> + sig + module rec Fixed : sig type t = F(Fixed).t end + module R : functor (X : sig end) -> sig type t = Fixed.t end + end +Line 5, characters 11-26: +5 | let f (x : Fix2(Id).R(M).t) = x;; + ^^^^^^^^^^^^^^^ +Error: In the signature of Fix2(Id): + The definition of Fixed.t contains a cycle: + Id(Fixed).t +|}] diff --git a/testsuite/tests/typing-modules/pr7818.ml b/testsuite/tests/typing-modules/pr7818.ml index 166faf8e..eec5440b 100644 --- a/testsuite/tests/typing-modules/pr7818.ml +++ b/testsuite/tests/typing-modules/pr7818.ml @@ -108,11 +108,11 @@ module Make2 (T' : S) : sig module Id : sig end module Id2 = Id end module Id2 = Id end;; [%%expect{| -Line _, characters 57-107: - .........................................................struct - module Id = T'.T.Id - module Id2 = Id - end.. +Line 2, characters 57-107: +2 | .........................................................struct +3 | module Id = T'.T.Id +4 | module Id2 = Id +5 | end.. Error: Signature mismatch: Modules do not match: sig module Id : sig end module Id2 = Id end @@ -148,9 +148,9 @@ module M = Make1 (struct module Term0 = M.Id.x;; [%%expect{| module M : sig module Id : sig end module Id2 = Id end -Line _, characters 0-6: - M.Id.x;; - ^^^^^^ +Line 3, characters 0-6: +3 | M.Id.x;; + ^^^^^^ Error: Unbound value M.Id.x |}] @@ -240,6 +240,7 @@ module MkT : val remove : elt -> t -> t val union : t -> t -> t val inter : t -> t -> t + val disjoint : t -> t -> bool val diff : t -> t -> t val compare : t -> t -> int val equal : t -> t -> bool @@ -310,10 +311,9 @@ module type S' = end module Asc : sig type t = int val compare : int -> int -> int end module Desc : sig type t = int val compare : int -> int -> int end -module rec M1 : - sig - type t = M.t = E of (MkT(Desc).t, MkT(Desc).t) eq - type u = t = E of (MkT(Asc).t, MkT(Desc).t) eq - end -val eq : (MkT(Asc).t, MkT(Desc).t) eq = Eq +Line 15, characters 16-64: +15 | module rec M1 : S' with module Term0 := Asc and module T := Desc = M1;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This variant or record definition does not match that of type M.t + The types for field E are not equal. |}] diff --git a/testsuite/tests/typing-modules/pr7851.ml b/testsuite/tests/typing-modules/pr7851.ml new file mode 100644 index 00000000..72a03871 --- /dev/null +++ b/testsuite/tests/typing-modules/pr7851.ml @@ -0,0 +1,79 @@ +(* TEST + * expect +*) + +(* Leo's version *) +module F(X : sig type t end) = struct + type x = X.t + type y = X.t + type t = E of x + type u = t = E of y +end;; + +module M = F(struct type t end);; + +module type S = module type of M;; +[%%expect{| +module F : + functor (X : sig type t end) -> + sig type x = X.t type y = X.t type t = E of x type u = t = E of y end +module M : sig type x type y type t = E of x type u = t = E of y end +module type S = sig type x type y type t = E of x type u = t = E of y end +|}] + +module rec M1 : S with type x = int and type y = bool = M1;; +[%%expect{| +Line 1, characters 16-53: +1 | module rec M1 : S with type x = int and type y = bool = M1;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This variant or record definition does not match that of type M1.t + The types for field E are not equal. +|}] + +let bool_of_int x = + let (E y : M1.u) = (E x : M1.t) in + y;; + +bool_of_int 3;; +[%%expect{| +Line 2, characters 28-32: +2 | let (E y : M1.u) = (E x : M1.t) in + ^^^^ +Error: Unbound module M1 +|}] + +(* Also check the original version *) +type (_,_) eq = Eq : ('a,'a) eq +module F(X : Set.OrderedType) = struct +type x = Set.Make(X).t and y = Set.Make(X).t +type t = E of (x,x) eq +type u = t = E of (x,y) eq +end;; +module M = F(struct type t let compare = compare end);; +module type S = module type of M;; +[%%expect{| +type (_, _) eq = Eq : ('a, 'a) eq +module F : + functor (X : Set.OrderedType) -> + sig + type x = Set.Make(X).t + and y = Set.Make(X).t + type t = E of (x, x) eq + type u = t = E of (x, y) eq + end +module M : + sig type x and y type t = E of (x, x) eq type u = t = E of (x, y) eq end +module type S = + sig type x and y type t = E of (x, x) eq type u = t = E of (x, y) eq end +|}] +module rec M1 : S with type x = int and type y = bool = M1;; +let (E eq : M1.u) = (E Eq : M1.t);; +let cast : type a b. (a,b) eq -> a -> b = fun Eq x -> x;; +cast eq 3;; +[%%expect{| +Line 1, characters 16-53: +1 | module rec M1 : S with type x = int and type y = bool = M1;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This variant or record definition does not match that of type M1.t + The types for field E are not equal. +|}] diff --git a/testsuite/tests/typing-modules/recursive.ml b/testsuite/tests/typing-modules/recursive.ml index dd844c29..5a198f71 100644 --- a/testsuite/tests/typing-modules/recursive.ml +++ b/testsuite/tests/typing-modules/recursive.ml @@ -6,8 +6,8 @@ module rec T : sig type t = T.t end = T;; [%%expect{| -Line _, characters 15-35: - module rec T : sig type t = T.t end = T;; - ^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 15-35: +1 | module rec T : sig type t = T.t end = T;; + ^^^^^^^^^^^^^^^^^^^^ Error: The type abbreviation T.t is cyclic |}] diff --git a/testsuite/tests/typing-modules/unroll_private_abbrev.ml b/testsuite/tests/typing-modules/unroll_private_abbrev.ml new file mode 100644 index 00000000..3bc65dd7 --- /dev/null +++ b/testsuite/tests/typing-modules/unroll_private_abbrev.ml @@ -0,0 +1,80 @@ +(* TEST + * expect +*) + +module M : sig + type t = private [ `Bar of 'a | `Foo ] as 'a + val bar : t +end = struct + type t = [ `Bar of 'a | `Foo ] as 'a + let bar = `Bar `Foo +end;; +[%%expect{| +module M : sig type t = private [ `Bar of 'a | `Foo ] as 'a val bar : t end +|}] + +let y = + match (M.bar :> [ `Bar of 'a | `Foo ] as 'a) with + | `Bar x -> x + | `Foo -> assert false +;; +[%%expect{| +val y : [ `Bar of 'a | `Foo ] as 'a = `Foo +|}] + +let y = + match (M.bar :> [ `Bar of M.t | `Foo ]) with + | `Bar x -> x + | `Foo -> assert false +;; +[%%expect{| +Line 2, characters 8-41: +2 | match (M.bar :> [ `Bar of M.t | `Foo ]) with + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Type M.t is not a subtype of [ `Bar of M.t | `Foo ] + Type M.t = [ `Bar of M.t | `Foo ] is not a subtype of M.t +|}] + +module F(X : sig end) : sig + type s = private [ `Bar of 'a | `Foo ] as 'a + + val from : M.t -> s + val to_ : s -> M.t +end = struct + type s = M.t + + let from x = x + let to_ x = x +end;; +[%%expect{| +module F : + functor (X : sig end) -> + sig + type s = private [ `Bar of 'a | `Foo ] as 'a + val from : M.t -> s + val to_ : s -> M.t + end +|}] + +module N = F(struct end);; +[%%expect{| +module N : + sig + type s = private [ `Bar of 'a | `Foo ] as 'a + val from : M.t -> s + val to_ : s -> M.t + end +|}] + +let y = + match (N.from M.bar :> [ `Bar of N.s | `Foo ]) with + | `Bar x -> N.to_ x + | `Foo -> assert false +;; +[%%expect{| +Line 2, characters 8-48: +2 | match (N.from M.bar :> [ `Bar of N.s | `Foo ]) with + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Type N.s is not a subtype of [ `Bar of N.s | `Foo ] + Type N.s = [ `Bar of N.s | `Foo ] is not a subtype of N.s +|}] diff --git a/testsuite/tests/typing-multifile/pr7325.ml b/testsuite/tests/typing-multifile/pr7325.ml index 918549d7..33b69bc9 100644 --- a/testsuite/tests/typing-multifile/pr7325.ml +++ b/testsuite/tests/typing-multifile/pr7325.ml @@ -10,4 +10,4 @@ script = "rm a.cmi" ***** ocamlc.byte module = "c.ml" ****** check-ocamlc.byte-output -*) \ No newline at end of file +*) diff --git a/testsuite/tests/typing-objects-bugs/pr3968_bad.compilers.reference b/testsuite/tests/typing-objects-bugs/pr3968_bad.compilers.reference index dae88bcc..dc5c5312 100644 --- a/testsuite/tests/typing-objects-bugs/pr3968_bad.compilers.reference +++ b/testsuite/tests/typing-objects-bugs/pr3968_bad.compilers.reference @@ -1,4 +1,14 @@ File "pr3968_bad.ml", line 20, characters 0-165: +20 | object +21 | val l = e1 +22 | val r = e2 +23 | method eval env = +24 | match l with +25 | | `Abs(var,body) -> +26 | Hashtbl.add env var r; +27 | body +28 | | _ -> `App(l,r); +29 | end Error: The class type object val l : diff --git a/testsuite/tests/typing-objects-bugs/pr4018_bad.compilers.reference b/testsuite/tests/typing-objects-bugs/pr4018_bad.compilers.reference index bbcbed53..68b17665 100644 --- a/testsuite/tests/typing-objects-bugs/pr4018_bad.compilers.reference +++ b/testsuite/tests/typing-objects-bugs/pr4018_bad.compilers.reference @@ -1,4 +1,6 @@ File "pr4018_bad.ml", line 42, characters 11-17: +42 | let f (x : entity entity_container) = () + ^^^^^^ Error: This type entity = < destroy_subject : id subject; entity_id : id > should be an instance of type < destroy_subject : < add_observer : 'a entity_container -> 'c; .. > @@ -16,26 +18,23 @@ Error: This type entity = < destroy_subject : id subject; entity_id : id > 'a entity_container = < add_entity : (< destroy_subject : < add_observer : 'a entity_container -> - 'e; - .. >; + 'f; + .. > + as 'e; .. > as 'd) -> - 'e; + 'f; notify : 'd -> id -> unit > - Type < destroy_subject : id subject; entity_id : id > - is not compatible with type - entity = < destroy_subject : id subject; entity_id : id > + Type entity = < destroy_subject : id subject; entity_id : id > + is not compatible with type < destroy_subject : 'e; .. > as 'd Type - < add_observer : (id subject, id) observer -> unit; - notify_observers : id -> unit > - is not compatible with type id subject = < add_observer : (id subject, id) observer -> unit; - notify_observers : id -> unit > - Type < add_entity : 'd -> 'e; notify : 'd -> id -> unit > + notify_observers : id -> unit > + is not compatible with type + < add_observer : 'a entity_container -> 'f; .. > as 'e + Type (id subject, id) observer = < notify : id subject -> id -> unit > is not compatible with type 'a entity_container = - < add_entity : 'd -> 'e; notify : 'd -> id -> unit > - Type < notify : id subject -> id -> unit > is not compatible with type - (id subject, id) observer = < notify : id subject -> id -> unit > - Types for method add_entity are incompatible + < add_entity : 'd -> 'f; notify : 'd -> id -> unit > + The first object type has no method add_entity diff --git a/testsuite/tests/typing-objects-bugs/pr4435_bad.compilers.reference b/testsuite/tests/typing-objects-bugs/pr4435_bad.compilers.reference index 84f74be0..4a75d176 100644 --- a/testsuite/tests/typing-objects-bugs/pr4435_bad.compilers.reference +++ b/testsuite/tests/typing-objects-bugs/pr4435_bad.compilers.reference @@ -1,3 +1,5 @@ File "pr4435_bad.ml", line 14, characters 6-7: -Error: Multiple definition of the type name c. +14 | class c (v : int) = + ^ +Error: Multiple definition of the class name c. Names must be unique in a given structure or signature. diff --git a/testsuite/tests/typing-objects-bugs/pr4824a_bad.compilers.reference b/testsuite/tests/typing-objects-bugs/pr4824a_bad.compilers.reference index 01c209e3..8c644ef0 100644 --- a/testsuite/tests/typing-objects-bugs/pr4824a_bad.compilers.reference +++ b/testsuite/tests/typing-objects-bugs/pr4824a_bad.compilers.reference @@ -1,4 +1,6 @@ File "pr4824a_bad.ml", line 10, characters 2-45: +10 | struct class c x = object val x = x end end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Signature mismatch: ... Class declarations do not match: @@ -6,5 +8,3 @@ Error: Signature mismatch: does not match class c : 'a -> object val x : 'b end The instance variable x has type 'a but is expected to have type 'b - This instance of 'b is ambiguous: - it would escape the scope of its equation diff --git a/testsuite/tests/typing-objects-bugs/pr7284_bad.compilers.reference b/testsuite/tests/typing-objects-bugs/pr7284_bad.compilers.reference index 0969398d..de957e79 100644 --- a/testsuite/tests/typing-objects-bugs/pr7284_bad.compilers.reference +++ b/testsuite/tests/typing-objects-bugs/pr7284_bad.compilers.reference @@ -1,4 +1,6 @@ File "pr7284_bad.ml", line 35, characters 30-62: +35 | let f : X.v1 wit -> unit = function V1 s -> print_endline s + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error (warning 8): this pattern-matching is not exhaustive. Here is an example of a case that is not matched: V2 _ diff --git a/testsuite/tests/typing-objects/Exemples.ml b/testsuite/tests/typing-objects/Exemples.ml index 855ba343..4d8f62d9 100644 --- a/testsuite/tests/typing-objects/Exemples.ml +++ b/testsuite/tests/typing-objects/Exemples.ml @@ -95,12 +95,12 @@ class ref x_init = object method set y = x <- y end;; [%%expect{| -Line _, characters 0-95: - class ref x_init = object - val mutable x = x_init - method get = x - method set y = x <- y - end.. +Line 1, characters 0-95: +1 | class ref x_init = object +2 | val mutable x = x_init +3 | method get = x +4 | method set y = x <- y +5 | end.. Error: Some type variables are unbound in this type: class ref : 'a -> @@ -204,9 +204,9 @@ class ['a] color_circle : let c'' = new color_circle p;; [%%expect{| -Line _, characters 27-28: - let c'' = new color_circle p;; - ^ +Line 1, characters 27-28: +1 | let c'' = new color_circle p;; + ^ Error: This expression has type point but an expression was expected of type #color_point The first object type has no method color @@ -222,9 +222,9 @@ val c'' : color_point color_circle = |}];; (c'' :> point circle);; [%%expect{| -Line _, characters 0-21: - (c'' :> point circle);; - ^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-21: +1 | (c'' :> point circle);; + ^^^^^^^^^^^^^^^^^^^^^ Error: Type color_point color_circle = < center : color_point; color : string; move : int -> unit; @@ -233,12 +233,13 @@ Error: Type point circle = < center : point; move : int -> unit; set_center : point -> unit > Type point is not a subtype of color_point + The first object type has no method color |}];; (* Fail *) fun x -> (x : color_point color_circle :> point circle);; [%%expect{| -Line _, characters 9-55: - fun x -> (x : color_point color_circle :> point circle);; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 9-55: +1 | fun x -> (x : color_point color_circle :> point circle);; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Type color_point color_circle = < center : color_point; color : string; move : int -> unit; @@ -247,6 +248,7 @@ Error: Type point circle = < center : point; move : int -> unit; set_center : point -> unit > Type point is not a subtype of color_point + The first object type has no method color |}];; class printable_point y = object (s) @@ -284,9 +286,9 @@ class printable_color_point y c = object (self) Format.print_string ")" end;; [%%expect{| -Line _, characters 10-27: - inherit printable_point y as super - ^^^^^^^^^^^^^^^^^ +Line 3, characters 10-27: +3 | inherit printable_point y as super + ^^^^^^^^^^^^^^^^^ Warning 13: the following instance variables are overridden by the class printable_point : x The behaviour changed in ocaml 3.10 (previous behaviour was hiding.) @@ -532,9 +534,9 @@ val c2 : int_comparable2 = |}];; l#add (c2 :> int_comparable);; [%%expect{| -Line _, characters 6-28: - l#add (c2 :> int_comparable);; - ^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 6-28: +1 | l#add (c2 :> int_comparable);; + ^^^^^^^^^^^^^^^^^^^^^^ Error: Type int_comparable2 = < cmp : int_comparable2 -> int; set_x : int -> unit; x : int > @@ -544,6 +546,7 @@ Error: Type is not a subtype of int_comparable2 = < cmp : int_comparable2 -> int; set_x : int -> unit; x : int > + The first object type has no method set_x |}];; (* Fail : 'a comp2 is not a subtype *) (new sorted_list ())#add c2;; [%%expect{| @@ -577,9 +580,9 @@ l#add (c3 :> int_comparable);; |}];; (new sorted_list ())#add c3;; [%%expect{| -Line _, characters 25-27: - (new sorted_list ())#add c3;; - ^^ +Line 1, characters 25-27: +1 | (new sorted_list ())#add c3;; + ^^ Error: This expression has type int_comparable3 = < cmp : int_comparable -> int; setx : int -> unit; x : int > @@ -591,9 +594,9 @@ Error: This expression has type < cmp : int_comparable -> int; setx : int -> unit; x : int > The first object type has no method setx |}, Principal{| -Line _, characters 25-27: - (new sorted_list ())#add c3;; - ^^ +Line 1, characters 25-27: +1 | (new sorted_list ())#add c3;; + ^^ Error: This expression has type int_comparable3 = < cmp : int_comparable -> int; setx : int -> unit; x : int > @@ -612,9 +615,9 @@ let pr l = List.map (fun c -> Format.print_int c#x; Format.print_string " ") l; Format.print_newline ();; [%%expect{| -Line _, characters 2-69: - List.map (fun c -> Format.print_int c#x; Format.print_string " ") l; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 2-69: +2 | List.map (fun c -> Format.print_int c#x; Format.print_string " ") l; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 10: this expression should have type unit. val pr : < x : int; .. > list -> unit = |}];; diff --git a/testsuite/tests/typing-objects/Tests.ml b/testsuite/tests/typing-objects/Tests.ml index e187c566..6d0d832a 100644 --- a/testsuite/tests/typing-objects/Tests.ml +++ b/testsuite/tests/typing-objects/Tests.ml @@ -31,10 +31,10 @@ end and d () = object inherit ['a] c () end;; [%%expect{| -Line _, characters 4-45: - ....and d () = object - inherit ['a] c () - end.. +Line 3, characters 4-45: +3 | ....and d () = object +4 | inherit ['a] c () +5 | end.. Error: Some type variables are unbound in this type: class d : unit -> object method f : 'a -> unit end The method f has type 'a -> unit where 'a is unbound @@ -88,10 +88,10 @@ class x () = object method virtual f : int end;; [%%expect{| -Line _, characters 0-48: - class x () = object - method virtual f : int - end.. +Line 1, characters 0-48: +1 | class x () = object +2 | method virtual f : int +3 | end.. Error: This class should be virtual. The following methods are undefined : f |}];; (* The class x should be virtual: its methods f is undefined *) @@ -103,9 +103,9 @@ and virtual d x = object (_ : 'a) method g = true end;; [%%expect{| -Line _, characters 49-57: - class virtual c ((x : 'a): < f : int >) = object (_ : 'a) end - ^^^^^^^^ +Line 1, characters 49-57: +1 | class virtual c ((x : 'a): < f : int >) = object (_ : 'a) end + ^^^^^^^^ Error: This pattern cannot match self: it only matches values of type < f : int > |}];; @@ -116,11 +116,11 @@ class ['a] c () = object method f x = (x : bool c) end;; [%%expect{| -Line _, characters 0-78: - class ['a] c () = object - constraint 'a = int - method f x = (x : bool c) - end.. +Line 1, characters 0-78: +1 | class ['a] c () = object +2 | constraint 'a = int +3 | method f x = (x : bool c) +4 | end.. Error: The abbreviation c is used with parameters bool c which are incompatible with constraints int c |}];; @@ -162,10 +162,10 @@ class ['a] c () = object method f = (x : 'a) end;; [%%expect{| -Line _, characters 0-50: - class ['a] c () = object - method f = (x : 'a) - end.. +Line 1, characters 0-50: +1 | class ['a] c () = object +2 | method f = (x : 'a) +3 | end.. Error: The type of this class, class ['a] c : unit -> object constraint 'a = '_weak1 list ref method f : 'a end, @@ -176,9 +176,9 @@ Error: The type of this class, type 'a c = and 'a d = ;; [%%expect{| -Line _, characters 0-32: - type 'a c = - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-32: +1 | type 'a c = + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In the definition of d, type int c should be 'a c |}];; type 'a c = @@ -196,18 +196,18 @@ and 'a d = < f : int c > type 'a u = < x : 'a> and 'a t = 'a t u;; [%%expect{| -Line _, characters 0-17: - and 'a t = 'a t u;; - ^^^^^^^^^^^^^^^^^ +Line 2, characters 0-17: +2 | and 'a t = 'a t u;; + ^^^^^^^^^^^^^^^^^ Error: The definition of t contains a cycle: 'a t u |}];; (* fails since 4.04 *) type 'a u = 'a and 'a t = 'a t u;; [%%expect{| -Line _, characters 0-17: - and 'a t = 'a t u;; - ^^^^^^^^^^^^^^^^^ +Line 2, characters 0-17: +2 | and 'a t = 'a t u;; + ^^^^^^^^^^^^^^^^^ Error: The type abbreviation t is cyclic |}];; type 'a u = 'a;; @@ -216,9 +216,9 @@ type 'a u = 'a |}];; type t = t u * t u;; [%%expect{| -Line _, characters 0-18: - type t = t u * t u;; - ^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-18: +1 | type t = t u * t u;; + ^^^^^^^^^^^^^^^^^^ Error: The type abbreviation t is cyclic |}];; @@ -380,9 +380,9 @@ class e : unit -> object method f : int end |}];; class c () = object val x = - true val y = -. () end;; [%%expect{| -Line _, characters 30-34: - class c () = object val x = - true val y = -. () end;; - ^^^^ +Line 1, characters 30-34: +1 | class c () = object val x = - true val y = -. () end;; + ^^^^ Error: This expression has type bool but an expression was expected of type int |}];; @@ -447,26 +447,26 @@ class e () = object method b = b end;; [%%expect{| -Line _, characters 10-13: - inherit c 5 - ^^^ +Line 3, characters 10-13: +3 | inherit c 5 + ^^^ Warning 13: the following instance variables are overridden by the class c : x The behaviour changed in ocaml 3.10 (previous behaviour was hiding.) -Line _, characters 6-7: - val y = 3 - ^ +Line 4, characters 6-7: +4 | val y = 3 + ^ Warning 13: the instance variable y is overridden. The behaviour changed in ocaml 3.10 (previous behaviour was hiding.) -Line _, characters 10-13: - inherit d 7 - ^^^ +Line 6, characters 10-13: +6 | inherit d 7 + ^^^ Warning 13: the following instance variables are overridden by the class d : t z The behaviour changed in ocaml 3.10 (previous behaviour was hiding.) -Line _, characters 6-7: - val u = 3 - ^ +Line 7, characters 6-7: +7 | val u = 3 + ^ Warning 13: the instance variable u is overridden. The behaviour changed in ocaml 3.10 (previous behaviour was hiding.) class e : @@ -618,11 +618,11 @@ class virtual ['a] matrix (sz, init : int * 'a) = object method add (mtx : 'a matrix) = (mtx#m.(0).(0) : 'a) end;; [%%expect{| -Line _, characters 0-153: - class virtual ['a] matrix (sz, init : int * 'a) = object - val m = Array.make_matrix sz sz init - method add (mtx : 'a matrix) = (mtx#m.(0).(0) : 'a) - end.. +Line 1, characters 0-153: +1 | class virtual ['a] matrix (sz, init : int * 'a) = object +2 | val m = Array.make_matrix sz sz init +3 | method add (mtx : 'a matrix) = (mtx#m.(0).(0) : 'a) +4 | end.. Error: The abbreviation 'a matrix expands to type < add : 'a matrix -> 'a > but is used with type < m : 'a array array; .. > |}];; @@ -667,10 +667,10 @@ end : sig val f : #c -> #c end);; [%%expect{| -Line _, characters 12-43: - ............struct - let f (x : #c) = x - end...... +Line 1, characters 12-43: +1 | ............struct +2 | let f (x : #c) = x +3 | end...... Error: Signature mismatch: Modules do not match: sig val f : (#c as 'a) -> 'a end @@ -684,9 +684,9 @@ Error: Signature mismatch: module M = struct type t = int class t () = object end end;; [%%expect{| -Line _, characters 37-38: - module M = struct type t = int class t () = object end end;; - ^ +Line 1, characters 37-38: +1 | module M = struct type t = int class t () = object end end;; + ^ Error: Multiple definition of the type name t. Names must be unique in a given structure or signature. |}];; @@ -698,17 +698,17 @@ fun x -> (x :> < m : 'a -> 'a > as 'a);; fun x -> (x : int -> bool :> 'a -> 'a);; [%%expect{| -Line _, characters 9-38: - fun x -> (x : int -> bool :> 'a -> 'a);; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 9-38: +1 | fun x -> (x : int -> bool :> 'a -> 'a);; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Type int -> bool is not a subtype of int -> int Type bool is not a subtype of int |}];; fun x -> (x : int -> bool :> int -> int);; [%%expect{| -Line _, characters 9-40: - fun x -> (x : int -> bool :> int -> int);; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 9-40: +1 | fun x -> (x : int -> bool :> int -> int);; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Type int -> bool is not a subtype of int -> int Type bool is not a subtype of int |}];; @@ -741,17 +741,17 @@ type 'a t |}];; fun (x : 'a t as 'a) -> ();; [%%expect{| -Line _, characters 9-19: - fun (x : 'a t as 'a) -> ();; - ^^^^^^^^^^ +Line 1, characters 9-19: +1 | fun (x : 'a t as 'a) -> ();; + ^^^^^^^^^^ Error: This alias is bound to type 'a t but is used as an instance of type 'a The type variable 'a occurs inside 'a t |}];; fun (x : 'a t) -> (x : 'a); ();; [%%expect{| -Line _, characters 19-20: - fun (x : 'a t) -> (x : 'a); ();; - ^ +Line 1, characters 19-20: +1 | fun (x : 'a t) -> (x : 'a); ();; + ^ Error: This expression has type 'a t but an expression was expected of type 'a The type variable 'a occurs inside 'a t @@ -766,9 +766,9 @@ fun (x : 'a t as 'a) -> ();; |}];; fun (x : 'a t) -> (x : 'a); ();; [%%expect{| -Line _, characters 18-26: - fun (x : 'a t) -> (x : 'a); ();; - ^^^^^^^^ +Line 1, characters 18-26: +1 | fun (x : 'a t) -> (x : 'a); ();; + ^^^^^^^^ Warning 10: this expression should have type unit. - : ('a t as 'a) t -> unit = |}];; @@ -873,17 +873,17 @@ let o = object val x = 33 val y = 44 method m = x end in class a = let _ = new b in object end and b = let _ = new a in object end;; [%%expect{| -Line _, characters 10-37: - class a = let _ = new b in object end - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 10-37: +1 | class a = let _ = new b in object end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This kind of recursive class expression is not allowed |}];; class a = let _ = new a in object end;; [%%expect{| -Line _, characters 10-37: - class a = let _ = new a in object end;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 10-37: +1 | class a = let _ = new a in object end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This kind of recursive class expression is not allowed |}];; @@ -902,17 +902,17 @@ and b : object end class a = let x() = new a in let y = x() in object end;; [%%expect{| -Line _, characters 10-54: - class a = let x() = new a in let y = x() in object end;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 10-54: +1 | class a = let x() = new a in let y = x() in object end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This kind of recursive class expression is not allowed |}];; class a = object end and b = let x() = new a in let y = x() in object end;; [%%expect{| -Line _, characters 8-52: - and b = let x() = new a in let y = x() in object end;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 8-52: +2 | and b = let x() = new a in let y = x() in object end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This kind of recursive class expression is not allowed |}];; diff --git a/testsuite/tests/typing-objects/abstract_rows.ml b/testsuite/tests/typing-objects/abstract_rows.ml new file mode 100644 index 00000000..0ae3d307 --- /dev/null +++ b/testsuite/tests/typing-objects/abstract_rows.ml @@ -0,0 +1,26 @@ +(* TEST + * expect +*) +type u = +type t = private + +let f (x:t) (y:u) = x = y;; +[%%expect{| +type u = < x : int > +type t = private < x : int; .. > +Line 4, characters 24-25: +4 | let f (x:t) (y:u) = x = y;; + ^ +Error: This expression has type u but an expression was expected of type t + The second object type has an abstract row, it cannot be closed +|}] + + +let g (x:u) (y:t) = x = y;; +[%%expect{| +Line 1, characters 24-25: +1 | let g (x:u) (y:t) = x = y;; + ^ +Error: This expression has type t but an expression was expected of type u + The first object type has an abstract row, it cannot be closed +|}] diff --git a/testsuite/tests/typing-objects/dummy.ml b/testsuite/tests/typing-objects/dummy.ml index f0be9e9b..842c3bf7 100644 --- a/testsuite/tests/typing-objects/dummy.ml +++ b/testsuite/tests/typing-objects/dummy.ml @@ -42,9 +42,9 @@ and foo = object(self) end;; [%%expect{| -Line _, characters 22-26: - inherit child1' self - ^^^^ +Line 16, characters 22-26: +16 | inherit child1' self + ^^^^ Error: This expression has type < child : 'a; previous : 'b option; .. > but an expression was expected of type 'c Self type cannot escape its class @@ -139,11 +139,11 @@ class leading_up_to = object(self : 'a) end end;; [%%expect{| -Line _, characters 4-65: - ....object - inherit child1 self - inherit child2 - end +Line 4, characters 4-65: +4 | ....object +5 | inherit child1 self +6 | inherit child2 +7 | end Error: Cannot close type of object literal: < child : '_weak1; previous : 'a option; _.. > as 'a it has been unified with the self type of a class that is not yet @@ -162,14 +162,14 @@ class assertion_failure = object(self : 'a) end end;; [%%expect{| -Line _, characters 4-129: - ....object - inherit child1 self - inherit child2 - - method previous = None - method child = assert false - end +Line 4, characters 4-129: + 4 | ....object + 5 | inherit child1 self + 6 | inherit child2 + 7 | + 8 | method previous = None + 9 | method child = assert false +10 | end Error: Cannot close type of object literal: < child : '_weak2; previous : 'a option; _.. > as 'a it has been unified with the self type of a class that is not yet diff --git a/testsuite/tests/typing-objects/errors.ml b/testsuite/tests/typing-objects/errors.ml new file mode 100644 index 00000000..bd905628 --- /dev/null +++ b/testsuite/tests/typing-objects/errors.ml @@ -0,0 +1,15 @@ +(* TEST + * expect +*) + +class type virtual ['a] c = object constraint 'a = [<`A of int & float] end +[%%expect {| +Line 1, characters 0-75: +1 | class type virtual ['a] c = object constraint 'a = [<`A of int & float] end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: The type of this class, + class virtual ['a] c : + object constraint 'a = _[< `A of int & float ] end, + contains non-collapsible conjunctive types in constraints. + Type int is not compatible with type float +|}] diff --git a/testsuite/tests/typing-objects/ocamltests b/testsuite/tests/typing-objects/ocamltests index fcada949..cd995e9c 100644 --- a/testsuite/tests/typing-objects/ocamltests +++ b/testsuite/tests/typing-objects/ocamltests @@ -1,4 +1,6 @@ +abstract_rows.ml dummy.ml +errors.ml Exemples.ml open_in_classes.ml pr5545.ml @@ -7,4 +9,5 @@ pr5858.ml pr6123_bad.ml pr6383.ml pr6907_bad.ml +self_cannot_be_closed.ml Tests.ml diff --git a/testsuite/tests/typing-objects/pr5619_bad.ml b/testsuite/tests/typing-objects/pr5619_bad.ml index bd23693c..8cfa9066 100644 --- a/testsuite/tests/typing-objects/pr5619_bad.ml +++ b/testsuite/tests/typing-objects/pr5619_bad.ml @@ -40,14 +40,14 @@ class foo: foo_t = end ;; [%%expect{| -Line _, characters 2-156: - ..object(self) - method foo = "foo" - method cast: type a. a name -> a = - function - Foo -> (self :> foo_t) - | _ -> raise Exit - end +Line 2, characters 2-156: +2 | ..object(self) +3 | method foo = "foo" +4 | method cast: type a. a name -> a = +5 | function +6 | Foo -> (self :> foo_t) +7 | | _ -> raise Exit +8 | end Error: The class type object method cast : 'a name -> 'a method foo : string end is not matched by the class type foo_t diff --git a/testsuite/tests/typing-objects/pr5858.ml b/testsuite/tests/typing-objects/pr5858.ml index 4b92cb1d..a7f0bf84 100644 --- a/testsuite/tests/typing-objects/pr5858.ml +++ b/testsuite/tests/typing-objects/pr5858.ml @@ -9,8 +9,8 @@ class type c = object end module type S = sig class c: c end;; [%%expect{| -Line _, characters 29-30: - module type S = sig class c: c end;; - ^ +Line 1, characters 29-30: +1 | module type S = sig class c: c end;; + ^ Error: The class type c is not yet completely defined |}] diff --git a/testsuite/tests/typing-objects/pr6123_bad.ml b/testsuite/tests/typing-objects/pr6123_bad.ml index 55a8b8b0..6dff6598 100644 --- a/testsuite/tests/typing-objects/pr6123_bad.ml +++ b/testsuite/tests/typing-objects/pr6123_bad.ml @@ -26,9 +26,9 @@ object end ;; [%%expect{| -Line _, characters 50-54: - let args = List.map (fun ty -> new argument(self, ty)) args_ty in - ^^^^ +Line 15, characters 50-54: +15 | let args = List.map (fun ty -> new argument(self, ty)) args_ty in + ^^^^ Error: This expression has type < arguments : 'a; .. > but an expression was expected of type 'b Self type cannot escape its class diff --git a/testsuite/tests/typing-objects/pr6383.ml b/testsuite/tests/typing-objects/pr6383.ml index c039de87..12bc876e 100644 --- a/testsuite/tests/typing-objects/pr6383.ml +++ b/testsuite/tests/typing-objects/pr6383.ml @@ -4,8 +4,8 @@ let f (x: #M.foo) = 0;; [%%expect{| -Line _, characters 11-16: - let f (x: #M.foo) = 0;; - ^^^^^ +Line 1, characters 11-16: +1 | let f (x: #M.foo) = 0;; + ^^^^^ Error: Unbound module M |}];; diff --git a/testsuite/tests/typing-objects/pr6907_bad.ml b/testsuite/tests/typing-objects/pr6907_bad.ml index afdfc971..427ad987 100644 --- a/testsuite/tests/typing-objects/pr6907_bad.ml +++ b/testsuite/tests/typing-objects/pr6907_bad.ml @@ -13,9 +13,9 @@ module type S = sig class base : 'e -> ['e] t end;; [%%expect{| -Line _, characters 2-27: - class base : 'e -> ['e] t - ^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 2-27: +2 | class base : 'e -> ['e] t + ^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Some type variables are unbound in this type: class base : 'e -> ['e] t The method update has type 'e -> < update : 'a; .. > as 'a where 'e diff --git a/testsuite/tests/typing-objects/self_cannot_be_closed.ml b/testsuite/tests/typing-objects/self_cannot_be_closed.ml new file mode 100644 index 00000000..f2cbc406 --- /dev/null +++ b/testsuite/tests/typing-objects/self_cannot_be_closed.ml @@ -0,0 +1,17 @@ +(* TEST + * expect + *) +let is_empty (x : < >) = ();; +[%%expect {| +val is_empty : < > -> unit = +|}] + +class c = object (self) method private foo = is_empty self end;; +[%%expect {| +Line 1, characters 54-58: +1 | class c = object (self) method private foo = is_empty self end;; + ^^^^ +Error: This expression has type < .. > but an expression was expected of type + < > + Self type cannot be unified with a closed object type +|}] diff --git a/testsuite/tests/typing-ocamlc-i/ocamltests b/testsuite/tests/typing-ocamlc-i/ocamltests index dd3bd42f..5855e551 100644 --- a/testsuite/tests/typing-ocamlc-i/ocamltests +++ b/testsuite/tests/typing-ocamlc-i/ocamltests @@ -1 +1,5 @@ +pervasives_leitmotiv.ml +pr4791.ml +pr6323.ml +pr7402.ml pr7620_bad.ml diff --git a/testsuite/tests/typing-ocamlc-i/pervasives_leitmotiv.compilers.reference b/testsuite/tests/typing-ocamlc-i/pervasives_leitmotiv.compilers.reference new file mode 100644 index 00000000..358391a3 --- /dev/null +++ b/testsuite/tests/typing-ocamlc-i/pervasives_leitmotiv.compilers.reference @@ -0,0 +1,13 @@ +File "pervasives_leitmotiv.ml", line 1: +Warning 63: The printed interface differs from the inferred interface. +The inferred interface contained items which could not be printed +properly due to name collisions between identifiers. +File "pervasives_leitmotiv.ml", line 10, characters 0-45: + Definition of module Stdlib/1 +File "_none_", line 1: + Definition of module Stdlib/2 +Beware that this warning is purely informational and will not catch +all instances of erroneous printed interface. +type fpclass = A +module Stdlib : sig type fpclass = B end +val f : fpclass -> Stdlib/1.fpclass -> Stdlib/2.fpclass diff --git a/testsuite/tests/typing-ocamlc-i/pervasives_leitmotiv.ml b/testsuite/tests/typing-ocamlc-i/pervasives_leitmotiv.ml new file mode 100644 index 00000000..f6ec3f9b --- /dev/null +++ b/testsuite/tests/typing-ocamlc-i/pervasives_leitmotiv.ml @@ -0,0 +1,14 @@ +(* TEST +flags = "-i -w +63" +* setup-ocamlc.byte-build-env +** ocamlc.byte +*** check-ocamlc.byte-output +*) + +type fpclass = A + +module Stdlib = struct + type fpclass = B +end + +let f A Stdlib.B = FP_normal diff --git a/testsuite/tests/typing-ocamlc-i/pr4791.compilers.reference b/testsuite/tests/typing-ocamlc-i/pr4791.compilers.reference new file mode 100644 index 00000000..b4938f16 --- /dev/null +++ b/testsuite/tests/typing-ocamlc-i/pr4791.compilers.reference @@ -0,0 +1,12 @@ +File "pr4791.ml", line 1: +Warning 63: The printed interface differs from the inferred interface. +The inferred interface contained items which could not be printed +properly due to name collisions between identifiers. +File "pr4791.ml", line 11, characters 2-12: + Definition of type t/1 +File "pr4791.ml", line 8, characters 0-10: + Definition of type t/2 +Beware that this warning is purely informational and will not catch +all instances of erroneous printed interface. +type t = A +module B : sig type t = B val f : t/2 -> t/1 end diff --git a/testsuite/tests/typing-ocamlc-i/pr4791.ml b/testsuite/tests/typing-ocamlc-i/pr4791.ml new file mode 100644 index 00000000..f7810170 --- /dev/null +++ b/testsuite/tests/typing-ocamlc-i/pr4791.ml @@ -0,0 +1,13 @@ +(* TEST +flags = "-i -w +63" +* setup-ocamlc.byte-build-env +** ocamlc.byte +*** check-ocamlc.byte-output +*) + +type t = A +module B = +struct + type t = B + let f A = B +end diff --git a/testsuite/tests/typing-ocamlc-i/pr6323.compilers.reference b/testsuite/tests/typing-ocamlc-i/pr6323.compilers.reference new file mode 100644 index 00000000..c06cebec --- /dev/null +++ b/testsuite/tests/typing-ocamlc-i/pr6323.compilers.reference @@ -0,0 +1,14 @@ +File "pr6323.ml", line 1: +Warning 63: The printed interface differs from the inferred interface. +The inferred interface contained items which could not be printed +properly due to name collisions between identifiers. +File "pr6323.ml", line 15, characters 2-24: + Definition of type t/1 +File "pr6323.ml", line 8, characters 0-26: + Definition of type t/2 +Beware that this warning is purely informational and will not catch +all instances of erroneous printed interface. +type 'a t = B of 'a t list +val foo : 'a -> 'b t list -> 'c t list +module DT : + sig type 'a t = { bar : 'a; } val p : 'a t/2 list -> 'b t/2 list end diff --git a/testsuite/tests/typing-ocamlc-i/pr6323.ml b/testsuite/tests/typing-ocamlc-i/pr6323.ml new file mode 100644 index 00000000..7aff93f1 --- /dev/null +++ b/testsuite/tests/typing-ocamlc-i/pr6323.ml @@ -0,0 +1,17 @@ +(* TEST +flags = "-i -w +63" +* setup-ocamlc.byte-build-env +** ocamlc.byte +*** check-ocamlc.byte-output +*) + +type 'a t = B of 'a t list + +let rec foo f = function + | B(v)::tl -> B(foo f v)::foo f tl + | [] -> [] + +module DT = struct + type 'a t = {bar : 'a} + let p t = foo (fun x -> x) t +end diff --git a/testsuite/tests/typing-ocamlc-i/pr7402.compilers.reference b/testsuite/tests/typing-ocamlc-i/pr7402.compilers.reference new file mode 100644 index 00000000..08c87199 --- /dev/null +++ b/testsuite/tests/typing-ocamlc-i/pr7402.compilers.reference @@ -0,0 +1,12 @@ +File "pr7402.ml", line 1: +Warning 63: The printed interface differs from the inferred interface. +The inferred interface contained items which could not be printed +properly due to name collisions between identifiers. +File "pr7402.ml", line 14, characters 0-39: + Definition of module M/1 +File "pr7402.ml", line 8, characters 0-70: + Definition of module M/2 +Beware that this warning is purely informational and will not catch +all instances of erroneous printed interface. +module M : sig type t val v : t end +module F : sig module M : sig val v : M.t end val v : M/2.t end diff --git a/testsuite/tests/typing-ocamlc-i/pr7402.ml b/testsuite/tests/typing-ocamlc-i/pr7402.ml new file mode 100644 index 00000000..b1ccef88 --- /dev/null +++ b/testsuite/tests/typing-ocamlc-i/pr7402.ml @@ -0,0 +1,19 @@ +(* TEST +flags = "-i -w +63" +* setup-ocamlc.byte-build-env +** ocamlc.byte +*** check-ocamlc.byte-output +*) + +module M: sig type t val v:t end = struct + type t = A + let v = A +end + +module F = struct +module M = struct + let v = M.v + end + + let v = M.v +end diff --git a/testsuite/tests/typing-ocamlc-i/pr7620_bad.compilers.reference b/testsuite/tests/typing-ocamlc-i/pr7620_bad.compilers.reference index 99d84e40..89740996 100644 --- a/testsuite/tests/typing-ocamlc-i/pr7620_bad.compilers.reference +++ b/testsuite/tests/typing-ocamlc-i/pr7620_bad.compilers.reference @@ -1,4 +1,6 @@ File "pr7620_bad.ml", line 10, characters 17-19: +10 | (function `A | `B -> () : 'a) (`A : [`A]); + ^^ Error: This pattern matches values of type [? `B ] but a pattern was expected which matches values of type [ `A ] Types for tag `B are incompatible diff --git a/testsuite/tests/typing-ocamlc-i/pr7620_bad.ml b/testsuite/tests/typing-ocamlc-i/pr7620_bad.ml index 6c6cc395..25d199a6 100644 --- a/testsuite/tests/typing-ocamlc-i/pr7620_bad.ml +++ b/testsuite/tests/typing-ocamlc-i/pr7620_bad.ml @@ -6,6 +6,6 @@ ocamlc_byte_exit_status = "2" *** check-ocamlc.byte-output *) -let t = +let t = (function `A | `B -> () : 'a) (`A : [`A]); (failwith "dummy" : 'a) (* to know how 'a is unified *) diff --git a/testsuite/tests/typing-pattern_open/ocamltests b/testsuite/tests/typing-pattern_open/ocamltests deleted file mode 100644 index 10150243..00000000 --- a/testsuite/tests/typing-pattern_open/ocamltests +++ /dev/null @@ -1 +0,0 @@ -pattern_open.ml diff --git a/testsuite/tests/typing-pattern_open/pattern_open.ml b/testsuite/tests/typing-pattern_open/pattern_open.ml deleted file mode 100644 index b5d4eeeb..00000000 --- a/testsuite/tests/typing-pattern_open/pattern_open.ml +++ /dev/null @@ -1,151 +0,0 @@ -(* TEST - * toplevel -*) - -let pp fmt = Printf.printf fmt - -type 'a box = B of 'a -(* Basic tests *) -module M = struct - type c = C - type t = {x : c box } -end -;; -module N = struct - type d = D - let d = D - type t = {x: d box} -end -open N -;; -let f M.{ x=B C } y = M.C,y -;; -let g M.(x) M.(w) = x * w -;; -let g = function - | M.[] -> [] - | M.[C] -> M.[C] - | _ -> [] -;; -let h = function - | M.[||] -> None - | M.[| C |] -> Some M.C - | _ -> None -;; -let f2 = function - | M.( B (B C) ) -> M.C -;; - -;; -(* () constructor *) -let M.() = () -;; -(* Pattern open separation*) -module L = struct - type _ c = C : unit c - type t = { t : unit c } - type r = { r : unit c } - let x ()= pp "Wrong value L.x\n" -end -;; -module K = struct - type _ c = C : unit c - type t = { t : unit c } - type r = { r : unit c } - let x ()= pp "Right value K.x\n" -end -;; -let () = - let test = - let open K in - function - | L.{t}, ({r=C} : K.r) -> x () - in - test (L.{t=C}, K.{r=C}) -;; -module Exterior = struct -module Gadt = struct -module Boolean = struct - type t = { b : bool } - type wrong = false | true - let print () = pp "Wrong function: Exterior.Gadt.Boolean.print\n" -end - -type _ t = - | Bool : Boolean.t -> bool t - | Int : int -> int t - | Eq : 'a t * 'a t -> bool t - -let print () = pp "Wrong function: Exterior.Gadt.print\n" -end -let print () = pp "Wrong function: Exterior.print\n" -end -;; -let rec eval: type t. t Exterior.Gadt.t -> t = function - | Exterior.( Gadt.( Eq (a,b) ) ) -> (eval a) = (eval b) - | Exterior.( Gadt.( Bool Boolean.{b} ) ) -> b - | Exterior.Gadt.( Int n ) -> n -let () = - let print () = pp "Right function print\n" in - let choose (type a):a Exterior.Gadt.t * a Exterior.Gadt.t -> a -> a = - fun (a,b) c -> - match a, b, c with - | Exterior.( Gadt.( Bool Boolean.{b} ), Gadt.Bool _ , _ ) -> print(); true - | Exterior.(Gadt.Bool Gadt.Boolean.{b}), _ , true -> print(); true - | Exterior.(Gadt.Bool Gadt.Boolean.{b}), _ , false -> print(); b - | Exterior.Gadt.( Int n, Int k, 0 ) -> print(); 0 - | Exterior.( Gadt.(Int n, Gadt.Int k, l) ) -> print(); k+n+l - | Exterior.Gadt.( Eq (a,b) ), _, true -> print(); true - | Exterior.(Gadt.( Eq (a,b), _ , false )) -> print(); eval a = eval b in - let _ = - choose Exterior.Gadt.(Bool Boolean.{b=true}, Bool Boolean.{b=false}) false - in - print () -;; -(* existential type *) -module Existential = struct -type printable = E : 'a * ('a -> unit) -> printable -end - -let rec print: Existential.printable -> unit = function - | Existential.( E(x, print) ) -> print x -;; -(* Test that constructors and variables introduced in scope inside -M.(..) are not propagated outside of M.(..) *) -module S = struct -type 'a t = Sep : unit t -type ex = Ex: 'a * 'a -> ex -let s = Sep -end -;; -let test_separation = function - | S.(Sep), (S.(Sep,Sep), Sep) -> () -;; -let test_separation_2 = function - | S.(Ex(a,b)), Ex(c,d) -> () -;; -let test_separation_3 = function - | S.(Sep) -> s -;; - -(* Testing interaction of local open in pattern and backtracking *) -module PR6437 = struct - module Ctx = struct - type ('a, 'b) t = - | Nil : (unit, unit) t - | Cons : ('a, 'b) t -> ('a * unit, 'b * unit) t - end - - module Var = struct - type 'a t = - | O : ('a * unit) t - | S : 'a t -> ('a * unit) t - end -end - -let rec f : type g1 g2. (g1, g2) PR6437.Ctx.t * g1 PR6437.Var.t - -> g2 PR6437.Var.t = function - | PR6437.( Ctx.(Cons g), Var.(O) ) -> PR6437.Var.O - | PR6437.( Ctx.(Cons g), Var.(S n) ) -> PR6437.Var.S (f (g, n)) - | _ -> . -;; diff --git a/testsuite/tests/typing-pattern_open/pattern_open.ocaml.reference b/testsuite/tests/typing-pattern_open/pattern_open.ocaml.reference deleted file mode 100644 index 28bc57ca..00000000 --- a/testsuite/tests/typing-pattern_open/pattern_open.ocaml.reference +++ /dev/null @@ -1,80 +0,0 @@ -val pp : ('a, out_channel, unit) format -> 'a = -type 'a box = B of 'a -module M : sig type c = C type t = { x : c box; } end -module N : sig type d = D val d : d type t = { x : d box; } end -val f : M.t -> 'a -> M.c * 'a = -val g : int -> int -> int = -val g : M.c list -> M.c list = -val h : M.c array -> M.c option = -val f2 : M.c box box -> M.c = -module L : - sig - type _ c = C : unit c - type t = { t : unit c; } - type r = { r : unit c; } - val x : unit -> unit - end -module K : - sig - type _ c = C : unit c - type t = { t : unit c; } - type r = { r : unit c; } - val x : unit -> unit - end -Right value K.x -module Exterior : - sig - module Gadt : - sig - module Boolean : - sig - type t = { b : bool; } - type wrong = false | true - val print : unit -> unit - end - type _ t = - Bool : Boolean.t -> bool t - | Int : int -> int t - | Eq : 'a t * 'a t -> bool t - val print : unit -> unit - end - val print : unit -> unit - end -Right function print -Right function print -val eval : 't Exterior.Gadt.t -> 't = -module Existential : - sig type printable = E : 'a * ('a -> unit) -> printable end -val print : Existential.printable -> unit = -module S : - sig - type 'a t = Sep : unit t - type ex = Ex : 'a * 'a -> ex - val s : unit t - end -Characters 58-61: - | S.(Sep), (S.(Sep,Sep), Sep) -> () - ^^^ -Error: Unbound constructor Sep -Characters 50-52: - | S.(Ex(a,b)), Ex(c,d) -> () - ^^ -Error: Unbound constructor Ex -Characters 48-49: - | S.(Sep) -> s - ^ -Error: Unbound value s -module PR6437 : - sig - module Ctx : - sig - type ('a, 'b) t = - Nil : (unit, unit) t - | Cons : ('a, 'b) t -> ('a * unit, 'b * unit) t - end - module Var : - sig type 'a t = O : ('a * unit) t | S : 'a t -> ('a * unit) t end - end -val f : ('g1, 'g2) PR6437.Ctx.t * 'g1 PR6437.Var.t -> 'g2 PR6437.Var.t = - - diff --git a/testsuite/tests/typing-poly-bugs/pr5673_bad.compilers.reference b/testsuite/tests/typing-poly-bugs/pr5673_bad.compilers.reference index 63dbdb98..c4984037 100644 --- a/testsuite/tests/typing-poly-bugs/pr5673_bad.compilers.reference +++ b/testsuite/tests/typing-poly-bugs/pr5673_bad.compilers.reference @@ -1,11 +1,14 @@ File "pr5673_bad.ml", line 31, characters 22-23: +31 | let f (x : refer1) = (x : refer2) + ^ Error: This expression has type refer1 = < poly : 'a 'b 'c. ('b, 'c) #Classdef.cl2 as 'a > but an expression was expected of type refer2 = < poly : 'd 'b 'c. ('b, 'c) #Classdef.cl2 as 'd > - Type - ('b, 'c) Classdef.cl1 = - < m : 'b -> 'c -> int; raise_trouble : int -> 'b > + Type ('b, 'c, ('b, 'c) Classdef.cl1) Classdef.cl0 = < > is not compatible with type - < m : 'b -> 'c -> int; raise_trouble : int -> 'b > - The type variable 'e occurs inside 'e + ('b0, 'c0, ('b0, 'c0) Classdef.cl1) Classdef.cl0 + Type < m : 'b -> 'c -> int; .. > is not compatible with type + ('b, 'c) Classdef.cl1 = + < m : 'b -> 'c -> int; raise_trouble : int -> 'b > + The universal variable 'b would escape its scope diff --git a/testsuite/tests/typing-poly/error_messages.ml b/testsuite/tests/typing-poly/error_messages.ml new file mode 100644 index 00000000..0f22bccc --- /dev/null +++ b/testsuite/tests/typing-poly/error_messages.ml @@ -0,0 +1,85 @@ +(* TEST + * expect +*) + +type t = < x : 'a. int as 'a > +[%%expect {| +Line 1, characters 15-28: +1 | type t = < x : 'a. int as 'a > + ^^^^^^^^^^^^^ +Error: The universal type variable 'a cannot be generalized: it is bound to + int. +|}] +type u = < x : 'a 'b. 'a as 'b > +[%%expect {| +Line 1, characters 15-30: +1 | type u = < x : 'a 'b. 'a as 'b > + ^^^^^^^^^^^^^^^ +Error: The universal type variable 'b cannot be generalized: + it is already bound to another variable. +|}] +type v = 'b -> < x : 'a. 'b as 'a > +[%%expect {| +Line 1, characters 21-33: +1 | type v = 'b -> < x : 'a. 'b as 'a > + ^^^^^^^^^^^^ +Error: The universal type variable 'a cannot be generalized: + it escapes its scope. +|}] + + +(** Check that renaming universal type variable is properly tracked + in printtyp *) + +let f (x:) (y:) = x = y +[%%expect {| +Line 4, characters 49-50: +4 | let f (x:) (y:) = x = y + ^ +Error: This expression has type < a : 'a; b : 'a > + but an expression was expected of type < a : 'a; b : 'a0. 'a0 > + The method b has type 'a, but the expected method type was 'a0. 'a0 + The universal variable 'a0 would escape its scope +|}] + + +(** MPR 7565 *) +class type t_a = object + method f: 'a. 'a -> int + end +let f (o:t_a) = o # f 0 +let _ = f (object + method f _ = 0 + end);; +[%%expect {| +class type t_a = object method f : 'a -> int end +val f : t_a -> int = +Line 5, characters 10-42: +5 | ..........(object +6 | method f _ = 0 +7 | end).. +Error: This expression has type < f : 'a -> int > + but an expression was expected of type t_a + The method f has type 'a -> int, but the expected method type was + 'a0. 'a0 -> int + The universal variable 'a0 would escape its scope +|} +] + +type uv = [ `A of int > ] +type 'a v = [ `A of int > ] +let f (`A o:uv) = o # f 0 +let () = f ( `A (object method f _ = 0 end): _ v);; +[%%expect {| +type uv = [ `A of < f : 'a. 'a -> int > ] +type 'a v = [ `A of < f : 'a -> int > ] +val f : uv -> int = +Line 4, characters 11-49: +4 | let () = f ( `A (object method f _ = 0 end): _ v);; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This expression has type 'a v but an expression was expected of type + uv + The method f has type 'a -> int, but the expected method type was + 'a0. 'a0 -> int + The universal variable 'a0 would escape its scope +|}] diff --git a/testsuite/tests/typing-poly/ocamltests b/testsuite/tests/typing-poly/ocamltests index be3e7110..050266c6 100644 --- a/testsuite/tests/typing-poly/ocamltests +++ b/testsuite/tests/typing-poly/ocamltests @@ -1 +1,2 @@ +error_messages.ml poly.ml diff --git a/testsuite/tests/typing-poly/poly.ml b/testsuite/tests/typing-poly/poly.ml index 5f727c4e..c8f050c1 100644 --- a/testsuite/tests/typing-poly/poly.ml +++ b/testsuite/tests/typing-poly/poly.ml @@ -21,6 +21,75 @@ val f : 'a list -> 'a fold = - : int = 6 |}];; +type pty = {pv : 'a. 'a list};; +[%%expect {| +type pty = { pv : 'a. 'a list; } +|}];; + + +type id = { id : 'a. 'a -> 'a };; +let id x = x;; +let {id} = id { id };; +[%%expect {| +type id = { id : 'a. 'a -> 'a; } +val id : 'a -> 'a = +val id : 'a -> 'a = +|}];; + +let px = {pv = []};; +[%%expect {| +val px : pty = {pv = []} +|}];; + +match px with +| {pv=[]} -> "OK" +| {pv=5::_} -> "int" +| {pv=true::_} -> "bool" +;; +[%%expect {| +Line 1, characters 0-77: +1 | match px with +2 | | {pv=[]} -> "OK" +3 | | {pv=5::_} -> "int" +4 | | {pv=true::_} -> "bool" +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +{pv=false::_} +- : string = "OK" +|}];; + +match px with +| {pv=[]} -> "OK" +| {pv=true::_} -> "bool" +| {pv=5::_} -> "int" +;; +[%%expect {| +Line 1, characters 0-77: +1 | match px with +2 | | {pv=[]} -> "OK" +3 | | {pv=true::_} -> "bool" +4 | | {pv=5::_} -> "int" +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +{pv=0::_} +- : string = "OK" +|}];; + +match px with +| {pv=[]} -> "OK" +| {pv=5::_} -> "int" +| {pv=true::_} -> "bool" +| {pv=false::_} -> "bool" +;; +[%%expect {| +- : string = "OK" +|}];; + +fun {pv=v} -> true::v, 1::v;; +[%%expect {| +- : pty -> bool list * int list = +|}];; + class ['b] ilist l = object val l = l method add x = {< l = x :: l >} @@ -232,9 +301,9 @@ class ['a] ostream1 : method tl : 'b end |}, Principal{| -Line _, characters 4-16: - self#tl#fold ~f ~init:(f self#hd init) - ^^^^^^^^^^^^ +Line 8, characters 4-16: +8 | self#tl#fold ~f ~init:(f self#hd init) + ^^^^^^^^^^^^ Warning 18: this use of a polymorphic method is not principal. class ['a] ostream1 : hd:'a -> @@ -391,11 +460,13 @@ val cp : color_point = val c : circle = val d : float = 11. val f : < m : 'a. 'a -> 'a > -> < m : 'b. 'b -> 'b > = -Line _, characters 41-42: - let f (x : < m : 'a. 'a -> 'a list >) = (x : < m : 'b. 'b -> 'c >) - ^ +Line 9, characters 41-42: +9 | let f (x : < m : 'a. 'a -> 'a list >) = (x : < m : 'b. 'b -> 'c >) + ^ Error: This expression has type < m : 'b. 'b -> 'b list > but an expression was expected of type < m : 'b. 'b -> 'c > + The method m has type 'b. 'b -> 'b list, + but the expected method type was 'b. 'b -> 'c The universal variable 'b would escape its scope |}];; @@ -443,9 +514,9 @@ class ['a] id1 = object end ;; [%%expect {| -Line _, characters 12-17: - method id x = x - ^^^^^ +Line 3, characters 12-17: +3 | method id x = x + ^^^^^ Error: This method has type 'a -> 'a which is less general than 'b. 'b -> 'a |}];; @@ -455,9 +526,9 @@ class id2 (x : 'a) = object end ;; [%%expect {| -Line _, characters 12-17: - method id x = x - ^^^^^ +Line 3, characters 12-17: +3 | method id x = x + ^^^^^ Error: This method has type 'a -> 'a which is less general than 'b. 'b -> 'a |}];; @@ -468,9 +539,9 @@ class id3 x = object end ;; [%%expect {| -Line _, characters 12-17: - method id _ = x - ^^^^^ +Line 4, characters 12-17: +4 | method id _ = x + ^^^^^ Error: This method has type 'b -> 'b which is less general than 'a. 'a -> 'a |}];; @@ -484,11 +555,11 @@ class id4 () = object end ;; [%%expect {| -Line _, characters 12-79: - ............x = - match r with - None -> r <- Some x; x - | Some y -> y +Line 4, characters 12-79: +4 | ............x = +5 | match r with +6 | None -> r <- Some x; x +7 | | Some y -> y Error: This method has type 'b -> 'b which is less general than 'a. 'a -> 'a |}];; @@ -513,9 +584,9 @@ let f4 f = ignore(f : id); f#id 1, f#id true [%%expect {| val f1 : id -> int * bool = val f2 : id -> int * bool = -Line _, characters 24-28: - let f3 f = f#id 1, f#id true - ^^^^ +Line 5, characters 24-28: +5 | let f3 f = f#id 1, f#id true + ^^^^ Error: This expression has type bool but an expression was expected of type int |}];; @@ -543,9 +614,9 @@ type 'a foo = 'a foo list [%%expect {| class id2 : object method id : 'a -> 'a method mono : int -> int end val app : int * bool = (1, true) -Line _, characters 0-25: - type 'a foo = 'a foo list - ^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 9, characters 0-25: +9 | type 'a foo = 'a foo list + ^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The type abbreviation foo is cyclic |}];; @@ -753,9 +824,9 @@ let bad2 = {bad2 = None};; bad2.bad2 <- Some (ref None);; [%%expect {| type bad = { bad : 'a. 'a option ref; } -Line _, characters 17-25: - let bad = {bad = ref None};; - ^^^^^^^^ +Line 2, characters 17-25: +2 | let bad = {bad = ref None};; + ^^^^^^^^ Error: This field value has type 'b option ref which is less general than 'a. 'a option ref |}];; @@ -808,9 +879,9 @@ object method virtual caseNil : 'a end and virtual int_list = object method virtual visit : 'a.('a visitor -> 'a) end;; [%%expect {| -Line _, characters 30-51: - object method virtual visit : 'a.('a visitor -> 'a) end;; - ^^^^^^^^^^^^^^^^^^^^^ +Line 4, characters 30-51: +4 | object method virtual visit : 'a.('a visitor -> 'a) end;; + ^^^^^^^^^^^^^^^^^^^^^ Error: The universal type variable 'a cannot be generalized: it escapes its scope. |}];; @@ -835,9 +906,9 @@ type t = { f : 'a 'b. ('b -> (#ct as 'a) -> 'b) -> 'b; } (* PR#1663 *) type t = u and u = t;; [%%expect {| -Line _, characters 0-10: - type t = u and u = t;; - ^^^^^^^^^^ +Line 1, characters 0-10: +1 | type t = u and u = t;; + ^^^^^^^^^^ Error: The definition of t contains a cycle: u |}];; @@ -853,9 +924,9 @@ type t = [ `A of t a ] (* Wrong in 3.06 *) type ('a,'b) t constraint 'a = 'b and ('a,'b) u = ('a,'b) t;; [%%expect {| -Line _, characters 50-59: - type ('a,'b) t constraint 'a = 'b and ('a,'b) u = ('a,'b) t;; - ^^^^^^^^^ +Line 1, characters 50-59: +1 | type ('a,'b) t constraint 'a = 'b and ('a,'b) u = ('a,'b) t;; + ^^^^^^^^^ Error: Constraints are not satisfied in this type. Type ('a, 'b) t should be an instance of ('c, 'c) t |}];; @@ -873,9 +944,9 @@ type 'a u = 'a and 'a v = 'a u t;; type 'a u = 'a and 'a v = 'a u t constraint 'a = int;; [%%expect {| type 'a t constraint 'a = int -Line _, characters 26-32: - type 'a u = 'a and 'a v = 'a u t;; - ^^^^^^ +Line 2, characters 26-32: +2 | type 'a u = 'a and 'a v = 'a u t;; + ^^^^^^ Error: Constraints are not satisfied in this type. Type 'a u t should be an instance of int t |}];; @@ -888,9 +959,9 @@ type 'a u = 'a and 'a v = 'a u t constraint 'a = int;; [%%expect {| type g = int type 'a t = unit constraint 'a = g -Line _, characters 26-32: - type 'a u = 'a and 'a v = 'a u t;; - ^^^^^^ +Line 3, characters 26-32: +3 | type 'a u = 'a and 'a v = 'a u t;; + ^^^^^^ Error: Constraints are not satisfied in this type. Type 'a u t should be an instance of g t |}];; @@ -898,9 +969,9 @@ Error: Constraints are not satisfied in this type. (* Example of wrong expansion *) type 'a u = < m : 'a v > and 'a v = 'a list u;; [%%expect {| -Line _, characters 0-24: - type 'a u = < m : 'a v > and 'a v = 'a list u;; - ^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-24: +1 | type 'a u = < m : 'a v > and 'a v = 'a list u;; + ^^^^^^^^^^^^^^^^^^^^^^^^ Error: In the definition of v, type 'a list u should be 'a u |}];; @@ -930,9 +1001,9 @@ type u = 'a t as 'a type ('a, 'b) a = 'a -> unit constraint 'a = [> `B of ('a, 'b) b as 'b] and ('a, 'b) b = 'b -> unit constraint 'b = [> `A of ('a, 'b) a as 'a];; [%%expect {| -Line _, characters 0-71: - type ('a, 'b) a = 'a -> unit constraint 'a = [> `B of ('a, 'b) b as 'b] - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-71: +1 | type ('a, 'b) a = 'a -> unit constraint 'a = [> `B of ('a, 'b) b as 'b] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The definition of a contains a cycle: [> `B of ('a, 'b) b as 'b ] as 'a |}];; @@ -1008,15 +1079,15 @@ end;; class c : object method m : int end val f : unit -> c = val f : unit -> c = -Line _, characters 11-60: - let f () = object method private n = 1 method m = {<>}#n end;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 4, characters 11-60: +4 | let f () = object method private n = 1 method m = {<>}#n end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 15: the following private methods were made public implicitly: n. val f : unit -> < m : int; n : int > = -Line _, characters 11-56: - let f () = object (self:c) method n = 1 method m = 2 end;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 5, characters 11-56: +5 | let f () = object (self:c) method n = 1 method m = 2 end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This object is expected to have type c but actually has type < m : int; n : 'a > The first object type has no method n @@ -1032,13 +1103,15 @@ type 'a bar = > type bar' = let f (x : foo') = (x : bar');; [%%expect {| -Line _, characters 3-4: - (x : > as 'bar) >);; - ^ +Line 2, characters 3-4: +2 | (x : > as 'bar) >);; + ^ Error: This expression has type < m : 'a. 'a * < m : 'a * 'b > > as 'b but an expression was expected of type < m : 'a. 'a * (< m : 'a * < m : 'c. 'c * 'd > > as 'd) > - Types for method m are incompatible + The method m has type 'a. 'a * 'd, but the expected method type was + 'c. 'c * 'd + The universal variable 'a would escape its scope |}];; fun (x : as 'foo)>) -> @@ -1051,9 +1124,9 @@ let f x = (x : ('a * 'bar> as 'bar)> :> ('a * 'foo)> as 'foo);; [%%expect {| -Line _, characters 3-4: - (x : )> as 'bar);; - ^ +Line 2, characters 3-4: +2 | (x : )> as 'bar);; + ^ Error: This expression has type < m : 'b. 'b * ('b * < m : 'c. 'c * 'a > as 'a) > but an expression was expected of type @@ -1068,9 +1141,9 @@ module M : sig type t = as 'bar)> end = struct type t = as 'foo end;; [%%expect {| -Line _, characters 2-64: - = struct let f (x : as 'foo) = () end;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 2-64: +3 | = struct let f (x : as 'foo) = () end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Signature mismatch: Modules do not match: sig val f : (< m : 'a. 'a * ('a * 'b) > as 'b) -> unit end @@ -1128,9 +1201,9 @@ type v = private [> t ] - : t -> v = type u = private [< t ] - : u -> v = -Line _, characters 9-21: - fun x -> (x : v :> u);; - ^^^^^^^^^^^^ +Line 6, characters 9-21: +6 | fun x -> (x : v :> u);; + ^^^^^^^^^^^^ Error: Type v = [> `A | `B ] is not a subtype of u = [< `A | `B ] |}];; @@ -1149,9 +1222,9 @@ let f5 x = let f6 x = (x : ] as 'a> :> ] as 'a>);; [%%expect {| -Line _, characters 2-88: - ..(x : as 'a) -> int> - :> as 'b) -> int>).. +Line 2, characters 2-88: +2 | ..(x : as 'a) -> int> +3 | :> as 'b) -> int>).. Error: Type < m : 'a. (< p : int; .. > as 'a) -> int > is not a subtype of < m : 'b. (< p : int; q : int; .. > as 'b) -> int > Type < p : int; q : int; .. > as 'c is not a subtype of @@ -1174,21 +1247,21 @@ val f : < m : 'a. 'a -> 'a > -> < m : 'a. 'a -> 'a > array = - : < m : 'a. 'a -> 'a > -> 'b -> 'b = |}, Principal{| val f : < m : 'a. 'a -> 'a > -> < m : 'a. 'a -> 'a > = -Line _, characters 9-16: - fun x -> (f x)#m;; (* Warning 18 *) - ^^^^^^^ +Line 2, characters 9-16: +2 | fun x -> (f x)#m;; (* Warning 18 *) + ^^^^^^^ Warning 18: this use of a polymorphic method is not principal. - : < m : 'a. 'a -> 'a > -> 'b -> 'b = val f : < m : 'a. 'a -> 'a > * 'b -> < m : 'a. 'a -> 'a > = -Line _, characters 9-20: - fun x -> (f (x,x))#m;; (* Warning 18 *) - ^^^^^^^^^^^ +Line 4, characters 9-20: +4 | fun x -> (f (x,x))#m;; (* Warning 18 *) + ^^^^^^^^^^^ Warning 18: this use of a polymorphic method is not principal. - : < m : 'a. 'a -> 'a > -> 'b -> 'b = val f : < m : 'a. 'a -> 'a > -> < m : 'a. 'a -> 'a > array = -Line _, characters 9-20: - fun x -> (f x).(0)#m;; (* Warning 18 *) - ^^^^^^^^^^^ +Line 6, characters 9-20: +6 | fun x -> (f x).(0)#m;; (* Warning 18 *) + ^^^^^^^^^^^ Warning 18: this use of a polymorphic method is not principal. - : < m : 'a. 'a -> 'a > -> 'b -> 'b = |}];; @@ -1215,14 +1288,14 @@ val h : < id : 'a; .. > -> 'a = class c : object method id : 'a -> 'a end type u = c option val just : 'a option -> 'a = -Line _, characters 42-62: - let f x = let l = [Some x; (None : u)] in (just(List.hd l))#id;; - ^^^^^^^^^^^^^^^^^^^^ +Line 4, characters 42-62: +4 | let f x = let l = [Some x; (None : u)] in (just(List.hd l))#id;; + ^^^^^^^^^^^^^^^^^^^^ Warning 18: this use of a polymorphic method is not principal. val f : c -> 'a -> 'a = -Line _, characters 36-47: - let x = List.hd [Some x; none] in (just x)#id;; - ^^^^^^^^^^^ +Line 7, characters 36-47: +7 | let x = List.hd [Some x; none] in (just x)#id;; + ^^^^^^^^^^^ Warning 18: this use of a polymorphic method is not principal. val g : c -> 'a -> 'a = val h : < id : 'a; .. > -> 'a = @@ -1263,9 +1336,9 @@ val f : 'a -> int = val g : 'a -> int = type 'a t = Leaf of 'a | Node of ('a * 'a) t val depth : 'a t -> int = -Line _, characters 2-42: - function Leaf _ -> 1 | Node x -> 1 + d x - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 6, characters 2-42: +6 | function Leaf _ -> 1 | Node x -> 1 + d x + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This definition has type 'a t -> int which is less general than 'a0. 'a0 t -> int |}];; @@ -1279,9 +1352,9 @@ let zero = {f = `Int 0} ;; (* fails *) type t = { f : 'a. [> `B of 'a | `Int of int ] as 'a; } val zero : t = {f = `Int 0} type t = { f : 'a. [< `Int of int ] as 'a; } -Line _, characters 16-22: - let zero = {f = `Int 0} ;; (* fails *) - ^^^^^^ +Line 4, characters 16-22: +4 | let zero = {f = `Int 0} ;; (* fails *) + ^^^^^^ Error: This expression has type [> `Int of int ] but an expression was expected of type [< `Int of int ] Types for tag `Int are incompatible @@ -1331,9 +1404,9 @@ let f ?x y = y in {f};; (* fail *) [%%expect {| type t = { f : 'a. 'a -> unit; } - : t = {f = } -Line _, characters 19-20: - let f ?x y = y in {f};; (* fail *) - ^ +Line 3, characters 19-20: +3 | let f ?x y = y in {f};; (* fail *) + ^ Error: This field value has type unit -> unit which is less general than 'a. 'a -> unit |}];; @@ -1363,16 +1436,16 @@ let {foo} = (raise Exit : t);; type s = A of int let (A x) = (raise Exit : s);; [%%expect {| -Exception: Stdlib.Pervasives.Exit. +Exception: Stdlib.Exit. |}];; (* PR#5224 *) type 'x t = < f : 'y. 'y t >;; [%%expect {| -Line _, characters 0-28: - type 'x t = < f : 'y. 'y t >;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 0-28: +1 | type 'x t = < f : 'y. 'y t >;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In the definition of t, type 'y t should be 'x t |}];; @@ -1414,9 +1487,9 @@ val n : < m : 'x. [< `Foo of 'x ] -> 'x > = let (n : < m : 'a. [< `Foo of int] -> 'a >) = object method m : 'x. [< `Foo of 'x] -> 'x = fun x -> assert false end;; [%%expect {| -Line _, characters 2-72: - object method m : 'x. [< `Foo of 'x] -> 'x = fun x -> assert false end;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 2-72: +2 | object method m : 'x. [< `Foo of 'x] -> 'x = fun x -> assert false end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This expression has type < m : 'x. [< `Foo of 'x ] -> 'x > but an expression was expected of type < m : 'a. [< `Foo of int ] -> 'a > @@ -1426,9 +1499,9 @@ Error: This expression has type < m : 'x. [< `Foo of 'x ] -> 'x > let (n : 'b -> < m : 'a . ([< `Foo of int] as 'b) -> 'a >) = fun x -> object method m : 'x. [< `Foo of 'x] -> 'x = fun x -> assert false end;; [%%expect {| -Line _, characters 2-72: - object method m : 'x. [< `Foo of 'x] -> 'x = fun x -> assert false end;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 2, characters 2-72: +2 | object method m : 'x. [< `Foo of 'x] -> 'x = fun x -> assert false end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This expression has type < m : 'x. [< `Foo of 'x ] -> 'x > but an expression was expected of type < m : 'a. [< `Foo of int ] -> 'a > @@ -1440,9 +1513,9 @@ let f b (x: 'x) = let module M = struct type t = A end in if b then x else M.A;; [%%expect {| -Line _, characters 19-22: - if b then x else M.A;; - ^^^ +Line 3, characters 19-22: +3 | if b then x else M.A;; + ^^^ Error: This expression has type M.t but an expression was expected of type 'x The type constructor M.t would escape its scope |}];; @@ -1534,20 +1607,19 @@ type h = < m : int; n : string; x : string; y : int > type t = and g = [%%expect{| -Line _, characters 10-11: - type t = - ^ -Error: The type constructor g -is not yet completely defined +Line 1, characters 10-11: +1 | type t = + ^ +Error: The type constructor g is not yet completely defined |}] type t = int type g = [%%expect{| type t = int -Line _, characters 10-11: - type g = - ^ +Line 2, characters 10-11: +2 | type g = + ^ Error: The type int is not an object type |}] @@ -1586,9 +1658,9 @@ type r2 = < a : int > type gg = float; a:int> [%%expect{| -Line _, characters 27-30: - type gg = float; a:int> - ^^^ +Line 1, characters 27-30: +1 | type gg = float; a:int> + ^^^ Error: Method 'a' has type int, which should be int -> float |}] @@ -1596,9 +1668,9 @@ type t = type g = [%%expect{| type t = < a : int; b : string > -Line _, characters 19-20: - type g = - ^ +Line 2, characters 19-20: +2 | type g = + ^ Error: Method 'b' has type string, which should be float |}] @@ -1613,9 +1685,9 @@ type t = < f : int > type t = < int #A.t1 > [%%expect{| -Line _, characters 11-20: - type t = < int #A.t1 > - ^^^^^^^^^ +Line 1, characters 11-20: +1 | type t = < int #A.t1 > + ^^^^^^^^^ Error: Illegal open object type |}] @@ -1650,3 +1722,15 @@ module M : val i : 'a -> 'a end |}] + +(* #8550 *) +class ['a] r = let r : 'a = ref [] in object method get = r end;; +[%%expect{| +Line 1, characters 0-63: +1 | class ['a] r = let r : 'a = ref [] in object method get = r end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: The type of this class, + class ['a] r : + object constraint 'a = '_weak2 list ref method get : 'a end, + contains type variables that cannot be generalized +|}] diff --git a/testsuite/tests/typing-polyvariants-bugs-2/pr3918c.compilers.reference b/testsuite/tests/typing-polyvariants-bugs-2/pr3918c.compilers.reference index bd8cef8b..411578cf 100644 --- a/testsuite/tests/typing-polyvariants-bugs-2/pr3918c.compilers.reference +++ b/testsuite/tests/typing-polyvariants-bugs-2/pr3918c.compilers.reference @@ -1,4 +1,6 @@ File "pr3918c.ml", line 24, characters 11-12: +24 | let f x = (x : 'a vlist :> 'b vlist) + ^ Error: This expression has type 'b Pr3918b.vlist = 'a but an expression was expected of type 'b Pr3918b.vlist - The type variable 'a occurs inside 'a + The type variable 'a occurs inside ('d * 'c) Pr3918a.voption as 'c diff --git a/testsuite/tests/typing-polyvariants-bugs/pr5057a_bad.compilers.reference b/testsuite/tests/typing-polyvariants-bugs/pr5057a_bad.compilers.reference index 67200052..0dd205a3 100644 --- a/testsuite/tests/typing-polyvariants-bugs/pr5057a_bad.compilers.reference +++ b/testsuite/tests/typing-polyvariants-bugs/pr5057a_bad.compilers.reference @@ -1,4 +1,6 @@ File "pr5057a_bad.ml", line 14, characters 48-49: +14 | let _ = match flag with `A -> T.mem | `B r -> r in + ^ Error: This expression has type 'a but an expression was expected of type int -> T.t -> bool The type constructor T.t would escape its scope diff --git a/testsuite/tests/typing-polyvariants-bugs/pr7824.ml b/testsuite/tests/typing-polyvariants-bugs/pr7824.ml index 2592b4b5..59ffd96f 100644 --- a/testsuite/tests/typing-polyvariants-bugs/pr7824.ml +++ b/testsuite/tests/typing-polyvariants-bugs/pr7824.ml @@ -37,9 +37,9 @@ let f x = | _::_ -> (x :> [`A | `C] Element.t) ;; [%%expect{| -Line _, characters 2-54: - ..match [] with - | _::_ -> (x :> [`A | `C] Element.t) +Line 4, characters 2-54: +4 | ..match [] with +5 | | _::_ -> (x :> [`A | `C] Element.t) Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: [] diff --git a/testsuite/tests/typing-private-bugs/pr5026_bad.compilers.reference b/testsuite/tests/typing-private-bugs/pr5026_bad.compilers.reference index 906ef1cc..3f23c33f 100644 --- a/testsuite/tests/typing-private-bugs/pr5026_bad.compilers.reference +++ b/testsuite/tests/typing-private-bugs/pr5026_bad.compilers.reference @@ -1,3 +1,5 @@ File "pr5026_bad.ml", line 11, characters 0-36: +11 | type -'typing wrapped = private sexp + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The definition of wrapped contains a cycle: sexp diff --git a/testsuite/tests/typing-private/private.compilers.principal.reference b/testsuite/tests/typing-private/private.compilers.principal.reference index e8adbea9..ee60a677 100644 --- a/testsuite/tests/typing-private/private.compilers.principal.reference +++ b/testsuite/tests/typing-private/private.compilers.principal.reference @@ -1,8 +1,8 @@ module Foobar : sig type t = private int end module F0 : sig type t = private int end -Characters 21-22: - let f (x : F0.t) = (x : Foobar.t);; (* fails *) - ^ +Line 2, characters 20-21: +2 | let f (x : F0.t) = (x : Foobar.t);; (* fails *) + ^ Error: This expression has type F0.t but an expression was expected of type Foobar.t module F = Foobar @@ -10,17 +10,17 @@ val f : F.t -> Foobar.t = module M : sig type t = < m : int > end module M1 : sig type t = private < m : int; .. > end module M2 : sig type t = private < m : int; .. > end -Characters 19-20: - fun (x : M1.t) -> (x : M2.t);; (* fails *) - ^ +Line 1, characters 19-20: +1 | fun (x : M1.t) -> (x : M2.t);; (* fails *) + ^ Error: This expression has type M1.t but an expression was expected of type M2.t module M3 : sig type t = private M1.t end - : M3.t -> M1.t = - : M3.t -> M.t = -Characters 44-46: - module M4 : sig type t = private M3.t end = M2;; (* fails *) - ^^ +Line 1, characters 44-46: +1 | module M4 : sig type t = private M3.t end = M2;; (* fails *) + ^^ Error: Signature mismatch: Modules do not match: sig type t = M2.t end @@ -30,9 +30,9 @@ Error: Signature mismatch: type t = M2.t is not included in type t = private M3.t -Characters 44-45: - module M4 : sig type t = private M3.t end = M;; (* fails *) - ^ +Line 1, characters 44-45: +1 | module M4 : sig type t = private M3.t end = M;; (* fails *) + ^ Error: Signature mismatch: Modules do not match: sig type t = < m : int > end @@ -42,9 +42,9 @@ Error: Signature mismatch: type t = < m : int > is not included in type t = private M3.t -Characters 44-46: - module M4 : sig type t = private M3.t end = M1;; (* might be ok *) - ^^ +Line 1, characters 44-46: +1 | module M4 : sig type t = private M3.t end = M1;; (* might be ok *) + ^^ Error: Signature mismatch: Modules do not match: sig type t = M1.t end @@ -55,9 +55,9 @@ Error: Signature mismatch: is not included in type t = private M3.t module M5 : sig type t = private M1.t end -Characters 53-55: - module M6 : sig type t = private < n:int; .. > end = M1;; (* fails *) - ^^ +Line 1, characters 53-55: +1 | module M6 : sig type t = private < n:int; .. > end = M1;; (* fails *) + ^^ Error: Signature mismatch: Modules do not match: sig type t = M1.t end @@ -67,9 +67,9 @@ Error: Signature mismatch: type t = M1.t is not included in type t = private < n : int; .. > -Characters 69-118: - struct type t = int let f (x : int) = (x : t) end;; (* must fail *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 2-51: +3 | struct type t = int let f (x : int) = (x : t) end;; (* must fail *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Signature mismatch: Modules do not match: sig type t = int val f : int -> t end @@ -83,9 +83,9 @@ module M : sig type t = private T of int val mk : int -> t end module M1 : sig type t = M.t val mk : int -> t end module M2 : sig type t = M.t val mk : int -> t end module M3 : sig type t = M.t val mk : int -> t end -Characters 21-44: - type t = M.t = T of int - ^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 4-27: +3 | type t = M.t = T of int + ^^^^^^^^^^^^^^^^^^^^^^^ Error: This variant or record definition does not match that of type M.t A private type would be revealed. module M5 : sig type t = M.t = private T of int val mk : int -> t end @@ -99,22 +99,20 @@ module Test : sig type t = private A end module Test2 : sig type t = Test.t = private A end val f : Test.t -> Test2.t = val f : Test2.t -> unit = -Characters 8-15: - let a = Test2.A;; (* fail *) - ^^^^^^^ +Line 1, characters 8-15: +1 | let a = Test2.A;; (* fail *) + ^^^^^^^ Error: Cannot create values of the private type Test2.t -Characters 148-171: - module Test2 : module type of Test with type t = private Test.t = Test;; - ^^^^^^^^^^^^^^^^^^^^^^^ -Warning 3: deprecated: spurious use of private +Line 3, characters 40-63: +3 | module Test2 : module type of Test with type t = private Test.t = Test;; + ^^^^^^^^^^^^^^^^^^^^^^^ +Alert deprecated: spurious use of private module Test2 : sig type t = Test.t = private A end type t = private < x : int; .. > type t = private < x : int; .. > type t = private < x : int > type t = private < x : int > -Characters -1--1: - type 'a t = private < x : int; .. > as 'a;; - +Line 1: Error: Type declarations do not match: type 'a t = private 'a constraint 'a = < x : int; .. > is not included in diff --git a/testsuite/tests/typing-private/private.compilers.reference b/testsuite/tests/typing-private/private.compilers.reference index 17a936b5..bead385a 100644 --- a/testsuite/tests/typing-private/private.compilers.reference +++ b/testsuite/tests/typing-private/private.compilers.reference @@ -1,8 +1,8 @@ module Foobar : sig type t = private int end module F0 : sig type t = private int end -Characters 21-22: - let f (x : F0.t) = (x : Foobar.t);; (* fails *) - ^ +Line 2, characters 20-21: +2 | let f (x : F0.t) = (x : Foobar.t);; (* fails *) + ^ Error: This expression has type F0.t but an expression was expected of type Foobar.t module F = Foobar @@ -10,17 +10,17 @@ val f : F.t -> Foobar.t = module M : sig type t = < m : int > end module M1 : sig type t = private < m : int; .. > end module M2 : sig type t = private < m : int; .. > end -Characters 19-20: - fun (x : M1.t) -> (x : M2.t);; (* fails *) - ^ +Line 1, characters 19-20: +1 | fun (x : M1.t) -> (x : M2.t);; (* fails *) + ^ Error: This expression has type M1.t but an expression was expected of type M2.t module M3 : sig type t = private M1.t end - : M3.t -> M1.t = - : M3.t -> M.t = -Characters 44-46: - module M4 : sig type t = private M3.t end = M2;; (* fails *) - ^^ +Line 1, characters 44-46: +1 | module M4 : sig type t = private M3.t end = M2;; (* fails *) + ^^ Error: Signature mismatch: Modules do not match: sig type t = M2.t end @@ -30,9 +30,9 @@ Error: Signature mismatch: type t = M2.t is not included in type t = private M3.t -Characters 44-45: - module M4 : sig type t = private M3.t end = M;; (* fails *) - ^ +Line 1, characters 44-45: +1 | module M4 : sig type t = private M3.t end = M;; (* fails *) + ^ Error: Signature mismatch: Modules do not match: sig type t = < m : int > end @@ -42,9 +42,9 @@ Error: Signature mismatch: type t = < m : int > is not included in type t = private M3.t -Characters 44-46: - module M4 : sig type t = private M3.t end = M1;; (* might be ok *) - ^^ +Line 1, characters 44-46: +1 | module M4 : sig type t = private M3.t end = M1;; (* might be ok *) + ^^ Error: Signature mismatch: Modules do not match: sig type t = M1.t end @@ -55,9 +55,9 @@ Error: Signature mismatch: is not included in type t = private M3.t module M5 : sig type t = private M1.t end -Characters 53-55: - module M6 : sig type t = private < n:int; .. > end = M1;; (* fails *) - ^^ +Line 1, characters 53-55: +1 | module M6 : sig type t = private < n:int; .. > end = M1;; (* fails *) + ^^ Error: Signature mismatch: Modules do not match: sig type t = M1.t end @@ -67,9 +67,9 @@ Error: Signature mismatch: type t = M1.t is not included in type t = private < n : int; .. > -Characters 69-118: - struct type t = int let f (x : int) = (x : t) end;; (* must fail *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 2-51: +3 | struct type t = int let f (x : int) = (x : t) end;; (* must fail *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Signature mismatch: Modules do not match: sig type t = int val f : int -> t end @@ -83,9 +83,9 @@ module M : sig type t = private T of int val mk : int -> t end module M1 : sig type t = M.t val mk : int -> t end module M2 : sig type t = M.t val mk : int -> t end module M3 : sig type t = M.t val mk : int -> t end -Characters 21-44: - type t = M.t = T of int - ^^^^^^^^^^^^^^^^^^^^^^^ +Line 3, characters 4-27: +3 | type t = M.t = T of int + ^^^^^^^^^^^^^^^^^^^^^^^ Error: This variant or record definition does not match that of type M.t A private type would be revealed. module M5 : sig type t = M.t = private T of int val mk : int -> t end @@ -99,22 +99,20 @@ module Test : sig type t = private A end module Test2 : sig type t = Test.t = private A end val f : Test.t -> Test2.t = val f : Test2.t -> unit = -Characters 8-15: - let a = Test2.A;; (* fail *) - ^^^^^^^ +Line 1, characters 8-15: +1 | let a = Test2.A;; (* fail *) + ^^^^^^^ Error: Cannot create values of the private type Test2.t -Characters 148-171: - module Test2 : module type of Test with type t = private Test.t = Test;; - ^^^^^^^^^^^^^^^^^^^^^^^ -Warning 3: deprecated: spurious use of private +Line 3, characters 40-63: +3 | module Test2 : module type of Test with type t = private Test.t = Test;; + ^^^^^^^^^^^^^^^^^^^^^^^ +Alert deprecated: spurious use of private module Test2 : sig type t = Test.t = private A end type t = private < x : int; .. > type t = private < x : int; .. > type t = private < x : int > type t = private < x : int > -Characters -1--1: - type 'a t = private < x : int; .. > as 'a;; - +Line 1: Error: Type declarations do not match: type 'a t = private < x : int; .. > constraint 'a = 'a t is not included in diff --git a/testsuite/tests/typing-private/private.ml b/testsuite/tests/typing-private/private.ml index bc559708..156e9ba5 100644 --- a/testsuite/tests/typing-private/private.ml +++ b/testsuite/tests/typing-private/private.ml @@ -120,4 +120,3 @@ type 'a t = private 'a constraint 'a = < x : int; .. >;; (* PR#7437 *) type t = [` Closed ];; type nonrec t = private [> t];; - diff --git a/testsuite/tests/typing-recmod/gpr1626.ml b/testsuite/tests/typing-recmod/gpr1626.ml new file mode 100644 index 00000000..ab956355 --- /dev/null +++ b/testsuite/tests/typing-recmod/gpr1626.ml @@ -0,0 +1,16 @@ +(* TEST + * expect +*) + +module type S = sig module M : sig end module N = M end;; +[%%expect{| +module type S = sig module M : sig end module N = M end +|}];; + +module rec M : S with module M := M = M;; +[%%expect{| +Line 1, characters 34-35: +1 | module rec M : S with module M := M = M;; + ^ +Error: Illegal recursive module reference +|}];; diff --git a/testsuite/tests/typing-recmod/ocamltests b/testsuite/tests/typing-recmod/ocamltests index 5429e9d1..23289273 100644 --- a/testsuite/tests/typing-recmod/ocamltests +++ b/testsuite/tests/typing-recmod/ocamltests @@ -16,7 +16,7 @@ t15bad.ml t16ok.ml t17ok.ml t18ok.ml -t19ok.ml t20ok.ml t21ok.ml t22ok.ml +gpr1626.ml diff --git a/testsuite/tests/typing-recmod/t01bad.compilers.reference b/testsuite/tests/typing-recmod/t01bad.compilers.reference index d40baa5c..4601e424 100644 --- a/testsuite/tests/typing-recmod/t01bad.compilers.reference +++ b/testsuite/tests/typing-recmod/t01bad.compilers.reference @@ -1,2 +1,4 @@ File "t01bad.ml", line 10, characters 15-35: +10 | module rec A : sig type t = A.t end = struct type t = A.t end;; + ^^^^^^^^^^^^^^^^^^^^ Error: The type abbreviation A.t is cyclic diff --git a/testsuite/tests/typing-recmod/t02bad.compilers.reference b/testsuite/tests/typing-recmod/t02bad.compilers.reference index bc5f0d57..5236cc2c 100644 --- a/testsuite/tests/typing-recmod/t02bad.compilers.reference +++ b/testsuite/tests/typing-recmod/t02bad.compilers.reference @@ -1,3 +1,5 @@ File "t02bad.ml", line 10, characters 15-35: +10 | module rec A : sig type t = B.t end = struct type t = B.t end + ^^^^^^^^^^^^^^^^^^^^ Error: The definition of A.t contains a cycle: B.t diff --git a/testsuite/tests/typing-recmod/t04bad.compilers.reference b/testsuite/tests/typing-recmod/t04bad.compilers.reference index e8924181..9c6f0a26 100644 --- a/testsuite/tests/typing-recmod/t04bad.compilers.reference +++ b/testsuite/tests/typing-recmod/t04bad.compilers.reference @@ -1,3 +1,5 @@ File "t04bad.ml", line 10, characters 15-41: +10 | module rec A : sig type t = int * A.t end = struct type t = int * A.t end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The definition of A.t contains a cycle: int * A.t diff --git a/testsuite/tests/typing-recmod/t05bad.compilers.reference b/testsuite/tests/typing-recmod/t05bad.compilers.reference index 7bbe96d3..f94582ae 100644 --- a/testsuite/tests/typing-recmod/t05bad.compilers.reference +++ b/testsuite/tests/typing-recmod/t05bad.compilers.reference @@ -1,3 +1,5 @@ File "t05bad.ml", line 10, characters 15-42: +10 | module rec A : sig type t = B.t -> int end = struct type t = B.t -> int end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The definition of A.t contains a cycle: B.t -> int diff --git a/testsuite/tests/typing-recmod/t07bad.compilers.reference b/testsuite/tests/typing-recmod/t07bad.compilers.reference index 78b4bcf2..2fa8fc53 100644 --- a/testsuite/tests/typing-recmod/t07bad.compilers.reference +++ b/testsuite/tests/typing-recmod/t07bad.compilers.reference @@ -1,2 +1,4 @@ File "t07bad.ml", line 10, characters 15-51: +10 | module rec A : sig type 'a t = end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In the definition of A.t, type 'a list A.t should be 'a A.t diff --git a/testsuite/tests/typing-recmod/t08bad.compilers.reference b/testsuite/tests/typing-recmod/t08bad.compilers.reference index 14ab2141..2a8a0fdd 100644 --- a/testsuite/tests/typing-recmod/t08bad.compilers.reference +++ b/testsuite/tests/typing-recmod/t08bad.compilers.reference @@ -1,2 +1,4 @@ File "t08bad.ml", line 10, characters 15-68: +10 | module rec A : sig type 'a t = end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In the definition of B.t, type 'a array A.t should be 'a A.t diff --git a/testsuite/tests/typing-recmod/t09bad.compilers.reference b/testsuite/tests/typing-recmod/t09bad.compilers.reference index 28b6547f..26521d10 100644 --- a/testsuite/tests/typing-recmod/t09bad.compilers.reference +++ b/testsuite/tests/typing-recmod/t09bad.compilers.reference @@ -1,2 +1,4 @@ File "t09bad.ml", line 10, characters 15-41: +10 | module rec A : sig type 'a t = 'a B.t end + ^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In the definition of B.t, type 'a array A.t should be 'a A.t diff --git a/testsuite/tests/typing-recmod/t11bad.compilers.reference b/testsuite/tests/typing-recmod/t11bad.compilers.reference index a5371e89..bdde1398 100644 --- a/testsuite/tests/typing-recmod/t11bad.compilers.reference +++ b/testsuite/tests/typing-recmod/t11bad.compilers.reference @@ -1,2 +1,4 @@ File "t11bad.ml", line 12, characters 15-52: +12 | and B : sig type 'a t = end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In the definition of B.t, type 'a array B.t should be 'a B.t diff --git a/testsuite/tests/typing-recmod/t12bad.compilers.reference b/testsuite/tests/typing-recmod/t12bad.compilers.reference index d7705c7d..b83fdc6d 100644 --- a/testsuite/tests/typing-recmod/t12bad.compilers.reference +++ b/testsuite/tests/typing-recmod/t12bad.compilers.reference @@ -1,2 +1,7 @@ File "t12bad.ml", line 11, characters 4-101: +11 | ....sig +12 | class ['a] c : 'a -> object +13 | method map : ('a -> 'b) -> 'b M.c +14 | end +15 | end Error: In the definition of M.c, type 'b M.c should be 'a M.c diff --git a/testsuite/tests/typing-recmod/t14bad.compilers.reference b/testsuite/tests/typing-recmod/t14bad.compilers.reference index 6f3ce696..260384b0 100644 --- a/testsuite/tests/typing-recmod/t14bad.compilers.reference +++ b/testsuite/tests/typing-recmod/t14bad.compilers.reference @@ -1,3 +1,5 @@ -File "t14bad.ml", line 23, characters 17-37: +File "t14bad.ml", line 23, characters 17-39: +23 | module rec U : T with type D.t = U'.t = U + ^^^^^^^^^^^^^^^^^^^^^^ Error: The definition of U.D.t contains a cycle: U'.t diff --git a/testsuite/tests/typing-recmod/t14bad.ml b/testsuite/tests/typing-recmod/t14bad.ml index cd98ef3f..4ef06167 100644 --- a/testsuite/tests/typing-recmod/t14bad.ml +++ b/testsuite/tests/typing-recmod/t14bad.ml @@ -20,6 +20,6 @@ module PR_4261 = struct type t = D.t end - module rec U : T with module D = U' = U + module rec U : T with type D.t = U'.t = U and U' : S with type t = U'.t = U end;; diff --git a/testsuite/tests/typing-recmod/t15bad.compilers.reference b/testsuite/tests/typing-recmod/t15bad.compilers.reference index 009248cb..73706a57 100644 --- a/testsuite/tests/typing-recmod/t15bad.compilers.reference +++ b/testsuite/tests/typing-recmod/t15bad.compilers.reference @@ -1,2 +1,4 @@ File "t15bad.ml", line 11, characters 15-35: +11 | module rec M : S' with type t = M.t = struct type t = M.t end;; + ^^^^^^^^^^^^^^^^^^^^ Error: The type abbreviation M.t is cyclic diff --git a/testsuite/tests/typing-recmod/t19ok.ml b/testsuite/tests/typing-recmod/t19ok.ml deleted file mode 100644 index 91666d73..00000000 --- a/testsuite/tests/typing-recmod/t19ok.ml +++ /dev/null @@ -1,22 +0,0 @@ -(* TEST -flags = " -w a " -* setup-ocamlc.byte-build-env -** ocamlc.byte -*** check-ocamlc.byte-output -*) - -(* PR 4758, PR 4266 *) - -module PR_4758 = struct - module type S = sig end - module type Mod = sig - module Other : S - end - module rec A : S = struct end - and C : sig include Mod with module Other = A end = struct - module Other = A - end - module C' = C (* check that we can take an alias *) - module F(X:sig end) = struct type t end - let f (x : F(C).t) = (x : F(C').t) -end diff --git a/testsuite/tests/typing-recmod/t22ok.ml b/testsuite/tests/typing-recmod/t22ok.ml index bfc119f4..16e9cbcf 100644 --- a/testsuite/tests/typing-recmod/t22ok.ml +++ b/testsuite/tests/typing-recmod/t22ok.ml @@ -24,7 +24,7 @@ module rec A type t = Leaf of int | Node of ASet.t let compare x y = match (x,y) with - (Leaf i, Leaf j) -> Pervasives.compare i j + (Leaf i, Leaf j) -> Stdlib.compare i j | (Leaf i, Node t) -> -1 | (Node s, Leaf j) -> 1 | (Node s, Node t) -> ASet.compare s t diff --git a/testsuite/tests/typing-recordarg/recordarg.ocaml.reference b/testsuite/tests/typing-recordarg/recordarg.ocaml.reference index 75537f00..c6a5fb53 100644 --- a/testsuite/tests/typing-recordarg/recordarg.ocaml.reference +++ b/testsuite/tests/typing-recordarg/recordarg.ocaml.reference @@ -1,14 +1,14 @@ type t = A of { x : int; mutable y : int; } -Characters 14-15: - let f (A r) = r;; (* -> escape *) - ^ +Line 1, characters 14-15: +1 | let f (A r) = r;; (* -> escape *) + ^ Error: This form is not allowed as the type of the inlined record could escape. val f : t -> int = val f : int -> t = val f : t -> t = -Characters 14-15: - let f () = A {a = 1};; (* customized error message *) - ^ +Line 1, characters 14-15: +1 | let f () = A {a = 1};; (* customized error message *) + ^ Error: The field a is not part of the record argument for the t.A constructor val f : unit -> t = type _ t = A : { x : 'a; y : 'b; } -> 'a t @@ -25,39 +25,31 @@ module N : exception Foo of { x : int; } end module type S = sig exception A of { x : int; } end -Characters 65-74: - module A = (val X.x) - ^^^^^^^^^ +Line 3, characters 13-22: +3 | module A = (val X.x) + ^^^^^^^^^ Error: This expression creates fresh types. It is not allowed inside applicative functors. -Characters 61-62: - exception A of {x : string} - ^ +Line 5, characters 2-29: +5 | exception A of {x : string} + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Multiple definition of the extension constructor name A. Names must be unique in a given structure or signature. -Characters 58-59: - exception A of {x : string} - ^ +Line 4, characters 2-29: +4 | exception A of {x : string} + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Multiple definition of the extension constructor name A. Names must be unique in a given structure or signature. module M1 : sig exception A of { x : int; } end -Characters 34-44: - include M1 - ^^^^^^^^^^ -Error: Multiple definition of the extension constructor name A. - Names must be unique in a given structure or signature. +module M : sig exception A of { x : int; } end module type S1 = sig exception A of { x : int; } end -Characters 36-46: - include S1 - ^^^^^^^^^^ -Error: Multiple definition of the extension constructor name A. - Names must be unique in a given structure or signature. +module type S = sig exception A of { x : int; } end module M : sig exception A of { x : int; } end module X1 : sig type t = .. end module X2 : sig type t = .. end -Characters 62-63: - type X2.t += A of {x: int} - ^ +Line 3, characters 15-28: +3 | type X2.t += A of {x: int} + ^^^^^^^^^^^^^ Error: Multiple definition of the extension constructor name A. Names must be unique in a given structure or signature. type _ c = C : [ `A ] c diff --git a/testsuite/tests/typing-rectypes-bugs/pr5343_bad.compilers.reference b/testsuite/tests/typing-rectypes-bugs/pr5343_bad.compilers.reference index 71a12595..9fc704a3 100644 --- a/testsuite/tests/typing-rectypes-bugs/pr5343_bad.compilers.reference +++ b/testsuite/tests/typing-rectypes-bugs/pr5343_bad.compilers.reference @@ -1,2 +1,4 @@ File "pr5343_bad.ml", line 11, characters 2-14: +11 | type u = u t and v = v t + ^^^^^^^^^^^^ Error: The type abbreviation u is cyclic diff --git a/testsuite/tests/typing-rectypes-bugs/pr6174_bad.compilers.reference b/testsuite/tests/typing-rectypes-bugs/pr6174_bad.compilers.reference index 56d8c42f..8559e40c 100644 --- a/testsuite/tests/typing-rectypes-bugs/pr6174_bad.compilers.reference +++ b/testsuite/tests/typing-rectypes-bugs/pr6174_bad.compilers.reference @@ -1,3 +1,5 @@ File "pr6174_bad.ml", line 11, characters 24-25: +11 | fun C k -> k (fun x -> x);; + ^ Error: This expression has type $0 but an expression was expected of type $1 = ($2 -> $1) -> $1 diff --git a/testsuite/tests/typing-rectypes-bugs/pr6870_bad.compilers.reference b/testsuite/tests/typing-rectypes-bugs/pr6870_bad.compilers.reference index c3e1ff63..80fc303e 100644 --- a/testsuite/tests/typing-rectypes-bugs/pr6870_bad.compilers.reference +++ b/testsuite/tests/typing-rectypes-bugs/pr6870_bad.compilers.reference @@ -1,4 +1,6 @@ File "pr6870_bad.ml", line 10, characters 38-50: +10 | module Fix (T : T) = struct type r = ('r T.t as 'r) end + ^^^^^^^^^^^^ Error: This alias is bound to type 'a T.t but is used as an instance of type 'a The type variable 'a occurs inside 'a T.t diff --git a/testsuite/tests/typing-safe-linking/b_bad.compilers.reference b/testsuite/tests/typing-safe-linking/b_bad.compilers.reference index 818f3a0a..46124ba4 100644 --- a/testsuite/tests/typing-safe-linking/b_bad.compilers.reference +++ b/testsuite/tests/typing-safe-linking/b_bad.compilers.reference @@ -1,6 +1,10 @@ File "b_bad.ml", line 13, characters 29-66: +13 | .............................function +14 | A.X s -> print_endline s Error (warning 8): this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Y -File "b_bad.ml", line 17, characters 11-14: +File "b_bad.ml", line 18, characters 11-14: +18 | let () = f A.y + ^^^ Error: Unbound value A.y diff --git a/testsuite/tests/typing-safe-linking/b_bad.ml b/testsuite/tests/typing-safe-linking/b_bad.ml index 2fc7d558..4dc6e6b4 100644 --- a/testsuite/tests/typing-safe-linking/b_bad.ml +++ b/testsuite/tests/typing-safe-linking/b_bad.ml @@ -13,5 +13,6 @@ ocamlc_byte_exit_status = "2" let f : string A.t -> unit = function A.X s -> print_endline s -(* It is important that the line below is the last line of the file (see Makefile) *) +(* It is important that the line below is the last line of the file + (see Makefile) *) let () = f A.y diff --git a/testsuite/tests/typing-shadowing-of-pervasives-submodules/ocamltests b/testsuite/tests/typing-shadowing-of-pervasives-submodules/ocamltests index 2ac9cbae..658495ef 100644 --- a/testsuite/tests/typing-shadowing-of-pervasives-submodules/ocamltests +++ b/testsuite/tests/typing-shadowing-of-pervasives-submodules/ocamltests @@ -1 +1,2 @@ redefine_largefile.ml +redefine_largefile_top.ml diff --git a/testsuite/tests/typing-shadowing-of-pervasives-submodules/redefine_largefile_top.compilers.reference b/testsuite/tests/typing-shadowing-of-pervasives-submodules/redefine_largefile_top.compilers.reference new file mode 100644 index 00000000..cd257cfd --- /dev/null +++ b/testsuite/tests/typing-shadowing-of-pervasives-submodules/redefine_largefile_top.compilers.reference @@ -0,0 +1,2 @@ +Hello, world!- : unit = () + diff --git a/testsuite/tests/typing-shadowing-of-pervasives-submodules/redefine_largefile_top.ml b/testsuite/tests/typing-shadowing-of-pervasives-submodules/redefine_largefile_top.ml new file mode 100644 index 00000000..2b4ee473 --- /dev/null +++ b/testsuite/tests/typing-shadowing-of-pervasives-submodules/redefine_largefile_top.ml @@ -0,0 +1,16 @@ +(* TEST + files = "largeFile.ml" + * setup-ocaml-build-env + ** ocamlc.byte + compile_only = "true" + all_modules = "largeFile.ml" + *** script + script = "mkdir -p inc" + **** script + script = "mv largeFile.cmi largeFile.cmo inc/" + ***** ocaml + ****** check-ocaml-output +*) +#directory "inc";; +#load "largeFile.cmo";; +print_string LargeFile.message;; diff --git a/testsuite/tests/typing-short-paths/gpr1223.ml b/testsuite/tests/typing-short-paths/gpr1223.ml index a8ac8b57..9e66dfb9 100644 --- a/testsuite/tests/typing-short-paths/gpr1223.ml +++ b/testsuite/tests/typing-short-paths/gpr1223.ml @@ -1,5 +1,5 @@ (* TEST - flags = " -short-paths " + flags = " -short-paths " modules = "gpr1223_foo.mli gpr1223_bar.mli" * toplevel *) diff --git a/testsuite/tests/typing-short-paths/pr5918.compilers.reference b/testsuite/tests/typing-short-paths/pr5918.compilers.reference index 2ca36b02..268cb427 100644 --- a/testsuite/tests/typing-short-paths/pr5918.compilers.reference +++ b/testsuite/tests/typing-short-paths/pr5918.compilers.reference @@ -1,5 +1,5 @@ -Characters 136-146: - let _ = { a = () } - ^^^^^^^^^^ +Line 10, characters 9-19: +10 | let _ = { a = () } + ^^^^^^^^^^ Error: Some record fields are undefined: b diff --git a/testsuite/tests/typing-short-paths/pr7543.compilers.reference b/testsuite/tests/typing-short-paths/pr7543.compilers.reference index 6b52e2ac..ee55eef1 100644 --- a/testsuite/tests/typing-short-paths/pr7543.compilers.reference +++ b/testsuite/tests/typing-short-paths/pr7543.compilers.reference @@ -1,9 +1,9 @@ module type S = sig type t end module N : sig type 'a t = 'a end val f : (module S with type t = unit) -> unit = -Characters 19-20: - let () = f (module N);; - ^ +Line 1, characters 19-20: +1 | let () = f (module N);; + ^ Error: Signature mismatch: Modules do not match: sig type 'a t = 'a end diff --git a/testsuite/tests/typing-short-paths/short-paths.compilers.reference b/testsuite/tests/typing-short-paths/short-paths.compilers.reference index 7b505609..47f15b3d 100644 --- a/testsuite/tests/typing-short-paths/short-paths.compilers.reference +++ b/testsuite/tests/typing-short-paths/short-paths.compilers.reference @@ -61,9 +61,9 @@ module Core : module Std : sig module Int = Int end end val x : 'a Int.Map.t = -Characters 8-9: - let y = x + x ;; - ^ +Line 1, characters 8-9: +1 | let y = x + x ;; + ^ Error: This expression has type 'a Int.Map.t but an expression was expected of type int module M : sig type t = A type u = C end @@ -85,9 +85,9 @@ type t1 = B module N2 : sig type u = v and v = N1.v end module type PR6566 = sig type t = string end module PR6566 : sig type t = int end -Characters 26-32: - module PR6566' : PR6566 = PR6566;; - ^^^^^^ +Line 1, characters 26-32: +1 | module PR6566' : PR6566 = PR6566;; + ^^^^^^ Error: Signature mismatch: Modules do not match: sig type t = int end is not included in PR6566 Type declarations do not match: diff --git a/testsuite/tests/typing-signatures/pr6672.ocaml.reference b/testsuite/tests/typing-signatures/pr6672.ocaml.reference index 17e9b1ed..d99090fc 100644 --- a/testsuite/tests/typing-signatures/pr6672.ocaml.reference +++ b/testsuite/tests/typing-signatures/pr6672.ocaml.reference @@ -1,8 +1,8 @@ module type S = sig type 'a t end module type T = sig type 'a t = 'a list end -Characters 23-43: - module type T = S with type -'a t = 'a list;; - ^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 23-43: +1 | module type T = S with type -'a t = 'a list;; + ^^^^^^^^^^^^^^^^^^^^ Error: In this definition, expected parameter variances are not satisfied. The 1st type parameter was expected to be contravariant, but it is injective covariant. diff --git a/testsuite/tests/typing-sigsubst/mpr7852.mli b/testsuite/tests/typing-sigsubst/mpr7852.mli new file mode 100644 index 00000000..28a8d855 --- /dev/null +++ b/testsuite/tests/typing-sigsubst/mpr7852.mli @@ -0,0 +1,12 @@ +module M : sig + type t + val foo : t -> int + val bar : t -> int +end + +module N : sig + type outer + type t + val foo : t -> outer + val bar : t -> outer +end with type outer := int diff --git a/testsuite/tests/typing-sigsubst/ocamltests b/testsuite/tests/typing-sigsubst/ocamltests index 278c5eef..ca30f86e 100644 --- a/testsuite/tests/typing-sigsubst/ocamltests +++ b/testsuite/tests/typing-sigsubst/ocamltests @@ -1 +1,4 @@ +sig_local_aliases.ml +sig_local_aliases_syntax_errors.ml sigsubst.ml +test_locations.ml diff --git a/testsuite/tests/typing-sigsubst/sig_local_aliases.ml b/testsuite/tests/typing-sigsubst/sig_local_aliases.ml new file mode 100644 index 00000000..8bae4467 --- /dev/null +++ b/testsuite/tests/typing-sigsubst/sig_local_aliases.ml @@ -0,0 +1,120 @@ +(* TEST + * expect +*) + +module M = struct + type t +end;; +[%%expect{| +module M : sig type t end +|}] + +module type Accepted = sig + type t := int + + type 'a u := 'a list + + type 'a v := (string * 'a) list + + module T := M + + type _ w := T.t + + val f : t u -> char w v +end;; +[%%expect{| +module type Accepted = sig val f : int list -> (string * M.t) list end +|}] + +module F(X : sig type t end) = struct + type t = X.t +end;; +[%%expect{| +module F : functor (X : sig type t end) -> sig type t = X.t end +|}] + +module type Accepted2 = sig + module N := F(M) + + val foo : N.t -> int +end;; +[%%expect{| +module type Accepted2 = sig val foo : F(M).t -> int end +|}] + +module type Reject1 = sig + module M := Funct(M) +end;; +[%%expect{| +Line 2, characters 14-22: +2 | module M := Funct(M) + ^^^^^^^^ +Error: Unbound module Funct +Hint: Did you mean Fun? +|}] + +module type Reject2 = sig + module M := F(N) +end;; +[%%expect{| +Line 2, characters 14-18: +2 | module M := F(N) + ^^^^ +Error: Unbound module N +|}] + +module type Reject3 = sig + type t := u +end;; +[%%expect{| +Line 2, characters 12-13: +2 | type t := u + ^ +Error: Unbound type constructor u +|}] + +module type RejectRec = sig + type t := [ `Foo of t | `Nil ] +end;; +[%%expect{| +Line 2, characters 22-23: +2 | type t := [ `Foo of t | `Nil ] + ^ +Error: Unbound type constructor t +|}] + +module type AcceptAnd = sig + type t := int + and u := int * int +end;; +[%%expect{| +module type AcceptAnd = sig end +|}] + +module type RejectAnd = sig + type t := int + and u := t * int +end;; +[%%expect{| +Line 3, characters 11-12: +3 | and u := t * int + ^ +Error: Unbound type constructor t +|}] + +(** MPR7905, PR2231: + We want to reject invalid right-hand side + before typing the type declaration. +*) +module type Rejected = sig + type cycle = A of cycle + type t := cycle = A of t + (** this type declaration is purposefully erroneous *) +end + +[%%expect{| +Line 3, characters 2-26: +3 | type t := cycle = A of t + ^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Only type synonyms are allowed on the right of := +|}] diff --git a/testsuite/tests/typing-sigsubst/sig_local_aliases_syntax_errors.compilers.reference b/testsuite/tests/typing-sigsubst/sig_local_aliases_syntax_errors.compilers.reference new file mode 100644 index 00000000..860a36bf --- /dev/null +++ b/testsuite/tests/typing-sigsubst/sig_local_aliases_syntax_errors.compilers.reference @@ -0,0 +1,38 @@ +Line 6, characters 2-14: +6 | type t1 := A + ^^^^^^^^^^^^ +Error: Only type synonyms are allowed on the right of := +Line 3, characters 2-24: +3 | type t2 := { x : int } + ^^^^^^^^^^^^^^^^^^^^^^ +Error: Only type synonyms are allowed on the right of := +Line 3, characters 15-18: +3 | module M1 := sig end + ^^^ +Error: Syntax error: module path expected. +module F : functor (X : sig type t end) -> sig type t = X.t end +Line 3, characters 17-23: +3 | module M2 := F(struct type t = int end) + ^^^^^^ +Error: Syntax error: module path expected. +Line 2, characters 7-9: +2 | type t := int;; + ^^ +Error: Syntax error +Line 2, characters 9-11: +2 | module M := List;; + ^^ +Error: Syntax error +Line 4, characters 9-10: +4 | and u3 = char + ^ +Error: Syntax error: 'end' expected +Line 2, characters 24-27: +2 | module type Rejected3 = sig + ^^^ + This 'sig' might be unmatched +Line 3, characters 7-13: +3 | type nonrec t := int + ^^^^^^ +Error: Syntax error: nonrec flag not expected. + diff --git a/testsuite/tests/typing-sigsubst/sig_local_aliases_syntax_errors.ml b/testsuite/tests/typing-sigsubst/sig_local_aliases_syntax_errors.ml new file mode 100644 index 00000000..b387ec6a --- /dev/null +++ b/testsuite/tests/typing-sigsubst/sig_local_aliases_syntax_errors.ml @@ -0,0 +1,36 @@ +(* TEST + * toplevel +*) + +module type Rejected1 = sig + type t1 := A +end;; + +module type Rejected2 = sig + type t2 := { x : int } +end;; + +module type RejectedM1 = sig + module M1 := sig end +end;; + +module F(X : sig type t end) = struct + type t = X.t +end;; + +module type RejectedM2 = sig + module M2 := F(struct type t = int end) +end;; + +type t := int;; + +module M := List;; + +module type Rejected3 = sig + type t3 := int + and u3 = char +end;; + +module type Rejected0 = sig + type nonrec t := int +end;; diff --git a/testsuite/tests/typing-sigsubst/sigsubst.ml b/testsuite/tests/typing-sigsubst/sigsubst.ml index 379bf546..140acb49 100644 --- a/testsuite/tests/typing-sigsubst/sigsubst.ml +++ b/testsuite/tests/typing-sigsubst/sigsubst.ml @@ -4,11 +4,10 @@ module type Printable = sig type t - val print : Format.formatter -> t -> unit + val print : t -> unit end [%%expect {| -module type Printable = - sig type t val print : Format.formatter -> t -> unit end +module type Printable = sig type t val print : t -> unit end |}] module type Comparable = sig type t @@ -22,11 +21,14 @@ module type PrintableComparable = sig include Comparable with type t = t end [%%expect {| -Line _, characters 2-36: - include Comparable with type t = t - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: Multiple definition of the type name t. - Names must be unique in a given structure or signature. +Line 3, characters 2-36: +3 | include Comparable with type t = t + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Illegal shadowing of included type t/97 by t/101 + Line 2, characters 2-19: + Type t/97 came from this include + Line 3, characters 2-23: + The value print has no valid type if t/97 is shadowed |}] module type Sunderscore = sig @@ -45,11 +47,11 @@ module type S0 = sig and M2 : sig type t = int end end with type M.t = int [%%expect {| -Line _, characters 17-115: - .................sig - module rec M : sig type t = M2.t end - and M2 : sig type t = int end - end with type M.t = int +Line 1, characters 17-115: +1 | .................sig +2 | module rec M : sig type t = M2.t end +3 | and M2 : sig type t = int end +4 | end with type M.t = int Error: In this `with' constraint, the new definition of M.t does not match its original definition in the constrained signature: Type declarations do not match: @@ -66,11 +68,7 @@ module type PrintableComparable = sig end [%%expect {| module type PrintableComparable = - sig - type t - val print : Format.formatter -> t -> unit - val compare : t -> t -> int - end + sig type t val print : t -> unit val compare : t -> t -> int end |}] module type PrintableComparable = sig include Printable @@ -78,11 +76,7 @@ module type PrintableComparable = sig end [%%expect {| module type PrintableComparable = - sig - type t - val print : Format.formatter -> t -> unit - val compare : t -> t -> int - end + sig type t val print : t -> unit val compare : t -> t -> int end |}] module type ComparableInt = Comparable with type t := int [%%expect {| @@ -168,19 +162,19 @@ module type S = sig end with type 'a t2 := 'a t * bool [%%expect {| type 'a t constraint 'a = 'b list -Line _, characters 16-142: - ................sig - type 'a t2 constraint 'a = 'b list - type 'a mylist = 'a list - val x : int mylist t2 - end with type 'a t2 := 'a t * bool +Line 2, characters 16-142: +2 | ................sig +3 | type 'a t2 constraint 'a = 'b list +4 | type 'a mylist = 'a list +5 | val x : int mylist t2 +6 | end with type 'a t2 := 'a t * bool Error: Destructive substitutions are not supported for constrained types (other than when replacing a type constructor with a type constructor with the same arguments). |}] -(* Issue where the typer expands an alias, which breaks the typing of the rest - of the signature, but no error is given to the user. *) +(* Issue where the typer weakens an alias, which breaks the typing of the rest + of the signature. (MPR#7723)*) module type S = sig module M1 : sig type t = int end module M2 = M1 @@ -192,13 +186,42 @@ end with type M2.t = int module type S = sig module M1 : sig type t = int end - module M2 : sig type t = int end + module M2 = M1 module M3 : sig module M = M2 end module F : functor (X : sig module M = M1 end) -> sig type t end type t = F(M3).t end |}] +type (_, _) eq = Refl : ('a, 'a) eq + +module Equal (M : Set.OrderedType) (N : Set.OrderedType with type t = M.t) : sig + val eq : (Set.Make(M).t, Set.Make(N).t) eq +end = struct + type meq = Eq of (Set.Make(M).t, Set.Make(M).t) eq + module type S = sig + module N = M + type neq = meq = Eq of (Set.Make(M).t, Set.Make(N).t) eq + end + module type T = S with type N.t = M.t with module N := N;; + module rec T : T = T + let eq = + let T.Eq eq = Eq Refl in + eq +end;; +[%%expect {| +type (_, _) eq = Refl : ('a, 'a) eq +Line 11, characters 18-58: +11 | module type T = S with type N.t = M.t with module N := N;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: In this `with' constraint, the new definition of N + does not match its original definition in the constrained signature: + Modules do not match: + sig type t = M.t val compare : t -> t -> int end + is not included in + (module M) +|}] + (* Checking that the uses of M.t are rewritten regardless of how they are named, but we don't rewrite other types by the same name. *) module type S = sig @@ -244,11 +267,11 @@ module type S = sig module A = M end with type M.t := float [%%expect {| -Line _, characters 16-89: - ................sig - module M : sig type t end - module A = M - end with type M.t := float +Line 1, characters 16-89: +1 | ................sig +2 | module M : sig type t end +3 | module A = M +4 | end with type M.t := float Error: This `with' constraint on M.t changes M, which is aliased in the constrained signature (as A). |}] @@ -272,9 +295,9 @@ module type S = (* This particular substitution cannot be made to work *) module type S2 = S with type M.t := float [%%expect {| -Line _, characters 17-41: - module type S2 = S with type M.t := float - ^^^^^^^^^^^^^^^^^^^^^^^^ +Line 1, characters 17-41: +1 | module type S2 = S with type M.t := float + ^^^^^^^^^^^^^^^^^^^^^^^^ Error: This `with' constraint on M.t makes the applicative functor type F(M).t ill-typed in the constrained signature: Modules do not match: @@ -306,11 +329,11 @@ module type S3 = sig end with type M2.t := int [%%expect {| module Id : functor (X : sig type t end) -> sig type t = X.t end -Line _, characters 17-120: - .................sig - module rec M : sig type t = A of Id(M2).t end - and M2 : sig type t end - end with type M2.t := int +Line 2, characters 17-120: +2 | .................sig +3 | module rec M : sig type t = A of Id(M2).t end +4 | and M2 : sig type t end +5 | end with type M2.t := int Error: This `with' constraint on M2.t makes the applicative functor type Id(M2).t ill-typed in the constrained signature: Modules do not match: sig end is not included in sig type t end @@ -349,17 +372,17 @@ module type S = sig module Alias = M end with module M.N := A [%%expect {| -Line _, characters 16-159: - ................sig - module M : sig - module N : sig - module P : sig - type t - end - end - end - module Alias = M - end with module M.N := A +Line 1, characters 16-159: + 1 | ................sig + 2 | module M : sig + 3 | module N : sig + 4 | module P : sig + 5 | type t + 6 | end + 7 | end + 8 | end + 9 | module Alias = M +10 | end with module M.N := A Error: This `with' constraint on M.N changes M, which is aliased in the constrained signature (as Alias). |}] diff --git a/testsuite/tests/typing-sigsubst/test_functor.ml b/testsuite/tests/typing-sigsubst/test_functor.ml new file mode 100644 index 00000000..f0926653 --- /dev/null +++ b/testsuite/tests/typing-sigsubst/test_functor.ml @@ -0,0 +1,13 @@ +module type S = sig + type elt + type t + + val create : elt -> t +end + +module Apply (Arg : sig type t end) : S with type elt = Arg.t = struct + type elt = Arg.t + type t = elt list + + let create x = [ x ] +end diff --git a/testsuite/tests/typing-sigsubst/test_loc_modtype_type_eq.ml b/testsuite/tests/typing-sigsubst/test_loc_modtype_type_eq.ml new file mode 100644 index 00000000..db74e843 --- /dev/null +++ b/testsuite/tests/typing-sigsubst/test_loc_modtype_type_eq.ml @@ -0,0 +1,3 @@ +module type S = Test_functor.S with type elt = unit + +module M : S = Test_functor.Apply (String) diff --git a/testsuite/tests/typing-sigsubst/test_loc_modtype_type_subst.ml b/testsuite/tests/typing-sigsubst/test_loc_modtype_type_subst.ml new file mode 100644 index 00000000..f8880e6e --- /dev/null +++ b/testsuite/tests/typing-sigsubst/test_loc_modtype_type_subst.ml @@ -0,0 +1,3 @@ +module type S = Test_functor.S with type elt := unit + +module M : S = Test_functor.Apply (String) diff --git a/testsuite/tests/typing-sigsubst/test_loc_type_eq.ml b/testsuite/tests/typing-sigsubst/test_loc_type_eq.ml new file mode 100644 index 00000000..9bec56d6 --- /dev/null +++ b/testsuite/tests/typing-sigsubst/test_loc_type_eq.ml @@ -0,0 +1 @@ +module M : Test_functor.S with type elt = unit = Test_functor.Apply (String) diff --git a/testsuite/tests/typing-sigsubst/test_loc_type_subst.ml b/testsuite/tests/typing-sigsubst/test_loc_type_subst.ml new file mode 100644 index 00000000..a32ec8aa --- /dev/null +++ b/testsuite/tests/typing-sigsubst/test_loc_type_subst.ml @@ -0,0 +1 @@ +module M : Test_functor.S with type elt := unit = Test_functor.Apply (String) diff --git a/testsuite/tests/typing-sigsubst/test_locations.compilers.reference b/testsuite/tests/typing-sigsubst/test_locations.compilers.reference new file mode 100644 index 00000000..86afba67 --- /dev/null +++ b/testsuite/tests/typing-sigsubst/test_locations.compilers.reference @@ -0,0 +1,74 @@ +File "test_loc_type_eq.ml", line 1, characters 49-76: +1 | module M : Test_functor.S with type elt = unit = Test_functor.Apply (String) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Signature mismatch: + Modules do not match: + sig + type elt = String.t + type t = Test_functor.Apply(String).t + val create : elt -> t + end + is not included in + sig type elt = unit type t val create : elt -> t end + Type declarations do not match: + type elt = String.t + is not included in + type elt = unit + File "test_loc_type_eq.ml", line 1, characters 31-46: + Expected declaration + File "test_functor.ml", line 8, characters 45-61: Actual declaration +File "test_loc_modtype_type_eq.ml", line 3, characters 15-42: +3 | module M : S = Test_functor.Apply (String) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Signature mismatch: + Modules do not match: + sig + type elt = String.t + type t = Test_functor.Apply(String).t + val create : elt -> t + end + is not included in + S + Type declarations do not match: + type elt = String.t + is not included in + type elt = unit + File "test_loc_modtype_type_eq.ml", line 1, characters 36-51: + Expected declaration + File "test_functor.ml", line 8, characters 45-61: Actual declaration +File "test_loc_type_subst.ml", line 1, characters 50-77: +1 | module M : Test_functor.S with type elt := unit = Test_functor.Apply (String) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Signature mismatch: + Modules do not match: + sig + type elt = String.t + type t = Test_functor.Apply(String).t + val create : elt -> t + end + is not included in + sig type t val create : unit -> t end + Values do not match: + val create : elt -> t + is not included in + val create : unit -> t + File "test_functor.ml", line 5, characters 2-23: Expected declaration + File "test_functor.ml", line 5, characters 2-23: Actual declaration +File "test_loc_modtype_type_subst.ml", line 3, characters 15-42: +3 | module M : S = Test_functor.Apply (String) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Signature mismatch: + Modules do not match: + sig + type elt = String.t + type t = Test_functor.Apply(String).t + val create : elt -> t + end + is not included in + S + Values do not match: + val create : elt -> t + is not included in + val create : unit -> t + File "test_functor.ml", line 5, characters 2-23: Expected declaration + File "test_functor.ml", line 5, characters 2-23: Actual declaration diff --git a/testsuite/tests/typing-sigsubst/test_locations.ml b/testsuite/tests/typing-sigsubst/test_locations.ml new file mode 100644 index 00000000..31084001 --- /dev/null +++ b/testsuite/tests/typing-sigsubst/test_locations.ml @@ -0,0 +1,26 @@ +(* TEST +files = "test_functor.ml test_loc_modtype_type_eq.ml \ + test_loc_modtype_type_subst.ml test_loc_type_eq.ml \ + test_loc_type_subst.ml mpr7852.mli" +* setup-ocamlc.byte-build-env +** ocamlc.byte +module = "test_functor.ml" +** ocamlc.byte +module = "test_loc_type_eq.ml" +ocamlc_byte_exit_status = "2" +** ocamlc.byte +module = "test_loc_modtype_type_eq.ml" +ocamlc_byte_exit_status = "2" +** ocamlc.byte +module = "test_loc_type_subst.ml" +ocamlc_byte_exit_status = "2" +** ocamlc.byte +module = "test_loc_modtype_type_subst.ml" +ocamlc_byte_exit_status = "2" +** check-ocamlc.byte-output +** ocamlc.byte +flags = "-w +32" +module = "mpr7852.mli" +ocamlc_byte_exit_status = "0" +** check-ocamlc.byte-output +*) diff --git a/testsuite/tests/typing-typeparam/newtype.ocaml.reference b/testsuite/tests/typing-typeparam/newtype.ocaml.reference index dab29770..5b1a6039 100644 --- a/testsuite/tests/typing-typeparam/newtype.ocaml.reference +++ b/testsuite/tests/typing-typeparam/newtype.ocaml.reference @@ -5,14 +5,14 @@ true false val sort_uniq : ('a -> 'a -> int) -> 'a list -> 'a list = abc,xyz -Characters 33-34: - let f x (type a) (y : a) = (x = y);; (* Fails *) - ^ +Line 2, characters 32-33: +2 | let f x (type a) (y : a) = (x = y);; (* Fails *) + ^ Error: This expression has type a but an expression was expected of type 'a The type constructor a would escape its scope -Characters 117-118: - method n : 'a -> 'a = fun (type g) (x:g) -> self#m x - ^ +Line 3, characters 53-54: +3 | method n : 'a -> 'a = fun (type g) (x:g) -> self#m x + ^ Error: This expression has type g but an expression was expected of type 'a The type constructor g would escape its scope diff --git a/testsuite/tests/typing-unboxed-types/ocamltests b/testsuite/tests/typing-unboxed-types/ocamltests index 31c13b44..6fde39d7 100644 --- a/testsuite/tests/typing-unboxed-types/ocamltests +++ b/testsuite/tests/typing-unboxed-types/ocamltests @@ -1 +1,3 @@ test.ml +test_flat.ml +test_no_flat.ml diff --git a/testsuite/tests/typing-unboxed-types/test.ml b/testsuite/tests/typing-unboxed-types/test.ml index 25f03be2..8ee1588c 100644 --- a/testsuite/tests/typing-unboxed-types/test.ml +++ b/testsuite/tests/typing-unboxed-types/test.ml @@ -1,48 +1,108 @@ (* TEST - * flat-float-array - ** toplevel - compiler_reference = "${test_source_directory}/test.ml.reference-flat" - * no-flat-float-array - ** toplevel - compiler_reference = "${test_source_directory}/test.ml.reference-noflat" + * expect *) (* Check the unboxing *) (* For concrete types *) type t1 = A of string [@@ocaml.unboxed];; +[%%expect{| +type t1 = A of string [@@unboxed] +|}];; let x = A "foo" in Obj.repr x == Obj.repr (match x with A s -> s) ;; +[%%expect{| +- : bool = true +|}];; (* For records *) type t2 = { f : string } [@@ocaml.unboxed];; +[%%expect{| +type t2 = { f : string; } [@@unboxed] +|}];; let x = { f = "foo" } in Obj.repr x == Obj.repr x.f ;; +[%%expect{| +- : bool = true +|}];; (* For inline records *) type t3 = B of { g : string } [@@ocaml.unboxed];; +[%%expect{| +type t3 = B of { g : string; } [@@unboxed] +|}];; let x = B { g = "foo" } in Obj.repr x == Obj.repr (match x with B {g} -> g) ;; +[%%expect{| +- : bool = true +|}];; (* Check unboxable types *) type t4 = C [@@ocaml.unboxed];; (* no argument *) +[%%expect{| +Line 1, characters 0-29: +1 | type t4 = C [@@ocaml.unboxed];; (* no argument *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because its constructor has no argument. +|}];; type t5 = D of int * string [@@ocaml.unboxed];; (* more than one argument *) +[%%expect{| +Line 1, characters 0-45: +1 | type t5 = D of int * string [@@ocaml.unboxed];; (* more than one argument *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + its constructor has more than one argument. +|}];; type t5 = E | F [@@ocaml.unboxed];; (* more than one constructor *) +[%%expect{| +Line 1, characters 0-33: +1 | type t5 = E | F [@@ocaml.unboxed];; (* more than one constructor *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because it has more than one constructor. +|}];; type t6 = G of int | H [@@ocaml.unboxed];; +[%%expect{| +Line 1, characters 0-40: +1 | type t6 = G of int | H [@@ocaml.unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because it has more than one constructor. +|}];; type t7 = I of string | J of bool [@@ocaml.unboxed];; type t8 = { h : bool; i : int } [@@ocaml.unboxed];; (* more than one field *) +[%%expect{| +Line 1, characters 0-51: +1 | type t7 = I of string | J of bool [@@ocaml.unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because it has more than one constructor. +|}];; type t9 = K of { j : string; l : int } [@@ocaml.unboxed];; +[%%expect{| +Line 1, characters 0-56: +1 | type t9 = K of { j : string; l : int } [@@ocaml.unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + its constructor has more than one argument. +|}];; (* let rec must be rejected *) type t10 = A of t10 [@@ocaml.unboxed];; +[%%expect{| +type t10 = A of t10 [@@unboxed] +|}];; let rec x = A x;; +[%%expect{| +Line 1, characters 12-15: +1 | let rec x = A x;; + ^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +|}];; (* Representation mismatch between module and signature must be rejected *) module M : sig @@ -50,64 +110,177 @@ module M : sig end = struct type t = A of string [@@ocaml.unboxed] end;; +[%%expect{| +Line 3, characters 6-57: +3 | ......struct +4 | type t = A of string [@@ocaml.unboxed] +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig type t = A of string [@@unboxed] end + is not included in + sig type t = A of string end + Type declarations do not match: + type t = A of string [@@unboxed] + is not included in + type t = A of string + Their internal representations differ: + the first declaration uses unboxed representation. +|}];; module N : sig type t = A of string [@@ocaml.unboxed] end = struct type t = A of string end;; +[%%expect{| +Line 3, characters 6-39: +3 | ......struct +4 | type t = A of string +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig type t = A of string end + is not included in + sig type t = A of string [@@unboxed] end + Type declarations do not match: + type t = A of string + is not included in + type t = A of string [@@unboxed] + Their internal representations differ: + the second declaration uses unboxed representation. +|}];; module O : sig type t = { f : string } end = struct type t = { f : string } [@@ocaml.unboxed] end;; +[%%expect{| +Line 3, characters 6-60: +3 | ......struct +4 | type t = { f : string } [@@ocaml.unboxed] +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig type t = { f : string; } [@@unboxed] end + is not included in + sig type t = { f : string; } end + Type declarations do not match: + type t = { f : string; } [@@unboxed] + is not included in + type t = { f : string; } + Their internal representations differ: + the first declaration uses unboxed representation. +|}];; module P : sig type t = { f : string } [@@ocaml.unboxed] end = struct type t = { f : string } end;; +[%%expect{| +Line 3, characters 6-42: +3 | ......struct +4 | type t = { f : string } +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig type t = { f : string; } end + is not included in + sig type t = { f : string; } [@@unboxed] end + Type declarations do not match: + type t = { f : string; } + is not included in + type t = { f : string; } [@@unboxed] + Their internal representations differ: + the second declaration uses unboxed representation. +|}];; module Q : sig type t = A of { f : string } end = struct type t = A of { f : string } [@@ocaml.unboxed] end;; +[%%expect{| +Line 3, characters 6-65: +3 | ......struct +4 | type t = A of { f : string } [@@ocaml.unboxed] +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig type t = A of { f : string; } [@@unboxed] end + is not included in + sig type t = A of { f : string; } end + Type declarations do not match: + type t = A of { f : string; } [@@unboxed] + is not included in + type t = A of { f : string; } + Their internal representations differ: + the first declaration uses unboxed representation. +|}];; module R : sig type t = A of { f : string } [@@ocaml.unboxed] end = struct type t = A of { f : string } end;; +[%%expect{| +Line 3, characters 6-47: +3 | ......struct +4 | type t = A of { f : string } +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig type t = A of { f : string; } end + is not included in + sig type t = A of { f : string; } [@@unboxed] end + Type declarations do not match: + type t = A of { f : string; } + is not included in + type t = A of { f : string; } [@@unboxed] + Their internal representations differ: + the second declaration uses unboxed representation. +|}];; (* Check interference with representation of float arrays. *) type t11 = L of float [@@ocaml.unboxed];; +[%%expect{| +type t11 = L of float [@@unboxed] +|}];; let x = Array.make 10 (L 3.14) (* represented as a flat array *) and f (a : t11 array) = a.(0) (* might wrongly assume an array of pointers *) in assert (f x = L 3.14);; +[%%expect{| +- : unit = () +|}];; (* Check for a potential infinite loop in the typing algorithm. *) type 'a t12 = M of 'a t12 [@@ocaml.unboxed];; +[%%expect{| +type 'a t12 = M of 'a t12 [@@unboxed] +|}];; let f (a : int t12 array) = a.(0);; +[%%expect{| +val f : int t12 array -> int t12 = +|}];; (* Check for another possible loop *) type t13 = A : _ t12 -> t13 [@@ocaml.unboxed];; - +[%%expect{| +type t13 = A : 'a t12 -> t13 [@@unboxed] +|}];; (* should work *) type t14;; type t15 = A of t14 [@@ocaml.unboxed];; - -(* should fail *) -type 'a abs;; -type t16 = A : _ abs -> t16 [@@ocaml.unboxed];; - -(* should work *) -type t18 = A : _ list abs -> t18 [@@ocaml.unboxed];; +[%%expect{| +type t14 +type t15 = A of t14 [@@unboxed] +|}];; (* should fail because the compiler knows that t is actually float and optimizes the record's representation *) @@ -118,7 +291,24 @@ end = struct type t = A of float [@@ocaml.unboxed] type u = { f1 : t; f2 : t } end;; - +[%%expect{| +Line 4, characters 6-86: +4 | ......struct +5 | type t = A of float [@@ocaml.unboxed] +6 | type u = { f1 : t; f2 : t } +7 | end.. +Error: Signature mismatch: + Modules do not match: + sig type t = A of float [@@unboxed] type u = { f1 : t; f2 : t; } end + is not included in + sig type t type u = { f1 : t; f2 : t; } end + Type declarations do not match: + type u = { f1 : t; f2 : t; } + is not included in + type u = { f1 : t; f2 : t; } + Their internal representations differ: + the first declaration uses unboxed float representation. +|}];; (* implementing [@@immediate] with [@@ocaml.unboxed]: this works because the representation of [t] is [int] @@ -128,54 +318,37 @@ module T : sig end = struct type t = A of int [@@ocaml.unboxed] end;; - -(* regression test for PR#7511 (wrong determination of unboxability for GADTs) -*) -type 'a s = S : 'a -> 'a s [@@unboxed];; -type t = T : _ s -> t [@@unboxed];; - -(* regression test for GPR#1133 (follow-up to PR#7511) *) -type 'a s = S : 'a -> 'a option s [@@unboxed];; -type t = T : _ s -> t [@@unboxed];; - -(* Another test for GPR#1133: abstract types *) -module M : sig - type 'a r constraint 'a = unit -> 'b - val inj : 'b -> (unit -> 'b) r -end = struct - type 'a r = 'b constraint 'a = unit -> 'b - let inj x = x -end;; - -(* reject *) -type t = T : (unit -> _) M.r -> t [@@unboxed];; - -type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed];; - -(* reject *) -type t = T : _ s -> t [@@unboxed];; - -(* accept *) -type 'a t = T : 'a s -> 'a t [@@unboxed];; - - -(* Another corner case from GPR#1133 *) -type _ s = S : 'a t -> _ s [@@unboxed] - and _ t = T : 'a -> 'a s t -;; - +[%%expect{| +module T : sig type t [@@immediate] end +|}];; (* Another corner case *) type 'a s type ('a, 'p) t = private 'a s type 'a packed = T : ('a, _) t -> 'a packed [@@unboxed] ;; +[%%expect{| +type 'a s +type ('a, 'p) t = private 'a s +type 'a packed = T : ('a, 'b) t -> 'a packed [@@unboxed] +|}];; (* MPR#7682 *) type f = {field: 'a. 'a list} [@@unboxed];; let g = Array.make 10 { field=[] };; let h = g.(5);; +[%%expect{| +type f = { field : 'a. 'a list; } [@@unboxed] +val g : f array = + [|{field = []}; {field = []}; {field = []}; {field = []}; {field = []}; + {field = []}; {field = []}; {field = []}; {field = []}; {field = []}|] +val h : f = {field = []} +|}];; (* Using [@@immediate] information (GPR#1469) *) type 'a t [@@immediate];; type u = U : 'a t -> u [@@unboxed];; +[%%expect{| +type 'a t [@@immediate] +type u = U : 'a t -> u [@@unboxed] +|}];; diff --git a/testsuite/tests/typing-unboxed-types/test.ml.reference-flat b/testsuite/tests/typing-unboxed-types/test.ml.reference-flat deleted file mode 100644 index a9515e4d..00000000 --- a/testsuite/tests/typing-unboxed-types/test.ml.reference-flat +++ /dev/null @@ -1,212 +0,0 @@ -type t1 = A of string [@@unboxed] -- : bool = true -type t2 = { f : string; } [@@unboxed] -- : bool = true -type t3 = B of { g : string; } [@@unboxed] -- : bool = true -Characters 29-58: - type t4 = C [@@ocaml.unboxed];; (* no argument *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because its constructor has no argument. -Characters 0-45: - type t5 = D of int * string [@@ocaml.unboxed];; (* more than one argument *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because - its constructor has more than one argument. -Characters 0-33: - type t5 = E | F [@@ocaml.unboxed];; (* more than one constructor *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because it has more than one constructor. -Characters 0-40: - type t6 = G of int | H [@@ocaml.unboxed];; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because it has more than one constructor. -Characters 0-51: - type t7 = I of string | J of bool [@@ocaml.unboxed];; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because it has more than one constructor. -Characters 1-50: - type t8 = { h : bool; i : int } [@@ocaml.unboxed];; (* more than one field *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because it has more than one field. -Characters 0-56: - type t9 = K of { j : string; l : int } [@@ocaml.unboxed];; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because - its constructor has more than one argument. -type t10 = A of t10 [@@unboxed] -Characters 12-15: - let rec x = A x;; - ^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 121-172: - ......struct - type t = A of string [@@ocaml.unboxed] - end.. -Error: Signature mismatch: - Modules do not match: - sig type t = A of string [@@unboxed] end - is not included in - sig type t = A of string end - Type declarations do not match: - type t = A of string [@@unboxed] - is not included in - type t = A of string - Their internal representations differ: - the first declaration uses unboxed representation. -Characters 63-96: - ......struct - type t = A of string - end.. -Error: Signature mismatch: - Modules do not match: - sig type t = A of string end - is not included in - sig type t = A of string [@@unboxed] end - Type declarations do not match: - type t = A of string - is not included in - type t = A of string [@@unboxed] - Their internal representations differ: - the second declaration uses unboxed representation. -Characters 48-102: - ......struct - type t = { f : string } [@@ocaml.unboxed] - end.. -Error: Signature mismatch: - Modules do not match: - sig type t = { f : string; } [@@unboxed] end - is not included in - sig type t = { f : string; } end - Type declarations do not match: - type t = { f : string; } [@@unboxed] - is not included in - type t = { f : string; } - Their internal representations differ: - the first declaration uses unboxed representation. -Characters 66-102: - ......struct - type t = { f : string } - end.. -Error: Signature mismatch: - Modules do not match: - sig type t = { f : string; } end - is not included in - sig type t = { f : string; } [@@unboxed] end - Type declarations do not match: - type t = { f : string; } - is not included in - type t = { f : string; } [@@unboxed] - Their internal representations differ: - the second declaration uses unboxed representation. -Characters 53-112: - ......struct - type t = A of { f : string } [@@ocaml.unboxed] - end.. -Error: Signature mismatch: - Modules do not match: - sig type t = A of { f : string; } [@@unboxed] end - is not included in - sig type t = A of { f : string; } end - Type declarations do not match: - type t = A of { f : string; } [@@unboxed] - is not included in - type t = A of { f : string; } - Their internal representations differ: - the first declaration uses unboxed representation. -Characters 71-112: - ......struct - type t = A of { f : string } - end.. -Error: Signature mismatch: - Modules do not match: - sig type t = A of { f : string; } end - is not included in - sig type t = A of { f : string; } [@@unboxed] end - Type declarations do not match: - type t = A of { f : string; } - is not included in - type t = A of { f : string; } [@@unboxed] - Their internal representations differ: - the second declaration uses unboxed representation. -type t11 = L of float [@@unboxed] -- : unit = () -type 'a t12 = M of 'a t12 [@@unboxed] -val f : int t12 array -> int t12 = -type t13 = A : 'a t12 -> t13 [@@unboxed] -type t14 -type t15 = A of t14 [@@unboxed] -type 'a abs -Characters 0-45: - type t16 = A : _ abs -> t16 [@@ocaml.unboxed];; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because - it might contain both float and non-float values. - You should annotate it with [@@ocaml.boxed]. -Characters 19-69: - type t18 = A : _ list abs -> t18 [@@ocaml.unboxed];; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because - it might contain both float and non-float values. - You should annotate it with [@@ocaml.boxed]. -Characters 176-256: - ......struct - type t = A of float [@@ocaml.unboxed] - type u = { f1 : t; f2 : t } - end.. -Error: Signature mismatch: - ... - Type declarations do not match: - type u = { f1 : t; f2 : t; } - is not included in - type u = { f1 : t; f2 : t; } - Their internal representations differ: - the first declaration uses unboxed float representation. -module T : sig type t [@@immediate] end -type 'a s = S : 'a -> 'a s [@@unboxed] -Characters 0-33: - type t = T : _ s -> t [@@unboxed];; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because - it might contain both float and non-float values. - You should annotate it with [@@ocaml.boxed]. -type 'a s = S : 'a -> 'a option s [@@unboxed] -Characters 0-33: - type t = T : _ s -> t [@@unboxed];; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because - it might contain both float and non-float values. - You should annotate it with [@@ocaml.boxed]. -module M : - sig type 'a r constraint 'a = unit -> 'b val inj : 'b -> (unit -> 'b) r end -Characters 14-59: - type t = T : (unit -> _) M.r -> t [@@unboxed];; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because - it might contain both float and non-float values. - You should annotate it with [@@ocaml.boxed]. -type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed] -Characters 14-47: - type t = T : _ s -> t [@@unboxed];; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because - it might contain both float and non-float values. - You should annotate it with [@@ocaml.boxed]. -type 'a t = T : 'a s -> 'a t [@@unboxed] -Characters 42-81: - type _ s = S : 'a t -> _ s [@@unboxed] - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because - it might contain both float and non-float values. - You should annotate it with [@@ocaml.boxed]. -type 'a s -type ('a, 'p) t = private 'a s -type 'a packed = T : ('a, 'b) t -> 'a packed [@@unboxed] -type f = { field : 'a. 'a list; } [@@unboxed] -val g : f array = - [|{field = []}; {field = []}; {field = []}; {field = []}; {field = []}; - {field = []}; {field = []}; {field = []}; {field = []}; {field = []}|] -val h : f = {field = []} -type 'a t [@@immediate] -type u = U : 'a t -> u [@@unboxed] - diff --git a/testsuite/tests/typing-unboxed-types/test.ml.reference-noflat b/testsuite/tests/typing-unboxed-types/test.ml.reference-noflat deleted file mode 100644 index 49fd74e9..00000000 --- a/testsuite/tests/typing-unboxed-types/test.ml.reference-noflat +++ /dev/null @@ -1,178 +0,0 @@ -type t1 = A of string [@@unboxed] -- : bool = true -type t2 = { f : string; } [@@unboxed] -- : bool = true -type t3 = B of { g : string; } [@@unboxed] -- : bool = true -Characters 29-58: - type t4 = C [@@ocaml.unboxed];; (* no argument *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because its constructor has no argument. -Characters 0-45: - type t5 = D of int * string [@@ocaml.unboxed];; (* more than one argument *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because - its constructor has more than one argument. -Characters 0-33: - type t5 = E | F [@@ocaml.unboxed];; (* more than one constructor *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because it has more than one constructor. -Characters 0-40: - type t6 = G of int | H [@@ocaml.unboxed];; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because it has more than one constructor. -Characters 0-51: - type t7 = I of string | J of bool [@@ocaml.unboxed];; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because it has more than one constructor. -Characters 1-50: - type t8 = { h : bool; i : int } [@@ocaml.unboxed];; (* more than one field *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because it has more than one field. -Characters 0-56: - type t9 = K of { j : string; l : int } [@@ocaml.unboxed];; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: This type cannot be unboxed because - its constructor has more than one argument. -type t10 = A of t10 [@@unboxed] -Characters 12-15: - let rec x = A x;; - ^^^ -Error: This kind of expression is not allowed as right-hand side of `let rec' -Characters 121-172: - ......struct - type t = A of string [@@ocaml.unboxed] - end.. -Error: Signature mismatch: - Modules do not match: - sig type t = A of string [@@unboxed] end - is not included in - sig type t = A of string end - Type declarations do not match: - type t = A of string [@@unboxed] - is not included in - type t = A of string - Their internal representations differ: - the first declaration uses unboxed representation. -Characters 63-96: - ......struct - type t = A of string - end.. -Error: Signature mismatch: - Modules do not match: - sig type t = A of string end - is not included in - sig type t = A of string [@@unboxed] end - Type declarations do not match: - type t = A of string - is not included in - type t = A of string [@@unboxed] - Their internal representations differ: - the second declaration uses unboxed representation. -Characters 48-102: - ......struct - type t = { f : string } [@@ocaml.unboxed] - end.. -Error: Signature mismatch: - Modules do not match: - sig type t = { f : string; } [@@unboxed] end - is not included in - sig type t = { f : string; } end - Type declarations do not match: - type t = { f : string; } [@@unboxed] - is not included in - type t = { f : string; } - Their internal representations differ: - the first declaration uses unboxed representation. -Characters 66-102: - ......struct - type t = { f : string } - end.. -Error: Signature mismatch: - Modules do not match: - sig type t = { f : string; } end - is not included in - sig type t = { f : string; } [@@unboxed] end - Type declarations do not match: - type t = { f : string; } - is not included in - type t = { f : string; } [@@unboxed] - Their internal representations differ: - the second declaration uses unboxed representation. -Characters 53-112: - ......struct - type t = A of { f : string } [@@ocaml.unboxed] - end.. -Error: Signature mismatch: - Modules do not match: - sig type t = A of { f : string; } [@@unboxed] end - is not included in - sig type t = A of { f : string; } end - Type declarations do not match: - type t = A of { f : string; } [@@unboxed] - is not included in - type t = A of { f : string; } - Their internal representations differ: - the first declaration uses unboxed representation. -Characters 71-112: - ......struct - type t = A of { f : string } - end.. -Error: Signature mismatch: - Modules do not match: - sig type t = A of { f : string; } end - is not included in - sig type t = A of { f : string; } [@@unboxed] end - Type declarations do not match: - type t = A of { f : string; } - is not included in - type t = A of { f : string; } [@@unboxed] - Their internal representations differ: - the second declaration uses unboxed representation. -type t11 = L of float [@@unboxed] -- : unit = () -type 'a t12 = M of 'a t12 [@@unboxed] -val f : int t12 array -> int t12 = -type t13 = A : 'a t12 -> t13 [@@unboxed] -type t14 -type t15 = A of t14 [@@unboxed] -type 'a abs -type t16 = A : 'a abs -> t16 [@@unboxed] -type t18 = A : 'a list abs -> t18 [@@unboxed] -Characters 176-256: - ......struct - type t = A of float [@@ocaml.unboxed] - type u = { f1 : t; f2 : t } - end.. -Error: Signature mismatch: - ... - Type declarations do not match: - type u = { f1 : t; f2 : t; } - is not included in - type u = { f1 : t; f2 : t; } - Their internal representations differ: - the first declaration uses unboxed float representation. -module T : sig type t [@@immediate] end -type 'a s = S : 'a -> 'a s [@@unboxed] -type t = T : 'a s -> t [@@unboxed] -type 'a s = S : 'a -> 'a option s [@@unboxed] -type t = T : 'a s -> t [@@unboxed] -module M : - sig type 'a r constraint 'a = unit -> 'b val inj : 'b -> (unit -> 'b) r end -type t = T : (unit -> 'a) M.r -> t [@@unboxed] -type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed] -type t = T : 'a s -> t [@@unboxed] -type 'a t = T : 'a s -> 'a t [@@unboxed] -type _ s = S : 'a t -> 'b s [@@unboxed] -and _ t = T : 'a -> 'a s t -type 'a s -type ('a, 'p) t = private 'a s -type 'a packed = T : ('a, 'b) t -> 'a packed [@@unboxed] -type f = { field : 'a. 'a list; } [@@unboxed] -val g : f array = - [|{field = []}; {field = []}; {field = []}; {field = []}; {field = []}; - {field = []}; {field = []}; {field = []}; {field = []}; {field = []}|] -val h : f = {field = []} -type 'a t [@@immediate] -type u = U : 'a t -> u [@@unboxed] - diff --git a/testsuite/tests/typing-unboxed-types/test_flat.ml b/testsuite/tests/typing-unboxed-types/test_flat.ml new file mode 100644 index 00000000..a2c04fe8 --- /dev/null +++ b/testsuite/tests/typing-unboxed-types/test_flat.ml @@ -0,0 +1,202 @@ +(* TEST + * flat-float-array + ** expect +*) + +(* should fail *) +type 'a abs;; +type t16 = A : _ abs -> t16 [@@ocaml.unboxed];; +[%%expect{| +type 'a abs +Line 2, characters 0-45: +2 | type t16 = A : _ abs -> t16 [@@ocaml.unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +|}];; + +(* should fail (the existential _ still occurs in an abstract type) *) +type t18 = A : _ list abs -> t18 [@@ocaml.unboxed];; +[%%expect{| +Line 1, characters 0-50: +1 | type t18 = A : _ list abs -> t18 [@@ocaml.unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +|}];; + +(* regression test for PR#7511 (wrong determination of unboxability for GADTs) +*) +type 'a s = S : 'a -> 'a s [@@unboxed];; +type t = T : _ s -> t [@@unboxed];; +[%%expect{| +type 'a s = S : 'a -> 'a s [@@unboxed] +Line 2, characters 0-33: +2 | type t = T : _ s -> t [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +|}];; + +(* regression test for GPR#1133 (follow-up to PR#7511) *) +type 'a s = S : 'a -> 'a option s [@@unboxed];; +type t = T : _ s -> t [@@unboxed];; +[%%expect{| +type 'a s = S : 'a -> 'a option s [@@unboxed] +Line 2, characters 0-33: +2 | type t = T : _ s -> t [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +|}];; + +(* Another test for GPR#1133: abstract types *) +module M : sig + type 'a r constraint 'a = unit -> 'b + val inj : 'b -> (unit -> 'b) r +end = struct + type 'a r = 'b constraint 'a = unit -> 'b + let inj x = x +end;; +[%%expect{| +module M : + sig type 'a r constraint 'a = unit -> 'b val inj : 'b -> (unit -> 'b) r end +|}];; + +(* reject *) +type t = T : (unit -> _) M.r -> t [@@unboxed];; +[%%expect{| +Line 1, characters 0-45: +1 | type t = T : (unit -> _) M.r -> t [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +|}];; + +type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed];; +[%%expect{| +type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed] +|}];; + +(* reject *) +type t = T : _ s -> t [@@unboxed];; +[%%expect{| +Line 1, characters 0-33: +1 | type t = T : _ s -> t [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +|}];; + +(* accept *) +type 'a t = T : 'a s -> 'a t [@@unboxed];; +[%%expect{| +type 'a t = T : 'a s -> 'a t [@@unboxed] +|}];; + + +(* Another corner case from GPR#1133 *) +type _ s = S : 'a t -> _ s [@@unboxed] + and _ t = T : 'a -> 'a s t +;; +[%%expect{| +Line 1, characters 0-39: +1 | type _ s = S : 'a t -> _ s [@@unboxed] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +|}];; + +(* regression test for PR#7511 (wrong determination of unboxability for GADTs) +*) +type 'a s = S : 'a -> 'a s [@@unboxed];; +type t = T : _ s -> t [@@unboxed];; +[%%expect{| +type 'a s = S : 'a -> 'a s [@@unboxed] +Line 2, characters 0-33: +2 | type t = T : _ s -> t [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +|}];; + +(* regression test for GPR#1133 (follow-up to PR#7511) *) +type 'a s = S : 'a -> 'a option s [@@unboxed];; +type t = T : _ s -> t [@@unboxed];; +[%%expect{| +type 'a s = S : 'a -> 'a option s [@@unboxed] +Line 2, characters 0-33: +2 | type t = T : _ s -> t [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +|}];; + +(* Another test for GPR#1133: abstract types *) +module M : sig + type 'a r constraint 'a = unit -> 'b + val inj : 'b -> (unit -> 'b) r +end = struct + type 'a r = 'b constraint 'a = unit -> 'b + let inj x = x +end;; +[%%expect{| +module M : + sig type 'a r constraint 'a = unit -> 'b val inj : 'b -> (unit -> 'b) r end +|}];; + +(* reject *) +type t = T : (unit -> _) M.r -> t [@@unboxed];; +[%%expect{| +Line 1, characters 0-45: +1 | type t = T : (unit -> _) M.r -> t [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +|}];; + +type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed];; +[%%expect{| +type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed] +|}];; + +(* reject *) +type t = T : _ s -> t [@@unboxed];; +[%%expect{| +Line 1, characters 0-33: +1 | type t = T : _ s -> t [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +|}];; + +(* accept *) +type 'a t = T : 'a s -> 'a t [@@unboxed];; +[%%expect{| +type 'a t = T : 'a s -> 'a t [@@unboxed] +|}];; + + +(* Another corner case from GPR#1133 *) +type _ s = S : 'a t -> _ s [@@unboxed] + and _ t = T : 'a -> 'a s t +;; +[%%expect{| +Line 1, characters 0-39: +1 | type _ s = S : 'a t -> _ s [@@unboxed] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This type cannot be unboxed because + it might contain both float and non-float values. + You should annotate it with [@@ocaml.boxed]. +|}];; diff --git a/testsuite/tests/typing-unboxed-types/test_no_flat.ml b/testsuite/tests/typing-unboxed-types/test_no_flat.ml new file mode 100644 index 00000000..a1c48d2c --- /dev/null +++ b/testsuite/tests/typing-unboxed-types/test_no_flat.ml @@ -0,0 +1,154 @@ +(* TEST + * no-flat-float-array + ** expect +*) + +(* This file copies the tests from test_flat.ml, + but is only tested when -no-flat-float-array + is set, and thus all types are unboxable. + + We kept the comments on why each test should fail, + to make it easier to compare the two files, + but the test in this file should all pass, + as shown in the expected outputs. +*) + +(* should fail *) +type 'a abs;; +type t16 = A : _ abs -> t16 [@@ocaml.unboxed];; +[%%expect{| +type 'a abs +type t16 = A : 'a abs -> t16 [@@unboxed] +|}];; + +(* should fail (the existential _ still occurs in an abstract type) *) +type t18 = A : _ list abs -> t18 [@@ocaml.unboxed];; +[%%expect{| +type t18 = A : 'a list abs -> t18 [@@unboxed] +|}];; + +(* regression test for PR#7511 (wrong determination of unboxability for GADTs) +*) +type 'a s = S : 'a -> 'a s [@@unboxed];; +type t = T : _ s -> t [@@unboxed];; +[%%expect{| +type 'a s = S : 'a -> 'a s [@@unboxed] +type t = T : 'a s -> t [@@unboxed] +|}];; + +(* regression test for GPR#1133 (follow-up to PR#7511) *) +type 'a s = S : 'a -> 'a option s [@@unboxed];; +type t = T : _ s -> t [@@unboxed];; +[%%expect{| +type 'a s = S : 'a -> 'a option s [@@unboxed] +type t = T : 'a s -> t [@@unboxed] +|}];; + +(* Another test for GPR#1133: abstract types *) +module M : sig + type 'a r constraint 'a = unit -> 'b + val inj : 'b -> (unit -> 'b) r +end = struct + type 'a r = 'b constraint 'a = unit -> 'b + let inj x = x +end;; +[%%expect{| +module M : + sig type 'a r constraint 'a = unit -> 'b val inj : 'b -> (unit -> 'b) r end +|}];; + +(* reject *) +type t = T : (unit -> _) M.r -> t [@@unboxed];; +[%%expect{| +type t = T : (unit -> 'a) M.r -> t [@@unboxed] +|}];; + +type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed];; +[%%expect{| +type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed] +|}];; + +(* reject *) +type t = T : _ s -> t [@@unboxed];; +[%%expect{| +type t = T : 'a s -> t [@@unboxed] +|}];; + +(* accept *) +type 'a t = T : 'a s -> 'a t [@@unboxed];; +[%%expect{| +type 'a t = T : 'a s -> 'a t [@@unboxed] +|}];; + + +(* Another corner case from GPR#1133 *) +type _ s = S : 'a t -> _ s [@@unboxed] + and _ t = T : 'a -> 'a s t +;; +[%%expect{| +type _ s = S : 'a t -> 'b s [@@unboxed] +and _ t = T : 'a -> 'a s t +|}];; + +(* regression test for PR#7511 (wrong determination of unboxability for GADTs) +*) +type 'a s = S : 'a -> 'a s [@@unboxed];; +type t = T : _ s -> t [@@unboxed];; +[%%expect{| +type 'a s = S : 'a -> 'a s [@@unboxed] +type t = T : 'a s -> t [@@unboxed] +|}];; + +(* regression test for GPR#1133 (follow-up to PR#7511) *) +type 'a s = S : 'a -> 'a option s [@@unboxed];; +type t = T : _ s -> t [@@unboxed];; +[%%expect{| +type 'a s = S : 'a -> 'a option s [@@unboxed] +type t = T : 'a s -> t [@@unboxed] +|}];; + +(* Another test for GPR#1133: abstract types *) +module M : sig + type 'a r constraint 'a = unit -> 'b + val inj : 'b -> (unit -> 'b) r +end = struct + type 'a r = 'b constraint 'a = unit -> 'b + let inj x = x +end;; +[%%expect{| +module M : + sig type 'a r constraint 'a = unit -> 'b val inj : 'b -> (unit -> 'b) r end +|}];; + +(* reject *) +type t = T : (unit -> _) M.r -> t [@@unboxed];; +[%%expect{| +type t = T : (unit -> 'a) M.r -> t [@@unboxed] +|}];; + +type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed];; +[%%expect{| +type 'a s = S : (unit -> 'a) M.r -> 'a option s [@@unboxed] +|}];; + +(* reject *) +type t = T : _ s -> t [@@unboxed];; +[%%expect{| +type t = T : 'a s -> t [@@unboxed] +|}];; + +(* accept *) +type 'a t = T : 'a s -> 'a t [@@unboxed];; +[%%expect{| +type 'a t = T : 'a s -> 'a t [@@unboxed] +|}];; + + +(* Another corner case from GPR#1133 *) +type _ s = S : 'a t -> _ s [@@unboxed] + and _ t = T : 'a -> 'a s t +;; +[%%expect{| +type _ s = S : 'a t -> 'b s [@@unboxed] +and _ t = T : 'a -> 'a s t +|}];; diff --git a/testsuite/tests/typing-unboxed/test.ml b/testsuite/tests/typing-unboxed/test.ml index b577013d..4dff4e46 100644 --- a/testsuite/tests/typing-unboxed/test.ml +++ b/testsuite/tests/typing-unboxed/test.ml @@ -1,7 +1,7 @@ (* TEST - * toplevel + flags = "-strict-sequence" + * expect *) - external a : (int [@untagged]) -> unit = "a" "a_nat" external b : (int32 [@unboxed]) -> unit = "b" "b_nat" external c : (int64 [@unboxed]) -> unit = "c" "c_nat" @@ -20,8 +20,23 @@ end = struct external b : (int [@untagged]) -> int = "b" "b_nat" end;; +[%%expect{| +external a : (int [@untagged]) -> unit = "a" "a_nat" +external b : (int32 [@unboxed]) -> unit = "b" "b_nat" +external c : (int64 [@unboxed]) -> unit = "c" "c_nat" +external d : (nativeint [@unboxed]) -> unit = "d" "d_nat" +external e : (float [@unboxed]) -> unit = "e" "e_nat" +type t = private int +external f : (t [@untagged]) -> unit = "f" "f_nat" +module M : + sig + external a : int -> (int [@untagged]) = "a" "a_nat" + external b : (int [@untagged]) -> int = "b" "b_nat" + end +|}] + module Global_attributes = struct - [@@@ocaml.warning "-3"] + [@@@ocaml.alert "-deprecated"] external a : float -> float = "a" "noalloc" "a_nat" "float" external b : float -> float = "b" "noalloc" "b_nat" @@ -37,6 +52,14 @@ module Global_attributes = struct external i : int -> int = "i" "i_nat" [@@untagged] [@@noalloc] end;; +[%%expect{| +Line 11, characters 2-71: +11 | external f : (int32 [@unboxed]) -> (int32 [@unboxed]) = "f" "noalloc" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: [@The native code version of the primitive is mandatory + when attributes [@untagged] or [@unboxed] are present. +|}] + module Old_style_warning = struct [@@@ocaml.warning "+3"] external a : float -> float = "a" "noalloc" "a_nat" "float" @@ -44,7 +67,35 @@ module Old_style_warning = struct external c : float -> float = "c" "c_nat" "float" external d : float -> float = "d" "noalloc" external e : float -> float = "c" "float" -end +end;; +[%%expect{| +Line 3, characters 2-61: +3 | external a : float -> float = "a" "noalloc" "a_nat" "float" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Alert deprecated: [@@unboxed] + [@@noalloc] should be used +instead of "float" +Line 4, characters 2-53: +4 | external b : float -> float = "b" "noalloc" "b_nat" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Alert deprecated: [@@noalloc] should be used instead of "noalloc" +Line 5, characters 2-51: +5 | external c : float -> float = "c" "c_nat" "float" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Alert deprecated: [@@unboxed] + [@@noalloc] should be used +instead of "float" +Line 6, characters 2-45: +6 | external d : float -> float = "d" "noalloc" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Alert deprecated: [@@noalloc] should be used instead of "noalloc" +module Old_style_warning : + sig + external a : float -> float = "a" "a_nat" [@@unboxed] [@@noalloc] + external b : float -> float = "b" "b_nat" [@@noalloc] + external c : float -> float = "c" "c_nat" [@@unboxed] [@@noalloc] + external d : float -> float = "d" [@@noalloc] + external e : float -> float = "c" "float" + end +|}] (* Bad: attributes not reported in the interface *) @@ -54,24 +105,88 @@ end = struct external f : int -> (int [@untagged]) = "f" "f_nat" end;; +[%%expect{| +Line 3, characters 6-70: +3 | ......struct +4 | external f : int -> (int [@untagged]) = "f" "f_nat" +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig external f : int -> (int [@untagged]) = "f" "f_nat" end + is not included in + sig external f : int -> int = "f" "f_nat" end + Values do not match: + external f : int -> (int [@untagged]) = "f" "f_nat" + is not included in + external f : int -> int = "f" "f_nat" +|}] + module Bad2 : sig external f : int -> int = "a" "a_nat" end = struct external f : (int [@untagged]) -> int = "f" "f_nat" end;; +[%%expect{| +Line 3, characters 6-70: +3 | ......struct +4 | external f : (int [@untagged]) -> int = "f" "f_nat" +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig external f : (int [@untagged]) -> int = "f" "f_nat" end + is not included in + sig external f : int -> int = "a" "a_nat" end + Values do not match: + external f : (int [@untagged]) -> int = "f" "f_nat" + is not included in + external f : int -> int = "a" "a_nat" +|}] + module Bad3 : sig external f : float -> float = "f" "f_nat" end = struct external f : float -> (float [@unboxed]) = "f" "f_nat" end;; +[%%expect{| +Line 3, characters 6-73: +3 | ......struct +4 | external f : float -> (float [@unboxed]) = "f" "f_nat" +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig external f : float -> (float [@unboxed]) = "f" "f_nat" end + is not included in + sig external f : float -> float = "f" "f_nat" end + Values do not match: + external f : float -> (float [@unboxed]) = "f" "f_nat" + is not included in + external f : float -> float = "f" "f_nat" +|}] + module Bad4 : sig external f : float -> float = "a" "a_nat" end = struct external f : (float [@unboxed]) -> float = "f" "f_nat" end;; +[%%expect{| +Line 3, characters 6-73: +3 | ......struct +4 | external f : (float [@unboxed]) -> float = "f" "f_nat" +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig external f : (float [@unboxed]) -> float = "f" "f_nat" end + is not included in + sig external f : float -> float = "a" "a_nat" end + Values do not match: + external f : (float [@unboxed]) -> float = "f" "f_nat" + is not included in + external f : float -> float = "a" "a_nat" +|}] + (* Bad: attributes in the interface but not in the implementation *) module Bad5 : sig @@ -80,53 +195,264 @@ end = struct external f : int -> int = "f" "f_nat" end;; +[%%expect{| +Line 3, characters 6-56: +3 | ......struct +4 | external f : int -> int = "f" "f_nat" +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig external f : int -> int = "f" "f_nat" end + is not included in + sig external f : int -> (int [@untagged]) = "f" "f_nat" end + Values do not match: + external f : int -> int = "f" "f_nat" + is not included in + external f : int -> (int [@untagged]) = "f" "f_nat" +|}] + module Bad6 : sig external f : (int [@untagged]) -> int = "f" "f_nat" end = struct external f : int -> int = "a" "a_nat" end;; +[%%expect{| +Line 3, characters 6-56: +3 | ......struct +4 | external f : int -> int = "a" "a_nat" +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig external f : int -> int = "a" "a_nat" end + is not included in + sig external f : (int [@untagged]) -> int = "f" "f_nat" end + Values do not match: + external f : int -> int = "a" "a_nat" + is not included in + external f : (int [@untagged]) -> int = "f" "f_nat" +|}] + module Bad7 : sig external f : float -> (float [@unboxed]) = "f" "f_nat" end = struct external f : float -> float = "f" "f_nat" end;; +[%%expect{| +Line 3, characters 6-60: +3 | ......struct +4 | external f : float -> float = "f" "f_nat" +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig external f : float -> float = "f" "f_nat" end + is not included in + sig external f : float -> (float [@unboxed]) = "f" "f_nat" end + Values do not match: + external f : float -> float = "f" "f_nat" + is not included in + external f : float -> (float [@unboxed]) = "f" "f_nat" +|}] + module Bad8 : sig external f : (float [@unboxed]) -> float = "f" "f_nat" end = struct external f : float -> float = "a" "a_nat" end;; +[%%expect{| +Line 3, characters 6-60: +3 | ......struct +4 | external f : float -> float = "a" "a_nat" +5 | end.. +Error: Signature mismatch: + Modules do not match: + sig external f : float -> float = "a" "a_nat" end + is not included in + sig external f : (float [@unboxed]) -> float = "f" "f_nat" end + Values do not match: + external f : float -> float = "a" "a_nat" + is not included in + external f : (float [@unboxed]) -> float = "f" "f_nat" +|}] + (* Bad: unboxed or untagged with the wrong type *) external g : (float [@untagged]) -> float = "g" "g_nat";; +[%%expect{| +Line 1, characters 14-19: +1 | external g : (float [@untagged]) -> float = "g" "g_nat";; + ^^^^^ +Error: Don't know how to untag this type. Only int can be untagged. +|}] external h : (int [@unboxed]) -> float = "h" "h_nat";; +[%%expect{| +Line 1, characters 14-17: +1 | external h : (int [@unboxed]) -> float = "h" "h_nat";; + ^^^ +Error: Don't know how to unbox this type. + Only float, int32, int64 and nativeint can be unboxed. +|}] (* Bad: unboxing the function type *) external i : int -> float [@unboxed] = "i" "i_nat";; +[%%expect{| +Line 1, characters 13-25: +1 | external i : int -> float [@unboxed] = "i" "i_nat";; + ^^^^^^^^^^^^ +Error: Don't know how to unbox this type. + Only float, int32, int64 and nativeint can be unboxed. +|}] (* Bad: unboxing a "deep" sub-type. *) external j : int -> (float [@unboxed]) * float = "j" "j_nat";; +[%%expect{| +Line 1, characters 21-26: +1 | external j : int -> (float [@unboxed]) * float = "j" "j_nat";; + ^^^^^ +Error: The attribute '@unboxed' should be attached to + a direct argument or result of the primitive, + it should not occur deeply into its type. +|}] (* This should be rejected, but it is quite complicated to do in the current state of things *) external k : int -> (float [@unboxd]) = "k" "k_nat";; +[%%expect{| +external k : int -> float = "k" "k_nat" +|}] (* Bad: old style annotations + new style attributes *) external l : float -> float = "l" "l_nat" "float" [@@unboxed];; +[%%expect{| +Line 1, characters 0-61: +1 | external l : float -> float = "l" "l_nat" "float" [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Cannot use "float" in conjunction with [@unboxed]/[@untagged]. +|}] external m : (float [@unboxed]) -> float = "m" "m_nat" "float";; +[%%expect{| +Line 1, characters 0-62: +1 | external m : (float [@unboxed]) -> float = "m" "m_nat" "float";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Cannot use "float" in conjunction with [@unboxed]/[@untagged]. +|}] external n : float -> float = "n" "noalloc" [@@noalloc];; +[%%expect{| +Line 1, characters 0-55: +1 | external n : float -> float = "n" "noalloc" [@@noalloc];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Cannot use "noalloc" in conjunction with [@@noalloc]. +|}] (* Warnings: unboxed / untagged without any native implementation *) external o : (float[@unboxed]) -> float = "o";; +[%%expect{| +Line 1, characters 0-45: +1 | external o : (float[@unboxed]) -> float = "o";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: [@The native code version of the primitive is mandatory + when attributes [@untagged] or [@unboxed] are present. +|}] external p : float -> (float[@unboxed]) = "p";; +[%%expect{| +Line 1, characters 0-45: +1 | external p : float -> (float[@unboxed]) = "p";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: [@The native code version of the primitive is mandatory + when attributes [@untagged] or [@unboxed] are present. +|}] external q : (int[@untagged]) -> float = "q";; +[%%expect{| +Line 1, characters 0-44: +1 | external q : (int[@untagged]) -> float = "q";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: [@The native code version of the primitive is mandatory + when attributes [@untagged] or [@unboxed] are present. +|}] external r : int -> (int[@untagged]) = "r";; +[%%expect{| +Line 1, characters 0-42: +1 | external r : int -> (int[@untagged]) = "r";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: [@The native code version of the primitive is mandatory + when attributes [@untagged] or [@unboxed] are present. +|}] external s : int -> int = "s" [@@untagged];; +[%%expect{| +Line 1, characters 0-42: +1 | external s : int -> int = "s" [@@untagged];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: [@The native code version of the primitive is mandatory + when attributes [@untagged] or [@unboxed] are present. +|}] external t : float -> float = "t" [@@unboxed];; +[%%expect{| +Line 1, characters 0-45: +1 | external t : float -> float = "t" [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: [@The native code version of the primitive is mandatory + when attributes [@untagged] or [@unboxed] are present. +|}] (* PR#7424 *) type 'a b = B of 'a b b [@@unboxed];; +[%%expect{| +type 'a b = B of 'a b b [@@unboxed] +|}] + + +(* MPR#7828 *) +type i = I of int +external id : i -> i = "%identity";; +[%%expect{| +type i = I of int +Line 2, characters 0-34: +2 | external id : i -> i = "%identity";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 61: This primitive declaration uses type i, which is unannotated and +unboxable. The representation of such types may change in future +versions. You should annotate the declaration of i with [@@boxed] +or [@@unboxed]. +external id : i -> i = "%identity" +|}];; + +type i = I of int +type j = J of int +external id : i -> j = "%identity";; +[%%expect{| +type i = I of int +type j = J of int +Line 3, characters 0-34: +3 | external id : i -> j = "%identity";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 61: This primitive declaration uses type i, which is unannotated and +unboxable. The representation of such types may change in future +versions. You should annotate the declaration of i with [@@boxed] +or [@@unboxed]. +Line 3, characters 0-34: +3 | external id : i -> j = "%identity";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 61: This primitive declaration uses type j, which is unannotated and +unboxable. The representation of such types may change in future +versions. You should annotate the declaration of j with [@@boxed] +or [@@unboxed]. +external id : i -> j = "%identity" +|}];; + +type ib = I of int [@@boxed] +external idb : ib -> ib = "%identity";; +[%%expect{| +type ib = I of int +external idb : ib -> ib = "%identity" +|}];; + +type iub = I of int [@@unboxed] +external idub : iub -> iub = "%identity";; +[%%expect{| +type iub = I of int [@@unboxed] +external idub : iub -> iub = "%identity" +|}];; diff --git a/testsuite/tests/typing-unboxed/test.ocaml.reference b/testsuite/tests/typing-unboxed/test.ocaml.reference index 335fed79..e476a629 100644 --- a/testsuite/tests/typing-unboxed/test.ocaml.reference +++ b/testsuite/tests/typing-unboxed/test.ocaml.reference @@ -10,27 +10,27 @@ module M : external a : int -> (int [@untagged]) = "a" "a_nat" external b : (int [@untagged]) -> int = "b" "b_nat" end -Characters 382-451: +Line 12, characters 2-71: external f : (int32 [@unboxed]) -> (int32 [@unboxed]) = "f" "noalloc" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The native code version of the primitive is mandatory when attributes [@untagged] or [@unboxed] are present -Characters 63-122: +Line 4, characters 2-61: external a : float -> float = "a" "noalloc" "a_nat" "float" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 3: deprecated: [@@unboxed] + [@@noalloc] should be used instead of "float" -Characters 125-176: +Alert deprecated: [@@unboxed] + [@@noalloc] should be used instead of "float" +Line 5, characters 2-53: external b : float -> float = "b" "noalloc" "b_nat" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 3: deprecated: [@@noalloc] should be used instead of "noalloc" -Characters 179-228: +Alert deprecated: [@@noalloc] should be used instead of "noalloc" +Line 6, characters 2-51: external c : float -> float = "c" "c_nat" "float" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 3: deprecated: [@@unboxed] + [@@noalloc] should be used instead of "float" -Characters 231-274: +Alert deprecated: [@@unboxed] + [@@noalloc] should be used instead of "float" +Line 7, characters 2-45: external d : float -> float = "d" "noalloc" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 3: deprecated: [@@noalloc] should be used instead of "noalloc" -Characters 441-505: +Alert deprecated: [@@noalloc] should be used instead of "noalloc" +Line 15, characters 6-70: ......struct external f : int -> (int [@untagged]) = "f" "f_nat" end.. @@ -43,7 +43,7 @@ Error: Signature mismatch: external f : int -> (int [@untagged]) = "f" "f_nat" is not included in external f : int -> int = "f" "f_nat" -Characters 65-129: +Line 4, characters 6-70: ......struct external f : (int [@untagged]) -> int = "f" "f_nat" end.. @@ -56,7 +56,7 @@ Error: Signature mismatch: external f : (int [@untagged]) -> int = "f" "f_nat" is not included in external f : int -> int = "a" "a_nat" -Characters 69-136: +Line 4, characters 6-73: ......struct external f : float -> (float [@unboxed]) = "f" "f_nat" end.. @@ -69,7 +69,7 @@ Error: Signature mismatch: external f : float -> (float [@unboxed]) = "f" "f_nat" is not included in external f : float -> float = "f" "f_nat" -Characters 69-136: +Line 4, characters 6-73: ......struct external f : (float [@unboxed]) -> float = "f" "f_nat" end.. @@ -82,7 +82,7 @@ Error: Signature mismatch: external f : (float [@unboxed]) -> float = "f" "f_nat" is not included in external f : float -> float = "a" "a_nat" -Characters 149-199: +Line 6, characters 6-56: ......struct external f : int -> int = "f" "f_nat" end.. @@ -95,7 +95,7 @@ Error: Signature mismatch: external f : int -> int = "f" "f_nat" is not included in external f : int -> (int [@untagged]) = "f" "f_nat" -Characters 79-129: +Line 4, characters 6-56: ......struct external f : int -> int = "a" "a_nat" end.. @@ -108,7 +108,7 @@ Error: Signature mismatch: external f : int -> int = "a" "a_nat" is not included in external f : (int [@untagged]) -> int = "f" "f_nat" -Characters 82-136: +Line 4, characters 6-60: ......struct external f : float -> float = "f" "f_nat" end.. @@ -121,7 +121,7 @@ Error: Signature mismatch: external f : float -> float = "f" "f_nat" is not included in external f : float -> (float [@unboxed]) = "f" "f_nat" -Characters 82-136: +Line 4, characters 6-60: ......struct external f : float -> float = "a" "a_nat" end.. @@ -134,56 +134,56 @@ Error: Signature mismatch: external f : float -> float = "a" "a_nat" is not included in external f : (float [@unboxed]) -> float = "f" "f_nat" -Characters 67-72: +Line 4, characters 14-19: external g : (float [@untagged]) -> float = "g" "g_nat";; ^^^^^ Error: Don't know how to untag this type. Only int can be untagged -Characters 14-17: +Line 1, characters 14-17: external h : (int [@unboxed]) -> float = "h" "h_nat";; ^^^ Error: Don't know how to unbox this type. Only float, int32, int64 and nativeint can be unboxed -Characters 52-64: +Line 3, characters 13-25: external i : int -> float [@unboxed] = "i" "i_nat";; ^^^^^^^^^^^^ Error: Don't know how to unbox this type. Only float, int32, int64 and nativeint can be unboxed -Characters 61-66: +Line 3, characters 21-26: external j : int -> (float [@unboxed]) * float = "j" "j_nat";; ^^^^^ Error: The attribute '@unboxed' should be attached to a direct argument or result of the primitive, it should not occur deeply into its type external k : int -> float = "k" "k_nat" -Characters 58-119: +Line 4, characters 0-61: external l : float -> float = "l" "l_nat" "float" [@@unboxed];; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Cannot use "float" in conjunction with [@unboxed]/[@untagged] -Characters 0-62: +Line 1, characters 0-62: external m : (float [@unboxed]) -> float = "m" "m_nat" "float";; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Cannot use "float" in conjunction with [@unboxed]/[@untagged] -Characters 0-55: +Line 1, characters 0-55: external n : float -> float = "n" "noalloc" [@@noalloc];; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Cannot use "noalloc" in conjunction with [@@noalloc] -Characters 70-115: +Line 3, characters 0-45: external o : (float[@unboxed]) -> float = "o";; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The native code version of the primitive is mandatory when attributes [@untagged] or [@unboxed] are present -Characters 0-45: +Line 1, characters 0-45: external p : float -> (float[@unboxed]) = "p";; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The native code version of the primitive is mandatory when attributes [@untagged] or [@unboxed] are present -Characters 0-44: +Line 1, characters 0-44: external q : (int[@untagged]) -> float = "q";; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The native code version of the primitive is mandatory when attributes [@untagged] or [@unboxed] are present -Characters 0-42: +Line 1, characters 0-42: external r : int -> (int[@untagged]) = "r";; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The native code version of the primitive is mandatory when attributes [@untagged] or [@unboxed] are present -Characters 0-42: +Line 1, characters 0-42: external s : int -> int = "s" [@@untagged];; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The native code version of the primitive is mandatory when attributes [@untagged] or [@unboxed] are present -Characters 0-45: +Line 1, characters 0-45: external t : float -> float = "t" [@@unboxed];; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The native code version of the primitive is mandatory when attributes [@untagged] or [@unboxed] are present diff --git a/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.compilers.reference b/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.compilers.reference deleted file mode 100644 index f0b7dc59..00000000 --- a/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.compilers.reference +++ /dev/null @@ -1,163 +0,0 @@ -- : unit = () - -<---------------------------------------------------------------------- -To check the result file for this test, it suffices to look for "val" -lines corresponding to toplevel answers. If they start with - - val ambiguous_... - -then just above there should be the warning text for Warning 57 -(we try to avoid all other warnings). If they start with - - val not_ambiguous_... - -then just above there should be *no* warning text. -----------------------------------------------------------------------> - -type expr = Val of int | Rest -Characters 46-71: - | ((Val x, _) | (_, Val x)) when x < 0 -> () - ^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 57: Ambiguous or-pattern variables under guard; -variable x may match different arguments. (See manual section 9.5) -val ambiguous_typical_example : expr * expr -> unit = -Note that an Assert_failure is expected just below. -Exception: Assert_failure ("//toplevel//", 30, 6). -val not_ambiguous__no_orpat : int option -> unit = -val not_ambiguous__no_guard : [< `A | `B | `C ] -> unit = -val not_ambiguous__no_patvar_in_guard : - bool -> [> `B of 'a | `C of 'a ] -> unit = -val not_ambiguous__disjoint_cases : [> `B of bool | `C of bool ] -> unit = - -val not_ambiguous__prefix_variables : - [> `B of bool * 'a option * 'a option ] -> unit = -Characters 33-72: - | (`B (x, _, Some y) | `B (x, Some y, _)) when y -> ignore x - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 57: Ambiguous or-pattern variables under guard; -variable y may match different arguments. (See manual section 9.5) -val ambiguous__y : [> `B of 'a * bool option * bool option ] -> unit = -val not_ambiguous__rhs_not_protected : - [> `B of 'a * bool option * bool option ] -> unit = -Characters 35-74: - | (`B (x, _, Some y) | `B (x, Some y, _)) when x < y -> () - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 57: Ambiguous or-pattern variables under guard; -variable y may match different arguments. (See manual section 9.5) -val ambiguous__x_y : [> `B of 'a * 'a option * 'a option ] -> unit = -Characters 37-76: - | (`B (x, z, Some y) | `B (x, Some y, z)) when x < y || Some x = z -> () - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 57: Ambiguous or-pattern variables under guard; -variables y,z may match different arguments. (See manual section 9.5) -val ambiguous__x_y_z : [> `B of 'a * 'a option * 'a option ] -> unit = -val not_ambiguous__disjoint_in_depth : - [> `A of [> `B of bool | `C of bool ] ] -> unit = -val not_ambiguous__prefix_variables_in_depth : - [> `A of [> `B of bool * [> `C1 | `C2 ] ] ] -> unit = -Characters 40-76: - | `A (`B (Some x, _) | `B (_, Some x)) when x -> () - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 57: Ambiguous or-pattern variables under guard; -variable x may match different arguments. (See manual section 9.5) -val ambiguous__in_depth : - [> `A of [> `B of bool option * bool option ] ] -> unit = -val not_ambiguous__several_orpats : - [> `A of - [> `B of 'a * 'b option * 'c option ] * - [> `C of 'a * 'd option * 'e option ] * - [> `D1 of 'f * 'a * 'g option * 'h | `D2 of 'i * 'a * 'j * 'k option ] ] -> - unit = -Characters 43-140: - ....`A ((`B (Some x, _) | `B (_, Some x)), - (`C (Some y, Some _, _) | `C (Some y, _, Some _)))................. -Warning 57: Ambiguous or-pattern variables under guard; -variable x may match different arguments. (See manual section 9.5) -val ambiguous__first_orpat : - [> `A of - [> `B of 'a option * 'a option ] * - [> `C of 'a option * 'b option * 'c option ] ] -> - unit = -Characters 44-141: - ....`A ((`B (Some x, Some _, _) | `B (Some x, _, Some _)), - (`C (Some y, _) | `C (_, Some y)))................. -Warning 57: Ambiguous or-pattern variables under guard; -variable y may match different arguments. (See manual section 9.5) -val ambiguous__second_orpat : - [> `A of - [> `B of 'a option * 'b option * 'c option ] * - [> `C of 'a option * 'a option ] ] -> - unit = -val not_ambiguous__pairs : bool * 'a option * 'b option -> unit = -val not_ambiguous__vars : bool -> unit = -val not_ambiguous__as : - ('a list * 'b list -> bool) -> 'a list * 'b list -> unit = -val not_ambiguous__as_var : ('a list * 'b -> bool) -> 'a list * 'b -> unit = - -val not_ambiguous__var_as : - ('a list * 'b -> bool) -> ('a list * 'b) * 'c option * 'd option -> unit = - -val not_ambiguous__lazy : ('a list * 'b list) * bool lazy_t -> unit = -type t = A of int * int option * int option | B -val not_ambiguous__constructor : t -> unit = -type amoi = Z of int | Y of int * int | X of amoi * amoi -Characters 40-73: - ..X (Z x,Y (y,0)) - | X (Z y,Y (x,_)) -Warning 57: Ambiguous or-pattern variables under guard; -variables x,y may match different arguments. (See manual section 9.5) -val ambiguous__amoi : amoi -> int = -module type S = sig val b : bool end -Characters 56-101: - ....(module M:S),_,(1,_) - | _,(module M:S),(_,1)................... -Warning 57: Ambiguous or-pattern variables under guard; -variable M may match different arguments. (See manual section 9.5) -val ambiguous__module_variable : - (module S) * (module S) * (int * int) -> bool -> int = -val not_ambiguous__module_variable : - (module S) * (module S) * (int * int) -> bool -> int = -type t2 = A of int * int | B of int * int -Characters 55-56: - | A (x as z,(0 as y))|A (0 as y as z,x)|B (x,(y as z)) when g x (y+z) -> 1 - ^ -Warning 41: A belongs to several types: t2 t -The first one was selected. Please disambiguate if this is wrong. -Characters 42-138: - .........................................function - | A (x as z,(0 as y))|A (0 as y as z,x)|B (x,(y as z)) when g x (y+z) -> 1 - | _ -> 2 -Warning 4: this pattern-matching is fragile. -It will remain exhaustive when constructors are added to type t2. -Characters 55-107: - | A (x as z,(0 as y))|A (0 as y as z,x)|B (x,(y as z)) when g x (y+z) -> 1 - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 57: Ambiguous or-pattern variables under guard; -variables x,y may match different arguments. (See manual section 9.5) -val ambiguous_xy_but_not_ambiguous_z : (int -> int -> bool) -> t2 -> int = - -val not_ambiguous__as_disjoint_on_second_column_split : - int option * int -> unit = -no warning below -val solved_ambiguity_typical_example : expr * expr -> unit = -yet a warning below -Characters 164-189: - | ((Val y, _) | (_, Val y)) when y < 0 -> () - ^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 57: Ambiguous or-pattern variables under guard; -variable y may match different arguments. (See manual section 9.5) -val guarded_ambiguity : expr * expr -> unit = -type a = A1 | A2 -type 'a alg = Val of 'a | Binop of 'a alg * 'a alg -warning below -Characters 100-125: - | ((Val x, _) | (_, Val x)) when pred x -> () - ^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 57: Ambiguous or-pattern variables under guard; -variable x may match different arguments. (See manual section 9.5) -val cmp : (a -> bool) -> a alg -> a alg -> unit = -type a = A1 -type 'a alg = Val of 'a | Binop of 'a alg * 'a alg -no warning below -val cmp : (a -> bool) -> a alg -> a alg -> unit = - diff --git a/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml b/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml index 9570afd2..3a8d5a01 100644 --- a/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml +++ b/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml @@ -1,29 +1,18 @@ (* TEST flags = " -w A -strict-sequence " - * toplevel + * expect *) (* Ignore OCAMLRUNPARAM=b to be reproducible *) Printexc.record_backtrace false;; - -let () = print_endline "\n\ - <----------------------------------------------------------------------\n\ - To check the result file for this test, it suffices to look for \"val\"\n\ - lines corresponding to toplevel answers. If they start with\n\ - \n\ - \ val ambiguous_...\n\ - \n\ - then just above there should be the warning text for Warning 57\n\ - (we try to avoid all other warnings). If they start with\n\ - \n\ - \ val not_ambiguous_...\n\ - \n\ - then just above there should be *no* warning text.\n\ - ---------------------------------------------------------------------->\n\ -";; - +[%%expect {| +- : unit = () +|}] type expr = Val of int | Rest;; +[%%expect {| +type expr = Val of int | Rest +|}] let ambiguous_typical_example = function | ((Val x, _) | (_, Val x)) when x < 0 -> () @@ -34,31 +23,55 @@ let ambiguous_typical_example = function (* to hold here, but it is wrong! *) () ;; +[%%expect {| +Line 2, characters 4-29: +2 | | ((Val x, _) | (_, Val x)) when x < 0 -> () + ^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 57: Ambiguous or-pattern variables under guard; +variable x may match different arguments. (See manual section 9.5) +val ambiguous_typical_example : expr * expr -> unit = +|}] -let () = print_endline "Note that an Assert_failure is expected just below.";; let fails = ambiguous_typical_example (Val 2, Val (-1)) ;; +[%%expect {| +Exception: Assert_failure ("", 6, 6). +|}] let not_ambiguous__no_orpat = function | Some x when x > 0 -> () | Some _ -> () | None -> () ;; +[%%expect {| +val not_ambiguous__no_orpat : int option -> unit = +|}] let not_ambiguous__no_guard = function | `A -> () | (`B | `C) -> () ;; +[%%expect {| +val not_ambiguous__no_guard : [< `A | `B | `C ] -> unit = +|}] let not_ambiguous__no_patvar_in_guard b = function | (`B x | `C x) when b -> ignore x | _ -> () ;; +[%%expect {| +val not_ambiguous__no_patvar_in_guard : + bool -> [> `B of 'a | `C of 'a ] -> unit = +|}] let not_ambiguous__disjoint_cases = function | (`B x | `C x) when x -> () | _ -> () ;; +[%%expect {| +val not_ambiguous__disjoint_cases : [> `B of bool | `C of bool ] -> unit = + +|}] (* the curious (..., _, Some _) | (..., Some _, _) device used in those tests serves to avoid warning 12 (this sub-pattern @@ -68,11 +81,23 @@ let not_ambiguous__prefix_variables = function | (`B (x, _, Some y) | `B (x, Some y, _)) when x -> ignore y | _ -> () ;; +[%%expect {| +val not_ambiguous__prefix_variables : + [> `B of bool * 'a option * 'a option ] -> unit = +|}] let ambiguous__y = function | (`B (x, _, Some y) | `B (x, Some y, _)) when y -> ignore x | _ -> () ;; +[%%expect {| +Line 2, characters 4-43: +2 | | (`B (x, _, Some y) | `B (x, Some y, _)) when y -> ignore x + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 57: Ambiguous or-pattern variables under guard; +variable y may match different arguments. (See manual section 9.5) +val ambiguous__y : [> `B of 'a * bool option * bool option ] -> unit = +|}] (* it should be understood that the ambiguity warning only protects (p | q) when guard -> ... @@ -87,31 +112,68 @@ let not_ambiguous__rhs_not_protected = function | (`B (x, _, Some y) | `B (x, Some y, _)) -> if y then ignore x else () | _ -> () ;; +[%%expect {| +val not_ambiguous__rhs_not_protected : + [> `B of 'a * bool option * bool option ] -> unit = +|}] let ambiguous__x_y = function | (`B (x, _, Some y) | `B (x, Some y, _)) when x < y -> () | _ -> () ;; +[%%expect {| +Line 2, characters 4-43: +2 | | (`B (x, _, Some y) | `B (x, Some y, _)) when x < y -> () + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 57: Ambiguous or-pattern variables under guard; +variable y may match different arguments. (See manual section 9.5) +val ambiguous__x_y : [> `B of 'a * 'a option * 'a option ] -> unit = +|}] let ambiguous__x_y_z = function | (`B (x, z, Some y) | `B (x, Some y, z)) when x < y || Some x = z -> () | _ -> () ;; +[%%expect {| +Line 2, characters 4-43: +2 | | (`B (x, z, Some y) | `B (x, Some y, z)) when x < y || Some x = z -> () + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 57: Ambiguous or-pattern variables under guard; +variables y,z may match different arguments. (See manual section 9.5) +val ambiguous__x_y_z : [> `B of 'a * 'a option * 'a option ] -> unit = +|}] let not_ambiguous__disjoint_in_depth = function | `A (`B x | `C x) when x -> () | _ -> () ;; +[%%expect {| +val not_ambiguous__disjoint_in_depth : + [> `A of [> `B of bool | `C of bool ] ] -> unit = +|}] let not_ambiguous__prefix_variables_in_depth = function | `A (`B (x, `C1) | `B (x, `C2)) when x -> () | _ -> () ;; +[%%expect {| +val not_ambiguous__prefix_variables_in_depth : + [> `A of [> `B of bool * [> `C1 | `C2 ] ] ] -> unit = +|}] let ambiguous__in_depth = function | `A (`B (Some x, _) | `B (_, Some x)) when x -> () | _ -> () ;; +[%%expect {| +Line 2, characters 4-40: +2 | | `A (`B (Some x, _) | `B (_, Some x)) when x -> () + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 57: Ambiguous or-pattern variables under guard; +variable x may match different arguments. (See manual section 9.5) +val ambiguous__in_depth : + [> `A of [> `B of bool option * bool option ] ] -> unit = +|}] let not_ambiguous__several_orpats = function | `A ((`B (x, Some _, _) | `B (x, _, Some _)), @@ -120,24 +182,59 @@ let not_ambiguous__several_orpats = function () | _ -> () ;; +[%%expect {| +val not_ambiguous__several_orpats : + [> `A of + [> `B of 'a * 'b option * 'c option ] * + [> `C of 'a * 'd option * 'e option ] * + [> `D1 of 'f * 'a * 'g option * 'h | `D2 of 'i * 'a * 'j * 'k option ] + ] -> unit = +|}] let ambiguous__first_orpat = function | `A ((`B (Some x, _) | `B (_, Some x)), (`C (Some y, Some _, _) | `C (Some y, _, Some _))) when x < y -> () | _ -> () ;; +[%%expect {| +Line 2, characters 4-101: +2 | ....`A ((`B (Some x, _) | `B (_, Some x)), +3 | (`C (Some y, Some _, _) | `C (Some y, _, Some _)))................. +Warning 57: Ambiguous or-pattern variables under guard; +variable x may match different arguments. (See manual section 9.5) +val ambiguous__first_orpat : + [> `A of + [> `B of 'a option * 'a option ] * + [> `C of 'a option * 'b option * 'c option ] ] -> + unit = +|}] let ambiguous__second_orpat = function | `A ((`B (Some x, Some _, _) | `B (Some x, _, Some _)), (`C (Some y, _) | `C (_, Some y))) when x < y -> () | _ -> () ;; +[%%expect {| +Line 2, characters 4-101: +2 | ....`A ((`B (Some x, Some _, _) | `B (Some x, _, Some _)), +3 | (`C (Some y, _) | `C (_, Some y)))................. +Warning 57: Ambiguous or-pattern variables under guard; +variable y may match different arguments. (See manual section 9.5) +val ambiguous__second_orpat : + [> `A of + [> `B of 'a option * 'b option * 'c option ] * + [> `C of 'a option * 'a option ] ] -> + unit = +|}] (* check that common prefixes work as expected *) let not_ambiguous__pairs = function | (x, Some _, _) | (x, _, Some _) when x -> () | _ -> () ;; +[%%expect {| +val not_ambiguous__pairs : bool * 'a option * 'b option -> unit = +|}] let not_ambiguous__vars = begin[@warning "-12"] function @@ -145,38 +242,64 @@ let not_ambiguous__vars = | _ -> () end ;; +[%%expect {| +val not_ambiguous__vars : bool -> unit = +|}] let not_ambiguous__as p = function | (([], _) as x | ((_, []) as x)) when p x -> () | _ -> () ;; +[%%expect {| +val not_ambiguous__as : + ('a list * 'b list -> bool) -> 'a list * 'b list -> unit = +|}] let not_ambiguous__as_var p = function | (([], _) as x | x) when p x -> () | _ -> () ;; +[%%expect {| +val not_ambiguous__as_var : ('a list * 'b -> bool) -> 'a list * 'b -> unit = + +|}] let not_ambiguous__var_as p = function | (x, Some _, _) | (([], _) as x, _, Some _) when p x -> () | _ -> () ;; +[%%expect {| +val not_ambiguous__var_as : + ('a list * 'b -> bool) -> ('a list * 'b) * 'c option * 'd option -> unit = + +|}] let not_ambiguous__lazy = function | (([], _), lazy x) | ((_, []), lazy x) when x -> () | _ -> () - ;; +[%%expect {| +val not_ambiguous__lazy : ('a list * 'b list) * bool lazy_t -> unit = +|}] type t = A of int * int option * int option | B;; +[%%expect {| +type t = A of int * int option * int option | B +|}] let not_ambiguous__constructor = function | A (x, Some _, _) | A (x, _, Some _) when x > 0 -> () | A _ | B -> () ;; - +[%%expect {| +val not_ambiguous__constructor : t -> unit = +|}] type amoi = Z of int | Y of int * int | X of amoi * amoi ;; +[%%expect {| +type amoi = Z of int | Y of int * int | X of amoi * amoi +|}] let ambiguous__amoi a = match a with | X (Z x,Y (y,0)) @@ -184,31 +307,78 @@ let ambiguous__amoi a = match a with when x+y > 0 -> 0 | X _|Y _|Z _ -> 1 ;; +[%%expect {| +Line 2, characters 2-35: +2 | ..X (Z x,Y (y,0)) +3 | | X (Z y,Y (x,_)) +Warning 57: Ambiguous or-pattern variables under guard; +variables x,y may match different arguments. (See manual section 9.5) +val ambiguous__amoi : amoi -> int = +|}] module type S = sig val b : bool end ;; +[%%expect {| +module type S = sig val b : bool end +|}] let ambiguous__module_variable x b = match x with | (module M:S),_,(1,_) | _,(module M:S),(_,1) when M.b && b -> 1 | _ -> 2 ;; +[%%expect {| +Line 2, characters 4-49: +2 | ....(module M:S),_,(1,_) +3 | | _,(module M:S),(_,1)................... +Warning 57: Ambiguous or-pattern variables under guard; +variable M may match different arguments. (See manual section 9.5) +val ambiguous__module_variable : + (module S) * (module S) * (int * int) -> bool -> int = +|}] let not_ambiguous__module_variable x b = match x with | (module M:S),_,(1,_) | _,(module M:S),(_,1) when b -> 1 | _ -> 2 ;; +[%%expect {| +val not_ambiguous__module_variable : + (module S) * (module S) * (int * int) -> bool -> int = +|}] (* Mixed case *) type t2 = A of int * int | B of int * int ;; +[%%expect {| +type t2 = A of int * int | B of int * int +|}] let ambiguous_xy_but_not_ambiguous_z g = function | A (x as z,(0 as y))|A (0 as y as z,x)|B (x,(y as z)) when g x (y+z) -> 1 | _ -> 2 ;; +[%%expect {| +Line 2, characters 4-5: +2 | | A (x as z,(0 as y))|A (0 as y as z,x)|B (x,(y as z)) when g x (y+z) -> 1 + ^ +Warning 41: A belongs to several types: t2 t +The first one was selected. Please disambiguate if this is wrong. +Line 1, characters 41-137: +1 | .........................................function +2 | | A (x as z,(0 as y))|A (0 as y as z,x)|B (x,(y as z)) when g x (y+z) -> 1 +3 | | _ -> 2 +Warning 4: this pattern-matching is fragile. +It will remain exhaustive when constructors are added to type t2. +Line 2, characters 4-56: +2 | | A (x as z,(0 as y))|A (0 as y as z,x)|B (x,(y as z)) when g x (y+z) -> 1 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 57: Ambiguous or-pattern variables under guard; +variables x,y may match different arguments. (See manual section 9.5) +val ambiguous_xy_but_not_ambiguous_z : (int -> int -> bool) -> t2 -> int = + +|}] (* Regression test against an erroneous simplification of the algorithm @@ -223,8 +393,11 @@ let not_ambiguous__as_disjoint_on_second_column_split = function | ((Some a, (1 as b)) | (Some b, (2 as a))) when a = 0 -> ignore a; ignore b | _ -> () ;; +[%%expect {| +val not_ambiguous__as_disjoint_on_second_column_split : + int option * int -> unit = +|}] -let () = print_endline "no warning below";; (* we check for the ambiguous case first, so there is no warning *) let solved_ambiguity_typical_example = function @@ -240,8 +413,10 @@ let solved_ambiguity_typical_example = function (* to hold here. *) () ;; +[%%expect {| +val solved_ambiguity_typical_example : expr * expr -> unit = +|}] -let () = print_endline "yet a warning below";; (* if the check for the ambiguous case is guarded, there is still a warning *) let guarded_ambiguity = function @@ -254,15 +429,28 @@ let guarded_ambiguity = function (* to hold here. *) () ;; +[%%expect {| +Line 3, characters 4-29: +3 | | ((Val y, _) | (_, Val y)) when y < 0 -> () + ^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 57: Ambiguous or-pattern variables under guard; +variable y may match different arguments. (See manual section 9.5) +val guarded_ambiguity : expr * expr -> unit = +|}] (* see GPR#1552 *) type a = A1 | A2;; +[%%expect {| +type a = A1 | A2 +|}] type 'a alg = | Val of 'a | Binop of 'a alg * 'a alg;; +[%%expect {| +type 'a alg = Val of 'a | Binop of 'a alg * 'a alg +|}] -let () = print_endline "warning below";; let cmp (pred : a -> bool) (x : a alg) (y : a alg) = match x, y with | Val A1, Val A1 -> () @@ -270,14 +458,27 @@ let cmp (pred : a -> bool) (x : a alg) (y : a alg) = (* below: silence exhaustiveness/fragility warnings *) | (Val (A1 | A2) | Binop _), _ -> () ;; +[%%expect {| +Line 4, characters 4-29: +4 | | ((Val x, _) | (_, Val x)) when pred x -> () + ^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 57: Ambiguous or-pattern variables under guard; +variable x may match different arguments. (See manual section 9.5) +val cmp : (a -> bool) -> a alg -> a alg -> unit = +|}] type a = A1;; +[%%expect {| +type a = A1 +|}] type 'a alg = | Val of 'a | Binop of 'a alg * 'a alg;; +[%%expect {| +type 'a alg = Val of 'a | Binop of 'a alg * 'a alg +|}] -let () = print_endline "no warning below";; let cmp (pred : a -> bool) (x : a alg) (y : a alg) = match x, y with | Val A1, Val A1 -> () @@ -285,3 +486,6 @@ let cmp (pred : a -> bool) (x : a alg) (y : a alg) = (* below: silence exhaustiveness/fragility warnings *) | (Val A1 | Binop _), _ -> () ;; +[%%expect {| +val cmp : (a -> bool) -> a alg -> a alg -> unit = +|}] diff --git a/testsuite/tests/typing-warnings/application.compilers.reference b/testsuite/tests/typing-warnings/application.compilers.reference deleted file mode 100644 index f5ec668b..00000000 --- a/testsuite/tests/typing-warnings/application.compilers.reference +++ /dev/null @@ -1,13 +0,0 @@ -- : unit = () -Characters 16-19: - let _ = ignore (+);; - ^^^ -Warning 5: this function application is partial, -maybe some arguments are missing. -- : unit = () -Characters 19-20: - let _ = raise Exit 3;; - ^ -Warning 20: this argument will not be used by the function. -Exception: Stdlib.Pervasives.Exit. - diff --git a/testsuite/tests/typing-warnings/application.ml b/testsuite/tests/typing-warnings/application.ml index 0232adc9..6a5105f7 100644 --- a/testsuite/tests/typing-warnings/application.ml +++ b/testsuite/tests/typing-warnings/application.ml @@ -1,10 +1,86 @@ (* TEST flags = " -w A -strict-sequence " - * toplevel + * expect *) (* Ignore OCAMLRUNPARAM=b to be reproducible *) Printexc.record_backtrace false;; +[%%expect {| +- : unit = () +|}] + +let _ = Array.get;; +[%%expect {| +- : 'a array -> int -> 'a = +|}] + +let _ = Array.get [||];; +[%%expect {| +Line 1, characters 8-22: +1 | let _ = Array.get [||];; + ^^^^^^^^^^^^^^ +Warning 5: this function application is partial, +maybe some arguments are missing. +- : int -> 'a = +|}] + +let () = ignore Array.get;; +[%%expect {| +|}] + +let () = ignore (Array.get [||]);; +[%%expect {| +Line 1, characters 16-32: +1 | let () = ignore (Array.get [||]);; + ^^^^^^^^^^^^^^^^ +Warning 5: this function application is partial, +maybe some arguments are missing. +|}] + + +let _ = if true then Array.get else (fun _ _ -> 12);; +[%%expect {| +- : int array -> int -> int = +|}] + +let _ = if true then Array.get [||] else (fun _ -> 12);; +[%%expect {| +Line 1, characters 21-35: +1 | let _ = if true then Array.get [||] else (fun _ -> 12);; + ^^^^^^^^^^^^^^ +Warning 5: this function application is partial, +maybe some arguments are missing. +- : int -> int = +|}] + +let _ = (if true then Array.get [||] else (fun _ -> 12) : _ -> _);; +[%%expect {| +- : int -> int = +|}] + +type t = {r: int -> int -> int} + +let f x = let _ = x.r in ();; +[%%expect {| +type t = { r : int -> int -> int; } +val f : t -> unit = +|}] + +let f x = let _ = x.r 1 in ();; +[%%expect {| +Line 1, characters 18-23: +1 | let f x = let _ = x.r 1 in ();; + ^^^^^ +Warning 5: this function application is partial, +maybe some arguments are missing. +val f : t -> unit = +|}] -let _ = ignore (+);; let _ = raise Exit 3;; +[%%expect {| +Line 1, characters 19-20: +1 | let _ = raise Exit 3;; + ^ +Warning 20: this argument will not be used by the function. +Exception: Stdlib.Exit. +|}] diff --git a/testsuite/tests/typing-warnings/coercions.compilers.principal.reference b/testsuite/tests/typing-warnings/coercions.compilers.principal.reference deleted file mode 100644 index cbc423c7..00000000 --- a/testsuite/tests/typing-warnings/coercions.compilers.principal.reference +++ /dev/null @@ -1,25 +0,0 @@ -Characters 168-171: - fun b -> if b then format_of_string "x" else "y";; - ^^^ -Warning 18: this coercion to format6 is not principal. -- : bool -> ('a, 'b, 'c, 'd, 'd, 'a) format6 = -Characters 28-48: - fun b -> if b then "x" else format_of_string "y";; - ^^^^^^^^^^^^^^^^^^^^ -Error: This expression has type - ('a, 'b, 'c, 'd, 'd, 'a) format6 = - ('a, 'b, 'c, 'd, 'd, 'a) CamlinternalFormatBasics.format6 - but an expression was expected of type string -- : bool -> ('a, 'b, 'a) format = -module PR7135 : - sig - module M : sig type t = private int end - type t = M.t - val lift2 : (int -> int -> int) -> t -> t -> int - end -Characters 133-143: - let f x = let y = if true then x else (x:t) in (y :> int) - ^^^^^^^^^^ -Warning 18: this ground coercion is not principal. -module Test1 : sig type t = private int val f : t -> int end - diff --git a/testsuite/tests/typing-warnings/coercions.compilers.reference b/testsuite/tests/typing-warnings/coercions.compilers.reference deleted file mode 100644 index 84136fe0..00000000 --- a/testsuite/tests/typing-warnings/coercions.compilers.reference +++ /dev/null @@ -1,17 +0,0 @@ -- : bool -> ('a, 'b, 'c, 'd, 'd, 'a) format6 = -Characters 28-48: - fun b -> if b then "x" else format_of_string "y";; - ^^^^^^^^^^^^^^^^^^^^ -Error: This expression has type - ('a, 'b, 'c, 'd, 'd, 'a) format6 = - ('a, 'b, 'c, 'd, 'd, 'a) CamlinternalFormatBasics.format6 - but an expression was expected of type string -- : bool -> ('a, 'b, 'a) format = -module PR7135 : - sig - module M : sig type t = private int end - type t = M.t - val lift2 : (int -> int -> int) -> t -> t -> int - end -module Test1 : sig type t = private int val f : t -> int end - diff --git a/testsuite/tests/typing-warnings/coercions.ml b/testsuite/tests/typing-warnings/coercions.ml index 69e17138..ac238bef 100644 --- a/testsuite/tests/typing-warnings/coercions.ml +++ b/testsuite/tests/typing-warnings/coercions.ml @@ -1,14 +1,39 @@ (* TEST flags = " -w A -strict-sequence " - * toplevel - * toplevel with principal + * expect *) (* comment 9644 of PR#6000 *) -fun b -> if b then format_of_string "x" else "y";; -fun b -> if b then "x" else format_of_string "y";; -fun b : (_,_,_) format -> if b then "x" else "y";; +fun b -> if b then format_of_string "x" else "y" +[%%expect {| +- : bool -> ('a, 'b, 'c, 'd, 'd, 'a) format6 = +|}, Principal{| +Line 1, characters 45-48: +1 | fun b -> if b then format_of_string "x" else "y" + ^^^ +Warning 18: this coercion to format6 is not principal. +- : bool -> ('a, 'b, 'c, 'd, 'd, 'a) format6 = +|}] +;; + +fun b -> if b then "x" else format_of_string "y" +[%%expect {| +Line 1, characters 28-48: +1 | fun b -> if b then "x" else format_of_string "y" + ^^^^^^^^^^^^^^^^^^^^ +Error: This expression has type + ('a, 'b, 'c, 'd, 'd, 'a) format6 = + ('a, 'b, 'c, 'd, 'd, 'a) CamlinternalFormatBasics.format6 + but an expression was expected of type string +|}] +;; + +fun b : (_,_,_) format -> if b then "x" else "y" +[%%expect {| +- : bool -> ('a, 'b, 'a) format = +|}] +;; (* PR#7135 *) @@ -19,10 +44,27 @@ module PR7135 = struct let lift2 (f : int -> int -> int) (x : t) (y : t) = f (x :> int) (y :> int) end;; +[%%expect {| +module PR7135 : + sig + module M : sig type t = private int end + type t = M.t + val lift2 : (int -> int -> int) -> t -> t -> int + end +|}] -(* exemple of non-ground coercion *) +(* example of non-ground coercion *) module Test1 = struct type t = private int let f x = let y = if true then x else (x:t) in (y :> int) end;; +[%%expect {| +module Test1 : sig type t = private int val f : t -> int end +|}, Principal{| +Line 3, characters 49-59: +3 | let f x = let y = if true then x else (x:t) in (y :> int) + ^^^^^^^^^^ +Warning 18: this ground coercion is not principal. +module Test1 : sig type t = private int val f : t -> int end +|}] diff --git a/testsuite/tests/typing-warnings/exhaustiveness.compilers.reference b/testsuite/tests/typing-warnings/exhaustiveness.compilers.reference deleted file mode 100644 index 03c0fe7c..00000000 --- a/testsuite/tests/typing-warnings/exhaustiveness.compilers.reference +++ /dev/null @@ -1,152 +0,0 @@ -Characters 121-173: - ........function - None, None -> 1 - | Some _, Some _ -> 2.. -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -((Some _, None)|(None, Some _)) -val f : 'a option * 'b option -> int = -type _ t = A : int t | B : bool t | C : char t | D : float t -type (_, _, _, _) u = U : (int, int, int, int) u -type v = E | F | G -Characters 124-205: - .function A, A, A, A, A, A, A, _, U, U -> 1 - | _, _, _, _, _, _, _, G, _, _ -> 1 -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -(A, A, A, A, A, A, B, (E|F), _, _) -Characters 172-200: - | _, _, _, _, _, _, _, G, _, _ -> 1 - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 56: this match case is unreachable. -Consider replacing it with a refutation case ' -> .' -val f : - 'a t * 'b t * 'c t * 'd t * 'e t * 'f t * 'g t * v * ('a, 'b, 'c, 'd) u * - ('e, 'f, 'g, 'g) u -> int = -Characters 40-68: - let f (x : int t) = match x with A -> 1 | _ -> 2;; (* warn *) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 4: this pattern-matching is fragile. -It will remain exhaustive when constructors are added to type t. -Characters 62-63: - let f (x : int t) = match x with A -> 1 | _ -> 2;; (* warn *) - ^ -Warning 56: this match case is unreachable. -Consider replacing it with a refutation case ' -> .' -val f : int t -> int = -Characters 53-54: - let f (x : unit t option) = match x with None -> 1 | _ -> 2 ;; (* warn? *) - ^ -Warning 56: this match case is unreachable. -Consider replacing it with a refutation case ' -> .' -val f : unit t option -> int = -Characters 53-59: - let f (x : unit t option) = match x with None -> 1 | Some _ -> 2 ;; (* warn *) - ^^^^^^ -Warning 56: this match case is unreachable. -Consider replacing it with a refutation case ' -> .' -val f : unit t option -> int = -val f : int t option -> int = -Characters 27-49: - let f (x : int t option) = match x with None -> 1;; (* warn *) - ^^^^^^^^^^^^^^^^^^^^^^ -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -Some A -val f : int t option -> int = -type 'a box = Box of 'a -type 'a pair = { left : 'a; right : 'a; } -Characters 50-69: - let f : (int t box pair * bool) option -> unit = function None -> ();; - ^^^^^^^^^^^^^^^^^^^ -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -Some ({left=Box A; right=Box A}, _) -val f : (int t box pair * bool) option -> unit = -val f : (string t box pair * bool) option -> unit = -Characters 8-39: - let f = function {left=Box 0; _ } -> ();; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -{left=Box 1; _ } -val f : int box pair -> unit = -Characters 8-47: - let f = function {left=Box 0;right=Box 1} -> ();; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -{left=Box 0; right=Box 0} -val f : int box pair -> unit = -type _ t = Int : int t | Bool : bool t -val f : 'a t -> 'a = -val g : int t -> int = -val h : 'a t -> 'a t -> bool = -type (_, _) cmp = Eq : ('a, 'a) cmp | Any : ('a, 'b) cmp -module A : sig type a type b val eq : (a, b) cmp end -Characters 33-51: - let f : (A.a, A.b) cmp -> unit = function Any -> () - ^^^^^^^^^^^^^^^^^^ -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -Eq -val f : (A.a, A.b) cmp -> unit = -val deep : char t option -> char = -type zero = Zero -type _ succ = Succ -type (_, _, _) plus = - Plus0 : (zero, 'a, 'a) plus - | PlusS : ('a, 'b, 'c) plus -> ('a succ, 'b, 'c succ) plus -val trivial : (zero succ, zero, zero) plus option -> bool = -val easy : (zero, zero succ, zero) plus option -> bool = -Characters 71-93: - function None -> false - ^^^^^^^^^^^^^^^^^^^^^^ -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -Some (PlusS _) -val harder : (zero succ, zero succ, zero succ) plus option -> bool = -val harder : (zero succ, zero succ, zero succ) plus option -> bool = -val inv_zero : ('a, 'b, 'c) plus -> ('c, 'd, zero) plus -> bool = -type _ t = Int : int t -val f : bool t -> 'a = -Characters 54-55: - let f () = match None with _ -> .;; (* error *) - ^ -Error: This match case could not be refuted. - Here is an example of a value that would reach it: _ -Characters 47-48: - let g () = match None with _ -> () | exception _ -> .;; (* error *) - ^ -Error: This match case could not be refuted. - Here is an example of a value that would reach it: _ -Characters 27-28: - let h () = match None with _ -> . | exception _ -> .;; (* error *) - ^ -Error: This match case could not be refuted. - Here is an example of a value that would reach it: _ -val f : 'a option -> unit = -Characters 47-77: - let f x y = match 1 with 1 when x = y -> 1;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 8: this pattern-matching is not exhaustive. -All clauses in this pattern-matching are guarded. -val f : 'a -> 'a -> int = -Characters 62-91: - let f = function {contents=_}, 0 -> 0;; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -(_, 1) -val f : 'a ref * int -> int = -Characters 68-148: - ........function - | None -> () - | Some x when x > 0 -> () - | Some x when x <= 0 -> () -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -Some _ -(However, some guarded clause may match this value.) -val f : int option -> unit = - diff --git a/testsuite/tests/typing-warnings/exhaustiveness.ml b/testsuite/tests/typing-warnings/exhaustiveness.ml index bc79d166..35b10046 100644 --- a/testsuite/tests/typing-warnings/exhaustiveness.ml +++ b/testsuite/tests/typing-warnings/exhaustiveness.ml @@ -1,12 +1,22 @@ (* TEST flags = " -w A -strict-sequence " - * toplevel + * expect *) (* Warn about all relevant cases when possible *) let f = function None, None -> 1 | Some _, Some _ -> 2;; +[%%expect {| +Line 1, characters 8-60: +1 | ........function +2 | None, None -> 1 +3 | | Some _, Some _ -> 2.. +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +((Some _, None)|(None, Some _)) +val f : 'a option * 'b option -> int = +|}] (* Exhaustiveness check is very slow *) type _ t = @@ -14,6 +24,11 @@ type _ t = type (_,_,_,_) u = U : (int, int, int, int) u type v = E | F | G ;; +[%%expect {| +type _ t = A : int t | B : bool t | C : char t | D : float t +type (_, _, _, _) u = U : (int, int, int, int) u +type v = E | F | G +|}] let f : type a b c d e f g. a t * b t * c t * d t * e t * f t * g t * v @@ -22,23 +37,121 @@ let f : type a b c d e f g. | _, _, _, _, _, _, _, G, _, _ -> 1 (*| _ -> _ *) ;; +[%%expect {| +Line 4, characters 1-82: +4 | .function A, A, A, A, A, A, A, _, U, U -> 1 +5 | | _, _, _, _, _, _, _, G, _, _ -> 1 +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +(A, A, A, A, A, A, B, (E|F), _, _) +Line 5, characters 5-33: +5 | | _, _, _, _, _, _, _, G, _, _ -> 1 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 56: this match case is unreachable. +Consider replacing it with a refutation case ' -> .' +val f : + 'a t * 'b t * 'c t * 'd t * 'e t * 'f t * 'g t * v * ('a, 'b, 'c, 'd) u * + ('e, 'f, 'g, 'g) u -> int = +|}] (* Unused cases *) let f (x : int t) = match x with A -> 1 | _ -> 2;; (* warn *) +[%%expect {| +Line 1, characters 20-48: +1 | let f (x : int t) = match x with A -> 1 | _ -> 2;; (* warn *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 4: this pattern-matching is fragile. +It will remain exhaustive when constructors are added to type t. +Line 1, characters 42-43: +1 | let f (x : int t) = match x with A -> 1 | _ -> 2;; (* warn *) + ^ +Warning 56: this match case is unreachable. +Consider replacing it with a refutation case ' -> .' +val f : int t -> int = +|}] + let f (x : unit t option) = match x with None -> 1 | _ -> 2 ;; (* warn? *) +[%%expect {| +Line 1, characters 53-54: +1 | let f (x : unit t option) = match x with None -> 1 | _ -> 2 ;; (* warn? *) + ^ +Warning 56: this match case is unreachable. +Consider replacing it with a refutation case ' -> .' +val f : unit t option -> int = +|}] + let f (x : unit t option) = match x with None -> 1 | Some _ -> 2 ;; (* warn *) +[%%expect {| +Line 1, characters 53-59: +1 | let f (x : unit t option) = match x with None -> 1 | Some _ -> 2 ;; (* warn *) + ^^^^^^ +Warning 56: this match case is unreachable. +Consider replacing it with a refutation case ' -> .' +val f : unit t option -> int = +|}] + let f (x : int t option) = match x with None -> 1 | _ -> 2;; +[%%expect {| +val f : int t option -> int = +|}] + let f (x : int t option) = match x with None -> 1;; (* warn *) +[%%expect {| +Line 1, characters 27-49: +1 | let f (x : int t option) = match x with None -> 1;; (* warn *) + ^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +Some A +val f : int t option -> int = +|}] (* Example with record, type, single case *) type 'a box = Box of 'a type 'a pair = {left: 'a; right: 'a};; +[%%expect {| +type 'a box = Box of 'a +type 'a pair = { left : 'a; right : 'a; } +|}] let f : (int t box pair * bool) option -> unit = function None -> ();; +[%%expect {| +Line 1, characters 49-68: +1 | let f : (int t box pair * bool) option -> unit = function None -> ();; + ^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +Some ({left=Box A; right=Box A}, _) +val f : (int t box pair * bool) option -> unit = +|}] + let f : (string t box pair * bool) option -> unit = function None -> ();; +[%%expect {| +val f : (string t box pair * bool) option -> unit = +|}] + let f = function {left=Box 0; _ } -> ();; +[%%expect {| +Line 1, characters 8-39: +1 | let f = function {left=Box 0; _ } -> ();; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +{left=Box 1; _ } +val f : int box pair -> unit = +|}] + let f = function {left=Box 0;right=Box 1} -> ();; +[%%expect {| +Line 1, characters 8-47: +1 | let f = function {left=Box 0;right=Box 1} -> ();; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +{left=Box 0; right=Box 0} +val f : int box pair -> unit = +|}] (* Examples from ML2015 paper *) @@ -46,76 +159,197 @@ type _ t = | Int : int t | Bool : bool t ;; +[%%expect {| +type _ t = Int : int t | Bool : bool t +|}] let f : type a. a t -> a = function | Int -> 1 | Bool -> true ;; +[%%expect {| +val f : 'a t -> 'a = +|}] + let g : int t -> int = function | Int -> 1 ;; +[%%expect {| +val g : int t -> int = +|}] + let h : type a. a t -> a t -> bool = fun x y -> match x, y with | Int, Int -> true | Bool, Bool -> true ;; +[%%expect {| +val h : 'a t -> 'a t -> bool = +|}] + type (_, _) cmp = | Eq : ('a, 'a) cmp | Any: ('a, 'b) cmp module A : sig type a type b val eq : (a, b) cmp end = struct type a type b = a let eq = Eq end ;; +[%%expect {| +type (_, _) cmp = Eq : ('a, 'a) cmp | Any : ('a, 'b) cmp +module A : sig type a type b val eq : (a, b) cmp end +|}] + let f : (A.a, A.b) cmp -> unit = function Any -> () ;; +[%%expect {| +Line 1, characters 33-51: +1 | let f : (A.a, A.b) cmp -> unit = function Any -> () + ^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +Eq +val f : (A.a, A.b) cmp -> unit = +|}] + let deep : char t option -> char = function None -> 'c' ;; +[%%expect {| +val deep : char t option -> char = +|}] + type zero = Zero type _ succ = Succ ;; +[%%expect {| +type zero = Zero +type _ succ = Succ +|}] + type (_,_,_) plus = | Plus0 : (zero, 'a, 'a) plus | PlusS : ('a, 'b, 'c) plus -> ('a succ, 'b, 'c succ) plus ;; +[%%expect {| +type (_, _, _) plus = + Plus0 : (zero, 'a, 'a) plus + | PlusS : ('a, 'b, 'c) plus -> ('a succ, 'b, 'c succ) plus +|}] + let trivial : (zero succ, zero, zero) plus option -> bool = function None -> false ;; +[%%expect {| +val trivial : (zero succ, zero, zero) plus option -> bool = +|}] + let easy : (zero, zero succ, zero) plus option -> bool = function None -> false ;; +[%%expect {| +val easy : (zero, zero succ, zero) plus option -> bool = +|}] + let harder : (zero succ, zero succ, zero succ) plus option -> bool = function None -> false ;; +[%%expect {| +Line 2, characters 2-24: +2 | function None -> false + ^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +Some (PlusS _) +val harder : (zero succ, zero succ, zero succ) plus option -> bool = +|}] + let harder : (zero succ, zero succ, zero succ) plus option -> bool = function None -> false | Some (PlusS _) -> . ;; +[%%expect {| +val harder : (zero succ, zero succ, zero succ) plus option -> bool = +|}] + let inv_zero : type a b c d. (a,b,c) plus -> (c,d,zero) plus -> bool = fun p1 p2 -> match p1, p2 with | Plus0, Plus0 -> true ;; +[%%expect {| +val inv_zero : ('a, 'b, 'c) plus -> ('c, 'd, zero) plus -> bool = +|}] (* Empty match *) type _ t = Int : int t;; +[%%expect {| +type _ t = Int : int t +|}] + let f (x : bool t) = match x with _ -> . ;; (* ok *) +[%%expect {| +val f : bool t -> 'a = +|}] (* trefis in PR#6437 *) let f () = match None with _ -> .;; (* error *) +[%%expect {| +Line 1, characters 27-28: +1 | let f () = match None with _ -> .;; (* error *) + ^ +Error: This match case could not be refuted. + Here is an example of a value that would reach it: _ +|}] + let g () = match None with _ -> () | exception _ -> .;; (* error *) +[%%expect {| +Line 1, characters 47-48: +1 | let g () = match None with _ -> () | exception _ -> .;; (* error *) + ^ +Error: This match case could not be refuted. + Here is an example of a value that would reach it: _ +|}] + let h () = match None with _ -> . | exception _ -> .;; (* error *) +[%%expect {| +Line 1, characters 27-28: +1 | let h () = match None with _ -> . | exception _ -> .;; (* error *) + ^ +Error: This match case could not be refuted. + Here is an example of a value that would reach it: _ +|}] + let f x = match x with _ -> () | None -> .;; (* do not warn *) +[%%expect {| +val f : 'a option -> unit = +|}] (* #7059, all clauses guarded *) let f x y = match 1 with 1 when x = y -> 1;; +[%%expect {| +Line 1, characters 12-42: +1 | let f x y = match 1 with 1 when x = y -> 1;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +All clauses in this pattern-matching are guarded. +val f : 'a -> 'a -> int = +|}] (* #7504, Example with no constraints on a record *) let f = function {contents=_}, 0 -> 0;; +[%%expect {| +Line 1, characters 8-37: +1 | let f = function {contents=_}, 0 -> 0;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +(_, 1) +val f : 'a ref * int -> int = +|}] (* inexhaustive however some guarded clause might match *) let f = function @@ -123,3 +357,15 @@ let f = function | Some x when x > 0 -> () | Some x when x <= 0 -> () ;; +[%%expect {| +Line 1, characters 8-88: +1 | ........function +2 | | None -> () +3 | | Some x when x > 0 -> () +4 | | Some x when x <= 0 -> () +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +Some _ +(However, some guarded clause may match this value.) +val f : int option -> unit = +|}] diff --git a/testsuite/tests/typing-warnings/ocamltests b/testsuite/tests/typing-warnings/ocamltests index 46b2664e..0a148d9e 100644 --- a/testsuite/tests/typing-warnings/ocamltests +++ b/testsuite/tests/typing-warnings/ocamltests @@ -11,4 +11,6 @@ pr7261.ml pr7297.ml pr7553.ml records.ml +unused_rec.ml unused_types.ml +open_warnings.ml diff --git a/testsuite/tests/typing-warnings/open_warnings.ml b/testsuite/tests/typing-warnings/open_warnings.ml new file mode 100755 index 00000000..d0778c4d --- /dev/null +++ b/testsuite/tests/typing-warnings/open_warnings.ml @@ -0,0 +1,179 @@ +(* TEST + flags = " -w A-41-42-18" + * expect +*) +module T1 : sig end = struct + module M = struct type t end (* unused type t *) + open M (* unused open *) +end;; +[%%expect{| +Line 2, characters 20-26: +2 | module M = struct type t end (* unused type t *) + ^^^^^^ +Warning 34: unused type t. +Line 3, characters 2-8: +3 | open M (* unused open *) + ^^^^^^ +Warning 33: unused open M. +module T1 : sig end +|}] + + +module T2 : sig type s end = struct + module M = struct type t end + open M (* used by line below *) + type s = t +end;; +[%%expect{| +module T2 : sig type s end +|}] + +module T3 : sig end = struct + type t0 = A (* unused type and constructor *) + module M = struct type t = A end + open M (* used by line below; shadow constructor A *) + let _ = A (* A belongs to several types *) +end;; +[%%expect{| +Line 4, characters 2-8: +4 | open M (* used by line below; shadow constructor A *) + ^^^^^^ +Warning 45: this open statement shadows the constructor A (which is later used) +Line 2, characters 2-13: +2 | type t0 = A (* unused type and constructor *) + ^^^^^^^^^^^ +Warning 34: unused type t0. +Line 2, characters 2-13: +2 | type t0 = A (* unused type and constructor *) + ^^^^^^^^^^^ +Warning 37: unused constructor A. +module T3 : sig end +|}] + +module T4 : sig end = struct + type t0 = A + module M = struct type t = A end (* unused type and constructor *) + open M (* unused open; no shadowing (A below refers to the one in t0) *) + let _ : t0 = A (* disambiguation used *) +end;; +[%%expect{| +Line 3, characters 20-30: +3 | module M = struct type t = A end (* unused type and constructor *) + ^^^^^^^^^^ +Warning 34: unused type t. +Line 3, characters 20-30: +3 | module M = struct type t = A end (* unused type and constructor *) + ^^^^^^^^^^ +Warning 37: unused constructor A. +Line 4, characters 2-8: +4 | open M (* unused open; no shadowing (A below refers to the one in t0) *) + ^^^^^^ +Warning 33: unused open M. +module T4 : sig end +|}] + +module T5 : sig end = struct + type t0 = A (* unused type and constructor *) + module M = struct type t = A end + open M (* shadow constructor A *) + let _ : t = A +end;; +[%%expect{| +Line 4, characters 2-8: +4 | open M (* shadow constructor A *) + ^^^^^^ +Warning 45: this open statement shadows the constructor A (which is later used) +Line 2, characters 2-13: +2 | type t0 = A (* unused type and constructor *) + ^^^^^^^^^^^ +Warning 34: unused type t0. +Line 2, characters 2-13: +2 | type t0 = A (* unused type and constructor *) + ^^^^^^^^^^^ +Warning 37: unused constructor A. +module T5 : sig end +|}] + + +module T1_bis : sig end = struct + module M = struct type t end (* unused type t *) + open! M (* unused open *) +end;; +[%%expect{| +Line 2, characters 20-26: +2 | module M = struct type t end (* unused type t *) + ^^^^^^ +Warning 34: unused type t. +Line 3, characters 2-9: +3 | open! M (* unused open *) + ^^^^^^^ +Warning 66: unused open! M. +module T1_bis : sig end +|}] + +module T2_bis : sig type s end = struct + module M = struct type t end + open! M (* used by line below *) + type s = t +end;; +[%%expect{| +module T2_bis : sig type s end +|}] + +module T3_bis : sig end = struct + type t0 = A (* unused type and constructor *) + module M = struct type t = A end + open! M (* used by line below; shadow constructor A (disabled) *) + let _ = A (* A belongs to several types *) +end;; +[%%expect{| +Line 2, characters 2-13: +2 | type t0 = A (* unused type and constructor *) + ^^^^^^^^^^^ +Warning 34: unused type t0. +Line 2, characters 2-13: +2 | type t0 = A (* unused type and constructor *) + ^^^^^^^^^^^ +Warning 37: unused constructor A. +module T3_bis : sig end +|}] + +module T4_bis : sig end = struct + type t0 = A + module M = struct type t = A end (* unused type and constructor *) + open! M (* unused open; no shadowing (A below refers to the one in t0) *) + let _ : t0 = A (* disambiguation used *) +end;; +[%%expect{| +Line 3, characters 20-30: +3 | module M = struct type t = A end (* unused type and constructor *) + ^^^^^^^^^^ +Warning 34: unused type t. +Line 3, characters 20-30: +3 | module M = struct type t = A end (* unused type and constructor *) + ^^^^^^^^^^ +Warning 37: unused constructor A. +Line 4, characters 2-9: +4 | open! M (* unused open; no shadowing (A below refers to the one in t0) *) + ^^^^^^^ +Warning 66: unused open! M. +module T4_bis : sig end +|}] + +module T5_bis : sig end = struct + type t0 = A (* unused type and constructor *) + module M = struct type t = A end + open! M (* shadow constructor A (disabled) *) + let _ : t = A +end;; +[%%expect{| +Line 2, characters 2-13: +2 | type t0 = A (* unused type and constructor *) + ^^^^^^^^^^^ +Warning 34: unused type t0. +Line 2, characters 2-13: +2 | type t0 = A (* unused type and constructor *) + ^^^^^^^^^^^ +Warning 37: unused constructor A. +module T5_bis : sig end +|}] diff --git a/testsuite/tests/typing-warnings/pr5892.compilers.reference b/testsuite/tests/typing-warnings/pr5892.compilers.reference deleted file mode 100644 index 3c195d93..00000000 --- a/testsuite/tests/typing-warnings/pr5892.compilers.reference +++ /dev/null @@ -1,11 +0,0 @@ -type _ choice = - Left : CamlinternalOO.label choice - | Right : CamlinternalOO.tag choice -Characters 31-52: - let f : label choice -> bool = function Left -> true;; (* warn *) - ^^^^^^^^^^^^^^^^^^^^^ -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -Right -val f : CamlinternalOO.label choice -> bool = - diff --git a/testsuite/tests/typing-warnings/pr5892.ml b/testsuite/tests/typing-warnings/pr5892.ml index a1ac2b31..46213d74 100644 --- a/testsuite/tests/typing-warnings/pr5892.ml +++ b/testsuite/tests/typing-warnings/pr5892.ml @@ -1,8 +1,24 @@ (* TEST flags = " -w A -strict-sequence " - * toplevel + * expect *) open CamlinternalOO;; + type _ choice = Left : label choice | Right : tag choice;; +[%%expect {| +type _ choice = + Left : CamlinternalOO.label choice + | Right : CamlinternalOO.tag choice +|}] + let f : label choice -> bool = function Left -> true;; (* warn *) +[%%expect {| +Line 1, characters 31-52: +1 | let f : label choice -> bool = function Left -> true;; (* warn *) + ^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +Right +val f : CamlinternalOO.label choice -> bool = +|}] diff --git a/testsuite/tests/typing-warnings/pr6587.compilers.reference b/testsuite/tests/typing-warnings/pr6587.compilers.reference deleted file mode 100644 index 5b46ca55..00000000 --- a/testsuite/tests/typing-warnings/pr6587.compilers.reference +++ /dev/null @@ -1,16 +0,0 @@ -module A : sig val f : fpclass -> fpclass end -type fpclass = A -Characters 49-85: - ..struct - let f A = FP_normal - end -Error: Signature mismatch: - Modules do not match: - sig val f : fpclass -> Stdlib.fpclass end - is not included in - sig val f : fpclass -> fpclass end - Values do not match: - val f : fpclass -> Stdlib.fpclass - is not included in - val f : fpclass -> fpclass - diff --git a/testsuite/tests/typing-warnings/pr6587.ml b/testsuite/tests/typing-warnings/pr6587.ml index 96cd8949..ed7ade44 100644 --- a/testsuite/tests/typing-warnings/pr6587.ml +++ b/testsuite/tests/typing-warnings/pr6587.ml @@ -1,6 +1,6 @@ (* TEST flags = " -w A -strict-sequence " - * toplevel + * expect *) @@ -8,11 +8,32 @@ module A: sig val f: fpclass -> fpclass end = struct let f _ = FP_normal end;; +[%%expect {| +module A : sig val f : fpclass -> fpclass end +|}] type fpclass = A ;; +[%%expect {| +type fpclass = A +|}] module B: sig val f: fpclass -> fpclass end = struct let f A = FP_normal end ;; +[%%expect {| +Line 2, characters 2-38: +2 | ..struct +3 | let f A = FP_normal +4 | end +Error: Signature mismatch: + Modules do not match: + sig val f : fpclass -> Stdlib.fpclass end + is not included in + sig val f : fpclass -> fpclass end + Values do not match: + val f : fpclass -> Stdlib.fpclass + is not included in + val f : fpclass -> fpclass +|}] diff --git a/testsuite/tests/typing-warnings/pr6872.compilers.principal.reference b/testsuite/tests/typing-warnings/pr6872.compilers.principal.reference deleted file mode 100644 index f4b8f013..00000000 --- a/testsuite/tests/typing-warnings/pr6872.compilers.principal.reference +++ /dev/null @@ -1,38 +0,0 @@ -- : unit = () -exception A -type a = A -Characters 1-2: - A;; - ^ -Warning 41: A belongs to several types: a exn -The first one was selected. Please disambiguate if this is wrong. -- : a = A -Characters 6-7: - raise A;; - ^ -Warning 42: this use of A relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Exception: A. -- : a -> unit = -Characters 26-27: - function Not_found -> 1 | A -> 2 | _ -> 3;; - ^ -Warning 41: A belongs to several types: a exn -The first one was selected. Please disambiguate if this is wrong. -Characters 26-27: - function Not_found -> 1 | A -> 2 | _ -> 3;; - ^ -Error: This pattern matches values of type a - but a pattern was expected which matches values of type exn -Characters 10-11: - try raise A with A -> 2;; - ^ -Warning 42: this use of A relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 17-18: - try raise A with A -> 2;; - ^ -Warning 42: this use of A relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -- : int = 2 - diff --git a/testsuite/tests/typing-warnings/pr6872.compilers.reference b/testsuite/tests/typing-warnings/pr6872.compilers.reference deleted file mode 100644 index f852c1b9..00000000 --- a/testsuite/tests/typing-warnings/pr6872.compilers.reference +++ /dev/null @@ -1,34 +0,0 @@ -- : unit = () -exception A -type a = A -Characters 1-2: - A;; - ^ -Warning 41: A belongs to several types: a exn -The first one was selected. Please disambiguate if this is wrong. -- : a = A -Characters 6-7: - raise A;; - ^ -Warning 42: this use of A relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Exception: A. -- : a -> unit = -Characters 26-27: - function Not_found -> 1 | A -> 2 | _ -> 3;; - ^ -Warning 42: this use of A relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -- : exn -> int = -Characters 10-11: - try raise A with A -> 2;; - ^ -Warning 42: this use of A relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 17-18: - try raise A with A -> 2;; - ^ -Warning 42: this use of A relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -- : int = 2 - diff --git a/testsuite/tests/typing-warnings/pr6872.ml b/testsuite/tests/typing-warnings/pr6872.ml index 86cc9a96..2bf9b848 100644 --- a/testsuite/tests/typing-warnings/pr6872.ml +++ b/testsuite/tests/typing-warnings/pr6872.ml @@ -1,17 +1,89 @@ (* TEST flags = " -w A -strict-sequence " - * toplevel - * toplevel with principal + * expect *) (* Ignore OCAMLRUNPARAM=b to be reproducible *) -Printexc.record_backtrace false;; +Printexc.record_backtrace false +[%%expect {| +- : unit = () +|}] +;; -exception A;; -type a = A;; +exception A +[%%expect {| +exception A +|}] +;; -A;; -raise A;; -fun (A : a) -> ();; -function Not_found -> 1 | A -> 2 | _ -> 3;; -try raise A with A -> 2;; +type a = A +[%%expect {| +type a = A +|}] +;; + +A +[%%expect {| +Line 1, characters 0-1: +1 | A + ^ +Warning 41: A belongs to several types: a exn +The first one was selected. Please disambiguate if this is wrong. +- : a = A +|}] +;; + +raise A +[%%expect {| +Line 1, characters 6-7: +1 | raise A + ^ +Warning 42: this use of A relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Exception: A. +|}] +;; + +fun (A : a) -> () +[%%expect {| +- : a -> unit = +|}] +;; + +function Not_found -> 1 | A -> 2 | _ -> 3 +[%%expect {| +Line 1, characters 26-27: +1 | function Not_found -> 1 | A -> 2 | _ -> 3 + ^ +Warning 42: this use of A relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +- : exn -> int = +|}, Principal{| +Line 1, characters 26-27: +1 | function Not_found -> 1 | A -> 2 | _ -> 3 + ^ +Warning 41: A belongs to several types: a exn +The first one was selected. Please disambiguate if this is wrong. +Line 1, characters 26-27: +1 | function Not_found -> 1 | A -> 2 | _ -> 3 + ^ +Error: This pattern matches values of type a + but a pattern was expected which matches values of type exn +|}] +;; + +try raise A with A -> 2 +[%%expect {| +Line 1, characters 10-11: +1 | try raise A with A -> 2 + ^ +Warning 42: this use of A relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 1, characters 17-18: +1 | try raise A with A -> 2 + ^ +Warning 42: this use of A relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +- : int = 2 +|}] +;; diff --git a/testsuite/tests/typing-warnings/pr7085.compilers.reference b/testsuite/tests/typing-warnings/pr7085.compilers.reference deleted file mode 100644 index 3b24db3f..00000000 --- a/testsuite/tests/typing-warnings/pr7085.compilers.reference +++ /dev/null @@ -1,19 +0,0 @@ -Characters 355-385: - match M.is_t () with None -> 0 - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -Some (Is Eq) -module TypEq : sig type (_, _) t = Eq : ('a, 'a) t end -module type T = - sig - type _ is_t = Is : ('a, 'b) TypEq.t -> 'a is_t - val is_t : unit -> unit is_t option - end -module Make : functor (M : T) -> sig val f : unit -> int end -Characters 89-90: - let g : t -> int = function _ -> . - ^ -Error: This match case could not be refuted. - Here is an example of a value that would reach it: T (Is Eq) - diff --git a/testsuite/tests/typing-warnings/pr7085.ml b/testsuite/tests/typing-warnings/pr7085.ml index b2185c92..0307b468 100644 --- a/testsuite/tests/typing-warnings/pr7085.ml +++ b/testsuite/tests/typing-warnings/pr7085.ml @@ -1,6 +1,6 @@ (* TEST flags = " -w A -strict-sequence " - * toplevel + * expect *) module TypEq = struct @@ -21,8 +21,30 @@ module Make (M : T) = let f () = match M.is_t () with None -> 0 end;; +[%%expect {| +module TypEq : sig type (_, _) t = Eq : ('a, 'a) t end +module type T = + sig + type _ is_t = Is : ('a, 'b) TypEq.t -> 'a is_t + val is_t : unit -> unit is_t option + end +Line 17, characters 5-35: +17 | match M.is_t () with None -> 0 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +Some (Is Eq) +module Make : functor (M : T) -> sig val f : unit -> int end +|}] module Make2 (M : T) = struct type t = T of unit M.is_t let g : t -> int = function _ -> . end;; +[%%expect {| +Line 3, characters 30-31: +3 | let g : t -> int = function _ -> . + ^ +Error: This match case could not be refuted. + Here is an example of a value that would reach it: T (Is Eq) +|}] diff --git a/testsuite/tests/typing-warnings/pr7115.compilers.reference b/testsuite/tests/typing-warnings/pr7115.compilers.reference deleted file mode 100644 index 1d795c1a..00000000 --- a/testsuite/tests/typing-warnings/pr7115.compilers.reference +++ /dev/null @@ -1,21 +0,0 @@ -type t = A : t -Characters 40-41: - let _f ~x (* x unused argument *) = function - ^ -Warning 27: unused variable x. -module X1 : sig end -Characters 36-37: - let x = 42 (* unused value *) - ^ -Warning 32: unused value x. -module X2 : sig end -Characters 54-55: - module O = struct let x = 42 (* unused *) end - ^ -Warning 32: unused value x. -Characters 80-86: - open O (* unused open *) - ^^^^^^ -Warning 33: unused open O. -module X3 : sig end - diff --git a/testsuite/tests/typing-warnings/pr7115.ml b/testsuite/tests/typing-warnings/pr7115.ml index b8a6c6fc..ed6f5535 100644 --- a/testsuite/tests/typing-warnings/pr7115.ml +++ b/testsuite/tests/typing-warnings/pr7115.ml @@ -1,20 +1,37 @@ (* TEST flags = " -w A -strict-sequence " - * toplevel + * expect *) type t = A : t;; +[%%expect {| +type t = A : t +|}] module X1 : sig end = struct let _f ~x (* x unused argument *) = function | A -> let x = () in x end;; +[%%expect {| +Line 2, characters 10-11: +2 | let _f ~x (* x unused argument *) = function + ^ +Warning 27: unused variable x. +module X1 : sig end +|}] module X2 : sig end = struct let x = 42 (* unused value *) let _f = function | A -> let x = () in x end;; +[%%expect {| +Line 2, characters 6-7: +2 | let x = 42 (* unused value *) + ^ +Warning 32: unused value x. +module X2 : sig end +|}] module X3 : sig end = struct module O = struct let x = 42 (* unused *) end @@ -23,3 +40,14 @@ module X3 : sig end = struct let _f = function | A -> let x = () in x end;; +[%%expect {| +Line 2, characters 24-25: +2 | module O = struct let x = 42 (* unused *) end + ^ +Warning 32: unused value x. +Line 3, characters 2-8: +3 | open O (* unused open *) + ^^^^^^ +Warning 33: unused open O. +module X3 : sig end +|}] diff --git a/testsuite/tests/typing-warnings/pr7261.compilers.reference b/testsuite/tests/typing-warnings/pr7261.compilers.reference index 6c66e6d9..671e51d8 100644 --- a/testsuite/tests/typing-warnings/pr7261.compilers.reference +++ b/testsuite/tests/typing-warnings/pr7261.compilers.reference @@ -1,10 +1,10 @@ -Characters 93-95: - Foo: [> `Bla ] as 'b ) * 'b -> foo;; - ^^ +Line 7, characters 19-21: +7 | Foo: [> `Bla ] as 'b ) * 'b -> foo;; + ^^ Error: Syntax error -Characters 46-60: - Foo: 'b * 'b -> foo constraint 'b = [> `Bla ];; - ^^^^^^^^^^^^^^ +Line 2, characters 35-49: +2 | Foo: 'b * 'b -> foo constraint 'b = [> `Bla ];; + ^^^^^^^^^^^^^^ Warning 62: Type constraints do not apply to GADT cases of variant types. type foo = Foo : 'b * 'b -> foo diff --git a/testsuite/tests/typing-warnings/pr7297.compilers.reference b/testsuite/tests/typing-warnings/pr7297.compilers.reference index b8926110..14402e75 100644 --- a/testsuite/tests/typing-warnings/pr7297.compilers.reference +++ b/testsuite/tests/typing-warnings/pr7297.compilers.reference @@ -3,5 +3,5 @@ Characters 10-20: let () = raise Exit; () ;; (* warn *) ^^^^^^^^^^ Warning 21: this statement never returns (or has an unsound type.) -Exception: Stdlib.Pervasives.Exit. +Exception: Stdlib.Exit. diff --git a/testsuite/tests/typing-warnings/pr7297.ml b/testsuite/tests/typing-warnings/pr7297.ml index 055823f0..99131274 100644 --- a/testsuite/tests/typing-warnings/pr7297.ml +++ b/testsuite/tests/typing-warnings/pr7297.ml @@ -1,9 +1,19 @@ (* TEST flags = " -w A -strict-sequence " - * toplevel + * expect *) (* Ignore OCAMLRUNPARAM=b to be reproducible *) Printexc.record_backtrace false;; +[%%expect {| +- : unit = () +|}] let () = raise Exit; () ;; (* warn *) +[%%expect {| +Line 1, characters 9-19: +1 | let () = raise Exit; () ;; (* warn *) + ^^^^^^^^^^ +Warning 21: this statement never returns (or has an unsound type.) +Exception: Stdlib.Exit. +|}] diff --git a/testsuite/tests/typing-warnings/pr7553.compilers.reference b/testsuite/tests/typing-warnings/pr7553.compilers.reference deleted file mode 100644 index 7a173ed7..00000000 --- a/testsuite/tests/typing-warnings/pr7553.compilers.reference +++ /dev/null @@ -1,19 +0,0 @@ -module A : sig type foo end -module rec B : sig type bar = Bar of A.foo end -Characters 22-28: - open A - ^^^^^^ -Warning 33: unused open A. -module rec C : sig end -Characters 110-114: - let None = None - ^^^^ -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a case that is not matched: -Some _ -Characters 93-99: - open A - ^^^^^^ -Warning 33: unused open A. -module rec D : sig module M : sig module X : sig end end end - diff --git a/testsuite/tests/typing-warnings/pr7553.ml b/testsuite/tests/typing-warnings/pr7553.ml index 70b968e7..1b3ac74d 100644 --- a/testsuite/tests/typing-warnings/pr7553.ml +++ b/testsuite/tests/typing-warnings/pr7553.ml @@ -1,18 +1,31 @@ (* TEST flags = " -w A -strict-sequence " - * toplevel + * expect *) module A = struct type foo end;; +[%%expect {| +module A : sig type foo end +|}] module rec B : sig open A type bar = Bar of foo end = B;; +[%%expect {| +module rec B : sig type bar = Bar of A.foo end +|}] module rec C : sig open A end = C;; +[%%expect {| +Line 2, characters 2-8: +2 | open A + ^^^^^^ +Warning 33: unused open A. +module rec C : sig end +|}] module rec D : sig module M : module type of struct @@ -22,4 +35,16 @@ module rec D : sig end end end = D;; - +[%%expect {| +Line 5, characters 10-14: +5 | let None = None + ^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +Some _ +Line 4, characters 6-12: +4 | open A + ^^^^^^ +Warning 33: unused open A. +module rec D : sig module M : sig module X : sig end end end +|}] diff --git a/testsuite/tests/typing-warnings/records.compilers.principal.reference b/testsuite/tests/typing-warnings/records.compilers.principal.reference deleted file mode 100644 index 38e5e0fd..00000000 --- a/testsuite/tests/typing-warnings/records.compilers.principal.reference +++ /dev/null @@ -1,320 +0,0 @@ -module M1 : - sig type t = { x : int; y : int; } type u = { x : bool; y : bool; } end -Characters 49-50: - let f1 (r:t) = r.x (* ok *) - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 89-90: - let f2 r = ignore (r:t); r.x (* non principal *) - ^ -Warning 18: this type-based field disambiguation is not principal. -Characters 89-90: - let f2 r = ignore (r:t); r.x (* non principal *) - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 148-149: - match r with {x; y} -> y + y (* ok *) - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 151-152: - match r with {x; y} -> y + y (* ok *) - ^ -Warning 42: this use of y relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 148-149: - match r with {x; y} -> y + y (* ok *) - ^ -Warning 27: unused variable x. -module OK : - sig val f1 : M1.t -> int val f2 : M1.t -> int val f3 : M1.t -> int end -Characters 55-61: - let f r = match r with {x; y} -> y + y - ^^^^^^ -Warning 41: these field labels belong to several types: M1.u M1.t -The first one was selected. Please disambiguate if this is wrong. -Characters 65-66: - let f r = match r with {x; y} -> y + y - ^ -Error: This expression has type bool but an expression was expected of type - int -Characters 85-91: - {x; y} -> y + y - ^^^^^^ -Warning 41: these field labels belong to several types: M1.u M1.t -The first one was selected. Please disambiguate if this is wrong. -Characters 85-91: - {x; y} -> y + y - ^^^^^^ -Error: This pattern matches values of type M1.u - but a pattern was expected which matches values of type M1.t -module M : sig type t = { x : int; } type u = { x : bool; } end -Characters 18-21: - let f (r:M.t) = r.M.x;; (* ok *) - ^^^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -val f : M.t -> int = -Characters 18-19: - let f (r:M.t) = r.x;; (* warning *) - ^ -Warning 40: x was selected from type M.t. -It is not visible in the current scope, and will not -be selected if the type becomes unknown. -Characters 18-19: - let f (r:M.t) = r.x;; (* warning *) - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -val f : M.t -> int = -Characters 8-9: - let f ({x}:M.t) = x;; (* warning *) - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 7-10: - let f ({x}:M.t) = x;; (* warning *) - ^^^ -Warning 40: this record of type M.t contains fields that are -not visible in the current scope: x. -They will not be selected if the type becomes unknown. -val f : M.t -> int = -module M : sig type t = { x : int; y : int; } end -module N : sig type u = { x : bool; y : bool; } end -Characters 57-58: - let f (r:M.t) = r.x - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 30-36: - open N - ^^^^^^ -Warning 33: unused open N. -module OK : sig val f : M.t -> int end -module M : - sig - type t = { x : int; } - module N : sig type s = t = { x : int; } end - type u = { x : bool; } - end -module OK : sig val f : M.t -> int end -module M : - sig - type u = { x : bool; y : int; z : char; } - type t = { x : int; y : bool; } - end -Characters 37-38: - let f {x;z} = x,z - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 36-41: - let f {x;z} = x,z - ^^^^^ -Warning 9: the following labels are not bound in this record pattern: -y -Either bind these labels explicitly or add '; _' to the pattern. -module OK : sig val f : M.u -> bool * char end -Characters 38-52: - let r = {x=true;z='z'} - ^^^^^^^^^^^^^^ -Error: Some record fields are undefined: y -Characters 90-91: - let r = {x=3; y=true} - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 95-96: - let r = {x=3; y=true} - ^ -Warning 42: this use of y relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -module OK : - sig - type u = { x : int; y : bool; } - type t = { x : bool; y : int; z : char; } - val r : u - end -Characters 111-112: - let b : bar = {x=3; y=4} - ^ -Error: This record expression is expected to have type bar - The field y does not belong to type bar -module M : sig type foo = { x : int; y : int; } end -module N : sig type bar = { x : int; y : int; } end -Characters 19-22: - let r = { M.x = 3; N.y = 4; };; (* error: different definitions *) - ^^^ -Error: The record field N.y belongs to the type N.bar - but is mixed here with fields of type M.foo -module MN : - sig - type foo = M.foo = { x : int; y : int; } - type bar = N.bar = { x : int; y : int; } - end -module NM : - sig - type bar = N.bar = { x : int; y : int; } - type foo = M.foo = { x : int; y : int; } - end -Characters 8-28: - let r = {MN.x = 3; NM.y = 4};; (* error: type would change with order *) - ^^^^^^^^^^^^^^^^^^^^ -Warning 41: x belongs to several types: MN.bar MN.foo -The first one was selected. Please disambiguate if this is wrong. -Characters 8-28: - let r = {MN.x = 3; NM.y = 4};; (* error: type would change with order *) - ^^^^^^^^^^^^^^^^^^^^ -Warning 41: y belongs to several types: NM.foo NM.bar -The first one was selected. Please disambiguate if this is wrong. -Characters 19-23: - let r = {MN.x = 3; NM.y = 4};; (* error: type would change with order *) - ^^^^ -Error: The record field NM.y belongs to the type NM.foo = M.foo - but is mixed here with fields of type MN.bar = N.bar -module M : - sig - type foo = { x : int; y : int; } - type bar = { x : int; y : int; z : int; } - end -Characters 65-66: - let f r = ignore (r: foo); {r with x = 2; z = 3} - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 72-73: - let f r = ignore (r: foo); {r with x = 2; z = 3} - ^ -Error: This record expression is expected to have type M.foo - The field z does not belong to type M.foo -module M : - sig - type foo = M.foo = { x : int; y : int; } - type bar = M.bar = { x : int; y : int; z : int; } - type other = { a : int; b : int; } - end -Characters 66-67: - let f r = ignore (r: foo); { r with x = 3; a = 4 } - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 73-74: - let f r = ignore (r: foo); { r with x = 3; a = 4 } - ^ -Error: This record expression is expected to have type M.foo - The field a does not belong to type M.foo -Characters 39-40: - let r = {x=1; y=2} - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 44-45: - let r = {x=1; y=2} - ^ -Warning 42: this use of y relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 67-68: - let r: other = {x=1; y=2} - ^ -Error: This record expression is expected to have type M.other - The field x does not belong to type M.other -module A : sig type t = { x : int; } end -module B : sig type t = { x : int; } end -Characters 20-23: - let f (r : B.t) = r.A.x;; (* fail *) - ^^^ -Error: The field A.x belongs to the record type A.t - but a field was expected belonging to the record type B.t -Characters 88-91: - let a : t = {x=1;yyz=2} - ^^^ -Error: This record expression is expected to have type t - The field yyz does not belong to type t -Hint: Did you mean yyy? -type t = A -type s = A -class f : t -> object end -Characters 12-13: - class g = f A;; (* ok *) - ^ -Warning 42: this use of A relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -class g : f -class f : 'a -> 'a -> object end -Characters 13-14: - class g = f (A : t) A;; (* warn with -principal *) - ^ -Warning 42: this use of A relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 20-21: - class g = f (A : t) A;; (* warn with -principal *) - ^ -Warning 18: this type-based constructor disambiguation is not principal. -Characters 20-21: - class g = f (A : t) A;; (* warn with -principal *) - ^ -Warning 42: this use of A relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -class g : f -Characters 199-200: - let y : t = {x = 0} - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 114-120: - open M (* this open is unused, it isn't reported as shadowing 'x' *) - ^^^^^^ -Warning 33: unused open M. -module Shadow1 : - sig - type t = { x : int; } - module M : sig type s = { x : string; } end - val y : t - end -Characters 97-103: - open M (* this open shadows label 'x' *) - ^^^^^^ -Warning 45: this open statement shadows the label x (which is later used) -Characters 149-157: - let y = {x = ""} - ^^^^^^^^ -Warning 41: these field labels belong to several types: M.s t -The first one was selected. Please disambiguate if this is wrong. -module Shadow2 : - sig - type t = { x : int; } - module M : sig type s = { x : string; } end - val y : M.s - end -Characters 167-170: - let f (u : u) = match u with `Key {loc} -> loc - ^^^ -Warning 42: this use of loc relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -module P6235 : - sig - type t = { loc : string; } - type v = { loc : string; x : int; } - type u = [ `Key of t ] - val f : u -> string - end -Characters 219-224: - |`Key {loc} -> loc - ^^^^^ -Warning 41: these field labels belong to several types: v t -The first one was selected. Please disambiguate if this is wrong. -Characters 219-224: - |`Key {loc} -> loc - ^^^^^ -Warning 9: the following labels are not bound in this record pattern: -x -Either bind these labels explicitly or add '; _' to the pattern. -Characters 214-224: - |`Key {loc} -> loc - ^^^^^^^^^^ -Error: This pattern matches values of type [? `Key of v ] - but a pattern was expected which matches values of type u - Types for tag `Key are incompatible - diff --git a/testsuite/tests/typing-warnings/records.compilers.reference b/testsuite/tests/typing-warnings/records.compilers.reference deleted file mode 100644 index 0864f679..00000000 --- a/testsuite/tests/typing-warnings/records.compilers.reference +++ /dev/null @@ -1,312 +0,0 @@ -module M1 : - sig type t = { x : int; y : int; } type u = { x : bool; y : bool; } end -Characters 49-50: - let f1 (r:t) = r.x (* ok *) - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 89-90: - let f2 r = ignore (r:t); r.x (* non principal *) - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 148-149: - match r with {x; y} -> y + y (* ok *) - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 151-152: - match r with {x; y} -> y + y (* ok *) - ^ -Warning 42: this use of y relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 148-149: - match r with {x; y} -> y + y (* ok *) - ^ -Warning 27: unused variable x. -module OK : - sig val f1 : M1.t -> int val f2 : M1.t -> int val f3 : M1.t -> int end -Characters 55-61: - let f r = match r with {x; y} -> y + y - ^^^^^^ -Warning 41: these field labels belong to several types: M1.u M1.t -The first one was selected. Please disambiguate if this is wrong. -Characters 65-66: - let f r = match r with {x; y} -> y + y - ^ -Error: This expression has type bool but an expression was expected of type - int -Characters 86-87: - {x; y} -> y + y - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 89-90: - {x; y} -> y + y - ^ -Warning 42: this use of y relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 86-87: - {x; y} -> y + y - ^ -Warning 27: unused variable x. -module F2 : sig val f : M1.t -> int end -module M : sig type t = { x : int; } type u = { x : bool; } end -Characters 18-21: - let f (r:M.t) = r.M.x;; (* ok *) - ^^^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -val f : M.t -> int = -Characters 18-19: - let f (r:M.t) = r.x;; (* warning *) - ^ -Warning 40: x was selected from type M.t. -It is not visible in the current scope, and will not -be selected if the type becomes unknown. -Characters 18-19: - let f (r:M.t) = r.x;; (* warning *) - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -val f : M.t -> int = -Characters 8-9: - let f ({x}:M.t) = x;; (* warning *) - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 7-10: - let f ({x}:M.t) = x;; (* warning *) - ^^^ -Warning 40: this record of type M.t contains fields that are -not visible in the current scope: x. -They will not be selected if the type becomes unknown. -val f : M.t -> int = -module M : sig type t = { x : int; y : int; } end -module N : sig type u = { x : bool; y : bool; } end -Characters 57-58: - let f (r:M.t) = r.x - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 30-36: - open N - ^^^^^^ -Warning 33: unused open N. -module OK : sig val f : M.t -> int end -module M : - sig - type t = { x : int; } - module N : sig type s = t = { x : int; } end - type u = { x : bool; } - end -module OK : sig val f : M.t -> int end -module M : - sig - type u = { x : bool; y : int; z : char; } - type t = { x : int; y : bool; } - end -Characters 37-38: - let f {x;z} = x,z - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 36-41: - let f {x;z} = x,z - ^^^^^ -Warning 9: the following labels are not bound in this record pattern: -y -Either bind these labels explicitly or add '; _' to the pattern. -module OK : sig val f : M.u -> bool * char end -Characters 38-52: - let r = {x=true;z='z'} - ^^^^^^^^^^^^^^ -Error: Some record fields are undefined: y -Characters 90-91: - let r = {x=3; y=true} - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 95-96: - let r = {x=3; y=true} - ^ -Warning 42: this use of y relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -module OK : - sig - type u = { x : int; y : bool; } - type t = { x : bool; y : int; z : char; } - val r : u - end -Characters 111-112: - let b : bar = {x=3; y=4} - ^ -Error: This record expression is expected to have type bar - The field y does not belong to type bar -module M : sig type foo = { x : int; y : int; } end -module N : sig type bar = { x : int; y : int; } end -Characters 19-22: - let r = { M.x = 3; N.y = 4; };; (* error: different definitions *) - ^^^ -Error: The record field N.y belongs to the type N.bar - but is mixed here with fields of type M.foo -module MN : - sig - type foo = M.foo = { x : int; y : int; } - type bar = N.bar = { x : int; y : int; } - end -module NM : - sig - type bar = N.bar = { x : int; y : int; } - type foo = M.foo = { x : int; y : int; } - end -Characters 8-28: - let r = {MN.x = 3; NM.y = 4};; (* error: type would change with order *) - ^^^^^^^^^^^^^^^^^^^^ -Warning 41: x belongs to several types: MN.bar MN.foo -The first one was selected. Please disambiguate if this is wrong. -Characters 8-28: - let r = {MN.x = 3; NM.y = 4};; (* error: type would change with order *) - ^^^^^^^^^^^^^^^^^^^^ -Warning 41: y belongs to several types: NM.foo NM.bar -The first one was selected. Please disambiguate if this is wrong. -Characters 19-23: - let r = {MN.x = 3; NM.y = 4};; (* error: type would change with order *) - ^^^^ -Error: The record field NM.y belongs to the type NM.foo = M.foo - but is mixed here with fields of type MN.bar = N.bar -module M : - sig - type foo = { x : int; y : int; } - type bar = { x : int; y : int; z : int; } - end -Characters 65-66: - let f r = ignore (r: foo); {r with x = 2; z = 3} - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 72-73: - let f r = ignore (r: foo); {r with x = 2; z = 3} - ^ -Error: This record expression is expected to have type M.foo - The field z does not belong to type M.foo -module M : - sig - type foo = M.foo = { x : int; y : int; } - type bar = M.bar = { x : int; y : int; z : int; } - type other = { a : int; b : int; } - end -Characters 66-67: - let f r = ignore (r: foo); { r with x = 3; a = 4 } - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 73-74: - let f r = ignore (r: foo); { r with x = 3; a = 4 } - ^ -Error: This record expression is expected to have type M.foo - The field a does not belong to type M.foo -Characters 39-40: - let r = {x=1; y=2} - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 44-45: - let r = {x=1; y=2} - ^ -Warning 42: this use of y relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 67-68: - let r: other = {x=1; y=2} - ^ -Error: This record expression is expected to have type M.other - The field x does not belong to type M.other -module A : sig type t = { x : int; } end -module B : sig type t = { x : int; } end -Characters 20-23: - let f (r : B.t) = r.A.x;; (* fail *) - ^^^ -Error: The field A.x belongs to the record type A.t - but a field was expected belonging to the record type B.t -Characters 88-91: - let a : t = {x=1;yyz=2} - ^^^ -Error: This record expression is expected to have type t - The field yyz does not belong to type t -Hint: Did you mean yyy? -type t = A -type s = A -class f : t -> object end -Characters 12-13: - class g = f A;; (* ok *) - ^ -Warning 42: this use of A relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -class g : f -class f : 'a -> 'a -> object end -Characters 13-14: - class g = f (A : t) A;; (* warn with -principal *) - ^ -Warning 42: this use of A relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 20-21: - class g = f (A : t) A;; (* warn with -principal *) - ^ -Warning 42: this use of A relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -class g : f -Characters 199-200: - let y : t = {x = 0} - ^ -Warning 42: this use of x relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -Characters 114-120: - open M (* this open is unused, it isn't reported as shadowing 'x' *) - ^^^^^^ -Warning 33: unused open M. -module Shadow1 : - sig - type t = { x : int; } - module M : sig type s = { x : string; } end - val y : t - end -Characters 97-103: - open M (* this open shadows label 'x' *) - ^^^^^^ -Warning 45: this open statement shadows the label x (which is later used) -Characters 149-157: - let y = {x = ""} - ^^^^^^^^ -Warning 41: these field labels belong to several types: M.s t -The first one was selected. Please disambiguate if this is wrong. -module Shadow2 : - sig - type t = { x : int; } - module M : sig type s = { x : string; } end - val y : M.s - end -Characters 167-170: - let f (u : u) = match u with `Key {loc} -> loc - ^^^ -Warning 42: this use of loc relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -module P6235 : - sig - type t = { loc : string; } - type v = { loc : string; x : int; } - type u = [ `Key of t ] - val f : u -> string - end -Characters 220-223: - |`Key {loc} -> loc - ^^^ -Warning 42: this use of loc relies on type-directed disambiguation, -it will not compile with OCaml 4.00 or earlier. -module P6235' : - sig - type t = { loc : string; } - type v = { loc : string; x : int; } - type u = [ `Key of t ] - val f : u -> string - end - diff --git a/testsuite/tests/typing-warnings/records.ml b/testsuite/tests/typing-warnings/records.ml index 52663ec2..5771dbe3 100644 --- a/testsuite/tests/typing-warnings/records.ml +++ b/testsuite/tests/typing-warnings/records.ml @@ -1,7 +1,6 @@ (* TEST flags = " -w A -strict-sequence " - * toplevel - * toplevel with principal + * expect *) (* Use type information *) @@ -9,6 +8,10 @@ module M1 = struct type t = {x: int; y: int} type u = {x: bool; y: bool} end;; +[%%expect{| +module M1 : + sig type t = { x : int; y : int; } type u = { x : bool; y : bool; } end +|}] module OK = struct open M1 @@ -18,11 +21,82 @@ module OK = struct let f3 (r: t) = match r with {x; y} -> y + y (* ok *) end;; +[%%expect{| +Line 3, characters 19-20: +3 | let f1 (r:t) = r.x (* ok *) + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 4, characters 29-30: +4 | let f2 r = ignore (r:t); r.x (* non principal *) + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 7, characters 18-19: +7 | match r with {x; y} -> y + y (* ok *) + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 7, characters 21-22: +7 | match r with {x; y} -> y + y (* ok *) + ^ +Warning 42: this use of y relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 7, characters 18-19: +7 | match r with {x; y} -> y + y (* ok *) + ^ +Warning 27: unused variable x. +module OK : + sig val f1 : M1.t -> int val f2 : M1.t -> int val f3 : M1.t -> int end +|}, Principal{| +Line 3, characters 19-20: +3 | let f1 (r:t) = r.x (* ok *) + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 4, characters 29-30: +4 | let f2 r = ignore (r:t); r.x (* non principal *) + ^ +Warning 18: this type-based field disambiguation is not principal. +Line 4, characters 29-30: +4 | let f2 r = ignore (r:t); r.x (* non principal *) + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 7, characters 18-19: +7 | match r with {x; y} -> y + y (* ok *) + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 7, characters 21-22: +7 | match r with {x; y} -> y + y (* ok *) + ^ +Warning 42: this use of y relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 7, characters 18-19: +7 | match r with {x; y} -> y + y (* ok *) + ^ +Warning 27: unused variable x. +module OK : + sig val f1 : M1.t -> int val f2 : M1.t -> int val f3 : M1.t -> int end +|}] module F1 = struct open M1 let f r = match r with {x; y} -> y + y end;; (* fails *) +[%%expect{| +Line 3, characters 25-31: +3 | let f r = match r with {x; y} -> y + y + ^^^^^^ +Warning 41: these field labels belong to several types: M1.u M1.t +The first one was selected. Please disambiguate if this is wrong. +Line 3, characters 35-36: +3 | let f r = match r with {x; y} -> y + y + ^ +Error: This expression has type bool but an expression was expected of type + int +|}] module F2 = struct open M1 @@ -31,57 +105,198 @@ module F2 = struct match r with {x; y} -> y + y end;; (* fails for -principal *) +[%%expect{| +Line 6, characters 8-9: +6 | {x; y} -> y + y + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 6, characters 11-12: +6 | {x; y} -> y + y + ^ +Warning 42: this use of y relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 6, characters 8-9: +6 | {x; y} -> y + y + ^ +Warning 27: unused variable x. +module F2 : sig val f : M1.t -> int end +|}, Principal{| +Line 6, characters 7-13: +6 | {x; y} -> y + y + ^^^^^^ +Warning 41: these field labels belong to several types: M1.u M1.t +The first one was selected. Please disambiguate if this is wrong. +Line 6, characters 7-13: +6 | {x; y} -> y + y + ^^^^^^ +Error: This pattern matches values of type M1.u + but a pattern was expected which matches values of type M1.t +|}] (* Use type information with modules*) module M = struct type t = {x:int} type u = {x:bool} end;; +[%%expect{| +module M : sig type t = { x : int; } type u = { x : bool; } end +|}] let f (r:M.t) = r.M.x;; (* ok *) +[%%expect{| +Line 1, characters 18-21: +1 | let f (r:M.t) = r.M.x;; (* ok *) + ^^^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +val f : M.t -> int = +|}] let f (r:M.t) = r.x;; (* warning *) +[%%expect{| +Line 1, characters 18-19: +1 | let f (r:M.t) = r.x;; (* warning *) + ^ +Warning 40: x was selected from type M.t. +It is not visible in the current scope, and will not +be selected if the type becomes unknown. +Line 1, characters 18-19: +1 | let f (r:M.t) = r.x;; (* warning *) + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +val f : M.t -> int = +|}] let f ({x}:M.t) = x;; (* warning *) +[%%expect{| +Line 1, characters 8-9: +1 | let f ({x}:M.t) = x;; (* warning *) + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 1, characters 7-10: +1 | let f ({x}:M.t) = x;; (* warning *) + ^^^ +Warning 40: this record of type M.t contains fields that are +not visible in the current scope: x. +They will not be selected if the type becomes unknown. +val f : M.t -> int = +|}] module M = struct type t = {x: int; y: int} end;; +[%%expect{| +module M : sig type t = { x : int; y : int; } end +|}] module N = struct type u = {x: bool; y: bool} end;; +[%%expect{| +module N : sig type u = { x : bool; y : bool; } end +|}] module OK = struct open M open N let f (r:M.t) = r.x end;; +[%%expect{| +Line 4, characters 20-21: +4 | let f (r:M.t) = r.x + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 3, characters 2-8: +3 | open N + ^^^^^^ +Warning 33: unused open N. +module OK : sig val f : M.t -> int end +|}] module M = struct type t = {x:int} module N = struct type s = t = {x:int} end type u = {x:bool} end;; +[%%expect{| +module M : + sig + type t = { x : int; } + module N : sig type s = t = { x : int; } end + type u = { x : bool; } + end +|}] module OK = struct open M.N let f (r:M.t) = r.x end;; +[%%expect{| +module OK : sig val f : M.t -> int end +|}] (* Use field information *) module M = struct type u = {x:bool;y:int;z:char} type t = {x:int;y:bool} end;; +[%%expect{| +module M : + sig + type u = { x : bool; y : int; z : char; } + type t = { x : int; y : bool; } + end +|}] module OK = struct open M let f {x;z} = x,z end;; (* ok *) +[%%expect{| +Line 3, characters 9-10: +3 | let f {x;z} = x,z + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 3, characters 8-13: +3 | let f {x;z} = x,z + ^^^^^ +Warning 9: the following labels are not bound in this record pattern: +y +Either bind these labels explicitly or add '; _' to the pattern. +module OK : sig val f : M.u -> bool * char end +|}] module F3 = struct open M let r = {x=true;z='z'} end;; (* fail for missing label *) +[%%expect{| +Line 3, characters 10-24: +3 | let r = {x=true;z='z'} + ^^^^^^^^^^^^^^ +Error: Some record fields are undefined: y +|}] module OK = struct type u = {x:int;y:bool} type t = {x:bool;y:int;z:char} let r = {x=3; y=true} end;; (* ok *) +[%%expect{| +Line 4, characters 11-12: +4 | let r = {x=3; y=true} + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 4, characters 16-17: +4 | let r = {x=3; y=true} + ^ +Warning 42: this use of y relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +module OK : + sig + type u = { x : int; y : bool; } + type t = { x : bool; y : int; z : char; } + val r : u + end +|}] (* Corner cases *) @@ -90,14 +305,63 @@ module F4 = struct type bar = {x:int} let b : bar = {x=3; y=4} end;; (* fail but don't warn *) +[%%expect{| +Line 4, characters 22-23: +4 | let b : bar = {x=3; y=4} + ^ +Error: This record expression is expected to have type bar + The field y does not belong to type bar +|}] module M = struct type foo = {x:int;y:int} end;; +[%%expect{| +module M : sig type foo = { x : int; y : int; } end +|}] module N = struct type bar = {x:int;y:int} end;; +[%%expect{| +module N : sig type bar = { x : int; y : int; } end +|}] let r = { M.x = 3; N.y = 4; };; (* error: different definitions *) +[%%expect{| +Line 1, characters 19-22: +1 | let r = { M.x = 3; N.y = 4; };; (* error: different definitions *) + ^^^ +Error: The record field N.y belongs to the type N.bar + but is mixed here with fields of type M.foo +|}] module MN = struct include M include N end module NM = struct include N include M end;; +[%%expect{| +module MN : + sig + type foo = M.foo = { x : int; y : int; } + type bar = N.bar = { x : int; y : int; } + end +module NM : + sig + type bar = N.bar = { x : int; y : int; } + type foo = M.foo = { x : int; y : int; } + end +|}] let r = {MN.x = 3; NM.y = 4};; (* error: type would change with order *) +[%%expect{| +Line 1, characters 8-28: +1 | let r = {MN.x = 3; NM.y = 4};; (* error: type would change with order *) + ^^^^^^^^^^^^^^^^^^^^ +Warning 41: x belongs to several types: MN.bar MN.foo +The first one was selected. Please disambiguate if this is wrong. +Line 1, characters 8-28: +1 | let r = {MN.x = 3; NM.y = 4};; (* error: type would change with order *) + ^^^^^^^^^^^^^^^^^^^^ +Warning 41: y belongs to several types: NM.foo NM.bar +The first one was selected. Please disambiguate if this is wrong. +Line 1, characters 19-23: +1 | let r = {MN.x = 3; NM.y = 4};; (* error: type would change with order *) + ^^^^ +Error: The record field NM.y belongs to the type NM.foo = M.foo + but is mixed here with fields of type MN.bar = N.bar +|}] (* Lpw25 *) @@ -105,27 +369,94 @@ module M = struct type foo = { x: int; y: int } type bar = { x:int; y: int; z: int} end;; +[%%expect{| +module M : + sig + type foo = { x : int; y : int; } + type bar = { x : int; y : int; z : int; } + end +|}] module F5 = struct open M let f r = ignore (r: foo); {r with x = 2; z = 3} end;; +[%%expect{| +Line 3, characters 37-38: +3 | let f r = ignore (r: foo); {r with x = 2; z = 3} + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 3, characters 44-45: +3 | let f r = ignore (r: foo); {r with x = 2; z = 3} + ^ +Error: This record expression is expected to have type M.foo + The field z does not belong to type M.foo +|}] module M = struct include M type other = { a: int; b: int } end;; +[%%expect{| +module M : + sig + type foo = M.foo = { x : int; y : int; } + type bar = M.bar = { x : int; y : int; z : int; } + type other = { a : int; b : int; } + end +|}] module F6 = struct open M let f r = ignore (r: foo); { r with x = 3; a = 4 } end;; +[%%expect{| +Line 3, characters 38-39: +3 | let f r = ignore (r: foo); { r with x = 3; a = 4 } + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 3, characters 45-46: +3 | let f r = ignore (r: foo); { r with x = 3; a = 4 } + ^ +Error: This record expression is expected to have type M.foo + The field a does not belong to type M.foo +|}] module F7 = struct open M let r = {x=1; y=2} let r: other = {x=1; y=2} end;; +[%%expect{| +Line 3, characters 11-12: +3 | let r = {x=1; y=2} + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 3, characters 16-17: +3 | let r = {x=1; y=2} + ^ +Warning 42: this use of y relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 4, characters 18-19: +4 | let r: other = {x=1; y=2} + ^ +Error: This record expression is expected to have type M.other + The field x does not belong to type M.other +|}] module A = struct type t = {x: int} end module B = struct type t = {x: int} end;; +[%%expect{| +module A : sig type t = { x : int; } end +module B : sig type t = { x : int; } end +|}] let f (r : B.t) = r.A.x;; (* fail *) +[%%expect{| +Line 1, characters 20-23: +1 | let f (r : B.t) = r.A.x;; (* fail *) + ^^^ +Error: The field A.x belongs to the record type A.t + but a field was expected belonging to the record type B.t +|}] (* Spellchecking *) @@ -133,6 +464,14 @@ module F8 = struct type t = {x:int; yyy:int} let a : t = {x=1;yyz=2} end;; +[%%expect{| +Line 3, characters 19-22: +3 | let a : t = {x=1;yyz=2} + ^^^ +Error: This record expression is expected to have type t + The field yyz does not belong to type t +Hint: Did you mean yyy? +|}] (* PR#6004 *) @@ -140,10 +479,53 @@ type t = A type s = A class f (_ : t) = object end;; +[%%expect{| +type t = A +type s = A +class f : t -> object end +|}] class g = f A;; (* ok *) class f (_ : 'a) (_ : 'a) = object end;; +[%%expect{| +Line 1, characters 12-13: +1 | class g = f A;; (* ok *) + ^ +Warning 42: this use of A relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +class g : f +class f : 'a -> 'a -> object end +|}] class g = f (A : t) A;; (* warn with -principal *) +[%%expect{| +Line 1, characters 13-14: +1 | class g = f (A : t) A;; (* warn with -principal *) + ^ +Warning 42: this use of A relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 1, characters 20-21: +1 | class g = f (A : t) A;; (* warn with -principal *) + ^ +Warning 42: this use of A relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +class g : f +|}, Principal{| +Line 1, characters 13-14: +1 | class g = f (A : t) A;; (* warn with -principal *) + ^ +Warning 42: this use of A relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 1, characters 20-21: +1 | class g = f (A : t) A;; (* warn with -principal *) + ^ +Warning 18: this type-based constructor disambiguation is not principal. +Line 1, characters 20-21: +1 | class g = f (A : t) A;; (* warn with -principal *) + ^ +Warning 42: this use of A relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +class g : f +|}] (* PR#5980 *) @@ -156,6 +538,23 @@ module Shadow1 = struct open M (* this open is unused, it isn't reported as shadowing 'x' *) let y : t = {x = 0} end;; +[%%expect{| +Line 7, characters 15-16: +7 | let y : t = {x = 0} + ^ +Warning 42: this use of x relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +Line 6, characters 2-8: +6 | open M (* this open is unused, it isn't reported as shadowing 'x' *) + ^^^^^^ +Warning 33: unused open M. +module Shadow1 : + sig + type t = { x : int; } + module M : sig type s = { x : string; } end + val y : t + end +|}] module Shadow2 = struct type t = {x: int} module M = struct @@ -164,6 +563,23 @@ module Shadow2 = struct open M (* this open shadows label 'x' *) let y = {x = ""} end;; +[%%expect{| +Line 6, characters 2-8: +6 | open M (* this open shadows label 'x' *) + ^^^^^^ +Warning 45: this open statement shadows the label x (which is later used) +Line 7, characters 10-18: +7 | let y = {x = ""} + ^^^^^^^^ +Warning 41: these field labels belong to several types: M.s t +The first one was selected. Please disambiguate if this is wrong. +module Shadow2 : + sig + type t = { x : int; } + module M : sig type s = { x : string; } end + val y : M.s + end +|}] (* PR#6235 *) @@ -173,6 +589,20 @@ module P6235 = struct type u = [ `Key of t ] let f (u : u) = match u with `Key {loc} -> loc end;; +[%%expect{| +Line 5, characters 37-40: +5 | let f (u : u) = match u with `Key {loc} -> loc + ^^^ +Warning 42: this use of loc relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +module P6235 : + sig + type t = { loc : string; } + type v = { loc : string; x : int; } + type u = [ `Key of t ] + val f : u -> string + end +|}] (* Remove interaction between branches *) @@ -184,3 +614,35 @@ module P6235' = struct | (_ : u) when false -> "" |`Key {loc} -> loc end;; +[%%expect{| +Line 7, characters 11-14: +7 | |`Key {loc} -> loc + ^^^ +Warning 42: this use of loc relies on type-directed disambiguation, +it will not compile with OCaml 4.00 or earlier. +module P6235' : + sig + type t = { loc : string; } + type v = { loc : string; x : int; } + type u = [ `Key of t ] + val f : u -> string + end +|}, Principal{| +Line 7, characters 10-15: +7 | |`Key {loc} -> loc + ^^^^^ +Warning 41: these field labels belong to several types: v t +The first one was selected. Please disambiguate if this is wrong. +Line 7, characters 10-15: +7 | |`Key {loc} -> loc + ^^^^^ +Warning 9: the following labels are not bound in this record pattern: +x +Either bind these labels explicitly or add '; _' to the pattern. +Line 7, characters 5-15: +7 | |`Key {loc} -> loc + ^^^^^^^^^^ +Error: This pattern matches values of type [? `Key of v ] + but a pattern was expected which matches values of type u + Types for tag `Key are incompatible +|}] diff --git a/testsuite/tests/typing-warnings/unused_rec.ml b/testsuite/tests/typing-warnings/unused_rec.ml new file mode 100644 index 00000000..0ba9849f --- /dev/null +++ b/testsuite/tests/typing-warnings/unused_rec.ml @@ -0,0 +1,49 @@ +(* TEST + * expect +*) + +[@@@ocaml.warning "+39"] + +let rec f () = 3;; +[%%expect{| +Line 3, characters 8-9: +3 | let rec f () = 3;; + ^ +Warning 39: unused rec flag. +val f : unit -> int = +|}];; + +let[@warning "-39"] rec g () = 3;; +[%%expect{| +val g : unit -> int = +|}];; + +let[@warning "+39"] rec h () = 3;; +[%%expect{| +Line 1, characters 24-25: +1 | let[@warning "+39"] rec h () = 3;; + ^ +Warning 39: unused rec flag. +val h : unit -> int = +|}];; + +[@@@ocaml.warning "-39"] + +let rec f () = 3;; +[%%expect{| +val f : unit -> int = +|}];; + +let[@warning "-39"] rec g () = 3;; +[%%expect{| +val g : unit -> int = +|}];; + +let[@warning "+39"] rec h () = 3;; +[%%expect{| +Line 1, characters 24-25: +1 | let[@warning "+39"] rec h () = 3;; + ^ +Warning 39: unused rec flag. +val h : unit -> int = +|}];; diff --git a/testsuite/tests/typing-warnings/unused_types.compilers.reference b/testsuite/tests/typing-warnings/unused_types.compilers.reference deleted file mode 100644 index 22014bcf..00000000 --- a/testsuite/tests/typing-warnings/unused_types.compilers.reference +++ /dev/null @@ -1,57 +0,0 @@ -Characters 98-115: - type unused = int - ^^^^^^^^^^^^^^^^^ -Warning 34: unused type unused. -module Unused : sig end -Characters 68-93: - type nonrec unused = used - ^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 34: unused type unused. -module Unused_nonrec : sig end -Characters 40-65: - type unused = A of unused - ^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 34: unused type unused. -Characters 40-65: - type unused = A of unused - ^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 37: unused constructor A. -module Unused_rec : sig end -Characters 46-70: - exception Nobody_uses_me - ^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 38: unused exception Nobody_uses_me -module Unused_exception : sig end -Characters 96-110: - type t += Nobody_uses_me - ^^^^^^^^^^^^^^ -Warning 38: unused extension constructor Nobody_uses_me -module Unused_extension_constructor : sig type t = .. end -Characters 91-121: - exception Nobody_constructs_me - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning 38: exception Nobody_constructs_me is never used to build values. -(However, this constructor appears in patterns.) -module Unused_exception_outside_patterns : sig val falsity : exn -> bool end -Characters 127-147: - type t += Nobody_constructs_me - ^^^^^^^^^^^^^^^^^^^^ -Warning 38: extension constructor Nobody_constructs_me is never used to build values. -(However, this constructor appears in patterns.) -module Unused_extension_outside_patterns : - sig type t = .. val falsity : t -> bool end -Characters 88-109: - exception Private_exn - ^^^^^^^^^^^^^^^^^^^^^ -Warning 38: exception Private_exn is never used to build values. -It is exported or rebound as a private extension. -module Unused_private_exception : sig type exn += private Private_exn end -Characters 124-135: - type t += Private_ext - ^^^^^^^^^^^ -Warning 38: extension constructor Private_ext is never used to build values. -It is exported or rebound as a private extension. -module Unused_private_extension : - sig type t = .. type t += private Private_ext end -module Pr7438 : sig end - diff --git a/testsuite/tests/typing-warnings/unused_types.ml b/testsuite/tests/typing-warnings/unused_types.ml index 839d505b..cb1fc65f 100644 --- a/testsuite/tests/typing-warnings/unused_types.ml +++ b/testsuite/tests/typing-warnings/unused_types.ml @@ -1,6 +1,6 @@ (* TEST flags = " -w A -strict-sequence " - * toplevel + * expect *) module Unused : sig @@ -8,6 +8,13 @@ end = struct type unused = int end ;; +[%%expect {| +Line 3, characters 2-19: +3 | type unused = int + ^^^^^^^^^^^^^^^^^ +Warning 34: unused type unused. +module Unused : sig end +|}] module Unused_nonrec : sig end = struct @@ -15,18 +22,43 @@ end = struct type nonrec unused = used end ;; +[%%expect {| +Line 4, characters 2-27: +4 | type nonrec unused = used + ^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 34: unused type unused. +module Unused_nonrec : sig end +|}] module Unused_rec : sig end = struct type unused = A of unused end ;; +[%%expect {| +Line 3, characters 2-27: +3 | type unused = A of unused + ^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 34: unused type unused. +Line 3, characters 2-27: +3 | type unused = A of unused + ^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 37: unused constructor A. +module Unused_rec : sig end +|}] module Unused_exception : sig end = struct exception Nobody_uses_me end ;; +[%%expect {| +Line 3, characters 2-26: +3 | exception Nobody_uses_me + ^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 38: unused exception Nobody_uses_me +module Unused_exception : sig end +|}] module Unused_extension_constructor : sig type t = .. @@ -35,6 +67,13 @@ end = struct type t += Nobody_uses_me end ;; +[%%expect {| +Line 5, characters 12-26: +5 | type t += Nobody_uses_me + ^^^^^^^^^^^^^^ +Warning 38: unused extension constructor Nobody_uses_me +module Unused_extension_constructor : sig type t = .. end +|}] module Unused_exception_outside_patterns : sig val falsity : exn -> bool @@ -45,18 +84,35 @@ end = struct | _ -> false end ;; +[%%expect {| +Line 4, characters 2-32: +4 | exception Nobody_constructs_me + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 38: exception Nobody_constructs_me is never used to build values. +(However, this constructor appears in patterns.) +module Unused_exception_outside_patterns : sig val falsity : exn -> bool end +|}] module Unused_extension_outside_patterns : sig type t = .. val falsity : t -> bool end = struct type t = .. - type t += Nobody_constructs_me + type t += Noone_builds_me let falsity = function - | Nobody_constructs_me -> true + | Noone_builds_me -> true | _ -> false end ;; +[%%expect {| +Line 6, characters 12-27: +6 | type t += Noone_builds_me + ^^^^^^^^^^^^^^^ +Warning 38: extension constructor Noone_builds_me is never used to build values. +(However, this constructor appears in patterns.) +module Unused_extension_outside_patterns : + sig type t = .. val falsity : t -> bool end +|}] module Unused_private_exception : sig type exn += private Private_exn @@ -64,6 +120,14 @@ end = struct exception Private_exn end ;; +[%%expect {| +Line 4, characters 2-23: +4 | exception Private_exn + ^^^^^^^^^^^^^^^^^^^^^ +Warning 38: exception Private_exn is never used to build values. +It is exported or rebound as a private extension. +module Unused_private_exception : sig type exn += private Private_exn end +|}] module Unused_private_extension : sig type t = .. @@ -73,9 +137,46 @@ end = struct type t += Private_ext end ;; +[%%expect {| +Line 6, characters 12-23: +6 | type t += Private_ext + ^^^^^^^^^^^ +Warning 38: extension constructor Private_ext is never used to build values. +It is exported or rebound as a private extension. +module Unused_private_extension : + sig type t = .. type t += private Private_ext end +|}] module Pr7438 : sig end = struct module type S = sig type t = private [> `Foo] end - module type X = sig type t = private [> `Foo | `Bar] include S with type t := t end + module type X = + sig type t = private [> `Foo | `Bar] include S with type t := t end +end;; +[%%expect {| +module Pr7438 : sig end +|}] + +module Unused_type_disable_warning : sig +end = struct + type t = A [@@warning "-34"] +end;; +[%%expect {| +Line 3, characters 2-30: +3 | type t = A [@@warning "-34"] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 37: unused constructor A. +module Unused_type_disable_warning : sig end +|}] + +module Unused_constructor_disable_warning : sig +end = struct + type t = A [@@warning "-37"] end;; +[%%expect {| +Line 3, characters 2-30: +3 | type t = A [@@warning "-37"] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 34: unused type t. +module Unused_constructor_disable_warning : sig end +|}] diff --git a/testsuite/tests/unboxed-primitive-args/Makefile b/testsuite/tests/unboxed-primitive-args/Makefile deleted file mode 100644 index 7a5c5ef1..00000000 --- a/testsuite/tests/unboxed-primitive-args/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Jeremie Dimino, Jane Street Europe * -#* * -#* Copyright 2015 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -BASEDIR=../.. -LIBRARIES=unix bigarray -MODULES=common -MAIN_MODULE=main -C_FILES=test_common stubs -C_INCLUDES=-I $(OTOPDIR)/otherlibs/bigarray -ADD_COMPFLAGS=-I $(OTOPDIR)/otherlibs/bigarray \ - -I $(OTOPDIR)/otherlibs/$(UNIXLIB) - -include $(BASEDIR)/makefiles/Makefile.one -include $(BASEDIR)/makefiles/Makefile.common - -NATIVECODE_ONLY=true -NATIVECCCOMPOPTS+=-I $(OTOPDIR)/otherlibs/bigarray -GENERATED_SOURCES+=main.ml stubs.c - -main.ml: gen_test.ml - @$(OCAML) gen_test.ml ml > $@ - -stubs.c: gen_test.ml - @$(OCAML) gen_test.ml c > $@ - -common.cmx: common.cmi - -compile: stubs.c diff --git a/testsuite/tests/unboxed-primitive-args/common.ml b/testsuite/tests/unboxed-primitive-args/common.ml index d1f13d34..19c0451e 100644 --- a/testsuite/tests/unboxed-primitive-args/common.ml +++ b/testsuite/tests/unboxed-primitive-args/common.ml @@ -45,7 +45,7 @@ let expand_test = function | T (s, fn, p) -> Test (s, fn, p) let string_of : type a. a typ -> a -> string = function - | Int -> string_of_int + | Int -> Int.to_string | Int32 -> Printf.sprintf "%ldl" | Int64 -> Printf.sprintf "%LdL" | Nativeint -> Printf.sprintf "%ndn" diff --git a/testsuite/tests/unboxed-primitive-args/ocamltests b/testsuite/tests/unboxed-primitive-args/ocamltests new file mode 100644 index 00000000..31c13b44 --- /dev/null +++ b/testsuite/tests/unboxed-primitive-args/ocamltests @@ -0,0 +1 @@ +test.ml diff --git a/testsuite/tests/unboxed-primitive-args/test.ml b/testsuite/tests/unboxed-primitive-args/test.ml new file mode 100644 index 00000000..62104351 --- /dev/null +++ b/testsuite/tests/unboxed-primitive-args/test.ml @@ -0,0 +1,22 @@ +(* TEST + +* hasunix +include unix + +files = "common.mli common.ml test_common.c test_common.h" + +** setup-ocamlopt.byte-build-env +*** ocaml +test_file = "${test_source_directory}/gen_test.ml" +ocaml_script_as_argument = "true" +arguments = "c" +compiler_output = "stubs.c" +**** ocaml +arguments = "ml" +compiler_output = "main.ml" +***** ocamlopt.byte +all_modules = "test_common.c stubs.c common.mli common.ml main.ml" +****** run +******* check-program-output + +*) diff --git a/testsuite/tests/unboxed-primitive-args/test.reference b/testsuite/tests/unboxed-primitive-args/test.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/unwind/Makefile b/testsuite/tests/unwind/Makefile deleted file mode 100644 index ad88faf9..00000000 --- a/testsuite/tests/unwind/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -BASEDIR=../.. - -# The -keep_dwarf_unwind option of ld was introduced in ld version 224.1. -# (The last released version where it is not supported is version 136.) -default: - @printf " ... testing 'unwind_test':" - @if [ ! $(SYSTEM) = macosx ]; then \ - echo " => skipped (not on Mac OSX)"; \ - elif $(BYTECODE_ONLY); then \ - echo " => skipped (bytecode only)"; \ - else \ - LDFULL="`ld -v 2>&1`"; \ - LD="`echo $$LDFULL | grep -o \"ld64-[0-9]*\"`"; \ - LDVER="`echo $$LD | sed \"s/ld64-//\"`"; \ - if [[ -z "$$LD" ]]; then \ - echo " => skipped (unknown linker: pattern ld64-[0-9]* not found" \ - echo " in 'ld -v' output)"; \ - elif [[ $$LDVER -lt 224 ]]; then \ - echo " => skipped (ld version is $$LDVER, only 224 or above " \ - echo " are supported)"; \ - else \ - $(MAKE) native_macosx_tests; \ - fi; \ - fi - -native_macosx_tests: - @$(MAKE) clean ; $(MAKE) unwind_test && \ - ./unwind_test >/dev/null 2>&1 && echo " => passed" || echo " => failed" - -unwind_test: - @$(OCAMLOPT) -c -opaque mylib.mli - @$(OCAMLOPT) -c driver.ml - @$(OCAMLOPT) -c mylib.ml - @$(OCAMLOPT) -ccopt -I -ccopt $(CTOPDIR)/byterun -c stack_walker.c - @$(OCAMLOPT) -cclib -Wl,-keep_dwarf_unwind -o unwind_test mylib.cmx \ - driver.cmx stack_walker.o - -clean: - @rm -f *.cm* *.o unwind_test - -include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/unwind/check-linker-version.sh b/testsuite/tests/unwind/check-linker-version.sh new file mode 100644 index 00000000..0b15681e --- /dev/null +++ b/testsuite/tests/unwind/check-linker-version.sh @@ -0,0 +1,16 @@ +#!/bin/sh +exec > ${ocamltest_response} 2>&1 +LDFULL="`ld -v 2>&1`" +LD="`echo $LDFULL | grep -o \"ld64-[0-9]*\"`" +LDVER="`echo $LD | sed \"s/ld64-//\"`" +if [[ -z "$LD" ]]; then + echo "unknown linker: pattern ld64-[0-9]* not found in 'ld -v' output"; + test_result=${TEST_SKIP}; +elif [[ $LDVER -lt 224 ]]; then + echo "ld version is $LDVER, only 224 or above are supported"; + test_result=${TEST_SKIP}; +else + test_reslut=${TEST_PASS}; +fi + +exit ${TEST_RESULT} diff --git a/testsuite/tests/unwind/driver.ml b/testsuite/tests/unwind/driver.ml index cd289b6b..421f85a6 100644 --- a/testsuite/tests/unwind/driver.ml +++ b/testsuite/tests/unwind/driver.ml @@ -1,3 +1,23 @@ +(* TEST + +script = "sh ${test_source_directory}/check-linker-version.sh" +files = "mylib.mli mylib.ml stack_walker.c" + +* macos +** script +*** setup-ocamlopt.byte-build-env +**** ocamlopt.byte +flags = "-opaque" +module = "mylib.mli" +***** ocamlopt.byte +module = "" +flags = "-cclib -Wl,-keep_dwarf_unwind" +all_modules = "mylib.ml driver.ml stack_walker.c" +program = "${test_build_directory}/unwind_test" +****** run + +*) + let () = Mylib.foo1 Mylib.bar 1 2 3 4 5 6 7 8 9 10; Mylib.foo2 Mylib.baz 1 2 3 4 5 6 7 8 9 10 diff --git a/testsuite/tests/unwind/ocamltests b/testsuite/tests/unwind/ocamltests new file mode 100644 index 00000000..6550b8e3 --- /dev/null +++ b/testsuite/tests/unwind/ocamltests @@ -0,0 +1 @@ +driver.ml diff --git a/testsuite/tests/utils/edit_distance.ml b/testsuite/tests/utils/edit_distance.ml index 3f3807fe..1ac10701 100644 --- a/testsuite/tests/utils/edit_distance.ml +++ b/testsuite/tests/utils/edit_distance.ml @@ -1,7 +1,7 @@ (* TEST include config include testing -binary_modules = "misc identifiable numbers" +binary_modules = "config build_path_prefix_map misc identifiable numbers" * bytecode *) @@ -16,7 +16,7 @@ let test = fun a b cutoff expected -> let show_result = function | None -> "None" - | Some d -> "Some " ^ string_of_int d in + | Some d -> "Some " ^ Int.to_string d in incr counter; Printf.printf "[%02d] (edit_distance %S %S %s), expected %s\n" !counter a b (show_cutoff cutoff) (show_result expected); diff --git a/testsuite/tests/utils/overflow_detection.ml b/testsuite/tests/utils/overflow_detection.ml index ca5fa543..11f3aafa 100644 --- a/testsuite/tests/utils/overflow_detection.ml +++ b/testsuite/tests/utils/overflow_detection.ml @@ -1,7 +1,7 @@ (* TEST include config include testing -binary_modules = "misc identifiable numbers" +binary_modules = "config build_path_prefix_map misc identifiable numbers" * bytecode *) @@ -11,7 +11,7 @@ let print_int i = else if i = min_int then "min_int" else - string_of_int i + Int.to_string i let test_no_overflow_add a b = Printf.printf "Misc.no_overflow_add %s %s = %b\n" diff --git a/testsuite/tests/utils/test_strongly_connected_components.ml b/testsuite/tests/utils/test_strongly_connected_components.ml index c818f383..05845228 100644 --- a/testsuite/tests/utils/test_strongly_connected_components.ml +++ b/testsuite/tests/utils/test_strongly_connected_components.ml @@ -1,7 +1,9 @@ (* TEST include config include testing -binary_modules = "misc identifiable numbers strongly_connected_components" +binary_modules = + "config build_path_prefix_map misc identifiable numbers \ + strongly_connected_components" * bytecode *) @@ -23,7 +25,7 @@ let print_scc scc = | SCC.No_loop e -> Printf.printf "%i\n" e | SCC.Has_loop l -> Printf.printf "[%s]\n" - (String.concat "; " (List.map string_of_int l))) scc; + (String.concat "; " (List.map Stdlib.Int.to_string l))) scc; Printf.printf "end\n" let scc graph = diff --git a/testsuite/tests/warnings/deprecated_module.compilers.reference b/testsuite/tests/warnings/deprecated_module.compilers.reference index 09a3a45a..c733b917 100644 --- a/testsuite/tests/warnings/deprecated_module.compilers.reference +++ b/testsuite/tests/warnings/deprecated_module.compilers.reference @@ -1,4 +1,8 @@ File "deprecated_module.ml", line 16, characters 8-11: -Warning 3: deprecated: module M +16 | let _ = M.x + ^^^ +Alert deprecated: module M File "deprecated_module.ml", line 17, characters 8-9: -Warning 3: deprecated: module M +17 | include M + ^ +Alert deprecated: module M diff --git a/testsuite/tests/warnings/deprecated_module_assigment.compilers.reference b/testsuite/tests/warnings/deprecated_module_assigment.compilers.reference index 6a635d9f..e918a19d 100644 --- a/testsuite/tests/warnings/deprecated_module_assigment.compilers.reference +++ b/testsuite/tests/warnings/deprecated_module_assigment.compilers.reference @@ -1,72 +1,138 @@ File "deprecated_module_assigment.ml", line 17, characters 33-34: -Warning 3: deprecated: x +17 | module Y : sig val x : int end = X + ^ +Alert deprecated: x DEPRECATED - File "deprecated_module_assigment.ml", line 12, characters 2-41: +File "deprecated_module_assigment.ml", line 12, characters 2-41: +12 | val x : int [@@deprecated "DEPRECATED"] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Definition - File "deprecated_module_assigment.ml", line 17, characters 15-26: +File "deprecated_module_assigment.ml", line 17, characters 15-26: +17 | module Y : sig val x : int end = X + ^^^^^^^^^^^ Expected signature File "deprecated_module_assigment.ml", line 23, characters 13-14: -Warning 3: deprecated: x +23 | module B = F(X) + ^ +Alert deprecated: x DEPRECATED - File "deprecated_module_assigment.ml", line 12, characters 2-41: +File "deprecated_module_assigment.ml", line 12, characters 2-41: +12 | val x : int [@@deprecated "DEPRECATED"] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Definition - File "deprecated_module_assigment.ml", line 21, characters 17-28: +File "deprecated_module_assigment.ml", line 21, characters 17-28: +21 | module F(A : sig val x : int end) = struct let _ = A.x end + ^^^^^^^^^^^ Expected signature File "deprecated_module_assigment.ml", line 33, characters 39-78: -Warning 3: deprecated: A - File "deprecated_module_assigment.ml", line 33, characters 55-70: +33 | module CSTR : sig type t = A | B end = struct type t = A [@deprecated] | B end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Alert deprecated: A +File "deprecated_module_assigment.ml", line 33, characters 55-70: +33 | module CSTR : sig type t = A | B end = struct type t = A [@deprecated] | B end + ^^^^^^^^^^^^^^^ Definition - File "deprecated_module_assigment.ml", line 33, characters 27-28: +File "deprecated_module_assigment.ml", line 33, characters 27-28: +33 | module CSTR : sig type t = A | B end = struct type t = A [@deprecated] | B end + ^ Expected signature File "deprecated_module_assigment.ml", line 37, characters 2-20: -Warning 3: deprecated: A - File "deprecated_module_assigment.ml", line 36, characters 11-26: +37 | type s = t = A | B + ^^^^^^^^^^^^^^^^^^ +Alert deprecated: A +File "deprecated_module_assigment.ml", line 36, characters 11-26: +36 | type t = A [@deprecated] | B + ^^^^^^^^^^^^^^^ Definition - File "deprecated_module_assigment.ml", line 37, characters 15-16: +File "deprecated_module_assigment.ml", line 37, characters 15-16: +37 | type s = t = A | B + ^ Expected signature File "deprecated_module_assigment.ml", line 45, characters 0-58: -Warning 3: deprecated: mutating field x - File "deprecated_module_assigment.ml", line 45, characters 17-53: +45 | struct type t = {mutable x: int [@deprecated_mutable]} end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Alert deprecated: mutating field x +File "deprecated_module_assigment.ml", line 45, characters 17-53: +45 | struct type t = {mutable x: int [@deprecated_mutable]} end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Definition - File "deprecated_module_assigment.ml", line 44, characters 14-28: +File "deprecated_module_assigment.ml", line 44, characters 14-28: +44 | sig type t = {mutable x: int} end = + ^^^^^^^^^^^^^^ Expected signature File "deprecated_module_assigment.ml", line 49, characters 2-31: -Warning 3: deprecated: mutating field x - File "deprecated_module_assigment.ml", line 48, characters 12-48: +49 | type s = t = {mutable x: int} + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Alert deprecated: mutating field x +File "deprecated_module_assigment.ml", line 48, characters 12-48: +48 | type t = {mutable x: int [@deprecated_mutable]} + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Definition - File "deprecated_module_assigment.ml", line 49, characters 16-30: +File "deprecated_module_assigment.ml", line 49, characters 16-30: +49 | type s = t = {mutable x: int} + ^^^^^^^^^^^^^^ Expected signature File "deprecated_module_assigment.ml", line 54, characters 37-75: -Warning 3: deprecated: t - File "deprecated_module_assigment.ml", line 54, characters 44-71: +54 | module TYPE : sig type t = int end = struct type t = int [@@deprecated] end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Alert deprecated: t +File "deprecated_module_assigment.ml", line 54, characters 44-71: +54 | module TYPE : sig type t = int end = struct type t = int [@@deprecated] end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Definition - File "deprecated_module_assigment.ml", line 54, characters 18-30: +File "deprecated_module_assigment.ml", line 54, characters 18-30: +54 | module TYPE : sig type t = int end = struct type t = int [@@deprecated] end + ^^^^^^^^^^^^ Expected signature File "deprecated_module_assigment.ml", line 60, characters 0-52: -Warning 3: deprecated: c +60 | struct class c = object end [@@deprecated "FOO"] end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Alert deprecated: c FOO - File "deprecated_module_assigment.ml", line 60, characters 7-48: +File "deprecated_module_assigment.ml", line 60, characters 7-48: +60 | struct class c = object end [@@deprecated "FOO"] end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Definition - File "deprecated_module_assigment.ml", line 59, characters 4-24: +File "deprecated_module_assigment.ml", line 59, characters 4-24: +59 | sig class c : object end end = + ^^^^^^^^^^^^^^^^^^^^ Expected signature File "deprecated_module_assigment.ml", line 64, characters 0-57: -Warning 3: deprecated: c +64 | struct class type c = object end [@@deprecated "FOO"] end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Alert deprecated: c FOO - File "deprecated_module_assigment.ml", line 64, characters 7-53: +File "deprecated_module_assigment.ml", line 64, characters 7-53: +64 | struct class type c = object end [@@deprecated "FOO"] end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Definition - File "deprecated_module_assigment.ml", line 63, characters 4-29: +File "deprecated_module_assigment.ml", line 63, characters 4-29: +63 | sig class type c = object end end = + ^^^^^^^^^^^^^^^^^^^^^^^^^ Expected signature File "deprecated_module_assigment.ml", line 71, characters 0-55: -Warning 3: deprecated: S +71 | struct module type S = sig end [@@deprecated "FOO"] end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Alert deprecated: S FOO - File "deprecated_module_assigment.ml", line 71, characters 7-51: +File "deprecated_module_assigment.ml", line 71, characters 7-51: +71 | struct module type S = sig end [@@deprecated "FOO"] end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Definition - File "deprecated_module_assigment.ml", line 70, characters 4-27: +File "deprecated_module_assigment.ml", line 70, characters 4-27: +70 | sig module type S = sig end end = + ^^^^^^^^^^^^^^^^^^^^^^^ Expected signature File "deprecated_module_assigment.ml", line 82, characters 0-53: -Warning 3: deprecated: M +82 | struct module M = struct end [@@deprecated "FOO"] end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Alert deprecated: M FOO - File "deprecated_module_assigment.ml", line 82, characters 7-49: +File "deprecated_module_assigment.ml", line 82, characters 7-49: +82 | struct module M = struct end [@@deprecated "FOO"] end + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Definition - File "deprecated_module_assigment.ml", line 81, characters 4-22: +File "deprecated_module_assigment.ml", line 81, characters 4-22: +81 | sig module M : sig end end = + ^^^^^^^^^^^^^^^^^^ Expected signature diff --git a/testsuite/tests/warnings/deprecated_module_use.compilers.reference b/testsuite/tests/warnings/deprecated_module_use.compilers.reference index 73772b73..c713064f 100644 --- a/testsuite/tests/warnings/deprecated_module_use.compilers.reference +++ b/testsuite/tests/warnings/deprecated_module_use.compilers.reference @@ -1,14 +1,24 @@ File "deprecated_module_use.ml", line 18, characters 5-22: -Warning 3: deprecated: module Deprecated_module +18 | open Deprecated_module + ^^^^^^^^^^^^^^^^^ +Alert deprecated: module Deprecated_module As you could guess, Deprecated_module is deprecated. Please use something else! File "deprecated_module_use.ml", line 20, characters 9-12: -Warning 3: deprecated: module Deprecated_module.M +20 | type s = M.t + ^^^ +Alert deprecated: module Deprecated_module.M File "deprecated_module_use.ml", line 20, characters 9-12: -Warning 3: deprecated: Deprecated_module.M.t +20 | type s = M.t + ^^^ +Alert deprecated: Deprecated_module.M.t File "deprecated_module_use.ml", line 22, characters 5-6: -Warning 3: deprecated: module Deprecated_module.M +22 | open M + ^ +Alert deprecated: module Deprecated_module.M File "deprecated_module_use.ml", line 23, characters 8-9: -Warning 3: deprecated: Deprecated_module.M.x +23 | let _ = x + ^ +Alert deprecated: Deprecated_module.M.x diff --git a/testsuite/tests/warnings/ocamltests b/testsuite/tests/warnings/ocamltests index 2f143cf8..fa3318d2 100644 --- a/testsuite/tests/warnings/ocamltests +++ b/testsuite/tests/warnings/ocamltests @@ -2,6 +2,7 @@ deprecated_module_assigment.ml deprecated_module.ml deprecated_module_use.ml w01.ml +w03.ml w04_failure.ml w04.ml w06.ml diff --git a/testsuite/tests/warnings/w01.compilers.reference b/testsuite/tests/warnings/w01.compilers.reference index ea21e869..6973f4d5 100644 --- a/testsuite/tests/warnings/w01.compilers.reference +++ b/testsuite/tests/warnings/w01.compilers.reference @@ -1,15 +1,27 @@ File "w01.ml", line 14, characters 12-14: +14 | let foo = ( *);; + ^^ Warning 2: this is not the end of a comment. File "w01.ml", line 20, characters 0-3: +20 | f 1; f 1;; + ^^^ Warning 5: this function application is partial, maybe some arguments are missing. File "w01.ml", line 30, characters 4-5: +30 | let 1 = 1;; + ^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: 0 File "w01.ml", line 35, characters 0-1: +35 | 1; 1;; + ^ Warning 10: this expression should have type unit. -File "w01.ml", line 19, characters 8-9: -Warning 27: unused variable y. File "w01.ml", line 42, characters 2-3: +42 | | 1 -> () + ^ Warning 11: this match case is unused. +File "w01.ml", line 19, characters 8-9: +19 | let f x y = x;; + ^ +Warning 27: unused variable y. diff --git a/testsuite/tests/warnings/w03.compilers.reference b/testsuite/tests/warnings/w03.compilers.reference new file mode 100644 index 00000000..3e75b2ef --- /dev/null +++ b/testsuite/tests/warnings/w03.compilers.reference @@ -0,0 +1,8 @@ +File "w03.ml", line 14, characters 8-9: +14 | let _ = A + ^ +Alert deprecated: A +File "w03.ml", line 17, characters 12-26: +17 | exception B [@@deprecated] + ^^^^^^^^^^^^^^ +Warning 53: the "deprecated" attribute cannot appear in this context diff --git a/testsuite/tests/warnings/w03.ml b/testsuite/tests/warnings/w03.ml new file mode 100644 index 00000000..b9f70b1d --- /dev/null +++ b/testsuite/tests/warnings/w03.ml @@ -0,0 +1,24 @@ +(* TEST + +flags = "-w A" + +* setup-ocamlc.byte-build-env +** ocamlc.byte +compile_only = "true" +*** check-ocamlc.byte-output + +*) + +exception A [@deprecated] + +let _ = A + + +exception B [@@deprecated] + +let _ = B + + +exception C [@deprecated] + +let _ = B [@warning "-53"] diff --git a/testsuite/tests/warnings/w04.compilers.reference b/testsuite/tests/warnings/w04.compilers.reference index d746bd60..3f091a39 100644 --- a/testsuite/tests/warnings/w04.compilers.reference +++ b/testsuite/tests/warnings/w04.compilers.reference @@ -1,3 +1,6 @@ File "w04.ml", line 21, characters 10-40: +21 | ..........match x with +22 | | A -> 0 +23 | | _ -> 1 Warning 4: this pattern-matching is fragile. It will remain exhaustive when constructors are added to type t. diff --git a/testsuite/tests/warnings/w04.ml b/testsuite/tests/warnings/w04.ml index fc33df31..dd0fa00f 100644 --- a/testsuite/tests/warnings/w04.ml +++ b/testsuite/tests/warnings/w04.ml @@ -13,7 +13,7 @@ compile_only = "true" type expr = E of int [@@unboxed] - + let f x = match x with (E e) -> e type t = A | B diff --git a/testsuite/tests/warnings/w04_failure.compilers.reference b/testsuite/tests/warnings/w04_failure.compilers.reference index d4182ae4..e833d2bb 100644 --- a/testsuite/tests/warnings/w04_failure.compilers.reference +++ b/testsuite/tests/warnings/w04_failure.compilers.reference @@ -1,9 +1,21 @@ File "w04_failure.ml", line 20, characters 2-78: +20 | ..match r1, r2, t with +21 | | AB, _, A -> () +22 | | _, XY, X -> () +23 | | _, _, _ -> () Warning 4: this pattern-matching is fragile. It will remain exhaustive when constructors are added to type repr. File "w04_failure.ml", line 20, characters 2-78: +20 | ..match r1, r2, t with +21 | | AB, _, A -> () +22 | | _, XY, X -> () +23 | | _, _, _ -> () Warning 4: this pattern-matching is fragile. It will remain exhaustive when constructors are added to type ab. File "w04_failure.ml", line 20, characters 2-78: +20 | ..match r1, r2, t with +21 | | AB, _, A -> () +22 | | _, XY, X -> () +23 | | _, _, _ -> () Warning 4: this pattern-matching is fragile. It will remain exhaustive when constructors are added to type xy. diff --git a/testsuite/tests/warnings/w06.compilers.reference b/testsuite/tests/warnings/w06.compilers.reference index 1c602821..4a118e20 100644 --- a/testsuite/tests/warnings/w06.compilers.reference +++ b/testsuite/tests/warnings/w06.compilers.reference @@ -1,4 +1,8 @@ File "w06.ml", line 16, characters 9-12: +16 | let () = foo 2 + ^^^ Warning 6: label bar was omitted in the application of this function. File "w06.ml", line 17, characters 9-12: +17 | let () = bar 4 2 + ^^^ Warning 6: labels foo, baz were omitted in the application of this function. diff --git a/testsuite/tests/warnings/w32.compilers.reference b/testsuite/tests/warnings/w32.compilers.reference index 2d5342db..e1d5fdbd 100644 --- a/testsuite/tests/warnings/w32.compilers.reference +++ b/testsuite/tests/warnings/w32.compilers.reference @@ -1,30 +1,67 @@ File "w32.ml", line 40, characters 24-25: +40 | let[@warning "-32"] rec q x = x + ^ Warning 39: unused rec flag. File "w32.ml", line 43, characters 24-25: +43 | let[@warning "-32"] rec s x = x + ^ Warning 39: unused rec flag. File "w32.ml", line 20, characters 4-5: +20 | let h x = x + ^ Warning 32: unused value h. File "w32.ml", line 26, characters 4-5: +26 | and j x = x + ^ Warning 32: unused value j. File "w32.ml", line 28, characters 4-5: +28 | let k x = x + ^ Warning 32: unused value k. File "w32.ml", line 41, characters 4-5: +41 | and r x = x + ^ Warning 32: unused value r. File "w32.ml", line 44, characters 20-21: +44 | and[@warning "-39"] t x = x + ^ Warning 32: unused value t. File "w32.ml", line 46, characters 24-25: +46 | let[@warning "-39"] rec u x = x + ^ Warning 32: unused value u. File "w32.ml", line 47, characters 4-5: +47 | and v x = v x + ^ Warning 32: unused value v. File "w32.ml", line 55, characters 22-23: +55 | let[@warning "+32"] g x = x + ^ Warning 32: unused value g. File "w32.ml", line 56, characters 22-23: +56 | let[@warning "+32"] h x = x + ^ Warning 32: unused value h. File "w32.ml", line 59, characters 22-23: +59 | and[@warning "+32"] k x = x + ^ Warning 32: unused value k. File "w32.ml", line 52, characters 0-174: +52 | module M = struct +53 | [@@@warning "-32"] +54 | let f x = x +55 | let[@warning "+32"] g x = x +56 | let[@warning "+32"] h x = x +57 | and i x = x +58 | let j x = x +59 | and[@warning "+32"] k x = x +60 | end Warning 60: unused module M. File "w32.ml", line 63, characters 18-29: +63 | module F (X : sig val x : int end) = struct end + ^^^^^^^^^^^ Warning 32: unused value x. File "w32.ml", line 65, characters 18-29: +65 | module G (X : sig val x : int end) = X + ^^^^^^^^^^^ Warning 32: unused value x. diff --git a/testsuite/tests/warnings/w32b.compilers.reference b/testsuite/tests/warnings/w32b.compilers.reference index 9f8837bc..5266ba18 100644 --- a/testsuite/tests/warnings/w32b.compilers.reference +++ b/testsuite/tests/warnings/w32b.compilers.reference @@ -1,2 +1,4 @@ File "w32b.ml", line 13, characters 18-24: +13 | module Q (M : sig type t end) = struct end + ^^^^^^ Warning 34: unused type t. diff --git a/testsuite/tests/warnings/w33.compilers.reference b/testsuite/tests/warnings/w33.compilers.reference index 0b1f4c4b..52b77b10 100644 --- a/testsuite/tests/warnings/w33.compilers.reference +++ b/testsuite/tests/warnings/w33.compilers.reference @@ -1,4 +1,12 @@ File "w33.ml", line 19, characters 6-11: +19 | let f M.(x) = x (* useless open *) + ^^^^^ Warning 33: unused open M. +File "w33.ml", line 26, characters 0-7: +26 | open! M (* useless open! *) + ^^^^^^^ +Warning 66: unused open! M. File "w33.ml", line 27, characters 0-6: +27 | open M (* useless open *) + ^^^^^^ Warning 33: unused open M. diff --git a/testsuite/tests/warnings/w33.ml b/testsuite/tests/warnings/w33.ml index b6faa9af..cff8d9f3 100644 --- a/testsuite/tests/warnings/w33.ml +++ b/testsuite/tests/warnings/w33.ml @@ -23,5 +23,5 @@ let h R.{x} = R.{x} open N (* used open *) let i (A|B) = B -open! M (* open! also deactivates unused open warning *) +open! M (* useless open! *) open M (* useless open *) diff --git a/testsuite/tests/warnings/w45.compilers.reference b/testsuite/tests/warnings/w45.compilers.reference index 9e74aed2..74830f68 100644 --- a/testsuite/tests/warnings/w45.compilers.reference +++ b/testsuite/tests/warnings/w45.compilers.reference @@ -1,7 +1,13 @@ File "w45.ml", line 24, characters 2-9: +24 | open T2 (* shadow X, which is later used; but not A, see #6762 *) + ^^^^^^^ Warning 45: this open statement shadows the constructor X (which is later used) File "w45.ml", line 26, characters 14-15: +26 | let _ = (A, X) (* X belongs to several types *) + ^ Warning 41: X belongs to several types: T2.s T1.s The first one was selected. Please disambiguate if this is wrong. File "w45.ml", line 23, characters 2-9: +23 | open T1 (* unused open *) + ^^^^^^^ Warning 33: unused open T1. diff --git a/testsuite/tests/warnings/w47_inline.compilers.reference b/testsuite/tests/warnings/w47_inline.compilers.reference index e1735a8d..7c9bed8e 100644 --- a/testsuite/tests/warnings/w47_inline.compilers.reference +++ b/testsuite/tests/warnings/w47_inline.compilers.reference @@ -1,15 +1,42 @@ +File "w47_inline.ml", line 30, characters 20-22: +30 | let[@local never] f2 x = x (* ok *) in + ^^ +Warning 26: unused variable f2. +File "w47_inline.ml", line 31, characters 24-26: +31 | let[@local malformed] f3 x = x (* bad payload *) in + ^^ +Warning 26: unused variable f3. File "w47_inline.ml", line 15, characters 23-29: +15 | let d = (fun x -> x) [@inline malformed attribute] (* rejected *) + ^^^^^^ Warning 47: illegal payload for attribute 'inline'. -It must be either empty, 'always' or 'never' +It must be either 'never', 'always' or empty File "w47_inline.ml", line 16, characters 23-29: +16 | let e = (fun x -> x) [@inline malformed_attribute] (* rejected *) + ^^^^^^ Warning 47: illegal payload for attribute 'inline'. -It must be either empty, 'always' or 'never' +It must be either 'never', 'always' or empty File "w47_inline.ml", line 17, characters 23-29: +17 | let f = (fun x -> x) [@inline : malformed_attribute] (* rejected *) + ^^^^^^ Warning 47: illegal payload for attribute 'inline'. -It must be either empty, 'always' or 'never' +It must be either 'never', 'always' or empty File "w47_inline.ml", line 18, characters 23-29: +18 | let g = (fun x -> x) [@inline ? malformed_attribute] (* rejected *) + ^^^^^^ Warning 47: illegal payload for attribute 'inline'. -It must be either empty, 'always' or 'never' +It must be either 'never', 'always' or empty File "w47_inline.ml", line 23, characters 15-22: +23 | let k x = (a [@inlined malformed]) x (* rejected *) + ^^^^^^^ Warning 47: illegal payload for attribute 'inlined'. -It must be either empty, 'always' or 'never' +It must be either 'never', 'always' or empty +File "w47_inline.ml", line 31, characters 7-12: +31 | let[@local malformed] f3 x = x (* bad payload *) in + ^^^^^ +Warning 47: illegal payload for attribute 'local'. +It must be either 'never', 'always', 'maybe' or empty +File "w47_inline.ml", line 32, characters 17-26: +32 | let[@local] f4 x = 2 * x (* not local *) in + ^^^^^^^^^ +Warning 55: Cannot inline: This function cannot be compiled into a static continuation diff --git a/testsuite/tests/warnings/w47_inline.ml b/testsuite/tests/warnings/w47_inline.ml index 8ff34cc8..e4b74860 100644 --- a/testsuite/tests/warnings/w47_inline.ml +++ b/testsuite/tests/warnings/w47_inline.ml @@ -23,3 +23,19 @@ let j x = (a [@inlined always]) x (* accepted *) let k x = (a [@inlined malformed]) x (* rejected *) let l x = x [@@inline] (* accepted *) + + +let test x = + let[@local always] f1 x = x (* ok *) in + let[@local never] f2 x = x (* ok *) in + let[@local malformed] f3 x = x (* bad payload *) in + let[@local] f4 x = 2 * x (* not local *) in + let[@local] f5 x = f1 x (* ok *) in + let[@local] f6 x = 3 * x (* ok *) in + let r = + if x = 1 then f1 x + else if x = 2 then f4 x + else if x = 3 then f1 x + else f5 x + in + f4 (f6 r) diff --git a/testsuite/tests/warnings/w50.compilers.reference b/testsuite/tests/warnings/w50.compilers.reference index 4628e0df..5b41948c 100644 --- a/testsuite/tests/warnings/w50.compilers.reference +++ b/testsuite/tests/warnings/w50.compilers.reference @@ -1,4 +1,8 @@ File "w50.ml", line 13, characters 2-17: +13 | module L = List + ^^^^^^^^^^^^^^^ Warning 60: unused module L. File "w50.ml", line 17, characters 2-16: +17 | module Y1 = X1 + ^^^^^^^^^^^^^^ Warning 60: unused module Y1. diff --git a/testsuite/tests/warnings/w51.compilers.reference b/testsuite/tests/warnings/w51.compilers.reference index 95c98e67..b09e55a9 100644 --- a/testsuite/tests/warnings/w51.compilers.reference +++ b/testsuite/tests/warnings/w51.compilers.reference @@ -1,2 +1,4 @@ File "w51.ml", line 14, characters 13-37: +14 | | n -> n * (fact [@tailcall]) (n-1) + ^^^^^^^^^^^^^^^^^^^^^^^^ Warning 51: expected tailcall diff --git a/testsuite/tests/warnings/w51_bis.compilers.reference b/testsuite/tests/warnings/w51_bis.compilers.reference index aa47c337..79163112 100644 --- a/testsuite/tests/warnings/w51_bis.compilers.reference +++ b/testsuite/tests/warnings/w51_bis.compilers.reference @@ -1,2 +1,4 @@ File "w51_bis.ml", line 15, characters 12-48: +15 | try (foldl [@tailcall]) op (op x acc) xs + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 51: expected tailcall diff --git a/testsuite/tests/warnings/w52.compilers.reference b/testsuite/tests/warnings/w52.compilers.reference deleted file mode 100644 index 546a14e0..00000000 --- a/testsuite/tests/warnings/w52.compilers.reference +++ /dev/null @@ -1,12 +0,0 @@ -File "w52.ml", line 12, characters 38-43: -Warning 52: Code should not depend on the actual values of -this constructor's arguments. They are only for information -and may change in future versions. (See manual section 9.5) -File "w52.ml", line 20, characters 7-17: -Warning 52: Code should not depend on the actual values of -this constructor's arguments. They are only for information -and may change in future versions. (See manual section 9.5) -File "w52.ml", line 25, characters 8-10: -Warning 52: Code should not depend on the actual values of -this constructor's arguments. They are only for information -and may change in future versions. (See manual section 9.5) diff --git a/testsuite/tests/warnings/w52.ml b/testsuite/tests/warnings/w52.ml index 58dec69d..2f9e77be 100644 --- a/testsuite/tests/warnings/w52.ml +++ b/testsuite/tests/warnings/w52.ml @@ -1,33 +1,100 @@ (* TEST - -flags = "-w A" - -* setup-ocamlc.byte-build-env -** ocamlc.byte -compile_only = "true" -*** check-ocamlc.byte-output - + flags = "-w A" + * expect *) let () = try () with Invalid_argument "Any" -> ();; +[%%expect{| +Line 1, characters 38-43: +1 | let () = try () with Invalid_argument "Any" -> ();; + ^^^^^ +Warning 52: Code should not depend on the actual values of +this constructor's arguments. They are only for information +and may change in future versions. (See manual section 9.5) +|}];; + +let () = try () with Match_failure ("Any",_,_) -> ();; +[%%expect{| +Line 1, characters 35-46: +1 | let () = try () with Match_failure ("Any",_,_) -> ();; + ^^^^^^^^^^^ +Warning 52: Code should not depend on the actual values of +this constructor's arguments. They are only for information +and may change in future versions. (See manual section 9.5) +|}];; + +let () = try () with Match_failure (_,0,_) -> ();; +[%%expect{| +Line 1, characters 35-42: +1 | let () = try () with Match_failure (_,0,_) -> ();; + ^^^^^^^ +Warning 52: Code should not depend on the actual values of +this constructor's arguments. They are only for information +and may change in future versions. (See manual section 9.5) +|}];; type t = | Warn of string [@ocaml.warn_on_literal_pattern] | Without_warning of string - | Warn' of nativeint [@ocaml.warn_on_literal_pattern];; + | Warn' of nativeint [@ocaml.warn_on_literal_pattern] + | Deep of (string * int) list [@ocaml.warn_on_literal_pattern];; +[%%expect{| +type t = + Warn of string + | Without_warning of string + | Warn' of nativeint + | Deep of (string * int) list +|}];; let f = function | Warn "anything" -> () -| Warn _ | Warn' _ | Without_warning _ -> () -;; +| Warn _ | Warn' _ | Without_warning _ | Deep _ -> ();; +[%%expect{| +Line 2, characters 7-17: +2 | | Warn "anything" -> () + ^^^^^^^^^^ +Warning 52: Code should not depend on the actual values of +this constructor's arguments. They are only for information +and may change in future versions. (See manual section 9.5) +val f : t -> unit = +|}];; let g = function | Warn' 0n -> () -| Warn _ | Warn' _ | Without_warning _ -> () -;; - +| Warn _ | Warn' _ | Without_warning _ | Deep _ -> ();; +[%%expect{| +Line 2, characters 8-10: +2 | | Warn' 0n -> () + ^^ +Warning 52: Code should not depend on the actual values of +this constructor's arguments. They are only for information +and may change in future versions. (See manual section 9.5) +val g : t -> unit = +|}];; let h = function | Without_warning "outside" -> () -| Warn _ | Warn' _ | Without_warning _ -> () -;; +| Warn _ | Warn' _ | Without_warning _ | Deep _ -> ();; +[%%expect{| +val h : t -> unit = +|}];; + +let i = function +| Deep (_ :: _ :: _ :: _) -> () +| Warn _ | Warn' _ | Without_warning _ | Deep _ -> ();; +[%%expect{| +val i : t -> unit = +|}];; + +let j = function +| Deep (_ :: _ :: ("deep",_) :: _) -> () +| Warn _ | Warn' _ | Without_warning _ | Deep _ -> ();; +[%%expect{| +Line 2, characters 7-34: +2 | | Deep (_ :: _ :: ("deep",_) :: _) -> () + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 52: Code should not depend on the actual values of +this constructor's arguments. They are only for information +and may change in future versions. (See manual section 9.5) +val j : t -> unit = +|}];; diff --git a/testsuite/tests/warnings/w53.compilers.reference b/testsuite/tests/warnings/w53.compilers.reference index 0f37b0d6..e8ee95f3 100644 --- a/testsuite/tests/warnings/w53.compilers.reference +++ b/testsuite/tests/warnings/w53.compilers.reference @@ -1,26 +1,52 @@ File "w53.ml", line 12, characters 4-5: +12 | let h x = x [@inline] (* rejected *) + ^ Warning 32: unused value h. File "w53.ml", line 12, characters 14-20: +12 | let h x = x [@inline] (* rejected *) + ^^^^^^ Warning 53: the "inline" attribute cannot appear in this context File "w53.ml", line 13, characters 14-26: +13 | let h x = x [@ocaml.inline] (* rejected *) + ^^^^^^^^^^^^ Warning 53: the "ocaml.inline" attribute cannot appear in this context File "w53.ml", line 15, characters 14-21: +15 | let i x = x [@inlined] (* rejected *) + ^^^^^^^ Warning 53: the "inlined" attribute cannot appear in this context File "w53.ml", line 16, characters 14-27: +16 | let j x = x [@ocaml.inlined] (* rejected *) + ^^^^^^^^^^^^^ Warning 53: the "ocaml.inlined" attribute cannot appear in this context File "w53.ml", line 19, characters 16-23: +19 | let l x = h x [@inlined] (* rejected *) + ^^^^^^^ Warning 53: the "inlined" attribute cannot appear in this context File "w53.ml", line 21, characters 14-22: +21 | let m x = x [@tailcall] (* rejected *) + ^^^^^^^^ Warning 53: the "tailcall" attribute cannot appear in this context File "w53.ml", line 22, characters 14-28: +22 | let n x = x [@ocaml.tailcall] (* rejected *) + ^^^^^^^^^^^^^^ Warning 53: the "ocaml.tailcall" attribute cannot appear in this context File "w53.ml", line 25, characters 16-24: +25 | let q x = h x [@tailcall] (* rejected *) + ^^^^^^^^ Warning 53: the "tailcall" attribute cannot appear in this context File "w53.ml", line 33, characters 0-32: +33 | module C = struct end [@@inline] (* rejected *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 53: the "inline" attribute cannot appear in this context File "w53.ml", line 34, characters 0-39: +34 | module C' = struct end [@@ocaml.inline] (* rejected *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 53: the "inline" attribute cannot appear in this context File "w53.ml", line 40, characters 16-22: +40 | module G = (A [@inline])(struct end) (* rejected *) + ^^^^^^ Warning 53: the "inline" attribute cannot appear in this context File "w53.ml", line 41, characters 17-29: +41 | module G' = (A [@ocaml.inline])(struct end) (* rejected *) + ^^^^^^^^^^^^ Warning 53: the "ocaml.inline" attribute cannot appear in this context diff --git a/testsuite/tests/warnings/w54.compilers.reference b/testsuite/tests/warnings/w54.compilers.reference index 6a75df34..e476122c 100644 --- a/testsuite/tests/warnings/w54.compilers.reference +++ b/testsuite/tests/warnings/w54.compilers.reference @@ -1,8 +1,16 @@ File "w54.ml", line 12, characters 33-39: +12 | let f = (fun x -> x) [@inline] [@inline never] + ^^^^^^ Warning 54: the "inline" attribute is used more than once on this expression File "w54.ml", line 13, characters 51-63: +13 | let g = (fun x -> x) [@inline] [@something_else] [@ocaml.inline] + ^^^^^^^^^^^^ Warning 54: the "ocaml.inline" attribute is used more than once on this expression File "w54.ml", line 15, characters 26-39: +15 | let h x = (g [@inlined] [@ocaml.inlined never]) x + ^^^^^^^^^^^^^ Warning 54: the "ocaml.inlined" attribute is used more than once on this expression File "w54.ml", line 19, characters 0-43: +19 | let i = ((fun x -> x) [@inline]) [@@inline] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 54: the "inline" attribute is used more than once on this expression diff --git a/testsuite/tests/warnings/w55.flambda.reference b/testsuite/tests/warnings/w55.flambda.reference index f1a5b21a..b7175390 100644 --- a/testsuite/tests/warnings/w55.flambda.reference +++ b/testsuite/tests/warnings/w55.flambda.reference @@ -1,6 +1,12 @@ File "w55.ml", line 33, characters 10-26: +33 | let h x = (j [@inlined]) x + ^^^^^^^^^^^^^^^^ Warning 55: Cannot inline: [@inlined] attributes may not be used on partial applications File "w55.ml", line 29, characters 10-27: +29 | let i x = (!h [@inlined]) x + ^^^^^^^^^^^^^^^^^ Warning 55: Cannot inline: [@inlined] attribute was not used on this function application (the optimizer did not know what function was being applied) File "w55.ml", line 39, characters 12-30: +39 | let b x y = (a [@inlined]) x y + ^^^^^^^^^^^^^^^^^^ Warning 55: Cannot inline: [@inlined] attribute was not used on this function application (the optimizer did not know what function was being applied) diff --git a/testsuite/tests/warnings/w55.native.reference b/testsuite/tests/warnings/w55.native.reference index 31315b26..03e5ea4e 100644 --- a/testsuite/tests/warnings/w55.native.reference +++ b/testsuite/tests/warnings/w55.native.reference @@ -1,12 +1,24 @@ File "w55.ml", line 25, characters 10-26: +25 | let g x = (f [@inlined]) x + ^^^^^^^^^^^^^^^^ Warning 55: Cannot inline: Function information unavailable File "w55.ml", line 29, characters 10-27: +29 | let i x = (!h [@inlined]) x + ^^^^^^^^^^^^^^^^^ Warning 55: Cannot inline: Unknown function File "w55.ml", line 33, characters 10-26: +33 | let h x = (j [@inlined]) x + ^^^^^^^^^^^^^^^^ Warning 55: Cannot inline: Partial application File "w55.ml", line 39, characters 12-30: +39 | let b x y = (a [@inlined]) x y + ^^^^^^^^^^^^^^^^^^ Warning 55: Cannot inline: Over-application File "w55.ml", line 39, characters 12-30: +39 | let b x y = (a [@inlined]) x y + ^^^^^^^^^^^^^^^^^^ Warning 55: Cannot inline: Function information unavailable File "w55.ml", line 42, characters 10-26: +42 | let d x = (c [@inlined]) x + ^^^^^^^^^^^^^^^^ Warning 55: Cannot inline: Function information unavailable diff --git a/testsuite/tests/warnings/w59.flambda.reference b/testsuite/tests/warnings/w59.flambda.reference index c8f62751..912da659 100644 --- a/testsuite/tests/warnings/w59.flambda.reference +++ b/testsuite/tests/warnings/w59.flambda.reference @@ -1,20 +1,30 @@ File "w59.ml", line 46, characters 2-43: +46 | Obj.set_field (Obj.repr o) 0 (Obj.repr 3); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 59: A potential assignment to a non-mutable value was detected in this source file. Such assignments may generate incorrect code when using Flambda. File "w59.ml", line 47, characters 2-43: +47 | Obj.set_field (Obj.repr p) 0 (Obj.repr 3); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 59: A potential assignment to a non-mutable value was detected in this source file. Such assignments may generate incorrect code when using Flambda. File "w59.ml", line 48, characters 2-43: +48 | Obj.set_field (Obj.repr q) 0 (Obj.repr 3); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 59: A potential assignment to a non-mutable value was detected in this source file. Such assignments may generate incorrect code when using Flambda. File "w59.ml", line 49, characters 2-43: +49 | Obj.set_field (Obj.repr r) 0 (Obj.repr 3) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 59: A potential assignment to a non-mutable value was detected in this source file. Such assignments may generate incorrect code when using Flambda. File "w59.ml", line 56, characters 2-7: +56 | set o + ^^^^^ Warning 59: A potential assignment to a non-mutable value was detected in this source file. Such assignments may generate incorrect code when using Flambda. diff --git a/testsuite/tests/win-unicode/Makefile b/testsuite/tests/win-unicode/Makefile deleted file mode 100644 index def3d939..00000000 --- a/testsuite/tests/win-unicode/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -BASEDIR=../.. -LIBRARIES=unix -ADD_COMPFLAGS= \ - -I $(OTOPDIR)/otherlibs/$(UNIXLIBVAR)unix \ - -strict-sequence -safe-string -w A -warn-error A -LD_PATH=$(TOPDIR)/otherlibs/$(UNIXLIBVAR)unix -C_FILES=mkfiles - -.PHONY: test -test: - @if echo 'let () = exit (if Config.windows_unicode then 0 else 1)' | $(OCAML) -I $(OTOPDIR)/utils config.cmo -stdin; then \ - $(MAKE) printargv.exe printenv.exe symlink_tests.precheck && \ - $(MAKE) check; \ - else \ - $(MAKE) SKIP=true C_FILES= run-all; \ - fi - -.PHONY: symlink_tests.precheck -symlink_tests.precheck: - @echo 'echo "let () = exit (if Unix.has_symlink () then 0 else 1)" | $(OCAML) $(ADD_COMPFLAGS) unix.cma -stdin' > $@ - -include $(BASEDIR)/makefiles/Makefile.several -include $(BASEDIR)/makefiles/Makefile.common - -GENERATED_SOURCES=symlink_tests.precheck - -ifeq ($(CCOMPTYPE),msvc) -CCOMP=set -o pipefail ; $(CC) $(CFLAGS) $(CPPFLAGS) /Fe$(1) $(addprefix /link ,$(LDFLAGS)) | tail -n +2 -else -CCOMP=$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $(1) -endif - -%.exe: %.c - @$(call CCOMP,$*.exe $*.c) diff --git a/testsuite/tests/win-unicode/exec_tests.ml b/testsuite/tests/win-unicode/exec_tests.ml deleted file mode 100755 index b0aa2939..00000000 --- a/testsuite/tests/win-unicode/exec_tests.ml +++ /dev/null @@ -1,63 +0,0 @@ -let values = - [ - "\xD0\xB2\xD0\xB5\xD1\x80\xD0\xB1\xD0\xBB\xD1\x8E\xD0\xB4\xD1\x8B"; (* "верблюды" *) - "\xE9\xAA\x86\xE9\xA9\xBC"; (* "骆驼" *) - "\215\167\215\162\215\158\215\156"; (* "קעמל" *) - "\216\167\217\136\217\134\217\185"; (* "اونٹ" *) - ] - -let env0 = - List.sort compare (List.mapi (fun i v -> Printf.sprintf "OCAML_UTF8_VAR%d=%s" i v) values) - -let split sep s = - match String.index s sep with - | i -> - String.sub s 0 i, String.sub s (i + 1) (String.length s - i - 1) - | exception Not_found -> - s, "" - -let test_environment () = - print_endline "test_environment"; - let vars = List.map (fun s -> fst (split '=' s)) env0 in - let f s = List.mem (fst (split '=' s)) vars in - let env = List.filter f (Array.to_list (Unix.environment ())) in - assert (List.length env0 = List.length env); - List.iter2 (fun s1 s2 -> assert (s1 = s2)) env0 env - -let test0 () = - print_endline "test0"; - Unix.execve Sys.executable_name [|Sys.executable_name; "1"|] (Array.of_list env0) - -let test_argv () = - print_endline "test_argv"; - let argv = match Array.to_list Sys.argv with _ :: _ :: argv -> argv | _ -> assert false in - List.iter2 (fun s1 s2 -> assert (s1 = s2)) argv values - -let test1 () = - print_endline "test1"; - Unix.execv Sys.executable_name (Array.of_list (Sys.executable_name :: "2" :: values)) - -let restart = function - | 0 -> test0 () - | 1 -> test_environment (); test1 () - | 2 -> test_argv () - | _ -> assert false - -let main () = - match Array.length Sys.argv with - | 1 -> - let pid = Unix.create_process Sys.executable_name [|Sys.executable_name; "0"|] Unix.stdin Unix.stdout Unix.stderr in - begin match Unix.waitpid [] pid with - | _, Unix.WEXITED 0 -> () - | _, (Unix.WEXITED _ | Unix.WSIGNALED _ | Unix.WSTOPPED _) -> failwith "Child process error" - end - | _ -> - restart (int_of_string Sys.argv.(1)) - -let () = - match main () with - | () -> - Printf.printf "OK\n%!" - | exception e -> - Printf.printf "BAD: %s\n%!" (Printexc.to_string e); - exit 1 diff --git a/testsuite/tests/win-unicode/exec_tests.precheck b/testsuite/tests/win-unicode/exec_tests.precheck deleted file mode 100644 index 6132b219..00000000 --- a/testsuite/tests/win-unicode/exec_tests.precheck +++ /dev/null @@ -1,3 +0,0 @@ -# exec_tests.ml disabled because it fails non-deterministically (at least under CI) -# seems to be a problem redirecting handles -exit 1 diff --git a/testsuite/tests/win-unicode/exec_tests.reference b/testsuite/tests/win-unicode/exec_tests.reference deleted file mode 100644 index 5d6e024a..00000000 --- a/testsuite/tests/win-unicode/exec_tests.reference +++ /dev/null @@ -1,6 +0,0 @@ -test0 -OK -test_environment -test1 -test_argv -OK diff --git a/testsuite/tests/win-unicode/mkfiles.c b/testsuite/tests/win-unicode/mkfiles.c deleted file mode 100644 index 71eab6ea..00000000 --- a/testsuite/tests/win-unicode/mkfiles.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -/* Returns an OCaml string with the UTF-16 representation of [s], *including* the final (2-byte) NULL */ -CAMLprim value caml_to_utf16(value s) -{ - CAMLparam1(s); - CAMLlocal1(w); - int size; - size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, String_val(s), caml_string_length(s), NULL, 0); - if (size == 0) caml_failwith("Invalid UTF-8"); - w = caml_alloc_string((size + 1) * sizeof(wchar_t)); - ((wchar_t *)String_val(w))[size] = 0; - size = MultiByteToWideChar(CP_UTF8, 0, String_val(s), caml_string_length(s), (wchar_t *)String_val(w), size); - assert(size != 0); - CAMLreturn(w); -} - -CAMLprim value caml_create_file(value s, value contents) -{ - CAMLparam2(s, contents); - FILE * f; - f = _wfopen((wchar_t *)String_val(s), _T("w")); - if (f == NULL) caml_failwith("fopen failed"); - fwrite(String_val(contents), 1, caml_string_length(contents), f); - fclose(f); - CAMLreturn(Val_unit); -} diff --git a/testsuite/tests/win-unicode/mltest.compilers.reference b/testsuite/tests/win-unicode/mltest.compilers.reference new file mode 100755 index 00000000..5a17c421 --- /dev/null +++ b/testsuite/tests/win-unicode/mltest.compilers.reference @@ -0,0 +1,83 @@ +val foreign_names : string list = ["été"; "simple"; "sœur"; "你好"] +val test_files : string list = + ["été.txt"; "simple.txt"; "sœur.txt"; "你好.txt"] +val to_create_and_delete_files : string list = + ["верблюды"; "骆驼"; "קעמל"; "اونٹ"; "Lạc đà"; + "ఒంటె"; "ஒட்டகம்"; "وشتر"; + "उष्ट्रः"; "اٺ"] +val foreign_names2 : string list = + ["верблюды"; "骆驼"; "קעמל"; "اونٹ"] +val getenvironmentenv : string -> string = +val unix_getcwd : unit -> string = +val sys_getcwd : unit -> string = +val unix_readdir : string -> string list = +val sys_readdir : string -> string list = +val test_readdir : (string -> string list) -> string list = +val test_open_in : unit -> string list = +val test_getenv : unit -> (string * string) list = +val test_mkdir : unit -> (bool * bool) list = +val test_chdir : (string -> unit) -> (unit -> 'a) -> 'a list = +val test_rmdir : unit -> bool list = +val test_stat : + unit -> + (Unix.file_kind * Unix.file_kind * Unix.file_kind * Unix.file_kind) list = + +val test_access : unit -> unit = +val test_rename : + (string -> string -> unit) -> ((bool * bool) * (bool * bool)) list = +val test_open_out : unit -> string list = +val test_file_exists : unit -> bool list = +val test_remove : unit -> bool list = +val create_file : string -> unit = +val test_symlink : unit -> bool = +- : unit = () +val t_unix_readdir : string list = + ["été.txt"; "simple.txt"; "sœur.txt"; "你好.txt"] +val t_sys_readdir : string list = + ["été.txt"; "simple.txt"; "sœur.txt"; "你好.txt"] +val t_open_in : string list = + ["été.txt"; "simple.txt"; "sœur.txt"; "你好.txt"] +val t_open_out : string list = + ["Hello, верблюды"; "Hello, 骆驼"; "Hello, קעמל"; + "Hello, اونٹ"; "Hello, Lạc đà"; "Hello, ఒంటె"; + "Hello, ஒட்டகம்"; "Hello, وشتر"; + "Hello, उष्ट्रः"; "Hello, اٺ"] +val t_file_exists : bool list = + [true; true; true; true; true; true; true; true; true; true] +val t_stat : + (Unix.file_kind * Unix.file_kind * Unix.file_kind * Unix.file_kind) list = + [(Unix.S_REG, Unix.S_REG, Unix.S_REG, Unix.S_REG); + (Unix.S_REG, Unix.S_REG, Unix.S_REG, Unix.S_REG); + (Unix.S_REG, Unix.S_REG, Unix.S_REG, Unix.S_REG); + (Unix.S_REG, Unix.S_REG, Unix.S_REG, Unix.S_REG); + (Unix.S_REG, Unix.S_REG, Unix.S_REG, Unix.S_REG); + (Unix.S_REG, Unix.S_REG, Unix.S_REG, Unix.S_REG); + (Unix.S_REG, Unix.S_REG, Unix.S_REG, Unix.S_REG); + (Unix.S_REG, Unix.S_REG, Unix.S_REG, Unix.S_REG); + (Unix.S_REG, Unix.S_REG, Unix.S_REG, Unix.S_REG); + (Unix.S_REG, Unix.S_REG, Unix.S_REG, Unix.S_REG)] +- : unit = () +val t_unix_rename : ((bool * bool) * (bool * bool)) list = + [((false, true), (true, false)); ((false, true), (true, false)); + ((false, true), (true, false)); ((false, true), (true, false)); + ((false, true), (true, false)); ((false, true), (true, false)); + ((false, true), (true, false)); ((false, true), (true, false)); + ((false, true), (true, false)); ((false, true), (true, false))] +val t_sys_rename : ((bool * bool) * (bool * bool)) list = + [((false, true), (true, false)); ((false, true), (true, false)); + ((false, true), (true, false)); ((false, true), (true, false)); + ((false, true), (true, false)); ((false, true), (true, false)); + ((false, true), (true, false)); ((false, true), (true, false)); + ((false, true), (true, false)); ((false, true), (true, false))] +- : bool list = +[false; false; false; false; false; false; false; false; false; false] +- : (bool * bool) list = +[(true, true); (true, true); (true, true); (true, true)] +val t_sys_chdir : string list = ["été"; "simple"; "sœur"; "你好"] +val t_unix_chdir : string list = ["été"; "simple"; "sœur"; "你好"] +- : bool list = [false; false; false; false] +val t_getenv : (string * string) list = + [("верблюды", "верблюды"); ("骆驼", "骆驼"); + ("קעמל", "קעמל"); ("اونٹ", "اونٹ")] +- : bool = true + diff --git a/testsuite/tests/win-unicode/mltest.ml b/testsuite/tests/win-unicode/mltest.ml index c22f5a7d..802cf504 100644 --- a/testsuite/tests/win-unicode/mltest.ml +++ b/testsuite/tests/win-unicode/mltest.ml @@ -1,9 +1,9 @@ -let total = ref 0 -let failed = ref 0 -let num = ref 0 - -external to_utf16 : string -> string = "caml_to_utf16" -external create_file : string -> string -> unit = "caml_create_file" +(* TEST +include unix +flags += "-strict-sequence -safe-string -w A -warn-error A" +* windows-unicode +** toplevel +*) let foreign_names = List.sort compare @@ -13,13 +13,16 @@ let foreign_names = "\x73\xC5\x93\x75\x72"; (* "sœur" *) "e\204\129te\204\129"; (* "été" *) ] +;; let test_files = List.map (fun s -> s ^ ".txt") foreign_names +;; let to_create_and_delete_files = [ - "\xD0\xB2\xD0\xB5\xD1\x80\xD0\xB1\xD0\xBB\xD1\x8E\xD0\xB4\xD1\x8B"; (* "верблюды" *) + (* "верблюды" *) + "\xD0\xB2\xD0\xB5\xD1\x80\xD0\xB1\xD0\xBB\xD1\x8E\xD0\xB4\xD1\x8B"; "\xE9\xAA\x86\xE9\xA9\xBC"; (* "骆驼" *) "\215\167\215\162\215\158\215\156"; (* "קעמל" *) "\216\167\217\136\217\134\217\185"; (* "اونٹ" *) @@ -32,385 +35,243 @@ let to_create_and_delete_files = \164\176\224\164\131"; (* "उष्ट्रः" *) "\216\167\217\186"; (* "اٺ" *) ] - -let rec take n l = - if n = 0 then [] - else List.hd l :: take (n-1) (List.tl l) +;; let foreign_names2 = - take (List.length foreign_names) to_create_and_delete_files - -let env0 = - List.sort compare (List.mapi (fun i v -> Printf.sprintf "OCAML_UTF8_VAR%d=%s" i v) foreign_names2) - -let read_all ic = - set_binary_mode_in ic false; - let rec loop acc = - match input_line ic with - | exception End_of_file -> - List.rev acc - | s -> - loop (s :: acc) + let rec take n l = + if n = 0 then [] + else List.hd l :: take (n-1) (List.tl l) in - loop [] - -let split sep s = - match String.index s sep with - | i -> - String.sub s 0 i, String.sub s (i+1) (String.length s - i - 1) - | exception Not_found -> - s, "" + take (List.length foreign_names) to_create_and_delete_files +;; + +(* let env0 = + List.sort compare + (List.mapi (fun i v -> Printf.sprintf "OCAML_UTF8_VAR%d=%s" i v) + foreign_names2) *) + +(* let read_all ic = *) +(* set_binary_mode_in ic false; *) +(* let rec loop acc = *) +(* match input_line ic with *) +(* | exception End_of_file -> *) +(* List.rev acc *) +(* | s -> *) +(* loop (s :: acc) *) +(* in *) +(* loop [] *) (** WRAPPERS *) -let quote s = "\"" ^ s ^ "\"" - -let ok _ = "OK" - -let unit _ = "()" - -let list f l = String.concat " " (List.map f l) - -let ell _ = "..." - -let file_kind = function - | Unix.S_REG -> "S_REG" - | Unix.S_DIR -> "S_DIR" - | Unix.S_CHR -> "S_CHR" - | Unix.S_BLK -> "S_BLK" - | Unix.S_LNK -> "S_LNK" - | Unix.S_FIFO -> "S_FIFO" - | Unix.S_SOCK -> "S_SOCK" - -let wrap s f quote_in x quote_out = - Printf.printf "%s %s ... " s (quote_in x); - match f x with - | x -> - Printf.printf "%s\n%!" (quote_out x); - x - | exception e -> - Printf.printf "FAILED: %s\n%!" (Printexc.to_string e); - raise e - -let wrap2 s f quote_in1 quote_in2 x y quote_out = - Printf.printf "%s %s %s ... " s (quote_in1 x) (quote_in2 y); - match f x y with - | x -> - Printf.printf "%s\n%!" (quote_out x); - x - | exception e -> - Printf.printf "FAILED: %s\n%!" (Printexc.to_string e); - raise e - -let getenv s = - wrap "Sys.getenv" Sys.getenv quote s quote - let getenvironmentenv s = - let get s = - let env = Unix.environment () in - let rec loop i = - if i >= Array.length env then - "" - else begin - let e = env.(i) in - let pos = String.index e '=' in - if String.sub e 0 pos = s then - String.sub e (pos+1) (String.length e - pos - 1) - else - loop (i+1) - end - in - loop 0 + let env = Unix.environment () in + let rec loop i = + if i >= Array.length env then + "" + else begin + let e = env.(i) in + let pos = String.index e '=' in + if String.sub e 0 pos = s then + String.sub e (pos+1) (String.length e - pos - 1) + else + loop (i+1) + end in - wrap "Unix.environment" get quote s quote - -let putenv s x = - wrap2 "Unix.putenv" Unix.putenv quote quote s x ok - -let sys_rename s x = - wrap2 "Sys.rename" Sys.rename quote quote s x ok - -let unix_rename s x = - wrap2 "Unix.rename" Unix.rename quote quote s x ok - -let mkdir s mode = - wrap2 "Unix.mkdir" Unix.mkdir quote string_of_int s mode ok - -let file_exists s = - wrap "Sys.file_exists" Sys.file_exists quote s string_of_bool - -let is_directory s = - wrap "Sys.is_directory" Sys.is_directory quote s string_of_bool - -let unix_chdir s = - wrap "Unix.chdir" Unix.chdir quote s ok - -let sys_chdir s = - wrap "Sys.chdir" Sys.chdir quote s ok + loop 0 +;; let unix_getcwd () = - wrap "Unix.getcwd" (fun s -> Filename.basename (Unix.getcwd s)) unit () quote + Filename.basename (Unix.getcwd ()) +;; let sys_getcwd () = - wrap "Sys.getcwd" (fun s -> Filename.basename (Sys.getcwd s)) unit () quote + Filename.basename (Sys.getcwd ()) +;; -let rmdir s = - wrap "Unix.rmdir" Unix.rmdir quote s ok - -let remove s = - wrap "Sys.remove" Sys.remove quote s ok - -let unlink s = - wrap "Unix.unlink" Unix.unlink quote s ok - -let stat s = - let f s = (Unix.stat s).Unix.st_kind in - wrap "Unix.stat" f quote s file_kind - -let lstat s = - let f s = (Unix.lstat s).Unix.st_kind in - wrap "Unix.lstat" f quote s file_kind - -let large_stat s = - let f s = (Unix.LargeFile.stat s).Unix.LargeFile.st_kind in - wrap "Unix.LargeFile.stat" f quote s file_kind - -let large_lstat s = - let f s = (Unix.LargeFile.lstat s).Unix.LargeFile.st_kind in - wrap "Unix.LargeFile.lstat" f quote s file_kind - -let access s = - let f s = Unix.access s [Unix.F_OK] in - wrap "Unix.access" f quote s ok - -let unix_readdir f s = - let f s = - let h = Unix.opendir s in - let rec loop acc = - match Unix.readdir h with - | s -> - if f s then - loop (s :: acc) - else - loop acc - | exception End_of_file -> - Unix.closedir h; - List.sort compare acc - in - loop [] - in - wrap "Unix.{opendir,readdir}" f quote s (list quote) - -let sys_readdir f s = - let f s = - let entries = Sys.readdir s in - List.sort compare (List.filter f (Array.to_list entries)) - in - wrap "Sys.readdir" f quote s (list quote) - -let open_in s = - wrap "open_in" open_in quote s ok - -let open_out s = - wrap "open_out" open_out quote s ok - -let open_process_in cmdline = - let f cmdline = - let ic as proc = Unix.open_process_in cmdline in - let l = List.tl (read_all ic) in - ignore (Unix.close_process_in proc); - l - in - wrap "Unix.open_process_in" f ell cmdline (list quote) - -let open_process_full filter cmdline env = - let f cmdline env = - let (ic, _, _) as proc = Unix.open_process_full cmdline (Array.of_list env) in - let l = read_all ic in - ignore (Unix.close_process_full proc); - List.sort compare (List.filter filter l) +let unix_readdir s = + let h = Unix.opendir s in + let rec loop acc = + match Unix.readdir h with + | s -> + loop (s :: acc) + | exception End_of_file -> + Unix.closedir h; + acc in - wrap2 "Unix.open_process_full" f ell (list quote) cmdline env (list quote) - -(** TESTS *) - -let title s = - let s = Printf.sprintf "Testing %s" s in - let u = String.make (String.length s) '=' in - Printf.printf "\n#%02d. %s\n%s\n\n%!" !num s u - -let expect_gen quote x b = - total := !total + 1; - if x <> b then begin - Printf.printf "** ERROR: EXPECTED RESULT = %s ACTUAL RESULT = %s\n%!" (quote x) (quote b); - failed := !failed + 1 - end - -let expect_file_kind x b = - expect_gen file_kind x b - -let expect_string x s = - expect_gen quote x s - -let expect_bool x b = - expect_gen string_of_bool x b - -let expect_int x b = - expect_gen string_of_int x b + List.sort compare (loop []) +;; + +let sys_readdir s = + List.sort compare (Array.to_list (Sys.readdir s)) +;; + +(* let open_process_in cmdline = *) +(* let f cmdline = *) +(* let ic as proc = Unix.open_process_in cmdline in *) +(* let l = List.tl (read_all ic) in *) +(* ignore (Unix.close_process_in proc); *) +(* l *) +(* in *) +(* wrap "Unix.open_process_in" f ell cmdline (list quote) *) + +(* let open_process_full filter cmdline env = + let f cmdline env = + let (ic, _, _) as proc = + Unix.open_process_full cmdline (Array.of_list env) + in + let l = read_all ic in + ignore (Unix.close_process_full proc); + List.sort compare (List.filter filter l) + in + wrap2 "Unix.open_process_full" f ell (list quote) cmdline env (list quote) +*) let test_readdir readdir = - let filter s = List.mem s test_files in - let entries = readdir filter Filename.current_dir_name in - let entries = List.filter (fun s -> Filename.check_suffix s ".txt") entries in - expect_int (List.length entries) (List.length test_files); - List.iter2 expect_string entries test_files + let filter s = List.mem s test_files && Filename.check_suffix s ".txt" in + List.filter filter (readdir Filename.current_dir_name) +;; let test_open_in () = - let dump_file s = + let check s = let ic = open_in s in let l = input_line ic in close_in ic; - expect_string s l + l in let filter s = List.mem s test_files in - let files = sys_readdir filter Filename.current_dir_name in - List.iter dump_file files + let files = List.filter filter (sys_readdir Filename.current_dir_name) in + List.map check files +;; let test_getenv () = let doit key s = - putenv key s; - expect_string (getenv key) s; - expect_string (getenvironmentenv key) s + Unix.putenv key s; + Sys.getenv key, getenvironmentenv key in - List.iter2 doit foreign_names foreign_names2 + List.map2 doit foreign_names foreign_names2 +;; let test_mkdir () = let doit s = - mkdir s 0o755; - expect_bool (file_exists s) true; - expect_bool (is_directory s) true + Unix.mkdir s 0o755; + Sys.file_exists s, Sys.is_directory s in - List.iter doit foreign_names + List.map doit foreign_names +;; let test_chdir chdir getcwd = let doit s = chdir s; - expect_string (getcwd ()) s; - chdir Filename.parent_dir_name + let d = getcwd () in + chdir Filename.parent_dir_name; + d in - List.iter doit foreign_names + List.map doit foreign_names +;; let test_rmdir () = let doit s = - rmdir s; - expect_bool (file_exists s) false + Unix.rmdir s; + Sys.file_exists s in - List.iter doit foreign_names + List.map doit foreign_names +;; let test_stat () = let doit s = - expect_file_kind (stat s) Unix.S_REG; - expect_file_kind (lstat s) Unix.S_REG; - expect_file_kind (large_stat s) Unix.S_REG; - expect_file_kind (large_lstat s) Unix.S_REG + (Unix.stat s).Unix.st_kind, + (Unix.lstat s).Unix.st_kind, + (Unix.LargeFile.stat s).Unix.LargeFile.st_kind, + (Unix.LargeFile.lstat s).Unix.LargeFile.st_kind in - List.iter doit to_create_and_delete_files + List.map doit to_create_and_delete_files +;; let test_access () = - List.iter access to_create_and_delete_files + List.iter (fun s -> Unix.access s [Unix.F_OK]) to_create_and_delete_files let test_rename rename = let doit s = let s' = s ^ "-1" in rename s s'; - expect_bool (file_exists s) false; - expect_bool (file_exists s') true; + let x = Sys.file_exists s, Sys.file_exists s' in rename s' s; - expect_bool (file_exists s) true; - expect_bool (file_exists s') false + let y = Sys.file_exists s, Sys.file_exists s' in + x, y in - List.iter doit to_create_and_delete_files + List.map doit to_create_and_delete_files +;; let test_open_out () = let doit s = let oc = open_out s in Printf.fprintf oc "Hello, %s\n" s; - close_out oc + close_out oc; + let ic = open_in s in + let l = input_line ic in + close_in ic; + l in - List.iter doit to_create_and_delete_files + List.map doit to_create_and_delete_files +;; -let test_file_exists expected = - let doit s = - expect_bool (file_exists s) expected; - in - List.iter doit to_create_and_delete_files +let test_file_exists () = + List.map Sys.file_exists to_create_and_delete_files +;; -let test_remove remove = +let test_remove () = let doit s = - remove s; - expect_bool (file_exists s) false + Sys.remove s; + Sys.file_exists s in - List.iter doit to_create_and_delete_files - -let test_open_process_in () = - let cmdline = - String.concat " " (Filename.concat Filename.current_dir_name "printargv.exe" :: List.map Filename.quote to_create_and_delete_files) + List.map doit to_create_and_delete_files +;; + +let create_file s = + let oc = open_out_bin s in + output_string oc s; + close_out oc +;; + +let test_symlink () = + let foodir = "UNIQU\xE4\xBD\xA0\xE5\xA5\xBD" (* "UNIQU你好" *) in + let foofile = "UNIQU\xE4\xBD\xA0\xE5\xA5\xBD/\xE4\xBD\xA0\xE5\xA5\xBD.txt" + (* "UNIQU你好/你好.txt" *) in - let l = open_process_in cmdline in - List.iter2 expect_string l to_create_and_delete_files - -let test_open_process_full () = - let vars = List.map (fun s -> fst (split '=' s)) env0 in - let filter s = List.mem (fst (split '=' s)) vars in - let l = open_process_full filter (Filename.concat Filename.current_dir_name "printenv.exe") env0 in - expect_int (List.length env0) (List.length l); - List.iter2 expect_string env0 l - -(* Order matters *) -let tests = - [| - "test_readdir unix_readdir", (fun () -> test_readdir unix_readdir); - "test_readdir sys_readdir", (fun () -> test_readdir sys_readdir); - "test_open_in", test_open_in; - "test_open_out", test_open_out; - "test_file_exists", (fun () -> test_file_exists true); - "test_stat", test_stat; - "test_access", test_access; - "test_rename unix_rename", (fun () -> test_rename unix_rename); - "test_rename sys_rename", (fun () -> test_rename sys_rename); - "test_remove remove", (fun () -> test_remove remove); - "test_file_exists", (fun () -> test_file_exists false); - "test_mkdir", test_mkdir; - "test_chdir sys_chdir sys_getcwd", (fun () -> test_chdir sys_chdir sys_getcwd); - "test_chdir unix_chdir unix_getcwd", (fun () -> test_chdir unix_chdir unix_getcwd); - "test_rmdir", test_rmdir; - "test_getenv", test_getenv; - "test_open_process_in", test_open_process_in; - "test_open_process_full", test_open_process_full; - |] - -(** MAIN *) - -let prepare () = - List.iter (fun s -> create_file (to_utf16 s) s) test_files - -let cleanup () = - List.iter Sys.remove test_files - -let main () = - for i = 0 to Array.length tests - 1 do - num := !num + 1; - let s, f = tests.(i) in - title s; - f () - done; - Printf.printf "\n\n*** ALL TESTS DONE (%d/%d OK) ***\n%!" (!total - !failed) !total - -let () = - try - prepare (); - main (); - cleanup () - with e -> - Printf.printf "** ERROR: %s\n%!" (Printexc.to_string e); - exit 1 + let fileln = "\xE4\xBD\xA0\xE5\xA5\xBD-file-ln-s" (* "你好-file-ln-s" *) in + let dirln = "\xE4\xBD\xA0\xE5\xA5\xBD-dir-ln-s" (* "你好-dir-ln-s" *) in + Unix.mkdir foodir 0o777; + create_file foofile; + Unix.symlink ~to_dir:true foodir dirln; + Unix.symlink ~to_dir:false foofile fileln; + let res = + (Unix.stat fileln).Unix.st_kind = Unix.S_REG && + (Unix.stat dirln).Unix.st_kind = Unix.S_DIR && + (Unix.lstat fileln).Unix.st_kind = Unix.S_LNK && + (Unix.lstat dirln).Unix.st_kind = Unix.S_LNK + in + Sys.remove foofile; + Sys.remove fileln; + Unix.rmdir dirln; + Unix.rmdir foodir; + res +;; + +List.iter create_file test_files;; + +let t_unix_readdir = test_readdir unix_readdir;; +let t_sys_readdir = test_readdir sys_readdir;; +let t_open_in = test_open_in ();; +let t_open_out = test_open_out ();; +let t_file_exists = test_file_exists ();; +let t_stat = test_stat ();; +test_access ();; +let t_unix_rename = test_rename Unix.rename;; +let t_sys_rename = test_rename Sys.rename;; +test_remove ();; +test_mkdir ();; +let t_sys_chdir = test_chdir Sys.chdir sys_getcwd;; +let t_unix_chdir = test_chdir Unix.chdir unix_getcwd;; +test_rmdir ();; +let t_getenv = test_getenv ();; +if Unix.has_symlink () then test_symlink () else true;; diff --git a/testsuite/tests/win-unicode/mltest.reference b/testsuite/tests/win-unicode/mltest.reference deleted file mode 100644 index 3a70cf8f..00000000 --- a/testsuite/tests/win-unicode/mltest.reference +++ /dev/null @@ -1,360 +0,0 @@ - -#01. Testing test_readdir unix_readdir -================================= - -Unix.{opendir,readdir} "." ... "été.txt" "simple.txt" "sœur.txt" "你好.txt" - -#02. Testing test_readdir sys_readdir -================================ - -Sys.readdir "." ... "été.txt" "simple.txt" "sœur.txt" "你好.txt" - -#03. Testing test_open_in -==================== - -Sys.readdir "." ... "été.txt" "simple.txt" "sœur.txt" "你好.txt" -open_in "été.txt" ... OK -open_in "simple.txt" ... OK -open_in "sœur.txt" ... OK -open_in "你好.txt" ... OK - -#04. Testing test_open_out -===================== - -open_out "верблюды" ... OK -open_out "骆驼" ... OK -open_out "קעמל" ... OK -open_out "اونٹ" ... OK -open_out "Lạc đà" ... OK -open_out "ఒంటె" ... OK -open_out "ஒட்டகம்" ... OK -open_out "وشتر" ... OK -open_out "उष्ट्रः" ... OK -open_out "اٺ" ... OK - -#05. Testing test_file_exists -======================== - -Sys.file_exists "верблюды" ... true -Sys.file_exists "骆驼" ... true -Sys.file_exists "קעמל" ... true -Sys.file_exists "اونٹ" ... true -Sys.file_exists "Lạc đà" ... true -Sys.file_exists "ఒంటె" ... true -Sys.file_exists "ஒட்டகம்" ... true -Sys.file_exists "وشتر" ... true -Sys.file_exists "उष्ट्रः" ... true -Sys.file_exists "اٺ" ... true - -#06. Testing test_stat -================= - -Unix.stat "верблюды" ... S_REG -Unix.lstat "верблюды" ... S_REG -Unix.LargeFile.stat "верблюды" ... S_REG -Unix.LargeFile.lstat "верблюды" ... S_REG -Unix.stat "骆驼" ... S_REG -Unix.lstat "骆驼" ... S_REG -Unix.LargeFile.stat "骆驼" ... S_REG -Unix.LargeFile.lstat "骆驼" ... S_REG -Unix.stat "קעמל" ... S_REG -Unix.lstat "קעמל" ... S_REG -Unix.LargeFile.stat "קעמל" ... S_REG -Unix.LargeFile.lstat "קעמל" ... S_REG -Unix.stat "اونٹ" ... S_REG -Unix.lstat "اونٹ" ... S_REG -Unix.LargeFile.stat "اونٹ" ... S_REG -Unix.LargeFile.lstat "اونٹ" ... S_REG -Unix.stat "Lạc đà" ... S_REG -Unix.lstat "Lạc đà" ... S_REG -Unix.LargeFile.stat "Lạc đà" ... S_REG -Unix.LargeFile.lstat "Lạc đà" ... S_REG -Unix.stat "ఒంటె" ... S_REG -Unix.lstat "ఒంటె" ... S_REG -Unix.LargeFile.stat "ఒంటె" ... S_REG -Unix.LargeFile.lstat "ఒంటె" ... S_REG -Unix.stat "ஒட்டகம்" ... S_REG -Unix.lstat "ஒட்டகம்" ... S_REG -Unix.LargeFile.stat "ஒட்டகம்" ... S_REG -Unix.LargeFile.lstat "ஒட்டகம்" ... S_REG -Unix.stat "وشتر" ... S_REG -Unix.lstat "وشتر" ... S_REG -Unix.LargeFile.stat "وشتر" ... S_REG -Unix.LargeFile.lstat "وشتر" ... S_REG -Unix.stat "उष्ट्रः" ... S_REG -Unix.lstat "उष्ट्रः" ... S_REG -Unix.LargeFile.stat "उष्ट्रः" ... S_REG -Unix.LargeFile.lstat "उष्ट्रः" ... S_REG -Unix.stat "اٺ" ... S_REG -Unix.lstat "اٺ" ... S_REG -Unix.LargeFile.stat "اٺ" ... S_REG -Unix.LargeFile.lstat "اٺ" ... S_REG - -#07. Testing test_access -=================== - -Unix.access "верблюды" ... OK -Unix.access "骆驼" ... OK -Unix.access "קעמל" ... OK -Unix.access "اونٹ" ... OK -Unix.access "Lạc đà" ... OK -Unix.access "ఒంటె" ... OK -Unix.access "ஒட்டகம்" ... OK -Unix.access "وشتر" ... OK -Unix.access "उष्ट्रः" ... OK -Unix.access "اٺ" ... OK - -#08. Testing test_rename unix_rename -=============================== - -Unix.rename "верблюды" "верблюды-1" ... OK -Sys.file_exists "верблюды" ... false -Sys.file_exists "верблюды-1" ... true -Unix.rename "верблюды-1" "верблюды" ... OK -Sys.file_exists "верблюды" ... true -Sys.file_exists "верблюды-1" ... false -Unix.rename "骆驼" "骆驼-1" ... OK -Sys.file_exists "骆驼" ... false -Sys.file_exists "骆驼-1" ... true -Unix.rename "骆驼-1" "骆驼" ... OK -Sys.file_exists "骆驼" ... true -Sys.file_exists "骆驼-1" ... false -Unix.rename "קעמל" "קעמל-1" ... OK -Sys.file_exists "קעמל" ... false -Sys.file_exists "קעמל-1" ... true -Unix.rename "קעמל-1" "קעמל" ... OK -Sys.file_exists "קעמל" ... true -Sys.file_exists "קעמל-1" ... false -Unix.rename "اونٹ" "اونٹ-1" ... OK -Sys.file_exists "اونٹ" ... false -Sys.file_exists "اونٹ-1" ... true -Unix.rename "اونٹ-1" "اونٹ" ... OK -Sys.file_exists "اونٹ" ... true -Sys.file_exists "اونٹ-1" ... false -Unix.rename "Lạc đà" "Lạc đà-1" ... OK -Sys.file_exists "Lạc đà" ... false -Sys.file_exists "Lạc đà-1" ... true -Unix.rename "Lạc đà-1" "Lạc đà" ... OK -Sys.file_exists "Lạc đà" ... true -Sys.file_exists "Lạc đà-1" ... false -Unix.rename "ఒంటె" "ఒంటె-1" ... OK -Sys.file_exists "ఒంటె" ... false -Sys.file_exists "ఒంటె-1" ... true -Unix.rename "ఒంటె-1" "ఒంటె" ... OK -Sys.file_exists "ఒంటె" ... true -Sys.file_exists "ఒంటె-1" ... false -Unix.rename "ஒட்டகம்" "ஒட்டகம்-1" ... OK -Sys.file_exists "ஒட்டகம்" ... false -Sys.file_exists "ஒட்டகம்-1" ... true -Unix.rename "ஒட்டகம்-1" "ஒட்டகம்" ... OK -Sys.file_exists "ஒட்டகம்" ... true -Sys.file_exists "ஒட்டகம்-1" ... false -Unix.rename "وشتر" "وشتر-1" ... OK -Sys.file_exists "وشتر" ... false -Sys.file_exists "وشتر-1" ... true -Unix.rename "وشتر-1" "وشتر" ... OK -Sys.file_exists "وشتر" ... true -Sys.file_exists "وشتر-1" ... false -Unix.rename "उष्ट्रः" "उष्ट्रः-1" ... OK -Sys.file_exists "उष्ट्रः" ... false -Sys.file_exists "उष्ट्रः-1" ... true -Unix.rename "उष्ट्रः-1" "उष्ट्रः" ... OK -Sys.file_exists "उष्ट्रः" ... true -Sys.file_exists "उष्ट्रः-1" ... false -Unix.rename "اٺ" "اٺ-1" ... OK -Sys.file_exists "اٺ" ... false -Sys.file_exists "اٺ-1" ... true -Unix.rename "اٺ-1" "اٺ" ... OK -Sys.file_exists "اٺ" ... true -Sys.file_exists "اٺ-1" ... false - -#09. Testing test_rename sys_rename -============================== - -Sys.rename "верблюды" "верблюды-1" ... OK -Sys.file_exists "верблюды" ... false -Sys.file_exists "верблюды-1" ... true -Sys.rename "верблюды-1" "верблюды" ... OK -Sys.file_exists "верблюды" ... true -Sys.file_exists "верблюды-1" ... false -Sys.rename "骆驼" "骆驼-1" ... OK -Sys.file_exists "骆驼" ... false -Sys.file_exists "骆驼-1" ... true -Sys.rename "骆驼-1" "骆驼" ... OK -Sys.file_exists "骆驼" ... true -Sys.file_exists "骆驼-1" ... false -Sys.rename "קעמל" "קעמל-1" ... OK -Sys.file_exists "קעמל" ... false -Sys.file_exists "קעמל-1" ... true -Sys.rename "קעמל-1" "קעמל" ... OK -Sys.file_exists "קעמל" ... true -Sys.file_exists "קעמל-1" ... false -Sys.rename "اونٹ" "اونٹ-1" ... OK -Sys.file_exists "اونٹ" ... false -Sys.file_exists "اونٹ-1" ... true -Sys.rename "اونٹ-1" "اونٹ" ... OK -Sys.file_exists "اونٹ" ... true -Sys.file_exists "اونٹ-1" ... false -Sys.rename "Lạc đà" "Lạc đà-1" ... OK -Sys.file_exists "Lạc đà" ... false -Sys.file_exists "Lạc đà-1" ... true -Sys.rename "Lạc đà-1" "Lạc đà" ... OK -Sys.file_exists "Lạc đà" ... true -Sys.file_exists "Lạc đà-1" ... false -Sys.rename "ఒంటె" "ఒంటె-1" ... OK -Sys.file_exists "ఒంటె" ... false -Sys.file_exists "ఒంటె-1" ... true -Sys.rename "ఒంటె-1" "ఒంటె" ... OK -Sys.file_exists "ఒంటె" ... true -Sys.file_exists "ఒంటె-1" ... false -Sys.rename "ஒட்டகம்" "ஒட்டகம்-1" ... OK -Sys.file_exists "ஒட்டகம்" ... false -Sys.file_exists "ஒட்டகம்-1" ... true -Sys.rename "ஒட்டகம்-1" "ஒட்டகம்" ... OK -Sys.file_exists "ஒட்டகம்" ... true -Sys.file_exists "ஒட்டகம்-1" ... false -Sys.rename "وشتر" "وشتر-1" ... OK -Sys.file_exists "وشتر" ... false -Sys.file_exists "وشتر-1" ... true -Sys.rename "وشتر-1" "وشتر" ... OK -Sys.file_exists "وشتر" ... true -Sys.file_exists "وشتر-1" ... false -Sys.rename "उष्ट्रः" "उष्ट्रः-1" ... OK -Sys.file_exists "उष्ट्रः" ... false -Sys.file_exists "उष्ट्रः-1" ... true -Sys.rename "उष्ट्रः-1" "उष्ट्रः" ... OK -Sys.file_exists "उष्ट्रः" ... true -Sys.file_exists "उष्ट्रः-1" ... false -Sys.rename "اٺ" "اٺ-1" ... OK -Sys.file_exists "اٺ" ... false -Sys.file_exists "اٺ-1" ... true -Sys.rename "اٺ-1" "اٺ" ... OK -Sys.file_exists "اٺ" ... true -Sys.file_exists "اٺ-1" ... false - -#10. Testing test_remove remove -========================== - -Sys.remove "верблюды" ... OK -Sys.file_exists "верблюды" ... false -Sys.remove "骆驼" ... OK -Sys.file_exists "骆驼" ... false -Sys.remove "קעמל" ... OK -Sys.file_exists "קעמל" ... false -Sys.remove "اونٹ" ... OK -Sys.file_exists "اونٹ" ... false -Sys.remove "Lạc đà" ... OK -Sys.file_exists "Lạc đà" ... false -Sys.remove "ఒంటె" ... OK -Sys.file_exists "ఒంటె" ... false -Sys.remove "ஒட்டகம்" ... OK -Sys.file_exists "ஒட்டகம்" ... false -Sys.remove "وشتر" ... OK -Sys.file_exists "وشتر" ... false -Sys.remove "उष्ट्रः" ... OK -Sys.file_exists "उष्ट्रः" ... false -Sys.remove "اٺ" ... OK -Sys.file_exists "اٺ" ... false - -#11. Testing test_file_exists -======================== - -Sys.file_exists "верблюды" ... false -Sys.file_exists "骆驼" ... false -Sys.file_exists "קעמל" ... false -Sys.file_exists "اونٹ" ... false -Sys.file_exists "Lạc đà" ... false -Sys.file_exists "ఒంటె" ... false -Sys.file_exists "ஒட்டகம்" ... false -Sys.file_exists "وشتر" ... false -Sys.file_exists "उष्ट्रः" ... false -Sys.file_exists "اٺ" ... false - -#12. Testing test_mkdir -================== - -Unix.mkdir "été" 493 ... OK -Sys.file_exists "été" ... true -Sys.is_directory "été" ... true -Unix.mkdir "simple" 493 ... OK -Sys.file_exists "simple" ... true -Sys.is_directory "simple" ... true -Unix.mkdir "sœur" 493 ... OK -Sys.file_exists "sœur" ... true -Sys.is_directory "sœur" ... true -Unix.mkdir "你好" 493 ... OK -Sys.file_exists "你好" ... true -Sys.is_directory "你好" ... true - -#13. Testing test_chdir sys_chdir sys_getcwd -======================================= - -Sys.chdir "été" ... OK -Sys.getcwd () ... "été" -Sys.chdir ".." ... OK -Sys.chdir "simple" ... OK -Sys.getcwd () ... "simple" -Sys.chdir ".." ... OK -Sys.chdir "sœur" ... OK -Sys.getcwd () ... "sœur" -Sys.chdir ".." ... OK -Sys.chdir "你好" ... OK -Sys.getcwd () ... "你好" -Sys.chdir ".." ... OK - -#14. Testing test_chdir unix_chdir unix_getcwd -========================================= - -Unix.chdir "été" ... OK -Unix.getcwd () ... "été" -Unix.chdir ".." ... OK -Unix.chdir "simple" ... OK -Unix.getcwd () ... "simple" -Unix.chdir ".." ... OK -Unix.chdir "sœur" ... OK -Unix.getcwd () ... "sœur" -Unix.chdir ".." ... OK -Unix.chdir "你好" ... OK -Unix.getcwd () ... "你好" -Unix.chdir ".." ... OK - -#15. Testing test_rmdir -================== - -Unix.rmdir "été" ... OK -Sys.file_exists "été" ... false -Unix.rmdir "simple" ... OK -Sys.file_exists "simple" ... false -Unix.rmdir "sœur" ... OK -Sys.file_exists "sœur" ... false -Unix.rmdir "你好" ... OK -Sys.file_exists "你好" ... false - -#16. Testing test_getenv -=================== - -Unix.putenv "été" "верблюды" ... OK -Sys.getenv "été" ... "верблюды" -Unix.environment "été" ... "верблюды" -Unix.putenv "simple" "骆驼" ... OK -Sys.getenv "simple" ... "骆驼" -Unix.environment "simple" ... "骆驼" -Unix.putenv "sœur" "קעמל" ... OK -Sys.getenv "sœur" ... "קעמל" -Unix.environment "sœur" ... "קעמל" -Unix.putenv "你好" "اونٹ" ... OK -Sys.getenv "你好" ... "اونٹ" -Unix.environment "你好" ... "اونٹ" - -#17. Testing test_open_process_in -============================ - -Unix.open_process_in ... ... "верблюды" "骆驼" "קעמל" "اونٹ" "Lạc đà" "ఒంటె" "ஒட்டகம்" "وشتر" "उष्ट्रः" "اٺ" - -#18. Testing test_open_process_full -============================== - -Unix.open_process_full ... "OCAML_UTF8_VAR0=верблюды" "OCAML_UTF8_VAR1=骆驼" "OCAML_UTF8_VAR2=קעמל" "OCAML_UTF8_VAR3=اونٹ" ... "OCAML_UTF8_VAR0=верблюды" "OCAML_UTF8_VAR1=骆驼" "OCAML_UTF8_VAR2=קעמל" "OCAML_UTF8_VAR3=اونٹ" - - -*** ALL TESTS DONE (207/207 OK) *** diff --git a/testsuite/tests/win-unicode/ocamltests b/testsuite/tests/win-unicode/ocamltests new file mode 100644 index 00000000..681ef54c --- /dev/null +++ b/testsuite/tests/win-unicode/ocamltests @@ -0,0 +1 @@ +mltest.ml diff --git a/testsuite/tests/win-unicode/printargv.c b/testsuite/tests/win-unicode/printargv.c deleted file mode 100755 index 78bfbbdf..00000000 --- a/testsuite/tests/win-unicode/printargv.c +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include - -#include - -int wmain(int argc, wchar_t ** argv) -{ - int len; - char * p; - - int i; - for (i = 0; i < argc; i ++) { - /* printf("%S\n", argv[i]); */ - len = WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL); - assert(len != 0); - p = malloc(len); - len = WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, p, len, NULL, NULL); - assert(len != 0); - printf("%s\n", p); - free(p); - } - fflush(stdout); - return 0; -} diff --git a/testsuite/tests/win-unicode/printenv.c b/testsuite/tests/win-unicode/printenv.c deleted file mode 100755 index 33dfb50f..00000000 --- a/testsuite/tests/win-unicode/printenv.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include - -#ifdef _WIN32 - -#include - -int wmain(int argc, char ** argv, wchar_t ** envp) -{ - wchar_t * p; - char * s; - int i = 0, len; - while (envp[i]) { - p = envp[i++]; - len = WideCharToMultiByte(CP_UTF8, 0, p, -1, NULL, 0, NULL, NULL); - assert(len != 0); - s = malloc(len); - len = WideCharToMultiByte(CP_UTF8, 0, p, -1, s, len, NULL, NULL); - assert(len != 0); - printf("%s\n", s); - free(s); - } - return 0; -} - -#else - -int main(int argc, char ** argv, char ** env) -{ - int i = 0; - while (env[i]) - printf("%s\n", env[i++]); - return 0; -} - -#endif diff --git a/testsuite/tests/win-unicode/symlink_tests.ml b/testsuite/tests/win-unicode/symlink_tests.ml deleted file mode 100755 index b51121ce..00000000 --- a/testsuite/tests/win-unicode/symlink_tests.ml +++ /dev/null @@ -1,27 +0,0 @@ -external to_utf16 : string -> string = "caml_to_utf16" -external create_file : string -> string -> unit = "caml_create_file" - -let foodir = "UNIQU\xE4\xBD\xA0\xE5\xA5\xBD" (* "UNIQU你好" *) -let foofile = "UNIQU\xE4\xBD\xA0\xE5\xA5\xBD/\xE4\xBD\xA0\xE5\xA5\xBD.txt" (* "UNIQU你好/你好.txt" *) -let foofile2 = "UNIQU\xE4\xBD\xA0\xE5\xA5\xBD\\\xE4\xBD\xA0\xE5\xA5\xBD.txt" (* "UNIQU你好\\你好.txt" *) -let fileln = "\xE4\xBD\xA0\xE5\xA5\xBD-file-ln-s" (* "你好-file-ln-s" *) -let dirln = "\xE4\xBD\xA0\xE5\xA5\xBD-dir-ln-s" (* "你好-dir-ln-s" *) - -open Unix - -let () = - mkdir foodir 0o777; - create_file (to_utf16 foofile) foofile; - symlink ~to_dir:true foodir dirln; - symlink ~to_dir:false (if Sys.win32 then foofile2 else foofile) fileln; (* workaround MPR#7564 *) - assert ((stat fileln).st_kind = S_REG); - assert ((stat dirln).st_kind = S_DIR); - assert ((lstat fileln).st_kind = S_LNK); - assert ((lstat dirln).st_kind = S_LNK); - Sys.remove foofile; - Sys.remove fileln; - rmdir dirln; - rmdir foodir - -let () = - print_endline "OK." diff --git a/testsuite/tests/win-unicode/symlink_tests.reference b/testsuite/tests/win-unicode/symlink_tests.reference deleted file mode 100644 index d5c32f4a..00000000 --- a/testsuite/tests/win-unicode/symlink_tests.reference +++ /dev/null @@ -1 +0,0 @@ -OK. diff --git a/testsuite/tools/Makefile b/testsuite/tools/Makefile index 2abced57..9027bf61 100644 --- a/testsuite/tools/Makefile +++ b/testsuite/tools/Makefile @@ -12,20 +12,72 @@ #* * #************************************************************************** -BASEDIR=.. -MAIN=expect_test -PROG=$(MAIN)$(EXE) -COMPFLAGS=-I $(OTOPDIR)/parsing -I $(OTOPDIR)/utils \ - -I $(OTOPDIR)/driver -I $(OTOPDIR)/toplevel -LIBRARIES=../../compilerlibs/ocamlcommon \ - ../../compilerlibs/ocamlbytecomp \ - ../../compilerlibs/ocamltoplevel - -$(PROG): $(MAIN).cmo $(LIBRARIES:=.cma) - $(OCAMLC) -linkall -o $(PROG) $(LIBRARIES:=.cma) $(MAIN).cmo +BASEDIR = .. + +ROOTDIR = ../.. + +include $(ROOTDIR)/Makefile.config +expect_MAIN=expect_test +expect_PROG=$(expect_MAIN)$(EXE) +expect_COMPFLAGS=-I $(OTOPDIR)/parsing -I $(OTOPDIR)/utils \ + -I $(OTOPDIR)/driver -I $(OTOPDIR)/typing -I $(OTOPDIR)/toplevel +expect_LIBRARIES := $(addprefix $(ROOTDIR)/compilerlibs/,\ + ocamlcommon ocamlbytecomp ocamltoplevel) + +codegen_INCLUDES=\ + -I $(OTOPDIR)/parsing \ + -I $(OTOPDIR)/utils \ + -I $(OTOPDIR)/typing \ + -I $(OTOPDIR)/middle_end \ + -I $(OTOPDIR)/bytecomp \ + -I $(OTOPDIR)/asmcomp + +codegen_OTHEROBJECTS=\ + $(OTOPDIR)/compilerlibs/ocamlcommon.cma \ + $(OTOPDIR)/compilerlibs/ocamloptcomp.cma + +codegen_OBJECTS=parsecmmaux.cmo parsecmm.cmo lexcmm.cmo codegen_main.cmo + +codegen_ADD_COMPFLAGS=$(codegen_INCLUDES) -w -40 -g + +targets := $(expect_PROG) + +ifneq "$(ARCH)" "none" +targets += codegen +ifneq "$(CCOMPTYPE)-$(ARCH)" "msvc-amd64" +# The asmgen tests are not ported to MSVC64 yet +# so do not compile any arch-specific module +targets += asmgen_$(ARCH).$(O) +endif +endif + +all: $(targets) + +$(expect_PROG): $(expect_LIBRARIES:=.cma) $(expect_MAIN).cmo + @$(OCAMLC) -linkall -o $@ $^ include $(BASEDIR)/makefiles/Makefile.common .PHONY: clean clean: defaultclean - rm -f $(PROG) + rm -f $(expect_PROG) + rm -f codegen parsecmm.ml parsecmm.mli lexcmm.ml + +expect_test.cmo: COMPFLAGS=$(expect_COMPFLAGS) + +$(codegen_OBJECTS): ADD_COMPFLAGS = $(codegen_ADD_COMPFLAGS) + +codegen_main.cmo: parsecmm.cmo + +codegen: $(codegen_OBJECTS) + @$(OCAMLC) $(LINKFLAGS) -o $@ $(codegen_OTHEROBJECTS) $^ + +parsecmm.mli parsecmm.ml: parsecmm.mly + @$(OCAMLYACC) -q parsecmm.mly + +lexcmm.ml: lexcmm.mll + @$(OCAMLLEX) -q lexcmm.mll + +asmgen_i386.obj: asmgen_i386nt.asm + @set -o pipefail ; \ + $(ASM) $@ $^ | tail -n +2 diff --git a/testsuite/tests/asmgen/amd64.S b/testsuite/tools/asmgen_amd64.S similarity index 100% rename from testsuite/tests/asmgen/amd64.S rename to testsuite/tools/asmgen_amd64.S diff --git a/testsuite/tests/asmgen/arm.S b/testsuite/tools/asmgen_arm.S similarity index 100% rename from testsuite/tests/asmgen/arm.S rename to testsuite/tools/asmgen_arm.S diff --git a/testsuite/tests/asmgen/arm64.S b/testsuite/tools/asmgen_arm64.S similarity index 100% rename from testsuite/tests/asmgen/arm64.S rename to testsuite/tools/asmgen_arm64.S diff --git a/testsuite/tools/asmgen_i386.S b/testsuite/tools/asmgen_i386.S new file mode 100644 index 00000000..5878395a --- /dev/null +++ b/testsuite/tools/asmgen_i386.S @@ -0,0 +1,72 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Linux with ELF binaries does not prefix identifiers with _. + Linux with a.out binaries, FreeBSD, and NextStep do. */ + +#if defined(SYS_linux_elf) || defined(SYS_bsd_elf) \ + || defined(SYS_solaris) || defined(SYS_beos) || defined(SYS_gnu) +#define G(x) x +#define FUNCTION_ALIGN 16 +#else +#define G(x) _##x +#define FUNCTION_ALIGN 4 +#endif + + .globl G(call_gen_code) + .align FUNCTION_ALIGN +G(call_gen_code): + pushl %ebp + movl %esp,%ebp + pushl %ebx + pushl %esi + pushl %edi + movl 12(%ebp),%eax + movl 16(%ebp),%ebx + movl 20(%ebp),%ecx + movl 24(%ebp),%edx + call *8(%ebp) + popl %edi + popl %esi + popl %ebx + popl %ebp + ret + + .globl G(caml_c_call) + .align FUNCTION_ALIGN +G(caml_c_call): + jmp *%eax + + .comm G(caml_exception_pointer), 4 + .comm G(young_ptr), 4 + .comm G(young_start), 4 + +/* Some tests are designed to cause registers to spill; on + * x86 we require the caml_extra_params symbol from the RTS. */ + .data + .globl G(caml_extra_params) +G(caml_extra_params): +#ifndef SYS_solaris + .space 64 +#else + .zero 64 +#endif + + + +#if defined(SYS_linux_elf) + /* Mark stack as non-executable */ + .section .note.GNU-stack,"",%progbits +#endif diff --git a/testsuite/tools/asmgen_i386nt.asm b/testsuite/tools/asmgen_i386nt.asm new file mode 100644 index 00000000..281f34ec --- /dev/null +++ b/testsuite/tools/asmgen_i386nt.asm @@ -0,0 +1,71 @@ +;*********************************************************************; +; ; +; OCaml ; +; ; +; Xavier Leroy, projet Cristal, INRIA Rocquencourt ; +; ; +; Copyright 1996 Institut National de Recherche en Informatique et ; +; en Automatique. All rights reserved. This file is distributed ; +; under the terms of the Q Public License version 1.0. ; +; ; +;*********************************************************************; + + .386 + .MODEL FLAT + + .CODE + PUBLIC _call_gen_code + ALIGN 4 +_call_gen_code: + push ebp + mov ebp, esp + push ebx + push esi + push edi + mov eax, [ebp+12] + mov ebx, [ebp+16] + mov ecx, [ebp+20] + mov edx, [ebp+24] + call DWORD PTR [ebp+8] + pop edi + pop esi + pop ebx + pop ebp + ret + + PUBLIC _caml_c_call + ALIGN 4 +_caml_c_call: + ffree st(0) + ffree st(1) + ffree st(2) + ffree st(3) + jmp eax + + PUBLIC _caml_call_gc + PUBLIC _caml_alloc + PUBLIC _caml_alloc1 + PUBLIC _caml_alloc2 + PUBLIC _caml_alloc3 + PUBLIC _caml_allocN + PUBLIC _caml_extra_params + PUBLIC _caml_raise_exn +_caml_call_gc: +_caml_alloc: +_caml_alloc1: +_caml_alloc2: +_caml_alloc3: +_caml_allocN: +_caml_extra_params: +_caml_raise_exn: + int 3 + + .DATA + PUBLIC _caml_exception_pointer +_caml_exception_pointer dword 0 + PUBLIC _caml_young_ptr +_caml_young_ptr dword 0 + PUBLIC _caml_young_limit +_caml_young_limit dword 0 + + END diff --git a/testsuite/tests/asmgen/power.S b/testsuite/tools/asmgen_power.S similarity index 100% rename from testsuite/tests/asmgen/power.S rename to testsuite/tools/asmgen_power.S diff --git a/testsuite/tests/asmgen/s390x.S b/testsuite/tools/asmgen_s390x.S similarity index 100% rename from testsuite/tests/asmgen/s390x.S rename to testsuite/tools/asmgen_s390x.S diff --git a/testsuite/tools/codegen_main.ml b/testsuite/tools/codegen_main.ml new file mode 100644 index 00000000..52aa0c37 --- /dev/null +++ b/testsuite/tools/codegen_main.ml @@ -0,0 +1,81 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +open Clflags +let write_asm_file = ref false + +let compile_file filename = + if !write_asm_file then begin + let out_name = Filename.chop_extension filename ^ ".s" in + Emitaux.output_channel := open_out out_name + end; (* otherwise, stdout *) + Compilenv.reset "test"; + Emit.begin_assembly(); + let ic = open_in filename in + let lb = Lexing.from_channel ic in + lb.Lexing.lex_curr_p <- { lb.Lexing.lex_curr_p with pos_fname = filename }; + try + while true do + Asmgen.compile_phrase ~ppf_dump:Format.std_formatter + (Parsecmm.phrase Lexcmm.token lb) + done + with + End_of_file -> + close_in ic; Emit.end_assembly(); + if !write_asm_file then close_out !Emitaux.output_channel + | Lexcmm.Error msg -> + close_in ic; Lexcmm.report_error lb msg + | Parsing.Parse_error -> + close_in ic; + let start_p = Lexing.lexeme_start_p lb in + let end_p = Lexing.lexeme_end_p lb in + Printf.eprintf "File \"%s\", line %i, characters %i-%i:\n\ + Syntax error.\n%!" + filename + start_p.Lexing.pos_lnum + (start_p.Lexing.pos_cnum - start_p.Lexing.pos_bol) + (end_p.Lexing.pos_cnum - start_p.Lexing.pos_bol) + | Parsecmmaux.Error msg -> + close_in ic; Parsecmmaux.report_error msg + | x -> + close_in ic; raise x + +let usage = "Usage: codegen \noptions are:" + +let main() = + Arg.parse [ + "-S", Arg.Set write_asm_file, + " Output file to filename.s (default is stdout)"; + "-g", Arg.Set Clflags.debug, ""; + "-dcmm", Arg.Set dump_cmm, ""; + "-dcse", Arg.Set dump_cse, ""; + "-dsel", Arg.Set dump_selection, ""; + "-dlive", Arg.Unit(fun () -> dump_live := true; + Printmach.print_live := true), ""; + "-dspill", Arg.Set dump_spill, ""; + "-dsplit", Arg.Set dump_split, ""; + "-dinterf", Arg.Set dump_interf, ""; + "-dprefer", Arg.Set dump_prefer, ""; + "-dalloc", Arg.Set dump_regalloc, ""; + "-dreload", Arg.Set dump_reload, ""; + "-dscheduling", Arg.Set dump_scheduling, ""; + "-dlinear", Arg.Set dump_linear, ""; + "-dtimings", Arg.Unit (fun () -> profile_columns := [ `Time ]), ""; + ] compile_file usage + +let () = + main (); + Profile.print Format.std_formatter !Clflags.profile_columns; + exit 0 diff --git a/testsuite/tools/expect_test.ml b/testsuite/tools/expect_test.ml index 497328cf..73941acc 100644 --- a/testsuite/tools/expect_test.ml +++ b/testsuite/tools/expect_test.ml @@ -62,8 +62,7 @@ let match_expect_extension (ext : Parsetree.extension) = match ext with | ({Asttypes.txt="expect"|"ocaml.expect"; loc = extid_loc}, payload) -> let invalid_payload () = - Location.raise_errorf ~loc:extid_loc - "invalid [%%%%expect payload]" + Location.raise_errorf ~loc:extid_loc "invalid [%%%%expect payload]" in let string_constant (e : Parsetree.expression) = match e.pexp_desc with @@ -130,26 +129,9 @@ let split_chunks phrases = loop phrases [] [] module Compiler_messages = struct - let print_loc ppf (loc : Location.t) = - let startchar = loc.loc_start.pos_cnum - loc.loc_start.pos_bol in - let endchar = loc.loc_end.pos_cnum - loc.loc_start.pos_bol in - Format.fprintf ppf "Line _"; - if startchar >= 0 then - Format.fprintf ppf ", characters %d-%d" startchar endchar; - Format.fprintf ppf ":@."; - if startchar >= 0 then - begin match !Location.input_lexbuf with - | None -> () - | Some lexbuf -> - Location.show_code_at_location ppf lexbuf loc - end; - () - let capture ppf ~f = Misc.protect_refs - [ R (Location.formatter_for_warnings , ppf) - ; R (Location.printer , print_loc) - ] + [ R (Location.formatter_for_warnings, ppf) ] f end @@ -250,6 +232,7 @@ let eval_expect_file _fname ~file_contents = let _ : bool = List.fold_left phrases ~init:true ~f:(fun acc phrase -> acc && + let snap = Btype.snapshot () in try exec_phrase ppf phrase with exn -> @@ -260,6 +243,7 @@ let eval_expect_file _fname ~file_contents = (Printexc.to_string exn) (Printexc.raw_backtrace_to_string bt) end; + Btype.backtrack snap; false ) in @@ -329,8 +313,11 @@ let process_expect_file fname = write_corrected ~file:corrected_fname ~file_contents correction let repo_root = ref None +let keep_original_error_size = ref false let main fname = + if not !keep_original_error_size then + Clflags.error_size := 0; Toploop.override_sys_argv (Array.sub Sys.argv ~pos:!Arg.current ~len:(Array.length Sys.argv - !Arg.current)); @@ -357,10 +344,9 @@ module Options = Main_args.Make_bytetop_options (struct let set r () = r := true let clear r () = r := false open Clflags - let _absname = set Location.absname - let _I dir = - let dir = Misc.expand_directory Config.standard_library dir in - include_dirs := dir :: !include_dirs + let _absname = set absname + let _alert = Warnings.parse_alert_option + let _I dir = include_dirs := dir :: !include_dirs let _init s = init_file := Some s let _noinit = set noinit let _labels = clear classic @@ -373,6 +359,7 @@ module Options = Main_args.Make_bytetop_options (struct let _noprompt = set noprompt let _nopromptcont = set nopromptcont let _nostdlib = set no_std_include + let _nopervasives = set nopervasives let _open s = open_modules := s :: !open_modules let _ppx _s = (* disabled *) () let _principal = set principal @@ -388,7 +375,7 @@ module Options = Main_args.Make_bytetop_options (struct let _no_strict_formats = clear strict_formats let _unboxed_types = set unboxed_types let _no_unboxed_types = clear unboxed_types - let _unsafe = set fast + let _unsafe = set unsafe let _unsafe_string = set unsafe_string let _version () = (* disabled *) () let _vnum () = (* disabled *) () @@ -407,6 +394,9 @@ module Options = Main_args.Make_bytetop_options (struct let _dtimings () = profile_columns := [ `Time ] let _dprofile () = profile_columns := Profile.all_columns let _dinstr = set dump_instr + let _dcamlprimc = set keep_camlprimc_file + let _color = Misc.set_or_ignore color_reader.parse color + let _error_style = Misc.set_or_ignore error_style_reader.parse error_style let _args = Arg.read_arg let _args0 = Arg.read_arg0 @@ -419,6 +409,8 @@ let args = ( [ "-repo-root", Arg.String (fun s -> repo_root := Some s), " root of the OCaml repository. This causes the tool to use \ the stdlib from the current source tree rather than the installed one." + ; "-keep-original-error-size", Arg.Set keep_original_error_size, + " truncate long error messages as the compiler would" ] @ Options.list ) @@ -427,7 +419,6 @@ let usage = "Usage: expect_test [script-file [arguments]]\n\ let () = Clflags.color := Some Misc.Color.Never; - Clflags.error_size := 0; try Arg.parse args main usage; Printf.eprintf "expect_test: no input file\n"; diff --git a/testsuite/tools/lexcmm.mli b/testsuite/tools/lexcmm.mli new file mode 100644 index 00000000..9bac47a0 --- /dev/null +++ b/testsuite/tools/lexcmm.mli @@ -0,0 +1,25 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +val token: Lexing.lexbuf -> Parsecmm.token + +type error = + Illegal_character + | Unterminated_comment + | Unterminated_string + +exception Error of error + +val report_error: Lexing.lexbuf -> error -> unit diff --git a/testsuite/tools/lexcmm.mll b/testsuite/tools/lexcmm.mll new file mode 100644 index 00000000..77ea888a --- /dev/null +++ b/testsuite/tools/lexcmm.mll @@ -0,0 +1,259 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +{ +open Parsecmm + +type error = + Illegal_character + | Unterminated_comment + | Unterminated_string + +exception Error of error + +(* For nested comments *) + +let comment_depth = ref 0 + +(* The table of keywords *) + +let keyword_table = + Misc.create_hashtable 149 [ + "absf", ABSF; + "addr", ADDR; + "align", ALIGN; + "alloc", ALLOC; + "and", AND; + "app", APPLY; + "assign", ASSIGN; + "byte", BYTE; + "case", CASE; + "catch", CATCH; + "checkbound", CHECKBOUND; + "data", DATA; + "exit", EXIT; + "extcall", EXTCALL; + "float", FLOAT; + "float32", FLOAT32; + "float64", FLOAT64; + "floatofint", FLOATOFINT; + "function", FUNCTION; + "global", GLOBAL; + "half", HALF; + "if", IF; + "int", INT; + "int32", INT32; + "intoffloat", INTOFFLOAT; + "string", KSTRING; + "let", LET; + "load", LOAD; + "mod", MODI; + "mulh", MULH; + "or", OR; + "proj", PROJ; + "raise_withtrace", RAISE Cmm.Raise_withtrace; + "raise_notrace", RAISE Cmm.Raise_notrace; + "seq", SEQ; + "signed", SIGNED; + "skip", SKIP; + "store", STORE; + "switch", SWITCH; + "try", TRY; + "unit", UNIT; + "unsigned", UNSIGNED; + "val", VAL; + "while", WHILE; + "with", WITH; + "xor", XOR; + "addraref", ADDRAREF; + "intaref", INTAREF; + "floataref", FLOATAREF; + "addraset", ADDRASET; + "intaset", INTASET; + "floataset", FLOATASET +] + +(* To buffer string literals *) + +let initial_string_buffer = Bytes.create 256 +let string_buff = ref initial_string_buffer +let string_index = ref 0 + +let reset_string_buffer () = + string_buff := initial_string_buffer; + string_index := 0 + +let store_string_char c = + if !string_index >= Bytes.length (!string_buff) then begin + let new_buff = Bytes.create (Bytes.length (!string_buff) * 2) in + Bytes.blit (!string_buff) 0 new_buff 0 (Bytes.length (!string_buff)); + string_buff := new_buff + end; + Bytes.unsafe_set (!string_buff) (!string_index) c; + incr string_index + +let get_stored_string () = + let s = Bytes.sub_string (!string_buff) 0 (!string_index) in + string_buff := initial_string_buffer; + s + +(* To translate escape sequences *) + +let char_for_backslash = function + 'n' -> '\010' + | 'r' -> '\013' + | 'b' -> '\008' + | 't' -> '\009' + | c -> c + +let char_for_decimal_code lexbuf i = + Char.chr(100 * (Char.code(Lexing.lexeme_char lexbuf i) - 48) + + 10 * (Char.code(Lexing.lexeme_char lexbuf (i+1)) - 48) + + (Char.code(Lexing.lexeme_char lexbuf (i+2)) - 48)) + +(* Error report *) + +let report_error lexbuf msg = + prerr_string "Lexical error around character "; + prerr_int (Lexing.lexeme_start lexbuf); + match msg with + Illegal_character -> + prerr_string ": illegal character" + | Unterminated_comment -> + prerr_string ": unterminated comment" + | Unterminated_string -> + prerr_string ": unterminated string" + +} + +let newline = ('\013'* '\010') + +rule token = parse + newline + { Lexing.new_line lexbuf; token lexbuf } + | [' ' '\009' '\012'] + + { token lexbuf } + | "+a" { ADDA } + | "+v" { ADDV } + | "+f" { ADDF } + | "+" { ADDI } + | ">>s" { ASR } + | ":" { COLON } + | "/f" { DIVF } + | "/" { DIVI } + | eof { EOF } + | "==a" { EQA } + | "==f" { EQF } + | "==" { EQI } + | ">=a" { GEA } + | ">=f" { GEF } + | ">=" { GEI } + | ">a" { GTA } + | ">f" { GTF } + | ">" { GTI } + | "[" { LBRACKET } + | "<=a" { LEA } + | "<=f" { LEF } + | "<=" { LEI } + | "(" { LPAREN } + | "<<" { LSL } + | ">>u" { LSR } + | "=f" { NGEF } + | "!>f" { NGTF } + | "!<=f" { NLEF } + | "! + IDENT s } + | "\"" + { reset_string_buffer(); + string lexbuf; + STRING (get_stored_string()) } + | "(*" + { comment_depth := 1; + comment lexbuf; + token lexbuf } + | '{' ['A' - 'Z' 'a'-'z' '/' ',' '.' '-' '_' ' ''0'-'9']+ + ':' [ '0'-'9' ]+ ',' ['0'-'9' ]+ '-' ['0'-'9' ]+ '}' + { + let loc_s = Lexing.lexeme lexbuf in + let pos_fname, pos_lnum, start, end_ = + Scanf.sscanf loc_s "{%s@:%i,%i-%i}" (fun file line start end_ -> + (file, line, start, end_)) + in + let loc_start = + Lexing.{ pos_fname; pos_lnum; pos_bol = 0; pos_cnum = start } + in + let loc_end = + Lexing.{ pos_fname; pos_lnum; pos_bol = 0; pos_cnum = end_ } + in + let location = Location.{ loc_start; loc_end; loc_ghost = false } in + LOCATION location } + | _ { raise(Error(Illegal_character)) } + +and comment = parse + "(*" + { comment_depth := succ !comment_depth; comment lexbuf } + | "*)" + { comment_depth := pred !comment_depth; + if !comment_depth > 0 then comment lexbuf } + | eof + { raise (Error(Unterminated_comment)) } + | newline + { Lexing.new_line lexbuf; comment lexbuf } + | _ + { comment lexbuf } + +and string = parse + '"' + { () } + | '\\' [' ' '\010' '\013' '\009' '\026' '\012'] + + { string lexbuf } + | '\\' ['\\' '"' 'n' 't' 'b' 'r'] + { store_string_char(char_for_backslash(Lexing.lexeme_char lexbuf 1)); + string lexbuf } + | '\\' ['0'-'9'] ['0'-'9'] ['0'-'9'] + { store_string_char(char_for_decimal_code lexbuf 1); + string lexbuf } + | eof + { raise (Error(Unterminated_string)) } + | _ + { store_string_char(Lexing.lexeme_char lexbuf 0); + string lexbuf } diff --git a/testsuite/tools/parsecmm.mly b/testsuite/tools/parsecmm.mly new file mode 100644 index 00000000..673ded99 --- /dev/null +++ b/testsuite/tools/parsecmm.mly @@ -0,0 +1,385 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* A simple parser for C-- */ + +%{ +open Cmm +open Parsecmmaux + +let rec make_letdef def body = + match def with + [] -> body + | (id, def) :: rem -> + unbind_ident id; + Clet(id, def, make_letdef rem body) + +let make_switch n selector caselist = + let index = Array.make n 0 in + let casev = Array.of_list caselist in + let actv = Array.make (Array.length casev) (Cexit(0,[])) in + for i = 0 to Array.length casev - 1 do + let (posl, e) = casev.(i) in + List.iter (fun pos -> index.(pos) <- i) posl; + actv.(i) <- e + done; + Cswitch(selector, index, actv, Debuginfo.none) + +let access_array base numelt size = + match numelt with + Cconst_int 0 -> base + | Cconst_int n -> Cop(Cadda, [base; Cconst_int(n * size)], Debuginfo.none) + | _ -> Cop(Cadda, [base; + Cop(Clsl, [numelt; Cconst_int(Misc.log2 size)], + Debuginfo.none)], + Debuginfo.none) + +%} + +%token ABSF +%token ADDA +%token ADDF +%token ADDI +%token ADDV +%token ADDR +%token ALIGN +%token ALLOC +%token AND +%token APPLY +%token ASR +%token ASSIGN +%token BYTE +%token CASE +%token CATCH +%token CHECKBOUND +%token COLON +%token DATA +%token DIVF +%token DIVI +%token EOF +%token EQA +%token EQF +%token EQI +%token EXIT +%token EXTCALL +%token FLOAT +%token FLOAT32 +%token FLOAT64 +%token FLOATCONST +%token FLOATOFINT +%token FUNCTION +%token GEA +%token GEF +%token GEI +%token GLOBAL +%token GTA +%token GTF +%token GTI +%token HALF +%token IDENT +%token IF +%token INT +%token INT32 +%token INTCONST +%token INTOFFLOAT +%token KSTRING +%token LBRACKET +%token LEA +%token LEF +%token LEI +%token LET +%token LOAD +%token LOCATION +%token LPAREN +%token LSL +%token LSR +%token LTA +%token LTF +%token LTI +%token MODI +%token MULF +%token MULH +%token MULI +%token NEA +%token NEF +%token NEI +%token NGEF +%token NGTF +%token NLEF +%token NLTF +%token OR +%token POINTER +%token PROJ +%token RAISE +%token RBRACKET +%token RPAREN +%token SEQ +%token SIGNED +%token SKIP +%token STAR +%token STORE +%token STRING +%token SUBF +%token SUBI +%token SWITCH +%token TRY +%token UNIT +%token UNSIGNED +%token VAL +%token WHILE +%token WITH +%token XOR +%token ADDRAREF +%token INTAREF +%token FLOATAREF +%token ADDRASET +%token INTASET +%token FLOATASET + +%start phrase +%type phrase + +%% + +phrase: + fundecl { Cfunction $1 } + | datadecl { Cdata $1 } + | EOF { raise End_of_file } +; +fundecl: + LPAREN FUNCTION fun_name LPAREN params RPAREN sequence RPAREN + { List.iter (fun (id, ty) -> unbind_ident id) $5; + {fun_name = $3; fun_args = $5; fun_body = $7; + fun_codegen_options = + if Config.flambda then [ + Reduce_code_size; + No_CSE; + ] + else [ Reduce_code_size ]; + fun_dbg = debuginfo ()} } +; +fun_name: + STRING { $1 } + | IDENT { $1 } +params: + oneparam params { $1 :: $2 } + | /**/ { [] } +; +oneparam: + IDENT COLON machtype { (bind_ident $1, $3) } +; +machtype: + UNIT { [||] } + | componentlist { Array.of_list(List.rev $1) } +; +component: + VAL { Val } + | ADDR { Addr } + | INT { Int } + | FLOAT { Float } +; +componentlist: + component { [$1] } + | componentlist STAR component { $3 :: $1 } +; +expr: + INTCONST { Cconst_int $1 } + | FLOATCONST { Cconst_float (float_of_string $1) } + | STRING { Cconst_symbol $1 } + | POINTER { Cconst_pointer $1 } + | IDENT { Cvar(find_ident $1) } + | LBRACKET RBRACKET { Ctuple [] } + | LPAREN LET letdef sequence RPAREN { make_letdef $3 $4 } + | LPAREN ASSIGN IDENT expr RPAREN { Cassign(find_ident $3, $4) } + | LPAREN APPLY location expr exprlist machtype RPAREN + { Cop(Capply $6, $4 :: List.rev $5, debuginfo ?loc:$3 ()) } + | LPAREN EXTCALL STRING exprlist machtype RPAREN + {Cop(Cextcall($3, $5, false, None), List.rev $4, debuginfo ())} + | LPAREN ALLOC exprlist RPAREN { Cop(Calloc, List.rev $3, debuginfo ()) } + | LPAREN SUBF expr RPAREN { Cop(Cnegf, [$3], debuginfo ()) } + | LPAREN SUBF expr expr RPAREN { Cop(Csubf, [$3; $4], debuginfo ()) } + | LPAREN unaryop expr RPAREN { Cop($2, [$3], debuginfo ()) } + | LPAREN binaryop expr expr RPAREN { Cop($2, [$3; $4], debuginfo ()) } + | LPAREN SEQ sequence RPAREN { $3 } + | LPAREN IF expr expr expr RPAREN { Cifthenelse($3, $4, $5) } + | LPAREN SWITCH INTCONST expr caselist RPAREN { make_switch $3 $4 $5 } + | LPAREN WHILE expr sequence RPAREN + { let body = + match $3 with + Cconst_int x when x <> 0 -> $4 + | _ -> Cifthenelse($3, $4, (Cexit(0,[]))) in + Ccatch(Recursive, [0, [], Cloop body], Ctuple []) } + | LPAREN EXIT IDENT exprlist RPAREN + { Cexit(find_label $3, List.rev $4) } + | LPAREN CATCH sequence WITH catch_handlers RPAREN + { let handlers = $5 in + List.iter (fun (_, l, _) -> + List.iter (fun (x, _) -> unbind_ident x) l) handlers; + Ccatch(Recursive, handlers, $3) } + | EXIT { Cexit(0,[]) } + | LPAREN TRY sequence WITH bind_ident sequence RPAREN + { unbind_ident $5; Ctrywith($3, $5, $6) } + | LPAREN VAL expr expr RPAREN + { Cop(Cload (Word_val, Mutable), [access_array $3 $4 Arch.size_addr], + debuginfo ()) } + | LPAREN ADDRAREF expr expr RPAREN + { Cop(Cload (Word_val, Mutable), [access_array $3 $4 Arch.size_addr], + Debuginfo.none) } + | LPAREN INTAREF expr expr RPAREN + { Cop(Cload (Word_int, Mutable), [access_array $3 $4 Arch.size_int], + Debuginfo.none) } + | LPAREN FLOATAREF expr expr RPAREN + { Cop(Cload (Double_u, Mutable), [access_array $3 $4 Arch.size_float], + Debuginfo.none) } + | LPAREN ADDRASET expr expr expr RPAREN + { Cop(Cstore (Word_val, Assignment), + [access_array $3 $4 Arch.size_addr; $5], Debuginfo.none) } + | LPAREN INTASET expr expr expr RPAREN + { Cop(Cstore (Word_int, Assignment), + [access_array $3 $4 Arch.size_int; $5], Debuginfo.none) } + | LPAREN FLOATASET expr expr expr RPAREN + { Cop(Cstore (Double_u, Assignment), + [access_array $3 $4 Arch.size_float; $5], Debuginfo.none) } +; +exprlist: + exprlist expr { $2 :: $1 } + | /**/ { [] } +; +letdef: + oneletdef { [$1] } + | LPAREN letdefmult RPAREN { $2 } +; +letdefmult: + /**/ { [] } + | oneletdef letdefmult { $1 :: $2 } +; +oneletdef: + IDENT expr { (bind_ident $1, $2) } +; +chunk: + UNSIGNED BYTE { Byte_unsigned } + | SIGNED BYTE { Byte_signed } + | UNSIGNED HALF { Sixteen_unsigned } + | SIGNED HALF { Sixteen_signed } + | UNSIGNED INT32 { Thirtytwo_unsigned } + | SIGNED INT32 { Thirtytwo_signed } + | INT { Word_int } + | ADDR { Word_val } + | FLOAT32 { Single } + | FLOAT64 { Double } + | FLOAT { Double_u } + | VAL { Word_val } +; +unaryop: + LOAD chunk { Cload ($2, Mutable) } + | FLOATOFINT { Cfloatofint } + | INTOFFLOAT { Cintoffloat } + | RAISE { Craise $1 } + | ABSF { Cabsf } +; +binaryop: + STORE chunk { Cstore ($2, Assignment) } + | ADDI { Caddi } + | SUBI { Csubi } + | STAR { Cmuli } + | DIVI { Cdivi } + | MODI { Cmodi } + | AND { Cand } + | OR { Cor } + | XOR { Cxor } + | LSL { Clsl } + | LSR { Clsr } + | ASR { Casr } + | EQI { Ccmpi Ceq } + | NEI { Ccmpi Cne } + | LTI { Ccmpi Clt } + | LEI { Ccmpi Cle } + | GTI { Ccmpi Cgt } + | GEI { Ccmpi Cge } + | ADDA { Cadda } + | ADDV { Caddv } + | EQA { Ccmpa Ceq } + | NEA { Ccmpa Cne } + | LTA { Ccmpa Clt } + | LEA { Ccmpa Cle } + | GTA { Ccmpa Cgt } + | GEA { Ccmpa Cge } + | ADDF { Caddf } + | MULF { Cmulf } + | DIVF { Cdivf } + | EQF { Ccmpf CFeq } + | NEF { Ccmpf CFneq } + | LTF { Ccmpf CFlt } + | NLTF { Ccmpf CFnlt } + | LEF { Ccmpf CFle } + | NLEF { Ccmpf CFnle } + | GTF { Ccmpf CFgt } + | NGTF { Ccmpf CFngt } + | GEF { Ccmpf CFge } + | NGEF { Ccmpf CFnge } + | CHECKBOUND { Ccheckbound } + | MULH { Cmulhi } +; +sequence: + expr sequence { Csequence($1, $2) } + | expr { $1 } +; +caselist: + onecase sequence caselist { ($1, $2) :: $3 } + | /**/ { [] } +; +onecase: + CASE INTCONST COLON onecase { $2 :: $4 } + | CASE INTCONST COLON { [$2] } +; +bind_ident: + IDENT { bind_ident $1 } +; +datadecl: + LPAREN datalist RPAREN { List.rev $2 } + | LPAREN DATA datalist RPAREN { List.rev $3 } +; +datalist: + datalist dataitem { $2 :: $1 } + | /**/ { [] } +; +dataitem: + STRING COLON { Cdefine_symbol $1 } + | BYTE INTCONST { Cint8 $2 } + | HALF INTCONST { Cint16 $2 } + | INT INTCONST { Cint(Nativeint.of_int $2) } + | FLOAT FLOATCONST { Cdouble (float_of_string $2) } + | ADDR STRING { Csymbol_address $2 } + | VAL STRING { Csymbol_address $2 } + | KSTRING STRING { Cstring $2 } + | SKIP INTCONST { Cskip $2 } + | ALIGN INTCONST { Calign $2 } + | GLOBAL STRING { Cglobal_symbol $2 } +; +catch_handlers: + | catch_handler + { [$1] } + | catch_handler AND catch_handlers + { $1 :: $3 } + +catch_handler: + | sequence + { 0, [], $1 } + | LPAREN IDENT params RPAREN sequence + { find_label $2, $3, $5 } + +location: + /**/ { None } + | LOCATION { Some $1 } diff --git a/testsuite/tools/parsecmmaux.ml b/testsuite/tools/parsecmmaux.ml new file mode 100644 index 00000000..c2fb7565 --- /dev/null +++ b/testsuite/tools/parsecmmaux.ml @@ -0,0 +1,58 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(* Auxiliary functions for parsing *) + +type error = + Unbound of string + +exception Error of error + +let tbl_ident = (Hashtbl.create 57 : (string, Backend_var.t) Hashtbl.t) +let tbl_label = (Hashtbl.create 57 : (string, int) Hashtbl.t) + +let ident_name s = + match String.index s '/' with + | exception Not_found -> s + | n -> String.sub s 0 n + +let bind_ident s = + let id = Backend_var.create_local (ident_name s) in + Hashtbl.add tbl_ident s id; + Backend_var.With_provenance.create id + +let find_ident s = + try + Hashtbl.find tbl_ident s + with Not_found -> + raise(Error(Unbound s)) + +let unbind_ident id = + Hashtbl.remove tbl_ident (Backend_var.With_provenance.name id) + +let find_label s = + try + Hashtbl.find tbl_label s + with Not_found -> + let lbl = Lambda.next_raise_count () in + Hashtbl.add tbl_label s lbl; + lbl + +let report_error = function + Unbound s -> + prerr_string "Unbound identifier "; prerr_string s; prerr_endline "." + +let debuginfo ?(loc=Location.symbol_rloc ()) () = + Debuginfo.(from_location loc) diff --git a/testsuite/tools/parsecmmaux.mli b/testsuite/tools/parsecmmaux.mli new file mode 100644 index 00000000..a6728b49 --- /dev/null +++ b/testsuite/tools/parsecmmaux.mli @@ -0,0 +1,31 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(* Auxiliary functions for parsing *) + +val bind_ident: string -> Backend_var.With_provenance.t +val find_ident: string -> Backend_var.t +val unbind_ident: Backend_var.With_provenance.t -> unit + +val find_label: string -> int + +val debuginfo: ?loc:Location.t -> unit -> Debuginfo.t + +type error = + Unbound of string + +exception Error of error + +val report_error: error -> unit diff --git a/tools/.depend b/tools/.depend index add9b377..c96026b9 100644 --- a/tools/.depend +++ b/tools/.depend @@ -1,87 +1,235 @@ -addlabels.cmo : ../parsing/parsetree.cmi ../parsing/parse.cmi \ - ../parsing/longident.cmi ../parsing/location.cmi ../parsing/asttypes.cmi -addlabels.cmx : ../parsing/parsetree.cmi ../parsing/parse.cmx \ - ../parsing/longident.cmx ../parsing/location.cmx ../parsing/asttypes.cmi -cmpbyt.cmo : ../bytecomp/bytesections.cmi -cmpbyt.cmx : ../bytecomp/bytesections.cmx -cmt2annot.cmo : ../typing/untypeast.cmi ../typing/types.cmi \ - ../typing/typedtree.cmi ../typing/tast_mapper.cmi ../typing/stypes.cmi \ - ../parsing/pprintast.cmi ../typing/path.cmi ../typing/oprint.cmi \ - ../parsing/location.cmi ../typing/ident.cmi ../typing/envaux.cmi \ - ../typing/env.cmi ../utils/config.cmi ../typing/cmt_format.cmi \ - ../parsing/asttypes.cmi ../typing/annot.cmi -cmt2annot.cmx : ../typing/untypeast.cmx ../typing/types.cmx \ - ../typing/typedtree.cmx ../typing/tast_mapper.cmx ../typing/stypes.cmx \ - ../parsing/pprintast.cmx ../typing/path.cmx ../typing/oprint.cmx \ - ../parsing/location.cmx ../typing/ident.cmx ../typing/envaux.cmx \ - ../typing/env.cmx ../utils/config.cmx ../typing/cmt_format.cmx \ - ../parsing/asttypes.cmi ../typing/annot.cmi +addlabels.cmo : \ + ../parsing/parsetree.cmi \ + ../parsing/parse.cmi \ + ../parsing/longident.cmi \ + ../parsing/location.cmi \ + ../parsing/asttypes.cmi +addlabels.cmx : \ + ../parsing/parsetree.cmi \ + ../parsing/parse.cmx \ + ../parsing/longident.cmx \ + ../parsing/location.cmx \ + ../parsing/asttypes.cmi +caml_tex.cmo : \ + ../toplevel/toploop.cmi \ + ../parsing/syntaxerr.cmi \ + ../parsing/parsetree.cmi \ + ../parsing/parse.cmi \ + ../utils/misc.cmi \ + ../parsing/location.cmi \ + ../parsing/lexer.cmi \ + ../driver/compmisc.cmi \ + ../driver/compenv.cmi \ + ../utils/clflags.cmi \ + ../parsing/ast_iterator.cmi \ + ../parsing/ast_helper.cmi +caml_tex.cmx : \ + ../toplevel/toploop.cmx \ + ../parsing/syntaxerr.cmx \ + ../parsing/parsetree.cmi \ + ../parsing/parse.cmx \ + ../utils/misc.cmx \ + ../parsing/location.cmx \ + ../parsing/lexer.cmx \ + ../driver/compmisc.cmx \ + ../driver/compenv.cmx \ + ../utils/clflags.cmx \ + ../parsing/ast_iterator.cmx \ + ../parsing/ast_helper.cmx +cmpbyt.cmo : \ + ../bytecomp/bytesections.cmi +cmpbyt.cmx : \ + ../bytecomp/bytesections.cmx +cmt2annot.cmo : \ + ../typing/untypeast.cmi \ + ../typing/types.cmi \ + ../typing/typedtree.cmi \ + ../typing/tast_mapper.cmi \ + ../typing/stypes.cmi \ + ../parsing/pprintast.cmi \ + ../typing/path.cmi \ + ../typing/oprint.cmi \ + ../parsing/location.cmi \ + ../utils/load_path.cmi \ + ../typing/ident.cmi \ + ../typing/envaux.cmi \ + ../typing/env.cmi \ + ../typing/cmt_format.cmi \ + ../parsing/asttypes.cmi \ + ../typing/annot.cmi +cmt2annot.cmx : \ + ../typing/untypeast.cmx \ + ../typing/types.cmx \ + ../typing/typedtree.cmx \ + ../typing/tast_mapper.cmx \ + ../typing/stypes.cmx \ + ../parsing/pprintast.cmx \ + ../typing/path.cmx \ + ../typing/oprint.cmx \ + ../parsing/location.cmx \ + ../utils/load_path.cmx \ + ../typing/ident.cmx \ + ../typing/envaux.cmx \ + ../typing/env.cmx \ + ../typing/cmt_format.cmx \ + ../parsing/asttypes.cmi \ + ../typing/annot.cmi cvt_emit.cmo : cvt_emit.cmx : -dumpobj.cmo : ../utils/tbl.cmi opnames.cmo ../bytecomp/opcodes.cmo \ - ../parsing/location.cmi ../bytecomp/lambda.cmi ../bytecomp/instruct.cmi \ - ../typing/ident.cmi ../utils/config.cmi ../bytecomp/cmo_format.cmi \ - ../bytecomp/bytesections.cmi ../parsing/asttypes.cmi -dumpobj.cmx : ../utils/tbl.cmx opnames.cmx ../bytecomp/opcodes.cmx \ - ../parsing/location.cmx ../bytecomp/lambda.cmx ../bytecomp/instruct.cmx \ - ../typing/ident.cmx ../utils/config.cmx ../bytecomp/cmo_format.cmi \ - ../bytecomp/bytesections.cmx ../parsing/asttypes.cmi -eqparsetree.cmo : ../parsing/parsetree.cmi ../parsing/longident.cmi \ - ../parsing/location.cmi ../parsing/asttypes.cmi -eqparsetree.cmx : ../parsing/parsetree.cmi ../parsing/longident.cmx \ - ../parsing/location.cmx ../parsing/asttypes.cmi -lintapidiff.cmo : ../typing/printtyp.cmi ../driver/pparse.cmi \ - ../typing/path.cmi ../parsing/parsetree.cmi ../parsing/parse.cmi \ - ../utils/misc.cmi ../parsing/location.cmi ../typing/ident.cmi -lintapidiff.cmx : ../typing/printtyp.cmx ../driver/pparse.cmx \ - ../typing/path.cmx ../parsing/parsetree.cmi ../parsing/parse.cmx \ - ../utils/misc.cmx ../parsing/location.cmx ../typing/ident.cmx +dumpobj.cmo : \ + ../bytecomp/symtable.cmi \ + opnames.cmo \ + ../bytecomp/opcodes.cmo \ + ../parsing/location.cmi \ + ../bytecomp/lambda.cmi \ + ../bytecomp/instruct.cmi \ + ../typing/ident.cmi \ + ../utils/config.cmi \ + ../bytecomp/cmo_format.cmi \ + ../bytecomp/bytesections.cmi \ + ../parsing/asttypes.cmi +dumpobj.cmx : \ + ../bytecomp/symtable.cmx \ + opnames.cmx \ + ../bytecomp/opcodes.cmx \ + ../parsing/location.cmx \ + ../bytecomp/lambda.cmx \ + ../bytecomp/instruct.cmx \ + ../typing/ident.cmx \ + ../utils/config.cmx \ + ../bytecomp/cmo_format.cmi \ + ../bytecomp/bytesections.cmx \ + ../parsing/asttypes.cmi +eqparsetree.cmo : \ + ../parsing/parsetree.cmi \ + ../parsing/longident.cmi \ + ../parsing/location.cmi \ + ../parsing/asttypes.cmi +eqparsetree.cmx : \ + ../parsing/parsetree.cmi \ + ../parsing/longident.cmx \ + ../parsing/location.cmx \ + ../parsing/asttypes.cmi +lintapidiff.cmo : \ + ../typing/printtyp.cmi \ + ../driver/pparse.cmi \ + ../typing/path.cmi \ + ../parsing/parsetree.cmi \ + ../parsing/parse.cmi \ + ../utils/misc.cmi \ + ../parsing/location.cmi \ + ../typing/ident.cmi +lintapidiff.cmx : \ + ../typing/printtyp.cmx \ + ../driver/pparse.cmx \ + ../typing/path.cmx \ + ../parsing/parsetree.cmi \ + ../parsing/parse.cmx \ + ../utils/misc.cmx \ + ../parsing/location.cmx \ + ../typing/ident.cmx make_opcodes.cmo : make_opcodes.cmx : -objinfo.cmo : ../utils/tbl.cmi ../middle_end/base_types/symbol.cmi \ - ../asmcomp/printclambda.cmi ../utils/misc.cmi \ - ../middle_end/base_types/linkage_name.cmi ../typing/ident.cmi \ - ../asmcomp/export_info.cmi ../utils/config.cmi \ - ../middle_end/base_types/compilation_unit.cmi ../asmcomp/cmx_format.cmi \ - ../typing/cmt_format.cmi ../bytecomp/cmo_format.cmi \ - ../typing/cmi_format.cmi ../bytecomp/bytesections.cmi -objinfo.cmx : ../utils/tbl.cmx ../middle_end/base_types/symbol.cmx \ - ../asmcomp/printclambda.cmx ../utils/misc.cmx \ - ../middle_end/base_types/linkage_name.cmx ../typing/ident.cmx \ - ../asmcomp/export_info.cmx ../utils/config.cmx \ - ../middle_end/base_types/compilation_unit.cmx ../asmcomp/cmx_format.cmi \ - ../typing/cmt_format.cmx ../bytecomp/cmo_format.cmi \ - ../typing/cmi_format.cmx ../bytecomp/bytesections.cmx +objinfo.cmo : \ + ../bytecomp/symtable.cmi \ + ../middle_end/base_types/symbol.cmi \ + ../asmcomp/printclambda.cmi \ + ../utils/misc.cmi \ + ../middle_end/base_types/linkage_name.cmi \ + ../typing/ident.cmi \ + ../asmcomp/export_info.cmi \ + ../utils/config.cmi \ + ../middle_end/base_types/compilation_unit.cmi \ + ../asmcomp/cmx_format.cmi \ + ../typing/cmt_format.cmi \ + ../bytecomp/cmo_format.cmi \ + ../typing/cmi_format.cmi \ + ../bytecomp/bytesections.cmi +objinfo.cmx : \ + ../bytecomp/symtable.cmx \ + ../middle_end/base_types/symbol.cmx \ + ../asmcomp/printclambda.cmx \ + ../utils/misc.cmx \ + ../middle_end/base_types/linkage_name.cmx \ + ../typing/ident.cmx \ + ../asmcomp/export_info.cmx \ + ../utils/config.cmx \ + ../middle_end/base_types/compilation_unit.cmx \ + ../asmcomp/cmx_format.cmi \ + ../typing/cmt_format.cmx \ + ../bytecomp/cmo_format.cmi \ + ../typing/cmi_format.cmx \ + ../bytecomp/bytesections.cmx ocaml299to3.cmo : ocaml299to3.cmx : -ocamlcp.cmo : ../driver/main_args.cmi -ocamlcp.cmx : ../driver/main_args.cmx -ocamldep.cmo : ../driver/makedepend.cmi -ocamldep.cmx : ../driver/makedepend.cmx -ocamlmklib.cmo : ocamlmklibconfig.cmo ../utils/misc.cmi ../utils/config.cmi -ocamlmklib.cmx : ocamlmklibconfig.cmx ../utils/misc.cmx ../utils/config.cmx +ocamlcp.cmo : \ + ../driver/main_args.cmi +ocamlcp.cmx : \ + ../driver/main_args.cmx +ocamldep.cmo : \ + ../driver/makedepend.cmi +ocamldep.cmx : \ + ../driver/makedepend.cmx +ocamlmklib.cmo : \ + ocamlmklibconfig.cmo \ + ../utils/misc.cmi \ + ../utils/config.cmi +ocamlmklib.cmx : \ + ocamlmklibconfig.cmx \ + ../utils/misc.cmx \ + ../utils/config.cmx ocamlmklibconfig.cmo : ocamlmklibconfig.cmx : -ocamlmktop.cmo : ../utils/ccomp.cmi -ocamlmktop.cmx : ../utils/ccomp.cmx -ocamloptp.cmo : ../driver/main_args.cmi -ocamloptp.cmx : ../driver/main_args.cmx -ocamlprof.cmo : ../utils/warnings.cmi ../parsing/parsetree.cmi \ - ../parsing/parse.cmi ../parsing/location.cmi -ocamlprof.cmx : ../utils/warnings.cmx ../parsing/parsetree.cmi \ - ../parsing/parse.cmx ../parsing/location.cmx +ocamlmktop.cmo : \ + ../utils/ccomp.cmi +ocamlmktop.cmx : \ + ../utils/ccomp.cmx +ocamloptp.cmo : \ + ../driver/main_args.cmi +ocamloptp.cmx : \ + ../driver/main_args.cmx +ocamlprof.cmo : \ + ../utils/warnings.cmi \ + ../parsing/parsetree.cmi \ + ../parsing/parse.cmi \ + ../parsing/location.cmi +ocamlprof.cmx : \ + ../utils/warnings.cmx \ + ../parsing/parsetree.cmi \ + ../parsing/parse.cmx \ + ../parsing/location.cmx opnames.cmo : opnames.cmx : -primreq.cmo : ../utils/config.cmi ../bytecomp/cmo_format.cmi -primreq.cmx : ../utils/config.cmx ../bytecomp/cmo_format.cmi -profiling.cmo : profiling.cmi -profiling.cmx : profiling.cmi +primreq.cmo : \ + ../utils/misc.cmi \ + ../utils/config.cmi \ + ../bytecomp/cmo_format.cmi +primreq.cmx : \ + ../utils/misc.cmx \ + ../utils/config.cmx \ + ../bytecomp/cmo_format.cmi +profiling.cmo : \ + profiling.cmi +profiling.cmx : \ + profiling.cmi profiling.cmi : -read_cmt.cmo : ../parsing/location.cmi ../driver/compmisc.cmi \ - ../typing/cmt_format.cmi cmt2annot.cmo ../utils/clflags.cmi -read_cmt.cmx : ../parsing/location.cmx ../driver/compmisc.cmx \ - ../typing/cmt_format.cmx cmt2annot.cmx ../utils/clflags.cmx +read_cmt.cmo : \ + ../parsing/location.cmi \ + ../driver/compmisc.cmi \ + ../typing/cmt_format.cmi \ + cmt2annot.cmo \ + ../utils/clflags.cmi +read_cmt.cmx : \ + ../parsing/location.cmx \ + ../driver/compmisc.cmx \ + ../typing/cmt_format.cmx \ + cmt2annot.cmx \ + ../utils/clflags.cmx scrapelabels.cmo : scrapelabels.cmx : -stripdebug.cmo : ../utils/misc.cmi ../bytecomp/bytesections.cmi -stripdebug.cmx : ../utils/misc.cmx ../bytecomp/bytesections.cmx +stripdebug.cmo : \ + ../utils/misc.cmi \ + ../bytecomp/bytesections.cmi +stripdebug.cmx : \ + ../utils/misc.cmx \ + ../bytecomp/bytesections.cmx diff --git a/tools/Makefile b/tools/Makefile index 78d2a106..ee0e0be4 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -14,8 +14,10 @@ #************************************************************************** MAKEFLAGS := -r -R -include ../config/Makefile -include ../Makefile.common +ROOTDIR = .. + +include $(ROOTDIR)/Makefile.config +include $(ROOTDIR)/Makefile.common ifeq ($(SYSTEM),unix) override define shellquote @@ -24,8 +26,7 @@ endef $(foreach i,BINDIR LIBDIR STUBLIBDIR MANDIR,$(eval $(shellquote))) endif -CAMLRUN ?= ../boot/ocamlrun -CAMLYACC ?= ../boot/ocamlyacc +CAMLRUN ?= $(ROOTDIR)/boot/ocamlrun DESTDIR ?= # Setup GNU make variables storing per-target source and target, # a list of installed tools, and a function to quote a filename for @@ -48,10 +49,11 @@ define byte_and_opt_ $(and $(filter-out 1,$(words $1)),$(error \ cannot build file with whitespace in name)) $1: $3 $2 - $$(CAMLC) $$(LINKFLAGS) -I .. -o $$@ $2 + $$(CAMLC) $$(LINKFLAGS) -I $$(ROOTDIR) -o $$@ $2 $1.opt: $3 $$(call byte2native,$2) - $$(CAMLOPT) $$(LINKFLAGS) -I .. -o $$@ $$(call byte2native,$2) + $$(CAMLOPT_CMD) $$(LINKFLAGS) -I $$(ROOTDIR) -o $$@ \ + $$(call byte2native,$2) all: $1 @@ -71,42 +73,28 @@ $(eval $(call \ byte_and_opt_,$(subst $$,$$$$,$1),$(subst $$,$$$$,$2),$(subst $$,$$$$,$3))) endef -ROOTDIR=.. - -ifeq "$(wildcard $(ROOTDIR)/flexdll/Makefile)" "" -export OCAML_FLEXLINK:= -else -export OCAML_FLEXLINK:=$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/flexdll/flexlink.exe -endif - -CAMLC=$(CAMLRUN) ../boot/ocamlc -nostdlib -I ../boot \ - -use-prims ../byterun/primitives -I .. -CAMLOPT=$(CAMLRUN) ../ocamlopt -nostdlib -I ../stdlib -ifeq "$(UNIX_OR_WIN32)" "win32" - ifneq "$(wildcard ../flexdll/Makefile)" "" - CAMLOPT := OCAML_FLEXLINK="../boot/ocamlrun ../flexdll/flexlink.exe" \ - $(CAMLOPT) - endif -endif -CAMLLEX=$(CAMLRUN) ../boot/ocamllex -INCLUDES=-I ../utils -I ../parsing -I ../typing -I ../bytecomp -I ../asmcomp \ - -I ../middle_end -I ../middle_end/base_types -I ../driver \ - -I ../toplevel -COMPFLAGS= -absname -w +a-4-9-41-42-44-45-48 -strict-sequence -warn-error A \ +CAMLC = $(CAMLRUN) $(ROOTDIR)/boot/ocamlc -g -nostdlib -I $(ROOTDIR)/boot \ + -use-prims $(ROOTDIR)/runtime/primitives -I $(ROOTDIR) +CAMLOPT = $(CAMLRUN) $(ROOTDIR)/ocamlopt -g -nostdlib -I $(ROOTDIR)/stdlib +CAMLLEX = $(CAMLRUN) $(ROOTDIR)/boot/ocamllex +INCLUDES = $(addprefix -I $(ROOTDIR)/,utils parsing typing bytecomp asmcomp \ + middle_end middle_end/base_types driver toplevel) +COMPFLAGS = -absname -w +a-4-9-41-42-44-45-48 -strict-sequence -warn-error A \ -safe-string -strict-formats -bin-annot $(INCLUDES) -LINKFLAGS=$(INCLUDES) +LINKFLAGS = $(INCLUDES) VPATH := $(filter-out -I,$(INCLUDES)) # scrapelabels addlabels -.PHONY: all opt.opt +.PHONY: all allopt opt.opt # allopt and opt.opt are synonyms +allopt: opt.opt # The dependency generator CAMLDEP_OBJ=ocamldep.cmo CAMLDEP_IMPORTS= \ - ../compilerlibs/ocamlcommon.cma \ - ../compilerlibs/ocamlbytecomp.cma + $(ROOTDIR)/compilerlibs/ocamlcommon.cma \ + $(ROOTDIR)/compilerlibs/ocamlbytecomp.cma ocamldep: LINKFLAGS += -compat-32 $(call byte_and_opt,ocamldep,$(CAMLDEP_IMPORTS) $(CAMLDEP_OBJ),) ocamldep: depend.cmi @@ -122,16 +110,19 @@ clean:: # The profiler CSLPROF=ocamlprof.cmo -CSLPROF_IMPORTS=misc.cmo config.cmo identifiable.cmo numbers.cmo \ - arg_helper.cmo clflags.cmo terminfo.cmo \ - build_path_prefix_map.cmo \ +CSLPROF_IMPORTS=config.cmo build_path_prefix_map.cmo misc.cmo identifiable.cmo \ + numbers.cmo arg_helper.cmo clflags.cmo terminfo.cmo \ warnings.cmo location.cmo longident.cmo docstrings.cmo \ - syntaxerr.cmo ast_helper.cmo parser.cmo lexer.cmo parse.cmo + syntaxerr.cmo ast_helper.cmo \ + camlinternalMenhirLib.cmo parser.cmo \ + pprintast.cmo \ + lexer.cmo parse.cmo $(call byte_and_opt,ocamlprof,$(CSLPROF_IMPORTS) profiling.cmo $(CSLPROF),) -ocamlcp_cmos = misc.cmo profile.cmo warnings.cmo config.cmo identifiable.cmo \ - numbers.cmo arg_helper.cmo clflags.cmo main_args.cmo +ocamlcp_cmos = config.cmo build_path_prefix_map.cmo misc.cmo profile.cmo \ + warnings.cmo identifiable.cmo numbers.cmo arg_helper.cmo \ + clflags.cmo main_args.cmo $(call byte_and_opt,ocamlcp,$(ocamlcp_cmos) ocamlcp.cmo,) $(call byte_and_opt,ocamloptp,$(ocamlcp_cmos) ocamloptp.cmo,) @@ -140,8 +131,13 @@ opt:: profiling.cmx install:: $(INSTALL_DATA) \ - profiling.cmi profiling.cmo profiling.cmt profiling.cmti \ + profiling.cmi profiling.cmo \ + "$(INSTALL_LIBDIR)" +ifeq "$(INSTALL_SOURCE_ARTIFACTS)" "true" + $(INSTALL_DATA) \ + profiling.cmt profiling.cmti \ "$(INSTALL_LIBDIR)" +endif installopt:: $(INSTALL_DATA) \ @@ -150,17 +146,16 @@ installopt:: # To help building mixed-mode libraries (OCaml + C) -$(call byte_and_opt,ocamlmklib,ocamlmklibconfig.cmo config.cmo misc.cmo \ - ocamlmklib.cmo,) +$(call byte_and_opt,ocamlmklib,ocamlmklibconfig.cmo config.cmo \ + build_path_prefix_map.cmo misc.cmo ocamlmklib.cmo,) -ocamlmklibconfig.ml: ../config/Makefile Makefile +ocamlmklibconfig.ml: $(ROOTDIR)/Makefile.config Makefile (echo 'let bindir = "$(BINDIR)"'; \ echo 'let supports_shared_libraries = $(SUPPORTS_SHARED_LIBRARIES)';\ echo 'let default_rpath = "$(RPATH)"'; \ echo 'let mksharedlibrpath = "$(MKSHAREDLIBRPATH)"'; \ - echo 'let toolpref = "$(TOOLPREF)"'; \ - sed -n -e 's/^#ml //p' ../config/Makefile) \ + echo 'let toolpref = "$(TOOLPREF)"';) \ > ocamlmklibconfig.ml beforedepend:: ocamlmklibconfig.ml @@ -171,15 +166,16 @@ clean:: # To make custom toplevels OCAMLMKTOP=ocamlmktop.cmo -OCAMLMKTOP_IMPORTS=misc.cmo identifiable.cmo numbers.cmo config.cmo \ - arg_helper.cmo clflags.cmo ccomp.cmo +OCAMLMKTOP_IMPORTS=config.cmo build_path_prefix_map.cmo misc.cmo \ + identifiable.cmo numbers.cmo arg_helper.cmo clflags.cmo \ + load_path.cmo ccomp.cmo $(call byte_and_opt,ocamlmktop,$(OCAMLMKTOP_IMPORTS) $(OCAMLMKTOP),) # Converter olabl/ocaml 2.99 to ocaml 3 -OCAML299TO3= lexer299.cmo ocaml299to3.cmo -LIBRARY3= misc.cmo warnings.cmo build_path_prefix_map.cmo location.cmo +OCAML299TO3=lexer299.cmo ocaml299to3.cmo +LIBRARY3=config.cmo build_path_prefix_map.cmo misc.cmo warnings.cmo location.cmo ocaml299to3: $(OCAML299TO3) $(CAMLC) $(LINKFLAGS) -o ocaml299to3 $(LIBRARY3) $(OCAML299TO3) @@ -211,9 +207,8 @@ clean:: # Insert labels following an interface file (upgrade 3.02 to 3.03) -ADDLABELS_IMPORTS=misc.cmo config.cmo arg_helper.cmo clflags.cmo \ - identifiable.cmo numbers.cmo terminfo.cmo \ - build_path_prefix_map.cmo \ +ADDLABELS_IMPORTS=config.cmo build_path_prefix_map.cmo misc.cmo arg_helper.cmo \ + clflags.cmo identifiable.cmo numbers.cmo terminfo.cmo \ warnings.cmo location.cmo longident.cmo docstrings.cmo \ syntaxerr.cmo ast_helper.cmo parser.cmo lexer.cmo parse.cmo @@ -231,9 +226,10 @@ LN := cp -pf endif install:: +ifeq "$(INSTALL_BYTECODE_PROGRAMS)" "true" for i in $(install_files); \ do \ - $(INSTALL_PROG) "$$i" "$(INSTALL_BINDIR)/$$i.byte$(EXE)" && \ + $(INSTALL_PROG) "$$i" "$(INSTALL_BINDIR)/$$i.byte$(EXE)"; \ if test -f "$$i".opt; then \ $(INSTALL_PROG) "$$i.opt" "$(INSTALL_BINDIR)/$$i.opt$(EXE)" && \ (cd "$(INSTALL_BINDIR)/" && $(LN) "$$i.opt$(EXE)" "$$i$(EXE)"); \ @@ -241,6 +237,14 @@ install:: (cd "$(INSTALL_BINDIR)/" && $(LN) "$$i.byte$(EXE)" "$$i$(EXE)"); \ fi; \ done +else + for i in $(install_files); \ + do \ + if test -f "$$i".opt; then \ + $(INSTALL_PROG) "$$i.opt" "$(INSTALL_BINDIR)/$$i.opt$(EXE)"; \ + fi; \ + done +endif clean:: rm -f addlabels @@ -269,8 +273,8 @@ beforedepend:: cvt_emit.ml # Reading cmt files READ_CMT= \ - ../compilerlibs/ocamlcommon.cma \ - ../compilerlibs/ocamlbytecomp.cma \ + $(ROOTDIR)/compilerlibs/ocamlcommon.cma \ + $(ROOTDIR)/compilerlibs/ocamlbytecomp.cma \ \ cmt2annot.cmo read_cmt.cmo @@ -287,11 +291,13 @@ install:: # The bytecode disassembler -DUMPOBJ=opnames.cmo dumpobj.cmo +DUMPOBJ= \ + $(ROOTDIR)/compilerlibs/ocamlcommon.cma \ + $(ROOTDIR)/compilerlibs/ocamlbytecomp.cma \ + \ + opnames.cmo dumpobj.cmo -$(call byte_and_opt,dumpobj,misc.cmo config.cmo identifiable.cmo \ - numbers.cmo arg_helper.cmo clflags.cmo tbl.cmo \ - ident.cmo opcodes.cmo bytesections.cmo $(DUMPOBJ),) +$(call byte_and_opt,dumpobj,$(DUMPOBJ),) make_opcodes.ml: make_opcodes.mll $(CAMLLEX) make_opcodes.mll @@ -299,8 +305,8 @@ make_opcodes.ml: make_opcodes.mll make_opcodes: make_opcodes.ml $(CAMLC) make_opcodes.ml -o $@ -opnames.ml: ../byterun/caml/instruct.h make_opcodes - $(CAMLRUN) make_opcodes -opnames < $< > $@ +opnames.ml: $(ROOTDIR)/runtime/caml/instruct.h make_opcodes + $(ROOTDIR)/runtime/ocamlrun make_opcodes -opnames < $< > $@ clean:: rm -f opnames.ml make_opcodes make_opcodes.ml @@ -315,15 +321,16 @@ else DEF_SYMBOL_PREFIX = '-Dsymbol_prefix=""' endif -objinfo_helper$(EXE): objinfo_helper.c ../byterun/caml/s.h - $(CC) $(CFLAGS) $(CPPFLAGS) -I../byterun $(OUTPUTEXE)$@ \ +objinfo_helper$(EXE): objinfo_helper.c $(ROOTDIR)/runtime/caml/s.h + $(CC) $(OC_CFLAGS) $(OC_CPPFLAGS) -I$(ROOTDIR)/runtime $(OUTPUTEXE)$@ \ $(DEF_SYMBOL_PREFIX) $(LIBBFD_INCLUDE) $< $(LIBBFD_LINK) -OBJINFO=../compilerlibs/ocamlcommon.cma \ - ../compilerlibs/ocamlbytecomp.cma \ - ../compilerlibs/ocamlmiddleend.cma \ - ../asmcomp/printclambda.cmo \ - ../asmcomp/export_info.cmo \ +OBJINFO=$(ROOTDIR)/compilerlibs/ocamlcommon.cma \ + $(ROOTDIR)/compilerlibs/ocamlbytecomp.cma \ + $(ROOTDIR)/compilerlibs/ocamlmiddleend.cma \ + $(ROOTDIR)/asmcomp/backend_var.cmo \ + $(ROOTDIR)/asmcomp/printclambda.cmo \ + $(ROOTDIR)/asmcomp/export_info.cmo \ objinfo.cmo $(call byte_and_opt,ocamlobjinfo,$(OBJINFO),objinfo_helper$(EXE)) @@ -332,20 +339,25 @@ install:: $(INSTALL_PROG) \ objinfo_helper$(EXE) "$(INSTALL_LIBDIR)/objinfo_helper$(EXE)" +primreq=$(ROOTDIR)/compilerlibs/ocamlcommon.cma \ + $(ROOTDIR)/compilerlibs/ocamlbytecomp.cma \ + primreq.cmo + # Scan object files for required primitives -$(call byte_and_opt,primreq,config.cmo primreq.cmo,) - -LINTAPIDIFF=../compilerlibs/ocamlcommon.cmxa \ - ../compilerlibs/ocamlbytecomp.cmxa \ - ../compilerlibs/ocamlmiddleend.cmxa \ - ../asmcomp/printclambda.cmx \ - ../asmcomp/export_info.cmx \ - ../otherlibs/str/str.cmxa \ +$(call byte_and_opt,primreq,$(primreq),) + +LINTAPIDIFF=$(ROOTDIR)/compilerlibs/ocamlcommon.cmxa \ + $(ROOTDIR)/compilerlibs/ocamlbytecomp.cmxa \ + $(ROOTDIR)/compilerlibs/ocamlmiddleend.cmxa \ + $(ROOTDIR)/asmcomp/backend_var.cmx \ + $(ROOTDIR)/asmcomp/printclambda.cmx \ + $(ROOTDIR)/asmcomp/export_info.cmx \ + $(ROOTDIR)/otherlibs/str/str.cmxa \ lintapidiff.cmx -lintapidiff.opt: INCLUDES+= -I ../otherlibs/str +lintapidiff.opt: INCLUDES+= -I $(ROOTDIR)/otherlibs/str lintapidiff.opt: $(LINTAPIDIFF) - $(CAMLOPT) $(LINKFLAGS) -I .. -o $@ $(LINTAPIDIFF) + $(CAMLOPT_CMD) $(LINKFLAGS) -I $(ROOTDIR) -o $@ $(LINTAPIDIFF) clean:: rm -f -- lintapidiff.opt lintapidiff.cm? lintapidiff.o @@ -356,16 +368,16 @@ clean:: # Copy a bytecode executable, stripping debug info -stripdebug=../compilerlibs/ocamlcommon.cma \ - ../compilerlibs/ocamlbytecomp.cma \ +stripdebug=$(ROOTDIR)/compilerlibs/ocamlcommon.cma \ + $(ROOTDIR)/compilerlibs/ocamlbytecomp.cma \ stripdebug.cmo $(call byte_and_opt,stripdebug,$(stripdebug),) # Compare two bytecode executables -CMPBYT=../compilerlibs/ocamlcommon.cma \ - ../compilerlibs/ocamlbytecomp.cma \ +CMPBYT=$(ROOTDIR)/compilerlibs/ocamlcommon.cma \ + $(ROOTDIR)/compilerlibs/ocamlbytecomp.cma \ cmpbyt.cmo $(call byte_and_opt,cmpbyt,$(CMPBYT),) @@ -377,6 +389,29 @@ install:: "$(INSTALL_BINDIR)/" endif +CAMLTEX= $(ROOTDIR)/compilerlibs/ocamlcommon.cma \ + $(ROOTDIR)/compilerlibs/ocamlbytecomp.cma \ + $(ROOTDIR)/compilerlibs/ocamltoplevel.cma \ + $(ROOTDIR)/otherlibs/str/str.cma \ + $(ROOTDIR)/otherlibs/$(UNIXLIB)/unix.cma \ + caml_tex.ml + +#Scan latex files, and run ocaml code examples + +caml-tex: INCLUDES += $(addprefix -I $(ROOTDIR)/otherlibs/,str $(UNIXLIB)) +caml-tex: $(CAMLTEX) + $(ROOTDIR)/runtime/ocamlrun $(ROOTDIR)/ocamlc -nostdlib \ + -I $(ROOTDIR)/stdlib $(LINKFLAGS) -linkall \ + -o $@ -no-alias-deps $(CAMLTEX) + +# we need str and unix which depend on the bytecode version of other tools +# thus we delay building caml-tex to the opt.opt stage +ifneq "$(WITH_CAMLTEX)" "" +opt.opt:caml-tex +endif +clean:: + rm -f -- caml-tex caml_tex.cm? + # Common stuff .SUFFIXES: @@ -393,8 +428,11 @@ endif clean:: rm -f *.cmo *.cmi *.cma *.dll *.so *.lib *.a +CAMLDEP=$(CAMLRUN) $(ROOTDIR)/boot/ocamlc -depend +DEPFLAGS=-slash +DEPINCLUDES=$(INCLUDES) depend: beforedepend - $(CAMLRUN) ./ocamldep -slash $(INCLUDES) *.mli *.ml > .depend + $(CAMLDEP) $(DEPFLAGS) $(DEPINCLUDES) *.mli *.ml > .depend .PHONY: clean install beforedepend depend diff --git a/tools/Makefile.nt b/tools/Makefile.nt deleted file mode 100644 index ed9900bb..00000000 --- a/tools/Makefile.nt +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include Makefile diff --git a/tools/caml_tex.ml b/tools/caml_tex.ml new file mode 100644 index 00000000..108a0f66 --- /dev/null +++ b/tools/caml_tex.ml @@ -0,0 +1,761 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Gallium, INRIA Paris *) +(* Jacques Garrigue, Nagoya University *) +(* Florian Angeletti *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +[@@@warning "a-40-6"] +open StdLabels +open Str + +let camlbegin = "\\caml" +let camlend = "\\endcaml" +let camlin = {|\\?\1|} +let camlout = {|\\:\1|} +let camlbunderline = "\\<" +let camleunderline = "\\>" + +let start newline out s args = + Format.fprintf out "%s%s" camlbegin s; + List.iter (Format.fprintf out "{%s}") args; + if newline then Format.fprintf out "\n" + +let stop newline out s = + Format.fprintf out "%s%s" camlend s; + if newline then Format.fprintf out "\n" + +let code_env ?(newline=true) env out s = + let sep = if s.[String.length s - 1] = '\n' then "" else "\n" in + Format.fprintf out "%a%s%s%a" + (fun ppf env -> start false ppf env []) env s sep (stop newline) env + +let main = "example" +type example_mode = Toplevel | Verbatim | Signature +let string_of_mode = function + | Toplevel -> "toplevel" + | Verbatim -> "verbatim" + | Signature -> "signature" + +let input_env = "input" +let ok_output ="output" +let error ="error" +let warning ="warn" +let phrase_env = "" + +let verbose = ref true +let linelen = ref 72 +let outfile = ref "" +let cut_at_blanks = ref false +let files = ref [] +let repo_root = ref "" + +let (~!) = + let memo = ref [] in + fun key -> + try List.assq key !memo + with Not_found -> + let data = Str.regexp key in + memo := (key, data) :: !memo; + data + +exception Phrase_parsing of string + +module Toplevel = struct + (** Initialize the toplevel loop, redirect stdout and stderr, + capture warnings and error messages *) + + type output = + { + error : string; (** error message text *) + warnings : string list; (** warning messages text *) + values : string; (** toplevel output *) + stdout : string; (** output printed on the toplevel stdout *) + underlined : (int * int) list + (** locations to underline in input phrases *) + } + + let buffer_fmt () = + let b = Buffer.create 30 in b, Format.formatter_of_buffer b + + let error_fmt = buffer_fmt () + let warning_fmt = buffer_fmt () + + let out_fmt = buffer_fmt () + + let flush_fmt (b,fmt) = + Format.pp_print_flush fmt (); + let r = Buffer.contents b in + Buffer.reset b; + r + + (** Redirect the stdout *) + let stdout_out, stdout_in = Unix.pipe ~cloexec:true () + let () = Unix.dup2 stdout_in Unix.stdout + + let self_error_fmt = Format.formatter_of_out_channel stderr + let eprintf = Format.eprintf + + let read_stdout = + let size = 50 in + let b = Bytes.create size in + let buffer = Buffer.create 100 in + let rec read_toplevel_stdout () = + match Unix.select[stdout_out][][] 0. with + | [a], _, _ -> + let n = Unix.read stdout_out b 0 size in + Buffer.add_subbytes buffer b 0 n; + if n = size then read_toplevel_stdout () + | _ -> () + in + fun () -> + let () = flush stdout; read_toplevel_stdout () in + let r = Buffer.contents buffer in + Buffer.reset buffer; + r + + (** Store character intervals directly *) + let locs = ref [] + let register_loc (loc : Location.t) = + let startchar = loc.loc_start.pos_cnum in + let endchar = loc.loc_end.pos_cnum in + if startchar >= 0 then + locs := (startchar, endchar) :: !locs + + (** Record the main location instead of printing it *) + let printer_register_locs = + { Location.batch_mode_printer with + pp_main_loc = (fun _ _ _ loc -> register_loc loc) } + + (** Capture warnings and keep them in a list *) + let warnings = ref [] + let report_printer = + (* Extend [printer_register_locs] *) + let pp self ppf report = + match report.Location.kind with + | Location.Report_warning _ | Location.Report_warning_as_error _ -> + printer_register_locs.pp self (snd warning_fmt) report; + let w = flush_fmt warning_fmt in + warnings := w :: !warnings + | _ -> + printer_register_locs.pp self ppf report + in + { printer_register_locs with pp } + + let fatal ic oc fmt = + Format.kfprintf + (fun ppf -> Format.fprintf ppf "@]@."; close_in ic; close_out oc; exit 1) + self_error_fmt ("@[ Error " ^^ fmt) + + let init () = + Location.report_printer := (fun () -> report_printer); + Clflags.color := Some Misc.Color.Never; + Clflags.no_std_include := true; + Compenv.last_include_dirs := [Filename.concat !repo_root "stdlib"]; + Compmisc.init_path false; + try + Toploop.initialize_toplevel_env (); + Sys.interactive := false + with _ -> + (eprintf "Invalid repo root: %s?%!" !repo_root; exit 2) + + let exec (_,ppf) p = + try + ignore @@ Toploop.execute_phrase true ppf p + with exn -> + let bt = Printexc.get_raw_backtrace () in + begin try Location.report_exception (snd error_fmt) exn + with _ -> + eprintf "Uncaught exception: %s\n%s\n" + (Printexc.to_string exn) + (Printexc.raw_backtrace_to_string bt) + end + + let parse fname mode s = + let lex = Lexing.from_string s in + Location.init lex fname; + Location.input_name := fname; + Location.input_lexbuf := Some lex; + try + match mode with + | Toplevel -> Parse.toplevel_phrase lex + | Verbatim -> Ptop_def (Parse.implementation lex) + | Signature -> + let sign = Parse.interface lex in + let name = Location.mknoloc "wrap" in + let str = + Ast_helper.[Str.modtype @@ Mtd.mk ~typ:(Mty.signature sign) name] in + Ptop_def str + with + | Lexer.Error _ | Syntaxerr.Error _ -> + raise (Phrase_parsing s) + + let take x = let r = !x in x := []; r + + let read_output () = + let warnings = take warnings in + let error = flush_fmt error_fmt in + let values = + replace_first ~!{|^#\( *\*\)* *|} "" @@ flush_fmt out_fmt in + (* the inner ( *\* )* group is here to clean the starting "*" + introduced for multiline comments *) + let underlined = take locs in + let stdout = read_stdout () in + { values; warnings; error; stdout; underlined } + + (** exec and ignore all output from the toplevel *) + let eval b = + let s = Buffer.contents b in + let ast = Parse.toplevel_phrase (Lexing.from_string s) in + exec out_fmt ast; + ignore (read_output()); + Buffer.reset b + +end + +let () = + Arg.parse ["-n", Arg.Int (fun n -> linelen := n), "line length"; + "-o", Arg.String (fun s -> outfile := s), "output"; + "-repo-root", Arg.String ((:=) repo_root ), "repo root"; + "-w", Arg.Set cut_at_blanks, "cut at blanks"; + "-v", Arg.Bool (fun b -> verbose := b ), "output result on stderr" + ] + (fun s -> files := s :: !files) + "caml-tex: "; + Toplevel.init () + + +(** The Output module deals with the analysis and classification + of the interpreter output and the parsing of status-related options + or annotations for the caml_example environment *) +module Output = struct + + (** Interpreter output status *) + type status = + | Ok + | Warning of int + | Error + + type kind = + | Annotation (** Local annotation: [ [@@expect (*annotation*) ] ]*) + | Option (** Global environment option: + [\begin{caml_example}[option[=value]] + ... + \end{caml_example}] *) + + (** Pretty printer for status *) + let pp_status ppf = function + | Error -> Format.fprintf ppf "error" + | Ok -> Format.fprintf ppf "ok" + | Warning n -> Format.fprintf ppf "warning %d" n + + (** Pretty printer for status preceded with an undefined determinant *) + let pp_a_status ppf = function + | Error -> Format.fprintf ppf "an error" + | Ok -> Format.fprintf ppf "an ok" + | Warning n -> Format.fprintf ppf "a warning %d" n + + (** {1 Related latex environment } *) + let env = function + | Error -> error + | Warning _ -> warning + | Ok -> ok_output + + (** {1 Exceptions } *) + exception Parsing_error of kind * string + + type source = + { + file : string; + lines : int * int; + phrase : string; + output : string + } + type unexpected_report = {source : source; expected : status; got : status} + exception Unexpected_status of unexpected_report + + let print_source ppf {file; lines = (start, stop); phrase; output} = + Format.fprintf ppf "%s, lines %d to %d:\n\"\n%s\n\"\n\"\n%s\n\"." + file start stop phrase output + + let print_unexpected {source; expected; got} = + if expected = Ok then + Toplevel.eprintf + "Error when evaluating a caml_example environment in %a\n\ + Unexpected %a status.\n\ + If %a status was expected, add an [@@expect %a] annotation.\n" + print_source source + pp_status got + pp_a_status got + pp_status got + else + Toplevel.eprintf + "Error when evaluating a guarded caml_example environment in %a\n\ + Unexpected %a status, %a status was expected.\n\ + If %a status was in fact expected, change the status annotation to \ + [@@expect %a].\n" + print_source source + pp_status got + pp_a_status expected + pp_a_status got + pp_status got; + flush stderr + + let print_parsing_error k s = + match k with + | Option -> + Toplevel.eprintf + "Unknown caml_example option: [%s].\n\ + Supported options are \"ok\",\"error\", or \"warning=n\" (with n \ + a warning number).\n" s + | Annotation -> + Toplevel.eprintf + "Unknown caml_example phrase annotation: [@@expect %s].\n\ + Supported annotations are [@@expect ok], [@@expect error],\n\ + and [@@expect warning n] (with n a warning number).\n" s + + (** {1 Output analysis} *) + let catch_error = function + | "" -> None + | _ -> Some Error + + let catch_warning = + function + | [] -> None + | s :: _ when string_match ~!{|Warning \([0-9]+\):|} s 0 -> + Some (Warning (int_of_string @@ matched_group 1 s)) + | _ -> None + + let status ws es = + match catch_warning ws, catch_error es with + | Some w, _ -> w + | None, Some e -> e + | None, None -> Ok + + (** {1 Parsing caml_example options } *) + + (** Parse [warning=n] options for caml_example options *) + let parse_warning s = + if string_match ~!{|warning=\([0-9]+\)|} s 0 then + Some (Warning (int_of_string @@ matched_group 1 s)) + else + None + + (** Parse [warning n] annotations *) + let parse_local_warning s = + if string_match ~!{|warning \([0-9]+\)|} s 0 then + Some (Warning (int_of_string @@ matched_group 1 s)) + else + None + + let parse_error s = + if s="error" then Some Error else None + + let parse_ok s = + if s = "ok" then Some Ok else None + + (** Parse the environment-wide expected status output *) + let expected s = + match parse_warning s, parse_error s with + | Some w, _ -> w + | None, Some e -> e + | None, None -> raise (Parsing_error (Option,s)) + + (** Parse the local (i.e. phrase-wide) expected status output *) + let local_expected s = + match parse_local_warning s, parse_error s, parse_ok s with + | Some w, _, _ -> w + | None, Some e, _ -> e + | None, None, Some ok -> ok + | None, None, None -> raise (Parsing_error (Annotation,s)) + +end + +module Text_transform = struct + + type kind = + | Underline + | Ellipsis + + type t = { kind : kind; start : int; stop : int} + exception Intersection of + { + line : int; + file : string; + left : t; + right : t; + } + + let pp ppf = function + | Underline -> Format.fprintf ppf "underline" + | Ellipsis -> Format.fprintf ppf "ellipsis" + + let underline start stop = { kind = Underline; start; stop} + let ellipsis start stop = { kind = Ellipsis; start; stop } + + let escape_specials s = + let s1 = global_replace ~!"\\\\" "\\\\\\\\" s in + let s2 = global_replace ~!"'" "\\\\textquotesingle\\\\-" s1 in + let s3 = global_replace ~!"`" "\\\\textasciigrave\\\\-" s2 in + s3 + + let rec apply_transform input (pos,underline_stop,out) t = + if pos >= String.length input then pos, underline_stop, out + else match underline_stop with + | Some stop when stop <= t.start -> + let f = escape_specials (String.sub input ~pos ~len:(stop - pos)) in + let out = {|\>|} :: f :: out in + apply_transform input (stop,None,out) t + | _ -> + let out = + escape_specials (String.sub input ~pos ~len:(t.start - pos))::out in + match t.kind with + | Ellipsis -> t.stop, underline_stop, {|\ldots|} :: out + | Underline -> + t.start, Some t.stop, {|\<|} :: out + + (** Check that all ellipsis are strictly nested inside underline transform + and that otherwise no transform starts before the end of the previous + transform in a list of transforms *) + type partition = U of t * t list | E of t + let check_partition line file l = + let init = ellipsis 0 0 in + let rec partition = function + | [] -> [] + | {kind=Underline; _ } as t :: q -> underline t [] q + | {kind=Ellipsis; _ } as t :: q -> E t :: partition q + and underline u n = function + | [] -> end_underline u n [] + | {kind=Underline; _ } :: _ as q -> end_underline u n q + | {kind=Ellipsis; _ } as t :: q -> + if t.stop < u.stop then underline u (t::n) q + else end_underline u n (t::q) + and end_underline u n l = U(u,List.rev n) :: partition l in + let check_elt last t = + if t.start < last.stop then + raise (Intersection {line;file; left = last; right = t}) + else + t in + let check acc = function + | E t -> check_elt acc t + | U(u,n) -> + let _ = check_elt acc u in + let _ = List.fold_left ~f:check_elt ~init n in + u in + List.fold_left ~f:check ~init (partition l) + |> ignore + + let apply ts file line s = + (* remove duplicated transforms that can appear due to + duplicated parse tree elements. For instance, + [let f : (_ [@ellipsis] = ()] is transformed to + [let f: (_ [@ellipsis]) = (():(_ [@ellipsis])] with the same location + for the two ellipses. *) + let ts = List.sort_uniq compare ts in + let ts = List.sort (fun x y -> compare x.start y.start) ts in + check_partition line file ts; + let last, underline, ls = + List.fold_left ~f:(apply_transform s) ~init:(0,None,[]) ts in + let last, ls = match underline with + | None -> last, ls + | Some stop -> + let f = escape_specials (String.sub s ~pos:last ~len:(stop - last)) in + stop, {|\>|} :: f :: ls in + let ls = + let n = String.length s in + if last = n then ls else + escape_specials (String.sub s last (n-last)) :: ls in + String.concat "" (List.rev ls) +end + + +exception Missing_double_semicolon of string * int + +exception Missing_mode of string * int + +type incompatibility = + | Signature_with_visible_answer of string * int +exception Incompatible_options of incompatibility + + +module Ellipsis = struct + (** This module implements the extraction of ellipsis locations + from phrases. + + An ellipsis is either an [[@ellipsis]] attribute, or a pair + of [[@@@ellipsis.start]...[@@@ellipsis.stop]] attributes. *) + + exception Unmatched_ellipsis of {kind : string; start : int; stop : int} + (** raised when an [[@@@ellipsis.start]] or [[@@@ellipsis.stop]] is + not paired with another ellipsis attribute *) + + exception Nested_ellipses of {first : int ; second : int} + (** raised by [[@@@ellipsis.start][@@@ellipsis.start]] *) + + let extract f x = + let transforms = ref [] in + let last_loc = ref Location.none in + let left_mark = ref None (* stored position of [@@@ellipsis.start]*) in + let location _this loc = + (* we rely on the fact that the default iterator calls first + the location subiterator, then the attribute subiterator *) + last_loc := loc in + let attribute _this attr = + let module L = Location in + let module P = Parsetree in + let name = attr.P.attr_name.L.txt in + let loc = !last_loc in + let start = loc.L.loc_start.Lexing.pos_cnum in + let attr_start = attr.P.attr_loc.L.loc_start.Lexing.pos_cnum in + let attr_stop = attr.P.attr_loc.L.loc_end.Lexing.pos_cnum in + let stop = max loc.L.loc_end.Lexing.pos_cnum attr_stop in + let check_nested () = match !left_mark with + | Some (first,_) -> raise (Nested_ellipses {first; second=attr_start}) + | None -> () in + match name with + | "ellipsis" -> + check_nested (); + transforms := + {Text_transform.kind=Ellipsis; start; stop } + :: !transforms + | "ellipsis.start" -> + check_nested (); + left_mark := Some (start, stop) + | "ellipsis.stop" -> + begin match !left_mark with + | None -> raise (Unmatched_ellipsis {kind="right"; start; stop}) + | Some (start', stop' ) -> + let start, stop = min start start', max stop stop' in + transforms := {kind=Ellipsis; start ; stop } :: !transforms; + left_mark := None + end + | _ -> () + in + f {Ast_iterator.default_iterator with location; attribute} x; + (match !left_mark with + | None -> () + | Some (start,stop) -> + raise (Unmatched_ellipsis {kind="left"; start; stop }) + ); + !transforms + + let find = function + | Parsetree.Ptop_def ast -> extract (fun it -> it.structure it) ast + | Ptop_dir _ -> [] + +end + +let process_file file = + let ic = try open_in file with _ -> failwith "Cannot read input file" in + let phrase_start = ref 1 and phrase_stop = ref 1 in + let incr_phrase_start () = + incr phrase_start; + phrase_stop := !phrase_start in + let oc = + try if !outfile = "-" then + stdout + else if !outfile = "" then + open_out (replace_first ~!"\\.tex$" "" file ^ ".ml.tex") + else + open_out_gen [Open_wronly; Open_creat; Open_append; Open_text] + 0x666 !outfile + with _ -> failwith "Cannot open output file" in + let tex_fmt = Format.formatter_of_out_channel oc in + let fatal x = Toplevel.fatal ic oc x in + let re_spaces = "[ \t]*" in + let re_start = ~!( + {|\\begin{caml_example\(\*?\)}|} ^ re_spaces + ^ {|\({toplevel}\|{verbatim}\|{signature}\)?|} ^ re_spaces + ^ {|\(\[\(.*\)\]\)?|} ^ re_spaces + ^ "$" + ) in + try while true do + let input = ref (input_line ic) in + incr_phrase_start(); + if string_match re_start !input 0 + then begin + let omit_answer = matched_group 1 !input = "*" in + let mode = + match matched_group 2 !input with + | exception Not_found -> raise (Missing_mode(file, !phrase_stop)) + | "{toplevel}" -> Toplevel + | "{verbatim}" -> Verbatim + | "{signature}" -> Signature + | _ -> assert false in + if mode = Signature && not omit_answer then raise + (Incompatible_options( + Signature_with_visible_answer(file,!phrase_stop)) + ); + let explicit_stop = match mode with + | Verbatim | Signature -> false + | Toplevel -> true in + let global_expected = try Output.expected @@ matched_group 4 !input + with Not_found -> Output.Ok in + start true tex_fmt main [string_of_mode mode]; + let first = ref true in + let read_phrase () = + let phrase = Buffer.create 256 in + let rec read () = + let input = incr phrase_stop; input_line ic in + let implicit_stop = + if string_match ~!"\\\\end{caml_example\\*?}[ \t]*$" + input 0 + then + begin + if !phrase_stop = 1 + !phrase_start then + raise End_of_file + else if explicit_stop then + raise @@ Missing_double_semicolon (file,!phrase_stop) + else + true + end + else false in + if Buffer.length phrase > 0 then Buffer.add_char phrase '\n'; + let stop = + implicit_stop || + ( not (mode = Signature) + && string_match ~!"\\(.*\\)[ \t]*;;[ \t]*$" input 0 ) + in + if not stop then ( + Buffer.add_string phrase input; read () + ) + else begin + decr phrase_stop; + let last_input = + if implicit_stop then "" else matched_group 1 input in + let expected = + if string_match ~!{|\(.*\)\[@@expect \(.*\)\]|} last_input 0 then + ( Buffer.add_string phrase (matched_group 1 last_input); + Output.local_expected @@ matched_group 2 last_input ) + else + (Buffer.add_string phrase last_input; global_expected) + in + if not implicit_stop then Buffer.add_string phrase ";;"; + implicit_stop, Buffer.contents phrase, expected + end in + read () + in + try while true do + let implicit_stop, phrase, expected = read_phrase () in + let ast = Toplevel.parse file mode phrase in + let ellipses = Ellipsis.find ast in + let () = Toplevel.(exec out_fmt) ast in + let out = Toplevel.read_output () in + let error_msgs = String.concat "" (out.warnings @ [out.error]) in + let output = String.concat "" [error_msgs; out.stdout; out.values] in + let status = Output.status out.warnings out.error in + if status <> expected then ( + let source = Output.{ + file; + lines = (!phrase_start, !phrase_stop); + phrase; + output + } in + raise (Output.Unexpected_status + {Output.got=status; expected; source} ) ) + else ( incr phrase_stop; phrase_start := !phrase_stop ); + let phrase = + let underline = + List.map (fun (x,y) -> Text_transform.underline x y) + out.underlined in + Text_transform.apply (underline @ ellipses) + file !phrase_stop phrase in + (* Special characters may also appear in output strings -Didier *) + let output = Text_transform.escape_specials output in + let phrase = global_replace ~!{|^\(.\)|} camlin phrase + and output = global_replace ~!{|^\(.\)|} camlout output in + let final_output = + if omit_answer && String.length error_msgs > 0 then + global_replace ~!{|^\(.\)|} camlout error_msgs + else if omit_answer then "" + else output in + start false tex_fmt phrase_env []; + code_env ~newline:omit_answer input_env tex_fmt phrase; + if String.length final_output > 0 then + code_env ~newline:false (Output.env status) tex_fmt final_output; + stop true tex_fmt phrase_env; + flush oc; + first := false; + if implicit_stop then raise End_of_file + done + with End_of_file -> phrase_start:= !phrase_stop; stop true tex_fmt main + end + else if string_match ~!"\\\\begin{caml_eval}[ \t]*$" !input 0 + then begin + let eval_buffer = Buffer.create 256 in + while input := input_line ic; + not (string_match ~!"\\\\end{caml_eval}[ \t]*$" !input 0) + do + Buffer.add_string eval_buffer !input; + Buffer.add_char eval_buffer '\n'; + if string_match ~!".*;;[ \t]*$" !input 0 then begin + Toplevel.eval eval_buffer + end + done; + if Buffer.length eval_buffer > 0 then + ( Buffer.add_string eval_buffer ";;\n"; Toplevel.eval eval_buffer ) + end else begin + Format.fprintf tex_fmt "%s\n" !input; + Format.pp_print_flush tex_fmt () + end + done with + | End_of_file -> close_in ic; close_out oc + | Output.Unexpected_status r -> + ( Output.print_unexpected r; close_in ic; close_out oc; exit 1 ) + | Output.Parsing_error (k,s) -> + ( Output.print_parsing_error k s; + close_in ic; close_out oc; exit 1 ) + | Phrase_parsing s -> fatal "when parsing the following phrase:@ %s" s + | Missing_double_semicolon (file, line_number) -> + fatal + "when evaluating a caml_example environment in %s:@;\ + missing \";;\" at line %d" file (line_number-2) + | Missing_mode (file, line_number) -> + fatal "when parsing a caml_example environment in %s:@;\ + missing mode argument at line %d,@ \ + available modes {toplevel,verbatim}" + file (line_number-2) + | Incompatible_options Signature_with_visible_answer (file, line_number) -> + fatal + "when parsing a caml_example environment in@ \ + %s, line %d:@,\ + the signature mode is only compatible with \"caml_example*\"@ \ + Hint: did you forget to add \"*\"?" + file (line_number-2); + | Text_transform.Intersection {line;file;left;right} -> + fatal + "when evaluating a caml_example environment in %s, line %d:@ \ + Textual transforms must be well-separated.@ The \"%a\" transform \ + spanned the interval %d-%d,@ \ + intersecting with another \"%a\" transform @ \ + on the %d-%d interval.@ \ + Hind: did you try to elide a code fragment which raised a warning?" + file (line-2) + Text_transform.pp left.kind left.start left.stop + Text_transform.pp right.kind right.start right.stop + | Ellipsis.Unmatched_ellipsis {kind;start;stop} -> + fatal "when evaluating a caml_example environment,@ \ + the %s mark at position %d-%d was unmatched" + kind start stop + | Ellipsis.Nested_ellipses {first;second} -> + fatal "when evaluating a caml_example environment,@ \ + there were two nested ellipsis attribute.@ The first one \ + started at position %d,@ the second one at %d" + first second + +let _ = + if !outfile <> "-" && !outfile <> "" then begin + try close_out (open_out !outfile) + with _ -> failwith "Cannot open output file" + end; + List.iter process_file (List.rev !files); diff --git a/tools/check-parser-uptodate-or-warn.sh b/tools/check-parser-uptodate-or-warn.sh new file mode 100755 index 00000000..5502eae5 --- /dev/null +++ b/tools/check-parser-uptodate-or-warn.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +#************************************************************************** +#* * +#* OCaml * +#* * +#* Gabriel Scherer, projet Parsifal, INRIA Saclay * +#* * +#* Copyright 2018 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +# We try to warn if the user edits parsing/parser.mly but forgets to +# rebuild the generated parser. Our heuristic is to use the file +# modification timestamp, but just testing +# (parsing/parser.mly -nt boot/menhir/parser.ml) +# is not robust to clone/checkout refreshing the files in an arbitrary +# order, so we check whether parser.mly was modified at least 10 +# seconds after boot/menhir/parser.ml. + +# mtime(): access a file's last modification time as a timestamp, +# using either GNU coreutils' stat --format, or BSD/macos stat -f. +# Default to 0 if 'stat' is not available. + +stat . 2>/dev/null 1>/dev/null +if test $? != 0 +then MTIME="" +elif test -n "$(stat --version 2>/dev/null | grep coreutils)" +then MTIME="stat --format %Y" +else MTIME="stat -f %m" +fi + +mtime() { + if test -z "$MTIME" + then echo 0 + else $MTIME $1 + fi +} + +# The check itself +SOURCE_MTIME=$(mtime parsing/parser.mly) +GENERATED_MTIME=$(mtime boot/menhir/parser.ml) +if test $SOURCE_MTIME -gt $(( $GENERATED_MTIME + 10 )) +then + echo + tput setaf 3; tput bold; printf "Warning: "; tput sgr0 + echo "Your 'parser.mly' file is more recent than the parser in 'boot/'." + echo "Its changes will be ignored unless you run:" + echo " make promote-menhir" + echo +fi diff --git a/tools/check-symbol-names b/tools/check-symbol-names index 805215c8..83d8d0cf 100755 --- a/tools/check-symbol-names +++ b/tools/check-symbol-names @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash #************************************************************************** #* * diff --git a/tools/check-typo b/tools/check-typo index 90149526..caeb4bc2 100755 --- a/tools/check-typo +++ b/tools/check-typo @@ -30,32 +30,14 @@ # - presence of a copyright header (missing-header) # - absence of a leftover "$Id" string (svn-keyword) -# Exceptions are handled with a git attribute: "ocaml-typo". +# Exceptions are handled with git attributes: "typo.*". # Its value for a given file is a comma-separated list of rule names, # which lists the rules that should be disabled for this file. # The rule names are the ones shown above in parentheses. -# Built-in exceptions: +# Built-in exception: # - Any file git identifies as binary # is automatically exempt from all the rules. -# - Any file whose name matches one of the following patterns is -# automatically exempt from all rules -# *.reference -# *.opt_reference -# */reference -# */.depend* -# - Any file whose name begins with "Makefile" is automatically exempt -# from the "tabs" rule. -# - Any file whose name matches one of the following patterns is -# automatically exempt from the "missing-header" rule. -# *.mlpack -# *.mllib -# *.mltop -# *.odocl -# *.clib -# - Any file whose name matches the following pattern is automatically -# exempt from the "long-line" rule (but not from "very-long-line"). -# */ocamldoc/* # ASCII characters are bytes from 0 to 127. Any other byte is # flagged as a non-ASCII character. @@ -75,22 +57,72 @@ # This program ignores any file that is not under git control, unless # explicitly given on the command line. -# If a directory has the git attribute "ocaml-typo" set to "prune", -# then it and its contents are ignored. +# If a directory has the git attribute "typo.prune" then it and its contents are +# ignored. # You can ignore a rule by giving the option - on the command # line (before any file names). +# Files which include the utf8 rule will be validated using grep and line-length +# computations will take UTF-8 sequences into account. As a special case, UTF-8 +# sequences are always allowed in the copyright headers. + # First prevent i18n from messing up everything. export LC_ALL=C +OCAML_CT_CAT=${OCAML_CT_CAT:-cat} +OCAML_CT_LS_FILES=${OCAML_CT_LS_FILES:-git ls-files} +OCAML_CT_HEAD=${OCAML_CT_HEAD:-HEAD} +OCAML_CT_AWK=${OCAML_CT_AWK:-awk} +if [ -z "${OCAML_CT_GIT_INDEX+x}" ] ; then + OCAML_CT_GIT_INDEX= +else + OCAML_CT_GIT_INDEX="GIT_INDEX_FILE=$OCAML_CT_GIT_INDEX" +fi + +# The output of processing the attributes should be whitespace-separated with +# - the "typo." prefix dropped +# - unset/false keys not present +# - set/true keys present +# - "may" keys present, suffixed by a question mark +# +# for example, +# typo.long-line: set +# typo.missing-header: may +# typo.very-long-line: false +# should result in "long-line missing-header?" +get_attrs() { + env $OCAML_CT_GIT_INDEX git check-attr --all $OCAML_CT_CA_FLAG "$1" \ + | grep -o " typo\\..*$" | sed "s/ typo\\.//g" \ + | grep -v ": unset" | grep -v ": false" \ + | sed "s/: set//g" | sed "s/: true//g" | sed "s/: may/?/g" +} + +# empty if the path is *not* pruned +check_prune() { + env $OCAML_CT_GIT_INDEX git check-attr typo.prune $OCAML_CT_CA_FLAG "$1" \ + | grep -v ': unspecified$' | grep -v ': false$' +} + # Special case for recursive call from the find command (see IGNORE_DIRS). case "$1" in --check-prune) - case `git check-attr ocaml-typo "$2" 2>/dev/null` in - *prune*) echo "INFO: pruned directory $2 (ocaml-typo=prune)" >&2; exit 0;; - *) exit 3;; - esac;; + case $2 in + .git|.git/*) + echo "INFO: pruned path $2 (.git)" >&2 + exit 0;; + esac + if test -n "$(check_prune "$2")"; then + echo "INFO: pruned path $2 (typo.prune)" >&2 + exit 0 + fi + exit 3;; +esac + +case "$1" in + --get-attrs) + get_attrs "$2" + exit 0;; esac usage () { @@ -103,7 +135,7 @@ userrules='' while : ; do case "$1" in -help|--help) usage;; - -*) userrules="${1#-},$userrules"; shift;; + -*) userrules="${1#-} $userrules"; shift;; --) shift; break;; *) break;; esac @@ -113,24 +145,31 @@ IGNORE_DIRS=" -name .git -prune -o -type d -exec $0 --check-prune {} ; -prune -o " +# `-type d`: simple files (not directories) are not pruned during the +# "find" invocation but below (look for "check_prune") for performance +# reasons: most files outside pruned directories are not pruned, so it +# is faster to optimistically run check-typo on them (and maybe get +# out in the middle) than to first check then run. +EXIT_CODE=0 ( case $# in 0) find . $IGNORE_DIRS -type f -print;; *) for i in "$@"; do find "$i" $IGNORE_DIRS -type f -print; done;; esac ) | ( while read f; do - case `git ls-files "$f" 2>&1` in - "") is_svn=false;; - *) is_svn=true;; + if test -n "$(check_prune "$f")"; then continue; fi + case `$OCAML_CT_LS_FILES "$f" 2>&1` in + "") path_in_index=false;; + *) path_in_index=true;; esac case "$*" in *$f*) is_cmd_line=true;; *) is_cmd_line=false;; esac - if $is_svn || $is_cmd_line; then :; else continue; fi - svnrules='' - if $is_svn; then + if $path_in_index || $is_cmd_line; then :; else continue; fi + attr_rules='' + if $path_in_index; then # Below is a git plumbing command to detect whether git regards a # particular file as binary. This takes into account .gitattributes, but # also works if the file has been automatically detected as binary by git. @@ -143,35 +182,46 @@ IGNORE_DIRS=" # the documentation for the --numstat option. Commands designated as # "plumbing" commands in git have stable output intended for parsing) EMPTY=`git hash-object -t tree /dev/null` - git diff-tree --numstat $EMPTY HEAD -- "$f" | grep -q "^-[[:blank:]]-" \ - && continue - svnrules=`git check-attr ocaml-typo "$f" | sed -e 's/.*: //'` - case $svnrules in unspecified) svnrules= ;; esac + git diff-tree --numstat $EMPTY $OCAML_CT_HEAD -- "$f" \ + | grep -q "^-[[:blank:]]-" && continue + attr_rules=$(get_attrs "$f") fi rules="$userrules" - add_hd(){ rules="missing-header,$rules"; } - case "$f" in - Makefile*|*/Makefile*) rules="tab,$rules";; - *.mlpack|*.mllib|*.mltop|*.odocl|*.itarget|*.clib) add_hd;; - *.reference|*.opt_reference|*/reference|*/.depend*) continue;; - esac - case "$f" in - ocamldoc/*|*/ocamldoc/*) rules="long-line,$rules";; - esac - (cat "$f" | tr -d '\r'; echo) \ - | awk -v rules="$rules" -v svnrules="$svnrules" -v file="$f" \ + # remove newlines, ensure spaces at boundary + rules=" $(echo $rules) " + attr_rules=" $(echo $attr_rules) " + + if test -n "$(echo "$rules $attr_rules" | grep " utf8 ")" + then + # grep -a is used to force the file to be considered as text and -x + # requires the entire line to match. This specifically detects the + # presence of lines containing malformed UTF-8. It may be tested using + # https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt + if $OCAML_CT_CAT "$OCAML_CT_PREFIX$f" \ + | LC_ALL=en_US.UTF8 grep -qaxv '.*' ; then + echo "File \"$f\" is not correctly encoded in UTF-8" + exit 2 + fi + fi + if ! \ + ($OCAML_CT_CAT "$OCAML_CT_PREFIX$f" | tr -d '\r'; echo) \ + | $OCAML_CT_AWK -v rules="$rules" -v attr_rules="$attr_rules" -v file="$f" \ ' function is_err(name) { - return (("," rules svnrules ",") !~ ("[, ]" name "[, ]")); + return ((rules attr_rules) !~ (" " name "[\\? ]")); + } + + function report_err(name, msg) { + printf ("%s:%d.%d:", file, NR, RSTART + RLENGTH); + printf (" [%s] %s\n", name, msg); + got_errors = 1; } function err(name, msg) { ++ counts[name]; - if (is_err(name) && counts[name] <= 10){ - printf ("%s:%d.%d:", file, NR, RSTART + RLENGTH); - printf (" [%s] %s\n", name, msg); - got_errors = 1; + if (is_err(name) && counts[name] <= 10) { + report_err(name, msg); if (counts[name] == 10){ printf ("WARNING: too many [%s] in this file.", name); printf (" Others will not be reported.\n"); @@ -179,6 +229,14 @@ IGNORE_DIRS=" } } + function err_if(guard, name, msg) { + if (is_err(guard)) { + err(name, msg); + } else { + ++ counts[name]; + } + } + function more_columns(str, limit, c){ c = 0; for (i = 1; i <= length(str); i++){ @@ -191,16 +249,31 @@ IGNORE_DIRS=" return c > limit; } + function utf8_decode(str) { + if (is_err("utf8")) { + return str; + } else { + # This script assumes that the UTF-8 has been externally validated + t = str; + gsub(/[\300-\367][\200-\277]+/, "?", t); + if (t != str) { + ++ counts["utf8"]; + } + return t; + } + } + BEGIN { state = "(first line)"; } match($0, /\t/) { err("tab", "TAB character(s)"); - if (more_columns($0, 80)){ + t = utf8_decode($0); + if (more_columns(t, 80)){ RSTART=81; RLENGTH = 0; - err("long-line", "line is over 80 columns"); + err_if("very-long-line", "long-line", "line is over 80 columns"); } - if (more_columns($0, 132)){ + if (more_columns(t, 132)){ RSTART=133; RLENGTH = 0; err("very-long-line", "line is over 132 columns"); @@ -209,10 +282,14 @@ IGNORE_DIRS=" match($0, /[\200-\377]/) \ && state != "authors" && state != "copyright" { - err("non-ascii", "non-ASCII character(s)"); - if (header_utf8 && !is_err("non-ascii")) { - err("non-ascii-utf8", \ - "non-ASCII character(s) AND UTF-8 encountered"); + if (is_err("utf8")) { + err("non-ascii", "non-ASCII character(s)"); + if (header_utf8 && !is_err("non-ascii")) { + err("non-ascii-utf8", \ + "non-ASCII character(s) AND UTF-8 encountered"); + } + } else { + ++ counts["utf8"]; } } @@ -229,19 +306,22 @@ IGNORE_DIRS=" } $0 !~ /\t/ && length($0) > 80 { - t = $0; - sub(/https?:[A-Za-z0-9._~:/?#\[\]@!$&\047()*+,;=%-]{73,}$/, "", t); + t = utf8_decode($0); + sub(/https?:[A-Za-z0-9._~:\/?#\[\]@!$&\047()*+,;=%-]{73,}$/, "", t); if (length(t) > 80) { RSTART = 81; RLENGTH = 0; - err("long-line", "line is over 80 columns"); + err_if("very-long-line", "long-line", "line is over 80 columns"); } } $0 !~ /\t/ && length($0) > 132 { RSTART = 133; RLENGTH = 0; - err("very-long-line", "line is over 132 columns"); + t = utf8_decode($0); + if (length(t) > 132) { + err("very-long-line", "line is over 132 columns"); + } } # Record that the header contained UTF-8 sequences @@ -313,18 +393,24 @@ IGNORE_DIRS=" counts["missing-header"] = 1; } } - split(svnrules, r, "[, ]"); + split(attr_rules, r, "[? ]"); for (i in r){ name = r[i]; if (name != "" && !counts[name]){ NR = 1; RSTART = 1; RLENGTH = 0; - err("unused-prop", sprintf("unused [%s] in ocaml-typo", name)); + if (attr_rules !~ (" " name "\\? ")) { + report_err(name, + sprintf("attribute is unused", name)); + } } } exit got_errors; } - ' + ' ; then + EXIT_CODE=1 + fi done + exit $EXIT_CODE ) diff --git a/tools/check-typo-since b/tools/check-typo-since new file mode 100755 index 00000000..77a9fa29 --- /dev/null +++ b/tools/check-typo-since @@ -0,0 +1,37 @@ +#!/bin/sh + +#************************************************************************** +#* * +#* OCaml * +#* * +#* Gabriel Scherer, projet Parsifal, INRIA Saclay * +#* * +#* Copyright 2018 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +# Run check-typo, comparing only files that have changed since a particular +# git state + +check_typo_since() { + CHECK_TYPO=$(dirname $0)/check-typo + git diff --name-only $1 \ + | (while IFS= read -r path + do + if test -e "$path"; then :; else continue; fi + $CHECK_TYPO --check-prune "$path" 2>/dev/null + if test $? -eq 0; then continue; fi + $CHECK_TYPO "$path" + done) +} + +case $# in + 0) echo "usage: check-typo-since "; exit 2;; + 1) check_typo_since $1; break;; + *) echo "too many arguments"; exit 2;; +esac diff --git a/tools/ci/appveyor/appveyor_build.cmd b/tools/ci/appveyor/appveyor_build.cmd index 89cb8770..9f0ebc97 100644 --- a/tools/ci/appveyor/appveyor_build.cmd +++ b/tools/ci/appveyor/appveyor_build.cmd @@ -24,18 +24,6 @@ goto %1 goto :EOF -:SaveVars -set OCAML_PREV_PATH=%PATH% -set OCAML_PREV_LIB=%LIB% -set OCAML_PREV_INCLUDE=%INCLUDE% -goto :EOF - -:RestoreVars -set PATH=%OCAML_PREV_PATH% -set LIB=%OCAML_PREV_LIB% -set INCLUDE=%OCAML_PREV_INCLUDE% -goto :EOF - :CheckPackage "%CYG_ROOT%\bin\bash.exe" -lc "cygcheck -dc %1" | findstr %1 > nul if %ERRORLEVEL% equ 1 ( @@ -59,11 +47,15 @@ goto :EOF chcp 65001 > nul rem This must be kept in sync with appveyor_build.sh set BUILD_PREFIX=🐫реализация -git worktree add "..\%BUILD_PREFIX%-msvc64" -b appveyor-build-msvc64 -git worktree add "..\%BUILD_PREFIX%-mingw32" -b appveyor-build-mingw32 -git worktree add "..\%BUILD_PREFIX%-msvc32" -b appveyor-build-msvc32 -cd "..\%BUILD_PREFIX%-mingw32" -git submodule update --init flexdll +git worktree add "..\%BUILD_PREFIX%-%PORT%" -b appveyor-build-%PORT% +if "%PORT%" equ "msvc64" ( + git worktree add "..\%BUILD_PREFIX%-msvc32" -b appveyor-build-%PORT%32 +) + +cd "..\%BUILD_PREFIX%-%PORT%" +if "%PORT%" equ "mingw32" ( + git submodule update --init flexdll +) cd "%APPVEYOR_BUILD_FOLDER%" appveyor DownloadFile "https://github.com/alainfrisch/flexdll/archive/0.37.tar.gz" -FileName "flexdll.tar.gz" || exit /b 1 @@ -80,8 +72,12 @@ rem in the list just so that the Cygwin version is always displayed on the log). rem CYGWIN_COMMANDS is a corresponding command to run with --version to test rem whether the package works. This is used to verify whether the installation rem needs upgrading. -set CYGWIN_PACKAGES=cygwin make diffutils mingw64-i686-gcc-core -set CYGWIN_COMMANDS=cygcheck make diff i686-w64-mingw32-gcc +set CYGWIN_PACKAGES=cygwin make diffutils +set CYGWIN_COMMANDS=cygcheck make diff +if "%PORT%" equ "mingw32" ( + set CYGWIN_PACKAGES=%CYGWIN_PACKAGES% mingw64-i686-gcc-core + set CYGWIN_COMMANDS=%CYGWIN_COMMANDS% i686-w64-mingw32-gcc +) set CYGWIN_INSTALL_PACKAGES= set CYGWIN_UPGRADE_REQUIRED=0 @@ -91,23 +87,26 @@ call :UpgradeCygwin "%CYG_ROOT%\bin\bash.exe" -lec "$APPVEYOR_BUILD_FOLDER/tools/ci/appveyor/appveyor_build.sh install" || exit /b 1 -call :SaveVars goto :EOF :build -rem Run the msvc64 and mingw32 builds -call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat" +if "%PORT%" equ "msvc64" ( + setlocal + call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat" +) +rem Do the main build (either msvc64 or mingw32) "%CYG_ROOT%\bin\bash.exe" -lec "$APPVEYOR_BUILD_FOLDER/tools/ci/appveyor/appveyor_build.sh" || exit /b 1 +if "%PORT%" neq "msvc64" goto :EOF + rem Reconfigure the environment and run the msvc32 partial build -call :RestoreVars +endlocal call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x86 "%CYG_ROOT%\bin\bash.exe" -lec "$APPVEYOR_BUILD_FOLDER/tools/ci/appveyor/appveyor_build.sh msvc32-only" || exit /b 1 goto :EOF :test rem Reconfigure the environment for the msvc64 build -call :RestoreVars call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat" "%CYG_ROOT%\bin\bash.exe" -lec "$APPVEYOR_BUILD_FOLDER/tools/ci/appveyor/appveyor_build.sh test" || exit /b 1 goto :EOF diff --git a/tools/ci/appveyor/appveyor_build.sh b/tools/ci/appveyor/appveyor_build.sh index 995553f1..055ef3f5 100644 --- a/tools/ci/appveyor/appveyor_build.sh +++ b/tools/ci/appveyor/appveyor_build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash #************************************************************************** #* * #* OCaml * @@ -33,16 +33,33 @@ function run { fi } +# Function: set_configuration +# Takes 3 arguments +# $1:the Windows port. Recognized values: mingw, msvc and msvc64 +# $2: the prefix to use to install +# $3: C compiler flags to use to turn warnings into errors function set_configuration { - cp config/m-nt.h byterun/caml/m.h - cp config/s-nt.h byterun/caml/s.h - - FILE=$(pwd | cygpath -f - -m)/config/Makefile - echo "Edit $FILE to set PREFIX=$2" - sed -e "/PREFIX=/s|=.*|=$2|" \ - -e "/^ *CFLAGS *=/s/\r\?$/ $3\0/" \ - config/Makefile.$1 > config/Makefile -# run "Content of $FILE" cat config/Makefile + case "$1" in + mingw) + build='--build=i686-pc-cygwin' + host='--host=i686-w64-mingw32' + ;; + msvc) + build='--build=i686-pc-cygwin' + host='--host=i686-pc-windows' + ;; + msvc64) + build='--build=x86_64-unknown-cygwin' + host='--host=x86_64-pc-windows' + ;; + esac + + ./configure $build $host --prefix="$2" + + FILE=$(pwd | cygpath -f - -m)/Makefile.config + echo "Edit $FILE to turn C compiler warnings into errors" + sed -i -e "/^ *OC_CFLAGS *=/s/\r\?$/ $3\0/" $FILE +# run "Content of $FILE" cat Makefile.config } APPVEYOR_BUILD_FOLDER=$(echo $APPVEYOR_BUILD_FOLDER| cygpath -f -) @@ -64,7 +81,10 @@ case "$1" in for f in flexdll.h flexlink.exe flexdll*_msvc.obj default*.manifest ; do cp $f "$OCAMLROOT/bin/flexdll/" done - echo 'eval $($APPVEYOR_BUILD_FOLDER/tools/msvs-promote-path)' >> ~/.bash_profile + if [ "$PORT" = "msvc64" ] ; then + echo 'eval $($APPVEYOR_BUILD_FOLDER/tools/msvs-promote-path)' \ + >> ~/.bash_profile + fi ;; msvc32-only) cd $APPVEYOR_BUILD_FOLDER/../$BUILD_PREFIX-msvc32 @@ -80,46 +100,50 @@ case "$1" in ;; test) FULL_BUILD_PREFIX=$APPVEYOR_BUILD_FOLDER/../$BUILD_PREFIX - run "ocamlc.opt -version" $FULL_BUILD_PREFIX-msvc64/ocamlc.opt -version - run "test msvc64" make -C $FULL_BUILD_PREFIX-msvc64 tests - run "test mingw32" make -C $FULL_BUILD_PREFIX-mingw32 tests - run "install msvc64" make -C $FULL_BUILD_PREFIX-msvc64 install - run "install mingw32" make -C $FULL_BUILD_PREFIX-mingw32 install + run "ocamlc.opt -version" $FULL_BUILD_PREFIX-$PORT/ocamlc.opt -version + run "test $PORT" make -C $FULL_BUILD_PREFIX-$PORT tests + run "install $PORT" make -C $FULL_BUILD_PREFIX-$PORT install + if [ "$PORT" = "msvc64" ] ; then + run "check_all_arches" make -C $FULL_BUILD_PREFIX-$PORT check_all_arches + fi ;; *) - cd $APPVEYOR_BUILD_FOLDER/../$BUILD_PREFIX-msvc64 - - tar -xzf $APPVEYOR_BUILD_FOLDER/flexdll.tar.gz - cd flexdll-$FLEXDLL_VERSION - make MSVC_DETECT=0 CHAINS=msvc64 support - cp flexdll*_msvc64.obj "$OCAMLROOT/bin/flexdll/" - cd .. - - set_configuration msvc64 "$OCAMLROOT" -WX - - cd ../$BUILD_PREFIX-mingw32 + cd $APPVEYOR_BUILD_FOLDER/../$BUILD_PREFIX-$PORT + + if [ "$PORT" = "msvc64" ] ; then + tar -xzf $APPVEYOR_BUILD_FOLDER/flexdll.tar.gz + cd flexdll-$FLEXDLL_VERSION + make MSVC_DETECT=0 CHAINS=msvc64 support + cp flexdll*_msvc64.obj "$OCAMLROOT/bin/flexdll/" + cd .. + fi - set_configuration mingw "$OCAMLROOT-mingw32" -Werror + if [ "$PORT" = "msvc64" ] ; then + set_configuration msvc64 "$OCAMLROOT" -WX + else + set_configuration mingw "$OCAMLROOT-mingw32" -Werror + fi - cd $APPVEYOR_BUILD_FOLDER/../$BUILD_PREFIX-msvc64 + cd $APPVEYOR_BUILD_FOLDER/../$BUILD_PREFIX-$PORT export TERM=ansi - script --quiet --return --command "make -C ../$BUILD_PREFIX-mingw32 flexdll world.opt" ../$BUILD_PREFIX-mingw32/build.log >/dev/null 2>/dev/null & - BUILD_PID=$! - run "make world" make world - run "make bootstrap" make bootstrap - run "make opt" make opt - run "make opt.opt" make opt.opt - - set +e - - # For an explanation of the sed command, see https://github.com/appveyor/ci/issues/1824 - tail --pid=$BUILD_PID -n +1 -f ../$BUILD_PREFIX-mingw32/build.log | sed -e 's/\d027\[K//g' -e 's/\d027\[m/\d027[0m/g' -e 's/\d027\[01\([m;]\)/\d027[1\1/g' & - TAIL_PID=$! - wait $BUILD_PID - STATUS=$? - wait $TAIL_PID - exit $STATUS + if [ "$PORT" = "mingw32" ] ; then + set -o pipefail + # For an explanation of the sed command, see + # https://github.com/appveyor/ci/issues/1824 + script --quiet --return --command \ + "make -C ../$BUILD_PREFIX-mingw32 flexdll world.opt" \ + ../$BUILD_PREFIX-mingw32/build.log | + sed -e 's/\d027\[K//g' \ + -e 's/\d027\[m/\d027[0m/g' \ + -e 's/\d027\[01\([m;]\)/\d027[1\1/g' + else + run "make world" make world + run "make bootstrap" make bootstrap + run "make opt" make opt + run "make opt.opt" make opt.opt + fi + ;; esac diff --git a/tools/ci/inria/bootstrap b/tools/ci/inria/bootstrap new file mode 100755 index 00000000..a77c1ed1 --- /dev/null +++ b/tools/ci/inria/bootstrap @@ -0,0 +1,245 @@ +#!/bin/sh +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Gallium, INRIA Rocquencourt * +#* * +#* Copyright 2014 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +# This script is run on Inria's continuous-integration servers to make sure +# it is possible to bootstrap the compiler. + +# To know the slave's architecture, this script looks at the OCAML_ARCH +# environment variable. For a given node NODe, this variable can be defined +# in Jenkins at the following address: +# https://ci.inria.fr/ocaml/computer/NODE/configure + +# Other environments variables that are honored: +# OCAML_CONFIGURE_OPTIONS additional options for configure +# OCAML_JOBS number of jobs to run in parallel (make -j) + +# Command-line arguments: +# -conf configure-option add configure-option to configure cmd line +# -patch1 file-name apply patch with -p1 +# -no-native do not build "opt" and "opt.opt" +# -jNN pass "-jNN" option to make for parallel builds + +error () { + echo "$1" >&2 + exit 3 +} + +arch_error() { + configure_url="https://ci.inria.fr/ocaml/computer/${NODE_NAME}/configure" + msg="Unknown architecture. Make sure the OCAML_ARCH environment" + msg="$msg variable has been defined." + msg="$msg\nSee ${configure_url}" + error "$msg" +} + +# Kill a task on Windows +# Errors are ignored +kill_task() +{ + task=$1 + taskkill /f /im ${task} /t || true +} + +quote1 () { + printf "'%s'" "`printf %s "$1" | sed -e "s/'/'\\\\\\\\''/g"`"; +} + +# Functions used to modify the source code + +change_exe_magic_number() { + old=`./runtime/ocamlrun -M` + new="$1" + echo Changing executable magic number from ${old} to ${new} + # Change magic number in runtime/caml/exec.h + sed -i 's/\x23define \+EXEC_MAGIC \+\x22'${old}\ +'\x22/#define EXEC_MAGIC "'${new}'"/' runtime/caml/exec.h + # Change magic number in utils/config.mlp + sed -i 's/let \+exec_magic_number \+= \+\x22'${old}\ +'\x22/let exec_magic_number = "'${new}'"/' utils/config.mlp +} + +remove_primitive() +{ + echo Removing the \'sinh\' primitive + patch -p1 < tools/ci/inria/remove-sinh-primitive.patch +} + +######################################################################### +# be verbose +set -x + +######################################################################### +# Save the current directory (on cygwin, /etc/profile changes it) +jenkinsdir="$(pwd)" +echo jenkinsdir=${jenkinsdir} + +######################################################################### +# If we are called from a Windows batch script, we must set up the +# Unix environment variables (e.g. PATH). + +case "${OCAML_ARCH}" in + bsd|macos|linux) ;; + cygwin|cygwin64|mingw|mingw64) + . /etc/profile + . "$HOME/.profile" + ;; + msvc) + . /etc/profile + . "$HOME/.profile" + . "$HOME/.msenv32" + ;; + msvc64) + . /etc/profile + . "$HOME/.profile" + . "$HOME/.msenv64" + ;; + *) arch_error;; +esac + +######################################################################### + +# be considerate towards other potential users of the test machine +case "${OCAML_ARCH}" in + bsd|macos|linux) renice 10 $$ ;; +esac + +# be verbose and stop on error +set -ex + +######################################################################### +# set up variables + +# default values +make=make +instdir="$HOME/ocaml-tmp-install" +confoptions="${OCAML_CONFIGURE_OPTIONS}" +make_native=true +cleanup=false +check_make_alldepend=false +dorebase=false +jobs='' +build='' +host='' + +case "${OCAML_ARCH}" in + bsd) make=gmake ;; + macos) ;; + linux) + check_make_alldepend=true + ;; + cygwin) + cleanup=true + check_make_alldepend=true + ;; + cygwin64) + cleanup=true + check_make_alldepend=true + dorebase=true + ;; + mingw) + build='--build=i686-pc-cygwin' + host='--host=i686-w64-mingw32' + instdir='C:/ocamlmgw' + cleanup=true + check_make_alldepend=true + ;; + mingw64) + build='--build=x86_64-unknown-cygwin' + host='--host=x86_64-w64-mingw32' + instdir='C:/ocamlmgw64' + cleanup=true + check_make_alldepend=true + ;; + msvc) + build='--build=i686-pc-cygwin' + host='--host=i686-pc-windows' + instdir='C:/ocamlms' + configure=nt + cleanup=true + ;; + msvc64) + build='--build=x86_64-unknown-cygwin' + host='--host=x86_64-pc-windows' + instdir='C:/ocamlms64' + configure=nt + cleanup=true + ;; + *) arch_error;; +esac + +# Make sure two builds won't use the same install directory +instdir="$instdir-$$" + +case "${OCAML_JOBS}" in + [1-9]|[1-9][0-9]) jobs="-j${OCAML_JOBS}" ;; +esac + +######################################################################### +# On Windows, cleanup processes that may remain from previous run + +if $cleanup; then + tasks="tee ocamlrun program ocamltest ocamltest.opt" + for task in ${tasks}; do kill_task ${task}.exe; done +fi + +######################################################################### +# Go to the right directory + +pwd +cd "$jenkinsdir" + +######################################################################### +# parse optional command-line arguments (has to be done after the "cd") + +while [ $# -gt 0 ]; do + case $1 in + -conf) confoptions="$confoptions `quote1 "$2"`"; shift;; + -patch1) patch -f -p1 <"$2"; shift;; + -no-native) make_native=false;; + -j[1-9]|-j[1-9][0-9]) jobs="$1";; + *) error "unknown option $1";; + esac + shift +done + +######################################################################### +# Do the work + +# Tell gcc to use only ASCII in its diagnostic outputs. +export LC_ALL=C + +$make -s distclean || : + +# `make distclean` does not clean the files from previous versions that +# are not produced by the current version, so use `git clean` in addition. +git clean -f -d -x + +# Also make a hard reset +git reset --hard HEAD + +if $flambda; then + confoptions="$confoptions -enable-flambda --enable-flambda-invariants" +fi +eval "./configure $build $host --prefix='$instdir' $confoptions" + +$make world + +change_exe_magic_number "CI-bootstrap" + +remove_primitive + +$make coreall +$make bootstrap diff --git a/tools/ci/inria/extra-checks b/tools/ci/inria/extra-checks new file mode 100755 index 00000000..64b851bb --- /dev/null +++ b/tools/ci/inria/extra-checks @@ -0,0 +1,233 @@ +#!/bin/sh +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, Xavier Leroy, projet Gallium, INRIA Paris * +#* * +#* Copyright 2018 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +# This script is run on Inria's continuous-integration servers to recompile +# from scratch, adding more run-time checks ("sanitizers") to the C code, +# and run the test suite. + +# In this context, it is necessary to skip a few tests whose behaviour +# is modified by the instrumentation: + +export OCAMLTEST_SKIP_TESTS="tests/afl-instrumentation/afltest.ml \ +tests/runtime-errors/stackoverflow.ml" + +# To know the slave's architecture, this script looks at the OCAML_ARCH +# environment variable. For a given node NODE, this variable can be defined +# in Jenkins at the following address: +# https://ci.inria.fr/ocaml/computer/NODE/configure + +# Other environment variables that are honored: +# OCAML_JOBS number of jobs to run in parallel (make -j) + +# Command-line arguments: +# -jNN pass "-jNN" option to make for parallel builds + +error () { + echo "$1" >&2 + exit 3 +} + +arch_error() { + configure_url="https://ci.inria.fr/ocaml/computer/${NODE_NAME}/configure" + msg="Unknown architecture. Make sure the OCAML_ARCH environment" + msg="$msg variable has been defined." + msg="$msg\nSee ${configure_url}" + error "$msg" +} + +# Change a variable in Makefile.config +# Usage: set_config_var + + +set_config_var() { + conffile=Makefile.config + mv ${conffile} ${conffile}.bak + (grep -v "^$1=" ${conffile}.bak; echo "$1=$2") > ${conffile} +} + +######################################################################### +# stop on error +set -e + +# be considerate towards other potential users of the test machine +case "${OCAML_ARCH}" in + bsd|macos|linux) renice 10 $$ ;; +esac + +# set up variables + +make=make +jobs='' + +case "${OCAML_ARCH}" in + bsd) make=gmake ;; + macos) ;; + linux) ;; + cygwin|cygwin64|mingw|mingw64|msvc|msvc64) + error "Don't run this test under Windows";; + *) arch_error;; +esac + +case "${OCAML_JOBS}" in + [1-9]|[1-9][0-9]) jobs="-j${OCAML_JOBS}" ;; +esac + +# parse optional command-line arguments + +while [ $# -gt 0 ]; do + case $1 in + -j[1-9]|-j[1-9][0-9]) jobs="$1";; + *) error "unknown option $1";; + esac + shift +done + +# Tell gcc to use only ASCII in its diagnostic outputs. +export LC_ALL=C + +# How to run the test suite +if test -n "$jobs" && test -x /usr/bin/parallel; then + export PARALLEL="$jobs $PARALLEL" + run_testsuite="$make -C testsuite parallel" +else + run_testsuite="$make -C testsuite all" +fi + +# A tool that make error backtrace nicer +# Need to pick the one that matches clang-6.0 and is named "llvm-symbolizer" +# (/usr/bin/llvm-symbolizer-6.0 doesn't work, that would be too easy) +export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer +export TSAN_SYMBOLIZER_PATH="$ASAN_SYMBOLIZER_PATH" + +######################################################################### + +echo "======== clang 6.0, address sanitizer, UB sanitizer ==========" + +$make -s distclean || : + +# `make distclean` does not clean the files from previous versions that +# are not produced by the current version, so use `git clean` in addition. +git clean -f -d -x + +# Use clang 6.0 +# We cannot give the sanitizer options as part of -cc because +# then various autoconfiguration tests fail. +# Instead, we'll fix OC_CFLAGS a posteriori. +./configure CC=clang-6.0 + +# These are the undefined behaviors we want to check +# Others occur on purpose e.g. signed arithmetic overflow +ubsan="\ +bool,\ +builtin,\ +bounds,\ +enum,\ +nonnull-attribute,\ +nullability,\ +object-size,\ +pointer-overflow,\ +returns-nonnull-attribute,\ +shift-exponent,\ +unreachable" + +# Select address sanitizer and UB sanitizer, with trap-on-error behavior +# Don't optimize too much to get better backtraces of errors +set_config_var OC_CFLAGS "-O1 \ +-fno-strict-aliasing -fwrapv -fno-omit-frame-pointer \ +-Wall -Werror \ +-fsanitize=address \ +-fsanitize-trap=$ubsan" + +# Build the system. We want to check for memory leaks, hence +# 1- force ocamlrun to free memory before exiting +# 2- add an exception for ocamlyacc, which doesn't free memory + +OCAMLRUNPARAM="c=1" \ +LSAN_OPTIONS="suppressions=$(pwd)/tools/ci/inria/lsan-suppr.txt" \ +make $jobs world.opt + +# Run the testsuite. +# The suppressed leak detections related to ocamlyacc mess up the output +# of the tests and are reported as failures by ocamltest. +# Hence, deactivate leak detection entirely. + +ASAN_OPTIONS="detect_leaks=0" $run_testsuite + +######################################################################### + +echo "======== clang 6.0, thread sanitizer ==========" + +$make -s distclean || : + +./configure CC=clang-6.0 + +# Select thread sanitizer +# Don't optimize too much to get better backtraces of errors +set_config_var OC_CFLAGS "-O1 \ +-fno-strict-aliasing -fwrapv -fno-omit-frame-pointer \ +-Wall -Werror \ +-fsanitize=thread \ +-fsanitize-blacklist=$(pwd)/tools/ci/inria/tsan-suppr.txt" + +# Build the system +make $jobs world.opt + +# Run the testsuite. +# ThreadSanitizer complains about fork() in threaded programs, +# we ask it to just continue in this case. +TSAN_OPTIONS="die_after_fork=0" $run_testsuite + +######################################################################### + +# This is a failed attempt at using the memory sanitizer +# (to detect reads from uninitialized memory). +# Some alarms are reported that look like false positive +# and are impossible to debug. + +# echo "======== clang 6.0, memory sanitizer ==========" + +# $make -s distclean || : + +# # Use clang 6.0 +# # We cannot give the sanitizer options as part of -cc because +# # then various autoconfiguration tests fail. +# # Instead, we'll fix OC_CFLAGS a posteriori. +# # Memory sanitizer doesn't like the static data generated by ocamlopt, +# # hence build bytecode only +# ./configure CC=clang-6.0 --disable-native-compiler + +# # Select memory sanitizer +# # Don't optimize at all to get better backtraces of errors +# set_config_var OC_CFLAGS "-O0 -g \ +# -fno-strict-aliasing -fwrapv -fno-omit-frame-pointer \ +# -Wall -Werror \ +# -fsanitize=memory" + +# # A tool that make error backtrace nicer +# # Need to pick the one that matches clang-6.0 +# export MSAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer + +# # Build the system (bytecode only) and test +# make $jobs world +# $run_testsuite + +######################################################################### + +# Ensure that the repo still passes the check-typo script +if [ ! -x tools/check-typo ] ; then + error "tools/check-typo does not appear to be executable?" +fi +tools/check-typo diff --git a/tools/ci/inria/lsan-suppr.txt b/tools/ci/inria/lsan-suppr.txt new file mode 100644 index 00000000..160e7fc6 --- /dev/null +++ b/tools/ci/inria/lsan-suppr.txt @@ -0,0 +1,2 @@ +# ocamlyacc doesn't clean memory on exit +leak:ocamlyacc diff --git a/tools/ci/inria/main b/tools/ci/inria/main index 11e41fee..e427196f 100755 --- a/tools/ci/inria/main +++ b/tools/ci/inria/main @@ -18,11 +18,11 @@ # from scratch and run the test suite. # To know the slave's architecture, this script looks at the OCAML_ARCH -# environment variable. For a given node NODe, this variable can be defined +# environment variable. For a given node NODE, this variable can be defined # in Jenkins at the following address: # https://ci.inria.fr/ocaml/computer/NODE/configure -# Other environments variables that are honored: +# Other environment variables that are honored: # OCAML_CONFIGURE_OPTIONS additional options for configure # OCAML_JOBS number of jobs to run in parallel (make -j) @@ -39,7 +39,7 @@ error () { arch_error() { configure_url="https://ci.inria.fr/ocaml/computer/${NODE_NAME}/configure" - msg="Unknown architecture. Make sure the OCAML_ARCH environemnt" + msg="Unknown architecture. Make sure the OCAML_ARCH environment" msg="$msg variable has been defined." msg="$msg\nSee ${configure_url}" error "$msg" @@ -72,7 +72,7 @@ echo jenkinsdir=${jenkinsdir} case "${OCAML_ARCH}" in bsd|macos|linux) ;; - cygwin|mingw|mingw64) + cygwin|cygwin64|mingw|mingw64) . /etc/profile . "$HOME/.profile" ;; @@ -99,13 +99,30 @@ esac # be verbose and stop on error set -ex +# On PowerPC, the OCAML_CONFIGURE_OPTIONS is used to specify which C +# compiler to use. However with the introduction of autoconf the way +# to do that has changed. Once all the branches on which we do CI will use +# autoconf, the variable shall be updated on the host. But until then, +# we leave it with its legacy value and override it here. +CCOMP= +case $NODE_NAME in + ocaml-ppc-32) + CCOMP="CC='gcc -m32'" + OCAML_CONFIGURE_OPTIONS=;; + ocaml-ppc-64) + CCOMP="CC='gcc -m64'" + OCAML_CONFIGURE_OPTIONS=;; +esac + ######################################################################### # set up variables # default values +build='' +host='' +conffile=Makefile.config make=make instdir="$HOME/ocaml-tmp-install" -configure=unix confoptions="${OCAML_CONFIGURE_OPTIONS}" make_native=true cleanup=false @@ -117,34 +134,42 @@ case "${OCAML_ARCH}" in bsd) make=gmake ;; macos) ;; linux) - confoptions="${confoptions} -with-instrumented-runtime" check_make_alldepend=true ;; cygwin) cleanup=true check_make_alldepend=true - dorebase=true + ;; + cygwin64) + cleanup=true + check_make_alldepend=true + dorebase=false + confoptions="$confoptions --disable-shared " ;; mingw) + build='--build=i686-pc-cygwin' + host='--host=i686-w64-mingw32' instdir='C:/ocamlmgw' - configure=nt cleanup=true check_make_alldepend=true ;; mingw64) + build='--build=x86_64-unknown-cygwin' + host='--host=x86_64-w64-mingw32' instdir='C:/ocamlmgw64' - configure=nt cleanup=true check_make_alldepend=true ;; msvc) + build='--build=i686-pc-cygwin' + host='--host=i686-pc-windows' instdir='C:/ocamlms' - configure=nt cleanup=true ;; msvc64) + build='--build=x86_64-unknown-cygwin' + host='--host=x86_64-pc-windows' instdir='C:/ocamlms64' - configure=nt cleanup=true ;; *) arch_error;; @@ -197,26 +222,11 @@ $make -s distclean || : # are not produced by the current version, so use `git clean` in addition. git clean -f -d -x -case $configure in - unix) - confoptions="$confoptions -with-debug-runtime" - if $flambda; then - confoptions="$confoptions -flambda -with-flambda-invariants" - fi - eval "./configure -prefix '$instdir' $confoptions" - ;; - nt) - cp config/m-nt.h byterun/caml/m.h - cp config/s-nt.h byterun/caml/s.h - cp config/Makefile.${OCAML_ARCH} config/Makefile - sed -i "s%PREFIX=\(.\+\)%PREFIX=${instdir}%" config/Makefile - sed -i 's%RUNTIMED=.\+%RUNTIMED=true%' config/Makefile - if $flambda; then - sed -i 's%FLAMBDA=.\+%FLAMBDA=true%' config/Makefile - fi - ;; - *) error "internal error";; -esac +if $flambda; then + confoptions="$confoptions --enable-flambda --enable-flambda-invariants" +fi + +eval ./configure "$CCOMP" $build $host --prefix='$instdir' $confoptions if $make_native; then $make $jobs world.opt diff --git a/tools/ci/inria/other-configs b/tools/ci/inria/other-configs index c9ef0e98..accd724f 100755 --- a/tools/ci/inria/other-configs +++ b/tools/ci/inria/other-configs @@ -22,8 +22,8 @@ set -e mainjob=./tools/ci/inria/main main="${mainjob} -j8" -${main} -conf -no-native-compiler -no-native -${main} -conf -no-naked-pointers -${main} -conf -no-flat-float-array -${main} -conf -flambda -conf -no-naked-pointers +${main} -conf --disable-native-compiler -no-native +${main} -conf --disable-naked-pointers +${main} -conf --disable-flat-float-array +${main} -conf --enable-flambda -conf --disable-naked-pointers OCAMLRUNPARAM="c=1" ${main} diff --git a/tools/ci/inria/remove-sinh-primitive.patch b/tools/ci/inria/remove-sinh-primitive.patch new file mode 100644 index 00000000..c6a21157 --- /dev/null +++ b/tools/ci/inria/remove-sinh-primitive.patch @@ -0,0 +1,103 @@ +The patch below removes the 'sinh' primitive from the OCaml runtime +and standard library. + +It is used on Inria's CI to make sure the bootstrap procedure works. + +diff --git a/otherlibs/threads/stdlib.ml b/otherlibs/threads/stdlib.ml +index 27cb01e54..eea32ee94 100644 +--- a/otherlibs/threads/stdlib.ml ++++ b/otherlibs/threads/stdlib.ml +@@ -152,8 +152,6 @@ external log10 : float -> float = "caml_log10_float" "log10" + external log1p : float -> float = "caml_log1p_float" "caml_log1p" + [@@unboxed] [@@noalloc] + external sin : float -> float = "caml_sin_float" "sin" [@@unboxed] [@@noalloc] +-external sinh : float -> float = "caml_sinh_float" "sinh" +- [@@unboxed] [@@noalloc] + external sqrt : float -> float = "caml_sqrt_float" "sqrt" + [@@unboxed] [@@noalloc] + external tan : float -> float = "caml_tan_float" "tan" [@@unboxed] [@@noalloc] +diff --git a/runtime/floats.c b/runtime/floats.c +index b93f6a409..6edbed9c6 100644 +--- a/runtime/floats.c ++++ b/runtime/floats.c +@@ -536,11 +536,6 @@ CAMLprim value caml_sin_float(value f) + return caml_copy_double(sin(Double_val(f))); + } + +-CAMLprim value caml_sinh_float(value f) +-{ +- return caml_copy_double(sinh(Double_val(f))); +-} +- + CAMLprim value caml_cos_float(value f) + { + return caml_copy_double(cos(Double_val(f))); +diff --git a/stdlib/float.ml b/stdlib/float.ml +index 8d9c5cca6..3b3ca61bc 100644 +--- a/stdlib/float.ml ++++ b/stdlib/float.ml +@@ -69,8 +69,6 @@ external hypot : float -> float -> float + = "caml_hypot_float" "caml_hypot" [@@unboxed] [@@noalloc] + external cosh : float -> float = "caml_cosh_float" "cosh" + [@@unboxed] [@@noalloc] +-external sinh : float -> float = "caml_sinh_float" "sinh" +- [@@unboxed] [@@noalloc] + external tanh : float -> float = "caml_tanh_float" "tanh" + [@@unboxed] [@@noalloc] + external ceil : float -> float = "caml_ceil_float" "ceil" +diff --git a/stdlib/float.mli b/stdlib/float.mli +index 2cdd31608..904f4af0e 100644 +--- a/stdlib/float.mli ++++ b/stdlib/float.mli +@@ -196,10 +196,6 @@ external cosh : float -> float = "caml_cosh_float" "cosh" + [@@unboxed] [@@noalloc] + (** Hyperbolic cosine. Argument is in radians. *) + +-external sinh : float -> float = "caml_sinh_float" "sinh" +-[@@unboxed] [@@noalloc] +-(** Hyperbolic sine. Argument is in radians. *) +- + external tanh : float -> float = "caml_tanh_float" "tanh" + [@@unboxed] [@@noalloc] + (** Hyperbolic tangent. Argument is in radians. *) +diff --git a/stdlib/pervasives.ml b/stdlib/pervasives.ml +index 945512716..55bc9e921 100644 +--- a/stdlib/pervasives.ml ++++ b/stdlib/pervasives.ml +@@ -97,8 +97,6 @@ external hypot : float -> float -> float = "caml_hypot_float" "caml_hypot" + [@@unboxed] [@@noalloc] + external cosh : float -> float = "caml_cosh_float" "cosh" + [@@unboxed] [@@noalloc] +-external sinh : float -> float = "caml_sinh_float" "sinh" +- [@@unboxed] [@@noalloc] + external tanh : float -> float = "caml_tanh_float" "tanh" + [@@unboxed] [@@noalloc] + external ceil : float -> float = "caml_ceil_float" "ceil" +diff --git a/stdlib/stdlib.ml b/stdlib/stdlib.ml +index 425728f64..4057dbc90 100644 +--- a/stdlib/stdlib.ml ++++ b/stdlib/stdlib.ml +@@ -148,8 +148,6 @@ external log10 : float -> float = "caml_log10_float" "log10" + external log1p : float -> float = "caml_log1p_float" "caml_log1p" + [@@unboxed] [@@noalloc] + external sin : float -> float = "caml_sin_float" "sin" [@@unboxed] [@@noalloc] +-external sinh : float -> float = "caml_sinh_float" "sinh" +- [@@unboxed] [@@noalloc] + external sqrt : float -> float = "caml_sqrt_float" "sqrt" + [@@unboxed] [@@noalloc] + external tan : float -> float = "caml_tan_float" "tan" [@@unboxed] [@@noalloc] +diff --git a/stdlib/stdlib.mli b/stdlib/stdlib.mli +index d451bba9c..990a41467 100644 +--- a/stdlib/stdlib.mli ++++ b/stdlib/stdlib.mli +@@ -461,10 +461,6 @@ external cosh : float -> float = "caml_cosh_float" "cosh" + [@@unboxed] [@@noalloc] + (** Hyperbolic cosine. Argument is in radians. *) + +-external sinh : float -> float = "caml_sinh_float" "sinh" +- [@@unboxed] [@@noalloc] +-(** Hyperbolic sine. Argument is in radians. *) +- + external tanh : float -> float = "caml_tanh_float" "tanh" + [@@unboxed] [@@noalloc] + (** Hyperbolic tangent. Argument is in radians. *) diff --git a/tools/ci/inria/tsan-suppr.txt b/tools/ci/inria/tsan-suppr.txt new file mode 100644 index 00000000..70521db6 --- /dev/null +++ b/tools/ci/inria/tsan-suppr.txt @@ -0,0 +1,6 @@ +# The treatment of pending signals involves unsynchronized accesses +fun:caml_record_signal +fun:caml_process_pending_signals +fun:caml_leave_blocking_section +# st_masterlock_waiters polls m->waiters without locking +fun:st_masterlock_waiters diff --git a/tools/ci/travis/travis-ci.sh b/tools/ci/travis/travis-ci.sh index c4dbab84..da7259c2 100755 --- a/tools/ci/travis/travis-ci.sh +++ b/tools/ci/travis/travis-ci.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash #************************************************************************** #* * #* OCaml * @@ -14,10 +14,6 @@ #* * #************************************************************************** -PREFIX=~/local - -MAKE=make SHELL=dash - # TRAVIS_COMMIT_RANGE has the form ... # TRAVIS_CUR_HEAD is # TRAVIS_PR_HEAD is @@ -33,11 +29,42 @@ MAKE=make SHELL=dash # TRAVIS_MERGE_BASE # echo TRAVIS_COMMIT_RANGE=$TRAVIS_COMMIT_RANGE +echo TRAVIS_COMMIT=$TRAVIS_COMMIT +if [[ $TRAVIS_EVENT_TYPE = "pull_request" ]] ; then + FETCH_HEAD=$(git rev-parse FETCH_HEAD) + echo FETCH_HEAD=$FETCH_HEAD +else + FETCH_HEAD=$TRAVIS_COMMIT +fi + +if [[ $TRAVIS_COMMIT != $(git rev-parse FETCH_HEAD) ]] ; then + echo "WARNING! Travis TRAVIS_COMMIT and FETCH_HEAD do not agree!" + if git cat-file -e $TRAVIS_COMMIT 2> /dev/null ; then + echo "TRAVIS_COMMIT exists, so going with it" + else + echo "TRAVIS_COMMIT does not exist; setting to FETCH_HEAD" + TRAVIS_COMMIT=$FETCH_HEAD + fi +fi + +set -x + +PREFIX=~/local + +MAKE=make SHELL=dash + TRAVIS_CUR_HEAD=${TRAVIS_COMMIT_RANGE%%...*} TRAVIS_PR_HEAD=${TRAVIS_COMMIT_RANGE##*...} case $TRAVIS_EVENT_TYPE in # If this is not a pull request then TRAVIS_COMMIT_RANGE may be empty. pull_request) + DEEPEN=50 + while ! git merge-base $TRAVIS_CUR_HEAD $TRAVIS_PR_HEAD > /dev/null 2>&1 + do + echo Deepening $TRAVIS_BRANCH by $DEEPEN commits + git fetch origin --deepen=$DEEPEN $TRAVIS_BRANCH + ((DEEPEN*=2)) + done TRAVIS_MERGE_BASE=$(git merge-base $TRAVIS_CUR_HEAD $TRAVIS_PR_HEAD);; esac @@ -53,15 +80,19 @@ critical errors that must be understood and fixed before your pull request can be merged. ------------------------------------------------------------------------ EOF + + configure_flags="\ + --prefix=$PREFIX \ + --enable-flambda-invariants \ + $CONFIG_ARG" case $XARCH in x64) - ./configure --prefix $PREFIX -with-debug-runtime \ - -with-instrumented-runtime -with-flambda-invariants $CONFIG_ARG + ./configure $configure_flags ;; i386) - ./configure --prefix $PREFIX -with-debug-runtime \ - -with-instrumented-runtime -with-flambda-invariants $CONFIG_ARG \ - -host i686-pc-linux-gnu + ./configure --build=x86_64-pc-linux-gnu --host=i386-pc-linux-gnu \ + AS="as" ASPP="gcc -c" \ + $configure_flags ;; *) echo unknown arch @@ -79,6 +110,7 @@ EOF $MAKE USE_RUNTIME="d" OCAMLTESTDIR=$(pwd)/_ocamltestd TESTLOG=_logd all cd .. $MAKE install + echo Check the code examples in the manual $MAKE manual-pregen # check_all_arches checks tries to compile all backends in place, # we would need to redo (small parts of) world.opt afterwards to @@ -120,6 +152,18 @@ CheckNoChangesMessage () { fi } +CheckManual () { + cat< /dev/null && exit 1 || echo pass } +# Test to see if any part of the directory name has been marked prune +not_pruned () { + DIR=$(dirname "$1") + if [ "$DIR" = "." ] ; then + return 0 + else + case ",$(git check-attr typo.prune "$DIR" | sed -e 's/.*: //')," in + ,set,) + return 1 + ;; + *) + + not_pruned $DIR + return $? + esac + fi +} + +CheckTypoTree () { + export OCAML_CT_HEAD=$1 + export OCAML_CT_LS_FILES="git diff-tree --no-commit-id --name-only -r $2 --" + export OCAML_CT_CAT="git cat-file --textconv" + export OCAML_CT_PREFIX="$1:" + GIT_INDEX_FILE=tmp-index git read-tree --reset -i $1 + git diff-tree --diff-filter=d --no-commit-id --name-only -r $2 \ + | (while IFS= read -r path + do + if not_pruned $path ; then + echo "Checking $1: $path" + if ! tools/check-typo ./$path ; then + touch check-typo-failed + fi + else + echo "NOT checking $1: $path (typo.prune)" + fi + done) + rm -f tmp-index +} + +CHECK_ALL_COMMITS=0 + +CheckTypo () { + export OCAML_CT_GIT_INDEX="tmp-index" + export OCAML_CT_CA_FLAG="--cached" + # Work around an apparent bug in Ubuntu 12.4.5 + # See https://bugs.launchpad.net/ubuntu/+source/gawk/+bug/1647879 + export OCAML_CT_AWK="awk --re-interval" + rm -f check-typo-failed + if test -z "$TRAVIS_COMMIT_RANGE" + then CheckTypoTree $TRAVIS_COMMIT $TRAVIS_COMMIT + else + if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ] + then TRAVIS_COMMIT_RANGE=$TRAVIS_MERGE_BASE..$TRAVIS_PULL_REQUEST_SHA + fi + if [ $CHECK_ALL_COMMITS -eq 1 ] + then + for commit in $(git rev-list $TRAVIS_COMMIT_RANGE --reverse) + do + CheckTypoTree $commit $commit + done + else + if [ -z "$TRAVIS_PULL_REQUEST_SHA" ] + then CheckTypoTree $TRAVIS_COMMIT $TRAVIS_COMMIT + else CheckTypoTree $TRAVIS_COMMIT $TRAVIS_COMMIT_RANGE + fi + fi + fi + echo complete + if [ -e check-typo-failed ] + then exit 1 + fi +} + + case $CI_KIND in build) BuildAndTest;; changes) case $TRAVIS_EVENT_TYPE in pull_request) CheckChangesModified;; esac;; +manual) + CheckManual;; tests) case $TRAVIS_EVENT_TYPE in pull_request) CheckTestsuiteModified;; esac;; +check-typo) + set +x + CheckTypo;; *) echo unknown CI kind exit 1 ;; diff --git a/tools/cmt2annot.ml b/tools/cmt2annot.ml index ef044beb..bfbac7c4 100644 --- a/tools/cmt2annot.ml +++ b/tools/cmt2annot.ml @@ -99,13 +99,12 @@ let rec iterator ~scope rebuild_env = bind_bindings exp.exp_loc bindings | Texp_let (Nonrecursive, bindings, body) -> bind_bindings body.exp_loc bindings - | Texp_match (_, f1, f2, _) -> - bind_cases f1; - bind_cases f2 + | Texp_match (_, f1, _) -> + bind_cases f1 | Texp_function { cases = f; } | Texp_try (_, f) -> bind_cases f - | Texp_letmodule (_, modname, _, body ) -> + | Texp_letmodule (_, modname, _, _, body ) -> Stypes.record (Stypes.An_ident (modname.loc,modname.txt,Annot.Idef body.exp_loc)) | _ -> () @@ -198,7 +197,7 @@ let record_cmt_info cmt = let gen_annot ?(save_cmt_info=false) target_filename filename cmt = let open Cmt_format in Envaux.reset_cache (); - Config.load_path := cmt.cmt_loadpath @ !Config.load_path; + List.iter Load_path.add_dir (List.rev cmt.cmt_loadpath); let target_filename = match target_filename with | None -> Some (filename ^ ".annot") diff --git a/tools/dumpobj.ml b/tools/dumpobj.ml index 5d2e43aa..0b8b1653 100644 --- a/tools/dumpobj.ml +++ b/tools/dumpobj.ml @@ -529,8 +529,9 @@ let dump_exe ic = !globals.(i) <- Constant (init_data.(i)) done; ignore(Bytesections.seek_section ic "SYMB"); - let (_, sym_table) = (input_value ic : int * (Ident.t, int) Tbl.t) in - Tbl.iter (fun id pos -> !globals.(pos) <- Global id) sym_table; + let sym_table = (input_value ic : Symtable.global_map) in + Symtable.iter_global_map + (fun id pos -> !globals.(pos) <- Global id) sym_table; begin try ignore (Bytesections.seek_section ic "DBUG"); let num_eventlists = input_binary_int ic in diff --git a/tools/dune b/tools/dune new file mode 100644 index 00000000..91a71fdc --- /dev/null +++ b/tools/dune @@ -0,0 +1,25 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +(executables + (names make_opcodes cvt_emit) + (modules make_opcodes cvt_emit)) + +(ocamllex + (modules make_opcodes) + (mode fallback)) + +(ocamllex + (modules cvt_emit) + (mode fallback)) diff --git a/tools/eqparsetree.ml b/tools/eqparsetree.ml index ae204bfb..9630fcd8 100644 --- a/tools/eqparsetree.ml +++ b/tools/eqparsetree.ml @@ -766,8 +766,8 @@ and eq_expression : (expression * expression) -> 'result = { pexp_desc = b0; pexp_loc = b1 }) -> (eq_expression_desc (a0, b0)) && (Location.eq_t (a1, b1)) -let rec eq_directive_argument : - (directive_argument * directive_argument) -> 'result = +let rec eq_directive_argument_desc : + (directive_argument_desc * directive_argument_desc) -> 'result = function | (Pdir_none, Pdir_none) -> true | (Pdir_string a0, Pdir_string b0) -> eq_string (a0, b0) @@ -775,10 +775,18 @@ let rec eq_directive_argument : | (Pdir_ident a0, Pdir_ident b0) -> Longident.eq_t (a0, b0) | (Pdir_bool a0, Pdir_bool b0) -> eq_bool (a0, b0) | (_, _) -> false +and eq_directive_argument : + (directive_argument * directive_argument) -> 'result = + fun + ({pdira_desc = a0; pdira_loc = a1}, + {pdira_desc = b0; pdira_loc = b1}) + -> (eq_directive_argument_desc (a0, b0)) && (Location.eq_t (a1, b1)) + and eq_toplevel_phrase : (toplevel_phrase * toplevel_phrase) -> 'result = function | (Ptop_def a0, Ptop_def b0) -> eq_structure (a0, b0) - | (Ptop_dir (a0, a1), Ptop_dir (b0, b1)) -> - (eq_string (a0, b0)) && (eq_directive_argument (a1, b1)) + | (Ptop_dir a0, Ptop_dir a1) -> + Asttypes.eq_loc eq_string (a0.pdir_name, b0.pdir_name) && + (eq_directive_argument (a1, b1)) | (_, _) -> false diff --git a/tools/lintapidiff.ml b/tools/lintapidiff.ml index 9422869d..47fe1cee 100644 --- a/tools/lintapidiff.ml +++ b/tools/lintapidiff.ml @@ -38,7 +38,7 @@ let ignore_changes_for = [ "value Unix.map_file_impl"; ] -module IdMap = Map.Make(String) +module IdMap = Misc.StringMap module Version : sig type t @@ -174,7 +174,7 @@ module Ast = struct let id = orig |> Filename.chop_extension |> Filename.basename |> String.capitalize_ascii |> Ident.create in - let ast = Pparse.file ~tool_name:"lintapidiff" Format.err_formatter input + let ast = Pparse.file ~tool_name:"lintapidiff" input Parse.interface Pparse.Signature in Location.input_name := orig; add_items ~f (Path.Pident id) (init,IdMap.empty) ast @@ -248,7 +248,8 @@ module Diff = struct let first_seen = Version.of_string_exn rev in let empty = {last_not_seen=None;first_seen;deprecated=false} in let f = Ast.parse_file ~orig:path ~init:empty ~f:(fun _ _ attrs -> - { last_not_seen=None;first_seen; deprecated=Doc.is_deprecated attrs }) in + { last_not_seen=None;first_seen; deprecated=Doc.is_deprecated attrs }) + in let map = match Git.with_show ~f rev path with | Ok r -> r | Error `Not_found -> IdMap.empty diff --git a/tools/markdown-add-pr-links.sh b/tools/markdown-add-pr-links.sh new file mode 100644 index 00000000..3b388006 --- /dev/null +++ b/tools/markdown-add-pr-links.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +#************************************************************************** +#* * +#* OCaml * +#* * +#* Gabriel Scherer, projet Parsifal, INRIA Saclay * +#* * +#* Copyright 2018 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +# This script performs a series of transformation on standard input to +# turn ASCII references into Markdown-format links: +# - GPR#NNNN links to Github +# - MPR#NNNN and PR#NNNN link to Mantis +# - (Changes#VERSION) link to the Changes file + +# It was only tested with GNU sed. Sorry! + +GITHUB=https://github.com/ocaml/ocaml +MANTIS=https://caml.inria.fr/mantis + +cat \ +| sed "s,GPR#\\([0-9]*\\),[GPR~#~\\1]($GITHUB/pull/\\1),g"\ +| sed "s,MPR#\\([0-9]*\\),[PR~#~\\1]($MANTIS/view.php?id=\\1),g"\ +| sed "s,PR#\\([0-9]*\\),[PR~#~\\1]($MANTIS/view.php?id=\\1),g"\ +| sed "s,(Changes#\\(.*\\)),[Changes file for \\1]($GITHUB/blob/\\1/Changes),g"\ +| sed "s,PR~#~,PR#,g" \ diff --git a/tools/msvs-promote-path b/tools/msvs-promote-path index 668fc55d..b4f4f9d7 100755 --- a/tools/msvs-promote-path +++ b/tools/msvs-promote-path @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash #************************************************************************** #* * #* OCaml * diff --git a/tools/objinfo.ml b/tools/objinfo.ml index 0e780991..adb54538 100644 --- a/tools/objinfo.ml +++ b/tools/objinfo.ml @@ -127,9 +127,9 @@ let print_general_infos name crc defines cmi cmx = let print_global_table table = printf "Globals defined:\n"; - Tbl.iter + Symtable.iter_global_map (fun id _ -> print_line (Ident.name id)) - table.num_tbl + table open Cmx_format @@ -209,7 +209,7 @@ let p_list title print = function let dump_byte ic = Bytesections.read_toc ic; let toc = Bytesections.toc () in - let toc = List.sort Pervasives.compare toc in + let toc = List.sort Stdlib.compare toc in List.iter (fun (section, _) -> try @@ -242,24 +242,24 @@ let dump_byte ic = toc let read_dyn_header filename ic = - let tempfile = Filename.temp_file "objinfo" ".out" in let helper = Filename.concat Config.standard_library "objinfo_helper" in + let tempfile = Filename.temp_file "objinfo" ".out" in try try_finally + ~always:(fun () -> remove_file tempfile) (fun () -> - let rc = Sys.command (sprintf "%s %s > %s" - (Filename.quote helper) - (Filename.quote filename) - tempfile) in - if rc <> 0 then failwith "cannot read"; - let tc = Scanf.Scanning.from_file tempfile in - try_finally - (fun () -> - let ofs = Scanf.bscanf tc "%Ld" (fun x -> x) in - LargeFile.seek_in ic ofs; - Some(input_value ic : dynheader)) - (fun () -> Scanf.Scanning.close_in tc)) - (fun () -> remove_file tempfile) + let rc = Sys.command (sprintf "%s %s > %s" + (Filename.quote helper) + (Filename.quote filename) + tempfile) in + if rc <> 0 then failwith "cannot read"; + let tc = Scanf.Scanning.from_file tempfile in + try_finally + ~always:(fun () -> Scanf.Scanning.close_in tc) + (fun () -> + let ofs = Scanf.bscanf tc "%Ld" (fun x -> x) in + LargeFile.seek_in ic ofs; + Some(input_value ic : dynheader))) with Failure _ | Sys_error _ -> None let dump_obj filename = @@ -327,8 +327,10 @@ let dump_obj filename = end let arg_list = [ - "-no-approx", Arg.Set no_approx, " Do not print module approximation information"; - "-no-code", Arg.Set no_code, " Do not print code from exported flambda functions"; + "-no-approx", Arg.Set no_approx, + " Do not print module approximation information"; + "-no-code", Arg.Set no_code, + " Do not print code from exported flambda functions"; "-null-crc", Arg.Set no_crc, " Print a null CRC for imported interfaces"; "-args", Arg.Expand Arg.read_arg, " Read additional newline separated command line arguments \n\ diff --git a/tools/ocaml-instr-graph b/tools/ocaml-instr-graph index 5792da11..edf2d363 100755 --- a/tools/ocaml-instr-graph +++ b/tools/ocaml-instr-graph @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash #************************************************************************** #* * diff --git a/tools/ocaml-objcopy-macosx b/tools/ocaml-objcopy-macosx index 3b8dcc2a..2a51773f 100755 --- a/tools/ocaml-objcopy-macosx +++ b/tools/ocaml-objcopy-macosx @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash #************************************************************************** #* * diff --git a/tools/ocamlcp.ml b/tools/ocamlcp.ml index eed29359..3c2edfcc 100644 --- a/tools/ocamlcp.ml +++ b/tools/ocamlcp.ml @@ -23,6 +23,9 @@ let option opt () = compargs := opt :: !compargs let option_with_arg opt arg = compargs := (Filename.quote arg) :: opt :: !compargs ;; +let option_with_int opt arg = + compargs := (Int.to_string arg) :: opt :: !compargs +;; let make_archive = ref false;; let with_impl = ref false;; @@ -45,6 +48,7 @@ let incompatible o = module Options = Main_args.Make_bytecomp_options (struct let _a () = make_archive := true; option "-a" () let _absname = option "-absname" + let _alert = option_with_arg "-alert" let _annot = option "-annot" let _binannot = option "-bin-annot" let _c = option "-c" @@ -52,6 +56,7 @@ module Options = Main_args.Make_bytecomp_options (struct let _cclib s = option_with_arg "-cclib" s let _ccopt s = option_with_arg "-ccopt" s let _config = option "-config" + let _config_var s = option_with_arg "-config-var" s let _compat_32 = option "-compat-32" let _custom = option "-custom" let _dllib = option_with_arg "-dllib" @@ -59,6 +64,7 @@ module Options = Main_args.Make_bytecomp_options (struct let _dtypes = option "-dtypes" let _for_pack = option_with_arg "-for-pack" let _g = option "-g" + let _stop_after = option_with_arg "-stop-after" let _i = option "-i" let _I s = option_with_arg "-I" s let _impl s = with_impl := true; option_with_arg "-impl" s @@ -116,8 +122,11 @@ module Options = Main_args.Make_bytecomp_options (struct let _warn_error = option_with_arg "-warn-error" let _warn_help = option "-warn-help" let _color s = option_with_arg "-color" s + let _error_style s = option_with_arg "-error-style" s let _where = option "-where" let _nopervasives = option "-nopervasives" + let _match_context_rows n = option_with_int "-match-context-rows" n + let _dump_into_file = option "-dump-into-file" let _dno_unique_ids = option "-dno-unique-ids" let _dunique_ids = option "-dunique-ids" let _dsource = option "-dsource" @@ -127,6 +136,7 @@ module Options = Main_args.Make_bytecomp_options (struct let _dlambda = option "-dlambda" let _dflambda = option "-dflambda" let _dinstr = option "-dinstr" + let _dcamlprimc = option "-dcamlprimc" let _dtimings = option "-dtimings" let _dprofile = option "-dprofile" let _args = Arg.read_arg diff --git a/tools/ocamlmklib.ml b/tools/ocamlmklib.ml index 3d7fdd6d..b5c0aee5 100644 --- a/tools/ocamlmklib.ml +++ b/tools/ocamlmklib.ml @@ -16,6 +16,21 @@ open Printf open Ocamlmklibconfig +let syslib x = + if Config.ccomp_type = "msvc" then x ^ ".lib" else "-l" ^ x + +let mklib out files opts = + if Config.ccomp_type = "msvc" + then let machine = + if Config.architecture="amd64" + then "-machine:AMD64 " + else "" + in + Printf.sprintf "link -lib -nologo %s-out:%s %s %s" + machine out opts files + else Printf.sprintf "%s rcs %s %s %s && %s %s" + Config.ar out opts files Config.ranlib out + (* PR#4783: under Windows, don't use absolute paths because we do not know where the binary distribution will be installed. *) let compiler_path name = @@ -64,14 +79,25 @@ let print_version_num () = ;; let parse_arguments argv = - let i = ref 1 in - let next_arg () = - if !i + 1 >= Array.length argv - then raise (Bad_argument("Option " ^ argv.(!i) ^ " expects one argument")); - incr i; argv.(!i) in - while !i < Array.length argv do - let s = argv.(!i) in - if ends_with s ".cmo" || ends_with s ".cma" then + let args = Stack.create () in + let push_args ~first arr = + for i = Array.length arr - 1 downto first do + Stack.push arr.(i) args + done + in + let next_arg s = + if Stack.is_empty args + then raise (Bad_argument("Option " ^ s ^ " expects one argument")); + Stack.pop args + in + push_args ~first:1 argv; + while not (Stack.is_empty args) do + let s = Stack.pop args in + if s = "-args" then + push_args ~first:0 (Arg.read_arg (next_arg s)) + else if s = "-args0" then + push_args ~first:0 (Arg.read_arg0 (next_arg s)) + else if ends_with s ".cmo" || ends_with s ".cma" then bytecode_objs := s :: !bytecode_objs else if ends_with s ".cmx" || ends_with s ".cmxa" then native_objs := s :: !native_objs @@ -83,13 +109,13 @@ let parse_arguments argv = then c_objs := s :: !c_objs else if s = "-cclib" then - caml_libs := next_arg () :: "-cclib" :: !caml_libs + caml_libs := next_arg s :: "-cclib" :: !caml_libs else if s = "-ccopt" then - caml_opts := next_arg () :: "-ccopt" :: !caml_opts + caml_opts := next_arg s :: "-ccopt" :: !caml_opts else if s = "-custom" then dynlink := false else if s = "-I" then - caml_opts := next_arg () :: "-I" :: !caml_opts + caml_opts := next_arg s :: "-I" :: !caml_opts else if s = "-failsafe" then failsafe := true else if s = "-g" then @@ -97,7 +123,7 @@ let parse_arguments argv = else if s = "-h" || s = "-help" || s = "--help" then raise (Bad_argument "") else if s = "-ldopt" then - ld_opts := next_arg () :: !ld_opts + ld_opts := next_arg s :: !ld_opts else if s = "-linkall" then caml_opts := s :: !caml_opts else if starts_with s "-l" then @@ -113,23 +139,23 @@ let parse_arguments argv = let l = chop_prefix s "-L" in if not (Filename.is_relative l) then rpath := l :: !rpath) else if s = "-ocamlcflags" then - ocamlc_opts := next_arg () :: !ocamlc_opts + ocamlc_opts := next_arg s :: !ocamlc_opts else if s = "-ocamlc" then - ocamlc := next_arg () + ocamlc := next_arg s else if s = "-ocamlopt" then - ocamlopt := next_arg () + ocamlopt := next_arg s else if s = "-ocamloptflags" then - ocamlopt_opts := next_arg () :: !ocamlopt_opts + ocamlopt_opts := next_arg s :: !ocamlopt_opts else if s = "-o" then - output := next_arg() + output := next_arg s else if s = "-oc" then - output_c := next_arg() + output_c := next_arg s else if s = "-dllpath" || s = "-R" || s = "-rpath" then - rpath := next_arg() :: !rpath + rpath := next_arg s :: !rpath else if starts_with s "-R" then rpath := chop_prefix s "-R" :: !rpath else if s = "-Wl,-rpath" then - (let a = next_arg() in + (let a = next_arg s in if starts_with a "-Wl," then rpath := chop_prefix a "-Wl," :: !rpath else raise (Bad_argument("Option -Wl,-rpath expects a -Wl, argument"))) @@ -146,12 +172,11 @@ let parse_arguments argv = else if starts_with s "-F" then c_opts := s :: !c_opts else if s = "-framework" then - (let a = next_arg() in c_opts := a :: s :: !c_opts) + (let a = next_arg s in c_opts := a :: s :: !c_opts) else if starts_with s "-" then prerr_endline ("Unknown option " ^ s) else - raise (Bad_argument("Don't know what to do with " ^ s)); - incr i + raise (Bad_argument("Don't know what to do with " ^ s)) done; List.iter (fun r -> r := List.rev !r) @@ -166,6 +191,10 @@ let usage = "\ Usage: ocamlmklib [options] <.cmo|.cma|.cmx|.cmxa|.ml|.mli|.o|.a|.obj|.lib|\ .dll|.dylib files>\ \nOptions are:\ +\n -args Read additional newline-terminated command line arguments\ +\n from \ +\n -args0 Read additional null character terminated command line\ +\n arguments from \ \n -cclib C library passed to ocamlc -a or ocamlopt -a only\ \n -ccopt C option passed to ocamlc -a or ocamlopt -a only\ \n -custom Disable dynamic loading\ diff --git a/tools/ocamloptp.ml b/tools/ocamloptp.ml index fbeee6de..480480d7 100644 --- a/tools/ocamloptp.ml +++ b/tools/ocamloptp.ml @@ -24,7 +24,7 @@ let option_with_arg opt arg = compargs := (Filename.quote arg) :: opt :: !compargs ;; let option_with_int opt arg = - compargs := (string_of_int arg) :: opt :: !compargs + compargs := (Int.to_string arg) :: opt :: !compargs ;; let option_with_float opt arg = compargs := (string_of_float arg) :: opt :: !compargs @@ -53,6 +53,7 @@ module Options = Main_args.Make_optcomp_options (struct let _absname = option "-absname" let _afl_instrument = option "-afl-instrument" let _afl_inst_ratio n = option_with_int "-afl-inst-ratio" n + let _alert = option_with_arg "-alert" let _annot = option "-annot" let _binannot = option "-bin-annot" let _c = option "-c" @@ -62,8 +63,10 @@ module Options = Main_args.Make_optcomp_options (struct let _clambda_checks = option "-clambda-checks" let _compact = option "-compact" let _config = option "-config" + let _config_var s = option_with_arg "-config-var" s let _for_pack s = option_with_arg "-for-pack" s let _g = option "-g" + let _stop_after = option_with_arg "-stop-after" let _i = option "-i" let _I s = option_with_arg "-I" s let _impl s = with_impl := true; option_with_arg "-impl" s @@ -73,7 +76,7 @@ module Options = Main_args.Make_optcomp_options (struct let _dump_pass = option_with_arg "-dump-pass" let _inline_max_depth n = option_with_arg "-inline-max-depth" n let _rounds n = option_with_int "-rounds" n - let _inline_max_unroll n = option_with_arg "-unroll" n + let _inline_max_unroll n = option_with_arg "-inline-max-unroll" n let _inline_call_cost n = option_with_arg "-inline-call-cost" n let _inline_alloc_cost n = option_with_arg "-inline-alloc-cost" n let _inline_prim_cost n = option_with_arg "-inline-prim-cost" n @@ -142,10 +145,13 @@ module Options = Main_args.Make_optcomp_options (struct let _warn_error = option_with_arg "-warn-error" let _warn_help = option "-warn-help" let _color s = option_with_arg "-color" s + let _error_style s = option_with_arg "-error-style" s let _where = option "-where" let _linscan = option "-linscan" let _nopervasives = option "-nopervasives" + let _match_context_rows n = option_with_int "-match-context-rows" n + let _dump_into_file = option "-dump-into-file" let _dno_unique_ids = option "-dno-unique_ids" let _dunique_ids = option "-dunique_ids" let _dsource = option "-dsource" diff --git a/tools/ocamlprof.ml b/tools/ocamlprof.ml index 2e72d52c..4ee1ef06 100644 --- a/tools/ocamlprof.ml +++ b/tools/ocamlprof.ml @@ -139,7 +139,7 @@ let final_rewrite add_function = List.iter add_function !to_insert; copy (in_channel_length !inchan); if !instr_mode then begin - let len = string_of_int !prof_counter in + let len = Int.to_string !prof_counter in if String.length len > 9 then raise (Profiler "too many counters"); seek_out !outchan (!pos_len - String.length len); output_string !outchan len @@ -297,8 +297,12 @@ and rw_exp iflag sexp = List.iter (rewrite_class_field iflag) cl.pcstr_fields | Pexp_newtype (_, sexp) -> rewrite_exp iflag sexp - | Pexp_open (_ovf, _, e) -> rewrite_exp iflag e + | Pexp_open (_, e) -> rewrite_exp iflag e | Pexp_pack (smod) -> rewrite_mod iflag smod + | Pexp_letop {let_; ands; body; _} -> + rewrite_exp iflag let_.pbop_exp; + List.iter (fun {pbop_exp; _} -> rewrite_exp iflag pbop_exp) ands; + rewrite_exp iflag body | Pexp_extension _ -> () | Pexp_unreachable -> () @@ -367,7 +371,7 @@ and rewrite_class_expr iflag cexpr = | Pcl_let (_, spat_sexp_list, cexpr) -> rewrite_patexp_list iflag spat_sexp_list; rewrite_class_expr iflag cexpr - | Pcl_open (_, _, cexpr) + | Pcl_open (_, cexpr) | Pcl_constraint (cexpr, _) -> rewrite_class_expr iflag cexpr | Pcl_extension _ -> () @@ -507,11 +511,11 @@ let main () = "-vnum", Arg.Unit print_version_num, " Print version number and exit"; "-args", Arg.Expand Arg.read_arg, - " Read additional newline separated command line arguments \n\ - \ from "; + " Read additional newline separated command line arguments \n\ + \ from "; "-args0", Arg.Expand Arg.read_arg0, - " Read additional NUL separated command line arguments from \n\ - \ " + " Read additional NUL separated command line arguments from \n\ + \ " ] process_anon_file usage; exit 0 with diff --git a/tools/pre-commit-githook b/tools/pre-commit-githook new file mode 100755 index 00000000..4a846f1a --- /dev/null +++ b/tools/pre-commit-githook @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +#************************************************************************** +#* * +#* OCaml * +#* * +#* David Allsopp, MetaStack Solutions Ltd. * +#* * +#* Copyright 2017 MetaStack Solutions Ltd. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +# Bump this on any changes. It's vital that HOOK_VERSION followed by equals +# appears nowhere else in these sources! +HOOK_VERSION=3 + +# For what it's worth, allow for empty trees! +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 +fi + +# Redirect output to stderr. +exec 1>&2 + +# Check to see if the script's been updated +if git ls-files --error-unmatch tools/pre-commit-githook >/dev/null 2>&1 ; then + THEIR_VERSION=$(git cat-file --textconv HEAD:tools/pre-commit-githook \ + | sed -ne 's/^HOOK_VERSION=//p') + if [[ -n $THEIR_VERSION && $THEIR_VERSION -gt $HOOK_VERSION ]] ; then + echo "Note: tools/pre-commit-githook is newer than .git/hooks/pre-commit" + echo " You may wish to update your local githook" + fi +fi + +# Git's built-in mechanism for whitespace is neater than ours, so do it first. +# The strange construction below creates a list of files which have either +# white-at-eol or white-at-eof included in ocaml-typo in .gitattributes and by +# prefixing the names with :! causes git diff-index to skip over them. +if [[ -n $(git diff-index --cached --name-only $against) ]] ; then + FILES=$(git diff-index --cached --name-only $against \ + | xargs git check-attr --cached ocaml-typo \ + | sed -ne 's/\(.*\): ocaml-typo:.*[ ,]white-at-eo[fl]\(,\|$\)/:!\1/p') + if ! git diff-index --check --cached $against -- $FILES ; then + exit 1 + fi +else + exit 0 +fi + +# Test to see if any part of the directory name has been marked prune +not_pruned () { + DIR=$(dirname "$1") + if [ "$DIR" = "." ] ; then + return 0 + else + case ",$(git check-attr typo.prune "$DIR" | sed -e 's/.*: //')," in + ,set,) + return 1 + ;; + *) + + not_pruned $DIR + return $? + esac + fi +} + +# Now run check-typo over all the files in the index +ERRORS=0 +export OCAML_CT_PREFIX=: +export OCAML_CT_CAT="git cat-file --textconv" +export OCAML_CT_CA_FLAG=--cached +git diff --diff-filter=d --staged --name-only | (while IFS= read -r path +do + if not_pruned $path && ! tools/check-typo ./$path ; then + ERRORS=1 + fi +done; exit $ERRORS) diff --git a/tools/primreq.ml b/tools/primreq.ml index c84543ae..04832ad8 100644 --- a/tools/primreq.ml +++ b/tools/primreq.ml @@ -18,21 +18,20 @@ open Config open Cmo_format - -module StringSet = Set.Make(struct type t = string let compare = compare end) +module String = Misc.Stdlib.String let defined = ref true let used = ref false let exclude_file = ref "" -let primitives = ref StringSet.empty +let primitives = ref String.Set.empty let scan_reloc = function - (Reloc_primitive s, _) -> primitives := StringSet.add s !primitives + (Reloc_primitive s, _) -> primitives := String.Set.add s !primitives | _ -> () let scan_prim s = - primitives := StringSet.add s !primitives + primitives := String.Set.add s !primitives let scan_info cu = if !used then List.iter scan_reloc cu.cu_reloc; @@ -63,7 +62,7 @@ let exclude filename = try while true do let s = input_line ic in - primitives := StringSet.remove s !primitives + primitives := String.Set.remove s !primitives done with End_of_file -> close_in ic | x -> close_in ic; raise x @@ -87,7 +86,7 @@ let main() = scan_obj "Usage: primreq [options] <.cmo and .cma files>\nOptions are:"; if String.length !exclude_file > 0 then exclude !exclude_file; - StringSet.iter + String.Set.iter (fun s -> if s.[0] <> '%' then begin print_string s; print_newline() end) !primitives; diff --git a/tools/release-checklist b/tools/release-checklist new file mode 100644 index 00000000..0dd02095 --- /dev/null +++ b/tools/release-checklist @@ -0,0 +1,386 @@ +These are informal notes on how to do an OCaml release. + +Following these steps requires commit right in the OCaml repository, +as well as SSH access to the inria.fr file servers hosting the +distribution archives and manual. + +We are not fully confident that those steps are correct, feel free to +check with other release managers in case of doubt. + +Note: we say that a new release is a "testing release" if it is a Beta +version or Release Candidate. Otherwise, we call it a "production +release". + + +## A few days in advance + +Send a mail on caml-devel to warn Gabriel (to make a pass on Changes) +and the OCamlLabs folks (for OPAM testing). + +## 0: release environment setup + +``` +rm -f /tmp/env-$USER.sh +cat >/tmp/env-$USER.sh < 4.07.0+dev9-2018-06-26 +# for production releases: check and change the Changes header +# (remove "next version" and add a date) +# Update ocaml-variants.opam file to depend on the new version of ocaml. +git add VERSION Changes ocaml-variants.opam +git commit -m "last commit before tagging $VERSION" +# update VERSION with the new release; for example, +# 4.07.0+dev9-2018-06-26 => 4.07.0+rc2 +make coreboot -j5 +make coreboot -j5 # must say "Fixpoint reached, bootstrap succeeded." +git commit -m "change VERSION for $VERSION" -a +git tag -m "release $VERSION" $VERSION + +# for production releases, change the VERSION file into (N+1)+dev0; for example, +# 4.08.0 => 4.08.1+dev0 +# for testing candidates, use N+dev(D+2) instead; for example, +# 4.07.0+rc2 => 4.07.0+dev10-2018-06-26 +git commit -m "increment version number after tagging $VERSION" VERSION +git push +git push --tags +``` + + +## 6: create OPAM switches + +Create OPAM switches for the new version, copying the particular +switch configuration choices from the previous version. + +We currently use a semi-automated process, copying and batch-editing +the compiler descriptions from the last release. The instructions +below assume an opam1 repository organization, an opam2 repository +will have a different layout. + +From a branch of the opam-repository, in `compilers/$MAJOR.$MINOR.$BUGFIX`: + +``` +cd .../opam-repository/packages/ocaml-variants +# copy foo+rc2+... switches into foo+rc3+... +OLD_DIRS=*+rc2* +VER="s/+rc2/+rc3/g" + +NEW_DIRS="" +for f in $OLD_DIRS; do NEW_DIRS="$NEW_DIRS $(echo $f | sed $VER)"; done +echo $NEW_DIRS # for checking + +for f in $OLD_DIRS; do + mkdir -p $(echo $f | sed $VER) + for file in $f/*; do + cp $file $(echo $file | sed $VER) + # we copy the file, but their content still corresponds to the old version + done + git add $(echo $f | sed $VER) +done + +git status + # inspect the new filenames + +for f in $NEW_DIRS; do sed -i $VER $f/*; done +git diff # inspect the result of this last change + +git add $NEW_DIRS + +# the strings below work on .descr files, +# they may need to be adapted +for f in $NEW_DIRS; do + sed -i "s/rc2/rc3/g" $f/* + sed -i "s/Second release candidate/Third release candidate/g" $f/* +done +git diff # inspect the result of this last change + +git add $NEW_DIRS + +git diff --cached # inspect the complete result + +git commit -m "OPAM switches for $VERSION" +``` + +## 7: build the release archives + +``` +cd .../ocaml +TMPDIR=/tmp/ocaml-release +git checkout $VERSION +git checkout-index -a -f --prefix=$TMPDIR/ocaml-$VERSION/ +cd $TMPDIR +(cd ocaml-$VERSION && rm -rf experimental) +gtar -c --owner 0 --group 0 -f ocaml-$VERSION.tar ocaml-$VERSION +gzip -9 ocaml-$VERSION.tar.gz +xz ocaml-$VERSION.tar.xz +``` + + +## 8: upload the archives and compute checksums + +``` +scp ocaml-$VERSION.tar.{xz,gz} $ARCHIVE_HOST:$DIST +``` + +To update the checksum files on the remote host, we first upload the +release environment. +(note: this assumes the user name is the same on the two machines) + +``` +scp /tmp/env-$USER.sh $ARCHIVE_HOST:/tmp/env-$USER.sh +``` + +and then login there to update the checksums (MD5SUM, SHA512SUM) + +``` +ssh $ARCHIVE_HOST +source /tmp/env-$USER.sh +cd $DIST + +cp MD5SUM MD5SUM.old +md5sum ocaml-$VERSION.tar.{xz,gz} > new-md5s +# check new-md5s to ensure that they look right, and then +cat new-md5s >> MD5SUM +# if everything worked well, +rm MD5SUM.old new-md5s + +# same thing for SHA512 +cp SHA512SUM SHA512SUM.old +sha512sum ocaml-$VERSION.tar.{xz,gz} > new-sha512s +cat new-sha512s >> SHA512SUM +rm SHA512SUM.old new-sha512s + +# clean up +rm /tmp/env-$USER.sh +exit +``` + + +## 9: update note files (technical documentation) + +``` +ssh $ARCHIVE_HOST "mkdir -p $DIST/notes" +cd ocaml-$VERSION +scp INSTALL.adoc LICENSE README.adoc README.win32.adoc Changes \ + $ARCHIVE_HOST:$DIST/notes/ +``` + + +## 10: upload the reference manual + +You don't need to do this if the previous release had the same +$MAJOR.$MINOR ($BRANCH) value and the exact same manual -- this is frequent if +it was a release candidate. + +``` +make world.opt +make install +export PATH="$INSTDIR/bin:$PATH" +cd manual +make clean +make +rm -rf /tmp/release +mkdir -p /tmp/release +RELEASENAME="ocaml-$BRANCH-" RELEASE=/tmp/release/$RELEASENAME make release +scp /tmp/release/* $ARCHIVE_HOST:$DIST/ + + +# upload manual checksums +ssh $ARCHIVE_HOST "cd $DIST; md5sum ocaml-$BRANCH-refman* >>MD5SUM" +ssh $ARCHIVE_HOST "cd $DIST; sha512sum ocaml-$BRANCH-refman* >>SHA512SUM" +``` + +Releasing the manual online happens on another machine: + +``` +ssh $ARCHIVE_HOST +source /tmp/env.sh +scp /tmp/env.sh $WEB_HOST:/tmp +ssh $WEB_HOST +source /tmp/env.sh + +cd $WEB_PATH/caml/pub/docs +mkdir -p manual-ocaml-$BRANCH +cd manual-ocaml-$BRANCH +wget http://caml.inria.fr/pub/distrib/ocaml-$BRANCH/ocaml-$BRANCH-refman-html.tar.gz +tar -xzvf ocaml-$BRANCH-refman-html.tar.gz # this extracts into htmlman/ +cp -r htmlman/* . # move HTML content to docs/manual-caml-$BRANCH +rm -fR htmlman + +cd $WEB_PATH/caml/pub/docs +ln -sf manual-ocaml-$BRANCH manual-ocaml +``` + + +## 11: prepare web announce for the release + +For production releases, you should get in touch with ocaml.org to +organize the webpage for the new release. See + + + + +## 12: update Mantis + +Update Mantis by adding $MAJOR.$MINOR.$BUGFIX as a version number for reports. + +Provided you have a sufficient Mantis privilege level, this is done from + + https://caml.inria.fr/mantis/manage_proj_edit_page.php?project_id=1 + +after login, by scrolling down to "Versions". + +(If you don't have the necessary Mantis rights, you need to ask +someone else to do this.) + + +## 13: announce the release on caml-list and caml-announce + +See the email announce templates at the end of this file. + + + +# Announces + +## Announcing a production release: + +``` +Dear OCaml users, + +We have the pleasure of celebrating by announcing the release of +OCaml version $VERSION. +This is mainly a bug-fix release, see the list of changes below. + +It is (or soon will be) available as a set of OPAM switches, +and as a source download here: + https://caml.inria.fr/pub/distrib/ocaml-$BRANCH/ + +Happy hacking, + +-- Damien Doligez for the OCaml team. + +<< insert the relevant Changes section >> +``` + +## Announcing a release candidate: + +``` +Dear OCaml users, + +The release of OCaml version is imminent. We have +created a for your testing pleasure. Please +download the sources, compile, install, and test your favourite +software with it. Then let me know whether it works for you. + +We want to know about any show-stopping bugs, especially in the +compilation and installation phases. + +This is available as source code at this +address: < http://caml.inria.fr/pub/distrib/ocaml-$BRANCH/ > + +Happy hacking, + +-- Damien Doligez for the OCaml team. + +<< insert the relevant Changes section >> +``` + +## Announcing a beta version: + +``` +Dear OCaml users, + +The release of OCaml $BRANCH.$BUGFIX is approaching. We have created +a beta version to help you adapt your software to the new features +ahead of the release. + +The source code is available at this address: + + https://github.com/ocaml/ocaml/archive/$VERSION.tar.gz + +and the compiler is also available as a set of OPAM switches. + +We want to know about all bugs. Please report them here: + https://github.com/ocaml/ocaml/issues + +Happy hacking, + +-- Damien Doligez for the OCaml team. +``` diff --git a/tools/scrapelabels.ml b/tools/scrapelabels.ml index 018bc398..9a20e07a 100644 --- a/tools/scrapelabels.ml +++ b/tools/scrapelabels.ml @@ -30,7 +30,7 @@ let modules = ref [ "Arg"; "BigArray"; "Buffer"; "Condition"; "Dbm"; "Digest"; "Dynlink"; "Event"; "Filename"; "Format"; "Gc"; "Genlex"; "Graphics"; "Lexing"; "Marshal"; "Mutex"; "Parsing"; "Pervasives"; "Queue"; - "Sort"; "Stack"; "Str"; "Stream"; "Sys"; + "Stack"; "Str"; "Stream"; "Sys"; "Thread"; "ThreadUnix"; "Weak" ] let stdlabels = ["Array"; "List"; "String"] @@ -85,7 +85,7 @@ let convert_impl buffer = | UIDENT _ | LIDENT _ -> dropext (next_token ()) | _ -> - prerr_endline ("bad index at position " ^ string_of_int s); + prerr_endline ("bad index at position " ^ Int.to_string s); (token, s, e) end | _ -> @@ -186,7 +186,7 @@ let convert_impl buffer = end | Closing _ -> prerr_endline ("bad closing token at position " ^ - string_of_int (Lexing.lexeme_start buffer)); + Int.to_string (Lexing.lexeme_start buffer)); modified := false type state = Out | Enter | In | Escape diff --git a/toplevel/dune b/toplevel/dune new file mode 100644 index 00000000..476274b9 --- /dev/null +++ b/toplevel/dune @@ -0,0 +1,98 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +(library + (name ocamltoplevel) + (wrapped false) + (flags (:standard -principal -nostdlib)) + (libraries stdlib ocamlcommon ocamlbytecomp) + (modules genprintval toploop trace topdirs topmain)) + +(executable + (name topstart) + (modes byte) + (flags (:standard -principal -nostdlib)) + (libraries ocamlbytecomp ocamlcommon ocamltoplevel runtime stdlib) + (modules topstart)) + +(executable + (name expunge) + (modes byte) + (flags (:standard -principal -nostdlib)) + (libraries ocamlbytecomp ocamlcommon runtime stdlib) + (modules expunge)) + +(rule + (targets ocaml.byte) + (action (run %{ocaml_where}/expunge %{dep:topstart.exe} %{targets} + ; FIXME: inlined $(STDLIB_MODULES) ... minus Labels ones ... + stdlib__Spacetime + stdlib__Arg + stdlib__Array + ; stdlib__ArrayLabels + stdlib__Bigarray + stdlib__Buffer + stdlib__Bytes + ; stdlib__BytesLabels + stdlib__Callback + camlinternalFormat + camlinternalFormatBasics + camlinternalLazy + camlinternalMod + camlinternalOO + stdlib__Char + stdlib__Complex + stdlib__Digest + stdlib__Ephemeron + stdlib__Filename + stdlib__Float + stdlib__Format + stdlib__Gc + stdlib__Genlex + stdlib__Hashtbl + stdlib__Int32 + stdlib__Int64 + stdlib__Lazy + stdlib__Lexing + stdlib__List + ; stdlib__ListLabels + stdlib__Map + stdlib__Marshal + ; stdlib__MoreLabels + stdlib__Nativeint + stdlib__Obj + stdlib__Oo + stdlib__Option + stdlib__Parsing + stdlib__Pervasives + stdlib__Printexc + stdlib__Printf + stdlib__Queue + stdlib__Random + stdlib__Result + stdlib__Scanf + stdlib__Seq + stdlib__Set + stdlib__Stack + ; stdlib__StdLabels + stdlib + stdlib__Stream + stdlib__String + ; stdlib__StringLabels + stdlib__Sys + stdlib__Uchar + stdlib__Weak + ; the rest + outcometree topdirs toploop + ))) diff --git a/toplevel/expunge.ml b/toplevel/expunge.ml index e97d8e59..22eb46f6 100644 --- a/toplevel/expunge.ml +++ b/toplevel/expunge.ml @@ -17,25 +17,20 @@ Usage: expunge *) open Misc - -module StringSet = - Set.Make(struct - type t = string - let compare = compare - end) +module String = Misc.Stdlib.String let is_exn = let h = Hashtbl.create 64 in Array.iter (fun n -> Hashtbl.add h n ()) Runtimedef.builtin_exceptions; Hashtbl.mem h -let to_keep = ref StringSet.empty +let to_keep = ref String.Set.empty let negate = Sys.argv.(3) = "-v" let keep = - if negate then fun name -> is_exn name || not (StringSet.mem name !to_keep) - else fun name -> is_exn name || (StringSet.mem name !to_keep) + if negate then fun name -> is_exn name || not (String.Set.mem name !to_keep) + else fun name -> is_exn name || (String.Set.mem name !to_keep) let expunge_map tbl = Symtable.filter_global_map (fun id -> keep (Ident.name id)) tbl @@ -47,7 +42,7 @@ let main () = let input_name = Sys.argv.(1) in let output_name = Sys.argv.(2) in for i = (if negate then 4 else 3) to Array.length Sys.argv - 1 do - to_keep := StringSet.add (String.capitalize_ascii Sys.argv.(i)) !to_keep + to_keep := String.Set.add (String.capitalize_ascii Sys.argv.(i)) !to_keep done; let ic = open_in_bin input_name in Bytesections.read_toc ic; diff --git a/toplevel/genprintval.ml b/toplevel/genprintval.ml index 09b8fbeb..bda4fd9c 100644 --- a/toplevel/genprintval.ml +++ b/toplevel/genprintval.ml @@ -21,6 +21,7 @@ open Longident open Path open Types open Outcometree +module Out_name = Printtyp.Out_name module type OBJ = sig @@ -38,7 +39,7 @@ module type OBJ = module type EVALPATH = sig type valu - val eval_path: Env.t -> Path.t -> valu + val eval_address: Env.address -> valu exception Error val same_value: valu -> valu -> bool end @@ -102,7 +103,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct else if O.tag arg = Obj.double_tag then list := Oval_float (O.obj arg : float) :: !list else - list := Oval_constr (Oide_ident "_", []) :: !list + list := Oval_constr (Oide_ident (Out_name.create "_"), []) :: !list done; List.rev !list end @@ -110,7 +111,8 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct let outval_of_untyped_exception bucket = if O.tag bucket <> 0 then - Oval_constr (Oide_ident (O.obj (O.field bucket 0) : string), []) + let name = Out_name.create (O.obj (O.field bucket 0) : string) in + Oval_constr (Oide_ident name, []) else let name = (O.obj(O.field(O.field bucket 0) 0) : string) in let args = @@ -121,7 +123,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct && O.tag(O.field bucket 1) = 0 then outval_of_untyped_exception_args (O.field bucket 1) 0 else outval_of_untyped_exception_args bucket 1 in - Oval_constr (Oide_ident name, args) + Oval_constr (Oide_ident (Out_name.create name), args) (* The user-defined printers. Also used for some builtin types. *) @@ -131,28 +133,29 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct O.t -> Outcometree.out_value) gen_printer) let printers = ref ([ - ( Pident(Ident.create "print_int"), + ( Pident(Ident.create_local "print_int"), Simple (Predef.type_int, (fun x -> Oval_int (O.obj x : int))) ); - ( Pident(Ident.create "print_float"), + ( Pident(Ident.create_local "print_float"), Simple (Predef.type_float, (fun x -> Oval_float (O.obj x : float))) ); - ( Pident(Ident.create "print_char"), + ( Pident(Ident.create_local "print_char"), Simple (Predef.type_char, (fun x -> Oval_char (O.obj x : char))) ); - ( Pident(Ident.create "print_int32"), + ( Pident(Ident.create_local "print_int32"), Simple (Predef.type_int32, (fun x -> Oval_int32 (O.obj x : int32))) ); - ( Pident(Ident.create "print_nativeint"), + ( Pident(Ident.create_local "print_nativeint"), Simple (Predef.type_nativeint, (fun x -> Oval_nativeint (O.obj x : nativeint))) ); - ( Pident(Ident.create "print_int64"), + ( Pident(Ident.create_local "print_int64"), Simple (Predef.type_int64, (fun x -> Oval_int64 (O.obj x : int64)) )) ] : (Path.t * printer) list) let exn_printer ppf path exn = - fprintf ppf "" Printtyp.path path (Printexc.to_string exn) + fprintf ppf "" Printtyp.path path + (Printexc.to_string exn) let out_exn path exn = Oval_printer (fun ppf -> exn_printer ppf path exn) @@ -198,14 +201,14 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct match ty_path with | Pident _ -> Oide_ident name - | Pdot(p, _s, _pos) -> + | Pdot(p, _s) -> if try - match (lookup_fun (Lident name) env).desc with + match (lookup_fun (Lident (Out_name.print name)) env).desc with | Tconstr(ty_path', _, _) -> Path.same ty_path ty_path' | _ -> false with Not_found -> false then Oide_ident name - else Oide_dot (Printtyp.tree_of_path p, name) + else Oide_dot (Printtyp.tree_of_path p, Out_name.print name) | Papply _ -> Printtyp.tree_of_path ty_path @@ -219,7 +222,9 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct (* An abstract type *) let abstract_type = - Ctype.newty (Tconstr (Pident (Ident.create "abstract"), [], ref Mnil)) + let id = Ident.create_local "abstract" in + let ty = Btype.newgenty (Tconstr (Pident id, [], ref Mnil)) in + ty (* The main printing function *) @@ -363,7 +368,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct then nest tree_of_val depth forced_obj ty_arg else tree_of_val depth forced_obj ty_arg in - Oval_constr (Oide_ident "lazy", [v]) + Oval_constr (Oide_ident (Out_name.create "lazy"), [v]) end | Tconstr(path, ty_list, _) -> begin try @@ -413,7 +418,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct lbls 0 obj unbx in Oval_constr(tree_of_constr env path - (Ident.name cd_id), + (Out_name.create (Ident.name cd_id)), [ r ]) end | {type_kind = Type_record(lbl_list, rep)} -> @@ -422,7 +427,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct | None -> let pos = match rep with - | Record_extension -> 1 + | Record_extension _ -> 1 | _ -> 0 in let unbx = @@ -493,8 +498,8 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct (* PR#5722: print full module path only for first record field *) let lid = - if pos = 0 then tree_of_label env path name - else Oide_ident name + if pos = 0 then tree_of_label env path (Out_name.create name) + else Oide_ident (Out_name.create name) and v = if unboxed then tree_of_val (depth - 1) obj ty_arg @@ -522,7 +527,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct and tree_of_constr_with_args tree_of_cstr cstr_name inlined start depth obj ty_args unboxed = - let lid = tree_of_cstr cstr_name in + let lid = tree_of_cstr (Out_name.create cstr_name) in let args = if inlined || unboxed then match ty_args with @@ -549,10 +554,11 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct Cstr_extension(p, _) -> p | _ -> raise Not_found in + let addr = Env.find_constructor_address path env in (* Make sure this is the right exception and not an homonym, by evaluating the exception found and comparing with the identifier contained in the exception bucket *) - if not (EVP.same_value slot (EVP.eval_path env path)) + if not (EVP.same_value slot (EVP.eval_address addr)) then raise Not_found; tree_of_constr_with_args (fun x -> Oide_ident x) name (cstr.cstr_inlined <> None) @@ -583,7 +589,8 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct and apply_generic_printer path printer args = match (printer, args) with - | (Zero fn, []) -> (fun (obj : O.t)-> try fn obj with exn -> out_exn path exn) + | (Zero fn, []) -> + (fun (obj : O.t)-> try fn obj with exn -> out_exn path exn) | (Succ fn, arg :: args) -> let printer = fn (fun depth obj -> tree_of_val depth obj arg) in apply_generic_printer path printer args diff --git a/toplevel/genprintval.mli b/toplevel/genprintval.mli index e45050e9..a74de583 100644 --- a/toplevel/genprintval.mli +++ b/toplevel/genprintval.mli @@ -34,7 +34,7 @@ module type OBJ = module type EVALPATH = sig type valu - val eval_path: Env.t -> Path.t -> valu + val eval_address: Env.address -> valu exception Error val same_value: valu -> valu -> bool end diff --git a/toplevel/opttopdirs.ml b/toplevel/opttopdirs.ml index 795c7e48..9170cb62 100644 --- a/toplevel/opttopdirs.ml +++ b/toplevel/opttopdirs.ml @@ -34,13 +34,26 @@ let _ = Hashtbl.add directive_table "quit" (Directive_none dir_quit) let dir_directory s = let d = expand_directory Config.standard_library s in - Config.load_path := d :: !Config.load_path + let dir = Load_path.Dir.create d in + Load_path.add dir; + toplevel_env := + Stdlib.String.Set.fold + (fun name env -> + Env.add_persistent_structure (Ident.create_persistent name) env) + (Env.persistent_structures_of_dir dir) + !toplevel_env let _ = Hashtbl.add directive_table "directory" (Directive_string dir_directory) (* To remove a directory from the load path *) let dir_remove_directory s = let d = expand_directory Config.standard_library s in - Config.load_path := List.filter (fun d' -> d' <> d) !Config.load_path + let keep id = + match Load_path.find_uncap (Ident.name id ^ ".cmi") with + | exception Not_found -> true + | fn -> Filename.dirname fn <> d + in + toplevel_env := Env.filter_non_loaded_persistent keep !toplevel_env; + Load_path.remove_dir s let _ = Hashtbl.add directive_table "remove_directory" @@ -49,7 +62,7 @@ let _ = let _ = Hashtbl.add directive_table "show_dirs" (Directive_none (fun () -> - List.iter print_endline !Config.load_path + List.iter print_endline (Load_path.get_paths ()) )) (* To change the current directory *) @@ -62,7 +75,7 @@ let _ = Hashtbl.add directive_table "cd" (Directive_string dir_cd) let load_file ppf name0 = let name = - try Some (find_in_path !Config.load_path name0) + try Some (Load_path.find name0) with Not_found -> None in match name with @@ -72,7 +85,7 @@ let load_file ppf name0 = if Filename.check_suffix name ".cmx" || Filename.check_suffix name ".cmxa" then let cmxs = Filename.temp_file "caml" ".cmxs" in - Asmlink.link_shared ppf [name] cmxs; + Asmlink.link_shared ~ppf_dump:ppf [name] cmxs; cmxs,true else name,false @@ -117,12 +130,11 @@ let match_printer_type ppf desc typename = with Not_found -> fprintf ppf "Cannot find type Topdirs.%s.@." typename; raise Exit in - Ctype.init_def(Ident.current_time()); Ctype.begin_def(); let ty_arg = Ctype.newvar() in Ctype.unify !toplevel_env (Ctype.newconstr printer_type [ty_arg]) - (Ctype.instance_def desc.val_type); + (Ctype.instance desc.val_type); Ctype.end_def(); Ctype.generalize ty_arg; ty_arg @@ -148,7 +160,7 @@ let find_printer_type ppf lid = let dir_install_printer ppf lid = try let (ty_arg, path, is_old_style) = find_printer_type ppf lid in - let v = eval_path !toplevel_env path in + let v = eval_value_path !toplevel_env path in let print_function = if is_old_style then (fun _formatter repr -> Obj.obj v (Obj.obj repr)) diff --git a/toplevel/opttoploop.ml b/toplevel/opttoploop.ml index cd6d91da..45918317 100644 --- a/toplevel/opttoploop.ml +++ b/toplevel/opttoploop.ml @@ -15,7 +15,6 @@ (* The interactive toplevel loop *) -open Path open Format open Config open Misc @@ -62,16 +61,14 @@ type directive_fun = | Directive_bool of (bool -> unit) -(* Return the value referred to by a path *) - let remembered = ref Ident.empty let rec remember phrase_name i = function | [] -> () - | Sig_value (id, _) :: rest - | Sig_module (id, _, _) :: rest - | Sig_typext (id, _, _) :: rest - | Sig_class (id, _, _) :: rest -> + | Sig_value (id, _, _) :: rest + | Sig_module (id, _, _, _, _) :: rest + | Sig_typext (id, _, _, _) :: rest + | Sig_class (id, _, _, _) :: rest -> remembered := Ident.add id (phrase_name, i) !remembered; remember phrase_name (succ i) rest | _ :: rest -> remember phrase_name i rest @@ -98,25 +95,41 @@ let toplevel_value id = in (Obj.magic (global_symbol glob)).(pos) -let rec eval_path = function - | Pident id -> +(* Return the value referred to by a path *) + +let rec eval_address = function + | Env.Aident id -> if Ident.persistent id || Ident.global id then global_symbol id else toplevel_value id - | Pdot(p, _s, pos) -> - Obj.field (eval_path p) pos - | Papply _ -> - fatal_error "Toploop.eval_path" + | Env.Adot(a, pos) -> + Obj.field (eval_address a) pos + +let eval_path find env path = + match find path env with + | addr -> eval_address addr + | exception Not_found -> + fatal_error ("Cannot find address for: " ^ (Path.name path)) + +let eval_module_path env path = + eval_path Env.find_module_address env path + +let eval_value_path env path = + eval_path Env.find_value_address env path + +let eval_extension_path env path = + eval_path Env.find_constructor_address env path -let eval_path env path = - eval_path (Env.normalize_path (Some Location.none) env path) +let eval_class_path env path = + eval_path Env.find_class_address env path (* To print values *) module EvalPath = struct type valu = Obj.t exception Error - let eval_path env p = try eval_path env p with _ -> raise Error + let eval_address addr = + try eval_address addr with _ -> raise Error let same_value v1 v2 = (v1 == v2) end @@ -155,14 +168,15 @@ let remove_printer = Printer.remove_printer let parse_toplevel_phrase = ref Parse.toplevel_phrase let parse_use_file = ref Parse.use_file -let print_location = Location.print_error (* FIXME change back to print *) -let print_error = Location.print_error +let print_location = Location.print_loc +let print_error = Location.print_report let print_warning = Location.print_warning let input_name = Location.input_name let parse_mod_use_file name lb = let modname = - String.capitalize_ascii (Filename.chop_extension (Filename.basename name)) + String.capitalize_ascii + (Filename.remove_extension (Filename.basename name)) in let items = List.concat @@ -179,10 +193,26 @@ let parse_mod_use_file name lb = ] ] -(* Hooks for initialization *) +(* Hook for initialization *) let toplevel_startup_hook = ref (fun () -> ()) +type event = .. +type event += + | Startup + | After_setup + +let hooks = ref [] + +let add_hook f = hooks := f :: !hooks + +let () = + add_hook (function + | Startup -> !toplevel_startup_hook () + | _ -> ()) + +let run_hooks hook = List.iter (fun f -> f hook) !hooks + (* Load in-core and execute a lambda term *) let phrase_seqid = ref 0 @@ -221,13 +251,13 @@ let load_lambda ppf ~module_ident ~required_globals lam size = let fn = Filename.chop_extension dll in if not Config.flambda then Asmgen.compile_implementation_clambda - ~toplevel:need_symbol fn ppf + ~toplevel:need_symbol fn ~ppf_dump:ppf { Lambda.code=slam ; main_module_block_size=size; module_ident; required_globals } else Asmgen.compile_implementation_flambda - ~required_globals ~backend ~toplevel:need_symbol fn ppf - (Middle_end.middle_end ppf ~prefixname:"" ~backend ~size + ~required_globals ~backend ~toplevel:need_symbol fn ~ppf_dump:ppf + (Middle_end.middle_end ~ppf_dump:ppf ~prefixname:"" ~backend ~size ~module_ident ~module_initializer:slam ~filename:"toplevel"); Asmlink.call_linker_shared [fn ^ ext_obj] dll; Sys.remove (fn ^ ext_obj); @@ -248,7 +278,7 @@ let load_lambda ppf ~module_ident ~required_globals lam size = let pr_item = Printtyp.print_items (fun env -> function - | Sig_value(id, {val_kind = Val_reg; val_type}) -> + | Sig_value(id, {val_kind = Val_reg; val_type}, _) -> Some (outval_of_value env (toplevel_value id) val_type) | _ -> None ) @@ -297,9 +327,9 @@ let execute_phrase print_outcome ppf phr = [ Ast_helper.Str.value ~loc Asttypes.Nonrecursive [vb] ], true | _ -> sstr, false in - let (str, sg, newenv) = Typemod.type_toplevel_phrase oldenv sstr in + let (str, sg, names, newenv) = Typemod.type_toplevel_phrase oldenv sstr in if !Clflags.dump_typedtree then Printtyped.implementation ppf str; - let sg' = Typemod.simplify_signature sg in + let sg' = Typemod.Signature_names.simplify newenv names sg in (* Why is this done? *) ignore (Includemod.signatures oldenv sg sg'); Typecore.force_delayed_checks (); @@ -335,7 +365,7 @@ let execute_phrase print_outcome ppf phr = | _ -> if rewritten then match sg' with - | [ Sig_value (id, vd) ] -> + | [ Sig_value (id, vd, _) ] -> let outv = outval_of_value newenv (toplevel_value id) vd.val_type @@ -344,7 +374,7 @@ let execute_phrase print_outcome ppf phr = Ophr_eval (outv, ty) | _ -> assert false else - Ophr_signature (pr_item newenv sg')) + Ophr_signature (pr_item oldenv sg')) else Ophr_signature [] | Exception exn -> toplevel_env := oldenv; @@ -362,7 +392,7 @@ let execute_phrase print_outcome ppf phr = with x -> toplevel_env := oldenv; raise x end - | Ptop_dir(dir_name, dir_arg) -> + | Ptop_dir {pdir_name = {Location.txt = dir_name}; pdir_arg } -> let d = try Some (Hashtbl.find directive_table dir_name) with Not_found -> None @@ -372,10 +402,10 @@ let execute_phrase print_outcome ppf phr = fprintf ppf "Unknown directive `%s'.@." dir_name; false | Some d -> - match d, dir_arg with - | Directive_none f, Pdir_none -> f (); true - | Directive_string f, Pdir_string s -> f s; true - | Directive_int f, Pdir_int (n,None) -> + match d, pdir_arg with + | Directive_none f, None -> f (); true + | Directive_string f, Some {pdira_desc = Pdir_string s} -> f s; true + | Directive_int f, Some {pdira_desc = Pdir_int (n,None)} -> begin match Int_literal_converter.int n with | n -> f n; true | exception _ -> @@ -384,12 +414,12 @@ let execute_phrase print_outcome ppf phr = dir_name; false end - | Directive_int _, Pdir_int (_, Some _) -> + | Directive_int _, Some {pdira_desc = Pdir_int (_, Some _)} -> fprintf ppf "Wrong integer literal for directive `%s'.@." dir_name; false - | Directive_ident f, Pdir_ident lid -> f lid; true - | Directive_bool f, Pdir_bool b -> f b; true + | Directive_ident f, Some {pdira_desc = Pdir_ident lid} -> f lid; true + | Directive_bool f, Some {pdira_desc = Pdir_bool b} -> f b; true | _ -> fprintf ppf "Wrong type of argument for directive `%s'.@." dir_name; @@ -423,7 +453,7 @@ let use_file ppf wrap_mod name = if name = "" then ("(stdin)", stdin, false) else begin - let filename = find_in_path !Config.load_path name in + let filename = Load_path.find name in let ic = open_in_bin filename in (filename, ic, true) end @@ -464,12 +494,12 @@ let first_line = ref true let got_eof = ref false;; let read_input_default prompt buffer len = - output_string Pervasives.stdout prompt; flush Pervasives.stdout; + output_string stdout prompt; flush stdout; let i = ref 0 in try while true do if !i >= len then raise Exit; - let c = input_char Pervasives.stdin in + let c = input_char stdin in Bytes.set buffer !i c; incr i; if c = '\n' then raise Exit; @@ -508,7 +538,6 @@ let refill_lexbuf buffer len = let _ = Sys.interactive := true; - Compdynlink.init (); Compmisc.init_path true; Clflags.dlcode := true; () @@ -530,9 +559,18 @@ let set_paths () = (* Add whatever -I options have been specified on the command line, but keep the directories that user code linked in with ocamlmktop may have added to load_path. *) - load_path := !load_path @ [Filename.concat Config.standard_library "camlp4"]; - load_path := "" :: (List.rev !Clflags.include_dirs @ !load_path); - () + let expand = Misc.expand_directory Config.standard_library in + let current_load_path = Load_path.get_paths () in + let load_path = List.concat [ + [ "" ]; + List.map expand (List.rev !Compenv.first_include_dirs); + List.map expand (List.rev !Clflags.include_dirs); + List.map expand (List.rev !Compenv.last_include_dirs); + current_load_path; + [expand "+camlp4"]; + ] + in + Load_path.init load_path let initialize_toplevel_env () = toplevel_env := Compmisc.initial_env() @@ -551,6 +589,7 @@ let loop ppf = Location.input_name := "//toplevel//"; Location.input_lexbuf := Some lb; Sys.catch_break true; + run_hooks After_setup; load_ocamlinit ppf; while true do let snap = Btype.snapshot () in @@ -590,6 +629,7 @@ let run_script ppf name args = (* Note: would use [Filename.abspath] here, if we had it. *) toplevel_env := Compmisc.initial_env(); Sys.interactive := false; + run_hooks After_setup; let explicit_name = (* Prevent use_silently from searching in the path. *) if Filename.is_implicit name diff --git a/toplevel/opttoploop.mli b/toplevel/opttoploop.mli index f234b4f4..a9a15d50 100644 --- a/toplevel/opttoploop.mli +++ b/toplevel/opttoploop.mli @@ -61,7 +61,10 @@ val mod_use_file : formatter -> string -> bool [use_file] prints the types and values of the results. [use_silently] does not print them. [mod_use_file] wrap the file contents into a module. *) -val eval_path: Env.t -> Path.t -> Obj.t +val eval_module_path: Env.t -> Path.t -> Obj.t +val eval_value_path: Env.t -> Path.t -> Obj.t +val eval_extension_path: Env.t -> Path.t -> Obj.t +val eval_class_path: Env.t -> Path.t -> Obj.t (* Return the toplevel object referred to by the given path *) (* Printing of values *) @@ -92,7 +95,7 @@ val max_printer_steps: int ref val parse_toplevel_phrase : (Lexing.lexbuf -> Parsetree.toplevel_phrase) ref val parse_use_file : (Lexing.lexbuf -> Parsetree.toplevel_phrase list) ref val print_location : formatter -> Location.t -> unit -val print_error : formatter -> Location.t -> unit +val print_error : formatter -> Location.error -> unit val print_warning : Location.t -> formatter -> Warnings.t -> unit val input_name : string ref @@ -117,10 +120,27 @@ val print_out_phrase : val read_interactive_input : (string -> bytes -> int -> int * bool) ref -(* Hooks for initialization *) +(* Hooks *) val toplevel_startup_hook : (unit -> unit) ref +type event = .. +type event += + | Startup + | After_setup + (* Just after the setup, when the toplevel is ready to evaluate user + input. This happens before the toplevel has evaluated any kind of + user input, in particular this happens before loading the + [.ocamlinit] file. *) + +val add_hook : (event -> unit) -> unit +(* Add a function that will be called at key points of the toplevel + initialization process. *) + +val run_hooks : event -> unit +(* Run all the registered hooks. *) + + (* Misc *) val override_sys_argv : string array -> unit diff --git a/toplevel/opttopmain.ml b/toplevel/opttopmain.ml index 423d68c2..cbc0fd56 100644 --- a/toplevel/opttopmain.ml +++ b/toplevel/opttopmain.ml @@ -32,9 +32,11 @@ let is_expanded pos = pos < !first_nonexpanded_pos let expand_position pos len = if pos < !first_nonexpanded_pos then - first_nonexpanded_pos := !first_nonexpanded_pos + len (* Shift the position *) + (* Shift the position *) + first_nonexpanded_pos := !first_nonexpanded_pos + len else - first_nonexpanded_pos := pos + len + 2 (* New last position *) + (* New last position *) + first_nonexpanded_pos := pos + len + 2 let prepare ppf = @@ -43,7 +45,7 @@ let prepare ppf = let res = List.for_all (Opttopdirs.load_file ppf) (List.rev !preload_objects) in - !Opttoploop.toplevel_startup_hook (); + Opttoploop.run_hooks Opttoploop.Startup; res with x -> try Location.report_exception ppf x; false @@ -63,13 +65,14 @@ let file_argument name = than the original argv. *) Printf.eprintf "For implementation reasons, the toplevel does not support\ - \ having script files (here %S) inside expanded arguments passed through the\ - \ -args{,0} command-line option.\n" name; + \ having script files (here %S) inside expanded arguments passed through\ + \ the -args{,0} command-line option.\n" name; exit 2 end else begin let newargs = Array.sub !argv !Arg.current (Array.length !argv - !Arg.current) in + Compmisc.read_clflags_from_env (); if prepare ppf && Opttoploop.run_script ppf name newargs then exit 0 else exit 2 @@ -95,11 +98,10 @@ module Options = Main_args.Make_opttop_options (struct let set r () = r := true let clear r () = r := false - let _absname = set Location.absname + let _absname = set absname + let _alert = Warnings.parse_alert_option let _compact = clear optimize_for_speed - let _I dir = - let dir = Misc.expand_directory Config.standard_library dir in - include_dirs := dir :: !include_dirs + let _I dir = include_dirs := dir :: !include_dirs let _init s = init_file := Some s let _noinit = set noinit let _clambda_checks () = clambda_checks := true @@ -187,6 +189,7 @@ module Options = Main_args.Make_opttop_options (struct let _noprompt = set noprompt let _nopromptcont = set nopromptcont let _nostdlib = set no_std_include + let _nopervasives = set nopervasives let _ppx s = Compenv.first_ppx := s :: !Compenv.first_ppx let _principal = set principal let _no_principal = clear principal @@ -202,7 +205,7 @@ module Options = Main_args.Make_opttop_options (struct let _stdin () = file_argument "" let _unboxed_types = set unboxed_types let _no_unboxed_types = clear unboxed_types - let _unsafe = set fast + let _unsafe = set unsafe let _verbose = set verbose let _version () = print_version () let _vnum () = print_version_num () @@ -240,6 +243,8 @@ module Options = Main_args.Make_opttop_options (struct let _safe_string = clear unsafe_string let _unsafe_string = set unsafe_string let _open s = open_modules := s :: !open_modules + let _color = Misc.set_or_ignore color_reader.parse color + let _error_style = Misc.set_or_ignore error_style_reader.parse error_style let _args = wrap_expand Arg.read_arg let _args0 = wrap_expand Arg.read_arg0 @@ -247,6 +252,14 @@ module Options = Main_args.Make_opttop_options (struct let anonymous = file_argument end);; +let () = + let extra_paths = + match Sys.getenv "OCAMLTOP_INCLUDE_PATH" with + | exception Not_found -> [] + | s -> Misc.split_path_contents s + in + Clflags.include_dirs := List.rev_append extra_paths !Clflags.include_dirs + let main () = native_code := true; let list = ref Options.list in @@ -257,6 +270,7 @@ let main () = | Arg.Bad msg -> Format.fprintf Format.err_formatter "%s%!" msg; exit 2 | Arg.Help msg -> Format.fprintf Format.std_formatter "%s%!" msg; exit 0 end; + Compmisc.read_clflags_from_env (); if not (prepare Format.err_formatter) then exit 2; Compmisc.init_path true; Opttoploop.loop Format.std_formatter diff --git a/toplevel/topdirs.ml b/toplevel/topdirs.ml index ec61f572..c4518bcf 100644 --- a/toplevel/topdirs.ml +++ b/toplevel/topdirs.ml @@ -70,8 +70,15 @@ let _ = add_directive "quit" (Directive_none dir_quit) let dir_directory s = let d = expand_directory Config.standard_library s in - Config.load_path := d :: !Config.load_path; - Dll.add_path [d] + Dll.add_path [d]; + let dir = Load_path.Dir.create d in + Load_path.add dir; + toplevel_env := + Stdlib.String.Set.fold + (fun name env -> + Env.add_persistent_structure (Ident.create_persistent name) env) + (Env.persistent_structures_of_dir dir) + !toplevel_env let _ = add_directive "directory" (Directive_string dir_directory) { @@ -83,7 +90,13 @@ let _ = add_directive "directory" (Directive_string dir_directory) (* To remove a directory from the load path *) let dir_remove_directory s = let d = expand_directory Config.standard_library s in - Config.load_path := List.filter (fun d' -> d' <> d) !Config.load_path; + let keep id = + match Load_path.find_uncap (Ident.name id ^ ".cmi") with + | exception Not_found -> true + | fn -> Filename.dirname fn <> d + in + toplevel_env := Env.filter_non_loaded_persistent keep !toplevel_env; + Load_path.remove_dir s; Dll.remove_path [d] let _ = add_directive "remove_directory" (Directive_string dir_remove_directory) @@ -124,10 +137,10 @@ let load_compunit ic filename ppf compunit = check_consistency ppf filename compunit; seek_in ic compunit.cu_pos; let code_size = compunit.cu_codesize + 8 in - let code = Meta.static_alloc code_size in - unsafe_really_input ic code 0 compunit.cu_codesize; - Bytes.unsafe_set code compunit.cu_codesize (Char.chr Opcodes.opRETURN); - String.unsafe_blit "\000\000\000\001\000\000\000" 0 + let code = LongString.create code_size in + LongString.input_bytes_into code ic compunit.cu_codesize; + LongString.set code compunit.cu_codesize (Char.chr Opcodes.opRETURN); + LongString.blit_string "\000\000\000\001\000\000\000" 0 code (compunit.cu_codesize + 1) 7; let initial_symtable = Symtable.current_state() in Symtable.patch_object code compunit.cu_reloc; @@ -138,10 +151,10 @@ let load_compunit ic filename ppf compunit = seek_in ic compunit.cu_debug; [| input_value ic |] end in - Meta.add_debug_info code code_size events; begin try may_trace := true; - ignore((Meta.reify_bytecode code code_size) ()); + let _bytecode, closure = Meta.reify_bytecode code events None in + ignore (closure ()); may_trace := false; with exn -> record_backtrace (); @@ -153,19 +166,15 @@ let load_compunit ic filename ppf compunit = let rec load_file recursive ppf name = let filename = - try Some (find_in_path !Config.load_path name) with Not_found -> None + try Some (Load_path.find name) with Not_found -> None in match filename with | None -> fprintf ppf "Cannot find file %s.@." name; false | Some filename -> let ic = open_in_bin filename in - try - let success = really_load_file recursive ppf name filename ic in - close_in ic; - success - with exn -> - close_in ic; - raise exn + Misc.try_finally + ~always:(fun () -> close_in ic) + (fun () -> really_load_file recursive ppf name filename ic) and really_load_file recursive ppf name filename ic = let buffer = really_input_string ic (String.length Config.cmo_magic_number) in @@ -180,12 +189,9 @@ and really_load_file recursive ppf name filename ic = | (Reloc_getglobal id, _) when not (Symtable.is_global_defined id) -> let file = Ident.name id ^ ".cmo" in - begin match try Some (Misc.find_in_path_uncap !Config.load_path - file) - with Not_found -> None - with - | None -> () - | Some file -> + begin match Load_path.find_uncap file with + | exception Not_found -> () + | file -> if not (load_file recursive ppf file) then raise Load_failed end | _ -> () @@ -294,7 +300,7 @@ let match_simple_printer_type desc printer_type = let ty_arg = Ctype.newvar() in Ctype.unify !toplevel_env (Ctype.newconstr printer_type [ty_arg]) - (Ctype.instance_def desc.val_type); + (Ctype.instance desc.val_type); Ctype.end_def(); Ctype.generalize ty_arg; (ty_arg, None) @@ -312,7 +318,7 @@ let match_generic_printer_type desc path args printer_type = ty_args (Ctype.newconstr printer_type [ty_target]) in Ctype.unify !toplevel_env ty_expected - (Ctype.instance_def desc.val_type); + (Ctype.instance desc.val_type); Ctype.end_def(); Ctype.generalize ty_expected; if not (Ctype.all_distinct_vars !toplevel_env args) then @@ -322,7 +328,6 @@ let match_generic_printer_type desc path args printer_type = let match_printer_type ppf desc = let printer_type_new = printer_type ppf "printer_type_new" in let printer_type_old = printer_type ppf "printer_type_old" in - Ctype.init_def(Ident.current_time()); try (match_simple_printer_type desc printer_type_new, false) with Ctype.Unify _ -> @@ -353,7 +358,7 @@ let dir_install_printer ppf lid = try let ((ty_arg, ty), path, is_old_style) = find_printer_type ppf lid in - let v = eval_path !toplevel_env path in + let v = eval_value_path !toplevel_env path in match ty with | None -> let print_function = @@ -418,7 +423,7 @@ let dir_trace ppf lid = fprintf ppf "%a is an external function and cannot be traced.@." Printtyp.longident lid | _ -> - let clos = eval_path !toplevel_env path in + let clos = eval_value_path !toplevel_env path in (* Nothing to do if it's not a closure *) if Obj.is_block clos && (Obj.tag clos = Obj.closure_tag || Obj.tag clos = Obj.infix_tag) @@ -483,11 +488,15 @@ let trim_signature = function Mty_signature (List.map (function - Sig_module (id, md, rs) -> - Sig_module (id, {md with md_attributes = - (Location.mknoloc "...", Parsetree.PStr []) - :: md.md_attributes}, - rs) + Sig_module (id, pres, md, rs, priv) -> + let attribute = + Ast_helper.Attr.mk + (Location.mknoloc "...") + (Parsetree.PStr []) + in + Sig_module (id, pres, {md with md_attributes = + attribute :: md.md_attributes}, + rs, priv) (*| Sig_modtype (id, Modtype_manifest mty) -> Sig_modtype (id, Modtype_manifest (trim_modtype mty))*) | item -> item) @@ -531,7 +540,7 @@ let () = reg_show_prim "show_val" (fun env loc id lid -> let _path, desc = Typetexp.find_value env loc lid in - [ Sig_value (id, desc) ] + [ Sig_value (id, desc, Exported) ] ) "Print the signature of the corresponding value." @@ -539,7 +548,7 @@ let () = reg_show_prim "show_type" (fun env loc id lid -> let _path, desc = Typetexp.find_type env loc lid in - [ Sig_type (id, desc, Trec_not) ] + [ Sig_type (id, desc, Trec_not, Exported) ] ) "Print the signature of the corresponding type constructor." @@ -562,7 +571,7 @@ let () = Types.ext_loc = desc.cstr_loc; Types.ext_attributes = desc.cstr_attributes; } in - [Sig_typext (id, ext, Text_exception)] + [Sig_typext (id, ext, Text_exception, Exported)] ) "Print the signature of the corresponding exception." @@ -572,10 +581,11 @@ let () = let rec accum_aliases path acc = let md = Env.find_module path env in let acc = - Sig_module (id, {md with md_type = trim_signature md.md_type}, - Trec_not) :: acc in + Sig_module (id, Mp_present, + {md with md_type = trim_signature md.md_type}, + Trec_not, Exported) :: acc in match md.md_type with - | Mty_alias(_, path) -> accum_aliases path acc + | Mty_alias path -> accum_aliases path acc | Mty_ident _ | Mty_signature _ | Mty_functor _ -> List.rev acc in @@ -588,7 +598,7 @@ let () = reg_show_prim "show_module_type" (fun env loc id lid -> let _path, desc = Typetexp.find_modtype env loc lid in - [ Sig_modtype (id, desc) ] + [ Sig_modtype (id, desc, Exported) ] ) "Print the signature of the corresponding module type." @@ -596,7 +606,7 @@ let () = reg_show_prim "show_class" (fun env loc id lid -> let _path, desc = Typetexp.find_class env loc lid in - [ Sig_class (id, desc, Trec_not) ] + [ Sig_class (id, desc, Trec_not, Exported) ] ) "Print the signature of the corresponding class." @@ -604,7 +614,7 @@ let () = reg_show_prim "show_class_type" (fun env loc id lid -> let _path, desc = Typetexp.find_class_type env loc lid in - [ Sig_class_type (id, desc, Trec_not) ] + [ Sig_class_type (id, desc, Trec_not, Exported) ] ) "Print the signature of the corresponding class type." diff --git a/toplevel/toploop.ml b/toplevel/toploop.ml index bd8720a6..1326d060 100644 --- a/toplevel/toploop.ml +++ b/toplevel/toploop.ml @@ -15,15 +15,14 @@ (* The interactive toplevel loop *) -open Path open Format -open Config open Misc open Parsetree open Types open Typedtree open Outcometree open Ast_helper +module String = Misc.Stdlib.String type directive_fun = | Directive_none of (unit -> unit) @@ -39,46 +38,58 @@ type directive_info = { (* The table of toplevel value bindings and its accessors *) -module StringMap = Map.Make(String) - -let toplevel_value_bindings : Obj.t StringMap.t ref = ref StringMap.empty +let toplevel_value_bindings : Obj.t String.Map.t ref = ref String.Map.empty let getvalue name = try - StringMap.find name !toplevel_value_bindings + String.Map.find name !toplevel_value_bindings with Not_found -> fatal_error (name ^ " unbound at toplevel") let setvalue name v = - toplevel_value_bindings := StringMap.add name v !toplevel_value_bindings + toplevel_value_bindings := String.Map.add name v !toplevel_value_bindings (* Return the value referred to by a path *) -let rec eval_path = function - | Pident id -> +let rec eval_address = function + | Env.Aident id -> if Ident.persistent id || Ident.global id then Symtable.get_global_value id else begin let name = Translmod.toplevel_name id in try - StringMap.find name !toplevel_value_bindings + String.Map.find name !toplevel_value_bindings with Not_found -> raise (Symtable.Error(Symtable.Undefined_global name)) end - | Pdot(p, _s, pos) -> - Obj.field (eval_path p) pos - | Papply _ -> - fatal_error "Toploop.eval_path" + | Env.Adot(p, pos) -> + Obj.field (eval_address p) pos + +let eval_path find env path = + match find path env with + | addr -> eval_address addr + | exception Not_found -> + fatal_error ("Cannot find address for: " ^ (Path.name path)) + +let eval_module_path env path = + eval_path Env.find_module_address env path + +let eval_value_path env path = + eval_path Env.find_value_address env path -let eval_path env path = - eval_path (Env.normalize_path (Some Location.none) env path) +let eval_extension_path env path = + eval_path Env.find_constructor_address env path + +let eval_class_path env path = + eval_path Env.find_class_address env path (* To print values *) module EvalPath = struct type valu = Obj.t exception Error - let eval_path env p = try eval_path env p with Symtable.Error _ -> raise Error + let eval_address addr = + try eval_address addr with Symtable.Error _ -> raise Error let same_value v1 v2 = (v1 == v2) end @@ -117,14 +128,15 @@ let remove_printer = Printer.remove_printer let parse_toplevel_phrase = ref Parse.toplevel_phrase let parse_use_file = ref Parse.use_file -let print_location = Location.print_error (* FIXME change back to print *) -let print_error = Location.print_error +let print_location = Location.print_loc +let print_error = Location.print_report let print_warning = Location.print_warning let input_name = Location.input_name let parse_mod_use_file name lb = let modname = - String.capitalize_ascii (Filename.chop_extension (Filename.basename name)) + String.capitalize_ascii + (Filename.remove_extension (Filename.basename name)) in let items = List.concat @@ -141,10 +153,26 @@ let parse_mod_use_file name lb = ] ] -(* Hooks for initialization *) +(* Hook for initialization *) let toplevel_startup_hook = ref (fun () -> ()) +type event = .. +type event += + | Startup + | After_setup + +let hooks = ref [] + +let add_hook f = hooks := f :: !hooks + +let () = + add_hook (function + | Startup -> !toplevel_startup_hook () + | _ -> ()) + +let run_hooks hook = List.iter (fun f -> f hook) !hooks + (* Load in-core and execute a lambda term *) let may_trace = ref false (* Global lock on tracing *) @@ -165,34 +193,26 @@ let load_lambda ppf lam = fprintf ppf "%a%a@." Printinstr.instrlist init_code Printinstr.instrlist fun_code; - let (code, code_size, reloc, events) = + let (code, reloc, events) = Emitcode.to_memory init_code fun_code in - Meta.add_debug_info code code_size [| events |]; let can_free = (fun_code = []) in let initial_symtable = Symtable.current_state() in Symtable.patch_object code reloc; Symtable.check_global_initialized reloc; Symtable.update_global_table(); let initial_bindings = !toplevel_value_bindings in + let bytecode, closure = Meta.reify_bytecode code [| events |] None in try may_trace := true; - let retval = (Meta.reify_bytecode code code_size) () in + let retval = closure () in may_trace := false; - if can_free then begin - Meta.remove_debug_info code; - Meta.static_release_bytecode code code_size; - Meta.static_free code; - end; + if can_free then Meta.release_bytecode bytecode; Result retval with x -> may_trace := false; + if can_free then Meta.release_bytecode bytecode; record_backtrace (); - if can_free then begin - Meta.remove_debug_info code; - Meta.static_release_bytecode code code_size; - Meta.static_free code; - end; toplevel_value_bindings := initial_bindings; (* PR#6211 *) Symtable.restore_state initial_symtable; Exception x @@ -202,7 +222,7 @@ let load_lambda ppf lam = let pr_item = Printtyp.print_items (fun env -> function - | Sig_value(id, {val_kind = Val_reg; val_type}) -> + | Sig_value(id, {val_kind = Val_reg; val_type}, _) -> Some (outval_of_value env (getvalue (Translmod.toplevel_name id)) val_type) | _ -> None @@ -248,9 +268,9 @@ let execute_phrase print_outcome ppf phr = | Ptop_def sstr -> let oldenv = !toplevel_env in Typecore.reset_delayed_checks (); - let (str, sg, newenv) = Typemod.type_toplevel_phrase oldenv sstr in + let (str, sg, sn, newenv) = Typemod.type_toplevel_phrase oldenv sstr in if !Clflags.dump_typedtree then Printtyped.implementation ppf str; - let sg' = Typemod.simplify_signature sg in + let sg' = Typemod.Signature_names.simplify newenv sn sg in ignore (Includemod.signatures oldenv sg sg'); Typecore.force_delayed_checks (); let lam = Translmod.transl_toplevel_definition str in @@ -280,7 +300,7 @@ let execute_phrase print_outcome ppf phr = Ophr_eval (outv, ty) | [] -> Ophr_signature [] - | _ -> Ophr_signature (pr_item newenv sg')) + | _ -> Ophr_signature (pr_item oldenv sg')) else Ophr_signature [] | Exception exn -> toplevel_env := oldenv; @@ -307,7 +327,7 @@ let execute_phrase print_outcome ppf phr = with x -> toplevel_env := oldenv; raise x end - | Ptop_dir(dir_name, dir_arg) -> + | Ptop_dir {pdir_name = {Location.txt = dir_name}; pdir_arg } -> let d = try Some (Hashtbl.find directive_table dir_name) with Not_found -> None @@ -322,10 +342,10 @@ let execute_phrase print_outcome ppf phr = fprintf ppf "@."; false | Some d -> - match d, dir_arg with - | Directive_none f, Pdir_none -> f (); true - | Directive_string f, Pdir_string s -> f s; true - | Directive_int f, Pdir_int (n,None) -> + match d, pdir_arg with + | Directive_none f, None -> f (); true + | Directive_string f, Some {pdira_desc = Pdir_string s} -> f s; true + | Directive_int f, Some {pdira_desc = Pdir_int (n,None) } -> begin match Int_literal_converter.int n with | n -> f n; true | exception _ -> @@ -334,12 +354,12 @@ let execute_phrase print_outcome ppf phr = dir_name; false end - | Directive_int _, Pdir_int (_, Some _) -> + | Directive_int _, Some {pdira_desc = Pdir_int (_, Some _)} -> fprintf ppf "Wrong integer literal for directive `%s'.@." dir_name; false - | Directive_ident f, Pdir_ident lid -> f lid; true - | Directive_bool f, Pdir_bool b -> f b; true + | Directive_ident f, Some {pdira_desc = Pdir_ident lid} -> f lid; true + | Directive_bool f, Some {pdira_desc = Pdir_bool b} -> f b; true | _ -> fprintf ppf "Wrong type of argument for directive `%s'.@." dir_name; @@ -379,7 +399,7 @@ let use_file ppf wrap_mod name = if name = "" then ("(stdin)", stdin, false) else begin - let filename = find_in_path !Config.load_path name in + let filename = Load_path.find name in let ic = open_in_bin filename in (filename, ic, true) end @@ -390,7 +410,9 @@ let use_file ppf wrap_mod name = (* Skip initial #! line if any *) Lexer.skip_hash_bang lb; let success = - protect_refs [ R (Location.input_name, filename) ] (fun () -> + protect_refs [ R (Location.input_name, filename); + R (Location.input_lexbuf, Some lb); ] + (fun () -> try List.iter (fun ph -> @@ -421,12 +443,12 @@ let first_line = ref true let got_eof = ref false;; let read_input_default prompt buffer len = - output_string Pervasives.stdout prompt; flush Pervasives.stdout; + output_string stdout prompt; flush stdout; let i = ref 0 in try while true do if !i >= len then raise Exit; - let c = input_char Pervasives.stdin in + let c = input_char stdin in Bytes.set buffer !i c; incr i; if c = '\n' then raise Exit; @@ -467,7 +489,6 @@ let _ = if !Sys.interactive then (* PR#6108 *) invalid_arg "The ocamltoplevel.cma library from compiler-libs \ cannot be loaded inside the OCaml toplevel"; - Clflags.debug := true; Sys.interactive := true; let crc_intfs = Symtable.init_toplevel() in Compmisc.init_path false; @@ -497,11 +518,19 @@ let set_paths () = (* Add whatever -I options have been specified on the command line, but keep the directories that user code linked in with ocamlmktop may have added to load_path. *) - load_path := !load_path @ [Filename.concat Config.standard_library "camlp4"]; - load_path := "" :: List.rev (!Compenv.last_include_dirs @ - !Clflags.include_dirs @ - !Compenv.first_include_dirs) @ !load_path; - Dll.add_path !load_path + let expand = Misc.expand_directory Config.standard_library in + let current_load_path = Load_path.get_paths () in + let load_path = List.concat [ + [ "" ]; + List.map expand (List.rev !Compenv.first_include_dirs); + List.map expand (List.rev !Clflags.include_dirs); + List.map expand (List.rev !Compenv.last_include_dirs); + current_load_path; + [expand "+camlp4"]; + ] + in + Load_path.init load_path; + Dll.add_path load_path let initialize_toplevel_env () = toplevel_env := Compmisc.initial_env() @@ -511,6 +540,7 @@ let initialize_toplevel_env () = exception PPerror let loop ppf = + Clflags.debug := true; Location.formatter_for_warnings := ppf; if not !Clflags.noversion then fprintf ppf " OCaml version %s@.@." Config.version; @@ -524,6 +554,7 @@ let loop ppf = Location.input_name := "//toplevel//"; Location.input_lexbuf := Some lb; Sys.catch_break true; + run_hooks After_setup; load_ocamlinit ppf; while true do let snap = Btype.snapshot () in @@ -562,6 +593,7 @@ let run_script ppf name args = Location.report_exception ppf exn; exit 2 end; Sys.interactive := false; + run_hooks After_setup; let explicit_name = (* Prevent use_silently from searching in the path. *) if name <> "" && Filename.is_implicit name diff --git a/toplevel/toploop.mli b/toplevel/toploop.mli index 7a478b3c..b78de712 100644 --- a/toplevel/toploop.mli +++ b/toplevel/toploop.mli @@ -71,7 +71,7 @@ val execute_phrase : bool -> formatter -> Parsetree.toplevel_phrase -> bool First bool says whether the values and types of the results should be printed. Uncaught exceptions are always printed. *) val preprocess_phrase : - formatter -> Parsetree.toplevel_phrase -> Parsetree.toplevel_phrase + formatter -> Parsetree.toplevel_phrase -> Parsetree.toplevel_phrase (* Preprocess the given toplevel phrase using regular and ppx preprocessors. Return the updated phrase. *) val use_file : formatter -> string -> bool @@ -81,7 +81,10 @@ val mod_use_file : formatter -> string -> bool [use_file] prints the types and values of the results. [use_silently] does not print them. [mod_use_file] wrap the file contents into a module. *) -val eval_path: Env.t -> Path.t -> Obj.t +val eval_module_path: Env.t -> Path.t -> Obj.t +val eval_value_path: Env.t -> Path.t -> Obj.t +val eval_extension_path: Env.t -> Path.t -> Obj.t +val eval_class_path: Env.t -> Path.t -> Obj.t (* Return the toplevel object referred to by the given path *) val record_backtrace : unit -> unit @@ -113,7 +116,7 @@ val max_printer_steps: int ref val parse_toplevel_phrase : (Lexing.lexbuf -> Parsetree.toplevel_phrase) ref val parse_use_file : (Lexing.lexbuf -> Parsetree.toplevel_phrase list) ref val print_location : formatter -> Location.t -> unit -val print_error : formatter -> Location.t -> unit +val print_error : formatter -> Location.error -> unit val print_warning : Location.t -> formatter -> Warnings.t -> unit val input_name : string ref @@ -138,10 +141,26 @@ val print_out_phrase : val read_interactive_input : (string -> bytes -> int -> int * bool) ref -(* Hooks for initialization *) +(* Hooks *) val toplevel_startup_hook : (unit -> unit) ref +type event = .. +type event += + | Startup + | After_setup + (* Just after the setup, when the toplevel is ready to evaluate user + input. This happens before the toplevel has evaluated any kind of + user input, in particular this happens before loading the + [.ocamlinit] file. *) + +val add_hook : (event -> unit) -> unit +(* Add a function that will be called at key points of the toplevel + initialization process. *) + +val run_hooks : event -> unit +(* Run all the registered hooks. *) + (* Used by Trace module *) val may_trace : bool ref diff --git a/toplevel/topmain.ml b/toplevel/topmain.ml index 4b1a06a6..ebe47cb8 100644 --- a/toplevel/topmain.ml +++ b/toplevel/topmain.ml @@ -33,9 +33,11 @@ let is_expanded pos = pos < !first_nonexpanded_pos let expand_position pos len = if pos < !first_nonexpanded_pos then - first_nonexpanded_pos := !first_nonexpanded_pos + len (* Shift the position *) + (* Shift the position *) + first_nonexpanded_pos := !first_nonexpanded_pos + len else - first_nonexpanded_pos := pos + len + 2 (* New last position *) + (* New last position *) + first_nonexpanded_pos := pos + len + 2 let prepare ppf = Toploop.set_paths (); @@ -46,7 +48,7 @@ let prepare ppf = in List.for_all (Topdirs.load_file ppf) objects in - !Toploop.toplevel_startup_hook (); + Toploop.run_hooks Toploop.Startup; res with x -> try Location.report_exception ppf x; false @@ -73,6 +75,7 @@ let file_argument name = (Array.length !argv - !current) in Compenv.readenv ppf Before_link; + Compmisc.read_clflags_from_env (); if prepare ppf && Toploop.run_script ppf name newargs then exit 0 else exit 2 @@ -98,10 +101,9 @@ module Options = Main_args.Make_bytetop_options (struct let set r () = r := true let clear r () = r := false - let _absname = set Location.absname - let _I dir = - let dir = Misc.expand_directory Config.standard_library dir in - include_dirs := dir :: !include_dirs + let _absname = set Clflags.absname + let _alert = Warnings.parse_alert_option + let _I dir = include_dirs := dir :: !include_dirs let _init s = init_file := Some s let _noinit = set noinit let _labels = clear classic @@ -114,6 +116,7 @@ module Options = Main_args.Make_bytetop_options (struct let _noprompt = set noprompt let _nopromptcont = set nopromptcont let _nostdlib = set no_std_include + let _nopervasives = set nopervasives let _open s = open_modules := s :: !open_modules let _ppx s = first_ppx := s :: !first_ppx let _principal = set principal @@ -129,7 +132,7 @@ module Options = Main_args.Make_bytetop_options (struct let _no_strict_formats = clear strict_formats let _unboxed_types = set unboxed_types let _no_unboxed_types = clear unboxed_types - let _unsafe = set fast + let _unsafe = set unsafe let _unsafe_string = set unsafe_string let _version () = print_version () let _vnum () = print_version_num () @@ -148,6 +151,8 @@ module Options = Main_args.Make_bytetop_options (struct let _dtimings () = profile_columns := [ `Time ] let _dprofile () = profile_columns := Profile.all_columns let _dinstr = set dump_instr + let _color = Misc.set_or_ignore color_reader.parse color + let _error_style = Misc.set_or_ignore error_style_reader.parse error_style let _args = wrap_expand Arg.read_arg let _args0 = wrap_expand Arg.read_arg0 @@ -155,6 +160,13 @@ module Options = Main_args.Make_bytetop_options (struct let anonymous s = file_argument s end);; +let () = + let extra_paths = + match Sys.getenv "OCAMLTOP_INCLUDE_PATH" with + | exception Not_found -> [] + | s -> Misc.split_path_contents s + in + Clflags.include_dirs := List.rev_append extra_paths !Clflags.include_dirs let main () = let ppf = Format.err_formatter in @@ -168,6 +180,7 @@ let main () = | Arg.Help msg -> Printf.printf "%s" msg; exit 0 end; Compenv.readenv ppf Before_link; + Compmisc.read_clflags_from_env (); if not (prepare ppf) then exit 2; Compmisc.init_path false; Toploop.loop Format.std_formatter diff --git a/typing/TODO.md b/typing/TODO.md new file mode 100755 index 00000000..4b559958 --- /dev/null +++ b/typing/TODO.md @@ -0,0 +1,79 @@ +TODO for the OCaml typechecker implementation +============================================= + +There is a consensus that the current implementation of the OCaml +typechecker is overly complex and fragile. A big rewriting "from +scratch" might be possible or desirable at some point, or not, but +incremental cleanup steps are certainly accessible and could bring the +current implementation in a better shape at a relatively small cost +and in a reasonably distant future. + +Goals of the cleanup: + + - Make the implementation more maintainable and less fragile. + + - Allow new contributors, or people involved in bigger rewriting + projects, to get familiar with the code base more easily. + + - Pave the way for future extensions or bigger structural changes to + the implementation. + +This file collects specific cleanup ideas which have been discussed +amongst maintainers. Having the list committed in the repo allows for +everyone to get an idea of planned tasks, refine them through Pull +Requests, suggest more cleanups, or even start working on specific +tasks (ideally after discussing it first with maintainers). + +Not all ideas have been thoroughly discussed, and there might not be a +consensus for all of them. + +- Make the level generator be part of `Env.t` instead of being global. + +- Introduce an abstraction boundary between "the type algebra" and + "the type checker" (at first between Ctype and Typecore) so that the + type checker is forced to go through a proper API to access/mutate + type nodes. This would make it impossible to "forget" a call + to `repr` and will allow further changes on the internal representation. + +- Tidy up Typeclass (use records instead of 14-tuples, avoid + "#"-encoding, etc). + +- Collect all global state of the type checker in a single place, + possibly a single reference to a persistent data structure + (e.g. maps instead of hashtables). + +- Get rid of Tsubst. With the unique ids on each type node, copying + can be implemented rather efficiently with a map. + +- Document row_desc, get rid of row_bound. + +- Implement union-find with a more abstract/persistent datastructure + (be careful about memory leaks with the naive approach of representing + links with a persistent heap). + +- Make the logic for record/constructor disambiguation more readable. + +- Tidy up destructive substitution. + +- Get rid of syntactic encodings (generating Parsetree fragments + during type-checking, cf optional arguments or classes). + +- Track "string literals" in the type-checker, which often act as + magic "internal" names which should be avoided. + +- Get rid of -annot. + +- Consider storing warning settings (+other context) as part of `Env.t`? + +- Parse attributes understood (e.g. the deprecated attribute) by the + compiler into a structured representation during type-checking. + +- Introduce a notion of syntactic "path-like location" to point to + allow pointing to AST fragments, and use that to implement "unused" + warnings in a less invasive and less imperative way. + +- Deprecate -nolabels, or even get rid of it? + +- Using e.g. bisect_ppx, monitor coverage of the typechecker + implementation while running the testsuite, and expand the testsuite + and/or kill dead code in the typechecker to increase coverage ratio. diff --git a/typing/btype.ml b/typing/btype.ml index c4f03ac3..0549d843 100644 --- a/typing/btype.ml +++ b/typing/btype.ml @@ -32,10 +32,10 @@ let print_raw = (**** Type level management ****) -let generic_level = 100000000 +let generic_level = Ident.highest_scope (* Used to mark a type during a traversal. *) -let lowest_level = 0 +let lowest_level = Ident.lowest_scope let pivot_level = 2 * lowest_level - 1 (* pivot_level - lowest_level < lowest_level *) @@ -44,7 +44,7 @@ let pivot_level = 2 * lowest_level - 1 let new_id = ref (-1) let newty2 level desc = - incr new_id; { desc; level; scope = None; id = !new_id } + incr new_id; { desc; level; scope = lowest_level; id = !new_id } let newgenty desc = newty2 generic_level desc let newgenvar ?name () = newgenty (Tvar name) (* @@ -72,7 +72,7 @@ type change = Ctype of type_expr * type_desc | Ccompress of type_expr * type_desc * type_desc | Clevel of type_expr * int - | Cscope of type_expr * int option + | Cscope of type_expr * int | Cname of (Path.t * type_expr list) option ref * (Path.t * type_expr list) option | Crow of row_field option ref * row_field option @@ -210,7 +210,7 @@ let proxy ty = (**** Utilities for fixed row private types ****) -let row_of_type t = +let row_of_type t = match (repr t).desc with Tobject(t,_) -> let rec get_row t = @@ -235,7 +235,7 @@ let is_constr_row ~allow_ident t = match t.desc with Tconstr (Path.Pident id, _, _) when allow_ident -> is_row_name (Ident.name id) - | Tconstr (Path.Pdot (_, s, _), _, _) -> is_row_name s + | Tconstr (Path.Pdot (_, s), _, _) -> is_row_name s | _ -> false @@ -243,37 +243,61 @@ let is_constr_row ~allow_ident t = (* Utilities for type traversal *) (**********************************) -let rec iter_row f row = - List.iter - (fun (_, fi) -> - match row_field_repr fi with - | Rpresent(Some ty) -> f ty - | Reither(_, tl, _, _) -> List.iter f tl - | _ -> ()) - row.row_fields; +let rec fold_row f init row = + let result = + List.fold_left + (fun init (_, fi) -> + match row_field_repr fi with + | Rpresent(Some ty) -> f init ty + | Reither(_, tl, _, _) -> List.fold_left f init tl + | _ -> init) + init + row.row_fields + in match (repr row.row_more).desc with - Tvariant row -> iter_row f row + Tvariant row -> fold_row f result row | Tvar _ | Tunivar _ | Tsubst _ | Tconstr _ | Tnil -> - Misc.may (fun (_,l) -> List.iter f l) row.row_name + begin match + Misc.may_map (fun (_,l) -> List.fold_left f result l) row.row_name + with + | None -> result + | Some result -> result + end | _ -> assert false -let iter_type_expr f ty = +let iter_row f row = + fold_row (fun () v -> f v) () row + +let fold_type_expr f init ty = match ty.desc with - Tvar _ -> () - | Tarrow (_, ty1, ty2, _) -> f ty1; f ty2 - | Ttuple l -> List.iter f l - | Tconstr (_, l, _) -> List.iter f l + Tvar _ -> init + | Tarrow (_, ty1, ty2, _) -> + let result = f init ty1 in + f result ty2 + | Ttuple l -> List.fold_left f init l + | Tconstr (_, l, _) -> List.fold_left f init l | Tobject(ty, {contents = Some (_, p)}) - -> f ty; List.iter f p - | Tobject (ty, _) -> f ty - | Tvariant row -> iter_row f row; f (row_more row) - | Tfield (_, _, ty1, ty2) -> f ty1; f ty2 - | Tnil -> () - | Tlink ty -> f ty - | Tsubst ty -> f ty - | Tunivar _ -> () - | Tpoly (ty, tyl) -> f ty; List.iter f tyl - | Tpackage (_, _, l) -> List.iter f l + -> + let result = f init ty in + List.fold_left f result p + | Tobject (ty, _) -> f init ty + | Tvariant row -> + let result = fold_row f init row in + f result (row_more row) + | Tfield (_, _, ty1, ty2) -> + let result = f init ty1 in + f result ty2 + | Tnil -> init + | Tlink ty -> f init ty + | Tsubst ty -> f init ty + | Tunivar _ -> init + | Tpoly (ty, tyl) -> + let result = f init ty in + List.fold_left f result tyl + | Tpackage (_, _, l) -> List.fold_left f init l + +let iter_type_expr f ty = + fold_type_expr (fun () v -> f v) () ty let rec iter_abbrev f = function Mnil -> () @@ -325,13 +349,13 @@ let type_iterators = let it_signature it = List.iter (it.it_signature_item it) and it_signature_item it = function - Sig_value (_, vd) -> it.it_value_description it vd - | Sig_type (_, td, _) -> it.it_type_declaration it td - | Sig_typext (_, td, _) -> it.it_extension_constructor it td - | Sig_module (_, md, _) -> it.it_module_declaration it md - | Sig_modtype (_, mtd) -> it.it_modtype_declaration it mtd - | Sig_class (_, cd, _) -> it.it_class_declaration it cd - | Sig_class_type (_, ctd, _) -> it.it_class_type_declaration it ctd + Sig_value (_, vd, _) -> it.it_value_description it vd + | Sig_type (_, td, _, _) -> it.it_type_declaration it td + | Sig_typext (_, td, _, _) -> it.it_extension_constructor it td + | Sig_module (_, _, md, _, _) -> it.it_module_declaration it md + | Sig_modtype (_, mtd, _) -> it.it_modtype_declaration it mtd + | Sig_class (_, cd, _, _) -> it.it_class_declaration it cd + | Sig_class_type (_, ctd, _, _) -> it.it_class_type_declaration it ctd and it_value_description it vd = it.it_type_expr it vd.val_type and it_type_declaration it td = @@ -358,7 +382,7 @@ let type_iterators = it.it_path ctd.clty_path and it_module_type it = function Mty_ident p - | Mty_alias(_, p) -> it.it_path p + | Mty_alias p -> it.it_path p | Mty_signature sg -> it.it_signature it sg | Mty_functor (_, mto, mt) -> may (it.it_module_type it) mto; @@ -456,28 +480,49 @@ let rec copy_type_desc ?(keep_names=false) f = function (* Utilities for copying *) -let saved_desc = ref [] - (* Saved association of generic nodes with their description. *) - -let save_desc ty desc = - saved_desc := (ty, desc)::!saved_desc - -let saved_kinds = ref [] (* duplicated kind variables *) -let new_kinds = ref [] (* new kind variables *) -let dup_kind r = - (match !r with None -> () | Some _ -> assert false); - if not (List.memq r !new_kinds) then begin - saved_kinds := r :: !saved_kinds; - let r' = ref None in - new_kinds := r' :: !new_kinds; - r := Some (Fvar r') - end +module For_copy : sig + type copy_scope + + val save_desc: copy_scope -> type_expr -> type_desc -> unit + + val dup_kind: copy_scope -> field_kind option ref -> unit -(* Restored type descriptions. *) -let cleanup_types () = - List.iter (fun (ty, desc) -> ty.desc <- desc) !saved_desc; - List.iter (fun r -> r := None) !saved_kinds; - saved_desc := []; saved_kinds := []; new_kinds := [] + val with_scope: (copy_scope -> 'a) -> 'a +end = struct + type copy_scope = { + mutable saved_desc : (type_expr * type_desc) list; + (* Save association of generic nodes with their description. *) + + mutable saved_kinds: field_kind option ref list; + (* duplicated kind variables *) + + mutable new_kinds : field_kind option ref list; + (* new kind variables *) + } + + let save_desc copy_scope ty desc = + copy_scope.saved_desc <- (ty, desc) :: copy_scope.saved_desc + + let dup_kind copy_scope r = + assert (Option.is_none !r); + if not (List.memq r copy_scope.new_kinds) then begin + copy_scope.saved_kinds <- r :: copy_scope.saved_kinds; + let r' = ref None in + copy_scope.new_kinds <- r' :: copy_scope.new_kinds; + r := Some (Fvar r') + end + + (* Restore type descriptions. *) + let cleanup { saved_desc; saved_kinds; _ } = + List.iter (fun (ty, desc) -> ty.desc <- desc) saved_desc; + List.iter (fun r -> r := None) saved_kinds + + let with_scope f = + let scope = { saved_desc = []; saved_kinds = []; new_kinds = [] } in + let res = f scope in + cleanup scope; + res +end (* Mark a type. *) let rec mark_type ty = @@ -672,11 +717,15 @@ let link_type ty ty' = (* ; assert (check_memorized_abbrevs ()) *) (* ; check_expans [] ty' *) let set_level ty level = - if ty.id <= !last_snapshot then log_change (Clevel (ty, ty.level)); - ty.level <- level + if level <> ty.level then begin + if ty.id <= !last_snapshot then log_change (Clevel (ty, ty.level)); + ty.level <- level + end let set_scope ty scope = - if ty.id <= !last_snapshot then log_change (Cscope (ty, ty.scope)); - ty.scope <- scope + if scope <> ty.scope then begin + if ty.id <= !last_snapshot then log_change (Cscope (ty, ty.scope)); + ty.scope <- scope + end let set_univar rty ty = log_change (Cuniv (rty, !rty)); rty := Some ty let set_name nm v = diff --git a/typing/btype.mli b/typing/btype.mli index 630f2598..00d24745 100644 --- a/typing/btype.mli +++ b/typing/btype.mli @@ -90,8 +90,10 @@ val is_constr_row: allow_ident:bool -> type_expr -> bool val iter_type_expr: (type_expr -> unit) -> type_expr -> unit (* Iteration on types *) +val fold_type_expr: ('a -> type_expr -> 'a) -> 'a -> type_expr -> 'a val iter_row: (type_expr -> unit) -> row_desc -> unit (* Iteration on types in a row *) +val fold_row: ('a -> type_expr -> 'a) -> 'a -> row_desc -> 'a val iter_abbrev: (type_expr -> unit) -> abbrev_memo -> unit (* Iteration on types in an abbreviation list *) @@ -125,12 +127,25 @@ val copy_row: bool -> row_desc -> bool -> type_expr -> row_desc val copy_kind: field_kind -> field_kind -val save_desc: type_expr -> type_desc -> unit +module For_copy : sig + + type copy_scope + (* The private state that the primitives below are mutating, it should + remain scoped within a single [with_scope] call. + + While it is possible to circumvent that discipline in various + ways, you should NOT do that. *) + + val save_desc: copy_scope -> type_expr -> type_desc -> unit (* Save a type description *) -val dup_kind: field_kind option ref -> unit + + val dup_kind: copy_scope -> field_kind option ref -> unit (* Save a None field_kind, and make it point to a fresh Fvar *) -val cleanup_types: unit -> unit - (* Restore type descriptions *) + + val with_scope: (copy_scope -> 'a) -> 'a + (* [with_scope f] calls [f] and restores saved type descriptions + before returning its result. *) +end val lowest_level: int (* Marked type: ty.level < lowest_level *) @@ -198,7 +213,7 @@ val link_type: type_expr -> type_expr -> unit (* Set the desc field of [t1] to [Tlink t2], logging the old value if there is an active snapshot *) val set_level: type_expr -> int -> unit -val set_scope: type_expr -> int option -> unit +val set_scope: type_expr -> int -> unit val set_name: (Path.t * type_expr list) option ref -> (Path.t * type_expr list) option -> unit diff --git a/typing/cmi_format.ml b/typing/cmi_format.ml index 67795219..2c85a9b7 100644 --- a/typing/cmi_format.ml +++ b/typing/cmi_format.ml @@ -15,7 +15,7 @@ type pers_flags = | Rectypes - | Deprecated of string + | Alerts of string Misc.Stdlib.String.Map.t | Opaque | Unsafe_string diff --git a/typing/cmi_format.mli b/typing/cmi_format.mli index d36612b1..b42dc9c2 100644 --- a/typing/cmi_format.mli +++ b/typing/cmi_format.mli @@ -15,7 +15,7 @@ type pers_flags = | Rectypes - | Deprecated of string + | Alerts of string Misc.Stdlib.String.Map.t | Opaque | Unsafe_string diff --git a/typing/cmt_format.ml b/typing/cmt_format.ml index e0cc55ad..09c787d9 100644 --- a/typing/cmt_format.ml +++ b/typing/cmt_format.ml @@ -112,31 +112,29 @@ let output_cmt oc cmt = let read filename = (* Printf.fprintf stderr "Cmt_format.read %s\n%!" filename; *) let ic = open_in_bin filename in - try - let magic_number = read_magic_number ic in - let cmi, cmt = - if magic_number = Config.cmt_magic_number then - None, Some (input_cmt ic) - else if magic_number = Config.cmi_magic_number then - let cmi = Cmi_format.input_cmi ic in - let cmt = try - let magic_number = read_magic_number ic in - if magic_number = Config.cmt_magic_number then - let cmt = input_cmt ic in - Some cmt - else None - with _ -> None - in - Some cmi, cmt - else - raise(Cmi_format.Error(Cmi_format.Not_an_interface filename)) - in - close_in ic; -(* Printf.fprintf stderr "Cmt_format.read done\n%!"; *) - cmi, cmt - with e -> - close_in ic; - raise e + Misc.try_finally + ~always:(fun () -> close_in ic) + (fun () -> + let magic_number = read_magic_number ic in + let cmi, cmt = + if magic_number = Config.cmt_magic_number then + None, Some (input_cmt ic) + else if magic_number = Config.cmi_magic_number then + let cmi = Cmi_format.input_cmi ic in + let cmt = try + let magic_number = read_magic_number ic in + if magic_number = Config.cmt_magic_number then + let cmt = input_cmt ic in + Some cmt + else None + with _ -> None + in + Some cmi, cmt + else + raise(Cmi_format.Error(Cmi_format.Not_an_interface filename)) + in + cmi, cmt + ) let read_cmt filename = match read filename with @@ -183,7 +181,7 @@ let save_cmt filename modname binary_annots sourcefile initial_env cmi = cmt_args = Sys.argv; cmt_sourcefile = sourcefile; cmt_builddir = Location.rewrite_absolute_path (Sys.getcwd ()); - cmt_loadpath = !Config.load_path; + cmt_loadpath = Load_path.get_paths (); cmt_source_digest = source_digest; cmt_initial_env = if need_to_clear_env then keep_only_summary initial_env else initial_env; diff --git a/typing/ctype.ml b/typing/ctype.ml index ce4e584e..fb8f4c10 100644 --- a/typing/ctype.ml +++ b/typing/ctype.ml @@ -54,7 +54,91 @@ open Btype (**** Errors ****) -exception Unify of (type_expr * type_expr) list +module Unification_trace = struct + + type position = First | Second + let swap_position = function + | First -> Second + | Second -> First + + type desc = { t: type_expr; expanded: type_expr option } + type 'a diff = { got: 'a; expected: 'a} + + type 'a escape = + | Constructor of Path.t + | Univ of type_expr + (* The type_expr argument of [Univ] is always a [Tunivar _], + we keep a [type_expr] to track renaming in {!Printtyp} *) + | Self + | Module_type of Path.t + | Equation of 'a + + type variant = + | No_intersection + | No_tags of position * (Asttypes.label * row_field) list + | Incompatible_types_for of string + + type obj = + | Missing_field of position * string + | Abstract_row of position + | Self_cannot_be_closed + + type 'a elt = + | Diff of 'a diff + | Variant of variant + | Obj of obj + | Escape of {context:type_expr option; kind: 'a escape} + | Incompatible_fields of {name:string; diff:type_expr diff } + | Rec_occur of type_expr * type_expr + + type t = desc elt list + let short t = { t; expanded = None } + let map_diff f r = + (* ordering is often meaningful when dealing with type_expr *) + let got = f r.got in + let expected = f r.expected in + { got; expected} + let diff got expected = Diff (map_diff short {got;expected}) + + let map_elt f = function + | Diff x -> Diff (map_diff f x) + | Escape {kind=Equation x; context} -> Escape {kind=Equation(f x); context} + | Rec_occur (_,_) + | Escape {kind=(Univ _ | Self|Constructor _ | Module_type _ ); _} + | Variant _ | Obj _ + | Incompatible_fields _ as x -> x + let map f = List.map (map_elt f) + + + (* Convert desc to type_expr * type_expr *) + let flatten_desc f x = match x.expanded with + | None -> f x.t x.t + | Some expanded -> f x.t expanded + let flatten f = map (flatten_desc f) + + (* Permute the expected and actual values *) + let swap_diff x = { got = x.expected; expected = x.got } + let swap_elt = function + | Diff x -> Diff (swap_diff x) + | Incompatible_fields {name;diff} -> + Incompatible_fields { name; diff = swap_diff diff} + | Obj (Missing_field(pos,s)) -> Obj(Missing_field(swap_position pos,s)) + | Obj (Abstract_row pos) -> Obj(Abstract_row (swap_position pos)) + | x -> x + let swap x = List.map swap_elt x + + exception Unify of t + + let escape kind = Escape { kind; context = None} + let scope_escape x = Unify[escape (Equation (short x))] + let rec_occur x y = Unify[Rec_occur(x, y)] + let incompatible_fields name got expected = + Incompatible_fields {name; diff={got; expected} } + +end +module Trace = Unification_trace + +exception Unify = Trace.Unify exception Tags of label * label @@ -71,18 +155,12 @@ let () = | _ -> None ) -exception Subtype of - (type_expr * type_expr) list * (type_expr * type_expr) list +exception Subtype of Unification_trace.t * Unification_trace.t exception Cannot_expand exception Cannot_apply -exception Recursive_abbrev - -(* GADT: recursive abbrevs can appear as a result of local constraints *) -exception Unification_recursive_abbrev of (type_expr * type_expr) list - (**** Type level management ****) let current_level = ref 0 @@ -119,6 +197,9 @@ let end_def () = let (cl, nl) = List.hd !saved_level in saved_level := List.tl !saved_level; current_level := cl; nongen_level := nl +let create_scope () = + init_def (!current_level + 1); + !current_level let reset_global_level () = global_level := !current_level + 1 @@ -133,7 +214,7 @@ let restore_global_level gl = let is_object_type path = let name = match path with Path.Pident id -> Ident.name id - | Path.Pdot(_, s,_) -> s + | Path.Pdot(_, s) -> s | Path.Papply _ -> assert false in name.[0] = '#' @@ -207,23 +288,10 @@ let generate_equations = ref false let assume_injective = ref false let set_mode_pattern ~generate ~injective f = - let old_unification_mode = !umode - and old_gen = !generate_equations - and old_inj = !assume_injective in - try - umode := Pattern; - generate_equations := generate; - assume_injective := injective; - let ret = f () in - umode := old_unification_mode; - generate_equations := old_gen; - assume_injective := old_inj; - ret - with e -> - umode := old_unification_mode; - generate_equations := old_gen; - assume_injective := old_inj; - raise e + Misc.protect_refs + [Misc.R (umode, Pattern); + Misc.R (generate_equations, generate); + Misc.R (assume_injective, injective)] f (*** Checks for type definitions ***) @@ -328,8 +396,9 @@ let close_object ty = let ty = repr ty in match ty.desc with Tvar _ -> - link_type ty (newty2 ty.level Tnil) - | Tfield(lab, _, _, _) when lab = dummy_method -> raise (Unify []) + link_type ty (newty2 ty.level Tnil); true + | Tfield(lab, _, _, _) when lab = dummy_method -> + false | Tfield(_, _, _, ty') -> close ty' | _ -> assert false in @@ -642,9 +711,9 @@ let rec generalize_structure var_level ty = end end -let generalize_structure var_level ty = +let generalize_structure ty = simple_abbrevs := Mnil; - generalize_structure var_level ty + generalize_structure !current_level ty (* Generalize the spine of a function, if the level >= !current_level *) @@ -676,23 +745,6 @@ let forward_try_expand_once = (* Forward declaration *) Lower the levels of a type (assume [level] is not [generic_level]). *) -(* - The level of a type constructor must be greater than its binding - time. That way, a type constructor cannot escape the scope of its - definition, as would be the case in - let x = ref [] - module M = struct type t let _ = (x : t list ref) end - (without this constraint, the type system would actually be unsound.) -*) -let get_path_scope env p = - try - match (Env.find_type p env).type_newtype_level with - | None -> Path.binding_time p - | Some (x, _) -> x - with - | Not_found -> - (* no newtypes in predef *) - Path.binding_time p let rec normalize_package_path env p = let t = @@ -703,62 +755,69 @@ let rec normalize_package_path env p = | Some (Mty_ident p) -> normalize_package_path env p | Some (Mty_signature _ | Mty_functor _ | Mty_alias _) | None -> match p with - Path.Pdot (p1, s, n) -> + Path.Pdot (p1, s) -> (* For module aliases *) - let p1' = Env.normalize_path None env p1 in + let p1' = Env.normalize_module_path None env p1 in if Path.same p1 p1' then p else - normalize_package_path env (Path.Pdot (p1', s, n)) + normalize_package_path env (Path.Pdot (p1', s)) | _ -> p -let check_scope_escape level ty = - let rec aux ty = +let check_scope_escape env level ty = + let rec loop ty = let ty = repr ty in if ty.level >= lowest_level then begin ty.level <- pivot_level - ty.level; - begin match ty.scope with - Some lv -> - let var = newvar2 level in - if level < lv then raise (Unify [(ty,ty); (var, var)]) - | None -> () + if level < ty.scope then + raise(Trace.scope_escape ty); + begin match ty.desc with + | Tconstr (p, _, _) when level < Path.scope p -> + begin match !forward_try_expand_once env ty with + | ty' -> aux ty' + | exception Cannot_expand -> + raise Trace.(Unify [escape (Constructor p)]) + end + | Tpackage (p, nl, tl) when level < Path.scope p -> + let p' = normalize_package_path env p in + if Path.same p p' then raise Trace.(Unify [escape (Module_type p)]); + aux { ty with desc = Tpackage (p', nl, tl) } + | _ -> + iter_type_expr loop ty end; - iter_type_expr aux ty end - in - try - aux ty; + and aux ty = + loop ty; unmark_type ty - with Unify trace -> - let var = newvar2 level in - raise (Unify ((ty, ty) :: (var, var) :: trace)) + in + try aux ty; + with Unify [Trace.Escape x] -> + raise Trace.(Unify[Escape { x with context = Some ty }]) let update_scope scope ty = - match scope with - | None -> () - | Some lvl -> - let ty = repr ty in - let scope = - match ty.scope with - | None -> lvl - | Some lvl' -> max lvl lvl' - in - if ty.level < scope then raise (Unify [(ty, newvar2 ty.level)]); - set_scope ty (Some scope) + let ty = repr ty in + let scope = max scope ty.scope in + if ty.level < scope then raise (Trace.scope_escape ty); + set_scope ty scope + +(* Note: the level of a type constructor must be greater than its binding + time. That way, a type constructor cannot escape the scope of its + definition, as would be the case in + let x = ref [] + module M = struct type t let _ = (x : t list ref) end + (without this constraint, the type system would actually be unsound.) +*) let rec update_level env level expand ty = let ty = repr ty in if ty.level > level then begin - begin match ty.scope with - Some lv -> if level < lv then raise (Unify [(ty, newvar2 level)]) - | None -> () - end; + if level < ty.scope then raise (Trace.scope_escape ty); match ty.desc with - Tconstr(p, _tl, _abbrev) when level < get_path_scope env p -> + Tconstr(p, _tl, _abbrev) when level < Path.scope p -> (* Try first to replace an abbreviation by its expansion. *) begin try link_type ty (!forward_try_expand_once env ty); update_level env level expand ty with Cannot_expand -> - raise (Unify [(ty, newvar2 level)]) + raise Trace.(Unify [escape(Constructor p)]) end | Tconstr(_, _ :: _, _) when expand -> begin try @@ -768,19 +827,19 @@ let rec update_level env level expand ty = set_level ty level; iter_type_expr (update_level env level expand) ty end - | Tpackage (p, nl, tl) when level < Path.binding_time p -> + | Tpackage (p, nl, tl) when level < Path.scope p -> let p' = normalize_package_path env p in - if Path.same p p' then raise (Unify [(ty, newvar2 level)]); + if Path.same p p' then raise Trace.(Unify [escape (Module_type p)]); log_type ty; ty.desc <- Tpackage (p', nl, tl); update_level env level expand ty | Tobject(_, ({contents=Some(p, _tl)} as nm)) - when level < get_path_scope env p -> + when level < Path.scope p -> set_name nm None; update_level env level expand ty | Tvariant row -> let row = row_repr row in begin match row.row_name with - | Some (p, _tl) when level < get_path_scope env p -> + | Some (p, _tl) when level < Path.scope p -> log_type ty; ty.desc <- Tvariant {row with row_name = None} | _ -> () @@ -789,7 +848,7 @@ let rec update_level env level expand ty = iter_type_expr (update_level env level expand) ty | Tfield(lab, _, ty1, _) when lab = dummy_method && (repr ty1).level > level -> - raise (Unify [(ty1, newvar2 level)]) + raise Trace.(Unify [escape Self]) | _ -> set_level ty level; (* XXX what about abbreviations in Tconstr ? *) @@ -809,43 +868,47 @@ let update_level env level ty = update_level env level true ty end -(* Generalize and lower levels of contravariant branches simultaneously *) +(* Lower level of type variables inside contravariant branches *) -let rec generalize_expansive env var_level visited ty = +let rec lower_contravariant env var_level visited contra ty = let ty = repr ty in - if ty.level = generic_level || ty.level <= var_level then () else - if not (Hashtbl.mem visited ty.id) then begin - Hashtbl.add visited ty.id (); + let must_visit = + ty.level > var_level && + match Hashtbl.find visited ty.id with + | done_contra -> contra && not done_contra + | exception Not_found -> true + in + if must_visit then begin + Hashtbl.add visited ty.id contra; + let generalize_rec = lower_contravariant env var_level visited in match ty.desc with - Tconstr (path, tyl, abbrev) -> + Tvar _ -> if contra then set_level ty var_level + | Tconstr (path, tyl, abbrev) -> let variance = try (Env.find_type path env).type_variance - with Not_found -> List.map (fun _ -> Variance.may_inv) tyl in + with Not_found -> + (* See testsuite/tests/typing-missing-cmi-2 for an example *) + List.map (fun _ -> Variance.may_inv) tyl + in abbrev := Mnil; List.iter2 (fun v t -> if Variance.(mem May_weak v) - then generalize_structure var_level t - else generalize_expansive env var_level visited t) + then generalize_rec true t + else generalize_rec contra t) variance tyl | Tpackage (_, _, tyl) -> - List.iter (generalize_structure var_level) tyl + List.iter (generalize_rec true) tyl | Tarrow (_, t1, t2, _) -> - generalize_structure var_level t1; - generalize_expansive env var_level visited t2 + generalize_rec true t1; + generalize_rec contra t2 | _ -> - iter_type_expr (generalize_expansive env var_level visited) ty + iter_type_expr (generalize_rec contra) ty end -let generalize_expansive env ty = +let lower_contravariant env ty = simple_abbrevs := Mnil; - try - generalize_expansive env !nongen_level (Hashtbl.create 7) ty - with Unify ([_, ty'] as tr) -> - raise (Unify ((ty, ty') :: tr)) - -let generalize_global ty = generalize_structure !global_level ty -let generalize_structure ty = generalize_structure !current_level ty + lower_contravariant env !nongen_level (Hashtbl.create 7) false ty (* Correct the levels of type [ty]. *) let correct_levels ty = @@ -971,8 +1034,8 @@ let abbreviations = ref (ref Mnil) (* partial: we may not wish to copy the non generic types before we call type_pat *) -let rec copy ?partial ?keep_names ty = - let copy = copy ?partial ?keep_names in +let rec copy ?partial ?keep_names scope ty = + let copy = copy ?partial ?keep_names scope in let ty = repr ty in match ty.desc with Tsubst ty -> ty @@ -991,7 +1054,7 @@ let rec copy ?partial ?keep_names ty = in if forget <> generic_level then newty2 forget (Tvar None) else let desc = ty.desc in - save_desc ty desc; + For_copy.save_desc scope ty desc; let t = newvar() in (* Stub *) set_scope t ty.scope; ty.desc <- Tsubst t; @@ -1034,10 +1097,10 @@ let rec copy ?partial ?keep_names ty = match more.desc with Tsubst ty -> ty | Tconstr _ | Tnil -> - save_desc more more.desc; + For_copy.save_desc scope more more.desc; copy more | Tvar _ | Tunivar _ -> - save_desc more more.desc; + For_copy.save_desc scope more more.desc; if keep then more else newty more.desc | _ -> assert false in @@ -1081,7 +1144,7 @@ let rec copy ?partial ?keep_names ty = Fabsent -> Tlink (copy ty2) | Fpresent -> copy_type_desc copy desc | Fvar r -> - dup_kind r; + For_copy.dup_kind scope r; copy_type_desc copy desc end | Tobject (ty1, _) when partial <> None -> @@ -1090,8 +1153,6 @@ let rec copy ?partial ?keep_names ty = end; t -let simple_copy t = copy t - (**** Variants of instantiations ****) let instance ?partial sch = @@ -1100,14 +1161,7 @@ let instance ?partial sch = None -> None | Some keep -> Some (compute_univars sch, keep) in - let ty = copy ?partial sch in - cleanup_types (); - ty - -let instance_def sch = - let ty = copy sch in - cleanup_types (); - ty + For_copy.with_scope (fun scope -> copy ?partial scope sch) let generic_instance sch = let old = !current_level in @@ -1117,9 +1171,7 @@ let generic_instance sch = ty let instance_list schl = - let tyl = List.map (fun t -> copy t) schl in - cleanup_types (); - tyl + For_copy.with_scope (fun scope -> List.map (fun t -> copy scope t) schl) let reified_var_counter = ref Vars.empty let reset_reified_var_counter () = @@ -1136,7 +1188,7 @@ let get_new_abstract_name s = if index = 0 && s <> "" && s.[String.length s - 1] <> '$' then s else Printf.sprintf "%s%d" s index -let new_declaration newtype manifest = +let new_declaration expansion_scope manifest = { type_params = []; type_arity = 0; @@ -1144,51 +1196,59 @@ let new_declaration newtype manifest = type_private = Public; type_manifest = manifest; type_variance = []; - type_newtype_level = newtype; + type_is_newtype = true; + type_expansion_scope = expansion_scope; type_loc = Location.none; type_attributes = []; type_immediate = false; type_unboxed = unboxed_false_default_false; } +let existential_name cstr ty = match repr ty with + | {desc = Tvar (Some name)} -> "$" ^ cstr.cstr_name ^ "_'" ^ name + | _ -> "$" ^ cstr.cstr_name + let instance_constructor ?in_pattern cstr = - begin match in_pattern with - | None -> () - | Some (env, newtype_lev) -> - let process existential = - let decl = new_declaration (Some (newtype_lev, newtype_lev)) None in - let name = - match repr existential with - {desc = Tvar (Some name)} -> "$" ^ cstr.cstr_name ^ "_'" ^ name - | _ -> "$" ^ cstr.cstr_name + For_copy.with_scope (fun scope -> + begin match in_pattern with + | None -> () + | Some (env, expansion_scope) -> + let process existential = + let decl = new_declaration expansion_scope None in + let name = existential_name cstr existential in + let path = + Path.Pident + (Ident.create_scoped ~scope:expansion_scope + (get_new_abstract_name name)) + in + let new_env = Env.add_local_type path decl !env in + env := new_env; + let to_unify = newty (Tconstr (path,[],ref Mnil)) in + let tv = copy scope existential in + assert (is_Tvar tv); + link_type tv to_unify in - let path = Path.Pident (Ident.create (get_new_abstract_name name)) in - let new_env = Env.add_local_type path decl !env in - env := new_env; - let to_unify = newty (Tconstr (path,[],ref Mnil)) in - let tv = copy existential in - assert (is_Tvar tv); - link_type tv to_unify - in - List.iter process cstr.cstr_existentials - end; - let ty_res = copy cstr.cstr_res in - let ty_args = List.map simple_copy cstr.cstr_args in - cleanup_types (); - (ty_args, ty_res) + List.iter process cstr.cstr_existentials + end; + let ty_res = copy scope cstr.cstr_res in + let ty_args = List.map (copy scope) cstr.cstr_args in + (ty_args, ty_res) + ) let instance_parameterized_type ?keep_names sch_args sch = - let ty_args = List.map (fun t -> copy ?keep_names t) sch_args in - let ty = copy sch in - cleanup_types (); - (ty_args, ty) + For_copy.with_scope (fun scope -> + let ty_args = List.map (fun t -> copy ?keep_names scope t) sch_args in + let ty = copy scope sch in + (ty_args, ty) + ) let instance_parameterized_type_2 sch_args sch_lst sch = - let ty_args = List.map simple_copy sch_args in - let ty_lst = List.map simple_copy sch_lst in - let ty = copy sch in - cleanup_types (); - (ty_args, ty_lst, ty) + For_copy.with_scope (fun scope -> + let ty_args = List.map (copy scope) sch_args in + let ty_lst = List.map (copy scope) sch_lst in + let ty = copy scope sch in + (ty_args, ty_lst, ty) + ) let map_kind f = function | Type_abstract -> Type_abstract @@ -1211,36 +1271,44 @@ let map_kind f = function let instance_declaration decl = - let decl = - {decl with type_params = List.map simple_copy decl.type_params; - type_manifest = may_map simple_copy decl.type_manifest; - type_kind = map_kind simple_copy decl.type_kind; + For_copy.with_scope (fun scope -> + {decl with type_params = List.map (copy scope) decl.type_params; + type_manifest = may_map (copy scope) decl.type_manifest; + type_kind = map_kind (copy scope) decl.type_kind; } - in - cleanup_types (); + ) + +let generic_instance_declaration decl = + let old = !current_level in + current_level := generic_level; + let decl = instance_declaration decl in + current_level := old; decl let instance_class params cty = - let rec copy_class_type = - function - Cty_constr (path, tyl, cty) -> - Cty_constr (path, List.map simple_copy tyl, copy_class_type cty) + let rec copy_class_type scope = function + | Cty_constr (path, tyl, cty) -> + let tyl' = List.map (copy scope) tyl in + let cty' = copy_class_type scope cty in + Cty_constr (path, tyl', cty') | Cty_signature sign -> Cty_signature - {csig_self = copy sign.csig_self; + {csig_self = copy scope sign.csig_self; csig_vars = - Vars.map (function (m, v, ty) -> (m, v, copy ty)) sign.csig_vars; + Vars.map (function (m, v, ty) -> (m, v, copy scope ty)) + sign.csig_vars; csig_concr = sign.csig_concr; csig_inher = - List.map (fun (p,tl) -> (p, List.map simple_copy tl)) + List.map (fun (p,tl) -> (p, List.map (copy scope) tl)) sign.csig_inher} | Cty_arrow (l, ty, cty) -> - Cty_arrow (l, copy ty, copy_class_type cty) + Cty_arrow (l, copy scope ty, copy_class_type scope cty) in - let params' = List.map simple_copy params in - let cty' = copy_class_type cty in - cleanup_types (); - (params', cty') + For_copy.with_scope (fun scope -> + let params' = List.map (copy scope) params in + let cty' = copy_class_type scope cty in + (params', cty') + ) (**** Instantiation for types with free universal variables ****) @@ -1258,14 +1326,14 @@ let delayed_copy = ref [] (* Copy without sharing until there are no free univars left *) (* all free univars must be included in [visited] *) -let rec copy_sep fixed free bound visited ty = +let rec copy_sep cleanup_scope fixed free bound visited ty = let ty = repr ty in let univars = free ty in if TypeSet.is_empty univars then if ty.level <> generic_level then ty else let t = newvar () in delayed_copy := - lazy (t.desc <- Tlink (copy ty)) + lazy (t.desc <- Tlink (copy cleanup_scope ty)) :: !delayed_copy; t else try @@ -1280,7 +1348,7 @@ let rec copy_sep fixed free bound visited ty = Tarrow _ | Ttuple _ | Tvariant _ | Tconstr _ | Tobject _ | Tpackage _ -> (ty,(t,bound)) :: visited | _ -> visited in - let copy_rec = copy_sep fixed free bound visited in + let copy_rec = copy_sep cleanup_scope fixed free bound visited in t.desc <- begin match ty.desc with | Tvariant row0 -> @@ -1298,13 +1366,13 @@ let rec copy_sep fixed free bound visited ty = let bound = tl @ bound in let visited = List.map2 (fun ty t -> ty,(t,bound)) tl tl' @ visited in - Tpoly (copy_sep fixed free bound visited t1, tl') + Tpoly (copy_sep cleanup_scope fixed free bound visited t1, tl') | _ -> copy_type_desc copy_rec ty.desc end; t end -let instance_poly ?(keep_names=false) fixed univars sch = +let instance_poly' cleanup_scope ~keep_names fixed univars sch = let univars = List.map repr univars in let copy_var ty = match ty.desc with @@ -1314,23 +1382,28 @@ let instance_poly ?(keep_names=false) fixed univars sch = let vars = List.map copy_var univars in let pairs = List.map2 (fun u v -> u, (v, [])) univars vars in delayed_copy := []; - let ty = copy_sep fixed (compute_univars sch) [] pairs sch in + let ty = copy_sep cleanup_scope fixed (compute_univars sch) [] pairs sch in List.iter Lazy.force !delayed_copy; delayed_copy := []; - cleanup_types (); vars, ty +let instance_poly ?(keep_names=false) fixed univars sch = + For_copy.with_scope (fun cleanup_scope -> + instance_poly' cleanup_scope ~keep_names fixed univars sch + ) + let instance_label fixed lbl = - let ty_res = copy lbl.lbl_res in - let vars, ty_arg = - match repr lbl.lbl_arg with - {desc = Tpoly (ty, tl)} -> - instance_poly fixed tl ty - | _ -> - [], copy lbl.lbl_arg - in - cleanup_types (); - (vars, ty_arg, ty_res) + For_copy.with_scope (fun scope -> + let ty_res = copy scope lbl.lbl_res in + let vars, ty_arg = + match repr lbl.lbl_arg with + {desc = Tpoly (ty, tl)} -> + instance_poly' scope ~keep_names:false fixed tl ty + | _ -> + [], copy scope lbl.lbl_arg + in + (vars, ty_arg, ty_res) + ) (**** Instantiation with parameter substitution ****) @@ -1447,7 +1520,7 @@ let expand_abbrev_gen kind find_type_expansion env ty = match find_type_expansion path env with | exception Not_found -> (* another way to expand is to normalize the path itself *) - let path' = Env.normalize_path None env path in + let path' = Env.normalize_type_path None env path in if Path.same path path' then raise Cannot_expand else newty2 level (Tconstr (path', args, abbrev)) | (params, body, lv) -> @@ -1457,12 +1530,10 @@ let expand_abbrev_gen kind find_type_expansion env ty = (* For gadts, remember type as non exportable *) (* The ambiguous level registered for ty' should be the highest *) if !trace_gadt_instances then begin - match max lv ty.scope with - None -> () - | Some lv -> - if level < lv then raise (Unify [(ty, newvar2 level)]); - set_scope ty (Some lv); - set_scope ty' (Some lv) + let scope = max lv ty.scope in + if level < scope then raise (Trace.scope_escape ty); + set_scope ty scope; + set_scope ty' scope end; ty' end @@ -1670,7 +1741,9 @@ let occur env ty0 ty = merge type_changed old with exn -> merge type_changed old; - raise (match exn with Occur -> Unify [] | _ -> exn) + match exn with + | Occur -> raise (Trace.rec_occur ty0 ty) + | _ -> raise exn let occur_in env ty0 t = try occur env ty0 t; false with Unify _ -> true @@ -1765,7 +1838,8 @@ let occur_univar env ty = then match ty.desc with Tunivar _ -> - if not (TypeSet.mem ty bound) then raise (Unify [ty, newgenvar ()]) + if not (TypeSet.mem ty bound) then + raise Trace.(Unify [escape (Univ ty)]) | Tpoly (ty, tyl) -> let bound = List.fold_right TypeSet.add (List.map repr tyl) bound in occur_rec bound ty @@ -1783,10 +1857,10 @@ let occur_univar env ty = end | _ -> iter_type_expr (occur_rec bound) ty in - try - occur_rec TypeSet.empty ty; unmark_type ty - with exn -> - unmark_type ty; raise exn + Misc.try_finally (fun () -> + occur_rec TypeSet.empty ty + ) + ~always:(fun () -> unmark_type ty) (* Grouping univars by families according to their binders *) let add_univars = @@ -1817,7 +1891,7 @@ let univars_escape env univar_pairs vl ty = if List.exists (fun t -> TypeSet.mem (repr t) family) tl then () else occur t | Tunivar _ -> - if TypeSet.mem t family then raise Occur + if TypeSet.mem t family then raise Trace.(Unify [escape(Univ t)]) | Tconstr (_, [], _) -> () | Tconstr (p, tl, _) -> begin try @@ -1833,7 +1907,7 @@ let univars_escape env univar_pairs vl ty = iter_type_expr occur t end in - try occur ty; false with Occur -> true + occur ty (* Wrapper checking that no variable escapes and updating univar_pairs *) let enter_poly env univar_pairs t1 tl1 t2 tl2 f = @@ -1843,40 +1917,42 @@ let enter_poly env univar_pairs t1 tl1 t2 tl2 f = TypeSet.empty old_univars in let tl1 = List.map repr tl1 and tl2 = List.map repr tl2 in - if List.exists (fun t -> TypeSet.mem t known_univars) tl1 && - univars_escape env old_univars tl1 (newty(Tpoly(t2,tl2))) - || List.exists (fun t -> TypeSet.mem t known_univars) tl2 && - univars_escape env old_univars tl2 (newty(Tpoly(t1,tl1))) - then raise (Unify []); + if List.exists (fun t -> TypeSet.mem t known_univars) tl1 then + univars_escape env old_univars tl1 (newty(Tpoly(t2,tl2))); + if List.exists (fun t -> TypeSet.mem t known_univars) tl2 then + univars_escape env old_univars tl2 (newty(Tpoly(t1,tl1))); let cl1 = List.map (fun t -> t, ref None) tl1 and cl2 = List.map (fun t -> t, ref None) tl2 in univar_pairs := (cl1,cl2) :: (cl2,cl1) :: old_univars; - try let res = f t1 t2 in univar_pairs := old_univars; res - with exn -> univar_pairs := old_univars; raise exn + Misc.try_finally (fun () -> f t1 t2) + ~always:(fun () -> univar_pairs := old_univars) let univar_pairs = ref [] (* assumption: [ty] is fully generalized. *) let reify_univars ty = - let rec subst_univar vars ty = + let rec subst_univar scope vars ty = let ty = repr ty in if ty.level >= lowest_level then begin ty.level <- pivot_level - ty.level; match ty.desc with | Tvar name -> - save_desc ty ty.desc; + For_copy.save_desc scope ty ty.desc; let t = newty2 ty.level (Tunivar name) in vars := t :: !vars; ty.desc <- Tsubst t | _ -> - iter_type_expr (subst_univar vars) ty + iter_type_expr (subst_univar scope vars) ty end in let vars = ref [] in - subst_univar vars ty; - unmark_type ty; - let ty = copy ty in - cleanup_types (); + let ty = + For_copy.with_scope (fun scope -> + subst_univar scope vars ty; + unmark_type ty; + copy scope ty + ) + in newty2 ty.level (Tpoly(repr ty, !vars)) @@ -1896,17 +1972,10 @@ let rec has_cached_expansion p abbrev = (* +++ Move it to some other place ? *) let expand_trace env trace = - List.fold_right - (fun (t1, t2) rem -> - (repr t1, full_expand env t1)::(repr t2, full_expand env t2)::rem) - trace [] - -(* build a dummy variant type *) -let mkvariant fields closed = - newgenty - (Tvariant - {row_fields = fields; row_closed = closed; row_more = newvar(); - row_bound = (); row_fixed = false; row_name = None }) + let expand_desc x = match x.Trace.expanded with + | None -> Trace.{ t = repr x.t; expanded= Some(full_expand env x.t) } + | Some _ -> x in + Unification_trace.map expand_desc trace (**** Unification ****) @@ -1949,26 +2018,31 @@ let deep_occur t0 ty = information is indeed lost, but it probably does not worth it. *) -let newtype_level = ref None +let gadt_equations_level = ref None -let get_newtype_level () = - match !newtype_level with +let get_gadt_equations_level () = + match !gadt_equations_level with | None -> assert false | Some x -> x + (* a local constraint can be added only if the rhs of the constraint does not contain any Tvars. They need to be removed using this function *) let reify env t = - let newtype_level = get_newtype_level () in + let fresh_constr_scope = get_gadt_equations_level () in let create_fresh_constr lev name = - let decl = new_declaration (Some (newtype_level, newtype_level)) None in let name = match name with Some s -> "$'"^s | _ -> "$" in - let path = Path.Pident (Ident.create (get_new_abstract_name name)) in + let path = + Path.Pident + (Ident.create_scoped ~scope:fresh_constr_scope + (get_new_abstract_name name)) + in + let decl = new_declaration fresh_constr_scope None in let new_env = Env.add_local_type path decl !env in let t = newty2 lev (Tconstr (path,[],ref Mnil)) in env := new_env; - t + path, t in let visited = ref TypeSet.empty in let rec iterator ty = @@ -1977,10 +2051,10 @@ let reify env t = visited := TypeSet.add ty !visited; match ty.desc with Tvar o -> - let t = create_fresh_constr ty.level o in + let path, t = create_fresh_constr ty.level o in link_type ty t; - if ty.level < newtype_level then - raise (Unify [t, newvar2 ty.level]) + if ty.level < fresh_constr_scope then + raise Trace.(Unify [escape (Constructor path)]) | Tvariant r -> let r = row_repr r in if not (static_row r) then begin @@ -1988,12 +2062,12 @@ let reify env t = let m = r.row_more in match m.desc with Tvar o -> - let t = create_fresh_constr m.level o in + let path, t = create_fresh_constr m.level o in let row = {r with row_fields=[]; row_fixed=true; row_more = t} in link_type m (newty2 m.level (Tvariant row)); - if m.level < newtype_level then - raise (Unify [t, newvar2 m.level]) + if m.level < fresh_constr_scope then + raise Trace.(Unify [escape (Constructor path)]) | _ -> assert false end; iter_row iterator r @@ -2008,14 +2082,14 @@ let reify env t = let is_newtype env p = try let decl = Env.find_type p env in - decl.type_newtype_level <> None && + decl.type_expansion_scope <> Btype.lowest_level && decl.type_kind = Type_abstract && decl.type_private = Public with Not_found -> false let non_aliasable p decl = (* in_pervasives p || (subsumed by in_current_module) *) - in_current_module p && decl.type_newtype_level = None + in_current_module p && not decl.type_is_newtype let is_instantiable env p = try @@ -2258,22 +2332,18 @@ let find_lowest_level ty = end in find ty; unmark_type ty; !lowest -let find_expansion_level env path = - (* always guarded by a call to [is_newtype], so we *always* have a newtype - level. *) - match (Env.find_type path env).type_newtype_level with - | Some (_, x) -> x - | None -> assert false +let find_expansion_scope env path = + (Env.find_type path env).type_expansion_scope let add_gadt_equation env source destination = (* Format.eprintf "@[add_gadt_equation %s %a@]@." (Path.name source) !Btype.print_raw destination; *) if local_non_recursive_abbrev !env source destination then begin let destination = duplicate_type destination in - let source_lev = get_path_scope !env source in - let decl = - new_declaration (Some (source_lev, get_newtype_level ())) (Some destination) + let expansion_scope = + max (Path.scope source) (get_gadt_equations_level ()) in + let decl = new_declaration expansion_scope (Some destination) in env := Env.add_local_type source decl !env; cleanup_abbrev () end @@ -2301,7 +2371,7 @@ let rec concat_longident lid1 = | Lapply (lid2, lid) -> Lapply (concat_longident lid1 lid2, lid) let nondep_instance env level id ty = - let ty = !nondep_type' env id ty in + let ty = !nondep_type' env [id] ty in if level = generic_level then duplicate_type ty else let old = !current_level in current_level := level; @@ -2312,8 +2382,19 @@ let nondep_instance env level id ty = (* Find the type paths nl1 in the module type mty2, and add them to the list (nl2, tl2). raise Not_found if impossible *) let complete_type_list ?(allow_absent=false) env nl1 lv2 mty2 nl2 tl2 = - let id2 = Ident.create "Pkg" in - let env' = Env.add_module id2 mty2 env in + (* This is morally WRONG: we're adding a (dummy) module without a scope in the + environment. However no operation which cares about levels/scopes is going + to happen while this module exists. + The only operations that happen are: + - Env.lookup_type + - Env.find_type + - nondep_instance + None of which check the scope. + + It'd be nice if we avoided creating such temporary dummy modules and broken + environments though. *) + let id2 = Ident.create_local "Pkg" in + let env' = Env.add_module id2 Mp_present mty2 env in let rec complete nl1 ntl2 = match nl1, ntl2 with [], _ -> ntl2 @@ -2420,7 +2501,7 @@ let rec unify (env:Env.t ref) t1 t2 = && is_newtype !env p1 && is_newtype !env p2 -> (* Do not use local constraints more than necessary *) begin try - if find_expansion_level !env p1 > find_expansion_level !env p2 then + if find_expansion_scope !env p1 > find_expansion_scope !env p2 then unify env t1 (try_expand_once !env t2) else unify env (try_expand_once !env t1) t2 @@ -2433,7 +2514,7 @@ let rec unify (env:Env.t ref) t1 t2 = reset_trace_gadt_instances reset_tracing; with Unify trace -> reset_trace_gadt_instances reset_tracing; - raise (Unify ((t1, t2)::trace)) + raise( Unify (Trace.diff t1 t2 :: trace) ) and unify2 env t1 t2 = (* Second step: expansion of abbreviations *) @@ -2464,7 +2545,7 @@ and unify2 env t1 t2 = unify3 env t1 t1' t2 t2' else try unify3 env t2 t2' t1 t1' with Unify trace -> - raise (Unify (List.map (fun (x, y) -> (y, x)) trace)) + raise (Unify (Trace.swap trace)) and unify3 env t1 t1' t2 t2' = (* Third step: truly unification *) @@ -2540,7 +2621,7 @@ and unify3 env t1 t1' t2 t2' = when is_instantiable !env path && is_instantiable !env path' && !generate_equations -> let source, destination = - if get_path_scope !env path > get_path_scope !env path' + if Path.scope path > Path.scope path' then path , t2' else path', t1' in @@ -2586,7 +2667,13 @@ and unify3 env t1 t1' t2 t2' = set_kind r Fabsent; if d2 = Tnil then unify env rem t2' else unify env (newty2 rem.level Tnil) rem - | _ -> raise (Unify []) + | _ -> + if f = dummy_method then + raise (Unify Trace.[Obj Self_cannot_be_closed]) + else if d1 = Tnil then + raise (Unify Trace.[Obj(Missing_field (First, f))]) + else + raise (Unify Trace.[Obj(Missing_field (Second, f))]) end | (Tnil, Tnil) -> () @@ -2603,8 +2690,9 @@ and unify3 env t1 t1' t2 t2' = List.iter (reify env) (tl1 @ tl2); (* if !generate_equations then List.iter2 (mcomp !env) tl1 tl2 *) end - | (_, _) -> - raise (Unify []) + | (Tnil, Tconstr _ ) -> raise (Unify Trace.[Obj(Abstract_row Second)]) + | (Tconstr _, Tnil ) -> raise (Unify Trace.[Obj(Abstract_row First)]) + | (_, _) -> raise (Unify []) end; (* XXX Commentaires + changer "create_recursion" ||| Comments + change "create_recursion" *) @@ -2667,8 +2755,8 @@ and unify_fields env ty1 ty2 = (* Optimization *) end; unify env t1 t2 with Unify trace -> - raise (Unify ((newty (Tfield(n, k1, t1, newty Tnil)), - newty (Tfield(n, k2, t2, newty Tnil)))::trace))) + raise( Unify (Trace.incompatible_fields n t1 t2 :: trace) ) + ) pairs with exn -> log_type rest1; rest1.desc <- d1; @@ -2721,7 +2809,7 @@ and unify_row env row1 row2 = (fun (_,f1,f2) -> row_field_repr f1 = Rabsent || row_field_repr f2 = Rabsent) pairs - then raise (Unify [mkvariant [] true, mkvariant [] true]); + then raise Trace.( Unify [Variant No_intersection] ); let name = if row1.row_name <> None && (row1.row_closed || empty r2) && (not row2.row_closed || keep (fun f1 f2 -> f1, f2) && empty r1) @@ -2740,8 +2828,8 @@ and unify_row env row1 row2 = else rest in if rest <> [] && (row.row_closed || row_fixed row) || closed && row_fixed row && not row.row_closed then begin - let t1 = mkvariant [] true and t2 = mkvariant rest false in - raise (Unify [if row == row1 then (t1,t2) else (t2,t1)]) + let pos = if row == row1 then Trace.First else Trace.Second in + raise Trace.(Unify [Variant (No_tags(pos,rest))]) end; (* The following test is not principal... should rather use Tnil *) let rm = row_more row in @@ -2765,8 +2853,8 @@ and unify_row env row1 row2 = (fun (l,f1,f2) -> try unify_row_field env fixed1 fixed2 more l f1 f2 with Unify trace -> - raise (Unify ((mkvariant [l,f1] true, - mkvariant [l,f2] true) :: trace))) + raise Trace.( Unify( Variant (Incompatible_types_for l) :: trace )) + ) pairs; if static_row row1 then begin let rm = row_more row1 in @@ -2864,20 +2952,17 @@ let unify env ty1 ty2 = Unify trace -> undo_compress snap; raise (Unify (expand_trace !env trace)) - | Recursive_abbrev -> - undo_compress snap; - raise (Unification_recursive_abbrev (expand_trace !env [(ty1,ty2)])) -let unify_gadt ~newtype_level:lev (env:Env.t ref) ty1 ty2 = +let unify_gadt ~equations_level:lev (env:Env.t ref) ty1 ty2 = try univar_pairs := []; - newtype_level := Some lev; + gadt_equations_level := Some lev; set_mode_pattern ~generate:true ~injective:true (fun () -> unify env ty1 ty2); - newtype_level := None; + gadt_equations_level := None; TypePairs.clear unify_eq_set; with e -> - newtype_level := None; + gadt_equations_level := None; TypePairs.clear unify_eq_set; raise e @@ -2897,7 +2982,7 @@ let unify_var env t1 t2 = reset_trace_gadt_instances reset_tracing; with Unify trace -> reset_trace_gadt_instances reset_tracing; - let expanded_trace = expand_trace env ((t1,t2)::trace) in + let expanded_trace = expand_trace env @@ Trace.diff t1 t2 :: trace in raise (Unify expanded_trace) end | _ -> @@ -2995,7 +3080,7 @@ let filter_self_method env lab priv meths ty = try Meths.find lab !meths with Not_found -> - let pair = (Ident.create lab, ty') in + let pair = (Ident.create_local lab, ty') in meths := Meths.add lab pair !meths; pair @@ -3097,8 +3182,7 @@ let rec moregen inst_nongen type_pairs env t1 t2 = | (_, _) -> raise (Unify []) end - with Unify trace -> - raise (Unify ((t1, t2)::trace)) + with Unify trace -> raise( Unify ( Trace.diff t1 t2 :: trace ) ) and moregen_list inst_nongen type_pairs env tl1 tl2 = if List.length tl1 <> List.length tl2 then @@ -3116,8 +3200,11 @@ and moregen_fields inst_nongen type_pairs env ty1 ty2 = (fun (n, k1, t1, k2, t2) -> moregen_kind k1 k2; try moregen inst_nongen type_pairs env t1 t2 with Unify trace -> - raise (Unify ((newty (Tfield(n, k1, t1, rest2)), - newty (Tfield(n, k2, t2, rest2)))::trace))) + let e = Trace.diff + (newty (Tfield(n, k1, t1, rest2))) + (newty (Tfield(n, k2, t2, rest2))) in + raise( Unify ( e :: trace ) ) + ) pairs and moregen_kind k1 k2 = @@ -3366,8 +3453,7 @@ let rec eqtype rename type_pairs subst env t1 t2 = | (_, _) -> raise (Unify []) end - with Unify trace -> - raise (Unify ((t1, t2)::trace)) + with Unify trace -> raise ( Unify (Trace.diff t1 t2 :: trace) ) and eqtype_list rename type_pairs subst env tl1 tl2 = if List.length tl1 <> List.length tl2 then @@ -3394,8 +3480,11 @@ and eqtype_fields rename type_pairs subst env ty1 ty2 = (function (n, k1, t1, k2, t2) -> eqtype_kind k1 k2; try eqtype rename type_pairs subst env t1 t2 with Unify trace -> - raise (Unify ((newty (Tfield(n, k1, t1, rest2)), - newty (Tfield(n, k2, t2, rest2)))::trace))) + let e = Trace.diff + (newty (Tfield(n, k1, t1, rest2))) + (newty (Tfield(n, k2, t2, rest2))) in + raise ( Unify ( e :: trace ) ) + ) pairs and eqtype_kind k1 k2 = @@ -3445,8 +3534,9 @@ and eqtype_row rename type_pairs subst env row1 row2 = let eqtype_list rename type_pairs subst env tl1 tl2 = univar_pairs := []; let snap = Btype.snapshot () in - try eqtype_list rename type_pairs subst env tl1 tl2; backtrack snap - with exn -> backtrack snap; raise exn + Misc.try_finally + ~always:(fun () -> backtrack snap) + (fun () -> eqtype_list rename type_pairs subst env tl1 tl2) let eqtype rename type_pairs subst env t1 t2 = eqtype_list rename type_pairs subst env [t1] [t2] @@ -3467,11 +3557,11 @@ let equal env rename tyl1 tyl2 = type class_match_failure = CM_Virtual_class | CM_Parameter_arity_mismatch of int * int - | CM_Type_parameter_mismatch of Env.t * (type_expr * type_expr) list + | CM_Type_parameter_mismatch of Env.t * Unification_trace.t | CM_Class_type_mismatch of Env.t * class_type * class_type - | CM_Parameter_mismatch of Env.t * (type_expr * type_expr) list - | CM_Val_type_mismatch of string * Env.t * (type_expr * type_expr) list - | CM_Meth_type_mismatch of string * Env.t * (type_expr * type_expr) list + | CM_Parameter_mismatch of Env.t * Unification_trace.t + | CM_Val_type_mismatch of string * Env.t * Unification_trace.t + | CM_Meth_type_mismatch of string * Env.t * Unification_trace.t | CM_Non_mutable_value of string | CM_Non_concrete_value of string | CM_Missing_value of string @@ -3795,7 +3885,7 @@ let memq_warn t visited = let rec lid_of_path ?(hash="") = function Path.Pident id -> Longident.Lident (hash ^ Ident.name id) - | Path.Pdot (p1, s, _) -> + | Path.Pdot (p1, s) -> Longident.Ldot (lid_of_path p1, hash ^ s) | Path.Papply (p1, p2) -> Longident.Lapply (lid_of_path ~hash p1, lid_of_path p2) @@ -4018,8 +4108,8 @@ let rec subtype_rec env trace t1 t2 cstrs = (trace, t1, t2, !univar_pairs)::cstrs | (Tarrow(l1, t1, u1, _), Tarrow(l2, t2, u2, _)) when l1 = l2 || !Clflags.classic && not (is_optional l1 || is_optional l2) -> - let cstrs = subtype_rec env ((t2, t1)::trace) t2 t1 cstrs in - subtype_rec env ((u1, u2)::trace) u1 u2 cstrs + let cstrs = subtype_rec env (Trace.diff t2 t1::trace) t2 t1 cstrs in + subtype_rec env (Trace.diff u1 u2::trace) u1 u2 cstrs | (Ttuple tl1, Ttuple tl2) -> subtype_list env trace tl1 tl2 cstrs | (Tconstr(p1, [], _), Tconstr(p2, [], _)) when Path.same p1 p2 -> @@ -4040,9 +4130,9 @@ let rec subtype_rec env trace t1 t2 cstrs = if cn then (trace, newty2 t1.level (Ttuple[t1]), newty2 t2.level (Ttuple[t2]), !univar_pairs) :: cstrs - else subtype_rec env ((t1, t2)::trace) t1 t2 cstrs + else subtype_rec env (Trace.diff t1 t2::trace) t1 t2 cstrs else - if cn then subtype_rec env ((t2, t1)::trace) t2 t1 cstrs + if cn then subtype_rec env (Trace.diff t2 t1::trace) t2 t1 cstrs else cstrs) cstrs decl.type_variance (List.combine tl1 tl2) with Not_found -> @@ -4109,7 +4199,7 @@ and subtype_list env trace tl1 tl2 cstrs = if List.length tl1 <> List.length tl2 then subtype_error env trace; List.fold_left2 - (fun cstrs t1 t2 -> subtype_rec env ((t1, t2)::trace) t1 t2 cstrs) + (fun cstrs t1 t2 -> subtype_rec env (Trace.diff t1 t2::trace) t1 t2 cstrs) cstrs tl1 tl2 and subtype_fields env trace ty1 ty2 cstrs = @@ -4120,7 +4210,7 @@ and subtype_fields env trace ty1 ty2 cstrs = let cstrs = if rest2.desc = Tnil then cstrs else if miss1 = [] then - subtype_rec env ((rest1, rest2)::trace) rest1 rest2 cstrs + subtype_rec env (Trace.diff rest1 rest2::trace) rest1 rest2 cstrs else (trace, build_fields (repr ty1).level miss1 rest1, rest2, !univar_pairs) :: cstrs @@ -4133,7 +4223,7 @@ and subtype_fields env trace ty1 ty2 cstrs = List.fold_left (fun cstrs (_, _k1, t1, _k2, t2) -> (* These fields are always present *) - subtype_rec env ((t1, t2)::trace) t1 t2 cstrs) + subtype_rec env (Trace.diff t1 t2::trace) t1 t2 cstrs) cstrs pairs and subtype_row env trace row1 row2 cstrs = @@ -4146,7 +4236,7 @@ and subtype_row env trace row1 row2 cstrs = and more2 = repr row2.row_more in match more1.desc, more2.desc with Tconstr(p1,_,_), Tconstr(p2,_,_) when Path.same p1 p2 -> - subtype_rec env ((more1,more2)::trace) more1 more2 cstrs + subtype_rec env (Trace.diff more1 more2::trace) more1 more2 cstrs | (Tvar _|Tconstr _|Tnil), (Tvar _|Tconstr _|Tnil) when row1.row_closed && r1 = [] -> List.fold_left @@ -4155,16 +4245,16 @@ and subtype_row env trace row1 row2 cstrs = (Rpresent None|Reither(true,_,_,_)), Rpresent None -> cstrs | Rpresent(Some t1), Rpresent(Some t2) -> - subtype_rec env ((t1, t2)::trace) t1 t2 cstrs + subtype_rec env (Trace.diff t1 t2::trace) t1 t2 cstrs | Reither(false, t1::_, _, _), Rpresent(Some t2) -> - subtype_rec env ((t1, t2)::trace) t1 t2 cstrs + subtype_rec env (Trace.diff t1 t2::trace) t1 t2 cstrs | Rabsent, _ -> cstrs | _ -> raise Exit) cstrs pairs | Tunivar _, Tunivar _ when row1.row_closed = row2.row_closed && r1 = [] && r2 = [] -> let cstrs = - subtype_rec env ((more1,more2)::trace) more1 more2 cstrs in + subtype_rec env (Trace.diff more1 more2::trace) more1 more2 cstrs in List.fold_left (fun cstrs (_,f1,f2) -> match row_field_repr f1, row_field_repr f2 with @@ -4174,7 +4264,7 @@ and subtype_row env trace row1 row2 cstrs = cstrs | Rpresent(Some t1), Rpresent(Some t2) | Reither(false,[t1],_,_), Reither(false,[t2],_,_) -> - subtype_rec env ((t1, t2)::trace) t1 t2 cstrs + subtype_rec env (Trace.diff t1 t2::trace) t1 t2 cstrs | _ -> raise Exit) cstrs pairs | _ -> @@ -4184,7 +4274,7 @@ let subtype env ty1 ty2 = TypePairs.clear subtypes; univar_pairs := []; (* Build constraint set. *) - let cstrs = subtype_rec env [(ty1, ty2)] ty1 ty2 [] in + let cstrs = subtype_rec env [Trace.diff ty1 ty2] ty1 ty2 [] in TypePairs.clear subtypes; (* Enforce constraints. *) function () -> @@ -4192,7 +4282,7 @@ let subtype env ty1 ty2 = (function (trace0, t1, t2, pairs) -> try unify_pairs (ref env) t1 t2 pairs with Unify trace -> raise (Subtype (expand_trace env (List.rev trace0), - List.tl (List.tl trace)))) + List.tl trace))) (List.rev cstrs) (*******************) @@ -4304,10 +4394,10 @@ let rec normalize_type_rec env visited ty = let tm = row_of_type ty in begin if not (is_Tconstr ty) && is_constr_row ~allow_ident:false tm then match tm.desc with (* PR#7348 *) - Tconstr (Path.Pdot(m,i,pos), tl, _abbrev) -> + Tconstr (Path.Pdot(m,i), tl, _abbrev) -> let i' = String.sub i 0 (String.length i - 4) in log_type ty; - ty.desc <- Tconstr(Path.Pdot(m,i',pos), tl, ref Mnil) + ty.desc <- Tconstr(Path.Pdot(m,i'), tl, ref Mnil) | _ -> assert false else match ty.desc with | Tvariant row -> @@ -4382,10 +4472,15 @@ let nondep_variants = TypeHash.create 17 let clear_hash () = TypeHash.clear nondep_hash; TypeHash.clear nondep_variants -let rec nondep_type_rec env id ty = +exception Nondep_cannot_erase of Ident.t + +let rec nondep_type_rec ?(expand_private=false) env ids ty = + let expand_abbrev env t = + if expand_private then expand_abbrev_opt env t else expand_abbrev env t + in match ty.desc with Tvar _ | Tunivar _ -> ty - | Tlink ty -> nondep_type_rec env id ty + | Tlink ty -> nondep_type_rec env ids ty | _ -> try TypeHash.find nondep_hash ty with Not_found -> let ty' = newgenvar () in (* Stub *) @@ -4393,32 +4488,36 @@ let rec nondep_type_rec env id ty = ty'.desc <- begin match ty.desc with | Tconstr(p, tl, _abbrev) -> - if Path.isfree id p then - begin try - Tlink (nondep_type_rec env id - (expand_abbrev env (newty2 ty.level ty.desc))) - (* - The [Tlink] is important. The expanded type may be a - variable, or may not be completely copied yet - (recursive type), so one cannot just take its - description. - *) - with Cannot_expand | Unify _ -> - raise Not_found - end - else - Tconstr(p, List.map (nondep_type_rec env id) tl, ref Mnil) - | Tpackage(p, nl, tl) when Path.isfree id p -> + begin match Path.find_free_opt ids p with + | Some id -> + begin try + Tlink (nondep_type_rec ~expand_private env ids + (expand_abbrev env (newty2 ty.level ty.desc))) + (* + The [Tlink] is important. The expanded type may be a + variable, or may not be completely copied yet + (recursive type), so one cannot just take its + description. + *) + with Cannot_expand | Unify _ -> + raise (Nondep_cannot_erase id) + end + | None -> + Tconstr(p, List.map (nondep_type_rec env ids) tl, ref Mnil) + end + | Tpackage(p, nl, tl) when Path.exists_free ids p -> let p' = normalize_package_path env p in - if Path.isfree id p' then raise Not_found; - Tpackage (p', nl, List.map (nondep_type_rec env id) tl) + begin match Path.find_free_opt ids p' with + | Some id -> raise (Nondep_cannot_erase id) + | None -> Tpackage (p', nl, List.map (nondep_type_rec env ids) tl) + end | Tobject (t1, name) -> - Tobject (nondep_type_rec env id t1, + Tobject (nondep_type_rec env ids t1, ref (match !name with None -> None | Some (p, tl) -> - if Path.isfree id p then None - else Some (p, List.map (nondep_type_rec env id) tl))) + if Path.exists_free ids p then None + else Some (p, List.map (nondep_type_rec env ids) tl))) | Tvariant row -> let row = row_repr row in let more = repr row.row_more in @@ -4435,13 +4534,13 @@ let rec nondep_type_rec env id ty = let more' = if static then newgenty Tnil else more in (* Return a new copy *) let row = - copy_row (nondep_type_rec env id) true row true more' in + copy_row (nondep_type_rec env ids) true row true more' in match row.row_name with - Some (p, _tl) when Path.isfree id p -> + Some (p, _tl) when Path.exists_free ids p -> Tvariant {row with row_name = None} | _ -> Tvariant row end - | _ -> copy_type_desc (nondep_type_rec env id) ty.desc + | _ -> copy_type_desc (nondep_type_rec env ids) ty.desc end; ty' @@ -4450,42 +4549,36 @@ let nondep_type env id ty = let ty' = nondep_type_rec env id ty in clear_hash (); ty' - with Not_found -> + with Nondep_cannot_erase _ as exn -> clear_hash (); - raise Not_found + raise exn let () = nondep_type' := nondep_type -let unroll_abbrev id tl ty = - let ty = repr ty and path = Path.Pident id in - if is_Tvar ty || (List.exists (deep_occur ty) tl) - || is_object_type path then - ty - else - let ty' = newty2 ty.level ty.desc in - link_type ty (newty2 ty.level (Tconstr (path, tl, ref Mnil))); - ty' - (* Preserve sharing inside type declarations. *) -let nondep_type_decl env mid id is_covariant decl = +let nondep_type_decl env mid is_covariant decl = try let params = List.map (nondep_type_rec env mid) decl.type_params in let tk = try map_kind (nondep_type_rec env mid) decl.type_kind - with Not_found when is_covariant -> Type_abstract - and tm = - try match decl.type_manifest with - None -> None + with Nondep_cannot_erase _ when is_covariant -> Type_abstract + and tm, priv = + match decl.type_manifest with + | None -> None, decl.type_private | Some ty -> - Some (unroll_abbrev id params (nondep_type_rec env mid ty)) - with Not_found when is_covariant -> - None + try Some (nondep_type_rec env mid ty), decl.type_private + with Nondep_cannot_erase _ when is_covariant -> + clear_hash (); + try Some (nondep_type_rec ~expand_private:true env mid ty), + Private + with Nondep_cannot_erase _ -> + None, decl.type_private in clear_hash (); let priv = match tm with | Some ty when Btype.has_constr_row ty -> Private - | _ -> decl.type_private + | _ -> priv in { type_params = params; type_arity = decl.type_arity; @@ -4493,38 +4586,40 @@ let nondep_type_decl env mid id is_covariant decl = type_manifest = tm; type_private = priv; type_variance = decl.type_variance; - type_newtype_level = None; + type_is_newtype = false; + type_expansion_scope = Btype.lowest_level; type_loc = decl.type_loc; type_attributes = decl.type_attributes; type_immediate = decl.type_immediate; type_unboxed = decl.type_unboxed; } - with Not_found -> + with Nondep_cannot_erase _ as exn -> clear_hash (); - raise Not_found + raise exn (* Preserve sharing inside extension constructors. *) -let nondep_extension_constructor env mid ext = +let nondep_extension_constructor env ids ext = try let type_path, type_params = - if Path.isfree mid ext.ext_type_path then + match Path.find_free_opt ids ext.ext_type_path with + | Some id -> begin let ty = newgenty (Tconstr(ext.ext_type_path, ext.ext_type_params, ref Mnil)) in - let ty' = nondep_type_rec env mid ty in + let ty' = nondep_type_rec env ids ty in match (repr ty').desc with Tconstr(p, tl, _) -> p, tl - | _ -> raise Not_found + | _ -> raise (Nondep_cannot_erase id) end - else + | None -> let type_params = - List.map (nondep_type_rec env mid) ext.ext_type_params + List.map (nondep_type_rec env ids) ext.ext_type_params in ext.ext_type_path, type_params in - let args = map_type_expr_cstr_args (nondep_type_rec env mid) ext.ext_args in - let ret_type = may_map (nondep_type_rec env mid) ext.ext_ret_type in + let args = map_type_expr_cstr_args (nondep_type_rec env ids) ext.ext_args in + let ret_type = may_map (nondep_type_rec env ids) ext.ext_ret_type in clear_hash (); { ext_type_path = type_path; ext_type_params = type_params; @@ -4534,9 +4629,9 @@ let nondep_extension_constructor env mid ext = ext_attributes = ext.ext_attributes; ext_loc = ext.ext_loc; } - with Not_found -> + with Nondep_cannot_erase _ as exn -> clear_hash (); - raise Not_found + raise exn (* Preserve sharing inside class types. *) @@ -4550,29 +4645,29 @@ let nondep_class_signature env id sign = List.map (fun (p,tl) -> (p, List.map (nondep_type_rec env id) tl)) sign.csig_inher } -let rec nondep_class_type env id = +let rec nondep_class_type env ids = function - Cty_constr (p, _, cty) when Path.isfree id p -> - nondep_class_type env id cty + Cty_constr (p, _, cty) when Path.exists_free ids p -> + nondep_class_type env ids cty | Cty_constr (p, tyl, cty) -> - Cty_constr (p, List.map (nondep_type_rec env id) tyl, - nondep_class_type env id cty) + Cty_constr (p, List.map (nondep_type_rec env ids) tyl, + nondep_class_type env ids cty) | Cty_signature sign -> - Cty_signature (nondep_class_signature env id sign) + Cty_signature (nondep_class_signature env ids sign) | Cty_arrow (l, ty, cty) -> - Cty_arrow (l, nondep_type_rec env id ty, nondep_class_type env id cty) + Cty_arrow (l, nondep_type_rec env ids ty, nondep_class_type env ids cty) -let nondep_class_declaration env id decl = - assert (not (Path.isfree id decl.cty_path)); +let nondep_class_declaration env ids decl = + assert (not (Path.exists_free ids decl.cty_path)); let decl = - { cty_params = List.map (nondep_type_rec env id) decl.cty_params; + { cty_params = List.map (nondep_type_rec env ids) decl.cty_params; cty_variance = decl.cty_variance; - cty_type = nondep_class_type env id decl.cty_type; + cty_type = nondep_class_type env ids decl.cty_type; cty_path = decl.cty_path; cty_new = begin match decl.cty_new with None -> None - | Some ty -> Some (nondep_type_rec env id ty) + | Some ty -> Some (nondep_type_rec env ids ty) end; cty_loc = decl.cty_loc; cty_attributes = decl.cty_attributes; @@ -4581,12 +4676,12 @@ let nondep_class_declaration env id decl = clear_hash (); decl -let nondep_cltype_declaration env id decl = - assert (not (Path.isfree id decl.clty_path)); +let nondep_cltype_declaration env ids decl = + assert (not (Path.exists_free ids decl.clty_path)); let decl = - { clty_params = List.map (nondep_type_rec env id) decl.clty_params; + { clty_params = List.map (nondep_type_rec env ids) decl.clty_params; clty_variance = decl.clty_variance; - clty_type = nondep_class_type env id decl.clty_type; + clty_type = nondep_class_type env ids decl.clty_type; clty_path = decl.clty_path; clty_loc = decl.clty_loc; clty_attributes = decl.clty_attributes; diff --git a/typing/ctype.mli b/typing/ctype.mli index c4d1e55f..15e70c99 100644 --- a/typing/ctype.mli +++ b/typing/ctype.mli @@ -18,14 +18,65 @@ open Asttypes open Types -exception Unify of (type_expr * type_expr) list +module Unification_trace: sig + (** Unification traces are used to explain unification errors + when printing error messages *) + + type position = First | Second + type desc = { t: type_expr; expanded: type_expr option } + type 'a diff = { got: 'a; expected: 'a} + + (** Scope escape related errors *) + type 'a escape = + | Constructor of Path.t + | Univ of type_expr + (** The type_expr argument of [Univ] is always a [Tunivar _], + we keep a [type_expr] to track renaming in {!Printtyp} *) + | Self + | Module_type of Path.t + | Equation of 'a + + (** Errors for polymorphic variants *) + type variant = + | No_intersection + | No_tags of position * (Asttypes.label * row_field) list + | Incompatible_types_for of string + + type obj = + | Missing_field of position * string + | Abstract_row of position + | Self_cannot_be_closed + + type 'a elt = + | Diff of 'a diff + | Variant of variant + | Obj of obj + | Escape of {context: type_expr option; kind:'a escape} + | Incompatible_fields of {name:string; diff: type_expr diff } + | Rec_occur of type_expr * type_expr + + type t = desc elt list + + val diff: type_expr -> type_expr -> desc elt + + (** [map_diff f {expected;got}] is [{expected=f expected; got=f got}] *) + val map_diff: ('a -> 'b) -> 'a diff -> 'b diff + + (** [flatten f trace] flattens all elements of type {!desc} in + [trace] to either [f x.t expanded] if [x.expanded=Some expanded] + or [f x.t x.t] otherwise *) + val flatten: (type_expr -> type_expr -> 'a) -> t -> 'a elt list + + (** Switch [expected] and [got] *) + val swap: t -> t + +end + +exception Unify of Unification_trace.t exception Tags of label * label -exception Subtype of - (type_expr * type_expr) list * (type_expr * type_expr) list +exception Subtype of Unification_trace.t * Unification_trace.t exception Cannot_expand exception Cannot_apply -exception Recursive_abbrev -exception Unification_recursive_abbrev of (type_expr * type_expr) list val init_def: int -> unit (* Set the initial variable level *) @@ -46,6 +97,8 @@ type levels = val save_levels: unit -> levels val set_levels: levels -> unit +val create_scope : unit -> int + val newty: type_desc -> type_expr val newvar: ?name:string -> unit -> type_expr val newvar2: ?name:string -> int -> type_expr @@ -73,7 +126,7 @@ val associate_fields: (string * field_kind * type_expr) list * (string * field_kind * type_expr) list val opened_object: type_expr -> bool -val close_object: type_expr -> unit +val close_object: type_expr -> bool val row_variable: type_expr -> type_expr (* Return the row variable of an open object type *) val set_object_name: @@ -93,12 +146,9 @@ val filter_row_fields: val generalize: type_expr -> unit (* Generalize in-place the given type *) -val generalize_expansive: Env.t -> type_expr -> unit - (* Generalize the covariant part of a type, making - contravariant branches non-generalizable *) -val generalize_global: type_expr -> unit - (* Generalize the structure of a type, lowering variables - to !global_level *) +val lower_contravariant: Env.t -> type_expr -> unit + (* Lower level of type variables inside contravariant branches; + to be used before generalize for expansive expressions *) val generalize_structure: type_expr -> unit (* Same, but variables are only lowered to !current_level *) val generalize_spine: type_expr -> unit @@ -109,8 +159,8 @@ val limited_generalize: type_expr -> type_expr -> unit (* Only generalize some part of the type Make the remaining of the type non-generalizable *) -val check_scope_escape : int -> type_expr -> unit - (* [check_scope_escape lvl ty] ensures that [ty] could be raised +val check_scope_escape : Env.t -> int -> type_expr -> unit + (* [check_scope_escape env lvl ty] ensures that [ty] could be raised to the level [lvl] without any scope escape. Raises [Unify] otherwise *) @@ -119,12 +169,11 @@ val instance: ?partial:bool -> type_expr -> type_expr (* partial=None -> normal partial=false -> newvar() for non generic subterms partial=true -> newty2 ty.level Tvar for non generic subterms *) -val instance_def: type_expr -> type_expr - (* use defaults *) val generic_instance: type_expr -> type_expr (* Same as instance, but new nodes at generic_level *) val instance_list: type_expr list -> type_expr list (* Take an instance of a list of type schemes *) +val existential_name: constructor_description -> type_expr -> string val instance_constructor: ?in_pattern:Env.t ref * int -> constructor_description -> type_expr list * type_expr @@ -136,6 +185,8 @@ val instance_parameterized_type_2: type_expr list -> type_expr list -> type_expr -> type_expr list * type_expr list * type_expr val instance_declaration: type_declaration -> type_declaration +val generic_instance_declaration: type_declaration -> type_declaration + (* Same as instance_declaration, but new nodes at generic_level *) val instance_class: type_expr list -> class_type -> type_expr list * class_type val instance_poly: @@ -169,7 +220,8 @@ val enforce_constraints: Env.t -> type_expr -> unit val unify: Env.t -> type_expr -> type_expr -> unit (* Unify the two types given. Raise [Unify] if not possible. *) -val unify_gadt: newtype_level:int -> Env.t ref -> type_expr -> type_expr -> unit +val unify_gadt: + equations_level:int -> Env.t ref -> type_expr -> type_expr -> unit (* Unify the two types given and update the environment with the local constraints. Raise [Unify] if not possible. *) val unify_var: Env.t -> type_expr -> type_expr -> unit @@ -205,11 +257,11 @@ val reify_univars : Types.type_expr -> Types.type_expr type class_match_failure = CM_Virtual_class | CM_Parameter_arity_mismatch of int * int - | CM_Type_parameter_mismatch of Env.t * (type_expr * type_expr) list + | CM_Type_parameter_mismatch of Env.t * Unification_trace.t | CM_Class_type_mismatch of Env.t * class_type * class_type - | CM_Parameter_mismatch of Env.t * (type_expr * type_expr) list - | CM_Val_type_mismatch of string * Env.t * (type_expr * type_expr) list - | CM_Meth_type_mismatch of string * Env.t * (type_expr * type_expr) list + | CM_Parameter_mismatch of Env.t * Unification_trace.t + | CM_Val_type_mismatch of string * Env.t * Unification_trace.t + | CM_Meth_type_mismatch of string * Env.t * Unification_trace.t | CM_Non_mutable_value of string | CM_Non_concrete_value of string | CM_Missing_value of string @@ -239,23 +291,25 @@ val subtype: Env.t -> type_expr -> type_expr -> unit -> unit enforce and returns a function that enforces this constraints. *) -val nondep_type: Env.t -> Ident.t -> type_expr -> type_expr +exception Nondep_cannot_erase of Ident.t + +val nondep_type: Env.t -> Ident.t list -> type_expr -> type_expr (* Return a type equivalent to the given type but without - references to the given module identifier. Raise [Not_found] - if no such type exists. *) + references to any of the given identifiers. + Raise [Nondep_cannot_erase id] if no such type exists because [id], + in particular, could not be erased. *) val nondep_type_decl: - Env.t -> Ident.t -> Ident.t -> bool -> type_declaration -> - type_declaration + Env.t -> Ident.t list -> bool -> type_declaration -> type_declaration (* Same for type declarations. *) val nondep_extension_constructor: - Env.t -> Ident.t -> extension_constructor -> + Env.t -> Ident.t list -> extension_constructor -> extension_constructor (* Same for extension constructor *) val nondep_class_declaration: - Env.t -> Ident.t -> class_declaration -> class_declaration + Env.t -> Ident.t list -> class_declaration -> class_declaration (* Same for class declarations. *) val nondep_cltype_declaration: - Env.t -> Ident.t -> class_type_declaration -> class_type_declaration + Env.t -> Ident.t list -> class_type_declaration -> class_type_declaration (* Same for class type declarations. *) (*val correct_abbrev: Env.t -> Path.t -> type_expr list -> type_expr -> unit*) val cyclic_abbrev: Env.t -> Ident.t -> type_expr -> bool diff --git a/typing/datarepr.ml b/typing/datarepr.ml index 052e7417..9c997a78 100644 --- a/typing/datarepr.ml +++ b/typing/datarepr.ml @@ -85,7 +85,8 @@ let constructor_args priv cd_args cd_res path rep = type_private = priv; type_manifest = None; type_variance = List.map (fun _ -> Variance.full) type_params; - type_newtype_level = None; + type_is_newtype = false; + type_expansion_scope = Btype.lowest_level; type_loc = Location.none; type_attributes = []; type_immediate = false; @@ -129,7 +130,7 @@ let constructor_descrs ty_path decl cstrs = else Record_inlined idx_nonconst in constructor_args decl.type_private cd_args cd_res - (Path.Pdot (ty_path, cstr_name, Path.nopos)) representation + (Path.Pdot (ty_path, cstr_name)) representation in let cstr = { cstr_name; @@ -158,7 +159,7 @@ let extension_descr path_ext ext = in let existentials, cstr_args, cstr_inlined = constructor_args ext.ext_private ext.ext_args ext.ext_ret_type - path_ext Record_extension + path_ext (Record_extension path_ext) in { cstr_name = Path.last path_ext; cstr_res = ty_res; @@ -176,7 +177,7 @@ let extension_descr path_ext ext = cstr_inlined; } -let none = {desc = Ttuple []; level = -1; scope = None; id = -1} +let none = {desc = Ttuple []; level = -1; scope = Btype.generic_level; id = -1} (* Clearly ill-formed type *) let dummy_label = { lbl_name = ""; lbl_res = none; lbl_arg = none; lbl_mut = Immutable; diff --git a/typing/env.ml b/typing/env.ml index f49a8478..3a544a3f 100644 --- a/typing/env.ml +++ b/typing/env.ml @@ -16,7 +16,6 @@ (* Environment handling *) open Cmi_format -open Config open Misc open Asttypes open Longident @@ -24,6 +23,8 @@ open Path open Types open Btype +module String = Misc.Stdlib.String + let add_delayed_check_forward = ref (fun _ -> assert false) let value_declarations : ((string * Location.t), (unit -> unit)) Hashtbl.t = @@ -55,8 +56,6 @@ let used_constructors : (string * Location.t * string, (constructor_usage -> unit)) Hashtbl.t = Hashtbl.create 16 -let prefixed_sg = Hashtbl.create 113 - type error = | Illegal_renaming of string * string * string | Inconsistent_import of string * string * string @@ -77,10 +76,12 @@ module EnvLazy : sig val force : ('a -> 'b) -> ('a,'b) t -> 'b val create : 'a -> ('a,'b) t val get_arg : ('a,'b) t -> 'a option + val create_forced : 'b -> ('a, 'b) t + val create_failed : exn -> ('a, 'b) t - (* [force_logged log f t] is equivalent to [force f t] but if [f] returns [None] then - [t] is recorded in [log]. [backtrack log] will then reset all the recorded [t]s back - to their original state. *) + (* [force_logged log f t] is equivalent to [force f t] but if [f] returns + [None] then [t] is recorded in [log]. [backtrack log] will then reset all + the recorded [t]s back to their original state. *) val log : unit -> log val force_logged : log -> ('a -> 'b option) -> ('a,'b option) t -> 'b option val backtrack : log -> unit @@ -119,6 +120,12 @@ end = struct let create x = ref (Thunk x) + let create_forced y = + ref (Done y) + + let create_failed e = + ref (Raise e) + let log () = ref Nil @@ -150,21 +157,27 @@ end = struct end -module PathMap = Map.Make(Path) +(** Map indexed by the name of module components. *) +module NameMap = String.Map type summary = Env_empty | Env_value of summary * Ident.t * value_description | Env_type of summary * Ident.t * type_declaration | Env_extension of summary * Ident.t * extension_constructor - | Env_module of summary * Ident.t * module_declaration + | Env_module of summary * Ident.t * module_presence * module_declaration | Env_modtype of summary * Ident.t * modtype_declaration | Env_class of summary * Ident.t * class_declaration | Env_cltype of summary * Ident.t * class_type_declaration - | Env_open of summary * StringSet.t * Path.t + | Env_open of summary * Path.t | Env_functor_arg of summary * Ident.t - | Env_constraints of summary * type_declaration PathMap.t + | Env_constraints of summary * type_declaration Path.Map.t | Env_copy_types of summary * string list + | Env_persistent of summary * Ident.t + +type address = + | Aident of Ident.t + | Adot of address * int module TycompTbl = struct @@ -181,7 +194,7 @@ module TycompTbl = } and 'a opened = { - components: (string, 'a list) Tbl.t; + components: ('a list) NameMap.t; (** Components from the opened module. We keep a list of bindings for each name, as in comp_labels and comp_constrs. *) @@ -237,7 +250,7 @@ module TycompTbl = | None -> [] | Some {using; next; components} -> let rest = find_all name next in - match Tbl.find_str name components with + match NameMap.find name components with | exception Not_found -> rest | opened -> List.map @@ -250,8 +263,8 @@ module TycompTbl = match tbl.opened with | Some {using = _; next; components} -> acc - |> Tbl.fold - (fun _name -> List.fold_right (fun desc -> f desc)) + |> NameMap.fold + (fun _name -> List.fold_right f) components |> fold_name f next | None -> @@ -297,7 +310,7 @@ module IdTbl = its local names to produce a valid path in the current environment. *) - components: (string, 'a * int) Tbl.t; + components: 'a NameMap.t; (** Components from the opened module. *) using: (string -> ('a * 'a) option -> unit) option; @@ -314,6 +327,9 @@ module IdTbl = let add id x tbl = {tbl with current = Ident.add id x tbl.current} + let remove id tbl = + {tbl with current = Ident.remove id tbl.current} + let add_open slot wrap root components next = let using = match slot with @@ -341,14 +357,15 @@ module IdTbl = begin match tbl.opened with | Some {using; root; next; components} -> begin try - let (descr, pos) = Tbl.find_str name components in - let res = Pdot (root, name, pos), descr in + let descr = NameMap.find name components in + let res = Pdot (root, name), descr in if mark then begin match using with | None -> () - | Some f -> - begin try f name (Some (snd (find_name ~mark:false name next), snd res)) - with Not_found -> f name None - end + | Some f -> begin + match find_name ~mark:false name next with + | exception Not_found -> f name None + | _, descr' -> f name (Some (descr', descr)) + end end; res with Not_found -> @@ -367,9 +384,9 @@ module IdTbl = begin match tbl.opened with | Some {root; using; next; components} -> begin try - let (desc, pos) = Tbl.find_str name components in + let desc = NameMap.find name components in let new_desc = f desc in - let components = Tbl.add name (new_desc, pos) components in + let components = NameMap.add name new_desc components in {tbl with opened = Some {root; using; next; components}} with Not_found -> let next = update name f next in @@ -382,23 +399,29 @@ module IdTbl = let rec find_all name tbl = - List.map (fun (id, desc) -> Pident id, desc) (Ident.find_all name tbl.current) @ + List.map + (fun (id, desc) -> Pident id, desc) + (Ident.find_all name tbl.current) @ match tbl.opened with | None -> [] | Some {root; using = _; next; components} -> try - let (desc, pos) = Tbl.find_str name components in - (Pdot (root, name, pos), desc) :: find_all name next + let desc = NameMap.find name components in + (Pdot (root, name), desc) :: find_all name next with Not_found -> find_all name next let rec fold_name f tbl acc = - let acc = Ident.fold_name (fun id d -> f (Ident.name id) (Pident id, d)) tbl.current acc in + let acc = + Ident.fold_name + (fun id d -> f (Ident.name id) (Pident id, d)) + tbl.current acc + in match tbl.opened with | Some {root; using = _; next; components} -> acc - |> Tbl.fold - (fun name (desc, pos) -> f name (Pdot (root, name, pos), desc)) + |> NameMap.fold + (fun name desc -> f name (Pdot (root, name), desc)) components |> fold_name f next | None -> @@ -415,8 +438,11 @@ module IdTbl = Ident.iter (fun id desc -> f id (Pident id, desc)) tbl.current; match tbl.opened with | Some {root; using = _; next; components} -> - Tbl.iter - (fun s (x, pos) -> f (Ident.hide (Ident.create s) (* ??? *)) (Pdot (root, s, pos), x)) + NameMap.iter + (fun s x -> + let root_scope = Path.scope root in + f (Ident.create_scoped ~scope:root_scope s) + (Pdot (root, s), x)) components; iter f next | None -> () @@ -437,48 +463,60 @@ type type_descriptions = let in_signature_flag = 0x01 +type 'a value_or_persistent = + | Value of 'a + | Persistent + type t = { - values: value_description IdTbl.t; - constrs: constructor_description TycompTbl.t; + values: (value_description * address_lazy) IdTbl.t; + constrs: (constructor_description * address_lazy option) TycompTbl.t; labels: label_description TycompTbl.t; types: (type_declaration * type_descriptions) IdTbl.t; - modules: (Subst.t * module_declaration, module_declaration) EnvLazy.t IdTbl.t; + modules: (module_declaration_lazy * address_lazy) value_or_persistent IdTbl.t; modtypes: modtype_declaration IdTbl.t; - components: module_components IdTbl.t; - classes: class_declaration IdTbl.t; + components: (module_components * address_lazy) value_or_persistent IdTbl.t; + classes: (class_declaration * address_lazy) IdTbl.t; cltypes: class_type_declaration IdTbl.t; functor_args: unit Ident.tbl; summary: summary; - local_constraints: type_declaration PathMap.t; + local_constraints: type_declaration Path.Map.t; flags: int; } +and module_declaration_lazy = + (Subst.t * Subst.scoping * module_declaration, module_declaration) EnvLazy.t + and module_components = { - deprecated: string option; + alerts: string Misc.Stdlib.String.Map.t; loc: Location.t; - comps: - (t * Subst.t * Path.t * Types.module_type, module_components_repr option) - EnvLazy.t; + comps: (components_maker, module_components_repr option) EnvLazy.t; } +and components_maker = { + cm_env: t; + cm_freshening_subst: Subst.t option; + cm_prefixing_subst: Subst.t; + cm_path: Path.t; + cm_addr: address_lazy; + cm_mty: Types.module_type; +} + and module_components_repr = Structure_comps of structure_components | Functor_comps of functor_components -and 'a comp_tbl = (string, ('a * int)) Tbl.t - and structure_components = { - mutable comp_values: value_description comp_tbl; - mutable comp_constrs: (string, constructor_description list) Tbl.t; - mutable comp_labels: (string, label_description list) Tbl.t; - mutable comp_types: (type_declaration * type_descriptions) comp_tbl; - mutable comp_modules: - (Subst.t * module_declaration, module_declaration) EnvLazy.t comp_tbl; - mutable comp_modtypes: modtype_declaration comp_tbl; - mutable comp_components: module_components comp_tbl; - mutable comp_classes: class_declaration comp_tbl; - mutable comp_cltypes: class_type_declaration comp_tbl; + mutable comp_values: (value_description * address_lazy) NameMap.t; + mutable comp_constrs: + ((constructor_description * address_lazy option) list) NameMap.t; + mutable comp_labels: label_description list NameMap.t; + mutable comp_types: (type_declaration * type_descriptions) NameMap.t; + mutable comp_modules: (module_declaration_lazy * address_lazy) NameMap.t; + mutable comp_modtypes: modtype_declaration NameMap.t; + mutable comp_components: (module_components * address_lazy) NameMap.t; + mutable comp_classes: (class_declaration * address_lazy) NameMap.t; + mutable comp_cltypes: class_type_declaration NameMap.t; } and functor_components = { @@ -489,6 +527,13 @@ and functor_components = { fcomp_subst_cache: (Path.t, module_type) Hashtbl.t } +and address_unforced = + | Projection of { parent : address_lazy; pos : int; } + | ModAlias of { env : t; path : Path.t; } + +and address_lazy = (address_unforced, address) EnvLazy.t + + let copy_local ~from env = { env with local_constraints = from.local_constraints; @@ -496,6 +541,8 @@ let copy_local ~from env = let same_constr = ref (fun _ _ _ -> assert false) +let check_well_formed_module = ref (fun _ -> assert false) + (* Helper to decide whether to report an identifier shadowing by some 'open'. For labels and constructors, we do not report if the two elements are from the same re-exported declaration. @@ -504,7 +551,7 @@ let same_constr = ref (fun _ _ _ -> assert false) type declarations to silence the shadowing warnings. *) let check_shadowing env = function - | `Constructor (Some (c1, c2)) + | `Constructor (Some ((c1, _), (c2, _))) when not (!same_constr env c1.cstr_res c2.cstr_res) -> Some "constructor" | `Label (Some (l1, l2)) @@ -521,9 +568,8 @@ let check_shadowing env = function | `Class None | `Class_type None | `Component None -> None -let subst_modtype_maker (subst, md) = - if subst == Subst.identity then md - else {md with md_type = Subst.modtype subst md.md_type} +let subst_modtype_maker (subst, scoping, md) = + {md with md_type = Subst.modtype scoping subst md.md_type} let empty = { values = IdTbl.empty; constrs = TycompTbl.empty; @@ -531,7 +577,7 @@ let empty = { modules = IdTbl.empty; modtypes = IdTbl.empty; components = IdTbl.empty; classes = IdTbl.empty; cltypes = IdTbl.empty; - summary = Env_empty; local_constraints = PathMap.empty; + summary = Env_empty; local_constraints = Path.Map.empty; flags = 0; functor_args = Ident.empty; } @@ -550,7 +596,7 @@ let is_ident = function | Pdot _ | Papply _ -> false let is_local_ext = function - | {cstr_tag = Cstr_extension(p, _)} -> is_ident p + | {cstr_tag = Cstr_extension(p, _)}, _ -> is_ident p | _ -> false let diff env1 env2 = @@ -578,13 +624,13 @@ let without_cmis f x = (* Forward declarations *) let components_of_module' = - ref ((fun ~deprecated:_ ~loc:_ _env _sub _path _mty -> assert false) : - deprecated:string option -> loc:Location.t -> t -> Subst.t -> - Path.t -> module_type -> + ref ((fun ~alerts:_ ~loc:_ _env _sub _path _addr _mty -> assert false) : + alerts:string Misc.Stdlib.String.Map.t -> loc:Location.t -> t -> + Subst.t option -> Subst.t -> Path.t -> address_lazy -> module_type -> module_components) let components_of_module_maker' = - ref ((fun (_env, _sub, _path, _mty) -> assert false) : - t * Subst.t * Path.t * module_type -> module_components_repr option) + ref ((fun _ -> assert false) : + components_maker -> module_components_repr option) let components_of_functor_appl' = ref ((fun _f _env _p1 _p2 -> assert false) : functor_components -> t -> Path.t -> Path.t -> module_components) @@ -609,24 +655,37 @@ let get_components_opt c = let empty_structure = Structure_comps { - comp_values = Tbl.empty; - comp_constrs = Tbl.empty; - comp_labels = Tbl.empty; - comp_types = Tbl.empty; - comp_modules = Tbl.empty; comp_modtypes = Tbl.empty; - comp_components = Tbl.empty; comp_classes = Tbl.empty; - comp_cltypes = Tbl.empty } + comp_values = NameMap.empty; + comp_constrs = NameMap.empty; + comp_labels = NameMap.empty; + comp_types = NameMap.empty; + comp_modules = NameMap.empty; comp_modtypes = NameMap.empty; + comp_components = NameMap.empty; comp_classes = NameMap.empty; + comp_cltypes = NameMap.empty } let get_components c = match get_components_opt c with | None -> empty_structure | Some c -> c +(* Print addresses *) + +let rec print_address ppf = function + | Aident id -> Format.fprintf ppf "%s" (Ident.name id) + | Adot(a, pos) -> Format.fprintf ppf "%a.[%i]" print_address a pos + (* The name of the compilation unit currently compiled. "" if outside a compilation unit. *) let current_unit = ref "" +let find_same_module id tbl = + match IdTbl.find_same id tbl with + | x -> x + | exception Not_found + when Ident.persistent id && not (Ident.name id = !current_unit) -> + Persistent + (* Persistent structure descriptions *) type pers_struct = @@ -644,20 +703,20 @@ let persistent_structures = let crc_units = Consistbl.create() -let imported_units = ref StringSet.empty +let imported_units = ref String.Set.empty let add_import s = - imported_units := StringSet.add s !imported_units + imported_units := String.Set.add s !imported_units -let imported_opaque_units = ref StringSet.empty +let imported_opaque_units = ref String.Set.empty let add_imported_opaque s = - imported_opaque_units := StringSet.add s !imported_opaque_units + imported_opaque_units := String.Set.add s !imported_opaque_units let clear_imports () = Consistbl.clear crc_units; - imported_units := StringSet.empty; - imported_opaque_units := StringSet.empty + imported_units := String.Set.empty; + imported_opaque_units := String.Set.empty let check_consistency ps = try @@ -680,7 +739,7 @@ let save_pers_struct crc ps = List.iter (function | Rectypes -> () - | Deprecated _ -> () + | Alerts _ -> () | Unsafe_string -> () | Opaque -> add_imported_opaque modname) ps.ps_flags; @@ -693,29 +752,43 @@ module Persistent_signature = struct cmi : Cmi_format.cmi_infos } let load = ref (fun ~unit_name -> - match find_in_path_uncap !load_path (unit_name ^ ".cmi") with - | filename -> Some { filename; cmi = read_cmi filename } - | exception Not_found -> None) + match Load_path.find_uncap (unit_name ^ ".cmi") with + | filename -> Some { filename; cmi = read_cmi filename } + | exception Not_found -> None) end +let add_persistent_structure id env = + if not (Ident.persistent id) then invalid_arg "Env.add_persistent_structure"; + if Ident.name id <> !current_unit then + { env with + modules = IdTbl.add id Persistent env.modules; + components = IdTbl.add id Persistent env.components; + summary = Env_persistent (env.summary, id); + } + else + env + let acknowledge_pers_struct check modname { Persistent_signature.filename; cmi } = let name = cmi.cmi_name in let sign = cmi.cmi_sign in let crcs = cmi.cmi_crcs in let flags = cmi.cmi_flags in - let deprecated = - List.fold_left (fun acc -> function Deprecated s -> Some s | _ -> acc) None + let alerts = + List.fold_left (fun acc -> function Alerts s -> s | _ -> acc) + Misc.Stdlib.String.Map.empty flags in + let id = Ident.create_persistent name in + let path = Pident id in + let addr = EnvLazy.create_forced (Aident id) in let comps = - !components_of_module' ~deprecated ~loc:Location.none - empty Subst.identity - (Pident(Ident.create_persistent name)) - (Mty_signature sign) + !components_of_module' ~alerts ~loc:Location.none + empty (Some Subst.identity) Subst.identity path addr + (Mty_signature sign) in let ps = { ps_name = name; - ps_sig = lazy (Subst.signature Subst.identity sign); + ps_sig = lazy (Subst.signature Make_local Subst.identity sign); ps_comps = comps; ps_crcs = crcs; ps_filename = filename; @@ -732,7 +805,7 @@ let acknowledge_pers_struct check modname | Unsafe_string -> if Config.safe_string then error (Depend_on_unsafe_string_unit (ps.ps_name, !current_unit)); - | Deprecated _ -> () + | Alerts _ -> () | Opaque -> add_imported_opaque modname) ps.ps_flags; if check then check_consistency ps; @@ -822,8 +895,7 @@ let reset_cache () = Hashtbl.clear value_declarations; Hashtbl.clear type_declarations; Hashtbl.clear module_declarations; - Hashtbl.clear used_constructors; - Hashtbl.clear prefixed_sg + Hashtbl.clear used_constructors let reset_cache_toplevel () = (* Delete 'missing cmi' entries from the cache. *) @@ -836,8 +908,7 @@ let reset_cache_toplevel () = Hashtbl.clear value_declarations; Hashtbl.clear type_declarations; Hashtbl.clear module_declarations; - Hashtbl.clear used_constructors; - Hashtbl.clear prefixed_sg + Hashtbl.clear used_constructors let set_unit_name name = @@ -851,18 +922,14 @@ let get_unit_name () = let rec find_module_descr path env = match path with Pident id -> - begin try - IdTbl.find_same id env.components - with Not_found -> - if Ident.persistent id && not (Ident.name id = !current_unit) - then (find_pers_struct (Ident.name id)).ps_comps - else raise Not_found + begin match find_same_module id env.components with + | Value x -> fst x + | Persistent -> (find_pers_struct (Ident.name id)).ps_comps end - | Pdot(p, s, _pos) -> + | Pdot(p, s) -> begin match get_components (find_module_descr p env) with Structure_comps c -> - let (descr, _pos) = Tbl.find_str s c.comp_components in - descr + fst (NameMap.find s c.comp_components) | Functor_comps _ -> raise Not_found end @@ -876,29 +943,32 @@ let rec find_module_descr path env = let find proj1 proj2 path env = match path with - Pident id -> - IdTbl.find_same id (proj1 env) - | Pdot(p, s, _pos) -> + Pident id -> IdTbl.find_same id (proj1 env) + | Pdot(p, s) -> begin match get_components (find_module_descr p env) with - Structure_comps c -> - let (data, _pos) = Tbl.find_str s (proj2 c) in data + Structure_comps c -> NameMap.find s (proj2 c) | Functor_comps _ -> raise Not_found end | Papply _ -> raise Not_found -let find_value = +let find_value_full = find (fun env -> env.values) (fun sc -> sc.comp_values) and find_type_full = find (fun env -> env.types) (fun sc -> sc.comp_types) and find_modtype = find (fun env -> env.modtypes) (fun sc -> sc.comp_modtypes) -and find_class = +and find_class_full = find (fun env -> env.classes) (fun sc -> sc.comp_classes) and find_cltype = find (fun env -> env.cltypes) (fun sc -> sc.comp_cltypes) +let find_value p env = + fst (find_value_full p env) +let find_class p env = + fst (find_class_full p env) + let type_of_cstr path = function | {cstr_inlined = Some d; _} -> (d, ([], List.map snd (Datarepr.labels_of_type path d))) @@ -908,7 +978,7 @@ let type_of_cstr path = function let find_type_full path env = match Path.constructor_typath path with | Regular p -> - (try (PathMap.find p env.local_constraints, ([], [])) + (try (Path.Map.find p env.local_constraints, ([], [])) with Not_found -> find_type_full p env) | Cstr (ty_path, s) -> let (_, (cstrs, _)) = @@ -922,7 +992,7 @@ let find_type_full path env = type_of_cstr path cstr | LocalExt id -> let cstr = - try TycompTbl.find_same id env.constrs + try fst (TycompTbl.find_same id env.constrs) with Not_found -> assert false in type_of_cstr path cstr @@ -938,12 +1008,12 @@ let find_type_full path env = in let exts = List.filter - (function {cstr_tag=Cstr_extension _} -> true | _ -> false) - (try Tbl.find_str s comps.comp_constrs + (function ({cstr_tag=Cstr_extension _}, _) -> true | _ -> false) + (try NameMap.find s comps.comp_constrs with Not_found -> assert false) in match exts with - | [cstr] -> type_of_cstr path cstr + | [(cstr, _)] -> type_of_cstr path cstr | _ -> assert false let find_type p env = @@ -954,19 +1024,17 @@ let find_type_descrs p env = let find_module ~alias path env = match path with Pident id -> - begin try - let data = IdTbl.find_same id env.modules in - EnvLazy.force subst_modtype_maker data - with Not_found -> - if Ident.persistent id && not (Ident.name id = !current_unit) then - let ps = find_pers_struct (Ident.name id) in - md (Mty_signature(Lazy.force ps.ps_sig)) - else raise Not_found + begin + match find_same_module id env.modules with + | Value (data, _) -> EnvLazy.force subst_modtype_maker data + | Persistent -> + let ps = find_pers_struct (Ident.name id) in + md (Mty_signature(Lazy.force ps.ps_sig)) end - | Pdot(p, s, _pos) -> + | Pdot(p, s) -> begin match get_components (find_module_descr p env) with Structure_comps c -> - let (data, _pos) = Tbl.find_str s c.comp_modules in + let data, _ = NameMap.find s c.comp_modules in EnvLazy.force subst_modtype_maker data | Functor_comps _ -> raise Not_found @@ -975,24 +1043,79 @@ let find_module ~alias path env = let desc1 = find_module_descr p1 env in begin match get_components desc1 with Functor_comps f -> - md begin match f.fcomp_res with - | Mty_alias _ as mty -> mty - | mty -> - if alias then mty else - try - Hashtbl.find f.fcomp_subst_cache p2 - with Not_found -> - let mty = - Subst.modtype - (Subst.add_module f.fcomp_param p2 Subst.identity) - f.fcomp_res in - Hashtbl.add f.fcomp_subst_cache p2 mty; - mty - end + let mty = + match f.fcomp_res with + | Mty_alias _ as mty -> mty + | mty -> + if alias then mty else + try + Hashtbl.find f.fcomp_subst_cache p2 + with Not_found -> + let mty = + Subst.modtype (Rescope (Path.scope path)) + (Subst.add_module f.fcomp_param p2 Subst.identity) + f.fcomp_res in + Hashtbl.add f.fcomp_subst_cache p2 mty; + mty + in + md mty | Structure_comps _ -> raise Not_found end +let rec find_module_address path env = + match path with + | Pident id -> + begin + match find_same_module id env.modules with + | Value (_, addr) -> get_address addr + | Persistent -> Aident id + end + | Pdot(p, s) -> begin + match get_components (find_module_descr p env) with + | Structure_comps c -> + let _, addr = NameMap.find s c.comp_modules in + get_address addr + | Functor_comps _ -> + raise Not_found + end + | Papply _ -> raise Not_found + +and force_address = function + | Projection { parent; pos } -> Adot(get_address parent, pos) + | ModAlias { env; path } -> find_module_address path env + +and get_address a = + EnvLazy.force force_address a + +let find_value_address p env = + get_address (snd (find_value_full p env)) + +let find_class_address p env = + get_address (snd (find_class_full p env)) + +let rec get_constrs_address = function + | [] -> raise Not_found + | (_, None) :: rest -> get_constrs_address rest + | (_, Some a) :: _ -> get_address a + +let find_constructor_address path env = + match path with + | Pident id -> begin + match TycompTbl.find_same id env.constrs with + | _, None -> raise Not_found + | _, Some addr -> get_address addr + end + | Pdot(p, s) -> begin + match get_components (find_module_descr p env) with + | Structure_comps c -> + get_constrs_address (NameMap.find s c.comp_constrs) + | Functor_comps _ -> + raise Not_found + end + | Papply _ -> + raise Not_found + let required_globals = ref [] let reset_required_globals () = required_globals := [] let get_required_globals () = !required_globals @@ -1001,18 +1124,25 @@ let add_required_global id = && not (List.exists (Ident.same id) !required_globals) then required_globals := id :: !required_globals -let rec normalize_path lax env path = - let path = - match path with - Pdot(p, s, pos) -> - Pdot(normalize_path lax env p, s, pos) - | Papply(p1, p2) -> - Papply(normalize_path lax env p1, normalize_path true env p2) - | _ -> path - in +let rec normalize_module_path lax env = function + | Pident id as path when lax && Ident.persistent id -> + path (* fast path (avoids lookup) *) + | Pdot (p, s) as path -> + let p' = normalize_module_path lax env p in + if p == p' then expand_module_path lax env path + else expand_module_path lax env (Pdot(p', s)) + | Papply (p1, p2) as path -> + let p1' = normalize_module_path lax env p1 in + let p2' = normalize_module_path true env p2 in + if p1 == p1' && p2 == p2' then expand_module_path lax env path + else expand_module_path lax env (Papply(p1', p2')) + | Pident _ as path -> + expand_module_path lax env path + +and expand_module_path lax env path = try match find_module ~alias:true path env with - {md_type=Mty_alias(_, path1)} -> - let path' = normalize_path lax env path1 in + {md_type=Mty_alias path1} -> + let path' = normalize_module_path lax env path1 in if lax || !Clflags.transparent_modules then path' else let id = Path.head path in if Ident.global id && not (Ident.same id (Path.head path')) @@ -1023,24 +1153,52 @@ let rec normalize_path lax env path = || (match path with Pident id -> not (Ident.persistent id) | _ -> true) -> path -let normalize_path oloc env path = - try normalize_path (oloc = None) env path +let normalize_module_path oloc env path = + try normalize_module_path (oloc = None) env path with Not_found -> match oloc with None -> assert false | Some loc -> - raise (Error(Missing_module(loc, path, normalize_path true env path))) + raise (Error(Missing_module(loc, path, + normalize_module_path true env path))) let normalize_path_prefix oloc env path = match path with - Pdot(p, s, pos) -> - Pdot(normalize_path oloc env p, s, pos) + Pdot(p, s) -> + let p2 = normalize_module_path oloc env p in + if p == p2 then path else Pdot(p2, s) | Pident _ -> path | Papply _ -> assert false +let is_uident s = + match s.[0] with + | 'A'..'Z' -> true + | _ -> false + +let normalize_type_path oloc env path = + (* Inlined version of Path.is_constructor_typath: + constructor type paths (i.e. path pointing to an inline + record argument of a constructpr) are built as a regular + type path followed by a capitalized constructor name. *) + match path with + | Pident _ -> + path + | Pdot(p, s) -> + let p2 = + if is_uident s && not (is_uident (Path.last p)) then + (* Cstr M.t.C *) + normalize_path_prefix oloc env p + else + (* Regular M.t, Ext M.C *) + normalize_module_path oloc env p + in + if p == p2 then path else Pdot (p2, s) + | Papply _ -> + assert false -let find_module = find_module ~alias:false +let find_module path env = + find_module ~alias:false path env (* Find the manifest type associated to a type when appropriate: - the type should be public or should have a private row, @@ -1051,7 +1209,7 @@ let find_type_expansion path env = | Some body when decl.type_private = Public || decl.type_kind <> Type_abstract || Btype.has_constr_row body -> - (decl.type_params, body, may_map snd decl.type_newtype_level) + (decl.type_params, body, decl.type_expansion_scope) (* The manifest type of Private abstract data types without private row are still considered unknown to the type system. Hence, this case is caught by the following clause that also handles @@ -1067,7 +1225,8 @@ let find_type_expansion_opt path env = match decl.type_manifest with (* The manifest type of Private abstract data types can still get an approximation using their manifest type. *) - | Some body -> (decl.type_params, body, may_map snd decl.type_newtype_level) + | Some body -> + (decl.type_params, body, decl.type_expansion_scope) | _ -> raise Not_found let find_modtype_expansion path env = @@ -1081,18 +1240,23 @@ let rec is_functor_arg path env = begin try Ident.find_same id env.functor_args; true with Not_found -> false end - | Pdot (p, _s, _) -> is_functor_arg p env + | Pdot (p, _s) -> is_functor_arg p env | Papply _ -> true (* Lookup by name *) exception Recmodule -let report_deprecated ?loc p deprecated = - match loc, deprecated with - | Some loc, Some txt -> - let txt = if txt = "" then "" else "\n" ^ txt in - Location.deprecated loc (Printf.sprintf "module %s%s" (Path.name p) txt) +let report_alerts ?loc p alerts = + match loc with + | Some loc -> + Misc.Stdlib.String.Map.iter + (fun kind message -> + let message = if message = "" then "" else "\n" ^ message in + Location.alert ~kind loc + (Printf.sprintf "module %s%s" (Path.name p) message) + ) + alerts | _ -> () let mark_module_used name loc = @@ -1102,19 +1266,22 @@ let mark_module_used name loc = let rec lookup_module_descr_aux ?loc ~mark lid env = match lid with Lident s -> - begin try - IdTbl.find_name ~mark s env.components - with Not_found -> - if s = !current_unit then raise Not_found; - let ps = find_pers_struct s in - (Pident(Ident.create_persistent s), ps.ps_comps) + begin match IdTbl.find_name ~mark s env.components with + | exception Not_found when s <> !current_unit -> + let p = Path.Pident (Ident.create_persistent s) in + (p, (find_pers_struct s).ps_comps) + | (p, data) -> + (p, + match data with + | Value (comp, _) -> comp + | Persistent -> (find_pers_struct s).ps_comps) end | Ldot(l, s) -> let (p, descr) = lookup_module_descr ?loc ~mark l env in begin match get_components descr with Structure_comps c -> - let (descr, pos) = Tbl.find_str s c.comp_components in - (Pdot(p, s, pos), descr) + let (descr, _addr) = NameMap.find s c.comp_components in + (Pdot(p, s), descr) | Functor_comps _ -> raise Not_found end @@ -1140,49 +1307,51 @@ and lookup_module_descr ?loc ~mark lid env = Format.printf "USE module %s at %a@." (Path.last p) Location.print comps.loc; *) - report_deprecated ?loc p comps.deprecated; + report_alerts ?loc p comps.alerts; res and lookup_module ~load ?loc ~mark lid env : Path.t = match lid with Lident s -> - begin try - let (p, data) = IdTbl.find_name ~mark s env.modules in - let {md_loc; md_attributes; md_type} = - EnvLazy.force subst_modtype_maker data - in - if mark then mark_module_used s md_loc; - begin match md_type with - | Mty_ident (Path.Pident id) when Ident.name id = "#recmod#" -> - (* see #5965 *) - raise Recmodule - | _ -> () - end; - report_deprecated ?loc p - (Builtin_attributes.deprecated_of_attrs md_attributes); - p - with Not_found -> - if s = !current_unit then raise Not_found; - let p = Pident(Ident.create_persistent s) in - if !Clflags.transparent_modules && not load - then - let loc = match loc with Some l -> l | None -> Location.none in - check_pers_struct ~loc s - else begin - let ps = find_pers_struct s in - report_deprecated ?loc p ps.ps_comps.deprecated - end; - p + begin match IdTbl.find_name ~mark s env.modules with + | exception Not_found when !Clflags.transparent_modules && not load -> + check_pers_struct s + ~loc:(Option.value loc ~default:Location.none); + Path.Pident (Ident.create_persistent s) + | p, data -> + begin match data with + | Value (data, _) -> + let {md_loc; md_attributes; md_type} = + EnvLazy.force subst_modtype_maker data + in + if mark then mark_module_used s md_loc; + begin match md_type with + | Mty_ident (Path.Pident id) when Ident.name id = "#recmod#" -> + (* see #5965 *) + raise Recmodule + | _ -> () + end; + report_alerts ?loc p + (Builtin_attributes.alerts_of_attrs md_attributes) + | Persistent -> + if !Clflags.transparent_modules && not load then + check_pers_struct s + ~loc:(Option.value loc ~default:Location.none) + else begin + let ps = find_pers_struct s in + report_alerts ?loc p ps.ps_comps.alerts + end + end; + p end | Ldot(l, s) -> let (p, descr) = lookup_module_descr ?loc ~mark l env in begin match get_components descr with Structure_comps c -> - let (_data, pos) = Tbl.find_str s c.comp_modules in - let (comps, _) = Tbl.find_str s c.comp_components in + let (comps, _) = NameMap.find s c.comp_components in if mark then mark_module_used s comps.loc; - let p = Pdot(p, s, pos) in - report_deprecated ?loc p comps.deprecated; + let p = Pdot(p, s) in + report_alerts ?loc p comps.alerts; p | Functor_comps _ -> raise Not_found @@ -1205,14 +1374,13 @@ and lookup_module ~load ?loc ~mark lid env : Path.t = let lookup proj1 proj2 ?loc ~mark lid env = match lid with - Lident s -> - IdTbl.find_name ~mark s (proj1 env) + | Lident s -> IdTbl.find_name ~mark s (proj1 env) | Ldot(l, s) -> - let (p, desc) = lookup_module_descr ?loc ~mark l env in + let path, desc = lookup_module_descr ?loc ~mark l env in begin match get_components desc with Structure_comps c -> - let (data, pos) = Tbl.find_str s (proj2 c) in - (Pdot(p, s, pos), data) + let data = NameMap.find s (proj2 c) in + (Pdot(path, s), data) | Functor_comps _ -> raise Not_found end @@ -1236,7 +1404,7 @@ let lookup_all_simple proj1 proj2 shadow ?loc ~mark lid env = begin match get_components desc with Structure_comps c -> let comps = - try Tbl.find_str s (proj2 c) with Not_found -> [] + try NameMap.find s (proj2 c) with Not_found -> [] in List.map (fun data -> (data, (fun () -> ()))) @@ -1247,35 +1415,58 @@ let lookup_all_simple proj1 proj2 shadow ?loc ~mark lid env = | Lapply _ -> raise Not_found -let has_local_constraints env = not (PathMap.is_empty env.local_constraints) +let has_local_constraints env = not (Path.Map.is_empty env.local_constraints) -let cstr_shadow cstr1 cstr2 = +let cstr_shadow (cstr1, _) (cstr2, _) = match cstr1.cstr_tag, cstr2.cstr_tag with | Cstr_extension _, Cstr_extension _ -> true | _ -> false let lbl_shadow _lbl1 _lbl2 = false -let lookup_value = - lookup (fun env -> env.values) (fun sc -> sc.comp_values) -let lookup_all_constructors = +let ignore_address (path, (desc, _addr)) = (path, desc) + +let lookup_value ?loc ~mark lid env = + ignore_address + (lookup (fun env -> env.values) (fun sc -> sc.comp_values) + ?loc ~mark lid env) +let lookup_all_constructors ?loc ~mark lid env = lookup_all_simple (fun env -> env.constrs) (fun sc -> sc.comp_constrs) - cstr_shadow -let lookup_all_labels = + cstr_shadow ?loc ~mark lid env +let lookup_all_labels ?loc ~mark lid env = lookup_all_simple (fun env -> env.labels) (fun sc -> sc.comp_labels) - lbl_shadow -let lookup_type = + lbl_shadow ?loc ~mark lid env +let lookup_type ?loc ~mark lid env= lookup (fun env -> env.types) (fun sc -> sc.comp_types) -let lookup_modtype = + ?loc ~mark lid env +let lookup_modtype ?loc ~mark lid env = lookup (fun env -> env.modtypes) (fun sc -> sc.comp_modtypes) -let lookup_class = - lookup (fun env -> env.classes) (fun sc -> sc.comp_classes) -let lookup_cltype = + ?loc ~mark lid env +let lookup_class ?loc ~mark lid env = + ignore_address + (lookup (fun env -> env.classes) (fun sc -> sc.comp_classes) + ?loc ~mark lid env) +let lookup_cltype ?loc ~mark lid env = lookup (fun env -> env.cltypes) (fun sc -> sc.comp_cltypes) + ?loc ~mark lid env -let copy_types l env = - let f desc = {desc with val_type = Subst.type_expr Subst.identity desc.val_type} in - let values = List.fold_left (fun env s -> IdTbl.update s f env) env.values l in +type copy_of_types = { + to_copy: string list; + initial_values: (value_description * address_lazy) IdTbl.t; + new_values: (value_description * address_lazy) IdTbl.t; +} + +let make_copy_of_types l env : copy_of_types = + let f (desc, addr) = + {desc with val_type = Subst.type_expr Subst.identity desc.val_type}, addr + in + let values = + List.fold_left (fun env s -> IdTbl.update s f env) env.values l + in + {to_copy = l; initial_values = env.values; new_values = values} + +let do_copy_types { to_copy = l; initial_values; new_values = values } env = + if initial_values != env.values then fatal_error "Env.do_copy_types"; {env with values; summary = Env_copy_types (env.summary, l)} let mark_value_used name vd = @@ -1313,7 +1504,7 @@ let set_type_used_callback name td callback = else let key = (name, loc) in let old = try Hashtbl.find type_declarations key - with Not_found -> assert false + with Not_found -> ignore in Hashtbl.replace type_declarations key (fun () -> callback old) @@ -1341,7 +1532,7 @@ let ty_path t = let lookup_constructor ?loc ?(mark = true) lid env = match lookup_all_constructors ?loc ~mark lid env with [] -> raise Not_found - | (desc, use) :: _ -> + | ((desc, _), use) :: _ -> if mark then begin mark_type_path env (ty_path desc.cstr_res); use () @@ -1361,7 +1552,7 @@ let lookup_all_constructors ?loc ?(mark = true) lid env = use () end in - List.map (fun (cstr, use) -> (cstr, wrap_use cstr use)) cstrs + List.map (fun ((cstr, _), use) -> (cstr, wrap_use cstr use)) cstrs with Not_found when is_lident lid -> [] @@ -1423,20 +1614,29 @@ let lookup_cltype ?loc ?(mark = true) lid env = mark_type_path env desc.clty_path; r +(* Helper to handle optional substitutions. *) + +let may_subst subst_f sub x = + match sub with + | None -> x + | Some sub -> subst_f sub x + (* Iter on an environment (ignoring the body of functors and not yet evaluated structures) *) type iter_cont = unit -> unit let iter_env_cont = ref [] -let rec scrape_alias_for_visit env mty = +let rec scrape_alias_for_visit env sub mty = match mty with - | Mty_alias(_, Pident id) - when Ident.persistent id - && not (Hashtbl.mem persistent_structures (Ident.name id)) -> false - | Mty_alias(_, path) -> (* PR#6600: find_module may raise Not_found *) - begin try scrape_alias_for_visit env (find_module path env).md_type - with Not_found -> false + | Mty_alias path -> + begin match may_subst Subst.module_path sub path with + | Pident id + when Ident.persistent id + && not (Hashtbl.mem persistent_structures (Ident.name id)) -> false + | path -> (* PR#6600: find_module may raise Not_found *) + try scrape_alias_for_visit env sub (find_module path env).md_type + with Not_found -> false end | _ -> true @@ -1447,30 +1647,30 @@ let iter_env proj1 proj2 f env () = let visit = match EnvLazy.get_arg mcomps.comps with | None -> true - | Some (env, _sub, _path, mty) -> scrape_alias_for_visit env mty + | Some { cm_mty; cm_freshening_subst; _ } -> + scrape_alias_for_visit env cm_freshening_subst cm_mty in if not visit then () else match get_components mcomps with Structure_comps comps -> - Tbl.iter - (fun s (d, n) -> f (Pdot (path, s, n)) (Pdot (path', s, n), d)) + NameMap.iter + (fun s d -> f (Pdot (path, s)) (Pdot (path', s), d)) (proj2 comps); - Tbl.iter - (fun s (c, n) -> - iter_components (Pdot (path, s, n)) (Pdot (path', s, n)) c) + NameMap.iter + (fun s (c, _) -> + iter_components (Pdot (path, s)) (Pdot (path', s)) c) comps.comp_components | Functor_comps _ -> () in iter_env_cont := (path, cont) :: !iter_env_cont in - Hashtbl.iter - (fun s pso -> - match pso with None -> () - | Some ps -> - let id = Pident (Ident.create_persistent s) in - iter_components id id ps.ps_comps) - persistent_structures; IdTbl.iter - (fun id (path, comps) -> iter_components (Pident id) path comps) + (fun id (path, comps) -> + match comps with + | Value (comps, _) -> iter_components (Pident id) path comps + | Persistent -> + match Hashtbl.find persistent_structures (Ident.name id) with + | exception Not_found | None -> () + | Some ps -> iter_components (Pident id) path ps.ps_comps) env.components let run_iter_cont l = @@ -1491,21 +1691,29 @@ let used_persistent () = persistent_structures; !r -let find_all_comps proj s (p,mcomps) = +let find_all_comps proj s (p,(mcomps, _)) = match get_components mcomps with Functor_comps _ -> [] | Structure_comps comps -> - try let (c,n) = Tbl.find_str s (proj comps) in [Pdot(p,s,n), c] + try + let c = NameMap.find s (proj comps) in + [Pdot(p,s), c] with Not_found -> [] let rec find_shadowed_comps path env = match path with Pident id -> - IdTbl.find_all (Ident.name id) env.components - | Pdot (p, s, _) -> + List.filter_map + (fun (p, data) -> + match data with + | Value x -> Some (p, x) + | Persistent -> None) + (IdTbl.find_all (Ident.name id) env.components) + | Pdot (p, s) -> let l = find_shadowed_comps p env in let l' = - List.map (find_all_comps (fun comps -> comps.comp_components) s) l in + List.map (find_all_comps (fun comps -> comps.comp_components) s) l + in List.flatten l' | Papply _ -> [] @@ -1513,7 +1721,7 @@ let find_shadowed proj1 proj2 path env = match path with Pident id -> IdTbl.find_all (Ident.name id) (proj1 env) - | Pdot (p, s, _) -> + | Pdot (p, s) -> let l = find_shadowed_comps p env in let l' = List.map (find_all_comps proj2 s) l in List.flatten l' @@ -1526,17 +1734,23 @@ let find_shadowed_types path env = (* Expand manifest module type names at the top of the given module type *) -let rec scrape_alias env ?path mty = +let rec scrape_alias env sub ?path mty = match mty, path with - Mty_ident p, _ -> + Mty_ident _, _ -> + let p = + match may_subst (Subst.modtype Keep) sub mty with + | Mty_ident p -> p + | _ -> assert false (* only [Mty_ident]s in [sub] *) + in begin try - scrape_alias env (find_modtype_expansion p env) ?path + scrape_alias env sub (find_modtype_expansion p env) ?path with Not_found -> mty end - | Mty_alias(_, path), _ -> + | Mty_alias path, _ -> + let path = may_subst Subst.module_path sub path in begin try - scrape_alias env (find_module path env).md_type ~path + scrape_alias env sub (find_module path env).md_type ~path with Not_found -> (*Location.prerr_warning Location.none (Warnings.No_cmi_file (Path.name path));*) @@ -1546,173 +1760,255 @@ let rec scrape_alias env ?path mty = !strengthen ~aliasable:true env mty path | _ -> mty -let scrape_alias env mty = scrape_alias env mty - (* Given a signature and a root path, prefix all idents in the signature by the root path and build the corresponding substitution. *) -let rec prefix_idents root pos sub = function - [] -> ([], sub) - | Sig_value(id, decl) :: rem -> - let p = Pdot(root, Ident.name id, pos) in - let nextpos = match decl.val_kind with Val_prim _ -> pos | _ -> pos+1 in - let (pl, final_sub) = prefix_idents root nextpos sub rem in - (p::pl, final_sub) - | Sig_type(id, _, _) :: rem -> - let p = Pdot(root, Ident.name id, nopos) in - let (pl, final_sub) = - prefix_idents root pos (Subst.add_type id p sub) rem in - (p::pl, final_sub) - | Sig_typext(id, _, _) :: rem -> - let p = Pdot(root, Ident.name id, pos) in +let prefix_idents root freshening_sub prefixing_sub sg = + let refresh id add_fn = function + | None -> id, None + | Some sub -> + let id' = Ident.rename id in + id', Some (add_fn id (Pident id') sub) + in + let rec prefix_idents root items_and_paths freshening_sub prefixing_sub = + function + | [] -> (List.rev items_and_paths, freshening_sub, prefixing_sub) + | Sig_value(id, _, _) as item :: rem -> + let p = Pdot(root, Ident.name id) in + prefix_idents root + ((item, p) :: items_and_paths) freshening_sub prefixing_sub rem + | Sig_type(id, td, rs, vis) :: rem -> + let p = Pdot(root, Ident.name id) in + let id', freshening_sub = refresh id Subst.add_type freshening_sub in + prefix_idents root + ((Sig_type(id', td, rs, vis), p) :: items_and_paths) + freshening_sub + (Subst.add_type id' p prefixing_sub) + rem + | Sig_typext(id, ec, es, vis) :: rem -> + let p = Pdot(root, Ident.name id) in + let id', freshening_sub = refresh id Subst.add_type freshening_sub in (* we extend the substitution in case of an inlined record *) - let (pl, final_sub) = - prefix_idents root (pos+1) (Subst.add_type id p sub) rem in - (p::pl, final_sub) - | Sig_module(id, _, _) :: rem -> - let p = Pdot(root, Ident.name id, pos) in - let (pl, final_sub) = - prefix_idents root (pos+1) (Subst.add_module id p sub) rem in - (p::pl, final_sub) - | Sig_modtype(id, _) :: rem -> - let p = Pdot(root, Ident.name id, nopos) in - let (pl, final_sub) = - prefix_idents root pos - (Subst.add_modtype id (Mty_ident p) sub) rem in - (p::pl, final_sub) - | Sig_class(id, _, _) :: rem -> + prefix_idents root + ((Sig_typext(id', ec, es, vis), p) :: items_and_paths) + freshening_sub + (Subst.add_type id' p prefixing_sub) + rem + | Sig_module(id, pres, md, rs, vis) :: rem -> + let p = Pdot(root, Ident.name id) in + let id', freshening_sub = refresh id Subst.add_module freshening_sub in + prefix_idents root + ((Sig_module(id', pres, md, rs, vis), p) :: items_and_paths) + freshening_sub + (Subst.add_module id' p prefixing_sub) + rem + | Sig_modtype(id, mtd, vis) :: rem -> + let p = Pdot(root, Ident.name id) in + let id', freshening_sub = + refresh id (fun i p s -> Subst.add_modtype i (Mty_ident p) s) + freshening_sub + in + prefix_idents root + ((Sig_modtype(id', mtd, vis), p) :: items_and_paths) + freshening_sub + (Subst.add_modtype id' (Mty_ident p) prefixing_sub) + rem + | Sig_class(id, cd, rs, vis) :: rem -> (* pretend this is a type, cf. PR#6650 *) - let p = Pdot(root, Ident.name id, pos) in - let (pl, final_sub) = - prefix_idents root (pos + 1) (Subst.add_type id p sub) rem in - (p::pl, final_sub) - | Sig_class_type(id, _, _) :: rem -> - let p = Pdot(root, Ident.name id, nopos) in - let (pl, final_sub) = - prefix_idents root pos (Subst.add_type id p sub) rem in - (p::pl, final_sub) - -let prefix_idents root sub sg = - if sub = Subst.identity then - let sgs = - try - Hashtbl.find prefixed_sg root - with Not_found -> - let sgs = ref [] in - Hashtbl.add prefixed_sg root sgs; - sgs - in - try - List.assq sg !sgs - with Not_found -> - let r = prefix_idents root 0 sub sg in - sgs := (sg, r) :: !sgs; - r - else - prefix_idents root 0 sub sg + let p = Pdot(root, Ident.name id) in + let id', freshening_sub = refresh id Subst.add_type freshening_sub in + prefix_idents root + ((Sig_class(id', cd, rs, vis), p) :: items_and_paths) + freshening_sub + (Subst.add_type id' p prefixing_sub) + rem + | Sig_class_type(id, ctd, rs, vis) :: rem -> + let p = Pdot(root, Ident.name id) in + let id', freshening_sub = refresh id Subst.add_type freshening_sub in + prefix_idents root + ((Sig_class_type(id', ctd, rs, vis), p) :: items_and_paths) + freshening_sub + (Subst.add_type id' p prefixing_sub) + rem + in + prefix_idents root [] freshening_sub prefixing_sub sg (* Compute structure descriptions *) let add_to_tbl id decl tbl = - let decls = - try Tbl.find_str id tbl with Not_found -> [] in - Tbl.add id (decl :: decls) tbl + let decls = try NameMap.find id tbl with Not_found -> [] in + NameMap.add id (decl :: decls) tbl + +let value_declaration_address (_ : t) id decl = + match decl.val_kind with + | Val_prim _ -> EnvLazy.create_failed Not_found + | _ -> EnvLazy.create_forced (Aident id) + +let extension_declaration_address (_ : t) id (_ : extension_constructor) = + EnvLazy.create_forced (Aident id) + +let class_declaration_address (_ : t) id (_ : class_declaration) = + EnvLazy.create_forced (Aident id) -let rec components_of_module ~deprecated ~loc env sub path mty = +let module_declaration_address env id presence md = + match presence with + | Mp_absent -> begin + match md.md_type with + | Mty_alias path -> EnvLazy.create (ModAlias {env; path}) + | _ -> assert false + end + | Mp_present -> + EnvLazy.create_forced (Aident id) + +let rec components_of_module ~alerts ~loc env fs ps path addr mty = { - deprecated; + alerts; loc; - comps = EnvLazy.create (env, sub, path, mty) + comps = EnvLazy.create { + cm_env = env; + cm_freshening_subst = fs; + cm_prefixing_subst = ps; + cm_path = path; + cm_addr = addr; + cm_mty = mty + } } -and components_of_module_maker (env, sub, path, mty) = - match scrape_alias env mty with +and components_of_module_maker {cm_env; cm_freshening_subst; cm_prefixing_subst; + cm_path; cm_addr; cm_mty} = + match scrape_alias cm_env cm_freshening_subst cm_mty with Mty_signature sg -> let c = - { comp_values = Tbl.empty; - comp_constrs = Tbl.empty; - comp_labels = Tbl.empty; comp_types = Tbl.empty; - comp_modules = Tbl.empty; comp_modtypes = Tbl.empty; - comp_components = Tbl.empty; comp_classes = Tbl.empty; - comp_cltypes = Tbl.empty } in - let pl, sub = prefix_idents path sub sg in - let env = ref env in + { comp_values = NameMap.empty; + comp_constrs = NameMap.empty; + comp_labels = NameMap.empty; comp_types = NameMap.empty; + comp_modules = NameMap.empty; comp_modtypes = NameMap.empty; + comp_components = NameMap.empty; comp_classes = NameMap.empty; + comp_cltypes = NameMap.empty } in + let items_and_paths, freshening_sub, prefixing_sub = + prefix_idents cm_path cm_freshening_subst cm_prefixing_subst sg + in + let env = ref cm_env in let pos = ref 0 in - List.iter2 (fun item path -> + let next_address () = + let addr : address_unforced = + Projection { parent = cm_addr; pos = !pos } + in + incr pos; + EnvLazy.create addr + in + let sub = may_subst Subst.compose freshening_sub prefixing_sub in + List.iter (fun (item, path) -> match item with - Sig_value(id, decl) -> + Sig_value(id, decl, _) -> let decl' = Subst.value_description sub decl in + let addr = + match decl.val_kind with + | Val_prim _ -> EnvLazy.create_failed Not_found + | _ -> next_address () + in c.comp_values <- - Tbl.add (Ident.name id) (decl', !pos) c.comp_values; - begin match decl.val_kind with - Val_prim _ -> () | _ -> incr pos - end - | Sig_type(id, decl, _) -> - let decl' = Subst.type_declaration sub decl in - Datarepr.set_row_name decl' (Subst.type_path sub (Path.Pident id)); + NameMap.add (Ident.name id) (decl', addr) c.comp_values; + | Sig_type(id, decl, _, _) -> + let fresh_decl = + may_subst Subst.type_declaration freshening_sub decl + in + let final_decl = Subst.type_declaration prefixing_sub fresh_decl in + Datarepr.set_row_name final_decl + (Subst.type_path prefixing_sub (Path.Pident id)); let constructors = - List.map snd (Datarepr.constructors_of_type path decl') in + List.map snd (Datarepr.constructors_of_type path final_decl) in let labels = - List.map snd (Datarepr.labels_of_type path decl') in + List.map snd (Datarepr.labels_of_type path final_decl) in c.comp_types <- - Tbl.add (Ident.name id) - ((decl', (constructors, labels)), nopos) + NameMap.add (Ident.name id) + (final_decl, (constructors, labels)) c.comp_types; List.iter (fun descr -> c.comp_constrs <- - add_to_tbl descr.cstr_name descr c.comp_constrs) + add_to_tbl descr.cstr_name (descr, None) c.comp_constrs) constructors; List.iter (fun descr -> c.comp_labels <- add_to_tbl descr.lbl_name descr c.comp_labels) labels; - env := store_type_infos id decl !env - | Sig_typext(id, ext, _) -> + env := store_type_infos id fresh_decl !env + | Sig_typext(id, ext, _, _) -> let ext' = Subst.extension_constructor sub ext in let descr = Datarepr.extension_descr path ext' in + let addr = next_address () in c.comp_constrs <- - add_to_tbl (Ident.name id) descr c.comp_constrs; - incr pos - | Sig_module(id, md, _) -> - let md' = EnvLazy.create (sub, md) in + add_to_tbl (Ident.name id) (descr, Some addr) c.comp_constrs + | Sig_module(id, pres, md, _, _) -> + let md' = + (* The prefixed items get the same scope as [cm_path], which is + the prefix. *) + EnvLazy.create (sub, Subst.Rescope (Path.scope cm_path), md) + in + let addr = + match pres with + | Mp_absent -> begin + match md.md_type with + | Mty_alias p -> + let path = may_subst Subst.module_path freshening_sub p in + EnvLazy.create (ModAlias {env = !env; path}) + | _ -> assert false + end + | Mp_present -> next_address () + in c.comp_modules <- - Tbl.add (Ident.name id) (md', !pos) c.comp_modules; - let deprecated = - Builtin_attributes.deprecated_of_attrs md.md_attributes + NameMap.add (Ident.name id) (md', addr) c.comp_modules; + let alerts = + Builtin_attributes.alerts_of_attrs md.md_attributes in let comps = - components_of_module ~deprecated ~loc:md.md_loc !env sub path - md.md_type + components_of_module ~alerts ~loc:md.md_loc !env freshening_sub + prefixing_sub path addr md.md_type in c.comp_components <- - Tbl.add (Ident.name id) (comps, !pos) c.comp_components; - env := store_module ~check:false id md !env; - incr pos - | Sig_modtype(id, decl) -> - let decl' = Subst.modtype_declaration sub decl in + NameMap.add (Ident.name id) (comps, addr) c.comp_components; + env := + store_module ~freshening_sub ~check:false id addr pres md !env + | Sig_modtype(id, decl, _) -> + let fresh_decl = + (* the fresh_decl is only going in the local temporary env, and + shouldn't be used for anything. So we make the items local. *) + may_subst (Subst.modtype_declaration Make_local) freshening_sub + decl + in + let final_decl = + (* The prefixed items get the same scope as [cm_path], which is + the prefix. *) + Subst.modtype_declaration (Rescope (Path.scope cm_path)) + prefixing_sub fresh_decl + in c.comp_modtypes <- - Tbl.add (Ident.name id) (decl', nopos) c.comp_modtypes; - env := store_modtype id decl !env - | Sig_class(id, decl, _) -> + NameMap.add (Ident.name id) final_decl c.comp_modtypes; + env := store_modtype id fresh_decl !env + | Sig_class(id, decl, _, _) -> let decl' = Subst.class_declaration sub decl in c.comp_classes <- - Tbl.add (Ident.name id) (decl', !pos) c.comp_classes; - incr pos - | Sig_class_type(id, decl, _) -> + NameMap.add (Ident.name id) (decl', next_address ()) + c.comp_classes + | Sig_class_type(id, decl, _, _) -> let decl' = Subst.cltype_declaration sub decl in c.comp_cltypes <- - Tbl.add (Ident.name id) (decl', !pos) c.comp_cltypes) - sg pl; + NameMap.add (Ident.name id) decl' c.comp_cltypes) + items_and_paths; Some (Structure_comps c) | Mty_functor(param, ty_arg, ty_res) -> + let sub = + may_subst Subst.compose cm_freshening_subst cm_prefixing_subst + in + let scoping = Subst.Rescope (Path.scope cm_path) in Some (Functor_comps { fcomp_param = param; (* fcomp_arg and fcomp_res must be prefixed eagerly, because they are interpreted in the outer environment *) - fcomp_arg = may_map (Subst.modtype sub) ty_arg; - fcomp_res = Subst.modtype sub ty_res; + fcomp_arg = may_map (Subst.modtype scoping sub) ty_arg; + fcomp_res = Subst.modtype scoping sub ty_res; fcomp_cache = Hashtbl.create 17; fcomp_subst_cache = Hashtbl.create 17 }) | Mty_ident _ @@ -1745,11 +2041,11 @@ and check_value_name name loc = done -and store_value ?check id decl env = +and store_value ?check id addr decl env = check_value_name (Ident.name id) decl.val_loc; may (fun f -> check_usage decl.val_loc id f value_declarations) check; { env with - values = IdTbl.add id decl env.values; + values = IdTbl.add id (decl, addr) env.values; summary = Env_value(env.summary, id, decl) } and store_type ~check id info env = @@ -1785,7 +2081,7 @@ and store_type ~check id info env = { env with constrs = List.fold_right - (fun (id, descr) constrs -> TycompTbl.add id descr constrs) + (fun (id, descr) constrs -> TycompTbl.add id (descr, None) constrs) constructors env.constrs; labels = @@ -1793,8 +2089,7 @@ and store_type ~check id info env = (fun (id, descr) labels -> TycompTbl.add id descr labels) labels env.labels; - types = - IdTbl.add id (info, descrs) env.types; + types = IdTbl.add id (info, descrs) env.types; summary = Env_type(env.summary, id, info) } and store_type_infos id info env = @@ -1804,11 +2099,10 @@ and store_type_infos id info env = keep track of type abbreviations (e.g. type t = float) in the computation of label representations. *) { env with - types = IdTbl.add id (info,([],[])) - env.types; + types = IdTbl.add id (info,([],[])) env.types; summary = Env_type(env.summary, id, info) } -and store_extension ~check id ext env = +and store_extension ~check id addr ext env = let loc = ext.ext_loc in if check && not loc.Location.loc_ghost && Warnings.is_active (Warnings.Unused_extension ("", false, false, false)) @@ -1830,36 +2124,41 @@ and store_extension ~check id ext env = ) end; end; + let desc = Datarepr.extension_descr (Pident id) ext in { env with - constrs = TycompTbl.add id - (Datarepr.extension_descr (Pident id) ext) - env.constrs; + constrs = TycompTbl.add id (desc, Some addr) env.constrs; summary = Env_extension(env.summary, id, ext) } -and store_module ~check id md env = +and store_module ~check ~freshening_sub id addr presence md env = let loc = md.md_loc in if check then check_usage loc id (fun s -> Warnings.Unused_module s) module_declarations; - - let deprecated = Builtin_attributes.deprecated_of_attrs md.md_attributes in + let alerts = Builtin_attributes.alerts_of_attrs md.md_attributes in + let module_decl_lazy = + match freshening_sub with + | None -> EnvLazy.create_forced md + | Some s -> EnvLazy.create (s, Subst.Rescope (Ident.scope id), md) + in { env with - modules = IdTbl.add id (EnvLazy.create (Subst.identity, md)) env.modules; + modules = IdTbl.add id (Value (module_decl_lazy, addr)) env.modules; components = IdTbl.add id - (components_of_module ~deprecated ~loc:md.md_loc - env Subst.identity (Pident id) md.md_type) + (Value + (components_of_module ~alerts ~loc:md.md_loc + env freshening_sub Subst.identity (Pident id) addr md.md_type, + addr)) env.components; - summary = Env_module(env.summary, id, md) } + summary = Env_module(env.summary, id, presence, md) } and store_modtype id info env = { env with modtypes = IdTbl.add id info env.modtypes; summary = Env_modtype(env.summary, id, info) } -and store_class id desc env = +and store_class id addr desc env = { env with - classes = IdTbl.add id desc env.classes; + classes = IdTbl.add id (desc, addr) env.classes; summary = Env_class(env.summary, id, desc) } and store_cltype id desc env = @@ -1867,6 +2166,8 @@ and store_cltype id desc env = cltypes = IdTbl.add id desc env.cltypes; summary = Env_cltype(env.summary, id, desc) } +let scrape_alias env mty = scrape_alias env None mty + (* Compute the components of a functor application in a path. *) let components_of_functor_appl f env p1 p2 = @@ -1875,10 +2176,18 @@ let components_of_functor_appl f env p1 p2 = with Not_found -> let p = Papply(p1, p2) in let sub = Subst.add_module f.fcomp_param p2 Subst.identity in - let mty = Subst.modtype sub f.fcomp_res in - let comps = components_of_module ~deprecated:None ~loc:Location.none + (* we have to apply eagerly instead of passing sub to [components_of_module] + because of the call to [check_well_formed_module]. *) + let mty = Subst.modtype (Rescope (Path.scope p)) sub f.fcomp_res in + let addr = EnvLazy.create_failed Not_found in + !check_well_formed_module env Location.(in_file !input_name) + ("the signature of " ^ Path.name p) mty; + let comps = + components_of_module ~alerts:Misc.Stdlib.String.Map.empty + ~loc:Location.none (*???*) - env Subst.identity p mty in + env None Subst.identity p addr mty + in Hashtbl.add f.fcomp_cache p2 comps; comps @@ -1897,105 +2206,113 @@ let add_functor_arg id env = summary = Env_functor_arg (env.summary, id)} let add_value ?check id desc env = - store_value ?check id desc env + let addr = value_declaration_address env id desc in + store_value ?check id addr desc env let add_type ~check id info env = store_type ~check id info env and add_extension ~check id ext env = - store_extension ~check id ext env + let addr = extension_declaration_address env id ext in + store_extension ~check id addr ext env -and add_module_declaration ?(arg=false) ~check id md env = - let env = store_module ~check id md env in +and add_module_declaration ?(arg=false) ~check id presence md env = + let addr = module_declaration_address env id presence md in + let env = store_module ~freshening_sub:None ~check id addr presence md env in if arg then add_functor_arg id env else env and add_modtype id info env = store_modtype id info env and add_class id ty env = - store_class id ty env + let addr = class_declaration_address env id ty in + store_class id addr ty env and add_cltype id ty env = store_cltype id ty env -let add_module ?arg id mty env = - add_module_declaration ~check:false ?arg id (md mty) env +let add_module ?arg id presence mty env = + add_module_declaration ~check:false ?arg id presence (md mty) env let add_local_type path info env = { env with - local_constraints = PathMap.add path info env.local_constraints } + local_constraints = Path.Map.add path info env.local_constraints } (* Insertion of bindings by name *) -let enter store_fun name data env = - let id = Ident.create name in (id, store_fun id data env) - -let enter_value ?check = enter (store_value ?check) -and enter_type = enter (store_type ~check:true) -and enter_extension = enter (store_extension ~check:true) -and enter_module_declaration ?arg id md env = - add_module_declaration ?arg ~check:true id md env - (* let (id, env) = enter store_module name md env in - (id, add_functor_arg ?arg id env) *) -and enter_modtype = enter store_modtype -and enter_class = enter store_class -and enter_cltype = enter store_cltype - -let enter_module ?arg s mty env = - let id = Ident.create s in - (id, enter_module_declaration ?arg id (md mty) env) +let enter_value ?check name desc env = + let id = Ident.create_local name in + let addr = value_declaration_address env id desc in + let env = store_value ?check id addr desc env in + (id, env) + +let enter_type ~scope name info env = + let id = Ident.create_scoped ~scope name in + let env = store_type ~check:true id info env in + (id, env) + +let enter_extension ~scope name ext env = + let id = Ident.create_scoped ~scope name in + let addr = extension_declaration_address env id ext in + let env = store_extension ~check:true id addr ext env in + (id, env) + +let enter_module_declaration ?arg id presence md env = + add_module_declaration ?arg ~check:true id presence md env + +let enter_modtype ~scope name mtd env = + let id = Ident.create_scoped ~scope name in + let env = store_modtype id mtd env in + (id, env) + +let enter_class ~scope name desc env = + let id = Ident.create_scoped ~scope name in + let addr = class_declaration_address env id desc in + let env = store_class id addr desc env in + (id, env) + +let enter_cltype ~scope name desc env = + let id = Ident.create_scoped ~scope name in + let env = store_cltype id desc env in + (id, env) + +let enter_module ~scope ?arg s presence mty env = + let id = Ident.create_scoped ~scope s in + let env = enter_module_declaration ?arg id presence (md mty) env in + (id, env) (* Insertion of all components of a signature *) let add_item comp env = match comp with - Sig_value(id, decl) -> add_value id decl env - | Sig_type(id, decl, _) -> add_type ~check:false id decl env - | Sig_typext(id, ext, _) -> add_extension ~check:false id ext env - | Sig_module(id, md, _) -> add_module_declaration ~check:false id md env - | Sig_modtype(id, decl) -> add_modtype id decl env - | Sig_class(id, decl, _) -> add_class id decl env - | Sig_class_type(id, decl, _) -> add_cltype id decl env + Sig_value(id, decl, _) -> add_value id decl env + | Sig_type(id, decl, _, _) -> add_type ~check:false id decl env + | Sig_typext(id, ext, _, _) -> add_extension ~check:false id ext env + | Sig_module(id, presence, md, _, _) -> + add_module_declaration ~check:false id presence md env + | Sig_modtype(id, decl, _) -> add_modtype id decl env + | Sig_class(id, decl, _, _) -> add_class id decl env + | Sig_class_type(id, decl, _, _) -> add_cltype id decl env let rec add_signature sg env = match sg with [] -> env | comp :: rem -> add_signature rem (add_item comp env) +let enter_signature ~scope sg env = + let sg = Subst.signature (Rescope scope) Subst.identity sg in + sg, add_signature sg env + (* Open a signature path *) -let add_components ?filter_modules slot root env0 comps = +let add_components slot root env0 comps = let add_l w comps env0 = TycompTbl.add_open slot w comps env0 in let add w comps env0 = IdTbl.add_open slot w root comps env0 in - let skipped_modules = ref StringSet.empty in - let filter tbl env0_tbl = - match filter_modules with - | None -> tbl - | Some f -> - Tbl.fold (fun m x acc -> - if f m then - Tbl.add m x acc - else begin - assert - (match IdTbl.find_name m env0_tbl~mark:false with - | (_ : _ * _) -> false - | exception _ -> true); - skipped_modules := StringSet.add m !skipped_modules; - acc - end) - tbl Tbl.empty - in - - let filter_and_add w comps env0 = - let comps = filter comps env0 in - add w comps env0 - in - let constrs = add_l (fun x -> `Constructor x) comps.comp_constrs env0.constrs in @@ -2019,15 +2336,21 @@ let add_components ?filter_modules slot root env0 comps = add (fun x -> `Class_type x) comps.comp_cltypes env0.cltypes in let components = - filter_and_add (fun x -> `Component x) comps.comp_components env0.components + let components = + NameMap.map (fun x -> Value x) comps.comp_components + in + add (fun x -> `Component x) components env0.components in let modules = - filter_and_add (fun x -> `Module x) comps.comp_modules env0.modules + let modules = + NameMap.map (fun x -> Value x) comps.comp_modules + in + add (fun x -> `Module x) modules env0.modules in { env0 with - summary = Env_open(env0.summary, !skipped_modules, root); + summary = Env_open(env0.summary, root); constrs; labels; values; @@ -2039,11 +2362,11 @@ let add_components ?filter_modules slot root env0 comps = modules; } -let open_signature ?filter_modules slot root env0 = +let open_signature slot root env0 = match get_components (find_module_descr root env0) with | Functor_comps _ -> None | Structure_comps comps -> - Some (add_components ?filter_modules slot root env0 comps) + Some (add_components slot root env0 comps) (* Open a signature from a file *) @@ -2053,45 +2376,39 @@ let open_pers_signature name env = | Some env -> env | None -> assert false (* a compilation unit cannot refer to a functor *) -let open_signature_of_initially_opened_module root env = - let load_path = !Config.load_path in - let filter_modules m = - match Misc.find_in_path_uncap load_path (m ^ ".cmi") with - | (_ : string) -> false - | exception Not_found -> true - in - open_signature None root env ~filter_modules - -let open_signature_from_env_summary root env ~hidden_submodules = - let filter_modules = - if StringSet.is_empty hidden_submodules then - None - else - Some (fun m -> not (StringSet.mem m hidden_submodules)) - in - open_signature None root env ?filter_modules - let open_signature ?(used_slot = ref false) ?(loc = Location.none) ?(toplevel = false) ovf root env = - if not toplevel && ovf = Asttypes.Fresh && not loc.Location.loc_ghost - && (Warnings.is_active (Warnings.Unused_open "") - || Warnings.is_active (Warnings.Open_shadow_identifier ("", "")) - || Warnings.is_active (Warnings.Open_shadow_label_constructor ("",""))) + let unused = + match ovf with + | Asttypes.Fresh -> Warnings.Unused_open (Path.name root) + | Asttypes.Override -> Warnings.Unused_open_bang (Path.name root) + in + let warn_unused = + Warnings.is_active unused + and warn_shadow_id = + Warnings.is_active (Warnings.Open_shadow_identifier ("", "")) + and warn_shadow_lc = + Warnings.is_active (Warnings.Open_shadow_label_constructor ("","")) + in + if not toplevel && not loc.Location.loc_ghost + && (warn_unused || warn_shadow_id || warn_shadow_lc) then begin let used = used_slot in - !add_delayed_check_forward - (fun () -> - if not !used then begin - used := true; - Location.prerr_warning loc (Warnings.Unused_open (Path.name root)) - end - ); + if warn_unused then + !add_delayed_check_forward + (fun () -> + if not !used then begin + used := true; + Location.prerr_warning loc unused + end + ); let shadowed = ref [] in let slot s b = begin match check_shadowing env b with - | Some kind when not (List.mem (kind, s) !shadowed) -> + | Some kind when + ovf = Asttypes.Fresh && not (List.mem (kind, s) !shadowed) -> shadowed := (kind, s) :: !shadowed; let w = match kind with @@ -2114,6 +2431,30 @@ let read_signature modname filename = let ps = read_pers_struct modname filename in Lazy.force ps.ps_sig +let is_identchar_latin1 = function + | 'A'..'Z' | 'a'..'z' | '_' | '\192'..'\214' | '\216'..'\246' + | '\248'..'\255' | '\'' | '0'..'9' -> true + | _ -> false + +let unit_name_of_filename fn = + match Filename.extension fn with + | ".cmi" -> begin + let unit = + String.capitalize_ascii (Filename.remove_extension fn) + in + if String.for_all is_identchar_latin1 unit then + Some unit + else + None + end + | _ -> None + +let persistent_structures_of_dir dir = + Load_path.Dir.files dir + |> List.to_seq + |> Seq.filter_map unit_name_of_filename + |> String.Set.of_seq + (* Return the CRC of the interface of the given compilation unit *) let crc_of_unit name = @@ -2131,61 +2472,63 @@ let crc_of_unit name = (* Return the list of imported interfaces with their CRCs *) let imports () = - Consistbl.extract (StringSet.elements !imported_units) crc_units + Consistbl.extract (String.Set.elements !imported_units) crc_units (* Returns true if [s] is an opaque imported module *) let is_imported_opaque s = - StringSet.mem s !imported_opaque_units + String.Set.mem s !imported_opaque_units (* Save a signature to a file *) -let save_signature_with_imports ~deprecated sg modname filename imports = +let save_signature_with_imports ~alerts sg modname filename imports = (*prerr_endline filename; List.iter (fun (name, crc) -> prerr_endline name) imports;*) Btype.cleanup_abbrev (); Subst.reset_for_saving (); - let sg = Subst.signature (Subst.for_saving Subst.identity) sg in + let sg = Subst.signature Make_local (Subst.for_saving Subst.identity) sg in let flags = List.concat [ if !Clflags.recursive_types then [Cmi_format.Rectypes] else []; if !Clflags.opaque then [Cmi_format.Opaque] else []; (if !Clflags.unsafe_string then [Cmi_format.Unsafe_string] else []); - (match deprecated with Some s -> [Deprecated s] | None -> []); + [Alerts alerts]; ] in - try - let cmi = { - cmi_name = modname; - cmi_sign = sg; - cmi_crcs = imports; - cmi_flags = flags; - } in - let crc = - output_to_file_via_temporary (* see MPR#7472, MPR#4991 *) - ~mode: [Open_binary] filename - (fun temp_filename oc -> output_cmi temp_filename oc cmi) in - (* Enter signature in persistent table so that imported_unit() - will also return its crc *) - let comps = - components_of_module ~deprecated ~loc:Location.none - empty Subst.identity - (Pident(Ident.create_persistent modname)) (Mty_signature sg) in - let ps = - { ps_name = modname; - ps_sig = lazy (Subst.signature Subst.identity sg); - ps_comps = comps; - ps_crcs = (cmi.cmi_name, Some crc) :: imports; - ps_filename = filename; - ps_flags = cmi.cmi_flags; + Misc.try_finally (fun () -> + let cmi = { + cmi_name = modname; + cmi_sign = sg; + cmi_crcs = imports; + cmi_flags = flags; } in - save_pers_struct crc ps; - cmi - with exn -> - remove_file filename; - raise exn + let crc = + output_to_file_via_temporary (* see MPR#7472, MPR#4991 *) + ~mode: [Open_binary] filename + (fun temp_filename oc -> output_cmi temp_filename oc cmi) in + (* Enter signature in persistent table so that imported_unit() + will also return its crc *) + let id = Ident.create_persistent modname in + let path = Pident id in + let addr = EnvLazy.create_forced (Aident id) in + let comps = + components_of_module ~alerts ~loc:Location.none + empty None Subst.identity path addr (Mty_signature sg) + in + let ps = + { ps_name = modname; + ps_sig = lazy (Subst.signature Make_local Subst.identity sg); + ps_comps = comps; + ps_crcs = (cmi.cmi_name, Some crc) :: imports; + ps_filename = filename; + ps_flags = cmi.cmi_flags; + } in + save_pers_struct crc ps; + cmi + ) + ~exceptionally:(fun () -> remove_file filename) -let save_signature ~deprecated sg modname filename = - save_signature_with_imports ~deprecated sg modname filename (imports()) +let save_signature ~alerts sg modname filename = + save_signature_with_imports ~alerts sg modname filename (imports()) (* Folding on environments *) @@ -2199,8 +2542,8 @@ let find_all proj1 proj2 f lid env acc = let p, desc = lookup_module_descr ~mark:true l env in begin match get_components desc with Structure_comps c -> - Tbl.fold - (fun s (data, pos) acc -> f s (Pdot (p, s, pos)) data acc) + NameMap.fold + (fun s data acc -> f s (Pdot (p, s)) data acc) (proj2 c) acc | Functor_comps _ -> acc @@ -2216,12 +2559,11 @@ let find_all_simple_list proj1 proj2 f lid env acc = let (_p, desc) = lookup_module_descr ~mark:true l env in begin match get_components desc with Structure_comps c -> - Tbl.fold + NameMap.fold (fun _s comps acc -> - match comps with - [] -> acc - | data :: _ -> - f data acc) + match comps with + | [] -> acc + | data :: _ -> f data acc) (proj2 c) acc | Functor_comps _ -> acc @@ -2229,54 +2571,114 @@ let find_all_simple_list proj1 proj2 f lid env acc = let fold_modules f lid env acc = match lid with - | None -> - let acc = - IdTbl.fold_name - (fun name (p, data) acc -> - let data = EnvLazy.force subst_modtype_maker data in - f name p data acc - ) - env.modules - acc - in - Hashtbl.fold - (fun name ps acc -> - match ps with - None -> acc - | Some ps -> - f name (Pident(Ident.create_persistent name)) - (md (Mty_signature (Lazy.force ps.ps_sig))) acc) - persistent_structures + | None -> + IdTbl.fold_name + (fun name (p, data) acc -> + match data with + | Value (data, _) -> + let data = EnvLazy.force subst_modtype_maker data in + f name p data acc + | Persistent -> + match Hashtbl.find persistent_structures name with + | exception Not_found | None -> acc + | Some ps -> + f name p (md (Mty_signature (Lazy.force ps.ps_sig))) acc) + env.modules acc - | Some l -> + | Some l -> let p, desc = lookup_module_descr ~mark:true l env in begin match get_components desc with - Structure_comps c -> - Tbl.fold - (fun s (data, pos) acc -> - f s (Pdot (p, s, pos)) - (EnvLazy.force subst_modtype_maker data) acc) - c.comp_modules - acc - | Functor_comps _ -> + | Structure_comps c -> + NameMap.fold + (fun s (data, _) acc -> + f s (Pdot (p, s)) + (EnvLazy.force subst_modtype_maker data) acc) + c.comp_modules acc + | Functor_comps _ -> + acc end let fold_values f = - find_all (fun env -> env.values) (fun sc -> sc.comp_values) f + find_all (fun env -> env.values) (fun sc -> sc.comp_values) + (fun k p (vd, _) acc -> f k p vd acc) and fold_constructors f = - find_all_simple_list (fun env -> env.constrs) (fun sc -> sc.comp_constrs) f + find_all_simple_list (fun env -> env.constrs) (fun sc -> sc.comp_constrs) + (fun (cd, _) acc -> f cd acc) and fold_labels f = find_all_simple_list (fun env -> env.labels) (fun sc -> sc.comp_labels) f and fold_types f = find_all (fun env -> env.types) (fun sc -> sc.comp_types) f and fold_modtypes f = find_all (fun env -> env.modtypes) (fun sc -> sc.comp_modtypes) f -and fold_classs f = - find_all (fun env -> env.classes) (fun sc -> sc.comp_classes) f +and fold_classes f = + find_all (fun env -> env.classes) (fun sc -> sc.comp_classes) + (fun k p (vd, _) acc -> f k p vd acc) and fold_cltypes f = find_all (fun env -> env.cltypes) (fun sc -> sc.comp_cltypes) f +let filter_non_loaded_persistent f env = + let to_remove = + IdTbl.fold_name + (fun name (_, data) acc -> + match data with + | Value _ -> acc + | Persistent -> + match Hashtbl.find persistent_structures name with + | Some _ -> acc + | exception Not_found | None -> + if f (Ident.create_persistent name) then + acc + else + String.Set.add name acc) + env.modules + String.Set.empty + in + let remove_ids tbl ids = + String.Set.fold + (fun name tbl -> IdTbl.remove (Ident.create_persistent name) tbl) + ids + tbl + in + let rec filter_summary summary ids = + if String.Set.is_empty ids then + summary + else + match summary with + | Env_empty -> summary + | Env_value (s, id, vd) -> + Env_value (filter_summary s ids, id, vd) + | Env_type (s, id, td) -> + Env_type (filter_summary s ids, id, td) + | Env_extension (s, id, ec) -> + Env_extension (filter_summary s ids, id, ec) + | Env_module (s, id, mp, md) -> + Env_module (filter_summary s ids, id, mp, md) + | Env_modtype (s, id, md) -> + Env_modtype (filter_summary s ids, id, md) + | Env_class (s, id, cd) -> + Env_class (filter_summary s ids, id, cd) + | Env_cltype (s, id, ctd) -> + Env_cltype (filter_summary s ids, id, ctd) + | Env_open (s, p) -> + Env_open (filter_summary s ids, p) + | Env_functor_arg (s, id) -> + Env_functor_arg (filter_summary s ids, id) + | Env_constraints (s, cstrs) -> + Env_constraints (filter_summary s ids, cstrs) + | Env_copy_types (s, types) -> + Env_copy_types (filter_summary s ids, types) + | Env_persistent (s, id) -> + if String.Set.mem (Ident.name id) ids then + filter_summary s (String.Set.remove (Ident.name id) ids) + else + Env_persistent (filter_summary s ids, id) + in + { env with + modules = remove_ids env.modules to_remove; + components = remove_ids env.components to_remove; + summary = filter_summary env.summary to_remove; + } (* Make the initial environment *) let (initial_safe_string, initial_unsafe_string) = @@ -2288,7 +2690,7 @@ let (initial_safe_string, initial_unsafe_string) = (* Return the environment summary *) let summary env = - if PathMap.is_empty env.local_constraints then env.summary + if Path.Map.is_empty env.local_constraints then env.summary else Env_constraints (env.summary, env.local_constraints) let last_env = ref empty @@ -2360,7 +2762,7 @@ let () = | Error (Missing_module (loc, _, _) | Illegal_value_name (loc, _) as err) when loc <> Location.none -> - Some (Location.error_of_printer loc report_error err) + Some (Location.error_of_printer ~loc report_error err) | Error err -> Some (Location.error_of_printer_file report_error err) | _ -> None ) diff --git a/typing/env.mli b/typing/env.mli index 0110504a..9fd1e8fd 100644 --- a/typing/env.mli +++ b/typing/env.mli @@ -17,24 +17,26 @@ open Types -module PathMap : Map.S with type key = Path.t - and type 'a t = 'a Map.Make(Path).t - type summary = Env_empty | Env_value of summary * Ident.t * value_description | Env_type of summary * Ident.t * type_declaration | Env_extension of summary * Ident.t * extension_constructor - | Env_module of summary * Ident.t * module_declaration + | Env_module of summary * Ident.t * module_presence * module_declaration | Env_modtype of summary * Ident.t * modtype_declaration | Env_class of summary * Ident.t * class_declaration | Env_cltype of summary * Ident.t * class_type_declaration - | Env_open of summary * Misc.StringSet.t * Path.t + | Env_open of summary * Path.t (** The string set argument of [Env_open] represents a list of module names to skip, i.e. that won't be imported in the toplevel namespace. *) | Env_functor_arg of summary * Ident.t - | Env_constraints of summary * type_declaration PathMap.t + | Env_constraints of summary * type_declaration Path.Map.t | Env_copy_types of summary * string list + | Env_persistent of summary * Ident.t + +type address = + | Aident of Ident.t + | Adot of address * int type t @@ -71,21 +73,35 @@ val find_class: Path.t -> t -> class_declaration val find_cltype: Path.t -> t -> class_type_declaration val find_type_expansion: - Path.t -> t -> type_expr list * type_expr * int option + Path.t -> t -> type_expr list * type_expr * int val find_type_expansion_opt: - Path.t -> t -> type_expr list * type_expr * int option + Path.t -> t -> type_expr list * type_expr * int (* Find the manifest type information associated to a type for the sake of the compiler's type-based optimisations. *) val find_modtype_expansion: Path.t -> t -> module_type + +val find_value_address: Path.t -> t -> address +val find_module_address: Path.t -> t -> address +val find_class_address: Path.t -> t -> address +val find_constructor_address: Path.t -> t -> address + val add_functor_arg: Ident.t -> t -> t val is_functor_arg: Path.t -> t -> bool -val normalize_path: Location.t option -> t -> Path.t -> Path.t -(* Normalize the path to a concrete value or module. + +val normalize_module_path: Location.t option -> t -> Path.t -> Path.t +(* Normalize the path to a concrete module. If the option is None, allow returning dangling paths. Otherwise raise a Missing_module error, and may add forgotten head as required global. *) + +val normalize_type_path: Location.t option -> t -> Path.t -> Path.t +(* Normalize the prefix part of the type path *) + val normalize_path_prefix: Location.t option -> t -> Path.t -> Path.t -(* Only normalize the prefix part of the path *) +(* Normalize the prefix part of other kinds of paths + (value/modtype/etc) *) + + val reset_required_globals: unit -> unit val get_required_globals: unit -> Ident.t list val add_required_global: Ident.t -> unit @@ -94,7 +110,7 @@ val has_local_constraints: t -> bool (* Lookup by long identifiers *) -(* ?loc is used to report 'deprecated module' warnings *) +(* ?loc is used to report 'deprecated module' warnings and other alerts *) val lookup_value: ?loc:Location.t -> ?mark:bool -> @@ -127,8 +143,11 @@ val lookup_cltype: ?loc:Location.t -> ?mark:bool -> Longident.t -> t -> Path.t * class_type_declaration -val copy_types: string list -> t -> t - (* Used only in Typecore.duplicate_ident_types. *) +type copy_of_types +val make_copy_of_types: string list -> t -> copy_of_types +val do_copy_types: copy_of_types -> t -> t +(** [do_copy_types copy env] will raise a fatal error if the values in + [env] are different from the env passed to [make_copy_of_types]. *) exception Recmodule (* Raise by lookup_module when the identifier refers @@ -141,14 +160,34 @@ val add_value: ?check:(string -> Warnings.t) -> Ident.t -> value_description -> t -> t val add_type: check:bool -> Ident.t -> type_declaration -> t -> t val add_extension: check:bool -> Ident.t -> extension_constructor -> t -> t -val add_module: ?arg:bool -> Ident.t -> module_type -> t -> t +val add_module: + ?arg:bool -> Ident.t -> module_presence -> module_type -> t -> t val add_module_declaration: ?arg:bool -> check:bool -> Ident.t -> - module_declaration -> t -> t + module_presence -> module_declaration -> t -> t val add_modtype: Ident.t -> modtype_declaration -> t -> t val add_class: Ident.t -> class_declaration -> t -> t val add_cltype: Ident.t -> class_type_declaration -> t -> t val add_local_type: Path.t -> type_declaration -> t -> t +(* Insertion of persistent signatures *) + +(* [add_persistent_structure id env] is an environment such that + module [id] points to the persistent structure contained in the + external compilation unit with the same name. + + The compilation unit itself is looked up in the load path when the + contents of the module is accessed. *) +val add_persistent_structure : Ident.t -> t -> t + +(* Returns the set of persistent structures found in the given + directory. *) +val persistent_structures_of_dir : Load_path.Dir.t -> Misc.Stdlib.String.Set.t + +(* [filter_non_loaded_persistent f env] removes all the persistent + structures that are not yet loaded and for which [f] returns + [false]. *) +val filter_non_loaded_persistent : (Ident.t -> bool) -> t -> t + (* Insertion of all fields of a signature. *) val add_item: signature_item -> t -> t @@ -163,23 +202,6 @@ val open_signature: Asttypes.override_flag -> Path.t -> t -> t option -(* Similar to [open_signature], except that modules from the load path - have precedence over sub-modules of the opened module. - - For instance, if opening a module [M] with a sub-module [X]: - - if the load path contains a [x.cmi] file, then resolving [X] in the - new environment yields the same result as resolving [X] in the - old environment - - otherwise, in the new environment [X] resolves to [M.X] -*) -val open_signature_of_initially_opened_module: - Path.t -> t -> t option - -(* Similar to [open_signature] except that sub-modules of the opened modules - that are in [hidden_submodules] are not added to the environment. *) -val open_signature_from_env_summary: - Path.t -> t -> hidden_submodules:Misc.StringSet.t -> t option - val open_pers_signature: string -> t -> t (* Insertion by name *) @@ -187,14 +209,23 @@ val open_pers_signature: string -> t -> t val enter_value: ?check:(string -> Warnings.t) -> string -> value_description -> t -> Ident.t * t -val enter_type: string -> type_declaration -> t -> Ident.t * t -val enter_extension: string -> extension_constructor -> t -> Ident.t * t -val enter_module: ?arg:bool -> string -> module_type -> t -> Ident.t * t +val enter_type: scope:int -> string -> type_declaration -> t -> Ident.t * t +val enter_extension: + scope:int -> string -> extension_constructor -> t -> Ident.t * t +val enter_module: + scope:int -> ?arg:bool -> string -> module_presence -> + module_type -> t -> Ident.t * t val enter_module_declaration: - ?arg:bool -> Ident.t -> module_declaration -> t -> t -val enter_modtype: string -> modtype_declaration -> t -> Ident.t * t -val enter_class: string -> class_declaration -> t -> Ident.t * t -val enter_cltype: string -> class_type_declaration -> t -> Ident.t * t + ?arg:bool -> Ident.t -> module_presence -> module_declaration -> t -> t +val enter_modtype: + scope:int -> string -> modtype_declaration -> t -> Ident.t * t +val enter_class: scope:int -> string -> class_declaration -> t -> Ident.t * t +val enter_cltype: + scope:int -> string -> class_type_declaration -> t -> Ident.t * t + +(* Same as [add_signature] but refreshes (new stamp) and rescopes bound idents + in the process. *) +val enter_signature: scope:int -> signature -> t -> signature * t (* Initialize the cache of in-core module interfaces. *) val reset_cache: unit -> unit @@ -211,10 +242,11 @@ val get_unit_name: unit -> string val read_signature: string -> string -> signature (* Arguments: module name, file name. Results: signature. *) val save_signature: - deprecated:string option -> signature -> string -> string -> Cmi_format.cmi_infos + alerts:string Misc.Stdlib.String.Map.t -> signature -> string -> string -> + Cmi_format.cmi_infos (* Arguments: signature, module name, file name. *) val save_signature_with_imports: - deprecated:string option -> + alerts:string Misc.Stdlib.String.Map.t -> signature -> string -> string -> (string * Digest.t option) list -> Cmi_format.cmi_infos (* Arguments: signature, module name, file name, @@ -289,6 +321,9 @@ val set_type_used_callback: (* Forward declaration to break mutual recursion with Includemod. *) val check_modtype_inclusion: (loc:Location.t -> t -> module_type -> Path.t -> module_type -> unit) ref +(* Forward declaration to break mutual recursion with Typemod. *) +val check_well_formed_module: + (t -> Location.t -> string -> module_type -> unit) ref (* Forward declaration to break mutual recursion with Typecore. *) val add_delayed_check_forward: ((unit -> unit) -> unit) ref (* Forward declaration to break mutual recursion with Mtype. *) @@ -320,7 +355,7 @@ val fold_modules: val fold_modtypes: (string -> Path.t -> modtype_declaration -> 'a -> 'a) -> Longident.t option -> t -> 'a -> 'a -val fold_classs: +val fold_classes: (string -> Path.t -> class_declaration -> 'a -> 'a) -> Longident.t option -> t -> 'a -> 'a val fold_cltypes: @@ -331,6 +366,8 @@ val fold_cltypes: val scrape_alias: t -> module_type -> module_type val check_value_name: string -> Location.t -> unit +val print_address : Format.formatter -> address -> unit + module Persistent_signature : sig type t = { filename : string; (** Name of the file containing the signature. *) diff --git a/typing/envaux.ml b/typing/envaux.ml index caa67f38..2780cc04 100644 --- a/typing/envaux.ml +++ b/typing/envaux.ml @@ -47,12 +47,12 @@ let rec env_from_summary sum subst = Env.add_extension ~check:false id (Subst.extension_constructor subst desc) (env_from_summary s subst) - | Env_module(s, id, desc) -> - Env.add_module_declaration ~check:false id - (Subst.module_declaration subst desc) + | Env_module(s, id, pres, desc) -> + Env.add_module_declaration ~check:false id pres + (Subst.module_declaration Keep subst desc) (env_from_summary s subst) | Env_modtype(s, id, desc) -> - Env.add_modtype id (Subst.modtype_declaration subst desc) + Env.add_modtype id (Subst.modtype_declaration Keep subst desc) (env_from_summary s subst) | Env_class(s, id, desc) -> Env.add_class id (Subst.class_declaration subst desc) @@ -60,27 +60,32 @@ let rec env_from_summary sum subst = | Env_cltype (s, id, desc) -> Env.add_cltype id (Subst.cltype_declaration subst desc) (env_from_summary s subst) - | Env_open(s, hidden_submodules, path) -> + | Env_open(s, path) -> let env = env_from_summary s subst in let path' = Subst.module_path subst path in - begin match Env.open_signature_from_env_summary path' env - ~hidden_submodules with + begin match Env.open_signature Asttypes.Override path' env with | Some env -> env | None -> assert false + | exception Not_found -> raise (Error (Module_not_found path')) end - | Env_functor_arg(Env_module(s, id, desc), id') when Ident.same id id' -> + | Env_functor_arg(Env_module(s, id, pres, desc), id') + when Ident.same id id' -> Env.add_module_declaration ~check:false - id (Subst.module_declaration subst desc) + id pres (Subst.module_declaration Keep subst desc) ~arg:true (env_from_summary s subst) | Env_functor_arg _ -> assert false | Env_constraints(s, map) -> - PathMap.fold + Path.Map.fold (fun path info -> Env.add_local_type (Subst.type_path subst path) (Subst.type_declaration subst info)) map (env_from_summary s subst) | Env_copy_types (s, sl) -> - Env.copy_types sl (env_from_summary s subst) + let env = env_from_summary s subst in + Env.do_copy_types (Env.make_copy_of_types sl env) env + | Env_persistent (s, id) -> + let env = env_from_summary s subst in + Env.add_persistent_structure id env in Hashtbl.add env_cache (sum, subst) env; env diff --git a/typing/ident.ml b/typing/ident.ml index 1235b058..b10b3dec 100644 --- a/typing/ident.ml +++ b/typing/ident.ml @@ -13,44 +13,85 @@ (* *) (**************************************************************************) -open Format +let lowest_scope = 0 +let highest_scope = 100000000 -type t = { stamp: int; name: string; flags: int } - -let global_flag = 1 -let predef_exn_flag = 2 +type t = + | Local of { name: string; stamp: int } + | Scoped of { name: string; stamp: int; scope: int } + | Global of string + | Predef of { name: string; stamp: int } + (* the stamp is here only for fast comparison, but the name of + predefined identifiers is always unique. *) (* A stamp of 0 denotes a persistent identifier *) let currentstamp = ref 0 +let predefstamp = ref 0 -let create s = - incr currentstamp; - { name = s; stamp = !currentstamp; flags = 0 } - -let create_predef_exn s = +let create_scoped ~scope s = incr currentstamp; - { name = s; stamp = !currentstamp; - flags = predef_exn_flag lor global_flag } - -let create_persistent s = - { name = s; stamp = 0; flags = global_flag } + Scoped { name = s; stamp = !currentstamp; scope } -let rename i = +let create_local s = incr currentstamp; - { i with stamp = !currentstamp } + Local { name = s; stamp = !currentstamp } -let name i = i.name +let create_predef s = + incr predefstamp; + Predef { name = s; stamp = !predefstamp } -let with_name i name = { i with name; } - -let unique_name i = i.name ^ "_" ^ string_of_int i.stamp - -let unique_toplevel_name i = i.name ^ "/" ^ string_of_int i.stamp - -let persistent i = (i.stamp = 0) - -let equal i1 i2 = i1.name = i2.name +let create_persistent s = + Global s + +let name = function + | Local { name; _ } + | Scoped { name; _ } + | Global name + | Predef { name; _ } -> name + +let rename = function + | Local { name; stamp = _ } + | Scoped { name; stamp = _; scope = _ } -> + incr currentstamp; + Local { name; stamp = !currentstamp } + | id -> + Misc.fatal_errorf "Ident.rename %s" (name id) + +let unique_name = function + | Local { name; stamp } + | Scoped { name; stamp } -> name ^ "_" ^ Int.to_string stamp + | Global name -> + (* we're adding a fake stamp, because someone could have named his unit + [Foo_123] and since we're using unique_name to produce symbol names, + we might clash with an ident [Local { "Foo"; 123 }]. *) + name ^ "_0" + | Predef { name; _ } -> + (* we know that none of the predef names (currently) finishes in + "_", and that their name is unique. *) + name + +let unique_toplevel_name = function + | Local { name; stamp } + | Scoped { name; stamp } -> name ^ "/" ^ Int.to_string stamp + | Global name + | Predef { name; _ } -> name + +let persistent = function + | Global _ -> true + | _ -> false + +let equal i1 i2 = + match i1, i2 with + | Local { name = name1; _ }, Local { name = name2; _ } + | Scoped { name = name1; _ }, Scoped { name = name2; _ } + | Global name1, Global name2 -> + name1 = name2 + | Predef { stamp = s1; _ }, Predef { stamp = s2 } -> + (* if they don't have the same stamp, they don't have the same name *) + s1 = s2 + | _ -> + false let same i1 i2 = i1 = i2 (* Possibly more efficient version (with a real compiler, at least): @@ -58,12 +99,17 @@ let same i1 i2 = i1 = i2 then i1.stamp = i2.stamp else i2.stamp = 0 && i1.name = i2.name *) -let compare i1 i2 = Pervasives.compare i1 i2 +let compare i1 i2 = Stdlib.compare i1 i2 -let binding_time i = i.stamp +let stamp = function + | Local { stamp; _ } + | Scoped { stamp; _ } -> stamp + | _ -> 0 -let current_time() = !currentstamp -let set_current_time t = currentstamp := max !currentstamp t +let scope = function + | Scoped { scope; _ } -> scope + | Local _ -> highest_scope + | Global _ | Predef _ -> lowest_scope let reinit_level = ref (-1) @@ -72,24 +118,34 @@ let reinit () = then reinit_level := !currentstamp else currentstamp := !reinit_level -let hide i = - { i with stamp = -1 } - -let global i = - (i.flags land global_flag) <> 0 - -let is_predef_exn i = - (i.flags land predef_exn_flag) <> 0 - -let print ppf i = - match i.stamp with - | 0 -> fprintf ppf "%s!" i.name - | -1 -> fprintf ppf "%s#" i.name - | n -> - let stampstr = - if !Clflags.unique_ids then Printf.sprintf "/%i" n else "" - in - fprintf ppf "%s%s%s" i.name stampstr (if global i then "g" else "") +let global = function + | Local _ + | Scoped _ -> false + | Global _ + | Predef _ -> true + +let is_predef = function + | Predef _ -> true + | _ -> false + +let print ~with_scope ppf = + let open Format in + function + | Global name -> fprintf ppf "%s!" name + | Predef { name; stamp = n } -> + fprintf ppf "%s%s!" name + (if !Clflags.unique_ids then sprintf "/%i" n else "") + | Local { name; stamp = n } -> + fprintf ppf "%s%s" name + (if !Clflags.unique_ids then sprintf "/%i" n else "") + | Scoped { name; stamp = n; scope } -> + fprintf ppf "%s%s%s" name + (if !Clflags.unique_ids then sprintf "/%i" n else "") + (if with_scope then sprintf "[%i]" scope else "") + +let print_with_scope ppf id = print ~with_scope:true ppf id + +let print ppf id = print ~with_scope:false ppf id type 'a tbl = Empty @@ -141,7 +197,7 @@ let rec add id data = function Empty -> Node(Empty, {ident = id; data = data; previous = None}, Empty, 1) | Node(l, k, r, h) -> - let c = compare id.name k.ident.name in + let c = compare (name id) (name k.ident) in if c = 0 then Node(l, {ident = id; data = data; previous = Some k}, r, h) else if c < 0 then @@ -149,47 +205,79 @@ let rec add id data = function else balance l k (add id data r) -let rec find_stamp s = function +let rec min_binding = function + Empty -> raise Not_found + | Node (Empty, d, _, _) -> d + | Node (l, _, _, _) -> min_binding l + +let rec remove_min_binding = function + Empty -> invalid_arg "Map.remove_min_elt" + | Node (Empty, _, r, _) -> r + | Node (l, d, r, _) -> balance (remove_min_binding l) d r + +let merge t1 t2 = + match (t1, t2) with + (Empty, t) -> t + | (t, Empty) -> t + | (_, _) -> + let d = min_binding t2 in + balance t1 d (remove_min_binding t2) + +let rec remove id = function + Empty -> + Empty + | (Node (l, k, r, h) as m) -> + let c = compare (name id) (name k.ident) in + if c = 0 then + match k.previous with + | None -> merge l r + | Some k -> Node (l, k, r, h) + else if c < 0 then + let ll = remove id l in if l == ll then m else balance ll k r + else + let rr = remove id r in if r == rr then m else balance l k rr + +let rec find_previous id = function None -> raise Not_found | Some k -> - if k.ident.stamp = s then k.data else find_stamp s k.previous + if same id k.ident then k.data else find_previous id k.previous let rec find_same id = function Empty -> raise Not_found | Node(l, k, r, _) -> - let c = compare id.name k.ident.name in + let c = compare (name id) (name k.ident) in if c = 0 then - if id.stamp = k.ident.stamp + if same id k.ident then k.data - else find_stamp id.stamp k.previous + else find_previous id k.previous else find_same id (if c < 0 then l else r) -let rec find_name name = function +let rec find_name n = function Empty -> raise Not_found | Node(l, k, r, _) -> - let c = compare name k.ident.name in + let c = compare n (name k.ident) in if c = 0 then k.ident, k.data else - find_name name (if c < 0 then l else r) + find_name n (if c < 0 then l else r) let rec get_all = function | None -> [] | Some k -> (k.ident, k.data) :: get_all k.previous -let rec find_all name = function +let rec find_all n = function Empty -> [] | Node(l, k, r, _) -> - let c = compare name k.ident.name in + let c = compare n (name k.ident) in if c = 0 then (k.ident, k.data) :: get_all k.previous else - find_all name (if c < 0 then l else r) + find_all n (if c < 0 then l else r) let rec fold_aux f stack accu = function Empty -> @@ -224,22 +312,36 @@ let key_name = "" let make_key_generator () = let c = ref 1 in - fun id -> - let stamp = !c in - decr c ; - { id with name = key_name; stamp = stamp; } + function + | Local _ + | Scoped _ -> + let stamp = !c in + decr c ; + Local { name = key_name; stamp = stamp } + | global_id -> + Misc.fatal_errorf "Ident.make_key_generator () %s" (name global_id) let compare x y = - let c = x.stamp - y.stamp in - if c <> 0 then c - else - let c = compare x.name y.name in - if c <> 0 then c - else - compare x.flags y.flags + match x, y with + | Local x, Local y -> + let c = x.stamp - y.stamp in + if c <> 0 then c + else compare x.name y.name + | Local _, _ -> 1 + | _, Local _ -> (-1) + | Scoped x, Scoped y -> + let c = x.stamp - y.stamp in + if c <> 0 then c + else compare x.name y.name + | Scoped _, _ -> 1 + | _, Scoped _ -> (-1) + | Global x, Global y -> compare x y + | Global _, _ -> 1 + | _, Global _ -> (-1) + | Predef { stamp = s1; _ }, Predef { stamp = s2; _ } -> compare s1 s2 let output oc id = output_string oc (unique_name id) -let hash i = (Char.code i.name.[0]) lxor i.stamp +let hash i = (Char.code (name i).[0]) lxor (stamp i) let original_equal = equal include Identifiable.Make (struct diff --git a/typing/ident.mli b/typing/ident.mli index e34ce37f..65ddb9fc 100644 --- a/typing/ident.mli +++ b/typing/ident.mli @@ -24,35 +24,42 @@ include Identifiable.S with type t := t - [compare] compares identifiers by binding location *) +val print_with_scope : Format.formatter -> t -> unit + (** Same as {!print} except that it will also add a "[n]" suffix + if the scope of the argument is [n]. *) -val create: string -> t + +val create_scoped: scope:int -> string -> t +val create_local: string -> t val create_persistent: string -> t -val create_predef_exn: string -> t +val create_predef: string -> t + val rename: t -> t + (** Creates an identifier with the same name as the input, a fresh + stamp, and no scope. + @raises [Fatal_error] if called on a persistent / predef ident. *) + val name: t -> string -val with_name: t -> string -> t val unique_name: t -> string val unique_toplevel_name: t -> string val persistent: t -> bool val same: t -> t -> bool - (* Compare identifiers by binding location. - Two identifiers are the same either if they are both - non-persistent and have been created by the same call to - [new], or if they are both persistent and have the same - name. *) + (** Compare identifiers by binding location. + Two identifiers are the same either if they are both + non-persistent and have been created by the same call to + [create_*], or if they are both persistent and have the same + name. *) + val compare: t -> t -> int -val hide: t -> t - (* Return an identifier with same name as the given identifier, - but stamp different from any stamp returned by new. - When put in a 'a tbl, this identifier can only be looked - up by name. *) val global: t -> bool -val is_predef_exn: t -> bool +val is_predef: t -> bool + +val scope: t -> int + +val lowest_scope : int +val highest_scope: int -val binding_time: t -> int -val current_time: unit -> int -val set_current_time: int -> unit val reinit: unit -> unit type 'a tbl @@ -66,7 +73,7 @@ val find_all: string -> 'a tbl -> (t * 'a) list val fold_name: (t -> 'a -> 'b -> 'b) -> 'a tbl -> 'b -> 'b val fold_all: (t -> 'a -> 'b -> 'b) -> 'a tbl -> 'b -> 'b val iter: (t -> 'a -> unit) -> 'a tbl -> unit - +val remove: t -> 'a tbl -> 'a tbl (* Idents for sharing keys *) diff --git a/typing/includeclass.ml b/typing/includeclass.ml index 5501631a..b641e138 100644 --- a/typing/includeclass.ml +++ b/typing/includeclass.ml @@ -21,7 +21,7 @@ let class_types env cty1 cty2 = Ctype.match_class_types env cty1 cty2 let class_type_declarations ~loc env cty1 cty2 = - Builtin_attributes.check_deprecated_inclusion + Builtin_attributes.check_alerts_inclusion ~def:cty1.clty_loc ~use:cty2.clty_loc loc @@ -57,7 +57,7 @@ let include_err ppf = fprintf ppf "The classes do not have the same number of type parameters" | CM_Type_parameter_mismatch (env, trace) -> - Printtyp.report_unification_error ppf env ~unif:false trace + Printtyp.report_unification_error ppf env trace (function ppf -> fprintf ppf "A type parameter has type") (function ppf -> @@ -70,19 +70,19 @@ let include_err ppf = "is not matched by the class type" Printtyp.class_type cty2) | CM_Parameter_mismatch (env, trace) -> - Printtyp.report_unification_error ppf env ~unif:false trace + Printtyp.report_unification_error ppf env trace (function ppf -> fprintf ppf "A parameter has type") (function ppf -> fprintf ppf "but is expected to have type") | CM_Val_type_mismatch (lab, env, trace) -> - Printtyp.report_unification_error ppf env ~unif:false trace + Printtyp.report_unification_error ppf env trace (function ppf -> fprintf ppf "The instance variable %s@ has type" lab) (function ppf -> fprintf ppf "but is expected to have type") | CM_Meth_type_mismatch (lab, env, trace) -> - Printtyp.report_unification_error ppf env ~unif:false trace + Printtyp.report_unification_error ppf env trace (function ppf -> fprintf ppf "The method %s@ has type" lab) (function ppf -> diff --git a/typing/includecore.ml b/typing/includecore.ml index 9ee520f3..98e99b8c 100644 --- a/typing/includecore.ml +++ b/typing/includecore.ml @@ -27,7 +27,7 @@ exception Dont_match let value_descriptions ~loc env name (vd1 : Types.value_description) (vd2 : Types.value_description) = - Builtin_attributes.check_deprecated_inclusion + Builtin_attributes.check_alerts_inclusion ~def:vd1.val_loc ~use:vd2.val_loc loc @@ -169,36 +169,34 @@ let report_type_mismatch0 first second decl ppf err = "uses unboxed representation" | Immediate -> pr "%s is not an immediate type" first -let report_type_mismatch first second decl ppf = - List.iter - (fun err -> - if err = Manifest then () else - Format.fprintf ppf "@ %a." (report_type_mismatch0 first second decl) err) +let report_type_mismatch first second decl ppf err = + if err = Manifest then () else + Format.fprintf ppf "@ %a." (report_type_mismatch0 first second decl) err let rec compare_constructor_arguments ~loc env cstr params1 params2 arg1 arg2 = match arg1, arg2 with | Types.Cstr_tuple arg1, Types.Cstr_tuple arg2 -> - if List.length arg1 <> List.length arg2 then [Field_arity cstr] + if List.length arg1 <> List.length arg2 then Some (Field_arity cstr) else if (* Ctype.equal must be called on all arguments at once, cf. PR#7378 *) Ctype.equal env true (params1 @ arg1) (params2 @ arg2) - then [] else [Field_type cstr] + then None else Some (Field_type cstr) | Types.Cstr_record l1, Types.Cstr_record l2 -> compare_records env ~loc params1 params2 0 l1 l2 - | _ -> [Field_type cstr] + | _ -> Some (Field_type cstr) and compare_variants ~loc env params1 params2 n (cstrs1 : Types.constructor_declaration list) (cstrs2 : Types.constructor_declaration list) = match cstrs1, cstrs2 with - [], [] -> [] - | [], c::_ -> [Field_missing (true, c.Types.cd_id)] - | c::_, [] -> [Field_missing (false, c.Types.cd_id)] + [], [] -> None + | [], c::_ -> Some (Field_missing (true, c.Types.cd_id)) + | c::_, [] -> Some (Field_missing (false, c.Types.cd_id)) | cd1::rem1, cd2::rem2 -> if Ident.name cd1.cd_id <> Ident.name cd2.cd_id then - [Field_names (n, cd1.cd_id, cd2.cd_id)] + Some (Field_names (n, cd1.cd_id, cd2.cd_id)) else begin - Builtin_attributes.check_deprecated_inclusion + Builtin_attributes.check_alerts_inclusion ~def:cd1.cd_loc ~use:cd2.cd_loc loc @@ -210,14 +208,14 @@ and compare_variants ~loc env params1 params2 n if Ctype.equal env true [r1] [r2] then compare_constructor_arguments ~loc env cd1.cd_id [r1] [r2] cd1.cd_args cd2.cd_args - else [Field_type cd1.cd_id] + else Some (Field_type cd1.cd_id) | Some _, None | None, Some _ -> - [Field_type cd1.cd_id] + Some (Field_type cd1.cd_id) | _ -> compare_constructor_arguments ~loc env cd1.cd_id params1 params2 cd1.cd_args cd2.cd_args in - if r <> [] then r + if r <> None then r else compare_variants ~loc env params1 params2 (n+1) rem1 rem2 end @@ -226,13 +224,15 @@ and compare_records ~loc env params1 params2 n (labels1 : Types.label_declaration list) (labels2 : Types.label_declaration list) = match labels1, labels2 with - [], [] -> [] - | [], l::_ -> [Field_missing (true, l.Types.ld_id)] - | l::_, [] -> [Field_missing (false, l.Types.ld_id)] + [], [] -> None + | [], l::_ -> Some (Field_missing (true, l.Types.ld_id)) + | l::_, [] -> Some (Field_missing (false, l.Types.ld_id)) | ld1::rem1, ld2::rem2 -> if Ident.name ld1.ld_id <> Ident.name ld2.ld_id - then [Field_names (n, ld1.ld_id, ld2.ld_id)] - else if ld1.ld_mutable <> ld2.ld_mutable then [Field_mutable ld1.ld_id] else begin + then Some (Field_names (n, ld1.ld_id, ld2.ld_id)) + else if ld1.ld_mutable <> ld2.ld_mutable then + Some (Field_mutable ld1.ld_id) + else begin Builtin_attributes.check_deprecated_mutable_inclusion ~def:ld1.ld_loc ~use:ld2.ld_loc @@ -246,47 +246,47 @@ and compare_records ~loc env params1 params2 n (n+1) rem1 rem2 else - [Field_type ld1.ld_id] + Some (Field_type ld1.ld_id) end -let type_declarations ?(equality = false) ~loc env ~mark name decl1 id decl2 = - Builtin_attributes.check_deprecated_inclusion +let type_declarations ?(equality = false) ~loc env ~mark name decl1 path decl2 = + Builtin_attributes.check_alerts_inclusion ~def:decl1.type_loc ~use:decl2.type_loc loc decl1.type_attributes decl2.type_attributes name; - if decl1.type_arity <> decl2.type_arity then [Arity] else - if not (private_flags decl1 decl2) then [Privacy] else + if decl1.type_arity <> decl2.type_arity then Some Arity else + if not (private_flags decl1 decl2) then Some Privacy else let err = match (decl1.type_manifest, decl2.type_manifest) with (_, None) -> if Ctype.equal env true decl1.type_params decl2.type_params - then [] else [Constraint] + then None else Some Constraint | (Some ty1, Some ty2) -> if type_manifest env ty1 decl1.type_params ty2 decl2.type_params decl2.type_private - then [] else [Manifest] + then None else Some Manifest | (None, Some ty2) -> let ty1 = - Btype.newgenty (Tconstr(Pident id, decl2.type_params, ref Mnil)) + Btype.newgenty (Tconstr(path, decl2.type_params, ref Mnil)) in if Ctype.equal env true decl1.type_params decl2.type_params then - if Ctype.equal env false [ty1] [ty2] then [] - else [Manifest] - else [Constraint] + if Ctype.equal env false [ty1] [ty2] then None + else Some Manifest + else Some Constraint in - if err <> [] then err else + if err <> None then err else let err = match (decl2.type_kind, decl1.type_unboxed.unboxed, decl2.type_unboxed.unboxed) with - | Type_abstract, _, _ -> [] - | _, true, false -> [Unboxed_representation false] - | _, false, true -> [Unboxed_representation true] - | _ -> [] + | Type_abstract, _, _ -> None + | _, true, false -> Some (Unboxed_representation false) + | _, false, true -> Some (Unboxed_representation true) + | _ -> None in - if err <> [] then err else + if err <> None then err else let err = match (decl1.type_kind, decl2.type_kind) with - (_, Type_abstract) -> [] + (_, Type_abstract) -> None | (Type_variant cstrs1, Type_variant cstrs2) -> if mark then begin let mark cstrs usage name decl = @@ -301,7 +301,7 @@ let type_declarations ?(equality = false) ~loc env ~mark name decl1 id decl2 = then Env.Positive else Env.Privatize in mark cstrs1 usage name decl1; - if equality then mark cstrs2 Env.Positive (Ident.name id) decl2 + if equality then mark cstrs2 Env.Positive (Path.name path) decl2 end; compare_variants ~loc env decl1.type_params decl2.type_params 1 cstrs1 cstrs2 @@ -310,12 +310,12 @@ let type_declarations ?(equality = false) ~loc env ~mark name decl1 id decl2 = compare_records ~loc env decl1.type_params decl2.type_params 1 labels1 labels2 in - if err <> [] || rep1 = rep2 then err else - [Record_representation (rep2 = Record_float)] - | (Type_open, Type_open) -> [] - | (_, _) -> [Kind] + if err <> None || rep1 = rep2 then err else + Some (Record_representation (rep2 = Record_float)) + | (Type_open, Type_open) -> None + | (_, _) -> Some Kind in - if err <> [] then err else + if err <> None then err else let abstr = decl2.type_kind = Type_abstract && decl2.type_manifest = None in (* If attempt to assign a non-immediate type (e.g. string) to a type that * must be immediate, then we error *) @@ -323,13 +323,13 @@ let type_declarations ?(equality = false) ~loc env ~mark name decl1 id decl2 = if abstr && not decl1.type_immediate && decl2.type_immediate then - [Immediate] - else [] + Some Immediate + else None in - if err <> [] then err else + if err <> None then err else let need_variance = abstr || decl1.type_private = Private || decl1.type_kind = Type_open in - if not need_variance then [] else + if not need_variance then None else let abstr = abstr || decl2.type_private = Private in let opn = decl2.type_kind = Type_open && decl2.type_manifest = None in let constrained ty = not (Btype.(is_Tvar (repr ty))) in @@ -344,7 +344,7 @@ let type_declarations ?(equality = false) ~loc env ~mark name decl1 id decl2 = let (p1,n1,i1,j1) = get_lower v1 and (p2,n2,i2,j2) = get_lower v2 in imp abstr (imp p2 p1 && imp n2 n1 && imp i2 i1 && imp j2 j1)) decl2.type_params (List.combine decl1.type_variance decl2.type_variance) - then [] else [Variance] + then None else Some Variance (* Inclusion between extension constructors *) @@ -362,21 +362,22 @@ let extension_constructors ~loc env ~mark id ext1 ext2 = let ty2 = Btype.newgenty (Tconstr(ext2.ext_type_path, ext2.ext_type_params, ref Mnil)) in - if Ctype.equal env true - (ty1 :: ext1.ext_type_params) - (ty2 :: ext2.ext_type_params) - then - if compare_constructor_arguments ~loc env (Ident.create "") + if not (Ctype.equal env true (ty1 :: ext1.ext_type_params) + (ty2 :: ext2.ext_type_params)) + then Some (Field_type id) + else + let r = + compare_constructor_arguments ~loc env id ext1.ext_type_params ext2.ext_type_params - ext1.ext_args ext2.ext_args = [] then - if match ext1.ext_ret_type, ext2.ext_ret_type with - Some r1, Some r2 when not (Ctype.equal env true [r1] [r2]) -> false - | Some _, None | None, Some _ -> false - | _ -> true - then + ext1.ext_args ext2.ext_args + in + if r <> None then r else + match ext1.ext_ret_type, ext2.ext_ret_type with + Some r1, Some r2 when not (Ctype.equal env true [r1] [r2]) -> + Some (Field_type id) + | Some _, None | None, Some _ -> + Some (Field_type id) + | _ -> match ext1.ext_private, ext2.ext_private with - Private, Public -> false - | _, _ -> true - else false - else false - else false + Private, Public -> Some Privacy + | _, _ -> None diff --git a/typing/includecore.mli b/typing/includecore.mli index 5193a9d0..820cc61a 100644 --- a/typing/includecore.mli +++ b/typing/includecore.mli @@ -44,15 +44,15 @@ val type_declarations: ?equality:bool -> loc:Location.t -> Env.t -> mark:bool -> string -> - type_declaration -> Ident.t -> type_declaration -> type_mismatch list + type_declaration -> Path.t -> type_declaration -> type_mismatch option val extension_constructors: loc:Location.t -> Env.t -> mark:bool -> Ident.t -> - extension_constructor -> extension_constructor -> bool + extension_constructor -> extension_constructor -> type_mismatch option (* val class_types: Env.t -> class_type -> class_type -> bool *) val report_type_mismatch: - string -> string -> string -> Format.formatter -> type_mismatch list -> unit + string -> string -> string -> Format.formatter -> type_mismatch -> unit diff --git a/typing/includemod.ml b/typing/includemod.ml index c1a691a2..670dd947 100644 --- a/typing/includemod.ml +++ b/typing/includemod.ml @@ -16,7 +16,6 @@ (* Inclusion checks for the module language *) open Misc -open Path open Typedtree open Types @@ -24,9 +23,9 @@ type symptom = Missing_field of Ident.t * Location.t * string (* kind *) | Value_descriptions of Ident.t * value_description * value_description | Type_declarations of Ident.t * type_declaration - * type_declaration * Includecore.type_mismatch list - | Extension_constructors of - Ident.t * extension_constructor * extension_constructor + * type_declaration * Includecore.type_mismatch + | Extension_constructors of Ident.t * extension_constructor + * extension_constructor * Includecore.type_mismatch | Module_types of module_type * module_type | Modtype_infos of Ident.t * modtype_declaration * modtype_declaration | Modtype_permutation @@ -81,43 +80,45 @@ let value_descriptions ~loc env ~mark cxt subst id vd1 vd2 = (* Inclusion between type declarations *) -let type_declarations ~loc env ~mark ?(old_env=env) cxt subst id decl1 decl2 = +let type_declarations ~loc env ~mark ?old_env:_ cxt subst id decl1 decl2 = let mark = mark_positive mark in if mark then Env.mark_type_used (Ident.name id) decl1; let decl2 = Subst.type_declaration subst decl2 in - let err = + match Includecore.type_declarations ~loc env ~mark - (Ident.name id) decl1 id decl2 - in - if err <> [] then - raise(Error[cxt, old_env, Type_declarations(id, decl1, decl2, err)]) + (Ident.name id) decl1 (Path.Pident id) decl2 + with + | None -> () + | Some err -> + raise(Error[cxt, env, Type_declarations(id, decl1, decl2, err)]) (* Inclusion between extension constructors *) let extension_constructors ~loc env ~mark cxt subst id ext1 ext2 = let mark = mark_positive mark in let ext2 = Subst.extension_constructor subst ext2 in - if Includecore.extension_constructors ~loc env ~mark id ext1 ext2 - then () - else raise(Error[cxt, env, Extension_constructors(id, ext1, ext2)]) + match Includecore.extension_constructors ~loc env ~mark id ext1 ext2 with + | None -> () + | Some err -> + raise(Error[cxt, env, Extension_constructors(id, ext1, ext2, err)]) (* Inclusion between class declarations *) -let class_type_declarations ~loc ~old_env env cxt subst id decl1 decl2 = +let class_type_declarations ~loc ~old_env:_ env cxt subst id decl1 decl2 = let decl2 = Subst.cltype_declaration subst decl2 in match Includeclass.class_type_declarations ~loc env decl1 decl2 with [] -> () | reason -> - raise(Error[cxt, old_env, + raise(Error[cxt, env, Class_type_declarations(id, decl1, decl2, reason)]) -let class_declarations ~old_env env cxt subst id decl1 decl2 = +let class_declarations ~old_env:_ env cxt subst id decl1 decl2 = let decl2 = Subst.class_declaration subst decl2 in match Includeclass.class_declarations env decl1 decl2 with [] -> () | reason -> - raise(Error[cxt, old_env, Class_declarations(id, decl1, decl2, reason)]) + raise(Error[cxt, env, Class_declarations(id, decl1, decl2, reason)]) (* Expand a module type identifier when possible *) @@ -165,24 +166,34 @@ let kind_of_field_desc = function | Field_class _ -> "class" | Field_classtype _ -> "class type" +(** Map indexed by both field types and names. + This avoids name clashes between different sorts of fields + such as values and types. *) +module FieldMap = Map.Make(struct + type t = field_desc + let compare = Stdlib.compare + end) + let item_ident_name = function - Sig_value(id, d) -> (id, d.val_loc, Field_value(Ident.name id)) - | Sig_type(id, d, _) -> (id, d.type_loc, Field_type(Ident.name id)) - | Sig_typext(id, d, _) -> (id, d.ext_loc, Field_typext(Ident.name id)) - | Sig_module(id, d, _) -> (id, d.md_loc, Field_module(Ident.name id)) - | Sig_modtype(id, d) -> (id, d.mtd_loc, Field_modtype(Ident.name id)) - | Sig_class(id, d, _) -> (id, d.cty_loc, Field_class(Ident.name id)) - | Sig_class_type(id, d, _) -> (id, d.clty_loc, Field_classtype(Ident.name id)) + Sig_value(id, d, _) -> (id, d.val_loc, Field_value(Ident.name id)) + | Sig_type(id, d, _, _) -> (id, d.type_loc, Field_type(Ident.name id)) + | Sig_typext(id, d, _, _) -> (id, d.ext_loc, Field_typext(Ident.name id)) + | Sig_module(id, _, d, _, _) -> (id, d.md_loc, Field_module(Ident.name id)) + | Sig_modtype(id, d, _) -> (id, d.mtd_loc, Field_modtype(Ident.name id)) + | Sig_class(id, d, _, _) -> (id, d.cty_loc, Field_class(Ident.name id)) + | Sig_class_type(id, d, _, _) -> + (id, d.clty_loc, Field_classtype(Ident.name id)) let is_runtime_component = function - | Sig_value(_,{val_kind = Val_prim _}) - | Sig_type(_,_,_) - | Sig_modtype(_,_) - | Sig_class_type(_,_,_) -> false - | Sig_value(_,_) - | Sig_typext(_,_,_) - | Sig_module(_,_,_) - | Sig_class(_, _,_) -> true + | Sig_value(_,{val_kind = Val_prim _}, _) + | Sig_type(_,_,_,_) + | Sig_module(_,Mp_absent,_,_,_) + | Sig_modtype(_,_,_) + | Sig_class_type(_,_,_,_) -> false + | Sig_value(_,_,_) + | Sig_typext(_,_,_,_) + | Sig_module(_,Mp_present,_,_,_) + | Sig_class(_,_,_,_) -> true (* Print a coercion *) @@ -208,7 +219,7 @@ let rec print_coercion ppf c = | Tcoerce_primitive {pc_desc; pc_env = _; pc_type} -> pr "prim %s@ (%a)" pc_desc.Primitive.prim_name Printtyp.raw_type_expr pc_type - | Tcoerce_alias (p, c) -> + | Tcoerce_alias (_, p, c) -> pr "@[<2>alias %a@ (%a)@]" Printtyp.path p print_coercion c @@ -239,42 +250,33 @@ let rec modtypes ~loc env ~mark cxt subst mty1 mty2 = try_modtypes ~loc env ~mark cxt subst mty1 mty2 with Dont_match -> - raise(Error[cxt, env, Module_types(mty1, Subst.modtype subst mty2)]) + raise(Error[cxt, env, + Module_types(mty1, Subst.modtype Make_local subst mty2)]) | Error reasons as err -> match mty1, mty2 with Mty_alias _, _ | _, Mty_alias _ -> raise err | _ -> - raise(Error((cxt, env, Module_types(mty1, Subst.modtype subst mty2)) + raise(Error((cxt, env, + Module_types(mty1, Subst.modtype Make_local subst mty2)) :: reasons)) and try_modtypes ~loc env ~mark cxt subst mty1 mty2 = - match (mty1, mty2) with - | (Mty_alias(pres1, p1), Mty_alias(pres2, p2)) -> begin + match mty1, mty2 with + | Mty_alias p1, Mty_alias p2 -> if Env.is_functor_arg p2 env then raise (Error[cxt, env, Invalid_module_alias p2]); if not (Path.same p1 p2) then begin - let p1 = Env.normalize_path None env p1 - and p2 = Env.normalize_path None env (Subst.module_path subst p2) in + let p1 = Env.normalize_module_path None env p1 + and p2 = Env.normalize_module_path None env + (Subst.module_path subst p2) + in if not (Path.same p1 p2) then raise Dont_match end; - match pres1, pres2 with - | Mta_present, Mta_present -> Tcoerce_none - (* Should really be Tcoerce_ignore if it existed *) - | Mta_absent, Mta_absent -> Tcoerce_none - (* Should really be Tcoerce_empty if it existed *) - | Mta_present, Mta_absent -> Tcoerce_none - | Mta_absent, Mta_present -> - let p1 = try - Env.normalize_path (Some Location.none) env p1 - with Env.Error (Env.Missing_module (_, _, path)) -> - raise (Error[cxt, env, Unbound_module_path path]) - in - Tcoerce_alias (p1, Tcoerce_none) - end - | (Mty_alias(pres1, p1), _) -> begin + Tcoerce_none + | (Mty_alias p1, _) -> begin let p1 = try - Env.normalize_path (Some Location.none) env p1 + Env.normalize_module_path (Some Location.none) env p1 with Env.Error (Env.Missing_module (_, _, path)) -> raise (Error[cxt, env, Unbound_module_path path]) in @@ -282,16 +284,13 @@ and try_modtypes ~loc env ~mark cxt subst mty1 mty2 = Mtype.strengthen ~aliasable:true env (expand_module_alias env cxt p1) p1 in - let cc = modtypes ~loc env ~mark cxt subst mty1 mty2 in - match pres1 with - | Mta_present -> cc - | Mta_absent -> Tcoerce_alias (p1, cc) + modtypes ~loc env ~mark cxt subst mty1 mty2 end | (Mty_ident p1, _) when may_expand_module_path env p1 -> try_modtypes ~loc env ~mark cxt subst (expand_module_path env cxt p1) mty2 | (_, Mty_ident _) -> - try_modtypes2 ~loc env ~mark cxt mty1 (Subst.modtype subst mty2) + try_modtypes2 ~loc env ~mark cxt mty1 (Subst.modtype Keep subst mty2) | (Mty_signature sig1, Mty_signature sig2) -> signatures ~loc env ~mark cxt subst sig1 sig2 | (Mty_functor(param1, None, res1), Mty_functor(_param2, None, res2)) -> @@ -302,14 +301,15 @@ and try_modtypes ~loc env ~mark cxt subst mty1 mty2 = end | (Mty_functor(param1, Some arg1, res1), Mty_functor(param2, Some arg2, res2)) -> - let arg2' = Subst.modtype subst arg2 in + let arg2' = Subst.modtype Keep subst arg2 in let cc_arg = modtypes ~loc env ~mark:(negate_mark mark) (Arg param1::cxt) Subst.identity arg2' arg1 in let cc_res = - modtypes ~loc (Env.add_module param1 arg2' env) ~mark - (Body param1::cxt) (Subst.add_module param2 (Pident param1) subst) + modtypes ~loc (Env.add_module param1 Mp_present arg2' env) ~mark + (Body param1::cxt) + (Subst.add_module param2 (Path.Pident param1) subst) res1 res2 in begin match (cc_arg, cc_res) with @@ -342,7 +342,7 @@ and signatures ~loc env ~mark cxt subst sig1 sig2 = let (id_pos_list,_) = List.fold_left (fun (l,pos) -> function - Sig_module (id, _, _) -> + Sig_module (id, Mp_present, _, _, _) -> ((id,pos,Tcoerce_none)::l , pos+1) | item -> (l, if is_runtime_component item then pos+1 else pos)) ([], 0) sig1 in @@ -350,13 +350,26 @@ and signatures ~loc env ~mark cxt subst sig1 sig2 = The table is indexed by kind and name of component *) let rec build_component_table pos tbl = function [] -> pos, tbl + | (Sig_value (_, _, Hidden) + |Sig_type (_, _, _, Hidden) + |Sig_typext (_, _, _, Hidden) + |Sig_module (_, _, _, _, Hidden) + |Sig_modtype (_, _, Hidden) + |Sig_class (_, _, _, Hidden) + |Sig_class_type (_, _, _, Hidden) + ) as item :: rem -> + let pos = if is_runtime_component item then pos + 1 else pos in + build_component_table pos tbl rem (* do not pair private items. *) | item :: rem -> let (id, _loc, name) = item_ident_name item in - let nextpos = if is_runtime_component item then pos + 1 else pos in + let pos, nextpos = + if is_runtime_component item then pos, pos + 1 + else -1, pos + in build_component_table nextpos - (Tbl.add name (id, item, pos) tbl) rem in + (FieldMap.add name (id, item, pos) tbl) rem in let len1, comps1 = - build_component_table 0 Tbl.empty sig1 in + build_component_table 0 FieldMap.empty sig1 in let len2 = List.fold_left (fun n i -> if is_runtime_component i then n + 1 else n) @@ -386,7 +399,7 @@ and signatures ~loc env ~mark cxt subst sig1 sig2 = let (id2, loc, name2) = item_ident_name item2 in let name2, report = match item2, name2 with - Sig_type (_, {type_manifest=None}, _), Field_type s + Sig_type (_, {type_manifest=None}, _, _), Field_type s when Btype.is_row_name s -> (* Do not report in case of failure, as the main type will generate an error *) @@ -394,15 +407,15 @@ and signatures ~loc env ~mark cxt subst sig1 sig2 = | _ -> name2, true in begin try - let (id1, item1, pos1) = Tbl.find name2 comps1 in + let (id1, item1, pos1) = FieldMap.find name2 comps1 in let new_subst = match item2 with Sig_type _ -> - Subst.add_type id2 (Pident id1) subst + Subst.add_type id2 (Path.Pident id1) subst | Sig_module _ -> - Subst.add_module id2 (Pident id1) subst + Subst.add_module id2 (Path.Pident id1) subst | Sig_modtype _ -> - Subst.add_modtype id2 (Mty_ident (Pident id1)) subst + Subst.add_modtype id2 (Mty_ident (Path.Pident id1)) subst | Sig_value _ | Sig_typext _ | Sig_class _ | Sig_class_type _ -> subst @@ -428,7 +441,7 @@ and signature_components ~loc old_env ~mark env cxt subst paired = in match paired with [] -> [] - | (Sig_value(id1, valdecl1), Sig_value(_id2, valdecl2), pos) :: rem -> + | (Sig_value(id1, valdecl1, _), Sig_value(_id2, valdecl2, _), pos) :: rem -> let cc = value_descriptions ~loc env ~mark cxt subst id1 valdecl1 valdecl2 in @@ -436,37 +449,46 @@ and signature_components ~loc old_env ~mark env cxt subst paired = Val_prim _ -> comps_rec rem | _ -> (pos, cc) :: comps_rec rem end - | (Sig_type(id1, tydecl1, _), Sig_type(_id2, tydecl2, _), _pos) :: rem -> + | (Sig_type(id1, tydecl1, _, _), Sig_type(_id2, tydecl2, _, _), _pos) :: rem + -> type_declarations ~loc ~old_env env ~mark cxt subst id1 tydecl1 tydecl2; comps_rec rem - | (Sig_typext(id1, ext1, _), Sig_typext(_id2, ext2, _), pos) + | (Sig_typext(id1, ext1, _, _), Sig_typext(_id2, ext2, _, _), pos) :: rem -> extension_constructors ~loc env ~mark cxt subst id1 ext1 ext2; (pos, Tcoerce_none) :: comps_rec rem - | (Sig_module(id1, mty1, _), Sig_module(_id2, mty2, _), pos) :: rem -> + | (Sig_module(id1, pres1, mty1, _, _), + Sig_module(_id2, pres2, mty2, _, _), pos) :: rem -> begin let cc = module_declarations ~loc env ~mark cxt subst id1 mty1 mty2 in - (pos, cc) :: comps_rec rem - | (Sig_modtype(id1, info1), Sig_modtype(_id2, info2), _pos) :: rem -> + let rem = comps_rec rem in + match pres1, pres2, mty1.md_type with + | Mp_present, Mp_present, _ -> (pos, cc) :: rem + | _, Mp_absent, _ -> rem + | Mp_absent, Mp_present, Mty_alias p1 -> + (pos, Tcoerce_alias (env, p1, cc)) :: rem + | Mp_absent, Mp_present, _ -> assert false + end + | (Sig_modtype(id1, info1, _), Sig_modtype(_id2, info2, _), _pos) :: rem -> modtype_infos ~loc env ~mark cxt subst id1 info1 info2; comps_rec rem - | (Sig_class(id1, decl1, _), Sig_class(_id2, decl2, _), pos) :: rem -> + | (Sig_class(id1, decl1, _, _), Sig_class(_id2, decl2, _, _), pos) :: rem -> class_declarations ~old_env env cxt subst id1 decl1 decl2; (pos, Tcoerce_none) :: comps_rec rem - | (Sig_class_type(id1, info1, _), - Sig_class_type(_id2, info2, _), _pos) :: rem -> + | (Sig_class_type(id1, info1, _, _), + Sig_class_type(_id2, info2, _, _), _pos) :: rem -> class_type_declarations ~loc ~old_env env cxt subst id1 info1 info2; comps_rec rem | _ -> assert false and module_declarations ~loc env ~mark cxt subst id1 md1 md2 = - Builtin_attributes.check_deprecated_inclusion + Builtin_attributes.check_alerts_inclusion ~def:md1.md_loc ~use:md2.md_loc loc md1.md_attributes md2.md_attributes (Ident.name id1); - let p1 = Pident id1 in + let p1 = Path.Pident id1 in if mark_positive mark then Env.mark_module_used (Ident.name id1) md1.md_loc; modtypes ~loc env ~mark (Module id1::cxt) subst @@ -475,13 +497,13 @@ and module_declarations ~loc env ~mark cxt subst id1 md1 md2 = (* Inclusion between module type specifications *) and modtype_infos ~loc env ~mark cxt subst id info1 info2 = - Builtin_attributes.check_deprecated_inclusion + Builtin_attributes.check_alerts_inclusion ~def:info1.mtd_loc ~use:info2.mtd_loc loc info1.mtd_attributes info2.mtd_attributes (Ident.name id); - let info2 = Subst.modtype_declaration subst info2 in + let info2 = Subst.modtype_declaration Keep subst info2 in let cxt' = Modtype id :: cxt in try match (info1.mtd_type, info2.mtd_type) with @@ -490,7 +512,7 @@ and modtype_infos ~loc env ~mark cxt subst id info1 info2 = | (Some mty1, Some mty2) -> check_modtype_equiv ~loc env ~mark cxt' mty1 mty2 | (None, Some mty2) -> - check_modtype_equiv ~loc env ~mark cxt' (Mty_ident(Pident id)) mty2 + check_modtype_equiv ~loc env ~mark cxt' (Mty_ident(Path.Pident id)) mty2 with Error reasons -> raise(Error((cxt, env, Modtype_infos(id, info1, info2)) :: reasons)) @@ -509,9 +531,9 @@ and check_modtype_equiv ~loc env ~mark cxt mty1 mty2 = let can_alias env path = let rec no_apply = function - | Pident _ -> true - | Pdot(p, _, _) -> no_apply p - | Papply _ -> false + | Path.Pident _ -> true + | Path.Pdot(p, _) -> no_apply p + | Path.Papply _ -> false in no_apply path && not (Env.is_functor_arg path env) @@ -557,7 +579,6 @@ let modtypes env m1 m2 = (* Error report *) open Format -open Printtyp let show_loc msg ppf loc = let pos = loc.Location.loc_start in @@ -570,41 +591,49 @@ let show_locs ppf (loc1, loc2) = let include_err ppf = function | Missing_field (id, loc, kind) -> - fprintf ppf "The %s `%a' is required but not provided" kind ident id; + fprintf ppf "The %s `%a' is required but not provided" + kind Printtyp.ident id; show_loc "Expected declaration" ppf loc | Value_descriptions(id, d1, d2) -> fprintf ppf "@[Values do not match:@ %a@;<1 -2>is not included in@ %a@]" - (value_description id) d1 (value_description id) d2; - show_locs ppf (d1.val_loc, d2.val_loc); - | Type_declarations(id, d1, d2, errs) -> + !Oprint.out_sig_item (Printtyp.tree_of_value_description id d1) + !Oprint.out_sig_item (Printtyp.tree_of_value_description id d2); + show_locs ppf (d1.val_loc, d2.val_loc) + | Type_declarations(id, d1, d2, err) -> fprintf ppf "@[@[%s:@;<1 2>%a@ %s@;<1 2>%a@]%a%a@]" "Type declarations do not match" - (type_declaration id) d1 + !Oprint.out_sig_item + (Printtyp.tree_of_type_declaration id d1 Trec_first) "is not included in" - (type_declaration id) d2 + !Oprint.out_sig_item + (Printtyp.tree_of_type_declaration id d2 Trec_first) show_locs (d1.type_loc, d2.type_loc) (Includecore.report_type_mismatch - "the first" "the second" "declaration") errs - | Extension_constructors(id, x1, x2) -> - fprintf ppf - "@[Extension declarations do not match:@ \ - %a@;<1 -2>is not included in@ %a@]" - (extension_constructor id) x1 - (extension_constructor id) x2; - show_locs ppf (x1.ext_loc, x2.ext_loc) + "the first" "the second" "declaration") err + | Extension_constructors(id, x1, x2, err) -> + fprintf ppf "@[@[%s:@;<1 2>%a@ %s@;<1 2>%a@]%a%a@]" + "Extension declarations do not match" + !Oprint.out_sig_item + (Printtyp.tree_of_extension_constructor id x1 Text_first) + "is not included in" + !Oprint.out_sig_item + (Printtyp.tree_of_extension_constructor id x2 Text_first) + show_locs (x1.ext_loc, x2.ext_loc) + (Includecore.report_type_mismatch + "the first" "the second" "declaration") err | Module_types(mty1, mty2)-> fprintf ppf "@[Modules do not match:@ \ %a@;<1 -2>is not included in@ %a@]" - modtype mty1 - modtype mty2 + !Oprint.out_module_type (Printtyp.tree_of_modtype mty1) + !Oprint.out_module_type (Printtyp.tree_of_modtype mty2) | Modtype_infos(id, d1, d2) -> fprintf ppf "@[Module type declarations do not match:@ \ %a@;<1 -2>does not match@ %a@]" - (modtype_declaration id) d1 - (modtype_declaration id) d2 + !Oprint.out_sig_item (Printtyp.tree_of_modtype_declaration id d1) + !Oprint.out_sig_item (Printtyp.tree_of_modtype_declaration id d2) | Modtype_permutation -> fprintf ppf "Illegal permutation of structure fields" | Interface_mismatch(impl_name, intf_name) -> @@ -614,15 +643,17 @@ let include_err ppf = function fprintf ppf "@[Class type declarations do not match:@ \ %a@;<1 -2>does not match@ %a@]@ %a" - (Printtyp.cltype_declaration id) d1 - (Printtyp.cltype_declaration id) d2 + !Oprint.out_sig_item + (Printtyp.tree_of_cltype_declaration id d1 Trec_first) + !Oprint.out_sig_item + (Printtyp.tree_of_cltype_declaration id d2 Trec_first) Includeclass.report_error reason | Class_declarations(id, d1, d2, reason) -> fprintf ppf "@[Class declarations do not match:@ \ %a@;<1 -2>does not match@ %a@]@ %a" - (Printtyp.class_declaration id) d1 - (Printtyp.class_declaration id) d2 + !Oprint.out_sig_item (Printtyp.tree_of_class_declaration id d1 Trec_first) + !Oprint.out_sig_item (Printtyp.tree_of_class_declaration id d2 Trec_first) Includeclass.report_error reason | Unbound_modtype_path path -> fprintf ppf "Unbound module type %a" Printtyp.path path @@ -633,13 +664,14 @@ let include_err ppf = function let rec context ppf = function Module id :: rem -> - fprintf ppf "@[<2>module %a%a@]" ident id args rem + fprintf ppf "@[<2>module %a%a@]" Printtyp.ident id args rem | Modtype id :: rem -> - fprintf ppf "@[<2>module type %a =@ %a@]" ident id context_mty rem + fprintf ppf "@[<2>module type %a =@ %a@]" + Printtyp.ident id context_mty rem | Body x :: rem -> fprintf ppf "functor (%s) ->@ %a" (argname x) context_mty rem | Arg x :: rem -> - fprintf ppf "functor (%a : %a) -> ..." ident x context_mty rem + fprintf ppf "functor (%a : %a) -> ..." Printtyp.ident x context_mty rem | [] -> fprintf ppf "" and context_mty ppf = function @@ -650,7 +682,7 @@ and args ppf = function Body x :: rem -> fprintf ppf "(%s)%a" (argname x) args rem | Arg x :: rem -> - fprintf ppf "(%a :@ %a) : ..." ident x context_mty rem + fprintf ppf "(%a :@ %a) : ..." Printtyp.ident x context_mty rem | cxt -> fprintf ppf " :@ %a" context_mty cxt and argname x = @@ -660,16 +692,16 @@ and argname x = let path_of_context = function Module id :: rem -> let rec subm path = function - [] -> path - | Module id :: rem -> subm (Pdot (path, Ident.name id, -1)) rem + | [] -> path + | Module id :: rem -> subm (Path.Pdot (path, Ident.name id)) rem | _ -> assert false - in subm (Pident id) rem + in subm (Path.Pident id) rem | _ -> assert false let context ppf cxt = if cxt = [] then () else if List.for_all (function Module _ -> true | _ -> false) cxt then - fprintf ppf "In module %a:@ " path (path_of_context cxt) + fprintf ppf "In module %a:@ " Printtyp.path (path_of_context cxt) else fprintf ppf "@[At position@ %a@]@ " context cxt @@ -696,8 +728,9 @@ let report_error ppf errs = else if !pe then (fprintf ppf "...@ "; pe := false) in let print_errs ppf = List.iter (include_err' ppf) in - fprintf ppf "@[%a%a@]" print_errs errs include_err err - + Printtyp.Conflicts.reset(); + fprintf ppf "@[%a%a%t@]" print_errs errs include_err err + Printtyp.Conflicts.print (* We could do a better job to split the individual error items as sub-messages of the main interface mismatch on the whole unit. *) diff --git a/typing/includemod.mli b/typing/includemod.mli index 2909ee99..1996894e 100644 --- a/typing/includemod.mli +++ b/typing/includemod.mli @@ -36,7 +36,8 @@ val modtypes: module_type -> module_type -> module_coercion val check_modtype_inclusion : - loc:Location.t -> Env.t -> Types.module_type -> Path.t -> Types.module_type -> unit + loc:Location.t -> Env.t -> Types.module_type -> Path.t -> Types.module_type -> + unit (** [check_modtype_inclusion ~loc env mty1 path1 mty2] checks that the functor application F(M) is well typed, where mty2 is the type of the argument of F and path1/mty1 is the path/unstrenghened type of M. *) @@ -58,9 +59,9 @@ type symptom = Missing_field of Ident.t * Location.t * string (* kind *) | Value_descriptions of Ident.t * value_description * value_description | Type_declarations of Ident.t * type_declaration - * type_declaration * Includecore.type_mismatch list - | Extension_constructors of - Ident.t * extension_constructor * extension_constructor + * type_declaration * Includecore.type_mismatch + | Extension_constructors of Ident.t * extension_constructor + * extension_constructor * Includecore.type_mismatch | Module_types of module_type * module_type | Modtype_infos of Ident.t * modtype_declaration * modtype_declaration | Modtype_permutation diff --git a/typing/mtype.ml b/typing/mtype.ml index f22ac743..adbd7d70 100644 --- a/typing/mtype.ml +++ b/typing/mtype.ml @@ -30,13 +30,13 @@ let rec scrape env mty = end | _ -> mty -let freshen mty = - Subst.modtype Subst.identity mty +let freshen ~scope mty = + Subst.modtype (Rescope scope) Subst.identity mty let rec strengthen ~aliasable env mty p = match scrape env mty with Mty_signature sg -> - Mty_signature(strengthen_sig ~aliasable env sg p 0) + Mty_signature(strengthen_sig ~aliasable env sg p) | Mty_functor(param, arg, res) when !Clflags.applicative_functors && Ident.name param <> "*" -> Mty_functor(param, arg, @@ -44,95 +44,89 @@ let rec strengthen ~aliasable env mty p = | mty -> mty -and strengthen_sig ~aliasable env sg p pos = +and strengthen_sig ~aliasable env sg p = match sg with [] -> [] - | (Sig_value(_, desc) as sigelt) :: rem -> - let nextpos = - match desc.val_kind with - | Val_prim _ -> pos - | _ -> pos + 1 - in - sigelt :: strengthen_sig ~aliasable env rem p nextpos - | Sig_type(id, {type_kind=Type_abstract}, _) :: - (Sig_type(id', {type_private=Private}, _) :: _ as rem) + | (Sig_value(_, _, _) as sigelt) :: rem -> + sigelt :: strengthen_sig ~aliasable env rem p + | Sig_type(id, {type_kind=Type_abstract}, _, _) :: + (Sig_type(id', {type_private=Private}, _, _) :: _ as rem) when Ident.name id = Ident.name id' ^ "#row" -> - strengthen_sig ~aliasable env rem p pos - | Sig_type(id, decl, rs) :: rem -> + strengthen_sig ~aliasable env rem p + | Sig_type(id, decl, rs, vis) :: rem -> let newdecl = match decl.type_manifest, decl.type_private, decl.type_kind with Some _, Public, _ -> decl | Some _, Private, (Type_record _ | Type_variant _) -> decl | _ -> let manif = - Some(Btype.newgenty(Tconstr(Pdot(p, Ident.name id, nopos), + Some(Btype.newgenty(Tconstr(Pdot(p, Ident.name id), decl.type_params, ref Mnil))) in if decl.type_kind = Type_abstract then { decl with type_private = Public; type_manifest = manif } else { decl with type_manifest = manif } in - Sig_type(id, newdecl, rs) :: strengthen_sig ~aliasable env rem p pos + Sig_type(id, newdecl, rs, vis) :: strengthen_sig ~aliasable env rem p | (Sig_typext _ as sigelt) :: rem -> - sigelt :: strengthen_sig ~aliasable env rem p (pos+1) - | Sig_module(id, md, rs) :: rem -> + sigelt :: strengthen_sig ~aliasable env rem p + | Sig_module(id, pres, md, rs, vis) :: rem -> let str = - strengthen_decl ~aliasable env md (Pdot(p, Ident.name id, pos)) + strengthen_decl ~aliasable env md (Pdot(p, Ident.name id)) in - Sig_module(id, str, rs) + Sig_module(id, pres, str, rs, vis) :: strengthen_sig ~aliasable - (Env.add_module_declaration ~check:false id md env) rem p (pos+1) + (Env.add_module_declaration ~check:false id pres md env) rem p (* Need to add the module in case it defines manifest module types *) - | Sig_modtype(id, decl) :: rem -> + | Sig_modtype(id, decl, vis) :: rem -> let newdecl = match decl.mtd_type with None -> - {decl with mtd_type = Some(Mty_ident(Pdot(p,Ident.name id,nopos)))} + {decl with mtd_type = Some(Mty_ident(Pdot(p,Ident.name id)))} | Some _ -> decl in - Sig_modtype(id, newdecl) :: - strengthen_sig ~aliasable (Env.add_modtype id decl env) rem p pos + Sig_modtype(id, newdecl, vis) :: + strengthen_sig ~aliasable (Env.add_modtype id decl env) rem p (* Need to add the module type in case it is manifest *) | (Sig_class _ as sigelt) :: rem -> - sigelt :: strengthen_sig ~aliasable env rem p (pos+1) + sigelt :: strengthen_sig ~aliasable env rem p | (Sig_class_type _ as sigelt) :: rem -> - sigelt :: strengthen_sig ~aliasable env rem p pos + sigelt :: strengthen_sig ~aliasable env rem p and strengthen_decl ~aliasable env md p = match md.md_type with | Mty_alias _ -> md - | _ when aliasable -> {md with md_type = Mty_alias(Mta_present, p)} + | _ when aliasable -> {md with md_type = Mty_alias p} | mty -> {md with md_type = strengthen ~aliasable env mty p} let () = Env.strengthen := strengthen -let rec make_aliases_absent mty = +let rec make_aliases_absent pres mty = match mty with - | Mty_alias(_, p) -> - Mty_alias(Mta_absent, p) + | Mty_alias _ -> Mp_absent, mty | Mty_signature sg -> - Mty_signature(make_aliases_absent_sig sg) + pres, Mty_signature(make_aliases_absent_sig sg) | Mty_functor(param, arg, res) -> - Mty_functor(param, arg, make_aliases_absent res) + let _, res = make_aliases_absent Mp_present res in + pres, Mty_functor(param, arg, res) | mty -> - mty + pres, mty and make_aliases_absent_sig sg = match sg with [] -> [] - | Sig_module(id, md, rs) :: rem -> - let str = - { md with md_type = make_aliases_absent md.md_type } - in - Sig_module(id, str, rs) :: make_aliases_absent_sig rem + | Sig_module(id, pres, md, rs, priv) :: rem -> + let pres, md_type = make_aliases_absent pres md.md_type in + let md = { md with md_type } in + Sig_module(id, pres, md, rs, priv) :: make_aliases_absent_sig rem | sigelt :: rem -> sigelt :: make_aliases_absent_sig rem -let scrape_for_type_of env mty = +let scrape_for_type_of env pres mty = let rec loop env path mty = match mty, path with - | Mty_alias(_, path), _ -> begin + | Mty_alias path, _ -> begin try let md = Env.find_module path env in loop env (Some path) md.md_type @@ -142,7 +136,7 @@ let scrape_for_type_of env mty = strengthen ~aliasable:false env mty path | _ -> mty in - make_aliases_absent (loop env None mty) + make_aliases_absent pres (loop env None mty) (* In nondep_supertype, env is only used for the type it assigns to id. Hence there is no need to keep env up-to-date by adding the bindings @@ -150,67 +144,81 @@ let scrape_for_type_of env mty = type variance = Co | Contra | Strict -let nondep_supertype env mid mty = - - let rec nondep_mty env va mty = - match mty with - Mty_ident p -> - if Path.isfree mid p then - nondep_mty env va (Env.find_modtype_expansion p env) - else mty - | Mty_alias(_, p) -> - if Path.isfree mid p then - nondep_mty env va (Env.find_module p env).md_type - else mty - | Mty_signature sg -> - Mty_signature(nondep_sig env va sg) - | Mty_functor(param, arg, res) -> - let var_inv = - match va with Co -> Contra | Contra -> Co | Strict -> Strict in - Mty_functor(param, Misc.may_map (nondep_mty env var_inv) arg, +let rec nondep_mty_with_presence env va ids pres mty = + match mty with + Mty_ident p -> + begin match Path.find_free_opt ids p with + | Some id -> + let expansion = + try Env.find_modtype_expansion p env + with Not_found -> + raise (Ctype.Nondep_cannot_erase id) + in + nondep_mty_with_presence env va ids pres expansion + | None -> pres, mty + end + | Mty_alias p -> + begin match Path.find_free_opt ids p with + | Some id -> + let expansion = + try Env.find_module p env + with Not_found -> + raise (Ctype.Nondep_cannot_erase id) + in + nondep_mty_with_presence env va ids Mp_present expansion.md_type + | None -> pres, mty + end + | Mty_signature sg -> + let mty = Mty_signature(nondep_sig env va ids sg) in + pres, mty + | Mty_functor(param, arg, res) -> + let var_inv = + match va with Co -> Contra | Contra -> Co | Strict -> Strict in + let mty = + Mty_functor(param, Misc.may_map (nondep_mty env var_inv ids) arg, nondep_mty - (Env.add_module ~arg:true param - (Btype.default_mty arg) env) va res) + (Env.add_module ~arg:true param Mp_present + (Btype.default_mty arg) env) va ids res) + in + pres, mty + +and nondep_mty env va ids mty = + snd (nondep_mty_with_presence env va ids Mp_present mty) + +and nondep_sig_item env va ids = function + | Sig_value(id, d, vis) -> + Sig_value(id, + {d with val_type = Ctype.nondep_type env ids d.val_type}, + vis) + | Sig_type(id, d, rs, vis) -> + Sig_type(id, Ctype.nondep_type_decl env ids (va = Co) d, rs, vis) + | Sig_typext(id, ext, es, vis) -> + Sig_typext(id, Ctype.nondep_extension_constructor env ids ext, es, vis) + | Sig_module(id, pres, md, rs, vis) -> + let pres, mty = nondep_mty_with_presence env va ids pres md.md_type in + Sig_module(id, pres, {md with md_type = mty}, rs, vis) + | Sig_modtype(id, d, vis) -> + begin try + Sig_modtype(id, nondep_modtype_decl env ids d, vis) + with Ctype.Nondep_cannot_erase _ as exn -> + match va with + Co -> Sig_modtype(id, {mtd_type=None; mtd_loc=Location.none; + mtd_attributes=[]}, vis) + | _ -> raise exn + end + | Sig_class(id, d, rs, vis) -> + Sig_class(id, Ctype.nondep_class_declaration env ids d, rs, vis) + | Sig_class_type(id, d, rs, vis) -> + Sig_class_type(id, Ctype.nondep_cltype_declaration env ids d, rs, vis) - and nondep_sig env va = function - [] -> [] - | item :: rem -> - let rem' = nondep_sig env va rem in - match item with - Sig_value(id, d) -> - Sig_value(id, - {d with val_type = Ctype.nondep_type env mid d.val_type}) - :: rem' - | Sig_type(id, d, rs) -> - Sig_type(id, Ctype.nondep_type_decl env mid id (va = Co) d, rs) - :: rem' - | Sig_typext(id, ext, es) -> - Sig_typext(id, Ctype.nondep_extension_constructor env mid ext, es) - :: rem' - | Sig_module(id, md, rs) -> - Sig_module(id, {md with md_type=nondep_mty env va md.md_type}, rs) - :: rem' - | Sig_modtype(id, d) -> - begin try - Sig_modtype(id, nondep_modtype_decl env d) :: rem' - with Not_found -> - match va with - Co -> Sig_modtype(id, {mtd_type=None; mtd_loc=Location.none; - mtd_attributes=[]}) :: rem' - | _ -> raise Not_found - end - | Sig_class(id, d, rs) -> - Sig_class(id, Ctype.nondep_class_declaration env mid d, rs) - :: rem' - | Sig_class_type(id, d, rs) -> - Sig_class_type(id, Ctype.nondep_cltype_declaration env mid d, rs) - :: rem' - - and nondep_modtype_decl env mtd = - {mtd with mtd_type = Misc.may_map (nondep_mty env Strict) mtd.mtd_type} +and nondep_sig env va ids sg = + List.map (nondep_sig_item env va ids) sg - in - nondep_mty env Co mty +and nondep_modtype_decl env ids mtd = + {mtd with mtd_type = Misc.may_map (nondep_mty env Strict ids) mtd.mtd_type} + +let nondep_supertype env ids = nondep_mty env Co ids +let nondep_sig_item env ids = nondep_sig_item env Co ids let enrich_typedecl env p id decl = match decl.type_manifest with @@ -252,68 +260,69 @@ let rec enrich_modtype env p mty = mty and enrich_item env p = function - Sig_type(id, decl, rs) -> + Sig_type(id, decl, rs, priv) -> Sig_type(id, - enrich_typedecl env (Pdot(p, Ident.name id, nopos)) id decl, rs) - | Sig_module(id, md, rs) -> - Sig_module(id, + enrich_typedecl env (Pdot(p, Ident.name id)) id decl, rs, priv) + | Sig_module(id, pres, md, rs, priv) -> + Sig_module(id, pres, {md with md_type = enrich_modtype env - (Pdot(p, Ident.name id, nopos)) md.md_type}, - rs) + (Pdot(p, Ident.name id)) md.md_type}, + rs, + priv) | item -> item let rec type_paths env p mty = match scrape env mty with Mty_ident _ -> [] | Mty_alias _ -> [] - | Mty_signature sg -> type_paths_sig env p 0 sg + | Mty_signature sg -> type_paths_sig env p sg | Mty_functor _ -> [] -and type_paths_sig env p pos sg = +and type_paths_sig env p sg = match sg with [] -> [] - | Sig_value(_id, decl) :: rem -> - let pos' = match decl.val_kind with Val_prim _ -> pos | _ -> pos + 1 in - type_paths_sig env p pos' rem - | Sig_type(id, _decl, _) :: rem -> - Pdot(p, Ident.name id, nopos) :: type_paths_sig env p pos rem - | Sig_module(id, md, _) :: rem -> - type_paths env (Pdot(p, Ident.name id, pos)) md.md_type @ - type_paths_sig (Env.add_module_declaration ~check:false id md env) - p (pos+1) rem - | Sig_modtype(id, decl) :: rem -> - type_paths_sig (Env.add_modtype id decl env) p pos rem - | (Sig_typext _ | Sig_class _) :: rem -> - type_paths_sig env p (pos+1) rem - | (Sig_class_type _) :: rem -> - type_paths_sig env p pos rem - -let rec no_code_needed env mty = - match scrape env mty with - Mty_ident _ -> false - | Mty_signature sg -> no_code_needed_sig env sg - | Mty_functor(_, _, _) -> false - | Mty_alias(Mta_absent, _) -> true - | Mty_alias(Mta_present, _) -> false + | Sig_type(id, _decl, _, _) :: rem -> + Pdot(p, Ident.name id) :: type_paths_sig env p rem + | Sig_module(id, pres, md, _, _) :: rem -> + type_paths env (Pdot(p, Ident.name id)) md.md_type @ + type_paths_sig (Env.add_module_declaration ~check:false id pres md env) + p rem + | Sig_modtype(id, decl, _) :: rem -> + type_paths_sig (Env.add_modtype id decl env) p rem + | (Sig_value _ | Sig_typext _ | Sig_class _ | Sig_class_type _) :: rem -> + type_paths_sig env p rem + + +let rec no_code_needed_mod env pres mty = + match pres with + | Mp_absent -> true + | Mp_present -> begin + match scrape env mty with + Mty_ident _ -> false + | Mty_signature sg -> no_code_needed_sig env sg + | Mty_functor _ -> false + | Mty_alias _ -> false + end and no_code_needed_sig env sg = match sg with [] -> true - | Sig_value(_id, decl) :: rem -> + | Sig_value(_id, decl, _) :: rem -> begin match decl.val_kind with | Val_prim _ -> no_code_needed_sig env rem | _ -> false end - | Sig_module(id, md, _) :: rem -> - no_code_needed env md.md_type && + | Sig_module(id, pres, md, _, _) :: rem -> + no_code_needed_mod env pres md.md_type && no_code_needed_sig - (Env.add_module_declaration ~check:false id md env) rem + (Env.add_module_declaration ~check:false id pres md env) rem | (Sig_type _ | Sig_modtype _ | Sig_class_type _) :: rem -> no_code_needed_sig env rem | (Sig_typext _ | Sig_class _) :: _ -> false +let no_code_needed env mty = no_code_needed_mod env Mp_present mty (* Check whether a module type may return types *) @@ -335,16 +344,16 @@ and contains_type_sig env = List.iter (contains_type_item env) and contains_type_item env = function Sig_type (_,({type_manifest = None} | - {type_kind = Type_abstract; type_private = Private}),_) + {type_kind = Type_abstract; type_private = Private}),_, _) | Sig_modtype _ - | Sig_typext (_, {ext_args = Cstr_record _}, _) -> + | Sig_typext (_, {ext_args = Cstr_record _}, _, _) -> (* We consider that extension constructors with an inlined record create a type (the inlined record), even though it would be technically safe to ignore that considering the current constraints which guarantee that this type is kept local to expressions. *) raise Exit - | Sig_module (_, {md_type = mty}, _) -> + | Sig_module (_, _, {md_type = mty}, _, _) -> contains_type env mty | Sig_value _ | Sig_type _ @@ -359,30 +368,27 @@ let contains_type env mty = (* Remove module aliases from a signature *) -module PathSet = Set.Make (Path) -module PathMap = Map.Make (Path) - let rec get_prefixes = function - Pident _ -> PathSet.empty - | Pdot (p, _, _) - | Papply (p, _) -> PathSet.add p (get_prefixes p) + | Pident _ -> Path.Set.empty + | Pdot (p, _) + | Papply (p, _) -> Path.Set.add p (get_prefixes p) let rec get_arg_paths = function - Pident _ -> PathSet.empty - | Pdot (p, _, _) -> get_arg_paths p + | Pident _ -> Path.Set.empty + | Pdot (p, _) -> get_arg_paths p | Papply (p1, p2) -> - PathSet.add p2 - (PathSet.union (get_prefixes p2) - (PathSet.union (get_arg_paths p1) (get_arg_paths p2))) + Path.Set.add p2 + (Path.Set.union (get_prefixes p2) + (Path.Set.union (get_arg_paths p1) (get_arg_paths p2))) let rec rollback_path subst p = - try Pident (PathMap.find p subst) + try Pident (Path.Map.find p subst) with Not_found -> match p with Pident _ | Papply _ -> p - | Pdot (p1, s, n) -> + | Pdot (p1, s) -> let p1' = rollback_path subst p1 in - if Path.same p1 p1' then p else rollback_path subst (Pdot (p1', s, n)) + if Path.same p1 p1' then p else rollback_path subst (Pdot (p1', s)) let rec collect_ids subst bindings p = begin match rollback_path subst p with @@ -397,22 +403,22 @@ let rec collect_ids subst bindings p = let collect_arg_paths mty = let open Btype in - let paths = ref PathSet.empty - and subst = ref PathMap.empty + let paths = ref Path.Set.empty + and subst = ref Path.Map.empty and bindings = ref Ident.empty in (* let rt = Ident.create "Root" in and prefix = ref (Path.Pident rt) in *) - let it_path p = paths := PathSet.union (get_arg_paths p) !paths + let it_path p = paths := Path.Set.union (get_arg_paths p) !paths and it_signature_item it si = type_iterators.it_signature_item it si; match si with - Sig_module (id, {md_type=Mty_alias(_, p)}, _) -> + | Sig_module (id, _, {md_type=Mty_alias p}, _, _) -> bindings := Ident.add id p !bindings - | Sig_module (id, {md_type=Mty_signature sg}, _) -> + | Sig_module (id, _, {md_type=Mty_signature sg}, _, _) -> List.iter - (function Sig_module (id', _, _) -> + (function Sig_module (id', _, _, _, _) -> subst := - PathMap.add (Pdot (Pident id, Ident.name id', -1)) id' !subst + Path.Map.add (Pdot (Pident id, Ident.name id')) id' !subst | _ -> ()) sg | _ -> () @@ -420,7 +426,7 @@ let collect_arg_paths mty = let it = {type_iterators with it_path; it_signature_item} in it.it_module_type it mty; it.it_module_type unmark_iterators mty; - PathSet.fold (fun p -> Ident.Set.union (collect_ids !subst !bindings p)) + Path.Set.fold (fun p -> Ident.Set.union (collect_ids !subst !bindings p)) !paths Ident.Set.empty type remove_alias_args = @@ -428,36 +434,45 @@ type remove_alias_args = exclude: Ident.t -> Path.t -> bool; scrape: Env.t -> module_type -> module_type } -let rec remove_aliases_mty env args mty = +let rec remove_aliases_mty env args pres mty = let args' = {args with modified = false} in - let mty' = + let res = match args.scrape env mty with Mty_signature sg -> - Mty_signature (remove_aliases_sig env args' sg) + Mp_present, Mty_signature (remove_aliases_sig env args' sg) | Mty_alias _ -> let mty' = Env.scrape_alias env mty in - if mty' = mty then mty else - (args'.modified <- true; remove_aliases_mty env args' mty') + if mty' = mty then begin + pres, mty + end else begin + args'.modified <- true; + remove_aliases_mty env args' Mp_present mty' + end | mty -> - mty + Mp_present, mty in - if args'.modified then (args.modified <- true; mty') else mty + if args'.modified then begin + args.modified <- true; + res + end else begin + pres, mty + end and remove_aliases_sig env args sg = match sg with [] -> [] - | Sig_module(id, md, rs) :: rem -> - let mty = + | Sig_module(id, pres, md, rs, priv) :: rem -> + let pres, mty = match md.md_type with - Mty_alias (_, p) when args.exclude id p -> - md.md_type + Mty_alias p when args.exclude id p -> + pres, md.md_type | mty -> - remove_aliases_mty env args mty + remove_aliases_mty env args pres mty in - Sig_module(id, {md with md_type = mty} , rs) :: - remove_aliases_sig (Env.add_module id mty env) args rem - | Sig_modtype(id, mtd) :: rem -> - Sig_modtype(id, mtd) :: + Sig_module(id, pres, {md with md_type = mty} , rs, priv) :: + remove_aliases_sig (Env.add_module id pres mty env) args rem + | Sig_modtype(id, mtd, priv) :: rem -> + Sig_modtype(id, mtd, priv) :: remove_aliases_sig (Env.add_modtype id mtd env) args rem | it :: rem -> it :: remove_aliases_sig env args rem @@ -466,16 +481,23 @@ let scrape_for_functor_arg env mty = let exclude _id p = try ignore (Env.find_module p env); true with Not_found -> false in - remove_aliases_mty env {modified=false; exclude; scrape} mty + let _, mty = + remove_aliases_mty env {modified=false; exclude; scrape} Mp_present mty + in + mty let scrape_for_type_of ~remove_aliases env mty = if remove_aliases then begin let excl = collect_arg_paths mty in let exclude id _p = Ident.Set.mem id excl in let scrape _ mty = mty in - remove_aliases_mty env {modified=false; exclude; scrape} mty + let _, mty = + remove_aliases_mty env {modified=false; exclude; scrape} Mp_present mty + in + mty end else begin - scrape_for_type_of env mty + let _, mty = scrape_for_type_of env Mp_present mty in + mty end (* Lower non-generalizable type variables *) diff --git a/typing/mtype.mli b/typing/mtype.mli index 30d13ec6..68d290b3 100644 --- a/typing/mtype.mli +++ b/typing/mtype.mli @@ -26,7 +26,7 @@ val scrape_for_functor_arg: Env.t -> module_type -> module_type val scrape_for_type_of: remove_aliases:bool -> Env.t -> module_type -> module_type (* Process type for module type of *) -val freshen: module_type -> module_type +val freshen: scope:int -> module_type -> module_type (* Return an alpha-equivalent copy of the given module type where bound identifiers are fresh. *) val strengthen: aliasable:bool -> Env.t -> module_type -> Path.t -> module_type @@ -34,10 +34,15 @@ val strengthen: aliasable:bool -> Env.t -> module_type -> Path.t -> module_type given path. *) val strengthen_decl: aliasable:bool -> Env.t -> module_declaration -> Path.t -> module_declaration -val nondep_supertype: Env.t -> Ident.t -> module_type -> module_type +val nondep_supertype: Env.t -> Ident.t list -> module_type -> module_type (* Return the smallest supertype of the given type - in which the given ident does not appear. - Raise [Not_found] if no such type exists. *) + in which none of the given idents appears. + @raise [Ctype.Nondep_cannot_erase] if no such type exists. *) +val nondep_sig_item: Env.t -> Ident.t list -> signature_item -> signature_item + (* Returns the signature item with its type updated + to be the smallest supertype of its initial type + in which none of the given idents appears. + @raise [Ctype.Nondep_cannot_erase] if no such type exists. *) val no_code_needed: Env.t -> module_type -> bool val no_code_needed_sig: Env.t -> signature -> bool (* Determine whether a module needs no implementation code, diff --git a/typing/oprint.ml b/typing/oprint.ml index f65ad7ea..ed6a4dbf 100644 --- a/typing/oprint.ml +++ b/typing/oprint.ml @@ -28,19 +28,36 @@ let print_lident ppf = function let rec print_ident ppf = function - Oide_ident s -> print_lident ppf s + Oide_ident s -> print_lident ppf s.printed_name | Oide_dot (id, s) -> print_ident ppf id; pp_print_char ppf '.'; print_lident ppf s | Oide_apply (id1, id2) -> fprintf ppf "%a(%a)" print_ident id1 print_ident id2 +let out_ident = ref print_ident + +(* Check a character matches the [identchar_latin1] class from the lexer *) +let is_ident_char c = + match c with + | 'A'..'Z' | 'a'..'z' | '_' | '\192'..'\214' | '\216'..'\246' + | '\248'..'\255' | '\'' | '0'..'9' -> true + | _ -> false + +let all_ident_chars s = + let rec loop s len i = + if i < len then begin + if is_ident_char s.[i] then loop s len (i+1) + else false + end else begin + true + end + in + let len = String.length s in + loop s len 0 + let parenthesized_ident name = (List.mem name ["or"; "mod"; "land"; "lor"; "lxor"; "lsl"; "lsr"; "asr"]) - || - (match name.[0] with - 'a'..'z' | 'A'..'Z' | '\223'..'\246' | '\248'..'\255' | '_' -> - false - | _ -> true) + || not (all_ident_chars name) let value_ident ppf name = if parenthesized_ident name then @@ -79,7 +96,8 @@ let parenthesize_if_neg ppf fmt v isneg = if isneg then pp_print_char ppf ')' let escape_string s = - (* Escape only C0 control characters (bytes <= 0x1F), DEL(0x7F), '\\' and '"' *) + (* Escape only C0 control characters (bytes <= 0x1F), DEL(0x7F), '\\' + and '"' *) let n = ref 0 in for i = 0 to String.length s - 1 do n := !n + @@ -151,7 +169,9 @@ let print_out_value ppf tree = | Oval_int32 i -> parenthesize_if_neg ppf "%lil" i (i < 0l) | Oval_int64 i -> parenthesize_if_neg ppf "%LiL" i (i < 0L) | Oval_nativeint i -> parenthesize_if_neg ppf "%nin" i (i < 0n) - | Oval_float f -> parenthesize_if_neg ppf "%s" (float_repres f) (f < 0.0 || 1. /. f = neg_infinity) + | Oval_float f -> + parenthesize_if_neg ppf "%s" (float_repres f) + (f < 0.0 || 1. /. f = neg_infinity) | Oval_string (_,_, Ostr_bytes) as tree -> pp_print_char ppf '('; print_simple_tree ppf tree; @@ -233,13 +253,15 @@ let rec print_list pr sep ppf = let pr_present = print_list (fun ppf s -> fprintf ppf "`%s" s) (fun ppf -> fprintf ppf "@ ") +let pr_var = Pprintast.tyvar + let pr_vars = - print_list (fun ppf s -> fprintf ppf "'%s" s) (fun ppf -> fprintf ppf "@ ") + print_list pr_var (fun ppf -> fprintf ppf "@ ") let rec print_out_type ppf = function | Otyp_alias (ty, s) -> - fprintf ppf "@[%a@ as '%s@]" print_out_type ty s + fprintf ppf "@[%a@ as %a@]" print_out_type ty pr_var s | Otyp_poly (sl, ty) -> fprintf ppf "@[%a.@ %a@]" pr_vars sl @@ -276,7 +298,7 @@ and print_simple_out_type ppf = | Otyp_object (fields, rest) -> fprintf ppf "@[<2>< %a >@]" (print_fields rest) fields | Otyp_stuff s -> pp_print_string ppf s - | Otyp_var (ng, s) -> fprintf ppf "'%s%s" (if ng then "_" else "") s + | Otyp_var (ng, s) -> pr_var ppf (if ng then "_" ^ s else s) | Otyp_variant (non_gen, row_fields, closed, tags) -> let print_present ppf = function @@ -291,7 +313,8 @@ and print_simple_out_type ppf = | Ovar_typ typ -> print_simple_out_type ppf typ in - fprintf ppf "%s[%s@[@[%a@]%a ]@]" (if non_gen then "_" else "") + fprintf ppf "%s@[[%s@[@[%a@]%a@]@ ]@]" + (if non_gen then "_" else "") (if closed then if tags = None then " " else "< " else if tags = None then "> " else "? ") print_fields row_fields @@ -306,7 +329,7 @@ and print_simple_out_type ppf = | Otyp_sum _ | Otyp_manifest (_, _) -> () | Otyp_record lbls -> print_record_decl ppf lbls | Otyp_module (p, n, tyl) -> - fprintf ppf "@[<1>(module %s" p; + fprintf ppf "@[<1>(module %a" print_ident p; let first = ref true in List.iter2 (fun s t -> @@ -372,10 +395,13 @@ let out_type = ref print_out_type (* Class types *) +let print_type_parameter ppf s = + if s = "_" then fprintf ppf "_" else pr_var ppf s + let type_parameter ppf (ty, (co, cn)) = - fprintf ppf "%s%s" + fprintf ppf "%s%a" (if not cn then "+" else if not co then "-" else "") - (if ty = "_" then ty else "'"^ty) + print_type_parameter ty let print_out_class_params ppf = function @@ -640,10 +666,6 @@ and print_out_constr ppf (name, tyl,ret_type_opt) = and print_out_extension_constructor ppf ext = let print_extended_type ppf = - let print_type_parameter ppf ty = - fprintf ppf "%s" - (if ty = "_" then ty else "'"^ty) - in match ext.oext_type_params with [] -> fprintf ppf "%s" ext.oext_type_name | [ty_param] -> @@ -664,10 +686,6 @@ and print_out_extension_constructor ppf ext = and print_out_type_extension ppf te = let print_extended_type ppf = - let print_type_parameter ppf ty = - fprintf ppf "%s" - (if ty = "_" then ty else "'"^ty) - in match te.otyext_params with [] -> fprintf ppf "%s" te.otyext_name | [param] -> diff --git a/typing/oprint.mli b/typing/oprint.mli index 7ce08a38..27ff8bc1 100644 --- a/typing/oprint.mli +++ b/typing/oprint.mli @@ -16,6 +16,7 @@ open Format open Outcometree +val out_ident : (formatter -> out_ident -> unit) ref val out_value : (formatter -> out_value -> unit) ref val out_type : (formatter -> out_type -> unit) ref val out_class_type : (formatter -> out_class_type -> unit) ref diff --git a/typing/outcometree.mli b/typing/outcometree.mli index e4c62c31..ec92d15f 100644 --- a/typing/outcometree.mli +++ b/typing/outcometree.mli @@ -22,10 +22,14 @@ [Toploop.print_out_sig_item] [Toploop.print_out_phrase] *) +(** An [out_name] is a string representation of an identifier which can be + rewritten on the fly to avoid name collisions *) +type out_name = { mutable printed_name: string } + type out_ident = | Oide_apply of out_ident * out_ident | Oide_dot of out_ident * string - | Oide_ident of string + | Oide_ident of out_name type out_string = | Ostr_string @@ -69,7 +73,7 @@ type out_type = | Otyp_variant of bool * out_variant * bool * (string list) option | Otyp_poly of string list * out_type - | Otyp_module of string * string list * out_type list + | Otyp_module of out_ident * string list * out_type list | Otyp_attribute of out_type * out_attribute and out_variant = diff --git a/typing/parmatch.ml b/typing/parmatch.ml index adc75862..ccf0dd35 100644 --- a/typing/parmatch.ml +++ b/typing/parmatch.ml @@ -34,7 +34,7 @@ let omega = make_pat Tpat_any Ctype.none Env.empty let extra_pat = make_pat - (Tpat_var (Ident.create "+", mknoloc "+")) + (Tpat_var (Ident.create_local "+", mknoloc "+")) Ctype.none Env.empty let rec omegas i = @@ -72,11 +72,11 @@ let zero = make_pat (Tpat_constant (Const_int 0)) Ctype.none Env.empty S -------> | "" | U | S, "" | __/ | () | - --------> | _, () | \ ¬ S + --------> | _, () | \ not S | U, _, () | __/ -------> | () | | _, S, "" | \ ---------> | S, "" | ----------> | "" | - ¬ U S + not U S v} where following an edge labelled by a pattern P means "assuming the value I @@ -91,7 +91,7 @@ let zero = make_pat (Tpat_constant (Const_int 0)) Ctype.none Env.empty a value would be ill-typed, so we can never actually get there. Checking the first column at each step of the recursion and making the - concious decision of "aborting" the algorithm whenever the first column + conscious decision of "aborting" the algorithm whenever the first column becomes incoherent, allows us to retain the initial assumption in later stages of the algorithms. @@ -229,7 +229,7 @@ let first_column simplified_matrix = The second clause above will NOT (and cannot) be flagged as useless. - Finally, there are two compatibility fonction + Finally, there are two compatibility functions: compat p q ---> 'syntactic compatibility, used for diagnostics. may_compat p q ---> a safe approximation of possible compat, for compilation @@ -246,7 +246,7 @@ let is_absent_pat p = match p.pat_desc with let const_compare x y = match x,y with | Const_float f1, Const_float f2 -> - Pervasives.compare (float_of_string f1) (float_of_string f2) + Stdlib.compare (float_of_string f1) (float_of_string f2) | Const_string (s1, _), Const_string (s2, _) -> String.compare s1 s2 | (Const_int _ @@ -256,7 +256,7 @@ let const_compare x y = |Const_int32 _ |Const_int64 _ |Const_nativeint _ - ), _ -> Pervasives.compare x y + ), _ -> Stdlib.compare x y let records_args l1 l2 = (* Invariant: fields are already sorted by Typecore.type_label_a_list *) @@ -443,7 +443,8 @@ let rec normalize_pat q = match q.pat_desc with q.pat_type q.pat_env | Tpat_lazy _ -> make_pat (Tpat_lazy omega) q.pat_type q.pat_env - | Tpat_or _ -> fatal_error "Parmatch.normalize_pat" + | Tpat_or _ + | Tpat_exception _ -> fatal_error "Parmatch.normalize_pat" (* Consider a pattern matrix whose first column has been simplified to contain only _ or a head constructor @@ -781,7 +782,8 @@ let row_of_pat pat = are simplified, and are not omega/Tpat_any. *) let full_match closing env = match env with -| ({pat_desc = (Tpat_any | Tpat_var _ | Tpat_alias _ | Tpat_or _)},_) :: _ -> +| ({pat_desc = (Tpat_any | Tpat_var _ | Tpat_alias _ + | Tpat_or _ | Tpat_exception _)},_) :: _ -> (* discriminating patterns are simplified *) assert false | [] -> false @@ -820,7 +822,8 @@ let full_match closing env = match env with | ({pat_desc = Tpat_array(_)},_) :: _ -> false | ({pat_desc = Tpat_lazy(_)},_) :: _ -> true -(* Written as a non-fragile matching, PR#7451 originated from a fragile matching below. *) +(* Written as a non-fragile matching, PR#7451 originated from a fragile matching + below. *) let should_extend ext env = match ext with | None -> false | Some ext -> begin match env with @@ -836,7 +839,7 @@ let should_extend ext env = match ext with | Tpat_constant _|Tpat_tuple _|Tpat_variant _ | Tpat_record _|Tpat_array _ | Tpat_lazy _ -> false - | Tpat_any|Tpat_var _|Tpat_alias _|Tpat_or _ + | Tpat_any|Tpat_var _|Tpat_alias _|Tpat_or _|Tpat_exception _ -> assert false end end @@ -971,7 +974,7 @@ let some_private_tag = "" let build_other ext env = match env with | ({pat_desc = Tpat_construct (lid, {cstr_tag=Cstr_extension _},_)},_) :: _ -> (* let c = {c with cstr_name = "*extension*"} in *) (* PR#7330 *) - make_pat (Tpat_var (Ident.create "*extension*", + make_pat (Tpat_var (Ident.create_local "*extension*", {lid with txt="*extension*"})) Ctype.none Env.empty | ({pat_desc = Tpat_construct _} as p,_) :: _ -> begin match ext with @@ -1106,6 +1109,7 @@ let rec has_instance p = match p.pat_desc with | Tpat_record (lps,_) -> has_instances (List.map (fun (_,_,x) -> x) lps) | Tpat_lazy p -> has_instance p + | Tpat_exception _ -> assert false and has_instances = function @@ -1361,7 +1365,8 @@ let rec exhaust (ext:Path.t option) pss n = match pss with exhaust ext pss (List.length (simple_match_args p omega) + n - 1) with - | Witnesses r -> Witnesses (List.map (fun row -> (set_args p row)) r) + | Witnesses r -> + Witnesses (List.map (fun row -> (set_args p row)) r) | r -> r in let before = try_many try_non_omega constrs in if @@ -1813,8 +1818,19 @@ and lubs ps qs = match ps,qs with (* Apply pressure to variants *) let pressure_variants tdefs patl = - let pss = List.map (fun p -> [p;omega]) patl in - ignore (pressure_variants (Some tdefs) pss) + let add_row pss p_opt = + match p_opt with + | None -> pss + | Some p -> [p; omega] :: pss + in + let val_pss, exn_pss = + List.fold_right (fun pat (vpss, epss)-> + let (vp, ep) = split_pattern pat in + add_row vpss vp, add_row epss ep + ) patl ([], []) + in + ignore (pressure_variants (Some tdefs) val_pss); + ignore (pressure_variants (Some tdefs) exn_pss) (*****************************) (* Utilities for diagnostics *) @@ -1855,7 +1871,7 @@ module Conv = struct let fresh name = let current = !name_counter in name_counter := !name_counter + 1; - "#$" ^ name ^ string_of_int current + "#$" ^ name ^ Int.to_string current let conv typed = let constrs = Hashtbl.create 7 in @@ -1902,6 +1918,8 @@ module Conv = struct mkpat (Ppat_array (List.map loop lst)) | Tpat_lazy p -> mkpat (Ppat_lazy (loop p)) + | Tpat_exception _ -> + assert false in let ps = loop typed in (ps, constrs, labels) @@ -1973,7 +1991,7 @@ let do_check_partial ~pred loc casel pss = match pss with Buffer.add_string buf "\nMatching over values of extensible variant types \ (the *extension* above)\n\ - must include a wild card pattern in order to be exhaustive." + must include a wild card pattern in order to be exhaustive." ; Buffer.contents buf with _ -> @@ -2028,6 +2046,7 @@ let rec collect_paths_from_pat r p = match p.pat_desc with | Tpat_lazy p -> collect_paths_from_pat r p +| Tpat_exception _ -> assert false (* @@ -2082,8 +2101,8 @@ let check_unused pred casel = - the clause under consideration is not a refutation clause and either: + there are no other lines - + we do not care whether the types prevent this clause to be - reached. + + we do not care whether the types prevent this clause to + be reached. If the clause under consideration *is* a refutation clause then we do need to check more carefully whether it can be refuted or not. *) @@ -2159,6 +2178,7 @@ let inactive ~partial pat = ldps | Tpat_or (p,q,_) -> loop p && loop q + | Tpat_exception _ -> assert false in loop pat end @@ -2433,12 +2453,13 @@ let all_rhs_idents exp = and perform "indirect check for them" *) let is_unpack exp = List.exists - (fun (attr, _) -> attr.txt = "#modulepat") exp.exp_attributes + (fun attr -> attr.Parsetree.attr_name.txt = "#modulepat") + exp.exp_attributes let leave_expression exp = if is_unpack exp then begin match exp.exp_desc with | Texp_letmodule - (id_mod,_, + (id_mod,_,_, {mod_desc= Tmod_unpack ({exp_desc=Texp_ident (Path.Pident id_exp,_,_)},_)}, _) -> diff --git a/typing/parmatch.mli b/typing/parmatch.mli index 4426795c..000b02b4 100644 --- a/typing/parmatch.mli +++ b/typing/parmatch.mli @@ -34,7 +34,7 @@ val normalize_pat : pattern -> pattern val const_compare : constant -> constant -> int (** [const_compare c1 c2] compares the actual values represented by [c1] and - [c2], while simply using [Pervasives.compare] would compare the + [c2], while simply using [Stdlib.compare] would compare the representations. cf. MPR#5758 *) @@ -106,9 +106,10 @@ val check_unused: (* Irrefutability tests *) val irrefutable : pattern -> bool -(** An inactive pattern is a pattern, matching against which can be duplicated, erased or - delayed without change in observable behavior of the program. Patterns containing - (lazy _) subpatterns or reads of mutable fields are active. *) +(** An inactive pattern is a pattern, matching against which can be duplicated, + erased or delayed without change in observable behavior of the program. + Patterns containing (lazy _) subpatterns or reads of mutable fields are + active. *) val inactive : partial:partial -> pattern -> bool (* Ambiguous bindings *) diff --git a/typing/path.ml b/typing/path.ml index cff31cb8..e5a8d7eb 100644 --- a/typing/path.ml +++ b/typing/path.ml @@ -15,23 +15,23 @@ type t = Pident of Ident.t - | Pdot of t * string * int + | Pdot of t * string | Papply of t * t -let nopos = -1 - let rec same p1 p2 = - match (p1, p2) with + p1 == p2 + || match (p1, p2) with (Pident id1, Pident id2) -> Ident.same id1 id2 - | (Pdot(p1, s1, _pos1), Pdot(p2, s2, _pos2)) -> s1 = s2 && same p1 p2 + | (Pdot(p1, s1), Pdot(p2, s2)) -> s1 = s2 && same p1 p2 | (Papply(fun1, arg1), Papply(fun2, arg2)) -> same fun1 fun2 && same arg1 arg2 | (_, _) -> false let rec compare p1 p2 = - match (p1, p2) with + if p1 == p2 then 0 + else match (p1, p2) with (Pident id1, Pident id2) -> Ident.compare id1 id2 - | (Pdot(p1, s1, _pos1), Pdot(p2, s2, _pos2)) -> + | (Pdot(p1, s1), Pdot(p2, s2)) -> let h = compare p1 p2 in if h <> 0 then h else String.compare s1 s2 | (Papply(fun1, arg1), Papply(fun2, arg2)) -> @@ -40,33 +40,46 @@ let rec compare p1 p2 = | ((Pident _ | Pdot _), (Pdot _ | Papply _)) -> -1 | ((Pdot _ | Papply _), (Pident _ | Pdot _)) -> 1 -let rec isfree id = function - Pident id' -> Ident.same id id' - | Pdot(p, _s, _pos) -> isfree id p - | Papply(p1, p2) -> isfree id p1 || isfree id p2 +let rec find_free_opt ids = function + Pident id -> List.find_opt (Ident.same id) ids + | Pdot(p, _s) -> find_free_opt ids p + | Papply(p1, p2) -> + match find_free_opt ids p1 with + | None -> find_free_opt ids p2 + | Some _ as res -> res + +let exists_free ids p = + match find_free_opt ids p with + | None -> false + | _ -> true -let rec binding_time = function - Pident id -> Ident.binding_time id - | Pdot(p, _s, _pos) -> binding_time p - | Papply(p1, p2) -> max (binding_time p1) (binding_time p2) +let rec scope = function + Pident id -> Ident.scope id + | Pdot(p, _s) -> scope p + | Papply(p1, p2) -> max (scope p1) (scope p2) let kfalse _ = false let rec name ?(paren=kfalse) = function Pident id -> Ident.name id - | Pdot(p, s, _pos) -> + | Pdot(p, s) -> name ~paren p ^ if paren s then ".( " ^ s ^ " )" else "." ^ s | Papply(p1, p2) -> name ~paren p1 ^ "(" ^ name ~paren p2 ^ ")" +let rec print ppf = function + | Pident id -> Ident.print_with_scope ppf id + | Pdot(p, s) -> Format.fprintf ppf "%a.%s" print p s + | Papply(p1, p2) -> Format.fprintf ppf "%a(%a)" print p1 print p2 + let rec head = function Pident id -> id - | Pdot(p, _s, _pos) -> head p + | Pdot(p, _s) -> head p | Papply _ -> assert false let flatten = let rec flatten acc = function | Pident id -> `Ok (id, acc) - | Pdot (p, s, _) -> flatten (s :: acc) p + | Pdot (p, s) -> flatten (s :: acc) p | Papply _ -> `Contains_apply in fun t -> flatten [] t @@ -74,14 +87,14 @@ let flatten = let heads p = let rec heads p acc = match p with | Pident id -> id :: acc - | Pdot (p, _s, _pos) -> heads p acc + | Pdot (p, _s) -> heads p acc | Papply(p1, p2) -> heads p1 (heads p2 acc) in heads p [] let rec last = function | Pident id -> Ident.name id - | Pdot(_, s, _) -> s + | Pdot(_, s) -> s | Papply(_, p) -> last p let is_uident s = @@ -98,7 +111,7 @@ type typath = let constructor_typath = function | Pident id when is_uident (Ident.name id) -> LocalExt id - | Pdot(ty_path, s, _) when is_uident s -> + | Pdot(ty_path, s) when is_uident s -> if is_uident (last ty_path) then Ext (ty_path, s) else Cstr (ty_path, s) | p -> Regular p @@ -107,3 +120,10 @@ let is_constructor_typath p = match constructor_typath p with | Regular _ -> false | _ -> true + +module T = struct + type nonrec t = t + let compare = compare +end +module Set = Set.Make(T) +module Map = Map.Make(T) diff --git a/typing/path.mli b/typing/path.mli index 18491462..b008fabf 100644 --- a/typing/path.mli +++ b/typing/path.mli @@ -17,21 +17,22 @@ type t = Pident of Ident.t - | Pdot of t * string * int + | Pdot of t * string | Papply of t * t val same: t -> t -> bool val compare: t -> t -> int -val isfree: Ident.t -> t -> bool -val binding_time: t -> int +val find_free_opt: Ident.t list -> t -> Ident.t option +val exists_free: Ident.t list -> t -> bool +val scope: t -> int val flatten : t -> [ `Contains_apply | `Ok of Ident.t * string list ] -val nopos: int - val name: ?paren:(string -> bool) -> t -> string (* [paren] tells whether a path suffix needs parentheses *) val head: t -> Ident.t +val print: Format.formatter -> t -> unit + val heads: t -> Ident.t list val last: t -> string @@ -44,3 +45,6 @@ type typath = val constructor_typath: t -> typath val is_constructor_typath: t -> bool + +module Map : Map.S with type key = t +module Set : Set.S with type elt = t diff --git a/typing/predef.ml b/typing/predef.ml index a7688ccc..5399656d 100644 --- a/typing/predef.ml +++ b/typing/predef.ml @@ -26,8 +26,7 @@ let wrap create s = builtin_idents := (s, id) :: !builtin_idents; id -let ident_create = wrap Ident.create -let ident_create_predef_exn = wrap Ident.create_predef_exn +let ident_create = wrap Ident.create_predef let ident_int = ident_create "int" and ident_char = ident_create "char" @@ -84,19 +83,19 @@ and type_extension_constructor = newgenty (Tconstr(path_extension_constructor, [], ref Mnil)) and type_floatarray = newgenty (Tconstr(path_floatarray, [], ref Mnil)) -let ident_match_failure = ident_create_predef_exn "Match_failure" -and ident_out_of_memory = ident_create_predef_exn "Out_of_memory" -and ident_invalid_argument = ident_create_predef_exn "Invalid_argument" -and ident_failure = ident_create_predef_exn "Failure" -and ident_not_found = ident_create_predef_exn "Not_found" -and ident_sys_error = ident_create_predef_exn "Sys_error" -and ident_end_of_file = ident_create_predef_exn "End_of_file" -and ident_division_by_zero = ident_create_predef_exn "Division_by_zero" -and ident_stack_overflow = ident_create_predef_exn "Stack_overflow" -and ident_sys_blocked_io = ident_create_predef_exn "Sys_blocked_io" -and ident_assert_failure = ident_create_predef_exn "Assert_failure" +let ident_match_failure = ident_create "Match_failure" +and ident_out_of_memory = ident_create "Out_of_memory" +and ident_invalid_argument = ident_create "Invalid_argument" +and ident_failure = ident_create "Failure" +and ident_not_found = ident_create "Not_found" +and ident_sys_error = ident_create "Sys_error" +and ident_end_of_file = ident_create "End_of_file" +and ident_division_by_zero = ident_create "Division_by_zero" +and ident_stack_overflow = ident_create "Stack_overflow" +and ident_sys_blocked_io = ident_create "Sys_blocked_io" +and ident_assert_failure = ident_create "Assert_failure" and ident_undefined_recursive_module = - ident_create_predef_exn "Undefined_recursive_module" + ident_create "Undefined_recursive_module" let all_predef_exns = [ ident_match_failure; @@ -125,7 +124,8 @@ let decl_abstr = type_private = Asttypes.Public; type_manifest = None; type_variance = []; - type_newtype_level = None; + type_is_newtype = false; + type_expansion_scope = lowest_level; type_attributes = []; type_immediate = false; type_unboxed = unboxed_false_default_false; @@ -198,9 +198,9 @@ let common_initial_env add_type add_extension empty_env = ext_ret_type = None; ext_private = Asttypes.Public; ext_loc = Location.none; - ext_attributes = [{Asttypes.txt="ocaml.warn_on_literal_pattern"; - loc=Location.none}, - Parsetree.PStr[]] } + ext_attributes = [Ast_helper.Attr.mk + (Location.mknoloc "ocaml.warn_on_literal_pattern") + (Parsetree.PStr [])] } in add_extension ident_match_failure [newgenty (Ttuple[type_string; type_int; type_int])] ( @@ -245,9 +245,4 @@ let build_initial_env add_type add_exception empty_env = let builtin_values = List.map (fun id -> (Ident.name id, id)) all_predef_exns -(* Start non-predef identifiers at 1000. This way, more predefs can - be defined in this file (above!) without breaking .cmi - compatibility. *) - -let _ = Ident.set_current_time 999 let builtin_idents = List.rev !builtin_idents diff --git a/typing/primitive.ml b/typing/primitive.ml index 4d0a070d..c28bdfbf 100644 --- a/typing/primitive.ml +++ b/typing/primitive.ml @@ -111,7 +111,8 @@ let parse_declaration valdecl ~native_repr_args ~native_repr_res = let old_style_noalloc = old_style_noalloc || old_style_float in if old_style_float then Location.deprecated valdecl.pval_loc - "[@@unboxed] + [@@noalloc] should be used instead of \"float\"" + "[@@unboxed] + [@@noalloc] should be used\n\ + instead of \"float\"" else if old_style_noalloc then Location.deprecated valdecl.pval_loc "[@@noalloc] should be used instead of \"noalloc\""; @@ -203,20 +204,20 @@ let report_error ppf err = match err with | Old_style_float_with_native_repr_attribute -> Format.fprintf ppf "Cannot use \"float\" in conjunction with \ - [%@unboxed]/[%@untagged]" + [%@unboxed]/[%@untagged]." | Old_style_noalloc_with_noalloc_attribute -> Format.fprintf ppf "Cannot use \"noalloc\" in conjunction with \ - [%@%@noalloc]" + [%@%@noalloc]." | No_native_primitive_with_repr_attribute -> Format.fprintf ppf - "The native code version of the primitive is mandatory when \ - attributes [%@untagged] or [%@unboxed] are present" + "[@The native code version of the primitive is mandatory@ \ + when attributes [%@untagged] or [%@unboxed] are present.@]" let () = Location.register_error_of_exn (function | Error (loc, err) -> - Some (Location.error_of_printer loc report_error err) + Some (Location.error_of_printer ~loc report_error err) | _ -> None ) diff --git a/typing/printpat.ml b/typing/printpat.ml index e19b55ba..03cd0cd7 100644 --- a/typing/printpat.ml +++ b/typing/printpat.ml @@ -89,6 +89,8 @@ let rec pretty_val ppf v = fprintf ppf "@[[| %a |]@]" (pretty_vals " ;") vs | Tpat_lazy v -> fprintf ppf "@[<2>lazy@ %a@]" pretty_arg v + | Tpat_exception v -> + fprintf ppf "@[<2>exception@ %a@]" pretty_arg v | Tpat_alias (v, x,_) -> fprintf ppf "@[(%a@ as %a)@]" pretty_val v Ident.print x | Tpat_or (v,w,_) -> diff --git a/typing/printtyp.ml b/typing/printtyp.ml index efb2ed09..dfc67a57 100644 --- a/typing/printtyp.ml +++ b/typing/printtyp.ml @@ -25,6 +25,8 @@ open Types open Btype open Outcometree +module String = Misc.Stdlib.String + (* Print a long identifier *) let rec longident ppf = function @@ -32,44 +34,261 @@ let rec longident ppf = function | Ldot(p, s) -> fprintf ppf "%a.%s" longident p s | Lapply(p1, p2) -> fprintf ppf "%a(%a)" longident p1 longident p2 -(* Print an identifier *) +(* Print an identifier avoiding name collisions *) + +module Out_name = struct + let create x = { printed_name = x } + let print x = x.printed_name + let set out_name x = out_name.printed_name <- x +end -let unique_names = ref Ident.empty +(* printing environment for path shortening and naming *) +let printing_env = ref Env.empty +let human_unique n id = Printf.sprintf "%s/%d" (Ident.name id) n -let ident_name id = - try Ident.find_same id !unique_names with Not_found -> Ident.name id +type namespace = + | Type + | Module + | Module_type + | Class + | Class_type + | Other (** Other bypasses the unique name identifier mechanism *) -let add_unique id = - try ignore (Ident.find_same id !unique_names) - with Not_found -> - unique_names := Ident.add id (Ident.unique_toplevel_name id) !unique_names +module Namespace = struct -let ident ppf id = pp_print_string ppf (ident_name id) + let id = function + | Type -> 0 + | Module -> 1 + | Module_type -> 2 + | Class -> 3 + | Class_type -> 4 + | Other -> 5 + + let size = 1 + id Other + + let show = + function + | Type -> "type" + | Module -> "module" + | Module_type -> "module type" + | Class -> "class" + | Class_type -> "class type" + | Other -> "" + + let lookup = + let to_lookup f lid = + fst @@ f ?loc:None ?mark:(Some false) (Lident lid) !printing_env in + function + | Type -> fun id -> + Env.lookup_type ?loc:None ~mark:false (Lident id) !printing_env + | Module -> fun id -> + Env.lookup_module ~load:true ~mark:false ?loc:None + (Lident id) !printing_env + | Module_type -> to_lookup Env.lookup_modtype + | Class -> to_lookup Env.lookup_class + | Class_type -> to_lookup Env.lookup_cltype + | Other -> fun _ -> raise Not_found + + let location namespace id = + let env = !printing_env in + let path = Path.Pident id in + try Some ( + match namespace with + | Type -> (Env.find_type path env).type_loc + | Module -> (Env.find_module path env).md_loc + | Module_type -> (Env.find_modtype path env).mtd_loc + | Class -> (Env.find_class path env).cty_loc + | Class_type -> (Env.find_cltype path env).clty_loc + | Other -> Location.none + ) with Not_found -> None + + let best_class_namespace = function + | Papply _ | Pdot _ -> Module + | Pident c -> + match location Class c with + | Some _ -> Class + | None -> Class_type + +end + +(** {2 Conflicts printing} + Conflicts arise when multiple items are attributed the same name, + the following module stores the global conflict references and + provides the printing functions for explaining the source of + the conflicts. +*) +module Conflicts = struct + module M = String.Map + type explanation = { kind: namespace; name:string; location:Location.t} + let explanations = ref M.empty + let explain namespace n id = + let name = human_unique n id in + if not (M.mem name !explanations) then + match Namespace.location namespace id with + | None -> () + | Some location -> + explanations := + M.add name { kind = namespace; location; name } !explanations + + let pp_explanation ppf r= + Format.fprintf ppf "@[%a:@,Definition of %s %s@]" + Location.print_loc r.location (Namespace.show r.kind) r.name + + let pp ppf l = + Format.fprintf ppf "@[%a@]" (Format.pp_print_list pp_explanation) l + + let reset () = explanations := M.empty + let take () = + let c = !explanations in + reset (); + c |> M.bindings |> List.map snd |> List.sort Stdlib.compare + + let print ppf = + let sep ppf = Format.fprintf ppf "@ " in + let l = + List.filter (* remove toplevel locations, since they are too imprecise *) + ( fun a -> + a.location.Location.loc_start.Lexing.pos_fname <> "//toplevel//" ) + (take ()) in + match l with + | [] -> () + | l -> Format.fprintf ppf "%t%a" sep pp l + + let exists () = M.cardinal !explanations >0 +end + + +module Naming_context = struct + +module M = String.Map +module S = String.Set + +let enabled = ref true +let enable b = enabled := b + +(** Name mapping *) +type mapping = + | Need_unique_name of int Ident.Map.t + (** The same name has already been attributed to multiple types. + The [map] argument contains the specific binding time attributed to each + types. + *) + | Uniquely_associated_to of Ident.t * out_name + (** For now, the name [Ident.name id] has been attributed to [id], + [out_name] is used to expand this name if a conflict arises + at a later point + *) + | Associated_to_pervasives of out_name + (** [Associated_to_pervasives out_name] is used when the item + [Stdlib.$name] has been associated to the name [$name]. + Upon a conflict, this name will be expanded to ["Stdlib." ^ name ] *) + +let hid_start = 0 + +let add_hid_id id map = + let new_id = 1 + Ident.Map.fold (fun _ -> max) map hid_start in + new_id, Ident.Map.add id new_id map + +let find_hid id map = + try Ident.Map.find id map, map with + Not_found -> add_hid_id id map + +let pervasives name = "Stdlib." ^ name + +let map = Array.make Namespace.size M.empty +let get namespace = map.(Namespace.id namespace) +let set namespace x = map.(Namespace.id namespace) <- x + +(* Names used in recursive definitions are not considered when determining + if a name is already attributed in the current environment. + This is a weaker version of hidden_rec_items used by short-path. *) +let protected = ref S.empty +let add_protected id = protected := S.add (Ident.name id) !protected +let reset_protected () = protected := S.empty + +let pervasives_name namespace name = + if not !enabled then Out_name.create name else + match M.find name (get namespace) with + | Associated_to_pervasives r -> r + | Need_unique_name _ -> Out_name.create (pervasives name) + | Uniquely_associated_to (id',r) -> + let hid, map = add_hid_id id' Ident.Map.empty in + Out_name.set r (human_unique hid id'); + Conflicts.explain namespace hid id'; + set namespace @@ M.add name (Need_unique_name map) (get namespace); + Out_name.create (pervasives name) + | exception Not_found -> + let r = Out_name.create name in + set namespace @@ M.add name (Associated_to_pervasives r) (get namespace); + r + +(** Lookup for preexisting named item within the current {!printing_env} *) +let env_ident namespace name = + if S.mem name !protected then None else + match Namespace.lookup namespace name with + | Pident id -> Some id + | _ -> None + | exception Not_found -> None + +(** Associate a name to the identifier [id] within [namespace] *) +let ident_name_simple namespace id = + if not !enabled then Out_name.create (Ident.name id) else + let name = Ident.name id in + match M.find name (get namespace) with + | Uniquely_associated_to (id',r) when Ident.same id id' -> + r + | Need_unique_name map -> + let hid, m = find_hid id map in + Conflicts.explain namespace hid id; + set namespace @@ M.add name (Need_unique_name m) (get namespace); + Out_name.create (human_unique hid id) + | Uniquely_associated_to (id',r) -> + let hid', m = find_hid id' Ident.Map.empty in + let hid, m = find_hid id m in + Out_name.set r (human_unique hid' id'); + List.iter (fun (id,hid) -> Conflicts.explain namespace hid id) + [id, hid; id', hid' ]; + set namespace @@ M.add name (Need_unique_name m) (get namespace); + Out_name.create (human_unique hid id) + | Associated_to_pervasives r -> + Out_name.set r ("Stdlib." ^ Out_name.print r); + let hid, m = find_hid id Ident.Map.empty in + set namespace @@ M.add name (Need_unique_name m) (get namespace); + Out_name.create (human_unique hid id) + | exception Not_found -> + let r = Out_name.create name in + set namespace + @@ M.add name (Uniquely_associated_to (id,r) ) (get namespace); + r + +(** Same as {!ident_name_simple} but lookup to existing named identifiers + in the current {!printing_env} *) +let ident_name namespace id = + begin match env_ident namespace (Ident.name id) with + | Some id' -> ignore (ident_name_simple namespace id') + | None -> () + end; + ident_name_simple namespace id + +let reset () = + Array.iteri ( fun i _ -> map.(i) <- M.empty ) map + +end +let ident_name = Naming_context.ident_name +let reset_naming_context = Naming_context.reset + +let ident ppf id = pp_print_string ppf + (Out_name.print (Naming_context.ident_name_simple Other id)) (* Print a path *) let ident_stdlib = Ident.create_persistent "Stdlib" -let printing_env = ref Env.empty + let non_shadowed_pervasive = function - | Pdot(Pident id, s, _) as path -> + | Pdot(Pident id, s) as path -> Ident.same id ident_stdlib && (try Path.same path (Env.lookup_type (Lident s) !printing_env) with Not_found -> true) - | Pdot(Pdot (Pident id, "Pervasives", _), s, _) as path -> - Ident.same id ident_stdlib && - (* Make sure Stdlib. is the same as Stdlib.Pervasives. *) - (try - let td = - Env.find_type (Env.lookup_type (Lident s) !printing_env) - !printing_env - in - match td.type_private, td.type_manifest with - | Private, _ | _, None -> false - | Public, Some te -> - match (Btype.repr te).desc with - | Tconstr (path', _, _) -> Path.same path path' - | _ -> false - with Not_found -> true) | _ -> false let find_double_underscore s = @@ -86,7 +305,7 @@ let find_double_underscore s = let rec module_path_is_an_alias_of env path ~alias_of = match Env.find_module path env with - | { md_type = Mty_alias (_, path'); _ } -> + | { md_type = Mty_alias path'; _ } -> Path.same path' alias_of || module_path_is_an_alias_of env path' ~alias_of | _ -> false @@ -96,8 +315,8 @@ let rec module_path_is_an_alias_of env path ~alias_of = for Foo__bar. This pattern is used by the stdlib. *) let rec rewrite_double_underscore_paths env p = match p with - | Pdot (p, s, n) -> - Pdot (rewrite_double_underscore_paths env p, s, n) + | Pdot (p, s) -> + Pdot (rewrite_double_underscore_paths env p, s) | Papply (a, b) -> Papply (rewrite_double_underscore_paths env a, rewrite_double_underscore_paths env b) @@ -126,44 +345,29 @@ let rewrite_double_underscore_paths env p = else rewrite_double_underscore_paths env p -let rec tree_of_path = function +let rec tree_of_path namespace = function | Pident id -> - Oide_ident (ident_name id) - | Pdot(_, s, _pos) as path - when non_shadowed_pervasive path -> - Oide_ident s - | Pdot(p, s, _pos) -> - Oide_dot (tree_of_path p, s) + Oide_ident (ident_name namespace id) + | Pdot(_, s) as path when non_shadowed_pervasive path -> + Oide_ident (Naming_context.pervasives_name namespace s) + | Pdot(p, s) -> + Oide_dot (tree_of_path Module p, s) | Papply(p1, p2) -> - Oide_apply (tree_of_path p1, - tree_of_path p2) + Oide_apply (tree_of_path Module p1, tree_of_path Module p2) -let rec path ppf = function - | Pident id -> - ident ppf id - | Pdot(_, s, _pos) as path - when non_shadowed_pervasive path -> - pp_print_string ppf s - | Pdot(p, s, _pos) -> - path ppf p; - pp_print_char ppf '.'; - pp_print_string ppf s - | Papply(p1, p2) -> - fprintf ppf "%a(%a)" path p1 path p2 +let tree_of_path namespace p = + tree_of_path namespace (rewrite_double_underscore_paths !printing_env p) -let tree_of_path p = - tree_of_path (rewrite_double_underscore_paths !printing_env p) let path ppf p = - path ppf (rewrite_double_underscore_paths !printing_env p) + !Oprint.out_ident ppf (tree_of_path Other p) -let rec string_of_out_ident = function - | Oide_ident s -> s - | Oide_dot (id, s) -> String.concat "." [string_of_out_ident id; s] - | Oide_apply (id1, id2) -> - String.concat "" - [string_of_out_ident id1; "("; string_of_out_ident id2; ")"] +let string_of_path p = + Format.asprintf "%a" path p -let string_of_path p = string_of_out_ident (tree_of_path p) +let strings_of_paths namespace p = + reset_naming_context (); + let trees = List.map (tree_of_path namespace) p in + List.map (Format.asprintf "%a" !Oprint.out_ident) trees (* Print a recursive annotation *) @@ -329,8 +533,7 @@ let printing_depth = ref 0 let printing_cont = ref ([] : Env.iter_cont list) let printing_old = ref Env.empty let printing_pers = ref Concr.empty -module PathMap = Map.Make(Path) -let printing_map = ref PathMap.empty +let printing_map = ref Path.Map.empty let same_type t t' = repr t == repr t' @@ -363,7 +566,7 @@ let rec normalize_type_path ?(cache=false) env p = (p, Nth (index params ty)) with Not_found -> - (Env.normalize_path None env p, Id) + (Env.normalize_type_path None env p, Id) let penalty s = if s <> "" && s.[0] = '_' then @@ -375,8 +578,8 @@ let penalty s = let rec path_size = function Pident id -> - penalty (Ident.name id), -Ident.binding_time id - | Pdot (p, _, _) -> + penalty (Ident.name id), -Ident.scope id + | Pdot (p, _) -> let (l, b) = path_size p in (1+l, b) | Papply (p1, p2) -> let (l, b) = path_size p1 in @@ -396,7 +599,7 @@ let set_printing_env env = (* printf "Reset printing_map@."; *) printing_old := env; printing_pers := Env.used_persistent (); - printing_map := PathMap.empty; + printing_map := Path.Map.empty; printing_depth := 0; (* printf "Recompute printing_map.@."; *) let cont = @@ -406,19 +609,19 @@ let set_printing_env env = (* Format.eprintf "%a -> %a = %a@." path p path p' path p1 *) if s1 = Id then try - let r = PathMap.find p1 !printing_map in + let r = Path.Map.find p1 !printing_map in match !r with Paths l -> r := Paths (p :: l) | Best p' -> r := Paths [p; p'] (* assert false *) with Not_found -> - printing_map := PathMap.add p1 (ref (Paths [p])) !printing_map) + printing_map := Path.Map.add p1 (ref (Paths [p])) !printing_map) env in printing_cont := [cont]; end let wrap_printing_env env f = - set_printing_env env; - try_finally f (fun () -> set_printing_env Env.empty) + set_printing_env env; reset_naming_context (); + try_finally f ~always:(fun () -> set_printing_env Env.empty) let wrap_printing_env ~error env f = if error then Env.without_cmis (wrap_printing_env env) f @@ -462,7 +665,7 @@ let best_type_path p = then (p, Id) else let (p', s) = normalize_type_path !printing_env p in - let get_path () = get_best_path (PathMap.find p' !printing_map) in + let get_path () = get_best_path (Path.Map.find p' !printing_map) in while !printing_cont <> [] && try fst (path_size (get_path ())) > !printing_depth with Not_found -> true do @@ -481,7 +684,7 @@ let named_vars = ref ([] : string list) let weak_counter = ref 1 let weak_var_map = ref TypeMap.empty -let named_weak_vars = ref StringSet.empty +let named_weak_vars = ref String.Set.empty let reset_names () = names := []; name_counter := 0; named_vars := [] let add_named_var ty = @@ -494,23 +697,23 @@ let add_named_var ty = let name_is_already_used name = List.mem name !named_vars || List.exists (fun (_, name') -> name = name') !names - || StringSet.mem name !named_weak_vars + || String.Set.mem name !named_weak_vars let rec new_name () = let name = if !name_counter < 26 then String.make 1 (Char.chr(97 + !name_counter)) else String.make 1 (Char.chr(97 + !name_counter mod 26)) ^ - string_of_int(!name_counter / 26) in + Int.to_string(!name_counter / 26) in incr name_counter; if name_is_already_used name then new_name () else name let rec new_weak_name ty () = - let name = "weak" ^ string_of_int !weak_counter in + let name = "weak" ^ Int.to_string !weak_counter in incr weak_counter; if name_is_already_used name then new_weak_name ty () else begin - named_weak_vars := StringSet.add name !named_weak_vars; + named_weak_vars := String.Set.add name !named_weak_vars; weak_var_map := TypeMap.add ty name !weak_var_map; name end @@ -529,7 +732,7 @@ let name_of_type name_generator t = let current_name = ref name in let i = ref 0 in while List.exists (fun (_, name') -> !current_name = name') !names do - current_name := name ^ (string_of_int !i); + current_name := name ^ (Int.to_string !i); i := !i + 1; done; !current_name @@ -642,14 +845,18 @@ let mark_loops ty = let reset_loop_marks () = visited_objects := []; aliased := []; delayed := [] +let reset_except_context () = + reset_names (); reset_loop_marks () + let reset () = - unique_names := Ident.empty; reset_names (); reset_loop_marks () + reset_naming_context (); Conflicts.reset (); + reset_except_context () let reset_and_mark_loops ty = - reset (); mark_loops ty + reset_except_context (); mark_loops ty let reset_and_mark_loops_list tyl = - reset (); List.iter mark_loops tyl + reset_except_context (); List.iter mark_loops tyl (* Disabled in classic mode when printing an unification error *) let print_labels = ref true @@ -666,7 +873,7 @@ let rec tree_of_typexp sch ty = match ty.desc with | Tvar _ -> (*let lev = - if is_non_gen sch ty then "/" ^ string_of_int ty.level else "" in*) + if is_non_gen sch ty then "/" ^ Int.to_string ty.level else "" in*) let non_gen = is_non_gen sch ty in let name_gen = if non_gen then new_weak_name ty else new_name in Otyp_var (non_gen, name_of_type name_gen ty) @@ -691,7 +898,7 @@ let rec tree_of_typexp sch ty = let p', s = best_type_path p in let tyl' = apply_subst s tyl in if is_nth s && not (tyl'=[]) then tree_of_typexp sch (List.hd tyl') else - Otyp_constr (tree_of_path p', tree_of_typlist sch tyl') + Otyp_constr (tree_of_path Type p', tree_of_typlist sch tyl') | Tvariant row -> let row = row_repr row in let fields = @@ -710,7 +917,7 @@ let rec tree_of_typexp sch ty = begin match row.row_name with | Some(p, tyl) when namable_row row -> let (p', s) = best_type_path p in - let id = tree_of_path p' in + let id = tree_of_path Type p' in let args = tree_of_typlist sch (apply_subst s tyl) in let out_variant = if is_nth s then List.hd args else Otyp_constr (id, args) in @@ -760,7 +967,7 @@ let rec tree_of_typexp sch ty = | Tpackage (p, n, tyl) -> let n = List.map (fun li -> String.concat "." (Longident.flatten li)) n in - Otyp_module (Path.name p, n, tree_of_typlist sch tyl) + Otyp_module (tree_of_path Module_type p, n, tree_of_typlist sch tyl) in if List.memq px !delayed then delayed := List.filter ((!=) px) !delayed; if is_aliased px && aliasable ty then begin @@ -804,7 +1011,7 @@ and tree_of_typobject sch fi nm = let args = tree_of_typlist sch tyl in let (p', s) = best_type_path p in assert (s = Id); - Otyp_class (non_gen, tree_of_path p', args) + Otyp_class (non_gen, tree_of_path Type p', args) | _ -> fatal_error "Printtyp.tree_of_typobject" end @@ -836,15 +1043,6 @@ and type_sch ppf ty = typexp true ppf ty and type_scheme ppf ty = reset_and_mark_loops ty; typexp true ppf ty -let type_expansion ppf ty1 ty2 = - let tree1 = tree_of_typexp false ty1 in - let tree2 = tree_of_typexp false ty2 in - let pp = !Oprint.out_type in - if tree1 = tree2 then - pp ppf tree1 - else - fprintf ppf "@[<2>%a@ =@ %a@]" pp tree1 pp tree2 - (* Maxence *) let type_scheme_max ?(b_reset_names=true) ppf ty = if b_reset_names then reset_names () ; @@ -881,7 +1079,7 @@ let mark_loops_constructor_arguments = function let rec tree_of_type_decl id decl = - reset(); + reset_except_context(); let params = filter_params decl.type_params in @@ -1028,7 +1226,7 @@ let constructor_arguments ppf a = (* Print an extension declaration *) let tree_of_extension_constructor id ext es = - reset (); + reset_except_context (); let ty_name = Path.name ext.ext_type_path in let ty_params = filter_params ext.ext_type_params in List.iter add_alias ty_params; @@ -1148,7 +1346,8 @@ let rec tree_of_class_type sch params = then tree_of_class_type sch params cty else - Octy_constr (tree_of_path p', tree_of_typlist true tyl) + let namespace = Namespace.best_class_namespace p' in + Octy_constr (tree_of_path namespace p', tree_of_typlist true tyl) | Cty_signature sign -> let sty = repr sign.csig_self in let self_ty = @@ -1185,13 +1384,13 @@ let rec tree_of_class_type sch params = let lab = if !print_labels || is_optional l then string_of_label l else "" in - let ty = + let tr = if is_optional l then match (repr ty).desc with - | Tconstr(path, [ty], _) when Path.same path Predef.path_option -> ty - | _ -> newconstr (Path.Pident(Ident.create "")) [] - else ty in - let tr = tree_of_typexp sch ty in + | Tconstr(path, [ty], _) when Path.same path Predef.path_option -> + tree_of_typexp sch ty + | _ -> Otyp_stuff "" + else tree_of_typexp sch ty in Octy_arrow (lab, tr, tree_of_class_type sch params cty) let class_type ppf cty = @@ -1211,7 +1410,7 @@ let class_variance = let tree_of_class_declaration id cl rs = let params = filter_params cl.cty_params in - reset (); + reset_except_context (); List.iter add_alias params; prepare_class_type params cl.cty_type; let sty = Ctype.self_type cl.cty_type in @@ -1233,7 +1432,7 @@ let class_declaration id ppf cl = let tree_of_cltype_declaration id cl rs = let params = List.map repr cl.clty_params in - reset (); + reset_except_context (); List.iter add_alias params; prepare_class_type params cl.clty_type; let sty = Ctype.self_type cl.clty_type in @@ -1284,30 +1483,58 @@ let filter_rem_sig item rem = let dummy = { type_params = []; type_arity = 0; type_kind = Type_abstract; type_private = Public; type_manifest = None; type_variance = []; - type_newtype_level = None; type_loc = Location.none; + type_is_newtype = false; type_expansion_scope = Btype.lowest_level; + type_loc = Location.none; type_attributes = []; type_immediate = false; type_unboxed = unboxed_false_default_false; } +let hide ids env = List.fold_right + (fun id -> Env.add_type ~check:false (Ident.rename id) dummy) + ids env + let hide_rec_items = function - | Sig_type(id, _decl, rs) ::rem + | Sig_type(id, _decl, rs, _) ::rem when rs = Trec_first && not !Clflags.real_paths -> let rec get_ids = function - Sig_type (id, _, Trec_next) :: rem -> + Sig_type (id, _, Trec_next, _) :: rem -> id :: get_ids rem | _ -> [] in let ids = id :: get_ids rem in set_printing_env - (List.fold_right - (fun id -> Env.add_type ~check:false (Ident.rename id) dummy) - ids !printing_env) + (hide ids !printing_env) | _ -> () +let recursive_sigitem = function + | Sig_class(id,_,rs,_) -> Some(id,rs,3) + | Sig_class_type (id,_,rs,_) -> Some(id,rs,2) + | Sig_type(id, _, rs, _) + | Sig_module(id, _, _, rs, _) -> Some (id,rs,0) + | _ -> None + +let skip k l = snd (Misc.Stdlib.List.split_at k l) + +let protect_rec_items items = + let rec get_ids recs = function + | [] -> [] + | item :: rem -> match recursive_sigitem item with + | Some (id, r, k ) when r = recs -> id :: get_ids Trec_next (skip k rem) + | _ -> [] in + List.iter Naming_context.add_protected (get_ids Trec_first items) + +let still_in_type_group env' in_type_group item = + match in_type_group, recursive_sigitem item with + true, Some (_,Trec_next,_) -> true + | _, Some (_, (Trec_not | Trec_first),_) -> + Naming_context.reset_protected (); + set_printing_env env'; true + | _ -> Naming_context.reset_protected (); set_printing_env env'; false + let rec tree_of_modtype ?(ellipsis=false) = function | Mty_ident p -> - Omty_ident (tree_of_path p) + Omty_ident (tree_of_path Module_type p) | Mty_signature sg -> Omty_signature (if ellipsis then [Osig_ellipsis] else tree_of_signature sg) @@ -1315,13 +1542,13 @@ let rec tree_of_modtype ?(ellipsis=false) = function let res = match ty_arg with None -> tree_of_modtype ~ellipsis ty_res | Some mty -> - wrap_env (Env.add_module ~arg:true param mty) + wrap_env (Env.add_module ~arg:true param Mp_present mty) (tree_of_modtype ~ellipsis) ty_res in Omty_functor (Ident.name param, may_map (tree_of_modtype ~ellipsis:false) ty_arg, res) - | Mty_alias(_, p) -> - Omty_alias (tree_of_path p) + | Mty_alias p -> + Omty_alias (tree_of_path Module p) and tree_of_signature sg = wrap_env (fun env -> env) (tree_of_signature_rec !printing_env false) sg @@ -1329,39 +1556,36 @@ and tree_of_signature sg = and tree_of_signature_rec env' in_type_group = function [] -> [] | item :: rem as items -> - let in_type_group = - match in_type_group, item with - true, Sig_type (_, _, Trec_next) -> true - | _, Sig_type (_, _, (Trec_not | Trec_first)) -> - set_printing_env env'; true - | _ -> set_printing_env env'; false - in + let in_type_group = still_in_type_group env' in_type_group item in let (sg, rem) = filter_rem_sig item rem in hide_rec_items items; + protect_rec_items items; + reset_naming_context (); let trees = trees_of_sigitem item in let env' = Env.add_signature (item :: sg) env' in trees @ tree_of_signature_rec env' in_type_group rem and trees_of_sigitem = function - | Sig_value(id, decl) -> + | Sig_value(id, decl, _) -> [tree_of_value_description id decl] - | Sig_type(id, _, _) when is_row_name (Ident.name id) -> + | Sig_type(id, _, _, _) when is_row_name (Ident.name id) -> [] - | Sig_type(id, decl, rs) -> + | Sig_type(id, decl, rs, _) -> [tree_of_type_declaration id decl rs] - | Sig_typext(id, ext, es) -> + | Sig_typext(id, ext, es, _) -> [tree_of_extension_constructor id ext es] - | Sig_module(id, md, rs) -> + | Sig_module(id, _, md, rs, _) -> let ellipsis = - List.exists (function ({txt="..."}, Parsetree.PStr []) -> true - | _ -> false) + List.exists (function + | Parsetree.{attr_name = {txt="..."}; attr_payload = PStr []} -> true + | _ -> false) md.md_attributes in [tree_of_module id md.md_type rs ~ellipsis] - | Sig_modtype(id, decl) -> + | Sig_modtype(id, decl, _) -> [tree_of_modtype_declaration id decl] - | Sig_class(id, decl, rs) -> + | Sig_class(id, decl, rs, _) -> [tree_of_class_declaration id decl rs] - | Sig_class_type(id, decl, rs) -> + | Sig_class_type(id, decl, rs, _) -> [tree_of_cltype_declaration id decl rs] and tree_of_modtype_declaration id decl = @@ -1387,25 +1611,30 @@ let refresh_weak () = if is_non_gen true (repr t) then begin TypeMap.add t name m, - StringSet.add name s + String.Set.add name s end else m, s in let m, s = - TypeMap.fold refresh !weak_var_map (TypeMap.empty ,StringSet.empty) in + TypeMap.fold refresh !weak_var_map (TypeMap.empty ,String.Set.empty) in named_weak_vars := s; weak_var_map := m let print_items showval env x = refresh_weak(); - let rec print showval env = function + reset_naming_context (); + Conflicts.reset (); + let rec print showval in_type_group env = function | [] -> [] | item :: rem as items -> - let (_sg, rem) = filter_rem_sig item rem in + let in_type_group = still_in_type_group env in_type_group item in + let (sg, rem) = filter_rem_sig item rem in hide_rec_items items; + protect_rec_items items; + reset_naming_context (); let trees = trees_of_sigitem item in List.map (fun d -> (d, showval env item)) trees @ - print showval env rem in - print showval env x + print showval in_type_group (Env.add_signature (item :: sg) env) rem in + print showval false env x (* Print a signature body (used by -i when compiling a .ml) *) @@ -1415,6 +1644,22 @@ let print_signature ppf tree = let signature ppf sg = fprintf ppf "%a" print_signature (tree_of_signature sg) +(* Print a signature body (used by -i when compiling a .ml) *) +let printed_signature sourcefile ppf sg = + (* we are tracking any collision event for warning 63 *) + Conflicts.reset (); + reset_naming_context (); + let t = tree_of_signature sg in + if Warnings.(is_active @@ Erroneous_printed_signature "") + && Conflicts.exists () + then begin + let conflicts = Format.asprintf "%t" Conflicts.print in + Location.prerr_warning (Location.in_file sourcefile) + (Warnings.Erroneous_printed_signature conflicts); + Warnings.check_fatal () + end; + fprintf ppf "%a" print_signature t + (* Print an unification error *) let same_path t t' = @@ -1434,44 +1679,95 @@ let same_path t t' = | _ -> false -let type_expansion t ppf t' = +type 'a diff = Same of 'a | Diff of 'a * 'a + +let trees_of_type_expansion (t,t') = if same_path t t' - then begin add_delayed (proxy t); type_expr ppf t end + then begin add_delayed (proxy t); Same (tree_of_typexp false t) end else - let t' = if proxy t == proxy t' then unalias t' else t' in - type_expansion ppf t t' - -let type_path_expansion tp ppf tp' = - if Path.same tp tp' then path ppf tp else - fprintf ppf "@[<2>%a@ =@ %a@]" path tp path tp' + let t' = if proxy t == proxy t' then unalias t' else t' in + (* beware order matter due to side effect, + e.g. when printing object types *) + let first = tree_of_typexp false t in + let second = tree_of_typexp false t' in + if first = second then Same first + else Diff(first,second) + +let type_expansion ppf = function + | Same t -> !Oprint.out_type ppf t + | Diff(t,t') -> + fprintf ppf "@[<2>%a@ =@ %a@]" !Oprint.out_type t !Oprint.out_type t' + +module Trace = Ctype.Unification_trace + +let trees_of_trace = List.map (Trace.map_diff trees_of_type_expansion) + +let trees_of_type_path_expansion (tp,tp') = + if Path.same tp tp' then Same(tree_of_path Type tp) else + Diff(tree_of_path Type tp, tree_of_path Type tp') + +let type_path_expansion ppf = function + | Same p -> !Oprint.out_ident ppf p + | Diff(p,p') -> + fprintf ppf "@[<2>%a@ =@ %a@]" + !Oprint.out_ident p + !Oprint.out_ident p' let rec trace fst txt ppf = function - | (t1, t1') :: (t2, t2') :: rem -> + | {Trace.got; expected} :: rem -> if not fst then fprintf ppf "@,"; fprintf ppf "@[Type@;<1 2>%a@ %s@;<1 2>%a@] %a" - (type_expansion t1) t1' txt (type_expansion t2) t2' + type_expansion got txt type_expansion expected (trace false txt) rem | _ -> () + +type printing_status = + | Discard + | Keep + | Optional_refinement + (** An [Optional_refinement] printing status is attributed to trace + elements that are focusing on a new subpart of a structural type. + Since the whole type should have been printed earlier in the trace, + we only print those elements if they are the last printed element + of a trace, and there is no explicit explanation for the + type error. + *) + +let printing_status = function + | Trace.(Diff { got=t1, t1'; expected=t2, t2'}) -> + if is_constr_row ~allow_ident:true t1' + || is_constr_row ~allow_ident:true t2' + then Discard + else if same_path t1 t1' && same_path t2 t2' then Optional_refinement + else Keep + | _ -> Keep + +(** Flatten the trace and remove elements that are always discarded + during printing *) +let prepare_trace f tr = + let clean_trace x l = match printing_status x with + | Keep -> x :: l + | Optional_refinement when l = [] -> [x] + | Optional_refinement | Discard -> l + in + match Trace.flatten f tr with + | [] -> [] + | elt :: rem -> (* the first element is always kept *) + elt :: List.fold_right clean_trace rem [] + +(** Keep elements that are not [Diff _ ] and take the decision + for the last element, require a prepared trace *) let rec filter_trace keep_last = function - | (_, t1') :: (_, t2') :: [] when is_Tvar t1' || is_Tvar t2' -> - [] - | (t1, t1') :: (t2, t2') :: rem -> - let rem' = filter_trace keep_last rem in - if is_constr_row ~allow_ident:true t1' - || is_constr_row ~allow_ident:true t2' - || same_path t1 t1' && same_path t2 t2' && not (keep_last && rem' = []) - then rem' - else (t1, t1') :: (t2, t2') :: rem' - | _ -> [] - -let rec type_path_list ppf = function - | [tp, tp'] -> type_path_expansion tp ppf tp' - | (tp, tp') :: rem -> - fprintf ppf "%a@;<2 0>%a" - (type_path_expansion tp) tp' - type_path_list rem - | [] -> () + | [] -> [] + | [Trace.Diff d as elt] when printing_status elt = Optional_refinement -> + if keep_last then [d] else [] + | Trace.Diff d :: rem -> d :: filter_trace keep_last rem + | _ :: rem -> filter_trace keep_last rem + +let type_path_list = + Format.pp_print_list ~pp_sep:(fun ppf () -> Format.pp_print_break ppf 2 0) + type_path_expansion (* Hide variant name and var, to force printing the expanded type *) let hide_variant_name t = @@ -1514,7 +1810,7 @@ let unifiable env ty1 ty2 = Btype.backtrack snap; res -let explanation env unif t3 t4 : (Format.formatter -> unit) option = +let explanation_diff env t3 t4 : (Format.formatter -> unit) option = match t3.desc, t4.desc with | Tarrow (_, ty1, ty2, _), _ when is_unit env ty1 && unifiable env ty2 t4 -> @@ -1525,90 +1821,91 @@ let explanation env unif t3 t4 : (Format.formatter -> unit) option = when is_unit env ty1 && unifiable env t3 ty2 -> Some (fun ppf -> fprintf ppf - "@,@[Hint: Did you forget to wrap the expression using `fun () ->'?@]") - | Ttuple [], Tvar _ | Tvar _, Ttuple [] -> - Some (fun ppf -> - fprintf ppf "@,Self type cannot escape its class") - | Tconstr (p, _, _), Tvar _ - when unif && t4.level < Path.binding_time p -> - Some (fun ppf -> - fprintf ppf - "@,@[The type constructor@;<1 2>%a@ would escape its scope@]" - path p) - | Tvar _, Tconstr (p, _, _) - when unif && t3.level < Path.binding_time p -> - Some (fun ppf -> - fprintf ppf - "@,@[The type constructor@;<1 2>%a@ would escape its scope@]" - path p) - | Tvar _, Tunivar _ | Tunivar _, Tvar _ -> - Some (fun ppf -> - fprintf ppf "@,The universal variable %a would escape its scope" - type_expr (if is_Tunivar t3 then t3 else t4)) - | Tvar _, _ | _, Tvar _ -> - Some (fun ppf -> - let t, t' = if is_Tvar t3 then (t3, t4) else (t4, t3) in - if occur_in Env.empty t t' then - fprintf ppf "@,@[The type variable %a occurs inside@ %a@]" - type_expr t type_expr t' - else - fprintf ppf "@,@[This instance of %a is ambiguous:@ %s@]" - type_expr t' - "it would escape the scope of its equation") - | Tfield (lab, _, _, _), _ when lab = dummy_method -> - Some (fun ppf -> - fprintf ppf - "@,Self type cannot be unified with a closed object type") - | _, Tfield (lab, _, _, _) when lab = dummy_method -> - Some (fun ppf -> - fprintf ppf - "@,Self type cannot be unified with a closed object type") - | Tfield (l,_,_,{desc=Tnil}), Tfield (l',_,_,{desc=Tnil}) when l = l' -> - Some (fun ppf -> - fprintf ppf "@,Types for method %s are incompatible" l) - | (Tnil|Tconstr _), Tfield (l, _, _, _) -> - Some (fun ppf -> - fprintf ppf - "@,@[The first object type has no method %s@]" l) - | Tfield (l, _, _, _), (Tnil|Tconstr _) -> - Some (fun ppf -> - fprintf ppf - "@,@[The second object type has no method %s@]" l) - | Tnil, Tconstr _ | Tconstr _, Tnil -> - Some (fun ppf -> - fprintf ppf - "@,@[The %s object type has an abstract row, it cannot be closed@]" - (if t4.desc = Tnil then "first" else "second")) - | Tvariant row1, Tvariant row2 -> - Some (fun ppf -> - let row1 = row_repr row1 and row2 = row_repr row2 in - begin match - row1.row_fields, row1.row_closed, row2.row_fields, row2.row_closed with - | [], true, [], true -> - fprintf ppf "@,These two variant types have no intersection" - | [], true, (_::_ as fields), _ -> - fprintf ppf - "@,@[The first variant type does not allow tag(s)@ @[%a@]@]" - print_tags fields - | (_::_ as fields), _, [], true -> - fprintf ppf - "@,@[The second variant type does not allow tag(s)@ @[%a@]@]" - print_tags fields - | [l1,_], true, [l2,_], true when l1 = l2 -> - fprintf ppf "@,Types for tag `%s are incompatible" l1 - | _ -> () - end) + "@,@[Hint: Did you forget to wrap the expression using \ + `fun () ->'?@]") | _ -> None -let rec mismatch env unif = function - (_, t) :: (_, t') :: rem -> - begin match mismatch env unif rem with - Some _ as m -> m - | None -> explanation env unif t t' - end - | [] -> None - | _ -> assert false +let print_pos ppf = function + | Trace.First -> fprintf ppf "first" + | Trace.Second -> fprintf ppf "second" + +let explain_variant = function + | Trace.No_intersection -> + Some(dprintf "@,These two variant types have no intersection") + | Trace.No_tags(pos,fields) -> Some( + dprintf + "@,@[The %a variant type does not allow tag(s)@ @[%a@]@]" + print_pos pos + print_tags fields + ) + | Trace.Incompatible_types_for s -> + Some(dprintf "@,Types for tag `%s are incompatible" s) + +let explain_escape intro prev ctx e = + let pre = match ctx with + | Some ctx -> dprintf "@[%t@;<1 2>%a@]" intro type_expr ctx + | None -> match e, prev with + | Trace.Univ _, Some(Trace.Incompatible_fields {name; diff}) -> + dprintf "@,@[The method %s has type@ %a,@ \ + but the expected method type was@ %a@]" name + type_expr diff.Trace.got type_expr diff.Trace.expected + | _ -> ignore in + match e with + | Trace.Univ u -> Some( + dprintf "%t@,The universal variable %a would escape its scope" + pre type_expr u) + | Trace.Constructor p -> Some( + dprintf + "%t@,@[The type constructor@;<1 2>%a@ would escape its scope@]" + pre path p + ) + | Trace.Module_type p -> Some( + dprintf + "%t@,@[The module type@;<1 2>%a@ would escape its scope@]" + pre path p + ) + | Trace.Equation (_,t) -> Some( + dprintf "%t @,@[This instance of %a is ambiguous:@ %s@]" + pre type_expr t + "it would escape the scope of its equation" + ) + | Trace.Self -> + Some (dprintf "%t@,Self type cannot escape its class" pre) + + +let explain_object = function + | Trace.Self_cannot_be_closed -> + Some (dprintf "@,Self type cannot be unified with a closed object type") + | Trace.Missing_field (pos,f) -> + Some(dprintf "@,@[The %a object type has no method %s@]" print_pos pos f) + | Trace.Abstract_row pos -> Some( + dprintf + "@,@[The %a object type has an abstract row, it cannot be closed@]" + print_pos pos + ) + + +let explanation intro prev env = function + | Trace.Diff { Trace.got = _, s; expected = _,t } -> explanation_diff env s t + | Trace.Escape {kind;context} -> explain_escape intro prev context kind + | Trace.Incompatible_fields { name; _ } -> + Some(dprintf "@,Types for method %s are incompatible" name) + | Trace.Variant v -> explain_variant v + | Trace.Obj o -> explain_object o + | Trace.Rec_occur(x,y) -> + mark_loops y; + Some(dprintf "@,@[The type variable %a occurs inside@ %a@]" + type_expr x type_expr y) + +let mismatch intro env trace = + let rec mismatch intro env = function + | [] -> None + | [h] -> explanation intro None env h + | h :: (prev :: _ as rem) -> match explanation intro (Some prev) env h with + | Some _ as m -> m + | None -> mismatch intro env rem in + mismatch intro env (List.rev trace) let explain mis ppf = match mis with @@ -1628,81 +1925,78 @@ let warn_on_missing_def env ppf t = end | _ -> () -let ident_same_name id1 id2 = - if Ident.equal id1 id2 && not (Ident.same id1 id2) then begin - add_unique id1; add_unique id2 - end -let rec path_same_name p1 p2 = - match p1, p2 with - Pident id1, Pident id2 -> ident_same_name id1 id2 - | Pdot (p1, s1, _), Pdot (p2, s2, _) when s1 = s2 -> path_same_name p1 p2 - | Papply (p1, p1'), Papply (p2, p2') -> - path_same_name p1 p2; path_same_name p1' p2' - | _ -> () +let prepare_expansion_head empty_tr = function + | Trace.Diff d -> + Some(Trace.map_diff (may_prepare_expansion empty_tr) d) + | _ -> None -let type_same_name t1 t2 = - match (repr t1).desc, (repr t2).desc with - Tconstr (p1, _, _), Tconstr (p2, _, _) -> - path_same_name (fst (best_type_path p1)) (fst (best_type_path p2)) - | _ -> () +let head_error_printer txt_got txt_but = function + | None -> ignore + | Some d -> + let d = Trace.map_diff trees_of_type_expansion d in + dprintf "%t@;<1 2>%a@ %t@;<1 2>%a" + txt_got type_expansion d.Trace.got + txt_but type_expansion d.Trace.expected -let rec trace_same_names = function - (t1, t1') :: (t2, t2') :: rem -> - type_same_name t1 t2; type_same_name t1' t2'; trace_same_names rem - | _ -> () +let warn_on_missing_defs env ppf = function + | None -> () + | Some {Trace.got=te1,_; expected=te2,_ } -> + warn_on_missing_def env ppf te1; + warn_on_missing_def env ppf te2 -let unification_error env unif tr txt1 ppf txt2 ty_expect_explanation = +let unification_error env tr txt1 ppf txt2 ty_expect_explanation = reset (); - trace_same_names tr; - let tr = List.map (fun (t, t') -> (t, hide_variant_name t')) tr in - let mis = mismatch env unif tr in + let tr = prepare_trace (fun t t' -> t, hide_variant_name t') tr in + let mis = mismatch txt1 env tr in match tr with - | [] | _ :: [] -> assert false - | t1 :: t2 :: tr -> + | [] -> assert false + | elt :: tr -> try - let tr = filter_trace (mis = None) tr in - let t1, t1' = may_prepare_expansion (tr = []) t1 - and t2, t2' = may_prepare_expansion (tr = []) t2 in print_labels := not !Clflags.classic; - let tr = List.map prepare_expansion tr in + let tr = filter_trace (mis = None) tr in + let head = prepare_expansion_head (tr=[]) elt in + let tr = List.map (Trace.map_diff prepare_expansion) tr in + let head_error = head_error_printer txt1 txt2 head in + let tr = trees_of_trace tr in fprintf ppf "@[\ - @[%t@;<1 2>%a@ \ - %t@;<1 2>%a\ - %t\ - @]%a%t\ + @[%t%t@]%a%t\ @]" - txt1 (type_expansion t1) t1' - txt2 (type_expansion t2) t2' + head_error ty_expect_explanation (trace false "is not compatible with type") tr (explain mis); if env <> Env.empty - then begin - warn_on_missing_def env ppf t1; - warn_on_missing_def env ppf t2 - end; + then warn_on_missing_defs env ppf head; + Conflicts.print ppf; print_labels := true with exn -> print_labels := true; raise exn -let report_unification_error ppf env ?(unif=true) tr +let report_unification_error ppf env tr ?(type_expected_explanation = fun _ -> ()) txt1 txt2 = - wrap_printing_env env (fun () -> unification_error env unif tr txt1 ppf txt2 + wrap_printing_env env (fun () -> unification_error env tr txt1 ppf txt2 type_expected_explanation) ~error:true ;; +(** [trace] requires the trace to be prepared *) let trace fst keep_last txt ppf tr = print_labels := not !Clflags.classic; - trace_same_names tr; try match tr with - t1 :: t2 :: tr' -> - if fst then trace fst txt ppf (t1 :: t2 :: filter_trace keep_last tr') - else trace fst txt ppf (filter_trace keep_last tr); + | elt :: tr' -> + let elt = match elt with + | Trace.Diff diff -> [Trace.map_diff trees_of_type_expansion diff] + | _ -> [] in + let tr = + trees_of_trace + @@ List.map (Trace.map_diff prepare_expansion) + @@ filter_trace keep_last tr' in + if fst then trace fst txt ppf (elt @ tr) + else trace fst txt ppf tr; print_labels := true | _ -> () with exn -> @@ -1712,34 +2006,46 @@ let trace fst keep_last txt ppf tr = let report_subtyping_error ppf env tr1 txt1 tr2 = wrap_printing_env ~error:true env (fun () -> reset (); - let tr1 = List.map prepare_expansion tr1 - and tr2 = List.map prepare_expansion tr2 in - fprintf ppf "@[%a" (trace true (tr2 = []) txt1) tr1; + let tr1 = prepare_trace (fun t t' -> prepare_expansion (t, t')) tr1 in + let tr2 = prepare_trace (fun t t' -> prepare_expansion (t, t')) tr2 in + let keep_first = match tr2 with + | Trace.[Obj _ | Variant _ | Escape _ ] | [] -> true + | _ -> false in + fprintf ppf "@[%a" (trace true keep_first txt1) tr1; if tr2 = [] then fprintf ppf "@]" else - let mis = mismatch env true tr2 in - fprintf ppf "%a%t@]" + let mis = mismatch (dprintf "Within this type") env tr2 in + fprintf ppf "%a%t%t@]" (trace false (mis = None) "is not compatible with type") tr2 - (explain mis)) + (explain mis) + Conflicts.print + ) + -let report_ambiguous_type_error ppf env (tp0, tp0') tpl txt1 txt2 txt3 = +let report_ambiguous_type_error ppf env tp0 tpl txt1 txt2 txt3 = wrap_printing_env ~error:true env (fun () -> reset (); - List.iter - (fun (tp, tp') -> path_same_name tp0 tp; path_same_name tp0' tp') - tpl; - match tpl with + let tp0 = trees_of_type_path_expansion tp0 in + match tpl with [] -> assert false - | [tp, tp'] -> + | [tp] -> fprintf ppf "@[%t@;<1 2>%a@ \ %t@;<1 2>%a\ @]" - txt1 (type_path_expansion tp) tp' - txt3 (type_path_expansion tp0) tp0' + txt1 type_path_expansion (trees_of_type_path_expansion tp) + txt3 type_path_expansion tp0 | _ -> fprintf ppf "@[%t@;<1 2>@[%a@]\ @ %t@;<1 2>%a\ @]" - txt2 type_path_list tpl - txt3 (type_path_expansion tp0) tp0') + txt2 type_path_list (List.map trees_of_type_path_expansion tpl) + txt3 type_path_expansion tp0) + +(* Adapt functions to exposed interface *) +let tree_of_path = tree_of_path Other +let tree_of_modtype = tree_of_modtype ~ellipsis:false +let type_expansion ty ppf ty' = + type_expansion ppf (trees_of_type_expansion (ty,ty')) +let tree_of_type_declaration id td rs = + wrap_env (hide [id]) (fun () -> tree_of_type_declaration id td rs) () diff --git a/typing/printtyp.mli b/typing/printtyp.mli index b824d164..77061d1a 100644 --- a/typing/printtyp.mli +++ b/typing/printtyp.mli @@ -24,6 +24,24 @@ val ident: formatter -> Ident.t -> unit val tree_of_path: Path.t -> out_ident val path: formatter -> Path.t -> unit val string_of_path: Path.t -> string + +module Out_name: sig + val create: string -> out_name + val print: out_name -> string +end + +type namespace = + | Type + | Module + | Module_type + | Class + | Class_type + | Other (** Other bypasses the unique name for identifier mechanism *) + +val strings_of_paths: namespace -> Path.t list -> string list + (** Print a list of paths, using the same naming context to + avoid name collisions *) + val raw_type_expr: formatter -> type_expr -> unit val string_of_label: Asttypes.arg_label -> string @@ -32,6 +50,34 @@ val wrap_printing_env: error:bool -> Env.t -> (unit -> 'a) -> 'a (* This affects all the printing functions below *) (* Also, if [~error:true], then disable the loading of cmis *) +module Naming_context: sig + val enable: bool -> unit + (** When contextual names are enabled, the mapping between identifiers + and names is ensured to be one-to-one. *) + + val reset: unit -> unit + (** Reset the naming context *) +end + +(** The [Conflicts] module keeps track of conflicts arising when attributing + names to identifiers and provides functions that can print explanations + for these conflict in error messages *) +module Conflicts: sig + val exists: unit -> bool + (** [exists()] returns true if the current naming context renamed + an identifier to avoid a name collision *) + + type explanation = + { kind: namespace; + name:string; location:Location.t} + + val take: unit -> explanation list + val pp: Format.formatter -> explanation list -> unit + val print: Format.formatter -> unit + val reset: unit -> unit +end + + val reset: unit -> unit val mark_loops: type_expr -> unit val reset_and_mark_loops: type_expr -> unit @@ -59,6 +105,7 @@ val tree_of_module: Ident.t -> ?ellipsis:bool -> module_type -> rec_status -> out_sig_item val modtype: formatter -> module_type -> unit val signature: formatter -> signature -> unit +val tree_of_modtype: module_type -> out_module_type val tree_of_modtype_declaration: Ident.t -> modtype_declaration -> out_sig_item val tree_of_signature: Types.signature -> out_sig_item list @@ -74,16 +121,17 @@ val cltype_declaration: Ident.t -> formatter -> class_type_declaration -> unit val type_expansion: type_expr -> Format.formatter -> type_expr -> unit val prepare_expansion: type_expr * type_expr -> type_expr * type_expr val trace: - bool -> bool-> string -> formatter -> (type_expr * type_expr) list -> unit + bool -> bool-> string -> formatter + -> (type_expr * type_expr) Ctype.Unification_trace.elt list -> unit val report_unification_error: - formatter -> Env.t -> ?unif:bool -> - (type_expr * type_expr) list -> + formatter -> Env.t -> + Ctype.Unification_trace.t -> ?type_expected_explanation:(formatter -> unit) -> (formatter -> unit) -> (formatter -> unit) -> unit val report_subtyping_error: - formatter -> Env.t -> (type_expr * type_expr) list -> - string -> (type_expr * type_expr) list -> unit + formatter -> Env.t -> Ctype.Unification_trace.t -> string + -> Ctype.Unification_trace.t -> unit val report_ambiguous_type_error: formatter -> Env.t -> (Path.t * Path.t) -> (Path.t * Path.t) list -> (formatter -> unit) -> (formatter -> unit) -> (formatter -> unit) -> unit @@ -92,7 +140,10 @@ val report_ambiguous_type_error: val print_items: (Env.t -> signature_item -> 'a option) -> Env.t -> signature_item list -> (out_sig_item * 'a option) list -(* Simple heuristic to rewrite Foo__bar.* as Foo.Bar.* when Foo.Bar is an alias for - Foo__bar. This pattern is used by the stdlib. *) +(* Simple heuristic to rewrite Foo__bar.* as Foo.Bar.* when Foo.Bar is an alias + for Foo__bar. This pattern is used by the stdlib. *) val rewrite_double_underscore_paths: Env.t -> Path.t -> Path.t +(** [printed_signature sourcefile ppf sg] print the signature [sg] of + [sourcefile] with potential warnings for name collisions *) +val printed_signature: string -> formatter -> signature -> unit diff --git a/typing/printtyped.ml b/typing/printtyped.ml index 1d06ad9b..60eed58c 100644 --- a/typing/printtyped.ml +++ b/typing/printtyped.ml @@ -46,7 +46,7 @@ let fmt_ident = Ident.print let rec fmt_path_aux f x = match x with | Path.Pident (s) -> fprintf f "%a" fmt_ident s; - | Path.Pdot (y, s, _pos) -> fprintf f "%a.%s" fmt_path_aux y s; + | Path.Pdot (y, s) -> fprintf f "%a.%s" fmt_path_aux y s; | Path.Papply (y, z) -> fprintf f "%a(%a)" fmt_path_aux y fmt_path_aux z; ;; @@ -152,16 +152,18 @@ let record_representation i ppf = let open Types in function | Record_float -> line i ppf "Record_float\n" | Record_unboxed b -> line i ppf "Record_unboxed %b\n" b | Record_inlined i -> line i ppf "Record_inlined %d\n" i - | Record_extension -> line i ppf "Record_extension\n" + | Record_extension p -> line i ppf "Record_extension %a\n" fmt_path p + +let attribute i ppf k a = + line i ppf "%s \"%s\"\n" k a.Parsetree.attr_name.txt; + Printast.payload i ppf a.Parsetree.attr_payload let attributes i ppf l = let i = i + 1 in - List.iter - (fun (s, arg) -> - line i ppf "attribute \"%s\"\n" s.txt; - Printast.payload (i + 1) ppf arg; - ) - l + List.iter (fun a -> + line i ppf "attribute \"%s\"\n" a.Parsetree.attr_name.txt; + Printast.payload (i + 1) ppf a.Parsetree.attr_payload + ) l let rec core_type i ppf x = line i ppf "core_type %a\n" fmt_location x.ctyp_loc; @@ -188,10 +190,11 @@ let rec core_type i ppf x = | Ttyp_object (l, c) -> line i ppf "Ttyp_object %a\n" fmt_closed_flag c; let i = i + 1 in - List.iter (function - | OTtag (s, attrs, t) -> + List.iter (fun {of_desc; of_attributes; _} -> + match of_desc with + | OTtag (s, t) -> line i ppf "method %s\n" s.txt; - attributes i ppf attrs; + attributes i ppf of_attributes; core_type (i + 1) ppf t | OTinherit ct -> line i ppf "OTinherit\n"; @@ -267,6 +270,9 @@ and pattern i ppf x = | Tpat_lazy p -> line i ppf "Tpat_lazy\n"; pattern i ppf p; + | Tpat_exception p -> + line i ppf "Tpat_exception\n"; + pattern i ppf p; and expression_extra i ppf x attrs = match x with @@ -279,9 +285,6 @@ and expression_extra i ppf x attrs = attributes i ppf attrs; option i core_type ppf cto1; core_type i ppf cto2; - | Texp_open (ovf, m, _, _) -> - line i ppf "Texp_open %a \"%a\"\n" fmt_override_flag ovf fmt_path m; - attributes i ppf attrs; | Texp_poly cto -> line i ppf "Texp_poly\n"; attributes i ppf attrs; @@ -314,11 +317,10 @@ and expression i ppf x = line i ppf "Texp_apply\n"; expression i ppf e; list i label_x_expression ppf l; - | Texp_match (e, l1, l2, _partial) -> + | Texp_match (e, l, _partial) -> line i ppf "Texp_match\n"; expression i ppf e; - list i case ppf l1; - list i case ppf l2; + list i case ppf l; | Texp_try (e, l) -> line i ppf "Texp_try\n"; expression i ppf e; @@ -386,7 +388,7 @@ and expression i ppf x = | Texp_override (_, l) -> line i ppf "Texp_override\n"; list i string_x_expression ppf l; - | Texp_letmodule (s, _, me, e) -> + | Texp_letmodule (s, _, _, me, e) -> line i ppf "Texp_letmodule \"%a\"\n" fmt_ident s; module_expr i ppf me; expression i ppf e; @@ -406,10 +408,21 @@ and expression i ppf x = | Texp_pack me -> line i ppf "Texp_pack"; module_expr i ppf me + | Texp_letop {let_; ands; param = _; body; partial = _} -> + line i ppf "Texp_letop"; + binding_op (i+1) ppf let_; + list (i+1) binding_op ppf ands; + case i ppf body | Texp_unreachable -> line i ppf "Texp_unreachable" | Texp_extension_constructor (li, _) -> line i ppf "Texp_extension_constructor %a" fmt_longident li + | Texp_open (o, e) -> + line i ppf "Texp_open %a\n" + fmt_override_flag o.open_override; + module_expr i ppf o.open_expr; + attributes i ppf o.open_attributes; + expression i ppf e; and value_description i ppf x = line i ppf "value_description %a %a\n" fmt_ident x.val_id fmt_location @@ -418,6 +431,11 @@ and value_description i ppf x = core_type (i+1) ppf x.val_desc; list (i+1) string ppf x.val_prim; +and binding_op i ppf x = + line i ppf "binding_op %a %a\n" fmt_path x.bop_op_path + fmt_location x.bop_loc; + expression i ppf x.bop_exp + and type_parameter i ppf (x, _variance) = core_type i ppf x and type_declaration i ppf x = @@ -459,6 +477,14 @@ and type_extension i ppf x = list (i+1) extension_constructor ppf x.tyext_constructors; line i ppf "ptyext_private = %a\n" fmt_private_flag x.tyext_private; +and type_exception i ppf x = + line i ppf "type_exception\n"; + attributes i ppf x.tyexn_attributes; + let i = i+1 in + line i ppf "ptyext_constructor =\n"; + let i = i+1 in + extension_constructor i ppf x.tyexn_constructor + and extension_constructor i ppf x = line i ppf "extension_constructor %a\n" fmt_location x.ext_loc; attributes i ppf x.ext_attributes; @@ -493,8 +519,10 @@ and class_type i ppf x = arg_label i ppf l; core_type i ppf co; class_type i ppf cl; - | Tcty_open (ovf, m, _, _, e) -> - line i ppf "Tcty_open %a \"%a\"\n" fmt_override_flag ovf fmt_path m; + | Tcty_open (o, e) -> + line i ppf "Tcty_open %a %a\n" + fmt_override_flag o.open_override + fmt_path (fst o.open_expr); class_type i ppf e and class_signature i ppf { csig_self = ct; csig_fields = l } = @@ -522,9 +550,8 @@ and class_type_field i ppf x = line i ppf "Tctf_constraint\n"; core_type (i+1) ppf ct1; core_type (i+1) ppf ct2; - | Tctf_attribute (s, arg) -> - line i ppf "Tctf_attribute \"%s\"\n" s.txt; - Printast.payload i ppf arg + | Tctf_attribute a -> + attribute i ppf "Tctf_attribute" a and class_description i ppf x = line i ppf "class_description %a\n" fmt_location x.ci_loc; @@ -570,15 +597,17 @@ and class_expr i ppf x = | Tcl_let (rf, l1, l2, ce) -> line i ppf "Tcl_let %a\n" fmt_rec_flag rf; list i value_binding ppf l1; - list i ident_x_loc_x_expression_def ppf l2; + list i ident_x_expression_def ppf l2; class_expr i ppf ce; | Tcl_constraint (ce, Some ct, _, _, _) -> line i ppf "Tcl_constraint\n"; class_expr i ppf ce; class_type i ppf ct | Tcl_constraint (ce, None, _, _, _) -> class_expr i ppf ce - | Tcl_open (ovf, m, _, _, e) -> - line i ppf "Tcty_open %a \"%a\"\n" fmt_override_flag ovf fmt_path m; + | Tcl_open (o, e) -> + line i ppf "Tcl_open %a %a\n" + fmt_override_flag o.open_override + fmt_path (fst o.open_expr); class_expr i ppf e and class_structure i ppf { cstr_self = p; cstr_fields = l } = @@ -608,9 +637,8 @@ and class_field i ppf x = | Tcf_initializer (e) -> line i ppf "Tcf_initializer\n"; expression (i+1) ppf e; - | Tcf_attribute (s, arg) -> - line i ppf "Tcf_attribute \"%s\"\n" s.txt; - Printast.payload i ppf arg + | Tcf_attribute a -> + attribute i ppf "Tcf_attribute" a and class_field_kind i ppf = function | Tcfk_concrete (o, e) -> @@ -664,16 +692,23 @@ and signature_item i ppf x = | Tsig_type (rf, l) -> line i ppf "Tsig_type %a\n" fmt_rec_flag rf; list i type_declaration ppf l; + | Tsig_typesubst l -> + line i ppf "Tsig_typesubst\n"; + list i type_declaration ppf l; | Tsig_typext e -> line i ppf "Tsig_typext\n"; type_extension i ppf e; | Tsig_exception ext -> line i ppf "Tsig_exception\n"; - extension_constructor i ppf ext + type_exception i ppf ext | Tsig_module md -> line i ppf "Tsig_module \"%a\"\n" fmt_ident md.md_id; attributes i ppf md.md_attributes; module_type i ppf md.md_type + | Tsig_modsubst ms -> + line i ppf "Tsig_modsubst \"%a\" = %a\n" + fmt_ident ms.ms_id fmt_path ms.ms_manifest; + attributes i ppf ms.ms_attributes; | Tsig_recmodule decls -> line i ppf "Tsig_recmodule\n"; list i module_declaration ppf decls; @@ -683,8 +718,8 @@ and signature_item i ppf x = modtype_declaration i ppf x.mtd_type | Tsig_open od -> line i ppf "Tsig_open %a %a\n" - fmt_override_flag od.open_override - fmt_path od.open_path; + fmt_override_flag od.open_override + fmt_path (fst od.open_expr); attributes i ppf od.open_attributes | Tsig_include incl -> line i ppf "Tsig_include\n"; @@ -696,9 +731,8 @@ and signature_item i ppf x = | Tsig_class_type (l) -> line i ppf "Tsig_class_type\n"; list i class_type_declaration ppf l; - | Tsig_attribute (s, arg) -> - line i ppf "Tsig_attribute \"%s\"\n" s.txt; - Printast.payload i ppf arg + | Tsig_attribute a -> + attribute i ppf "Tsig_attribute" a and module_declaration i ppf md = line i ppf "%a" fmt_ident md.md_id; @@ -775,7 +809,7 @@ and structure_item i ppf x = type_extension i ppf te | Tstr_exception ext -> line i ppf "Tstr_exception\n"; - extension_constructor i ppf ext; + type_exception i ppf ext; | Tstr_module x -> line i ppf "Tstr_module\n"; module_binding i ppf x @@ -787,9 +821,9 @@ and structure_item i ppf x = attributes i ppf x.mtd_attributes; modtype_declaration i ppf x.mtd_type | Tstr_open od -> - line i ppf "Tstr_open %a %a\n" - fmt_override_flag od.open_override - fmt_path od.open_path; + line i ppf "Tstr_open %a\n" + fmt_override_flag od.open_override; + module_expr i ppf od.open_expr; attributes i ppf od.open_attributes | Tstr_class (l) -> line i ppf "Tstr_class\n"; @@ -801,9 +835,8 @@ and structure_item i ppf x = line i ppf "Tstr_include"; attributes i ppf incl.incl_attributes; module_expr i ppf incl.incl_mod; - | Tstr_attribute (s, arg) -> - line i ppf "Tstr_attribute \"%s\"\n" s.txt; - Printast.payload i ppf arg + | Tstr_attribute a -> + attribute i ppf "Tstr_attribute" a and longident_x_with_constraint i ppf (li, _, wc) = line i ppf "%a\n" fmt_path li; @@ -869,15 +902,15 @@ and label_x_expression i ppf (l, e) = arg_label (i+1) ppf l; (match e with None -> () | Some e -> expression (i+1) ppf e) -and ident_x_loc_x_expression_def i ppf (l,_, e) = +and ident_x_expression_def i ppf (l, e) = line i ppf " \"%a\"\n" fmt_ident l; expression (i+1) ppf e; and label_x_bool_x_core_type_list i ppf x = - match x with - Ttag (l, attrs, b, ctl) -> + match x.rf_desc with + | Ttag (l, b, ctl) -> line i ppf "Ttag \"%s\" %s\n" l.txt (string_of_bool b); - attributes (i+1) ppf attrs; + attributes (i+1) ppf x.rf_attributes; list (i+1) core_type ppf ctl | Tinherit (ct) -> line i ppf "Tinherit\n"; diff --git a/typing/rec_check.ml b/typing/rec_check.ml new file mode 100644 index 00000000..e3ffec6c --- /dev/null +++ b/typing/rec_check.ml @@ -0,0 +1,1244 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jeremy Yallop, University of Cambridge *) +(* Gabriel Scherer, Project Parsifal, INRIA Saclay *) +(* Alban Reynaud, ENS Lyon *) +(* *) +(* Copyright 2017 Jeremy Yallop *) +(* Copyright 2018 Alban Reynaud *) +(* Copyright 2018 INRIA *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** Static checking of recursive declarations + +Some recursive definitions are meaningful +{[ + let rec factorial = function 0 -> 1 | n -> n * factorial (n - 1) + let rec infinite_list = 0 :: infinite_list +]} +but some other are meaningless +{[ + let rec x = x + let rec x = x+1 +|} + +Intuitively, a recursive definition makes sense when the body of the +definition can be evaluated without fully knowing what the recursive +name is yet. + +In the [factorial] example, the name [factorial] refers to a function, +evaluating the function definition [function ...] can be done +immediately and will not force a recursive call to [factorial] -- this +will only happen later, when [factorial] is called with an argument. + +In the [infinite_list] example, we can evaluate [0 :: infinite_list] +without knowing the full content of [infinite_list], but with just its +address. This is a case of productive/guarded recursion. + +On the contrary, [let rec x = x] is unguarded recursion (the meaning +is undetermined), and [let rec x = x+1] would need the value of [x] +while evaluating its definition [x+1]. + +This file implements a static check to decide which definitions are +known to be meaningful, and which may be meaningless. In the general +case, we handle a set of mutually-recursive definitions +{[ +let rec x1 = e1 +and x2 = e2 +... +and xn = en +]} + + +Our check (see function [is_valid_recursive_expression] is defined +using two criteria: + +Usage of recursive variables: how does each of the [e1 .. en] use the + recursive variables [x1 .. xn]? + +Static or dynamic size: for which of the [ei] can we compute the + in-memory size of the value without evaluating [ei] (so that we can + pre-allocate it, and thus know its final address before evaluation). + +The "static or dynamic size" is decided by the classify_* functions below. + +The "variable usage" question is decided by a static analysis looking +very much like a type system. The idea is to assign "access modes" to +variables, where an "access mode" [m] is defined as either + + m ::= Ignore (* the value is not used at all *) + | Delay (* the value is not needed at definition time *) + | Guard (* the value is stored under a data constructor *) + | Return (* the value result is directly returned *) + | Dereference (* full access and inspection of the value *) + +The access modes of an expression [e] are represented by a "context" +[G], which is simply a mapping from variables (the variables used in +[e]) to access modes. + +The core notion of the static check is a type-system-like judgment of +the form [G |- e : m], which can be interpreted as meaning either of: + +- If we are allowed to use the variables of [e] at the modes in [G] + (but not more), then it is safe to use [e] at the mode [m]. + +- If we want to use [e] at the mode [m], then its variables are + used at the modes in [G]. + +In practice, for a given expression [e], our implementation takes the +desired mode of use [m] as *input*, and returns a context [G] as +*output*, which is (uniquely determined as) the most permissive choice +of modes [G] for the variables of [e] such that [G |- e : m] holds. +*) + +open Asttypes +open Typedtree +open Types + +exception Illegal_expr + +(** {1 Static or dynamic size} *) + +type sd = Static | Dynamic + +let is_ref : Types.value_description -> bool = function + | { Types.val_kind = + Types.Val_prim { Primitive.prim_name = "%makemutable"; + prim_arity = 1 } } -> + true + | _ -> false + +(* See the note on abstracted arguments in the documentation for + Typedtree.Texp_apply *) +let is_abstracted_arg : arg_label * expression option -> bool = function + | (_, None) -> true + | (_, Some _) -> false + +let classify_expression : Typedtree.expression -> sd = + (* We need to keep track of the size of expressions + bound by local declarations, to be able to predict + the size of variables. Compare: + + let rec r = + let y = fun () -> r () + in y + + and + + let rec r = + let y = if Random.bool () then ignore else fun () -> r () + in y + + In both cases the final address of `r` must be known before `y` is compiled, + and this is only possible if `r` has a statically-known size. + + The first definition can be allowed (`y` has a statically-known + size) but the second one is unsound (`y` has no statically-known size). + *) + let rec classify_expression env e = match e.exp_desc with + (* binding and variable cases *) + | Texp_let (rec_flag, vb, e) -> + let env = classify_value_bindings rec_flag env vb in + classify_expression env e + | Texp_ident (path, _, _) -> + classify_path env path + + (* non-binding cases *) + | Texp_open (_, e) + | Texp_letmodule (_, _, _, _, e) + | Texp_sequence (_, e) + | Texp_letexception (_, e) -> + classify_expression env e + + | Texp_construct (_, {cstr_tag = Cstr_unboxed}, [e]) -> + classify_expression env e + | Texp_construct _ -> + Static + + | Texp_record { representation = Record_unboxed _; + fields = [| _, Overridden (_,e) |] } -> + classify_expression env e + | Texp_record _ -> + Static + + | Texp_apply ({exp_desc = Texp_ident (_, _, vd)}, _) + when is_ref vd -> + Static + | Texp_apply (_,args) + when List.exists is_abstracted_arg args -> + Static + | Texp_apply _ -> + Dynamic + + | Texp_for _ + | Texp_constant _ + | Texp_new _ + | Texp_instvar _ + | Texp_tuple _ + | Texp_array _ + | Texp_variant _ + | Texp_setfield _ + | Texp_while _ + | Texp_setinstvar _ + | Texp_pack _ + | Texp_object _ + | Texp_function _ + | Texp_lazy _ + | Texp_unreachable + | Texp_extension_constructor _ -> + Static + + | Texp_match _ + | Texp_ifthenelse _ + | Texp_send _ + | Texp_field _ + | Texp_assert _ + | Texp_try _ + | Texp_override _ + | Texp_letop _ -> + Dynamic + and classify_value_bindings rec_flag env bindings = + (* We use a non-recursive classification, classifying each + binding with respect to the old environment + (before all definitions), even if the bindings are recursive. + + Note: computing a fixpoint in some way would be more + precise, as the following could be allowed: + + let rec topdef = + let rec x = y and y = fun () -> topdef () + in x + *) + ignore rec_flag; + let old_env = env in + let add_value_binding env vb = + match vb.vb_pat.pat_desc with + | Tpat_var (id, _loc) -> + let size = classify_expression old_env vb.vb_expr in + Ident.add id size env + | _ -> + (* Note: we don't try to compute any size for complex patterns *) + env + in + List.fold_left add_value_binding env bindings + and classify_path env = function + | Path.Pident x -> + begin + try Ident.find_same x env + with Not_found -> + (* an identifier will be missing from the map if either: + - it is a non-local identifier + (bound outside the letrec-binding we are analyzing) + - or it is bound by a complex (let p = e in ...) local binding + - or it is bound within a module (let module M = ... in ...) + that we are not traversing for size computation + + For non-local identifiers it might be reasonable (although + not completely clear) to consider them Static (they have + already been evaluated), but for the others we must + under-approximate with Dynamic. + + This could be fixed by a more complete implementation. + *) + Dynamic + end + | Path.Pdot _ | Path.Papply _ -> + (* local modules could have such paths to local definitions; + classify_expression could be extend to compute module + shapes more precisely *) + Dynamic + in classify_expression Ident.empty + + +(** {1 Usage of recursive variables} *) + +module Mode = struct + (** For an expression in a program, its "usage mode" represents + static information about how the value produced by the expression + will be used by the context around it. *) + type t = + | Ignore + (** [Ignore] is for subexpressions that are not used at all during + the evaluation of the whole program. This is the mode of + a variable in an expression in which it does not occur. *) + + | Delay + (** A [Delay] context can be fully evaluated without evaluating its argument + , which will only be needed at a later point of program execution. For + example, [fun x -> ?] or [lazy ?] are [Delay] contexts. *) + + | Guard + (** A [Guard] context returns the value as a member of a data structure, + for example a variant constructor or record. The value can safely be + defined mutually-recursively with their context, for example in + [let rec li = 1 :: li]. + When these subexpressions participate in a cyclic definition, + this definition is productive/guarded. + + The [Guard] mode is also used when a value is not dereferenced, + it is returned by a sub-expression, but the result of this + sub-expression is discarded instead of being returned. + For example, the subterm [?] is in a [Guard] context + in [let _ = ? in e] and in [?; e]. + When these subexpressions participate in a cyclic definition, + they cannot create a self-loop. + *) + + | Return + (** A [Return] context returns its value without further inspection. + This value cannot be defined mutually-recursively with its context, + as there is a risk of self-loop: in [let rec x = y and y = x], the + two definitions use a single variable in [Return] context. *) + + | Dereference + (** A [Dereference] context consumes, inspects and uses the value + in arbitrary ways. Such a value must be fully defined at the point + of usage, it cannot be defined mutually-recursively with its context. *) + + let equal = ((=) : t -> t -> bool) + + (* Lower-ranked modes demand/use less of the variable/expression they qualify + -- so they allow more recursive definitions. + + Ignore < Delay < Guard < Return < Dereference + *) + let rank = function + | Ignore -> 0 + | Delay -> 1 + | Guard -> 2 + | Return -> 3 + | Dereference -> 4 + + (* Returns the more conservative (highest-ranking) mode of the two + arguments. + + In judgments we write (m + m') for (join m m'). + *) + let join m m' = + if rank m >= rank m' then m else m' + + (* If x is used with the mode m in e[x], and e[x] is used with mode + m' in e'[e[x]], then x is used with mode m'[m] (our notation for + "compose m' m") in e'[e[x]]. + + Return is neutral for composition: m[Return] = m = Return[m]. + + Composition is associative and [Ignore] is a zero/annihilator for + it: (compose Ignore m) and (compose m Ignore) are both Ignore. *) + let compose m' m = match m', m with + | Ignore, _ | _, Ignore -> Ignore + | Dereference, _ -> Dereference + | Delay, _ -> Delay + | Guard, Return -> Guard + | Guard, ((Dereference | Guard | Delay) as m) -> m + | Return, Return -> Return + | Return, ((Dereference | Guard | Delay) as m) -> m +end + +type mode = Mode.t = Ignore | Delay | Guard | Return | Dereference + +module Env : +sig + type t + + val single : Ident.t -> Mode.t -> t + (** Create an environment with a single identifier used with a given mode. + *) + + val empty : t + (** An environment with no used identifiers. *) + + val find : Ident.t -> t -> Mode.t + (** Find the mode of an identifier in an environment. The default mode is + Ignore. *) + + val unguarded : t -> Ident.t list -> Ident.t list + (** unguarded e l: the list of all identifiers in l that are dereferenced or + returned in the environment e. *) + + val dependent : t -> Ident.t list -> Ident.t list + (** dependent e l: the list of all identifiers in l that are used in e + (not ignored). *) + + val join : t -> t -> t + val join_list : t list -> t + (** Environments can be joined pointwise (variable per variable) *) + + val compose : Mode.t -> t -> t + (** Environment composition m[G] extends mode composition m1[m2] + by composing each mode in G pointwise *) + + val remove : Ident.t -> t -> t + (** Remove an identifier from an environment. *) + + val take: Ident.t -> t -> Mode.t * t + (** Remove an identifier from an environment, and return its mode *) + + val remove_list : Ident.t list -> t -> t + (** Remove all the identifiers of a list from an environment. *) + + val equal : t -> t -> bool +end = struct + module M = Map.Make(Ident) + + (** A "t" maps each rec-bound variable to an access status *) + type t = Mode.t M.t + + let equal = M.equal Mode.equal + + let find (id: Ident.t) (tbl: t) = + try M.find id tbl with Not_found -> Ignore + + let empty = M.empty + + let join (x: t) (y: t) = + M.fold + (fun (id: Ident.t) (v: Mode.t) (tbl: t) -> + let v' = find id tbl in + M.add id (Mode.join v v') tbl) + x y + + let join_list li = List.fold_left join empty li + + let compose m env = + M.map (Mode.compose m) env + + let single id mode = M.add id mode empty + + let unguarded env li = + List.filter (fun id -> Mode.rank (find id env) > Mode.rank Guard) li + + let dependent env li = + List.filter (fun id -> Mode.rank (find id env) > Mode.rank Ignore) li + + let remove = M.remove + + let take id env = (find id env, remove id env) + + let remove_list l env = + List.fold_left (fun env id -> M.remove id env) env l +end + +let remove_pat pat env = + Env.remove_list (pat_bound_idents pat) env + +let remove_patlist pats env = + List.fold_right remove_pat pats env + +(* Usage mode judgments. + + There are two main groups of judgment functions: + + - Judgments of the form "G |- ... : m" + compute the environment G of a subterm ... from its mode m, so + the corresponding function has type [... -> Mode.t -> Env.t]. + + We write [... -> term_judg] in this case. + + - Judgments of the form "G |- ... : m -| G'" + + correspond to binding constructs (for example "let x = e" in the + term "let x = e in body") that have both an exterior environment + G (the environment of the whole term "let x = e in body") and an + interior environment G' (the environment at the "in", after the + binding construct has introduced new names in scope). + + For example, let-binding could be given the following rule: + + G |- e : m + m' + ----------------------------------- + G+G' |- (let x = e) : m -| x:m', G' + + Checking the whole term composes this judgment + with the "G |- e : m" form for the let body: + + G |- (let x = e) : m -| G' + G' |- body : m + ------------------------------- + G |- let x = e in body : m + + To this judgment "G |- e : m -| G'" our implementation gives the + type [... -> Mode.t -> Env.t -> Env.t]: it takes the mode and + interior environment as inputs, and returns the exterior + environment. + + We write [... -> bind_judg] in this case. +*) +type term_judg = Mode.t -> Env.t +type bind_judg = Mode.t -> Env.t -> Env.t + +let option : 'a. ('a -> term_judg) -> 'a option -> term_judg = + fun f o m -> match o with + | None -> Env.empty + | Some v -> f v m +let list : 'a. ('a -> term_judg) -> 'a list -> term_judg = + fun f li m -> + List.fold_left (fun env item -> Env.join env (f item m)) Env.empty li +let array : 'a. ('a -> term_judg) -> 'a array -> term_judg = + fun f ar m -> + Array.fold_left (fun env item -> Env.join env (f item m)) Env.empty ar + +let single : Ident.t -> term_judg = Env.single +let remove_id : Ident.t -> term_judg -> term_judg = + fun id f m -> Env.remove id (f m) +let remove_ids : Ident.t list -> term_judg -> term_judg = + fun ids f m -> Env.remove_list ids (f m) + +let join : term_judg list -> term_judg = + fun li m -> Env.join_list (List.map (fun f -> f m) li) + +let empty = fun _ -> Env.empty + +(* A judgment [judg] takes a mode from the context as input, and + returns an environment. The judgment [judg << m], given a mode [m'] + from the context, evaluates [judg] in the composed mode [m'[m]]. *) +let (<<) : term_judg -> Mode.t -> term_judg = + fun f inner_mode -> fun outer_mode -> f (Mode.compose outer_mode inner_mode) + +(* A binding judgment [binder] expects a mode and an inner environment, + and returns an outer environment. [binder >> judg] computes + the inner environment as the environment returned by [judg] + in the ambient mode. *) +let (>>) : bind_judg -> term_judg -> term_judg = + fun binder term mode -> binder mode (term mode) + +(* Expression judgment: + G |- e : m + where (m) is an input of the code and (G) is an output; + in the Prolog mode notation, this is (+G |- -e : -m). +*) +let rec expression : Typedtree.expression -> term_judg = + fun exp -> match exp.exp_desc with + | Texp_ident (pth, _, _) -> + path pth + | Texp_let (rec_flag, bindings, body) -> + (* + G |- : m -| G' + G' |- body : m + ------------------------------- + G |- let in body : m + *) + value_bindings rec_flag bindings >> expression body + | Texp_letmodule (x, _, _, mexp, e) -> + module_binding (x, mexp) >> expression e + | Texp_match (e, cases, _) -> + (* + (Gi; mi |- pi -> ei : m)^i + G |- e : sum(mi)^i + ---------------------------------------------- + G + sum(Gi)^i |- match e with (pi -> ei)^i : m + *) + (fun mode -> + let pat_envs, pat_modes = + List.split (List.map (fun c -> case c mode) cases) in + let env_e = expression e (List.fold_left Mode.join Ignore pat_modes) in + Env.join_list (env_e :: pat_envs)) + | Texp_for (_, _, low, high, _, body) -> + (* + G1 |- low: m[Dereference] + G2 |- high: m[Dereference] + G3 |- body: m[Guard] + --- + G1 + G2 + G3 |- for _ = low to high do body done: m + *) + join [ + expression low << Dereference; + expression high << Dereference; + expression body << Guard; + ] + | Texp_constant _ -> + empty + | Texp_new (pth, _, _) -> + (* + G |- c: m[Dereference] + ----------------------- + G |- new c: m + *) + path pth << Dereference + | Texp_instvar (self_path, pth, _inst_var) -> + join [path self_path << Dereference; path pth] + | Texp_apply ({exp_desc = Texp_ident (_, _, vd)}, [_, Some arg]) + when is_ref vd -> + (* + G |- e: m[Guard] + ------------------ + G |- ref e: m + *) + expression arg << Guard + | Texp_apply (e, args) -> + let arg (_, eo) = option expression eo in + let app_mode = if List.exists is_abstracted_arg args + then (* see the comment on Texp_apply in typedtree.mli; + the non-abstracted arguments are bound to local + variables, which corresponds to a Guard mode. *) + Guard + else Dereference + in + join [expression e; list arg args] << app_mode + | Texp_tuple exprs -> + list expression exprs << Guard + | Texp_array exprs -> + let array_mode = match Typeopt.array_kind exp with + | Lambda.Pfloatarray -> + (* (flat) float arrays unbox their elements *) + Dereference + | Lambda.Pgenarray -> + (* This is counted as a use, because constructing a generic array + involves inspecting to decide whether to unbox (PR#6939). *) + Dereference + | Lambda.Paddrarray | Lambda.Pintarray -> + (* non-generic, non-float arrays act as constructors *) + Guard + in + list expression exprs << array_mode + | Texp_construct (_, desc, exprs) -> + let access_constructor = + match desc.cstr_tag with + | Cstr_extension (pth, _) -> + path pth << Dereference + | _ -> empty + in + let m' = match desc.cstr_tag with + | Cstr_unboxed -> + Return + | Cstr_constant _ | Cstr_block _ | Cstr_extension _ -> + Guard + in + join [ + access_constructor; + list expression exprs << m' + ] + | Texp_variant (_, eo) -> + (* + G |- e: m[Guard] + ------------------ ----------- + G |- `A e: m [] |- `A: m + *) + option expression eo << Guard + | Texp_record { fields = es; extended_expression = eo; + representation = rep } -> + let field_mode = match rep with + | Record_float -> Dereference + | Record_unboxed _ -> Return + | Record_regular | Record_inlined _ + | Record_extension _ -> Guard + in + let field (_label, field_def) = match field_def with + Kept _ -> empty + | Overridden (_, e) -> expression e + in + join [ + array field es << field_mode; + option expression eo << Dereference + ] + | Texp_ifthenelse (cond, ifso, ifnot) -> + (* + Gc |- c: m[Dereference] + G1 |- e1: m + G2 |- e2: m + --- + Gc + G1 + G2 |- if c then e1 else e2: m + + Note: `if c then e1 else e2` is treated in the same way as + `match c with true -> e1 | false -> e2` + *) + join [ + expression cond << Dereference; + expression ifso; + option expression ifnot; + ] + | Texp_setfield (e1, _, _, e2) -> + (* + G1 |- e1: m[Dereference] + G2 |- e2: m[Dereference] + --- + G1 + G2 |- e1.x <- e2: m + + Note: e2 is dereferenced in the case of a field assignment to + a record of unboxed floats in that case, e2 evaluates to + a boxed float and it is unboxed on assignment. + *) + join [ + expression e1 << Dereference; + expression e2 << Dereference; + ] + | Texp_sequence (e1, e2) -> + (* + G1 |- e1: m[Guard] + G2 |- e2: m + -------------------- + G1 + G2 |- e1; e2: m + + Note: `e1; e2` is treated in the same way as `let _ = e1 in e2` + *) + join [ + expression e1 << Guard; + expression e2; + ] + | Texp_while (cond, body) -> + (* + G1 |- cond: m[Dereference] + G2 |- body: m[Guard] + --------------------------------- + G1 + G2 |- while cond do body done: m + *) + join [ + expression cond << Dereference; + expression body << Guard; + ] + | Texp_send (e1, _, eo) -> + (* + G |- e: m[Dereference] + ---------------------- (plus weird 'eo' option) + G |- e#x: m + *) + join [ + expression e1 << Dereference; + option expression eo << Dereference; + ] + | Texp_field (e, _, _) -> + (* + G |- e: m[Dereference] + ----------------------- + G |- e.x: m + *) + expression e << Dereference + | Texp_setinstvar (pth,_,_,e) -> + (* + G |- e: m[Dereference] + ---------------------- + G |- x <- e: m + *) + join [ + path pth << Dereference; + expression e << Dereference; + ] + | Texp_letexception ({ext_id}, e) -> + (* G |- e: m + ---------------------------- + G |- let exception A in e: m + *) + remove_id ext_id (expression e) + | Texp_assert e -> + (* + G |- e: m[Dereference] + ----------------------- + G |- assert e: m + + Note: `assert e` is treated just as if `assert` was a function. + *) + expression e << Dereference + | Texp_pack mexp -> + (* + G |- M: m + ---------------- + G |- module M: m + *) + modexp mexp + | Texp_object (clsstrct, _) -> + class_structure clsstrct + | Texp_try (e, cases) -> + (* + G |- e: m (Gi; _ |- pi -> ei : m)^i + -------------------------------------------- + G + sum(Gi)^i |- try e with (pi -> ei)^i : m + + Contrarily to match, the patterns p do not inspect + the value of e, so their mode does not influence the + mode of e. + *) + let case_env c m = fst (case c m) in + join [ + expression e; + list case_env cases; + ] + | Texp_override (pth, fields) -> + (* + G |- pth : m (Gi |- ei : m[Derefence])^i + ---------------------------------------------------- + G + sum(Gi)^i |- {< (xi = ei)^i >} (at path pth) : m + + Note: {< .. >} is desugared to a function application, but + the function implementation might still use its arguments in + a guarded way only -- intuitively it should behave as a constructor. + We could possibly refine the arguments' Dereference into Guard here. + *) + let field (_, _, arg) = expression arg in + join [ + path pth << Dereference; + list field fields << Dereference; + ] + | Texp_function { cases } -> + (* + (Gi; _ |- pi -> ei : m[Delay])^i + -------------------------------------- + sum(Gi)^i |- function (pi -> ei)^i : m + + Contrarily to match, the value that is pattern-matched + is bound locally, so the pattern modes do not influence + the final environment. + *) + let case_env c m = fst (case c m) in + list case_env cases << Delay + | Texp_lazy e -> + (* + G |- e: m[Delay] + ---------------- (modulo some subtle compiler optimizations) + G |- lazy e: m + *) + let lazy_mode = match Typeopt.classify_lazy_argument e with + | `Constant_or_function + | `Identifier _ + | `Float_that_cannot_be_shortcut -> + Return + | `Other -> + Delay + in + expression e << lazy_mode + | Texp_letop{let_; ands; body; _} -> + let case_env c m = fst (case c m) in + join [ + list binding_op (let_ :: ands) << Dereference; + case_env body << Delay + ] + | Texp_unreachable -> + (* + ---------- + [] |- .: m + *) + empty + | Texp_extension_constructor (_lid, pth) -> + path pth << Dereference + | Texp_open (od, e) -> + open_declaration od >> expression e + +and binding_op : Typedtree.binding_op -> term_judg = + fun bop -> + join [path bop.bop_op_path; expression bop.bop_exp] + +and class_structure : Typedtree.class_structure -> term_judg = + fun cs -> list class_field cs.cstr_fields + +and class_field : Typedtree.class_field -> term_judg = + fun cf -> match cf.cf_desc with + | Tcf_inherit (_, ce, _super, _inh_vars, _inh_meths) -> + class_expr ce << Dereference + | Tcf_val (_lab, _mut, _, cfk, _) -> + class_field_kind cfk + | Tcf_method (_, _, cfk) -> + class_field_kind cfk + | Tcf_constraint _ -> + empty + | Tcf_initializer e -> + expression e << Dereference + | Tcf_attribute _ -> + empty + +and class_field_kind : Typedtree.class_field_kind -> term_judg = + fun cfk -> match cfk with + | Tcfk_virtual _ -> + empty + | Tcfk_concrete (_, e) -> + expression e << Dereference + +and modexp : Typedtree.module_expr -> term_judg = + fun mexp -> match mexp.mod_desc with + | Tmod_ident (pth, _) -> + path pth + | Tmod_structure s -> + structure s + | Tmod_functor (_, _, _, e) -> + modexp e << Delay + | Tmod_apply (f, p, _) -> + join [ + modexp f << Dereference; + modexp p << Dereference; + ] + | Tmod_constraint (mexp, _, _, coe) -> + let rec coercion coe k = match coe with + | Tcoerce_none -> + k Return + | Tcoerce_structure _ + | Tcoerce_functor _ -> + (* These coercions perform a shallow copy of the input module, + by creating a new module with fields obtained by accessing + the same fields in the input module. *) + k Dereference + | Tcoerce_primitive _ -> + (* This corresponds to 'external' declarations, + and the coercion ignores its argument *) + k Ignore + | Tcoerce_alias (_, pth, coe) -> + (* Alias coercions ignore their arguments, but they evaluate + their alias module 'pth' under another coercion. *) + coercion coe (fun m -> path pth << m) + in + coercion coe (fun m -> modexp mexp << m) + | Tmod_unpack (e, _) -> + expression e + + +(* G |- pth : m *) +and path : Path.t -> term_judg = + (* + ------------ + x: m |- x: m + + G |- A: m[Dereference] + ----------------------- + G |- A.x: m + + G1 |- A: m[Dereference] + G2 |- B: m[Dereference] + ------------------------ (as for term application) + G1 + G2 |- A(B): m + *) + fun pth -> match pth with + | Path.Pident x -> + single x + | Path.Pdot (t, _) -> + path t << Dereference + | Path.Papply (f, p) -> + join [ + path f << Dereference; + path p << Dereference; + ] + +(* G |- struct ... end : m *) +and structure : Typedtree.structure -> term_judg = + (* + G1, {x: _, x in vars(G1)} |- item1: G2 + ... + Gn in m + G2, {x: _, x in vars(G2)} |- item2: G3 + ... + Gn in m + ... + Gn, {x: _, x in vars(Gn)} |- itemn: [] in m + --- + (G1 + ... + Gn) - V |- struct item1 ... itemn end: m + *) + fun s m -> + List.fold_right (fun it env -> structure_item it m env) + s.str_items Env.empty + +(* G |- : m -| G' + where G is an output and m, G' are inputs *) +and structure_item : Typedtree.structure_item -> bind_judg = + fun s m env -> match s.str_desc with + | Tstr_eval (e, _) -> + (* + Ge |- e: m[Guard] + G |- items: m -| G' + --------------------------------- + Ge + G |- (e;; items): m -| G' + + The expression `e` is treated in the same way as let _ = e + *) + let judg_e = expression e << Guard in + Env.join (judg_e m) env + | Tstr_value (rec_flag, bindings) -> + value_bindings rec_flag bindings m env + | Tstr_module {mb_id; mb_expr} -> + module_binding (mb_id, mb_expr) m env + | Tstr_recmodule mbs -> + let bindings = List.map (fun {mb_id; mb_expr} -> (mb_id, mb_expr)) mbs in + recursive_module_bindings bindings m env + | Tstr_primitive _ -> + env + | Tstr_type _ -> + (* + ------------------- + G |- type t: m -| G + *) + env + | Tstr_typext {tyext_constructors = exts; _} -> + let ext_ids = List.map (fun {ext_id = id; _} -> id) exts in + Env.join + (list extension_constructor exts m) + (Env.remove_list ext_ids env) + | Tstr_exception {tyexn_constructor = ext; _} -> + Env.join + (extension_constructor ext m) + (Env.remove ext.ext_id env) + | Tstr_modtype _ + | Tstr_class_type _ + | Tstr_attribute _ -> + env + | Tstr_open od -> + open_declaration od m env + | Tstr_class classes -> + let class_ids = + let class_id ({ci_id_class = id; _}, _) = id in + List.map class_id classes in + let class_declaration ({ci_expr; _}, _) m = + Env.remove_list class_ids (class_expr ci_expr m) in + Env.join + (list class_declaration classes m) + (Env.remove_list class_ids env) + | Tstr_include { incl_mod = mexp; incl_type = mty; _ } -> + let included_ids = List.map Types.signature_item_id mty in + Env.join (modexp mexp m) (Env.remove_list included_ids env) + +(* G |- module M = E : m -| G *) +and module_binding : (Ident.t * Typedtree.module_expr) -> bind_judg = + fun (id, mexp) m env -> + (* + GE |- E: m[mM + Guard] + ------------------------------------- + GE + G |- module M = E : m -| M:mM, G + *) + let mM, env = Env.take id env in + let judg_E = modexp mexp << (Mode.join mM Guard) in + Env.join (judg_E m) env + +and open_declaration : Typedtree.open_declaration -> bind_judg = + fun { open_expr = mexp; open_bound_items = sg; _ } m env -> + let judg_E = modexp mexp in + let bound_ids = List.map Types.signature_item_id sg in + Env.join (judg_E m) (Env.remove_list bound_ids env) + +and recursive_module_bindings + : (Ident.t * Typedtree.module_expr) list -> bind_judg = + fun m_bindings m env -> + let mids = List.map fst m_bindings in + let binding (mid, mexp) m = + let mM = Env.find mid env in + Env.remove_list mids (modexp mexp Mode.(compose m (join mM Guard))) + in + Env.join (list binding m_bindings m) (Env.remove_list mids env) + +and class_expr : Typedtree.class_expr -> term_judg = + fun ce -> match ce.cl_desc with + | Tcl_ident (pth, _, _) -> + path pth << Dereference + | Tcl_structure cs -> + class_structure cs + | Tcl_fun (_, _, args, ce, _) -> + let ids = List.map fst args in + remove_ids ids (class_expr ce << Delay) + | Tcl_apply (ce, args) -> + let arg (_label, eo) = option expression eo in + join [ + class_expr ce << Dereference; + list arg args << Dereference; + ] + | Tcl_let (rec_flag, bindings, _, ce) -> + value_bindings rec_flag bindings >> class_expr ce + | Tcl_constraint (ce, _, _, _, _) -> + class_expr ce + | Tcl_open (_, ce) -> + class_expr ce + +and extension_constructor : Typedtree.extension_constructor -> term_judg = + fun ec -> match ec.ext_kind with + | Text_decl _ -> + empty + | Text_rebind (pth, _lid) -> + path pth + +(* G |- let (rec?) (pi = ei)^i : m -| G' *) +and value_bindings : rec_flag -> Typedtree.value_binding list -> bind_judg = + fun rec_flag bindings mode bound_env -> + let all_bound_pats = List.map (fun vb -> vb.vb_pat) bindings in + let outer_env = remove_patlist all_bound_pats bound_env in + let bindings_env = + match rec_flag with + | Nonrecursive -> + (* + (Gi, pi:_ |- ei : m[mbody_i])^i (pi : mbody_i -| D)^i + ------------------------------------------------------------ + Sum(Gi) + (D - (pi)^i) |- let (pi=ei)^i : m -| D + *) + let binding_env {vb_pat; vb_expr; _} m = + let m' = Mode.compose m (pattern vb_pat bound_env) in + remove_pat vb_pat (expression vb_expr m') in + list binding_env bindings mode + | Recursive -> + (* + (Gi, (xj : mdef_ij)^j |- ei : m[mbody_i])^i (xi : mbody_i -| D)^i + G'i = Gi + mdef_ij[G'j] + ------------------------------------------------------------------- + Sum(G'i) + (D - (pi)^i) |- let rec (xi=ei)^i : m -| D + + The (mdef_ij)^i,j are a family of modes over two indices: + mdef_ij represents the mode of use, within e_i the definition of x_i, + of the mutually-recursive variable x_j. + + The (G'i)^i are defined from the (Gi)^i as a family of equations, + whose smallest solution is computed as a least fixpoint. + + The (Gi)^i are the "immediate" dependencies of each (ei)^i + on the outer context (excluding the mutually-defined + variables). + The (G'i)^i contain the "transitive" dependencies as well: + if ei depends on xj, then the dependencies of G'i of xi + must contain the dependencies of G'j, composed by + the mode mdef_ij of use of xj in ei. + + For example, consider: + + let rec z = + let rec x = ref y + and y = ref z + in f x + + this definition should be rejected as the body [f x] + dereferences [x], which can be used to access the + yet-unitialized value [z]. This requires realizing that [x] + depends on [z] through [y], which requires the transitive + closure computation. + + An earlier version of our check would take only the (Gi)^i + instead of the (G'i)^i, which is incorrect and would accept + the example above. + *) + (* [binding_env] takes a binding (x_i = e_i) + and computes (Gi, (mdef_ij)^j). *) + let binding_env {vb_pat = x_i; vb_expr = e_i; _} = + let mbody_i = pattern x_i bound_env in + (* Gi, (x_j:mdef_ij)^j *) + let rhs_env_i = expression e_i (Mode.compose mode mbody_i) in + (* (mdef_ij)^j (for a fixed i) *) + let mutual_modes = + let mdef_ij {vb_pat = x_j; _} = pattern x_j rhs_env_i in + List.map mdef_ij bindings in + (* Gi *) + let env_i = remove_patlist all_bound_pats rhs_env_i in + (* (Gi, (mdef_ij)^j) *) + (env_i, mutual_modes) in + let env, mdef = + List.split (List.map binding_env bindings) in + let rec transitive_closure env = + let transitive_deps env_i mdef_i = + (* Gi, (mdef_ij)^j => Gi + Sum_j mdef_ij[Gj] *) + Env.join env_i + (Env.join_list (List.map2 Env.compose mdef_i env)) in + let env' = List.map2 transitive_deps env mdef in + if List.for_all2 Env.equal env env' + then env' + else transitive_closure env' + in + let env'_i = transitive_closure env in + Env.join_list env'_i + in Env.join bindings_env outer_env + +(* G; m' |- (p -> e) : m + with outputs G, m' and input m + + m' is the mode under which the scrutinee of p + (the value matched against p) is placed. +*) +and case : Typedtree.case -> mode -> Env.t * mode = + fun { Typedtree.c_lhs; c_guard; c_rhs } -> + (* + Ge |- e : m Gg |- g : m[Dereference] + G := Ge+Gg p : mp -| G + ---------------------------------------- + G - p; m[mp] |- (p (when g)? -> e) : m + *) + let judg = join [ + option expression c_guard << Dereference; + expression c_rhs; + ] in + (fun m -> + let env = judg m in + (remove_pat c_lhs env), Mode.compose m (pattern c_lhs env)) + +(* p : m -| G + with output m and input G + + m is the mode under which the scrutinee of p is placed. +*) +and pattern : pattern -> Env.t -> mode = fun pat env -> + (* + mp := | Dereference if p is destructuring + | Guard otherwise + me := sum{G(x), x in vars(p)} + -------------------------------------------- + p : (mp + me) -| G + *) + let m_pat = if is_destructuring_pattern pat + then Dereference + else Guard + in + let m_env = + pat_bound_idents pat + |> List.map (fun id -> Env.find id env) + |> List.fold_left Mode.join Ignore + in + Mode.join m_pat m_env + +and is_destructuring_pattern : Typedtree.pattern -> bool = + fun pat -> match pat.pat_desc with + | Tpat_any -> false + | Tpat_var (_, _) -> false + | Tpat_alias (pat, _, _) -> is_destructuring_pattern pat + | Tpat_constant _ -> true + | Tpat_tuple _ -> true + | Tpat_construct (_, _, _) -> true + | Tpat_variant _ -> true + | Tpat_record (_, _) -> true + | Tpat_array _ -> true + | Tpat_or (l,r,_) -> + is_destructuring_pattern l || is_destructuring_pattern r + | Tpat_lazy _ -> true + | Tpat_exception _ -> false + +let is_valid_recursive_expression idlist expr = + let ty = expression expr Return in + match Env.unguarded ty idlist, Env.dependent ty idlist, + classify_expression expr with + | _ :: _, _, _ (* The expression inspects rec-bound variables *) + | [], _ :: _, Dynamic -> (* The expression depends on rec-bound variables + and its size is unknown *) + false + | [], _, Static (* The expression has known size *) + | [], [], Dynamic -> (* The expression has unknown size, + but does not depend on rec-bound variables *) + true + +(* A class declaration may contain let-bindings. If they are recursive, + their validity will already be checked by [is_valid_recursive_expression] + during type-checking. This function here prevents a different kind of + invalid recursion, which is the unsafe creations of objects of this class + in the let-binding. For example, + {|class a = let x = new a in object ... end|} + is forbidden, but + {|class a = let x () = new a in object ... end|} + is allowed. +*) +let is_valid_class_expr idlist ce = + let rec class_expr : mode -> Typedtree.class_expr -> Env.t = + fun mode ce -> match ce.cl_desc with + | Tcl_ident (_, _, _) -> + (* + ---------- + [] |- a: m + *) + Env.empty + | Tcl_structure _ -> + (* + ----------------------- + [] |- struct ... end: m + *) + Env.empty + | Tcl_fun (_, _, _, _, _) -> Env.empty + (* + --------------------------- + [] |- fun x1 ... xn -> C: m + *) + | Tcl_apply (_, _) -> Env.empty + | Tcl_let (rec_flag, bindings, _, ce) -> + value_bindings rec_flag bindings mode (class_expr mode ce) + | Tcl_constraint (ce, _, _, _, _) -> + class_expr mode ce + | Tcl_open (_, ce) -> + class_expr mode ce + in + match Env.unguarded (class_expr Return ce) idlist with + | [] -> true + | _ :: _ -> false diff --git a/typing/rec_check.mli b/typing/rec_check.mli new file mode 100644 index 00000000..aa5c1ca3 --- /dev/null +++ b/typing/rec_check.mli @@ -0,0 +1,19 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jeremy Yallop, University of Cambridge *) +(* *) +(* Copyright 2017 Jeremy Yallop *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +exception Illegal_expr + +val is_valid_recursive_expression : Ident.t list -> Typedtree.expression -> bool + +val is_valid_class_expr : Ident.t list -> Typedtree.class_expr -> bool diff --git a/typing/stypes.ml b/typing/stypes.ml index 5615037a..5e6ef97d 100644 --- a/typing/stypes.ml +++ b/typing/stypes.ml @@ -27,7 +27,7 @@ open Lexing;; open Location;; open Typedtree;; -let output_int oc i = output_string oc (string_of_int i) +let output_int oc i = output_string oc (Int.to_string i) type annotation = | Ti_pat of pattern diff --git a/typing/subst.ml b/typing/subst.ml index 5ac528e1..bddea430 100644 --- a/typing/subst.ml +++ b/typing/subst.ml @@ -24,32 +24,30 @@ type type_replacement = | Path of Path.t | Type_function of { params : type_expr list; body : type_expr } -module PathMap = Map.Make(Path) - type t = - { types: type_replacement PathMap.t; - modules: Path.t PathMap.t; - modtypes: (Ident.t, module_type) Tbl.t; + { types: type_replacement Path.Map.t; + modules: Path.t Path.Map.t; + modtypes: module_type Ident.Map.t; for_saving: bool; } let identity = - { types = PathMap.empty; - modules = PathMap.empty; - modtypes = Tbl.empty; + { types = Path.Map.empty; + modules = Path.Map.empty; + modtypes = Ident.Map.empty; for_saving = false; } -let add_type_path id p s = { s with types = PathMap.add id (Path p) s.types } +let add_type_path id p s = { s with types = Path.Map.add id (Path p) s.types } let add_type id p s = add_type_path (Pident id) p s let add_type_function id ~params ~body s = - { s with types = PathMap.add id (Type_function { params; body }) s.types } + { s with types = Path.Map.add id (Type_function { params; body }) s.types } -let add_module_path id p s = { s with modules = PathMap.add id p s.modules } +let add_module_path id p s = { s with modules = Path.Map.add id p s.modules } let add_module id p s = add_module_path (Pident id) p s -let add_modtype id ty s = { s with modtypes = Tbl.add id ty s.modtypes } +let add_modtype id ty s = { s with modtypes = Ident.Map.add id ty s.modtypes } let for_saving s = { s with for_saving = true } @@ -61,10 +59,10 @@ let remove_loc = {default_mapper with location = (fun _this _loc -> Location.none)} let is_not_doc = function - | ({Location.txt = "ocaml.doc"}, _) -> false - | ({Location.txt = "ocaml.text"}, _) -> false - | ({Location.txt = "doc"}, _) -> false - | ({Location.txt = "text"}, _) -> false + | {Parsetree.attr_name = {Location.txt = "ocaml.doc"}; _} -> false + | {Parsetree.attr_name = {Location.txt = "ocaml.text"}; _} -> false + | {Parsetree.attr_name = {Location.txt = "doc"}; _} -> false + | {Parsetree.attr_name = {Location.txt = "text"}; _} -> false | _ -> true let attrs s x = @@ -78,48 +76,48 @@ let attrs s x = else x let rec module_path s path = - try PathMap.find path s.modules + try Path.Map.find path s.modules with Not_found -> match path with | Pident _ -> path - | Pdot(p, n, pos) -> - Pdot(module_path s p, n, pos) + | Pdot(p, n) -> + Pdot(module_path s p, n) | Papply(p1, p2) -> Papply(module_path s p1, module_path s p2) let modtype_path s = function Pident id as p -> begin try - match Tbl.find id s.modtypes with + match Ident.Map.find id s.modtypes with | Mty_ident p -> p | _ -> fatal_error "Subst.modtype_path" with Not_found -> p end - | Pdot(p, n, pos) -> - Pdot(module_path s p, n, pos) + | Pdot(p, n) -> + Pdot(module_path s p, n) | Papply _ -> fatal_error "Subst.modtype_path" let type_path s path = - match PathMap.find path s.types with + match Path.Map.find path s.types with | Path p -> p | Type_function _ -> assert false | exception Not_found -> match path with | Pident _ -> path - | Pdot(p, n, pos) -> - Pdot(module_path s p, n, pos) + | Pdot(p, n) -> + Pdot(module_path s p, n) | Papply _ -> fatal_error "Subst.type_path" let type_path s p = match Path.constructor_typath p with | Regular p -> type_path s p - | Cstr (ty_path, cstr) -> Pdot(type_path s ty_path, cstr, nopos) + | Cstr (ty_path, cstr) -> Pdot(type_path s ty_path, cstr) | LocalExt _ -> type_path s p - | Ext (p, cstr) -> Pdot(module_path s p, cstr, nopos) + | Ext (p, cstr) -> Pdot(module_path s p, cstr) let to_subst_by_type_function s p = - match PathMap.find p s.types with + match Path.Map.find p s.types with | Path _ -> false | Type_function _ -> true | exception Not_found -> false @@ -131,7 +129,7 @@ let reset_for_saving () = new_id := -1 let newpersty desc = decr new_id; - { desc = desc; level = generic_level; scope = None; id = !new_id } + { desc; level = generic_level; scope = Btype.lowest_level; id = !new_id } (* ensure that all occurrences of 'Tvar None' are physically shared *) let tvar_none = Tvar None @@ -144,7 +142,7 @@ let norm = function let ctype_apply_env_empty = ref (fun _ -> assert false) (* Similar to [Ctype.nondep_type_rec]. *) -let rec typexp s ty = +let rec typexp copy_scope s ty = let ty = repr ty in match ty.desc with Tvar _ | Tunivar _ as desc -> @@ -153,7 +151,9 @@ let rec typexp s ty = if s.for_saving then newpersty (norm desc) else newty2 ty.level desc in - save_desc ty desc; ty.desc <- Tsubst ty'; ty' + For_copy.save_desc copy_scope ty desc; + ty.desc <- Tsubst ty'; + ty' else ty | Tsubst ty -> ty @@ -167,7 +167,7 @@ let rec typexp s ty = *) | _ -> let desc = ty.desc in - save_desc ty desc; + For_copy.save_desc copy_scope ty desc; let tm = row_of_type ty in let has_fixed_row = not (is_Tconstr ty) && is_constr_row ~allow_ident:false tm in @@ -177,29 +177,32 @@ let rec typexp s ty = ty'.desc <- begin if has_fixed_row then match tm.desc with (* PR#7348 *) - Tconstr (Pdot(m,i,pos), tl, _abbrev) -> + Tconstr (Pdot(m,i), tl, _abbrev) -> let i' = String.sub i 0 (String.length i - 4) in - Tconstr(type_path s (Pdot(m,i',pos)), tl, ref Mnil) + Tconstr(type_path s (Pdot(m,i')), tl, ref Mnil) | _ -> assert false else match desc with | Tconstr (p, args, _abbrev) -> - let args = List.map (typexp s) args in - begin match PathMap.find p s.types with + let args = List.map (typexp copy_scope s) args in + begin match Path.Map.find p s.types with | exception Not_found -> Tconstr(type_path s p, args, ref Mnil) | Path _ -> Tconstr(type_path s p, args, ref Mnil) | Type_function { params; body } -> (!ctype_apply_env_empty params body args).desc end | Tpackage(p, n, tl) -> - Tpackage(modtype_path s p, n, List.map (typexp s) tl) + Tpackage(modtype_path s p, n, List.map (typexp copy_scope s) tl) | Tobject (t1, name) -> - Tobject (typexp s t1, - ref (match !name with - None -> None - | Some (p, tl) -> - if to_subst_by_type_function s p - then None - else Some (type_path s p, List.map (typexp s) tl))) + let t1' = typexp copy_scope s t1 in + let name' = + match !name with + | None -> None + | Some (p, tl) -> + if to_subst_by_type_function s p + then None + else Some (type_path s p, List.map (typexp copy_scope s) tl) + in + Tobject (t1', ref name') | Tvariant row -> let row = row_repr row in let more = repr row.row_more in @@ -218,9 +221,9 @@ let rec typexp s ty = let more' = match more.desc with Tsubst ty -> ty - | Tconstr _ | Tnil -> typexp s more + | Tconstr _ | Tnil -> typexp copy_scope s more | Tunivar _ | Tvar _ -> - save_desc more more.desc; + For_copy.save_desc copy_scope more more.desc; if s.for_saving then newpersty (norm more.desc) else if dup && is_Tvar more then newgenty more.desc else more | _ -> assert false @@ -229,7 +232,7 @@ let rec typexp s ty = more.desc <- Tsubst(newgenty(Ttuple[more';ty'])); (* Return a new copy *) let row = - copy_row (typexp s) true row (not dup) more' in + copy_row (typexp copy_scope s) true row (not dup) more' in match row.row_name with | Some (p, tl) -> Tvariant {row with row_name = @@ -240,8 +243,8 @@ let rec typexp s ty = Tvariant row end | Tfield(_label, kind, _t1, t2) when field_kind_repr kind = Fabsent -> - Tlink (typexp s t2) - | _ -> copy_type_desc (typexp s) desc + Tlink (typexp copy_scope s t2) + | _ -> copy_type_desc (typexp copy_scope s) desc end; ty' @@ -250,234 +253,277 @@ let rec typexp s ty = might not be correct. *) let type_expr s ty = - let ty' = typexp s ty in - cleanup_types (); - ty' + For_copy.with_scope (fun copy_scope -> typexp copy_scope s ty) -let label_declaration s l = +let label_declaration copy_scope s l = { ld_id = l.ld_id; ld_mutable = l.ld_mutable; - ld_type = typexp s l.ld_type; + ld_type = typexp copy_scope s l.ld_type; ld_loc = loc s l.ld_loc; ld_attributes = attrs s l.ld_attributes; } -let constructor_arguments s = function +let constructor_arguments copy_scope s = function | Cstr_tuple l -> - Cstr_tuple (List.map (typexp s) l) + Cstr_tuple (List.map (typexp copy_scope s) l) | Cstr_record l -> - Cstr_record (List.map (label_declaration s) l) + Cstr_record (List.map (label_declaration copy_scope s) l) -let constructor_declaration s c = +let constructor_declaration copy_scope s c = { cd_id = c.cd_id; - cd_args = constructor_arguments s c.cd_args; - cd_res = may_map (typexp s) c.cd_res; + cd_args = constructor_arguments copy_scope s c.cd_args; + cd_res = may_map (typexp copy_scope s) c.cd_res; cd_loc = loc s c.cd_loc; cd_attributes = attrs s c.cd_attributes; } +let type_declaration' copy_scope s decl = + { type_params = List.map (typexp copy_scope s) decl.type_params; + type_arity = decl.type_arity; + type_kind = + begin match decl.type_kind with + Type_abstract -> Type_abstract + | Type_variant cstrs -> + Type_variant (List.map (constructor_declaration copy_scope s) cstrs) + | Type_record(lbls, rep) -> + Type_record (List.map (label_declaration copy_scope s) lbls, rep) + | Type_open -> Type_open + end; + type_manifest = + begin + match decl.type_manifest with + None -> None + | Some ty -> Some(typexp copy_scope s ty) + end; + type_private = decl.type_private; + type_variance = decl.type_variance; + type_is_newtype = false; + type_expansion_scope = Btype.lowest_level; + type_loc = loc s decl.type_loc; + type_attributes = attrs s decl.type_attributes; + type_immediate = decl.type_immediate; + type_unboxed = decl.type_unboxed; + } + let type_declaration s decl = - let decl = - { type_params = List.map (typexp s) decl.type_params; - type_arity = decl.type_arity; - type_kind = - begin match decl.type_kind with - Type_abstract -> Type_abstract - | Type_variant cstrs -> - Type_variant (List.map (constructor_declaration s) cstrs) - | Type_record(lbls, rep) -> - Type_record (List.map (label_declaration s) lbls, rep) - | Type_open -> Type_open - end; - type_manifest = - begin - match decl.type_manifest with - None -> None - | Some ty -> Some(typexp s ty) - end; - type_private = decl.type_private; - type_variance = decl.type_variance; - type_newtype_level = None; - type_loc = loc s decl.type_loc; - type_attributes = attrs s decl.type_attributes; - type_immediate = decl.type_immediate; - type_unboxed = decl.type_unboxed; - } - in - cleanup_types (); - decl + For_copy.with_scope (fun copy_scope -> type_declaration' copy_scope s decl) -let class_signature s sign = - { csig_self = typexp s sign.csig_self; +let class_signature copy_scope s sign = + { csig_self = typexp copy_scope s sign.csig_self; csig_vars = - Vars.map (function (m, v, t) -> (m, v, typexp s t)) sign.csig_vars; + Vars.map + (function (m, v, t) -> (m, v, typexp copy_scope s t)) sign.csig_vars; csig_concr = sign.csig_concr; csig_inher = - List.map (fun (p, tl) -> (type_path s p, List.map (typexp s) tl)) + List.map + (fun (p, tl) -> (type_path s p, List.map (typexp copy_scope s) tl)) sign.csig_inher; } -let rec class_type s = - function - Cty_constr (p, tyl, cty) -> - Cty_constr (type_path s p, List.map (typexp s) tyl, class_type s cty) +let rec class_type copy_scope s = function + | Cty_constr (p, tyl, cty) -> + let p' = type_path s p in + let tyl' = List.map (typexp copy_scope s) tyl in + let cty' = class_type copy_scope s cty in + Cty_constr (p', tyl', cty') | Cty_signature sign -> - Cty_signature (class_signature s sign) + Cty_signature (class_signature copy_scope s sign) | Cty_arrow (l, ty, cty) -> - Cty_arrow (l, typexp s ty, class_type s cty) + Cty_arrow (l, typexp copy_scope s ty, class_type copy_scope s cty) + +let class_declaration' copy_scope s decl = + { cty_params = List.map (typexp copy_scope s) decl.cty_params; + cty_variance = decl.cty_variance; + cty_type = class_type copy_scope s decl.cty_type; + cty_path = type_path s decl.cty_path; + cty_new = + begin match decl.cty_new with + | None -> None + | Some ty -> Some (typexp copy_scope s ty) + end; + cty_loc = loc s decl.cty_loc; + cty_attributes = attrs s decl.cty_attributes; + } let class_declaration s decl = - let decl = - { cty_params = List.map (typexp s) decl.cty_params; - cty_variance = decl.cty_variance; - cty_type = class_type s decl.cty_type; - cty_path = type_path s decl.cty_path; - cty_new = - begin match decl.cty_new with - None -> None - | Some ty -> Some (typexp s ty) - end; - cty_loc = loc s decl.cty_loc; - cty_attributes = attrs s decl.cty_attributes; - } - in - (* Do not clean up if saving: next is cltype_declaration *) - if not s.for_saving then cleanup_types (); - decl + For_copy.with_scope (fun copy_scope -> class_declaration' copy_scope s decl) + +let cltype_declaration' copy_scope s decl = + { clty_params = List.map (typexp copy_scope s) decl.clty_params; + clty_variance = decl.clty_variance; + clty_type = class_type copy_scope s decl.clty_type; + clty_path = type_path s decl.clty_path; + clty_loc = loc s decl.clty_loc; + clty_attributes = attrs s decl.clty_attributes; + } let cltype_declaration s decl = - let decl = - { clty_params = List.map (typexp s) decl.clty_params; - clty_variance = decl.clty_variance; - clty_type = class_type s decl.clty_type; - clty_path = type_path s decl.clty_path; - clty_loc = loc s decl.clty_loc; - clty_attributes = attrs s decl.clty_attributes; - } - in - (* Do clean up even if saving: type_declaration may be recursive *) - cleanup_types (); - decl + For_copy.with_scope (fun copy_scope -> cltype_declaration' copy_scope s decl) let class_type s cty = - let cty = class_type s cty in - cleanup_types (); - cty + For_copy.with_scope (fun copy_scope -> class_type copy_scope s cty) -let value_description s descr = - { val_type = type_expr s descr.val_type; +let value_description' copy_scope s descr = + { val_type = typexp copy_scope s descr.val_type; val_kind = descr.val_kind; val_loc = loc s descr.val_loc; val_attributes = attrs s descr.val_attributes; } +let value_description s descr = + For_copy.with_scope (fun copy_scope -> value_description' copy_scope s descr) + +let extension_constructor' copy_scope s ext = + { ext_type_path = type_path s ext.ext_type_path; + ext_type_params = List.map (typexp copy_scope s) ext.ext_type_params; + ext_args = constructor_arguments copy_scope s ext.ext_args; + ext_ret_type = may_map (typexp copy_scope s) ext.ext_ret_type; + ext_private = ext.ext_private; + ext_attributes = attrs s ext.ext_attributes; + ext_loc = if s.for_saving then Location.none else ext.ext_loc; } + let extension_constructor s ext = - let ext = - { ext_type_path = type_path s ext.ext_type_path; - ext_type_params = List.map (typexp s) ext.ext_type_params; - ext_args = constructor_arguments s ext.ext_args; - ext_ret_type = may_map (typexp s) ext.ext_ret_type; - ext_private = ext.ext_private; - ext_attributes = attrs s ext.ext_attributes; - ext_loc = if s.for_saving then Location.none else ext.ext_loc; } + For_copy.with_scope + (fun copy_scope -> extension_constructor' copy_scope s ext) + +type scoping = + | Keep + | Make_local + | Rescope of int + +let rename_bound_idents scoping s sg = + let rename = + let open Ident in + match scoping with + | Keep -> (fun id -> create_scoped ~scope:(scope id) (name id)) + | Make_local -> Ident.rename + | Rescope scope -> (fun id -> create_scoped ~scope (name id)) in - cleanup_types (); - ext - -let rec rename_bound_idents s idents = function - [] -> (List.rev idents, s) - | Sig_type(id, _, _) :: sg -> - let id' = Ident.rename id in - rename_bound_idents (add_type id (Pident id') s) (id' :: idents) sg - | Sig_module(id, _, _) :: sg -> - let id' = Ident.rename id in - rename_bound_idents (add_module id (Pident id') s) (id' :: idents) sg - | Sig_modtype(id, _) :: sg -> - let id' = Ident.rename id in - rename_bound_idents (add_modtype id (Mty_ident(Pident id')) s) - (id' :: idents) sg - | (Sig_class(id, _, _) | Sig_class_type(id, _, _)) :: sg -> - (* cheat and pretend they are types cf. PR#6650 *) - let id' = Ident.rename id in - rename_bound_idents (add_type id (Pident id') s) (id' :: idents) sg - | (Sig_value(id, _) | Sig_typext(id, _, _)) :: sg -> - let id' = Ident.rename id in - rename_bound_idents s (id' :: idents) sg + let rec rename_bound_idents s sg = function + | [] -> sg, s + | Sig_type(id, td, rs, vis) :: rest -> + let id' = rename id in + rename_bound_idents + (add_type id (Pident id') s) + (Sig_type(id', td, rs, vis) :: sg) + rest + | Sig_module(id, pres, md, rs, vis) :: rest -> + let id' = rename id in + rename_bound_idents + (add_module id (Pident id') s) + (Sig_module (id', pres, md, rs, vis) :: sg) + rest + | Sig_modtype(id, mtd, vis) :: rest -> + let id' = rename id in + rename_bound_idents + (add_modtype id (Mty_ident(Pident id')) s) + (Sig_modtype(id', mtd, vis) :: sg) + rest + | Sig_class(id, cd, rs, vis) :: rest -> + (* cheat and pretend they are types cf. PR#6650 *) + let id' = rename id in + rename_bound_idents + (add_type id (Pident id') s) + (Sig_class(id', cd, rs, vis) :: sg) + rest + | Sig_class_type(id, ctd, rs, vis) :: rest -> + (* cheat and pretend they are types cf. PR#6650 *) + let id' = rename id in + rename_bound_idents + (add_type id (Pident id') s) + (Sig_class_type(id', ctd, rs, vis) :: sg) + rest + | Sig_value(id, vd, vis) :: rest -> + (* scope doesn't matter for value identifiers. *) + let id' = Ident.rename id in + rename_bound_idents s (Sig_value(id', vd, vis) :: sg) rest + | Sig_typext(id, ec, es, vis) :: rest -> + let id' = rename id in + rename_bound_idents s (Sig_typext(id',ec,es,vis) :: sg) rest + in + rename_bound_idents s [] sg -let rec modtype s = function +let rec modtype scoping s = function Mty_ident p as mty -> begin match p with Pident id -> - begin try Tbl.find id s.modtypes with Not_found -> mty end - | Pdot(p, n, pos) -> - Mty_ident(Pdot(module_path s p, n, pos)) + begin try Ident.Map.find id s.modtypes with Not_found -> mty end + | Pdot(p, n) -> + Mty_ident(Pdot(module_path s p, n)) | Papply _ -> fatal_error "Subst.modtype" end | Mty_signature sg -> - Mty_signature(signature s sg) + Mty_signature(signature scoping s sg) | Mty_functor(id, arg, res) -> let id' = Ident.rename id in - Mty_functor(id', may_map (modtype s) arg, - modtype (add_module id (Pident id') s) res) - | Mty_alias(pres, p) -> - Mty_alias(pres, module_path s p) + Mty_functor(id', may_map (modtype scoping s) arg, + modtype scoping (add_module id (Pident id') s) res) + | Mty_alias p -> + Mty_alias (module_path s p) -and signature s sg = +and signature scoping s sg = (* Components of signature may be mutually recursive (e.g. type declarations or class and type declarations), so first build global renaming substitution... *) - let (new_idents, s') = rename_bound_idents s [] sg in + let (sg', s') = rename_bound_idents scoping s sg in (* ... then apply it to each signature component in turn *) - List.map2 (signature_component s') sg new_idents + For_copy.with_scope (fun copy_scope -> + List.rev_map (signature_item' copy_scope scoping s') sg' + ) + -and signature_component s comp newid = +and signature_item' copy_scope scoping s comp = match comp with - Sig_value(_id, d) -> - Sig_value(newid, value_description s d) - | Sig_type(_id, d, rs) -> - Sig_type(newid, type_declaration s d, rs) - | Sig_typext(_id, ext, es) -> - Sig_typext(newid, extension_constructor s ext, es) - | Sig_module(_id, d, rs) -> - Sig_module(newid, module_declaration s d, rs) - | Sig_modtype(_id, d) -> - Sig_modtype(newid, modtype_declaration s d) - | Sig_class(_id, d, rs) -> - Sig_class(newid, class_declaration s d, rs) - | Sig_class_type(_id, d, rs) -> - Sig_class_type(newid, cltype_declaration s d, rs) - -and module_declaration s decl = + Sig_value(id, d, vis) -> + Sig_value(id, value_description' copy_scope s d, vis) + | Sig_type(id, d, rs, vis) -> + Sig_type(id, type_declaration' copy_scope s d, rs, vis) + | Sig_typext(id, ext, es, vis) -> + Sig_typext(id, extension_constructor' copy_scope s ext, es, vis) + | Sig_module(id, pres, d, rs, vis) -> + Sig_module(id, pres, module_declaration scoping s d, rs, vis) + | Sig_modtype(id, d, vis) -> + Sig_modtype(id, modtype_declaration scoping s d, vis) + | Sig_class(id, d, rs, vis) -> + Sig_class(id, class_declaration' copy_scope s d, rs, vis) + | Sig_class_type(id, d, rs, vis) -> + Sig_class_type(id, cltype_declaration' copy_scope s d, rs, vis) + +and signature_item s comp = + For_copy.with_scope (fun copy_scope -> signature_item' copy_scope s comp) + +and module_declaration scoping s decl = { - md_type = modtype s decl.md_type; + md_type = modtype scoping s decl.md_type; md_attributes = attrs s decl.md_attributes; md_loc = loc s decl.md_loc; } -and modtype_declaration s decl = +and modtype_declaration scoping s decl = { - mtd_type = may_map (modtype s) decl.mtd_type; + mtd_type = may_map (modtype scoping s) decl.mtd_type; mtd_attributes = attrs s decl.mtd_attributes; mtd_loc = loc s decl.mtd_loc; } + (* For every binding k |-> d of m1, add k |-> f d to m2 and return resulting merged map. *) let merge_tbls f m1 m2 = - Tbl.fold (fun k d accu -> Tbl.add k (f d) accu) m1 m2 + Ident.Map.fold (fun k d accu -> Ident.Map.add k (f d) accu) m1 m2 let merge_path_maps f m1 m2 = - PathMap.fold (fun k d accu -> PathMap.add k (f d) accu) m1 m2 + Path.Map.fold (fun k d accu -> Path.Map.add k (f d) accu) m1 m2 let type_replacement s = function | Path p -> Path (type_path s p) | Type_function { params; body } -> - let params = List.map (typexp s) params in - let body = typexp s body in + let params = List.map (type_expr s) params in + let body = type_expr s body in Type_function { params; body } (* Composition of substitutions: @@ -486,6 +532,6 @@ let type_replacement s = function let compose s1 s2 = { types = merge_path_maps (type_replacement s2) s1.types s2.types; modules = merge_path_maps (module_path s2) s1.modules s2.modules; - modtypes = merge_tbls (modtype s2) s1.modtypes s2.modtypes; + modtypes = merge_tbls (modtype Keep s2) s1.modtypes s2.modtypes; for_saving = s1.for_saving || s2.for_saving; } diff --git a/typing/subst.mli b/typing/subst.mli index f81cb4da..f0b1a8be 100644 --- a/typing/subst.mli +++ b/typing/subst.mli @@ -54,12 +54,27 @@ val extension_constructor: t -> extension_constructor -> extension_constructor val class_declaration: t -> class_declaration -> class_declaration val cltype_declaration: t -> class_type_declaration -> class_type_declaration -val modtype: t -> module_type -> module_type -val signature: t -> signature -> signature -val modtype_declaration: t -> modtype_declaration -> modtype_declaration -val module_declaration: t -> module_declaration -> module_declaration -val typexp : t -> Types.type_expr -> Types.type_expr -val class_signature: t -> class_signature -> class_signature + +(* + When applied to a signature item, a substitution not only modifies the types + present in its declaration, but also refreshes the identifier of the item. + Effectively this creates new declarations, and so one should decide what the + scope of this new declaration should be. + + This is decided by the [scoping] argument passed to the following functions. +*) + +type scoping = + | Keep + | Make_local + | Rescope of int + +val modtype: scoping -> t -> module_type -> module_type +val signature: scoping -> t -> signature -> signature +val signature_item: scoping -> t -> signature_item -> signature_item +val modtype_declaration: + scoping -> t -> modtype_declaration -> modtype_declaration +val module_declaration: scoping -> t -> module_declaration -> module_declaration (* Composition of substitutions: apply (compose s1 s2) x = apply s2 (apply s1 x) *) diff --git a/typing/tast_mapper.ml b/typing/tast_mapper.ml index 36e33e3f..b4bd2ede 100644 --- a/typing/tast_mapper.ml +++ b/typing/tast_mapper.ml @@ -17,10 +17,11 @@ open Asttypes open Typedtree (* TODO: add 'methods' for location, attribute, extension, - open_description, include_declaration, include_description *) + include_declaration, include_description *) type mapper = { + binding_op: mapper -> binding_op -> binding_op; case: mapper -> case -> case; cases: mapper -> case list -> case list; class_declaration: mapper -> class_declaration -> class_declaration; @@ -40,6 +41,7 @@ type mapper = module_binding: mapper -> module_binding -> module_binding; module_coercion: mapper -> module_coercion -> module_coercion; module_declaration: mapper -> module_declaration -> module_declaration; + module_substitution: mapper -> module_substitution -> module_substitution; module_expr: mapper -> module_expr -> module_expr; module_type: mapper -> module_type -> module_type; module_type_declaration: @@ -48,15 +50,18 @@ type mapper = pat: mapper -> pattern -> pattern; row_field: mapper -> row_field -> row_field; object_field: mapper -> object_field -> object_field; + open_declaration: mapper -> open_declaration -> open_declaration; + open_description: mapper -> open_description -> open_description; signature: mapper -> signature -> signature; signature_item: mapper -> signature_item -> signature_item; structure: mapper -> structure -> structure; structure_item: mapper -> structure_item -> structure_item; typ: mapper -> core_type -> core_type; type_declaration: mapper -> type_declaration -> type_declaration; - type_declarations: mapper -> (rec_flag * type_declaration list) -> - (rec_flag * type_declaration list); + type_declarations: mapper -> (rec_flag * type_declaration list) + -> (rec_flag * type_declaration list); type_extension: mapper -> type_extension -> type_extension; + type_exception: mapper -> type_exception -> type_exception; type_kind: mapper -> type_kind -> type_kind; value_binding: mapper -> value_binding -> value_binding; value_bindings: mapper -> (rec_flag * value_binding list) -> @@ -70,6 +75,7 @@ let tuple2 f1 f2 (x, y) = (f1 x, f2 y) let tuple3 f1 f2 f3 (x, y, z) = (f1 x, f2 y, f3 z) let opt f = function None -> None | Some x -> Some (f x) + let structure sub {str_items; str_type; str_final_env} = { str_items = List.map (sub.structure_item sub) str_items; @@ -91,6 +97,8 @@ let module_declaration sub x = let md_type = sub.module_type sub x.md_type in {x with md_type} +let module_substitution _ x = x + let include_infos f x = {x with incl_mod = f x.incl_mod} let class_type_declaration sub x = @@ -112,7 +120,7 @@ let structure_item sub {str_desc; str_loc; str_env} = let (rec_flag, list) = sub.type_declarations sub (rec_flag, list) in Tstr_type (rec_flag, list) | Tstr_typext te -> Tstr_typext (sub.type_extension sub te) - | Tstr_exception ext -> Tstr_exception (sub.extension_constructor sub ext) + | Tstr_exception ext -> Tstr_exception (sub.type_exception sub ext) | Tstr_module mb -> Tstr_module (sub.module_binding sub mb) | Tstr_recmodule list -> Tstr_recmodule (List.map (sub.module_binding sub) list) @@ -125,7 +133,7 @@ let structure_item sub {str_desc; str_loc; str_env} = (List.map (tuple3 id id (sub.class_type_declaration sub)) list) | Tstr_include incl -> Tstr_include (include_infos (sub.module_expr sub) incl) - | Tstr_open _ + | Tstr_open od -> Tstr_open (sub.open_declaration sub od) | Tstr_attribute _ as d -> d in {str_desc; str_env; str_loc} @@ -174,6 +182,12 @@ let type_extension sub x = in {x with tyext_constructors; tyext_params} +let type_exception sub x = + let tyexn_constructor = + sub.extension_constructor sub x.tyexn_constructor + in + {x with tyexn_constructor} + let extension_constructor sub x = let ext_kind = match x.ext_kind with @@ -208,6 +222,7 @@ let pat sub x = Tpat_or (sub.pat sub p1, sub.pat sub p2, rd) | Tpat_alias (p, id, s) -> Tpat_alias (sub.pat sub p, id, s) | Tpat_lazy p -> Tpat_lazy (sub.pat sub p) + | Tpat_exception p -> Tpat_exception (sub.pat sub p) in {x with pat_extra; pat_desc; pat_env} @@ -217,8 +232,6 @@ let expr sub x = Texp_constraint (sub.typ sub cty) | Texp_coerce (cty1, cty2) -> Texp_coerce (opt (sub.typ sub) cty1, sub.typ sub cty2) - | Texp_open (ovf, path, loc, env) -> - Texp_open (ovf, path, loc, sub.env sub env) | Texp_newtype _ as d -> d | Texp_poly cto -> Texp_poly (opt (sub.typ sub) cto) in @@ -239,11 +252,10 @@ let expr sub x = sub.expr sub exp, List.map (tuple2 id (opt (sub.expr sub))) list ) - | Texp_match (exp, cases, exn_cases, p) -> + | Texp_match (exp, cases, p) -> Texp_match ( sub.expr sub exp, sub.cases sub cases, - sub.cases sub exn_cases, p ) | Texp_try (exp, cases) -> @@ -325,10 +337,11 @@ let expr sub x = path, List.map (tuple3 id id (sub.expr sub)) list ) - | Texp_letmodule (id, s, mexpr, exp) -> + | Texp_letmodule (id, s, pres, mexpr, exp) -> Texp_letmodule ( id, s, + pres, sub.module_expr sub mexpr, sub.expr sub exp ) @@ -345,10 +358,20 @@ let expr sub x = Texp_object (sub.class_structure sub cl, sl) | Texp_pack mexpr -> Texp_pack (sub.module_expr sub mexpr) + | Texp_letop {let_; ands; param; body; partial} -> + Texp_letop{ + let_ = sub.binding_op sub let_; + ands = List.map (sub.binding_op sub) ands; + param; + body = sub.case sub body; + partial; + } | Texp_unreachable -> Texp_unreachable | Texp_extension_constructor _ as e -> e + | Texp_open (od, e) -> + Texp_open (sub.open_declaration sub od, sub.expr sub e) in {x with exp_extra; exp_desc; exp_env} @@ -357,6 +380,9 @@ let package_type sub x = let pack_fields = List.map (tuple2 id (sub.typ sub)) x.pack_fields in {x with pack_fields} +let binding_op sub x = + { x with bop_exp = sub.expr sub x.bop_exp } + let signature sub x = let sig_final_env = sub.env sub x.sig_final_env in let sig_items = List.map (sub.signature_item sub) x.sig_items in @@ -371,12 +397,17 @@ let signature_item sub x = | Tsig_type (rec_flag, list) -> let (rec_flag, list) = sub.type_declarations sub (rec_flag, list) in Tsig_type (rec_flag, list) + | Tsig_typesubst list -> + let (_, list) = sub.type_declarations sub (Nonrecursive, list) in + Tsig_typesubst list | Tsig_typext te -> Tsig_typext (sub.type_extension sub te) | Tsig_exception ext -> - Tsig_exception (sub.extension_constructor sub ext) + Tsig_exception (sub.type_exception sub ext) | Tsig_module x -> Tsig_module (sub.module_declaration sub x) + | Tsig_modsubst x -> + Tsig_modsubst (sub.module_substitution sub x) | Tsig_recmodule list -> Tsig_recmodule (List.map (sub.module_declaration sub) list) | Tsig_modtype x -> @@ -388,7 +419,7 @@ let signature_item sub x = | Tsig_class_type list -> Tsig_class_type (List.map (sub.class_type_declaration sub) list) - | Tsig_open _ + | Tsig_open od -> Tsig_open (sub.open_description sub od) | Tsig_attribute _ as d -> d in {x with sig_desc; sig_env} @@ -426,12 +457,19 @@ let with_constraint sub = function | Twith_module _ | Twith_modsubst _ as d -> d +let open_description sub od = + {od with open_env = sub.env sub od.open_env} + +let open_declaration sub od = + {od with open_expr = sub.module_expr sub od.open_expr; + open_env = sub.env sub od.open_env} + let module_coercion sub = function | Tcoerce_none -> Tcoerce_none | Tcoerce_functor (c1,c2) -> Tcoerce_functor (sub.module_coercion sub c1, sub.module_coercion sub c2) - | Tcoerce_alias (p, c1) -> - Tcoerce_alias (p, sub.module_coercion sub c1) + | Tcoerce_alias (env, p, c1) -> + Tcoerce_alias (sub.env sub env, p, sub.module_coercion sub c1) | Tcoerce_structure (l1, l2) -> let l1' = List.map (fun (i,c) -> i, sub.module_coercion sub c) l1 in let l2' = @@ -501,7 +539,7 @@ let class_expr sub x = Tcl_fun ( label, sub.pat sub pat, - List.map (tuple3 id id (sub.expr sub)) priv, + List.map (tuple2 id (sub.expr sub)) priv, sub.class_expr sub cl, partial ) @@ -517,13 +555,13 @@ let class_expr sub x = Tcl_let ( rec_flag, value_bindings, - List.map (tuple3 id id (sub.expr sub)) ivars, + List.map (tuple2 id (sub.expr sub)) ivars, sub.class_expr sub cl ) | Tcl_ident (path, lid, tyl) -> Tcl_ident (path, lid, List.map (sub.typ sub) tyl) - | Tcl_open (ovf, p, lid, env, e) -> - Tcl_open (ovf, p, lid, sub.env sub env, sub.class_expr sub e) + | Tcl_open (od, e) -> + Tcl_open (sub.open_description sub od, sub.class_expr sub e) in {x with cl_desc; cl_env} @@ -544,8 +582,8 @@ let class_type sub x = sub.typ sub ct, sub.class_type sub cl ) - | Tcty_open (ovf, p, lid, env, e) -> - Tcty_open (ovf, p, lid, sub.env sub env, sub.class_type sub e) + | Tcty_open (od, e) -> + Tcty_open (sub.open_description sub od, sub.class_type sub e) in {x with cltyp_desc; cltyp_env} @@ -604,15 +642,21 @@ let class_structure sub x = let cstr_fields = List.map (sub.class_field sub) x.cstr_fields in {x with cstr_self; cstr_fields} -let row_field sub = function - | Ttag (label, attrs, b, list) -> - Ttag (label, attrs, b, List.map (sub.typ sub) list) - | Tinherit ct -> Tinherit (sub.typ sub ct) +let row_field sub x = + let rf_desc = match x.rf_desc with + | Ttag (label, b, list) -> + Ttag (label, b, List.map (sub.typ sub) list) + | Tinherit ct -> Tinherit (sub.typ sub ct) + in + { x with rf_desc; } -let object_field sub = function - | OTtag (label, attrs, ct) -> - OTtag (label, attrs, (sub.typ sub ct)) - | OTinherit ct -> OTinherit (sub.typ sub ct) +let object_field sub x = + let of_desc = match x.of_desc with + | OTtag (label, ct) -> + OTtag (label, (sub.typ sub ct)) + | OTinherit ct -> OTinherit (sub.typ sub ct) + in + { x with of_desc; } let class_field_kind sub = function | Tcfk_virtual ct -> Tcfk_virtual (sub.typ sub ct) @@ -660,6 +704,7 @@ let env _sub x = x let default = { + binding_op; case; cases; class_declaration; @@ -677,6 +722,7 @@ let default = module_binding; module_coercion; module_declaration; + module_substitution; module_expr; module_type; module_type_declaration; @@ -684,6 +730,8 @@ let default = pat; row_field; object_field; + open_declaration; + open_description; signature; signature_item; structure; @@ -692,6 +740,7 @@ let default = type_declaration; type_declarations; type_extension; + type_exception; type_kind; value_binding; value_bindings; diff --git a/typing/tast_mapper.mli b/typing/tast_mapper.mli index 2251fa57..467f203e 100644 --- a/typing/tast_mapper.mli +++ b/typing/tast_mapper.mli @@ -20,6 +20,7 @@ open Typedtree type mapper = { + binding_op: mapper -> binding_op -> binding_op; case: mapper -> case -> case; cases: mapper -> case list -> case list; class_declaration: mapper -> class_declaration -> class_declaration; @@ -39,6 +40,7 @@ type mapper = module_binding: mapper -> module_binding -> module_binding; module_coercion: mapper -> module_coercion -> module_coercion; module_declaration: mapper -> module_declaration -> module_declaration; + module_substitution: mapper -> module_substitution -> module_substitution; module_expr: mapper -> module_expr -> module_expr; module_type: mapper -> module_type -> module_type; module_type_declaration: @@ -47,15 +49,18 @@ type mapper = pat: mapper -> pattern -> pattern; row_field: mapper -> row_field -> row_field; object_field: mapper -> object_field -> object_field; + open_declaration: mapper -> open_declaration -> open_declaration; + open_description: mapper -> open_description -> open_description; signature: mapper -> signature -> signature; signature_item: mapper -> signature_item -> signature_item; structure: mapper -> structure -> structure; structure_item: mapper -> structure_item -> structure_item; typ: mapper -> core_type -> core_type; type_declaration: mapper -> type_declaration -> type_declaration; - type_declarations: mapper -> (rec_flag * type_declaration list) -> - (rec_flag * type_declaration list); + type_declarations: mapper -> (rec_flag * type_declaration list) + -> (rec_flag * type_declaration list); type_extension: mapper -> type_extension -> type_extension; + type_exception: mapper -> type_exception -> type_exception; type_kind: mapper -> type_kind -> type_kind; value_binding: mapper -> value_binding -> value_binding; value_bindings: mapper -> (rec_flag * value_binding list) -> diff --git a/typing/typeclass.ml b/typing/typeclass.ml index e03c2cd3..e384cf18 100644 --- a/typing/typeclass.ml +++ b/typing/typeclass.ml @@ -48,8 +48,8 @@ type class_type_info = { } type error = - Unconsistent_constraint of (type_expr * type_expr) list - | Field_type_mismatch of string * string * (type_expr * type_expr) list + Unconsistent_constraint of Ctype.Unification_trace.t + | Field_type_mismatch of string * string * Ctype.Unification_trace.t | Structure_expected of class_type | Cannot_apply of class_type | Apply_wrong_label of arg_label @@ -58,20 +58,19 @@ type error = | Unbound_class_2 of Longident.t | Unbound_class_type_2 of Longident.t | Abbrev_type_clash of type_expr * type_expr * type_expr - | Constructor_type_mismatch of string * (type_expr * type_expr) list + | Constructor_type_mismatch of string * Ctype.Unification_trace.t | Virtual_class of bool * bool * string list * string list | Parameter_arity_mismatch of Longident.t * int * int - | Parameter_mismatch of (type_expr * type_expr) list + | Parameter_mismatch of Ctype.Unification_trace.t | Bad_parameters of Ident.t * type_expr * type_expr | Class_match_failure of Ctype.class_match_failure list | Unbound_val of string | Unbound_type_var of (formatter -> unit) * Ctype.closed_class_failure - | Make_nongen_seltype of type_expr | Non_generalizable_class of Ident.t * Types.class_declaration | Cannot_coerce_self of type_expr | Non_collapsable_conjunction of - Ident.t * Types.class_declaration * (type_expr * type_expr) list - | Final_self_clash of (type_expr * type_expr) list + Ident.t * Types.class_declaration * Ctype.Unification_trace.t + | Final_self_clash of Ctype.Unification_trace.t | Mutability_mismatch of string * mutable_flag | No_overriding of string * string | Duplicate of string * string @@ -82,6 +81,11 @@ exception Error_forward of Location.error open Typedtree +let type_open_descr : + (?used_slot:bool ref -> Env.t -> Parsetree.open_description + -> open_description * Env.t) ref = + ref (fun ?used_slot:_ _ -> assert false) + let ctyp desc typ env loc = { ctyp_desc = desc; ctyp_type = typ; ctyp_loc = loc; ctyp_env = env; ctyp_attributes = [] } @@ -101,7 +105,8 @@ let dummy_method = Btype.dummy_method Path associated to the temporary class type of a class being typed (its constructor is not available). *) -let unbound_class = Path.Pident (Ident.create "*undef*") +let unbound_class = + Path.Pident (Ident.create_local "*undef*") (************************************) @@ -237,15 +242,18 @@ let rc node = (* Enter a value in the method environment only *) let enter_met_env ?check loc lab kind ty val_env met_env par_env = let (id, val_env) = - Env.enter_value lab {val_type = ty; val_kind = Val_unbound; - val_attributes = []; - Types.val_loc = loc} val_env + Env.enter_value lab + {val_type = ty; + val_kind = Val_unbound Val_unbound_instance_variable; + val_attributes = []; + Types.val_loc = loc} val_env in (id, val_env, Env.add_value ?check id {val_type = ty; val_kind = kind; val_attributes = []; Types.val_loc = loc} met_env, - Env.add_value id {val_type = ty; val_kind = Val_unbound; + Env.add_value id {val_type = ty; + val_kind = Val_unbound Val_unbound_instance_variable; val_attributes = []; Types.val_loc = loc} par_env) @@ -287,11 +295,11 @@ let inheritance self_type env ovf concr_meths warn_vals loc parent = begin try Ctype.unify env self_type cl_sig.csig_self with Ctype.Unify trace -> + let open Ctype.Unification_trace in match trace with - _::_::_::({desc = Tfield(n, _, _, _)}, _)::rem -> + | Diff _ :: Incompatible_fields {name = n; _ } :: rem -> raise(Error(loc, env, Field_type_mismatch ("method", n, rem))) - | _ -> - assert false + | _ -> assert false end; (* Overriding *) @@ -551,10 +559,10 @@ and class_type_aux env scty = let typ = Cty_arrow (l, ty, clty.cltyp_type) in cltyp (Tcty_arrow (l, cty, clty)) typ - | Pcty_open (ovf, lid, e) -> - let (path, newenv) = !Typecore.type_open ovf env scty.pcty_loc lid in + | Pcty_open (od, e) -> + let (od, newenv) = !type_open_descr env od in let clty = class_type newenv e in - cltyp (Tcty_open (ovf, path, lid, newenv, clty)) clty.cltyp_type + cltyp (Tcty_open (od, clty)) clty.cltyp_type | Pcty_extension ext -> raise (Error_forward (Builtin_attributes.error_of_extension ext)) @@ -605,7 +613,7 @@ and class_field_aux self_loc cl_num self_type meths vars in (* Inherited concrete methods *) let inh_meths = - Concr.fold (fun lab rem -> (lab, Ident.create lab)::rem) + Concr.fold (fun lab rem -> (lab, Ident.create_local lab)::rem) cl_sig.csig_concr [] in (* Super *) @@ -657,10 +665,7 @@ and class_field_aux self_loc cl_num self_type meths vars No_overriding ("instance variable", lab.txt))) end; if !Clflags.principal then Ctype.begin_def (); - let exp = - try type_exp val_env sexp with Ctype.Unify [(ty, _)] -> - raise(Error(loc, val_env, Make_nongen_seltype ty)) - in + let exp = type_exp val_env sexp in if !Clflags.principal then begin Ctype.end_def (); Ctype.generalize_structure exp.exp_type @@ -764,7 +769,7 @@ and class_field_aux self_loc cl_num self_type meths vars let meth_type = mk_expected ( Ctype.newty (Tarrow (Nolabel, self_type, - Ctype.instance_def Predef.type_unit, Cok)) + Ctype.instance Predef.type_unit, Cok)) ) in vars := vars_local; let texp = type_expect met_env expr meth_type in @@ -783,7 +788,7 @@ and class_field_aux self_loc cl_num self_type meths vars (* N.B. the self type of a final object type doesn't contain a dummy method in the beginning. - We only explicitely add a dummy method to class definitions (and class (type) + We only explicitly add a dummy method to class definitions (and class (type) declarations)), which are later removed (made absent) by [final_decl]. If we ever find a dummy method in a final object self type, it means that @@ -863,10 +868,8 @@ and class_structure cl_num final val_env met_env loc if final then begin (* Unify private_self and a copy of self_type. self_type will not be modified after this point *) - begin try Ctype.close_object self_type - with Ctype.Unify [] -> - raise(Error(loc, val_env, Closing_self_type self_type)) - end; + if not (Ctype.close_object self_type) then + raise(Error(loc, val_env, Closing_self_type self_type)); let mets = virtual_methods {sign with csig_self = self_type} in let vals = Vars.fold @@ -1010,11 +1013,11 @@ and class_expr_aux cl_num val_env met_env scl = end; let pv = List.map - begin fun (id, id_loc, id', _ty) -> + begin fun (id, id', _ty) -> let path = Pident id' in (* do not mark the value as being used *) let vd = Env.find_value path val_env' in - (id, id_loc, + (id, {exp_desc = Texp_ident(path, mknoloc (Longident.Lident (Ident.name id)), vd); exp_loc = Location.none; exp_extra = []; @@ -1042,7 +1045,7 @@ and class_expr_aux cl_num val_env met_env scl = rc {cl_desc = Tcl_fun (l, pat, pv, cl, partial); cl_loc = scl.pcl_loc; cl_type = Cty_arrow - (l, Ctype.instance_def pat.pat_type, cl.cl_type); + (l, Ctype.instance pat.pat_type, cl.cl_type); cl_env = val_env; cl_attributes = scl.pcl_attributes; } @@ -1157,14 +1160,10 @@ and class_expr_aux cl_num val_env met_env scl = } | Pcl_let (rec_flag, sdefs, scl') -> let (defs, val_env) = - try - Typecore.type_let val_env rec_flag sdefs None - with Ctype.Unify [(ty, _)] -> - raise(Error(scl.pcl_loc, val_env, Make_nongen_seltype ty)) - in + Typecore.type_let In_class_def val_env rec_flag sdefs None in let (vals, met_env) = List.fold_right - (fun (id, id_loc) (vals, met_env) -> + (fun (id, _id_loc, _typ) (vals, met_env) -> let path = Pident id in (* do not mark the value as used *) let vd = Env.find_value path val_env in @@ -1187,8 +1186,8 @@ and class_expr_aux cl_num val_env met_env scl = Types.val_loc = vd.Types.val_loc; } in - let id' = Ident.create (Ident.name id) in - ((id', id_loc, expr) + let id' = Ident.create_local (Ident.name id) in + ((id', expr) :: vals, Env.add_value id' desc met_env)) (let_bound_idents_with_loc defs) @@ -1232,12 +1231,12 @@ and class_expr_aux cl_num val_env met_env scl = cl_env = val_env; cl_attributes = scl.pcl_attributes; } - | Pcl_open (ovf, lid, e) -> + | Pcl_open (pod, e) -> let used_slot = ref false in - let (path, new_val_env) = !Typecore.type_open ~used_slot ovf val_env scl.pcl_loc lid in - let (_path, new_met_env) = !Typecore.type_open ~used_slot ovf met_env scl.pcl_loc lid in + let (od, new_val_env) = !type_open_descr ~used_slot val_env pod in + let ( _, new_met_env) = !type_open_descr ~used_slot met_env pod in let cl = class_expr cl_num new_val_env new_met_env e in - rc {cl_desc = Tcl_open (ovf, path, lid, new_val_env, cl); + rc {cl_desc = Tcl_open (od, cl); cl_loc = scl.pcl_loc; cl_type = cl.cl_type; cl_env = val_env; @@ -1257,7 +1256,7 @@ let rec approx_declaration cl = match cl.pcl_desc with Pcl_fun (l, _, _, cl) -> let arg = - if Btype.is_optional l then Ctype.instance_def var_option + if Btype.is_optional l then Ctype.instance var_option else Ctype.newvar () in Ctype.newty (Tarrow (l, arg, approx_declaration cl, Cok)) | Pcl_let (_, _, cl) -> @@ -1270,7 +1269,7 @@ let rec approx_description ct = match ct.pcty_desc with Pcty_arrow (l, _, ct) -> let arg = - if Btype.is_optional l then Ctype.instance_def var_option + if Btype.is_optional l then Ctype.instance var_option else Ctype.newvar () in Ctype.newty (Tarrow (l, arg, approx_description ct, Cok)) | _ -> Ctype.newvar () @@ -1291,7 +1290,8 @@ let temp_abbrev loc env id arity = type_private = Public; type_manifest = Some ty; type_variance = Misc.replicate_list Variance.full arity; - type_newtype_level = None; + type_is_newtype = false; + type_expansion_scope = Btype.lowest_level; type_loc = loc; type_attributes = []; (* or keep attrs from the class decl? *) type_immediate = false; @@ -1410,9 +1410,8 @@ let class_infos define_class kind begin let ty = Ctype.self_type obj_type in Ctype.hide_private_methods ty; - begin try Ctype.close_object ty - with Ctype.Unify [] -> raise(Error(cl.pci_loc, env, Closing_self_type ty)) - end; + if not (Ctype.close_object ty) then + raise(Error(cl.pci_loc, env, Closing_self_type ty)); begin try List.iter2 (Ctype.unify env) obj_params obj_params' with Ctype.Unify _ -> @@ -1541,7 +1540,8 @@ let class_infos define_class kind type_private = Public; type_manifest = Some obj_ty; type_variance = List.map (fun _ -> Variance.full) obj_params; - type_newtype_level = None; + type_is_newtype = false; + type_expansion_scope = Btype.lowest_level; type_loc = cl.pci_loc; type_attributes = []; (* or keep attrs from cl? *) type_immediate = false; @@ -1560,7 +1560,8 @@ let class_infos define_class kind type_private = Public; type_manifest = Some cl_ty; type_variance = List.map (fun _ -> Variance.full) cl_params; - type_newtype_level = None; + type_is_newtype = false; + type_expansion_scope = Btype.lowest_level; type_loc = cl.pci_loc; type_attributes = []; (* or keep attrs from cl? *) type_immediate = false; @@ -1719,15 +1720,17 @@ let check_coercions env (*******************************) let type_classes define_class approx kind env cls = + let scope = Ctype.create_scope () in let cls = List.map (function cl -> (cl, - Ident.create cl.pci_name.txt, Ident.create cl.pci_name.txt, - Ident.create cl.pci_name.txt, Ident.create ("#" ^ cl.pci_name.txt))) + Ident.create_scoped ~scope cl.pci_name.txt, + Ident.create_scoped ~scope cl.pci_name.txt, + Ident.create_scoped ~scope cl.pci_name.txt, + Ident.create_scoped ~scope ("#" ^ cl.pci_name.txt))) cls in - Ctype.init_def (Ident.current_time ()); Ctype.begin_class_def (); let (res, env) = List.fold_left (initial_env define_class approx) ([], env) cls @@ -1738,7 +1741,11 @@ let type_classes define_class approx kind env cls = Ctype.end_def (); let res = List.rev_map (final_decl env define_class) res in let decls = List.fold_right extract_type_decls res [] in - let decls = Typedecl.compute_variance_decls env decls in + let decls = + try Typedecl_variance.update_class_decls env decls + with Typedecl_variance.Error(loc, err) -> + raise (Typedecl.Error(loc, Typedecl.Variance err)) + in let res = List.map2 merge_type_decls res decls in let env = List.fold_left (final_env define_class) env res in let res = List.map (check_coercions env) res in @@ -1747,7 +1754,7 @@ let type_classes define_class approx kind env cls = let class_num = ref 0 let class_declaration env sexpr = incr class_num; - let expr = class_expr (string_of_int !class_num) env env sexpr in + let expr = class_expr (Int.to_string !class_num) env env sexpr in (expr, expr.cl_type) let class_description env sexpr = @@ -1799,7 +1806,7 @@ let rec unify_parents env ty cl = | _exn -> assert false end | Tcl_structure st -> unify_parents_struct env ty st - | Tcl_open (_, _, _, _, cl) + | Tcl_open (_, cl) | Tcl_fun (_, _, _, cl, _) | Tcl_apply (cl, _) | Tcl_let (_, _, _, cl) @@ -1815,7 +1822,7 @@ and unify_parents_struct env ty st = let type_object env loc s = incr class_num; let (desc, sign) = - class_structure (string_of_int !class_num) true env env loc s in + class_structure (Int.to_string !class_num) true env env loc s in let sty = Ctype.expand_head env sign.csig_self in Ctype.hide_private_methods sty; let (fields, _) = Ctype.flatten_fields (Ctype.object_fields sty) in @@ -1888,9 +1895,9 @@ let report_error env ppf = function Printtyp.reset_and_mark_loops_list [abbrev; actual; expected]; fprintf ppf "@[The abbreviation@ %a@ expands to type@ %a@ \ but is used with type@ %a@]" - Printtyp.type_expr abbrev - Printtyp.type_expr actual - Printtyp.type_expr expected + !Oprint.out_type (Printtyp.tree_of_typexp false abbrev) + !Oprint.out_type (Printtyp.tree_of_typexp false actual) + !Oprint.out_type (Printtyp.tree_of_typexp false expected) | Constructor_type_mismatch (c, trace) -> Printtyp.report_unification_error ppf env trace (function ppf -> @@ -1930,7 +1937,9 @@ let report_error env ppf = function fprintf ppf "@[The abbreviation %a@ is used with parameters@ %a@ \ which are incompatible with constraints@ %a@]" - Printtyp.ident id Printtyp.type_expr params Printtyp.type_expr cstrs + Printtyp.ident id + !Oprint.out_type (Printtyp.tree_of_typexp false params) + !Oprint.out_type (Printtyp.tree_of_typexp false cstrs) | Class_match_failure error -> Includeclass.report_error ppf error | Unbound_val lab -> @@ -1942,7 +1951,9 @@ let report_error env ppf = function List.iter Printtyp.mark_loops [ty; ty1]; fprintf ppf "The %s %s@ has type@;<1 2>%a@ where@ %a@ is unbound" - kind lab Printtyp.type_expr ty Printtyp.type_expr ty0 + kind lab + !Oprint.out_type (Printtyp.tree_of_typexp false ty) + !Oprint.out_type (Printtyp.tree_of_typexp false ty0) in let print_reason ppf = function | Ctype.CC_Method (ty0, real, lab, ty) -> @@ -1955,12 +1966,6 @@ let report_error env ppf = function "@[@[Some type variables are unbound in this type:@;<1 2>%t@]@ \ @[%a@]@]" printer print_reason reason - | Make_nongen_seltype ty -> - fprintf ppf - "@[@[Self type should not occur in the non-generic type@;<1 2>\ - %a@]@,\ - It would escape the scope of its class@]" - Printtyp.type_scheme ty | Non_generalizable_class (id, clty) -> fprintf ppf "@[The type of this class,@ %a,@ \ @@ -1975,11 +1980,12 @@ let report_error env ppf = function | Non_collapsable_conjunction (id, clty, trace) -> fprintf ppf "@[The type of this class,@ %a,@ \ - contains non-collapsible conjunctive types in constraints@]" - (Printtyp.class_declaration id) clty; - Printtyp.report_unification_error ppf env trace - (fun ppf -> fprintf ppf "Type") - (fun ppf -> fprintf ppf "is not compatible with type") + contains non-collapsible conjunctive types in constraints.@ %t@]" + (Printtyp.class_declaration id) clty + (fun ppf -> Printtyp.report_unification_error ppf env trace + (fun ppf -> fprintf ppf "Type") + (fun ppf -> fprintf ppf "is not compatible with type") + ) | Final_self_clash trace -> Printtyp.report_unification_error ppf env trace (function ppf -> @@ -2016,7 +2022,7 @@ let () = Location.register_error_of_exn (function | Error (loc, env, err) -> - Some (Location.error_of_printer loc (report_error env) err) + Some (Location.error_of_printer ~loc (report_error env) err) | Error_forward err -> Some err | _ -> diff --git a/typing/typeclass.mli b/typing/typeclass.mli index b9a0d210..c3503526 100644 --- a/typing/typeclass.mli +++ b/typing/typeclass.mli @@ -90,8 +90,8 @@ val type_classes : *) type error = - Unconsistent_constraint of (type_expr * type_expr) list - | Field_type_mismatch of string * string * (type_expr * type_expr) list + Unconsistent_constraint of Ctype.Unification_trace.t + | Field_type_mismatch of string * string * Ctype.Unification_trace.t | Structure_expected of class_type | Cannot_apply of class_type | Apply_wrong_label of arg_label @@ -100,20 +100,19 @@ type error = | Unbound_class_2 of Longident.t | Unbound_class_type_2 of Longident.t | Abbrev_type_clash of type_expr * type_expr * type_expr - | Constructor_type_mismatch of string * (type_expr * type_expr) list + | Constructor_type_mismatch of string * Ctype.Unification_trace.t | Virtual_class of bool * bool * string list * string list | Parameter_arity_mismatch of Longident.t * int * int - | Parameter_mismatch of (type_expr * type_expr) list + | Parameter_mismatch of Ctype.Unification_trace.t | Bad_parameters of Ident.t * type_expr * type_expr | Class_match_failure of Ctype.class_match_failure list | Unbound_val of string | Unbound_type_var of (formatter -> unit) * Ctype.closed_class_failure - | Make_nongen_seltype of type_expr | Non_generalizable_class of Ident.t * Types.class_declaration | Cannot_coerce_self of type_expr | Non_collapsable_conjunction of - Ident.t * Types.class_declaration * (type_expr * type_expr) list - | Final_self_clash of (type_expr * type_expr) list + Ident.t * Types.class_declaration * Ctype.Unification_trace.t + | Final_self_clash of Ctype.Unification_trace.t | Mutability_mismatch of string * mutable_flag | No_overriding of string * string | Duplicate of string * string @@ -123,3 +122,9 @@ exception Error of Location.t * Env.t * error exception Error_forward of Location.error val report_error : Env.t -> formatter -> error -> unit + +(* Forward decl filled in by Typemod.type_open_descr *) +val type_open_descr : + (?used_slot:bool ref -> + Env.t -> Parsetree.open_description -> Typedtree.open_description * Env.t) + ref diff --git a/typing/typecore.ml b/typing/typecore.ml index cd3df704..e87169ae 100644 --- a/typing/typecore.ml +++ b/typing/typecore.ml @@ -33,27 +33,38 @@ type type_forcing_context = | For_loop_body | Assert_condition | Sequence_left_hand_side + | When_guard type type_expected = { ty: type_expr; explanation: type_forcing_context option; } +type existential_restriction = + | At_toplevel (** no existential types at the toplevel *) + | In_group (** nor with let ... and ... *) + | In_rec (** or recursive definition *) + | With_attributes (** or let[@any_attribute] = ... *) + | In_class_args (** or in class arguments *) + | In_class_def (** or in [class c = let ... in ...] *) + | In_self_pattern (** or in self pattern *) + type error = - Polymorphic_label of Longident.t | Constructor_arity_mismatch of Longident.t * int * int - | Label_mismatch of Longident.t * (type_expr * type_expr) list - | Pattern_type_clash of (type_expr * type_expr) list - | Or_pattern_type_clash of Ident.t * (type_expr * type_expr) list + | Label_mismatch of Longident.t * Ctype.Unification_trace.t + | Pattern_type_clash of Ctype.Unification_trace.t + | Or_pattern_type_clash of Ident.t * Ctype.Unification_trace.t | Multiply_bound_variable of string | Orpat_vars of Ident.t * Ident.t list - | Expr_type_clash of (type_expr * type_expr) list * type_forcing_context option + | Expr_type_clash of + Ctype.Unification_trace.t * type_forcing_context option | Apply_non_function of type_expr | Apply_wrong_label of arg_label * type_expr | Label_multiply_defined of string | Label_missing of Ident.t list | Label_not_mutable of Longident.t - | Wrong_name of string * type_expected * string * Path.t * string * string list + | Wrong_name of + string * type_expected * string * Path.t * string * string list | Name_type_mismatch of string * Longident.t * (Path.t * Path.t) * (Path.t * Path.t) list | Invalid_format of string @@ -64,27 +75,27 @@ type error = | Private_label of Longident.t * type_expr | Unbound_instance_variable of string * string list | Instance_variable_not_mutable of bool * string - | Not_subtype of (type_expr * type_expr) list * (type_expr * type_expr) list + | Not_subtype of Ctype.Unification_trace.t * Ctype.Unification_trace.t | Outside_class | Value_multiply_overridden of string | Coercion_failure of - type_expr * type_expr * (type_expr * type_expr) list * bool + type_expr * type_expr * Ctype.Unification_trace.t * bool | Too_many_arguments of bool * type_expr * type_forcing_context option | Abstract_wrong_label of arg_label * type_expr * type_forcing_context option | Scoping_let_module of string * type_expr | Masked_instance_variable of Longident.t | Not_a_variant_type of Longident.t | Incoherent_label_order - | Less_general of string * (type_expr * type_expr) list + | Less_general of string * Ctype.Unification_trace.t | Modules_not_allowed | Cannot_infer_signature | Not_a_packed_module of type_expr - | Recursive_local_constraint of (type_expr * type_expr) list - | Unexpected_existential + | Unexpected_existential of existential_restriction * string * string list | Invalid_interval | Invalid_for_loop_index | No_value_clauses - | Exception_pattern_below_toplevel + | Exception_pattern_disallowed + | Mixed_value_and_exception_patterns_under_guard | Inlined_record_escape | Inlined_record_expected | Unrefuted_pattern of pattern @@ -96,6 +107,9 @@ type error = | Illegal_letrec_expr | Illegal_class_expr | Empty_pattern + | Letop_type_clash of string * Ctype.Unification_trace.t + | Andop_type_clash of string * Ctype.Unification_trace.t + | Bindings_type_clash of Ctype.Unification_trace.t exception Error of Location.t * Env.t * error exception Error_forward of Location.error @@ -114,6 +128,12 @@ let type_open : ref = ref (fun ?used_slot:_ _ -> assert false) +let type_open_decl : + (?used_slot:bool ref -> Env.t -> Parsetree.open_declaration + -> open_declaration * Types.signature * Env.t) + ref = + ref (fun ?used_slot:_ _ -> assert false) + (* Forward declaration, to be filled in by Typemod.type_package *) let type_package = @@ -177,7 +197,7 @@ let iter_expression f e = | Pexp_variant (_, eo) -> may expr eo | Pexp_record (iel, eo) -> may expr eo; List.iter (fun (_, e) -> expr e) iel - | Pexp_open (_, _, e) + | Pexp_open (_, e) | Pexp_newtype (_, e) | Pexp_poly (e, _) | Pexp_lazy e @@ -196,6 +216,8 @@ let iter_expression f e = | Pexp_override sel -> List.iter (fun (_, e) -> expr e) sel | Pexp_letmodule (_, me, e) -> expr e; module_expr me | Pexp_object { pcstr_fields = fs } -> List.iter class_field fs + | Pexp_letop { let_; ands; body; _ } -> + binding_op let_; List.iter binding_op ands; expr body | Pexp_pack me -> module_expr me | Pexp_unreachable -> () @@ -203,6 +225,9 @@ let iter_expression f e = may expr pc_guard; expr pc_rhs + and binding_op { pbop_exp; _ } = + expr pbop_exp + and binding x = expr x.pvb_expr @@ -244,7 +269,7 @@ let iter_expression f e = class_expr ce; List.iter (fun (_, e) -> expr e) lel | Pcl_let (_, pel, ce) -> List.iter binding pel; class_expr ce - | Pcl_open (_, _, ce) + | Pcl_open (_, ce) | Pcl_constraint (ce, _) -> class_expr ce | Pcl_extension _ -> () @@ -262,32 +287,16 @@ let iter_expression f e = expr e -let all_idents_cases el = - let idents = Hashtbl.create 8 in - let f = function - | {pexp_desc=Pexp_ident { txt = Longident.Lident id; _ }; _} -> - Hashtbl.replace idents id () - | _ -> () - in - List.iter - (fun cp -> - may (iter_expression f) cp.pc_guard; - iter_expression f cp.pc_rhs - ) - el; - Hashtbl.fold (fun x () rest -> x :: rest) idents [] - - (* Typing of constants *) let type_constant = function - Const_int _ -> instance_def Predef.type_int - | Const_char _ -> instance_def Predef.type_char - | Const_string _ -> instance_def Predef.type_string - | Const_float _ -> instance_def Predef.type_float - | Const_int32 _ -> instance_def Predef.type_int32 - | Const_int64 _ -> instance_def Predef.type_int64 - | Const_nativeint _ -> instance_def Predef.type_nativeint + Const_int _ -> instance Predef.type_int + | Const_char _ -> instance Predef.type_char + | Const_string _ -> instance Predef.type_string + | Const_float _ -> instance Predef.type_float + | Const_int32 _ -> instance Predef.type_int32 + | Const_int64 _ -> instance Predef.type_int64 + | Const_nativeint _ -> instance Predef.type_nativeint let constant : Parsetree.constant -> (Asttypes.constant, error) result = function @@ -390,28 +399,19 @@ let unify_exp_types loc env ty expected_ty = raise(Typetexp.Error(loc, env, Typetexp.Variant_tags (l1, l2))) (* level at which to create the local type declarations *) -let newtype_level = ref None -let get_newtype_level () = - match !newtype_level with +let gadt_equations_level = ref None +let get_gadt_equations_level () = + match !gadt_equations_level with Some y -> y | None -> assert false let unify_pat_types_gadt loc env ty ty' = - let newtype_level = - match !newtype_level with - | None -> assert false - | Some x -> x - in - try - unify_gadt ~newtype_level env ty ty' + try unify_gadt ~equations_level:(get_gadt_equations_level ()) env ty ty' with - Unify trace -> + | Unify trace -> raise(Error(loc, !env, Pattern_type_clash(trace))) | Tags(l1,l2) -> raise(Typetexp.Error(loc, !env, Typetexp.Variant_tags (l1, l2))) - | Unification_recursive_abbrev trace -> - raise(Error(loc, !env, Recursive_local_constraint trace)) - (* Creating new conjunctive types is not allowed when typing patterns *) @@ -460,12 +460,23 @@ let has_variants p = (* pattern environment *) -let pattern_variables = ref ([] : - (Ident.t * type_expr * string loc * Location.t * bool (* as-variable *)) list) +type pattern_variable = + { + pv_id: Ident.t; + pv_type: type_expr; + pv_loc: Location.t; + pv_as_var: bool; + pv_attributes: attributes; + } + +type module_variable = + string loc * Location.t + +let pattern_variables = ref ([] : pattern_variable list) let pattern_force = ref ([] : (unit -> unit) list) let pattern_scope = ref (None : Annot.ident option);; let allow_modules = ref false -let module_variables = ref ([] : (string loc * Location.t) list) +let module_variables = ref ([] : module_variable list) let reset_pattern scope allow = pattern_variables := []; pattern_force := []; @@ -474,13 +485,33 @@ let reset_pattern scope allow = module_variables := []; ;; -let enter_variable ?(is_module=false) ?(is_as_variable=false) loc name ty = - if List.exists (fun (id, _, _, _, _) -> Ident.name id = name.txt) +let maybe_add_pattern_variables_ghost loc_let env pv = + List.fold_right + (fun {pv_id; pv_type; _} env -> + let lid = Longident.Lident (Ident.name pv_id) in + match Env.lookup_value ~mark:false lid env with + | _ -> env + | exception Not_found -> + Env.add_value pv_id + { val_type = pv_type; + val_kind = Val_unbound Val_unbound_ghost_recursive; + val_loc = loc_let; + val_attributes = []; + } env + ) pv env + +let enter_variable ?(is_module=false) ?(is_as_variable=false) loc name ty + attrs = + if List.exists (fun {pv_id; _} -> Ident.name pv_id = name.txt) !pattern_variables then raise(Error(loc, Env.empty, Multiply_bound_variable name.txt)); - let id = Ident.create name.txt in + let id = Ident.create_local name.txt in pattern_variables := - (id, ty, name, loc, is_as_variable) :: !pattern_variables; + {pv_id = id; + pv_type = ty; + pv_loc = loc; + pv_as_var = is_as_variable; + pv_attributes = attrs} :: !pattern_variables; if is_module then begin (* Note: unpack patterns enter a variable of the same name *) if not !allow_modules then @@ -494,8 +525,8 @@ let enter_variable ?(is_module=false) ?(is_as_variable=false) loc name ty = let sort_pattern_variables vs = List.sort - (fun (x,_,_,_,_) (y,_,_,_,_) -> - Pervasives.compare (Ident.name x) (Ident.name y)) + (fun {pv_id = x; _} {pv_id = y; _} -> + Stdlib.compare (Ident.name x) (Ident.name y)) vs let enter_orpat_variables loc env p1_vs p2_vs = @@ -505,14 +536,15 @@ let enter_orpat_variables loc env p1_vs p2_vs = and p2_vs = sort_pattern_variables p2_vs in let rec unify_vars p1_vs p2_vs = - let vars vs = List.map (fun (x,_t,_,_l,_a) -> x) vs in + let vars vs = List.map (fun {pv_id; _} -> pv_id) vs in match p1_vs, p2_vs with - | (x1,t1,_,_l1,_a1)::rem1, (x2,t2,_,_l2,_a2)::rem2 + | {pv_id = x1; pv_type = t1; _}::rem1, {pv_id = x2; pv_type = t2; _}::rem2 when Ident.equal x1 x2 -> if x1==x2 then unify_vars rem1 rem2 else begin begin try + unify_var env (newvar ()) t1; unify env t1 t2 with | Unify trace -> @@ -521,9 +553,9 @@ let enter_orpat_variables loc env p1_vs p2_vs = (x2,x1)::unify_vars rem1 rem2 end | [],[] -> [] - | (x,_,_,_,_)::_, [] -> raise (Error (loc, env, Orpat_vars (x, []))) - | [],(y,_,_,_,_)::_ -> raise (Error (loc, env, Orpat_vars (y, []))) - | (x,_,_,_,_)::_, (y,_,_,_,_)::_ -> + | {pv_id; _}::_, [] | [],{pv_id; _}::_ -> + raise (Error (loc, env, Orpat_vars (pv_id, []))) + | {pv_id = x; _}::_, {pv_id = y; _}::_ -> let err = if Ident.name x < Ident.name y then Orpat_vars (x, vars p2_vs) @@ -582,7 +614,7 @@ let rec build_as_type env p = newty (Tvariant{row with row_closed=false; row_more=newvar()}) end | Tpat_any | Tpat_var _ | Tpat_constant _ - | Tpat_array _ | Tpat_lazy _ -> p.pat_type + | Tpat_array _ | Tpat_lazy _ | Tpat_exception _ -> p.pat_type let build_or_pat env loc lid = let path, decl = Typetexp.find_type env lid.loc lid.txt @@ -623,7 +655,10 @@ let build_or_pat env loc lid = pats in match pats with - [] -> raise(Error(lid.loc, env, Not_a_variant_type lid.txt)) + [] -> + (* empty polymorphic variants: not possible with the concrete language + but valid at the ast level *) + raise(Error(lid.loc, env, Not_a_variant_type lid.txt)) | pat :: pats -> let r = List.fold_left @@ -633,6 +668,19 @@ let build_or_pat env loc lid = pat pats in (path, rp { r with pat_loc = loc },ty) +let split_cases env cases = + let add_case lst case = function + | None -> lst + | Some c_lhs -> { case with c_lhs } :: lst + in + List.fold_right (fun ({ c_lhs; c_guard } as case) (vals, exns) -> + match split_pattern c_lhs with + | Some _, Some _ when c_guard <> None -> + raise (Error (c_lhs.pat_loc, env, + Mixed_value_and_exception_patterns_under_guard)) + | vp, ep -> add_case vals case vp, add_case exns case ep + ) cases ([], []) + (* Type paths *) let rec expand_path env p = @@ -646,7 +694,7 @@ let rec expand_path env p = | _ -> assert false end | _ -> - let p' = Env.normalize_path None env p in + let p' = Env.normalize_type_path None env p in if Path.same p p' then p else expand_path env p' let compare_type_path env tpath1 tpath2 = @@ -700,7 +748,9 @@ end) = struct let tpaths = unique (compare_type_path env) [tpath] others in match tpaths with [_] -> [] - | _ -> List.map Printtyp.string_of_path tpaths + | _ -> let open Printtyp in + wrap_printing_env ~error:true env (fun () -> + reset(); strings_of_paths Type tpaths) let disambiguate_by_type env tpath lbls = let check_type (lbl, _) = @@ -717,11 +767,13 @@ end) = struct [] -> unbound_name_error env lid | (lbl, use) :: rest -> use (); + Printtyp.Conflicts.reset (); let paths = ambiguous_types env lbl rest in + let expansion = Format.asprintf "%t" Printtyp.Conflicts.print in if paths <> [] then warn lid.loc (Warnings.Ambiguous_name ([Longident.last lid.txt], - paths, false)); + paths, false, expansion)); lbl end | Some(tpath0, tpath, pr) -> @@ -742,18 +794,23 @@ end) = struct let lbl_tpath = get_type_path lbl' in if not (compare_type_path env tpath lbl_tpath) then warn_pr () else + Printtyp.Conflicts.reset (); let paths = ambiguous_types env lbl rest in + let expansion = + Format.asprintf "%t" Printtyp.Conflicts.print in if paths <> [] then warn lid.loc (Warnings.Ambiguous_name ([Longident.last lid.txt], - paths, false)) + paths, false, expansion)) end; lbl with Not_found -> try let lbl = lookup_from_type env tpath lid in if in_env lbl then begin - let s = Printtyp.string_of_path tpath in + let s = + Printtyp.wrap_printing_env ~error:true env + (fun () -> Printtyp.string_of_path tpath) in warn lid.loc (Warnings.Name_out_of_scope (s, [Longident.last lid.txt], false)); end; @@ -797,7 +854,7 @@ module Label = NameChoice (struct let in_env lbl = match lbl.lbl_repres with | Record_regular | Record_float | Record_unboxed false -> true - | Record_unboxed true | Record_inlined _ | Record_extension -> false + | Record_unboxed true | Record_inlined _ | Record_extension _ -> false end) let disambiguate_label_by_ids keep closed ids labels = @@ -822,7 +879,7 @@ let disambiguate_lid_a_list loc closed env opath lid_a_list = let open Warnings in match msg with | Not_principal _ -> w_pr := true - | Ambiguous_name([s], l, _) -> w_amb := (s, l) :: !w_amb + | Ambiguous_name([s], l, _, ex) -> w_amb := (s, l, ex) :: !w_amb | Name_out_of_scope(ty, [s], _) -> w_scope := s :: !w_scope; w_scope_ty := ty | _ -> Location.prerr_warning loc msg @@ -856,17 +913,18 @@ let disambiguate_lid_a_list loc closed env opath lid_a_list = (Warnings.Not_principal "this type-based record disambiguation") else begin match List.rev !w_amb with - (_,types)::_ as amb -> + (_,types,ex)::_ as amb -> let paths = List.map (fun (_,lbl,_) -> Label.get_type_path lbl) lbl_a_list in let path = List.hd paths in + let fst3 (x,_,_) = x in if List.for_all (compare_type_path env path) (List.tl paths) then Location.prerr_warning loc - (Warnings.Ambiguous_name (List.map fst amb, types, true)) + (Warnings.Ambiguous_name (List.map fst3 amb, types, true, ex)) else List.iter - (fun (s,l) -> Location.prerr_warning loc - (Warnings.Ambiguous_name ([s],l,false))) + (fun (s,l,ex) -> Location.prerr_warning loc + (Warnings.Ambiguous_name ([s],l,false, ex))) amb | _ -> () end; @@ -992,35 +1050,108 @@ type type_pat_mode = | Inside_or (* inside a non-split or-pattern *) | Split_or (* always split or-patterns *) +(* "half typed" cases are produced in [type_cases] when we've just typechecked + the pattern but haven't type-checked the body yet. + At this point we might have added some type equalities to the environment, + but haven't yet added identifiers bound by the pattern. *) +type half_typed_case = + { typed_pat: pattern; + pat_type_for_unif: type_expr; + untyped_case: Parsetree.case; + branch_env: Env.t; + pat_vars: pattern_variable list; + unpacks: module_variable list; + contains_gadt: bool; } + +let all_idents_cases half_typed_cases = + let idents = Hashtbl.create 8 in + let f = function + | {pexp_desc=Pexp_ident { txt = Longident.Lident id; _ }; _} -> + Hashtbl.replace idents id () + | {pexp_desc=Pexp_letop{ let_; ands; _ }; _ } -> + Hashtbl.replace idents let_.pbop_op.txt (); + List.iter + (fun { pbop_op; _ } -> Hashtbl.replace idents pbop_op.txt ()) + ands + | _ -> () + in + List.iter + (fun { untyped_case = cp; _ } -> + may (iter_expression f) cp.pc_guard; + iter_expression f cp.pc_rhs + ) + half_typed_cases; + Hashtbl.fold (fun x () rest -> x :: rest) idents [] + +let rec has_literal_pattern p = match p.ppat_desc with + | Ppat_constant _ + | Ppat_interval _ -> + true + | Ppat_any + | Ppat_variant (_, None) + | Ppat_construct (_, None) + | Ppat_type _ + | Ppat_var _ + | Ppat_unpack _ + | Ppat_extension _ -> + false + | Ppat_exception p + | Ppat_variant (_, Some p) + | Ppat_construct (_, Some p) + | Ppat_constraint (p, _) + | Ppat_alias (p, _) + | Ppat_lazy p + | Ppat_open (_, p) -> + has_literal_pattern p + | Ppat_tuple ps + | Ppat_array ps -> + List.exists has_literal_pattern ps + | Ppat_record (ps, _) -> + List.exists (fun (_,p) -> has_literal_pattern p) ps + | Ppat_or (p, q) -> + has_literal_pattern p || has_literal_pattern q + exception Need_backtrack +let check_scope_escape loc env level ty = + try Ctype.check_scope_escape env level ty + with Unify trace -> + raise(Error(loc, env, Pattern_type_clash(trace))) + (* type_pat propagates the expected type as well as maps for constructors and labels. Unification may update the typing environment. *) (* constrs <> None => called from parmatch: backtrack on or-patterns explode > 0 => explode Ppat_any for gadts *) -let rec type_pat ~constrs ~labels ~no_existentials ~mode ~explode ~env - sp expected_ty k = +let rec type_pat ?(exception_allowed=false) ~constrs ~labels ~no_existentials + ~mode ~explode ~env sp expected_ty k = Builtin_attributes.warning_scope sp.ppat_attributes (fun () -> - type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env - sp expected_ty k + type_pat_aux ~exception_allowed ~constrs ~labels ~no_existentials ~mode + ~explode ~env sp expected_ty k ) -and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env - sp expected_ty k = +and type_pat_aux ~exception_allowed ~constrs ~labels ~no_existentials ~mode + ~explode ~env sp expected_ty k = let mode' = if mode = Splitting_or then Normal else mode in - let type_pat ?(constrs=constrs) ?(labels=labels) ?(mode=mode') - ?(explode=explode) ?(env=env) = - type_pat ~constrs ~labels ~no_existentials ~mode ~explode ~env in + let type_pat ?(exception_allowed=false) ?(constrs=constrs) ?(labels=labels) + ?(mode=mode') ?(explode=explode) ?(env=env) = + type_pat ~exception_allowed ~constrs ~labels ~no_existentials ~mode ~explode + ~env + in let loc = sp.ppat_loc in + let rup k x = + if constrs = None then (ignore (rp x)); + unify_pat !env x (instance expected_ty); + k x + in let rp k x : pattern = if constrs = None then k (rp x) else k x in match sp.ppat_desc with Ppat_any -> let k' d = rp k { pat_desc = d; pat_loc = loc; pat_extra=[]; - pat_type = expected_ty; + pat_type = instance expected_ty; pat_attributes = sp.ppat_attributes; pat_env = !env } in @@ -1041,33 +1172,38 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env ~explode sp expected_ty k else k' Tpat_any | Ppat_var name -> + let ty = instance expected_ty in let id = (* PR#7330 *) - if name.txt = "*extension*" then Ident.create name.txt else - enter_variable loc name expected_ty + if name.txt = "*extension*" then + Ident.create_local name.txt + else + enter_variable loc name ty sp.ppat_attributes in rp k { pat_desc = Tpat_var (id, name); pat_loc = loc; pat_extra=[]; - pat_type = expected_ty; + pat_type = ty; pat_attributes = sp.ppat_attributes; pat_env = !env } | Ppat_unpack name -> assert (constrs = None); - let id = enter_variable loc name expected_ty ~is_module:true in + let t = instance expected_ty in + let id = enter_variable loc name t ~is_module:true sp.ppat_attributes in rp k { pat_desc = Tpat_var (id, name); pat_loc = sp.ppat_loc; pat_extra=[Tpat_unpack, loc, sp.ppat_attributes]; - pat_type = expected_ty; + pat_type = t; pat_attributes = []; pat_env = !env } - | Ppat_constraint({ppat_desc=Ppat_var name; ppat_loc=lloc}, - ({ptyp_desc=Ptyp_poly _} as sty)) -> + | Ppat_constraint( + {ppat_desc=Ppat_var name; ppat_loc=lloc; ppat_attributes = attrs}, + ({ptyp_desc=Ptyp_poly _} as sty)) -> (* explicitly polymorphic type *) assert (constrs = None); let cty, force = Typetexp.transl_simple_type_delayed !env sty in let ty = cty.ctyp_type in - unify_pat_types lloc !env ty expected_ty; + unify_pat_types lloc !env ty (instance expected_ty); pattern_force := force :: !pattern_force; begin match ty.desc with | Tpoly (body, tyl) -> @@ -1075,7 +1211,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env let _, ty' = instance_poly ~keep_names:true false tyl body in end_def (); generalize ty'; - let id = enter_variable lloc name ty' in + let id = enter_variable lloc name ty' attrs in rp k { pat_desc = Tpat_var (id, name); pat_loc = lloc; @@ -1093,7 +1229,9 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env let ty_var = build_as_type !env q in end_def (); generalize ty_var; - let id = enter_variable ~is_as_variable:true loc name ty_var in + let id = + enter_variable ~is_as_variable:true loc name ty_var sp.ppat_attributes + in rp k { pat_desc = Tpat_alias(q, id, name); pat_loc = loc; pat_extra=[]; @@ -1102,11 +1240,10 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env pat_env = !env }) | Ppat_constant cst -> let cst = constant_or_raise !env loc cst in - unify_pat_types loc !env (type_constant cst) expected_ty; - rp k { + rup k { pat_desc = Tpat_constant cst; pat_loc = loc; pat_extra=[]; - pat_type = expected_ty; + pat_type = type_constant cst; pat_attributes = sp.ppat_attributes; pat_env = !env } | Ppat_interval (Pconst_char c1, Pconst_char c2) -> @@ -1127,14 +1264,18 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env raise (Error (loc, !env, Invalid_interval)) | Ppat_tuple spl -> assert (List.length spl >= 2); - let spl_ann = List.map (fun p -> (p,newvar ())) spl in - let ty = newty (Ttuple(List.map snd spl_ann)) in + let spl_ann = List.map (fun p -> (p,newgenvar ())) spl in + let ty = newgenty (Ttuple(List.map snd spl_ann)) in + begin_def (); + let expected_ty = instance expected_ty in + end_def (); + generalize_structure expected_ty; unify_pat_types loc !env ty expected_ty; map_fold_cont (fun (p,t) -> type_pat p t) spl_ann (fun pl -> rp k { pat_desc = Tpat_tuple pl; pat_loc = loc; pat_extra=[]; - pat_type = expected_ty; + pat_type = newty (Ttuple(List.map (fun p -> p.pat_type) pl)); pat_attributes = sp.ppat_attributes; pat_env = !env }) | Ppat_construct(lid, sarg) -> @@ -1158,14 +1299,19 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env if constr.cstr_generalized && constrs <> None && mode = Inside_or then raise Need_backtrack; Env.mark_constructor Env.Pattern !env (Longident.last lid.txt) constr; - Builtin_attributes.check_deprecated loc constr.cstr_attributes + Builtin_attributes.check_alerts loc constr.cstr_attributes constr.cstr_name; - if no_existentials && constr.cstr_existentials <> [] then - raise (Error (loc, !env, Unexpected_existential)); + begin match no_existentials, constr.cstr_existentials with + | None, _ | _, [] -> () + | Some r, (_ :: _ as exs) -> + let exs = List.map (Ctype.existential_name constr) exs in + let name = constr.cstr_name in + raise (Error (loc, !env, Unexpected_existential (r,name, exs))) + end; (* if constructor is gadt, we must verify that the expected type has the correct head *) if constr.cstr_generalized then - unify_head_only loc !env expected_ty constr; + unify_head_only loc !env (instance expected_ty) constr; let sargs = match sarg with None -> [] @@ -1179,24 +1325,29 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env Warnings.Wildcard_arg_to_constant_constr; replicate_list sp constr.cstr_arity | Some sp -> [sp] in - begin match sargs with - | [{ppat_desc = Ppat_constant _} as sp] - when Builtin_attributes.warn_on_literal_pattern - constr.cstr_attributes -> - Location.prerr_warning sp.ppat_loc - Warnings.Fragile_literal_pattern - | _ -> () - end; + if Builtin_attributes.warn_on_literal_pattern constr.cstr_attributes then + begin match List.filter has_literal_pattern sargs with + | sp :: _ -> + Location.prerr_warning sp.ppat_loc Warnings.Fragile_literal_pattern + | _ -> () + end; if List.length sargs <> constr.cstr_arity then raise(Error(loc, !env, Constructor_arity_mismatch(lid.txt, constr.cstr_arity, List.length sargs))); + begin_def (); let (ty_args, ty_res) = - instance_constructor ~in_pattern:(env, get_newtype_level ()) constr + instance_constructor ~in_pattern:(env, get_gadt_equations_level ()) + constr in + let expected_ty = instance expected_ty in (* PR#7214: do not use gadt unification for toplevel lets *) - if not constr.cstr_generalized || mode = Inside_or || no_existentials + if not constr.cstr_generalized || no_existentials <> None then unify_pat_types loc !env ty_res expected_ty else unify_pat_types_gadt loc env ty_res expected_ty; + end_def (); + generalize_structure expected_ty; + generalize_structure ty_res; + List.iter generalize_structure ty_args; let rec check_non_escaping p = match p.ppat_desc with @@ -1217,27 +1368,31 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env rp k { pat_desc=Tpat_construct(lid, constr, args); pat_loc = loc; pat_extra=[]; - pat_type = expected_ty; + pat_type = instance expected_ty; pat_attributes = sp.ppat_attributes; pat_env = !env }) | Ppat_variant(l, sarg) -> - let arg_type = match sarg with None -> [] | Some _ -> [newvar()] in + let arg_type = match sarg with None -> [] | Some _ -> [newgenvar()] in let row = { row_fields = [l, Reither(sarg = None, arg_type, true, ref None)]; row_bound = (); row_closed = false; - row_more = newvar (); + row_more = newgenvar (); row_fixed = false; row_name = None } in + begin_def (); + let expected_ty = instance expected_ty in + end_def (); + generalize_structure expected_ty; (* PR#7404: allow some_private_tag blindly, as it would not unify with the abstract row variable *) if l = Parmatch.some_private_tag then assert (constrs <> None) - else unify_pat_types loc !env (newty (Tvariant row)) expected_ty; + else unify_pat_types loc !env (newgenty (Tvariant row)) expected_ty; let k arg = rp k { pat_desc = Tpat_variant(l, arg, ref {row with row_more = newvar()}); pat_loc = loc; pat_extra=[]; - pat_type = expected_ty; + pat_type = instance expected_ty; pat_attributes = sp.ppat_attributes; pat_env = !env } in begin @@ -1251,40 +1406,34 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env let opath, record_ty = try let (p0, p,_) = extract_concrete_record !env expected_ty in - Some (p0, p, true), expected_ty + begin_def (); + let ty = instance expected_ty in + end_def (); + generalize_structure ty; + Some (p0, p, true), ty with Not_found -> None, newvar () in let type_label_pat (label_lid, label, sarg) k = begin_def (); - let (vars, ty_arg, ty_res) = instance_label false label in - if vars = [] then end_def (); + let (_, ty_arg, ty_res) = instance_label false label in begin try - unify_pat_types loc !env ty_res record_ty - with Unify trace -> + unify_pat_types loc !env ty_res (instance record_ty) + with Error(_loc, _env, Pattern_type_clash(trace)) -> raise(Error(label_lid.loc, !env, Label_mismatch(label_lid.txt, trace))) end; + end_def (); + generalize_structure ty_res; + generalize_structure ty_arg; type_pat sarg ty_arg (fun arg -> - if vars <> [] then begin - end_def (); - generalize ty_arg; - List.iter generalize vars; - let instantiated tv = - let tv = expand_head !env tv in - not (is_Tvar tv) || tv.level <> generic_level in - if List.exists instantiated vars then - raise - (Error(label_lid.loc, !env, Polymorphic_label label_lid.txt)) - end; k (label_lid, label, arg)) in let k' k lbl_pat_list = check_recordpat_labels loc lbl_pat_list closed; - unify_pat_types loc !env record_ty expected_ty; - rp k { + rup k { pat_desc = Tpat_record (lbl_pat_list, closed); pat_loc = loc; pat_extra=[]; - pat_type = expected_ty; + pat_type = instance record_ty; pat_attributes = sp.ppat_attributes; pat_env = !env } in @@ -1298,14 +1447,18 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env type_label_a_list ?labels loc false !env type_label_pat opath lid_sp_list (k' k) | Ppat_array spl -> - let ty_elt = newvar() in + let ty_elt = newgenvar() in + begin_def (); + let expected_ty = instance expected_ty in + end_def (); + generalize_structure expected_ty; unify_pat_types - loc !env (instance_def (Predef.type_array ty_elt)) expected_ty; + loc !env (Predef.type_array ty_elt) expected_ty; map_fold_cont (fun p -> type_pat p ty_elt) spl (fun pl -> rp k { pat_desc = Tpat_array pl; pat_loc = loc; pat_extra=[]; - pat_type = expected_ty; + pat_type = instance expected_ty; pat_attributes = sp.ppat_attributes; pat_env = !env }) | Ppat_or(sp1, sp2) -> @@ -1314,17 +1467,37 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env if mode = Split_or || mode = Splitting_or then raise Need_backtrack; let initial_pattern_variables = !pattern_variables in let initial_module_variables = !module_variables in + let equation_level = !gadt_equations_level in + let outter_lev = get_current_level () in + (* introduce a new scope *) + begin_def (); + let lev = get_current_level () in + gadt_equations_level := Some lev; + let env1 = ref !env in let p1 = - try Some (type_pat ~mode:Inside_or sp1 expected_ty (fun x -> x)) + try Some (type_pat ~exception_allowed ~mode:Inside_or sp1 expected_ty + ~env:env1 (fun x -> x)) with Need_backtrack -> None in let p1_variables = !pattern_variables in let p1_module_variables = !module_variables in pattern_variables := initial_pattern_variables; module_variables := initial_module_variables; + let env2 = ref !env in let p2 = - try Some (type_pat ~mode:Inside_or sp2 expected_ty (fun x -> x)) + try Some (type_pat ~exception_allowed ~mode:Inside_or sp2 expected_ty + ~env:env2 (fun x -> x)) with Need_backtrack -> None in + end_def (); + gadt_equations_level := equation_level; let p2_variables = !pattern_variables in + (* Make sure no variable with an ambiguous type gets added to the + environment. *) + List.iter (fun { pv_type; pv_loc; _ } -> + check_scope_escape pv_loc !env1 outter_lev pv_type + ) p1_variables; + List.iter (fun { pv_type; pv_loc; _ } -> + check_scope_escape pv_loc !env2 outter_lev pv_type + ) p2_variables; match p1, p2 with None, None -> raise Need_backtrack | Some p, None | None, Some p -> p (* no variables in this case *) @@ -1335,7 +1508,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env module_variables := p1_module_variables; { pat_desc = Tpat_or(p1, alpha_pat alpha_env p2, None); pat_loc = loc; pat_extra=[]; - pat_type = expected_ty; + pat_type = instance expected_ty; pat_attributes = sp.ppat_attributes; pat_env = !env } with @@ -1345,44 +1518,38 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env set_state state env; let mode = if mode = Split_or then mode else Splitting_or in - try type_pat ~mode sp1 expected_ty k with Error _ -> + try type_pat ~exception_allowed ~mode sp1 expected_ty k + with Error _ -> set_state state env; - type_pat ~mode sp2 expected_ty k + type_pat ~exception_allowed ~mode sp2 expected_ty k end | Ppat_lazy sp1 -> - let nv = newvar () in - unify_pat_types loc !env (instance_def (Predef.type_lazy_t nv)) - expected_ty; + let nv = newgenvar () in + unify_pat_types loc !env (Predef.type_lazy_t nv) expected_ty; (* do not explode under lazy: PR#7421 *) type_pat ~explode:0 sp1 nv (fun p1 -> rp k { pat_desc = Tpat_lazy p1; pat_loc = loc; pat_extra=[]; - pat_type = expected_ty; + pat_type = instance expected_ty; pat_attributes = sp.ppat_attributes; pat_env = !env }) | Ppat_constraint(sp, sty) -> - (* Separate when not already separated by !principal *) - let separate = true in - if separate then begin_def(); + (* Pretend separate = true *) + begin_def(); let cty, force = Typetexp.transl_simple_type_delayed !env sty in let ty = cty.ctyp_type in - let ty, expected_ty' = - if separate then begin - end_def(); - generalize_structure ty; - instance ty, instance ty - end else ty, ty - in - unify_pat_types loc !env ty expected_ty; - type_pat sp expected_ty' (fun p -> + end_def(); + generalize_structure ty; + let ty, expected_ty' = instance ty, ty in + unify_pat_types loc !env ty (instance expected_ty); + type_pat ~exception_allowed sp expected_ty' (fun p -> (*Format.printf "%a@.%a@." Printtyp.raw_type_expr ty Printtyp.raw_type_expr p.pat_type;*) pattern_force := force :: !pattern_force; let extra = (Tpat_constraint cty, loc, sp.ppat_attributes) in let p = - if not separate then p else match p.pat_desc with Tpat_var (id,s) -> {p with pat_type = ty; @@ -1395,37 +1562,45 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env in k p) | Ppat_type lid -> let (path, p,ty) = build_or_pat !env loc lid in - unify_pat_types loc !env ty expected_ty; + unify_pat_types loc !env ty (instance expected_ty); k { p with pat_extra = (Tpat_type (path, lid), loc, sp.ppat_attributes) :: p.pat_extra } | Ppat_open (lid,p) -> let path, new_env = !type_open Asttypes.Fresh !env sp.ppat_loc lid in let new_env = ref new_env in - type_pat ~env:new_env p expected_ty ( fun p -> + type_pat ~exception_allowed ~env:new_env p expected_ty ( fun p -> env := Env.copy_local !env ~from:!new_env; k { p with pat_extra =( Tpat_open (path,lid,!new_env), loc, sp.ppat_attributes) :: p.pat_extra } ) - | Ppat_exception _ -> - raise (Error (loc, !env, Exception_pattern_below_toplevel)) + | Ppat_exception p -> + if not exception_allowed then + raise (Error (loc, !env, Exception_pattern_disallowed)) + else begin + let p_exn = type_pat p Predef.type_exn k in + rp k { + pat_desc = Tpat_exception p_exn; + pat_loc = sp.ppat_loc; + pat_extra = []; + pat_type = expected_ty; + pat_env = !env; + pat_attributes = sp.ppat_attributes; + } + end | Ppat_extension ext -> raise (Error_forward (Builtin_attributes.error_of_extension ext)) -let type_pat ?(allow_existentials=false) ?constrs ?labels ?(mode=Normal) +let type_pat ?exception_allowed ?no_existentials ?constrs ?labels ?(mode=Normal) ?(explode=0) ?(lev=get_current_level()) env sp expected_ty = - newtype_level := Some lev; - try - let r = - type_pat ~no_existentials:(not allow_existentials) ~constrs ~labels - ~mode ~explode ~env sp expected_ty (fun x -> x) in - iter_pattern (fun p -> p.pat_env <- !env) r; - newtype_level := None; - r - with e -> - newtype_level := None; - raise e - + Misc.protect_refs [Misc.R (gadt_equations_level, Some lev)] (fun () -> + let r = + type_pat ?exception_allowed ~no_existentials ~constrs ~labels ~mode + ~explode ~env sp expected_ty (fun x -> x) + in + iter_pattern (fun p -> p.pat_env <- !env) r; + r + ) (* this function is passed to Partial.parmatch to type check gadt nonexhaustiveness *) @@ -1436,8 +1611,7 @@ let partial_pred ~lev ?mode ?explode env expected_ty constrs labels p = reset_pattern None true; let typed_p = Ctype.with_passive_variants - (type_pat ~allow_existentials:true ~lev - ~constrs ~labels ?mode ?explode env p) + (type_pat ~lev ~constrs ~labels ?mode ?explode env p) expected_ty in set_state state env; @@ -1464,46 +1638,47 @@ let check_unused ?(lev=get_current_level ()) env expected_ty cases = | r -> r) cases -let add_pattern_variables ?check ?check_as env = - let pv = get_ref pattern_variables in - (List.fold_right - (fun (id, ty, _name, loc, as_var) env -> - let check = if as_var then check_as else check in - Env.add_value ?check id - {val_type = ty; val_kind = Val_reg; Types.val_loc = loc; - val_attributes = []; +let iter_pattern_variables_type f : pattern_variable list -> unit = + List.iter (fun {pv_type; _} -> f pv_type) + +let add_pattern_variables ?check ?check_as env pv = + List.fold_right + (fun {pv_id; pv_type; pv_loc; pv_as_var; pv_attributes} env -> + let check = if pv_as_var then check_as else check in + Env.add_value ?check pv_id + {val_type = pv_type; val_kind = Val_reg; Types.val_loc = pv_loc; + val_attributes = pv_attributes; } env - ) - pv env, - get_ref module_variables) + ) + pv env -let type_pattern ~lev env spat scope expected_ty = +let type_pattern ?exception_allowed ~lev env spat scope expected_ty = reset_pattern scope true; let new_env = ref env in - let pat = type_pat ~allow_existentials:true ~lev new_env spat expected_ty in - let new_env, unpacks = - add_pattern_variables !new_env - ~check:(fun s -> Warnings.Unused_var_strict s) - ~check_as:(fun s -> Warnings.Unused_var s) in - (pat, new_env, get_ref pattern_force, unpacks) - -let type_pattern_list env spatl scope expected_tys allow = + let pat = type_pat ?exception_allowed ~lev new_env spat expected_ty in + let pvs = get_ref pattern_variables in + let unpacks = get_ref module_variables in + (pat, !new_env, get_ref pattern_force, pvs, unpacks) + +let type_pattern_list no_existentials env spatl scope expected_tys allow = reset_pattern scope allow; let new_env = ref env in let type_pat (attrs, pat) ty = Builtin_attributes.warning_scope ~ppwarning:false attrs (fun () -> - type_pat new_env pat ty + type_pat ~no_existentials new_env pat ty ) in let patl = List.map2 type_pat spatl expected_tys in - let new_env, unpacks = add_pattern_variables !new_env in - (patl, new_env, get_ref pattern_force, unpacks) + let pvs = get_ref pattern_variables in + let unpacks = get_ref module_variables in + let new_env = add_pattern_variables !new_env pvs in + (patl, new_env, get_ref pattern_force, pvs, unpacks) let type_class_arg_pattern cl_num val_env met_env l spat = reset_pattern None false; let nv = newvar () in - let pat = type_pat (ref val_env) spat nv in + let pat = type_pat ~no_existentials:In_class_args (ref val_env) spat nv in if has_variants pat then begin Parmatch.pressure_variants val_env [pat]; iter_pattern finalize_variant pat @@ -1512,21 +1687,21 @@ let type_class_arg_pattern cl_num val_env met_env l spat = if is_optional l then unify_pat val_env pat (type_option (newvar ())); let (pv, met_env) = List.fold_right - (fun (id, ty, name, loc, as_var) (pv, env) -> + (fun {pv_id; pv_type; pv_loc; pv_as_var; pv_attributes} (pv, env) -> let check s = - if as_var then Warnings.Unused_var s + if pv_as_var then Warnings.Unused_var s else Warnings.Unused_var_strict s in - let id' = Ident.create (Ident.name id) in - ((id', name, id, ty)::pv, - Env.add_value id' {val_type = ty; + let id' = Ident.create_local (Ident.name pv_id) in + ((id', pv_id, pv_type)::pv, + Env.add_value id' {val_type = pv_type; val_kind = Val_ivar (Immutable, cl_num); - val_attributes = []; - Types.val_loc = loc; + val_attributes = pv_attributes; + Types.val_loc = pv_loc; } ~check env)) !pattern_variables ([], met_env) in - let val_env, _ = add_pattern_variables val_env in + let val_env = add_pattern_variables val_env (get_ref pattern_variables) in (pat, pv, val_env, met_env) let type_self_pattern cl_num privty val_env met_env par_env spat = @@ -1537,7 +1712,7 @@ let type_self_pattern cl_num privty val_env met_env par_env spat = in reset_pattern None false; let nv = newvar() in - let pat = type_pat (ref val_env) spat nv in + let pat = type_pat ~no_existentials:In_self_pattern (ref val_env) spat nv in List.iter (fun f -> f()) (get_ref pattern_force); let meths = ref Meths.empty in let vars = ref Vars.empty in @@ -1545,24 +1720,29 @@ let type_self_pattern cl_num privty val_env met_env par_env spat = pattern_variables := []; let (val_env, met_env, par_env) = List.fold_right - (fun (id, ty, _name, loc, as_var) (val_env, met_env, par_env) -> - (Env.add_value id {val_type = ty; - val_kind = Val_unbound; - val_attributes = []; - Types.val_loc = loc; - } val_env, - Env.add_value id {val_type = ty; - val_kind = Val_self (meths, vars, cl_num, privty); - val_attributes = []; - Types.val_loc = loc; - } - ~check:(fun s -> if as_var then Warnings.Unused_var s + (fun {pv_id; pv_type; pv_loc; pv_as_var; pv_attributes} + (val_env, met_env, par_env) -> + (Env.add_value pv_id {val_type = pv_type; + val_kind = + Val_unbound Val_unbound_instance_variable; + val_attributes = pv_attributes; + Types.val_loc = pv_loc; + } val_env, + Env.add_value pv_id {val_type = pv_type; + val_kind = + Val_self (meths, vars, cl_num, privty); + val_attributes = pv_attributes; + Types.val_loc = pv_loc; + } + ~check:(fun s -> if pv_as_var then Warnings.Unused_var s else Warnings.Unused_var_strict s) met_env, - Env.add_value id {val_type = ty; val_kind = Val_unbound; - val_attributes = []; - Types.val_loc = loc; - } par_env)) + Env.add_value pv_id {val_type = pv_type; + val_kind = + Val_unbound Val_unbound_instance_variable; + val_attributes = pv_attributes; + Types.val_loc = pv_loc; + } par_env)) pv (val_env, met_env, par_env) in (pat, meths, vars, val_env, met_env, par_env) @@ -1605,11 +1785,24 @@ let rec is_nonexpansive exp = | Texp_function _ -> true | Texp_apply(e, (_,None)::el) -> is_nonexpansive e && List.for_all is_nonexpansive_opt (List.map snd el) - | Texp_match(e, cases, [], _) -> + | Texp_match(e, cases, _) -> + (* Not sure this is necessary, if [e] is nonexpansive then we shouldn't + care if there are exception patterns. But the previous version enforced + that there be none, so... *) + let contains_exception_pat p = + let res = ref false in + iter_pattern (fun p -> + match p.pat_desc with + | Tpat_exception _ -> res := true + | _ -> () + ) p; + !res + in is_nonexpansive e && List.for_all - (fun {c_lhs = _; c_guard; c_rhs} -> + (fun {c_lhs; c_guard; c_rhs} -> is_nonexpansive_opt c_guard && is_nonexpansive c_rhs + && not (contains_exception_pat c_lhs) ) cases | Texp_tuple el -> List.for_all is_nonexpansive el @@ -1651,13 +1844,15 @@ let rec is_nonexpansive exp = Vars.fold (fun _ (mut,_,_) b -> decr count; b && mut = Immutable) vars true && !count = 0 - | Texp_letmodule (_, _, mexp, e) -> + | Texp_letmodule (_, _, _, mexp, e) + | Texp_open ({ open_expr = mexp; _}, e) -> is_nonexpansive_mod mexp && is_nonexpansive e | Texp_pack mexp -> is_nonexpansive_mod mexp - (* Computations which raise exceptions are nonexpansive, since (raise e) is equivalent - to (raise e; diverge), and a nonexpansive "diverge" can be produced using lazy values - or the relaxed value restriction. See GPR#1142 *) + (* Computations which raise exceptions are nonexpansive, since (raise e) is + equivalent to (raise e; diverge), and a nonexpansive "diverge" can be + produced using lazy values or the relaxed value restriction. + See GPR#1142 *) | Texp_assert exp -> is_nonexpansive exp | Texp_apply ( @@ -1678,17 +1873,19 @@ and is_nonexpansive_mod mexp = List.for_all (fun item -> match item.str_desc with | Tstr_eval _ | Tstr_primitive _ | Tstr_type _ - | Tstr_modtype _ | Tstr_open _ | Tstr_class_type _ -> true + | Tstr_modtype _ | Tstr_class_type _ -> true | Tstr_value (_, pat_exp_list) -> List.for_all (fun vb -> is_nonexpansive vb.vb_expr) pat_exp_list | Tstr_module {mb_expr=m;_} + | Tstr_open {open_expr=m;_} | Tstr_include {incl_mod=m;_} -> is_nonexpansive_mod m | Tstr_recmodule id_mod_list -> List.for_all (fun {mb_expr=m;_} -> is_nonexpansive_mod m) id_mod_list - | Tstr_exception {ext_kind = Text_decl _} -> + | Tstr_exception {tyexn_constructor = {ext_kind = Text_decl _}} -> false (* true would be unsound *) - | Tstr_exception {ext_kind = Text_rebind _} -> true + | Tstr_exception {tyexn_constructor = {ext_kind = Text_rebind _}} -> + true | Tstr_typext te -> List.for_all (function {ext_kind = Text_decl _} -> false @@ -1704,754 +1901,20 @@ and is_nonexpansive_opt = function None -> true | Some e -> is_nonexpansive e -module Env' = Env -module Rec_context = -struct - type access = - Dereferenced - (** [Dereferenced] indicates that the value (not just the address) of a - variable is accessed *) - - | Guarded - (** [Guarded] indicates that the address of a variable is used in a - guarded context, i.e. under a constructor. A variable that is - dereferenced within a function body or lazy context is also considered - guarded. *) - - | Unguarded - (** [Unguarded] indicates that the address of a variable is used in an - unguarded context, i.e. not under a constructor. *) - - (** [guard] represents guarded contexts such as [C -] and [{l = -}] *) - let guard : access -> access = function - | Dereferenced -> Dereferenced - | Guarded -> Guarded - | Unguarded -> Guarded - - (** [inspect] represents elimination contexts such as [match - with cases], - [e -] and [- e] *) - let inspect : access -> access = function - | Dereferenced -> Dereferenced - | Guarded -> Dereferenced - | Unguarded -> Dereferenced - - (** [delay] represents contexts that delay evaluation such as [fun p -> -] - or [lazy -] *) - let delay : access -> access = function - | Dereferenced -> Guarded - | Guarded -> Guarded - | Unguarded -> Guarded - - module Use : - sig - type t - val guard : t -> t - (** An expression appears in a guarded context *) - - val discard : t -> t - (** The address of a subexpression is not used, but may be bound *) - - val inspect : t -> t - (** The value of a subexpression is inspected with match, application, etc. *) - - val delay : t -> t - (** An expression appears under 'fun p ->' or 'lazy' *) - - val join : t -> t -> t - (** Combine the access information of two expressions *) - - val single : Ident.t -> access -> t - (** Combine the access information of two expressions *) - - val empty : t - (** No variables are accessed in an expression; it might be a - constant or a global identifier *) - - val unguarded : t -> Ident.t list - (** The list of identifiers that are used in an unguarded context *) - - val dependent : t -> Ident.t list - (** The list of all used identifiers *) - end = - struct - module M = Map.Make(Ident) - - (** A "t" maps each rec-bound variable to an access status *) - type t = access M.t - - let map f tbl = M.map f tbl - let guard t = map guard t - let inspect t = map inspect t - let delay t = map delay t - let discard = guard - - let prec x y = - match x, y with - | Dereferenced, _ - | _, Dereferenced -> Dereferenced - | Unguarded, _ - | _, Unguarded -> Unguarded - | _ -> Guarded - - let join x y = - M.fold - (fun id v tbl -> - let v' = try M.find id tbl with Not_found -> Guarded in - M.add id (prec v v') tbl) - x y - - let single id access = M.add id access M.empty - - let empty = M.empty - - let list_matching p t = - let r = ref [] in - M.iter (fun id v -> if p v then r := id :: !r) t; - !r - - let unguarded = - list_matching (function Unguarded | Dereferenced -> true | _ -> false) - - let dependent = - list_matching (function _ -> true) - end - - module Env = - struct - (* A typing environment maps identifiers to types *) - type env = Use.t Ident.tbl - - let empty = Ident.empty - - let join x y = - let r = - Ident.fold_all - (fun id v tbl -> - let v' = try Ident.find_same id tbl with Not_found -> Use.empty in - Ident.add id (Use.join v v') tbl) - x - y - in - r - end -end - -let rec pattern_variables : Typedtree.pattern -> Ident.t list = - fun pat -> match pat.pat_desc with - | Tpat_any -> [] - | Tpat_var (id, _) -> [id] - | Tpat_alias (pat, id, _) -> id :: pattern_variables pat - | Tpat_constant _ -> [] - | Tpat_tuple pats -> List.concat (List.map pattern_variables pats) - | Tpat_construct (_, _, pats) -> - List.concat (List.map pattern_variables pats) - | Tpat_variant (_, Some pat, _) -> pattern_variables pat - | Tpat_variant (_, None, _) -> [] - | Tpat_record (fields, _) -> - List.concat (List.map (fun (_,_,p) -> pattern_variables p) fields) - | Tpat_array pats -> - List.concat (List.map pattern_variables pats) - | Tpat_or (l,r,_) -> - pattern_variables l @ pattern_variables r - | Tpat_lazy p -> - pattern_variables p - -module Rec_check = -struct - open Rec_context - - let build_unguarded_env : Ident.t list -> Env.env = fun idlist -> - List.fold_left - (fun env id -> Ident.add id (Use.single id Unguarded) env) - Env.empty - idlist - - let is_ref : Types.value_description -> bool = function - | { Types.val_kind = - Types.Val_prim { Primitive.prim_name = "%makemutable"; - prim_arity = 1 } } -> - true - | _ -> false - - let scrape env ty = - (Ctype.repr (Ctype.expand_head_opt env (Ctype.correct_levels ty))).desc - - let array_element_kind env ty = - match scrape env ty with - | Tvar _ | Tunivar _ -> - `Pgenarray - | Tconstr(p, _, _) -> - if Path.same p Predef.path_int || Path.same p Predef.path_char then - `Pintarray - else if Path.same p Predef.path_float then - if Config.flat_float_array then `Pfloatarray else `Paddrarray - else if Path.same p Predef.path_string - || Path.same p Predef.path_array - || Path.same p Predef.path_nativeint - || Path.same p Predef.path_int32 - || Path.same p Predef.path_int64 then - `Paddrarray - else begin - try - match Env'.find_type p env with - {type_kind = Type_abstract} -> - `Pgenarray - | {type_kind = Type_variant cstrs} - when List.for_all (fun c -> c.Types.cd_args = Types.Cstr_tuple []) - cstrs -> - `Pintarray - | {type_kind = _} -> - `Paddrarray - with Not_found -> - (* This can happen due to e.g. missing -I options, - causing some .cmi files to be unavailable. - Maybe we should emit a warning. *) - `Pgenarray - end - | _ -> - `Paddrarray - - let array_type_kind env ty = - match scrape env ty with - | Tconstr(p, [elt_ty], _) | Tpoly({desc = Tconstr(p, [elt_ty], _)}, _) - when Path.same p Predef.path_array -> - array_element_kind env elt_ty - | _ -> - (* This can happen with e.g. Obj.field *) - `Pgenarray - - let array_kind exp = array_type_kind exp.exp_env exp.exp_type - - let has_concrete_element_type : Typedtree.expression -> bool = - fun e -> array_kind e <> `Pgenarray - - (* See the note on abstracted arguments in the documentation for - Typedtree.Texp_apply *) - let is_abstracted_arg : arg_label * expression option -> bool = function - | (_, None) -> true - | (_, Some _) -> false - - type sd = Static | Dynamic - - let classify_expression : Typedtree.expression -> sd = - (* We need to keep track of the size of expressions - bound by local declarations, to be able to predict - the size of variables. Compare: - - let rec r = - let y = fun () -> r () - in y - - and - - let rec r = - let y = if Random.bool () then ignore else fun () -> r () - in y - - In both cases the final adress of `r` must be known before `y` is compiled, - and this is only possible if `r` has a statically-known size. - - The first definition can be allowed (`y` has a statically-known - size) but the second one is unsound (`y` has no statically-known size). - *) - let rec classify_expression env e = match e.exp_desc with - (* binding and variable cases *) - | Texp_let (rec_flag, vb, e) -> - let env = classify_value_bindings rec_flag env vb in - classify_expression env e - | Texp_ident (path, _, _) -> - classify_path env path - - (* non-binding cases *) - | Texp_letmodule (_, _, _, e) - | Texp_sequence (_, e) - | Texp_letexception (_, e) -> - classify_expression env e - - | Texp_construct (_, {cstr_tag = Cstr_unboxed}, [e]) -> - classify_expression env e - | Texp_construct _ -> - Static - - | Texp_record { representation = Record_unboxed _; - fields = [| _, Overridden (_,e) |] } -> - classify_expression env e - | Texp_record _ -> - Static - - | Texp_apply ({exp_desc = Texp_ident (_, _, vd)}, _) - when is_ref vd -> - Static - | Texp_apply (_,args) - when List.exists is_abstracted_arg args -> - Static - | Texp_apply _ -> - Dynamic - - | Texp_for _ - | Texp_constant _ - | Texp_new _ - | Texp_instvar _ - | Texp_tuple _ - | Texp_array _ - | Texp_variant _ - | Texp_setfield _ - | Texp_while _ - | Texp_setinstvar _ - | Texp_pack _ - | Texp_object _ - | Texp_function _ - | Texp_lazy _ - | Texp_unreachable - | Texp_extension_constructor _ -> - Static - - | Texp_match _ - | Texp_ifthenelse _ - | Texp_send _ - | Texp_field _ - | Texp_assert _ - | Texp_try _ - | Texp_override _ -> - Dynamic - and classify_value_bindings rec_flag env bindings = - (* We use a non-recursive classification, classifying each - binding with respect to the old environment - (before all definitions), even if the bindings are recursive. - - Note: computing a fixpoint in some way would be more - precise, as the following could be allowed: - - let rec topdef = - let rec x = y and y = fun () -> topdef () - in x - *) - ignore rec_flag; - let old_env = env in - let add_value_binding env vb = - match vb.vb_pat.pat_desc with - | Tpat_var (id, _loc) -> - let size = classify_expression old_env vb.vb_expr in - Ident.add id size env - | _ -> - (* Note: we don't try to compute any size for complex patterns *) - env - in - List.fold_left add_value_binding env bindings - and classify_path env = function - | Path.Pident x -> - begin - try Ident.find_same x env - with Not_found -> - (* an identifier will be missing from the map if either: - - it is a non-local identifier - (bound outside the letrec-binding we are analyzing) - - or it is bound by a complex (let p = e in ...) local binding - - or it is bound within a module (let module M = ... in ...) - that we are not traversing for size computation - - For non-local identifiers it might be reasonable (although - not completely clear) to consider them Static (they have - already been evaluated), but for the others we must - under-approximate with Dynamic. - - This could be fixed by a more complete implementation. - *) - Dynamic - end - | Path.Pdot _ | Path.Papply _ -> - (* local modules could have such paths to local definitions; - classify_expression could be extend to compute module - shapes more precisely *) - Dynamic - in classify_expression Ident.empty - - let rec expression : Env.env -> Typedtree.expression -> Use.t = - fun env exp -> match exp.exp_desc with - | Texp_ident (pth, _, _) -> - (path env pth) - | Texp_let (rec_flag, bindings, body) -> - let env', ty = value_bindings rec_flag env bindings in - (* Here and in other binding constructs 'discard' is used in a - similar way to the way it's used in sequence: uses are - propagated, but unguarded access are not. *) - Use.join (Use.discard ty) (expression (Env.join env env') body) - | Texp_letmodule (x, _, m, e) -> - let ty = modexp env m in - Use.join (Use.discard ty) (expression (Ident.add x ty env) e) - | Texp_match (e, val_cases, exn_cases, _) -> - let t = expression env e in - let exn_case env {Typedtree.c_rhs} = expression env c_rhs in - let cs = list (case ~scrutinee:t) env val_cases - and es = list exn_case env exn_cases in - Use.(join cs es) - | Texp_for (_, _, e1, e2, _, e3) -> - Use.(join - (join - (inspect (expression env e1)) - (inspect (expression env e2))) - (* The body is evaluated, but not used, and not available - for inclusion in another value *) - (discard (expression env e3))) - - | Texp_constant _ -> - Use.empty - | Texp_new (pth, _, _) -> - Use.inspect (path env pth) - | Texp_instvar _ -> - Use.empty - | Texp_apply ({exp_desc = Texp_ident (_, _, vd)}, [_, Some arg]) - when is_ref vd -> - Use.guard (expression env arg) - | Texp_apply (e, args) -> - let arg env (_, eo) = option expression env eo in - let ty = Use.join (list arg env args) (expression env e) in - if List.exists is_abstracted_arg args - then (* evaluate expressions, abstract over the results - let g = f and x = e in fun z -> g ~x z *) - Use.discard ty - else Use.inspect ty - | Texp_tuple exprs -> - Use.guard (list expression env exprs) - | Texp_array exprs when array_kind exp = `Pfloatarray -> - Use.inspect (list expression env exprs) - | Texp_array exprs when has_concrete_element_type exp -> - Use.guard (list expression env exprs) - | Texp_array exprs -> - (* This is counted as a use, because constructing a generic array - involves inspecting the elements (PR#6939). *) - Use.inspect (list expression env exprs) - | Texp_construct (_, desc, exprs) -> - let access_constructor = - match desc.cstr_tag with - | Cstr_extension (pth, _) -> Use.inspect (path env pth) - | _ -> Use.empty - in - let use = match desc.cstr_tag with - | Cstr_unboxed -> (fun x -> x) - | Cstr_constant _ | Cstr_block _ | Cstr_extension _ -> Use.guard - in - Use.join access_constructor (use (list expression env exprs)) - | Texp_variant (_, eo) -> - Use.guard (option expression env eo) - | Texp_record { fields = es; extended_expression = eo; - representation = rep } -> - let use = match rep with - | Record_float -> Use.inspect - | Record_unboxed _ -> (fun x -> x) - | Record_regular | Record_inlined _ - | Record_extension -> Use.guard - in - let field env = function - _, Kept _ -> Use.empty - | _, Overridden (_, e) -> expression env e - in - Use.join - (use (array field env es)) - (option expression env eo) - | Texp_ifthenelse (cond, ifso, ifnot) -> - Use.(join (inspect (expression env cond)) - (join - (expression env ifso) - (option expression env ifnot))) - | Texp_setfield (e1, _, _, e2) -> - Use.(join (inspect (expression env e1)) - (inspect (expression env e2))) - | Texp_sequence (e1, e2) -> - Use.(join (discard (expression env e1)) - (expression env e2)) - | Texp_while (e1, e2) -> - Use.(join (inspect (expression env e1)) - (discard (expression env e2))) - | Texp_send (e1, _, eo) -> - Use.(join (inspect (expression env e1)) - (inspect (option expression env eo))) - | Texp_field (e, _, _) -> - Use.(inspect (expression env e)) - | Texp_setinstvar (_,_,_,e) -> - Use.(inspect (expression env e)) - | Texp_letexception (_, e) -> - expression env e - | Texp_assert e -> - Use.inspect (expression env e) - | Texp_pack m -> - modexp env m - | Texp_object (clsstrct, _) -> - class_structure env clsstrct - | Texp_try (e, cases) -> - (* This is more permissive than the old check. *) - let case env {Typedtree.c_rhs} = expression env c_rhs in - Use.join (expression env e) - (list case env cases) - | Texp_override (_, fields) -> - let field env (_, _, e) = expression env e in - Use.inspect (list field env fields) - | Texp_function { cases } -> - Use.delay (list (case ~scrutinee:Use.empty) env cases) - | Texp_lazy e -> - begin match Typeopt.classify_lazy_argument e with - | `Constant_or_function - | `Identifier _ - | `Float_that_cannot_be_shortcut -> - expression env e - | `Other -> - Use.delay (expression env e) - end - | Texp_unreachable -> - Use.empty - | Texp_extension_constructor _ -> - Use.empty - and option : 'a. (Env.env -> 'a -> Use.t) -> Env.env -> 'a option -> Use.t = - fun f env -> Misc.Stdlib.Option.value_default (f env) ~default:Use.empty - and list : 'a. (Env.env -> 'a -> Use.t) -> Env.env -> 'a list -> Use.t = - fun f env -> - List.fold_left (fun typ item -> Use.join (f env item) typ) Use.empty - and array : 'a. (Env.env -> 'a -> Use.t) -> Env.env -> 'a array -> Use.t = - fun f env -> - Array.fold_left (fun typ item -> Use.join (f env item) typ) Use.empty - and class_structure : Env.env -> Typedtree.class_structure -> Use.t = - fun env cs -> Use.(inspect (list class_field env cs.cstr_fields)) - and class_field : Env.env -> Typedtree.class_field -> Use.t = - fun env cf -> match cf.cf_desc with - | Tcf_inherit (_, ce, _super, _inh_vars, _inh_meths) -> - Use.inspect (class_expr env ce) - | Tcf_val (_lab, _mut, _, cfk, _) -> - class_field_kind env cfk - | Tcf_method (_, _, cfk) -> - class_field_kind env cfk - | Tcf_constraint _ -> - Use.empty - | Tcf_initializer e -> - Use.inspect (expression env e) - | Tcf_attribute _ -> - Use.empty - and class_field_kind : Env.env -> Typedtree.class_field_kind -> Use.t = - fun env cfk -> match cfk with - | Tcfk_virtual _ -> - Use.empty - | Tcfk_concrete (_, e) -> - Use.inspect (expression env e) - and modexp : Env.env -> Typedtree.module_expr -> Use.t = - fun env m -> match m.mod_desc with - | Tmod_ident (pth, _) -> - (path env pth) - | Tmod_structure s -> - structure env s - | Tmod_functor (_, _, _, e) -> - Use.delay (modexp env e) - | Tmod_apply (f, p, _) -> - Use.(join - (inspect (modexp env f)) - (inspect (modexp env p))) - | Tmod_constraint (m, _, _, Tcoerce_none) -> - modexp env m - | Tmod_constraint (m, _, _, _) -> - Use.inspect (modexp env m) - | Tmod_unpack (e, _) -> - expression env e - and path : Env.env -> Path.t -> Use.t = - fun env pth -> match pth with - | Path.Pident x -> - (try Ident.find_same x env with Not_found -> Use.empty) - | Path.Pdot (t, _, _) -> - Use.inspect (path env t) - | Path.Papply (f, p) -> - Use.(inspect (join (path env f) (path env p))) - and structure : Env.env -> Typedtree.structure -> Use.t = - fun env s -> - let _, ty = - List.fold_left - (fun (env, ty) item -> - let env', ty' = structure_item env item in - Env.join env env', Use.join ty ty') - (env, Use.empty) - s.str_items - in - Use.guard ty - and structure_item : Env.env -> Typedtree.structure_item -> Env.env * Use.t = - fun env s -> match s.str_desc with - | Tstr_eval (e, _) -> - Env.empty, expression env e - | Tstr_value (rec_flag, valbinds) -> - value_bindings rec_flag env valbinds - | Tstr_module {mb_id; mb_expr} -> - let ty = modexp env mb_expr in - Ident.add mb_id ty Env.empty, ty - | Tstr_recmodule mbs -> - let modbind env {mb_expr} = modexp env mb_expr in - (* Over-approximate: treat any access as a use *) - Env.empty, Use.inspect (list modbind env mbs) - | Tstr_primitive _ -> - Env.empty, Use.empty - | Tstr_type _ -> - Env.empty, Use.empty - | Tstr_typext _ -> - Env.empty, Use.empty - | Tstr_exception _ -> - Env.empty, Use.empty - | Tstr_modtype _ -> - Env.empty, Use.empty - | Tstr_open _ -> - Env.empty, Use.empty - | Tstr_class classes -> - (* Any occurrence in a class definition is counted as a use, - so there's no need to add anything to the environment. *) - let cls env ({ci_expr=ce}, _) = class_expr env ce in - Env.empty, Use.inspect (list cls env classes) - | Tstr_class_type _ -> - Env.empty, Use.empty - | Tstr_include inc -> - (* This is a kind of projection. There's no need to add - anything to the environment because everything is used in - the type component already *) - Env.empty, Use.inspect (modexp env inc.incl_mod) - | Tstr_attribute _ -> - Env.empty, Use.empty - and class_expr : Env.env -> Typedtree.class_expr -> Use.t = - fun env ce -> match ce.cl_desc with - | Tcl_ident (pth, _, _) -> - Use.inspect (path env pth) - | Tcl_structure cs -> - class_structure env cs - | Tcl_fun (_, _, args, ce, _) -> - let arg env (_, _, e) = expression env e in - Use.inspect (Use.join (list arg env args) - (class_expr env ce)) - | Tcl_apply (ce, args) -> - let arg env (_, eo) = option expression env eo in - Use.inspect (Use.join (class_expr env ce) - (list arg env args)) - | Tcl_let (rec_flag, valbinds, _, ce) -> - let env', ty = value_bindings rec_flag env valbinds in - Use.(inspect (join ty (class_expr env' ce))) - | Tcl_constraint (ce, _, _, _, _) -> - class_expr env ce - | Tcl_open (_, _, _, _, ce) -> - class_expr env ce - and case : Env.env -> Typedtree.case -> scrutinee:Use.t -> Use.t = - fun env { Typedtree.c_lhs; c_guard; c_rhs } ~scrutinee:ty -> - let ty = - if is_destructuring_pattern c_lhs then Use.inspect ty - else Use.discard ty (* as in 'let' *) - in - let vars = pattern_variables c_lhs in - let env = - List.fold_left - (fun env id -> Ident.add id ty env) - env - vars - in - Use.(join ty - (join (expression env c_rhs) - (inspect (option expression env c_guard)))) - and value_bindings : rec_flag -> Env.env -> Typedtree.value_binding list -> Env.env * Use.t = - fun rec_flag env bindings -> - match rec_flag with - | Recursive -> - (* Approximation: - let rec y = - let rec x1 = e1 - and x2 = e2 - in e - treated as - let rec y = - let rec x = (e1, e2)[x1:=fst x, x2:=snd x] in - e[x1:=fst x, x2:=snd x] - Further, use the fact that x1,x2 cannot occur unguarded in e1, e2 - to avoid recursive trickiness. - *) - let ids, ty = - List.fold_left - (fun (pats, tys) {vb_pat=p; vb_expr=e} -> - (pattern_variables p @ pats, - Use.join (expression env e) tys)) - ([], Use.empty) - bindings - in - (List.fold_left (fun (env : Env.env) (id : Ident.t) -> - Ident.add id ty env) Env.empty ids, - ty) - | Nonrecursive -> - List.fold_left - (fun (env2, ty) binding -> - let env', ty' = value_binding env binding in - (Env.join env2 env', Use.join ty ty')) - (Env.empty, Use.empty) - bindings - and value_binding : Env.env -> Typedtree.value_binding -> Env.env * Use.t = - (* NB: returns new environment only *) - fun env { vb_pat; vb_expr } -> - let vars = pattern_variables vb_pat in - let ty = expression env vb_expr in - let ty = if is_destructuring_pattern vb_pat then Use.inspect ty else ty in - (List.fold_left - (fun env id -> Ident.add id ty env) - Env.empty - vars, - ty) - and is_destructuring_pattern : Typedtree.pattern -> bool = - fun pat -> match pat.pat_desc with - | Tpat_any -> false - | Tpat_var (_, _) -> false - | Tpat_alias (pat, _, _) -> is_destructuring_pattern pat - | Tpat_constant _ -> true - | Tpat_tuple _ -> true - | Tpat_construct (_, _, _) -> true - | Tpat_variant _ -> true - | Tpat_record (_, _) -> true - | Tpat_array _ -> true - | Tpat_or (l,r,_) -> is_destructuring_pattern l || is_destructuring_pattern r - | Tpat_lazy _ -> true - - let check_recursive_expression env idlist expr = - let ty = expression (build_unguarded_env idlist) expr in - match Use.unguarded ty, Use.dependent ty, classify_expression expr with - | _ :: _, _, _ (* The expression inspects rec-bound variables *) - | _, _ :: _, Dynamic -> (* The expression depends on rec-bound variables - and its size is unknown *) - raise(Error(expr.exp_loc, env, Illegal_letrec_expr)) - | [], _, Static (* The expression has known size *) - | [], [], Dynamic -> (* The expression has unknown size, - but does not depend on rec-bound variables *) - () - let check_class_expr env idlist ce = - let rec class_expr : Env.env -> Typedtree.class_expr -> Use.t = - fun env ce -> match ce.cl_desc with - | Tcl_ident (_, _, _) -> Use.empty - | Tcl_structure _ -> Use.empty - | Tcl_fun (_, _, _, _, _) -> Use.empty - | Tcl_apply (_, _) -> Use.empty - | Tcl_let (rec_flag, valbinds, _, ce) -> - (* This rule looks like the `Texp_let` rule in the `expression` - function. There is no `Use.discard` here because the - occurrences of the variables in [idlist] are only of the form - [new id], so they are either absent, Dereferenced, or Guarded - (under a delay), never Unguarded, and `discard` would be a no-op. - *) - let env', ty = value_bindings rec_flag env valbinds in - Use.join ty (class_expr env' ce) - | Tcl_constraint (ce, _, _, _, _) -> - class_expr env ce - | Tcl_open (_, _, _, _, ce) -> - class_expr env ce - in - match Use.unguarded (class_expr (build_unguarded_env idlist) ce) with - | [] -> () - | _ :: _ -> raise(Error(ce.cl_loc, env, Illegal_class_expr)) -end - let check_recursive_bindings env valbinds = - let ids = List.concat - (List.map (fun b -> pattern_variables b.vb_pat) valbinds) in + let ids = let_bound_idents valbinds in List.iter (fun {vb_expr} -> - Rec_check.check_recursive_expression env ids vb_expr) + if not (Rec_check.is_valid_recursive_expression ids vb_expr) then + raise(Error(vb_expr.exp_loc, env, Illegal_letrec_expr)) + ) valbinds let check_recursive_class_bindings env ids exprs = List.iter (fun expr -> - Rec_check.check_class_expr env ids expr) + if not (Rec_check.is_valid_class_expr ids expr) then + raise(Error(expr.cl_loc, env, Illegal_class_expr))) exprs (* Approximate the type of an expression, for better recursion *) @@ -2527,7 +1990,7 @@ let list_labels env ty = (* Check that all univars are safe in a type *) let check_univars env expans kind exp ty_expected vars = if expans && not (is_nonexpansive exp) then - generalize_expansive env exp.exp_type; + lower_contravariant env exp.exp_type; (* need to expand twice? cf. Ctype.unify2 *) let vars = List.map (expand_head env) vars in let vars = List.map (expand_head env) vars in @@ -2545,19 +2008,74 @@ let check_univars env expans kind exp ty_expected vars = let ty = newgenty (Tpoly(repr exp.exp_type, vars')) and ty_expected = repr ty_expected in raise (Error (exp.exp_loc, env, - Less_general(kind, [ty, ty; ty_expected, ty_expected]))) - -(* Check that a type is not a function *) -let check_application_result env statement exp = - let loc = exp.exp_loc in - match (expand_head env exp.exp_type).desc with - | Tarrow _ -> - Location.prerr_warning exp.exp_loc Warnings.Partial_application - | Tvar _ -> () - | Tconstr (p, _, _) when Path.same p Predef.path_unit -> () - | _ -> - if statement then - Location.prerr_warning loc Warnings.Statement_type + Less_general(kind, [Unification_trace.diff ty ty_expected]))) + +let check_partial_application statement exp = + let rec f delay = + let ty = (expand_head exp.exp_env exp.exp_type).desc in + let check_statement () = + match ty with + | Tconstr (p, _, _) when Path.same p Predef.path_unit -> + () + | _ -> + if statement then + let rec loop {exp_loc; exp_desc; exp_extra; _} = + match exp_desc with + | Texp_let (_, _, e) + | Texp_sequence (_, e) + | Texp_letexception (_, e) + | Texp_letmodule (_, _, _, _, e) -> + loop e + | _ -> + let loc = + match List.find_opt (function + | (Texp_constraint _, _, _) -> true + | _ -> false) exp_extra + with + | Some (_, loc, _) -> loc + | None -> exp_loc + in + Location.prerr_warning loc Warnings.Statement_type + in + loop exp + in + match ty, exp.exp_desc with + | Tarrow _, _ -> + let rec check {exp_desc; exp_loc; exp_extra; _} = + if List.exists (function + | (Texp_constraint _, _, _) -> true + | _ -> false) exp_extra then check_statement () + else begin + match exp_desc with + | Texp_ident _ | Texp_constant _ | Texp_tuple _ + | Texp_construct _ | Texp_variant _ | Texp_record _ + | Texp_field _ | Texp_setfield _ | Texp_array _ + | Texp_while _ | Texp_for _ | Texp_instvar _ + | Texp_setinstvar _ | Texp_override _ | Texp_assert _ + | Texp_lazy _ | Texp_object _ | Texp_pack _ | Texp_unreachable + | Texp_extension_constructor _ | Texp_ifthenelse (_, _, None) + | Texp_function _ -> + check_statement () + | Texp_match (_, cases, _) -> + List.iter (fun {c_rhs; _} -> check c_rhs) cases + | Texp_try (e, cases) -> + check e; List.iter (fun {c_rhs; _} -> check c_rhs) cases + | Texp_ifthenelse (_, e1, Some e2) -> + check e1; check e2 + | Texp_let (_, _, e) | Texp_sequence (_, e) | Texp_open (_, e) + | Texp_letexception (_, e) | Texp_letmodule (_, _, _, _, e) -> + check e + | Texp_apply _ | Texp_send _ | Texp_new _ | Texp_letop _ -> + Location.prerr_warning exp_loc Warnings.Partial_application + end + in + check exp + | Tvar _, _ -> + if delay then add_delayed_check (fun () -> f false) + | _ -> + check_statement () + in + f true (* Check that a type is generalizable at some level *) let generalizable level ty = @@ -2588,7 +2106,8 @@ let create_package_type loc env (p, l) = let open Ast_helper in List.fold_left (fun sexp (name, loc) -> - Exp.letmodule ~loc:sexp.pexp_loc ~attrs:[mknoloc "#modulepat",PStr []] + Exp.letmodule ~loc:sexp.pexp_loc + ~attrs:[Attr.mk (mknoloc "#modulepat") (PStr [])] name (Mod.unpack ~loc (Exp.ident ~loc:name.loc (mkloc (Longident.Lident name.txt) @@ -2685,10 +2204,13 @@ let check_absent_variant env = (* Duplicate types of values in the environment *) (* XXX Should we do something about global type variables too? *) -let duplicate_ident_types caselist env = +let duplicate_ident_types half_typed_cases env = let caselist = - List.filter (fun {pc_lhs} -> may_contain_gadts pc_lhs) caselist in - Env.copy_types (all_idents_cases caselist) env + List.filter (fun { typed_pat; _ } -> + contains_gadt typed_pat + ) half_typed_cases + in + Env.make_copy_of_types (all_idents_cases caselist) env (* Getting proper location of already typed expressions. @@ -2714,12 +2236,15 @@ let proper_exp_loc exp = (* To find reasonable names for let-bound and lambda-bound idents *) let rec name_pattern default = function - [] -> Ident.create default - | {c_lhs=p; _} :: rem -> - match p.pat_desc with - Tpat_var (id, _) -> id - | Tpat_alias(_, id, _) -> id - | _ -> name_pattern default rem + [] -> Ident.create_local default + | p :: rem -> + match p.pat_desc with + Tpat_var (id, _) -> id + | Tpat_alias(_, id, _) -> id + | _ -> name_pattern default rem + +let name_cases default lst = + name_pattern default (List.map (fun c -> c.c_lhs) lst) (* Typing of expressions *) @@ -2772,71 +2297,51 @@ and type_expect_ in match sexp.pexp_desc with | Pexp_ident lid -> - begin - let (path, desc) = Typetexp.find_value env lid.loc lid.txt in - if !Clflags.annotations then begin - let dloc = desc.Types.val_loc in - let annot = - if dloc.Location.loc_ghost then Annot.Iref_external - else Annot.Iref_internal dloc - in - let name = Path.name ~paren:Oprint.parenthesized_ident path in - Stypes.record (Stypes.An_ident (loc, name, annot)) - end; - let is_recarg = - match (repr desc.val_type).desc with - | Tconstr(p, _, _) -> Path.is_constructor_typath p - | _ -> false - in - - begin match is_recarg, recarg, (repr desc.val_type).desc with - | _, Allowed, _ - | true, Required, _ - | false, Rejected, _ - -> () - | true, Rejected, _ - | false, Required, (Tvar _ | Tconstr _) -> - raise (Error (loc, env, Inlined_record_escape)) - | false, Required, _ -> - () (* will fail later *) - end; - rue { - exp_desc = - begin match desc.val_kind with - Val_ivar (_, cl_num) -> - let (self_path, _) = - Env.lookup_value (Longident.Lident ("self-" ^ cl_num)) env - in - Texp_instvar(self_path, path, - match lid.txt with - Longident.Lident txt -> { txt; loc = lid.loc } - | _ -> assert false) - | Val_self (_, _, cl_num, _) -> - let (path, _) = - Env.lookup_value (Longident.Lident ("self-" ^ cl_num)) env - in - Texp_ident(path, lid, desc) - | Val_unbound -> - raise(Error(loc, env, Masked_instance_variable lid.txt)) - (*| Val_prim _ -> - let p = Env.normalize_path (Some loc) env path in - Env.add_required_global (Path.head p); - Texp_ident(path, lid, desc)*) - | _ -> - Texp_ident(path, lid, desc) - end; - exp_loc = loc; exp_extra = []; - exp_type = instance desc.val_type; - exp_attributes = sexp.pexp_attributes; - exp_env = env } - end + let path, desc = type_ident env ~recarg lid in + let exp_desc = + match desc.val_kind with + | Val_ivar (_, cl_num) -> + let (self_path, _) = + Env.lookup_value (Longident.Lident ("self-" ^ cl_num)) env + in + Texp_instvar(self_path, path, + match lid.txt with + Longident.Lident txt -> { txt; loc = lid.loc } + | _ -> assert false) + | Val_self (_, _, cl_num, _) -> + let (path, _) = + Env.lookup_value (Longident.Lident ("self-" ^ cl_num)) env + in + Texp_ident(path, lid, desc) + | Val_unbound Val_unbound_instance_variable -> + raise(Error(loc, env, Masked_instance_variable lid.txt)) + | Val_unbound Val_unbound_ghost_recursive -> + let desc_loc = desc.Types.val_loc in + (* Only display the "missing rec" hint for non-ghost code *) + if not loc.Location.loc_ghost + && not desc_loc.Location.loc_ghost + then + raise Typetexp.(Error ( + loc, env, Unbound_value_missing_rec (lid.txt, desc_loc) + )) + else + raise Typetexp.(Error (loc, env, Unbound_value lid.txt)) + | _ -> + Texp_ident(path, lid, desc) + in + rue { + exp_desc; exp_loc = loc; exp_extra = []; + exp_type = instance desc.val_type; + exp_attributes = sexp.pexp_attributes; + exp_env = env } | Pexp_constant(Pconst_string (str, _) as cst) -> ( let cst = constant_or_raise env loc cst in (* Terrible hack for format strings *) let ty_exp = expand_head env ty_expected in let fmt6_path = Path.(Pdot (Pident (Ident.create_persistent "CamlinternalFormatBasics"), - "format6", 0)) in + "format6")) + in let is_format = match ty_exp.desc with | Tconstr(path, _, _) when Path.same path fmt6_path -> if !Clflags.principal && ty_exp.level <> generic_level then @@ -2853,7 +2358,7 @@ and type_expect_ rue { exp_desc = Texp_constant cst; exp_loc = loc; exp_extra = []; - exp_type = instance_def Predef.type_string; + exp_type = instance Predef.type_string; exp_attributes = sexp.pexp_attributes; exp_env = env } ) @@ -2874,14 +2379,18 @@ and type_expect_ pexp_desc = Pexp_match (sval, [Ast_helper.Exp.case spat sbody])} ty_expected_explained | Pexp_let(rec_flag, spat_sexp_list, sbody) -> + let existential_context = + if rec_flag = Recursive then In_rec + else if List.compare_length_with spat_sexp_list 1 > 0 then In_group + else With_attributes in let scp = match sexp.pexp_attributes, rec_flag with - | [{txt="#default"},_], _ -> None + | [{attr_name = {txt="#default"}; _}], _ -> None | _, Recursive -> Some (Annot.Idef loc) | _, Nonrecursive -> Some (Annot.Idef sbody.pexp_loc) in let (pat_exp_list, new_env, unpacks) = - type_let env rec_flag spat_sexp_list scp true in + type_let existential_context env rec_flag spat_sexp_list scp true in let body = type_expect new_env (wrap_unpacks sbody unpacks) ty_expected_explained in @@ -2925,14 +2434,15 @@ and type_expect_ in let pat = Pat.var ~loc:sloc (mknoloc "*opt*") in let body = - Exp.let_ ~loc Nonrecursive ~attrs:[mknoloc "#default",PStr []] + Exp.let_ ~loc Nonrecursive + ~attrs:[Attr.mk (mknoloc "#default") (PStr [])] [Vb.mk spat smatch] sbody in - type_function ?in_function loc sexp.pexp_attributes env ty_expected_explained - l [Exp.case pat body] + type_function ?in_function loc sexp.pexp_attributes env + ty_expected_explained l [Exp.case pat body] | Pexp_fun (l, None, spat, sbody) -> - type_function ?in_function loc sexp.pexp_attributes env ty_expected_explained - l [Ast_helper.Exp.case spat sbody] + type_function ?in_function loc sexp.pexp_attributes env + ty_expected_explained l [Ast_helper.Exp.case spat sbody] | Pexp_function caselist -> type_function ?in_function loc sexp.pexp_attributes env ty_expected_explained Nolabel caselist @@ -2971,27 +2481,14 @@ and type_expect_ begin_def (); let arg = type_exp env sarg in end_def (); - if not (is_nonexpansive arg) then generalize_expansive env arg.exp_type; + if not (is_nonexpansive arg) then lower_contravariant env arg.exp_type; generalize arg.exp_type; - let rec split_cases vc ec = function - | [] -> List.rev vc, List.rev ec - | {pc_lhs = {ppat_desc=Ppat_exception p}} as c :: rest -> - split_cases vc ({c with pc_lhs = p} :: ec) rest - | c :: rest -> - split_cases (c :: vc) ec rest + let cases, partial = + type_cases ~exception_allowed:true env arg.exp_type ty_expected true loc + caselist in - let val_caselist, exn_caselist = split_cases [] [] caselist in - if val_caselist = [] && exn_caselist <> [] then - raise (Error (loc, env, No_value_clauses)); - (* Note: val_caselist = [] and exn_caselist = [], i.e. a fully - empty pattern matching can be generated by Camlp4 with its - revised syntax. Let's accept it for backward compatibility. *) - let val_cases, partial = - type_cases env arg.exp_type ty_expected true loc val_caselist in - let exn_cases, _ = - type_cases env Predef.type_exn ty_expected false loc exn_caselist in re { - exp_desc = Texp_match(arg, val_cases, exn_cases, partial); + exp_desc = Texp_match(arg, cases, partial); exp_loc = loc; exp_extra = []; exp_type = instance ty_expected; exp_attributes = sexp.pexp_attributes; @@ -3077,8 +2574,10 @@ and type_expect_ let get_path ty = try let (p0, p,_) = extract_concrete_record env ty in - (* XXX level may be wrong *) - Some (p0, p, ty.level = generic_level || not !Clflags.principal) + let principal = + (repr ty).level = generic_level || not !Clflags.principal + in + Some (p0, p, principal) with Not_found -> None in match get_path ty_expected with @@ -3221,7 +2720,7 @@ and type_expect_ rue { exp_desc = Texp_setfield(record, label_loc, label, newval); exp_loc = loc; exp_extra = []; - exp_type = instance_def Predef.type_unit; + exp_type = instance Predef.type_unit; exp_attributes = sexp.pexp_attributes; exp_env = env } | Pexp_array(sargl) -> @@ -3279,7 +2778,7 @@ and type_expect_ rue { exp_desc = Texp_while(cond, body); exp_loc = loc; exp_extra = []; - exp_type = instance_def Predef.type_unit; + exp_type = instance Predef.type_unit; exp_attributes = sexp.pexp_attributes; exp_env = env } | Pexp_for(param, slow, shigh, dir, sbody) -> @@ -3289,9 +2788,9 @@ and type_expect_ (mk_expected ~explanation:For_loop_stop_index Predef.type_int) in let id, new_env = match param.ppat_desc with - | Ppat_any -> Ident.create "_for", env + | Ppat_any -> Ident.create_local "_for", env | Ppat_var {txt} -> - Env.enter_value txt {val_type = instance_def Predef.type_int; + Env.enter_value txt {val_type = instance Predef.type_int; val_attributes = []; val_kind = Val_reg; Types.val_loc = loc; } env ~check:(fun s -> Warnings.Unused_for_index s) @@ -3302,22 +2801,17 @@ and type_expect_ rue { exp_desc = Texp_for(id, param, low, high, dir, body); exp_loc = loc; exp_extra = []; - exp_type = instance_def Predef.type_unit; + exp_type = instance Predef.type_unit; exp_attributes = sexp.pexp_attributes; exp_env = env } | Pexp_constraint (sarg, sty) -> - let separate = true in (* always separate, 1% slowdown for lablgtk *) - if separate then begin_def (); + (* Pretend separate = true, 1% slowdown for lablgtk *) + begin_def (); let cty = Typetexp.transl_simple_type env false sty in let ty = cty.ctyp_type in - let (arg, ty') = - if separate then begin - end_def (); - generalize_structure ty; - (type_argument env sarg ty (instance ty), instance ty) - end else - (type_argument env sarg ty ty, ty) - in + end_def (); + generalize_structure ty; + let (arg, ty') = (type_argument env sarg ty (instance ty), instance ty) in rue { exp_desc = arg.exp_desc; exp_loc = arg.exp_loc; @@ -3328,7 +2822,7 @@ and type_expect_ (Texp_constraint cty, loc, sexp.pexp_attributes) :: arg.exp_extra; } | Pexp_coerce(sarg, sty, sty') -> - let separate = true in (* always separate, 1% slowdown for lablgtk *) + (* Pretend separate = true, 1% slowdown for lablgtk *) (* Also see PR#7199 for a problem with the following: let separate = !Clflags.principal || Env.has_local_constraints env in*) let (arg, ty',cty,cty') = @@ -3338,18 +2832,12 @@ and type_expect_ Typetexp.transl_simple_type_delayed env sty' in let ty' = cty'.ctyp_type in - if separate then begin_def (); + begin_def (); let arg = type_exp env sarg in - let gen = - if separate then begin - end_def (); - let tv = newvar () in - let gen = generalizable tv.level arg.exp_type in - (try unify_var env tv arg.exp_type with Unify trace -> - raise(Error(arg.exp_loc, env, Expr_type_clash (trace, None)))); - gen - end else true - in + end_def (); + let tv = newvar () in + let gen = generalizable tv.level arg.exp_type in + unify_var env tv arg.exp_type; begin match arg.exp_desc, !self_coercion, (repr ty').desc with Texp_ident(_, _, {val_kind=Val_self _}), (path,r) :: _, Tconstr(path',_,_) when Path.same path path' -> @@ -3386,7 +2874,7 @@ and type_expect_ end; (arg, ty', None, cty') | Some sty -> - if separate then begin_def (); + begin_def (); let (cty, force) = Typetexp.transl_simple_type_delayed env sty and (cty', force') = @@ -3400,14 +2888,11 @@ and type_expect_ with Subtype (tr1, tr2) -> raise(Error(loc, env, Not_subtype(tr1, tr2))) end; - if separate then begin - end_def (); - generalize_structure ty; - generalize_structure ty'; - (type_argument env sarg ty (instance ty), - instance ty', Some cty, cty') - end else - (type_argument env sarg ty ty, ty', Some cty, cty') + end_def (); + generalize_structure ty; + generalize_structure ty'; + (type_argument env sarg ty (instance ty), + instance ty', Some cty, cty') in rue { exp_desc = arg.exp_desc; @@ -3456,30 +2941,34 @@ and type_expect_ let (obj_ty, res_ty) = filter_arrow env method_type Nolabel in unify env obj_ty desc.val_type; unify env res_ty (instance typ); + let method_desc = + {val_type = method_type; + val_kind = Val_reg; + val_attributes = []; + Types.val_loc = Location.none} + in + let exp_env = Env.add_value method_id method_desc env in let exp = Texp_apply({exp_desc = - Texp_ident(Path.Pident method_id, lid, - {val_type = method_type; - val_kind = Val_reg; - val_attributes = []; - Types.val_loc = Location.none}); + Texp_ident(Path.Pident method_id, + lid, method_desc); exp_loc = loc; exp_extra = []; exp_type = method_type; exp_attributes = []; (* check *) - exp_env = env}, + exp_env = exp_env}, [ Nolabel, Some {exp_desc = Texp_ident(path, lid, desc); exp_loc = obj.exp_loc; exp_extra = []; exp_type = desc.val_type; exp_attributes = []; (* check *) - exp_env = env} + exp_env = exp_env} ]) in (Tmeth_name met, Some (re {exp_desc = exp; exp_loc = loc; exp_extra = []; exp_type = typ; exp_attributes = []; (* check *) - exp_env = env}), typ) + exp_env = exp_env}), typ) | _ -> assert false end @@ -3502,7 +2991,7 @@ and type_expect_ snd (instance_poly false tl ty) | {desc = Tvar _} as ty -> let ty' = newvar () in - unify env (instance_def ty) (newty(Tpoly(ty',[]))); + unify env (instance ty) (newty(Tpoly(ty',[]))); (* if not !Clflags.nolabels then Location.prerr_warning loc (Warnings.Unknown_method met); *) ty' @@ -3541,7 +3030,7 @@ and type_expect_ rue { exp_desc = Texp_new (cl_path, cl, cl_decl); exp_loc = loc; exp_extra = []; - exp_type = instance_def ty; + exp_type = instance ty; exp_attributes = sexp.pexp_attributes; exp_env = env } end @@ -3559,7 +3048,7 @@ and type_expect_ rue { exp_desc = Texp_setinstvar(path_self, path, lab, newval); exp_loc = loc; exp_extra = []; - exp_type = instance_def Predef.type_unit; + exp_type = instance Predef.type_unit; exp_attributes = sexp.pexp_attributes; exp_env = env } | Val_ivar _ -> @@ -3621,31 +3110,29 @@ and type_expect_ let ty = newvar() in (* remember original level *) begin_def (); - Ident.set_current_time ty.level; let context = Typetexp.narrow () in let modl = !type_module env smodl in Mtype.lower_nongen ty.level modl.mod_type; - let (id, new_env) = Env.enter_module name.txt modl.mod_type env in - Ctype.init_def(Ident.current_time()); + let pres = + match modl.mod_type with + | Mty_alias _ -> Mp_absent + | _ -> Mp_present + in + let scope = create_scope () in + let (id, new_env) = + Env.enter_module ~scope name.txt pres modl.mod_type env + in Typetexp.widen context; + (* ideally, we should catch Expr_type_clash errors + in type_expect triggered by escaping identifiers from the local module + and refine them into Scoping_let_module errors + *) let body = type_expect new_env sbody ty_expected_explained in (* go back to original level *) end_def (); - (* Unification of body.exp_type with the fresh variable ty - fails if and only if the prefix condition is violated, - i.e. if generative types rooted at id show up in the - type body.exp_type. Thus, this unification enforces the - scoping condition on "let module". *) - (* Note that this code will only be reached if ty_expected - is a generic type variable, otherwise the error will occur - above in type_expect *) - begin try - Ctype.unify_var new_env ty body.exp_type - with Unify _ -> - raise(Error(loc, env, Scoping_let_module(name.txt, body.exp_type))) - end; + Ctype.unify_var new_env ty body.exp_type; re { - exp_desc = Texp_letmodule(id, name, modl, body); + exp_desc = Texp_letmodule(id, name, pres, modl, body); exp_loc = loc; exp_extra = []; exp_type = ty; exp_attributes = sexp.pexp_attributes; @@ -3668,7 +3155,7 @@ and type_expect_ | Texp_construct(_, {cstr_name="false"}, _) -> instance ty_expected | _ -> - instance_def Predef.type_unit + instance Predef.type_unit in rue { exp_desc = Texp_assert cond; @@ -3747,7 +3234,6 @@ and type_expect_ (* remember original level *) begin_def (); (* Create a fake abstract type declaration for name. *) - let level = get_current_level () in let decl = { type_params = []; type_arity = 0; @@ -3755,16 +3241,16 @@ and type_expect_ type_private = Public; type_manifest = None; type_variance = []; - type_newtype_level = Some (level, level); + type_is_newtype = true; + type_expansion_scope = Btype.lowest_level; type_loc = loc; type_attributes = []; type_immediate = false; type_unboxed = unboxed_false_default_false; } in - Ident.set_current_time ty.level; - let (id, new_env) = Env.enter_type name decl env in - Ctype.init_def(Ident.current_time()); + let scope = create_scope () in + let (id, new_env) = Env.enter_type ~scope name decl env in let body = type_exp new_env sbody in (* Replace every instance of this type constructor in the resulting @@ -3813,14 +3299,81 @@ and type_expect_ exp_type = newty (Tpackage (p, nl, tl')); exp_attributes = sexp.pexp_attributes; exp_env = env } - | Pexp_open (ovf, lid, e) -> - let (path, newenv) = !type_open ovf env sexp.pexp_loc lid in + | Pexp_open (od, e) -> + let (od, _, newenv) = !type_open_decl env od in let exp = type_expect newenv e ty_expected_explained in - { exp with - exp_extra = (Texp_open (ovf, path, lid, newenv), loc, - sexp.pexp_attributes) :: - exp.exp_extra; + rue { + exp_desc = Texp_open (od, exp); + exp_type = exp.exp_type; + exp_loc = loc; + exp_extra = []; + exp_attributes = sexp.pexp_attributes; + exp_env = env; } + | Pexp_letop{ let_ = slet; ands = sands; body = sbody } -> + let rec loop spat_acc ty_acc sands = + match sands with + | [] -> spat_acc, ty_acc + | { pbop_pat = spat; _} :: rest -> + let ty = newvar () in + let loc = { slet.pbop_op.loc with Location.loc_ghost = true } in + let spat_acc = Ast_helper.Pat.tuple ~loc [spat_acc; spat] in + let ty_acc = newty (Ttuple [ty_acc; ty]) in + loop spat_acc ty_acc rest + in + if !Clflags.principal then begin_def (); + let let_loc = slet.pbop_op.loc in + let op_path, op_desc = type_binding_op_ident env slet.pbop_op in + let op_type = instance op_desc.val_type in + let spat_params, ty_params = loop slet.pbop_pat (newvar ()) sands in + let ty_func_result = newvar () in + let ty_func = newty (Tarrow(Nolabel, ty_params, ty_func_result, Cok)) in + let ty_result = newvar () in + let ty_andops = newvar () in + let ty_op = + newty (Tarrow(Nolabel, ty_andops, + newty (Tarrow(Nolabel, ty_func, ty_result, Cok)), Cok)) + in + begin try + unify env op_type ty_op + with Unify trace -> + raise(Error(let_loc, env, Letop_type_clash(slet.pbop_op.txt, trace))) + end; + if !Clflags.principal then begin + end_def (); + generalize_structure ty_andops; + generalize_structure ty_params; + generalize_structure ty_func_result; + generalize_structure ty_result + end; + let exp, ands = type_andops env slet.pbop_exp sands ty_andops in + let scase = Ast_helper.Exp.case spat_params sbody in + let cases, partial = + type_cases env ty_params ty_func_result true loc [scase] + in + let body = + match cases with + | [case] -> case + | _ -> assert false + in + let param = name_cases "param" cases in + let let_ = + { bop_op_name = slet.pbop_op; + bop_op_path = op_path; + bop_op_val = op_desc; + bop_op_type = op_type; + bop_exp = exp; + bop_loc = slet.pbop_loc; } + in + let desc = + Texp_letop{let_; ands; param; body; partial} + in + rue { exp_desc = desc; + exp_loc = sexp.pexp_loc; + exp_extra = []; + exp_type = instance ty_result; + exp_env = env; + exp_attributes = sexp.pexp_attributes; } | Pexp_extension ({ txt = ("ocaml.extension_constructor" |"extension_constructor"); _ }, @@ -3837,7 +3390,7 @@ and type_expect_ rue { exp_desc = Texp_extension_constructor (lid, path); exp_loc = loc; exp_extra = []; - exp_type = instance_def Predef.type_extension_constructor; + exp_type = instance Predef.type_extension_constructor; exp_attributes = sexp.pexp_attributes; exp_env = env } | _ -> @@ -3853,6 +3406,61 @@ and type_expect_ exp_attributes = sexp.pexp_attributes; exp_env = env } +and type_ident env ?(recarg=Rejected) lid = + let (path, desc) = Typetexp.find_value env lid.loc lid.txt in + if !Clflags.annotations then begin + let dloc = desc.Types.val_loc in + let annot = + if dloc.Location.loc_ghost then Annot.Iref_external + else Annot.Iref_internal dloc + in + let name = Path.name ~paren:Oprint.parenthesized_ident path in + Stypes.record (Stypes.An_ident (lid.loc, name, annot)) + end; + let is_recarg = + match (repr desc.val_type).desc with + | Tconstr(p, _, _) -> Path.is_constructor_typath p + | _ -> false + in + begin match is_recarg, recarg, (repr desc.val_type).desc with + | _, Allowed, _ + | true, Required, _ + | false, Rejected, _ -> () + | true, Rejected, _ + | false, Required, (Tvar _ | Tconstr _) -> + raise (Error (lid.loc, env, Inlined_record_escape)) + | false, Required, _ -> () (* will fail later *) + end; + path, desc + +and type_binding_op_ident env s = + let loc = s.loc in + let lid = Location.mkloc (Longident.Lident s.txt) loc in + let path, desc = type_ident env lid in + let path = + match desc.val_kind with + | Val_ivar _ | Val_unbound Val_unbound_instance_variable -> + fatal_error "Illegal name for instance variable" + | Val_self (_, _, cl_num, _) -> + let path, _ = + Env.lookup_value (Longident.Lident ("self-" ^ cl_num)) env + in + path + | Val_unbound Val_unbound_ghost_recursive -> + let desc_loc = desc.Types.val_loc in + (* Only display the "missing rec" hint for non-ghost code *) + if not loc.Location.loc_ghost + && not desc_loc.Location.loc_ghost + then + raise Typetexp.(Error ( + loc, env, Unbound_value_missing_rec (lid.txt, desc_loc) + )) + else + raise Typetexp.(Error (loc, env, Unbound_value lid.txt)) + | _ -> path + in + path, desc + and type_function ?in_function loc attrs env ty_expected_explained l caselist = let { ty = ty_expected; explanation } = ty_expected_explained in let (loc_fun, ty_fun) = @@ -3898,7 +3506,7 @@ and type_function ?in_function loc attrs env ty_expected_explained l caselist = if is_optional l && not_function ty_res then Location.prerr_warning (List.hd cases).c_lhs.pat_loc Warnings.Unerasable_optional_argument; - let param = name_pattern "param" cases in + let param = name_cases "param" cases in re { exp_desc = Texp_function { arg_label = l; param; cases; partial; }; exp_loc = loc; exp_extra = []; @@ -3938,6 +3546,7 @@ and type_format loc str env = let mk_exp_loc pexp_desc = { pexp_desc = pexp_desc; pexp_loc = loc; + pexp_loc_stack = []; pexp_attributes = []; } and mk_lid_loc lid = { txt = lid; @@ -3951,7 +3560,7 @@ and type_format loc str env = | _ :: _ :: _ -> Some (mk_exp_loc (Pexp_tuple args)) in mk_exp_loc (Pexp_construct (mk_lid_loc lid, arg)) in let mk_cst cst = mk_exp_loc (Pexp_constant cst) in - let mk_int n = mk_cst (Pconst_integer (string_of_int n, None)) + let mk_int n = mk_cst (Pconst_integer (Int.to_string n, None)) and mk_string str = mk_cst (Pconst_string (str, None)) and mk_char chr = mk_cst (Pconst_char chr) in let rec mk_formatting_lit fmting = match fmting with @@ -3997,7 +3606,8 @@ and type_format loc str env = | Int_x -> mk_constr "Int_x" [] | Int_Cx -> mk_constr "Int_Cx" [] | Int_X -> mk_constr "Int_X" [] | Int_CX -> mk_constr "Int_CX" [] | Int_o -> mk_constr "Int_o" [] | Int_Co -> mk_constr "Int_Co" [] - | Int_u -> mk_constr "Int_u" [] + | Int_u -> mk_constr "Int_u" [] | Int_Cd -> mk_constr "Int_Cd" [] + | Int_Ci -> mk_constr "Int_Ci" [] | Int_Cu -> mk_constr "Int_Cu" [] and mk_fconv fconv = match fconv with | Float_f -> mk_constr "Float_f" [] | Float_pf -> mk_constr "Float_pf" [] @@ -4192,12 +3802,12 @@ and type_label_exp create env loc ty_expected generalize_structure ty_res end; begin try - unify env (instance_def ty_res) (instance ty_expected) + unify env (instance ty_res) (instance ty_expected) with Unify trace -> raise (Error(lid.loc, env, Label_mismatch(lid.txt, trace))) end; (* Instantiate so that we can generalize internal nodes *) - let ty_arg = instance_def ty_arg in + let ty_arg = instance ty_arg in if separate then begin end_def (); (* Generalize information merged from ty_expected *) @@ -4221,7 +3831,7 @@ and type_label_exp create env loc ty_expected begin_def (); let arg = type_exp env sarg in end_def (); - generalize_expansive env arg.exp_type; + lower_contravariant env arg.exp_type; unify_exp env arg ty_arg; check_univars env false "field value" arg label.lbl_arg vars; arg @@ -4240,7 +3850,7 @@ and type_argument ?recarg env sarg ty_expected' ty_expected = match sexp.pexp_desc with Pexp_ident _ | Pexp_apply _ | Pexp_field _ | Pexp_constraint _ | Pexp_coerce _ | Pexp_send _ | Pexp_new _ -> true - | Pexp_sequence (_, e) | Pexp_open (_, _, e) -> is_inferred e + | Pexp_sequence (_, e) | Pexp_open (_, e) -> is_inferred e | Pexp_ifthenelse (_, e1, Some e2) -> is_inferred e1 && is_inferred e2 | _ -> false in @@ -4278,17 +3888,20 @@ and type_argument ?recarg env sarg ty_expected' ty_expected = if args = [] then texp else (* eta-expand to avoid side effects *) let var_pair name ty = - let id = Ident.create name in + let id = Ident.create_local name in + let desc = + { val_type = ty; val_kind = Val_reg; + val_attributes = []; + Types.val_loc = Location.none} + in + let exp_env = Env.add_value id desc env in {pat_desc = Tpat_var (id, mknoloc name); pat_type = ty;pat_extra=[]; pat_attributes = []; pat_loc = Location.none; pat_env = env}, - {exp_type = ty; exp_loc = Location.none; exp_env = env; + {exp_type = ty; exp_loc = Location.none; exp_env = exp_env; exp_extra = []; exp_attributes = []; exp_desc = - Texp_ident(Path.Pident id, mknoloc (Longident.Lident name), - {val_type = ty; val_kind = Val_reg; - val_attributes = []; - Types.val_loc = Location.none})} + Texp_ident(Path.Pident id, mknoloc (Longident.Lident name), desc)} in let eta_pat, eta_var = var_pair "eta" ty_arg in let func texp = @@ -4299,7 +3912,7 @@ and type_argument ?recarg env sarg ty_expected' ty_expected = args @ [Nolabel, Some eta_var])} in let cases = [case eta_pat e] in - let param = name_pattern "param" cases in + let param = name_cases "param" cases in { texp with exp_type = ty_fun; exp_desc = Texp_function { arg_label = Nolabel; param; cases; partial = Total; } } @@ -4510,27 +4123,24 @@ and type_application env funct sargs = filter_arrow env (instance funct.exp_type) Nolabel in let exp = type_expect env sarg (mk_expected ty_arg) in - begin match (expand_head env exp.exp_type).desc with - | Tarrow _ -> - Location.prerr_warning exp.exp_loc Warnings.Partial_application - | Tvar _ -> - add_delayed_check (fun () -> check_application_result env false exp) - | _ -> () - end; + check_partial_application false exp; ([Nolabel, Some exp], ty_res) | _ -> - let ty = funct.exp_type in - if ignore_labels then - type_args [] [] ty (instance ty) ty [] sargs - else - type_args [] [] ty (instance ty) ty sargs [] + let ty = funct.exp_type in + if ignore_labels then + type_args [] [] ty (instance ty) ty [] sargs + else + type_args [] [] ty (instance ty) ty sargs [] and type_construct env loc lid sarg ty_expected_explained attrs = let { ty = ty_expected; explanation } = ty_expected_explained in let opath = try let (p0, p,_) = extract_concrete_variant env ty_expected in - Some(p0, p, ty_expected.level = generic_level || not !Clflags.principal) + let principal = + (repr ty_expected).level = generic_level || not !Clflags.principal + in + Some(p0, p, principal) with Not_found -> None in let constrs = Typetexp.find_all_constructors env lid.loc lid.txt in @@ -4539,7 +4149,7 @@ and type_construct env loc lid sarg ty_expected_explained attrs = ty_expected_explained (Constructor.disambiguate lid env opath) constrs in Env.mark_constructor Env.Positive env (Longident.last lid.txt) constr; - Builtin_attributes.check_deprecated loc constr.cstr_attributes + Builtin_attributes.check_alerts loc constr.cstr_attributes constr.cstr_name; let sargs = match sarg with @@ -4550,7 +4160,7 @@ and type_construct env loc lid sarg ty_expected_explained attrs = | Some se -> [se] in if List.length sargs <> constr.cstr_arity then raise(Error(loc, env, Constructor_arity_mismatch - (lid.txt, constr.cstr_arity, List.length sargs))); + (lid.txt, constr.cstr_arity, List.length sargs))); let separate = !Clflags.principal || Env.has_local_constraints env in if separate then (begin_def (); begin_def ()); let (ty_args, ty_res) = instance_constructor constr in @@ -4565,8 +4175,8 @@ and type_construct env loc lid sarg ty_expected_explained attrs = end_def (); generalize_structure ty_res; with_explanation explanation (fun () -> - unify_exp env {texp with exp_type = instance_def ty_res} - (instance ty_expected)); + unify_exp env {texp with exp_type = instance ty_res} + (instance ty_expected)); end_def (); List.iter generalize_structure ty_args; generalize_structure ty_res; @@ -4582,14 +4192,14 @@ and type_construct env loc lid sarg ty_expected_explained attrs = match constr.cstr_inlined with | None -> Rejected | Some _ -> - begin match sargs with - | [{pexp_desc = - Pexp_ident _ | - Pexp_record (_, (Some {pexp_desc = Pexp_ident _}| None))}] -> - Required - | _ -> - raise (Error(loc, env, Inlined_record_expected)) - end + begin match sargs with + | [{pexp_desc = + Pexp_ident _ | + Pexp_record (_, (Some {pexp_desc = Pexp_ident _}| None))}] -> + Required + | _ -> + raise (Error(loc, env, Inlined_record_expected)) + end in let args = List.map2 (fun e (t,t0) -> type_argument ~recarg env e t t0) sargs @@ -4609,33 +4219,21 @@ and type_statement ?explanation env sexp = end_def(); let ty = expand_head env exp.exp_type and tv = newvar() in if is_Tvar ty && ty.level > tv.level then - Location.prerr_warning loc Warnings.Nonreturning_statement; + Location.prerr_warning loc Warnings.Nonreturning_statement; if !Clflags.strict_sequence then - let expected_ty = instance_def Predef.type_unit in + let expected_ty = instance Predef.type_unit in with_explanation explanation (fun () -> unify_exp env exp expected_ty); exp else begin - begin match ty.desc with - | Tarrow _ -> - Location.prerr_warning loc Warnings.Partial_application - | Tconstr (p, _, _) when Path.same p Predef.path_unit -> () - | Tvar _ -> - add_delayed_check (fun () -> check_application_result env true exp) - | _ -> - Location.prerr_warning loc Warnings.Statement_type - end; + check_partial_application true exp; unify_var env tv ty; exp end (* Typing of match cases *) -and check_scope_escape loc env level ty = - try Ctype.check_scope_escape level ty - with Unify trace -> - raise(Error(loc, env, Pattern_type_clash(trace))) - -and type_cases ?in_function env ty_arg ty_res partial_flag loc caselist = +and type_cases ?exception_allowed ?in_function env ty_arg ty_res partial_flag + loc caselist = (* ty_arg is _fully_ generalized *) let patterns = List.map (fun {pc_lhs=p} -> p) caselist in let contains_polyvars = List.exists contains_polymorphic_variant patterns in @@ -4644,10 +4242,6 @@ and type_cases ?in_function env ty_arg ty_res partial_flag loc caselist = let ty_arg = if (may_contain_gadts || erase_either) && not !Clflags.principal then correct_levels ty_arg else ty_arg - and ty_res, env = - if may_contain_gadts && not !Clflags.principal then - correct_levels ty_res, duplicate_ident_types caselist env - else ty_res, env in let rec is_var spat = match spat.ppat_desc with @@ -4661,25 +4255,21 @@ and type_cases ?in_function env ty_arg ty_res partial_flag loc caselist = | _ -> true in let outer_level = get_current_level () in - if may_contain_gadts then begin_def (); - let lev = get_current_level () in - (* Do we need to propagate polymorphism *) - let propagate = - !Clflags.principal || may_contain_gadts || (repr ty_arg).level = generic_level || - match caselist with - [{pc_lhs}] when is_var pc_lhs -> false - | _ -> true in + let lev = + if may_contain_gadts then begin_def (); + get_current_level () + in let take_partial_instance = if !Clflags.principal || erase_either then Some false else None in - if propagate then begin_def (); (* propagation of the argument *) + begin_def (); (* propagation of the argument *) let pattern_force = ref [] in (* Format.printf "@[%i %i@ %a@]@." lev (get_current_level()) Printtyp.raw_type_expr ty_arg; *) - let pat_env_list = + let half_typed_cases = List.map - (fun {pc_lhs; pc_guard; pc_rhs} -> + (fun ({pc_lhs; pc_guard; pc_rhs} as case) -> let loc = let open Location in match pc_guard with @@ -4692,32 +4282,46 @@ and type_cases ?in_function env ty_arg ty_res partial_flag loc caselist = let ty_arg = instance ?partial:take_partial_instance ty_arg in end_def (); generalize_structure ty_arg; - let expected_ty_arg = instance ty_arg in - let (pat, ext_env, force, unpacks) = - type_pattern ~lev env pc_lhs scope expected_ty_arg + let (pat, ext_env, force, pvs, unpacks) = + type_pattern ?exception_allowed ~lev env pc_lhs scope ty_arg in pattern_force := force @ !pattern_force; let pat = if !Clflags.principal then begin end_def (); - iter_pattern (fun {pat_type=t} -> generalize_structure t) pat; + iter_pattern_variables_type generalize_structure pvs; { pat with pat_type = instance pat.pat_type } end else pat in (* Ensure that no ambivalent pattern type escapes its branch *) check_scope_escape pat.pat_loc env outer_level ty_arg; - (pat, ty_arg, (ext_env, unpacks))) + { typed_pat = pat; + pat_type_for_unif = ty_arg; + untyped_case = case; + branch_env = ext_env; + pat_vars = pvs; + unpacks; + contains_gadt = contains_gadt pat; } + ) caselist in + let patl = List.map (fun { typed_pat; _ } -> typed_pat) half_typed_cases in + let does_contain_gadt = + List.exists (fun { contains_gadt; _ } -> contains_gadt) half_typed_cases + in + let ty_res, duplicated_ident_types = + if does_contain_gadt && not !Clflags.principal then + correct_levels ty_res, duplicate_ident_types half_typed_cases env + else ty_res, duplicate_ident_types [] env + in (* Unify all cases (delayed to keep it order-free) *) let ty_arg' = newvar () in let unify_pats ty = - List.iter (fun (pat, pat_ty, _) -> + List.iter (fun { typed_pat = pat; pat_type_for_unif = pat_ty; _ } -> unify_pat_types pat.pat_loc env pat_ty ty - ) pat_env_list + ) half_typed_cases in unify_pats ty_arg'; (* Check for polymorphic variants to close *) - let patl = List.map (fun (pat, _, _) -> pat) pat_env_list in if List.exists has_variants patl then begin Parmatch.pressure_variants env patl; List.iter (iter_pattern finalize_variant) patl @@ -4726,20 +4330,32 @@ and type_cases ?in_function env ty_arg ty_res partial_flag loc caselist = List.iter (fun f -> f()) !pattern_force; (* Post-processing and generalization *) if take_partial_instance <> None then unify_pats (instance ty_arg); - if propagate then begin - List.iter - (fun (pat, _, (env, _)) -> - iter_pattern (fun {pat_type=t} -> unify_var env (newvar()) t) pat) - pat_env_list; - end_def (); - generalize ty_arg'; - List.iter (iter_pattern (fun {pat_type=t} -> generalize t)) patl; - end; + List.iter (fun { pat_vars; _ } -> + iter_pattern_variables_type (fun t -> unify_var env (newvar()) t) pat_vars + ) half_typed_cases; + end_def (); + generalize ty_arg'; + List.iter (fun { pat_vars; _ } -> + iter_pattern_variables_type generalize pat_vars + ) half_typed_cases; (* type bodies *) let in_function = if List.length caselist = 1 then in_function else None in let cases = - List.map2 - (fun (pat, _, (ext_env, unpacks)) {pc_lhs = _; pc_guard; pc_rhs} -> + List.map + (fun { typed_pat = pat; branch_env = ext_env; pat_vars = pvs; unpacks; + untyped_case = {pc_lhs = _; pc_guard; pc_rhs}; + contains_gadt; _ } -> + let ext_env = + if contains_gadt then + Env.do_copy_types duplicated_ident_types ext_env + else + ext_env + in + let ext_env = + add_pattern_variables ext_env pvs + ~check:(fun s -> Warnings.Unused_var_strict s) + ~check_as:(fun s -> Warnings.Unused_var s) + in let sexp = wrap_unpacks pc_rhs unpacks in let ty_res' = if !Clflags.principal then begin @@ -4748,7 +4364,12 @@ and type_cases ?in_function env ty_arg ty_res partial_flag loc caselist = end_def (); generalize_structure ty; ty end - else if contains_gadt pat then correct_levels ty_res + else if contains_gadt then + (* Even though we've already done that, apparently we need to do it + again. + stdlib/camlinternalFormat.ml:2288 is an example of use of this + call to [correct_levels]... *) + correct_levels ty_res else ty_res in (* Format.printf "@[%i %i, ty_res' =@ %a@]@." lev (get_current_level()) Printtyp.raw_type_expr ty_res'; *) @@ -4758,7 +4379,7 @@ and type_cases ?in_function env ty_arg ty_res partial_flag loc caselist = | Some scond -> Some (type_expect ext_env (wrap_unpacks scond unpacks) - (mk_expected Predef.type_bool)) + (mk_expected ~explanation:When_guard Predef.type_bool)) in let exp = type_expect ?in_function ext_env sexp (mk_expected ty_res') in @@ -4768,44 +4389,45 @@ and type_cases ?in_function env ty_arg ty_res partial_flag loc caselist = c_rhs = {exp with exp_type = instance ty_res'} } ) - pat_env_list caselist + half_typed_cases in - if !Clflags.principal || may_contain_gadts then begin + if !Clflags.principal || does_contain_gadt then begin let ty_res' = instance ty_res in List.iter (fun c -> unify_exp env c.c_rhs ty_res') cases end; - (* We could check whether there actually is a GADT here instead of reusing - [has_constructor], but I'm not sure it's worth it. *) let do_init = may_contain_gadts || needs_exhaust_check in - if do_init && not may_contain_gadts then begin_def (); - let lev = get_current_level () in let ty_arg_check = if do_init then (* Hack: use for_saving to copy variables too *) Subst.type_expr (Subst.for_saving Subst.identity) ty_arg' else ty_arg' in + let val_cases, exn_cases = split_cases env cases in + if val_cases = [] && exn_cases <> [] then + raise (Error (loc, env, No_value_clauses)); let partial = if partial_flag then - check_partial ~lev env (instance ty_arg_check) loc cases + check_partial ~lev env ty_arg_check loc val_cases else Partial in - let unused_check () = - begin_def (); - init_def lev; - List.iter (fun (pat, _, (env, _)) -> check_absent_variant env pat) - pat_env_list; - check_unused ~lev env (instance ty_arg_check) cases; - Parmatch.check_ambiguous_bindings cases; - end_def () + let unused_check delayed = + List.iter (fun { typed_pat; branch_env; _ } -> + check_absent_variant branch_env typed_pat + ) half_typed_cases; + if delayed then (begin_def (); init_def lev); + check_unused ~lev env ty_arg_check val_cases ; + check_unused ~lev env Predef.type_exn exn_cases ; + if delayed then end_def (); + Parmatch.check_ambiguous_bindings val_cases ; + Parmatch.check_ambiguous_bindings exn_cases in - if contains_polyvars || do_init then - add_delayed_check unused_check + if contains_polyvars then + add_delayed_check (fun () -> unused_check true) else - unused_check (); - (* Check for unused cases, do not delay because of gadts *) - if do_init then begin + (* Check for unused cases, do not delay because of gadts *) + unused_check false; + if may_contain_gadts then begin end_def (); (* Ensure that existential types do not escape *) unify_exp_types loc env (instance ty_res) (newvar ()) ; @@ -4814,8 +4436,10 @@ and type_cases ?in_function env ty_arg ty_res partial_flag loc caselist = (* Typing of let bindings *) -and type_let ?(check = fun s -> Warnings.Unused_var s) - ?(check_strict = fun s -> Warnings.Unused_var_strict s) +and type_let + ?(check = fun s -> Warnings.Unused_var s) + ?(check_strict = fun s -> Warnings.Unused_var_strict s) + existential_context env rec_flag spat_sexp_list scope allow = let open Ast_helper in begin_def(); @@ -4848,8 +4472,8 @@ and type_let ?(check = fun s -> Warnings.Unused_var s) | _ -> spat) spat_sexp_list in let nvs = List.map (fun _ -> newvar ()) spatl in - let (pat_list, new_env, force, unpacks) = - type_pattern_list env spatl scope nvs allow in + let (pat_list, new_env, force, pvs, unpacks) = + type_pattern_list existential_context env spatl scope nvs allow in let attrs_list = List.map fst spatl in let is_recursive = (rec_flag = Recursive) in (* If recursive, first unify with an approximation of the expression *) @@ -4876,16 +4500,40 @@ and type_let ?(check = fun s -> Warnings.Unused_var s) let pat_list = if !Clflags.principal then begin end_def (); - List.map - (fun pat -> - iter_pattern (fun pat -> generalize_structure pat.pat_type) pat; - {pat with pat_type = instance pat.pat_type}) - pat_list - end else pat_list in + iter_pattern_variables_type generalize_structure pvs; + List.map (fun pat -> + generalize_structure pat.pat_type; + {pat with pat_type = instance pat.pat_type} + ) pat_list + end else + pat_list + in (* Only bind pattern variables after generalizing *) List.iter (fun f -> f()) force; + let sexp_is_fun { pvb_expr = sexp; _ } = + match sexp.pexp_desc with + | Pexp_fun _ | Pexp_function _ -> true + | _ -> false + in let exp_env = - if is_recursive then new_env else env in + if is_recursive then new_env + else if List.for_all sexp_is_fun spat_sexp_list + then begin + (* Add ghost bindings to help detecting missing "rec" keywords. + + We only add those if the body of the definition is obviously a + function. The rationale is that, in other cases, the hint is probably + wrong (and the user is using "advanced features" anyway (lazy, + recursive values...)). + + [pvb_loc] (below) is the location of the first let-binding (in case of + a let .. and ..), and is where the missing "rec" hint suggests to add a + "rec" keyword. *) + match spat_sexp_list with + | {pvb_loc; _} :: _ -> maybe_add_pattern_variables_ghost pvb_loc env pvs + | _ -> assert false + end + else env in let current_slot = ref None in let rec_needed = ref false in @@ -4893,8 +4541,8 @@ and type_let ?(check = fun s -> Warnings.Unused_var s) List.exists (fun attrs -> Builtin_attributes.warning_scope ~ppwarning:false attrs (fun () -> - Warnings.is_active (check "") || Warnings.is_active (check_strict "") || - (is_recursive && (Warnings.is_active Warnings.Unused_rec_flag)))) + Warnings.is_active (check "") || Warnings.is_active (check_strict "") + || (is_recursive && (Warnings.is_active Warnings.Unused_rec_flag)))) attrs_list in let pat_slot_list = @@ -4925,7 +4573,8 @@ and type_let ?(check = fun s -> Warnings.Unused_var s) List.iter (fun id -> let vd = Env.find_value (Path.Pident id) new_env in - (* note: Env.find_value does not trigger the value_used event *) + (* note: Env.find_value does not trigger the value_used + event *) let name = Ident.name id in let used = ref false in if not (name = "" || name.[0] = '_' || name.[0] = '#') then @@ -4982,8 +4631,7 @@ and type_let ?(check = fun s -> Warnings.Unused_var s) type_expect exp_env sexp (mk_expected pat.pat_type))) spat_sexp_list pat_slot_list in current_slot := None; - if is_recursive && not !rec_needed - && Warnings.is_active Warnings.Unused_rec_flag then begin + if is_recursive && not !rec_needed then begin let {pvb_pat; pvb_attributes} = List.hd spat_sexp_list in (* See PR#6677 *) Builtin_attributes.warning_scope ~ppwarning:false pvb_attributes @@ -5001,15 +4649,26 @@ and type_let ?(check = fun s -> Warnings.Unused_var s) ) pat_list (List.map2 (fun (attrs, _) e -> attrs, e) spatl exp_list); + let pvs = List.map (fun pv -> { pv with pv_type = instance pv.pv_type}) pvs in end_def(); List.iter2 (fun pat exp -> if not (is_nonexpansive exp) then - iter_pattern (fun pat -> generalize_expansive env pat.pat_type) pat) + lower_contravariant env pat.pat_type) pat_list exp_list; - List.iter - (fun pat -> iter_pattern (fun pat -> generalize pat.pat_type) pat) - pat_list; + iter_pattern_variables_type generalize pvs; + (* The next line changes the toplevel experience from: + {[ + let _ = Array.get;; + - : '_weak1 array -> int -> '_weak1 = + ]} + to: + {[ + let _ = Array.get;; + - : 'a array -> int -> 'a = + ]} + *) + List.iter (fun exp -> generalize exp.exp_type) exp_list; let l = List.combine pat_list exp_list in let l = List.map2 @@ -5026,8 +4685,58 @@ and type_let ?(check = fun s -> Warnings.Unused_var s) | Tpat_alias ({pat_desc=Tpat_any}, _, _) -> () | _ -> raise(Error(pat.pat_loc, env, Illegal_letrec_pat))) l; + List.iter (function + | {vb_pat = {pat_desc = Tpat_any; pat_extra; _}; vb_expr; _} -> + if not (List.exists (function (Tpat_constraint _, _, _) -> true + | _ -> false) pat_extra) then + check_partial_application false vb_expr + | _ -> ()) l; (l, new_env, unpacks) +and type_andops env sarg sands expected_ty = + let rec loop env let_sarg rev_sands expected_ty = + match rev_sands with + | [] -> type_expect env let_sarg (mk_expected expected_ty), [] + | { pbop_op = sop; pbop_exp = sexp; pbop_loc = loc; _ } :: rest -> + if !Clflags.principal then begin_def (); + let op_path, op_desc = type_binding_op_ident env sop in + let op_type = instance op_desc.val_type in + let ty_arg = newvar () in + let ty_rest = newvar () in + let ty_result = newvar() in + let ty_rest_fun = newty (Tarrow(Nolabel, ty_arg, ty_result, Cok)) in + let ty_op = newty (Tarrow(Nolabel, ty_rest, ty_rest_fun, Cok)) in + begin try + unify env op_type ty_op + with Unify trace -> + raise(Error(sop.loc, env, Andop_type_clash(sop.txt, trace))) + end; + if !Clflags.principal then begin + end_def (); + generalize_structure ty_rest; + generalize_structure ty_arg; + generalize_structure ty_result + end; + let let_arg, rest = loop env let_sarg rest ty_rest in + let exp = type_expect env sexp (mk_expected ty_arg) in + begin try + unify env (instance ty_result) (instance expected_ty) + with Unify trace -> + raise(Error(loc, env, Bindings_type_clash(trace))) + end; + let andop = + { bop_op_name = sop; + bop_op_path = op_path; + bop_op_val = op_desc; + bop_op_type = op_type; + bop_exp = exp; + bop_loc = loc } + in + let_arg, andop :: rest + in + let let_arg, rev_ands = loop env sarg (List.rev sands) expected_ty in + let_arg, List.rev rev_ands + (* Typing of toplevel bindings *) let type_binding env rec_flag spat_sexp_list scope = @@ -5036,13 +4745,14 @@ let type_binding env rec_flag spat_sexp_list scope = type_let ~check:(fun s -> Warnings.Unused_value_declaration s) ~check_strict:(fun s -> Warnings.Unused_value_declaration s) + At_toplevel env rec_flag spat_sexp_list scope false in (pat_exp_list, new_env) -let type_let env rec_flag spat_sexp_list scope = +let type_let existential_ctx env rec_flag spat_sexp_list scope = let (pat_exp_list, new_env, _unpacks) = - type_let env rec_flag spat_sexp_list scope false in + type_let existential_ctx env rec_flag spat_sexp_list scope false in (pat_exp_list, new_env) (* Typing of toplevel expressions *) @@ -5052,7 +4762,7 @@ let type_expression env sexp = begin_def(); let exp = type_exp env sexp in end_def(); - if not (is_nonexpansive exp) then generalize_expansive env exp.exp_type; + if not (is_nonexpansive exp) then lower_contravariant env exp.exp_type; generalize exp.exp_type; match sexp.pexp_desc with Pexp_ident lid -> @@ -5094,6 +4804,8 @@ let report_type_expected_explanation expl ppf = fprintf ppf "the condition of an assertion" | Sequence_left_hand_side -> fprintf ppf "the left-hand side of a sequence" + | When_guard -> + fprintf ppf "a when-guard" let report_type_expected_explanation_opt expl ppf = match expl with @@ -5103,9 +4815,6 @@ let report_type_expected_explanation_opt expl ppf = (report_type_expected_explanation expl) let report_error env ppf = function - | Polymorphic_label lid -> - fprintf ppf "@[The record field %a is polymorphic.@ %s@]" - longident lid "You cannot instantiate it in a pattern." | Constructor_arity_mismatch(lid, expected, provided) -> fprintf ppf "@[The constructor %a@ expects %i argument(s),@ \ @@ -5310,15 +5019,37 @@ let report_error env ppf = function fprintf ppf "This expression is packed module, but the expected type is@ %a" type_expr ty - | Recursive_local_constraint trace -> - report_unification_error ppf env trace - (function ppf -> - fprintf ppf "Recursive local constraint when unifying") - (function ppf -> - fprintf ppf "with") - | Unexpected_existential -> - fprintf ppf - "Unexpected existential" + | Unexpected_existential (reason, name, types) -> ( + begin match reason with + | In_class_args -> + fprintf ppf "Existential types are not allowed in class arguments,@ " + | In_class_def -> + fprintf ppf "Existential types are not allowed in bindings inside \ + class definition,@ " + | In_self_pattern -> + fprintf ppf "Existential types are not allowed in self patterns,@ " + | At_toplevel -> + fprintf ppf + "Existential types are not allowed in toplevel bindings,@ " + | In_group -> + fprintf ppf + "Existential types are not allowed in \"let ... and ...\" bindings,\ + @ " + | In_rec -> + fprintf ppf + "Existential types are not allowed in recursive bindings,@ " + | With_attributes -> + fprintf ppf + "Existential types are not allowed in presence of attributes,@ " + end; + try + let example = List.find (fun ty -> ty <> "$" ^ name) types in + fprintf ppf + "but this pattern introduces the existential type %s." example + with Not_found -> + fprintf ppf + "but the constructor %s introduces existential types." name + ) | Invalid_interval -> fprintf ppf "@[Only character intervals are supported in patterns.@]" | Invalid_for_loop_index -> @@ -5327,9 +5058,13 @@ let report_error env ppf = function | No_value_clauses -> fprintf ppf "None of the patterns in this 'match' expression match values." - | Exception_pattern_below_toplevel -> + | Exception_pattern_disallowed -> fprintf ppf - "@[Exception patterns must be at the top level of a match case.@]" + "@[Exception patterns are not allowed in this position.@]" + | Mixed_value_and_exception_patterns_under_guard -> + fprintf ppf + "@[Mixing value and exception patterns under when-guards is not \ + supported.@]" | Inlined_record_escape -> fprintf ppf "@[This form is not allowed as the type of the inlined record could \ @@ -5362,6 +5097,24 @@ let report_error env ppf = function "This kind of expression is not allowed as right-hand side of `let rec'" | Illegal_class_expr -> fprintf ppf "This kind of recursive class expression is not allowed" + | Letop_type_clash(name, trace) -> + report_unification_error ppf env trace + (function ppf -> + fprintf ppf "The operator %s has type" name) + (function ppf -> + fprintf ppf "but it was expected to have type") + | Andop_type_clash(name, trace) -> + report_unification_error ppf env trace + (function ppf -> + fprintf ppf "The operator %s has type" name) + (function ppf -> + fprintf ppf "but it was expected to have type") + | Bindings_type_clash(trace) -> + report_unification_error ppf env trace + (function ppf -> + fprintf ppf "These bindings have type") + (function ppf -> + fprintf ppf "but bindings were expected of type") | Empty_pattern -> assert false let report_error env ppf err = @@ -5371,7 +5124,7 @@ let () = Location.register_error_of_exn (function | Error (loc, env, err) -> - Some (Location.error_of_printer loc (report_error env) err) + Some (Location.error_of_printer ~loc (report_error env) err) | Error_forward err -> Some err | _ -> diff --git a/typing/typecore.mli b/typing/typecore.mli index 30a0854a..08f865f1 100644 --- a/typing/typecore.mli +++ b/typing/typecore.mli @@ -37,6 +37,7 @@ type type_forcing_context = | For_loop_body | Assert_condition | Sequence_left_hand_side + | When_guard (* The combination of a type and a "type forcing context". The intent is that it describes a type that is "expected" (required) by the context. If unifying @@ -55,13 +56,22 @@ val mk_expected: val is_nonexpansive: Typedtree.expression -> bool +type existential_restriction = + | At_toplevel (** no existential types at the toplevel *) + | In_group (** nor with [let ... and ...] *) + | In_rec (** or recursive definition *) + | With_attributes (** or [let[@any_attribute] = ...] *) + | In_class_args (** or in class arguments [class c (...) = ...] *) + | In_class_def (** or in [class c = let ... in ...] *) + | In_self_pattern (** or in self pattern *) + val type_binding: Env.t -> rec_flag -> Parsetree.value_binding list -> Annot.ident option -> Typedtree.value_binding list * Env.t val type_let: - Env.t -> rec_flag -> + existential_restriction -> Env.t -> rec_flag -> Parsetree.value_binding list -> Annot.ident option -> Typedtree.value_binding list * Env.t @@ -69,7 +79,7 @@ val type_expression: Env.t -> Parsetree.expression -> Typedtree.expression val type_class_arg_pattern: string -> Env.t -> Env.t -> arg_label -> Parsetree.pattern -> - Typedtree.pattern * (Ident.t * string loc * Ident.t * type_expr) list * + Typedtree.pattern * (Ident.t * Ident.t * type_expr) list * Env.t * Env.t val type_self_pattern: string -> type_expr -> Env.t -> Env.t -> Env.t -> Parsetree.pattern -> @@ -100,25 +110,28 @@ val generalizable: int -> type_expr -> bool val reset_delayed_checks: unit -> unit val force_delayed_checks: unit -> unit -val name_pattern : string -> Typedtree.case list -> Ident.t +val name_pattern : string -> Typedtree.pattern list -> Ident.t + +val name_cases : string -> Typedtree.case list -> Ident.t val self_coercion : (Path.t * Location.t list ref) list ref type error = - Polymorphic_label of Longident.t | Constructor_arity_mismatch of Longident.t * int * int - | Label_mismatch of Longident.t * (type_expr * type_expr) list - | Pattern_type_clash of (type_expr * type_expr) list - | Or_pattern_type_clash of Ident.t * (type_expr * type_expr) list + | Label_mismatch of Longident.t * Ctype.Unification_trace.t + | Pattern_type_clash of Ctype.Unification_trace.t + | Or_pattern_type_clash of Ident.t * Ctype.Unification_trace.t | Multiply_bound_variable of string | Orpat_vars of Ident.t * Ident.t list - | Expr_type_clash of (type_expr * type_expr) list * type_forcing_context option + | Expr_type_clash of + Ctype.Unification_trace.t * type_forcing_context option | Apply_non_function of type_expr | Apply_wrong_label of arg_label * type_expr | Label_multiply_defined of string | Label_missing of Ident.t list | Label_not_mutable of Longident.t - | Wrong_name of string * type_expected * string * Path.t * string * string list + | Wrong_name of + string * type_expected * string * Path.t * string * string list | Name_type_mismatch of string * Longident.t * (Path.t * Path.t) * (Path.t * Path.t) list | Invalid_format of string @@ -129,27 +142,27 @@ type error = | Private_label of Longident.t * type_expr | Unbound_instance_variable of string * string list | Instance_variable_not_mutable of bool * string - | Not_subtype of (type_expr * type_expr) list * (type_expr * type_expr) list + | Not_subtype of Ctype.Unification_trace.t * Ctype.Unification_trace.t | Outside_class | Value_multiply_overridden of string | Coercion_failure of - type_expr * type_expr * (type_expr * type_expr) list * bool + type_expr * type_expr * Ctype.Unification_trace.t * bool | Too_many_arguments of bool * type_expr * type_forcing_context option | Abstract_wrong_label of arg_label * type_expr * type_forcing_context option | Scoping_let_module of string * type_expr | Masked_instance_variable of Longident.t | Not_a_variant_type of Longident.t | Incoherent_label_order - | Less_general of string * (type_expr * type_expr) list + | Less_general of string * Ctype.Unification_trace.t | Modules_not_allowed | Cannot_infer_signature | Not_a_packed_module of type_expr - | Recursive_local_constraint of (type_expr * type_expr) list - | Unexpected_existential + | Unexpected_existential of existential_restriction * string * string list | Invalid_interval | Invalid_for_loop_index | No_value_clauses - | Exception_pattern_below_toplevel + | Exception_pattern_disallowed + | Mixed_value_and_exception_patterns_under_guard | Inlined_record_escape | Inlined_record_expected | Unrefuted_pattern of Typedtree.pattern @@ -161,12 +174,15 @@ type error = | Illegal_letrec_expr | Illegal_class_expr | Empty_pattern + | Letop_type_clash of string * Ctype.Unification_trace.t + | Andop_type_clash of string * Ctype.Unification_trace.t + | Bindings_type_clash of Ctype.Unification_trace.t exception Error of Location.t * Env.t * error exception Error_forward of Location.error val report_error: Env.t -> formatter -> error -> unit - (* Deprecated. Use Location.{error_of_exn, report_error}. *) + (** @deprecated. Use {!Location.error_of_exn}, {!Location.print_report}. *) (* Forward declaration, to be filled in by Typemod.type_module *) val type_module: (Env.t -> Parsetree.module_expr -> Typedtree.module_expr) ref @@ -175,6 +191,11 @@ val type_open: (?used_slot:bool ref -> override_flag -> Env.t -> Location.t -> Longident.t loc -> Path.t * Env.t) ref +(* Forward declaration, to be filled in by Typemod.type_open_decl *) +val type_open_decl: + (?used_slot:bool ref -> Env.t -> Parsetree.open_declaration -> + Typedtree.open_declaration * Types.signature * Env.t) + ref (* Forward declaration, to be filled in by Typeclass.class_structure *) val type_object: (Env.t -> Location.t -> Parsetree.class_structure -> diff --git a/typing/typedecl.ml b/typing/typedecl.ml index 18e56e87..982a83e0 100644 --- a/typing/typedecl.ml +++ b/typing/typedecl.ml @@ -22,6 +22,8 @@ open Primitive open Types open Typetexp +module String = Misc.Stdlib.String + type native_repr_kind = Unboxed | Untagged type error = @@ -31,30 +33,29 @@ type error = | Duplicate_label of string | Recursive_abbrev of string | Cycle_in_def of string * type_expr - | Definition_mismatch of type_expr * Includecore.type_mismatch list + | Definition_mismatch of type_expr * Includecore.type_mismatch option | Constraint_failed of type_expr * type_expr - | Inconsistent_constraint of Env.t * (type_expr * type_expr) list - | Type_clash of Env.t * (type_expr * type_expr) list + | Inconsistent_constraint of Env.t * Ctype.Unification_trace.t + | Type_clash of Env.t * Ctype.Unification_trace.t | Parameters_differ of Path.t * type_expr * type_expr | Null_arity_external | Missing_native_external | Unbound_type_var of type_expr * type_declaration | Cannot_extend_private_type of Path.t | Not_extensible_type of Path.t - | Extension_mismatch of Path.t * Includecore.type_mismatch list - | Rebind_wrong_type of Longident.t * Env.t * (type_expr * type_expr) list + | Extension_mismatch of Path.t * Includecore.type_mismatch + | Rebind_wrong_type of Longident.t * Env.t * Ctype.Unification_trace.t | Rebind_mismatch of Longident.t * Path.t * Path.t | Rebind_private of Longident.t - | Bad_variance of int * (bool * bool * bool) * (bool * bool * bool) + | Variance of Typedecl_variance.error | Unavailable_type_constructor of Path.t | Bad_fixed_type of string | Unbound_type_var_ext of type_expr * extension_constructor - | Varying_anonymous | Val_in_structure | Multiple_native_repr_attributes | Cannot_unbox_or_untag_type of native_repr_kind | Deep_unbox_or_untag_attribute of native_repr_kind - | Bad_immediate_attribute + | Immediacy of Typedecl_immediacy.error | Bad_unboxed_attribute of string | Wrong_unboxed_type_float | Boxed_and_unboxed @@ -79,6 +80,10 @@ let get_unboxed_from_attributes sdecl = (* Enter all declared types in the environment as abstract types *) +let add_type ~check id decl env = + Builtin_attributes.warning_scope ~ppwarning:false decl.type_attributes + (fun () -> Env.add_type ~check id decl env) + let enter_type rec_flag env sdecl id = let needed = match rec_flag with @@ -104,14 +109,15 @@ let enter_type rec_flag env sdecl id = begin match sdecl.ptype_manifest with None -> None | Some _ -> Some(Ctype.newvar ()) end; type_variance = List.map (fun _ -> Variance.full) sdecl.ptype_params; - type_newtype_level = None; + type_is_newtype = false; + type_expansion_scope = Btype.lowest_level; type_loc = sdecl.ptype_loc; type_attributes = sdecl.ptype_attributes; type_immediate = false; type_unboxed = unboxed_false_default_false; } in - Env.add_type ~check:true id decl env + add_type ~check:true id decl env let update_type temp_env env id loc = let path = Path.Pident id in @@ -123,37 +129,8 @@ let update_type temp_env env id loc = with Ctype.Unify trace -> raise (Error(loc, Type_clash (env, trace))) -(* We use the Ctype.expand_head_opt version of expand_head to get access - to the manifest type of private abbreviations. *) -let rec get_unboxed_type_representation env ty fuel = - if fuel < 0 then None else - let ty = Ctype.repr (Ctype.expand_head_opt env ty) in - match ty.desc with - | Tconstr (p, args, _) -> - begin match Env.find_type p env with - | exception Not_found -> Some ty - | {type_immediate = true; _} -> Some Predef.type_int - | {type_unboxed = {unboxed = false}} -> Some ty - | {type_params; type_kind = - Type_record ([{ld_type = ty2; _}], _) - | Type_variant [{cd_args = Cstr_tuple [ty2]; _}] - | Type_variant [{cd_args = Cstr_record [{ld_type = ty2; _}]; _}]} - - -> - let ty2 = match ty2.desc with Tpoly (t, _) -> t | _ -> ty2 in - get_unboxed_type_representation env - (Ctype.apply env type_params ty2 args) (fuel - 1) - | {type_kind=Type_abstract} -> None - (* This case can occur when checking a recursive unboxed type - declaration. *) - | _ -> assert false (* only the above can be unboxed *) - end - | _ -> Some ty - -let get_unboxed_type_representation env ty = - (* Do not give too much fuel: PR#7424 *) - get_unboxed_type_representation env ty 100 -;; +let get_unboxed_type_representation = + Typedecl_unboxed.get_unboxed_type_representation (* Determine if a type's values are represented by floats at run-time. *) let is_float env ty = @@ -204,12 +181,6 @@ let set_fixed_row env loc p decl = (* Translate one type declaration *) -module StringSet = - Set.Make(struct - type t = string - let compare (x:t) y = compare x y - end) - let make_params env params = let make_param (sty, v) = try @@ -221,12 +192,12 @@ let make_params env params = let transl_labels env closed lbls = assert (lbls <> []); - let all_labels = ref StringSet.empty in + let all_labels = ref String.Set.empty in List.iter (fun {pld_name = {txt=name; loc}} -> - if StringSet.mem name !all_labels then + if String.Set.mem name !all_labels then raise(Error(loc, Duplicate_label name)); - all_labels := StringSet.add name !all_labels) + all_labels := String.Set.add name !all_labels) lbls; let mk {pld_name=name;pld_mutable=mut;pld_type=arg;pld_loc=loc; pld_attributes=attrs} = @@ -234,7 +205,8 @@ let transl_labels env closed lbls = (fun () -> let arg = Ast_helper.Typ.force_poly arg in let cty = transl_simple_type env closed arg in - {ld_id = Ident.create name.txt; ld_name = name; ld_mutable = mut; + {ld_id = Ident.create_local name.txt; + ld_name = name; ld_mutable = mut; ld_type = cty; ld_loc = loc; ld_attributes = attrs} ) in @@ -434,19 +406,19 @@ let transl_declaration env sdecl id = | (_,_,loc)::_ -> Location.prerr_warning loc Warnings.Constraint_on_gadt end; - let all_constrs = ref StringSet.empty in + let all_constrs = ref String.Set.empty in List.iter (fun {pcd_name = {txt = name}} -> - if StringSet.mem name !all_constrs then + if String.Set.mem name !all_constrs then raise(Error(sdecl.ptype_loc, Duplicate_constructor name)); - all_constrs := StringSet.add name !all_constrs) + all_constrs := String.Set.add name !all_constrs) scstrs; if List.length (List.filter (fun cd -> cd.pcd_args <> Pcstr_tuple []) scstrs) > (Config.max_tag + 1) then raise(Error(sdecl.ptype_loc, Too_many_constructors)); let make_cstr scstr = - let name = Ident.create scstr.pcd_name.txt in + let name = Ident.create_local scstr.pcd_name.txt in let targs, tret_type, args, ret_type, cstr_params = make_constructor env (Path.Pident id) params scstr.pcd_args scstr.pcd_res @@ -517,7 +489,8 @@ let transl_declaration env sdecl id = type_private = sdecl.ptype_private; type_manifest = man; type_variance = List.map (fun _ -> Variance.full) params; - type_newtype_level = None; + type_is_newtype = false; + type_expansion_scope = Btype.lowest_level; type_loc = sdecl.ptype_loc; type_attributes = sdecl.ptype_attributes; type_immediate = false; @@ -596,8 +569,6 @@ let rec check_constraints_rec env loc visited ty = Btype.iter_type_expr (check_constraints_rec env loc visited) ty end -module SMap = Map.Make(String) - let check_constraints_labels env visited l pl = let rec get_loc name = function [] -> assert false @@ -622,14 +593,14 @@ let check_constraints env sdecl (_, decl) = let pl = find_pl sdecl.ptype_kind in let pl_index = let foldf acc x = - SMap.add x.pcd_name.txt x acc + String.Map.add x.pcd_name.txt x acc in - List.fold_left foldf SMap.empty pl + List.fold_left foldf String.Map.empty pl in List.iter (fun {Types.cd_id=name; cd_args; cd_res} -> let {pcd_args; pcd_res; _} = - try SMap.find (Ident.name name) pl_index + try String.Map.find (Ident.name name) pl_index with Not_found -> assert false in begin match cd_args, pcd_args with | Cstr_tuple tyl, Pcstr_tuple styl -> @@ -670,7 +641,7 @@ let check_constraints env sdecl (_, decl) = need to check that the equation refers to a type of the same kind with the same constructors and labels. *) -let check_coherence env loc id decl = +let check_coherence env loc dpath decl = match decl with { type_kind = (Type_variant _ | Type_record _| Type_open); type_manifest = Some ty } -> @@ -680,29 +651,29 @@ let check_coherence env loc id decl = let decl' = Env.find_type path env in let err = if List.length args <> List.length decl.type_params - then [Includecore.Arity] + then Some Includecore.Arity else if not (Ctype.equal env false args decl.type_params) - then [Includecore.Constraint] + then Some Includecore.Constraint else Includecore.type_declarations ~loc ~equality:true env ~mark:true (Path.last path) decl' - id + dpath (Subst.type_declaration - (Subst.add_type id path Subst.identity) decl) + (Subst.add_type_path dpath path Subst.identity) decl) in - if err <> [] then + if err <> None then raise(Error(loc, Definition_mismatch (ty, err))) with Not_found -> raise(Error(loc, Unavailable_type_constructor path)) end - | _ -> raise(Error(loc, Definition_mismatch (ty, []))) + | _ -> raise(Error(loc, Definition_mismatch (ty, None))) end | _ -> () let check_abbrev env sdecl (id, decl) = - check_coherence env sdecl.ptype_loc id decl + check_coherence env sdecl.ptype_loc (Path.Pident id) decl (* Check that recursion is well-founded *) @@ -774,7 +745,7 @@ let check_well_founded_decl env loc path decl to_check = let it = {type_iterators with it_type_expr = (fun _ -> check_well_founded env loc path to_check)} in - it.it_type_declaration it (Ctype.instance_declaration decl) + it.it_type_declaration it (Ctype.generic_instance_declaration decl) (* Check for ill-defined abbrevs *) @@ -839,382 +810,6 @@ let check_abbrev_recursion env id_loc_list to_check tdecl = let id = tdecl.typ_id in check_recursion env (List.assoc id id_loc_list) (Path.Pident id) decl to_check -(* Compute variance *) - -let get_variance ty visited = - try TypeMap.find ty !visited with Not_found -> Variance.null - -let compute_variance env visited vari ty = - let rec compute_variance_rec vari ty = - (* Format.eprintf "%a: %x@." Printtyp.type_expr ty (Obj.magic vari); *) - let ty = Ctype.repr ty in - let vari' = get_variance ty visited in - if Variance.subset vari vari' then () else - let vari = Variance.union vari vari' in - visited := TypeMap.add ty vari !visited; - let compute_same = compute_variance_rec vari in - match ty.desc with - Tarrow (_, ty1, ty2, _) -> - let open Variance in - let v = conjugate vari in - let v1 = - if mem May_pos v || mem May_neg v - then set May_weak true v else v - in - compute_variance_rec v1 ty1; - compute_same ty2 - | Ttuple tl -> - List.iter compute_same tl - | Tconstr (path, tl, _) -> - let open Variance in - if tl = [] then () else begin - try - let decl = Env.find_type path env in - let cvari f = mem f vari in - List.iter2 - (fun ty v -> - let cv f = mem f v in - let strict = - cvari Inv && cv Inj || (cvari Pos || cvari Neg) && cv Inv - in - if strict then compute_variance_rec full ty else - let p1 = inter v vari - and n1 = inter v (conjugate vari) in - let v1 = - union (inter covariant (union p1 (conjugate p1))) - (inter (conjugate covariant) (union n1 (conjugate n1))) - and weak = - cvari May_weak && (cv May_pos || cv May_neg) || - (cvari May_pos || cvari May_neg) && cv May_weak - in - let v2 = set May_weak weak v1 in - compute_variance_rec v2 ty) - tl decl.type_variance - with Not_found -> - List.iter (compute_variance_rec may_inv) tl - end - | Tobject (ty, _) -> - compute_same ty - | Tfield (_, _, ty1, ty2) -> - compute_same ty1; - compute_same ty2 - | Tsubst ty -> - compute_same ty - | Tvariant row -> - let row = Btype.row_repr row in - List.iter - (fun (_,f) -> - match Btype.row_field_repr f with - Rpresent (Some ty) -> - compute_same ty - | Reither (_, tyl, _, _) -> - let open Variance in - let upper = - List.fold_left (fun s f -> set f true s) - null [May_pos; May_neg; May_weak] - in - let v = inter vari upper in - (* cf PR#7269: - if List.length tyl > 1 then upper else inter vari upper *) - List.iter (compute_variance_rec v) tyl - | _ -> ()) - row.row_fields; - compute_same row.row_more - | Tpoly (ty, _) -> - compute_same ty - | Tvar _ | Tnil | Tlink _ | Tunivar _ -> () - | Tpackage (_, _, tyl) -> - let v = - Variance.(if mem Pos vari || mem Neg vari then full else may_inv) - in - List.iter (compute_variance_rec v) tyl - in - compute_variance_rec vari ty - -let make p n i = - let open Variance in - set May_pos p (set May_neg n (set May_weak n (set Inj i null))) - -let compute_variance_type env check (required, loc) decl tyl = - (* Requirements *) - let required = - List.map (fun (c,n,i) -> if c || n then (c,n,i) else (true,true,i)) - required - in - (* Prepare *) - let params = List.map Btype.repr decl.type_params in - let tvl = ref TypeMap.empty in - (* Compute occurrences in the body *) - let open Variance in - List.iter - (fun (cn,ty) -> - compute_variance env tvl (if cn then full else covariant) ty) - tyl; - if check then begin - (* Check variance of parameters *) - let pos = ref 0 in - List.iter2 - (fun ty (c, n, i) -> - incr pos; - let var = get_variance ty tvl in - let (co,cn) = get_upper var and ij = mem Inj var in - if Btype.is_Tvar ty && (co && not c || cn && not n || not ij && i) - then raise (Error(loc, Bad_variance (!pos, (co,cn,ij), (c,n,i))))) - params required; - (* Check propagation from constrained parameters *) - let args = Btype.newgenty (Ttuple params) in - let fvl = Ctype.free_variables args in - let fvl = List.filter (fun v -> not (List.memq v params)) fvl in - (* If there are no extra variables there is nothing to do *) - if fvl = [] then () else - let tvl2 = ref TypeMap.empty in - List.iter2 - (fun ty (p,n,_) -> - if Btype.is_Tvar ty then () else - let v = - if p then if n then full else covariant else conjugate covariant in - compute_variance env tvl2 v ty) - params required; - let visited = ref TypeSet.empty in - let rec check ty = - let ty = Ctype.repr ty in - if TypeSet.mem ty !visited then () else - let visited' = TypeSet.add ty !visited in - visited := visited'; - let v1 = get_variance ty tvl in - let snap = Btype.snapshot () in - let v2 = - TypeMap.fold - (fun t vt v -> - if Ctype.equal env false [ty] [t] then union vt v else v) - !tvl2 null in - Btype.backtrack snap; - let (c1,n1) = get_upper v1 and (c2,n2,_,i2) = get_lower v2 in - if c1 && not c2 || n1 && not n2 then - if List.memq ty fvl then - let code = if not i2 then -2 else if c2 || n2 then -1 else -3 in - raise (Error (loc, Bad_variance (code, (c1,n1,false), (c2,n2,false)))) - else - Btype.iter_type_expr check ty - in - List.iter (fun (_,ty) -> check ty) tyl; - end; - List.map2 - (fun ty (p, n, i) -> - let v = get_variance ty tvl in - let tr = decl.type_private in - (* Use required variance where relevant *) - let concr = decl.type_kind <> Type_abstract (*|| tr = Type_new*) in - let (p, n) = - if tr = Private || not (Btype.is_Tvar ty) then (p, n) (* set *) - else (false, false) (* only check *) - and i = concr || i && tr = Private in - let v = union v (make p n i) in - let v = - if not concr then v else - if mem Pos v && mem Neg v then full else - if Btype.is_Tvar ty then v else - union v - (if p then if n then full else covariant else conjugate covariant) - in - if decl.type_kind = Type_abstract && tr = Public then v else - set May_weak (mem May_neg v) v) - params required - -let add_false = List.map (fun ty -> false, ty) - -(* A parameter is constrained if it is either instantiated, - or it is a variable appearing in another parameter *) -let constrained vars ty = - match ty.desc with - | Tvar _ -> List.exists (fun tl -> List.memq ty tl) vars - | _ -> true - -let for_constr = function - | Types.Cstr_tuple l -> add_false l - | Types.Cstr_record l -> - List.map - (fun {Types.ld_mutable; ld_type} -> (ld_mutable = Mutable, ld_type)) - l - -let compute_variance_gadt env check (required, loc as rloc) decl - (tl, ret_type_opt) = - match ret_type_opt with - | None -> - compute_variance_type env check rloc {decl with type_private = Private} - (for_constr tl) - | Some ret_type -> - match Ctype.repr ret_type with - | {desc=Tconstr (_, tyl, _)} -> - (* let tyl = List.map (Ctype.expand_head env) tyl in *) - let tyl = List.map Ctype.repr tyl in - let fvl = List.map (Ctype.free_variables ?env:None) tyl in - let _ = - List.fold_left2 - (fun (fv1,fv2) ty (c,n,_) -> - match fv2 with [] -> assert false - | fv :: fv2 -> - (* fv1 @ fv2 = free_variables of other parameters *) - if (c||n) && constrained (fv1 @ fv2) ty then - raise (Error(loc, Varying_anonymous)); - (fv :: fv1, fv2)) - ([], fvl) tyl required - in - compute_variance_type env check rloc - {decl with type_params = tyl; type_private = Private} - (for_constr tl) - | _ -> assert false - -let compute_variance_extension env check decl ext rloc = - compute_variance_gadt env check rloc - {decl with type_params = ext.ext_type_params} - (ext.ext_args, ext.ext_ret_type) - -let compute_variance_decl env check decl (required, _ as rloc) = - if (decl.type_kind = Type_abstract || decl.type_kind = Type_open) - && decl.type_manifest = None then - List.map - (fun (c, n, i) -> - make (not n) (not c) (decl.type_kind <> Type_abstract || i)) - required - else - let mn = - match decl.type_manifest with - None -> [] - | Some ty -> [false, ty] - in - match decl.type_kind with - Type_abstract | Type_open -> - compute_variance_type env check rloc decl mn - | Type_variant tll -> - if List.for_all (fun c -> c.Types.cd_res = None) tll then - compute_variance_type env check rloc decl - (mn @ List.flatten (List.map (fun c -> for_constr c.Types.cd_args) - tll)) - else begin - let mn = - List.map (fun (_,ty) -> (Types.Cstr_tuple [ty],None)) mn in - let tll = - mn @ List.map (fun c -> c.Types.cd_args, c.Types.cd_res) tll in - match List.map (compute_variance_gadt env check rloc decl) tll with - | vari :: rem -> - let varl = List.fold_left (List.map2 Variance.union) vari rem in - List.map - Variance.(fun v -> if mem Pos v && mem Neg v then full else v) - varl - | _ -> assert false - end - | Type_record (ftl, _) -> - compute_variance_type env check rloc decl - (mn @ List.map (fun {Types.ld_mutable; ld_type} -> - (ld_mutable = Mutable, ld_type)) ftl) - -let is_hash id = - let s = Ident.name id in - String.length s > 0 && s.[0] = '#' - -let marked_as_immediate decl = - Builtin_attributes.immediate decl.type_attributes - -let compute_immediacy env tdecl = - match (tdecl.type_kind, tdecl.type_manifest) with - | (Type_variant [{cd_args = Cstr_tuple [arg]; _}], _) - | (Type_variant [{cd_args = Cstr_record [{ld_type = arg; _}]; _}], _) - | (Type_record ([{ld_type = arg; _}], _), _) - when tdecl.type_unboxed.unboxed -> - begin match get_unboxed_type_representation env arg with - | Some argrepr -> not (Ctype.maybe_pointer_type env argrepr) - | None -> false - end - | (Type_variant (_ :: _ as cstrs), _) -> - not (List.exists (fun c -> c.Types.cd_args <> Types.Cstr_tuple []) cstrs) - | (Type_abstract, Some(typ)) -> - not (Ctype.maybe_pointer_type env typ) - | (Type_abstract, None) -> marked_as_immediate tdecl - | _ -> false - -(* Computes the fixpoint for the variance and immediacy of type declarations *) - -let rec compute_properties_fixpoint env decls required variances immediacies = - let new_decls = - List.map2 - (fun (id, decl) (variance, immediacy) -> - id, {decl with type_variance = variance; type_immediate = immediacy}) - decls (List.combine variances immediacies) - in - let new_env = - List.fold_right - (fun (id, decl) env -> Env.add_type ~check:true id decl env) - new_decls env - in - let new_variances = - List.map2 - (fun (_id, decl) -> compute_variance_decl new_env false decl) - new_decls required - in - let new_variances = - List.map2 (List.map2 Variance.union) new_variances variances in - let new_immediacies = - List.map - (fun (_id, decl) -> compute_immediacy new_env decl) - new_decls - in - if new_variances <> variances || new_immediacies <> immediacies then - compute_properties_fixpoint env decls required new_variances new_immediacies - else begin - (* List.iter (fun (id, decl) -> - Printf.eprintf "%s:" (Ident.name id); - List.iter (fun (v : Variance.t) -> - Printf.eprintf " %x" (Obj.magic v : int)) - decl.type_variance; - prerr_endline "") - new_decls; *) - List.iter (fun (_, decl) -> - if (marked_as_immediate decl) && (not decl.type_immediate) then - raise (Error (decl.type_loc, Bad_immediate_attribute)) - else ()) - new_decls; - List.iter2 - (fun (id, decl) req -> if not (is_hash id) then - ignore (compute_variance_decl new_env true decl req)) - new_decls required; - new_decls, new_env - end - -let init_variance (_id, decl) = - List.map (fun _ -> Variance.null) decl.type_params - -let add_injectivity = - List.map - (function - | Covariant -> (true, false, false) - | Contravariant -> (false, true, false) - | Invariant -> (false, false, false) - ) - -(* for typeclass.ml *) -let compute_variance_decls env cldecls = - let decls, required = - List.fold_right - (fun (obj_id, obj_abbr, _cl_abbr, _clty, _cltydef, ci) (decls, req) -> - let variance = List.map snd ci.ci_params in - (obj_id, obj_abbr) :: decls, - (add_injectivity variance, ci.ci_loc) :: req) - cldecls ([],[]) - in - let (decls, _) = - compute_properties_fixpoint env decls required - (List.map init_variance decls) - (List.map (fun _ -> false) decls) - in - List.map2 - (fun (_,decl) (_, _, cl_abbr, clty, cltydef, _) -> - let variance = decl.type_variance in - (decl, {cl_abbr with type_variance = variance}, - {clty with cty_variance = variance}, - {cltydef with clty_variance = variance})) - decls cldecls - (* Check multiple declarations of labels/constructors *) let check_duplicates sdecl_list = @@ -1262,8 +857,32 @@ let name_recursion sdecl id decl = else decl | _ -> decl +let name_recursion_decls sdecls decls = + List.map2 (fun sdecl (id, decl) -> (id, name_recursion sdecl id decl)) + sdecls decls + +(* Warn on definitions of type "type foo = ()" which redefine a different unit + type and are likely a mistake. *) +let check_redefined_unit (td: Parsetree.type_declaration) = + let open Parsetree in + let is_unit_constructor cd = cd.pcd_name.txt = "()" in + match td with + | { ptype_name = { txt = name }; + ptype_manifest = None; + ptype_kind = Ptype_variant [ cd ] } + when is_unit_constructor cd -> + Location.prerr_warning td.ptype_loc (Warnings.Redefining_unit name) + | _ -> + () + +let add_types_to_env decls env = + List.fold_right + (fun (id, decl) env -> add_type ~check:true id decl env) + decls env + (* Translate a set of type declarations, mutually recursive or not *) let transl_type_decl env rec_flag sdecl_list = + List.iter check_redefined_unit sdecl_list; (* Add dummy types for fixed rows *) let fixed_types = List.filter is_fixed_type sdecl_list in let sdecl_list = @@ -1278,16 +897,11 @@ let transl_type_decl env rec_flag sdecl_list = in (* Create identifiers. *) + let scope = Ctype.create_scope () in let id_list = - List.map (fun sdecl -> Ident.create sdecl.ptype_name.txt) sdecl_list + List.map (fun sdecl -> Ident.create_scoped ~scope sdecl.ptype_name.txt) + sdecl_list in - (* - Since we've introduced fresh idents, make sure the definition - level is at least the binding time of these events. Otherwise, - passing one of the recursively-defined type constrs as argument - to an abbreviation may fail. - *) - Ctype.init_def(Ident.current_time()); Ctype.begin_def(); (* Enter types. *) let temp_env = @@ -1331,17 +945,13 @@ let transl_type_decl env rec_flag sdecl_list = (* Check for duplicates *) check_duplicates sdecl_list; (* Build the final env. *) - let newenv = - List.fold_right - (fun (id, decl) env -> Env.add_type ~check:true id decl env) - decls env - in + let new_env = add_types_to_env decls env in (* Update stubs *) begin match rec_flag with | Asttypes.Nonrecursive -> () | Asttypes.Recursive -> List.iter2 - (fun id sdecl -> update_type temp_env newenv id sdecl.ptype_loc) + (fun id sdecl -> update_type temp_env new_env id sdecl.ptype_loc) id_list sdecl_list end; (* Generalize type declarations. *) @@ -1353,16 +963,16 @@ let transl_type_decl env rec_flag sdecl_list = id_list sdecl_list in List.iter (fun (id, decl) -> - check_well_founded_manifest newenv (List.assoc id id_loc_list) + check_well_founded_manifest new_env (List.assoc id id_loc_list) (Path.Pident id) decl) decls; let to_check = function Path.Pident id -> List.mem_assoc id id_loc_list | _ -> false in List.iter (fun (id, decl) -> - check_well_founded_decl newenv (List.assoc id id_loc_list) (Path.Pident id) + check_well_founded_decl new_env (List.assoc id id_loc_list) (Path.Pident id) decl to_check) decls; - List.iter (check_abbrev_recursion newenv id_loc_list to_check) tdecls; + List.iter (check_abbrev_recursion new_env id_loc_list to_check) tdecls; (* Check that all type variables are closed *) List.iter2 (fun sdecl tdecl -> @@ -1372,34 +982,28 @@ let transl_type_decl env rec_flag sdecl_list = | None -> ()) sdecl_list tdecls; (* Check that constraints are enforced *) - List.iter2 (check_constraints newenv) sdecl_list decls; - (* Name recursion *) + List.iter2 (check_constraints new_env) sdecl_list decls; + (* Add type properties to declarations *) let decls = - List.map2 (fun sdecl (id, decl) -> id, name_recursion sdecl id decl) - sdecl_list decls - in - (* Add variances to the environment *) - let required = - List.map - (fun sdecl -> - add_injectivity (List.map snd sdecl.ptype_params), - sdecl.ptype_loc - ) - sdecl_list - in - let final_decls, final_env = - compute_properties_fixpoint env decls required - (List.map init_variance decls) - (List.map (fun _ -> false) decls) + try + decls + |> name_recursion_decls sdecl_list + |> Typedecl_variance.update_decls env sdecl_list + |> Typedecl_immediacy.update_decls env + with + | Typedecl_variance.Error (loc, err) -> raise (Error (loc, Variance err)) + | Typedecl_immediacy.Error (loc, err) -> raise (Error (loc, Immediacy err)) in + (* Compute the final environment with variance and immediacy *) + let final_env = add_types_to_env decls env in (* Check re-exportation *) - List.iter2 (check_abbrev final_env) sdecl_list final_decls; + List.iter2 (check_abbrev final_env) sdecl_list decls; (* Keep original declaration *) let final_decls = List.map2 (fun tdecl (_id2, decl) -> { tdecl with typ_type = decl } - ) tdecls final_decls + ) tdecls decls in (* Done *) (final_decls, final_env) @@ -1408,7 +1012,8 @@ let transl_type_decl env rec_flag sdecl_list = let transl_extension_constructor env type_path type_params typext_params priv sext = - let id = Ident.create sext.pext_name.txt in + let scope = Ctype.create_scope () in + let id = Ident.create_scoped ~scope sext.pext_name.txt in let args, ret_type, kind = match sext.pext_kind with Pext_decl(sargs, sret_type) -> @@ -1499,7 +1104,7 @@ let transl_extension_constructor env type_path type_params List.iter2 (Ctype.unify env) decl.type_params tl; let lbls = match decl.type_kind with - | Type_record (lbls, Record_extension) -> lbls + | Type_record (lbls, Record_extension _) -> lbls | _ -> assert false in Types.Cstr_record lbls @@ -1563,16 +1168,18 @@ let transl_type_extension extend env loc styext = in let err = if type_decl.type_arity <> List.length styext.ptyext_params then - [Includecore.Arity] + Some Includecore.Arity else if List.for_all2 (fun (c1, n1, _) (c2, n2, _) -> (not c2 || c1) && (not n2 || n1)) type_variance - (add_injectivity (List.map snd styext.ptyext_params)) - then [] else [Includecore.Variance] + (Typedecl_variance.variance_of_params styext.ptyext_params) + then None else Some Includecore.Variance in - if err <> [] then - raise (Error(loc, Extension_mismatch (type_path, err))); + begin match err with + | None -> () + | Some err -> raise (Error(loc, Extension_mismatch (type_path, err))) + end; let ttype_params = make_params env styext.ptyext_params in let type_params = List.map (fun (cty, _) -> cty.ctyp_type) ttype_params in List.iter2 (Ctype.unify_var env) @@ -1602,8 +1209,14 @@ let transl_type_extension extend env loc styext = (* Check variances are correct *) List.iter (fun ext-> - ignore (compute_variance_extension env true type_decl - ext.ext_type (type_variance, loc))) + (* Note that [loc] here is distinct from [type_decl.type_loc], which + makes the [loc] parameter to this function useful. [loc] is the + location of the extension, while [type_decl] points to the original + type declaration being extended. *) + try Typedecl_variance.check_variance_extension + env type_decl ext (type_variance, loc) + with Typedecl_variance.Error (loc, err) -> + raise (Error (loc, Variance err))) constructors; (* Add extension constructors to the environment *) let newenv = @@ -1618,6 +1231,7 @@ let transl_type_extension extend env loc styext = tyext_params = ttype_params; tyext_constructors = constructors; tyext_private = styext.ptyext_private; + tyext_loc = styext.ptyext_loc; tyext_attributes = styext.ptyext_attributes; } in (tyext, newenv) @@ -1644,7 +1258,20 @@ let transl_exception env sext = | None -> () end; let newenv = Env.add_extension ~check:true ext.ext_id ext.ext_type env in - ext, newenv + ext, newenv + +let transl_type_exception env t = + Builtin_attributes.check_no_alert t.ptyexn_attributes; + let contructor, newenv = + Builtin_attributes.warning_scope t.ptyexn_attributes + (fun () -> + transl_exception env t.ptyexn_constructor + ) + in + {tyexn_constructor = contructor; + tyexn_loc = t.ptyexn_loc; + tyexn_attributes = t.ptyexn_attributes}, newenv + type native_repr_attribute = | Native_repr_attr_absent @@ -1727,15 +1354,25 @@ let rec parse_native_repr_attributes env core_type ty ~global_repr = let check_unboxable env loc ty = - let ty = Ctype.repr (Ctype.expand_head_opt env ty) in - try match ty.desc with - | Tconstr (p, _, _) -> - let tydecl = Env.find_type p env in - if tydecl.type_unboxed.unboxed then - Location.prerr_warning loc - (Warnings.Unboxable_type_in_prim_decl (Path.name p)) - | _ -> () - with Not_found -> () + let check_type acc ty : Path.Set.t = + let ty = Ctype.repr (Ctype.expand_head_opt env ty) in + try match ty.desc with + | Tconstr (p, _, _) -> + let tydecl = Env.find_type p env in + if tydecl.type_unboxed.default then + Path.Set.add p acc + else acc + | _ -> acc + with Not_found -> acc + in + let all_unboxable_types = Btype.fold_type_expr check_type Path.Set.empty ty in + Path.Set.fold + (fun p () -> + Location.prerr_warning loc + (Warnings.Unboxable_type_in_prim_decl (Path.name p)) + ) + all_unboxable_types + () (* Translate a value declaration *) let transl_value_decl env loc valdecl = @@ -1771,7 +1408,7 @@ let transl_value_decl env loc valdecl = && prim.prim_arity > 5 && prim.prim_native_name = "" then raise(Error(valdecl.pval_type.ptyp_loc, Missing_native_external)); - Btype.iter_type_expr (check_unboxable env loc) ty; + check_unboxable env loc ty; { val_type = ty; val_kind = Val_prim prim; Types.val_loc = loc; val_attributes = valdecl.pval_attributes } in @@ -1848,7 +1485,8 @@ let transl_with_constraint env id row_path orig_decl sdecl = type_private = priv; type_manifest = man; type_variance = []; - type_newtype_level = None; + type_is_newtype = false; + type_expansion_scope = Btype.lowest_level; type_loc = sdecl.ptype_loc; type_attributes = sdecl.ptype_attributes; type_immediate = false; @@ -1863,10 +1501,13 @@ let transl_with_constraint env id row_path orig_decl sdecl = end; let decl = name_recursion sdecl id decl in let type_variance = - compute_variance_decl env true decl - (add_injectivity (List.map snd sdecl.ptype_params), sdecl.ptype_loc) - in - let type_immediate = compute_immediacy env decl in + try Typedecl_variance.compute_decl + env ~check:true decl (Typedecl_variance.variance_of_sdecl sdecl) + with Typedecl_variance.Error (loc, err) -> + raise (Error (loc, Variance err)) in + let type_immediate = + (* Typedecl_immediacy.compute_decl never raises *) + Typedecl_immediacy.compute_decl env decl in let decl = {decl with type_variance; type_immediate} in Ctype.end_def(); generalize_decl decl; @@ -1896,7 +1537,8 @@ let abstract_type_decl arity = type_private = Public; type_manifest = None; type_variance = replicate_list Variance.full arity; - type_newtype_level = None; + type_is_newtype = false; + type_expansion_scope = Btype.lowest_level; type_loc = Location.none; type_attributes = []; type_immediate = false; @@ -1907,9 +1549,10 @@ let abstract_type_decl arity = decl let approx_type_decl sdecl_list = + let scope = Ctype.create_scope () in List.map (fun sdecl -> - (Ident.create sdecl.ptype_name.txt, + (Ident.create_scoped ~scope sdecl.ptype_name.txt, abstract_type_decl (List.length sdecl.ptype_params))) sdecl_list @@ -1919,10 +1562,12 @@ let approx_type_decl sdecl_list = let check_recmod_typedecl env loc recmod_ids path decl = (* recmod_ids is the list of recursively-defined module idents. (path, decl) is the type declaration to be checked. *) - let to_check path = - List.exists (fun id -> Path.isfree id path) recmod_ids in + let to_check path = Path.exists_free recmod_ids path in check_well_founded_decl env loc path decl to_check; - check_recursion env loc path decl to_check + check_recursion env loc path decl to_check; + (* additionally check coherece, as one might build an incoherent signature, + and use it to build an incoherent module, cf. #7851 *) + check_coherence env loc path decl (**** Error report ****) @@ -1987,25 +1632,35 @@ let report_error ppf = function Printtyp.reset_and_mark_loops ty; fprintf ppf "@[The definition of %s contains a cycle:@ %a@]" s Printtyp.type_expr ty - | Definition_mismatch (ty, errs) -> + | Definition_mismatch (ty, None) -> + Printtyp.reset_and_mark_loops ty; + fprintf ppf "@[@[%s@ %s@;<1 2>%a@]@]" + "This variant or record definition" "does not match that of type" + Printtyp.type_expr ty + | Definition_mismatch (ty, Some err) -> Printtyp.reset_and_mark_loops ty; fprintf ppf "@[@[%s@ %s@;<1 2>%a@]%a@]" "This variant or record definition" "does not match that of type" Printtyp.type_expr ty (Includecore.report_type_mismatch "the original" "this" "definition") - errs + err | Constraint_failed (ty, ty') -> Printtyp.reset_and_mark_loops ty; Printtyp.mark_loops ty'; + Printtyp.Naming_context.reset (); fprintf ppf "@[%s@ @[Type@ %a@ should be an instance of@ %a@]@]" "Constraints are not satisfied in this type." - Printtyp.type_expr ty Printtyp.type_expr ty' + !Oprint.out_type (Printtyp.tree_of_typexp false ty) + !Oprint.out_type (Printtyp.tree_of_typexp false ty') | Parameters_differ (path, ty, ty') -> Printtyp.reset_and_mark_loops ty; Printtyp.mark_loops ty'; + Printtyp.Naming_context.reset (); fprintf ppf "@[In the definition of %s, type@ %a@ should be@ %a@]" - (Path.name path) Printtyp.type_expr ty Printtyp.type_expr ty' + (Path.name path) + !Oprint.out_type (Printtyp.tree_of_typexp false ty) + !Oprint.out_type (Printtyp.tree_of_typexp false ty') | Inconsistent_constraint (env, trace) -> fprintf ppf "The type constraints are not consistent.@."; Printtyp.report_unification_error ppf env trace @@ -2034,7 +1689,7 @@ let report_error ppf = function ) "case" (fun ppf c -> fprintf ppf - "%s of %a" (Ident.name c.Types.cd_id) + "%a of %a" Printtyp.ident c.Types.cd_id Printtyp.constructor_arguments c.Types.cd_args) | Type_record (tl, _), _ -> explain_unbound ppf ty tl (fun l -> l.Types.ld_type) @@ -2056,13 +1711,13 @@ let report_error ppf = function "Type definition" Printtyp.path path "is not extensible" - | Extension_mismatch (path, errs) -> + | Extension_mismatch (path, err) -> fprintf ppf "@[@[%s@ %s@;<1 2>%s@]%a@]" "This extension" "does not match the definition of type" (Path.name path) (Includecore.report_type_mismatch "the type" "this extension" "definition") - errs + err | Rebind_wrong_type (lid, env, trace) -> Printtyp.report_unification_error ppf env trace (function ppf -> @@ -2082,7 +1737,7 @@ let report_error ppf = function "The constructor" Printtyp.longident lid "is private" - | Bad_variance (n, v1, v2) -> + | Variance (Typedecl_variance.Bad_variance (n, v1, v2)) -> let variance (p,n,i) = let inj = if i then "injective " else "" in match p, n with @@ -2099,6 +1754,7 @@ let report_error ppf = function | 3 when not teen -> "rd" | _ -> "th" in + (* FIXME: this test below is horrible, use a proper variant *) if n = -1 then fprintf ppf "@[%s@ %s@ It" "In this definition, a type variable has a variance that" @@ -2123,7 +1779,7 @@ let report_error ppf = function fprintf ppf "The definition of type %a@ is unavailable" Printtyp.path p | Bad_fixed_type r -> fprintf ppf "This fixed type %s" r - | Varying_anonymous -> + | Variance Typedecl_variance.Varying_anonymous -> fprintf ppf "@[%s@ %s@ %s@]" "In this GADT definition," "the variance of some parameter" "cannot be checked" @@ -2132,17 +1788,18 @@ let report_error ppf = function | Multiple_native_repr_attributes -> fprintf ppf "Too many [@@unboxed]/[@@untagged] attributes" | Cannot_unbox_or_untag_type Unboxed -> - fprintf ppf "Don't know how to unbox this type. Only float, int32, \ - int64 and nativeint can be unboxed" + fprintf ppf "@[Don't know how to unbox this type.@ \ + Only float, int32, int64 and nativeint can be unboxed.@]" | Cannot_unbox_or_untag_type Untagged -> - fprintf ppf "Don't know how to untag this type. Only int \ - can be untagged" + fprintf ppf "@[Don't know how to untag this type.@ \ + Only int can be untagged.@]" | Deep_unbox_or_untag_attribute kind -> fprintf ppf - "The attribute '%s' should be attached to a direct argument or \ - result of the primitive, it should not occur deeply into its type" + "@[The attribute '%s' should be attached to@ \ + a direct argument or result of the primitive,@ \ + it should not occur deeply into its type.@]" (match kind with Unboxed -> "@unboxed" | Untagged -> "@untagged") - | Bad_immediate_attribute -> + | Immediacy Typedecl_immediacy.Bad_immediate_attribute -> fprintf ppf "@[%s@ %s@]" "Types marked with the immediate attribute must be" "non-pointer types like int or bool" @@ -2162,7 +1819,7 @@ let () = Location.register_error_of_exn (function | Error (loc, err) -> - Some (Location.error_of_printer loc report_error err) + Some (Location.error_of_printer ~loc report_error err) | _ -> None ) diff --git a/typing/typedecl.mli b/typing/typedecl.mli index 1c687cd0..93b83471 100644 --- a/typing/typedecl.mli +++ b/typing/typedecl.mli @@ -23,8 +23,12 @@ val transl_type_decl: Typedtree.type_declaration list * Env.t val transl_exception: + Env.t -> Parsetree.extension_constructor -> + Typedtree.extension_constructor * Env.t + +val transl_type_exception: Env.t -> - Parsetree.extension_constructor -> Typedtree.extension_constructor * Env.t + Parsetree.type_exception -> Typedtree.type_exception * Env.t val transl_type_extension: bool -> Env.t -> Location.t -> Parsetree.type_extension -> @@ -45,24 +49,14 @@ val approx_type_decl: val check_recmod_typedecl: Env.t -> Location.t -> Ident.t list -> Path.t -> type_declaration -> unit val check_coherence: - Env.t -> Location.t -> Ident.t -> type_declaration -> unit + Env.t -> Location.t -> Path.t -> type_declaration -> unit (* for fixed types *) val is_fixed_type : Parsetree.type_declaration -> bool -(* for typeclass.ml *) -val compute_variance_decls: - Env.t -> - (Ident.t * Types.type_declaration * Types.type_declaration * - Types.class_declaration * Types.class_type_declaration * - 'a Typedtree.class_infos) list -> - (Types.type_declaration * Types.type_declaration * - Types.class_declaration * Types.class_type_declaration) list - (* for typeopt.ml *) val get_unboxed_type_representation: Env.t -> type_expr -> type_expr option - type native_repr_kind = Unboxed | Untagged type error = @@ -72,30 +66,29 @@ type error = | Duplicate_label of string | Recursive_abbrev of string | Cycle_in_def of string * type_expr - | Definition_mismatch of type_expr * Includecore.type_mismatch list + | Definition_mismatch of type_expr * Includecore.type_mismatch option | Constraint_failed of type_expr * type_expr - | Inconsistent_constraint of Env.t * (type_expr * type_expr) list - | Type_clash of Env.t * (type_expr * type_expr) list + | Inconsistent_constraint of Env.t * Ctype.Unification_trace.t + | Type_clash of Env.t * Ctype.Unification_trace.t | Parameters_differ of Path.t * type_expr * type_expr | Null_arity_external | Missing_native_external | Unbound_type_var of type_expr * type_declaration | Cannot_extend_private_type of Path.t | Not_extensible_type of Path.t - | Extension_mismatch of Path.t * Includecore.type_mismatch list - | Rebind_wrong_type of Longident.t * Env.t * (type_expr * type_expr) list + | Extension_mismatch of Path.t * Includecore.type_mismatch + | Rebind_wrong_type of Longident.t * Env.t * Ctype.Unification_trace.t | Rebind_mismatch of Longident.t * Path.t * Path.t | Rebind_private of Longident.t - | Bad_variance of int * (bool*bool*bool) * (bool*bool*bool) + | Variance of Typedecl_variance.error | Unavailable_type_constructor of Path.t | Bad_fixed_type of string | Unbound_type_var_ext of type_expr * extension_constructor - | Varying_anonymous | Val_in_structure | Multiple_native_repr_attributes | Cannot_unbox_or_untag_type of native_repr_kind | Deep_unbox_or_untag_attribute of native_repr_kind - | Bad_immediate_attribute + | Immediacy of Typedecl_immediacy.error | Bad_unboxed_attribute of string | Wrong_unboxed_type_float | Boxed_and_unboxed diff --git a/typing/typedecl_immediacy.ml b/typing/typedecl_immediacy.ml new file mode 100644 index 00000000..3bb6907a --- /dev/null +++ b/typing/typedecl_immediacy.ml @@ -0,0 +1,62 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Gabriel Scherer, projet Parsifal, INRIA Saclay *) +(* Rodolphe Lepigre, projet Deducteam, INRIA Saclay *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +open Types + +type error = Bad_immediate_attribute +exception Error of Location.t * error + +let marked_as_immediate decl = + Builtin_attributes.immediate decl.type_attributes + +let compute_decl env tdecl = + match (tdecl.type_kind, tdecl.type_manifest) with + | (Type_variant [{cd_args = Cstr_tuple [arg]; _}], _) + | (Type_variant [{cd_args = Cstr_record [{ld_type = arg; _}]; _}], _) + | (Type_record ([{ld_type = arg; _}], _), _) + when tdecl.type_unboxed.unboxed -> + begin match Typedecl_unboxed.get_unboxed_type_representation env arg with + | Some argrepr -> not (Ctype.maybe_pointer_type env argrepr) + | None -> false + end + | (Type_variant (_ :: _ as cstrs), _) -> + not (List.exists (fun c -> c.Types.cd_args <> Types.Cstr_tuple []) cstrs) + | (Type_abstract, Some(typ)) -> + not (Ctype.maybe_pointer_type env typ) + | (Type_abstract, None) -> marked_as_immediate tdecl + | _ -> false + +let property : (bool, unit) Typedecl_properties.property = + let open Typedecl_properties in + let eq = (=) in + let merge ~prop:_ ~new_prop = new_prop in + let default _decl = false in + let compute env decl () = compute_decl env decl in + let update_decl decl immediacy = { decl with type_immediate = immediacy } in + let check _env _id decl () = + if (marked_as_immediate decl) && (not decl.type_immediate) then + raise (Error (decl.type_loc, Bad_immediate_attribute)) in + { + eq; + merge; + default; + compute; + update_decl; + check; + } + +let update_decls env decls = + Typedecl_properties.compute_property_noreq property env decls diff --git a/typing/typedecl_immediacy.mli b/typing/typedecl_immediacy.mli new file mode 100644 index 00000000..6a9c3d91 --- /dev/null +++ b/typing/typedecl_immediacy.mli @@ -0,0 +1,27 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Gabriel Scherer, projet Parsifal, INRIA Saclay *) +(* Rodolphe Lepigre, projet Deducteam, INRIA Saclay *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +type error = Bad_immediate_attribute +exception Error of Location.t * error + +val compute_decl : Env.t -> Types.type_declaration -> bool + +val property : (bool, unit) Typedecl_properties.property + +val update_decls : + Env.t -> + (Ident.t * Typedecl_properties.decl) list -> + (Ident.t * Typedecl_properties.decl) list diff --git a/typing/typedecl_properties.ml b/typing/typedecl_properties.ml new file mode 100644 index 00000000..28a1bb66 --- /dev/null +++ b/typing/typedecl_properties.ml @@ -0,0 +1,73 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Gabriel Scherer, projet Parsifal, INRIA Saclay *) +(* Rodolphe Lepigre, projet Deducteam, INRIA Saclay *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +type decl = Types.type_declaration + +type ('prop, 'req) property = { + eq : 'prop -> 'prop -> bool; + merge : prop:'prop -> new_prop:'prop -> 'prop; + + default : decl -> 'prop; + compute : Env.t -> decl -> 'req -> 'prop; + update_decl : decl -> 'prop -> decl; + + check : Env.t -> Ident.t -> decl -> 'req -> unit; +} + +let add_type ~check id decl env = + let open Types in + Builtin_attributes.warning_scope ~ppwarning:false decl.type_attributes + (fun () -> Env.add_type ~check id decl env) + +let add_types_to_env decls env = + List.fold_right + (fun (id, decl) env -> add_type ~check:true id decl env) + decls env + +let compute_property +: ('prop, 'req) property -> Env.t -> + (Ident.t * decl) list -> 'req list -> (Ident.t * decl) list += fun property env decls required -> + (* [decls] and [required] must be lists of the same size, + with [required] containing the requirement for the corresponding + declaration in [decls]. *) + let props = List.map (fun (_id, decl) -> property.default decl) decls in + let rec compute_fixpoint props = + let new_decls = + List.map2 (fun (id, decl) prop -> + (id, property.update_decl decl prop)) + decls props in + let new_env = add_types_to_env new_decls env in + let new_props = + List.map2 + (fun (_id, decl) (prop, req) -> + let new_prop = property.compute new_env decl req in + property.merge ~prop ~new_prop) + new_decls (List.combine props required) in + if not (List.for_all2 property.eq props new_props) + then compute_fixpoint new_props + else begin + List.iter2 + (fun (id, decl) req -> property.check new_env id decl req) + new_decls required; + new_decls + end + in + compute_fixpoint props + +let compute_property_noreq property env decls = + let req = List.map (fun _ -> ()) decls in + compute_property property env decls req diff --git a/typing/typedecl_properties.mli b/typing/typedecl_properties.mli new file mode 100644 index 00000000..153c3f71 --- /dev/null +++ b/typing/typedecl_properties.mli @@ -0,0 +1,55 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Gabriel Scherer, projet Parsifal, INRIA Saclay *) +(* Rodolphe Lepigre, projet Deducteam, INRIA Saclay *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +type decl = Types.type_declaration + +(** An abstract interface for properties of type definitions, such as + variance and immediacy, that are computed by a fixpoint on + mutually-recursive type declarations. This interface contains all + the operations needed to initialize and run the fixpoint + computation, and then (optionally) check that the result is + consistent with the declaration or user expectations. *) + +type ('prop, 'req) property = { + eq : 'prop -> 'prop -> bool; + merge : prop:'prop -> new_prop:'prop -> 'prop; + + default : decl -> 'prop; + compute : Env.t -> decl -> 'req -> 'prop; + update_decl : decl -> 'prop -> decl; + + check : Env.t -> Ident.t -> decl -> 'req -> unit; +} +(** ['prop] represents the type of property values + ({!Types.Variance.t}, just 'bool' for immediacy, etc). + + ['req] represents the property value required by the author of the + declaration, if they gave an expectation: [type +'a t = ...]. + + Some properties have no natural notion of user requirement, or + their requirement is global, or already stored in + [type_declaration]; they can just use [unit] as ['req] parameter. *) + + +(** [compute_property prop env decls req] performs a fixpoint computation + to determine the final values of a property on a set of mutually-recursive + type declarations. The [req] argument must be a list of the same size as + [decls], providing the user requirement for each declaration. *) +val compute_property : ('prop, 'req) property -> Env.t -> + (Ident.t * decl) list -> 'req list -> (Ident.t * decl) list + +val compute_property_noreq : ('prop, unit) property -> Env.t -> + (Ident.t * decl) list -> (Ident.t * decl) list diff --git a/typing/typedecl_unboxed.ml b/typing/typedecl_unboxed.ml new file mode 100644 index 00000000..8a1f0e28 --- /dev/null +++ b/typing/typedecl_unboxed.ml @@ -0,0 +1,49 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Gabriel Scherer, projet Parsifal, INRIA Saclay *) +(* Rodolphe Lepigre, projet Deducteam, INRIA Saclay *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +open Types + +(* We use the Ctype.expand_head_opt version of expand_head to get access + to the manifest type of private abbreviations. *) +let rec get_unboxed_type_representation env ty fuel = + if fuel < 0 then None else + let ty = Ctype.repr (Ctype.expand_head_opt env ty) in + match ty.desc with + | Tconstr (p, args, _) -> + begin match Env.find_type p env with + | exception Not_found -> Some ty + | {type_immediate = true; _} -> Some Predef.type_int + | {type_unboxed = {unboxed = false}} -> Some ty + | {type_params; type_kind = + Type_record ([{ld_type = ty2; _}], _) + | Type_variant [{cd_args = Cstr_tuple [ty2]; _}] + | Type_variant [{cd_args = Cstr_record [{ld_type = ty2; _}]; _}]} + + -> + let ty2 = match ty2.desc with Tpoly (t, _) -> t | _ -> ty2 in + get_unboxed_type_representation env + (Ctype.apply env type_params ty2 args) (fuel - 1) + | {type_kind=Type_abstract} -> None + (* This case can occur when checking a recursive unboxed type + declaration. *) + | _ -> assert false (* only the above can be unboxed *) + end + | _ -> Some ty + +let get_unboxed_type_representation env ty = + (* Do not give too much fuel: PR#7424 *) + get_unboxed_type_representation env ty 100 +;; diff --git a/typing/typedecl_unboxed.mli b/typing/typedecl_unboxed.mli new file mode 100644 index 00000000..88a056de --- /dev/null +++ b/typing/typedecl_unboxed.mli @@ -0,0 +1,4 @@ +open Types + +(* for typeopt.ml *) +val get_unboxed_type_representation: Env.t -> type_expr -> type_expr option diff --git a/typing/typedecl_variance.ml b/typing/typedecl_variance.ml new file mode 100644 index 00000000..1e9a48c6 --- /dev/null +++ b/typing/typedecl_variance.ml @@ -0,0 +1,372 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Gabriel Scherer, projet Parsifal, INRIA Saclay *) +(* Rodolphe Lepigre, projet Deducteam, INRIA Saclay *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +open Asttypes +open Types + +module TypeSet = Btype.TypeSet +module TypeMap = Btype.TypeMap + +type surface_variance = bool * bool * bool + +type error = +| Bad_variance of int * surface_variance * surface_variance +| Varying_anonymous + +exception Error of Location.t * error + +(* Compute variance *) + +let get_variance ty visited = + try TypeMap.find ty !visited with Not_found -> Variance.null + +let compute_variance env visited vari ty = + let rec compute_variance_rec vari ty = + (* Format.eprintf "%a: %x@." Printtyp.type_expr ty (Obj.magic vari); *) + let ty = Ctype.repr ty in + let vari' = get_variance ty visited in + if Variance.subset vari vari' then () else + let vari = Variance.union vari vari' in + visited := TypeMap.add ty vari !visited; + let compute_same = compute_variance_rec vari in + match ty.desc with + Tarrow (_, ty1, ty2, _) -> + let open Variance in + let v = conjugate vari in + let v1 = + if mem May_pos v || mem May_neg v + then set May_weak true v else v + in + compute_variance_rec v1 ty1; + compute_same ty2 + | Ttuple tl -> + List.iter compute_same tl + | Tconstr (path, tl, _) -> + let open Variance in + if tl = [] then () else begin + try + let decl = Env.find_type path env in + let cvari f = mem f vari in + List.iter2 + (fun ty v -> + let cv f = mem f v in + let strict = + cvari Inv && cv Inj || (cvari Pos || cvari Neg) && cv Inv + in + if strict then compute_variance_rec full ty else + let p1 = inter v vari + and n1 = inter v (conjugate vari) in + let v1 = + union (inter covariant (union p1 (conjugate p1))) + (inter (conjugate covariant) (union n1 (conjugate n1))) + and weak = + cvari May_weak && (cv May_pos || cv May_neg) || + (cvari May_pos || cvari May_neg) && cv May_weak + in + let v2 = set May_weak weak v1 in + compute_variance_rec v2 ty) + tl decl.type_variance + with Not_found -> + List.iter (compute_variance_rec may_inv) tl + end + | Tobject (ty, _) -> + compute_same ty + | Tfield (_, _, ty1, ty2) -> + compute_same ty1; + compute_same ty2 + | Tsubst ty -> + compute_same ty + | Tvariant row -> + let row = Btype.row_repr row in + List.iter + (fun (_,f) -> + match Btype.row_field_repr f with + Rpresent (Some ty) -> + compute_same ty + | Reither (_, tyl, _, _) -> + let open Variance in + let upper = + List.fold_left (fun s f -> set f true s) + null [May_pos; May_neg; May_weak] + in + let v = inter vari upper in + (* cf PR#7269: + if List.length tyl > 1 then upper else inter vari upper *) + List.iter (compute_variance_rec v) tyl + | _ -> ()) + row.row_fields; + compute_same row.row_more + | Tpoly (ty, _) -> + compute_same ty + | Tvar _ | Tnil | Tlink _ | Tunivar _ -> () + | Tpackage (_, _, tyl) -> + let v = + Variance.(if mem Pos vari || mem Neg vari then full else may_inv) + in + List.iter (compute_variance_rec v) tyl + in + compute_variance_rec vari ty + +let make p n i = + let open Variance in + set May_pos p (set May_neg n (set May_weak n (set Inj i null))) + +let compute_variance_type env ~check (required, loc) decl tyl = + (* Requirements *) + let required = + List.map (fun (c,n,i) -> if c || n then (c,n,i) else (true,true,i)) + required + in + (* Prepare *) + let params = List.map Btype.repr decl.type_params in + let tvl = ref TypeMap.empty in + (* Compute occurrences in the body *) + let open Variance in + List.iter + (fun (cn,ty) -> + compute_variance env tvl (if cn then full else covariant) ty) + tyl; + if check then begin + (* Check variance of parameters *) + let pos = ref 0 in + List.iter2 + (fun ty (c, n, i) -> + incr pos; + let var = get_variance ty tvl in + let (co,cn) = get_upper var and ij = mem Inj var in + if Btype.is_Tvar ty && (co && not c || cn && not n || not ij && i) + then raise (Error(loc, Bad_variance (!pos, (co,cn,ij), (c,n,i))))) + params required; + (* Check propagation from constrained parameters *) + let args = Btype.newgenty (Ttuple params) in + let fvl = Ctype.free_variables args in + let fvl = List.filter (fun v -> not (List.memq v params)) fvl in + (* If there are no extra variables there is nothing to do *) + if fvl = [] then () else + let tvl2 = ref TypeMap.empty in + List.iter2 + (fun ty (p,n,_) -> + if Btype.is_Tvar ty then () else + let v = + if p then if n then full else covariant else conjugate covariant in + compute_variance env tvl2 v ty) + params required; + let visited = ref TypeSet.empty in + let rec check ty = + let ty = Ctype.repr ty in + if TypeSet.mem ty !visited then () else + let visited' = TypeSet.add ty !visited in + visited := visited'; + let v1 = get_variance ty tvl in + let snap = Btype.snapshot () in + let v2 = + TypeMap.fold + (fun t vt v -> + if Ctype.equal env false [ty] [t] then union vt v else v) + !tvl2 null in + Btype.backtrack snap; + let (c1,n1) = get_upper v1 and (c2,n2,_,i2) = get_lower v2 in + if c1 && not c2 || n1 && not n2 then + if List.memq ty fvl then + let code = if not i2 then -2 else if c2 || n2 then -1 else -3 in + raise (Error (loc, Bad_variance (code, (c1,n1,false), (c2,n2,false)))) + else + Btype.iter_type_expr check ty + in + List.iter (fun (_,ty) -> check ty) tyl; + end; + List.map2 + (fun ty (p, n, i) -> + let v = get_variance ty tvl in + let tr = decl.type_private in + (* Use required variance where relevant *) + let concr = decl.type_kind <> Type_abstract (*|| tr = Type_new*) in + let (p, n) = + if tr = Private || not (Btype.is_Tvar ty) then (p, n) (* set *) + else (false, false) (* only check *) + and i = concr || i && tr = Private in + let v = union v (make p n i) in + let v = + if not concr then v else + if mem Pos v && mem Neg v then full else + if Btype.is_Tvar ty then v else + union v + (if p then if n then full else covariant else conjugate covariant) + in + if decl.type_kind = Type_abstract && tr = Public then v else + set May_weak (mem May_neg v) v) + params required + +let add_false = List.map (fun ty -> false, ty) + +(* A parameter is constrained if it is either instantiated, + or it is a variable appearing in another parameter *) +let constrained vars ty = + match ty.desc with + | Tvar _ -> List.exists (fun tl -> List.memq ty tl) vars + | _ -> true + +let for_constr = function + | Types.Cstr_tuple l -> add_false l + | Types.Cstr_record l -> + List.map + (fun {Types.ld_mutable; ld_type} -> (ld_mutable = Mutable, ld_type)) + l + +let compute_variance_gadt env ~check (required, loc as rloc) decl + (tl, ret_type_opt) = + match ret_type_opt with + | None -> + compute_variance_type env ~check rloc {decl with type_private = Private} + (for_constr tl) + | Some ret_type -> + match Ctype.repr ret_type with + | {desc=Tconstr (_, tyl, _)} -> + (* let tyl = List.map (Ctype.expand_head env) tyl in *) + let tyl = List.map Ctype.repr tyl in + let fvl = List.map (Ctype.free_variables ?env:None) tyl in + let _ = + List.fold_left2 + (fun (fv1,fv2) ty (c,n,_) -> + match fv2 with [] -> assert false + | fv :: fv2 -> + (* fv1 @ fv2 = free_variables of other parameters *) + if (c||n) && constrained (fv1 @ fv2) ty then + raise (Error(loc, Varying_anonymous)); + (fv :: fv1, fv2)) + ([], fvl) tyl required + in + compute_variance_type env ~check rloc + {decl with type_params = tyl; type_private = Private} + (for_constr tl) + | _ -> assert false + +let compute_variance_extension env ~check decl ext rloc = + compute_variance_gadt env ~check rloc + {decl with type_params = ext.ext_type_params} + (ext.ext_args, ext.ext_ret_type) + +let compute_variance_decl env ~check decl (required, _ as rloc) = + if (decl.type_kind = Type_abstract || decl.type_kind = Type_open) + && decl.type_manifest = None then + List.map + (fun (c, n, i) -> + make (not n) (not c) (decl.type_kind <> Type_abstract || i)) + required + else + let mn = + match decl.type_manifest with + None -> [] + | Some ty -> [false, ty] + in + match decl.type_kind with + Type_abstract | Type_open -> + compute_variance_type env ~check rloc decl mn + | Type_variant tll -> + if List.for_all (fun c -> c.Types.cd_res = None) tll then + compute_variance_type env ~check rloc decl + (mn @ List.flatten (List.map (fun c -> for_constr c.Types.cd_args) + tll)) + else begin + let mn = + List.map (fun (_,ty) -> (Types.Cstr_tuple [ty],None)) mn in + let tll = + mn @ List.map (fun c -> c.Types.cd_args, c.Types.cd_res) tll in + match List.map (compute_variance_gadt env ~check rloc decl) tll with + | vari :: rem -> + let varl = List.fold_left (List.map2 Variance.union) vari rem in + List.map + Variance.(fun v -> if mem Pos v && mem Neg v then full else v) + varl + | _ -> assert false + end + | Type_record (ftl, _) -> + compute_variance_type env ~check rloc decl + (mn @ List.map (fun {Types.ld_mutable; ld_type} -> + (ld_mutable = Mutable, ld_type)) ftl) + +let is_hash id = + let s = Ident.name id in + String.length s > 0 && s.[0] = '#' + +let check_variance_extension env decl ext rloc = + (* TODO: refactorize compute_variance_extension *) + ignore (compute_variance_extension env ~check:true decl + ext.Typedtree.ext_type rloc) + +let compute_decl env ~check decl req = + compute_variance_decl env ~check decl (req, decl.type_loc) + +let check_decl env decl req = + ignore (compute_variance_decl env ~check:true decl (req, decl.type_loc)) + +type prop = Variance.t list +type req = surface_variance list +let property : (prop, req) Typedecl_properties.property = + let open Typedecl_properties in + let eq li1 li2 = + try List.for_all2 Variance.eq li1 li2 with _ -> false in + let merge ~prop ~new_prop = + List.map2 Variance.union prop new_prop in + let default decl = + List.map (fun _ -> Variance.null) decl.type_params in + let compute env decl req = + compute_decl env ~check:false decl req in + let update_decl decl variance = + { decl with type_variance = variance } in + let check env id decl req = + if is_hash id then () else check_decl env decl req in + { + eq; + merge; + default; + compute; + update_decl; + check; + } + +let transl_variance : Asttypes.variance -> _ = function + | Covariant -> (true, false, false) + | Contravariant -> (false, true, false) + | Invariant -> (false, false, false) + +let variance_of_params ptype_params = + List.map transl_variance (List.map snd ptype_params) + +let variance_of_sdecl sdecl = + variance_of_params sdecl.Parsetree.ptype_params + +let update_decls env sdecls decls = + let required = List.map variance_of_sdecl sdecls in + Typedecl_properties.compute_property property env decls required + +let update_class_decls env cldecls = + let decls, required = + List.fold_right + (fun (obj_id, obj_abbr, _cl_abbr, _clty, _cltydef, ci) (decls, req) -> + (obj_id, obj_abbr) :: decls, + variance_of_params ci.Typedtree.ci_params :: req) + cldecls ([],[]) + in + let decls = + Typedecl_properties.compute_property property env decls required in + List.map2 + (fun (_,decl) (_, _, cl_abbr, clty, cltydef, _) -> + let variance = decl.type_variance in + (decl, {cl_abbr with type_variance = variance}, + {clty with cty_variance = variance}, + {cltydef with clty_variance = variance})) + decls cldecls diff --git a/typing/typedecl_variance.mli b/typing/typedecl_variance.mli new file mode 100644 index 00000000..bcebcd7b --- /dev/null +++ b/typing/typedecl_variance.mli @@ -0,0 +1,56 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Gabriel Scherer, projet Parsifal, INRIA Saclay *) +(* Rodolphe Lepigre, projet Deducteam, INRIA Saclay *) +(* *) +(* Copyright 2018 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +open Types +open Typedecl_properties + +type surface_variance = bool * bool * bool + +val variance_of_params : + (Parsetree.core_type * Asttypes.variance) list -> surface_variance list +val variance_of_sdecl : + Parsetree.type_declaration -> surface_variance list + +type prop = Variance.t list +type req = surface_variance list +val property : (Variance.t list, req) property + +type error = +| Bad_variance of int * surface_variance * surface_variance +| Varying_anonymous + +exception Error of Location.t * error + +val check_variance_extension : + Env.t -> type_declaration -> + Typedtree.extension_constructor -> req * Location.t -> unit + +val compute_decl : + Env.t -> check:bool -> type_declaration -> req -> prop + +val update_decls : + Env.t -> Parsetree.type_declaration list -> + (Ident.t * type_declaration) list -> + (Ident.t * type_declaration) list + +val update_class_decls : + Env.t -> + (Ident.t * Typedecl_properties.decl * Types.type_declaration * + Types.class_declaration * Types.class_type_declaration * + 'a Typedtree.class_infos) list -> + (Typedecl_properties.decl * Types.type_declaration * + Types.class_declaration * Types.class_type_declaration) list +(* FIXME: improve this horrible interface *) diff --git a/typing/typedtree.ml b/typing/typedtree.ml index 4cc99643..43de0ff0 100644 --- a/typing/typedtree.ml +++ b/typing/typedtree.ml @@ -56,6 +56,7 @@ and pattern_desc = | Tpat_array of pattern list | Tpat_or of pattern * pattern * row_desc option | Tpat_lazy of pattern + | Tpat_exception of pattern and expression = { exp_desc: expression_desc; @@ -69,7 +70,6 @@ and expression = and exp_extra = | Texp_constraint of core_type | Texp_coerce of core_type option * core_type - | Texp_open of override_flag * Path.t * Longident.t loc * Env.t | Texp_poly of core_type option | Texp_newtype of string @@ -80,7 +80,7 @@ and expression_desc = | Texp_function of { arg_label : arg_label; param : Ident.t; cases : case list; partial : partial; } | Texp_apply of expression * (arg_label * expression option) list - | Texp_match of expression * case list * case list * partial + | Texp_match of expression * case list * partial | Texp_try of expression * case list | Texp_tuple of expression list | Texp_construct of @@ -106,14 +106,23 @@ and expression_desc = | Texp_instvar of Path.t * Path.t * string loc | Texp_setinstvar of Path.t * Path.t * string loc * expression | Texp_override of Path.t * (Path.t * string loc * expression) list - | Texp_letmodule of Ident.t * string loc * module_expr * expression + | Texp_letmodule of + Ident.t * string loc * Types.module_presence * module_expr * expression | Texp_letexception of extension_constructor * expression | Texp_assert of expression | Texp_lazy of expression | Texp_object of class_structure * string list | Texp_pack of module_expr + | Texp_letop of { + let_ : binding_op; + ands : binding_op list; + param : Ident.t; + body : case; + partial : partial; + } | Texp_unreachable | Texp_extension_constructor of Longident.t loc * Path.t + | Texp_open of open_declaration * expression and meth = Tmeth_name of string @@ -130,6 +139,16 @@ and record_label_definition = | Kept of Types.type_expr | Overridden of Longident.t loc * expression +and binding_op = + { + bop_op_path : Path.t; + bop_op_name : string loc; + bop_op_val : Types.value_description; + bop_op_type : Types.type_expr; + bop_exp : expression; + bop_loc : Location.t; + } + (* Value expressions for the class language *) and class_expr = @@ -145,15 +164,15 @@ and class_expr_desc = Tcl_ident of Path.t * Longident.t loc * core_type list | Tcl_structure of class_structure | Tcl_fun of - arg_label * pattern * (Ident.t * string loc * expression) list + arg_label * pattern * (Ident.t * expression) list * class_expr * partial | Tcl_apply of class_expr * (arg_label * expression option) list | Tcl_let of rec_flag * value_binding list * - (Ident.t * string loc * expression) list * class_expr + (Ident.t * expression) list * class_expr | Tcl_constraint of class_expr * class_type option * string list * string list * Concr.t (* Visible instance variables, methods and concrete methods *) - | Tcl_open of override_flag * Path.t * Longident.t loc * Env.t * class_expr + | Tcl_open of open_description * class_expr and class_structure = { @@ -226,11 +245,11 @@ and structure_item_desc = | Tstr_primitive of value_description | Tstr_type of rec_flag * type_declaration list | Tstr_typext of type_extension - | Tstr_exception of extension_constructor + | Tstr_exception of type_exception | Tstr_module of module_binding | Tstr_recmodule of module_binding list | Tstr_modtype of module_type_declaration - | Tstr_open of open_description + | Tstr_open of open_declaration | Tstr_class of (class_declaration * string list) list | Tstr_class_type of (Ident.t * string loc * class_type_declaration) list | Tstr_include of include_declaration @@ -240,6 +259,7 @@ and module_binding = { mb_id: Ident.t; mb_name: string loc; + mb_presence: module_presence; mb_expr: module_expr; mb_attributes: attribute list; mb_loc: Location.t; @@ -259,7 +279,7 @@ and module_coercion = (Ident.t * int * module_coercion) list | Tcoerce_functor of module_coercion * module_coercion | Tcoerce_primitive of primitive_coercion - | Tcoerce_alias of Path.t * module_coercion + | Tcoerce_alias of Env.t * Path.t * module_coercion and module_type = { mty_desc: module_type_desc; @@ -300,9 +320,11 @@ and signature_item = and signature_item_desc = Tsig_value of value_description | Tsig_type of rec_flag * type_declaration list + | Tsig_typesubst of type_declaration list | Tsig_typext of type_extension - | Tsig_exception of extension_constructor + | Tsig_exception of type_exception | Tsig_module of module_declaration + | Tsig_modsubst of module_substitution | Tsig_recmodule of module_declaration list | Tsig_modtype of module_type_declaration | Tsig_open of open_description @@ -315,11 +337,22 @@ and module_declaration = { md_id: Ident.t; md_name: string loc; + md_presence: module_presence; md_type: module_type; md_attributes: attribute list; md_loc: Location.t; } +and module_substitution = + { + ms_id: Ident.t; + ms_name: string loc; + ms_manifest: Path.t; + ms_txt: Longident.t loc; + ms_attributes: attributes; + ms_loc: Location.t; + } + and module_type_declaration = { mtd_id: Ident.t; @@ -329,15 +362,20 @@ and module_type_declaration = mtd_loc: Location.t; } -and open_description = +and 'a open_infos = { - open_path: Path.t; - open_txt: Longident.t loc; + open_expr: 'a; + open_bound_items: Types.signature; open_override: override_flag; + open_env: Env.t; open_loc: Location.t; open_attributes: attribute list; } +and open_description = (Path.t * Longident.t loc) open_infos + +and open_declaration = module_expr open_infos + and 'a include_infos = { incl_mod: 'a; @@ -385,12 +423,24 @@ and package_type = { pack_txt : Longident.t loc; } -and row_field = - Ttag of string loc * attributes * bool * core_type list +and row_field = { + rf_desc : row_field_desc; + rf_loc : Location.t; + rf_attributes : attributes; +} + +and row_field_desc = + Ttag of string loc * bool * core_type list | Tinherit of core_type -and object_field = - | OTtag of string loc * attributes * core_type +and object_field = { + of_desc : object_field_desc; + of_loc : Location.t; + of_attributes : attributes; +} + +and object_field_desc = + | OTtag of string loc * core_type | OTinherit of core_type and value_description = @@ -453,9 +503,17 @@ and type_extension = tyext_params: (core_type * variance) list; tyext_constructors: extension_constructor list; tyext_private: private_flag; + tyext_loc: Location.t; tyext_attributes: attribute list; } +and type_exception = + { + tyexn_constructor: extension_constructor; + tyexn_loc: Location.t; + tyexn_attributes: attribute list; + } + and extension_constructor = { ext_id: Ident.t; @@ -483,7 +541,7 @@ and class_type_desc = Tcty_constr of Path.t * Longident.t loc * core_type list | Tcty_signature of class_signature | Tcty_arrow of arg_label * core_type * class_type - | Tcty_open of override_flag * Path.t * Longident.t loc * Env.t * class_type + | Tcty_open of open_description * class_type and class_signature = { csig_self: core_type; @@ -540,6 +598,7 @@ let iter_pattern_desc f = function | Tpat_array patl -> List.iter f patl | Tpat_or(p1, p2, _) -> f p1; f p2 | Tpat_lazy p -> f p + | Tpat_exception p -> f p | Tpat_any | Tpat_var _ | Tpat_constant _ -> () @@ -557,6 +616,7 @@ let map_pattern_desc f d = | Tpat_array pats -> Tpat_array (List.map f pats) | Tpat_lazy p1 -> Tpat_lazy (f p1) + | Tpat_exception p1 -> Tpat_exception (f p1) | Tpat_variant (x1, Some p1, x2) -> Tpat_variant (x1, Some (f p1), x2) | Tpat_or (p1,p2,path) -> @@ -568,24 +628,27 @@ let map_pattern_desc f d = (* List the identifiers bound by a pattern or a let *) -let idents = ref([]: (Ident.t * string loc) list) +let idents = ref([]: (Ident.t * string loc * Types.type_expr) list) let rec bound_idents pat = match pat.pat_desc with - | Tpat_var (id,s) -> idents := (id,s) :: !idents - | Tpat_alias(p, id, s ) -> - bound_idents p; idents := (id,s) :: !idents + | Tpat_var (id,s) -> idents := (id,s,pat.pat_type) :: !idents + | Tpat_alias(p, id, s) -> + bound_idents p; idents := (id,s,pat.pat_type) :: !idents | Tpat_or(p1, _, _) -> (* Invariant : both arguments binds the same variables *) bound_idents p1 | d -> iter_pattern_desc bound_idents d -let pat_bound_idents pat = +let pat_bound_idents_full pat = idents := []; bound_idents pat; let res = !idents in idents := []; - List.map fst res + res + +let pat_bound_idents pat = + List.map (fun (id,_,_) -> id) (pat_bound_idents_full pat) let rev_let_bound_idents_with_loc bindings = idents := []; @@ -595,8 +658,11 @@ let rev_let_bound_idents_with_loc bindings = let let_bound_idents_with_loc pat_expr_list = List.rev(rev_let_bound_idents_with_loc pat_expr_list) -let rev_let_bound_idents pat = List.map fst (rev_let_bound_idents_with_loc pat) -let let_bound_idents pat = List.map fst (let_bound_idents_with_loc pat) +let rev_let_bound_idents pat = + List.map (fun (id,_,_) -> id) (rev_let_bound_idents_with_loc pat) + +let let_bound_idents pat = + List.map (fun (id,_,_) -> id) (let_bound_idents_with_loc pat) let alpha_var env id = List.assoc id env @@ -617,3 +683,31 @@ let rec alpha_pat env p = match p.pat_desc with let mkloc = Location.mkloc let mknoloc = Location.mknoloc + +let split_pattern pat = + let combine_pattern_desc_opts ~into p1 p2 = + match p1, p2 with + | None, None -> None + | Some p, None + | None, Some p -> + Some p + | Some p1, Some p2 -> + (* The third parameter of [Tpat_or] is [Some _] only for "#typ" + patterns, which we do *not* expand. Hence we can put [None] here. *) + Some { into with pat_desc = Tpat_or (p1, p2, None) } + in + let rec split_pattern pat = + match pat.pat_desc with + | Tpat_or (p1, p2, None) -> + let vals1, exns1 = split_pattern p1 in + let vals2, exns2 = split_pattern p2 in + combine_pattern_desc_opts ~into:pat vals1 vals2, + (* We could change the pattern type for exception patterns to + [Predef.exn], but it doesn't really matter. *) + combine_pattern_desc_opts ~into:pat exns1 exns2 + | Tpat_exception p -> + None, Some p + | _ -> + Some pat, None + in + split_pattern pat diff --git a/typing/typedtree.mli b/typing/typedtree.mli index 2e89ed52..129f34f0 100644 --- a/typing/typedtree.mli +++ b/typing/typedtree.mli @@ -106,6 +106,8 @@ and pattern_desc = *) | Tpat_lazy of pattern (** lazy P *) + | Tpat_exception of pattern + (** exception P *) and expression = { exp_desc: expression_desc; @@ -123,10 +125,6 @@ and exp_extra = (** E :> T [Texp_coerce (None, T)] E : T0 :> T [Texp_coerce (Some T0, T)] *) - | Texp_open of override_flag * Path.t * Longident.t loc * Env.t - (** let open[!] M in [Texp_open (!, P, M, env)] - where [env] is the environment after opening [P] - *) | Texp_poly of core_type option (** Used for method bodies. *) | Texp_newtype of string @@ -171,13 +169,14 @@ and expression_desc = (Labelled "y", Some (Texp_constant Const_int 3)) ]) *) - | Texp_match of expression * case list * case list * partial + | Texp_match of expression * case list * partial (** match E0 with | P1 -> E1 - | P2 -> E2 - | exception P3 -> E3 + | P2 | exception P3 -> E2 + | exception P4 -> E3 - [Texp_match (E0, [(P1, E1); (P2, E2)], [(P3, E3)], _)] + [Texp_match (E0, [(P1, E1); (P2 | exception P3, E2); + (exception P4, E3)], _)] *) | Texp_try of expression * case list (** try E with P1 -> E1 | ... | PN -> EN *) @@ -221,14 +220,24 @@ and expression_desc = | Texp_instvar of Path.t * Path.t * string loc | Texp_setinstvar of Path.t * Path.t * string loc * expression | Texp_override of Path.t * (Path.t * string loc * expression) list - | Texp_letmodule of Ident.t * string loc * module_expr * expression + | Texp_letmodule of + Ident.t * string loc * Types.module_presence * module_expr * expression | Texp_letexception of extension_constructor * expression | Texp_assert of expression | Texp_lazy of expression | Texp_object of class_structure * string list | Texp_pack of module_expr + | Texp_letop of { + let_ : binding_op; + ands : binding_op list; + param : Ident.t; + body : case; + partial : partial; + } | Texp_unreachable | Texp_extension_constructor of Longident.t loc * Path.t + | Texp_open of open_declaration * expression + (** let open[!] M in e *) and meth = Tmeth_name of string @@ -245,6 +254,18 @@ and record_label_definition = | Kept of Types.type_expr | Overridden of Longident.t loc * expression +and binding_op = + { + bop_op_path : Path.t; + bop_op_name : string loc; + bop_op_val : Types.value_description; + bop_op_type : Types.type_expr; + (* This is the type at which the operator was used. + It is always an instance of [bop_op_val.val_type] *) + bop_exp : expression; + bop_loc : Location.t; + } + (* Value expressions for the class language *) and class_expr = @@ -260,15 +281,15 @@ and class_expr_desc = Tcl_ident of Path.t * Longident.t loc * core_type list | Tcl_structure of class_structure | Tcl_fun of - arg_label * pattern * (Ident.t * string loc * expression) list + arg_label * pattern * (Ident.t * expression) list * class_expr * partial | Tcl_apply of class_expr * (arg_label * expression option) list | Tcl_let of rec_flag * value_binding list * - (Ident.t * string loc * expression) list * class_expr + (Ident.t * expression) list * class_expr | Tcl_constraint of class_expr * class_type option * string list * string list * Concr.t (* Visible instance variables, methods and concrete methods *) - | Tcl_open of override_flag * Path.t * Longident.t loc * Env.t * class_expr + | Tcl_open of open_description * class_expr and class_structure = { @@ -347,11 +368,11 @@ and structure_item_desc = | Tstr_primitive of value_description | Tstr_type of rec_flag * type_declaration list | Tstr_typext of type_extension - | Tstr_exception of extension_constructor + | Tstr_exception of type_exception | Tstr_module of module_binding | Tstr_recmodule of module_binding list | Tstr_modtype of module_type_declaration - | Tstr_open of open_description + | Tstr_open of open_declaration | Tstr_class of (class_declaration * string list) list | Tstr_class_type of (Ident.t * string loc * class_type_declaration) list | Tstr_include of include_declaration @@ -361,6 +382,7 @@ and module_binding = { mb_id: Ident.t; mb_name: string loc; + mb_presence: module_presence; mb_expr: module_expr; mb_attributes: attributes; mb_loc: Location.t; @@ -380,7 +402,7 @@ and module_coercion = (Ident.t * int * module_coercion) list | Tcoerce_functor of module_coercion * module_coercion | Tcoerce_primitive of primitive_coercion - | Tcoerce_alias of Path.t * module_coercion + | Tcoerce_alias of Env.t * Path.t * module_coercion and module_type = { mty_desc: module_type_desc; @@ -420,9 +442,11 @@ and signature_item = and signature_item_desc = Tsig_value of value_description | Tsig_type of rec_flag * type_declaration list + | Tsig_typesubst of type_declaration list | Tsig_typext of type_extension - | Tsig_exception of extension_constructor + | Tsig_exception of type_exception | Tsig_module of module_declaration + | Tsig_modsubst of module_substitution | Tsig_recmodule of module_declaration list | Tsig_modtype of module_type_declaration | Tsig_open of open_description @@ -435,11 +459,22 @@ and module_declaration = { md_id: Ident.t; md_name: string loc; + md_presence: module_presence; md_type: module_type; md_attributes: attributes; md_loc: Location.t; } +and module_substitution = + { + ms_id: Ident.t; + ms_name: string loc; + ms_manifest: Path.t; + ms_txt: Longident.t loc; + ms_attributes: attributes; + ms_loc: Location.t; + } + and module_type_declaration = { mtd_id: Ident.t; @@ -449,15 +484,21 @@ and module_type_declaration = mtd_loc: Location.t; } -and open_description = +and 'a open_infos = { - open_path: Path.t; - open_txt: Longident.t loc; + open_expr: 'a; + open_bound_items: Types.signature; open_override: override_flag; + open_env: Env.t; open_loc: Location.t; open_attributes: attribute list; } +and open_description = (Path.t * Longident.t loc) open_infos + +and open_declaration = module_expr open_infos + + and 'a include_infos = { incl_mod: 'a; @@ -506,12 +547,24 @@ and package_type = { pack_txt : Longident.t loc; } -and row_field = - Ttag of string loc * attributes * bool * core_type list +and row_field = { + rf_desc : row_field_desc; + rf_loc : Location.t; + rf_attributes : attributes; +} + +and row_field_desc = + Ttag of string loc * bool * core_type list | Tinherit of core_type -and object_field = - | OTtag of string loc * attributes * core_type +and object_field = { + of_desc : object_field_desc; + of_loc : Location.t; + of_attributes : attributes; +} + +and object_field_desc = + | OTtag of string loc * core_type | OTinherit of core_type and value_description = @@ -575,9 +628,17 @@ and type_extension = tyext_params: (core_type * variance) list; tyext_constructors: extension_constructor list; tyext_private: private_flag; + tyext_loc: Location.t; tyext_attributes: attributes; } +and type_exception = + { + tyexn_constructor: extension_constructor; + tyexn_loc: Location.t; + tyexn_attributes: attribute list; + } + and extension_constructor = { ext_id: Ident.t; @@ -605,7 +666,7 @@ and class_type_desc = Tcty_constr of Path.t * Longident.t loc * core_type list | Tcty_signature of class_signature | Tcty_arrow of arg_label * core_type * class_type - | Tcty_open of override_flag * Path.t * Longident.t loc * Env.t * class_type + | Tcty_open of open_description * class_type and class_signature = { csig_self : core_type; @@ -659,7 +720,7 @@ val let_bound_idents: value_binding list -> Ident.t list val rev_let_bound_idents: value_binding list -> Ident.t list val let_bound_idents_with_loc: - value_binding list -> (Ident.t * string loc) list + value_binding list -> (Ident.t * string loc * type_expr) list (** Alpha conversion of patterns *) val alpha_pat: (Ident.t * Ident.t) list -> pattern -> pattern @@ -668,3 +729,8 @@ val mknoloc: 'a -> 'a Asttypes.loc val mkloc: 'a -> Location.t -> 'a Asttypes.loc val pat_bound_idents: pattern -> Ident.t list +val pat_bound_idents_full: + pattern -> (Ident.t * string loc * type_expr) list + +(** Splits an or pattern into its value (left) and exception (right) parts. *) +val split_pattern : pattern -> pattern option * pattern option diff --git a/typing/typedtreeIter.ml b/typing/typedtreeIter.ml index a3be8d3b..3c3fe34c 100644 --- a/typing/typedtreeIter.ml +++ b/typing/typedtreeIter.ml @@ -27,6 +27,7 @@ module type IteratorArgument = sig val enter_structure : structure -> unit val enter_value_description : value_description -> unit val enter_type_extension : type_extension -> unit + val enter_type_exception : type_exception -> unit val enter_extension_constructor : extension_constructor -> unit val enter_pattern : pattern -> unit val enter_expression : expression -> unit @@ -53,6 +54,7 @@ module type IteratorArgument = sig val leave_structure : structure -> unit val leave_value_description : value_description -> unit val leave_type_extension : type_extension -> unit + val leave_type_exception : type_exception -> unit val leave_extension_constructor : extension_constructor -> unit val leave_pattern : pattern -> unit val leave_expression : expression -> unit @@ -141,11 +143,11 @@ module MakeIterator(Iter : IteratorArgument) : sig | Tstr_primitive vd -> iter_value_description vd | Tstr_type (rf, list) -> iter_type_declarations rf list | Tstr_typext tyext -> iter_type_extension tyext - | Tstr_exception ext -> iter_extension_constructor ext + | Tstr_exception ext -> iter_type_exception ext | Tstr_module x -> iter_module_binding x | Tstr_recmodule list -> List.iter iter_module_binding list | Tstr_modtype mtd -> iter_module_type_declaration mtd - | Tstr_open _ -> () + | Tstr_open od -> iter_module_expr od.open_expr | Tstr_class list -> List.iter (fun (ci, _) -> iter_class_declaration ci) list | Tstr_class_type list -> @@ -219,6 +221,11 @@ module MakeIterator(Iter : IteratorArgument) : sig List.iter iter_extension_constructor tyext.tyext_constructors; Iter.leave_type_extension tyext + and iter_type_exception tyexn = + Iter.enter_type_exception tyexn; + iter_extension_constructor tyexn.tyexn_constructor; + Iter.leave_type_exception tyexn + and iter_pattern pat = Iter.enter_pattern pat; List.iter (fun (cstr, _, _attrs) -> match cstr with @@ -245,7 +252,8 @@ module MakeIterator(Iter : IteratorArgument) : sig List.iter (fun (_, _, pat) -> iter_pattern pat) list | Tpat_array list -> List.iter iter_pattern list | Tpat_or (p1, p2, _) -> iter_pattern p1; iter_pattern p2 - | Tpat_lazy p -> iter_pattern p + | Tpat_lazy p + | Tpat_exception p -> iter_pattern p end; Iter.leave_pattern pat @@ -259,7 +267,6 @@ module MakeIterator(Iter : IteratorArgument) : sig iter_core_type ct | Texp_coerce (cty1, cty2) -> option iter_core_type cty1; iter_core_type cty2 - | Texp_open _ -> () | Texp_poly cto -> option iter_core_type cto | Texp_newtype _ -> ()) exp.exp_extra; @@ -279,10 +286,9 @@ module MakeIterator(Iter : IteratorArgument) : sig None -> () | Some exp -> iter_expression exp ) list - | Texp_match (exp, list1, list2, _) -> + | Texp_match (exp, list, _) -> iter_expression exp; - iter_cases list1; - iter_cases list2; + iter_cases list | Texp_try (exp, list) -> iter_expression exp; iter_cases list @@ -343,7 +349,7 @@ module MakeIterator(Iter : IteratorArgument) : sig List.iter (fun (_path, _, exp) -> iter_expression exp ) list - | Texp_letmodule (_id, _, mexpr, exp) -> + | Texp_letmodule (_id, _, _, mexpr, exp) -> iter_module_expr mexpr; iter_expression exp | Texp_letexception (cd, exp) -> @@ -355,13 +361,23 @@ module MakeIterator(Iter : IteratorArgument) : sig iter_class_structure cl | Texp_pack (mexpr) -> iter_module_expr mexpr + | Texp_letop{let_; ands; param = _; body; partial = _} -> + iter_binding_op let_; + List.iter iter_binding_op ands; + iter_case body | Texp_unreachable -> () | Texp_extension_constructor _ -> () + | Texp_open (od, e) -> + iter_module_expr od.open_expr; + iter_expression e end; Iter.leave_expression exp; + and iter_binding_op bop = + iter_expression bop.bop_exp + and iter_package_type pack = Iter.enter_package_type pack; List.iter (fun (_s, ct) -> iter_core_type ct) pack.pack_fields; @@ -380,12 +396,15 @@ module MakeIterator(Iter : IteratorArgument) : sig iter_value_description vd | Tsig_type (rf, list) -> iter_type_declarations rf list + | Tsig_typesubst list -> + iter_type_declarations Nonrecursive list | Tsig_exception ext -> - iter_extension_constructor ext + iter_type_exception ext | Tsig_typext tyext -> iter_type_extension tyext | Tsig_module md -> iter_module_type md.md_type + | Tsig_modsubst _ -> () | Tsig_recmodule list -> List.iter (fun md -> iter_module_type md.md_type) list | Tsig_modtype mtd -> @@ -489,7 +508,7 @@ module MakeIterator(Iter : IteratorArgument) : sig | Tcl_structure clstr -> iter_class_structure clstr | Tcl_fun (_label, pat, priv, cl, _partial) -> iter_pattern pat; - List.iter (fun (_id, _, exp) -> iter_expression exp) priv; + List.iter (fun (_id, exp) -> iter_expression exp) priv; iter_class_expr cl | Tcl_apply (cl, args) -> @@ -502,7 +521,7 @@ module MakeIterator(Iter : IteratorArgument) : sig | Tcl_let (rec_flat, bindings, ivars, cl) -> iter_bindings rec_flat bindings; - List.iter (fun (_id, _, exp) -> iter_expression exp) ivars; + List.iter (fun (_id, exp) -> iter_expression exp) ivars; iter_class_expr cl | Tcl_constraint (cl, Some clty, _vals, _meths, _concrs) -> @@ -512,7 +531,7 @@ module MakeIterator(Iter : IteratorArgument) : sig | Tcl_ident (_, _, tyl) -> List.iter iter_core_type tyl - | Tcl_open (_, _, _, _, e) -> + | Tcl_open (_, e) -> iter_class_expr e end; Iter.leave_class_expr cexpr; @@ -527,7 +546,7 @@ module MakeIterator(Iter : IteratorArgument) : sig | Tcty_arrow (_label, ct, cl) -> iter_core_type ct; iter_class_type cl - | Tcty_open (_, _, _, _, e) -> + | Tcty_open (_, e) -> iter_class_type e end; Iter.leave_class_type ct; @@ -588,14 +607,14 @@ module MakeIterator(Iter : IteratorArgument) : sig and iter_row_field rf = - match rf with - Ttag (_label, _attrs, _bool, list) -> + match rf.rf_desc with + | Ttag (_label, _bool, list) -> List.iter iter_core_type list | Tinherit ct -> iter_core_type ct and iter_object_field ofield = - match ofield with - OTtag (_, _, ct) | OTinherit ct -> iter_core_type ct + match ofield.of_desc with + | OTtag (_, ct) | OTinherit ct -> iter_core_type ct and iter_class_field cf = Iter.enter_class_field cf; @@ -626,6 +645,7 @@ module DefaultIteratorArgument = struct let enter_structure _ = () let enter_value_description _ = () let enter_type_extension _ = () + let enter_type_exception _ = () let enter_extension_constructor _ = () let enter_pattern _ = () let enter_expression _ = () @@ -652,6 +672,7 @@ module DefaultIteratorArgument = struct let leave_structure _ = () let leave_value_description _ = () let leave_type_extension _ = () + let leave_type_exception _ = () let leave_extension_constructor _ = () let leave_pattern _ = () let leave_expression _ = () diff --git a/typing/typedtreeIter.mli b/typing/typedtreeIter.mli index 53aa54c1..2e2d0d05 100644 --- a/typing/typedtreeIter.mli +++ b/typing/typedtreeIter.mli @@ -21,6 +21,7 @@ module type IteratorArgument = sig val enter_structure : structure -> unit val enter_value_description : value_description -> unit val enter_type_extension : type_extension -> unit + val enter_type_exception : type_exception -> unit val enter_extension_constructor : extension_constructor -> unit val enter_pattern : pattern -> unit val enter_expression : expression -> unit @@ -47,6 +48,7 @@ module type IteratorArgument = sig val leave_structure : structure -> unit val leave_value_description : value_description -> unit val leave_type_extension : type_extension -> unit + val leave_type_exception : type_exception -> unit val leave_extension_constructor : extension_constructor -> unit val leave_pattern : pattern -> unit val leave_expression : expression -> unit diff --git a/typing/typedtreeMap.ml b/typing/typedtreeMap.ml deleted file mode 100644 index ccde8c03..00000000 --- a/typing/typedtreeMap.ml +++ /dev/null @@ -1,732 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Fabrice Le Fessant, INRIA Saclay *) -(* *) -(* Copyright 2012 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -open Typedtree - -module type MapArgument = sig - val enter_structure : structure -> structure - val enter_value_description : value_description -> value_description - val enter_type_declaration : type_declaration -> type_declaration - val enter_type_extension : type_extension -> type_extension - val enter_extension_constructor : - extension_constructor -> extension_constructor - val enter_pattern : pattern -> pattern - val enter_expression : expression -> expression - val enter_package_type : package_type -> package_type - val enter_signature : signature -> signature - val enter_signature_item : signature_item -> signature_item - val enter_module_type_declaration : - module_type_declaration -> module_type_declaration - val enter_module_type : module_type -> module_type - val enter_module_expr : module_expr -> module_expr - val enter_with_constraint : with_constraint -> with_constraint - val enter_class_expr : class_expr -> class_expr - val enter_class_signature : class_signature -> class_signature - val enter_class_declaration : class_declaration -> class_declaration - val enter_class_description : class_description -> class_description - val enter_class_type_declaration : - class_type_declaration -> class_type_declaration - val enter_class_type : class_type -> class_type - val enter_class_type_field : class_type_field -> class_type_field - val enter_core_type : core_type -> core_type - val enter_class_structure : class_structure -> class_structure - val enter_class_field : class_field -> class_field - val enter_structure_item : structure_item -> structure_item - - val leave_structure : structure -> structure - val leave_value_description : value_description -> value_description - val leave_type_declaration : type_declaration -> type_declaration - val leave_type_extension : type_extension -> type_extension - val leave_extension_constructor : - extension_constructor -> extension_constructor - val leave_pattern : pattern -> pattern - val leave_expression : expression -> expression - val leave_package_type : package_type -> package_type - val leave_signature : signature -> signature - val leave_signature_item : signature_item -> signature_item - val leave_module_type_declaration : - module_type_declaration -> module_type_declaration - val leave_module_type : module_type -> module_type - val leave_module_expr : module_expr -> module_expr - val leave_with_constraint : with_constraint -> with_constraint - val leave_class_expr : class_expr -> class_expr - val leave_class_signature : class_signature -> class_signature - val leave_class_declaration : class_declaration -> class_declaration - val leave_class_description : class_description -> class_description - val leave_class_type_declaration : - class_type_declaration -> class_type_declaration - val leave_class_type : class_type -> class_type - val leave_class_type_field : class_type_field -> class_type_field - val leave_core_type : core_type -> core_type - val leave_class_structure : class_structure -> class_structure - val leave_class_field : class_field -> class_field - val leave_structure_item : structure_item -> structure_item - -end - - -module MakeMap(Map : MapArgument) = struct - - open Misc - - let rec map_structure str = - let str = Map.enter_structure str in - let str_items = List.map map_structure_item str.str_items in - Map.leave_structure { str with str_items = str_items } - - and map_binding vb = - { - vb_pat = map_pattern vb.vb_pat; - vb_expr = map_expression vb.vb_expr; - vb_attributes = vb.vb_attributes; - vb_loc = vb.vb_loc; - } - - and map_bindings list = - List.map map_binding list - - and map_case {c_lhs; c_guard; c_rhs} = - { - c_lhs = map_pattern c_lhs; - c_guard = may_map map_expression c_guard; - c_rhs = map_expression c_rhs; - } - - and map_cases list = - List.map map_case list - - and map_structure_item item = - let item = Map.enter_structure_item item in - let str_desc = - match item.str_desc with - Tstr_eval (exp, attrs) -> Tstr_eval (map_expression exp, attrs) - | Tstr_value (rec_flag, list) -> - Tstr_value (rec_flag, map_bindings list) - | Tstr_primitive vd -> - Tstr_primitive (map_value_description vd) - | Tstr_type (rf, list) -> - Tstr_type (rf, List.map map_type_declaration list) - | Tstr_typext tyext -> - Tstr_typext (map_type_extension tyext) - | Tstr_exception ext -> - Tstr_exception (map_extension_constructor ext) - | Tstr_module x -> - Tstr_module (map_module_binding x) - | Tstr_recmodule list -> - let list = List.map map_module_binding list in - Tstr_recmodule list - | Tstr_modtype mtd -> - Tstr_modtype (map_module_type_declaration mtd) - | Tstr_open od -> Tstr_open od - | Tstr_class list -> - let list = - List.map - (fun (ci, string_list) -> - map_class_declaration ci, string_list) - list - in - Tstr_class list - | Tstr_class_type list -> - let list = - List.map - (fun (id, name, ct) -> - id, name, map_class_type_declaration ct) - list - in - Tstr_class_type list - | Tstr_include incl -> - Tstr_include {incl with incl_mod = map_module_expr incl.incl_mod} - | Tstr_attribute x -> Tstr_attribute x - in - Map.leave_structure_item { item with str_desc = str_desc} - - and map_module_binding x = - {x with mb_expr = map_module_expr x.mb_expr} - - and map_value_description v = - let v = Map.enter_value_description v in - let val_desc = map_core_type v.val_desc in - Map.leave_value_description { v with val_desc = val_desc } - - and map_type_declaration decl = - let decl = Map.enter_type_declaration decl in - let typ_params = List.map map_type_parameter decl.typ_params in - let typ_cstrs = List.map (fun (ct1, ct2, loc) -> - (map_core_type ct1, - map_core_type ct2, - loc) - ) decl.typ_cstrs in - let typ_kind = match decl.typ_kind with - Ttype_abstract -> Ttype_abstract - | Ttype_variant list -> - let list = List.map map_constructor_declaration list in - Ttype_variant list - | Ttype_record list -> - let list = - List.map - (fun ld -> - {ld with ld_type = map_core_type ld.ld_type} - ) list - in - Ttype_record list - | Ttype_open -> Ttype_open - in - let typ_manifest = may_map map_core_type decl.typ_manifest in - Map.leave_type_declaration { decl with typ_params = typ_params; - typ_cstrs = typ_cstrs; typ_kind = typ_kind; typ_manifest = typ_manifest } - - and map_type_parameter (ct, v) = (map_core_type ct, v) - - and map_constructor_arguments = function - | Cstr_tuple l -> - Cstr_tuple (List.map map_core_type l) - | Cstr_record l -> - Cstr_record - (List.map (fun ld -> {ld with ld_type = map_core_type ld.ld_type}) - l) - - and map_constructor_declaration cd = - let cd_args = map_constructor_arguments cd.cd_args in - {cd with cd_args; - cd_res = may_map map_core_type cd.cd_res - } - - and map_type_extension tyext = - let tyext = Map.enter_type_extension tyext in - let tyext_params = List.map map_type_parameter tyext.tyext_params in - let tyext_constructors = - List.map map_extension_constructor tyext.tyext_constructors - in - Map.leave_type_extension { tyext with tyext_params = tyext_params; - tyext_constructors = tyext_constructors } - - and map_extension_constructor ext = - let ext = Map.enter_extension_constructor ext in - let ext_kind = match ext.ext_kind with - Text_decl(args, ret) -> - let args = map_constructor_arguments args in - let ret = may_map map_core_type ret in - Text_decl(args, ret) - | Text_rebind(p, lid) -> Text_rebind(p, lid) - in - Map.leave_extension_constructor {ext with ext_kind = ext_kind} - - and map_pattern pat = - let pat = Map.enter_pattern pat in - let pat_desc = - match pat.pat_desc with - | Tpat_alias (pat1, p, text) -> - let pat1 = map_pattern pat1 in - Tpat_alias (pat1, p, text) - | Tpat_tuple list -> Tpat_tuple (List.map map_pattern list) - | Tpat_construct (lid, cstr_decl, args) -> - Tpat_construct (lid, cstr_decl, - List.map map_pattern args) - | Tpat_variant (label, pato, rowo) -> - let pato = match pato with - None -> pato - | Some pat -> Some (map_pattern pat) - in - Tpat_variant (label, pato, rowo) - | Tpat_record (list, closed) -> - Tpat_record (List.map (fun (lid, lab_desc, pat) -> - (lid, lab_desc, map_pattern pat) ) list, closed) - | Tpat_array list -> Tpat_array (List.map map_pattern list) - | Tpat_or (p1, p2, rowo) -> - Tpat_or (map_pattern p1, map_pattern p2, rowo) - | Tpat_lazy p -> Tpat_lazy (map_pattern p) - | Tpat_constant _ - | Tpat_any - | Tpat_var _ -> pat.pat_desc - - in - let pat_extra = List.map map_pat_extra pat.pat_extra in - Map.leave_pattern { pat with pat_desc = pat_desc; pat_extra = pat_extra } - - and map_pat_extra pat_extra = - match pat_extra with - | Tpat_constraint ct, loc, attrs -> - (Tpat_constraint (map_core_type ct), loc, attrs) - | (Tpat_type _ | Tpat_unpack | Tpat_open _ ), _, _ -> pat_extra - - and map_expression exp = - let exp = Map.enter_expression exp in - let exp_desc = - match exp.exp_desc with - Texp_ident (_, _, _) - | Texp_constant _ -> exp.exp_desc - | Texp_let (rec_flag, list, exp) -> - Texp_let (rec_flag, - map_bindings list, - map_expression exp) - | Texp_function { arg_label; param; cases; partial; } -> - Texp_function { arg_label; param; cases = map_cases cases; partial; } - | Texp_apply (exp, list) -> - Texp_apply (map_expression exp, - List.map (fun (label, expo) -> - let expo = - match expo with - None -> expo - | Some exp -> Some (map_expression exp) - in - (label, expo) - ) list ) - | Texp_match (exp, list1, list2, partial) -> - Texp_match ( - map_expression exp, - map_cases list1, - map_cases list2, - partial - ) - | Texp_try (exp, list) -> - Texp_try ( - map_expression exp, - map_cases list - ) - | Texp_tuple list -> - Texp_tuple (List.map map_expression list) - | Texp_construct (lid, cstr_desc, args) -> - Texp_construct (lid, cstr_desc, - List.map map_expression args ) - | Texp_variant (label, expo) -> - let expo =match expo with - None -> expo - | Some exp -> Some (map_expression exp) - in - Texp_variant (label, expo) - | Texp_record { fields; representation; extended_expression } -> - let fields = - Array.map (function - | label, Kept t -> label, Kept t - | label, Overridden (lid, exp) -> - label, Overridden (lid, map_expression exp)) - fields - in - let extended_expression = match extended_expression with - None -> extended_expression - | Some exp -> Some (map_expression exp) - in - Texp_record { fields; representation; extended_expression } - | Texp_field (exp, lid, label) -> - Texp_field (map_expression exp, lid, label) - | Texp_setfield (exp1, lid, label, exp2) -> - Texp_setfield ( - map_expression exp1, - lid, - label, - map_expression exp2) - | Texp_array list -> - Texp_array (List.map map_expression list) - | Texp_ifthenelse (exp1, exp2, expo) -> - Texp_ifthenelse ( - map_expression exp1, - map_expression exp2, - match expo with - None -> expo - | Some exp -> Some (map_expression exp) - ) - | Texp_sequence (exp1, exp2) -> - Texp_sequence ( - map_expression exp1, - map_expression exp2 - ) - | Texp_while (exp1, exp2) -> - Texp_while ( - map_expression exp1, - map_expression exp2 - ) - | Texp_for (id, name, exp1, exp2, dir, exp3) -> - Texp_for ( - id, name, - map_expression exp1, - map_expression exp2, - dir, - map_expression exp3 - ) - | Texp_send (exp, meth, expo) -> - Texp_send (map_expression exp, meth, may_map map_expression expo) - | Texp_new _ -> exp.exp_desc - | Texp_instvar _ -> exp.exp_desc - | Texp_setinstvar (path, lid, path2, exp) -> - Texp_setinstvar (path, lid, path2, map_expression exp) - | Texp_override (path, list) -> - Texp_override ( - path, - List.map (fun (path, lid, exp) -> - (path, lid, map_expression exp) - ) list - ) - | Texp_letmodule (id, name, mexpr, exp) -> - Texp_letmodule ( - id, name, - map_module_expr mexpr, - map_expression exp - ) - | Texp_letexception (cd, exp) -> - Texp_letexception ( - map_extension_constructor cd, - map_expression exp - ) - | Texp_assert exp -> Texp_assert (map_expression exp) - | Texp_lazy exp -> Texp_lazy (map_expression exp) - | Texp_object (cl, string_list) -> - Texp_object (map_class_structure cl, string_list) - | Texp_pack (mexpr) -> - Texp_pack (map_module_expr mexpr) - | Texp_unreachable -> - Texp_unreachable - | Texp_extension_constructor _ as e -> - e - in - let exp_extra = List.map map_exp_extra exp.exp_extra in - Map.leave_expression { - exp with - exp_desc = exp_desc; - exp_extra = exp_extra; } - - and map_exp_extra ((desc, loc, attrs) as exp_extra) = - match desc with - | Texp_constraint ct -> - Texp_constraint (map_core_type ct), loc, attrs - | Texp_coerce (None, ct) -> - Texp_coerce (None, map_core_type ct), loc, attrs - | Texp_coerce (Some ct1, ct2) -> - Texp_coerce (Some (map_core_type ct1), - map_core_type ct2), loc, attrs - | Texp_poly (Some ct) -> - Texp_poly (Some ( map_core_type ct )), loc, attrs - | Texp_newtype _ - | Texp_open _ - | Texp_poly None -> exp_extra - - - and map_package_type pack = - let pack = Map.enter_package_type pack in - let pack_fields = List.map ( - fun (s, ct) -> (s, map_core_type ct) ) pack.pack_fields in - Map.leave_package_type { pack with pack_fields = pack_fields } - - and map_signature sg = - let sg = Map.enter_signature sg in - let sig_items = List.map map_signature_item sg.sig_items in - Map.leave_signature { sg with sig_items = sig_items } - - and map_signature_item item = - let item = Map.enter_signature_item item in - let sig_desc = - match item.sig_desc with - Tsig_value vd -> - Tsig_value (map_value_description vd) - | Tsig_type (rf, list) -> - Tsig_type (rf, List.map map_type_declaration list) - | Tsig_typext tyext -> - Tsig_typext (map_type_extension tyext) - | Tsig_exception ext -> - Tsig_exception (map_extension_constructor ext) - | Tsig_module md -> - Tsig_module {md with md_type = map_module_type md.md_type} - | Tsig_recmodule list -> - Tsig_recmodule - (List.map - (fun md -> {md with md_type = map_module_type md.md_type}) - list - ) - | Tsig_modtype mtd -> - Tsig_modtype (map_module_type_declaration mtd) - | Tsig_open _ -> item.sig_desc - | Tsig_include incl -> - Tsig_include {incl with incl_mod = map_module_type incl.incl_mod} - | Tsig_class list -> Tsig_class (List.map map_class_description list) - | Tsig_class_type list -> - Tsig_class_type (List.map map_class_type_declaration list) - | Tsig_attribute _ as x -> x - in - Map.leave_signature_item { item with sig_desc = sig_desc } - - and map_module_type_declaration mtd = - let mtd = Map.enter_module_type_declaration mtd in - let mtd = {mtd with mtd_type = may_map map_module_type mtd.mtd_type} in - Map.leave_module_type_declaration mtd - - and map_class_declaration cd = - let cd = Map.enter_class_declaration cd in - let ci_params = List.map map_type_parameter cd.ci_params in - let ci_expr = map_class_expr cd.ci_expr in - Map.leave_class_declaration - { cd with ci_params = ci_params; ci_expr = ci_expr } - - and map_class_description cd = - let cd = Map.enter_class_description cd in - let ci_params = List.map map_type_parameter cd.ci_params in - let ci_expr = map_class_type cd.ci_expr in - Map.leave_class_description - { cd with ci_params = ci_params; ci_expr = ci_expr} - - and map_class_type_declaration cd = - let cd = Map.enter_class_type_declaration cd in - let ci_params = List.map map_type_parameter cd.ci_params in - let ci_expr = map_class_type cd.ci_expr in - Map.leave_class_type_declaration - { cd with ci_params = ci_params; ci_expr = ci_expr } - - and map_module_type mty = - let mty = Map.enter_module_type mty in - let mty_desc = - match mty.mty_desc with - Tmty_ident _ -> mty.mty_desc - | Tmty_alias _ -> mty.mty_desc - | Tmty_signature sg -> Tmty_signature (map_signature sg) - | Tmty_functor (id, name, mtype1, mtype2) -> - Tmty_functor (id, name, Misc.may_map map_module_type mtype1, - map_module_type mtype2) - | Tmty_with (mtype, list) -> - Tmty_with (map_module_type mtype, - List.map (fun (path, lid, withc) -> - (path, lid, map_with_constraint withc) - ) list) - | Tmty_typeof mexpr -> - Tmty_typeof (map_module_expr mexpr) - in - Map.leave_module_type { mty with mty_desc = mty_desc} - - and map_with_constraint cstr = - let cstr = Map.enter_with_constraint cstr in - let cstr = - match cstr with - Twith_type decl -> Twith_type (map_type_declaration decl) - | Twith_typesubst decl -> Twith_typesubst (map_type_declaration decl) - | Twith_module _ -> cstr - | Twith_modsubst _ -> cstr - in - Map.leave_with_constraint cstr - - and map_module_expr mexpr = - let mexpr = Map.enter_module_expr mexpr in - let mod_desc = - match mexpr.mod_desc with - Tmod_ident _ -> mexpr.mod_desc - | Tmod_structure st -> Tmod_structure (map_structure st) - | Tmod_functor (id, name, mtype, mexpr) -> - Tmod_functor (id, name, Misc.may_map map_module_type mtype, - map_module_expr mexpr) - | Tmod_apply (mexp1, mexp2, coercion) -> - Tmod_apply (map_module_expr mexp1, map_module_expr mexp2, coercion) - | Tmod_constraint (mexpr, mod_type, Tmodtype_implicit, coercion ) -> - Tmod_constraint (map_module_expr mexpr, mod_type, - Tmodtype_implicit, coercion) - | Tmod_constraint (mexpr, mod_type, - Tmodtype_explicit mtype, coercion) -> - Tmod_constraint (map_module_expr mexpr, mod_type, - Tmodtype_explicit (map_module_type mtype), - coercion) - | Tmod_unpack (exp, mod_type) -> - Tmod_unpack (map_expression exp, mod_type) - in - Map.leave_module_expr { mexpr with mod_desc = mod_desc } - - and map_class_expr cexpr = - let cexpr = Map.enter_class_expr cexpr in - let cl_desc = - match cexpr.cl_desc with - | Tcl_constraint (cl, None, string_list1, string_list2, concr ) -> - Tcl_constraint (map_class_expr cl, None, string_list1, - string_list2, concr) - | Tcl_structure clstr -> Tcl_structure (map_class_structure clstr) - | Tcl_fun (label, pat, priv, cl, partial) -> - Tcl_fun (label, map_pattern pat, - List.map (fun (id, name, exp) -> - (id, name, map_expression exp)) priv, - map_class_expr cl, partial) - - | Tcl_apply (cl, args) -> - Tcl_apply (map_class_expr cl, - List.map (fun (label, expo) -> - (label, may_map map_expression expo) - ) args) - | Tcl_let (rec_flag, bindings, ivars, cl) -> - Tcl_let (rec_flag, map_bindings bindings, - List.map (fun (id, name, exp) -> - (id, name, map_expression exp)) ivars, - map_class_expr cl) - - | Tcl_constraint (cl, Some clty, vals, meths, concrs) -> - Tcl_constraint ( map_class_expr cl, - Some (map_class_type clty), vals, meths, concrs) - - | Tcl_ident (id, name, tyl) -> - Tcl_ident (id, name, List.map map_core_type tyl) - | Tcl_open (ovf, p, lid, env, e) -> - Tcl_open (ovf, p, lid, env, map_class_expr e) - in - Map.leave_class_expr { cexpr with cl_desc = cl_desc } - - and map_class_type ct = - let ct = Map.enter_class_type ct in - let cltyp_desc = - match ct.cltyp_desc with - Tcty_signature csg -> Tcty_signature (map_class_signature csg) - | Tcty_constr (path, lid, list) -> - Tcty_constr (path, lid, List.map map_core_type list) - | Tcty_arrow (label, ct, cl) -> - Tcty_arrow (label, map_core_type ct, map_class_type cl) - | Tcty_open (ovf, p, lid, env, e) -> - Tcty_open (ovf, p, lid, env, map_class_type e) - in - Map.leave_class_type { ct with cltyp_desc = cltyp_desc } - - and map_class_signature cs = - let cs = Map.enter_class_signature cs in - let csig_self = map_core_type cs.csig_self in - let csig_fields = List.map map_class_type_field cs.csig_fields in - Map.leave_class_signature { cs with - csig_self = csig_self; csig_fields = csig_fields } - - - and map_class_type_field ctf = - let ctf = Map.enter_class_type_field ctf in - let ctf_desc = - match ctf.ctf_desc with - Tctf_inherit ct -> Tctf_inherit (map_class_type ct) - | Tctf_val (s, mut, virt, ct) -> - Tctf_val (s, mut, virt, map_core_type ct) - | Tctf_method (s, priv, virt, ct) -> - Tctf_method (s, priv, virt, map_core_type ct) - | Tctf_constraint (ct1, ct2) -> - Tctf_constraint (map_core_type ct1, map_core_type ct2) - | Tctf_attribute _ as x -> x - in - Map.leave_class_type_field { ctf with ctf_desc = ctf_desc } - - and map_core_type ct = - let ct = Map.enter_core_type ct in - let ctyp_desc = - match ct.ctyp_desc with - Ttyp_any - | Ttyp_var _ -> ct.ctyp_desc - | Ttyp_arrow (label, ct1, ct2) -> - Ttyp_arrow (label, map_core_type ct1, map_core_type ct2) - | Ttyp_tuple list -> Ttyp_tuple (List.map map_core_type list) - | Ttyp_constr (path, lid, list) -> - Ttyp_constr (path, lid, List.map map_core_type list) - | Ttyp_object (list, o) -> - Ttyp_object - (List.map map_object_field list, o) - | Ttyp_class (path, lid, list) -> - Ttyp_class (path, lid, List.map map_core_type list) - | Ttyp_alias (ct, s) -> Ttyp_alias (map_core_type ct, s) - | Ttyp_variant (list, bool, labels) -> - Ttyp_variant (List.map map_row_field list, bool, labels) - | Ttyp_poly (list, ct) -> Ttyp_poly (list, map_core_type ct) - | Ttyp_package pack -> Ttyp_package (map_package_type pack) - in - Map.leave_core_type { ct with ctyp_desc = ctyp_desc } - - and map_class_structure cs = - let cs = Map.enter_class_structure cs in - let cstr_self = map_pattern cs.cstr_self in - let cstr_fields = List.map map_class_field cs.cstr_fields in - Map.leave_class_structure { cs with cstr_self; cstr_fields } - - and map_row_field rf = - match rf with - Ttag (label, attrs, bool, list) -> - Ttag (label, attrs, bool, List.map map_core_type list) - | Tinherit ct -> Tinherit (map_core_type ct) - - and map_object_field ofield = - match ofield with - OTtag (label, attrs, ct) -> - OTtag (label, attrs, map_core_type ct) - | OTinherit ct -> OTinherit (map_core_type ct) - - and map_class_field cf = - let cf = Map.enter_class_field cf in - let cf_desc = - match cf.cf_desc with - Tcf_inherit (ovf, cl, super, vals, meths) -> - Tcf_inherit (ovf, map_class_expr cl, super, vals, meths) - | Tcf_constraint (cty, cty') -> - Tcf_constraint (map_core_type cty, map_core_type cty') - | Tcf_val (lab, mut, ident, Tcfk_virtual cty, b) -> - Tcf_val (lab, mut, ident, Tcfk_virtual (map_core_type cty), b) - | Tcf_val (lab, mut, ident, Tcfk_concrete (o, exp), b) -> - Tcf_val (lab, mut, ident, Tcfk_concrete (o, map_expression exp), b) - | Tcf_method (lab, priv, Tcfk_virtual cty) -> - Tcf_method (lab, priv, Tcfk_virtual (map_core_type cty)) - | Tcf_method (lab, priv, Tcfk_concrete (o, exp)) -> - Tcf_method (lab, priv, Tcfk_concrete (o, map_expression exp)) - | Tcf_initializer exp -> Tcf_initializer (map_expression exp) - | Tcf_attribute _ as x -> x - in - Map.leave_class_field { cf with cf_desc = cf_desc } -end - - -module DefaultMapArgument = struct - - let enter_structure t = t - let enter_value_description t = t - let enter_type_declaration t = t - let enter_type_extension t = t - let enter_extension_constructor t = t - let enter_pattern t = t - let enter_expression t = t - let enter_package_type t = t - let enter_signature t = t - let enter_signature_item t = t - let enter_module_type_declaration t = t - let enter_module_type t = t - let enter_module_expr t = t - let enter_with_constraint t = t - let enter_class_expr t = t - let enter_class_signature t = t - let enter_class_declaration t = t - let enter_class_description t = t - let enter_class_type_declaration t = t - let enter_class_type t = t - let enter_class_type_field t = t - let enter_core_type t = t - let enter_class_structure t = t - let enter_class_field t = t - let enter_structure_item t = t - - - let leave_structure t = t - let leave_value_description t = t - let leave_type_declaration t = t - let leave_type_extension t = t - let leave_extension_constructor t = t - let leave_pattern t = t - let leave_expression t = t - let leave_package_type t = t - let leave_signature t = t - let leave_signature_item t = t - let leave_module_type_declaration t = t - let leave_module_type t = t - let leave_module_expr t = t - let leave_with_constraint t = t - let leave_class_expr t = t - let leave_class_signature t = t - let leave_class_declaration t = t - let leave_class_description t = t - let leave_class_type_declaration t = t - let leave_class_type t = t - let leave_class_type_field t = t - let leave_core_type t = t - let leave_class_structure t = t - let leave_class_field t = t - let leave_structure_item t = t - -end diff --git a/typing/typedtreeMap.mli b/typing/typedtreeMap.mli deleted file mode 100644 index 7a826ae8..00000000 --- a/typing/typedtreeMap.mli +++ /dev/null @@ -1,94 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Fabrice Le Fessant, INRIA Saclay *) -(* *) -(* Copyright 2012 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -open Typedtree - -module type MapArgument = sig - val enter_structure : structure -> structure - val enter_value_description : value_description -> value_description - val enter_type_declaration : type_declaration -> type_declaration - val enter_type_extension : type_extension -> type_extension - val enter_extension_constructor : - extension_constructor -> extension_constructor - val enter_pattern : pattern -> pattern - val enter_expression : expression -> expression - val enter_package_type : package_type -> package_type - val enter_signature : signature -> signature - val enter_signature_item : signature_item -> signature_item - val enter_module_type_declaration : - module_type_declaration -> module_type_declaration - val enter_module_type : module_type -> module_type - val enter_module_expr : module_expr -> module_expr - val enter_with_constraint : with_constraint -> with_constraint - val enter_class_expr : class_expr -> class_expr - val enter_class_signature : class_signature -> class_signature - val enter_class_declaration : class_declaration -> class_declaration - val enter_class_description : class_description -> class_description - val enter_class_type_declaration : - class_type_declaration -> class_type_declaration - val enter_class_type : class_type -> class_type - val enter_class_type_field : class_type_field -> class_type_field - val enter_core_type : core_type -> core_type - val enter_class_structure : class_structure -> class_structure - val enter_class_field : class_field -> class_field - val enter_structure_item : structure_item -> structure_item - - val leave_structure : structure -> structure - val leave_value_description : value_description -> value_description - val leave_type_declaration : type_declaration -> type_declaration - val leave_type_extension : type_extension -> type_extension - val leave_extension_constructor : - extension_constructor -> extension_constructor - val leave_pattern : pattern -> pattern - val leave_expression : expression -> expression - val leave_package_type : package_type -> package_type - val leave_signature : signature -> signature - val leave_signature_item : signature_item -> signature_item - val leave_module_type_declaration : - module_type_declaration -> module_type_declaration - val leave_module_type : module_type -> module_type - val leave_module_expr : module_expr -> module_expr - val leave_with_constraint : with_constraint -> with_constraint - val leave_class_expr : class_expr -> class_expr - val leave_class_signature : class_signature -> class_signature - val leave_class_declaration : class_declaration -> class_declaration - val leave_class_description : class_description -> class_description - val leave_class_type_declaration : - class_type_declaration -> class_type_declaration - val leave_class_type : class_type -> class_type - val leave_class_type_field : class_type_field -> class_type_field - val leave_core_type : core_type -> core_type - val leave_class_structure : class_structure -> class_structure - val leave_class_field : class_field -> class_field - val leave_structure_item : structure_item -> structure_item - -end - -module MakeMap : - functor - (Iter : MapArgument) -> -sig - val map_structure : structure -> structure - val map_pattern : pattern -> pattern - val map_structure_item : structure_item -> structure_item - val map_expression : expression -> expression - val map_class_expr : class_expr -> class_expr - - val map_signature : signature -> signature - val map_signature_item : signature_item -> signature_item - val map_module_type : module_type -> module_type -end - -module DefaultMapArgument : MapArgument diff --git a/typing/typemod.ml b/typing/typemod.ml index c251f57f..b89f0f0d 100644 --- a/typing/typemod.ml +++ b/typing/typemod.ml @@ -21,6 +21,58 @@ open Parsetree open Types open Format +module String = Misc.Stdlib.String + +module Sig_component_kind = struct + type t = + | Value + | Type + | Module + | Module_type + | Extension_constructor + | Class + | Class_type + + let to_string = function + | Value -> "value" + | Type -> "type" + | Module -> "module" + | Module_type -> "module type" + | Extension_constructor -> "extension constructor" + | Class -> "class" + | Class_type -> "class type" + + (** Whether the name of a component of that kind can appear in a type. *) + let can_appear_in_types = function + | Value + | Extension_constructor -> + false + | Type + | Module + | Module_type + | Class + | Class_type -> + true +end + +type hiding_error = + | Illegal_shadowing of { + shadowed_item_id: Ident.t; + shadowed_item_kind: Sig_component_kind.t; + shadowed_item_loc: Location.t; + shadower_id: Ident.t; + user_id: Ident.t; + user_kind: Sig_component_kind.t; + user_loc: Location.t; + } + | Appears_in_signature of { + opened_item_id: Ident.t; + opened_item_kind: Sig_component_kind.t; + user_id: Ident.t; + user_kind: Sig_component_kind.t; + user_loc: Location.t; + } + type error = Cannot_apply of module_type | Not_included of Includemod.error list @@ -33,7 +85,7 @@ type error = Longident.t * Path.t * Includemod.error list | With_changes_module_alias of Longident.t * Ident.t * Path.t | With_cannot_remove_constrained_type - | Repeated_name of string * string + | Repeated_name of Sig_component_kind.t * string | Non_generalizable of type_expr | Non_generalizable_class of Ident.t * class_declaration | Non_generalizable_module of module_type @@ -46,10 +98,18 @@ type error = | Recursive_module_require_explicit_type | Apply_generative | Cannot_scrape_alias of Path.t + | Badly_formed_signature of string * Typedecl.error + | Cannot_hide_id of hiding_error + | Invalid_type_subst_rhs exception Error of Location.t * Env.t * error exception Error_forward of Location.error +let update_location loc = function + Error (_, env, err) -> Error (loc, env, err) + | err -> err +let () = Typetexp.typemod_update_location := update_location + module ImplementationHooks = Misc.MakeHooks(struct type t = Typedtree.structure * Typedtree.module_coercion end) @@ -59,12 +119,10 @@ module InterfaceHooks = Misc.MakeHooks(struct open Typedtree -let fst3 (x,_,_) = x - let rec path_concat head p = match p with - Pident tail -> Pdot (Pident head, Ident.name tail, 0) - | Pdot (pre, s, pos) -> Pdot (path_concat head pre, s, pos) + Pident tail -> Pdot (Pident head, Ident.name tail) + | Pdot (pre, s) -> Pdot (path_concat head pre, s) | Papply _ -> assert false (* Extract a signature from a module type *) @@ -72,14 +130,14 @@ let rec path_concat head p = let extract_sig env loc mty = match Env.scrape_alias env mty with Mty_signature sg -> sg - | Mty_alias(_, path) -> + | Mty_alias path -> raise(Error(loc, env, Cannot_scrape_alias path)) | _ -> raise(Error(loc, env, Signature_expected)) let extract_sig_open env loc mty = match Env.scrape_alias env mty with Mty_signature sg -> sg - | Mty_alias(_, path) -> + | Mty_alias path -> raise(Error(loc, env, Cannot_scrape_alias path)) | mty -> raise(Error(loc, env, Structure_expected mty)) @@ -94,56 +152,76 @@ let type_open_ ?used_slot ?toplevel ovf env loc lid = ignore (extract_sig_open env lid.loc md.md_type); assert false -let type_initially_opened_module env module_name = - let loc = Location.in_file "compiler internals" in - let lid = { Asttypes.loc; txt = Longident.Lident module_name } in - let path = Typetexp.lookup_module ~load:true env lid.loc lid.txt in - match Env.open_signature_of_initially_opened_module path env with - | Some env -> path, env - | None -> - let md = Env.find_module path env in - ignore (extract_sig_open env lid.loc md.md_type); - assert false - let initial_env ~loc ~safe_string ~initially_opened_module - ~open_implicit_modules = + ~open_implicit_modules = let env = if safe_string then Env.initial_safe_string else Env.initial_unsafe_string in - let env = - match initially_opened_module with - | None -> env - | Some name -> - snd (type_initially_opened_module env name) - in - let open_implicit_module env m = + let open_module env m = let open Asttypes in let lid = {loc; txt = Longident.parse m } in snd (type_open_ Override env lid.loc lid) in - List.fold_left open_implicit_module env open_implicit_modules + let add_units env units = + String.Set.fold + (fun name env -> + Env.add_persistent_structure (Ident.create_persistent name) env) + units + env + in + let units = + List.rev_map Env.persistent_structures_of_dir (Load_path.get ()) + in + let env, units = + match initially_opened_module with + | None -> (env, units) + | Some m -> + (* Locate the directory that contains [m], adds the units it + contains to the environment and open [m] in the resulting + environment. *) + let rec loop before after = + match after with + | [] -> None + | units :: after -> + if String.Set.mem m units then + Some (units, List.rev_append before after) + else + loop (units :: before) after + in + let env, units = + match loop [] units with + | None -> + (env, units) + | Some (units_containing_m, other_units) -> + (add_units env units_containing_m, other_units) + in + (open_module env m, units) + in + let env = List.fold_left add_units env units in + List.fold_left open_module env open_implicit_modules -let type_open ?toplevel env sod = +let type_open_descr ?used_slot ?toplevel env sod = let (path, newenv) = Builtin_attributes.warning_scope sod.popen_attributes (fun () -> - type_open_ ?toplevel sod.popen_override env sod.popen_loc - sod.popen_lid + type_open_ ?used_slot ?toplevel sod.popen_override env sod.popen_loc + sod.popen_expr ) in let od = { + open_expr = (path, sod.popen_expr); + open_bound_items = []; open_override = sod.popen_override; - open_path = path; - open_txt = sod.popen_lid; + open_env = newenv; open_attributes = sod.popen_attributes; open_loc = sod.popen_loc; } in - (path, newenv, od) + (od, newenv) (* Record a module type *) let rm node = @@ -156,10 +234,24 @@ let type_module_type_of_fwd : Typedtree.module_expr * Types.module_type) ref = ref (fun _env _m -> assert false) +(* Additional validity checks on type definitions arising from + recursive modules *) + +let check_recmod_typedecls env decls = + let recmod_ids = List.map fst decls in + List.iter + (fun (id, md) -> + List.iter + (fun path -> + Typedecl.check_recmod_typedecl env md.Types.md_loc recmod_ids + path (Env.find_type path env)) + (Mtype.type_paths env (Pident id) md.Types.md_type)) + decls + (* Merge one "with" constraint in a signature *) let rec add_rec_types env = function - Sig_type(id, decl, Trec_next) :: rem -> + Sig_type(id, decl, Trec_next, _) :: rem -> add_rec_types (Env.add_type ~check:true id decl env) rem | _ -> env @@ -172,27 +264,27 @@ let check_type_decl env loc id row_id newdecl decl rs rem = in let env = if rs = Trec_not then env else add_rec_types env rem in Includemod.type_declarations ~loc env id newdecl decl; - Typedecl.check_coherence env loc id newdecl + Typedecl.check_coherence env loc (Path.Pident id) newdecl let update_rec_next rs rem = match rs with Trec_next -> rem | Trec_first | Trec_not -> match rem with - Sig_type (id, decl, Trec_next) :: rem -> - Sig_type (id, decl, rs) :: rem - | Sig_module (id, mty, Trec_next) :: rem -> - Sig_module (id, mty, rs) :: rem + Sig_type (id, decl, Trec_next, priv) :: rem -> + Sig_type (id, decl, rs, priv) :: rem + | Sig_module (id, pres, mty, Trec_next, priv) :: rem -> + Sig_module (id, pres, mty, rs, priv) :: rem | _ -> rem -let make p n i = +let make_variance p n i = let open Variance in set May_pos p (set May_neg n (set May_weak n (set Inj i null))) let rec iter_path_apply p ~f = match p with | Pident _ -> () - | Pdot (p, _, _) -> iter_path_apply p ~f + | Pdot (p, _) -> iter_path_apply p ~f | Papply (p1, p2) -> iter_path_apply p1 ~f; iter_path_apply p2 ~f; @@ -215,14 +307,14 @@ let path_is_strict_prefix = && list_is_strict_prefix l1 ~prefix:l2 let iterator_with_env env = - let env = ref env in + let env = ref (lazy env) in let super = Btype.type_iterators in env, { super with Btype.it_signature = (fun self sg -> (* add all items to the env before recursing down, to handle recursive definitions *) let env_before = !env in - List.iter (fun i -> env := Env.add_item i !env) sg; + env := lazy (Env.add_signature sg (Lazy.force env_before)); super.Btype.it_signature self sg; env := env_before ); @@ -230,7 +322,8 @@ let iterator_with_env env = | Mty_functor (param, mty_arg, mty_body) -> may (self.Btype.it_module_type self) mty_arg; let env_before = !env in - env := Env.add_module ~arg:true param (Btype.default_mty mty_arg) !env; + env := lazy (Env.add_module ~arg:true param Mp_present + (Btype.default_mty mty_arg) (Lazy.force env_before)); self.Btype.it_module_type self mty_body; env := env_before; | mty -> @@ -261,13 +354,13 @@ let check_usage_of_path_of_substituted_item paths env signature ~loc ~lid = let env, super = iterator_with_env env in { super with Btype.it_signature_item = (fun self -> function - | Sig_module (id, { md_type = Mty_alias (_, aliased_path); _ }, _) + | Sig_module (id, _, { md_type = Mty_alias aliased_path; _ }, _, _) when List.exists (fun path -> path_is_strict_prefix path ~prefix:aliased_path) paths -> let e = With_changes_module_alias (lid.txt, id, aliased_path) in - raise(Error(loc, !env, e)) + raise(Error(loc, Lazy.force !env, e)) | sig_item -> super.Btype.it_signature_item self sig_item ); @@ -277,7 +370,7 @@ let check_usage_of_path_of_substituted_item paths env signature ~loc ~lid = (fun path -> path_is_strict_prefix path ~prefix:arg) paths then - let env = !env in + let env = Lazy.force !env in try retype_applicative_functor_type ~loc env funct arg with Includemod.Error explanation -> raise(Error(loc, env, @@ -290,6 +383,47 @@ let check_usage_of_path_of_substituted_item paths env signature ~loc ~lid = iterator.Btype.it_signature iterator signature; Btype.unmark_iterators.Btype.it_signature Btype.unmark_iterators signature +(* After substitution one also needs to re-check the well-foundedness + of type declarations in recursive modules *) +let rec extract_next_modules = function + | Sig_module (id, _, mty, Trec_next, _) :: rem -> + let (id_mty_l, rem) = extract_next_modules rem in + ((id, mty) :: id_mty_l, rem) + | sg -> ([], sg) + +let check_well_formed_module env loc context mty = + (* Format.eprintf "@[check_well_formed_module@ %a@]@." + Printtyp.modtype mty; *) + let open Btype in + let iterator = + let rec check_signature env = function + | [] -> () + | Sig_module (id, _, mty, Trec_first, _) :: rem -> + let (id_mty_l, rem) = extract_next_modules rem in + begin try + check_recmod_typedecls (Lazy.force env) ((id, mty) :: id_mty_l) + with Typedecl.Error (_, err) -> + raise (Error (loc, Lazy.force env, + Badly_formed_signature(context, err))) + end; + check_signature env rem + | _ :: rem -> + check_signature env rem + in + let env, super = iterator_with_env env in + { super with + it_type_expr = (fun _self _ty -> ()); + it_signature = (fun self sg -> + let env_before = !env in + let env = lazy (Env.add_signature sg (Lazy.force env_before)) in + check_signature env sg; + super.it_signature self sg); + } + in + iterator.it_module_type iterator mty + +let () = Env.check_well_formed_module := check_well_formed_module + let type_decl_is_alias sdecl = (* assuming no explicit constraint *) match sdecl.ptype_manifest with | Some {ptyp_desc = Ptyp_constr (lid, stl)} @@ -336,7 +470,7 @@ let merge_constraint initial_env remove_aliases loc sg constr = match (sg, namelist, constr) with ([], _, _) -> raise(Error(loc, env, With_no_component lid.txt)) - | (Sig_type(id, decl, rs) :: rem, [s], + | (Sig_type(id, decl, rs, priv) :: rem, [s], Pwith_type (_, ({ptype_kind = Ptype_abstract} as sdecl))) when Ident.name id = s && Typedecl.is_fixed_type sdecl -> let decl_row = @@ -355,16 +489,17 @@ let merge_constraint initial_env remove_aliases loc sg constr = | Contravariant -> false, true | Invariant -> false, false in - make (not n) (not c) false + make_variance (not n) (not c) false ) sdecl.ptype_params; type_loc = sdecl.ptype_loc; - type_newtype_level = None; + type_is_newtype = false; + type_expansion_scope = Btype.lowest_level; type_attributes = []; type_immediate = false; type_unboxed = unboxed_false_default_false; } - and id_row = Ident.create (s^"#row") in + and id_row = Ident.create_local (s^"#row") in let initial_env = Env.add_type ~check:false id_row decl_row initial_env in @@ -375,18 +510,21 @@ let merge_constraint initial_env remove_aliases loc sg constr = let decl_row = {decl_row with type_params = newdecl.type_params} in let rs' = if rs = Trec_first then Trec_not else rs in (Pident id, lid, Twith_type tdecl), - Sig_type(id_row, decl_row, rs') :: Sig_type(id, newdecl, rs) :: rem - | (Sig_type(id, decl, rs) :: rem , [s], Pwith_type (_, sdecl)) + Sig_type(id_row, decl_row, rs', priv) + :: Sig_type(id, newdecl, rs, priv) + :: rem + | (Sig_type(id, decl, rs, priv) :: rem , [s], Pwith_type (_, sdecl)) when Ident.name id = s -> let tdecl = Typedecl.transl_with_constraint initial_env id None decl sdecl in let newdecl = tdecl.typ_type in check_type_decl env sdecl.ptype_loc id row_id newdecl decl rs rem; - (Pident id, lid, Twith_type tdecl), Sig_type(id, newdecl, rs) :: rem - | (Sig_type(id, _, _) :: rem, [s], (Pwith_type _ | Pwith_typesubst _)) + (Pident id, lid, Twith_type tdecl), + Sig_type(id, newdecl, rs, priv) :: rem + | (Sig_type(id, _, _, _) :: rem, [s], (Pwith_type _ | Pwith_typesubst _)) when Ident.name id = s ^ "#row" -> merge env rem namelist (Some id) - | (Sig_type(id, decl, rs) :: rem, [s], Pwith_typesubst (_, sdecl)) + | (Sig_type(id, decl, rs, _priv) :: rem, [s], Pwith_typesubst (_, sdecl)) when Ident.name id = s -> (* Check as for a normal with constraint, but discard definition *) let tdecl = @@ -396,7 +534,7 @@ let merge_constraint initial_env remove_aliases loc sg constr = real_ids := [Pident id]; (Pident id, lid, Twith_typesubst tdecl), update_rec_next rs rem - | (Sig_module(id, md, rs) :: rem, [s], Pwith_module (_, lid')) + | (Sig_module(id, pres, md, rs, priv) :: rem, [s], Pwith_module (_, lid')) when Ident.name id = s -> let path, md' = Typetexp.find_module initial_env loc lid'.txt in let mty = md'.md_type in @@ -405,8 +543,8 @@ let merge_constraint initial_env remove_aliases loc sg constr = let newmd = Mtype.strengthen_decl ~aliasable:false env md'' path in ignore(Includemod.modtypes ~loc env newmd.md_type md.md_type); (Pident id, lid, Twith_module (path, lid')), - Sig_module(id, newmd, rs) :: rem - | (Sig_module(id, md, rs) :: rem, [s], Pwith_modsubst (_, lid')) + Sig_module(id, pres, newmd, rs, priv) :: rem + | (Sig_module(id, _, md, rs, _) :: rem, [s], Pwith_modsubst (_, lid')) when Ident.name id = s -> let path, md' = Typetexp.find_module initial_env loc lid'.txt in let aliasable = not (Env.is_functor_arg path env) in @@ -415,13 +553,24 @@ let merge_constraint initial_env remove_aliases loc sg constr = real_ids := [Pident id]; (Pident id, lid, Twith_modsubst (path, lid')), update_rec_next rs rem - | (Sig_module(id, md, rs) :: rem, s :: namelist, _) + | (Sig_module(id, _, ({md_type = Mty_alias _} as md), _, _) as item :: rem, + s :: namelist, (Pwith_module _ | Pwith_type _)) + when Ident.name id = s -> + let ((path, _, tcstr), _) = + merge env (extract_sig env loc md.md_type) namelist None + in + let path = path_concat id path in + real_ids := path :: !real_ids; + (path, lid, tcstr), item :: rem + | (Sig_module(id, _, md, rs, priv) :: rem, s :: namelist, _) when Ident.name id = s -> let ((path, _path_loc, tcstr), newsg) = - merge env (extract_sig env loc md.md_type) namelist None in + merge env (extract_sig env loc md.md_type) namelist None + in let path = path_concat id path in real_ids := path :: !real_ids; - let item = Sig_module(id, {md with md_type=Mty_signature newsg}, rs) in + let newmd = {md with md_type=Mty_signature newsg} in + let item = Sig_module(id, Mp_present, newmd, rs, priv) in (path, lid, tcstr), item :: rem | (item :: rem, _, _) -> @@ -469,11 +618,16 @@ let merge_constraint initial_env remove_aliases loc sg constr = in let params = tdecl.typ_type.type_params in if params_are_constrained params - then raise(Error(loc, initial_env, With_cannot_remove_constrained_type)); + then raise(Error(loc, initial_env, + With_cannot_remove_constrained_type)); fun s path -> Subst.add_type_function path ~params ~body s in let sub = List.fold_left how_to_extend_subst Subst.identity !real_ids in - Subst.signature sub sg + (* This signature will not be used direcly, it will always be freshened + by the caller. So what we do with the scope doesn't really matter. But + making it local makes it unlikely that we will ever use the result of + this function unfreshened without issue. *) + Subst.signature Make_local sub sg | (_, _, Twith_modsubst (real_path, _)) -> let sub = List.fold_left @@ -481,10 +635,13 @@ let merge_constraint initial_env remove_aliases loc sg constr = Subst.identity !real_ids in - Subst.signature sub sg + (* See explanation in the [Twith_typesubst] case above. *) + Subst.signature Make_local sub sg | _ -> sg in + check_well_formed_module initial_env loc "this instantiated signature" + (Mty_signature sg); (tcstr, sg) with Includemod.Error explanation -> raise(Error(loc, initial_env, With_mismatch(lid.txt, explanation))) @@ -536,17 +693,34 @@ let rec approx_modtype env smty = Mty_ident path | Pmty_alias lid -> let path = Typetexp.lookup_module env smty.pmty_loc lid.txt in - Mty_alias(Mta_absent, path) + Mty_alias path | Pmty_signature ssg -> Mty_signature(approx_sig env ssg) | Pmty_functor(param, sarg, sres) -> let arg = may_map (approx_modtype env) sarg in let rarg = Mtype.scrape_for_functor_arg env (Btype.default_mty arg) in - let (id, newenv) = Env.enter_module ~arg:true param.txt rarg env in + let scope = Ctype.create_scope () in + let (id, newenv) = + Env.enter_module ~scope ~arg:true param.txt + Mp_present rarg env + in let res = approx_modtype newenv sres in Mty_functor(id, arg, res) - | Pmty_with(sbody, _constraints) -> - approx_modtype env sbody + | Pmty_with(sbody, constraints) -> + let body = approx_modtype env sbody in + List.iter + (fun sdecl -> + match sdecl with + | Pwith_type _ -> () + | Pwith_typesubst _ -> () + | Pwith_module (_, lid') -> + (* Lookup the module to make sure that it is not recursive. + (GPR#1626) *) + ignore (Typetexp.find_module env lid'.loc lid'.txt) + | Pwith_modsubst (_, lid') -> + ignore (Typetexp.find_module env lid'.loc lid'.txt)) + constraints; + body | Pmty_typeof smod -> let (_, mty) = !type_module_type_of_fwd env smod in mty @@ -569,17 +743,38 @@ and approx_sig env ssg = let decls = Typedecl.approx_type_decl sdecls in let rem = approx_sig env srem in map_rec_type ~rec_flag - (fun rs (id, info) -> Sig_type(id, info, rs)) decls rem + (fun rs (id, info) -> Sig_type(id, info, rs, Exported)) decls rem + | Psig_typesubst _ -> approx_sig env srem | Psig_module pmd -> - let id = Ident.create pmd.pmd_name.txt in + let scope = Ctype.create_scope () in + let id = Ident.create_scoped ~scope pmd.pmd_name.txt in let md = approx_module_declaration env pmd in - let newenv = Env.enter_module_declaration id md env in - Sig_module(id, md, Trec_not) :: approx_sig newenv srem + let pres = + match md.Types.md_type with + | Mty_alias _ -> Mp_absent + | _ -> Mp_present + in + let newenv = Env.enter_module_declaration id pres md env in + Sig_module(id, pres, md, Trec_not, Exported) :: approx_sig newenv srem + | Psig_modsubst pms -> + let scope = Ctype.create_scope () in + let id = Ident.create_scoped ~scope pms.pms_name.txt in + let _, md = + Typetexp.find_module env pms.pms_manifest.loc pms.pms_manifest.txt + in + let pres = + match md.Types.md_type with + | Mty_alias _ -> Mp_absent + | _ -> Mp_present + in + let newenv = Env.enter_module_declaration id pres md env in + approx_sig newenv srem | Psig_recmodule sdecls -> + let scope = Ctype.create_scope () in let decls = List.map (fun pmd -> - (Ident.create pmd.pmd_name.txt, + (Ident.create_scoped ~scope pmd.pmd_name.txt, approx_module_declaration env pmd) ) sdecls @@ -587,35 +782,42 @@ and approx_sig env ssg = let newenv = List.fold_left (fun env (id, md) -> Env.add_module_declaration ~check:false - id md env) - env decls in - map_rec (fun rs (id, md) -> Sig_module(id, md, rs)) decls - (approx_sig newenv srem) + id Mp_present md env) + env decls + in + map_rec + (fun rs (id, md) -> Sig_module(id, Mp_present, md, rs, Exported)) + decls + (approx_sig newenv srem) | Psig_modtype d -> let info = approx_modtype_info env d in - let (id, newenv) = Env.enter_modtype d.pmtd_name.txt info env in - Sig_modtype(id, info) :: approx_sig newenv srem + let scope = Ctype.create_scope () in + let (id, newenv) = + Env.enter_modtype ~scope d.pmtd_name.txt info env + in + Sig_modtype(id, info, Exported) :: approx_sig newenv srem | Psig_open sod -> - let (_path, mty, _od) = type_open env sod in - approx_sig mty srem + let _, env = type_open_descr env sod in + approx_sig env srem | Psig_include sincl -> let smty = sincl.pincl_mod in let mty = approx_modtype env smty in - let sg = Subst.signature Subst.identity - (extract_sig env smty.pmty_loc mty) in - let newenv = Env.add_signature sg env in + let scope = Ctype.create_scope () in + let sg, newenv = Env.enter_signature ~scope + (extract_sig env smty.pmty_loc mty) env in sg @ approx_sig newenv srem | Psig_class sdecls | Psig_class_type sdecls -> let decls = Typeclass.approx_class_declarations env sdecls in let rem = approx_sig env srem in - List.flatten - (map_rec - (fun rs decl -> - let open Typeclass in - [Sig_class_type(decl.clsty_ty_id, decl.clsty_ty_decl, rs); - Sig_type(decl.clsty_obj_id, decl.clsty_obj_abbr, rs); - Sig_type(decl.clsty_typesharp_id, decl.clsty_abbr, rs)]) - decls [rem]) + map_rec (fun rs decl -> + let open Typeclass in [ + Sig_class_type(decl.clsty_ty_id, decl.clsty_ty_decl, rs, + Exported); + Sig_type(decl.clsty_obj_id, decl.clsty_obj_abbr, rs, Exported); + Sig_type(decl.clsty_typesharp_id, decl.clsty_abbr, rs, Exported); + ] + ) decls [rem] + |> List.flatten | _ -> approx_sig env srem @@ -630,81 +832,237 @@ let approx_modtype env smty = Warnings.without_warnings (fun () -> approx_modtype env smty) -(* Additional validity checks on type definitions arising from - recursive modules *) - -let check_recmod_typedecls env sdecls decls = - let recmod_ids = List.map fst3 decls in - List.iter2 - (fun pmd (id, _, mty) -> - let mty = mty.mty_type in - List.iter - (fun path -> - Typedecl.check_recmod_typedecl env pmd.pmd_type.pmty_loc recmod_ids - path (Env.find_type path env)) - (Mtype.type_paths env (Pident id) mty)) - sdecls decls - -(* Auxiliaries for checking uniqueness of names in signatures and structures *) - -module StringSet = - Set.Make(struct type t = string let compare (x:t) y = String.compare x y end) +(* Auxiliaries for checking the validity of name shadowing in signatures and + structures. + If a shadowing is valid, we also record some information (its ident, + location where it first appears, etc) about the item that gets shadowed. *) +module Signature_names : sig + type t + + type info = [ + | `Exported + | `From_open + | `Shadowable of Ident.t * Location.t + | `Substituted_away of Subst.t + ] + + val create : unit -> t + + val check_value : ?info:info -> t -> Location.t -> Ident.t -> unit + val check_type : ?info:info -> t -> Location.t -> Ident.t -> unit + val check_typext : ?info:info -> t -> Location.t -> Ident.t -> unit + val check_module : ?info:info -> t -> Location.t -> Ident.t -> unit + val check_modtype : ?info:info -> t -> Location.t -> Ident.t -> unit + val check_class : ?info:info -> t -> Location.t -> Ident.t -> unit + val check_class_type: ?info:info -> t -> Location.t -> Ident.t -> unit + + val check_sig_item: + ?info:info -> t -> Location.t -> Types.signature_item -> unit + + val simplify: Env.t -> t -> Types.signature -> Types.signature +end = struct + + type bound_info = [ + | `Exported + | `Shadowable of Ident.t * Location.t + ] + + type info = [ + | `From_open + | `Substituted_away of Subst.t + | bound_info + ] + + type hide_reason = + | From_open + | Shadowed_by of Ident.t * Location.t + + type to_be_removed = { + mutable subst: Subst.t; + mutable hide: (Sig_component_kind.t * Location.t * hide_reason) Ident.Map.t; + } -let check cl loc set_ref name = - if StringSet.mem name !set_ref - then raise(Error(loc, Env.empty, Repeated_name(cl, name))) - else set_ref := StringSet.add name !set_ref + type names_infos = (string, bound_info) Hashtbl.t -type names = - { - types: StringSet.t ref; - modules: StringSet.t ref; - modtypes: StringSet.t ref; - typexts: StringSet.t ref; + type names = { + values: names_infos; + types: names_infos; + modules: names_infos; + modtypes: names_infos; + typexts: names_infos; + classes: names_infos; + class_types: names_infos; } -let new_names () = - { - types = ref StringSet.empty; - modules = ref StringSet.empty; - modtypes = ref StringSet.empty; - typexts = ref StringSet.empty; + let new_names () = { + values = Hashtbl.create 16; + types = Hashtbl.create 16; + modules = Hashtbl.create 16; + modtypes = Hashtbl.create 16; + typexts = Hashtbl.create 16; + classes = Hashtbl.create 16; + class_types = Hashtbl.create 16; } + type t = { + bound: names; + to_be_removed: to_be_removed; + } -let check_name check names name = check names name.loc name.txt -let check_type names loc s = check "type" loc names.types s -let check_module names loc s = check "module" loc names.modules s -let check_modtype names loc s = check "module type" loc names.modtypes s -let check_typext names loc s = check "extension constructor" loc names.typexts s - - -let check_sig_item names loc = function - | Sig_type(id, _, _) -> check_type names loc (Ident.name id) - | Sig_module(id, _, _) -> check_module names loc (Ident.name id) - | Sig_modtype(id, _) -> check_modtype names loc (Ident.name id) - | Sig_typext(id, _, _) -> check_typext names loc (Ident.name id) - | _ -> () - -(* Simplify multiple specifications of a value or an extension in a signature. - (Other signature components, e.g. types, modules, etc, are checked for - name uniqueness.) If multiple specifications with the same name, - keep only the last (rightmost) one. *) + let create () = { + bound = new_names (); + to_be_removed = { + subst = Subst.identity; + hide = Ident.Map.empty; + }; + } -let simplify_signature sg = - let rec aux = function - | [] -> [], StringSet.empty - | (Sig_value(id, _descr) as component) :: sg -> - let (sg, val_names) as k = aux sg in + let check cl loc (tbl : names_infos) id (info : info) to_be_removed = + match info with + | `Substituted_away s -> + to_be_removed.subst <- Subst.compose s to_be_removed.subst + | `From_open -> + to_be_removed.hide <- + Ident.Map.add id (cl, loc, From_open) to_be_removed.hide + | #bound_info as bound_info -> let name = Ident.name id in - if StringSet.mem name val_names then k - else (component :: sg, StringSet.add name val_names) - | component :: sg -> - let (sg, val_names) = aux sg in - (component :: sg, val_names) - in - let (sg, _) = aux sg in - sg + match Hashtbl.find_opt tbl name with + | None -> Hashtbl.add tbl name bound_info + | Some (`Shadowable (shadowed_id, shadowed_loc)) -> + Hashtbl.replace tbl name bound_info; + let reason = Shadowed_by (id, loc) in + to_be_removed.hide <- + Ident.Map.add shadowed_id (cl, shadowed_loc, reason) + to_be_removed.hide + | Some `Exported -> + raise(Error(loc, Env.empty, Repeated_name(cl, name))) + + let check_value ?info t loc id = + let info = + match info with + | Some i -> i + | None -> `Shadowable (id, loc) + in + check Sig_component_kind.Value loc t.bound.values id info t.to_be_removed + let check_type ?(info=`Exported) t loc id = + check Sig_component_kind.Type loc t.bound.types id info t.to_be_removed + let check_module ?(info=`Exported) t loc id = + check Sig_component_kind.Module loc t.bound.modules id info t.to_be_removed + let check_modtype ?(info=`Exported) t loc id = + check Sig_component_kind.Module_type loc t.bound.modtypes id info + t.to_be_removed + let check_typext ?(info=`Exported) t loc id = + check Sig_component_kind.Extension_constructor loc t.bound.typexts id info + t.to_be_removed + let check_class ?(info=`Exported) t loc id = + check Sig_component_kind.Class loc t.bound.classes id info t.to_be_removed + let check_class_type ?(info=`Exported) t loc id = + check Sig_component_kind.Class_type loc t.bound.class_types id info + t.to_be_removed + + let check_sig_item ?info names loc component = + let info id loc = + match info with + | None -> `Shadowable (id, loc) + | Some i -> i + in + match component with + | Sig_type(id, _, _, _) -> + check_type names loc id ~info:(info id loc) + | Sig_module(id, _, _, _, _) -> + check_module names loc id ~info:(info id loc) + | Sig_modtype(id, _, _) -> + check_modtype names loc id ~info:(info id loc) + | Sig_typext(id, _, _, _) -> + check_typext names loc id ~info:(info id loc) + | Sig_value (id, _, _) -> + check_value names loc id ~info:(info id loc) + | Sig_class (id, _, _, _) -> + check_class names loc id ~info:(info id loc) + | Sig_class_type (id, _, _, _) -> + check_class_type names loc id ~info:(info id loc) + + (* We usually require name uniqueness of signature components (e.g. types, + modules, etc), however in some situation reusing the name is allowed: if + the component is a value or an extension, or if the name is introduced by + an include. + When there are multiple specifications of a component with the same name, + we try to keep only the last (rightmost) one, removing all references to + the previous ones from the signature. + If some reference cannot be removed, then we error out with + [Cannot_hide_id]. + *) + + let simplify env t sg = + let to_remove = t.to_be_removed in + let ids_to_remove = + Ident.Map.fold (fun id (kind, _, _) lst -> + if Sig_component_kind.can_appear_in_types kind then + id :: lst + else + lst + ) to_remove.hide [] + in + let aux component sg = + let user_kind, user_id, user_loc = + let open Sig_component_kind in + match component with + | Sig_value(id, v, _) -> Value, id, v.val_loc + | Sig_type (id, td, _, _) -> Type, id, td.type_loc + | Sig_typext (id, te, _, _) -> Extension_constructor, id, te.ext_loc + | Sig_module (id, _, md, _, _) -> Module, id, md.md_loc + | Sig_modtype (id, mtd, _) -> Module_type, id, mtd.mtd_loc + | Sig_class (id, c, _, _) -> Class, id, c.cty_loc + | Sig_class_type (id, ct, _, _) -> Class_type, id, ct.clty_loc + in + if Ident.Map.mem user_id to_remove.hide then + sg + else begin + let component = + if to_remove.subst == Subst.identity then + component + else + Subst.signature_item Keep to_remove.subst component + in + let component = + match ids_to_remove with + | [] -> component + | ids -> + try Mtype.nondep_sig_item env ids component with + | Ctype.Nondep_cannot_erase removed_item_id -> + let (removed_item_kind, removed_item_loc, reason) = + Ident.Map.find removed_item_id to_remove.hide + in + let err_loc, hiding_error = + match reason with + | From_open -> + removed_item_loc, + Appears_in_signature { + opened_item_kind = removed_item_kind; + opened_item_id = removed_item_id; + user_id; + user_kind; + user_loc; + } + | Shadowed_by (shadower_id, shadower_loc) -> + shadower_loc, + Illegal_shadowing { + shadowed_item_kind = removed_item_kind; + shadowed_item_id = removed_item_id; + shadowed_item_loc = removed_item_loc; + shadower_id; + user_id; + user_kind; + user_loc; + } + in + raise (Error(err_loc, env, Cannot_hide_id hiding_error)) + in + component :: sg + end + in + List.fold_right aux sg [] +end let has_remove_aliases_attribute attr = let remove_aliases = @@ -759,7 +1117,7 @@ and transl_modtype_aux env smty = smty.pmty_attributes | Pmty_alias lid -> let path = transl_module_alias loc env lid.txt in - mkmty (Tmty_alias (path, lid)) (Mty_alias(Mta_absent, path)) env loc + mkmty (Tmty_alias (path, lid)) (Mty_alias path) env loc smty.pmty_attributes | Pmty_signature ssg -> let sg = transl_signature env ssg in @@ -768,9 +1126,11 @@ and transl_modtype_aux env smty = | Pmty_functor(param, sarg, sres) -> let arg = Misc.may_map (transl_modtype_functor_arg env) sarg in let ty_arg = Misc.may_map (fun m -> m.mty_type) arg in + let scope = Ctype.create_scope () in let (id, newenv) = - Env.enter_module ~arg:true param.txt (Btype.default_mty ty_arg) env in - Ctype.init_def(Ident.current_time()); (* PR#6513 *) + Env.enter_module ~scope ~arg:true + param.txt Mp_present (Btype.default_mty ty_arg) env + in let res = transl_modtype newenv sres in mkmty (Tmty_functor (id, param, arg, res)) (Mty_functor(id, ty_arg, res.mty_type)) env loc @@ -788,8 +1148,9 @@ and transl_modtype_aux env smty = (tcstr :: rev_tcstrs, sg) ) ([],init_sg) constraints in + let scope = Ctype.create_scope () in mkmty (Tmty_with ( body, List.rev rev_tcstrs)) - (Mtype.freshen (Mty_signature final_sg)) env loc + (Mtype.freshen ~scope (Mty_signature final_sg)) env loc smty.pmty_attributes | Pmty_typeof smod -> let env = Env.in_signature false env in @@ -799,9 +1160,8 @@ and transl_modtype_aux env smty = raise (Error_forward (Builtin_attributes.error_of_extension ext)) and transl_signature env sg = - let names = new_names () in + let names = Signature_names.create () in let rec transl_sig env sg = - Ctype.init_def(Ident.current_time()); match sg with [] -> [], [], env | item :: srem -> @@ -811,69 +1171,150 @@ and transl_signature env sg = let (tdesc, newenv) = Typedecl.transl_value_decl env item.psig_loc sdesc in + Signature_names.check_value names tdesc.val_loc tdesc.val_id; let (trem,rem, final_env) = transl_sig newenv srem in mksig (Tsig_value tdesc) env loc :: trem, - Sig_value(tdesc.val_id, tdesc.val_val) :: rem, + Sig_value(tdesc.val_id, tdesc.val_val, Exported) :: rem, final_env | Psig_type (rec_flag, sdecls) -> - List.iter - (fun decl -> check_name check_type names decl.ptype_name) - sdecls; let (decls, newenv) = Typedecl.transl_type_decl env rec_flag sdecls in + List.iter (fun td -> + Signature_names.check_type names td.typ_loc td.typ_id + ) decls; let (trem, rem, final_env) = transl_sig newenv srem in + let sg = + map_rec_type_with_row_types ~rec_flag + (fun rs td -> Sig_type(td.typ_id, td.typ_type, rs, Exported)) + decls rem + in mksig (Tsig_type (rec_flag, decls)) env loc :: trem, - map_rec_type_with_row_types ~rec_flag - (fun rs td -> Sig_type(td.typ_id, td.typ_type, rs)) decls rem, + sg, + final_env + | Psig_typesubst sdecls -> + List.iter (fun td -> + if td.ptype_kind <> Ptype_abstract || td.ptype_manifest = None || + td.ptype_private = Private + then + (* This error should be a parsing error, + once we have nice error messages there. *) + raise (Error (td.ptype_loc, env, Invalid_type_subst_rhs)) + ) sdecls; + let (decls, newenv) = + Typedecl.transl_type_decl env Nonrecursive sdecls + in + List.iter (fun td -> + let info = + let subst = + Subst.add_type_function (Pident td.typ_id) + ~params:td.typ_type.type_params + ~body:(Option.get td.typ_type.type_manifest) + Subst.identity + in + Some (`Substituted_away subst) + in + Signature_names.check_type ?info names td.typ_loc td.typ_id + ) decls; + let (trem, rem, final_env) = transl_sig newenv srem in + let sg = rem + in + mksig (Tsig_typesubst decls) env loc :: trem, + sg, final_env | Psig_typext styext -> - List.iter - (fun pext -> check_name check_typext names pext.pext_name) - styext.ptyext_constructors; let (tyext, newenv) = Typedecl.transl_type_extension false env item.psig_loc styext in - let (trem, rem, final_env) = transl_sig newenv srem in let constructors = tyext.tyext_constructors in + List.iter (fun ext -> + Signature_names.check_typext names ext.ext_loc ext.ext_id + ) constructors; + let (trem, rem, final_env) = transl_sig newenv srem in mksig (Tsig_typext tyext) env loc :: trem, map_ext (fun es ext -> - Sig_typext(ext.ext_id, ext.ext_type, es)) constructors rem, + Sig_typext(ext.ext_id, ext.ext_type, es, Exported) + ) constructors rem, final_env | Psig_exception sext -> - check_name check_typext names sext.pext_name; - let (ext, newenv) = Typedecl.transl_exception env sext in + let (ext, newenv) = Typedecl.transl_type_exception env sext in + let constructor = ext.tyexn_constructor in + Signature_names.check_typext names constructor.ext_loc + constructor.ext_id; let (trem, rem, final_env) = transl_sig newenv srem in mksig (Tsig_exception ext) env loc :: trem, - Sig_typext(ext.ext_id, ext.ext_type, Text_exception) :: rem, + Sig_typext(constructor.ext_id, + constructor.ext_type, + Text_exception, + Exported) :: rem, final_env | Psig_module pmd -> - check_name check_module names pmd.pmd_name; - let id = Ident.create pmd.pmd_name.txt in + let scope = Ctype.create_scope () in + let id = Ident.create_scoped ~scope pmd.pmd_name.txt in let tmty = Builtin_attributes.warning_scope pmd.pmd_attributes (fun () -> transl_modtype env pmd.pmd_type) in + let pres = + match tmty.mty_type with + | Mty_alias _ -> Mp_absent + | _ -> Mp_present + in let md = { md_type=tmty.mty_type; md_attributes=pmd.pmd_attributes; md_loc=pmd.pmd_loc; } in - let newenv = Env.enter_module_declaration id md env in + Signature_names.check_module names pmd.pmd_name.loc id; + let newenv = Env.enter_module_declaration id pres md env in let (trem, rem, final_env) = transl_sig newenv srem in - mksig (Tsig_module {md_id=id; md_name=pmd.pmd_name; md_type=tmty; + mksig (Tsig_module {md_id=id; md_name=pmd.pmd_name; + md_presence=pres; md_type=tmty; md_loc=pmd.pmd_loc; md_attributes=pmd.pmd_attributes}) env loc :: trem, - Sig_module(id, md, Trec_not) :: rem, + Sig_module(id, pres, md, Trec_not, Exported) :: rem, + final_env + | Psig_modsubst pms -> + let scope = Ctype.create_scope () in + let id = Ident.create_scoped ~scope pms.pms_name.txt in + let path, md = + Typetexp.find_module env pms.pms_manifest.loc pms.pms_manifest.txt + in + let aliasable = not (Env.is_functor_arg path env) in + let md = + if not aliasable then + md + else + { md_type = Mty_alias path; + md_attributes = pms.pms_attributes; + md_loc = pms.pms_loc } + in + let pres = + match md.md_type with + | Mty_alias _ -> Mp_absent + | _ -> Mp_present + in + let info = + `Substituted_away (Subst.add_module id path Subst.identity) + in + Signature_names.check_module ~info names pms.pms_name.loc id; + let newenv = Env.enter_module_declaration id pres md env in + let (trem, rem, final_env) = transl_sig newenv srem in + mksig (Tsig_modsubst {ms_id=id; ms_name=pms.pms_name; + ms_manifest=path; ms_txt=pms.pms_manifest; + ms_loc=pms.pms_loc; + ms_attributes=pms.pms_attributes}) + env loc :: trem, + rem, final_env | Psig_recmodule sdecls -> - List.iter - (fun pmd -> check_name check_module names pmd.pmd_name) - sdecls; let (decls, newenv) = transl_recmodule_modtypes env sdecls in + List.iter + (fun md -> Signature_names.check_module names md.md_loc md.md_id) + decls; let (trem, rem, final_env) = transl_sig newenv srem in mksig (Tsig_recmodule decls) env loc :: trem, map_rec (fun rs md -> @@ -881,19 +1322,17 @@ and transl_signature env sg = md_attributes = md.md_attributes; md_loc = md.md_loc; } in - Sig_module(md.md_id, d, rs)) + Sig_module(md.md_id, Mp_present, d, rs, Exported)) decls rem, final_env | Psig_modtype pmtd -> - let newenv, mtd, sg = - transl_modtype_decl names env pmtd - in + let newenv, mtd, sg = transl_modtype_decl names env pmtd in let (trem, rem, final_env) = transl_sig newenv srem in mksig (Tsig_modtype mtd) env loc :: trem, sg :: rem, final_env | Psig_open sod -> - let (_path, newenv, od) = type_open env sod in + let (od, newenv) = type_open_descr env sod in let (trem, rem, final_env) = transl_sig newenv srem in mksig (Tsig_open od) env loc :: trem, rem, final_env @@ -904,10 +1343,10 @@ and transl_signature env sg = (fun () -> transl_modtype env smty) in let mty = tmty.mty_type in - let sg = Subst.signature Subst.identity - (extract_sig env smty.pmty_loc mty) in - List.iter (check_sig_item names item.psig_loc) sg; - let newenv = Env.add_signature sg env in + let scope = Ctype.create_scope () in + let sg, newenv = Env.enter_signature ~scope + (extract_sig env smty.pmty_loc mty) env in + List.iter (Signature_names.check_sig_item names item.psig_loc) sg; let incl = { incl_mod = tmty; incl_type = sg; @@ -920,43 +1359,63 @@ and transl_signature env sg = sg @ rem, final_env | Psig_class cl -> - List.iter - (fun {pci_name} -> check_name check_type names pci_name) - cl; let (classes, newenv) = Typeclass.class_descriptions env cl in + List.iter (fun cls -> + let open Typeclass in + let loc = cls.cls_id_loc.Location.loc in + Signature_names.check_type names loc cls.cls_obj_id; + Signature_names.check_class names loc cls.cls_id; + Signature_names.check_class_type names loc cls.cls_ty_id; + Signature_names.check_type names loc cls.cls_typesharp_id; + ) classes; let (trem, rem, final_env) = transl_sig newenv srem in - mksig (Tsig_class - (List.map (fun decr -> + let sg = + map_rec (fun rs cls -> + let open Typeclass in + [Sig_class(cls.cls_id, cls.cls_decl, rs, Exported); + Sig_class_type(cls.cls_ty_id, cls.cls_ty_decl, rs, Exported); + Sig_type(cls.cls_obj_id, cls.cls_obj_abbr, rs, Exported); + Sig_type(cls.cls_typesharp_id, cls.cls_abbr, rs, Exported)] + ) classes [rem] + |> List.flatten + in + let typedtree = + mksig (Tsig_class + (List.map (fun decr -> decr.Typeclass.cls_info) classes)) env loc - :: trem, - List.flatten - (map_rec - (fun rs cls -> - let open Typeclass in - [Sig_class(cls.cls_id, cls.cls_decl, rs); - Sig_class_type(cls.cls_ty_id, cls.cls_ty_decl, rs); - Sig_type(cls.cls_obj_id, cls.cls_obj_abbr, rs); - Sig_type(cls.cls_typesharp_id, cls.cls_abbr, rs)]) - classes [rem]), - final_env + :: trem + in + typedtree, sg, final_env | Psig_class_type cl -> - List.iter - (fun {pci_name} -> check_name check_type names pci_name) - cl; let (classes, newenv) = Typeclass.class_type_declarations env cl in + List.iter (fun decl -> + let open Typeclass in + let loc = decl.clsty_id_loc.Location.loc in + Signature_names.check_class_type names loc decl.clsty_ty_id; + Signature_names.check_type names loc decl.clsty_obj_id; + Signature_names.check_type names loc decl.clsty_typesharp_id; + ) classes; let (trem,rem, final_env) = transl_sig newenv srem in - mksig (Tsig_class_type - (List.map (fun decl -> decl.Typeclass.clsty_info) classes)) - env loc :: trem, - List.flatten - (map_rec - (fun rs decl -> - let open Typeclass in - [Sig_class_type(decl.clsty_ty_id, decl.clsty_ty_decl, rs); - Sig_type(decl.clsty_obj_id, decl.clsty_obj_abbr, rs); - Sig_type(decl.clsty_typesharp_id, decl.clsty_abbr, rs)]) - classes [rem]), - final_env + let sg = + map_rec (fun rs decl -> + let open Typeclass in + [Sig_class_type(decl.clsty_ty_id, decl.clsty_ty_decl, rs, + Exported); + Sig_type(decl.clsty_obj_id, decl.clsty_obj_abbr, rs, Exported); + Sig_type(decl.clsty_typesharp_id, decl.clsty_abbr, rs, + Exported) + ] + ) classes [rem] + |> List.flatten + in + let typedtree = + mksig + (Tsig_class_type + (List.map (fun decl -> decl.Typeclass.clsty_info) classes)) + env loc + :: trem + in + typedtree, sg, final_env | Psig_attribute x -> Builtin_attributes.warning_attribute x; let (trem,rem, final_env) = transl_sig env srem in @@ -968,8 +1427,10 @@ and transl_signature env sg = Builtin_attributes.warning_scope [] (fun () -> let (trem, rem, final_env) = transl_sig (Env.in_signature true env) sg in - let rem = simplify_signature rem in - let sg = { sig_items = trem; sig_type = rem; sig_final_env = final_env } in + let rem = Signature_names.simplify final_env names rem in + let sg = + { sig_items = trem; sig_type = rem; sig_final_env = final_env } + in Cmt_format.set_saved_types ((Cmt_format.Partial_signature sg) :: previous_saved_types); sg @@ -981,7 +1442,6 @@ and transl_modtype_decl names env pmtd = and transl_modtype_decl_aux names env {pmtd_name; pmtd_type; pmtd_attributes; pmtd_loc} = - check_name check_modtype names pmtd_name; let tmty = Misc.may_map (transl_modtype env) pmtd_type in let decl = { @@ -990,7 +1450,9 @@ and transl_modtype_decl_aux names env mtd_loc=pmtd_loc; } in - let (id, newenv) = Env.enter_modtype pmtd_name.txt decl env in + let scope = Ctype.create_scope () in + let (id, newenv) = Env.enter_modtype ~scope pmtd_name.txt decl env in + Signature_names.check_modtype names pmtd_loc id; let mtd = { mtd_id=id; @@ -1000,16 +1462,18 @@ and transl_modtype_decl_aux names env mtd_loc=pmtd_loc; } in - newenv, mtd, Sig_modtype(id, decl) + newenv, mtd, Sig_modtype(id, decl, Exported) and transl_recmodule_modtypes env sdecls = let make_env curr = List.fold_left - (fun env (id, _, mty) -> Env.add_module ~arg:true id mty env) + (fun env (id, _, mty) -> + Env.add_module ~arg:true id Mp_present mty env) env curr in let make_env2 curr = List.fold_left - (fun env (id, _, mty) -> Env.add_module ~arg:true id mty.mty_type env) + (fun env (id, _, mty) -> + Env.add_module ~arg:true id Mp_present mty.mty_type env) env curr in let transition env_c curr = List.map2 @@ -1020,7 +1484,15 @@ and transl_recmodule_modtypes env sdecls = in (id, id_loc, tmty)) sdecls curr in - let ids = List.map (fun x -> Ident.create x.pmd_name.txt) sdecls in + let map_mtys = List.map + (fun (id, _, mty) -> + (id, Types.{md_type = mty.mty_type; + md_loc = mty.mty_loc; + md_attributes = mty.mty_attributes})) in + let scope = Ctype.create_scope () in + let ids = + List.map (fun x -> Ident.create_scoped ~scope x.pmd_name.txt) sdecls + in let approx_env = (* cf #5965 @@ -1030,12 +1502,13 @@ and transl_recmodule_modtypes env sdecls = *) List.fold_left (fun env id -> - let dummy = Mty_ident (Path.Pident (Ident.create "#recmod#")) in - Env.add_module ~arg:true id dummy env + let dummy = + Mty_ident (Path.Pident (Ident.create_scoped ~scope "#recmod#")) + in + Env.add_module ~arg:true id Mp_present dummy env ) env ids in - Ctype.init_def(Ident.current_time()); (* PR#7082 *) let init = List.map2 (fun id pmd -> @@ -1048,7 +1521,7 @@ and transl_recmodule_modtypes env sdecls = (fun () -> transition env0 init) in let env1 = make_env2 dcl1 in - check_recmod_typedecls env1 sdecls dcl1; + check_recmod_typedecls env1 (map_mtys dcl1); let dcl2 = transition env1 dcl1 in (* List.iter @@ -1057,11 +1530,12 @@ and transl_recmodule_modtypes env sdecls = dcl2; *) let env2 = make_env2 dcl2 in - check_recmod_typedecls env2 sdecls dcl2; + check_recmod_typedecls env2 (map_mtys dcl2); let dcl2 = List.map2 (fun pmd (id, id_loc, mty) -> {md_id=id; md_name=id_loc; md_type=mty; + md_presence=Mp_present; md_loc=pmd.pmd_loc; md_attributes=pmd.pmd_attributes}) sdecls dcl2 @@ -1074,7 +1548,7 @@ exception Not_a_path let rec path_of_module mexp = match mexp.mod_desc with - Tmod_ident (p,_) -> p + | Tmod_ident (p,_) -> p | Tmod_apply(funct, arg, _coercion) when !Clflags.applicative_functors -> Papply(path_of_module funct, path_of_module arg) | Tmod_constraint (mexp, _, _, _) -> @@ -1093,20 +1567,22 @@ let rec closed_modtype env = function let env = Env.add_signature sg env in List.for_all (closed_signature_item env) sg | Mty_functor(id, param, body) -> - let env = Env.add_module ~arg:true id (Btype.default_mty param) env in + let env = + Env.add_module ~arg:true id Mp_present (Btype.default_mty param) env + in closed_modtype env body and closed_signature_item env = function - Sig_value(_id, desc) -> Ctype.closed_schema env desc.val_type - | Sig_module(_id, md, _) -> closed_modtype env md.md_type + Sig_value(_id, desc, _) -> Ctype.closed_schema env desc.val_type + | Sig_module(_id, _, md, _, _) -> closed_modtype env md.md_type | _ -> true let check_nongen_scheme env sig_item = match sig_item with - Sig_value(_id, vd) -> + Sig_value(_id, vd, _) -> if not (Ctype.closed_schema env vd.val_type) then raise (Error (vd.val_loc, env, Non_generalizable vd.val_type)) - | Sig_module (_id, md, _) -> + | Sig_module (_id, _, md, _, _) -> if not (closed_modtype env md.md_type) then raise(Error(md.md_loc, env, Non_generalizable_module md.md_type)) | _ -> () @@ -1117,7 +1593,7 @@ let check_nongen_schemes env sg = (* Helpers for typing recursive modules *) let anchor_submodule name anchor = - match anchor with None -> None | Some p -> Some(Pdot(p, name, nopos)) + match anchor with None -> None | Some p -> Some(Pdot(p, name)) let anchor_recmodule id = Some (Pident id) @@ -1129,7 +1605,7 @@ let enrich_type_decls anchor decls oldenv newenv = (fun e info -> let id = info.typ_id in let info' = - Mtype.enrich_typedecl oldenv (Pdot(p, Ident.name id, nopos)) + Mtype.enrich_typedecl oldenv (Pdot(p, Ident.name id)) id info.typ_type in Env.add_type ~check:true id info' e) @@ -1138,7 +1614,7 @@ let enrich_type_decls anchor decls oldenv newenv = let enrich_module_type anchor name mty env = match anchor with None -> mty - | Some p -> Mtype.enrich_modtype env (Pdot(p, name, nopos)) mty + | Some p -> Mtype.enrich_modtype env (Pdot(p, name)) mty let check_recmodule_inclusion env bindings = (* PR#4450, PR#4470: consider @@ -1161,17 +1637,18 @@ let check_recmodule_inclusion env bindings = recursive definitions being accepted. A good choice appears to be the number of mutually recursive declarations. *) - let subst_and_strengthen env s id mty = - Mtype.strengthen ~aliasable:false env (Subst.modtype s mty) + let subst_and_strengthen env scope s id mty = + Mtype.strengthen ~aliasable:false env (Subst.modtype (Rescope scope) s mty) (Subst.module_path s (Pident id)) in let rec check_incl first_time n env s = + let scope = Ctype.create_scope () in if n > 0 then begin (* Generate fresh names Y_i for the rec. bound module idents X_i *) let bindings1 = List.map - (fun (id, _, _mty_decl, _modl, mty_actual, _attrs, _loc) -> - (id, Ident.rename id, mty_actual)) + (fun (id, name, _mty_decl, _modl, mty_actual, _attrs, _loc) -> + (id, Ident.create_scoped ~scope name.txt, mty_actual)) bindings in (* Enter the Y_i in the environment with their actual types substituted by the input substitution s *) @@ -1181,8 +1658,8 @@ let check_recmodule_inclusion env bindings = let mty_actual' = if first_time then mty_actual - else subst_and_strengthen env s id mty_actual in - Env.add_module ~arg:false id' mty_actual' env) + else subst_and_strengthen env scope s id mty_actual in + Env.add_module ~arg:false id' Mp_present mty_actual' env) env bindings1 in (* Build the output substitution Y_i <- X_i *) let s' = @@ -1196,8 +1673,8 @@ let check_recmodule_inclusion env bindings = (* Base case: check inclusion of s(mty_actual) in s(mty_decl) and insert coercion if needed *) let check_inclusion (id, id_loc, mty_decl, modl, mty_actual, attrs, loc) = - let mty_decl' = Subst.modtype s mty_decl.mty_type - and mty_actual' = subst_and_strengthen env s id mty_actual in + let mty_decl' = Subst.modtype (Rescope scope) s mty_decl.mty_type + and mty_actual' = subst_and_strengthen env scope s id mty_actual in let coercion = try Includemod.modtypes ~loc:modl.mod_loc env mty_actual' mty_decl' @@ -1214,6 +1691,7 @@ let check_recmodule_inclusion env bindings = { mb_id = id; mb_name = id_loc; + mb_presence = Mp_present; mb_expr = modl'; mb_attributes = attrs; mb_loc = loc; @@ -1231,11 +1709,11 @@ let rec package_constraints env loc mty constrs = let sg' = List.map (function - | Sig_type (id, ({type_params=[]} as td), rs) + | Sig_type (id, ({type_params=[]} as td), rs, priv) when List.mem_assoc [Ident.name id] constrs -> let ty = List.assoc [Ident.name id] constrs in - Sig_type (id, {td with type_manifest = Some ty}, rs) - | Sig_module (id, md, rs) -> + Sig_type (id, {td with type_manifest = Some ty}, rs, priv) + | Sig_module (id, _, md, rs, priv) -> let rec aux = function | (m :: ((_ :: _) as l), t) :: rest when m = Ident.name id -> (l, t) :: aux rest @@ -1247,7 +1725,7 @@ let rec package_constraints env loc mty constrs = md_type = package_constraints env loc md.md_type (aux constrs) } in - Sig_module (id, md, rs) + Sig_module (id, Mp_present, md, rs, priv) | item -> item ) sg @@ -1306,7 +1784,7 @@ and type_module_aux ~alias sttn funct_body anchor env smod = let path = Typetexp.lookup_module ~load:(not alias) env smod.pmod_loc lid.txt in let md = { mod_desc = Tmod_ident (path, lid); - mod_type = Mty_alias(Mta_absent, path); + mod_type = Mty_alias path; mod_env = env; mod_attributes = smod.pmod_attributes; mod_loc = smod.pmod_loc } in @@ -1315,12 +1793,13 @@ and type_module_aux ~alias sttn funct_body anchor env smod = if alias && aliasable then (Env.add_required_global (Path.head path); md) else match (Env.find_module path env).md_type with - Mty_alias(_, p1) when not alias -> - let p1 = Env.normalize_path (Some smod.pmod_loc) env p1 in + | Mty_alias p1 when not alias -> + let p1 = Env.normalize_module_path (Some smod.pmod_loc) env p1 in let mty = Includemod.expand_module_alias env [] p1 in { md with - mod_desc = Tmod_constraint (md, mty, Tmodtype_implicit, - Tcoerce_alias (p1, Tcoerce_none)); + mod_desc = + Tmod_constraint (md, mty, Tmodtype_implicit, + Tcoerce_alias (env, path, Tcoerce_none)); mod_type = if sttn then Mtype.strengthen ~aliasable:true env mty p1 else mty } @@ -1332,7 +1811,7 @@ and type_module_aux ~alias sttn funct_body anchor env smod = { md with mod_type = mty } in rm md | Pmod_structure sstr -> - let (str, sg, _finalenv) = + let (str, sg, names, _finalenv) = type_structure funct_body anchor env sstr smod.pmod_loc in let md = rm { mod_desc = Tmod_structure str; @@ -1341,17 +1820,21 @@ and type_module_aux ~alias sttn funct_body anchor env smod = mod_attributes = smod.pmod_attributes; mod_loc = smod.pmod_loc } in - let sg' = simplify_signature sg in + let sg' = Signature_names.simplify _finalenv names sg in if List.length sg' = List.length sg then md else wrap_constraint env false md (Mty_signature sg') Tmodtype_implicit | Pmod_functor(name, smty, sbody) -> let mty = may_map (transl_modtype_functor_arg env) smty in let ty_arg = Misc.may_map (fun m -> m.mty_type) mty in + let scope = Ctype.create_scope () in let (id, newenv), funct_body = - match ty_arg with None -> (Ident.create "*", env), false - | Some mty -> Env.enter_module ~arg:true name.txt mty env, true in - Ctype.init_def(Ident.current_time()); (* PR#6981 *) + match ty_arg with + | None -> (Ident.create_scoped ~scope "*", env), false + | Some mty -> + Env.enter_module ~scope ~arg:true name.txt Mp_present mty env, + true + in let body = type_module sttn funct_body None newenv sbody in rm { mod_desc = Tmod_functor(id, name, mty, body); mod_type = Mty_functor(id, ty_arg, body.mod_type); @@ -1381,24 +1864,45 @@ and type_module_aux ~alias sttn funct_body anchor env smod = let mty_appl = match path with Some path -> - Subst.modtype (Subst.add_module param path Subst.identity) - mty_res + let scope = Ctype.create_scope () in + Subst.modtype (Rescope scope) + (Subst.add_module param path Subst.identity) + mty_res | None -> if generative then mty_res else - try - Mtype.nondep_supertype - (Env.add_module ~arg:true param arg.mod_type env) - param mty_res - with Not_found -> - raise(Error(smod.pmod_loc, env, - Cannot_eliminate_dependency mty_functor)) + let env = + Env.add_module ~arg:true param Mp_present arg.mod_type env + in + check_well_formed_module env smod.pmod_loc + "the signature of this functor application" mty_res; + let nondep_mty = + try Mtype.nondep_supertype env [param] mty_res + with Ctype.Nondep_cannot_erase _ -> + raise(Error(smod.pmod_loc, env, + Cannot_eliminate_dependency mty_functor)) + in + begin match + Includemod.modtypes ~loc:smod.pmod_loc env mty_res nondep_mty + with + | Tcoerce_none -> () + | _ -> + fatal_error + "unexpected coercion from original module type to \ + nondep_supertype one" + | exception Includemod.Error _ -> + fatal_error + "nondep_supertype not included in original module type" + end; + nondep_mty in + check_well_formed_module env smod.pmod_loc + "the signature of this functor application" mty_appl; rm { mod_desc = Tmod_apply(funct, arg, coercion); mod_type = mty_appl; mod_env = env; mod_attributes = smod.pmod_attributes; mod_loc = smod.pmod_loc } - | Mty_alias(_, path) -> + | Mty_alias path -> raise(Error(sfunct.pmod_loc, env, Cannot_scrape_alias path)) | _ -> raise(Error(sfunct.pmod_loc, env, Cannot_apply funct.mod_type)) @@ -1449,8 +1953,65 @@ and type_module_aux ~alias sttn funct_body anchor env smod = | Pmod_extension ext -> raise (Error_forward (Builtin_attributes.error_of_extension ext)) +and type_open_decl ?used_slot ?toplevel funct_body names env sod = + Builtin_attributes.warning_scope sod.popen_attributes + (fun () -> + type_open_decl_aux ?used_slot ?toplevel funct_body names env sod + ) + +and type_open_decl_aux ?used_slot ?toplevel funct_body names env od = + let loc = od.popen_loc in + match od.popen_expr.pmod_desc with + | Pmod_ident lid -> + let path, newenv = + type_open_ ?used_slot ?toplevel od.popen_override env loc lid + in + let md = { mod_desc = Tmod_ident (path, lid); + mod_type = Mty_alias path; + mod_env = env; + mod_attributes = od.popen_expr.pmod_attributes; + mod_loc = od.popen_expr.pmod_loc } + in + let open_descr = { + open_expr = md; + open_bound_items = []; + open_override = od.popen_override; + open_env = newenv; + open_loc = loc; + open_attributes = od.popen_attributes + } in + open_descr, [], newenv + | _ -> + let md = type_module true funct_body None env od.popen_expr in + let scope = Ctype.create_scope () in + let sg, newenv = + Env.enter_signature ~scope (extract_sig_open env md.mod_loc md.mod_type) + env + in + List.iter (Signature_names.check_sig_item ~info:`From_open names loc) sg; + let sg = + List.map (function + | Sig_value(id, vd, _) -> Sig_value(id, vd, Hidden) + | Sig_type(id, td, rs, _) -> Sig_type(id, td, rs, Hidden) + | Sig_typext(id, ec, et, _) -> Sig_typext(id, ec, et, Hidden) + | Sig_module(id, mp, md, rs, _) -> Sig_module(id, mp, md, rs, Hidden) + | Sig_modtype(id, mtd, _) -> Sig_modtype(id, mtd, Hidden) + | Sig_class(id, cd, rs, _) -> Sig_class(id, cd, rs, Hidden) + | Sig_class_type(id, ctd, rs, _) -> Sig_class_type(id, ctd, rs, Hidden) + ) sg + in + let open_descr = { + open_expr = md; + open_bound_items = sg; + open_override = od.popen_override; + open_env = newenv; + open_loc = loc; + open_attributes = od.popen_attributes + } in + open_descr, sg, newenv + and type_structure ?(toplevel = false) funct_body anchor env sstr scope = - let names = new_names () in + let names = Signature_names.create () in let type_str_item env srem {pstr_loc = loc; pstr_desc = desc} = match desc with @@ -1482,45 +2043,59 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope = (* Note: Env.find_value does not trigger the value_used event. Values will be marked as being used during the signature inclusion test. *) Tstr_value(rec_flag, defs), - List.map (fun id -> Sig_value(id, Env.find_value (Pident id) newenv)) - (let_bound_idents defs), + List.map (fun (id, { Asttypes.loc; _ }, _typ)-> + Signature_names.check_value names loc id; + Sig_value(id, Env.find_value (Pident id) newenv, Exported) + ) (let_bound_idents_with_loc defs), newenv | Pstr_primitive sdesc -> let (desc, newenv) = Typedecl.transl_value_decl env loc sdesc in - Tstr_primitive desc, [Sig_value(desc.val_id, desc.val_val)], newenv + Signature_names.check_value names desc.val_loc desc.val_id; + Tstr_primitive desc, + [Sig_value(desc.val_id, desc.val_val, Exported)], + newenv | Pstr_type (rec_flag, sdecls) -> - List.iter - (fun decl -> check_name check_type names decl.ptype_name) - sdecls; let (decls, newenv) = Typedecl.transl_type_decl env rec_flag sdecls in + List.iter + Signature_names.(fun td -> check_type names td.typ_loc td.typ_id) + decls; Tstr_type (rec_flag, decls), map_rec_type_with_row_types ~rec_flag - (fun rs info -> Sig_type(info.typ_id, info.typ_type, rs)) + (fun rs info -> Sig_type(info.typ_id, info.typ_type, rs, Exported)) decls [], enrich_type_decls anchor decls env newenv | Pstr_typext styext -> - List.iter - (fun pext -> check_name check_typext names pext.pext_name) - styext.ptyext_constructors; let (tyext, newenv) = Typedecl.transl_type_extension true env loc styext in + let constructors = tyext.tyext_constructors in + List.iter + Signature_names.(fun ext -> check_typext names ext.ext_loc ext.ext_id) + constructors; (Tstr_typext tyext, map_ext - (fun es ext -> Sig_typext(ext.ext_id, ext.ext_type, es)) - tyext.tyext_constructors [], + (fun es ext -> Sig_typext(ext.ext_id, ext.ext_type, es, Exported)) + constructors [], newenv) | Pstr_exception sext -> - check_name check_typext names sext.pext_name; - let (ext, newenv) = Typedecl.transl_exception env sext in + let (ext, newenv) = Typedecl.transl_type_exception env sext in + let constructor = ext.tyexn_constructor in + Signature_names.check_typext names constructor.ext_loc + constructor.ext_id; Tstr_exception ext, - [Sig_typext(ext.ext_id, ext.ext_type, Text_exception)], + [Sig_typext(constructor.ext_id, + constructor.ext_type, + Text_exception, + Exported)], newenv | Pstr_module {pmb_name = name; pmb_expr = smodl; pmb_attributes = attrs; pmb_loc; } -> - check_name check_module names name; - let id = Ident.create name.txt in (* create early for PR#6752 *) + let scope = Ctype.create_scope () in + let id = + Ident.create_scoped ~scope name.txt (* create early for PR#6752 *) + in + Signature_names.check_module names pmb_loc id; let modl = Builtin_attributes.warning_scope attrs (fun () -> @@ -1528,6 +2103,11 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope = (anchor_submodule name.txt anchor) env smodl ) in + let pres = + match modl.mod_type with + | Mty_alias _ -> Mp_absent + | _ -> Mp_present + in let md = { md_type = enrich_module_type anchor name.txt modl.mod_type env; md_attributes = attrs; @@ -1535,16 +2115,15 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope = } in (*prerr_endline (Ident.unique_toplevel_name id);*) - Mtype.lower_nongen (Ident.binding_time id - 1) md.md_type; - let newenv = Env.enter_module_declaration id md env in + Mtype.lower_nongen (scope - 1) md.md_type; + let newenv = Env.enter_module_declaration id pres md env in Tstr_module {mb_id=id; mb_name=name; mb_expr=modl; - mb_attributes=attrs; mb_loc=pmb_loc; - }, - [Sig_module(id, + mb_presence=pres; mb_attributes=attrs; mb_loc=pmb_loc; }, + [Sig_module(id, pres, {md_type = modl.mod_type; md_attributes = attrs; md_loc = pmb_loc; - }, Trec_not)], + }, Trec_not, Exported)], newenv | Pstr_recmodule sbind -> let sbind = @@ -1562,15 +2141,15 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope = ) sbind in - List.iter - (fun (name, _, _, _, _) -> check_name check_module names name) - sbind; let (decls, newenv) = transl_recmodule_modtypes env (List.map (fun (name, smty, _smodl, attrs, loc) -> {pmd_name=name; pmd_type=smty; pmd_attributes=attrs; pmd_loc=loc}) sbind ) in + List.iter + Signature_names.(fun md -> check_module names md.md_loc md.md_id) + decls; let bindings1 = List.map2 (fun {md_id=id; md_type=mty} (name, _, smodl, attrs, loc) -> @@ -1596,7 +2175,8 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope = md_loc = md.md_loc; } in - Env.add_module_declaration ~check:true md.md_id mdecl env + Env.add_module_declaration ~check:true + md.md_id Mp_present mdecl env ) env decls in @@ -1604,27 +2184,32 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope = check_recmodule_inclusion newenv bindings1 in Tstr_recmodule bindings2, map_rec (fun rs mb -> - Sig_module(mb.mb_id, { + Sig_module(mb.mb_id, Mp_present, { md_type=mb.mb_expr.mod_type; md_attributes=mb.mb_attributes; md_loc=mb.mb_loc; - }, rs)) + }, rs, Exported)) bindings2 [], newenv | Pstr_modtype pmtd -> (* check that it is non-abstract *) - let newenv, mtd, sg = - transl_modtype_decl names env pmtd - in + let newenv, mtd, sg = transl_modtype_decl names env pmtd in Tstr_modtype mtd, [sg], newenv | Pstr_open sod -> - let (_path, newenv, od) = type_open ~toplevel env sod in - Tstr_open od, [], newenv + let (od, sg, newenv) = + type_open_decl ~toplevel funct_body names env sod + in + Tstr_open od, sg, newenv | Pstr_class cl -> - List.iter - (fun {pci_name} -> check_name check_type names pci_name) - cl; let (classes, new_env) = Typeclass.class_declarations env cl in + List.iter (fun cls -> + let open Typeclass in + let loc = cls.cls_id_loc.Location.loc in + Signature_names.check_class names loc cls.cls_id; + Signature_names.check_class_type names loc cls.cls_ty_id; + Signature_names.check_type names loc cls.cls_obj_id; + Signature_names.check_type names loc cls.cls_typesharp_id; + ) classes; Tstr_class (List.map (fun cls -> (cls.Typeclass.cls_info, @@ -1641,17 +2226,21 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope = (map_rec (fun rs cls -> let open Typeclass in - [Sig_class(cls.cls_id, cls.cls_decl, rs); - Sig_class_type(cls.cls_ty_id, cls.cls_ty_decl, rs); - Sig_type(cls.cls_obj_id, cls.cls_obj_abbr, rs); - Sig_type(cls.cls_typesharp_id, cls.cls_abbr, rs)]) + [Sig_class(cls.cls_id, cls.cls_decl, rs, Exported); + Sig_class_type(cls.cls_ty_id, cls.cls_ty_decl, rs, Exported); + Sig_type(cls.cls_obj_id, cls.cls_obj_abbr, rs, Exported); + Sig_type(cls.cls_typesharp_id, cls.cls_abbr, rs, Exported)]) classes []), new_env | Pstr_class_type cl -> - List.iter - (fun {pci_name} -> check_name check_type names pci_name) - cl; let (classes, new_env) = Typeclass.class_type_declarations env cl in + List.iter (fun decl -> + let open Typeclass in + let loc = decl.clsty_id_loc.Location.loc in + Signature_names.check_class_type names loc decl.clsty_ty_id; + Signature_names.check_type names loc decl.clsty_obj_id; + Signature_names.check_type names loc decl.clsty_typesharp_id; + ) classes; Tstr_class_type (List.map (fun cl -> (cl.Typeclass.clsty_ty_id, @@ -1666,9 +2255,12 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope = (map_rec (fun rs decl -> let open Typeclass in - [Sig_class_type(decl.clsty_ty_id, decl.clsty_ty_decl, rs); - Sig_type(decl.clsty_obj_id, decl.clsty_obj_abbr, rs); - Sig_type(decl.clsty_typesharp_id, decl.clsty_abbr, rs)]) + [Sig_class_type(decl.clsty_ty_id, decl.clsty_ty_decl, rs, + Exported); + Sig_type(decl.clsty_obj_id, decl.clsty_obj_abbr, rs, Exported); + Sig_type(decl.clsty_typesharp_id, decl.clsty_abbr, rs, + Exported) + ]) classes []), new_env | Pstr_include sincl -> @@ -1677,11 +2269,11 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope = Builtin_attributes.warning_scope sincl.pincl_attributes (fun () -> type_module true funct_body None env smodl) in + let scope = Ctype.create_scope () in (* Rename all identifiers bound by this signature to avoid clashes *) - let sg = Subst.signature Subst.identity - (extract_sig_open env smodl.pmod_loc modl.mod_type) in - List.iter (check_sig_item names loc) sg; - let new_env = Env.add_signature sg env in + let sg, new_env = Env.enter_signature ~scope + (extract_sig_open env smodl.pmod_loc modl.mod_type) env in + List.iter (Signature_names.check_sig_item names loc) sg; let incl = { incl_mod = modl; incl_type = sg; @@ -1697,7 +2289,6 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope = Tstr_attribute x, [], env in let rec type_struct env sstr = - Ctype.init_def(Ident.current_time()); match sstr with | [] -> ([], [], env) | pstr :: srem -> @@ -1718,19 +2309,19 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope = let str = { str_items = items; str_type = sg; str_final_env = final_env } in Cmt_format.set_saved_types (Cmt_format.Partial_structure str :: previous_saved_types); - str, sg, final_env + str, sg, names, final_env in if toplevel then run () else Builtin_attributes.warning_scope [] run let type_toplevel_phrase env s = Env.reset_required_globals (); - let (str, sg, env) = + let (str, sg, to_remove_from_sg, env) = type_structure ~toplevel:true false None env s Location.none in let (str, _coerce) = ImplementationHooks.apply_hooks { Misc.sourcefile = "//toplevel//" } (str, Tcoerce_none) in - (str, sg, env) + (str, sg, to_remove_from_sg, env) let type_module_alias = type_module ~alias:true true false None let type_module = type_module true false None @@ -1747,8 +2338,8 @@ let rec normalize_modtype env = function and normalize_signature env = List.iter (normalize_signature_item env) and normalize_signature_item env = function - Sig_value(_id, desc) -> Ctype.normalize_type env desc.val_type - | Sig_module(_id, md, _) -> normalize_modtype env md.md_type + Sig_value(_id, desc, _) -> Ctype.normalize_type env desc.val_type + | Sig_module(_id, _, md, _, _) -> normalize_modtype env md.md_type | _ -> () (* Extract the module type of a module expression *) @@ -1777,25 +2368,25 @@ let type_module_type_of env smod = let type_package env m p nl = (* Same as Pexp_letmodule *) (* remember original level *) - let lv = Ctype.get_current_level () in Ctype.begin_def (); - Ident.set_current_time lv; let context = Typetexp.narrow () in let modl = type_module env m in - Ctype.init_def(Ident.current_time()); + let scope = Ctype.create_scope () in Typetexp.widen context; let (mp, env) = match modl.mod_desc with - Tmod_ident (mp,_) -> (mp, env) + | Tmod_ident (mp,_) -> (mp, env) | Tmod_constraint ({mod_desc=Tmod_ident (mp,_)}, _, Tmodtype_implicit, _) -> (mp, env) (* PR#6982 *) | _ -> - let (id, new_env) = Env.enter_module ~arg:true "%M" modl.mod_type env in + let (id, new_env) = + Env.enter_module ~scope ~arg:true "%M" Mp_present modl.mod_type env + in (Pident id, new_env) in let rec mkpath mp = function - | Lident name -> Pdot(mp, name, nopos) - | Ldot (m, name) -> Pdot(mkpath mp m, name, nopos) + | Lident name -> Pdot(mp, name) + | Ldot (m, name) -> Pdot(mkpath mp m, name) | _ -> assert false in let tl' = @@ -1818,12 +2409,22 @@ let type_package env m p nl = (wrap_constraint env true modl mty Tmodtype_implicit, tl') (* Fill in the forward declarations *) + +let type_open_decl ?used_slot env od = + type_open_decl ?used_slot ?toplevel:None false (Signature_names.create ()) env + od + +let type_open_descr ?used_slot env od = + type_open_descr ?used_slot ?toplevel:None env od + let () = Typecore.type_module := type_module_alias; Typetexp.transl_modtype_longident := transl_modtype_longident; Typetexp.transl_modtype := transl_modtype; Typecore.type_open := type_open_ ?toplevel:None; + Typecore.type_open_decl := type_open_decl; Typecore.type_package := type_package; + Typeclass.type_open_descr := type_open_descr; type_module_type_of_fwd := type_module_type_of @@ -1831,72 +2432,74 @@ let () = let type_implementation sourcefile outputprefix modulename initial_env ast = Cmt_format.clear (); - try - Typecore.reset_delayed_checks (); - Env.reset_required_globals (); - if !Clflags.print_types then (* #7656 *) - Warnings.parse_options false "-32-34-37-38-60"; - let (str, sg, finalenv) = - type_structure initial_env ast (Location.in_file sourcefile) in - let simple_sg = simplify_signature sg in - if !Clflags.print_types then begin - Typecore.force_delayed_checks (); - Printtyp.wrap_printing_env ~error:false initial_env - (fun () -> fprintf std_formatter "%a@." Printtyp.signature simple_sg); - (str, Tcoerce_none) (* result is ignored by Compile.implementation *) - end else begin - let sourceintf = - Filename.remove_extension sourcefile ^ !Config.interface_suffix in - if Sys.file_exists sourceintf then begin - let intf_file = - try - find_in_path_uncap !Config.load_path (modulename ^ ".cmi") - with Not_found -> - raise(Error(Location.in_file sourcefile, Env.empty, - Interface_not_compiled sourceintf)) in - let dclsig = Env.read_signature modulename intf_file in - let coercion = - Includemod.compunit initial_env ~mark:Includemod.Mark_positive - sourcefile sg intf_file dclsig - in - Typecore.force_delayed_checks (); - (* It is important to run these checks after the inclusion test above, - so that value declarations which are not used internally but exported - are not reported as being unused. *) - Cmt_format.save_cmt (outputprefix ^ ".cmt") modulename - (Cmt_format.Implementation str) (Some sourcefile) initial_env None; - (str, coercion) - end else begin - let coercion = - Includemod.compunit initial_env ~mark:Includemod.Mark_positive - sourcefile sg "(inferred signature)" simple_sg - in - check_nongen_schemes finalenv simple_sg; - normalize_signature finalenv simple_sg; - Typecore.force_delayed_checks (); - (* See comment above. Here the target signature contains all - the value being exported. We can still capture unused - declarations like "let x = true;; let x = 1;;", because in this - case, the inferred signature contains only the last declaration. *) - if not !Clflags.dont_write_files then begin - let deprecated = Builtin_attributes.deprecated_of_str ast in - let cmi = - Env.save_signature ~deprecated - simple_sg modulename (outputprefix ^ ".cmi") - in + Misc.try_finally (fun () -> + Typecore.reset_delayed_checks (); + Env.reset_required_globals (); + if !Clflags.print_types then (* #7656 *) + Warnings.parse_options false "-32-34-37-38-60"; + let (str, sg, names, finalenv) = + type_structure initial_env ast (Location.in_file sourcefile) in + let simple_sg = Signature_names.simplify finalenv names sg in + if !Clflags.print_types then begin + Typecore.force_delayed_checks (); + Printtyp.wrap_printing_env ~error:false initial_env + (fun () -> fprintf std_formatter "%a@." + (Printtyp.printed_signature sourcefile) simple_sg + ); + (str, Tcoerce_none) (* result is ignored by Compile.implementation *) + end else begin + let sourceintf = + Filename.remove_extension sourcefile ^ !Config.interface_suffix in + if Sys.file_exists sourceintf then begin + let intf_file = + try + Load_path.find_uncap (modulename ^ ".cmi") + with Not_found -> + raise(Error(Location.in_file sourcefile, Env.empty, + Interface_not_compiled sourceintf)) in + let dclsig = Env.read_signature modulename intf_file in + let coercion = + Includemod.compunit initial_env ~mark:Includemod.Mark_positive + sourcefile sg intf_file dclsig + in + Typecore.force_delayed_checks (); + (* It is important to run these checks after the inclusion test above, + so that value declarations which are not used internally but + exported are not reported as being unused. *) + Cmt_format.save_cmt (outputprefix ^ ".cmt") modulename + (Cmt_format.Implementation str) (Some sourcefile) initial_env None; + (str, coercion) + end else begin + let coercion = + Includemod.compunit initial_env ~mark:Includemod.Mark_positive + sourcefile sg "(inferred signature)" simple_sg + in + check_nongen_schemes finalenv simple_sg; + normalize_signature finalenv simple_sg; + Typecore.force_delayed_checks (); + (* See comment above. Here the target signature contains all + the value being exported. We can still capture unused + declarations like "let x = true;; let x = 1;;", because in this + case, the inferred signature contains only the last declaration. *) + if not !Clflags.dont_write_files then begin + let alerts = Builtin_attributes.alerts_of_str ast in + let cmi = + Env.save_signature ~alerts + simple_sg modulename (outputprefix ^ ".cmi") + in + Cmt_format.save_cmt (outputprefix ^ ".cmt") modulename + (Cmt_format.Implementation str) + (Some sourcefile) initial_env (Some cmi); + end; + (str, coercion) + end + end + ) + ~exceptionally:(fun () -> Cmt_format.save_cmt (outputprefix ^ ".cmt") modulename - (Cmt_format.Implementation str) - (Some sourcefile) initial_env (Some cmi); - end; - (str, coercion) - end - end - with e -> - Cmt_format.save_cmt (outputprefix ^ ".cmt") modulename - (Cmt_format.Partial_implementation - (Array.of_list (Cmt_format.get_saved_types ()))) - (Some sourcefile) initial_env None; - raise e + (Cmt_format.Partial_implementation + (Array.of_list (Cmt_format.get_saved_types ()))) + (Some sourcefile) initial_env None) let type_implementation sourcefile outputprefix modulename initial_env ast = ImplementationHooks.apply_hooks { Misc.sourcefile } @@ -1912,18 +2515,33 @@ let type_interface sourcefile env ast = (* "Packaging" of several compilation units into one unit having them as sub-modules. *) -let rec package_signatures subst = function - [] -> [] - | (name, sg) :: rem -> - let sg' = Subst.signature subst sg in - let oldid = Ident.create_persistent name - and newid = Ident.create name in - Sig_module(newid, {md_type=Mty_signature sg'; - md_attributes=[]; - md_loc=Location.none; - }, - Trec_not) :: - package_signatures (Subst.add_module oldid (Pident newid) subst) rem +let package_signatures units = + let units_with_ids = + List.map + (fun (name, sg) -> + let oldid = Ident.create_persistent name in + let newid = Ident.create_local name in + (oldid, newid, sg)) + units + in + let subst = + List.fold_left + (fun acc (oldid, newid, _) -> + Subst.add_module oldid (Pident newid) acc) + Subst.identity units_with_ids + in + List.map + (fun (_, newid, sg) -> + (* This signature won't be used for anything, it'll just be saved in a cmi + and cmt. *) + let sg = Subst.signature Make_local subst sg in + let md = + { md_type=Mty_signature sg; + md_attributes=[]; + md_loc=Location.none; } + in + Sig_module(newid, Mp_present, md, Trec_not, Exported)) + units_with_ids let package_units initial_env objfiles cmifile modulename = (* Read the signatures of the units *) @@ -1941,7 +2559,7 @@ let package_units initial_env objfiles cmifile modulename = objfiles in (* Compute signature of packaged unit *) Ident.reinit(); - let sg = package_signatures Subst.identity units in + let sg = package_signatures units in (* See if explicit interface is provided *) let prefix = Filename.remove_extension cmifile in let mlifile = prefix ^ !Config.interface_suffix in @@ -1964,12 +2582,13 @@ let package_units initial_env objfiles cmifile modulename = (* Write packaged signature *) if not !Clflags.dont_write_files then begin let cmi = - Env.save_signature_with_imports ~deprecated:None + Env.save_signature_with_imports ~alerts:Misc.Stdlib.String.Map.empty sg modulename (prefix ^ ".cmi") imports in Cmt_format.save_cmt (prefix ^ ".cmt") modulename - (Cmt_format.Packed (cmi.Cmi_format.cmi_sign, objfiles)) None initial_env (Some cmi) + (Cmt_format.Packed (cmi.Cmi_format.cmi_sign, objfiles)) None initial_env + (Some cmi) end; Tcoerce_none end @@ -1988,7 +2607,7 @@ let report_error ppf = function | Cannot_eliminate_dependency mty -> fprintf ppf "@[This functor has type@ %a@ \ - The parameter cannot be eliminated in the result type.@ \ + The parameter cannot be eliminated in the result type.@ \ Please bind the argument to a module identifier.@]" modtype mty | Signature_expected -> fprintf ppf "This module type is not a signature" | Structure_expected mty -> @@ -2027,7 +2646,8 @@ let report_error ppf = function | Repeated_name(kind, name) -> fprintf ppf "@[Multiple definition of the %s name %s.@ \ - Names must be unique in a given structure or signature.@]" kind name + Names must be unique in a given structure or signature.@]" + (Sig_component_kind.to_string kind) name | Non_generalizable typ -> fprintf ppf "@[The type of this expression,@ %a,@ \ @@ -2075,6 +2695,35 @@ let report_error ppf = function fprintf ppf "This is an alias for module %a, which is missing" path p + | Badly_formed_signature (context, err) -> + fprintf ppf "@[In %s:@ %a@]" context Typedecl.report_error err + | Cannot_hide_id Illegal_shadowing + { shadowed_item_kind; shadowed_item_id; shadowed_item_loc; + shadower_id; user_id; user_kind; user_loc } -> + let shadowed_item_kind= Sig_component_kind.to_string shadowed_item_kind in + fprintf ppf + "@[Illegal shadowing of included %s %a by %a@ \ + %a:@;<1 2>%s %a came from this include@ \ + %a:@;<1 2>The %s %s has no valid type if %a is shadowed@]" + shadowed_item_kind Ident.print shadowed_item_id Ident.print shadower_id + Location.print_loc shadowed_item_loc + (String.capitalize_ascii shadowed_item_kind) + Ident.print shadowed_item_id + Location.print_loc user_loc + (Sig_component_kind.to_string user_kind) (Ident.name user_id) + Ident.print shadowed_item_id + | Cannot_hide_id Appears_in_signature + { opened_item_kind; opened_item_id; user_id; user_kind; user_loc } -> + let opened_item_kind= Sig_component_kind.to_string opened_item_kind in + fprintf ppf + "@[The %s %a introduced by this open appears in the signature@ \ + %a:@;<1 2>The %s %s has no valid type if %a is hidden@]" + opened_item_kind Ident.print opened_item_id + Location.print_loc user_loc + (Sig_component_kind.to_string user_kind) (Ident.name user_id) + Ident.print opened_item_id + | Invalid_type_subst_rhs -> + fprintf ppf "Only type synonyms are allowed on the right of :=" let report_error env ppf err = Printtyp.wrap_printing_env ~error:true env (fun () -> report_error ppf err) @@ -2083,7 +2732,7 @@ let () = Location.register_error_of_exn (function | Error (loc, env, err) -> - Some (Location.error_of_printer loc (report_error env) err) + Some (Location.error_of_printer ~loc (report_error env) err) | Error_forward err -> Some err | _ -> diff --git a/typing/typemod.mli b/typing/typemod.mli index 68d2103e..ac895d39 100644 --- a/typing/typemod.mli +++ b/typing/typemod.mli @@ -13,19 +13,30 @@ (* *) (**************************************************************************) -(** Type-checking of the module language and typed ast plugin hooks *) +(** Type-checking of the module language and typed ast plugin hooks + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) open Types open Format +module Signature_names : sig + type t + + val simplify: Env.t -> t -> signature -> signature +end + val type_module: Env.t -> Parsetree.module_expr -> Typedtree.module_expr val type_structure: - Env.t -> Parsetree.structure -> Location.t -> - Typedtree.structure * Types.signature * Env.t + Env.t -> Parsetree.structure -> Location.t -> + Typedtree.structure * Types.signature * Signature_names.t * Env.t val type_toplevel_phrase: - Env.t -> Parsetree.structure -> - Typedtree.structure * Types.signature * Env.t + Env.t -> Parsetree.structure -> + Typedtree.structure * Types.signature * Signature_names.t * Env.t val type_implementation: string -> string -> string -> Env.t -> Parsetree.structure -> Typedtree.structure * Typedtree.module_coercion @@ -35,14 +46,15 @@ val transl_signature: Env.t -> Parsetree.signature -> Typedtree.signature val check_nongen_schemes: Env.t -> Types.signature -> unit + (* val type_open_: ?used_slot:bool ref -> ?toplevel:bool -> Asttypes.override_flag -> Env.t -> Location.t -> Longident.t Asttypes.loc -> Path.t * Env.t + *) val modtype_of_package: Env.t -> Location.t -> Path.t -> Longident.t list -> type_expr list -> module_type -val simplify_signature: signature -> signature val path_of_module : Typedtree.module_expr -> Path.t option @@ -59,6 +71,37 @@ val initial_env: initially_opened_module:string option -> open_implicit_modules:string list -> Env.t +module Sig_component_kind : sig + type t = + | Value + | Type + | Module + | Module_type + | Extension_constructor + | Class + | Class_type + + val to_string : t -> string +end + +type hiding_error = + | Illegal_shadowing of { + shadowed_item_id: Ident.t; + shadowed_item_kind: Sig_component_kind.t; + shadowed_item_loc: Location.t; + shadower_id: Ident.t; + user_id: Ident.t; + user_kind: Sig_component_kind.t; + user_loc: Location.t; + } + | Appears_in_signature of { + opened_item_id: Ident.t; + opened_item_kind: Sig_component_kind.t; + user_id: Ident.t; + user_kind: Sig_component_kind.t; + user_loc: Location.t; + } + type error = Cannot_apply of module_type | Not_included of Includemod.error list @@ -71,7 +114,7 @@ type error = Longident.t * Path.t * Includemod.error list | With_changes_module_alias of Longident.t * Ident.t * Path.t | With_cannot_remove_constrained_type - | Repeated_name of string * string + | Repeated_name of Sig_component_kind.t * string | Non_generalizable of type_expr | Non_generalizable_class of Ident.t * class_declaration | Non_generalizable_module of module_type @@ -84,6 +127,9 @@ type error = | Recursive_module_require_explicit_type | Apply_generative | Cannot_scrape_alias of Path.t + | Badly_formed_signature of string * Typedecl.error + | Cannot_hide_id of hiding_error + | Invalid_type_subst_rhs exception Error of Location.t * Env.t * error exception Error_forward of Location.error diff --git a/typing/typeopt.ml b/typing/typeopt.ml index 4851b6c9..8ca209a5 100644 --- a/typing/typeopt.ml +++ b/typing/typeopt.ml @@ -121,7 +121,7 @@ let array_pattern_kind pat = array_type_kind pat.pat_env pat.pat_type let bigarray_decode_type env ty tbl dfl = match scrape env ty with - | Tconstr(Pdot(Pident mod_id, type_name, _), [], _) + | Tconstr(Pdot(Pident mod_id, type_name), [], _) when Ident.name mod_id = "Stdlib__bigarray" -> begin try List.assoc type_name tbl with Not_found -> dfl end | _ -> @@ -171,6 +171,10 @@ let value_kind env ty = | _ -> Pgenval +let function_return_value_kind env ty = + match is_function_type env ty with + | Some (_lhs, rhs) -> value_kind env rhs + | None -> Pgenval (** Whether a forward block is needed for a lazy thunk on a value, i.e. if the value can be represented as a float/forward/lazy *) @@ -205,3 +209,7 @@ let classify_lazy_argument : Typedtree.expression -> `Identifier `Other | _ -> `Other + +let value_kind_union k1 k2 = + if k1 = k2 then k1 + else Pgenval diff --git a/typing/typeopt.mli b/typing/typeopt.mli index 24ea55f4..0f6b9f37 100644 --- a/typing/typeopt.mli +++ b/typing/typeopt.mli @@ -29,9 +29,15 @@ val array_pattern_kind : Typedtree.pattern -> Lambda.array_kind val bigarray_type_kind_and_layout : Env.t -> Types.type_expr -> Lambda.bigarray_kind * Lambda.bigarray_layout val value_kind : Env.t -> Types.type_expr -> Lambda.value_kind +val function_return_value_kind : Env.t -> Types.type_expr -> Lambda.value_kind val classify_lazy_argument : Typedtree.expression -> [ `Constant_or_function | `Float_that_cannot_be_shortcut | `Identifier of [`Forward_value | `Other] | `Other] + +val value_kind_union : + Lambda.value_kind -> Lambda.value_kind -> Lambda.value_kind + (** [value_kind_union k1 k2] is a value_kind at least as general as + [k1] and [k2] *) diff --git a/typing/types.ml b/typing/types.ml index 94b41a16..8bda6b6c 100644 --- a/typing/types.ml +++ b/typing/types.ml @@ -22,7 +22,7 @@ open Asttypes type type_expr = { mutable desc: type_desc; mutable level: int; - mutable scope: int option; + mutable scope: int; id: int } and type_desc = @@ -80,9 +80,7 @@ end (* Maps of methods and instance variables *) -module OrderedString = - struct type t = string let compare (x:t) y = compare x y end -module Meths = Map.Make(OrderedString) +module Meths = Misc.Stdlib.String.Map module Vars = Meths (* Value descriptions *) @@ -105,7 +103,11 @@ and value_kind = (* Self *) | Val_anc of (string * Ident.t) list * string (* Ancestor *) - | Val_unbound (* Unbound variable *) + | Val_unbound of value_unbound_reason (* Unbound variable *) + +and value_unbound_reason = + | Val_unbound_instance_variable + | Val_unbound_ghost_recursive (* Variance *) @@ -123,6 +125,7 @@ module Variance = struct let union v1 v2 = v1 lor v2 let inter v1 v2 = v1 land v2 let subset v1 v2 = (v1 land v2 = v1) + let eq (v1 : t) v2 = (v1 = v2) let set x b v = if b then v lor single x else v land (lnot (single x)) let mem x = subset (single x) @@ -146,7 +149,8 @@ type type_declaration = type_private: private_flag; type_manifest: type_expr option; type_variance: Variance.t list; - type_newtype_level: (int * int) option; + type_is_newtype: bool; + type_expansion_scope: int; type_loc: Location.t; type_attributes: Parsetree.attributes; type_immediate: bool; @@ -164,7 +168,7 @@ and record_representation = | Record_float (* All fields are floats *) | Record_unboxed of bool (* Unboxed single-field record, inlined or not *) | Record_inlined of int (* Inlined record *) - | Record_extension (* Inlined record under extension *) + | Record_extension of Path.t (* Inlined record under extension *) and label_declaration = { @@ -215,7 +219,7 @@ and type_transparence = (* Type expressions for the class language *) -module Concr = Set.Make(OrderedString) +module Concr = Misc.Stdlib.String.Set type class_type = Cty_constr of Path.t * type_expr list * class_type @@ -250,26 +254,31 @@ type class_type_declaration = (* Type expressions for the module language *) +type visibility = + | Exported + | Hidden + type module_type = Mty_ident of Path.t | Mty_signature of signature | Mty_functor of Ident.t * module_type option * module_type - | Mty_alias of alias_presence * Path.t + | Mty_alias of Path.t -and alias_presence = - | Mta_present - | Mta_absent +and module_presence = + | Mp_present + | Mp_absent and signature = signature_item list and signature_item = - Sig_value of Ident.t * value_description - | Sig_type of Ident.t * type_declaration * rec_status - | Sig_typext of Ident.t * extension_constructor * ext_status - | Sig_module of Ident.t * module_declaration * rec_status - | Sig_modtype of Ident.t * modtype_declaration - | Sig_class of Ident.t * class_declaration * rec_status - | Sig_class_type of Ident.t * class_type_declaration * rec_status + Sig_value of Ident.t * value_description * visibility + | Sig_type of Ident.t * type_declaration * rec_status * visibility + | Sig_typext of Ident.t * extension_constructor * ext_status * visibility + | Sig_module of + Ident.t * module_presence * module_declaration * rec_status * visibility + | Sig_modtype of Ident.t * modtype_declaration * visibility + | Sig_class of Ident.t * class_declaration * rec_status * visibility + | Sig_class_type of Ident.t * class_type_declaration * rec_status * visibility and module_declaration = { @@ -323,12 +332,12 @@ and constructor_tag = | Cstr_extension of Path.t * bool (* Extension constructor true if a constant false if a block*) -let equal_tag t1 t2 = +let equal_tag t1 t2 = match (t1, t2) with | Cstr_constant i1, Cstr_constant i2 -> i2 = i1 | Cstr_block i1, Cstr_block i2 -> i2 = i1 | Cstr_unboxed, Cstr_unboxed -> true - | Cstr_extension (path1, b1), Cstr_extension (path2, b2) -> + | Cstr_extension (path1, b1), Cstr_extension (path2, b2) -> Path.same path1 path2 && b1 = b2 | (Cstr_constant _|Cstr_block _|Cstr_unboxed|Cstr_extension _), _ -> false @@ -348,3 +357,23 @@ type label_description = lbl_loc: Location.t; lbl_attributes: Parsetree.attributes; } + +let rec bound_value_identifiers = function + [] -> [] + | Sig_value(id, {val_kind = Val_reg}, _) :: rem -> + id :: bound_value_identifiers rem + | Sig_typext(id, _, _, _) :: rem -> id :: bound_value_identifiers rem + | Sig_module(id, Mp_present, _, _, _) :: rem -> + id :: bound_value_identifiers rem + | Sig_class(id, _, _, _) :: rem -> id :: bound_value_identifiers rem + | _ :: rem -> bound_value_identifiers rem + +let signature_item_id = function + | Sig_value (id, _, _) + | Sig_type (id, _, _, _) + | Sig_typext (id, _, _, _) + | Sig_module (id, _, _, _, _) + | Sig_modtype (id, _, _) + | Sig_class (id, _, _, _) + | Sig_class_type (id, _, _, _) + -> id diff --git a/typing/types.mli b/typing/types.mli index 1ca92c12..32c468f4 100644 --- a/typing/types.mli +++ b/typing/types.mli @@ -58,7 +58,7 @@ open Asttypes type type_expr = { mutable desc: type_desc; mutable level: int; - mutable scope: int option; + mutable scope: int; id: int } and type_desc = @@ -260,7 +260,11 @@ and value_kind = (* Self *) | Val_anc of (string * Ident.t) list * string (* Ancestor *) - | Val_unbound (* Unbound variable *) + | Val_unbound of value_unbound_reason (* Unbound variable *) + +and value_unbound_reason = + | Val_unbound_instance_variable + | Val_unbound_ghost_recursive (* Variance *) @@ -274,6 +278,7 @@ module Variance : sig val union : t -> t -> t val inter : t -> t -> t val subset : t -> t -> bool + val eq : t -> t -> bool val set : f -> bool -> t -> t val mem : f -> t -> bool val conjugate : t -> t (* exchange positive and negative *) @@ -291,8 +296,8 @@ type type_declaration = type_manifest: type_expr option; type_variance: Variance.t list; (* covariant, contravariant, weakly contravariant, injective *) - type_newtype_level: (int * int) option; - (* definition level * expansion level *) + type_is_newtype: bool; + type_expansion_scope: int; type_loc: Location.t; type_attributes: Parsetree.attributes; type_immediate: bool; (* true iff type should not be a pointer *) @@ -310,7 +315,7 @@ and record_representation = | Record_float (* All fields are floats *) | Record_unboxed of bool (* Unboxed single-field record, inlined or not *) | Record_inlined of int (* Inlined record *) - | Record_extension (* Inlined record under extension *) + | Record_extension of Path.t (* Inlined record under extension *) and label_declaration = { @@ -401,26 +406,31 @@ type class_type_declaration = (* Type expressions for the module language *) +type visibility = + | Exported + | Hidden + type module_type = Mty_ident of Path.t | Mty_signature of signature | Mty_functor of Ident.t * module_type option * module_type - | Mty_alias of alias_presence * Path.t + | Mty_alias of Path.t -and alias_presence = - | Mta_present - | Mta_absent +and module_presence = + | Mp_present + | Mp_absent and signature = signature_item list and signature_item = - Sig_value of Ident.t * value_description - | Sig_type of Ident.t * type_declaration * rec_status - | Sig_typext of Ident.t * extension_constructor * ext_status - | Sig_module of Ident.t * module_declaration * rec_status - | Sig_modtype of Ident.t * modtype_declaration - | Sig_class of Ident.t * class_declaration * rec_status - | Sig_class_type of Ident.t * class_type_declaration * rec_status + Sig_value of Ident.t * value_description * visibility + | Sig_type of Ident.t * type_declaration * rec_status * visibility + | Sig_typext of Ident.t * extension_constructor * ext_status * visibility + | Sig_module of + Ident.t * module_presence * module_declaration * rec_status * visibility + | Sig_modtype of Ident.t * modtype_declaration * visibility + | Sig_class of Ident.t * class_declaration * rec_status * visibility + | Sig_class_type of Ident.t * class_type_declaration * rec_status * visibility and module_declaration = { @@ -493,3 +503,11 @@ type label_description = lbl_loc: Location.t; lbl_attributes: Parsetree.attributes; } + +(** Extracts the list of "value" identifiers bound by a signature. + "Value" identifiers are identifiers for signature components that + correspond to a run-time value: values, extensions, modules, classes. + Note: manifest primitives do not correspond to a run-time value! *) +val bound_value_identifiers: signature -> Ident.t list + +val signature_item_id : signature_item -> Ident.t diff --git a/typing/typetexp.ml b/typing/typetexp.ml index d392fc58..0fc8882e 100644 --- a/typing/typetexp.ml +++ b/typing/typetexp.ml @@ -34,8 +34,8 @@ type error = | Bound_type_variable of string | Recursive_type | Unbound_row_variable of Longident.t - | Type_mismatch of (type_expr * type_expr) list - | Alias_type_mismatch of (type_expr * type_expr) list + | Type_mismatch of Ctype.Unification_trace.t + | Alias_type_mismatch of Ctype.Unification_trace.t | Present_has_conjunction of string | Present_has_no_type of string | Constructor_mismatch of type_expr * type_expr @@ -64,12 +64,19 @@ type error = | Cannot_scrape_alias of Longident.t * Path.t | Opened_object of Path.t option | Not_an_object of type_expr + | Unbound_value_missing_rec of Longident.t * Location.t exception Error of Location.t * Env.t * error exception Error_forward of Location.error +(** Map indexed by type variable names. *) +module TyVarMap = Misc.Stdlib.String.Map -type variable_context = int * (string, type_expr) Tbl.t +type variable_context = int * type_expr TyVarMap.t + +(* To update locations from Typemod.check_well_founded_module. *) + +let typemod_update_location = ref (fun _ -> assert false) (* Narrowing unbound identifier errors. *) @@ -93,7 +100,7 @@ let rec narrow_unbound_lid_error : 'a. _ -> _ -> _ -> _ -> 'a = error (Wrong_use_of_module (mlid, `Functor_used_as_structure)) | Mty_ident _ -> error (Wrong_use_of_module (mlid, `Abstract_used_as_structure)) - | Mty_alias(_, p) -> error (Cannot_scrape_alias(mlid, p)) + | Mty_alias p -> error (Cannot_scrape_alias(mlid, p)) | Mty_signature _ -> () end | Longident.Lapply (flid, mlid) -> @@ -105,7 +112,7 @@ let rec narrow_unbound_lid_error : 'a. _ -> _ -> _ -> _ -> 'a = error (Wrong_use_of_module (flid, `Structure_used_as_functor)) | Mty_ident _ -> error (Wrong_use_of_module (flid, `Abstract_used_as_functor)) - | Mty_alias(_, p) -> error (Cannot_scrape_alias(flid, p)) + | Mty_alias p -> error (Cannot_scrape_alias(flid, p)) | Mty_functor (_, None, _) -> error (Wrong_use_of_module (flid, `Generative_used_as_applicative)) | Mty_functor (_, Some mty_param, _) -> mty_param @@ -114,7 +121,7 @@ let rec narrow_unbound_lid_error : 'a. _ -> _ -> _ -> _ -> 'a = let mpath = Env.lookup_module ~load:true mlid env in let mmd = Env.find_module mpath env in begin match Env.scrape_alias env mmd.md_type with - | Mty_alias(_, p) -> error (Cannot_scrape_alias(mlid, p)) + | Mty_alias p -> error (Cannot_scrape_alias(mlid, p)) | mty_arg -> let details = try Includemod.check_modtype_inclusion @@ -138,6 +145,8 @@ let find_component (lookup : ?loc:_ -> ?mark:_ -> _) make_error env loc lid = narrow_unbound_lid_error env loc lid make_error | Env.Recmodule -> raise (Error (loc, env, Illegal_reference_to_recursive_module)) + | err -> + raise (!typemod_update_location loc err) let find_type env loc lid = let path = @@ -145,7 +154,7 @@ let find_type env loc lid = env loc lid in let decl = Env.find_type path env in - Builtin_attributes.check_deprecated loc decl.type_attributes (Path.name path); + Builtin_attributes.check_alerts loc decl.type_attributes (Path.name path); (path, decl) let find_constructor = @@ -162,7 +171,7 @@ let find_class env loc lid = let (path, decl) as r = find_component Env.lookup_class (fun lid -> Unbound_class lid) env loc lid in - Builtin_attributes.check_deprecated loc decl.cty_attributes (Path.name path); + Builtin_attributes.check_alerts loc decl.cty_attributes (Path.name path); r let find_value env loc lid = @@ -170,17 +179,18 @@ let find_value env loc lid = let (path, decl) as r = find_component Env.lookup_value (fun lid -> Unbound_value lid) env loc lid in - Builtin_attributes.check_deprecated loc decl.val_attributes (Path.name path); + Builtin_attributes.check_alerts loc decl.val_attributes (Path.name path); r let lookup_module ?(load=false) env loc lid = - find_component (fun ?loc ?mark lid env -> (Env.lookup_module ~load ?loc ?mark lid env)) + find_component + (fun ?loc ?mark lid env -> (Env.lookup_module ~load ?loc ?mark lid env)) (fun lid -> Unbound_module lid) env loc lid let find_module env loc lid = let path = lookup_module ~load:true env loc lid in let decl = Env.find_module path env in - (* No need to check for deprecated here, this is done in Env. *) + (* No need to check for alerts here, this is done in Env. *) (path, decl) let find_modtype env loc lid = @@ -188,7 +198,7 @@ let find_modtype env loc lid = find_component Env.lookup_modtype (fun lid -> Unbound_modtype lid) env loc lid in - Builtin_attributes.check_deprecated loc decl.mtd_attributes (Path.name path); + Builtin_attributes.check_alerts loc decl.mtd_attributes (Path.name path); r let find_class_type env loc lid = @@ -196,7 +206,7 @@ let find_class_type env loc lid = find_component Env.lookup_cltype (fun lid -> Unbound_cltype lid) env loc lid in - Builtin_attributes.check_deprecated loc decl.clty_attributes (Path.name path); + Builtin_attributes.check_alerts loc decl.clty_attributes (Path.name path); r let unbound_constructor_error env lid = @@ -240,15 +250,15 @@ let create_package_mty fake loc env (p, l) = (* Translation of type expressions *) -let type_variables = ref (Tbl.empty : (string, type_expr) Tbl.t) +let type_variables = ref (TyVarMap.empty : type_expr TyVarMap.t) let univars = ref ([] : (string * type_expr) list) let pre_univars = ref ([] : type_expr list) -let used_variables = ref (Tbl.empty : (string, type_expr * Location.t) Tbl.t) +let used_variables = ref (TyVarMap.empty : (type_expr * Location.t) TyVarMap.t) let reset_type_variables () = reset_global_level (); Ctype.reset_reified_var_counter (); - type_variables := Tbl.empty + type_variables := TyVarMap.empty let narrow () = (increase_global_level (), !type_variables) @@ -271,7 +281,7 @@ let newvar ?name () = let type_variable loc name = try - Tbl.find name !type_variables + TyVarMap.find name !type_variables with Not_found -> raise(Error(loc, Env.empty, Unbound_type_variable ("'" ^ name))) @@ -287,11 +297,11 @@ let transl_type_param env styp = try if name <> "" && name.[0] = '_' then raise (Error (loc, Env.empty, Invalid_variable_name ("'" ^ name))); - ignore (Tbl.find name !type_variables); + ignore (TyVarMap.find name !type_variables); raise Already_bound with Not_found -> let v = new_global_var ~name () in - type_variables := Tbl.add name v !type_variables; + type_variables := TyVarMap.add name v !type_variables; v in { ctyp_desc = Ttyp_var name; ctyp_type = ty; ctyp_env = env; @@ -308,10 +318,6 @@ let transl_type_param env styp = let new_pre_univar ?name () = let v = newvar ?name () in pre_univars := v :: !pre_univars; v -let rec swap_list = function - x :: y :: l -> y :: x :: swap_list l - | l -> l - type policy = Fixed | Extensible | Univars let rec transl_type env policy styp = @@ -340,12 +346,12 @@ and transl_type_aux env policy styp = begin try instance (List.assoc name !univars) with Not_found -> try - instance (fst(Tbl.find name !used_variables)) + instance (fst (TyVarMap.find name !used_variables)) with Not_found -> let v = if policy = Univars then new_pre_univar ~name () else newvar ~name () in - used_variables := Tbl.add name (v, styp.ptyp_loc) !used_variables; + used_variables := TyVarMap.add name (v, styp.ptyp_loc) !used_variables; v end in @@ -388,7 +394,9 @@ and transl_type_aux env policy styp = List.iter2 (fun (sty, cty) ty' -> try unify_param env ty' cty.ctyp_type with Unify trace -> - raise (Error(sty.ptyp_loc, env, Type_mismatch (swap_list trace)))) + let trace = Unification_trace.swap trace in + raise (Error(sty.ptyp_loc, env, Type_mismatch trace)) + ) (List.combine stl args) params; let constr = newconstr path (List.map (fun ctyp -> ctyp.ctyp_type) args) in @@ -441,7 +449,9 @@ and transl_type_aux env policy styp = List.iter2 (fun (sty, cty) ty' -> try unify_var env ty' cty.ctyp_type with Unify trace -> - raise (Error(sty.ptyp_loc, env, Type_mismatch (swap_list trace)))) + let trace = Unification_trace.swap trace in + raise (Error(sty.ptyp_loc, env, Type_mismatch trace)) + ) (List.combine stl args) params; let ty_args = List.map (fun ctyp -> ctyp.ctyp_type) args in let ty = @@ -487,21 +497,22 @@ and transl_type_aux env policy styp = let t = try List.assoc alias !univars with Not_found -> - instance (fst(Tbl.find alias !used_variables)) + instance (fst(TyVarMap.find alias !used_variables)) in let ty = transl_type env policy st in begin try unify_var env t ty.ctyp_type with Unify trace -> - let trace = swap_list trace in + let trace = Unification_trace.swap trace in raise(Error(styp.ptyp_loc, env, Alias_type_mismatch trace)) end; ty with Not_found -> if !Clflags.principal then begin_def (); let t = newvar () in - used_variables := Tbl.add alias (t, styp.ptyp_loc) !used_variables; + used_variables := + TyVarMap.add alias (t, styp.ptyp_loc) !used_variables; let ty = transl_type env policy st in begin try unify_var env t ty.ctyp_type with Unify trace -> - let trace = swap_list trace in + let trace = Unification_trace.swap trace in raise(Error(styp.ptyp_loc, env, Alias_type_mismatch trace)) end; if !Clflags.principal then begin @@ -539,11 +550,14 @@ and transl_type_aux env policy styp = with Not_found -> Hashtbl.add hfields h (l,f) in - let add_field = function - Rtag (l, attrs, c, stl) -> + let add_field field = + let rf_loc = field.prf_loc in + let rf_attributes = field.prf_attributes in + let rf_desc = match field.prf_desc with + | Rtag (l, c, stl) -> name := None; let tl = - Builtin_attributes.warning_scope attrs + Builtin_attributes.warning_scope rf_attributes (fun () -> List.map (transl_type env policy) stl) in let f = match present with @@ -559,7 +573,7 @@ and transl_type_aux env policy styp = Rpresent (Some st.ctyp_type) in add_typed_field styp.ptyp_loc l.txt f; - Ttag (l,attrs,c,tl) + Ttag (l,c,tl) | Rinherit sty -> let cty = transl_type env policy sty in let ty = cty.ctyp_type in @@ -602,6 +616,8 @@ and transl_type_aux env policy styp = add_typed_field sty.ptyp_loc l f) fl; Tinherit cty + in + { rf_desc; rf_loc; rf_attributes; } in let tfields = List.map add_field fields in let fields = Hashtbl.fold (fun _ p l -> p :: l) hfields [] in @@ -688,13 +704,16 @@ and transl_fields env policy o fields = raise(Error(loc, env, Method_mismatch (l, ty, ty'))) with Not_found -> Hashtbl.add hfields l ty in - let add_field = function - | Otag (s, a, ty1) -> begin + let add_field {pof_desc; pof_loc; pof_attributes;} = + let of_loc = pof_loc in + let of_attributes = pof_attributes in + let of_desc = match pof_desc with + | Otag (s, ty1) -> begin let ty1 = - Builtin_attributes.warning_scope a + Builtin_attributes.warning_scope of_attributes (fun () -> transl_poly_type env policy ty1) in - let field = OTtag (s, a, ty1) in + let field = OTtag (s, ty1) in add_typed_field ty1.ctyp_loc s.txt ty1.ctyp_type; field end @@ -723,6 +742,8 @@ and transl_fields env policy o fields = raise (Error (sty.ptyp_loc, env, Unbound_type_constructor_2 p)) | _ -> raise (Error (sty.ptyp_loc, env, Not_an_object t)) end in + { of_desc; of_loc; of_attributes; } + in let object_fields = List.map add_field fields in let fields = Hashtbl.fold (fun s ty l -> (s, ty) :: l) hfields [] in let ty_init = @@ -764,21 +785,21 @@ let create_package_mty = create_package_mty false let globalize_used_variables env fixed = let r = ref [] in - Tbl.iter + TyVarMap.iter (fun name (ty, loc) -> let v = new_global_var () in let snap = Btype.snapshot () in if try unify env v ty; true with _ -> Btype.backtrack snap; false then try - r := (loc, v, Tbl.find name !type_variables) :: !r + r := (loc, v, TyVarMap.find name !type_variables) :: !r with Not_found -> if fixed && Btype.is_Tvar (repr ty) then raise(Error(loc, env, Unbound_type_variable ("'"^name))); let v2 = new_global_var () in r := (loc, v, v2) :: !r; - type_variables := Tbl.add name v2 !type_variables) + type_variables := TyVarMap.add name v2 !type_variables) !used_variables; - used_variables := Tbl.empty; + used_variables := TyVarMap.empty; fun () -> List.iter (function (loc, t1, t2) -> @@ -787,23 +808,23 @@ let globalize_used_variables env fixed = !r let transl_simple_type env fixed styp = - univars := []; used_variables := Tbl.empty; + univars := []; used_variables := TyVarMap.empty; let typ = transl_type env (if fixed then Fixed else Extensible) styp in globalize_used_variables env fixed (); make_fixed_univars typ.ctyp_type; typ let transl_simple_type_univars env styp = - univars := []; used_variables := Tbl.empty; pre_univars := []; + univars := []; used_variables := TyVarMap.empty; pre_univars := []; begin_def (); let typ = transl_type env Univars styp in (* Only keep already global variables in used_variables *) let new_variables = !used_variables in - used_variables := Tbl.empty; - Tbl.iter + used_variables := TyVarMap.empty; + TyVarMap.iter (fun name p -> - if Tbl.mem name !type_variables then - used_variables := Tbl.add name p !used_variables) + if TyVarMap.mem name !type_variables then + used_variables := TyVarMap.add name p !used_variables) new_variables; globalize_used_variables env false (); end_def (); @@ -823,7 +844,7 @@ let transl_simple_type_univars env styp = instance (Btype.newgenty (Tpoly (typ.ctyp_type, univs))) } let transl_simple_type_delayed env styp = - univars := []; used_variables := Tbl.empty; + univars := []; used_variables := TyVarMap.empty; let typ = transl_type env Extensible styp in make_fixed_univars typ.ctyp_type; (typ, globalize_used_variables env false) @@ -856,21 +877,31 @@ let spellcheck ppf fold env lid = let fold_descr fold get_name f = fold (fun descr acc -> f (get_name descr) acc) let fold_simple fold4 f = fold4 (fun name _path _descr acc -> f name acc) -let fold_values = fold_simple Env.fold_values +let fold_values f = + (* We only use "real" values while spellchecking (as opposed to "ghost" + values inserted in the environment to trigger the "missing rec" hint). + This is needed in order to avoid dummy suggestions like: + "unbound value x, did you mean x?" *) + Env.fold_values + (fun name _path descr acc -> + match descr.val_kind with + | Val_unbound _ -> acc + | _ -> f name acc) let fold_types = fold_simple Env.fold_types let fold_modules = fold_simple Env.fold_modules let fold_constructors = fold_descr Env.fold_constructors (fun d -> d.cstr_name) let fold_labels = fold_descr Env.fold_labels (fun d -> d.lbl_name) -let fold_classs = fold_simple Env.fold_classs +let fold_classes = fold_simple Env.fold_classes let fold_modtypes = fold_simple Env.fold_modtypes let fold_cltypes = fold_simple Env.fold_cltypes let report_error env ppf = function | Unbound_type_variable name -> - (* we don't use "spellcheck" here: the function that raises this - error seems not to be called anywhere, so it's unclear how it - should be handled *) - fprintf ppf "Unbound type parameter %s@." name + let add_name name _ l = if name = "_" then l else ("'" ^ name) :: l in + let names = TyVarMap.fold add_name !type_variables [] in + fprintf ppf "The type variable %s is unbound in this type declaration.@ %a" + name + did_you_mean (fun () -> Misc.spellcheck names name ) | Unbound_type_constructor lid -> fprintf ppf "Unbound type constructor %a" longident lid; spellcheck ppf fold_types env lid; @@ -883,7 +914,7 @@ let report_error env ppf = function but is here applied to %i argument(s)@]" longident lid expected provided | Bound_type_variable name -> - fprintf ppf "Already bound type parameter '%s" name + fprintf ppf "Already bound type parameter %a" Pprintast.tyvar name | Recursive_type -> fprintf ppf "This type is recursive" | Unbound_row_variable lid -> @@ -905,15 +936,21 @@ let report_error env ppf = function | Present_has_conjunction l -> fprintf ppf "The present constructor %s has a conjunctive type" l | Present_has_no_type l -> - fprintf ppf "The present constructor %s has no type" l + fprintf ppf + "@[@[The constructor %s is missing from the upper bound@ \ + (between '<'@ and '>')@ of this polymorphic variant@ \ + but is present in@ its lower bound (after '>').@]@,\ + @[Hint: Either add `%s in the upper bound,@ \ + or remove it@ from the lower bound.@]@]" + l l | Constructor_mismatch (ty, ty') -> wrap_printing_env ~error:true env (fun () -> Printtyp.reset_and_mark_loops_list [ty; ty']; fprintf ppf "@[%s %a@ %s@ %a@]" "This variant type contains a constructor" - Printtyp.type_expr ty + !Oprint.out_type (tree_of_typexp false ty) "which should be" - Printtyp.type_expr ty') + !Oprint.out_type (tree_of_typexp false ty')) | Not_a_variant ty -> Printtyp.reset_and_mark_loops ty; fprintf ppf @@ -933,11 +970,15 @@ let report_error env ppf = function fprintf ppf "The type variable name %s is not allowed in programs" name | Cannot_quantify (name, v) -> fprintf ppf - "@[The universal type variable '%s cannot be generalized:@ %s.@]" - name - (if Btype.is_Tvar v then "it escapes its scope" else - if Btype.is_Tunivar v then "it is already bound to another variable" - else "it is not a variable") + "@[The universal type variable %a cannot be generalized:@ " + Pprintast.tyvar name; + if Btype.is_Tvar v then + fprintf ppf "it escapes its scope" + else if Btype.is_Tunivar v then + fprintf ppf "it is already bound to another variable" + else + fprintf ppf "it is bound to@ %a" Printtyp.type_expr v; + fprintf ppf ".@]"; | Multiple_constraints_on_type s -> fprintf ppf "Multiple constraints for type %a" longident s | Method_mismatch (l, ty, ty') -> @@ -959,7 +1000,7 @@ let report_error env ppf = function spellcheck ppf fold_labels env lid; | Unbound_class lid -> fprintf ppf "Unbound class %a" longident lid; - spellcheck ppf fold_classs env lid; + spellcheck ppf fold_classes env lid; | Unbound_modtype lid -> fprintf ppf "Unbound module type %a" longident lid; spellcheck ppf fold_modtypes env lid; @@ -1007,12 +1048,22 @@ let report_error env ppf = function Printtyp.reset_and_mark_loops ty; fprintf ppf "@[The type %a@ is not an object type@]" Printtyp.type_expr ty + | Unbound_value_missing_rec (lid, loc) -> + fprintf ppf + "Unbound value %a" longident lid; + spellcheck ppf fold_values env lid; + let (_, line, _) = Location.get_pos_info loc.Location.loc_start in + fprintf ppf + "@.@[%s@ %s %i@]" + "Hint: If this is a recursive definition," + "you should add the 'rec' keyword on line" + line let () = Location.register_error_of_exn (function | Error (loc, env, err) -> - Some (Location.error_of_printer loc (report_error env) err) + Some (Location.error_of_printer ~loc (report_error env) err) | Error_forward err -> Some err | _ -> diff --git a/typing/typetexp.mli b/typing/typetexp.mli index 87e95505..b6cea61b 100644 --- a/typing/typetexp.mli +++ b/typing/typetexp.mli @@ -46,8 +46,8 @@ type error = | Bound_type_variable of string | Recursive_type | Unbound_row_variable of Longident.t - | Type_mismatch of (type_expr * type_expr) list - | Alias_type_mismatch of (type_expr * type_expr) list + | Type_mismatch of Ctype.Unification_trace.t + | Alias_type_mismatch of Ctype.Unification_trace.t | Present_has_conjunction of string | Present_has_no_type of string | Constructor_mismatch of type_expr * type_expr @@ -76,6 +76,7 @@ type error = | Cannot_scrape_alias of Longident.t * Path.t | Opened_object of Path.t option | Not_an_object of type_expr + | Unbound_value_missing_rec of Longident.t * Location.t exception Error of Location.t * Env.t * error @@ -118,3 +119,6 @@ val find_class_type: val unbound_constructor_error: Env.t -> Longident.t Location.loc -> 'a val unbound_label_error: Env.t -> Longident.t Location.loc -> 'a + +(* To update location from typemod errors *) +val typemod_update_location: (Location.t -> exn -> exn) ref diff --git a/typing/untypeast.ml b/typing/untypeast.ml index 625c70ef..f54ea60e 100644 --- a/typing/untypeast.ml +++ b/typing/untypeast.ml @@ -23,6 +23,7 @@ module T = Typedtree type mapper = { attribute: mapper -> T.attribute -> attribute; attributes: mapper -> T.attribute list -> attribute list; + binding_op: mapper -> T.binding_op -> T.pattern -> binding_op; case: mapper -> T.case -> case; cases: mapper -> T.case list -> case list; class_declaration: mapper -> T.class_declaration -> class_declaration; @@ -46,11 +47,13 @@ type mapper = { location: mapper -> Location.t -> Location.t; module_binding: mapper -> T.module_binding -> module_binding; module_declaration: mapper -> T.module_declaration -> module_declaration; + module_substitution: mapper -> T.module_substitution -> module_substitution; module_expr: mapper -> T.module_expr -> module_expr; module_type: mapper -> T.module_type -> module_type; module_type_declaration: mapper -> T.module_type_declaration -> module_type_declaration; package_type: mapper -> T.package_type -> package_type; + open_declaration: mapper -> T.open_declaration -> open_declaration; open_description: mapper -> T.open_description -> open_description; pat: mapper -> T.pattern -> pattern; row_field: mapper -> T.row_field -> row_field; @@ -62,6 +65,7 @@ type mapper = { typ: mapper -> T.core_type -> core_type; type_declaration: mapper -> T.type_declaration -> type_declaration; type_extension: mapper -> T.type_extension -> type_extension; + type_exception: mapper -> T.type_exception -> type_exception; type_kind: mapper -> T.type_kind -> type_kind; value_binding: mapper -> T.value_binding -> value_binding; value_description: mapper -> T.value_description -> value_description; @@ -96,7 +100,7 @@ let map_opt f = function None -> None | Some e -> Some (f e) let rec lident_of_path = function | Path.Pident id -> Longident.Lident (Ident.name id) - | Path.Pdot (p, s, _) -> Longident.Ldot (lident_of_path p, s) + | Path.Pdot (p, s) -> Longident.Ldot (lident_of_path p, s) | Path.Papply (p1, p2) -> Longident.Lapply (lident_of_path p1, lident_of_path p2) @@ -105,7 +109,7 @@ let map_loc sub {loc; txt} = {loc = sub.location sub loc; txt} (** Try a name [$name$0], check if it's free, if not, increment and repeat. *) let fresh_name s env = let rec aux i = - let name = s ^ string_of_int i in + let name = s ^ Int.to_string i in try let _ = Env.lookup_value (Lident name) env in name @@ -114,18 +118,39 @@ let fresh_name s env = in aux 0 +(** Extract the [n] patterns from the case of a letop *) +let rec extract_letop_patterns n pat = + if n = 0 then pat, [] + else begin + match pat.pat_desc with + | Tpat_tuple([first; rest]) -> + let next, others = extract_letop_patterns (n-1) rest in + first, next :: others + | _ -> + let rec anys n = + if n = 0 then [] + else { pat with pat_desc = Tpat_any } :: anys (n-1) + in + { pat with pat_desc = Tpat_any }, anys (n-1) + end + (** Mapping functions. *) let constant = function | Const_char c -> Pconst_char c | Const_string (s,d) -> Pconst_string (s,d) - | Const_int i -> Pconst_integer (string_of_int i, None) + | Const_int i -> Pconst_integer (Int.to_string i, None) | Const_int32 i -> Pconst_integer (Int32.to_string i, Some 'l') | Const_int64 i -> Pconst_integer (Int64.to_string i, Some 'L') | Const_nativeint i -> Pconst_integer (Nativeint.to_string i, Some 'n') | Const_float f -> Pconst_float (f,None) -let attribute sub (s, p) = (map_loc sub s, p) +let attribute sub a = { + attr_name = map_loc sub a.attr_name; + attr_payload = a.attr_payload; + attr_loc = a.attr_loc + } + let attributes sub l = List.map (sub.attribute sub) l let structure sub str = @@ -136,7 +161,14 @@ let open_description sub od = let attrs = sub.attributes sub od.open_attributes in Opn.mk ~loc ~attrs ~override:od.open_override - (map_loc sub od.open_txt) + (snd od.open_expr) + +let open_declaration sub od = + let loc = sub.location sub od.open_loc in + let attrs = sub.attributes sub od.open_attributes in + Opn.mk ~loc ~attrs + ~override:od.open_override + (sub.module_expr sub od.open_expr) let structure_item sub item = let loc = sub.location sub item.str_loc in @@ -152,7 +184,7 @@ let structure_item sub item = | Tstr_typext tyext -> Pstr_typext (sub.type_extension sub tyext) | Tstr_exception ext -> - Pstr_exception (sub.extension_constructor sub ext) + Pstr_exception (sub.type_exception sub ext) | Tstr_module mb -> Pstr_module (sub.module_binding sub mb) | Tstr_recmodule list -> @@ -160,7 +192,7 @@ let structure_item sub item = | Tstr_modtype mtd -> Pstr_modtype (sub.module_type_declaration sub mtd) | Tstr_open od -> - Pstr_open (sub.open_description sub od) + Pstr_open (sub.open_declaration sub od) | Tstr_class list -> Pstr_class (List.map @@ -246,6 +278,11 @@ let type_extension sub tyext = (map_loc sub tyext.tyext_txt) (List.map (sub.extension_constructor sub) tyext.tyext_constructors) +let type_exception sub tyexn = + let attrs = sub.attributes sub tyexn.tyexn_attributes in + Te.mk_exception ~attrs + (sub.extension_constructor sub tyexn.tyexn_constructor) + let extension_constructor sub ext = let loc = sub.location sub ext.ext_loc in let attrs = sub.attributes sub ext.ext_attributes in @@ -315,6 +352,7 @@ let pattern sub pat = | Tpat_array list -> Ppat_array (List.map (sub.pat sub) list) | Tpat_or (p1, p2, _) -> Ppat_or (sub.pat sub p1, sub.pat sub p2) | Tpat_lazy p -> Ppat_lazy (sub.pat sub p) + | Tpat_exception p -> Ppat_exception (sub.pat sub p) in Pat.mk ~loc ~attrs desc @@ -329,8 +367,6 @@ let exp_extra sub (extra, loc, attrs) sexp = sub.typ sub cty2) | Texp_constraint cty -> Pexp_constraint (sexp, sub.typ sub cty) - | Texp_open (ovf, _path, lid, _) -> - Pexp_open (ovf, map_loc sub lid, sexp) | Texp_poly cto -> Pexp_poly (sexp, map_opt (sub.typ sub) cto) | Texp_newtype s -> Pexp_newtype (mkloc s loc, sexp) in @@ -386,18 +422,8 @@ let expression sub exp = None -> list | Some exp -> (label, sub.expr sub exp) :: list ) list []) - | Texp_match (exp, cases, exn_cases, _) -> - let merged_cases = sub.cases sub cases - @ List.map - (fun c -> - let uc = sub.case sub c in - let pat = { uc.pc_lhs - with ppat_desc = Ppat_exception uc.pc_lhs } - in - { uc with pc_lhs = pat }) - exn_cases - in - Pexp_match (sub.expr sub exp, merged_cases) + | Texp_match (exp, cases, _) -> + Pexp_match (sub.expr sub exp, sub.cases sub cases) | Texp_try (exp, cases) -> Pexp_try (sub.expr sub exp, sub.cases sub cases) | Texp_tuple list -> @@ -452,7 +478,7 @@ let expression sub exp = Pexp_override (List.map (fun (_path, lid, exp) -> (map_loc sub lid, sub.expr sub exp) ) list) - | Texp_letmodule (_id, name, mexpr, exp) -> + | Texp_letmodule (_id, name, _pres, mexpr, exp) -> Pexp_letmodule (name, sub.module_expr sub mexpr, sub.expr sub exp) | Texp_letexception (ext, exp) -> @@ -464,6 +490,14 @@ let expression sub exp = Pexp_object (sub.class_structure sub cl) | Texp_pack (mexpr) -> Pexp_pack (sub.module_expr sub mexpr) + | Texp_letop {let_; ands; body; _} -> + let pat, and_pats = + extract_letop_patterns (List.length ands) body.c_lhs + in + let let_ = sub.binding_op sub let_ pat in + let ands = List.map2 (sub.binding_op sub) ands and_pats in + let body = sub.expr sub body.c_rhs in + Pexp_letop {let_; ands; body } | Texp_unreachable -> Pexp_unreachable | Texp_extension_constructor (lid, _) -> @@ -471,10 +505,19 @@ let expression sub exp = PStr [ Str.eval ~loc (Exp.construct ~loc (map_loc sub lid) None) ]) + | Texp_open (od, exp) -> + Pexp_open (sub.open_declaration sub od, sub.expr sub exp) in List.fold_right (exp_extra sub) exp.exp_extra (Exp.mk ~loc ~attrs desc) +let binding_op sub bop pat = + let pbop_op = bop.bop_op_name in + let pbop_pat = sub.pat sub pat in + let pbop_exp = sub.expr sub bop.bop_exp in + let pbop_loc = bop.bop_loc in + {pbop_op; pbop_pat; pbop_exp; pbop_loc} + let package_type sub pack = (map_loc sub pack.pack_txt, List.map (fun (s, ct) -> @@ -498,12 +541,16 @@ let signature_item sub item = Psig_value (sub.value_description sub v) | Tsig_type (rec_flag, list) -> Psig_type (rec_flag, List.map (sub.type_declaration sub) list) + | Tsig_typesubst list -> + Psig_typesubst (List.map (sub.type_declaration sub) list) | Tsig_typext tyext -> Psig_typext (sub.type_extension sub tyext) | Tsig_exception ext -> - Psig_exception (sub.extension_constructor sub ext) + Psig_exception (sub.type_exception sub ext) | Tsig_module md -> Psig_module (sub.module_declaration sub md) + | Tsig_modsubst ms -> + Psig_modsubst (sub.module_substitution sub ms) | Tsig_recmodule list -> Psig_recmodule (List.map (sub.module_declaration sub) list) | Tsig_modtype mtd -> @@ -528,6 +575,13 @@ let module_declaration sub md = (map_loc sub md.md_name) (sub.module_type sub md.md_type) +let module_substitution sub ms = + let loc = sub.location sub ms.ms_loc in + let attrs = sub.attributes sub ms.ms_attributes in + Ms.mk ~loc ~attrs + (map_loc sub ms.ms_name) + (map_loc sub ms.ms_txt) + let include_infos f sub incl = let loc = sub.location sub incl.incl_loc in let attrs = sub.attributes sub incl.incl_attributes in @@ -634,8 +688,8 @@ let class_expr sub cexpr = | Tcl_constraint (cl, Some clty, _vals, _meths, _concrs) -> Pcl_constraint (sub.class_expr sub cl, sub.class_type sub clty) - | Tcl_open (ovf, _p, lid, _env, e) -> - Pcl_open (ovf, lid, sub.class_expr sub e) + | Tcl_open (od, e) -> + Pcl_open (sub.open_description sub od, sub.class_expr sub e) | Tcl_ident _ -> assert false | Tcl_constraint (_, None, _, _, _) -> assert false @@ -651,8 +705,8 @@ let class_type sub ct = Pcty_constr (map_loc sub lid, List.map (sub.typ sub) list) | Tcty_arrow (label, ct, cl) -> Pcty_arrow (label, sub.typ sub ct, sub.class_type sub cl) - | Tcty_open (ovf, _p, lid, _env, e) -> - Pcty_open (ovf, lid, sub.class_type sub e) + | Tcty_open (od, e) -> + Pcty_open (sub.open_description sub od, sub.class_type sub e) in Cty.mk ~loc ~attrs desc @@ -716,17 +770,25 @@ let class_structure sub cs = pcstr_fields = List.map (sub.class_field sub) cs.cstr_fields; } -let row_field sub rf = - match rf with - Ttag (label, attrs, bool, list) -> - Rtag (label, sub.attributes sub attrs, bool, List.map (sub.typ sub) list) - | Tinherit ct -> Rinherit (sub.typ sub ct) - -let object_field sub ofield = - match ofield with - OTtag (label, attrs, ct) -> - Otag (label, sub.attributes sub attrs, sub.typ sub ct) - | OTinherit ct -> Oinherit (sub.typ sub ct) +let row_field sub {rf_loc; rf_desc; rf_attributes;} = + let loc = sub.location sub rf_loc in + let attrs = sub.attributes sub rf_attributes in + let desc = match rf_desc with + | Ttag (label, bool, list) -> + Rtag (label, bool, List.map (sub.typ sub) list) + | Tinherit ct -> Rinherit (sub.typ sub ct) + in + Rf.mk ~loc ~attrs desc + +let object_field sub {of_loc; of_desc; of_attributes;} = + let loc = sub.location sub of_loc in + let attrs = sub.attributes sub of_attributes in + let desc = match of_desc with + | OTtag (label, ct) -> + Otag (label, sub.typ sub ct) + | OTinherit ct -> Oinherit (sub.typ sub ct) + in + Of.mk ~loc ~attrs desc and is_self_pat = function | { pat_desc = Tpat_alias(_pat, id, _) } -> @@ -774,8 +836,9 @@ let location _sub l = l let default_mapper = { - attribute = attribute ; - attributes = attributes ; + attribute = attribute; + attributes = attributes; + binding_op = binding_op; structure = structure; structure_item = structure_item; module_expr = module_expr; @@ -796,14 +859,17 @@ let default_mapper = type_kind = type_kind; typ = core_type; type_extension = type_extension; + type_exception = type_exception; extension_constructor = extension_constructor; value_description = value_description; pat = pattern; expr = expression; module_declaration = module_declaration; + module_substitution = module_substitution; module_type_declaration = module_type_declaration; module_binding = module_binding; package_type = package_type ; + open_declaration = open_declaration; open_description = open_description; include_description = include_description; include_declaration = include_declaration; diff --git a/typing/untypeast.mli b/typing/untypeast.mli index 20a6668c..3cb888f1 100644 --- a/typing/untypeast.mli +++ b/typing/untypeast.mli @@ -20,6 +20,8 @@ val lident_of_path : Path.t -> Longident.t type mapper = { attribute: mapper -> Typedtree.attribute -> attribute; attributes: mapper -> Typedtree.attribute list -> attribute list; + binding_op: mapper -> Typedtree.binding_op -> Typedtree.pattern + -> binding_op; case: mapper -> Typedtree.case -> case; cases: mapper -> Typedtree.case list -> case list; class_declaration: mapper -> Typedtree.class_declaration -> class_declaration; @@ -47,11 +49,14 @@ type mapper = { module_binding: mapper -> Typedtree.module_binding -> module_binding; module_declaration: mapper -> Typedtree.module_declaration -> module_declaration; + module_substitution: + mapper -> Typedtree.module_substitution -> module_substitution; module_expr: mapper -> Typedtree.module_expr -> module_expr; module_type: mapper -> Typedtree.module_type -> module_type; module_type_declaration: mapper -> Typedtree.module_type_declaration -> module_type_declaration; package_type: mapper -> Typedtree.package_type -> package_type; + open_declaration: mapper -> Typedtree.open_declaration -> open_declaration; open_description: mapper -> Typedtree.open_description -> open_description; pat: mapper -> Typedtree.pattern -> pattern; row_field: mapper -> Typedtree.row_field -> row_field; @@ -63,6 +68,7 @@ type mapper = { typ: mapper -> Typedtree.core_type -> core_type; type_declaration: mapper -> Typedtree.type_declaration -> type_declaration; type_extension: mapper -> Typedtree.type_extension -> type_extension; + type_exception: mapper -> Typedtree.type_exception -> type_exception; type_kind: mapper -> Typedtree.type_kind -> type_kind; value_binding: mapper -> Typedtree.value_binding -> value_binding; value_description: mapper -> Typedtree.value_description -> value_description; diff --git a/utils/HACKING.adoc b/utils/HACKING.adoc new file mode 100644 index 00000000..af2fd01f --- /dev/null +++ b/utils/HACKING.adoc @@ -0,0 +1,60 @@ +== Magic numbers + +The magic numbers in `config.mlp` are included in the header of +compiled files produced by the OCaml compiler. Different kind of files +(cmi, cmo, cmx, cma, executables, etc.) get different magic numbers, +and we also change the magic number whenever we change the format of +the corresponding file. + +Note that the `exec_magic_number` value is duplicated as `EXEC_MAGIC` +in `runtime/caml/exec.h` and they must be kept in sync. + +This lets the compiler differentiate files that should be valid files +of the kind it expects, and files that are passed by mistake, either +that are not at all valid compiled files, or because they come from +a different compiler version with an incompatible file format. + +We say that we "bump" a magic number when we update its version part +in config.mlp. To bump all magic numbers is to increment the version +of every kind of magic number. + +=== Updating magic numbers + +Previously people tried to update magic numbers as infrequently as +possible, to maximize the lifetime of tools supporting only a fixed +version of magic numbers -- so that they would work for as long as the +underlying representation is compatible. + +However, it is more dangerous to forget to update a number than to +update it too often. If we update too often, at worst tool authors have +to update their codebase to support more numbers. If we don't update +often enough, tools break with horrible parsing/deserialization errors +and their authors can do nothing to prevent it. + +We have thus decided to systematically bump all magic numbers on each +new major release of the compiler. (We don't want to change compiled +file formats in minor releases, so we shouldn't need to bump magic +numbers systematically. If a format change was necessary for +a critical bugfix, then we would still need to bump on a minor +release.) + +This should preferably be done just before the first testing release +(the first beta, or the first rc if there is no beta) of the new major +release. We want it to happen after all format-breaking changes have +been included in the development version, but before the version gets +tested on a large scale: this is when tool authors may update their +tools to test the new release, and if you update *after* that you risk +breaking them again without them noticing. + +For example, the magic numbers for 4.07 were updated in + 7c416d1c01f82122b767cd6f08ca7d0839fd15fa +and + c10b2edccc9704fd99673812f688c103e2ffcfcf + +(There are two commits as one kind of magic number was forgotten, +ideally there should be only one commit.) + +=== How to update magic numbers + +In order to update magic numbers, you must follow the boostrap procedure +described in BOOTSTRAP.adoc diff --git a/utils/Makefile b/utils/Makefile new file mode 100644 index 00000000..b446d8da --- /dev/null +++ b/utils/Makefile @@ -0,0 +1,93 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 1999 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +# The Makefile for generating the configuration file + +ROOTDIR = .. + +include $(ROOTDIR)/Makefile.config + +ifeq "$(UNIX_OR_WIN32)" "win32" +ifeq "$(wildcard $(ROOTDIR)/flexdll/Makefile)" "" + FLEXDLL_DIR = +else + FLEXDLL_DIR = $(if $(wildcard $(ROOTDIR)/flexdll/flexdll_*.$(O)),+flexdll) +endif +else + FLEXDLL_DIR = +endif + +# SUBST generates the sed substitution for the variable *named* in $1 +# SUBST_QUOTE does the same, adding double-quotes around non-empty strings +# (see FLEXDLL_DIR which must empty if FLEXDLL_DIR is empty but an OCaml +# string otherwise) +SUBST_ESCAPE=$(subst ",\\",$(subst \,\\,$(if $2,$2,$($1)))) +SUBST=-e 's|%%$1%%|$(call SUBST_ESCAPE,$1,$2)|' +SUBST_QUOTE2=-e 's|%%$1%%|$(if $2,"$2")|' +SUBST_QUOTE=$(call SUBST_QUOTE2,$1,$(call SUBST_ESCAPE,$1,$2)) +FLEXLINK_LDFLAGS=$(if $(OC_LDFLAGS), -link "$(OC_LDFLAGS)") +config.ml: config.mlp $(ROOTDIR)/Makefile.config Makefile + sed $(call SUBST,AFL_INSTRUMENT) \ + $(call SUBST,ARCH) \ + $(call SUBST,ARCMD) \ + $(call SUBST,ASM) \ + $(call SUBST,ASM_CFI_SUPPORTED) \ + $(call SUBST,BYTECCLIBS) \ + $(call SUBST,CC) \ + $(call SUBST,CCOMPTYPE) \ + $(call SUBST,CC_PROFILE) \ + $(call SUBST,OUTPUTOBJ) \ + $(call SUBST,EXT_ASM) \ + $(call SUBST,EXT_DLL) \ + $(call SUBST,EXE) \ + $(call SUBST,EXT_LIB) \ + $(call SUBST,EXT_OBJ) \ + $(call SUBST,FLAMBDA) \ + $(call SUBST,WITH_FLAMBDA_INVARIANTS) \ + $(call SUBST,FLEXLINK_FLAGS) \ + $(call SUBST_QUOTE,FLEXDLL_DIR) \ + $(call SUBST,HOST) \ + $(call SUBST,LIBDIR) \ + $(call SUBST,LIBUNWIND_AVAILABLE) \ + $(call SUBST,LIBUNWIND_LINK_FLAGS) \ + $(call SUBST,MKDLL) \ + $(call SUBST,MKEXE) \ + $(call SUBST,FLEXLINK_LDFLAGS) \ + $(call SUBST,MKMAINDLL) \ + $(call SUBST,MODEL) \ + $(call SUBST,NATIVECCLIBS) \ + $(call SUBST,OCAMLC_CFLAGS) \ + $(call SUBST,OCAMLC_CPPFLAGS) \ + $(call SUBST,OCAMLOPT_CFLAGS) \ + $(call SUBST,OCAMLOPT_CPPFLAGS) \ + $(call SUBST,PACKLD) \ + $(call SUBST,PROFILING) \ + $(call SUBST,PROFINFO_WIDTH) \ + $(call SUBST,RANLIBCMD) \ + $(call SUBST,FORCE_SAFE_STRING) \ + $(call SUBST,DEFAULT_SAFE_STRING) \ + $(call SUBST,WINDOWS_UNICODE) \ + $(call SUBST,SUPPORTS_SHARED_LIBRARIES) \ + $(call SUBST,SYSTEM) \ + $(call SUBST,SYSTHREAD_SUPPORT) \ + $(call SUBST,TARGET) \ + $(call SUBST,WITH_FRAME_POINTERS) \ + $(call SUBST,WITH_PROFINFO) \ + $(call SUBST,WITH_SPACETIME) \ + $(call SUBST,ENABLE_CALL_COUNTS) \ + $(call SUBST,FLAT_FLOAT_ARRAY) \ + $(call SUBST,CC_HAS_DEBUG_PREFIX_MAP) \ + $(call SUBST,AS_HAS_DEBUG_PREFIX_MAP) \ + $< > $@ diff --git a/utils/arg_helper.mli b/utils/arg_helper.mli index fba7aa21..18f60fea 100644 --- a/utils/arg_helper.mli +++ b/utils/arg_helper.mli @@ -16,8 +16,13 @@ (** Decipher command line arguments of the form | =[,...] + (as used for example for the specification of inlining parameters varying by simplification round). + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + *) module Make (S : sig diff --git a/utils/build_path_prefix_map.ml b/utils/build_path_prefix_map.ml index 40e3e8e3..c204d3a6 100644 --- a/utils/build_path_prefix_map.ml +++ b/utils/build_path_prefix_map.ml @@ -1,3 +1,18 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Gabriel Scherer, projet Parsifal, INRIA Saclay *) +(* *) +(* Copyright 2017 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + type path = string type path_prefix = string type error_message = string diff --git a/utils/build_path_prefix_map.mli b/utils/build_path_prefix_map.mli index c21f4583..dbcc8dc1 100644 --- a/utils/build_path_prefix_map.mli +++ b/utils/build_path_prefix_map.mli @@ -1,3 +1,26 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Gabriel Scherer, projet Parsifal, INRIA Saclay *) +(* *) +(* Copyright 2017 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** Rewrite paths for reproducible builds + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) + + type path = string type path_prefix = string type error_message = string diff --git a/utils/ccomp.ml b/utils/ccomp.ml index 3f186b3b..d5cee649 100644 --- a/utils/ccomp.ml +++ b/utils/ccomp.ml @@ -21,7 +21,9 @@ let command cmdline = prerr_string cmdline; prerr_newline() end; - Sys.command cmdline + let res = Sys.command cmdline in + if res = 127 then raise (Sys_error cmdline); + res let run_command cmdline = ignore(command cmdline) @@ -64,7 +66,7 @@ let display_msvc_output file name = close_in c; Sys.remove file -let compile_file ?output ?(opt="") name = +let compile_file ?output ?(opt="") ?stable_name name = let (pipe, file) = if Config.ccomp_type = "msvc" && not !Clflags.verbose then try @@ -75,10 +77,15 @@ let compile_file ?output ?(opt="") name = ("", "") else ("", "") in + let debug_prefix_map = + match stable_name with + | Some stable when Config.c_has_debug_prefix_map -> + Printf.sprintf " -fdebug-prefix-map=%s=%s" name stable + | Some _ | None -> "" in let exit = command (Printf.sprintf - "%s %s %s -c %s %s %s %s %s%s" + "%s%s %s %s -c %s %s %s %s %s%s" (match !Clflags.c_compiler with | Some cc -> cc | None -> @@ -87,13 +94,16 @@ let compile_file ?output ?(opt="") name = then (Config.ocamlopt_cflags, Config.ocamlopt_cppflags) else (Config.ocamlc_cflags, Config.ocamlc_cppflags) in (String.concat " " [Config.c_compiler; cflags; cppflags])) + debug_prefix_map (match output with | None -> "" | Some o -> Printf.sprintf "%s%s" Config.c_output_obj o) opt (if !Clflags.debug && Config.ccomp_type <> "msvc" then "-g" else "") (String.concat " " (List.rev !Clflags.all_ccopts)) - (quote_prefixed "-I" (List.rev !Clflags.include_dirs)) + (quote_prefixed "-I" + (List.map (Misc.expand_directory Config.standard_library) + (List.rev !Clflags.include_dirs))) (Clflags.std_include_flag "-I") (Filename.quote name) (* cl tediously includes the name of the C file as the first thing it @@ -151,7 +161,7 @@ let expand_libname name = let libname = "lib" ^ String.sub name 2 (String.length name - 2) ^ Config.ext_lib in try - Misc.find_in_path !Config.load_path libname + Load_path.find libname with Not_found -> libname end @@ -181,7 +191,7 @@ let call_linker mode output_name files extra = Printf.sprintf "%s%s %s %s %s" Config.native_pack_linker (Filename.quote output_name) - (quote_prefixed l_prefix !Config.load_path) + (quote_prefixed l_prefix (Load_path.get_paths ())) (quote_files (remove_Wl files)) extra else @@ -196,7 +206,7 @@ let call_linker mode output_name files extra = (Filename.quote output_name) (if !Clflags.gprofile then Config.cc_profile else "") "" (*(Clflags.std_include_flag "-I")*) - (quote_prefixed "-L" !Config.load_path) + (quote_prefixed "-L" (Load_path.get_paths ())) (String.concat " " (List.rev !Clflags.all_ccopts)) (quote_files files) extra diff --git a/utils/ccomp.mli b/utils/ccomp.mli index 17094ba2..cf67f24e 100644 --- a/utils/ccomp.mli +++ b/utils/ccomp.mli @@ -13,11 +13,17 @@ (* *) (**************************************************************************) -(* Compiling C files and building C libraries *) +(** Compiling C files and building C libraries + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) val command: string -> int val run_command: string -> unit -val compile_file: ?output:string -> ?opt:string -> string -> int +val compile_file: + ?output:string -> ?opt:string -> ?stable_name:string -> string -> int val create_archive: string -> string list -> int val expand_libname: string -> string val quote_files: string list -> string diff --git a/utils/clflags.ml b/utils/clflags.ml index 4e2916b7..c0a70280 100644 --- a/utils/clflags.ml +++ b/utils/clflags.ml @@ -49,7 +49,8 @@ and no_std_include = ref false (* -nostdlib *) and print_types = ref false (* -i *) and make_archive = ref false (* -a *) and debug = ref false (* -g *) -and fast = ref false (* -unsafe *) +and debug_full = ref false (* For full DWARF support *) +and unsafe = ref false (* -unsafe *) and use_linscan = ref false (* -linscan *) and link_everything = ref false (* -linkall *) and custom_runtime = ref false (* -custom *) @@ -60,8 +61,10 @@ and output_complete_object = ref false (* -output-complete-obj *) and all_ccopts = ref ([] : string list) (* -ccopt *) and classic = ref false (* -nolabels *) and nopervasives = ref false (* -nopervasives *) +and match_context_rows = ref 32 (* -match-context-rows *) and preprocessor = ref(None : string option) (* -pp *) and all_ppx = ref ([] : string list) (* -ppx *) +let absname = ref false (* -absname *) let annotations = ref false (* -annot *) let binary_annotations = ref false (* -annot *) and use_threads = ref false (* -thread *) @@ -105,6 +108,7 @@ and dump_flambda = ref false (* -dflambda *) and dump_flambda_let = ref (None : int option) (* -dflambda-let=... *) and dump_flambda_verbose = ref false (* -dflambda-verbose *) and dump_instr = ref false (* -dinstr *) +and keep_camlprimc_file = ref false (* -dcamlprimc *) let keep_asm_file = ref false (* -S *) let optimize_for_speed = ref true (* -compact *) @@ -362,33 +366,95 @@ let set_dumped_pass s enabled = dumped_passes_list := dumped_passes end -let parse_color_setting = function - | "auto" -> Some Misc.Color.Auto - | "always" -> Some Misc.Color.Always - | "never" -> Some Misc.Color.Never - | _ -> None -let color = ref None ;; (* -color *) +let dump_into_file = ref false (* -dump-into-file *) + +type 'a env_reader = { + parse : string -> 'a option; + usage : string; + env_var : string; +} + +let color = ref None (* -color *) + +let color_reader = { + parse = (function + | "auto" -> Some Misc.Color.Auto + | "always" -> Some Misc.Color.Always + | "never" -> Some Misc.Color.Never + | _ -> None); + usage = "expected \"auto\", \"always\" or \"never\""; + env_var = "OCAML_COLOR"; +} + +let error_style = ref None (* -error-style *) + +let error_style_reader = { + parse = (function + | "contextual" -> Some Misc.Error_style.Contextual + | "short" -> Some Misc.Error_style.Short + | _ -> None); + usage = "expected \"contextual\" or \"short\""; + env_var = "OCAML_ERROR_STYLE"; +} let unboxed_types = ref false +(* This is used by the -stop-after option. *) +module Compiler_pass = struct + (* If you add a new pass, the following must be updated: + - the variable `passes` below + - the manpages in man/ocaml{c,opt}.m + - the manual manual/manual/cmds/unified-options.etex + *) + type t = Parsing | Typing + + let to_string = function + | Parsing -> "parsing" + | Typing -> "typing" + + let of_string = function + | "parsing" -> Some Parsing + | "typing" -> Some Typing + | _ -> None + + let rank = function + | Parsing -> 0 + | Typing -> 1 + + let passes = [ + Parsing; + Typing; + ] + let pass_names = List.map to_string passes +end + +let stop_after = ref None (* -stop-after *) + +let should_stop_after pass = + match !stop_after with + | None -> false + | Some stop -> Compiler_pass.rank stop <= Compiler_pass.rank pass + +module String = Misc.Stdlib.String + let arg_spec = ref [] -let arg_names = ref Misc.StringMap.empty +let arg_names = ref String.Map.empty let reset_arguments () = arg_spec := []; - arg_names := Misc.StringMap.empty + arg_names := String.Map.empty let add_arguments loc args = List.iter (function (arg_name, _, _) as arg -> try - let loc2 = Misc.StringMap.find arg_name !arg_names in + let loc2 = String.Map.find arg_name !arg_names in Printf.eprintf "Warning: plugin argument %s is already defined:\n" arg_name; Printf.eprintf " First definition: %s\n" loc2; Printf.eprintf " New definition: %s\n" loc; with Not_found -> arg_spec := !arg_spec @ [ arg ]; - arg_names := Misc.StringMap.add arg_name loc !arg_names + arg_names := String.Map.add arg_name loc !arg_names ) args let print_arguments usage = diff --git a/utils/clflags.mli b/utils/clflags.mli index 04c41c64..9355f2ee 100644 --- a/utils/clflags.mli +++ b/utils/clflags.mli @@ -76,7 +76,8 @@ val no_std_include : bool ref val print_types : bool ref val make_archive : bool ref val debug : bool ref -val fast : bool ref +val debug_full : bool ref +val unsafe : bool ref val use_linscan : bool ref val link_everything : bool ref val custom_runtime : bool ref @@ -87,9 +88,11 @@ val output_complete_object : bool ref val all_ccopts : string list ref val classic : bool ref val nopervasives : bool ref +val match_context_rows : int ref val open_modules : string list ref val preprocessor : string option ref val all_ppx : string list ref +val absname : bool ref val annotations : bool ref val binary_annotations : bool ref val use_threads : bool ref @@ -131,6 +134,7 @@ val dump_rawflambda : bool ref val dump_flambda : bool ref val dump_flambda_let : int option ref val dump_instr : bool ref +val keep_camlprimc_file : bool ref val keep_asm_file : bool ref val optimize_for_speed : bool ref val dump_cmm : bool ref @@ -207,11 +211,33 @@ val all_passes : string list ref val dumped_pass : string -> bool val set_dumped_pass : string -> bool -> unit -val parse_color_setting : string -> Misc.Color.setting option +val dump_into_file : bool ref + +(* Support for flags that can also be set from an environment variable *) +type 'a env_reader = { + parse : string -> 'a option; + usage : string; + env_var : string; +} + val color : Misc.Color.setting option ref +val color_reader : Misc.Color.setting env_reader + +val error_style : Misc.Error_style.setting option ref +val error_style_reader : Misc.Error_style.setting env_reader val unboxed_types : bool ref +module Compiler_pass : sig + type t = Parsing | Typing + val of_string : string -> t option + val to_string : t -> string + val passes : t list + val pass_names : string list +end +val stop_after : Compiler_pass.t option ref +val should_stop_after : Compiler_pass.t -> bool + val arg_spec : (string * Arg.spec * string) list ref (* [add_arguments __LOC__ args] will add the arguments from [args] at diff --git a/utils/config.mli b/utils/config.mli index e7dd460d..cb830782 100644 --- a/utils/config.mli +++ b/utils/config.mli @@ -13,174 +13,236 @@ (* *) (**************************************************************************) -(* System configuration *) +(** System configuration + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) val version: string - (* The current version number of the system *) +(** The current version number of the system *) val standard_library: string - (* The directory containing the standard libraries *) -val standard_runtime: string - (* The full path to the standard bytecode interpreter ocamlrun *) +(** The directory containing the standard libraries *) + val ccomp_type: string - (* The "kind" of the C compiler, assembler and linker used: one of - "cc" (for Unix-style C compilers) - "msvc" (for Microsoft Visual C++ and MASM) *) +(** The "kind" of the C compiler, assembler and linker used: one of + "cc" (for Unix-style C compilers) + "msvc" (for Microsoft Visual C++ and MASM) *) + val c_compiler: string - (* The compiler to use for compiling C files *) +(** The compiler to use for compiling C files *) + val c_output_obj: string - (* Name of the option of the C compiler for specifying the output file *) +(** Name of the option of the C compiler for specifying the output + file *) + +val c_has_debug_prefix_map : bool +(** Whether the C compiler supports -fdebug-prefix-map *) + +val as_has_debug_prefix_map : bool +(** Whether the assembler supports --debug-prefix-map *) + val ocamlc_cflags : string - (* The flags ocamlc should pass to the C compiler *) +(** The flags ocamlc should pass to the C compiler *) + val ocamlc_cppflags : string - (* The flags ocamlc should pass to the C preprocessor *) +(** The flags ocamlc should pass to the C preprocessor *) + val ocamlopt_cflags : string - (* The flags ocamlopt should pass to the C compiler *) +(** The flags ocamlopt should pass to the C compiler *) + val ocamlopt_cppflags : string - (* The flags ocamlopt should pass to the C preprocessor *) +(** The flags ocamlopt should pass to the C preprocessor *) + val bytecomp_c_libraries: string - (* The C libraries to link with custom runtimes *) +(** The C libraries to link with custom runtimes *) + val native_c_libraries: string - (* The C libraries to link with native-code programs *) +(** The C libraries to link with native-code programs *) + val native_pack_linker: string - (* The linker to use for packaging (ocamlopt -pack) and for partial - links (ocamlopt -output-obj). *) +(** The linker to use for packaging (ocamlopt -pack) and for partial + links (ocamlopt -output-obj). *) + val mkdll: string - (* The linker command line to build dynamic libraries. *) +(** The linker command line to build dynamic libraries. *) + val mkexe: string - (* The linker command line to build executables. *) +(** The linker command line to build executables. *) + val mkmaindll: string - (* The linker command line to build main programs as dlls. *) +(** The linker command line to build main programs as dlls. *) + val ranlib: string - (* Command to randomize a library, or "" if not needed *) +(** Command to randomize a library, or "" if not needed *) + val ar: string - (* Name of the ar command, or "" if not needed (MSVC) *) -val cc_profile : string - (* The command line option to the C compiler to enable profiling. *) +(** Name of the ar command, or "" if not needed (MSVC) *) -val load_path: string list ref - (* Directories in the search path for .cmi and .cmo files *) +val cc_profile : string +(** The command line option to the C compiler to enable profiling. *) val interface_suffix: string ref - (* Suffix for interface file names *) +(** Suffix for interface file names *) val exec_magic_number: string - (* Magic number for bytecode executable files *) +(** Magic number for bytecode executable files *) + val cmi_magic_number: string - (* Magic number for compiled interface files *) +(** Magic number for compiled interface files *) + val cmo_magic_number: string - (* Magic number for object bytecode files *) +(** Magic number for object bytecode files *) + val cma_magic_number: string - (* Magic number for archive files *) +(** Magic number for archive files *) + val cmx_magic_number: string - (* Magic number for compilation unit descriptions *) +(** Magic number for compilation unit descriptions *) + val cmxa_magic_number: string - (* Magic number for libraries of compilation unit descriptions *) +(** Magic number for libraries of compilation unit descriptions *) + val ast_intf_magic_number: string - (* Magic number for file holding an interface syntax tree *) +(** Magic number for file holding an interface syntax tree *) + val ast_impl_magic_number: string - (* Magic number for file holding an implementation syntax tree *) +(** Magic number for file holding an implementation syntax tree *) + val cmxs_magic_number: string - (* Magic number for dynamically-loadable plugins *) +(** Magic number for dynamically-loadable plugins *) + val cmt_magic_number: string - (* Magic number for compiled interface files *) +(** Magic number for compiled interface files *) val max_tag: int - (* Biggest tag that can be stored in the header of a regular block. *) +(** Biggest tag that can be stored in the header of a regular block. *) + val lazy_tag : int - (* Normally the same as Obj.lazy_tag. Separate definition because - of technical reasons for bootstrapping. *) +(** Normally the same as Obj.lazy_tag. Separate definition because + of technical reasons for bootstrapping. *) + val max_young_wosize: int - (* Maximal size of arrays that are directly allocated in the - minor heap *) +(** Maximal size of arrays that are directly allocated in the + minor heap *) + val stack_threshold: int - (* Size in words of safe area at bottom of VM stack, - see byterun/config.h *) +(** Size in words of safe area at bottom of VM stack, + see runtime/caml/config.h *) + val stack_safety_margin: int - (* Size in words of the safety margin between the bottom of - the stack and the stack pointer. This margin can be used by - intermediate computations of some instructions, or the event - handler. *) +(** Size in words of the safety margin between the bottom of + the stack and the stack pointer. This margin can be used by + intermediate computations of some instructions, or the event + handler. *) val architecture: string - (* Name of processor type for the native-code compiler *) +(** Name of processor type for the native-code compiler *) + val model: string - (* Name of processor submodel for the native-code compiler *) +(** Name of processor submodel for the native-code compiler *) + val system: string - (* Name of operating system for the native-code compiler *) +(** Name of operating system for the native-code compiler *) val asm: string - (* The assembler (and flags) to use for assembling - ocamlopt-generated code. *) +(** The assembler (and flags) to use for assembling + ocamlopt-generated code. *) val asm_cfi_supported: bool - (* Whether assembler understands CFI directives *) +(** Whether assembler understands CFI directives *) + val with_frame_pointers : bool - (* Whether assembler should maintain frame pointers *) +(** Whether assembler should maintain frame pointers *) val ext_obj: string - (* Extension for object files, e.g. [.o] under Unix. *) +(** Extension for object files, e.g. [.o] under Unix. *) + val ext_asm: string - (* Extension for assembler files, e.g. [.s] under Unix. *) +(** Extension for assembler files, e.g. [.s] under Unix. *) + val ext_lib: string - (* Extension for library files, e.g. [.a] under Unix. *) +(** Extension for library files, e.g. [.a] under Unix. *) + val ext_dll: string - (* Extension for dynamically-loaded libraries, e.g. [.so] under Unix.*) +(** Extension for dynamically-loaded libraries, e.g. [.so] under Unix.*) val default_executable_name: string - (* Name of executable produced by linking if none is given with -o, - e.g. [a.out] under Unix. *) +(** Name of executable produced by linking if none is given with -o, + e.g. [a.out] under Unix. *) val systhread_supported : bool - (* Whether the system thread library is implemented *) +(** Whether the system thread library is implemented *) val flexdll_dirs : string list - (* Directories needed for the FlexDLL objects *) +(** Directories needed for the FlexDLL objects *) val host : string - (* Whether the compiler is a cross-compiler *) +(** Whether the compiler is a cross-compiler *) val target : string - (* Whether the compiler is a cross-compiler *) - -val print_config : out_channel -> unit;; +(** Whether the compiler is a cross-compiler *) val profiling : bool - (* Whether profiling with gprof is supported on this platform *) +(** Whether profiling with gprof is supported on this platform *) val flambda : bool - (* Whether the compiler was configured for flambda *) +(** Whether the compiler was configured for flambda *) + val with_flambda_invariants : bool - (* Whether the invariants checks for flambda are enabled *) +(** Whether the invariants checks for flambda are enabled *) val spacetime : bool - (* Whether the compiler was configured for Spacetime profiling *) +(** Whether the compiler was configured for Spacetime profiling *) + val enable_call_counts : bool - (* Whether call counts are to be available when Spacetime profiling *) +(** Whether call counts are to be available when Spacetime profiling *) + val profinfo : bool - (* Whether the compiler was configured for profiling *) +(** Whether the compiler was configured for profiling *) + val profinfo_width : int - (* How many bits are to be used in values' headers for profiling - information *) +(** How many bits are to be used in values' headers for profiling + information *) + val libunwind_available : bool - (* Whether the libunwind library is available on the target *) +(** Whether the libunwind library is available on the target *) + val libunwind_link_flags : string - (* Linker flags to use libunwind *) +(** Linker flags to use libunwind *) val safe_string: bool - (* Whether the compiler was configured with -force-safe-string; - in that case, the -unsafe-string compile-time option is unavailable +(** Whether the compiler was configured with -force-safe-string; + in that case, the -unsafe-string compile-time option is unavailable + + @since 4.05.0 *) - @since 4.05.0 *) val default_safe_string: bool - (* Whether the compiler was configured to use the -safe-string - or -unsafe-string compile-time option by default. +(** Whether the compiler was configured to use the -safe-string + or -unsafe-string compile-time option by default. + + @since 4.06.0 *) - @since 4.06.0 *) val flat_float_array : bool - (* Whether the compiler and runtime automagically flatten float - arrays *) +(** Whether the compiler and runtime automagically flatten float + arrays *) + val windows_unicode: bool - (* Whether Windows Unicode runtime is enabled *) +(** Whether Windows Unicode runtime is enabled *) + +val supports_shared_libraries: bool +(** Whether shared libraries are supported + + @since 4.08.0 *) + val afl_instrument : bool - (* Whether afl-fuzz instrumentation is generated by default *) +(** Whether afl-fuzz instrumentation is generated by default *) + + +(** Access to configuration values *) +val print_config : out_channel -> unit + +val config_var : string -> string option +(** the configuration value of a variable, if it exists *) diff --git a/utils/config.mlp b/utils/config.mlp index 729e1378..025497a7 100644 --- a/utils/config.mlp +++ b/utils/config.mlp @@ -28,10 +28,11 @@ let standard_library = with Not_found -> standard_library_default -let standard_runtime = "%%BYTERUN%%" let ccomp_type = "%%CCOMPTYPE%%" let c_compiler = "%%CC%%" let c_output_obj = "%%OUTPUTOBJ%%" +let c_has_debug_prefix_map = %%CC_HAS_DEBUG_PREFIX_MAP%% +let as_has_debug_prefix_map = %%AS_HAS_DEBUG_PREFIX_MAP%% let ocamlc_cflags = "%%OCAMLC_CFLAGS%%" let ocamlc_cppflags = "%%OCAMLC_CPPFLAGS%%" let ocamlopt_cflags = "%%OCAMLOPT_CFLAGS%%" @@ -77,33 +78,32 @@ let with_flambda_invariants = %%WITH_FLAMBDA_INVARIANTS%% let safe_string = %%FORCE_SAFE_STRING%% let default_safe_string = %%DEFAULT_SAFE_STRING%% let windows_unicode = %%WINDOWS_UNICODE%% != 0 +let supports_shared_libraries = %%SUPPORTS_SHARED_LIBRARIES%% let flat_float_array = %%FLAT_FLOAT_ARRAY%% let afl_instrument = %%AFL_INSTRUMENT%% -let exec_magic_number = "Caml1999X023" - (* exec_magic_number is duplicated in byterun/caml/exec.h *) -and cmi_magic_number = "Caml1999I024" -and cmo_magic_number = "Caml1999O023" -and cma_magic_number = "Caml1999A023" +let exec_magic_number = "Caml1999X025" + (* exec_magic_number is duplicated in runtime/caml/exec.h *) +and cmi_magic_number = "Caml1999I025" +and cmo_magic_number = "Caml1999O025" +and cma_magic_number = "Caml1999A025" and cmx_magic_number = if flambda then - "Caml1999y023" + "Caml1999y025" else - "Caml1999Y023" + "Caml1999Y025" and cmxa_magic_number = if flambda then - "Caml1999z023" + "Caml1999z025" else - "Caml1999Z023" -and ast_impl_magic_number = "Caml1999M023" -and ast_intf_magic_number = "Caml1999N023" -and cmxs_magic_number = "Caml1999D023" + "Caml1999Z025" +and ast_impl_magic_number = "Caml1999M025" +and ast_intf_magic_number = "Caml1999N025" +and cmxs_magic_number = "Caml1999D025" (* cmxs_magic_number is duplicated in otherlibs/dynlink/natdynlink.ml *) -and cmt_magic_number = "Caml1999T024" - -let load_path = ref ([] : string list) +and cmt_magic_number = "Caml1999T025" let interface_suffix = ref ".mli" @@ -114,7 +114,7 @@ let max_tag = 245 let lazy_tag = 246 let max_young_wosize = 256 -let stack_threshold = 256 (* see byterun/config.h *) +let stack_threshold = 256 (* see runtime/caml/config.h *) let stack_safety_margin = 60 let architecture = "%%ARCH%%" @@ -150,14 +150,19 @@ let systhread_supported = %%SYSTHREAD_SUPPORT%%;; let flexdll_dirs = [%%FLEXDLL_DIR%%];; -let print_config oc = - let p name valu = Printf.fprintf oc "%s: %s\n" name valu in - let p_int name valu = Printf.fprintf oc "%s: %d\n" name valu in - let p_bool name valu = Printf.fprintf oc "%s: %B\n" name valu in +type configuration_value = + | String of string + | Int of int + | Bool of bool + +let configuration_variables = + let p x v = (x, String v) in + let p_int x v = (x, Int v) in + let p_bool x v = (x, Bool v) in +[ p "version" version; p "standard_library_default" standard_library_default; p "standard_library" standard_library; - p "standard_runtime" standard_runtime; p "ccomp_type" ccomp_type; p "c_compiler" c_compiler; p "ocamlc_cflags" ocamlc_cflags; @@ -197,8 +202,8 @@ let print_config oc = p_bool "flat_float_array" flat_float_array; p_bool "afl_instrument" afl_instrument; p_bool "windows_unicode" windows_unicode; + p_bool "supports_shared_libraries" supports_shared_libraries; - (* print the magic number *) p "exec_magic_number" exec_magic_number; p "cmi_magic_number" cmi_magic_number; p "cmo_magic_number" cmo_magic_number; @@ -209,6 +214,30 @@ let print_config oc = p "ast_intf_magic_number" ast_intf_magic_number; p "cmxs_magic_number" cmxs_magic_number; p "cmt_magic_number" cmt_magic_number; +] +let print_config_value oc = function + | String s -> + Printf.fprintf oc "%s" s + | Int n -> + Printf.fprintf oc "%d" n + | Bool p -> + Printf.fprintf oc "%B" p + +let print_config oc = + let print (x, v) = + Printf.fprintf oc "%s: %a\n" x print_config_value v in + List.iter print configuration_variables; flush oc; ;; + +let config_var x = + match List.assoc_opt x configuration_variables with + | None -> None + | Some v -> + let s = match v with + | String s -> s + | Int n -> Int.to_string n + | Bool b -> string_of_bool b + in + Some s diff --git a/utils/consistbl.mli b/utils/consistbl.mli index c532bddf..af3e7e58 100644 --- a/utils/consistbl.mli +++ b/utils/consistbl.mli @@ -13,7 +13,12 @@ (* *) (**************************************************************************) -(* Consistency tables: for checking consistency of module CRCs *) +(** Consistency tables: for checking consistency of module CRCs + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) type t diff --git a/utils/dune b/utils/dune new file mode 100644 index 00000000..e372dcf2 --- /dev/null +++ b/utils/dune @@ -0,0 +1,21 @@ +;************************************************************************** +;* * +;* OCaml * +;* * +;* Thomas Refis, Jane Street Europe * +;* * +;* Copyright 2018 Jane Street Group LLC * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU Lesser General Public License version 2.1, with the * +;* special exception on linking described in the file LICENSE. * +;* * +;************************************************************************** + +(rule + (targets config.ml) + (mode fallback) + (deps (:mk Makefile) + ../Makefile.config + config.mlp) + (action (system "make -f %{mk} %{targets}"))) diff --git a/utils/identifiable.ml b/utils/identifiable.ml index b0b706f8..e82390ad 100644 --- a/utils/identifiable.ml +++ b/utils/identifiable.ml @@ -46,7 +46,9 @@ module type Map = sig val filter_map : 'a t -> f:(key -> 'a -> 'b option) -> 'b t val of_list : (key * 'a) list -> 'a t - val disjoint_union : ?eq:('a -> 'a -> bool) -> ?print:(Format.formatter -> 'a -> unit) -> 'a t -> 'a t -> 'a t + val disjoint_union : + ?eq:('a -> 'a -> bool) -> ?print:(Format.formatter -> 'a -> unit) -> 'a t -> + 'a t -> 'a t val union_right : 'a t -> 'a t -> 'a t diff --git a/utils/identifiable.mli b/utils/identifiable.mli index 50e3ac57..4e260711 100644 --- a/utils/identifiable.mli +++ b/utils/identifiable.mli @@ -14,7 +14,12 @@ (* *) (**************************************************************************) -(** Uniform interface for common data structures over various things. *) +(** Uniform interface for common data structures over various things. + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) module type Thing = sig type t @@ -53,7 +58,9 @@ module type Map = sig (** [disjoint_union m1 m2] contains all bindings from [m1] and [m2]. If some binding is present in both and the associated value is not equal, a Fatal_error is raised *) - val disjoint_union : ?eq:('a -> 'a -> bool) -> ?print:(Format.formatter -> 'a -> unit) -> 'a t -> 'a t -> 'a t + val disjoint_union : + ?eq:('a -> 'a -> bool) -> ?print:(Format.formatter -> 'a -> unit) -> 'a t -> + 'a t -> 'a t (** [union_right m1 m2] contains all bindings from [m1] and [m2]. If some binding is present in both, the one from [m2] is taken *) diff --git a/utils/load_path.ml b/utils/load_path.ml new file mode 100644 index 00000000..d95ef079 --- /dev/null +++ b/utils/load_path.ml @@ -0,0 +1,89 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jeremie Dimino, Jane Street Europe *) +(* *) +(* Copyright 2018 Jane Street Group LLC *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +module SMap = Misc.Stdlib.String.Map + +(* Mapping from basenames to full filenames *) +type registry = string SMap.t ref + +let files : registry = ref SMap.empty +let files_uncap : registry = ref SMap.empty + +module Dir = struct + type t = { + path : string; + files : string list; + } + + let path t = t.path + let files t = t.files + + (* For backward compatibility reason, simulate the behavior of + [Misc.find_in_path]: silently ignore directories that don't exist + + treat [""] as the current directory. *) + let readdir_compat dir = + try + Sys.readdir (if dir = "" then Filename.current_dir_name else dir) + with Sys_error _ -> + [||] + + let create path = + { path; files = Array.to_list (readdir_compat path) } +end + +let dirs = ref [] + +let reset () = + files := SMap.empty; + files_uncap := SMap.empty; + dirs := [] + +let get () = !dirs +let get_paths () = List.map Dir.path !dirs + +let add dir = + let add_file base = + let fn = Filename.concat dir.Dir.path base in + files := SMap.add base fn !files; + files_uncap := SMap.add (String.uncapitalize_ascii base) fn !files_uncap; + in + List.iter add_file dir.Dir.files; + dirs := dir :: !dirs + +let remove_dir dir = + let new_dirs = List.filter (fun d -> Dir.path d <> dir) !dirs in + if new_dirs <> !dirs then begin + reset (); + List.iter add (List.rev new_dirs) + end + +let add_dir dir = add (Dir.create dir) + +let init l = + reset (); + List.iter add_dir (List.rev l) + +let is_basename fn = Filename.basename fn = fn + +let find fn = + if is_basename fn then + SMap.find fn !files + else + Misc.find_in_path (get_paths ()) fn + +let find_uncap fn = + if is_basename fn then + SMap.find (String.uncapitalize_ascii fn) !files_uncap + else + Misc.find_in_path_uncap (get_paths ()) fn diff --git a/utils/load_path.mli b/utils/load_path.mli new file mode 100644 index 00000000..433eaab7 --- /dev/null +++ b/utils/load_path.mli @@ -0,0 +1,67 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jeremie Dimino, Jane Street Europe *) +(* *) +(* Copyright 2018 Jane Street Group LLC *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(** Management of include directories. + + This module offers a high level interface to locating files in the + load path, which is constructed from [-I] command line flags and a few + other parameters. + + It makes the assumption that the contents of include directories + doesn't change during the execution of the compiler. +*) + +val add_dir : string -> unit +(** Add a directory to the load path *) + +val remove_dir : string -> unit +(** Remove a directory from the load path *) + +val reset : unit -> unit +(** Remove all directories *) + +val init : string list -> unit +(** [init l] is the same as [reset (); List.iter add_dir (List.rev l)] *) + +val get_paths : unit -> string list +(** Return the list of directories passed to [add_dir] so far, in + reverse order. *) + +val find : string -> string +(** Locate a file in the load path. Raise [Not_found] if the file + cannot be found. This function is optimized for the case where the + filename is a basename, i.e. doesn't contain a directory + separator. *) + +val find_uncap : string -> string +(** Same as [find], but search also for uncapitalized name, i.e. if + name is Foo.ml, allow /path/Foo.ml and /path/foo.ml to match. *) + +module Dir : sig + type t + (** Represent one directory in the load path. *) + + val create : string -> t + + val path : t -> string + + val files : t -> string list + (** All the files in that directory. This doesn't include files in + sub-directories of this directory. *) +end + +val add : Dir.t -> unit + +val get : unit -> Dir.t list +(** Same as [get_paths ()], except that it returns a [Dir.t list]. *) diff --git a/utils/misc.ml b/utils/misc.ml index 7878f467..f9115fe6 100644 --- a/utils/misc.ml +++ b/utils/misc.ml @@ -17,18 +17,37 @@ exception Fatal_error -let fatal_error msg = - prerr_string ">> Fatal error: "; prerr_endline msg; raise Fatal_error +let fatal_errorf fmt = + Format.kfprintf + (fun _ -> raise Fatal_error) + Format.err_formatter + ("@?>> Fatal error: " ^^ fmt ^^ "@.") -let fatal_errorf fmt = Format.kasprintf fatal_error fmt +let fatal_error msg = fatal_errorf "%s" msg (* Exceptions *) -let try_finally work cleanup = - let result = (try work () with e -> cleanup (); raise e) in - cleanup (); - result -;; +let try_finally ?(always=(fun () -> ())) ?(exceptionally=(fun () -> ())) work = + match work () with + | result -> + begin match always () with + | () -> result + | exception always_exn -> + let always_bt = Printexc.get_raw_backtrace () in + exceptionally (); + Printexc.raise_with_backtrace always_exn always_bt + end + | exception work_exn -> + let work_bt = Printexc.get_raw_backtrace () in + begin match always () with + | () -> + exceptionally (); + Printexc.raise_with_backtrace work_exn work_bt + | exception always_exn -> + let always_bt = Printexc.get_raw_backtrace () in + exceptionally (); + Printexc.raise_with_backtrace always_exn always_bt + end type ref_and_value = R : 'a ref * 'a -> ref_and_value @@ -93,16 +112,13 @@ module Stdlib = struct | (hd1 :: tl1, hd2 :: tl2) -> eq hd1 hd2 && equal eq tl1 tl2 | (_, _) -> false - let filter_map f l = - let rec aux acc l = - match l with - | [] -> List.rev acc - | h :: t -> - match f h with - | None -> aux acc t - | Some v -> aux (v :: acc) t - in - aux [] l + let rec find_map f = function + | x :: xs -> + begin match f x with + | None -> find_map f xs + | Some _ as y -> y + end + | [] -> None let map2_prefix f l1 l2 = let rec aux acc l1 l2 = @@ -139,6 +155,14 @@ module Stdlib = struct module Option = struct type 'a t = 'a option + let is_none = function + | None -> true + | Some _ -> false + + let is_some = function + | None -> false + | Some _ -> true + let equal eq o1 o2 = match o1, o2 with | None, None -> true @@ -174,6 +198,25 @@ module Stdlib = struct else loop (succ i) in loop 0 end + + module String = struct + include String + module Set = Set.Make(String) + module Map = Map.Make(String) + module Tbl = Hashtbl.Make(struct + include String + let hash = Hashtbl.hash + end) + + let for_all f t = + let len = String.length t in + let rec loop i = + i = len || (f t.[i] && loop (i + 1)) + in + loop 0 + end + + external compare : 'a -> 'a -> int = "%compare" end let may = Stdlib.Option.iter @@ -237,6 +280,15 @@ let expand_directory alt s = (String.sub s 1 (String.length s - 1)) else s +let path_separator = + match Sys.os_type with + | "Win32" -> ';' + | _ -> ':' + +let split_path_contents ?(sep = path_separator) = function + | "" -> [] + | s -> String.split_on_char sep s + (* Hashtable functions *) let create_hashtable size init = @@ -378,6 +430,11 @@ let get_ref r = let v = !r in r := []; v +let set_or_ignore f opt x = + match f x with + | None -> () + | Some y -> opt := Some y + let fst3 (x, _, _) = x let snd3 (_,x,_) = x let thd3 (_,_,x) = x @@ -416,19 +473,26 @@ module LongString = struct set dst (dstoff + i) (get src (srcoff + i)) done + let blit_string src srcoff dst dstoff len = + for i = 0 to len - 1 do + set dst (dstoff + i) (String.get src (srcoff + i)) + done + let output oc tbl pos len = for i = pos to pos + len - 1 do output_char oc (get tbl i) done - let unsafe_blit_to_bytes src srcoff dst dstoff len = - for i = 0 to len - 1 do - Bytes.unsafe_set dst (dstoff + i) (get src (srcoff + i)) - done + let input_bytes_into tbl ic len = + let count = ref len in + Array.iter (fun str -> + let chunk = min !count (Bytes.length str) in + really_input ic str 0 chunk; + count := !count - chunk) tbl let input_bytes ic len = let tbl = create len in - Array.iter (fun str -> really_input ic str 0 (Bytes.length str)) tbl; + input_bytes_into tbl ic len; tbl end @@ -495,6 +559,7 @@ let spellcheck env name = else if dist = best_dist then (head :: best_choice, dist) else acc in + let env = List.sort_uniq (fun s1 s2 -> String.compare s2 s1) env in fst (List.fold_left (compare name) ([], max_int) env) let did_you_mean ppf get_choices = @@ -516,10 +581,6 @@ let cut_at s c = let pos = String.index s c in String.sub s 0 pos, String.sub s (pos+1) (String.length s - pos - 1) - -module StringSet = Set.Make(struct type t = string let compare = compare end) -module StringMap = Map.Make(struct type t = string let compare = compare end) - (* Color handling *) module Color = struct (* use ANSI color codes, see https://en.wikipedia.org/wiki/ANSI_escape_code *) @@ -583,9 +644,9 @@ module Color = struct (* map a tag to a style, if the tag is known. @raise Not_found otherwise *) let style_of_tag s = match s with - | "error" -> (!cur_styles).error - | "warning" -> (!cur_styles).warning - | "loc" -> (!cur_styles).loc + | Format.String_tag "error" -> (!cur_styles).error + | Format.String_tag "warning" -> (!cur_styles).warning + | Format.String_tag "loc" -> (!cur_styles).loc | _ -> raise Not_found let color_enabled = ref true @@ -606,13 +667,13 @@ module Color = struct (* add color handling to formatter [ppf] *) let set_color_tag_handling ppf = let open Format in - let functions = pp_get_formatter_tag_functions ppf () in + let functions = pp_get_formatter_stag_functions ppf () in let functions' = {functions with - mark_open_tag=(mark_open_tag ~or_else:functions.mark_open_tag); - mark_close_tag=(mark_close_tag ~or_else:functions.mark_close_tag); + mark_open_stag=(mark_open_tag ~or_else:functions.mark_open_stag); + mark_close_stag=(mark_close_tag ~or_else:functions.mark_close_stag); } in pp_set_mark_tags ppf true; (* enable tags *) - pp_set_formatter_tag_functions ppf functions'; + pp_set_formatter_stag_functions ppf functions'; (* also setup margins *) pp_set_margin ppf (pp_get_margin std_formatter()); () @@ -647,6 +708,12 @@ module Color = struct () end +module Error_style = struct + type setting = + | Contextual + | Short +end + let normalise_eol s = let b = Buffer.create 80 in for i = 0 to String.length s - 1 do @@ -686,6 +753,27 @@ let delete_eol_spaces src = let stop = loop 0 0 in Bytes.sub_string dst 0 stop +let pp_two_columns ?(sep = "|") ?max_lines ppf (lines: (string * string) list) = + let left_column_size = + List.fold_left (fun acc (s, _) -> max acc (String.length s)) 0 lines in + let lines_nb = List.length lines in + let ellipsed_first, ellipsed_last = + match max_lines with + | Some max_lines when lines_nb > max_lines -> + let printed_lines = max_lines - 1 in (* the ellipsis uses one line *) + let lines_before = printed_lines / 2 + printed_lines mod 2 in + let lines_after = printed_lines / 2 in + (lines_before, lines_nb - lines_after - 1) + | _ -> (-1, -1) + in + Format.fprintf ppf "@["; + List.iteri (fun k (line_l, line_r) -> + if k = ellipsed_first then Format.fprintf ppf "...@,"; + if ellipsed_first <= k && k <= ellipsed_last then () + else Format.fprintf ppf "%*s %s %s@," left_column_size line_l sep line_r + ) lines; + Format.fprintf ppf "@]" + type hook_info = { sourcefile : string; } @@ -732,3 +820,63 @@ module MakeHooks(M: sig let apply_hooks sourcefile intf = fold_hooks !hooks sourcefile intf end + +(* showing configuration and configuration variables *) +let show_config_and_exit () = + Config.print_config stdout; + exit 0 + +let show_config_variable_and_exit x = + match Config.config_var x with + | Some v -> + (* we intentionally don't print a newline to avoid Windows \r + issues: bash only strips the trailing \n when using a command + substitution $(ocamlc -config-var foo), so a trailing \r would + remain if printing a newline under Windows and scripts would + have to use $(ocamlc -config-var foo | tr -d '\r') + for portability. Ugh. *) + print_string v; + exit 0 + | None -> + exit 2 + +let get_build_path_prefix_map = + let init = ref false in + let map_cache = ref None in + fun () -> + if not !init then begin + init := true; + match Sys.getenv "BUILD_PATH_PREFIX_MAP" with + | exception Not_found -> () + | encoded_map -> + match Build_path_prefix_map.decode_map encoded_map with + | Error err -> + fatal_errorf + "Invalid value for the environment variable \ + BUILD_PATH_PREFIX_MAP: %s" err + | Ok map -> map_cache := Some map + end; + !map_cache + +let debug_prefix_map_flags () = + if not Config.as_has_debug_prefix_map then + [] + else begin + match get_build_path_prefix_map () with + | None -> [] + | Some map -> + List.fold_right + (fun map_elem acc -> + match map_elem with + | None -> acc + | Some { Build_path_prefix_map.target; source; } -> + (Printf.sprintf "--debug-prefix-map %s=%s" + (Filename.quote source) + (Filename.quote target)) :: acc) + map + [] + end + +let print_if ppf flag printer arg = + if !flag then Format.fprintf ppf "%a@." printer arg; + arg diff --git a/utils/misc.mli b/utils/misc.mli index 7b918440..7005dcfb 100644 --- a/utils/misc.mli +++ b/utils/misc.mli @@ -13,13 +13,52 @@ (* *) (**************************************************************************) -(* Miscellaneous useful types and functions *) +(** Miscellaneous useful types and functions + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) val fatal_error: string -> 'a val fatal_errorf: ('a, Format.formatter, unit, 'b) format4 -> 'a exception Fatal_error -val try_finally : (unit -> 'a) -> (unit -> unit) -> 'a;; +val try_finally : + ?always:(unit -> unit) -> + ?exceptionally:(unit -> unit) -> + (unit -> 'a) -> 'a +(** [try_finally work ~always ~exceptionally] is designed to run code + in [work] that may fail with an exception, and has two kind of + cleanup routines: [always], that must be run after any execution + of the function (typically, freeing system resources), and + [exceptionally], that should be run only if [work] or [always] + failed with an exception (typically, undoing user-visible state + changes that would only make sense if the function completes + correctly). For example: + + {[ + let objfile = outputprefix ^ ".cmo" in + let oc = open_out_bin objfile in + Misc.try_finally + (fun () -> + bytecode + ++ Timings.(accumulate_time (Generate sourcefile)) + (Emitcode.to_file oc modulename objfile); + Warnings.check_fatal ()) + ~always:(fun () -> close_out oc) + ~exceptionally:(fun _exn -> remove_file objfile); + ]} + + If [exceptionally] fail with an exception, it is propagated as + usual. + + If [always] or [exceptionally] use exceptions internally for + control-flow but do not raise, then [try_finally] is careful to + preserve any exception backtrace coming from [work] or [always] + for easier debugging. +*) + val map_end: ('a -> 'b) -> 'a list -> 'b list -> 'b list (* [map_end f l t] is [map f l @ t], just more efficient. *) @@ -59,10 +98,9 @@ module Stdlib : sig (** Returns [true] iff the given lists have the same length and content with respect to the given equality function. *) - val filter_map : ('a -> 'b option) -> 'a t -> 'b t - (** [filter_map f l] applies [f] to every element of [l], filters - out the [None] elements and returns the list of the arguments of - the [Some] elements. *) + val find_map : ('a -> 'b option) -> 'a t -> 'b option + (** [find_map f l] returns the first evaluation of [f] that returns [Some], + or returns None if there is no such element. *) val some_if_all_elements_are_some : 'a option t -> 'a t option (** If all elements of the given list are [Some _] then [Some xs] @@ -83,6 +121,9 @@ module Stdlib : sig module Option : sig type 'a t = 'a option + val is_none : 'a t -> bool + val is_some : 'a t -> bool + val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool val iter : ('a -> unit) -> 'a t -> unit @@ -97,6 +138,17 @@ module Stdlib : sig Invalid_argument if the two arrays are determined to have different lengths. *) end + + module String : sig + include module type of String + module Set : Set.S with type elt = string + module Map : Map.S with type key = string + module Tbl : Hashtbl.S with type key = string + + val for_all : (char -> bool) -> t -> bool + end + + external compare : 'a -> 'a -> int = "%compare" end val find_in_path: string list -> string -> string @@ -113,6 +165,13 @@ val expand_directory: string -> string -> string (* [expand_directory alt file] eventually expands a [+] at the beginning of file into [alt] (an alternate root directory) *) +val split_path_contents: ?sep:char -> string -> string list +(* [split_path_contents ?sep s] interprets [s] as the value of a "PATH"-like + variable and returns the corresponding list of directories. [s] is split + using the platform-specific delimiter, or [~sep] if it is passed. + + Returns the empty list if [s] is empty. *) + val create_hashtable: int -> ('a * 'b) list -> ('a, 'b) Hashtbl.t (* Create a hashtable of the given size and fills it with the given bindings. *) @@ -188,6 +247,9 @@ val get_ref: 'a list ref -> 'a list (* [get_ref lr] returns the content of the list reference [lr] and reset its content to the empty list. *) +val set_or_ignore : ('a -> 'b option) -> 'b option ref -> 'a -> unit + (* [set_or_ignore f opt x] sets [opt] to [f x] if it returns [Some _], + or leaves it unmodified if it returns [None]. *) val fst3: 'a * 'b * 'c -> 'a val snd3: 'a * 'b * 'c -> 'b @@ -206,8 +268,9 @@ module LongString : val get : t -> int -> char val set : t -> int -> char -> unit val blit : t -> int -> t -> int -> int -> unit + val blit_string : string -> int -> t -> int -> int -> unit val output : out_channel -> t -> int -> int -> unit - val unsafe_blit_to_bytes : t -> int -> bytes -> int -> int -> unit + val input_bytes_into : t -> in_channel -> int -> unit val input_bytes : in_channel -> int -> t end @@ -253,12 +316,6 @@ val cut_at : string -> char -> string * string @since 4.01 *) - -module StringSet: Set.S with type elt = string -module StringMap: Map.S with type key = string -(* TODO: replace all custom instantiations of StringSet/StringMap in various - compiler modules with this one. *) - (* Color handling *) module Color : sig type color = @@ -302,6 +359,13 @@ module Color : sig (* adds functions to support color tags to the given formatter. *) end +(* See the -error-style option *) +module Error_style : sig + type setting = + | Contextual + | Short +end + val normalise_eol : string -> string (** [normalise_eol s] returns a fresh copy of [s] with any '\r' characters removed. Intended for pre-processing text which will subsequently be printed @@ -312,7 +376,31 @@ val delete_eol_spaces : string -> string line spaces removed. Intended to normalize the output of the toplevel for tests. *) - +val pp_two_columns : + ?sep:string -> ?max_lines:int -> + Format.formatter -> (string * string) list -> unit +(** [pp_two_columns ?sep ?max_lines ppf l] prints the lines in [l] as two + columns separated by [sep] ("|" by default). [max_lines] can be used to + indicate a maximum number of lines to print -- an ellipsis gets inserted at + the middle if the input has too many lines. + + Example: + + {v pp_two_columns ~max_lines:3 Format.std_formatter [ + "abc", "hello"; + "def", "zzz"; + "a" , "bllbl"; + "bb" , "dddddd"; + ] v} + + prints + + {v + abc | hello + ... + bb | dddddd + v} +*) (** {1 Hook machinery} @@ -347,3 +435,20 @@ module type HookSig = sig end module MakeHooks : functor (M : sig type t end) -> HookSig with type t = M.t + + +(** configuration variables *) +val show_config_and_exit : unit -> unit +val show_config_variable_and_exit : string -> unit + +val get_build_path_prefix_map: unit -> Build_path_prefix_map.map option +(** Returns the map encoded in the [BUILD_PATH_PREFIX_MAP] environment + variable. *) + +val debug_prefix_map_flags: unit -> string list +(** Returns the list of [--debug-prefix-map] flags to be passed to the + assembler, built from the [BUILD_PATH_PREFIX_MAP] environment variable. *) + +val print_if : + Format.formatter -> bool ref -> (Format.formatter -> 'a -> unit) -> 'a -> 'a +(** [print_if ppf flag fmt x] prints [x] with [fmt] on [ppf] if [b] is true. *) diff --git a/utils/numbers.ml b/utils/numbers.ml index 3e361e66..18006a5b 100644 --- a/utils/numbers.ml +++ b/utils/numbers.ml @@ -77,7 +77,7 @@ module Float = struct include Identifiable.Make (struct type t = float - let compare x y = Pervasives.compare x y + let compare x y = Stdlib.compare x y let output oc x = Printf.fprintf oc "%f" x let hash f = Hashtbl.hash f let equal (i : float) j = i = j diff --git a/utils/numbers.mli b/utils/numbers.mli index 4d5e285f..f9c49ef6 100644 --- a/utils/numbers.mli +++ b/utils/numbers.mli @@ -14,7 +14,12 @@ (* *) (**************************************************************************) -(** Modules about numbers, some of which satisfy {!Identifiable.S}. *) +(** Modules about numbers, some of which satisfy {!Identifiable.S}. + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) module Int : sig include Identifiable.S with type t = int diff --git a/utils/profile.ml b/utils/profile.ml index 59d67a12..02e3a16d 100644 --- a/utils/profile.ml +++ b/utils/profile.ml @@ -90,12 +90,12 @@ let record_call ?(accumulate = false) name f = in hierarchy := E this_table; Misc.try_finally f - (fun () -> - hierarchy := E prev_hierarchy; - let end_measure = Measure.create () in - let measure_diff = - Measure_diff.accumulate this_measure_diff start_measure end_measure in - Hashtbl.add prev_hierarchy name (measure_diff, E this_table)) + ~always:(fun () -> + hierarchy := E prev_hierarchy; + let end_measure = Measure.create () in + let measure_diff = + Measure_diff.accumulate this_measure_diff start_measure end_measure in + Hashtbl.add prev_hierarchy name (measure_diff, E this_table)) let record ?accumulate pass f x = record_call ?accumulate pass (fun () -> f x) @@ -310,7 +310,8 @@ let print ppf columns = | None -> Measure.zero in let total = Measure_diff.of_diff Measure.zero (Measure.create ()) in - display_rows ppf (rows_of_hierarchy !hierarchy total initial_measure columns) + display_rows ppf + (rows_of_hierarchy !hierarchy total initial_measure columns) let column_mapping = [ "time", `Time; diff --git a/utils/profile.mli b/utils/profile.mli index 83a82524..7eff6957 100644 --- a/utils/profile.mli +++ b/utils/profile.mli @@ -13,7 +13,12 @@ (* *) (**************************************************************************) -(** Compiler performance recording *) +(** Compiler performance recording + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) type file = string diff --git a/utils/strongly_connected_components.mli b/utils/strongly_connected_components.mli index 59af9eec..e7009527 100644 --- a/utils/strongly_connected_components.mli +++ b/utils/strongly_connected_components.mli @@ -14,7 +14,12 @@ (* *) (**************************************************************************) -(** Kosaraju's algorithm for strongly connected components. *) +(** Kosaraju's algorithm for strongly connected components. + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) module type S = sig module Id : Identifiable.S diff --git a/utils/targetint.ml b/utils/targetint.ml index 78405a36..9d15a2ff 100644 --- a/utils/targetint.ml +++ b/utils/targetint.ml @@ -28,7 +28,9 @@ module type S = sig val sub : t -> t -> t val mul : t -> t -> t val div : t -> t -> t + val unsigned_div : t -> t -> t val rem : t -> t -> t + val unsigned_rem : t -> t -> t val succ : t -> t val pred : t -> t val abs : t -> t @@ -53,8 +55,10 @@ module type S = sig val of_string : string -> t val to_string : t -> string val compare: t -> t -> int + val unsigned_compare : t -> t -> int val equal: t -> t -> bool val repr: t -> repr + val print : Format.formatter -> t -> unit end let size = Sys.word_size @@ -80,6 +84,7 @@ module Int32 = struct let of_int64 = Int64.to_int32 let to_int64 = Int64.of_int32 let repr x = Int32 x + let print ppf t = Format.fprintf ppf "%ld" t end module Int64 = struct @@ -88,6 +93,7 @@ module Int64 = struct let of_int64 x = x let to_int64 x = x let repr x = Int64 x + let print ppf t = Format.fprintf ppf "%Ld" t end include (val diff --git a/utils/targetint.mli b/utils/targetint.mli index 788d690f..72d464d2 100644 --- a/utils/targetint.mli +++ b/utils/targetint.mli @@ -23,6 +23,10 @@ pointer type in the C compiler. All arithmetic operations over are taken modulo 2{^32} or 2{^64} depending on the word size of the target architecture. + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + *) type t @@ -52,7 +56,11 @@ val mul : t -> t -> t val div : t -> t -> t (** Integer division. Raise [Division_by_zero] if the second argument is zero. This division rounds the real quotient of - its arguments towards zero, as specified for {!Pervasives.(/)}. *) + its arguments towards zero, as specified for {!Stdlib.(/)}. *) + +val unsigned_div : t -> t -> t +(** Same as {!div}, except that arguments and result are interpreted as {e + unsigned} integers. *) val rem : t -> t -> t (** Integer remainder. If [y] is not zero, the result @@ -62,6 +70,10 @@ val rem : t -> t -> t (Targetint.rem x y)]. If [y = 0], [Targetint.rem x y] raises [Division_by_zero]. *) +val unsigned_rem : t -> t -> t +(** Same as {!rem}, except that arguments and result are interpreted as {e + unsigned} integers. *) + val succ : t -> t (** Successor. [Targetint.succ x] is [Targetint.add x Targetint.one]. *) @@ -173,10 +185,14 @@ val to_string : t -> string val compare: t -> t -> int (** The comparison function for target integers, with the same specification as - {!Pervasives.compare}. Along with the type [t], this function [compare] + {!Stdlib.compare}. Along with the type [t], this function [compare] allows the module [Targetint] to be passed as argument to the functors {!Set.Make} and {!Map.Make}. *) +val unsigned_compare: t -> t -> int +(** Same as {!compare}, except that arguments are interpreted as {e unsigned} + integers. *) + val equal: t -> t -> bool (** The equal function for target ints. *) @@ -186,3 +202,6 @@ type repr = val repr : t -> repr (** The concrete representation of a native integer. *) + +val print : Format.formatter -> t -> unit +(** Print a target integer to a formatter. *) diff --git a/utils/tbl.ml b/utils/tbl.ml deleted file mode 100644 index fa278b43..00000000 --- a/utils/tbl.ml +++ /dev/null @@ -1,123 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -type ('k, 'v) t = - Empty - | Node of ('k, 'v) t * 'k * 'v * ('k, 'v) t * int - -let empty = Empty - -let height = function - Empty -> 0 - | Node(_,_,_,_,h) -> h - -let create l x d r = - let hl = height l and hr = height r in - Node(l, x, d, r, (if hl >= hr then hl + 1 else hr + 1)) - -let bal l x d r = - let hl = height l and hr = height r in - if hl > hr + 1 then - match l with - | Node (ll, lv, ld, lr, _) when height ll >= height lr -> - create ll lv ld (create lr x d r) - | Node (ll, lv, ld, Node (lrl, lrv, lrd, lrr, _), _) -> - create (create ll lv ld lrl) lrv lrd (create lrr x d r) - | _ -> assert false - else if hr > hl + 1 then - match r with - | Node (rl, rv, rd, rr, _) when height rr >= height rl -> - create (create l x d rl) rv rd rr - | Node (Node (rll, rlv, rld, rlr, _), rv, rd, rr, _) -> - create (create l x d rll) rlv rld (create rlr rv rd rr) - | _ -> assert false - else - create l x d r - -let rec add x data = function - Empty -> - Node(Empty, x, data, Empty, 1) - | Node(l, v, d, r, h) -> - let c = compare x v in - if c = 0 then - Node(l, x, data, r, h) - else if c < 0 then - bal (add x data l) v d r - else - bal l v d (add x data r) - -let rec find x = function - Empty -> - raise Not_found - | Node(l, v, d, r, _) -> - let c = compare x v in - if c = 0 then d - else find x (if c < 0 then l else r) - -let rec find_str (x : string) = function - Empty -> - raise Not_found - | Node(l, v, d, r, _) -> - let c = compare x v in - if c = 0 then d - else find_str x (if c < 0 then l else r) - -let rec mem x = function - Empty -> false - | Node(l, v, _d, r, _) -> - let c = compare x v in - c = 0 || mem x (if c < 0 then l else r) - -let rec merge t1 t2 = - match (t1, t2) with - (Empty, t) -> t - | (t, Empty) -> t - | (Node(l1, v1, d1, r1, _h1), Node(l2, v2, d2, r2, _h2)) -> - bal l1 v1 d1 (bal (merge r1 l2) v2 d2 r2) - -let rec remove x = function - Empty -> - Empty - | Node(l, v, d, r, _h) -> - let c = compare x v in - if c = 0 then - merge l r - else if c < 0 then - bal (remove x l) v d r - else - bal l v d (remove x r) - -let rec iter f = function - Empty -> () - | Node(l, v, d, r, _) -> - iter f l; f v d; iter f r - -let rec map f = function - Empty -> Empty - | Node(l, v, d, r, h) -> Node(map f l, v, f v d, map f r, h) - -let rec fold f m accu = - match m with - | Empty -> accu - | Node(l, v, d, r, _) -> - fold f r (f v d (fold f l accu)) - -open Format - -let print print_key print_data ppf tbl = - let print_tbl ppf tbl = - iter (fun k d -> fprintf ppf "@[<2>%a ->@ %a;@]@ " print_key k print_data d) - tbl in - fprintf ppf "@[[[%a]]@]" print_tbl tbl diff --git a/utils/tbl.mli b/utils/tbl.mli deleted file mode 100644 index d23b959c..00000000 --- a/utils/tbl.mli +++ /dev/null @@ -1,34 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - -(* Association tables from any ordered type to any type. - We use the generic ordering to compare keys. *) - -type ('k, 'v) t - -val empty: ('k, 'v) t -val add: 'k -> 'v -> ('k, 'v) t -> ('k, 'v) t -val find: 'k -> ('k, 'v) t -> 'v -val find_str: string -> (string, 'v) t -> 'v -val mem: 'k -> ('k, 'v) t -> bool -val remove: 'k -> ('k, 'v) t -> ('k, 'v) t -val iter: ('k -> 'v -> unit) -> ('k, 'v) t -> unit -val map: ('k -> 'v1 -> 'v2) -> ('k, 'v1) t -> ('k, 'v2) t -val fold: ('k -> 'v -> 'acc -> 'acc) -> ('k, 'v) t -> 'acc -> 'acc - -open Format - -val print: (formatter -> 'k -> unit) -> (formatter -> 'v -> unit) -> - formatter -> ('k, 'v) t -> unit diff --git a/utils/terminfo.ml b/utils/terminfo.ml index 03e882f4..1b4a3578 100644 --- a/utils/terminfo.ml +++ b/utils/terminfo.ml @@ -23,7 +23,7 @@ type status = | Bad_term | Good_term -let setup oc = +let setup oc = let term = try Sys.getenv "TERM" with Not_found -> "" in (* Same heuristics as in Misc.Color.should_enable_color *) if term <> "" && term <> "dumb" && isatty oc diff --git a/utils/terminfo.mli b/utils/terminfo.mli index f70f224d..10f5f545 100644 --- a/utils/terminfo.mli +++ b/utils/terminfo.mli @@ -13,7 +13,12 @@ (* *) (**************************************************************************) -(* Basic interface to the terminfo database *) +(** Basic interface to the terminfo database + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) type status = | Uninitialised diff --git a/utils/warnings.ml b/utils/warnings.ml index 46142677..c5044a3e 100644 --- a/utils/warnings.ml +++ b/utils/warnings.ml @@ -13,11 +13,9 @@ (* *) (**************************************************************************) -(* When you change this, you need to update the documentation: +(* When you change this, you need to update: + - the list 'description' at the bottom of this file - man/ocamlc.m - - man/ocamlopt.m - - manual/manual/cmds/comp.etex - - manual/manual/cmds/native.etex *) type loc = { @@ -29,7 +27,7 @@ type loc = { type t = | Comment_start (* 1 *) | Comment_not_end (* 2 *) - | Deprecated of string * loc * loc (* 3 *) +(*| Deprecated --> alert "deprecated" *) (* 3 *) | Fragile_match of string (* 4 *) | Partial_application (* 5 *) | Labels_omitted of string list (* 6 *) @@ -67,7 +65,7 @@ type t = | Unused_extension of string * bool * bool * bool (* 38 *) | Unused_rec_flag (* 39 *) | Name_out_of_scope of string * string list * bool (* 40 *) - | Ambiguous_name of string list * string list * bool (* 41 *) + | Ambiguous_name of string list * string list * bool * string (* 41 *) | Disambiguated_name of string (* 42 *) | Nonoptional_label of string (* 43 *) | Open_shadow_identifier of string * string (* 44 *) @@ -89,6 +87,10 @@ type t = | Unused_module of string (* 60 *) | Unboxable_type_in_prim_decl of string (* 61 *) | Constraint_on_gadt (* 62 *) + | Erroneous_printed_signature of string (* 63 *) + | Unsafe_without_parsing (* 64 *) + | Redefining_unit of string (* 65 *) + | Unused_open_bang of string (* 66 *) ;; (* If you remove a warning, leave a hole in the numbering. NEVER change @@ -97,10 +99,12 @@ type t = do NOT reuse one of the holes. *) +type alert = {kind:string; message:string; def:loc; use:loc} + + let number = function | Comment_start -> 1 | Comment_not_end -> 2 - | Deprecated _ -> 3 | Fragile_match _ -> 4 | Partial_application -> 5 | Labels_omitted _ -> 6 @@ -160,9 +164,13 @@ let number = function | Unused_module _ -> 60 | Unboxable_type_in_prim_decl _ -> 61 | Constraint_on_gadt -> 62 + | Erroneous_printed_signature _ -> 63 + | Unsafe_without_parsing -> 64 + | Redefining_unit _ -> 65 + | Unused_open_bang _ -> 66 ;; -let last_warning_number = 62 +let last_warning_number = 66 ;; (* Must be the max number returned by the [number] function. *) @@ -203,6 +211,8 @@ type state = { active: bool array; error: bool array; + alerts: (Misc.Stdlib.String.Set.t * bool); (* false:set complement *) + alert_errors: (Misc.Stdlib.String.Set.t * bool); (* false:set complement *) } let current = @@ -210,6 +220,8 @@ let current = { active = Array.make (last_warning_number + 1) true; error = Array.make (last_warning_number + 1) false; + alerts = (Misc.Stdlib.String.Set.empty, false); (* all enabled *) + alert_errors = (Misc.Stdlib.String.Set.empty, true); (* all soft *) } let disabled = ref false @@ -221,8 +233,21 @@ let backup () = !current let restore x = current := x -let is_active x = not !disabled && (!current).active.(number x);; -let is_error x = not !disabled && (!current).error.(number x);; +let is_active x = + not !disabled && (!current).active.(number x) + +let is_error x = + not !disabled && (!current).error.(number x) + +let alert_is_active {kind; _} = + not !disabled && + let (set, pos) = (!current).alerts in + Misc.Stdlib.String.Set.mem kind set = pos + +let alert_is_error {kind; _} = + not !disabled && + let (set, pos) = (!current).alert_errors in + Misc.Stdlib.String.Set.mem kind set = pos let mk_lazy f = let state = backup () in @@ -239,10 +264,79 @@ let mk_lazy f = raise exn ) -let parse_opt error active flags s = - let set i = flags.(i) <- true in - let clear i = flags.(i) <- false in - let set_all i = active.(i) <- true; error.(i) <- true in +let set_alert ~error ~enable s = + let upd = + match s with + | "all" -> + (Misc.Stdlib.String.Set.empty, not enable) + | s -> + let (set, pos) = + if error then (!current).alert_errors else (!current).alerts + in + let f = + if enable = pos + then Misc.Stdlib.String.Set.add + else Misc.Stdlib.String.Set.remove + in + (f s set, pos) + in + if error then + current := {(!current) with alert_errors=upd} + else + current := {(!current) with alerts=upd} + +let parse_alert_option s = + let n = String.length s in + let id_char = function + | 'a'..'z' | 'A'..'Z' | '_' | '\'' | '0'..'9' -> true + | _ -> false + in + let rec parse_id i = + if i < n && id_char s.[i] then parse_id (i + 1) else i + in + let rec scan i = + if i = n then () + else if i + 1 = n then raise (Arg.Bad "Ill-formed list of alert settings") + else match s.[i], s.[i+1] with + | '+', '+' -> id (set_alert ~error:true ~enable:true) (i + 2) + | '+', _ -> id (set_alert ~error:false ~enable:true) (i + 1) + | '-', '-' -> id (set_alert ~error:true ~enable:false) (i + 2) + | '-', _ -> id (set_alert ~error:false ~enable:false) (i + 1) + | '@', _ -> + id (fun s -> + set_alert ~error:true ~enable:true s; + set_alert ~error:false ~enable:true s) + (i + 1) + | _ -> raise (Arg.Bad "Ill-formed list of alert settings") + and id f i = + let j = parse_id i in + if j = i then raise (Arg.Bad "Ill-formed list of alert settings"); + let id = String.sub s i (j - i) in + f id; + scan j + in + scan 0 + +let parse_opt error active errflag s = + let flags = if errflag then error else active in + let set i = + if i = 3 then set_alert ~error:errflag ~enable:true "deprecated" + else flags.(i) <- true + in + let clear i = + if i = 3 then set_alert ~error:errflag ~enable:false "deprecated" + else flags.(i) <- false + in + let set_all i = + if i = 3 then begin + set_alert ~error:false ~enable:true "deprecated"; + set_alert ~error:true ~enable:true "deprecated" + end + else begin + active.(i) <- true; + error.(i) <- true + end + in let error () = raise (Arg.Bad "Ill-formed list of warnings") in let rec get_num n i = if i >= String.length s then i, n @@ -293,11 +387,11 @@ let parse_opt error active flags s = let parse_options errflag s = let error = Array.copy (!current).error in let active = Array.copy (!current).active in - parse_opt error active (if errflag then error else active) s; - current := {error; active} + parse_opt error active errflag s; + current := {(!current) with error; active} (* If you change these, don't forget to change them in man/ocamlc.m *) -let defaults_w = "+a-4-6-7-9-27-29-32..42-44-45-48-50-60";; +let defaults_w = "+a-4-6-7-9-27-29-32..42-44-45-48-50-60-66";; let defaults_warn_error = "-a+31";; let () = parse_options false defaults_w;; @@ -314,14 +408,6 @@ let message = function "this `(*' is the start of a comment.\n\ Hint: Did you forget spaces when writing the infix operator `( * )'?" | Comment_not_end -> "this is not the end of a comment." - | Deprecated (s, _, _) -> - (* Reduce \r\n to \n: - - Prevents any \r characters being printed on Unix when processing - Windows sources - - Prevents \r\r\n being generated on Windows, which affects the - testsuite - *) - "deprecated: " ^ Misc.normalise_eol s | Fragile_match "" -> "this pattern-matching is fragile." | Fragile_match s -> @@ -397,6 +483,7 @@ let message = function file1 file2 modname | Unused_value_declaration v -> "unused value " ^ v ^ "." | Unused_open s -> "unused open " ^ s ^ "." + | Unused_open_bang s -> "unused open! " ^ s ^ "." | Unused_type_declaration s -> "unused type " ^ s ^ "." | Unused_for_index s -> "unused for-loop index " ^ s ^ "." | Unused_ancestor s -> "unused ancestor variable " ^ s ^ "." @@ -436,14 +523,16 @@ let message = function not visible in the current scope: " ^ String.concat " " slist ^ ".\n\ They will not be selected if the type becomes unknown." - | Ambiguous_name ([s], tl, false) -> + | Ambiguous_name ([s], tl, false, expansion) -> s ^ " belongs to several types: " ^ String.concat " " tl ^ "\nThe first one was selected. Please disambiguate if this is wrong." - | Ambiguous_name (_, _, false) -> assert false - | Ambiguous_name (_slist, tl, true) -> + ^ expansion + | Ambiguous_name (_, _, false, _ ) -> assert false + | Ambiguous_name (_slist, tl, true, expansion) -> "these field labels belong to several types: " ^ String.concat " " tl ^ "\nThe first one was selected. Please disambiguate if this is wrong." + ^ expansion | Disambiguated_name s -> "this use of " ^ s ^ " relies on type-directed disambiguation,\n\ it will not compile with OCaml 4.00 or earlier." @@ -521,20 +610,26 @@ let message = function or [@@unboxed]." t t | Constraint_on_gadt -> "Type constraints do not apply to GADT cases of variant types." + | Erroneous_printed_signature s -> + "The printed interface differs from the inferred interface.\n\ + The inferred interface contained items which could not be printed\n\ + properly due to name collisions between identifiers." + ^ s + ^ "\nBeware that this warning is purely informational and will not catch\n\ + all instances of erroneous printed interface." + | Unsafe_without_parsing -> + "option -unsafe used with a preprocessor returning a syntax tree" + | Redefining_unit name -> + Printf.sprintf + "This type declaration is defining a new '()' constructor\n\ + which shadows the existing one.\n\ + Hint: Did you mean 'type %s = unit'?" name ;; -let sub_locs = function - | Deprecated (_, def, use) -> - [ - def, "Definition"; - use, "Expected signature"; - ] - | _ -> [] - let nerrors = ref 0;; type reporting_information = - { number : int + { id : string ; message : string ; is_error : bool ; sub_locs : (loc * string) list; @@ -545,10 +640,42 @@ let report w = | false -> `Inactive | true -> if is_error w then incr nerrors; - `Active { number = number w; message = message w; is_error = is_error w; - sub_locs = sub_locs w; - } -;; + `Active + { id = string_of_int (number w); + message = message w; + is_error = is_error w; + sub_locs = []; + } + +let report_alert (alert : alert) = + match alert_is_active alert with + | false -> `Inactive + | true -> + let is_error = alert_is_error alert in + if is_error then incr nerrors; + let message = Misc.normalise_eol alert.message in + (* Reduce \r\n to \n: + - Prevents any \r characters being printed on Unix when processing + Windows sources + - Prevents \r\r\n being generated on Windows, which affects the + testsuite + *) + let sub_locs = + if not alert.def.loc_ghost && not alert.use.loc_ghost then + [ + alert.def, "Definition"; + alert.use, "Expected signature"; + ] + else + [] + in + `Active + { + id = alert.kind; + message; + is_error; + sub_locs; + } exception Errors;; @@ -566,7 +693,7 @@ let descriptions = [ 1, "Suspicious-looking start-of-comment mark."; 2, "Suspicious-looking end-of-comment mark."; - 3, "Deprecated feature."; + 3, "Deprecated synonym for the 'deprecated' alert"; 4, "Fragile pattern matching: matching that will remain complete even\n\ \ if additional constructors are added to one of the variant types\n\ \ matched."; @@ -636,7 +763,11 @@ let descriptions = 59, "Assignment to non-mutable value"; 60, "Unused module declaration"; 61, "Unboxable type in primitive declaration"; - 62, "Type constraint on GADT type declaration" + 62, "Type constraint on GADT type declaration"; + 63, "Erroneous printed signature"; + 64, "-unsafe used with a preprocessor returning a syntax tree"; + 65, "Type declaration defining a new '()' constructor"; + 66, "Unused open! statement"; ] ;; @@ -652,7 +783,7 @@ let help_warnings () = | l -> Printf.printf " %c warnings %s.\n" (Char.uppercase_ascii c) - (String.concat ", " (List.map string_of_int l)) + (String.concat ", " (List.map Int.to_string l)) done; exit 0 ;; diff --git a/utils/warnings.mli b/utils/warnings.mli index 1171f8b3..4fe4964f 100644 --- a/utils/warnings.mli +++ b/utils/warnings.mli @@ -13,6 +13,13 @@ (* *) (**************************************************************************) +(** Warning definitions + + {b Warning:} this module is unstable and part of + {{!Compiler_libs}compiler-libs}. + +*) + type loc = { loc_start: Lexing.position; loc_end: Lexing.position; @@ -22,7 +29,7 @@ type loc = { type t = | Comment_start (* 1 *) | Comment_not_end (* 2 *) - | Deprecated of string * loc * loc (* 3 *) +(*| Deprecated --> alert "deprecated" *) (* 3 *) | Fragile_match of string (* 4 *) | Partial_application (* 5 *) | Labels_omitted of string list (* 6 *) @@ -60,7 +67,7 @@ type t = | Unused_extension of string * bool * bool * bool (* 38 *) | Unused_rec_flag (* 39 *) | Name_out_of_scope of string * string list * bool (* 40 *) - | Ambiguous_name of string list * string list * bool (* 41 *) + | Ambiguous_name of string list * string list * bool * string (* 41 *) | Disambiguated_name of string (* 42 *) | Nonoptional_label of string (* 43 *) | Open_shadow_identifier of string * string (* 44 *) @@ -82,11 +89,24 @@ type t = | Unused_module of string (* 60 *) | Unboxable_type_in_prim_decl of string (* 61 *) | Constraint_on_gadt (* 62 *) + | Erroneous_printed_signature of string (* 63 *) + | Unsafe_without_parsing (* 64 *) + | Redefining_unit of string (* 65 *) + | Unused_open_bang of string (* 66 *) ;; +type alert = {kind:string; message:string; def:loc; use:loc} + val parse_options : bool -> string -> unit;; +val parse_alert_option: string -> unit + (** Disable/enable alerts based on the parameter to the -alert + command-line option. Raises [Arg.Bad] if the string is not a + valid specification. + *) + val without_warnings : (unit -> 'a) -> 'a + (** Run the thunk with all warnings and alerts disabled. *) val is_active : t -> bool;; val is_error : t -> bool;; @@ -95,13 +115,14 @@ val defaults_w : string;; val defaults_warn_error : string;; type reporting_information = - { number : int + { id : string ; message : string ; is_error : bool ; sub_locs : (loc * string) list; } val report : t -> [ `Active of reporting_information | `Inactive ] +val report_alert : alert -> [ `Active of reporting_information | `Inactive ] exception Errors;; @@ -115,4 +136,4 @@ val backup: unit -> state val restore: state -> unit val mk_lazy: (unit -> 'a) -> 'a Lazy.t (** Like [Lazy.of_fun], but the function is applied with - the warning settings at the time [mk_lazy] is called. *) + the warning/alert settings at the time [mk_lazy] is called. *) diff --git a/yacc/Makefile b/yacc/Makefile index 8d3b0870..d4a0c8cc 100644 --- a/yacc/Makefile +++ b/yacc/Makefile @@ -15,11 +15,19 @@ # Makefile for the parser generator. -include ../config/Makefile +ROOTDIR = .. -OBJS= closure.$(O) error.$(O) lalr.$(O) lr0.$(O) main.$(O) \ - mkpar.$(O) output.$(O) reader.$(O) \ - skeleton.$(O) symtab.$(O) verbose.$(O) warshall.$(O) +include $(ROOTDIR)/Makefile.config + +OC_CPPFLAGS += -I$(ROOTDIR)/runtime + +ocamlyacc_SOURCES := $(addsuffix .c,\ + closure error lalr lr0 main mkpar output reader skeleton symtab verbose \ + warshall) + +ocamlyacc_OBJECTS := $(ocamlyacc_SOURCES:.c=.$(O)) + +generated_files := ocamlyacc$(EXE) $(ocamlyacc_OBJECTS) version.h all: ocamlyacc$(EXE) @@ -27,14 +35,14 @@ ifeq ($(TOOLCHAIN),cc) MKEXE_ANSI=$(MKEXE) endif -ocamlyacc$(EXE): $(OBJS) - $(MKEXE_ANSI) -o ocamlyacc$(EXE) $(OBJS) $(EXTRALIBS) +ocamlyacc$(EXE): $(ocamlyacc_OBJECTS) + $(MKEXE_ANSI) -o $@ $^ $(EXTRALIBS) -version.h : ../VERSION - echo "#define OCAML_VERSION \"`sed -e 1q $^ | tr -d '\r'`\"" > $@ +version.h : $(ROOTDIR)/VERSION + echo "#define OCAML_VERSION \"`sed -e 1q $< | tr -d '\r'`\"" > $@ clean: - rm -f *.$(O) ocamlyacc$(EXE) *~ version.h + rm -f $(generated_files) depend: @@ -55,4 +63,4 @@ warshall.$(O): defs.h # also works for .obj files. %.$(O): %.c - $(CC) -c $(CFLAGS) $(CPPFLAGS) -I../byterun $(OUTPUTOBJ)$@ $< + $(CC) -c $(OC_CFLAGS) $(OC_CPPFLAGS) $(OUTPUTOBJ)$@ $< diff --git a/yacc/Makefile.nt b/yacc/Makefile.nt deleted file mode 100644 index ed9900bb..00000000 --- a/yacc/Makefile.nt +++ /dev/null @@ -1,16 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -#* * -#* Copyright 1999 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -include Makefile diff --git a/yacc/reader.c b/yacc/reader.c index 0fb3a9cd..ea1460b7 100644 --- a/yacc/reader.c +++ b/yacc/reader.c @@ -21,7 +21,7 @@ /* The line size must be a positive integer. One hundred was chosen */ /* because few lines in Yacc input grammars exceed 100 characters. */ /* Note that if a line exceeds LINESIZE characters, the line buffer */ -/* will be expanded to accomodate it. */ +/* will be expanded to accommodate it. */ #define LINESIZE 100 -- 2.30.2

Gr=fdn%kgCAd3K-=7eCR`6)>=Ywwv{!Z{u zgMStLeDK@BlX94j1)IT(0{>?Gmj+)Ke0T8u!4C#M5xh6Jet&8(I3C;)JU4iL@S@NJibgZM386OSCIzE z;xlTwp4Z}7Lt_l<)@SuD<8h3A%;DAgHlCsSz3L2&oIc*OH1fJzEv%}+QHNSP5Xdhs z=3hhbx3PN4sXeW!eJj>SPL}QO`o<3X`N=QsYGTFv80)pjHJ#1ps=BP*=6Y3K@~!83 zlo`)Z*O$d#xpne9>Yv|l#?{65=JsmNO!d^K`57O-FFapU6F4bv%VM@i{qear^gCZ2 zy?a*0y^8yhn^9&bUs}uiCco+nE@6J3F7t`Mb9;E0-({oBGClYmWyYGPZ_M@8^2evz zIFtU_K;Dv$jQTd(q*9C71{#5WK z!B+*}5PVyp&GRznt1)(-e0}eJyzr3>KTihoHn0CfnbXSqxQ9-t3_EkZeA%ns<1@X> zY|H6rdzp-{i`S9atAGCfc{ja2`|T!kAToQkt-kiU$JyM;7u=2OJJpwZ*{QzfXJgs> zRSaVt^^EKv=J~*mHhyo{KIi@JfZshc>0Yi;KDy7v)OShiqh~_RJAwa{hpW3legdbpV#O1eX{*`y?$osNbr=v*&b`x zS@kaOxwbyO+u3B}V6g7qz8ChgM}50z94H=oM<(cq5+4+p(NdsmO~+lQaN6B^?(8GN;l(_P8qJh#j0xOK$O z#xT~iJ9}9SYIUyv+SShXzwaVWXX9k>F~Rc!Z5b!>w2YGrnYT9PMLcBZdDx5W{O*~* z+ebc^t+C(Qn#W^oecc-Pz~y24-wILR;<-C`R-nz}$M1M2&iP(eLv#M+yXQdcBM0MI zUzX3-?r66)v6G$oSz2aiRa~R~c@ET)vqPWrgfC}p%=M_3AN@SJKmC!5eiq&s=IJXx zbKBeRvhBZX_b%HPkniU&e)GxK*vVJ=;t!|tKp0Od91h*Q|*m@;Rgq+_TYc+TldU)lehW55#fEX6`WqIUD;n{ zlfSEMuG+H~KXGv=kY9cEQI2q-&MySGRR8j+{@jDDp?)1S|2|pgJ+BW&-qqtgE_LC& zEZgVYkgqOJwLj|YoTtyDwE#vCkfTcpmR!akH^+$-H=QsI@+po%1md_VoS89=qMkZts?5_V_Z_wak8NbD8`H z+O`;4i({;f5kKl^H{ax8&gC+Fa}J%=k;7%5Vc2eck~Qu-ZO$)0w9)^@$iMoumA<=9 z?a%9be6O*)FBof{4Rx=sThnAZH}ZKf^VaH*I`17O4*u-sgRjZyxDfQ*t?L6DbB?ao zr=GVl2IqWL3@^>vpbSqv+>u>#&4dD zKOtlB@kLxcGyK8#pZlGie=qxJ)~}CT{r}b3?`i)~#(1We4RZMX+RWdOXYG0N!@69) zDeK1OtKYtlpY*4D+2`t)$LjH9&$Drndrm-~=5vKUKiHMOADjJN`5R~BPnyONy=?zp zgEad1UM}h6^S{pTdaI?{_>$>&%Z;`FxW?~#+pl)3^OI)3FaGZ7_r2+3e^V!oPkg{Z zc@i^TZV2d;=U)rCEh2`?EcSR-L{K2_cXrh zhp~I0d|sIPe7Jw=i;W%o8}pA&I^~tzxb}~yHGbBocMkII5BA)nUH{Z+-QOWu^V!^* z+}|_k>t4Fszjcxo`v*<3zCT;t|M^$0%)^go%!c=BW&Ykw=FiW@pEK?8c@1Z+3xB6k z9j_ep*0&>BXY1JXJdr2)4Re$Hk@TBKpF67W4^Hd$R-eyJ%@JMA(UGBlH2uokTYc~S zAKP&sALf24b7SuQ^(1rWAoDk7GG9B%+%?ENnmILkI?(9U#&e}!pBWs@;*0bAD}lyW zpKWdkeCG8IRr~TOKDCG+>vCr7{r(pZZ2wz2;;9|>GrjaZOCOA%b=0ppKB)71f@AT| zJR3Kq0NhWkTm7_qfy_ z^X5!#1mixswE8$cyO*!_;P&1?dsVC86ORze&L%~$*O&4DI$y3``+0(8DShBM`#-U z$!a4v{M^pp_Rl}iy;tC4;d7q!-5u25+tTOj%>j;Xk6#z_1b0|-qxQslGS4Fcw>JZg zelgaDJc_}yw)Ewd-OWI=kDlgipUJc_emhJUSGw1l^yZ4bc`n-yBJlo@Q8vaMleOAYN&zCdf zOv2G&-dO%B*SqFK=73-HYtG)qz`3>0nVjolXD3~3JtJ_R9m~@@W+QMnoE`24XKAkI zWajuJZn0_VYR*}?^Q8CO?4Gj6`@tP{$82r9!wzMgZ|8&F-F(2cTI+o8*802ZZe7RM zJ7@lkzTP!k`#}48XJXVwKJl=9UblY+M!wg9dL$?RJ*Q8a`grVJp}zDt1FhV$i;Dv$ z({S88+?~F>$k$e2%{`;p^OQwzRUB9MZWo6d{oRh|9`U3O%1b|&dM7&v>Qy86QM<^U ziOksmS0K;0Z!W64pOc+CZL9}&o;s^boXfTIb@yy-tXa8izWDt}Ab0xO+|JWxx<)%6 zJzIM`cAh@dHQKpnwzjUFGl>V+YG2H_eINwj+8r9Ti=R93xldh}`@`v5cVEqO?jAlC z(C0p`th%iJ-qD%5{Po2v)5kOZ*d;nFSr|=EAQyH23q;V+nX0NkIi*$Ti*vS_RHnffNego{mFq={e80Y`}H%Z zGr;#d18wwKWaU`RmuvUGJx2m})%ievaBYke@?>raDx*&5cfQElqj{gJ1MAL+&n(WN zd$xB!S^74Dz6-X}SHI@Y1ZStdanEr5qD#9kP>Zh!*c6j9ZLa4t-NkwD`Na`E_LBLo z6dMlge@h@1zB@-B8%2EI3~md0M~pGirCyzVd!Ca$&ckM4&oUm^)7ZkT#vi)I`gdL) z3B-RcVCNrBU)$4bj?B;G?-J(R$rJ9J+oJ*B+ZSuW2kV-AFW9BB2?{?Wh9CH~3D z#RuPxsn|i-D#HmH!>v$-W@`FE3 zKAS^z^Smi9?k7H}8?_}LopZLkUrvt(&AYR!H4geW0)E^V-L;qD<@XC+TLY|hKVRJ) zTIc$_R_~LI=yuoL%Sc-F_xbzzeWLdHu14{AK4>nixvS)aOz6L&-sSG(G~YXID`PoQ zJK8qKkG+@Ni_O<4SFU>wFCjI>T z=8W0XaEpunU8s3AMcxyip6*P~;-;Z*u4C~St1(ZX|DO}Ep{chg1HxI`HUw%9|?B$`GXhx@kx(;p6eo_JNhnXbKiH{(|GZ|ZoJLW zE!op}uguM%#eL@9S%&ht!MU{VE$4h%#&hkS%6je2?>aRE@>#vk)2O@lakY~jduoTS z>e$$2pYt~EV}IMv?SEfw87E}w7yTNWbKjTw+xkyPoZ{d3uDt;0>kF8jVyuF9*N_?pw#C+pzEnsV#t z+DRs6uHgDX6KVCk&-%}=-QfP(P3BsytBZ|5U8qO-yFc(=^xkkjj|S>UuI1gG=+0Ne zYNFpyYHf`=-TB7*gK?dnWn=Gnvfd%fY_yJBfAe>Z8u^^;{fxj9Po8l1(Dym2GM|+G z8zxkC)w6q6t&j6`8f)i+Rp(L7h*`V`f|CJmwVn1oE9>^TQ^q~5IXT0RwoFfR;+`t6 z=H_?FGJSkiE9U~acw#;m_Oq0FxIH)&(AV?bn5wTf)qy(G>gTwIldYidbv)Movbbw+ zBXVLp8}Jcod;2_o$l~kNmt=kp@8|j4PUDDQ_8srfFp*Y!ebz4hbKJaSZZ0z)<4K%2 zJQm2w{lPlt7q1Tl@@?;U9;@^5p5M8R=5_V?{gB1?&z#Q@;#O1U?wGBOa$`SYm-%1! zEF8(6`nc0s*y+r*mdW&dynM~`v6Vfo^K>u!zf(=K*UuG4)0fND{NC_{kIs7GerW&5 z&^L!~Pp$R4E{|$zK4TtrKF1Gmj^x*#MxA$4UJ+N;6!ixC^R?I(t#r%US=3lU6 z-d*|kLNu=Bq4~~_(q8fPbpA`9EB@cB|0iSjQ|13{#@;<0|6s;Gt91N*8ISt^M#k>R zqwz_z=AKbg_Tb9*O>W4O9cx6b;p?`n$s?QAy5Afb@qAjoM`15Ny5Eyd&+4t8a<`f9 zThKXvpX4JlN2cFDs11Jn*Lc)>aU)R}wh)u|Kycl=4y?>uB`Q74-^Y4(zPX7IuUJ=9o^}&Pj}jOTveo;kj0qwkHezLs}7 z#<=b0%QByE4fcpf493lkx)PsyGQSn@Z;U~1a6`_%a!L+w?nKxOG=3fna7!=FmvPG% zIvWeFj|TQ^1RAdEqukd-kF?;Sej7bo-D!TMzQdWOQy(&booJM&j_kCw-B+nO{lho^$pH16cOevC5ne2+5n^zV4dmab<^=+L!Vq#<5H~Lk+tdrBm^`59#qh(yzYBgU_@!XZ6MtH_a`DjtuGGL>_WsQEz0f)^_D(Uj z*S_O{Gc?}k*JrGa_U7;T3t6{^9r~I>`qd`?yr1dcACU2$Hvinf`DqQ0=bp~mU3J#Z zMTSnlqu9>?J>z>hgN^C&?5VH4hmOXtxlef3=C#b{=5c-f z<9S%M7cadt9?AEQSDnvgwSs$f$@WbFzMXYN1U&`;ijvAAv?*}~; z$N2v0puab5kFPyGZnpN4%zb{KURzr)OW!H9=fHpuP2X96aqwAzR@*O4|Bo$Z9@As) zy1>4Tz&@WV=;*#aw{33!KHMi}{c4bHOZASwXL2GkJ3+2@TEA9nIKeqi^tJPW8d%1g z`H{C9Gj5%zD>dc&|K5q}ULBka)J|=&N6)w}$7h1G0sWwMo)#Pp=J&>d%+2N1FgyHr zPc*0X?^&61hqR9Qo4?|@#1H-B!A8*YW=%YN)94*P*OHz4z^47Q6co$zq_&f0D|YP&kbyw^Q^T6a%lR4?8O_TjMi8-L_kZQ{?m z`wZ`5(K=)># z&G+%G`}s2FhwnJDPL96Y0(szPd6u*GA4p%EZ2H_)j`f%2kY24e#6cI{+36WC=Np;Z zi3j?s16!3-0X4(|D&CH`dcHm-_x2q1>1kQR zsWWnGKsWnZ^@+RnbbI<^eUumL=IK(ac-DS2^(`jxIYaIuvG3+PfBDZRy6+7>Az1Z! zNd2txtubyzMtlbX?fyU=;Z%OaYuxjbe@<}WyINWGxyZebAA804q~JnuJh+|sx$|>)%lP5*kziF`*e-wUkN#M*9|z5`dTU=z>1(a| zdEV`JhWR_55jJ~9KQ#SQfx6N7@PU2*Zhu|u>jG!}V}ch3FArW5ygm4q;Cq7~3Vt$p zZ*X*9{0y`?|NlAs%h^UCC!2wWmxGJm`*SO|IFVoZJD#W7#QSET*?)M^d(0+&*uX8G z*0I}jY>%HmlehAJHFu=*xSQRPBX(ikJ&h4JzcFzuhMr@(>BE=vNN>3ln?70n%|Khm zB^^EoSJ%1p_Xm%}X8E}(WBPF}H*@{wo5%6%*N+=?l;emlWH)uv_~bs-%9q&1y3@Pg z&o1!E+1VGoINDh_S?AmQYrWp1?7P$1$Dy-^NAq|zKg#Tz#;rSR`VRzZKrHKieqqO+ z%|OF*@4)g*zxOIXR&hGNbH$AhIcr|Tay-}y*kOCszJ8WlN494Z->dX)ztgvWPE6i$ zcweC3bK~dAZ_l{#S68MM?*p>qJK;dabN{Pz+umcptNE13x+7j0d}i>L;2nWB)(IOu z1Fd7ec1~X9p`4oMb8D&g=Q`DgJbGWM4>8Np(}HFCdLQta-2H()^zxBD`Tg;5M(>Tm z@qn*$TRr3b+)>?gAH}lla|avevZh|XF8x)p^O3Lg@)Z}x{ArH;ZU8?Yk5A%tKP}_k zn!EgD&^j9Z!X3YwPkxR0C`X4gzjJMEe?N~Nww@h)T;O~EFAuclN~})}_cOT4CJmmXX z%lm?Fe045X>3467ZLXU>`{^W8&RVPN91Z4YZJ8dqnAecH(5#Jl!lBQ+wP!rq>eoPg zp5JNsZag^E_-lXXn>Y3Bw&yQB{KMH+fHU!r{R}VXy5Fl`75`k8?Q?-V{D&p?6CboW z7xlYbbS!o?HqU8uGurc+eaumH`7A(3^Go;fKoehe;Op;4hkNKkK>lRF=ehm*Pgm`X zK9#RAhmD=w7$3WH{o@@Z*K%}UAb0%Zb8S4FzS=2Q%Ve7qcmBvx_td_;fzP_`2>sgS z2iS8k*b3(N1KE3mkH3DKzgMTA@$=*4)z@fjbpP)yuY6`0MxV)ox?t^8 zcr(ym6*LBW%E86-%h##&)xk2k$Ik4=BJcc>f9<}&I$e0iJze~%ujEI)ugDmG;_(h_ zoxC!Aao!l<36Jdf41{xb#LX7I+?{kB55#mjU`u;XK>mC{$9>aSP2-7NW519-zaN<9 z_|Lza1N-dnI-iaOe10%slWmO*`OQG<+A=--=Er8BRaT$Rd^acFkvq2dqjnw&DzlaT za|7-A;M}6O{k<4tt?TYwdeqLh2O3{+{bZ@8+ zeu?S3GuJU+{`NFh4|fFS$bEgjnWQd#o*n1EJM(hUIr2X+$*P~j!x}xmm^E|!;%DRH zKY5(iw=ak<=J{t$t<}y(`j?_Bk44Ph-DDbzyk5xu>f_fPlRkRbF!$uljU4$mu-L3E zKErGBf1iLJ$zS_6v>jqu;B+KtVIqfyaXZE^w^R#E2r|Wm}d!x8F z&tFgWJ;ja}a^n8k`1$O7aU{O__p{kwj-9<#+|yUS>z_I`@BDZko1Q1~Y(C`l4Y8TW z!Y_9D^A9GwbXH&ezaew<;o7q~oZGu~T6eC=@!!+E<9TFy9-p4KPtP;claJ)?nw~zl z8b2+tCN7^fZpr^a^o_rM>C)c_{%!E&e4+Yi@K1tY4gOc~YJy#!SiFL=d-8h=Jb4Cp3e#B z*KlXgGlNeI(eCjNN>SkAY#=A_(!kl%ckkNooi9)41HP&eIr8kBr#u`B`2J|1@$o=l zKlEIiZ@xY64KyQwB>E6`N2jZkl!}k*deyUk=K6@MtUKK2}_tea@ z-Mw^*ul7C7iOF+WuJ|nPWTCkp{k2|y`D4sxWpT;pdCm@Gj(_UTo{hks#z=m*7*9rK z-58g}r_Snsx!KH|hJW#BU$p&L)ZkuxwoUHUn1(}V0YBnA8mI&O$*=XzK-*mWdFAH? zKC!ab@IK83*6(vemUbCPWYxqR{3@{9BoCPSlDYU8|eeS+_Cz6X??by@Z|l# zH_v0kcr$&?Jbq6E>I}ztquW0Hk#jkr-&$+1d#&-4zjW1KbJfY7{(S)*?D1WnAIF1v zp2g)ZIuumDn5&<@>c4sFFUu|e=wb&K_KdNK$2=RAa~|2<3Yv#>7ye(&6UTJCI{3IK z{G2?=(LMK1EgcQS=Y4W#a8JO-$d|o zxi~$^R-d17wC_Y99(mHv2jy*Dy>znm%S&{Q{zPPPHV*5gT?oYKGlKoSqqoxMw{t{R zTsz6q@%DfYHT9Tezt#dppU#ZIZPIzwT!?@p?R9 z7mQB@vCr-D!e9H;TI*sN z-}o)6m(O6owLZJPitmS4@Qu^ahPvR_@76gIOSwIm{+NH~lYd%kLcWXVq~G<^>0cMr zZ+bwDsIhkixh^g}BTvm(BX7>%b^6+Zy!x?6yC?XhaOWK`{u}vx%a%ngzc}ma0{2G) z`}v~IUy`*^_N5uCiJmR`UzR!b%SQjN$P?+)k)_2MJ)bApmuG^lQC7}yr`{{~iXG&9 z4&j5EdsA>R`1}BeINNPKA`5=(r-#kg2l%}=PmM1A+#KNaivmsk({IlE;lZGGD~rc* zKEnmK_Vithn`6`bC|ljt8Igspj?ZL#HV`N9|JA`mL495&^V%I`a8NE5`l7u0vb6Bw zVxGRns4tywOng5Y$nz_&e=JtDA=c`zy!qP$b*PQ}jJjU6M_pt5^g0W2t?ryxcJ2){ zvD7{e8XNoX2ym=bM`MuVxgPam9~oSYHt4w}ct@a5PW`+&An$IS>#N*5vZlWkkX>fm z`Xj;X0=D~khu`M{>;7$e`|;rXnius~NqmOq_b7LIGGS_oG@?o!cy!hno&`ketBz zZkl9p_w!5Ud=K%4LFPRf<9_t@k7jPn!Iwv7W;m0!eBr9KC zBm3X8c6c^V&y(|gtIB2gg!?o0qyxG}hwpWDoZ%B5on)K$PmHf(8D+k0k}3D}eAE)T z?}*&fv-ZhRFvkC(k>!WaYqj%}ku`VQF!w{58+rW4lgvj(hHbFNo!ie5$I`clPv+b& zp5R^U&eeR5({~SjL=FJnjt2a62IbU!@xzx}9+~Fl#J&^L^VIZgJZCdz`*@(?!~27OpAyo1_INZ2J(DL{ zxzglDo?d2JZuMYZu)Tkeg%-sPW_;xzr%Wk&WWq-7dbAF7r>8uTTd1=5l{d`(x zdn@z&I1sFx12siw;~jaz8+3i11AZ^df%CK*56g0(j&|dL5AO;zacW{tNi6m{=W672 z!I6M}YHv4xmgU7AcP;#BuK1yq<8r|EX9Rh*Exr#Tu1A7pxfDnD+b2J*|NGLP=cwnz z9cb?;Q@^@)KI`;VW~{%LWWM#+dEA<-pXpxVn|RsRs~ z#N-vV!Y{V9*23xZ%Y)*Z4a5c^wcfRkoOkJ)=YvjfENODG>_iBF@2v=J{Yn|L{ zR^*mk_xs*D?%y7KZ|+b1FAaP)tIqn>Jn;2Qa5mtRHm{W%x2G3;IjfD|boJ@q7j#{1 z^!~9na_$}=N9I^SU*+ZTj-bBy8c&SmfljfEK9e1N_TG~>^L(Oz^!fD}Kl}d2&PZb* z&rf#j!yjK^Gtfpqy{GQ_-=6s4_NzJVVxV^Txe@T)I^BJ*C6!mi_<8x-;*Losk0<=t zY`}9((B^|8FwxIpJG%e|_fXzW(B1`x7VI z__7BFe{h+VaRnf_ReIXB-H z^3UWs*7c(qYwD+Y;WG|y2%MX^f9dW#j|KE^2HHHwZ<*%oo!haGJ~g>N5kDi(LQL)N z<(X}Z_vUkT($py%_XX-R<-Fj)JdVxd#9HGqeraGI4#>!X`OWFsI=~@rfIN`9HxM&E z%xQGGW3=itCzoXT#Ev6@= zX1?;qcpAs=%otbBs5Zu><_`wtfz4ZkF;~@fbLL0>$lkI-maVz0xd#IIEPwO*P*ar? zAGwo3Yk|!(LGO;Ir~mpD{K&t!=)lotpc&(6GtksxIhd~*p9|Ri;nZ~N?`X!YF@0x3 z4UW8xdOtF2Y-|P^-^d;|NVATY%|Nr447+nVyle&&D|4x)>JpIPT%Ldm*nYZ?bx=zIzK9X zZJAE>FzS56OeecI?ma1A;(sJ~?bI*dBOjwY{xz|Rz5D2y@8P?>o@~u+JNu*VXHBxp z;w?{a+##mgxi@+?0>1H)ugm-Aea{3grq zCkOa_Q#QC0{CpfGuY}77)*d^=i&?|;FPj*k{Nyo83UY&1G`qWzQ zEB68!>-4YzWcd8@z#4m7f%mZc_&{Lqy@B?sfNx~^t973{WVe0l&pvvcNqgNlw*~yh z>F2}=b2zUL7t;sv`26&gJdXtQ$On!z`n(fHeV@BWeSG+n*~1@qalePn-;uYSxW(g~ zTXpf8p!aKIoAVoy#odo5xozy-Cq_Ku`?W#2>iev9-TgO3M$T|#4qwipSe#A!J$Kv3 z7dfdP_)s^-^m)?Z9iU#d(}A@!!P!8*0Jnu$%4NEXdZc@>FiA9r~XV z_!%p)y(O`2=J^{zx|hGc@wNRp_WzTOs?tI^Y{!yRbEpT=|KMQ<)>-79nd8!M#(`vId3AFr(3~A}&kX)_6gfi=gtRkx z(qB%UX>}^L_HRhP@Ofun7<48J`PaI}m%&$cgj5fc&^0uhs!qcbiA3qHpa4#o13Fg4G;$KL#b?gioa?-hbv${#F{s{i>1+9QwJY93{(T>L z>iU10#$@G0&D?8{=6uTaDF1_l{BsGVkrN-j)xviM+RF1sx@>|v81 zzHi=jO@qLW-%vHwnKy=BSIQq_PtbDMJck8$_b_X|Z zf0JV?w|V3^!cfeAA1f><6EY&*zCib_44m7F!nCMBi}T#%>ln^vv%05eKzk4 z?hQ10#H8_A|CzxT#EBQ@`IS?$-kJVO0(LYyaNg%j(-()vmfdNh5uam*iUID2itUwRJ&_VJl- zcqm8p(YhL$@52fG_#k6Hf9*r%y@B<0Ke zpYPVSIp5}Co9F$DpIx)ZXF2n9i9-x(*W9}TO-#nlX-4k zfG+u>SB>K8e1I!{l)L(4UaODBHwK3TKHV8OC&vPO+#c8~*LVcB>`?>rJ=UEGaq&$Y zbhl5>nc(a+XC6=X>GPd_{;3)M8_(_3x8{$XWxDBWtu*GIk0V*z4eXCH8D7CFAK_68 zY2pU?QHT2c-wd?+?W~J;+{b@$Yy|pvcVE%NhJN+QIp5@54$lX@yW~Zz{Y)qyBTsZ_ zc)xYg+uqMcIihbIe`Ln?y*lXkX80wBey(JL?_xX|7^@|6^feFSs-5P-9lIOEJIZ8u zSx^1*{g~SWwzq=vIj=df@sscTx+4$^U;jbg_4wx_IkA+p-QsXQcY`=anG7$-QSSJ` zpZZURZQSwKd3ZRGd-0C`Rpw~s^?Of=Reo*^wB|q^%-=m@PRBckKCQlxoBOgG_vO{z za{;b@B%F_Wj%7~#Bj5G6HDf>E6UKhW?%#3#=^4K(2jreS#j+V_uiAcG=EQ!vXf5%v zXVH1)H~+q7@_YQZlH_h)Z_NSz@#EZW1--ZET6MnpDbMmru6;h~*H1aLUY*+Ji3CP`pbqk+Tr7}I%3=TVcY(`-})TuyZV}6HBiV$`<~7@j`jQ0 z*Q#eXf5y6=*MI$Xu5j{&D>%VLbC~X;){f@sjEZ}Iz`wIoKaT}ZxYp|H=!-qL5_7rG z_t}x&rv>)n74{f%K>Y+sbvDrfCNpswx@yqBFp zw(kr0;XH{^|HeQp<2dRrkG*@?EKg+FpsRJ=bI*nxiVX*RQa9xJz$g1I2CX0UZQopn z`FjI<>2c=fdfe^wwRU}JxwVv4Nw_03UoZhnF#)+Buy0 zxx6_s?3N#&1MFRvANA9<<_5?7ss6_AiSvtr^KdF4qh`K1MBJ077&ZgV9ct~}E7tf< zo~>nh6+6D1?Q?+|I5)f(S|4=CZ{yrdzj~cxcGNE4<&aLX>{KhQ7e4T>_W@tnFj*? ziK+D^u5yQ8eLNfs_=w+qLC@d(`?by--8~ECl}&q~bwxi}dD8Eb4XE7V^cx@B+C08H zwx<{I(Wx~)`4OLds}b>vlMOblt1D-G9uIz?ap==?W56$ce&VO`(Xa2Usd>%*9Faw1 z(>`|fyWjZ1;2FW4!A9VGHFj}P;$V*+92!@z-0AoHzdHSXju$)qWO}!Wr}qS% z{1>m*`0Z(&_HG7RbHxYufjSs{mp6E4z<+y<-xX+V+xI0Q>7G34*$gy#G(L#mK5^nu z+>Q6O>GKg`^PK_z#BH8UF>94kd!)&$8_%6U4}ZzDuItBq z4Y!+tHu`H^`+R&!aHq+%&X0bvvy)HO#?K#Wq`u(OIl(W#amdD4vv0{5PxRPl58gKd zvUo9W-LT~>Y)y0WsF9_kPqCH%%5G$ijf+9=B73e6&IQ_c4et!G<5vx8VrY#lvvuP_ z>iui+&%}VUfoJ}n48)+{JH9ch7yka?;Ao)nmz+Jv0=C`%J#YLpZy%2766>g&t=^@L z-~JEEf;IQR;oz3wz5qX-?9fLypSp*BHu-|*gt%z-G{2kMQ;Xa+uKHkK`}`So^XGWr ziSNxoI~~w-CO8|&rN(CE_|bdHx_SQFOW#g=o#(6Ft47AXjcqUX<@fRGz|W{-FZShs z+`CQ;H)l`zzmWc)3e*E#+WkRuvyuL&-~0=MWx3f+@A*Nmyw3H$V1?dHUzXM9yLuI? z9O|nVIvW>1!M(UI5}%Z(bLP1&B6@j0y}b+d*Ma@y_~+^T^qk@QWT5He4*$*qp4?0A zzcqa_;;Brz6LWKJ4;#3UAN{?`XUoEtn%oMiXIUTj{1zME##-XL*0s&WXgiPM<~QBF z561VG_k}x*++D#lg3Ul&4+pObwANE?@S(A9EF`X8rnR_}o)^Z37d*V=J;Z~8EE|C4`0Y{1(i1^&hEQD{d0ll z{~+YIvo?NC8THv)U-h-#ZSUG1UVfiEI*rGe^&biNp|8;o4+Qe19&j_-Ve9_DI@yy! z_lw`$(Lg&N7>mok{{O;XkYMG89emVIx{E#iTrV>*+$vjHD#n=EVw+UDZV$NaE&|1hWC9-YPq@)URVKazfZ=(B6K zs1Y$V7O~QY%ig&!NPi=kfBzL{?i`}eNn`0mJ$_Fy@rsb3LPf<%;k8Y&=`( zHy(Pu(?%Y}AQt-N>SAzXK(<^ROkcwRuIL==uRe>LZd{xU_))%a4Sbdda(GZ@awbpK zt82S%pSXxw+{IJVx36PQIy$zl;ZF?Jhht-{bA93m2ROSeFvg4Vt$|kAo-O{%A7A8} z@82`!dVD99yY6o;=w@>(Xl?PYwNVb)ScgM?-5$`XiNEzj@0c5W@z-4En+rVl9ZcUc z`}b$QI>-I17vcFVP= z{Tkk^HK*S<<@5`#-`3AByjK3gO#YjO^UjxYGLM&U>^9c=KyI9G3K)cIPqjO>C9L z&Cy`2)7o#%SC);gsWo~=dm9;lpzK|k?A4di?>TQ*>)Wzi{D17-3B0D~T^D?kGtErj z7I@#1Os0y>oY|K&v}v2rh4h)u64C`>XhWKmu$+-jYD-x}X{BwTv8{p%p+J#EkwvNq zq995Isx{<|+4lbvw1Q-4N&dw*3AKlr(o?OVm8w%d0lc5JnF z^So~UEkbwM^}+r?4tjrjdQhHwKKO-8G9R(U{JG1_*Z=KgSVR8h)?BlLHM@7PX3wxD z&1GzyU%57(?ZfF`9Vq6#D>R3U;im6=jUykNZNu*AhzLxt;E#)_E^6y;GTp$Ba`Z)0np~HLaBLbziukv@( zTd$7AlsV?%!^7$dV6z#cw``N6<54-mSiu|PKY;Yw$lJST@ zsXc7jYP?@7SU;YFuHVRb<6sTnM*rvB&wX@vDQ5$IY{l{Aa_FY)9YN06U)9c%OB~3v zzB6B&7GD({ktL3g3=}^29jKmH;%6;BzhCGbz(c`Pp)5+30%A`*fpW+ z$oBco=STQUr#W`KCdfZkUH)!r_Pr!n3l0YN27WF=oa|Q`%e&I%TjL!-W4oy;2py5Rf6pIZLb zjx;a%i5uf$Qv1s1+%7rf9%Bo%eSO+&n~&>@>lY-hx1`3$B2exLe9kq-ubknKE%HtN zDYd0@Be$z;FSpipZ)3{eIoLXm;dkt(yObj@M}GhDjNiGvKD%5GUJyJYP|CS}{VDfr z8QTc@%)FR3ojpU&L{u*SouKho1!S}LMFBY<5ZoL1J%;?^|4W0P3qB?IfOSY z+oyS)9SjsUHy6o&m(7p9^l#k70-U3^$9f!pO4dA>fUP=D8<`vZZf=eCUd)>MvX-{8 zYHV)ns%MQcb{+~=&1ZO-2YALYF8E(Q9!ML{@=r~ccLMg{mE2u{dA_jMogiP7+DP^X z1oM5nGe+*QK;CWybbn~zXK~0opdHAAy@5h5S37yp3b?_J!=Jj=4RTlRuZ${;2m#<&S$SZ@YRc z`N!keiJ)9H9%AACUJDd`Ipqu+8~0t8{`~8Lveaz;d#PWF784JoVkoXxniaVA&<%BXL5lG1a+Ugo*ylpk_2Z#I|D ziT8W^Z$EzGLXCJxs*_toTTJy@TX}5uZheb)awv;Jqz`Y)RGZxF=jpzLdk>}p(+}JKRbmQ+g^7o-}jf=*a z{2$0Tz2*F1+WI$7^^;TA9?yhN$lvPb*Q#}Nk@>}wE^=^I8$Nd!_gpgXuIs*+PPX8i z{kI4B#trDJ`Jl}o^V-(ir!D^c(Ppc7Ywr%|G^X#JMBjRSU!Uk#H-Gi%IXAWG_uMhg z4$mHKcAO68`GR}%@8}&f4_90v~)4b3VU4Kg7j9 zTBn)TvZ`Oll=b$_Pb@BL@7I6l+4 zZ`QwN*8j!)!W%j&lTEkIWd2yzjDEa0{rNe@jl5zjZl0GlBZvPnf5*NYE{1jAopBu6 ze`*;2`izfb?0Rq-d)Bnh*sG^8d0n0^PGj=EW9O$a=b~e`O=HeY$4*RRY^VQ@ss89` zjl1J_!w){nS(@+n*oiZH>QC?T-qjzGIeMJoZ&)GYrWx;lWm@AdaL19|GwEGd-)9i& zqIQ>SXR&kY`Ex}+8}|%QdnZ?SU)T3;I55p0p6cEe$EQC3?7wNMpD@)=nriRi=375) z>OW(uJtxeIvATCx@3zmJ#$P$r&z|b%PW4Al^_^3F*Hph?s=NMqQ~wjD`ogS!@zlR> zs{ia%zig^sKGmN()t^4qpE1>cVXFO%DnDL5)t@!hpEK33o9e$b)t@`ne|4(=`c!|x zRDa=Af6-Kb$y9&oRDb1Ef7Mif^;CatYUfivD<2fx8$31m;w1C)Q{R+9aXb+?TktV~ zC#JlY1IGg6;v&bKyGI2#Pkpr<{gTL(JDwf=9q)(Iz9x{Pa~Z~*8~f!L{^gLd%Antz zy~gG0k$_BNY$1nTopaXe6CXfskfqHJxo)o-)&s@))vr$df}Q-?70|g6;6{IyKJSTh zeRyLFo)mJt6VO2?+qKzqbzrU-^^>Dm%U+zgGgjGzClFVEzu`%#femf%q-Imsk%z}I zADR<#;Z4Z}b~lbMPaAjq%hbE&LidvQxZwJLoG;Dd%jJ~4?83nqi@D#=%X~p*+gDPP zc{X4t|KC55M;8NesK0401JkT!qbSa<)d_%b`8}yluP}tB?O56pVU| z*{6`r&%YhTV=mRt>a2{7taT@{f0b|UpF>dwyC%qmCj`cxliK^ug{g1N%hG-z(Eh>H zzZImp@*LvX{UJVl;0wRS^sD2;7}KvwAIHrtetvDn9+NuNL*jKPeR)MD-DjpYo}GRA z8s9XRXVW_4l`nS{W3|y3&c^+?lOJ+uuFJV#1DU&m^?==9H~CT<#`wr@a>kr+rs%-U ze6BL+8P|+H;~7SN|4wWe`ThFz+4klg*mf@K=ySK?f-d>SW?XreoDA6N?=F4yDBY$`Dfj&9&_ohBsTkZLVX${@>{QdOh^vKOO z&enWW`ndTAso6Hhzp z?EdzAHfjI);JUzmzWl=#vgHKZ*fq}ycFBv%XWu`H41SFE9ZDbPnOfRuPv_IT^c*~v z_BeO#G)MQS$2s!cJU)$AR@ZOL#(TzgW!xM+#`yd#F>2I_Pd={&V zr86ogam_9qd}|i2iZT82xN_M5cLvXz+BhC#uFpPP8@E=>%86VMV`pPMutq%cF~IUO zW%m5z*t1pMx#z^|hQL{2WA~G7|F=#1`B<*;v_BA6d)S2woc@!npXUH>o*(d648R&- z`_aIDg)FgD_-))+&+R{re6rR8`o2AVcD^O`{JBLgAL$c!d+C5r`kGI_r1_xrVQ|C6?mK$M1@4@yW*+?{u%@)mna=e{1H& zI@LpBbtrwgXKii31>mANFW<;I9pJ>A_X0&6#7kb#EAC^Q$u_<*8{apL^QAFw+}TAA zT?*Osv&X$dmbh6{yUQKh7J>empn3B6v@ZngX}+epwC%;I$s6b78oQkVGUQov|DT6Q zeE(+neq!qV0b9sn&nh`=9>@7j{(KxS{G`vC(*gbC8SXw~^`-m7v;5dU=Vz0(OX>{oj*y+T$8Nl6O2f5sdM} zvwnS-Yua>vZ)CA=ltmx@$1}akcRsln$tLUjBFnom*>vF5`1fag%mM?6X+bAaVzb9<`@tOXgNPlkQzniW3 z_vy3oCsSX}#^YHhe$EDn-&M(m2U6onU6{u)-*7CB_`EyV6^H|#8&h_&d)2mE#)SZm)eT*mJCKHqC1$KGGO!oAh`OPASqJhDe#@co2fv}Kd4-AkTu1^8{d zb@SK#=KV@J6X4;s0h#!=4!73feJ!w#O#V9Ka$f)T0I&RU_lmnUrvhcM{QqX$#F{Pi zkRd+j17qvKB2bP6^sn;$(=u*99rV|JynIw(?&0up$F#TdUYou$=fl_a{I!nH>_`Y7 z^8Lv-<{8TVi-9%e2sb#w-71dwb0828@^NIHePpo3nD>ISf%9zLZ2_AUGMo{$+};Sa+>Lh7fg83o&)9!1 z5F2^I7JfDF8Z+_cr@lEcms8qz2J(&G{~W#JJJEkh-(LJY5a7LQe|@(0H`2%9Z%%vY z8tp%nex{Z={oeH9zs~IXt;wEMKK$Rawf`-BKK%By=W;&ax;Z3XuMco^U7$2h=ESLM z#a?-Guq&YRccOFEc{T5RDSQxP`>qM(#O?r}b6Y+;V`6KMLdWk$$2`A}W}FO#eR9Kd zLB8nQ_j}nVU*_?Y3*@iTznSm5mY*qIn>B?!){}29eG$LRO}hS{%jn9Ir4MJPJ)^zi z1$3`X;2Zws_kWM<=clGm|M#bUbNYWwefF{C|4m>1TR-<5|M;2v&Zo=S@joX$a0XUEjEv)N)x0tO^z#b*iJ3TP(~ZO3v2WEK zU>^4yL7%1GNmt3(a~U7U9Kz35wmdR&#B7Yyq4e2;=gP4ke|VN>?!Uht?!_3klK+21 zK3-PI&(!h`y*)J_?+ls)kILj$`BQ$_c3ogU+s6Hm-r@dvF1$8!6!NNvuk!N!w~%S= z-auZIr+zjH(L4Pr;B(dZs6Fn|zV${CiCH zuF5-m>8&m9$>yf^kpKq@8_8s|TJCFG*EU@r6kYUI&dbw26!Z-3O*y%-wW24!`3th_oclG z_OBXWHI}89a=|+XTRivJDc9)iczwvw`~8X7)aMa9?elM7`aJ5`Z%ofSVtZ{S^jGDQ9K1GYtk?(q!Lj@yU(S$qU1ZUDZ_v-kY7Y)SI5Mmo_nXJr z7$a-{RMy&mZ_vL-;2bnJ$<$`s!`- znC7K3acA1@$Gy{7*NMHaY?UA8k8U$R`e^O3tleq;9M9TS`Ez2Dv6K7}zbwCO{*3YFck^&n z{+x`!o#qd@WB%Njy*tSt`{d8#vwo-f<9W_*x$~VvGkAK?vz6`399DZ~UX>@BGgZiuwp+W``NpPW zfztTCHf^%yymf1Vb9ZwfBUy$2&>kM7;7cWYECYR429c;ymaciC(*mou&AP`Sl_M0!n)gnU4gBPy6R*?@;FKCsz!s`%Kz$Ma?HNJ#!R()mHo1 z+V@~KilJwXb#y;z(oObw$L&wwz1;U3F~V;-5UWwnlP5XsnakmW7>ZjtV85|)@RV$v z^LHro_L9ke_H0aT{LS;(+2%2y_XZ~dI`BjvpUEm8d>(zcWeXeVwU4aIz`6a3bI(qE z-kOD5#c_A$Yd;%Dd2DQ6ssZ2f>}Viv^_TCr2B(6P0pDH`uu1Ga`#v;wkTJ%>eIah< zl~wzmdYOIfSheqI+w5a+Imgk{vv!_uhcb>s9I@{iS;O|n2lgMHYI7g9&D?F<%sq3P zxkcty@g+{>UAzF#&XP91#X#{hMe>QS2LisHirlSyy<9%aiEMwjJ4+6d{jAC6d($4@ zkJDY=sbZyAdpc{&XWx(6^@5-|aVBe=b2@Q8&Yhj+@F520(kJ)!)Z3lgId}Gac=pJl zF*oIS?YJZJJBf0XpUnq+wY`)2T-M8t#_!IwZweG+d=o?W zgc=vt>F8ONBjU~O>LA-*{_YCgSL%5VHAZj9+z4^{kl@3D z=LKRl&cAHdr;ojC{KyzWx3l#2KM2R;A?~55Byu5>w|tD;GT?)@fEAPV~D)=wUAmK@WtFc6JPb4o~?4l`WI#W z`==h)yFaf9=sgqg`_5qG@`GCFT=Pp}@0d}~`z{@mA(y^MX8 z&6j(xVC~0U!P<|%g0-KJwOhsJ6Eo)wk6f>cjdKWx1F;=Bxi5XWi$i?kSeySFJCJ`i z>+mhE;)TCQ2J-S50e$W|zwc5Gv%`HN{t>^_=Z@(e{F1cSf`fsakPqVMIU?4t4HP;R zc3y}e^JI@)REGRf`Yhrn-E!OLuAXzaI`|y*!b7z5nO~_S`hJ+1MOot3Hl##lO1(>*a~}z(1QsbFL3$+}DZx zqm!Nf{S`a)*8^YM=;MK}FO3|zGq-zx#@H;@^vL6z13a*ABaj>BSNY|AoR6blxUL^^ zVsF5Pmqj4EnhWmXgMq^LzSrYkf3yW3t88JH^*Fq7YP07j!UrzMxi8>1Uf9bw^6HQM zo-KGNXXVn@hxV|Ie0*B>ocvC#ZwWp;-$Qvrbon_c<2Z!s!QrS!Og}k;I5-usm0i|} z`}KixIxuG4CW;lC`K;|*d}Ig4A}U(;6QLPQ0&jIgj#+N?{m`@58No` z5|ZWI=cP?n?*Vq>;i^nQk0|8&?E_#3Ht2CjkSt->(2+x3A)K-M`f`gs@^R>em>*P4?MgvkRRf7Fkpl7 z+Q7O$r;}2yJ}GVdyxL%jeftC4DdKe?=(@WNrWluxpQ4lEYa{)aUIy0O5IkX6cPef1 zU>_fFqWpVtMoPh9$px;bq=R%f3dWbyUJ zzP9DuT{;V1E&^kP@8&9vy-p-#-|8apF zdO^U?jllezt53+7dqt6_KNplc9Q|&@)tDK(YUxVBG(4Q{OuIrPzNe zVEcujoU^gHWsJ`wcl`W|6G!~$&-64`K5O8>c^^62j=$;e_j=c`Kz;Mk^1+7G?(w5Z2g((z2s!t%6Fx2zPV=2 zKmX6~`hB*qndYrGcOiXtb^rO<{Ey{piE;j$X8jX+xgG8KwS3s6&p*#-G1pfcQyZs` zzuz;he`eYWUA0~R`(pdp|GB}JYi7UO_ILBUX~j|;Mw@?S_B(8UGJUpK$2NQ1cVfss z`AVlbXX+i%dHBD)^PR5>cIO*D&&VGNJ|Fy>;J1SP`G@is1NlJj=u3HheRP(G`hRuS zzId{^y4k{p!ue#2wQTu{=-HKD#36R8^qh{oRpYm8F@AiD@edxxS8>EwHr8JJ>DP~I zr~baFb{5R9Pc>fjZwmNF9vRPwZ$BB_o8KY&LHWl=Z_e-Byf(ks<88r({7zOmQ@wYj zjT3z~>booSA2sz;E&JkPo}T>y{WyGczHqbNeC4VS2JEuNS^lQzPIbv&cbs*H1G4D7 zJF?g@@=qT*?6H2%lQAe?d#AolIIxC&#*YQYw9f|46J7i}9Xxt~^K^4?AUGAU z(SGvmx6gk2*g!_t>pL&)FVe1lu~!}pM*qooxB4BB>{t&%(NeyePyTk+ho!zIPN+w) zMW2lMnhY)NWfyzddM@z%+#lQ;&`Xaso$F5JCedD^gwj8@FH5>X2znFIS$u+XX z4L8>92|SnYk1_5vwvf$MGB$!y2K&iiyYplXe(nhPK&HLytv`*c{s{Ju{Z;KOd5E0m zJiTi{-#6$y8L&Yt#902zvw0qWY{q;(|C-dk2gJW}`I5BBJs248oq;p3PJJq%>oEcU z-3xdzUb}F~F6%}+%lT)A#9K0l%SE7g{~Fic79zn^x59G-CfG-CEbM7nrvA3}@zv|B7r*Zzs5juKj(Yq0pOEQhIf!sNFWbs*f zFc|qboIbwrAr`yLNy^C*S z<*oP7k&K0^OR{h*$8p~~Jk3kov%~t)kcZ8y>agj5fJ!$EiJdvZu1;k9Fq6y7D?d%DH-)uRj;lmp_X@Vb4M%MQ&O@ zm(!f(-yOjXL2Yv0?+SXC+&8u9!xK9zPkVpBKHT3vwE6O+KsgaJCvJF+LmgF6AQ|ZVSXqDWA9zV|{TDJF>0{#yMlwsI561Siee7 z?Z&~#;raCOeju=>>(o69r_$!rXb(AbiF@VAgT`fl+6M#s#8){M@C%QDNy&eh1e)w9S=3L>?IUKp_xx|TirCdK8StIYw%hBHI zU_*1+nH0-Kpfo3&M{*N3b7t4_j4jfCcJQ*mTy378wI^gwF`u-#^qGwN#QEbRJD#_; znX3oVzB^#UuHcryT6XvA8{=S&d{-Xatd=sZ6$3uft1j^Ee$uDwRKWhmm`wV-E4(&I z$~J$aUO61lJNiq`lLE5HFjxMx`DhJ$ddJB9d2X1)g|)TCJ;YYL9SnLWSu3{s>p^Yg zH#^8U6Bi}wYu!}!r+kblM^M!oe)W-8^?+xVo zo}jYX$-dr6?jz4IzC1C&$8!RCQ9tOc9cpXwwFs2jZ~YhpHp0lQy?i+pSZ}Yqy4+s= zjeD=&;ojy;b(Zhy#AW?^a@yiRPyN&1sej~*HqxKbuPNMvBOb$vR+=)UUA_| z<3u-kc#|h;{`vVhp}8_Tr$mTriKL`P$nuhEruLZZ^-(=I1l)WHb5ABR1f; zcMCc7tug9)w%0GbIk)VypX~arU-^r)=_FU4GK66-uWpPl!xPky{mj+$J~ed#(w@dqjFJS={X;5=1cDe&tCDBt5*jbLC412>zzC1 zoqQ}eW3CzBj+^EmAK83Y(DOt8b~%~pWzN|vM)=^PT3$8}_2E>Y$Z0ky_StWrns2?Y z=pJL)`N~~nUfIbRvFBv47X18l$BeSsC--`0dKcRx7T+`N`J9|jeX-sjh@befU)}S# zlk-JJ?{V#jzH}$;nc9^{wl%v0?Q$Te<$*cz7kh2|Zk2zJ$sAqHqn+fRJ#3OA-H$Ii zJOe!e>13a=8-k5MF5~dR)D|mc9(S=N7w_BU>>~4ub0H4oYb#Osu*W`0T9p ze33Ku$smiJl}CQtTix^GPPZa9+nt~Jo!+?F-?+<5oU0pi95q)*JAA!lZ*!9Ea;1D4 zcaQLco$^Hy6I{;i8Q*Q>7=Fre?b(XkEWLCt=lixg-;D`-;>x?(^KkhY`M47QaaqnU z7fWBaK9GdDCAGX+1j;>|)$)w^p8w(W#ZSE*e7@iLG%xY)Zhk~C=B?OV7c`D(Zo7V0 z=J(Fl+bd4w+#lq+d#AQ|kG_iw`{fTgO834vZToO`$1pzT)eAF@S9{53yY*sQuJ2CU zd6Z-Lye6<`{2XEn^0SGh*k>mrLk;@GL*|m%(8wxUCKl2Nxa(+*s)c*0Dv!Q)wq`AB*Ms%%B zYqS+-gbX&zu`_}ErK`Dlx%_1N8)mj2&KO-IkLfO-TX&|$&#l3SXVGV+rtbv-F4-gg z_&XoSU%-VNGw&>&3&>(`WxXox%4*!*A;33hQjC;xrEQP+sB!m~)1l+uz|ZQ^yWc^+y5Yb)*gCKPx{N(jIqgn+!o;(&8w2M8-kd)^nCepQzb*gnp&a0{`(HQx zdx)MJGS6j_Px9OU@A&~z&&t1=Me4tndT#soX3gl| zThi}c(Y4J3eKzq^-Fy(g`n@~tzc=&yO_BMi*&f`ob1nFDnJ0Vn|2flGbBsQatM-ZQ z)WTF-?y*1s0}@fa=m(fHs73i z)HL5*?wRXZb{4w+tFj)K`r`Z7(kHun=X==n(rHcYX)N$!Z|%X)`n0z9)c$FW^Dz4P z*5ThN;JbX(j-Kn@f9sPRXNk_^0eQH_=WY2$(suT&ITnY$S9t^Vky_}>_{llnTXc@ZZWX^* zYAe~~`ku&IYG-W`D64E|_nyG{D*%3+gx)j?Nxb3p7Enw%=hg4ufo?Neky!EG1Xh$C&#y#|KrZd!#xMxhdcN4 z$-wz|(eyQgd*7T~RLkGyB96zozN5(D&K*eGb7#KCxM$CNyn6aBHOeyA_neN8_It*R z^7zBPN6g0gVBEbmu4lh-&&P3`EynlE#y!i8=c;rnsN0x)nU9S=StHlx zYmCpwyx+{n=CbzfV2$_fxg4J#%*TBFGmiC+eox2D*9Y{t`{k|s&YgHwun~xN-znK( zja*Q)Zwustax9P|_H~Ut8X#aMW8H}|KFUy zV`}3LCnI;x{KEEZ+0wBuoyKC$rLn&;jitIY_GQypePHjGPh+FaUonl1c7NqG zHroC-r?Jugzcr1GK77?QHu~|mr!l_pLv2s<_y6yG=eJyF;{#3w^D~UU|Gj>Dewt4` z*ZoXe&UNgEr+2Aw?AtT;M~&OLFQ4;A&_;L5S5IgB$!Yhl`kHC%DZ|*;PGk0T-PcWH zw+>@}XBu<&cHP%cV?NL7*qf)ZrwwC&cN%;8F!uMRv1bfp-!P4R*f93@r!mjm>iEWK z%o#N%N8GE6KpCIC?$L$8l<|4w-dq?=k#h@;6!+vpBSozD1dBk?ch4^ZML(uIq(9nW zezc|i-Yslf)yA=}?Y*n>4UCQNBpttRSYr%NY*5$+K3h^-%O3qb0sY#$1KenP-^Y!% zcO2YkvjsQj0)E(kc536qXAtGX^MACXpZ8hkyenUm?{mnxZ;D~|eR$CL{)1`kj$!PZ zr?F=bWB+g(d(JTSkEXHb4rAXkjXiG|`_^gfBc`!*m)zii&-JlBsd1;aM%{JVuy3lp z1L^ncu*XgP{ZoBlst--|k*Pj5)hDL<#;Lw(s&AfZ=Z*YlO*J3%@0{wpruy!we$iCl zJJlaQ)t@-k7pD4?ruyPkzhtUkI@O;%)t@repFY)}ky>2Y{ZI4#3S6>B9;$DcYIa&D zmp)?pzJ^>I^WwuYF4xZo_{A0d@5qDKxc5Fh%N05J(SdyH9%JUn)Rwbs@HL3|eL&E- z$xCzd?-#iDjF)G3l)ju+FQ&TuH}`usK75*g_EbN2svD<|ociad+W8{)1ylVoQ~gK5 z4nB*kf-g4W*o4KU90rTwR?hcMuyTm7DxP%GfKIU-#$lX^Lk)i=Wyz0T;=KI;Lab{qe z4t5+4l+NMB9Ioh>xAG6jwee^{w(gE@S+352$-?oKO6+gHPlx0%fuM|0WlYNP8o|3mNrwEp0L7 z8+*DxD#sZSQ&ICy37 z(!kHF%D{CGHm}?PnJ|)&h21AC#-=ss8qF&YHO$)kpqT{Lmqn#ye?Myl^8P z|0E8uNuN#inJ%$(M%h%ka@1P6>nxrMtgYRx>2#i)`~ATf3!I$|R-Ie>$GB9EaXBkT zoKJVEGjV!qJLhfFr9H}`b0=p~oa}RdjAu}PJim+dmBsS^n`hMCjo?_YHjR&d%KLvB zL&$M2-xtVJw!6RY4{#|Sa%OLEe_#yw?#{8tyga%;Fjt+&(>@V2Kkz_b?_V;S(_6L0 z)*f+iKc5Wv^Mli8)92F`ivxioXY_lY$r~K1<;aZz8^!BK^VyM_ZlL36K;Nyw`2GE3 z>DyPI_{=Z*^Raqfg(OQ-MMUJG;g_e&~@e-aqBjdLVw^9);zS z?ygC5c`rGe*7DyxTh<~?yC6@y{)&HN-ZA!A!)Bmo{4505>^>PN-#o;|9B%Am2Y=Pg zZTu|)rFL$0Hk<*RDC`+?r*hTeOy?p{$lVi+Jd3sBOdJcY3L0B&WsDvF6tSb5{np`% zk4oo8F5a<%i*YX*IB<>*23H5`p`d;Hh<0puMTkX(m*j*dCus|18bihD5nGV zikYv))MBjO3Xh%5?M;wXeRhuQsK*(l>X2ykrL-#Lhj*KCv`6`i2*=GiQzb8FM7v zr5$@TQtI1y4w`eLZPqonnu|APjDG81mb0}hwLHMNcK4s0#;hf$wi{P|GJD5!`rP!% zF>lZR%(J07-6_V`g3q4DacYbmw`a`Wt~2)I`MGMj8?nppp|pKV#@-Ua?lSf&7Xx

8=`?TrDJO2D0NxYcf7iYhGR3<)%Ja}{1elU_`N^BJaK+BbL>>e*c;5{ zj$=1u{&*lq#EzZ(WxpE4?odE38x(f1^*_w)@Ov{yJO9NRyKp?WYd$v0xfFlJVU#)V zkMe$VW~c9{_&M??mZQ9R|8nKYhf&_xzaewt(D;i(&j7oQ1o%2hnH`?E)w&e@5k|IHvtj@LvM9)>qGj z-WBG5BiJ|1v-bz4_JP#amcxEW;d=n>?ZS&s$ zF@qa6E7tbjw&(VMJi0p0Zn@Dq*&{NStc>amucWB!f$ zaR2eq$6kBLB71LeLvTF67qGu~13Nq4T)?mW*7CdY>mD{(%T{)FKO6Mzf9BM-pFfQc zxiH3vADaPN8Xq-Z4oqWXOrDZ4h3q~*`J_#@J&lQ2@Z;}aVl3E22Ahus?BJLCK@7;Y zrgFb?x|?v0Ynj-`?Y~wydDbpKi_MA*WzOl@JCF>ePf)*INY3dV)AI? zfLD9f>*B!<#X7uO3yncJ>)eUV@$2thVoY!(CSoBbWbYP}ZyjP{-#jMx*bdlT+r*^c zr+CmI9=@09Id&Hw4%pxEerI*xv`*jMNUxYS7sSn;#*<9HA5pQEKDo_LXPxb8HuUV@ znl_n=b+{zgGt(M*Am(2ixwZMa^tXb_Fz&M*)%+*Ny{{N+8$Y)N*08}DWSzOi}PvY(OADQZq4|{(j zFz3#?b*fV>eP*+}=U`y|SU~R$!SR5N@`Mk5pR;E*E;`0n>y6=I^uKNKFn`}LFE_;F z`~+vYelF5h7R&$d$n?8UzAXJSfx8ul&kDXS`uhxL(;`slw&%gr^F3dGkv)8z@A-yZ z_Rue%`6!RH#R@O;T0F%9uXvXqa_mH4ufNkLCi?h1IK?o{3*T{jmgc|Zd9g=6vNt9! z{hmK-k7WE@ptjF?dhNl}s`a;L+&Vs4^X)NMepE)97w!%@*LOpH-4^sL;Km;LbyuJ- z_GF$6806B2ez$sh01FWZ=iVeQZN=B%lGb9S{01H7|U49-sV#Xg&m?e0<@3VtKt2btph z15;c6Ts5`3XKq99k&D3EVOCkbi67xkauycdol?5h(QINxbR|fc91nw#0I2*_Lg?IDp?w`?SckhPo+pSNg zn0Jks^MyXX;NF@i2RM60z!&ye%MR=I2R(*31q#{xsU2+J6R@pk zR;;>*P3!jDlDWQb$o=jiZ`Gc1AU+QU3jf67e1PBaXSVEd7TI`pu-m#5ndcW7>v2>gBkam3Ss zU^^)P{OGeCSN2v0nR1aFy7ouTIB%W3l_hVE2I4ITDp!s3&ePMpafX2|yp8X#m1{5i zw*vO^mpuxfjNt=6xcrk5CKkpQf#PnhPTT^!_;)ZMA2;^AJg~x=YnSaEJ@VrEfUO%r zd7jt&+zi-LAJ`|xxUa2gF8{985B}NL{HKLZiaC5J&Sdell>)-N^ z|HhHUa`hwElXczCfB8ROH}~Qz-~AEm=6>R-|N547bD#Vx|Mu^!oBNS3`N=ES&HcpR zdCzan=T^lGzw%z}#O=1=P=Mck!Kyutwe`-K_2T1vb-kD>*2sDB_dUA3-EZ8wf1YvY z_iP}a)$+r<@(-r@t+bsJI^8eoah>0NWZpV*&IHXT?Q!j&9oCY?Z)>g59@ldoxcAO!ud(j!+N)-3 zZ_8Tu#QeSRXvWCi44mgt9~tZ(b)KAb8mF_*DEs6VS@L7t^O2XKdz3NPedVN^kE?W- zH}mCN&9>gnV#G#k7s1}3I@xUAdTsR>gK@m_jKMWijSufuWGcsk@!obe+(}~5?*`c0 zJFDa5@R1xoI9uYQy$BStaeYH@Jm_7wa}V$QZX$Bry(fZC2>AYzKymiSI}^~u4mcms zcPJnq2g+{i-6@x|-d!|b?~JpD9(J(HUBR}3ZQ#9ZPe4ZVG|ja(_C4-s)`+=6&no|| zCG%3(lGnA3h5JIR$rn@4XE`N?YB7;RxYciN;r+nSmph%q@n%4_{Ke5CP>uy;RsTlX z@?n*JoPz!I$+K1RaBwN|nxky3y!uEkyMP~RemiINM;xsqXAvmJ0=!;|{zu~vozT7N z`vSH#_nTLjV#976h`~Az=qwM7>!ao2>d2B;bm0!i{Go$Sn?bpr=gz8FH*dv8PVVL- zdFy;!m%qFD>FfaAw+G~lkv2XXH#Yh_Le_18T(;J_=9D&Wx}TkRF}^pDx7s-9^Fb_{ zujcSpKj_gW|J>AO)7hy_zq@Px93bO{;CP@7Y!Vy%)~EAnv#)n5yU6d}azhW;e>AXe zT+{Pk9k{_0*k`;t*n*dFKRvtYz>(r}g}n;D@zVDKp9{&^4z3R5Cz;kmIUei!w3&H! zb)PudLw@;h-Fp&G=cjpcdbY$_fBXz&kLS>lz&_MW*pFUOmU7 z406i7x_8W+_YZ_VaR)rfT{iMhTTMTE^{rV1cCq z;b-LamFe?|4eY-yVDtRXk%=p=&7BOax9<&soZzo{aa{yrZf)PuaAEGuFm63g@aY~X zxAwV{%sbc54V220v-XX)$Ors&j~F;B^3xbj*;v_lJ{b7C{->h2vc$=_zVCh5RGanX z1)JE=^I?87poh-urZ#`A6KnFy1v`wJubwoQ?Ny&I$mhpqK-T>H8XM!r4*V#`0_&BB zgT|g8z!sRFDg1QpM%v=}V4&d0*qMOro%iKO{$6Ih`A+0p)4;KHi$J-1r@FA8?nS^J zaXcFw4&<1z#@`%2&AB6LAKTWg!^NXnM$d-u^d{yF3NBtO{G z^Ej`q>)0Y~WwHGK`^HbDe<+~W`cXel$Uhh0j$PKQv&((72-rpM)j_#3Mur$~1#)oo zvv#WK5c|f<9b>a&TpQTLj8t z`TtAf;P$M=A%5kA7|0265<{_CmlNV64vV09A@1@o7tNJ* zHM#Obyf=bHpe&aEf1l1VKYWKh<_8||f(Lrm@!(xy5tIX*(0?LOekOlLdp90NpZM7O z$ewcP9vZnY*M0629IB0-4sf>!l*RJ@J8SG4eRijgKL1X-7x=XZl*RJ@I~>UEk%QmK z_kz5s@2%y^Dh`|z`O&=doR-T60y(7|3-EeFa6Gtjf@k9XsqLJ|#Xj4}Bf}UpzuDmI z$m@=oUj#~ZZKpjSXKQWHJ`pH>-rx?pF}PyF@5}jPbMKh*Y16BJC@@F9aweeHUd4G> z*ROtSuMha++^NU&{~u%1*#E`!Ju5c@>&LmD&K%xw&&DHxHPyveobSBD?)-Zo;%VME z`{{RY9SHcKVfg5|h#~%!EYK~3gXO7z0HMQN^!vWv6100Ti z&{v&g*KRevY-Fps9bb2T&iKsq73;|M4r(3Qc(7hyyS`uSom4(pYY)3CXOZ?5fm&HC z|Np-C(7V#-*S>(?Cj(rPHGh}2j=jpmK{>Hr?2ZR?0ejvUI8$VKE|nL0o);(Sl$!?w zT-_1Sfm84IU1ML*mUZNv2J(V@LjZSOT^^q;)-5y*Om~Y#f%1U$B z^JE@J>{BlGcTI3emptRQez{2V5wiZ%aITyKzLwYKEI$qe=YvsB?VodjC;8^AIVXz% z4|2#ESp@oI9Sv|Zm%;vV?;?H0_*}-3jLGw-1oWN@$X2u4n4FQnO6?PiCj?|V<7(*7 zJ?P&GybEju&NM#n4f>gj?3V@fZwKY1wy?D}jOX>~8CPlxon%<6E#7L}tJ!%XV8>sc zVz%!5@n!BQ}tywugLcaly{+*Iu=sPvvkt-*Uja3tfEh`N6Ya&A-inPxhY;ZVtXJ zhOkA<&Ij^f{4-+rq~Cu_QQnbnJstG9pVaoYjr+}juI+%0d{pRR56;C!nUC@LSipx5 zCKrGDGPvL?F2r!o1^=46yK#ayahD(K`1wF^;e3O0s+J3f0`Xx(Io7W|eA1S$>+-Gd z;N-Sl*-yxrJWDu?IiS zIUeo`_=DGVcQrrAE-yIZt1;Zz-#mLb?ehF+c)Z*7rWtrk6fB zAujZ>(VUuXbn(p{a5_-r1Udb=)>hh$CmHMF$tFJY6W5Bkt+KUtH73qud84b(?sdBC zdsgsgV*Jgi`LqZWoGNtpxx>dfH*yvS&^!K6+Uzx^oDCX#I?e>MXe+r+MxS zetQnUsxw%waqA8u*V%CHdUn|6?9I<+{cbGW33NJ7>+S@y@nqdbpgbJZ4r6S2JYp`s zY51EMLT@zNWdf{p!>oESuSi4>}dGS!W*~aO)YcKM+IjF8ol+ zy>+$UoWAD_-*Is+pmU6uw!)r;MhctcjXmb+V_Tm~2h)}p&S`U~&sBHw8v=UV2PXpM zM{_?}Kjuesj2`}5%Wi*1nmwalYmNqNq4vnf+n( z-mK@RTv)di)DN796S>x`;)G1|bN`I-Ppp*j{NO|^&jjT9+(kG4>kk{eyENBZi@)(p zeb3m1Gdo^8aig=gtJ~N45SN17~$_;FHo?(<9D8nbRO)#i-JQ98A)!-w|XpfPb*$Wh~RpgE#Xzdkv)O>KJkX1xAs zlYMJIw<1@`z9Bdsh>7CDQ(k7uL~f9p3uqr`opmV8AAR zD7`Nh%ifNS=pJo6G0pu{?j17NN(Y^6HZM2*T^hRFt|d&`bw5v>b9`>5YwYi)3r{1D^O*j^5L5Azlgim( z^lj`v9{SGA^o{*d-=*Y^-(xoV+`Qe44mmf^9lptBI-Nr`9$*nDxY!fa7H4aF8h2jD zadVZSCcF7be%sZd?)MVTbwQufIq@mX-5aoLUr<}L{|9$>0;c&@mIRoyXO1O#m(8C^E~&nob$e2-RaiYpw}DHKVyG5 z9pAtW3*G7+WO}IZ}D@_8w0*HAM$Na483+M`TuhRv9pes&nJ4>C?D~2mVNoS zET9*BkJXdCaO&yeo41Tk^`}-Ws>pEa#E zd=K)u<2;@9!Uh&Y+)pZ1H)2p!xSk zn@2IZD9~RSRR7Hj=FOXUvN`4rzeh~#{HL$};%d$(xpV&F055tD2mL&s=Y~vkW8By+ z$_+bg>zC!oIgMQPu_>Qw?PPM&b7}|g^+3((HFpx{lZ~gdYQ>q2K&)Ur(8LX|{#tM? zV|BsKslkcrg4{}=sf*^3UEe>yD*=y26hzXuY z1AF7|Q#td>>CD$h2`+qa);r@&&-t_T`0WjFV7Gkvs(HiIwst7!TP1$`19E`Tw#aAH5FFvxxPxie(TGyOc%k!M?q>nE5!MWSx)@nAJ{<6epLq87GVpfywbrhD@ToFS$hdyX1E}A%!2M`F zbPrd1^vL7*R^yMCGkD>$9*B3>-M#;sjR&QtV?EGr4mJX3+*kk3r2Q8MKbe|0{<7d+ zfx05w7~DFHPZU4j5pe5S<1v2hd?7`N=HjM|%ULcD1ie4a zf!v6-ywhWRD5yWTWn6vUclo{IH z_Ul7)AokX^#-u%dd^f)+I5S|cH79Pn13KM3<1w!%`un)lsk~`-1n&#fL2bNg8q-U* z{`!0{epo(U`=~Vrjor!C2z@;}j~^cM8aWxhbne7i z?B{y3w9Vs4#_#v@`2X(iF$B|m&Zz};qKWr4fwxtTDRAzJz}|sC z%=z6nR-LZ|IFaek=)7O*%eyOn-NR=suuqS5-yyBbpBm6APmVmUqs}?!>W$d;uZM8Q zO}jJb_mKAX$N0!y_tO%{sgMy!$lvF8Fg3 za!}xZYv3$jH-_=ZCCl5fW>>7~-+F7dYG_~PuL|B8XgJ8Bnh}==2H%&%@^D6g8(nhT zJgP10ePh=%*3=S?_>x^zOMJ5LuJ?X;r>tvos2vU(yYkcH1U}3AxzQTNf0N4?^;_S>L4MVFW7M9H&d9wpa<87`<_CA+ z>3m}rvCVp6Umd8!YXcm~-Idt<&<-}$VtvBd=gG*sHH!yMBS-RMt+v*2yes@(a~JqE zA0rQ(cLn0!{L0JQ^WXQVGr3aZca_%<-vwT+>oIoXrQv)@fYYVHzG-akjZqt7sqW^V z^Y-}Q-##YKhx(Y|=HG8!AH84pj|S_3hQqo+8V=&54*%N{-{$6Z*#dtYwp!tZocNej570i{VAt$UjJ62gTGs!FI&G}S8w;9)}1l; z7VHihFaC+OyN^E|>Oel7ai_`leP8wtt1HbJH6q9Cuz8|4lx=6`-@)c{Zyo((tmORq zVXg7thj`r)X!VUR>lV`JSqaE?ypeJ5#+e!K4>bSA3O{^b6PvXF=gM}^8Gg6c`M)Q? zy)t-_Id{R@c?;IgpRHY(Io|HakHn#J5C`}2v|w(leu)FyA8I~ghJVw$LjR<~)>y8YJY5(0 ziINgvjeREs#q>jkJ?tpFbX9QYxjCtV4Mj*B$N435d z%nl#{f#&Xmw*(Jw zhW3&`Ozvlr_QYUif;h8*ho5zd{h{E-z!`ZVW34_KuLpQId*L+Z6VB%c;@Wk(KPbt$8o`-MYtrHK1SJ+s93BjjS<_d}RA;;v@a<3##v`jC&`# z<_!I}1pZBk)(X9Bbe}xiR|lGU-@Q57`mXIBlC2!>?t(LFPc9kvTUIBmVU~ z`}S@L8n@J!3vwv&ZM7fi-8;o;$&JevuJF z`{g1wJ;UaBrh3$L&m5V?Wa+lfA91)U;EQ%iuo8%`v3u+D2zT-PnJ6%BOx1yWoBKCV z_#%!s1wOCott`LU@Aof0Yy`EF;pXQiAD!_Xi+%c>TMx9>&3Nu5S(kV5(#H20Cpv43 zZ)!lyE)3Wh_r~#9Z_XVG#H}3gq6goxX6bC+$f#}p?how!+JZZCLDuP(YiG%eHHb4C z{tX@LtASqY=S1g+v&JT_dU28O^0(IeeqP44WnI4N4_mnI4d^~2Xlzz8Ru|qwduk0& zT>3VUdFKK@)rQ>RBQJQ?H#YESjnGMsez8%r+0&Q~ih=JIyV-;_gnWGaL^D z;xxwFy$~b&K0Euasv$b<^Ha<#Grpa^*FGV8YGNZ0pOrw93;f149Oc708>a;t8>1|{ z&Z)<8=o$5(m6sZkpUxWxx-Sm&d>rM-kiRIvUGDq&eKh0NSccm`oHB-OO%y=zWbmmaj+0pN0qqP*VO<8q;rlKYvRQ|?w=hT4W1uVW{iE7H}B&a>78v{^`8@XNAR=P7@eJQ zYh|?K4BNG@uRc25U-DwU?E8|>88UpFe<#Axp4j=EqvzUbO#hK-%&t6>VPA~r-+dZ? zXDVM=ef4$En@A7d)(m~5V&HN36kecLpzA5YJG8Sh`5bj*FfF=sTs`*(o$Z_cK8 z=HJ6PlKEVx?{3=Ymsp#(HpY4V*0&y)`TFLGr<&y}pZR* zclnw7)|mhDk~92UcIHZCe0(ac~ndgP?8okEeKs_4=gNuSQ z0&%=E(Dda;AAaWrrv>!%O~cQhnZ%FI);Jlwpx*=5GuG7eN>G1{m-+MJNtRyv`S|&P z#)dWiu;Y%(H(9y1@BZMc*X{Kjhshaa|9@NUv2FP9GnLA(&q| z%ts!0lA+UipN&U@gTY#Wr+Yqre$I33{6^qBUi`t=xs^b>GZ1Hdt;==u!!{o4f!6%c z2lnZ6{?w_j9&@&}?l+J0FUzAm>hwKsEm#jUKC7epEZ)m}erERUkG1=>%r&;yKbhLSB66)=Jnw4l@>!k8 zIbZAFqWZ^&zvSF;eb4E|r)$0=$*I;FBEz@!Koc)AjTfJn#p_;^EdAu#AI!L%=m*@2 zli_hmQd$QL2 zHa?4TGrmpoDLy!g4;{wV=+}EE)&t!1+WO}IZ{@{$-y8DF^5XsBFPpWs?5%0O?VlQK z1lHK9->qSv9lk^D3B+Q5pnc2mvmrUQUv7Idz9`rg%;V30_jNrOeYSq@V5f8Q96Q4% zj^3u-!6F@egwZ#Cu;2e~kd6y7Uz_B{I$6z{wo{$Buk?dFHCF7tZi>~idU1x`-di;x zhu&O!c=jGNp7lu#)&p%>&6B~soXGm`q#L`{%-JV5`b}PQ77zR09^B+f&6V3c*XL%B z{_)Sr(gBO|-@S5Tdr#1Ox_kAVO~7YSP4vv1lQVpAZhv6@o*@pqGiTHK7zdwOnzQb{ z7|=lm@9MPX{?RQzuRTHD$+Jh+9co1uxHXVaX$`sD8)V8h$77N~CEgk(n;GOzV|61cn^yAD%Yw(PW@lYdLd$AEm+|~mPe|~#E z&kXz;gunds*}*qwR;Tg&EIW;%F|dP^`nWF8S|9k*L8kXl-#fG?V?4yrni!rHI3owk z-eDY_y(v&*?lSph_X$sOD}g3PV~zUt0h^$Xa48S5*&m3_tA{&928Y_+JI$+C&!6!Q zbZ?ABYptK%d}9yiuQ-9d-qrs4hAra@19_h3if()2&^>Z6a;klQmqht3`^*&|ZJu*; zwI!x~Yx(rnN$0ZM;;|O!`yI*WD?QGuVR4=Fx4#}}WJVvI12TB2x&49mfquRo$=QQ} z9Lzso&(9iLty3}D9k?U*`Z?kLeW*Vt_|DfcJ{y^(^OAQzw3g(>U58ro$Z)*ZCW9u8! zc#MTH@OO70N4VhT%*Y|rO%CFtm4i64?arL&Gq3e8$5#hhW7B(u%esxU`cWQi0N)P> z^x>h0>fpm#upVfQfpK$YtY-O4SMR$yPV5+8KaJJ)g+X&hr`TOK_31YMoVzugoF%^! z%=z2r!xIA%WX=e1(7Ip$$F-X`CAMVF%-G#=R=&K^#&UU6;Qcdai%+g{OYe*5z-+MeJ8-8(a9YwM?CYn=N#sdv(g2fi-~`1IEJwx0g) z1OCygUi_S4)a&nu8Rs|5=8v4s*Jtww&gPfR=6{m^j%d{Xj%gk$oA=Y56vw_1`cU8g zUT03`s^E-3^Zm@YvG*N*tgX@BH_YrmcbZ?8^WvfX-9H~Y*0?`8`(wP0O!E(qT+c}L zrT^>LvCirE`q}&!Gq=t+x}7;~vYp{l-`VCfd-Yx47#WKNIZZ5#PbL$M65cZ2mdFw`;9k9OcoT zF`XUb*|B%8WA~zCZ*Iq8*)d)7u{hA9wLWow{ofrs);yU1aOR`W-JU09MZ2X)hQ=4*q(agr#nOA}GPN(x z=4(@b-=U{Ny}vzQZhAkis@79lqQCW`0=GbNUAa`YWfNJ@bbK z&hYEorZenVALnxKn902*b9aLr zy^YaNXML=NADW%}lFZeax)PgvOuhSM?q1U+FOSF%g?gvNbuDx9wRKMB&akI^+^qm^~^LyWa zpXluRpJyFUy7&T*m~`|`w9YTj9xm4h&WpuY=e##^(YtrYWRontUohF~{BfE0ZkGeD za5x;kJ8+K8#{}hk&UCJN-ksn48EfS&nbS*WYe1a7JnMAz?V$U`)0*#V)%S>LZM=7v zOl#hr%6(+k*lp}GyxZS~^G5pd*Fp0&RZMxK9|9}wYlOHiF(o3(PcM_zy5 zsc#PC-}<#v|EQ^d^wi%p^Qbln%iI2c&Od}Y`u5b>{K2#N{buuz&79xvE}Lp#C2Kg2Yrmhru-IC2NbaYyhL6va z#_{FTS~>CUC0Xk`d5=lf`I{!$u95w?Y0a<6tMenXR()B%+c)Pg7H0Re2bs@bu=coV z?K20tebd@!4Qv0D-^8Zx^MI@o+t_UP!I z{L*uN(DNS_8EY3zYjXGIKipay@9(Rpwce+4@_9)Yd!IJRhyk6g_fh8Fkr`{?w9Lo% zuX-<^bbMNR_YE&L{`}{+-skF8Uu->V>hGBPm!`+-wBYsmM=Hph)AOUhfBfgof6jd5 z^wP}fylpu1oN4Vj!`eq>t-i8Xo@(Q=Hy+RPWz#u6yyf?{&Xv!rGiR^9UzxGF?=t%5 z1=TI*pB&xJYPaX?$oa6k$pbPoBI8(_@f<@XOZ{$pgUlRY=JnbyccKlkZ=*0d*% zmA`3_@7mSF8XbM3=(zW=SNT)2)_AEa>tuiHw~o(AbN3P1qgQ>Er(TTpjos-PKO;Ki z;IhCQ0*_3crQ7!5y2;KDX3hE6OnW$dZhj-JIqVztt<%0-zWeRRzX?B=`8~2u&#R~Y zXVUYD{N>rV_vO4&7@ws3&KQ(hY#y8*>-?p`eo4wu-KK#(M=WbW$ zE2gyrlYH;>tXUZ)4rxXIlHdtlRsAzhAzs_09 zSey?BS=#)$%2*exzq+OO=d<^)Kx6xjLFdl*p8R6Q?5ew8NzISCzGgOmd){GZ>3e(N z9ACaB>p1%F5$~HGXL`hi=Tue|PGCZR$U7>Yq3Dzccl}H}x-^`p=pAe?RqKIQ3sY^e(8Dh)YreaO!NBn=xP4Asei)MKXK}xH1#)3{gbEumZ|@g zsek;e@2`<6-@H}s&nNlYrv6z||D37+%&C9w)PKg*f9}-J^YOFO`m3k@ho=79rvBTf z{yV0=-!Z;_nt%7yzjEqdHTA8(AD-sk1aY0`{|~11*3)lK^VUc6=RI}4{&*4Z{4@QI_p>E zjC$AZ8T?+LK7aEbTYnzln9H3e_wK!#Iwh};8ufmBY+$?y4;IPuB&w@z)q1dK)vbAbU7CGjP|< zy}Qn+v-aX4?t6muKy%04XM5gnpEo`$olz&=3^q3caw~y$XP{pAuZB(wG+H+_oNs*)2i*C-QyiQphpTpHaB6T@Ir|=g z7d;1q-GTZNlX*PFUu*nYWBfT0>i3nK8n%9himSY;tNJgua?ihczRJ%zdvc14I$O3! zMxObI1K;F$T$i)1uV<`@Eg7x;K5T2c`5kF}8k1WIHUj!9v!1bLUtW4ojrqnV{ruk- zSYxMa7Yu73$Q?YI^J|Hd0oK{Zk)1%4l?m!%BJHNfQ z{paf40eV&f?L(oXHp^4Y_)|`7km=gSG`~K*=FPyB&wn#;m4`jSIRPC<1A2OH^!tPL zV-Y8DJQ>?ZA}5FLseIw0Z(NMw>OjMLo@>7Mjrp34!5O{yTpak0@VMaV!Dj_u7<_5q zEDq#xaNo+Iw&k5aIFQHT?$fxjBikI37kl-*5|G#LWJ|v0=WCx`K96>Bb!Xf&cUQeM zmN?O;ua5fAJ7%3;e$eZ_jra4K%<*N1EM4*hbng%Bf8|hf^?N<*^wEnqIp^`EYwjmb z-jkDwlk?u`-GOoax;o=C0y-AuhCDm&_GoA1RT(@-8DsI)#MplCk}G z{$IzA`5xqF6!yf{*!fY%gC?C>-mEe9>C?L_{a$m%w9a??^Zwjv{rvPk|DD&o3v{U0 zw`bAk={MeMaov0ARk@M{G#oyWc{Pf;u?*-YhPS}TofwRAriTggD z-J7|(5syXZot3ldcxQC@zBAXsz8GH`>nXNMOCO*^1rP zzh&X9CI*#}vkLPrrwC?9${B#er+WY+_ z_UO}2q|awp>qdO|q{i{SHgNta0pI>0w$vY3zb#k|$U1vnz(+9wGS3alrM}RQznb0p zy!o)rxVo$C`x)IQ1_0P!Ix*T@hy|pGb;~Ji9Y2v`nyR(2_-yX589qV+J z|1&dQ#-F}3197BlCBXYr0(Sl+cFs!AzMlW}Yc*rJ?HVoFfnl##6&Fqe6ocj z|Kw_nKRHd@n|Jjx_et#Oo%=SA{d*>RWZBE~ID2BKR_u!l8Mdwn`m<Y~bHKJw4;qfNor`o5o@Q&dT*#p!L4eewzIXj?{O;XpPTdLhpw))Gn*;aZeN(LD zbiB)ZGgk}lj^-{#bW_JzU$~F@{%+FeoceO6TvjutQ)9~=Xg!nDMvnb%`}dR16LEBw zPyZ14en!`}IBK=2xA$oQU-?lEN2W1-qpvHOJ9AUO&Oc7PcJkF-;wwKJ-_hny@wLY$ zTmLlK!ckn+N_|_+82?4Kj%L07)fT_#{O2g!DNf$CM+7^?s=EHy33Ty)Cq0L=&$sIP z-gQVawXV}?t$x#QP0iD#Ri7W8?BwgR?))^R z>&>gCHGAcEN^E$G`yOv(ycWpoxc;nZJ>B-YJmo)YJjQQ#q@N4URsX5c@68ACtbX@# zT(5qgA7Z!?h<9zMJvQi2$E!hWuX-xmw`cToA~whLE|(2TmiR!AG;)D^3`omtZ|Tw!vT&@2ynmq zjQgi%ZPj|<>~+%^FL3sm!CGJ+XL+oBcJ3eS5A5fU8E^mm_3X@@Yu$+9*5}dc=Fe1d zzA~WmIl;?LG$7;qnIcr~?kikp+KVq0W z^R!?!AeYb`_b!S_eJe-YaQLt&AKx?aSPQgq{TZ2CKV@3S;o;M`_QjF?+B!UqYwI2- zVe4Sd%1ULF9)C5Wjk#V_hc`q< z4SZzmwEkLS^Ezza<>zE`QJYb}{r>*j$rg@mkr{2NpGCHA&H6m=_3v=@*l657DiiN} zc{Xlz_wD2NSrZqZVa}I_`g8BRE6y}FYW~pyz18E)Mz9)?^)B6W2fgkleYH92Ihu90 z={S1_9V^+dj)NKFIqJDJ^SuE+_O!!+dwD3}`#I6ikJe9Pl%?%;y76f~D*N=Tc~e?v z*JeyN8{$|S=Vr1f4-wg3A8m}XY_Pr4TUI;g#SU)X*fEEhZmzRY?&JGW{>$p<{11?S zeJXczzTtLjus7Hhh?OR8V{Y!1jSnO@?2LJt>%I4fNbhyAbN7j}aeYw->PC ztE=}07yP60gn8UE@h6M_yuQl6amE8*^(DVuuV2n<{4$oeP5BsT3|c32XkDk<*!oT} ztIoaAxl_#KtGwh;>)8uGh_e@+#96+q268>Oeep@27q{{JSd&q)?aL*ZG!OIGcDkL}E?vNLZ`SAcwRO{bC&w$n zkpPeWKFPl5!;^gZ*8kP4(W~Jy*4Sn}ZtlGQ*SFnw{+WUJEUUpwv$ro012H^1V9Wi} z)A6`K?AbQ&uebM4ocV^c-u_dA)!_7iUb=j?MSK%vjs|$y7mMySNAi%rMrQN(393V` z$T@#&;GM3#wNDA;fE?Q=uNCiR$jQ_?e{k>PS59&13$!2 zE#VI2^H-s4%Abg{&pv*BVlZ<4q|9+Xu!OT;qpt=dXSu=`=zLlrA6jEd=Y1o9XXWT3 zcfqvANBL88_n-Qnr`OMaR|7Hfz5RYW=<~+WcU?f9PVvFRcqhG=FVVY_bM&d@`cXZ8 zzq7u$m$j|Oy`PKsk8brX{^D-0F{PJZ2Tx#M?3?fWwJ4ka&0u-Z=N;G^@SB}^-T1EJ z+m`*9+PtS^*nU73tN~qQFAn%&|B4;69lC!zBp zC!uqU2cNE-`SgUW;mWpr^F1QlF}Wq<`cm%hzy(3;?oh`3epJBEkBfqN-q~3Vn)e4s zMr_z}wmj&yjz{l@TK2Q&c`e_N_0>Rb`Sy^L(0Og-dOw`oN#{!T#e^J=j}Q3w(AXKj zbKowId=r~_%s)Qz`~-S@E;QzR9QV}oJl<@6LWIV6RY$hAYf3)kLQkiAs-EZfqPfF& z^bZ%duF7HewRiTh8LtN9TPMaNZ|~Kd_p&-+lbwe}!MsjJTXMP{nbB|i?5qTG*}c|g zeLg*VV;=Axf9Zg9t7A|6K(2g7)UU4Bmb$!r+CL?|eQWvaMmGOj=E~9Y z$$=VCOX9+IZC*3^h{xQfIX`hb6ghPVqi!6R)!zl#qgTG@q3`N|zQfTc$6);vgVkWn zGrkeq1eqIx#-kh>KcCNAG2Z%ps6CnAKX^=_9SP>&>%?p&p!;xu*O3@h7xV9QBR}!( zJ}GIpZb{)pcDa;)cUq*SOw$if`A| z2+nM)gRURU*nKT;Hs|p=J8LTe9?-bqkE{8^195!#6i4|HPyEYuHDhx0!m9c#6LzZmHoi%-rN@0CD2-(SOb-#mX#)~*Vk5qwdgkz@CfQPR4pUAnZc z^S$3|`J~m3`zXIS;WNgVET83#AM`uddb=iL{^Ied942S3uT10M{a=~(=p|#Val!F- zlOMGwHrj`RqdF|dPyAQpC~mzc;_>L%Vt0(gTIO2U=f2w?@92DgyqAp)Tb~qL?8vtq zJvP`I>&f)ExddCTu$7QiO z8GUvJkH;_Jv64NUP7lhn{^Qd>t6=}qU|%4Hcr41ngR_p$6DB^53$Cky9B8$%EXEIu z3_UkQ&pgJXF1|f+=9~SUVw}H%?q9^%8?qYg6yqBwpL!q4qcMKc5*{at@!wBx#-bR@ ziI^P@$17snHU6lK#YJoU>38=1@Ac`MwQyn96Ce`(nOvZa-y}HKr>!)>myDmQO3TN_S-t~hSUmTP-o5rvYgN#>ZM~kIucpuAp}6qx|rZO!K=aPwUwi&!!p%kfXe_%< zuQjb}c=?&%m^(Gw{c>r%M=p);*^%c1F2KI~AlLF@epMjupBkRxuq^K0gXZ7)+Q;eA zU|*o_0GH;P?x#h!_Zir{I;g*0?;F7HcTRQ8o_+U+&C1YmO|UoE74UcDAlK~6H7?}o zz-42~hd5e)Sg;z9)oR0eG1BMArmW9CyjKG8 zYwl#<0I})Yz;|!*=*tC}lW~U6e5LDt0b9?CEq9>z-uLs>fV|fDj(pWEAL#Mjj-F>v zocozzZ`4KZIaA!yZJxC+Za9hyy<((B_~h4V#^pfg#|Nu{yg5ggbM6RExO_$y`v#0W zoWbKWm+)B0o*11T;6rz9<8w0K0k4f5n+F11K5OFA`18i=o&U=J_0z}ag8anWkO zbt8Y{+j@59WWB*p3!WQjV$ob*o-r=Zow$f8JGkr(aOqp)9NEu~Z0}fQ%c<*qr__eV zcY5T4FLaG{vywSot-a5QkoqR8ceb`xGsa7uH)CLywy(i|GVgKeCGPQPM20lpwO7#s<-#_@TxII_RCDe?aJilfh#F^-3`CMWcWEg!{t zCE%aj^6&Z4e^z?3`o@0r6Q$-~RqQ zi@#dWzwji_`+4OU!!dSvik&rl_Xjw?Xo?@s;>WiAF@BkDzi;&5OXjLzEzrCf-4h$% z)0T0$XZCSvtzI^ropXEf#4X)+jz@0pfp%T6E2#Z)o7?B_zmKv}ZeEY>oP9c$<+Sxk zjvsU0FPV6sD5hh~%6TpNG_fg9@jNY<`%@lgXRkcU<+AB~V|;n${Q1I(Te=g*)EiL_ z+{a1X#Vt^O~KPW90mq0^pt zy2GRWFZ)-p|K%sJzpO3}hZ{fCt=N1;^o%v?Gh{W`sV>xD7uqPJeR|0%? z2l#w-gnWLI?e`J;Y^?@jbV?w8IE#xv3&x)h=6mp+F*v?Iqi$KaeK$KUz%yb?E|2DGT)#ZB z*0rvS>(5Pb6$5S5zvwRPjSRbAAG>Fz$3^da?XPAm4k)w5jvmN}KRvsG)=KN)8=|*) zufFo`I(`1zO) zEXwD88Tb7lb7`L#y2VZ(O?5_o@0eOx8F!K1ZO=WRc8<-ERk zy=Q$Fu%{;M$=Q!2R^lsXm19FK0sXko)$8hgF3VtTJYthKI>Huz{ChZ}GM5DS&+{ra<+dm`&fxrmQ*6kLd1ZSwXl&;E)!wTnE{pP7AI7}iKWDTf zfxNX|$(ADyy8_?!4g}uH-2waLaQ>l*Gacmh;?3XH0B5z%&Um-QncTU-S|Eq^`SKm{ zWqd!$vAH+EhYhV9UNg%z+jMG+Vnx3?8e@eI&?(>YfA7HO3m=-(Q4SAp@6mv4`Hgq` zWaZr#`c?uQKzx5VMA-0skd4(q479^R_gc$x_0l8|XFifGcQMu~D^6^R5#9R(_VZ6J zZhybGCkCTWWbhRu>*XtdIRCe7$RCt5KF;Cn9L%})Em5bZM%o!1y=%LJ1A({bM{-zA z@J(FApuXDw(H-`)y`5uRe{6y5-mKHjH;sR4g8YvU^0=|ROrGz~{KRmke4XJRpPQf7 zO6#gQ!NqrI?~5E(-WbH|l+B23@f0s{cx~+Ff1997jQHft=+l3XQ11!3`s04gWq)!9 z**P!1zb^9P1f%ZJ@A_finV%YLG`?ar-dD8*Hw5a;m`~3C^mM*9*RrPZ(OT=@yDBF1 zir3FfT+?lGwKwu)13oFZBhY&G^-Ipu`?Iq>eCWZ2t@6QdPvBnAZ_k{LpPT7e#!WnY zPjluCvoj}S*LSP(pyTIfI%?P68<*^jb?}VHtp;lPnZaiU{CifQ@lVd)H0iR}e;)u} zwUMpOGhM$ZbM;U=y*IaKO*=Ed?-z2A-BG8r?vwpr++qJjy5GFRS-O8|hy4@j{^cFc z()}wt?4L;YTXr~0_pk1-eMve|?Aj6X|~I4rl59jUDz+r2B0h)02&y=@EzqeqlQ}@hUJ(qpQ31koFOhh*It9|c* zcTVeizu&lbzm-Mr=V*Ix=I#hNjodpU=Uo`(`WDPN{&r+f)}MFX1=-)Z3$nkvgX}zK z{oMJz1!o!yxtO1m!=C;9yKvTbC*PIC`0%8|eAM>`(WicVzKk(n&AfGSBxCtKGf=00 zm@~`XyGyd~EuH(o{vAQSUTpqsNG{cCRBeBr{?Q41a|Rb@oc)YxY)u`op?3JEmi{<` zYI5{zZ|3~s@BTphjc`(f=4|-&7GE!$=IQQsOa6mlePzBOGW6aj2Y01+zVdXubSD3z zNoQ^To7wz-=I76BcK>a&`A^K|FQ3i7csBp^+59oH`N7ObpU=$v9+Q3i-<5wGNSy2M zYcm&PwW5Zs%k%eSUCb-@O__^%=bxE5`T4n9vhF>o+^)=9hh2MbeuDu=JlLonxg%>& zZ(mPFUpZqqd+N`f`tzsWowDz{vfg)n{p!^F&S0))^xh%8+SbcA+%KT}8l|MAC(;>IoGTFIq`P3H4Z)BZL z{IpSKcjmVR&k1VR{n;0IH*xb`$cxXIrw5wxCvT3n-u32^Ux$Ovoi%so>)*I9Ce1k> z^qv!(9<-+0pOH2C;OanI-~9ir`(8P{yzC9`9=JEVg4+4xjM?$N(Mf(hd)91DZavWE zdhwjgk8|-@545h&b>POnd*I&TBrojpwd?rr3F^CivG4pc*+qKi=bP_Sq6ft0!PEF~ zdbKs?u5SlF@WHEhSe|zW{N8#a`~+v~&31R`FYgSuYw>oIH2E5TzRxdb+&5#~=-voM zyAR787q;j>Goa_xz4hFk}-XpajpZq7ocYYlW$l5cvcWpqf zZ)Ww0h5hjiZlk`|1Rr(>boRV?_x;+CKCNrsEHXC+eC4|)zH^&$EO+9uNWY(*@rexC z#>zSyawi7()BnPtHm@`eac8>U{EF3lzx+Qwd-bXDZN0NMLY<8BMdOHU=YT%8Ys>cv zwwibKaB8qItYvuInZ`uS#Dx5%!M@;>3GVEer$sRkC#_uM$rX_3 zBk!NjKR(XS;i=hEOO0p0SG5<CnavJt5N>w{Z^-p|IkYy5QP ztl(s7f=)RcDUV>R~OwMV(l`$Rv&bIO8NYVlRI5irIRgCd8$DaJ5es zkH*>au{=+t26fraP6DryY5Cn=feW6@v?^hdZ2Z^IkeVT-kGs*i2F5xd>iBaf0MuN z5pKPc;vxy@A%X_VYR_ zrx!%lIrEJ`{>$sCjMa&IXJ2j2`-53ylfTa5ZH)Kpr+NK&UFMp*)f%rYeptID@N*QL z&I{O9JH4}qGwxj#cbty~t*4W%voXHkl=IpcE4id!&En?H<6?~46@k_>?H9#a+!|+h zQ_a+G{;;tU@IwsP5<|XR8+bd!Onk}X#h(1orS+|L@6?>Tczqxbc#rMtq^lLEtbVqUM~sQzBJeuIIBG~ z!2g;AiXAni?!-=v)Ct+!g62t$Sre;q&F4z>s6RHz)uwac-0px+&2#VOg<11f+apVl z`0xSGbCV=~;CEA?PUX?wfxzb(o&9W~9&dM9w@3!l~ljU7HUpCcE#)HZJ7J)R?fFu;|)F&5&a-5E3%Y7VyU!Pd`9`6?e9 z0q*ROITYY^d!U^i*pn|@#l^lHu|5CpPcJ?FPD!`A>}MKXV$Hw$&lmab*>Y&l?kJP# zHjnx*pSuG(>nDA%5^Myx7~eXK8zbwui8HXb7Vxv*1FHW}*4}UD!#C^XtgI~q{`0*o zZO0m~GlDAvxx@trv3|a_z`pf60!{qH*;%!==xl3G490zT>_9*t-D}hMPSvFYtG|}i?LkeMh821`|eGbxxJB#x>%X^$ofw4CsFvI^th}C+RZ`jlgFvC z;lFc#nse5D|GX%0UQXFI=8HUd3##kFjP0)l8^O_F{4V2++NZZ?J|W{hfu_#ccPFn8 z#NmmX{fFP}$uT}c9XvVsT>Z57{lnOr^I|8ac;O;0#@4`Ff-j%CP7V*etjopufkp;D zK8&^8_^A(#FUIoJJB!bv`R=Uy94$9C*xmB|)XnkAv^L7IQJryjv-KVAo6$Tq=Ip!Q ze6x3TK(}-1$^MyB?C|hebbFwQ*G5p?bgBWo`LG^T$K2=lglM_3@jo)p|F(Z-FHd}K zUC1w;)?O0G!FhpJK5CEOtwZu-+%L!+pYE&2>gWGjfQvh&9SYbZ&wgdqHGaQkuT)A z9B9=mN0)4_Z27|nYwnoV99wIB=;`vtj4_f&cTlYR9%Q(k-!ab4(NUdpZqBF5jr+}u z`Wg4>8U1@`7Ou?Nvd^&iHpRKWHU7l_W_M*+|Lw#vG0t1_kvApY^r0n?2AAD>3mS| z=W*IQ?Q`7wRll53Z`zBeKR?DMy=sq*F{YPi&KCRPC$D|SGTgLp&3Sd^JPvG=!%f}e zAV>IY1makT9sTm;Y-`uqwZPdiN94r!?0`M7G{%#k)_T_XWaWL%IKMLW@=p)Hjnz%< zn%C}Jex7e}*$A5B^^7$!S~p1Z?$O!U(jl&W54~yE2R_^IVUs>Sijv<2+qz^gR*6>p-B1?@BQ85C^)}18uIWT-d#LK!-K)6(_ZzZjVkNvl`$a zmhNERI`P1d@8uxopx$=};>72U8`muTi#xQ_XAk@Au!pDE;@CTe(|8Bjl+SYApD`W& zo)&(*FIW$>p5>3m#+kvBf-3^{_%Ys3GJB@=!|9vL)@J>5mhWRtsJY%>^74;^xK-!T zjQbvv)mocm<$)}{&WWA6AnP+ztkgQ6Zwm0mrS(G&=ho|6GoHs3FLlEACkB2FW)0lS z5nbdVWr zej>0%=K85mw;hw_m~J^1C$%uver3d)jC>i7wJs0N$+xi>kmVQq&WM>--E+NXX0Nf4 zb2^;2-myE;b88u|24aJ^JHf{IIl^ZRx7N2F2YTd_Zgoh9w_<;AO7QOdnee#`J~+sk zy#vACz#*#mFn?tp)M(f1Bqm+=UGjPpg~h-~U1i;tL$KToFrNN{_g$%V#eXRbC$!&`jo z|LGZ@6^Mlz6CeJ|g}l!F=d*isAaK^Zr-?!Hf{PjzPx{IY@56x}#C_yNZmzp|6jN}n zpFhnbU*%=A*&ME9eeT1ULt|~sp*5K2?fk4QgBUN`%ks7!{6>h+-at&{iB0>hHQe1H zF(xzT^Zcxhz~L3MwfQ{Tn|kEd8z-Kc`S^Kg51)-d&4{s@x!*Jv`?CVP)uQ{UsX;k+ zekCY>=a-$iHha!gA35(TZq9jA!2Z~a-)ewoIkYxfi>(8C?9tiyUXn4NJ|?iw7dF^; z7sP|^wV<5Dm|x`NYFS@y@;2u}*SsdjSY>;&9^2b{LLkKWxHt7T!{cH;=FI(EB;R<` zQ@BW=HOM`uZ`|9%pcXl*>?+&Viy!nlR__qcdd%gEc zeX_SV5L5Z89h{(_)AaC%4e!`$puX5pm){y_hXTI!U4Bu z>#sPBdlzMn@5n)1G;fCdIt%2)sXgu&2Ylk6T3HXYn}bDb&8zsr)|>eL-+QLRxl01R zlesS7C+>2M6OQ~C-#vWQyfgOkglYUn9lh%r)>6I-|>fJZ3LU+e9<@} zn|jVn@2;I6c$>tKKjT~0&l!G+J3qu;F8apGZP)l=epA3-{?K_K7~eno=r|{!SDjj0 z3A8(djerg|I~Kpjhb-`UQJs^OKRnge?m%6Rb1@bFMd#UVu5dgQ=!@py5n1~mF{B54 zI$qY(+d3NWl680KfdTGp;#XUA`^?dU_;tLjAMe%uB0tW1zZY>4TU_MR7?%$V*qPTo zAH;hjkTY>+#~K|tYoi~ph=a>GFIrbitur~icYvF^wXUAWb$J?dJ)iSsS?=+7H|XYr z_j^6i*s@NyvA033;L^J9`*$E~W8I6>)8e-{u}yA0(CFg#sF&@vAV;=qK^|Iz`Z1>W ziQsD1{$22G!JC7>58jr-f_ny61vdt-547?88?tuy=zzZ%#$B8D&9_`rcO>A~;eao= z>PH)Dp>=!xv`=Ok=w1ob(K};goPSg1_Sh9mcIAd$`L%XSa9iMgu}5D0`rdLy`rUy& zan}~@otJgri^N+_^%y=~*BWLQy-uXjMW^X{ougCbKe)#ttGyh(edH%QQ z&pg+C2gGuBuq=LEZ;sgc50f3b&HcUQ#*LdC;(hkeKOp1szE{ShzNb#-4`3w2Yje}cy4r$K3qPVKQ40(FMhbUxZkRxZ4fX{q6X<+= zpy4H+^R?$^ZO)hf>wzX-^o=>af9CwJF89(q!)NWf0B?R=8>oHXap-Vg%{dKKa<7gnh>fOHBEjo+Gva|CVBfB1G;(AJe ztM&E|$hf@40q>(j9B{cP;AeAAk2bFnv6-*&p?FEgIGz{KaeJWI*Sasi+8tZn=Ds^d zzgD@v3zfrtBe*2+{modc=wA;sanQzEkjwJ+{_GA$U%FO5^jq)gsdxLvjOFU-0iO;9 z^zri{fo6@qo+0lZyPIl2o$&7`r}3zxK6kD8=c^i}V{c$CZuHSl-zx*Ud-nE>HE|o| zUYZ3D}`)Q7%@pKJqF|Ur>GuGzk=5ud{R!(XFC%smEW4_ACy=w(sL+T73Yr}))Ao$Tvx4d^tle&fDf#&S@7Vz4{FeZI!Vp+K(na_t@56WBWv zsDaiL8E^dlK>L-vqu!2d1F_&I+s?4%Ubw^b$%l2Z9_7Vtk$m-SWFIef*8@%LRswml z-u{Y=^H=O0t2~~&0)Iba`G~_sftqd1aDdTIF~NcUa_oCFey=zq`|`mKuEyl6o4-#A z9-T#F@x^8QUMPn3VZPV(_Ix`h5L5gf70`dL02i?&%fGp<>#~N!r%!v=B+24vou9j> zb$P>yjhh1V^8@-01oF(z^8y^$s%?72UHggQbGG{EVpF>_=v~2C%-gd?_I?2#^-Eon z(O(g~FE-et^UDW&=VrbZR6kvR63C77c#7rOL1WqXulncv{N9+(8LtPLdZhPAfM4 zk457#*5bZNhjWh)9voDM+8q5I`Hs0V-pOC}yhxs3tAT#x#Qr!}tJ+Hfc@RJCj;(Gp z$8@kEXY;zWw-NAfr@O;uxrnhh=aN8Pmc2REO^$Bu&fwBOY~`CSyyPE$Z?9%7rkb3! zj>!Qz5ZnCKuE+MKXOEob&W-l*b8CLx_fT2>dA z1@`fHQtF#N{PDrXeX1^UnmzjPe@LJif5PTytG?=c>ug@P_7~MH`~7aUn(+r4U-sqa zaKNU%-&Ov#V=rEfy_n~(k3J@+jXB@GCu`}pzsDPI-NUWFFBoUFt*Iro;XbVgbh{(` z)9NER=YTAmdxG_#XI3)SPUZ~#?DUK}-5*&0_3-aKZJk&Lb<$Y#bt9-AJlsLtb_en_ z&iU!QwTA_J0yQ@3Q9tbPm)yAlUGD#rf^UtHThrUa_xeE2$@~1$H%@wS_upOInsfN* z;p2yK*YpRbePgZXS2G?#*EnA^J|i-C`~1WOXK}9I*5)!~>2|Nzg2x9>3YTSajnn!d z|A~>$|2FGDyvgY63;jO-^dNs7FYCRF@`8^T;X^0B&FLcF_*kFxK1)X5ekSu#_djNi zySnISN$q}QHjLG`S{h|mGRN(-$QU09`aY=(b6nW>rjLK7iJtognppMo&bumCz7Kde z*|uMQ$9=gK6KDA;zIYn*&p9$;y%x-6@w4yqlFj)(&VHW#&}pBq&k4k;Hfx8hUw`gS z5Bz&dpy6|NP(D{=%pMs!>Dx)>k=b_-eM?o$~)J6@=p%5-dVo}xgyZ-1oyZ5{JlIl6yWa8=v%)BGF}UC z9N($dEnUve>voh~RJY^)qPo2>I<@+SCtLcH1bZtZe-}3SYWz z4V;&kGXi=Z6wvd6z~_S6B2&HNJ{^w>aHUgBTl2mTj}XUkzGxhg&0Nq!H@oUqZq+$| z@q}@m{kXQh*3ZTNxA?F#=QDD*e|CT;UyRGw8sFsK821y&i$m+BwINsHqQ2DLSU2{p zbx*$KRZfiUJs{W{;H{>g6!6K6gKI%~ihp_DJL8cf z-|W}UgEMA_?op@D+db2IZL($kqQDwo?+p6xnFIgv6(_ye@WUQ1bN&}+O)V_j=N~`z z2kiQHn~$ake0pB|E(z#4KXA^zvt;luS7UL&QI7QT0?!X{W=l-$<9y#hO!x$R={xbX zjMbrjgjkJpzn-pyNq1j^>N39&6nz4NAN8mlq z$1(eIR~tB95r~bLI;+*jwHdDl`kmlh_toBI0sq)hyLxuTLe3hCk;{qvb%q`N$>Oxg zmcyca*k6>3@!TR_d^|5W6!7o%Kr=^efx>$?MWtWM|W zM~<~4wqw4{=W^Z;_v=Z)t~gB|%I9dth4-*^ArE)t((&t;gMSD<_0+BZUcowCu(H*E zUHUUKPq%$uF6byeC;P@egSs~Faiv2HpOC<8OyhS>y06U~$HPJ20C}L(Ier>PeDkd^ z7T;0to3m-3E;^0`>VwYKkA92;p7rO8GM@9E&)M@n@?$LojM;0<*)*0fc8&RQXzKC0 zCAcl{8R|`x2j8QN$yuj&tkXL(7lX$Hd~7XTk+Irx=K4Tew0BL`ofi+B&JUdRXP4H} zC;gjoShR;rb;=QY`uUpLE?$zcdOs)7I>&t@5I_FmpDP+SJ94`447e(SGHBY~}d<`)9)*yYu_hI#Ej>6Lh|;AMJkipjWN%O&;I@!CF9G ztVTaN|Eh^+=ciBl4oALsN#DBv@r+0OANKA&$nrC-4?CJ3w4)$%S!PEgHsw9tJ(r$o z&F*S6l2!;tN6d{O;SyM}k_Hq^3+N$hE*oPbffr;6vo7P9jN>>d$MM=!ytQAwx95E>-{*PX zbGm0%;^R19HO3u%eQ){coLo(RFZAcLHrDRznQM8X7VF2;<511IC;Y~zc#j5+S*$-4 z&;`z@DL$+^vzzsV{uzHi|E?|Xo;&6}_MKxppzpf_wPgLh!Dhe@GJ63Zjs^2Tt55UA z?Dkwuk8`=<8=dC^I`P7u?>$=qzwZ_6zZ97l0`9ZImqHp~B5!W)8lYeEo_jdl? z!b8h5=hC~|?!zkqAJrZX`HD~NPleCMgM0CaZ6nZb1+7o#)mr60kTH2SaEZGMfp-UA z_M0QUI$&39UoqIl#dc6T?Dsw&%6QfMN3yO?#5I-uFLTIR@5IM49-+3!`Kqz=?u5HA z+F+AEUmqCDpFEa>qszH?9}V#1yqs$94%W$B%%1u<9?NS$k@YPGhmKjZ?lGZv=QR&-`;n9pUL9XQur34wn@JPyg>M?KWRWGO))EZq$evow*Qrm$!q)D6V6H+Uc44_I%c+;LCJv zoM-#aJ*hsm_k}jnx;EY=Z-CalyZNM+V9LpKKFaJx9#=SeIcT2vB{$ul=9JFLI^X?r zJ)PsU-1lz!ox;VeZ!LB8te#!^yXFp#^Uuu&|N0#lXX3(>zIjqJWBm9V=c~r-s0DF- zlmlr;gN>kX0o%5$H&*-3{Bnfo==@tJ^Iyo^dA@pU>g&{(sqglu_0JAn>^>WZ%=u{k zFAjFZ{ZPQ>8-eByXuSvS!iB*4c0k9KU@!PkujB~k`kIO;dG;ux`-~d-23C4e)U-P~y-`#88*`kB(pNuVYzM21bfjzcyjaT#0 zKX*fIi`j#R0ow5|KQ-TC(}_nOnEGan&u<9yYaE*$dXQqX%p%UI)kYnuO$2K>bZe(-cWaMl`m zdDZu9<94ol>{Q176Tx;M&ffn+%Q+i(==@^Fhl9o~&Jp|_=c~peub+(knC~|-zb}{t z{B7O2Ppe`P$8>MX3!fT$dC}92J9-}rrW|Z!4JUsj7=8XLne$N{`HT~zx>Dn>1>SC) zYV=pmKG~Ooy(o|~b^3B3CzX3P=v@6h8Hiadz6XebaZQpA$+u$hmTZr>6q3jkWxN%!?DlxNFlsB6rSvyGF?MIA1l!*FRpvSGMl_{;%Br zlQpvVSjCfgap|)|z4?rw3+HN69vlDkjpF}wZ90$0LZ{kPXQN){ThotaycMwBJKcAW z-=~)Qy(8Ah!}9^(KPPZr{n|ekY%b^1wc6z`9b?`PWsWav^6ztLCtw@!QZB{yO2EE& z$cxjP!lwP}fz~tg#q6zrE_xLLVQS58Ux@BX}mz$ly>84hM2$Or}0t z-wm{%NsP|$zi+ra6s_mxOn*?|hF*2xj6c)2R-OD|TYpeYb@Evq^A{iLh&^N9E7%pU zb83XFW<2G0I`^Gdt4_Mqk7iAs=;@SWt@q#{`qi*jK2Bzg5B)(A(YJ8SCqD93ooal< zk9$@>58|I%Q$M}$d@G+gRab1`t?O)d-FbH1WwyOb4+Pq^fDZdt1Abo#*pR!vXXf_k zV2l4R1e?J_f%;-wjBJx*gAQZ4A!E$X?O>E+(;i>wCJ+4WdA&2v_I)!~XLP?e5J%rO zzNj}okZFz3sb0Sz5WhE=&Uv8GGdD={9?@|ta5vP-p}-n{js-ZNpB?u3Lg(G~$>WyH z@j%Sh@IVJ$_@;~B*2wakJ^R+>Wx9@cpUZs1A-!VW4{+lg|Md2{PR5$^-nMfAIles_ z%mTS1(>N>7Pv_Lc(*e8Ut4^`>9Dmge&aJuM7XtrZMQd_uy=Um1p0U5`EW6}um+r@c z>ZhmhXLH8o)>(7)y&KT;WPIx9j(Bj<+N%%Nr=JCC#6JG62XwPDl~YIL#7a)P6`Tpq z2KKd{lW+MaKV6ec>#hI88Se!b zvzea?a7aIy(QemY&$_0r#y6YYjbNQl-!XqB!9I~*-19(lU$s^Dh)wmW_S_G=vt!+O z>{|zVaq9V~$EDw;%mTI2da%wHv3f)J-dw0hJX{XQ;LCRfYwhP5YkilTpIb;<^$s~J zfAqf(u<4geLiDr z;&Ps!tLn6VzMOqNl7V@ky&azFzr6BaKIDZT-cWqd$Ct{=FIjQPQ)|Gv=6^e5XM3jn z(7P3AWYto0kBhxvCotA}Uj4A?yfgUG^Pw_NXM8GFu2k=p*C2++GXBWp2zq zPOk>u68A(cidT(Z4CvB&AJ_3jKV8n&mnm1-TF9_NhW+y7>@-IHp9#(e>PH)E0EhS= zWypzd9%z*@X4f7c`CEJa9No{FJgM&^0bT24=-mjkd+8f}kk8%4sk~Xk=ZTs;6;$Ww zE1$ug!581zw1(qPCl+^~fAajEfX>}O?0@er{;?~T7XtjrWx1kfGZ2%t@xQz6-4MsK zfp#Mxx;8#NiUFyD{ z&&G7C9di8UuUr`8@40~A;&hJftATa3aU>vbjec>G{o=$q-qp{`oId`|0)ErA8H~Er z5MAVs1@yxzSzK4vJ~=i=yZ`<0?_+VF#6>q5y!>Br%4hqvfR1^fxmWbDVNVWU547!| zd*wnr)}X$!b9}ir#$~)4Xn#5W;RO%mjYn>*RrlzN+|t1wed~OzT^!#ZOm+Kw8)IRQ zo%;8k6aVO26=!`Mec_|p*$dQ&8iW0yHE4V>;G0%C`|Rl51^s)13&F3Zmei?tN-qYz z@1lCX$f+1UEBHkIzLWE8dk@C3I`9Tx57_e-+owx!P0i@lw>3GP?wJGb^wraK{yY}& z&%LRCd_6tB4XsAK+&`|Q}qU(e9pGwMnn@ZsL`gDhLtdgkfnTHmA> zGv5iy2RoIehkiM>?o4?c->u5sx0EAGPP-MH3C;%gK@E!0*jc{Io4&rPty#c-^6H1Y z`a2(-3Z`p~b)G#h$Kx$A0cGhlDzj67fDZ#!VqzRw*#vr9%z;n$d~GxquL za!_8KCug5cx?Tyyo4U1J-st86}y^~T5E zM;7zj|Lq1g|Jy(t*MB7>vR}WQ)9}OA>n3UZYmLd}|DJPfT@BR7k-(d!CreM`@f{k^ z?lT?oM#tY>>bR6KTR7YgG;87#`ws_g}}de0Uy@r+6egb z*Cx7N&zjcQEB7NyzukTDi|cYgAD{7XKEQ>XSR1+6TJG_y_j)s9bG}!XxfsYC54Hn7 zkdYtjYKuPgt48?B54QDcs4NCi z-<#KRn5~7(S7)%7@lGI4XDk1D#+v&=9v@RZ8(Cv(9s%RlA-UF}dRbM6IN`55NXG}F z!<;Si-3;oF+~Jy!{AkYgBM;t;KON9f{~L4dyeFI1-j1*G!Z+vmb~rl3TN@{rd#gC= znO{#Z#+QOAkIk+Bo&mn#{rgVM%fG(l z3LkvF61c-S!IK#9VsF)Zk9WGu9lhp!@Roj2ATM}*D$tCd2x9uqTae-6vy<(<4_&L> zGg;URyyY7I=u+>v5j);`|GIuLYwCeLd$r;39MH8DXkwhck#w*_ul?p@GvoSsEaTIG zcktoh{Q=&d4{&fJP~&`cj!t8>F>>c~rQF%4m%eiWeRS~!$F-f|Lg&r&cyf-8RoqsF zo+p+v<${e90WNSv=4_y;1^12*tN0}=zP-SEIS({(^TS!^_+I|lX$-Anb;5=`z8Z){ ztaOj-<2#8cptv>l+{a*d~$l!uM;$gpcy*}ej4D_zs^KLy7@Jst}zO(b! zn*z@3#ZQkp-+)eFzjyz;hwuC+v%VRK4~)e==1RTNy=u=o+s?}0BLP40+%$RbU@nz31b9QzEwfj%=m#FCA1J2pvQ{S-q^q#D#_l-bI zxK(59&_CU~m^JZ<760Up1*4obHuc_->E0?G?};3Lr*9)2M<;uyGFOM`l0kY0o&TufL~VvzVMqKJXkO9);0rnj|6023i@~A z)Tkx~@w?~b_;@q$IWWG-iEt9^54 z*uojRYM}AaInJA-Rp-48F9eT730;>0=k?+!T1y|#8asNBlaAN*Ht8}zJT3_CjUrdpWcYvSx>3c?oJehKXml58Y zalUFi>N~yECw4g-ZN{C&TPIdy`4QKcCvi;wf2yq&{?>nM=5oP4eWM>@8t0#k0AAe# ze2Rk~M}w`vTKCFz_nL2KHiPMWU2XF3`(syasz*M13+92wCL8>q^IG7Y;m?bK^WTy4 zI5`)nb8@`{e%{^7+#A5>d7#k?qh7YvO^z)1c4p+A-mwPw^?2~Z!H)*N9QbcvU5NsC zBIB!3R9gR`lnW>z|q48UFR1;qyVx$*1$~m7JRYt>k{3|5)Z) zx&9lO7i@NXx88XimSgv_ajIjS^VjG3w0|sXv!H$^r3*j*&52(>l=%q0jq_FGh%9m} zug$TX^QZpWldI_)hU3P7yXHy`#W40`3?t`aH+S!F-nsvNpH|MF%X|v)P1nY`^Nm4Y z&Yim#=NFbTv-DHmKQ!^}{h6-laD)(^4#{;?ReP&Nx9SgPtJp5dM3U%B2rDnY~cynLs z2mJ?y_m`}??4A3Y%Q0Ki?*e?_&qKjRFxDKutTm4DZuG94&;BeZm-Mk+y-#NRPR8>6 z(Wi+~JiYV1C*r`jpC9=+_I$;^8t%Ps{W>o`xpR)3IeoLhyDlz#;Hz<#<8R2C_L0E< zXVd4&+ktqrD}g!~>tfw!8=rlrITg5@n}OKnO$^iC=N`TG*jv@Rzm++=lo|WSvW6RH zcLN-$`B{L=7X$p*_x_#>rr(#$_X1~~nFrd9+ufZ%PbkOzjJw-8xj7uLEl1j|ptacj z_Waxl=;Xttp#I>$-|gHde&B?hT(}Qp@qabg3g&@U9rMNP&EK!_YwBo>U5@90hBLaH9r0-9@>G4^p3{M|+O@zrv5G;hsJ-dEGPfr#cU-J$?r1Q6 z9?&D_I3mlAp5J;o)U!DY=xPq^H3zX?8;FUc+->3bBtoi>P&eG#st8Q_SAN$8L?-_RZ zqHj&mu^aHme@mb>OUJ2z54}71*U0!ij`|b>f2V6WwBEa{KK6p0z?d#E!)t+iCJyUw z1RC91_kEsd-N$cripSaJsb|Dx{q;Z-uN+u&|M9UA@S`z2o3YrPr5|5>o(G!zvQ3wB z-B?DOmG$VU7vwTH+0g`dq}E#&T*4ej5 z?$>UM-mxVHc19n6IrF_h%&nRF_IlQ|_Xpy*9F&XdsjaWe9{;WeVp`{0x%sN4d~J=s zsX6}tRG@~`l6^I6Jl4T8nV$;S6j#swrx~+#HL%C`gZOnea^e{M+RR+DCP($>p^W8S zPFt(|*$UY19a)vz-RxVR{{L9SLZ4Xd?M=J$%tdH%`I=yN&b+vxKu4!=1v z^x%UZ-?$uKP0ztvcH&K z>|&vN^m}W$ZjFzceDQ0#_Da^+wMUm8H>>iqo%NnSmhtJpXM%Hd;Kle-K+i#P{nsad zMt>^j=oFh+%h@_!b|QoKRh;#+iZ1+>BfgD%`26Y`pXII`kXyCp&aeAS>zh$~?gKr| zFOJGH&g9F_n>e?JKe5Y=oR?2Mzvy>{59+P{@uz2<_xVruYQVOfZ3On{ah@JF$Q}vC zb^AwyLjk{xo#(SPwZ*nII_@POkvlmRFAmsru09%DtKZLOOt!Vo_i0V|oSg@nyW%|H zqH!7XwYdEjKe+flb0+Keg7_+v;hmo^eB~zxy`uPu}$E82|e10KY#RX!Vz# zgWv}TIb6`$dX&f3BVP9cw!SMMD+lW3@#UPo{Q!5@0%!OvXZF+}{qBu8$XyKFS*`Da z&jI@DhkEA+dyT(3_=pSZxX>!Yo;`NduhzZlemZORYFm6?9H`@R`GJf_h-I9w8b{>L zdEe_tI6uzUjXx)H%?ZENg5Ld{_7}3&{{|wy#361uo7VlRHSxsEo zyKfl&4u$-l3Y>Ef&IY&yXXLTmljEaYemqc1tz&DI^ZD`Z0ogALv`c|{XpZ^@>epd5 z+4DBhqej`n*(^{G&jo0`bZ}f2&)p_37!1+2b2t_^U3@2YjuZ zpS#G7@f=;sG#)m`eKkWz^{I~s0vwkczD#Z5mF)ci*^NMJ47gGg_V}!=+iT6@5OC(K zS~wi+1@y3G?tS4?{T}DylY>>~k7WIY;K$-DJ95gFp1(!w`)_8A9X)){alvQy?`Ee=7Dx2 zcrkG1+c$2XKbJB2=8{h*19rt#d-UuE>gtaVznk!LHrvkK&F(6F;t<i5 z4t?uR&Zd7B*ZOz1{#!G5j(z$@Kg2Z7e=7nwcCYcuE>AV)W-~4GE{+*o1$+=)!hd+_My{xk>o_V0r3!`4P zw}Tv6@a@dVJNsh|@XPnDp9_9Fcszu@6nruY;E!eeSAw4ko~1PHwLqQ!aOV6H|DRdz zRrjCB9FO{gLf+((?pJbdd=DPZnmEVzpn3E;B1T+@_tSX~{y^-m%L88dsFv7sXLf^7 z^BLbe{QUTK-hxpV|HU*9wE5znx8oA`^#Io!%k^97$J#$1-?ipoCv%X8j_=hwe=j za5wmXD`(gB=d(8p+%spLkvrh~x^rD0&*QxB5q;)=H%Z5R=RcddR__1n%nKZKe7D|t zoR)L7(74@e@$=7TDoBY_MKS7)Ew}aorC1y!cumY zewv5t6Ca<+d=>b)YTX*nygjXFy!mX>`>wjKpZbNvlM{d5oB6%Kw^1h3cZ4(X%z`Or zK9{uC?yqKi5b(2dK0l5Ia@zaPp3f9~Z3p=Hg#ab$y7y2`d!wER+^70M|3T63SL2=h ziKRZa)_rf|_eL<*q8hZ;IPP|b&PQ$*lvA{$%uNcoA3MhTbEejr_$e z{x<{suj=c&d*}Z3&1kLDDSz@x$BE@!e6zr3g)y$gD&~>@Z_Zq6KEE#Gw*xV1Z|C!p z&%W0@65!!GGV$n%Sw+-Xxi_AAHFodAz~xD?bMclVXRcS?7V zAGji?Hr*kzxVsu`1@l0wj`?DCJ0|D(awa$%_+9|`;jgwCsMYD(t6Ag67(1Wmfrc}> zoSo*9oII@RAIUa%9WfkOei{NulI<>_^<@234J=$NjJ^K38tqla!W+^aty znG=Cn)#FAWzx496{;6woxez~pd!NYT#{Ou}yJxSiq_M>({oUZ5u6?@rUY&Y%zZ>B3{^9pg-nLVLc+Lc81Ac32;9h@M20z7X zD9(Mz)$0LA2tKEFtvu=V{6n$ek1T1 zrgrf0v&-?QgRffGdauN}j*IdjKlHOh|9>9vah)Ib$o=)DTy2U)osGW!2bu2$awN~r zUJiQS@aNq31=BsXIr_jqe9$kaeE8wzn9lOKpD|gwM_caCk)Zz4-_Lw@ymi*-?!Cj^ z-8h^r_vNNKp!RvIb_S`pT$l!%-{j86yUyt?FHtmX%aLEfqp z2U~%-<>_AMcbBrW74Hfj`Nj|VIDO*s>s4d^c~-a)Z!2Kd2AdE!rP-j3tJ#Xgz4p?9=05x=9SwR*4q ze9quhuKM{dkK^AFsgCJ-{q9}lhnm?6>|F__cSy`v1MiK#pKab(Tv>ZQaHr*5+Yc%y z5AON6h6ihG@$pIj@4`UKA9{#z%X zQ}mIC%K<&rEBEI5yXjrzZK-#>n|Pp~fAWR%X%7DQa=$tG!OV^27$keu`0&@YdB)<@YwPZo^M``o5B|_02i4V{-SfdLAUEbny_oy6l#ydT zk8^QpIA)`E`O40CA3Mj{XqP^E*<*Jvn8w$*aJv)mx7?D&U*Bdvms@q?XDagA8@Ic~ zXO1DCn%}X1HtTqt2iiJ+_$=1OK=xK}CO8}L1Mt&2k#n_l(9biUHF)*L^0B!zZmsBX zrxz=ZjSmO2z}_nErggdQb4@*tpKIp0;|s3XnFrdGEAit*yB3g@FPz}vQb3Qpw=P!u zpGvH3wN9q79?c%#E(iMopK4!a^|7_OrFb}jTU*)Nv zM{G1#WW5#rEPps-@wP7c;yu#XFSlcVQ2S!R5r5dwZr$z{F{=gbQc(Z&-fjP%b$(3Y z?u={GIbL=Gc8$eF=lS4dAosW>!>2RB+2z$v?ypt-MmL1V`Yusshn^NRu7;+B85w4Q4(SNM2$ zAdY#U%@_Z?%_UBb2Ye#OJ{#3hA8uxCv@1vRK$|cA`DU%qA(rX78vTFb)D!91?f#97 zwM)THAg=KqWP0bj^G3$LQ;MrO9XYlx7TjvaKA+e5ghzR4PUYkI#CK<2d}s8Q(~MD$vs_HZ`;t@Uijm@mm8N%maOYn7 z3xV%K*1>&schxp|_SD~~mz~jm-@|^!&_jne4fkYU3C4OD?-e`z*KP&t{I-83pzm@Z zwo3t@#mq-{o6n=I>3wist&HpJzi+vQANSEcYp*Ul_U9=bpU-#}&?oQwqMu*Y$v>Q! zJJ<8m-udp|O)vd?FURzY+4)Zdnl)`dz;$im>|$^@aM#@}wL1?qxsXpe;L9{m_B8R~ z$NoCrr)R~_?zk?N@?;%Pd}MpJhfIw4*27I?_@ct@AR^{8))wuetxJPZ}6dD z6+h17hwMDi@Mc|GRipf2v%Y*6^3&+xud{NfZoe&icgpHv^v+)~)$GqFbD^fN$lXyqHhpemZMY@N>F0&a?d% zzvZraalsF*Yh#Rj;IB7KT~GhsGVVgR0yb_0 z&a*YmgLvF~aj+woy@T#b>y*u@&d0O%YbkW+uLpa9ywN46&Wit`fSvJv%`?~J&^wJI zHkxxfyb=7dX6}6J;&{gMK6ix^ z4)ON`%bwpF+s5Uue2IV5%O|q#!#vRXy^x)by&LnudGX@aU6vdE`TZRDZ6{Dyazp>By(}-jx5&4BayWAi*J^buP(N(Y zWp5s6Y&2gzH@A_dR^;<$U{Aiqil3j4F>|`vq;o%L-sG`$gfG5So-g&&nsH^sP=DF4 z-BIS)Qs(*ebjiib0UL6n4#i5>wZK0A=)lLSULBkd=upqQ0UiJA@b5tPHmF;*N{*h* z<@^)rHTpGi@t+>;rv^PZEN|7tM{DyyQ?K}I?!`3^G`?;Gty$cyt6BV22Y=>)wiD2) z-MZZ^?jK$1L42*9=Q75HX5CoaV@)|T4>Y>jB1azgQ}xD+%7 zzKgwn->bh{EY+#5_yY9Z?Op2r-SqOEpRKLdt(yHrpjp$zXS^TK?d-)sjB>S#LvrQN z`FWu21okwXvB!t;@BHu!&uV3?Q?YB6x2KL;!|XXX4>Y#ucMhiYirc%@tJ)gtm0$Bf zYtHvGCPV*Lz@9yRh;v=v8s3eJyL9EZ-u!pKjk%zk9&wJj8Shr}a4j7~0K>OAJSMHElSLM9*a(O8`y%QT*=NEqN)t`^dEV$SGrpx`78{>I^ zr&a#pT#a}~=7F{oSoeMFpGLtG>7Abkn(tfARJS!}aBwC#8ys3f+;oXsuTK5hj=1Fp zf6e2_5qsXtrvkAUlk450Z$B9QmIrpN(e>V7D>$f}TEMLw9}cwn;-7EE$39-6^71D3 z_Pz^T4cMLs8d+!cbe~wxanksF|0LsnsGI8V8?QFsu5S8v0{&@N0-WPV4|t;YbkN%F zKA!FA&URVjwn+O*w8oi1BzpNA=Whxp3zzPtTzM2jt}*FXLQ|*z0#N zXZX)HUB1iV&N@ElfkubVRXtACp>yKE6TL46)uU$51$5%8_WooP?`6&hzRd$|m3}^K z2VyFh`sP6Yk-(q7JiU?ccR7IP?+^ZJ@DBs)h5tXO@eilJ9;Nt|TfSTloTXo1y~g-Z zXU5;W?2Xr<-@WAeTznempBMZ2-@>l=*>x}2#i6yAf}4TQBX*w*rvLx&FUlG{{S3R1 zv3xu8c%ZG?dw_q~%a2@M4di?tXq7*o@hot68izeL^w2v= z@7?r~Js+G1=yL~fsNQh;^9g+9^ibwpH!3vGe0gJDvaKWzDd| zM`zg6ci#T7tkr)yN4@{!Qjgr@$~!I2QRW9Dlm9JZQlHa$tiR&wcwJ8~U1EAIgK_=` zmv&b9lJFO2{!nC$#m!%K)YkO(KVpz?_3Rx`Pi!3y*#5@oxmTX(7SqGQx_GRQTzxps zjdTCKj&c6##ID-o+h))^qPETD!tW%sd&#jOUjC5no394k8GY}Ndwns$g*IRO^EOZR zGld<4$B6*nxH>4OQ$D90kDU1rxsCH*jFEAEa^O^~J~xgA-WLAj#hl;9 zdbOkPy8c4oUe5yY^fLq}a&s<-sRfVy3@Ptqro7k2$lW^L`KjFsaCkXzPMyo!a{>R@ z|5WZ@`QqFYDe0e)m4&)11Hf=)C>;tc|ro_d6BKAD+bG zzuz^+_U{a_sJ-&)j(tg>@flh}vy9b{?>XuQhhp)0)m}`y!QtRX^Y6Q}-hB7IjeTo` z9KGiB&I0$oHOF_H^OFqw^i1nc-Bu@Adi&XF4DRK{fREaI@z2}$y?6Fj*5pI%VrE-j zoo9Q03AXq)3+N+vIjAlCHU6&Y&j%+0_sVBz(sAJLJAEto+VQF$k9^~|`u>#|8R!4Q zWdEV;lf4q~TO8^akF9~fmN7oq#zSKp`)9JQiSt-cJ}Sd6{Nc`fJ`3c!TsuQIF6kKi zb-J5l@B9yqk1)?mYc|{*m8VAP3@+ z^TR=XeJW$VvLj!(UKOMBVx*VsJkV|g;>QEt@x^B4#(Qi}yi?mxX6;}S&E8HR=KAXFXp1aA$?yg5{4&R}zI8?RVt^NIzWC>D8}_tYx4XBz;iux%s=K*v zO$;9i{M__d`Vr2I^HpQ##ehftt1q$1`&J;oY8MydzWdz$&(9by?n>*49`g93Pu-EX z);py?AE^7*GF^PqKApInKS*4@ue_bO@HCC5u^uF@F<<|7bd8X&alUHo{N;cx@#)Lc zw`4qmzHz>4d?+&Xku6`w?!feCf-le73&95i`F8K+o9y`KL-_F4YzE{;e#pAl9|+Wg zdvh&l{vXa*KGa`(HG=cLbIrlKvgW;$!|maBm2}Jkcdzx-`#ruz&ab-PWNHs5{Ag}_ z&&7Q)U_+ZP{(1X;+tY3Z?BiJL9qXMqo;4h}V||yaznqa}UrzYsJ#@xeW%cKS69FFS zVs|6Jf9>_Xn%+^dt&7FpJE0?L7JQsZe>Ny5;%aQT#69r!Y9Q8mp!w|a7Bxfkc6M3^mA#O?e9igYS$aOOjl23H7Waj()h!nO zR|gsLI1{6}xVHl`WG@DX18u(e=k5AveBEPz{Cz`h?`Iw8_U7PLZ1lsud>Hvy<%@lB z)!+8z2Zy@>KW_{*do=UYfqq)AtbdTq8wh{C##q)OrYJSw=JBelu2XynNbuE5lwQ!I-My~HDn_sh>^WFT5 zgE5ZRGuPCjbCr86W4@NlX}s!xUA*FE>q1~GwsJO&x7>fK@#2i%cw*CMusPq&jkWsf zZtzL3jlNAepi>^@-y8H~a4w+R_w#qM{@gW~^2)Bagw5B2=Ysz%5Zm7fru=SYO%oSR z8#lRCHTjpaF3yn$K4{j|_0fQgW?Y`i`M;GlJhQ>CA6kyr*=~*fv8CK-ySl|o*DJx8 zPjhy9=JkxV-GD!rgVx$q*EcU^M!)F7%V^{4mU2@Y_@r}{jdJnjOI_1BJL0(#*c)|t zAGL9&@i5wjVf4##tQjL6gr>-ugOud)|2V=)))9SFQ1r&tq>4x9jJ@ z&-gbohM!o%-S2qpzjRn{-bX#ojo{BXUo~zG;o@UK_2LyzaxwjR?s(R4dNg3e`>)pY z*7VNn=~z`8mA#Pt-^_Q56Y14A+14bVzC6&%)puol5Qw#MeC3DyvfJA5j;W7t2;8YR z0?pear=35a@%TOTJ(<%(ufDN%T~4g?VO{KG8~ZF{u{+b+Fdk7^`gViE!IupG?wq5U zpAH@hwDQ%QyLVvT@w#4IAU z&38|CiVgQi-<4~MJQc`?h66eA z#;753bn{7nKH%qQ_hRPqLx*?88NSi`K)~Kku(2G|Ro#`VeRKM!9N-Pu?f71OL>F<0 zzkc7$_}hZ|v$q_}h59%f@E4kszIlAYjW@z~d<{=q!Pf>jsJ@Mi9}eyhR-MDMbJcx4 zV~s4;&HWE#EM`4CwCulPSo`K-Oh$e2j}PVfRcpa_26$5kqkr=BLckWE)wh~2Z;e^K z@cYF8ho2c(!%N>6ZwFoK)czQwdqp>U)^VmMw;gnk-O&!8)W&E>e2pc;JHIEsWs-*D zX)WWnv4~Zz?FaRpA9Amb>%*a8ekxl^)sCfW9RAbzMpx;q;(BPWS$S?2S1uS zR2^)}1-|jXKfX`(_b!t;6Pyjm0$*{_-uR{9g>2F*4;s7t$BCM;C;q*_nR%eucR%KV zX3oAGoe1c|<>*JIi+ZfwZsr@oFAYCy(}^Qo)TjE8rN#NVLE5;^?=imeE03Fjm~P*x zLyOu}pKNQ++Gq320&QIL^D7Rn26(@+>~SeadY`d4us;v9F;3@ye27!tw}W>F>Pdej z!1;3lefSf{hXYLVURK8NSiSE*Xv8H*4v^MV+XXg6)pi^$~fC9+kL}HF?mFTtAX|LSE?PJDnp} z{Qlesd|!IMfqU6BM>VeJHVGS!P&q$@4dQY-<;1qL$+)3PS1FLBXiApzG}@;;~4$L zjr@?+^GOcq`CsxT%V*E`e)I3Q{U|z|ZRAhdCep9!IQVEx7sY<&t*)H#t(jVPYl!VU-E{ITftbLY*-(^r{5T4 zMp@&%p#I{Y4`VO);@A%G%lE!LTO= zDWIqKYJC53p+5S(qc!ViNp|gxXXzgAcKPEM*}L7%Y~QKP#@ibGSoZjLE>Le{J$_5( z{PXs#^M|k70sk83(Tq0(KFZ~h0N34b%(!w6%DZ?rf}4S{^^VAFZ6g@Hqvhe&UmlQ*~1N;VqW+8*w2KEk#SG8a<0a3A#Q$+H8Y*F zq2_yrtTku(qumOsTW{U|R|ndafX|l${$2{iEnf3g@s=Yp&dU4r^T3A<%d5<7dw?MJ)Dtt0Vl2j!OC>w&ft z(4pN5aAVEgITM@>Z~`9*WQ9K;2);0|E-zw|7xD28e`=?^I>Qf~((RmmI3Ju2_+g!Y z(C-fR`CpEYWGrU=e&BP*K3gN#YU0^I6BBv*>mQ%NXPWbBQ;m|9SF)>Oqj&V(S-$t3 zl{fxbYhOQSS);qYvB6&N77lUO+{yXoat;6Y#j7XM!$zR>3~tXYR^GaHB5Uki4aD1+ z@E{I7Zux`@d~OBh)1LWWfFq3_G1;33nlnAW@)T9@?W!rHX<_=E>O z(ox@L8S_o->{f^Ip@8f>(2Oqy_`S{Lg9|%s-3{Uz_cOhtr}5#jd16D}aJd`s<4+8~ zQ!AfYUT~z&)wnpS&*vt-`09LXZYswHxg&vgIe0U^LyPwgpZw7pKfcsyxp!}lP3B_K zdgk@p)8BJ$s%Ojt-(L>o)wp?8AJDwkM)RUpN65iAH$FF6%XH!E1L=KV7W4gqIPg0D zomL$A?9)FVl!q5H=BpT-VZ(c+cKS1hy~ZSV?bhw?4p+_NSQmU|%lBsa)WpqSb)x<0 zp-z0(oC?_I6I->rk#V`iD=zuiyNfS2I=9Ex*c(GRXJZ5%<9yXPB6rRo&v=CM<9yZF zd4BP={_*KULH~Rk2XyTPe85*@ZyoJtZH(7>HSMlBFK0c2FSrsoQ(GGuZw2y0o;^B_ z1dj**EW%HuS2OcKyAjZ(mgI+@#?G@X=W2j0^>}&N8~1lJ?!Vakc_$Y4dOK(w0_z%m^wOuF>R9D7xp|<`wGm8fUT$hv?d&e)esOqrT5EDFKKbR39>#Nj zdwFjB_nXfmqgKlUd$<7cl>heoS)+3nh`-+#ej5x_VTmFo3 zp&z-}&U|{;_(gW=7yb1M@1xDm`NoH*0zQD6rO&wiDj($YOCzH`>Z|+Far;$g{f?i% z&f0fB<@HD)o@>GV0UhMb`E0JX%*7|q-c0Mxws!~K6=;q7#f*0XF|%mky-OhNLFFAGATgzwhlykm_K|j@__VFbSIqPQu z+tWDuX0YYX;%YB&&Kgd{v})ek=>A6JG(7Yi-=MxWA9!W&jX>jDjH-{~<&hgc_u^q}7Py96&=XVC{^8TgSqsJS>|9OC~)`5J@mTUD} z?KwjyzmE<56B#Scd-?8ceV6n4Ti?aY_b&<7`L6!?QC|0#vg^1ZOXsQXV)X$pZ8E-CS=yrD0+xTjy zb37Q!DWBDL@1>lZH|Ofb97p8EYL4UjaVldm+Xwq>8j~A)_RQ6ic#Y}wp4rpN(O4@x zSr_BF8ae2@CU&*XzPl-IJ~qCw7nA!j3)nXA=W~V&Kk=xR`6rL}@~`KeyA`zeJ-B@G z5jUFwKd0*_vqt7ja5kU=DwpBnUFti6SMTTPKwidkPiEe~qjD)@{#_4nBroLkc-RWo z$-kVv^1wItaQjN|wES&exROC1@)&jy(%}C zBlj-^`U007>)9M-GF|NRORRcm4a_q>yj*jhuly0W<_uqYAJp&Wa*aG)_WMqm8`CMa zs{tRc1kTdudrxi2S=TRSTps$FpqAvDOwaJo8b0Y`XWWw`d-AmrX#C(CKPt~J=N|~v z-O<21#uokJQg375nrw|X*R#lpd8|L@=%3b?_lbXeCeypXZ`}Hv=o&w))vmnZOr1O% zXg31-)ab(j4%eNpzhiCgMxN~-9eyt51D^3W);Rrqsva@$Z*RFq&-DP0a%g@0u8U86 zx5tg#h-n^ZzMIfbZWhpKzRGTv7x}cWX7%E4d}1^ITZwHay&N?jobgXRO!=~gV}9}R z*+9ef^t}D+fta0Rb*(*~>vw;z$!}-yub!HVdBz&9ol&!5_t~_uoF7W>^Y&bz z#?-*$!J#;gPw~zJZCW4A7Y@hIJHF8Ma?tuQ<_CLw!+6XmeU}3^<%3>+xnrjSv1#)9 zK(K3)_D_bp?VXcnaeh-E?vDj;1oW#*?fZfpTihG#8vl%^=j`!G`^4?;KzgRJ@dc+F z;r7||xF{#1toPbGs=md3WQpe0JAjMnyKr;4CiYn%))#}?5Q93B6TZ9>$W=d&aK9he ztBt`)!Y@LW}D`1 zt~UaWEwJ7i>hBbHS)pn zK0UU1I>Nv`N~@73)|Mjrl}uitsM%^1ZRWp;}bXJR`Ka<;TkGZ0Y-D`of+rfQ7-$lBN)wVItE(g_5*Fj~SZ7k{&ht}{(AHBH4 z0bh;13F>q=;MZ%zXQH~~FCXNVjP|iX#^($>^us8(w?a;y&jlv}=g7Y==;sw3^-1p@ z>K|J652wEw;6!Y*pzng%NBh4q{JrkR;tYNAf)8W$C^qr`x#gMh-Nh3gdY1gEv-<}) zdo*X|gWZnD+E*uHz|C}B3~B^d_4n~LF}gdwFZ|vKyiq=9J{qWPpV4f%n;PBxl8@;+ z9e8*(pxbyakgu`c=b3AC&kfT09?deYem#H2Is4749uM?*C&a6!e{%S{_{TDr7yjb1 zF}c@rNjE*?9Iw_JtMl#xIWf%w^~9d`?+*6LKfl;CXY*u0r`}zv4K;3E-+N-truXYz zA&y-f&Vs|i^z%~uxW5z_lkMjvKgFpQn`3@iyA_-X&MxPCb+&mW$4|Lr*O{H*&~i)` zZ|>AQ(7Io}m970ZZi{`&-=&U(k9l;kt=HJ(-^MUrWnb=aBsXgO3j;Cp&0X(Z;nz8riscsv-tCwZUn<6L8+_xpl;y#H?ZuV*f=`$69{afn|&^w#y8!KiE0 z!B4oC9(kij9Xa1QZux2r7i3ng(Qn=Pd7ycl@w@K(n)v9WTb&v=zS^ii2a$EQ-`B)k zzSISMc;k3_-eF4Au zOh$s%Hn7#XguROq6 z-z((9*^bBi>azqVxS6iYhZ-5bul@6DVsuBvsHqF~9$xmxmpvQL2Dq9B+IWx8WbU(% zU3pL^awG@z_50T8<^1HbHzy-6vp}Bq0`Ix^fek*X!|8Vr`f=GiKKiq<+`EZ$Z{gRh4JZw;=<>e(xI z;t}VlkNng(`_}_;)Q)~L;O8pP>#orE_wqJ~iLbpsKby63PM5!vBxmXgm)hk3mzS13 zKiIU^@jPP}urk)*Sr%gS;G)$E{qm$xds*_*g*4%|L$1;iGSH z&v!3d3q9hf9`a(E))5_i-VD@A_a9xZxyv{_vV=Qn+@8(tfGu*ZaX!5m;L{yy-tZvS z={+U45s244ZGQMypWHEiYIt(DG(OPFrdV*rhI6eSdvY@77AJm3QTchs8XY*+YTJEs zzxh~B`MMYMKJk@Zd2hbS|4&1{`Fbi)bK_a(pmES$+q)Sz?n@bqo$vL7jmFV4*1j)@ z>ECTUV&4z?9^s_w5wBqfDlE^wieTtkrjU(as0m_npTbQ5)U?oWm$H-lKBZ9Jw3h@ks8G z;2AL%tZ-{_b+Ewa8z3a3g2U{o#zKXZEtDuI7POu5V@BSop#Icn_`N z4tgi$gkOz|J>25V`uO?J<}4ti9>l1g$-r4T?v|F=e2U`En&+# zu5nd3BPS;U@v0%MF^wEeWpTmpX>FFXL)l}moYCLds=u6hpKBmR$ zOvW0WCj#>P>={0R{p&&fXP2$h!6W6V#XsK^FSMOb|!P2^Ow%*;u~G= z6JNyQvqY^v9{h7DswecpJkaQ+$Gw7bCNAq@u!ifcfIU8{PpIvuGq#T>ag-;y5qr7n zy8F~P55k}N;1AvM&kyz6zMPmtx%ZiIDmWJKTkNj~n(xK+m;Sy>xDyMX<=|Ri-`dMT z{oTk|{O1C3)#k{*J5Qg+-@TyUTkVNy^!+`V^OFvoHiQt;;j@<#*mbmQ6H&A=WX)wO(W1o(&Z0XuBY15F%q)9-)$ zrqi1H@OZ?s|lN+5pzch7nDwOfI_v5)IB!Px-cnzQU^ za>$P{Zn5kIPXrIf8UByID`;-|W&vNxI76O&cToP_g+~Is()T<0 z^E&(FtD8PK_&~4~$T?j&!dGJyH}Jvzp9dP*)}ENR13LS=KRQNUGhO(0GCiOAIZ2Mc z*8~2t94_T)C%|F-5$9gevyHd8>-%szGR}|ZoV^+?Wkm%kcY zbAz<5S1%c;Kk~^ZIi;H)_Qkjv$We1|E{BcV{jg?!E*L+npUGU~qgb~BXW6qx);aIC zd&oY{uLpa9J@xfydUYh`RorHI5leN6i>+%x&xl8BOw}!Ce7PKaJPi>a1A4zK(A?whJIC(fpt%u$?^1bF-~4?fkZUpgOuqBz>BhTp_3kd$ z$nt&46MdRN#I!yk;m(e$h2@b|zV=gs8HDt&ZR zAGvk&IupjhodpKjwUA!4|osZh(V3b$ynp$LM z+`HdKnzvXE*nB?dXUU5h<5kXZb{<_#s<|N3H({n&!v}pJ>aV2_Fpww%k+*OXDSG>gT_-!YkaiSrdu)fO3JIp^D| zcaU83|KW^(AkeD6b>{mHJ9y~Y(dF9n>BZ>X)x;#P*2rr;<2w;Oe9^P{2LcUWAJVk>ewo&7k$`tncyO24~BSd{m}gp894KvfNnbFs&(8o@oWTg@$L|}s%Elv zCqJ!g^}vq0|9C+6LrYliXC~czxDjaNtK)RWZ}+>~$UA*g9@zW2aO?9_9f-GYnQ?8) zgIw(eF9ziSr=$OPrE_}j<>eXq&~DxC?!0OEuqQWkA6kwtrEmVmx>hgt*yqEJsZ*8;U5Px_wc2lT!*u2uQG5;^T&Ipeqb>ic~zW8CWxiij@aFAvVk zTm4hd>}&^`yCOH__$Ow3IztW*^FVWlt}jNn&$$=wmNopE%ab+mF49%oxWW%P^748t z=zZj~eDKYB&&iEkTI0|D5_~-o&?7hYtvwR(Lw^2j^0}9O)tkT;-Ol@am$io@Ib)N( z^3Yt*vnEgWE(dIi>;9lVloNh*jXiQ3!RQk`^FYIkGxyr}7C2X*GhFyw{rB2G6Zx|N zTOdX;$wA}6Y30N=%8hoNEth2e;gU0o` zUiO^-+Q8@G`vTtyHUc`uF%QHfp3Q&{wWqh&+M8vp4z$sxzk5`l*V%Ng`sNvrHr<1J z*%aFYfjG7C{~KDKa52h!$KY3G#3$~?p5dLkDwlJMY4gQD-}LQz=JMbyf5|r{e&O{i zV$mvcUnC!^N* zDW77nwi(O=t?PW6TS&thzc)lR@9g#x52* z#ZI<0&JQ;DUfpBt{OX;OD{?rbOMH(6IH2<@<0re~;X^s5gS>TTa5UPuk~zP`Q@`j0 z{IFSm)RoT_O>NRwp8S0ZdgZyXkS`bH%Yij<%LTjRcH}csaoH zR|Vdy3&HUKw|%qZoSkcdJoDXs@E+_2_I_%TbF%iy@`cXoW&7R1k)VEMxX>@p&N$mW z`mY9Rq;JIajO+WMjBzo(k7B|h9p?gi+3ox2GqL`tx7J)^y_>y_$ZOuu+7#mtT1>+o ze)_rc-5HNyYn*p1Pv5ZIOSi}ypXt-H@%})bx+l?;#lU}L1TF_ zWA%G~@S$K8f8wJDkMycJvUu<3%mW!~c-jl9(>b+CzVC^5a4UG;TJTPN)*Oy54Y%cz zf9$tD_$&_gN1xO{W9l14N4Y$eu^82-oQ^z*i+(bA6#GU%Pi@GB&kB5u>zOWc-t*3l z??c~Vb}t3f&nV~A$0Gq59Q;y#r;=`w8+O_B@1oyN@19#D`}0|=K7NkhBi*6;;k-KJ zxA^ezzCc|ZSAmjJ?eLM z)KBhGu*wc!*zuWxkEtEp`@7ALrl;e%fULV{ely^AziV2<4X(}xYAwe<<|-(RU-zM*i>#?l(VhO`o`NuBOfecp`^0H9}TCaWH;=w#M#eK&MzVemJuq z$c6aLHTuX;-#WJGU-i~Gi#tAU1llw%zPdN-d{uK-0{v?Nf7#OBxZN#c7x&eG-0RDA z9M@m%Al@u$n(vFMm` zr?$5O@$vg0F};(1$p!BEeY&;79~|pH68N*bi|MCuFQ;qcJlk*iTw<$wSgdMG{CLL+f9*lJx|uN< zcJ<=M^(>%oFX$cVeZbp6?!&txr`-x34?aJHJds|G=Ye)37Z{J06X=2Ao_tZ__1-WeAjrpsuA5Ue>5Bk;R$-vqFm$^HE*ZeH&gHPs! zFw;=0G?^qWFlV;Rl3@uX5rOcGGnqJ0EGh{h(SV)-W)P9O6A%aq;=V-cuC;bS(JE@y z+FGSnThwYRzP8n>MXeiFUqN3*DV_KCea`hC6J4PFYfN1 z;I9SF*dxCqXze~eC8dezQz0_W?;SVQ#D zu@R7CtM|ue1z!73)RuVJ&^Q18t2Ux)snh3-{PFcbfHU^-&)&$Pc*QmP;0)f51avv~ zia?w`Tjj(#+?@_uV>rbZyEwEy{uw~$apTuc-Wa|BU3&VC24wn~rbhQq^K{EPr(cfe z^(0^X^I1@y)u;H_u-?ykb3W>Q*67*PUmeH|JG%nDnbUbJ5XZj2x-)#iX*sioPv_~= zzcO&n8DQI8^c{$g@`V%48KBS46`q!!J`G3n^?o0*e;}aSdvRqH-h^NpLVY6v&ghx+cIo9>qo%|LJf1r!$7~eYv(GKkT?$nwaEgzE&Q{Zv^Zt0*!7q*vJ1z1SbQr zzdj%@w$_MTHEub7Y9OA*F!p^{)xZcj9OtXXeOtulj%ddN{P2|z&hZ&~KjlZh@XaqE ztM474n-9&=^%?I99v;|R3)sc^=m*>Qut%Rd+!-fU)uDa9;Ei6KTH`Z+_J5XZ%vJQ_|6;Ja!uT?Q@o1K3k zb9(d#gF^wCjbL7baz?lNhA%vb5eLApT>*c(R!(lo8hzrbfBM$n<1>D!kRP(zmj3~YR;N-@>9FzM!f9tsa(wYsc!yNcYU(P zuil-b8EXdud(D+|AZGWA4LlzX==$2}=kDI|eVOx1kDvNlj(Q$PbnFf25O3`{r+HVl zFGrg-Ef$>c1t+Z`x(az4eS60izOkp#>F>KeDN2p+5B@6P6FbKOeAFlVe;&AJ_T8VK zoyKCuoAsV)Ox896TrUC*p9_OD^5W6hF9l=rk<=5#z zUiSxL_oiJHg*T?>%OcS33L2AG@xn&m5pV16K%8Tpko%eBLd-CiXM_Jc0(GVRz?3_= z_I+wkz|Y?IlNq}c?!fkdUUfjG_po)hKCQ7~kAL>m!LF&V-eZ}Meth2G2mRvP2rADH zjqZg(+JQh!I|F{t>WFg;JiHYedKc<-!*f1)bL2(7$bhjmaT()~PsZB=xi@}9pyrI_RjnA~4==`i z#62CWxE%jG!OfAHbY7g+_%uH&E?nE^>+!&u))s%~XXbZRorzI95XiqqclpQXk8Htz z<;$N~`O1Ix`A-kKW1RToZ};Tw<1!bIJu&bNkJ{+l#catn+w@;Z*I0|{#GAA&|0f1{ zWe1-dLG7O!#?G*TKmN9M*gPEA_vhf}oG-Gj(a9D$=h>sHXWzWy?9;PP-r2R_1HGfC za|ZCfCz$)DM*Ep@b;jy>JhLlvKG#>V9t|`;*(cM@*^}I&ky@IcKJnrg+;#p*06AOMHN-V#2fmk-8!@J0j@qOgKxi>>EF16p9Tc6gQ zlcQCC568Lf!LdNS=91IQxI4f@#i;-{NyG5O@(%D+TFJATDN55apwz|_@DSRZ}CEH)Za-n;bVc?7q`N zn!KI~?DccH^UB|xJ-O8m1bld2AdY@dF{XF?o``Spz9x{)S)9nBdU!>ELvC#Z zfA2sFU>m$JTYXfg!bI{z?KRW2r)JFNXUt7-a48&{w za6r$WPIceArB2w?M!9!waX;v2?&NLNcTE1YW^2E^@}0f%k(>p1#?g%ey%Fyb+|Fm$~N~KKQZf?xAN*PiighY12NYB@$=%6tlt^52FUPxewY0`hu@7M!*joOpu0Jyd#iZy zvnN;!_=eL}zNvrQXxd1SY-h-<4@#O5B;p*bgh`ZPAjIUF6uL>*l-%db$n=*8TSs>Z?8c z*xw!4uiSS>j-UJ;V3?e z%h`kLRvpQq{PUr{nwOVXW~^p*1{yBsu{z5hzwPV!5IYL9%V8; zr>DL>Dr@So+;qJha}-ujCG5%it6hX45;!b5#r z%a}dfH4pC3=x1f+fIWQE?d+&K(`BvU;-!K2<#gb@JZZaw>Z7Z7j$FrL7N^|#KCgbg zt=9$Ai1WSqbM2pzd+TmGD^GNnE4rN(SL<6`e6Kt|>kAvs(~lpV*c)p|&GF-Kpq{)_ zjg35;eAmeB3+Nj;+Q^)(lK~xk!Byj^zAP>Mp@%=X@ZRkW#6Z4!*#LUQguCXnHTKx7 zvE6v}WO4Gm09TI*oZCKuZ)%&q_I%hC;Ns5UK)@ey^OL`H^qu23-)i^C8MC_{jmDj6X9V`;0*2H=S}Y`j_dFk5&HRSX_O>z9i!j z;u+`jF`HWT@Xw#k!LhjJ{v6Dj`rtPn?5hvGIX$}rwcxH?6WF8Anbv_EZv^=5J(qJa zT4Q?=XkB-HVIi&gQ4`{SVz4jZL*G008=u~JIiUZc#!Ig@#`%cM#mH{!WB%uv=J9Qd zY~y&S@jZO9aUwn6#o(+MdQa5$(ZK%A0iLyTP+sK7+FEc)aDC8P{D_SA2kg0DeAS*1 z$b(kd!x`@j$f$)w)0j>^v<~$2>G>pfckH^rSsXqt@8$0W>WP1aUl+5hhWJAduH}rc z?6i)&?`-3QjQi$o)0$&c6%?Z zsUNmryc6PH1RCy~9Y0g7HwM1fZ}!=}JMiB$9X~fJqfT+kUt_%Yey{^{Hoo4A^{mlv z{_vo49J1+*&&<(|u^O?yJD_{qr$gHj9A1t#{~W>m9NxVH+XJ$rf7K@j`ozUYIl`k{ z&@ImK-^r*?7t(nsXXqpYwMF0D$Lguf<09kiM$j7JQ)`58cx#RL4s%I>Pxq6)RdLoQ zby!$BYjSdY>c_ZnpoX-~ciQh7 zZpvGeE56b>a#4{>zO`Eum* zoV@+sM>grD^P$#P_2kHw_2n%(6wt5LhgEr!)7}?c^YK)`M=|+~*vd!oiHF=;z@B?7 z{?=w~uX-cMjQebBW38XgoL_Ry4|l?S)9_~Pc;Mcc>j9rf1MRMWpY*b+ku~S@$d`G~ zv*~?09B8Y4uh-}4g<=?W^MPL{15I4UY@P{x=CRqIA&9;5&Q?Cda~zHOt@DTfczR}_ z8Gl^B4z9}M!!vHJ$|1Y>!HvArV=O-VhXVfH7Hkjr{1upjnIM@-0g?$)fxis^UW!B%fSU228Ro;{lJ_-;2|vh;a>{oHO(`Z?I0uZ{C;Kj?npPmP_lk=7X5 zITq;gc{tF1diL(}b9-<@@aP!7F}*X3K)Y+RJD0QSYz#g(M(|(#jcfDqM)u`pwTF6 zPxG~Lp6zorN_O;X_ZEIRv#Q3+)sgJer60lXaXyYWvgZzY1IT$(&3m7pGOe9TKj&1w zj}5Z&XU+T5UvqhX*l-r_cx)cL&FXv4Ute7ta>}RX!kzhvDHr8|eRj*i$Z^L}|3T+s z?-ssA<(BoJHrdoaRFoqzmg~L|Th(1{=;!0E&DSqv=YJQ6{8i6uLG8)={JlDsHSdes zlf&DCZw$y9zba5O-PgC~$lo%}t*cr3{EW@~QGvI|+E%jtUZGyk1Z?`w@0`yK`-?!M zPcB#We6rr&`Py&qO&5!{SpM(kJ=mM^rGYocKAU}W+xJfWZuaRE~i`gB7`bwrT z7`HCO1E&Mr@_!L%i{<}r=G;B%y#1N1$zA8|#o&9oT2Y_P^YM(wdO4B#OM_1dUOw$v zds%=Fanw&f10D1pn|gD8cRuHg4)S=U6DOn2jm-Pqog5quoD-Y(z<88nV-Z{$RAyVo zquxx<=_PY4z#%@I+e(&w@)wg^r8CEtXGdFnuPr{}@cuya`LZ)0e_Oz|n)UC)JuZFM zai+1k9<(0mYo4we#-qI~pF1Z{KnD)-VXV>9I;sARtg(4=+UL8siC=dF&%6#Fy&W%CD$Dmq+8d-#u3!$drfjhwq-Ve@ig(dm{5k2lyQC&()caIhx1S z?@kdr$ANL}%W*%Gc4dq!w!IyE+7b93D+adR6ZL*=>i%?kwd2pyw^ll*XFcd!-1Wm* z+ZCvx?%{>*jlfuq9}EsnV{`s20*$Rj;0*b-pz`d}L%wI&S_GQfTNtF(7I`{xSD)#` zzxg82=4aW`P6vy?89KX8Ufk}Mx7lX^8Ex}j+WfNsi_E<>`X^0&x@C^s#nCV8_1pMZ zK!(0c9=2_%-**l98s96nwc|l^r3ZeFamvfKfE^rbwNqI#;v8ig+uTO|XKN9RdCT-c zoUucWjzyr2oK_b<_67VLbI&JdapE&W{c81J{Tl0Wa#=u!HJ@ee?Wr5BF^{?2%J!Jo z>v9(4zGME?7xhW^?qIwNYne9=GURcxnd3{Be(|jkqg;zat%+l_)6X_G=%#Zqjd4p4 z`PS8(&*m*6OMm5H?lar-bM<>Ydu+;!-duj_M~3HWZ6o8+-kAIQ2&SnYa@{*Mj9;Ab ze@-yIgWee&4zxeXuU+ue`R~r={_bLZA|sxk$QobF@$*HKOy{r2eAM~;XV1bXzk2G`xViUK?{m!OlJlC{HD>45 z;PPM|`@tdhk*8fO`4GV0`avPP#hTsD`>Tu<`Ww@>@!%Klrj-<&x| zjxX%l|GMl~uXFZWJN7?kvOTWz=~ULO^^Dl)w0GOI#||03ckh;IuQtT|l&m$TOds|) zGN1G6JlS{sj|bn+-^skZ*T&nkHb0N!aw@KW5*an**Aa5mIMi?TeCuRO4A%_nUy=3E z|JP(L{<+-CruF*%g3QZ>Se~7^JANdGE=kNvAAJ&&9Ae1_5Y>|oUMd(nfxPY9fKr!LLee&)?<=!LJ{^!t&K zqwh&mfBV$mHT8I=4_9yevrR6ZIPLYj8XmqUf4P^ga_n8C_l~K*JAM82-Syii`(!Hn z$r(59Pl>+n^_-Yaz3x2UADcND-?4k{$KGw8fzds|o(=9*G?Oz>ibq@FL z)R)Hg$iqiwULJkMIPXr9_a40G4>#kyXIkU`7iVqEt26c8=b!oWr(T_!JFmYtpqu}1 z%YXE-oPR;)_Fo;;_BUi-J^2~0rdtoJ`8xpORoA1;=odZw{oKipcbJW9r~c5?*H`bn z{g+Jr%cuVSssECx|FZOS$AyP|T7ENepGUIqT-Wul54!&szkmL7 z=mnG9>xTVb$bLDq?))2u{ePH!Yxa7tad6oiHfu#~+jsBvUlg!?Y4EC?9Z=d}`(^-4gaCtUA7$E=BVePx8 zwQ?X9@@%{!dtx5HLp(ktF0%HX;PQaJ-XY&t%JCaBZp;tQcs((1q;H+?$e11NIkAJw zM+VjP*%|k{>9=M~);sW*`H%0F_ivom`T8qaFCW!$Mb`QE`BTrP`8Ngijn3bVZ|RnM z_fEaHk4;?uz36uC^8)?11U=984}S6HTUk5bmNjSXy=*%B1=E^59Lj$n$lZTVz{mBV zG4;K2_Ah_?e5|j`obB%j>erj6{c`?=lg#TU88!5`@*CT7Sl;QlInaBv^y58z=Wo9M zXTiIs_{!&Nr*m&gUteC7b98mjxE!o!Z}dT|_Hgk#?>HahHJLldSN+kc=byQ|q5p=d ze@l9L)!*Gw{O?akU~`*(li!DqfVbNUYi`g^DTOQ-&O(l_t8{iX0i zZ|kjn>#(0o`=;}1nqEHXUpMvMGV?E)`Y)gQzdP%HEOYk7=`-QIvHz$qKYR8$!7m06 z`^vLtPX#~uRcFuM`_*U9z9Ya5(EmWtoSd3s{n}|w9JkK+_|QqlS=cr8zB`-0ET9h; zZ~yhPXJ4BB^1$BL1;>K*V9d)8L{1JK8IbE8cF(>wd)E2}@#)oB8_&Ny^VagX{({*$ zo}AbIU3hSx=*Zh|U*YxSE)vvL}?v5P0 z<)wG^A7st?KMHDp?%cs8e^YfWI<6V9Gub%f=P4vyg4IQ2LyV+IKdheQ_ zcaz&c^#`ZEK0J1s*Owcnx%bPtkC}S0n;)I}6H|Y3>hGBPekbgm?%nbxJ3sPb{!gd% zADQ|eo%(+<^>3Z}pPc%in)-h;^>3T{pPTw$ocdp$`d^*;Uz_^hnEH25{hv?$d#3)c z(&Gldj}M-f+IsW@XV1RjYtNqjoNvnA3*Pe0XU{(KTh5;SsBb%a_Tk_D;5+!ZoDmoM za;TPWm~v>nd8u6a{@(1_|G~hy%Yr}umGj@p_+tP1sb5Te-}rl{`43P1zn=P^p8Cf9 zj?C%5Ja|I%t7UrSO)h(n_(jhABPKa>ckZuc?##0T{adGAj>w4lUH|#K?teb*|M=9) z1v&4^y^*_oTCXoZHqGBU^?dJrcPD=MJ0AR<@pY5j>!RXS`n&!Wi-WmSfmow_cT-%wsSRNVB@ljJ>oyVqm@6N|h z^Sh`1tET=_0wx_J@KGd(+vo zKlYtx&&mZ~j|bwA_h0^x=W|$&z31e9d+L8`>i;mkbL#e$IY;Iv1O3kh%^$t*{;tjZ zk(YzJC;1m-+_jIJY?s4+H~FJUhQIIp1%Rb>?&a>E_*} zLk&N5h0Iq)hAiLkM|OD!eqr-|ymnf1{;gT-9Z-|yfS=A^KJ_V|<(!Q5eonn;n!jr5 zzjW%qV(Q;G_04zl`Nz}xyQW_K(%bs{usCOab^6A?GxJaVq4TlvyRm&%;&^H1_5U3i z9}Ct4dOmgPTSxe~ZHS%B6DFAxQ~!*qf7aB0`qY2M)PLdBzh>&cXzIUm>c3{{zj^BW z9{ln&|Lv*&y{Z3$ssF>NFDLJt<`O<~^q6VBo*qZuzz+|u{O4!S{^pOLJ-h2C^4+UbloQ>w{Pcm+8|IOH|Up~KXpW=CB#vc+ijyvK59ghk0pE>ovJN3Um^?#ba`h4bo z^S|EYhaPc%bo9J5{o{-SeydM@uLt(j^{PD~@{2BKu3Ev%69-<%ih;lL`s`;wKd;u} z9J^#6ow0sT`s>oCTmB5=Z~XLTEHUw*KdbQzKX?AS!lz{KWWaVg{=SUWWb^suKfC$! zy4I=B0k*sU13&ZN-(!AN=3*ybf5iXrf4k{V{U$?)y8G{MJO8=a&x6Z{{WoV{jL!`8 z9??vOhWX zy@&3&b!YUurvBYi|7TO*H>2NyT8n=$?f>D_|KC%;ck1^{{hOwqpX~J4Cm%7*TkGr7 zyyvf-=6zpop61V(`e#r5$4~t~oO-pv&hw}KQ>Xsa)W2-%>(>uW^Us?4&zbuEEbdFE z`TT9}{NGOdKR@+voBE%d`d^s(w@>}AO#M5i{=ZFqdHthlUOwM7&FA@e&$QmVrGUh( zCiFg+^v(Apr+MFFpM&;4d?wd>`M7EQ2~+RCBSikQ=^Xl}OzTgZ`lnC*(WyT+^(UtO znN$DqQ~&I#_xDHX{p6{?d+J{>^`AENr>6czQ-6BuKX>ZCaOz((TmSrN{)#Q+UOlb9 zZtCx!`mdP!ubTR=nffAHc{=2K<_{M4eh-v;!ncp&vzd7R*8LR0_1I^gI z)&6F1C^An@|D-&G&q@C+kA43?L+E>@m&jY>o_}PJW6O7*AJ)7ZPtHSTyg%@HLFRa1 z&1b^p6RuD1zTFU;-oc)|C*!?=v)+qU=bfdmI&O>(Z{}RbWm)6f!QfEfjeTBV4HvcR zt^1J7cL#R{IEc!nz9Z@J%I{YMw+GH{1P7*Zy5-L+=@p}XldnscvgCoDo)e!&-scMa z{2%|_xZ5&!hOB*ZV!k%O4f|qje7J%!SKj5%o!09cJLBKA;O~bA>w&QtLF*ZOc<=nX zPm{=&ll&t3+n+M z_(GR;^(E)@&2=>{wP#S3a_HU!cj)4Z%&>a8}&r zA3e;;m#6l0T@`57=;f38^RDa)#80j^o;>L^*W?cmi$KH0{y-h6dHSvl=J!y*8~qkiP5kd1LS~ ziH{%s?-4YXgIR06(Q|Kr7o3^j7ii__DHBiIvL+W#9p>cg_r>^r+H|fyJBRO8oU=Xm zlf2lxv;MuA_4HdoEUWgiy!4mNRsPC_MQ}o6NloYvo@ZdN$*f??9DzK<^Ks8(`#*iuqs}9 z>2G}Qk-0b)Ti8%rYL z8)d|FX~2)#`(S)H_7HtIegPj2#)t7u=pDaExP@M+Wc$Z|sWGje#^n7CE^`A7ITNSgl4-4pM%=GkrJtt>Zol|SQ zU#n_HjHBdd%zo>gAFVxlTEn+rM90p^Hip|X=C{_hzQ50n9(6SLr7?Mn z?uZQAqs;!y$*g|&Hb1}lO^%M|MaR58t7GJwul&*KEAIX(cTN88ynw&%E?akP;jeqc z)`>toIF9K1y@9?TsHJ>#FaP^!WS}|3C0{-{i)wJyJE9((8TrZdL7$Oo1t*P@-hR); z?M84QFkTDz%r|%cOz^Ux`!{8LBw+WhK*Qw~%h6_xwWSC7d`_?{p!1HvnexQezJPsp z_;6|(<8h45oKF6e#a;J}HM+MiN9SYi_dtG-6Z4MXdBJxDmjyU>j=z2_Y|dZ29}n0) zHqFWSS$^x4UhfC_u62JsYjpH%KeJzzwGr|-&R2~i@*rQzZ*7(9`qG-=pT?JdZj5WK zhpU%Tn=<%0Jk9e*U(WqG$B)X|o&e8cl@nait9P&Z^N8y+Cd<}S1N@5fwm?p_`fR+F zf4Fc)p0tk)$XcUwBVgNmw+J*g{p>^Io9~3q)LuCfL(l51&;6g*0N&jr@0*;PF9J7J=rRIPVM&1a$Ga_l~aSi$1aA98L#h)h~{4zX&wC+&S%m z&F(=z3)`8sYp3;N>03K~7G@83pAoRn#`rTbJlJ0Z8e7|zqw{rtedc6VaY^Tyz+1Bj zw9()B{kxDZJak_i@;ldy->ZYh=}z((_jA8nH_e?G?hd{_a0ldPBjE2^K*uG)l|k*x z#qNN7Kf~ppT)#t{%y<=V^^ISx=lV?_J2wQM5(oK6k7mp+|K;a!z}Nhi=efJA?)XJF z&iW4Dl<|>ZeCKPkaW=j$iX8po?%GQ;{?q{PY6Udh$+P+Rb5OeZ;jWN*aX=^7`#XU% zZ0!ihurbPf*0lD)*ri*%y_@vDHn=3vS_AlYhc<%pwU)8g+#SsLP~dF&nEQTX_U=xC zE@rp2AzrrCE!%3E{rv%dt_twfyE$@uYu3q~2ym<>)X2`DXVeN`e2(y&?4Cf}WVPnq z7(Z%7-DtN2Y`drKcXiRr_tQb&tjjWHqjkwQF;xG^AGzuhGhL&8F<7(L*wxUkK&&{k zM-ML9CSNWyT&}Y(9=(|8S_GQ&cw*OG^fN7S`JA{SpzpfiXz*phcLv`V{BXdq-~YQR z*vM3jd{_(QflYTzyCoPobT{Q#967%HjA+jJqSY_{*jo?qg#+htyCcx#hW?&uP19wM z4*PP;rueqfi4$$q*;=LF8(cqjWlUc=zcgdAxE4SEjLG{wHoS;~yuGV~>Re>3)z-<3 zanqQbc~qcvjgPGvys$;T?+RPRhYNb^6Hc6=r+Rz-aMrd3H_zTx+|#3-2ylB#fV